PyTorch 一元线性回归

PyTorch 一元线性回归,本文介绍一元回归模型的基本原理,然后介绍通过 PyTorch 解决一个简单的一元回归问题,得到一条直线去尽可能逼近这些离散的点。

一元线性回归

给定数据集 D = {(x_1,y_1),(x_2,y_2),(x_3,y_3),…,(x_m,y_m)},线性回归希望能够优化一个好的函数 f(x),使得f(x_i)=wx_i + b,能够与y_i 尽可能接近。

如何才能学习到参数w 和 b呢? 很简单,只需要确定如何衡量 f(x) 与 y 之间的差别,可以用它们之间的距离差异 Loss = \sum_{i=1}^m{(f(x_i)- y_i)^2}来衡量误差,取平方是因为距离有正由负,我们希望能够将它们全部变成正的。这就是著名的均方误差,要做的事情就是希望能够找到 w^*b^*,使得:
PyTorch 一元线性回归

均方误差非常直观,也有着很好的几何意义,对应了常用的欧几里得距离,基于均方误差最小化来进行模型求解的办法也称为“最小二乘法”。

求解办法其实非常简单,如果求这个连续函数的最小值,那么只需要求它的偏导数,让它的偏导数等于 0 来估计它的参数,即:
PyTorch 一元线性回归

通过上面的求解式,我们可以得到 w 和 b 的最优解:
PyTorch 一元线性回归
其中 \frac{1}{m}\sum_{i=1}^m{x_i} 及为x 的均值。

一元线性回归的实现

下面用 PyTorch 来求解一下一元线性回归问题,首先给出一些点:

x_train = np.array([[3.3],[4.4],[5.5],[6.71],[6.93],[4.168],[9.779],[6.182],[7.59],[2.167],[7.042],
                    [10.791],[5.313],[7.997],[3.1]], dtype=np.float32)
y_train = np.array([[1.7],[2.76],[2.09],[3.19],[1.694],[1.573],[3.366],[2.596],[2.53],[1.221],
                    [2.827],[3.465],[1.65],[2.904],[1.3]], dtype=np.float32)

我么要做的事情就是找一条直线去逼近这些点,也就是希望这条直线离这些点的距离之和最小,

  • 先将numpy.array转换称 Tsensor,因为 PyTorch里面的处理单元是 Tensor。
  • 接着需要建立模型,这里定义一个简单的模型 y = wx + b, 输入参数是一维,输出参数也是一维,这就是一条直线,让然这里可以根据你想要的输入维度进行更改,我们希望去优化参数w 和b 能够使得这条直线尽可能接近这些点,如果支持 GPU 加速,可以通过 model.cuda() 将模型放到 GPU 上。
  • 然后定义损失函数和优化函数,这里使用均方误差作为优化函数,使用梯度下降进行优化。
  • 最后定义好我们要跑的epoch个数,将数据变成 Variable 放入计算图,然后通过 out=model(input) 得到网络前向传播得到的结果,通过loss=criterion(out, target)得到 损失函数,然后归零梯度,做后向传播和更新参数,特别注意的是,每次做反向传播之前都要归零梯度,optimizer.zero_grad(),不然梯度会累加在一起,造成结果不能收敛。
  • 做完训练后可以预测一下结果,首先需要通过model.eval()将模型变成测试模型,这是因为有一些层操作,比如DropoutBatchNormalization在训练和测试的时候不一样的,所以我们需要通过这样一个操作来转换这些不一样的层操作。然后将测试数据放入网络前向传播得到结果。
import torch
from torch.autograd import Variable
import matplotlib.pyplot as plt
import numpy as np
import torch.nn as nn
import torch.optim as optim

x_train = np.array([[3.3],[4.4],[5.5],[6.71],[6.93],[4.168],[9.779],[6.182],[7.59],[2.167],[7.042],
                    [10.791],[5.313],[7.997],[3.1]], dtype=np.float32)
y_train = np.array([[1.7],[2.76],[2.09],[3.19],[1.694],[1.573],[3.366],[2.596],[2.53],[1.221],
                    [2.827],[3.465],[1.65],[2.904],[1.3]], dtype=np.float32)

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

class LinearRegression(nn.Module):
    def __init__(self):
        super(LinearRegression, self).__init__()
        self.linear = nn.Linear(1, 1)

    def forward(self, x):
        out = self.linear(x)
        return out

model = LinearRegression()

criterion = nn.MSELoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)

num_epochs = 1000
for epoch in range(num_epochs):
    inputs = Variable(x_train)
    target = Variable(y_train)

    # forward
    out = model(inputs)
    loss = criterion(out, target)
    # backward
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

    if (epoch+1) % 20 == 0:
        print('Epoch[{}/{}],loss:{:.6f}'.format(epoch+1, num_epochs, loss.item()))

if __name__ == '__main__':
    model.eval()
    predict = model(Variable(x_train))
    predict = predict.data.numpy()
    plt.plot(x_train.numpy(), y_train.numpy(), 'ro', label='Original data')
    plt.plot(x_train.numpy(), predict, label='Fitting Line')
    plt.show()

输出结果如下:
PyTorch 一元线性回归
这样我们就通过 PyTorch 解决了一个简单的一元回归问题,得到了一条直线去尽可能逼近这些离散的点。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程