Пользовательский оценщик Tensorflow с API набора данных: встраивание поиска (feature_column) NMT-задача

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


ЦЕЛЬ

Для обслуживания специального оценщика, который использует Dataset API для ввода данных. Задача - NMT (seq2seq).


Проблема

Оценщик требует в качестве входных данных feature_columns для обслуживания. В моей задаче NMT есть только одна функция: вводимое предложение для перевода (или, возможно, каждое слово в предложении является функцией?). И поэтому я не уверен, как построить feature_column (и, таким образом, embedding_column и, наконец, input_layer), используя мои входные предложения в качестве функции, которую можно передать в RNN (которая ожидает embedding_lookup [batch_size, max_seqence_len, embedding_dim]), который, наконец, позвольте мне служить Оценщику.


Фон

Я пытаюсь использовать настраиваемый оценщик для реализации NMT в стиле seq2seq. Мне нужно иметь возможность обслуживать модель через tf-serve, что, по-видимому, относительно легко сделать оценщики.

Однако я наткнулся на препятствие с «как» служить модели. Насколько я могу судить, мне нужны «feature_columns», которые будут входить в модель.

https://github.com/MtDersvan/tf_playground/blob/master/wide_and_deep_tutorial/wide_and_deep_basic_serving.md

Показывает, что вам нужен export_input_fn, который использует feature_spec, которому в качестве входных данных требуется feature_column (s). Это имеет смысл, однако, для моего варианта использования у меня нет набора (разных) функций, вместо этого у меня есть предложения ввода (где каждое слово является функцией), которые нужно искать с помощью встраиваний и использовать в качестве функций ...

Итак, я знаю, что мне нужны входные данные для моей модели в виде столбцов функций. Мой ввод для NMT - это просто тензор [batch_size, max_sequence_len], который заполняется индексами слов из предложений (например, для batch_size = 1 [3, 17, 132, 2, 1, 0, ...] где каждый индекс должен отображаться на вектор внедрения). Обычно я скармливаю это в embedding_lookup через

    embs = tf.get_variable('embedding', [vocab_size, embedding_dim])
    tf.nn.embedding_lookup(embs, inputs)

и мне было бы хорошо пойти, я мог бы передать это в RNN в качестве входных данных, а остальное - история, а не проблема.

НО, вот где я столкнулся с проблемой, мне нужно использовать feature_columns (чтобы я мог обслуживать модель). Ответ на вопрос, который я упомянул в начале, показывает, как использовать embedding_column, но вместо этого он предлагает, чтобы встраивание рассматривало все предложение как одну единственную функцию, но обычно вы должны искать каждое слово в предложении и получить его вложение.

Точно так же https://www.damienpontifex.com/2018/01/02/using-tensorflow-feature-columns-in-your-custom-estimator-model/

Показывает, «как реализовать функциональный столбец в настраиваемом оценщике», и действительно, его код «До» совершенно правильный (как я написал), tf.get_variable в tf.nn.embedding_lookup, но его код «после», опять же, включает только 1 функцию (все предложение?).

Я проверил это, используя их код и передав свои данные из [batch_size, max_seq_len] в tf.feature_column.categorical_column_with_identity, а выходной тензор равен [batch_size, embedding_dim]

информация о последовательности потеряна? Или просто сплющивается? когда я печатаю вывод его размер (?, embedding_dim) где? обычно мой размер batch_size.

РЕДАКТИРОВАТЬ: Я подтвердил, что форма [batch_size, embedding_dim] не просто сплющена ... Таким образом, информация о последовательности потеряна

Я предполагаю, что он должен обрабатывать ввод как одну функцию ввода (таким образом, batch_size = 1 ex [3, 17, 132, 2, 1, 0, ...], где каждый индекс сопоставляется с вектором внедрения) будет отображать с одной функцией, которая не является тем, что нам нужно, мы хотим, чтобы каждый индекс отображался на встраивание, а требуемый результат - [batch_size, max_seq_len, embedding_dim].

Похоже, что мне вместо этого нужен не один category_column_with_ *, а их количество max_seq_len (1 для каждого слова в моей последовательности), это звучит правильно? Каждое слово будет особенностью моей модели, поэтому я склоняюсь к тому, чтобы это был правильный подход, но здесь также есть проблемы. Я использую Dataset API, поэтому в моем input_train_fn () я загружаю свои данные из файла, а затем использую tf.data.Dataset.from_tensor_slices (data, labels), чтобы разделить данные на тензоры, которые затем я могу dataset.batch ( batch_size) .make_one_shot_iterator (). get_next () для передачи в мой Оценщик. Я не могу выполнять итерацию по каждому пакету (тестеры не повторяются), поэтому я не могу просто создать 100 feature_columns для каждого входного пакета ...

Кто-нибудь знает, как это сделать? Этот встраиваемый поиск - очень простая вещь, которую можно сделать с помощью простых заполнителей или переменных (и это общий подход в задачах НЛП). Но когда я отваживаюсь на Dataset API и оценщики, я наталкиваюсь на стену, в которой очень мало информации (это не базовый пример).

Я допускаю, что у меня могут быть пробелы в моем понимании, пользовательские оценщики и API наборов данных для меня внове, и поиск информации о них иногда может быть затруднен. Так что не стесняйтесь давать мне информацию.

Спасибо, что прочитали мою стену с текстом и, надеюсь, помогли мне (и другие, которых я видел, задают вопрос, похожий на этот, но не получают ответа https://groups.google.com/a/tensorflow.org/forum/#!searchin/Discuss/embeddings 20 долларов США в 20 долларов США по индивидуальному заказу $ 20estimator / Discussion / U3vFQF_jeaY / EjgwRQ3RDQAJ Мне жаль этого парня, на его вопрос не было ответа (по той же причине, что изложена здесь, и его ветка была захвачена ...).


person Andrew Schenck    schedule 21.02.2018    source источник


Ответы (4)


Если я правильно понимаю, вы хотите использовать API-интерфейс оценщика для создания модели SeqSeq. Хорошее место для начала здесь, загляните в Проблемы-Решения / текст папка.

Чтобы ответить на ваш вопрос о том, как использовать поиск emedding, вот один пример

vocab_table = lookup.index_table_from_file(vocabulary_file='data/vocab.csv', num_oov_buckets=1, default_value=-1)
text = features[commons.FEATURE_COL]
words = tf.string_split(text)
dense_words = tf.sparse_tensor_to_dense(words, default_value=commons.PAD_WORD)
word_ids = vocab_table.lookup(dense_words)

padding = tf.constant([[0, 0], [0, commons.MAX_DOCUMENT_LENGTH]])
# Pad all the word_ids entries to the maximum document length
word_ids_padded = tf.pad(word_ids, padding)
word_id_vector = tf.slice(word_ids_padded, [0, 0], [-1, commons.MAX_DOCUMENT_LENGTH])

word_id_vector = {commons.FEATURE_COL: word_id_vector}

bow_column = tf.feature_column.categorical_column_with_identity(commons.FEATURE_COL, num_buckets=params.N_WORDS)
bow_embedding_column = tf.feature_column.embedding_column(bow_column, dimension=50, combiner='sqrtn')
bow = tf.feature_column.input_layer(word_id_vector, feature_columns=[bow_embedding_column])
logits = tf.layers.dense(bow, 2, activation=None)

Приведенный выше код можно обернуть в Оценщик model_fn. Вышеупомянутое репо содержит этот код. Пожалуйста, взгляните на это.

person Kishore Karunakaran    schedule 22.02.2018
comment
Спасибо за пример, но это все равно не то, что мне нужно. Я точно использовал ваш код, форма «лука» - [размер_пакета, размер_встраивания], и мне нужно размер_пакета, макс_секвенс_лен, размер_встраивания]. Для меня это большая проблема. example incoming data: ["This is the first sentence", "This is another sentence", ...] тогда (после заполнения до max_seq_len) форма будет [batch_size, max_seq_len], затем, как только вы найдете все слова для их вложений, она должна быть [batch_size, max_seq_len, embedding_dim] (это то, что вы получаете, используя tf.get_variable () и tf.nn.embedding_lookup ()) - person Andrew Schenck; 22.02.2018
comment
Таким образом, имеет смысл, что результат input_layer не имеет ранга 3, из docs A Tensor, который представляет входной уровень модели. Его форма (batch_size, first_layer_dimension), а его dtype - float32. first_layer_dimension определяется на основе заданных feature_columns. Так разве input_layer - не то, что мне нужно использовать? Вроде хлюпает информацию о последовательности. Я попытался изменить его форму (подумав, что, возможно, он сплющится в первое измерение), но его размер на самом деле просто [batch_size, embedding_dim], а не что-то вроде [batch_size * seq_len, embedding_dim] - person Andrew Schenck; 22.02.2018

В итоге я сделал эту работу следующим образом: я сделал каждое слово функцией ввода, затем я просто выполняю преобразование wrd_2_idx, передаю его как функцию в числовом_колонке (s, у вас есть max_seq_lens из них), а затем передаю эти столбцы в input_layer. Затем в своем графике я использую эти функции и ищу вложения как обычно. В основном обходя поиск embedding_column, так как я не могу понять, как заставить его действовать так, как я хочу. Это, наверное, не оптимально, но работает и тренирует ...

Я оставлю это как принятый ответ и надеюсь, что когда-нибудь в будущем либо я найду лучший способ сделать это, либо кто-то другой может просветить меня, как лучше всего подойти к этому.

person Andrew Schenck    schedule 23.02.2018

Мне удалось заставить это работать ... также сошел с рельсов из-за того, что RNN не потреблял встраивание.

Что я сделал, чтобы это заработало (в простейшем случае):

#features[VALUE_FEATURE_NAME] is shape (?, 200), ie. 200 words per row
inputs = tf.contrib.layers.embed_sequence(
  features[VALUES_FEATURE_NAME], 3000, 5,
)

# create an LSTM cell of size 100
lstm_cell = tf.nn.rnn_cell.BasicLSTMCell(200)

# create the complete LSTM
_, final_states = tf.nn.dynamic_rnn(
    lstm_cell, inputs, dtype=tf.float32)
outputs = final_states.h 

Думаю, ответ кроется в документации по тензорному потоку для динамического rnn.

Создает повторяющуюся нейронную сеть, заданную ячейкой RNNCell.

Выполняет полностью динамическое развертывание входов.

Таким образом, развертывание здесь означает, что RNN потребляет [batch, time_steps, values] в качестве входных данных.

Лучшее

person wirtsi    schedule 21.02.2019

Вы можете использовать tf.contrib.feature_column.sequence_categorical_column_with_vocabulary_list и tf.contrib.feature_column.sequence_input_layer, чтобы решить эту проблему.

Демо-код выглядит следующим образом:

import tensorflow as tf
if __name__ == "__main__":
  #tf.enable_eager_execution()
  feature = {
      'aa': [['1', '2', '3'], 
             ['-1', '4', '-1'], 
             ['2', '-1', '-1'],
             ['4', '5', '6']]
  }

  aa_id = tf.contrib.feature_column.sequence_categorical_column_with_vocabulary_list(
      'aa', ['1', '2', '3', '4', '5']
    )
  seq_emb_matrix = tf.feature_column.embedding_column(aa_id, 2)
  seq_tensor, seq_length = tf.contrib.feature_column.sequence_input_layer(feature, [seq_emb_matrix])
  seq_tensor1, seq_length1 = tf.contrib.feature_column.sequence_input_layer(feature1, [seq_emb_matrix])
  seq_tensor2 = tf.squeeze(seq_tensor1)
  # print(tensor)
  with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    sess.run(tf.tables_initializer())
    a, a_len = sess.run([seq_tensor, seq_length])
    b, b_len = sess.run([seq_tensor1, seq_length1])
    print(a)
    print('a_len', a_len)
    print(a.shape)
    print('-'*50)
    print(b)
    print('b_len', b_len)
    print(b.shape)
    print(sess.run([seq_tensor2]))

результаты печати следующие:

[[[ 0.5333682  -0.39895234]
  [ 0.5335079   0.64998794]
  [-1.0432893  -0.8391434 ]]

 [[ 0.          0.        ]
  [-0.29623085 -0.17570129]
  [ 0.          0.        ]]

 [[ 0.5335079   0.64998794]
  [ 0.          0.        ]
  [ 0.          0.        ]]

 [[-0.29623085 -0.17570129]
  [ 0.7100604   0.9935588 ]
  [ 0.          0.        ]]]
('a_len', array([3, 3, 3, 3]))
(4, 3, 2)
--------------------------------------------------
[[[-0.24147142 -0.37740025]]

 [[-0.6222648   1.3862932 ]]

 [[ 1.2226609  -0.68292266]]]
('b_len', array([1, 1, 1]))
(3, 1, 2)
[array([[-0.24147142, -0.37740025],
       [-0.6222648 ,  1.3862932 ],
       [ 1.2226609 , -0.68292266]], dtype=float32)]
person Ocxs    schedule 21.08.2019