趋近智
requires_grad)backward()).grad)torch.nn 搭建模型torch.nn.Module 基类torch.nn 损失)torch.optim)torch.utils.data.Datasettorchvision.transforms)torch.utils.data.DataLoader对 PyTorch 张量执行基本操作是一项主要技能。张量支持多种数学和逻辑运算。这些运算许多都与 NumPy 中的对应功能类似,都是按元素进行的。这些运算是神经网络计算的根本。
最常见的运算是将标准算术函数独立应用于参与运算的张量的每个元素。这些运算通常要求张量具有兼容的形状(关于形状兼容性,我们将在下一章讨论广播时详细说明)。
您可以使用标准 Python 算术运算符或等效的 torch 函数:
+ 或 torch.add()- 或 torch.sub()* 或 torch.mul()/ 或 torch.div()** 或 torch.pow()让我们看看这些操作如何运行:
import torch
# 创建两个张量
a = torch.tensor([[1., 2.], [3., 4.]])
b = torch.tensor([[5., 6.], [7., 8.]])
# 加法
sum_tensor = a + b
print("加法 (a + b):\n", sum_tensor)
print("加法 (torch.add(a, b)):\n", torch.add(a, b))
# 减法
diff_tensor = a - b
print("\n减法 (a - b):\n", diff_tensor)
# 按元素乘法
mul_tensor = a * b
print("\n按元素乘法 (a * b):\n", mul_tensor)
print("按元素乘法 (torch.mul(a, b)):\n", torch.mul(a, b))
# 除法
div_tensor = a / b
print("\n除法 (a / b):\n", div_tensor)
# 幂运算
pow_tensor = a ** 2
print("\n幂运算 (a ** 2):\n", pow_tensor)
print("幂运算 (torch.pow(a, 2)):\n", torch.pow(a, 2))
这些操作会创建包含结果的新张量。原始张量 a 和 b 保持不变。
PyTorch 也提供许多操作的就地版本。这些操作直接修改张量,而不创建新对象,这可以节省内存。就地函数通常可以通过名称中末尾的下划线 _ 来识别(例如,add_、mul_)。
import torch
a = torch.tensor([[1., 2.], [3., 4.]])
b = torch.tensor([[5., 6.], [7., 8.]])
print("原始张量 'a':\n", a)
# 执行就地加法
a.add_(b) # a 被直接修改
print("\na.add_(b) 后张量 'a':\n", a)
# 如果取消注释,这将引发错误,
# 因为 a + b 的结果是一个新张量,
# 不适合直接重新赋值给 'a' 的内存
# a = a + b # 标准加法会创建一个新张量
# 另一个就地操作
a.mul_(2) # 将 'a' 就地乘以 2
print("\na.mul_(2) 后张量 'a':\n", a)
虽然就地操作可以提高内存效率,但请谨慎使用。如果在计算图中的其他地方需要原始值,就地修改张量可能会导致自动求导(Autograd)(第 3 章会介绍)中的梯度计算问题。通常更稳妥的做法,尤其是在学习时,是使用返回新张量的标准操作。
您可以对张量和单个数字(标量)执行算术运算。PyTorch 会自动扩展标量以匹配张量的形状,从而进行按元素运算。
import torch
t = torch.tensor([[1, 2, 3], [4, 5, 6]])
scalar = 10
# 加标量
print("t + 标量:\n", t + scalar)
# 乘以标量
print("\nt * 标量:\n", t * scalar)
# 减去标量
print("\nt - 标量:\n", t - scalar)
PyTorch 提供丰富的数学函数库,这些函数按元素对张量进行操作,类似于 NumPy 的通用函数(ufuncs)。
import torch
t = torch.tensor([[1., 4.], [9., 16.]])
# 平方根
print("平方根 (torch.sqrt(t)):\n", torch.sqrt(t))
# 指数
print("\n指数 (torch.exp(t)):\n", torch.exp(t)) # e^x
# 自然对数
# 注意:确保对数的值为正
t_pos = torch.abs(t) + 1e-6 # 添加小的 epsilon 以提高稳定性(如果存在零)
print("\n自然对数 (torch.log(t_pos)):\n", torch.log(t_pos))
# 绝对值
t_neg = torch.tensor([[-1., 2.], [-3., 4.]])
print("\n绝对值 (torch.abs(t_neg)):\n", torch.abs(t_neg))
torch 模块中还有许多其他函数,例如 torch.sin()、torch.cos()、torch.tanh()、torch.sigmoid() 等。
归约操作会减少张量中的元素数量,通常用于汇总信息。常见例子包括求和、求平均值、求最小值和最大值。
import torch
t = torch.tensor([[1., 2., 3.], [4., 5., 6.]])
print("原始张量:\n", t)
# 所有元素的和
total_sum = torch.sum(t)
print("\n所有元素的和 (torch.sum(t)):", total_sum)
# 所有元素的平均值
# 注意:平均值计算需要浮点张量
mean_val = torch.mean(t.float())
print("所有元素的平均值 (torch.mean(t.float())):", mean_val)
# 最大值
max_val = torch.max(t)
print("张量中的最大值 (torch.max(t)):", max_val)
# 最小值
min_val = torch.min(t)
print("张量中的最小值 (torch.min(t)):", min_val)
您还可以使用 dim 参数沿着特定维度执行归约操作。这会折叠指定的维度,返回一个维度减少的张量。
import torch
t = torch.tensor([[1., 2., 3.], [4., 5., 6.]])
print("原始张量:\n", t)
# 沿着维度 0 求和(对行求和)
sum_dim0 = torch.sum(t, dim=0)
print("\n沿着 dim=0 求和(列):\n", sum_dim0)
# 沿着维度 1 求和(对列求和)
sum_dim1 = torch.sum(t, dim=1)
print("\n沿着 dim=1 求和(行):\n", sum_dim1)
# 沿着维度 1 求平均值
mean_dim1 = torch.mean(t.float(), dim=1)
print("\n沿着 dim=1 求平均值(行):\n", mean_dim1)
对张量
[[1, 2, 3], [4, 5, 6]]沿着dim=1求和,结果为[1+2+3, 4+5+6] = [6, 15]。
了解 dim 的工作原理对许多深度学习操作很重要,例如计算每个批次项的损失或应用批归一化。
您可以使用标准比较运算符(>、<、>=、<=、==、!=)按元素比较张量。结果是一个布尔值张量(torch.bool)。
import torch
a = torch.tensor([[1, 2], [3, 4]])
b = torch.tensor([[1, 5], [0, 4]])
print("张量 'a':\n", a)
print("张量 'b':\n", b)
# 相等检查
print("\na == b:\n", a == b)
# 大于检查
print("\na > b:\n", a > b)
# 小于或等于检查
print("\na <= b:\n", a <= b)
布尔张量对掩码操作很有用,您将在更高级的张量操作中遇到它们。
逻辑操作(torch.logical_and()、torch.logical_or()、torch.logical_not())按元素对布尔张量或可在布尔上下文中求值的张量进行操作(其中 0 为假,非零为真)。
import torch
bool_a = torch.tensor([[True, False], [True, True]])
bool_b = torch.tensor([[False, True], [True, False]])
print("布尔张量 'bool_a':\n", bool_a)
print("布尔张量 'bool_b':\n", bool_b)
# 逻辑与
print("\ntorch.logical_and(bool_a, bool_b):\n", torch.logical_and(bool_a, bool_b))
# 逻辑或
print("\ntorch.logical_or(bool_a, bool_b):\n", torch.logical_or(bool_a, bool_b))
# 逻辑非
print("\ntorch.logical_not(bool_a):\n", torch.logical_not(bool_a))
这些基本操作为更复杂的计算提供了基本组成部分。掌握它们是在 PyTorch 中实现数值算法和神经网络层的第一步。在下一章中,我们将介绍更高级的张量操作方法,包括索引、切片、重塑和广播。
这部分内容有帮助吗?
torch, PyTorch Core Team, 2025 - PyTorch张量操作的官方指南,涵盖逐元素、归约和原地操作。© 2026 ApX Machine Learning用心打造