【深度学习】移动坐标点(动量法)

走出第一步

有了大小和方向,接下来我们就可以开始走出我们的第一步了。来看权重的迭代公式:
\omega_{(t+1)}=\omega_{(t)}-\eta{\frac{\partial L(\omega)}{\partial \omega}}

现在我们的偏导数部分已经计算出来了,就是我们使用backward求解出的结果。而\eta学习率,或者步长,是我们在迭代开始之前就人为设置好的,一般是0.01-0.5之间的某个小数。因此现在我们已经可以无障碍地使用代码实现权重的迭代了

先定义模型并进行反向传播:

import torch
from torch.nn import functional as F
import torch.nn as nn

#随机生成数据
torch.manual_seed(212)
X=torch.rand((500,20),dtype=torch.float32)*100
y=torch.randint(low=0,high=3
                ,size=(500,) #交叉熵损失函数要求y是一维的
                ,dtype=torch.float32) #交叉熵损失函数要求y是int64类型,调用时再转int

#定义输入及输出的特征量
input_=X.shape[1]
output_=len(y.unique())

#定义神经网络架构
#3分类,500个样本,20个特征,共3层,第一层13个神经元,第二层8个神经元
#第一层激活函数ReLU,第二层sigmoid
class Model(nn.Module):
    def __init__(self,in_features=40,out_features=2):
        super().__init__()
        self.linear1=nn.Linear(in_features,13,bias=False)
        self.linear2=nn.Linear(13,8,bias=False)
        self.output=nn.Linear(8,out_features,bias=True)
    
    def forward(self,x):
        sigma1=torch.relu(self.linear1(x))
        sigma2=torch.sigmoid(self.linear2(sigma1))
        zhat=self.output(sigma2)
        return zhat
net=Model(in_features=input_,out_features=output_)
zhat=net.forward(X)

#定义损失函数,使用交叉熵CrossEntropyLoss
criterion=nn.CrossEntropyLoss()

loss=criterion(zhat,y.long()) #要求y是int64类型
loss.backward()

net.linear1.weight.grad #查看梯度值

走出第一步的代码

#w(t+1)=w(t)-步长*grad
lr=0.1 #定义学习率
w=net.linear1.weight.data

dw=net.linear1.weight.grad
w-=lr*dw

w #查看w变化

从第一步到第二步:动量法Momentum

在反向传播优化算法中,动量法(Momentum)是一种常用的梯度下降优化算法的改进版。它的目标是加速梯度下降的收敛过程,并借鉴前面走过的方向,利用历史梯度方向中的信息。

我们让上一步的梯度向量(的反方向) 与现在这一点的梯度向量 (的反方向)以加权的方式求和,求解出受到上一步大小和方向影响的真实下降方向,再让坐标点向真实下降方向移动。在坐标轴上,可以表示为:

 其中,对上一步的梯度向量加上的权重被称为动量参数(也叫做衰减力度,通常使用进行表示),对这一点的梯度向量加上的权重就是步长(依然表示为\eta),真实移动的向量为v,被称为“动量”(Momentum)。将上述过程使用公式表示,则有:

v_{(t)}=\gamma v_{(t-1)}-\eta \frac{L}{\partial \omega}\\ \omega_{(t+1)}=\omega_{(t)}+v_{(t)}

在第一步中,没有历史梯度方向,因此第一步的真实方向就是起始点梯度的反方向,v_0=0。其中v_{(t-1)}代表了之前所有步骤所累积的动量和(其实也就代表着上一步的真真实方向)。在这种情况下,梯度下降的方向有了“惯性”,受到历史累计动量的影响,当新坐标点的梯度反方向与历史累计动量的方向一致时,历史累计动量会加大实际方向的步子,相反,当新坐标点的梯度反方向与历史累计动量的方向不一致时,历史累计动量会减小实际方向的步子。

在Pytorch中手工实现动量法:

#v(t)=gamma*v(t-1)-lr*dw
#w(t+1)=w(t)+v(t)
lr=0.1 #定义学习率
gamma=0.9

w=net.linear1.weight.data
dw=net.linear1.weight.grad
dw.shape #查看dw的形状

# 需要定义一个v0
v=torch.zeros(dw.shape[0],dw.shape[1])
v=gamma*v-lr*dw
w+=v
w

torch.optim实现带动量的梯度下降

步骤:

  1. 向前传播
  2. 本轮向前传播的损失函数值
  3. 反向传播-得到梯度
  4. 更新权重和动量
  5. 清空梯度-清除原来计算出来的,基于上一个点的坐标计算的梯度 
import torch
from torch.nn import functional as F
import torch.nn as nn
import torch.optim as optim

#随机生成数据
torch.manual_seed(212)
X=torch.rand((500,20),dtype=torch.float32)*100
y=torch.randint(low=0,high=3
                ,size=(500,) #交叉熵损失函数要求y是一维的
                ,dtype=torch.float32) #交叉熵损失函数要求y是int64类型,调用时再转int

#定义输入及输出的特征量
input_=X.shape[1]
output_=len(y.unique())

#定义神经网络架构
#3分类,500个样本,20个特征,共3层,第一层13个神经元,第二层8个神经元
#第一层激活函数ReLU,第二层sigmoid
class Model(nn.Module):
    def __init__(self,in_features=40,out_features=2):
        super().__init__()
        self.linear1=nn.Linear(in_features,13,bias=False)
        self.linear2=nn.Linear(13,8,bias=False)
        self.output=nn.Linear(8,out_features,bias=True)
    
    def forward(self,x):
        sigma1=torch.relu(self.linear1(x))
        sigma2=torch.sigmoid(self.linear2(sigma1))
        zhat=self.output(sigma2)
        return zhat
net=Model(in_features=input_,out_features=output_)

#定义损失函数,使用交叉熵CrossEntropyLoss
criterion=nn.CrossEntropyLoss()

然后定义优化算法

#定义优化算法
lr=0.1 #定义学习率
gamma=0.9

opt=optim.SGD(net.parameters()#需要进行迭代的权重
              ,lr=lr
              ,momentum=gamma)

以下这段每运行一次就可迭代更新一次权重,loss.item()的值会慢慢变小

zhat=net.forward(X)

loss=criterion(zhat,y.long()) #要求y是int64类型
loss.backward()

opt.step() #走一步
opt.zero_grad()

#print(net.linear1.weight.data) #查看权重值
print(loss.item()) #查看损失值

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值