Как я могу получить часть тензора с индексами, исходящими от другого тензора?(Keras, TF Backend) - PullRequest
0 голосов
/ 01 марта 2019

Я работаю с RNN и механизмами внимания.

В отличие от мягкого внимания (которое взвешивает временные шаги RNN по тензору внимания и суммирует их), я хочу выбрать наиболее k важные временные шаги и использовать другие методы для их объединения.

Таким образом, у меня есть три тензора:

  • RNNMatrix, с формой (None, time_steps, cell_num), где None - размер партии
  • AttMatrix, с формой (None, time_steps)
  • IdxMatrix, с формой (None, k), каждая строка является указателем наиболее k важных временных шагов, получим от AttMatrix

В идеале я могу получить *От 1024 * в форме (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.

Но я не знаю, как это исправить.

Или, операция 'выбрать тензор по индексу' теоретически недифференцируема?Если да, то есть ли обходной путь?
В худшем случае, может ли обучение с подкреплением удержать это?

Я также часто ищу в Интернете и нахожу очень похожий вопрос , заданныйДаниэль МёллерОднако Даниэль не показывает больше подробностей о том, как он решает эту проблему.

...