<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                # 五、使用 Keras 解決多分類問題 在本章中,我們將使用 Keras 和 TensorFlow 來處理具有許多自變量的 10 類多分類問題。 和以前一樣,我們將討論使用深度學習解決此問題的利弊; 但是,您不會發現很多缺點。 最后,我們將花費大量時間討論控制過擬合的方法。 我們將在本章介紹以下主題: * 多分類和深度神經網絡 * 案例研究 – 手寫數字分類 * 在 Keras 中建立多分類器 * 通過丟棄控制方差 * 通過正則化控制方差 # 多分類和深度神經網絡 這里是! 我們終于找到了有趣的東西! 在本章中,我們將創建一個深度神經網絡,該網絡可以將觀察結果分類為多個類別,這是神經網絡確實發揮出色的地方之一。 讓我們再談一些關于深度神經網絡對此類問題的好處。 就像我們都在談論同一件事一樣,讓我們??在開始之前定義多分類。 想象我們有一個分類器,該分類器將各種水果的權重作為輸入,并根據給定的權重來預測水果。 輸出可能恰好是一組類(蘋果,香蕉,芒果等)中的一個類。 這是多分類,不要與多標簽混淆,在這種情況下,模型可能會預測一組標簽是否將應用于互不排斥的觀察結果。 # 優點 當我們需要預測大量類時,相對于其他模型,深度神經網絡的確是出色的執行者。 當輸入向量中的特征數量變大時,神經網絡自然適合。 當這兩種情況都集中在同一個問題上時,我可能就是從那里開始的。 這正是我們將在本章中要研究的案例研究中看到的問題的類型。 # 缺點 和以前一樣,更簡單的模型可能會比深度學習模型做的更好或更好。 在所有其他條件都相同的情況下,您可能應該支持更簡單的模型。 但是,隨著類數的增加,深度神經網絡復雜性的弊端通常會減少。 為了容納許多類,許多其他模型的實現必須變得非常復雜,有些模型甚至可能需要優化作為超參數用于模型的多類策略。 # 案例研究 - 手寫數字分類 我們將使用多分類網絡來識別手寫數字的相應類。 與以前一樣,如果您想繼續閱讀,可以在本書的 Git 存儲庫中的`Chapter05`下找到本章的完整代碼。 # 問題定義 `MNIST`數據集已成為幾乎規范的神經網絡數據集。 該數據集由 60,000 個手寫數字組成的圖像,屬于代表它們各自數字`(0, 1, 2 ... 9)`的 10 類。 由于此數據集變得如此普遍,因此許多深度學習框架都在 API 中內置了 MNIST 加載方法。 TensorFlow 和 Keras 都擁有一個,我們將使用 Keras MNIST 加載器使我們的生活更輕松。 但是,如果您想從原始數據中獲取數據,或者想進一步了解 MNIST 的歷史,可以在[這個頁面](http://yann.lecun.com/exdb/mnist/)中找到更多信息。 # 模型輸入和輸出 我們的數據集已被劃分為一個訓練集,該訓練集的大小為 50,000 個觀察值,一個測試集為 10,000 個觀察值。 我將從訓練集中獲取最后 5,000 個觀察值,并將其用作驗證集。 # 拼合輸入 每個輸入觀察都是一個 28 像素乘 28 像素的黑白圖像。 像這樣的一幅圖像在磁盤上表示為`28x28`的矩陣,其值介于 0 到 255 之間,其中每個值都是該像素中黑色的強度。 至此,我們只知道如何在二維向量上訓練網絡(稍后我們將學習一種更好的方法); 因此我們將這個`28x28`矩陣展平為`1 x 784`輸入向量。 一旦我們堆疊了所有這些`1x784`向量,就剩下`50,000 x 784`訓練集。 如果您對卷積神經網絡有豐富的經驗,那么您可能現在正在翻白眼,如果您還沒有,那么很快就會有更好的方法,但是不要太快地跳過本章。 我認為扁平化的`MNIST`是一個非常好的數據集,因為它的外觀和行為與我們在許多投入領域(例如,物聯網,制造業,生物,制藥和醫療用例)中遇到的許多復雜的現實生活問題非常相似)。 # 類別輸出 我們的輸出層將為每個類包含一個神經元。 每個類別的關聯神經元將經過訓練,以將該類別的概率預測為介于 0 和 1 之間的值。我們將使用一種稱為 **softmax** 的特殊激活,以確保所有這些輸出總和為 1,我們將介紹 softmax 的詳細信息。 這意味著我們將需要為我們的類創建一個二元/分類編碼。 例如,如果我們使`y = [0, 3, 2, 1]`并對其進行分類編碼,則將具有如下矩陣`y`: ![](https://img.kancloud.cn/05/dd/05dd3b103b0a22a302b935266ee6a06c_1580x990.png) 幸運的是,Keras 為我們提供了方便的功能來進行這種轉換。 # 成本函數 我們將使用的成本函數稱為**多項式交叉熵**。 多項式交叉熵實際上只是在第 4 章“使用 Keras 進行二分類”中看到的二元交叉熵函數的概括。 讓我們一起看看它們,而不只是顯示分類交叉熵。 我要斷言它們是平等的,然后解釋原因: ![](https://img.kancloud.cn/7f/06/7f06327a6d4ecb226e8e21181ab43b56_5880x570.png) 前面的等式是正確的(`m = 2`時) 好吧,別害怕。 我知道,這是一堆數學。 絕對交叉熵方程是一直存在于右邊的方程。 二元交叉熵緊隨其后。 現在,設想`m = 2`的情況。 在這種情況下,您可能會發現,`j = 0`和`j = 1`的`y[ij]log(p[ij])`的和,對于`i`中的每個值,等于來自二元交叉熵的結果。 希望這種減少足以使分類交叉熵有意義。 如果沒有,我建議選擇一些值并進行編碼。 只需一秒鐘,稍后您將感謝我! # 指標 分類交叉熵是一個很好的成本函數,但實際上并不能告訴我們很多我們可以從網絡中獲得的預測質量。 不幸的是,像 ROC AUC 這樣的二分類指標也對我們沒有太大幫助,因為我們超越了二分類 AUC 的定義并沒有。 鑒于缺少更好的指標,我將使用準確率作為人類可以理解的訓練指標。 幸運的是,在這種情況下,我的數據集是平衡的。 正如您所期望的那樣,準確率是指真實值與預測值的匹配次數除以數據集的總大小。 訓練結束后,我將使用 scikit-learn 的分類報告向我們顯示每個類的精確度和召回率。 如果您愿意,也可以為此使用混淆矩陣。 # 在 Keras 中建立多分類器 由于我們現在有一個定義明確的問題,因此可以開始對其進行編碼。 如前所述,這次我們必須對輸入和輸出進行一些轉換。 在我們建立網絡的過程中,我將向您展示這些內容。 # 載入 MNIST 對我們來說幸運的是,在 Keras 中內置了一個 MNIST 加載函數,該函數可以檢索 MNIST 數據并為我們加載。 我們需要做的就是導入`keras.datasets.mnist`并使用`load_data()`方法,如以下代碼所示: ```py (train_X, train_y), (test_X, test_y) = mnist.load_data() ``` `train_X`的形狀為`50,000 x 28 x 28`。正如我們在“模型輸入和輸出”部分中所述,我們將需要將`28x28`矩陣展平為 784 個元素向量。 NumPy 使這變得非常容易。 以下代碼說明了此技術: ```py train_X = train_X.reshape(-1, 784) ``` 有了這種方式,我們應該考慮擴展輸入。 以前,我們使用 scikit-learn 的`StandardScaler`。 MNIST 不需要這樣做。 由于我們知道每個像素都在 0 到 255 的相同范圍內,因此我們可以通過除以`255`輕松地將值轉換為 0 和 1 之間的值,然后在執行操作之前將數據類型顯式轉換為`float32`,如以下代碼所示: ```py train_X = train_X.astype('float32') train_X /= 255 ``` 正如我們在“模型輸入和輸出”部分中所述,在加載數據時,我們可能應該將因變量向量轉換為分類向量。 為此,我們將在以下代碼的幫助下使用`keras.utils.to_categorical()`: ```py train_y = to_categorical(train_y) ``` 這樣,我們的數據就可以進行訓練了! # 輸入層 我們的輸入層實際上與之前的示例保持不變,但我將在此處包括它以使其成為適當的快速參考: ```py def build_network(input_features=None): inputs = Input(shape=(input_features,), name="input") ``` # 隱藏層 我將使用帶有`512`神經元的第一個隱藏層。 這比輸入向量的 784 個元素略小,但這完全不是規則。 同樣,此架構只是一個開始,并不一定是最好的。 然后,我將在第二和第三隱藏層中瀏覽大小,如以下代碼所示: ```py x = Dense(512, activation='relu', name="hidden1")(inputs) x = Dense(256, activation='relu', name="hidden2")(x) x = Dense(128, activation='relu', name="hidden3")(x) ``` # 輸出層 我們的輸出層將包含 10 個神經元,一個觀察值可能屬于其中的每個可能的類。 這對應于我們在`y`向量上使用`to_categorical()`時施加的編碼: ```py prediction = Dense(10, activation='softmax', name="output")(x) ``` 如您所見,我們正在使用的激活稱為 **softmax**。 讓我們討論一下`softmax`是什么,以及為什么有用。 # Softmax 激活 想象一下,如果不是使用深層神經網絡,而是使用`k`個邏輯回歸,其中每個回歸都預測單個類中的成員。 邏輯回歸的集合(每個類一個)如下所示: ![](https://img.kancloud.cn/81/13/81138efe71e5211dd04f78f48f6d2310_3150x1030.png) 使用這組邏輯回歸的問題是每個邏輯回歸的輸出都是獨立的。 想象一下,在我們的集合中,這些邏輯回歸中的一些不確定其所屬類別的成員資格,從而導致多個答案在`P(Y = k) = 0.5`附近。 這使我們無法將這些輸出用作`k`類中類成員資格的總體概率,因為它們不一定總和為 1。 Softmax 壓縮所有這些邏輯回歸的輸出,使它們的總和為 1,從而將其用作整體類成員的概率,從而為我們提供了幫助。 `softmax`函數如下所示: ![](https://img.kancloud.cn/a9/21/a9211f66c33ad81102187198bb5700ca_1440x500.png) (對于`j = 1`至`k`類,其中`zj / zk`是屬于`k`的邏輯回歸) 因此,如果將`softmax`函數放在我們先前的回歸集的前面,我們將得到一組類別概率,它們合計為 1,可以用作 k 個類別中成員資格的概率。 這改變了我們的整體函數,如下所示: ![](https://img.kancloud.cn/12/ec/12ecd4a0c35ca2d5868fe65cf2e350d0_4320x1030.png) 先前的函數通常稱為多項式邏輯回歸。 它有點像一層,僅輸出和神經網絡。 我們不再頻繁使用多項式邏輯回歸。 但是,我們當然可以一直使用`softmax`函數。 對于本書中的大多數多分類問題,我們將使用`softmax`,因此值得理解。 如果您像我一樣,并且發現所有數學知識都難以閱讀,那么在代碼中查看`softmax`可能會更容易。 因此,在繼續操作之前,請使用以下代碼段進行操作: ```py def softmax(z): z_exp = [math.exp(x) for x in z] sum_z_exp = sum(z_exp) softmax = [round(i / sum_z_exp, 3) for i in z_exp] return softmax ``` 讓我們快速嘗試一個例子。 想象一下,我們有一組邏輯輸出,如下所示: ```py z = np.array([0.9, 0.8, 0.2, 0.1, 0.5]) ``` 如果應用`softmax`,我們可以輕松地將這些輸出轉換為相對的類概率,如下所示: ```py print(softmax(z)) [0.284, 0.257, 0.141, 0.128, 0.19] ``` # 放在一起 現在我們已經涵蓋了各個部分,讓我們看一下我們的整個網絡。 這看起來與我們之前在本書中介紹的模型相似。 但是,我們使用的損失函數`categorical_crossentropy`在本章的“成本函數”部分中介紹了。 我們將使用以下代碼定義網絡: ```py def build_network(input_features=None): # first we specify an input layer, with a shape == features inputs = Input(shape=(input_features,), name="input") x = Dense(512, activation='relu', name="hidden1")(inputs) x = Dense(256, activation='relu', name="hidden2")(x) x = Dense(128, activation='relu', name="hidden3")(x) prediction = Dense(10, activation='softmax', name="output")(x) model = Model(inputs=inputs, outputs=prediction) model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=["accuracy"]) return model ``` # 訓練 現在我們已經定義了神經網絡并加載了數據,剩下的就是訓練它了。 在本書中以及本書的其他幾個示例中,我使用的是稱為數據的字典,以繞過`train_X`,`val_X`和`test_X`等各種數據集。 我使用這種表示法來保持代碼的可讀性,并且因為傳遞整個字典的必要性經常高于沒有。 這是我將如何訓練我們剛剛建立的模型的方法。 ```py model = build_network(data["train_X"].shape[1]) model.fit(x=data["train_X"], y=data["train_y"], batch_size=30, epochs=50, validation_data=(data["val_X"], data["val_y"]), verbose=1, callbacks=callbacks) ``` 我正在使用與以前相同的回調。 我沒有使用我們在第 4 章“使用 Keras 進行二分類”中構建的 ROC AUC 回調,因為 ROC AUC 沒有為多分類器明確定義。 存在一些針對該問題的創造性解決方案。 例如,[**通過成對分析近似多類 ROC**](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.108.3250&rep=rep1&type=pdf) 和 [**ROC 表面下體積**](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.14.2427&rep=rep1&type=pdf)都是出色的論文,都可以解決這個問題。 但是,實際上,這些方法及其度量標準很少在 R 中使用,最常在 R 中實現。因此,到目前為止,讓我們堅持使用多類準確率,并且遠離 R。 讓我們觀看 TensorBoard 在我們的模型訓練中: ![](https://img.kancloud.cn/f4/5e/f45e4b4cd78fdd1c0e878f5c8e86f3a0_333x597.png) 在閱讀下一段之前,請花點時間思考一下這些圖形在告訴我們什么。 得到它了? 好的,讓我們繼續。 因此,這是一個熟悉的情況。 我們的訓練損失正在繼續下降,而我們的驗證損失正在上升。 我們過擬合。 雖然當然可以選擇提前停止,但讓我向您展示一些處理過擬合的新技巧。 讓我們在下一部分中查看丟棄法和 l2 正則化。 但是,在進行此操作之前,我們應該研究如何使用多類網絡來測量準確率和進行預測。 # 在多類模型中使用 scikit-learn 指標 和以前一樣,我們可以借鑒 scikit-learn 的指標來衡量我們的模型。 但是,為此,我們需要從模型的`y`的分類輸出中進行一些簡單的轉換,因為 scikit-learn 需要使用類標簽,而不是二元類指示器。 為了取得飛躍,我們將使用以下代碼開始進行預測: ```py y_softmax = model.predict(data["test_X"]) ``` 然后,我們將選擇概率最大的類的索引,使用以下代碼將其方便地作為該類: ```py y_hat = y_softmax.argmax(axis=-1) ``` 然后,我們可以像以前一樣使用 scikit-learn 的分類報告。 相同的代碼如下: ```py from sklearn.metrics import classification_report print(classification_report(test_y, y_hat)) ``` 現在,我們實際上可以查看所有 10 個類的精度,召回率和 f1 得分。 下圖說明了`sklearn.metrics.classification_report()`的輸出: ![](https://img.kancloud.cn/cb/46/cb464c93eebf4016fe970ff0500adaa3_498x293.png) # 通過丟棄控制方差 減少深度神經網絡過擬合的一種非常好的方法是采用一種稱為**丟棄法**的技術。 丟棄法完全按照其說的去做,它使神經元脫離隱藏層。 運作方式如下。 通過每個小批量,我們將隨機選擇關閉每個隱藏層中的節點。 想象一下,我們在某個隱藏層中實現了丟棄,并且我們選擇了丟棄率為 0.5。 這意味著,對于每個小批量,對于每個神經元,我們都擲硬幣以查看是否使用該神經元。 這樣,您可能會隨機關閉該隱藏層中大約一半的神經元: ![](https://img.kancloud.cn/f9/4e/f94ea2b8d25d2d7ad7352e2389f2e36a_1272x1463.png) 如果我們一遍又一遍地執行此操作,就好像我們正在訓練許多較小的網絡。 模型權重保持相對較小,每個較小的網絡不太可能過擬合數據。 這也迫使每個神經元減少對其他神經元的依賴。 丟棄法效果驚人,可以很好地解決您可能遇到的許多(如果不是大多數)深度學習問題的過擬合問題。 如果您具有高方差模型,則丟棄是減少過擬合的好選擇。 Keras 包含一個內置的`Dropout`層,我們可以輕松地在網絡中使用它來實現`Dropout`。 `Dropout`層將簡單地隨機關閉前一層神經元的輸出,以使我們輕松地改造網絡以使用`Dropout`。 要使用它,除了我們正在使用的其他層類型之外,我們還需要首先導入新層,如以下代碼所示: ```py from keras.layers import Input, Dense, Dropout ``` 然后,我們只需將`Dropout`層插入模型,如以下代碼所示: ```py def build_network(input_features=None): # first we specify an input layer, with a shape == features inputs = Input(shape=(input_features,), name="input") x = Dense(512, activation='relu', name="hidden1")(inputs) x = Dropout(0.5)(x) x = Dense(256, activation='relu', name="hidden2")(x) x = Dropout(0.5)(x) x = Dense(128, activation='relu', name="hidden3")(x) x = Dropout(0.5)(x) prediction = Dense(10, activation='softmax', name="output")(x) model = Model(inputs=inputs, outputs=prediction) model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=["accuracy"]) return model ``` 這是我們先前使用的確切模型; 但是,我們在每個`Dense`層之后都插入了`Dropout`層,這是我通常在實現丟棄時開始的方式。 像其他模型架構決策一樣,您可以選擇僅在某些層,所有層或沒有層中實現丟棄。 您還可以選擇更改退出/保留概率; 但是,我確實建議從 0.5 開始,因為它通常效果很好。 一個安全的選擇是在每一層都退出,保持概率為 0.5。 不錯的第二種嘗試是僅在第一層使用丟棄。 讓我們用丟棄法訓練我們的新模型,看看它與我們的第一次嘗試相比如何: ![](https://img.kancloud.cn/24/0f/240f3ffd389c14d0d77964cd1acf3ed6_340x555.png) 首先讓我們看一下驗證準確率。 使用丟棄模型的訓練速度與未規范模型的訓練速度一樣快,但是在這種情況下,它的確似乎很快就開始加速。 看看在第 44 個周期的驗證準確率。它比非正規模型略好。 現在,讓我們看看驗證損失。 您可以看到丟棄法對模型過擬合的影響,而且確實非常明顯。 雖然僅轉換為最終產品的少量改進,但丟棄法表現相當不錯,可以防止我們的驗證損失提升。 # 通過正則化控制方差 **正則化**是控制過擬合的另一種方法,當模型中的各個權重增大時會對其進行懲罰。 如果您熟悉線性模型(例如線性和邏輯回歸),那么它與在神經元級別應用的技術完全相同。 可以使用兩種形式的正則化,稱為 L1 和 L2,來對神經網絡進行正則化。 但是,由于 L2 正則化計算效率更高,因此幾乎總是在神經網絡中使用它。 快速地,我們需要首先規范化成本函數。 如果我們將`C[0]`,分類交叉熵作為原始成本函數,則正規化的`cost`函數將如下所示: ![](https://img.kancloud.cn/e8/dd/e8ddc2fb6edc9fa65d42a5a7bc8b67e4_1650x500.png) 這里,`λ`是可以增加或減少以更改應用的正則化量的正則化參數。 此正則化參數會懲罰較大的權重值,從而使網絡總體上希望具有較小的權重。 要更深入地了解神經網絡中的正則化,請查看 Michael Nielsen 的[《神經網絡和深度學習》的第 3 章](http://neuralnetworksanddeeplearning.com/chap3.html)。 可以將正則化應用于 Keras 層中的權重,偏差和激活。 我將使用帶有默認參數的 L2 演示此技術。 在以下示例中,我將正則化應用于每個隱藏層: ```py def build_network(input_features=None): # first we specify an input layer, with a shape == features inputs = Input(shape=(input_features,), name="input") x = Dense(512, activation='relu', name="hidden1", kernel_regularizer='l2') \ (inputs) x = Dense(256, activation='relu', name="hidden2", kernel_regularizer='l2')(x) x = Dense(128, activation='relu', name="hidden3", kernel_regularizer='l2')(x) prediction = Dense(10, activation='softmax', name="output")(x) model = Model(inputs=inputs, outputs=prediction) model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=["accuracy"]) return model ``` 因此,讓我們將默認的 L2 正則化與其他兩個模型進行比較。 下圖顯示了比較: ![](https://img.kancloud.cn/e2/34/e234b6e20b50c7cf2236e3c9f490d463_349x559.png) 不幸的是,我們的新 L2 正則化網絡很容易找到。 在這種情況下,似乎 L2 正則化效果很好。 我們的網絡現在偏差嚴重,對其他兩個方面的了解還不夠。 如果我真的確定要使用正則化來解決此問題,那么我將首先更改正則化率并嘗試找到更合適的值,但我們相距甚遠,我對此表示懷疑,我們會做得比我們更好 `dropout`模型。 # 總結 在本章中,我們實際上已經開始了解深度神經網絡在進行多分類時的威力。 我們詳細介紹了`softmax`函數,然后我們構建并訓練了一個網絡來將手寫數字分為 10 個各自的類別。 最后,當我們注意到模型過擬合時,我們嘗試同時使用丟棄和 L2 正則化來減少模型的方差。 到目前為止,您已經看到深度神經網絡需要很多選擇,關于架構的選擇,學習率,甚至是正則化率。 我們將在下一章中學習如何優化這些選擇。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看