• Q-Learning


    一、什么是Q-learning

            Q-Learning是强化学习中,一种基于值(values-based)的算法,最终的return是一个表格,即Q-Table。这个表格的每一行都代表着一个状态(state),每一行的每一列都代表着一个动作(action),而每个值就代表着如果在该state下,采取该action所能获取的最大的未来期望奖励。通过Q-Table就可以找到每个状态下的最优行为,进而通过找到所有的最优action来最终得到最大的期望奖励。

    二、马尔科夫奖励模型(Markov Reward Process,MRP)

            马尔科夫奖励模型是带回报值的马尔可夫模型

    马尔科夫奖励模型的定义:

    1、S 是有限个状态的集合s∈S;

    2、P 是一个动态转移模型;

    3、R 是一个奖励函数;

    4、γ 衰减因子。

     回报 & 值函数

    马尔可夫决策过程(马尔可夫过程 + 奖励 + 动作)

     马尔可夫决策过程的策略:

    1、对于MDP,希望得到一个策略 \pi,对于每一个状态,都能给予一个动作;

    2、策略可以是固定的,也可是随机的;

    3、更一般地说,我们会将其视为一个条件概率分布;

    4、最优策略\pi*:一个执行之后能得到最大回报的策略

    马尔可夫决策过程的搜索树:

     三、贝尔曼方程

     收敛性:

     四、Q-Learning算法流程

    在这里插入图片描述

    1、建立Q表;

    2、选择当前状态的最优action(或设置一定概率随机选择action)

    3、执行选择的action,更新当前状态下所选行为的Q值(估计值)

    4、更新方法:

    在这里插入图片描述

     五、算法实例1

    实例情况:

            环境为一个直长廊,直长廊正前方,有一个钻石,直长廊后面,是一个深渊。此处一个Agent,可选择的action有两个,分别是left和right。设定:掉进深渊,score为-1,得到钻石,score为+1 ,其余score均为0 。

            可以根据下方图画理解:

            如图,这个长得像小人的,就是Agent,它左侧阴影部分,就是深渊,掉进去就-1;离它较远的右侧,有一个粉红的球,就是钻石,得到就是+1.

            我们可以画一个表格,来抽象化一下环境和奖励:

    深渊-1Agent起始位置0000钻石+1
    0123456

    这个表格第一行就是地图,第二行是地图下标。

    我们规定,Agent有只有两种动作,Left和Right,也就是左和右。

    代码大致流程可以写出:

    1、初始化,初始化环境参数、Agent参数;

    2、图画更新,为便于用户观察,动态展示Agent位置;

    3、Agent观察环境,看是否经历过这个state,如果经历过就选最优action,如果没有就随机action;

    4、执行3所选的action;

    5、观察终点,看是否到终点或是否掉入深渊;

    6、更新坐标;

    7、获取下一环境;

    8、学习;

    9、参数归零;

    10、2-9迭代,直到5成立。

    伪代码形式:

    1. 初始化测试环境对象
    2. 初始化Agent
    3. 循环:
    4. 环境观察
    5. 图画更新
    6. while(1):
    7. 终点观察
    8. if(到达终点):
    9. 参数归零
    10. break;
    11. 动作选择
    12. 获取下一步的环境的实际情况
    13. 学习
    14. 更新坐标
    15. 图画更新

    下面展示一下实际代码:

    首先是环境代码:

    Env.py

            这是环境代码,主要功能包括:生成图像、获取所在位置、检测是否到终点、更新当前位置、获取下一步的实际情况和初始化地图

    1. # -*- coding: utf-8 -*-
    2. """
    3. @Project :Q_learn
    4. @File :Env.py
    5. @Author :Hao
    6. @Date :2022-09-10 010 8:38
    7. """
    8. import numpy as np
    9. class Env:
    10. def __init__(self, column, start_colum, maze_column):
    11. self.column = column # 表示地图的长度
    12. self.maze_column = maze_column - 1 # 宝藏所在的位置
    13. self.x = start_colum # 初始化x
    14. self.map = np.arange(column) # 给予每个地点一个标号
    15. self.count = 0 # 用于记录一共走了多少步
    16. # 生成图像
    17. def draw(self):
    18. a = []
    19. for j in range(self.column): # 更新图画
    20. if j == 0:
    21. a.append('x')
    22. elif j == self.x:
    23. a.append('o')
    24. elif j == self.maze_column:
    25. a.append('m')
    26. else:
    27. a.append('_')
    28. interaction = ''.join(a)
    29. print('\r{}'.format(interaction), end='')
    30. # 获取所在位置
    31. def get_observation(self):
    32. return self.map[self.x] # 返回现在所在位置
    33. # 是否已到达终点
    34. def get_terminal(self):
    35. if self.x == self.maze_column: # 如果得到了宝藏,则返回已经完成
    36. done = True
    37. elif self.x == 0: # 如果掉入左边边缘,失败,-1
    38. done = True
    39. else:
    40. done = False
    41. return done
    42. # 更新当前位置
    43. def update_place(self, action):
    44. self.count += 1 # 更新的时候表示已经走了一步
    45. if action == 'right':
    46. if self.x < self.column - 1:
    47. self.x += 1
    48. elif action == 'left': # left
    49. if self.x > 0:
    50. self.x -= 1
    51. # 获得下一步的环境的实际情况
    52. def get_target(self, action):
    53. if action == 'right': # 获得下一步的环境的实际情况
    54. if self.x + 1 == self.maze_column:
    55. score = 1
    56. pre_done = True
    57. else:
    58. score = 0
    59. pre_done = False
    60. return self.map[self.x + 1], score, pre_done
    61. elif action == 'left': # left
    62. if self.x - 1 == self.maze_column:
    63. score = 1
    64. pre_done = True
    65. elif self.x - 1 == 0:
    66. score = -1
    67. pre_done = True
    68. else:
    69. score = 0
    70. pre_done = False
    71. return self.map[self.x - 1], score, pre_done
    72. # 初始化,位置0,计数器归零
    73. def retry(self, start_colum): # 初始化
    74. self.x = start_colum
    75. self.count = 0

    Agent.py

            这是智能体的初始化、选择行动和学习的代码。

    1. # -*- coding: utf-8 -*-
    2. """
    3. @Project :Q_learn
    4. @File :Env.py
    5. @Author :Hao
    6. @Date :2022-09-10 010 8:38
    7. @Describe :Agent
    8. """
    9. import numpy as np
    10. import pandas as pd
    11. class Agent:
    12. def __init__(self, actions, long, learning_rate=0.05, reward_decay=0.9, e_greedy=0.9):
    13. self.actions = actions # 初始化可以进行的各种行为,传入为列表
    14. self.lr = learning_rate # 学习率,用于更新Q_table的值
    15. self.gamma = reward_decay # 当没有到达终点时,下一环境对当前环境的影响
    16. # self.epsilon = e_greedy # 随机选择几率为1-e_greedy,当处于e_greedy内时,不随机选择。
    17. self.q_table = pd.DataFrame(columns=self.actions, dtype=np.float64) # 生成q_table,列向量为columns
    18. for i in range(long):
    19. line_table = pd.Series(
    20. [0.0, 0.0],
    21. name=i,
    22. index=actions
    23. )
    24. line_table_2_frame = line_table.to_frame()
    25. self.q_table = pd.concat([self.q_table, line_table_2_frame.T])
    26. # 选择行动
    27. def choose_action(self, observation):
    28. action_list = self.q_table.loc[observation, :] # 取出当前observation所在的不同方向
    29. # if np.random.uniform() < self.epsilon: # 如果在epsilon几率内
    30. # # 选出当前observation中Q值最大的方向,这里再加一个random.choice是为了防止出现两个概率相同
    31. # action = np.random.choice(action_list[action_list == np.max(action_list)].index)
    32. # else:
    33. # action = np.random.choice(self.actions) # 如果不在epsilon内,则随机选择一个动作
    34. action = np.random.choice(action_list[action_list == np.max(action_list)].index) # action总选择最优解
    35. return action # 返回应当做的action
    36. # 学习
    37. def learn(self, observation_now, action, score, observation_after, done):
    38. q_predict = self.q_table.loc[observation_now, action] # 获得当前状态下,当前所作动作所对应的预测得分
    39. if done:
    40. q_target = score # 如果完成了则q_target为下一个环境的实际情况得分,本例子中此时score为1
    41. else:
    42. # 如果未完成则取下一个环境若干个动作中的最大得分作为这个环境的价值传递给当前环境
    43. q_target = score + self.gamma * self.q_table.loc[observation_after, :].max()
    44. # 根据所处的当前环境对各个动作的预测得分和下一步的环境的实际情况更新当前环境的q表
    45. self.q_table.loc[observation_now, action] += self.lr * (q_target - q_predict)

            此处的选择行动,可以设置一定的随机率,比如说设置为0.9的几率为选择Q-table中最优的action,剩下0.1的概率让agent随机选择。或者是不设置随机率,每一步都贪心。

    接下来是main

    1. # -*- coding: utf-8 -*-
    2. """
    3. @Project :Q_learn
    4. @File :run_this.py
    5. @Author :Hao
    6. @Date :2022-09-10 010 8:40
    7. """
    8. from Env import Env
    9. from Agent import Agent
    10. import time
    11. import pandas
    12. LONG = 7 # 总长度为6
    13. START_PLACE = 1 # 游戏开始的位置
    14. MAZE_PLACE = 7 # 宝藏在第六位
    15. TIMES = 1000 # 限制最大1000次循环,防止死循环
    16. STOP_FLAG = False
    17. e = 1e-2
    18. people = Agent(['left', 'right'], LONG) # 生成QLearn主体的对象,包含left和right,传入两个action
    19. site = Env(LONG, START_PLACE, MAZE_PLACE) # 生成测试环境
    20. for episode in range(TIMES):
    21. state = site.get_observation() # 观察初始环境
    22. site.draw() # 生成图像
    23. time.sleep(0.2) # 暂停
    24. while True:
    25. done = site.get_terminal() # 判断当前环境是否到达最后
    26. if done: # 如果到达,则初始化
    27. interaction = '\n第%s次episode,共使用步数:%s。' % (episode + 1, site.count)
    28. print(interaction)
    29. # 存储本次记录,计算与上次最大差值
    30. fileName = "data/episode" + str(episode) + ".csv"
    31. people.q_table.to_csv(fileName) # 将本次的q_table存储到本地文件中
    32. # print(f"\n第{episode}轮数据:\n{people.q_table}\n")
    33. if episode != 0: # 第一轮不进行判断
    34. old_file_name = "data/episode" + str(episode - 1) + ".csv" # 读取上一次的q_table
    35. old_q_table = pandas.read_csv(old_file_name, index_col=0)
    36. # print(f"\n第{episode - 1}轮数据:\n{old_q_table}\n")
    37. difference = (people.q_table - old_q_table).abs()
    38. # print(f"两次差值:\n{difference}\n")
    39. max_difference = difference.max()[0] \
    40. if difference.max()[0] >= difference.max()[1] else difference.max()[1]
    41. # print(f"与上一次最大差值:\n{difference.max()}\n{difference.max()[0]},{difference.max()[1]}\n")
    42. print(f"最大差值:{max_difference}"
    43. f"\n------{episode + 1}------")
    44. if max_difference <= e: # 达到收敛条件
    45. STOP_FLAG = True
    46. break
    47. site.retry(START_PLACE) # 初始化
    48. time.sleep(0.5)
    49. break
    50. action = people.choose_action(state) # 获得下一步方向
    51. state_after, score, pre_done = site.get_target(action) # 获得下一步的环境的实际情况
    52. people.learn(state, action, score, state_after, pre_done) # 根据所处的当前环境对各个动作的预测得分和下一步的环境的实际情况更新当前环境的q表
    53. site.update_place(action) # 更新位置
    54. state = state_after # 状态更新
    55. site.draw() # 更新画布
    56. time.sleep(0.2)
    57. if STOP_FLAG:
    58. break
    59. print(people.q_table)

            这里可以设置两种结束条件,一种是比较简单的设置循环次数,比如说循环20次、50次就强制结束,此种方法的缺点是,不能保证此结果已经收敛;还有一种方法是,加上收敛的判定条件,比如以上代码设置了判断收敛的方法,即判断本次Q-table的和上一次Q-table最大的差值,是否小于设定的一个阙值,若小于此阙值,则已经收敛,若不小于,则继续迭代。

    六、算法实例2

             这次实例是上一次的升级版本,这次是二维环境,action也变成了四个,分别是up、down、left和right,同样是一个Agent要获取钻石,即SUCCESS,到达之后会score+1,如果到FAIL,就是score-1,图中阴影部分,是一堵墙,无法穿过,图中的边缘部分,无法穿过,例如在起始位置,往上或者往左,都是无法移动(但是计步器会+1)。而且为了让Agent最快的找到SUCESS,这里设定Agent每走一步,都会获得一个-0.02的score。

    此次的Environment.py

    1. # -*- coding: utf-8 -*-
    2. """
    3. @Project :Q_learn
    4. @File :environment.py
    5. @Author :Hao
    6. @Date :2022-09-15 015 15:51
    7. @Describe :
    8. """
    9. import numpy as np
    10. class Environment:
    11. def __init__(self, map_high, map_width, wall_place, success_place, fail_place):
    12. self.map_high = map_high # 初始化地图
    13. self.map_width = map_width
    14. self.x = 0 # 初始化Agent所在坐标
    15. self.y = 0
    16. self.wall_place = wall_place # 初始化墙的位置
    17. self.success_place = success_place # 初始化成功坐标
    18. self.fail_place = fail_place # 初始化失败坐标
    19. self.map = np.arange(map_width * map_high) # 给予每个地点一个标号(width * y + x)
    20. self.count = 0 # 用于记录一共走了多少步
    21. print(f"Environment初始化成功!\n"
    22. f"map_high:{self.map_high}, map_width:{self.map_width}\n"
    23. f"wall:{self.wall_place},success:{self.success_place},fail:{self.fail_place}")
    24. # 打印地图
    25. def print_map(self):
    26. print(f"\n------MAP------")
    27. for x in range(self.map_high):
    28. for y in range(self.map_width):
    29. if x == self.wall_place[0] and y == self.wall_place[1]:
    30. print(f"#", end=' ')
    31. elif x == self.success_place[0] and y == self.success_place[1]:
    32. print(f"√", end=' ')
    33. elif x == self.fail_place[0] and y == self.fail_place[1]:
    34. print(f"X", end=' ')
    35. else:
    36. print(f"{x * self.map_width + y}", end=' ')
    37. print()
    38. print(f'------MAP------\n')
    39. # 获取所在位置
    40. def get_observation(self):
    41. return self.map[self.x * self.map_width + self.y] # 返回现在所在位置
    42. # 更新当前位置
    43. def update_place(self, action):
    44. self.count += 1
    45. if action == 'down': # down
    46. if self.x < self.map_high - 1:
    47. if self.y == self.wall_place[1] and self.x + 1 == self.wall_place[0]:
    48. pass
    49. else:
    50. # print(f"{self.x, self.y}--> down --> ", end='')
    51. self.x += 1
    52. # print(f"{self.x, self.y}")
    53. elif action == 'up': # up
    54. if self.x > 0:
    55. if self.y == self.wall_place[1] and self.x - 1 == self.wall_place[0]:
    56. pass
    57. else:
    58. # print(f"{self.x, self.y}--> up--> ", end='')
    59. self.x -= 1
    60. # print(f"{self.x, self.y}")
    61. elif action == 'left': # left
    62. if self.y > 0:
    63. if self.x == self.wall_place[0] and self.y - 1 == self.wall_place[1]:
    64. pass
    65. else:
    66. # print(f"{self.x, self.y}--> left -->", end='')
    67. self.y -= 1
    68. # print(f"{self.x, self.y}")
    69. elif action == 'right': # right
    70. if self.y < self.map_width - 1:
    71. if self.x == self.wall_place[0] and self.y + 1 == self.wall_place[1]:
    72. pass
    73. else:
    74. # print(f"{self.x, self.y}--> right --> ", end='')
    75. self.y += 1
    76. # print(f"{self.x, self.y}")
    77. # 是否已到达终点
    78. def get_terminal(self):
    79. if self.x == self.success_place[0] and self.y == self.success_place[1]:
    80. done = True
    81. elif self.x == self.fail_place[0] and self.y == self.fail_place[1]:
    82. done = True
    83. else:
    84. done = False
    85. return done
    86. # 获得下一步的环境的实际情况
    87. def get_target(self, action):
    88. if action == 'down':
    89. if self.x + 1 == self.success_place[0] and self.y == self.success_place[1]:
    90. score = 1
    91. pre_done = True
    92. elif self.x + 1 == self.fail_place[0] and self.y == self.fail_place[1]:
    93. score = -1
    94. pre_done = True
    95. else:
    96. score = -0.02
    97. pre_done = False
    98. if self.x == self.map_high - 1:
    99. return self.map[self.x * self.map_width + self.y], score, pre_done
    100. else:
    101. if self.x + 1 == self.wall_place[0] and self.y == self.wall_place[1]:
    102. return self.map[self.x * self.map_width + self.y], score, pre_done
    103. return self.map[(self.x + 1) * self.map_width + self.y], score, pre_done
    104. elif action == 'up':
    105. if self.x - 1 == self.success_place[0] and self.y == self.success_place[1]:
    106. score = 1
    107. pre_done = True
    108. elif self.x - 1 == self.fail_place[0] and self.y == self.fail_place[1]:
    109. score = -1
    110. pre_done = True
    111. else:
    112. score = -0.02
    113. pre_done = False
    114. if self.x == 0:
    115. return self.map[self.x * self.map_width + self.y], score, pre_done
    116. else:
    117. if self.x - 1 == self.wall_place[0] and self.y == self.wall_place[1]:
    118. return self.map[self.x * self.map_width + self.y], score, pre_done
    119. return self.map[(self.x - 1) * self.map_width + self.y], score, pre_done
    120. elif action == 'left':
    121. if self.y - 1 == self.success_place[1] and self.x == self.success_place[0]:
    122. score = 1
    123. pre_done = True
    124. elif self.y - 1 == self.fail_place[1] and self.x == self.fail_place[0]:
    125. score = -1
    126. pre_done = True
    127. else:
    128. score = -0.02
    129. pre_done = False
    130. if self.y == 0:
    131. return self.map[self.x * self.map_width + self.y], score, pre_done
    132. else:
    133. if self.y - 1 == self.wall_place[0] and self.x == self.wall_place[1]:
    134. return self.map[self.x * self.map_width + self.y], score, pre_done
    135. return self.map[self.x * self.map_width + self.y - 1], score, pre_done
    136. elif action == 'right':
    137. if self.y + 1 == self.success_place[1] and self.x == self.success_place[0]:
    138. score = 1
    139. pre_done = True
    140. elif self.y + 1 == self.fail_place[1] and self.x == self.fail_place[0]:
    141. score = -1
    142. pre_done = True
    143. else:
    144. score = -0.02
    145. pre_done = False
    146. if self.y == self.map_width - 1:
    147. return self.map[self.x * self.map_width + self.y], score, pre_done
    148. else:
    149. if self.y + 1 == self.wall_place[0] and self.x == self.wall_place[1]:
    150. return self.map[self.x * self.map_width + self.y], score, pre_done
    151. return self.map[self.x * self.map_width + self.y + 1], score, pre_done
    152. # 初始化,位置0,计数器归零
    153. def retry(self, start_colum): # 初始化
    154. self.x = start_colum
    155. self.y = start_colum
    156. self.count = 0

    此案例的Agent.py

    1. # -*- coding: utf-8 -*-
    2. """
    3. @Project :Q_learn
    4. @File :agent.py
    5. @Author :Hao
    6. @Date :2022-09-15 015 15:51
    7. @Describe :
    8. """
    9. import numpy as np
    10. import pandas as pd
    11. class Agent:
    12. def __init__(self, actions, long, learning_rate=0.05, reward_decay=0.9, e_greedy=1):
    13. self.actions = actions # 初始化可以进行的各种行为,传入为列表
    14. self.lr = learning_rate # 学习率,用于更新Q_table的值
    15. self.gamma = reward_decay # 衰减因子
    16. self.epsilon = e_greedy # 随机选择几率为1-e_greedy,当处于e_greedy内时,不随机选择。
    17. self.q_table = pd.DataFrame(columns=self.actions, dtype=np.float64) # 生成q_table,列向量为columns
    18. for i in range(long): # 向新建的q_table插入与二维格子相同数量的行向量
    19. line_table = pd.Series(
    20. [0.0, 0.0, 0.0, 0.0],
    21. name=i,
    22. index=actions
    23. )
    24. line_table_2_frame = line_table.to_frame()
    25. self.q_table = pd.concat([self.q_table, line_table_2_frame.T])
    26. print(f"Agent初始化成功!\n"
    27. f"{self.q_table}")
    28. # 贪心选择行动
    29. def choose_action_greed(self, observation):
    30. action_list = self.q_table.loc[observation, :] # 取出当前observation所在的不同方向
    31. action = np.random.choice(action_list[action_list == np.max(action_list)].index) # action总选择最优解
    32. return action # 返回应当做的action
    33. # 伴有部分随机选择
    34. def choose_action(self, observation):
    35. action_list = self.q_table.loc[observation, :] # 取出当前observation所在的不同方向
    36. if np.random.uniform() < self.epsilon: # 如果在epsilon几率内
    37. # 选出当前observation中Q值最大的方向,这里再加一个random.choice是为了防止出现两个概率相同
    38. action = np.random.choice(action_list[action_list == np.max(action_list)].index)
    39. else:
    40. action = np.random.choice(self.actions) # 如果不在epsilon内,则随机选择一个动作
    41. return action # 返回应当做的action
    42. # 学习
    43. def learn(self, observation_now, action, score, observation_after, done):
    44. q_predict = self.q_table.loc[observation_now, action] # 获得当前状态下,当前所作动作所对应的预测得分
    45. if done:
    46. # 如果完成了则q_target为下一个环境的实际情况得分,本例子中此时score为1
    47. q_target = score
    48. else:
    49. # 如果未完成则取下一个环境若干个动作中的最大得分作为这个环境的价值传递给当前环境
    50. q_target = score + self.gamma * self.q_table.loc[observation_after, :].max()
    51. # 根据所处的当前环境对各个动作的预测得分和下一步的环境的实际情况更新当前环境的q表
    52. self.q_table.loc[observation_now, action] += self.lr * (q_target - q_predict)

    这里给了两种行为选择方式,一种是全部贪心,一种是伴有10%的随机选择。

    main.py

    1. # -*- coding: utf-8 -*-
    2. """
    3. @Project :Q_learn
    4. @File :main.py
    5. @Author :Hao
    6. @Date :2022-09-15 015 15:50
    7. @Describe :
    8. """
    9. import time
    10. from environment import Environment
    11. from agent import Agent
    12. from find_max import find_max
    13. import pandas
    14. import matplotlib.pyplot as plt
    15. MAP_HIGH = 3
    16. MAP_WIDTH = 4
    17. WALL_PLACE = [1, 1]
    18. SUCCESS_PLACE = [2, 3]
    19. FAIL_PLACE = [1, 3]
    20. TIMES = 200
    21. e = 1e-4
    22. # site.print_map()
    23. E_LIST = []
    24. def train(learn_function):
    25. robot = Agent(['left', 'right', 'up', 'down'], MAP_HIGH * MAP_WIDTH) # 生成Agent
    26. site = Environment(MAP_HIGH, MAP_WIDTH, WALL_PLACE, SUCCESS_PLACE, FAIL_PLACE) # 生成环境
    27. STOP_FLAG = False
    28. for episode in range(TIMES):
    29. state = site.get_observation()
    30. while True:
    31. done = site.get_terminal() # 判断当前环境是否到达最后
    32. if done:
    33. interaction = '\n%s--第%s次episode,共使用步数:%s。' % (learn_function, episode + 1, site.count)
    34. print(interaction)
    35. # 存储本次记录,方便后续计算与上次最大差值
    36. fileName = "data/" + str(learn_function) + "_episode" + str(episode) + ".csv"
    37. robot.q_table.to_csv(fileName) # 将本次的q_table存储到本地文件中
    38. if episode != 0:
    39. old_file_name = "data/" + str(learn_function) + "_episode" + str(
    40. episode - 1) + ".csv" # 读取上一次的q_table
    41. old_q_table = pandas.read_csv(old_file_name, index_col=0)
    42. difference = (robot.q_table - old_q_table).abs()
    43. max_difference = find_max(difference.max())
    44. print(max_difference)
    45. print(f"最大差值:{max_difference}"
    46. f"\n------{episode + 2}------")
    47. E_LIST.append(max_difference)
    48. if max_difference <= e:
    49. STOP_FLAG = True
    50. break
    51. site.retry(0)
    52. break
    53. if learn_function == 'greed': # 贪心
    54. action = robot.choose_action_greed(state) # 获得下一步方向
    55. else:
    56. action = robot.choose_action(state) # 获得下一步方向
    57. state_after, score, pre_done = site.get_target(action) # 获得下一步的环境的实际情况
    58. robot.learn(state, action, score, state_after, pre_done) # 根据所处的当前环境对各个动作的预测得分和下一步的环境的实际情况更新当前环境的q表
    59. site.update_place(action) # 更新位置
    60. # print(f"state_now: {state}, action: {action}, state_after: {state_after}")
    61. state = state_after
    62. if STOP_FLAG:
    63. site.retry(0)
    64. break
    65. train('greed')
    66. random_e_list = E_LIST.copy()
    67. E_LIST.clear()
    68. train('random')
    69. greed_e_list = E_LIST.copy()
    70. plt.title('greed and random')
    71. plt.plot(greed_e_list, 'b--', random_e_list, 'g')
    72. plt.xlabel('Iterations')
    73. plt.ylabel('Adjacent difference')
    74. plt.legend(['choose_action_greed', 'choose_action_random1'], loc=1)
    75. plt.savefig('./photo/greed_random1.svg', dpi=300) # svg文件,可伸缩矢量图形
    76. plt.show()
    77. # print(f"greed_e_list:\n{greed_e_list}")
    78. # print(f"random_e_list:\n{random_e_list}")

    还有一个小工具类,find_max.py

    1. def find_max(different_max):
    2. max = -9999
    3. for i in range(4):
    4. if different_max[i] >= max:
    5. max = different_max[i]
    6. return max

    代码的最后,最生成图像,可以看到收敛曲线

  • 相关阅读:
    高效使用python之xlwt库编辑写入excel表内容
    数字孪生论文阅读笔记【3】
    Ansible自动化部署安装openGauss3.1企业版单机
    计算机、通信方向学习考证经验分享
    [k8s] kubectl port-forward 和kubectl expose的区别
    【算法】Inclusion of a Shuffled String Into another String
    鸿蒙Harmony应用开发—ArkTS声明式开发(触摸交互控制:触摸测试控制)
    2024Node.js零基础教程(小白友好型),nodejs新手到高手,(九)NodeJS入门——http模块
    RUST运算符重载
    我来谈谈“人工智能”这个词给我带来了哪些想法
  • 原文地址:https://blog.csdn.net/Hao_ge_666/article/details/126894658