我目前正在使用朴素贝叶斯算法进行一些分类。 为此,通常假设 p(x|C_i) 是高斯分布。在这个假设下,我会假设当不满足这个假设时,即数据分布是高斯分布的混合时,这种方法表现不佳。 为此,我实现了一个非常基本的测试,一次使用 sklearn 中的 GaussianNB,一次使用我的自定义实现:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import accuracy_score
from sklearn.naive_bayes import GaussianNB
def gaussian(x, mu, sig):
return np.exp(-np.power(x - mu, 2.) / (2 * np.power(sig, 2.)))
x = np.arange(0, 10, 0.1)
MULTIMODAL = False # toggle for unimodal / multimodal
def class1_proba(x):
if MULTIMODAL:
return gaussian(x, 5, 2)
else:
return gaussian(x, 1, 2)
def class2_proba(x):
if MULTIMODAL:
return 1 * gaussian(x, 9, 2) + 1 * gaussian(x, 1, 2)
else:
return gaussian(x, 9, 2)
class1 = class1_proba(x)
class2 = class2_proba(x)
data_x = np.expand_dims(np.random.rand(10000) * 10, axis=1)
data_y = np.squeeze(np.argmax(np.asarray([class1_proba(data_x), class2_proba(data_x)]), axis=0))
model = GaussianNB()
model.fit(data_x, data_y)
predicted = model.predict(data_x)
print("NB:")
print(accuracy_score(data_y, predicted))
pC1 = data_y[data_y == 0].shape[0] / float(data_y.shape[0])
pC2 = data_y[data_y == 1].shape[0] / float(data_y.shape[0])
mean1 = np.mean(data_x[data_y == 0])
mean2 = np.mean(data_x[data_y == 1])
var1 = np.var(data_x[data_y == 0])
var2 = np.var(data_x[data_y == 1])
def get_prediction(x):
p1 = pC1 * gaussian(x, mean1, var1)
p2 = pC2 * gaussian(x, mean2, var2)
if p1 > p2:
return 0
else:
return 1
custom_prediction = []
for i in range(data_x.shape[0]):
custom_prediction.append(get_prediction(data_x[i]))
custom_prediction = np.asarray(custom_prediction)
print("Custom:")
print(accuracy_score(data_y, custom_prediction))
plt.plot(x, class1)
plt.plot(x, class2)
# plt.scatter(data_x, data_y)
plt.scatter(data_x, custom_prediction)
plt.show()
当每个 p(x|C_i) 遵循单个高斯分布时,两种方法都提供了非常好的预期精度 (99%)。 然而,然后 p(x|C_i) 变得更加复杂,我的简单方法失败了(这也是我所期望的),但 GaussianNB 仍然提供了非常好的结果(90% 准确率)。
如果您能告诉我您对此的想法,那就太好了。 为什么当数据是多模态时 GaussianNB 仍然有效?它适合这个吗?在文档/代码中我找不到任何东西...... 我的实现中有一个愚蠢的错误吗?为什么会产生不同的结果?
非常感谢!
我也遇到过同样的问题。 scikit learn 实现确实有秘诀。
他们使用的是对数概率,而你的代码则使用普通概率。
我已经修改了你的
gaussian
函数以充当对数概率。现在我在 unimodal
和 multimodal
状态下都得到了相同的结果。
def 高斯(x, mu, sig): return (1 / (np.sqrt(2 * np.pi * sig))) * np.exp(-np.power(x - mu, 2.) / (2 * sig))
对数概率防止数值下溢并提高稳定性。了解更多信息:https://stats.stackexchange.com/questions/483927/why-are-log-probabilities-useful
有关更多信息,请查看
_partial_fit
类方法中的 GaussianNB
。他们使用 epsilon 变量。 https://scikit-learn.org/stable/modules/ generated/sklearn.naive_bayes.GaussianNB.html