2016-08-12 63 views
0

对于深度学习模式,我需要通过批量加载数据。对于每个时期(对所有数据进行全面迭代),每行都需要传递一次,但重要的是数据以随机顺序传递给算法。我的数据集太大,无法在内存中完整读取。它是具有可变长度的序列数据,输入格式可以更改,因为它是来自另一个脚本输出的群集的转储。目前它是每行一些元信息,然后按';'分割序列。从文本文件中随机读取块

我目前的解决方案是一个生成器,将所有行号混合,将它们分成4块并读取文件,解析与块行号匹配的行。它会产生批量大小的序列,直到没有剩下任何东西,然后解析下一个行数。它有效,但我觉得可能有更好的解决方案。谁有更好的工作流程?这是我经常遇到的问题。问题是我完全扫描每个块的文件,每个时代。尽管我可以用它只用4块,30个纪元是120倍读大文件。

+2

*“是很重要的是,数据以随机馈送为了算法“*顺序磁盘I/O API不是为这种疯狂而设计的。 - 签名,对“深度学习”一无所知的人 –

+0

我会用'set(file_obj)'做一组文件。然后使用'random.sample'来获取正确数量的随机元素。 – zondo

+0

@zondo不会将整个文件内容加载到内存中吗? –

回答

3

构建内存中行的索引(需要单次遍历文件,但不是全部在内存中),然后可以随机快速访问行。

这不是鲁棒(没有验证/范围检查等),但:

import sys 

BUFFER_LEN = 1024 


def findNewLines(s): 
    retval = [] 
    lastPos = 0 
    while True: 
     pos = s.find("\n", lastPos) 
     if pos >= 0: 
     pos += 1 
     retval.append(pos) 
     lastPos = pos 
     else: 
     break 
    return retval 


class RandomAccessFile(object): 
    def __init__(self, fileName): 
     self.fileName = fileName 
     self.startPositions = [0] 
     with open(fileName, "rb") as f: 
     looking = True 
     fileOffset = 0 
     while (looking): 
      bytes = f.read(BUFFER_LEN) 
      if len(bytes) < BUFFER_LEN: 
       looking = False 
      newLines = findNewLines(bytes) 
      for newLine in newLines: 
       self.startPositions.append(fileOffset+newLine) 
      fileOffset += len(bytes) 

    def GetLine(self, index): 
     start, stop = self.startPositions[index],self.startPositions[index+1]-1 
     with open(self.fileName, "rb") as f: 
     f.seek(start) 
     return f.read((stop-start)-1) 



raf = RandomAccessFile('/usr/share/dict/words') 


print raf.GetLine(0) 
print raf.GetLine(10) 
print raf.GetLine(456) 
print raf.GetLine(71015) 

输出是:

python indexedFile.py 
A 
Aaronic 
abrim 
flippantness