nanopony / keras-convautoencoder

Keras autoencoders (convolutional/fcc) [proof of concept]
174 stars 55 forks source link

Converting to new 1.0 API? #5

Open GPistre opened 8 years ago

GPistre commented 8 years ago

I've been trying to use the conv_autoencoder.py with the new Keras API, but I'm running into some problems. I adapted the build() method to take the input_shape argument, which results in a Theano error: ValueError: Cannot reshape input of shape (1,) to shape [ 1 32 1 1]

I also tried changing the output_shape method to get_output_shape_for(self, input_shape) as explained here. But this results in another error:

TypeError: get_output_shape_for() missing 1 required positional argument: 'input_shape'

Any idea on how to make it work?

nanopony commented 8 years ago

Thank you for heads up with 1.0! I look into the issue. In the meantime, could you please show the model, since I suspect that there's might be something odd with the input data to the layer.

GPistre commented 8 years ago

I'm using the exact same code and data (Keras MNIST) as I took on your repo. I also replaced the get_output methods by call(self, x, mask=None) and tried to adapt the code inside, but I'm not that familiar with Keras, 1.0 or before. I now get a theano.gradient.DisconnectedInputError at the depooling layer.

For reference: The Depool get_output_shape_for() and call() methods I wrote:

def get_output_shape_for(self, input_shape):
        if self.dim_ordering == 'th':
            return (input_shape[0],
                    input_shape[1],
                    self.size[0] * input_shape[2],
                    self.size[1] * input_shape[3])
        elif self.dim_ordering == 'tf':
            return (input_shape[0],
                    self.size[0] * input_shape[1],
                    self.size[1] * input_shape[2],
                    input_shape[3])
        else:
            raise Exception('Invalid dim_ordering: ' + self.dim_ordering)

def call(self, x, mask=None):
    if self.dim_ordering == 'th':
        output = K.repeat_elements(x, self.size[0], axis=2)
        output = K.repeat_elements(output, self.size[1], axis=3)
    elif self.dim_ordering == 'tf':
        output = K.repeat_elements(x, self.size[0], axis=1)
        output = K.repeat_elements(output, self.size[1], axis=2)
    else:
        raise Exception('Invalid dim_ordering: ' + self.dim_ordering)

    f = T.grad(T.sum(self._pool2d_layer.call(x)),
               wrt=self._pool2d_layer.call(x)) * output

    return

And the ones for the deconvolution layer:

def get_output_shape_for(self, input_shape):
        output_shape = list(super().get_output_shape_for(input_shape))

        if self.dim_ordering == 'th':
            output_shape[1] = self.nb_out_channels
        elif self.dim_ordering == 'tf':
            output_shape[0] = self.nb_out_channels
        else:
            raise Exception('Invalid dim_ordering: ' + self.dim_ordering)
        return tuple(output_shape)

def call(self, x, mask=None):
    X = x
    conv_out = deconv2d_fast(X, self.W,
                             strides=self.subsample,
                             border_mode=self.border_mode,
                             dim_ordering=self.dim_ordering,
                             image_shape=self.input_shape,
                             filter_shape=self.W_shape)

    if self.dim_ordering == 'th':
        output = conv_out + K.reshape(self.b, (1, self.nb_out_channels, 1, 1))
    elif self.dim_ordering == 'tf':
        output = conv_out + K.reshape(self.b, (1, 1, 1, self.nb_out_channels))
    else:
        raise Exception('Invalid dim_ordering: ' + self.dim_ordering)

    output = self.activation(output)
    return output
pkainz commented 8 years ago

In your DePool2D.call() function, you have a malformed return statement. It should probably read

return f
pkainz commented 8 years ago

I just posted this PR: #8, which ported the autoencoder layers to the new API. I also included a sample implementation for 1100cars using the functional API.

MrRobot2211 commented 4 years ago

Hi thank tou for the contribution, I am interested in migrating this layer to keras 2.x , Do you know any guidelines on how to do it ? I am trying something like

`class InverseMaxPool2D(UpSampling2D): ''' This layer makes tied max pooling with the one before '''

def __init__(self, max_pool,size,activation=None , **kwargs):

    #super(ClusteringLayer, self).__init__(incoming, **kwargs)
    self.size = size
    self.max_pool = max_pool

def build(self, input_shape):

    super(InverseMaxPool2D, self).build(input_shape)
@property
def output(self):
    incoming = self.input
    output = K.repeat_elements(incoming, self.size[0], axis=1)
    output = K.repeat_elements(output, self.size[1], axis=2)
    f = K.gradients(K.sum(self.max_pool.output), wrt=self.max_pool.input) * output

    return f`