機器學習-降維演算法(MDS演算法)
一,介紹
在現實資料中,很多資料都是高緯度的,在高緯度情況下進行資料處理將會有極大的資料處理量。為了,減少計算量,常常需要緩解這種資料維度災難,這有兩種途徑:降維和特徵選擇。
我們在這裡介紹其中一種降維演算法:MDS演算法。MDS演算法要求原始空間中樣本之間的距離在低維空間中得以保持。但是為了有效降維,我們往往只需要降維後的距離與原始空間距離儘可能接近即可。
要學習MDS演算法,首先,我們要了解範數的概念:
(1)向量範數
如果定義一個向量為:a=[-5,6,8, -10]
向量的1範數即:向量的各個元素的絕對值之和,上述向量a的1範數結果就是:29;
向量的2範數即:向量的每個元素的平方和再開平方根,上述a的2範數結果就是:15;
向量的負無窮範數即:向量的所有元素的絕對值中最小的:上述向量a的負無窮範數結果就是:5;
向量的正無窮範數即:向量的所有元素的絕對值中最大的:上述向量a的負無窮範數結果就是:10;
(2)矩陣範數
定義矩陣A = [ -1 2 -3;
4 -6 6]
矩陣的1範數(也叫A的列範數)即:矩陣的每一列上的元素絕對值先求和,再從中取個最大的,(列和最大),上述矩陣A的1範數先得到[5,8,9],再取最大的最終結果就是:9;
矩陣的2範數即:矩陣ATA的最大特徵值開平方根,A的特徵值為[3.06384528e-15,7.50621894e-0.1, 1.01249378e+02]上述矩陣A的2範數得到的最終結果是:10.0623;
矩陣的無窮範數即(也叫A的行範數):矩陣的每一行上的元素絕對值先求和,再從中取個最大的,(行和最大),上述矩陣A的1範數先得到[6;16],再取最大的最終結果就是:16;
接下來我們要介紹機器學習的低秩,稀疏等一些地方用到的範數,一般有核範數,L0範數,L1範數(有時很多人也叫1範數,這就讓初學者很容易混淆),L21範數(有時也叫2範數),F範數。。。上述範數都是為了解決實際問題中的困難而提出的新的範數定義,不同於前面的矩陣範數。
矩陣的核範數即:矩陣的奇異值(將矩陣svd分解)之和,這個範數可以用來低秩表示(因為最小化核範數,相當於最小化矩陣的秩——低秩),上述矩陣A最終結果就是:10.9287;
矩陣的L0範數即:矩陣的非0元素的個數,通常用它來表示稀疏,L0範數越小0元素越多,也就越稀疏,上述矩陣A最終結果就是:6;
矩陣的L1範數即:矩陣中的每個元素絕對值之和,它是L0範數的最優凸近似,因此它也可以表示稀疏,上述矩陣A最終結果就是:22;
矩陣的F範數即:矩陣的各個元素平方之和再開平方根,它通常也叫做矩陣的L2範數,它的有點在它是一個凸函式,可以求導求解,易於計算,上述矩陣A最終結果就是:10.0995;
矩陣的L21範數即:矩陣先以每一列為單位,求每一列的F範數(也可認為是向量的2範數),然後再將得到的結果求L1範數(也可認為是向量的1範數),很容易看出它是介於L1和L2之間的一種範數,上述矩陣A最終結果就是:17.1559。
演算法推導:
假定m個樣本之間的距離在原始控制元件的距離矩陣為D,我們目的是獲得降維到d維度的樣本矩陣Z:
即,第i個樣本和第j個樣本在D中距離為dist[i,j],在Z中為||Zi-Zj||(矩陣第i行減去第j行後的1範數),且dist[i,j]=||Zi-Zj||
我們令,則,從而得到:
(1)
為了便於討論,我們令樣本矩陣Z被中心化,即:
我們可以得到:
(2)
我們令:
(3)
(2)(3)代入(1)可得:
對距離矩陣B做特徵值分解,則可以獲得Z表示式:
二,程式碼
import numpy from sklearn import metrics, datasets, manifold from scipy import optimize from matplotlib import pyplot import pandas import collections def calculate_distance(x, y): d = numpy.sqrt(numpy.sum((x - y) ** 2)) return d # 計算矩陣各行之間的歐式距離;x矩陣的第i行與y矩陣的第0-j行繼續歐式距離計算,構成新矩陣第i行[i0、i1...ij] def calculate_distance_matrix(x, y): d = metrics.pairwise_distances(x, y) return d def cal_B(D): (n1, n2) = D.shape DD = numpy.square(D) # 矩陣D 所有元素平方 Di = numpy.sum(DD, axis=1) / n1 # 計算dist(i.)^2 Dj = numpy.sum(DD, axis=0) / n1 # 計算dist(.j)^2 Dij = numpy.sum(DD) / (n1 ** 2) # 計算dist(ij)^2 B = numpy.zeros((n1, n1)) for i in range(n1): for j in range(n2): B[i, j] = (Dij + DD[i, j] - Di[i] - Dj[j]) / (-2) # 計算b(ij) return B def MDS(data, n=2): D = calculate_distance_matrix(data, data) print(D) B = cal_B(D) Be, Bv = numpy.linalg.eigh(B) # Be矩陣B的特徵值,Bv歸一化的特徵向量 # print numpy.sum(B-numpy.dot(numpy.dot(Bv,numpy.diag(Be)),Bv.T)) Be_sort = numpy.argsort(-Be) Be = Be[Be_sort] # 特徵值從大到小排序 Bv = Bv[:, Be_sort] # 歸一化特徵向量 Bez = numpy.diag(Be[0:n]) # 前n個特徵值對角矩陣 # print Bez Bvz = Bv[:, 0:n] # 前n個歸一化特徵向量 Z = numpy.dot(numpy.sqrt(Bez), Bvz.T).T print(Z) return Z if __name__ == '__main__': data = numpy.mat([[3,2,4],[2,0,2],[4,2,4]]) Z = MDS(data)
得到結果:
原始距離矩陣為:
[[0. 3. 1. ]
[3. 0. 3.46410162]
[1. 3.46410162 0. ]]
可以,第一個點到第二個點的距離為3,第一個點到第三個點的距離為1,第二個點到第三個點的距離為3.464
降維矩陣:
[[-0.81858227 0.46777341]
[ 2.13331316 -0.06730921]
[-1.31473089 -0.4004642 ]]
根據上面的矩陣範數計算公式:
第一個點到第三個點的距離為||Z1-Z2||=2.951,第一個點到第二個點的距離為||Z1-Z3||=0.868,第二個點到第三個點的距離為2.447.
我們的資料從三維降低到了2維