距离矩阵的计算

距离矩阵 D i j x = ∥ x i − x j ∥ 2 2 D^x_{ij}=\left\|\boldsymbol{x}_i-\boldsymbol{x}_j\right\|_2^2 Dijx=xixj22的计算

给定数据矩阵 X ( N × D ) \boldsymbol{X}\left(N\times D\right) X(N×D), 经常需要求解每两个样本间的距离 D i j x = ∥ x i − x j ∥ 2 2 D^x_{ij}=\left\|\boldsymbol{x}_i-\boldsymbol{x}_j\right\|_2^2 Dijx=xixj22.

Remark: 这个距离矩阵的用处有很多,如核函数,对比学习, etc.

目前我所知有3种编程方法可以求解 D i j x D^x_{ij} Dijx.

  1. For Loop
import numpy as np

x = np.array([[1,5],[3,7],[7,9]])


def distance_forloop(x):
    N, _ = x.shape
    d = np.zeros((N,N))
    for i in range(N):
        for j in range(N):
            d[i,j] = np.sum((x[i,:]-x[j,:])*(x[i,:]-x[j,:]))
    
    return d
  1. Elementary calculation
def distance_elementary(x):
    aa = bb = np.sum(x * x, axis = 1, keepdims = True)
    ab = np.matmul(x, x.T)
    return aa + bb.T - 2 * ab
  1. Matrix Form

D x = d i a g n o a l { d i a g ( X X ⊤ ) } 1 1 ⊤ + 1 1 ⊤ d i a g n o a l { d i a g ( X X ⊤ ) } − 2 X X ⊤ \boldsymbol{D}^x=diagnoal\left\{diag\left(\boldsymbol{X}\boldsymbol{X}^\top \right)\right\}\boldsymbol{1}\boldsymbol{1}^\top+\boldsymbol{1}\boldsymbol{1}^\top diagnoal\left\{diag\left(\boldsymbol{X}\boldsymbol{X}^\top\right)\right\}-2\boldsymbol{X}\boldsymbol{X}^\top Dx=diagnoal{diag(XX)}11+11diagnoal{diag(XX)}2XX

where d i a g ( X X ⊤ ) = [ ∥ x 1 ∥ 2 2 , ⋯   , ∥ x N ∥ 2 2 ] diag\left(\boldsymbol{X}\boldsymbol{X}^\top \right) = \left[ \|\boldsymbol{x}_1\|_2^2, \cdots, \|\boldsymbol{x}_N\|_2^2\right] diag(XX)=[x122,,xN22].

def distance_matrixform(x):
    N, _ = x.shape
    diag = np.diagonal(np.matmul(x,x.T))# 这里得到的是向量
    diag = np.diag(diag)#还需要转换成对角矩阵
    one_one_t = np.ones((N,N))
    return np.matmul(diag,one_one_t) + np.matmul(one_one_t,diag) - 2*np.matmul(x, x.T)

Remakr: np.diagonal: (N,N)->(N,), np.diag:(N,)->(N,N)

经过检验这3种计算方式所得结果相同

d1 = distance_forloop(x)
print(d1)

d2 = distance_elementary(x)
print(d2)

d3 = distance_matrixform(x)
print(d3)

print((d1==d3)&(d1==d2))

但是方法2和方法3是类似的,计算效率都比1高,但是我个人倾向于方法3,因为它是公式化描述的。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值