https://www.tensorflow.org/tutorials/recurrent でサンプルコードを理解しようとしていますが、これは https://github.com/tensorflow/で見つけることができますmodels/blob/master/tutorials/rnn/ptb/ptb_Word_lm.py
(テンソルフロー1.3.0を使用。)
私の質問の主要な部分を以下に要約します(私が思うに):
_ size = 200
vocab_size = 10000
layers = 2
# input_.input_data is a 2D tensor [batch_size, num_steps] of
# Word ids, from 1 to 10000
cell = tf.contrib.rnn.MultiRNNCell(
[tf.contrib.rnn.BasicLSTMCell(size) for _ in range(2)]
)
embedding = tf.get_variable(
"embedding", [vocab_size, size], dtype=tf.float32)
inputs = tf.nn.embedding_lookup(embedding, input_.input_data)
inputs = tf.unstack(inputs, num=num_steps, axis=1)
outputs, state = tf.contrib.rnn.static_rnn(
cell, inputs, initial_state=self._initial_state)
output = tf.reshape(tf.stack(axis=1, values=outputs), [-1, size])
softmax_w = tf.get_variable(
"softmax_w", [size, vocab_size], dtype=data_type())
softmax_b = tf.get_variable("softmax_b", [vocab_size], dtype=data_type())
logits = tf.matmul(output, softmax_w) + softmax_b
# Then calculate loss, do gradient descent, etc.
_
私の最大の質問は、文の最初のいくつかの単語が与えられたときに、生成されたモデルを使用して次のWord提案を実際に生成する方法です?具体的には、フローは次のようになっていると思いますが、コメント行のコードがどうなるかについて頭を悩ますことはできません。
_prefix = ["What", "is", "your"]
state = #Zeroes
# Call static_rnn(cell) once for each Word in prefix to initialize state
# Use final output to set a string, next_Word
print(next_Word)
_
私のサブ質問は次のとおりです。
(私はそれらをすべて一つの質問として尋ねています。それらはすべてつながっており、私の理解のあるギャップにつながっていると思うからです。)
ここで期待していたのは、既存のWord2vecのWord埋め込みセットを読み込み(たとえばgensimのKeyedVectors.load_Word2vec_format()
を使用して)、各文を読み込むときに入力コーパスの各Wordをその表現に変換し、その後LSTM同じ次元のベクトルを吐き出し、最も類似したWordを見つけようとします(たとえば、gensimのsimilar_by_vector(y, topn=1)
を使用)。
Softmaxを使用すると、比較的遅いsimilar_by_vector(y, topn=1)
呼び出しから私たちを救いますか?
ところで、私の質問の既存のWord2vec部分については Word生成にLSTMで事前に訓練されたWord2vecを使用する も同様です。しかし、現在の答えは、私が探しているものではありません。私が望んでいるのは、わかりやすい英語の説明であり、私に光を灯し、私の理解のギャップが何であれプラグインします。 lstm言語モデルで事前に訓練されたWord2vecを使用しますか? も同様の質問です。
UPDATE:言語モデルのテンソルフローの例を使用した次の単語の予測 および LSTM ptbモデルを使用した次の単語の予測tensorflow example も同様の質問です。ただし、実際には文の最初のいくつかの単語を取得し、次の単語の予測を印刷するコードは表示されません。 2番目の質問と https://stackoverflow.com/a/39282697/8418 (githubブランチに付属)からのコードを貼り付けましたが、エラーなしで実行できません。 TensorFlowの以前のバージョン用だと思いますか?
ANOTHER UPDATE:さらに基本的に同じことを尋ねる別の質問: Tensorflowの例からLSTMモデルの次の単語を予測する リンク先- 言語モデルのテンソルフローの例を使用して次のWordを予測する (そして、また、そこにある答えは私が探しているものとはまったく異なります)。
まだ明確でない場合、getNextWord(model, sentencePrefix)
と呼ばれる高レベル関数を記述しようとしています。ここで、model
は、ディスクからロードした以前に構築されたLSTMです。 sentencePrefix
は「Open the」などの文字列で、「pod」を返す場合があります。次に、「ポッドを開く」で呼び出すと、「ベイ」が返されます。
例(キャラクターRNNを使用し、mxnetを使用)は、 https://github.com/zackchase/mxnet-the-straight-Dope/blobの終わり近くに表示されるsample()
関数です。 /master/chapter05_recurrent-neural-networks/simple-rnn.ipynb トレーニング中にsample()
を呼び出すことができますが、トレーニング後に必要な文で呼び出すこともできます。
私の最大の質問は、作成されたモデルを使用して、文の最初のいくつかの単語を考慮して、実際に次の単語の提案を生成する方法ですか?
つまり署名付き関数を作成しようとしています:getNextWord(model、statementPrefix)
答えを説明する前に、まず# Call static_rnn(cell) once for each Word in prefix to initialize state
への提案について発言します。_static_rnn
_はnumpy配列のような値ではなくテンソルを返すことに注意してください。 (1)セッション(セッションは、モデルパラメーターの値を含む計算グラフの状態を保持します)および(2)計算に必要な入力で、実行時に値に対するテンソルを評価できますテンソル値。入力は、入力リーダー(チュートリアルのアプローチ)またはプレースホルダー(以下で使用するもの)を使用して提供できます。
実際の答えは次のとおりです。チュートリアルのモデルは、ファイルから入力データを読み取るように設計されています。 @ user3080953の答えは、独自のテキストファイルを操作する方法をすでに示しましたが、私が理解しているように、データをモデルに供給する方法をさらに制御する必要があります。これを行うには、独自のプレースホルダーを定義し、session.run()
を呼び出すときにこれらのプレースホルダーにデータを供給する必要があります。
以下のコードでは、PTBModel
をサブクラス化し、モデルにデータを明示的に供給する役割を担っています。 PTBInteractiveInput
に似たインターフェースを持つ特別なPTBInput
を導入したので、PTBModel
の機能を再利用できます。モデルをトレーニングするには、PTBModel
が必要です。
_class PTBInteractiveInput(object):
def __init__(self, config):
self.batch_size = 1
self.num_steps = config.num_steps
self.input_data = tf.placeholder(dtype=tf.int32, shape=[self.batch_size, self.num_steps])
self.sequence_len = tf.placeholder(dtype=tf.int32, shape=[])
self.targets = tf.placeholder(dtype=tf.int32, shape=[self.batch_size, self.num_steps])
class InteractivePTBModel(PTBModel):
def __init__(self, config):
input = PTBInteractiveInput(config)
PTBModel.__init__(self, is_training=False, config=config, input_=input)
output = self.logits[:, self._input.sequence_len - 1, :]
self.top_Word_id = tf.argmax(output, axis=2)
def get_next(self, session, prefix):
prefix_array, sequence_len = self._preprocess(prefix)
feeds = {
self._input.sequence_len: sequence_len,
self._input.input_data: prefix_array,
}
fetches = [self.top_Word_id]
result = session.run(fetches, feeds)
self._postprocess(result)
def _preprocess(self, prefix):
num_steps = self._input.num_steps
seq_len = len(prefix)
if seq_len > num_steps:
raise ValueError("Prefix to large for model.")
prefix_ids = self._prefix_to_ids(prefix)
num_items_to_pad = num_steps - seq_len
prefix_ids.extend([0] * num_items_to_pad)
prefix_array = np.array([prefix_ids], dtype=np.float32)
return prefix_array, seq_len
def _prefix_to_ids(self, prefix):
# should convert your prefix to a list of ids
pass
def _postprocess(self, result):
# convert ids back to strings
pass
_
PTBModel
の___init__
_関数では、次の行を追加する必要があります。
_self.logits = logits
_
ランダムな(初期化されていない、訓練されていない)ワード埋め込みを使用する理由
最初に、埋め込みは最初はランダムですが、残りのネットワークでトレーニングされることに注意してください。トレーニング後に取得する埋め込みには、Word2vecモデルで取得する埋め込みと同様の特性があります。たとえば、ベクトル演算(キング-男性+女性=女王など)で類推の質問に答える能力です。言語モデリング(注釈付きトレーニングデータを必要としない)やニューラル機械翻訳などのトレーニングデータの場合、埋め込みを最初からトレーニングする方が一般的です。
なぜsoftmaxを使用するのですか?
Softmaxは、類似度スコア(ロジット)のベクトルを確率分布に正規化する関数です。クロスエントロピー損失を使用してモデルをトレーニングし、モデルからサンプリングできるようにするには、確率分布が必要です。訓練されたモデルの最も可能性の高い単語のみに関心がある場合は、softmaxは必要なく、ロジットを直接使用できることに注意してください。
非表示レイヤーは、入力の次元(つまり、Word2vec埋め込みの次元)と一致する必要がありますか
いいえ、原則として任意の値を指定できます。ただし、埋め込みディメンションよりも低いディメンションで非表示の状態を使用することはあまり意味がありません。
初期化されていないモデルの代わりに、事前にトレーニングされたWord2vecモデルをどのように取り込むことができますか?
以下は、指定されたnumpy配列で埋め込みを初期化する自己完結型の例です。トレーニング中に埋め込みを固定/一定のままにする場合は、trainable
をFalse
に設定します。
_import tensorflow as tf
import numpy as np
vocab_size = 10000
size = 200
trainable=True
embedding_matrix = np.zeros([vocab_size, size]) # replace this with code to load your pretrained embedding
embedding = tf.get_variable("embedding",
initializer=tf.constant_initializer(embedding_matrix),
shape=[vocab_size, size],
dtype=tf.float32,
trainable=trainable)
_
テストセットを使用する代わりにカスタムデータをロードします。
reader.py@ptb_raw_data
test_path = os.path.join(data_path, "ptb.test.txt")
test_data = _file_to_Word_ids(test_path, Word_to_id) # change this line
test_data
にはWord IDを含める必要があります(マッピング用にWord_to_id
を出力します)。例として、次のようになります。[1、52、562、246] ...
sess.run
への呼び出しで、FCレイヤーの出力(logits
)を返す必要があります
ptb_Word_lm.py@PTBModel.__init__
logits = tf.reshape(logits, [self.batch_size, self.num_steps, vocab_size])
self.top_Word_id = tf.argmax(logits, axis=2) # add this line
ptb_Word_lm.py@run_Epoch
fetches = {
"cost": model.cost,
"final_state": model.final_state,
"top_Word_id": model.top_Word_id # add this line
}
関数の後半で、vals['top_Word_id']
には、最上位のWordのIDを持つ整数の配列があります。 Word_to_id
でこれを調べて、予測された単語を決定します。私は少し前に小さなモデルでこれを行いましたが、トップ1の精度はかなり低かった(20〜30%iirc)。
ランダムな(初期化されていない、訓練されていない)ワード埋め込みを使用する理由
著者に尋ねる必要がありますが、私の意見では、埋め込みをトレーニングすると、これはスタンドアロンのチュートリアルになります:埋め込みをブラックボックスとして扱うのではなく、それがどのように機能するかを示します。
なぜsoftmaxを使用するのですか?
最終的な予測は、notであり、隠れ層の出力に対するコサインの類似性によって決定されます。 LSTMの後には、埋め込まれた状態を最終的なWordのワンホットエンコードに変換するFCレイヤーがあります。
ニューラルネットの操作と次元のスケッチを次に示します。
Word -> one hot code (1 x vocab_size) -> embedding (1 x hidden_size) -> LSTM -> FC layer (1 x vocab_size) -> softmax (1 x vocab_size)
非表示レイヤーは、入力の次元(つまり、Word2vec埋め込みの次元)と一致する必要がありますか
技術的にはありません。 LSTMの方程式を見ると、重み行列が適切に調整されている限り、x(入力)は任意のサイズにできます。
初期化されていないモデルの代わりに、事前にトレーニングされたWord2vecモデルをどのように取り込むことができますか?
わかりません、ごめんなさい。
多くの質問がありますが、そのうちのいくつかを明確にしようと思います。
作成されたモデルを使用して、文の最初の数語を実際に次のWord提案を生成するにはどうすればよいですか?
ここで重要なことは、次のワード生成は実際には語彙のワード分類であるということです。したがって、分類器が必要です。そのため、出力にソフトマックスがあります。
原則は、各タイムステップで、最後の単語の埋め込みと前の単語の内部メモリに基づいて、モデルが次の単語を出力することです。 tf.contrib.rnn.static_rnn
入力をメモリに自動的に結合しますが、最後のWord埋め込みを提供し、次のWordを分類する必要があります。
事前トレーニング済みのWord2vecモデルを使用できます。事前にトレーニング済みのembedding
マトリックスを初期化します。チュートリアルでは、単純化のためにランダム行列を使用していると思います。メモリサイズは埋め込みサイズとは関係ありません。メモリサイズを大きくすると、より多くの情報を保持できます。
これらのチュートリアルは高レベルです。詳細を深く理解したい場合は、プレーンpython/numpyのソースコードを参照することをお勧めします。