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

时间:2018-07-21 14:21:09

标签: python scikit-learn naivebayes

我目前正在使用朴素贝叶斯算法进行一些分类。 为此,通常假设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%)。

如果您能给我您的想法,那将是很棒的。 当数据为多峰时,为什么高斯NB仍然可以工作?它适合吗?在文档/代码中我什么都找不到... 我的实现中有愚蠢的错误吗?为什么给出不同的结果?

非常感谢!

0 个答案:

没有答案