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