只用 PyTorch 就能吗?
如果你是深度学习开发者,可能曾经对这两者的关系感到困惑。
在细读微调代码时,总会看到这两个名字。
import numpy as np
import torch
“但张量运算已经全在 PyTorch 里了…为什么还需要 NumPy?” “它们的概念好像重叠,是否还需要单独学习 NumPy?”
我也对这个问题很好奇,基于一条清晰的回答整理了以下内容。
1. NumPy 与 PyTorch,究竟有什么区别?
粗略来说,PyTorch 可以被视为:
“GPU 上的 NumPy + 自动微分(autograd)”
拆开来看:
- NumPy
- 在 CPU 上运行的数组/矩阵库
- 数值计算、线性代数、统计运算的事实“Python 标准”
-
以
ndarray为核心数据结构 -
PyTorch
- 与 NumPy 的 API 非常相似
- 但不仅能在 CPU 上运行,还能在 GPU(CUDA)上运行
- 支持张量运算的自动微分 → 使深度学习训练成为可能
PyTorch 的开发者几乎模仿了 NumPy 的语法。
np.array([...])→torch.tensor([...])x_np.shape→x_torch.shapenp.reshape(x, ...)→x_torch.view(...)或x_torch.reshape(...)
因此,当你学习 PyTorch 的张量运算时,自然也会同时掌握 NumPy 的思维方式和语法。
2. “先学 NumPy 吗?”的现实答案
许多教程先从 NumPy 开始,容易让人产生误解。实务角度来看,答案是:
不必先学 NumPy。PyTorch 可以直接从张量运算开始学习。
原因很简单。
- 张量的形状/广播/索引等概念 NumPy 与 PyTorch 几乎完全相同。
- 在深度学习中,我们真正需要的是 “深度学习模型的张量运算 + 自动微分”, 这完全在 PyTorch 里完成。
所以,如果你的目标是深度学习:
- 先掌握 PyTorch 的张量操作
- 当代码中出现
np.xxx时 只需理解为“在 CPU 上的张量操作”即可。
3. 但为什么 NumPy 仍然频繁出现?——“生态系统的通用语言”
这就产生了疑问:
“PyTorch 更强大,为什么不全部用 PyTorch 张量?”
原因是:
Python 数据/科学生态的大多数库都是以 NumPy 为基准设计的。
3-1. 数据预处理阶段:NumPy 的世界
常用的库:
OpenCV、Pillow→ 读取图像时通常返回 NumPy 数组pandas→DataFrame.values/to_numpy()等使用 NumPy 数组- 各种统计/数值包 → 输入/输出大多以 NumPy 为标准
也就是说,“送进模型之前的数据操作”大多使用 NumPy。
3-2. 模型训练/推理阶段:PyTorch 的世界
当你准备把数据送进深度学习模型时:
import numpy as np
import torch
x_np = ... # 预处理得到的 NumPy 数组
x_tensor = torch.from_numpy(x_np) # 转为张量
x_tensor = x_tensor.to("cuda") # 移到 GPU
out = model(x_tensor)
从这里开始,就是 PyTorch 的张量世界。
3-3. 可视化/保存/后处理阶段:又回到 NumPy
模型预测结果:
- 用
matplotlib绘图 - 再放回
pandas并导出 CSV - 进行简单统计
这些库大多以 NumPy 数组为基础。
因此,你需要把张量再转换回 NumPy:
out_cpu = out.detach().cpu().numpy()
常见错误是:
TypeError: can't convert cuda:0 device type tensor to numpy
因为 GPU 张量不能直接 .numpy(),必须先 .cpu()。
4. 系统层面的重要点:Zero‑Copy 共享
从更低层面来看,有一个有趣的点。
x_np = np.random.randn(3, 3)
x_tensor = torch.from_numpy(x_np) # 这里!
实际上并没有复制数据。
torch.from_numpy(...)共享 NumPy 使用的内存。- 因此,即使是大数组,也几乎不占用额外内存。
相反:
x_np2 = x_tensor.numpy()
同样(CPU 张量)会得到共享同一块内存的 NumPy 数组。
这导致了以下现象:
x_np = np.zeros((2, 2))
x_tensor = torch.from_numpy(x_np)
x_tensor[0, 0] = 1
print(x_np)
# [[1. 0.]
# [0. 0.]] ← NumPy 数组也随之改变
两者像“窗户”一样共享同一数据。
总结: * PyTorch 与 NumPy 可以在 CPU 上共享内存 * 这使得“预处理(NumPy)↔训练(PyTorch)↔后处理(NumPy)”可以在几乎不产生复制成本的情况下完成。
5. 一次性看到完整流程的简易示例
假设你要做一个极其简单的图像分类:
import cv2
import numpy as np
import torch
# 1. 图像读取 & NumPy 预处理(NumPy 区域)
img = cv2.imread("cat.png") # shape: (H, W, C), BGR, NumPy array
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = cv2.resize(img, (224, 224))
img = img.astype(np.float32) / 255.0
img = np.transpose(img, (2, 0, 1)) # (C, H, W)
# 2. NumPy → PyTorch 张量转换 & GPU 移动(PyTorch 区域)
x = torch.from_numpy(img) # shape: (3, 224, 224)
x = x.unsqueeze(0) # 添加 batch 维度: (1, 3, 224, 224)
x = x.to("cuda")
# 3. 模型推理
with torch.no_grad():
logits = model(x)
probs = torch.softmax(logits, dim=1)
# 4. 再转回 NumPy 进行后处理/可视化(NumPy 区域)
probs_np = probs.cpu().numpy()
pred_class = np.argmax(probs_np, axis=1)[0]
从代码流程可以看到:
- 输入/输出边界是 NumPy
- 中间训练/推理是 PyTorch
6. 最终总结:这样理解更轻松
总结如下:
- 学习 PyTorch 就是学习“未来版 NumPy”。 掌握张量操作和广播感知,实际上就是掌握 NumPy 的思维。
- 不必深入学习 NumPy。
如果目标是深度学习,先学 PyTorch,遇到
np.xxx时只需把它视为“CPU 版张量操作”。 - 但在实际工作中:
* 数据预处理 / 后处理 / 可视化 / 统计计算
* 需要使用 NumPy
* 关键是熟悉 PyTorch ↔ NumPy 的转换代码(
.numpy()、torch.from_numpy、.cpu())。 - 从系统角度看: * 两者可以共享内存(Zero‑Copy),在大数据场景下高效切换。
当你看到深度学习代码时,记住:
- 张量在 GPU 上并且需要微分 → PyTorch 区域
- 与周围库交互、数据处理、可视化 → NumPy 区域
这两者自然流畅地往返,就是现代 Python 深度学习开发者的基本技能。

目前没有评论。