neural networks
使用torch.nn
包中的工具来构建神经网络
构建一个神经网络需要以下几步:
- 定义神经网络的
权重
,搭建网络结构 - 遍历整个数据集进行训练
- 将数据输入神经网络
- 计算loss
- 计算网络权重的梯度
- 更新网络权重
- weight = weight + learning_rate * gradient
import torch
import torch.nn as nn
import torch.nn.functional as F
#nn.Conv2d接受输入4维的Tensor:n个样本*n个色彩频道*高度*宽度
class Net(nn.Module):#需要继承nn.Module这个类
#Net初始化函数
def __init__(self):
super(Net,self).__init__() #调用父类Net的初始化方法
#建立了两个卷积层:self.conv1,self.conv2,这些层不包括激活函数
self.conv1=nn.Conv2d(1,6,5) #输入为1个通道, 输出为6个特征图,卷积核为5*5正方形
self.conv2=nn.Conv2d(6,16,5)#输入为6个通道,输出为16个特征图,卷积核为5*5正方形
#建立了三个全连接层:全连接函数为线性函数y=wx+b
self.fc1=nn.Linear(16*5*5,120) #将上一层输出的16*5*5个节点连接到120个节点上
self.fc2=nn.Linear(120,84) #将上一层输出的120节点连接到84个节点上
self.fc3=nn.Linear(84,10) #将上一层输出的84节点连接到10个节点上
# 定义该神经网络的向前传播函数,该函数必须定义,一旦定义成功,向后传播函数也会自动生成(autograd)
def forward(self,x):
x=F.max_pool2d(F.relu(self.conv1(x)),(2,2))#输入x经卷积conv1->经激活函数Relu->使用窗口2*2进行最大池化
x=F.max_pool2d(F.relu(self.conv2(x)),(2,2))#输入x经卷积conv2->经激活函数Relu->使用窗口2*2进行最大池化
#x = F.max_pool2d(F.relu(self.conv2(x)), 2) #与上一行2*2等价
x=x.view(-1,self.num_flat_features(x))#view函数将张量x变形成一维的向量形式,总特征数并不改变,为接下来的全连接作准备
x=F.relu(self.fc1(x)) #输入x经过全连接fc1->经过ReLU激活函数,然后更新x
x=F.relu(self.fc2(x)) #输入x经过全连接fc2->经过ReLU激活函数,然后更新x
x=self.fc3(x) #输入x经过全连接fc3,然后更新x
return x
# 使用num_flat_features函数计算张量x的特征总量(把每个数字都看出是一个特征,即特征总量)
# 比如x是4*2*2的张量,那么它的特征总量就是16。
def num_flat_features(self,x):
#pytorch只接受批输入,也就是说一次性输入好几张图片,那么输入数据张量的维度自然上升到了4维。
size=x.size()[1:]# 这里为什么要使用[1:],【1:】让我们把注意力放在后3维上面
num_features=1
for s in size:
num_features*=s
return num_features
net=Net()
print(net)
#---------------------------------
params = list(net.parameters())
print(len(params))
print(params[0].size()) # conv1's .weight
#-----------查看网络结构和参数数量-------------
params = list(net.parameters())
k=0
for i in params:
l =1
print("该层的结构:"+str(list(i.size())))
for j in i.size():
l *= j
print("参数和:"+str(l))
k = k+l
print("总参数和:"+ str(k))
一个完整NN
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
#nn.Conv2d接受输入4维的Tensor:n个样本*n个色彩频道*高度*宽度
########################################################################
# Define a Convolution Neural Network
class Net(nn.Module):#需要继承nn.Module这个类
#Net初始化函数
def __init__(self):
super(Net,self).__init__() #调用父类Net的初始化方法
#建立了两个卷积层:self.conv1,self.conv2,这些层不包括激活函数
self.conv1=nn.Conv2d(1,6,5) #输入为1个通道, 输出为6个特征图,卷积核为5*5正方形
self.conv2=nn.Conv2d(6,16,5)#输入为6个通道,输出为16个特征图,卷积核为5*5正方形
#建立了三个全连接层:全连接函数为线性函数y=wx+b
self.fc1=nn.Linear(16*5*5,120) #将上一层输出的16*5*5个节点连接到120个节点上
self.fc2=nn.Linear(120,84) #将上一层输出的120节点连接到84个节点上
self.fc3=nn.Linear(84,10) #将上一层输出的84节点连接到10个节点上
# 定义该神经网络的向前传播函数,该函数必须定义,一旦定义成功,向后传播函数也会自动生成(autograd)
def forward(self,x):
x=F.max_pool2d(F.relu(self.conv1(x)),(2,2))#输入x经卷积conv1->经激活函数Relu->使用窗口2*2进行最大池化
x=F.max_pool2d(F.relu(self.conv2(x)),(2,2))#输入x经卷积conv2->经激活函数Relu->使用窗口2*2进行最大池化
#x = F.max_pool2d(F.relu(self.conv2(x)), 2) #与上一行2*2等价
x=x.view(-1,self.num_flat_features(x))#view函数将张量x变形成一维的向量形式,总特征数并不改变,为接下来的全连接作准备
x=F.relu(self.fc1(x)) #输入x经过全连接fc1->经过ReLU激活函数,然后更新x
x=F.relu(self.fc2(x)) #输入x经过全连接fc2->经过ReLU激活函数,然后更新x
x=self.fc3(x) #输入x经过全连接fc3,然后更新x
return x
# 使用num_flat_features函数计算张量x的特征总量(把每个数字都看出是一个特征,即特征总量)
# 比如x是4*2*2的张量,那么它的特征总量就是16。
def num_flat_features(self,x):
#pytorch只接受批输入,也就是说一次性输入好几张图片,那么输入数据张量的维度自然上升到了4维。
size=x.size()[1:]# 这里为什么要使用[1:],【1:】让我们把注意力放在后3维上面
num_features=1
for s in size:
num_features*=s
return num_features
net=Net()
print(net)
#如果使用MNIST数据集来训练这个LeNet网络,需要把图片大小重新调整到32*32
input = torch.randn(1, 1, 32, 32)
out = net(input)
print(out)
#将所有参数的梯度缓存清零,然后进行随机梯度的的反向传播.
net.zero_grad()
out.backward(torch.randn(1, 10))
########################################################################
# Define a Loss function and optimizer
output=net(input)
target=torch.randn(10)
target=target.view(1,-1)
criterion=nn.MSELoss()
loss=criterion(output,target)
print(loss)
# create your optimizer
optimizer = optim.SGD(net.parameters(), lr=0.01)
# in your training loop:
optimizer.zero_grad() # zero the gradient buffers
output = net(input)
loss = criterion(output, target)
loss.backward()
optimizer.step() # Does the update