大型 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 毫秒,而你只做一次,谁在乎呢?
我真的很想从 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 毫秒,而你只做一次,谁在乎呢?