簡體   English   中英

scikit-learn .predict() 默認閾值

[英]scikit-learn .predict() default threshold

我正在研究不平衡類(5% 1)的分類問題。 我想預測類別,而不是概率。

在二元分類問題中,scikit 的classifier.predict()默認使用0.5 如果沒有,默認方法是什么? 如果是,我該如何更改?

在 scikit 中,一些分類器具有class_weight='auto'選項,但並非所有分類器都有。 使用class_weight='auto'class_weight='auto' .predict()使用實際人口比例作為閾值嗎?

什么是像一個分類,以做到這一點的方式MultinomialNB不支持class_weight 除了使用predict_proba()然后自己計算類。

可以使用clf.predict_proba()設置閾值

例如:

from sklearn.tree import DecisionTreeClassifier
clf = DecisionTreeClassifier(random_state = 2)
clf.fit(X_train,y_train)
# y_pred = clf.predict(X_test)  # default threshold is 0.5
y_pred = (clf.predict_proba(X_test)[:,1] >= 0.3).astype(bool) # set threshold as 0.3

scikit 的classifier.predict()默認使用0.5?

在概率分類器中,是的。 正如其他人所解釋的那樣,從數學的角度來看,這是唯一合理的閾值。

在像class_weight這樣不支持class_weight的分類器中這樣做的方法是什么?

您可以設置class_prior ,這是每個類y的先驗概率 P( y ) 。 這有效地改變了決策邊界。 例如

# minimal dataset
>>> X = [[1, 0], [1, 0], [0, 1]]
>>> y = [0, 0, 1]
# use empirical prior, learned from y
>>> MultinomialNB().fit(X,y).predict([1,1])
array([0])
# use custom prior to make 1 more likely
>>> MultinomialNB(class_prior=[.1, .9]).fit(X,y).predict([1,1])
array([1])

scikit learn 中二元分類的閾值是 0.5,哪個類對多類分類的概率最大。 在許多問題中,通過調整閾值可以獲得更好的結果。 但是,這必須小心完成,而不是在堅持測試數據上,而是通過對訓練數據進行交叉驗證。 如果您對測試數據的閾值進行任何調整,則只會過度擬合測試數據。

大多數調整閾值的方法基於接收器操作特性 (ROC)Youden's J 統計量,但也可以通過其他方法完成,例如使用遺傳算法進行搜索。

這是一篇同行評議期刊文章,描述了在醫學中這樣做:

http://www.ncbi.nlm.nih.gov/pmc/articles/PMC2515362/

據我所知,沒有在 Python 中執行此操作的軟件包,但在 Python 中使用蠻力搜索找到它相對簡單(但效率低下)。

這是一些執行此操作的 R 代碼。

## load data
DD73OP <- read.table("/my_probabilites.txt", header=T, quote="\"")

library("pROC")
# No smoothing
roc_OP <- roc(DD73OP$tc, DD73OP$prob)
auc_OP <- auc(roc_OP)
auc_OP
Area under the curve: 0.8909
plot(roc_OP)

# Best threshold
# Method: Youden
#Youden's J statistic (Youden, 1950) is employed. The optimal cut-off is the threshold that maximizes the distance to the identity (diagonal) line. Can be shortened to "y".
#The optimality criterion is:
#max(sensitivities + specificities)
coords(roc_OP, "best", ret=c("threshold", "specificity", "sensitivity"), best.method="youden")
#threshold specificity sensitivity 
#0.7276835   0.9092466   0.7559022

你似乎在這里混淆了概念。 閾值不是“通用分類器”的概念——最基本的方法是基於一些可調閾值,但大多數現有方法為分類創建了復雜的規則,這些規則不能(或至少不應該)被視為閾值。

所以首先 - 人們無法回答關於 scikit 分類器默認閾值的問題,因為沒有這樣的東西。

第二類加權與閾值無關,與分類器處理不平衡類的能力有關,它取決於特定的分類器。 例如 - 在 SVM 情況下,它是在優化問題中對松弛變量進行加權的方式,或者如果您願意的話 - 與特定類別相關的拉格朗日乘子值的上限。 將此設置為“自動”意味着使用一些默認啟發式方法,但再一次 - 它不能簡單地轉換為某種閾值。

另一方面,朴素貝葉斯直接從訓練集中估計類概率。 它被稱為“類先驗”,您可以使用“class_prior”變量在構造函數中設置它。

文檔

類的先驗概率。 如果指定,則不會根據數據調整先驗。

萬一有人訪問此線程,希望獲得即用型功能(python 2.7)。 在此示例中,截止旨在反映原始數據集df中事件與非事件的比率,而y_prob可能是.predict_proba方法的結果(假設分層訓練/測試拆分)。

def predict_with_cutoff(colname, y_prob, df):
    n_events = df[colname].values
    event_rate = sum(n_events) / float(df.shape[0]) * 100
    threshold = np.percentile(y_prob[:, 1], 100 - event_rate)
    print "Cutoff/threshold at: " + str(threshold)
    y_pred = [1 if x >= threshold else 0 for x in y_prob[:, 1]]
    return y_pred

隨意批評/修改。 希望在類平衡無法解決且數據集本身高度不平衡的極少數情況下它會有所幫助。

0.5與任何方式的人口比例無關。 它的概率輸出。 沒有“閾值”,如果一個類的概率為0.51,那么它似乎是最可能的類。 0.5如果總是應該使用的是*,並且沒有包使用不同的“閾值”。 如果您的概率分數是* ccurate且真正具有代表性*,那么您必須始終選擇最可能的類 否則只會降低您的准確性。 由於我們使用各種算法進行假設,我們不知道概率是正確的 - 但是你會違背模型所做的假設。

感到困惑的class_weight做什么。 改變類權重會增加較少表示的類中數據點的權重(對於過度表示的類減少/),以便每個類的“權重”相等 - 好像它們具有相同數量的正面和負面示例。 這是嘗試避免總是為最常見的類投票的分類器的常見技巧。 因為這樣,從學習算法的角度來看,這兩個類同樣很常見。

  • 注意:如果你害怕誤報/漏報,那么你可以選擇只接受一個類,如果它的概率滿足某個最小值。 但這並不會改變學習方式,也不會改變概率背后的含義。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM