PyTorch 是当前主流的深度学习框架。掌握其核心数据结构——张量的基本操作,是进行模型构建、数据处理和算法实现的第一步。本文将详细介绍 PyTorch 张量的创建方法、常见数学运算、形状变换以及与 NumPy 数组的互操作性。
环境准备
首先,需要安装 PyTorch。如果你的环境支持 CUDA,可以使用以下命令安装 GPU 版本以加速计算:
pip install torch torchaudio torchvision --index-url https://download.pytorch.org/whl/cu130
安装过程如下图所示,会下载并构建相关的 wheel 包:

安装完成后,可以通过简单的代码验证安装是否成功,以及 CUDA 是否可用:
import torch
print(torch.cuda.is_available())
若输出 True,则说明 PyTorch 已正确安装且 GPU 加速可用。

张量基础操作
张量是 PyTorch 的基础,类似于 NumPy 的多维数组,但支持在 GPU 上进行加速计算。
张量的多种创建方式
PyTorch 提供了丰富的函数来创建不同初始状态的张量。
import torch
# 1. 创建一个 5行2列 未初始化的张量
x = torch.empty(5,2)
print("empty tensor:\n", x)

# 2. 创建一个 5行3列 随机初始化的张量
# 均匀分布进行随机初始化,区间[0,1),不能指定dtype=torch.long
x = torch.rand(5,3)
print("random tensor:\n", x)

# 3. 创建一个 5行3列 根据标准正太分布随机初始化的张量
x = torch.randn(5,3)
print("random tensor:\n", x)

# 4. 创建一个全为 0 的张量
x = torch.zeros(5,3)
print("zeros tensor:\n", x)

# 5. 创建一个全为 0, 数据类型为 long 的张量
x = torch.zeros(5,3, dtype=torch.long)
print("zeros tensor:\n", x)

# 6. 创建一个全为1的张量
x = torch.ones(5,3)
print("ones tensor:\n", x)

除了直接指定形状,我们还可以基于现有张量的形状来创建新张量。
# 7. 使用 rand_like 创建一个形状和另一个张量相同的随机张量
x = torch.ones(2,2)
y = torch.randn_like(x)
print("rand like tensor:\n", y)

# 8. 使用 ones_like
x = torch.rand(3,3)
y = torch.ones_like(x, dtype=torch.long)
print("ones like tensor:\n", y)

# 9. 使用zeros_like
x = torch.rand(4,4)
y = torch.zeros_like(x)
print("zeros like tensor:\n", y)

# 10. 使用 full_like。
x = torch.rand(2,2)
y = torch.full_like(x, 3) # 创建一个值全为3的 2行2列 的张量
print("full like tensor:\n", y)

最直接的方式是从 Python 列表或嵌套列表创建张量,PyTorch 会自动推断数据类型。
# 11. 直接从数据创建张量,tensor的类型会保持一致
x = torch.tensor([
[1.0, 2],
[2.5,3]
])
print("data tensor:\n", x)
print(x.type(), x.dtype)

张量运算操作
张量支持丰富的数学运算,包括逐元素运算和矩阵运算。
# 加法,相同位置的数值相加 1+5, 2+6, 3+7, 4+8
a = torch.tensor([
[1,2],
[3,4]
])
b = torch.tensor([
[5,6],
[7,8]
])
print("张量加法:\n", a+b)

# 减法, 1-5, 2-6, 3-7, 4-8
print("张量减法:\n", a-b)

# 乘法,1*5, 2*6, 3*7, 4*8
print("张量乘法:\n", a*b)

# 矩阵乘法 1*5+2*7,1*6+2*8,3*5+4*7, 3*6+4*8
print("张量矩阵乘法:\n", a @ b)
print("张量矩阵乘法:\n", torch.matmul(a, b))

张量拼接是组合数据的常用操作,dim 参数决定了拼接的维度。
# 拼接, dim=0 按第1个维度行拼接 dim=1按第2个维度列拼接。dim也可以是负数,-1表示最后一个维度,在二维张量中代表列
print("concat tensors:\n", torch.cat((a,b),dim=0)) # 行拼接,所有行按顺序拼接到一起
print("concat tensors:\n", torch.cat((a,b),dim=1)) # 列拼接,相同行号的列拼接到一行中
print("concat tensors:\n", torch.cat((a,b),dim=-1)) # 列拼接
print("concat tensors:\n", torch.cat((a,b),dim=-2)) # 行拼接

张量形状变换
在数据处理和模型层间传递时,经常需要改变张量的形状。
# reshape
x = torch.arange(1,13) # 1~12
print("Original tensor:\n", x)
print("Reshape to 6x2:\n", x.reshape(6,2)) # 6行2列

view 是另一个常用的变形方法,但它要求操作的张量在内存中是连续的。
# view 与 reshape 类似,但是要求张量是连续的
print("view to 4x3:\n", x.view(4,3))

transpose 用于交换张量的两个维度。
# transpose 交换两个维度
x = torch.randn(2,3,4) # 按照正太分布随机生成 三维 张量
print("Original tensor shape:\n", x.shape)
print("Transpose from (2,3,4) to (2,4,3):\n", x.transpose(1,2).shape)

squeeze 和 unsqueeze 用于删除或增加大小为1的维度。
# squeeze / unsqueeze 删除或增加维度
x = torch.randn(1,3,1,2)
print("Squeeze Tensor:\n", x.squeeze().shape) # 删除所有数值为1的维度
print("Unsqueeze at dim=0:\n", x.unsqueeze(0).shape) # 在第1个位置增加一个维度

理解张量的连续性(Contiguity)很重要。连续张量的元素在内存中按索引顺序连续存储,某些操作(如 view)需要张量是连续的。
# is_contiguous 判断是否连续张量
a = torch.tensor([
[1,2,3],
[4,5,6]
])
print("a是不是连续张量:", a.is_contiguous())
b = a.transpose(0,1) # 转置操作
print("转置后的tensor:\n", b)
print("b是不是连续张量:", b.is_contiguous())

对于非连续张量,可以调用 contiguous() 方法将其转换为连续张量,然后进行 view 等操作。
# contiguous 将张量转为连续张量
print("转为连续张量:\n", b.contiguous())
print("转为连续张量后使用view变形:\n", b.contiguous().view(-1))

与 Numpy 互操作
PyTorch 与 NumPy 可以方便地相互转换,便于利用两个生态的优势。
import numpy as np
# 从numpy array 创建张量
np_array = np.array([[1,2,3],[4,5,6],[7,8,9]])
print(np_array, type(np_array))
tensor = torch.from_numpy(np_array)
print(tensor, type(tensor))

# tensor 转 numpy
tensor = torch.rand(2,2)
np_array = tensor.numpy()
print("tensor转numpy:\n",np_array, type(np_array))

一个重要特性是:当张量位于 CPU 上时,通过 from_numpy() 创建的张量和 numpy() 方法返回的数组会共享底层内存。这意味着修改其中一个,另一个也会随之改变。
# 如果张量在CPU上, from_numpy() 和 numpy() 会共享内存
print(tensor.device)
tensor.add_(2) # 原地操作,给张量每个元素加2
print("修改后的张量:\n", tensor)
print("对应的NumPy数组:\n", np_array)
可以看到,当张量在 CPU 上时,对张量进行原地修改,对应的 NumPy 数组也同步发生了变化。

以上就是 PyTorch 张量基础操作的全面介绍。从创建、运算到形状变换,这些操作构成了使用 PyTorch 进行深度学习研究和开发的基石。熟练掌握它们,能让你在后续的模型构建和数据处理中更加得心应手。如果想探讨更多深度学习或Python相关话题,欢迎来到云栈社区交流分享。