-
Notifications
You must be signed in to change notification settings - Fork 951
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Transposed Convolution Layers from base class #850
base: master
Are you sure you want to change the base?
Conversation
I really do not understand the error message I get from Travis... some import problem. The funny thing is on my pc py.test runs fine. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, looks good in principle! And sorry for the extra work of rebasing. Apart from the comments I have, the tests will need to be refactored as well to test all three dimensionalities. Check how it was done for the forward convolutional layers, and let me know if you need help. Cheers!
docs/modules/layers.rst
Outdated
Deconv2DLayer | ||
Deconv3DLayer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, good catch, we missed to add it there in #841.
I think I'd prefer the order:
TransposedConv1DLayer
Deconv1DLayer
TransposedConv2DLayer
Deconv2DLayer
TransposedConv3DLayer
Deconv3DLayer
So the alias always comes directly after a documented layer.
docs/conf.py
Outdated
@@ -354,6 +354,9 @@ def setup(app): | |||
if not hasattr(theano.tensor.nnet, 'conv3d'): | |||
theano.tensor.nnet.conv3d = Mock() | |||
reload(lasagne.layers.conv) | |||
if not hasattr(theano.tensor.nnet.abstract_conv, 'AbstractConv_gradInputs'): | |||
theano.tensor.nnet.abstract_conv.AbstractConv1d_gradInputs = Mock() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess you meant AbstractConv_gradInputs
, without 1d
.
docs/modules/layers/conv.rst
Outdated
|
||
.. autoclass:: Deconv2DLayer | ||
|
||
.. autoclass:: Deconv3DLayer | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, thank you for catching this, but I'd prefer to have each alias come directly after the actual class.
lasagne/layers/conv.py
Outdated
"Deconv2DLayer", | ||
"Deconv3DLayer", | ||
"DilatedConv2DLayer", | ||
"TransposedConv3DLayer", | ||
"Deconv3DLayer", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 3Ds are duplicated now. I'm fine with placing them before the dilated layers, but again I'd prefer the aliases directly after the respective classes.
lasagne/layers/conv.py
Outdated
conved = op(self.W, input, output_size) | ||
return conved | ||
|
||
|
||
class TransposedConv1DLayer(BaseTransposedConvLayer): # pragma: no cover |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Detail: We usually (hopefully always) have two spaces before line comments.
lasagne/layers/conv.py
Outdated
the input (by adding ``stride - 1`` zeros between adjacent input elements), | ||
padding it with ``filter_size - 1 - crop`` zeros, and cross-correlating it | ||
with the filters. See [1]_ for more background. | ||
See `BaseTransposedConvLayer` for more. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aha, I guess we will have to copy this note to all subclasses, as we cannot refer to the base class.
lasagne/layers/conv.py
Outdated
|
||
Examples | ||
-------- | ||
To transpose an existing convolution, with tied filter weights: | ||
|
||
>>> from lasagne.layers import Conv3DLayer, TransposedConv3DLayer | ||
>>> conv = Conv3DLayer((None, 1, 32, 32, 32), 16, 3, stride=2, pad=2) | ||
>>> conv = Conv3DLayer((None, 1, 32, 64, 64), 16, 3, stride=2, pad=2) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the previous one was okay.
.. [1] Vincent Dumoulin, Francesco Visin (2016): | ||
A guide to convolution arithmetic for deep learning. arXiv. | ||
http://arxiv.org/abs/1603.07285, | ||
https://github.com/vdumoulin/conv_arithmetic |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I think we'll have to replicate this reference in all three subclasses as well.
lasagne/layers/conv.py
Outdated
def __init__(self, incoming, num_filters, filter_size, | ||
stride=(1, 1, 1), crop=0, untie_biases=False, | ||
def __init__(self, incoming, num_filters, filter_size, stride=1, | ||
crop=0, untie_biases=False, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer (1, 1, 1)
just for consistency with the forward convolutional layers.
lasagne/layers/conv.py
Outdated
# Hide TransposedConv2DLayer for old Theano versions | ||
del TransposedConv2DLayer, Deconv2DLayer | ||
__all__.remove('TransposedConv2DLayer') | ||
__all__.remove('Deconv2DLayer') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 2D version is always available in the Theano versions we support. I'd prefer to only add the check for 1D, directly after the 1D definitions.
The exact error is
Even with Theano 0.8? |
No, maybe theano 0.8 is the problem then. I tried with the bleeding-edge version. I fixed all the things you mentioned (thanks a lot for the in-depth review). I'm sorry for the many mistakes but it's my first time rebasing and I made a mess... |
Ok, I tried adding test by copying and modifying the tests for the other cases. I am not at all sure how this whole unit-test thing works (I understand that it should check the output shape, but the code is a bit weird and right now I do not have time to delve into it.) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the updates, and sorry for the thesis-based delay. Looks much better, there are still a few inconsistencies in the docstrings from copying things around, and the tests need to skip the TransposedConv1DLayer if it's not available. Otherwise the tests look good. It might be possible to refactor them as well to minimize code duplication, but we can leave that for another time (it's actually good to first check that the old tests still run through with the new code).
lasagne/tests/layers/test_conv.py
Outdated
@pytest.mark.parametrize( | ||
"input, kernel, output, kwargs", list(transp_conv1d_test_sets())) | ||
def test_defaults(self, DummyInputLayer, input, kernel, output, kwargs): | ||
from lasagne.layers import TransposedConv1DLayer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You'll need to wrap this in a try..except
:
try:
from lasagne.layers import TransposedConv1DLayer
except ImportError:
pytest.skip("TransposedConv1DLayer not available")
Same for the second test below. This ensures it will run through on Travis / on Theano 0.8.x.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
The dimensionality of the transposed convolution (i.e., the number of | ||
spatial dimensions of each feature map and each convolutional filter). | ||
If ``None``, will be inferred from the input shape. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The untie_biases
docstring still needs to be adapted (https://github.com/Lasagne/Lasagne/pull/850/files#r123304501). Unfortunately I cannot comment on the correct line for that because it's not part of the diff.
lasagne/layers/conv.py
Outdated
W=lasagne.init.GlorotUniform(), b=lasagne.init.Constant(0.), | ||
nonlinearity=lasagne.nonlinearities.rectify, flip_filters=False, **kwargs) | ||
nonlinearity=lasagne.nonlinearities.rectify, flip_filters=False, | ||
n=None, **kwargs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
output_size
is mysteriously missing here (not your fault, but would be good to fix while we're at it, should come before n
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was also missing from the three subclasses. Fixed.
incoming : a :class:`Layer` instance or a tuple | ||
The layer feeding into this layer, or the expected input shape. The | ||
output of this layer should be a 4D tensor, with shape | ||
``(batch_size, num_input_channels, input_rows, input_columns)``. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be 3D, without input_columns
lasagne/layers/conv.py
Outdated
An integer or 1-element tuple specifying the size of the filters. | ||
|
||
stride : int | ||
An integeror 1-element tuple specifying the stride of the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
integeror -> integer or
W : Theano shared variable, expression, numpy array or callable | ||
Initial value, expression or initializer for the weights. | ||
These should be a 4D tensor with shape | ||
``(num_input_channels, num_filters, filter_rows, filter_columns)``. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is correct now. I wonder whether my previous comment (https://github.com/Lasagne/Lasagne/pull/850/files#r123304988) was originally attached to the 1D version and github messed up, or whether I accidentally thought it was about the 1D version.
``None``, the layer will have no biases. Otherwise, biases should be | ||
a 1D array with shape ``(num_filters,)`` if `untied_biases` is set to | ||
``False``. If it is set to ``True``, its shape should be | ||
``(num_filters, output_rows, output_columns)`` instead. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lasagne/layers/conv.py
Outdated
``(batch_size, num_input_channels, input_depth, input_rows, | ||
input_columns)``. | ||
output of this layer should be a 4D tensor, with shape | ||
``(batch_size, num_input_channels, input_rows, input_columns)``. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lasagne/layers/conv.py
Outdated
@@ -1006,7 +1325,8 @@ class TransposedConv3DLayer(BaseConvLayer): # pragma: no cover | |||
W : Theano shared variable, expression, numpy array or callable | |||
Initial value, expression or initializer for the weights. | |||
These should be a 5D tensor with shape | |||
``(num_input_channels, num_filters, filter_rows, filter_columns)``. | |||
``(num_input_channels, num_filters, input_depth, input_rows, | |||
- input_columns)``. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like you left an initial -
in there.
lasagne/layers/conv.py
Outdated
def __init__(self, incoming, num_filters, filter_size, | ||
stride=(1, 1, 1), crop=0, untie_biases=False, | ||
def __init__(self, incoming, num_filters, filter_size, stride=(1, 1, 1), | ||
crop=0, untie_biases=False, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary change, better to avoid, but not a big deal.
I made a bit of mess with the rebase (first time trying it...). I tried to merge the changes meaningfully. I'm uploading it because today I have no more time, then on Monday I'll see...