您的位置:首页 > 其它

【增强学习】Torch中的增强学习层

2016-06-17 13:31 302 查看
要想在Torch框架下解决计算机视觉中的增强学习问题(例如Visual Attention),可以使用Nicholas Leonard提供的dpnn包。这个包对Torch中原有nn包进行了强大的扩展,在Torch官方的教程中予以推荐。

增强学习是一个非常广阔的领域,本文只从理解代码的角度进行最简单说明。

理念

机器学习可以分为三支:

- 无监督学习(unsupervised):没有教师信号。例:给定一系列图片,学习网络参数,能够按照训练集的概率,生成新的图片。聚类也是一种无监督学习。

- 监督学习(supervised):有教师信号,教导正确的动作。例:手把手教你下棋:这种局面下这儿,那种局面下那儿。常见的图像识别问题也是监督学习。

- 增强学习(reinforce):有教师信号,但不知道正确的动作是什么,只给出动作的反馈。例:其实我也太不会下棋,但是你下完我知道数子儿判断输赢。

对于同一个问题,可以用不同的观点来看待。以手写数字识别任务为例:

监督学习观点下,把分类结果看成动作,教师给出的是标定的分类结果。

增强学习观点下,把每次观察位置看成动作1,教师给出的反馈是分类正确与否。

监督学习

作为复习,先来看看监督学习网络的结构:



网络输入为x,输出为y。输出由网络参数θ控制:

y=f(x;θ)

训练时,需要在后面接一个准则(Criterion)模块充当教师,给出一个代价函数E。

准则模块是解析的,可以求出代价对输出的导数

gradOut=∂E∂y

根据链式法则,进一步可以求出代价对输入的导数:

gradIn=gradOut⋅∂y∂x=∂E∂x

网络模块可以串接:

gradInn+1=gradInn⋅∂yn∂xn

训练时,网络参数更新:

−Δθn=∂E∂θn=gradInn+1⋅∂yn∂θn

最关键的部分是:求出每一层的gradIn,之后传递给前一层。

增强学习

增强学习网络具有如下结构:



乍一看差不多,但有两处不同

第一,增强学习的层是统计的(stochastic),而不是确定的。也就是说,y是个随机变量,服从围绕x的某种分布。

y∼f(x,y;θ)

举例:f(x,y;θ)=N(y;θTx,σ),σ为预设参数。

物理意义

在训练时,随机采样层围绕着现有策略,生成一些探索策略。在测试时,可以把这一层变成确定的。

训练时,需要在后面接一个反馈(Reward)模块充当教师,反馈是规则式的,对于输入往往不可导,这是第二点不同。所以增强学习中没有gradOutput这项。

反馈对输入的导数如下求解:

gradIn=∂R∂x=R⋅∂lnf(x,y;θ)∂x

物理意义

∂lnf/∂x - 找到概率相对于输入的变化方向。x沿着这个方向变化,则生成当前动作y的概率增大得最快。

R - 用反馈来给上述变化加权。反馈为正,说明动作y选择得当,则x正向变化,提升输出y的概率;反馈为负,x向反方向变化,修改当前策略。

在实现时,为了更清晰简洁,把增强学习层中的参数部分抽出来,变成一个监督学习层:

x¯=θTx

y∼N(y;x¯,σ)

即:增强学习层本身不包含参数,在测试时正向生成采样,在训练时反向生成gradInput。

Variance Reduction

对上式中的加权做修改:

gradIn=∂R∂x=(R−b)⋅∂lnf(x,y)∂x

其中b称为baseline,用来降低上式的绝对值,称为variance reduction,简称VR。

b是一个随着训练而变化的参数,设定为反馈的期望:b=E[R]。

举例:分类正确R=1,分类错误R=0。当前网络能正确分类20%样本,则b=0.2。加权范围从[0,1]变成[−0.2,0.8]。

物理意义

VR实际上对反馈进行了归一化:比“当前策略”好的策略,才值得表彰,给予正反馈。

混合网络

实际应用中的网络,往往混合了监督学习层(Sup)和增强学习层(Rei)。



训练时,反馈直接传播给增强学习层(红线)。增强学习层之后的梯度(gradInput3, gradOutput)都是0。



为了避免后续模块没法优化,实际中往往还需要一个监督学习中可导的Criterion模块(绿线)。



Criterion模块带来的梯度传播到增强学习模块就停止了。换句话说:增强学习层出口处的gradOut是被忽略的

实验

构造网络

我们在Torch中构造一个简单的网络来研究增强学习层。这个网络参数已经设定好了,没有任何实际意义。

require 'dpnn'

-- ------ CREATE NET --------
net = nn.Sequential()
-- [1]: fully connect
layer_fc1 = nn.Linear(3,2)
weight = torch.DoubleTensor(2,3)
for h=1,2 do
for w=1,3 do
weight[h][w] = (h-1)*3+w
end
end
layer_fc1.weight = weight
layer_fc1.bias:fill(0)
net:add(layer_fc1)

-- [2]: reinforce
net:add(nn.ReinforceNormal(0.2,false))    -- 0.2: gaussian sampling variance; false: do not sample when testing

-- [3]: fully connect
layer_fc3 = nn.Linear(2,2)
layer_fc3.weight[1][1] = 1
layer_fc3.weight[1][2] = 0
layer_fc3.weight[2][1] = 0
layer_fc3.weight[2][2] = 1
layer_fc3.bias:fill(0)
net:add(layer_fc3)


网络结构是这样:



可以用如下语句查看网络结构:

for i=1,#net do
print(net:get(i))
end


前向传播

构造一个输入:[1,1,1],送入网络:

x = torch.Tensor(3):fill(1)       -- don't make Tensor(1,3): ReinforceNormal will give trouble
y = net:forward(x)
print(x)
for i=1,3 do
print(net:get(i).output)
end


如果不考虑增强学习层的高斯采样,网络应该输出[6,15],加上随机采样之后,输出围绕这个值波动。

接上增强学习模块

如果网络中包含ReinforceXXX层,必须使用带有反馈的教师模块。我们把网络输出y看做针对两类的打分,使用VRClassReward模块。

eval = nn.VRClassReward(net)


注意:创建增强学习评估时,必须指明连接的网络,因为要将反馈广播给网络中的所有增强学习层。

VRClassReward的输入为各类得分,如果最高得分类和标定相同,则反馈+1,否则反馈-1。除了y,VRClassReward还需要两个数据:一个标量baseline,一个标量ground_truth指出正确的类标。

baseline = torch.Tensor(1):fill(0.5)
ground_truth = torch.Tensor(1):fill(2)


评估层输入包含分类得分y和baseline,用前向传播获得损失。由于y[2]>y[1],分类为2结果正确,获得的reward是1,loss为-1:

loss = eval:forward({y,baseline},ground_truth)  --loss = -reward


eval模块后向传播获得gradOut

gradient_eval = eval:backward({y,baseline}, ground_truth)


gradient_eval是个长度为2的sequence。gradient_eval[1]为针对输出y的梯度,gradient_eval[2]为baseline的期望。

我们暂时不更新baseline,只更新网络参数,可以得到出口处的梯度:

gradient_net = net:backward(x, gradient_eval[1])


经过反向传播之后,可以看到反馈R−b被存储在增强学习层中reward变量中。

print(net:get(2).reward)


更多信息,可以参看ReinforceNormal.lua中的updateOutput和updateGradInput函数。

接上监督学习模块

如果只使用一个监督学习层作为教师模块,ReinforceNormal层的reward没有赋值,无法执行反向传播。

使用ParallelCriterion层,把增强学习和监督学习的评估函数联合起来。

eval_reward = nn.VRClassReward(net)
eval_criterion = nn.MSECriterion()   --mean square error
eval = nn.ParallelCriterion():add(eval_reward):add(eval_criterion)


监督学习的真值和输出y尺寸相同。两个真值组合成gt:

gt_reward = torch.Tensor(1):fill(2)
gt_criterion = torch.Tensor(2)
gt_criterion[1] = 9
gt_criterion[2] = 10
gt = {gt_reward, gt_criterion}


执行前向传播时,分别设定给增强学习和监督学习的输入:

baseline = torch.Tensor(1):fill(0.5)
input = {{y,baseline},y}    -- two input
loss = eval:forward(input,gt)


反向传播的结果和输入结构类似

gradient_eval = eval:backward(input, gt)


gradient_eval结构

th> {
..>   1 :
..>     {
..>       1 : DoubleTensor - size: 2
..>       2 : DoubleTensor - size: 1
..>     }
..>   2 : DoubleTensor - size: 2
..> }
..>


和网络输出y相关的是gradient_eval[1][1]和gradient_eval[2],两者相加,作为gradOut:

gradient_eval_hybrid =gradient_eval[1][1] + gradient_eval[2]
gradient_net = net:backward(x, gradient_eval_hybrid)


这里使用了visual attention的概念。不是一次看整张图进行判断。而是每次看一小部分,边看边移动,多次观察进行判断。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息