import torch
import torch.nn as nn
import torch.nn.functional as F
#Variable就是 变量 的意思from torch.autograd import Variable
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms
import pylab
import matplotlib.pyplot as plt
import numpy as np
#==============一、让我们来定义一个LeNet神经网络:==================classNet(nn.Module):#接收的输入是nn.Module#构造函数就是自己定义的一些运算层,参数是随机初始化的def__init__(self):super(Net,self).__init__()
self.conv1 = nn.Conv2d(1,6,5)# 1 input image channel, 6 output channels, 5x5 square convolution kernel
self.conv2 = nn.Conv2d(6,16,5)
self.fc1 = nn.Linear(16*5*5,120)# an affine operation: y = Wx + b
self.fc2 = nn.Linear(120,84)
self.fc3 = nn.Linear(84,10)#前向计算:前向计算则是层之间的运算,反向传播(自动生成)相关运算则是模型自动定义defforward(self, x ):
x = F.max_pool2d(F.relu(self.conv1(x)),(2,2))# Max pooling over a (2, 2) window
x = F.max_pool2d(F.relu(self.conv2(x)),2)# If the size is a square you can only specify a single number
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
defnum_flat_features(self, x):
size = x.size()[1:]# all dimensions except the batch dimensionprint("size==",size)
num_features =1for s in size:
num_features *= s
return num_features
net = Net()print(net)""""
仅仅需要定义一个forward函数就可以了,backward会自动地生成。
你可以在forward函数中使用所有的Tensor中的操作。
模型中可学习的参数会由net.parameters()返回。"""
params =list(net.parameters())print(len(params))print(params[0].size())# conv1's .weightinput=Variable(torch.randn(1,1,32,32))#输入到模型中做前向计算的一定是一个Variable
out = net(input)#接着初始化网络中所有参数的梯度,然后用随机的梯度做一次反向传播
net.zero_grad()# 对所有的参数的梯度缓冲区进行归零,
out.backward(torch.randn(1,10))# 使用随机的梯度进行反向传播#通过预期值和实际值求loss# 神经网络的参数是要用训练数据去训练的,这就需要定义loss funtion,pytorch中的nn模块内定义了各种loss function,# torch中的loss function 包含输出和目标值。手写体字符有10个元素,我们就用1-10来表示,定义loss如下:
output = net(input)
target = Variable(torch.arange(1,11))# a dummy target, for example
target = target.view(1,-1)# make it the same shape as output 就是和numpy里的reshape是一样的,output不改变数据,但是改变数据的形状,1是表示一列,最后得到的是一个列tensor
criterion = nn.MSELoss()#求predict = output和target之间的loss。
loss = criterion(output, target)print("loss:",loss)"""Pytorch里面的X.view(-1)操作: X.view(-1)中的-1本意是根据另外一个数来自动调整维度,但是这里只有一个维度,因此就会将X里面的所有维度数据转化成一维的,并且按先后顺序排列。"""#更新optimizer 优化器#利用loss做一次反向传播就可以求出所有参数的梯度值,一般在计算定义loss后,先初始化所有参数的梯度值,再更新梯度。# 我们知道,梯度下降法只是求解优化问题中的参数的一种方法。其他方法还有Adam, RMSProp等。# create your optimizer 优化器
optimizer = optim.SGD(net.parameters(), lr=0.01)#net.parameters()网络中所有参数 lr=0.01学习率# in your training loop:训练循环
optimizer.zero_grad()# zero the gradient buffers# 对所有的参数的梯度缓冲区进行归零,
output = net(input)
loss = criterion(output.to(torch.float32), target.to(torch.float32))#易报错:做类型转换
loss.backward()
m = optimizer.step()# 所有的optimizer都实现了step()方法,这个方法会更新所有的参数print("优化过程--------------------",m)"""=======二、简单的分类网络架构=============="""#一个完整的分类网络包括:读取数据→展示数据样例→定义网络结构→定义loss和优化方法→训练网络→测试网络。以CIFAR10为例#下载数据集
transform = transforms.Compose([transforms.ToTensor(),
transforms.Normalize(mean=(0.5,0.5,0.5), std=(0.5,0.5,0.5))])#前面的(0.5,0.5,0.5) 是 R G B 三个通道上的均值, 后面(0.5, 0.5, 0.5)是三个通道的标准差std,"""注意通道顺序是 R G B ,用过opencv的同学应该知道openCV读出来的图像是 BRG顺序。这两个tuple数据是用来对RGB 图像做归一化的,如其名称 Normalize 所示这里都取0.5只是一个近似的操作,实际上其均值和方差并不是这么多,但是就这个示例而言 影响可不计。"""
batch_size=4# !!!!!!!!!!!! 数据集下载完后,改程序段,将download改为False !!!!!!!!!!!!!!
trainset = torchvision.datasets.CIFAR10(root='./data', train=True,download=False, transform=transform)#download,表示是否自动下载cifar数据集 ,train,表示是否加载数据库的训练集,False的时候加载测试集; transform,表示是否需要对数据进行预处理,none为不进行预处理;;
trainloader = torch.utils.data.DataLoader(trainset, batch_size=batch_size,shuffle=True, num_workers=2)
testset = torchvision.datasets.CIFAR10(root='./data', train=False,
download=False, transform=transform)#download=False,表示不自动下载
testloader = torch.utils.data.DataLoader(dataset=testset, batch_size=batch_size,
shuffle=False, num_workers=2)#um_workers=0意思大概就是不使用多进程 ,设置为2,就是同时跑两个进程,加快数据加载速度
classes =('plane','car','bird','cat','deer','dog','frog','horse','ship','truck')#10分类