• PyTorch在对矩阵沿列方向求平均值时如何忽略掉padding的影响?


    问题背景

    这是最近某技术交流群群友提出来的一个问题,感觉挺有意思,因此做个简单的记录。

    我们分两种情形来考虑,需要注意的是,无论是哪种情形,矩阵的形状基本是 (batch_size, sequence_length)

    情形一:整型矩阵

    此时矩阵中的每个元素均为相应词元在词表中的索引,例如

    a = torch.tensor([
        [3, 6, 1, 9, 9],
        [2, 7, 9, 9, 9],
    ])
    
    • 1
    • 2
    • 3
    • 4

    其中填充词元在词表中的索引为 9 9 9。不难看出,第一个句子的实际长度为 3 3 3,第二个句子的实际长度为 2 2 2

    我们期望最终的输出结果为

    tensor([3.3333, 4.5000])
    
    • 1

    即第一个句子的平均为 ( 3 + 6 + 1 ) / 3 = 3.333 (3+6+1)/3=3.333 (3+6+1)/3=3.333,第二个句子的平均为 ( 2 + 7 ) / 2 = 4.5 (2+7)/2=4.5 (2+7)/2=4.5

    情形二:浮点型矩阵

    浮点型矩阵可能来源于神经网络中某一层的输出,例如

    a = torch.tensor([
        [1.2607, -1.4688, 1.4340, 1.2454, 1.8901],
        [0.5616, -0.1035, 0.1797, 0.0235, -0.6699],
    ])
    
    • 1
    • 2
    • 3
    • 4

    我们期望最终的输出结果为

    tensor([0.4086, 0.2291])
    
    • 1

    即第一个句子的平均为 ( 1.2607 − 1.4688 + 1.4340 ) / 3 = 0.4086 (1.2607-1.4688+1.4340)/3=0.4086 (1.26071.4688+1.4340)/3=0.4086,第二个句子的平均为 ( 0.5616 − 0.1035 ) / 2 = 0.2291 (0.5616-0.1035)/2=0.2291 (0.56160.1035)/2=0.2291

    思路

    我们先来看情形一。

    为求得平均值,我们可以先统计每一行的实际长度

    tensor([3, 2])
    
    • 1

    然后让填充词元所在位置都变成 0 0 0

    tensor([[3, 6, 1, 0, 0],
            [2, 7, 0, 0, 0]])
    
    • 1
    • 2

    对该矩阵沿列方向求和再除以上述的实际长度即可。

    具体实现:

    def mean_without_padding(a, padding_idx):
        b = (a != padding_idx).sum(dim=1)
        c = copy.deepcopy(a)
        c[a == padding_idx] = 0
        return c.sum(dim=1) / b
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在计算浮点型矩阵的平均值时,我们一定会有情形一中的整型矩阵。这是因为,如果没有整型矩阵,我们就无法做embedding,进而得不到神经网络的输入,自然也就不可能产生浮点型矩阵。

    📝 大部分时候应该都是计算情形二中的矩阵,因为计算情形一并没有太多意义。

  • 相关阅读:
    大数据分析案例-基于随机森林模型对北京房价进行预测
    Vite入门从手写一个乞丐版的Vite开始(上)
    防止忘了,记录一下
    【图像压缩】DCT图像无损压缩【含GUI Matlab源码 726期】
    纯干货:准备输入文件 | VASP零基础保姆级指南
    Nginx 安装配置和实际使用
    5 步教你将 MRS 数据导入 DWS
    Android开发基础——UI实践
    Minifilter过滤驱动与R3程序通讯实现文件保护
    【论文阅读】视频理解系列论文精读
  • 原文地址:https://blog.csdn.net/raelum/article/details/128046231