【实验目的】
理解神经网络原理,掌握神经网络前向推理和后向传播方法;
掌握使用pytorch框架训练和推理全连接神经网络模型的编程实现方法。
【实验内容】
1.使用pytorch框架,设计一个全连接神经网络,实现Mnist手写数字字符集的训练与识别。
【实验报告要求】
修改神经网络结构,改变层数观察层数对训练和检测时间,准确度等参数的影响;
修改神经网络的学习率,观察对训练和检测效果的影响;
修改神经网络结构,增强或减少神经元的数量,观察对训练的检测效果的影响。
import torch
import torch.nn as nn
import torch.nn.functional as F
import matplotlib.pyplot as plt
import torchvision
import numpy as np
import torch.optim as optim
from torch.utils.data import Dataset
from torch.utils.data import DataLoader
from torchvision import transforms
from torchvision import datasets
import os
train_transform = transforms.Compose([
transforms.RandomAffine(degrees = 0,translate=(0.1, 0.1)),
transforms.RandomRotation((-10,10)),
transforms.ToTensor(),
transforms.Normalize((0.1307,),(0.3081,))])
test_transform = transforms.Compose([transforms.ToTensor(),
transforms.Normalize((0.1307,),(0.3081,))])
train_batch_size = 256
learning_rate = 0.006
test_batch_size = 100
random_seed = 2
torch.manual_seed(random_seed)
torch.cuda.manual_seed_all(random_seed)
train_dataset = datasets.FashionMNIST(
root='../datasets', train=True, transform=transforms.ToTensor(), download=False)
test_dataset = datasets.FashionMNIST(
root='../datasets', train=False, transform=transforms.ToTensor(),download=False)
train_loader = DataLoader(dataset=train_dataset,batch_size=train_batch_size,shuffle=True,pin_memory=True)
test_loader = DataLoader(dataset=test_dataset,batch_size=test_batch_size,shuffle=False,pin_memory=True)
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(1 ,32, kernel_size=5,padding=2)
self.conv2 = nn.Conv2d(32 ,64, kernel_size=5,padding=2)
self.conv3 = nn.Conv2d(64 ,128,kernel_size=5,padding=2)
self.conv4 = nn.Conv2d(128,192,kernel_size=5,padding=2)
self.rblock1 = ResidualBlock(32)
self.rblock2 = ResidualBlock(64)
self.rblock3 = ResidualBlock(128)
self.rblock4 = ResidualBlock(192)
self.bn1 = nn.BatchNorm2d(32)
self.bn2 = nn.BatchNorm2d(64)
self.bn3 = nn.BatchNorm2d(128)
self.bn4 = nn.BatchNorm2d(192)
self.mp = nn.MaxPool2d(2)
self.fc1 = nn.Linear(192*7*7, 256)
self.fc6 = nn.Linear(256, 10)
def forward(self, x):
in_size = x.size(0)
x = self.conv1(x)
x = self.bn1(x)
x = F.relu(x)
x = self.rblock1(x)
x = self.conv2(x)
x = F.relu(x)
x = self.bn2(x)
x = self.rblock2(x)
x = self.mp(x)
x = self.conv3(x)
x = self.bn3(x)
x = F.relu(x)
x = self.rblock3(x)
x = self.conv4(x)
x = self.bn4(x)
x = F.relu(x)
x = self.rblock4(x)
x = self.mp(x)
x = x.view(in_size, -1)
x = F.relu(self.fc1(x))
return self.fc6(x)
os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"
torch.backends.cudnn.benchmark = True
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
torch.cuda.empty_cache()
model.to(device)
criterion = torch.nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(),lr=learning_rate,momentum=0.5)
scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='max', factor=0.5, patience=2, verbose=True, threshold=0.00005, threshold_mode='rel', cooldown=0, min_lr=0, eps=1e-08)
def train(epoch):
running_loss =0.0
for batch_idx,data in enumerate(train_loader,0):
inputs,target = data
inputs,target = inputs.to(device),target.to(device)
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs,target)
loss.backward()
optimizer.step()
running_loss+=loss.item()
if batch_idx%300==299:
train_loss_val.append((running_loss/300))
print('[%d, %5d] loss: %.3f' % (epoch + 1, batch_idx + 1, running_loss / 300))
running_loss = 0.0
def test():
correct = 0
total = 0
with torch.no_grad():
for data in test_loader:
images,labels = data
images, labels = images.to(device), labels.to(device)
outputs = model(images)
predicted = torch.max(outputs.data,dim=1)
total += labels.size(0)
correct += (predicted==labels).sum().item()
print('Accuracy on test set: %f %% [%d/%d]' % (100 * correct / total, correct, total))
return correct/total
train_epoch = []
model_accuracy = []
temp_acc = 0.0
train_loss_val = []
for epoch in range(30):
train(epoch)
acc = test()
print(epoch + 1,acc)
train_epoch.append(epoch)
model_accuracy.append(acc)
scheduler.step(acc)
plt.figure(1)
plt.plot(train_epoch, model_accuracy)
plt.grid(linestyle=':')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.show()
运行结果: