'代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則'

人工智能 深度學習 數據庫 CNN 讀芯術 2019-08-30
"
全文共5505字,預計學習時長11分鐘或更長
"
全文共5505字,預計學習時長11分鐘或更長
代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

圖片來源:Unsplash/Dewang Gupta

通過本文的學習, 我們可以瞭解如何著手構建初始神經網絡, 學習經驗法則,比如:隱藏層的數量、節點的數量、激活並觀察其在TensorFlow2中的應用。


深度學習提供了種類繁多的模型。有了它們,就可以建立非常精確的預測模型。然而,由於設置參數數量巨大且種類繁多,要找到出發點會有些困難。


本文將帶領大家找到構建神經網絡的出發點,具體來說是以構建多層感知器為例子。雖然使用了多層感知器為例,但大多數法則都是普遍適用於神經網絡構建的。


整體思路是通過經驗法則先建立第一個神經網絡模型。如果第一個模型能合理運行(達到最低可接受精確度),就對其進行調整與優化。否則,就最好去查看數據和問題所在,或採用其他方法。


本文將介紹:

· 建立神經網絡的經驗法則。

· TensorFlow2中二進制分類的實施代碼。


"
全文共5505字,預計學習時長11分鐘或更長
代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

圖片來源:Unsplash/Dewang Gupta

通過本文的學習, 我們可以瞭解如何著手構建初始神經網絡, 學習經驗法則,比如:隱藏層的數量、節點的數量、激活並觀察其在TensorFlow2中的應用。


深度學習提供了種類繁多的模型。有了它們,就可以建立非常精確的預測模型。然而,由於設置參數數量巨大且種類繁多,要找到出發點會有些困難。


本文將帶領大家找到構建神經網絡的出發點,具體來說是以構建多層感知器為例子。雖然使用了多層感知器為例,但大多數法則都是普遍適用於神經網絡構建的。


整體思路是通過經驗法則先建立第一個神經網絡模型。如果第一個模型能合理運行(達到最低可接受精確度),就對其進行調整與優化。否則,就最好去查看數據和問題所在,或採用其他方法。


本文將介紹:

· 建立神經網絡的經驗法則。

· TensorFlow2中二進制分類的實施代碼。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

神經網絡


神經網絡在卷積神經網絡(CNN)、遞歸神經網絡(RNN)等領域都取得了巨大進步。且隨著時間的推移,每個神經網絡的幾個亞型都得到了發展。正是這一個個的進步,成功地提高了模型的預測能力。


但與此同時,找到模型構建的出發點也變得更難了。


每個神經網絡模型都是不同的,不同的模型有不同的特點和功能,所以在這種情況下,選擇適用的模型變得像在林立的廣告牌中選擇合適的商品一樣困難。


接下來,我們將利用經驗法則構建第一個模型,以克服這些干擾。


"
全文共5505字,預計學習時長11分鐘或更長
代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

圖片來源:Unsplash/Dewang Gupta

通過本文的學習, 我們可以瞭解如何著手構建初始神經網絡, 學習經驗法則,比如:隱藏層的數量、節點的數量、激活並觀察其在TensorFlow2中的應用。


深度學習提供了種類繁多的模型。有了它們,就可以建立非常精確的預測模型。然而,由於設置參數數量巨大且種類繁多,要找到出發點會有些困難。


本文將帶領大家找到構建神經網絡的出發點,具體來說是以構建多層感知器為例子。雖然使用了多層感知器為例,但大多數法則都是普遍適用於神經網絡構建的。


整體思路是通過經驗法則先建立第一個神經網絡模型。如果第一個模型能合理運行(達到最低可接受精確度),就對其進行調整與優化。否則,就最好去查看數據和問題所在,或採用其他方法。


本文將介紹:

· 建立神經網絡的經驗法則。

· TensorFlow2中二進制分類的實施代碼。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

神經網絡


神經網絡在卷積神經網絡(CNN)、遞歸神經網絡(RNN)等領域都取得了巨大進步。且隨著時間的推移,每個神經網絡的幾個亞型都得到了發展。正是這一個個的進步,成功地提高了模型的預測能力。


但與此同時,找到模型構建的出發點也變得更難了。


每個神經網絡模型都是不同的,不同的模型有不同的特點和功能,所以在這種情況下,選擇適用的模型變得像在林立的廣告牌中選擇合適的商品一樣困難。


接下來,我們將利用經驗法則構建第一個模型,以克服這些干擾。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

經驗法則


在形形色色的神經網絡中,多層感知器是通往深度學習的敲門磚。因此,當學習或構建一個深度學習領域的模型時,多層感知器就是很好的出發點。


以下是構建多層感知器的經驗法則,且大多數法則都適用於其他深度學習模型。


1. 層數:從兩個隱藏層開始(這其中不包含最後一層)。

2. 中間層的節點數量(大小):是2的倍數,如4,8,16,32……第一層的節點數應該是輸入數據特徵數量的一半左右。下一層的大小是上一層的一半。

3. 分類層最後一層的節點數量(大小):如果是二進制分類,則節點大小為一。對於多類分類器,節點大小等於類的數量。

4. 迴歸層最後一層的大小:如果是單響應,最後一層的大小為1。對於多響應迴歸,最後一層的大小等於響應的數量。

5. 激活中間層,使用Relu激活函數。

6. 激活最後一層:如果是二進制分類,使用sigmoid函數,多類分類器使用softmax函數,迴歸則使用linear函數。對於自動編碼器,如果輸入數據是連續的,使用linear函數進行激活。對於二進制或多級分類輸入,使用sigmoid或softmax函數。

7. Dropout層:除了輸入層以外,在其他每個層都加設Dropout(如果單獨定義輸入層)。將Dropout率設置為0.5。Dropout率大於0.5時結果會適得其反。因此如果覺得0.5會使太多的節點正則化,可以選擇增加層的大小,而不是將Dropout率設置在0.5以下。筆者不喜歡在輸入層設置任何Dropout。但如果認為有必要這樣做,請把Dropout率設置在0.2以下。

8. 數據預處理:假設預測器X是數字,且已經將所有分類列轉化成了獨熱編碼。那麼就可以在進行模型訓練前使用MinMaxScalar對數據進行大小預處理。如果MMS不奏效,就在相同的數據庫中使用StandardScalar對數據進行標準化處理。整個數據處理過程不對y進行操作。

9. 將數據分為訓練數據,有效數據與測試數據:

使用sklearn.model_selection的train_test_split語句。具體操作見下方示例。

10. 類權重:如果數據不平衡,可以在model.fit中設置類權重以平衡損失。對於二進制分類器,權重應為:{0:1的數量/數據大小,1:0的數量/數據大小}。對於極不平衡數據(罕見事件),類權重可能不起作用,請小心添加使用。

11. 優化器:使用adam優化器,應用其默認學習率。

12. 分類損失:對於二進制分類,使用binary_crossentropy.對於多類別分類,如果標籤是獨熱編碼而成的,使用categorical_crossentropy。當標籤都是整數時,使用sparse_categorical_crossentropy 。

13. 迴歸損失:使用均方誤差(mse)函數。

14. 分類指標:使用accuracy顯示正確分類的百分比。對不平衡數據,也要加上tf.keras.metrics.Recall() 和 tf.keras.metrics.FalsePositives().

15. 迴歸指標:使用tf.keras.metrics.RootMeanSquaredError()。

16. 訓練週期:先從20開始,看模型訓練是否顯示出損失的減少,或任何在精確度上的提高。如果20個週期還沒有一點成果就換個方法。如果得到了些許成果,就把訓練週期提升到100。

17. 批處理大小:將批處理大小選擇為2的倍數,對於不平衡數據,通常選用較大值,如128,否則一般都從16開始選用。


"
全文共5505字,預計學習時長11分鐘或更長
代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

圖片來源:Unsplash/Dewang Gupta

通過本文的學習, 我們可以瞭解如何著手構建初始神經網絡, 學習經驗法則,比如:隱藏層的數量、節點的數量、激活並觀察其在TensorFlow2中的應用。


深度學習提供了種類繁多的模型。有了它們,就可以建立非常精確的預測模型。然而,由於設置參數數量巨大且種類繁多,要找到出發點會有些困難。


本文將帶領大家找到構建神經網絡的出發點,具體來說是以構建多層感知器為例子。雖然使用了多層感知器為例,但大多數法則都是普遍適用於神經網絡構建的。


整體思路是通過經驗法則先建立第一個神經網絡模型。如果第一個模型能合理運行(達到最低可接受精確度),就對其進行調整與優化。否則,就最好去查看數據和問題所在,或採用其他方法。


本文將介紹:

· 建立神經網絡的經驗法則。

· TensorFlow2中二進制分類的實施代碼。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

神經網絡


神經網絡在卷積神經網絡(CNN)、遞歸神經網絡(RNN)等領域都取得了巨大進步。且隨著時間的推移,每個神經網絡的幾個亞型都得到了發展。正是這一個個的進步,成功地提高了模型的預測能力。


但與此同時,找到模型構建的出發點也變得更難了。


每個神經網絡模型都是不同的,不同的模型有不同的特點和功能,所以在這種情況下,選擇適用的模型變得像在林立的廣告牌中選擇合適的商品一樣困難。


接下來,我們將利用經驗法則構建第一個模型,以克服這些干擾。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

經驗法則


在形形色色的神經網絡中,多層感知器是通往深度學習的敲門磚。因此,當學習或構建一個深度學習領域的模型時,多層感知器就是很好的出發點。


以下是構建多層感知器的經驗法則,且大多數法則都適用於其他深度學習模型。


1. 層數:從兩個隱藏層開始(這其中不包含最後一層)。

2. 中間層的節點數量(大小):是2的倍數,如4,8,16,32……第一層的節點數應該是輸入數據特徵數量的一半左右。下一層的大小是上一層的一半。

3. 分類層最後一層的節點數量(大小):如果是二進制分類,則節點大小為一。對於多類分類器,節點大小等於類的數量。

4. 迴歸層最後一層的大小:如果是單響應,最後一層的大小為1。對於多響應迴歸,最後一層的大小等於響應的數量。

5. 激活中間層,使用Relu激活函數。

6. 激活最後一層:如果是二進制分類,使用sigmoid函數,多類分類器使用softmax函數,迴歸則使用linear函數。對於自動編碼器,如果輸入數據是連續的,使用linear函數進行激活。對於二進制或多級分類輸入,使用sigmoid或softmax函數。

7. Dropout層:除了輸入層以外,在其他每個層都加設Dropout(如果單獨定義輸入層)。將Dropout率設置為0.5。Dropout率大於0.5時結果會適得其反。因此如果覺得0.5會使太多的節點正則化,可以選擇增加層的大小,而不是將Dropout率設置在0.5以下。筆者不喜歡在輸入層設置任何Dropout。但如果認為有必要這樣做,請把Dropout率設置在0.2以下。

8. 數據預處理:假設預測器X是數字,且已經將所有分類列轉化成了獨熱編碼。那麼就可以在進行模型訓練前使用MinMaxScalar對數據進行大小預處理。如果MMS不奏效,就在相同的數據庫中使用StandardScalar對數據進行標準化處理。整個數據處理過程不對y進行操作。

9. 將數據分為訓練數據,有效數據與測試數據:

使用sklearn.model_selection的train_test_split語句。具體操作見下方示例。

10. 類權重:如果數據不平衡,可以在model.fit中設置類權重以平衡損失。對於二進制分類器,權重應為:{0:1的數量/數據大小,1:0的數量/數據大小}。對於極不平衡數據(罕見事件),類權重可能不起作用,請小心添加使用。

11. 優化器:使用adam優化器,應用其默認學習率。

12. 分類損失:對於二進制分類,使用binary_crossentropy.對於多類別分類,如果標籤是獨熱編碼而成的,使用categorical_crossentropy。當標籤都是整數時,使用sparse_categorical_crossentropy 。

13. 迴歸損失:使用均方誤差(mse)函數。

14. 分類指標:使用accuracy顯示正確分類的百分比。對不平衡數據,也要加上tf.keras.metrics.Recall() 和 tf.keras.metrics.FalsePositives().

15. 迴歸指標:使用tf.keras.metrics.RootMeanSquaredError()。

16. 訓練週期:先從20開始,看模型訓練是否顯示出損失的減少,或任何在精確度上的提高。如果20個週期還沒有一點成果就換個方法。如果得到了些許成果,就把訓練週期提升到100。

17. 批處理大小:將批處理大小選擇為2的倍數,對於不平衡數據,通常選用較大值,如128,否則一般都從16開始選用。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


給高級從業人員的一些額外經驗法則


1. 振盪損耗:如果在訓練中遇到振盪損耗,則是由趨同問題導致的。遇到這種問題時,可以嘗試減小學習率和/或更改批處理大小。

2. 過採樣和欠採樣:如果數據不平衡,使用imblearn.over_sampling中的SMOTE算法。

3. 曲線移動:如果需要進行位移預測,比如早期預測,可以使用曲線移動。下方展示了curve_shift的執行。

4. 自定義度量:假陽率是不平衡二進制分類中的一個重要度量。可以如下方給出的class FalsePositiveRate()的執行所示,構建假陽率度量和其他自定義度量。

5. Selu激活函數:在現今所有的激活函數中,selu激活函數被認為是最好的。我並不完全同意這一點,但如果想要使用selu激活函數,可以使用kernel_initializer=’lecun_normal’和 AlphaDropout.在AlphaDropout中使用0.1比率,AlphaDropout(0.1) 。執行實例在下方給出。


"
全文共5505字,預計學習時長11分鐘或更長
代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

圖片來源:Unsplash/Dewang Gupta

通過本文的學習, 我們可以瞭解如何著手構建初始神經網絡, 學習經驗法則,比如:隱藏層的數量、節點的數量、激活並觀察其在TensorFlow2中的應用。


深度學習提供了種類繁多的模型。有了它們,就可以建立非常精確的預測模型。然而,由於設置參數數量巨大且種類繁多,要找到出發點會有些困難。


本文將帶領大家找到構建神經網絡的出發點,具體來說是以構建多層感知器為例子。雖然使用了多層感知器為例,但大多數法則都是普遍適用於神經網絡構建的。


整體思路是通過經驗法則先建立第一個神經網絡模型。如果第一個模型能合理運行(達到最低可接受精確度),就對其進行調整與優化。否則,就最好去查看數據和問題所在,或採用其他方法。


本文將介紹:

· 建立神經網絡的經驗法則。

· TensorFlow2中二進制分類的實施代碼。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

神經網絡


神經網絡在卷積神經網絡(CNN)、遞歸神經網絡(RNN)等領域都取得了巨大進步。且隨著時間的推移,每個神經網絡的幾個亞型都得到了發展。正是這一個個的進步,成功地提高了模型的預測能力。


但與此同時,找到模型構建的出發點也變得更難了。


每個神經網絡模型都是不同的,不同的模型有不同的特點和功能,所以在這種情況下,選擇適用的模型變得像在林立的廣告牌中選擇合適的商品一樣困難。


接下來,我們將利用經驗法則構建第一個模型,以克服這些干擾。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

經驗法則


在形形色色的神經網絡中,多層感知器是通往深度學習的敲門磚。因此,當學習或構建一個深度學習領域的模型時,多層感知器就是很好的出發點。


以下是構建多層感知器的經驗法則,且大多數法則都適用於其他深度學習模型。


1. 層數:從兩個隱藏層開始(這其中不包含最後一層)。

2. 中間層的節點數量(大小):是2的倍數,如4,8,16,32……第一層的節點數應該是輸入數據特徵數量的一半左右。下一層的大小是上一層的一半。

3. 分類層最後一層的節點數量(大小):如果是二進制分類,則節點大小為一。對於多類分類器,節點大小等於類的數量。

4. 迴歸層最後一層的大小:如果是單響應,最後一層的大小為1。對於多響應迴歸,最後一層的大小等於響應的數量。

5. 激活中間層,使用Relu激活函數。

6. 激活最後一層:如果是二進制分類,使用sigmoid函數,多類分類器使用softmax函數,迴歸則使用linear函數。對於自動編碼器,如果輸入數據是連續的,使用linear函數進行激活。對於二進制或多級分類輸入,使用sigmoid或softmax函數。

7. Dropout層:除了輸入層以外,在其他每個層都加設Dropout(如果單獨定義輸入層)。將Dropout率設置為0.5。Dropout率大於0.5時結果會適得其反。因此如果覺得0.5會使太多的節點正則化,可以選擇增加層的大小,而不是將Dropout率設置在0.5以下。筆者不喜歡在輸入層設置任何Dropout。但如果認為有必要這樣做,請把Dropout率設置在0.2以下。

8. 數據預處理:假設預測器X是數字,且已經將所有分類列轉化成了獨熱編碼。那麼就可以在進行模型訓練前使用MinMaxScalar對數據進行大小預處理。如果MMS不奏效,就在相同的數據庫中使用StandardScalar對數據進行標準化處理。整個數據處理過程不對y進行操作。

9. 將數據分為訓練數據,有效數據與測試數據:

使用sklearn.model_selection的train_test_split語句。具體操作見下方示例。

10. 類權重:如果數據不平衡,可以在model.fit中設置類權重以平衡損失。對於二進制分類器,權重應為:{0:1的數量/數據大小,1:0的數量/數據大小}。對於極不平衡數據(罕見事件),類權重可能不起作用,請小心添加使用。

11. 優化器:使用adam優化器,應用其默認學習率。

12. 分類損失:對於二進制分類,使用binary_crossentropy.對於多類別分類,如果標籤是獨熱編碼而成的,使用categorical_crossentropy。當標籤都是整數時,使用sparse_categorical_crossentropy 。

13. 迴歸損失:使用均方誤差(mse)函數。

14. 分類指標:使用accuracy顯示正確分類的百分比。對不平衡數據,也要加上tf.keras.metrics.Recall() 和 tf.keras.metrics.FalsePositives().

15. 迴歸指標:使用tf.keras.metrics.RootMeanSquaredError()。

16. 訓練週期:先從20開始,看模型訓練是否顯示出損失的減少,或任何在精確度上的提高。如果20個週期還沒有一點成果就換個方法。如果得到了些許成果,就把訓練週期提升到100。

17. 批處理大小:將批處理大小選擇為2的倍數,對於不平衡數據,通常選用較大值,如128,否則一般都從16開始選用。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


給高級從業人員的一些額外經驗法則


1. 振盪損耗:如果在訓練中遇到振盪損耗,則是由趨同問題導致的。遇到這種問題時,可以嘗試減小學習率和/或更改批處理大小。

2. 過採樣和欠採樣:如果數據不平衡,使用imblearn.over_sampling中的SMOTE算法。

3. 曲線移動:如果需要進行位移預測,比如早期預測,可以使用曲線移動。下方展示了curve_shift的執行。

4. 自定義度量:假陽率是不平衡二進制分類中的一個重要度量。可以如下方給出的class FalsePositiveRate()的執行所示,構建假陽率度量和其他自定義度量。

5. Selu激活函數:在現今所有的激活函數中,selu激活函數被認為是最好的。我並不完全同意這一點,但如果想要使用selu激活函數,可以使用kernel_initializer=’lecun_normal’和 AlphaDropout.在AlphaDropout中使用0.1比率,AlphaDropout(0.1) 。執行實例在下方給出。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

TensorFlow 2中的多層感知器(MLP)實例


在這個執行中,可以看到上述經驗法則中所提到的內容的實際操作。


上述執行是在TensorFlow 2中完成的。強烈建議所有人都轉戰使用TensorFlow 2。它不僅擁有Keras所具有的簡易性,還顯著地提升了計算效率。


本文目的並不是嘗試找到最好的模型,而是學習神經網絡的實現。不會為了簡化過程而跳過任何步驟。相反,本文給出的步驟都很詳細,以幫助讀者的直接應用。



%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as snsimport pandas as pd
import numpy as np
from pylab import rcParamsfrom collections import Counterimport tensorflow as tffrom tensorflow.keras import optimizers
from tensorflow.keras.models import Model, load_model, Sequential
from tensorflow.keras.layers import Input, Dense, Dropout, AlphaDropout
from tensorflow.keras.callbacks import ModelCheckpoint, TensorBoardfrom sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, precision_recall_curve
from sklearn.metrics import recall_score, classification_report, auc, roc_curve
from sklearn.metrics import precision_recall_fscore_support, f1_scorefrom numpy.random import seed
seed(1)SEED = 123 #used to help randomly select the data points
DATA_SPLIT_PCT = 0.2rcParams['figure.figsize'] = 8, 6
LABELS = ["Normal","Break"]


測試是否使用了正確的TensorFlow版本,運行:tf.__version__

"
全文共5505字,預計學習時長11分鐘或更長
代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

圖片來源:Unsplash/Dewang Gupta

通過本文的學習, 我們可以瞭解如何著手構建初始神經網絡, 學習經驗法則,比如:隱藏層的數量、節點的數量、激活並觀察其在TensorFlow2中的應用。


深度學習提供了種類繁多的模型。有了它們,就可以建立非常精確的預測模型。然而,由於設置參數數量巨大且種類繁多,要找到出發點會有些困難。


本文將帶領大家找到構建神經網絡的出發點,具體來說是以構建多層感知器為例子。雖然使用了多層感知器為例,但大多數法則都是普遍適用於神經網絡構建的。


整體思路是通過經驗法則先建立第一個神經網絡模型。如果第一個模型能合理運行(達到最低可接受精確度),就對其進行調整與優化。否則,就最好去查看數據和問題所在,或採用其他方法。


本文將介紹:

· 建立神經網絡的經驗法則。

· TensorFlow2中二進制分類的實施代碼。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

神經網絡


神經網絡在卷積神經網絡(CNN)、遞歸神經網絡(RNN)等領域都取得了巨大進步。且隨著時間的推移,每個神經網絡的幾個亞型都得到了發展。正是這一個個的進步,成功地提高了模型的預測能力。


但與此同時,找到模型構建的出發點也變得更難了。


每個神經網絡模型都是不同的,不同的模型有不同的特點和功能,所以在這種情況下,選擇適用的模型變得像在林立的廣告牌中選擇合適的商品一樣困難。


接下來,我們將利用經驗法則構建第一個模型,以克服這些干擾。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

經驗法則


在形形色色的神經網絡中,多層感知器是通往深度學習的敲門磚。因此,當學習或構建一個深度學習領域的模型時,多層感知器就是很好的出發點。


以下是構建多層感知器的經驗法則,且大多數法則都適用於其他深度學習模型。


1. 層數:從兩個隱藏層開始(這其中不包含最後一層)。

2. 中間層的節點數量(大小):是2的倍數,如4,8,16,32……第一層的節點數應該是輸入數據特徵數量的一半左右。下一層的大小是上一層的一半。

3. 分類層最後一層的節點數量(大小):如果是二進制分類,則節點大小為一。對於多類分類器,節點大小等於類的數量。

4. 迴歸層最後一層的大小:如果是單響應,最後一層的大小為1。對於多響應迴歸,最後一層的大小等於響應的數量。

5. 激活中間層,使用Relu激活函數。

6. 激活最後一層:如果是二進制分類,使用sigmoid函數,多類分類器使用softmax函數,迴歸則使用linear函數。對於自動編碼器,如果輸入數據是連續的,使用linear函數進行激活。對於二進制或多級分類輸入,使用sigmoid或softmax函數。

7. Dropout層:除了輸入層以外,在其他每個層都加設Dropout(如果單獨定義輸入層)。將Dropout率設置為0.5。Dropout率大於0.5時結果會適得其反。因此如果覺得0.5會使太多的節點正則化,可以選擇增加層的大小,而不是將Dropout率設置在0.5以下。筆者不喜歡在輸入層設置任何Dropout。但如果認為有必要這樣做,請把Dropout率設置在0.2以下。

8. 數據預處理:假設預測器X是數字,且已經將所有分類列轉化成了獨熱編碼。那麼就可以在進行模型訓練前使用MinMaxScalar對數據進行大小預處理。如果MMS不奏效,就在相同的數據庫中使用StandardScalar對數據進行標準化處理。整個數據處理過程不對y進行操作。

9. 將數據分為訓練數據,有效數據與測試數據:

使用sklearn.model_selection的train_test_split語句。具體操作見下方示例。

10. 類權重:如果數據不平衡,可以在model.fit中設置類權重以平衡損失。對於二進制分類器,權重應為:{0:1的數量/數據大小,1:0的數量/數據大小}。對於極不平衡數據(罕見事件),類權重可能不起作用,請小心添加使用。

11. 優化器:使用adam優化器,應用其默認學習率。

12. 分類損失:對於二進制分類,使用binary_crossentropy.對於多類別分類,如果標籤是獨熱編碼而成的,使用categorical_crossentropy。當標籤都是整數時,使用sparse_categorical_crossentropy 。

13. 迴歸損失:使用均方誤差(mse)函數。

14. 分類指標:使用accuracy顯示正確分類的百分比。對不平衡數據,也要加上tf.keras.metrics.Recall() 和 tf.keras.metrics.FalsePositives().

15. 迴歸指標:使用tf.keras.metrics.RootMeanSquaredError()。

16. 訓練週期:先從20開始,看模型訓練是否顯示出損失的減少,或任何在精確度上的提高。如果20個週期還沒有一點成果就換個方法。如果得到了些許成果,就把訓練週期提升到100。

17. 批處理大小:將批處理大小選擇為2的倍數,對於不平衡數據,通常選用較大值,如128,否則一般都從16開始選用。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


給高級從業人員的一些額外經驗法則


1. 振盪損耗:如果在訓練中遇到振盪損耗,則是由趨同問題導致的。遇到這種問題時,可以嘗試減小學習率和/或更改批處理大小。

2. 過採樣和欠採樣:如果數據不平衡,使用imblearn.over_sampling中的SMOTE算法。

3. 曲線移動:如果需要進行位移預測,比如早期預測,可以使用曲線移動。下方展示了curve_shift的執行。

4. 自定義度量:假陽率是不平衡二進制分類中的一個重要度量。可以如下方給出的class FalsePositiveRate()的執行所示,構建假陽率度量和其他自定義度量。

5. Selu激活函數:在現今所有的激活函數中,selu激活函數被認為是最好的。我並不完全同意這一點,但如果想要使用selu激活函數,可以使用kernel_initializer=’lecun_normal’和 AlphaDropout.在AlphaDropout中使用0.1比率,AlphaDropout(0.1) 。執行實例在下方給出。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

TensorFlow 2中的多層感知器(MLP)實例


在這個執行中,可以看到上述經驗法則中所提到的內容的實際操作。


上述執行是在TensorFlow 2中完成的。強烈建議所有人都轉戰使用TensorFlow 2。它不僅擁有Keras所具有的簡易性,還顯著地提升了計算效率。


本文目的並不是嘗試找到最好的模型,而是學習神經網絡的實現。不會為了簡化過程而跳過任何步驟。相反,本文給出的步驟都很詳細,以幫助讀者的直接應用。



%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as snsimport pandas as pd
import numpy as np
from pylab import rcParamsfrom collections import Counterimport tensorflow as tffrom tensorflow.keras import optimizers
from tensorflow.keras.models import Model, load_model, Sequential
from tensorflow.keras.layers import Input, Dense, Dropout, AlphaDropout
from tensorflow.keras.callbacks import ModelCheckpoint, TensorBoardfrom sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, precision_recall_curve
from sklearn.metrics import recall_score, classification_report, auc, roc_curve
from sklearn.metrics import precision_recall_fscore_support, f1_scorefrom numpy.random import seed
seed(1)SEED = 123 #used to help randomly select the data points
DATA_SPLIT_PCT = 0.2rcParams['figure.figsize'] = 8, 6
LABELS = ["Normal","Break"]


測試是否使用了正確的TensorFlow版本,運行:tf.__version__

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

讀取與準備數據


數據下載傳送門:https://docs.google.com/forms/d/e/1FAIpQLSdyUk3lfDl7I5KYK_pw285LCApc-_RcoC0Tf9cnDnZ_TWzPAw/viewform?source=post_page---------------------------


df = pd.read_csv("data/processminer-rare-event-mts - data.csv") 
df.head(n=5) # visualize the data.


"
全文共5505字,預計學習時長11分鐘或更長
代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

圖片來源:Unsplash/Dewang Gupta

通過本文的學習, 我們可以瞭解如何著手構建初始神經網絡, 學習經驗法則,比如:隱藏層的數量、節點的數量、激活並觀察其在TensorFlow2中的應用。


深度學習提供了種類繁多的模型。有了它們,就可以建立非常精確的預測模型。然而,由於設置參數數量巨大且種類繁多,要找到出發點會有些困難。


本文將帶領大家找到構建神經網絡的出發點,具體來說是以構建多層感知器為例子。雖然使用了多層感知器為例,但大多數法則都是普遍適用於神經網絡構建的。


整體思路是通過經驗法則先建立第一個神經網絡模型。如果第一個模型能合理運行(達到最低可接受精確度),就對其進行調整與優化。否則,就最好去查看數據和問題所在,或採用其他方法。


本文將介紹:

· 建立神經網絡的經驗法則。

· TensorFlow2中二進制分類的實施代碼。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

神經網絡


神經網絡在卷積神經網絡(CNN)、遞歸神經網絡(RNN)等領域都取得了巨大進步。且隨著時間的推移,每個神經網絡的幾個亞型都得到了發展。正是這一個個的進步,成功地提高了模型的預測能力。


但與此同時,找到模型構建的出發點也變得更難了。


每個神經網絡模型都是不同的,不同的模型有不同的特點和功能,所以在這種情況下,選擇適用的模型變得像在林立的廣告牌中選擇合適的商品一樣困難。


接下來,我們將利用經驗法則構建第一個模型,以克服這些干擾。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

經驗法則


在形形色色的神經網絡中,多層感知器是通往深度學習的敲門磚。因此,當學習或構建一個深度學習領域的模型時,多層感知器就是很好的出發點。


以下是構建多層感知器的經驗法則,且大多數法則都適用於其他深度學習模型。


1. 層數:從兩個隱藏層開始(這其中不包含最後一層)。

2. 中間層的節點數量(大小):是2的倍數,如4,8,16,32……第一層的節點數應該是輸入數據特徵數量的一半左右。下一層的大小是上一層的一半。

3. 分類層最後一層的節點數量(大小):如果是二進制分類,則節點大小為一。對於多類分類器,節點大小等於類的數量。

4. 迴歸層最後一層的大小:如果是單響應,最後一層的大小為1。對於多響應迴歸,最後一層的大小等於響應的數量。

5. 激活中間層,使用Relu激活函數。

6. 激活最後一層:如果是二進制分類,使用sigmoid函數,多類分類器使用softmax函數,迴歸則使用linear函數。對於自動編碼器,如果輸入數據是連續的,使用linear函數進行激活。對於二進制或多級分類輸入,使用sigmoid或softmax函數。

7. Dropout層:除了輸入層以外,在其他每個層都加設Dropout(如果單獨定義輸入層)。將Dropout率設置為0.5。Dropout率大於0.5時結果會適得其反。因此如果覺得0.5會使太多的節點正則化,可以選擇增加層的大小,而不是將Dropout率設置在0.5以下。筆者不喜歡在輸入層設置任何Dropout。但如果認為有必要這樣做,請把Dropout率設置在0.2以下。

8. 數據預處理:假設預測器X是數字,且已經將所有分類列轉化成了獨熱編碼。那麼就可以在進行模型訓練前使用MinMaxScalar對數據進行大小預處理。如果MMS不奏效,就在相同的數據庫中使用StandardScalar對數據進行標準化處理。整個數據處理過程不對y進行操作。

9. 將數據分為訓練數據,有效數據與測試數據:

使用sklearn.model_selection的train_test_split語句。具體操作見下方示例。

10. 類權重:如果數據不平衡,可以在model.fit中設置類權重以平衡損失。對於二進制分類器,權重應為:{0:1的數量/數據大小,1:0的數量/數據大小}。對於極不平衡數據(罕見事件),類權重可能不起作用,請小心添加使用。

11. 優化器:使用adam優化器,應用其默認學習率。

12. 分類損失:對於二進制分類,使用binary_crossentropy.對於多類別分類,如果標籤是獨熱編碼而成的,使用categorical_crossentropy。當標籤都是整數時,使用sparse_categorical_crossentropy 。

13. 迴歸損失:使用均方誤差(mse)函數。

14. 分類指標:使用accuracy顯示正確分類的百分比。對不平衡數據,也要加上tf.keras.metrics.Recall() 和 tf.keras.metrics.FalsePositives().

15. 迴歸指標:使用tf.keras.metrics.RootMeanSquaredError()。

16. 訓練週期:先從20開始,看模型訓練是否顯示出損失的減少,或任何在精確度上的提高。如果20個週期還沒有一點成果就換個方法。如果得到了些許成果,就把訓練週期提升到100。

17. 批處理大小:將批處理大小選擇為2的倍數,對於不平衡數據,通常選用較大值,如128,否則一般都從16開始選用。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


給高級從業人員的一些額外經驗法則


1. 振盪損耗:如果在訓練中遇到振盪損耗,則是由趨同問題導致的。遇到這種問題時,可以嘗試減小學習率和/或更改批處理大小。

2. 過採樣和欠採樣:如果數據不平衡,使用imblearn.over_sampling中的SMOTE算法。

3. 曲線移動:如果需要進行位移預測,比如早期預測,可以使用曲線移動。下方展示了curve_shift的執行。

4. 自定義度量:假陽率是不平衡二進制分類中的一個重要度量。可以如下方給出的class FalsePositiveRate()的執行所示,構建假陽率度量和其他自定義度量。

5. Selu激活函數:在現今所有的激活函數中,selu激活函數被認為是最好的。我並不完全同意這一點,但如果想要使用selu激活函數,可以使用kernel_initializer=’lecun_normal’和 AlphaDropout.在AlphaDropout中使用0.1比率,AlphaDropout(0.1) 。執行實例在下方給出。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

TensorFlow 2中的多層感知器(MLP)實例


在這個執行中,可以看到上述經驗法則中所提到的內容的實際操作。


上述執行是在TensorFlow 2中完成的。強烈建議所有人都轉戰使用TensorFlow 2。它不僅擁有Keras所具有的簡易性,還顯著地提升了計算效率。


本文目的並不是嘗試找到最好的模型,而是學習神經網絡的實現。不會為了簡化過程而跳過任何步驟。相反,本文給出的步驟都很詳細,以幫助讀者的直接應用。



%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as snsimport pandas as pd
import numpy as np
from pylab import rcParamsfrom collections import Counterimport tensorflow as tffrom tensorflow.keras import optimizers
from tensorflow.keras.models import Model, load_model, Sequential
from tensorflow.keras.layers import Input, Dense, Dropout, AlphaDropout
from tensorflow.keras.callbacks import ModelCheckpoint, TensorBoardfrom sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, precision_recall_curve
from sklearn.metrics import recall_score, classification_report, auc, roc_curve
from sklearn.metrics import precision_recall_fscore_support, f1_scorefrom numpy.random import seed
seed(1)SEED = 123 #used to help randomly select the data points
DATA_SPLIT_PCT = 0.2rcParams['figure.figsize'] = 8, 6
LABELS = ["Normal","Break"]


測試是否使用了正確的TensorFlow版本,運行:tf.__version__

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

讀取與準備數據


數據下載傳送門:https://docs.google.com/forms/d/e/1FAIpQLSdyUk3lfDl7I5KYK_pw285LCApc-_RcoC0Tf9cnDnZ_TWzPAw/viewform?source=post_page---------------------------


df = pd.read_csv("data/processminer-rare-event-mts - data.csv") 
df.head(n=5) # visualize the data.


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


將分類列轉換為獨熱編碼

hotencoding1 = pd.get_dummies(df['x28']) # Grade&Bwt
hotencoding1 = hotencoding1.add_prefix('grade_')
hotencoding2 = pd.get_dummies(df['x61']) # EventPress
hotencoding2 = hotencoding2.add_prefix('eventpress_')df=df.drop(['x28', 'x61'], axis=1)df=pd.concat([df, hotencoding1, hotencoding2], axis=1)


曲線移動


以下是一個時間序列數據,要求必須提前預測時間(y=1)。在這個數據中,連續行之間間隔兩分鐘。我們將把行y中的標籤移動兩行,以提前四分鐘進行預測。

sign = lambda x: (1, -1)[x < 0]def curve_shift(df, shift_by):
'''
This function will shift the binary labels in a dataframe.
The curve shift will be with respect to the 1s.
For example, if shift is -2, the following process
will happen: if row n is labeled as 1, then
- Make row (n+shift_by):(n+shift_by-1) = 1.
- Remove row n.
i.e. the labels will be shifted up to 2 rows up.

Inputs:
df A pandas dataframe with a binary labeled column.
This labeled column should be named as 'y'.
shift_by An integer denoting the number of rows to shift.

Output
df A dataframe with the binary labels shifted by shift.
'''vector = df['y'].copy()
for s in range(abs(shift_by)):
tmp = vector.shift(sign(shift_by))
tmp = tmp.fillna(0)
vector += tmp
labelcol = 'y'
# Add vector to the df
df.insert(loc=0, column=labelcol+'tmp', value=vector)
# Remove the rows with labelcol == 1.
df = df.drop(df[df[labelcol] == 1].index)
# Drop labelcol and rename the tmp col as labelcol
df = df.drop(labelcol, axis=1)
df = df.rename(columns={labelcol+'tmp': labelcol})
# Make the labelcol binary
df.loc[df[labelcol] > 0, labelcol] = 1return df


向上移動兩行


df = curve_shift(df, shift_by = -2)


從這裡開始不需要時間行了,將其移除。


df = df.drop(['time'], axis=1)


將數據分為訓練數據,有效數據和測試數據。

df_train, df_test = train_test_split(df, test_size=DATA_SPLIT_PCT, random_state=SEED)
df_train, df_valid = train_test_split(df_train, test_size=DATA_SPLIT_PCT, random_state=SEED)


把X和y分開

x_train = df_train.drop(['y'], axis=1)
y_train = df_train.y.valuesx_valid = df_valid.drop(['y'], axis=1)
y_valid = df_valid.y.valuesx_test = df_test.drop(['y'], axis=1)
y_test = df_test.y


數據縮放

scaler = MinMaxScaler().fit(x_train)
# scaler = StandardScaler().fit(x_train)
x_train_scaled = scaler.transform(x_train)
x_valid_scaled = scaler.transform(x_valid)
x_test_scaled = scaler.transform(x_test)


"
全文共5505字,預計學習時長11分鐘或更長
代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

圖片來源:Unsplash/Dewang Gupta

通過本文的學習, 我們可以瞭解如何著手構建初始神經網絡, 學習經驗法則,比如:隱藏層的數量、節點的數量、激活並觀察其在TensorFlow2中的應用。


深度學習提供了種類繁多的模型。有了它們,就可以建立非常精確的預測模型。然而,由於設置參數數量巨大且種類繁多,要找到出發點會有些困難。


本文將帶領大家找到構建神經網絡的出發點,具體來說是以構建多層感知器為例子。雖然使用了多層感知器為例,但大多數法則都是普遍適用於神經網絡構建的。


整體思路是通過經驗法則先建立第一個神經網絡模型。如果第一個模型能合理運行(達到最低可接受精確度),就對其進行調整與優化。否則,就最好去查看數據和問題所在,或採用其他方法。


本文將介紹:

· 建立神經網絡的經驗法則。

· TensorFlow2中二進制分類的實施代碼。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

神經網絡


神經網絡在卷積神經網絡(CNN)、遞歸神經網絡(RNN)等領域都取得了巨大進步。且隨著時間的推移,每個神經網絡的幾個亞型都得到了發展。正是這一個個的進步,成功地提高了模型的預測能力。


但與此同時,找到模型構建的出發點也變得更難了。


每個神經網絡模型都是不同的,不同的模型有不同的特點和功能,所以在這種情況下,選擇適用的模型變得像在林立的廣告牌中選擇合適的商品一樣困難。


接下來,我們將利用經驗法則構建第一個模型,以克服這些干擾。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

經驗法則


在形形色色的神經網絡中,多層感知器是通往深度學習的敲門磚。因此,當學習或構建一個深度學習領域的模型時,多層感知器就是很好的出發點。


以下是構建多層感知器的經驗法則,且大多數法則都適用於其他深度學習模型。


1. 層數:從兩個隱藏層開始(這其中不包含最後一層)。

2. 中間層的節點數量(大小):是2的倍數,如4,8,16,32……第一層的節點數應該是輸入數據特徵數量的一半左右。下一層的大小是上一層的一半。

3. 分類層最後一層的節點數量(大小):如果是二進制分類,則節點大小為一。對於多類分類器,節點大小等於類的數量。

4. 迴歸層最後一層的大小:如果是單響應,最後一層的大小為1。對於多響應迴歸,最後一層的大小等於響應的數量。

5. 激活中間層,使用Relu激活函數。

6. 激活最後一層:如果是二進制分類,使用sigmoid函數,多類分類器使用softmax函數,迴歸則使用linear函數。對於自動編碼器,如果輸入數據是連續的,使用linear函數進行激活。對於二進制或多級分類輸入,使用sigmoid或softmax函數。

7. Dropout層:除了輸入層以外,在其他每個層都加設Dropout(如果單獨定義輸入層)。將Dropout率設置為0.5。Dropout率大於0.5時結果會適得其反。因此如果覺得0.5會使太多的節點正則化,可以選擇增加層的大小,而不是將Dropout率設置在0.5以下。筆者不喜歡在輸入層設置任何Dropout。但如果認為有必要這樣做,請把Dropout率設置在0.2以下。

8. 數據預處理:假設預測器X是數字,且已經將所有分類列轉化成了獨熱編碼。那麼就可以在進行模型訓練前使用MinMaxScalar對數據進行大小預處理。如果MMS不奏效,就在相同的數據庫中使用StandardScalar對數據進行標準化處理。整個數據處理過程不對y進行操作。

9. 將數據分為訓練數據,有效數據與測試數據:

使用sklearn.model_selection的train_test_split語句。具體操作見下方示例。

10. 類權重:如果數據不平衡,可以在model.fit中設置類權重以平衡損失。對於二進制分類器,權重應為:{0:1的數量/數據大小,1:0的數量/數據大小}。對於極不平衡數據(罕見事件),類權重可能不起作用,請小心添加使用。

11. 優化器:使用adam優化器,應用其默認學習率。

12. 分類損失:對於二進制分類,使用binary_crossentropy.對於多類別分類,如果標籤是獨熱編碼而成的,使用categorical_crossentropy。當標籤都是整數時,使用sparse_categorical_crossentropy 。

13. 迴歸損失:使用均方誤差(mse)函數。

14. 分類指標:使用accuracy顯示正確分類的百分比。對不平衡數據,也要加上tf.keras.metrics.Recall() 和 tf.keras.metrics.FalsePositives().

15. 迴歸指標:使用tf.keras.metrics.RootMeanSquaredError()。

16. 訓練週期:先從20開始,看模型訓練是否顯示出損失的減少,或任何在精確度上的提高。如果20個週期還沒有一點成果就換個方法。如果得到了些許成果,就把訓練週期提升到100。

17. 批處理大小:將批處理大小選擇為2的倍數,對於不平衡數據,通常選用較大值,如128,否則一般都從16開始選用。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


給高級從業人員的一些額外經驗法則


1. 振盪損耗:如果在訓練中遇到振盪損耗,則是由趨同問題導致的。遇到這種問題時,可以嘗試減小學習率和/或更改批處理大小。

2. 過採樣和欠採樣:如果數據不平衡,使用imblearn.over_sampling中的SMOTE算法。

3. 曲線移動:如果需要進行位移預測,比如早期預測,可以使用曲線移動。下方展示了curve_shift的執行。

4. 自定義度量:假陽率是不平衡二進制分類中的一個重要度量。可以如下方給出的class FalsePositiveRate()的執行所示,構建假陽率度量和其他自定義度量。

5. Selu激活函數:在現今所有的激活函數中,selu激活函數被認為是最好的。我並不完全同意這一點,但如果想要使用selu激活函數,可以使用kernel_initializer=’lecun_normal’和 AlphaDropout.在AlphaDropout中使用0.1比率,AlphaDropout(0.1) 。執行實例在下方給出。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

TensorFlow 2中的多層感知器(MLP)實例


在這個執行中,可以看到上述經驗法則中所提到的內容的實際操作。


上述執行是在TensorFlow 2中完成的。強烈建議所有人都轉戰使用TensorFlow 2。它不僅擁有Keras所具有的簡易性,還顯著地提升了計算效率。


本文目的並不是嘗試找到最好的模型,而是學習神經網絡的實現。不會為了簡化過程而跳過任何步驟。相反,本文給出的步驟都很詳細,以幫助讀者的直接應用。



%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as snsimport pandas as pd
import numpy as np
from pylab import rcParamsfrom collections import Counterimport tensorflow as tffrom tensorflow.keras import optimizers
from tensorflow.keras.models import Model, load_model, Sequential
from tensorflow.keras.layers import Input, Dense, Dropout, AlphaDropout
from tensorflow.keras.callbacks import ModelCheckpoint, TensorBoardfrom sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, precision_recall_curve
from sklearn.metrics import recall_score, classification_report, auc, roc_curve
from sklearn.metrics import precision_recall_fscore_support, f1_scorefrom numpy.random import seed
seed(1)SEED = 123 #used to help randomly select the data points
DATA_SPLIT_PCT = 0.2rcParams['figure.figsize'] = 8, 6
LABELS = ["Normal","Break"]


測試是否使用了正確的TensorFlow版本,運行:tf.__version__

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

讀取與準備數據


數據下載傳送門:https://docs.google.com/forms/d/e/1FAIpQLSdyUk3lfDl7I5KYK_pw285LCApc-_RcoC0Tf9cnDnZ_TWzPAw/viewform?source=post_page---------------------------


df = pd.read_csv("data/processminer-rare-event-mts - data.csv") 
df.head(n=5) # visualize the data.


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


將分類列轉換為獨熱編碼

hotencoding1 = pd.get_dummies(df['x28']) # Grade&Bwt
hotencoding1 = hotencoding1.add_prefix('grade_')
hotencoding2 = pd.get_dummies(df['x61']) # EventPress
hotencoding2 = hotencoding2.add_prefix('eventpress_')df=df.drop(['x28', 'x61'], axis=1)df=pd.concat([df, hotencoding1, hotencoding2], axis=1)


曲線移動


以下是一個時間序列數據,要求必須提前預測時間(y=1)。在這個數據中,連續行之間間隔兩分鐘。我們將把行y中的標籤移動兩行,以提前四分鐘進行預測。

sign = lambda x: (1, -1)[x < 0]def curve_shift(df, shift_by):
'''
This function will shift the binary labels in a dataframe.
The curve shift will be with respect to the 1s.
For example, if shift is -2, the following process
will happen: if row n is labeled as 1, then
- Make row (n+shift_by):(n+shift_by-1) = 1.
- Remove row n.
i.e. the labels will be shifted up to 2 rows up.

Inputs:
df A pandas dataframe with a binary labeled column.
This labeled column should be named as 'y'.
shift_by An integer denoting the number of rows to shift.

Output
df A dataframe with the binary labels shifted by shift.
'''vector = df['y'].copy()
for s in range(abs(shift_by)):
tmp = vector.shift(sign(shift_by))
tmp = tmp.fillna(0)
vector += tmp
labelcol = 'y'
# Add vector to the df
df.insert(loc=0, column=labelcol+'tmp', value=vector)
# Remove the rows with labelcol == 1.
df = df.drop(df[df[labelcol] == 1].index)
# Drop labelcol and rename the tmp col as labelcol
df = df.drop(labelcol, axis=1)
df = df.rename(columns={labelcol+'tmp': labelcol})
# Make the labelcol binary
df.loc[df[labelcol] > 0, labelcol] = 1return df


向上移動兩行


df = curve_shift(df, shift_by = -2)


從這裡開始不需要時間行了,將其移除。


df = df.drop(['time'], axis=1)


將數據分為訓練數據,有效數據和測試數據。

df_train, df_test = train_test_split(df, test_size=DATA_SPLIT_PCT, random_state=SEED)
df_train, df_valid = train_test_split(df_train, test_size=DATA_SPLIT_PCT, random_state=SEED)


把X和y分開

x_train = df_train.drop(['y'], axis=1)
y_train = df_train.y.valuesx_valid = df_valid.drop(['y'], axis=1)
y_valid = df_valid.y.valuesx_test = df_test.drop(['y'], axis=1)
y_test = df_test.y


數據縮放

scaler = MinMaxScaler().fit(x_train)
# scaler = StandardScaler().fit(x_train)
x_train_scaled = scaler.transform(x_train)
x_valid_scaled = scaler.transform(x_valid)
x_test_scaled = scaler.transform(x_test)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

MLP模型


自定義度量:FalsePositiveRate()


開發一個在下面所有模型中都要用到的FalsePositiveRate()度量。


class FalsePositiveRate(tf.keras.metrics.Metric):
def __init__(self, name='false_positive_rate', **kwargs):
super(FalsePositiveRate, self).__init__(name=name, **kwargs)
self.negatives = self.add_weight(name='negatives', initializer='zeros')
self.false_positives = self.add_weight(name='false_negatives', initializer='zeros')

def update_state(self, y_true, y_pred, sample_weight=None):
'''
Arguments:
y_true The actual y. Passed by default to Metric classes.
y_pred The predicted y. Passed by default to Metric classes.

'''
# Compute the number of negatives.
y_true = tf.cast(y_true, tf.bool)

negatives = tf.reduce_sum(tf.cast(tf.equal(y_true, False), self.dtype))

self.negatives.assign_add(negatives)

# Compute the number of false positives.
y_pred = tf.greater_equal(y_pred, 0.5) # Using default threshold of 0.5 to call a prediction as positive labeled.

false_positive_values = tf.logical_and(tf.equal(y_true, False), tf.equal(y_pred, True))
false_positive_values = tf.cast(false_positive_values, self.dtype)
if sample_weight is not None:
sample_weight = tf.cast(sample_weight, self.dtype)
sample_weight = tf.broadcast_weights(sample_weight, values)
values = tf.multiply(false_positive_values, sample_weight)

false_positives = tf.reduce_sum(false_positive_values)

self.false_positives.assign_add(false_positives)

def result(self):
return tf.divide(self.false_positives, self.negatives)


常規性能繪圖函數


def plot_loss(model_history):
train_loss=[value for key, value in model_history.items() if 'loss' in key.lower()][0]
valid_loss=[value for key, value in model_history.items() if 'loss' in key.lower()][1]fig, ax1 = plt.subplots()color = 'tab:blue'
ax1.set_xlabel('Epoch')
ax1.set_ylabel('Loss', color=color)
ax1.plot(train_loss, '--', color=color, label='Train Loss')
ax1.plot(valid_loss, color=color, label='Valid Loss')
ax1.tick_params(axis='y', labelcolor=color)
plt.legend(loc='upper left')
plt.title('Model Loss')plt.show()def plot_model_recall_fpr(model_history):
train_recall=[value for key, value in model_history.items() if 'recall' in key.lower()][0]
valid_recall=[value for key, value in model_history.items() if 'recall' in key.lower()][1]train_fpr=[value for key, value in model_history.items() if 'false_positive_rate' in key.lower()][0]
valid_fpr=[value for key, value in model_history.items() if 'false_positive_rate' in key.lower()][1]fig, ax1 = plt.subplots()color = 'tab:red'
ax1.set_xlabel('Epoch')
ax1.set_ylabel('Recall', color=color)
ax1.set_ylim([-0.05,1.05])
ax1.plot(train_recall, '--', color=color, label='Train Recall')
ax1.plot(valid_recall, color=color, label='Valid Recall')
ax1.tick_params(axis='y', labelcolor=color)
plt.legend(loc='upper left')
plt.title('Model Recall and FPR')ax2 = ax1.twinx() # instantiate a second axes that shares the same x-axiscolor = 'tab:blue'
ax2.set_ylabel('False Positive Rate', color=color) # we already handled the x-label with ax1
ax2.plot(train_fpr, '--', color=color, label='Train FPR')
ax2.plot(valid_fpr, color=color, label='Valid FPR')
ax2.tick_params(axis='y', labelcolor=color)
ax2.set_ylim([-0.05,1.05])fig.tight_layout() # otherwise the right y-label is slightly clipped
plt.legend(loc='upper right')
plt.show()


模型1.參照算法


n_features = x_train_scaled.shape[1]
mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dense(1, activation='sigmoid'))
mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid_scaled, y_valid),
verbose=0).history


觀察模型擬合損失和準確度(召回率和假陽率)變化


plot_loss(history)

"
全文共5505字,預計學習時長11分鐘或更長
代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

圖片來源:Unsplash/Dewang Gupta

通過本文的學習, 我們可以瞭解如何著手構建初始神經網絡, 學習經驗法則,比如:隱藏層的數量、節點的數量、激活並觀察其在TensorFlow2中的應用。


深度學習提供了種類繁多的模型。有了它們,就可以建立非常精確的預測模型。然而,由於設置參數數量巨大且種類繁多,要找到出發點會有些困難。


本文將帶領大家找到構建神經網絡的出發點,具體來說是以構建多層感知器為例子。雖然使用了多層感知器為例,但大多數法則都是普遍適用於神經網絡構建的。


整體思路是通過經驗法則先建立第一個神經網絡模型。如果第一個模型能合理運行(達到最低可接受精確度),就對其進行調整與優化。否則,就最好去查看數據和問題所在,或採用其他方法。


本文將介紹:

· 建立神經網絡的經驗法則。

· TensorFlow2中二進制分類的實施代碼。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

神經網絡


神經網絡在卷積神經網絡(CNN)、遞歸神經網絡(RNN)等領域都取得了巨大進步。且隨著時間的推移,每個神經網絡的幾個亞型都得到了發展。正是這一個個的進步,成功地提高了模型的預測能力。


但與此同時,找到模型構建的出發點也變得更難了。


每個神經網絡模型都是不同的,不同的模型有不同的特點和功能,所以在這種情況下,選擇適用的模型變得像在林立的廣告牌中選擇合適的商品一樣困難。


接下來,我們將利用經驗法則構建第一個模型,以克服這些干擾。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

經驗法則


在形形色色的神經網絡中,多層感知器是通往深度學習的敲門磚。因此,當學習或構建一個深度學習領域的模型時,多層感知器就是很好的出發點。


以下是構建多層感知器的經驗法則,且大多數法則都適用於其他深度學習模型。


1. 層數:從兩個隱藏層開始(這其中不包含最後一層)。

2. 中間層的節點數量(大小):是2的倍數,如4,8,16,32……第一層的節點數應該是輸入數據特徵數量的一半左右。下一層的大小是上一層的一半。

3. 分類層最後一層的節點數量(大小):如果是二進制分類,則節點大小為一。對於多類分類器,節點大小等於類的數量。

4. 迴歸層最後一層的大小:如果是單響應,最後一層的大小為1。對於多響應迴歸,最後一層的大小等於響應的數量。

5. 激活中間層,使用Relu激活函數。

6. 激活最後一層:如果是二進制分類,使用sigmoid函數,多類分類器使用softmax函數,迴歸則使用linear函數。對於自動編碼器,如果輸入數據是連續的,使用linear函數進行激活。對於二進制或多級分類輸入,使用sigmoid或softmax函數。

7. Dropout層:除了輸入層以外,在其他每個層都加設Dropout(如果單獨定義輸入層)。將Dropout率設置為0.5。Dropout率大於0.5時結果會適得其反。因此如果覺得0.5會使太多的節點正則化,可以選擇增加層的大小,而不是將Dropout率設置在0.5以下。筆者不喜歡在輸入層設置任何Dropout。但如果認為有必要這樣做,請把Dropout率設置在0.2以下。

8. 數據預處理:假設預測器X是數字,且已經將所有分類列轉化成了獨熱編碼。那麼就可以在進行模型訓練前使用MinMaxScalar對數據進行大小預處理。如果MMS不奏效,就在相同的數據庫中使用StandardScalar對數據進行標準化處理。整個數據處理過程不對y進行操作。

9. 將數據分為訓練數據,有效數據與測試數據:

使用sklearn.model_selection的train_test_split語句。具體操作見下方示例。

10. 類權重:如果數據不平衡,可以在model.fit中設置類權重以平衡損失。對於二進制分類器,權重應為:{0:1的數量/數據大小,1:0的數量/數據大小}。對於極不平衡數據(罕見事件),類權重可能不起作用,請小心添加使用。

11. 優化器:使用adam優化器,應用其默認學習率。

12. 分類損失:對於二進制分類,使用binary_crossentropy.對於多類別分類,如果標籤是獨熱編碼而成的,使用categorical_crossentropy。當標籤都是整數時,使用sparse_categorical_crossentropy 。

13. 迴歸損失:使用均方誤差(mse)函數。

14. 分類指標:使用accuracy顯示正確分類的百分比。對不平衡數據,也要加上tf.keras.metrics.Recall() 和 tf.keras.metrics.FalsePositives().

15. 迴歸指標:使用tf.keras.metrics.RootMeanSquaredError()。

16. 訓練週期:先從20開始,看模型訓練是否顯示出損失的減少,或任何在精確度上的提高。如果20個週期還沒有一點成果就換個方法。如果得到了些許成果,就把訓練週期提升到100。

17. 批處理大小:將批處理大小選擇為2的倍數,對於不平衡數據,通常選用較大值,如128,否則一般都從16開始選用。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


給高級從業人員的一些額外經驗法則


1. 振盪損耗:如果在訓練中遇到振盪損耗,則是由趨同問題導致的。遇到這種問題時,可以嘗試減小學習率和/或更改批處理大小。

2. 過採樣和欠採樣:如果數據不平衡,使用imblearn.over_sampling中的SMOTE算法。

3. 曲線移動:如果需要進行位移預測,比如早期預測,可以使用曲線移動。下方展示了curve_shift的執行。

4. 自定義度量:假陽率是不平衡二進制分類中的一個重要度量。可以如下方給出的class FalsePositiveRate()的執行所示,構建假陽率度量和其他自定義度量。

5. Selu激活函數:在現今所有的激活函數中,selu激活函數被認為是最好的。我並不完全同意這一點,但如果想要使用selu激活函數,可以使用kernel_initializer=’lecun_normal’和 AlphaDropout.在AlphaDropout中使用0.1比率,AlphaDropout(0.1) 。執行實例在下方給出。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

TensorFlow 2中的多層感知器(MLP)實例


在這個執行中,可以看到上述經驗法則中所提到的內容的實際操作。


上述執行是在TensorFlow 2中完成的。強烈建議所有人都轉戰使用TensorFlow 2。它不僅擁有Keras所具有的簡易性,還顯著地提升了計算效率。


本文目的並不是嘗試找到最好的模型,而是學習神經網絡的實現。不會為了簡化過程而跳過任何步驟。相反,本文給出的步驟都很詳細,以幫助讀者的直接應用。



%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as snsimport pandas as pd
import numpy as np
from pylab import rcParamsfrom collections import Counterimport tensorflow as tffrom tensorflow.keras import optimizers
from tensorflow.keras.models import Model, load_model, Sequential
from tensorflow.keras.layers import Input, Dense, Dropout, AlphaDropout
from tensorflow.keras.callbacks import ModelCheckpoint, TensorBoardfrom sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, precision_recall_curve
from sklearn.metrics import recall_score, classification_report, auc, roc_curve
from sklearn.metrics import precision_recall_fscore_support, f1_scorefrom numpy.random import seed
seed(1)SEED = 123 #used to help randomly select the data points
DATA_SPLIT_PCT = 0.2rcParams['figure.figsize'] = 8, 6
LABELS = ["Normal","Break"]


測試是否使用了正確的TensorFlow版本,運行:tf.__version__

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

讀取與準備數據


數據下載傳送門:https://docs.google.com/forms/d/e/1FAIpQLSdyUk3lfDl7I5KYK_pw285LCApc-_RcoC0Tf9cnDnZ_TWzPAw/viewform?source=post_page---------------------------


df = pd.read_csv("data/processminer-rare-event-mts - data.csv") 
df.head(n=5) # visualize the data.


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


將分類列轉換為獨熱編碼

hotencoding1 = pd.get_dummies(df['x28']) # Grade&Bwt
hotencoding1 = hotencoding1.add_prefix('grade_')
hotencoding2 = pd.get_dummies(df['x61']) # EventPress
hotencoding2 = hotencoding2.add_prefix('eventpress_')df=df.drop(['x28', 'x61'], axis=1)df=pd.concat([df, hotencoding1, hotencoding2], axis=1)


曲線移動


以下是一個時間序列數據,要求必須提前預測時間(y=1)。在這個數據中,連續行之間間隔兩分鐘。我們將把行y中的標籤移動兩行,以提前四分鐘進行預測。

sign = lambda x: (1, -1)[x < 0]def curve_shift(df, shift_by):
'''
This function will shift the binary labels in a dataframe.
The curve shift will be with respect to the 1s.
For example, if shift is -2, the following process
will happen: if row n is labeled as 1, then
- Make row (n+shift_by):(n+shift_by-1) = 1.
- Remove row n.
i.e. the labels will be shifted up to 2 rows up.

Inputs:
df A pandas dataframe with a binary labeled column.
This labeled column should be named as 'y'.
shift_by An integer denoting the number of rows to shift.

Output
df A dataframe with the binary labels shifted by shift.
'''vector = df['y'].copy()
for s in range(abs(shift_by)):
tmp = vector.shift(sign(shift_by))
tmp = tmp.fillna(0)
vector += tmp
labelcol = 'y'
# Add vector to the df
df.insert(loc=0, column=labelcol+'tmp', value=vector)
# Remove the rows with labelcol == 1.
df = df.drop(df[df[labelcol] == 1].index)
# Drop labelcol and rename the tmp col as labelcol
df = df.drop(labelcol, axis=1)
df = df.rename(columns={labelcol+'tmp': labelcol})
# Make the labelcol binary
df.loc[df[labelcol] > 0, labelcol] = 1return df


向上移動兩行


df = curve_shift(df, shift_by = -2)


從這裡開始不需要時間行了,將其移除。


df = df.drop(['time'], axis=1)


將數據分為訓練數據,有效數據和測試數據。

df_train, df_test = train_test_split(df, test_size=DATA_SPLIT_PCT, random_state=SEED)
df_train, df_valid = train_test_split(df_train, test_size=DATA_SPLIT_PCT, random_state=SEED)


把X和y分開

x_train = df_train.drop(['y'], axis=1)
y_train = df_train.y.valuesx_valid = df_valid.drop(['y'], axis=1)
y_valid = df_valid.y.valuesx_test = df_test.drop(['y'], axis=1)
y_test = df_test.y


數據縮放

scaler = MinMaxScaler().fit(x_train)
# scaler = StandardScaler().fit(x_train)
x_train_scaled = scaler.transform(x_train)
x_valid_scaled = scaler.transform(x_valid)
x_test_scaled = scaler.transform(x_test)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

MLP模型


自定義度量:FalsePositiveRate()


開發一個在下面所有模型中都要用到的FalsePositiveRate()度量。


class FalsePositiveRate(tf.keras.metrics.Metric):
def __init__(self, name='false_positive_rate', **kwargs):
super(FalsePositiveRate, self).__init__(name=name, **kwargs)
self.negatives = self.add_weight(name='negatives', initializer='zeros')
self.false_positives = self.add_weight(name='false_negatives', initializer='zeros')

def update_state(self, y_true, y_pred, sample_weight=None):
'''
Arguments:
y_true The actual y. Passed by default to Metric classes.
y_pred The predicted y. Passed by default to Metric classes.

'''
# Compute the number of negatives.
y_true = tf.cast(y_true, tf.bool)

negatives = tf.reduce_sum(tf.cast(tf.equal(y_true, False), self.dtype))

self.negatives.assign_add(negatives)

# Compute the number of false positives.
y_pred = tf.greater_equal(y_pred, 0.5) # Using default threshold of 0.5 to call a prediction as positive labeled.

false_positive_values = tf.logical_and(tf.equal(y_true, False), tf.equal(y_pred, True))
false_positive_values = tf.cast(false_positive_values, self.dtype)
if sample_weight is not None:
sample_weight = tf.cast(sample_weight, self.dtype)
sample_weight = tf.broadcast_weights(sample_weight, values)
values = tf.multiply(false_positive_values, sample_weight)

false_positives = tf.reduce_sum(false_positive_values)

self.false_positives.assign_add(false_positives)

def result(self):
return tf.divide(self.false_positives, self.negatives)


常規性能繪圖函數


def plot_loss(model_history):
train_loss=[value for key, value in model_history.items() if 'loss' in key.lower()][0]
valid_loss=[value for key, value in model_history.items() if 'loss' in key.lower()][1]fig, ax1 = plt.subplots()color = 'tab:blue'
ax1.set_xlabel('Epoch')
ax1.set_ylabel('Loss', color=color)
ax1.plot(train_loss, '--', color=color, label='Train Loss')
ax1.plot(valid_loss, color=color, label='Valid Loss')
ax1.tick_params(axis='y', labelcolor=color)
plt.legend(loc='upper left')
plt.title('Model Loss')plt.show()def plot_model_recall_fpr(model_history):
train_recall=[value for key, value in model_history.items() if 'recall' in key.lower()][0]
valid_recall=[value for key, value in model_history.items() if 'recall' in key.lower()][1]train_fpr=[value for key, value in model_history.items() if 'false_positive_rate' in key.lower()][0]
valid_fpr=[value for key, value in model_history.items() if 'false_positive_rate' in key.lower()][1]fig, ax1 = plt.subplots()color = 'tab:red'
ax1.set_xlabel('Epoch')
ax1.set_ylabel('Recall', color=color)
ax1.set_ylim([-0.05,1.05])
ax1.plot(train_recall, '--', color=color, label='Train Recall')
ax1.plot(valid_recall, color=color, label='Valid Recall')
ax1.tick_params(axis='y', labelcolor=color)
plt.legend(loc='upper left')
plt.title('Model Recall and FPR')ax2 = ax1.twinx() # instantiate a second axes that shares the same x-axiscolor = 'tab:blue'
ax2.set_ylabel('False Positive Rate', color=color) # we already handled the x-label with ax1
ax2.plot(train_fpr, '--', color=color, label='Train FPR')
ax2.plot(valid_fpr, color=color, label='Valid FPR')
ax2.tick_params(axis='y', labelcolor=color)
ax2.set_ylim([-0.05,1.05])fig.tight_layout() # otherwise the right y-label is slightly clipped
plt.legend(loc='upper right')
plt.show()


模型1.參照算法


n_features = x_train_scaled.shape[1]
mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dense(1, activation='sigmoid'))
mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid_scaled, y_valid),
verbose=0).history


觀察模型擬合損失和準確度(召回率和假陽率)變化


plot_loss(history)

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

plot_model_recall_fpr(history)

"
全文共5505字,預計學習時長11分鐘或更長
代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

圖片來源:Unsplash/Dewang Gupta

通過本文的學習, 我們可以瞭解如何著手構建初始神經網絡, 學習經驗法則,比如:隱藏層的數量、節點的數量、激活並觀察其在TensorFlow2中的應用。


深度學習提供了種類繁多的模型。有了它們,就可以建立非常精確的預測模型。然而,由於設置參數數量巨大且種類繁多,要找到出發點會有些困難。


本文將帶領大家找到構建神經網絡的出發點,具體來說是以構建多層感知器為例子。雖然使用了多層感知器為例,但大多數法則都是普遍適用於神經網絡構建的。


整體思路是通過經驗法則先建立第一個神經網絡模型。如果第一個模型能合理運行(達到最低可接受精確度),就對其進行調整與優化。否則,就最好去查看數據和問題所在,或採用其他方法。


本文將介紹:

· 建立神經網絡的經驗法則。

· TensorFlow2中二進制分類的實施代碼。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

神經網絡


神經網絡在卷積神經網絡(CNN)、遞歸神經網絡(RNN)等領域都取得了巨大進步。且隨著時間的推移,每個神經網絡的幾個亞型都得到了發展。正是這一個個的進步,成功地提高了模型的預測能力。


但與此同時,找到模型構建的出發點也變得更難了。


每個神經網絡模型都是不同的,不同的模型有不同的特點和功能,所以在這種情況下,選擇適用的模型變得像在林立的廣告牌中選擇合適的商品一樣困難。


接下來,我們將利用經驗法則構建第一個模型,以克服這些干擾。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

經驗法則


在形形色色的神經網絡中,多層感知器是通往深度學習的敲門磚。因此,當學習或構建一個深度學習領域的模型時,多層感知器就是很好的出發點。


以下是構建多層感知器的經驗法則,且大多數法則都適用於其他深度學習模型。


1. 層數:從兩個隱藏層開始(這其中不包含最後一層)。

2. 中間層的節點數量(大小):是2的倍數,如4,8,16,32……第一層的節點數應該是輸入數據特徵數量的一半左右。下一層的大小是上一層的一半。

3. 分類層最後一層的節點數量(大小):如果是二進制分類,則節點大小為一。對於多類分類器,節點大小等於類的數量。

4. 迴歸層最後一層的大小:如果是單響應,最後一層的大小為1。對於多響應迴歸,最後一層的大小等於響應的數量。

5. 激活中間層,使用Relu激活函數。

6. 激活最後一層:如果是二進制分類,使用sigmoid函數,多類分類器使用softmax函數,迴歸則使用linear函數。對於自動編碼器,如果輸入數據是連續的,使用linear函數進行激活。對於二進制或多級分類輸入,使用sigmoid或softmax函數。

7. Dropout層:除了輸入層以外,在其他每個層都加設Dropout(如果單獨定義輸入層)。將Dropout率設置為0.5。Dropout率大於0.5時結果會適得其反。因此如果覺得0.5會使太多的節點正則化,可以選擇增加層的大小,而不是將Dropout率設置在0.5以下。筆者不喜歡在輸入層設置任何Dropout。但如果認為有必要這樣做,請把Dropout率設置在0.2以下。

8. 數據預處理:假設預測器X是數字,且已經將所有分類列轉化成了獨熱編碼。那麼就可以在進行模型訓練前使用MinMaxScalar對數據進行大小預處理。如果MMS不奏效,就在相同的數據庫中使用StandardScalar對數據進行標準化處理。整個數據處理過程不對y進行操作。

9. 將數據分為訓練數據,有效數據與測試數據:

使用sklearn.model_selection的train_test_split語句。具體操作見下方示例。

10. 類權重:如果數據不平衡,可以在model.fit中設置類權重以平衡損失。對於二進制分類器,權重應為:{0:1的數量/數據大小,1:0的數量/數據大小}。對於極不平衡數據(罕見事件),類權重可能不起作用,請小心添加使用。

11. 優化器:使用adam優化器,應用其默認學習率。

12. 分類損失:對於二進制分類,使用binary_crossentropy.對於多類別分類,如果標籤是獨熱編碼而成的,使用categorical_crossentropy。當標籤都是整數時,使用sparse_categorical_crossentropy 。

13. 迴歸損失:使用均方誤差(mse)函數。

14. 分類指標:使用accuracy顯示正確分類的百分比。對不平衡數據,也要加上tf.keras.metrics.Recall() 和 tf.keras.metrics.FalsePositives().

15. 迴歸指標:使用tf.keras.metrics.RootMeanSquaredError()。

16. 訓練週期:先從20開始,看模型訓練是否顯示出損失的減少,或任何在精確度上的提高。如果20個週期還沒有一點成果就換個方法。如果得到了些許成果,就把訓練週期提升到100。

17. 批處理大小:將批處理大小選擇為2的倍數,對於不平衡數據,通常選用較大值,如128,否則一般都從16開始選用。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


給高級從業人員的一些額外經驗法則


1. 振盪損耗:如果在訓練中遇到振盪損耗,則是由趨同問題導致的。遇到這種問題時,可以嘗試減小學習率和/或更改批處理大小。

2. 過採樣和欠採樣:如果數據不平衡,使用imblearn.over_sampling中的SMOTE算法。

3. 曲線移動:如果需要進行位移預測,比如早期預測,可以使用曲線移動。下方展示了curve_shift的執行。

4. 自定義度量:假陽率是不平衡二進制分類中的一個重要度量。可以如下方給出的class FalsePositiveRate()的執行所示,構建假陽率度量和其他自定義度量。

5. Selu激活函數:在現今所有的激活函數中,selu激活函數被認為是最好的。我並不完全同意這一點,但如果想要使用selu激活函數,可以使用kernel_initializer=’lecun_normal’和 AlphaDropout.在AlphaDropout中使用0.1比率,AlphaDropout(0.1) 。執行實例在下方給出。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

TensorFlow 2中的多層感知器(MLP)實例


在這個執行中,可以看到上述經驗法則中所提到的內容的實際操作。


上述執行是在TensorFlow 2中完成的。強烈建議所有人都轉戰使用TensorFlow 2。它不僅擁有Keras所具有的簡易性,還顯著地提升了計算效率。


本文目的並不是嘗試找到最好的模型,而是學習神經網絡的實現。不會為了簡化過程而跳過任何步驟。相反,本文給出的步驟都很詳細,以幫助讀者的直接應用。



%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as snsimport pandas as pd
import numpy as np
from pylab import rcParamsfrom collections import Counterimport tensorflow as tffrom tensorflow.keras import optimizers
from tensorflow.keras.models import Model, load_model, Sequential
from tensorflow.keras.layers import Input, Dense, Dropout, AlphaDropout
from tensorflow.keras.callbacks import ModelCheckpoint, TensorBoardfrom sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, precision_recall_curve
from sklearn.metrics import recall_score, classification_report, auc, roc_curve
from sklearn.metrics import precision_recall_fscore_support, f1_scorefrom numpy.random import seed
seed(1)SEED = 123 #used to help randomly select the data points
DATA_SPLIT_PCT = 0.2rcParams['figure.figsize'] = 8, 6
LABELS = ["Normal","Break"]


測試是否使用了正確的TensorFlow版本,運行:tf.__version__

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

讀取與準備數據


數據下載傳送門:https://docs.google.com/forms/d/e/1FAIpQLSdyUk3lfDl7I5KYK_pw285LCApc-_RcoC0Tf9cnDnZ_TWzPAw/viewform?source=post_page---------------------------


df = pd.read_csv("data/processminer-rare-event-mts - data.csv") 
df.head(n=5) # visualize the data.


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


將分類列轉換為獨熱編碼

hotencoding1 = pd.get_dummies(df['x28']) # Grade&Bwt
hotencoding1 = hotencoding1.add_prefix('grade_')
hotencoding2 = pd.get_dummies(df['x61']) # EventPress
hotencoding2 = hotencoding2.add_prefix('eventpress_')df=df.drop(['x28', 'x61'], axis=1)df=pd.concat([df, hotencoding1, hotencoding2], axis=1)


曲線移動


以下是一個時間序列數據,要求必須提前預測時間(y=1)。在這個數據中,連續行之間間隔兩分鐘。我們將把行y中的標籤移動兩行,以提前四分鐘進行預測。

sign = lambda x: (1, -1)[x < 0]def curve_shift(df, shift_by):
'''
This function will shift the binary labels in a dataframe.
The curve shift will be with respect to the 1s.
For example, if shift is -2, the following process
will happen: if row n is labeled as 1, then
- Make row (n+shift_by):(n+shift_by-1) = 1.
- Remove row n.
i.e. the labels will be shifted up to 2 rows up.

Inputs:
df A pandas dataframe with a binary labeled column.
This labeled column should be named as 'y'.
shift_by An integer denoting the number of rows to shift.

Output
df A dataframe with the binary labels shifted by shift.
'''vector = df['y'].copy()
for s in range(abs(shift_by)):
tmp = vector.shift(sign(shift_by))
tmp = tmp.fillna(0)
vector += tmp
labelcol = 'y'
# Add vector to the df
df.insert(loc=0, column=labelcol+'tmp', value=vector)
# Remove the rows with labelcol == 1.
df = df.drop(df[df[labelcol] == 1].index)
# Drop labelcol and rename the tmp col as labelcol
df = df.drop(labelcol, axis=1)
df = df.rename(columns={labelcol+'tmp': labelcol})
# Make the labelcol binary
df.loc[df[labelcol] > 0, labelcol] = 1return df


向上移動兩行


df = curve_shift(df, shift_by = -2)


從這裡開始不需要時間行了,將其移除。


df = df.drop(['time'], axis=1)


將數據分為訓練數據,有效數據和測試數據。

df_train, df_test = train_test_split(df, test_size=DATA_SPLIT_PCT, random_state=SEED)
df_train, df_valid = train_test_split(df_train, test_size=DATA_SPLIT_PCT, random_state=SEED)


把X和y分開

x_train = df_train.drop(['y'], axis=1)
y_train = df_train.y.valuesx_valid = df_valid.drop(['y'], axis=1)
y_valid = df_valid.y.valuesx_test = df_test.drop(['y'], axis=1)
y_test = df_test.y


數據縮放

scaler = MinMaxScaler().fit(x_train)
# scaler = StandardScaler().fit(x_train)
x_train_scaled = scaler.transform(x_train)
x_valid_scaled = scaler.transform(x_valid)
x_test_scaled = scaler.transform(x_test)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

MLP模型


自定義度量:FalsePositiveRate()


開發一個在下面所有模型中都要用到的FalsePositiveRate()度量。


class FalsePositiveRate(tf.keras.metrics.Metric):
def __init__(self, name='false_positive_rate', **kwargs):
super(FalsePositiveRate, self).__init__(name=name, **kwargs)
self.negatives = self.add_weight(name='negatives', initializer='zeros')
self.false_positives = self.add_weight(name='false_negatives', initializer='zeros')

def update_state(self, y_true, y_pred, sample_weight=None):
'''
Arguments:
y_true The actual y. Passed by default to Metric classes.
y_pred The predicted y. Passed by default to Metric classes.

'''
# Compute the number of negatives.
y_true = tf.cast(y_true, tf.bool)

negatives = tf.reduce_sum(tf.cast(tf.equal(y_true, False), self.dtype))

self.negatives.assign_add(negatives)

# Compute the number of false positives.
y_pred = tf.greater_equal(y_pred, 0.5) # Using default threshold of 0.5 to call a prediction as positive labeled.

false_positive_values = tf.logical_and(tf.equal(y_true, False), tf.equal(y_pred, True))
false_positive_values = tf.cast(false_positive_values, self.dtype)
if sample_weight is not None:
sample_weight = tf.cast(sample_weight, self.dtype)
sample_weight = tf.broadcast_weights(sample_weight, values)
values = tf.multiply(false_positive_values, sample_weight)

false_positives = tf.reduce_sum(false_positive_values)

self.false_positives.assign_add(false_positives)

def result(self):
return tf.divide(self.false_positives, self.negatives)


常規性能繪圖函數


def plot_loss(model_history):
train_loss=[value for key, value in model_history.items() if 'loss' in key.lower()][0]
valid_loss=[value for key, value in model_history.items() if 'loss' in key.lower()][1]fig, ax1 = plt.subplots()color = 'tab:blue'
ax1.set_xlabel('Epoch')
ax1.set_ylabel('Loss', color=color)
ax1.plot(train_loss, '--', color=color, label='Train Loss')
ax1.plot(valid_loss, color=color, label='Valid Loss')
ax1.tick_params(axis='y', labelcolor=color)
plt.legend(loc='upper left')
plt.title('Model Loss')plt.show()def plot_model_recall_fpr(model_history):
train_recall=[value for key, value in model_history.items() if 'recall' in key.lower()][0]
valid_recall=[value for key, value in model_history.items() if 'recall' in key.lower()][1]train_fpr=[value for key, value in model_history.items() if 'false_positive_rate' in key.lower()][0]
valid_fpr=[value for key, value in model_history.items() if 'false_positive_rate' in key.lower()][1]fig, ax1 = plt.subplots()color = 'tab:red'
ax1.set_xlabel('Epoch')
ax1.set_ylabel('Recall', color=color)
ax1.set_ylim([-0.05,1.05])
ax1.plot(train_recall, '--', color=color, label='Train Recall')
ax1.plot(valid_recall, color=color, label='Valid Recall')
ax1.tick_params(axis='y', labelcolor=color)
plt.legend(loc='upper left')
plt.title('Model Recall and FPR')ax2 = ax1.twinx() # instantiate a second axes that shares the same x-axiscolor = 'tab:blue'
ax2.set_ylabel('False Positive Rate', color=color) # we already handled the x-label with ax1
ax2.plot(train_fpr, '--', color=color, label='Train FPR')
ax2.plot(valid_fpr, color=color, label='Valid FPR')
ax2.tick_params(axis='y', labelcolor=color)
ax2.set_ylim([-0.05,1.05])fig.tight_layout() # otherwise the right y-label is slightly clipped
plt.legend(loc='upper right')
plt.show()


模型1.參照算法


n_features = x_train_scaled.shape[1]
mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dense(1, activation='sigmoid'))
mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid_scaled, y_valid),
verbose=0).history


觀察模型擬合損失和準確度(召回率和假陽率)變化


plot_loss(history)

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

plot_model_recall_fpr(history)

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

模型2.類權重


參照上文提到的經驗法則決定類權重。


class_weight = {0: sum(y_train == 1)/len(y_train), 1: sum(y_train == 0)/len(y_train)}


開始訓練模型。


n_features = x_train_scaled.shape[1]mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dense(1, activation='sigmoid'))mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid_scaled, y_valid),
class_weight=class_weight,
verbose=0).historyplot_loss(history)


"
全文共5505字,預計學習時長11分鐘或更長
代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

圖片來源:Unsplash/Dewang Gupta

通過本文的學習, 我們可以瞭解如何著手構建初始神經網絡, 學習經驗法則,比如:隱藏層的數量、節點的數量、激活並觀察其在TensorFlow2中的應用。


深度學習提供了種類繁多的模型。有了它們,就可以建立非常精確的預測模型。然而,由於設置參數數量巨大且種類繁多,要找到出發點會有些困難。


本文將帶領大家找到構建神經網絡的出發點,具體來說是以構建多層感知器為例子。雖然使用了多層感知器為例,但大多數法則都是普遍適用於神經網絡構建的。


整體思路是通過經驗法則先建立第一個神經網絡模型。如果第一個模型能合理運行(達到最低可接受精確度),就對其進行調整與優化。否則,就最好去查看數據和問題所在,或採用其他方法。


本文將介紹:

· 建立神經網絡的經驗法則。

· TensorFlow2中二進制分類的實施代碼。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

神經網絡


神經網絡在卷積神經網絡(CNN)、遞歸神經網絡(RNN)等領域都取得了巨大進步。且隨著時間的推移,每個神經網絡的幾個亞型都得到了發展。正是這一個個的進步,成功地提高了模型的預測能力。


但與此同時,找到模型構建的出發點也變得更難了。


每個神經網絡模型都是不同的,不同的模型有不同的特點和功能,所以在這種情況下,選擇適用的模型變得像在林立的廣告牌中選擇合適的商品一樣困難。


接下來,我們將利用經驗法則構建第一個模型,以克服這些干擾。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

經驗法則


在形形色色的神經網絡中,多層感知器是通往深度學習的敲門磚。因此,當學習或構建一個深度學習領域的模型時,多層感知器就是很好的出發點。


以下是構建多層感知器的經驗法則,且大多數法則都適用於其他深度學習模型。


1. 層數:從兩個隱藏層開始(這其中不包含最後一層)。

2. 中間層的節點數量(大小):是2的倍數,如4,8,16,32……第一層的節點數應該是輸入數據特徵數量的一半左右。下一層的大小是上一層的一半。

3. 分類層最後一層的節點數量(大小):如果是二進制分類,則節點大小為一。對於多類分類器,節點大小等於類的數量。

4. 迴歸層最後一層的大小:如果是單響應,最後一層的大小為1。對於多響應迴歸,最後一層的大小等於響應的數量。

5. 激活中間層,使用Relu激活函數。

6. 激活最後一層:如果是二進制分類,使用sigmoid函數,多類分類器使用softmax函數,迴歸則使用linear函數。對於自動編碼器,如果輸入數據是連續的,使用linear函數進行激活。對於二進制或多級分類輸入,使用sigmoid或softmax函數。

7. Dropout層:除了輸入層以外,在其他每個層都加設Dropout(如果單獨定義輸入層)。將Dropout率設置為0.5。Dropout率大於0.5時結果會適得其反。因此如果覺得0.5會使太多的節點正則化,可以選擇增加層的大小,而不是將Dropout率設置在0.5以下。筆者不喜歡在輸入層設置任何Dropout。但如果認為有必要這樣做,請把Dropout率設置在0.2以下。

8. 數據預處理:假設預測器X是數字,且已經將所有分類列轉化成了獨熱編碼。那麼就可以在進行模型訓練前使用MinMaxScalar對數據進行大小預處理。如果MMS不奏效,就在相同的數據庫中使用StandardScalar對數據進行標準化處理。整個數據處理過程不對y進行操作。

9. 將數據分為訓練數據,有效數據與測試數據:

使用sklearn.model_selection的train_test_split語句。具體操作見下方示例。

10. 類權重:如果數據不平衡,可以在model.fit中設置類權重以平衡損失。對於二進制分類器,權重應為:{0:1的數量/數據大小,1:0的數量/數據大小}。對於極不平衡數據(罕見事件),類權重可能不起作用,請小心添加使用。

11. 優化器:使用adam優化器,應用其默認學習率。

12. 分類損失:對於二進制分類,使用binary_crossentropy.對於多類別分類,如果標籤是獨熱編碼而成的,使用categorical_crossentropy。當標籤都是整數時,使用sparse_categorical_crossentropy 。

13. 迴歸損失:使用均方誤差(mse)函數。

14. 分類指標:使用accuracy顯示正確分類的百分比。對不平衡數據,也要加上tf.keras.metrics.Recall() 和 tf.keras.metrics.FalsePositives().

15. 迴歸指標:使用tf.keras.metrics.RootMeanSquaredError()。

16. 訓練週期:先從20開始,看模型訓練是否顯示出損失的減少,或任何在精確度上的提高。如果20個週期還沒有一點成果就換個方法。如果得到了些許成果,就把訓練週期提升到100。

17. 批處理大小:將批處理大小選擇為2的倍數,對於不平衡數據,通常選用較大值,如128,否則一般都從16開始選用。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


給高級從業人員的一些額外經驗法則


1. 振盪損耗:如果在訓練中遇到振盪損耗,則是由趨同問題導致的。遇到這種問題時,可以嘗試減小學習率和/或更改批處理大小。

2. 過採樣和欠採樣:如果數據不平衡,使用imblearn.over_sampling中的SMOTE算法。

3. 曲線移動:如果需要進行位移預測,比如早期預測,可以使用曲線移動。下方展示了curve_shift的執行。

4. 自定義度量:假陽率是不平衡二進制分類中的一個重要度量。可以如下方給出的class FalsePositiveRate()的執行所示,構建假陽率度量和其他自定義度量。

5. Selu激活函數:在現今所有的激活函數中,selu激活函數被認為是最好的。我並不完全同意這一點,但如果想要使用selu激活函數,可以使用kernel_initializer=’lecun_normal’和 AlphaDropout.在AlphaDropout中使用0.1比率,AlphaDropout(0.1) 。執行實例在下方給出。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

TensorFlow 2中的多層感知器(MLP)實例


在這個執行中,可以看到上述經驗法則中所提到的內容的實際操作。


上述執行是在TensorFlow 2中完成的。強烈建議所有人都轉戰使用TensorFlow 2。它不僅擁有Keras所具有的簡易性,還顯著地提升了計算效率。


本文目的並不是嘗試找到最好的模型,而是學習神經網絡的實現。不會為了簡化過程而跳過任何步驟。相反,本文給出的步驟都很詳細,以幫助讀者的直接應用。



%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as snsimport pandas as pd
import numpy as np
from pylab import rcParamsfrom collections import Counterimport tensorflow as tffrom tensorflow.keras import optimizers
from tensorflow.keras.models import Model, load_model, Sequential
from tensorflow.keras.layers import Input, Dense, Dropout, AlphaDropout
from tensorflow.keras.callbacks import ModelCheckpoint, TensorBoardfrom sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, precision_recall_curve
from sklearn.metrics import recall_score, classification_report, auc, roc_curve
from sklearn.metrics import precision_recall_fscore_support, f1_scorefrom numpy.random import seed
seed(1)SEED = 123 #used to help randomly select the data points
DATA_SPLIT_PCT = 0.2rcParams['figure.figsize'] = 8, 6
LABELS = ["Normal","Break"]


測試是否使用了正確的TensorFlow版本,運行:tf.__version__

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

讀取與準備數據


數據下載傳送門:https://docs.google.com/forms/d/e/1FAIpQLSdyUk3lfDl7I5KYK_pw285LCApc-_RcoC0Tf9cnDnZ_TWzPAw/viewform?source=post_page---------------------------


df = pd.read_csv("data/processminer-rare-event-mts - data.csv") 
df.head(n=5) # visualize the data.


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


將分類列轉換為獨熱編碼

hotencoding1 = pd.get_dummies(df['x28']) # Grade&Bwt
hotencoding1 = hotencoding1.add_prefix('grade_')
hotencoding2 = pd.get_dummies(df['x61']) # EventPress
hotencoding2 = hotencoding2.add_prefix('eventpress_')df=df.drop(['x28', 'x61'], axis=1)df=pd.concat([df, hotencoding1, hotencoding2], axis=1)


曲線移動


以下是一個時間序列數據,要求必須提前預測時間(y=1)。在這個數據中,連續行之間間隔兩分鐘。我們將把行y中的標籤移動兩行,以提前四分鐘進行預測。

sign = lambda x: (1, -1)[x < 0]def curve_shift(df, shift_by):
'''
This function will shift the binary labels in a dataframe.
The curve shift will be with respect to the 1s.
For example, if shift is -2, the following process
will happen: if row n is labeled as 1, then
- Make row (n+shift_by):(n+shift_by-1) = 1.
- Remove row n.
i.e. the labels will be shifted up to 2 rows up.

Inputs:
df A pandas dataframe with a binary labeled column.
This labeled column should be named as 'y'.
shift_by An integer denoting the number of rows to shift.

Output
df A dataframe with the binary labels shifted by shift.
'''vector = df['y'].copy()
for s in range(abs(shift_by)):
tmp = vector.shift(sign(shift_by))
tmp = tmp.fillna(0)
vector += tmp
labelcol = 'y'
# Add vector to the df
df.insert(loc=0, column=labelcol+'tmp', value=vector)
# Remove the rows with labelcol == 1.
df = df.drop(df[df[labelcol] == 1].index)
# Drop labelcol and rename the tmp col as labelcol
df = df.drop(labelcol, axis=1)
df = df.rename(columns={labelcol+'tmp': labelcol})
# Make the labelcol binary
df.loc[df[labelcol] > 0, labelcol] = 1return df


向上移動兩行


df = curve_shift(df, shift_by = -2)


從這裡開始不需要時間行了,將其移除。


df = df.drop(['time'], axis=1)


將數據分為訓練數據,有效數據和測試數據。

df_train, df_test = train_test_split(df, test_size=DATA_SPLIT_PCT, random_state=SEED)
df_train, df_valid = train_test_split(df_train, test_size=DATA_SPLIT_PCT, random_state=SEED)


把X和y分開

x_train = df_train.drop(['y'], axis=1)
y_train = df_train.y.valuesx_valid = df_valid.drop(['y'], axis=1)
y_valid = df_valid.y.valuesx_test = df_test.drop(['y'], axis=1)
y_test = df_test.y


數據縮放

scaler = MinMaxScaler().fit(x_train)
# scaler = StandardScaler().fit(x_train)
x_train_scaled = scaler.transform(x_train)
x_valid_scaled = scaler.transform(x_valid)
x_test_scaled = scaler.transform(x_test)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

MLP模型


自定義度量:FalsePositiveRate()


開發一個在下面所有模型中都要用到的FalsePositiveRate()度量。


class FalsePositiveRate(tf.keras.metrics.Metric):
def __init__(self, name='false_positive_rate', **kwargs):
super(FalsePositiveRate, self).__init__(name=name, **kwargs)
self.negatives = self.add_weight(name='negatives', initializer='zeros')
self.false_positives = self.add_weight(name='false_negatives', initializer='zeros')

def update_state(self, y_true, y_pred, sample_weight=None):
'''
Arguments:
y_true The actual y. Passed by default to Metric classes.
y_pred The predicted y. Passed by default to Metric classes.

'''
# Compute the number of negatives.
y_true = tf.cast(y_true, tf.bool)

negatives = tf.reduce_sum(tf.cast(tf.equal(y_true, False), self.dtype))

self.negatives.assign_add(negatives)

# Compute the number of false positives.
y_pred = tf.greater_equal(y_pred, 0.5) # Using default threshold of 0.5 to call a prediction as positive labeled.

false_positive_values = tf.logical_and(tf.equal(y_true, False), tf.equal(y_pred, True))
false_positive_values = tf.cast(false_positive_values, self.dtype)
if sample_weight is not None:
sample_weight = tf.cast(sample_weight, self.dtype)
sample_weight = tf.broadcast_weights(sample_weight, values)
values = tf.multiply(false_positive_values, sample_weight)

false_positives = tf.reduce_sum(false_positive_values)

self.false_positives.assign_add(false_positives)

def result(self):
return tf.divide(self.false_positives, self.negatives)


常規性能繪圖函數


def plot_loss(model_history):
train_loss=[value for key, value in model_history.items() if 'loss' in key.lower()][0]
valid_loss=[value for key, value in model_history.items() if 'loss' in key.lower()][1]fig, ax1 = plt.subplots()color = 'tab:blue'
ax1.set_xlabel('Epoch')
ax1.set_ylabel('Loss', color=color)
ax1.plot(train_loss, '--', color=color, label='Train Loss')
ax1.plot(valid_loss, color=color, label='Valid Loss')
ax1.tick_params(axis='y', labelcolor=color)
plt.legend(loc='upper left')
plt.title('Model Loss')plt.show()def plot_model_recall_fpr(model_history):
train_recall=[value for key, value in model_history.items() if 'recall' in key.lower()][0]
valid_recall=[value for key, value in model_history.items() if 'recall' in key.lower()][1]train_fpr=[value for key, value in model_history.items() if 'false_positive_rate' in key.lower()][0]
valid_fpr=[value for key, value in model_history.items() if 'false_positive_rate' in key.lower()][1]fig, ax1 = plt.subplots()color = 'tab:red'
ax1.set_xlabel('Epoch')
ax1.set_ylabel('Recall', color=color)
ax1.set_ylim([-0.05,1.05])
ax1.plot(train_recall, '--', color=color, label='Train Recall')
ax1.plot(valid_recall, color=color, label='Valid Recall')
ax1.tick_params(axis='y', labelcolor=color)
plt.legend(loc='upper left')
plt.title('Model Recall and FPR')ax2 = ax1.twinx() # instantiate a second axes that shares the same x-axiscolor = 'tab:blue'
ax2.set_ylabel('False Positive Rate', color=color) # we already handled the x-label with ax1
ax2.plot(train_fpr, '--', color=color, label='Train FPR')
ax2.plot(valid_fpr, color=color, label='Valid FPR')
ax2.tick_params(axis='y', labelcolor=color)
ax2.set_ylim([-0.05,1.05])fig.tight_layout() # otherwise the right y-label is slightly clipped
plt.legend(loc='upper right')
plt.show()


模型1.參照算法


n_features = x_train_scaled.shape[1]
mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dense(1, activation='sigmoid'))
mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid_scaled, y_valid),
verbose=0).history


觀察模型擬合損失和準確度(召回率和假陽率)變化


plot_loss(history)

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

plot_model_recall_fpr(history)

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

模型2.類權重


參照上文提到的經驗法則決定類權重。


class_weight = {0: sum(y_train == 1)/len(y_train), 1: sum(y_train == 0)/len(y_train)}


開始訓練模型。


n_features = x_train_scaled.shape[1]mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dense(1, activation='sigmoid'))mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid_scaled, y_valid),
class_weight=class_weight,
verbose=0).historyplot_loss(history)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


plot_model_recall_fpr(history)


"
全文共5505字,預計學習時長11分鐘或更長
代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

圖片來源:Unsplash/Dewang Gupta

通過本文的學習, 我們可以瞭解如何著手構建初始神經網絡, 學習經驗法則,比如:隱藏層的數量、節點的數量、激活並觀察其在TensorFlow2中的應用。


深度學習提供了種類繁多的模型。有了它們,就可以建立非常精確的預測模型。然而,由於設置參數數量巨大且種類繁多,要找到出發點會有些困難。


本文將帶領大家找到構建神經網絡的出發點,具體來說是以構建多層感知器為例子。雖然使用了多層感知器為例,但大多數法則都是普遍適用於神經網絡構建的。


整體思路是通過經驗法則先建立第一個神經網絡模型。如果第一個模型能合理運行(達到最低可接受精確度),就對其進行調整與優化。否則,就最好去查看數據和問題所在,或採用其他方法。


本文將介紹:

· 建立神經網絡的經驗法則。

· TensorFlow2中二進制分類的實施代碼。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

神經網絡


神經網絡在卷積神經網絡(CNN)、遞歸神經網絡(RNN)等領域都取得了巨大進步。且隨著時間的推移,每個神經網絡的幾個亞型都得到了發展。正是這一個個的進步,成功地提高了模型的預測能力。


但與此同時,找到模型構建的出發點也變得更難了。


每個神經網絡模型都是不同的,不同的模型有不同的特點和功能,所以在這種情況下,選擇適用的模型變得像在林立的廣告牌中選擇合適的商品一樣困難。


接下來,我們將利用經驗法則構建第一個模型,以克服這些干擾。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

經驗法則


在形形色色的神經網絡中,多層感知器是通往深度學習的敲門磚。因此,當學習或構建一個深度學習領域的模型時,多層感知器就是很好的出發點。


以下是構建多層感知器的經驗法則,且大多數法則都適用於其他深度學習模型。


1. 層數:從兩個隱藏層開始(這其中不包含最後一層)。

2. 中間層的節點數量(大小):是2的倍數,如4,8,16,32……第一層的節點數應該是輸入數據特徵數量的一半左右。下一層的大小是上一層的一半。

3. 分類層最後一層的節點數量(大小):如果是二進制分類,則節點大小為一。對於多類分類器,節點大小等於類的數量。

4. 迴歸層最後一層的大小:如果是單響應,最後一層的大小為1。對於多響應迴歸,最後一層的大小等於響應的數量。

5. 激活中間層,使用Relu激活函數。

6. 激活最後一層:如果是二進制分類,使用sigmoid函數,多類分類器使用softmax函數,迴歸則使用linear函數。對於自動編碼器,如果輸入數據是連續的,使用linear函數進行激活。對於二進制或多級分類輸入,使用sigmoid或softmax函數。

7. Dropout層:除了輸入層以外,在其他每個層都加設Dropout(如果單獨定義輸入層)。將Dropout率設置為0.5。Dropout率大於0.5時結果會適得其反。因此如果覺得0.5會使太多的節點正則化,可以選擇增加層的大小,而不是將Dropout率設置在0.5以下。筆者不喜歡在輸入層設置任何Dropout。但如果認為有必要這樣做,請把Dropout率設置在0.2以下。

8. 數據預處理:假設預測器X是數字,且已經將所有分類列轉化成了獨熱編碼。那麼就可以在進行模型訓練前使用MinMaxScalar對數據進行大小預處理。如果MMS不奏效,就在相同的數據庫中使用StandardScalar對數據進行標準化處理。整個數據處理過程不對y進行操作。

9. 將數據分為訓練數據,有效數據與測試數據:

使用sklearn.model_selection的train_test_split語句。具體操作見下方示例。

10. 類權重:如果數據不平衡,可以在model.fit中設置類權重以平衡損失。對於二進制分類器,權重應為:{0:1的數量/數據大小,1:0的數量/數據大小}。對於極不平衡數據(罕見事件),類權重可能不起作用,請小心添加使用。

11. 優化器:使用adam優化器,應用其默認學習率。

12. 分類損失:對於二進制分類,使用binary_crossentropy.對於多類別分類,如果標籤是獨熱編碼而成的,使用categorical_crossentropy。當標籤都是整數時,使用sparse_categorical_crossentropy 。

13. 迴歸損失:使用均方誤差(mse)函數。

14. 分類指標:使用accuracy顯示正確分類的百分比。對不平衡數據,也要加上tf.keras.metrics.Recall() 和 tf.keras.metrics.FalsePositives().

15. 迴歸指標:使用tf.keras.metrics.RootMeanSquaredError()。

16. 訓練週期:先從20開始,看模型訓練是否顯示出損失的減少,或任何在精確度上的提高。如果20個週期還沒有一點成果就換個方法。如果得到了些許成果,就把訓練週期提升到100。

17. 批處理大小:將批處理大小選擇為2的倍數,對於不平衡數據,通常選用較大值,如128,否則一般都從16開始選用。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


給高級從業人員的一些額外經驗法則


1. 振盪損耗:如果在訓練中遇到振盪損耗,則是由趨同問題導致的。遇到這種問題時,可以嘗試減小學習率和/或更改批處理大小。

2. 過採樣和欠採樣:如果數據不平衡,使用imblearn.over_sampling中的SMOTE算法。

3. 曲線移動:如果需要進行位移預測,比如早期預測,可以使用曲線移動。下方展示了curve_shift的執行。

4. 自定義度量:假陽率是不平衡二進制分類中的一個重要度量。可以如下方給出的class FalsePositiveRate()的執行所示,構建假陽率度量和其他自定義度量。

5. Selu激活函數:在現今所有的激活函數中,selu激活函數被認為是最好的。我並不完全同意這一點,但如果想要使用selu激活函數,可以使用kernel_initializer=’lecun_normal’和 AlphaDropout.在AlphaDropout中使用0.1比率,AlphaDropout(0.1) 。執行實例在下方給出。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

TensorFlow 2中的多層感知器(MLP)實例


在這個執行中,可以看到上述經驗法則中所提到的內容的實際操作。


上述執行是在TensorFlow 2中完成的。強烈建議所有人都轉戰使用TensorFlow 2。它不僅擁有Keras所具有的簡易性,還顯著地提升了計算效率。


本文目的並不是嘗試找到最好的模型,而是學習神經網絡的實現。不會為了簡化過程而跳過任何步驟。相反,本文給出的步驟都很詳細,以幫助讀者的直接應用。



%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as snsimport pandas as pd
import numpy as np
from pylab import rcParamsfrom collections import Counterimport tensorflow as tffrom tensorflow.keras import optimizers
from tensorflow.keras.models import Model, load_model, Sequential
from tensorflow.keras.layers import Input, Dense, Dropout, AlphaDropout
from tensorflow.keras.callbacks import ModelCheckpoint, TensorBoardfrom sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, precision_recall_curve
from sklearn.metrics import recall_score, classification_report, auc, roc_curve
from sklearn.metrics import precision_recall_fscore_support, f1_scorefrom numpy.random import seed
seed(1)SEED = 123 #used to help randomly select the data points
DATA_SPLIT_PCT = 0.2rcParams['figure.figsize'] = 8, 6
LABELS = ["Normal","Break"]


測試是否使用了正確的TensorFlow版本,運行:tf.__version__

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

讀取與準備數據


數據下載傳送門:https://docs.google.com/forms/d/e/1FAIpQLSdyUk3lfDl7I5KYK_pw285LCApc-_RcoC0Tf9cnDnZ_TWzPAw/viewform?source=post_page---------------------------


df = pd.read_csv("data/processminer-rare-event-mts - data.csv") 
df.head(n=5) # visualize the data.


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


將分類列轉換為獨熱編碼

hotencoding1 = pd.get_dummies(df['x28']) # Grade&Bwt
hotencoding1 = hotencoding1.add_prefix('grade_')
hotencoding2 = pd.get_dummies(df['x61']) # EventPress
hotencoding2 = hotencoding2.add_prefix('eventpress_')df=df.drop(['x28', 'x61'], axis=1)df=pd.concat([df, hotencoding1, hotencoding2], axis=1)


曲線移動


以下是一個時間序列數據,要求必須提前預測時間(y=1)。在這個數據中,連續行之間間隔兩分鐘。我們將把行y中的標籤移動兩行,以提前四分鐘進行預測。

sign = lambda x: (1, -1)[x < 0]def curve_shift(df, shift_by):
'''
This function will shift the binary labels in a dataframe.
The curve shift will be with respect to the 1s.
For example, if shift is -2, the following process
will happen: if row n is labeled as 1, then
- Make row (n+shift_by):(n+shift_by-1) = 1.
- Remove row n.
i.e. the labels will be shifted up to 2 rows up.

Inputs:
df A pandas dataframe with a binary labeled column.
This labeled column should be named as 'y'.
shift_by An integer denoting the number of rows to shift.

Output
df A dataframe with the binary labels shifted by shift.
'''vector = df['y'].copy()
for s in range(abs(shift_by)):
tmp = vector.shift(sign(shift_by))
tmp = tmp.fillna(0)
vector += tmp
labelcol = 'y'
# Add vector to the df
df.insert(loc=0, column=labelcol+'tmp', value=vector)
# Remove the rows with labelcol == 1.
df = df.drop(df[df[labelcol] == 1].index)
# Drop labelcol and rename the tmp col as labelcol
df = df.drop(labelcol, axis=1)
df = df.rename(columns={labelcol+'tmp': labelcol})
# Make the labelcol binary
df.loc[df[labelcol] > 0, labelcol] = 1return df


向上移動兩行


df = curve_shift(df, shift_by = -2)


從這裡開始不需要時間行了,將其移除。


df = df.drop(['time'], axis=1)


將數據分為訓練數據,有效數據和測試數據。

df_train, df_test = train_test_split(df, test_size=DATA_SPLIT_PCT, random_state=SEED)
df_train, df_valid = train_test_split(df_train, test_size=DATA_SPLIT_PCT, random_state=SEED)


把X和y分開

x_train = df_train.drop(['y'], axis=1)
y_train = df_train.y.valuesx_valid = df_valid.drop(['y'], axis=1)
y_valid = df_valid.y.valuesx_test = df_test.drop(['y'], axis=1)
y_test = df_test.y


數據縮放

scaler = MinMaxScaler().fit(x_train)
# scaler = StandardScaler().fit(x_train)
x_train_scaled = scaler.transform(x_train)
x_valid_scaled = scaler.transform(x_valid)
x_test_scaled = scaler.transform(x_test)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

MLP模型


自定義度量:FalsePositiveRate()


開發一個在下面所有模型中都要用到的FalsePositiveRate()度量。


class FalsePositiveRate(tf.keras.metrics.Metric):
def __init__(self, name='false_positive_rate', **kwargs):
super(FalsePositiveRate, self).__init__(name=name, **kwargs)
self.negatives = self.add_weight(name='negatives', initializer='zeros')
self.false_positives = self.add_weight(name='false_negatives', initializer='zeros')

def update_state(self, y_true, y_pred, sample_weight=None):
'''
Arguments:
y_true The actual y. Passed by default to Metric classes.
y_pred The predicted y. Passed by default to Metric classes.

'''
# Compute the number of negatives.
y_true = tf.cast(y_true, tf.bool)

negatives = tf.reduce_sum(tf.cast(tf.equal(y_true, False), self.dtype))

self.negatives.assign_add(negatives)

# Compute the number of false positives.
y_pred = tf.greater_equal(y_pred, 0.5) # Using default threshold of 0.5 to call a prediction as positive labeled.

false_positive_values = tf.logical_and(tf.equal(y_true, False), tf.equal(y_pred, True))
false_positive_values = tf.cast(false_positive_values, self.dtype)
if sample_weight is not None:
sample_weight = tf.cast(sample_weight, self.dtype)
sample_weight = tf.broadcast_weights(sample_weight, values)
values = tf.multiply(false_positive_values, sample_weight)

false_positives = tf.reduce_sum(false_positive_values)

self.false_positives.assign_add(false_positives)

def result(self):
return tf.divide(self.false_positives, self.negatives)


常規性能繪圖函數


def plot_loss(model_history):
train_loss=[value for key, value in model_history.items() if 'loss' in key.lower()][0]
valid_loss=[value for key, value in model_history.items() if 'loss' in key.lower()][1]fig, ax1 = plt.subplots()color = 'tab:blue'
ax1.set_xlabel('Epoch')
ax1.set_ylabel('Loss', color=color)
ax1.plot(train_loss, '--', color=color, label='Train Loss')
ax1.plot(valid_loss, color=color, label='Valid Loss')
ax1.tick_params(axis='y', labelcolor=color)
plt.legend(loc='upper left')
plt.title('Model Loss')plt.show()def plot_model_recall_fpr(model_history):
train_recall=[value for key, value in model_history.items() if 'recall' in key.lower()][0]
valid_recall=[value for key, value in model_history.items() if 'recall' in key.lower()][1]train_fpr=[value for key, value in model_history.items() if 'false_positive_rate' in key.lower()][0]
valid_fpr=[value for key, value in model_history.items() if 'false_positive_rate' in key.lower()][1]fig, ax1 = plt.subplots()color = 'tab:red'
ax1.set_xlabel('Epoch')
ax1.set_ylabel('Recall', color=color)
ax1.set_ylim([-0.05,1.05])
ax1.plot(train_recall, '--', color=color, label='Train Recall')
ax1.plot(valid_recall, color=color, label='Valid Recall')
ax1.tick_params(axis='y', labelcolor=color)
plt.legend(loc='upper left')
plt.title('Model Recall and FPR')ax2 = ax1.twinx() # instantiate a second axes that shares the same x-axiscolor = 'tab:blue'
ax2.set_ylabel('False Positive Rate', color=color) # we already handled the x-label with ax1
ax2.plot(train_fpr, '--', color=color, label='Train FPR')
ax2.plot(valid_fpr, color=color, label='Valid FPR')
ax2.tick_params(axis='y', labelcolor=color)
ax2.set_ylim([-0.05,1.05])fig.tight_layout() # otherwise the right y-label is slightly clipped
plt.legend(loc='upper right')
plt.show()


模型1.參照算法


n_features = x_train_scaled.shape[1]
mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dense(1, activation='sigmoid'))
mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid_scaled, y_valid),
verbose=0).history


觀察模型擬合損失和準確度(召回率和假陽率)變化


plot_loss(history)

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

plot_model_recall_fpr(history)

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

模型2.類權重


參照上文提到的經驗法則決定類權重。


class_weight = {0: sum(y_train == 1)/len(y_train), 1: sum(y_train == 0)/len(y_train)}


開始訓練模型。


n_features = x_train_scaled.shape[1]mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dense(1, activation='sigmoid'))mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid_scaled, y_valid),
class_weight=class_weight,
verbose=0).historyplot_loss(history)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


plot_model_recall_fpr(history)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

模型3. Dropout正則化


n_features = x_train_scaled.shape[1]mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dropout(0.5))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dropout(0.5))
mlp.add(Dense(1, activation='sigmoid'))mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid_scaled, y_valid),
class_weight=class_weight,
verbose=0).historyplot_loss(history)
"
全文共5505字,預計學習時長11分鐘或更長
代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

圖片來源:Unsplash/Dewang Gupta

通過本文的學習, 我們可以瞭解如何著手構建初始神經網絡, 學習經驗法則,比如:隱藏層的數量、節點的數量、激活並觀察其在TensorFlow2中的應用。


深度學習提供了種類繁多的模型。有了它們,就可以建立非常精確的預測模型。然而,由於設置參數數量巨大且種類繁多,要找到出發點會有些困難。


本文將帶領大家找到構建神經網絡的出發點,具體來說是以構建多層感知器為例子。雖然使用了多層感知器為例,但大多數法則都是普遍適用於神經網絡構建的。


整體思路是通過經驗法則先建立第一個神經網絡模型。如果第一個模型能合理運行(達到最低可接受精確度),就對其進行調整與優化。否則,就最好去查看數據和問題所在,或採用其他方法。


本文將介紹:

· 建立神經網絡的經驗法則。

· TensorFlow2中二進制分類的實施代碼。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

神經網絡


神經網絡在卷積神經網絡(CNN)、遞歸神經網絡(RNN)等領域都取得了巨大進步。且隨著時間的推移,每個神經網絡的幾個亞型都得到了發展。正是這一個個的進步,成功地提高了模型的預測能力。


但與此同時,找到模型構建的出發點也變得更難了。


每個神經網絡模型都是不同的,不同的模型有不同的特點和功能,所以在這種情況下,選擇適用的模型變得像在林立的廣告牌中選擇合適的商品一樣困難。


接下來,我們將利用經驗法則構建第一個模型,以克服這些干擾。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

經驗法則


在形形色色的神經網絡中,多層感知器是通往深度學習的敲門磚。因此,當學習或構建一個深度學習領域的模型時,多層感知器就是很好的出發點。


以下是構建多層感知器的經驗法則,且大多數法則都適用於其他深度學習模型。


1. 層數:從兩個隱藏層開始(這其中不包含最後一層)。

2. 中間層的節點數量(大小):是2的倍數,如4,8,16,32……第一層的節點數應該是輸入數據特徵數量的一半左右。下一層的大小是上一層的一半。

3. 分類層最後一層的節點數量(大小):如果是二進制分類,則節點大小為一。對於多類分類器,節點大小等於類的數量。

4. 迴歸層最後一層的大小:如果是單響應,最後一層的大小為1。對於多響應迴歸,最後一層的大小等於響應的數量。

5. 激活中間層,使用Relu激活函數。

6. 激活最後一層:如果是二進制分類,使用sigmoid函數,多類分類器使用softmax函數,迴歸則使用linear函數。對於自動編碼器,如果輸入數據是連續的,使用linear函數進行激活。對於二進制或多級分類輸入,使用sigmoid或softmax函數。

7. Dropout層:除了輸入層以外,在其他每個層都加設Dropout(如果單獨定義輸入層)。將Dropout率設置為0.5。Dropout率大於0.5時結果會適得其反。因此如果覺得0.5會使太多的節點正則化,可以選擇增加層的大小,而不是將Dropout率設置在0.5以下。筆者不喜歡在輸入層設置任何Dropout。但如果認為有必要這樣做,請把Dropout率設置在0.2以下。

8. 數據預處理:假設預測器X是數字,且已經將所有分類列轉化成了獨熱編碼。那麼就可以在進行模型訓練前使用MinMaxScalar對數據進行大小預處理。如果MMS不奏效,就在相同的數據庫中使用StandardScalar對數據進行標準化處理。整個數據處理過程不對y進行操作。

9. 將數據分為訓練數據,有效數據與測試數據:

使用sklearn.model_selection的train_test_split語句。具體操作見下方示例。

10. 類權重:如果數據不平衡,可以在model.fit中設置類權重以平衡損失。對於二進制分類器,權重應為:{0:1的數量/數據大小,1:0的數量/數據大小}。對於極不平衡數據(罕見事件),類權重可能不起作用,請小心添加使用。

11. 優化器:使用adam優化器,應用其默認學習率。

12. 分類損失:對於二進制分類,使用binary_crossentropy.對於多類別分類,如果標籤是獨熱編碼而成的,使用categorical_crossentropy。當標籤都是整數時,使用sparse_categorical_crossentropy 。

13. 迴歸損失:使用均方誤差(mse)函數。

14. 分類指標:使用accuracy顯示正確分類的百分比。對不平衡數據,也要加上tf.keras.metrics.Recall() 和 tf.keras.metrics.FalsePositives().

15. 迴歸指標:使用tf.keras.metrics.RootMeanSquaredError()。

16. 訓練週期:先從20開始,看模型訓練是否顯示出損失的減少,或任何在精確度上的提高。如果20個週期還沒有一點成果就換個方法。如果得到了些許成果,就把訓練週期提升到100。

17. 批處理大小:將批處理大小選擇為2的倍數,對於不平衡數據,通常選用較大值,如128,否則一般都從16開始選用。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


給高級從業人員的一些額外經驗法則


1. 振盪損耗:如果在訓練中遇到振盪損耗,則是由趨同問題導致的。遇到這種問題時,可以嘗試減小學習率和/或更改批處理大小。

2. 過採樣和欠採樣:如果數據不平衡,使用imblearn.over_sampling中的SMOTE算法。

3. 曲線移動:如果需要進行位移預測,比如早期預測,可以使用曲線移動。下方展示了curve_shift的執行。

4. 自定義度量:假陽率是不平衡二進制分類中的一個重要度量。可以如下方給出的class FalsePositiveRate()的執行所示,構建假陽率度量和其他自定義度量。

5. Selu激活函數:在現今所有的激活函數中,selu激活函數被認為是最好的。我並不完全同意這一點,但如果想要使用selu激活函數,可以使用kernel_initializer=’lecun_normal’和 AlphaDropout.在AlphaDropout中使用0.1比率,AlphaDropout(0.1) 。執行實例在下方給出。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

TensorFlow 2中的多層感知器(MLP)實例


在這個執行中,可以看到上述經驗法則中所提到的內容的實際操作。


上述執行是在TensorFlow 2中完成的。強烈建議所有人都轉戰使用TensorFlow 2。它不僅擁有Keras所具有的簡易性,還顯著地提升了計算效率。


本文目的並不是嘗試找到最好的模型,而是學習神經網絡的實現。不會為了簡化過程而跳過任何步驟。相反,本文給出的步驟都很詳細,以幫助讀者的直接應用。



%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as snsimport pandas as pd
import numpy as np
from pylab import rcParamsfrom collections import Counterimport tensorflow as tffrom tensorflow.keras import optimizers
from tensorflow.keras.models import Model, load_model, Sequential
from tensorflow.keras.layers import Input, Dense, Dropout, AlphaDropout
from tensorflow.keras.callbacks import ModelCheckpoint, TensorBoardfrom sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, precision_recall_curve
from sklearn.metrics import recall_score, classification_report, auc, roc_curve
from sklearn.metrics import precision_recall_fscore_support, f1_scorefrom numpy.random import seed
seed(1)SEED = 123 #used to help randomly select the data points
DATA_SPLIT_PCT = 0.2rcParams['figure.figsize'] = 8, 6
LABELS = ["Normal","Break"]


測試是否使用了正確的TensorFlow版本,運行:tf.__version__

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

讀取與準備數據


數據下載傳送門:https://docs.google.com/forms/d/e/1FAIpQLSdyUk3lfDl7I5KYK_pw285LCApc-_RcoC0Tf9cnDnZ_TWzPAw/viewform?source=post_page---------------------------


df = pd.read_csv("data/processminer-rare-event-mts - data.csv") 
df.head(n=5) # visualize the data.


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


將分類列轉換為獨熱編碼

hotencoding1 = pd.get_dummies(df['x28']) # Grade&Bwt
hotencoding1 = hotencoding1.add_prefix('grade_')
hotencoding2 = pd.get_dummies(df['x61']) # EventPress
hotencoding2 = hotencoding2.add_prefix('eventpress_')df=df.drop(['x28', 'x61'], axis=1)df=pd.concat([df, hotencoding1, hotencoding2], axis=1)


曲線移動


以下是一個時間序列數據,要求必須提前預測時間(y=1)。在這個數據中,連續行之間間隔兩分鐘。我們將把行y中的標籤移動兩行,以提前四分鐘進行預測。

sign = lambda x: (1, -1)[x < 0]def curve_shift(df, shift_by):
'''
This function will shift the binary labels in a dataframe.
The curve shift will be with respect to the 1s.
For example, if shift is -2, the following process
will happen: if row n is labeled as 1, then
- Make row (n+shift_by):(n+shift_by-1) = 1.
- Remove row n.
i.e. the labels will be shifted up to 2 rows up.

Inputs:
df A pandas dataframe with a binary labeled column.
This labeled column should be named as 'y'.
shift_by An integer denoting the number of rows to shift.

Output
df A dataframe with the binary labels shifted by shift.
'''vector = df['y'].copy()
for s in range(abs(shift_by)):
tmp = vector.shift(sign(shift_by))
tmp = tmp.fillna(0)
vector += tmp
labelcol = 'y'
# Add vector to the df
df.insert(loc=0, column=labelcol+'tmp', value=vector)
# Remove the rows with labelcol == 1.
df = df.drop(df[df[labelcol] == 1].index)
# Drop labelcol and rename the tmp col as labelcol
df = df.drop(labelcol, axis=1)
df = df.rename(columns={labelcol+'tmp': labelcol})
# Make the labelcol binary
df.loc[df[labelcol] > 0, labelcol] = 1return df


向上移動兩行


df = curve_shift(df, shift_by = -2)


從這裡開始不需要時間行了,將其移除。


df = df.drop(['time'], axis=1)


將數據分為訓練數據,有效數據和測試數據。

df_train, df_test = train_test_split(df, test_size=DATA_SPLIT_PCT, random_state=SEED)
df_train, df_valid = train_test_split(df_train, test_size=DATA_SPLIT_PCT, random_state=SEED)


把X和y分開

x_train = df_train.drop(['y'], axis=1)
y_train = df_train.y.valuesx_valid = df_valid.drop(['y'], axis=1)
y_valid = df_valid.y.valuesx_test = df_test.drop(['y'], axis=1)
y_test = df_test.y


數據縮放

scaler = MinMaxScaler().fit(x_train)
# scaler = StandardScaler().fit(x_train)
x_train_scaled = scaler.transform(x_train)
x_valid_scaled = scaler.transform(x_valid)
x_test_scaled = scaler.transform(x_test)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

MLP模型


自定義度量:FalsePositiveRate()


開發一個在下面所有模型中都要用到的FalsePositiveRate()度量。


class FalsePositiveRate(tf.keras.metrics.Metric):
def __init__(self, name='false_positive_rate', **kwargs):
super(FalsePositiveRate, self).__init__(name=name, **kwargs)
self.negatives = self.add_weight(name='negatives', initializer='zeros')
self.false_positives = self.add_weight(name='false_negatives', initializer='zeros')

def update_state(self, y_true, y_pred, sample_weight=None):
'''
Arguments:
y_true The actual y. Passed by default to Metric classes.
y_pred The predicted y. Passed by default to Metric classes.

'''
# Compute the number of negatives.
y_true = tf.cast(y_true, tf.bool)

negatives = tf.reduce_sum(tf.cast(tf.equal(y_true, False), self.dtype))

self.negatives.assign_add(negatives)

# Compute the number of false positives.
y_pred = tf.greater_equal(y_pred, 0.5) # Using default threshold of 0.5 to call a prediction as positive labeled.

false_positive_values = tf.logical_and(tf.equal(y_true, False), tf.equal(y_pred, True))
false_positive_values = tf.cast(false_positive_values, self.dtype)
if sample_weight is not None:
sample_weight = tf.cast(sample_weight, self.dtype)
sample_weight = tf.broadcast_weights(sample_weight, values)
values = tf.multiply(false_positive_values, sample_weight)

false_positives = tf.reduce_sum(false_positive_values)

self.false_positives.assign_add(false_positives)

def result(self):
return tf.divide(self.false_positives, self.negatives)


常規性能繪圖函數


def plot_loss(model_history):
train_loss=[value for key, value in model_history.items() if 'loss' in key.lower()][0]
valid_loss=[value for key, value in model_history.items() if 'loss' in key.lower()][1]fig, ax1 = plt.subplots()color = 'tab:blue'
ax1.set_xlabel('Epoch')
ax1.set_ylabel('Loss', color=color)
ax1.plot(train_loss, '--', color=color, label='Train Loss')
ax1.plot(valid_loss, color=color, label='Valid Loss')
ax1.tick_params(axis='y', labelcolor=color)
plt.legend(loc='upper left')
plt.title('Model Loss')plt.show()def plot_model_recall_fpr(model_history):
train_recall=[value for key, value in model_history.items() if 'recall' in key.lower()][0]
valid_recall=[value for key, value in model_history.items() if 'recall' in key.lower()][1]train_fpr=[value for key, value in model_history.items() if 'false_positive_rate' in key.lower()][0]
valid_fpr=[value for key, value in model_history.items() if 'false_positive_rate' in key.lower()][1]fig, ax1 = plt.subplots()color = 'tab:red'
ax1.set_xlabel('Epoch')
ax1.set_ylabel('Recall', color=color)
ax1.set_ylim([-0.05,1.05])
ax1.plot(train_recall, '--', color=color, label='Train Recall')
ax1.plot(valid_recall, color=color, label='Valid Recall')
ax1.tick_params(axis='y', labelcolor=color)
plt.legend(loc='upper left')
plt.title('Model Recall and FPR')ax2 = ax1.twinx() # instantiate a second axes that shares the same x-axiscolor = 'tab:blue'
ax2.set_ylabel('False Positive Rate', color=color) # we already handled the x-label with ax1
ax2.plot(train_fpr, '--', color=color, label='Train FPR')
ax2.plot(valid_fpr, color=color, label='Valid FPR')
ax2.tick_params(axis='y', labelcolor=color)
ax2.set_ylim([-0.05,1.05])fig.tight_layout() # otherwise the right y-label is slightly clipped
plt.legend(loc='upper right')
plt.show()


模型1.參照算法


n_features = x_train_scaled.shape[1]
mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dense(1, activation='sigmoid'))
mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid_scaled, y_valid),
verbose=0).history


觀察模型擬合損失和準確度(召回率和假陽率)變化


plot_loss(history)

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

plot_model_recall_fpr(history)

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

模型2.類權重


參照上文提到的經驗法則決定類權重。


class_weight = {0: sum(y_train == 1)/len(y_train), 1: sum(y_train == 0)/len(y_train)}


開始訓練模型。


n_features = x_train_scaled.shape[1]mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dense(1, activation='sigmoid'))mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid_scaled, y_valid),
class_weight=class_weight,
verbose=0).historyplot_loss(history)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


plot_model_recall_fpr(history)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

模型3. Dropout正則化


n_features = x_train_scaled.shape[1]mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dropout(0.5))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dropout(0.5))
mlp.add(Dense(1, activation='sigmoid'))mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid_scaled, y_valid),
class_weight=class_weight,
verbose=0).historyplot_loss(history)
代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

plot_model_recall_fpr(history)

"
全文共5505字,預計學習時長11分鐘或更長
代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

圖片來源:Unsplash/Dewang Gupta

通過本文的學習, 我們可以瞭解如何著手構建初始神經網絡, 學習經驗法則,比如:隱藏層的數量、節點的數量、激活並觀察其在TensorFlow2中的應用。


深度學習提供了種類繁多的模型。有了它們,就可以建立非常精確的預測模型。然而,由於設置參數數量巨大且種類繁多,要找到出發點會有些困難。


本文將帶領大家找到構建神經網絡的出發點,具體來說是以構建多層感知器為例子。雖然使用了多層感知器為例,但大多數法則都是普遍適用於神經網絡構建的。


整體思路是通過經驗法則先建立第一個神經網絡模型。如果第一個模型能合理運行(達到最低可接受精確度),就對其進行調整與優化。否則,就最好去查看數據和問題所在,或採用其他方法。


本文將介紹:

· 建立神經網絡的經驗法則。

· TensorFlow2中二進制分類的實施代碼。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

神經網絡


神經網絡在卷積神經網絡(CNN)、遞歸神經網絡(RNN)等領域都取得了巨大進步。且隨著時間的推移,每個神經網絡的幾個亞型都得到了發展。正是這一個個的進步,成功地提高了模型的預測能力。


但與此同時,找到模型構建的出發點也變得更難了。


每個神經網絡模型都是不同的,不同的模型有不同的特點和功能,所以在這種情況下,選擇適用的模型變得像在林立的廣告牌中選擇合適的商品一樣困難。


接下來,我們將利用經驗法則構建第一個模型,以克服這些干擾。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

經驗法則


在形形色色的神經網絡中,多層感知器是通往深度學習的敲門磚。因此,當學習或構建一個深度學習領域的模型時,多層感知器就是很好的出發點。


以下是構建多層感知器的經驗法則,且大多數法則都適用於其他深度學習模型。


1. 層數:從兩個隱藏層開始(這其中不包含最後一層)。

2. 中間層的節點數量(大小):是2的倍數,如4,8,16,32……第一層的節點數應該是輸入數據特徵數量的一半左右。下一層的大小是上一層的一半。

3. 分類層最後一層的節點數量(大小):如果是二進制分類,則節點大小為一。對於多類分類器,節點大小等於類的數量。

4. 迴歸層最後一層的大小:如果是單響應,最後一層的大小為1。對於多響應迴歸,最後一層的大小等於響應的數量。

5. 激活中間層,使用Relu激活函數。

6. 激活最後一層:如果是二進制分類,使用sigmoid函數,多類分類器使用softmax函數,迴歸則使用linear函數。對於自動編碼器,如果輸入數據是連續的,使用linear函數進行激活。對於二進制或多級分類輸入,使用sigmoid或softmax函數。

7. Dropout層:除了輸入層以外,在其他每個層都加設Dropout(如果單獨定義輸入層)。將Dropout率設置為0.5。Dropout率大於0.5時結果會適得其反。因此如果覺得0.5會使太多的節點正則化,可以選擇增加層的大小,而不是將Dropout率設置在0.5以下。筆者不喜歡在輸入層設置任何Dropout。但如果認為有必要這樣做,請把Dropout率設置在0.2以下。

8. 數據預處理:假設預測器X是數字,且已經將所有分類列轉化成了獨熱編碼。那麼就可以在進行模型訓練前使用MinMaxScalar對數據進行大小預處理。如果MMS不奏效,就在相同的數據庫中使用StandardScalar對數據進行標準化處理。整個數據處理過程不對y進行操作。

9. 將數據分為訓練數據,有效數據與測試數據:

使用sklearn.model_selection的train_test_split語句。具體操作見下方示例。

10. 類權重:如果數據不平衡,可以在model.fit中設置類權重以平衡損失。對於二進制分類器,權重應為:{0:1的數量/數據大小,1:0的數量/數據大小}。對於極不平衡數據(罕見事件),類權重可能不起作用,請小心添加使用。

11. 優化器:使用adam優化器,應用其默認學習率。

12. 分類損失:對於二進制分類,使用binary_crossentropy.對於多類別分類,如果標籤是獨熱編碼而成的,使用categorical_crossentropy。當標籤都是整數時,使用sparse_categorical_crossentropy 。

13. 迴歸損失:使用均方誤差(mse)函數。

14. 分類指標:使用accuracy顯示正確分類的百分比。對不平衡數據,也要加上tf.keras.metrics.Recall() 和 tf.keras.metrics.FalsePositives().

15. 迴歸指標:使用tf.keras.metrics.RootMeanSquaredError()。

16. 訓練週期:先從20開始,看模型訓練是否顯示出損失的減少,或任何在精確度上的提高。如果20個週期還沒有一點成果就換個方法。如果得到了些許成果,就把訓練週期提升到100。

17. 批處理大小:將批處理大小選擇為2的倍數,對於不平衡數據,通常選用較大值,如128,否則一般都從16開始選用。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


給高級從業人員的一些額外經驗法則


1. 振盪損耗:如果在訓練中遇到振盪損耗,則是由趨同問題導致的。遇到這種問題時,可以嘗試減小學習率和/或更改批處理大小。

2. 過採樣和欠採樣:如果數據不平衡,使用imblearn.over_sampling中的SMOTE算法。

3. 曲線移動:如果需要進行位移預測,比如早期預測,可以使用曲線移動。下方展示了curve_shift的執行。

4. 自定義度量:假陽率是不平衡二進制分類中的一個重要度量。可以如下方給出的class FalsePositiveRate()的執行所示,構建假陽率度量和其他自定義度量。

5. Selu激活函數:在現今所有的激活函數中,selu激活函數被認為是最好的。我並不完全同意這一點,但如果想要使用selu激活函數,可以使用kernel_initializer=’lecun_normal’和 AlphaDropout.在AlphaDropout中使用0.1比率,AlphaDropout(0.1) 。執行實例在下方給出。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

TensorFlow 2中的多層感知器(MLP)實例


在這個執行中,可以看到上述經驗法則中所提到的內容的實際操作。


上述執行是在TensorFlow 2中完成的。強烈建議所有人都轉戰使用TensorFlow 2。它不僅擁有Keras所具有的簡易性,還顯著地提升了計算效率。


本文目的並不是嘗試找到最好的模型,而是學習神經網絡的實現。不會為了簡化過程而跳過任何步驟。相反,本文給出的步驟都很詳細,以幫助讀者的直接應用。



%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as snsimport pandas as pd
import numpy as np
from pylab import rcParamsfrom collections import Counterimport tensorflow as tffrom tensorflow.keras import optimizers
from tensorflow.keras.models import Model, load_model, Sequential
from tensorflow.keras.layers import Input, Dense, Dropout, AlphaDropout
from tensorflow.keras.callbacks import ModelCheckpoint, TensorBoardfrom sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, precision_recall_curve
from sklearn.metrics import recall_score, classification_report, auc, roc_curve
from sklearn.metrics import precision_recall_fscore_support, f1_scorefrom numpy.random import seed
seed(1)SEED = 123 #used to help randomly select the data points
DATA_SPLIT_PCT = 0.2rcParams['figure.figsize'] = 8, 6
LABELS = ["Normal","Break"]


測試是否使用了正確的TensorFlow版本,運行:tf.__version__

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

讀取與準備數據


數據下載傳送門:https://docs.google.com/forms/d/e/1FAIpQLSdyUk3lfDl7I5KYK_pw285LCApc-_RcoC0Tf9cnDnZ_TWzPAw/viewform?source=post_page---------------------------


df = pd.read_csv("data/processminer-rare-event-mts - data.csv") 
df.head(n=5) # visualize the data.


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


將分類列轉換為獨熱編碼

hotencoding1 = pd.get_dummies(df['x28']) # Grade&Bwt
hotencoding1 = hotencoding1.add_prefix('grade_')
hotencoding2 = pd.get_dummies(df['x61']) # EventPress
hotencoding2 = hotencoding2.add_prefix('eventpress_')df=df.drop(['x28', 'x61'], axis=1)df=pd.concat([df, hotencoding1, hotencoding2], axis=1)


曲線移動


以下是一個時間序列數據,要求必須提前預測時間(y=1)。在這個數據中,連續行之間間隔兩分鐘。我們將把行y中的標籤移動兩行,以提前四分鐘進行預測。

sign = lambda x: (1, -1)[x < 0]def curve_shift(df, shift_by):
'''
This function will shift the binary labels in a dataframe.
The curve shift will be with respect to the 1s.
For example, if shift is -2, the following process
will happen: if row n is labeled as 1, then
- Make row (n+shift_by):(n+shift_by-1) = 1.
- Remove row n.
i.e. the labels will be shifted up to 2 rows up.

Inputs:
df A pandas dataframe with a binary labeled column.
This labeled column should be named as 'y'.
shift_by An integer denoting the number of rows to shift.

Output
df A dataframe with the binary labels shifted by shift.
'''vector = df['y'].copy()
for s in range(abs(shift_by)):
tmp = vector.shift(sign(shift_by))
tmp = tmp.fillna(0)
vector += tmp
labelcol = 'y'
# Add vector to the df
df.insert(loc=0, column=labelcol+'tmp', value=vector)
# Remove the rows with labelcol == 1.
df = df.drop(df[df[labelcol] == 1].index)
# Drop labelcol and rename the tmp col as labelcol
df = df.drop(labelcol, axis=1)
df = df.rename(columns={labelcol+'tmp': labelcol})
# Make the labelcol binary
df.loc[df[labelcol] > 0, labelcol] = 1return df


向上移動兩行


df = curve_shift(df, shift_by = -2)


從這裡開始不需要時間行了,將其移除。


df = df.drop(['time'], axis=1)


將數據分為訓練數據,有效數據和測試數據。

df_train, df_test = train_test_split(df, test_size=DATA_SPLIT_PCT, random_state=SEED)
df_train, df_valid = train_test_split(df_train, test_size=DATA_SPLIT_PCT, random_state=SEED)


把X和y分開

x_train = df_train.drop(['y'], axis=1)
y_train = df_train.y.valuesx_valid = df_valid.drop(['y'], axis=1)
y_valid = df_valid.y.valuesx_test = df_test.drop(['y'], axis=1)
y_test = df_test.y


數據縮放

scaler = MinMaxScaler().fit(x_train)
# scaler = StandardScaler().fit(x_train)
x_train_scaled = scaler.transform(x_train)
x_valid_scaled = scaler.transform(x_valid)
x_test_scaled = scaler.transform(x_test)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

MLP模型


自定義度量:FalsePositiveRate()


開發一個在下面所有模型中都要用到的FalsePositiveRate()度量。


class FalsePositiveRate(tf.keras.metrics.Metric):
def __init__(self, name='false_positive_rate', **kwargs):
super(FalsePositiveRate, self).__init__(name=name, **kwargs)
self.negatives = self.add_weight(name='negatives', initializer='zeros')
self.false_positives = self.add_weight(name='false_negatives', initializer='zeros')

def update_state(self, y_true, y_pred, sample_weight=None):
'''
Arguments:
y_true The actual y. Passed by default to Metric classes.
y_pred The predicted y. Passed by default to Metric classes.

'''
# Compute the number of negatives.
y_true = tf.cast(y_true, tf.bool)

negatives = tf.reduce_sum(tf.cast(tf.equal(y_true, False), self.dtype))

self.negatives.assign_add(negatives)

# Compute the number of false positives.
y_pred = tf.greater_equal(y_pred, 0.5) # Using default threshold of 0.5 to call a prediction as positive labeled.

false_positive_values = tf.logical_and(tf.equal(y_true, False), tf.equal(y_pred, True))
false_positive_values = tf.cast(false_positive_values, self.dtype)
if sample_weight is not None:
sample_weight = tf.cast(sample_weight, self.dtype)
sample_weight = tf.broadcast_weights(sample_weight, values)
values = tf.multiply(false_positive_values, sample_weight)

false_positives = tf.reduce_sum(false_positive_values)

self.false_positives.assign_add(false_positives)

def result(self):
return tf.divide(self.false_positives, self.negatives)


常規性能繪圖函數


def plot_loss(model_history):
train_loss=[value for key, value in model_history.items() if 'loss' in key.lower()][0]
valid_loss=[value for key, value in model_history.items() if 'loss' in key.lower()][1]fig, ax1 = plt.subplots()color = 'tab:blue'
ax1.set_xlabel('Epoch')
ax1.set_ylabel('Loss', color=color)
ax1.plot(train_loss, '--', color=color, label='Train Loss')
ax1.plot(valid_loss, color=color, label='Valid Loss')
ax1.tick_params(axis='y', labelcolor=color)
plt.legend(loc='upper left')
plt.title('Model Loss')plt.show()def plot_model_recall_fpr(model_history):
train_recall=[value for key, value in model_history.items() if 'recall' in key.lower()][0]
valid_recall=[value for key, value in model_history.items() if 'recall' in key.lower()][1]train_fpr=[value for key, value in model_history.items() if 'false_positive_rate' in key.lower()][0]
valid_fpr=[value for key, value in model_history.items() if 'false_positive_rate' in key.lower()][1]fig, ax1 = plt.subplots()color = 'tab:red'
ax1.set_xlabel('Epoch')
ax1.set_ylabel('Recall', color=color)
ax1.set_ylim([-0.05,1.05])
ax1.plot(train_recall, '--', color=color, label='Train Recall')
ax1.plot(valid_recall, color=color, label='Valid Recall')
ax1.tick_params(axis='y', labelcolor=color)
plt.legend(loc='upper left')
plt.title('Model Recall and FPR')ax2 = ax1.twinx() # instantiate a second axes that shares the same x-axiscolor = 'tab:blue'
ax2.set_ylabel('False Positive Rate', color=color) # we already handled the x-label with ax1
ax2.plot(train_fpr, '--', color=color, label='Train FPR')
ax2.plot(valid_fpr, color=color, label='Valid FPR')
ax2.tick_params(axis='y', labelcolor=color)
ax2.set_ylim([-0.05,1.05])fig.tight_layout() # otherwise the right y-label is slightly clipped
plt.legend(loc='upper right')
plt.show()


模型1.參照算法


n_features = x_train_scaled.shape[1]
mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dense(1, activation='sigmoid'))
mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid_scaled, y_valid),
verbose=0).history


觀察模型擬合損失和準確度(召回率和假陽率)變化


plot_loss(history)

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

plot_model_recall_fpr(history)

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

模型2.類權重


參照上文提到的經驗法則決定類權重。


class_weight = {0: sum(y_train == 1)/len(y_train), 1: sum(y_train == 0)/len(y_train)}


開始訓練模型。


n_features = x_train_scaled.shape[1]mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dense(1, activation='sigmoid'))mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid_scaled, y_valid),
class_weight=class_weight,
verbose=0).historyplot_loss(history)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


plot_model_recall_fpr(history)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

模型3. Dropout正則化


n_features = x_train_scaled.shape[1]mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dropout(0.5))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dropout(0.5))
mlp.add(Dense(1, activation='sigmoid'))mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid_scaled, y_valid),
class_weight=class_weight,
verbose=0).historyplot_loss(history)
代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

plot_model_recall_fpr(history)

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

模型4. 過採樣-欠採樣


使用SMOTE重採樣。


from imblearn.over_sampling import SMOTE
smote = SMOTE(random_state=212)
x_train_scaled_resampled, y_train_resampled = smote.fit_resample(x_train_scaled, y_train)
print('Resampled dataset shape %s' % Counter(y_train_resampled))


"
全文共5505字,預計學習時長11分鐘或更長
代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

圖片來源:Unsplash/Dewang Gupta

通過本文的學習, 我們可以瞭解如何著手構建初始神經網絡, 學習經驗法則,比如:隱藏層的數量、節點的數量、激活並觀察其在TensorFlow2中的應用。


深度學習提供了種類繁多的模型。有了它們,就可以建立非常精確的預測模型。然而,由於設置參數數量巨大且種類繁多,要找到出發點會有些困難。


本文將帶領大家找到構建神經網絡的出發點,具體來說是以構建多層感知器為例子。雖然使用了多層感知器為例,但大多數法則都是普遍適用於神經網絡構建的。


整體思路是通過經驗法則先建立第一個神經網絡模型。如果第一個模型能合理運行(達到最低可接受精確度),就對其進行調整與優化。否則,就最好去查看數據和問題所在,或採用其他方法。


本文將介紹:

· 建立神經網絡的經驗法則。

· TensorFlow2中二進制分類的實施代碼。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

神經網絡


神經網絡在卷積神經網絡(CNN)、遞歸神經網絡(RNN)等領域都取得了巨大進步。且隨著時間的推移,每個神經網絡的幾個亞型都得到了發展。正是這一個個的進步,成功地提高了模型的預測能力。


但與此同時,找到模型構建的出發點也變得更難了。


每個神經網絡模型都是不同的,不同的模型有不同的特點和功能,所以在這種情況下,選擇適用的模型變得像在林立的廣告牌中選擇合適的商品一樣困難。


接下來,我們將利用經驗法則構建第一個模型,以克服這些干擾。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

經驗法則


在形形色色的神經網絡中,多層感知器是通往深度學習的敲門磚。因此,當學習或構建一個深度學習領域的模型時,多層感知器就是很好的出發點。


以下是構建多層感知器的經驗法則,且大多數法則都適用於其他深度學習模型。


1. 層數:從兩個隱藏層開始(這其中不包含最後一層)。

2. 中間層的節點數量(大小):是2的倍數,如4,8,16,32……第一層的節點數應該是輸入數據特徵數量的一半左右。下一層的大小是上一層的一半。

3. 分類層最後一層的節點數量(大小):如果是二進制分類,則節點大小為一。對於多類分類器,節點大小等於類的數量。

4. 迴歸層最後一層的大小:如果是單響應,最後一層的大小為1。對於多響應迴歸,最後一層的大小等於響應的數量。

5. 激活中間層,使用Relu激活函數。

6. 激活最後一層:如果是二進制分類,使用sigmoid函數,多類分類器使用softmax函數,迴歸則使用linear函數。對於自動編碼器,如果輸入數據是連續的,使用linear函數進行激活。對於二進制或多級分類輸入,使用sigmoid或softmax函數。

7. Dropout層:除了輸入層以外,在其他每個層都加設Dropout(如果單獨定義輸入層)。將Dropout率設置為0.5。Dropout率大於0.5時結果會適得其反。因此如果覺得0.5會使太多的節點正則化,可以選擇增加層的大小,而不是將Dropout率設置在0.5以下。筆者不喜歡在輸入層設置任何Dropout。但如果認為有必要這樣做,請把Dropout率設置在0.2以下。

8. 數據預處理:假設預測器X是數字,且已經將所有分類列轉化成了獨熱編碼。那麼就可以在進行模型訓練前使用MinMaxScalar對數據進行大小預處理。如果MMS不奏效,就在相同的數據庫中使用StandardScalar對數據進行標準化處理。整個數據處理過程不對y進行操作。

9. 將數據分為訓練數據,有效數據與測試數據:

使用sklearn.model_selection的train_test_split語句。具體操作見下方示例。

10. 類權重:如果數據不平衡,可以在model.fit中設置類權重以平衡損失。對於二進制分類器,權重應為:{0:1的數量/數據大小,1:0的數量/數據大小}。對於極不平衡數據(罕見事件),類權重可能不起作用,請小心添加使用。

11. 優化器:使用adam優化器,應用其默認學習率。

12. 分類損失:對於二進制分類,使用binary_crossentropy.對於多類別分類,如果標籤是獨熱編碼而成的,使用categorical_crossentropy。當標籤都是整數時,使用sparse_categorical_crossentropy 。

13. 迴歸損失:使用均方誤差(mse)函數。

14. 分類指標:使用accuracy顯示正確分類的百分比。對不平衡數據,也要加上tf.keras.metrics.Recall() 和 tf.keras.metrics.FalsePositives().

15. 迴歸指標:使用tf.keras.metrics.RootMeanSquaredError()。

16. 訓練週期:先從20開始,看模型訓練是否顯示出損失的減少,或任何在精確度上的提高。如果20個週期還沒有一點成果就換個方法。如果得到了些許成果,就把訓練週期提升到100。

17. 批處理大小:將批處理大小選擇為2的倍數,對於不平衡數據,通常選用較大值,如128,否則一般都從16開始選用。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


給高級從業人員的一些額外經驗法則


1. 振盪損耗:如果在訓練中遇到振盪損耗,則是由趨同問題導致的。遇到這種問題時,可以嘗試減小學習率和/或更改批處理大小。

2. 過採樣和欠採樣:如果數據不平衡,使用imblearn.over_sampling中的SMOTE算法。

3. 曲線移動:如果需要進行位移預測,比如早期預測,可以使用曲線移動。下方展示了curve_shift的執行。

4. 自定義度量:假陽率是不平衡二進制分類中的一個重要度量。可以如下方給出的class FalsePositiveRate()的執行所示,構建假陽率度量和其他自定義度量。

5. Selu激活函數:在現今所有的激活函數中,selu激活函數被認為是最好的。我並不完全同意這一點,但如果想要使用selu激活函數,可以使用kernel_initializer=’lecun_normal’和 AlphaDropout.在AlphaDropout中使用0.1比率,AlphaDropout(0.1) 。執行實例在下方給出。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

TensorFlow 2中的多層感知器(MLP)實例


在這個執行中,可以看到上述經驗法則中所提到的內容的實際操作。


上述執行是在TensorFlow 2中完成的。強烈建議所有人都轉戰使用TensorFlow 2。它不僅擁有Keras所具有的簡易性,還顯著地提升了計算效率。


本文目的並不是嘗試找到最好的模型,而是學習神經網絡的實現。不會為了簡化過程而跳過任何步驟。相反,本文給出的步驟都很詳細,以幫助讀者的直接應用。



%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as snsimport pandas as pd
import numpy as np
from pylab import rcParamsfrom collections import Counterimport tensorflow as tffrom tensorflow.keras import optimizers
from tensorflow.keras.models import Model, load_model, Sequential
from tensorflow.keras.layers import Input, Dense, Dropout, AlphaDropout
from tensorflow.keras.callbacks import ModelCheckpoint, TensorBoardfrom sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, precision_recall_curve
from sklearn.metrics import recall_score, classification_report, auc, roc_curve
from sklearn.metrics import precision_recall_fscore_support, f1_scorefrom numpy.random import seed
seed(1)SEED = 123 #used to help randomly select the data points
DATA_SPLIT_PCT = 0.2rcParams['figure.figsize'] = 8, 6
LABELS = ["Normal","Break"]


測試是否使用了正確的TensorFlow版本,運行:tf.__version__

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

讀取與準備數據


數據下載傳送門:https://docs.google.com/forms/d/e/1FAIpQLSdyUk3lfDl7I5KYK_pw285LCApc-_RcoC0Tf9cnDnZ_TWzPAw/viewform?source=post_page---------------------------


df = pd.read_csv("data/processminer-rare-event-mts - data.csv") 
df.head(n=5) # visualize the data.


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


將分類列轉換為獨熱編碼

hotencoding1 = pd.get_dummies(df['x28']) # Grade&Bwt
hotencoding1 = hotencoding1.add_prefix('grade_')
hotencoding2 = pd.get_dummies(df['x61']) # EventPress
hotencoding2 = hotencoding2.add_prefix('eventpress_')df=df.drop(['x28', 'x61'], axis=1)df=pd.concat([df, hotencoding1, hotencoding2], axis=1)


曲線移動


以下是一個時間序列數據,要求必須提前預測時間(y=1)。在這個數據中,連續行之間間隔兩分鐘。我們將把行y中的標籤移動兩行,以提前四分鐘進行預測。

sign = lambda x: (1, -1)[x < 0]def curve_shift(df, shift_by):
'''
This function will shift the binary labels in a dataframe.
The curve shift will be with respect to the 1s.
For example, if shift is -2, the following process
will happen: if row n is labeled as 1, then
- Make row (n+shift_by):(n+shift_by-1) = 1.
- Remove row n.
i.e. the labels will be shifted up to 2 rows up.

Inputs:
df A pandas dataframe with a binary labeled column.
This labeled column should be named as 'y'.
shift_by An integer denoting the number of rows to shift.

Output
df A dataframe with the binary labels shifted by shift.
'''vector = df['y'].copy()
for s in range(abs(shift_by)):
tmp = vector.shift(sign(shift_by))
tmp = tmp.fillna(0)
vector += tmp
labelcol = 'y'
# Add vector to the df
df.insert(loc=0, column=labelcol+'tmp', value=vector)
# Remove the rows with labelcol == 1.
df = df.drop(df[df[labelcol] == 1].index)
# Drop labelcol and rename the tmp col as labelcol
df = df.drop(labelcol, axis=1)
df = df.rename(columns={labelcol+'tmp': labelcol})
# Make the labelcol binary
df.loc[df[labelcol] > 0, labelcol] = 1return df


向上移動兩行


df = curve_shift(df, shift_by = -2)


從這裡開始不需要時間行了,將其移除。


df = df.drop(['time'], axis=1)


將數據分為訓練數據,有效數據和測試數據。

df_train, df_test = train_test_split(df, test_size=DATA_SPLIT_PCT, random_state=SEED)
df_train, df_valid = train_test_split(df_train, test_size=DATA_SPLIT_PCT, random_state=SEED)


把X和y分開

x_train = df_train.drop(['y'], axis=1)
y_train = df_train.y.valuesx_valid = df_valid.drop(['y'], axis=1)
y_valid = df_valid.y.valuesx_test = df_test.drop(['y'], axis=1)
y_test = df_test.y


數據縮放

scaler = MinMaxScaler().fit(x_train)
# scaler = StandardScaler().fit(x_train)
x_train_scaled = scaler.transform(x_train)
x_valid_scaled = scaler.transform(x_valid)
x_test_scaled = scaler.transform(x_test)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

MLP模型


自定義度量:FalsePositiveRate()


開發一個在下面所有模型中都要用到的FalsePositiveRate()度量。


class FalsePositiveRate(tf.keras.metrics.Metric):
def __init__(self, name='false_positive_rate', **kwargs):
super(FalsePositiveRate, self).__init__(name=name, **kwargs)
self.negatives = self.add_weight(name='negatives', initializer='zeros')
self.false_positives = self.add_weight(name='false_negatives', initializer='zeros')

def update_state(self, y_true, y_pred, sample_weight=None):
'''
Arguments:
y_true The actual y. Passed by default to Metric classes.
y_pred The predicted y. Passed by default to Metric classes.

'''
# Compute the number of negatives.
y_true = tf.cast(y_true, tf.bool)

negatives = tf.reduce_sum(tf.cast(tf.equal(y_true, False), self.dtype))

self.negatives.assign_add(negatives)

# Compute the number of false positives.
y_pred = tf.greater_equal(y_pred, 0.5) # Using default threshold of 0.5 to call a prediction as positive labeled.

false_positive_values = tf.logical_and(tf.equal(y_true, False), tf.equal(y_pred, True))
false_positive_values = tf.cast(false_positive_values, self.dtype)
if sample_weight is not None:
sample_weight = tf.cast(sample_weight, self.dtype)
sample_weight = tf.broadcast_weights(sample_weight, values)
values = tf.multiply(false_positive_values, sample_weight)

false_positives = tf.reduce_sum(false_positive_values)

self.false_positives.assign_add(false_positives)

def result(self):
return tf.divide(self.false_positives, self.negatives)


常規性能繪圖函數


def plot_loss(model_history):
train_loss=[value for key, value in model_history.items() if 'loss' in key.lower()][0]
valid_loss=[value for key, value in model_history.items() if 'loss' in key.lower()][1]fig, ax1 = plt.subplots()color = 'tab:blue'
ax1.set_xlabel('Epoch')
ax1.set_ylabel('Loss', color=color)
ax1.plot(train_loss, '--', color=color, label='Train Loss')
ax1.plot(valid_loss, color=color, label='Valid Loss')
ax1.tick_params(axis='y', labelcolor=color)
plt.legend(loc='upper left')
plt.title('Model Loss')plt.show()def plot_model_recall_fpr(model_history):
train_recall=[value for key, value in model_history.items() if 'recall' in key.lower()][0]
valid_recall=[value for key, value in model_history.items() if 'recall' in key.lower()][1]train_fpr=[value for key, value in model_history.items() if 'false_positive_rate' in key.lower()][0]
valid_fpr=[value for key, value in model_history.items() if 'false_positive_rate' in key.lower()][1]fig, ax1 = plt.subplots()color = 'tab:red'
ax1.set_xlabel('Epoch')
ax1.set_ylabel('Recall', color=color)
ax1.set_ylim([-0.05,1.05])
ax1.plot(train_recall, '--', color=color, label='Train Recall')
ax1.plot(valid_recall, color=color, label='Valid Recall')
ax1.tick_params(axis='y', labelcolor=color)
plt.legend(loc='upper left')
plt.title('Model Recall and FPR')ax2 = ax1.twinx() # instantiate a second axes that shares the same x-axiscolor = 'tab:blue'
ax2.set_ylabel('False Positive Rate', color=color) # we already handled the x-label with ax1
ax2.plot(train_fpr, '--', color=color, label='Train FPR')
ax2.plot(valid_fpr, color=color, label='Valid FPR')
ax2.tick_params(axis='y', labelcolor=color)
ax2.set_ylim([-0.05,1.05])fig.tight_layout() # otherwise the right y-label is slightly clipped
plt.legend(loc='upper right')
plt.show()


模型1.參照算法


n_features = x_train_scaled.shape[1]
mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dense(1, activation='sigmoid'))
mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid_scaled, y_valid),
verbose=0).history


觀察模型擬合損失和準確度(召回率和假陽率)變化


plot_loss(history)

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

plot_model_recall_fpr(history)

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

模型2.類權重


參照上文提到的經驗法則決定類權重。


class_weight = {0: sum(y_train == 1)/len(y_train), 1: sum(y_train == 0)/len(y_train)}


開始訓練模型。


n_features = x_train_scaled.shape[1]mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dense(1, activation='sigmoid'))mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid_scaled, y_valid),
class_weight=class_weight,
verbose=0).historyplot_loss(history)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


plot_model_recall_fpr(history)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

模型3. Dropout正則化


n_features = x_train_scaled.shape[1]mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dropout(0.5))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dropout(0.5))
mlp.add(Dense(1, activation='sigmoid'))mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid_scaled, y_valid),
class_weight=class_weight,
verbose=0).historyplot_loss(history)
代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

plot_model_recall_fpr(history)

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

模型4. 過採樣-欠採樣


使用SMOTE重採樣。


from imblearn.over_sampling import SMOTE
smote = SMOTE(random_state=212)
x_train_scaled_resampled, y_train_resampled = smote.fit_resample(x_train_scaled, y_train)
print('Resampled dataset shape %s' % Counter(y_train_resampled))


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

n_features = x_train_scaled.shape[1]mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dropout(0.5))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dropout(0.5))
mlp.add(Dense(1, activation='sigmoid'))mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled_resampled,
y=y_train_resampled,
batch_size=128,
epochs=100,
validation_data=(x_valid, y_valid),
class_weight=class_weight,
verbose=0).historyplot_loss(history)


"
全文共5505字,預計學習時長11分鐘或更長
代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

圖片來源:Unsplash/Dewang Gupta

通過本文的學習, 我們可以瞭解如何著手構建初始神經網絡, 學習經驗法則,比如:隱藏層的數量、節點的數量、激活並觀察其在TensorFlow2中的應用。


深度學習提供了種類繁多的模型。有了它們,就可以建立非常精確的預測模型。然而,由於設置參數數量巨大且種類繁多,要找到出發點會有些困難。


本文將帶領大家找到構建神經網絡的出發點,具體來說是以構建多層感知器為例子。雖然使用了多層感知器為例,但大多數法則都是普遍適用於神經網絡構建的。


整體思路是通過經驗法則先建立第一個神經網絡模型。如果第一個模型能合理運行(達到最低可接受精確度),就對其進行調整與優化。否則,就最好去查看數據和問題所在,或採用其他方法。


本文將介紹:

· 建立神經網絡的經驗法則。

· TensorFlow2中二進制分類的實施代碼。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

神經網絡


神經網絡在卷積神經網絡(CNN)、遞歸神經網絡(RNN)等領域都取得了巨大進步。且隨著時間的推移,每個神經網絡的幾個亞型都得到了發展。正是這一個個的進步,成功地提高了模型的預測能力。


但與此同時,找到模型構建的出發點也變得更難了。


每個神經網絡模型都是不同的,不同的模型有不同的特點和功能,所以在這種情況下,選擇適用的模型變得像在林立的廣告牌中選擇合適的商品一樣困難。


接下來,我們將利用經驗法則構建第一個模型,以克服這些干擾。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

經驗法則


在形形色色的神經網絡中,多層感知器是通往深度學習的敲門磚。因此,當學習或構建一個深度學習領域的模型時,多層感知器就是很好的出發點。


以下是構建多層感知器的經驗法則,且大多數法則都適用於其他深度學習模型。


1. 層數:從兩個隱藏層開始(這其中不包含最後一層)。

2. 中間層的節點數量(大小):是2的倍數,如4,8,16,32……第一層的節點數應該是輸入數據特徵數量的一半左右。下一層的大小是上一層的一半。

3. 分類層最後一層的節點數量(大小):如果是二進制分類,則節點大小為一。對於多類分類器,節點大小等於類的數量。

4. 迴歸層最後一層的大小:如果是單響應,最後一層的大小為1。對於多響應迴歸,最後一層的大小等於響應的數量。

5. 激活中間層,使用Relu激活函數。

6. 激活最後一層:如果是二進制分類,使用sigmoid函數,多類分類器使用softmax函數,迴歸則使用linear函數。對於自動編碼器,如果輸入數據是連續的,使用linear函數進行激活。對於二進制或多級分類輸入,使用sigmoid或softmax函數。

7. Dropout層:除了輸入層以外,在其他每個層都加設Dropout(如果單獨定義輸入層)。將Dropout率設置為0.5。Dropout率大於0.5時結果會適得其反。因此如果覺得0.5會使太多的節點正則化,可以選擇增加層的大小,而不是將Dropout率設置在0.5以下。筆者不喜歡在輸入層設置任何Dropout。但如果認為有必要這樣做,請把Dropout率設置在0.2以下。

8. 數據預處理:假設預測器X是數字,且已經將所有分類列轉化成了獨熱編碼。那麼就可以在進行模型訓練前使用MinMaxScalar對數據進行大小預處理。如果MMS不奏效,就在相同的數據庫中使用StandardScalar對數據進行標準化處理。整個數據處理過程不對y進行操作。

9. 將數據分為訓練數據,有效數據與測試數據:

使用sklearn.model_selection的train_test_split語句。具體操作見下方示例。

10. 類權重:如果數據不平衡,可以在model.fit中設置類權重以平衡損失。對於二進制分類器,權重應為:{0:1的數量/數據大小,1:0的數量/數據大小}。對於極不平衡數據(罕見事件),類權重可能不起作用,請小心添加使用。

11. 優化器:使用adam優化器,應用其默認學習率。

12. 分類損失:對於二進制分類,使用binary_crossentropy.對於多類別分類,如果標籤是獨熱編碼而成的,使用categorical_crossentropy。當標籤都是整數時,使用sparse_categorical_crossentropy 。

13. 迴歸損失:使用均方誤差(mse)函數。

14. 分類指標:使用accuracy顯示正確分類的百分比。對不平衡數據,也要加上tf.keras.metrics.Recall() 和 tf.keras.metrics.FalsePositives().

15. 迴歸指標:使用tf.keras.metrics.RootMeanSquaredError()。

16. 訓練週期:先從20開始,看模型訓練是否顯示出損失的減少,或任何在精確度上的提高。如果20個週期還沒有一點成果就換個方法。如果得到了些許成果,就把訓練週期提升到100。

17. 批處理大小:將批處理大小選擇為2的倍數,對於不平衡數據,通常選用較大值,如128,否則一般都從16開始選用。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


給高級從業人員的一些額外經驗法則


1. 振盪損耗:如果在訓練中遇到振盪損耗,則是由趨同問題導致的。遇到這種問題時,可以嘗試減小學習率和/或更改批處理大小。

2. 過採樣和欠採樣:如果數據不平衡,使用imblearn.over_sampling中的SMOTE算法。

3. 曲線移動:如果需要進行位移預測,比如早期預測,可以使用曲線移動。下方展示了curve_shift的執行。

4. 自定義度量:假陽率是不平衡二進制分類中的一個重要度量。可以如下方給出的class FalsePositiveRate()的執行所示,構建假陽率度量和其他自定義度量。

5. Selu激活函數:在現今所有的激活函數中,selu激活函數被認為是最好的。我並不完全同意這一點,但如果想要使用selu激活函數,可以使用kernel_initializer=’lecun_normal’和 AlphaDropout.在AlphaDropout中使用0.1比率,AlphaDropout(0.1) 。執行實例在下方給出。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

TensorFlow 2中的多層感知器(MLP)實例


在這個執行中,可以看到上述經驗法則中所提到的內容的實際操作。


上述執行是在TensorFlow 2中完成的。強烈建議所有人都轉戰使用TensorFlow 2。它不僅擁有Keras所具有的簡易性,還顯著地提升了計算效率。


本文目的並不是嘗試找到最好的模型,而是學習神經網絡的實現。不會為了簡化過程而跳過任何步驟。相反,本文給出的步驟都很詳細,以幫助讀者的直接應用。



%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as snsimport pandas as pd
import numpy as np
from pylab import rcParamsfrom collections import Counterimport tensorflow as tffrom tensorflow.keras import optimizers
from tensorflow.keras.models import Model, load_model, Sequential
from tensorflow.keras.layers import Input, Dense, Dropout, AlphaDropout
from tensorflow.keras.callbacks import ModelCheckpoint, TensorBoardfrom sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, precision_recall_curve
from sklearn.metrics import recall_score, classification_report, auc, roc_curve
from sklearn.metrics import precision_recall_fscore_support, f1_scorefrom numpy.random import seed
seed(1)SEED = 123 #used to help randomly select the data points
DATA_SPLIT_PCT = 0.2rcParams['figure.figsize'] = 8, 6
LABELS = ["Normal","Break"]


測試是否使用了正確的TensorFlow版本,運行:tf.__version__

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

讀取與準備數據


數據下載傳送門:https://docs.google.com/forms/d/e/1FAIpQLSdyUk3lfDl7I5KYK_pw285LCApc-_RcoC0Tf9cnDnZ_TWzPAw/viewform?source=post_page---------------------------


df = pd.read_csv("data/processminer-rare-event-mts - data.csv") 
df.head(n=5) # visualize the data.


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


將分類列轉換為獨熱編碼

hotencoding1 = pd.get_dummies(df['x28']) # Grade&Bwt
hotencoding1 = hotencoding1.add_prefix('grade_')
hotencoding2 = pd.get_dummies(df['x61']) # EventPress
hotencoding2 = hotencoding2.add_prefix('eventpress_')df=df.drop(['x28', 'x61'], axis=1)df=pd.concat([df, hotencoding1, hotencoding2], axis=1)


曲線移動


以下是一個時間序列數據,要求必須提前預測時間(y=1)。在這個數據中,連續行之間間隔兩分鐘。我們將把行y中的標籤移動兩行,以提前四分鐘進行預測。

sign = lambda x: (1, -1)[x < 0]def curve_shift(df, shift_by):
'''
This function will shift the binary labels in a dataframe.
The curve shift will be with respect to the 1s.
For example, if shift is -2, the following process
will happen: if row n is labeled as 1, then
- Make row (n+shift_by):(n+shift_by-1) = 1.
- Remove row n.
i.e. the labels will be shifted up to 2 rows up.

Inputs:
df A pandas dataframe with a binary labeled column.
This labeled column should be named as 'y'.
shift_by An integer denoting the number of rows to shift.

Output
df A dataframe with the binary labels shifted by shift.
'''vector = df['y'].copy()
for s in range(abs(shift_by)):
tmp = vector.shift(sign(shift_by))
tmp = tmp.fillna(0)
vector += tmp
labelcol = 'y'
# Add vector to the df
df.insert(loc=0, column=labelcol+'tmp', value=vector)
# Remove the rows with labelcol == 1.
df = df.drop(df[df[labelcol] == 1].index)
# Drop labelcol and rename the tmp col as labelcol
df = df.drop(labelcol, axis=1)
df = df.rename(columns={labelcol+'tmp': labelcol})
# Make the labelcol binary
df.loc[df[labelcol] > 0, labelcol] = 1return df


向上移動兩行


df = curve_shift(df, shift_by = -2)


從這裡開始不需要時間行了,將其移除。


df = df.drop(['time'], axis=1)


將數據分為訓練數據,有效數據和測試數據。

df_train, df_test = train_test_split(df, test_size=DATA_SPLIT_PCT, random_state=SEED)
df_train, df_valid = train_test_split(df_train, test_size=DATA_SPLIT_PCT, random_state=SEED)


把X和y分開

x_train = df_train.drop(['y'], axis=1)
y_train = df_train.y.valuesx_valid = df_valid.drop(['y'], axis=1)
y_valid = df_valid.y.valuesx_test = df_test.drop(['y'], axis=1)
y_test = df_test.y


數據縮放

scaler = MinMaxScaler().fit(x_train)
# scaler = StandardScaler().fit(x_train)
x_train_scaled = scaler.transform(x_train)
x_valid_scaled = scaler.transform(x_valid)
x_test_scaled = scaler.transform(x_test)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

MLP模型


自定義度量:FalsePositiveRate()


開發一個在下面所有模型中都要用到的FalsePositiveRate()度量。


class FalsePositiveRate(tf.keras.metrics.Metric):
def __init__(self, name='false_positive_rate', **kwargs):
super(FalsePositiveRate, self).__init__(name=name, **kwargs)
self.negatives = self.add_weight(name='negatives', initializer='zeros')
self.false_positives = self.add_weight(name='false_negatives', initializer='zeros')

def update_state(self, y_true, y_pred, sample_weight=None):
'''
Arguments:
y_true The actual y. Passed by default to Metric classes.
y_pred The predicted y. Passed by default to Metric classes.

'''
# Compute the number of negatives.
y_true = tf.cast(y_true, tf.bool)

negatives = tf.reduce_sum(tf.cast(tf.equal(y_true, False), self.dtype))

self.negatives.assign_add(negatives)

# Compute the number of false positives.
y_pred = tf.greater_equal(y_pred, 0.5) # Using default threshold of 0.5 to call a prediction as positive labeled.

false_positive_values = tf.logical_and(tf.equal(y_true, False), tf.equal(y_pred, True))
false_positive_values = tf.cast(false_positive_values, self.dtype)
if sample_weight is not None:
sample_weight = tf.cast(sample_weight, self.dtype)
sample_weight = tf.broadcast_weights(sample_weight, values)
values = tf.multiply(false_positive_values, sample_weight)

false_positives = tf.reduce_sum(false_positive_values)

self.false_positives.assign_add(false_positives)

def result(self):
return tf.divide(self.false_positives, self.negatives)


常規性能繪圖函數


def plot_loss(model_history):
train_loss=[value for key, value in model_history.items() if 'loss' in key.lower()][0]
valid_loss=[value for key, value in model_history.items() if 'loss' in key.lower()][1]fig, ax1 = plt.subplots()color = 'tab:blue'
ax1.set_xlabel('Epoch')
ax1.set_ylabel('Loss', color=color)
ax1.plot(train_loss, '--', color=color, label='Train Loss')
ax1.plot(valid_loss, color=color, label='Valid Loss')
ax1.tick_params(axis='y', labelcolor=color)
plt.legend(loc='upper left')
plt.title('Model Loss')plt.show()def plot_model_recall_fpr(model_history):
train_recall=[value for key, value in model_history.items() if 'recall' in key.lower()][0]
valid_recall=[value for key, value in model_history.items() if 'recall' in key.lower()][1]train_fpr=[value for key, value in model_history.items() if 'false_positive_rate' in key.lower()][0]
valid_fpr=[value for key, value in model_history.items() if 'false_positive_rate' in key.lower()][1]fig, ax1 = plt.subplots()color = 'tab:red'
ax1.set_xlabel('Epoch')
ax1.set_ylabel('Recall', color=color)
ax1.set_ylim([-0.05,1.05])
ax1.plot(train_recall, '--', color=color, label='Train Recall')
ax1.plot(valid_recall, color=color, label='Valid Recall')
ax1.tick_params(axis='y', labelcolor=color)
plt.legend(loc='upper left')
plt.title('Model Recall and FPR')ax2 = ax1.twinx() # instantiate a second axes that shares the same x-axiscolor = 'tab:blue'
ax2.set_ylabel('False Positive Rate', color=color) # we already handled the x-label with ax1
ax2.plot(train_fpr, '--', color=color, label='Train FPR')
ax2.plot(valid_fpr, color=color, label='Valid FPR')
ax2.tick_params(axis='y', labelcolor=color)
ax2.set_ylim([-0.05,1.05])fig.tight_layout() # otherwise the right y-label is slightly clipped
plt.legend(loc='upper right')
plt.show()


模型1.參照算法


n_features = x_train_scaled.shape[1]
mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dense(1, activation='sigmoid'))
mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid_scaled, y_valid),
verbose=0).history


觀察模型擬合損失和準確度(召回率和假陽率)變化


plot_loss(history)

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

plot_model_recall_fpr(history)

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

模型2.類權重


參照上文提到的經驗法則決定類權重。


class_weight = {0: sum(y_train == 1)/len(y_train), 1: sum(y_train == 0)/len(y_train)}


開始訓練模型。


n_features = x_train_scaled.shape[1]mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dense(1, activation='sigmoid'))mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid_scaled, y_valid),
class_weight=class_weight,
verbose=0).historyplot_loss(history)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


plot_model_recall_fpr(history)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

模型3. Dropout正則化


n_features = x_train_scaled.shape[1]mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dropout(0.5))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dropout(0.5))
mlp.add(Dense(1, activation='sigmoid'))mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid_scaled, y_valid),
class_weight=class_weight,
verbose=0).historyplot_loss(history)
代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

plot_model_recall_fpr(history)

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

模型4. 過採樣-欠採樣


使用SMOTE重採樣。


from imblearn.over_sampling import SMOTE
smote = SMOTE(random_state=212)
x_train_scaled_resampled, y_train_resampled = smote.fit_resample(x_train_scaled, y_train)
print('Resampled dataset shape %s' % Counter(y_train_resampled))


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

n_features = x_train_scaled.shape[1]mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dropout(0.5))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dropout(0.5))
mlp.add(Dense(1, activation='sigmoid'))mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled_resampled,
y=y_train_resampled,
batch_size=128,
epochs=100,
validation_data=(x_valid, y_valid),
class_weight=class_weight,
verbose=0).historyplot_loss(history)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

plot_model_recall_fpr(history)

"
全文共5505字,預計學習時長11分鐘或更長
代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

圖片來源:Unsplash/Dewang Gupta

通過本文的學習, 我們可以瞭解如何著手構建初始神經網絡, 學習經驗法則,比如:隱藏層的數量、節點的數量、激活並觀察其在TensorFlow2中的應用。


深度學習提供了種類繁多的模型。有了它們,就可以建立非常精確的預測模型。然而,由於設置參數數量巨大且種類繁多,要找到出發點會有些困難。


本文將帶領大家找到構建神經網絡的出發點,具體來說是以構建多層感知器為例子。雖然使用了多層感知器為例,但大多數法則都是普遍適用於神經網絡構建的。


整體思路是通過經驗法則先建立第一個神經網絡模型。如果第一個模型能合理運行(達到最低可接受精確度),就對其進行調整與優化。否則,就最好去查看數據和問題所在,或採用其他方法。


本文將介紹:

· 建立神經網絡的經驗法則。

· TensorFlow2中二進制分類的實施代碼。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

神經網絡


神經網絡在卷積神經網絡(CNN)、遞歸神經網絡(RNN)等領域都取得了巨大進步。且隨著時間的推移,每個神經網絡的幾個亞型都得到了發展。正是這一個個的進步,成功地提高了模型的預測能力。


但與此同時,找到模型構建的出發點也變得更難了。


每個神經網絡模型都是不同的,不同的模型有不同的特點和功能,所以在這種情況下,選擇適用的模型變得像在林立的廣告牌中選擇合適的商品一樣困難。


接下來,我們將利用經驗法則構建第一個模型,以克服這些干擾。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

經驗法則


在形形色色的神經網絡中,多層感知器是通往深度學習的敲門磚。因此,當學習或構建一個深度學習領域的模型時,多層感知器就是很好的出發點。


以下是構建多層感知器的經驗法則,且大多數法則都適用於其他深度學習模型。


1. 層數:從兩個隱藏層開始(這其中不包含最後一層)。

2. 中間層的節點數量(大小):是2的倍數,如4,8,16,32……第一層的節點數應該是輸入數據特徵數量的一半左右。下一層的大小是上一層的一半。

3. 分類層最後一層的節點數量(大小):如果是二進制分類,則節點大小為一。對於多類分類器,節點大小等於類的數量。

4. 迴歸層最後一層的大小:如果是單響應,最後一層的大小為1。對於多響應迴歸,最後一層的大小等於響應的數量。

5. 激活中間層,使用Relu激活函數。

6. 激活最後一層:如果是二進制分類,使用sigmoid函數,多類分類器使用softmax函數,迴歸則使用linear函數。對於自動編碼器,如果輸入數據是連續的,使用linear函數進行激活。對於二進制或多級分類輸入,使用sigmoid或softmax函數。

7. Dropout層:除了輸入層以外,在其他每個層都加設Dropout(如果單獨定義輸入層)。將Dropout率設置為0.5。Dropout率大於0.5時結果會適得其反。因此如果覺得0.5會使太多的節點正則化,可以選擇增加層的大小,而不是將Dropout率設置在0.5以下。筆者不喜歡在輸入層設置任何Dropout。但如果認為有必要這樣做,請把Dropout率設置在0.2以下。

8. 數據預處理:假設預測器X是數字,且已經將所有分類列轉化成了獨熱編碼。那麼就可以在進行模型訓練前使用MinMaxScalar對數據進行大小預處理。如果MMS不奏效,就在相同的數據庫中使用StandardScalar對數據進行標準化處理。整個數據處理過程不對y進行操作。

9. 將數據分為訓練數據,有效數據與測試數據:

使用sklearn.model_selection的train_test_split語句。具體操作見下方示例。

10. 類權重:如果數據不平衡,可以在model.fit中設置類權重以平衡損失。對於二進制分類器,權重應為:{0:1的數量/數據大小,1:0的數量/數據大小}。對於極不平衡數據(罕見事件),類權重可能不起作用,請小心添加使用。

11. 優化器:使用adam優化器,應用其默認學習率。

12. 分類損失:對於二進制分類,使用binary_crossentropy.對於多類別分類,如果標籤是獨熱編碼而成的,使用categorical_crossentropy。當標籤都是整數時,使用sparse_categorical_crossentropy 。

13. 迴歸損失:使用均方誤差(mse)函數。

14. 分類指標:使用accuracy顯示正確分類的百分比。對不平衡數據,也要加上tf.keras.metrics.Recall() 和 tf.keras.metrics.FalsePositives().

15. 迴歸指標:使用tf.keras.metrics.RootMeanSquaredError()。

16. 訓練週期:先從20開始,看模型訓練是否顯示出損失的減少,或任何在精確度上的提高。如果20個週期還沒有一點成果就換個方法。如果得到了些許成果,就把訓練週期提升到100。

17. 批處理大小:將批處理大小選擇為2的倍數,對於不平衡數據,通常選用較大值,如128,否則一般都從16開始選用。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


給高級從業人員的一些額外經驗法則


1. 振盪損耗:如果在訓練中遇到振盪損耗,則是由趨同問題導致的。遇到這種問題時,可以嘗試減小學習率和/或更改批處理大小。

2. 過採樣和欠採樣:如果數據不平衡,使用imblearn.over_sampling中的SMOTE算法。

3. 曲線移動:如果需要進行位移預測,比如早期預測,可以使用曲線移動。下方展示了curve_shift的執行。

4. 自定義度量:假陽率是不平衡二進制分類中的一個重要度量。可以如下方給出的class FalsePositiveRate()的執行所示,構建假陽率度量和其他自定義度量。

5. Selu激活函數:在現今所有的激活函數中,selu激活函數被認為是最好的。我並不完全同意這一點,但如果想要使用selu激活函數,可以使用kernel_initializer=’lecun_normal’和 AlphaDropout.在AlphaDropout中使用0.1比率,AlphaDropout(0.1) 。執行實例在下方給出。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

TensorFlow 2中的多層感知器(MLP)實例


在這個執行中,可以看到上述經驗法則中所提到的內容的實際操作。


上述執行是在TensorFlow 2中完成的。強烈建議所有人都轉戰使用TensorFlow 2。它不僅擁有Keras所具有的簡易性,還顯著地提升了計算效率。


本文目的並不是嘗試找到最好的模型,而是學習神經網絡的實現。不會為了簡化過程而跳過任何步驟。相反,本文給出的步驟都很詳細,以幫助讀者的直接應用。



%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as snsimport pandas as pd
import numpy as np
from pylab import rcParamsfrom collections import Counterimport tensorflow as tffrom tensorflow.keras import optimizers
from tensorflow.keras.models import Model, load_model, Sequential
from tensorflow.keras.layers import Input, Dense, Dropout, AlphaDropout
from tensorflow.keras.callbacks import ModelCheckpoint, TensorBoardfrom sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, precision_recall_curve
from sklearn.metrics import recall_score, classification_report, auc, roc_curve
from sklearn.metrics import precision_recall_fscore_support, f1_scorefrom numpy.random import seed
seed(1)SEED = 123 #used to help randomly select the data points
DATA_SPLIT_PCT = 0.2rcParams['figure.figsize'] = 8, 6
LABELS = ["Normal","Break"]


測試是否使用了正確的TensorFlow版本,運行:tf.__version__

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

讀取與準備數據


數據下載傳送門:https://docs.google.com/forms/d/e/1FAIpQLSdyUk3lfDl7I5KYK_pw285LCApc-_RcoC0Tf9cnDnZ_TWzPAw/viewform?source=post_page---------------------------


df = pd.read_csv("data/processminer-rare-event-mts - data.csv") 
df.head(n=5) # visualize the data.


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


將分類列轉換為獨熱編碼

hotencoding1 = pd.get_dummies(df['x28']) # Grade&Bwt
hotencoding1 = hotencoding1.add_prefix('grade_')
hotencoding2 = pd.get_dummies(df['x61']) # EventPress
hotencoding2 = hotencoding2.add_prefix('eventpress_')df=df.drop(['x28', 'x61'], axis=1)df=pd.concat([df, hotencoding1, hotencoding2], axis=1)


曲線移動


以下是一個時間序列數據,要求必須提前預測時間(y=1)。在這個數據中,連續行之間間隔兩分鐘。我們將把行y中的標籤移動兩行,以提前四分鐘進行預測。

sign = lambda x: (1, -1)[x < 0]def curve_shift(df, shift_by):
'''
This function will shift the binary labels in a dataframe.
The curve shift will be with respect to the 1s.
For example, if shift is -2, the following process
will happen: if row n is labeled as 1, then
- Make row (n+shift_by):(n+shift_by-1) = 1.
- Remove row n.
i.e. the labels will be shifted up to 2 rows up.

Inputs:
df A pandas dataframe with a binary labeled column.
This labeled column should be named as 'y'.
shift_by An integer denoting the number of rows to shift.

Output
df A dataframe with the binary labels shifted by shift.
'''vector = df['y'].copy()
for s in range(abs(shift_by)):
tmp = vector.shift(sign(shift_by))
tmp = tmp.fillna(0)
vector += tmp
labelcol = 'y'
# Add vector to the df
df.insert(loc=0, column=labelcol+'tmp', value=vector)
# Remove the rows with labelcol == 1.
df = df.drop(df[df[labelcol] == 1].index)
# Drop labelcol and rename the tmp col as labelcol
df = df.drop(labelcol, axis=1)
df = df.rename(columns={labelcol+'tmp': labelcol})
# Make the labelcol binary
df.loc[df[labelcol] > 0, labelcol] = 1return df


向上移動兩行


df = curve_shift(df, shift_by = -2)


從這裡開始不需要時間行了,將其移除。


df = df.drop(['time'], axis=1)


將數據分為訓練數據,有效數據和測試數據。

df_train, df_test = train_test_split(df, test_size=DATA_SPLIT_PCT, random_state=SEED)
df_train, df_valid = train_test_split(df_train, test_size=DATA_SPLIT_PCT, random_state=SEED)


把X和y分開

x_train = df_train.drop(['y'], axis=1)
y_train = df_train.y.valuesx_valid = df_valid.drop(['y'], axis=1)
y_valid = df_valid.y.valuesx_test = df_test.drop(['y'], axis=1)
y_test = df_test.y


數據縮放

scaler = MinMaxScaler().fit(x_train)
# scaler = StandardScaler().fit(x_train)
x_train_scaled = scaler.transform(x_train)
x_valid_scaled = scaler.transform(x_valid)
x_test_scaled = scaler.transform(x_test)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

MLP模型


自定義度量:FalsePositiveRate()


開發一個在下面所有模型中都要用到的FalsePositiveRate()度量。


class FalsePositiveRate(tf.keras.metrics.Metric):
def __init__(self, name='false_positive_rate', **kwargs):
super(FalsePositiveRate, self).__init__(name=name, **kwargs)
self.negatives = self.add_weight(name='negatives', initializer='zeros')
self.false_positives = self.add_weight(name='false_negatives', initializer='zeros')

def update_state(self, y_true, y_pred, sample_weight=None):
'''
Arguments:
y_true The actual y. Passed by default to Metric classes.
y_pred The predicted y. Passed by default to Metric classes.

'''
# Compute the number of negatives.
y_true = tf.cast(y_true, tf.bool)

negatives = tf.reduce_sum(tf.cast(tf.equal(y_true, False), self.dtype))

self.negatives.assign_add(negatives)

# Compute the number of false positives.
y_pred = tf.greater_equal(y_pred, 0.5) # Using default threshold of 0.5 to call a prediction as positive labeled.

false_positive_values = tf.logical_and(tf.equal(y_true, False), tf.equal(y_pred, True))
false_positive_values = tf.cast(false_positive_values, self.dtype)
if sample_weight is not None:
sample_weight = tf.cast(sample_weight, self.dtype)
sample_weight = tf.broadcast_weights(sample_weight, values)
values = tf.multiply(false_positive_values, sample_weight)

false_positives = tf.reduce_sum(false_positive_values)

self.false_positives.assign_add(false_positives)

def result(self):
return tf.divide(self.false_positives, self.negatives)


常規性能繪圖函數


def plot_loss(model_history):
train_loss=[value for key, value in model_history.items() if 'loss' in key.lower()][0]
valid_loss=[value for key, value in model_history.items() if 'loss' in key.lower()][1]fig, ax1 = plt.subplots()color = 'tab:blue'
ax1.set_xlabel('Epoch')
ax1.set_ylabel('Loss', color=color)
ax1.plot(train_loss, '--', color=color, label='Train Loss')
ax1.plot(valid_loss, color=color, label='Valid Loss')
ax1.tick_params(axis='y', labelcolor=color)
plt.legend(loc='upper left')
plt.title('Model Loss')plt.show()def plot_model_recall_fpr(model_history):
train_recall=[value for key, value in model_history.items() if 'recall' in key.lower()][0]
valid_recall=[value for key, value in model_history.items() if 'recall' in key.lower()][1]train_fpr=[value for key, value in model_history.items() if 'false_positive_rate' in key.lower()][0]
valid_fpr=[value for key, value in model_history.items() if 'false_positive_rate' in key.lower()][1]fig, ax1 = plt.subplots()color = 'tab:red'
ax1.set_xlabel('Epoch')
ax1.set_ylabel('Recall', color=color)
ax1.set_ylim([-0.05,1.05])
ax1.plot(train_recall, '--', color=color, label='Train Recall')
ax1.plot(valid_recall, color=color, label='Valid Recall')
ax1.tick_params(axis='y', labelcolor=color)
plt.legend(loc='upper left')
plt.title('Model Recall and FPR')ax2 = ax1.twinx() # instantiate a second axes that shares the same x-axiscolor = 'tab:blue'
ax2.set_ylabel('False Positive Rate', color=color) # we already handled the x-label with ax1
ax2.plot(train_fpr, '--', color=color, label='Train FPR')
ax2.plot(valid_fpr, color=color, label='Valid FPR')
ax2.tick_params(axis='y', labelcolor=color)
ax2.set_ylim([-0.05,1.05])fig.tight_layout() # otherwise the right y-label is slightly clipped
plt.legend(loc='upper right')
plt.show()


模型1.參照算法


n_features = x_train_scaled.shape[1]
mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dense(1, activation='sigmoid'))
mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid_scaled, y_valid),
verbose=0).history


觀察模型擬合損失和準確度(召回率和假陽率)變化


plot_loss(history)

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

plot_model_recall_fpr(history)

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

模型2.類權重


參照上文提到的經驗法則決定類權重。


class_weight = {0: sum(y_train == 1)/len(y_train), 1: sum(y_train == 0)/len(y_train)}


開始訓練模型。


n_features = x_train_scaled.shape[1]mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dense(1, activation='sigmoid'))mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid_scaled, y_valid),
class_weight=class_weight,
verbose=0).historyplot_loss(history)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


plot_model_recall_fpr(history)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

模型3. Dropout正則化


n_features = x_train_scaled.shape[1]mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dropout(0.5))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dropout(0.5))
mlp.add(Dense(1, activation='sigmoid'))mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid_scaled, y_valid),
class_weight=class_weight,
verbose=0).historyplot_loss(history)
代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

plot_model_recall_fpr(history)

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

模型4. 過採樣-欠採樣


使用SMOTE重採樣。


from imblearn.over_sampling import SMOTE
smote = SMOTE(random_state=212)
x_train_scaled_resampled, y_train_resampled = smote.fit_resample(x_train_scaled, y_train)
print('Resampled dataset shape %s' % Counter(y_train_resampled))


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

n_features = x_train_scaled.shape[1]mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dropout(0.5))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dropout(0.5))
mlp.add(Dense(1, activation='sigmoid'))mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled_resampled,
y=y_train_resampled,
batch_size=128,
epochs=100,
validation_data=(x_valid, y_valid),
class_weight=class_weight,
verbose=0).historyplot_loss(history)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

plot_model_recall_fpr(history)

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

模型5. Selu激活


使用因其自規範化屬性而廣為人知的selu激活函數。


注意:


· 使用kernel_initializer=’lecun_normal’ 並AlphaDropout(0.1)

· 在AlphaDropout中使用0.1比率,AlphaDropout(0.1)


n_features = x_train_scaled.shape[1]mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, kernel_initializer='lecun_normal', activation='selu'))
mlp.add(AlphaDropout(0.1))
mlp.add(Dense(16, kernel_initializer='lecun_normal', activation='selu'))
mlp.add(AlphaDropout(0.1))
mlp.add(Dense(1, activation='sigmoid'))mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid, y_valid),
class_weight=class_weight,
verbose=0).historyplot_loss(history)


"
全文共5505字,預計學習時長11分鐘或更長
代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

圖片來源:Unsplash/Dewang Gupta

通過本文的學習, 我們可以瞭解如何著手構建初始神經網絡, 學習經驗法則,比如:隱藏層的數量、節點的數量、激活並觀察其在TensorFlow2中的應用。


深度學習提供了種類繁多的模型。有了它們,就可以建立非常精確的預測模型。然而,由於設置參數數量巨大且種類繁多,要找到出發點會有些困難。


本文將帶領大家找到構建神經網絡的出發點,具體來說是以構建多層感知器為例子。雖然使用了多層感知器為例,但大多數法則都是普遍適用於神經網絡構建的。


整體思路是通過經驗法則先建立第一個神經網絡模型。如果第一個模型能合理運行(達到最低可接受精確度),就對其進行調整與優化。否則,就最好去查看數據和問題所在,或採用其他方法。


本文將介紹:

· 建立神經網絡的經驗法則。

· TensorFlow2中二進制分類的實施代碼。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

神經網絡


神經網絡在卷積神經網絡(CNN)、遞歸神經網絡(RNN)等領域都取得了巨大進步。且隨著時間的推移,每個神經網絡的幾個亞型都得到了發展。正是這一個個的進步,成功地提高了模型的預測能力。


但與此同時,找到模型構建的出發點也變得更難了。


每個神經網絡模型都是不同的,不同的模型有不同的特點和功能,所以在這種情況下,選擇適用的模型變得像在林立的廣告牌中選擇合適的商品一樣困難。


接下來,我們將利用經驗法則構建第一個模型,以克服這些干擾。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

經驗法則


在形形色色的神經網絡中,多層感知器是通往深度學習的敲門磚。因此,當學習或構建一個深度學習領域的模型時,多層感知器就是很好的出發點。


以下是構建多層感知器的經驗法則,且大多數法則都適用於其他深度學習模型。


1. 層數:從兩個隱藏層開始(這其中不包含最後一層)。

2. 中間層的節點數量(大小):是2的倍數,如4,8,16,32……第一層的節點數應該是輸入數據特徵數量的一半左右。下一層的大小是上一層的一半。

3. 分類層最後一層的節點數量(大小):如果是二進制分類,則節點大小為一。對於多類分類器,節點大小等於類的數量。

4. 迴歸層最後一層的大小:如果是單響應,最後一層的大小為1。對於多響應迴歸,最後一層的大小等於響應的數量。

5. 激活中間層,使用Relu激活函數。

6. 激活最後一層:如果是二進制分類,使用sigmoid函數,多類分類器使用softmax函數,迴歸則使用linear函數。對於自動編碼器,如果輸入數據是連續的,使用linear函數進行激活。對於二進制或多級分類輸入,使用sigmoid或softmax函數。

7. Dropout層:除了輸入層以外,在其他每個層都加設Dropout(如果單獨定義輸入層)。將Dropout率設置為0.5。Dropout率大於0.5時結果會適得其反。因此如果覺得0.5會使太多的節點正則化,可以選擇增加層的大小,而不是將Dropout率設置在0.5以下。筆者不喜歡在輸入層設置任何Dropout。但如果認為有必要這樣做,請把Dropout率設置在0.2以下。

8. 數據預處理:假設預測器X是數字,且已經將所有分類列轉化成了獨熱編碼。那麼就可以在進行模型訓練前使用MinMaxScalar對數據進行大小預處理。如果MMS不奏效,就在相同的數據庫中使用StandardScalar對數據進行標準化處理。整個數據處理過程不對y進行操作。

9. 將數據分為訓練數據,有效數據與測試數據:

使用sklearn.model_selection的train_test_split語句。具體操作見下方示例。

10. 類權重:如果數據不平衡,可以在model.fit中設置類權重以平衡損失。對於二進制分類器,權重應為:{0:1的數量/數據大小,1:0的數量/數據大小}。對於極不平衡數據(罕見事件),類權重可能不起作用,請小心添加使用。

11. 優化器:使用adam優化器,應用其默認學習率。

12. 分類損失:對於二進制分類,使用binary_crossentropy.對於多類別分類,如果標籤是獨熱編碼而成的,使用categorical_crossentropy。當標籤都是整數時,使用sparse_categorical_crossentropy 。

13. 迴歸損失:使用均方誤差(mse)函數。

14. 分類指標:使用accuracy顯示正確分類的百分比。對不平衡數據,也要加上tf.keras.metrics.Recall() 和 tf.keras.metrics.FalsePositives().

15. 迴歸指標:使用tf.keras.metrics.RootMeanSquaredError()。

16. 訓練週期:先從20開始,看模型訓練是否顯示出損失的減少,或任何在精確度上的提高。如果20個週期還沒有一點成果就換個方法。如果得到了些許成果,就把訓練週期提升到100。

17. 批處理大小:將批處理大小選擇為2的倍數,對於不平衡數據,通常選用較大值,如128,否則一般都從16開始選用。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


給高級從業人員的一些額外經驗法則


1. 振盪損耗:如果在訓練中遇到振盪損耗,則是由趨同問題導致的。遇到這種問題時,可以嘗試減小學習率和/或更改批處理大小。

2. 過採樣和欠採樣:如果數據不平衡,使用imblearn.over_sampling中的SMOTE算法。

3. 曲線移動:如果需要進行位移預測,比如早期預測,可以使用曲線移動。下方展示了curve_shift的執行。

4. 自定義度量:假陽率是不平衡二進制分類中的一個重要度量。可以如下方給出的class FalsePositiveRate()的執行所示,構建假陽率度量和其他自定義度量。

5. Selu激活函數:在現今所有的激活函數中,selu激活函數被認為是最好的。我並不完全同意這一點,但如果想要使用selu激活函數,可以使用kernel_initializer=’lecun_normal’和 AlphaDropout.在AlphaDropout中使用0.1比率,AlphaDropout(0.1) 。執行實例在下方給出。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

TensorFlow 2中的多層感知器(MLP)實例


在這個執行中,可以看到上述經驗法則中所提到的內容的實際操作。


上述執行是在TensorFlow 2中完成的。強烈建議所有人都轉戰使用TensorFlow 2。它不僅擁有Keras所具有的簡易性,還顯著地提升了計算效率。


本文目的並不是嘗試找到最好的模型,而是學習神經網絡的實現。不會為了簡化過程而跳過任何步驟。相反,本文給出的步驟都很詳細,以幫助讀者的直接應用。



%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as snsimport pandas as pd
import numpy as np
from pylab import rcParamsfrom collections import Counterimport tensorflow as tffrom tensorflow.keras import optimizers
from tensorflow.keras.models import Model, load_model, Sequential
from tensorflow.keras.layers import Input, Dense, Dropout, AlphaDropout
from tensorflow.keras.callbacks import ModelCheckpoint, TensorBoardfrom sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, precision_recall_curve
from sklearn.metrics import recall_score, classification_report, auc, roc_curve
from sklearn.metrics import precision_recall_fscore_support, f1_scorefrom numpy.random import seed
seed(1)SEED = 123 #used to help randomly select the data points
DATA_SPLIT_PCT = 0.2rcParams['figure.figsize'] = 8, 6
LABELS = ["Normal","Break"]


測試是否使用了正確的TensorFlow版本,運行:tf.__version__

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

讀取與準備數據


數據下載傳送門:https://docs.google.com/forms/d/e/1FAIpQLSdyUk3lfDl7I5KYK_pw285LCApc-_RcoC0Tf9cnDnZ_TWzPAw/viewform?source=post_page---------------------------


df = pd.read_csv("data/processminer-rare-event-mts - data.csv") 
df.head(n=5) # visualize the data.


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


將分類列轉換為獨熱編碼

hotencoding1 = pd.get_dummies(df['x28']) # Grade&Bwt
hotencoding1 = hotencoding1.add_prefix('grade_')
hotencoding2 = pd.get_dummies(df['x61']) # EventPress
hotencoding2 = hotencoding2.add_prefix('eventpress_')df=df.drop(['x28', 'x61'], axis=1)df=pd.concat([df, hotencoding1, hotencoding2], axis=1)


曲線移動


以下是一個時間序列數據,要求必須提前預測時間(y=1)。在這個數據中,連續行之間間隔兩分鐘。我們將把行y中的標籤移動兩行,以提前四分鐘進行預測。

sign = lambda x: (1, -1)[x < 0]def curve_shift(df, shift_by):
'''
This function will shift the binary labels in a dataframe.
The curve shift will be with respect to the 1s.
For example, if shift is -2, the following process
will happen: if row n is labeled as 1, then
- Make row (n+shift_by):(n+shift_by-1) = 1.
- Remove row n.
i.e. the labels will be shifted up to 2 rows up.

Inputs:
df A pandas dataframe with a binary labeled column.
This labeled column should be named as 'y'.
shift_by An integer denoting the number of rows to shift.

Output
df A dataframe with the binary labels shifted by shift.
'''vector = df['y'].copy()
for s in range(abs(shift_by)):
tmp = vector.shift(sign(shift_by))
tmp = tmp.fillna(0)
vector += tmp
labelcol = 'y'
# Add vector to the df
df.insert(loc=0, column=labelcol+'tmp', value=vector)
# Remove the rows with labelcol == 1.
df = df.drop(df[df[labelcol] == 1].index)
# Drop labelcol and rename the tmp col as labelcol
df = df.drop(labelcol, axis=1)
df = df.rename(columns={labelcol+'tmp': labelcol})
# Make the labelcol binary
df.loc[df[labelcol] > 0, labelcol] = 1return df


向上移動兩行


df = curve_shift(df, shift_by = -2)


從這裡開始不需要時間行了,將其移除。


df = df.drop(['time'], axis=1)


將數據分為訓練數據,有效數據和測試數據。

df_train, df_test = train_test_split(df, test_size=DATA_SPLIT_PCT, random_state=SEED)
df_train, df_valid = train_test_split(df_train, test_size=DATA_SPLIT_PCT, random_state=SEED)


把X和y分開

x_train = df_train.drop(['y'], axis=1)
y_train = df_train.y.valuesx_valid = df_valid.drop(['y'], axis=1)
y_valid = df_valid.y.valuesx_test = df_test.drop(['y'], axis=1)
y_test = df_test.y


數據縮放

scaler = MinMaxScaler().fit(x_train)
# scaler = StandardScaler().fit(x_train)
x_train_scaled = scaler.transform(x_train)
x_valid_scaled = scaler.transform(x_valid)
x_test_scaled = scaler.transform(x_test)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

MLP模型


自定義度量:FalsePositiveRate()


開發一個在下面所有模型中都要用到的FalsePositiveRate()度量。


class FalsePositiveRate(tf.keras.metrics.Metric):
def __init__(self, name='false_positive_rate', **kwargs):
super(FalsePositiveRate, self).__init__(name=name, **kwargs)
self.negatives = self.add_weight(name='negatives', initializer='zeros')
self.false_positives = self.add_weight(name='false_negatives', initializer='zeros')

def update_state(self, y_true, y_pred, sample_weight=None):
'''
Arguments:
y_true The actual y. Passed by default to Metric classes.
y_pred The predicted y. Passed by default to Metric classes.

'''
# Compute the number of negatives.
y_true = tf.cast(y_true, tf.bool)

negatives = tf.reduce_sum(tf.cast(tf.equal(y_true, False), self.dtype))

self.negatives.assign_add(negatives)

# Compute the number of false positives.
y_pred = tf.greater_equal(y_pred, 0.5) # Using default threshold of 0.5 to call a prediction as positive labeled.

false_positive_values = tf.logical_and(tf.equal(y_true, False), tf.equal(y_pred, True))
false_positive_values = tf.cast(false_positive_values, self.dtype)
if sample_weight is not None:
sample_weight = tf.cast(sample_weight, self.dtype)
sample_weight = tf.broadcast_weights(sample_weight, values)
values = tf.multiply(false_positive_values, sample_weight)

false_positives = tf.reduce_sum(false_positive_values)

self.false_positives.assign_add(false_positives)

def result(self):
return tf.divide(self.false_positives, self.negatives)


常規性能繪圖函數


def plot_loss(model_history):
train_loss=[value for key, value in model_history.items() if 'loss' in key.lower()][0]
valid_loss=[value for key, value in model_history.items() if 'loss' in key.lower()][1]fig, ax1 = plt.subplots()color = 'tab:blue'
ax1.set_xlabel('Epoch')
ax1.set_ylabel('Loss', color=color)
ax1.plot(train_loss, '--', color=color, label='Train Loss')
ax1.plot(valid_loss, color=color, label='Valid Loss')
ax1.tick_params(axis='y', labelcolor=color)
plt.legend(loc='upper left')
plt.title('Model Loss')plt.show()def plot_model_recall_fpr(model_history):
train_recall=[value for key, value in model_history.items() if 'recall' in key.lower()][0]
valid_recall=[value for key, value in model_history.items() if 'recall' in key.lower()][1]train_fpr=[value for key, value in model_history.items() if 'false_positive_rate' in key.lower()][0]
valid_fpr=[value for key, value in model_history.items() if 'false_positive_rate' in key.lower()][1]fig, ax1 = plt.subplots()color = 'tab:red'
ax1.set_xlabel('Epoch')
ax1.set_ylabel('Recall', color=color)
ax1.set_ylim([-0.05,1.05])
ax1.plot(train_recall, '--', color=color, label='Train Recall')
ax1.plot(valid_recall, color=color, label='Valid Recall')
ax1.tick_params(axis='y', labelcolor=color)
plt.legend(loc='upper left')
plt.title('Model Recall and FPR')ax2 = ax1.twinx() # instantiate a second axes that shares the same x-axiscolor = 'tab:blue'
ax2.set_ylabel('False Positive Rate', color=color) # we already handled the x-label with ax1
ax2.plot(train_fpr, '--', color=color, label='Train FPR')
ax2.plot(valid_fpr, color=color, label='Valid FPR')
ax2.tick_params(axis='y', labelcolor=color)
ax2.set_ylim([-0.05,1.05])fig.tight_layout() # otherwise the right y-label is slightly clipped
plt.legend(loc='upper right')
plt.show()


模型1.參照算法


n_features = x_train_scaled.shape[1]
mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dense(1, activation='sigmoid'))
mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid_scaled, y_valid),
verbose=0).history


觀察模型擬合損失和準確度(召回率和假陽率)變化


plot_loss(history)

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

plot_model_recall_fpr(history)

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

模型2.類權重


參照上文提到的經驗法則決定類權重。


class_weight = {0: sum(y_train == 1)/len(y_train), 1: sum(y_train == 0)/len(y_train)}


開始訓練模型。


n_features = x_train_scaled.shape[1]mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dense(1, activation='sigmoid'))mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid_scaled, y_valid),
class_weight=class_weight,
verbose=0).historyplot_loss(history)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


plot_model_recall_fpr(history)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

模型3. Dropout正則化


n_features = x_train_scaled.shape[1]mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dropout(0.5))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dropout(0.5))
mlp.add(Dense(1, activation='sigmoid'))mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid_scaled, y_valid),
class_weight=class_weight,
verbose=0).historyplot_loss(history)
代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

plot_model_recall_fpr(history)

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

模型4. 過採樣-欠採樣


使用SMOTE重採樣。


from imblearn.over_sampling import SMOTE
smote = SMOTE(random_state=212)
x_train_scaled_resampled, y_train_resampled = smote.fit_resample(x_train_scaled, y_train)
print('Resampled dataset shape %s' % Counter(y_train_resampled))


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

n_features = x_train_scaled.shape[1]mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dropout(0.5))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dropout(0.5))
mlp.add(Dense(1, activation='sigmoid'))mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled_resampled,
y=y_train_resampled,
batch_size=128,
epochs=100,
validation_data=(x_valid, y_valid),
class_weight=class_weight,
verbose=0).historyplot_loss(history)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

plot_model_recall_fpr(history)

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

模型5. Selu激活


使用因其自規範化屬性而廣為人知的selu激活函數。


注意:


· 使用kernel_initializer=’lecun_normal’ 並AlphaDropout(0.1)

· 在AlphaDropout中使用0.1比率,AlphaDropout(0.1)


n_features = x_train_scaled.shape[1]mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, kernel_initializer='lecun_normal', activation='selu'))
mlp.add(AlphaDropout(0.1))
mlp.add(Dense(16, kernel_initializer='lecun_normal', activation='selu'))
mlp.add(AlphaDropout(0.1))
mlp.add(Dense(1, activation='sigmoid'))mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid, y_valid),
class_weight=class_weight,
verbose=0).historyplot_loss(history)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


plot_model_recall_fpr(history)


"
全文共5505字,預計學習時長11分鐘或更長
代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

圖片來源:Unsplash/Dewang Gupta

通過本文的學習, 我們可以瞭解如何著手構建初始神經網絡, 學習經驗法則,比如:隱藏層的數量、節點的數量、激活並觀察其在TensorFlow2中的應用。


深度學習提供了種類繁多的模型。有了它們,就可以建立非常精確的預測模型。然而,由於設置參數數量巨大且種類繁多,要找到出發點會有些困難。


本文將帶領大家找到構建神經網絡的出發點,具體來說是以構建多層感知器為例子。雖然使用了多層感知器為例,但大多數法則都是普遍適用於神經網絡構建的。


整體思路是通過經驗法則先建立第一個神經網絡模型。如果第一個模型能合理運行(達到最低可接受精確度),就對其進行調整與優化。否則,就最好去查看數據和問題所在,或採用其他方法。


本文將介紹:

· 建立神經網絡的經驗法則。

· TensorFlow2中二進制分類的實施代碼。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

神經網絡


神經網絡在卷積神經網絡(CNN)、遞歸神經網絡(RNN)等領域都取得了巨大進步。且隨著時間的推移,每個神經網絡的幾個亞型都得到了發展。正是這一個個的進步,成功地提高了模型的預測能力。


但與此同時,找到模型構建的出發點也變得更難了。


每個神經網絡模型都是不同的,不同的模型有不同的特點和功能,所以在這種情況下,選擇適用的模型變得像在林立的廣告牌中選擇合適的商品一樣困難。


接下來,我們將利用經驗法則構建第一個模型,以克服這些干擾。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

經驗法則


在形形色色的神經網絡中,多層感知器是通往深度學習的敲門磚。因此,當學習或構建一個深度學習領域的模型時,多層感知器就是很好的出發點。


以下是構建多層感知器的經驗法則,且大多數法則都適用於其他深度學習模型。


1. 層數:從兩個隱藏層開始(這其中不包含最後一層)。

2. 中間層的節點數量(大小):是2的倍數,如4,8,16,32……第一層的節點數應該是輸入數據特徵數量的一半左右。下一層的大小是上一層的一半。

3. 分類層最後一層的節點數量(大小):如果是二進制分類,則節點大小為一。對於多類分類器,節點大小等於類的數量。

4. 迴歸層最後一層的大小:如果是單響應,最後一層的大小為1。對於多響應迴歸,最後一層的大小等於響應的數量。

5. 激活中間層,使用Relu激活函數。

6. 激活最後一層:如果是二進制分類,使用sigmoid函數,多類分類器使用softmax函數,迴歸則使用linear函數。對於自動編碼器,如果輸入數據是連續的,使用linear函數進行激活。對於二進制或多級分類輸入,使用sigmoid或softmax函數。

7. Dropout層:除了輸入層以外,在其他每個層都加設Dropout(如果單獨定義輸入層)。將Dropout率設置為0.5。Dropout率大於0.5時結果會適得其反。因此如果覺得0.5會使太多的節點正則化,可以選擇增加層的大小,而不是將Dropout率設置在0.5以下。筆者不喜歡在輸入層設置任何Dropout。但如果認為有必要這樣做,請把Dropout率設置在0.2以下。

8. 數據預處理:假設預測器X是數字,且已經將所有分類列轉化成了獨熱編碼。那麼就可以在進行模型訓練前使用MinMaxScalar對數據進行大小預處理。如果MMS不奏效,就在相同的數據庫中使用StandardScalar對數據進行標準化處理。整個數據處理過程不對y進行操作。

9. 將數據分為訓練數據,有效數據與測試數據:

使用sklearn.model_selection的train_test_split語句。具體操作見下方示例。

10. 類權重:如果數據不平衡,可以在model.fit中設置類權重以平衡損失。對於二進制分類器,權重應為:{0:1的數量/數據大小,1:0的數量/數據大小}。對於極不平衡數據(罕見事件),類權重可能不起作用,請小心添加使用。

11. 優化器:使用adam優化器,應用其默認學習率。

12. 分類損失:對於二進制分類,使用binary_crossentropy.對於多類別分類,如果標籤是獨熱編碼而成的,使用categorical_crossentropy。當標籤都是整數時,使用sparse_categorical_crossentropy 。

13. 迴歸損失:使用均方誤差(mse)函數。

14. 分類指標:使用accuracy顯示正確分類的百分比。對不平衡數據,也要加上tf.keras.metrics.Recall() 和 tf.keras.metrics.FalsePositives().

15. 迴歸指標:使用tf.keras.metrics.RootMeanSquaredError()。

16. 訓練週期:先從20開始,看模型訓練是否顯示出損失的減少,或任何在精確度上的提高。如果20個週期還沒有一點成果就換個方法。如果得到了些許成果,就把訓練週期提升到100。

17. 批處理大小:將批處理大小選擇為2的倍數,對於不平衡數據,通常選用較大值,如128,否則一般都從16開始選用。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


給高級從業人員的一些額外經驗法則


1. 振盪損耗:如果在訓練中遇到振盪損耗,則是由趨同問題導致的。遇到這種問題時,可以嘗試減小學習率和/或更改批處理大小。

2. 過採樣和欠採樣:如果數據不平衡,使用imblearn.over_sampling中的SMOTE算法。

3. 曲線移動:如果需要進行位移預測,比如早期預測,可以使用曲線移動。下方展示了curve_shift的執行。

4. 自定義度量:假陽率是不平衡二進制分類中的一個重要度量。可以如下方給出的class FalsePositiveRate()的執行所示,構建假陽率度量和其他自定義度量。

5. Selu激活函數:在現今所有的激活函數中,selu激活函數被認為是最好的。我並不完全同意這一點,但如果想要使用selu激活函數,可以使用kernel_initializer=’lecun_normal’和 AlphaDropout.在AlphaDropout中使用0.1比率,AlphaDropout(0.1) 。執行實例在下方給出。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

TensorFlow 2中的多層感知器(MLP)實例


在這個執行中,可以看到上述經驗法則中所提到的內容的實際操作。


上述執行是在TensorFlow 2中完成的。強烈建議所有人都轉戰使用TensorFlow 2。它不僅擁有Keras所具有的簡易性,還顯著地提升了計算效率。


本文目的並不是嘗試找到最好的模型,而是學習神經網絡的實現。不會為了簡化過程而跳過任何步驟。相反,本文給出的步驟都很詳細,以幫助讀者的直接應用。



%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as snsimport pandas as pd
import numpy as np
from pylab import rcParamsfrom collections import Counterimport tensorflow as tffrom tensorflow.keras import optimizers
from tensorflow.keras.models import Model, load_model, Sequential
from tensorflow.keras.layers import Input, Dense, Dropout, AlphaDropout
from tensorflow.keras.callbacks import ModelCheckpoint, TensorBoardfrom sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, precision_recall_curve
from sklearn.metrics import recall_score, classification_report, auc, roc_curve
from sklearn.metrics import precision_recall_fscore_support, f1_scorefrom numpy.random import seed
seed(1)SEED = 123 #used to help randomly select the data points
DATA_SPLIT_PCT = 0.2rcParams['figure.figsize'] = 8, 6
LABELS = ["Normal","Break"]


測試是否使用了正確的TensorFlow版本,運行:tf.__version__

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

讀取與準備數據


數據下載傳送門:https://docs.google.com/forms/d/e/1FAIpQLSdyUk3lfDl7I5KYK_pw285LCApc-_RcoC0Tf9cnDnZ_TWzPAw/viewform?source=post_page---------------------------


df = pd.read_csv("data/processminer-rare-event-mts - data.csv") 
df.head(n=5) # visualize the data.


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


將分類列轉換為獨熱編碼

hotencoding1 = pd.get_dummies(df['x28']) # Grade&Bwt
hotencoding1 = hotencoding1.add_prefix('grade_')
hotencoding2 = pd.get_dummies(df['x61']) # EventPress
hotencoding2 = hotencoding2.add_prefix('eventpress_')df=df.drop(['x28', 'x61'], axis=1)df=pd.concat([df, hotencoding1, hotencoding2], axis=1)


曲線移動


以下是一個時間序列數據,要求必須提前預測時間(y=1)。在這個數據中,連續行之間間隔兩分鐘。我們將把行y中的標籤移動兩行,以提前四分鐘進行預測。

sign = lambda x: (1, -1)[x < 0]def curve_shift(df, shift_by):
'''
This function will shift the binary labels in a dataframe.
The curve shift will be with respect to the 1s.
For example, if shift is -2, the following process
will happen: if row n is labeled as 1, then
- Make row (n+shift_by):(n+shift_by-1) = 1.
- Remove row n.
i.e. the labels will be shifted up to 2 rows up.

Inputs:
df A pandas dataframe with a binary labeled column.
This labeled column should be named as 'y'.
shift_by An integer denoting the number of rows to shift.

Output
df A dataframe with the binary labels shifted by shift.
'''vector = df['y'].copy()
for s in range(abs(shift_by)):
tmp = vector.shift(sign(shift_by))
tmp = tmp.fillna(0)
vector += tmp
labelcol = 'y'
# Add vector to the df
df.insert(loc=0, column=labelcol+'tmp', value=vector)
# Remove the rows with labelcol == 1.
df = df.drop(df[df[labelcol] == 1].index)
# Drop labelcol and rename the tmp col as labelcol
df = df.drop(labelcol, axis=1)
df = df.rename(columns={labelcol+'tmp': labelcol})
# Make the labelcol binary
df.loc[df[labelcol] > 0, labelcol] = 1return df


向上移動兩行


df = curve_shift(df, shift_by = -2)


從這裡開始不需要時間行了,將其移除。


df = df.drop(['time'], axis=1)


將數據分為訓練數據,有效數據和測試數據。

df_train, df_test = train_test_split(df, test_size=DATA_SPLIT_PCT, random_state=SEED)
df_train, df_valid = train_test_split(df_train, test_size=DATA_SPLIT_PCT, random_state=SEED)


把X和y分開

x_train = df_train.drop(['y'], axis=1)
y_train = df_train.y.valuesx_valid = df_valid.drop(['y'], axis=1)
y_valid = df_valid.y.valuesx_test = df_test.drop(['y'], axis=1)
y_test = df_test.y


數據縮放

scaler = MinMaxScaler().fit(x_train)
# scaler = StandardScaler().fit(x_train)
x_train_scaled = scaler.transform(x_train)
x_valid_scaled = scaler.transform(x_valid)
x_test_scaled = scaler.transform(x_test)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

MLP模型


自定義度量:FalsePositiveRate()


開發一個在下面所有模型中都要用到的FalsePositiveRate()度量。


class FalsePositiveRate(tf.keras.metrics.Metric):
def __init__(self, name='false_positive_rate', **kwargs):
super(FalsePositiveRate, self).__init__(name=name, **kwargs)
self.negatives = self.add_weight(name='negatives', initializer='zeros')
self.false_positives = self.add_weight(name='false_negatives', initializer='zeros')

def update_state(self, y_true, y_pred, sample_weight=None):
'''
Arguments:
y_true The actual y. Passed by default to Metric classes.
y_pred The predicted y. Passed by default to Metric classes.

'''
# Compute the number of negatives.
y_true = tf.cast(y_true, tf.bool)

negatives = tf.reduce_sum(tf.cast(tf.equal(y_true, False), self.dtype))

self.negatives.assign_add(negatives)

# Compute the number of false positives.
y_pred = tf.greater_equal(y_pred, 0.5) # Using default threshold of 0.5 to call a prediction as positive labeled.

false_positive_values = tf.logical_and(tf.equal(y_true, False), tf.equal(y_pred, True))
false_positive_values = tf.cast(false_positive_values, self.dtype)
if sample_weight is not None:
sample_weight = tf.cast(sample_weight, self.dtype)
sample_weight = tf.broadcast_weights(sample_weight, values)
values = tf.multiply(false_positive_values, sample_weight)

false_positives = tf.reduce_sum(false_positive_values)

self.false_positives.assign_add(false_positives)

def result(self):
return tf.divide(self.false_positives, self.negatives)


常規性能繪圖函數


def plot_loss(model_history):
train_loss=[value for key, value in model_history.items() if 'loss' in key.lower()][0]
valid_loss=[value for key, value in model_history.items() if 'loss' in key.lower()][1]fig, ax1 = plt.subplots()color = 'tab:blue'
ax1.set_xlabel('Epoch')
ax1.set_ylabel('Loss', color=color)
ax1.plot(train_loss, '--', color=color, label='Train Loss')
ax1.plot(valid_loss, color=color, label='Valid Loss')
ax1.tick_params(axis='y', labelcolor=color)
plt.legend(loc='upper left')
plt.title('Model Loss')plt.show()def plot_model_recall_fpr(model_history):
train_recall=[value for key, value in model_history.items() if 'recall' in key.lower()][0]
valid_recall=[value for key, value in model_history.items() if 'recall' in key.lower()][1]train_fpr=[value for key, value in model_history.items() if 'false_positive_rate' in key.lower()][0]
valid_fpr=[value for key, value in model_history.items() if 'false_positive_rate' in key.lower()][1]fig, ax1 = plt.subplots()color = 'tab:red'
ax1.set_xlabel('Epoch')
ax1.set_ylabel('Recall', color=color)
ax1.set_ylim([-0.05,1.05])
ax1.plot(train_recall, '--', color=color, label='Train Recall')
ax1.plot(valid_recall, color=color, label='Valid Recall')
ax1.tick_params(axis='y', labelcolor=color)
plt.legend(loc='upper left')
plt.title('Model Recall and FPR')ax2 = ax1.twinx() # instantiate a second axes that shares the same x-axiscolor = 'tab:blue'
ax2.set_ylabel('False Positive Rate', color=color) # we already handled the x-label with ax1
ax2.plot(train_fpr, '--', color=color, label='Train FPR')
ax2.plot(valid_fpr, color=color, label='Valid FPR')
ax2.tick_params(axis='y', labelcolor=color)
ax2.set_ylim([-0.05,1.05])fig.tight_layout() # otherwise the right y-label is slightly clipped
plt.legend(loc='upper right')
plt.show()


模型1.參照算法


n_features = x_train_scaled.shape[1]
mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dense(1, activation='sigmoid'))
mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid_scaled, y_valid),
verbose=0).history


觀察模型擬合損失和準確度(召回率和假陽率)變化


plot_loss(history)

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

plot_model_recall_fpr(history)

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

模型2.類權重


參照上文提到的經驗法則決定類權重。


class_weight = {0: sum(y_train == 1)/len(y_train), 1: sum(y_train == 0)/len(y_train)}


開始訓練模型。


n_features = x_train_scaled.shape[1]mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dense(1, activation='sigmoid'))mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid_scaled, y_valid),
class_weight=class_weight,
verbose=0).historyplot_loss(history)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


plot_model_recall_fpr(history)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

模型3. Dropout正則化


n_features = x_train_scaled.shape[1]mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dropout(0.5))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dropout(0.5))
mlp.add(Dense(1, activation='sigmoid'))mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid_scaled, y_valid),
class_weight=class_weight,
verbose=0).historyplot_loss(history)
代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

plot_model_recall_fpr(history)

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

模型4. 過採樣-欠採樣


使用SMOTE重採樣。


from imblearn.over_sampling import SMOTE
smote = SMOTE(random_state=212)
x_train_scaled_resampled, y_train_resampled = smote.fit_resample(x_train_scaled, y_train)
print('Resampled dataset shape %s' % Counter(y_train_resampled))


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

n_features = x_train_scaled.shape[1]mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dropout(0.5))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dropout(0.5))
mlp.add(Dense(1, activation='sigmoid'))mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled_resampled,
y=y_train_resampled,
batch_size=128,
epochs=100,
validation_data=(x_valid, y_valid),
class_weight=class_weight,
verbose=0).historyplot_loss(history)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

plot_model_recall_fpr(history)

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

模型5. Selu激活


使用因其自規範化屬性而廣為人知的selu激活函數。


注意:


· 使用kernel_initializer=’lecun_normal’ 並AlphaDropout(0.1)

· 在AlphaDropout中使用0.1比率,AlphaDropout(0.1)


n_features = x_train_scaled.shape[1]mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, kernel_initializer='lecun_normal', activation='selu'))
mlp.add(AlphaDropout(0.1))
mlp.add(Dense(16, kernel_initializer='lecun_normal', activation='selu'))
mlp.add(AlphaDropout(0.1))
mlp.add(Dense(1, activation='sigmoid'))mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid, y_valid),
class_weight=class_weight,
verbose=0).historyplot_loss(history)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


plot_model_recall_fpr(history)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

結論


· 儘管深度學習提供了預測模型能力, 在尋找出發點的時候也可能會無所適從。

· 文中的經驗法則提供了構建初始神經網絡的出發點。

· 在此基礎上構建的模型應進行進一步調整,以提高性能。

· 如果使用這些經驗法則構建的模型性能沒有任何可取之處,進一步調整可能不會帶來太大的改進,這時就應嘗試使用其他的方法。

· 本文介紹了在TensorFlow 2中實現神經網絡的步驟。

· 如果沒有TensorFlow 2,建議開始使用它。Tensorflow2不僅具有Keras所具有的簡易性,同時還具備高性能的特點。


Tensorflow2安裝指南:https://towardsdatascience.com/step-by-step-guide-to-install-tensorflow-2-0-67bc73e79b82?source=post_page---------------------------


"
全文共5505字,預計學習時長11分鐘或更長
代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

圖片來源:Unsplash/Dewang Gupta

通過本文的學習, 我們可以瞭解如何著手構建初始神經網絡, 學習經驗法則,比如:隱藏層的數量、節點的數量、激活並觀察其在TensorFlow2中的應用。


深度學習提供了種類繁多的模型。有了它們,就可以建立非常精確的預測模型。然而,由於設置參數數量巨大且種類繁多,要找到出發點會有些困難。


本文將帶領大家找到構建神經網絡的出發點,具體來說是以構建多層感知器為例子。雖然使用了多層感知器為例,但大多數法則都是普遍適用於神經網絡構建的。


整體思路是通過經驗法則先建立第一個神經網絡模型。如果第一個模型能合理運行(達到最低可接受精確度),就對其進行調整與優化。否則,就最好去查看數據和問題所在,或採用其他方法。


本文將介紹:

· 建立神經網絡的經驗法則。

· TensorFlow2中二進制分類的實施代碼。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

神經網絡


神經網絡在卷積神經網絡(CNN)、遞歸神經網絡(RNN)等領域都取得了巨大進步。且隨著時間的推移,每個神經網絡的幾個亞型都得到了發展。正是這一個個的進步,成功地提高了模型的預測能力。


但與此同時,找到模型構建的出發點也變得更難了。


每個神經網絡模型都是不同的,不同的模型有不同的特點和功能,所以在這種情況下,選擇適用的模型變得像在林立的廣告牌中選擇合適的商品一樣困難。


接下來,我們將利用經驗法則構建第一個模型,以克服這些干擾。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

經驗法則


在形形色色的神經網絡中,多層感知器是通往深度學習的敲門磚。因此,當學習或構建一個深度學習領域的模型時,多層感知器就是很好的出發點。


以下是構建多層感知器的經驗法則,且大多數法則都適用於其他深度學習模型。


1. 層數:從兩個隱藏層開始(這其中不包含最後一層)。

2. 中間層的節點數量(大小):是2的倍數,如4,8,16,32……第一層的節點數應該是輸入數據特徵數量的一半左右。下一層的大小是上一層的一半。

3. 分類層最後一層的節點數量(大小):如果是二進制分類,則節點大小為一。對於多類分類器,節點大小等於類的數量。

4. 迴歸層最後一層的大小:如果是單響應,最後一層的大小為1。對於多響應迴歸,最後一層的大小等於響應的數量。

5. 激活中間層,使用Relu激活函數。

6. 激活最後一層:如果是二進制分類,使用sigmoid函數,多類分類器使用softmax函數,迴歸則使用linear函數。對於自動編碼器,如果輸入數據是連續的,使用linear函數進行激活。對於二進制或多級分類輸入,使用sigmoid或softmax函數。

7. Dropout層:除了輸入層以外,在其他每個層都加設Dropout(如果單獨定義輸入層)。將Dropout率設置為0.5。Dropout率大於0.5時結果會適得其反。因此如果覺得0.5會使太多的節點正則化,可以選擇增加層的大小,而不是將Dropout率設置在0.5以下。筆者不喜歡在輸入層設置任何Dropout。但如果認為有必要這樣做,請把Dropout率設置在0.2以下。

8. 數據預處理:假設預測器X是數字,且已經將所有分類列轉化成了獨熱編碼。那麼就可以在進行模型訓練前使用MinMaxScalar對數據進行大小預處理。如果MMS不奏效,就在相同的數據庫中使用StandardScalar對數據進行標準化處理。整個數據處理過程不對y進行操作。

9. 將數據分為訓練數據,有效數據與測試數據:

使用sklearn.model_selection的train_test_split語句。具體操作見下方示例。

10. 類權重:如果數據不平衡,可以在model.fit中設置類權重以平衡損失。對於二進制分類器,權重應為:{0:1的數量/數據大小,1:0的數量/數據大小}。對於極不平衡數據(罕見事件),類權重可能不起作用,請小心添加使用。

11. 優化器:使用adam優化器,應用其默認學習率。

12. 分類損失:對於二進制分類,使用binary_crossentropy.對於多類別分類,如果標籤是獨熱編碼而成的,使用categorical_crossentropy。當標籤都是整數時,使用sparse_categorical_crossentropy 。

13. 迴歸損失:使用均方誤差(mse)函數。

14. 分類指標:使用accuracy顯示正確分類的百分比。對不平衡數據,也要加上tf.keras.metrics.Recall() 和 tf.keras.metrics.FalsePositives().

15. 迴歸指標:使用tf.keras.metrics.RootMeanSquaredError()。

16. 訓練週期:先從20開始,看模型訓練是否顯示出損失的減少,或任何在精確度上的提高。如果20個週期還沒有一點成果就換個方法。如果得到了些許成果,就把訓練週期提升到100。

17. 批處理大小:將批處理大小選擇為2的倍數,對於不平衡數據,通常選用較大值,如128,否則一般都從16開始選用。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


給高級從業人員的一些額外經驗法則


1. 振盪損耗:如果在訓練中遇到振盪損耗,則是由趨同問題導致的。遇到這種問題時,可以嘗試減小學習率和/或更改批處理大小。

2. 過採樣和欠採樣:如果數據不平衡,使用imblearn.over_sampling中的SMOTE算法。

3. 曲線移動:如果需要進行位移預測,比如早期預測,可以使用曲線移動。下方展示了curve_shift的執行。

4. 自定義度量:假陽率是不平衡二進制分類中的一個重要度量。可以如下方給出的class FalsePositiveRate()的執行所示,構建假陽率度量和其他自定義度量。

5. Selu激活函數:在現今所有的激活函數中,selu激活函數被認為是最好的。我並不完全同意這一點,但如果想要使用selu激活函數,可以使用kernel_initializer=’lecun_normal’和 AlphaDropout.在AlphaDropout中使用0.1比率,AlphaDropout(0.1) 。執行實例在下方給出。


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

TensorFlow 2中的多層感知器(MLP)實例


在這個執行中,可以看到上述經驗法則中所提到的內容的實際操作。


上述執行是在TensorFlow 2中完成的。強烈建議所有人都轉戰使用TensorFlow 2。它不僅擁有Keras所具有的簡易性,還顯著地提升了計算效率。


本文目的並不是嘗試找到最好的模型,而是學習神經網絡的實現。不會為了簡化過程而跳過任何步驟。相反,本文給出的步驟都很詳細,以幫助讀者的直接應用。



%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as snsimport pandas as pd
import numpy as np
from pylab import rcParamsfrom collections import Counterimport tensorflow as tffrom tensorflow.keras import optimizers
from tensorflow.keras.models import Model, load_model, Sequential
from tensorflow.keras.layers import Input, Dense, Dropout, AlphaDropout
from tensorflow.keras.callbacks import ModelCheckpoint, TensorBoardfrom sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, precision_recall_curve
from sklearn.metrics import recall_score, classification_report, auc, roc_curve
from sklearn.metrics import precision_recall_fscore_support, f1_scorefrom numpy.random import seed
seed(1)SEED = 123 #used to help randomly select the data points
DATA_SPLIT_PCT = 0.2rcParams['figure.figsize'] = 8, 6
LABELS = ["Normal","Break"]


測試是否使用了正確的TensorFlow版本,運行:tf.__version__

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

讀取與準備數據


數據下載傳送門:https://docs.google.com/forms/d/e/1FAIpQLSdyUk3lfDl7I5KYK_pw285LCApc-_RcoC0Tf9cnDnZ_TWzPAw/viewform?source=post_page---------------------------


df = pd.read_csv("data/processminer-rare-event-mts - data.csv") 
df.head(n=5) # visualize the data.


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


將分類列轉換為獨熱編碼

hotencoding1 = pd.get_dummies(df['x28']) # Grade&Bwt
hotencoding1 = hotencoding1.add_prefix('grade_')
hotencoding2 = pd.get_dummies(df['x61']) # EventPress
hotencoding2 = hotencoding2.add_prefix('eventpress_')df=df.drop(['x28', 'x61'], axis=1)df=pd.concat([df, hotencoding1, hotencoding2], axis=1)


曲線移動


以下是一個時間序列數據,要求必須提前預測時間(y=1)。在這個數據中,連續行之間間隔兩分鐘。我們將把行y中的標籤移動兩行,以提前四分鐘進行預測。

sign = lambda x: (1, -1)[x < 0]def curve_shift(df, shift_by):
'''
This function will shift the binary labels in a dataframe.
The curve shift will be with respect to the 1s.
For example, if shift is -2, the following process
will happen: if row n is labeled as 1, then
- Make row (n+shift_by):(n+shift_by-1) = 1.
- Remove row n.
i.e. the labels will be shifted up to 2 rows up.

Inputs:
df A pandas dataframe with a binary labeled column.
This labeled column should be named as 'y'.
shift_by An integer denoting the number of rows to shift.

Output
df A dataframe with the binary labels shifted by shift.
'''vector = df['y'].copy()
for s in range(abs(shift_by)):
tmp = vector.shift(sign(shift_by))
tmp = tmp.fillna(0)
vector += tmp
labelcol = 'y'
# Add vector to the df
df.insert(loc=0, column=labelcol+'tmp', value=vector)
# Remove the rows with labelcol == 1.
df = df.drop(df[df[labelcol] == 1].index)
# Drop labelcol and rename the tmp col as labelcol
df = df.drop(labelcol, axis=1)
df = df.rename(columns={labelcol+'tmp': labelcol})
# Make the labelcol binary
df.loc[df[labelcol] > 0, labelcol] = 1return df


向上移動兩行


df = curve_shift(df, shift_by = -2)


從這裡開始不需要時間行了,將其移除。


df = df.drop(['time'], axis=1)


將數據分為訓練數據,有效數據和測試數據。

df_train, df_test = train_test_split(df, test_size=DATA_SPLIT_PCT, random_state=SEED)
df_train, df_valid = train_test_split(df_train, test_size=DATA_SPLIT_PCT, random_state=SEED)


把X和y分開

x_train = df_train.drop(['y'], axis=1)
y_train = df_train.y.valuesx_valid = df_valid.drop(['y'], axis=1)
y_valid = df_valid.y.valuesx_test = df_test.drop(['y'], axis=1)
y_test = df_test.y


數據縮放

scaler = MinMaxScaler().fit(x_train)
# scaler = StandardScaler().fit(x_train)
x_train_scaled = scaler.transform(x_train)
x_valid_scaled = scaler.transform(x_valid)
x_test_scaled = scaler.transform(x_test)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

MLP模型


自定義度量:FalsePositiveRate()


開發一個在下面所有模型中都要用到的FalsePositiveRate()度量。


class FalsePositiveRate(tf.keras.metrics.Metric):
def __init__(self, name='false_positive_rate', **kwargs):
super(FalsePositiveRate, self).__init__(name=name, **kwargs)
self.negatives = self.add_weight(name='negatives', initializer='zeros')
self.false_positives = self.add_weight(name='false_negatives', initializer='zeros')

def update_state(self, y_true, y_pred, sample_weight=None):
'''
Arguments:
y_true The actual y. Passed by default to Metric classes.
y_pred The predicted y. Passed by default to Metric classes.

'''
# Compute the number of negatives.
y_true = tf.cast(y_true, tf.bool)

negatives = tf.reduce_sum(tf.cast(tf.equal(y_true, False), self.dtype))

self.negatives.assign_add(negatives)

# Compute the number of false positives.
y_pred = tf.greater_equal(y_pred, 0.5) # Using default threshold of 0.5 to call a prediction as positive labeled.

false_positive_values = tf.logical_and(tf.equal(y_true, False), tf.equal(y_pred, True))
false_positive_values = tf.cast(false_positive_values, self.dtype)
if sample_weight is not None:
sample_weight = tf.cast(sample_weight, self.dtype)
sample_weight = tf.broadcast_weights(sample_weight, values)
values = tf.multiply(false_positive_values, sample_weight)

false_positives = tf.reduce_sum(false_positive_values)

self.false_positives.assign_add(false_positives)

def result(self):
return tf.divide(self.false_positives, self.negatives)


常規性能繪圖函數


def plot_loss(model_history):
train_loss=[value for key, value in model_history.items() if 'loss' in key.lower()][0]
valid_loss=[value for key, value in model_history.items() if 'loss' in key.lower()][1]fig, ax1 = plt.subplots()color = 'tab:blue'
ax1.set_xlabel('Epoch')
ax1.set_ylabel('Loss', color=color)
ax1.plot(train_loss, '--', color=color, label='Train Loss')
ax1.plot(valid_loss, color=color, label='Valid Loss')
ax1.tick_params(axis='y', labelcolor=color)
plt.legend(loc='upper left')
plt.title('Model Loss')plt.show()def plot_model_recall_fpr(model_history):
train_recall=[value for key, value in model_history.items() if 'recall' in key.lower()][0]
valid_recall=[value for key, value in model_history.items() if 'recall' in key.lower()][1]train_fpr=[value for key, value in model_history.items() if 'false_positive_rate' in key.lower()][0]
valid_fpr=[value for key, value in model_history.items() if 'false_positive_rate' in key.lower()][1]fig, ax1 = plt.subplots()color = 'tab:red'
ax1.set_xlabel('Epoch')
ax1.set_ylabel('Recall', color=color)
ax1.set_ylim([-0.05,1.05])
ax1.plot(train_recall, '--', color=color, label='Train Recall')
ax1.plot(valid_recall, color=color, label='Valid Recall')
ax1.tick_params(axis='y', labelcolor=color)
plt.legend(loc='upper left')
plt.title('Model Recall and FPR')ax2 = ax1.twinx() # instantiate a second axes that shares the same x-axiscolor = 'tab:blue'
ax2.set_ylabel('False Positive Rate', color=color) # we already handled the x-label with ax1
ax2.plot(train_fpr, '--', color=color, label='Train FPR')
ax2.plot(valid_fpr, color=color, label='Valid FPR')
ax2.tick_params(axis='y', labelcolor=color)
ax2.set_ylim([-0.05,1.05])fig.tight_layout() # otherwise the right y-label is slightly clipped
plt.legend(loc='upper right')
plt.show()


模型1.參照算法


n_features = x_train_scaled.shape[1]
mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dense(1, activation='sigmoid'))
mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid_scaled, y_valid),
verbose=0).history


觀察模型擬合損失和準確度(召回率和假陽率)變化


plot_loss(history)

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

plot_model_recall_fpr(history)

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

模型2.類權重


參照上文提到的經驗法則決定類權重。


class_weight = {0: sum(y_train == 1)/len(y_train), 1: sum(y_train == 0)/len(y_train)}


開始訓練模型。


n_features = x_train_scaled.shape[1]mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dense(1, activation='sigmoid'))mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid_scaled, y_valid),
class_weight=class_weight,
verbose=0).historyplot_loss(history)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


plot_model_recall_fpr(history)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

模型3. Dropout正則化


n_features = x_train_scaled.shape[1]mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dropout(0.5))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dropout(0.5))
mlp.add(Dense(1, activation='sigmoid'))mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid_scaled, y_valid),
class_weight=class_weight,
verbose=0).historyplot_loss(history)
代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

plot_model_recall_fpr(history)

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

模型4. 過採樣-欠採樣


使用SMOTE重採樣。


from imblearn.over_sampling import SMOTE
smote = SMOTE(random_state=212)
x_train_scaled_resampled, y_train_resampled = smote.fit_resample(x_train_scaled, y_train)
print('Resampled dataset shape %s' % Counter(y_train_resampled))


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

n_features = x_train_scaled.shape[1]mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, activation='relu'))
mlp.add(Dropout(0.5))
mlp.add(Dense(16, activation='relu'))
mlp.add(Dropout(0.5))
mlp.add(Dense(1, activation='sigmoid'))mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled_resampled,
y=y_train_resampled,
batch_size=128,
epochs=100,
validation_data=(x_valid, y_valid),
class_weight=class_weight,
verbose=0).historyplot_loss(history)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

plot_model_recall_fpr(history)

代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

模型5. Selu激活


使用因其自規範化屬性而廣為人知的selu激活函數。


注意:


· 使用kernel_initializer=’lecun_normal’ 並AlphaDropout(0.1)

· 在AlphaDropout中使用0.1比率,AlphaDropout(0.1)


n_features = x_train_scaled.shape[1]mlp = Sequential()
mlp.add(Input(shape=(n_features, )))
mlp.add(Dense(32, kernel_initializer='lecun_normal', activation='selu'))
mlp.add(AlphaDropout(0.1))
mlp.add(Dense(16, kernel_initializer='lecun_normal', activation='selu'))
mlp.add(AlphaDropout(0.1))
mlp.add(Dense(1, activation='sigmoid'))mlp.summary()mlp.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', tf.keras.metrics.Recall(), FalsePositiveRate()]
)history = mlp.fit(x=x_train_scaled,
y=y_train,
batch_size=128,
epochs=100,
validation_data=(x_valid, y_valid),
class_weight=class_weight,
verbose=0).historyplot_loss(history)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


plot_model_recall_fpr(history)


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則

結論


· 儘管深度學習提供了預測模型能力, 在尋找出發點的時候也可能會無所適從。

· 文中的經驗法則提供了構建初始神經網絡的出發點。

· 在此基礎上構建的模型應進行進一步調整,以提高性能。

· 如果使用這些經驗法則構建的模型性能沒有任何可取之處,進一步調整可能不會帶來太大的改進,這時就應嘗試使用其他的方法。

· 本文介紹了在TensorFlow 2中實現神經網絡的步驟。

· 如果沒有TensorFlow 2,建議開始使用它。Tensorflow2不僅具有Keras所具有的簡易性,同時還具備高性能的特點。


Tensorflow2安裝指南:https://towardsdatascience.com/step-by-step-guide-to-install-tensorflow-2-0-67bc73e79b82?source=post_page---------------------------


代碼詳解:以多層感知器為例,教你構建神經網絡的經驗法則


留言 點贊 發個朋友圈

我們一起分享AI學習與發展的乾貨

編譯組:段昌蓉、蔣馨怡

相關鏈接:

https://towardsdatascience.com/17-rules-of-thumb-for-building-a-neural-network-93356f9930af

如需轉載,請後臺留言,遵守轉載規範

"

相關推薦

推薦中...