Как построить слой встраивания в Tensorflow RNN?

Я строю сеть RNN LSTM для классификации текстов на основе возраста писателей (бинарная классификация - молодой / взрослый).

Похоже, сеть не учится и внезапно начинает перегружаться:

rnn_overfitting
Красный: поезд
Синий: проверка

Возможно, что представление данных недостаточно хорошее. Я просто отсортировал уникальные слова по частоте и дал им индексы. Например:

unknown -> 0
the     -> 1
a       -> 2
.       -> 3
to      -> 4

Поэтому я пытаюсь заменить это на встраивание слов. Я видел пару примеров, но я не смог реализовать это в своем коде. Большинство примеров выглядят так:

embedding = tf.Variable(tf.random_uniform([vocab_size, hidden_size], -1, 1))
inputs = tf.nn.embedding_lookup(embedding, input_data)

Означает ли это, что мы создаем слой, который изучает встраивание? Я подумал, что нужно скачать какой-нибудь Word2Vec или Glove и просто использовать это.

В любом случае, скажем, я хочу создать этот слой для встраивания...
Если я использую эти 2 строки в своем коде, я получаю сообщение об ошибке:

TypeError: Значение, переданное параметру 'indexes', имеет тип DataType float32, отсутствующий в списке допустимых значений: int32, int64

Так что я думаю, что я должен изменить input_data введите в int32, Так что я делаю это (это все индексы в конце концов), и я получаю это:

Ошибка типа: входные данные должны быть последовательностью

Я пробовал оборачивать inputs (аргумент tf.contrib.rnn.static_rnn) со списком: [inputs] как предложено в этом ответе, но это вызвало еще одну ошибку:

ValueError: Размер ввода (размер 0 входов) должен быть доступен через вывод формы, но значение значения None отсутствует.


Обновить:

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

Обновленный код:

MIN_TOKENS = 10
MAX_TOKENS = 30
x = tf.placeholder("int32", [None, MAX_TOKENS, 1])
y = tf.placeholder("float", [None, N_CLASSES]) # 0.0 / 1.0
...
seqlen = tf.placeholder(tf.int32, [None]) #list of each sequence length*
embedding = tf.Variable(tf.random_uniform([VOCAB_SIZE, HIDDEN_SIZE], -1, 1))
inputs = tf.nn.embedding_lookup(embedding, x) #x is the text after converting to indices
inputs = tf.unstack(inputs, MAX_POST_LENGTH, 1)
outputs, states = tf.contrib.rnn.static_rnn(lstm_cell, inputs, dtype=tf.float32, sequence_length=seqlen) #---> Produces error

* seqlen: я дополнил нулями последовательности, так что все они имеют одинаковый размер списка, но поскольку фактический размер отличается, я подготовил список, описывающий длину без заполнения.

Новая ошибка:

ValueError: Вход 0 слоя basic_lstm_cell_1 несовместим со слоем: ожидаемый ndim=2, найденный ndim=3. Полная форма получена: [Нет, 1, 64]

64 размер каждого скрытого слоя.

Очевидно, что у меня проблема с размерами... Как я могу сделать входы подходящими для сети после встраивания?

2 ответа

Из tf.nn.static_rnn мы можем увидеть inputs аргументы быть:

Список входов длины T, каждый из которых является тензором формы [batch_size, input_size]

Так что ваш код должен быть примерно таким:

x = tf.placeholder("int32", [None, MAX_TOKENS])
...
inputs = tf.unstack(inputs, axis=1)

tf.squeeze - это метод, который удаляет размеры размера 1 из тензора. Если конечная цель состоит в том, чтобы иметь входную форму как [Нет,64], то поместите строку, аналогичную inputs = tf.squeeze(inputs) и это решило бы вашу проблему.

Другие вопросы по тегам