Как загрузить обученные веса автоэнкодера для декодера? - PullRequest
1 голос
/ 13 октября 2019

У меня есть автоматический энкодер CNN 1d с плотным центральным слоем. Я хотел бы обучить этот автоэнкодер и сохранить его модель. Я также хотел бы сохранить часть декодера с этой целью: подать некоторые центральные функции (рассчитанные независимо) в обученный и загруженный декодер, чтобы увидеть, каковы изображения этих независимо рассчитанных функций через декодер.

## 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 некоторыми новыми центральными функциями, которыми я буду кормить свой декодер.

РЕДАКТИРОВАТЬ следующий ответ:

Iреализовал предложение, см. код ниже

## 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)

Затем я открываю другой файл, и я

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()

prediction и autoencoderpredictions не согласен. Кажется, что prediction - это просто небольшой шум, тогда как autoencoder predictions имеет разумные значения.

1 Ответ

0 голосов
/ 13 октября 2019

Вам необходимо: (1) сохранить веса AE (автоэнкодер);(2) загрузить файл весов;(3) десериализовать файл и назначить только те веса, которые совместимы с новой моделью (декодером).

  • (1): .save включает в себя веса, но с дополнительным этапом десериализации, которыйсэкономлено с помощью .save_weights вместо. Кроме того, .save сохраняет состояние оптимизатора и архитектуру модели, которая не важна для вашего нового декодера.
  • (2): load_weights по умолчанию пытается присвоить всем сохраненным весам, которые выигралине работает

Приведенный ниже код выполняет (3) (и средства защиты (2)) следующим образом:

  1. Загрузить все веса
  2. Получить имена загруженных грузови сохраните их в file_layer_names (список)
  3. Извлеките текущую модель весовых имен и сохраните их в model_layer_names (список)
  4. Переберите file_layer_names как name;если name находится в model_layer_names, добавьте загруженный вес с этим именем к weight_values_to_load
  5. Присвойте веса в weight_values_to_load модели, используя K.batch_set_value

Обратите внимание, что этотребует, чтобы вы назвали каждый слой в моделях AE и декодера и сделали их соответствующими. Можно переписать этот код для последовательного перебора в цикле try-except, но это неэффективно и подвержено ошибкам.


Использование :

## 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)
...