在Keras中将多个层添加到自动编码器

时间:2018-11-02 17:16:52

标签: python keras lstm keras-layer autoencoder

我想在LSTM自动编码器的顶部添加一个乘法层。 乘法层应将张量乘以一个恒定值。 我编写了以下代码,这些代码无需乘法层即可工作。 有谁知道如何调整并使之生效?

import keras
from keras import backend as K
from keras.models import Sequential, Model
from keras.layers import Input, LSTM, RepeatVector, TimeDistributed
from keras.layers.core import Flatten, Dense, Dropout, Lambda
from keras.optimizers import SGD, RMSprop, Adam
from keras import objectives
from keras.engine.topology import Layer
import numpy as np

class LayerKMultiply(Layer):

    def __init__(self, output_dim, **kwargs):
        self.output_dim = output_dim
        self.k = Null
        super(LayerKMultiply, self).__init__(**kwargs)

    def build(self, input_shape):
        # Create a trainable weight variable for this layer.
        self.k = self.add_weight(
            name='k',
            shape=(),
            initializer='ones',
            dtype='float32',
            trainable=True,
        )
        super(LayerKMultiply, self).build(input_shape)  # Be sure to call this at the end

    def call(self, x):
        #return K.tf.multiply(self.k, x)
        return self.k * x

    def compute_output_shape(self, input_shape):
        return (input_shape[0], self.output_dim)

    timesteps, input_dim, latent_dim = 10, 3, 32


inputs = Input(shape=(timesteps, input_dim))
encoded = LSTM(latent_dim, return_sequences=False, activation='linear')(inputs)
decoded = RepeatVector(timesteps)(encoded)
decoded = LSTM(input_dim, return_sequences=True, activation='linear')(decoded)
decoded = TimeDistributed(Dense(input_dim, activation='linear'))(decoded)
#decoded = LayerKMultiply(k = 20)(decoded)

sequence_autoencoder = Model(inputs, decoded)
encoder = Model(inputs, encoded)

autoencoder = Model(inputs, decoded)
autoencoder.compile(optimizer='adam', loss='mse')

    X = np.array([[[1,2,3,4,5,6,7,8,9,10],[1,2,3,4,5,6,7,8,9,10],[1,2,3,4,5,6,7,8,9,10]]])
X = X.reshape(1,10,3)
p = autoencoder.predict(x=X, batch_size=1)
print(p)

我遇到以下错误:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-3-b2f9497bbf47> in <module>()
      7 decoded = LSTM(input_dim, return_sequences=True, activation='linear')(decoded)
      8 decoded = TimeDistributed(Dense(input_dim, activation='linear'))(decoded)
----> 9 decoded = LayerKMultiply(k = 20)(decoded)
     10 
     11 sequence_autoencoder = Model(inputs, decoded)

TypeError: __init__() missing 1 required positional argument: 'output_dim'

编辑

我要实现的是下图中描述的体系结构:

https://github.com/mg64ve/SMTDAE/blob/master/images/SMTDAE.png https://github.com/mg64ve/SMTDAE/blob/master/images/REF.png

所以从这个意义上讲,我认为乘法层必须位于TimeDistributed和Dense层之前。 我将代码修改如下:

import keras
from keras import backend as K
from keras.models import Sequential, Model
from keras.layers import Input, LSTM, RepeatVector, TimeDistributed
from keras.layers.core import Flatten, Dense, Dropout, Lambda
from keras.optimizers import SGD, RMSprop, Adam
from keras import objectives
from keras.engine.topology import Layer
import numpy as np

class LayerKMultiply(Layer):

    def __init__(self, output_dim, **kwargs):
        self.output_dim = output_dim
        self.k = None
        super(LayerKMultiply, self).__init__(**kwargs)

    def build(self, input_shape):
        # Create a trainable weight variable for this layer.
        self.k = self.add_weight(
            name='k',
            shape=(),
            initializer='ones',
            dtype='float32',
            trainable=True,
        )
        super(LayerKMultiply, self).build(input_shape)  # Be sure to call this at the end

    def call(self, x):
        return self.k * x

    def compute_output_shape(self, input_shape):
        return (input_shape[0], input_shape[1], self.output_dim)

timesteps, input_dim, latent_dim = 31, 31, 32


inputs = Input(shape=(timesteps, input_dim))
encoded = LSTM(latent_dim, return_sequences=False, activation='linear')(inputs)
decoded = RepeatVector(timesteps)(encoded)
decoded = LSTM(input_dim, return_sequences=True, activation='linear')(decoded)
decoded = LayerKMultiply(20)(decoded)
decoded = TimeDistributed(Dense(input_dim, activation='linear'))(decoded)

autoencoder = Model(inputs, decoded)

batch_size = 100
X = np.zeros([5000,31,31])
autoencoder.fit(X, X, batch_size = batch_size, epochs=3)

autoencoder.compile(optimizer='adam', loss='mse')

但是我仍然遇到以下错误:

InvalidArgumentError: Incompatible shapes: [155,31,31] vs. [100,31,31]

2 个答案:

答案 0 :(得分:1)

您正在将位置参数关键字参数混合。当您定义类似def __init__(self, output_dim, **kwargs)的函数时,output_dim是位置参数。您需要:

  • 各自通过LayerMultiply(20)(decoded)传递20
  • 或更改def __init__(self, k=10, **kwargs)
  • 或从定义中删除output_dim并使用self.output_dim = kwargs['k']

更多信息here

答案 1 :(得分:0)

我相信解决方法如下:

import keras
from keras import backend as K
from keras.models import Sequential, Model
from keras.layers import Input, LSTM, RepeatVector, TimeDistributed
from keras.layers.core import Flatten, Dense, Dropout, Lambda
from keras.optimizers import SGD, RMSprop, Adam
from keras import objectives
from keras.engine.topology import Layer
import numpy as np

class LayerKMultiply(Layer):

    def __init__(self, output_dim, **kwargs):
        self.output_dim = output_dim
        self.k = None
        super(LayerKMultiply, self).__init__(**kwargs)

    def build(self, input_shape):
        # Create a trainable weight variable for this layer.
        self.k = self.add_weight(
            name='k',
            shape=(),
            initializer='ones',
            dtype='float32',
            trainable=True,
        )
        super(LayerKMultiply, self).build(input_shape)  # Be sure to call this at the end

    def call(self, x):
        return self.k * x

    def compute_output_shape(self, input_shape):
        return (input_shape[0], input_shape[1], input_shape[2])