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
ResizeLayer implementation #1098
Changes from 19 commits
526050b
4bcf594
3227197
c6c8da8
ddc1bd8
1c1ada0
1a8b6db
93ab8b2
04c51ca
ea407ba
1bae148
5b0fe4c
09d88f4
e609536
54e270a
097d883
ee2b78c
a09bb7b
ca0745b
d9add61
cc2a45e
095e012
4da35cb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# Define the files we need to compile | ||
# Anything not in this list will not be compiled into mlpack. | ||
set(SOURCES | ||
bilinear_function.hpp | ||
) | ||
|
||
# Add directory name to sources. | ||
set(DIR_SRCS) | ||
foreach(file ${SOURCES}) | ||
set(DIR_SRCS ${DIR_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/${file}) | ||
endforeach() | ||
# Append sources (with directory name) to list of all mlpack sources (used at | ||
# the parent scope). | ||
set(MLPACK_SRCS ${MLPACK_SRCS} ${DIR_SRCS} PARENT_SCOPE) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,200 @@ | ||
/** | ||
* @file bilinear_function.hpp | ||
* @author Kris Singh | ||
* | ||
* Definition and implementation of the bilinear interpolation function. | ||
* | ||
* mlpack is free software; you may redistribute it and/or modify it under the | ||
* terms of the 3-clause BSD license. You should have received a copy of the | ||
* 3-clause BSD license along with mlpack. If not, see | ||
* http://www.opensource.org/licenses/BSD-3-Clause for more information. | ||
*/ | ||
#ifndef MLPACK_METHODS_ANN_IMAGE_FUNCTIONS_BILINEAR_FUNCTION_HPP | ||
#define MLPACK_METHODS_ANN_IMAGE_FUNCTIONS_BILINEAR_FUNCTION_HPP | ||
|
||
#include <mlpack/prereqs.hpp> | ||
#include <assert.h> | ||
|
||
namespace mlpack { | ||
namespace ann /** Artificial Neural Network. */ { | ||
|
||
/** | ||
* The bilinear interpolation function | ||
* | ||
*/ | ||
class BiLinearFunction | ||
{ | ||
/* | ||
* The constructor for the bilinear interpolation. | ||
* | ||
* @param inRowSize: Number of input rows | ||
* @param inColSize: Number of input columns. | ||
* @param outRowSize: Number of output rows. | ||
* @param outColSie: Number of output columns. | ||
*/ | ||
public: | ||
BiLinearFunction( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you describe the arguments? |
||
const size_t inRowSize, | ||
const size_t inColSize, | ||
const size_t outRowSize, | ||
const size_t outColSize, | ||
const size_t depth = 1): | ||
inRowSize(inRowSize), | ||
inColSize(inColSize), | ||
outRowSize(outRowSize), | ||
outColSize(outColSize), | ||
depth(depth) | ||
{}; | ||
/** | ||
* UpSample the given input. | ||
* | ||
* @param input The input matrix | ||
* @param output The resulting interpolated output image. | ||
*/ | ||
template<typename eT> | ||
void UpSample(const arma::Mat<eT>& input, arma::Mat<eT>& output) | ||
{ | ||
if (output.is_empty()) | ||
output.set_size(outRowSize * outColSize, 1); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm.. I think I saw that before. You didn't take into account |
||
|
||
assert(output.n_rows == outRowSize * outColSize); | ||
assert(output.n_cols == 1); | ||
|
||
scaleRow = (double)inRowSize / (double) outRowSize; | ||
scaleCol = (double)inColSize / (double) outColSize; | ||
|
||
for (size_t k = 0; k < depth; k++) | ||
{ | ||
for (size_t i = 0; i < outRowSize; i++) | ||
{ | ||
for (size_t j = 0; j < outColSize; j++) | ||
{ | ||
rOrigin = std::floor(i * scaleRow); | ||
cOrigin = std::floor(j * scaleCol); | ||
|
||
if (rOrigin > inRowSize - 2) | ||
rOrigin = inRowSize - 2; | ||
if (cOrigin > inColSize - 2) | ||
cOrigin = inColSize - 2; | ||
|
||
double deltaR = i * scaleRow - rOrigin; | ||
double deltaC = j * scaleCol - cOrigin; | ||
coeff1 = (1 - deltaR) * (1 - deltaC); | ||
coeff2 = deltaR * (1 - deltaC); | ||
coeff3 = (1 - deltaR) * deltaC; | ||
coeff4 = deltaR * deltaC; | ||
|
||
size_t ptr = k * inRowSize * inColSize + cOrigin * inColSize + | ||
rOrigin; | ||
|
||
output(k * outRowSize * outColSize + j * outColSize + i) = | ||
input(ptr) * coeff1 + | ||
input(ptr + 1) * coeff2 + | ||
input(ptr + inColSize) * coeff3 + | ||
input(ptr + inColSize + 1) * coeff4; | ||
} | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* DownSample the given input. | ||
* | ||
* @param input The input matrix | ||
* @param output The resulting down-sampled output image. | ||
*/ | ||
template<typename eT> | ||
void DownSample(const arma::Mat<eT>& input, arma::Mat<eT>& output) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you describe the arguments? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While upsampling the input represents the image and output represent the zoomed image. |
||
{ | ||
if (output.is_empty()) | ||
output.set_size(inRowSize * inColSize, 1); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You didn't take into account |
||
|
||
assert(output.n_rows == inRowSize * inColSize); | ||
assert(output.n_cols == 1); | ||
|
||
if (input.n_elem == output.n_elem) | ||
{ | ||
output = input; | ||
} | ||
else | ||
{ | ||
scaleRow = (double)(outRowSize) / inRowSize; | ||
scaleCol = (double)(outColSize) / inColSize; | ||
|
||
for (size_t k = 0; k < depth; k++) | ||
for (size_t i = 0; i < inRowSize; i++) | ||
for (size_t j = 0; j < inColSize; j++) | ||
{ | ||
rOrigin = std::floor(i * scaleRow); | ||
cOrigin = std::floor(j * scaleCol); | ||
|
||
if (rOrigin > outRowSize - 2) | ||
rOrigin = outRowSize - 2; | ||
if (cOrigin > outColSize - 2) | ||
cOrigin = outColSize - 2; | ||
|
||
double deltaR = i * scaleRow - rOrigin; | ||
double deltaC = j * scaleCol - cOrigin; | ||
coeff1 = (1 - deltaR) * (1 - deltaC); | ||
coeff2 = deltaR * (1 - deltaC); | ||
coeff3 = (1 - deltaR) * deltaC; | ||
coeff4 = deltaR * deltaC; | ||
|
||
size_t ptr = k * outRowSize * outColSize + cOrigin * outColSize + | ||
rOrigin; | ||
|
||
output(k * inColSize * inRowSize + j * inColSize + i) = | ||
input(ptr) * coeff1 + | ||
input(ptr + 1) * coeff2 + | ||
input(ptr + outColSize) * coeff3 + | ||
input(ptr + outColSize + 1) * coeff4; | ||
} | ||
} | ||
} | ||
/** | ||
* Serialize the layer. | ||
*/ | ||
template<typename Archive> | ||
void Serialize(Archive& ar, const unsigned int /* version */) | ||
{ | ||
ar & data::CreateNVP(inRowSize, "inRowSize"); | ||
ar & data::CreateNVP(inColSize, "inColSize"); | ||
ar & data::CreateNVP(outRowSize, "outRowSize"); | ||
ar & data::CreateNVP(outColSize, "outColSize"); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You forgot to serialize |
||
|
||
private: | ||
//! Locally stored row size of the input. | ||
const size_t inRowSize; | ||
//! Locally stored column size of the input. | ||
const size_t inColSize; | ||
//! Locally stored row size of the output. | ||
const size_t outRowSize; | ||
//! Locally stored column size of the input. | ||
const size_t outColSize; | ||
//! Locally stored depth of the input. | ||
const size_t depth; | ||
|
||
//! Locally stored scaling factor along row. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess all variables below should be defined locally inside the functions. How do you think? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, the variables are used by both the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As for me, it improves readability and points out that you needn't these variables outside of the function. |
||
double scaleRow; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We discussed that before but the discussion was stopped: I think it is better to declare the variables below inside the functions since we needn't their values. As for me that improves readability. How do you think? |
||
//! Locally stored scaling factor along row. | ||
double scaleCol; | ||
//! Locally stored interger part of the current row idx in input. | ||
double rOrigin; | ||
//! Locally stored interger part of the current column idx in input. | ||
double cOrigin; | ||
|
||
//! Locally stored coefficient around given idx. | ||
double coeff1; | ||
//! Locally stored coefficient around given idx. | ||
double coeff2; | ||
//! Locally stored coefficient around given idx. | ||
double coeff3; | ||
//! Locally stored coefficient around given idx. | ||
double coeff4; | ||
}; // class BiLinearFunction | ||
|
||
} // namespace ann | ||
} // namespace mlpack | ||
|
||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,6 +34,7 @@ | |
#include <mlpack/methods/ann/layer/parametric_relu.hpp> | ||
#include <mlpack/methods/ann/layer/reinforce_normal.hpp> | ||
#include <mlpack/methods/ann/layer/select.hpp> | ||
#include <mlpack/methods/ann/layer/resize.hpp> | ||
|
||
// Convolution modules. | ||
#include <mlpack/methods/ann/convolution_rules/border_modes.hpp> | ||
|
@@ -114,7 +115,8 @@ using LayerTypes = boost::variant< | |
ReinforceNormal<arma::mat, arma::mat>*, | ||
Select<arma::mat, arma::mat>*, | ||
Sequential<arma::mat, arma::mat>*, | ||
VRClassReward<arma::mat, arma::mat>* | ||
VRClassReward<arma::mat, arma::mat>*, | ||
Resize<BiLinearFunction, arma::mat, arma::mat>* | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All layers except |
||
>; | ||
|
||
} // namespace ann | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
/** | ||
* @file resize.hpp | ||
* @author Kris Singh | ||
* | ||
* | ||
* | ||
* mlpack is free software; you may redistribute it and/or modify it under the | ||
* terms of the 3-clause BSD license. You should have received a copy of the | ||
* 3-clause BSD license along with mlpack. If not, see | ||
* http://www.opensource.org/licenses/BSD-3-Clause for more information. | ||
*/ | ||
#ifndef MLPACK_METHODS_ANN_LAYER_RESIZE_HPP | ||
#define MLPACK_METHODS_ANN_LAYER_RESIZE_HPP | ||
|
||
#include <mlpack/prereqs.hpp> | ||
|
||
#include <mlpack/methods/ann/image_functions/bilinear_function.hpp> | ||
|
||
namespace mlpack { | ||
namespace ann /** Artificial Neural Network. */ { | ||
|
||
/** | ||
* Implementation of the Resize layer class. The Resize class represents a | ||
* single layer of a neural network. | ||
* | ||
* @tparam InputDataType Type of the input data (arma::colvec, arma::mat, | ||
* arma::sp_mat or arma::cube). | ||
* @tparam OutputDataType Type of the output data (arma::colvec, arma::mat, | ||
* arma::sp_mat or arma::cube). | ||
* | ||
* @tparam InterpolationType Type of the inpterpolation applied to the input | ||
* (BilinearFunction) | ||
* | ||
*/ | ||
template < | ||
class InterpolationType = BiLinearFunction, | ||
typename InputDataType = arma::mat, | ||
typename OutputDataType = arma::mat | ||
> | ||
class Resize | ||
{ | ||
public: | ||
//! Create the Resize object. | ||
Resize(InterpolationType policy); | ||
|
||
/** | ||
* Forward pass through the Resize layer. The resize layer interpolates | ||
* the matrix using the given interpolation method. | ||
* If the size of the input and output are same the Forward layer | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I disagree with this statement.
Actually, the layer performs the interpolation. |
||
* does no nothing. | ||
* | ||
* @param input Input the input matrix to interpolate | ||
* @param output The interpolated matrix. | ||
*/ | ||
template<typename eT> | ||
void Forward(const arma::Mat<eT>&& input, arma::Mat<eT>&& output); | ||
|
||
/** | ||
* Ordinary feed backward pass of a neural network, calculating the function | ||
* f(x) by propagating x backwards trough f. Using the results from the feed | ||
* forward pass. | ||
* | ||
* @param input The propagated input activation. | ||
* @param gy The backpropagated error. | ||
* @param g The calculated gradient. | ||
*/ | ||
template<typename eT> | ||
void Backward(const arma::Mat<eT>&& /* input */, | ||
arma::Mat<eT>&& gy, | ||
arma::Mat<eT>&& g); | ||
|
||
//! Get the input parameter. | ||
InputDataType const& InputParameter() const { return inputParameter; } | ||
//! Modify the input parameter. | ||
InputDataType& InputParameter() { return inputParameter; } | ||
|
||
//! Get the output parameter. | ||
OutputDataType const& OutputParameter() const { return outputParameter; } | ||
//! Modify the output parameter. | ||
OutputDataType& OutputParameter() { return outputParameter; } | ||
|
||
//! Get the delta. | ||
OutputDataType const& Delta() const { return delta; } | ||
//! Modify the delta. | ||
OutputDataType& Delta() { return delta; } | ||
|
||
/** | ||
* Serialize the layer | ||
*/ | ||
template<typename Archive> | ||
void Serialize(Archive& ar, const unsigned int /* version */); | ||
|
||
private: | ||
//! Locally-stored interpolation method | ||
InterpolationType policy; | ||
//! Locally-stored delta object. | ||
OutputDataType delta; | ||
|
||
//! Locally-stored input parameter object. | ||
InputDataType inputParameter; | ||
|
||
//! Locally-stored output parameter object. | ||
OutputDataType outputParameter; | ||
}; // class Resize | ||
|
||
} // namespace ann | ||
} // namespace mlpack | ||
|
||
// Include implementation. | ||
#include "resize_impl.hpp" | ||
|
||
#endif |
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 forgot to describe the
depth
argument.