基于变量的Tensorflow切片

Tensorflow slicing based on variable

我发现索引在 tensorflow (#206) 中仍然是一个未解决的问题,所以我想知道目前我可以使用什么作为解决方法。我想 index/slice row/column 一个基于变量的矩阵,该变量随每个训练示例而变化。

到目前为止我尝试过的:

  1. 基于占位符的切片(不起作用)

以下(有效)代码片基于固定数量。

import tensorflow as tf
import numpy as np

x = tf.placeholder("float")
y = tf.slice(x,[0],[1])

#initialize
init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)

#run
result = sess.run(y, feed_dict={x:[1,2,3,4,5]})
print(result)

但是,我似乎不能简单地将其中一个固定数字替换为 tf.placeholder。下面的代码给我错误 "TypeError: List of Tensors when single Tensor expected."

import tensorflow as tf
import numpy as np

x = tf.placeholder("float")
i = tf.placeholder("int32")
y = tf.slice(x,[i],[1])

#initialize
init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)

#run
result = sess.run(y, feed_dict={x:[1,2,3,4,5],i:0})
print(result)

这听起来好像 [i] 周围的括号太多了,但删除它们也无济于事。如何使用placeholder/variable作为索引?

  1. 基于 python 变量的切片(backprop/update 不正确)

我也试过使用普通的 python 变量作为索引。这不会导致错误,但网络在训练时不会学到任何东西。我想是因为变化的变量没有正确注册,图形格式不正确并且更新不起作用?

  1. 通过 one-hot 向量 + 乘法进行切片(有效,但很慢)

我发现的一种解决方法是使用单热向量。在 numpy 中制作一个单热向量,使用占位符传递它,然后通过矩阵乘法进行切片。这有效,但速度很慢。

有什么想法可以有效地 slice/index 基于变量吗?

基于占位符的切片应该可以正常工作。由于一些细微的形状和类型问题,您似乎 运行 遇到了类型错误。如果您有以下内容:

x = tf.placeholder("float")
i = tf.placeholder("int32")
y = tf.slice(x,[i],[1])

...你应该改为:

x = tf.placeholder("float")
i = tf.placeholder("int32")
y = tf.slice(x,i,[1])

...然后您应该在 sess.run().

的调用中将 i 作为 [0] 提供

为了更清楚一点,我建议重写代码如下:

import tensorflow as tf
import numpy as np

x = tf.placeholder(tf.float32, shape=[None])  # 1-D tensor
i = tf.placeholder(tf.int32, shape=[1])
y = tf.slice(x, i, [1])

#initialize
init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)

#run
result = sess.run(y, feed_dict={x: [1, 2, 3, 4, 5], i: [0]})
print(result)

tf.placeholder 操作的附加 shape 参数有助于确保您输入的值具有适当的形状,并且如果形状不正确,TensorFlow 将引发错误。

如果你有一个额外的维度,这行得通。

import tensorflow as tf
import numpy as np

def reorder0(e, i, length):
    '''
    e: a two dimensional tensor
    i: a one dimensional int32 tensor, of shape (e.shape[0])
    returns: a tensor of the same shape as e, where the jth entry is entry i[j] from e
    '''
    return tf.concat(
        [ tf.expand_dims( e[i[j],:], axis=0)  for j in range(length) ],
        axis=0
    )

e = tf.placeholder(tf.float32, shape=(2,3,5), name='e' )  # sentences, words, embedding
i = tf.placeholder(tf.int32, shape=(2,3), name='i' ) # for each word, index of parent
p = tf.concat(
    [ tf.expand_dims(reorder0(e[k,:,:], i[k,:], 3), axis=0)  for k in range(2) ],
    axis=0,
    name='p'
)

#initialize
init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)

#run
result = sess.run(p, feed_dict={
    e: [ 
        ( (1.0,1.1,1.2,1.3,1.4),(2.0,2.1,2.2,2.3,2.4),(3.0,3.1,3.2,3.3,3.4) ), 
        ( (21.0,21.1,21.2,21.3,21.4),(22.0,22.1,22.2,22.3,22.4),(23.0,23.1,23.2,23.3,23.4) ),  
    ], 
    i: [ (1,1,1), (2,0,2)]
})
print(result)

如果在构建模型时不知道尺寸,请使用 TensorArray。

e = tf.placeholder(tf.float32, shape=(3,5) )  # words, embedding
i = tf.placeholder(tf.int32, shape=(3) ) # for each word, index of parent
#p = reorder0(e, i, 3)
a = tf.TensorArray(
    tf.float32, 
    size=e.get_shape()[0],
    dynamic_size=True,
    infer_shape= True,
    element_shape=e.get_shape()[1],
    clear_after_read = False
)


#initialize
init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)

#run
result = sess.run(
    a.unstack(e).gather(i), 
    feed_dict={
        e: ( (1.0,1.1,1.2,1.3,1.4),(2.0,2.1,2.2,2.3,2.4),(3.0,3.1,3.2,3.3,3.4) ),
            #( (21.0,21.1,21.2,21.3,21.4),(22.0,22.1,22.2,22.3,22.4),(23.0,23.1,23.2,23.3,23.4) ),  
        i: (2,0,2)
    }
)
print(result)