2017-07-14 12 views
2

私はTensorFlowの回帰にLSTMを使用しようとしていますが、データに適合しません。私はKerasに同じデータをうまく収めました(同じサイズのネットワークで)。正弦波をオーバーフィットしようとするための私のコードは以下の通りです:LSTMはトレーニングデータに余裕がない

import tensorflow as tf 
import numpy as np 

yt = np.cos(np.linspace(0, 2*np.pi, 256)) 
xt = np.array([yt[i-50:i] for i in range(50, len(yt))])[...,None] 
yt = yt[-xt.shape[0]:] 

g = tf.Graph() 
with g.as_default(): 
    x = tf.constant(xt, dtype=tf.float32) 
    y = tf.constant(yt, dtype=tf.float32) 

    lstm = tf.nn.rnn_cell.BasicLSTMCell(32) 
    outputs, state = tf.nn.dynamic_rnn(lstm, x, dtype=tf.float32) 
    pred = tf.layers.dense(outputs[:,-1], 1) 
    loss = tf.reduce_mean(tf.square(pred-y)) 
    train_op = tf.train.AdamOptimizer().minimize(loss) 
    init = tf.global_variables_initializer() 

sess = tf.InteractiveSession(graph=g) 
sess.run(init) 

for i in range(200): 
    _, l = sess.run([train_op, loss]) 
print(l) 

(Kerasが50のエポックの後に0.0022になっている間)これは、0.436067のMSEになり、そして予測は-0.1860から-0.1798の範囲。私はここで間違って何をしていますか?

編集:私は次のように私の損失関数を変更すると 、モデルが適切にフィットする:

def pinball(y_true, y_pred): 
    tau = np.arange(1,100).reshape(1,-1)/100 
    pin = tf.reduce_mean(tf.maximum(y_true[:,None] - y_pred, 0) * tau + 
       tf.maximum(y_pred - y_true[:,None], 0) * (1 - tau)) 
    return pin 

私も

pred = tf.layers.dense(outputs[:,-1], 99) 
loss = pinball(y, pred) 

predlossの割り当てを変更これがその結果それが訓練するにつれて損失が0.3から0.003に減少し、データに適切に適合していると思われる。

答えて

2

形状/放送の問題のように見えます。ここでは作業バージョンです:time_major=Falseで最初の次元は、バッチの寸法であることが予想されているので

import tensorflow as tf 
import numpy as np 

yt = np.cos(np.linspace(0, 2*np.pi, 256)) 
xt = np.array([yt[i-50:i] for i in range(50, len(yt))]) 
yt = yt[-xt.shape[0]:] 

g = tf.Graph() 
with g.as_default(): 
    x = tf.constant(xt, dtype=tf.float32) 
    y = tf.constant(yt, dtype=tf.float32) 

    lstm = tf.nn.rnn_cell.BasicLSTMCell(32) 
    outputs, state = tf.nn.dynamic_rnn(lstm, x[None, ...], dtype=tf.float32) 
    pred = tf.squeeze(tf.layers.dense(outputs, 1), axis=[0, 2]) 
    loss = tf.reduce_mean(tf.square(pred-y)) 
    train_op = tf.train.AdamOptimizer().minimize(loss) 
    init = tf.global_variables_initializer() 

sess = tf.InteractiveSession(graph=g) 
sess.run(init) 

for i in range(200): 
    _, l = sess.run([train_op, loss]) 
print(l) 

xは、dynamic_rnnに入る前に1のバッチ寸法を取得します。 tf.layers.denseの出力の最後の次元は、yTensorShape([256, 1])TensorShape([256])ブロードキャストはTensorShape([256, 256]))でブロードキャストされないように絞られることが重要です。それが収束し、それらの修正で:

5.78507e-05

0

dynamic_rnnの1回の呼び出しから次の状態に状態を渡すことはありません。それは確かに問題です。

また、出力の最後の項目だけを密集したレイヤー以降に取り込むのはなぜですか?

+0

私の理解から、私は複数のバッチを持っていた場合、私は状態のみを通過させることができるだろう。私は次のステップを予測するために過去50ステップを使用しようとしているので、最後のステップの出力を通過するだけです。私は非常に似ているが、別の損失を使用して動作するものの例を追加しました。 – cnapun

+0

ああ、最後の1つを見ると、1対多に対抗して1対1を予測したと思ったので、もっと慎重に見ていたはずです。ループでdynamic_rnnを複数回呼び出す。なぜ状態を前後に渡さないのですか? –

+0

私はちょうど私の問題を示すことができる最小の例を作りたいと思っていました。状態を通過させることなく別の損失関数を使用するので、私はMSEも状態を通過することなく動作すると期待します。また、私が知っていることから、Kerasはデフォルトで状態を渡さないので、必要とは思わない。 – cnapun

関連する問題