Scikit-Learn 逻辑回归内存错误

Posted

技术标签:

【中文标题】Scikit-Learn 逻辑回归内存错误【英文标题】:Scikit-Learn Logistic Regression Memory Error 【发布时间】:2012-06-27 01:35:22 【问题描述】:

我正在尝试使用 sklearn 0.11 的 LogisticRegression 对象来拟合具有大约 80,000 个特征的 200,000 个观察值的模型。目标是将短文本描述分类为 800 个类别中的 1 个。

当我尝试拟合分类器时,pythonw.exe 给了我:

应用程序错误“...处的指令引用了 0x00000000 处的内存”。内存无法写入”。

这些特征非常稀疏,每次观察大约 10 个,并且是二进制的(1 或 0),所以根据我的信封计算,我的 4 GB RAM 应该能够处理内存需求,但这并没有t 似乎是这样。只有当我使用更少的观察和/或更少的特征时,模型才适合。

如果有的话,我想使用更多的观察和特征。我天真的理解是,在幕后运行的 liblinear 库能够支持这一点。有什么想法可以让我加入更多观察吗?

我的代码如下所示:

y_vectorizer = LabelVectorizer(y) # my custom vectorizer for labels
y = y_vectorizer.fit_transform(y)

x_vectorizer = CountVectorizer(binary = True, analyzer = features)
x = x_vectorizer.fit_transform(x)

clf = LogisticRegression()
clf.fit(x, y)

我传递给分析器的 features() 函数只返回一个字符串列表,指示在每个观察中检测到的特征。

我使用的是 Python 2.7、sklearn 0.11、具有 4 GB RAM 的 Windows XP。

【问题讨论】:

Python 解释器崩溃了吗?写信给0x0 是一个非常严重的错误,我们(scikit-learn 开发人员)应该调查一下。 Python 解释器确实崩溃了。 你使用的数据集是公开的吗?你能用更小的数据集重现这个崩溃吗(例如x_first_half = x[:x.shape[0] / 2]x_second_half = x[x.shape[0] / 2:] 不幸的是,数据集不是公开的,但我会尝试在公开的数据集上重现问题。如果我使用任何一半的观察值,或者如果我在 CountVectorizer 中将 max_features 截止值设置为大约 50,000,分类器就很合适。 【参考方案1】:

liblinear(sklearn.linear_model.LogisticRegression 的支持实现)将托管自己的数据副本,因为它是一个 C++ 库,其内部内存布局不能直接映射到 scipy 中预先分配的稀疏矩阵,例如 scipy.sparse.csr_matrixscipy.sparse.csc_matrix.

在您的情况下,我建议将您的数据加载为scipy.sparse.csr_matrix 并将其提供给sklearn.linear_model.SGDClassifier(如果您想要逻辑回归模型并能够调用predict_proba 方法,则使用loss='log')。如果SGDClassifier 已经在使用scipy.sparse.csr_matrix 内存布局,则SGDClassifier 将不会复制输入数据。

预计它会在内存中分配 800 * (80000 + 1) * 8 / (1024 ** 2) = 488MB 的密集模型(除了输入数据集的大小)。

编辑:如何优化数据集的内存访问

要在数据集提取后释放内存,您可以:

x_vectorizer = CountVectorizer(binary = True, analyzer = features)
x = x_vectorizer.fit_transform(x)
from sklearn.externals import joblib
joblib.dump(x.tocsr(), 'dataset.joblib')

然后退出这个python进程(强制完成内存释放)并进入一个新进程:

x_csr = joblib.load('dataset.joblib')

在 linux / OSX 下,您可以通过以下方式更有效地进行内存映射:

x_csr = joblib.load('dataset.joblib', mmap_mode='c')

【讨论】:

很好的答案,与其他人为非常昂贵的软件相比,您为这个免费软件提供了更好的支持,这个世界非常感谢您。不过需要注意一点,SGDClassifier 的 predict_proba 方法似乎只针对 2 个类别分类任务实现。 确实,我忘记了。目前在邮件列表中讨论了向 SGDClassifier 添加适当的多项逻辑回归或实现 Platt 的缩放或变体以预测一对一多类设置中的概率。

以上是关于Scikit-Learn 逻辑回归内存错误的主要内容,如果未能解决你的问题,请参考以下文章

Python 逻辑回归产生错误的系数

保存 scikit-learn 分类器会导致内存错误

卡方作为回归的评分函数

如何修复我在 scikit-learn 中的线性回归中遇到的错误

如何实现 L1 逻辑回归?

Scikit-learn 逻辑回归的性能比 Python 中自己编写的逻辑回归差