轉載地址 :http://blog.csdn.net/eastmount/article/details/53285192
一. PCA降維
參考文章:http://blog.csdn.net/xl890727/article/details/16898315
參考書籍:《機器學習導論》
任何分類和迴歸方法的複雜度都依賴於輸入的數量,但爲了減少存儲量和計算時間,我們需要考慮降低問題的維度,丟棄不相關的特徵。同時,當數據可以用較少的維度表示而不丟失信息時,我們可以對數據繪圖,可視化分析它的結構和離羣點。
特徵降維是指採用一個低緯度的特徵來表示高緯度。特徵降維一般有兩類方法:特徵選擇(Feature Selection)和特徵提取(Feature Extraction)。
1.特徵選擇是從高緯度的特徵中選擇其中的一個子集來作爲新的特徵。最佳子集是以最少的維貢獻最大的正確率,丟棄不重要的維,使用合適的誤差函數進行,方法包括在向前選擇(Forword Selection)和在向後選擇(Backward Selection)。
2.特徵提取是指將高緯度的特徵經過某個函數映射至低緯度作爲新的特徵。常用的特徵抽取方法就是PCA(主成分分析)和LDA(線性判別分析) 。
降維的本質是學習一個映射函數f:X->Y,其中X是原始數據點,用n維向量表示。Y是數據點映射後的r維向量,其中n>r。通過這種映射方法,可以將高維空間中的數據點
主成分分析(Principal Component Analysis,PCA)是一種常用的線性降維數據分析方法,其實質是在能儘可能好的代表原特徵的情況下,將原特徵進行線性變換、映射至低緯度空間中。
PCA通過正交變換將一組可能存在相關性的變量轉換爲一組線性不相關的變量,轉換後的這組變量叫主成分,它可用於提取數據的主要特徵分量,常用於高維數據的降維。
該方法的重點在於:能否在各個變量之間相關關係研究基礎上,用較少的新變量代替原來較多的變量,而且這些較少新變量儘可能多地保留原來較多的變量所反映的信息,又能保證新指標之間保持相互無關(信息不重疊)。
圖形解釋:上圖將二維樣本的散點圖降爲一維表示,理想情況是這個1維新向量包含原始數據最多的信息,選擇那條紅色的線,類似於數據的橢圓長軸,該方向離散程度最大,方差最大,包含的信息量最多。短軸方向上的數據變化很少,對數據的解釋能力弱。
原理解釋:
下面引用xl890727的一張圖片簡單講解,因爲我數學實在好弱,惡補中。
PCA是多變量分析中最老的技術之一,它源於通信理論中的K-L變換。
詳細過程:
下面是主成分分析算法的過程,還是那句話:數學太差是硬傷,所以參考的百度文庫的,還請海涵,自己真的得加強數學。
總結PCA步驟如下圖所示:
推薦參考資料:
http://blog.codinglabs.org/articles/pca-tutorial.html - by: 張洋
特徵降維-PCA(Principal Component Analysis) - xl890727
PCA的原理及詳細步驟 - 百度文庫
二. Python中Sklearn的PCA擴展包
下面介紹Sklearn中PCA降維的方法,參考網址: http://scikit-learn.org/stable/modules/generated/sklearn.decomposition.PCA.html
導入方法:
- from sklearn.decomposition import PCA
- pca = PCA(n_components=2)
- 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]
- #載入數據集
- 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
- [[ 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)
三. 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()
輸出結果如下圖所示,感覺非常棒,這有利於做實驗對比。