【发布时间】:2019-03-28 06:23:36
【问题描述】:
我正在用 Python 实现一个朴素贝叶斯分类器(作为大学作业的一部分,所以 Python 是必需的)。我让它工作,它产生的结果与sklearn.naive_bayes.MultinomialNB 大致相同。但是,与 sklearn 实现相比,它确实很慢。
假设特征值是0到max_i范围内的整数,类标签也是0到max_y范围内的整数。示例数据集如下所示:
>>> X = np.array([2,1 1,2 2,2 0,2]).reshape(4,2) # design matrix
>>> print(X)
[[2 1]
[1 2]
[2 2]
[0 2]]
>>> y = np.array([0, 1, 2, 0 ]) # class labels
>>> print(y)
[0 1 2 0]
现在,作为处理联合对数似然之前的中间步骤,我需要计算类条件似然(即P(x_ij | y) 使得矩阵ccl 包含给定类 c 的特征 j 中值 k 的概率。对于上面的例子,这样一个矩阵的输出将是:
>>> print(ccl)
[[[0.5 0. 0.5]
[0. 0.5 0.5]]
[[0. 1. 0. ]
[0. 0. 1. ]]
[[0. 0. 1. ]
[0. 0. 1. ]]]
>>> print(ccl[0][1][1]) # prob. of value 1 in feature 1 given class 0
0.5
我实现的代码如下所示:
N, D = X.shape
K = np.max(X)+1
C = np.max(y)+1
ccl = np.zeros((C,D,K))
# ccl = ccl + alpha - 1 # disregard the dirichlet prior for this question
# Count occurences of feature values given class c
for i in range(N):
for d in range(D):
ccl[y[i]][d][X[i][d]] += 1
# Renormalize so it becomes a probability distribution again
for c in range(C):
for d in range(D):
cls[c][d] = np.divide(cls[c][d], np.sum(cls[c][d]))
因此,由于 Python 循环很慢,这也变得很慢。 我试图通过对每个特征值进行一次热编码来缓解这个问题(所以如果特征值在 [0,1,2] 范围内,a 2 变为:[0,0,1] 等等。)并总结像这样。虽然,我认为调用了太多的 np 函数,所以计算仍然需要太长时间:
ccl = np.zeros((C,D,K))
for c in range(C):
x = np.eye(K)[X[np.where(y==c)]] # one hot encoding
ccl[c] += np.sum(x, axis=0) # summing up
ccl[c] /= ccl[c].sum(axis=1)[:, numpy.newaxis] # renormalization
这将产生与上述相同的输出。关于如何加快速度的任何提示?我认为np.eye(单热编码)是不必要的并且会杀死它,但我想不出一种方法来摆脱它。我考虑的最后一件事是使用np.unique() 或collections.Counter 进行计数,但还没有弄清楚。
【问题讨论】:
标签: python numpy naivebayes