title: “人工智能实战(三):PyTorch 张量操作与 MLP 非线性分类”
tags: [“Python”, “深度学习”, “PyTorch”, “神经网络”, “MLP”]
categories: [“人工智能”]
description: “在 CPU 服务器上安装 PyTorch,完成张量操作与自动求导,并搭建一个三层 MLP 神经网络,用真实训练 loop 学习 XOR 非线性分类,打印每一步的 loss 与准确率。”

人工智能实战(三):PyTorch 张量操作与 MLP 非线性分类

「人工智能」阶段第三篇,正式进入深度学习。我们在纯 CPU 服务器上安装 PyTorch,跑通张量操作、自动求导,并训练一个真正的多层感知机(MLP)。所有输出均为真实执行结果。

一、背景与目标

深度学习框架中 PyTorch 最受研究者欢迎。本篇目标:

  1. 在无 GPU 的服务器上安装 CPU 版 PyTorch;
  2. 掌握张量(Tensor)的创建、运算、autograd 自动求导;
  3. 搭建三层 MLP,用训练 loop 让网络"学会"XOR 非线性分类,打印 loss 与准确率。

配套脚本 s8_03_pytorch.py。

二、环境准备:CPU 版 PyTorch 安装(含避坑)

官网默认的 download.pytorch.org 在国内访问极慢(本次实测卡住十几分钟无进展)。改用上海交大 PyTorch 镜像后秒下:

pip3 install --break-system-packages torch \
  --index-url https://mirror.sjtu.edu.cn/pytorch-wheels/cpu/

安装结果:

PyTorch 版本: 2.14.0+cpu
CUDA 可用: False

本机是 8 核 CPU、无 GPU,所以装 +cpu 版本(几百 MB,远小于含 CUDA 的数 GB 版本);CUDA 可用: False 是预期的。CPU 足够跑玩具级神经网络。

三、张量操作与自动求导

1. 张量四则与矩阵运算

a = torch.tensor([[1.0, 2.0], [3.0, 4.0]])
b = torch.tensor([[5.0, 6.0], [7.0, 8.0]])
矩阵乘法 a @ b:
 tensor([[19., 22.],
        [43., 50.]])
求和 sum(), 均值 mean(): 10.0 2.5
形状: torch.Size([2, 2])  数据类型: torch.float32

2. autograd 自动求导

x = torch.tensor(2.0, requires_grad=True)
y = x ** 3 + 2 * x + 1
y.backward()
print(x.grad)   # dy/dx = 3x^2 + 2
y = x^3 + 2x + 1, 在 x=2 处 dy/dx = 14.0 (理论 3*4+2=14)

框架自动算出了导数 14.0,与手算完全一致——这正是反向传播训练神经网络的基础。

四、MLP 学习 XOR(非线性分类)

XOR(异或)是经典的线性不可分问题:单层感知机无论怎么切都分不开,但加入非线性激活的多层网络能 100% 拟合。

网络结构

class MLP(nn.Module):
    def __init__(self):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(2, 8), nn.Tanh(),
            nn.Linear(8, 4), nn.Tanh(),
            nn.Linear(4, 1), nn.Sigmoid(),
        )
    def forward(self, x):
        return self.net(x)

三层全连接,隐藏层用 Tanh 激活(引入非线性),输出层 Sigmoid 映射到 (0,1),配 BCELoss(二分类交叉熵)。

训练 loop(打印 loss 与准确率)

opt = optim.Adam(model.parameters(), lr=0.1)
loss_fn = nn.BCELoss()
for ep in range(600):
    opt.zero_grad()
    out = model(X); loss = loss_fn(out, Y)
    loss.backward(); opt.step()
    if ep % 100 == 0:
        ...  # 打印 loss 与准确率

真实训练输出:

开始训练 MLP 学习 XOR(打印每个 epoch 的 loss)
epoch    0 | loss=0.6968 | acc=75.00%
epoch  100 | loss=0.0009 | acc=100.00%
epoch  200 | loss=0.0005 | acc=100.00%
epoch  300 | loss=0.0003 | acc=100.00%
epoch  400 | loss=0.0002 | acc=100.00%
epoch  500 | loss=0.0001 | acc=100.00%

训练完成:耗时 0.16s,最终 loss=0.0001
XOR 输入  ->  模型预测  |  真实
  [0.0, 0.0]  ->  0  |  0.0
  [0.0, 1.0]  ->  1  |  1.0
  [1.0, 0.0]  ->  1  |  1.0
  [1.0, 1.0]  ->  0  |  0.0
训练集准确率 = 100.00%
参数总量: 65

解读:

  • epoch 0:loss=0.6968(接近随机猜),acc 只有 75%;
  • epoch 100 之后:loss 逼近 0,acc 稳定 100%;
  • 四组 XOR 输入全部预测正确,网络完整学会了非线性决策边界;
  • 整个网络仅 65 个参数,0.16 秒就在 CPU 上训练完成。

五、关于 CNN / 残差网络的说明

文中 MLP 是全连接网络。更高级的 CNN(卷积神经网络) 与 ResNet(残差网络) 主要用于图像分类:CNN 用卷积核提取局部特征,ResNet 通过"跳跃连接"解决深层网络梯度消失问题。它们的共性都是:张量前向传播 + loss 反向传播 + 优化器更新参数,和本篇的训练 loop 完全一致。理解了本篇的训练骨架,往上叠加卷积层/残差块即可平滑进阶。

本机内存/下载条件有限,未跑 ImageNet 级别的 CNN;但用玩具级 MLP 完整走通"定义模型 → 前向 → 计算 loss → 反向 → 更新"的闭环,已具备迁移到 CNN 的全部基础。

六、常见坑

  1. 官网源下载慢:国外站点访问慢时用国内镜像(mirror.sjtu.edu.cn 等)装 +cpu 版。
  2. 张量形状不匹配:matmul 前先核对 shape,广播规则与 NumPy 一致但报错信息不同。
  3. 没写 opt.zero_grad():梯度会累加,导致 loss 乱跳——每个 step 前必须先清零。
  4. 忘记 model.eval()/no_grad():推理时关掉 dropout 和梯度追踪,否则结果不稳还浪费显存。

七、小结

本篇在纯 CPU 环境成功安装 PyTorch,跑通了张量运算、自动求导,并用一个 65 参数的 MLP 完整学会了 XOR 非线性分类,loss 从 0.69 降到 0.0001。至此「人工智能」阶段从经典机器学习到深度学习形成了完整闭环。

配套代码:code/s8_03_pytorch.py

更多推荐