Basic CNN代码实现
引入库
#引入torch
import torch
#从torchvision中引入图像转换
from torchvision import transforms
#从torchvision中引入数据集
from torchvision import datasets
#从torch的工具中的数据引入数据加载器
from torch.utils.data import DataLoader
#引入torch中的神经网络的激活函数(relu)
import torch.nn.functional as F
#引入torch中优化器
import torch.optim as optim
#batch_size的大小是64
batch_size = 64
#用Compose组合多个transform操作
transform = transforms.Compose([
#ToTensor将图像中的字节转换成tensor;
transforms.ToTensor(),
#Normalize将数据进行标准化,1是均值,2是标准差
transforms.Normalize((0.1307, ),(0.3081, ))
])
#训练数据集的MNIST的数据集的根在mnist文件夹中
train_dataset = datasets.MNIST(root='../dataset/mnist',
#让训练等于真,提取训练集
train=True,
#下载等于真,下载数据集
download=True
#transform直接应用上面的transform
transform=transform)
#训练加载器是数据加载器,引入训练数据集
train_loader = DataLoader(train_dataset,
#shuffle为真,将数据打乱
shuffle=True,
#batch的大小为前面设定好的大小
batch_size=batch_size)
#测试数据集的MNIST的数据集的根在mnist文件夹中
test_dataset = datasets.MNIST(root='../dataset/mnist/',
#训练为假,测试为真
train=False,
#下载为真,就是下载
download=True,
#transform直接应用上面的transform
transform=transform)
#测试加载器是数据加载器,引入测试数据集
test_loader = DataLoader(test_dataset,
#shuffle为假,不将数据打乱
shuffle=False,
#batch的大小为前面设定好的大小
batch_size=batch_size)
#设Net为一个类,继承自Module模块
class Net(torch.nn.Module):
#自身初始化
def __init__(self):
#调用父类初始化器
super(Net,self).__init__()
#第一层卷积层是用Conv2d模块,输入1,输出10,核5
self.conv1 = torch.nn.Conv2d(1,10,kernel_size=5)
#第二层卷积层是用Conv2d模块,输入10,输出20,核5
self.conv2 = torch.nn.Conv2d(10,20,kernel_size=5)
#池化层是引入MaxPool2d模块,设卷积核数量为2
self.pooling = torch.nn.MaxPool2d(kernel_size=2)
#全连接层是线性模型将输入320变成输出10
self.fc = torch.nn.Linear(320,10)
#定义自身前馈计算
def forward(self,x):
#定义batch的大小是数据张量的第0个维度的数据,也就是样本的数量
batch_size = x.size(0)
#先做卷积在做池化,最后激活
x = F.relu(self.pooling(self.conv1(x)))
#先做卷积在做池化,最后激活
x = F.relu(self.pooling(self.conv2(x)))
#用view改变x的形状,行为batch的大小,列自动计算得到
x = x.view(batch_size,-1)
#代入线性模型求出结果
x = self.fc(x)
#返回x
return x
#模型实例化
model = Net()
#定义装置,如果cuda是能用的,那你就用第一个显卡用cuda跑,否则用cpu跑
#device = torch.device("cuda:0"if torch.cuda.is_available()else"cpu")
#让模型在GPU上跑
#model.to(device)
#损失的标准是交叉熵损失
criterion = torch.nn.CrossEntropyLoss()
#用优化模块中的SGD优化模型中所有的参数,学习率为0.01,加入动量为0.5,加入一个惯性,优化方向
optimizer = optim.SGD(model.parameters(),lr=0.01,momentum=0.5)
#定义训练过程,epoch是循环次数
def train(epoch):
#设初始损失值是0
running_loss = 0.0
#batch_idx表示进行多少次的batch的迭代,data是数据,用列举的方法将train_loader的数据提取出来,从0开始
for batch_idx, data in enumerate(train_loader,0):
#将输入x和相应的目标y从数据中拿出来
inputs, target = data
#将输入和目标y都放到GPU上面
#inputs, target = inputs.to(device),target.to(device)
#用优化模块进行梯度归零
optimizer.zero_grad()
#将输入代入模型,求出输出y
outputs = model(inputs)
#将目标和输出代入标准器,计算损失
loss = criterion(outputs, target)
#反向传播
loss.backward()
#优化更新
optimizer.step()
#损失标量求和,求总的损失值
running_loss += loss.item()
#如果迭代次数除以300的余数等于299,每300轮输出一次
if batch_idx % 300 == 299:
#输出[%d代表是一位整数,%5d代表是5位,位数不够用空格填充],损失用小数点后三位浮点型表示。
#%用于格式化输出的连接符号,总的循环次数+1,batch的循环次数+1,损失除以2000轮,求一次损失
print('[%d,%5d] loss:%.3f'%(epoch + 1,batch_idx + 1,running_loss / 2000))
#将损失归零
running_loss = 0.0
#定义test模块
def test():
#正确的数量初始为0
correct = 0
#总数为0
total = 0
#用with方式让torch不计算梯度
with torch.no_grad():
#for循环data在测试加载器中
for data in test_loader:
#输入和目标送到数据里面
inputs, target = data
#将输入和目标y都放到GPU上面
#inputs, target = inputs.to(device),target.to(device)
#将输入代入模型,求输出
outputs = model(inputs)
#用torch中的max函数,沿着输出的数据的维度为1方式,找到最大值和最大值的下标,
#_是最大值,predicted是最大值的下标
_, predicted = torch.max(outputs.data,dim=1)
#总数等于标签的size取第0个元素相加求得总数
total += target.size(0)
#正确是预测和标签相等标量求和
correct += (predicted == target).sum().item()
#输出%d代表整数,%%代表%,%格式化输出得连接符号,正确除总数乘100
print('Accuracy on test set: %d %%' % (100 * correct / total))
#封装到if语句里面
if __name__ == '__main__':
#循环10次
for epoch in range(10):
#训练
train(epoch)
#测试
test()