在小白我的第一篇文里就提出過一個問題路克,就是現(xiàn)在的教程都太“分散”太“板塊”,每一個知識點都單獨用一個例子樊销,機器學(xué)習(xí)算法里也是這樣的饵蒂,可能邏輯回歸用葡萄酒的案例講声诸,決策樹又用鳶尾花的數(shù)據(jù)集了。今天退盯,我們只用乳腺癌數(shù)據(jù)集彼乌,專門來看一看二分類問題的實戰(zhàn)應(yīng)用泻肯。
導(dǎo)入包
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 解決坐標(biāo)軸刻度負(fù)號亂碼
plt.rcParams['axes.unicode_minus'] = False
# 解決中文亂碼問題
plt.rcParams['font.sans-serif'] = ['Simhei']
%matplotlib inline
導(dǎo)入數(shù)據(jù)
# 讀入癌癥數(shù)據(jù)集
from sklearn import datasets
from sklearn.model_selection import train_test_split
cancer=datasets.load_breast_cancer()
X=cancer.data
y=cancer.target
X_train,X_test,y_train,y_test=train_test_split(X,y)
print('訓(xùn)練集維度:{}\n測試集維度:{}'.format(X_train.shape,X_test.shape))
訓(xùn)練集維度:(426, 30)
測試集維度:(143, 30)
一、邏輯回歸
我們先來看看分類里最簡單卻又是最經(jīng)典的邏輯回歸:
1.1 sklearn實戰(zhàn)
廢話不多說慰照,看看用sklearn怎么做邏輯回歸灶挟。
from sklearn.linear_model import LogisticRegression
from sklearn import metrics
lr = LogisticRegression() # 實例化一個LR模型
lr.fit(X_train,y_train) # 訓(xùn)練模型
y_prob = lr.predict_proba(X_test)[:,1] # 預(yù)測1類的概率
y_pred = lr.predict(X_test) # 模型對測試集的預(yù)測結(jié)果
fpr_lr,tpr_lr,threshold_lr = metrics.roc_curve(y_test,y_prob) # 獲取真陽率、偽陽率毒租、閾值
auc_lr = metrics.auc(fpr_lr,tpr_lr) # AUC得分
score_lr = metrics.accuracy_score(y_test,y_pred) # 模型準(zhǔn)確率
print([score_lr,auc_lr])
得到準(zhǔn)確率為0.9720, AUC值為0.9954稚铣。這個結(jié)果可以說是相當(dāng)不錯了。
可以查看一下LR模型的默認(rèn)參數(shù)墅垮。
lr
1.2 對邏輯回歸的理解
這里的乳腺癌數(shù)據(jù)集有30個特征惕医,我們需要根據(jù)這些特征去判斷一個是否會患乳腺癌。不妨換一個思路算色,如果按照我們熟悉的線性回歸抬伺,這個問題該怎么思考呢?那么我們會根據(jù)每個人自身的特征給他打個分灾梦,我們規(guī)定分?jǐn)?shù)越高就越不健康峡钓。進(jìn)一步,我們希望把每個人的得分進(jìn)行歸一化若河,讓分?jǐn)?shù)限制在[0,1]這個區(qū)間能岩,這樣,打分的問題就變成了概率問題萧福。
那怎么把得分變成概率呢拉鹃?有很多方法,最經(jīng)典的就要說一說sigmoid函數(shù)了统锤。
https://www.cnblogs.com/xitingxie/p/9924523.html
我隨意貼了一個網(wǎng)上找的比較全的sigmoid函數(shù)解析毛俏,偷個懶。
1.3 損失函數(shù)
在這里饲窿,不得不說一下煌寇,小白我剛開始接觸邏輯回歸的時候,就掉入了這個坑逾雄,LR帶有回歸二字阀溶,我想當(dāng)然地就認(rèn)為損失函數(shù)肯定和回歸一樣嘛,真實值和預(yù)測值之間差值的平方和嘛鸦泳!but银锻,它本質(zhì)其實還是分類問題啊,分類模型的損失函數(shù)做鹰,是交叉熵击纬。
熵這個問題可能又會讓很多初學(xué)者很困擾了,我剛開始學(xué)的時候也是一知半解钾麸,在這里分享一篇覺得寫的很好的交叉熵的文:
http://www.reibang.com/p/8a0ad237b0ed
另外貼一篇損失函數(shù)推導(dǎo):
https://www.cnblogs.com/shayue/p/10520414.html
1.4 求解損失函數(shù)(max_iter)
使用梯度下降更振。這個經(jīng)典方法我在這兒也不過多說了炕桨,同樣,貼個鏈接大家可以自己去看:
http://www.reibang.com/p/93d9fea7f4c2
我們這里只來看一看max_iter這個參數(shù)肯腕,它表示梯度下降法中最大迭代次數(shù)献宫,max_iter越大,代表步長越小实撒,模型迭代時間越長姊途。我們來看一看效果。
trainList=[] # 用來記錄訓(xùn)練集得分
testList=[] # 用來記錄測試集得分
for i in range(1,101,10):
lr=LogisticRegression(max_iter=i).fit(X_train,y_train)
trainList.append(metrics.accuracy_score(y_train,lr.predict(X_train)))
testList.append(metrics.accuracy_score(y_test,lr.predict(X_test)))
plt.figure(figsize=(20, 5))
plt.style.use('seaborn-colorblind')
plt.plot(range(1,101,10),trainList,color='orange',label='train')
plt.plot(range(1,101,10),testList,color='red',label='train')
我們可以看到知态,基本迭代到30次的時候測試集和訓(xùn)練集的得分就不再提高了捷兰,繼續(xù)增大迭代次數(shù)也只是浪費了資源。
1.5 如何防止過擬合(penalty & C)
邏輯回歸和線性回歸一樣肴甸,為了防止過擬合寂殉,可以在損失函數(shù)的后面添加正則項。同樣的原在,我也貼個詳解的連接在后面,但大家只要知道我們有l(wèi)1和l2兩種正則項彤叉,sklearn里大多數(shù)算法默認(rèn)的都是l2范式庶柿,它會讓特征前的系數(shù)盡量小防止過擬合,但不會像l1范式那樣直接將某些系數(shù)減小到0:
https://blog.csdn.net/red_stone1/article/details/80755144
在sklearn中秽浇,通過penalty選擇l1還是l2范式浮庐,而通過C控制對系數(shù)的懲罰力度。要注意的是柬焕,C是加在損失函數(shù)前面的审残,而不是加在正則項前面,因此C越大斑举,表示對系數(shù)的懲罰力度越小搅轿,模型越容易過擬合。
lr1=LogisticRegression(penalty='l1').fit(X_train,y_train)
lr2=LogisticRegression(penalty='l2').fit(X_train,y_train)
print('L1正則得分:{}\nL2正則得分:{}'.format(metrics.accuracy_score(y_test,lr1.predict(X_test)),metrics.accuracy_score(y_test,lr2.predict(X_test))))
當(dāng)然富玷,這個數(shù)據(jù)集過于理想璧坟,因此使用l1和l2基本沒有不同。
list1=[] # 用來記錄l1正則得分
list2=[] # 用來記錄l2正則得分
for i in np.linspace(0.05,1,20):
lr1=LogisticRegression(penalty='l1',C=i).fit(X_train,y_train)
lr2=LogisticRegression(penalty='l2',C=i).fit(X_train,y_train)
list1.append(metrics.accuracy_score(y_test,lr1.predict(X_test)))
list2.append(metrics.accuracy_score(y_test,lr2.predict(X_test)))
plt.figure(figsize=(20, 5))
plt.style.use('seaborn-colorblind')
plt.plot(np.linspace(0.05,1,20),list1,color='orange',label='l1-test')
plt.plot(np.linspace(0.05,1,20),list2,color='red',label='l2-test')
plt.legend(loc='lower right')
plt.show()
我們一般是要防止過擬合赎懦,所以對C的調(diào)參一般是在[0,1]之間調(diào)整雀鹃。可以看到励两,加入C之后黎茎,l1和l2的區(qū)別就出來了。C取默認(rèn)值1.0的時候其實就是得分最高的了当悔,再調(diào)整C意義不大傅瞻。
1.6 如何處理樣本不均衡(class_weight)
pd.Series(y).value_counts()
在乳腺癌的數(shù)據(jù)集中迁酸,正例:負(fù)例是357:212,并不存在樣本不均衡問題俭正。但在實際現(xiàn)實問題建模時候奸鬓,樣本不均衡卻是常態(tài),比如在處理信用違約時掸读,不違約的人總是多數(shù)串远,而違約的人是非常少的,除了我們常用的上采用的方法儿惫,還可以通過class_weight參數(shù)調(diào)節(jié)澡罚,在這里就不舉例了。
二肾请、支持向量機
支持向量機在深度學(xué)習(xí)沒有興起的時候那可是不可撼動的王者地位留搔,當(dāng)然,它這么好用铛铁,也可想而知隔显,這家伙肯定是很難很復(fù)雜的。
2.1 sklearn實戰(zhàn)
同樣饵逐,廢話不多說括眠,先來看支持向量機算法在乳腺癌數(shù)據(jù)集上的表現(xiàn)。
from sklearn.svm import SVC
from sklearn import metrics
svc = SVC().fit(X_train,y_train)
y_prob = svc.decision_function(X_test) # 決策邊界距離
y_pred = svc.predict(X_test) # 模型對測試集的預(yù)測結(jié)果
fpr_svc,tpr_svc,threshold_svc = metrics.roc_curve(y_test,y_prob) # 獲取真陽率倍权、偽陽率掷豺、閾值
auc_svc = metrics.auc(fpr_svc,tpr_svc) # 模型準(zhǔn)確率
score_svc = metrics.accuracy_score(y_test,y_pred)
print([score_svc,auc_svc])
可以得到,在不調(diào)任何參數(shù)的情況下薄声,準(zhǔn)確率為0.6294, AUC值為0.9126当船。我們會發(fā)現(xiàn)AUC值很高,但是準(zhǔn)確率卻不高默辨。其實德频,通過metrics.precision_score(y_test,y_pred)和metrics.recall_score(y_test,y_pred),我們會發(fā)現(xiàn)精確率很低只有0.6294廓奕,但召回率為1.0抱婉。(什么是精確率和召回率大家也可以自行百度下)
同樣,我們可以看一下svc的默認(rèn)參數(shù)桌粉。
svc
2.2 對支持向量機的理解
我們之前說邏輯回歸的時候蒸绩,通過最好理解的線性回歸舉例,通過sigmoid函數(shù)將一個本該是線性回歸的問題轉(zhuǎn)化為了一個線性分類的問題铃肯。那么患亿,這個時候問題來了,如果數(shù)據(jù)不是線性可分的呢?這時候支持向量機就展現(xiàn)出它的核技術(shù)的魅力了步藕,通過將低維度的數(shù)據(jù)映射到高維度惦界,從而將非線性的問題轉(zhuǎn)換成一個線性問題。
是不是聽著就覺得很繞咙冗?這是不可避免的沾歪,因為邏輯回歸還可以用例子來理解,但是支持向量機基本上就是從數(shù)學(xué)推導(dǎo)的角度來選取一個最優(yōu)的分類方法雾消。但大家只要知道灾搏,算法是存在“進(jìn)化”的,邏輯回歸解決了線性回歸到線性分類的難題立润,而支持向量機解決了線性分類到非線性分類的難題狂窑。
支持向量機其實說白了,就是想通過數(shù)學(xué)的方法桑腮,看看怎么樣能夠?qū)?shù)據(jù)“最大程度”地分離開泉哈,就要找這個“最大程度”,我們叫“邊際”(margin)最大破讨。而支持向量機的名字也是有原因的丛晦,“邊際”其實只由兩類中離分割線最近的點所決定,這些點叫“支持向量”添忘。
另外采呐,需要注意的是,在邏輯回歸的損失函數(shù)求解過程中搁骑,我們是將不同類的標(biāo)簽記作1和0的,但是在支持向量機的損失函數(shù)求解中又固,我們是將不同類標(biāo)簽記作1和-1的仲器,這么做是對我們求解有用的。
2.3 損失函數(shù)
我們之前說過仰冠,支持向量機的求解目標(biāo)就是max margin乏冀,讓“邊際”最大。那么怎么去求這個“邊際”呢洋只?
原理鄙人的畫圖水平有限辆沦,在上圖中,我們假設(shè)有一條線w·x+b=0可以將兩類點分開识虚,這條線往上平移到紅色類的邊緣處肢扯,這條線就是w·x+b=1,;往下平移到橙色類邊緣處担锤,這條線就是w·x+b=-1蔚晨。那有人就會問,向上移應(yīng)該是截距項增加啊肛循,那也應(yīng)該是w·x+b=-1懊蟆银择?而且,為什么上下移動就是等號右邊加一個單位呢累舷?同志們浩考,我們這里只是一個記號而已,要知道被盈,w和b都是一個符號析孽,兩邊可以同時除以-1,也可以同時除以其他數(shù)害捕,等號左邊也同時除以绿淋,這時候我們會得到新的w和b,但是我們同樣用w和b表示而已尝盼,不必糾結(jié)吞滞。
我們?nèi)绻僭O(shè)Xc和Xd是決策邊界上的兩個點,那么就有W·Xc+b=0盾沫,W·Xd+b=0裁赠,相減得到W·(Xc-Xd)=0。兩個向量點積為0赴精,則說明垂直佩捞,w和我們要求的邊際d是相同方向。
這時候蕾哟,假設(shè)Xa和Xb分別在上邊緣和下邊緣上一忱,那么就有W·Xa+b=1,W·Xb+b=-1谭确,相減得到W·(Xa-Xb)=2帘营。
我們對兩邊同時除以W的模,則有W/||W|| · (Xa-Xb) = 2/||W||逐哈,線性代數(shù)過關(guān)的小伙伴們能很快反應(yīng)過來芬迄,等號左邊其實就是Xa和Xb兩點連線這個向量在w方向的投影,其實也就是我們要求的兩條邊界線之間的距離d昂秃。那么禀梳,我們的求解目標(biāo)也很明確了,就是要max d肠骆,也就是max 2/||W||算途。我們將這個問題轉(zhuǎn)化一下,其實也就是min 1/2 * W2哗戈,當(dāng)然郊艘,外加一個限制條件,y * (w*x+b)>1 (w·x+b>1表示的是紅色的點,這時候y=1纱注;w·x+b<-1表示的是橙色的點畏浆,這時候y=-1。這下明白將兩類標(biāo)簽定義為1和-1而不是1和0的用處了吧)狞贱。
當(dāng)然刻获,這只是我們弄出損失函數(shù)的第一步,這個帶約束條件的最小化問題仍然是不好求解的瞎嬉。之后蝎毡,我們還需要用拉格朗日乘數(shù)法,將上面這個約束條件去掉氧枣,轉(zhuǎn)化為一個拉格朗日函數(shù)沐兵,我叫它第二步;再之后便监,我們要用拉格朗日對偶的性質(zhì)扎谎,去求解我們第二步得到的拉格朗日函數(shù),這是第三步烧董。這就是我歸納的三步走毁靶。當(dāng)然,這些數(shù)學(xué)推導(dǎo)還是有點復(fù)雜和繁瑣的逊移,我在這里也不推導(dǎo)了预吆,想了解的自行百度。
2.4 損失函數(shù)求解
支持向量機損失函數(shù)的求解就不是梯度下降法這么簡單的了胳泉,涉及太多數(shù)學(xué)推導(dǎo)拐叉,在這里我同樣也不寫了,大家一定要自行去了解序列最小優(yōu)化算法(SMO)扇商,貼一篇吧:
https://blog.csdn.net/qq_39521554/article/details/80723770
2.5 核函數(shù)的選擇(kernel & gamma)
接下來是SVM中第一個重要參數(shù)巷嚣,kernel。我們之前也說過了钳吟,支持向量機之所以這么牛,就是因為核技術(shù)窘拯。核函數(shù)是什么呢红且?我們之前提到了,很多數(shù)據(jù)在本身的維度是線性不可分的涤姊,那怎么辦呢暇番?那就將數(shù)據(jù)映射到更高維度的空間去看一看,可能就可以線性分割了思喊。核函數(shù)可以做什么呢壁酬?1、不需要去知道將低維映射到高維所需要用的函數(shù);2舆乔、可以先在低維度進(jìn)行點積運算岳服,再直接映射到高緯度,大大減少了運算量希俩;3吊宋、避免了維度詛咒。
參數(shù)kernel常用的共有四個:“l(fā)inear”颜武、“poly”璃搜、“rbf”、“sigmoid”鳞上。默認(rèn)的并且是最常使用的是高斯核rbf这吻。效果最差的、也是最不常用的是“sigmoid”篙议。當(dāng)然唾糯,它們各自有各自出場的場合。
我們可以來看下三種核函數(shù)(只看‘linear’涡上、‘rbf’趾断、‘sigmoid’,'poly'跑出結(jié)果是非常久的吩愧,這里就不實驗了)在乳腺癌數(shù)據(jù)集上的表現(xiàn)芋酌。
from sklearn.svm import SVC
from sklearn import metrics
kernelList = ['linear','rbf','sigmoid']
for kernel in kernelList:
svc = SVC(kernel=kernel).fit(X_train,y_train)
y_pred = svc.predict(X_test)
score_svc = metrics.accuracy_score(y_test,y_pred)
print(score_svc)
可以看到,‘linear’雁佳、‘rbf’脐帝、‘sigmoid’核表現(xiàn)分別為0.9790、0.6503糖权、0.6503堵腹,可以看到秒梳,線性核表現(xiàn)最優(yōu)彭雾,高斯核作為默認(rèn)參數(shù)準(zhǔn)確率卻比較低。因為乳腺癌數(shù)據(jù)集是一個線性可分?jǐn)?shù)據(jù)集峦朗。
如果我們對數(shù)據(jù)標(biāo)準(zhǔn)化一下呢禁偎?
# 讀入癌癥數(shù)據(jù)集
from sklearn import datasets
from sklearn.model_selection import train_test_split
cancer=datasets.load_breast_cancer()
X=cancer.data
y=cancer.target
# 數(shù)據(jù)標(biāo)準(zhǔn)化
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaler.fit(X)
X= scaler.transform(X)
X_train,X_test,y_train,y_test=train_test_split(X,y)
再執(zhí)行一下上面的三個核函數(shù)腿堤,‘linear’、‘rbf’如暖、‘sigmoid’的得分分別為0.9790笆檀、
0.9860、0.9790盒至。我們會發(fā)現(xiàn)酗洒,高斯核的表現(xiàn)一下子變成了number one士修,“sigmoid”居然也都跟線性核打平手了。
因為涉及到算“距離”樱衷,所以可以看到棋嘲,量綱問題就非常重要了。
因為高斯核(rbf)在處理線性和非線性問題時都很好用箫老,所以我們重點看高斯核封字。
我們可以調(diào)的就是公式里的gamma值。我們試著來調(diào)一下gamma耍鬓。
score_gamma=[]
gammaList=np.logspace(-10,1,50)
for gamma in gammaList:
svc = SVC(gamma=gamma).fit(X_train,y_train)
score_gamma.append(svc.score(X_test,y_test))
print('gamma={}時,得分最高={}'.format(gammaList[score_gamma.index(max(score_gamma))],max(score_gamma)))
gamma=0.004291934260128779時,得分最高=0.986013986013986阔籽。
當(dāng)然,也可以將調(diào)參曲線畫出來牲蜀。
plt.plot(gammaList,score_gamma)
如果選用的是'poly'多項式核函數(shù)笆制,還可以去調(diào)一下degree,大家可自行去試涣达。
2.6 如何避免過擬合(重要參數(shù)C)
現(xiàn)實很殘酷在辆,基本是不可能找到一條線能夠?qū)深慄c完全分開的《忍Γ或者舉一個更明顯一點的例子匆篓,還是上面那個圖,如果這時候新來了兩個點1和點2寇窑,很明顯原來的那條分界線就不能將兩類點完全分開了鸦概,這時候藍(lán)色的新邊界才是能將點完全分開的最好分割線。但也有個問題甩骏,使用新的分割線窗市,兩類點之間的距離,也就是“邊際”(margin)就變窄了饮笛,很有可能這兩個點本身就是異常點咨察,這時候就需要我們?nèi)?quán)衡,是盡可能地將兩類點分開呢福青,還是讓大多數(shù)點分離得更遠(yuǎn)摄狱。前者呢,就叫做硬間隔(hard margin)无午,這時候有過擬合的風(fēng)險二蓝;后者呢,叫做軟間隔(soft margin)指厌,會有欠擬合的風(fēng)險。
為了防止過擬合呢踊跟,我們會給損失函數(shù)加上一個“松弛度”踩验,但作為權(quán)衡鸥诽,會在這個“松弛度”前面加上一個懲罰系數(shù)C,防止對分錯的點“太過寬松”箕憾。
需要注意的是牡借,邏輯回歸中也有這么一個懲罰系數(shù)C,但它不是在正則項前面袭异,而SVM中的C是在“松弛度”的前面钠龙,兩個C效果卻是一樣的,C太大御铃,模型容易過擬合碴里;C太小,模型容易欠擬合上真。
score_C=[]
CList=np.linspace(0.01,30,50)
for i in CList:
svc = SVC(C=i).fit(X_train,y_train)
score_C.append(svc.score(X_test,y_test))
print('C={}時,得分最高={}'.format(CList[score_C.index(max(score_C))],max(score_C)))
C=0.6220408163265306時,得分最高=0.986013986013986咬腋。
同樣可以畫出來看一看。
plt.plot(CList,score_C)
2.7 如何處理不均衡問題
同樣睡互,調(diào)節(jié)class_weight根竿。
三、K近鄰(knn算法)
knn可以說是分類中原理最簡單最容易理解的了就珠。
3.1 sklearn實戰(zhàn)
from sklearn.neighbors import KNeighborsClassifier
from sklearn import metrics
knn = KNeighborsClassifier().fit(X_train,y_train)
y_prob = knn.predict_proba(X_test)[:,1]
y_pred = knn.predict(X_test)
fpr_knn,tpr_knn,threshold_knn = metrics.roc_curve(y_test,y_prob)
auc_knn = metrics.auc(fpr_knn,tpr_knn)
score_knn = metrics.accuracy_score(y_test,y_pred)
print([score_knn,auc_knn])
knn算法的準(zhǔn)確率為0.9441, AUC值為0.9766寇壳。
這個結(jié)果其實已經(jīng)很不錯的,如果再將數(shù)據(jù)標(biāo)準(zhǔn)化呢妻怎?
我們將數(shù)據(jù)標(biāo)準(zhǔn)化后壳炎,得出準(zhǔn)確率為0.9930, AUC值為0.9977。這么一個最簡單的分類算法蹂季,在乳腺癌數(shù)據(jù)集上的表現(xiàn)居然如此之好冕广。
knn
3.2 knn原理
knn就是字面的意思,選定k個最近的點偿洁,看這k個點中占比最多的類作為標(biāo)簽撒汉。毫無疑問,k的取值至關(guān)重要涕滋。
3.3 K值選擇(n_neighbors)
score_K=[]
KList=range(2,13)
for k in KList:
knn = KNeighborsClassifier(n_neighbors=k).fit(X_train,y_train)
score_K.append(knn.score(X_test,y_test))
print('K={}時,得分最高={}'.format(KList[score_K.index(max(score_K))],max(score_K)))
K=5時,得分最高=0.9930睬辐。
plt.plot(KList,score_K)
3.4 k個點的權(quán)重(weights)
我們要去想這么一個問題,假設(shè)一個點周圍最近的5個點中宾肺,有2個點離得非常近溯饵,有3個點離得很遠(yuǎn)。這時候锨用,雖然3個點的類占大頭丰刊,但直覺告訴我們,它很可能是和離得比較近的那2個點是一類的增拥。所以啄巧,可能我們需要給離得近的那2個點更大一點的權(quán)重寻歧。
weights的默認(rèn)值是'uniform',表示所有最近鄰樣本權(quán)重都一樣秩仆。如果是"distance"码泛,則權(quán)重和距離成反比例,即距離預(yù)測目標(biāo)更近的近鄰具有更高的權(quán)重澄耍,這樣在預(yù)測類別或者做回歸時噪珊,更近的近鄰所占的影響因子會更加大。當(dāng)然齐莲,我們也可以自定義權(quán)重痢站,即自定義一個函數(shù),輸入是距離值铅搓,輸出是權(quán)重值瑟押。這樣我們可以自己控制不同的距離所對應(yīng)的權(quán)重。
from sklearn.neighbors import KNeighborsClassifier
from sklearn import metrics
knn = KNeighborsClassifier(weights='distance').fit(X_train,y_train)
y_prob = knn.predict_proba(X_test)[:,1]
y_pred = knn.predict(X_test)
fpr_knn,tpr_knn,threshold_knn = metrics.roc_curve(y_test,y_prob)
auc_knn = metrics.auc(fpr_knn,tpr_knn)
score_knn = metrics.accuracy_score(y_test,y_pred)
print([score_knn,auc_knn])
將weights改為'distance'之后星掰,會發(fā)現(xiàn)多望,精確度為0.9930,而AUC的值竟然上升到了0.9991氢烘。
3.5 距離計算方式(metric)
knn可以使用的距離度量較多怀偷,一般來說默認(rèn)的歐式距離,但knn里默認(rèn)的是‘minkowski’播玖∽倒ぃ可以來看下不同的距離計算方式下模型的表現(xiàn)。
list=['euclidean','manhattan','chebyshev','minkowski']
for i in list:
knn = KNeighborsClassifier(metric=i).fit(X_train,y_train)
print(knn.score(X_test,y_test))
可以看到蜀踏,euclidean歐氏距離和minkowski閔可夫斯基距離得分最高维蒙,同為0.9930,manhattan曼哈頓距離次之為0.9790果覆,chebyshev切比雪夫距離的效果最差為0.9510颅痊。
四、決策樹
接下來我們進(jìn)入到樹這個大類里了局待,前面三種算法基本都涉及到一個距離的計算斑响,但是樹卻不用,因此也并不需要標(biāo)準(zhǔn)化(乳腺癌的數(shù)據(jù)集標(biāo)準(zhǔn)化之后反而降低了得分)钳榨。
4.1sklearn實戰(zhàn)
from sklearn import tree
from sklearn import metrics
dtc = tree.DecisionTreeClassifier() # 建立決策樹模型
dtc.fit(X_train,y_train) # 訓(xùn)練模型
y_prob = dtc.predict_proba(X_test)[:,1] # 預(yù)測1類的概率
y_pred = dtc.predict(X_test) # 模型對測試集的預(yù)測結(jié)果
fpr_dtc,tpr_dtc,threshod_dtc= metrics.roc_curve(y_test,y_prob) # 獲取真陽率舰罚、偽陽率、閾值
score_dtc = metrics.accuracy_score(y_test,y_pred)
auc_dtc = metrics.auc(fpr_dtc,tpr_dtc)
print([score_dtc,auc_dtc])
決策樹得分0.9441薛耻,AUC值為0.9443营罢。
dtc
4.2 決策樹原理
關(guān)于決策樹的原理也是可以查到很多了,只需要知道這些概念:
①信息量:-lnP
②熵:信息量的期望值(-∑PlnP)
③gini:和信息熵類似(∑P(1-P))
④信息增益
⑤信息增益率
⑥預(yù)剪枝方法:預(yù)剪枝方法:1限制深度饼齿;2限制葉子結(jié)點的樣本個數(shù)愤钾;3對每次分裂的信息增益設(shè)定閾值瘟滨。
⑦搞清楚ID3、C4.5能颁、Cart樹:
ID3的局限性:1信息增益存在過度擬合的缺點。2不能直接處理連續(xù)型變量倒淫。3對缺失值敏感伙菊。
C4.5& cart改進(jìn):1使用信息增益率。2對連續(xù)型的自動分箱敌土。
關(guān)于熵:
http://www.reibang.com/p/8a0ad237b0ed
4.3 如何衡量信息純度(criterion)
決策樹需要找出最佳的分枝方法镜硕,衡量的指標(biāo)就是信息“不純度”,“不純度”越低返干,說明類別分的越純兴枯,也就是分類越好。
criterion這個參數(shù)就是用來選擇用何種方式來衡量這個“不純度”矩欠,提供了信息熵(entropy)和基尼系數(shù)(gini)兩種方法财剖,上面有提到過。但是這個指標(biāo)基本我們也不用去調(diào)癌淮,因為sklearn中用的是cart二叉樹的方法躺坟,cart樹的衡量指標(biāo)就是gini。
4.4 如何防止過擬合(max_depth & min_samples_leaf & max_features & min_impurity_decrease)
大家一定要知道乳蓄,樹是天生過擬合的算法咪橙,包括之后的隨機森林,甚至于以樹為基礎(chǔ)分類器的集成學(xué)習(xí)算法虚倒,都存在這樣一個過擬合的屬性美侦。
要防止樹的過擬合,第一個要提的就是max_depth魂奥,這也是防止過擬合最好的神器菠剩,在高維度地樣本量時非常好用。
depthList=np.arange(3,10)
score=[]
for i in depthList:
dtc = tree.DecisionTreeClassifier(max_depth=i).fit(X_train,y_train)
score.append(dtc.score(X_test,y_test))
print('最優(yōu)深度為{}捧弃,最佳得分是{}'.format(depthList[score.index(max(score))],max(score)))
最優(yōu)深度為6赠叼,最佳得分是0.9441。
plt.plot(depthList,score)
min_samples_leaf則限定每個葉子節(jié)點上的最小樣本個數(shù)违霞,防止最后分的太細(xì)嘴办。
max_features限制分枝時考慮的特征個數(shù),超過限制個數(shù)的特征都會被舍棄买鸽,也是用來限制高維度數(shù)據(jù)的過擬合的涧郊。
min_impurity_decrease則限制信息增益的大小,信息增益小于設(shè)定數(shù)值的分枝不會發(fā)生眼五。
其實可以通過網(wǎng)格搜索來確定以上這些參數(shù)的最佳組合妆艘。
from sklearn import tree
from sklearn import metrics
from sklearn.model_selection import GridSearchCV
params={'max_depth':[*np.arange(3,10)]
,'min_samples_leaf':[*np.arange(1,50,5)]
,'min_impurity_decrease':[*np.linspace(0,0.5,20)]}
dtc = tree.DecisionTreeClassifier()
GS = GridSearchCV(dtc, params, cv=10).fit(X_train,y_train)
GS.best_params_
GS.best_score_
得到最佳參數(shù){'max_depth': 4, 'min_impurity_decrease': 0.0, 'min_samples_leaf': 1}彤灶,交叉驗證最佳得分0.9343∨可以看到幌陕,加了別的參數(shù)的時候,最優(yōu)深度就不再是6而是4了汽煮。
4.5 樹的可視化
# 樹的可視化
import graphviz
from sklearn.tree import export_graphviz
dtc = tree.DecisionTreeClassifier().fit(X_train,y_train)
export_graphviz(dtc,out_file='DecisionTree.dot',class_names=['0','1'],impurity=False,filled=True)
with open('DecisionTree.dot') as f:
dot_graph=f.read()
graphviz.Source(dot_graph)
五搏熄、隨機森林
隨機森林,顧名思義暇赤,就是很多棵樹組合在一起心例。
5.1 sklearn實戰(zhàn)
from sklearn.ensemble import RandomForestClassifier
from sklearn import metrics
rfc = RandomForestClassifier() # 建立隨機森林分類器
rfc.fit(X_train,y_train) # 訓(xùn)練隨機森林模型
y_prob = rfc.predict_proba(X_test)[:,1] # 預(yù)測1類的概率
y_pred=rfc.predict(X_test) # 模型對測試集的預(yù)測結(jié)果
fpr_rfc,tpr_rfc,threshold_rfc = metrics.roc_curve(y_test,y_prob) # 獲取真陽率、偽陽率鞋囊、閾值
auc_rfc = metrics.auc(fpr_rfc,tpr_rfc) # AUC得分
score_rfc = metrics.accuracy_score(y_test,y_pred) # 模型準(zhǔn)確率
print([score_rfc,auc_rfc])
模型準(zhǔn)確率為0.9580止后,AUC值為0.9942。
rfc
5.2 到底種多少棵樹(n_estimators)
我們可以在5.1中看到隨機森林默認(rèn)的n_estimators是10溜腐,顯然译株,對于集成學(xué)習(xí)來說,10棵樹的數(shù)量是偏少了的逗扒。好像更新的版本之后n_estimators默認(rèn)值會變?yōu)?00古戴。我們來看下隨著建的樹越多,訓(xùn)練集和測試集數(shù)據(jù)的得分會有什么樣的變化矩肩。
from sklearn.ensemble import RandomForestClassifier
from sklearn import metrics
train_score=[]
test_score=[]
for i in range(10,101):
rfc = RandomForestClassifier(n_estimators=i,random_state=13).fit(X_train,y_train)
train_score.append(rfc.score(X_train,y_train))
test_score.append(rfc.score(X_test,y_test))
plt.figure(figsize=(20, 5))
plt.plot(range(10,101),train_score,color='orange',label='train')
plt.plot(range(10,101),test_score,color='red',label='test')
plt.legend(loc='lower right')
plt.show()
可以看到现恼,隨著樹的數(shù)量增多,訓(xùn)練集的效果明顯變好黍檩,測試集的得分有所上升叉袍,但變化不大。初步目測刽酱,n_estimators在60左右效果是最好的喳逛。
5.3 如何防止過擬合
這個跟樹是幾乎一樣,因為咱本身也是樹組成的棵里。調(diào)節(jié)幾個重要參數(shù)就好了:max_depth润文、min_samples_leaf、max_features殿怜、min_impurity_decrease典蝌。
六、二分類模型評價指標(biāo)
二分類模型評價指標(biāo)圍繞混淆矩陣展開头谜,這個也太經(jīng)典了骏掀,不在這兒詳說了:
https://blog.csdn.net/qq_27575895/article/details/81476871
以隨機森林為例,看一看precision和recall值。
metrics.precision_score(y_test,y_pred) # 精確率
metrics.recall_score(y_test,y_pred) # 召回率
隨機森林模型下精確率和召回率均為0.9759截驮。
plt.style.use('bmh')
plt.figure(figsize=(13,10))
plt.plot(fpr_lr,tpr_lr,label='lr') # 邏輯回歸
plt.plot(fpr_svc,tpr_svc,label='svc') # 支持向量機模型
plt.plot(fpr_knn,tpr_knn,label='knn') # K近鄰
plt.plot(fpr_dtc,tpr_dtc,label='dtc') # 決策樹
plt.plot(fpr_rfc,tpr_rfc,label='rfc') # 隨機森林
plt.legend(loc='lower right',prop={'size':25})
plt.xlabel('偽陽率')
plt.ylabel('真陽率')
plt.title('ROC曲線')
plt.show()
當(dāng)然笑陈,小白也是機器學(xué)習(xí)初學(xué)者,有什么理解錯誤的地方也歡迎指正葵袭。這篇文也是針對初學(xué)者做的一個總結(jié)涵妥,希望能夠有幫助。本文后續(xù)還會不斷更新坡锡,加入新的分類算法妹笆,加入新的調(diào)參參數(shù)。