1. 程式人生 > >機器學習-降維演算法(MDS演算法)

機器學習-降維演算法(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維