模型介紹、評(píng)估和參數(shù)調(diào)優(yōu)(附代碼)

我們在用訓(xùn)練數(shù)據(jù)對(duì)模型進(jìn)行擬合時(shí)會(huì)得到模型的一些參數(shù),但將模型用于新數(shù)據(jù)時(shí)需重設(shè)這些參數(shù),并且還需要評(píng)估這個(gè)模型的實(shí)用性。我們可以利用scikit-learn中的一些方法來達(dá)到這么目的。
我們本次所用到的數(shù)據(jù)是威斯康星乳腺癌數(shù)據(jù)(滿大街了都)
先加載數(shù)據(jù)吧。可以利用pandas直接去UCI網(wǎng)站讀取

import pandas as pd
df = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/wdbc.data',header=None)

接下來我們可以觀察下數(shù)據(jù)

df.head()

可以看到該數(shù)據(jù)有32列,第二列是關(guān)于樣本的診斷結(jié)果(M代表惡性,B代表良性),第3列-32列包含了30個(gè)從細(xì)胞核照片中提取、用實(shí)數(shù)值標(biāo)識(shí)的特征

#觀察缺失值,可以看到?jīng)]有缺失值
import missingno
missingno.matrix(df)

對(duì)于分類模型來講,目標(biāo)變量值最好為數(shù)值,比如男為1,女為0。我們可以觀察到該數(shù)據(jù)集的目標(biāo)變量為M和B,要將其轉(zhuǎn)化為0,1.而我們該興趣的是惡性的,所以要將M變?yōu)?,B變?yōu)?

#先將數(shù)據(jù)分為特征列和目標(biāo)列
X=df.loc[:,2:].values
y=df.loc[:,1].values
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
y=le.fit_transform(y)

被sklearn的LabelEncoder轉(zhuǎn)換器轉(zhuǎn)換之后,類標(biāo)被存儲(chǔ)在一個(gè)數(shù)組y中,此時(shí)M被標(biāo)識(shí)為1,B為0.我們可以通過transform方法來顯示虛擬類標(biāo)

le.transform(['M','B'])
Out:array([1, 0], dtype=int64)

也可以查看下類的比例情況

pd.Series.value_counts(y)

image.png

接下來將數(shù)據(jù)分為訓(xùn)練集和測試集

from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2,random_state=1)

1.基于流水線的工作流

接下來我們可以利用Pipeline類來進(jìn)行工作流

from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
pipe_lr = Pipeline([('scl',StandardScaler()),('pca',PCA(n_components=2)),('clf',LogisticRegression(random_state=1))])
pipe_lr.fit(X_train,y_train)
print("Test Accuracy:%.3f"%pipe_lr.score(X_test,y_test))
Out:Test Accuracy: 0.947

Pipeline對(duì)象采用元組的序列作為輸入,其中每個(gè)元組中的第一個(gè)值為一個(gè)字符串,可以是任意的標(biāo)識(shí)符,我們通過它來訪問流水線中的元素,而元組的第二個(gè)值則為scikit-learn中的一個(gè)轉(zhuǎn)換器或者評(píng)估器。我們以上的例子的執(zhí)行順序是先用StandardScaler將數(shù)據(jù)集標(biāo)準(zhǔn)化,然后將數(shù)據(jù)集降維到2維空間,然后再用邏輯回歸擬合訓(xùn)練集。

2.使用K折交叉驗(yàn)證評(píng)估模型性能

如果一個(gè)模型過于簡單,可能會(huì)面試欠擬合(高偏差)問題,但是如果模型太過復(fù)雜,又會(huì)面臨過擬合(高方差)問題。所以我們必須要借助一些手段對(duì)模型進(jìn)行評(píng)估。其中最常用的就是K折交叉驗(yàn)證,該方法魯棒性好??梢员容^好的應(yīng)對(duì)噪聲等問題
k折交叉驗(yàn)證的原理就是我們不重復(fù)地隨機(jī)將訓(xùn)練數(shù)據(jù)集劃分為K個(gè),其中K-1個(gè)用于模型的訓(xùn)練,剩余的1個(gè)用于測試。重復(fù)此過程K次,我們就可以得到K個(gè)模型對(duì)模型性能的評(píng)價(jià)


2.jpg

K折交叉驗(yàn)證使用無重復(fù)抽樣技術(shù).通常情況下,我們將K折交叉驗(yàn)證用于模型的調(diào)優(yōu),也就是找到使得模型泛化性能最優(yōu)的超參值。一旦我們找到了滿意的超參值,我們就可以在全部的訓(xùn)練集上重新訓(xùn)練模型,并使用獨(dú)立的測試集對(duì)模型性能做出最終評(píng)價(jià)。k折交叉驗(yàn)證中K的值一般是10,對(duì)于大多數(shù)數(shù)據(jù)來說是比較合理的。但是如果數(shù)據(jù)集比較小,建議加大K值。這可以是模型評(píng)價(jià)時(shí)得到較小的偏差(不怎么會(huì)欠擬合),但是方差會(huì)變大(過擬合)。當(dāng)數(shù)據(jù)集非常小時(shí),建議用留一交叉驗(yàn)證。留一交叉驗(yàn)證是將數(shù)據(jù)集劃分的數(shù)量等同于樣本量(k=n),這樣每次只有一個(gè)樣本用于測試。如果數(shù)據(jù)集較大,可以減少K值。在scikit-learn中可以用KFold來進(jìn)行k折交叉驗(yàn)證。但是當(dāng)類別比例相差較大時(shí),建議用分層交叉驗(yàn)證。在分層交叉驗(yàn)證中,類別比例在每個(gè)分塊中得以保持,這使得每個(gè)分塊中的類別比例與訓(xùn)練集的整體比例一致。

#分層K折交叉驗(yàn)證
#當(dāng)我們使用kfold迭代器在k個(gè)塊中進(jìn)行循環(huán)時(shí),使用train中返回的索引去擬合邏輯斯底回歸流水線。通過流水線,我們可以保證
#每次迭代時(shí)樣本都得到標(biāo)準(zhǔn)化縮放,然后使用test索引計(jì)算模型的準(zhǔn)確性和f1值,并存放到兩個(gè)列表中,用于計(jì)算平均值和標(biāo)準(zhǔn)差
import numpy as np
from sklearn.model_selection import StratifiedKFold
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LogisticRegression
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import f1_score
pipe_lr = Pipeline([('scl',StandardScaler()),('clf',LogisticRegression(random_state=1))])
kfold = StratifiedKFold(n_splits=10,random_state=1) #通過n_splits來設(shè)置塊的數(shù)量
scores=[]
f1_scores=[]
for k,(train,test) in enumerate(kfold.split(X_train,y_train)):
    pipe_lr.fit(X_train[train],y_train[train])
    p_pred = pipe_lr.predict(X_train[test])
    f1_sc = f1_score(y_true=y_train[test],y_pred=p_pred)
    f1_scores.append(f1_sc)
    score=pipe_lr.score(X_train[test],y_train[test])
    scores.append(score)
    print('Fold: %s, Class dist.: %s,Acc: %.3f,f1 score:%.3f' %(k+1,np.bincount(y_train[train]),score,f1_sc))

得到的結(jié)果為:


image.png
print('CV accuracy: %.3f +/- %.3f' %(np.mean(scores),np.std(scores)))
print("CV f1 score:%.3f +/- %.3f"%(np.mean(f1_scores),np.std(f1_scores)))
image.png

也可以使用sklearn中的cross_val_score直接將上述的結(jié)果計(jì)算出來

#sklearn方法求分成k折交叉驗(yàn)證
#cross_val_score可以將不同分塊的性能評(píng)估分布到多個(gè)CPU上處理。如果將n_jobs參數(shù)設(shè)置為1,則與StratifiedKFold一樣,
#只使用一個(gè)CPU對(duì)性能進(jìn)行評(píng)估,如果設(shè)置為-1,則可利用計(jì)算機(jī)所有的CPU并行地進(jìn)行計(jì)算。還可通過scoring參數(shù)來計(jì)算
#不同的評(píng)估指標(biāo)
from sklearn.model_selection import cross_val_score
scores=cross_val_score(estimator=pipe_lr,
                      X=X_train,
                      y=y_train,
                      scoring="accuracy",
                      cv=10,
                      n_jobs=1)
print("CV accuracy scores: %s" % scores)
image.png
print('CV accurary:%.3f +/- %.3f'%(np.mean(scores),np.std(scores)))
  • cross_val_score中scoring參數(shù)可以取以下這些:Valid options are ['accuracy', 'adjusted_mutual_info_score', 'adjusted_rand_score', 'average_precision', 'completeness_score', 'explained_variance', 'f1', 'f1_macro', 'f1_micro', 'f1_samples', 'f1_weighted', 'fowlkes_mallows_score', 'homogeneity_score', 'mutual_info_score', 'neg_log_loss', 'neg_mean_absolute_error', 'neg_mean_squared_error', 'neg_mean_squared_log_error', 'neg_median_absolute_error', 'normalized_mutual_info_score', 'precision', 'precision_macro', 'precision_micro', 'precision_samples', 'precision_weighted', 'r2', 'recall', 'recall_macro', 'recall_micro', 'recall_samples', 'recall_weighted', 'roc_auc', 'v_measure_score']

計(jì)算f1值

from sklearn.model_selection import cross_val_score
f1_scores = cross_val_score(estimator=pipe_lr,X=X_train,y=y_train,scoring='f1',cv=10,n_jobs=-1)
print('CV f1 scores:%s'%f1_scores)

計(jì)算auc值

from sklearn.model_selection import cross_val_score
aucs = cross_val_score(estimator=pipe_lr,X=X_train,y=y_train,scoring='roc_auc',cv=10,n_jobs=-1)
print('CV auc scores:%s'%aucs)

3.通過學(xué)習(xí)及驗(yàn)證曲線來調(diào)試算法

3.1通過學(xué)習(xí)曲線,我們可以判定算法偏差和方差問題。

將模型的訓(xùn)練及準(zhǔn)確性驗(yàn)證看做是訓(xùn)練數(shù)據(jù)集大小的函數(shù),并繪制圖像,我們可以比較容易的看出模型是高偏差還是高方差的問題,以及收集更多的數(shù)據(jù)是否有助于解決問題

1.jpg

上圖中左一是個(gè)高偏差模型,準(zhǔn)確率和交叉驗(yàn)證準(zhǔn)確率都很低,表示模型并沒有很好地?cái)M合數(shù)據(jù)。解決辦法:增加模型中參數(shù)的數(shù)量。比如收集或構(gòu)建額外特征,或者降低線性模型比如邏輯回歸和線性SVM的正則化程度。正則化是解決共線性(特征間高度相關(guān))的一個(gè)好辦法,他可以過濾掉噪聲,并最終防止過擬合。正則化是引入額外的信息來對(duì)極端參數(shù)做出懲罰。最常用的是L2正則化,也有L1正則化。特征縮放(標(biāo)準(zhǔn)化,歸一化)之所以重要,其中原因之一就是正則化,為了使得正則化起作用,需要確保所有特征的衡量標(biāo)準(zhǔn)保持統(tǒng)一。

在以上的例子中,我們使用的是Logistic回歸分類器,在該分類器中,我們可以調(diào)整的超參有:

  • penalty:正則懲罰項(xiàng),可以選L1或者L2.默認(rèn)是L2
  • C:正則化倒數(shù),C越小,代表正則化程度越高
  • solver:有四個(gè)值可選:'netton-cg','lbfgs',liblinear','sag'.默認(rèn)是liblinear,該方法對(duì)數(shù)據(jù)量小的數(shù)據(jù)效果較好,且只能處理兩分類。sag在數(shù)據(jù)量比較大的時(shí)候速度 較快。面對(duì)多分類的話,除了liblinear之外其他都可以,且另外幾個(gè)只能支持L2懲罰項(xiàng)。

上圖中右一是個(gè)高方差模型,訓(xùn)練準(zhǔn)確率和交叉驗(yàn)證準(zhǔn)確率之間有很大差距。針對(duì)此問題的解決方案是:收集更多的訓(xùn)練數(shù)據(jù)(降低模型過擬合的概率)或者降低模型的復(fù)雜度,比如增加正則化程度,降低特征的數(shù)量等。
對(duì)于不適合正則化的模型,可以通過特征選擇或者特征提取降低特征的數(shù)量

import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
from sklearn.model_selection import learning_curve
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
pipe_lr = Pipeline([('scl',StandardScaler()),('clf',LogisticRegression(penalty='l2',random_state=0))])
train_sizes,train_scores,test_scores = learning_curve(
    estimator=pipe_lr,
X=X_train,
y=y_train,
train_sizes = np.linspace(0.1,1.0,10),
cv=10,
n_jobs=-1)
train_mean = np.mean(train_scores,axis=1)
train_std = np.std(train_scores,axis=1)
test_mean = np.mean(test_scores,axis=1)
test_std = np.std(test_scores,axis=1)
plt.plot(train_sizes,train_mean,color='blue',marker='o',markersize=5,label='training accuracy')
plt.fill_between(train_sizes,train_mean+train_std,train_mean-train_std,alpha=0.15,color='blue')
plt.plot(train_sizes,test_mean,color='green',linestyle='--',markersize=5,label='validation accuracy')
plt.fill_between(train_sizes,test_mean+test_std,test_mean-test_std,color='green',alpha=0.15)
plt.grid()
plt.xlabel('Number of training samples')
plt.ylabel('Accuracy')
plt.legend(loc='best')
plt.ylim([0.8,1.0])

通過上面的代碼,我們可以得到下面的學(xué)習(xí)曲線


從圖像上來,模型在測試機(jī)上表現(xiàn)良好.但有些地方有較小差距,意味著有輕微的過擬合

通過learning_curve中的train_size參數(shù),我們可以控制用于生成學(xué)習(xí)曲線的樣本的絕對(duì)或相對(duì)數(shù)量。在此,通過設(shè)置train_size=np.linspace(0.1,1,10)來使用訓(xùn)練集上等距間隔的10個(gè)樣本。默認(rèn)情況下,learning_curve函數(shù)使用分層K折交叉驗(yàn)證來計(jì)算準(zhǔn)確率。

3.2通過驗(yàn)證曲線,我們可以判定算法欠擬合和過擬合問題。

驗(yàn)證曲線和學(xué)習(xí)曲線相似,不過繪制的不是樣本大小和訓(xùn)練準(zhǔn)確率、測試準(zhǔn)確率之間的函數(shù)關(guān)系,而是準(zhǔn)確率與模型參數(shù)之間的關(guān)系

from sklearn.model_selection import validation_curve
param_range = [0.001,0.01,0.1,1.0,10.0,100.0]
pipe_lr = Pipeline([('scl',StandardScaler()),('clf',LogisticRegression(penalty='l2',random_state=0))])
train_scores,test_scores = validation_curve(
estimator=pipe_lr,
X=X_train,
y=y_train,
param_name='clf__C',
param_range=param_range,
cv=10)
train_mean = np.mean(train_scores,axis=1)
train_std = np.std(train_scores,axis=1)
test_mean = np.mean(test_scores,axis=1)
test_std = np.std(test_scores,axis=1)
plt.plot(param_range,train_mean,color='blue',marker='o',markersize=5,label='training accuracy')
plt.fill_between(param_range,train_mean+train_std,train_mean-train_std,color='blue',alpha=0.15)
plt.plot(param_range,test_mean,color='green',linestyle='--',markersize=5,label='validation accuracy')
plt.fill_between(param_range,test_mean+test_std,test_mean-test_std,color='green',alpha=0.15)
plt.grid()
plt.xscale('log') #設(shè)置X軸的縮放比例,可以用'log','linear','logit','symlog'
plt.legend(loc='best')
plt.xlabel('Parameter C')
plt.ylabel('Accuracy')
plt.ylim([0.8,1])

通過上面的代碼,得到下面的圖形:


可以看到,如果加大正則化程度(較小的C),會(huì)導(dǎo)致模型輕微的欠擬合,如果降低正則化程度(較大的C),會(huì)趨向于過擬合。在本例中,最好的C值是0.1

4.使用網(wǎng)絡(luò)搜索調(diào)優(yōu)模型

在機(jī)器學(xué)習(xí)中,有兩類參數(shù):一是通過訓(xùn)練數(shù)據(jù)學(xué)習(xí)得到的參數(shù),如Logistic回歸中的回歸系數(shù);二是算法中需要單獨(dú)進(jìn)行優(yōu)化的參數(shù),即調(diào)優(yōu)參數(shù),也稱超參,如邏輯回歸中的正則化系數(shù),決策樹中的深度系數(shù)。
我們之前是通過驗(yàn)證曲線來得到較優(yōu)的C值,但是通過圖形來得出最優(yōu)值會(huì)帶點(diǎn)主觀性,所以我們可以利用網(wǎng)格搜索,通過明確的結(jié)果尋找最優(yōu)的超參值的組合

from sklearn.model_selection import GridSearchCV
pipe_lr = Pipeline([('scl',StandardScaler()),('clf',LogisticRegression(random_state=0))])
param_range=[0.0001,0.001,0.01,0.1,1,10,100,1000]
param_penalty=['l1','l2']
param_grid=[{'clf__C':param_range,'clf__penalty':param_penalty}]
gs = GridSearchCV(estimator=pipe_lr,
                 param_grid=param_grid,
                 scoring='f1',
                 cv=10,
                 n_jobs=-1)
gs = gs.fit(X_train,y_train)
print(gs.best_score_)
print(gs.best_params_)

得到的結(jié)果為:

0.970063106828
{'clf__C': 0.1, 'clf__penalty': 'l2'}

可以看到C值和penalty的最優(yōu)組合是0.1和l2。
在上述代碼中,我們是在流水線中調(diào)優(yōu)的,所以在GridSearchCV的param_grid參數(shù)以字典的方式定義待調(diào)優(yōu)的參數(shù)時(shí),我們填寫的是clf__C(英文狀態(tài)下兩個(gè)下劃線)和clf__penalty,這個(gè)clf在流水線中代表定義的邏輯回歸,后面代表的是要調(diào)優(yōu)的參數(shù)。
在訓(xùn)練數(shù)據(jù)集上完成網(wǎng)格搜索后,可以通過best_score_屬性得到你在scoring參數(shù)中指定的指標(biāo)的最優(yōu)值,而具體的待調(diào)優(yōu)的參數(shù)信息可通過best_params_屬性得到

最后我們可以通過GridSearchCV對(duì)象的best_estimator_屬性對(duì)最優(yōu)模型進(jìn)行性能評(píng)估

from sklearn.metrics import f1_score
clf = gs.best_estimator_
clf.fit(X_train,y_train)
y_pred = clf.predict(X_test)
print('Test f1 score:%.3f'%f1_score(y_true=y_test,y_pred=y_pred))

得到的結(jié)果為:

Test f1 score:0.963

也可以這樣:

from sklearn.model_selection import cross_val_score
clf=gs.best_estimator_
clf.fit(X_train,y_train)
f1_scores = cross_val_score(estimator=clf,X=X,y=y,scoring='f1',cv=10,n_jobs=-1)
print("CV f1 score:%.3f"%np.mean(f1_scores))

網(wǎng)格搜索雖然很給力,但是計(jì)算速度不怎么好。因?yàn)樗ㄟ^對(duì)我們指定的不同超參列表進(jìn)行暴力窮舉搜索,并計(jì)算評(píng)估每個(gè)組合對(duì)模型性能的影響,以獲得參數(shù)的最優(yōu)組合在sklearn中,還有其他的方法,具體可以參考:http://scikit-learn.org/stable/modules/grid_search.html#exhaustive-grid-search

5.通過嵌套交叉驗(yàn)證選擇算法

5X2交叉驗(yàn)證

在嵌套交叉驗(yàn)證的外圍循環(huán)中,我們將數(shù)據(jù)劃分為訓(xùn)練塊和測試塊,用于模型選擇的內(nèi)部循環(huán)中,我們基于外圍的訓(xùn)練塊使用K折交叉驗(yàn)證。在完成模型的選擇后,測試塊用于模型性能的評(píng)估。在上圖中是5X2交叉驗(yàn)證,適用于計(jì)算性能要求比較高的大規(guī)模數(shù)據(jù)集。
接下來我們使用邏輯回歸和隨機(jī)森林來對(duì)這個(gè)數(shù)據(jù)集進(jìn)行嵌套交叉驗(yàn)證

#邏輯回歸
from sklearn.model_selection import cross_val_score,GridSearchCV
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
pipe_lr = Pipeline([('scl',StandardScaler()),('clf',LogisticRegression(random_state=0))])
param_range=[0.0001,0.001,0.01,0.1,1,10,100,1000]
param_penalty=['l1','l2']
param_grid = [{'clf__C':param_range,'clf__penalty':param_penalty}]
clf_gs = GridSearchCV(estimator=pipe_lr,param_grid=param_grid,scoring='f1',cv=10,n_jobs=-1)
clf_f1_scores = cross_val_score(estimator=clf_gs,X=X,y=y,scoring='f1',cv=5)
print('CV clf f1 score:%.3f +/- %.3f'%(np.mean(clf_f1_scores),np.std(clf_f1_scores)))

結(jié)果為:

CV clf f1 score:0.969 +/- 0.012
#隨機(jī)森林
from sklearn.ensemble import RandomForestClassifier
rfc = RandomForestClassifier(random_state=0)
#在bootstap為True和False的情況下的參數(shù)組合
rfc_grid=[{'n_estimators':[3,10,15],'max_depth':[1,2,3,4,5,6,7,None]},
          {'bootstrap':[False],'n_estimators':[3,10],'max_depth':[1,2,3,4,5,6,7,None]}]
rfc_gs = GridSearchCV(estimator=rfc,param_grid=rfc_grid,cv=10,scoring='f1',n_jobs=-1)
rfc_f1_scores = cross_val_score(estimator=rfc_gs,X=X,y=y,scoring='f1',cv=5)
print('CV clf f1 score:%.3f +/- %.3f'%(np.mean(rfc_f1_scores),np.std(rfc_f1_scores)))

結(jié)果為:

CV clf f1 score:0.948 +/- 0.023

從結(jié)果來看,邏輯回歸的效果似乎更好一點(diǎn)哦

  • 既然用到了隨機(jī)森林,那我們講一下隨機(jī)森林(屬于bagging集成學(xué)習(xí))
    隨機(jī)森林可以視為多顆決策樹的集成,魯棒性更強(qiáng),泛化能力更好,不易產(chǎn)生過擬合現(xiàn)象。但是噪聲比較大的情況下會(huì)過擬合??梢院唵蔚膶㈦S機(jī)森林算法概括為四個(gè)簡單步驟:
  1. 使用bootstrap抽樣方法隨機(jī)選擇N個(gè)樣本用于訓(xùn)練(從訓(xùn)練集中隨機(jī)可重復(fù)地選擇N個(gè)樣本)
    2.使用第1步選定的樣本來構(gòu)造一個(gè)決策樹。節(jié)點(diǎn)劃分規(guī)則如下:
    (1)不重復(fù)地隨機(jī)選擇d個(gè)特征
    (2)根據(jù)目標(biāo)函數(shù)的要求,如最大化信息增益,使用選定的特征對(duì)節(jié)點(diǎn)進(jìn)行劃分
    3.重復(fù)上述過程1~2000次
    4.匯總每棵樹的類標(biāo)進(jìn)行多數(shù)投票。比如對(duì)于二分類類標(biāo),總共有15棵樹,有10棵樹分為1,5棵樹分為0,則多數(shù)服從少數(shù),最終結(jié)果為1

隨機(jī)森林相對(duì)于決策樹來講沒有那么好的可解釋性,但其顯著優(yōu)勢在于不必?fù)?dān)心超參值的選擇.不需要對(duì)隨機(jī)森林進(jìn)行剪枝,因?yàn)橄鄬?duì)于單棵決策樹來講,集成模型對(duì)噪聲的魯棒性更好
在實(shí)踐中,我們真正需要關(guān)心的參數(shù)是為構(gòu)建隨機(jī)森林所需的決策樹數(shù)量(即第3步驟)。通常情況下,決策樹的數(shù)量越多,隨機(jī)森林整體的分類表現(xiàn)越好,但這會(huì)增加計(jì)算成本。其他可調(diào)的參數(shù)有:
1.n_estimators : 隨機(jī)森林中樹的數(shù)量,也就是弱分類器的數(shù)量
2.criterion: 兩種衡量分割效果的方法,有基尼系數(shù)法和熵法(entropy)。
3.max_features : 尋找最佳分割時(shí)要考慮特征變量的個(gè)數(shù)
4.max_depth :設(shè)置決策樹最大深度,如果不設(shè)置該變量,決策樹一直延伸直至每個(gè)葉節(jié)點(diǎn)都完美分類,或者所有葉節(jié)點(diǎn)內(nèi)數(shù)量達(dá)到min_samples_split指定的樣本數(shù)量。
5.min_samples_split: 分割一個(gè)內(nèi)部節(jié)點(diǎn)所要求的最低樣本含量,低于這個(gè)數(shù)量就不再分割了。
6.max_leaf_nodes : 葉節(jié)點(diǎn)最大數(shù)目,默認(rèn)不限制葉節(jié)點(diǎn)的最大數(shù)量。
7.min_impurity_split: 如果純度還高于閾值,繼續(xù)分割,如果達(dá)到閾值,成為葉節(jié)點(diǎn)。
8.bootstrap : 在生長樹的時(shí)候是否采用bootstrap的方法,默認(rèn)是是True

6.不同的性能評(píng)價(jià)指標(biāo)

理論部分可以看下這個(gè)分類算法模型評(píng)估理論篇

6.1混淆矩陣
先利用網(wǎng)格搜索算出最優(yōu)的參數(shù)
from sklearn.metrics import confusion_matrix,classification_report
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import GridSearchCV
pipe_lr = Pipeline([('scl',StandardScaler()),('clf',LogisticRegression(random_state=0))])
param_range = [0.00001,0.0001,0.001,0.01,0.1,1,10,100,1000]
param_penalty = ['l1','l2']
param_grid=[{'clf__C':param_range,'clf__penalty':param_penalty}]
clf_gs = GridSearchCV(estimator=pipe_lr,param_grid=param_grid,scoring='f1',cv=10,n_jobs=-1)
gs = clf_gs.fit(X_train,y_train)
print(gs.best_params_)
結(jié)果為:
{'clf__C': 0.1, 'clf__penalty': 'l2'}
clf = clf_gs.best_estimator_
clf.fit(X_train,y_train)
y_pred = clf.predict(X_test)
confmat=confusion_matrix(y_true=y_test,y_pred=y_pred)
class_report = classification_report(y_true=y_test,y_pred=y_pred)
print(confmat)
print('******************************')
print(class_report)
結(jié)果

圖片上的就是混淆矩陣
我們還可以可視化混淆矩陣

fig,ax=plt.subplots(figsize=(2.5,2.5))
ax.matshow(confmat,cmap=plt.cm.Blues,alpha=0.3)
for i in range(confmat.shape[0]):
    for j in range(confmat.shape[1]):
        ax.text(x=j,y=i,s=confmat[i,j],va='center',ha='center')
plt.xlabel('predicted label')
plt.ylabel('true label')

結(jié)果如下:


image.png
6.2精度和召回率
from sklearn.metrics import precision_score #精度
from sklearn.metrics import recall_score,f1_score #召回率,f1分?jǐn)?shù)
print('Precision:%.3f'%precision_score(y_true=y_test,y_pred=y_pred))
print('Recall:%.3f'%recall_score(y_true=y_test,y_pred=y_pred))
print('f1:%.3f'%f1_score(y_true=y_test,y_pred=y_pred))

結(jié)果:
Precision:1.000
Recall:0.929
f1:0.963
#因?yàn)閟cikit-learn中將正類類標(biāo)標(biāo)識(shí)為1.如果想指定一個(gè)不同的正類類標(biāo)來評(píng)分的話,可以如下操作
from sklearn.metrics import make_scorer,f1_score
scorer = make_scorer(f1_score,pos_label=0)
gs = GridSearchCV(estimator=pipe_svc,param_grid=param_grid,scoring=scorer,cv=10)

以上這些也可以通過cross_val_score中的scoring參數(shù)指定計(jì)算出來

6.ROC曲線
from sklearn.metrics import roc_curve,auc
from scipy import interp
X_train2=X_train[:,[4,14]]
cv = StratifiedKFold(y_train,n_folds=3,random_state=1)
fig=plt.figure(figsize=(7,5))
mean_tpr = 0.0
mean_fpr = np.linspace(0,1,100)
all_tpr=[]
for i,(train,test) in enumerate(cv):
    probas = pipe_lr.fit(X_train2[train],
                        y_train[train]).predict_proba(X_train2[test])
    fpr,tpr,thresholds = roc_curve(y_train[test],probas[:,1],pos_label=1)
    mean_tpr+=interp(mean_fpr,fpr,tpr)
    mean_tpr[0]=0.0
    roc_auc=auc(fpr,tpr)
    plt.plot(fpr,tpr,lw=1,label='ROC fold %d (area=%0.2f)'%(i+1,roc_auc))
plt.plot([0,1],[0,1],linestyle='--',color=(0.6,0.6,0.6),label='random guessing')
mean_tpr/=len(cv)
mean_tpr[-1]=1.0
mean_auc=auc(mean_fpr,mean_tpr)
plt.plot(mean_fpr,mean_tpr,'k--',label='mean ROC(area=%0.2f)'%mean_auc,lw=2)
plt.plot([0,0,1],[0,1,1],lw=2,linestyle=':',color="black",label='perfect performance')
plt.xlim([-0.05,1.05])
plt.ylim([-0.05,1.05])
plt.xlabel('false positive tate')
plt.ylabel('true positive rate')
plt.title('Receiver Operator Characteristic')
plt.legend(loc='best')
plt.show()

結(jié)果為:


image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容