微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在PyTorch中,计算欧式距离而不是矩阵乘法

如何解决在PyTorch中,计算欧式距离而不是矩阵乘法

假设我们有2个矩阵:

mat = torch.randn([20,7]) * 100
mat2 = torch.randn([7,20]) * 100

n,m = mat.shape

最简单的常用矩阵乘法如下所示:

def mat_vec_dot_product(mat,vect):
    n,m = mat.shape
    
    res = torch.zeros([n])
    for i in range(n):
        for j in range(m):
            res[i] += mat[i][j] * vect[j]
        
    return res

res = torch.zeros([n,n])
for k in range(n):
    res[:,k] = mat_vec_dot_product(mat,mat2[:,k])
    

但是,如果我需要应用L2规范而不是点积怎么办?代码如下:

def mat_vec_l2_mult(mat,m = mat.shape
    
    res = torch.zeros([n])
    for i in range(n):
        for j in range(m):
            res[i] += (mat[i][j] - vect[j]) ** 2
            
    res = res.sqrt()
        
    return res

for k in range(n):
    res[:,k] = mat_vec_l2_mult(mat,k])

我们可以使用Torch或其他任何库以某种最佳方式进行此操作吗?因为天真的O(n ^ 3)Python代码的工作速度非常慢。

解决方法

首先,PyTorch中的矩阵乘法具有内置运算符:@。 因此,只需乘以mat和mat2即可:

mat @ mat2

(应该工作,假设尺寸一致)。

现在,要计算似乎要在第二个块中计算的平方差和(SSD或L2范数),您可以做一个简单的技巧。 由于平方L2范数||m_i - v||^2(其中m_i是矩阵M的第i行,v是向量)等于点积{{1 }}-从点积的线性获得:<m_i - v,m_i-v>,因此您可以通过计算每行一次L2范数的平方来从向量<m_i,m_i> - 2<m_i,v> + <v,v>计算M中每一行的SSD ,一次是每行与向量之间的点积,一次是向量的L2范数。可以在v中完成。 但是,对于2个矩阵之间的SSD,您仍然会得到O(n^2)。尽管可以通过向量化操作而不是使用循环来进行改进。 这是2种矩阵的简单实现:

O(n^3)

所得矩阵将在def mat_mat_l2_mult(mat,mat2): rows_norm = (torch.norm(mat,dim=1,p=2,keepdim=True)**2).repeat(1,mat2.shape[1]) cols_norm = (torch.norm(mat2,dim=0,keepdim=True)**2).repeat(mat.shape[0],1) rows_cols_dot_product = mat @ mat2 ssd = rows_norm -2*rows_cols_dot_product + cols_norm return ssd.sqrt() mat = torch.randn([20,7]) mat2 = torch.randn([7,20]) print(mat_mat_l2_mult(mat,mat2)) 的每个像元处具有i,j的每一行i与{{1}的每一列mat之间的差的L2-范数}。

,

torch.cdist用于L2范数-欧几里德距离

res = torch.cdist(mat,mat2.permute(1,0),p=2)

在这里,我已经使用permutemat2的暗淡从7,20切换到20,7

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。