LSTM不会过度训练数据

时间:2017-07-14 14:37:57

标签: python tensorflow

我一直试图在TensorFlow中使用LSTM进行回归,但它并不适合数据。我已成功地在Keras中使用相同的数据(具有相同大小的网络)。我试图过度拟合正弦波的代码如下:

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)

这导致MSE为0.436067(而Keras在50个时期后达到0.0022),预测范围从-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 个答案:

答案 0 :(得分:3)

看起来像形状/广播问题。这是一个有效的版本:

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,因为time_major=False第一个维度应该是批量维度。重要的是tf.layers.dense输出的最后一个维度被挤掉,以便它不会与yTensorShape([256, 1])TensorShape([256])广播一起广播到TensorShape([256, 256]))。通过这些修复,它会收敛:

  

5.78507e-05

答案 1 :(得分:0)

你没有将状态从dynamic_rnn的一次调用传递给next。这肯定是问题所在。

另外,为什么只通过密集层以及之前的输出的最后一项?