我們?cè)谟糜?xùn)練數(shù)據(jù)對(duì)模型進(jìn)行擬合時(shí)會(huì)得到模型的一些參數(shù)惰爬,但將模型用于新數(shù)據(jù)時(shí)需重設(shè)這些參數(shù)喊暖,并且還需要評(píng)估這個(gè)模型的實(shí)用性。我們可以利用scikit-learn中的一些方法來(lái)達(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)
接下來(lái)我們可以觀察下數(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ì)于分類模型來(lái)講,目標(biāo)變量值最好為數(shù)值禽车,比如男為1寇漫,女為0刊殉。我們可以觀察到該數(shù)據(jù)集的目標(biāo)變量為M和B,要將其轉(zhuǎn)化為0,1.而我們?cè)撆d趣的是惡性的,所以要將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.我們可以通過(guò)transform方法來(lái)顯示虛擬類標(biāo)
le.transform(['M','B'])
Out:array([1, 0], dtype=int64)
也可以查看下類的比例情況
pd.Series.value_counts(y)
接下來(lái)將數(shù)據(jù)分為訓(xùn)練集和測(cè)試集
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.基于流水線的工作流
接下來(lái)我們可以利用Pipeline類來(lái)進(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í)符瓤湘,我們通過(guò)它來(lái)訪問(wèn)流水線中的元素瓢颅,而元組的第二個(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è)模型過(guò)于簡(jiǎn)單木人,可能會(huì)面試欠擬合(高偏差)問(wèn)題信柿,但是如果模型太過(guò)復(fù)雜,又會(huì)面臨過(guò)擬合(高方差)問(wèn)題醒第。所以我們必須要借助一些手段對(duì)模型進(jìn)行評(píng)估渔嚷。其中最常用的就是K折交叉驗(yàn)證,該方法魯棒性好稠曼∑粤妫可以比較好的應(yīng)對(duì)噪聲等問(wèn)題
k折交叉驗(yàn)證的原理就是我們不重復(fù)地隨機(jī)將訓(xùn)練數(shù)據(jù)集劃分為K個(gè),其中K-1個(gè)用于模型的訓(xùn)練蒲列,剩余的1個(gè)用于測(cè)試窒朋。重復(fù)此過(guò)程K次,我們就可以得到K個(gè)模型對(duì)模型性能的評(píng)價(jià)
K折交叉驗(yàn)證使用無(wú)重復(fù)抽樣技術(shù).通常情況下蝗岖,我們將K折交叉驗(yàn)證用于模型的調(diào)優(yōu)侥猩,也就是找到使得模型泛化性能最優(yōu)的超參值。一旦我們找到了滿意的超參值抵赢,我們就可以在全部的訓(xùn)練集上重新訓(xùn)練模型欺劳,并使用獨(dú)立的測(cè)試集對(duì)模型性能做出最終評(píng)價(jià)。k折交叉驗(yàn)證中K的值一般是10铅鲤,對(duì)于大多數(shù)數(shù)據(jù)來(lái)說(shuō)是比較合理的划提。但是如果數(shù)據(jù)集比較小,建議加大K值邢享。這可以是模型評(píng)價(jià)時(shí)得到較小的偏差(不怎么會(huì)欠擬合)鹏往,但是方差會(huì)變大(過(guò)擬合)。當(dāng)數(shù)據(jù)集非常小時(shí)骇塘,建議用留一交叉驗(yàn)證伊履。留一交叉驗(yàn)證是將數(shù)據(jù)集劃分的數(shù)量等同于樣本量(k=n),這樣每次只有一個(gè)樣本用于測(cè)試韩容。如果數(shù)據(jù)集較大,可以減少K值唐瀑。在scikit-learn中可以用KFold來(lái)進(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中返回的索引去擬合邏輯斯底回歸流水線。通過(guò)流水線睛廊,我們可以保證
#每次迭代時(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) #通過(guò)n_splits來(lái)設(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é)果為:
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)))
也可以使用sklearn中的cross_val_score直接將上述的結(jié)果計(jì)算出來(lái)
#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ì)算疏遏。還可通過(guò)scoring參數(shù)來(lái)計(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)
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.通過(guò)學(xué)習(xí)及驗(yàn)證曲線來(lái)調(diào)試算法
3.1通過(guò)學(xué)習(xí)曲線脉课,我們可以判定算法偏差和方差問(wèn)題。
將模型的訓(xùn)練及準(zhǔn)確性驗(yàn)證看做是訓(xùn)練數(shù)據(jù)集大小的函數(shù)财异,并繪制圖像倘零,我們可以比較容易的看出模型是高偏差還是高方差的問(wèn)題,以及收集更多的數(shù)據(jù)是否有助于解決問(wèn)題
上圖中左一是個(gè)高偏差模型戳寸,準(zhǔn)確率和交叉驗(yàn)證準(zhǔn)確率都很低呈驶,表示模型并沒(méi)有很好地?cái)M合數(shù)據(jù)。解決辦法:增加模型中參數(shù)的數(shù)量疫鹊。比如收集或構(gòu)建額外特征袖瞻,或者降低線性模型比如邏輯回歸和線性SVM的正則化程度。正則化是解決共線性(特征間高度相關(guān))的一個(gè)好辦法拆吆,他可以過(guò)濾掉噪聲聋迎,并最終防止過(guò)擬合。正則化是引入額外的信息來(lái)對(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ì)此問(wèn)題的解決方案是:收集更多的訓(xùn)練數(shù)據(jù)(降低模型過(guò)擬合的概率)或者降低模型的復(fù)雜度,比如增加正則化程度斋配,降低特征的數(shù)量等孔飒。
對(duì)于不適合正則化的模型,可以通過(guò)特征選擇或者特征提取降低特征的數(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])
通過(guò)上面的代碼艰争,我們可以得到下面的學(xué)習(xí)曲線
通過(guò)learning_curve中的train_size參數(shù)甩卓,我們可以控制用于生成學(xué)習(xí)曲線的樣本的絕對(duì)或相對(duì)數(shù)量鸠匀。在此,通過(guò)設(shè)置train_size=np.linspace(0.1,1,10)來(lái)使用訓(xùn)練集上等距間隔的10個(gè)樣本猛频。默認(rèn)情況下狮崩,learning_curve函數(shù)使用分層K折交叉驗(yàn)證來(lái)計(jì)算準(zhǔn)確率。
3.2通過(guò)驗(yàn)證曲線鹿寻,我們可以判定算法欠擬合和過(guò)擬合問(wèn)題睦柴。
驗(yàn)證曲線和學(xué)習(xí)曲線相似,不過(guò)繪制的不是樣本大小和訓(xùn)練準(zhǔn)確率毡熏、測(cè)試準(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])
通過(guò)上面的代碼,得到下面的圖形:
4.使用網(wǎng)絡(luò)搜索調(diào)優(yōu)模型
在機(jī)器學(xué)習(xí)中躬络,有兩類參數(shù):一是通過(guò)訓(xùn)練數(shù)據(jù)學(xué)習(xí)得到的參數(shù),如Logistic回歸中的回歸系數(shù)搭儒;二是算法中需要單獨(dú)進(jìn)行優(yōu)化的參數(shù)穷当,即調(diào)優(yōu)參數(shù),也稱超參淹禾,如邏輯回歸中的正則化系數(shù)馁菜,決策樹(shù)中的深度系數(shù)。
我們之前是通過(guò)驗(yàn)證曲線來(lái)得到較優(yōu)的C值铃岔,但是通過(guò)圖形來(lái)得出最優(yōu)值會(huì)帶點(diǎn)主觀性汪疮,所以我們可以利用網(wǎng)格搜索,通過(guò)明確的結(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í)蜓洪,我們填寫(xiě)的是clf__C(英文狀態(tài)下兩個(gè)下劃線)和clf__penalty,這個(gè)clf在流水線中代表定義的邏輯回歸纤勒,后面代表的是要調(diào)優(yōu)的參數(shù)。
在訓(xùn)練數(shù)據(jù)集上完成網(wǎng)格搜索后隆檀,可以通過(guò)best_score_屬性得到你在scoring參數(shù)中指定的指標(biāo)的最優(yōu)值摇天,而具體的待調(diào)優(yōu)的參數(shù)信息可通過(guò)best_params_屬性得到
最后我們可以通過(guò)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)樗ㄟ^(guò)對(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.通過(guò)嵌套交叉驗(yàn)證選擇算法
在嵌套交叉驗(yàn)證的外圍循環(huán)中,我們將數(shù)據(jù)劃分為訓(xùn)練塊和測(cè)試塊歧斟,用于模型選擇的內(nèi)部循環(huán)中纯丸,我們基于外圍的訓(xùn)練塊使用K折交叉驗(yàn)證。在完成模型的選擇后静袖,測(cè)試塊用于模型性能的評(píng)估觉鼻。在上圖中是5X2交叉驗(yàn)證,適用于計(jì)算性能要求比較高的大規(guī)模數(shù)據(jù)集队橙。
接下來(lái)我們使用邏輯回歸和隨機(jī)森林來(lái)對(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為T(mén)rue和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é)果來(lái)看坠陈,邏輯回歸的效果似乎更好一點(diǎn)哦
- 既然用到了隨機(jī)森林萨惑,那我們講一下隨機(jī)森林(屬于bagging集成學(xué)習(xí))
隨機(jī)森林可以視為多顆決策樹(shù)的集成,魯棒性更強(qiáng)仇矾,泛化能力更好庸蔼,不易產(chǎn)生過(guò)擬合現(xiàn)象。但是噪聲比較大的情況下會(huì)過(guò)擬合贮匕〗憬觯可以簡(jiǎn)單的將隨機(jī)森林算法概括為四個(gè)簡(jiǎn)單步驟:
- 使用bootstrap抽樣方法隨機(jī)選擇N個(gè)樣本用于訓(xùn)練(從訓(xùn)練集中隨機(jī)可重復(fù)地選擇N個(gè)樣本)
2.使用第1步選定的樣本來(lái)構(gòu)造一個(gè)決策樹(shù)。節(jié)點(diǎn)劃分規(guī)則如下:
(1)不重復(fù)地隨機(jī)選擇d個(gè)特征
(2)根據(jù)目標(biāo)函數(shù)的要求粗合,如最大化信息增益萍嬉,使用選定的特征對(duì)節(jié)點(diǎn)進(jìn)行劃分
3.重復(fù)上述過(guò)程1~2000次
4.匯總每棵樹(shù)的類標(biāo)進(jìn)行多數(shù)投票乌昔。比如對(duì)于二分類類標(biāo)隙疚,總共有15棵樹(shù),有10棵樹(shù)分為1,5棵樹(shù)分為0磕道,則多數(shù)服從少數(shù)供屉,最終結(jié)果為1
隨機(jī)森林相對(duì)于決策樹(shù)來(lái)講沒(méi)有那么好的可解釋性,但其顯著優(yōu)勢(shì)在于不必?fù)?dān)心超參值的選擇.不需要對(duì)隨機(jī)森林進(jìn)行剪枝溺蕉,因?yàn)橄鄬?duì)于單棵決策樹(shù)來(lái)講伶丐,集成模型對(duì)噪聲的魯棒性更好
在實(shí)踐中,我們真正需要關(guān)心的參數(shù)是為構(gòu)建隨機(jī)森林所需的決策樹(shù)數(shù)量(即第3步驟)疯特。通常情況下哗魂,決策樹(shù)的數(shù)量越多,隨機(jī)森林整體的分類表現(xiàn)越好漓雅,但這會(huì)增加計(jì)算成本录别。其他可調(diào)的參數(shù)有:
1.n_estimators : 隨機(jī)森林中樹(shù)的數(shù)量,也就是弱分類器的數(shù)量
2.criterion: 兩種衡量分割效果的方法邻吞,有基尼系數(shù)法和熵法(entropy)组题。
3.max_features : 尋找最佳分割時(shí)要考慮特征變量的個(gè)數(shù)
4.max_depth :設(shè)置決策樹(shù)最大深度,如果不設(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 : 在生長(zhǎng)樹(shù)的時(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)
圖片上的就是混淆矩陣
我們還可以可視化混淆矩陣
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é)果如下:
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)來(lái)評(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)
以上這些也可以通過(guò)cross_val_score中的scoring參數(shù)指定計(jì)算出來(lái)
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é)果為: