在機器學習的分類問題中,我們都假設所有類別的分類代價是一樣的。但是事實上,不同分類的代價是不一樣的,比如我們通過一個用於檢測患病的系統來檢測馬匹是否能繼續存活,如果我們把能存活的馬匹檢測成患病,那么這匹馬可能就會被執行安樂死;如果我們把不能存活的馬匹檢測成健康,那么就會繼續喂養這匹馬。一個代價是錯殺一只昂貴的動物,一個代價是繼續喂養,很明顯這兩個代價是不一樣的。
性能度量
衡量模型泛化能力的評價標准,就是性能度量。除了基於錯誤率來衡量分類器任務的成功程度的。錯誤率指的是在所有測試樣例中錯分的樣例比例。但是,這樣卻掩蓋了樣例如何被錯分的事實。在機器學習中,有一個普遍試用的稱為混淆矩陣(confusion matrix)的工具,可以幫助人們更好地了解分類的錯誤。

利用混淆矩陣就可以更好地理解分類中的錯誤了。如果矩陣中的非對角元素均為0,就會得到一個完美的分類器。
正確率(Precision)、召回率(Recall)

正確率P = TP/(TP+FP),給出的是預測為正例的樣本中的真正正例的比例。
召回率R = TP/(TP+FN),給出的是預測為正例的真實正例占所有真實正例的比例。
另一個用於度量分類中的非均衡性的工具是ROC曲線(ROC curve),ROC代表接收者操作特征"Receiver Operating Characteristic"

ROC曲線的縱軸是“真正例率”,TPR=TP/(TP+FN)
橫軸是“假正例率”,FPR=FP/(TN+FP)
在理想的情況下,最佳的分類器應該盡可能地處於左上角,這就意味着分類器在假正例率很低的同時,獲得了很高的真正例率。
對不同的ROC曲線進行比較的一個指標就是曲線下的面積(AUC),AUC給出的是分類器的平均性能值。一個完美的分類器的AUC是1,而隨機猜測的AUC則為0.5。
若一個學習器的ROC曲線能把另一個學習器的ROC曲線完全包住,則這個學習器的性能比較好。
def plotROC(predStrengths, classLabels): #ROC曲線的繪制及AUC計算函數
import matplotlib.pyplot as plt
cur = (1.0,1.0) #cursor
ySum = 0.0 #variable to calculate AUC
numPosClas = sum(array(classLabels)==1.0)
yStep = 1/float(numPosClas); xStep = 1/float(len(classLabels)-numPosClas)
sortedIndicies = predStrengths.argsort()#get sorted index, it's reverse
fig = plt.figure()
fig.clf()
ax = plt.subplot(111)
#loop through all the values, drawing a line segment at each point
for index in sortedIndicies.tolist()[0]:
if classLabels[index] == 1.0:
delX = 0; delY = yStep;
else:
delX = xStep; delY = 0;
ySum += cur[1]
#draw line from cur to (cur[0]-delX,cur[1]-delY)
ax.plot([cur[0],cur[0]-delX],[cur[1],cur[1]-delY], c='b')
cur = (cur[0]-delX,cur[1]-delY)
ax.plot([0,1],[0,1],'b--')
plt.xlabel('False positive rate'); plt.ylabel('True positive rate')
plt.title('ROC curve for AdaBoost horse colic detection system')
ax.axis([0,1,0,1])
plt.show()
print "the Area Under the Curve is: ",ySum*xStep
mian.py
# coding:utf-8
# !/usr/bin/env python
import adaboost
if __name__ == '__main__':
datMat,classLabels = adaboost.loadDataSet("horseColicTraining2.txt")
weakClassArr,aggClassEst = adaboost.adaBoostTrainDS(datMat,classLabels,40)
# datMat1,classLabels1 = adaboost.loadDataSet("horseColicTest2.txt")
aggClassEst,sign = adaboost.adaClassify(datMat,weakClassArr)
print aggClassEst.T
adaboost.plotROC(aggClassEst.T, classLabels)

基於代價函數的分類器決策控制
為權衡不同類型錯誤所造成的不同損失,可為錯誤賦予“非均等代價”。

在“代價矩陣”中,將-1錯判成+1的代價(50),比把+1錯判成-1的代價(1)要高。
處理非均衡問題的數據抽樣方法
另外一種針對非均衡問題調節分類器的方法,就是對分類器的訓練數據進行改造。這可以通過欠抽樣或者過抽樣來實現。
過抽樣意味着復制樣例,而欠抽樣意味着刪除樣例。
