赞
踩
前面我们已经介绍了autograd
包,现在我们使用torch.nn
包来构建神经网络,nn
包依赖于autograd
包来定义模型并对它们求导。
nn.Module
是神经网络模块。包含神经网络各个层和一个forward(input)
方法,该方法返回output
。
nn.Parameter
也是一个tensor,当它作为一个属性分配给一个Module时,它会被自动注册为一个参数。
运行环境:PyTorch1.0
import torch import matplotlib.pyplot as plt # 做一些假数据来观看图像 x = torch.linspace(-5, 5, 200) # x data (tensor), shape=(100, 1) x = Variable(x) x_np = x.numpy() # 换成 numpy array, 出图时用 # 几种常用的 激励函数 y_relu = torch.relu(x).detach().numpy() y_sigmoid = torch.sigmoid(x).detach().numpy() y_tanh = torch.tanh(x).detach().numpy() plt.figure(1, figsize=(8, 6)) plt.subplot(221) plt.plot(x_np, y_relu, c='red', label='relu') plt.ylim((-1, 5)) plt.legend(loc='best') plt.subplot(222) plt.plot(x_np, y_sigmoid, c='red', label='sigmoid') plt.ylim((-0.2, 1.2)) plt.legend(loc='best') plt.subplot(223) plt.plot(x_np, y_tanh, c='red', label='tanh') plt.ylim((-1.2, 1.2)) plt.legend(loc='best') plt.show()
nSamples×nChannels×Height×Width
,输出一个4维张量:nSamples×nChannels\_out×Height\_out×Width\_out
torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True)
其他网络结构详见nn包文档:https://pytorch.org/docs/stable/nn.html#
一个损失函数接受一对(output, target)作为输入,计算一个值来估计网络的输出和目标值相差多少。
详见nn包文档:https://pytorch.org/docs/stable/nn.html#
网络上的很多代码都是PyTorch0.4以前的版本,自从0.4后variable和tensor合并,tensor也具有requires_grad的属性了。
import torch import torch.nn as nn import torch.nn.functional as F class Net(nn.Module): def __init__(self): super(Net, self).__init__() # CLASS torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True) # 1 input image channel, 6 output channels, 5x5 square convolution kernel self.conv1 = nn.Conv2d(1, 6, 5) self.conv2 = nn.Conv2d(6, 16, 5) # an affine operation: y = Wx + b self.fc1 = nn.Linear(16 * 5 * 5, 120) self.fc2 = nn.Linear(120, 84) self.fc3 = nn.Linear(84, 10) def forward(self, x): # Max pooling over a (2, 2) window x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2)) # If the size is a square you can only specify a single number x = F.max_pool2d(F.relu(self.conv2(x)), 2) # view函数将张量x变形成一维的向量形式,总特征数并不改变,为接下来的全连接作准备。 x = x.view(-1, self.num_flat_features(x)) x = F.relu(self.fc1(x)) x = F.relu(self.fc2(x)) x = self.fc3(x) return x # num_flat_features:计算张量x的总特征量(把每个数字都看出是一个特征,即特征总量) def num_flat_features(self, x): size = x.size()[1:] # all dimensions except the batch dimension(批大小维度) num_features = 1 for s in size: num_features *= s return num_features net = Net() print(net)
Net(
(conv1): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1))
(conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
(fc1): Linear(in_features=400, out_features=120, bias=True)
(fc2): Linear(in_features=120, out_features=84, bias=True)
(fc3): Linear(in_features=84, out_features=10, bias=True)
)
可以看出来,我们设置了5层网络,得到了10个参数((权重+偏置)* 5 层):
params = list(net.parameters())
print(len(params))
print(type(params[0]))
for i in range(10):
print("第{}个参数形状为{}".format(i,params[i].size()))
10
<class 'torch.nn.parameter.Parameter'>
第0个参数形状为torch.Size([6, 1, 5, 5])
第1个参数形状为torch.Size([6])
第2个参数形状为torch.Size([16, 6, 5, 5])
第3个参数形状为torch.Size([16])
第4个参数形状为torch.Size([120, 400])
第5个参数形状为torch.Size([120])
第6个参数形状为torch.Size([84, 120])
第7个参数形状为torch.Size([84])
第8个参数形状为torch.Size([10, 84])
第9个参数形状为torch.Size([10])
这个网络(LeNet)的期待输入是32x32,让我们随机生成一组数据作为输入:
input = torch.randn(1, 1, 32, 32)
print('conv1输出的形状:',net.conv1(input).size()) # conv1输出的形状
out = net(input)
print('输出层形状',out.size())
print('输出层结果:',out)
conv1输出的形状: torch.Size([1, 6, 28, 28])
输出层形状 torch.Size([1, 10])
输出层结果: tensor([[ 0.1090, 0.0137, 0.0531, -0.0406, -0.0739, 0.0899, 0.0254, 0.0115,
0.0654, 0.0346]], grad_fn=<AddmmBackward>)
output = net(input)
target = torch.randn(10) # a dummy target, for example
target = target.view(1, -1) # make it the same shape as output
criterion = nn.MSELoss()
loss = criterion(output, target)
print('loss:',loss)
print('''
反向跟踪loss,使用它的.grad_fn属性,你会看到向下面这样的一个计算图:
input -> conv2d -> relu -> maxpool2d -> conv2d -> relu -> maxpool2d -> view -> linear -> relu -> linear -> relu -> linear -> MSELoss -> loss''')
print(loss.grad_fn) # MSELoss
print(loss.grad_fn.next_functions[0][0]) # Linear
print(loss.grad_fn.next_functions[0][0].next_functions[0][0]) # ReLU
loss: tensor(0.6886, grad_fn=<MseLossBackward>)
反向跟踪loss,使用它的.grad_fn属性,你会看到向下面这样的一个计算图:
input -> conv2d -> relu -> maxpool2d -> conv2d -> relu -> maxpool2d -> view -> linear -> relu -> linear -> relu -> linear -> MSELoss -> loss
<MseLossBackward object at 0x0000021708CC6710>
<AddmmBackward object at 0x000002170910CE10>
<AccumulateGrad object at 0x0000021708CC6710>
包torch.optim 实现了各种不同的参数更新规则,如SGD、Nesterov-SGD、Adam、RMSProp等
# 优化器
optimizer = torch.optim.SGD(net.parameters(),lr=0.1)
for epoch in range(10):
optimizer.zero_grad() # zero the gradient buffers
output = net(input)
loss = criterion(output, target)
print(loss)
loss.backward()
optimizer.step() # Does the update
tensor(0.6886, grad_fn=<MseLossBackward>)
tensor(0.6061, grad_fn=<MseLossBackward>)
tensor(0.5165, grad_fn=<MseLossBackward>)
tensor(0.3901, grad_fn=<MseLossBackward>)
tensor(0.2053, grad_fn=<MseLossBackward>)
tensor(0.0425, grad_fn=<MseLossBackward>)
tensor(0.0061, grad_fn=<MseLossBackward>)
tensor(0.0012, grad_fn=<MseLossBackward>)
tensor(0.0007, grad_fn=<MseLossBackward>)
tensor(0.0010, grad_fn=<MseLossBackward>)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。