常用Tensor方法!🍧

常用Tensor方法

1.topk

Tensor.topk 是 PyTorch 中的一个函数,用于在张量(Tensor)中获取前 k 个最大值或最小值及其对应的索引。

具体而言,Tensor.topk 函数返回的是给定张量中的前 k 个最大值(或最小值)以及它们在张量中的位置索引。函数的签名通常如下:

1
values, indices = torch.topk(input, k, dim=None, largest=True, sorted=True, out=None)

其中:

  • input 是输入的张量。
  • k 是要获取的最大值或最小值的个数。
  • dim 是在哪个维度上进行检索。如果不指定,则默认为整个张量。
  • largest 是一个布尔值,用于指定是否获取最大值。如果为 True,则返回前 k 个最大值;如果为 False,则返回前 k 个最小值。
  • sorted 也是一个布尔值,用于指定返回的结果是否按照大小顺序排列。
  • out 是一个可选的输出张量。

以下是一个示例:

1
2
3
4
5
6
7
8
9
import torch

# 创建一个示例张量
tensor = torch.tensor([1, 3, 2, 5, 4])

# 获取前3个最大值及其索引
top_values, top_indices = tensor.topk(3)
print(top_values) # 输出: tensor([5, 4, 3])
print(top_indices) # 输出: tensor([3, 4, 1])

在这个示例中,top_values 包含了输入张量中的前 3 个最大值 [5, 4, 3],而 top_indices 包含了这些值在原始张量中的索引 [3, 4, 1]

2.add_

add_ 是PyTorch张量(Tensor)类的一个方法,用于将另一个张量的值加到当前张量上。这个方法是就地操作,即会修改调用它的张量,并且返回修改后的张量。

具体来说,add_ 方法有几种不同的用法:

2.1 张量相加

1
tensor1.add_(tensor2)

这会将张量 tensor2 的值加到张量 tensor1 上,并修改 tensor1 的值。如果 tensor1tensor2 的形状不匹配,PyTorch会自动进行广播(broadcasting)操作,使得它们可以相加。

2.2 标量相加

1
tensor.add_(scalar)

2.3 张量与标量相乘再相加

1
tensor.add_(other_tensor, alpha=scalar)

3.unsqueeze_

unsqueeze_ 是 PyTorch 中的一个张量操作函数,用于在指定的维度上增加一个大小为 1 的维度。这个操作是 in-place 的,意味着它会修改原始张量而不是返回一个新的张量。

语法如下:

1
tensor.unsqueeze_(dim)
  • tensor: 要进行操作的张量。
  • dim: 要在其前面插入维度的索引。如果 dim 是负数,则从末尾开始计数。

例如,假设有一个形状为 (3, 4) 的张量:

1
2
3
4
5
import torch

tensor = torch.tensor([[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]])

如果我们想在第一个维度上增加一个大小为 1 的维度,可以使用 unsqueeze_ 操作:

1
tensor.unsqueeze_(0)

这将使得张量的形状变为 (1, 3, 4),因为在原来的维度 0 的位置上插入了一个维度大小为 1 的维度。

同样,我们也可以在其他维度上插入维度:

1
tensor.unsqueeze_(2)

这将使得张量的形状变为 (1, 3, 1, 4)。

4.squeeze

tensor.squeeze() 是一个用于删除尺寸为 1 的维度的 PyTorch 张量方法。在张量中,有时会存在维度大小为 1 的维度,这些维度可能是由于某些操作或者数据结构的需求而产生的,但是它们对于张量的计算没有实质性的影响。squeeze() 方法就是用来删除这些维度,从而使得张量更加紧凑。

1
2
3
4
5
6
7
8
9
import torch

# 创建一个具有维度大小为 1 的维度的张量
tensor = torch.randn(1, 3, 1, 5)
print("原始张量形状:", tensor.shape) # 输出:torch.Size([1, 3, 1, 5])

# 删除维度大小为 1 的维度
squeezed_tensor = tensor.squeeze()
print("删除维度后的张量形状:", squeezed_tensor.shape) # 输出:torch.Size([3, 5])

tips:

  • 需要注意的是,squeeze() 方法默认会删除所有维度大小为 1 的维度,但也可以通过传递参数指定删除某些特定的维度。
  • 调用 squeeze(-1) 方法是针对张量的最后一个维度进行压缩,即删除最后一个维度中大小为 1 的维度。这在处理张量中的单例维度时非常有用,尤其是在处理很多卷积网络或循环神经网络的输出时。
  • 如果指定的维度大小不为 1,那么 squeeze(dim) 方法会保持原样,不会删除任何维度。这个方法仅仅会删除大小为 1 的维度。

5.detach

detach() 是 PyTorch 中张量的一个方法,用于创建一个新的张量,该张量与原始张量共享数据,但是不再与计算图相关联。换句话说,它会将张量从当前的计算图中分离出来,使得我们可以在不影响梯度计算的情况下对其进行操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
import torch

# 创建一个需要梯度的张量
tensor = torch.tensor([1.0, 2.0, 3.0], requires_grad=True)

# 对张量进行操作
result = tensor * 2

# 调用 detach() 方法,分离张量
detached_tensor = result.detach()

print("result:", result)
print("detached_tensor:", detached_tensor)

在这个示例中,result 是通过对 tensor 进行乘法运算得到的新张量,它依赖于 tensor,因此也会有梯度。调用 detach() 方法后,detached_tensor 将会分离出来,不再与计算图相关联,因此不再具有梯度信息。

6.fill_

fill_() 是 PyTorch 张量的一个方法,用于将张量中的所有元素填充为指定的值。这个方法会修改原始张量,并且不会返回新的张量。下划线(_)表示这个方法会就地修改张量,而不是返回一个新的张量。

1
2
3
4
5
6
7
8
9
10
11
import torch

# 创建一个形状为 2x3 的张量,所有元素初始化为 0
tensor = torch.zeros(2, 3)
print("Original Tensor:")
print(tensor)

# 使用 fill_ 方法将所有元素填充为 5
tensor.fill_(5)
print("\nTensor after fill_ with 5:")
print(tensor)

结果:

1
2
3
4
5
6
7
Original Tensor:
tensor([[0., 0., 0.],
[0., 0., 0.]])

Tensor after fill_ with 5:
tensor([[5., 5., 5.],
[5., 5., 5.]])

7.permute

permute 是 PyTorch 中用于维度置换(dimension permutation)的函数。它可以重新排列张量的维度。假设你有一个张量 tensor,你可以使用 permute 函数来重新排列其维度,如下所示:

1
2
3
4
5
6
7
8
9
import torch

# 创建一个示例张量
tensor = torch.randn(2, 3, 4) # 形状为 (2, 3, 4)

# 使用 permute 函数重新排列维度
permuted_tensor = tensor.permute(1, 2, 0) # 将第一个维度移到最后,形状变为 (3, 4, 2)

print(permuted_tensor.shape)

在这个示例中,原始张量的形状是 (2, 3, 4),使用 permute(1, 2, 0) 将第一个维度移到最后,新的张量形状变为 (3, 4, 2)

permute 函数接受一个整数参数序列作为输入,表示重新排列后的维度顺序。

8.view

在PyTorch中,tensor.view()是一个函数,用于调整张量的形状,但是不改变其数据。它可以用于在不复制数据的情况下改变张量的形状,这在深度学习中非常有用。

该函数的语法是:

1
new_tensor = tensor.view(*shape)

其中tensor是原始的张量,shape是一个元组,指定了新张量的形状。*shape的意思是将shape元组中的元素解包,作为独立的参数传递给view()函数。

值得注意的是,tensor.view()返回的新张量与原始张量共享数据存储空间,因此在某些情况下,修改新张量可能会影响原始张量,反之亦然。如果想要确保新张量和原始张量完全独立,可以使用tensor.clone().view()

1
2
3
4
5
6
7
8
9
10
11
12
13
import torch

# 创建一个4x4的张量
x = torch.arange(16).reshape(4, 4)
print("原始张量:", x)

# 改变形状为2x8
x_view = x.view(2, 8)
print("改变形状后的张量:", x_view)

# 改变形状为2x2x4
x_view = x.view(2, 2, 4)
print("改变形状后的张量:", x_view)

tips:

tensor.view()reshape()在功能上非常相似,都可以用于改变张量的形状,但它们在实现方式和一些细节上有所不同。

tensor.view()reshape()在功能上非常相似,都可以用于改变张量的形状,但它们在实现方式和一些细节上有所不同。

  1. 共享内存 vs 复制内存
    • tensor.view(): 返回的新张量与原始张量共享相同的数据存储空间,因此在内存上没有额外的开销。但是需要确保新形状的元素数量与原张量相同,否则会报错。
    • reshape(): 返回一个具有指定形状的新张量,如果新形状与原张量的元素数量相同,那么不会进行数据复制,否则会复制数据到一个新的内存空间中。
  2. 灵活性
    • tensor.view(): 由于共享内存,对原始张量的修改可能会影响到新张量,反之亦然。
    • reshape(): 返回一个新的张量,与原始张量完全独立,因此对新张量的修改不会影响原始张量,反之亦然。
  3. 适用范围
    • tensor.view(): 通常用于在不改变数据的情况下改变张量的形状,例如在神经网络中进行形状变换。
    • reshape(): 除了可以改变形状外,还可以用于在不同的内存布局之间转换张量,例如将行优先的张量转换为列优先的张量。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import torch

# 创建一个4x4的张量
x = torch.arange(16)

# 使用view改变形状
x_view = x.view(2, 8)

# 使用reshape改变形状
x_reshape = x.reshape(2, 8)

# 修改原始张量的一个元素
x[0] = 100

print("使用view改变形状后的张量:", x_view)
print("使用reshape改变形状后的张量:", x_reshape)

在上面的示例中,因为view()返回的张量与原始张量共享内存,所以对原始张量的修改会影响到x_view,而reshape()返回的是一个新的张量,因此x_reshape不受影响。

在PyTorch中,.view(1, -1)用于将张量重塑为具有1行的二维张量,并且该张量的列数由参数-1确定。这里的-1表示在给定的维度上由系统自动推断其大小,以确保原始张量中的元素数量与重塑后的张量中的元素数量保持一致。

例如,如果有一个形状为(4, 4)的张量,使用.view(1, -1)将会把它重塑为一个形状为(1, 16)的张量,其中有1行,列数由系统自动计算,即16列。这样做的效果是将原始张量中的所有元素都放入新的一行中。

这种操作通常在深度学习中用于将具有多个轴的张量(如多通道图像)转换为二维张量以便进行某些操作,比如全连接层的输入。

9.reshape

在 PyTorch 中,tensor.reshape() 方法用于重新塑形张量,使其具有新的形状,而不改变其数据。具体语法为:

1
tensor.reshape(*shape)

其中,*shape 是新的张量形状。该方法返回一个具有指定形状的新张量,但不改变原始张量的数据。

以下是一个简单的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import torch

# 创建一个大小为 (2, 3, 4) 的张量
tensor = torch.arange(24).reshape(2, 3, 4)

print("原始张量:")
print(tensor)
print("原始张量形状:", tensor.shape)

# 重新塑形为 (4, 6)
reshaped_tensor = tensor.reshape(4, 6)

print("重新塑形后的张量:")
print(reshaped_tensor)
print("重新塑形后的张量形状:", reshaped_tensor.shape)

输出结果为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
原始张量:
tensor([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]],

[[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23]]])
原始张量形状: torch.Size([2, 3, 4])
重新塑形后的张量:
tensor([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23]])
重新塑形后的张量形状: torch.Size([4, 6])

可以看到,原始张量是一个大小为 (2, 3, 4) 的三维张量,通过 reshape 方法重新塑形为大小为 (4, 6) 的二维张量。

10.transpose

tensor.transpose(0, 1) 是 PyTorch 中的一个函数调用,用于对张量进行转置操作。在这个特定的调用中,01 是维度索引,表示对张量的第一个和第二个维度进行转置操作。

假设有一个二维张量(2维数组):

1
2
3
4
import torch

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

执行 tensor.transpose(0, 1) 操作将交换张量的第一个维度和第二个维度,因此结果将是原始张量的转置,示例如下:

1
2
3
4
5
6
7
transposed_tensor = tensor.transpose(0, 1)
print(transposed_tensor)

输出:
tensor([[1, 4],
[2, 5],
[3, 6]])

11.masked_fill

masked_fill 是 PyTorch 中张量的一个方法,用于根据掩码(mask)替换张量中的元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import torch

# 创建一个原始张量
tensor = torch.tensor([[1, 2, 3],
[4, 5, 6]])

# 创建一个掩码张量
mask = torch.tensor([[True, False, True],
[False, True, False]])

# 将原始张量中掩码为 True 的位置替换为 0
result = tensor.masked_fill(mask, 0)

print(result)

输出:
tensor([[0, 2, 0],
[4, 0, 6]])

12.expand_as

expand_as 是 PyTorch 中的一个方法,用于将一个张量扩展成与另一个张量具有相同大小的形状。具体来说,expand_as 方法会返回一个新的张量,该张量与指定的张量具有相同的形状,但是复制了当前张量的内容,以填充新张量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import torch

# 创建两个张量
tensor1 = torch.tensor([[1, 2],
[3, 4]])
tensor2 = torch.tensor([[0.1, 0.2]])

# 使用 expand_as 方法将 tensor2 扩展成与 tensor1 相同的形状
expanded_tensor2 = tensor2.expand_as(tensor1)

print("原始张量 tensor2:")
print(tensor2)
print("扩展后的张量 expanded_tensor2:")
print(expanded_tensor2)

# 输出
原始张量 tensor2:
tensor([[0.1000, 0.2000]])

扩展后的张量 expanded_tensor2:
tensor([[0.1000, 0.2000],
[0.1000, 0.2000]])

常用Tensor方法!🍧
https://yangchuanzhi20.github.io/2024/02/03/人工智能/Pytorch/基础知识/常用张量操作/
作者
白色很哇塞
发布于
2024年2月3日
许可协议