本章涵蓋了
- 分類和回歸以外的機器學習形式
- 機器學習模型的正式評估過程
- 為深度學習準備數據
- 特征工程
- 解決過擬合
- 解決機器學習問題的通用工作流程
在第三章的三個實際例子之后,您應該開始熟悉如何使用神經網絡來處理分類和回歸問題,并且您已經看到了機器學習的核心問題:過擬合。
這一章將把你的一些新直覺形式化到一個堅固的概念框架中,用來解決深度學習的問題。我們將把所有這些概念——模型評估、數據預處理和特性工程,以及處理過擬合——整合到一個詳細的七步工作流程中,以處理任何機器學習任務。
4.1機器學習的四個分支
在前面的示例中,您已經熟悉了三種特定類型的機器學習問題:二分類、多分類和標量回歸。這三個都是監督學習(supervised learning)的實例,目標是學習訓練輸入和訓練目標之間的關系。
監督學習只是冰山一角——機器學習是一個有著復雜子領域類別的廣闊領域。機器學習算法通常分為四大類,在下面的部分中進行描述。
4.1.1 有監督學習
這是目前為止最常見的情況。它包括,在給定一組示例(通常由人來注釋)的情景下,學習將輸入數據映射到已知目標(也稱為注解(annotations))。到目前為止,你在這本書中遇到的四個例子都是有監督學習的典型例子。一般來說,目前備受關注的深度學習的幾乎所有應用都屬于這一類,例如光學字符識別(optical character recognition, OCR)、語音識別、圖像分類和語言翻譯。
雖然有監督學習主要由分類和回歸組成,但也有更多的外來變體,包括以下(有例子):
- 序列生成(Sequence generation)——給定一張圖片,預測描述它的標題。序列生成有時可以重新表述為一系列分類問題(例如在序列中反復預測單詞或詞組(Token))。
- 語法樹預測(Syntax tree prediction)——給定一個句子,預測它分解成的語法樹。
- 對象檢測(Object detection)—— 給定一張圖片,在圖片內的特定對象周圍畫一個邊框。這也可以表示為一個分類問題(給定許多候選邊界框,對每個邊界框的內容進行分類)或一個聯合了分類和回歸的問題,其中邊界框坐標是通過向量回歸預測的。
- 圖像分割(Image segmentation)——給定一幅圖片,在特定對象上繪制像素級的蒙版。
4.1.2無監督學習
機器學習的這個分支包括在不借助任何目標的情況下對輸入數據進行有趣的轉換,以實現數據可視化、數據壓縮或數據去噪,或者更好地理解當前數據中的相關性。無監督學習是數據分析的主要內容,在試圖解決一個有監督學習的問題之前,它通常是更好地理解數據集的必要步驟。降維(Dimensionality reduction)和聚類(clustering)是無監督學習的著名類別。
4.1.3 自助(Self-supervised)學習
這是監督學習的一個特例,但它的不同之處足以讓它應該有自己的類別。自主監督學習是一種無需人為標記標簽的監督學習——可以把它看作是沒有任何人參與的監督學習。這里仍然涉及到標簽(因為學習必須受到某些東西的監督),但它們是由輸入數據生成的,通常使用啟發式算法。
例如,autoencoders是自監督學習的一個眾所周知的實例,其中生成的目標是輸入,沒有修改。同樣地,給定過去的幀,試圖預測視頻中的下一幀,或給定之前的單詞,預測文本中的下一個單詞,都是自我監督學習的實例(短暫的監督學習(temporally supervised learning),在這種情況下:監督來自未來的輸入數據)。請注意,監督學習、自我監督學習和非監督學習之間的區別有時可能是模糊的——這些類別更像是沒有固定邊界的連續統一體。自我監督學習可以被重新解釋為監督學習或非監督學習,這取決于你關注的是學習機制還是它的應用環境。
請注意,在本書中,我們將特別關注監督學習,因為它是目前深度學習的主要形式,具有廣泛的行業應用。在后面的章節中,我們還將簡要介紹自我監督學習。
4.1.4強化學習
這個機器學習的分支被長期忽視,直到最近在谷歌DeepMind成功地將其應用于學習玩Atari游戲(后來,學習玩圍棋到最頂尖水平)之后,它開始受到很多關注。在強化學習中,agent會接收環境的信息,并學會選擇能獲得最大回報的行為。例如,可以通過強化學習來訓練一個神經網絡,它“看”電子游戲屏幕并輸出游戲動作以最大化它的分數。
目前,強化學習主要是一個研究領域,在游戲之外還沒有取得顯著的實際成功。然而,隨著時間的推移,我們預計強化學習將接管越來越廣泛的現實應用領域:自動駕駛汽車、機器人、資源管理、教育等等。這個想法的時機已經到來,或者即將到來。
分類及回歸術語表
分類和回歸涉及到許多專業術語。你在前面的例子中遇到過一些,在以后的章節中你會看到更多。它們有精確的、特定于機器學習的定義,您應該熟悉它們:
- Sample or input:輸入到模型中的一個數據點
- Prediction or output:模型的輸出結果
- Target:答案。理想情況下,根據一個外部來源的數據,模型應該預測的結果
- Prediction error or loss value: 模型的預期與目標間的差距的度量
- Classes:分類問題中可供選擇的一組可能的標簽。例如,當分類貓和狗的圖片時,“狗”和“貓”是兩個類。
- Label:分類問題中類注釋的特定實例。例如,如果圖片#1234被注釋為包含類“dog”,那么“dog”就是圖片#1234的標簽。
- Ground-truth or annotations:數據集的所有目標,通常由人類收集。
- Binary classification:一個分類任務,其中每個輸入樣本應該被分為兩個互斥的類別
- Multiclass classification:一個分類任務,其中每個輸入樣本都應該被分為兩類以上:例如,對手寫數字進行分類。
- Multilabel classification— 一個分類任務,其中每個輸入樣本可以分配多個標簽。例如,一個給定的圖像可能同時包含一只貓和一只狗,并且應該用“貓”標簽和“狗”的標簽進行標注。每個圖像的標簽數量通常是可變的。
- Scalar regression:目標是連續標量值的任務。預測房價就是一個很好的例子:不同的目標價格形成一個連續的空間。
- Vector regression:目標是一組連續值的任務:例如,一個連續向量。如果你對多個值進行回歸(例如圖像中邊界框的坐標),然后進行向量回歸。
Mini-batch or batch:由模型同時處理的一小部分樣品(通常在8到128之間)。為了便于在GPU上進行內存分配,樣本的數量通常是2的冪。在訓練時,使用一個迷你批處理(mini-batch)來計算應用于模型權重的單一梯度下降更新。
4.2 評估機器學習模型
評估一個模型總是歸結為將可用數據分成三組:訓練、驗證和測試。您利用訓練數據進行訓練,并根據驗證數據評估您的模型。一旦您的模型準備好了,您就可以在測試數據上最后一次測試它。
你可能會問,為什么不準備兩套呢:一套是訓練,一套是測試?你會對訓練數據進行訓練并對測試數據進行評估。更簡單!
原因是,開發一個模型總是涉及到調整其配置:例如,選擇層的數量或層的大小(稱為模型的超參數(hyperparameters),以區別于參數,后者是網絡的權重)。通過將模型在驗證數據上的性能作為反饋信號來執行此調優。從本質上講,這種調優是一種學習形式:在某些參數空間中搜索良好的配置。因此,根據模型在驗證集上的性能調整模型的配置會很快導致對驗證集的過擬合,即使您的模型從未直接針對驗證集進行過訓練。
這種現象的核心是信息泄露的概念。每次根據模型在驗證集上的性能調整模型的超參數時,關于驗證數據的一些信息就會泄漏到模型中。如果只對一個參數這樣做一次,那么很少有信息會泄漏,您的驗證集將保持可靠,以評估模型。但是,如果您重復這么多次——運行一個實驗、對驗證集進行評估,并將模型修改為結果——那么您就會將越來越多關于驗證集的信息泄漏到模型中。
最終,您將得到一個在驗證數據上人工執行良好的模型,因為這是您優化它的目的。您關心的是全新數據的性能,而不是驗證數據,因此您需要使用完全不同的、從未見過的數據集來評估模型:測試數據集。您的模型不應該訪問任何關于測試集的信息,即使是間接的。
如果基于測試集性能對模型進行了任何調整,那么您的泛化度量將是有缺陷的。
將數據分割成訓練、驗證和測試集看起來很簡單,但是有一些高級的方法可以在數據很少的時候派上用場。讓我們回顧一下三種經典的評估方法:簡單的保留驗證、Kfold驗證和通過變換迭代K-fold驗證。
-
簡單的保留驗證(SIMPLE HOLD-OUT VALIDATION)
將數據分離部分作為測試集。對剩余的數據進行訓練,并用測試集進行評估。正如您在前幾節中看到的,為了防止信息泄漏,您不應該基于測試集對模型進行調優,因此您還應該保留一個驗證集。
從示意圖上看,保持驗證如圖4.1所示。下面的清單顯示了一個簡單的實現。
Listing 4.1 Hold-out validation
這是最簡單的評估手段,它有一個缺陷:如果可用的數據很少,那么您的驗證和測試集可能包含的樣本太少,無法從統計學上代表手邊的數據。這很容易識別:如果在分割之前對數據進行不同的隨機洗牌最終會產生非常不同的模型性能度量,那么您就會遇到這個問題。K-fold驗證和迭代K-fold驗證是解決這一問題的兩種方法,下面將對此進行討論。
-
K-FOLD驗證法(K-FOLD VALIDATION)
使用這種方法,您可以將數據分割為大小相同的K個分區。對于每個分區i,在其余的K - 1分區上訓練一個模型,并在分區i上評估它。你的最終成績是K分的平均值。當模型的性能顯示出基于traintest分割的顯著差異時,這種方法是有幫助的。與保持驗證一樣,這種方法不會使您免于使用不同的驗證集進行模型校準。
從示意圖上看,K-fold交叉驗證類似于圖4.2。清單4.2顯示了一個簡單的實現:
Listing 4.2 K-fold cross-validation
-
混排迭代K-FOLD方法(ITERATED K-FOLD VALIDATION WITH SHUFFLING)
在這種情況下,可用數據相對較少,需要盡可能精確地評估模型。我發現它在Kaggle比賽上非常有用。它包括多次應用K-fold驗證,每次對數據進行洗牌,然后再以K種方式對數據進行拆分。最終得分是K-fold驗證每次運行時獲得的平均得分。注意,您最終培訓和評估P×K模型(P是您使用的迭代次數),這可能代價非常昂貴,
4.2.2注意事項
在選擇評估方案時要注意以下幾點:
- 數據的代表性(Data representativeness)——您希望您的訓練集和測試集都能代表手邊的數據。舉例來說,如果你要分類數字圖片,并且你從一個樣例數組開始,而這些樣例數組都按照它們的類別進行了排序,這時候你將前80%的數組數據作為訓練集,并將后續的20%作為你的測試集,將導致你的訓練數據只包含了分類0-7,而你的測試數據集只包含分類8-9。這似乎是一個荒謬的錯誤,但卻出奇地普遍。
因此,在將數據分解為訓練和測試集之前,您通常應該隨機地打亂(randomly shuffle)數據。
- 時間箭頭的方向(The arrow of time)——如果你想根據給定的過去來預測未來(例如,明天的天氣,股票運動等等),你不應該在分割數據之前隨機的洗牌數據。因為這樣做會造成暫時的泄漏:您的模型將有效地接受來自未來數據的訓練。在這種情況下,您應該始終確保測試集中的所有數據都在訓練集中的數據之后。
- 數據中的冗余(Redundancy in your data)——如果數據中的某些數據點出現了兩次(這在真實數據中相當常見),那么將數據重組并將其分割為訓練集和驗證集將導致訓練集和驗證集之間的冗余。實際上,您將在部分訓練數據上測試,這是您能做的最糟糕的事情!確保你的訓練集和驗證集是分開的。
4.3 神經網絡的數據預處理
數據預處理的目的是使手頭的原始數據更易于被神經網絡接受。這包括向量化、規范化、處理缺失值和特征提取(vectorization, normalization, handling missing values, and feature extraction)。
-
向量化(VECTORIZATION)
神經網絡中的所有輸入和目標必須是浮點數據的張量(或者,在特定情況下,整數的張量)
。任何需要處理的數據——聲音、圖像、文本——都必須首先轉換為張量,這一步稱為數據向量化。例如,在前面的兩個文本分類示例中,我們從表示為整數列表(表示單詞序列)的文本開始,并使用one-hot編碼將它們轉換為float32的張量。在對數字進行分類和預測房價的例子中,數據已經以向量形式出現,所以您可以跳過這一步。 -
數值歸一化(VALUE NORMALIZATION)
在digit-classification示例中,利用從0-255范圍內的整數編碼的圖像數據開始,編碼灰度值。在將這些數據輸入網絡之前,您必須將其轉換為float32并除以255,這樣您最終會得到0-1范圍內的浮點值。類似地,當預測房價時,你從各種范圍的特征開始——一些特征有小的浮點值,另一些特征有相當大的整數值。在將這些數據輸入網絡之前,必須獨立地對每個特性進行規范化,使其具有標準差1和平均值0。
一般來說,輸入相對較大值的神經網絡數據是不安全的(例如,多位整數,這比網絡權值所取的初始值大得多)或異構數據(例如,一個特性在0-1范圍內,另一個特性在100-200范圍內的數據)。這樣做將觸發大的梯度更新,從而阻礙網絡收斂。為了使您的網絡更容易學習,您的數據應該具有以下特征:
- 只取小值(Take small values)— 典型的,大多數值必須在0-1的范圍內。
- 必須同質( Be homogenous)— 也就是說,所有的特征大致都應該相同的范圍內取值。
此外,下面更嚴格的歸一化實踐是常見的,并且可以提供幫助,盡管它并不總是必要的(例如,您在digit-classification示例中沒有這樣做): - 分別對每個特性進行規范化,使其平均值為0。
-
獨立地規范化每個特性,使其標準差為1。
備注:這就是概率論里面學到的,如何將非單元高斯分布轉換為單元高斯分布時的變換公式 xx = (x- u) / σ,通過這種變換,就能符合單元高斯分布的要求了。 心塞,十年前學的數學,都還給老師了。
使用Numpy數組很容易做到這一點:
-
處理缺失值(HANDLING MISSING VALUES)
您的數據有時可能缺少值。例如,在房價示例中,第一個特征(數據中索引0的列)是人均犯罪率。如果這個特性不是對所有樣本可用呢?因此,在訓練或測試數據中就會有缺失值。
一般來說,使用神經網絡,將輸入的缺失值設置為0是安全的,條件是0已經不是一個有意義的值。網絡將從暴露的數據中了解到值0表示丟失數據,并將開始忽略該值。
注意,如果您期望測試數據中有缺失值,但是網絡是在沒有任何缺失值的數據上訓練的,那么網絡不會忽略缺失值!在這種情況下,您應該人為地生成缺少條目的訓練樣本:將一些訓練樣本復制幾次,并刪除一些您希望在測試數據中丟失的特征。
4.3.2 特征工程(Feature engineering)
特征工程是利用你自己關于數據和機器學習算法(在本例中是神經網絡)的知識,在數據進入模型之前對其應用硬編碼(非學習)轉換,使算法更好地工作。在許多情況下,期望機器學習模型能夠從完全任意的數據中學習是不合理的。數據需要以使模型的工作更容易的方式呈現給模型。
讓我們來看一個直觀的例子。假設您正在開發一個模型,該模型可以將時鐘的圖像作為輸入,并可以輸出一天的時間(參見圖4.3)。
如果您選擇使用圖像的原始像素作為輸入數據,那么您就會遇到一個機器學習的難題。你需要一個卷積神經網絡來解決它,你需要花費相當多的計算資源來訓練網絡。
但是,如果您已經在較高的層次上理解了這個問題(您已經理解了人類如何在時鐘面上讀取時間),那么您就可以為機器學習算法提供更好的輸入特性:例如,很容易寫五行代碼
Python腳本來跟蹤時鐘指針的黑色像素,并輸出每只指針尖端的(x, y)坐標。然后,一個簡單的機器學習算法可以學習將這些坐標與一天的適當時間相關聯。
你甚至可以更進一步:做一個坐標變換,把(x, y)坐標表示成關于圖像中心的極坐標。你的輸入將成為每個時鐘指針的角度。此時,您的特性使問題變得非常簡單,不需要機器學習;一個簡單的舍入操作和字典查找就足以恢復一天的大致時間。
這就是特征工程的本質:用更簡單的方式表達問題,從而使問題變得更容易。這通常需要深入了解問題。
在深度學習之前,特征工程曾經很重要,因為經典的淺層算法沒有足夠的假設空間來學習有用的特征。將數據呈現給算法的方式對算法的成功至關重要。例如,在卷積神經網絡成功之前MNIST數字分類問題,解決方案通常基于硬編碼的特征,如數字圖像中的線圈數,圖像中每個數字的高度,像素值的直方圖,等等。
幸運的是,
現代深度學習消除了對大多數特征工程的需求,因為神經網絡能夠從原始數據中自動提取有用的特征。
這是否意味著只要你使用深層神經網絡,你就不需要擔心特征工程?不,有兩個原因:
- 好的特性仍然允許您在使用更少的資源的同時更優雅地解決問題。例如,用卷積神經網絡解決時鐘面讀取的問題是荒謬的。
- 好的特性使您可以用更少的數據來解決問題。
深度學習模型自主學習特征的能力依賴于大量的訓練數據
;如果您只有幾個示例,那么它們特性中的信息值就變得至關重要。
4.4過擬合和欠擬合
在前一章的所有三個例子中——預測電影評論、主題分類和房價回歸——模型在被定義的驗證數據上的表現總是在幾個迭代之后達到頂峰,然后開始下降:模型很快開始過擬合訓練數據。過擬合發生在每一個機器學習問題。學習如何處理過擬合是掌握機器學習的關鍵。
機器學習的根本問題是優化和泛化之間的矛盾。優化是指調整模型以獲得對訓練數據的最佳性能(機器學習中的學習)的過程,而泛化是指訓練后的模型對以前從未見過的數據的表現。游戲的目標是得到好的泛化,當然,你不能控制泛化;只能根據訓練數據調整模型。
在訓練開始時,優化和泛化是相關的:訓練數據的損失越小,測試數據的損失就越小。當這種情況發生時,你的模型被認為是不合適的:仍有一些進展;網絡還沒有在訓練數據中對所有相關模式進行建模。但是,在對訓練數據進行一定數量的迭代之后,泛化停止了改進,驗證度量停止了,然后開始下降:模型開始過度擬合。也就是說,它開始學習特定于訓練數據的模式。但當涉及到新數據時,這些模式會產生誤導或不相關。
為了防止模型學習到在訓練數據中挖掘到誤導或不相關的模式,最好的解決方案是獲取更多的訓練數據。對更多數據進行訓練的模型自然會得到更好的推廣。如果這是不可能的,那么下一個最好的解決方案就是調整模型允許存儲的信息量,或者對允許存儲的信息添加約束。如果一個網絡只能記住少量的模式,那么優化過程就會迫使它把注意力集中在最突出的模式上,這樣就能更好地推廣。
用這種方法進行過擬合的過程稱為正則化(regularization)。讓我們回顧一些最常見的正則化技術,并將它們應用到實踐中,以改進3.4節中的電影分類模型。
4.4.1減小網絡規模
防止過擬合的最簡單方法是減小模型的大小:模型中可學習參數的數量(由層數和每層單元數決定)。
在深度學習中,模型中可學習參數的數量通常被稱為模型的容量。直觀地說,一個具有更多參數的模型具有更多的記憶能力(memorization capacity),因此可以很容易地學習到一個完美的字典式的訓練樣本與其目標之間的映射——一個沒有泛化能力的映射。例如,可以很容易的建立一個具有500,000個二進制參數的模型來學習MNIST訓練集中的每個數字的分類:我們每50,000個數字只需要10個二進制參數。(沒看懂表達的是啥,反正意思就是要說復雜參數任意導致過擬合訓練數據)但是這樣的模型對于新數字樣本的分類是無用的。始終牢記這一點:深度學習模型往往很好地適應訓練數據,但真正的挑戰是泛化,而不是擬合。
另一方面,如果網絡的記憶資源有限,它就無法輕易地學習這種映射;因此,為了使損失最小化,它將不得不學習對目標具有預測能力的壓縮表示——準確地說是我們感興趣的表示類型。與此同時,請記住,您應該使用具有足夠參數的模型以確保不會欠擬合:您的模型不應該缺乏記憶資源。在容量過大和容量不足之間需要找到一個折衷辦法。
不幸的是,沒有什么神奇的公式可以確定正確的層數或每個層的大小。您必須評估不同體系結構的數組(當然是在驗證集上,而不是在測試集上),以便為數據找到正確的模型大小。找到合適的模型大小的一般工作流程是從相對較少的層和參數開始,增加層的大小或添加新層,直到您看到驗證損失的回報遞減為止。
讓我們在電影評論分類網絡上試試,接下來顯示原始網絡。
Listing 4.3 Original model
from keras import models
from keras import layers
model = models.Sequential()
model.add(layers.Dense(16, activation='relu', input_shape=(10000,)))
model.add(layers.Dense(16, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
現在我們試著用這個更小的網絡來代替它。
Listing 4.4 Version of the model with lower capacity
model = models.Sequential()
model.add(layers.Dense(4, activation='relu', input_shape=(10000,)))
model.add(layers.Dense(4, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
圖4.4顯示了原始網絡和較小網絡的驗證損失的比較。點是較小網絡的驗證損失值,叉是初始網絡(記住,驗證損失越低越好)。
如您所見,較小的網絡開始過擬合的時間比參考網絡晚(在經歷了六個迭代而不是四個迭代之后),一旦開始過擬合,其性能下降的速度就會更慢。
現在,為了好玩,讓我們在這個基準上添加一個容量大得多的網絡——遠遠超過問題所要求的。
Listing 4.5 Version of the model with higher capacity
model = models.Sequential()
model.add(layers.Dense(512, activation='relu', input_shape=(10000,)))
model.add(layers.Dense(512, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
圖4.5顯示了與參考網絡相比,更大的網絡發生了什么。點是較大網絡的驗證損失值,叉號是初始網絡。
更大的網絡幾乎是在一個迭代之后就開始過擬合,而且過擬合程度要嚴重得多。它的驗證損失也更大。
同時,圖4.6顯示了兩個網絡的訓練損失。正如你所看到的,大網絡的訓練損失很快就接近于零。網絡的容量越大,建模訓練數據的速度就越快(導致了低的訓練損失),但是它越容易過度擬合(導致了訓練和驗證損失之間的巨大差異)。
4.4.2添加權重正則化
你可能對奧卡姆剃刀的原理很熟悉:對于某件事給出兩種解釋,最可能是正確的解釋是最簡單的一種——假設更少的那個。這一思想也適用于神經網絡學習的模型:給定一些訓練數據和網絡架構,多組權重值(多模型)可以解釋數據。更簡單的模型比復雜的模型更不容易過擬合。
在這個上下文中,一個簡單的模型是一個參數值分布具有較少熵的模型(或者一個參數較少的模型,如您在前一節中所見)。因此,減輕過擬合的一種常見方法是通過強制其權值取很小的值來限制網絡的復雜性,從而使權值的分布更有規律。這被稱為權值正則化
,它是通過增加網絡的損失函數來實現的,代價與擁有大權值相關。這種代價有兩種:
- L1 regularization— 增加的代價與權重系數(權重的L1范數)的絕對值成正比。
- L2 regularization— 增加的代價與權重系數(權重的L2范數)的平方成正比。L2正則化在神經網絡中也稱為權值衰減(weight decay)。別讓不同的名字迷惑了你:權值衰減在數學上和L2正則化是一樣的。
在Keras中,權重正則化是通過將權重正則化實例(weight regularizer instances)作為關鍵字參數傳遞到層來添加的。讓我們在電影評論分類網絡中加入L2權重正則化:
Listing 4.6 Adding L2 weight regularization to the model
from keras import regularizers
model = models.Sequential()
model.add(layers.Dense(16, kernel_regularizer=regularizers.l2(0.001),
activation='relu', input_shape=(10000,)))
model.add(layers.Dense(16, kernel_regularizer=regularizers.l2(0.001),
activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
l2(0.001)表示層的權重系數矩陣中的每一個系數都將給網絡的總損耗增加0.001 * weight_coefficient_value。注意,因為這個懲罰只在訓練時添加,所以這個網絡在訓練時的損失要比在測試時高得多。
圖4.7顯示了L2正則化懲罰的影響。正如您所看到的,具有L2正則化(dots)的模型比參考模型(cross)更抗過擬合,盡管兩個模型的參數數量相同。
作為L2正則化的一種替代方法,您可以使用以下Keras中的一個權重調節器。
Listing 4.7 Different weight regularizers available in Keras
4.4.3 添加dropout(丟失)
Dropout是神經網絡最有效和最常用的正則化技術之一,由Geoff Hinton和他在多倫多大學的學生開發。Dropout應用到一個layer上,包括隨機丟失(dropping out) (設置為0)訓練期間層的許多輸出特征。假設一個給定的層通常會在訓練過程中返回一個向量[0.2,0.5,1.3,0.8,1.1]。應用dropout之后,這個向量將會有幾個零項隨機分布:例如[0,0.5,1.3,0,1.1]。丟失率(dropout rate)是被歸零的特征的分數;它的值通常為0.2到0.5之間。在測試時,沒有單元會被丟失(dropped out);相反,該層的輸出值被縮減為與丟失率相等的因子,以平衡比訓練時更多的單元處于活動狀態這一事實。
考慮一個Numpy矩陣,它包含一個層的輸出layer_output,形狀為(batch_size, feature)。在訓練時,我們隨機將矩陣中值的一部分歸零:
# At training time, drops out 50% of the units in the output
layer_output *= np.random.randint(0, high=2, size=layer_output.shape)
在測試時,我們通過丟失率降低輸出。這里是0.5 (因為我們之前減少了一半的單元):
# At test time
layer_output *= 0.5
注意,這個過程可以通過在訓練時執行操作和在測試時保持輸出不變來實現,這通常是它在實踐中實現的方式(參見圖4.8):
這種方法似乎很奇怪,也很隨意。為什么這有助于減少過擬合?
Hinton說,他的靈感來自于銀行使用的一種防止欺詐的機制。用他自己的話來說,“我去了我的銀行。出納員們不停地變換,我問其中一個為什么。他說他不知道,但他們經常移動。我想一定是因為要想成功詐騙銀行需要員工之間的合作。這讓我意識到,在每個例子中隨機移除不同的神經元子集,可以防止陰謀,從而減少過擬合。核心思想是在一個層的輸出值中引入噪聲可以打破那些不重要的偶發事件模式(Hinton稱之為陰謀),如果沒有噪聲存在,網絡就會開始記憶這些模式。
在Keras中,您可以通過dropout層在網絡中引入dropout,它適用于它前面的層的輸出:
model.add(layers.Dropout(0.5))
讓我們在IMDB網絡中添加兩個Dropout層,看看它們在減少過擬合方面做得如何。
Listing 4.8 Adding dropout to the IMDB network
model = models.Sequential()
model.add(layers.Dense(16, activation='relu', input_shape=(10000,)))
model.add(layers.Dropout(0.5))
model.add(layers.Dense(16, activation='relu'))
model.add(layers.Dropout(0.5))
model.add(layers.Dense(1, activation='sigmoid'))
圖4.9顯示了結果的圖表。同樣,這是對參考網絡的明顯改進。
綜上所述,以下是防止神經網絡過擬合最常見的方法:
- 得到更多的訓練數據。
- 減少網絡的能力。
- 添加權值正規化。
- 添加Dropout。
4.5機器學習的通用工作流
在本節中,我們將展示一個通用藍圖,您可以使用它來攻破和解決任何機器學習問題。藍圖把你在這一章學到的概念聯系在一起:問題定義,評估,特性工程,和解決過擬合。
4.5.1定義問題并組裝數據集
首先,您必須定義手邊的問題:
- 您的輸入數據是什么?你想預測什么?只有當你有可用的訓練數據時,你才能學會預測:例如,只有當你有可用的電影評論和情感注釋時,你才能學會對電影評論的情緒進行分類。因此,數據可用性通常是這個階段的限制因素(除非你有辦法付錢讓別人幫你收集數據)。
- 你面臨什么樣的問題?是二分類嗎?多分類?標量回歸?向量回歸?多分類多標簽分類問題?
其他的東西,比如聚類、生成或強化學習?識別問題類型將指導您選擇模型體系結構、損失函數等。
除非您知道您的輸入和輸出是什么,以及您將使用什么數據,否則您無法進入下一個階段。注意你在這個階段所做的假設: - 你假設你的輸出可以通過你的輸入來預測。
- 你假設您的可用數據具有足夠的信息來了解輸入和輸出之間的關系。
在你有一個可行的模型之前,這些僅僅是假設,等待著被證實或失效。不是所有的問題都能解決;僅僅因為你裝配了輸入X和目標Y的樣本并不意味著X包含足夠的信息來預測。例如,如果你試圖預測某只股票在股票市場上的走勢,考慮到它最近的歷史價格,你不太可能成功,因為歷史價格不包含太多的預測信息。
你應該知道的一類不可解問題是非平穩問題(nonstationary problems)。假設您正在嘗試構建一個服裝推薦引擎,您正在對它為期一個月的數據進行訓練(8月份),并且希望在冬季開始生成推薦。一個大問題是,人們購買的服裝種類隨季節而變化:購買服裝在幾個月的時間里是一種非固定的現象。你試圖建立的模型會隨著時間而改變。在這種情況下,正確的做法是不斷地根據最近的數據重新訓練您的模型,或者在問題穩定的時間段收集數據。對于像買衣服這樣的周期性問題,幾年的數據就足以捕捉到季節的變化——但是記住把一年中的時間作為你的模型的輸入!(備注:機器學習沒法解決非平穩序列,其實也好理解,非平穩序列中,你的訓練數據與用來預測的數據間的關聯信息應該很少。當然例子中如果在同一個季節內部的預測,那就屬于一個平穩序列了)
記住,機器學習只能用于記憶訓練數據中的模式。
你只能認出你以前看到的東西。通過對過去數據的機器學習來預測未來,是在假設未來會像過去一樣。通常情況并非如此。
4.5.2選擇成功的標準
要控制某事,你需要能夠觀察它。為了獲得成功,你必須定義你所說的成功是什么——accuracy?Precision和recall?客戶保留利率?您的成功度量標準將指導損失函數的選擇:您的模型將如何優化。它應該直接與你的更高層次的目標相一致,比如你事業的成功。
對于均衡分類問題,每個類都是等概率的,receiver operating特性曲線(ROC AUC)下的accuracy和面積是常用的度量標準。對于分類不平衡的問題,可以使用precision和recall。對于排序問題或多標簽分類,可以使用平均精度(mean average precision)。而且,需要定義自己的標準來衡量成功的情況并不少見。要了解機器學習成功指標的多樣性以及它們如何與不同的問題領域相關聯,瀏覽data science com網站是很有幫助的。
4.5.3 決策評估方法
一旦你知道你的目標是什么,你必須確定如何衡量你目前的進展。我們之前回顧了三個常見的評估方案:
- 保持一個保留驗證集的方法:當你有足夠的數據
- 執行K-fold cross-validation:當你只有少量的樣本用于保留驗證時,該選擇是明知可靠的選擇
- 執行迭代K-fold驗證:在可用數據很少的情況下執行高度精確的模型評估
選一個吧。在大多數情況下,第一種方法都能很好地工作。
4.5.4 準備數據
一旦你知道你在訓練什么,你在優化什么,以及如何評估你的方法,你就幾乎準備好開始訓練模型了。但首先,你應該以一種可以被輸入機器學習模型的方式來格式化你的數據——在這里,我們假設一個深層神經網絡:
- 如前所述,數據應該格式化為張量。
- 張量中的值通常應該按比例縮小到較小的值:例如在[-1,1]或[0,1]之間。
- 如果不同的特征采用不同范圍(異構數據)的值,則應該對數據進行歸一化(normalized)
- 可能需要一些特性工程,特別是對于小數據問題
一旦輸入數據和目標數據的張量就緒,就可以開始訓練模型。
4.5.5開發一個比基線更好的模型
您在此階段的目標是實現統計能力(statistical power):即開發一個能夠超過靜默基線的小型模型。在MNIST digit-classification示例中,任何accuracy達到0.1以上的都可以稱為具有統計能力;在IMDB示例中,它的accuracy要求大于0.5。
注意,實現統計能力并不總是可能的。如果在嘗試了多個合理的體系結構之后,您不能打破一個隨機的基線,那么您所問問題的答案可能不會出現在輸入數據中。記住你做了兩個假設:
- 你假設你的輸出可以預測給定輸入。
- 您假設可用的數據足以提供足夠的信息來了解輸入和輸出之間的關系。
很可能這些假設是錯誤的,在這種情況下,你必須回到繪圖板(就是說要重新開始設計)。
假設一切順利,您需要做出三個關鍵選擇來構建您的第一個工作模型:
- 最后一層的激活函數(Last-layer activation):它建立了網絡輸出的有用約束。例如,IMDB分類示例在最后一層使用了sigmoid;回歸示例沒有在最后一層使用任何激活函數等等。
- 損失函數——這應該與您試圖解決的問題類型相匹配。例如,IMDB示例使用binary_crossentropy,回歸示例使用mse等等。
-
優化配置——您將使用什么優化器?它的學習率是多少?在大多數情況下,使用rmsprop,并配合它的默認學習率是安全的。
關于損失函數的選擇,請注意,并不是總是能夠直接優化用于度量問題成功與否的度量標準。有時,沒有簡單的方法可以將度量轉換為損失函數;畢竟,損失函數只需要給定一小批(mini-batch)數據就可以計算(理想情況下,損失函數只需要計算單個數據點),并且必須是可微的(否則,您不能使用反向傳播來訓練網絡)。例如,廣泛使用的分類度量ROC AUC不能直接進行優化。因此,在分類任務中,通常會優化ROC AUC的代理度量,比如交叉熵。一般來說,你可以希望交叉熵越低,ROC AUC就越高。
表4.1為模型選擇正確的最后一層激活和損失函數
4.5.6 擴展:開發一個過擬合的模型
一旦你得到了一個具有統計能力的模型,問題就變成了,你的模型是否足夠強大?它是否有足夠的層和參數來正確地建模手邊的問題?例如,一個只有一個隱藏層和兩個單元的網絡在MNIST上具有統計能力,但不足以很好地解決這個問題。記住,機器學習中的廣義張量是在優化和泛化之間;理想的模型是在不完全擬合和過度擬合之間的邊界;在undercapacity和overcapacity之間。想弄清楚這條邊界在哪里,你必須先穿過它。
為了弄清楚您需要多大的模型,您必須開發一個過擬合的模型。
這很簡單:
- 添加層
- 使得層更大
- 在更多的epochs中訓練
始終監控訓練損失和驗證損失,以及您關心的任何指標的訓練和驗證值。當您看到模型在驗證數據上的性能開始下降時,您已經實現了過擬合。
下一個階段是開始對模型進行正則化(regularizing)和調優,以盡可能接近既欠擬合也不過擬合的理想模型。
4.5.7模型正則化,調整超參數
這個步驟將花費最多的時間:您將反復修改模型,訓練它,評估您的驗證數據(此時不是測試數據),再次修改它,然后重復,直到模型達到最佳狀態。以下是一些你應該嘗試的事情:
- 添加dropout
- 嘗試不同的架構:添加或移除層
- 添加L1和L2正則化(regularization)
- 嘗試不同的超參數(例如每層單元的數量或優化器的學習率)來找到最佳配置。
- 可選地,迭代特性工程:添加新特征,或刪除那些看起來不提供信息的特征。
注意以下內容:每次使用驗證過程的反饋來優化模型時,您都會將驗證過程的信息泄漏到模型中。重復幾次,這是無害的;但是在多次迭代中系統地完成,最終會導致您的模型過擬合驗證過程(即使模型沒有直接針對任何驗證數據進行訓練)。這使得評估過程不那么可靠。
一旦你建立了一個令人滿意的模型配置,您可以在所有可用數據(訓練和驗證)上訓練您的最終產品模型,并在測試集中最后一次評估它。如果測試集上的性能明顯低于驗證數據上的性能,這可能意味著您的驗證過程根本不可靠,或者您在調優模型參數時開始度擬合驗證數據。在這種情況下,您可能希望切換到更可靠的評估協議(例如迭代K-fold驗證)。
章節總結
- 定義手頭的問題和要訓練的數據。收集這些數據,或者在需要時用標簽對其進行注釋。
- 選擇在你的問題上如何衡量成功。您將在驗證數據上監視哪些指標?
- 確定評估方法:保留驗證?K-fold驗證?應該使用哪一部分數據進行驗證?
- 開發第一個比基本基線更好的模型:一個具有統計能力的模型。
- 開發一個過擬合的模型。
- 根據驗證數據的性能,調整模型并調優其超參數。很多機器學習研究傾向于只關注這一步,但要把大局記在心里。
備注:
1,用sigmoid作為激活函數,為什么往往損失函數選用binary_crossentropy
參考地址:https://blog.csdn.net/wtq1993/article/details/51741471
2,softmax與categorical_crossentropy的關系,以及sigmoid與bianry_crossentropy的關系。
參考地址:https://www.zhihu.com/question/36307214
3,各大損失函數的定義:MSE,MAE,MAPE,hinge,squad_hinge,binary_crossentropy等
參考地址:https://www.cnblogs.com/laurdawn/p/5841192.html