1. 单层感知机

1.1 感知机

① 线性回归输出的是一个实数,感知机输出的是一个离散的类。

1.2 训练感知机

① 如果分类正确的话y<w,x>为正数,负号后变为一个负数,max后输出为0,则梯度不进行更新。

② 如果分类错了,y<w,x>为负数,下图中的if判断就成立了,就有梯度进行更新。

1.3 收敛半径

r是数据的大小

1.4 XOR问题

感知机不能分割异或问题;异或问题:同为1则为-1;同为0也为-1;不同则为1;

1.5 总结

2. 多层感知机

2.1 学习XOR

① 先用蓝色的线分,再用黄色的线分。

② 再对蓝色的线和黄色的线分出来的结果做乘法。【同正异负】

2.2 单隐藏层

① 不用激活函数的话,所以全连接层连接在一起依旧可以用一个最简单的线性函数来表示。

2.3 Sigmoid 函数

2.4 Tanh函数

2.5 ReLU

① ReLU的好处在于不需要执行指数运算。

② 在CPU上一次指数运算相当于上百次乘法运算。

2.6 多类分类

softmax就是将所有输入拉到0-1之间,所有输出的和为1

第一个隐藏层的输出会作为第二个隐藏层的输入;PS:不要忘记使用激活函数

2.7 总结

1. 多层感知机(使用自定义)

import torch
from torch import nn
from d2l import torch as d2l

batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)

# 实现一个具有单隐藏层的多层感知机,它包含256个隐藏单元
num_inputs, num_outputs, num_hiddens = 784, 10, 256 # 输入、输出是数据决定的,256是调参自己决定的
W1 = nn.Parameter(torch.randn(num_inputs, num_hiddens, requires_grad=True))
b1 = nn.Parameter(torch.zeros(num_hiddens, requires_grad=True))
W2 = nn.Parameter(torch.randn(num_hiddens, num_outputs, requires_grad=True))
b2 = nn.Parameter(torch.zeros(num_outputs, requires_grad=True))
params = [W1,b1,W2,b2]

# 实现 ReLu 激活函数
def relu(X):
    a = torch.zeros_like(X) # 数据类型、形状都一样,但是值全为 0
    return torch.max(X,a)

# 实现模型
def net(X):
    #print("X.shape:",X.shape)
    X = X.reshape((-1, num_inputs)) # -1为自适应的批量大小
    #print("X.shape:",X.shape)
    H = relu(X @ W1 + b1)
    #print("H.shape:",H.shape)
    #print("W2.shape:",W2.shape)
    return (H @ W2 + b2)

# 损失
loss = nn.CrossEntropyLoss() # 交叉熵损失

# 多层感知机的训练过程与softmax回归的训练过程完全一样
#num_epochs ,lr = 30, 0.1
#updater = torch.optim.SGD(params, lr=lr)
#d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, updater)

#手动实现训练过程
num_epochs, lr = 30, 0.1
updater = torch.optim.SGD(params, lr=lr)

for epoch in range(num_epochs):
    total_loss, total_acc, n = 0.0, 0.0, 0
    for X, y in train_iter:
        l = loss(net(X), y)
        updater.zero_grad()
        l.backward()
        updater.step()
        total_loss += l.item() * y.numel()
        total_acc += (net(X).argmax(axis=1) == y).sum().item()
        n += y.numel()
    print(f'epoch {epoch + 1}, loss {total_loss / n:.4f}, train_acc {total_acc / n:.4f}')

解释:

1. 导入工具

import torch
from torch import nn
from d2l import torch as d2l
  • torch:PyTorch 深度学习框架

  • nn:PyTorch 里专门用来搭神经网络的工具箱

  • d2l:李沐老师《动手学深度学习》配套的教程工具包,里面有很多方便的函数(比如加载数据、训练可视化)


2. 加载 Fashion-MNIST 数据集

batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)
  • 这是一个衣服/鞋子/包包等 10 类小图片的数据集

  • 每张图是 28×28 像素(灰度图)

  • batch_size = 256:一次取 256 张图来训练,不会一次把所有数据塞进去(内存不够)

  • train_iter:训练数据迭代器

  • test_iter:测试(验证)数据迭代器

相当于:准备好一批图片,每次拿 256 张给模型看。


3. 定义输入输出维度

num_inputs, num_outputs, num_hiddens = 784, 10, 256
  • num_inputs = 784:一张 28×28 图片展平后就是 784 个像素点(特征)

  • num_outputs = 10:最后要分成 10 个类别(上衣、裤子、鞋等)

  • num_hiddens = 256:隐藏层大小(中间层的神经元个数),可以当作“可以调节的超参数”

就像:模型中间加一个“思考层”,有 256 个神经元。


4. 定义两层神经网络的参数(权重 W、偏置 b)

W1 = nn.Parameter(torch.randn(num_inputs, num_hiddens, requires_grad=True))
b1 = nn.Parameter(torch.zeros(num_hiddens, requires_grad=True))
W2 = nn.Parameter(torch.randn(num_hiddens, num_outputs, requires_grad=True))
b2 = nn.Parameter(torch.zeros(num_outputs, requires_grad=True))
params = [W1,b1,W2,b2]
  • nn.Parameter:告诉 PyTorch 这些变量是“需要被训练的参数”

  • torch.randn:随机初始化(从正态分布中取一些数)

  • requires_grad=True:PyTorch 会自动计算梯度,帮我们更新参数

  • 两个全连接层(也叫线性层):

    • 第一层:784 → 256

    • 第二层:256 → 10

你可以理解成:
第一层从 784 维压缩到 256 维(提取特征)
第二层从 256 维映射到 10 维(分类结果)


5. 实现 ReLU 激活函数

def relu(X):
    a = torch.zeros_like(X)
    return torch.max(X, a)
  • 对每个元素:如果是负数就变成 0,正数保持不变

  • 给神经网络引入“非线性能力”(不然多层线性层等于一层)

就像:负值直接“掐掉”,只让正信息往后传。


6. 前向传播(模型如何计算)

python

def net(X):
    X = X.reshape((-1, num_inputs))   # 把图片拉平
    H = relu(X @ W1 + b1)             # 第一层
    return H @ W2 + b2                # 第二层(得到 10 个分数)
  • X @ W1:矩阵乘法(等价于 torch.matmul

  • -1:自动推导 batch size(256)

你给模型一张图
→ 展平成 784 长度
→ 第一层算出 256 个值
→ ReLU 把负数变 0
→ 第二层算出 10 个分数(哪个类别的分数高,就预测是哪一类)


7. 损失函数

loss = nn.CrossEntropyLoss()
  • 交叉熵损失:专门用于分类问题

  • 它会同时做 softmax + 求损失,不需要我们自己写 softmax

相当于告诉模型:“你预测错的越离谱,我给你的分数越差”。


8. 训练模型

num_epochs ,lr = 30, 0.1
updater = torch.optim.SGD(params, lr=lr)
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, updater)
  • epochs = 30:把全部数据学习 30 遍

  • lr = 0.1:学习率(每次迈多大步子去优化)

  • SGD:随机梯度下降优化器,帮我们一步一步减小损失

  • train_ch3:d2l 提供的训练函数,会打印训练损失和准确率

这就是让模型一遍遍看数据,不断调整参数,直到效果还不错。


一句话总结

这段代码实现了一个两层全连接神经网络(MLP),手写数字/衣服分类任务,通过 30 轮迭代训练,让模型学会把 28×28 像素的图片分为 10 类。

2. 多层感知机(使用框架)

① 调用高级API更简洁地实现多层感知机。

import torch
from torch import nn
from d2l import torch as d2l

# 隐藏层包含256个隐藏单元,并使用了ReLU激活函数
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,)
        
net.apply(init_weights)

# 训练过程
batch_size, lr, num_epochs = 256, 0.1, 10
loss = nn.CrossEntropyLoss()
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)

1️⃣ 准备数据

batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)
  • 去网上下载一个叫 Fashion-MNIST 的数据集

  • 里面全是衣服、鞋子、包、裙子等 10 类图片

  • 分成两部分:

    • train_iter:训练集(用来学习)

    • test_iter:测试集(用来考试)

  • 每次看 256 张,不一次看完

就像:你有一本 1000 页的习题册,每次翻 256 页来学。


2️⃣ 搭建模型

net = nn.Sequential(
    nn.Flatten(),
    nn.Linear(784, 256),
    nn.ReLU(),
    nn.Linear(256, 10)
)

这段就是在“造大脑”:

  • Flatten:把 28×28 的图片拉成一长条(784 个数字)

  • Linear(784, 256):第一层“思考层”,把 784 个数字压缩成 256 个核心特征

  • ReLU:只把“正的想法”传下去,负的丢掉

  • Linear(256, 10):第二层,最终输出 10 个分数(每个类别一个分数)

分数最高的那一类,就是模型的“猜测”。


3️⃣ 初始化参数

def init_weights(m):
    if type(m) == nn.Linear:
        nn.init.normal_(m.weight, std=0.01)
net.apply(init_weights)
  • 给模型的“脑细胞”设一个初始值

  • 一开始什么都不会,但也不能全是 0(否则学不动)

就像:小朋友刚开始学认东西,脑子里啥也没有,但脑子结构是正常的。


4️⃣ 准备“裁判”和“教练”

loss = nn.CrossEntropyLoss()
trainer = torch.optim.SGD(net.parameters(), lr=0.1)
  • loss:判断模型猜得对不对、差多远(交叉熵损失)

  • trainer:根据“差多远”去调整模型的内部参数(SGD 优化器)

裁判打分,教练调动作。


5️⃣ 开始训练

d2l.train_ch3(net, train_iter, test_iter, loss, 10, trainer)
  • 模型把训练数据看 10 遍(epochs = 10)

  • 每看一遍,就调整一次内部的“脑细胞连接”

  • 训练过程中,会在测试集上看看效果怎么样了

就像:拿着习题册反复刷题,每刷一遍就进步一点。


一句话总结“整体思路”

准备一批图片 → 搭一个“脑残”模型 → 让模型一遍一遍看图片和正确答案 → 每次猜错就纠正内部参数 → 最后考试

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐