TensorFlow的特征I/O

fio的Python项目详细描述


FIO

FIO是功能I/O的缩写。

fio是tensorflow的低级api的一个概念。更具体地说, fio是一个如何加入处理协议缓冲区的方法的概念。 将数据写入tf.record格式和tf.record格式。

FIO的工作原理是在"模式"中定义您的功能一次

例如,对于"正常"功能:

'my-features':     {'length': 'fixed', 'dtype': tf.string,  'shape': []}

我们结束了。使其成为tf.train.example或tf.train.sequenceexample, 写入并读取记录。

对于排名2的功能:

'seq':         {
      'length': 'fixed',
      'dtype': tf.int64,
      'shape': [3, 3],
      'encode': 'channels',
      'channel_names': ['Channel 1', 'Channel 2', 'Channel 3'],
      'data_format': 'channels_last'
  }

我们又结束了。我现在可以将其编码为一个tf.train.example(使用 可选,但此处提供了频道名称)或不带名称的tf.train.sequenceexample

查看演示笔记本

有用资源

S.O.

如何分解tf.record的张量如何恢复tf记录数据

COLAB

玩2级张量和tf记录恢复tf记录

动机

免责声明:我不熟悉tf、协议缓冲区等的复杂性。所以我在这里的动机对于那些为tf设计这个的专家来说可能没有意义。从我不知情的角度来看,我发现这个界面的某些部分很麻烦,而且缺少文档,fio就像是对我的特定问题(从tf记录中获取一些数据)的过度设计解决方案一样,它是对tf记录工作原理的探索。

"重复代码"

考虑一下非常琐碎的写和读数据:

my_feature = 'hi'

来自tf.记录。

示例

要将此功能写入记录,我们必须首先将此数据包装如下:

example = tf.train.Example(
  features=tf.train.Features(
      feature={
      'my-feature': tf.train.Feature(
        bytes_list=tf.train.BytesList(
          value=[my_feature.encode()] # wrap as list
        ) # end byteslist
      ) # end feature
    }
  ) # end features
) # end example

返回:

features {
  feature {
    key: "my-feature"
    value {
      bytes_list {
        value: "hi"
      }
    }
  }
}

我们可以使用以下命令将其写入记录:

with tf.python_io.TFRecordWriter('my_record.tfrecord') as writer:
    writer.write(example.SerializeToString())

我们可以使用以下命令从该文件中检索它:

DATASET_FILENAMES = tf.placeholder(tf.string, shape=[None])
dataset = tf.data.TFRecordDataset(DATASET_FILENAMES).map(lambda r: parse_fn(r)).repeat().batch(1)
iterator = dataset.make_initializable_iterator()
next_element = iterator.get_next()

for _ in range(1): # epochs
    sess.run(iterator.initializer, feed_dict={DATASET_FILENAMES: ['my_record.tfrecord']})
    for _ in range(1): # batch
        recovered = sess.run(next_element)

现在必须注意:

  1. 上面的代码比所需的基本示例(给定迭代器)要复杂一些,这里我将不详细介绍它,

  2. 由于未定义parse fn,上述代码将不会运行

由于我们使用的是tf示例,我将演示如何简单地读取示例以获取数据:

def parse_fn(record):
    features = {
        'my-feature': tf.FixedLenFeature([], dtype=tf.string)
    }
    parsed = tf.parse_single_example(record, features)
    # other things can be done if needed
    return parsed

现在运行上面的代码得到:

{'my-feature': array([b'hi'], dtype=object)}

所以如果我们想回到{'my-feature':'hi'}我们仍然需要打开列表并解码字符串:

'my-features':     {'length': 'fixed', 'dtype': tf.string,  'shape': []}

0

注意:这不能在解析函数中完成(至少和我在这里所做的一样)。

我想解决的问题

展示所有这些的要点是,如果在转换tf.records的数据时非常小心,那么为什么还要编写类似的代码来将其提取出来呢?

fio的一个目标是定义一个单一的模式,该模式将数据同时获取到一个tf记录中,并且可以恢复它(正如我们放入的那样)。

解/重组成张量:

我将在下一节中讨论tf.train.exampletf.train.sequenceexample之间的区别。无论您选择使用哪种张量,任何等级2或更高的张量都必须分解。

为了简单起见,请考虑以下顺序:

'my-features':     {'length': 'fixed', 'dtype': tf.string,  'shape': []}

1

tf.train.exampletf.train.sequenceexample都要求seq按通道分解:

或者是:

'my-features':     {'length': 'fixed', 'dtype': tf.string,  'shape': []}

2

或作为:

'my-features':     {'length': 'fixed', 'dtype': tf.string,  'shape': []}

3

这里的区别在于,对于sequenceexample,通道是未命名的特征。对于许多通道,这是有利的,因为您不必担心重新组合来自所有通道的序列。但是,如果只有几个通道(例如rgb),则可以在输入模型之前重新排列通道,或者如果有多个输入,则这可能有用。

无论哪种方式,fio的目标都是处理这一部分,既用于分解张量,又用于重新组合张量(在示例的情况下)。

单一界面

如上所述,examplesequenceexample之间的一个核心区别是每个特性是否命名。然而,还有一个核心区别:sequenceexample是元组。相反,我应该说,sequenceexample允许存储"context"(元数据),其中context是遵守示例的所有限制的功能。

文档中给出的示例是,跨序列的上下文可能相同,但大序列可能不同。这样就节省了空间。

我承认,虽然这听起来像一个结构,但我不知道如何在实践中利用它。SequenceExample需要上下文(尽管它可以是空的dict)。因此,如果单独存储示例,它们很可能将上下文存储在每个记录中。此外,根据我目前的理解,在sequenceexample功能列表中只能存储序列功能。

从我不知情的角度来看,只维护一个示例接口,然后使用类似(想象中的)tf.train.sequencefeature的东西来允许将所有内容存储在一起可能会更好。更好的是,tf.train.tensorfeature可以解决很多问题。

总之,fio旨在成为处理示例序列示例的单一接口,使张量易于分解为(非)命名特征并相应导出/导入。

分解技术

有很多方法可以把张量分解成它的通道。我只考虑上述seq的一些可能性:

  • seq的每个通道分开,并存储为相应的数字类型、名称和存储在example
  • 分离seq的每个通道,并通过numpy.ndarray.tostring()转换后存储为字节,命名并存储在example
  • seq的每个通道分开,并将每个元素转换为字节,然后存储为byteslist,命名并存储在example
  • 通过numpy.ndarray.tostring()seq转储到字节,命名并存储在example
  • 分离seq的每个通道并存储为相应的数字类型,保留未命名并存储在sequenceexample
  • 分离seq的每个通道,并通过numpy.ndarray.tostring()转换后存储为字节,保留未命名并存储在sequenceexample
  • seq的每个通道分开,并将每个元素转换为字节,然后存储为byteslist,保留未命名并存储在sequenceexample
  • 通过numpy.ndarray.tostring()seq转储到字节,并作为单个元素字节列表进行包装,从而完全存储。

哪个最好?不知道。 也许tf编码的floatint64功能到场景后面的字节。

我会注意到,有时当试图恢复数据时,如果编码为字节,那么张量就会变平。例如,[[1,2],[3,4]]恢复为[1,2,3,4]

无论如何,fio的目标是允许通过这些方法对张量进行编码和解码,因为老实说,不知道哪个是最好的(在文件大小、读取效率等方面)。

同样,我认为tf可以通过一个tf.train.tensorfeature来做得更好

P.S.如果有人知道为什么编码的功能在tf.train下(例如tf.train.feature(int64_list=tf.train.int64list(value=value)))以及如何解码的功能在tf下(例如tf.fixedlenfeature),我想知道。我觉得这很奇怪……

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java为什么需要ScheduledExecutorService。shutdown()使用我100%的CPU吗?   java如何加载应用程序。spring框架中的属性?   java立即绘制JFrame   java定时器不允许用户进行编辑   java如何通过在React应用程序中提交值来加载数据   java在Multimultiul maven项目中集成特性(文件)存储在哪里?   java Arjuna JTA事务意外回滚   java禁用edittext 安卓,在视图中使用if-else   java中的错误。图书馆从Matlab调用使用Cplex的Java函数时的路径   Java中的浮点计算错误   Java中C#IEnumerable的等价物是什么?是可协变的,不是可协变的   最终播放商店用户可见的java Apk名称