多层感知机

Admin
发布于 2026-05-26 / 2 阅读
0
0
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader

# Load the dataset
transform = transforms.Compose([
    transforms.ToTensor()  # Automatically converts to tensor and scales to [0, 1]
])
train_dataset = datasets.FashionMNIST(root='./data', train=True, download=True, transform=transform)
test_dataset = datasets.FashionMNIST(root='./data', train=False, download=True, transform=transform)

train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False)

# Define the model
class FashionMNISTModel(nn.Module):
    def __init__(self):
        super(FashionMNISTModel, self).__init__()
        self.flatten = nn.Flatten()
        self.linear_relu_stack = nn.Sequential(
            nn.Linear(28*28, 128),
            nn.ReLU(),
            nn.Linear(128, 10),
            nn.LogSoftmax(dim=1)
        )

    def forward(self, x):
        x = self.flatten(x)
        logits = self.linear_relu_stack(x)
        return logits

model = FashionMNISTModel()

# Define the loss function and optimizer
loss_function = nn.NLLLoss()
optimizer = optim.Adam(model.parameters())

# Train the model
def train(dataloader, model, loss_fn, optimizer):
    size = len(dataloader.dataset)
    model.train()
    for batch, (X, y) in enumerate(dataloader):
        # Compute prediction and loss
        pred = model(X)
        loss = loss_fn(pred, y)

        # Backpropagation
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        if batch % 100 == 0:
            loss, current = loss.item(), batch * len(X)
            print(f"loss: {loss:>7f}  [{current:>5d}/{size:>5d}]")

# Training process
epochs = 5
for t in range(epochs):
    print(f"Epoch {t+1}\n-------------------------------")
    train(train_loader, model, loss_function, optimizer)
print("Done!")

这段代码是一个使用 PyTorch 框架实现的经典深度学习图像分类任务,目标是训练一个多层感知机(MLP,即全连接神经网络)来对 FashionMNIST 数据集(时尚商品图片,如衣服、鞋子等)进行分类。

下面我将从**实现原理**、**用途**和**注意事项**三个方面为您详细解释这段代码。

---

### 一、 实现原理(代码逐段解析)

代码的执行流程遵循深度学习的标准范式:数据准备 -> 模型定义 -> 定义损失函数与优化器 -> 训练循环。

#### 1. 数据准备

```python

transform = transforms.Compose([transforms.ToTensor()])

train_dataset = datasets.FashionMNIST(...)

train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)

```

* transforms.ToTensor():将 PIL 图像或 NumPy 数组转换为 PyTorch 张量,并**自动将像素值从 [0, 255] 归一化到 [0.0, 1.0]**。

* FashionMNIST:下载并加载 FashionMNIST 数据集,包含 60,000 张训练图和 10,000 张测试图,每张图是 28x28 的灰度图,共 10 个类别。

* DataLoader:将数据集打包成批次,每批 64 张图片batch_size=64shuffle=True 表示在每个 epoch 开始时打乱训练数据顺序,以增加随机性,帮助模型更好地收敛。

#### 2. 模型定义

```python

class FashionMNISTModel(nn.Module):

def init(self):

...

self.flatten = nn.Flatten()

self.linear_relu_stack = nn.Sequential(

nn.Linear(28*28, 128),

nn.ReLU(),

nn.Linear(128, 10),

nn.LogSoftmax(dim=1)

)

```

* nn.Flatten():将二维图片(形状为 [64, 1, 28, 28])展平为一维向量(形状为 [64, 784]),因为全连接层只能接收一维输入。

* **nn.Linear(28*28, 128)**:输入层到隐藏层的全连接操作,将 784 维映射到 128 维。

* nn.ReLU():激活函数,引入非线性,解决线性模型表达能力不足的问题。

* nn.Linear(128, 10):隐藏层到输出层的全连接操作,映射到 10 个类别。

* nn.LogSoftmax(dim=1):对输出取对数软最大化。它将输出转化为各个类别的对数概率,数值范围在负无穷到 0 之间。

#### 3. 损失函数与优化器

```python

loss_function = nn.NLLLoss()

optimizer = optim.Adam(model.parameters())

```

* NLLLoss (负对数似然损失):常与 LogSoftmax 搭配使用,本质上等价于交叉熵损失。它衡量模型预测的对数概率与真实标签之间的差异。

* Adam 优化器:一种自适应学习率的随机梯度下降算法,是目前最常用的优化器之一,收敛速度快。

#### 4. 训练循环

```python

def train(dataloader, model, loss_fn, optimizer):

model.train()

for batch, (X, y) in enumerate(dataloader):

pred = model(X) # 前向传播:计算预测值

loss = loss_fn(pred, y) # 计算损失

optimizer.zero_grad() # 清除上一轮的梯度

loss.backward() # 反向传播:计算梯度

optimizer.step() # 更新权重参数

```

这是深度学习训练的核心四步:

1. 前向传播:将图片输入模型,得到预测结果。

2. 计算损失:对比预测结果和真实标签。

3. 梯度清零:PyTorch 默认会累加梯度,每次迭代前必须清零。

4. 反向传播与更新:根据损失计算各参数的梯度,并更新模型权重。

---

### 二、 用途

1. 图像分类基准测试:FashionMNIST 是 MNIST(手写数字)的现代替代品,比 MNIST 更难,常用于测试和验证深度学习算法的有效性。

2. 深度学习入门教学:这段代码结构完整、逻辑清晰,是非常标准的 PyTorch 教学代码,适合初学者理解神经网络的工作流。

3. 快速原型开发:该模型体积小、训练快(CPU 上几分钟即可跑完 5 个 epoch),适合在开发新算法或调试代码时作为基础骨架使用。

---

### 三、 注意事项与改进建议

1. 损失函数与输出层的冗余问题(可优化)

当前代码使用了 nn.LogSoftmax(dim=1) + nn.NLLLoss()。这在数学上完全正确,但 PyTorch 官方*更推荐直接使用 nn.CrossEntropyLoss()**。

* CrossEntropyLoss 内部已经集成了 LogSoftmax 操作,数值稳定性更好。如果改用 CrossEntropyLoss,需要将模型最后一行 nn.LogSoftmax(dim=1) 删除,直接输出 nn.Linear(128, 10) 的 logits 即可。

2. 缺少测试/验证环节

代码只写了 train 函数,虽然加载了 test_dataset,但并未在训练过程中评估模型在测试集上的表现。这容易导致*过拟合**而不知情。建议在每个 epoch 结束后添加验证循环,计算测试集准确率。

3. 未使用 GPU 加速

* 当前代码默认在 CPU 上运行。如果需要加速训练,应将模型和数据移动到 GPU 上:

```python

device = "cuda" if torch.cuda.is_available() else "cpu"

model = FashionMNISTModel().to(device)

# 在训练循环中:

X, y = X.to(device), y.to(device)

```

4. 模型表达能力有限

这是一个简单的全连接网络(MLP),它破坏了图像的空间结构(展平操作导致像素间的位置关系丢失)。对于更复杂的图像任务,准确率会遇到瓶颈。若要提升性能,应改用*卷积神经网络(CNN)**(如 ResNet, LeNet 等)。

5. 学习率未显式指定

* optim.Adam(model.parameters()) 使用了 Adam 的默认学习率 lr=0.001。虽然对于这个任务通常有效,但在实际项目中,建议显式指定学习率,并将其作为超参数进行调优。

100%|██████████| 26.4M/26.4M [10:57<00:00, 40.2kB/s]

100%|██████████| 29.5k/29.5k [00:00<00:00, 113kB/s]

100%|██████████| 4.42M/4.42M [01:00<00:00, 73.2kB/s]

100%|██████████| 5.15k/5.15k [00:00<00:00, 1.85MB/s]

Epoch 1

-------------------------------

loss: 2.314217 [ 0/60000]

loss: 0.678389 [ 6400/60000]

loss: 0.491603 [12800/60000]

loss: 0.396077 [19200/60000]

loss: 0.695226 [25600/60000]

loss: 0.497115 [32000/60000]

loss: 0.561746 [38400/60000]

loss: 0.349504 [44800/60000]

loss: 0.381095 [51200/60000]

loss: 0.483273 [57600/60000]

Epoch 2

-------------------------------

loss: 0.312787 [ 0/60000]

loss: 0.396534 [ 6400/60000]

loss: 0.470441 [12800/60000]

loss: 0.271157 [19200/60000]

loss: 0.292252 [25600/60000]

loss: 0.371871 [32000/60000]

loss: 0.406447 [38400/60000]

loss: 0.277172 [44800/60000]

loss: 0.278196 [51200/60000]

loss: 0.339613 [57600/60000]

Epoch 3

-------------------------------

loss: 0.292249 [ 0/60000]

loss: 0.623855 [ 6400/60000]

loss: 0.381458 [12800/60000]

loss: 0.451805 [19200/60000]

loss: 0.387722 [25600/60000]

loss: 0.372676 [32000/60000]

loss: 0.306402 [38400/60000]

loss: 0.301555 [44800/60000]

loss: 0.278181 [51200/60000]

loss: 0.273917 [57600/60000]

Epoch 4

-------------------------------

loss: 0.294174 [ 0/60000]

loss: 0.518456 [ 6400/60000]

loss: 0.266501 [12800/60000]

loss: 0.227342 [19200/60000]

loss: 0.472201 [25600/60000]

loss: 0.210108 [32000/60000]

loss: 0.309315 [38400/60000]

loss: 0.223636 [44800/60000]

loss: 0.355733 [51200/60000]

loss: 0.194906 [57600/60000]

Epoch 5

-------------------------------

loss: 0.452234 [ 0/60000]

loss: 0.343128 [ 6400/60000]

loss: 0.344998 [12800/60000]

loss: 0.194488 [19200/60000]

loss: 0.336010 [25600/60000]

loss: 0.263695 [32000/60000]

loss: 0.297133 [38400/60000]

loss: 0.361028 [44800/60000]

loss: 0.285834 [51200/60000]

loss: 0.357167 [57600/60000]

Done!

A breathtaking, detailed visualization showing the process of AI understanding fashion. On one side, vibrant, richly textured images of various clothing items (dresses, shoes, shirts) are visible. These images are not just flat pictures, but are transforming into complex, glowing streams of data points and geometric vectors. These streams flow into a central, massive, multi-layered neural network core (the MLP). Within the core, abstract nodes and glowing connections are working, transforming the chaotic data into a single, definitive, categorized output (e.g., a clear label glowing 'SHOE'). The aesthetic should be a fusion of digital circuit boards and Renaissance textile art. Cinematic lighting, Hyperdetailed, Octane render, 8K


评论