本节利用pytorch中的模块,生成一个更加简洁的代码来实现一样的功能python
%matplotlib inline import torch from IPython import display from matplotlib import pyplot as plt import numpy as np import random
num_inputs =2 ## 特征数量 num_examples=1000 # 样本量 true_w=[2,-3.4] # 真实的权重系数 true_b=4.2 # 真实的偏置量 features = torch.randn(num_examples,num_inputs,dtype=torch.float32) # 生成随机的特征 labels = true_w[0]*features[:,0]+true_w[1]*features[:,1]+true_b # 生成随机的标签 labels += torch.tensor(np.random.normal(0,0.01,size=labels.size()),dtype=torch.float32) #在标签上加上随机噪声项
pytotch 提供了data包来读取数据。因为data经常使用做变量名,咱们将data导入的data模块用Data代替。在每一次的迭代中,咱们将随机读取包含10个样本的小批量算法
import torch.utils.data as Data batch_size=10 dataset= Data.TensorDataset(features,labels) data_iter = Data.DataLoader(dataset,batch_size,shuffle=True) for X,y in data_iter: print(X,y) break
tensor([[ 1.9769, 1.5576], [-0.4743, 0.8653], [ 0.2641, 1.9682], [-2.3385, 0.3753], [ 0.3972, -0.6515], [ 1.1317, -0.2586], [ 1.6896, 1.0102], [-0.6803, 0.7734], [-0.3525, -0.7764], [ 0.3199, 0.9397]]) tensor([ 2.8727, 0.3198, -1.9711, -1.7576, 7.2187, 7.3517, 4.1360, 0.2171, 6.1193, 1.6434])
从上一节从零开始的实现中,咱们须要定义模型参数,并使用他们一步步描述模型是怎样计算的。当模型结果变得复杂时,这些步骤变得更加繁琐。其实pytorch提供了大量的预约义的层,这使我, 只须要关注使用哪些层来构造模型。下面介绍pytorch更加简洁的定义线性回归。网络
在实际使用中,经过会继承torch.Module,撰写本身的网络/层。一个nn.Module实例应该包含一些曾以及返回输出的前向传播(forward)方法.数据结构
from torch import nn class LinearNet(nn.Module): def __init__(self,n_features): super(LinearNet,self).__init__() self.linear = nn.Linear(n_features,1) # 这里的1是指out_features def forward(self,x): y = self.linear(x) return y net = LinearNet(num_inputs) # 输入特维度为2,输出结果维度为1 print(net)
LinearNet( (linear): Linear(in_features=2, out_features=1, bias=True) )
事实上,咱们还能够用nn.Sequential来更加方便的搭建网络,Sequential是一个有序的容器,网络层将按照在传入的Sequential的顺序依次被添加到计算图中。dom
# 写法1 net= nn.Sequential(nn.Linear(num_inputs,1) # 此处还能够传入其余的层 ) # 写法2 net = nn.Sequential() net.add_module('linear',nn.Linear(num_inputs,1)) # net.add_module ..... # 写法3 from collections import OrderedDict net = nn.Sequential( OrderedDict([ ('linear',nn.Linear(num_inputs,1)) # 其余的层 ]) ) print(net) print(net[0])
Sequential( (linear): Linear(in_features=2, out_features=1, bias=True) ) Linear(in_features=2, out_features=1, bias=True)
for param in net.parameters(): print(param)
Parameter containing: tensor([[-0.4229, -0.0282]], requires_grad=True) Parameter containing: tensor([0.0852], requires_grad=True)
做为一个单层神经网络,线性回归输出层中的神经元和输入层中各输入完成全链接,所以线性回归的输出层有叫做全链接层函数
在使用net前,咱们须要初始化模型参数,如线性回归模型中的权重和误差。pytorch在init模型中提供了多种参数初始化方法。这里的init是initializer的缩写形式。咱们经过init.normal_将权重参数每一个元素初始化为随机采样的均值为0,标准差为0.01的正态分布。误差会初始化为0工具
from torch.nn import init init.normal_(net[0].weight,mean=0,std=0.01) init.constant_(net[0].bias,val=0) # 该写法与后面的三种写法才能够使用,若是使用一开始的写法,net[0].weight 因改成net.linear.weight bias亦然。 #由于net[0]这样的写法只有当net是ModuleList或者Sequential实例时才能够。 #
Parameter containing: tensor([0.], requires_grad=True)
# pytorch在nn模块中提供了各类损失函数,这些损失函数能够看作是一种特殊的层,pytorch也将这些损失函数实现为nn.Module的子类。这里咱们使用 # pytorch提供的均方偏差损失做为模型的损失函数 loss = nn.MSELoss()
一样咱们也无需本身实现小批量随机梯度降低算法,torch.optim 模块提供了不少经常使用的优化算法,SGD,Adam,RMSPorp等。下面咱们建立了一个用于优化net全部参数的优化器实例,并指定学习率为0.03的小批量随机梯度降低(SGD)为优化算法。学习
import torch.optim as optim optimizer = optim.SGD(net.parameters(),lr=0.03) print(optimizer)
SGD ( Parameter Group 0 dampening: 0 lr: 0.03 momentum: 0 nesterov: False weight_decay: 0 )
咱们能够为不一样的子网络设置不一样的学习率,这在finetune时常常用到。优化
optimizer = optim.SGD( [ {'params':net.subset1.parameters()}, # lr 默认用最外层的学习率 {'params':net.subset2.parameters(),'lr':0.01} ], lr= 0.03 )
在使用pytorch训练模型时,咱们经过调用optim实例的step函数来迭代模型参数。按照小批量随机梯度降低的定义,咱们在step函数中指明批量大小
从而而批量中中样本梯度求平均ui
num_epochs =3 for epoch in range(1,num_epochs+1): for X,y in data_iter: output = net(X) l = loss(output,y.view(-1,1)) optimizer.zero_grad() # 梯度清零,等价于net.zero_grad() l.backward() optimizer.step() print('epoch %d loss: %f'%(epoch,l.item()))
epoch 1 loss: 0.000286 epoch 2 loss: 0.000199 epoch 3 loss: 0.000072
下面咱们分别比较学到的模型参数和真实的模型参数。咱们从net得到的须要的层,并访问其权重(weight)和误差(bias)。学到的参数和真实的参数很接近
dense=net[0] print(true_w,dense.weight) print(true_b,dense.bias)
[2, -3.4] Parameter containing: tensor([[ 2.0010, -3.3996]], requires_grad=True) 4.2 Parameter containing: tensor([4.2005], requires_grad=True)