Implementación simple, pytorch+ red totalmente conectada + reconocimiento MNIST

Tabla de contenido

red.py:

tren.py

prueba.py

Resumir:


Aquí hay una implementación simple del reconocimiento de escritura a mano basada en la capa completamente conectada, la siguiente es la parte del código

Definir una estructura de red de tres niveles, donde se establecen tres redes,

La primera SimpleNet es simplemente una red de tres capas

El segundo Activation_Net agrega una función de activación después de la salida de cada capa de la red.

El tercer Batch_Net, después de cada capa de salida de red, pasa por BatchNorm1d (normalización por lotes), después de pasar por la función de activación

Aviso:

red.py:

#  开发人员:    ***
#  开发时间:    2022/7/22 20:48
#  功能作用:    未知
import torch
import torch.nn as nn

from torch.autograd import Variable
from torch import optim

#建立简单的三层全连接神经网络
class SimpleNet(nn.Module):
    def __init__(self,in_dim, out_dim, n_hidden_1, n_hidden_2):
        super(SimpleNet, self).__init__()
        self.layer1 = nn.Linear(in_dim, n_hidden_1)
        self.layer2 = nn.Linear(n_hidden_1, n_hidden_2)
        self.layer3 = nn.Linear(n_hidden_2, out_dim)

    def forward(self, x):
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        return x

class Activation_Net(nn.Module):
    def __init__(self, in_dim, out_dim, n_hidden_1, n_hidden_2):
        super(Activation_Net, self).__init__()

        self.layer1 = nn.Sequential(
            nn.Linear(in_dim, n_hidden_1),
            nn.ReLU(True)
        )
        self.layer2 = nn.Sequential(
            nn.Linear(n_hidden_1, n_hidden_2),
            nn.ReLU(True)
        )
        self.layer3 = nn.Linear(n_hidden_2, out_dim)

    def forward(self, x):
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        return x

##加batch的话,能加快收敛
class Batch_Net(nn.Module):
    def __init__(self, in_dim, out_dim, n_hidden_1, n_hidden_2):
        super(Batch_Net, self).__init__()
        self.layer1 = nn.Sequential(
            nn.Linear(in_dim, n_hidden_1),
            nn.BatchNorm1d(n_hidden_1),
            nn.ReLU(True)
        )
        self.layer2 = nn.Sequential(
            nn.Linear(n_hidden_1, n_hidden_2),
            nn.BatchNorm1d(n_hidden_2),
            nn.ReLU(True)
        )
        self.layer3 = nn.Linear(n_hidden_2, out_dim)

    def forward(self, x):
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        return x


Después de configurar la capa de red, escribe la capa de entrenamiento

Debido a que ya descargué el conjunto de datos aquí, cambié la descarga a Falso, y si es una descarga, cámbielo a VERDADERO

train_dataset =mnist.MNIST('./data', train=True, transform=data_tf, download=False)
test_dataset =mnist.MNIST('./data', train=False, transform=data_tf, download=False)

tren.py

import torch
import time
import tqdm
import numpy as np
import torch.nn as nn
from torch import optim
from torch.autograd import Variable
from torch.utils.data import DataLoader
from torchvision import transforms
from torchvision.datasets import mnist # 导入 pytorch 内置的 mnist 数据
import matplotlib.pyplot as plt
import net

##设定一些数据
batch_size = 32
learning_rate = 1e-2
num_epoches = 5

##将图片转为Tensor格式后标准化,减去均值,再除以方差
data_tf = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize([0.5], [0.5])  ##因为是灰度值图,所以是单通道
# transforms.Normalize([0.5,0.5,0.5], [0.5,0.5,0.5])  ##因为是彩色图,所以是san通道
])

train_dataset =mnist.MNIST('./data', train=True, transform=data_tf, download=False)
test_dataset =mnist.MNIST('./data', train=False, transform=data_tf, download=False)


##设置迭代器,shuffle询问是否将数据打乱,意思是产生batch_size个数据
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=False)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)


##导入网络,定义损失函数和优化函数
model = net.Batch_Net(28*28, 10, 300, 100)


if torch.cuda.is_available():
    model.cuda()

criterion = nn.CrossEntropyLoss()       ##交叉煽函数
##此函数,好像是输入【通道数,类别种类的概率】,标签【通道数,所属类别数字】
optimizer = optim.SGD(model.parameters(), lr=learning_rate, momentum=0.8)


# 开始训练
losses_men = []
acces_men = []

start = time.time()
for epoche in range(num_epoches):
    train_loss = 0
    train_acc = 0
    print()
    print(f"第 {epoche + 1} / {num_epoches} 个 epoche。。。")
    for train_img, train_label in tqdm.tqdm(train_loader):
        ## train_loader的长度为1875,意为60000图片以32为一组分为1875组
        if torch.cuda.is_available():
            ##将 train_img【32,1,28,28】 变成 【32,1,786】这样才能输入进入模型
            train_img = torch.reshape(train_img, (batch_size, 1, -1))
            train_img = Variable(train_img).cuda()
            train_label = Variable(train_label).cuda()
        else:
            train_img = torch.reshape(train_img, (batch_size, 1, -1))
            train_img = Variable(train_img)
            train_label = Variable(train_label)

        ## train_img          : 【32,1,786】
        ## 要变成  : 【32,786】
        train_img = train_img.squeeze(1)

        # 前向传播
        out = model(train_img)
        
        loss = criterion(out, train_label)
        # 反向传播
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        # print("***")
        # print(train_img.shape)
        # print(len(test_loader))

        # 记录误差
        train_loss += loss.item()

        # 计算分类的准确率
        _, idx_max = out.max(1)
        num_correct = (idx_max == train_label ).sum().item()    ##计算每次batch_size正确的个数
        acc = num_correct / train_img.shape[0]      ##正确率
        train_acc +=acc

    losses_men.append(train_loss / len(train_loader))       #这里计算的是平均损失函数
    acces_men.append(train_acc / len(train_loader))
    print()
    print("损失率为: ", losses_men)
    print("正确率为: ", acces_men)
    torch.save(model.state_dict(), './params/simple.pth')
    print("参数保存成功")

during = time.time() - start
print()
print('During Time: {:.3f} s'.format(during))

###画出LOSS曲线和准确率曲线
plt.plot(np.arange(len(losses_men)), losses_men, label ='train loss')
plt.plot(np.arange(len(acces_men)), acces_men, label ='train acc')
plt.show()

Los parámetros del modelo entrenado se guardan en la carpeta params.Si no existe dicha carpeta, debe crearla usted mismo, de lo contrario, se informará un error.

Luego viene la prueba,

prueba.py

import torch
import time
import tqdm
import numpy as np
import torch.nn as nn
from torch import optim
from torch.autograd import Variable
from torch.utils.data import DataLoader
from torchvision import transforms
from torchvision.datasets import mnist # 导入 pytorch 内置的 mnist 数据
import matplotlib.pyplot as plt
import three_MNIST


model.load_state_dict(torch.load('./params/simple.pth'))

###测试
##初始化
model.eval()
eval_loss = 0
eval_acc = 0
test_loss = 0
test_acc = 0
for data in test_loader:
    img, label = data
    img = img.view(img.size(0), -1)
    if torch.cuda.is_available():
        img = Variable(img).cuda()
        label = Variable(label).cuda()
    else:
        img = Variable(img)
        label = Variable(label)

    out = model(img)
    loss = criterion(out, label)

    # 记录误差
    test_loss += loss.item()

    # 记录准确率
    _, pred = out.max(1)
    num_correct = (pred == label).sum().item()
    acc = num_correct / label.shape[0]
    test_acc += acc

eval_loss = test_loss / len(test_loader)
eval_acc = test_acc / len(test_loader)

print("损失率为: ",eval_loss)
print("正确率为: ",eval_acc)

Resumir:

        Esta vez solo se usaron 5 rondas de Epoche para el entrenamiento.La red tiene una estructura de tres capas y tres tipos de redes.

        De hecho, desde la perspectiva de la precisión y la tasa de pérdida, SimpleNet < Activation_Net < Batch_Net

acc_tren
NET / época 1 2 3 4 5
SimpleNet 0.875 0.900 0.905 0.90788 0.909783
Activación_Net 0.883 0.949 0.964 0.972 0.978
Batch_Net 0.934 0.972 0.985 0.993 0.997
SimpleNet Activación_Net Batch_Net

 Se puede ver que la tasa de precisión es muy alta.

Supongo que te gusta

Origin blog.csdn.net/qq_42792802/article/details/125976489
Recomendado
Clasificación