【pytorch 中 于contiguous、permute和transpose用法】

以下是关于contiguous、permute和transpose这几个方法的详细说明:

1. contiguous

方法定义:

在PyTorch中,contiguous是一个Tensor的方法,用于返回一个在内存中连续存储的Tensor。这意味着Tensor的所有元素在内存中都是连续排列的,没有间隔。

用途:

在进行某些操作(如view或reshape)之前,Tensor可能需要是连续的。
当使用某些操作(如to方法改变数据类型或设备)时,Tensor可能会变得不连续。
在某些情况下,为了效率考虑,你可能希望Tensor是连续的。

示例:

python
import torch  
  
x = torch.tensor([[1, 2], [3, 4], [5, 6]]).t().contiguous()  # 转置并确保连续  
print(x.is_contiguous())  # 输出: True

2. permute

方法定义:

permute是一个Tensor的方法,用于对Tensor的维度进行重新排序。

参数:

一个整数列表,表示新维度的顺序。
用途:

改变Tensor的维度顺序,而不改变其内容。
在神经网络中,经常需要改变Tensor的维度顺序以适应不同的层或操作。
示例:

python
import torch  
  
x = torch.tensor([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])  # 形状为(2, 2, 2)  
y = x.permute(2, 0, 1) 
print(y.shape)  # 输出: torch.Size([2, 2, 2])  
print(y)  


# 输出Tensor的内容,展示维度顺序的变化  
# tensor([[[1, 5],  
#          [2, 6]],  
#  
#         [[3, 7],  
#          [4, 8]]])

解释上述转换过程

在给出的代码中,x 是一个形状为 (2, 2, 2) 的三维Tensor。当你使用 x.permute(2, 0, 1) 时,你实际上是在重新排列Tensor的维度。具体来说,这个 permute 调用将原始Tensor x 的每个维度移动到指定的新位置。

原始Tensor x 的形状是 (2, 2, 2),其中:

维度0(大小为2)对应于外层的两个方括号,即两个 […] 块。
维度1(大小为2)对应于每个 […] 块内的两个 [1, 2] 或[3, 4] 这样的子列表。
维度2(大小为2)对应于每个 [1, 2] 或 [3, 4] 这样的子列表中的两个数字。

现在,当你调用 x.permute(2, 0, 1) 时,你告诉PyTorch按照以下方式重新排列维度:

将原始维度2(大小为2,对应于每个子列表中的两个数字)移动到新的维度0。
将原始维度0(大小为2,对应于外层的两个方括号)移动到新的维度1。
将原始维度1(大小为2,对应于每个 […] 块内的两个子列表)移动到新的维度2。

因此,新的Tensor y 的形状将是 (2, 2, 2),但数据的排列方式已经改变。具体来说,y 中的数据现在是这样排列的:

第一个维度(大小为2)现在是原始Tensor x 中每个子列表的两个数字。
第二个维度(大小为2)现在是原始Tensor x 的外层两个方括号对应的块。
第三个维度(大小为2)现在是原始Tensor x 的每个块内的两个子列表。

输出Tensor y 的内容将展示这种维度顺序的变化:

tensor([[[1, 5],  
         [2, 6]],  
  
        [[3, 7],  
         [4, 8]]])

你可以这样理解这个输出:

在 y 的第一个“层面”(对应于新的维度0,即大小为2的维度),你有两个元素 [1, 5] 和 [3, 7]。这些元素来自于原始Tensor x 的第一个和第二个 [1, 2] 和 [3, 4] 子列表。

在 y 的第二个“层面”(对应于新的维度1,即大小为2的维度),你有两个块,每个块包含两个 [1, 2] 或 [3, 4]类型的子列表。 这些块对应于原始Tensor x 的两个外层方括号。

在每个块内部(对应于新的维度2),你有两个数字,对应于原始Tensor x 的每个子列表中的两个数字。


3. transpose

方法定义:

transpose是一个Tensor的方法,用于对Tensor的两个维度进行交换。

参数:

dim0 (int): 要交换的第一个维度的索引。
dim1 (int): 要交换的第二个维度的索引。
用途:

交换Tensor的两个维度。
在处理图像数据时,经常需要将高度和宽度(即维度1和2)进行交换,以适应不同的库或框架的输入要求。
示例:

python
import torch  
  
x = torch.tensor([[1, 2], [3, 4]])  # 形状为(2, 2)  
y = x.transpose(0, 1)  # 交换维度01  
print(y.shape)  # 输出: torch.Size([2, 2])  
print(y)  
# 输出Tensor的内容,展示维度交换的结果  
# tensor([[1, 3],  
#         [2, 4]])

注意:transpose是permute的一个特例,其中只交换两个维度。当需要交换多个维度时,使用permute更为方便。

以下是一个简单的PyTorch代码示例,用于实现视觉Transformer的多头注意力机制: ``` python import torch import torch.nn as nn class MultiHeadAttention(nn.Module): def __init__(self, d_model, num_heads): super(MultiHeadAttention, self).__init__() self.num_heads = num_heads self.d_model = d_model assert d_model % self.num_heads == 0 self.depth = d_model // self.num_heads self.Wq = nn.Linear(d_model, d_model) self.Wk = nn.Linear(d_model, d_model) self.Wv = nn.Linear(d_model, d_model) self.fc = nn.Linear(d_model, d_model) def scaled_dot_product_attention(self, Q, K, V, mask=None): d_k = Q.size(-1) scores = torch.matmul(Q, K.transpose(-1, -2)) / torch.sqrt(torch.tensor(d_k, dtype=torch.float32)) if mask is not None: scores = scores.masked_fill(mask == 0, -1e9) attention = torch.softmax(scores, dim=-1) output = torch.matmul(attention, V) return output, attention def split_heads(self, x, batch_size): x = x.view(batch_size, -1, self.num_heads, self.depth) return x.permute(0, 2, 1, 3) def forward(self, Q, K, V, mask=None): batch_size = Q.size(0) Q = self.Wq(Q) K = self.Wk(K) V = self.Wv(V) Q = self.split_heads(Q, batch_size) K = self.split_heads(K, batch_size) V = self.split_heads(V, batch_size) scaled_attention, attention = self.scaled_dot_product_attention(Q, K, V, mask) scaled_attention = scaled_attention.permute(0, 2, 1, 3).contiguous() scaled_attention = scaled_attention.view(batch_size, -1, self.d_model) output = self.fc(scaled_attention) return output, attention ``` 在这个代码,我们定义了一个 `MultiHeadAttention` 类,它包含了多头注意力机制的实现。在 `__init__` 函数,我们定义了注意力机制的一些参数,包括输入向量的维度 `d_model` 和头的数量 `num_heads`。我们还定义了一些线性层,用于将输入向量映射到查询、键和值向量。最后,我们定义了一个全连接层,用于将多头注意力机制的输出向量映射回原始向量的维度。 在 `scaled_dot_product_attention` 函数,我们计算了查询向量 `Q` 和键向量 `K` 之间的点积相似度,并对其进行了缩放。我们还可以选择对注意力矩阵应用一个掩码矩阵,以排除一些不必要的信息。最后,我们将注意力矩阵与值向量 `V` 相乘,得到多头注意力机制的输出向量。 在 `split_heads` 函数,我们将输入向量分成多个头,并将它们重新排列成一个更高维的张量。这样做是为了使每个头可以独立地进行注意力计算,从而提高模型的效率。 在 `forward` 函数,我们首先将输入向量通过线性层映射到查询、键和值向量。然后,我们将它们分成多个头,并将它们传递给 `scaled_dot_product_attention` 函数。最后,我们将多头注意力机制的输出向量通过全连接层映射回原始向量的维度,并返回它们以及注意力矩阵。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值