1. 程式人生 > >【Python資料探勘課程】七.PCA降維操作及subplot子圖繪製

【Python資料探勘課程】七.PCA降維操作及subplot子圖繪製

        這篇文章主要介紹四個知識點,也是我那節課講課的內容。
        1.PCA降維操作;
        2.Python中Sklearn的PCA擴充套件包;
        3.Matplotlib的subplot函式繪製子圖;
        4.通過Kmeans對糖尿病資料集進行聚類,並繪製子圖。

        希望這篇文章對你有所幫助,尤其是剛剛接觸資料探勘以及大資料的同學,這些基礎知識真的非常重要。如果文章中存在不足或錯誤的地方,還請海涵~


一. PCA降維


        參考文章:
        參考書籍:《機器學習導論》
        任何分類和迴歸方法的複雜度都依賴於輸入的數量,但為了減少儲存量和計算時間,我們需要考慮降低問題的維度,丟棄不相關的特徵。同時,當資料可以用較少的維度表示而不丟失資訊時,我們可以對資料繪圖,視覺化分析它的結構和離群點。
        特徵降維是指採用一個低緯度的特徵來表示高緯度。特徵降維一般有兩類方法:特徵選擇(Feature Selection)
特徵提取(Feature Extraction)。
        1.特徵選擇是從高緯度的特徵中選擇其中的一個子集來作為新的特徵。最佳子集是以最少的維貢獻最大的正確率,丟棄不重要的維,使用合適的誤差函式進行,方法包括在向前選擇(Forword Selection)和在向後選擇(Backward Selection)。
        2.特徵提取是指將高緯度的特徵經過某個函式對映至低緯度作為新的特徵。常用的特徵抽取方法就是PCA(主成分分析)和LDA(線性判別分析) 。
        下面著重介紹PCA。
        降維的本質是學習一個對映函式f:X->Y,其中X是原始資料點,用n維向量表示。Y是資料點對映後的r維向量,其中n>r。通過這種對映方法,可以將高維空間中的資料點
        主成分分析
(Principal Component Analysis,PCA)是一種常用的線性降維資料分析方法,其實質是在能儘可能好的代表原特徵的情況下,將原特徵進行線性變換、對映至低緯度空間中。
        PCA通過正交變換將一組可能存在相關性的變數轉換為一組線性不相關的變數,轉換後的這組變數叫主成分,它可用於提取資料的主要特徵分量,常用於高維資料的降維。
        該方法的重點在於:能否在各個變數之間相關關係研究基礎上,用較少的新變數代替原來較多的變數,而且這些較少新變數儘可能多地保留原來較多的變數所反映的資訊,又能保證新指標之間保持相互無關(資訊不重疊)。


        圖形解釋:上圖將二維樣本的散點圖降為一維表示,理想情況是這個1維新向量包含原始資料最多的資訊,選擇那條紅色的線,類似於資料的橢圓長軸,該方向離散程度最大,方差最大,包含的資訊量最多。短軸方向上的資料變化很少,對資料的解釋能力弱。

        原理解釋:

        下面引用xl890727的一張圖片簡單講解,因為我數學實在好弱,惡補中。
        PCA是多變數分析中最老的技術之一,它源於通訊理論中的K-L變換。




        其結果是該點到n個樣本之間的距離最小,從而通過該點表示這n個樣本。

        詳細過程:
        下面是主成分分析演算法的過程,還是那句話:數學太差是硬傷,所以參考的百度文庫的,還請海涵,自己真的得加強數學。





        總結PCA步驟如下圖所示:


二. Python中Sklearn的PCA擴充套件包

from sklearn.decomposition import PCA
        呼叫函式如下,其中n_components=2表示降低為2維。
pca = PCA(n_components=2)
        例如下面程式碼進行PCA降維操作:
import numpy as np
from sklearn.decomposition import PCA
X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])
pca = PCA(n_components=2)
print pca
pca.fit(X)
print(pca.explained_variance_ratio_) 
        輸出結果如下所示:
PCA(copy=True, n_components=2, whiten=False)
[ 0.99244291  0.00755711]
        再如載入boston資料集,總共10個特徵,降維成兩個特徵:
#載入資料集
from sklearn.datasets import load_boston
d = load_boston()
x = d.data
y = d.target
print x[:10]
print u'形狀:', x.shape

#降維
import numpy as np
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
newData = pca.fit_transform(x)
print u'降維後資料:'
print newData[:4]
print u'形狀:', newData.shape
        輸出結果如下所示,降低為2維資料。
[[  6.32000000e-03   1.80000000e+01   2.31000000e+00   0.00000000e+00
    5.38000000e-01   6.57500000e+00   6.52000000e+01   4.09000000e+00
    1.00000000e+00   2.96000000e+02   1.53000000e+01   3.96900000e+02
    4.98000000e+00]
 [  2.73100000e-02   0.00000000e+00   7.07000000e+00   0.00000000e+00
    4.69000000e-01   6.42100000e+00   7.89000000e+01   4.96710000e+00
    2.00000000e+00   2.42000000e+02   1.78000000e+01   3.96900000e+02
    9.14000000e+00]
 [  2.72900000e-02   0.00000000e+00   7.07000000e+00   0.00000000e+00
    4.69000000e-01   7.18500000e+00   6.11000000e+01   4.96710000e+00
    2.00000000e+00   2.42000000e+02   1.78000000e+01   3.92830000e+02
    4.03000000e+00]
 [  3.23700000e-02   0.00000000e+00   2.18000000e+00   0.00000000e+00
    4.58000000e-01   6.99800000e+00   4.58000000e+01   6.06220000e+00
    3.00000000e+00   2.22000000e+02   1.87000000e+01   3.94630000e+02
    2.94000000e+00]]
形狀: (506L, 13L)
降維後資料:
[[-119.81821283    5.56072403]
 [-168.88993091  -10.11419701]
 [-169.31150637  -14.07855395]
 [-190.2305986   -18.29993274]]
形狀: (506L, 2L)
        推薦大家閱讀官方的文件,裡面的內容可以學習,例如Iris鳶尾花降維。




三. Kmeans聚類糖尿病及降維subplot繪製子圖

        繪製多子圖
        
Matplotlib 裡的常用類的包含關係為 Figure -> Axes -> (Line2D, Text, etc.)。一個Figure物件可以包含多個子圖(Axes),在matplotlib中用Axes物件表示一個繪圖區域,可以理解為子圖。可以使用subplot()快速繪製包含多個子圖的圖表,它的呼叫形式如下:
        subplot(numRows, numCols, plotNum)
        subplot將整個繪圖區域等分為numRows行* numCols列個子區域,然後按照從左到右,從上到下的順序對每個子區域進行編號,左上的子區域的編號為1。如果numRows,numCols和plotNum這三個數都小於10的話,可以把它們縮寫為一個整數,例如subplot(323)和subplot(3,2,3)是相同的。subplot在plotNum指定的區域中建立一個軸物件。如果新建立的軸和之前建立的軸重疊的話,之前的軸將被刪除。
        當前的圖表和子圖可以使用gcf()和gca()獲得,它們分別是“Get Current Figure”和“Get Current Axis”的開頭字母縮寫。gcf()獲得的是表示圖表的Figure物件,而gca()則獲得的是表示子圖的Axes物件。下面我們在Python中執行程式,然後呼叫gcf()和gca()檢視當前的Figure和Axes物件。

import numpy as np
import matplotlib.pyplot as plt
  
plt.figure(1) # 建立圖表1
plt.figure(2) # 建立圖表2
ax1 = plt.subplot(211) # 在圖表2中建立子圖1
ax2 = plt.subplot(212) # 在圖表2中建立子圖2
  
x = np.linspace(0, 3, 100)
for i in xrange(5):
    plt.figure(1)    # 選擇圖表1 
    plt.plot(x, np.exp(i*x/3))
    plt.sca(ax1)    # 選擇圖表2的子圖1
    plt.plot(x, np.sin(i*x))
    plt.sca(ax2)    # 選擇圖表2的子圖2
    plt.plot(x, np.cos(i*x))
  
plt.show()
        輸出如下圖所示:
    
        詳細程式碼
        下面這個例子是通過Kmeans聚類,資料集是load_diabetes載入糖尿病資料集,然後使用PCA對資料集進行降維操作,降低成兩維,最後分別聚類為2類、3類、4類和5類,通過subplot顯示子圖。
# -*- coding: utf-8 -*-

#糖尿病資料集
from sklearn.datasets import load_diabetes
data = load_diabetes()
x = data.data
print x[:4]
y = data.target
print y[:4]

#KMeans聚類演算法
from sklearn.cluster import KMeans
#訓練
clf = KMeans(n_clusters=2)
print clf
clf.fit(x)
#預測
pre = clf.predict(x)
print pre[:10]

#使用PCA降維操作
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
newData = pca.fit_transform(x)
print newData[:4]

L1 = [n[0] for n in newData]
L2 = [n[1] for n in newData]

#繪圖
import numpy as np
import matplotlib.pyplot as plt

#用來正常顯示中文標籤
plt.rc('font', family='SimHei', size=8)
#plt.rcParams['font.sans-serif']=['SimHei'] 

#用來正常顯示負號
plt.rcParams['axes.unicode_minus']=False 

p1 = plt.subplot(221)
plt.title(u"Kmeans聚類 n=2")
plt.scatter(L1,L2,c=pre,marker="s")
plt.sca(p1)


###################################
# 聚類 類蔟數=3

clf = KMeans(n_clusters=3)
clf.fit(x)
pre = clf.predict(x)

p2 = plt.subplot(222)
plt.title("Kmeans n=3")
plt.scatter(L1,L2,c=pre,marker="s")
plt.sca(p2)


###################################
# 聚類 類蔟數=4

clf = KMeans(n_clusters=4)
clf.fit(x)
pre = clf.predict(x)

p3 = plt.subplot(223)
plt.title("Kmeans n=4")
plt.scatter(L1,L2,c=pre,marker="+")
plt.sca(p3)


###################################
# 聚類 類蔟數=5

clf = KMeans(n_clusters=5)
clf.fit(x)
pre = clf.predict(x)

p4 = plt.subplot(224)
plt.title("Kmeans n=5")
plt.scatter(L1,L2,c=pre,marker="+")
plt.sca(p4)

#儲存圖片本地
plt.savefig('power.png', dpi=300)  
plt.show()

        輸出結果如下圖所示,感覺非常棒,這有利於做實驗對比。


        最後希望這篇文章對你有所幫助,尤其是我的學生和接觸資料探勘、機器學習的博友。本來是24號感恩節半夜寫完的,實在太累,星期六來辦公室寫的,同時評估終於結束了,好累,但慶幸的是好多可愛的學生,自己也在成長,經歷很多終究是好事,她的酒窩沒有酒,我卻醉得像條狗。楊老師加油~
       (By:Eastmount 2016-11-26 下午4點半http://blog.csdn.net/eastmount/)