Tensorflow自定义Estimator with Dataset API:嵌入查找(feature_column)NMT任务

问题描述 投票:2回答:3

我的问题与Feature Columns Embedding lookup的性质接近,但是我无法对那里给出的答案发表评论(没有足够的代表),我认为回答者要么没有完全理解这个问题,要么回答并不完全是问题。


目标

提供使用数据集API提供数据的自定义Estimator。任务是NMT(seq2seq)。


问题

Estimator需要feature_columns作为服务的输入。我的NMT任务只有一个特征,即要翻译的输入句子(或者句子中的每个单词都是一个特征?)。所以我不确定如何使用我的输入句子构建feature_column(因此是一个embedding_column,最后是一个input_layer),这个特性可以输入RNN(期望embedding_lookup [batch_size,max_seqence_len,embedding_dim])请允许我为Estimator提供服务。


背景

我试图利用自定义估算器来提供seq2seq样式的NMT实现。我需要能够通过服务提供服务模型,估计似乎相对容易。

然而,我打了一个“如何”为模型服务的路障。据我所知,我需要'feature_columns'作为模型的输入。

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

显示您需要具有export_input_fn,该export_input_fn使用需要feature_column作为输入的feature_spec。这是有道理的,但是,对于我的用例,我没有一堆(不同的)功能,而是我有输入句子(每个单词都是一个功能),需要通过嵌入查找并用作功能...

所以我知道我需要输入到我的模型中作为特征列。我对NMT的输入只是[batch_size,max_sequence_len]的张量,它填充了句子中单词的索引(例如,对于batch_size = 1 [3,17,132,2,1,0,...]其中每个索引应映射到嵌入向量)。通常我会将它提供给embedding_lookup via

    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/

显示'如何在自定义估算器中实现一个功能列',事实上他的'Before'代码完全正确(正如我写出来的),tf.get_variable到tf.nn.embedding_lookup,但他的'after'代码,再次,只接受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],它不仅仅是扁平...所以序列信息丢失了

我猜它必须将输入视为1个单输入特征(因此batch_size = 1 ex [3,17,132,2,1,0,...],其中每个索引映射到嵌入向量)将映射对于不是想要的单个特征,我们希望每个索引映射到嵌入,所需的输出是[batch_size,max_seq_len,embedding_dim]。

这听起来像我需要的,不是一个categorical_column_with_ *,而是max_seq_len的数量(我的序列中的每个单词为1),这听起来不对吗?每个单词都是我模型的一个特征,所以我倾向于这是正确的方法,但这也有问题。我正在使用数据集API,所以在我的input_train_fn()中我从一个文件加载我的数据,然后使用tf.data.Dataset.from_tensor_slices(数据,标签)将数据拆分成张量,然后我可以使用dataset.batch( batch_size).make_one_shot_iterator()。get_next()以提供给我的Estimator。我无法对每个批处理器进行迭代(测试器不可迭代)所以我不能简单地为每个输入批处理生成100个feature_columns ...

有谁知道怎么做?这种嵌入查找与简单的占位符或变量(以及NLP任务中的常用方法)非常简单。但是当我冒险进入数据集API和估算器时,我遇到的信息很少(这不是一个基本的例子)。

我承认我的理解可能存在差距,自定义估算器和数据集API对我来说是新的,有时难以找到有关它们的信息。所以随时向我发消息。

感谢您阅读我的文本墙,并希望帮助我(和我见过的其他人问一个类似的问题,但得不到答案https://groups.google.com/a/tensorflow.org/forum/#!searchin/discuss/embeddings $ 20in $ 20custom $ 20estimator / discuss / U3vFQF_jeaY / EjgwRQ3RDQAJ我觉得这个家伙不好,他的问题没有得到真正回答(出于同样的原因,这里概述了他的线程被劫持......)。

tensorflow tensorflow-serving tensorflow-datasets tensorflow-estimator
3个回答
0
投票

如果我理解正确,您希望使用Estimator API构建SeqSeq模型。启动here的好地方,查看Problems-Solutions / text文件夹。

要回答关于如何使用嵌入查找的问题,这是一个例子

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)

上面的代码可以包含在Estimator model_fn中。上面的repo包含此代码。请看一下。


0
投票

所以我最终完成这项工作的方式是我将每个单词作为输入要素,然后我只是进行wrd_2_idx转换,将其作为numeric_column中的一个要素传递(s,你有max_seq_lens这些),然后将这些列传递给input_layer。然后在我的图表中,我使用这些功能并正常查找嵌入。基本上绕过了embedding_column查找,因为我无法弄清楚如何让它按照我想要的方式运行。这可能不是最佳的,但它可以工作和训练......

我会把这作为公认的答案,希望将来某个时候或者我找到一个更好的方法来做,或者其他人可以启发我以最好的方式来解决这个问题。


0
投票

我设法让这个工作......由于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的tensorflow文档

创建由RNNCell单元指定的递归神经网络。

执行完全动态展开输入。

因此,这里的展开意味着RNN消耗[batch,time_steps,values]作为输入。

贝斯茨


0
投票

您可以使用tf.contrib.feature_column.sequence_categorical_column_with_vocabulary_listtf.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)]
© www.soinside.com 2019 - 2024. All rights reserved.