从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
评论(没有评论)