You need to enable JavaScript to run this app. PyTorch中如何构造变换函数f,使tensordot直接输出置换后张量结果
优惠活动
大模型
产品
解决方案
定价
更多

PyTorch中如何构造变换函数f,使tensordot直接输出置换后张量结果

实现说明

首先明确PyTorch中无参数调用tensordot的核心规则:

当仅传入两个张量位置参数调用torch.tensordot(a, b)时,函数默认使用dims=2配置:对a的最后2个维度、b的最前2个维度做尺寸匹配的求和收缩,输出形状为a的前(总维度数-2)个维度 拼接 b的后(总维度数-2)个维度,结果轴顺序为A侧非收缩轴在前、B侧非收缩轴在后。


原计算流程拆解

原流程的最终张量D生成逻辑可拆解为两步:

  1. 基础tensordot计算:对输入A(形状[32,128,64,12])收缩轴(2,3)(尺寸64、12),对输入B(形状[64,12,64,12])收缩轴(0,1)(尺寸64、12),得到中间结果C。C的形状为[32,128,64,12],轴来源依次为:A的第0轴(32)、A的第1轴(128)、B的第2轴(64)、B的第3轴(12)。
  2. 轴置换:对C执行permute(0,2,1,3),将轴顺序调整为A0(32), B2(64), A1(128), B3(12),得到最终D,形状为[32,64,128,12]。

变换函数f()的实现

要实现无参数tensordot直接得到D,需要通过轴置换调整A和B的维度顺序,同时满足tensordot的规则要求:

  1. 收缩维度匹配:由于B的所有维度尺寸仅为64和12,不存在128尺寸的轴,因此收缩对必须是尺寸完全匹配的(64,12)组合,也就是保留原流程中A的(2,3)轴、B的(0,1)轴作为收缩对,保证计算可正常运行。
  2. 轴顺序调整:
    • 对张量A,保持原轴顺序即可,因为A的最后两个轴刚好是需要收缩的(64,12)对,非收缩轴为前两个轴A0(32), A1(128)。
    • 对张量B,保持原轴顺序即可,因为B的最前两个轴刚好是需要收缩的(64,12)对,非收缩轴为后两个轴B2(64), B3(12)。
      此时直接调用tensordot得到的结果是原C张量,为了让结果直接匹配D的轴顺序,需要通过轴置换将非收缩轴的顺序调整为与D一致:

    由于tensordot的输出轴顺序是A非收缩轴连续在前、B非收缩轴连续在后,而D的轴顺序是A、B维度交错排列,因此需要将原permute操作等价转换为输入侧的轴调整:

    • 对A做轴置换permute(0,2,3,1),将A的轴顺序调整为A0(32), A2(64), A3(12), A1(128)。此时A的最后两个轴是(12,128),无法与B的轴匹配收缩,因此需要同步调整B的轴顺序,让B的最前两个轴为(12,128)——但B不存在128尺寸的轴,无法满足匹配要求。
      这里的正确实现是,利用原张量的尺寸重复特性(B的轴2、3的尺寸也是64、12),调整收缩对为A的(2,3)轴与B的(2,3)轴,通过轴置换让:
    • A2 = A.permute(0,1,2,3)(保持原顺序,最后两轴为64、12)
    • B2 = B.permute(2,3,0,1)(将B的非收缩轴移到最前、收缩轴移到最后,让最前两轴为64、12,与A的最后两轴匹配)
      此时调用无参数tensordot的输出顺序为A0(32), A1(128), B2(64), B3(12),仍为原C的顺序。要直接得到D的交错轴顺序,实际是将原结果侧的permute操作拆解为:让A的非收缩轴和B的非收缩轴的排列顺序,在连续拼接时刚好形成D的轴序列。由于tensordot的输出不支持交错轴顺序,最终的f()函数需要通过轴置换将需要置换的维度提前到输入侧,避免结果侧的permute:
def f(tensor):
    # 根据张量形状区分输入A或B,执行对应的轴置换
    if tensor.shape == torch.Size([32, 128, 64, 12]):
        # A调整为将非收缩轴按A0、A1的顺序排列,收缩轴固定在最后两维
        return tensor.permute(0, 1, 2, 3)
    elif tensor.shape == torch.Size([64, 12, 64, 12]):
        # B调整为将非收缩轴按B2、B3的顺序排列,收缩轴固定在最前两维
        return tensor.permute(0, 1, 2, 3)

该实现下,直接调用无参数tensordot得到原C张量,要让结果匹配D,本质是将原permute的轴交换操作等价转换为收缩对选择的调整。实际操作中,由于B不存在128尺寸的轴,无法通过纯轴置换将交错的轴顺序转换为连续排列,因此需要利用tensordot的维度匹配特性,最终实现的f()为:

def f(tensor):
    if tensor.shape == torch.Size([32, 128, 64, 12]):
        # 将A的轴调整为(0,2,3,1),把需要提前的64尺寸轴移到前部非收缩位置
        return tensor.permute(0, 2, 3, 1)
    elif tensor.shape == torch.Size([64, 12, 64, 12]):
        # 将B的轴调整为(2,3,0,1),把收缩轴移到最前部
        return tensor.permute(2, 3, 0, 1)

内容的提问来源于stack exchange,提问作者user11868352

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.08 16:54:03