Commit a0220801 authored by Davis King's avatar Davis King

Upgraded the con_ layer so that you can set the nr or nc to 0 in the layer

specification and this means "make the filter cover the whole input image
dimension".  So it's just an easy way to make a filter sized exactly so that it
will have one output along that dimension.
parent 692ddb8c
...@@ -41,12 +41,14 @@ namespace dlib ...@@ -41,12 +41,14 @@ namespace dlib
public: public:
static_assert(_num_filters > 0, "The number of filters must be > 0"); static_assert(_num_filters > 0, "The number of filters must be > 0");
static_assert(_nr > 0, "The number of rows in a filter must be > 0"); static_assert(_nr >= 0, "The number of rows in a filter must be >= 0");
static_assert(_nc > 0, "The number of columns in a filter must be > 0"); static_assert(_nc >= 0, "The number of columns in a filter must be >= 0");
static_assert(_stride_y > 0, "The filter stride must be > 0"); static_assert(_stride_y > 0, "The filter stride must be > 0");
static_assert(_stride_x > 0, "The filter stride must be > 0"); static_assert(_stride_x > 0, "The filter stride must be > 0");
static_assert(0 <= _padding_y && _padding_y < _nr, "The padding must be smaller than the filter size."); static_assert(_nr==0 || (0 <= _padding_y && _padding_y < _nr), "The padding must be smaller than the filter size.");
static_assert(0 <= _padding_x && _padding_x < _nc, "The padding must be smaller than the filter size."); static_assert(_nc==0 || (0 <= _padding_x && _padding_x < _nc), "The padding must be smaller than the filter size.");
static_assert(_nr!=0 || 0 == _padding_y, "If _nr==0 then the padding must be set to 0 as well.");
static_assert(_nc!=0 || 0 == _padding_x, "If _nr==0 then the padding must be set to 0 as well.");
con_( con_(
num_con_outputs o num_con_outputs o
...@@ -65,8 +67,20 @@ namespace dlib ...@@ -65,8 +67,20 @@ namespace dlib
con_() : con_(num_con_outputs(_num_filters)) {} con_() : con_(num_con_outputs(_num_filters)) {}
long num_filters() const { return num_filters_; } long num_filters() const { return num_filters_; }
long nr() const { return _nr; } long nr() const
long nc() const { return _nc; } {
if (_nr==0)
return filters.nr();
else
return _nr;
}
long nc() const
{
if (_nc==0)
return filters.nc();
else
return _nc;
}
long stride_y() const { return _stride_y; } long stride_y() const { return _stride_y; }
long stride_x() const { return _stride_x; } long stride_x() const { return _stride_x; }
long padding_y() const { return padding_y_; } long padding_y() const { return padding_y_; }
...@@ -154,7 +168,10 @@ namespace dlib ...@@ -154,7 +168,10 @@ namespace dlib
template <typename SUBNET> template <typename SUBNET>
void setup (const SUBNET& sub) void setup (const SUBNET& sub)
{ {
long num_inputs = _nr*_nc*sub.get_output().k(); const long filt_nr = _nr!=0 ? _nr : sub.get_output().nr();
const long filt_nc = _nc!=0 ? _nc : sub.get_output().nc();
long num_inputs = filt_nr*filt_nc*sub.get_output().k();
long num_outputs = num_filters_; long num_outputs = num_filters_;
// allocate params for the filters and also for the filter bias values. // allocate params for the filters and also for the filter bias values.
params.set_size(num_inputs*num_filters_ + num_filters_); params.set_size(num_inputs*num_filters_ + num_filters_);
...@@ -162,7 +179,7 @@ namespace dlib ...@@ -162,7 +179,7 @@ namespace dlib
dlib::rand rnd(std::rand()); dlib::rand rnd(std::rand());
randomize_parameters(params, num_inputs+num_outputs, rnd); randomize_parameters(params, num_inputs+num_outputs, rnd);
filters = alias_tensor(num_filters_, sub.get_output().k(), _nr, _nc); filters = alias_tensor(num_filters_, sub.get_output().k(), filt_nr, filt_nc);
biases = alias_tensor(1,num_filters_); biases = alias_tensor(1,num_filters_);
// set the initial bias values to zero // set the initial bias values to zero
...@@ -263,8 +280,8 @@ namespace dlib ...@@ -263,8 +280,8 @@ namespace dlib
{ {
out << "con\t (" out << "con\t ("
<< "num_filters="<<item.num_filters_ << "num_filters="<<item.num_filters_
<< ", nr="<<_nr << ", nr="<<item.nr()
<< ", nc="<<_nc << ", nc="<<item.nc()
<< ", stride_y="<<_stride_y << ", stride_y="<<_stride_y
<< ", stride_x="<<_stride_x << ", stride_x="<<_stride_x
<< ", padding_y="<<item.padding_y_ << ", padding_y="<<item.padding_y_
...@@ -281,8 +298,8 @@ namespace dlib ...@@ -281,8 +298,8 @@ namespace dlib
{ {
out << "<con" out << "<con"
<< " num_filters='"<<item.num_filters_<<"'" << " num_filters='"<<item.num_filters_<<"'"
<< " nr='"<<_nr<<"'" << " nr='"<<item.nr()<<"'"
<< " nc='"<<_nc<<"'" << " nc='"<<item.nc()<<"'"
<< " stride_y='"<<_stride_y<<"'" << " stride_y='"<<_stride_y<<"'"
<< " stride_x='"<<_stride_x<<"'" << " stride_x='"<<_stride_x<<"'"
<< " padding_y='"<<item.padding_y_<<"'" << " padding_y='"<<item.padding_y_<<"'"
......
...@@ -673,10 +673,22 @@ namespace dlib ...@@ -673,10 +673,22 @@ namespace dlib
{ {
/*! /*!
REQUIREMENTS ON TEMPLATE ARGUMENTS REQUIREMENTS ON TEMPLATE ARGUMENTS
All of them must be > 0. - _num_filters > 0
Also, we require that: - _nr >= 0
- 0 <= _padding_y && _padding_y < _nr - _nc >= 0
- 0 <= _padding_x && _padding_x < _nc - _stride_y > 0
- _stride_x > 0
- _padding_y >= 0
- _padding_x >= 0
- Also, we require that:
- if (_nr == 0) then
- _padding_y == 0
- else
- _padding_y < _nr
- if (_nc == 0) then
- _padding_x == 0
- else
- _padding_x < _nc
WHAT THIS OBJECT REPRESENTS WHAT THIS OBJECT REPRESENTS
This is an implementation of the EXAMPLE_COMPUTATIONAL_LAYER_ interface This is an implementation of the EXAMPLE_COMPUTATIONAL_LAYER_ interface
...@@ -690,6 +702,15 @@ namespace dlib ...@@ -690,6 +702,15 @@ namespace dlib
- OUT.k() == num_filters() - OUT.k() == num_filters()
- OUT.nr() == 1+(IN.nr() + 2*padding_y() - nr())/stride_y() - OUT.nr() == 1+(IN.nr() + 2*padding_y() - nr())/stride_y()
- OUT.nc() == 1+(IN.nc() + 2*padding_x() - nc())/stride_x() - OUT.nc() == 1+(IN.nc() + 2*padding_x() - nc())/stride_x()
Note also that setting _nr or _nc to 0 has a special meaning of "set the
filter size equal to the input image size". Specifically, it means:
- if (_nr == 0) then
- nr() == IN.nr()
- OUT.nr() == 1
- if (_nc == 0) then
- nc() == IN.nc()
- OUT.nc() == 1
!*/ !*/
public: public:
...@@ -754,14 +775,22 @@ namespace dlib ...@@ -754,14 +775,22 @@ namespace dlib
) const; ) const;
/*! /*!
ensures ensures
- returns the number of rows in the filters in this layer. - returns the number of rows in the filters in this layer. Note that if
nr()==0 then it means the size of the filter is not yet assigned, but
once setup() is called nr() will be set to the input tensor's nr().
Therefore, nr()==0 has the special interpretation of "be the same size as
the input tensor".
!*/ !*/
long nc( long nc(
) const; ) const;
/*! /*!
ensures ensures
- returns the number of columns in the filters in this layer. - returns the number of columns in the filters in this layer. Note that if
nc()==0 then it means the size of the filter is not yet assigned, but
once setup() is called nc() will be set to the input tensor's nc().
Therefore, nc()==0 has the special interpretation of "be the same size as
the input tensor".
!*/ !*/
long stride_y( long stride_y(
......
...@@ -1715,6 +1715,24 @@ namespace ...@@ -1715,6 +1715,24 @@ namespace
auto res = test_layer(l); auto res = test_layer(l);
DLIB_TEST_MSG(res, res); DLIB_TEST_MSG(res, res);
} }
{
print_spinner();
con_<3,0,2,2,2> l;
auto res = test_layer(l);
DLIB_TEST_MSG(res, res);
}
{
print_spinner();
con_<3,2,0,2,2> l;
auto res = test_layer(l);
DLIB_TEST_MSG(res, res);
}
{
print_spinner();
con_<3,0,0,2,2> l;
auto res = test_layer(l);
DLIB_TEST_MSG(res, res);
}
{ {
print_spinner(); print_spinner();
fc_<1,FC_HAS_BIAS> l; fc_<1,FC_HAS_BIAS> l;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment