天天看點

推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

來自于: AI蝸牛車團隊(作者:Miracle8070)

公衆号: AI蝸牛車

原文連結:

【白話機器學習】算法理論+實戰之PCA降維​mp.weixin.qq.com

推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

1. 寫在前面

如果想從事資料挖掘或者機器學習的工作,掌握常用的機器學習算法是非常有必要的,在這簡單的先捋一捋, 常見的機器學習算法:

  • 監督學習算法:邏輯回歸,線性回歸,決策樹,樸素貝葉斯,K近鄰,支援向量機,內建算法Adaboost等
  • 無監督算法:聚類, 降維 ,關聯規則, PageRank等

為了詳細的了解這些原理,曾經看過西瓜書,統計學習方法,機器學習實戰等書,也聽過一些機器學習的課程,但總感覺話語裡比較深奧,讀起來沒有耐心,并且

理論到處有,而實戰最重要

, 是以在這裡想用最淺顯易懂的語言寫一個

白話機器學習算法理論+實戰系列

個人認為,了解算法背後的idea和使用,要比看懂它的數學推導更加重要。idea會讓你有一個直覺的感受,進而明白算法的合理性,數學推導隻是将這種合理性用更加嚴謹的語言表達出來而已,打個比方,一個梨很甜,用數學的語言可以表述為糖分含量90%,但隻有親自咬一口,你才能真正感覺到這個梨有多甜,也才能真正了解數學上的90%的糖分究竟是怎麼樣的。如果這些機器學習算法是個梨,本文的首要目的就是先帶領大家咬一口。 另外還有下面幾個目的:

  • 檢驗自己對算法的了解程度,對算法理論做一個小總結
  • 能開心的學習這些算法的核心思想, 找到學習這些算法的興趣,為深入的學習這些算法打一個基礎。
  • 每一節課的理論都會放一個實戰案例,能夠真正的做到學以緻用,既可以鍛煉程式設計能力,又可以加深算法理論的把握程度。
  • 也想把之前所有的筆記和參考放在一塊,友善以後檢視時的友善。
學習算法的過程,獲得的不應該隻有算法理論,還應該有樂趣和解決實際問題的能力!

今天是白話機器學習算法理論+實戰的第十篇之PCA降維,也是這個系列的最後一篇,因為凡事都要十全十美嘛, 十這個數字其實挺好的,并且加上這篇已經基本上把上面常見的機器學習算法都整理完畢了。PCA(Principal Component Analysis)降維是一種無監督的方式,常用在資料的降維方面,也就是資料的預處理方面,

并不是作為最終的算法模型使用,隻是相當于一種幫助算法更好更快做出決策的輔助手段

。因為我們知道,如果給我們的資料特征次元太高,首先計算很麻煩,其次特征之間可能存在相關的情況,進而增加了問題的複雜程度,分析起來也不友善。這時候我們就會想是不是去掉一些特征就好了呢? 但是這個特征也不是憑自己的意願去掉的,因為盲目減少資料的特征會損失掉資料包含的關鍵資訊,容易産生錯誤的結論,對分析不利。

是以我們想找到一個合理的方式,

既可以減少我們需要分析的名額,而且盡可能多的保持原來資料的資訊

,PCA就是這個合理的方式之一。是以今天我們學習PCA降維,看看到底PCA再完成一個什麼樣的任務,是如何完成這個任務的?

首先,我們先從生活的場景出發感受一下降維的身影,然後我們會從二維資料的降維例子看看降維在做什麼事情,從宏觀的層面介紹PCA在完成什麼樣的任務,然後我會從數學的微觀層面上講解PCA是如何完成降維任務的,最後我們會用純Python實作PCA算法完成鸢尾花資料集的分類,接着會調用sklearn的pca工具來做一個人臉識别的降維分析,看看PCA到底在實戰任務中是怎樣的一個存在。 總之有了這個手段,你的模型分析起資料來會更加的得心應手。 最後也要提醒一句,雖然這次也是白話系列,但是這次會有一些數學的東西在裡面,畢竟沒有數學,PCA再怎麼描述也是靈魂出竅般的存在,但保證不會太難,并且有我的大白話在裡面,輕輕松松感受數學的強大。哈哈,我們開始吧! 對了,PCA也叫主成分分析,這倆是一回事!

大綱如下:
  • 資料降維? 其實就在我們身邊!
  • PCA到底在做什麼? (宏觀的角度把握)
  • PCA是如何做到降維的? (微觀角度了解PCA的數學原理)
  • PCA程式設計實戰(鸢尾花資料集+人臉識别的降維分析)

OK, let's go!

2. 資料降維? 其實就在我們身邊!

資料降維的身影,我們身邊也會有很多,我們常常說

算法來源于生活

,隻不過我們在人生路上走的太快,沒有去留意路邊的風景罷了。 沒事,隻要你喜歡聽聽别人的故事,我替你留意了一些,哈哈。下面我們就從一個故事場景中感受降維:

★ 我們走在一個城市中,總是會發現城市中的每一條道路會有一些奇怪的名字,什麼北京路,京哈路什麼各種,我就拿我所在的城市來講,道路起名字還算規範,因為我們這東北是渤海,南邊是黃河,是以城市中橫向的路統稱為黃河,然後從最南邊數,往北依次是黃河一路,黃河二路,黃河三路...., 縱向的路統稱為渤海,從東邊往西依次是渤海一路,渤海二路,渤海三路...,和我們坐标系的X軸和Y軸是非常像的。 可能剛到某個城市的時候你會有個疑問,為啥會給路起名字呢? 有的甚至起一些花裡胡哨的名字,聽都沒聽過。 這是因為,給街道起名字之後,城市中的位置資訊都可以通過街道名唯一确定了(比如黃河五路和渤海三路交叉口),這樣當你想找某個地方的時候,才更容易找到,畢竟給路起名之後,是大家公認的标準,當大家都說黃河五路和渤海三路交叉口的時候,保證說的是同一個位置,這些路就類似于我們說的坐标系。而城市中的每一個地方就類似于坐标系中的點,被坐标系唯一辨別。 那麼有個問題來了,我想讓你把黃河五路渤海三路交叉口這樣用兩個數字标注的位置資訊,轉換為隻有一個數字辨別的位置描述,你怎麼辦? 你可能沒法一下子想到。 但是如果有一條鐵路通過了城市,而城市中所有重要的建築都在鐵路邊,那麼就可以根據距離鐵路的起點多遠來定義每一個點的位置。那樣是不是這個問題就解決了?比如黃河五路渤海三路交叉口距離鐵路挺近的,在起點旁邊。 其實, 這就是一種降維了,把原來的需要兩個次元标注的資訊,現在用一條鐵路就可以搞定

當然,這樣的定位不如用倆個次元來的準,有的地點離鐵路遠,但是遠多少,在新的表示中就沒有得到展示了。

這說明資料降維不是無損的,會造成資訊的部分丢失。

那麼,降維有什麼用呢? 隻是為了造成資訊的部分丢失?還是回到上面的例子,資料降維的第一個用途是

資料壓縮

,如果你隻能在一張小便簽向一位你新認識的朋友寫下你家的位址,便簽上寫不下是黃河××路渤海××路,那你可寫鐵路第五。 而資料降維還可以去做

資料可視化或特征提取

,比如你要在城市中開一家店,你先看看哪裡人群更加密集,你可以通過資料降維,做出哪些地方周圍的點多,進而人流更密。 資料降維的第三個用途是

異常值檢測和聚類

,例如你通過資料降維,發現城市中的大部分人家都住在兩個火車站附近,但是有一倆個家卻不在這裡,這樣你就發現了城市裡那些特立獨行的人,接着你發現倆個火車站附件的人家,一家都姓張,一家都姓李,這樣,你就将城市的人家通過資料降維,分成了倆類。

現在對降維有了一個直覺的認識了吧, 那麼這個和我們的主角PCA有什麼關系呢? 主成分分析方法是一種資料降維的方式,剛才上面我們提到,隻要資料壓縮,必定會損失一些資訊,而PCA做的就是盡可能的去找到一些主要的關鍵特征去區分開資料,去除掉一些對區分資料不大的那些特征,這樣,既可以做到降維,也可以盡可能多的保留原來資料的資訊。在上面的例子中,我們找到的鐵路線就是我們的主成分,我們将城市的所有人家按照鐵路開來的順序,依次排序,進而得到了一個數字表示的距離,至于位置資訊的損失,肯定是損失一些,但至少能表示。

下面我們再詳細看看PCA究竟在做什麼?

3. PCA到底在做什麼? (宏觀的角度把握)

上面,我們已經通過生活的場景感受到了降維的身影,那麼也知道了主成分分析方法是降維的一種方式,它能夠盡可能多的保留資料的資訊而完成減少資料的次元,上面我還說,那條鐵路就是我們找出的主成分,但是在資料中主成分到底是什麼樣子呢?我們先通過一個例子來感受一下: 下表是某些學生的國文、數學、實體、化學成績統計:

推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

首先,假設這些科目成績不相關,也就是說某一科目考多少分與其他科目沒有關系。現在我想讓你用盡量少的科目成績來區分這三個同學學習等級的話,我想你一定不會選國文成績作為區分的标準(因為國文分數都一樣啊,沒有差別啊), 你一眼就可以看出來數學、實體、化學可以作為這組資料的主成分(很顯然,數學作為第一主成分,因為數學成績拉的最大),很大程度上我們光用數學成績就可以區分開這三個同學吧。這和我們平時考試一樣,為啥父母都喜歡說好好學數學,因為數學才能真正的拉開分決定誰考第一名。 這不,單單一門數學成績就可以完成分類任務了,不用考慮其他三科,這不就降維了啊。

那你怎麼就确定數學就是主成分的呢? 你說,因為數學拉開了分啊, 你這個拉開了分,其實就是說的這個分數在同學和同學之間的差距可能會比較大,這個正是我們機率論上常常講的

方差

。方差越大,所獲得的的資訊量就會越多。

而PCA找主成分的時候其實在尋找K個盡可能的把樣本區分開方向,即方差盡可能大的方向作為主成分,這樣就可以做到在保留盡可能多的資料資訊的情況下把資料的次元降到了K維(原來肯定是比K維大)

好了,那麼上圖比較簡單,你一下子就能看出主成分了,我們再看一組資料分數:

推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

你還能一下子找出哪一科可以作為主成分嗎? 你可能又會說,這還不簡單,這還不簡單? 你不是說了找方差極可能大的嗎?我算一算每一科的方差,然後我看看哪幾個方差最大不就行了? 哈哈,這個地方注意不要了解錯了,尋找主成分并不一定是在這原有的這幾科上去找某幾科方差最大的科目,而更像是這些科目的一種均衡,這啥意思? 就比如,我們的每個科目都代表一個方向,那麼每一個學生在空間中根據每門分數不同就成了一個個的點,我們想要找的主成分,不一定是這原來的某個方向或者某些方向,我們找的方向,是這每個學生投影上來之後能夠離得盡可能的遠,也就是方差盡可能大,這樣有利于我們的區分。

★ 還是拿吳恩達老師的這個圖來看一下:
推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

我們看二維裡面的這幾個資料點, 如果我們找那條橙色的線劃分這幾個樣本的話,你會發現每個點在橙色線上的投影離得距離很大,這樣即使用這一條線劃分資料的話,依然很容易劃分出來。但是如果找那條洋紅色的線劃分資料的話,會發現每個點線上上的投影離得很近,不太好區分開。 是以我們更傾向于選擇橙色的線作為主成分。

是以,對于上面那個多元的那些分數,我們更傾向于找一個下面這樣的軸來分開資料(換一個角度思考問題):

推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

嗯嗯,在宏觀上了解PCA的話,上面就是PCA做的事情 --- 尋找主成分,盡可能的去把資料分開而又不太損失原來的資訊。

具體的說,就是PCA在降維的時候, 是把資料看成空間中的點,然後嘗試去尋找幾個方向(上面橙色的和下面的PC1PC2), 把這些點進行投影,投影之後讓這些點離得盡可能的遠。 這樣這幾個方向就是主成分, 空間中的樣本點就可以通過這幾個新的方向進行描述了。 但是找的這幾個方向也是有要求的,就是互不幹擾,沒有線性關系,就像x軸和y軸那樣,這樣才能更好的去描述這些資料。主成分之間沒有備援。

是以,主成分的标準兩個條件,一是互不相關,二是用來描述資料的時候,方差盡可能大。

那麼PCA是怎麼做到的呢? 這個就得從數學的角度進行了解了。

4. PCA是如何做到降維的? (微觀角度了解PCA的數學原理)

談到數學這一塊,就得嚴謹一些了,我們上面知道了PCA就是去找主成分,而主成分的标準兩個條件,一是互不相關(注意不相關可不等于互相獨立,這裡隻保證沒有線性關系);二是用來描述資料的時候,方差盡可能大,也就是資料投影過去之後,離得盡可能遠。

接下來,其實就是弄明白PCA是怎麼去衡量這兩個條件的,第一個條件的話,互不相關,可以找一組主成分使得彼此之間的協方差為0(後面會提到), 那麼第二個條件,資料投影過去之後,離得盡可能遠? 這個有點麻煩,是以看第二個之前,我們先來看看什麼是投影,這個怎麼衡量?

這個就得先從向量的表示和基變換說起了:

4.1 向量的表示及基變換

要想看投影,我們先來看看向量的内積運算是怎麼回事來?

内積:
推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維
解釋:
推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

那麼,如果向量B的模為1, 那麼

A與B的内積值等于A向B所在的直線進行投影的矢量長度

。 看下面的圖檔:

推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

是以,兩個向量進行内積之後,相當于做了一個投影的操作。

那麼,我們看看向量在空間中是如何表示的:

★ 我們現在空間中標明一組基,那麼空間中的向量都可以表示為基的線性組合,這是什麼意思呢? 比如我們下面确定了一個坐标系,那麼下面這個紅色的向量,坐标是(3,2),就是因為這個坐标在x軸上的投影是3, 在y軸上的投影是2,實際上,這個向量可以表示成線性組合:
推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維
推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

而上面的(1,0)和(0,1)就叫做二維空間中的一組基。并且要求基是機關向量且要垂直,不相關,如果不知道講基幹啥用,那麼還記得主成分的第一個條件嗎?也是互不相關,難道隻是巧合? NO,隻不過這裡得先做一些鋪墊,有點想要呼之欲出的感覺。

我們學這個基到底幹啥用呢? 先别慌,有了基之後,我們就可以做基變換了,啥意思? 就是說,上圖中我們知道了紅色向量的坐标是(3,2),但這樣說不準确,正确的應該是先有了坐标系,在我這個x軸和y軸的坐标系下,我的紅色向量坐标(3,2)。 那麼,我要是換一組坐标系呢?看下圖,我問你,在藍色的坐标系中,紅色向量的坐标是什麼? 很顯然,不是(3,2)了吧,是以以後考慮問題的時候,要考慮的全面一些,萬事成立都是基于某些條件的,哈哈,沒想到基變換中還能學到人生哲理。

推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

那麼,換了這個坐标系之後,我們原來的(3,2)到底變成了多少呢? 我們依然是需要去找新坐标系中的基,看上面的藍色箭頭,就會發現這組基可以是

推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

,找到基之後怎麼做變換呢?

變換 : 資料與第一個基做内積運算,結果作為第一個新的坐标分量,然後與第二個基做内積運算,結果作為第二個新坐标的分量。 資料(3,2)映射到新基中的坐标:
推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

★ 是以,在藍色的坐标系中,紅色的向量坐标為

推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

那麼,明白了上面的變換之後,我們就可以得到基變換的更為一般的表達方式:

推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

兩個矩陣相乘的意義是将右邊矩陣中的每一列列向量變換到左邊矩陣中的每一行行向量為基所表示的空間中去。其中

推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

是列向量,

推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

是行向量,一個基。了解起來就是左邊的矩陣是一組基,右邊的矩陣是樣本集。這兩個矩陣相乘,就是樣本集在一個由一組新的基定義的空間中的表示。

這個基和我們的PCA有什麼關系呢? 現在就可以說一說了:

PCA做的就是尋找到一組基(主成分),這組基互不相關,并且使得所有的資料變換為這組基上的坐标表示之後,方內插補點盡可能的大。

我們知道一組基是互不相關的,但是PCA在具體選的時候,應該怎麼選呢? PCA肯定不是一次就把所有方向都選出來的, PCA其實是這麼做的,先選擇一個方向基,讓資料投影到這個基上的方差最大,然後再從和這個方向基正交的方向上選擇第二個方向基使得資料投影到這個基上的方差最大,然後再從與這兩個方向基都正交的方向上選擇第三個方向基,這樣依次選擇下去,就可以保證方向基之間是互相正交的,也可以保證方差最大了。 那麼談到方向基互相正交,就避不開數學上的另一個概念了: 協方差。先來看看這個概念:

4.2 協方差

如果說方差表示的一個變量之間資料之間的波動程度,那麼協方差表示的兩個變量之間的相關程度, 兩個變量X和Y的協方差可以表示成:

推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

如果我們把X和Y的均值變成0的時候(往往我們會先把資料做歸一化處理),這時候,協方差就變成了

推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

是以,如果想讓兩個基沒有相關性,就要保證他們的協方差為0.

4.3 PCA的優化目标

談完了基變換和協方差,下面我們就很容易把PCA的那兩個條件給用數學的語言表達一下了:

★ 将一組N為向量降維K維(0<K<N), 目标是選擇K個機關正交基,使得原始資料變換到這組基上後,各字段兩兩間協方差為0,字段的方差則盡可能大

那麼怎麼得到兩個基的協方差資訊呢? 我們需要一個協方差矩陣的東西。

我們假設我們的資料集X是2*m的一個矩陣,2表示兩維的特征,m表示m個樣本,那麼,我進行X内積操作看看得到了啥:

推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

發現了嗎? 得到的後面的這個矩陣就是特征的協方差矩陣了,這個矩陣主對角線上的兩個元素正好是特征自身的方差,而副對角線上的兩個元素正好兩個特征之間的協方差啊,是不是很神奇! 這樣一下子,特征自己的方差和特征之間的協方差直接就全了。并且這個協方差矩陣是個對稱矩陣喲!

那下面的任務就明确了,PCA是幹啥來,那兩個标準,一個就是需要特征之間的協方差為0,怎麼做呢? 就是讓

協方差矩陣相似對角化

, 另一個就是盡量的使得方差最大,就是

協方差矩陣對角化之後,把對角線上的元素從大到小排列

★ 協方差矩陣對角化:即通過變換讓協方差矩陣變成除對角線外的其它元素為0, 并且對角線上的元素按從大到小的順序排列
推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

那麼我們怎麼把這個協方差相似對角化呢? 這就涉及到線代的知識了,我們首先有這麼個定理:

★ 實對稱矩陣: 一個n行m列的實對稱矩陣一定可以找到n個機關的正交特征向量
推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維
使得
推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

是協方差矩陣C的n個特征值。

這樣,

我們隻要把特征值從大到小,對應的特征向量從上到下排列,則用前K行組成的矩陣乘以原始矩陣X, 就得到了我們需要的降維後的資料矩陣Y

。 也會是PCA之後的方式,而前K個特征向量組成的就是新空間下的一組基,也是PCA找的K個主成分。講到這裡你可能會有點懵,為啥呢? 為啥協方差矩陣的特征向量把協方差矩陣相似對角化,并把特征值從大到小排列之後,對應的特征向量就是那組基呢?這裡不太明白了,對吧。

那麼好,我們帶着這個疑問往下走一步,就是假設這個對應的特征向量真是那組基,那麼我們用這個特征向量乘以原始矩陣X就會得到降維後的資料矩陣Y。即

推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

那我們來看看,這個降維後的資料矩陣Y自己做内積然後乘以1/m是什麼東西,即

推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

這樣發現什麼了? 竟然這個降維後的資料矩陣Y與自己内積得到的是新的次元下的協方差矩陣,而這個協方差矩陣正好是之前X的協方差矩陣C相似對角化後取得前K個特征值組成的對角陣。

這就說明,PCA找到的主成分之間互不相關,且主成分本身的方差是從N維中選的前K個最大的值。 正好符合我們之前的目标。是以這個特征向量作為新的基對X進行變換成Y的過程是完全合理的。

這就是PCA在數學的角度是如何找到那K個主成分的詳細過程了。

先梳理一下這個過程,然後我們根據一個例子感受一下這個過程,遇到新的資料集X之後(N維),我們想降到K維,PCA是這樣做的

  • 首先,應該先把X每一維進行歸一化,把均值變成0
  • 然後,計算協方差矩陣C, 即
    推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維
  • 然後,計算C的特征值和特征向量,把特征值從大到小排列,對應的特征向量從上往下排列
  • 然後,将協方差矩陣相似對角化
  • 然後,去特征向量的前k個,得到K個基
  • 最後,用這K個基與X相乘,得到降維後的K維矩陣Y

下面我們看一個例子,感受一下這個過程:

  1. 輸入資料X: 2個特征,5個訓練樣本, 并去均值
    推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維
  2. 計算協方差矩陣C, 即
    推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維
推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

  1. 計算特征值和特征向量 特征值:
    推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維
    特征向量:
推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

特征向量機關化:

推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維
  1. 相似對角化
推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

  1. 降到1維,那麼就取
    推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維
    作為基,得最後結果
推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

到這裡,關于PCA的數學原理就整理完了,你消化了嗎? 沒消化的話,下面的代碼部分仍然可以幫助你了解這個過程,下面我們就用鸢尾花資料集,來手寫PCA對其降維。

5. PCA程式設計實戰

關于PCA實戰,我們已經知道了PCA一般是用于資料預處理,對資料進行降維,對後面的模型更好的工作起很強的輔助作用。 下面我們先從一個簡單的資料集鸢尾花,來看看如何将上面的數學過程寫成Python代碼的方式,并對鸢尾花資料集降維看看最後的效果。

5.1 鸢尾花資料集的降維分析

首先,我想用鸢尾花資料集(因為簡單一些,好了解)按照上面的PCA的過程,具體實作一下,看看降維到底有個什麼效果? 那麼我們開始吧:

★ 回憶一遍上面的過程:
  1. 得到資料,把資料歸一化
  2. 然後得到協方差矩陣C
  3. 求協方差矩陣的特征值和特征向量,并将特征值排序
  4. 取前K個特征向量作為基,最後與X相乘得到降維之後的資料矩陣Y

下面就來模拟一遍

  1. 先導入包(鸢尾花資料集在sklearn.datasets裡面)

    import numpy as np

    import pandas as pd

    import matplotlib.pyplot as plt

    from sklearn.datasets import load_iris

    from sklearn.preprocessing import StandardScaler

  2. 導入資料,并把它進行歸一化

    iris = load_iris()

    X = iris.data # Xshape(150, 4)

    # X的歸一化

    X_norm = StandardScaler().fit_transform(X)

    X_norm.mean(axis=0) # 這樣每一維均值為0了

  3. 下面就是用PCA進行降維的過程

    # 求特征值和特征向量

    ew, ev = np.linalg.eig(np.cov(X_norm.T)) # np.cov直接求協方差矩陣,每一行代表一個特征,每一輪代表樣本

    # 特征向量特征值的排序

    ew_oreder = np.argsort(ew)[::-1]

    ew_sort = ew[ew_oreder]

    ev_sort = ev[:, ew_oreder] # ev的每一列代表一個特征向量

    ev_sort.shape # (4,4)

    # 我們指定降成2維, 然後取出排序後的特征向量的前兩列就是基

    K = 2

    V = ev_sort[:, :2] # 4*2

    # 最後,我們得到降維後的資料

    X_new = X_norm.dot(V) # shape (150,2)

  4. 下面我們可視化一下X_new, 看看降維之後是什麼樣子:

    colors = ['red', 'black', 'orange']

    plt.figure()

    for i in [0, 1, 2]:

    plt.scatter(X_new[iris.target==i, 0],

    X_new[iris.target==i, 1],

    alpha=.7,

    c=colors[i],

    label=iris.target_names[i]

    )

    plt.legend()

    plt.title('PCa of IRIS dataset')

    plt.xlabel('PC_0')

    plt.ylabel('PC_1')

    plt.show()

    結果如下:

推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

從結果中,我們可以看到,PCA降維之後,首先是特征變成了2列,變得能夠可視化出來,然後發現鸢尾花資料的每一類其實是比較容易區分開的,是以後面用一些基礎的機器學習算法比如決策樹,KNN等這些都可以得到比較好的效果,這樣不僅可是使得計算簡單,也為我們後面選擇算法提供一個依據。

上面編寫這個過程是為了更好的消化數學公式,其實sklearn中已經幫我們完成了這個工具, 我們直接可以用,并且完成降維隻需一句話就可搞定,是不是簡單多了。下面我們也可以試試:

from sklearn.decomposition import PCA

# 然後使用
pca = PCA(n_compoents=2)
X_new = pca.fit_transform(X_norm)

"""檢視PCA的一些屬性"""
print(pca.explained_variance_)    # 屬性可以檢視降維後的每個特征向量上所帶的資訊量大小(可解釋性方差的大小)
print(pca.explained_variance_ratio_)  # 檢視降維後的每個新特征的資訊量占原始資料總資訊量的百分比
print(pca.explained_variance_ratio_.sum())    # 降維後資訊保留量

## 結果:
[4.22824171 0.24267075]   # 可以發現,降維後特征的方差
[0.92461872 0.05306648]  # 降維後的特征帶的原有資料的資訊量的比例
0.977685206318795      # 降維後的資訊保留(損失了3%, 去掉了一半特征,還算可以)
           

這樣就實作了X_norm的降維操作,關于sklearn裡面的PCA,詳細細節可以去看參考文檔,這裡再簡單的說一下PCA的幾個小細節:

  • pca的屬性 我們可以通過pca.explained_variance_ 屬性, 檢視降維之後每隔特征向量所帶的資訊量大小; pca.explained_variance_ratio_檢視降維後的每個新特征的資訊量占原始資料總資訊量的百分比; pca.explained_variance_ratio_.sum(),降維後資訊保留量
  • 參數n_coments怎麼選擇? 這個參數可以直接指定我們要降到幾維(一個整數,大于0小于資料總維數),當然這一個可能對于陌生的資料我們不太确定一下子是幾維,可以畫個圖探索一下:
推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

n_coments = 'mle',這是自選超參數, 就是計算機會根據一些計算,盡量保持多的資訊下,選擇最後降到幾維,但是次元很大的話這個計算量很大的 n_coments = [0,1]之間的浮點數,但是這時候必須指定另一個超參數: svd_solver='full' 。這個就是直接希望PCA保留多少的資訊量,

這種方法比較好,直接自己指定保留多少資訊

,不用畫圖探索,可以先上來保證80%的資訊量,看看會保留幾維特征,然後慢慢的加。

5.2 人臉資料集實戰

好了,明白了sklearn中的PCA如何使用,下面我們來玩一個人臉識别資料集的降維,再來看一下降維的一些細節吧,這次用的資料集是sklearn的fetch_lfw_people:

# 導入包
from sklearn.datasets import fetch_lfw_people
from sklearn.decomposition import PCA

import matplotlib.pyplot as plt
import numpy as np

# 導入資料,并且探索一下子
faces = fetch_lfw_people(min_faces_per_person=60)
faces.images.shape   # (1348, 64, 47)  1348張圖檔,每張64*47
faces.data.shape    # (1348, 2914)  這是把上面的後兩維進行了合并,共2914個特征(像素點)

# 下面我們先可視化一下子這些圖檔,看看長什麼樣
fig, axes = plt.subplots(3, 8, figsize=(8,4), subplot_kw={"xticks":[], "yticks":[]})

for i, ax in enumerate(axes.flat):
    ax.imshow(faces.images[i, :, :], cmap='gray')
           
推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

下面我們使用PCA進行降維處理

pca = PCA(150).fit(faces.data)  # 降到150維
V = pca.components_   # 這就是那組基
V.shape           #(150,2914) 每一行是一個基,用這個乘上我們樣本X,就會得到降維後的結果矩陣
           

上面的components_屬性就是提取的150維之後的那組基,也就是數學公式裡面的特征向量。 我們可以可視化一下這個,親身感受一下這組基是什麼樣子的(也就是PCA從原始資料上提取了怎麼樣的主成分特征)

# 下面可視化一下V
fig, axes = plt.subplots(3, 8, figsize=(8,4), subplot_kw={"xticks":[], "yticks":[]})
for i, ax in enumerate(axes.flat):
    ax.imshow(V[i,:].reshape(62, 47), cmap='gray')
           

結果如下:

推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

這個怎麼跟鬼一樣?不要害怕, 其實這就是PCA提取的主成分特征,雖然可能看不出模樣,但是你會發現,PCA提取特征的時候,會更加關注五官特征,眼睛輪廓,嘴,鼻子等還是比較明顯的,這也挺符合我們現在的人臉識别原理,我們識别人臉,不正是主要看五官的差別嗎? 是以PCA在這方面提取的特征還算是合理的。

那麼你可能會想了,PCA的這個降維過程能不能再回去啊?其實還真有個這樣的接口函數pca.inverse_transform, 這個可以實作降維的逆轉,但是真的完全逆轉嗎? 我們可以做一個實驗:

# 我們先得到降維後的資料
X_dr = pca.transform(faces.data)    # 這個是1358,150的資料

#然後我們調用接口逆轉
X_inverse = pca.inverse_transform(X_dr)
X_inverse.shape    # (1348, 2914) 看這個形狀還真回去了啊
           

我們看這個形狀,還真是回去了啊,但是真回去了嗎?

# 下面對比一下pca的逆轉和原來圖檔的差別
fig, ax = plt.subplots(2, 10, figsize=(10,2.5), subplot_kw={"xticks":[], "yticks":[]})
for i in range(10):
    ax[0,i].imshow(faces.images[i,:, :], cmap='binary_r')
    ax[1,i].imshow(X_inverse[i].reshape(62, 47), cmap="binary_r")   # 降維不是完全可逆的
           
推導pca的降維損失_【白話機器學習】算法理論+實戰之PCA降維

我們可以發現,逆轉回去的圖檔是模糊的,雖然能夠基本認出來。

★ Inverse_transform的功能: 是基于X_dr的資料進行升維,将資料重新映射到原資料所在的空間中,而并非恢複所有的資料。 但我們也看出,降維到150以後的資料,的確定留了原資料的大部分資訊,是以圖像看起來,才會和原資料高度相似,隻是稍微模糊罷了。

是以說

降維是不可能完全逆轉的

, 抛棄掉的那些資訊,很難找回來了,但是這樣我們更好了解PCA的常用應用了,原來我們現實的人臉識别系統,什麼汽車站,火車站,我們放上身份證,為啥能那麼快就能判斷出來是不是自己啊, 其實就是用了PCA的技術,因為用150個特征就可以判斷是不是本人,完全不需要原來的2914個特征啊,這樣計算量不就減少了?

5. 總結

終于到總結了,我的天啊,這次又是這麼多,畢竟是最後一篇了,得壓軸一些吧哈哈, 趕緊來總結一下,首先,從生活的場景出發,感受了一下什麼叫做降維,然後一個例子闡述PCA究竟在幹什麼事情,總結起來就是PCA找主成分的時候其實在尋找K個盡可能的把樣本區分開的方向,并且這個K個方向互不相關,這樣就可以做到在保留盡可能多的資料資訊的情況下把資料的次元降到了K維。 然後就是在這個基礎上講了一下PCA的數學原理,了解了一下PCA是怎麼去找K個互不相關的方向的。 最後用鸢尾花的例子實作了PCA的數學計算過程,然後又認識了sklearn中的PCA,然後用這個方式對人臉識别的資料集進行降維和逆轉,并進行對比。

總之,學習完之後希望還是有些幫助吧,之前也說過PCA是一個很有用的技術手段,一般用在資料特征處理的部分,是特征工程的部分,那麼最後再來說一個細節:和普通的特征選擇有什麼不同呢?

特征選擇是從已存在的特征中選取攜帶資訊最多的,選完之後的特征依然具有可解釋性,而PCA,将已存在的特征壓縮,降維完畢後不是原來特征的任何一個,也就是PCA降維之後的特征我們根本不知道什麼含義了

好了, 機器學習算法系列到這裡就告一段落了,曆時将近兩個月的時間,寫完了白話機器學習算法理論+實戰,十篇文章,十個算法,整理的過程中,也是一個對算法了解又重新學習的過程,是以收獲還是很多的,當然也希望這些算法,這些文章能夠幫助到更多的人。

參考

  • 白話資料降維
  • PCA降維
  • 我們了解PCA嗎
  • 維數災難問題及資料分析中的降維方法