强化学习(reinforcement learning),又称再励学习、评价学习,是一种重要的机器学习方法,强化学习是智能体(Agent)以“试错”的方式进行学习,通过与环境进行交互获得的奖赏指导行为,目标是使智能体获得最大的奖赏,强化学习不同于连接主义学习中的监督学习,主要表现在强化信号上,强化学习中由环境提供的强化信号是对产生动作的好坏作一种评价(通常为标量信号),而不是告诉强化学习系统RLS如何去产生正确的动作。由于外部环境提供的信息很少,RLS必须靠自身的经历进行学习。通过这种方式,RLS在行动-评价的环境中获得知识,改进行动方案以适应环境。
强化学习是从动物学习、参数扰动自适应控制等理论发展而来,其基本原理是:如果Agent的某个行为策略导致环境正的奖赏(强化信号),那么Agent以后产生这个行为策略的趋势便会加强。Agent的目标是在每个离散状态发现最优策略以使期望的折扣奖赏和最大。
强化学习把学习看作试探评价过程,Agent选择一个动作用于环境,环境接受该动作后状态发生变化,同时产生一个强化信号(奖或惩)反馈给Agent,Agent根据强化信号和环境当前状态再选择下一个动作,选择的原则是使受到正强化(奖)的概率增大。选择的动作不仅影响立即强化值,而且影响环境下一时刻的状态及最终的强化值。
强化学习不同于连接主义学习中的监督学习,主要表现在教师信号上,强化学习中由环境提供的强化信号是Agent对所产生动作的好坏作一种评价(通常为标量信号),而不是告诉Agent如何去产生正确的动作。由于外部环境提供了很少的信息,Agent必须靠自身的经历进行学习。通过这种方式,Agent在行动一一评价的环境中获得知识,改进行动方案以适应环境。
强化学习系统学习的目标是动态地调整参数,以达到强化信号最大。若已知r/A梯度信息,则可直接可以使用监督学习算法。因为强化信号r与Agent产生的动作A没有明确的函数形式描述,所以梯度信息r/A无法得到。因此,在强化学习系统中,需要某种随机单元,使用这种随机单元,Agent在可能动作空间中进行搜索并发现正确的动作。
了解下Q-learning算法
Q-learning算法的伪代码
中文版的伪代码:
Q value的更新是根据贝尔曼方程:
问题情境
-o—T:T 就是宝藏的位置, o 是探索者的位置。环境是一个一维世界,在世界的右边有宝藏,探索者只要得到宝藏尝到了甜头,以后就记住了得到宝藏的方法,这就是他用强化学习所学习到的行为。
Q-learning 是一种记录行为值 (Q value) 的方法,每种在一定状态的行为都会有一个值 Q(s, a),就是说 行为 a 在 s 状态的值是 Q(s, a)。s 在上面的探索者游戏中,就是 o 所在的地点了。而每一个地点探索者都能做出两个行为 left/right,这就是探索者的所有可行的 a 啦。
1.参数
2.探索者可到达的位置
3.定义一个函数确定当前位置状态的下一个位置
4.定义一个函数取得探索者执行的动作,返回的是一个list,包含所有合法的动作。
5.根据state制作表格:(表格为一个二维的dataframe)
q_table = pd.DataFrame(data=[[0 for _ in actions] for _ in states],
index=states, columns=actions)
关于Python panda库中.DataFrame建立如Excel那样的二维表格的内容参考链接:
python pandas (ix & iloc &loc) 的区别
【Python学习笔记】Pandas库之DataFrame
6.当探索成功后,更新环境, ‘-----T’!探索者到达状态(位置)时,将该位置的字符替换成’o’,并打印。
代码如下
'''
-o---T
T 就是宝藏的位置, o 是探索者的位置
'''
# @作者: James_Bobo
# @时间:20190327
import pandas as pd
import random
import time
#########参数
epsilon = 0.9 # 贪婪度 greedy
alpha = 0.1 # 学习率
gamma = 0.8 # 奖励递减值
#####探索者的状态,即其可到达的位置,有6个len('-o---T')。所以定义
states = range(6) # 状态集。从0到5
actions = ['left', 'right'] # 动作集。也可添加动作'none',表示停留
rewards = [0,0,0,0,0,1] # 奖励集。只有最后的宝藏所在位置才有奖励1,其他皆为0
q_table = pd.DataFrame(data=[[0 for _ in actions] for _ in states],
index=states, columns=actions)
def update_env(state):
'''更新环境,并打印'''
global states #states设置为全局变量
env = list('-----T') # 环境,就是这样一个字符串(list)!!
if state != states[-1]:
env[state] = 'o'
print('\r{}'.format(''.join(env)), end='')
time.sleep(0.1)
###那么,在某个状态下执行某个动作之后,到达的下一个状态如何确定呢?
def get_next_state(state, action):
'''对状态执行动作后,得到下一状态'''
global states
# l,r,n = -1,+1,0
if action == 'right' and state != states[-1]: # 除非最后一个状态(位置),向右就+1
next_state = state + 1
elif action == 'left' and state != states[0]: # 除非最前一个状态(位置),向左就-1
next_state = state -1
else:
next_state = state
return next_state
def get_valid_actions(state):
'''取当前状态下的合法动作集合,与reward无关!'''
global actions # ['left', 'right']
valid_actions = set(actions)
if state == states[-1]: # 最后一个状态(位置),则
valid_actions -= set(['right']) # 不能向右
if state == states[0]: # 最前一个状态(位置),则
valid_actions -= set(['left']) # 不能向左
return list(valid_actions)
for i in range(13):
#current_state = random.choice(states)
current_state = 0
update_env(current_state) # 环境相关
total_steps = 0 # 环境相关
while current_state != states[-1]:
if (random.uniform(0,1) > epsilon) or ((q_table.ix[current_state] == 0).all()): # 探索
current_action = random.choice(get_valid_actions(current_state))
else:
current_action = q_table.ix[current_state].idxmax() # 利用(贪婪)
next_state = get_next_state(current_state, current_action)
next_state_q_values = q_table.ix[next_state, get_valid_actions(next_state)]
q_table.ix[current_state, current_action] += alpha * (rewards[next_state] + gamma * next_state_q_values.max() - q_table.ix[current_state, current_action])
current_state = next_state
update_env(current_state) # 环境相关
total_steps += 1 # 环境相关
print('\rEpisode {}: total_steps = {}'.format(i, total_steps), end='') # 环境相关
time.sleep(2) # 环境相关
print('\r ', end='') # 环境相关
print('\nq_table:')
print(q_table)
在Python 3.6.0的环境下运行了一下上面的代码,在经过13次动态学习之后,结果如下所示:
q_table:
left right
0 0.000000 0.003027
1 0.000000 0.019097
2 0.000000 0.102957
3 0.007176 0.334104
4 0.026208 0.745813
5 0.000000 0.000000
Process finished with exit code 0