趋近智
如果你对 Python 中的科学计算有经验,你可能很熟悉 NumPy 及其 ndarray 对象。NumPy 提供了一种强大的 N 维数组结构,已成为 Python 中数值操作的标准。PyTorch 认识到这种普遍性,并提供了与 NumPy 数组出色的互操作性。事实上,PyTorch 张量与 NumPy 数组非常相似:它们都是数字多维网格的抽象。
这种密切关联使得两者之间的切换变得简单,让你在 PyTorch 生态系统中工作时,能够运用现有的 NumPy 代码或库。
从本质上看,PyTorch 张量和 NumPy 数组都表示多维的密集数值数据。你可能在 NumPy 数组上执行的许多操作,在 PyTorch 张量中都有直接对应,通常具有相似的命名约定:
然而,主要由于 PyTorch 对深度学习 (deep learning)的侧重,两者之间存在一些基本区别:
Autograd 系统(第 3 章会讲到)内置支持自动微分。这种机制会自动跟踪对需要梯度的张量执行的操作,并在反向传播 (backpropagation)期间计算这些梯度,这对训练神经网络 (neural network)来说很重要。NumPy 数组不具备此能力。PyTorch 使得在这两种数据结构之间转换变得简单。
你可以使用 torch.from_numpy() 函数直接从 NumPy 数组创建 PyTorch 张量。
import numpy as np
import torch
# 创建一个 NumPy 数组
numpy_array = np.array([[1, 2], [3, 4]], dtype=np.float32)
print(f"NumPy 数组:\n{numpy_array}")
print(f"NumPy 数组类型: {numpy_array.dtype}")
# 将 NumPy 数组转换为 PyTorch 张量
pytorch_tensor = torch.from_numpy(numpy_array)
print(f"\nPyTorch 张量:\n{pytorch_tensor}")
print(f"PyTorch 张量类型: {pytorch_tensor.dtype}")
内存共享的重要说明: 使用 torch.from_numpy() 时,生成的 PyTorch 张量和原始 NumPy 数组在 CPU 上共享相同的底层内存位置。这意味着修改一个对象会影响另一个。这种行为很高效,因为它避免了数据复制,但你需要注意这一点。
# 修改 NumPy 数组
numpy_array[0, 0] = 99
print(f"\n修改后的 NumPy 数组:\n{numpy_array}")
print(f"修改 NumPy 数组后的 PyTorch 张量:\n{pytorch_tensor}")
# 修改 PyTorch 张量
pytorch_tensor[1, 1] = -1
print(f"\n修改后的 PyTorch 张量:\n{pytorch_tensor}")
print(f"修改 PyTorch 张量后的 NumPy 数组:\n{numpy_array}")
如你所见,更改会反映在两个对象中,因为它们指向内存中的相同数据。
反之,你可以使用 .numpy() 方法将位于 CPU 上的 PyTorch 张量转换回 NumPy 数组。
# 在 CPU 上创建一个 PyTorch 张量
cpu_tensor = torch.tensor([[10.0, 20.0], [30.0, 40.0]])
print(f"原始 PyTorch 张量 (CPU):\n{cpu_tensor}")
# 将张量转换为 NumPy 数组
numpy_array_converted = cpu_tensor.numpy()
print(f"\n转换后的 NumPy 数组:\n{numpy_array_converted}")
print(f"NumPy 数组类型: {numpy_array_converted.dtype}")
同样,生成的 NumPy 数组和原始 CPU 张量共享相同的底层内存。对一个的修改会影响另一个。
# 修改张量
cpu_tensor[0, 1] = 25.0
print(f"\n修改后的 PyTorch 张量:\n{cpu_tensor}")
print(f"修改张量后的 NumPy 数组:\n{numpy_array_converted}")
# 修改 NumPy 数组
numpy_array_converted[1, 0] = 35.0
print(f"\n修改后的 NumPy 数组:\n{numpy_array_converted}")
print(f"修改 NumPy 数组后的张量:\n{cpu_tensor}")
GPU 张量: .numpy() 方法仅适用于存储在 CPU 上的张量。如果你的张量在 GPU 上,你必须先使用 .cpu() 方法将其移到 CPU,然后才能将其转换为 NumPy 数组。直接在 GPU 张量上调用 .numpy() 会导致错误。
# 假设有 GPU 可用的示例
if torch.cuda.is_available():
gpu_tensor = torch.tensor([[1.0, 2.0], [3.0, 4.0]], device='cuda')
print(f"\nGPU 上的张量:\n{gpu_tensor}")
# 这将导致错误: numpy_from_gpu = gpu_tensor.numpy()
# 正确方法: 先移到 CPU
cpu_tensor_from_gpu = gpu_tensor.cpu()
numpy_from_gpu = cpu_tensor_from_gpu.numpy()
print(f"\n转换后的 NumPy 数组 (来自 GPU 张量):\n{numpy_from_gpu}")
# 注意: numpy_from_gpu 与 cpu_tensor_from_gpu 共享内存,
# 但不与原始的 gpu_tensor 共享。
else:
print("\nCUDA 不可用,跳过 GPU 到 NumPy 的示例。")
轻松地在 NumPy 数组和 PyTorch 张量之间转换的能力非常实用。你可能使用熟悉的 NumPy 函数或其他操作 NumPy 数组的库来执行初始数据加载和预处理。然后,当需要构建或训练深度学习 (deep learning)模型时,你可以将数据转换为 PyTorch 张量,以借助于 GPU 加速和自动微分。同样,模型输出(即张量)可以转换回 NumPy 数组,以便使用 Matplotlib 或 Seaborn 等库进行分析或可视化。
理解这种关联和内存共享的含义,让你能够编写高效的代码,有效连接通用科学 Python 生态系统与 PyTorch 提供的专门深度学习能力。
这部分内容有帮助吗?
© 2026 ApX Machine LearningAI伦理与透明度•