强化学习及Python代码⽰例
1 概述
强化学习是机器学习⾥⾯的⼀个分⽀。它强调如何基于环境⽽⾏动,以取得最⼤化的预期收益。其灵感来源于⼼理学中的⾏为主义理论,既有机体如何在环境给予的奖励或者惩罚的刺激下,逐步形成对刺激的预期,产⽣能够最⼤利益的习惯性⾏为。结构简图如下:
因为强化学习考虑到了⾃主个体、环境、奖励等因素,所以很多⼈包括强化学习的研究者Richard Sutton 都认为它是⼈⼯智能中最⾼层的模型,其它深度学习、机器学习模型都是它的⼦系统。
在围棋界先后打败世界冠军的李世乭和柯洁额alphaGo就使⽤了强化学习模型,也正是这两次⽐赛,把⼈⼯智能这个概念传递给了⼤众。
2 结构
智能体(Agent):智能体的结构可以是⼀个神经⽹络,可以是⼀个简单的算法,智能体的输⼊通常是状态State,输出通常是策略Policy。
动作(Actions):动作空间。⽐如⼩⼈玩游戏,只有上下左右可移动,那Actions就是上、下、左、右。
状态(State):就是智能体的输⼊
奖励(Reward):进⼊某个状态时,能带来正奖励或者负奖励。
环境(Environment):接收action,返回state和reward。
3 思想
智能体对环境执⾏⼀个动作,环境接收动作后把当前状态和奖励返回给智能体;然后智能体根据环境返回的状态和奖赏执⾏下⼀个动作。
4 相关概念
探索(exploration): 不去选择最优解,⽽是随机选择
开发(exploitation):选择最优解
马尔科夫决策: 马尔科夫决策过程指你接下来的所有状态和决策只取决于你当前的状态和决策。⽐如你下象棋,你⾛第四步时,影响你决策和接下来状态的只有第三步。
5 执⾏过程
拿教电脑玩flappybird游戏来说明:
我们需要确定的两个东西是游戏,⼀个是电脑,
⽬的是电脑玩游戏。
游戏接收⼀个Action操作,Action是⼀个⼀维数组,⽐如a = [0,1] 当a[1] = 1的时候,我们让⼩鸟向上飞。如果是其它的数,⼩鸟下落。 游戏返回的是什么呢,游戏返回的是State,reward,terminal。terminal是⼀个布尔值True或者false,它和reward是对应的。当reward=-1时,terminal为True。reward取值有三种(1,-1,0.1)当crash时为-1,当越过障碍时为1,其它状态为0.1。⽽State的结构是类似80x80x4这样的图像。
也就是 currentState, reward,newState, terminal是⼀条数据被保存起来了。
好现在我们有了游戏的输⼊和输出。
看⼀下⼈的输⼊和输出。这⾥的⼈其实就是⼀个神经⽹络。
它是边训练,边迭代。
它的输⼊是state,这个有了。
但是我们还没有y啊 ,没有y我们怎么进⾏迭代呢。
y的计算⽅法是:如果停⽌了,y就等于本次的reward。如果这次没有停⽌,就等于这次的reward加上下次的价值Q
好了 有了y和x和神经⽹络的结构
我们的⽬标函数是⼆次函数。(y-QValue)^2。
6 推导
就是我们定义⼀个概念叫价值(Value),就是在某个时刻,某个状态下执⾏某个动作会得到⼀个回报(Reward),然后在下⼀个时刻执⾏某个动作⼜会得到⼀个回报,依次类推。
我们把这些回报累加起来:
这⾥的G相当于⽬前状态决策下的总回报。
如果我们把该回报的价值⽤⼀个价值函数来表⽰:
E表⽰期望
即价值函数为⽬前状态下回报的期望。
对上式进⾏展开运算:
即得到以上贝尔曼⽅程。当前状态下的价值取决于当前的回报加上之后状态的价值(根据lamda决定其权重)。这其实就相当于⼀种动态规划的思想。
7 ⽰例教机器⼈玩Flappy bird游戏
7.1 输⼊值预处理:
1)把图像⼤⼩resize成80x80
2)把图像转换成灰度图
3)把图像⼆值化,只有⿊⽩两⾊0或者255。
4)把连续的四帧图像作为⼀个输⼊(State)。
x_t = cv2.size(x_t, (80, 80)), cv2.COLOR_BGR2GRAY)
ret, x_t = cv2.threshold(x_t,1,255,cv2.THRESH_BINARY)
s_t = np.stack((x_t, x_t, x_t, x_t), axis=2)
7.2 构建智能体
智能体结构图
智能体是⼀个6层的神经⽹络
第⼀层(输⼊层)是80x80x4:80x80是图⽚的长宽像素值,4代表每次输⼊⽤4帧图⽚ 第⼆层是20x20x32:20x20代表特征图的长宽,32代表特征图个数
第三层是5x5x64:5x5代表特征图的长宽,64代表特征图个数
第四层是3x3x64 -> 256x1:3x3代表特征图的长宽,64代表特征图的个数
第五层是256x1:256=2x2x64,是矩阵reshape的结果
第六层(输出层)是2x1:2代表向上⾛的概率和向下⾛的概率
注:第⼆层和第三层在图上都有池化,在代码中并没有这个池化操作。
然后是各层的连接⽅式:
第⼀层与第⼆层,第⼆层与第三层,第三层与第四层是卷积。
第四层与第五层,第五层与第六层是全连接。
def createNetwork():
# network weights
W_conv1 = weight_variable([8, 8, 4, 32])
b_conv1 = bias_variable([32])
W_conv2 = weight_variable([4, 4, 32, 64])
b_conv2 = bias_variable([64])
W_conv3 = weight_variable([3, 3, 64, 64])
b_conv3 = bias_variable([64])
W_fc1 = weight_variable([1600, 512])
b_fc1 = bias_variable([512])
W_fc2 = weight_variable([512, ACTIONS])
b_fc2 = bias_variable([ACTIONS])
# input layer
s = tf.placeholder("float", [None, 80, 80, 4])
# hidden layers
h_conv1 = lu(conv2d(s, W_conv1, 4) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)
h_conv2 = lu(conv2d(h_pool1, W_conv2, 2) + b_conv2)
#h_pool2 = max_pool_2x2(h_conv2)
h_conv3 = lu(conv2d(h_conv2, W_conv3, 1) + b_conv3)
#h_pool3 = max_pool_2x2(h_conv3)
#h_pool3_flat = tf.reshape(h_pool3, [-1, 256])
h_conv3_flat = tf.reshape(h_conv3, [-1, 1600])
h_fc1 = lu(tf.matmul(h_conv3_flat, W_fc1) + b_fc1)
# readout layer
readout = tf.matmul(h_fc1, W_fc2) + b_fc2
return s, readout, h_fc1
7.3 获取智能体输⼊和输出
先观察100000次,把观察数据保存,然后在模型输⼊的时候,把这些数据拿出来作为模型的输⼊
# store the transition in D
D.append((s_t, a_t, r_t, s_t1, terminal))
python新手代码示例
...
s_j_batch = [d[0] for d in minibatch]
a_batch = [d[1] for d in minibatch]
r_batch = [d[2] for d in minibatch]
s_j1_batch = [d[3] for d in minibatch]
y_batch = []
readout_j1_batch = readout.eval(feed_dict = {s : s_j1_batch})
for i in range(0, len(minibatch)):
terminal = minibatch[i][4]
# if terminal, only equals reward
if terminal:
y_batch.append(r_batch[i])
else:
y_batch.append(r_batch[i] + GAMMA * np.max(readout_j1_batch[i]))
7.4 迭代训练
train_step = tf.train.AdamOptimizer(1e-6).minimize(cost)
7.5 智能体玩游戏
# run the selected action and observe next state and reward
x_t1_colored, r_t, terminal = game_state.frame_step(a_t)
8 应⽤领域
可以应⽤到游戏控制、机器⼈⼿臂控制、推荐系统、⾃然语⾔处理上。