Jupyter Notebook上运行第一个神经网络:基于MNIST数据集的手写数字识别

在这个数字化时代,手写数字识别已经成为了一个既经典又充满挑战的任务。而MNIST数据集,作为手写数字识别的“入门级”数据集,更是被广大学者和工程师们视为探索神经网络奥秘的“敲门砖”。在这篇文章中有完整的可运行的代码,让我们一起踏上这段充满挑战和乐趣的学习之旅吧!
在这里插入图片描述

一、安装conda

在安装 Jupyter Notebook 时,通常我们会用到 conda 这个包管理工具,因为它可以方便地管理 Python 包及其依赖关系。如果没有安装conda包管理工具,请参考这篇文章安装

AI开发利器:miniforge3无感平替Anaconda3

Conda配置镜像源。例如,使用清华大学或中科大的镜像源:

conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
conda config --set show_channel_urls yes

二、使用conda安装Jupyter Notebook

1. conda创建环境

打开命令行,如果你还没有创建环境,可以使用下面的命令来创建一个新的环境(例如,名为 myenv 的环境,并安装 Python 3.12):

conda create -n myenv python=3.12

然后激活这个环境:

conda activate myenv

2. 安装 Jupyter Notebook

在激活的环境中,使用以下命令安装 Jupyter Notebook:
conda install notebook

3. 安装pytorch依赖:

conda install pytorch torchvision torchaudio cpuonly -c pytorch
conda install matplotlib

4. 启动 Jupyter Notebook

安装完成后,你可以通过以下命令启动 Jupyter Notebook:

jupyter notebook

这将会在默认的 web 浏览器中打开 Jupyter Notebook 的界面。

5. 创建nodebook

  • file->New->Nodebook
    在这里插入图片描述
  • 点击select
    在这里插入图片描述

三、可运行代码

下面是神经网络,在MNIST数据集训练用于识别手写体数字的模型,运行完main()函数后会生成MNIST_model_params.pt模型保存到用户目录下。接下来注释掉main()函数,打开并运行predict()函数,进行预测应用。

import torch
from torch.utils.data import DataLoader
from torchvision import transforms
from torchvision.datasets import MNIST
import matplotlib.pyplot as plt

class Net(torch.nn.Module):  # 定义一个Net类,神经网络的主体
    def __init__(self):  # 全连接层,四个
        super().__init__()
        self.fc1 = torch.nn.Linear(28*28, 64)  # 输入层输入28*28,输出64
        self.fc2 = torch.nn.Linear(64, 64)  # 中间层,输入64,输出64
        self.fc3 = torch.nn.Linear(64, 64)
        self.fc4 = torch.nn.Linear(64, 10)  # 中间层(隐藏层)的最后一层,输出10个特征值
    
    def forward(self, x):  # 前向传播过程
        # self.fc1(x)全连接线性计算,再套上一个激活函数torch.nn.functional.relu()
        x = torch.nn.functional.relu(self.fc1(x))
        x = torch.nn.functional.relu(self.fc2(x))
        x = torch.nn.functional.relu(self.fc3(x))
        # 最后一层进行softmax归一化,log_softmax是为了提高计算稳定性,在softmax后面套上了一个对数运算
        x = torch.nn.functional.log_softmax(self.fc4(x), dim=1)
        return x


def get_data_loader(is_train):
    to_tensor = transforms.Compose([transforms.ToTensor()])  # 定义数据转换类型tensor,多维数组(张量)
    """下载MNIST数据集,
        "":当前位置
        is_train:判断是训练集还是测试集;
        batch_size:一个批次包含15张图片;
        shuffle:数据随机打乱的
    """
    data_set = MNIST("", is_train, transform=to_tensor, download=True)
    return DataLoader(data_set, batch_size=15, shuffle=True)  # 数据加载器


def evaluate(test_data, net):  # 用来评估神经网络
    n_correct = 0
    n_total = 0
    with torch.no_grad():
        for (x, y) in test_data:
            outputs = net.forward(x.view(-1, 28*28))  # 计算神经网络的预测值
            for i, output in enumerate(outputs):  # 对每个批次的预测值进行比较,累加正确预测的数量
                if torch.argmax(output) == y[i]:
                    n_correct += 1
                n_total += 1
    return n_correct / n_total  # 返回正确率


def main():
    # 导入训练集和测试集
    train_data = get_data_loader(is_train=True)
    test_data = get_data_loader(is_train=False)
    net = Net()  # 初始化神经网络

    # 打印初始网络的正确率,应当是10%附近。手写数字有十种结果,随机猜的正确率就是1/10
    print("initial accuracy:", evaluate(test_data, net))
    """训练神经网络
    pytorch的固定写法
    """
    optimizer = torch.optim.Adam(net.parameters(), lr=0.001)
    for epoch in range(3):  # 需要在一个数据集上反复训练神经网络,epoch网络轮次,提高数据集的利用率
        for (x, y) in train_data:
            net.zero_grad()  # 初始化
            output = net.forward(x.view(-1, 28*28))  # 正向传播
            # 计算差值,nll_loss对数损失函数,为了匹配log_softmax的log运算
            loss = torch.nn.functional.nll_loss(output, y)
            loss.backward()  # 反向误差传播
            optimizer.step()  # 优化网络参数
        print("epoch", epoch, "accuracy:", evaluate(test_data, net))  # 打印当前网络的正确率
    
    torch.save(net.state_dict() , 'MNIST_model_params.pt')  # 只保存网络中的参数 (速度快, 占内存少)
    """测试神经网络
        训练完成后,随机抽取3张图片进行测试
    """
    for (n, (x, _)) in enumerate(test_data):
        if n > 3:
            break
        predict = torch.argmax(net.forward(x[0].view(-1, 28*28)))  # 测试结果
        plt.figure(n)  # 画出图像
        plt.imshow(x[0].view(28, 28))  # 像素大小28*28
        plt.title("prediction: " + str(int(predict)))  # figure的标题
    plt.show()

main()

def predict():
    net = Net()  # 初始化神经网络
    net.load_state_dict(torch.load('MNIST_model_params.pt',weights_only=True))
    test_data = get_data_loader(is_train=False)
    for (n, (x, _)) in enumerate(test_data):
        if n > 8:
            break
        predict = torch.argmax(net.forward(x[0].view(-1, 28*28)))  # 测试结果
        # plt.figure(n)  # 画出图像
        plt.subplot(3, 3, n+1) # 创建3*3显示布局
        plt.imshow(x[0].view(28, 28))  # 像素大小28*28
        plt.title("prediction: " + str(int(predict)))  # figure的标题
    plt.show()

# predict()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhulangfly

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值