【Tensorflow RNN】for文でパラメータを変えながら実行
受付中
回答 1
投稿
- 評価
- クリップ 0
- VIEW 1,114
前提・実現したいこと
Tensorflowで3か所の雨量と1か所の水位をそれぞれ72時間分読み込んで、1時間先の水位を予測しています。
for文でニューロン数、バッチサイズを変更しつつ、最適なパラメータを探そうと思っています。
学習に使用するデータがランダムに抽出されるため、各ケース5回ずつ試行したいです。
(jupyter notebookで実行しています)
発生している問題・エラーメッセージ
エラーが出ずに実行はできるものの、2回目の試行以降lossグラフが1回目と全く異なります。
また、予測結果も2回目の試行以降は極端に悪い結果となります。
前回試行の結果が残っているのでしょうか?
for文を使わずに手動でパラメータを変更し再試行すると、多少の変化はあるもののこのような結果にはなりません。
該当のソースコード
全文は長いのでfor文の中身のみ記載します。
case_no = 0
for n_neurons in neuron_list:
for batch_size in batch_size_list:
for try_no in try_list:
case_no += 1 #通し番号
save_FileName = "WaterL_3rain"
# 保存ファイルのパスを設定--------------------------------------
save_FileName = "no"+'{:03}'.format(case_no)+"_"+save_FileName+".ckpt"
saveFN = os.path.join(Project_Dir, save_Dir, save_FileName)
if not os.path.isdir(saveFN):
os.makedirs(saveFN)
fig_FN = "no"+'{:03}'.format(case_no)+"_try"+str(try_no) +"_"+ fig_FN_ini + "_batch"+str(batch_size)+"_n"+str(n_neurons)
fig_title = "no"+str(case_no)+"try"+str(try_no) +" "+ fig_title_ini +str(n_neurons)+ "_batch"+str(batch_size)
reset_graph() # Reset
#モデル作成***********************************************************************************
# 変数 -----------------------------------------
X = tf.placeholder(tf.float32, [None, n_steps, n_inputs])
y = tf.placeholder(tf.float32, [None, n_steps, n_outputs])
# LSTM CELL ----------------------------------------------------------
# OutputProjectionWrapper のセルラッパで全結合層を追加したRNNCell
if useCELL == "LSTM":
rnn_CELL = tf.contrib.rnn.OutputProjectionWrapper(
tf.contrib.rnn.BasicLSTMCell(num_units=n_neurons, activation=nn_activation),
output_size=n_outputs)
elif useCELL == "GRU":
rnn_CELL = tf.contrib.rnn.OutputProjectionWrapper(
tf.contrib.rnn.GRUCell(num_units=n_neurons, activation=nn_activation),
output_size=n_outputs)
else:
print("CELL- Input Error : ",useCELL)
sys.exit
# モデルを定義(計算グラフ)Outputs--------------------------------------
outputs, states = tf.nn.dynamic_rnn(rnn_CELL, X, dtype=tf.float32)
# 損失関数 , 最適化関数の設定 -------------------------------------------
loss = tf.reduce_mean(tf.square(outputs - y)) # 損失関数(MSE)
#optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate) # 損失関数を最小化するための最適化関数を設定(学習率の設定)
training_op = optimizer.minimize(loss) # 訓練オペレーション(最小化)
#初期化----------------------------------------------------
init = tf.global_variables_initializer() # モデル初期化
early_stopping = EarlyStopping(err_frequency,bln_break) # 学習早期打ち切り
# 保存Saver設定
saver = tf.train.Saver()
#トレーニング開始*************************************************************************************
#モデルの初期化とトレーニング
gpuConfig = tf.ConfigProto(gpu_options=tf.GPUOptions(allow_growth=True))
with tf.Session(config=gpuConfig) as sess:
init.run()
#グラフ用の誤差保存用変数
val_loss = []
iterations = []
for iteration in range(n_iterations):
X_batch, y_batch, batch_num,t0_check = next_batch(batch_size, n_steps, n_inputs, t_min, t_max)
sess.run(training_op, feed_dict={X: X_batch, y: y_batch})
mse = loss.eval(feed_dict={X: X_batch, y: y_batch})
val_loss.append(mse)
iterations.append(iteration)
if early_stopping.validate(mse):
break
saver.save(sess, saveFN) # training結果の保存
#グラフ化
val_loss_sqrt = np.sqrt(val_loss)
plt.figure()
plt.plot(iterations,val_loss_sqrt,"b-",linewidth=1,label="loss")
plt.legend(loc="upper right")
plt.ylabel("Loss (m)")
plt.xlabel("Iteration")
save_fig("no"+'{:03}'.format(case_no) + "_loss_training")
#plt.show()
# テスト***********************************************************************************
# Test用データの読込み
test_Path = os.path.join(Project_Dir,Input_Dir,test_FN)
test_data = np.loadtxt(test_Path,delimiter=",",skiprows = 1,usecols=(1,2,3,4))
test_wl = test_data[:,0]
test_rain=test_data[:,1:4]
#-------------------------------------------------------------------------------------
test_num = test_data.shape[0] # 0行目を含むデータ数
tot_time=np.arange(test_num) # arange はtest_numを含まないのでデータ数は合致
t_delta = np.arange(2,t_pred+1) # 時間のtensor
with tf.Session() as sess: # Test実行
saver = tf.train.Saver()
saver.restore(sess,saveFN) # training結果の読込み ************
sequence =[] #予測結果を逐次格納する(予測バッチの最終時間のみ格納される)
t0 = t_start - n_steps # バッチの開始時間
wl_seq = test_wl[t0:t_start+1] #予測開始時点までの水位データ 以後予測値を追加する
test_batch = test_data[t0:t_start,:].reshape(-1,n_steps,n_inputs) #予測用のインプットバッチテンソル
y_pred = sess.run(outputs, feed_dict={X:test_batch}) #ループ前に一度予測
sequence = np.append(sequence,y_pred[0,-1,0]) #予測結果を格納するsequence
loss_test = np.zeros(n_steps+2) #予測誤差を格納(グラフ用)
se_test = np.zeros(n_steps+2) #予測の二乗誤差を格納
for dt in t_delta:
ts = t0 + dt
te = ts + n_steps
rain_batch = test_rain[ts:te].reshape(-1,3) # ***** 降雨変数 3 ******
wl_seq = np.append(wl_seq,sequence[sequence.shape[0]-1]) # sequenceの最終データを追加
wl_batch = wl_seq[dt:dt+n_steps+1].reshape(-1,1) # 水位のバッチ 水位変数 1
test_batch = np.insert(wl_batch,[1],rain_batch,axis=1) # インプットのためのバッチリスト作成
X_test_batch = test_batch.reshape(-1,n_steps,n_inputs) # インプット用バッチテンソル
y_pred = sess.run(outputs, feed_dict={X:X_test_batch}) # 予測計算
sequence = np.append(sequence,y_pred[0,-1,0]) # 予測結果を追加
squre_error = (y_pred[0,-1,0] - test_wl[te])**2 # 二乗誤差
se_test = np.append(se_test,squre_error)
loss_test =np.append(loss_test,np.sqrt(squre_error)) # 予測誤差(m)
# 出力時間設定(X軸)----------------------------------------------------------------------------
t_max = t_start + t_pred
t_=np.arange(t_start-n_steps,t_max+1)
#予測誤差
loss_mean = np.mean(loss_test) #平均予測誤差
rmse_test = np.sqrt(np.mean(se_test)) #RMSE
#グラフ設定
fig_loss_title = "MAE:" + '{: .3f}'.format(loss_mean) + "m RSME:"+'{: .3f}'.format(rmse_test)
plt.figure(figsize=(10,5))
ymax_plt = 6
ymin_plt = 0
plt.ylim(ymin_plt,ymax_plt)
#プロット
plt.title(fig_loss_title, fontsize=11)
plt.plot(t_[:], loss_test[:], "b-", linewidth=1, label="loss") #dtは2から
plt.legend(loc="upper right")
plt.ylabel("tolerancean (m)")
plt.xlabel("time")
save_fig("no"+'{:03}'.format(case_no) + "_loss_test")
#誤差取得
max_calc = np.max(sequence)
max_measured = np.max(test_data[t_start-n_steps:t_max+1,0])
loss_at_peak = max_calc - max_measured
# グラフ設定
plt.figure(figsize=(10,5))
#figタイトルを変更
fig_title = fig_title +"\n" + "iter:" + str(iteration)+" RSME:"+'{: .3f}'.format(rmse_test)+ \
" loss at peak:"+'{: .3f}'.format(loss_at_peak)+" max:"+'{: .3f}'.format(max_calc)
plt.title(fig_title, fontsize=14)
plt.ylim(-0.5, 8)
plt.grid()
#plt.plot(t_, test_data[t_start-n_steps:t_max+1,0], "bo", markersize=5, label="target") # xとyの個数は揃える必要あり
plt.plot(t_, test_data[t_start-n_steps:t_max+1,0], "b-", lw=3, label="target") # xとyの個数は揃える必要あり
plt.plot(t_[n_steps+1:], sequence[:], "r-", lw=1.5, label="prediction")
plt.legend(loc="upper right")
plt.xlabel("Time (hour)")
plt.ylabel("Water Level (m)")
# ファイル出力
save_fig(fig_FN)
#plt.show()
print("CASE NO : " + '{:03}'.format(case_no))
print("終了しました。\n実行ケース数:" + str(case_no))
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.20%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2019/04/03 20:05 編集
・必ず1度目の試行では振れ幅が大きく上下に変動しながら低くなる
・2度目以降の試行ではほぼ直線的に下がっていく
毎回上記2つのような結果になります。
抽出する学習データが毎回異なるためこのような結果になるケースもあることは理解できるのですが、
1度目と2度目以降で大きく傾向が異なるので気になりました。
>ちゃんと見てませんが学習したモデルをそのまま再利用してませんか?
その可能性はあると思うのですが、毎回初期化?リセット?して新しいモデルで学習するようにコーディングしたつもりでした。
間違いがあって1度目の学習に追加して学習するようになっているのかもしれませんが、
どこをどのように修正すればいいかが分かりません・・