基于pytorch平台实现对MNIST数据集的分类分析(前馈神经网络、softmax)升级版

基于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):
        # 注意 F 与 nn 下的激活函数使用起来不一样的
        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()
#momentum:动量因子
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=[64,1,28,28] 做完view()后变为[64,1*28*28]=[64,784]
            # 把图片数据格式转换成与网络匹配的格式
            img = img.view(img.size(0), -1)
            # 前向传播,将图片数据传入模型中
            # out输出10维,分别是各数字的概率,即每个类别的得分
            out = model(img)
            # 这里注意参数out是64*10,label是一维的64
            loss = criterion(out, label)
            # 反向传播
            # optimizer.zero_grad()意思是把梯度置零,也就是把loss关于weight的导数变成0
            optimizer.zero_grad()
            loss.backward()
            # 这个方法会更新所有的参数,一旦梯度被如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)#元组取最大值的下表
            #
            #print('predict:',predict)
            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("") # 为了导入上层目录的d2lzh_pytorch
#import d2lzh_pytorch as d2l
from d2l import torch as d2
#from sklearn.metrics import confusion_matrix
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)  # Channel x Height x Width


batch_size = 256
if sys.platform.startswith('win'):
    num_workers = 0  # 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)

#######softmax
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)
#定义Softmax函数
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):  # lr 为学习率
    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()

#我们可以评估在任意模型 net 的准确率
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)#元组取最大值的下表
            #
            #print('predict:',predict)
            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()

你可能感兴趣的:(深度学习与神经网络,深度学习,神经网络,人工智能)