大型 csv 文件导致 numpy.genfromtxt 的分段错误

large csv file makes segmentation fault for numpy.genfromtxt

我真的很想从 csv 文件创建一个 numpy 数组,但是,当文件长约 50k 行时(如 MNIST 训练集),我遇到了问题。我尝试导入的文件如下所示:

0.0,0.0,0.0,0.5,0.34,0.24,0.0,0.0,0.0
0.0,0.0,0.0,0.4,0.34,0.2,0.34,0.0,0.0
0.0,0.0,0.0,0.34,0.43,0.44,0.0,0.0,0.0
0.0,0.0,0.0,0.23,0.64,0.4,0.0,0.0,0.0

它适用于 10k 行长的东西,比如验证集:

import numpy as np
csv = np.genfromtxt("MNIST_valid_set_data.csv",delimiter = ",")

如果我对训练数据(更大的文件)做同样的事情,我会得到一个 c 风格的分段错误。有谁知道除了分解文件然后拼凑之外还有更好的方法吗?

最终结果是我想将数组腌制到一个类似的 mnist.pkl.gz 文件中,但如果我无法读入数据,我就无法做到这一点。

如有任何帮助,我们将不胜感激。

我认为您真的想找出实际问题并解决它,而不是仅仅解决它,因为我敢打赌您在安装 NumPy 时还有其他问题需要处理最终。

但是,由于您要求的解决方法比手动拆分、读取和合并文件更好,这里有两个:


首先,您可以以编程方式动态拆分文件,而不用手动拆分。这避免了浪费您自己的大量人力,并且还节省了这些副本所需的磁盘 space,即使这在概念上与您已经知道的操作相同。

正如 genfromtxt 文档明确指出的那样,fname 参数可以是路径名,或文件对象(以 'rb' 模式打开),或只是一个行生成器(如 bytes)。当然,文件对象本身就是行的生成器,但是,比方说,文件对象的 islice 或来自 grouper 的组也是如此。所以:

import numpy as np
from more_itertools import grouper

def getfrombigtxt(fname, *args, **kwargs):
    with open(fname, 'rb') as f:
        return np.vstack(np.genfromtxt(group, *args, **kwargs) 
                         for group in grouper(f, 5000, b''))

如果您不想安装 more_itertools,您也可以从 itertools 文档的 Recipes 部分复制两行 grouper 实现,甚至将迭代器直接内联压缩到您的代码中。


或者,您可以使用 stdlib 的 csv 模块而不是 NumPy 来解析 CSV 文件:

import csv
import numpy as np

def getfrombigtxt(fname, delimiter=','):
    with open(fname, 'r') as f: # note text mode, not binary
        rows = (list(map(float, row)) for row in csv.reader(f))
        return np.vstack(rows)

这显然会慢很多......但如果我们谈论将 50 毫秒的处理时间变成 1000 毫秒,而你只做一次,谁在乎呢?