用pytorch搭建一个手动计算的神经网络

一元线性回归的预测模型为:
y ^ i = w x i + b \hat{y}_{i}=w x_{i}+b y^i=wxi+b
式中 y ^ i \hat{y}_{i} y^i是预测的结果,希望通过预测值 y ^ i \hat{y}_{i} y^i 来拟合真实值 y i y_{i} yi,所以我们定义了误差函数:
f ( w , b ) = 1 n ∑ i = 1 n ( y ^ i − y i ) 2 f(w,b)=\frac{1}{n} \sum_{i=1}^{n}\left(\hat{y}_{i}-y_{i}\right)^{2} f(w,b)=n1i=1n(y^iyi)2
我们希望预测值 y ^ i \hat{y}_{i} y^i和真实值 y i y_{i} yi 误差最小。接下来我们要考虑的是 w w w b b b取何值时,能够使得误差函数的值最小。高中学过当函数导数为零时,能过取极值(极大值或极小值),我们把 f ( w , b ) f(w,b) f(w,b)分别对 w 、b 求导,求导的结果将为梯度下降时更新时用。
∂ f ( w , b ) ∂ w = 2 n ∑ i = 1 n x i ( w x i + b − y i ) \frac{\partial f(w, b)}{\partial w}=\frac{2}{n} \sum_{i=1}^{n} x_{i}\left(w x_{i}+b-y_{i}\right) wf(w,b)=n2i=1nxi(wxi+byi)

∂ f ( w , b ) ∂ b = 2 n   ∑ i = 1 n x i ( w x i + b − y i ) \frac{\partial f(w, b)}{\partial b}=\frac{2}{n} \ \sum_{i=1}^{n} x_{i}\left(w x_{i}+b-y_{i}\right) bf(w,b)=n2 i=1nxi(wxi+byi)
我们令求导结果为零,就能求解出当前 w 和 b 的值:
∂ f ( w , b ) ∂ w = ∑ i = 1 n y i ( x i − x ˉ ) ∑ i = 1 n x i 2 − 1 n ( ∑ i = 1 n x i ) 2 ∂ f ( w , b ) ∂ b = 1 n ∑ i = 1 n ( y i − w x i ) \begin{aligned} \frac{\partial f(w, b)}{\partial w} &=\frac{\sum_{i=1}^{n} y_{i}\left(x_{i}-\bar{x}\right)}{\sum_{i=1}^{n} x_{i}^{2}-\frac{1}{n}\left(\sum_{i=1}^{n} x_{i}\right)^{2}} \\ \frac{\partial f(w, b)}{\partial b} &=\frac{1}{n} \sum_{i=1}^{n}\left(y_{i}-w x_{i}\right) \end{aligned} wf(w,b)bf(w,b)=i=1nxi2n1(i=1nxi)2i=1nyi(xixˉ)=n1i=1n(yiwxi)
我们再来说梯度下降,我们给 w w w b b b随机初始化一个值,然后通过迭代来更新 w w w b b b,更新公式如下,更新后的结果是 w:和 b:
w : = w − η ∂ f ( w , b ) ∂ w b : = b − η ∂ f ( w , b ) ∂ b \begin{aligned} w &:=w-\eta \frac{\partial f(w, b)}{\partial w} \\ b &:=b-\eta \frac{\partial f(w, b)}{\partial b} \end{aligned} wb:=wηwf(w,b):=bηbf(w,b)
我们结合下图来说明原理。下图横坐标是 w w w,纵坐标是损失函数 f ( w , b ) f(w, b) f(w,b),我们的目的是求损失函数
f ( w , b ) f(w, b) f(w,b)的最小值,在a点时,损失函数并没有到最小值, f ( w , b ) f(w, b) f(w,b) w w w的斜率为负,带到 w : = w − η ∂ f ( w , b ) ∂ w w:=w-\eta \frac{\partial f(w, b)}{\partial w} w:=wηwf(w,b), w值增大,w增大损失函数的就会减小。当在 b 点时,斜率为正,带到 w : = w − η ∂ f ( w , b ) ∂ w w:=w-\eta \frac{\partial f(w, b)}{\partial w} w:=wηwf(w,b)中,w 的值减小,同时损失函数的值也在减小。通过不断的调整 w 和 b 的值就能找到损失函数的最小值。
在这里插入图片描述
我们用jupytor来运行上面的整个过程,大家也像我这样分块运行

导入需要的包

import torch
import numpy as np
from torch.autograd import Variable

读入数据 x 和 y


x_train = np.array([[3], [4], [5.5], [6], [6], [4],
                    [9.779], [6.182], [7.59], [2.167], [7.042],
                    [10.791], [5.3], [7.7], [3.1]], dtype=np.float32)

y_train = np.array([[1.7], [2.7], [2.09], [3.19], [1.64], [1.53],
                    [3.36], [2.5], [2.53], [1.221], [2.27],
                    [3.465], [1], [2.904], [1.3]], dtype=np.float32)

画出图像


import matplotlib.pyplot as plt
%matplotlib inline

plt.plot(x_train, y_train, 'bo')

在这里插入图片描述

转换成 Tensor


x_train = torch.from_numpy(x_train)
y_train = torch.from_numpy(y_train)

# 定义参数 w 和 b
w = Variable(torch.randn(1), requires_grad=True) # 随机初始化
b = Variable(torch.zeros(1), requires_grad=True) # 使用 0 进行初始化

构建线性回归模型


x_train = Variable(x_train)
y_train = Variable(y_train)

def linear_model(x):
    return x * w + b
y_ = linear_model(x_train)

经过上面的步骤我们就定义好了模型,在进行参数更新之前,我们可以先看看模型的输出结果长什么样

plt.plot(x_train.data.numpy(), y_train.data.numpy(), 'bo', label='real')
plt.plot(x_train.data.numpy(), y_.data.numpy(), 'ro', label='estimated')
plt.legend()

在这里插入图片描述

计算误差


def get_loss(y_, y):
    return torch.mean((y_ - y_train) ** 2)

loss = get_loss(y_, y_train)
# 打印一下看看 loss 的大小
print(loss)

自动求导


loss.backward()

查看 w 和 b 的梯度


print(w.grad)
print(b.grad)
# 更新一次参数
w.data = w.data - 1e-2 * w.grad.data
b.data = b.data - 1e-2 * b.grad.data

更新完成参数之后,我们再一次看看模型输出的结果

y_ = linear_model(x_train)
plt.plot(x_train.data.numpy(), y_train.data.numpy(), 'bo', label='real')
plt.plot(x_train.data.numpy(), y_.data.numpy(), 'ro', label='estimated')
plt.legend()

在这里插入图片描述

从上面的例子可以看到,更新之后红色的线跑到了蓝色的线下面,没有特别好的拟合蓝色的真实值,所以我们需要在进行几次更新

for e in range(10): # 进行 10 次更新
    y_ = linear_model(x_train)
    loss = get_loss(y_, y_train)
    
    w.grad.zero_() # 记得归零梯度
    b.grad.zero_() # 记得归零梯度
    loss.backward()
    
    w.data = w.data - 1e-2 * w.grad.data # 更新 w
    b.data = b.data - 1e-2 * b.grad.data # 更新 b 
    print('epoch: {}, loss: {}'.format(e, loss.item()))
y_ = linear_model(x_train)
plt.plot(x_train.data.numpy(), y_train.data.numpy(), 'bo', label='real')
plt.plot(x_train.data.numpy(), y_.data.numpy(), 'ro', label='estimated')
plt.legend()

在这里插入图片描述

经过 10 次更新,我们发现红色的预测结果已经比较好的拟合了蓝色的真实值。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值