实践 pytorch.nn.linear 线性回归

nn.Linear 定义:https://pytorch.org/docs/stable/generated/torch.nn.Linear.html#torch.nn.Linear

class torch.nn.Linear(in_features: int, out_features: int, bias: bool = True)

其中:

  • in_features – 每次输入的样本数,默认是1
  • out_features – 每次输出的样本数,默认也是1
  • bias – If set to False, the layer will not learn an additive bias. Default: True

pytorch 本身是没有神经网络层的概念的,所以如果我们要定义一个神经网络,需要通过 torch.nn.Module 来实现

假设我们有很多样本数据,符合模型 y = wx + c,我们也可以用 torch 来直接生成一些随即样本数据

x = torch.unsqueeze(torch.linspace(0, 1, 300),dim=1)
y = 2 * x + torch.rand(x.size())

可以得到:

现在,我们要基于这些样本数据,反推模型 y = wx + c 中的参数 w 和 c,怎么用 torch.nn.Linear 来实现呢?

对于神经网络的典型处理如下所示:

  1. 定义网络结构,并构造前向网络
  2. 定义优化算法
  3. 定义损失函数 loss function
  4. 循环迭代,直到求解最优解

1)定义网络结构,并构造前向网络

神经网络的定义主要是层的定义,以及如何构造(前向 forward 函数)

下面这是一个单层的神经网络模型

class LinearRegression(torch.nn.Module):
    """
    Linear Regressoin Module, the input features and output 
    features are defaults both 1
    """
    def __init__(self):
        super().__init__()
        self.linear = torch.nn.Linear(1, 1)

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

net = LinearRegression()

也可以定义多层的,对于求解简单线性回归问题,单层网络足够了

class LinearRegression(torch.nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.hidden = torch.nn.Linear(1, 10)   # hidden layer
        self.linear = torch.nn.Linear(10, 1)   # output layer

    def forward(self, x):
        x = F.relu(self.hidden(x))     # activation function for hidden layer
        y = self.linear(x)             # linear output
        return y

net = LinearRegression()

2)定义优化算法

深度神经网络的优化算法有很多,比如 SGD,Adam,Adagrad 等等。但是最常用的应该还是 SGD 随即梯度下降,Stochastic Gradient Descent,pytorch 有现成的 SGD 算法可以用

class torch.optim.SGD(params, lr=<required parameter>, momentum=0, dampening=0, weight_decay=0, nesterov=False)

其中:

  • params (iterable) – 待优化的参数列表
  • lr (float) – 学习速率
  • momentum (float, optional) – momentum factor (default: 0)
  • weight_decay (float, optional) – weight decay (L2 penalty) (default: 0)
  • dampening (float, optional) – dampening for momentum (default: 0)
  • nesterov (bool, optional) – enables Nesterov momentum (default: False)

大多时候只会用到前面两个参数:

optimizer = torch.optim.SGD(net.parameters(), lr=0.001)

另外学习速率这个参数需要注意一下,学习速率太快,可能会导致模型无法收敛,学习速度太慢,性能会很差。其实可以动态的设置学习速率,随着收敛程度越大,逐渐降低学习速率

3)定义损失函数 loss function

损失函数的是整个优化过程的目标,当误差优化到一定程度之内,学习过程就可以结束了。最常见的损失函数就是 MSE – 均方误差

class torch.nn.MSELoss(size_average=None, reduce=None, reduction: str = ‘mean’)

看了一下官方文档:https://pytorch.org/docs/stable/generated/torch.nn.MSELoss.html#torch.nn.MSELoss

size_averagereduce 都是废弃参数了,之看 reduction 即可

reduction (string, optional) – Specifies the reduction to apply to the output: 'none' | 'mean' | 'sum'. 'none': no reduction will be applied, 'mean': the sum of the output will be divided by the number of elements in the output, 'sum': the output will be summed. Note: size_average and reduce are in the process of being deprecated, and in the meantime, specifying either of those two args will override reduction. Default: 'mean'

loss_function = torch.nn.MSELoss()

4)循环迭代,求最优解

整个迭代的过程非常简单:

  1. 处理数据集
  2. 计算 loss
  3. 反向传播求梯度
  4. 根据梯度改变参数值
for epoch in range(1000):
    prediction = net(x)
    loss = loss_function(prediction, y)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

反向传播的过程只需要调用loss.backgrad()函数即可。但是由于变量的梯度是累加的,所以在求backward之前应该先对现有的梯度清零

如果把求解过程可视化的话,最终看起来是这个样子的

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注