计算两个矩阵之间的欧式距离「建议收藏」

计算两个矩阵之间的欧式距离「建议收藏」在我们使用k-NN模型时,需要计算测试集中每一点到训练集中每一点的欧氏距离,即需要求得两矩阵之间的欧氏距离。在实现k-NN算法时通常有三种方案,分别是使用两层循环,使用一层循环和不使用循环。使用两层循环分别对训练集和测试集中的数据进行循环遍历,计算每两个点之间的欧式距离,然后赋值给dist矩阵。此算法没有经过任何优化。num_test=X.shape[0]num_…

大家好,又见面了,我是你们的朋友全栈君。

在我们使用k-NN模型时,需要计算测试集中每一点到训练集中每一点的欧氏距离,即需要求得两矩阵之间的欧氏距离。在实现k-NN算法时通常有三种方案,分别是使用两层循环,使用一层循环和不使用循环。

使用两层循环

分别对训练集和测试集中的数据进行循环遍历,计算每两个点之间的欧式距离,然后赋值给dist矩阵。此算法没有经过任何优化。

num_test = X.shape[0]
    num_train = self.X_train.shape[0]
    dists = np.zeros((num_test, num_train)) 
    for i in xrange(num_test):
      for j in xrange(num_train):
        ##################################################################### # TODO: # # Compute the l2 distance between the ith test point and the jth # # training point, and store the result in dists[i, j]. You should # # not use a loop over dimension. # #####################################################################
        # pass
        dists[i][j] = np.sqrt(np.sum(np.square(X[i] - self.X_train[j])))
        ##################################################################### # END OF YOUR CODE # #####################################################################
    return dists

使用一层循环

使用矩阵表示训练集的数据,计算测试集中每一点到训练集矩阵的距离,可以对算法优化为只使用一层循环。

def compute_distances_one_loop(self, X):
    """ Compute the distance between each test point in X and each training point in self.X_train using a single loop over the test data. 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))
    for i in xrange(num_test):
      ####################################################################### # TODO: # # Compute the l2 distance between the ith test point and all training # # points, and store the result in dists[i, :]. # #######################################################################
      # pass
      dists[i] = np.sqrt(np.sum(np.square(self.X_train - X[i]), axis = 1))
      ####################################################################### # END OF YOUR CODE # #######################################################################
    return dists

不使用循环

运算效率最高的算法是将训练集和测试集都使用矩阵表示,然后使用矩阵运算的方法替代之前的循环操作。但此操作需要我们对矩阵的运算规则非常熟悉。接下来着重记录如何计算两个矩阵之间的欧式距离。

记录测试集矩阵P的大小为M*D,训练集矩阵C的大小为N*D(测试集中共有M个点,每个点为D维特征向量。训练集中共有N个点,每个点为D维特征向量)
Pi P i 是P的第i行,记 Cj C j 是C的第j行
Pi=[Pi1Pi2PiD] P i = [ P i 1 P i 2 ⋯ P i D ] Cj=[Cj1Cj2CjD] C j = [ C j 1 C j 2 ⋯ C j D ]


首先计算 Pi P i Cj C j 之间的距离dist(i,j)
d(Pi,Cj)=(Pi1Cj1)2+(Pi2Cj2)2++(PiDCjD)2=(P2i1+P2i2++P2iD)+(C2j1+C2j2++C2jD)2×(Pi1Cj1+Pi2Cj2++PiDCiD)=Pi2+Cj22×PiCTj d ( P i , C j ) = ( P i 1 − C j 1 ) 2 + ( P i 2 − C j 2 ) 2 + ⋯ + ( P i D − C j D ) 2 = ( P i 1 2 + P i 2 2 + ⋯ + P i D 2 ) + ( C j 1 2 + C j 2 2 + ⋯ + C j D 2 ) − 2 × ( P i 1 C j 1 + P i 2 C j 2 + ⋯ + P i D C i D ) = ‖ P i ‖ 2 + ‖ C j ‖ 2 − 2 × P i C j T


我们可以推广到距离矩阵的第i行的计算公式
dist[i]=(Pi2Pi2Pi2)+(C12C22CN2)2×Pi(CT1CT2CTN)=(Pi2Pi2Pi2)+(C12C22CN2)2×PiCT d i s t [ i ] = ( ‖ P i ‖ 2 ‖ P i ‖ 2 ⋯ ‖ P i ‖ 2 ) + ( ‖ C 1 ‖ 2 ‖ C 2 ‖ 2 ⋯ ‖ C N ‖ 2 ) − 2 × P i ( C 1 T C 2 T ⋯ C N T ) = ( ‖ P i ‖ 2 ‖ P i ‖ 2 ⋯ ‖ P i ‖ 2 ) + ( ‖ C 1 ‖ 2 ‖ C 2 ‖ 2 ⋯ ‖ C N ‖ 2 ) − 2 × P i C T


继续将公式推广为整个距离矩阵
dist=P12P22PM2P12P22PM2P12P22PM2+C12C12C12C22C22C22CN2CN2CN22×PCT d i s t = ( ‖ P 1 ‖ 2 ‖ P 1 ‖ 2 ⋯ ‖ P 1 ‖ 2 ‖ P 2 ‖ 2 ‖ P 2 ‖ 2 ⋯ ‖ P 2 ‖ 2 ⋮ ⋮ ⋱ ⋮ ‖ P M ‖ 2 ‖ P M ‖ 2 ⋯ ‖ P M ‖ 2 ) + ( ‖ C 1 ‖ 2 ‖ C 2 ‖ 2 ⋯ ‖ C N ‖ 2 ‖ C 1 ‖ 2 ‖ C 2 ‖ 2 ⋯ ‖ C N ‖ 2 ⋮ ⋮ ⋱ ⋮ ‖ C 1 ‖ 2 ‖ C 2 ‖ 2 ⋯ ‖ C N ‖ 2 ) − 2 × P C T

表示为python代码:

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. #
    #########################################################################
    # pass
    dists = np.sqrt(-2*np.dot(X, self.X_train.T) + np.sum(np.square(self.X_train), axis = 1) + np.transpose([np.sum(np.square(X), axis = 1)]))
    #########################################################################
    # END OF YOUR CODE #
    #########################################################################
    return dists
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/150938.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 更改nginx默认端口_更改端口号

    更改nginx默认端口_更改端口号一、查看当前Nginx配置信息打开nginx根目录下conf文件夹,点击编辑nginx.conf文件。Tips:Windows系统用记事本打开会使utf-8文件头部加上BOM头,这会导致配置文件不能正常读取,Nginx启动失败。因此推荐使用SublimeText3之类的编辑器打开。 server{listen80;#默认端口号…

    2022年9月7日
    2
  • python-回文字符串[通俗易懂]

    python-回文字符串[通俗易懂]回文字符串(10分)题目内容:给定一个字符串,判断它是否是回文字符串(即类似于peep,12321这样的对称字符串),如果是输出True,不是则输出False。判断过程中假定只考虑字母和数字字符,而且忽略字母的大小写和其它符号(如空格、标点符号等)。 输入格式:共一行,为一个字符串。 输出格式:共一行,为True或False。 输入样例: lo…

    2022年6月2日
    51
  • Linux安装Node.js(图文解说详细版)

    Linux安装Node.js(图文解说详细版)第一步,下载安装包https://nodejs.org/dist/v12.14.1/第二步,上传到云服务器第三步,解压源码tar-zxvfnode-v12.14.1-linux-x64.tar.gz第四步,验证是否成功出现版本号说明成功了第五步,设置全局命令行vim/etc/profile之后就在任何地方的命令行输入node-v显示出信息就说明安装成功了…

    2022年10月20日
    0
  • 字符串非空判断:StringUtils中 isNotEmpty 和isNotBlank的区别

    字符串非空判断:StringUtils中 isNotEmpty 和isNotBlank的区别在项目中,我们用的最多的是StringUtils中的非空判断方法,相信大部分人都用过IsNotEmpty或者isEmpty方法今天我们要提到的,是isNotBlankpublicstaticbooleanisNotEmpty(Stringstr)判断某字符串是否非空,等于!isEmpty(Stringstr),这里不能排除空格字符下面是示例:Stri

    2022年8月12日
    9
  • java之接口[通俗易懂]

    java之接口[通俗易懂]java之接口1、接口的概念2、接口的属性3、接口与抽象类4、静态和私有方法5、默认方法6、解决默认方法冲突7、接口与回调1、接口的概念在java中,接口不是类,而是对符合这个接口的类的一组需求接口用interface声明声明一个Comparable接口可以将接口看成一个没有实例字段的抽象类publicinterfaceComparable{ 声明一个方法,方法的实现由实现这个接口的类来实现方法 接口绝不会有示例字段,在java8以前,在接口中绝对不会实现 方法。 priv

    2022年7月7日
    22
  • pycharm最新激活码(注册激活)「建议收藏」

    (pycharm最新激活码)本文适用于JetBrains家族所有ide,包括IntelliJidea,phpstorm,webstorm,pycharm,datagrip等。https://javaforall.net/100143.htmlIntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,上面是详细链接哦~S…

    2022年3月26日
    131

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号