我正在研究不平衡类(5%1)的分类问题。我想预测班级,而不是概率。
在二进制分类问题中,scikit的classifier.predict()
默认使用0.5
?
如果没有,那么默认方法是什么?如果有,我该如何更改?
在scikit中,某些分类器具有class_weight='auto'
选项,但并非所有分类器都具有class_weight='auto'
选项。使用.predict()
,MultinomialNB
会将实际人口比例用作阈值吗?
在class_weight
这样不支持predict_proba()
的分类器中执行此操作的方法是什么?除了使用{{1}}然后自己计算类。
答案 0 :(得分:35)
是scikit的
classifier.predict()
默认使用0.5?
在概率分类器中,是的。正如其他人所解释的那样,这是数学观点上唯一明智的门槛。
在不支持
class_weight
的MultinomialNB等分类器中执行此操作的方法是什么?
您可以设置class_prior
,即每个班级 y 的先验概率P( y )。这有效地改变了决策边界。 E.g。
# 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])
答案 1 :(得分:27)
对于二元分类,scikit学习中的阈值为0.5,无论哪个类具有多类分类的最大概率。在许多问题中,通过调整阈值可以获得更好的结果。但是,这必须小心谨慎,而不是在保持测试数据上,而是通过对训练数据的交叉验证。如果您对测试数据进行了任何阈值调整,那么您只是过度拟合测试数据。
调整阈值的大多数方法都基于receiver operating characteristics (ROC)和Youden's J statistic,但也可以通过其他方法完成,例如使用遗传算法进行搜索。
这是一篇同行评审期刊文章,描述了在医学中这样做:
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
答案 2 :(得分:14)
可以使用class ViewController: UIViewController {
@IBOutlet weak var iv: UIImageView!
@IBOutlet weak var tf: UITextField!
@IBAction func doGo(_ sender: Any) {
let s = tf.text!
let s2 = NSAttributedString(string: s, attributes:
[.font:UIFont(name: "Georgia", size: 100)!,
.foregroundColor: UIColor.yellow])
let sz = iv.image!.size
let r = UIGraphicsImageRenderer(size:sz)
iv.image = r.image {
_ in
iv.image!.draw(at:.zero)
s2.draw(at: CGPoint(x:30, y:sz.height-150))
}
}
@IBAction func doRevert(_ sender: Any) {
config()
}
func config() {
iv.image = UIImage(named:"nice.jpg")
}
override func viewDidLoad() {
super.viewDidLoad()
config()
}
}
例如:
clf.predict_proba()
答案 3 :(得分:8)
你似乎在这里混淆概念。阈值不是“通用分类器”的概念 - 最基本的方法基于一些可调阈值,但是大多数现有方法创建了复杂的分类规则,这些规则不能(或至少不应该)被视为阈值。
首先 - 因为没有这样的事情,人们无法回答你的scikit分类器默认阈值的问题。
第二类加权不是关于阈值,关于分类器处理不平衡类的能力,它是依赖于特定分类器的东西。例如 - 在SVM情况下,它是在优化问题中加权松弛变量的方法,或者如果您愿意,则是与特定类相关联的拉格朗日乘数值的上限。将其设置为“auto”意味着使用一些默认启发式,但再一次 - 它不能简单地转换为某些阈值。
另一方面朴素贝叶斯直接估计训练集中的类概率。它被称为“类优先”,您可以使用“class_prior”变量在构造函数中设置它。
班级的先验概率。如果指定,则不会根据数据调整先验。
答案 4 :(得分:2)
0.5与人口比例无关。它的概率输出。没有“阈值”,如果一个类的概率为0.51,那么它似乎是最可能的类。 0.5如果总是应该使用的是*,并且没有包使用不同的“阈值”。如果您的概率分数是* ccurate且真正具有代表性*,那么您必须始终选择最可能的类。否则只会降低您的准确性。由于我们使用各种算法进行假设,我们不知道概率是正确的 - 但是你会违背模型所做的假设。
你 对class_weight的作用感到困惑。改变类权重会增加较少表示的类中数据点的权重(对于过度表示的类减少/),以便每个类的“权重”相等 - 好像它们具有相同数量的正面和负面示例。这是尝试避免总是为最常见的类投票的分类器的常见技巧。因为这样,从学习算法的角度来看,这两个类同样很常见。
答案 5 :(得分:1)
如果有人访问此线程,希望使用即用型功能(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
随意批评/修改。希望它在极少数情况下有助于课堂平衡是不可能的,而且数据集本身也是高度不平衡的。