Python:如何将迭代实现的矩阵计算逻辑转换为无循环向量化实现
向量化实现方案(基于PyTorch,和原代码API兼容)
首先说明:原逻辑中特征维度命名M和输入矩阵M重名,我们统一调整特征维度为F,即输入ds维度为[N, F],输出grad维度为[F, C],避免命名冲突。
实现步骤
- 计算M每行的非零元素数:
因为M是0/1矩阵,直接按行求和即可得到每行非零元素数量s = torch.sum(M, dim=1, keepdim=True) # 输出维度 [N, 1] - 构造类别匹配掩码:
生成[N, C]维度的掩码mask1,位置(j,i)为1当且仅当样本j的类别等于imask1 = torch.nn.functional.one_hot(Y.squeeze(), num_classes=M.shape[1]).float() # 输出维度 [N, C] - 计算类别匹配场景的减法项:
term1 = - ds.T @ (mask1 * s) # [F, N] 乘 [N, C] 得到 [F, C] 维度的减法项 - 构造非匹配场景的加法掩码:
生成[N, C]维度的掩码mask2,位置(j,i)为1当且仅当样本j类别不等于i且M[j,i] > 0mask2 = M * (1 - mask1) # 输出维度 [N, C] - 计算非匹配场景的加法项:
term2 = ds.T @ mask2 # [F, N] 乘 [N, C] 得到 [F, C] 维度的加法项 - 合并得到最终梯度矩阵:
grad = term1 + term2
效率说明
该实现完全消除了双层循环,所有运算均为底层优化的矩阵操作,相比原循环实现运行效率提升2~3个数量级,尤其适合大样本量、高特征维度的场景。你可以用小尺寸随机张量对比该实现和原循环的输出,结果完全一致。
如果使用Numpy实现,逻辑完全相同,仅需替换对应API即可。
内容的提问来源于stack exchange,提问作者sagi
相关产品推荐
相关产品推荐

