使用TensorFlow生成和转换数据集

时间:2019-12-19 21:47:44

标签: python tensorflow dataset

我目前正在尝试加载我的数据以在TensorFlow中训练网络。我在创建DataSet对象时遇到了麻烦。

问题背景: 我当前的数据集是一组10万个样本。每个样本都有14个以浮点数表示的特征。标签是一个512K值0.0或1.0的数组。数据保存在二进制文件中,该文件具有14 * 4字节的数据,然后对每个样本在接下来的64000字节中对标签进行位映射。

我的网络将tf.float32类型用于特征和预测。我使用的是TF r1.13。

我确实尝试使用tf.data.FixedLengthRecordDataSet,但是我无法成功将位图转换为tf.float32类型张量,这主要是由于缺乏对该过程的了解。因此,我切换到了tf.data.DataSet.from_generator。

目前,我有:

class Generator:
    def __init__(self, files: typing.Union[typing.List[str], typing.Tuple[str], str], structure: BinaryStructure,
                 grid: typing.Union[typing.List[int], typing.Tuple[int], int] = None):
        if isinstance(files, str):
            self._files = tuple([files])
        elif isinstance(files, list):
            self._files = tuple(files)
        elif isinstance(files, tuple):
            self._files = files
        else:
            raise TypeError('Expected a single string or a list of strings.')
        if not all(isinstance(t, str) for t in self._files):
            raise TypeError('Expected string type for file.')

        if isinstance(structure, BinaryStructure):
            self._structure = copy.deepcopy(structure)
        else:
            raise TypeError('Expected BinaryStructure type.')

        if grid:
            if isinstance(grid, int):
                self.grid = np.array([grid, grid, grid], dtype=np.int)
            elif isinstance(grid, list):
                self.grid = np.array(grid, dtype=np.int)
            elif isinstance(grid, tuple):
                self.grid = np.array(grid, dtype=np.int)
            else:
                raise TypeError('Expected a single int or a list of ints.')
            self._offset = (8 - (np.prod(self.grid) % 8)) % 8
        else:
            self._offset = 0
        self._num_samples = 0
        for f in self._files:
            sz = os.path.getsize(f)
            ssz = self._structure.get_stream_length()
            if sz % ssz:
                raise RuntimeError(
                    f'Expected fixed length input of N * {ssz}. Files {f} size {sz} does not match expected values.')
            else:
                self._num_samples += sz // ssz
        self._current_sample = -1
        self._f_current_sample = -1
        self._current_file = -1
        self._file_handle = None

    def __iter__(self):
        it = copy.copy(self)
        it._current_sample = -1
        it._f_current_sample = -1
        it._current_file = -1
        it._file_handle = None
        return it

    def __next__(self):
        self._current_sample += 1
        if self._current_file == -1:
            if self.open_next_file():
                raise IOError('Failed to open file.')
        if self._current_sample < self._num_samples:
            buffer = self.read_sample()
            if len(buffer) == 0:
                if self.open_next_file():
                    raise RuntimeError('Iterator failed to buffer the next sample.')
                buffer = self.read_sample()
            sample = GridData(buffer, self._structure, self._offset)
            sample.generate_output()
            return np.array(sample.input, dtype=np.float32), np.array(sample.output, dtype=np.float32)
        else:
            raise StopIteration

下面我将用它来创建数据集

def get_data_set(files: typing.Union[typing.List[str], typing.Tuple[str], str], structure: BinaryStructure,
                 grid: typing.Union[typing.List[int], typing.Tuple[int], int] = None, batch: int = 1):
    dg = dr.Generator(files, structure, grid)
    tds = tf.data.Dataset.from_generator(lambda: dg, (tf.float32, tf.float32), dg.get_output_shape()).batch(
        batch_size=batch)
    return dg.get_num_samples(), tds

我需要能够将来自此生成器的数据分为2组,一组用于训练,一组用于评估。我当前的代码可以吗?尽管此代码中的生成器详尽地读取了我的所有数据,但它能够跳过样本并仅读取所需数量的样本。

因为这是我第一次使用tf.data.DataSet,所以我不知道TF中生成器的性能影响。在这方面的任何建议也将不胜感激。

0 个答案:

没有答案