【问题标题】:How to feed input with changing size in Tensorflow如何在 Tensorflow 中通过改变大小来提供输入
【发布时间】:2018-05-08 20:11:42
【问题描述】:

我想训练一个具有平面曲线的网络,我将其表示为形状为 (L,2) 的 numpy 数组。 数字 2 代表 x,y 坐标,L 是我的数据集中变化的点数。我将 x,y 视为 2 个不同的“通道”。

我实现了一个函数next_batch(batch_size),它将下一批提供为形状为(batch_size,) 的一维numpy 数组,其中包含形状为(L,2) 的二维数组元素。这些是我的曲线,如前所述,元素之间的 L 是不同的。 (我不想限制曲线中固定数量的点)。

我的问题:

如何操作来自next_batch() 的输出,以便我能够使用输入曲线为网络提供输入曲线,使用类似于 Tensorflow 教程中出现的方案:https://www.tensorflow.org/get_started/mnist/pros

即,使用feed_dict 机制。 在给定的教程中,输入大小是固定的,在教程的代码行中:

train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})

batch[0] 具有固定形状:(50,784) (50 = #samples,784 = #pixels)

我无法将输入转换为形状为 (batch_size,L,2) 的 numpy 数组 因为数组在每个维度上都应该有固定的大小。 那我该怎么办?

我已经定义了一个占位符(大小未知):

#first dimension is the sample dim, second is curve length, third:x,y coordinates    
x = tf.placeholder(tf.float32, [None, None,2]) 

但是我怎样才能正确喂它呢?

【问题讨论】:

  • 填充输入是一种可能的解决方案吗?
  • 很遗憾没有,在我的问题中
  • @Day_Dreamer 你必须填充它才能使用批处理。创建一个长度占位符怎么样?

标签: python python-3.x numpy tensorflow


【解决方案1】:

您可以在 TF 中使用不同大小的输入。只需以与您列出的教程中相同的方式提供数据,但请确保将占位符中的更改尺寸定义为无。

下面是一个简单的例子,用不同的形状填充占位符:

import tensorflow as tf
import numpy as np


array1 = np.arange(9).reshape((3,3))
array2 = np.arange(16).reshape((4,4))
array3 = np.arange(25).reshape((5,5))

model_input = tf.placeholder(dtype='float32', shape=[None, None])
sqrt_result = tf.sqrt(model_input)
with tf.Session() as sess:
    print sess.run(sqrt_result, feed_dict={model_input:array1})
    print sess.run(sqrt_result, feed_dict={model_input:array2})
    print sess.run(sqrt_result, feed_dict={model_input:array3})

【讨论】:

    【解决方案2】:

    您可能正在寻找的简短答案:您不能没有填充或按长度分组样本。

    详细说明一下:在 tensorflow 中,必须在整个批次中固定维度,并且原生不支持锯齿状数组。
    尺寸可能是先验未知的(在这种情况下,您将占位符的尺寸设置为None),但仍会在运行时推断,因此 您拥有占位符的解决方案:

    x = tf.placeholder(tf.float32, [None, None, 2]) 
    

    无法工作,因为它在语义上等同于说“我不知道批次中曲线的常数先验长度,在运行时从数据中推断出来”。

    这并不是说您的模型通常不能接受不同维度的输入,如果您相应地构建它,但您每次调用 sess.run() 时提供的数据必须具有固定维度。

    那么,您的选择如下:

    1. 沿第二个维度填充您的批次。
      假设您有 2 条形状为 (4, 2)(5, 2) 的曲线,并且您知道数据集中的最大曲线长度为 6,您可以使用 np.pad,如下所示:

      In [1]: max_len = 6
         ...: curve1 = np.random.rand(4, 2)
         ...: curve2 = np.random.rand(5, 2)
         ...: batch = [curve1, curve2]
      
      In [2]: for b in batch:
         ...:     dim_difference = max_len - b.shape[0]
         ...:     print np.pad(b, [(0, dim_difference), (0,0)], 'constant')
         ...:     
      [[ 0.92870128  0.12910409]
       [ 0.41894655  0.59203704]
       [ 0.3007023   0.52024492]
       [ 0.47086336  0.72839691]
       [ 0.          0.        ]
       [ 0.          0.        ]]
      [[ 0.71349902  0.0967278 ]
       [ 0.5429274   0.19889411]
       [ 0.69114597  0.28624011]
       [ 0.43886002  0.54228625]
       [ 0.46894651  0.92786989]
       [ 0.          0.        ]]
      
    2. 让您的 next_batch() 函数返回按长度分组的曲线批次。

    这些是处理锯齿状数组时的标准处理方式。

    如果您的任务允许,另一种可能性是将您的所有点连接到一个形状为(None, 2) 的张量中,并更改您的模型以对单个点进行操作,就好像它们是一批样本一样。如果将原始样本长度保存在单独的数组中,则可以通过正确切片来恢复模型输出。这是非常低效的,并且需要对您的问题进行各种假设,但这是一种可能性。

    干杯,祝你好运!

    【讨论】:

      【解决方案3】:

      Tensorflow Fold 您可能会感兴趣。

      来自 Tensorflow 折叠自述文件:

      TensorFlow Fold 是一个用于创建使用结构化数据的 TensorFlow 模型的库,其中计算图的结构取决于输入数据的结构。Fold 实现了动态批处理。批量任意形状的计算图被转换以产生静态计算图。该图无论接收什么输入都具有相同的结构,并且可以通过 TensorFlow 高效执行。

      可以设置图结构以接受任意L 值,以便读取任何结构化输入。这在构建递归神经网络等架构时特别有用。整体结构与您习惯的非常相似(feed dicts 等)。由于您的应用程序需要动态计算图,因此从长远来看,这对您来说可能是一个不错的举措。

      【讨论】:

        【解决方案4】:

        您可以使用带有 [None, ..., None] 的初始 var 的占位符。每个“无”表示编译器在该维度上有输入提要数据。例如,[None, None] 表示您可以提供任何行和列长度的矩阵。但是,您应该注意使用哪种 NN。因为在处理 CNN 时,在卷积层和池化层必须确定“张量”的具体大小。

        【讨论】:

          猜你喜欢
          • 2017-12-07
          • 1970-01-01
          • 2018-09-26
          • 2018-05-27
          • 1970-01-01
          • 2015-08-22
          • 2012-06-02
          • 1970-01-01
          • 2016-05-17
          相关资源
          最近更新 更多