我如何才能获得带有来自另一个张量的索引的张量的一部分? (Keras,TF后端)

时间:2019-03-01 10:39:25

标签: python-3.x tensorflow keras slice tensor

我正在使用RNN和注意力机制。

与软注意力不同(通过注意力张量加权RNN的时间步长并对其求和),我想选择最k个重要的时间步长并使用其他方法将它们组合起来。

因此,我有三个张量:

  • RNNMatrix,形状为(None, time_steps, cell_num),其中None是批次大小
  • AttMatrix,形状为(None, time_steps)
  • IdxMatrix,形状为(None, k),每一行是最重要的k个时间步长的索引,从AttMatrix中获取

理想情况下,我可以通过KRNNMatrix(None, k, cell_num)得到RNNMatrix形的IdxMatrix

获取IdxMatrix的直接方法是使用tf.nn.top_k。我的代码如下:

selected_att_num = 10

def My_select_layer(ip, k_num):

    LSTM_out = ip[0]
    Attention = ip[1]

    idx = tf.nn.top_k(Attention, k=k_num, sorted = True).indices

    # gen row index
    row_idx = tf.range(tf.shape(Attention)[0])

    # repeat k times
    row_idx_repeat = tf.keras.backend.repeat(tf.reshape(row_idx,(-1,1)), k_num)

    # gen index for gather_nd
    row_idx_repeat_reshape = tf.reshape(row_idx_repeat, (-1,k_num))
    idx_stacked = tf.stack([row_idx_repeat_reshape, idx], axis=-1)

    return tf.gather_nd(LSTM_out, idx_stacked)


_input = Input(shape = (data_length, data_dim))
LSTM_out = LSTM(cells, return_sequences=True)(_input )

# compute att for each step
Attention = Activation('tanh')(LSTM_out)
Attention = Dense(1, use_bias=False)(Attention)
Attention = Flatten()(Attention)
Attention = Activation('softmax', name='attention')(Attention)

LSTM_out_gathered = Lambda(My_select_layer,arguments={'k_num':selected_att_num})([LSTM_out , Attention])

模型一致性好,在训练时会引发错误:

ValueError:操作具有None用于渐变。请确保您所有的操作都定义了渐变(即可区分)。没有渐变的常见操作:K.argmax,K.round,K.eval。

我非常确定此错误归咎于我的Lambda层,很可能归咎于indices的变量tf.nn.top_k

但是我不知道如何解决它。

或者,操作“按索引选择张量” 在理论上是不可微的吗?如果是这样,有什么解决方法吗?
在最坏的情况下,强化学习能否坚持下去?

我还在互联网上进行了大量搜索,并找到了丹尼尔·莫勒(DanielMöller)询问的非常相似的question。但是,Daniel没有显示有关如何解决此问题的更多详细信息。

0 个答案:

没有答案