PyTorch 第一个神经网络:从零开始理解深度学习
在人工智能的浪潮中,神经网络是驱动智能系统的核心引擎。对于初学者来说,掌握 PyTorch 这一主流深度学习框架,是迈出实战第一步的关键。今天,我们就来一步步搭建一个真正意义上的“第一个神经网络”——不依赖复杂理论,而是通过真实代码与直观解释,带你亲手训练一个简单的分类模型。
你不需要有深厚的数学背景,只需要一点耐心和对编程的好奇心。就像学习骑自行车,一开始可能会摇晃,但只要坚持踩踏板,很快就能稳稳前行。
为什么选择 PyTorch?
PyTorch 是由 Facebook AI 团队开发的开源深度学习框架,以其动态计算图、简洁的 API 和强大的社区支持而广受欢迎。相比 TensorFlow 等框架,PyTorch 更加“Pythonic”,代码风格自然流畅,尤其适合研究和快速原型开发。
在构建“PyTorch 第一个神经网络”时,你会感受到它的直观性:定义模型像写函数一样简单,训练过程像流水线一样清晰。这种体验,正是它被越来越多高校和企业采用的原因。
准备工作:环境与数据
在动手之前,我们需要准备好运行环境。建议使用 Python 3.8 或更高版本,并通过 pip 安装 PyTorch。
pip install torch torchvision torchaudio
这个命令会安装 PyTorch 核心库、图像处理工具包和音频处理模块。其中 torch 是我们今天的核心。
接下来,我们使用一个经典的数据集——MNIST 手写数字数据集。它包含 6 万张训练图像和 1 万张测试图像,每张图像是 28x28 像素的灰度图,代表数字 0 到 9。
import torch
import torchvision
import torchvision.transforms as transforms
transform = transforms.Compose([
transforms.ToTensor(), # 将PIL图像转为Tensor
transforms.Normalize((0.5,), (0.5,)) # 归一化:均值0.5,标准差0.5
])
trainset = torchvision.datasets.MNIST(
root='./data',
train=True,
download=True,
transform=transform
)
trainloader = torch.utils.data.DataLoader(
trainset,
batch_size=4, # 每次加载4张图片
shuffle=True, # 打乱数据顺序,避免模型学习到顺序
num_workers=2 # 使用2个子进程并行加载
)
testset = torchvision.datasets.MNIST(
root='./data',
train=False,
download=True,
transform=transform
)
testloader = torch.utils.data.DataLoader(
testset,
batch_size=4,
shuffle=False,
num_workers=2
)
classes = ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9')
注释说明:
transforms.ToTensor()将图像像素值从 0~255 缩放到 0.0~1.0,这是神经网络的常见输入范围。Normalize进一步将数据中心化到 0,方差缩放到 1,有助于训练稳定。DataLoader是 PyTorch 的数据管道,它能自动分批、打乱、多线程加载数据,极大提升效率。batch_size=4表示每次训练时只处理 4 张图片,适合初学者调试。
构建神经网络模型
现在我们来定义一个简单的神经网络。它由三个部分组成:输入层、隐藏层和输出层。
import torch.nn as nn
import torch.nn.functional as F
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
# 定义第一个全连接层:输入784维(28x28像素展平),输出128维
self.fc1 = nn.Linear(28 * 28, 128)
# 定义第二个全连接层:输入128维,输出64维
self.fc2 = nn.Linear(128, 64)
# 定义输出层:输入64维,输出10维(对应10个数字类别)
self.fc3 = nn.Linear(64, 10)
def forward(self, x):
# 展平输入图像:将28x28的二维数据变成784的一维向量
x = x.view(-1, 28 * 28)
# 第一层:输入通过fc1,再经过ReLU激活函数
x = F.relu(self.fc1(x))
# 第二层:通过fc2,再激活
x = F.relu(self.fc2(x))
# 输出层:直接输出10个类别的得分(未归一化)
x = self.fc3(x)
return x
net = Net()
注释说明:
nn.Module是 PyTorch 所有神经网络模块的基类,自定义模型必须继承它。nn.Linear表示全连接层,即每个输入神经元与每个输出神经元相连。F.relu是激活函数,它让神经元只在输入大于0时“兴奋”,模拟生物神经元的行为。x.view(-1, 28*28)将图像从 (batch, 1, 28, 28) 转为 (batch, 784),这是模型输入的必要步骤。forward方法定义了数据如何流动,是模型的“大脑”。
损失函数与优化器
训练神经网络的核心是“让模型不断试错,逐步减少错误”。这需要两个关键组件:损失函数和优化器。
import torch.optim as optim
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001)
注释说明:
CrossEntropyLoss是分类任务的标准损失函数。它结合了 Softmax 和负对数似然,能自动处理输出概率。optimizer.SGD是最基础的优化算法,它根据梯度方向调整权重,学习率lr=0.001控制每次更新的幅度。net.parameters()会自动提取模型中所有可训练的参数(权重和偏置),供优化器使用。
开始训练:完整训练循环
现在,我们进入真正的训练阶段。一个完整的训练过程包含前向传播、计算损失、反向传播和参数更新四个步骤。
for epoch in range(2): # 训练2个周期(epoch)
running_loss = 0.0
for i, data in enumerate(trainloader, 0):
# 1. 获取输入数据和标签
inputs, labels = data
# 2. 梯度清零(防止累积)
optimizer.zero_grad()
# 3. 前向传播:模型预测输出
outputs = net(inputs)
# 4. 计算损失
loss = criterion(outputs, labels)
# 5. 反向传播:计算梯度
loss.backward()
# 6. 优化器更新参数
optimizer.step()
# 累积损失
running_loss += loss.item()
# 每2000个批次打印一次损失
if i % 2000 == 1999:
print(f'Epoch: {epoch + 1}, Batch: {i + 1}, Loss: {running_loss / 2000:.3f}')
running_loss = 0.0
print('训练完成!')
注释说明:
epoch=2表示整个数据集被遍历两次。实际项目中可能需要几十甚至上百个 epoch。optimizer.zero_grad()清除上一轮的梯度,避免影响当前更新。loss.backward()是反向传播的核心,它计算每个参数对损失的敏感度。optimizer.step()根据梯度更新权重。- 每 2000 个批次输出一次损失,帮助我们观察训练趋势。
模型测试与评估
训练结束后,我们需要在未见过的数据上测试模型表现。
correct = 0
total = 0
with torch.no_grad(): # 不计算梯度,节省内存
for data in testloader:
images, labels = data
outputs = net(images)
# 获取最大得分的类别作为预测结果
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print(f'测试集准确率: {100 * correct / total:.2f}%')
注释说明:
torch.no_grad()禁用梯度计算,因为测试阶段不需要反向传播。torch.max(outputs.data, 1)找出每张图预测的最高得分类别(即模型认为的数字)。predicted == labels返回布尔数组,sum().item()统计正确预测的数量。
运行这段代码,你可能会看到类似“测试集准确率: 90.12%”的结果。这说明你的“PyTorch 第一个神经网络”已经成功训练并具备了一定的识别能力!
总结与展望
通过这篇文章,你已经亲手完成了从环境搭建、数据准备、模型定义到训练评估的完整流程。这个过程虽然简单,却是所有深度学习项目的基石。
记住:每一个复杂的神经网络,都是从这样一个“最小可运行版本”开始的。你今天的每一步,都在为未来的模型设计、图像识别、自然语言处理打下基础。
接下来,你可以尝试:
- 增加网络层数或调整隐藏层大小
- 更换优化器(如 Adam)
- 添加正则化(Dropout)
- 将模型保存为
.pt文件,用于后续加载使用
当你看到模型准确率从 10% 提升到 90% 时,那种成就感,是编程世界中最动人的时刻之一。
现在,你不再是“看别人写代码”的人,而是真正“写出代码”的开发者。欢迎进入深度学习的大门。