數據挖掘(三)分類模型的描述與性能評估,以決策樹為例


關於分類的第一部分我們要講一些關於分類的基本概念,然后介紹最基本的一種分類模型-決策樹模型,再基於此討論一下關於分類模型的性能評估。

===============================================================================

分類的直觀理解就是給定樣本的各類屬性,根據我們的模型或者某種規則將樣本划分到若干不同的類別中,划分目標是離散的就叫分類,如果是連續的我們就稱之為回歸。所以,分類的官方定義就是:通過學習得到一個目標函數f,把每個屬性集x映射到一個預先定義的類標號中。

分類模型按照目的划分可分為描述性建模和預測性建模。所謂描述性就是建立了一個分類模型之后,我們就可以得到哪些特征對哪些類別有決定性的作用,是一個解釋性的工具,而預測性是指建立完模型后我們拿來用在一個未知的樣本,確定它的類別。還有要說的一點就是,分類技術適合用於二元或者標稱類型的數據集,因為分類不考慮隱含在目標類中的序數關系,僅僅考慮樣本各屬性上的異同。

就像上面所說的,分類模型其實同時具有描述性和預測性,描述性要求模型可以最大程度上符合訓練數據,而預測性則要求模型在未知數據上有較好的預測能力。因此訓練誤差不是我們唯一的判別標准,較好的泛化能力也是我們的主要訴求。所以在訓練分類模型的時候,我們通常將數據划分成訓練集和檢驗集,其中訓練集用於建立模型,驗證集用於檢驗模型的泛化能力,當然這其中訓練集和檢驗集的划分還涉及到很多問題,比如說數據的不平衡啊,樣本是否符合同一分布等等,這里我們先不討論這些問題,但是得知道划分訓練集和檢驗集的必要性。

對於二元分類模型的性能通常根據模型正確和錯誤預測樣本計數進行評估,通常這些數字被存放在一個2*2的矩陣中,如下所示,我們稱之為混淆矩陣。

 

Predicted

1

0

Actual

1

a

b

0

c

d

其中,a,b,c,d分別是預測為1,0而實際是1,0的樣本個數,與混淆矩陣相關的概念有以下這么幾個

准確率:正確預測數除以預測總數。(a+d)/(a+b+c+d)

錯誤率:錯誤預測數除以預測總數。(b+c)/(a+b+c+d)

精確率:正確預測為正類的樣本數除以實際正類的的數目。a/(a+c)

召回率:正確預測為正類的樣本數除以預測正類的數目。a/(a+b)

混淆矩陣確實叫人有點混淆,其中比較有意思的就是精確率和召回率了,通俗地講,這兩個對應的就是“找的准”和“找的全”,精確率是指預測為正的樣本中真正為正的樣本的概率,召回率是指實際為正的樣本中被預測為正的樣本的概率。在知乎上看到一位同學舉得一個例子,預測一個人到底是不是罪犯的時候,我們抱着不冤枉一個好人的原則,可能要求模型的精確率比較高,這樣找出來的罪犯基本都是罪犯,盡管有可能召回率低導致漏掉一些真正的罪犯,但這樣可以盡量避免冤枉好人;另一個場景,預測地震的時候,我們希望召回率盡量高,因為這樣我們可以避免漏過任何一次地震,盡管有可能導致精確率不高有很多次誤報,但我們依然不希望有任何一次地震被漏報。說了這么多,相信你對這些二元分類模型的描述有點概念了,接下來我們講講如何在Python中划分訓練檢驗集以及使用這些評價參數。這里用的一個數據集是sklearn自帶的乳腺癌數據,根據30個特征將該腫瘤划分成初期和惡性,分類器用的決策樹。

from sklearn.datasets import load_breast_cancer
from sklearn.cross_validation import train_test_split
from sklearn import tree
from sklearn.metrics import confusion_matrix,classification_report

breast_cancer=load_breast_cancer()
data=breast_cancer.data
target=breast_cancer.target
x_train,x_test,y_train,y_test=train_test_split(data,target,test_size=0.3,random_state=0)
clf=tree.DecisionTreeClassifier(random_state=0)
clf.fit(x_train,y_train)
y_pred=clf.predict(x_test)
print '============================================================'
print 'Confusion Matrix'
print confusion_matrix(y_test,y_pred,labels=[1,0])
print '============================================================'
print classification_report(y_test,y_pred,labels=[1,0])

結果如下

============================================================

Confusion Matrix

[[97 11]

 [ 459]]

============================================================

            precision    recall  f1-score  support

 

         1       0.96      0.90     0.93       108

         0       0.84      0.94     0.89        63

 

avg / total       0.92     0.91      0.91       171

 

通過confusion_matrix和classification_report這兩個函數我們可以輕易地得到混淆矩陣及模型的精確率和召回率等等考慮在這個場景下,我們應該更注重模型的哪個參數呢?病人來看病我們的原則是啥,絕對不要漏掉一個真正的病患!因為有病誤診為沒病可能會要了病人的命,而沒病誤診為有病只會讓別人噴我是個庸醫,想忽悠別人多花點治療費,所以從醫生的立場來看,追求的是召回率一定要高,這才是負責任的做法。所以啊,學完這個是不是對醫生有多點理解呢,畢竟別人背負了你生命的責任,條件允許的話就聽醫生的吧,該查的查,該治的治~

===============================================================================接下來我們介紹介紹決策樹算法。之前在機器學習系列寫的決策樹在這里,傳送門http://blog.csdn.net/sinat_22594309/article/details/59090895

在那篇文章里我介紹了關於決策樹兩個最重要的部分,一是如何選擇划分的屬性,常用的標准有信息增益,信息增益比和Gini系數;二是決策樹的損失函數,我們如何評價一個樹的優劣,一方面看分類之后的信息增益,另一方面也要考慮模型的復雜度,同時這些也是我們優化決策樹的依據。這些內容我在這里就不重復了,大家有興趣可以自己去看看。

相信很多同學對熵總是有點不理解,雖然知道該他可以衡量一個系統的混亂度,但究竟是為什么,我這里可以給出一個比較直觀的解釋,相信可以幫助大家理解。

1 假設袋子里有四個球,A,B,C,D,每個被抽到的概率都為1/4,現在隨機從袋子里拿一個,讓你猜這是哪個球。

最佳的策略是啥呢?先猜是不是AB,是的話就在AB之中,再問是A嗎就可確定;不是的話就在CD之中,再問是C嗎就能確定。所以正確猜中的次數的期望就是1/4*2*4=2。

2 袋子里還是四個球,A,B,C,D,但是每個被抽中的概率變為1/2,1/4,1/8,1/8,還是隨機從袋子里面拿一個猜是哪個球。

這個時候最佳的策略是啥?先猜是不是A,因為A概率最大很有可能一次猜中,不是的話就在BCD中,由於這三者中B概率最大,所以猜是不是B,不是的話,再猜是不是C就能確定是C還是D了。那么這樣的話,猜中的次數的期望就是1/2*1+1/4*2+1/8*3*2=1.75。如果我們沒有采取最佳的策略而是沿用1的策略呢,猜中的次數的期望就是1/2*2+1/4*2+1/8*2*2=2。

寫到這里,不知道機智的你發現了沒,每一種策略都對應了一個概率分布。以第二個問題為例,策略1對應的概率分布為(1/2,1/4,1/8,1/8),策略2對應的概率分布為(1/4,1/4,1/4,1/4),然后對應的猜中次數的期望就是數據的實際分布乘以策略對應概率分布倒數的對數之和,這個形式是不是有點眼熟呢,如果策略使用的是真是分布,那么這個猜中次數的期望就是熵。很明顯,熵越大,猜中所需的次數越多,說明原始數據越混亂。但是如果采用策略所使用的不是真實分布,那么算出來的猜中次數期望會變大,我們將之稱為交叉熵。然后不同策略對應的交叉熵之差,我們就稱為相對熵。總結起來,如下:

真實分布為Pk(k=1,2,3,4…),策略所用分布為qk(k=1,2,3,4…)


此外,關於決策樹的特點,我覺得可以稍微總結一下:

1 決策樹是一種構建分類模型的非參數方法,它不假定類和其屬性服從一定的概率分布。

2 決策樹的建立並不需要特別大的計算開銷,所以往往能很快完成構建,預測的速度也很快。

3 決策樹相對比較容易解釋,特別是在小數據集上。

4 決策樹對冗余屬性不是很敏感,因為一旦有某個屬性被選中,與其相關的冗余屬性會自動被忽略。

5 決策樹的決策邊界通常是直線,也就是只涉及到某一個屬性,但其實也可以做斜決策樹,邊界為多個屬性的組合,不過這樣的計算開銷會變得很大,因為屬性組合是在太多,可以通過一開始構造符合屬性然后使用正常決策樹算法達到構建斜決策樹的目的。

以上就是關於決策樹的一些補充內容,很多人覺得決策樹算法相對初級一點,實際使用也只是在一些比較小的數據集上,但是畢竟它是Random Forest,GDBT等各種樹啊森林的基礎,所以也別小看它啦。另外,只要你想,決策樹在訓練集上的正確率可以做到非常非常高,這就引來了我們下一個話題,過擬合及分類器性能評價。

首先什么是過擬合?通俗的來說,就是我們為了追求訓練集上的錯誤率盡可能低,將模型構建的十分復雜,導致構建的模型在測試集上表現效果反而很差。導致這種情況的原因有哪些呢?

1、 噪聲。由於過分追求訓練集的正確率,導致訓練集中的一些噪聲或例外也被擬合在我們的模型之中,這樣分類器在實際使用時出現較高的錯誤率就是不可避免的了。

2、 缺乏代表性的樣本。這種情況通常出現在數據集比較小的情況,由於訓練數據不夠或者很不平衡,導致對於某些種類缺乏代表性樣本,模型實際拿來預測的時候效果不好也就是意料之中的事兒了。

3、 多重比較過程。首先解釋一下多重比較過程,假如預測某一件事成功的概率為0.1,對於某個個體來說,確實成功的概率不高,但假如讓50個人同時來預測這件事,假設他們是獨立的,那么50個人中有人成功的概率會很高。這在決策樹構建的過程中也是這樣,我們往往會設定一個閾值,然后用增益是否大於這個閾值來決定是否要拓展決策樹,然而數據的屬性是很多的,我們在選擇的時候其實就相當於是一個多重比較的過程,這樣找到一個划分節點的幾率就會大大增加,但其實這樣是有欺騙性的。

那么如何避免過擬合的情況發生呢?由於過擬合往往出現在對數據的過分擬合導致模型太復雜,所以在決策樹中,決定是否添加一個節點的時候,除了訓練誤差我們還可以添加一個復雜度懲罰項,這樣就綜合考慮了訓練誤差和模型復雜度。

當然,在決策樹種最常見的用於防止過擬合的方法就是剪枝了。

剪枝分為兩種,一種是在決策樹構建過程中進行剪枝。也就是通過設定增益的閾值或者葉節點的樣本數等等,防止構建太深的決策樹導致過擬合,但這也面臨一個閾值選擇的問題,因為閾值設置太大,導致對數據利用不足,容易欠擬合,但是閾值太小又起不到防止過擬合的作用。比較常見的做法是利用確認集,也就是將訓練集划分成訓練集和確認集,在訓練集上用不同的超參數訓練模型,然后在驗證集上驗證,取驗證集上誤差率最小的超參數所確定的模型。

既然說到了驗證集,我們就順便提一下交叉驗證吧,交叉驗證是一種很好的評估分類器性能的方法,當然根據這個性能評價我們可以完成比如上面所說的超參數選擇,還有模型啊特征的選擇。交叉驗證具體的做法就是將訓練集分成若干份,每次選擇其中一份作為驗證集,其他的用作訓練集,這樣的過程可以重復若干次,保證每份數據都被用作驗證集一次,這樣若干次計算出來的誤差總和就可以作為我們評價一個分類器性能的參考。感覺平時最常用的就是10折交叉驗證,極端情況也有留一驗證,這樣的做法雖然充分利用了數據來訓練,但是檢驗的誤差方差比較大。下面給出一個在Python中利用交叉驗證來選擇超參數的簡單例子,還是用的上面的乳腺癌數據,優化的超參數是樹的深度。

from sklearn.cross_validation import cross_val_score
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn import tree
breast_cancer=load_breast_cancer()
data=breast_cancer.data
target=breast_cancer.target
max_depth=np.linspace(1,15,15,endpoint=True)
scores_final=[]
for depth in max_depth:
clf=tree.DecisionTreeClassifier(random_state=0,max_depth=depth)
scores=cross_val_score(clf,data,target,cv=10,scoring='accuracy')
print 'max_depth=%f ,scores=%f'%(depth,scores.mean())
scores_final.append(scores.mean())
from matplotlib import pyplot as plt
plt.plot(max_depth,scores_final,'r-',lw=2)
plt.xlabel('max_depth')
plt.ylabel('CV scores')
plt.grid()
plt.show()

結果如下

max_depth=1.000000 ,scores=0.892966

max_depth=2.000000 ,scores=0.921164

max_depth=3.000000 ,scores=0.910543

max_depth=4.000000 ,scores=0.922858

max_depth=5.000000 ,scores=0.928092

max_depth=6.000000 ,scores=0.924705

max_depth=7.000000 ,scores=0.919411

max_depth=8.000000 ,scores=0.917563

max_depth=9.000000 ,scores=0.917563

max_depth=10.000000 ,scores=0.917563

max_depth=11.000000 ,scores=0.917563

max_depth=12.000000 ,scores=0.917563

max_depth=13.000000 ,scores=0.917563

max_depth=14.000000 ,scores=0.917563

max_depth=15.000000 ,scores=0.917563


從上面畫的圖中我們可以看出,一開始由於樹的深度比較淺,導致模型有點欠擬合,后來隨着樹的深度逐漸加深,我們看到交叉驗證的得分逐漸上升,在樹深度為5的時候得分達到最高。此后,樹的深度繼續增加但CV的得分反而降低了,原因就在於過於復雜的樹有可能導致數據有點過擬合了,效果反而不好,這樣我們最終選擇的超參數-樹的深度就是5。

還有一種就是在決策樹完全構建完成后進行剪枝,通過用葉節點或者樹中最常見的分代替子樹,自下而上直至樹不能被優化。后剪枝的效果往往比先剪枝好,但是當某個子樹被剪后,用於它的計算資源就浪費了。

關於分類器的性能評價的話,除了上面所說的交叉驗證之外,其它的多半是一些采樣的方法,包括提前划分訓練集和確認集啊,隨機二次抽樣或者說有放回抽樣等等,我想大家有興趣可以自己去看看,但最常用的應該還是交叉驗證吧。

這次我們主要討論了和分類相關的一些概念以及決策樹模型的特點,最后講了一些關於過擬合和分類器性能評估(主要是交叉驗證)的內容,下一次會介紹一些所謂更加高級的分類算法,但是這次我們所提到的這些概念和方法下次還是用得到~

Have a nice day~~~



注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
  © 2014-2022 ITdaan.com 联系我们: