TensorFlow入门中的`my_input_fn`如何允许对数据进行枚举?

fos*_*ndy 6 python tensorflow

我正在寻找张力流的第一步作为谷歌机器学习科学课程的一部分,并已经困惑.我的理解是(如果我错了,请纠正我):

  • 步骤4定义了一个输入函数my_input_fn,该函数将数据格式化为相关的TensorFlow结构传感器
  • 然后,步骤5将此功能提供给train呼叫.
  • 目的是火车呼叫将连续调用my_input_fn以获得连续批量数据以调整模型.(???现在对此嫌疑人)

my_input_fn 在这里定义:

def my_input_fn(features, targets, batch_size=1, shuffle=True, num_epochs=None):
    """Trains a linear regression model of one feature.

    Args:
      features: pandas DataFrame of features
      targets: pandas DataFrame of targets
      batch_size: Size of batches to be passed to the model
      shuffle: True or False. Whether to shuffle the data.
      num_epochs: Number of epochs for which data should be repeated. None = repeat indefinitely
    Returns:
      Tuple of (features, labels) for next data batch
    """

    # Convert pandas data into a dict of np arrays.
    features = {key:np.array(value) for key,value in dict(features).items()}                                           

    # Construct a dataset, and configure batching/repeating
    ds = Dataset.from_tensor_slices((features,targets)) # warning: 2GB limit
    ds = ds.batch(batch_size).repeat(num_epochs)

    # Shuffle the data, if specified
    if shuffle:
      ds = ds.shuffle(buffer_size=10000)

    # Return the next batch of data
    features, labels = ds.make_one_shot_iterator().get_next()
    return features, labels
Run Code Online (Sandbox Code Playgroud)

从我的阅读中my_input_fn,我不明白这是怎么发生的.我只有python的基本知识,但我对函数的读取是每次调用它都会重新初始化pandas帧中的张量结构,得到一个迭代器然后返回它的第一个元素.每次被召唤.当然,在这个例子的情况下,如果数据被洗牌(默认情况下是这样)并且数据集很大,那么你不可能在100步的情况下得到重复数据,但是这有点草率的编程(即在这种情况下)它没有被洗牌它总会返回相同的第一个训练数据集)所以我怀疑是这样的.

我的下一个怀疑是这个one_shot_iterator().get_next()电话正在做一些有趣/古怪/棘手的事情.就像返回某种后期eval结构一样,它允许train函数从自身枚举到下一批而不是重新调用my_input_fn

但老实说,我想澄清一下,因为在这个阶段,我想要考虑的时间比我想的更多,所以我不再接近理解.

我的研究尝试刚刚引起了进一步的混乱.

本教程建议阅读本文 - 有一点它说"火车,评估和预测每个Estimator的方法都需要输入函数来返回包含张量流张量的(特征,标签)对." 好的,这与我最初的想法是一致的.基本上是TensorFlow结构中打包的示例和标签.

但后来它显示了它返回的结果,它是这样的东西(例子):

({
    'SepalLength': <tf.Tensor 'IteratorGetNext:2' shape=(?,) dtype=float64>,
    'PetalWidth': <tf.Tensor 'IteratorGetNext:1' shape=(?,) dtype=float64>,
    'PetalLength': <tf.Tensor 'IteratorGetNext:0' shape=(?,) dtype=float64>,
    'SepalWidth': <tf.Tensor 'IteratorGetNext:3' shape=(?,) dtype=float64>},
Tensor("IteratorGetNext_1:4", shape=(?,), dtype=int64))
Run Code Online (Sandbox Code Playgroud)

在代码实验室中,my_input_fn(my_feature, targets)返回:

({'total_rooms': <tf.Tensor 'IteratorGetNext:0' shape=(?,) dtype=float64>},
Run Code Online (Sandbox Code Playgroud)

)

我没有想法如何做到这一点.我对张量的阅读没有提到这样的事情.我甚至不知道如何用我的基本Python和不存在的TensorFlow知识来查询这个问题.

单击迭代器的文档说它创建了一个枚举元素的迭代器.再次,这符合我的想法.

get_next文档说:

返回包含下一个元素的tf.Tensors的嵌套结构.

我不知道如何解析这个.什么样的嵌套结构?我的意思是它看起来像一个元组,但为什么你不会说元组?是什么决定这个?在哪里描述?当然这很重要吗?

我在这里误解了什么?

(对于一个据称不需要事先了解TensorFlow的课程,谷歌机器学习速成课程让我感到非常愚蠢.我真的很好奇我的情况中的其他人如何使用它.)

xdu*_*ch0 7

输入功能(在这种情况下my_input_function)不会重复调用.它被调用一次,创建一堆tensorflow操作(用于创建数据集,对其进行混洗等)并最终返回get_next迭代器的操作.这个操作被重复调用,但它只是迭代数据集.你做的事情my_input_function(如洗牌,配料,重复)只发生一次.

一般来说:使用Tensorflow程序时,你必须习惯它们与"普通"Python程序的工作方式完全不同.您编写的大多数代码(特别是tf.前面的代码)只会被执行一次以构建计算图,然后这个图执行多次.
编辑:但是,有一个实验性的tf.eagerAPI(据说可以完全集成在TF 1.7中),它会改变这一点,即在你编写它们时执行的东西(更像是numpy).这应该允许更快的实验.

要逐步完成输入接口:首先要使用从"张量切片"(例如numpy数组)创建的数据集.然后你调用batch方法.这实质上创建了一个新的数据集,其元素是原始数据集的多个元素.类似地,重复和混洗也会创建新的数据集(准确地说,它们会创建操作,一旦它们实际作为计算图的一部分执行,就会创建这些数据集).最后,在批处理的,重复的,混洗的数据集上返回一个迭代器.只有这个迭代器的get_nextop将重复执行,返回数据集的新元素,直到它耗尽为止.
编辑:确实iterator.get_next()只返回一个操作.只有在此操作中运行一次,才会执行迭代tf.Session.

至于你有"不知道该做什么"的输出:不确定你的问题是什么,但你发布的只是将字符串映射到张量的字符串.张量自动获取与生成它们的op相关的名称(iterator.get_next),并且它们的形状未知,因为批量大小可以变化 - 即使指定它,如果批量大小不均匀地划分数据集,最后一批可能会更小大小(例如,具有10个元素且批量大小为4的数据集 - 最后一批将为大小2).?张量形状中的元素表示未知的维度.
编辑:关于命名:操作接收默认名称.但是,IteratorGetNext在这种情况下,它们都会收到相同的默认名称(),但不能有多个具有相同名称的操作.因此,Tensorflow会自动附加整数以使名称唯一.就这样!

至于"嵌套结构":通常使用输入函数tf.estimator,期望一个相当简单的输入结构(包含Tensor或Tensors dict作为输入的元组,如果我没有弄错的话,Tensor作为输出).但是,通常,输入函数支持更复杂的嵌套输出结构,例如(a, (tuple, of), (tuples, (more, tuples, elements), and), words).请注意,这是一个输出的结构,即迭代器的一个"步骤"(例如一批数据).反复调用此op将枚举整个数据集.
编辑:输入函数返回的结构仅由该函数决定!例如,来自张量切片的数据集将返回元组,其中第n个元素是第n个"张量切片".有些功能dataset.zip就像Python等效一样.如果您将采用具有结构(e1,e2)的数据集并使用数据集(e3,)将其压缩,您将获得((e1,e2),e3).
需要什么格式取决于应用程序.原则上,您可以提供任何格式,然后接收此输入的代码可以对其执行任何操作.但是,正如我所说,可能最常见的用途是在上下文中tf.estimator,并且你的输入函数应该返回一个元组(特征,标签),其中特征是张量的张量或字典(如你的情况)和标签也是张量的张量或词典.如果其中一个是dict,则模型函数负责从那里获取正确的值/张量.

一般来说,我会建议你玩这些东西.查看tf.data API,当然还有程序员指南.创建一些数据集/输入函数,只需启动一个会话并重复运行iterator.get_next()op.看看那里出了什么.尝试所有不同的转换,例如zip,take,padded_batch...在行动中看到它,而不需要实际上这个数据应该给你一个更好的了解做任何事情.

  • 非常感谢。我不会假装我完全理解(需要一些消化)但我们正在返回操作的想法可能是我的主要突破。没有更强烈地强调这一点似乎很疯狂。我的意思是,如果这是 Haskell 或其他一些后期评估语言,这将是有道理的。偏离 Python 相当命令式的范式似乎值得粗略地提及。 (2认同)
  • 我通过编辑处理了所有评论.希望它清除一些东西. (2认同)