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

学习资料:从零设计并训练一个神经网络,你就能真正理解它了_哔哩哔哩_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))
相关推荐
wangruofeng18 分钟前
GLM-5.3-Flash 发布:追平 Opus 4.8 的智力,1/40 的价格,跑在国产芯片上
人工智能·aigc·chatglm (智谱)
皮皮虾❀2 小时前
钉钉AI服务商×教育行业:AI现代产业学院共建一体化实战——从“高校AI教学缺平台”到“校企共建AI产业学院培养数字化人才
人工智能·钉钉
kobe_OKOK_2 小时前
DRF接口幂等操作
python·django
火山引擎开发者社区3 小时前
【议程来了】火山引擎开发者社区技术日・NVIDIA 独家赞助-成都站
人工智能
三声三视3 小时前
从崩溃日志到 AI 技能:tri-god 蒸馏实战
人工智能·ai·aigc·agent
ZGIAI3 小时前
ZGI Workflow 并发控制:保护下游接口
人工智能·架构
richard_first3 小时前
Transformer 与大语言模型:第9章 LayerNorm 归一化层
人工智能·深度学习·机器学习·transformer
ZGIAI3 小时前
知识库有结果,不等于召回率合格
人工智能·架构
东小西3 小时前
【SAA实战】第 1 篇:ReactAgent 入门——先撸个"会调工具的助手"跑起来
java·人工智能·spring
廿士3 小时前
python脚本使用相关
python