【强化学习】什么是强化学习算法?

  • 一、强化学习解决什么问题?
  • 二、强化学习如何解决问题?
    • 2.1、强化学习的基本框架
    • 2.2、强化学习系统的要素
    • 2.3、强化学习与监督学习的区别
    • 2.4、强化学习与非监督学习的区别
  • 三、强化学习实例
    • 3.1、训练Tic-Tac-Toe游戏玩家的强化学习理解
    • 3.2、训练Tic-Tac-Toe游戏玩家的python代码
  • 参考资料

本博文通过参考《深入浅出强化学习原理入门》的第一章与《Reinforcement Learning: An Introduction》的Chapter 1部分和 知乎专栏,解释什么是强化学习算法。

一、强化学习解决什么问题?

强化学习的经典应用案例有:非线性二级摆系统(非线性控制问题)、棋类游戏、机器人学习站立和走路、无人驾驶、机器翻译、人机对话 等。概括来说,强化学习所能解决的问题为序贯决策问题,就是需要连续不断做出决策,才能实现最终目标的问题。强化学习与其它的机器学习方法相比,专注于从交互中进行以目标为导向的学习。

二、强化学习如何解决问题?

强化学习主要是学习What to do(在当前情况下该如何选择动作),就是如何将情况(situations)与动作(actions)对应起来,以达到最大化的数值奖励信号。

2.1、强化学习的基本框架

强化学习的基本框架如下图所示,强化学习的主体一般被称为agent,其与environment互动以达到某种目的。所有强化学习的agent有明确的目标,能够感知全部或者部分environment,并且选择action执行来影响environment。除此之外,还要假设在最开始,agent需要在对于所面对的environment一无所知的情况下采取行动。

强化学习的三个特征:(1)强化学习是一个闭环问题。(2)没有直接对该如何选择action的指示,需要试探搜索去发现哪个动作会产生最大的数值奖励。(3)动作不光会影响直接的奖励,还会影响接下来的环境状态。

2.2、强化学习系统的要素

一个强化学习系统一般包括如下的几个要素:
(1)policy(策略)
policy是从感知到的environment的state到在这些state下要执行的action的映射。这对应于心理学中stimulus-response rules or associations(应激-反应规则或关联)。在一些情况下,policy可以是简单的函数或者是查表。而在别的情况下,可能会需要更多的计算,例如暴力搜索。policy是强化学习agent的核心,因为一个policy便可以单独决定agent的行为。另外,policy也可能是随机的。
(2)reward signal(奖励信号)
reward signal定义了强化学习问题的目标(goal)。在每个时间步内,environment给agent发送一个奖励值。agent唯一的目标便是在长时间运行中最大化接收到的总的reward。reward signal定义了一件事对于agent来说是好是坏。任一时刻发送给agent的reward取决于agent当前的action以及当前environment的state。agent影响reward signal的唯一方式就是通过action直接影响reward,或者通过改变environment的state间接影响。reward signal是改变policy的首要基础。如果一个policy选择了低reward的action,则之后在同样情况下,policy可能会改为选其他的action。总的来说,reward signal可能是environment state和采取的action的函数(也可以带有随机性)。
(3)value function(值函数)
reward signal表示的是在直接感受下哪个是好的。而value function则是表示从长期来看,什么是好的。也就是state的value(价值)是一个agent从当前state开始,在未来期望累积的总的reward。reward定义的是环境state直接的好处,而value是state长期的好处,考虑了之后可能会出现的state以及这些state下的reward。例如一个state可能会产生一个低的reward,但是有着高的value,因为跟着它的通常是一些会产生高reward的state。反之亦然。

reward是首要的,而value是其次的,因为没有reward就没有value。但是当我们做决策并对决策进行评估时,更关注的是value。对于action的选择是基于value来判断的。我们追寻的是带来最高value的state而不是最高的reward,因为这些action从长远上来讲会获得最多的reward。但不幸的是,决定value要比决定reward难得多。reward是由environment直接给出的,但是value是需要对agent的整个执行时间内的状况进行观察,以此对value进行估计和重估计。事实上,强化学习算法中最重要的部分就是如何有效地估计value。
(4)model of the environment(环境模型)
model of the environment是用来模拟真实environment的行径的,或者说是对environment会如何表现的推断。例如,给定一个state和action,这个model会预测因此产生的下一state和下一reward。model一般用在planning(规划)里,可以在真正执行之前通过考虑未来的可能情况来决定一系列动作。利用model和planning用来解决强化学习问题的方法被称为model-based方法,作为更简单的model-free方法的对照。model-free方法主要是指通过trial-and-error(试错)学习,是planning的对立。(就是planning不需要直接执行action与真实的environment互动,可以对environment建模,然后自己跟这个environment模型互动。这样就叫planning)

2.3、强化学习与监督学习的区别

监督学习需要的是标签数据,通过训练获得模型来推断那些不在训练集中的样本的标签应该是什么,监督学习的主要目的是总结概括。强化学习需要的是带有回报的交互数据,agent需要通过从自己的经验中学习如何使自己的利益最大化。

2.4、强化学习与非监督学习的区别

非监督学习一般是寻找未标注数据中同一类的结构信息,而强化学习专注于为agent实现reward最大化。

三、强化学习实例

3.1、训练Tic-Tac-Toe游戏玩家的强化学习理解

Tic-Tac-Toe(井字棋)游戏:两名玩家轮流在一个三乘三的棋盘上比赛。 一个玩家画X和另一个玩家画O,直到一个玩家通过在水平,垂直或对角线上连续放置三个标记来获胜(下图表示画X的玩家获胜)。如果整个表都被填满了而没有人获胜,那么比赛就是平局。 由于一个比较熟练的玩家可以保证不败,我们假设我们的对手并不是一个完美的玩家,有时他会下错地方。我们认为输和平局对我们来说是一样坏的,我们该如何构建一个玩家,其能够发现对手的不完美并且学习如何最大化自己获胜的可能性?

本博文介绍基于value function的强化学习来训练tic-tac-toe游戏玩家的方法。首先对这个游戏每个可能的state建立一个数表,每个数都是从这个state开始获胜概率的最新估计。我们把这个估计看做这个state的value。若State A有比B更高的value,说明A比B好,也就是当前估计下,从state A开始获胜的概率比从B开始大。

假设我们是下X的,那么所有有三个X在一行(一列,斜对角)的state的获胜概率是1,所有三个O在一行(一列,斜对角)或者填满(平局)的state的获胜概率是0,其余所有state的初始概率是0.5,代表我们猜测我们有一半几率获胜。

强化学习训练过程中,需要权衡Exploration 和 Exploitation的平衡关系(参考资料4),下面的Tic-Tac-Toe游戏的python代码利用的是greedgreedgreed and ε−greed\varepsilon - greedε−greed 的方法。与对手玩多轮游戏。为了选择下一步该下在哪,我们检测了我们每一个可能的落子之后产生的state,在表中查询他们当前的value。一般情况下,我们是greedy的,也就是选择那些会导致有最高value的state的地方落子,也就是有最高获胜可能性的地方。偶尔,我们会在其他位置里随机选一个落子。这种叫exploratory(试探性的)的落子,因为这能让我们去经历之前没见过的state。

在玩这个游戏的过程中,不停改变这些state的value,尽可能让它们更准确地估计获胜概率。每一次落子之后,将之前state的value向之后state的value靠近。sss表示落子之前的state,s′s's′表示落子之后的state,V(S)V\left( S \right)V(S)表示sss对应的value,对于V(S)V\left( S \right)V(S)的更新可以写为:

V(S)←V(S)+α[V(S′)−V(S)]V\left( S \right) \leftarrow V\left( S \right) + \alpha \left[ {V\left( {S'} \right) - V\left( S \right)} \right]V(S)←V(S)+α[V(S′)−V(S)]

α\alphaα为步长,是一个小的分数,影响学习率。这种更新规则被称作temporal-difference(时间差分)学习方法。因为其更新是基于两个不同时间对value的估计之差V(S′)−V(S){V\left( {S'} \right) - V\left( S \right)}V(S′)−V(S)的。
如果步长参数随着时间适当减小,对于任意固定的对手,这个方法是可以收敛到每个state下我们真实的获胜概率的。更进一步地,我们所选择的落子的地方(除了exploratory的选择)事实上都是对抗对手最优的选择。也就是说,这种方法能够收敛到最优的policy。

强化学习可以应用于系统的高阶和低阶。虽然井字游戏的玩家只学习了游戏的基本动作,但没有什么能阻止强化学习在更高的层次上进行,在这个层次上,每个动作“可能本身就是一种精心设计的解决问题方法的应用”。在分层学习系统中,强化学习可以在多个层次上同时进行。

3.2、训练Tic-Tac-Toe游戏玩家的python代码

import numpy as np
import pickleBOARD_ROWS = 3   ##棋盘行数
BOARD_COLS = 3   ##棋盘列数
BOARD_SIZE = BOARD_ROWS * BOARD_COLSclass State:  def __init__(self):# the board is represented by an n * n array,# 1 represents a chessman of the player who moves first,# -1 represents a chessman of another player# 0 represents an empty positionself.data = np.zeros((BOARD_ROWS, BOARD_COLS))self.winner = Noneself.hash_val = Noneself.end = None# compute the hash value for one state, it's uniquedef hash(self):'''计算棋盘不同state对应的hash值'''if self.hash_val is None:self.hash_val = 0for i in self.data.reshape(BOARD_ROWS * BOARD_COLS):if i == -1:i = 2self.hash_val = self.hash_val * 3 + ireturn int(self.hash_val)# check whether a player has won the game, or it's a tie(监测是否有玩家获胜或平局)def is_end(self):if self.end is not None:return self.endresults = []# check rowfor i in range(0, BOARD_ROWS):results.append(np.sum(self.data[i, :]))# check columnsfor i in range(0, BOARD_COLS):results.append(np.sum(self.data[:, i]))# check diagonalsresults.append(0)for i in range(0, BOARD_ROWS):results[-1] += self.data[i, i]results.append(0)for i in range(0, BOARD_ROWS):results[-1] += self.data[i, BOARD_ROWS - 1 - i]for result in results:if result == 3:self.winner = 1self.end = Truereturn self.endif result == -3:self.winner = -1self.end = Truereturn self.end# whether it's a tie(当棋盘下满还没有胜负,则游戏为平局)sum = np.sum(np.abs(self.data))if sum == BOARD_ROWS * BOARD_COLS:self.winner = 0self.end = Truereturn self.end# game is still going onself.end = Falsereturn self.end# @symbol: 1 or -1# put chessman symbol in position (i, j)def next_state(self, i, j, symbol):new_state = State()new_state.data = np.copy(self.data)new_state.data[i, j] = symbolreturn new_state# print the boarddef print(self):for i in range(0, BOARD_ROWS):print('-------------')out = '| 'for j in range(0, BOARD_COLS):if self.data[i, j] == 1:token = '*'if self.data[i, j] == 0:token = '0'if self.data[i, j] == -1:token = 'x'out += token + ' | 'print(out)print('-------------')def get_all_states_impl(current_state, current_symbol, all_states):for i in range(0, BOARD_ROWS):for j in range(0, BOARD_COLS):if current_state.data[i][j] == 0:newState = current_state.next_state(i, j, current_symbol)newHash = newState.hash()if newHash not in all_states.keys():isEnd = newState.is_end()all_states[newHash] = (newState, isEnd)if not isEnd:get_all_states_impl(newState, -current_symbol, all_states)def get_all_states():current_symbol = 1current_state = State()all_states = dict()all_states[current_state.hash()] = (current_state, current_state.is_end())get_all_states_impl(current_state, current_symbol, all_states)return all_states# all possible board configurations
all_states = get_all_states()class Judger:# @player1: the player who will move first, its chessman will be 1# @player2: another player with a chessman -1# @feedback: if True, both players will receive rewards when game is enddef __init__(self, player1, player2):self.p1 = player1self.p2 = player2self.current_player = Noneself.p1_symbol = 1self.p2_symbol = -1self.p1.set_symbol(self.p1_symbol)self.p2.set_symbol(self.p2_symbol)self.current_state = State()def reset(self):self.p1.reset()self.p2.reset()def alternate(self):while True:yield self.p1yield self.p2# @print: if True, print each board during the gamedef play(self, print=False):alternator = self.alternate()self.reset()current_state = State()self.p1.set_state(current_state)self.p2.set_state(current_state)while True:player = next(alternator)if print:current_state.print()[i, j, symbol] = player.act()next_state_hash = current_state.next_state(i, j, symbol).hash()current_state, is_end = all_states[next_state_hash]self.p1.set_state(current_state)self.p2.set_state(current_state)if is_end:if print:current_state.print()return current_state.winner# AI player
class Player:# @step_size: the step size to update estimations# @epsilon: the probability to exploredef __init__(self, step_size=0.1, epsilon=0.1):self.estimations = dict()self.step_size = step_sizeself.epsilon = epsilonself.states = []self.greedy = []def reset(self):self.states = []self.greedy = []def set_state(self, state):self.states.append(state)self.greedy.append(True)def set_symbol(self, symbol):self.symbol = symbolfor hash_val in all_states.keys():(state, is_end) = all_states[hash_val]if is_end:if state.winner == self.symbol:self.estimations[hash_val] = 1.0elif state.winner == 0:# we need to distinguish between a tie and a loseself.estimations[hash_val] = 0.5else:self.estimations[hash_val] = 0else:self.estimations[hash_val] = 0.5# update value estimationdef backup(self):# for debug# print('player trajectory')# for state in self.states:#     state.print()self.states = [state.hash() for state in self.states]for i in reversed(range(len(self.states) - 1)):state = self.states[i]td_error = self.greedy[i] * (self.estimations[self.states[i + 1]] - self.estimations[state])self.estimations[state] += self.step_size * td_error# choose an action based on the statedef act(self):state = self.states[-1]next_states = []next_positions = []for i in range(BOARD_ROWS):for j in range(BOARD_COLS):if state.data[i, j] == 0:next_positions.append([i, j])next_states.append(state.next_state(i, j, self.symbol).hash())if np.random.rand() < self.epsilon:action = next_positions[np.random.randint(len(next_positions))]action.append(self.symbol)self.greedy[-1] = Falsereturn actionvalues = []for hash, pos in zip(next_states, next_positions):values.append((self.estimations[hash], pos))np.random.shuffle(values)values.sort(key=lambda x: x[0], reverse=True)action = values[0][1]action.append(self.symbol)return actiondef save_policy(self):with open('policy_%s.bin' % ('first' if self.symbol == 1 else 'second'), 'wb') as f:pickle.dump(self.estimations, f)def load_policy(self):with open('policy_%s.bin' % ('first' if self.symbol == 1 else 'second'), 'rb') as f:self.estimations = pickle.load(f)# human interface
# input a number to put a chessman
# | q | w | e |
# | a | s | d |
# | z | x | c |
class HumanPlayer:def __init__(self, **kwargs):self.symbol = Noneself.keys = ['q', 'w', 'e', 'a', 's', 'd', 'z', 'x', 'c']self.state = Nonereturndef reset(self):returndef set_state(self, state):self.state = statedef set_symbol(self, symbol):self.symbol = symbolreturndef backup(self, _):returndef act(self):self.state.print()key = input("Input your position:")data = self.keys.index(key)i = data // int(BOARD_COLS)j = data % BOARD_COLSreturn (i, j, self.symbol)def train(epochs):player1 = Player(epsilon=0.01)player2 = Player(epsilon=0.01)judger = Judger(player1, player2)player1_win = 0.0player2_win = 0.0for i in range(1, epochs + 1):winner = judger.play(print=False)if winner == 1:player1_win += 1if winner == -1:player2_win += 1print('Epoch %d, player 1 win %.02f, player 2 win %.02f' % (i, player1_win / i, player2_win / i))player1.backup()player2.backup()judger.reset()player1.save_policy()player2.save_policy()def compete(turns):player1 = Player(epsilon=0)player2 = Player(epsilon=0)judger = Judger(player1, player2)player1.load_policy()player2.load_policy()player1_win = 0.0player2_win = 0.0for i in range(0, turns):winner = judger.play()if winner == 1:player1_win += 1if winner == -1:player2_win += 1judger.reset()print('%d turns, player 1 win %.02f, player 2 win %.02f' % (turns, player1_win / turns, player2_win / turns))# The game is a zero sum game. If both players are playing with an optimal strategy, every game will end in a tie.
# So we test whether the AI can guarantee at least a tie if it goes second.
def play():while True:player1 = HumanPlayer()player2 = Player(epsilon=0)judger = Judger(player1, player2)player2.load_policy()winner = judger.play()if winner == player2.symbol:print("You lose!")elif winner == player1.symbol:print("You win!")else:print("It is a tie!")if __name__ == '__main__':##两个AI玩家进行强化学习训练train(int(1e5))##两个AI玩家进行强化学习测试compete(int(1e3))##human玩家与AI玩家比赛play()

参考资料

1、《深入浅出强化学习原理入门》
2、《Reinforcement Learning: An Introduction》
3、https://zhuanlan.zhihu.com/p/50347818
4、https://blog.csdn.net/LagrangeSK/article/details/81010195

【强化学习】什么是强化学习算法?相关推荐

  1. 强化学习ppt_机器学习原理、算法与应用配套PPT第四部分(深度学习概论、自动编码器、强化学习、聚类算法、半监督学习等)...

    本文是SIGAI公众号文章作者雷明编写的<机器学习>课程新版PPT第四部分,包含了课程内容的深度学习概论,自动编码器,受限玻尔兹曼机,聚类算法1,聚类算法2,聚类算法3,半监督学习,强化学 ...

  2. 离线强化学习(Offline RL)系列3: (算法篇) IQL(Implicit Q-learning)算法详解与实现

    [更新记录] 论文信息:Ilya Kostrikov, Ashvin Nair, Sergey Levine: "Offline Reinforcement Learning with Im ...

  3. 离线强化学习(Offline RL)系列3: (算法篇)策略约束 - BRAC算法原理详解与实现(经验篇)

    论文原文:[Yifan Wu, George Tucker, Ofir Nachum: "Behavior Regularized Offline Reinforcement Learnin ...

  4. 离线强化学习(Offline RL)系列3: (算法篇) AWAC算法详解与实现

    [更新记录] 论文信息:AWAC: Accelerating Online Reinforcement Learning with Offline Datasets [Code] 本文由UC Berk ...

  5. ChatGPT 使用 强化学习:Proximal Policy Optimization算法(详细图解)

    ChatGPT 使用 强化学习:Proximal Policy Optimization算法 强化学习中的PPO(Proximal Policy Optimization)算法是一种高效的策略优化方法 ...

  6. 人群环境中基于深度强化学习的移动机器人避障算法

    摘要: 为了控制移动机器人在人群密集的复杂环境中高效友好地完成避障任务,本文提出了一种人群环境中基于深度强化学习的移动机器人避障算法.首先,针对深度强化学习算法中值函数网络学习能力不足的情况,基于行人 ...

  7. 离线强化学习(Offline RL)系列3: (算法篇) Onestep 算法详解与实现

    [更新记录] 论文信息: David Brandfonbrener, William F. Whitney, Rajesh Ranganath, Joan Bruna: "Offline R ...

  8. 离线强化学习(Offline RL)系列3: (算法篇)策略约束 - BEAR算法原理详解与实现

    论文信息:Stabilizing Off-Policy Q-Learning via Bootstrapping Error Reduction 本文由UC Berkeley的Sergey Levin ...

  9. 计算机科学与技术对无人机,基于强化学习的无人机空中格斗算法研究-计算机科学与技术专业论文.docx...

    Classified Index: TP391.9 U.D.C: 629.7.08 Dissertation for the Master Degree in Engineering RESEARCH ...

  10. 第七章 人工智能,7.1 基于深度强化学习与自适应在线学习的搜索和推荐算法研究(作者:灵培、霹雳、哲予)...

    7.1 基于深度强化学习与自适应在线学习的搜索和推荐算法研究 1. 搜索算法研究与实践 1.1 背景 淘宝的搜索引擎涉及对上亿商品的毫秒级处理响应,而淘宝的用户不仅数量巨大,其行为特点以及对商品的偏好 ...

最新文章

  1. 基础练习 高精度加法
  2. Gradle of Android Example
  3. 构建、测试和部署驱动程序
  4. linux下的ps 查看进程命令
  5. 双缓冲 android,Android 的 SurfaceView 双缓冲应用
  6. docker启动顺序
  7. java获取spring数据源_Spring动态注册多数据源的实现方法
  8. 15.try...except...finally
  9. 【正在等待可用套接字】解决方法
  10. Output argument fuse (and maybe others) not assigned during call to
  11. flutter弹框怎么封装_Flutter初始化时 弹出弹出框
  12. C#反射技术的简单操作(读取和设置类的属性)
  13. Python3 打包成exe时,去掉dos窗口
  14. Python 求峰值
  15. 结对编程_我从结对编程面试中学到的东西
  16. python游戏解法图_python 游戏(记忆拼图Memory_Puzzle)
  17. 表单提交时报错:No result defined for action com.ylj.action.BbsAction and result input
  18. windows xp iis5.1服务器安装
  19. 2019牛客暑期多校训练营(第九场)H Cutting Bamboos(主席树+二分)
  20. Ebox 的OS定制

热门文章

  1. 硬件知识——主板结构
  2. Proxmox集群网络配置
  3. Pumpkin Raising Walk Through
  4. timesat数据如何读取_判二手车调表车另类方法。如何利用OBD读取可靠数据(技术类)...
  5. 如何计算机闲置虚拟机算法_利用闲置计算机的最佳方法
  6. ysdk应用宝渠道接入问题记录
  7. 双非二本计算机学生是应该考研还是就业
  8. jsapi设计_Sketch插件如何架构
  9. SEM(结构方程模型)
  10. 可靠性指标中MTTF MTBF MTTR