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 解释为线性模型。
这意味着您在MultinomialNB
的coef_
中实际看到的是与给定特定类别的每个特征相关联的概率的对数。或者,更准确地说:
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.Bernoulli 的朴素贝叶斯分类器;如何使用模型进行预测?
sklearn.naive_bayes中Bernoulli NB几种朴素贝叶斯分类器