it-swarm.com.ru

Как бороться с пакетами с последовательностями переменной длины в TensorFlow?

Я пытался использовать RNN (в частности, LSTM) для прогнозирования последовательности. Тем не менее, я столкнулся с проблемой с переменной длиной последовательности. Например,

sent_1 = "I am flying to Dubain"
sent_2 = "I was traveling from US to Dubai"

Я пытаюсь предсказать следующее слово после текущего с помощью простого RNN на основе этого эталона для построения модели PTB LSTM .

Однако параметр num_steps (используемый для развертывания до предыдущих скрытых состояний) должен оставаться неизменным в каждой эпохе Tensorflow. По сути, пакетное предложение невозможно, так как предложения различаются по длине. 

 # inputs = [tf.squeeze(input_, [1])
 #           for input_ in tf.split(1, num_steps, inputs)]
 # outputs, states = rnn.rnn(cell, inputs, initial_state=self._initial_state)

Здесь num_steps нужно менять в моем случае для каждого предложения. Я пробовал несколько взломов, но ничего не работает.

18
Seja Nair

Вы можете использовать идеи группирования и заполнения, которые описаны в: 

модели от последовательности к последовательности

Кроме того, функция rnn, которая создает сеть RNN, принимает параметр sequence_length.

Например, вы можете создать группы предложений одинакового размера, дополнить их необходимым количеством нулей или заполнителями, которые обозначают нулевое слово, а затем передать их вместе с seq_length = len (zero_words).

seq_length = tf.placeholder(tf.int32)
outputs, states = rnn.rnn(cell, inputs, initial_state=initial_state, sequence_length=seq_length)

sess = tf.Session()
feed = {
    seq_length: 20,
    #other feeds
}
sess.run(outputs, feed_dict=feed)

Взгляните также на эту ветку reddit: 

Пример базового RNN Tensorflow с последовательностями 'переменной длины'

18
Taras Sereda

Вместо этого вы можете использовать dynamic_rnn и указать длину каждой последовательности даже в пределах одного пакета, передав массив в параметр sequence_length . Пример ниже:

def length(sequence):
    used = tf.sign(tf.reduce_max(tf.abs(sequence), reduction_indices=2))
    length = tf.reduce_sum(used, reduction_indices=1)
    length = tf.cast(length, tf.int32)
    return length

from tensorflow.nn.rnn_cell import GRUCell

max_length = 100
frame_size = 64
num_hidden = 200

sequence = tf.placeholder(tf.float32, [None, max_length, frame_size])
output, state = tf.nn.dynamic_rnn(
    GRUCell(num_hidden),
    sequence,
    dtype=tf.float32,
    sequence_length=length(sequence),
)

Код взят из идеальная статья по теме, пожалуйста, также проверьте его. 

Обновление: Другой отличный пост на dynamic_rnn vs rnn вы можете найти 

14
Datalker

Вы можете ограничить максимальную длину ваших входных последовательностей, дополнить более короткие до этой длины, записать длину каждой последовательности и использовать tf.nn.dynamic_rnn . Он обрабатывает входные последовательности как обычно, но после последнего элемента последовательности, обозначенного seq_length, просто копирует состояние ячейки и для вывода выдает нулевой тензор.

4
tnq177

Вы можете использовать идеи группирования и заполнения, которые описаны в 

модели от последовательности к последовательности

Также функция rnn, которая создает сеть RNN, принимает параметр sequence_length.

В качестве примера вы можете создать группы отправлений одинакового размера, дополнить их необходимым количеством нулей или заполнить местами, что означает нулевое слово, а затем передать их вместе с seq_length = len (zero_words).

seq_length = tf.placeholder(tf.int32)
outputs, states = rnn.rnn(cell, inputs,initial_state=initial_state,sequence_length=seq_length)

sess = tf.Session()
feed = {
seq_lenght: 20,
#other feeds
       }
sess.run(outputs, feed_dict=feed)

Здесь самое важное, если вы хотите использовать состояния, полученные одним предложением as, состояние для следующего предложения, когда вы предоставляете sequence_length (скажем, 20, а предложение после заполнения равно 50). Вы хотите получить состояние, полученное на 20-м шаге по времени. Для этого делай

tf.pack(states)

После этого звонка 

for i in range(len(sentences)):
state_mat   = session.run([states],{
            m.input_data: x,m.targets: y,m.initial_state: state,     m.early_stop:early_stop })
state = state_mat[early_stop-1,:,:]
4
Seja Nair

Извините, что опубликовал сообщение о нерешенной проблеме, но я просто представил PR для лучшего решения. dynamic_rnn чрезвычайно гибкий, но ужасно медленный. Это работает, если это ваш единственный вариант, но CuDNN намного быстрее. Этот PR добавляет поддержку переменной длины в CuDNNLSTM, так что вы, возможно, скоро сможете это использовать.

Вам нужно отсортировать последовательности по убыванию длины. Затем вы можете pack_sequence, запустить ваши RNN, а затем unpack_sequence.

https://github.com/tensorflow/tensorflow/pull/22308

1
Benjamin Striner