入门Pytorch(一)——搭建第一个神经网络

第一步:安装Pytorch

个人电脑在pip上下载Pytorch报错,所以使用Anaconda下载,在此再也不赘述。html

第二步:准备数据、构建框架

首先咱们约定尝试搭建两层神经网络,数据量$N=64$,输入层、隐藏层、输出层的维度分别是:$d_{in}=1000,H=100,d_{out}=10$python

由于是一个Demo,因此尝试直接使用一些随机数据进行测试:网络

#  64个数据,1000-dim,,中间层100-dim,输出10-dim
x = torch.randn(N, d_in, requires_grad=True)
y = torch.randn(N, d_out, requires_grad=True)

注意在这个时候须要写出requires_grad=True,方便后续使用.grad属性直接计算梯度。app

接下来就是要定义一个模型,这个模型咱们是打算使用两层的神经网络,首先在官方的Doc中是这样定义torch.nn.module的用法的:框架

Base class for all neural network modules.ide

Your models should also subclass this class.函数

查阅Doc,主要有几个点是应该会用到的:学习

  • torch.nn.module应当是全部神经网络的基类,而且你要是写一个神经网络也应该继承自此。
  • 若是要应用这个模型到GPU,还可使用.cuda()函数。

对于其中的__init__,就是勾勒出整个模型的框架,咱们首先须要把基类的构造函数进行调用,而后把本模型所须要的函数进行定义,由于咱们想要作两层的神经网络,因此分别声明两层线性的函数。测试

对于其中的forward,是全部的子类都必须得进行override,表明了前向传播的逐层映射关系。激活函数咱们约定使用ReLu也就是.clamp(min=0)优化

因此咱们能够写成下面这个样子:

class TwoLayerNet(torch.nn.module):
    #  定义了init和forward就想到于给定了一个模型
    #  init至关于给了这个框架
    def __init__(self, d_in, H, d_out):
        super(TwoLayerNet, self).__init__()
        self.linear1 = nn.Linear(d_in, H)
        self.linear2 = nn.Linear(H, d_out)

    #  forward是定义前向传播的部分
    def forward(self, x):
        y_pred = self.linear2(self.linear1(x).clamp(min=0))
        return y_pred

第三步:应用模型

前向传播部分

主要是两个方面,第一是把上面定义好的框架应用起来,第二是给定学习率和loss function。

# 初始化model
model = TwoLayerNet(d_in, H, d_out)

# 规定loss function
loss_fn = nn.MSELoss(reduction='sum')

# 规定学习率
learning_rate = 1e-4

反向传播部分

首先,咱们约定反向传播的模型是SGD这种比较简单的模型:

optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
loss_list = []  # 为了画图

训练迭代部分

至此,咱们须要对模型有个直观认识,对于整个模型而言应当是$x \rightarrow H \rightarrow y_{pred}$为正向传播路径,而损失函数为:

$$loss = \sqrt{y_{pred}^2-y^2} $$

对于各层神经网络,我借用网图来讲明一下关系:

timg.jpg

第一层神经网络是输入部分:因此权重矩阵$w_1$应该是$d_{in}\times H$的维度,同理,第二层神经网络输出权重矩阵应当是$H \times d_{out}$维度。

咱们接下来就是进行训练迭代,咱们先约定训练$200$代,观察收敛效果。

for it in range(200):
    #  forward pass
    y_pred = model(x)

    #  compute loss
    loss = loss_fn(y_pred.float(), y.float())
    print(it, loss.item())
    loss_list.append(loss)

    #  backward pass
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

forward pass部分是把自变量$x$输入到模型中,而compute loss是计算损失数值,咱们须要注意如下这些点:

  • loss_fn(y_pred.float(), y.float())不能够写成loss_fn(y_pred- y),不然会缺失一个target参数
  • loss.item()是用来输出loss这个tensor包含的数值

backward pass中,咱们须要注意,每次求梯度降低以前,都须要把以前的梯度清零,缘由就是这个梯度若是不被清零,在每次迭代的时候都会被自动叠加,这样自动叠加的好处是对于一些连锁的梯度运算的时候更为方便了,可是对于每一代而言都须要手动进行清零。

第四步:结尾和简单分析

最后咱们只要简单的把迭代的图画出来便可,效果大概是这样的:

plt.plot(range(200), loss_list)
plt.show()

Figure_1.png
大概在$10$代附近就已经收敛了,效果仍是蛮不错的。能够经过第一次运行的结果调整迭代次数。

下面附上整个代码:

import torch
import torch.nn as nn
import numpy as np
import matplotlib.pyplot as plt
N, d_in, H, d_out = 64, 1000, 100, 10

#  随机建立一些训练数据
x = torch.randn(N, d_in, requires_grad=True)
y = torch.randn(N, d_out, requires_grad=True)


class TwoLayerNet(torch.nn.module):
    #  定义了init和forward就想到于给定了一个模型
    #  init至关于给了这个框架
    def __init__(self, D_in, H, D_out):
        super(TwoLayerNet, self).__init__()
        self.linear1 = nn.Linear(D_in, H)
        self.linear2 = nn.Linear(H, D_out)

    #  forward是
    def forward(self, x):
        y_pred = self.linear2(self.linear1(x).clamp(min=0))
        return y_pred


# 初始化model
model = TwoLayerNet(d_in, H, d_out)

# 规定loss function
loss_fn = nn.MSELoss(reduction='sum')

# 规定学习率
learning_rate = 1e-4

#  定义optimizer作优化
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
loss_list = []
for it in range(200):
    #  forward pass
    y_pred = model(x)

    #  compute loss
    loss = loss_fn(y_pred.float(), y.float())
    print(it, loss.item())
    loss_list.append(loss)

    #  backward pass
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

plt.plot(range(200), loss_list)
plt.show()

参考资料

pytorch官方文档

最好的PyTorch的入门与实战教程(16小时实战)

相关文章
相关标签/搜索