Del decodificador de pesos de Autoencoder con atado de pesos en Keras

He implementado un atado de pesos de Auto-codificador en Keras y han entrenado con éxito a la misma.

Mi objetivo es utilizar sólo el decodificador parte de la Auto-codificador como la última capa de la otra red, para afinar la red y el decodificador.

La cosa es que, como se puede ver a continuación del resumen, el decodificador no tiene parámetros con mi atado de pesos de la aplicación, así que no hay nada que afinar. (decoder.get_weights() devuelve [])

Mi pregunta es: debo cambiar la implementación de la atados pesos, por lo que el atado de la capa puede todavía sostener pesos, que es la transposición de los pesos de los encoder? Si sí, ¿cómo?

O solo estoy lejos?

A continuación se presenta el resumen de la autoencoder modelo así como la clase de la atados capa Densa (ligeramente modificado a partir de https://github.com/nanopony/keras-convautoencoder/blob/master/autoencoder_layers.py.)


Layer (type)                     Output Shape          Param #     Connected to                     
====================================================================================================
encoded (Dense)                  (None, Enc_dim)          33000       dense_input_1[0][0]              
____________________________________________________________________________________________________
tieddense_1 (TiedtDense)          (None, Out_Dim)            0           encoded[0][0]                    
====================================================================================================
Total params: 33,000
Trainable params: 33,000
Non-trainable params: 0
________________________________________________________________________


class TiedtDense(Dense):
def __init__(self, output_dim, master_layer, init='glorot_uniform', activation='linear', weights=None,
             W_regularizer=None, b_regularizer=None, activity_regularizer=None,
             W_constraint=None, b_constraint=None, input_dim=None, **kwargs):
    self.master_layer = master_layer
    super(TiedtDense, self).__init__(output_dim, **kwargs)

def build(self, input_shape):
    assert len(input_shape) >= 2
    input_dim = input_shape[-1]
    self.input_dim = input_dim


    self.W = tf.transpose(self.master_layer.W)
    self.b = K.zeros((self.output_dim,))
    self.params = [self.b]
    self.regularizers = []
    if self.W_regularizer:
        self.W_regularizer.set_param(self.W)
        self.regularizers.append(self.W_regularizer)

    if self.b_regularizer:
        self.b_regularizer.set_param(self.b)
        self.regularizers.append(self.b_regularizer)

    if self.activity_regularizer:
        self.activity_regularizer.set_layer(self)
        self.regularizers.append(self.activity_regularizer)

    if self.initial_weights is not None:
        self.set_weights(self.initial_weights)
        del self.initial_weights

1 Respuestas

  • rvinas
    4 de mayo de 2019

    Hace más de 2 años desde que esta pregunta se la hicieron, pero esta respuesta todavía podría ser relevante para algunos.

    La función Layer.get_weights() recupera de self.trainable_weights y self.non_trainable_weights (ver keras.motor.base_layer.La capa.pesos). En su capa personalizado, los pesos self.W y self.b no se agregan a cualquiera de estas colecciones y es por eso que la capa tiene 0 parámetros.

    Usted puede modificar su aplicación como sigue:

    class TiedtDense(Dense):
        def __init__(self, output_dim, master_layer, **kwargs):
            self.master_layer = master_layer
            super(TiedtDense, self).__init__(output_dim, **kwargs)
    
        def build(self, input_shape):
            assert len(input_shape) >= 2
            input_dim = input_shape[-1]
            self.input_dim = input_dim
    
            self.kernel = tf.transpose(self.master_layer.kernel)
            self.bias = K.zeros((self.units,))
            self.trainable_weights.append(self.kernel)
            self.trainable_weights.append(self.bias)
    

    NOTA: estoy excluyendo el regularizers y limitaciones para la simplicidad. Si desea que esas, por favor refiérase a keras.motor.base_layer.La capa.add_weight.