為什麼要學習機器學習,我認為有以下重要的三點:
- 可縮短我們的程式設計時間,比如可以通過機器學習學習垃圾話樣本,進行更快速更精準的垃圾話的檢測
- 普通程式設計方法難以解決的問題,比如使用者潛在喜好和使用者行為的預測
- 更重要的是擴寬我們程式設計師的思維邏輯,對於適用的方向能夠提出這方面的構思
從前JS程式設計師要學習機器學習,總是困難的,很多時候被演算法和複雜的邏輯所困住,但現在問題得到很大的緩解,我們可以用tensorflow.js(訓練和部署機器語言模型的JavaScript庫)提供的庫和用更好的方式來更簡單的實現機器學習能力。
本文將主要講解機器學習的一些主要概念。更偏重適用tensorflow.js的實戰的入門級教程,請點選這裡(前三節強烈推薦)。
基本的機器學習的流程一般是怎麼樣的
在學習機器學習前我認為首先要明確以下幾點
- 標籤 一般來說標籤就是預測目標的結果,也可以是預測的正確值。
- 特徵 一般是指提提供訓練的樣本,而樣本分以下幾類:
- 有標籤的樣本(帶正確答案的樣本,大部分都是使用有標籤的樣本進行訓練)
- 無標籤的樣本(不帶正常答案的樣本)
- 模型 指的的是預測和訓練樣本的工具。你可以形象的理解為嬰兒的大腦。
- 損失函式 用於計算標籤和模型預測值的差值。
- 優化器 用於將損失函式計算的差值向正確方向優化的步伐
- 學習速度 一般代表優化器的優化的步伐大小,過大則容易偏離正確值,過小則要更多運算才能到達正確值。就好比你要到馬路中間要走5米,然而一次走500米和一次走5釐米,都很難到達馬路中間。
好了,知道了以上幾種概念,那麼我們來以一張圖的方式來展示,機器到底是如何進行學習的。
那麼從圖中很容易瞭解到,我們是將特徵輸入到模型中計算出預測值,將標籤進行通過損失函式計算出誤差值,再交給優化器優化,引數更新後,模型再重複這一個過程,就構成了基本的機器學習的流程。
過擬合
為什麼要講過擬合?什麼是過擬合?
防止過擬合是分類器的一個核心任務。而比如人臉識別,實際上就是一個分類器,比如將圖片的風景,動物臉,人臉中的人臉的特徵進行歸類,將歐美人臉,亞太人臉,非洲人臉進行歸類,甚至可以將某個特定的人的臉單獨歸為一類。所以它在機器學習裡面也有舉足輕重的地位。
那什麼是過擬合呢?舉個例子,我們在日常生活中見到的羊都是白色的,那有一天看到了除了顏色是黑色其他特徵和我們日常見到的白羊都是一樣的,那我們是不是就會認為這不是一隻羊,人當然不會因為顏色就斷定這不是一隻羊,而機器卻會說我見過的羊都是白色的,所以不可能有黑色的羊,所以這不是一隻羊。過擬合官方的解釋是為了得到一致假設而使假設變得過度嚴格。
那麼過擬合要如何解決呢?這是一個機器學習重要的能力:泛化。
那麼如何保證泛化,經驗告訴我們有3個要點:
- 從分佈中抽取
獨立同分布
(iid)樣本 - 分佈是
平穩的
不會隨時間變化而變化 - 始終從
同一分佈
抽取樣本
但樣本的使用也同樣重要,一般我們會將樣本分為 訓練集,驗證集,測試集。
各自用途是什麼?為什麼需要分3個集?
用途是什麼,這個問題很簡單:
- 訓練集 用於訓練模型
- 驗證集 用於評估模型,即在訓練每輪後驗證訓練的準確性,並幫助矯正引數
- 測試集 用於測試模型,驗證模型的準確性
為什麼需要分3個集?可能大家會覺得為什麼要三個集,直接用測試集評估和測試模型不就好了。
那我們做一個假設。如果我們用測試集評估模型,然後調整引數的話如下圖:
那麼會不會出現之前所說過擬合
的問題呢?答案是會的。即為了得到一致假設而使假設變得過度嚴格,請仔細思考這句話。
而正確的方式應該是:
使用這樣的流程就不會產生因為測試資料加入訓練,導致通過了最終的測試資料中。
處理源資料的技巧
在訓練模型之前我們需要處理大量的源資料同時轉換為我們模型可以使用的資料,那麼源資料的處理技巧就至關重要了。
在將原始資料處理成特徵的這個過程,我們叫特徵工程。
那麼我們在做特徵工程時有什麼技巧:
- 字串可以使用獨熱編碼
- 過濾非合理資料,比如庫中極少的資料
- 篩選不隨時間變化的特徵
- 使用分箱技巧處理非線性性特徵
當然我們在處理這類資料時,也應保持以下幾點以更容易暴露有問題的資料:
- 將資料視覺化呈現
- 不斷地對資料進行除錯
- 對資料進行監控
講了資料處理,我們講講擴充套件資料集的方法,那麼什麼是擴充套件資料集呢?比如我們的資料集不是很充足,比如只有10個,顯然是不足以訓練模型的資料集,目前最主流的方法是可以通過它的單一特徵來實現擴充套件,比如都在某個城市出現過,這種是線性的擴充套件方式。但是 而對資料的處理中很多特徵,不是通過簡單的單一線性就能劃分的特徵,比如在某個城市出現過的且短期存在的特徵,這個就是非線性特徵,我們需要短期存在和某個城市出現兩個特徵一起查詢資料,這樣的過程叫做特徵交叉,即將兩個資料交叉後轉換為線性的方法。目前的事實也證明通過通過線性擴充套件資料是最高效的方法。(個人覺得說特徵交叉就高大上一點,而兩個條件相交查詢就不專業了)
如何讓預測結果更加正常和正確評估模型
在之前說過我們的模型訓練需要通過損失函式計算損失,那麼我們如何降低更多的損失呢?就比如我們訓練集的損失度通過不斷的學習越來越低,而測試集在訓練集損失最低的時刻並不能是最低點,甚至說訓練集樣本損失度更高的時候,測試集損失度反而更低,我們應該如何解決這個問題。讓機器學習更好泛化到新樣本中呢?
解決方案:
- 早停法,可以簡單理解為用測試集測試的損失度最低點時就停止訓練的模型
- 正則化
第一種方案在實際的操作中比較難控制,那麼我們今天主要來講講主要使用的L2(嶺迴歸)正則化,即以下幾點。
- 定義複雜度(模型)= 權重的平方和
- 使用適當的權重
- 對於線性模型:首選比較平緩的斜率
- 貝葉斯先驗概率:
- 權重應該以 0 為中心
- 權重應該呈正態分佈
除L2正則化還存在L0正則化,L0正則化主要是解決:
- 稀疏特徵組合造成記憶體消耗過大
- 噪點過多的問題
那麼L0,和L2的區別是什麼呢?即將權重設為0,處理稀疏特徵組合資料。L10屬於非凸優化問題。
那麼L0可能過於暴力,會導致NP-hard的問題,但我們還有一個折中的方案L1,即只對權重絕對值之和進行懲罰。同時L1屬於凸優化問題。
通常我們可以使用邏輯迴歸結合一起使用
例如在求解概率的問題上,我們可以使用線性邏輯迴歸來快速求解問題,在非線性的情況,我們可以使用上節提到的特徵交叉的方法來轉換成線性再進行線性邏輯迴歸來快速求解問題,同時引入早停法和正則化來防止過擬合。
例如之前說過人臉識別實際上是一個分類問題,我們就可以使用邏輯迴歸來判斷分類概率,同時設定閾值來判斷是否加入該分類,有時在這方面準確率產生也會產生誤導性,如:
- 在不同型別的問題需要不同的解決方案時
- 分類不平衡,即正類別或負類別極其罕見時
解決分類不平衡,我覺得我們需要先了解下真正例和假正例,官方說的很好,我直接把這個狼來了的故事搬過來。
- 真正例 我們正確地提醒了狼的出現!我們拯救了小鎮。
- 假正例 錯誤:我們錯誤地提醒了狼的出現。所有人都對我們非常生氣。
- 假負例 確實有一頭狼出現了,但我們沒有發現它。狼吃光了我們所有的雞。
- 假負例 沒有狼出現,也沒有提醒。大家都相安無事。
我們可以把真正例,假正例,假負例,假負例組成不同的指標
- 精確率:(真正例次數)/(所有正類別預測次數)
- 召回率:(真正例次數)/(所有實際正類別數)
精確率和召回率往往處於此消彼長的狀態,精確率和召回率是模型的重要評估指標,但往往我們無法直接得出精確率和召回率,所以可以使用AUC(ROC曲線下方的面積大小)來解決這個問題,即隨機挑選一個正樣本以及一個負樣本,當前的分類演算法根據計算得到的Score值將這個正樣本排在負樣本前面的概率就是AUC值,而這個AUC值越高,模型就越好。
還有一個重要評估的指標是預測偏差,即我們所有預測項的總和和觀察項的總和比較下的結果。但偏差為0也並不能說明模型就完美,但預測偏差是個很好的checklist專案。
深度神經網路
在處理源資料的技巧的小節上說到,對於非線性特徵可以使用特徵交叉的方法來轉換成線性特徵來解決,但對於十分複雜的特徵值,比如說真正例和假正例很接近,該如何處理呢?對的,可以使用深度神經網路來解決這個問題。
對於線性問題,我們的層級大概只有兩層,即輸入層和輸出層
但對於非線性問題,我們往往需要增加一些層,通常通過ReLU(線性整流函式)和BP(反向傳播演算法)來實現。
對於ReLU可以計算是否線性,一般來說大於0則為線性問題
對於BP來說,常見的方法有SGD(隨機梯度下降法),演算法由主要由兩個階段組成:激勵傳播與權重更新。
第1階段:激勵傳播
每次迭代中的傳播環節包含兩步:
- (前向傳播階段)將訓練輸入送入網路以獲得激勵響應;
- (反向傳播階段)將激勵響應同訓練輸入對應的目標輸出求差,從而獲得隱藏層和輸出層的響應誤差。
第2階段:權重更新
對於每個突觸上的權重,按照以下步驟進行更新:
- 將輸入激勵和響應誤差相乘,從而獲得權重的梯度;
- 將這個梯度乘上一個比例並取反後加到權重上。 這個比例(百分比)將會影響到訓練過程的速度和效果,因此成為“訓練因子”。梯度的方向指明瞭誤差擴大的方向,因此在更新權重的時候需要對其取反,從而減小權重引起的誤差。
第 1 和第 2 階段可以反覆迴圈迭代,直到網路對輸入的響應達到滿意的預定的目標範圍為止。
注意事項:
- 梯度很重要
- 如果它是可微的,則我們才能夠對其進行學習
- 梯度可能會消失
- 每個額外的層都會依次降低訊雜比
- ReLu 在這裡很有用
- 梯度可能會分解(比如媽媽裡面出現男,其實這在中國很常見)
- 學習速率在這裡很重要
- 批標準化(實用按鈕)可以提供幫助
- ReLu 層可能會消失
- 保持冷靜,並降低您的學習速率
如何解決該問題,標準化特徵值很重要
- 特徵具有合理的範圍
- 大致以 0 為中心,[-1, 1] 的範圍通常效果比較好
- 有助於梯度下降法收斂;避免 NaN 陷阱
- 避免離群值也會有幫助
- 可以使用一些標準方法:
- 線性縮放
- 為最大值和最小值設定硬性上下限(截斷)
- 對數縮放
其次在深度神經網路裡面還有一個很有用的技巧,丟棄
- 丟棄:另一種正則化形式,對神經網路很有用
- 工作原理是,在一個梯度步長中隨機“丟棄”網路的單元
- 有一個可用於整合學習此處的模型的連線
- 丟棄得越多,正則化效果就越強
- 0.0(一點都不丟棄) = 無丟棄正則化,得到原來的複雜模型
- 1.0 (全部丟棄) = 丟棄所有內容!學不到任何規律,得到特別簡單且無用的模型
- 中間值更有用(在這個位置進行丟棄,則是在這個位置應用了有效的正則化)
多類別神經網路
在之前的章節裡面說到,邏輯迴歸很適合一些是或者不是的問題,它可以很方便給某樣東西的是是或不是加上概率,比如是否是是垃圾郵件還是非垃圾郵件。
但在多類別中,我們是怎麼處理的呢,即如何處理狗是哺乳動物?還是植物?還是其他什麼?這種多分支選擇。
那麼我們在一對多類別中,我們可以:
- 為每個可能的類別建立唯一輸出
- 分別對“我的類別”與“所有其他類別”訊號進行訓練
- 可以在深度網路中執行,也可以藉助單獨的模型執行
那我們有沒有更好,更方便的方法呢?對的,我們可以使用SoftMax進行多類別劃分。SoftMax使得:
- 新增了附加限制:要求所有一對多節點的輸出總和為 1.0(100%,這就是邏輯迴歸的多類別升級版)
- 附加限制有助於快速訓練收斂
- 另外,允許輸出解析為概率
我們可以使用兩種方式讓SoftMax進行計算
- 全部資料計算 即暴力破解;針對所有類別進行計算
- 取樣資料計算 即針對所有正類別標籤進行計算,但僅針對負類別標籤的隨機樣本進行計算。
那我們應該如何使用標籤給多類別分類呢?
多類別單一標籤分類:
- 一個樣本可能只是一個類別的成員。
- 類別互斥這一限制是有用的結構。
- 有助於在損失中對此進行編碼。
- 將一個 softmax 損失用於所有可能的類別。
多類別多標籤分類:
- 一個樣本可能是多個類別的成員。
- 無需對類別成員資格設定額外的限制。
- 將一個邏輯迴歸損失用於每個可能的類別。
相似性神經網路
這個在商品推薦和廣告推薦比較常用。通常我們需要在多維度分析使用者來推薦對應商品:
- 比如使用者對商品的興趣可大致從N個方面分析
- 每部商品都變成一個點,在不同的維度中,這個點的高度都是不一樣的
- 那麼我們可從資料中巢狀學習,使用者在不同維度的興趣點
在深度網路中學習巢狀能做什麼?
- 無需單獨的訓練過程,也就是說,巢狀層只是隱藏層,每個維度一個單元
- 監督式資訊針對所需任務調整學到的巢狀,即根據使用者上一個商品調整,下一個商品出現
- 隱藏單元直觀地發現整理多維空間中的各項,才能最大限度地優化最終目標
我們可以使用輸入表示法來顯示使用者使用者興趣的相同特徵
- 每個樣本是使用者興趣的相同的特徵的稀疏向量
- 使矩陣樣本的密集表示法表示
比如
x | 雙肩包 | 沙發 | 冰箱 | 單肩包 |
---|---|---|---|---|
x | x | v | x | x |
x | x | x | v | x |
使用者 | v | x | x | v |
那麼使用者的矩陣樣本可表示為(1,0,0,1),但這種方法從空間和時間上來說,這種表示法並不高效,因為每個看過的商品都是一行,我這裡只例舉了雙肩包,沙發,冰箱,單肩包。而正常來說,使用者看的遠超這些。
我們如何選擇巢狀維度個數,請根據以下三條判斷:
- 巢狀維度的個數越多,越能準確地表示輸入值之間的關係
- 不過,維度個數越多,過擬合的可能性就越高,訓練速度也會越慢
- 經驗法則
巢狀能做什麼?
- 巢狀會以相似內容彼此靠近的方式將各項內容(如影片、文字等)對映到低維實向量
- 巢狀也可應用於密集資料(如音訊),以建立有意義的相似度指標
- 聯合巢狀多種型別的資料(如文字、圖片、音訊等),以定義這些資料之間的相似度
結語
為什麼要學習這些概念,我認為概念講解往往比程式碼講解更容易理解一樣東西,程式碼也僅僅是概念的一種實現,概念能更好幫助我們在後續的階段更好的學習,歡迎檢視tensorflow.js的實戰的入門級教程學習更多實戰內容。