多模态数据的自定义朴素贝叶斯实现与 sklearn.naive_bayes

问题描述 投票:0回答:1

我目前正在使用朴素贝叶斯算法进行一些分类。 为此,通常假设 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 仍然有效?它适合这个吗?在文档/代码中我找不到任何东西...... 我的实现中有一个愚蠢的错误吗?为什么会产生不同的结果?

非常感谢!

python scikit-learn naivebayes
1个回答
0
投票

我也遇到过同样的问题。 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

skikit-learn 实现中还有其他一些小事情:

有关更多信息,请查看

_partial_fit
类方法中的
GaussianNB
。他们使用 epsilon 变量。 https://scikit-learn.org/stable/modules/ generated/sklearn.naive_bayes.GaussianNB.html

© www.soinside.com 2019 - 2024. All rights reserved.