質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.78%

【Tensorflow RNN】for文でパラメータを変えながら実行

受付中

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 933

wrtnmi

score 10

前提・実現したいこと

Tensorflowで3か所の雨量と1か所の水位をそれぞれ72時間分読み込んで、1時間先の水位を予測しています。
for文でニューロン数、バッチサイズを変更しつつ、最適なパラメータを探そうと思っています。
学習に使用するデータがランダムに抽出されるため、各ケース5回ずつ試行したいです。
(jupyter notebookで実行しています)

発生している問題・エラーメッセージ

エラーが出ずに実行はできるものの、2回目の試行以降lossグラフが1回目と全く異なります。
また、予測結果も2回目の試行以降は極端に悪い結果となります。
前回試行の結果が残っているのでしょうか?
for文を使わずに手動でパラメータを変更し再試行すると、多少の変化はあるもののこのような結果にはなりません。

1回目
イメージ説明
2回目以降
イメージ説明

該当のソースコード

全文は長いので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ページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

0

Lossは低い方がいいんですよ。

ちゃんと見てませんが学習したモデルをそのまま再利用してませんか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/04/03 20:05 編集

    LOSSが低い方がいいのは分かるのですが、
    ・必ず1度目の試行では振れ幅が大きく上下に変動しながら低くなる
    ・2度目以降の試行ではほぼ直線的に下がっていく
    毎回上記2つのような結果になります。
    抽出する学習データが毎回異なるためこのような結果になるケースもあることは理解できるのですが、
    1度目と2度目以降で大きく傾向が異なるので気になりました。

    >ちゃんと見てませんが学習したモデルをそのまま再利用してませんか?
    その可能性はあると思うのですが、毎回初期化?リセット?して新しいモデルで学習するようにコーディングしたつもりでした。
    間違いがあって1度目の学習に追加して学習するようになっているのかもしれませんが、
    どこをどのように修正すればいいかが分かりません・・

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.78%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る