前言:前面已經(jīng)介紹了的幾種算法凳谦,應該對算法有了一個基本的認識了,本章主要是在前面已經(jīng)學到的基礎上衡未,對前面的算法模型進行整合操作尸执,訓練出效果更好的分類器模型。
集成學習
集成學習的思想是將若干個學習器(分類器&回歸器)組合之后產(chǎn)生一個新學習器缓醋。弱分類器( weak learner)指那些分類準確率只稍微好于隨機猜測的分類器( errorrate<0.5);集成算法的成功在于保證弱分類器的多樣性( Diversity)如失。而且集成不穩(wěn)定的算法也能夠得到一個比較明顯的性能提升。
常見的集成學習思想有:
(1)投票選舉(bagging: 自舉匯聚法 bootstrap aggregating): 是基于數(shù)據(jù)隨機重抽樣分類器構造的方法
(2)再學習(boosting): 是基于所有分類器的加權求和的方法
對于不同的數(shù)據(jù)進行不同的集成算法的構建送粱,大致來說可以分為以下四種情況:
(1)弱分類器間存在一定的差異性,這會導致分類的邊界不同,也就是說可能存在錯誤褪贵。那么將多個弱分類器合并后,就可以得到更加合理的邊界,減少整體的錯率,實現(xiàn)更好的效果;
(2)對于數(shù)據(jù)集過大或者過小,可以分別進行劃分和有放回的操作產(chǎn)生不同的數(shù)據(jù)子集,然后使用數(shù)據(jù)子集訓練不同的分類器,最終再合并成為一個大的分類器抗俄;
(3)如果數(shù)據(jù)的劃分邊界過于復雜,使用線性模型很難描述情況,那么可以訓練多個模型,然后再進行模型的融合脆丁;
(4)對于多個異構的特征集的時候,很難進行融合,那么可以考慮每個數(shù)據(jù)集構建一個分類模型,然后將多個模型融合。
例如下圖动雹,是構建三個不同的分類器槽卫,在做一個合并。
隨機森林
隨機森林是在 Bagging策略的基礎上進行修改后的一種算法洽胶。那隨機森林具體如何構建呢晒夹?,所謂的隨機森林姊氓,重點要理解“隨機”這兩個關鍵字丐怯,表現(xiàn)為以下兩個方面:
(1)數(shù)據(jù)的隨機性化
(2)待選特征的隨機化
使得隨機森林中的決策樹都能夠彼此不同,提升系統(tǒng)的多樣性翔横,從而提升分類性能读跷。數(shù)據(jù)的隨機化:使得隨機森林中的決策樹更普遍化一點,適合更多的場景禾唁。
構建流程
采取有放回的抽樣方式 構造子數(shù)據(jù)集效览,保證不同子集之間的數(shù)量級一樣(不同子集/同一子集 之間的元素可以重復)
利用子數(shù)據(jù)集來構建子決策樹,將這個數(shù)據(jù)放到每個子決策樹中荡短,每個子決策樹輸出一個結果丐枉。
然后統(tǒng)計子決策樹的投票結果,得到最終的分類 就是 隨機森林的輸出結果掘托。
具體構建過程如下:
(1)從樣本集中用 Bootstrap采樣選出n個樣本;
(2)從所有屬性中隨機選擇K個屬性,選擇出最佳分割屬性作為節(jié)點創(chuàng)建決策樹
(3)重復以上兩步m次,即建立m棵決策樹
(4)這m個決策樹形成隨機森林,通過投票表決結果決定數(shù)據(jù)屬于那一類
注意:(有放回的準確率在:70% 以上瘦锹, 無放回的準確率在:60% 以上)
如下圖,假設隨機森林中有3棵子決策樹,2棵子樹的分類結果是A類弯院,1棵子樹的分類結果是B類辱士,那么隨機森林的分類結果就是A類。
待選特征的隨機化過程
(1)子樹從所有的待選特征中隨機選取一定的特征听绳。
(2)在選取的特征中選取最優(yōu)的特征颂碘。
下圖中,藍色的方塊代表所有可以被選擇的特征椅挣,也就是目前的待選特征头岔;黃色的方塊是分裂特征。 左邊是一棵決策樹的特征選取過程鼠证,通過在待選特征中選取最優(yōu)的分裂特征完成分裂切油。 右邊是一個隨機森林中的子樹的特征選取過程稠集。
隨機森林推廣算法
算法總結
RF的主要優(yōu)點
1.訓練可以并行化,對于大規(guī)模樣本的訓練具有速度的優(yōu)勢衫冻;
2.由于進行隨機選擇決策樹劃分特征列表,這樣在樣本維度比較高的時候,仍然具有比較高的訓練性能碟摆;
3.給以給出各個特征的重要性列表;
4.由于存在隨機抽樣,訓練出來的模型方差小,泛化能力強娩鹉;
5.RF實現(xiàn)簡單;
6.對于部分特征的缺失不敏感稚伍。
RF的主要缺點:
1..在某些噪音比較大的特征上,RF模型容易陷入過擬弯予;
2.取值比較多的劃分特征對RF的決策會產(chǎn)生更大的影響,從而有可能影響模型的效果;
示例:乳腺癌預測
在現(xiàn)實生活中个曙,機器學習的應用非常廣泛锈嫩,在醫(yī)學方面也發(fā)揮著非常重要的作用,下面就以一個宮頸癌預測的例子來簡要說明一下隨機森林算法的思想垦搬。
比如呼寸,小明的媽媽感覺身體非常不好,醫(yī)生通過詢問和調(diào)查猴贰,收集和小明媽媽的很多數(shù)據(jù)对雪,比如年齡,工作米绕,是否抽煙等等瑟捣,把這些數(shù)據(jù)輸入計算機,計算機就會給一個患有某種病的概率栅干,醫(yī)生則可以根據(jù)這個概率做出疾病的最終結果迈套,例如把這些數(shù)據(jù)輸入一個患有乳腺癌的模型,可如何構建這個模型呢?這是我們應該關注的問題碱鳞。構建此模型的步驟如下:
首先收集數(shù)據(jù)
這是最基礎也是最重要的過程桑李,為了方便,我們直接下載權威結構公開的數(shù)據(jù):
下載的地址如下:http://archive.ics.uci.edu/ml/datasets/Cervical+cancer+(Risk+Factors)
然后觀察目標屬性和特征特征屬性如下:
u'Age', u'Number of sexual partners', u'First sexual intercourse', u'Num of pregnancies', u'Smokes', u'Smokes (years)', u'Smokes (packs/year)', u'Hormonal Contraceptives', u'Hormonal Contraceptives (years)', u'IUD', u'IUD (years)', u'STDs', u'STDs (number)', u'STDs:condylomatosis', u'STDs:cervical condylomatosis', u'STDs:vaginal condylomatosis', u'STDs:vulvo-perineal condylomatosis', u'STDs:syphilis', u'STDs:pelvic inflammatory disease', u'STDs:genital herpes', u'STDs:molluscum contagiosum', u'STDs:AIDS', u'STDs:HIV', u'STDs:Hepatitis B', u'STDs:HPV', u'STDs: Number of diagnosis', u'STDs: Time since first diagnosis', u'STDs: Time since last diagnosis', u'Dx:Cancer', u'Dx:CIN', u'Dx:HPV', u'Dx', u'Hinselmann', u'Schiller', u'Citology', u'Biopsy'
最后就是建立模型,建立模型的步驟如下:
- 導入模塊芙扎。
#導入我們要用的包星岗,包括算法數(shù)據(jù)導入模塊,算法評估模塊戒洼,算法模塊俏橘,以及畫圖模塊。
最后要畫roc和auc曲線圖圈浇,因而導入相應的畫圖包寥掐。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
from sklearn import tree
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler,Imputer,LabelBinarizer
from sklearn import metrics#參數(shù),roc和auc
from sklearn.preprocessing import label_binarize#二值化
mpl.rcParams['font.sans-serif'] = [u'SimHei']
mpl.rcParams['axes.unicode_minus'] = False
- 導入數(shù)據(jù)
#這里的導入數(shù)據(jù)就是導入剛剛下載的數(shù)據(jù)
names = [u'Age', u'Number of sexual partners', u'First sexual intercourse',
u'Num of pregnancies', u'Smokes', u'Smokes (years)',
u'Smokes (packs/year)', u'Hormonal Contraceptives',
u'Hormonal Contraceptives (years)', u'IUD', u'IUD (years)', u'STDs',
u'STDs (number)', u'STDs:condylomatosis',
u'STDs:cervical condylomatosis', u'STDs:vaginal condylomatosis',
u'STDs:vulvo-perineal condylomatosis', u'STDs:syphilis',
u'STDs:pelvic inflammatory disease', u'STDs:genital herpes',
u'STDs:molluscum contagiosum', u'STDs:AIDS', u'STDs:HIV',
u'STDs:Hepatitis B', u'STDs:HPV', u'STDs: Number of diagnosis',
u'STDs: Time since first diagnosis', u'STDs: Time since last diagnosis',
u'Dx:Cancer', u'Dx:CIN', u'Dx:HPV', u'Dx', u'Hinselmann', u'Schiller',
u'Citology', u'Biopsy']#df.columns
path="datas/risk_factors_cervical_cancer.csv"
df = pd.read_csv(path)
print(df.shape)
查看數(shù)據(jù)磷蜀,查看一下總的數(shù)據(jù)
print(df.shape)
輸出結果如下:
(858, 36)
- 建劃分數(shù)據(jù)集
#.劃分測試集合訓練集
x=df.iloc[:,0:-4]
y=df.iloc[:,-4:]
x=x.replace("?", np.NAN)
#通過平局值來替換nan
imputer=Imputer(missing_values="NaN")
x=imputer.fit_transform(x,y)
x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.2,random_state=0)
print("訓練樣本數(shù)量:%d,特征屬性數(shù)目:%d,目標屬性數(shù)目:%d"%(x_train.shape[0],x_train.shape[1],y_train.shape[1]))
輸出的結果如下:
訓練樣本數(shù)量:686,特征屬性數(shù)目:32,目標屬性數(shù)目:4
- 模型構建和預測:
ss = MinMaxScaler()
x_train = ss.fit_transform(x_train)
x_test = ss.transform(x_test)
rf = RandomForestClassifier(n_estimators=50,criterion="gini",max_depth=1,random_state=10)
rf.fit(x_train,y_train)
score = rf.score(x_test,y_test)
- 模型的評估
print("準確率:%.2f%%"%(score*100))
forest_y_score = rf.predict_proba(x_test)
# print(forest_y_score)
#計算roc和auc
forest_fpr1, forest_tpr1, _ = metrics.roc_curve(label_binarize(y_test[names[-4]],classes=(0,1,2)).T[0:-1].T.ravel(), forest_y_score[0].ravel())
forest_fpr2, forest_tpr2, _ = metrics.roc_curve(label_binarize(y_test[names[-3]],classes=(0,1,2)).T[0:-1].T.ravel(), forest_y_score[1].ravel())
forest_fpr3, forest_tpr3, _ = metrics.roc_curve(label_binarize(y_test[names[-2]],classes=(0,1,2)).T[0:-1].T.ravel(), forest_y_score[2].ravel())
forest_fpr4, forest_tpr4, _ = metrics.roc_curve(label_binarize(y_test[names[-1]],classes=(0,1,2)).T[0:-1].T.ravel(), forest_y_score[3].ravel())
#AUC值
auc1 = metrics.auc(forest_fpr1, forest_tpr1)
auc2 = metrics.auc(forest_fpr2, forest_tpr2)
auc3 = metrics.auc(forest_fpr3, forest_tpr3)
auc4 = metrics.auc(forest_fpr4, forest_tpr4)
print ("Hinselmann目標屬性AUC值:", auc1)
print ("Schiller目標屬性AUC值:", auc2)
print ("Citology目標屬性AUC值:", auc3)
print ("Biopsy目標屬性AUC值:", auc4)
輸出的結果為:
準確率:89.53%
Hinselmann目標屬性AUC值: 0.984586262844781
Schiller目標屬性AUC值: 0.9629867495943752
Citology目標屬性AUC值: 0.9453082747431043
Biopsy目標屬性AUC值: 0.9642712276906437
- 畫auc曲線
plt.figure(figsize=(8, 6), facecolor='w')
plt.plot(forest_fpr1,forest_tpr1,c='r',lw=2,label=u'Hinselmann目標屬性,AUC=%.3f' % auc1)
plt.plot(forest_fpr2,forest_tpr2,c='b',lw=2,label=u'Schiller目標屬性,AUC=%.3f' % auc2)
plt.plot(forest_fpr3,forest_tpr3,c='g',lw=2,label=u'Citology目標屬性,AUC=%.3f' % auc3)
plt.plot(forest_fpr4,forest_tpr4,c='y',lw=2,label=u'Biopsy目標屬性,AUC=%.3f' % auc4)
plt.plot((0,1),(0,1),c='#a0a0a0',lw=2,ls='--')
plt.xlim(-0.001, 1.001)
plt.ylim(-0.001, 1.001)
plt.xticks(np.arange(0, 1.1, 0.1))
plt.yticks(np.arange(0, 1.1, 0.1))
plt.xlabel('False Positive Rate(FPR)', fontsize=16)
plt.ylabel('True Positive Rate(TPR)', fontsize=16)
plt.grid(b=True, ls=':')
plt.legend(loc='lower right', fancybox=True, framealpha=0.8, fontsize=12)
plt.title(u'隨機森林多目標屬性分類ROC曲線', fontsize=18)
plt.show()
結果如下圖所示:
分析:由于目標屬性含有多個召耘,在進行評估的時候應該考慮多個目標屬性的影響,從上圖看出褐隆,模型的整體效果還是挺不錯的污它。
7.比較不同樹的數(shù)量和不同深度下對模型的影響
# 比較不同樹數(shù)目、樹最大深度的情況下隨機森林的正確率
# 一般情況下庶弃,初始的隨機森林樹個數(shù)是100衫贬,深度1,如果需要我們再進行優(yōu)化操作
x_train2, x_test2, y_train2, y_test2 = train_test_split(x,y, test_size=0.5, random_state=0)
print("訓練樣本數(shù)量%d歇攻,測試樣本數(shù)量:%d" % (x_train2.shape[0], x_test2.shape[0]))
## 比較
estimators = [1, 50, 100, 500]
depth = [1, 2, 3, 7, 15]
err_list = []
for es in estimators:
es_list = []
for d in depth:
tf = RandomForestClassifier(n_estimators=es, criterion='gini', max_depth=d, max_features=None,
random_state=0)
tf.fit(x_train2, y_train2)
st = tf.score(x_test2, y_test2)
err = 1 - st
es_list.append(err)
print("%d決策樹數(shù)目固惯,%d最大深度,正確率:%.2f%%" % (es, d, st * 100))
err_list.append(es_list)
## 畫圖
plt.figure(facecolor='w')
i = 0
colors = ['r', 'b', 'g', 'y']
lw = [1, 2, 4, 3]
max_err = 0
min_err = 100
for es, l in zip(estimators, err_list):
plt.plot(depth, l, c=colors[i], lw=lw[i], label=u'樹數(shù)目:%d' % es)
max_err = max((max(l), max_err))
min_err = min((min(l), min_err))
i += 1
plt.xlabel(u'樹深度', fontsize=16)
plt.ylabel(u'錯誤率', fontsize=16)
plt.legend(loc='upper left', fancybox=True, framealpha=0.8, fontsize=12)
plt.grid(True)
plt.xlim(min(depth), max(depth))
plt.ylim(min_err * 0.99, max_err * 1.01)
plt.title(u'隨機森林中樹數(shù)目缴守、深度和錯誤率的關系圖', fontsize=18)
plt.show()
得到的結果如下: