Python數(shù)據(jù)科學(xué):神經(jīng)網(wǎng)絡(luò)
(Artificial Neural Network,ANN)人工神經(jīng)網(wǎng)絡(luò)模型,以數(shù)學(xué)和物理的方法對人腦神經(jīng)網(wǎng)絡(luò)進(jìn)行簡化、抽象和模擬。
本次只是一個(gè)簡單的神經(jīng)網(wǎng)絡(luò)入門,涉及神經(jīng)元模型和BP神經(jīng)網(wǎng)絡(luò)。
這里簡單了解一下機(jī)器學(xué)習(xí)的三要素,分別是模型、策略與算法。
模型包括非隨機(jī)效應(yīng)部分(被解釋變量和解釋變量之間的關(guān)系,多為函數(shù)關(guān)系)和隨機(jī)效應(yīng)部分(擾動(dòng)項(xiàng))。
策略是指如何設(shè)定***化的目標(biāo)函數(shù),常見的目標(biāo)函數(shù)有線性回歸的殘差平方和、邏輯回歸的似然函數(shù)、SVM中的合頁函數(shù)等。
算法是對目標(biāo)函數(shù)求參的方法,比如通過求導(dǎo)的方法計(jì)算,或者使用數(shù)值計(jì)算領(lǐng)域的算法求解。
其中神經(jīng)網(wǎng)絡(luò)就是采用數(shù)值算法求解參數(shù),這就意味著每次計(jì)算得到的模型參數(shù)都會(huì)是不同的。
一、神經(jīng)網(wǎng)絡(luò)
01 神經(jīng)元模型
神經(jīng)網(wǎng)絡(luò)中最基本的成分是神經(jīng)元模型。
每個(gè)神經(jīng)元都是一個(gè)多輸入單輸出的信息處理單元,輸入信號(hào)通過帶權(quán)重的連接傳遞,和閾值對比后得到總輸入值,再通過激活函數(shù)的處理產(chǎn)生單個(gè)輸出。
神經(jīng)元的輸出,是對激活函數(shù)套用輸入加權(quán)和的結(jié)果。
神經(jīng)元的激活函數(shù)使得神經(jīng)元具有不同的信息處理特性,反映了神經(jīng)元輸出與其激活狀態(tài)之間的關(guān)系。
本次涉及到的激活函數(shù)有閾值函數(shù)(階躍函數(shù))、sigmoid函數(shù)(S型函數(shù))。
02 單層感知器
感知器是一種具有單層計(jì)算單元的神經(jīng)網(wǎng)絡(luò),只能用來解決線性可分的二分類問題。
無法運(yùn)用到多層感知器中,無法確定隱藏層的期望輸出。
它的結(jié)構(gòu)類似之前的神經(jīng)元模型。
激活函數(shù)采用單極性(或雙極性)閾值函數(shù)。
03 BP神經(jīng)網(wǎng)絡(luò)
采用誤差反向傳播算法(有監(jiān)督學(xué)習(xí)算法)訓(xùn)練的多層神經(jīng)網(wǎng)絡(luò)稱為BP神經(jīng)網(wǎng)絡(luò)。
屬于多層前饋型神經(jīng)網(wǎng)絡(luò),模型的學(xué)習(xí)過程由信號(hào)的正向傳播和誤差反向傳播兩個(gè)過程組成。
進(jìn)行正向傳播時(shí)信號(hào)從輸入層計(jì)算各層加權(quán)和,經(jīng)由各隱層最終傳遞到輸出層,得到輸出結(jié)果,比較輸出結(jié)果與期望結(jié)果(監(jiān)督信號(hào)),得到輸出誤差。
誤差反向傳播是依照梯度下降算法將誤差沿著隱藏層到輸入層逐層反向傳播,將誤差分?jǐn)偨o各層的所有單元,從而得到各個(gè)單元的誤差信號(hào)(學(xué)習(xí)信號(hào)),據(jù)此修改各單元權(quán)值。
這兩個(gè)信號(hào)傳播過程不斷循環(huán)以更新權(quán)值,最終根據(jù)判定條件判斷是否結(jié)束循環(huán)。
其網(wǎng)絡(luò)結(jié)構(gòu)普遍為單隱層網(wǎng)絡(luò),包括輸入層、隱層、輸出層。
激活函數(shù)多采用sigmoid函數(shù)或線性函數(shù),這里隱層和輸出層均采用sigmoid函數(shù)。
二、Python實(shí)現(xiàn)
神經(jīng)網(wǎng)絡(luò)在有明確的訓(xùn)練樣本后,網(wǎng)絡(luò)的輸入層結(jié)點(diǎn)數(shù)(解釋變量個(gè)數(shù))和輸出層結(jié)點(diǎn)數(shù)(被解釋變量的個(gè)數(shù))便已確定。
需要考慮的則是隱含層的個(gè)數(shù)和每個(gè)隱含層的結(jié)點(diǎn)個(gè)數(shù)。
下面利用書中的數(shù)據(jù)進(jìn)行實(shí)戰(zhàn)一波,一份移動(dòng)離網(wǎng)數(shù)據(jù)。
移動(dòng)通訊用戶消費(fèi)特征數(shù)據(jù),目標(biāo)字段為是否流失,具有兩個(gè)分類水平(是與否)。
自變量包含了用戶的基本信息、消費(fèi)的產(chǎn)品信息以及用戶的消費(fèi)特征。
讀取數(shù)據(jù)。
- import pandas as pd
- from sklearn import metrics
- import matplotlib.pyplot as plt
- from sklearn.preprocessing import MinMaxScaler
- from sklearn.neural_network import MLPClassifier
- from sklearn.model_selection import GridSearchCV
- from sklearn.model_selection import train_test_split
- # 設(shè)置***顯示行數(shù)
- pd.set_option('display.max_rows', 10)
- # 設(shè)置***顯示列數(shù)
- pd.set_option('display.max_columns', 10)
- # 設(shè)置顯示寬度為1000,這樣就不會(huì)在IDE中換行了
- pd.set_option('display.width', 1000)
- # 讀取數(shù)據(jù),skipinitialspace:忽略分隔符后的空白
- churn = pd.read_csv('telecom_churn.csv', skipinitialspace=True)
- print(churn)
輸出數(shù)據(jù)概況,包含3000多個(gè)用戶數(shù)據(jù)。
使用scikit-learn中的函數(shù)將數(shù)據(jù)集劃分為訓(xùn)練集和測試集。
- # 選取自變量數(shù)據(jù)
- data = churn.iloc[:, 2:]
- # 選取因變量數(shù)據(jù)
- target = churn['churn']
- # 使用scikit-learn將數(shù)據(jù)集劃分為訓(xùn)練集和測試集
- train_data, test_data, train_target, test_target = train_test_split(data, target, test_size=0.4, train_size=0.6, random_state=1234)
神經(jīng)網(wǎng)絡(luò)需要對數(shù)據(jù)進(jìn)行極值標(biāo)準(zhǔn)化。
需要對連續(xù)變量進(jìn)行極值標(biāo)準(zhǔn)化,分類變量需要轉(zhuǎn)變?yōu)樘摂M變量。
其中多分類名義變量必須轉(zhuǎn)變?yōu)樘摂M變量,而等級變量和二分類變量則可以選擇不轉(zhuǎn)變,當(dāng)做連續(xù)變量處理即可。
本次數(shù)據(jù)中,教育等級和套餐類型是等級變量,性別等變量為二分類變量,這些都可以作為連續(xù)變量進(jìn)行處理。
這也就意味著本次的數(shù)據(jù)集中不存在多分類名義變量,都可作為連續(xù)變量進(jìn)行處理。
- # 極值標(biāo)準(zhǔn)化處理
- scaler = MinMaxScaler()
- scaler.fit(train_data)
- scaled_train_data = scaler.transform(train_data)
- scaler_test_data = scaler.transform(test_data)
建立多層感知器模型。
- # 設(shè)置多層感知器對應(yīng)的模型
- mlp = MLPClassifier(hidden_layer_sizes=(10,), activation='logistic', alpha=0.1, max_iter=1000)
- # 對訓(xùn)練集進(jìn)行模型訓(xùn)練
- mlp.fit(scaled_train_data, train_target)
- # 輸出神經(jīng)網(wǎng)絡(luò)模型信息
- print(mlp)
輸出模型信息如下。
接下來使用經(jīng)過訓(xùn)練集訓(xùn)練的模型,對訓(xùn)練集及測試集進(jìn)行預(yù)測。
- # 使用模型進(jìn)行預(yù)測
- train_predict = mlp.predict(scaled_train_data)
- test_predict = mlp.predict(scaler_test_data)
輸出預(yù)測概率,用戶流失的概率。
- # 輸出模型預(yù)測概率(為1的情況)
- train_proba = mlp.predict_proba(scaled_train_data)[:, 1]
- test_proba = mlp.predict_proba(scaler_test_data)[:, 1]
對模型進(jìn)行評估,輸出評估數(shù)據(jù)。
- # 根據(jù)預(yù)測信息輸出模型評估結(jié)果
- print(metrics.confusion_matrix(test_target, test_predict, labels=[0, 1]))
- print(metrics.classification_report(test_target, test_predict))
輸出如下。
模型對流失用戶的f1-score(精確率和召回率的調(diào)和平均數(shù))值為0.81,效果不錯(cuò)。
此外對流失用戶的靈敏度recall為0.83,模型能識(shí)別出83%的流失用戶,說明模型識(shí)別流失用戶的能力還可以。
輸出模型預(yù)測的平均準(zhǔn)確度。
- # 使用指定數(shù)據(jù)集輸出模型預(yù)測的平均準(zhǔn)確度
- print(mlp.score(scaler_test_data, test_target))
- # 輸出值為0.8282828282828283
平均準(zhǔn)確度值為0.8282。
計(jì)算模型的ROC下面積。
- # 繪制ROC曲線
- fpr_test, tpr_test, th_test = metrics.roc_curve(test_target, test_proba)
- fpr_train, tpr_train, th_train = metrics.roc_curve(train_target, train_proba)
- plt.figure(figsize=[3, 3])
- plt.plot(fpr_test, tpr_test, 'b--')
- plt.plot(fpr_train, tpr_train, 'r-')
- plt.title('ROC curve')
- plt.show()
- # 計(jì)算AUC值
- print(metrics.roc_auc_score(test_target, test_proba))
- # 輸出值為0.9149632415075206
ROC曲線圖如下。
訓(xùn)練集和測試集的曲線很接近,沒有過擬合現(xiàn)象。
AUC值為0.9149,說明模型效果非常好。
對模型進(jìn)行***參數(shù)搜索,并且對***參數(shù)下的模型進(jìn)行訓(xùn)練。
- # 使用GridSearchCV進(jìn)行***參數(shù)搜索
- param_grid = {
- # 模型隱層數(shù)量
- 'hidden_layer_sizes': [(10, ), (15, ), (20, ), (5, 5)],
- # 激活函數(shù)
- 'activation': ['logistic', 'tanh', 'relu'],
- # 正則化系數(shù)
- 'alpha': [0.001, 0.01, 0.1, 0.2, 0.4, 1, 10]
- }
- mlp = MLPClassifier(max_iter=1000)
- # 選擇roc_auc作為評判標(biāo)準(zhǔn),4折交叉驗(yàn)證,n_jobs=-1使用多核CPU的全部線程
- gcv = GridSearchCV(estimator=mlp, param_grid=param_grid,
- scoring='roc_auc', cv=4, n_jobs=-1)
- gcv.fit(scaled_train_data, train_target)
輸出***參數(shù)的模型的情況。
- # 輸出***參數(shù)下模型的得分
- print(gcv.best_score_)
- # 輸出值為0.9258018987136855
- # 輸出***參數(shù)下模型的參數(shù)
- print(gcv.best_params_)
- # 輸出參數(shù)值為{'alpha': 0.01, 'activation': 'tanh', 'hidden_layer_sizes': (5, 5)}
- # 使用指定數(shù)據(jù)集輸出***模型預(yù)測的平均準(zhǔn)確度
- print(gcv.score(scaler_test_data, test_target))
- # 輸出值為0.9169384823390232
模型的roc_auc***得分為0.92,即該模型下的ROC曲線下面積為0.92。
較之前的0.9149,提高了一點(diǎn)點(diǎn)。
模型的***參數(shù),激活函數(shù)為relu類型,alpha為0.01,隱藏層節(jié)點(diǎn)數(shù)為15個(gè)。
模型的預(yù)測平均準(zhǔn)確率為0.9169,較之前的0.8282,提高了不少。