如何为 scikit-learn 的朴素贝叶斯指定先验概率

Posted

技术标签:

【中文标题】如何为 scikit-learn 的朴素贝叶斯指定先验概率【英文标题】:How to specify the prior probability for scikit-learn's Naive Bayes 【发布时间】:2015-09-02 23:18:00 【问题描述】:

我正在将 scikit-learn 机器学习库 (Python) 用于机器学习项目。我正在使用的算法之一是高斯朴素贝叶斯实现。 GaussianNB() 函数的属性之一如下:

class_prior_ : array, shape (n_classes,)

我想手动更改之前的类,因为我使用的数据非常倾斜,并且召回其中一个类非常重要。通过为该类分配高先验概率,召回率应该会增加。

但是,我不知道如何正确设置属性。我已经阅读了以下主题,但它们的答案对我不起作用。

How can the prior probabilities manually set for the Naive Bayes clf in scikit-learn?

How do I know what prior's I'm giving to sci-kit learn? (Naive-bayes classifiers.)

这是我的代码:

gnb = GaussianNB()
gnb.class_prior_ = [0.1, 0.9]
gnb.fit(data.XTrain, yTrain)
yPredicted = gnb.predict(data.XTest)

我认为这是正确的语法,我可以通过处理值找出哪个类属于数组中的哪个位置,但结果保持不变。也没有给出错误。

从 scikit-learn 库中设置 GaussianNB 算法属性的正确方法是什么?

Link to the scikit documentation of GaussianNB

【问题讨论】:

【参考方案1】:

@Jianxun Li:其实在 GaussianNB 中有一种设置先验概率的方法。它被称为“先验”,可作为参数使用。请参阅文档: “参数:先验:类数组,形状(n_classes,) 类的先验概率。如果指定,则不会根据数据调整先验。” 那我举个例子吧:

from sklearn.naive_bayes import GaussianNB
# minimal dataset
X = [[1, 0], [1, 0], [0, 1]]
y = [0, 0, 1]
# use empirical prior, learned from y
mn = GaussianNB()
print mn.fit(X,y).predict([1,1])
print mn.class_prior_

>>>[0]
>>>[ 0.66666667  0.33333333]

但是如果你改变了先验概率,它会给出一个不同的答案,我相信这就是你正在寻找的。​​p>

# use custom prior to make 1 more likely
mn = GaussianNB(priors=[0.1, 0.9])
mn.fit(X,y).predict([1,1])
>>>>array([1])

【讨论】:

好收获。此功能是在提出问题后添加的。 github.com/scikit-learn/scikit-learn/commit/…【参考方案2】:

在 scikit-learn 中实现的 GaussianNB() 不允许你设置类先验。如果您阅读在线文档,您会看到 .class_prior_ 是一个属性,而不是参数。一旦适合 GaussianNB(),您就可以访问 class_prior_ 属性。它是通过简单地计算训练样本中不同标签的数量来计算的。

from sklearn.datasets import make_classification
from sklearn.naive_bayes import GaussianNB


# simulate data with unbalanced weights
X, y = make_classification(n_samples=1000, weights=[0.1, 0.9])
# your GNB estimator
gnb = GaussianNB()
gnb.fit(X, y)

gnb.class_prior_
Out[168]: array([ 0.105,  0.895])

gnb.get_params()
Out[169]: 

您会发现估算器足够聪明,可以考虑重量不平衡的问题。所以你不必手动指定先验。

【讨论】:

嗯,这确实解释了很多。您是否知道任何方法可以将分类器引导到某个方向?在我的例子中,一个类的召回比另一个类的整体精度和召回更重要。谢谢 @PepijnvanDiepen 在不更改代码的情况下,有一种方法:如果召回第 1 类很重要,则添加标签为第 1 类的每个训练示例的额外副本。这将导致第 1 类具有更高的先验概率,这将使算法更频繁地预测第 1 类。

以上是关于如何为 scikit-learn 的朴素贝叶斯指定先验概率的主要内容,如果未能解决你的问题,请参考以下文章

scikit-learn 朴素贝叶斯类库使用小结

SciKit-learn - 训练高斯朴素贝叶斯分类器

NLTK 和 scikit-learn 中的伯努利朴素贝叶斯结果不同

Scikit-learn 使用朴素贝叶斯进行 10 折交叉验证的多类分类

在 python 中使用 BernoulliNB(朴素贝叶斯分类器)scikit-learn 的简单示例 - 无法解释分类

朴素贝叶斯分类器是不好的估计器