个人电脑在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
应当是全部神经网络的基类,而且你要是写一个神经网络也应该继承自此。.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} $$
对于各层神经网络,我借用网图来讲明一下关系:
第一层神经网络是输入部分:因此权重矩阵$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()
大概在$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()