本文作者:hhh5460

本文地址:https://www.cnblogs.com/hhh5460/p/10145797.html

0.说明

这里提供了二维迷宫问题的一个比较通用的模板,拿到后需要修改的地方非常少。

对于任意的二维迷宫的 class Agent,只需修改三个地方:MAZE_R, MAZE_R, rewards,其他的不要动!如下所示:

  1. class Agent(object):
  2. '''个体类'''
  3. MAZE_R = 6 # 迷宫行数
  4. MAZE_C = 6 # 迷宫列数
  5.  
  6. def __init__(self, alpha=0.1, gamma=0.9):
  7. '''初始化'''
  8. # ... ...
  9. self.rewards = [0,-10,0, 0, 0, 0,
  10. 0,-10,0, 0,-10, 0,
  11. 0,-10,0,-10, 0, 0,
  12. 0,-10,0,-10, 0, 0,
  13. 0,-10,0,-10, 1, 0,
  14. 0, 0,0,-10, 0,10,] # 奖励集。出口奖励10,陷阱奖励-10,元宝奖励1
  15. # ... ...

1.完整代码

  1. import pandas as pd
  2. import random
  3. import time
  4. import pickle
  5. import pathlib
  6. import os
  7. import tkinter as tk
  8.  
  9. '''
  10. 6*6 的迷宫:
  11. -------------------------------------------
  12. | 入口 | 陷阱 | | | | |
  13. -------------------------------------------
  14. | | 陷阱 | | | 陷阱 | |
  15. -------------------------------------------
  16. | | 陷阱 | | 陷阱 | | |
  17. -------------------------------------------
  18. | | 陷阱 | | 陷阱 | | |
  19. -------------------------------------------
  20. | | 陷阱 | | 陷阱 | 元宝 | |
  21. -------------------------------------------
  22. | | | | 陷阱 | | 出口 |
  23. -------------------------------------------
  24.  
  25. 作者:hhh5460
  26. 时间:20181219
  27. 地点:Tai Zi Miao
  28. '''
  29.  
  30. class Maze(tk.Tk):
  31. '''环境类(GUI)'''
  32. UNIT = 40 # pixels
  33. MAZE_R = 6 # grid row
  34. MAZE_C = 6 # grid column
  35.  
  36. def __init__(self):
  37. '''初始化'''
  38. super().__init__()
  39. self.title('迷宫')
  40. h = self.MAZE_R * self.UNIT
  41. w = self.MAZE_C * self.UNIT
  42. self.geometry('{0}x{1}'.format(h, w)) #窗口大小
  43. self.canvas = tk.Canvas(self, bg='white', height=h, width=w)
  44. # 画网格
  45. for c in range(1, self.MAZE_C):
  46. self.canvas.create_line(c * self.UNIT, 0, c * self.UNIT, h)
  47. for r in range(1, self.MAZE_R):
  48. self.canvas.create_line(0, r * self.UNIT, w, r * self.UNIT)
  49. # 画陷阱
  50. self._draw_rect(1, 0, 'black') # 在1列、0行处,下同
  51. self._draw_rect(1, 1, 'black')
  52. self._draw_rect(1, 2, 'black')
  53. self._draw_rect(1, 3, 'black')
  54. self._draw_rect(1, 4, 'black')
  55. self._draw_rect(3, 2, 'black')
  56. self._draw_rect(3, 3, 'black')
  57. self._draw_rect(3, 4, 'black')
  58. self._draw_rect(3, 5, 'black')
  59. self._draw_rect(4, 1, 'black')
  60. # 画奖励
  61. self._draw_rect(4, 4, 'yellow')
  62. # 画玩家(保存!!)
  63. self.rect = self._draw_rect(0, 0, 'red')
  64. self.canvas.pack() # 显示画作!
  65.  
  66. def _draw_rect(self, x, y, color):
  67. '''画矩形, x,y表示横,竖第几个格子'''
  68. padding = 5 # 内边距5px,参见CSS
  69. coor = [self.UNIT * x + padding, self.UNIT * y + padding, self.UNIT * (x+1) - padding, self.UNIT * (y+1) - padding]
  70. return self.canvas.create_rectangle(*coor, fill = color)
  71.  
  72. def move_agent_to(self, state, step_time=0.01):
  73. '''移动玩家到新位置,根据传入的状态'''
  74. coor_old = self.canvas.coords(self.rect) # 形如[5.0, 5.0, 35.0, 35.0](第一个格子左上、右下坐标)
  75. x, y = state % 6, state // 6 #横竖第几个格子
  76. padding = 5 # 内边距5px,参见CSS
  77. coor_new = [self.UNIT * x + padding, self.UNIT * y + padding, self.UNIT * (x+1) - padding, self.UNIT * (y+1) - padding]
  78. dx_pixels, dy_pixels = coor_new[0] - coor_old[0], coor_new[1] - coor_old[1] # 左上角顶点坐标之差
  79. self.canvas.move(self.rect, dx_pixels, dy_pixels)
  80. self.update() # tkinter内置的update!
  81. time.sleep(step_time)
  82.  
  83. class Agent(object):
  84. '''个体类'''
  85. MAZE_R = 6 # 迷宫行数
  86. MAZE_C = 6 # 迷宫列数
  87.  
  88. def __init__(self, alpha=0.1, gamma=0.9):
  89. '''初始化'''
  90. self.states = range(self.MAZE_R * self.MAZE_C) # 状态集。0~35 共36个状态
  91. self.actions = list('udlr') # 动作集。上下左右 4个动作 ↑↓←→ ←↑→↓↖↗↘↙
  92. self.rewards = [0,-10,0, 0, 0, 0,
  93. 0,-10,0, 0,-10, 0,
  94. 0,-10,0,-10, 0, 0,
  95. 0,-10,0,-10, 0, 0,
  96. 0,-10,0,-10, 1, 0,
  97. 0, 0,0,-10, 0,10,] # 奖励集。出口奖励10,陷阱奖励-10,元宝奖励5
  98. #self.hell_states = [1,7,13,19,25,15,31,37,43,10] # 陷阱位置
  99.  
  100. self.alpha = alpha
  101. self.gamma = gamma
  102.  
  103. self.q_table = pd.DataFrame(data=[[0 for _ in self.actions] for _ in self.states],
  104. index=self.states,
  105. columns=self.actions)
  106.  
  107. def save_policy(self):
  108. '''保存Q table'''
  109. with open('q_table.pickle', 'wb') as f:
  110. pickle.dump(self.q_table, f, pickle.HIGHEST_PROTOCOL)
  111.  
  112. def load_policy(self):
  113. '''导入Q table'''
  114. with open('q_table.pickle', 'rb') as f:
  115. self.q_table = pickle.load(f)
  116.  
  117. def choose_action(self, state, epsilon=0.8):
  118. '''选择相应的动作。根据当前状态,随机或贪婪,按照参数epsilon'''
  119. #if (random.uniform(0,1) > epsilon) or ((self.q_table.ix[state] == 0).all()): # 探索
  120. if random.uniform(0,1) > epsilon: # 探索
  121. action = random.choice(self.get_valid_actions(state))
  122. else:
  123. #action = self.q_table.ix[state].idxmax() # 利用 当有多个最大值时,会锁死第一个!
  124. #action = self.q_table.ix[state].filter(items=self.get_valid_actions(state)).idxmax() # 重大改进!然鹅与上面一样
  125. s = self.q_table.ix[state].filter(items=self.get_valid_actions(state))
  126. action = random.choice(s[s==s.max()].index) # 从可能有多个的最大值里面随机选择一个!
  127. return action
  128.  
  129. def get_q_values(self, state):
  130. '''取给定状态state的所有Q value'''
  131. q_values = self.q_table.ix[state, self.get_valid_actions(state)]
  132. return q_values
  133.  
  134. def update_q_value(self, state, action, next_state_reward, next_state_q_values):
  135. '''更新Q value,根据贝尔曼方程'''
  136. self.q_table.ix[state, action] += self.alpha * (next_state_reward + self.gamma * next_state_q_values.max() - self.q_table.ix[state, action])
  137.  
  138. def get_valid_actions(self, state):
  139. '''取当前状态下所有的合法动作'''
  140. valid_actions = set(self.actions)
  141. if state // self.MAZE_C == 0: # 首行,则 不能向上
  142. valid_actions -= set(['u'])
  143. elif state // self.MAZE_C == self.MAZE_R - 1: # 末行,则 不能向下
  144. valid_actions -= set(['d'])
  145.  
  146. if state % self.MAZE_C == 0: # 首列,则 不能向左
  147. valid_actions -= set(['l'])
  148. elif state % self.MAZE_C == self.MAZE_C - 1: # 末列,则 不能向右
  149. valid_actions -= set(['r'])
  150.  
  151. return list(valid_actions)
  152.  
  153. def get_next_state(self, state, action):
  154. '''对状态执行动作后,得到下一状态'''
  155. #u,d,l,r,n = -6,+6,-1,+1,0
  156. if action == 'u' and state // self.MAZE_C != 0: # 除首行外,向上-MAZE_C
  157. next_state = state - self.MAZE_C
  158. elif action == 'd' and state // self.MAZE_C != self.MAZE_R - 1: # 除末行外,向下+MAZE_C
  159. next_state = state + self.MAZE_C
  160. elif action == 'l' and state % self.MAZE_C != 0: # 除首列外,向左-1
  161. next_state = state - 1
  162. elif action == 'r' and state % self.MAZE_C != self.MAZE_C - 1: # 除末列外,向右+1
  163. next_state = state + 1
  164. else:
  165. next_state = state
  166. return next_state
  167.  
  168. def learn(self, env=None, episode=1000, epsilon=0.8):
  169. '''q-learning算法'''
  170. print('Agent is learning...')
  171. for i in range(episode):
  172. current_state = self.states[0]
  173.  
  174. if env is not None: # 若提供了环境,则重置之!
  175. env.move_agent_to(current_state)
  176.  
  177. while current_state != self.states[-1]:
  178. current_action = self.choose_action(current_state, epsilon) # 按一定概率,随机或贪婪地选择
  179. next_state = self.get_next_state(current_state, current_action)
  180. next_state_reward = self.rewards[next_state]
  181. next_state_q_values = self.get_q_values(next_state)
  182. self.update_q_value(current_state, current_action, next_state_reward, next_state_q_values)
  183. current_state = next_state
  184.  
  185. #if next_state not in self.hell_states: # 非陷阱,则往前;否则待在原位
  186. # current_state = next_state
  187.  
  188. if env is not None: # 若提供了环境,则更新之!
  189. env.move_agent_to(current_state)
  190. print(i)
  191. print('\nok')
  192.  
  193. def test(self):
  194. '''测试agent是否已具有智能'''
  195. count = 0
  196. current_state = self.states[0]
  197. while current_state != self.states[-1]:
  198. current_action = self.choose_action(current_state, 1.) # 1., 100%贪婪
  199. next_state = self.get_next_state(current_state, current_action)
  200. current_state = next_state
  201. count += 1
  202.  
  203. if count > self.MAZE_R * self.MAZE_C: # 没有在36步之内走出迷宫,则
  204. return False # 无智能
  205.  
  206. return True # 有智能
  207.  
  208. def play(self, env=None, step_time=0.5):
  209. '''玩游戏,使用策略'''
  210. assert env != None, 'Env must be not None!'
  211.  
  212. if not self.test(): # 若尚无智能,则
  213. if pathlib.Path("q_table.pickle").exists():
  214. self.load_policy()
  215. else:
  216. print("I need to learn before playing this game.")
  217. self.learn(env, episode=1000, epsilon=0.5)
  218. self.save_policy()
  219.  
  220. print('Agent is playing...')
  221. current_state = self.states[0]
  222. env.move_agent_to(current_state, step_time)
  223. while current_state != self.states[-1]:
  224. current_action = self.choose_action(current_state, 1.) # 1., 100%贪婪
  225. next_state = self.get_next_state(current_state, current_action)
  226. current_state = next_state
  227. env.move_agent_to(current_state, step_time)
  228. print('\nCongratulations, Agent got it!')
  229.  
  230. if __name__ == '__main__':
  231. env = Maze() # 环境
  232. agent = Agent() # 个体(智能体)
  233. agent.learn(env, episode=1000, epsilon=0.6) # 先学习
  234. #agent.save_policy()
  235. #agent.load_policy()
  236. agent.play(env) # 再玩耍
  237.  
  238. #env.after(0, agent.learn, env, 1000, 0.8) # 先学
  239. #env.after(0, agent.save_policy) # 保存所学
  240. #env.after(0, agent.load_policy) # 导入所学
  241. #env.after(0, agent.play, env) # 再玩
  242. env.mainloop()

Just enjoy it!

【强化学习】python 实现 q-learning 迷宫通用模板的更多相关文章

  1. 深度强化学习(DQN-Deep Q Network)之应用-Flappy Bird

    深度强化学习(DQN-Deep Q Network)之应用-Flappy Bird 本文系作者原创,转载请注明出处:https://www.cnblogs.com/further-further-fu ...

  2. 机器学习之强化学习概览(Machine Learning for Humans: Reinforcement Learning)

    声明:本文翻译自Vishal Maini在Medium平台上发布的<Machine Learning for Humans>的教程的<Part 5: Reinforcement Le ...

  3. 深度强化学习(Deep Reinforcement Learning)入门:RL base & DQN-DDPG-A3C introduction

    转自https://zhuanlan.zhihu.com/p/25239682 过去的一段时间在深度强化学习领域投入了不少精力,工作中也在应用DRL解决业务问题.子曰:温故而知新,在进一步深入研究和应 ...

  4. 【转】【强化学习】Deep Q Network(DQN)算法详解

    原文地址:https://blog.csdn.net/qq_30615903/article/details/80744083 DQN(Deep Q-Learning)是将深度学习deeplearni ...

  5. [Reinforcement Learning] 强化学习介绍

    随着AlphaGo和AlphaZero的出现,强化学习相关算法在这几年引起了学术界和工业界的重视.最近也翻了很多强化学习的资料,有时间了还是得自己动脑筋整理一下. 强化学习定义 先借用维基百科上对强化 ...

  6. Deep Learning专栏--强化学习之从 Policy Gradient 到 A3C(3)

    在之前的强化学习文章里,我们讲到了经典的MDP模型来描述强化学习,其解法包括value iteration和policy iteration,这类经典解法基于已知的转移概率矩阵P,而在实际应用中,我们 ...

  7. (转) 深度强化学习综述:从AlphaGo背后的力量到学习资源分享(附论文)

    本文转自:http://mp.weixin.qq.com/s/aAHbybdbs_GtY8OyU6h5WA 专题 | 深度强化学习综述:从AlphaGo背后的力量到学习资源分享(附论文) 原创 201 ...

  8. 强化学习论文(Scalable agent alignment via reward modeling: a research direction)

     原文地址: https://arxiv.org/pdf/1811.07871.pdf ======================================================== ...

  9. 如何用简单例子讲解 Q - learning 的具体过程?

    作者:牛阿链接:https://www.zhihu.com/question/26408259/answer/123230350来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...

随机推荐

  1. 安卓开发之ScrollView

    当界面不足以将所有的内容显示出来的时候便导致下面的部分内容无法显示出来 所有加上ScrollView 来讲要显示的内容放入之中便可以实现上下滚动界面内容 但是当要显示多个控件的时候会出错  原因是Sc ...

  2. C#语言————选择结构

    int[] num = new int[] {23,76,54,87,51,12 }; //冒泡排序 for (int i = 0; i < num.Length - 1; i++) { for ...

  3. 高通GPIO驱动(DTS方式)

    gpio调试的方式有很多,linux3.0以上ARM架构的处理器基本上都采用了DTS的方式,在linux3.0可以通过获取sysfs的方式来获取gpio状态: sysfs文件系统的建立可以参照下面的博 ...

  4. Linux运维面试题之--网页打开缓慢如何优化

    服务器负载过高或者网页打开缓慢,简单说说你的优化思路 ? 首先我们要发现问题的过程,通过操作系统,数据库,程序设计,硬件角度四个维度找到问题所在 找到瓶颈点的位置 制定好优化方案,形成处理问题的体系 ...

  5. 02LaTeX学习系列之---TeX环境的搭建

    目录 02Latex的下载与安装及其编译IDE 目录 前言 (一)Tex Live的下载 1. Tex Live官方下载网站: (二)TeXStudio 1.TeXStudio官网下载 2.TeXSt ...

  6. Android Studio打开SDK更新对话框

    再进行android自动化时,有时需要用到android的一些api,但苦于找不到 api文档,各种论坛查看是否有自己所需要的api,甚是麻烦.下面介绍如何通过 android studio将 and ...

  7. 基于tomcat插件的maven多模块工程热部署(附插件源码)

    内容属原创,转载请注明出处 写在前面的话 最近一直比较纠结,归根结底在于工程的模块化拆分.以前也干过这事,但是一直对以前的结果不满意,这会重操旧业,希望搞出个自己满意的结果. 之前有什么不满意的呢? ...

  8. activiti5.14版本在线流程设计器的国际化中文支持

    参考了前辈的一些国际化支持做法,加上自己对流程的一些理解,做了activiti5.14版本的国际化支持.发现有若干bug,比如属性设置弹出窗口里的grid里的下拉列表不支持显示中文(要修改oryx.d ...

  9. flex布局下el-table横向滚动条失效

    如下图,是一种常见的页面结构,我们可以有很多方法实现,inline-block,float,flex等等 但是,最近项目中遇到一个怪事,左边是侧边栏导航,右边是一个数据展示table,el-table ...

  10. Android Activity学习笔记——Activity的启动和创建

    http://www.cnblogs.com/bastard/archive/2012/04/07/2436262.html 最近学习Android相关知识,感觉仅仅了解Activity几个生命周期函 ...