矩陣之間無循環計算L2距離


實現兩個矩陣的無循環計算歐氏距離 Euclidean distance

navigation:
*[1.問題描述](#1.problems sources)
*[2.解決方法](#2.no loop cal the distances)

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]])


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM