从Zero到Hero:跟随Andrej Karpathy的神经网络教程实现你的第一个AI模型

1次阅读
没有评论

共计 3066 个字符,预计需要花费 8 分钟才能阅读完成。

image.webp

神经网络入门实战指南

作为 AI 领域的经典入门教程,Andrej Karpathy 的 ”Neural Networks: Zero to Hero” 系列以独特的教学视角帮助无数开发者跨入深度学习大门。本文将结合 PyTorch 框架,带大家用代码实现第一个能识别手写数字的神经网络。

从 Zero 到 Hero:跟随 Andrej Karpathy 的神经网络教程实现你的第一个 AI 模型

一、神经网络核心概念速览

在开始写代码前,我们需要理解三个基本概念:

  1. 前向传播:数据从输入层流向输出层的过程,就像用公式计算预测值
  2. 反向传播:根据预测误差反向调整网络参数的神奇算法
  3. 损失函数:衡量预测结果与真实值差异的 ” 打分器 ”

用一个简单类比:神经网络就像学习骑自行车——前向传播是尝试骑行,损失函数是判断是否保持平衡,反向传播则是调整身体姿势的过程。

二、用 PyTorch 搭建第一个网络

让我们用经典的 MNIST 手写数字数据集实战。先准备好开发环境:

import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
import matplotlib.pyplot as plt

数据预处理

好的数据准备是成功的一半:

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

train_set = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
train_loader = torch.utils.data.DataLoader(train_set, batch_size=64, shuffle=True)

定义网络结构

构建一个包含两个隐藏层的神经网络:

class SimpleNN(nn.Module):
    def __init__(self):
        super(SimpleNN, self).__init__()
        self.fc1 = nn.Linear(28*28, 128)  # 第一层:784 输入 -> 128 输出
        self.fc2 = nn.Linear(128, 64)     # 第二层:128 输入 -> 64 输出
        self.fc3 = nn.Linear(64, 10)      # 输出层:64 输入 -> 10 分类

    def forward(self, x):
        x = x.view(-1, 28*28)  # 展平图片
        x = torch.relu(self.fc1(x))
        x = torch.relu(self.fc2(x))
        x = self.fc3(x)
        return x

训练循环实现

完整的训练流程包含以下步骤:

  1. 初始化模型和优化器
  2. 定义损失函数
  3. 前向传播计算预测值
  4. 反向传播更新权重
  5. 循环执行直到收敛
model = SimpleNN()
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)

for epoch in range(10):
    running_loss = 0.0
    for images, labels in train_loader:
        optimizer.zero_grad()
        outputs = model(images)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        running_loss += loss.item()
    print(f'Epoch {epoch+1}, Loss: {running_loss/len(train_loader):.4f}')

三、模型评估与可视化

训练完成后,我们可以用测试集评估模型表现:

test_set = datasets.MNIST(root='./data', train=False, download=True, transform=transform)
test_loader = torch.utils.data.DataLoader(test_set, batch_size=64, shuffle=False)

correct = 0
total = 0
with torch.no_grad():
    for images, labels in test_loader:
        outputs = model(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()

print(f'Accuracy: {100 * correct / total:.2f}%')

可视化部分预测结果:

# 随机选取测试样本
images, labels = next(iter(test_loader))
outputs = model(images)
_, predicted = torch.max(outputs, 1)

# 绘制前 16 个样本
fig = plt.figure(figsize=(10,10))
for idx in range(16):
    ax = fig.add_subplot(4, 4, idx+1)
    ax.imshow(images[idx].numpy().squeeze(), cmap='gray')
    ax.set_title(f'Pred: {predicted[idx]} | True: {labels[idx]}')
    ax.axis('off')
plt.tight_layout()
plt.show()

四、常见问题解决方案

1. 梯度消失问题

  • 症状:模型无法学习,损失几乎不下降
  • 解决:使用 ReLU 激活函数,合理初始化权重

2. 过拟合问题

  • 症状:训练集表现好但测试集差
  • 解决:添加 Dropout 层,使用 L2 正则化

改进后的网络结构示例:

class ImprovedNN(nn.Module):
    def __init__(self):
        super(ImprovedNN, self).__init__()
        self.fc1 = nn.Linear(28*28, 256)
        self.dropout1 = nn.Dropout(0.5)
        self.fc2 = nn.Linear(256, 128)
        self.dropout2 = nn.Dropout(0.3)
        self.fc3 = nn.Linear(128, 10)

    def forward(self, x):
        x = x.view(-1, 28*28)
        x = torch.relu(self.fc1(x))
        x = self.dropout1(x)
        x = torch.relu(self.fc2(x))
        x = self.dropout2(x)
        x = self.fc3(x)
        return x

五、进阶学习建议

  1. 扩展实验
  2. 尝试不同的网络结构(增加 / 减少层数)
  3. 调整学习率观察训练效果变化
  4. 用其他数据集(如 FashionMNIST)测试模型泛化能力

  5. 推荐资源

  6. Andrej Karpathy 原版视频教程
  7. 《Deep Learning with PyTorch》官方书籍
  8. PyTorch 官方文档和教程案例

  9. 调试技巧

  10. 使用 torchsummary 打印网络结构
  11. 在训练循环中添加验证集评估
  12. 使用 TensorBoard 可视化训练过程

结语

通过这个简单的 MNIST 分类任务,我们走完了神经网络从数据准备到模型训练的全流程。虽然现在的模型还很基础,但已经包含了深度学习的核心要素。建议读者在理解这些基础后,继续探索卷积神经网络 (CNN) 等更强大的模型结构。记住,在 AI 领域,持续的动手实践是最好的学习方式!

正文完
 0
评论(没有评论)