一、什么是张量?

在PyTorch中,张量(Tensor) 是存储和操作数据的基本单位,类似于NumPy中的数组,但支持GPU加速,并且是神经网络计算的核心数据结构。你可以把张量想象成一个“容器”,里面装着数字(如整数、浮点数),并且可以对这个容器进行各种数学操作。

二、创建张量

要开始使用张量,首先需要学会创建它。PyTorch提供了多种方式创建张量,以下是最常用的几种:

  1. 从Python列表/NumPy数组创建
    使用 torch.tensor()torch.as_tensor() 直接从数据创建:
   import torch
   import numpy as np

   # 从列表创建
   data_list = [1, 2, 3, 4]
   tensor_list = torch.tensor(data_list)  # 结果:tensor([1, 2, 3, 4])

   # 从NumPy数组创建
   np_array = np.array([1, 2, 3])
   tensor_np = torch.as_tensor(np_array)  # 结果:tensor([1, 2, 3])
  1. 使用构造函数创建
    - torch.zeros(*size):创建全0张量,size 是形状元组(如 (2, 3) 表示2行3列)。
    - torch.ones(*size):创建全1张量。
    - torch.rand(*size):创建随机数张量(元素在 [0, 1) 之间)。
   zeros_tensor = torch.zeros(2, 3)  # 2行3列全0
   ones_tensor = torch.ones(1, 4)    # 1行4列全1
   rand_tensor = torch.rand(3, 3)    # 3x3随机数矩阵

三、张量的基本属性

创建张量后,需要了解它的基本属性以便后续操作:
- 形状(shape):用 .shape.size() 查看,返回一个元组。
- 数据类型(dtype):用 .dtype 查看,如 torch.float32(默认)、torch.int64 等。
- 设备(device):用 .device 查看,默认是CPU,可通过 .to('cuda') 转移到GPU。

tensor = torch.rand(2, 3)
print(tensor.shape)   # torch.Size([2, 3])
print(tensor.dtype)   # torch.float32
print(tensor.device)  # cpu

# 转换数据类型和设备
tensor = tensor.to(torch.float64).to('cuda')  # 先转double类型,再移到GPU

四、张量操作

张量的操作是PyTorch的核心,掌握这些操作才能灵活处理数据。

1. 算术操作

张量支持常见的算术运算,如加减乘除、取反等:
- 加法+torch.add()
- 减法-torch.sub()
- 乘法*torch.mul()(注意:矩阵乘法用 @torch.matmul()
- 除法/torch.div()

a = torch.tensor([1, 2, 3])
b = torch.tensor([4, 5, 6])

# 加法
print(a + b)        # tensor([5, 7, 9])
print(torch.add(a, b))  # 同上

# 矩阵乘法(示例:2x2 * 2x2)
a = torch.tensor([[1, 2], [3, 4]])
b = torch.tensor([[5, 6], [7, 8]])
print(a @ b)        # tensor([[19, 22], [43, 50]])
2. 索引与切片

张量的索引和切片与Python列表类似,支持多维索引:

tensor = torch.tensor([[1, 2, 3], [4, 5, 6]])

# 取第一行(维度0)
print(tensor[0])                # tensor([1, 2, 3])
# 取第二列(维度1)
print(tensor[:, 1])             # tensor([2, 5])
# 取第1-2行、第0-1列
print(tensor[0:2, 0:2])         # tensor([[1, 2], [4, 5]])
3. 变形操作

用于调整张量的维度(保持元素总数不变):
- reshape():改变形状,返回新张量(若形状不合法则报错)。
- squeeze():移除维度为1的轴(如 (1, 3, 1)(3,))。
- unsqueeze():增加维度为1的轴(如 (3,)(1, 3))。

tensor = torch.rand(1, 2, 1, 4)  # 形状:(1,2,1,4)
print(tensor.shape)  # torch.Size([1, 2, 1, 4])

# 移除维度1的轴
squeezed = tensor.squeeze()  # 形状:(2, 4)
print(squeezed.shape)  # torch.Size([2, 4])

# 增加维度为1的轴(在维度1处插入)
unsqueezed = tensor.unsqueeze(1)  # 形状:(1,1,2,1,4)
print(unsqueezed.shape)  # torch.Size([1, 1, 2, 1, 4])
4. 拼接与拆分
  • torch.cat():按指定维度拼接多个张量(需保持其他维度一致)。
  • torch.stack():新增一个维度拼接(需所有维度一致)。
  • torch.split() / torch.chunk():拆分张量为多个部分。
a = torch.tensor([[1, 2], [3, 4]])
b = torch.tensor([[5, 6], [7, 8]])

# 按维度0拼接(上下合并)
cat_dim0 = torch.cat([a, b], dim=0)  # 形状:(4, 2)
print(cat_dim0)
# 按维度1拼接(左右合并)
cat_dim1 = torch.cat([a, b], dim=1)  # 形状:(2, 4)
print(cat_dim1)

# 拆分:按每个部分大小拆分为2份
split_tensor = torch.cat([a, b], dim=0)
split_parts = torch.split(split_tensor, split_size_or_sections=2, dim=0)
print(split_parts)  # (tensor([[1,2],[3,4]]), tensor([[5,6],[7,8]]))

五、自动求导(Autograd)

自动求导是PyTorch实现神经网络反向传播的核心,用于自动计算梯度。

1. 核心概念
  • requires_grad:张量属性,设为 True 表示需要追踪其梯度。
  • 计算图:记录张量操作的计算流程,用于反向传播时自动计算梯度。
  • backward():对计算图中的叶子节点调用,触发梯度计算。
  • grad:张量的梯度属性,仅对 requires_grad=True 的张量有效。
2. 自动求导示例

以简单函数 y = x² 为例,演示如何计算梯度:

# 创建需要求导的张量,requires_grad=True
x = torch.tensor(3.0, requires_grad=True)  # x=3.0,需要追踪梯度

# 构建计算图:y = x²
y = x ** 2  

# 反向传播:计算梯度(y对x的导数)
y.backward()  

# 查看梯度:x.grad = dy/dx = 2x = 6
print(x.grad)  # tensor(6.)
3. 注意事项
  • 非叶子节点梯度:中间变量(非原始张量)的梯度在 backward() 后会被释放,如需保留需用 retain_graph=True
  • 累加梯度:多次调用 backward() 时,梯度会累加,需手动清空(x.grad.zero_())。
  • detach():分离张量,阻止其继续参与梯度计算(返回无梯度的新张量)。
x = torch.tensor(2.0, requires_grad=True)
y = x ** 2
z = y ** 2  # 计算图:z = (x²)² = x⁴

# 先对y求导(此时x的梯度会被计算)
y.backward()
print(x.grad)  # tensor(4.) (因为dy/dx=2x=4,此时z未参与计算)

# 若要计算z对x的梯度,需重新反向传播(需设置retain_graph=True保留计算图)
z.backward(retain_graph=True)
print(x.grad)  # tensor(16.) (4+12=16,因为grad是累加的)

六、总结

  • 张量是PyTorch数据的基本单位,支持多种创建方式和操作(算术、索引、变形等)。
  • 自动求导通过 requires_gradbackward() 实现梯度计算,是神经网络训练的核心。
  • 实践中需注意张量形状匹配、梯度累加、设备转移等细节,多动手尝试不同操作才能熟练掌握。

通过以上内容,你已掌握PyTorch基础的张量操作和自动求导,为后续学习神经网络打下基础!

小夜