基于pytorch平台实现对MNIST数据集的分类分析(前馈神经网络、softmax)进阶版
文章目录
- 基于pytorch平台实现对MNIST数据集的分类分析(前馈神经网络、softmax)进阶版
- 一、基于“前馈神经网络”模型(升级版)
- 二、基于“softmax”模型(升级版)
一、基于“前馈神经网络”模型(升级版)
import numpy as np
import torch
import matplotlib.pyplot as plt
from torchvision.datasets import mnist
from torchvision import transforms
from torch.utils.data import DataLoader
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
train_batch_size = 64
test_batch_size = 128
learning_rate = 0.01
nums_epoches = 20
lr = 0.1
momentum = 0.5
train_dataset = mnist.MNIST('./data', train=True, transform=transforms.ToTensor(), target_transform=None, download=True)
test_dataset = mnist.MNIST('./data', train=False, transform=transforms.ToTensor(), target_transform=None, download=False)
train_loader = DataLoader(train_dataset, batch_size=train_batch_size, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=test_batch_size, shuffle=False)
class model(nn.Module):
def __init__(self, in_dim, hidden_1, hidden_2, out_dim):
super(model, self).__init__()
self.layer1 = nn.Sequential(nn.Linear(in_dim, hidden_1, bias=True), nn.BatchNorm1d(hidden_1))
self.layer2 = nn.Sequential(nn.Linear(hidden_1, hidden_2, bias=True), nn.BatchNorm1d(hidden_2))
self.layer3 = nn.Sequential(nn.Linear(hidden_2, out_dim))
def forward(self, x):
x = F.relu(self.layer1(x))
x = F.relu(self.layer2(x))
x = self.layer3(x)
return x
model = model(28*28,300,100,10)
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(),lr=lr,momentum=momentum)
def train():
losses = []
acces = []
eval_losses = []
eval_acces = []
for epoch in range(nums_epoches):
train_loss = 0
train_acc = 0
model.train()
if epoch % 5 == 0:
optimizer.param_groups[0]['lr'] *= 0.1
for img, label in train_loader:
img = img.view(img.size(0), -1)
out = model(img)
loss = criterion(out, label)
optimizer.zero_grad()
loss.backward()
optimizer.step()
train_loss += loss.item()
_, pred = out.max(1)
num_correct = (pred == label).sum().item()
acc = num_correct / img.shape[0]
train_acc += acc
losses.append(train_loss / len(train_loader))
acces.append(train_acc / len(train_loader))
eval_loss = 0
eval_acc = 0
model.eval()
for img, label in test_loader:
img = img.view(img.size(0), -1)
out = model(img)
loss = criterion(out, label)
optimizer.zero_grad()
loss.backward()
optimizer.step()
eval_loss += loss.item()
_, pred = out.max(1)
num_correct = (pred == label).sum().item()
acc = num_correct / img.shape[0]
eval_acc += acc
eval_losses.append(eval_loss / len(test_loader))
eval_acces.append(eval_acc / len(test_loader))
print('epoch:{},Train Loss:{:.4f},Train Acc:{:.4f},Test Loss:{:.4f},Test Acc:{:.4f}'
.format(epoch, train_loss / len(train_loader), train_acc / len(train_loader),
eval_loss / len(test_loader), eval_acc / len(test_loader)))
plt.title('trainloss')
plt.plot(np.arange(len(losses)), losses)
plt.legend(['Train Loss'], loc='upper right')
from sklearn.metrics import confusion_matrix
import seaborn as sns
def test():
correct = 0
total = 0
y_predict=[]
y_true=[]
with torch.no_grad():
for data in test_loader:
input, target = data
input = input.view(input.size(0), -1)
output = model(input)
_, predict = torch.max(output.data, dim=1)
total += target.size(0)
correct += (predict == target).sum().item()
y_predict.extend(predict.tolist())
y_true.extend(target.tolist())
print('正确率:', correct / total)
print('correct=', correct)
sns.set()
f, ax = plt.subplots()
C2 = confusion_matrix(y_true, y_predict, labels=[0, 1, 2,3,4,5,6,7,8,9])
print(C2)
plt.imshow(C2, cmap=plt.cm.Blues)
plt.xticks(range(10),labels=[0, 1, 2,3,4,5,6,7,8,9] , rotation=45)
plt.yticks(range(10),labels=[0, 1, 2,3,4,5,6,7,8,9])
plt.colorbar()
plt.xlabel('True Labels')
plt.ylabel('Predicted Labels')
plt.title('Confusion matrix (acc=' + str(correct / total)+ ')')
plt.show()
train()
test()
二、基于“softmax”模型(升级版)
import torch
from torch import nn
import torchvision
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
import time
import sys
sys.path.append("")
from d2l import torch as d2
import numpy as np
mnist_train = torchvision.datasets.MNIST(root='~/Datasets/MNIST', train=True, download=True, transform=transforms.ToTensor())
mnist_test = torchvision.datasets.MNIST(root='~/Datasets/MNIST', train=False, download=True, transform=transforms.ToTensor())
print(type(mnist_train))
print(len(mnist_train), len(mnist_test))
feature, label = mnist_train[0]
print(feature.shape, label)
batch_size = 256
if sys.platform.startswith('win'):
num_workers = 0
else:
num_workers = 4
train_iter = torch.utils.data.DataLoader(mnist_train, batch_size=batch_size, shuffle=True, num_workers=num_workers)
test_iter = torch.utils.data.DataLoader(mnist_test, batch_size=batch_size, shuffle=False, num_workers=num_workers)
num_inputs = 784
num_outputs = 10
W = torch.normal(0, 0.01, size=(num_inputs, num_outputs), requires_grad=True)
b = torch.zeros(num_outputs, requires_grad=True)
def softmax(X):
X_exp = torch.exp(X)
partition = X_exp.sum(1, keepdim=True)
return X_exp / partition
def net(X):
return softmax(torch.matmul(X.reshape((-1, W.shape[0])), W) + b)
def cross_entropy(y_hat, y):
return - torch.log(y_hat.gather(1, y.view(-1, 1)))
def sgd(params, lr, batch_size):
for param in params:
param.data -= lr * param.grad / batch_size
def accuracy(y_hat, y):
return (y_hat.argmax(dim=1) == y).float().mean().item()
def evaluate_accuracy(data_iter, net):
"""计算在指定数据集上模型的精度。"""
if isinstance(net, torch.nn.Module):
net.eval()
metric = d2.Accumulator(2)
for X, y in data_iter:
metric.add(accuracy(net(X), y), y.numel())
return metric[0] / metric[1]
num_epochs,lr=20,0.1
def train_ch3(net, train_iter, test_iter, loss, num_epochs, batch_size, params=None, lr=None):
for epoch in range(num_epochs):
train_l_sum, train_acc_sum, n = 0.0, 0.0, 0
for X, y in train_iter:
y_hat = net(X)
l = loss(y_hat, y).sum()
if params is not None and params[0].grad is not None:
for param in params:
param.grad.data.zero_()
l.backward()
sgd(params, lr, batch_size)
train_l_sum += l.item()
train_acc_sum += (y_hat.argmax(dim=1) == y).sum().item()
n += y.shape[0]
test_acc = evaluate_accuracy(test_iter, net)
print('epoch %d, loss %.6f, train_acc %.6f, test_acc %.6f'
%(epoch+1, train_l_sum / n, train_acc_sum/n, test_acc))
from sklearn.metrics import confusion_matrix
import seaborn as sns
def test():
correct = 0
total = 0
y_predict=[]
y_true=[]
with torch.no_grad():
for data in test_iter:
input, target = data
output = net(input)
_, predict = torch.max(output.data, dim=1)
total += target.size(0)
correct += (predict == target).sum().item()
y_predict.extend(predict.tolist())
y_true.extend(target.tolist())
print('正确率:', correct / total)
print('correct=', correct)
sns.set()
f, ax = plt.subplots()
C2 = confusion_matrix(y_true, y_predict, labels=[0, 1, 2,3,4,5,6,7,8,9])
print(C2)
plt.imshow(C2, cmap=plt.cm.Blues)
plt.xticks(range(10),labels=[0, 1, 2,3,4,5,6,7,8,9] , rotation=45)
plt.yticks(range(10),labels=[0, 1, 2,3,4,5,6,7,8,9])
plt.colorbar()
plt.xlabel('True Labels')
plt.ylabel('Predicted Labels')
plt.title('Confusion matrix (acc=' + str(correct / total)+ ')')
plt.show()
train_ch3(net, train_iter, test_iter, cross_entropy, num_epochs, batch_size, [W, b], lr)
test()