Keras - 不同于编码器 + 解码器的自动编码器

数据挖掘 Python 神经网络 喀拉斯 自动编码器 降维
2022-02-15 21:14:05

我按照这个 SO question中的建议在 Keras 中构建了一个 CNN 1d 自动编码器,其中编码器和解码器是分开的。我的目标是在自动编码器经过训练后重新使用解码器。我的 Autoencoder 的中心层是一个Dense层,因为我想在以后学习它。

我的问题是,如果我编译并拟合整个自动编码器,写成输入Decoder()Encoder()(x)在哪里x,我会得到不同的预测

autoencoder.predict(training_set)

如果我首先将训练集编码为一组中心特征,然后让解码器解码它们。一旦自动编码器经过训练,这两种方法应该给出相同的答案。

from tensorflow.keras.layers import Input, Dense, BatchNormalization, Flatten, Lambda, Activation, Conv1D, MaxPooling1D, UpSampling1D, Reshape
from tensorflow.keras.models import Model
from tensorflow.keras import optimizers
from tensorflow.keras.layers import GaussianNoise
import keras.backend as K
from tensorflow.keras.layers import Add

import tensorflow as tf

import scipy.io
import sys
import matplotlib.pyplot as plt
import numpy as np
import copy


training = # some training set, 1500 samples of 501 point each
testing = # some testing set, 500 samples of 501 point each

# reshaping for CNN
training = np.reshape(training, [1500, 501, 1])
testing = np.reshape(testing, [500, 501, 1])


# normalize input
X_mean = training.mean()
oscillations -= X_mean
X_std = training.std()
training /= X_std


copy_of_test = copy.copy(testing)
testing -= X_mean
testing /= X_std

### MODEL ###

def Encoder():
    encoder_input = Input(batch_shape=(None, 501, 1))  
    e1 = Conv1D(256,3, activation='tanh', padding='valid')(encoder_input)
    e2 = MaxPooling1D(2)(e1)
    e3 = Conv1D(32,3, activation='tanh', padding='valid')(e2)
    e4 = MaxPooling1D(2)(e3)
    e5 = Flatten()(e4)
    encoded = Dense(32,activation = 'tanh')(e5)
    return Model(encoder_input, encoded)


def Decoder():
    encoded_input = Input(shape=(32,))  
    encoded_reshaped = Reshape((32,1))(encoded_input)
    d1 = Conv1D(32, 3, activation='tanh', padding='valid', name='decod_conv1d_1')(encoded_reshaped)
    d2 = UpSampling1D(2, name='decod_upsampling1d_1')(d1)
    d3 = Conv1D(256, 3, activation='tanh', padding='valid', name='decod_conv1d_2')(d2)
    d4 = UpSampling1D(2, name='decod_upsampling1d_2')(d3)
    d5 = Flatten(name='decod_flatten')(d4)
    d6 = Dense(501, name='decod_dense1')(d5)
    decoded = Reshape((501,1), name='decod_reshape')(d6)
    return Model(encoded_input, decoded)


# define input to the model:
x = Input(batch_shape=(None, 501, 1))
y = Input(shape=(32,))

# make the model:
autoencoder = Model(x, Decoder()(Encoder()(x)))

# compile the model:
autoencoder.compile(optimizer='adam', loss='mse')
for layer in autoencoder.layers: print(K.int_shape(layer.output))


epochs = 100
batch_size = 100
validation_split = 0.2
# train the model
history = autoencoder.fit(x = training, y = training,
                    epochs=epochs,
                    batch_size=batch_size,
                    validation_split=validation_split)

# Encoder
encoder = Model(inputs=x, outputs=Encoder()(x), name='encoder')
print('enc:')
for layer in encoder.layers: print(K.int_shape(layer.output))
features = encoder.predict(training) # features

# Decoder
decoder = Model(inputs=y, outputs=Decoder()(y), name='decoder')
print('dec:')
for layer in decoder.layers: print(K.int_shape(layer.output))
score = decoder.predict(features) # 
score = np.squeeze(score)    

predictions = autoencoder.predict(training)
predictions = np.squeeze(predictions)

# plotting one random case
# score should be equal to predictions!
# because score is obtained from the trained decoder acting on the encoded features, while predictions are obtained form the Autoencoder acting on the training set 
plt.plot(score[100], label='eD')
plt.plot(predictions[100], label='AE')
plt.legend()
plt.show()
plt.close()
1个回答

当您执行 autoencoder.fit 时,您的模型正在学习一些东西,因此您的编码器模型和解码器模型的权重正在发生变化。之后,在创建像“encoder = Model(inputs=x, outputs=Encoder()(x), name='encoder')”这样的编码器/解码器时,您正在创建另一个具有不同权重的编码器模型,您必须使用相同的权重向量。检查“autoencoder.layers[1].get_weights()”是否等于“encoder.get_weights()”,然后您将了解模型中发生了什么。(解码器也类似)。您可以使用以下代码进行检查,

for i in range(len(autoencoder.layers[1].weights)):
    print((autoencoder.layers[1].get_weights()[i]==encoder.get_weights()[i]).all())