benanne/nntools — pull request #52 by f0k (2014-11-17 17:48:33+00:00)
Title: Allow Layers to be constructed from input shapes

As discussed in #17, it seemed to be a good idea to allow Layer instances to be constructed from input shapes rather than other Layer instances. While `get_output()` would not work for such layers, they could still be used standalone with `get_output_for()` and `get_output_shape_for()` -- after all, a layer only needs to know about its input and input shape to function.

We thought that implementing this would only touch the `Layer` base class (and the `MultipleInputsLayer` base class). However, while implementing it, I found that several other layer implementations rely on `self.input_layer.get_output_shape()` to work. There are about four ways of solving it:
1. Distinguishing between `self.input_layer` being a shape tuple or a layer in each of these cases
2. Moving this distinction into a new `get_input_shape()` method in the base class
3. Relying on this distinction being present in `Layer.get_output_shape()` and using `super(XYZLayer, self).get_output_shape()` instead of `self.input_layer.get_output_shape()` (this only works for classes directly derived from `Layer`, because in this case the super `get_output_shape()` will just return the input shape, so that's both ugly and fragile)
4. Wrapping a shape tuple in something that implements `get_output_shape()`

It turns out that we have a ready-made class for option 4, which is `InputLayer`. By wrapping shape tuples given in the constructor in `InputLayer` instances, only the base classes need to be changed. However, it feels like an unnecessary / misplaced shortcut now... what do we gain compared to requiring the user to provide an `InputLayer` instance herself or himself? Should we possibly choose option 2 instead? Should we create an `InputShape` class that really just wraps a shape tuple with a `get_output_shape()` method? Or is this proposal a good solution anyway?