深度学习|模型训练:手写 SimpleNet

引言

从前文「深度学习|梯度下降法:误差最小化的权重参数」,我们知道了神经网络的学习就是“找寻使损失函数的值尽可能小的权重参数”的过程,又掌握了找寻的方法(梯度下降法)。凭借这些信息,我们可以以纯手写 Python 代码的方式,实现一个简单的神经网络 SimpleNet,使用这个 SimpleNet 来演示神经网络的整个训练过程,并验证它的推理效果。

在这里插入图片描述

SimpleNet 网络结构

我们依旧以手写数字识别为任务目标,实现一个可用于该任务的形如图 1 所示的 SimpleNet,亲身体验一下神经网络学会识别这些图片所代表数字的数学过程

在这里插入图片描述

如图 1 所示,SimpleNet 是一个两层神经网络,它的输入层有 784 个神经元,分别代表 28 × \times × 28 个像素值,第 1 层隐层有 50 个功能神经元,输出层有 10 个神经元,分别代表预测结果为 0 ~ 9 的概率。

从前文对神经网络的介绍中我们知道,要实现一个神经网络的基本功能,除了要确定神经网络的结构,我们还需要确定它每一层所使用的激活函数,以及在进行梯度下降法优化权重参数时所使用的损失函数以及梯度函数

激活函数

SimpleNet 的第 1 层隐层我们使用 Sigmoid 函数作为激活函数,Sigmoid 函数是一个 S 型函数,它将输入值映射到 0 到 1 之间,有助于神经网络的非线性表达。输出层我们使用 Softmax 函数作为激活函数,Softmax 函数将输入值映射成 0 到 1 之间的概率值,它输出值归一化,使得输出值之和为 1,用于此类多分类任务正好合适:

import numpy as np

def sigmoid(x):
    """S 型函数"""
    return 1 / (1 + np.exp(-x))

def softmax(x):
    """归一化指数函数"""
    if x.ndim == 2:
        x = x.T
        x = x - np.max(x, axis=0)
        y = np.exp(x) / np.sum(np.exp(x), axis=0)
        return y.T

    x = x - np.max(x)  # 溢出对策
    return np.exp(x) / np.sum(np.exp(x))

关于激活函数的更多详细介绍可以参见前文「深度学习|激活函数:网络表达增强」。

损失函数

SimpleNet 的损失函数我们可以选择使用交叉熵误差cross entropy error),交叉熵误差可用于评估类别的概率分布,常用于此类多分类任务。

交叉熵误差计算的是对应正确解神经元的输出的自然对数,用式 1 表示:

E = − ∑ k t k log ⁡ y k (1) E = - \sum_{k}t_k\log{y_k} \tag{1} E=ktklogyk(1)

其中 y k y_k yk 表示神经网络输出层的第 k 个神经元的输出值, t k t_k tk 表示监督数据的 one-hot 表示。

因为 t k t_k tk 中只有正确解索引位的值为 1,其他均为 0,式 1 实际只计算了对应正确解神经元输出的自然对数。

因此交叉熵误差的图形可以等价于自然对数函数图形:

在这里插入图片描述

y = [0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0]t = [0, 0, 1, 0, 0, 0, 0, 0, 0, 0] 为例,推理结果 y 相对实际结果 t 的交叉熵误差为:

E = − log ⁡ y 2 = − log ⁡ 0.6 = 0.51 。 E = -\log{y_2} \\ = -\log{0.6} \\ = 0.51。 E=logy2=log0.6=0.51

更一般的,我们可以将单个 (y, t) 数据样例的交叉熵误差计算推广到求一批包含 n 个样例的训练集的交叉熵误差计算(用于 mini-batch 的梯度计算),用式 2 表示:

E = − 1 n ∑ i = 1 n ∑ k t i k log ⁡ y i k (2) E =

<think>好的,我现在需要帮助用户找到PyTorch深度学习模型的简单入门代码。用户明确提到是给初学者的,所以代码应该尽量简洁易懂,同时涵盖基本概念。首先,我应该回忆PyTorch的基础知识,比如如何定义模型、准备数据、训练循环等。 接下来,用户的需求是入门级的代码,所以我应该选择一个简单的数据集,比如MNIST,因为它常用且容易获取。模型结构方面,简单的全连接网络或者卷积网络都可以考虑。不过对于真正的初学者来说,全连接网络可能更直观,尽管在图像任务上效果不如CNN,但作为入门示例已经足够。 然后,我需要确保代码结构清晰,步骤明确,包括数据加载、模型定义、损失函数和优化器的选择、训练循环和测试部分。同时,注释也是必要的,帮助用户理解每一部分的作用。 还要注意引用用户提供的参考内容,特别是引用[2]和[3],其中提到PyTorch的深度学习API和核心概念的可转移性。因此,在代码解释中应该强调这些点,比如说明PyTorch的nn.Module和如何定义前向传播,这样用户以后可以应用到其他库或项目中。 可能还需要考虑代码的可运行性,比如是否需要GPU支持,但作为入门示例,暂时用CPU即可,避免复杂设置。同时,训练轮次不宜过多,比如3个epoch,这样用户能快速看到结果。 最后,生成相关问题时要围绕用户可能遇到的下一步问题,比如如何改进模型、调整超参数或处理其他类型的数据,这样能引导用户深入学习。</think>以下是一个简单的PyTorch全连接神经网络实现MNIST手写数字识别的示例代码,包含详细注释和关键步骤说明: ```python # 导入必要库 import torch import torch.nn as nn import torchvision from torchvision import transforms # 1. 数据准备 transform = transforms.Compose([transforms.ToTensor()]) # 加载MNIST数据集(PyTorch内置数据集) train_dataset = torchvision.datasets.MNIST( root='./data', train=True, transform=transform, download=True) test_dataset = torchvision.datasets.MNIST( root='./data', train=False, transform=transform) # 创建数据加载器 train_loader = torch.utils.data.DataLoader( dataset=train_dataset, batch_size=100, shuffle=True) test_loader = torch.utils.data.DataLoader( dataset=test_dataset, batch_size=100, shuffle=False) # 2. 定义神经网络模型 class SimpleNet(nn.Module): def __init__(self): super(SimpleNet, self).__init__() self.fc1 = nn.Linear(28*28, 512) # 输入层到隐藏层 self.fc2 = nn.Linear(512, 10) # 隐藏层到输出层 self.relu = nn.ReLU() # 激活函数 def forward(self, x): x = x.view(-1, 28*28) # 展平图像数据 x = self.relu(self.fc1(x)) x = self.fc2(x) return x # 3. 初始化模型、损失函数和优化器 model = SimpleNet() criterion = nn.CrossEntropyLoss() optimizer = torch.optim.Adam(model.parameters(), lr=0.001) # 4. 训练循环 for epoch in range(3): # 训练3个epoch for images, labels in train_loader: # 前向传播 outputs = model(images) loss = criterion(outputs, labels) # 反向传播和优化 optimizer.zero_grad() loss.backward() optimizer.step() print(f'Epoch [{epoch+1}/3], Loss: {loss.item():.4f}') # 5. 测试模型 with torch.no_grad(): correct = 0 total = 0 for images, labels in test_loader: outputs = model(images) _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() print(f'Test Accuracy: {100 * correct / total:.2f}%') ``` 关键组件说明: 1. **数据管道**:使用`torchvision`加载标准数据集,通过`DataLoader`实现批量处理[^2] 2. **模型架构**:继承`nn.Module`定义网络结构,包含全连接层和激活函数 3. **训练流程**:标准的前向传播、损失计算、反向传播三步循环 4. **优化方法**:使用Adam优化器自动调整学习率[^4] 建议逐步尝试以下修改: 1. 增加隐藏层数量 2. 尝试不同的激活函数(如Sigmoid、LeakyReLU) 3. 调整学习率和批量大小 4. 增加训练轮次(epoch)
评论 45
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

三余知行

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

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

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

打赏作者

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

抵扣说明:

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

余额充值