4、神经网络的模块化接口torch.nn

本博客参考 http://studyai.com/pytorch-1.4/beginner/blitz/neural_networks_tutorial.html + 《PyTorch入门与实践》

torch.nn最核心的类是nn.Module,一个 nn.Module 包含若干 layers, 和一个方法 forward(input), 该方法返回 output 。

自定义的网络类需要继承nn.Module,其构造函数里必须执行一次父类构造函数。

网络中拥有可学习的参数的层要放在构造函数中,不拥有的随意。

torch.nn 仅支持 mini-batches。 整个 torch.nn package 仅支持以样本的 mini-batch 作为输入,而不支持单个样本作为输入。

例如, nn.Conv2d 将接受一个shape为 nSamples nChannels Height Width 的 4D Tensor 作为输入。

如果你有一个单样本, 请使用 input.unsqueeze(0) 将batch_size设为1(即nSamples),nChannels Height Width 

神经网络的训练步骤:

1、定义一个神经网络
2、处理输入并backward
3、计算损失(度量 网络的输出 离 我们期望的正确输出 还有多远)
4、使用优化器(优化方法)更新网络的权重和参数

#代码中的数据参考上图
########################################### 1、定义一个神经网络
import torch.nn as nn import torch.nn.functional as F class Net(nn.Module): #定义网络类,继承自nn.Module def __init__(self): #类的构造函数 super(Net,self).__init__() #执行一次父类的构造函数(硬性要求),等价于 nn.Module.__init__(self) ## 卷积层 self.conv1=nn.Conv2d(1,6,5) #输入图像 1 个通道, 6 个输出通道, 5x5 方形卷积核 self.conv2=nn.Conv2d(6,16,5) #上层的6作为此层的输入,输出16通道,5x5 ## 仿射层/全连接层,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): #卷积→激活→池化 # 最大池化的窗口大小(2, 2) x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2)) # 如果池化窗口是方形的,你只需要指定单个数字 x = F.max_pool2d(F.relu(self.conv2(x)), 2) #-1代表自适应,reshape x = x.view(x.size()[0],-1) x = F.relu(self.fc1(x)) x = F.relu(self.fc2(x)) x = self.fc3(x) return x net = Net() print(net)

只要nn.Module子类中定义了forward函数,backward函数就会被自动实现。下图输出的结果:

# 参数个数
print(len(list(net.parameters())))
# 输出参数
for name in net.parameters():
    print(name)
# 参数名,每个参数的大小
for name,param in net.named_parameters():
    print(name,":",param.size())

 

########################################### 2、处理输入并backward
#
尝试一个 32x32 的随机输入,这个网络(LeNet)期望的输入尺寸是 32x32 input=t.randn(1,1,32,32) out=net(input) #使用已设定的网络,1个输入,输出10个 print(out.size()) print(out) #反向传播前,所有参数的梯度清零 net.zero_grad() out.backward(t.randn(1, 10))

########################################### 3、计算损失(度量 网络的输出 离 我们期望的正确输出 还有多远)
output=net(input)
target=t.randn(10) #一个虚拟的目标值, 为了举例子,不要太在意
target=target.view(1,-1) # 使其具有与输出相同的shape
criterion=nn.MSELoss() #损失函数中的一种:平均平方误差(mean-squared error),nn.CrossEntropyLoss交叉熵损失

loss=criterion(output,target)
print(loss)

net.zero_grad() #把net中所有可学习参数的梯度清零
print("反向传播之前conv1.bias的梯度")
print(net.conv1.bias.grad)
loss.backward() #反向传播,该图会动态生成并自动微分,也会自动计算图中参数的导数
print("反向传播之后conv1.bias的梯度")
print(net.conv1.bias.grad)

########################################### 4、使用优化器(优化方法)更新网络的权重和参数
import torch.optim as optim
optimizer=optim.SGD(net.parameters(),lr=0.01) #新建优化器,指定要调整的参数和学习率。SGD随机梯度下降法
#先梯度清零
optimizer.zero_grad() #等效 net.zero_grad()
#计算损失
output=net(input)
loss=criterion(output,target)
#反向传播
loss.backward()
#更新参数
optimizer.step()

 

posted @ 2020-04-03 15:57  夕西行  阅读(548)  评论(0编辑  收藏  举报