深度学习:pytorch简单神经网络模型实现手写数字识别

PyTorch是一个开源的机器学习库,广泛用于计算机视觉和自然语言处理等应用。它提供了强大的GPU加速的张量计算能力,以及构建深度学习模型的动态计算图。

定义:

1. 张量(Tensor)

在PyTorch中,张量是多维数组的表示,类似于NumPy中的数组,但可以在GPU上进行计算。张量是PyTorch中最基本的数据结构,用于表示数据和模型参数。

2. 动态计算图(Dynamic Computational Graph)

PyTorch使用动态计算图(也称为自动微分系统)来构建和训练神经网络。在这种机制下,计算图在运行时构建,允许更灵活的模型设计和调试。每次执行计算时,都会构建一个新的图,这使得修改模型结构变得容易。

3. 自动微分(Autograd)

PyTorch的自动微分引擎能够自动计算梯度,这对于训练神经网络至关重要。当使用张量进行运算时,PyTorch会自动记录操作,使得反向传播变得简单。

4. 模块(Module)

torch.nn.Module是所有神经网络模块的基类。通过继承这个类,你可以定义自己的网络层、损失函数和模型。模块可以包含其他模块,支持模型的层次化设计。

5. 参数(Parameter)

在神经网络中,参数是模型的权重和偏置,它们在训练过程中被优化。在PyTorch中,ParameterTensor的一个子类,用于表示可以学习的参数。

6. 优化器(Optimizer)

优化器用于在训练过程中更新模型的参数。PyTorch提供了多种优化器,如SGD、Adam等,它们根据损失函数的梯度来调整参数。

7. 损失函数(Loss Function)

损失函数用于评估模型的预测与真实值之间的差异。常见的损失函数包括均方误差(MSE)、交叉熵损失(CrossEntropyLoss)等。

8. 数据加载器(DataLoader)

DataLoader是PyTorch中用于加载数据集的类。它提供了一种简便的方式来迭代数据集,支持批处理、打乱数据和多线程加载。

9. 训练循环(Training Loop)

训练循环是执行模型训练的代码块,通常包括前向传播、计算损失、反向传播和参数更新。

算法步骤

1. 数据准备

使用PyTorch的datasets.MNIST类加载MNIST数据集,包括训练集和测试集。数据集被转换为PyTorch张量,并使用DataLoader进行批量加载。

python 复制代码
# 导入必要的库
import torch.cuda
from torchvision import datasets
from torchvision.transforms import ToTensor

# 加载训练数据集
traning_data = datasets.MNIST(root='data', train=True, download=True, transform=ToTensor())
# 加载测试数据集
test_data = datasets.MNIST(root='data', train=False, download=True, transform=ToTensor())

# 打印训练数据集的大小
print(len(traning_data))

# 导入DataLoader工具,用于创建数据加载器
from torch.utils.data import DataLoader

# 创建训练数据加载器
train_dataloader = DataLoader(traning_data, batch_size=64)
# 创建测试数据加载器
test_dataloader = DataLoader(test_data, batch_size=64)

# 选择设备,优先使用GPU,如果没有GPU则使用CPU
device = 'cuda' if torch.cuda.is_available() else 'mps' if torch.backends.mps.is_available() else 'cpu'
# 打印选择的设备
print(f"{device}")

2. 模型构建

定义一个包含四个隐藏层和一个输出层的全连接神经网络。每个隐藏层后都使用Sigmoid激活函数。

python 复制代码
# 导入PyTorch的神经网络模块
import torch.nn as nn

# 定义神经网络模型
class NeuralNetwork(nn.Module):
    def __init__(self):
        super().__init__()
        # 定义一个展平层,将图像数据展平为一维向量
        self.flatten = nn.Flatten()
        # 定义四个隐藏层和一个输出层
        self.hidden1 = nn.Linear(28 * 28, 512)
        self.hidden2 = nn.Linear(512, 256)
        self.hidden3 = nn.Linear(256, 128)
        self.hidden4 = nn.Linear(128, 64)
        self.out = nn.Linear(64, 10)

    def forward(self, x):
        # 展平输入图像
        x = self.flatten(x)
        # 通过四个隐藏层进行前向传播
        x = self.hidden1(x)
        x = torch.sigmoid(x)
        x = self.hidden2(x)
        x = torch.sigmoid(x)
        x = self.hidden3(x)
        x = torch.sigmoid(x)
        x = self.hidden4(x)
        x = torch.sigmoid(x)
        # 通过输出层得到最终的预测结果
        x = self.out(x)
        return x

# 实例化模型并将其转移到选择的设备上
model = NeuralNetwork().to(device)

3.定义训练函数

python 复制代码
# 定义训练函数
def train(dataloader, model, loss_fn, optimizer):
    model.train()  # 设置模型为训练模式
    batch_size_num = 1
    for x, y in dataloader:
        x, y = x.to(device), y.to(device)  # 将数据转移到选择的设备上
        pred = model(x)  # 进行前向传播
        loss = loss_fn(pred, y)  # 计算损失
        optimizer.zero_grad()  # 清空梯度
        loss.backward()  # 反向传播
        optimizer.step()  # 更新参数
        loss_value = loss.item()
        if batch_size_num % 400 == 0:
            print(f"{loss_value} {batch_size_num}")
        batch_size_num += 1

4.定义测试函数

python 复制代码
# 定义测试函数
def test(dataloader, model, loss_fn):
    size = len(dataloader.dataset)
    num_batches = len(dataloader)
    model.eval()  # 设置模型为评估模式
    test_loss, correct = 0, 0
    with torch.no_grad():  # 关闭梯度计算
        for x, y in dataloader:
            x, y = x.to(device), y.to(device)
            pred = model(x)
            test_loss += loss_fn(pred, y).item()
            correct += (pred.argmax(1) == y).type(torch.float).sum().item()
    test_loss /= num_batches
    correct /= size
    print(f"Test result: \n Accuracy: {(100 * correct)}%, Avg loss: {test_loss}")

5. 损失函数和优化器

使用交叉熵损失函数和Adam优化器进行模型训练。在训练过程中,每400个批次输出一次损失值,以监控训练进度。

python 复制代码
# 定义损失函数和优化器
loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)

6. 测试过程

在训练完成后,使用测试数据集评估模型的性能。计算测试集上的准确率和平均损失。

python 复制代码
# 进行一次训练和测试
train(train_dataloader, model, loss_fn, optimizer)
test(test_dataloader, model, loss_fn)

7. 多轮训练

进行25轮训练,每轮结束后在测试集上评估模型性能。

python 复制代码
# 进行多个epoch的训练
epochs = 25
for t in range(epochs):
    print(f"epoch {t + 1}\n")
    train(train_dataloader, model, loss_fn, optimizer)
print("done")

# 在所有训练epoch完成后,再次测试模型的性能
test(test_dataloader, model, loss_fn)

实验结果

算法分析

  1. 模型结构:本实验使用的是一个简单的全连接神经网络,没有使用卷积层或池化层,这限制了模型对图像特征的提取能力。

  2. 激活函数:Sigmoid激活函数可能导致梯度消失问题,影响训练效果。可以考虑使用ReLU等其他激活函数。

  3. 优化器:Adam优化器在大多数情况下表现良好,但根据具体问题,可能需要调整学习率和其他超参数。

  4. 训练策略:实验中没有使用验证集来调整模型参数,这可能导致过拟合。可以考虑引入验证集来监控模型的泛化能力。

完整代码

python 复制代码
import torch.cuda
from torchvision import datasets
from torchvision.transforms import ToTensor
traning_data=datasets.MNIST(root='data',train=True,download=True,transform=ToTensor())
test_data=datasets.MNIST(root='data',train=False,download=True,transform=ToTensor())
print(len(traning_data))

# from matplotlib import pyplot as plt
# figure=plt.figure()
# for i in range(9):
#     img,label=traning_data[i+59000]
#     figure.add_subplot(3,3,i+1)
#     plt.title(label)
#     plt.axis("off")
#     plt.imshow(img.squeeze(),cmap="gray")
#     a=img.squeeze()
# plt.show()
from torch.utils.data import DataLoader
train_dataloader=DataLoader(traning_data,batch_size=64)
test_dataloader=DataLoader(test_data,batch_size=64)

device='cuda' if torch.cuda.is_available() else 'mps' if torch.backends.mps.is_available() else 'cpu'
print(f"{device}")
import torch.nn as nn
class NeuralNetwork(nn.Module):
    def __init__(self):
        super().__init__()
        self.flatten=nn.Flatten()#展开,创建一个展开对象flatten,输入层
        self.hidden1=nn.Linear(28*28,512)
        self.hidden2=nn.Linear(512,256)
        self.hidden3=nn.Linear(256,128)
        self.hidden4=nn.Linear(128,64)
        self.out=nn.Linear(64,10)

    def forward(self,x):
        x=self.flatten(x)

        x=self.hidden1(x)
        x=torch.sigmoid(x)

        x=self.hidden2(x)
        x = torch.sigmoid(x)

        x = self.hidden3(x)
        x = torch.sigmoid(x)

        x = self.hidden4(x)
        x = torch.sigmoid(x)
        x=self.out(x)
        return x
model=NeuralNetwork().to(device)
# print(model)
def train(dataloader,model,loss_fn,optimzier):
    model.train()
    batch_size_num=1
    for x,y in dataloader:
        x,y=x.to(device),y.to(device)
        pred=model.forward(x)
        loss=loss_fn(pred,y)
        optimzier.zero_grad()
        loss.backward()
        optimzier.step()
        loss_value=loss.item()
        if batch_size_num%400==0:

            print(f"{loss_value} {batch_size_num}")
        batch_size_num+=1


def test(dataloader,model,loss_fn):
    size=len(dataloader.dataset)
    num_batches=len(dataloader)
    model.eval()
    test_loss,correct=0,0
    with torch.no_grad():
        for x,y in dataloader:
            x,y=x.to(device),y.to(device)
            pred=model.forward(x)
            test_loss+=loss_fn(pred,y).item()
            correct+=(pred.argmax(1)==y).type(torch.float).sum().item()
            a=(pred.argmax(1)==y)
            b=(pred.argmax(1)==y).type(torch.float)
    test_loss/=num_batches
    correct/=size
    print(f"Test result: \n Accuracy: {(100*correct)}%, Avg loss: {test_loss}")



loss_fn=nn.CrossEntropyLoss()
optimizer=torch.optim.Adam(model.parameters(),lr=0.001)
train(train_dataloader,model,loss_fn,optimizer)
test(test_dataloader,model,loss_fn)

epochs=25
for t in range(epochs):
    print(f"epoch{t+1}\n")
    train(train_dataloader,model,loss_fn,optimizer)
print("done")
test(test_dataloader,model,loss_fn)

结论

通过本实验,我们成功地使用PyTorch构建了一个简单的神经网络,并在MNIST数据集上进行了训练和测试。实验结果表明,模型能够逐渐学习并提高准确率。然而,为了进一步提高模型性能,可以考虑使用更复杂的模型结构、调整激活函数和优化器,以及引入验证集等策略。

相关推荐
Guofu_Liao1 小时前
大语言模型---LoRA简介;LoRA的优势;LoRA训练步骤;总结
人工智能·语言模型·自然语言处理·矩阵·llama
朝九晚五ฺ3 小时前
【Linux探索学习】第十四弹——进程优先级:深入理解操作系统中的进程优先级
linux·运维·学习
Swift社区4 小时前
LeetCode - #139 单词拆分
算法·leetcode·职场和发展
秀儿还能再秀4 小时前
神经网络(系统性学习三):多层感知机(MLP)
神经网络·学习笔记·mlp·多层感知机
Kent_J_Truman4 小时前
greater<>() 、less<>()及运算符 < 重载在排序和堆中的使用
算法
猫爪笔记4 小时前
前端:HTML (学习笔记)【1】
前端·笔记·学习·html
IT 青年5 小时前
数据结构 (1)基本概念和术语
数据结构·算法
ZHOU_WUYI5 小时前
3.langchain中的prompt模板 (few shot examples in chat models)
人工智能·langchain·prompt
Dong雨5 小时前
力扣hot100-->栈/单调栈
算法·leetcode·职场和发展
如若1235 小时前
主要用于图像的颜色提取、替换以及区域修改
人工智能·opencv·计算机视觉