sklearn naive bayes MultinomialNB:尽管我有 2 个类,为啥我只得到一个带系数的数组?

Posted

技术标签:

【中文标题】sklearn naive bayes MultinomialNB:尽管我有 2 个类,为啥我只得到一个带系数的数组?【英文标题】:sklearn naive bayes MultinomialNB: Why do I get only one array with coefficients although I have 2 classes?sklearn naive bayes MultinomialNB:尽管我有 2 个类,为什么我只得到一个带系数的数组? 【发布时间】:2021-08-29 15:11:16 【问题描述】:

我已经训练了一个朴素贝叶斯 MultinomialNB 模型来预测短信是否为垃圾邮件。

我按预期获得了 2 个课程:

nb = MultinomialNB(alpha=0.0)
nb.fit(X_train, y_train)

print(nb.classes_)
#Output: ['ham' 'spam']

但是当我输出系数时,我只得到 1 个数组。

print(nb.coef_)
#Output: [[ -7.33025958  -6.48296172 -32.55333508 ...  -9.52748415 -32.55333508
  -32.55333508]]

我已经对另一个数据集做了同样的事情。有 5 个而不是 2 个类,它起作用了,我得到了一个包含 5 个数组的矩阵。

这是整个代码:

sms = pd.read_csv("spam-sms.csv", header=0, encoding = "ISO-8859-1")

X = sms.iloc[:, 1].values
X_clean = X[pd.notnull(X)]
y = sms.iloc[:,0].values
y_clean = y[pd.notnull(y)]



vectorizer = CountVectorizer()
X_cnt = vectorizer.fit_transform(X_clean)

X_train, X_test, y_train, y_test = train_test_split(X_cnt, y_clean,
test_size=0.2, random_state=0)

nb = MultinomialNB(alpha=0.0)
nb.fit(X_train, y_train)

y_pred = nb.predict(X_test)

print(nb.coef_)
print(nb.classes_)

Link to dataset

这里是它与 5 个类一起使用的代码

reviews = pd.read_csv("amazon-unlocked-mobile.csv", encoding='utf-8')
X = reviews.iloc[:,4].values
X_clean = X[pd.notnull(X)]
y = reviews.iloc[:,3].values
y_clean = y[pd.notnull(X)]

vectorizer = CountVectorizer()
X_cnt = vectorizer.fit_transform(X_clean)

X_train, X_test, y_train, y_test = train_test_split(X_cnt, y_clean,
test_size=0.2, random_state=0)

nb = MultinomialNB(alpha=0.0)
nb.fit(X_train, y_train)

y_predicted = nb.predict(X_test)

print(nb.coef_)
print(nb.classes_)

Linkt to dataset

【问题讨论】:

【参考方案1】:

TL;DR: 访问 feature_log_prob_ 属性以检索所有类的特征的所有日志概率。 coef_ 是对它们的镜像,但在二进制情况下仅返回类 1 (True) 的值。


MultinomialNB 的问题在于它不是线性分类器,实际上不计算系数来确定决策函数。假设您有一个具有特定值的特征向量,它通过计算样本作为特定类别的条件概率来工作。然后将概率最高的类视为最可能的类。

线性模型,如LogisticRegression,为其coef_ 属性声明以下内容:

coef_:形状为 (1, n_features) 或 (n_classes, n_features) 的 ndarray 决策函数中的特征系数。

当给定的问题是二进制时,coef_ 的形状为 (1, n_features)

出于兼容性原因,MultinomialNB 仍然具有 coef_ 属性,并且显然还会在像您这样的二进制情况下返回形状为 (1, n_features) 的数组。

但要了解它实际返回的内容,您应该查看documentation:

coef_:形状的ndarray(n_classes,n_features) 镜像 feature_log_prob_ 用于将 MultinomialNB 解释为线性模型。

这意味着您在MultinomialNBcoef_ 中实际看到的是与给定特定类别的每个特征相关联的概率的对数。或者,更准确地说:

feature_log_prob_:形状的ndarray(n_classes,n_features) 给定类别的特征的经验对数概率,P(x_i|y)

由于coef_ 只是feature_log_prob_ 的镜像,您可以通过访问feature_log_prob_ 来获取所有这些日志概率:

from sklearn.naive_bayes import MultinomialNB
import numpy as np
import random


random.seed(10)

X = np.array([1, 0, 0]*100).reshape(-1, 3)
y = np.array([random.choice([0, 1]) for _ in range(100)])

clf = MultinomialNB()
clf.fit(X, y)

print(clf.coef_)

>>> [[-0.03571808 -4.04305127 -4.04305127]]

print(clf.feature_log_prob_)

>>> [[-0.0416727  -3.8918203  -3.8918203 ]
 [-0.03571808 -4.04305127 -4.04305127]]

在示例中,您可以看到coef_ 只返回了类 1 的日志概率,而 feature_log_prob_ 返回了 0 和 1 的概率。

理解这些值代表什么以及它们与线性模型的系数不同是非常重要的。因此,根据您的特定用例,它们可能有用也可能没用。

我认为文档在这方面可以做得更好。但我想这不会成为未来的问题:

自 0.24 版起已弃用:coef_ 在 0.24 中已弃用,并将在 1.1 中删除(重命名为 0.26)

【讨论】:

我误解了 OP 的问题。感谢您指出。

以上是关于sklearn naive bayes MultinomialNB:尽管我有 2 个类,为啥我只得到一个带系数的数组?的主要内容,如果未能解决你的问题,请参考以下文章

如何纠正 sklearn.naive_bayes 中的 sample_weight?

sklearn中的naive bayes算法

使用 Sklearn.naive_bayes.Bernoulli 的朴素贝叶斯分类器;如何使用模型进行预测?

sklearn.naive_bayes中Bernoulli NB几种朴素贝叶斯分类器

朴素贝叶斯(Naive Bayes)及python实现(sklearn)

sklearn naive bayes MultinomialNB:尽管我有 2 个类,为啥我只得到一个带系数的数组?