使用 Python 3 在 scikit-learn 上进行大数据序列化

Posted

技术标签:

【中文标题】使用 Python 3 在 scikit-learn 上进行大数据序列化【英文标题】:Large data serialization on scikit-learn with Python 3 【发布时间】:2014-10-07 17:53:14 【问题描述】:

我有一台配备 16 Gb RAM 的 MacBook (Mac OS X 10.9)。 通过 Anaconda 安装的两个 Python:2.7.8 和 3.4.1。两者都配备了最新的 scikit-learn 0.15.1。 在尝试运行该简单代码时(只是测试序列化大型矩阵的可能性):

import numpy as np
test_data = np.random.rand(10000, 60000)
print(test_data.nbytes / 2**30)
from sklearn.externals import joblib
joblib.dump(test_data, '/Users/va/Desktop/test_data.joblib')

Python 2.7.8 运行良好,但 Python 3.4.1 出现以下错误:

Failed to save <class 'numpy.ndarray'> to .npy file:
Traceback (most recent call last):
  File "/Users/va/anaconda/python.app/Contents/lib/python3.4/site-
    packages/sklearn/externals/joblib/numpy_pickle.py", line 240, in save
    obj, filename = self._write_array(obj, filename)
  File "/Users/va/anaconda/python.app/Contents/lib/python3.4/site-
    packages/sklearn/externals/joblib/numpy_pickle.py", line 203, in _write_array
    self.np.save(filename, array)
  File "/Users/va/anaconda/python.app/Contents/lib/python3.4/site-
    packages/numpy/lib/npyio.py", line 453, in save
    format.write_array(fid, arr)
  File "/Users/va/anaconda/python.app/Contents/lib/python3.4/site-
    packages/numpy/lib/format.py", line 410, in write_array
    fp.write(array.tostring('C'))
OSError: [Errno 22] Invalid argument

Traceback (most recent call last):

  File "<ipython-input-3-90ed09e5c6d4>", line 1, in <module>
    joblib.dump(test_data, '/Users/va/Desktop/test_data.joblib')

  File "/Users/va/anaconda/python.app/Contents/lib/python3.4/site-
    packages/sklearn/externals/joblib/numpy_pickle.py", line 368, in dump
    pickler.dump(value)

  File "/Users/va/anaconda/python.app/Contents/lib/python3.4/pickle.py", line 412, in dump
    self.framer.end_framing()

  File "/Users/va/anaconda/python.app/Contents/lib/python3.4/pickle.py", line 196, in end_framing
    self.commit_frame(force=True)

  File "/Users/va/anaconda/python.app/Contents/lib/python3.4/pickle.py", line 208, in commit_frame
    write(data)

OSError: [Errno 22] Invalid argument

看来问题在于要存储的数据量。例如,Python 3 处理 np.random.rand(10000, 20000),它是 1.5 Gb,非常好。

以防万一,泡菜也不好用:

import pickle
with open('/Users/va/Desktop/test_data.pkl', 'wb') as f:
    pickle.dump(test_data, f, protocol=pickle.HIGHEST_PROTOCOL)

前往:

Traceback (most recent call last):

  File "<ipython-input-6-3f73f3011539>", line 3, in <module>
    pickle.dump(test_data, f, protocol=pickle.HIGHEST_PROTOCOL)

OSError: [Errno 22] Invalid argument

在 Windows 7 上,Python 3.4 与 joblibpickle 都可以正常工作。

有什么建议可以在 Mac 上使用 Python 3 解决这个问题吗?

【问题讨论】:

你安装的是 32 位还是 64 位 Python? 另外,你的底层文件系统类型是什么? FAT32、ext2,还有别的吗? 是的,64 位 Python。文件系统是HFS Plus。再一次,同样的代码在 2.7 上运行良好,所以它不能是文件系统。 这是 Python 中的一个错误。有一个开放的错误bugs.python.org/issue24658。他们创建了一个正在审查中的补丁(很长一段时间......) 【参考方案1】:

我在 OS X 10.10 和 Python 3.4.3 上也使用pickle 时发生这种情况

相反,我开始使用 https://github.com/zopefoundation/zodbpickle,它慢了大约 2-3 倍,但绝对适用于 sklearn 分类器

【讨论】:

另一种解决方法是使用python open('/tmp/null','w+b').write(bytearray(2**32)。注意 open() 中的参数“w+b”。为某些 OS X 工作(但不适合我)

以上是关于使用 Python 3 在 scikit-learn 上进行大数据序列化的主要内容,如果未能解决你的问题,请参考以下文章

使用 SVM 作为图像分类器的精度/F 分数是不是可以达到 10%?

TPOT: 自动化的sklearn

编码标准:是不是应该总是在每个方法或函数的末尾写“return”? [复制]

在 Python 3 上使用 PostGIS

使用 python 3.8+(默认协议=5)时,pickle.load 在 python 3.7 中的(协议=4)对象上失败

未找到在 C++ 'python33_d.lib' 中使用 Python 3.3