2016-07-27 15 views
4

私はテキストフレーズの推論を実行するためにTensorflowモデルを構築しています。 簡略化のために、出力クラスが固定数で、可変長テキストが入力されたの分類子が必要です。言い換えれば、私のミニバッチはフレーズのシーケンスですが、すべてのフレーズが同じ長さではありません。Tensorflowでの可変長テキストの操作

data = ['hello', 
     'my name is Mark', 
     'What is your name?'] 

私の最初の前処理ステップは、辞書内のすべての可能な単語の辞書を構築し、各単語を整数word-Idにマッピングすることでした。入力は次のようになります。

data = [[1], 
     [2, 3, 4, 5], 
     [6, 4, 7, 3] 

このような入力を処理するにはどうすればよいでしょうか? tf.placeholder()は同じバッチのデータ内で可変サイズの入力を処理できますか? また、すべての文字列の長さが同じ長さで、長さの長い文字列の長さに等しいように、欠落している単語のプレースホルダを使用するようにする必要がありますか?これは、ある文字列が他のほとんどの文字列よりもはるかに長い場合、非常にメモリ非効率であるようです。

- EDIT -

ここに具体例があります。

私は私のデータポイントの大きさを知っている私は、通常のようなものを使用(およびすべてのデータポイントは、例えば、同じ長さを持つ3。):

プレースホルダの最初の次元がminibatchサイズです
input = tf.placeholder(tf.int32, shape=(None, 3) 

with tf.Session() as sess: 
    print(sess.run([...], feed_dict={input:[[1, 2, 3], [1, 2, 3]]})) 

を。

入力シーケンスが異なる長さの文中の単語の場合はどうなりますか?

feed_dict={input:[[1, 2, 3], [1]]} 
+0

テキストは、しばしばシーケンスモデルによって処理されます。 IEでは、あなたのモデルは前のステップの現在の単語と出力を受け入れ、モデルのコピーを積み重ねます。ベースラインとして、「単語の袋」から始めることができます。すべての単語を1つの辞書ベクトルにまとめて追加するだけです。 –

+0

お返事ありがとうございます。私の質問は、Tensorflowのデータ構造がモデルよりも重要です。私はbag-of-wordsで表現されたテキストを与えられたRNNを使うことができます。それでもデータポイントの長さが異なる場合、このデータをどこに保存するのですか? – Marco

+0

単語の埋め込みに関する削除の参照を編集し、私の質問を明確にするための具体的な例を示しました。 – Marco

答えて

0

私は、先日、配列翻訳者に配列を構築していました。私がしたことは、あなたが望む限り長くすることができますが、平均的な文章の長さを少し超えた32語の固定長さにすることでした。その後、NULL単語を辞書に追加して、すべての文章ベクトルをそれに追加しました。そうすれば、私のシーケンスの終わりがどこにあったかをモデルに伝えることができ、モデルは出力の終わりにNULLを出力するだけです。たとえば、「あなたの名前は何ですか?」という表現を取ってください。これは "あなたの名前は何ですか?NULL NULL NULL NULL NULL ... NULL"になります。それはかなりうまくいっていますが、トレーニング中の損失と正確さは、モデルが通常、コストに当てはめるNULLsの権利を得ているため、実際には少し高いように見えます。

マスキングと呼ばれる別のアプローチがあります。これにより、固定長シーケンスのモデルを作成することもできますが、より短いシーケンスの最後までコストを評価するだけです。出力シーケンス(または期待される出力のいずれか大きい方)でNULLの最初のインスタンスを検索し、そのポイントまでのコストのみを評価することができます。また、tf.dynamic_rnnのようないくつかのテンソルフロー関数は、よりメモリ効率の良いマスキングをサポートしていると思います。私はパッディングの最初のアプローチを試みただけなので、わからない。

最後に、Seq2Seqモデルのテンソルフローの例では、さまざまなサイズのシーケンスにバケットを使用しています。これはおそらくあなたの記憶の問題を解決するでしょう。異なるサイズのモデル間で変数を共有できると思います。だからここ

0

(正直に言うとその100%であれば正しい方法がわからない)私がやったことです:

各キーはある特定の単語を指す数であるあなたの単語辞書には、別のキーを追加するにはKを言います今"<PAD>"(またはあなたがパディングに使用する任意の他の表現)

を指している入力のためのプレースホルダは、次のようになります。

なしあなたの最も大きいフレーズ/文/レコードを表していない
x_batch = tf.placeholder(tf.int32, shape=(batch_size, None)) 

ミニバッチ。

私が使った別の小さなトリックは、各フレーズの長さをミニバッチに保存することでした。私の入力であった場合

は:たとえばx_batch = [[1], [1,2,3], [4,5]] その後、私が保存:len_batch = [1, 3, 2]

後、私は、バイナリマスクを作成するために、私のminibatchにこのlen_batchやフレーズ(l_max)の最大サイズを使用します。今l_max=3上から、私のマスクは、このようなものになりますので:今

mask = [ 
[1, 0, 0], 
[1, 1, 1], 
[1, 1, 0] 
] 

を、あなたの損失でこれを掛ける場合は、基本的には、パディングの結果として導入されたすべての損失を排除するであろう。

これが役に立ちます。

1

その他の2つの回答は正確ですが、詳細は低いです。私はちょうどこれを自分で行う方法を見ていた。

Tensorには機械があり、このすべてに機械があります(一部の部分では過度なことがあります)。

文字列テンソルからスタート(形状[3]):(。疑問符の前にスペースを注意してください)

import tensorflow as tf 
lines = tf.constant([ 
    'Hello', 
    'my name is also Mark', 
    'Are there any other Marks here ?']) 
vocabulary = ['Hello', 'my', 'name', 'is', 'also', 'Mark', 'Are', 'there', 'any', 'other', 'Marks', 'here', '?'] 

単語にこれを分割されて最初に行うべきこと

words = tf.string_split(lines," ") 

言葉は疎テンソル(形[3,7])になります。インデックスの2つの次元が[行番号、位置]である場合。今、あなたは単語の検索を行うことができます

indices values 
0 0  'hello' 
1 0  'my' 
1 1  'name' 
1 2  'is' 
... 

::これは、次のように表現され

table = tf.contrib.lookup.index_table_from_tensor(vocabulary) 
word_indices = table.lookup(words) 

これは彼らの語彙指標に置き換え言葉でスパーステンソルを返します。そうしてみましょう...あなたはそれがLSTMに置くことはおそらくだ可変長シーケンスを処理しているのであれば

line_number = word_indices.indices[:,0] 
line_position = word_indices.indices[:,1] 
lengths = tf.segment_max(data = line_position, 
         segment_ids = line_number)+1 

今、あなたは、各ライン上の最大値の位置を見て、シーケンスの長さを読み出すことができますワード埋め込み(それが密入力を必要とする)入力のために使用します。今の形状を有することになる埋め込み

EMBEDDING_DIM = 100 

dense_word_indices = tf.sparse_tensor_to_dense(word_indices) 
e_layer = tf.contrib.keras.layers.Embedding(len(vocabulary), EMBEDDING_DIM) 
embedded = e_layer(dense_word_indices) 

を[3,7,100]、[行、単語、embedding_dim]。

次に簡単なLSTMを構築することができます。

LSTM_SIZE = 50 
lstm = tf.nn.rnn_cell.BasicLSTMCell(LSTM_SIZE) 

とパディングを扱う、シーケンス全体を実行します。

outputs, final_state = tf.nn.dynamic_rnn(
    cell=lstm, 
    inputs=embedded, 
    sequence_length=lengths, 
    dtype=tf.float32) 

出力は[3,7,50]、または[line、word、lstm_size]という形になりました。

from tensorflow.contrib.learn.python.learn.estimators.rnn_common import select_last_activations 
final_output = select_last_activations(outputs,tf.cast(lengths,tf.int32)) 

すべてのインデックスは、最後のタイムステップからの出力を選択するようにシャッフルん:あなたは、各ラインの最後のワードで状態をつかむしたい場合は、(!!隠された文書化されていない)select_last_activations機能を使用することができます。これは私がまだ詳細を働いていない[3,50]の大きさまたは[行、lstm_size]

init_t = tf.tables_initializer() 
init = tf.global_variables_initializer() 
with tf.Session() as sess: 
    init_t.run() 
    init.run() 
    print(final_output.eval().shape()) 

を与えるが、私は、これはおそらく、すべてを単一のtf.contrib.learn.DynamicRnnEstimatorに置き換えることができると思います。

関連する問題