当前位置: 首页 > article >正文

深度学习:神经网络--手写数字识别

目录

一、datasets

1.datasets简介

2.主要特点

二、MNIST

三、使用神经网络实现手写数字识别

1.创建数据加载器

2.判断是否使用GPU

3.创建神经网络

4.创建训练集模型

5.创建测试集模型

6.创建损失函数和优化器并训练


一、datasets

1.datasets简介

        datasets是一个广泛使用的库,尤其在机器学习和自然语言处理领域,用于方便地加载和处理各种数据集。它提供了标准化的接口,使得数据集的访问、处理和分割变得更加简单。

 

2.主要特点

  1. 丰富的数据集库

    提供了数百个公开数据集,涵盖不同领域,如文本、图像、音频等。
  2. 简化数据加载

    只需几行代码即可加载数据集,支持多种格式(如 CSV、JSON、文本文件等)。
  3. 高效的数据处理

    提供数据预处理功能,如分词、编码、数据增强等,方便进行数据清洗和转换。
  4. 数据集分割

    支持轻松地将数据集分为训练集、验证集和测试集。
  5. 自定义数据集

    用户可以自定义数据集,方便地与现有数据集结合使用。
  6. 与深度学习框架的兼容性

    可以与 PyTorch、TensorFlow 等深度学习框架无缝集成,便于模型训练。

 

二、MNIST

  • MNIST 是一个经典的手写数字识别数据集,广泛用于机器学习和计算机视觉领域的研究和教学。
  • 它包含 70,000 张 28x28 像素的灰度图像,分为 60,000 张训练样本和 10,000 张测试样本,每张图像对应一个 0 到 9 的数字标签。

代码实现:

import torch
from torch import nn  # 导入神经网络模块
from torch.utils.data import DataLoader  # 数据包管理工具,打包数据
from torchvision import datasets  # 封装了很多与图像相关的模型,数据集
from torchvision.transforms import ToTensor  # 数据转换,张量,将其他类型的数据转换为tensor张量

'''下载训练数据集(包含训练图片和标签)'''
train_data = datasets.MNIST(
    root='data'
    , train=True
    , download=True
    , transform=ToTensor()  # 张量,图片是不能直接传入神经网络模型
)  # 对于pytorch库能够识别的数据一般是tensor张量.

'''下载测试数据集(包含训练图片和标签)'''
test_data = datasets.MNIST(
    root='data'
    , train=False
    , download=True
    , transform=ToTensor()
)  # NumPy 数组只能在CPU上运行.Tensor可以在GPU上运行,这在深度学习应用中可以显著提高计算速度.
print(len(train_data))

'''展示手写数字图片'''
import matplotlib.pyplot as plt

figure = plt.figure()
for i in range(9):
    img, label = train_data[i + 100]
    figure.add_subplot(3, 3, i + 1)
    plt.title(label)
    plt.axis('off')
    plt.imshow(img.squeeze(), cmap='gray')
    a = img.squeeze()
plt.show()

输出:

 

三、使用神经网络实现手写数字识别

1.创建数据加载器

  • 对数据进行打包
  • 通过打包数据,可以提高工作效率,简化数据管理流程,并提升模型的训练和推理性能。
'''
创建数据DataLoader(数据加载器)
    batch_size:将数据集分成多份,每一份为batch_size个数据.
            优点:可以减少内存的使用,提高训练速度.
'''
train_dataloader = DataLoader(train_data, batch_size=64)  # 64张图片为一个包
test_dataloader = DataLoader(test_data, batch_size=64)
for x, y in test_dataloader:
    print(f"shape of x [N ,C,H,W]:{x.shape}")
    print(f"shape of y :{y.shape} {y.dtype}")
    break

输出:

  • 第一行输出表示一个包64张一个通道的图片,每张图片像素大小为28*28
  • 第二行输出表示包的大小为64,数据类型为torch里的int64
shape of x [N ,C,H,W]:torch.Size([64, 1, 28, 28])
shape of y :torch.Size([64]) torch.int64

 

2.判断是否使用GPU

'''判断当前设备是否支持GPU mps是苹果m系列芯片GPU'''
device = 'cuda' if torch.cuda.is_available() else 'mps' if torch.backends.mps.is_avaibale() else 'cpu'
print(f"using {device} device")

输出:

using cuda device

 

3.创建神经网络

'''创建神经网络类'''

class NeuralNetwork(nn.Module):
    def __init__(self):
        super().__init__()  # 继承的父类初始化
        self.flatten = nn.Flatten()  # 展开,创建一个展开对象flatten
        self.hidden1 = nn.Linear(28 * 28, 512)  # 第1个参数:有多少个神经元传入进来,第2个参数:有多少个数据传出去 前一层神经元的个数,当前本层神经元个数
        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):  # 前向传播,你得告诉它,数据的流向.是神经网络层连接起来,函数名称不能改.当你调用forward函数的时候,传入进来的图像数据
        x = self.flatten(x)  # 图像进行展开
        x = self.hidden1(x)
        x = torch.relu(x)  # 激活函数,relu,tanh,sigmod  relu没有梯度消失问题,且计算消耗大大降低
        x = self.hidden2(x)
        x = torch.relu(x)
        x = self.hidden3(x)
        x = torch.relu(x)
        x = self.hidden4(x)
        x = torch.relu(x)
        x = self.out(x)
        return x

model = NeuralNetwork().to(device)  # 把刚刚创建的模型传入到GPU
print(model)

输出:

  • 输出的就是神经网络的模型
  • 输入层--隐藏层1--隐藏层2--隐藏层3--隐藏层4--输出层
  • 每一层的输入神经元,输出神经元,偏置项
NeuralNetwork(
  (flatten): Flatten(start_dim=1, end_dim=-1)
  (hidden1): Linear(in_features=784, out_features=512, bias=True)
  (hidden2): Linear(in_features=512, out_features=256, bias=True)
  (hidden3): Linear(in_features=256, out_features=128, bias=True)
  (hidden4): Linear(in_features=128, out_features=64, bias=True)
  (out): Linear(in_features=64, out_features=10, bias=True)
)

 

4.创建训练集模型

def train(dataloader, model, loss_fn, optimizer):
    model.train()  # 告诉模型,我要开始训练,模型中w进行随机化操作,已经更新w.在训练过程中,w会被修改的
    # pytorch提供2种方式来切换训练和测试的模式,分别是:model.train()和 model.eval().
    # 一般用法是: 在训练开始之前写上model.trian(),在测试时写上model.eval().
    batch_size_num = 1
    for x, y in dataloader:
        x, y = x.to(device), y.to(device)  # 把训练数据集和标签传入CPU或GPU
        pred = model.forward(x)  # 向前传播
        loss = loss_fn(pred, y)  # 通过交叉熵损失函数计算损失值loss

        optimizer.zero_grad()  # 梯度值清零
        loss.backward()  # 反向传播计算得到每个参数的梯度值w
        optimizer.step()  # 根据梯度更新网络w参数

        loss_value = loss.item()  # 从tensor数据中提取数据出来,tensor获取损失值
        if batch_size_num % 200 == 0:
            print(f"loss:{loss_value:>7f} [number:{batch_size_num}]")
        batch_size_num += 1

 

5.创建测试集模型

def test(dataloader, model, loss_fn):
    size = len(dataloader.dataset)
    num_batches = len(dataloader)
    model.eval()  # 测试,w就不能再更新。
    test_loss, correct = 0, 0
    with torch.no_grad():  # 一个上下文管理器,关闭梯度计算。当你确认不会调用Tensor.backward()的时候。这可以减少计算所占用的消耗
        for x, y in dataloader:
            x, y = x.to(device), y.to(device)
            pred = model.forward(x)
            test_loss += loss_fn(pred, y).item()  # test loss是会自动累加每一个批次的损失值
            correct += (pred.argmax(1) == y).type(torch.float).sum().item()
            a = (pred.argmax(1) == y)  # dim=1表示每一行中的最大值对应的索引号,dim=0表示每一列中的最大值对应的索引号
            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}")

 

6.创建损失函数和优化器并训练

loss_fn = nn.CrossEntropyLoss()  # 处理多分类 损失函数
optimizer = torch.optim.Adam(model.parameters(), lr=0.0012)  #
# params:要训练的参数,一般我们传入的都是model.parameters()
# lr:leqrning rate学习率,也就是步长

epochs = 4  # 到底选择多少呢?
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)

输出:

  • 可以看到每一轮之后模型损失值都在变小,说明模型在进行优化
Epoch 1
--------------
loss:0.459520 [number:200]
loss:0.307480 [number:400]
loss:0.213908 [number:600]
loss:0.196316 [number:800]
Epoch 2
--------------
loss:0.175202 [number:200]
loss:0.251854 [number:400]
loss:0.085344 [number:600]
loss:0.091463 [number:800]
Epoch 3
--------------
loss:0.050711 [number:200]
loss:0.184462 [number:400]
loss:0.043357 [number:600]
loss:0.056628 [number:800]
Epoch 4
--------------
loss:0.022849 [number:200]
loss:0.125797 [number:400]
loss:0.019434 [number:600]
loss:0.023895 [number:800]
Done!
Test result: 
 Accuracy: 96.58%, Avg loss: 0.14490024165602944

http://www.kler.cn/a/320181.html

相关文章:

  • 网络爬虫 Python-(初始篇1 后期照样有)
  • AcWing 1234. 倍数问题(周二)
  • 软件测试基础三十 (Python + Flask实现Mock平台搭建)
  • 已有docker增加端口号,不用重新创建Docker
  • Debezium-MySqlConnectorTask
  • vscode文件重定向输入输出(竞赛向)
  • RocketMQ消息重试机制解析!
  • 优化java中 HashMap 的容量](capacity值)
  • pytest - 多线程提速
  • C# 串口通信的简单概述
  • Delphi 12.2 新出的 WebStencil 组件和 Quill 编辑器配合的问题
  • [uni-app]小兔鲜-02项目首页
  • spark,poi,jar包冲突(commons.io)
  • Mora:多智能体框架实现通用视频生成
  • K8s Fedora单机版
  • 人生苦短,我用Python✌
  • 创业者必备的7个AI工具
  • Vue 入门之 computed 计算属性
  • 进阶SpringBoot之 Dubbo 及 Zookeeper 安装
  • SPSS26统计分析笔记——5 卡法检验
  • 828华为云征文|华为云Flexus云服务器X实例——部署EduSoho网校系统、二次开发对接华为云视频点播实现CDN加速播放
  • 【机器学习】——线性回归(自我监督学习)
  • 关于ollama 在mac的部署问题
  • 在nuxt中集成mars3d
  • 极狐GitLab 17.4 重点功能解读【四】
  • 基于深度学习的人机情感交互