{"action":"created","issue":{"url":"https://api.github.com/repos/fchollet/keras/issues/2106","repository_url":"https://api.github.com/repos/fchollet/keras","labels_url":"https://api.github.com/repos/fchollet/keras/issues/2106/labels{/name}","comments_url":"https://api.github.com/repos/fchollet/keras/issues/2106/comments","events_url":"https://api.github.com/repos/fchollet/keras/issues/2106/events","html_url":"https://github.com/fchollet/keras/issues/2106","id":143985706,"number":2106,"title":"Anyone implemented a Deconvolutional layer combined the Keras and Tensorflow?","user":{"login":"meanmee","id":8026086,"avatar_url":"https://avatars.githubusercontent.com/u/8026086?v=3","gravatar_id":"","url":"https://api.github.com/users/meanmee","html_url":"https://github.com/meanmee","followers_url":"https://api.github.com/users/meanmee/followers","following_url":"https://api.github.com/users/meanmee/following{/other_user}","gists_url":"https://api.github.com/users/meanmee/gists{/gist_id}","starred_url":"https://api.github.com/users/meanmee/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/meanmee/subscriptions","organizations_url":"https://api.github.com/users/meanmee/orgs","repos_url":"https://api.github.com/users/meanmee/repos","events_url":"https://api.github.com/users/meanmee/events{/privacy}","received_events_url":"https://api.github.com/users/meanmee/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2016-03-28T14:08:36Z","updated_at":"2016-03-28T15:34:05Z","closed_at":null,"body":"I am a little confused by the output shape in conv_transpose( ) function. How to calculate it?\r\n\r\n```python\r\n\r\nclass Convolution2D_Transpose(Layer):\r\n    input_ndim = 4\r\n\r\n    def __init__(self, nb_filter, nb_row, nb_col,\r\n                 init='glorot_uniform', activation='linear', weights=None,\r\n                 border_mode='valid', subsample=(1, 1),deconv_shape = (),\r\n                 W_regularizer=None, b_regularizer=None, activity_regularizer=None,\r\n                 W_constraint=None, b_constraint=None, **kwargs):\r\n\r\n        if border_mode not in {'valid', 'same'}:\r\n            raise Exception('Invalid border mode for Convolution2D:', border_mode)\r\n        self.nb_filter = nb_filter\r\n        self.nb_row = nb_row\r\n        self.nb_col = nb_col\r\n        self.deconv_shape = deconv_shape\r\n        self.init = initializations.get(init)\r\n        self.activation = activations.get(activation)\r\n        assert border_mode in {'valid', 'same'}, 'border_mode must be in {valid, same}'\r\n        self.border_mode = border_mode\r\n        self.subsample = tuple(subsample)\r\n\r\n        self.W_regularizer = regularizers.get(W_regularizer)\r\n        self.b_regularizer = regularizers.get(b_regularizer)\r\n        self.activity_regularizer = regularizers.get(activity_regularizer)\r\n\r\n        self.W_constraint = constraints.get(W_constraint)\r\n        self.b_constraint = constraints.get(b_constraint)\r\n        self.constraints = [self.W_constraint, self.b_constraint]\r\n\r\n        self.initial_weights = weights\r\n        self.input = K.placeholder(ndim=4)\r\n        super(Convolution2D_Transpose, self).__init__(**kwargs)\r\n\r\n    def build(self):\r\n        stack_size = self.input_shape[1]\r\n        #self.W_shape = (self.nb_filter, stack_size, self.nb_row, self.nb_col)\r\n        self.W_shape = ( self.nb_col, self.nb_row, stack_size, self.nb_filter)\r\n        print self.W_shape\r\n        self.W = self.init(self.W_shape)\r\n        self.b = K.zeros((self.nb_filter,))\r\n        self.trainable_weights = [self.W, self.b]\r\n        self.regularizers = []\r\n\r\n        if self.W_regularizer:\r\n            self.W_regularizer.set_param(self.W)\r\n            self.regularizers.append(self.W_regularizer)\r\n\r\n        if self.b_regularizer:\r\n            self.b_regularizer.set_param(self.b)\r\n            self.regularizers.append(self.b_regularizer)\r\n\r\n        if self.activity_regularizer:\r\n            self.activity_regularizer.set_layer(self)\r\n            self.regularizers.append(self.activity_regularizer)\r\n\r\n        if self.initial_weights is not None:\r\n            self.set_weights(self.initial_weights)\r\n            del self.initial_weights\r\n\r\n    @property\r\n    def output_shape(self):\r\n        input_shape = self.input_shape\r\n        rows = input_shape[2]\r\n        cols = input_shape[3]\r\n        self.deconv_shape = (self.nb_filter, input_shape[0], rows+2, cols+2)\r\n        return self.deconv_shape\r\n\r\n    def get_output(self, train=False):\r\n        X = self.get_input(train)\r\n        X = K.permute_dimensions(X,(0,2,3,1))\r\n        #batch_size = tf.shape(X)[0]\r\n        #deconv_shape = tf.pack([batch_size, 40, 40, 32])\r\n        print 'deconv_shape: {0}'.format(self.deconv_shape)\r\n        print 'value: {0}'.format(X)\r\n        print 'W shape: {0}'.format(K.eval(self.W).shape)\r\n        conv_out = tf.nn.conv2d_transpose(X, self.W, strides=self.subsample,\r\n                            padding='VALID',\r\n                            output_shape=self.deconv_shape)\r\n\r\n        output = conv_out + K.reshape(self.b, (1, 1, 1,self.nb_filter))\r\n        return output\r\n\r\n    def get_config(self):\r\n        config = {'name': self.__class__.__name__,\r\n                  'nb_filter': self.nb_filter,\r\n                  'nb_row': self.nb_row,\r\n                  'nb_col': self.nb_col,\r\n                  'init': self.init.__name__,\r\n                  'activation': self.activation.__name__,\r\n                  'border_mode': self.border_mode,\r\n                  'subsample': self.subsample,\r\n                  'W_regularizer': self.W_regularizer.get_config() if self.W_regularizer else None,\r\n                  'b_regularizer': self.b_regularizer.get_config() if self.b_regularizer else None,\r\n                  'activity_regularizer': self.activity_regularizer.get_config() if self.activity_regularizer else None,\r\n                  'W_constraint': self.W_constraint.get_config() if self.W_constraint else None,\r\n                  'b_constraint': self.b_constraint.get_config() if self.b_constraint else None}\r\n        base_config = super(Convolution2D_Transpose, self).get_config()\r\n        return dict(list(base_config.items()) + list(config.items()))\r\n\r\n```"},"comment":{"url":"https://api.github.com/repos/fchollet/keras/issues/comments/202441808","html_url":"https://github.com/fchollet/keras/issues/2106#issuecomment-202441808","issue_url":"https://api.github.com/repos/fchollet/keras/issues/2106","id":202441808,"user":{"login":"NasenSpray","id":8047134,"avatar_url":"https://avatars.githubusercontent.com/u/8047134?v=3","gravatar_id":"","url":"https://api.github.com/users/NasenSpray","html_url":"https://github.com/NasenSpray","followers_url":"https://api.github.com/users/NasenSpray/followers","following_url":"https://api.github.com/users/NasenSpray/following{/other_user}","gists_url":"https://api.github.com/users/NasenSpray/gists{/gist_id}","starred_url":"https://api.github.com/users/NasenSpray/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/NasenSpray/subscriptions","organizations_url":"https://api.github.com/users/NasenSpray/orgs","repos_url":"https://api.github.com/users/NasenSpray/repos","events_url":"https://api.github.com/users/NasenSpray/events{/privacy}","received_events_url":"https://api.github.com/users/NasenSpray/received_events","type":"User","site_admin":false},"created_at":"2016-03-28T15:34:05Z","updated_at":"2016-03-28T15:34:05Z","body":"It's the shape of the input for a conv2d (just imagine), that, when done with exactly the same arguments, results in your input shape.\r\n\r\n```\r\nshape1 -> conv2d -> shape2\r\nshape2 -> conv2d_transpose -> shape1\r\n```\r\n\r\nLook for the shape calculation for conv2d and reverse it."}}