使用tensorflow的数据集管道,我如何*命名*map`操作的结果?

Dav*_*rks 5 python mapping dictionary tensorflow tensorflow-datasets

我有下面的map函数(runnable example),它输入a string并输出a string和a integer.

tf.data.Dataset.from_tensor_slices我命名原始输入'filenames'.但是当我从map函数返回值时,map_element_counts我只能返回一个元组(返回一个字典会产生异常).

有没有办法命名从我的map_element_counts函数返回的2个元素?

import tensorflow as tf

filelist = ['fileA_6', 'fileB_10', 'fileC_7']

def map_element_counts(fname):
  # perform operations outside of tensorflow
  return 'test', 10

ds = tf.data.Dataset.from_tensor_slices({'filenames': filelist})
ds = ds.map(map_func=lambda x: tf.py_func(
  func=map_element_counts, inp=[x['filenames']], Tout=[tf.string, tf.int64]
))
element = ds.make_one_shot_iterator().get_next()

with tf.Session() as sess:
  print(sess.run(element))
Run Code Online (Sandbox Code Playgroud)

结果:

(b'test', 10)
Run Code Online (Sandbox Code Playgroud)

期望的结果:

{'elementA': b'test', 'elementB': 10)
Run Code Online (Sandbox Code Playgroud)

添加细节:

当我这样做时,return {'elementA': 'test', 'elementB': 10}我得到这个例外:

tensorflow.python.framework.errors_impl.UnimplementedError: Unsupported object type dict
Run Code Online (Sandbox Code Playgroud)

Dav*_*rks 5

为了后代,我正在为这个问题提出最终解决方案。以下代码是一个复制/粘贴示例,该示例可在此问题解决的最复杂条件下工作(请注意,其他两个答案不是复制/可粘贴的代码示例):

该代码的目标是:

  • 取得(大)文件列表,并将其分成大块(文件名/索引对)
  • 使用map操作处理每个块(生成器在这里不是可行的解决方案,请参阅:https : //github.com/tensorflow/tensorflow/issues/16343
  • 从仅需要1个文件/块作为输入的映射操作中输出多个样本。
  • 在整个过程中保持元素命名

复制/粘贴Tensorflow 1.5 / Python 3.x的工作示例

import tensorflow as tf
import numpy as np

files = [b'testA', b'testB', b'testC']

def mymap1(x):
  result_tensors = tf.py_func(func=mymap2, inp=[x], Tout=[tf.string, tf.int64])
  return {'filename': result_tensors[0], 'value': result_tensors[1]}

def mymap2(x):
  return np.array([x, x, x]), np.array([10, 20, 30])

def myflatmap(named_elements):
  return tf.data.Dataset.zip({
    'filename': tf.data.Dataset.from_tensor_slices(named_elements['filename']),
    'value': tf.data.Dataset.from_tensor_slices(named_elements['value'])
  })

ds = tf.data.Dataset.from_tensor_slices(files)
ds = ds.map(map_func=mymap1)
ds = ds.flat_map(map_func=myflatmap)

element = ds.make_one_shot_iterator().get_next()

with tf.Session() as sess:
  for _ in range(9):
    print(sess.run(element))
Run Code Online (Sandbox Code Playgroud)

输出:

{'filename': b'testA', 'value': 10}
{'filename': b'testA', 'value': 20}
{'filename': b'testA', 'value': 30}
{'filename': b'testB', 'value': 10}
{'filename': b'testB', 'value': 20}
{'filename': b'testB', 'value': 30}
{'filename': b'testC', 'value': 10}
{'filename': b'testC', 'value': 20}
{'filename': b'testC', 'value': 30}
Run Code Online (Sandbox Code Playgroud)


rAy*_*yyy 1

适用于tf.py_func内部ds.map工程。

我创建了一个非常简单的文件作为示例。我在里面只写了10。

虚拟文件.txt:

10
Run Code Online (Sandbox Code Playgroud)

这里是脚本:

import tensorflow as tf

filelist = ['dummy_file.txt', 'dummy_file.txt', 'dummy_file.txt']


def py_func(input):
    # perform operations outside of tensorflow
    parsed_txt_file = int(input)
    return 'test', parsed_txt_file


def map_element_counts(fname):
    # let tensorflow read the text file
    file_string = tf.read_file(fname['filenames'])
    # then use python function on the extracted string
    a, b = tf.py_func(
                    func=py_func, inp=[file_string], Tout=[tf.string, tf.int64]
                    )
    return {'elementA': a, 'elementB': b, 'file': fname['filenames']}

ds = tf.data.Dataset.from_tensor_slices({'filenames': filelist})
ds = ds.map(map_element_counts)
element = ds.make_one_shot_iterator().get_next()

with tf.Session() as sess:
    print(sess.run(element))
    print(sess.run(element))
    print(sess.run(element))
Run Code Online (Sandbox Code Playgroud)

输出:

{'file': b'dummy_file.txt', 'elementA': b'test', 'elementB': 10}
{'file': b'dummy_file.txt', 'elementA': b'test', 'elementB': 10}
{'file': b'dummy_file.txt', 'elementA': b'test', 'elementB': 10}
Run Code Online (Sandbox Code Playgroud)