BVLC/caffe — pull request #1639 by longjon (2014-12-28 09:08:42+00:00)
Title: Crop layer for automatically aligning computations

After #1637 and #1638 (new content is just the commit https://github.com/longjon/caffe/commit/4e38c93d3f9e05aabb2e3fdb74bd79872dd2b008).

Existing layers shift and warp coordinate space: translation by padding (or lack thereof), contraction by strided convolution or pooling, and expansion by strided deconvolution (#1615). Often one wants to align two blobs, e.g., to establish a correspondence between input and output, or to fuse two different paths of computation. Counting conv/deconv strides to ensure that blob coordinates have the same scale is generally straightforward. Computing the offset between two blobs that results from intermediate padding and kernel sizes is trickier.

This layer takes two bottom blobs and produces one top, which is a copy of the first bottom cropped to the size of the second so that coordinates exactly correspond, i.e., it makes sense to fuse or compare the top blob with the second bottom, regardless of whatever padding or other shenanigans took place between their computation.

This is done by computing the coordinate mapping between the two bottom blobs, as provided by #1637 and made accessible by #1638. If that mapping is a simple translation, and has the right sign to allow the first blob to be "cropped to" the second, the layer simply performs the copy. If the mapping is not an integer translation, or the translation has the wrong sign, an error is thrown, and the net may be rearranged to allow sensible fusion.

The implementation of `LayerSetUp` amounts to some simple graph traversal to find the path connecting the two bottoms. Currently `Net` does not provide great facilities for traversing the layer graph, so it's a bit cumbersome; maybe this can be improved in the future.

There is a bit of engineering involved in these three PRs, but the result is pretty convenient: what was before a tricky offline calculation becomes a trivial layer specification.

Another way to implement this, without #1638, would be to remove the graph traversal from `CropLayer`, giving it a simple parameter instead, and provide some other mechanism for automatically filling in that parameter.

Currently CPU and GPU (trivially) are provided, but tests and documentation are not.