1. 程式人生 > >PCA主成分分析Python實現

PCA主成分分析Python實現

more 公式 最大 最重要的 例如 好的 mina details args

作者:拾毅者
出處:http://blog.csdn.net/Dream_angel_Z/article/details/50760130
Github源代碼:https://github.com/csuldw/MachineLearning/tree/master/PCA

PCA(principle component analysis) 。主成分分析,主要是用來減少數據集的維度,然後挑選出基本的特征。原理簡單,實現也簡單。關於原理公式的推導,本文不會涉及,你能夠參考以下的參考文獻,也能夠去Wikipedia,這裏主要關註實現,算是鍛煉一下自己。

本來是在復習LDA的,然後就看到了PCA。就跟著以下這篇文章的步驟,把PCA用python實現了一遍,詳細的思想能夠參考這篇文章,講的通俗易懂,主要是有個實例參考,值得擁有!

  • JerryLead之PCA主成分分析

以下自己來簡單的清理下思路!

PCA思想

主要思想:移動坐標軸,將n維特征映射到k維上(k<n),這k維是全新的正交特征。

這k維特征稱為主元,是又一次構造出來的k維特征。而不是簡單地從n維特征中去除其余n-k維特征。

說到PCA難免會提到LDA(linear discriminate analysis。線性判別分析),以及FA(factor analysis,因子分析)。關於LDA。打算有時間也用代碼實現一遍,以下給出它的主要思想。

LDA思想:最大類間距離,最小類內距離。簡而言之,第一,為了實現投影後的兩個類別的距離較遠。用映射後兩個類別的均值差的絕對值來度量。

第二。為了實現投影後,每一個類內部數據點比較聚集。用投影後每一個類別的方差來度量。

三者的描寫敘述例如以下

以下內容引自 Wikipedia- Linear discriminant analysis

LDA is also closely related to principal component analysis (PCA) and factor analysis in that they both look for linear combinations of variables which best explain the data.[4] LDA explicitly attempts to model the difference between the classes of data. PCA on the other hand does not take into account any difference in class, and factor analysis builds the feature combinations based on differences rather than similarities. Discriminant analysis is also different from factor analysis in that it is not an interdependence technique: a distinction between independent variables and dependent variables (also called criterion variables) must be made.

差別:PCA選擇樣本點投影具有最慷慨差的方向,LDA選擇分類性能最好的方向。

好了,以下來看下實現源代碼!

基本步驟

基本步驟:

  • 對數據進行歸一化處理(代碼中並不是這麽做的,而是直接減去均值)
  • 計算歸一化後的數據集的協方差矩陣
  • 計算協方差矩陣的特征值和特征向量
  • 保留最重要的k個特征(通常k要小於n)。也能夠自己制定。也能夠選擇一個閾值,然後通過前k個特征值之和減去後面n-k個特征值之和大於這個閾值,則選擇這個k
  • 找出k個特征值相應的特征向量
  • 將m * n的數據集乘以k個n維的特征向量的特征向量(n * k),得到最後降維的數據。

事實上PCA的本質就是對角化協方差矩陣。有必要解釋下為什麽將特征值按從大到小排序後再選。

首先,要明確特征值表示的是什麽?在線性代數裏面我們求過無數次了。那麽它詳細有什麽意義呢?對一個n*n的對稱矩陣進行分解。我們能夠求出它的特征值和特征向量,就會產生n個n維的正交基,每一個正交基會相應一個特征值。

然後把矩陣投影到這N個基上,此時特征值的模就表示矩陣在該基的投影長度。

特征值越大。說明矩陣在相應的特征向量上的方差越大。樣本點越離散。越easy區分,信息量也就越多。因此。特征值最大的相應的特征向量方向上所包括的信息量就越多,假設某幾個特征值非常小。那麽就說明在該方向的信息量非常少,我們就能夠刪除小特征值相應方向的數據,僅僅保留大特征值方向相應的數據,這樣做以後數據量減小。但實用的信息量都保留下來了。PCA就是這個原理。

源代碼實現

1.首先引入numpy,由於測試中用到了pandas和matplotlib。所以這裏一並載入

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

2.定義一個均值函數

#計算均值,要求輸入數據為numpy的矩陣格式,行表示樣本數,列表示特征    
def meanX(dataX):
    return np.mean(dataX,axis=0)#axis=0表示依照列來求均值。假設輸入list,則axis=1

3.編寫pca方法,詳細解釋參考凝視

"""
參數:
    - XMat:傳入的是一個numpy的矩陣格式,行表示樣本數,列表示特征    
    - k:表示取前k個特征值相應的特征向量
返回值:
    - finalData:參數一指的是返回的低維矩陣,相應於輸入參數二
    - reconData:參數二相應的是移動坐標軸後的矩陣
"""
def pca(XMat, k):
    average = meanX(XMat) 
    m, n = np.shape(XMat)
    data_adjust = []
    avgs = np.tile(average, (m, 1))
    data_adjust = XMat - avgs
    covX = np.cov(data_adjust.T)   #計算協方差矩陣
    featValue, featVec=  np.linalg.eig(covX)  #求解協方差矩陣的特征值和特征向量
    index = np.argsort(-featValue) #依照featValue進行從大到小排序
    finalData = []
    if k > n:
        print "k must lower than feature number"
        return
    else:
        #註意特征向量時列向量。而numpy的二維矩陣(數組)a[m][n]中,a[1]表示第1行值
        selectVec = np.matrix(featVec.T[index[:k]]) #所以這裏須要進行轉置
        finalData = data_adjust * selectVec.T 
        reconData = (finalData * selectVec) + average  
    return finalData, reconData

4.編寫一個載入數據集的函數

#輸入文件的每行數據都以\t隔開
def loaddata(datafile):
    return np.array(pd.read_csv(datafile,sep="\t",header=-1)).astype(np.float)

5.可視化結果

由於我將維數k指定為2,所以能夠使用以下的函數將其繪制出來:

def plotBestFit(data1, data2):    
    dataArr1 = np.array(data1)
    dataArr2 = np.array(data2)

    m = np.shape(dataArr1)[0]
    axis_x1 = []
    axis_y1 = []
    axis_x2 = []
    axis_y2 = []
    for i in range(m):
        axis_x1.append(dataArr1[i,0])
        axis_y1.append(dataArr1[i,1])
        axis_x2.append(dataArr2[i,0]) 
        axis_y2.append(dataArr2[i,1])                 
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.scatter(axis_x1, axis_y1, s=50, c=‘red‘, marker=‘s‘)
    ax.scatter(axis_x2, axis_y2, s=50, c=‘blue‘)
    plt.xlabel(‘x1‘); plt.ylabel(‘x2‘);
    plt.savefig("outfile.png")
    plt.show()  

6.測試方法

測試方法寫入main函數中,然後直接運行main方法就可以:

data.txt可到github中下載:data.txt

#依據數據集data.txt
def main():    
    datafile = "data.txt"
    XMat = loaddata(datafile)
    k = 2
    return pca(XMat, k)
if __name__ == "__main__":
    finalData, reconMat = main()
    plotBestFit(finalData, reconMat)

結果展示

最後的結果圖例如以下:


技術分享

藍色部分為重構後的原始數據。紅色則是提取後的二維特征!

參考文獻

[1] http://www.cnblogs.com/jerrylead/archive/2011/04/18/2020209.html
[2] Wikipedia- Linear discriminant analysis
[3] Wikipedia- Principal_component_analysis

PCA主成分分析Python實現