矩阵之间无循环计算L2距离

实现两个矩阵的无循环计算欧氏距离 Euclidean distance

navigation:
1.问题描述
2.解决方法

1.问题来源

kNN算法中会计算两个矩阵的距离

可以使用循环的方法来实现,效率较低

def compute_distances_one_loop(self, X):
    """
    train:5000x3072
    test: 500x3072
    - X: A numpy array of shape (num_test, D) containing test data
    Returns:
    - dists: A numpy array of shape (num_test, num_train) where dists[i, j]
      is the Euclidean distance between the ith test point and the jth training
      point.
    """
    num_test = X.shape[0]
    num_train = self.X_train.shape[0]
    dists = np.zeros((num_test, num_train))
    for i in range(num_test):
      #######################################################################
      # TODO:                                                               #
      # Compute the l2 distance between the ith test point and all training #
      # points, and store the result in dists[i, :].                        #
      #######################################################################
      distance=np.sqrt(np.sum(np.square(self.X_train - X[i,:]),axis=1))
      dists[i,:]=distance
    return dists

2.无循环计算L2 distances

一眼看到这个代码,真的是被深深折服!厉害,值得细细学习搞懂。

def compute_distances_no_loops(self, X):
    """
    Compute the distance between each test point in X and each training point
    in self.X_train using no explicit loops.
    Input / Output: Same as compute_distances_two_loops
    """
    num_test = X.shape[0]
    num_train = self.X_train.shape[0]
    dists = np.zeros((num_test, num_train))

    #########################################################################
    # TODO:                                                                 #
    # Compute the l2 distance between all test points and all training      #
    # points without using any explicit loops, and store the result in      #
    # dists.                                                                #
    #                                                                       #
    # You should implement this function using only basic array operations; #
    # in particular you should not use functions from scipy.                #
    #                                                                       #
    # HINT: Try to formulate the l2 distance using matrix multiplication    #
    #       and two broadcast sums.                                         #
    #########################################################################

    M = np.dot(X, self.X_train.T)
    nrow=M.shape[0]
    ncol=M.shape[1]
    te = np.diag(np.dot(X,X.T))
    tr = np.diag(np.dot(self.X_train,self.X_train.T))
    te= np.reshape(np.repeat(te,ncol),M.shape)
    tr = np.reshape(np.repeat(tr, nrow), M.T.shape)
    sq=-2 * M +te+tr.T
    dists = np.sqrt(sq)

    return dists

可能一下子有点懵,不着急 我们举个例子一步一步理解

要先知道计算L2的距离公式:
\[L2(x_{i},x_{j})=(\sum_{i=1}^{n} \mid x_{i}^{(l)} - x_{j}^{(l)} \mid ^{2})^{\frac{1}{2}}\]

计算L2距离需要得到 两点距离差的平方和的开方
再熟悉一个基本公式
\[(a-b)^{2}= a^{2}- 2ab+b^{2} \]

# 假设 x:4x3  ,y: 2x3 
# 最后输出一个 2x4矩阵
import numpy as np
>>> x=np.array([[1,2,3],[3,4,5],[5,6,7],[7,8,9]])
>>> x
array([[1, 2, 3],
       [3, 4, 5],
       [5, 6, 7],
       [7, 8, 9]])
>>> y=np.array([[2,3,4],[1,2,3]])
>>> y
array([[2, 3, 4],
       [1, 2, 3]])
# 计算两个矩阵的乘积
>>> M=np.dot(y,x.T)
>>> M
array([[20, 38, 56, 74],
       [14, 26, 38, 50]])
# 保存乘积矩阵的行列
>>> nrow=M.shape[0]
>>> ncol=M.shape[1]
>>> nrow
2
>>> ncol
4

先计算,提取出对角元素

>>> te=np.diag(np.dot(y,y.T))
>>> tr=np.diag(np.dot(x,x.T))
>>> te
array([29, 14])
>>> tr
array([ 14,  50, 110, 194])

按对角元素来进行扩充,满足矩阵计算要求

得到\(a^{2}\),\(b^{2}\)

# 继续整理
>>> te=np.reshape(np.repeat(te,ncol),M.shape)  # ncol:4 ,M: 2x4
>>> tr=np.reshape(np.repeat(tr,nrow),M.T.shape) #nrow:2 ,M.T:4x2
>>> te
array([[29, 29, 29, 29],
       [14, 14, 14, 14]])
>>> tr
array([[ 14,  14],
       [ 50,  50],
       [110, 110],
       [194, 194]])

\(-2ab\)就是-2*M
计算距离的开方

>>> sq=-2*M+te+tr.T
>>> dists=np.sqrt(sq)
>>> sq
array([[  3,   3,  27,  75],
       [  0,  12,  48, 108]])
>>> dists
array([[ 1.73205081,  1.73205081,  5.19615242,  8.66025404],
       [ 0.        ,  3.46410162,  6.92820323, 10.39230485]])
全部评论

相关推荐

10-19 10:28
已编辑
西南石油大学 后端工程师
团孝子已上线feeling:面了很多家公司,能感受到目前只有小公司+外包喜欢问八股。大厂虽然也问八股,但是是从实习、项目中进行提问,并且大厂会问很深,面试官也会对你的回答进行思考➕追问,所以准备大厂面试前一定要备好相关资料。对于算法,我做的是codetop前100+力扣hot100+力扣高频150,面试中实感hot100就足够,基本上只要是hot100就秒答。对于项目和八股,我做的也是烂大街的星球项目,八股则是看小林和问ai,自己也写了很多技术博客和画了很多思维导图,并且自己也尝试用嘴巴说出来,不只停留于纸面。运气也很重要,必须要让面试官/HR看到简历才行,所以建议投递时间是下午两点。tl:第一岗位9.9 投递9.10 一面(一面评价:最近见过最强的大三,结束五分钟后约二面,都晚上九点了不下班吗)9.11 二面(三道算法a出两道,反问评价:经验不够等横向,我实习生要啥经验)9.21挂(实习时间过短+其他原因,想要一年实习的,为什么不招个正职)第二岗位10.10投递10.11约面(主管打电话,说看到我之前投递记录了想要我挂qa职进去干后端,同意)10.14 一面(无八股,主动说确实很强,意愿很强)10.16 oc其余,友邦,东软,东华,惠择,用友oc已拒京东测开一面挂(投后端被测开捞)腾讯测试已拒(投后端被测开捞)ps:表扬惠择的主管面,没怎么问技术(可能是一面面试官沟通过了),全程一起讲大道理,解答了心中很多疑惑,也告诉我以面试官角度来看怎么选候选人,如果可以下次一定选惠择
HeaoDng:美团好像可以触发一面通
点赞 评论 收藏
分享
牛至超人:把哈工大,再加大加粗,看见闪闪发光的哈工大字样,面试官直接流口水
投递字节跳动等公司7个岗位
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务