人工智能依然這麼火,我還是老老實實寫下一篇吧。本篇要講的東西實際上很簡單,就是教你設計機器學習模型的通用步驟,在這裏你可以用matlab去實現,可以用python去實現,甚至你可以用C去實現。舉個反向傳播的設計例子。
看懂這一篇,你要具備的基礎知識是:線性代數增廣矩陣部分,數值計算函數擬合部分,概率與統計的檢驗假設部分。
在看這些之前,建議先補一補前置課程。
在開始之前,我先説一下整個反向傳播(BP)的思路,如果説你有數值計算的背景,你應該會很容易就理解反向傳播説的是什麼,它實際上就是假定我們能用函數去模擬一個過程,放在數值計算中,就是我們做擬合的過程。
比如如果我們要判斷電子顯微鏡下拍出來的細胞照片是否有癌變的可能性,經驗豐富的醫生會告訴你,你要看細胞的各個參數,比如細胞外形,細胞顏色變化等等。放到我們數學上説,這就是參數,在本篇文章中,我們用到的細胞參數數量一共有10個。
先給出所有的步驟:多層感知機(MLP)為例子:
1.數據導入與清洗。
2.數據劃分。
3.線性縮放。
4.矩陣增廣。
5.重置分類標籤。
6.初始化權重矩陣。
7.訓練網絡。
8.預測與分類。
1.數據導入與清洗。
在我們學習接觸機器學習的時候,尋找特定的數據集是非常重要的事情,因為機器學習的理論很容易掌握,但是數據很難獲得。所幸,網絡上會有很多提供給初學者的數據集。比如這次我們會用到的是乳腺癌判斷數據集,breast-cancer-Wisconsin.data。這些數據集在網絡上可以自己下載下來,或者直接用python命令行導入程序中。
https://archive.ics.uci.edu/ml/datasets/Breast+Cancer+Wisconsin+(Diagnostic)
在導入數據之後,我們會看到一共12列數據,從左往右看,第一列是0到697的數字,很明顯是編號,第二列是數據數字編號,這個可以忽略,第三到第11列就是我們需要的參數數據,第12列是2或者4的數字,代表每個樣本是屬於病變還是不屬於病變。。整個來看,這是一個13X697的矩陣,每一行都是一條數據。
我們可以看到,這個數據源是非常規整的,但是裏面也有缺失部分,用NaN代替。當然我們在處理缺失數據條的時候,有兩種處理辦法,一種是刪掉這條數據,一種是用0代替它。
因為機器學習對於數據量的要求很高,所以當我們的數據量只有不到700條的時候,刪除缺失數據就非常不好。所以我覺得用0代替是一個更加好的處理方式。
其實現在數據清洗也逐漸成為了一個職業,在有監督學習中,如何標註數據,以及標註足夠數量的數據,依然還是用人來完成的。
2.數據劃分。
當然,基於我們現在數據集很小的情況,我們需要採用特殊的統計學方法來充分利用起來數據集。這時候劃分數據集就成了非常重要的事情。
為什麼我們需要用小數據集進行劃分呢?因為我們想要充分利用有限的數據集,找到合適的參數模型,但是又要防止過擬合。這時候,k折交叉驗證(k-fold cross validation)與留出法(holdout cross validation)成了最通用的數據集劃分方法。
交叉驗證用於評估模型的預測性能,尤其是訓練好的模型在新數據上的表現性能,也可在一定程度上減小過擬合。也能儘量從有限的數據中獲得儘可能多的信息。
叉驗證的目的:在實際訓練中,模型通常對訓練數據好,但是對訓練數據之外的數據擬合程度差。用於評價模型的泛化能力,從而進行模型選擇。
交叉驗證的基本思想:把在某種意義下將原始數據(dataset)進行分組,一部分做為訓練集(train set),另一部分做為驗證集(validation set or test set),首先用訓練集對模型進行訓練,再利用驗證集來測試模型的泛化誤差。另外,現實中數據總是有限的,為了對數據形成重用,從而提出k-摺疊交叉驗證。
對於個分類或迴歸問題,假設可選的模型為。k-摺疊交叉驗證就是將訓練集的1/k作為測試集,每個模型訓練k次,測試k次,錯誤率為k次的平均,最終選擇平均率最小的模型Mi。
1、 將全部訓練集S分成k個不相交的子集,假設S中的訓練樣例個數為m,那麼每一個子集有m/k個訓練樣例,相應的子集稱作{}。
2、 每次從模型集合M中拿出來一個,然後在訓練子集中選擇出k-1個
{}(也就是每次只留下一個),使用這k-1個子集訓練後,得到假設函數。最後使用剩下的一份作測試,得到經驗錯誤。
3、 由於我們每次留下一個(j從1到k),因此會得到k個經驗錯誤,那麼對於一個,它的經驗錯誤是這k個經驗錯誤的平均。
4、 選出平均經驗錯誤率最小的,然後使用全部的S再做一次訓練,得到最後的。
最後我們劃分得到的數據集分為:訓練集,測試集。當然,有的會多劃分一點,多一個驗證集。
3.線性縮放。
在我們辛辛苦苦蒐集完數據,完成了最基礎的數據整理分類,數據集的劃分之後。下一步需要做的就是數據預處理。
數據預處理最常用的還是線性縮放。
數據的線性縮放實際上屬於特徵工程的部分。
舉個例子,面對多維特徵問題的時候,有時候數據的極值相差特別大,導致不同維度的數據的尺度相差很大,我們把多維數據在多維空間中畫出來的時候,會發現它是扁的,因而我們訓練的分類器很難把不同的數據分出來。
就像上面圖左邊的,我們用原始數據做訓練的時候,很難保證梯度下降能更快收斂。右邊是縮放之後的數據,我們可以看到,不同的圓圈之間的區分度更大了。這就是線性縮放的意義。
當然,在我們設計模型上,線性縮放的意義在於:提高模型的收斂速率,提高模型的精度。
線性縮放的方法同樣有幾種:歸一化特徵縮放(0-1縮放),標準化特徵縮放。
4.矩陣增廣。
這部分實際上是線性代數的知識。
在我們處理完數據矩陣,做完線性縮放之後,我們還需要做一個矩陣增廣,英文就是Augmented。
回到我們剛剛的數據矩陣中,當我們把數據矩陣進行線性縮放結束之後,我們可以把這個矩陣看成一個方程組,只不過這個方程組有10組參數,697個方程表達式。既然我們能把它看成方程組,那麼我們就可以套用成熟的線性代數理論去優化和驗證這個矩陣。非齊次線性方程組,就是方程組的等式右邊不為0的方程組,係數加上方程等式右邊的矩陣,叫做增廣矩陣。
方程組唯一確定增廣矩陣,通過增廣矩陣的初等行變換可用於判斷對應線性方程組是否有解,以及化簡求原方程組的解。在我們這個例子中,處理增廣很簡單,就是在矩陣最後一列增加一列1。這就保證了我們這個矩陣就是整個方程組的係數矩陣。
增廣矩陣用於判斷矩陣解的情況,
5.重置分類標籤。
其實這部分很簡單,就是把原有的分類標籤替換成我們自定義的分類標籤就行。
原有的數據中,2代表一個分類,4代表另一個分類。這就是一個簡單的二分類問題。在機器學習中,分類是很重要的一個環節,與二分類對應的是多分類問題。二類分類是假設每個樣本都被設置了一個且僅有一個標籤 0 或者 1。多標籤分類(Multilabel classification): 給每個樣本一系列的目標標籤. 可以想象成一個數據點的各屬性不是相互排斥的。
6.初始化權重矩陣。
在我們終於處理好數據,劃分完數據集,做完線性縮放,搞定分類標籤重置的任務之後。我們就開始設計完整的網絡,比如一個最簡單的三層多層感知機的設計:
其中,[x1,x2...x10]是輸入序列,我們在每一個數據行中,取出10個維度的數據分配給x1到x10。中間的隱藏層有兩層,每一層隱藏層都有9個節點,我們稱之為unit。當然,每一層之間的鏈接除了我圖上標註出來的之外,還有一個非線性變換,例如用sigmoid函數進行變換。
此處多嘴説幾個問題,一個是隱藏層是怎麼設置的,一個是為什麼要用非線性函數進行變換。
隱藏層之所以叫隱藏層,是因為我們整個模型設計結束之後,它是在模型內部的,並不會表現出來,我們能接觸到的部分是模型的輸入層與輸出層,中間這些我們不會接觸到的層,被稱為隱含層。
之所以説機器學習是煉丹,是因為隱藏層這個設定是純自主化的,你可以設定一千層,每一層有一千個節點,你也可以設定兩層,每一層有三個節點。當前並沒有一個完整而通用的數學模型來指導我們該如何設定隱藏層的數量與節點數,只有幾個經驗公式告訴我們該如何設置:
設置完隱藏層的數量之後,我們還需要初始化權重向量。但是很明顯,我們不能把權重向量設置成全0,這樣的話無論輸入什麼數據我們都沒有辦法去訓練網絡。
為什麼要在隱藏層之間進行非線性變換呢?
我們一般把這個非線性變換稱之為激活函數。如果激活函數為線性的話,我們可以很容易從數學角度推導出來一層與多層隱藏層之間沒有任何區別,我們也就失去了設置多層隱藏層的意義。
7.訓練網絡。
好了,在我們搞定數據集,搞定基本的網絡結構之後,我們還要進行訓練。這時候我們會引出一個新的問題,超參數怎麼設置?
我個人理解的超參數,主要指的是學習速率,迭代次數,層數,每層神經元的個數等等手動設置的參數,而模型可以自動確定定義的參數,比如權重矩陣這些,都被稱為是參數。
在設置學習率(learning rate)的時候,初學者總是設定固定的學習率,比如設定為0.00001。我之前第一次設計網絡的時候,網絡輸出一直有問題,後來發現是自己學習率設置太大,設成了0.1,導致網絡學習完數據之後就把所有的預測分類全都歸到一類去了。當然,現在學術界和工業界也有更多的想法,比如有的研究給出了可變學習率的模型,在開始訓練網絡的時候學習率會很大,幫助快速逼近最優解,當快逼近最優解的時候將學習率替換成更小的以細化訓練過程,防止訓練過於粗糙。
至於迭代次數,其實這也是一個非常玄學的問題。一般來説,我們有多少個數據就迭代多少次。但是網絡這個東西,你需要防止它過擬合。可能它訓練了100個數據就完全擬合了,但是你給了600個數據,那麼後面的訓練就是過擬合。最後得到的結果也是過擬合的。關於解決過擬合的方法論有很多,比如L1/L2正則化。但是跟迭代聯繫在一起之後,我們可以設定一個預測輸出與實際輸出的差值閾值,當預測輸出與實際輸出的插值小於我們設定的閾值時候我們就可以停止網絡訓練了。其實這個思路也就是我們數值計算中進行數值擬合的思路。
8.預測與分類。
其實預測與分類這部分應該放在網絡訓練之前講的,因為選擇合適的分類器是我們設計網絡之前的問題。
傳統的機器學習的監督學習分類分類和迴歸,分類是爭對離散的數據,而回歸是爭對連續的數據,在數據預處理好的基礎上要對數據進行預測,通常採用CV交叉驗證來進行模型評價和選擇。這篇文章通過連續的數據結合sklearn庫對各種迴歸器做一比較:
1.linear regression
缺點:顧名思義,linear regression是假設數據服從線性分佈的,這一假設前提也限制了該模型的準確率,因為現實中由於噪聲等的存在很少有數據是嚴格服從線性的。
優點:基於這種假設,linear regression可以通過normal equation求閉合解的方式求得y_predict
2.logistic regression
缺點:從線性迴歸衍生而來,將線性的值域通過sigmoid函數壓縮在(0,1)範圍內,缺點同linear regression,且也是要求數據是無缺失的
優點:有兩種方式求解,精確的解析解和SGD算法估計,在要求準確性時使用解析解,在要求時間效率時使用SGD 迭代
3.SVM(支持向量機 )
缺點:計算代價比較大,SVM是將低維無序雜亂的數據通過核函數(RBF,poly,linear,sigmoid)映射到高維空間,通過超平面將其分開
優點:SVM是通過支撐面做分類的,也就是説不需要計算所有的樣本,高維數據中只需去少量的樣本,節省了內存
在sklearn默認配置中三種核函數的準確率大概是:RBF>poly>linear
4.Naive Bayes
缺點:這一模型適合用在文本樣本上,採用了樸素貝葉斯原理假設樣本間是相互獨立的,因此在關聯比較強的樣本上效果很差
優點:也是基於其獨立的假設,概率計算大大簡化,節省內存和時間
5.K近鄰
缺點:k需要人為設定,且該算法的複雜度很高
優點:“近朱者赤,近墨者黑”KNN是無參數訓練的模型
6.決策樹(DT)
缺點:在訓練數據上比較耗時
優點:對數據要求度最低的模型,數據可以缺失,可以是非線性的,可以是不同的類型,,最接近人類邏輯思維的模型,可解釋性好
7.集成模型(眾志成城模型)
random forest:隨機抽取樣本形成多個分類器,通過vote,少數服從多數的方式決定最終屬於多數的分類器結果,分類器之間是相互去之間關聯的
gradient boost:弱弱變強,最典型的代表是adaboost(三個臭皮匠,頂個諸葛亮),弱分類器按照一定的計算方式組合形成強的分類器,分類器之間存在關聯,最終分類是多個分類器組合的結果
一般地,GB>RF>DT
但是集成模型缺點在於受概率的影響,具有不確定性
以上是常用的迴歸分類器的比較,在知道各種分類器的優缺點之後就可以使用正確的分類器完成自己的數據處理,如下表是通過計算各類分類器的殘差來對比同一任務不同分類器之間的好壞,可以看出來在sklearn默認參數的前提下,準確率排序是:集成模型>DT>SVM>KNN>Linear
有關於預測準確度的設計:
在機器學習裏面做一些分類任務時,經常會使用到一些評價指標,下面就一些常用的指標進行詳細的説明。
上圖表示為一個二分類的混淆矩陣(多分類同理,只需要把不屬於當前類的其他類都考慮為負例),表格中的四個參數説明:
True Positive(TP):預測為正例,實際為正例
False Positive(FP):預測為正例,實際為負例
True Negative(TN):預測為負例,實際為負例
False Negative(FN):預測為負例,實際為正例
從這我們可以看出,TP和TN都是預測對了,FP和FN都是預測錯了。
【指標分析】
我們最容易搞混的就是accuracy和precision,好像兩者都可以稱為準確率,正確率,精度等等...其實我們不必要考究兩者的中文稱呼究竟是什麼,搞清楚兩者的含義自然就可以區分它們。首先,accuracy指的是正確預測的樣本數佔總預測樣本數的比值,它不考慮預測的樣本是正例還是負例。而precision指的是正確預測的正樣本數佔所有預測為正樣本的數量的比值,也就是説所有預測為正樣本的樣本中有多少是真正的正樣本。從這我們可以看出,precision只關注預測為正樣本的部分,而accuracy考慮全部樣本。
Recall可以稱為召回率、查全率等等...我們也不考究如何翻譯它,它指的是正確預測的正樣本數佔真實正樣本總數的比值,也就是我能從這些樣本中能夠正確找出多少個正樣本。
F-score相當於precision和recall的調和平均,用意是要參考兩個指標。從公式我們可以看出,recall和precision任何一個數值減小,F-score都會減小,反之,亦然。
specificity指標平時見得不多,它是相對於sensitivity(recall)而言的,指的是正確預測的負樣本數佔真實負樣本總數的比值,也就是我能從這些樣本中能夠正確找出多少個負樣本。
【實例説明】
問題:假設某個學校有1000個王者榮耀玩家,其中有10個是王者段位,判斷這個玩家是不是王者選手?
現在我有一個分類器,檢測出來有20個王者選手,其中包含5個真正的王者選手。那麼上述指標該如何計算呢?
分析:檢測出來有20個王者選手,説明有980個選手被預測為非王者選手。這20個檢測為王者選手包含5個真正的王者選手,説明另外15個實際為非王者選手,所以,
accuracy = (5+980-5) / 1000 = 0.98
precision = 5 / 20 = 0.25
recall = 5 / 10 = 0.5
F-score = 2 / (1/0.25 + 1/0.5) = 0.33
sensitivity = recall = 0.5
specificity = (980-5) / (1000-10) = 0.98
從這個案例我們可以發現,雖然分類器的accuracy可以達到98%,但是如果我的目的是儘可能的找出隱藏在這1000人中的王者選手,那麼這個分類器的性能是不達標的,這也就是為什麼要引入precision和recall以及F-score評價指標的原因。
ok,關於設計一整個機器學習的流程,我就介紹到這裏。應該算是我簡單的個人想法之一。要説簡單也簡單,你跟這個這個流程一步一步做下去肯定可以自己設計一個深度學習模型出來,要説難也難,因為中間每一個流程都涉及到了大量的數學知識,你要根據自己的問題實際情況去選擇特定的數學工具組成這個的話,肯定是需要花費大量的時間的。
如果有問題可以在下面評論問我。