神经网络入门实战:用 PyTorch 从零构建第一个网络

从神经元与感知机讲起,用 PyTorch 从零构建并训练第一个神经网络:张量与自动求导、前向传播与损失函数、反向传播直觉、优化器与训练循环、评估与预测,最后完整跑通 MNIST 手写数字识别。

引言

深度学习是机器学习最耀眼的分支,而神经网络是它的地基。很多人畏惧神经网络,是因为被「反向传播」「梯度消失」这些术语吓住。但用现代框架(PyTorch/TensorFlow),训练一个网络的工程步骤只有四步:定义模型、定义损失、定义优化器、跑训练循环。剩下的是理解「它在学什么」。

本文从神经元讲起,带你用 PyTorch 从零到一构建、训练、评估一个真正能识别手写数字的网络。你不必先懂微积分——你只需要理解四个直觉:张量是数据容器、自动求导帮我们算梯度、损失衡量好坏、优化器让损失变小。跑通之后,通往 CNN/Transformer 的大门就打开了。

前置:[[ml]] 专题的评估方法(https://plumephp.com/ml-model-evaluation/)。深入原理见 [[ai-ml]] 专题的神经网络文章。


目录


1. 神经元与感知机:神经网络的最小单元

1.1 单个神经元

输入 x1,x2,x3 → 加权求和 Σ(w·x + b) → 激活函数 σ → 输出
  • 权重 w:每个输入的重要性。
  • 偏置 b:神经元的「倾向性」。
  • 激活函数 σ:加入非线性(否则多层线性叠加仍是线性)。

1.2 常见激活函数

函数公式直觉
ReLUmax(0, x)最常用,快
Sigmoid1/(1+e⁻ˣ)输出 0~1,二分类输出层
Softmax归一化指数多分类输出层,和为1

1.3 多层 = 逐层抽象

第一层看到原始像素,中间层学到「边缘/形状」,高层学到「眼睛/嘴巴」。层数越多,抽象层次越高(也越难训)。


2. 张量:PyTorch 的数据容器

2.1 安装与导入

pip install torch torchvision

2.2 张量基础

import torch

# 标量、向量、矩阵、高维
s = torch.tensor(3.0)              # 0维
v = torch.tensor([1., 2., 3.])     # 1维
m = torch.zeros(3, 4)              # 2维 (3行4列)

print(v.shape)          # torch.Size([3])
print(m.shape)          # torch.Size([3, 4])
print(v.dtype)          # torch.float32

2.3 与 NumPy 互转

import numpy as np

arr = np.random.randn(2, 3)
t = torch.from_numpy(arr)         # NumPy → Tensor
back = t.numpy()                  # Tensor → NumPy

神经网络的数据都装进张量,形状(shape)是你的好朋友——随时 print(x.shape) 确认维度没错。


3. 自动求导:梯度从哪来

3.1 训练需要梯度

训练时我们要算「损失对每个权重 w 的偏导」,才能知道往哪调。手写链式法则很痛苦——PyTorch 的 自动求导 替你算。

3.2 一个小实验

x = torch.tensor(3.0, requires_grad=True)
y = x**2 + 2*x + 1

y.backward()               # 自动算 dy/dx
print(x.grad)              # 2*x + 2 = 8.0

3.3 直觉

loss.backward()  →  每个参数的 .grad 被填上梯度
optimizer.step() →  参数按梯度更新一步
optimizer.zero_grad() → 清空上次梯度(否则会累加)

4. 网络结构:从输入到输出

4.1 用 nn.Sequential 搭一个全连接网络

MNIST 图片是 28×28=784 像素,输出 10 类:

import torch.nn as nn

model = nn.Sequential(
    nn.Linear(784, 128),        # 784 → 128
    nn.ReLU(),
    nn.Linear(128, 64),         # 128 → 64
    nn.ReLU(),
    nn.Linear(64, 10),          # 64 → 10 类
)

print(model)

4.2 前向传播

x = torch.randn(32, 784)        # 一批 32 张图,每张 784 像素
logits = model(x)               # 输出 (32, 10),10 个类的得分
print(logits.shape)

4.3 nn.Linear 内部

nn.Linear(in, out) 内含权重矩阵 W 与偏置 b,out = x @ W.T + b。训练就是学这两个参数。


5. 损失函数与优化器:训练的两个旋钮

5.1 损失函数:衡量错多少

任务损失直觉
回归MSELoss预测与真值的平方差
分类CrossEntropyLoss正确类的得分越高越好
import torch.nn as nn

criterion = nn.CrossEntropyLoss()

5.2 优化器:让损失变小

import torch.optim as optim

optimizer = optim.SGD(model.parameters(), lr=0.01)   # 梯度下降
# 或更常用的
optimizer = optim.Adam(model.parameters(), lr=0.001)
  • 学习率 lr:每步走多大。太大震荡不收敛,太小龟速。
  • Adam:自适应学习率,默认起点优选。

6. 训练循环:epoch、batch 与反向传播

6.1 三要素

概念含义
epoch遍历全部数据一遍
batch每批样本数(一次前向+反向)
iteration一个 batch 的训练步骤

6.2 最小训练循环

for epoch in range(10):
    running_loss = 0.0
    for images, labels in dataloader:
        optimizer.zero_grad()          # 1. 清梯度
        outputs = model(images)        # 2. 前向
        loss = criterion(outputs, labels)  # 3. 算损失
        loss.backward()                # 4. 反向:算梯度
        optimizer.step()               # 5. 更新参数
        running_loss += loss.item()
    print(f"epoch {epoch+1} loss={running_loss/len(dataloader):.4f}")

6.3 这个循环就是深度学习的一切

从全连接到 Transformer,训练循环骨架完全一样。区别只在模型结构与数据形式。


7. 完整实战:MNIST 手写数字识别

7.1 数据加载

import torch
import torchvision
import torchvision.transforms as T
from torch.utils.data import DataLoader

transform = T.Compose([T.ToTensor(), T.Normalize((0.5,), (0.5,))])

train_set = torchvision.datasets.MNIST(
    root='./data', train=True, download=True, transform=transform)
test_set = torchvision.datasets.MNIST(
    root='./data', train=False, download=True, transform=transform)

train_loader = DataLoader(train_set, batch_size=64, shuffle=True)
test_loader = DataLoader(test_set, batch_size=64, shuffle=False)

7.2 定义网络

import torch.nn as nn

model = nn.Sequential(
    nn.Flatten(),                 # 28×28 → 784
    nn.Linear(784, 128),
    nn.ReLU(),
    nn.Linear(128, 10),
)

7.3 训练 + 评估

import torch.optim as optim

criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

for epoch in range(5):
    model.train()                # 训练模式
    for images, labels in train_loader:
        optimizer.zero_grad()
        loss = criterion(model(images), labels)
        loss.backward()
        optimizer.step()

    # 每轮在测试集上评估
    model.eval()                 # 评估模式(关闭 Dropout 等)
    correct = total = 0
    with torch.no_grad():        # 评估不用算梯度,省内存
        for images, labels in test_loader:
            preds = model(images).argmax(dim=1)
            correct += (preds == labels).sum().item()
            total += labels.size(0)
    acc = correct / total
    print(f"epoch {epoch+1} 测试准确率={acc:.4f}")
输出示例(CPU 训练):
epoch 1 测试准确率=0.9479
epoch 2 测试准确率=0.9614
epoch 3 测试准确率=0.9675
epoch 4 测试准确率=0.9711
epoch 5 测试准确率=0.9721

一个 5 分钟训出来的全连接网络,MNIST 就能到 ~97% 准确率。这个「四步心法」就是深度学习的入场券。


8. 评估与改进:从入门网络走向实战

8.1 看错在哪里

# 收集几个预测错的样本,画出来看看
import matplotlib.pyplot as plt

wrong = 0
for images, labels in test_loader:
    preds = model(images).argmax(dim=1)
    for i in range(len(images)):
        if preds[i] != labels[i] and wrong < 5:
            plt.imshow(images[i][0], cmap='gray')
            plt.title(f"真值={labels[i].item()} 预测={preds[i].item()}")
            plt.show()
            wrong += 1

8.2 通往更高精度的路径

手段效果复杂度
加深加宽网络中低
换 CNN(卷积)大幅提升中
数据增强(旋转/平移)中低
调超参(lr/batch/epoch)中低
预训练 + 微调高中

8.3 用 CNN 快速试一下

cnn = nn.Sequential(
    nn.Conv2d(1, 16, kernel_size=3, padding=1), nn.ReLU(),
    nn.MaxPool2d(2),
    nn.Conv2d(16, 32, kernel_size=3, padding=1), nn.ReLU(),
    nn.MaxPool2d(2),
    nn.Flatten(),
    nn.Linear(32*7*7, 128), nn.ReLU(),
    nn.Linear(128, 10),
)

卷积能利用像素的局部空间结构,是图像任务的基本盘。


9. 总结:神经网络的四步心法

9.1 记住这四个步骤

1. 定义模型     nn.Sequential / nn.Module
2. 定义损失     CrossEntropyLoss / MSELoss
3. 定义优化器   Adam / SGD
4. 训练循环     forward → loss → backward → step

9.2 常见坑速查

症状原因解法
损失不降lr 太小调大 lr
损失 NaNlr 太大 / 输入未归一化调小 lr / Normalize
维度报错shape 不匹配print(x.shape) 排查
评估要开 no_grad省内存with torch.no_grad()
忘 zero_grad梯度累加每步 optimizer.zero_grad()

9.3 一句话心法

神经网络不是魔法,是「张量 + 自动求导 + 优化器」的工程组装。跑通最小闭环后,一切模型都是往这个骨架上加结构。


延伸阅读

  • https://plumephp.com/ml-model-evaluation/ — 评估方法论(训练/验证/测试的纪律)
  • https://plumephp.com/ml-python-environment-setup/ — GPU/环境配置
  • [[ai-ml]] 专题的神经网络、CNN、RNN/Transformer 深度文章
  • PyTorch 官方教程

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「ml」更多文章

  1. 集成学习实战:Bagging、随机森林、梯度提升与 Stacking
  2. 迁移学习实战:预训练模型、特征提取与微调全流程
  3. 计算机视觉入门实战:图像处理与 CNN 图像分类