我正在使用简单的RNN预测时间序列上的EWMA (exponential weighted moving average) formula。已经发布了关于它的here。
虽然使用keras-tf(来自tensorflow导入keras)完美地收敛了模型,但使用本地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。 据我所知,唯一的区别是导入类的方式。
我在两种实现方式中都使用了相同的随机种子。我正在Windows PC,带有keras 2.2.4和tensorflow版本1.13.1(其中包括版本2.2.4-tf中的keras)的anaconda环境中工作。对此有何见解?
答案 0 :(得分:1)
这可能是由于TF Keras
和Native Keras
之间在SimpleRNN的实现上存在差异(1个衬里)。
下面提到的行在TF Keras
中实现,而在Keras
中不实现。
self.input_spec = [InputSpec(ndim=3)]
这种差异的一种情况就是您上面提到的情况。
我想使用Sequential
类的Keras
来演示类似的情况。
以下代码对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'))
具有model
实现的Keras
甚至与TF Keras
实现的收敛相似。
在两种情况下,如果您想从代码角度了解实现的差异,可以参考以下链接:
https://github.com/keras-team/keras/blob/master/keras/layers/recurrent.py#L1082-L1091
如果您认为此答案有用,请接受此答案和/或对其进行投票。谢谢。