Skip to content

Commit

Permalink
BilinearUpsamplingFiller for DeconvolutionLayer
Browse files Browse the repository at this point in the history
  • Loading branch information
tnarihi committed Apr 6, 2015
1 parent 5c009d8 commit 4f249a0
Showing 1 changed file with 56 additions and 0 deletions.
56 changes: 56 additions & 0 deletions include/caffe/filler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,60 @@ class XavierFiller : public Filler<Dtype> {
};


/*!
@brief Fills a Blob with coefficients of bilinear interpolation for upsampling.
This is intended to be used in DeconvolutionLayer acting as UpsamplingLayer.
You can upsample a feature map with shape of (B, C, H, W) by any integer factor
using the following proto.
\code
layer {
name: "upsample", type: "Deconvolution"
bottom: "{{bottom_name}}" top: "{{top_name}}"
convolution_param {
kernel_size: {{2 * factor - factor % 2}} stride: {{factor}}
num_output: {{C}} group: {{C}}
pad: {{ceil((factor - 1) / 2.)}}
weight_filler: { type: "bilinear_upsampling" } bias_term: false
}
param { lr_mult: 0 decay_mult: 0 }
}
\endcode
Please use this by replacing `{{}}` with your values. By specifying
`num_output: {{C}} group: {{C}}`, it behaves as
channel-wise convolution. The filter shape of this deconvolution layer will be
(C, 1, K, K) where K is `kernel_size`, and this filler will set a (K, K)
interpolation kernel for every channel of the filter identically. The resulting
shape of the top feature map will be (B, C, factor * H, factor * W).
Note that the learning rate and the
weight decay are set to 0 in order to keep coefficient values of bilinear
interpolation unchanged during training. If you apply this to an image, this
operation is equivalent to the following call in Python with Scikit.Image.
\code{.py}
out = skimage.transform.rescale(img, factor, mode='constant', cval=0)
\endcode
*/
template <typename Dtype>
class BilinearUpsamplingFiller : public Filler<Dtype> {
public:
explicit BilinearUpsamplingFiller(const FillerParameter& param)
: Filler<Dtype>(param) {}
virtual void Fill(Blob<Dtype>* blob) {
CHECK_EQ(blob->num_axes(), 4) << "Blob must be 4 dim.";
CHECK_EQ(blob->width(), blob->height()) << "Filter must be square";
Dtype* data = blob->mutable_cpu_data();
int f = ceil(blob->width() / 2.);
float c = (2 * f - 1 - f % 2) / (2. * f);
for (int i = 0; i < blob->count(); ++i) {
float x = i % blob->width();
float y = (i / blob->width()) % blob->height();
data[i] = (1 - fabs(x / f - c)) * (1 - fabs(y / f - c));
}
CHECK_EQ(this->filler_param_.sparse(), -1)
<< "Sparsity not supported by this Filler.";
}
};

/**
* @brief Get a specific filler from the specification given in FillerParameter.
*
Expand All @@ -176,6 +230,8 @@ Filler<Dtype>* GetFiller(const FillerParameter& param) {
return new UniformFiller<Dtype>(param);
} else if (type == "xavier") {
return new XavierFiller<Dtype>(param);
} else if (type == "bilinear_upsampling") {
return new BilinearUpsamplingFiller<Dtype>(param);
} else {
CHECK(false) << "Unknown filler name: " << param.type();
}
Expand Down

0 comments on commit 4f249a0

Please sign in to comment.