简单实现,pytorch+全连接网络+MNIST识别

目录

net.py:

train.py

test.py

总结:


在这里简单实现一下基于全连接层的手写体识别,一下是代码部分

定义三层网络结构,在这里设定了三个网络,

第一个 SimpleNet,单纯就是三层网络

第二个 Activation_Net,在每层网络输出后面添加了激活函数

第三个 Batch_Net, 在每层网络输出后经过BatchNorm1d(批标准化),在经过激活函数

注意:

net.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


设定好网络层后,就编写训练层

因为数据集我这里已经下载完了,所以将download改为了False,若为下载则,改为TRUE

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

train.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()

训练好的模型参数保存在文件夹params下,如果没有这个文件夹的话,需自己创建,否则报错

接下来是测试,

test.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)

总结:

        本次只用了5轮Epoche进行训练,网络是三层结构,三种网络

        其实从准确率和损失率来看,SimpleNet < Activation_Net < Batch_Net

acc_train
NET / epoch12345
SimpleNet0.8750.9000.9050.907880.909783
Activation_Net0.8830.9490.9640.9720.978
Batch_Net0.9340.9720.9850.9930.997
SimpleNetActivation_NetBatch_Net

 可以看出,正确率很高了

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个使用PyTorch编写的全连接神经网络MNIST识别示例: ```python import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms # 定义超参数 batch_size = 64 learning_rate = 0.01 num_epochs = 10 # 载入MNIST数据集 transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))]) train_dataset = datasets.MNIST(root='./data/', train=True, transform=transform, download=True) test_dataset = datasets.MNIST(root='./data/', train=False, transform=transform, download=True) train_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True) test_loader = torch.utils.data.DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False) # 定义全连接神经网络模型 class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.fc1 = nn.Linear(28*28, 512) self.fc2 = nn.Linear(512, 256) self.fc3 = nn.Linear(256, 10) self.relu = nn.ReLU() self.dropout = nn.Dropout(p=0.5) def forward(self, x): x = x.view(-1, 28*28) x = self.relu(self.fc1(x)) x = self.dropout(x) x = self.relu(self.fc2(x)) x = self.dropout(x) x = self.fc3(x) return x model = Net() # 定义优化器和损失函数 criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(model.parameters(), lr=learning_rate) # 训练模型 for epoch in range(num_epochs): for i, (images, labels) in enumerate(train_loader): # 前向传播、计算损失、反向传播、更新权重 outputs = model(images) loss = criterion(outputs, labels) optimizer.zero_grad() loss.backward() optimizer.step() # 打印训练日志 if (i+1) % 100 == 0: print("Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}".format(epoch+1, num_epochs, i+1, len(train_loader), loss.item())) # 测试模型 model.eval() with torch.no_grad(): correct = 0 total = 0 for images, labels in test_loader: outputs = model(images) _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() print('Test Accuracy of the model on the 10000 test images: {} %'.format(100 * correct / total)) ``` 该模型定义了一个具有3个全连接层的神经网络模型,其中第一层具有512个神经元,第二层具有256个神经元,第三层输出10个类别的概率分布。模型使用ReLU激活函数和Dropout正则化。在训练过程中,使用了交叉熵损失函数和随机梯度下降优化器。最终,在测试集上计算了模型的准确度。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值