<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>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 四、使用深度學習解決二分類問題 在本章中,我們將使用 Keras 和 TensorFlow 解決棘手的二分類問題。 我們將首先討論深度學習對此類問題的利弊,然后我們將繼續使用與第 2 章“學習解決回歸問題”中使用的相同框架建立解決方案。 最后,我們將更深入地介紹 Keras 回調,甚至使用自定義回調來實現每個周期的**受試者工作特征的曲線下面積**(**ROC AUC**)指標。 我們將在本章介紹以下主題: * 二分類和深度神經網絡 * 案例研究 – 癲癇發作識別 * 在 Keras 中建立二分類器 * 在 Keras 中使用檢查點回調 * 在自定義回調中測量 ROC AUC * 測量精度,召回率和 f1 得分 # 二分類和深度神經網絡 二分類問題(例如回歸問題)是非常常見的機器學習任務。 如此之多,以至于任何一本有關深度學習的書都無法完整覆蓋。 可以肯定的是,我們還沒有真正達到深度神經網絡的甜蜜點,但是我們進展順利。 在開始編寫代碼之前,讓我們談談在選擇深度神經網絡來解決此類問題時應考慮的權衡。 # 深度神經網絡的好處 與更傳統的分類器(例如邏輯回歸模型)或什至基于樹的模型(例如**隨機森林**或**梯度提升機**)相比,深度神經網絡有一些不錯的優點。 與回歸一樣,在第 2 章“使用深度學習解決回歸問題”中,我們不需要選擇或篩選特征。 在本章選擇的問題中,有 178 個輸入變量。 每個輸入變量都是來自標記為`x1..x178`的**腦電圖**(**EEG**)的特定輸入。 即使您是醫生,也很難理解這么多特征與目標變量之間的關系。 這些特征中的某些特征很可能是不相關的,而這些變量和目標之間可能存在一些更高級別的交互,這是一個更好的機會。 如果使用傳統模型,則經過特征選擇步驟后,我們將獲得最佳模型表現。 使用深度神經網絡時不需要這樣做。 # 深度神經網絡的缺點 正如我們在第 2 章“使用深度學習解決回歸問題”所述,深度神經網絡不容易解釋。 雖然深度神經網絡是出色的預測器,但要理解它們為何得出自己的預測并不容易。 需要重復的是,當任務是要了解哪些特征與目標的變化最相關時,深度神經網絡并不是工作的工具。 但是,如果目標是原始預測能力,則應考慮使用深度神經網絡。 我們還應該考慮復雜性。 深度神經網絡是具有許多參數的復雜模型。 找到最佳的神經網絡可能需要花費時間和實驗。 并非所有問題都能確保達到如此復雜的水平。 在現實生活中,我很少使用深度學習作為結構化數據問題的第一個解決方案。 我將從可能可行的最簡單模型開始,然后根據問題的需要迭代進行深度學習。 當問題域包含圖像,音頻或文本時,我更有可能從深度學習開始。 # 案例研究 – 癲癇發作識別 您可能已經猜到了,我們將要解決二分類問題。 我們將使用與在第 2 章“使用深度學習解決回歸問題”建立的框架相同的框架來計劃問題,并根據需要對其進行修改。 您可以在本書的 GitHub 存儲庫中的第 4 章“使用深度學習解決回歸問題”,找到本章的完整代碼。 # 定義我們的數據集 我們將在本章中使用的數據集稱為**癲癇發作識別**數據集。 數據最初來自Andrzejak RG 等人在 Phys 上發表的論文《指示腦電活動的時間序列中的非線性確定性和有限維結構:對記錄區域和大腦狀態的依賴性》。您可以在 [UCI 機器學習存儲庫](http://archive.ics.uci.edu/ml/datasets/Epileptic+Seizure+Recognition)中找到數據。 我們的目標是創建一個深度神經網絡,根據輸入特征,該網絡可以預測患者是否有癲癇發作。 # 加載數據 我們可以使用以下函數加載本章中使用的數據。 它與我們在第 2 章中使用的函數非常相似,但是適用于此數據集。 ```py from sklearn.preprocessing import StandardScaler def load_data(): """Loads train, val, and test datasets from disk""" train = pd.read_csv(TRAIN_DATA) val = pd.read_csv(VAL_DATA) test = pd.read_csv(TEST_DATA) # we will use a dict to keep all this data tidy. data = dict() data["train_y"] = train.pop('y') data["val_y"] = val.pop('y') data["test_y"] = test.pop('y') # we will use sklearn's StandardScaler to scale our data to 0 mean, unit variance. scaler = StandardScaler() train = scaler.fit_transform(train) val = scaler.transform(val) test = scaler.transform(test) data["train_X"] = train data["val_X"] = val data["test_X"] = test # it's a good idea to keep the scaler (or at least the mean/variance) so we can unscale predictions data["scaler"] = scaler return data ``` # 模型輸入和輸出 該數據集中有 11,500 行。 數據集的每一行包含 178 個數據點,每個數據點代表 1 秒鐘的 EEG 記錄樣本和相應的患者狀態,跨 100 個不同患者生成。 數據集中有五個患者狀態。 但是,狀態 2 至狀態 5 的患者未發生癲癇發作。 狀態 1 的患者正在發作。 我已經修改了原始數據集,通過將狀態 2-5 更改為 0 級(表示無癲癇發作)和將 1 級(表示有癲癇發作)將狀態重新定義為二分類問題。 與第 2 章“使用深度學習解決回歸問題”中的回歸問題一樣,我們將使用 80% 的訓練,10% 的 val,10% 的測試分割。 # 成本函數 我們需要分類器來預測癲癇發作的可能性,即類別 1。這意味著我們的輸出將被限制為`[0, 1]`,就像在傳統的邏輯回歸模型中一樣。 在這種情況下,我們的成本函數將是二元交叉熵,也稱為**對數損失**。 如果您以前使用過分類器,那么您可能很熟悉此數學運算; 但是,作為復習,我將在這里包括。 對數損失的完整公式如下所示: ![](https://img.kancloud.cn/a4/47/a4476ea0bdbda47264ca39c9f8bd2c08_3740x540.png) 這可能更簡單地看作是兩個函數的集合,對于情況`y[i] = 0`和`y[i] = 1`,一個函數: ![](https://img.kancloud.cn/ab/95/ab9538720f2deb344ec04c3e0f226d27_1870x540.png) 當`y[i] = 1`, ![](https://img.kancloud.cn/c4/44/c444eab3aa3fa26b045004db47461dd7_2180x540.png) 當`y[i] = 0`。 對數函數在這里用于產生單調函數(一個一直在增加或減少的函數),我們可以輕松微分它。 與所有成本函數一樣,我們將調整網絡參數以最小化網絡成本。 # 使用指標評估表現 除了`loss`函數之外,Keras 還使我們可以使用度量標準來幫助判斷模型的表現。 雖然最大程度地降低損失是有好處的,但在給定`loss`函數的情況下,我們如何期望模型執行效果并不是特別明顯。 度量標準并不用于訓練模型,它們只是用來幫助我們了解當前狀態。 盡管損失對我們而言并不重要,但準確率卻對我們而言意義重大。 我們人類非常了解準確率。 Keras 定義二元精度如下: ```py def binary_accuracy(y_true, y_pred): return K.mean(K.equal(y_true, K.round(y_pred)), axis=-1) ``` 這實際上只是將正確答案的數量除以總答案的一種聰明方法,這是我們自從上學初期就可能一直在做的一項工作,目的是計算出考試的成績。 您可能想知道我們的數據集是否平衡,因為準確率對于不平衡的數據集而言效果很差。 實際上這是不平衡的。 只有五分之一的數據集是類 1。我們將 ROC AUC 分數作為自定義回調來計算,以解決此問題。 在 Keras 中未將 ROC 用作度量標準,因為度量標準是針對每個小型批次計算的,并且 ROC AUC 分數并非真正由小型批次定義。 # 在 Keras 中建立二分類器 既然我們已經定義了問題,輸入,期望的輸出和成本函數,我們就可以在 Keras 中快速編寫其余代碼。 我們唯一缺少的是網絡架構。 我們將很快討論更多。 關于 Keras 的我最喜歡的事情之一是調整網絡架構有多么容易。 如您所見,在找到最佳架構之前,可能需要進行大量實驗。 如果是這樣,那么易于更改的框架會使您的工作變得更加輕松! # 輸入層 和以前一樣,我們的輸入層需要知道數據集的維度。 我喜歡在一個函數中構建整個 Keras 模型,并允許該函數傳遞回已編譯的模型。 現在,此函數僅接受一個參數,即特征數。 以下代碼用于定義輸入層: ```py def build_network(input_features=None): # first we specify an input layer, with a shape == features inputs = Input(shape=(input_features,), name="input") ``` # 隱藏層 我們已經定義了輸入,這很容易。 現在我們需要確定網絡架構。 我們如何知道應該包括多少層以及應該包含多少個神經元? 我想給你一個公式。 我真的會。 不幸的是,它不存在。 實際上,有些人正在嘗試構建可以學習其他神經網絡的最佳架構的神經網絡。 對于我們其余的人,我們將不得不嘗試,尋找自己或借用別人的架構。 # 如果我們使用的神經元過多會怎樣? 如果我們使網絡架構過于復雜,則會發生兩件事: * 我們可能會開發一個高方差模型 * 該模型將比不太復雜的模型訓練得慢 如果我們增加許多層,我們的梯度將變得越來越小,直到前幾層幾乎沒有訓練為止,這就是**梯度消失問題**。 我們離那還很遙遠,但是我們稍后會討論。 用說唱傳奇克里斯托弗·華萊士(又名臭名昭著的 B.I.G.)的話來說,我們遇到的神經元越多,看到的問題就越多。 話雖如此,方差可以通過丟棄法,正則化和提早停止進行管理,GPU 計算的進步使更深層次的網絡成為可能。 如果我必須在神經元太多或太少的網絡之間進行選擇,而我只能嘗試一個實驗,那么我寧愿選擇稍微過多的神經元。 # 如果我們使用的神經元太少會怎樣? 想象一下,我們沒有隱藏層,只有輸入和輸出的情況。 我們在第 1 章“深度學習的基礎知識”中討論了該架構,在此我們展示了如何無法為`XOR`函數建模。 這樣的網絡架構無法對數據中的任何非線性進行建模,因此無法通過網絡進行建模。 每個隱藏層都為特征工程越來越復雜的交互提供了機會。 如果選擇的神經元太少,則結果可能如下: * 真正快速的神經網絡 * 那有很高的偏差,而且預測不是很好 # 選擇隱藏層架構 因此,既然我們了解選擇太多參數而不是選擇太多參數的價格和行為,那么從哪里開始呢? 據我所知,剩下的只是實驗。 測量這些實驗可能很棘手。 如果像我們的早期網絡一樣,您的網絡訓練很快,那么可以在多種架構中實現諸如交叉驗證之類的東西,以評估每種架構的多次運行。 如果您的網絡需要很長時間進行訓練,則可能會留下一些統計上不太復雜的信息。 我們將在第 6 章“超參數優化”中介紹網絡優化。 一些書籍提供了選擇神經網絡架構的經驗法則。 我對此表示懷疑和懷疑,您當然不會在這里找到一個。 # 為我們的示例編碼隱藏層 對于我們的示例問題,我將使用五個隱藏層,因為我認為特征之間存在許多交互。 我的直覺主要基于領域知識。 閱讀數據描述后,我知道這是時間序列的橫截面切片,并且可能是自動相關的。 我將從第一層的 128 個神經元開始(略小于我的輸入大小),然后在接近輸出時減半到 16 個神經元。 這完全不是憑經驗,它僅基于我自己的經驗。 我們將使用以下代碼定義隱藏層: ```py x = Dense(128, activation='relu', name="hidden1")(inputs) x = Dense(64, activation='relu', name="hidden2")(x) x = Dense(64, activation='relu', name="hidden3")(x) x = Dense(32, activation='relu', name="hidden4")(x) x = Dense(16, activation='relu', name="hidden5")(x) ``` 在每一層中,我都使用`relu`激活,因為它通常是最好和最安全的選擇,但是要確保這也是可以試驗的超參數。 # 輸出層 最后,我們需要網絡的輸出層。 我們將使用以下代碼定義輸出層: ```py prediction = Dense(1, activation='sigmoid', name="final")(x) ``` 在此示例中,我們正在構建一個二分類器,因此我們希望我們的網絡輸出觀察結果屬于類 1 的概率。幸運的是,`sigmoid`激活將精確地做到這一點,將網絡輸出限制在 0 到 1 之間。 # 放在一起 將所有代碼放在一起,剩下的就是編譯我們的 Keras 模型,將`binary_crossentrophy`指定為我們的`loss`函數,將`accuracy`指定為我們希望在訓練過程中監控的指標。 我們將使用以下代碼來編譯我們的 Keras 模型: ```py def build_network(input_features=None): inputs = Input(shape=(input_features,), name="input") x = Dense(128, activation='relu', name="hidden1")(inputs) x = Dense(64, activation='relu', name="hidden2")(x) x = Dense(64, activation='relu', name="hidden3")(x) x = Dense(32, activation='relu', name="hidden4")(x) x = Dense(16, activation='relu', name="hidden5")(x) prediction = Dense(1, activation='sigmoid', name="final")(x) model = Model(inputs=inputs, outputs=prediction) model.compile(optimizer='adam', loss='binary_crossentropy', metrics=["accuracy"]) return model ``` # 訓練我們的模型 現在我們已經定義了模型,我們都準備對其進行訓練。 我們的操作方法如下: ```py input_features = data["train_X"].shape[1] model = build_network(input_features=input_features) model.fit(x=data["train_X"], y=data["train_y"], batch_size=32, epochs=20, verbose=1, validation_data=(data["val_X"], data["val_y"]), callbacks=callbacks) ``` 如果您已經閱讀第 2 章“使用深度學習解決回歸問題”,則應該看起來很熟悉。 在大多數情況下,實際上是相同的。 回調列表包含 TensorBoard 回調,因此讓我們觀看我們的網絡訓練 20 個周期,看看會發生什么: ![](https://img.kancloud.cn/23/9b/239b0f6693515f541dd161ae4f72e7fc_339x656.png) 盡管我們的訓練損失繼續下降,但我們可以看到`val_loss`到處都在跳躍。 大約在第八個周期之后,我們就過擬合了。 有幾種方法可以減少網絡差異并管理這種過擬合,下一章將介紹大多數方法。 但是,在開始之前,我想向您展示一些有用的東西,稱為**檢查點回調**。 # 在 Keras 中使用檢查點回調 在第 2 章“使用深度學習解決回歸問題”中,我們看到了`.save()`方法,該方法使我們可以在完成訓練后保存 Keras 模型。 但是,如果我們可以不時地將權重寫入磁盤,以便在上一個示例中及時返回,并在模型開始過擬合之前保存其版本,那不好嗎? 然后,我們可以就此停止,并使用網絡的最低??方差版本。 這正是`ModelCheckpoint`回調為我們所做的。 讓我們來看看: ```py checkpoint_callback = ModelCheckpoint(filepath="./model-weights.{epoch:02d}-{val_acc:.6f}.hdf5", monitor='val_acc', verbose=1, save_best_only=True) ``` `ModelCheckpoint`將為我們執行的工作是按計劃的時間間隔保存模型。 在這里,我們告訴`ModelCheckpoint`每當我們達到新的最佳驗證精度(`val_acc`)時都要保存模型的副本。 我們也可以監視驗證損失或我們指定的任何其他指標。 文件名字符串將包含周期編號和運行的驗證準確率。 當我們再次訓練模型時,我們可以看到正在創建以下文件: ```py model-weights.00-0.971304.hdf5 model-weights.02-0.977391.hdf5 model-weights.05-0.985217.hdf5 ``` 因此,我們可以看到在第 5 個階段之后,我們無法達到`val_acc`的最佳水平,并且沒有編寫檢查點。 然后,我們可以返回并從檢查點 5 加載權重,并使用最佳模型。 這里有一些大的假設,將第 5 期稱為最佳。 您可能需要多次運行網絡,尤其是在您的數據集相對較小的情況下,就像本書中的早期示例一樣。 我們可以肯定地說,這個結果將是不穩定的。 順便說一下,這是防止過擬合的非常簡單的方法。 我們可以選擇使用方差太大之前發生的模型檢查點。 這是做類似提前停止的一種方法,這意味著當我們看到模型沒有改善時,我們會在指定的周期數之前停止訓練。 # 在自定義回調中測量 ROC AUC 讓我們再使用一個回調。 這次,我們將構建一個自定義的回調,以在每個周期結束時在訓練集和測試集上計算曲線下的接收器工作特征區域(ROC AUC)。 在 Keras 中創建自定義回調實際上非常簡單。 我們需要做的就是創建一個固有的`Callback`類,并覆蓋所需的方法。 由于我們想在每個周期結束時計算 ROC AUC 分數,因此我們將在`_epoch_end`上覆蓋: ```py from keras.callbacks import Callback class RocAUCScore(Callback): def __init__(self, training_data, validation_data): self.x = training_data[0] self.y = training_data[1] self.x_val = validation_data[0] self.y_val = validation_data[1] super(RocAUCScore, self).__init__() def on_epoch_end(self, epoch, logs={}): y_pred = self.model.predict(self.x) roc = roc_auc_score(self.y, y_pred) y_pred_val = self.model.predict(self.x_val) roc_val = roc_auc_score(self.y_val, y_pred_val) print('\n *** ROC AUC Score: %s - roc-auc_val: %s ***' % (str(roc), str(roc_val))) return ``` 現在,我們已經創建了新的自定義回調,我們可以將其添加到回調創建器函數中,如以下代碼所示: ```py def create_callbacks(data): tensorboard_callback = TensorBoard(log_dir=os.path.join(os.getcwd(), "tb_log", "5h_adam_20epochs"), histogram_freq=1, batch_size=32, write_graph=True, write_grads=False) roc_auc_callback = RocAUCScore(training_data=(data["train_X"], data["train_y"]), validation_data=(data["val_X"], data["val_y"])) checkpoint_callback = ModelCheckpoint(filepath="./model-weights. {epoch:02d}-{val_acc:.6f}.hdf5", monitor='val_acc',verbose=1, save_best_only=True) return [tensorboard_callback, roc_auc_callback, checkpoint_callback] ``` 這里的所有都是它的! 您可以用相同的方式實現其他任何指標。 # 測量精度,召回率和 f1 得分 正如您可能對其他二分類器有豐富的經驗一樣,我認為用幾句話討論如何創建與更傳統的二分類器一起使用的一些常規指標是明智的。 Keras 函數式 API 與 scikit-learn 中可能使用的 API 之間的區別是`.predict()`方法的行為。 當使用 Keras 時,對于`n`個樣本中的每個,`.predict()`將返回`k`類概率的`nxk`矩陣。 對于二分類器,將只有一列,即類別 1 的類別概率。這使 Keras `.predict()`更像 scikit-learn 中的`.predict_proba()`。 在計算精度,召回率或其他基于類的指標時,您需要通過選擇一些操作點來轉換`.predict()`輸出,如以下代碼所示: ```py def class_from_prob(x, operating_point=0.5): x[x >= operating_point] = 1 x[x < operating_point] = 0 return x ``` 完成此操作后,您可以隨意重用`sklearn.metric`中的典型指標,如以下代碼所示: ```py y_prob_val = model.predict(data["val_X"]) y_hat_val = class_from_prob(y_prob_val) print(classification_report(data["val_y"], y_hat_val)) ``` # 總結 在本章中,我們討論了使用深度神經網絡作為二分類器。 我們花了很多時間討論網絡架構的設計選擇,并提出了這樣的想法,即搜索和試驗是當前選擇架構的最佳方法。 我們學習了如何在 Keras 中使用檢查點回調來使我們能夠及時返回并找到具有所需表現特征的模型版本。 然后,我們在訓練的模型中創建并使用了自定義回調來衡量 ROC AUC 得分。 我們總結了如何將 Keras `.predict()`方法與`sklearn.metrics`中的傳統指標結合使用。 在下一章中,我們將研究多分類,我們將更多地討論如何防止過擬合。
                  <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>

                              哎呀哎呀视频在线观看