神经网络识别数字图像案例

学习资料:从零设计并训练一个神经网络,你就能真正理解它了_哔哩哔哩_bilibili

这个视频讲得相当清楚。本文是学习笔记,不是原创,图都是从视频上截图的。

1. 神经网络

2. 案例说明

具体来说,设计一个三层的神经网络。以数字图像作为输入,经过神经网络的计算,识别出图像中的数字是几,从而实现数字图像的分类。

3. 视频讲解内容的提纲

4. 神经网络的设计和实现

我们要处理的数据是28*28像素的灰色通道图像。

这样的灰色图像包括了28*28=784个数据点。需要先将他展平为1*784大小的向量。然后将这个向量输入到神经网络中。

用一个三层神经网络处理图片对应的向量X。输入成需要接收784维的图片向量X。X里面每个维度的数据都有一个神经元来接收。因此输入层要包含784个神经元。

隐藏成用于特征提取特征向量,将输入的特征向量处理成更高级的特征向量。

因为手写数字图像识别并不复杂,所以将隐藏层的神经元个数设置为256。这样,输入层和隐藏层之间就会有个784*256的线性层。它可以将一个784维的输入向量转换为256维的输出向量。

该输出向量会继续向前传播到达输出层。

由于最终要将数字图像识别为0~9,十种可能的数字。因此,输出层需要定义10个神经元,对应这十种数字。

256维的向量在经过隐藏层和输出层之间的线性层计算后,就得到了10维的输出结果。这个10维的向量就代表了10个数字的预测得分。

为了继续得到输出层的预测概率,还要将输出层的输出输入到softmax层。softmax层会将10维的向量转换为10个概率值p0~p9。p0~p9相加的总和等于1.

5. 神经网络的Pytorch实现

复制代码
import torch
from torch import nn

# 定义神经网络Network
class Network(nn.Module):
    def __init__(self):
        super().__init__()
        # 线性层1,输入层和隐藏层之间的线性层
        self.layer1 = nn.Linear(784, 258)
        # 线性层2,隐藏层和输出层之间的线性层
        self.layer2 = nn.Linear(256, 10)
    # 在前向传播,forward函数中,输入为图像x
    def forward(self, x):
        x = x.view(-1, 28 * 28) # 使用view函数,将x展平
        x = self.layer1(x) # 将x输入到layer1
        x = torch.relu(x) # 使用relu激活
        return self.layer2(x) # 输入至layer2计算结果

    # 这里没有直接定义softmax层,因为后面会使用CrossEntropyLoss损失函数
    # 在这个损失函数中,会实现softmax的计算

6. 训练数据的准备和处理

复制代码
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader

# 初学只要知道大致的数据处理流程即可
if __name__ == '__main__'
    # 实现图像的预处理pipeline
    transform = trnasforms.Compose([
        # 转换成单通道灰度图
        transforms.Grayscale(num_output_channels=1),
        # 转换为张量
        transforms.ToTensor()
    ])

    # 使用ImageFolder函数,读取数据文件夹,构建数据集dataset
    # 这个函数会将保持数据的文件夹的名字,作为数据的标签,组织数据
    train_dataset = datasets.ImageFolder(root='./mnist_images/train', transform=transform)
    test_dataset = datasets.ImageFolder(root='./mnist_images/test', transform=transform)

    # 打印他们的长度
    print("train_dataset length: ", len(train_dataset))
    print("test_dataset length: ", len(test_dataset))

    # 使用train_loader, 实现小批量的数据读取
    # 这里设置小批量的大小,batch_size=64. 也就是每个批次,包括64个数据
    train_loader = DataLoader(train_datase, batch_size=64, shuffle=True)
    # 打印train_loader的长度
    print("train_loader length: ", len(train_loader))
    # 6000个训练数据,如果每个小批量,读入64个样本,那么60000个数据会被分成938组
    # 938*64=60032,说明最后一组不够64个数据

    # 循环遍历train_loader
    # 每一次循环,都会取出64个图像数据,作为一个小批量batch
    for batch_idx, (data, label) in enumerate(train_loader)
        if batch_idx == 3:
            break
        print("batch_idx: ", batch_idx)
        print("data.shape: ", data.shape) # 数据的尺寸
        print("label: ", label.shape) # 图像中的数字
        print(label)

7. 模型的训练和测试

复制代码
import torch
from torch import nn
from torch import optim
from model import Network
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader

if __name__ == '__main__'
    # 图像的预处理
    transform = transforms.Compose([
        transforms.Grayscale(num_output_channels=1),
        transforms.ToTensor()
    ])

    # 读入并构造数据集
    train_dataset = datasets.ImageFolder(root='./mnist_images/train', transform=transform)
    print("train_dataset length: ", len(train_dataset))

    # 小批量的数据读入
    train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
    print("train_loader length: ", len(train_loader))

    # 在使用Pytorch训练模型时,需要创建三个对象:
    model = Network() # 1.模型本身,就是我们设计的神经网络
    optimizer = optim.Adam(model.parameters()) #2.优化器,优化模型中的参数
    criterion = nn.CrossEntropyLoss() #3.损失函数,分类问题,使用交叉熵损失误差

    # 进入模型的循环迭代
    # 外层循环,代表了整个训练数据集的遍历次数
    for epoch in range(10):
        # 内层循环使用train_loader, 进行小批量的数据读取
        for batch_idx, (data, label) in enumerate(train_loader):
            # 内层每循环一次,就会进行一次梯度下降算法
            # 包括了5个步骤
            # 这5个步骤是使用pytorch框架训练模型的定式,初学时先记住即可
            # 1. 计算神经网络的前向传播结果
            output = model(data)
            # 2. 计算output和标签label之间的损失loss
            loss = criterion(output, label)
            # 3. 使用backward计算梯度
            loss.backward()
            # 4. 使用optimizer.step更新参数
            optimizer.step()
            # 5.将梯度清零
            optimizer.zero_grad()

            if batch_idx % 100 == 0:
                print(f"Epoch {epoch + 1}/10"
                      f"| Batch {batch_idx}/{len(train_loader)}"
                      f"| Loss: {loss.item():.4f}"
                      )
    torch.save(model.state_dict(), 'mnist.pth')

复制代码
from model import Network
from torchvision import transforms
from torchvision import datasets
import torch

if __name__ == '__main__'
    transform = transforms.Compose([
        transforms.Grayscale(num_output_channels=1),
        transforms.ToTensor()
    ])
    # 读取测试数据集
    test_dataset = datasets.ImageFolder(root='./mnist_images/test', transform=transform)
    print("test_dataset length: ", len(test_dataset))

    model = Network() # 定义神经网络模型
    model.load_state_dict(torch.load('mnist.pth')) # 加载刚刚训练好的模型文件

    rigth = 0 # 保存正确识别的数量
    for i, (x, y) in enumerate(test_dataset):
        output = model(x) # 将其中的数据x输入到模型
        predict = output.argmax(1).item() # 选择概率最大标签的作为预测结果
        # 对比预测值predict和真实标签y
        if predict == y:
            right += 1
        else:
            # 将识别错误的样例打印出来
            img_path = test_dataset.samples[i][0]
            print(f"wrong case: predict = {predict} y = {y} img_path = {img_path}")
    # 计算出测试效果
    sample_num = len(test_dataset)
    acc = right * 1.0 / sample_num
    print("test accuracy = %d / %d = %.3lf" % (right, sample_num, acc))
相关推荐
天天找自己2 分钟前
精通分类:解析Scikit-learn中的KNN、朴素贝叶斯与决策树(含随机森林)
python·决策树·机器学习·分类·scikit-learn
那就摆吧14 分钟前
U-Net vs. 传统CNN:为什么医学图像分割需要跳过连接?
人工智能·神经网络·cnn·u-net·医学图像
深度学习实战训练营25 分钟前
中英混合的语音识别XPhoneBERT 监督的音频到音素的编码器结合 f0 特征LID
人工智能·音视频·语音识别
WADesk---瓜子33 分钟前
用 AI 自动生成口型同步视频,短视频内容也能一人完成
人工智能·音视频·语音识别·流量运营·用户运营
赵英英俊37 分钟前
Python day31
开发语言·python
星环科技TDH社区版41 分钟前
AI Agent 的 10 种应用场景:物联网、RAG 与灾难响应
人工智能·物联网
时序之心1 小时前
ICML 2025 | 深度剖析时序 Transformer:为何有效,瓶颈何在?
人工智能·深度学习·transformer
希艾席帝恩1 小时前
拥抱智慧物流时代:数字孪生技术的应用与前景
大数据·人工智能·低代码·数字化转型·业务系统
Bar_artist1 小时前
离线智能破局,架构创新突围:RockAI与中国AI的“另一条车道”
大数据·人工智能
双向331 小时前
高性能MCP服务器架构设计:并发、缓存与监控
人工智能