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

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

新規登録して質問してみよう
ただいま回答率
85.50%

Q&A

解決済

1回答

2389閲覧

TensorFlowのGradientDescentOptimizerについて

退会済みユーザー

退会済みユーザー

総合スコア0

0グッド

1クリップ

投稿2018/03/13 03:53

TensorFlow初心者です。
TensorFlowを使って重回帰分析をしようとしています。

tl;dr

最適化関数に勾配降下法を用いるために、GradientDescentOptimizerを使ってみましたが、
重みが上手く更新されているようには思えません。
何が原因なのでしょうか。

重回帰分析の実装

弁当の売り上げを目的変数とし、
「気温」「年」「月」「特定のメニューであるか否か('fun'と呼びます)」の4つの説明変数を用いています。
さらに

python

1trainX1 = np.transpose(np.matrix(train['temperature'])) 2trainX2 = np.transpose(np.matrix(train['year'])) 3trainX3 = np.transpose(np.matrix(train['month'])) 4trainX4 = np.transpose(np.matrix(train['fun'])) 5x_columns = np.concatenate((trainX1,trainX2,trainX3,trainX4), axis=1) 6one_columns = np.transpose(np.matrix(np.repeat(1,len(x_columns)))) 7 8trainX = np.concatenate((one_columns, x_columns), axis=1)

このようなコードで以下のようなtrainXの行列を作成します。
イメージ説明

また、学習させる重みベクトルであるwを用意します。

python

1w = tf.Variable(tf.random_normal(shape=[5,1]))

イメージ説明

これを損失関数RMSEと最適化関数SGDを使ってうまいこと更新してほしいのですが、うまくいきません。

python

1loss = tf.sqrt(tf.reduce_mean(tf.square(y_target - model_output))) 2train_op = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss)

実行してみた結果

正解である売り上げは1日せいぜい50個付近をうろうろするような値を取ります。

また、trainXの値はそれぞれ取る幅が大きく異なります。
気温は20前後、年は2015前後、月は1~12、funは0または1です。
なのにもかかわらず、
lossやwの遷移は、

1,000エポック目

Step #1000 w = [[ 2.5351398 ] [ 0.61772847] [ 1.01535892] [-0.57643688] [-0.82196891]] Loss = 1968.61

50,000エポック目

Step #50000 w = [[ 2.53515816] [-2.04255724] [ 1.06837845] [-0.21111657] [-0.7757085 ]] Loss = 2026.23

100,000エポック目

Step #100000 w = [[ 2.53515816] [-2.56503868] [ 1.07396245] [ 0.31354469] [-0.72820771]] Loss = 2031.3

という風な結果になっています。
売り上げは-1990個とかになっています。(正解は50個程度)
直感的に考えてw[2]は他に比べてもっと差のある数値になるはずですが、上手く更新されていません。

ちなみにハイパーパラメータは
207個のデータに対して、
学習率: 0.001
バッチサイズ: 100
エポック: 100,000
と設定しています。

個人的な考察

ここからは推測なのですが、TensorFlowのSGDは各パラメータに対して同程度の更新しかできないのでしょうか。
パラメータ1が0.1くらい増加するのが最適なら、
パラメータ2が100増加するのが最適だとしても0.1しか更新できない、という風に。
だとすればエポックをもっと増やせば上手くいく気もしますが、lossが減っていないところを見るとそうでもなさそうです。

標準化をすればよいのでしょうか。
しかし、適切な標準化の仕方がわかりません。
trainX,testXに対して同様の標準化をし、yにはしない。
という風にしても良い結果は得られませんでした。

python

1ss = StandardScaler() 2ss.fit(trainX) 3trainX = ss.transform(trainX)

結果

Step #1000 w = [[-0.66529876] [-0.34425855] [ 0.14133939] [ 0.35682976] [-0.86263251]] Loss = 91.1161
Step #100000 w = [[ -0.66529876] [-13.21006107] [-10.87212086] [ -0.82688373] [ 5.15802956]] Loss = 87.2392

売り上げは-31個とかを示しています。(正解は50個程度)

どなたかなにかわかる方がいらっしゃればご教示願えませんでしょうか。
よろしくお願いします。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

loss = tf.sqrt(tf.reduce_mean(tf.square(y_target - model_output)))

loss = tf.reduce_mean(tf.square(y_target - model_output))
としてから、学習率をがんがん下げてみてはいかがでしょうか。

投稿2018/03/13 06:23

mkgrei

総合スコア8560

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/03/13 06:39

回答ありがとうございます。実際にそのコードで実行してみると1000回目の時点でnan(発散してる?)になってしまします。 Step #1000 w = [[ nan] [ nan] [ nan] [ nan] [ nan]] Loss = nan
mkgrei

2018/03/13 08:07 編集

学習率が高いと簡単に発散します。 0.00000001とかにしてみてください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問