引言
神經(jīng)網(wǎng)絡(luò)是機器學(xué)習(xí)的一個迷人的領(lǐng)域,但是她們有時很難優(yōu)化和解釋。事實上,她們有幾個超參數(shù)。要優(yōu)化的最常見的超參數(shù)是隱藏層中的神經(jīng)元數(shù)量。讓我們看看如何為我們的數(shù)據(jù)集找到一個神經(jīng)網(wǎng)絡(luò)的最佳神經(jīng)元數(shù)量。
什么是神經(jīng)網(wǎng)絡(luò)?
神經(jīng)網(wǎng)絡(luò)是一種特定模型,她可以根據(jù)一層神經(jīng)元來捕捉特征與目標(biāo)之間的相關(guān)性,從而轉(zhuǎn)換數(shù)據(jù)集。一個神經(jīng)網(wǎng)絡(luò)是由幾層神經(jīng)元組成的。每個神經(jīng)元獲取一些輸入,轉(zhuǎn)換她們并返回輸出。一個神經(jīng)元的輸出可以成為下一層神經(jīng)元的輸入等等,構(gòu)建越來越復(fù)雜的架構(gòu)。
第一層稱為輸入層,由返回特征值本身的神經(jīng)元構(gòu)成。然后,第一層的每個神經(jīng)元連接到隱藏層的所有神經(jīng)元,負責(zé)網(wǎng)絡(luò)的學(xué)習(xí)能力。隱藏層后面可以跟幾個其他隱藏層,這是深度學(xué)習(xí)網(wǎng)絡(luò)的典型特征。最后,將最后一個隱藏層的輸出提供給給出結(jié)果(即目標(biāo)變量的值)的輸出層。
在最簡單的形式中,神經(jīng)網(wǎng)絡(luò)只有一個隱藏層,如下圖所示。
輸入層的神經(jīng)元數(shù)目等于特征數(shù)目。根據(jù)目標(biāo)變量定義輸出層的神經(jīng)元數(shù)。接下來的問題是如何為隱藏層找到正確的神經(jīng)元數(shù)量。
數(shù)量太少可能會產(chǎn)生欠擬合,因為網(wǎng)絡(luò)可能無法正確學(xué)習(xí)。但是數(shù)量太多有可能產(chǎn)生過擬合,因為從網(wǎng)絡(luò)中學(xué)習(xí)了太多從而無法泛化。因此必須有合適數(shù)量的神經(jīng)元來確保良好的訓(xùn)練。
如何優(yōu)化神經(jīng)元的數(shù)量
該過程非常簡單,她使用交叉驗證:
交叉驗證很重要,因為使用她我們可以確保模型不會過擬合或欠擬合。
這個過程非常類似于超參數(shù)調(diào)優(yōu),因為隱藏層中的神經(jīng)元數(shù)量實際上是一個要調(diào)優(yōu)的超參數(shù)。
現(xiàn)在讓我們看看如何在 Python 中實現(xiàn)這個過程。
在 Python 中的示例
在這個例子中,我將展示如何使用 scikit-learn 庫優(yōu)化 Python 中的神經(jīng)元數(shù)量。事實上,你也可能會使用 Keras 來構(gòu)建神經(jīng)網(wǎng)絡(luò),但概念是完全相同的。
我將使用 scikit-learn 中包含的乳腺癌示例數(shù)據(jù)集。
首先,讓我們導(dǎo)入一些有用的庫。
import numpy as npfrom sklearn.preprocessing import StandardScalerfrom sklearn.neural_network import MLPClassifierfrom sklearn.datasets import load_breast_cancerfrom sklearn.model_selection import train_test_split, GridSearchCVfrom sklearn.pipeline import Pipelinefrom sklearn.metrics import roc_auc_score
然后,我們可以加載我們的數(shù)據(jù)集,并將其分成訓(xùn)練集和測試集。
X,y = load_breast_cancer(return_X_y=True)X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=42)
現(xiàn)在,我們必須定義我們的模型。在本例中,我將使用一個簡單的帶有單個隱藏層的多層感知器。為了簡單起見,構(gòu)造函數(shù)的所有參數(shù)都保留在她們的標(biāo)準值中。我只是設(shè)置隨機狀態(tài),以確保結(jié)果的可重復(fù)性。
在將數(shù)據(jù)集提供給神經(jīng)網(wǎng)絡(luò)之前,不要忘記縮放特征。為簡單起見,我將在 scikit-learn 中使用 Pipeline 對象,然后應(yīng)用標(biāo)準化。
model = Pipeline([ ('scaler',StandardScaler()), ('model',MLPClassifier(random_state=0))])
現(xiàn)在,我們必須通過搜索最佳神經(jīng)元數(shù)量來優(yōu)化我們的網(wǎng)絡(luò)。請記住,我們嘗試了幾種可能的數(shù)字并計算交叉驗證中性能指標(biāo)的平均值。最大化這樣一個值的神經(jīng)元數(shù)量就是我們正在尋找的數(shù)量。
為此,我們可以使用 GridSearchCV 對象。由于我們正在處理二元分類問題,因此我們要最大化的指標(biāo)是 AUROC。我們將以 2 的步長跨越 5 到 100 個神經(jīng)元。
search = GridSearchCV(model, {'model__hidden_layer_sizes':[(x,) for x in np.arange(5,100,2)]}, cv = 5, scoring = "roc_auc", verbose=3, n_jobs = -1 )
最后,我們可以尋找最佳的神經(jīng)元數(shù)量。
search.fit(X_train, y_train)
搜索結(jié)束后,我們會得到最好的平均分,即:
search.best_score_# 0.9947175348495965
神經(jīng)元的最佳數(shù)量是:
search.best_params_# {'model__hidden_layer_sizes': (75,)}
最后,我們可以在測試數(shù)據(jù)集上計算這樣一個模型的 AUROC,以確保我們沒有對數(shù)據(jù)集進行過多的處理。
roc_auc_score(y_test,search.predict_proba(X_test)[:,1])# 0.9982730973233008
我們得到的值仍然很高,所以我們很確定優(yōu)化后的模型已經(jīng)泛化了訓(xùn)練數(shù)據(jù)集,從她攜帶的信息中學(xué)習(xí)。
總結(jié)
優(yōu)化神經(jīng)網(wǎng)絡(luò)可能是一個復(fù)雜的任務(wù)。在這篇文章中,我已經(jīng)解釋了一種優(yōu)化神經(jīng)元數(shù)量的可能方法,但是同樣的概念甚至可以應(yīng)用到其他超參數(shù)(比如激活函數(shù)、小批量大小、時代數(shù)量、學(xué)習(xí)速度)。記住,超參數(shù)的數(shù)量越多,優(yōu)化的速度就越慢。