1. 张量是一个多维数组,它是标量、向量、矩阵的高维拓展。
2. 在张量的定义中,方括号用于表示张量的形状。例如,torch.tensor([[1, 2, 3], [4, 5, 6]])
定义了一个2x3的二维张量,其中方括号 [[…], […]] 表示该张量有2行3列。 例如,torch.tensor([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
定义了一个2x2x3的三维张量,其中方括号 [[[…, …], […, …]], [[…, …], […, …]]] 表示该张量有2个2x3的矩阵。
3. PyTorch中的张量(Tensor)和数组(Array)之间存在一些关键区别。尽管它们在许多方面都很相似,但在一些重要的方面也有所不同。以下是它们之间的主要区别:
4. 张量中的8个属性:
data
:存储的实际数据,是一个多维数组。dtype
:张量中元素的数据类型,如torch.float32、torch.int64等。shape
:张量的形状,表示每个维度的大小。它是一个元组,例如(3, 256, 832)。device
:张量所在的设备,可以是CPU或GPU。requires_grad
:一个布尔值,表示是否需要计算梯度。如果设置为True,则PyTorch将记录该张量的操作历史,以便在反向传播时自动计算梯度。grad
:张量的梯度,形状与data一致。它存储了关于张量的梯度信息,用于反向传播和优化。grad_fn
:创建该张量时所用的函数(Function)。它记录了创建张量的操作历史,是自动求导的关键。is_leaf
:一个布尔值,表示该张量是否是叶子节点。叶子节点是指在计算图中没有依赖其他张量的节点。对于叶子节点,反向传播结束时其梯度仍会保存,非叶子节点的梯度会被释放,以节省内存。1. 直接创建:
import torch
# 定义一个标量张量
x = torch.tensor(5)
print(x)
# 定义一个一维张量(向量)
y = torch.tensor([1, 2, 3, 4, 5])
print(y)
# 定义一个二维张量(矩阵)
z = torch.tensor([[1, 2, 3], [4, 5, 6]])
print(z)
# 定义一个高维张量
w = torch.tensor([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
print(w)
2. 依据数值创建:
arr = np.array([1, 2, 3, 4, 5])
print(arr)
x = torch.tensor(arr)
print(x)
3. torch.arange
用于创建一个包含等间隔数值的一维张量(tensor)。注意:数值区间是[start, end)。
import torch
# 创建一个从 0 到 9 的一维张量,步长为 1
a = torch.arange(0, 10)
print(a)
# 输出:tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
# 创建一个从 1 到 10 的一维张量,步长为 2
b = torch.arange(1, 10, step=2)
print(b)
# 输出:tensor([1, 3, 5, 7, 9])
4. torch.linspace
用于创建一个包含等间隔数值的一维张量(tensor)。与torch.arange
不同的是,torch.linspace` 指定了序列中数值的个数,而不是步长。
import torch
# 创建一个从 0 到 1 的一维张量,包含 10 个数值
a = torch.linspace(0, 1, steps=10)
print(a)
# 输出:tensor([0.0000, 0.1111, 0.2222, 0.3333, 0.4444, 0.5556, 0.6667, 0.7778, 0.8889, 1.0000])
5. torch.normal
用于生成服从正态分布(高斯分布)的张量。其中每个元素都是从给定均值和标准差的正态分布中随机采样得到的。它可以用于生成随机数、模拟数据等。它的用法是:torch.normal(mean, std, size)
。
import torch
# 生成一个形状为 (3, 3) 的张量,服从均值为 0、标准差为 1 的正态分布
a = torch.normal(0, 1, size=(3, 3))
print(a)
#输出如下:
tensor([[ 0.6692, -0.6885, -0.3282],
[-1.0229, 0.2951, 1.3966],
[ 0.2123, -0.6048, 0.9535]])
6. torch.randn
用于生成服从标准正态分布(均值为 0,标准差为 1)的张量。torch.randn
函数返回一个指定形状的张量,其中每个元素都是从标准正态分布中随机采样得到的。它可以用于生成随机数、模拟数据等。与torch.normal
不同的是,torch.randn
默认生成的是标准正态分布的张量,而torch.normal
可以指定均值和标准差。
import torch
# 生成一个形状为 (3, 3) 的张量,服从标准正态分布
a = torch.randn(3, 3)
print(a)
1. torch.cat()
用于将多个张量按照指定的维度连接成一个新的张量。它的用法是:torch.cat(tensors, dim=0)
。
import torch
# 创建两个形状为 (3, 4) 的张量
a = torch.tensor([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
b = torch.tensor([[13, 14, 15, 16], [17, 18, 19, 20], [21, 22, 23, 24]])
# 在第 0 维上连接两个张量
c = torch.cat((a, b), dim=0)
print(c)
#输出为:
tensor([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12],
[13, 14, 15, 16],
[17, 18, 19, 20],
[21, 22, 23, 24]])
2. torch.stack()
用于将多个张量沿着新的维度进行堆叠。它的用法是:torch.stack(seq, dim=0)
。注意:torch.stack()
函数要求所有被堆叠的张量的形状必须相同。
import torch
# 创建两个形状为 (3,) 的张量
a = torch.tensor([1, 2, 3])
b = torch.tensor([4, 5, 6])
# 在第 0 维上堆叠两个张量
c = torch.stack((a, b), dim=0)
print(c)
#输出为:
tensor([[1, 2, 3],
[4, 5, 6]])
3. torch.chunk()
用于将张量拆分成多个块。它的用法是:torch.chunk(input, chunks, dim=0)
。
函数会将输入张量在指定的维度上均匀拆分成 chunks 个块,并返回一个包含这些块的元组。每个块的形状是将输入张量的形状在第 dim 维上分割成 chunks 个相等的部分而得到的。
import torch
# 创建一个形状为 (6,) 的张量
x = torch.tensor([1, 2, 3, 4, 5, 6])
# 在第 0 维上拆分成 3 个块
chunks = torch.chunk(x, 3)
# 打印拆分后的块
for i, chunk in enumerate(chunks):
print(f"Chunk {i}: {chunk}")
#输出为:
Chunk 0: tensor([1, 2])
Chunk 1: tensor([3, 4])
Chunk 2: tensor([5, 6])
4. torch.split()
用于将张量拆分成多个块,与torch.chunk()
类似。它的用法是:torch.split(tensor, split_size, dim=0)
。
import torch
# 创建一个形状为 (8, 3) 的张量
x = torch.randn(8, 3)
# 在第 0 维上拆分成大小为 2 的块
splits = torch.split(x, 2, dim=0)
# 打印拆分后的块
for i, split in enumerate(splits):
print(f"Split {i}: {split.shape}")
#输出为:
Split 0: torch.Size([2, 3])
Split 1: torch.Size([2, 3])
Split 2: torch.Size([2, 3])
Split 3: torch.Size([2, 3])
在这个示例中,我们创建了一个形状为 (8, 3) 的张量 x。然后,我们使用 torch.split(x, 2, dim=0) 在第 0 维上将其拆分成大小为 2 的块。最后,我们打印了每个块的形状。可以看到,输入张量被均匀拆分成了 4 个大小为 (2, 3) 的块。
1. torch.index_select()
用于沿着指定维度对张量进行索引。它返回一个新的张量,该张量是按照给定的索引从源张量中选择的元素构成的。它的用法是:torch.index_select(input, dim, index)
。
import torch
# 创建一个 3x3 的张量
x = torch.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 选择第 0 行(索引为 0)和第 2 行(索引为 2)
indices = torch.tensor([0, 2])
# 沿着维度 0(即行)进行索引选择
selected = torch.index_select(x, 0, indices)
print(selected)
#输出为:
tensor([[1, 2, 3],
[7, 8, 9]])
在这个例子中,我们首先创建了一个 3x3 的张量 x。然后,我们指定要选择的行的索引,即第 0 行和第 2 行。最后,我们调用torch.index_select()
函数,指定要索引的维度为 0(即行),并传入源张量和索引张量。函数返回一个新的张量,其中包含了选择的行。
2. torch.masked_select()
用于根据掩码张量从源张量中选择元素。它返回一个新的张量(返回值:一维张量),该张量包含源张量中对应掩码值为 True 的元素。它的用法是:torch.masked_select(input, mask)
。
import torch
# 创建一个 3x3 的张量
x = torch.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 创建一个掩码张量,选择大于 4 的元素
mask = x > 4
# 根据掩码选择元素
selected = torch.masked_select(x, mask)
print(selected)
#输出为:
tensor([5, 6, 7, 8, 9])
在这个例子中,我们首先创建了一个 3x3 的张量 x。然后,我们创建一个掩码张量 mask,其中大于 4 的元素被标记为 True。最后,我们调用 torch.masked_select() 函数,传入源张量和掩码张量。函数返回一个新的张量,其中包含了源张量中对应掩码值为 True 的元素。
1. torch.reshape()
用于改变张量的形状。它返回一个新的张量,该张量与原始张量共享数据,但具有不同的形状。它的用法是:torch.reshape(input, shape)
。
import torch
# 创建一个形状为 [2, 3] 的张量
x = torch.tensor([[1, 2, 3], [4, 5, 6]])
# 改变形状为 [3, 2]
reshaped = torch.reshape(x, [3, 2])
print(reshaped)
#输出为:
tensor([[1, 2],
[3, 4],
[5, 6]])
在这个例子中,我们首先创建了一个形状为 [2, 3] 的张量 x。然后,我们调用 torch.reshape() 函数,将 x 的形状改变为 [3, 2]。函数返回一个新的张量 reshaped,它与 x 共享数据,但具有不同的形状。
2. torch.transpose()
用于交换张量中的两个维度。它返回一个新的张量,其中指定的两个维度互换位置。它的用法是:torch.transpose(input, dim0, dim1)
。
import torch
# 创建一个形状为 [2, 3, 4] 的张量
x = torch.randn(2, 3, 4)
print(x)
# 交换第 0 和第 1 个维度
y = torch.transpose(x, 0, 1)
print(y)
print(y.shape) # 输出:torch.Size([3, 2, 4])
在这个例子中,我们首先创建了一个形状为 [2, 3, 4] 的张量 x。然后,我们调用 torch.transpose() 函数,将 x 中的第 0 和第 1 个维度交换。函数返回一个新的张量 y,其中第 0 和第 1 个维度互换位置,形状变为 [3, 2, 4]。