<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          用 PCA 方法進行數(shù)據(jù)降維

          共 4507字,需瀏覽 10分鐘

           ·

          2020-08-04 12:42

          在進行數(shù)據(jù)分析時,我們往往會遇到多維數(shù)據(jù),多維數(shù)據(jù)在處理時由于維度較大計算起來非常麻煩,這時我們需要對數(shù)據(jù)進行降維。而在所有降維方法中,PCA是我們最常用的方法之一,其在使用時可以消除指標間的相互影響,同時也不用考慮數(shù)據(jù)的分布,而且降維效果非常明顯,所以PCA可以在絕大多數(shù)情況下使用。而本文就是用python來解釋一下如何用PCA方法進行降維。

          首先對PCA進行一下簡介。PCA全稱是principal components analysis,即主成分分析。假設對某一事物的研究設計p個指標,分別用X1、X2、......、Xp表示,這p個指標構成的p維隨機向量為X=(X1, X2, ..., Xp)’,設X的均值為μ,協(xié)方差矩陣為Σ。對X進行線性變換,可以形成新的綜合變量,用Y表示,也就是說新的變量可以由原來的變量線性表示,即滿足圖1中的關系。

          圖1. PCA原理

          由于這個線性變換是任意的,所以可以得到不同的Y。為了取得理想的效果,我們希望Yi=(ui)’X的方差盡可能大且Yi之間相互獨立。所以我們將線性變換約束在下面的條件之內(nèi):
          (1)(ui)’(ui)=1 (i=1, 2, 3, ..., p)
          (2)Yi與Yj相互無關(i不等于j,i, j=1, 2, 3, ..., p)
          (3)Y1是X1、X2、...、Xp的一切滿足條件(1)的線性組合中方差最大者,Y2是與Y1不相關的X1、X2、...、Xp所有線性組合中方差最大者,......,Yp是與Y1、Y2、...、Y(p-1)不相關的X1、X2、...、Xp的所有線性組合中方差最大者。
          基于以上三條原則確定的綜合變量Y1、Y2、...、Yp分別稱為原始變量的第一、第二...第p個主成分。各綜合變量在總方差中所占的比重依次遞減。在實際運用中,我們往往選取方差最大的幾個主成分,就達到了降維的目的。
          下面就用python代碼結合實際例子來說明一下PCA的具體用法。在這里我們要說明一下本次使用的數(shù)據(jù)集,該數(shù)據(jù)集是Iris Flower Dataset,即著名的鳶尾花數(shù)據(jù)集。該數(shù)據(jù)集只有5個維度(其中我們主要用到前4個維度),樣本量也只有150個,整個數(shù)據(jù)集比較輕便,非常適合做數(shù)據(jù)展示。
          首先導入需要的庫。
          import?numpy?as?np?
          import?pandas?as?pd?
          import?seaborn?as?sns
          import?matplotlib.pyplot?as?plt
          from?sklearn.decomposition?import?PCA

          接下來讀取相關數(shù)據(jù)集,這個數(shù)據(jù)集位于seaborn庫當中。前8行數(shù)據(jù)如圖2所示。

          data?=?sns.load_dataset('iris')
          data.head(8)

          圖2. 數(shù)據(jù)集樣例

          然后對數(shù)據(jù)做一個簡單的處理,看一下各個維度之間的相關關系。所得結果如圖3和圖4所示。

          values?=?data.iloc[:,?:4]?#讀取前4列數(shù)據(jù)
          correlation?=?values.corr()?#列與列之間的相關系數(shù)
          fig,?ax?=?plt.subplots(figsize=(12,?10))
          sns.heatmap(correlation,?annot=True,?annot_kws={'size':16},?cmap='Reds',?square=True,?ax=ax)?#熱力圖
          sns.pairplot(data,?hue='species')?#散點關系圖

          圖3. 各維度之間的相關系數(shù)熱力圖

          圖4. 各維度之間的散點關系圖

          從圖中可以大致看出,sepal_length和petal_length與petal_width都有較強的相關性,而petal_length和petal_width的相關性最強,達到0.96。下面我們來用PCA具體來分析一下該數(shù)據(jù)集,首先先看看該數(shù)據(jù)在選取4個主成分下的情況,這時候其主成分的數(shù)量和原數(shù)據(jù)的維度數(shù)相等。其結果如圖5所示。

          pca?=?PCA(n_components=4)?#選取4個主成分
          pc?=?pca.fit_transform(values)?#對原數(shù)據(jù)進行pca處理
          print("explained?variance?ratio:?%s"?%?pca.explained_variance_ratio_)?#輸出各個主成分所占的比例
          plt.plot(range(1,?5),?np.cumsum(pca.explained_variance_ratio_))?#繪制主成分累積比例圖
          plt.scatter(range(1,5),np.cumsum(pca.explained_variance_ratio_))
          plt.xlim(0,?5)
          plt.ylim(0.9,?1.02)
          plt.xlabel("number?of?components")
          plt.ylabel("cumulative?explained?variance");

          圖5. 各主成分累加結果

          我們可以看到pca.explained_variance_ratio_的結果是[0.92461872 0.05306648 0.01710261 0.00521218],而圖5中也顯示前兩個主成分之和就已經(jīng)接近所有主成分的98%,所以在只考慮前兩個主成分的情況下,我們就能夠?qū)?shù)據(jù)的損失控制在很小的范圍內(nèi)。這里我們就只用前兩個主成分來做分析。接下來我們就只用前兩個主成分來分析原數(shù)據(jù),將兩個主成分的數(shù)據(jù)轉(zhuǎn)換成dataframe格式,然后再加上一列原數(shù)據(jù)中species的數(shù)據(jù),代碼如下,結果如圖6所示。

          pca1?=?PCA(n_components=2)?#選取2個主成分
          pc1?=?pca1.fit_transform(values)?
          pc1_df?=?pd.DataFrame(pc1,?columns=['pc_1',?'pc_2'])
          pc1_df['species']?=?data['species']?#加上一列species
          pc1_df.head(8)

          圖6. 只有兩個主成分的數(shù)據(jù)樣例

          接下來我們來看一下這兩個主成分的組成。

          print(pca1.components_)

          結果如下。

          [[?0.36138659?-0.08452251??0.85667061??0.3582892?]
          ?[?0.65658877??0.73016143?-0.17337266?-0.07548102]]

          用這個結果來驗證一下前面的數(shù)據(jù)。按照圖1中的原理來計算,pca1.components_第一行的數(shù)據(jù)和values第一行數(shù)據(jù)對應項相乘的和,應該等于pc1_dfpc_1列第一個數(shù)據(jù)-2.684126,即圖6中第一行第一列數(shù)據(jù)。即有下列代碼。

          print(np.dot(pca1.components_[0],?values.iloc[0]))

          按照上式計算,結果是2.8182395066394683。很多人看到這里,認為是不是算錯了,其實我們在計算方法上都沒有錯,只是在這里有一個隱含條件沒有滿足,就是sklearn在進行PCA計算時,數(shù)據(jù)要進行“中心化”,即每個數(shù)據(jù)減去這組數(shù)據(jù)的平均值,這樣做主要是為了后續(xù)方便計算。所以我們要把上述代碼改為下面這樣。

          print(np.dot(pca1.components_[0],?values.iloc[0]-values.mean(axis=0)))

          其得到的結果是-2.684125625969536,這就和前面的-2.684126對應起來了(這里排除小數(shù)點精度問題)。接下來就是用我們降維后的數(shù)據(jù)來作圖。我們將原先的數(shù)據(jù)從4維降為2維,這正好方便繪制二維圖,代碼如下。結果如圖7所示。

          setosa?=?pc1_df[pc1_df['species']=='setosa']?#找出setosa對應的主成分數(shù)據(jù)
          virginica?=?pc1_df[pc1_df['species']=='virginica']
          versicolor?=?pc1_df[pc1_df['species']=='versicolor']
          fig,?ax?=?plt.subplots(figsize=(10,?8))
          plt.scatter(setosa['pc_1'],?setosa['pc_2'],?alpha=0.7,?color?=?'red',?label='Setosa')?#繪制Setosa的散點圖
          plt.scatter(virginica['pc_1'],?virginica['pc_2'],?alpha=0.7,?color?=?'green',?label='Virginica')
          plt.scatter(versicolor['pc_1'],?versicolor['pc_2'],?alpha=0.7,?color?=?'blue',??label='Versicolor')
          plt.legend(loc='best')
          plt.xlabel('principal?component?1')
          plt.ylabel('principal?component?2')

          圖7 . 降維后的散點圖

          主成分分析這種方法雖然簡單易用,但其也有自身的缺點,比如對降維最終得到數(shù)目,不能很好地估計,同時PCA對于維度之間非線性的依賴關系不能得到很好的結果。此外本例中筆者沒有對原數(shù)據(jù)進行標準化,因為標準化可能會損失一定信息,這個問題業(yè)界也爭論了很長時間,到底是否對數(shù)據(jù)進行標準化需要根據(jù)實際情況來判斷,因為本例中各維度之間的數(shù)據(jù)差異不大,所以筆者并未進行標準化。所以針對PCA的使用,大家還是要根據(jù)數(shù)據(jù)的要求來進行判斷。


          作者簡介:Mort,數(shù)據(jù)分析愛好者,擅長數(shù)據(jù)可視化,比較關注機器學習領域,希望能和業(yè)內(nèi)朋友多學習交流。

          贊 賞 作 者



          Python中文社區(qū)作為一個去中心化的全球技術社區(qū),以成為全球20萬Python中文開發(fā)者的精神部落為愿景,目前覆蓋各大主流媒體和協(xié)作平臺,與阿里、騰訊、百度、微軟、亞馬遜、開源中國、CSDN等業(yè)界知名公司和技術社區(qū)建立了廣泛的聯(lián)系,擁有來自十多個國家和地區(qū)數(shù)萬名登記會員,會員來自以工信部、清華大學、北京大學、北京郵電大學、中國人民銀行、中科院、中金、華為、BAT、谷歌、微軟等為代表的政府機關、科研單位、金融機構以及海內(nèi)外知名公司,全平臺近20萬開發(fā)者關注。


          推薦閱讀:
          用 Python 進行系統(tǒng)聚類分析
          用 Python 對數(shù)據(jù)進行相關性分析
          如何在 matplotlib 中加注釋和內(nèi)嵌圖
          如何用一行代碼讓 gevent 爬蟲提速 100%


          ▼點擊成為社區(qū)會員? ?喜歡就點個在看吧

          瀏覽 69
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  爱情岛论坛www成人网站 | 国产无码免费看 | 豆花在线精品视频 | 欧美成人精品在线 | 2024国产中文一区二区在线播放 |