动手学深度学习学习笔记(7)

定义模型
pytorch提供了大量预定义的层
首先导入torch.nn模块,实际上nn是neural networks的缩写,该模块定义了大量神经网络的层。
nn就是利用autograd来定义层。nn的核心结构数据是Module,是一个抽象概念,既可以表示神经网络中的某个层,也可以表示很多层的神经网络。
最常用的做法是继承nn.Module,写自己的层

class LinearNet(nn.Module):
	def __init__(self,n_feature):
		super(LinearNet,self).__init__()
		self.linear = nn.Linear(n_feature,1)
	#定义前向传播
	def forward(self,x):
		y = self.linear(x)
		return y

net = LinearNet(num_inputs)
print(net)
#可以打印网络结构

输出

LinearNet(
  (linear): Linear(in_features=2, out_features=1, bias=True)
)

可以用nn.Sequential更方便的搭建网络,Sequential是一个有序的容器,网络层将按照传入Sequential的顺序依次添加到计算图中。

#写法一
net = nn.Sequential(nn.Linear(num_inputs,1)
#这里可添加其他层)

#写法二
net = nn.Sequential()
net.add_module('linear', nn.Linear(num_inputs, 1))
#可仿照上面添加其他层

#写法三
from collections import OrderedDict
net = nn.Sequential(OrderedDict([('linear',nn.Linear(num_inputs, 1))]))

print(net)
print(net[0])

输出:

Sequential(
  (0): Linear(in_features=2, out_features=1, bias=True)
)
Linear(in_features=2, out_features=1, bias=True)+

可以通过net.parameters()来查看模型所有的可学习参数,此函数将返回一个生成器

for param in net.parameters():
	print(param)

输出:

Parameter containing:
tensor([[-0.6227,  0.3988]], requires_grad=True)
Parameter containing:
tensor([0.4589], requires_grad=True)

作为一个单层神经网络,线型回归输出层中的神经元和输入层中各个输入完全连接。因此,线性回归的输出层又叫全连接层。

初始化模型参数
在使用net前,需要初始化模型参数,例如w和b
PyTorch在init模块中提供了多种参数初始化方法。这里的init是initializer的缩写。
通过init.normal_将权重参数每个都初始化微均值为0,标准差为0.01的正态分布。b初始化为0。

from torch.nn import init

init.normal_(net[0].weight,mean = 0,std = 0.01)
init.constant_(net[0].bias,val = 0)

重点
如果此时的net是自定义的,那么net[0].weight应该修改为net.linear.weight。因为net[0]这种根据下标访问层的写法只有当net是个ModuleList或者Sequential实例时才可以。

定义损失函数
PyTorch在nn模块中提供了各种损失函数,损失函数可以看作一种特殊的层,PyTorch也将这些损失函数实现为nn.Module的子类。
以均方误差损失作为模型的损失函数。

loss = nn.MSELoss()

定义优化算法
torch.optim提供了很多常见的优化算法如SGD,Adam和RMSProp等。
指定learing rate为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.subnet1.parameters()},
#没有指定lr的层,默认使用最外层的lr
{'params':net.subnet2.parameters(), 'lr':0.01}],
lr = 0.03)

有时不想让lr为一个固定的数。
第一种:一种是修改optimizer.param_groups中对应的学习率
第二种:新建优化器,optimizer十分轻量级,构建开销很小,因此可以构建新的optimizer。但是后者对于使用动量的优化器(例如Adam),会丢失动量等状态信息,可能会造成损失函数的收敛出现震荡等。

for param_group in optimer.param_groups:
	param_group['lr'] *= 0.1

训练模型
通过调用optim实例的step函数来迭代模型参数,在step中指明批量大小,对样本梯度求平均。

num_epochs = 3
for epoch in range(num_epochs):
	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 0, loss:0.000306
epoch 1, loss:0.000091
epoch 2, loss:0.000060

比较学习参数和实际参数

dense = net[0]
print(true_w, dense.weight)
print(true_b, dense.bias)

输出:

[2, -3.4] Parameter containing:
tensor([[ 2.0000, -3.3997]], requires_grad=True)
4.2 Parameter containing:
tensor([4.2006], requires_grad=True)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值