私はまったく同じ目標に向かって取り組んできましたが、それを機能させました。ここには多くの適切な変更がありますが、いくつかの手順を見逃していると思います.
まず、テキストを生成するには、単一のタイムステップのみを表すモデルの別のバージョンを作成する必要があります。その理由は、モデルの次のステップにフィードする前に、各出力 y をサンプリングする必要があるためです。num_steps
これを行うには、 とbatch_size
両方を 1に設定する新しい構成を作成しました。
class SmallGenConfig(object):
"""Small config. for generation"""
init_scale = 0.1
learning_rate = 1.0
max_grad_norm = 5
num_layers = 2
num_steps = 1 # this is the main difference
hidden_size = 200
max_epoch = 4
max_max_epoch = 13
keep_prob = 1.0
lr_decay = 0.5
batch_size = 1
vocab_size = 10000
また、次の行を使用してモデルに確率を追加しました。
self._output_probs = tf.nn.softmax(logits)
と
@property
def output_probs(self):
return self._output_probs
次に、私の機能にはいくつかの違いがありgenerate_text()
ます。tf.train.Saver()
1 つ目は、オブジェクトを使用してディスクから保存されたモデル パラメータをロードすることです。上記の新しい構成で PTBModel をインスタンス化した後にこれを行うことに注意してください。
def generate_text(train_path, model_path, num_sentences):
gen_config = SmallGenConfig()
with tf.Graph().as_default(), tf.Session() as session:
initializer = tf.random_uniform_initializer(-gen_config.init_scale,
gen_config.init_scale)
with tf.variable_scope("model", reuse=None, initializer=initializer):
m = PTBModel(is_training=False, config=gen_config)
# Restore variables from disk.
saver = tf.train.Saver()
saver.restore(session, model_path)
print("Model restored from file " + model_path)
2 つ目の違いは、ID から単語文字列へのルックアップ テーブルを取得することです (この関数を作成する必要がありました。以下のコードを参照してください)。
words = reader.get_vocab(train_path)
私はあなたと同じ方法で初期状態をセットアップしましたが、別の方法で初期トークンをセットアップしました。「文の終わり」トークンを使用して、適切な種類の単語で文を開始したいと考えています。単語インデックスを調べたところ、<eos>
たまたまインデックス 2 (決定論的) を持っていることがわかったので、それをハードコーディングしました。
state = m.initial_state.eval()
x = 2 # the id for '<eos>' from the training set
input = np.matrix([[x]]) # a 2D numpy matrix
最後に、文を生成する部分です。とsession.run()
を計算するように指示していることに注意してください。そして、入力と状態を与えます。最初の反復では、入力はであり、状態は ですが、後続の反復では、最後にサンプリングされた出力を入力として与え、最後の反復から状態を渡します。リストを使用して、出力インデックスから単語文字列を検索することにも注意してください。output_probs
final_state
<eos>
initial_state
words
text = ""
count = 0
while count < num_sentences:
output_probs, state = session.run([m.output_probs, m.final_state],
{m.input_data: input,
m.initial_state: state})
x = sample(output_probs[0], 0.9)
if words[x]=="<eos>":
text += ".\n\n"
count += 1
else:
text += " " + words[x]
# now feed this new word as input into the next iteration
input = np.matrix([[x]])
あとは、蓄積したテキストを印刷するだけです。
print(text)
return
関数は以上ですgenerate_text()
。
get_vocab()
最後に、reader.py に記述した の関数定義を示します。
def get_vocab(filename):
data = _read_words(filename)
counter = collections.Counter(data)
count_pairs = sorted(counter.items(), key=lambda x: (-x[1], x[0]))
words, _ = list(zip(*count_pairs))
return words
最後に行う必要があるのは、トレーニング後にモデルを保存できるようにすることです。これは次のようになります。
save_path = saver.save(session, "/tmp/model.ckpt")
これは、後でテキストを生成するときにディスクからロードするモデルです。
もう 1 つ問題がありました。Tensorflow のソフトマックス関数によって生成される確率分布の合計が正確に 1.0 にならないことがあることがわかりました。合計が 1.0 より大きい場合np.random.multinomial()
、エラーがスローされます。そのため、次のような独自のサンプリング関数を作成する必要がありました
def sample(a, temperature=1.0):
a = np.log(a) / temperature
a = np.exp(a) / np.sum(np.exp(a))
r = random.random() # range: [0,1)
total = 0.0
for i in range(len(a)):
total += a[i]
if total>r:
return i
return len(a)-1
これらすべてをまとめると、小さなモデルは私にいくつかのクールな文章を生成することができました. 幸運を。