機器學習--主成分分析(PCA)算法的原理及優缺點

1、PCA算法的原理算法

  PCA(principle component analysis),即主成分分析法,是一個非監督的機器學習算法,是一種用於探索高維數據結構的技術,主要用於對數據的降維,經過降維能夠發現更便於人理解的特徵,加快對樣本有價值信息的處理速度,此外還能夠應用於可視化(降到二維)和去噪。
數據結構

  PCA本質上是將方差最大的方向做爲主要特徵,而且在各個正交方向上將數據「離相關」,也就是讓它們在不一樣正交方向上沒有相關性。dom

                                      

  求解思路:用方差來定義樣本的間距,方差越大表示樣本分佈越稀疏,方差越小表示樣本分佈越密集。機器學習

  方差的公式以下:函數

      

 

    在求解最大方差前,爲了方便計算,能夠先對樣本進行demean(去均值)處理,即減去每一個特徵的均值,這種處理方式不會改變樣本的相對分佈(效果就像座標軸進行了移動)。去均值後,樣本x每一個特徵維度上的均值都是0,方差的公式轉換下圖的公式:學習

                                                                                                     在這裏,表明已經通過映射後的某樣本。spa

    對於只有2個維度的樣本,如今的目標就是:求一個軸的方向w=(w1,w2),使得映射到w方向後,方差最大。3d

    目標函數表示以下:code

          

    爲求解此問題,須要使用梯度上升算法,梯度的求解公式以下:component

                                        

    PCA算法流程:   

    (1)去平均值,即每一位特徵減去各自的平均值;

    (2)計算協方差矩陣;

    (3)計算協方差矩陣的特徵值與特徵向量;

    (4)對特徵值從大到小排序;

    (5)保留最大的個特徵向量;

    (6)將數據轉換到個特徵向量構建的新空間中。

  PCA降維準則:

    (1) 最近重構性:樣本集中全部點,重構後的點距離原來的點的偏差之和最小。

    (2) 最大可分性:樣本在低維空間的投影儘量分開。

  PCA算法優勢:

    (1)使得數據集更易使用;

    (2)下降算法的計算開銷;

    (3)去除噪聲;

    (4)使得結果容易理解;

    (5)徹底無參數限制。

  PCA算法缺點:

    (1)若是用戶對觀測對象有必定的先驗知識,掌握了數據的一些特徵,卻沒法經過參數化等方法對處理過程進行干預,可能會得不到預期的效果,效率也不高;

    (2) 特徵值分解有一些侷限性,好比變換的矩陣必須是方陣;

    (3) 在非高斯分佈狀況下,PCA方法得出的主元可能並非最優的。

  PCA算法應用:

    (1)高維數據集的探索與可視化。

    (2)數據壓縮。

    (3)數據預處理。

    (4)圖象、語音、通訊的分析處理。

    (5)降維(最主要),去除數據冗餘與噪聲。

2、代碼實現

  1.本身實現的PCA算法

import numpy as np
import matplotlib.pyplot as plt

X=np.empty((100,2))
X[:,0]=np.random.uniform(0,100,size=100)
X[:,1]=0.75*X[:,0]+3+np.random.normal(0,10,size=100)
plt.scatter(X[:,0],X[:,1])

def demean(X):
    return X-np.mean(X,axis=0)
X_demean=demean(X)
plt.figure(2)
plt.scatter(X_demean[:,0],X_demean[:,1])
#print(np.mean(X[:,0]))
#print(np.mean(X_deman[:,0]))
#print(np.mean(X_deman[:,1]))

def f(w,X):
    return np.sum((X.dot(w)**2))/len(X)

def df_math(w,X):
    return X.T.dot(X.dot(w))*2/len(X)
 
def direction(w):
    return w / np.linalg.norm(w)
    
def gradient_ascent(df, X, initial_w, eta, n_iters = 1e4, epsilon=1e-8):
    
    w = direction(initial_w) 
    cur_iter = 0

    while cur_iter < n_iters:
        gradient = df(w, X)
        last_w = w
        w = w + eta * gradient
        w = direction(w) # 注意1:每次求一個單位方向
        if(abs(f(w, X) - f(last_w, X)) < epsilon):
            break
            
        cur_iter += 1

    return w

initial_w = np.random.random(X.shape[1]) # 注意2:不能用0向量開始
eta = 0.001
w = gradient_ascent(df_math, X_demean, initial_w, eta)
plt.figure(3)
plt.scatter(X_demean[:,0], X_demean[:,1])
#plt.plot([0, w[0]*30], [0, w[1]*30], color='r')
plt.plot([0, w[0]*50], [0 , w[1]*50], color='r')

 

 輸出結果:

相關文章
相關標籤/搜索