我正在使用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没有显示有关如何解决此问题的更多详细信息。