梯度弥散和梯度爆炸
rnn在向w求梯度的过程中,有一项Whh的k次方。这一项会出现问题。Whh>1会趋向无穷,梯度非常非常大(梯度爆炸)。Whh<1会趋向0,梯度非常非常小(梯度弥散)。到一定的值时梯度剧烈变化。
梯度爆炸的解决办法
设定阈值,当梯度大于某个数的时候,所取得梯度就不是梯度,取得是(梯度/它的模长)*k。这样就可以把梯度限制在k大小的范围内不至于无穷大且方向不变。
#只需要在backward生成了梯度信息之后 #循环所有参数p然后将p中的grad参数限制在10以内,方向不变 loss=criteon(output,y) model.zero_grad() loss.backward() for p in model.parameters(): print(p.grad.norm()) torch.nn.utils.clip_grad_norm_(p,10) optimizer.step()
解决梯度弥散的方法下一节的lstm
lstm
长短记忆神经网络——通常称作LSTM,是一种特殊的RNN,能够学习长的依赖关系。
rnn的记忆长度非常的短,原始的rnn
lstm加入了三道门,hi记忆块过来的时候要经过一道sigmoid,上一级输出过来的时候也要经过一道sigmoid,他们两个结合起来也要经过一道sigmoid。
记忆块经过遗忘门后的信息
过滤后的新信息
以上两者结合的到新的记忆块
输出时也加入sigmoid,输出时也是用ct记忆块
一层
import numpy as np import torch from torch import nn cell=nn.LSTMCell(input_size=40,hidden_size=20) inputx=torch.randn(2,3,40) #两条曲线,3个时刻,每个时刻上的值用40维的向量表示 h=torch.zeros(3,20) #h和c的格式都是(时刻数,隐藏层数) c=torch.zeros(3,20) for i in inputx: #循环inputx,每次取出来(3,40) h,c=cell(i,[h,c]) #循环过程中会使用到h和c,弄出新的h和c print(h.shape,c.shape)
双层
import numpy as np import torch from torch import nn cell1=nn.LSTMCell(input_size=40,hidden_size=20) cell2=nn.LSTMCell(input_size=20,hidden_size=10) inputx=torch.randn(2,3,40) #两条曲线,3个时刻,每个时刻上的值用40维的向量表示 h1=torch.zeros(3,20) #h和c的格式都是(时刻数,隐藏层数) c1=torch.zeros(3,20) h2=torch.zeros(3,10) #h和c的格式都是(时刻数,隐藏层数) c2=torch.zeros(3,10) for i in inputx: #循环inputx,每次取出来(3,40) h1,c1=cell1(i,[h1,c1]) #循环过程中会使用到h和c,弄出新的h和c h2, c2 = cell2(h1, [h2, c2]) # 循环过程中会使用到h和c,弄出新的h和c print(h1.shape,c1.shape) print(h2.shape,c2.shape)
GAN
输入数据,在生成器的作用下生成伪数据,训练集里的是真实的数据。鉴别器可以鉴别出给出判断伪数据和真实数据中哪一个是真实的。在不断训练的过程中,生成器的效能应该是不断变好的,最终需要达到鉴别器很难鉴别出它与真实数据之间的差距。
判别模型的目标函数是:
其中D(x)是判别模型的输出结果,是一个0-1范围内的实数值,用来判断图片是真实图片的概率,其中Pr和Pg分别代表真实图像的分布与生成图像的数据分布情况,目标函数是找到使得两个式子之和最大
这一整个式子需要尽可能地大
是指使得真实数据放入到判别模型D(x)输出的计算值和整个式子值尽可能大
是指使得造假数据放入到判别模型D(x)输出的计算值尽可能小和整个式子值尽可能大,这样整合下来就是使得目标函数尽可能大,因此在训练时就可以根据目标函数进行梯度提升。
生成模型的目标是让判别模型无法区分真实图片和生成图片,其目标函数是:
要使得目标函数尽量小
GAN训练问题
Pr和Pg分别代表真实图像的分布与生成图像的数据分布情况,一开始如果Pr和Pg没有重合部分,梯度为0梯度就无法更新
解决没有重合部分的方法,引入em距离
通过把较远的数据搬移到近的地方,要找出代价最小的方法,代价就是一次搬多少而且搬移的距离是多大
WGAN为了解决梯度为0的情况,将从Pr真实图像的分布上的点x1和Pg生成图像的数据分布上的点x2的中间进行线性抽样出一定量的点(比如从28*28上的点x1(0.6)和28*28上的点x2(0.4)之间抽样产生出一个新的点0.5),然后对这一定量的点求导数再累求和,加到loss当中去