深度学习 PyTorch:张量、自动求导与模块

FreeGuideOnline 最新 2026-06-16

什么是 PyTorch

PyTorch 是一个基于 Python 的深度学习框架,提供了强大的 GPU 加速张量计算和自动求导系统。它的设计理念是灵活、直观、易于调试,非常适合研究和快速原型开发。本教程将带你从零掌握三个核心概念:张量自动求导模块,为你搭建现代神经网络打下坚实基础。

安装与环境配置

推荐使用 PyTorch 官方命令安装,可自动匹配 CUDA 版本:

# CPU 版本
pip install torch torchvision torchaudio

# CUDA 11.8 版本(示例)
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118

安装后验证:

import torch
print(torch.__version__)
print(torch.cuda.is_available())   # 检查 GPU 是否可用

张量:深度学习的数据基石

张量(Tensor)是 PyTorch 中最基本的数据结构,你可以把它理解为多维数组,类似 NumPy 的 ndarray,但额外支持 GPU 加速和自动求导。

创建张量

import torch

# 从列表创建
a = torch.tensor([1, 2, 3])
print(a)          # tensor([1, 2, 3])

# 全0、全1、未初始化
zeros = torch.zeros(2, 3)     # 2行3列
ones = torch.ones(3, 4)
empty = torch.empty(2, 2)     # 未初始化,值随机

# 从 NumPy 转换(共享内存)
import numpy as np
arr = np.array([4, 5, 6])
b = torch.from_numpy(arr)

# 生成特定范围的张量
c = torch.arange(0, 10, 2)    # tensor([0, 2, 4, 6, 8])
d = torch.linspace(0, 1, 5)   # tensor([0.0000, 0.2500, 0.5000, 0.7500, 1.0000])

张量属性

x = torch.randn(2, 3, 4)      # 随机张量,形状 (2,3,4)
print(x.shape)                # torch.Size([2, 3, 4])
print(x.dtype)                # torch.float32
print(x.device)               # cpu
print(x.ndim)                 # 3(维度数)

基本运算

张量支持与 NumPy 相似的向量化运算,且大多数操作都在 GPU 上无缝运行。

x = torch.tensor([1.0, 2.0, 3.0])
y = torch.tensor([4.0, 5.0, 6.0])

# 加减乘除
print(x + y)                  # tensor([5., 7., 9.])
print(x * y)                  # 逐元素乘
print(x @ y)                  # 点积(内积),等价于 torch.dot(x, y)

# 矩阵乘法
A = torch.randn(2, 3)
B = torch.randn(3, 4)
C = torch.mm(A, B)            # 形状 (2,4)
# 或使用 @ 运算符
C = A @ B

# 变形操作
t = torch.arange(12).reshape(3, 4)   # 改为3行4列
print(t.view(4, 3))                  # view 与 reshape 类似,但需内存连续
print(t.transpose(0, 1))             # 转置
print(t.squeeze())                   # 移除尺寸为1的维度
print(t.unsqueeze(0))                # 在第0维插入一个维度

GPU 张量

将张量转移到 GPU 非常简单:

if torch.cuda.is_available():
    device = torch.device("cuda")
    x = torch.tensor([1.0, 2.0]).to(device)
    y = torch.randn(2, 2, device=device)
    z = x + y               # 运算在GPU上执行

张量是 PyTorch 的通行证,后续所有神经网络中的输入、权重、输出全部以张量形式存在。


自动求导:省去手算梯度的烦恼

PyTorch 的自动求导系统(Autograd)能够自动计算任意张量操作的梯度,这是训练神经网络的核心机制。只要将张量的 requires_grad 属性设为 True,PyTorch 就会追踪该张量上的所有操作,并根据链式法则自动计算梯度。

一个简单的例子

x = torch.tensor(2.0, requires_grad=True)
y = x ** 3 + 5 * x + 2
print(y)                     # tensor(20., grad_fn=<AddBackward0>)

观察输出中的 grad_fn,它记录了该张量是通过什么运算得到的。调用反向传播:

y.backward()                 # 计算 dy/dx
print(x.grad)                # tensor(17.) 因为 3*x^2 + 5 = 3*4+5=17

多变量与向量梯度

对于多变量函数,通常会对一个标量损失执行 backward(),然后查看每个参数的梯度。

w = torch.tensor([1.0, 2.0], requires_grad=True)
b = torch.tensor(0.0, requires_grad=True)

# 模拟一个简单线性输出
x = torch.tensor([2.0, 3.0])
y = torch.dot(w, x) + b      # 点积 + 偏置

y.backward()
print(w.grad)                # tensor([2., 3.])  dy/dw = x
print(b.grad)                # tensor(1.)        dy/db = 1

如果 y 不是标量,需要传入一个与 y 形状相同的梯度参数:

v = torch.tensor([1.0, 0.1], requires_grad=True)
u = v ** 2                   # u = [v1^2, v2^2]
u.backward(torch.tensor([1.0, 0.5]))
print(v.grad)                # [2*v1*1.0, 2*v2*0.5]

动态计算图与 torch.no_grad()

PyTorch 的计算图是动态的,每次前向都会重新构建,这使得模型可以灵活控制流(如 if 语句、循环)。在评估或推理时,我们不需要计算梯度,可以使用 torch.no_grad() 减少内存消耗并加速计算:

x = torch.randn(100, 10, requires_grad=True)
with torch.no_grad():
    y = x @ x.T              # 此操作不会被追踪

梯度清零

训练循环中每次反向传播前,必须手动清空梯度,否则梯度会累加:

optimizer.zero_grad()        # 常用在优化器中
# 或直接
if w.grad is not None:
    w.grad.zero_()

nn.Module:构建神经网络的标准方式

PyTorch 提供了 torch.nn 模块来搭建神经网络。其中 nn.Module 是所有网络层的基类,通过继承并实现 __init__forward 方法,可以构建任意复杂的模型。

定义一个简单网络

import torch.nn as nn
import torch.nn.functional as F

class SimpleNet(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super(SimpleNet, self).__init__()
        self.fc1 = nn.Linear(input_size, hidden_size)   # 全连接层
        self.fc2 = nn.Linear(hidden_size, output_size)

    def forward(self, x):
        x = F.relu(self.fc1(x))          # 激活函数
        x = self.fc2(x)
        return x

模型实例化后,可以像函数一样调用,自动执行 forward 方法:

model = SimpleNet(10, 20, 1)
x = torch.randn(5, 10)                  # 5个样本,每个维度10
output = model(x)
print(output.shape)                     # torch.Size([5, 1])

常用网络层一览

层类型 说明 示例
nn.Linear 全连接层 nn.Linear(in, out)
nn.Conv2d 二维卷积 nn.Conv2d(in_c, out_c, k)
nn.LSTM 长短时记忆网络 nn.LSTM(input, hidden)
nn.BatchNorm2d 批归一化 nn.BatchNorm2d(num_features)
nn.Dropout 随机失活 nn.Dropout(p=0.5)
nn.ReLU / nn.Sigmoid 激活函数 nn.ReLU()

训练循环的标准写法

下面是一个极简训练循环,展示了模型、损失函数、优化器如何协作:

# 假数据
X = torch.randn(100, 10)
y = torch.randn(100, 1)

model = SimpleNet(10, 20, 1)
criterion = nn.MSELoss()               # 均方误差损失
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

epochs = 50
for epoch in range(epochs):
    # 前向
    pred = model(X)
    loss = criterion(pred, y)

    # 反向传播
    optimizer.zero_grad()               # 清零梯度
    loss.backward()                     # 计算梯度
    optimizer.step()                    # 更新参数

    if (epoch+1) % 10 == 0:
        print(f'Epoch {epoch+1}, Loss: {loss.item():.4f}')

参数管理与模型保存

model.parameters() 返回所有可学习参数,可以直接用于优化器。模型的保存和加载非常简单:

# 保存
torch.save(model.state_dict(), 'model.pth')

# 加载
model = SimpleNet(10, 20, 1)           # 同样结构的模型
model.load_state_dict(torch.load('model.pth'))
model.eval()                           # 切换到评估模式(影响 dropout/bn 等)

综合示例:线性回归从零实现

让我们用一个完整例子巩固张量、自动求导和模块的知识。使用 nn.Module 拟合一个线性函数。

import torch
import torch.nn as nn
import torch.optim as optim

# 生成数据 y = 3x + 2 + 噪声
torch.manual_seed(42)
X = torch.randn(200, 1) * 10
true_w = 3.0
true_b = 2.0
y = true_w * X + true_b + torch.randn(200, 1) * 2

# 定义模型
class LinearReg(nn.Module):
    def __init__(self):
        super().__init__()
        self.linear = nn.Linear(1, 1)    # 输入1维,输出1维

    def forward(self, x):
        return self.linear(x)

model = LinearReg()
loss_fn = nn.MSELoss()
optimizer = optim.SGD(model.parameters(), lr=0.001)

# 训练
for epoch in range(100):
    model.train()
    pred = model(X)
    loss = loss_fn(pred, y)

    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

    if (epoch+1) % 20 == 0:
        print(f"Epoch {epoch+1}: loss = {loss.item():.4f}")

# 打印学习到的参数
w, b = model.linear.weight.item(), model.linear.bias.item()
print(f"Learned: w = {w:.3f}, b = {b:.3f}")
print(f"True:    w = {true_w}, b = {true_b}")

运行后可以看到模型成功逼近了真实参数。这段代码完美融合了 张量生成自动求导模块搭建 三大知识点。


下一步学习建议

  • 深入阅读 PyTorch 官方文档的 torch.Tensortorch.autogradtorch.nn 部分。
  • 尝试构建更复杂的模型(如 CNN、RNN),并应用到图像或文本数据上。
  • 学习 torch.utils.data.DatasetDataLoader 实现高效数据加载。
  • 探索 PyTorch Lightning 等高级接口,让训练流程更整洁。

掌握张量、自动求导与模块这三柄利器,你已经敲开了深度学习的大门。接下来,就是在真实数据集上不断实践、调优,让模型为你所用。