python - 精确模型在 keras-tf 上收敛,但在 keras 上不收敛

标签 python tensorflow keras deep-learning

我正在努力预测 EWMA (exponential weighted moving average) formula使用简单的 RNN 来处理时间序列。已经发布了here .

虽然模型使用 keras-tf(从tensorflow import keras)完美地收敛,但使用 native keras(导入 keras)却无法使用完全相同的代码。

收敛模型代码(keras-tf):

from tensorflow import keras
import numpy as np

np.random.seed(1337)  # for reproducibility

def run_avg(signal, alpha=0.2):
    avg_signal = []
    avg = np.mean(signal)
    for i, sample in enumerate(signal):
        if np.isnan(sample) or sample == 0:
            sample = avg
        avg = (1 - alpha) * avg + alpha * sample
        avg_signal.append(avg)
    return np.array(avg_signal)

def train():
    x = np.random.rand(3000)
    y = run_avg(x)
    x = np.reshape(x, (-1, 1, 1))
    y = np.reshape(y, (-1, 1))

    input_layer = keras.layers.Input(batch_shape=(1, 1, 1), dtype='float32')
    rnn_layer = keras.layers.SimpleRNN(1, stateful=True, activation=None, name='rnn_layer_1')(input_layer)
    model = keras.Model(inputs=input_layer, outputs=rnn_layer)

    model.compile(optimizer=keras.optimizers.SGD(lr=0.1), loss='mse')
    model.summary()

    print(model.get_layer('rnn_layer_1').get_weights())
    model.fit(x=x, y=y, batch_size=1, epochs=10, shuffle=False)
    print(model.get_layer('rnn_layer_1').get_weights())

train()

非收敛模型代码:

from keras import Model
from keras.layers import SimpleRNN, Input
from keras.optimizers import SGD

import numpy as np

np.random.seed(1337)  # for reproducibility

def run_avg(signal, alpha=0.2):
    avg_signal = []
    avg = np.mean(signal)
    for i, sample in enumerate(signal):
        if np.isnan(sample) or sample == 0:
            sample = avg
        avg = (1 - alpha) * avg + alpha * sample
        avg_signal.append(avg)
    return np.array(avg_signal)

def train():
    x = np.random.rand(3000)
    y = run_avg(x)
    x = np.reshape(x, (-1, 1, 1))
    y = np.reshape(y, (-1, 1))

    input_layer = Input(batch_shape=(1, 1, 1), dtype='float32')
    rnn_layer = SimpleRNN(1, stateful=True, activation=None, name='rnn_layer_1')(input_layer)
    model = Model(inputs=input_layer, outputs=rnn_layer)


    model.compile(optimizer=SGD(lr=0.1), loss='mse')
    model.summary()

    print(model.get_layer('rnn_layer_1').get_weights())
    model.fit(x=x, y=y, batch_size=1, epochs=10, shuffle=False)
    print(model.get_layer('rnn_layer_1').get_weights())

train()

虽然在 tf-keras 收敛模型中,损失最小化并且权重非常接近 EWMA 公式,但在非收敛模型中,损失爆炸到 nan。据我所知,唯一的区别是导入类的方式。

我对这两种实现使用了相同的随机种子。我正在使用 keras 2.2.4 和 tensorflow 版本 1.13.1(其中包括版本 2.2.4-tf 中的 keras)的 Windows PC、Anaconda 环境中工作。

对此有什么见解吗?

最佳答案

这可能是因为 TF Keras 之间 SimpleRNN 的实现存在差异(1 行)和 Native Keras .

下面提到的Line是在TF Keras中实现的,在Keras中没有实现。

self.input_spec = [InputSpec(ndim=3)]

您上面提到的这种差异的一个例子。

我想使用 Keras 的 Sequential 类来演示类似的情况。

下面的代码适用于 TF Keras:

from tensorflow import keras
import numpy as np
from tensorflow.keras.models import Sequential as Sequential

np.random.seed(1337)  # for reproducibility

def run_avg(signal, alpha=0.2):
    avg_signal = []
    avg = np.mean(signal)
    for i, sample in enumerate(signal):
        if np.isnan(sample) or sample == 0:
            sample = avg
        avg = (1 - alpha) * avg + alpha * sample
        avg_signal.append(avg)
    return np.array(avg_signal)

def train():
    x = np.random.rand(3000)
    y = run_avg(x)
    x = np.reshape(x, (-1, 1, 1))
    y = np.reshape(y, (-1, 1))
    
    # SimpleRNN model
    model = Sequential()
    model.add(keras.layers.Input(batch_shape=(1, 1, 1), dtype='float32'))
    model.add(keras.layers.SimpleRNN(1, stateful=True, activation=None, name='rnn_layer_1'))
    model.compile(optimizer=keras.optimizers.SGD(lr=0.1), loss='mse')
    model.summary()
    
    print(model.get_layer('rnn_layer_1').get_weights())
    model.fit(x=x, y=y, batch_size=1, epochs=10, shuffle=False)
    print(model.get_layer('rnn_layer_1').get_weights())

train()

但是如果我们使用 Native Keras 运行相同的操作,我们会收到如下所示的错误:

TypeError: The added layer must be an instance of class Layer. Found: Tensor("input_1_1:0", shape=(1, 1, 1), dtype=float32)

如果我们替换下面的代码行

model.add(Input(batch_shape=(1, 1, 1), dtype='float32'))

使用下面的代码,

model.add(Dense(32, batch_input_shape=(1,1,1), dtype='float32'))

即使是带有 Keras 实现的模型也几乎与 TF Keras 实现相似。

如果您想从代码角度了解这两种情况的实现差异,可以引用以下链接:

https://github.com/tensorflow/tensorflow/blob/r1.14/tensorflow/python/keras/layers/recurrent.py#L1364-L1375

https://github.com/keras-team/keras/blob/master/keras/layers/recurrent.py#L1082-L1091

关于python - 精确模型在 keras-tf 上收敛,但在 keras 上不收敛,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57396482/

相关文章:

python - 在 Keras 中使用 multi_gpu_model 恢复训练

tensorflow - 为什么 Keras 会抛出 ResourceExhaustedError?

python - 为什么 Keras 不需要自定义损失函数的梯度?

python - python 中的 tensorflow 夜间轮

python-3.x - 在 Mask R-CNN 中添加多个类

python 博托 : How do you specify a subnet id AND a security group?

python - `Tensor`(相对于 `EagerTensor` )在 Tensorflow 2.0 中有什么用?

python - 使用 GAE + ndb 进行配对

python - 如何卸载 miniconda ? Python

python - 如何删除 pyqgis 中*除了*某些特定图层之外的所有图层?