(转)简单强化Q-learning的Python实现

(转)简单强化Q-learning的Python实现




强化学习(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的更新是根据贝尔曼方程:

Q(st,at)←Q(st,at)+α[rt+1+λmaxaQ(st+1,a)−Q(st,at)]
问题情境
-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

你可能感兴趣的:(强化学习,机器学习,python)