Day 78:【99天精通Python】深度学习入门 (PyTorch) 上篇 - 张量与自动求导

前言

欢迎来到第78天!

从今天开始,我们将触及 AI 技术皇冠上的明珠——深度学习 (Deep Learning)
无论是 ChatGPT、AI 绘画,还是自动驾驶,它们背后的核心都是神经网络。而要搭建和训练神经网络,我们需要一个趁手的框架。

PyTorch 是目前学术界和工业界最流行的深度学习框架之一(另一个是 TensorFlow)。它以动态图机制著称,代码写起来就像普通的 Python 代码一样自然、易调试。

本节内容:

  • PyTorch 安装与环境配置
  • 核心数据结构:张量 (Tensor)
  • 张量 vs NumPy 数组
  • 自动求导 (Autograd) 机制
  • 线性回归实战:手写第一个神经网络

一、环境准备

推荐安装 CPU 版本(学习足够用了)。如果你有 NVIDIA 显卡,可以安装 CUDA 版本。

# 访问 pytorch.org 查看适合你系统的命令
pip install torch torchvision

验证安装:

import torch
print(torch.__version__)
print(torch.cuda.is_available()) # True 表示可以使用 GPU

二、张量 (Tensor):PyTorch 的基石

张量本质上就是一个多维数组,这和 NumPy 的 ndarray 非常像。
区别在于:张量可以运行在 GPU 上,且支持自动求导。

2.1 创建张量

import torch
import numpy as np

# 1. 直接创建
x = torch.tensor([1, 2, 3])
print(x)

# 2. 从 NumPy 创建
arr = np.array([[1, 2], [3, 4]])
x_np = torch.from_numpy(arr)

# 3. 随机/全0/全1 (API 和 NumPy 几乎一样)
rand = torch.rand(2, 3) # 0-1 均匀分布
zeros = torch.zeros(2, 3)
ones = torch.ones(2, 3)

2.2 张量运算

x = torch.tensor([10, 20, 30])
y = torch.tensor([1, 2, 3])

# 加减乘除 (Element-wise)
print(x + y) # tensor([11, 22, 33])
print(x * y) # tensor([10, 40, 90])

# 矩阵乘法 (@ 或 matmul)
a = torch.tensor([[1, 2], [3, 4]])
b = torch.tensor([[5, 6], [7, 8]])
print(a @ b) 
# 1*5+2*7=19 ...

2.3 GPU 加速 (如果有显卡)

if torch.cuda.is_available():
    device = torch.device("cuda")
    x = x.to(device) # 把张量搬到显存
    y = y.to(device)
    z = x + y        # 在 GPU 上计算
    print(z)
    # 结果无法直接转 numpy,必须先搬回 cpu
    # print(z.cpu().numpy())

三、自动求导 (Autograd)

深度学习的核心算法是反向传播 (Backpropagation),即根据误差计算梯度(导数),从而更新模型参数。
PyTorch 的 autograd 模块帮我们自动完成了这一复杂的微积分过程。

3.1 requires_grad

# 创建张量,并告诉 PyTorch:我要对它求导
w = torch.tensor([1.0], requires_grad=True)
x = torch.tensor([2.0])
b = torch.tensor([3.0], requires_grad=True)

# 前向传播 (Forward):构建计算图
# y = w * x + b
y = w * x + b  # 1*2 + 3 = 5

# 后向传播 (Backward):自动计算梯度
# 计算 dy/dw, dy/db
y.backward()

# 查看梯度
print(w.grad) # dy/dw = x = 2.0
print(b.grad) # dy/db = 1.0

原理:PyTorch 会在后台构建一张动态计算图,记录所有的操作历史。调用 backward() 时,它会沿着图反向走一遍,算出所有叶子节点(w, b)的梯度。


四、实战:手动实现线性回归

我们来模拟一个最简单的机器学习任务:拟合直线 y = 2x + 5

4.1 准备数据

# 生成 100 个数据点
# y = 2x + 5 + 噪声
x_train = torch.rand(100, 1) * 10  # 0-10 之间
y_train = 2 * x_train + 5 + torch.randn(100, 1) * 0.5 # 加点高斯噪声

# 查看前5个
print(x_train[:5], y_train[:5])

4.2 训练模型

我们要训练两个参数 wb,让 w*x + b 尽可能接近 y_train

# 1. 初始化参数 (随机猜一个)
w = torch.randn(1, 1, requires_grad=True)
b = torch.randn(1, 1, requires_grad=True)

learning_rate = 0.01  # 学习率

for epoch in range(1000):
    # 2. 前向传播:计算预测值
    y_pred = x_train @ w + b
    
    # 3. 计算损失 (Loss):均方误差 (MSE)
    loss = (y_pred - y_train).pow(2).mean()
    
    # 4. 反向传播:计算梯度
    # 每次 backward 前必须清零梯度,否则会累加!
    if w.grad is not None:
        w.grad.zero_()
        b.grad.zero_()
        
    loss.backward()
    
    # 5. 更新参数 (Gradient Descent)
    # 使用 torch.no_grad(),因为更新参数的操作不需要记录进计算图
    with torch.no_grad():
        w -= learning_rate * w.grad
        b -= learning_rate * b.grad
        
    if epoch % 100 == 0:
        print(f"Epoch {epoch}: Loss = {loss.item():.4f}")

print(f"训练结果: w={w.item():.2f}, b={b.item():.2f}")
# 预期接近 w=2.00, b=5.00

五、常见问题

Q1:为什么要 grad.zero_()

PyTorch 设计为梯度累加。如果不清零,第 2 轮的梯度 = 第 1 轮梯度 + 第 2 轮梯度,这会导致更新方向错误。

Q2:with torch.no_grad(): 是什么?

在更新参数 w -= lr * w.grad 时,这只是一个数值更新操作,我们不希望 PyTorch 把它也算作计算图的一部分(否则下次 backward 会出错)。这也用于推理阶段(Inference)以节省内存。

Q3:tensor.item()

当张量只包含一个数值时(scalar),用 .item() 把它转为 Python 的 float/int。


六、小结

PyTorch 基础

Tensor (张量)

Autograd (自动求导)

训练流程

多维数组

支持 GPU

requires_grad=True

backward()

tensor.grad

Forward (算 Loss)

Backward (算梯度)

Update (减梯度)

Zero Grad (清零)

关键要点

  1. Tensor 是深度学习的数据容器。
  2. Autograd 让反向传播变得自动化。
  3. 训练循环 4 步走:算预测 -> 算 Loss -> Backward -> 更新参数。

七、课后作业

  1. 二次函数拟合:修改上面的代码,尝试拟合曲线 y = 3x^2 + 2x + 1。(提示:你需要三个参数 w1, w2, b,或者构造特征 x^2)。
  2. GPU 加速体验:如果你的电脑有显卡(或使用 Colab),尝试将张量移动到 .to('cuda') 上运行,对比大数据量下的矩阵乘法速度。
  3. 手动求导:复习一下高数,手动计算 y = w*x + bw 的偏导数,看看和 w.grad 的值是不是一样。

下节预告

Day 79:深度学习入门 (PyTorch) 下篇 - 神经网络 (nn.Module) - 手动更新参数太累了。明天我们学习 PyTorch 的高级 API,用搭积木的方式构建真正的神经网络!


系列导航

  • 上一篇:Day 77 - 计算机视觉OpenCV
  • 下一篇:Day 79 - 深度学习PyTorch下(待更新)
Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐