像搭积木一样学深度学习:手把手教你搭建第一个神经网络 ——新手也能看懂的深度学习入门

你好,欢迎来到深度学习的世界!如果你已经看过我之前写的关于softmax回归、线性回归的文章,那今天这篇《多层感知机的简洁实现》就是你迈向“真正神经网络”的第一步。别担心,我会用最通俗的语言、最少的数学公式,带你一步步理解并动手实现一个能识别手写数字的神经网络。

我们今天的目标是:用几行代码,搭建一个比softmax更强大的模型——多层感知机(MLP),并且让你明白每一行代码背后的“为什么”。


🌟 一、什么是多层感知机?它和softmax有啥区别?

先来打个比方:

  • Softmax回归:就像一个刚上学的小朋友,看到一张图片,直接数像素,然后猜是哪个数字。它只能画“直线”来分类,比如“横线多的是1,圆圈多的是0”。但现实世界的数据往往不是用一条直线就能分开的。

  • 多层感知机(MLP):就像是一个上了中学的学生,它多了一个“大脑中间层”——隐藏层。这个隐藏层会先对原始图像做一次“特征提取”,比如识别出“有没有拐角”、“有没有封闭区域”,然后再交给最后的“判断层”去决定这是几。这就让它能处理更复杂的问题。

👉 简单说:MLP = Softmax回归 + 隐藏层 + 激活函数


🛠️ 二、代码实现:用PyTorch搭一个MLP

我们使用 PyTorch 这个流行的深度学习框架,它的API设计得非常直观,就像搭积木一样。

1️⃣ 导入必要的工具包

1
2
3
from d2l import torch as d2l
import torch
from torch import nn
  • torch 是 PyTorch 的核心库。
  • nn 是“神经网络模块”,里面有很多现成的“积木块”,比如全连接层、激活函数等。
  • d2l 是一个教学辅助库,帮我们简化数据加载和训练流程。

2️⃣ 搭建模型结构:像搭积木一样

1
2
3
4
5
6
net = nn.Sequential(
nn.Flatten(), # 把 28x28 的图片压平成 784 维的向量
nn.Linear(784, 256), # 全连接层:784个输入 → 256个隐藏单元
nn.ReLU(), # 激活函数:让模型学会“非线性”
nn.Linear(256, 10) # 输出层:256个特征 → 10个类别(0~9)
)

我们来逐行解释:

作用
nn.Flatten() 图片是二维的(28×28),但神经网络喜欢一维数据,所以把它“展平”成784个数字的列表
nn.Linear(784, 256) 这是隐藏层。784个像素输入,输出256个“中间特征”。你可以把它想象成256个不同的“特征探测器”
nn.ReLU() 激活函数!没有它,再多层也等于一层。ReLU把负数变成0,只保留正数,让模型能拟合复杂曲线
nn.Linear(256, 10) 输出层。把256个特征综合起来,输出10个数字的可能性(哪个最大就是哪个)

💡 小知识:为什么叫“多层”?
虽然我们写了两层 Linear,但输入层不算,所以这是“一层隐藏层 + 一层输出层”,已经是“多层”了!

3️⃣ 初始化权重:给模型一个好起点

模型刚创建时,权重是随机的。我们需要让它从一个合理的起点开始学习:

1
2
3
4
5
def init_weights(m):
if type(m) == nn.Linear:
nn.init.normal_(m.weight, std=0.01) # 用正态分布初始化权重

net.apply(init_weights) # 应用到所有层

👉 这就像给一个新生儿的大脑设定初始连接强度,太大会导致爆炸,太小会学不动,0.01的标准差是个经验好值。

4️⃣ 训练配置:准备“学习三件套”

1
2
3
batch_size, lr, num_epochs = 256, 0.1, 10
loss = nn.CrossEntropyLoss(reduction='none') # 损失函数:衡量预测错得多离谱
trainer = torch.optim.SGD(net.parameters(), lr=lr) # 优化器:随机梯度下降(SGD)
  • batch_size=256:每次看256张图再更新一次参数,平衡速度和稳定性。
  • lr=0.1:学习率,决定每次调整参数的“步子”有多大。
  • num_epochs=10:把所有数据过10遍,让模型多学几轮。
  • CrossEntropyLoss:分类任务的标准损失函数,自动结合了Softmax和负对数似然。
  • SGD:最经典的优化算法,沿着梯度方向一步步逼近最优解。

5️⃣ 加载数据 & 开始训练

1
2
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, trainer)
  • load_data_fashion_mnist:加载经典的Fashion-MNIST数据集(10类服装图片,28×28灰度图)。
  • train_ch3:d2l库封装好的训练函数,自动完成前向传播、反向传播、参数更新等步骤。

运行完这段代码,你会看到准确率慢慢上升,最终可能达到85%以上!🎉


💡 三、关键知识点总结

概念 说明
隐藏层 模型的“中间大脑”,负责从原始输入中提取有用特征
激活函数(ReLU) 引入非线性,让模型能拟合复杂函数。没有它,多层=单层
全连接层(Linear) 每个输入都和每个输出相连,是最基础的神经网络层
损失函数 & 优化器 损失函数告诉模型“错得多离谱”,优化器告诉它“怎么改才能变对”
模块化设计 nn.Sequential 让我们可以像搭积木一样构建模型,清晰又灵活

🧪 四、动手练习:你可以这样玩得更深入

别光看,动手试试这些小实验,你会理解得更深:

  1. 改变隐藏层大小

    • 256 改成 128512,看看训练速度和最终准确率有什么变化?
    • 太小可能学不好,太大可能过拟合。
  2. 换一个激活函数

    • nn.ReLU() 换成 nn.Sigmoid()nn.Tanh(),效果如何?
    • ReLU 通常更快收敛,Sigmoid 容易梯度消失。
  3. 尝试不同的初始化

    • std=0.01 改成 0.10.001,看看模型会不会“学不动”或“震荡”?
    • 权重初始化对训练稳定性影响很大!
  4. 加更多隐藏层

    • 试试加一层:nn.Linear(256, 128) + nn.ReLU(),变成“深层网络”。
    • 你会发现:层数多了,训练可能变慢,甚至更难收敛——这就是为什么后来有了残差网络(ResNet)。

📌 五、写在最后:你已经迈出了重要一步!

恭喜你!你已经:
✅ 理解了多层感知机的基本原理
✅ 用PyTorch实现了一个能分类图像的神经网络
✅ 掌握了模型搭建、训练、调参的基本流程

这不仅是代码的胜利,更是思维的升级。你不再只是用公式拟合数据,而是在构建一个会“学习”的系统

接下来,你可以继续探索:

  • 卷积神经网络(CNN):更适合图像的结构
  • Dropout、BatchNorm:防止过拟合的利器
  • 更复杂的优化器:Adam、RMSProp

深度学习的大门,已经为你打开。继续加油,你会走得更远!


📌 附:完整代码(PyTorch版)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from d2l import torch as d2l
import torch
from torch import nn

# 模型定义
net = nn.Sequential(
nn.Flatten(),
nn.Linear(784, 256),
nn.ReLU(),
nn.Linear(256, 10)
)

# 初始化权重
def init_weights(m):
if type(m) == nn.Linear:
nn.init.normal_(m.weight, std=0.01)
net.apply(init_weights)

# 超参数
batch_size, lr, num_epochs = 256, 0.1, 10
loss = nn.CrossEntropyLoss(reduction='none')
trainer = torch.optim.SGD(net.parameters(), lr=lr)

# 数据 & 训练
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, trainer)

👉 只要安装好环境,复制粘贴就能运行!


如果你喜欢这篇文章,欢迎点赞、收藏、转发。也欢迎在评论区告诉我:你最想了解哪个深度学习主题?我们下期见!👋