TensorFlowでモデルを保存して復元できない
受付中
回答 1
投稿
- 評価
- クリップ 0
- VIEW 2,728
問題
本を参考にしながらRNNで言語モデルを作って、いざ文章を生成しようとすると、
トレーニングと生成を同時に実行するとそれらしい文章が出来るが、
トレーニングと生成を別々に実行すると、ちゃんとrestoreされていないのか、でたらめな文章が生成される。
saver.save()
で保存されたファイルは以下の4つ
checkpoint
language-model.ckpt.data-00000-of-00001
language-model.ckpt.index
language-model.ckpt.meta
tensorflowのあるバージョンからはmetaファイルが生成されるので
self.saver = tf.train.import_meta_graph(os.path.join(ckpt_dir, 'language-model.ckpt.meta'))
が必要という情報があったので試してみても結果は変わらず、
エラーも特に出ていないので手詰まり状態です。
下記のコードに問題があるところはありますでしょうか?
環境
OS:macOS High Sierra 10.13.6
tensorflow 1.9.0
Pyton3.6
import numpy as np
# テキストを読み込んで処理
with open('wordDataSet', 'r', encoding='utf-8')as f:
text = f.read()
text = text[:]
chars = set(text)
char2int = {ch: i for i, ch in enumerate(chars)}
int2char = dict(enumerate(chars))
text_ints = np.array([char2int[ch] for ch in text], dtype=np.int32)
def reshape_data(sequence, batch_size, num_steps):
tot_batch_length = batch_size * num_steps
num_batches = int(len(sequence) / tot_batch_length)
print(len(sequence))
if num_batches * tot_batch_length + 1 > len(sequence):
num_batches = num_batches - 1
# シーケンスの最後の部分から完全なバッチにならない半端な文字を削除
x = sequence[0:num_batches * tot_batch_length]
y = sequence[1:num_batches * tot_batch_length + 1]
# xとyをシーケンスのバッチのリストに分割
x_batch_splits = np.split(x, batch_size)
y_batch_splits = np.split(y, batch_size)
# それらのバッチを結合
# batch_size×tot_batch_length
x = np.stack(x_batch_splits)
y = np.stack(y_batch_splits)
return x, y
def create_batch_generator(data_x, data_y, num_steps):
batch_size, tot_batch_length = data_x.shape
num_batches = int(tot_batch_length / num_steps)
for b in range(num_batches):
yield (data_x[:, b * num_steps:(b + 1) * num_steps],
data_y[:, b * num_steps:(b + 1) * num_steps])
def get_top_char(probas, char_size, top_n=2):
p = np.squeeze(probas)
p[np.argsort(p)[:-top_n]] = 0.0
p = p / np.sum(p)
ch_id = np.random.choice(char_size, 1, p=p)[0]
return ch_id
import tensorflow as tf
import os
class CharRNN(object):
def __init__(self, num_classes, batch_size=64, num_steps=100,
lstm_size=128, num_layers=1, learning_rate=0.001,
keep_prob=0.5, grad_clip=5, sampling=False):
self.num_classes = num_classes
self.batch_size = batch_size
self.num_steps = num_steps
self.lstm_size = lstm_size
self.num_layers = num_layers
self.learning_rate = learning_rate
self.keep_prob = keep_prob
self.grad_clip = grad_clip
self.g = tf.Graph()
with self.g.as_default():
tf.set_random_seed(123)
self.build(sampling=sampling)
self.saver = tf.train.Saver(max_to_keep=2)
self.init_op = tf.global_variables_initializer()
def build(self, sampling):
if sampling == True:
batch_size, num_steps = 1, 1
else:
batch_size = self.batch_size
num_steps = self.num_steps
tf_x = tf.placeholder(tf.int32,
shape=[batch_size, num_steps],
name='tf_x')
tf_y = tf.placeholder(tf.int32,
shape=[batch_size, num_steps],
name='tf_y')
tf_keepprob = tf.placeholder(tf.float32,
name='tf_keepprob')
# one-hotエンコーディングを適用
x_onehot = tf.one_hot(tf_x, depth=self.num_classes)
y_onehot = tf.one_hot(tf_y, depth=self.num_classes)
# 多層RNNのセルを構築
cells = tf.contrib.rnn.MultiRNNCell([tf.contrib.rnn.DropoutWrapper(
tf.contrib.rnn.BasicLSTMCell(self.lstm_size),
output_keep_prob=tf_keepprob) for _ in range(self.num_layers)])
# 初期状態を定義
self.initial_state = cells.zero_state(batch_size, tf.float32)
# RNNで各シーケンスステップを実行
lstm_outputs, self.final_state = tf.nn.dynamic_rnn(cells, x_onehot, initial_state=self.initial_state)
print(' << lstm_outputs >>', lstm_outputs)
# 二次元テンソルに変形
seq_output_reshaped = tf.reshape(lstm_outputs,
shape=[-1, self.lstm_size],
name='seq_output_reshaped')
# そう入力を取得
logits = tf.layers.dense(inputs=seq_output_reshaped,
units=self.num_classes,
activation=None,
name='logits')
# 次の文字バッチの確率を計算
proba = tf.nn.softmax(logits, name='probabilities')
# コスト関数を定義
y_reshaped = tf.reshape(y_onehot,
shape=[-1, self.num_classes],
name='y_reshaped')
cost = tf.reduce_mean(
tf.nn.softmax_cross_entropy_with_logits(logits=logits,
labels=y_reshaped),
name='cost')
# 勾配発散問題を回避するための勾配刈り込み
tvars = tf.trainable_variables()
grads, _ = tf.clip_by_global_norm(tf.gradients(cost, tvars),
self.grad_clip)
# オプティマイザを定義
optimizer = tf.train.AdamOptimizer(self.learning_rate)
train_op = optimizer.apply_gradients(zip(grads, tvars),
name='train_op')
def train(self, train_x, train_y, num_epochs, ckpt_dir='./model/'):
# チェックポイントディレクトリがまだ存在しない場合は作成
if not os.path.exists(ckpt_dir):
os.mkdir(ckpt_dir)
with tf.Session(graph=self.g) as sess:
sess.run(self.init_op)
n_batches = int(train_x.shape[1] / self.num_steps)
iterations = n_batches * num_epochs
for epoch in range(num_epochs):
# ネットワークをトレーニング
new_state = sess.run(self.initial_state)
loss = 0
# ミニバッチジェネレータ
bgen = create_batch_generator(train_x, train_y, self.num_steps)
for b, (batch_x, batch_y) in enumerate(bgen, 1):
iteration = epoch * n_batches + b
feed = {'tf_x:0': batch_x,
'tf_y:0': batch_y,
'tf_keepprob:0': self.keep_prob,
self.initial_state: new_state}
batch_cost, _, new_state = sess.run(
['cost:0', 'train_op',
self.final_state],
feed_dict=feed)
if iteration % 10 == 0:
print('Epoch %d/%d iteration %d| Training loss: %.4f' %
(epoch + 1, num_epochs, iteration, batch_cost))
# トレーニング済みのモデルを保存
self.saver.save(sess,
os.path.join(ckpt_dir, 'language-model.ckpt'))
def sample(self, output_length, ckpt_dir, starter_seq="電子書籍"):
observed_seq = [ch for ch in starter_seq]
with tf.Session(graph=self.g)as sess:
self.saver = tf.train.import_meta_graph(os.path.join(ckpt_dir, 'language-model.ckpt.meta'))
self.saver.restore(sess, tf.train.latest_checkpoint(ckpt_dir))
# 1: starter_seqを使ってモデルを実行
new_state = sess.run(self.initial_state)
for ch in starter_seq:
x = np.zeros((1, 1))
x[0, 0] = char2int[ch]
feed = {'tf_x:0': x, 'tf_keepprob:0': 1.0,
self.initial_state: new_state}
proba, new_state = sess.run(
['probabilities:0', self.final_state],
feed_dict=feed)
ch_id = get_top_char(proba, len(chars))
observed_seq.append(int2char[ch_id])
# 2: 更新されたobserved_seqを使ってモデルを実行
for i in range(output_length):
x[0, 0] = ch_id
feed = {'tf_x:0': x, 'tf_keepprob:0': 1.0,
self.initial_state: new_state}
proba, new_state = sess.run(
['probabilities:0', self.final_state],
feed_dict=feed)
ch_id = get_top_char(proba, len(chars))
observed_seq.append(int2char[ch_id])
return ''.join(observed_seq)
batch_size = 32
num_steps = 30
train_x, train_y = reshape_data(text_ints, batch_size, num_steps)
# モデルのトレーニング
rnn=CharRNN(num_classes=len(chars),batch_size=batch_size)
rnn.train(train_x,train_y,num_epochs=1000,ckpt_dir='./model-100/')
del rnn
# 文章生成
np.random.seed(123)
rnn = CharRNN(len(chars), sampling=True)
print(rnn.sample(ckpt_dir='./model-100/', output_length=500,starter_seq='明日は'))
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
0
参考になるかわかりませんけど自分の環境ではsave,restoreは以下のように記述したらrestoreできてるような気がします。
#self.saver
self.saver = tf.train.Saver()
#モデルの保存
self.saver.save(self.sess,"./checkpoint/m.ckpt")
#restore
ckpt = tf.train.get_checkpoint_state('./checkpoint')
if ckpt:#モデルファイルがあるとき
last_model = ckpt.model_checkpoint_path
self.saver.restore(self.sess, last_model)
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.20%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2018/08/23 14:44
同じ記述でやってみたのですが、結果は変わりませんでした。
一度、別の環境で試してみます。