三元组法矩阵加法java_计算机视觉学习笔记(2.1)-KNN算法中距离矩阵的计算
本筆記系列以斯坦福大學CS231N課程為大綱,海豚瀏覽器每周組織一次授課和習題答疑。具體時間地點請見微信公眾號黑斑馬團隊(zero_zebra)和QQ群(142961883)發布。同時課程通過騰訊課堂(百納公開課)進行視頻直播.歡迎參與學習.
在CS231N的第二課,k-nearest neighbor這部分中,核心就是計算訓練集與測試集之元素之間的歐氏距離。課后作業要求從訓練集取5000個圖像,測試集取了500個圖像,計 算這5000個用于訓練的圖像與500個用于測試的圖像之間的歐氏距離,其結果就是一個5000*500的距離矩陣。
課后作業總共留了三道關于距離矩陣的計算題,分別是由易到難,從使用二重循環到不使用循環。特別是不使用循環的方法,需要一點數學基礎,不是特別直觀。經過研究《Numpy/Scipy Recipes for Data Science: Computing Nearest Neighbors》之后,決定把其中的方法寫出來。
任務定義
給定
階矩陣,滿足。這里第列向量是維向量。求矩陣,使得:計算方法
這里提供4種方法,需要使用到以下Python庫:
import numpy as np import numpy.linalg as la第一種方法:使用兩重循環
def compute_squared_EDM_method(X):# determin dimensions of data matrixm,n = X.shape# initialize squared EDM DD = np.zeros([n, n])# iterate over upper triangle of Dfor i in range(n):for j in range(i+1, n):D[i,j] = la.norm(X[:, i] - X[:, j])**2D[j,i] = D[i,j] #*1 return D由于是計算矩陣自身行向量之間的距離,所以結果是一個對稱的三角矩陣。注意*1行代碼處所做的優化。在上述方法中我們使用了兩層循環,因此代碼雖不簡潔,但十分易懂。
第二種方法
在第一種方法中,我們使用了numpy的norm這個方法,這個方法從數學上講,其計算公式是:
然后我們又將這個計算結果平方后賦給
因此,我們實際上是在計算:
上述運算可以使用點積(即矩陣內積)來計算:
D[i,j] = np.dot(X[:,i]-X[:,j],(X[:,i]-X[:,j]).T)現在代碼變化為:
def compute_squared_EDM_method2(X):# determin dimensions of data matrixm,n = X.shape# initialize squared EDM DD = np.zeros([n, n])# iterate over upper triangle of Dfor i in range(n):for j in range(i+1, n):d = X[:,i] - X[:,j]D[i,j] = np.dot(d, d)D[j,i] = D[i,j]return D第三種方法:避免循環內的點積運算
注意在上面的方法中,dot運算被調用了
次,并且每次進行了次乘積運算和次加法運算。盡管numpy底層可能對點積運算做了優化,但這里還是存在可能進行進一步優化。請看下面的數學推導:這里
屬于格拉姆矩陣中的元素,可以通過在循環外計算矩陣,在循環內直接引用元素值即可,從而在循環內我們只需要做兩次加(減)法運算:格拉姆矩陣的求法很簡單,只需要:
現在代碼變為:
def compute_squared_EDM_method3(X):# determin dimensions of data matrixm,n = X.shape# compute Gram matrixG = np.dot(X.T, X)# initialize squared EDM DD = np.zeros([n, n])# iterate over upper triangle of Dfor i in range(n):for j in range(i+1, n):d = X[:,i] - X[:,j]D[i,j] = G[i,i] - 2 * G[i,j] + G[j,j]D[j,i] = D[i,j]return D第四種方法:避免循環
假設距離矩陣可以表示為
,與公式進行對比,有:這里H中第i行的每一個元素,取值都為
,也就是H的每一列,都對應著格拉姆矩陣的對角陣,因此,我們可以用下面的代碼來計算H:H = np.tile(np.diag(G), (n,1))此外,由于
,所以最終距離矩陣可以計算為現在,代碼不再需要循環了:
def compute_squared_EDM_method4(x):m,n = X.shapeG = np.dot(X.T, X)H = np.tile(np.diag(G), (n,1))return H + H.T - 2*G擴展:任意行(列)同秩矩陣間的距離矩陣計算
上述方法解決了矩陣自身(列)向量之間的距離矩陣運算問題。對CS231N第二講的課程作業來說,需要求解的問題是:
給定訓練矩陣A為
階矩陣。這里5000 代表5000幅帶標簽的圖,3072是其各像素在RGB三個通道下的取值數。給定測試集矩陣B為階矩陣。求矩陣B的各行與矩陣A的各行的距離(即兩幅圖的差異)矩陣,這個矩陣是一個的矩陣。更一般地,這個問題可以描述如下:
給定矩陣A為
階矩陣,矩陣B為階矩陣,求矩陣B的任意行向量與矩陣A的任意行向量的距離矩陣。這個矩陣的數學表達式為(a, b均為行向量):為方便討論,我們將上述各項分別記為H, M, N, K,即:
顯然上述公式是無法進行運算的,因為除了M與D外,其它矩陣的秩各不相同。所以我們要回到前一個數學表達式上。
因此,可以在numpy中運用broadcasting機制,通過矩陣與行向量、列向量的運算傳播機制(broadcasting)來完成計算
def compute_distances_no_loops(A, B):m = np.shape(A)[0]n = np.shape(B)[0]dists = np.zeros((m, n)) # 求得矩陣M為 m*n維M = np.dot(A, B.T)# 對于H,我們只需要A.A^T的對角線元素,下面的方法高效求解(只計算對角線元素)# 結果H為m維行向量H = np.square(A).sum(axis = 1)#結果K為n維行向量.要將其元素運用到矩陣M的每一列,需要將其轉置為行向量K = np.square(B).sum(axis = 1)#H對M在y軸方向上傳播,即H加和到M上的第一行,K對M在x軸方向上傳播,即K加和到M上的每一列D = np.sqrt(-2*M+H+np.matrix(K).T)return D談談Numpy的broadcasting
在numpy中,當一個數與矩陣相加時,實際上是將矩陣中的每一個元素都加上這個數。注意在矩陣代數里,這種相加是不允許的。但實際應用中又很常見,所以Numpy就擴展了這個定義,允許一個實數矩陣相加,這就是broadcasting。
broadcasting在工程中是非常實用的。在第四種方法中,沒有使用 broadcasting機制,它是先取格拉姆矩陣的對角線元素(是n維列向量),再通過np.tile運算將其擴展為一個
的矩陣,然后才能完成相加的操作。而在擴展一節中,我們引入了行方向上(axis = 1)的傳播(與K的相加),也引入了列方向上(axis = 0)的傳播(與H的相加)。正因為有了這個傳播,我們無須象第四種方法那樣,顯式地生成一個矩陣。下面是broadcasting的規則:
這里看一個例子:
C = np.arange(0,3) D = np.arange(0, 40, 10).reshape(-1,1)這樣生成的C和D分別是3維行向量和4*1階矩陣。
>>> C array([0, 1, 2]) >>> D array([[ 0],[10],[20],[30]])如果計算C+D,結果如何?
課程導航
上一課:斯坦福CS231N課程學習筆記(二).理解CIFAR-10圖像數據庫
下一課
總結
以上是生活随笔為你收集整理的三元组法矩阵加法java_计算机视觉学习笔记(2.1)-KNN算法中距离矩阵的计算的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小米pay/mi pay怎么绑定招行信用
- 下一篇: nlp 命名实体识别 算法_中文命名实体