2017-07-14 100 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) 

这导致0.436067一个MSE(而Keras得0.0022后50时代),和预测的范围从-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 

我也改变predloss将分配到

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

这导致损失从0.3减少到0.003,并且似乎适合数据。

回答

2

看起来像一个形状/广播问题。这里有一个工作版本:

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得到的1批次尺寸再进dynamic_rnn,因为与time_major=False第一维有望成为一个批次的尺寸。重要的是tf.layers.dense的输出的最后一个尺寸被挤掉,以便它不会以yTensorShape([256, 1])TensorShape([256])广播到TensorShape([256, 256]))进行广播。有了这些修复它收敛:

5.78507e-05

0

您不是从dynamic_rnn的一次调用转移到下一个状态。这是肯定的问题。

此外,为什么只通过密集层和前进的输出的最后一项呢?

+0

从我的理解,我只将能够通过国家,如果我有多个批次。我只通过最后一步的输出,因为我试图用过去的50个步骤来预测下一个。我添加了一个非常相似的东西,但使用了不同的损失。 – cnapun

+0

啊我看到最后一个,我应该仔细看看,因为你认为你预测一对一,而不是一对多。您在循环中多次调用dynamic_rnn。为什么不来回传递状态? –

+0

我只是想创建可以证明我的问题的最小示例。因为在不通过状态的情况下使用不同的损失函数,我希望MSE也可以在不传递状态的情况下工作。另外,据我所知,Keras默认情况下不会通过状态,所以我不认为这是必要的。 – cnapun