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

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

ただいまの
回答率

88.81%

TensorFlow(CPU)でループ毎に異なる予測値になってしまう

受付中

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,542

Wind

score 404

わからないこと

TensorFlow(CPU版)で同じデータを渡して学習し予測しても、ループ毎に異なる予測値になってしまいます。

プログラム実行時は毎回同じ値にはなりますが、プログラム内部で関数をループさせると毎回異なる値になります。(初期化が足りないのでしょうか?)
当然ですがデータのシャッフルは行わず、常に同一データを入れています。

知りたいこと

ループで同じデータを入れた時に毎回同じ予測値を得るには、他に固定すべき乱数シードがあるのでしょうか?
もしくはCPUでも全く同じ値にはならないのでしょうか?

(TensorFlowのニューラルネットワークを使用して学習して予測した時に、常に同じ予測値になるサンプルが書かれたURLを教えて頂けるだけでも助かります。)

ソースコード(再現動作可能)

※7/20 kerasで学習が再現できない人へを参考に追記してみました。
※5/30 [sklearnボストンのデータセット]
(https://newtechnologylifestyle.net/%E3%83%9C%E3%82%B9%E3%83%88%E3%83%B3%E5%B8%82%E3%81%AE%E4%BD%8F%E5%AE%85%E4%BE%A1%E6%A0%BC%E3%82%92%E8%AA%BF%E3%81%B9%E3%81%A6%E3%81%BF%E3%82%8B/)を使用して、コピペで動作が再現出来る物に差し替えました。
犯罪発生数を目的変数にして他の説明変数で学習し、予測する形になっています。
実行すると、予測値が毎回異なってしまいます。

import os
import pandas as pd
import numpy as np
#from sklearn.preprocessing import MinMaxScaler
from sklearn.preprocessing import StandardScaler
import tensorflow as tf
import random

# サンプルデータセット(ボストン)
from sklearn.datasets import load_boston
boston = load_boston()


#y_bos = pd.DataFrame( boston.target)   # 価格は使用しない
pd_bos = pd.DataFrame(boston.data, columns=boston.feature_names)

bos_test = pd_bos.iloc[0:100, :]    # 行 0~100をテストデータにする
bos_train = pd_bos.iloc[100:500, :] # 行 101~500を訓練データにする

data_columns = bos_train.columns.values[1:]     # 説明変数の名前を取得(犯罪数CRIMは目的変数とするので除外)
#print('説明変数:%s' % data_columns)             # 説明変数を表示


# DL関数(学習データ, テストデータ)
# 返り値:予測値, 犯罪数
def tf_cross(val_train, val_test):
    # ニューロンの数を設定
    n_neurons_1 = 256
    n_neurons_2 = 128

    os.environ['PYTHONHASHSEED'] = '0'
    random.seed(0)          # Pythonの乱数シードを固定
    np.random.seed(0)       # Numpyの乱数シードを固定
    tf.set_random_seed(0)   # TensorFlowの乱数シードを固定

    session_conf = tf.ConfigProto(
        intra_op_parallelism_threads=1,
        inter_op_parallelism_threads=1
    )
    # セッションの開始
    tf_sess = tf.InteractiveSession(config=session_conf)

#    random.seed(0)          # Pythonの乱数シードを固定
#    np.random.seed(0)       # Numpyの乱数シードを固定
#    tf.set_random_seed(0)   # TensorFlowの乱数シードを固定

    #値を標準化
    scaler = StandardScaler() 
    scaler.fit(val_train)
    val_train_std = scaler.transform(val_train)
    val_test_std = scaler.transform(val_test)

    y_train_std = val_train_std[:, 0]       # 訓練データの目的変数を取得(先頭列)
    X_train_std = val_train_std[:, 1:]      # 訓練データの説明変数を取得(2列目以降)
    y_test_std = val_test_std[:, 0]         # テストデータの目的変数
    X_test_std = val_test_std[:, 1:]        # テストデータの説明変数

    # テストデータの目的変数を標準化から通常の値へ戻す
    y_test = y_test_std.reshape(len(y_test_std), 1)
    y_test_inv = np.concatenate((y_test, X_test_std), axis=1)
    y_test_inv = scaler.inverse_transform(y_test_inv)
    y_test_inv = y_test_inv[:, 0]


    # 訓練データの特徴量の"数"を取得
    n_stocks = X_train_std.shape[1]    # shape[1]は列数


    # プレースホルダーの作成
    X = tf.placeholder(dtype=tf.float32, shape=[None, n_stocks])
    Y = tf.placeholder(dtype=tf.float32, shape=[None])


    # 初期化
    sigma = 1
    weight_initializer = tf.variance_scaling_initializer(mode="fan_avg", distribution="uniform", scale=sigma)
    bias_initializer = tf.zeros_initializer()

    # Hidden weights
    W_hidden_1 = tf.Variable(weight_initializer([n_stocks, n_neurons_1]))
    bias_hidden_1 = tf.Variable(bias_initializer([n_neurons_1]))
    W_hidden_2 = tf.Variable(weight_initializer([n_neurons_1, n_neurons_2]))
    bias_hidden_2 = tf.Variable(bias_initializer([n_neurons_2]))


    # 出力の重み
    W_out = tf.Variable(weight_initializer([n_neurons_2, 1]))   # 2層
    bias_out = tf.Variable(bias_initializer([1]))

    # 隠れ層の設定(ReLU=活性化関数)(収束がすばやいが、極端な出力値が生成される可能性がある)
#    hidden_1 = tf.nn.relu(tf.add(tf.matmul(X, W_hidden_1), bias_hidden_1))
#    hidden_2 = tf.nn.relu(tf.add(tf.matmul(hidden_1, W_hidden_2), bias_hidden_2))

    # 隠れ層の設定:活性化関数をシグモイド(極端な出力値が少ないが、収束が遅い)
    hidden_1 = tf.nn.sigmoid(tf.add(tf.matmul(X, W_hidden_1), bias_hidden_1))
    hidden_2 = tf.nn.sigmoid(tf.add(tf.matmul(hidden_1, W_hidden_2), bias_hidden_2))

    # 出力層の設定
    out = tf.transpose(tf.add(tf.matmul(hidden_2, W_out), bias_out))   

    # コスト関数
    mse = tf.reduce_mean(tf.squared_difference(out, Y))
    # 最適化関数
    opt = tf.train.AdamOptimizer().minimize(mse)
    # 全ての変数を初期化
    tf_sess.run(tf.global_variables_initializer())

    # ニューラルネットワークの設定
    batch_size = 128

    # 訓練開始 n回の反復処理
    epochs = 100
    for e in range(epochs):
        tf_sess.run(opt, feed_dict={X: X_train_std, Y: y_train_std})    # 標準化されたデータで訓練

    # テストデータで予測
    pred_test = tf_sess.run(out, feed_dict = {X: X_test_std})

    pred_test = np.concatenate((pred_test.T, X_test_std), axis=1)
    pred_inv = scaler.inverse_transform(pred_test)      # 標準化から戻す
    pred_inv = pred_inv[:, 0]       # 1行目だけ取り出す(予測値)
    tf_sess.close()                 # セッションを閉じる

    return pred_inv, y_test_inv     # 予測値と犯罪数を返す


# ループ
for dat in data_columns:    # カラム数-1でループ
    ans = tf_cross(bos_train, bos_test)      # ***同じデータを毎回渡しているだけなのに、毎回同じ結果にならない***
    pred_inv = ans[0]       # 予測値
    y_test_inv = ans[1]     # 犯罪発生数

    np.set_printoptions(suppress=True, formatter={'float': '{: 0.3f}'.format})     #printで指数表示を禁止する、小数点第三位まで表示
    print('犯罪発生数:' , y_test_inv)
    print('予測値:' , pred_inv)

参考URL

参考URL
kerasで学習が再現できない人へ

環境

エディタ:VSCode
Python :3.6.4 64-bit(base:conda)
TensorFlow:1.13.1

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

0

まず、警告はCPUの最適化オプション関連で今回とは関係しないです。

https://qiita.com/yuyakato/items/9a5d80e6c7c41e9a9d22

乱数の固定は上のリンクがわかりやすいです。

シード固定とセッション開始の順番を変えてみてはいかがでしょう。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/05/29 21:24

    返信ありがとうございます。
    TensorFlowはシード固定の順番も大事なのですね、試してみます。

    キャンセル

  • 2019/05/30 09:34

    シード固定の順番を変えてみましたが、ダメでした。
    セッションの実行前に持って行ってもダメでしたね・・・。

    キャンセル

  • 2019/07/20 03:34

    intra_op_parallelism_threads=1, inter_op_parallelism_threads=1をやっても同じ値になりませんでした。
    https://qiita.com/okotaku/items/8d682a11d8f2370684c9

    キャンセル

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

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

関連した質問

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