pytorch神经网络算法

正向传播算法

设函数的输入数据为 x x x,参数为 w w w ,输出为 l o s s loss loss
正向传播过程如下:
y ^ = x ∗ w \hat{y} = x*w y^=xw
s = y − y ^ s = y-\hat{y} s=yy^
l o s s = s 2 loss = s^2 loss=s2

import torch


def forward(x, y, w):
    # 其中 x,y 为输入数据,w为该函数所需要的参数
    y_predicted = w * x
    loss = (y_predicted - y)**2
    return loss


# 测试代码
x = torch.tensor(1.0)
y = torch.tensor(2.0)
w = torch.tensor(1.0, requires_grad=True)
forward(x, y, w)  # (2-1)²=1

# 输出结果
# tensor(1., grad_fn=<PowBackward0>)

反向传播算法

反向传播就是正向传播的反向计算。其实反向传播的目的就是计算输出值和参数之间的梯度关系。
利用反向传播求取函数关于权重的偏导(即梯度),然后根据偏导使用梯度下降算法找到最佳的参数。这个过程其实就是深度学习中模型训练的过程。
利用 loss.backward() 进行后向传播,求取所要可偏导变量的偏导值:

x = torch.tensor(1.0)
y = torch.tensor(2.0)
# 将需要求取的 w 设置为可偏导
w = torch.tensor(1.0, requires_grad=True)
loss = forward(x, y, w)  # 计算损失
loss.backward()  # 反向传播,计算梯度
print("此时,loss 关于 w 的偏导为:", w.grad)
w.grad.zero_()  # 得到偏导后,清空梯度

# 输出结果
# 此时,loss 关于 w 的偏导为: tensor(-2.)
# tensor(0.)

梯度下降算法

假设 w 为损失函数需要求的变量,那么梯度下降算法的具体步骤如下:

  1. 随机初始化一个 w 的值。
  2. 在该 w 下进行正向传播,得到所有 x 的预测值 y_pre。
  3. 通过实际的值 y 和预测值 y_pre 计算损失。
  4. 通过损失计算梯度 dw。
  5. 更新 w : w = w − l r ⋅ d w w:w = w-lr\cdot dw ww=wlrdw,其中 l r lr lr 为步长,可自定义具体的值。
  6. 重复步骤 2 − 5 2-5 25,直到损失降到较小位置。

人工实现

import numpy as np

# 所有点的预测值和实际值的距离的平方和,再取平均值(这种距离叫做欧氏距离)。
def loss(y, y_pred):
    return ((y_pred - y)**2).mean()
#返回dJ/dw
def gradient(x, y, w):
    return np.mean(2*w*x*x-2*x*y)

定义数据集和变量值:

# 正向传播,计算预测值
def forward(x):
    return w * x
# 定义数据集合和 w 的初始化
X = np.array([1, 2, 3, 4], dtype=np.float32)
Y = np.array([2, 4, 6, 8], dtype=np.float32)
w = 0.0
# 定义步长和迭代次数
learning_rate = 0.01
n_iters = 20

利用梯度下降算法求解一元回归函数中的 w 的值:

for epoch in range(n_iters):
    y_pred = forward(X)
    #计算损失
    l = loss(Y, y_pred)
    #计算梯度
    dw = gradient(X, Y, w)
    #更新权重 w
    w -= learning_rate * dw

    if epoch % 2 == 0:
        print(f'epoch {epoch+1}: w = {w:.3f}, loss = {l:.8f}')
     
print(f'根据训练模型预测,当 x =5 时,y 的值为: {forward(5):.3f}')
epoch 1: w = 0.300, loss = 30.00000000
epoch 3: w = 0.772, loss = 15.66018677
epoch 5: w = 1.113, loss = 8.17471600
epoch 7: w = 1.359, loss = 4.26725292
epoch 9: w = 1.537, loss = 2.22753215
epoch 11: w = 1.665, loss = 1.16278565
epoch 13: w = 1.758, loss = 0.60698175
epoch 15: w = 1.825, loss = 0.31684822
epoch 17: w = 1.874, loss = 0.16539653
epoch 19: w = 1.909, loss = 0.08633806
根据训练模型预测,当 x =5 时,y 的值为: 9.612

pytorch实现

模型的函数表达式非常复杂非常复杂时,手动定义该函数的梯度函数就变得非常困难了。因此,这里使用后向传播函数来实现梯度下降算法,求解最佳权重 w。
定义数据集合以及 w 的初始值,并将其设置为可以求偏导的张量:

import torch
X = torch.tensor([1, 2, 3, 4], dtype=torch.float32)
Y = torch.tensor([2, 4, 6, 8], dtype=torch.float32)
#初始化张量 w
w = torch.tensor(0.0, dtype=torch.float32, requires_grad=True)
# 定义步长和迭代次数
learning_rate = 0.01
n_iters = 20

接下来让我们使用 .backward() 直接求解梯度:

 for epoch in range(n_iters):
    y_pred = forward(X)
    l = loss(Y, y_pred)
    # 无需定义梯度求解的函数,直接求解梯度
    l.backward()
    # 利用梯度下降更新参数
    with torch.no_grad():
        # w.grad :返回 w 的梯度
        w.data -= learning_rate * w.grad
    
    # 清空梯度
    w.grad.zero_()

    if epoch % 2 == 0:
        print(f'epoch {epoch+1}: w = {w.item():.3f}, loss = {l.item():.8f}')
print(f'根据训练模型预测,当 x =5 时,y 的值为: {forward(5):.3f}')
epoch 1: w = 0.300, loss = 30.00000000
epoch 3: w = 0.772, loss = 15.66018772
epoch 5: w = 1.113, loss = 8.17471695
epoch 7: w = 1.359, loss = 4.26725292
epoch 9: w = 1.537, loss = 2.22753215
epoch 11: w = 1.665, loss = 1.16278565
epoch 13: w = 1.758, loss = 0.60698116
epoch 15: w = 1.825, loss = 0.31684780
epoch 17: w = 1.874, loss = 0.16539653
epoch 19: w = 1.909, loss = 0.08633806
根据训练模型预测,当 x =5 时,y 的值为: 9.612

可以看到,利用 PyTorch 进行的梯度下降的结果和人工梯度下降结果一致。我们可以通过 PyTorch 中的 .backward(),简洁明了的求取任何复杂函数的梯度,大大的节约了我们公式推导的时间。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凡心curry

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值