如何在Tensorflow中输入大小不一的输入

时间:2017-11-24 20:23:51

标签: python python-3.x numpy tensorflow

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

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

我的问题:

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

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

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

batch[0]形状固定:(50,784)(50 =#个样本,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]) 

但我怎样才能正确喂它?

非常感谢

4 个答案:

答案 0 :(得分:7)

您可以在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})

答案 1 :(得分:2)

您可能正在寻找的简短回答:您无法通过长度填充或分组样本。

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

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

无法工作,因为它在语义上等同于说'#34;我不知道先前批次中曲线的常数长度,推断它在运行时来自数据"。

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

您的选择如下:

  1. 沿第二维填充批次。
    假设您有两条形状(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()函数返回按长度分组的曲线批次。
  3. 这些是处理锯齿状数组时的标准方法。

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

    干杯,祝你好运!

答案 2 :(得分:1)

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

答案 3 :(得分:0)

您可能会对

Tensorflow Fold 感兴趣。

来自Tensorflow折叠自述文件:

  

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

可以设置图形结构,以便接受任意L值,以便可以读入任何结构化输入。这在构建诸如递归神经网络的体系结构时尤其有用。整体结构与您习惯的非常相似(提供dicts等)。由于您需要一个适用于您的应用程序的动态计算图,从长远来看,这可能是一个很好的举措。