完整的训练过程
为了更好地理解pytorch框架下如何利用神经网络训练数据,可以通过一个简单的回归任务来学习理解。
第一步:生成数据集(y = a * x^2 + b)
import torch
from torch.autograd import Variable
import matplotlib.pyplot as plt
torch.manual_seed(1)
x = torch.unsqueeze(torch.linspace(-1, 1, 100), dim=1) # 张量 x: (100, 1)
y = x.pow(2) + 0.2*torch.rand(x.size()) # 加入噪声的张量 y: (100, 1)
# 将张量转为 Variable
x, y = Variable(x), Variable(y)
# 画一下
plt.scatter(x.data.numpy(), y.data.numpy())
plt.show()
第二步:建立网络结构
class Net(torch.nn.Module):
def __init__(self, n_feature, n_hidden, n_output):
super(Net, self).__init__()
self.hidden = torch.nn.Linear(n_feature, n_hidden) # 隐层
self.relu = torch.nn.ReLU() # 选择激活层
self.predict = torch.nn.Linear(n_hidden, n_output) # 输出层
def forward(self, x):
x = self.hidden(x) # 计算隐层
x = self.relu(x) # 计算激活层
x = self.predict(x) # 输出层
return x
net = Net(n_feature=1, n_hidden=10, n_output=1) # 定义网络
print(net) # 打印网络结构
第三步:网络的训练
# 选择损失函数和优化方法
loss_func = torch.nn.MSELoss()
optimizer = torch.optim.SGD(net.parameters(), lr=0.5)
plt.ion() # hold住图
for t in range(100):
prediction = net(x) # 用网络预测一下
loss = loss_func(prediction, y) # 计算损失
optimizer.zero_grad() # 清除上一步的梯度
loss.backward() # 反向传播, 计算梯度
optimizer.step() # 优化一步
if t % 5 == 0:
plt.cla()
plt.scatter(x.data.numpy(), y.data.numpy())
plt.plot(x.data.numpy(), prediction.data.numpy(), 'r-', lw=5)
plt.text(0.5, 0, 'Loss=%.4f' % loss.data[0], fontdict={'size': 20, 'color': 'red'})
plt.pause(0.1)
plt.ioff()
plt.show()
构建序列网络
torch.nn.Sequential是一个Sequential容器,模块将按照构造函数中传递的顺序添加到模块中。另外,也可以传入一个有序模块。 为了更容易理解,官方给出了一些案例:
# Sequential使用实例
model = nn.Sequential(
nn.Conv2d(1,20,5),
nn.ReLU(),
nn.Conv2d(20,64,5),
nn.ReLU()
)
# Sequential with OrderedDict使用实例
model = nn.Sequential(OrderedDict([
('conv1', nn.Conv2d(1,20,5)),
('relu1', nn.ReLU()),
('conv2', nn.Conv2d(20,64,5)),
('relu2', nn.ReLU())
]))
用序列化工具, 给予Pytorch 内部集成的网络层 快速搭建
seq_net = torch.nn.Sequential(
torch.nn.Linear(1, 10),
torch.nn.ReLU(),
torch.nn.Linear(10, 1)
)
作为对比,我们构建一样的网络结构,打印出来如下:
print(net) # 打印网络结构
"""
ModuleNet (
(hidden): Linear (1 -> 10)
(relu): ReLU ()
(predict): Linear (10 -> 1)
)
"""
print(seq_net) # 打印网络结构
"""
Sequential (
(0): Linear (1 -> 10)
(1): ReLU ()
(2): Linear (10 -> 1)
)
"""
第三种表示方法,通过add_module()添加每一层,并且为每一层增加了一个单独的名字。
**class _Transition(nn.Sequential):** #可改为nn.module
"""Transition layer between two adjacent DenseBlock"""
def __init__(self, num_input_feature, num_output_features):
super(_Transition, self).__init__()
#或者 self.conv=torch.nn.Sequential()
#self.conv.add_module(" ")
self.add_module("norm", nn.BatchNorm2d(num_input_feature))
self.add_module("relu", nn.ReLU(inplace=True))
self.add_module("conv", nn.Conv2d(num_input_feature, num_output_features,
kernel_size=1, stride=1, bias=False))
self.add_module("pool", nn.AvgPool2d(2, stride=2))