PyTorch 基础
学习目标
- 理解什么是
Tensor - 掌握张量的创建、形状、数据类型和常用运算
- 理解 PyTorch 和 NumPy 的关系
- 能独立读懂最基本的张量操作代码
一、张量到底是什么?
最实用的理解方式是:
张量 = 能在 CPU / GPU 上计算的多维数组
如果你学过 NumPy,可以先把它想成“升级版 ndarray”:
- 能做数值运算
- 能放到 GPU 上
- 能参与自动求导
类比一下:
| 概念 | 类比 |
|---|---|
| 标量(0 维) | 一个数字 |
| 向量(1 维) | 一排数字 |
| 矩阵(2 维) | 一张表 |
| 张量(更高维) | 一叠表 / 一批图片 / 一段视频 |
在深度学习里,几乎所有数据最后都会变成张量:
- 一张灰度图:
[高度, 宽度] - 一张彩色图:
[通道, 高度, 宽度] - 一批图片:
[批大小, 通道, 高度, 宽度] - 一批句子的词向量:
[批大小, 序列长度, 向量维度]
二、创建张量
运行环境
下面的代码可以直接运行。若本地未安装:
pip install torch
import torch
# 从 Python 列表创建
scores = torch.tensor([88, 92, 76, 95])
print(scores)
# 指定数据类型
prices = torch.tensor([12.5, 19.9, 8.8], dtype=torch.float32)
print(prices.dtype)
# 常见的初始化方式
zeros = torch.zeros((2, 3))
ones = torch.ones((2, 3))
randn = torch.randn((2, 3))
arange = torch.arange(0, 10, 2)
print("zeros:\n", zeros)
print("ones:\n", ones)
print("randn:\n", randn)
print("arange:", arange)
三、形状、维度和数据类型
初学深度学习,最容易卡住的不是公式,而是形状(shape)。
你可以把 shape 理解成“这个数据盒子有几层、每层装多少个元素”。
import torch
X = torch.tensor([
[1.0, 2.0, 3.0],
[4.0, 5.0, 6.0]
])
print("张量:\n", X)
print("shape:", X.shape) # torch.Size([2, 3])
print("ndim:", X.ndim) # 2 维
print("dtype:", X.dtype) # float32
print("元素总数:", X.numel()) # 6
一个非常重要的习惯
写模型前,先问自己:
- 这个张量每一维是什么意思?
- 当前形状对不对?
- 下一层会期待什么形状?
很多训练报错,本质上都是 shape 不匹配。
四、索引、切片、变形
import torch
X = torch.tensor([
[10, 20, 30],
[40, 50, 60],
[70, 80, 90]
])
print("第 0 行:", X[0])
print("第 1 行第 2 列:", X[1, 2])
print("前两行:\n", X[:2])
print("第 2 列:", X[:, 1])
# 变形
flat = X.reshape(9)
grid = flat.reshape(3, 3)
print("拉平:", flat)
print("重新变回 3x3:\n", grid)
reshape 的直觉
就像你把一盒积木重新摆放:
- 元素个数不能变
- 只是换了一种组织方式
五、张量运算
import torch
a = torch.tensor([1.0, 2.0, 3.0])
b = torch.tensor([4.0, 5.0, 6.0])
print("加法:", a + b)
print("减法:", a - b)
print("逐元素乘法:", a * b)
print("平方:", a ** 2)
print("求和:", a.sum())
print("均值:", a.mean())
矩阵乘法
深度学习里最常见的运算之一就是矩阵乘法:
import torch
X = torch.tensor([[1.0, 2.0],
[3.0, 4.0]])
W = torch.tensor([[2.0, 0.0],
[0.0, 2.0]])
Y = X @ W
print(Y)
这和你在第三阶段学的线性代数是同一件事。
神经网络里的很多层,本质上都是“张量做线性变换,再过一个非线性函数”。
六、广播机制
广播是 PyTorch 里一个特别省代码的机制。
它的直觉是:
“如果两个张量形状不完全一样,但差得不多,PyTorch 会自动帮你扩展。”
import torch
scores = torch.tensor([
[80.0, 85.0, 90.0],
[70.0, 75.0, 88.0]
])
bonus = torch.tensor([5.0, 5.0, 5.0])
print(scores + bonus)
这里 bonus 的 shape 是 [3],scores 的 shape 是 [2, 3]。
PyTorch 会自动把 bonus 当成每一行都加一次。
广播的常见用法
- 给一批样本统一加偏置
- 对图像做归一化
- 对 batch 中每个特征做缩放
七、和 NumPy 互转
NumPy 和 PyTorch 的关系非常近,所以互转很常见。
import numpy as np
import torch
arr = np.array([[1, 2], [3, 4]], dtype=np.float32)
tensor = torch.from_numpy(arr)
print("NumPy -> Tensor:\n", tensor)
back_to_numpy = tensor.numpy()
print("Tensor -> NumPy:\n", back_to_numpy)
什么时候用 NumPy,什么时候用 PyTorch?
- 数据分析、传统数值实验:NumPy 很方便
- 需要训练神经网络、自动求导、GPU:PyTorch 更合适
八、一个小例子:计算学生总成绩和平均分
这个例子没有“深度学习味”,但非常适合练张量思维。
import torch
# 3 个学生,4 门课
scores = torch.tensor([
[85.0, 92.0, 78.0, 90.0],
[76.0, 88.0, 91.0, 84.0],
[93.0, 87.0, 89.0, 95.0]
])
student_totals = scores.sum(dim=1)
student_means = scores.mean(dim=1)
subject_means = scores.mean(dim=0)
print("每位学生总分:", student_totals)
print("每位学生平均分:", student_means)
print("每门课程平均分:", subject_means)
这里你已经用到了张量最重要的思维之一:
“沿着哪一维做计算?”
dim=1表示按行聚合dim=0表示按列聚合
九、初学者最容易犯的错
1. 忽略 shape
很多人只看数字,不看张量形状。
结果是代码“看起来像对的”,一运行就维度报错。
2. 把 * 当成矩阵乘法
在 PyTorch 里:
*是逐元素乘法@才是矩阵乘法
3. 不清楚 dtype
有些模型需要 float32,标签有时又要 long。
类型不对,损失函数可能直接报错。
十、小结
这一节最重要的不是记住多少 API,而是建立三个基本反应:
- 看到数据先看
shape - 看到运算先区分“逐元素”还是“矩阵乘法”
- 知道深度学习里的输入、参数、输出,本质上都是张量
接下来我们就要让这些张量“自己知道该往哪里改”了,这就是自动求导。