如何为解码器加载训练有素的自动编码器权重? [英] How to load trained autoencoder weights for decoder?

查看:58
本文介绍了如何为解码器加载训练有素的自动编码器权重?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个CNN 1d自动编码器,该编码器具有密集的中央层.我想训练这种自动编码器并保存其模型.我还想保留解码器部分,以实现此目标:将一些中心特征(独立计算)提供给经过训练并加载的解码器,以通过解码器查看这些独立计算的特征的图像.

I have a CNN 1d autoencoder which has a dense central layer. I would like to train this Autoencoder and save its model. I would also like to save the decoder part, with this goal: feed some central features (calculated independently) to the trained and loaded decoder, to see what are the images of these independently calculated features through the decoder.

## ENCODER
encoder_input = Input(batch_shape=(None,501,1))
x  = Conv1D(256,3, activation='tanh', padding='valid')(encoder_input)
x  = MaxPooling1D(2)(x)
x  = Conv1D(32,3, activation='tanh', padding='valid')(x)
x  = MaxPooling1D(2)(x)
_x = Flatten()(x)
encoded = Dense(32,activation = 'tanh')(_x)

## DECODER (autoencoder)
y = Conv1D(32, 3, activation='tanh', padding='valid')(x)
y = UpSampling1D(2)(y)
y = Conv1D(256, 3, activation='tanh', padding='valid')(y)
y = UpSampling1D(2)(y)
y = Flatten()(y)
y = Dense(501)(y)
decoded = Reshape((501,1))(y)

autoencoder = Model(encoder_input, decoded)
autoencoder.save('autoencoder.hdf5')

## DECODER (independent)
decoder_input = Input(batch_shape=K.int_shape(x))  # import keras.backend as K
y = Conv1D(32, 3, activation='tanh', padding='valid')(decoder_input)
y = UpSampling1D(2)(y)
y = Conv1D(256, 3, activation='tanh', padding='valid')(y)
y = UpSampling1D(2)(y)
y = Flatten()(y)
y = Dense(501)(y)
decoded = Reshape((501,1))(y)

decoder = Model(decoder_input, decoded)
decoder.save('decoder.hdf5')

为了确保清楚,我首先需要联接encoded和第一个y,因为y必须以encoded作为输入.完成此操作后,我需要一种方法来加载训练有素的解码器,并用一些新的主要功能替换encoded,这些新功能将提供给我的解码器.

Just to make sure that it is clear, I first need to JOIN encoded and the first y, in the sense that y has to take encoded as input. Once this is done, I need a way to load a trained decoder and replace encoded with some new central features, which I will feed my decoder with.

编辑以下答案:

我实现了建议,请参见下面的代码

I implemented the suggestion, see code below

## ENCODER
encoder_input = Input(batch_shape=(None,501,1))
x  = Conv1D(256,3, activation='tanh', padding='valid')(encoder_input)
x  = MaxPooling1D(2)(x)
x  = Conv1D(32,3, activation='tanh', padding='valid')(x)
x  = MaxPooling1D(2)(x)
_x = Flatten()(x)
encoded = Dense(32,activation = 'tanh')(_x)

## DECODER (autoencoder)
encoded = Reshape((32,1))(encoded)
y = Conv1D(32, 3, activation='tanh', padding='valid')(encoded)
y = UpSampling1D(2)(y)
y = Conv1D(256, 3, activation='tanh', padding='valid')(y)
y = UpSampling1D(2)(y)
y = Flatten()(y)
y = Dense(501)(y)
decoded = Reshape((501,1))(y)

autoencoder = Model(encoder_input, decoded)
autoencoder.compile(optimizer='adam', loss='mse')
epochs = 10
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)
autoencoder.save_weights('autoencoder_weights.h5')


## DECODER (independent)
decoder_input = Input(batch_shape=K.int_shape(encoded))  # import keras.backend as K
y = Conv1D(32, 3, activation='tanh', padding='valid', name='decod_conv1d_1')(decoder_input)
y = UpSampling1D(2, name='decod_upsampling1d_1')(y)
y = Conv1D(256, 3, activation='tanh', padding='valid', name='decod_conv1d_2')(y)
y = UpSampling1D(2, name='decod_upsampling1d_2')(y)
y = Flatten(name='decod_flatten')(y)
y = Dense(501, name='decod_dense1')(y)
decoded = Reshape((501,1), name='decod_reshape')(y)

decoder = Model(decoder_input, decoded)
decoder.save_weights('decoder_weights.h5')


encoder = Model(inputs=encoder_input, outputs=encoded, name='encoder')
features = encoder.predict(training) # features
np.savetxt('features.txt', np.squeeze(features))

predictions = autoencoder.predict(training)
predictions = np.squeeze(predictions)
np.savetxt('predictions.txt', predictions)

然后我打开另一个文件,然后执行

Then I open another file and I do

import h5py
import keras.backend as K

def load_weights(model, filepath):
    with h5py.File(filepath, mode='r') as f:
        file_layer_names = [n.decode('utf8') for n in f.attrs['layer_names']]
        model_layer_names = [layer.name for layer in model.layers]

        weight_values_to_load = []
        for name in file_layer_names:
            if name not in model_layer_names:
                print(name, "is ignored; skipping")
                continue
            g = f[name]
            weight_names = [n.decode('utf8') for n in g.attrs['weight_names']]

            weight_values = []
            if len(weight_names) != 0:
                weight_values = [g[weight_name] for weight_name in weight_names]
            try:
                layer = model.get_layer(name=name)
            except:
                layer = None
            if layer is not None:
                symbolic_weights = (layer.trainable_weights + 
                                    layer.non_trainable_weights)
                if len(symbolic_weights) != len(weight_values):
                    print('Model & file weights shapes mismatch')
                else:
                    weight_values_to_load += zip(symbolic_weights, weight_values)

        K.batch_set_value(weight_values_to_load)

## DECODER (independent)
decoder_input = Input(batch_shape=(None,32,1))
y = Conv1D(32, 3, activation='tanh',padding='valid',name='decod_conv1d_1')(decoder_input)
y = UpSampling1D(2, name='decod_upsampling1d_1')(y)
y = Conv1D(256, 3, activation='tanh', padding='valid', name='decod_conv1d_2')(y)
y = UpSampling1D(2, name='decod_upsampling1d_2')(y)
y = Flatten(name='decod_flatten')(y)
y = Dense(501, name='decod_dense1')(y)
decoded = Reshape((501,1), name='decod_reshape')(y)

decoder = Model(decoder_input, decoded)
#decoder.save_weights('decoder_weights.h5')

load_weights(decoder, 'autoencoder_weights.h5')

# Read autoencoder
decoder.summary()

# read encoded features
features = np.loadtxt('features.txt'.format(batch_size, epochs))
features = np.reshape(features, [1500,32,1])

# evaluate loaded model on features
prediction = decoder.predict(features)



autoencoderpredictions = np.loadtxt('predictions.txt'.format(batch_size, epochs))

fig, ax = plt.subplots(5, figsize=(10,20))
for i in range(5):
        ax[i].plot(prediction[100*i], color='blue', label='Decoder')
        ax[i].plot(autoencoderpredictions[100*i], color='red', label='AE')
        ax[i].set_xlabel('Time components', fontsize='x-large')
        ax[i].set_ylabel('Amplitude', fontsize='x-large')
        ax[i].set_title('Seismogram n. {:}'.format(1500+100*i+1), fontsize='x-large')
        ax[i].legend(fontsize='x-large')
plt.subplots_adjust(hspace=1)
plt.close()

predictionautoencoderpredictions不一致.似乎prediction只是很小的噪音,而autoencoder predictions具有合理的值.

prediction and autoencoderpredictions do not agree. It seems as if prediction is just small noise, whereas autoencoder predictions has reasonable values.

推荐答案

您将需要:(1)节省AE(自动编码器)的权重; (2)负荷权重文件; (3)反序列化文件,并仅分配与新模型(解码器)兼容的权重.

You'll need to: (1) save weights of AE (autoencoder); (2) load weights file; (3) deserialize the file and assign only those weights that are compatible with the new model (decoder).

  • (1):.save确实包括权重,但是通过使用.save_weights可以省去一个额外的反序列化步骤.此外,.save保存了优化器状态和模型架构,后者与您的新解码器无关.
  • (2):默认情况下,load_weights尝试分配所有保存的权重,这将不起作用
  • (1): .save does include the weights, but with an extra deserialization step that's spared by using .save_weights instead. Also, .save saves optimizer state and model architecture, latter which is irrelevant for your new decoder
  • (2): load_weights by default attempts to assign all saved weights, which won't work

以下代码完成了(3)(和补救措施(2)),如下所示:

Code below accomplishes (3) (and remedies (2)) as follows:

  1. 加载所有重量
  2. 检索已加载的重量名称并将其存储在file_layer_names(列表)
  3. 检索当前型号的重量名称,并将其存储在model_layer_names(列表)
  4. file_layer_names迭代为name;如果namemodel_layer_names中,则将具有该名称的已加载重量附加到weight_values_to_load
  5. weight_values_to_load中分配权重以使用K.batch_set_value
  6. 进行建模
  1. Load all weights
  2. Retrieve loaded weight names and store them in file_layer_names (list)
  3. Retrieve current model weight names and store them in model_layer_names (list)
  4. Iterate over file_layer_names as name; if name is in model_layer_names, append loaded weight with that name to weight_values_to_load
  5. Assign weights in weight_values_to_load to model using K.batch_set_value

请注意,这要求您在AE和解码器模型中的每个图层命名并使它们匹配.可以在try-except循环中将此代码重写为按顺序进行暴力破解,但这既效率低又容易出错.

Note that this requires you to name every layer in both AE and decoder models and make them match. It's possible to rewrite this code to brute-force assign sequentially in a try-except loop, but that's both inefficient and bug-prone.

用法:

## omitted; use code as in question but name all ## DECODER layers as below
autoencoder.save_weights('autoencoder_weights.h5')

## DECODER (independent)
decoder_input = Input(batch_shape=K.int_shape(x))
y = Conv1D(32, 3, activation='tanh',padding='valid',name='decod_conv1d_1')(decoder_input)
y = UpSampling1D(2, name='decod_upsampling1d_1')(y)
y = Conv1D(256, 3, activation='tanh', padding='valid', name='decod_conv1d_2')(y)
y = UpSampling1D(2, name='decod_upsampling1d_2')(y)
y = Flatten(name='decod_flatten')(y)
y = Dense(501, name='decod_dense1')(y)
decoded = Reshape((501,1), name='decod_reshape')(y)

decoder = Model(decoder_input, decoded)
decoder.save_weights('decoder_weights.h5')

load_weights(decoder, 'autoencoder_weights.h5')


功能

import h5py
import keras.backend as K

def load_weights(model, filepath):
    with h5py.File(filepath, mode='r') as f:
        file_layer_names = [n.decode('utf8') for n in f.attrs['layer_names']]
        model_layer_names = [layer.name for layer in model.layers]

        weight_values_to_load = []
        for name in file_layer_names:
            if name not in model_layer_names:
                print(name, "is ignored; skipping")
                continue
            g = f[name]
            weight_names = [n.decode('utf8') for n in g.attrs['weight_names']]

            weight_values = []
            if len(weight_names) != 0:
                weight_values = [g[weight_name] for weight_name in weight_names]
            try:
                layer = model.get_layer(name=name)
            except:
                layer = None
            if layer is not None:
                symbolic_weights = (layer.trainable_weights + 
                                    layer.non_trainable_weights)
                if len(symbolic_weights) != len(weight_values):
                    print('Model & file weights shapes mismatch')
                else:
                    weight_values_to_load += zip(symbolic_weights, weight_values)

        K.batch_set_value(weight_values_to_load)

这篇关于如何为解码器加载训练有素的自动编码器权重?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆