import torch
import torchvision
# 预处理和加载数据集
from torchvision import datasets,transforms
# 分批加载打包数据
from torch.utils.data import DataLoader
# 神经网络模型
import torch.nn as nn
# 激活函数
import torch.nn.functional as F
# 加载优化器
import torch.optim as optim
# 可视化
import matplotlib.pyplot as plt
import numpy as np
import os
import matplotlib.pyplot as plt
os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"、
# 定义训练轮数
epoch_num = 20
# 定义学习率
lr = 0.1
momentum = 0.5
# 对图像预处理
transform=transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))])
# 加载数据集
train_set = datasets.CIFAR10('\data2',train = True,transform = transform,download = False)
test_set = datasets.CIFAR10('\data2',train = False,transform = transform,download = False)
# 分批加载
train_data = DataLoader(train_set,batch_size = 4,shuffle = True)
test_data = DataLoader(test_set ,batch_size = 4,shuffle = True)
# 定义卷积神经网络模型(卷积+池化+卷积+池化+平均池化+全连接层)
class Net(nn.Module):
def __init__(self,input_dim,conv1_dim,conv2_dim,out_dim,kernel):
super().__init__()
self.conv1 = nn.Sequential(nn.Conv2d(input_dim,conv1_dim,kernel),nn.ReLU(True))
self.pool1 = nn.MaxPool2d(2,2)
self.conv2 = nn.Sequential(nn.Conv2d(conv1_dim,conv2_dim,kernel),nn.ReLU(True))
self.pool2 = nn.MaxPool2d(2,2)
self.aap = nn.AdaptiveAvgPool2d(1)
self.Lin = nn.Linear(conv2_dim,out_dim)
def forward(self,x):
# 输入的x应该是四维的tensor
x = self.conv1(x)
x = self.pool1(x)
x = self.conv2(x)
x = self.pool2(x)
x = self.aap(x)
# 全连接神经网络要求输入的数据是2维tensor。
x = x.view(x.shape[0],-1)
x = self.Lin(x)
return x
module = Net(3,16,36,10,5)
device = torch.device('cpu')
module = module.to(device)
# 定义优化器
optimizer = optim.SGD(module.parameters(),lr = lr,momentum=momentum)
# 定义损失函数
loss_fun = nn.CrossEntropyLoss()
# 分别用来保存训练过程和测试过程中的损失和精确度
train_losses = []
train_accury = []
test_losses = []
test_accury = []
# 动态调整学习率
# def ajust_learning_rate(optimizer,lr):
# for param_group in optimizer.param_groups:
# param_group['lr']=lr
for epoch in range(epoch_num):
if epoch%2==0:
lr = lr*0.9
optimizer.param_groups[0]['lr'] = lr
# ajust_learning_rate(optimizer,lr)
# 用来计算训练过程中的损失和精确度
train_loss = 0
train_acc = 0
module.train()
for img ,label in train_data:
img = img.to(device)
label = label.to(device)
#
out = module(img)
loss = loss_fun(out,label)
train_loss+=loss.item()/img.shape[0]
# 梯度清0+ 反向传播+更新优化器中的参数
optimizer.zero_grad()
loss.backward()
optimizer.step()
_,prediction = out.max(1)
correct_num = (prediction==label).sum().item()
train_acc+=correct_num/img.shape[0]
train_losses.append(train_loss/len(train_data))
train_accury.append(train_acc/len(train_data))
# print('epoch:{} train_loss:{:.4f} train_acc:{:.4f}'.format(epoch,train_loss/len(train_data),train_acc/len(train_data)))
module.eval()
with torch.no_grad():
test_loss = 0
test_acc = 0
for img,label in test_data:
img = img.to(device)
label = label.to(device)
out = module(img)
loss = loss_fun(out,label)
test_loss+=loss.item()/img.shape[0]
_,prediction = out.max(1)
correct_num = (prediction==label).sum().item()
test_acc +=correct_num/img.shape[0]
print('epoch:{} train_loss:{:.4f} , train_acc:{:.4f} , test_loss:{:.4f} , test_acc:{:.4f}'.format(epoch,train_loss/len(train_data),
train_acc/len(train_data),test_loss/len(test_data),test_acc/len(test_data)))
test_losses.append(test_loss/len(test_data))
test_accury.append(test_acc/len(test_data))
可视化部分:
# 训练损失和精确度可视化
plt.plot(np.arange(len(test_losses)),test_losses,c='r',lw = 2)
plt.plot(np.arange(len(train_losses)),train_losses,c='b',lw = 2)
plt.legend(['Train_losses','test_losses'])
plt.plot(np.arange(len(test_losses)),test_accury,c='r',lw = 2)
plt.plot(np.arange(len(train_losses)),train_accury,c='b',lw = 2)
plt.legend(['Train_losses','test_losses'])
# 训练数据集可视化
kinds = ['plane','automobile','bird','cat','deer','dog','frog','horse','ship','truck']
dire = iter(train_data)
img ,label = dire.next()
imges = img
# torchvision.utils.make_grid 将若干个图像拼接成一个图像,z主要参数为输入的tensort,
# nrow用来调整排列方式,行数为 (batch_size % nrow) +1
img = torchvision.utils.make_grid(img,nrow=4,padding = 8)
# 反归一化处理((img-0.5)/0.5)的逆过程,就是img*0.5+0.5
img = img/2+0.5
npimg = img.numpy()
# 经过torchvision.utils.make_grid处理后,我们的img已经变成了3维(c,h,w)分布的图像,将它转化成(h,w,c)分布的图像
newimg = np.transpose(npimg,(1,2,0))
plt.imshow(newimg)
out = module(imges)
_,prediction = out.max(1)
label = label.numpy()
print("Real label: ")
for i in label:
print(kinds[i],end=" ")
pre = prediction.numpy()
print("\n")
print("predicted label: ")
for i in pre:
print(kinds[i],end=" ")