sklearn.naive_bayes.BernoulliNB 数据大小的实际限制

Practical limits to data size for sklearn.naive_bayes.BernoulliNB

我手头有一个机器学习任务,我想尝试使用伯努利朴素贝叶斯。
由于我需要很快产生一些有意义的结果,我想使用 Python,更具体地说,sklearn。数据是 "simple" 但我有很多,所以我试图找出正确的方法,让我可以编写一个基于 "quick and dirty" BernoulliNB 的原型,我可以将其应用于尽可能多的数据尽可能。

详情如下:

  1. 特征是二元的(True / False
  2. 类 也是二进制的(将其视为垃圾邮件过滤器)
  3. 一个特征向量最大长度为30000。它可能能够通过特征选择显着减少这一点,但现在让我们假设它这么长
  4. 我有多达 200,000 个数据点可用于 .fit() 训练我的模型

我还没有对实际数据进行预处理,所以我没有实际的特征矩阵和 class 用于训练的向量,但是在进行预处理时,我想弄清楚有多大我可以处理的数据块。我基本上想做的是重写以下代码块,以便它可以使用 nSamplesnFeatures:

的指定值
from sklearn.naive_bayes import BernoulliNB
import numpy as np

nSamples = 200000
nFeatures =  30000

# Don't care about actual values yet, just data size
X = np.random.randint( 2, size = ( nSamples, nFeatures ) )
Y = np.random.randint( 2, size = ( nSamples, ) )

clf = BernoulliNB()
clf.fit( X, Y )

res = clf.predict_proba( X[2] )

a) "best practices" 方法是什么?
b) 我需要加入 PyTables 吗?
c) sklearn 可以使用 PyTables 对象吗?

您需要弄清楚这些数据中有多少可以放入内存。

如果你的矩阵是稀疏的,你不需要把它分成块。不过看起来不像你的。

正在分块处理数据

BernoulliNB 和许多 scikit-learn 分类器都有一个 partial_fit 方法可以做到这一点(参见 this more complete example):

clf = BernoulliNB()
   all_classes = [0, 1]
   for X_train, y_train in iter_batches:
       clf.partial_fit(X_train, y_train, classes=all_classes)

其中 iter_batches 是一个为您提供数据块的迭代器。
现在您需要确保这些块适合内存。

它有多大?

您可以使用 nbytes 属性计算 np.array 的大小:

from sklearn.naive_bayes import BernoulliNB
import numpy as np

nSamples = 2000
nFeatures =  30000
X = np.random.randint(2, size=(nSamples,nFeatures))
X.nbytes / 10 ** 6
Out[11]: 480.0

所以这里的 X 数组在内存中大约是 480MB。
请注意,如果您有布尔变量并在加载数据时正确指定类型,则可以大大减少占用空间:

X = np.random.randint(2, size=(nSamples,nFeatures)).astype(np.int8)
X.nbytes / 10 ** 6
Out[12]: 60.0

A np.bool 仍然是 1 个字节(8 位)。

您也可以手动计算这些数字:数组大约 nSamples * nFeatures * 1 / 10 ** 6 MB。

其余取决于您可用的 RAM。整个 X 数组为 6GB,但您需要考虑 scikit-learn 所需的 RAM。 "That should not be a lot" 是我可以自信地说的所有内容 ;).
不要忘记将 binarize=None 传递给 BernoulliNB 构造函数以避免复制 X 数组(您的数据已经二值化)。

PyTables

你需要PyTables吗?不,但如果您愿意,您仍然可以使用它。 sklearn 适用于 numpy 数组,但 PyTables 也适用,因此您可以使用它向 partial_fit 循环提供数据块。

希望这对您有所帮助。