Start implementing copy and move constructors correctly.
This commit is contained in:
@@ -45,6 +45,18 @@ class AddType : public Layer<InputType, OutputType>
|
||||
//! Clone the AddType object. This handles polymorphism correctly.
|
||||
AddType* Clone() const { return new AddType(*this); }
|
||||
|
||||
// Virtual destructor.
|
||||
virtual ~AddType();
|
||||
|
||||
//! Copy the given AddType layer.
|
||||
AddType(const AddType& other);
|
||||
//! Take ownership of the given AddType layer.
|
||||
AddType(AddType&& other);
|
||||
//! Copy the given AddType layer.
|
||||
AddType& operator=(const AddType& other);
|
||||
//! Take ownership of the given AddType layer.
|
||||
AddType& operator=(AddType&& other);
|
||||
|
||||
/**
|
||||
* Ordinary feed forward pass of a neural network, evaluating the function
|
||||
* f(x) by propagating the activity forward through f.
|
||||
|
||||
@@ -25,6 +25,48 @@ AddType<InputType, OutputType>::AddType() : outSize(0)
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
template<typename InputType, typename OutputType>
|
||||
AddType<InputType, OutputType>::AddType(const AddType& other) :
|
||||
Layer<InputType, OutputType>(other),
|
||||
outSize(other.outSize)
|
||||
{
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
template<typename InputType, typename OutputType>
|
||||
AddType<InputType, OutputType>::AddType(AddType&& other) :
|
||||
Layer<InputType, OutputType>(std::move(other)),
|
||||
outSize(std::move(other.outSize))
|
||||
{
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
template<typename InputType, typename OutputType>
|
||||
AddType<InputType, OutputType>&
|
||||
AddType<InputType, OutputType>::operator=(const AddType& other)
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
Layer<InputType, OutputType>::operator=(other);
|
||||
outSize = other.outSize;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename InputType, typename OutputType>
|
||||
AddType<InputType, OutputType>&
|
||||
AddType<InputType, OutputType>::operator=(AddType&& other)
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
Layer<InputType, OutputType>::operator=(std::move(other));
|
||||
outSIze = std::move(other.outSize);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename InputType, typename OutputType>
|
||||
void AddType<InputType, OutputType>::Forward(
|
||||
const InputType& input, OutputType& output)
|
||||
|
||||
@@ -45,8 +45,8 @@ namespace ann /** Artificial Neural Network. */ {
|
||||
* @tparam OutputType Type of the output data (arma::colvec, arma::mat,
|
||||
* arma::sp_mat or arma::cube).
|
||||
*/
|
||||
template <typename InputType = arma::mat,
|
||||
typename OutputType = arma::mat>
|
||||
template<typename InputType = arma::mat,
|
||||
typename OutputType = arma::mat>
|
||||
class AlphaDropout : public Layer<InputType, OutputType>
|
||||
{
|
||||
public:
|
||||
@@ -64,6 +64,18 @@ class AlphaDropout : public Layer<InputType, OutputType>
|
||||
*/
|
||||
AlphaDropout* Clone() const { return new AlphaDropout(*this); }
|
||||
|
||||
// Virtual destructor.
|
||||
virtual ~AlphaDropout() { }
|
||||
|
||||
//! Copy the given AlphaDropout layer.
|
||||
AlphaDropout(const AlphaDropout& other);
|
||||
//! Take ownership of the given AlphaDropout layer.
|
||||
AlphaDropout(AlphaDropout&& other);
|
||||
//! Copy the given AlphaDropout layer.
|
||||
AlphaDropout& operator=(const AlphaDropout& other);
|
||||
//! Take ownership of the given AlphaDropout layer.
|
||||
AlphaDropout& operator=(AlphaDropout&& other);
|
||||
|
||||
/**
|
||||
* Ordinary feed forward pass of the alpha_dropout layer.
|
||||
*
|
||||
|
||||
@@ -32,6 +32,64 @@ AlphaDropout<InputType, OutputType>::AlphaDropout(
|
||||
Ratio(ratio);
|
||||
}
|
||||
|
||||
template<typename InputType, typename OutputType>
|
||||
AlphaDropout<InputType, OutputType>::AlphaDropout(const AlphaDropout& other) :
|
||||
Layer<InputType, OutputType>(other),
|
||||
mask(other.mask),
|
||||
ratio(other.ratio),
|
||||
alphaDash(other.alphaDash),
|
||||
a(other.a),
|
||||
b(other.b)
|
||||
{
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
template<typename InputType, typename OutputType>
|
||||
AlphaDropout<InputType, OutputType>::AlphaDropout(AlphaDropout&& other) :
|
||||
Layer<InputType, OutputType>(std::move(other)),
|
||||
mask(std::move(other.mask)),
|
||||
ratio(std::move(other.ratio)),
|
||||
alphaDash(std::move(other.alphaDash)),
|
||||
a(std::move(other.a)),
|
||||
b(std::move(other.b))
|
||||
{
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
template<typename InputType, typename OutputType>
|
||||
AlphaDropout<InputType, OutputType>&
|
||||
AlphaDropout<InputType, OutputType>::operator=(const AlphaDropout& other)
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
Layer<InputType, OutputType>::operator=(other);
|
||||
mask = other.mask;
|
||||
ratio = other.ratio;
|
||||
alphaDash = other.alphaDash;
|
||||
a = other.a;
|
||||
b = other.b;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename InputType, typename OutputType>
|
||||
AlphaDropout<InputType, OutputType>&
|
||||
AlphaDropout<InputType, OutputType>::operator=(AlphaDropout&& other)
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
Layer<InputType, OutputType>::operator=(std::move(other));
|
||||
mask = std::move(other.mask);
|
||||
ratio = std::move(other.ratio);
|
||||
alphaDash = std::move(other.alphaDash);
|
||||
a = std::move(other.a);
|
||||
b = std::move(other.b);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename InputType, typename OutputType>
|
||||
void AlphaDropout<InputType, OutputType>::Forward(
|
||||
const InputType& input, OutputType& output)
|
||||
|
||||
@@ -79,6 +79,12 @@ class BaseLayer : public Layer<InputType, OutputType>
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
// Virtual destructor.
|
||||
virtual ~BaseLayer() { }
|
||||
|
||||
// No copy constructor or operators needed here, since the class has no
|
||||
// members.
|
||||
|
||||
//! Clone the BaseLayer object. This handles polymorphism correctly.
|
||||
BaseLayer* Clone() const { return new BaseLayer(*this); }
|
||||
|
||||
|
||||
@@ -49,6 +49,18 @@ class ConcatenateType : public Layer<InputType, OutputType>
|
||||
//! Clone the ConcatenateType object. This handles polymorphism correctly.
|
||||
ConcatenateType* Clone() const { return new ConcatenateType(*this); }
|
||||
|
||||
// Virtual destructor.
|
||||
virtual ~ConcatenateType() { }
|
||||
|
||||
//! Copy the given ConcatenateType layer.
|
||||
ConcatenateType(const ConcatenateType& other);
|
||||
//! Take ownership of the given ConcatenateType layer.
|
||||
ConcatenateType(ConcatenateType&& other);
|
||||
//! Copy the given ConcatenateType layer.
|
||||
ConcatenateType& operator=(const ConcatenateType& other);
|
||||
//! Take ownership of the given ConcatenateType layer.
|
||||
ConcatenateType& operator=(ConcatenateType&& other);
|
||||
|
||||
/**
|
||||
* Ordinary feed forward pass of a neural network, evaluating the function
|
||||
* f(x) by propagating the activity forward through f.
|
||||
|
||||
@@ -27,6 +27,51 @@ ConcatenateType(const InputType& concat) :
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
template<typename InputType, typename OutputType>
|
||||
ConcatenateType<InputType, OutputType>::
|
||||
ConcatenateType(const ConcatenateType& other) :
|
||||
Layer<InputType, OutputType>(other),
|
||||
concat(other.concat)
|
||||
{
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
template<typename InputType, typename OutputType>
|
||||
ConcatenateType<InputType, OutputType>::
|
||||
ConcatenateType(ConcatenateType&& other) :
|
||||
Layer<InputType, OutputType>(std::move(other)),
|
||||
concat(other.concat)
|
||||
{
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
template<typename InputType, typename OutputType>
|
||||
ConcatenateType<InputType, OutputType>&
|
||||
ConcatenateType<InputType, OutputType>::operator=(const ConcatenateType& other)
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
Layer<InputType, OutputType>::operator=(other);
|
||||
concat = other.concat;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename InputType, typename OutputType>
|
||||
ConcatenateType<InputType, OutputType>&
|
||||
ConcatenateType<InputType, OutputType>::operator=(ConcatenateType&& other)
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
Layer<InputType, OutputType>::operator=(std::move(other));
|
||||
concat = std::move(other.concat);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename InputType, typename OutputType>
|
||||
void ConcatenateType<InputType, OutputType>::Forward(
|
||||
const InputType& input, OutputType& output)
|
||||
|
||||
@@ -132,16 +132,16 @@ class ConvolutionType : public Layer<InputType, OutputType>
|
||||
ConvolutionType* Clone() const { return new ConvolutionType(*this); }
|
||||
|
||||
//! Copy constructor.
|
||||
// ConvolutionType(const ConvolutionType& layer);
|
||||
ConvolutionType(const ConvolutionType& layer);
|
||||
|
||||
//! Move constructor.
|
||||
// ConvolutionType(ConvolutionType&&);
|
||||
ConvolutionType(ConvolutionType&&);
|
||||
|
||||
//! Copy assignment operator.
|
||||
// ConvolutionType& operator=(const ConvolutionType& layer);
|
||||
ConvolutionType& operator=(const ConvolutionType& layer);
|
||||
|
||||
//! Move assignment operator.
|
||||
// ConvolutionType& operator=(ConvolutionType&& layer);
|
||||
ConvolutionType& operator=(ConvolutionType&& layer);
|
||||
|
||||
/*
|
||||
* Set the weight and bias term.
|
||||
|
||||
@@ -107,7 +107,63 @@ ConvolutionType<
|
||||
this->paddingType = util::ToLower(paddingTypeIn);
|
||||
}
|
||||
|
||||
// TODO: copy/move constructor/operator
|
||||
template<
|
||||
typename ForwardConvolutionRule,
|
||||
typename BackwardConvolutionRule,
|
||||
typename GradientConvolutionRule,
|
||||
typename InputType,
|
||||
typename OutputType
|
||||
>
|
||||
ConvolutionType<
|
||||
ForwardConvolutionRule,
|
||||
BackwardConvolutionRule,
|
||||
GradientConvolutionRule,
|
||||
InputType,
|
||||
OutputType
|
||||
>::ConvolutionType(const ConvolutionType& other) :
|
||||
Layer<InputType, OutputType>(other),
|
||||
maps(other.maps),
|
||||
kernelWidth(other.kernelWidth),
|
||||
kernelHeight(other.kernelHeight),
|
||||
strideWidth(other.strideWidth),
|
||||
strideHeight(other.strideHeight),
|
||||
padWLeft(other.padWLeft),
|
||||
padWRight(other.padWRight),
|
||||
padHBottom(other.padHBottom),
|
||||
padHTop(other.padHTop),
|
||||
paddingType(other.paddingType)
|
||||
{
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
template<
|
||||
typename ForwardConvolutionRule,
|
||||
typename BackwardConvolutionRule,
|
||||
typename GradientConvolutionRule,
|
||||
typename InputType,
|
||||
typename OutputType
|
||||
>
|
||||
ConvolutionType<
|
||||
ForwardConvolutionRule,
|
||||
BackwardConvolutionRule,
|
||||
GradientConvolutionRule,
|
||||
InputType,
|
||||
OutputType
|
||||
>::ConvolutionType(ConvolutionType&& other) :
|
||||
Layer<InputType, OutputType>(std::move(other)),
|
||||
maps(other.maps),
|
||||
kernelWidth(other.kernelWidth),
|
||||
kernelHeight(other.kernelHeight),
|
||||
strideWidth(other.strideWidth),
|
||||
strideHeight(other.strideHeight),
|
||||
padWLeft(other.padWLeft),
|
||||
padWRight(other.padWRight),
|
||||
padHBottom(other.padHBottom),
|
||||
padHTop(other.padHTop),
|
||||
paddingType(std::move(other.paddingType))
|
||||
{
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
template<
|
||||
typename ForwardConvolutionRule,
|
||||
|
||||
@@ -60,25 +60,58 @@ class Layer
|
||||
{
|
||||
public:
|
||||
//! Default constructor.
|
||||
Layer() : validOutputDimensions(false) { /* Nothing to do here */ }
|
||||
Layer() : validOutputDimensions(false), training(false)
|
||||
{ /* Nothing to do here */ }
|
||||
|
||||
//! Default deconstructor.
|
||||
virtual ~Layer() { }
|
||||
|
||||
//! Copy constructor.
|
||||
Layer(const Layer& /* layer */) { /* Nothing to do here */ }
|
||||
//! Copy constructor. This is not responsible for copying weights!
|
||||
Layer(const Layer& layer) :
|
||||
inputDimensions(layer.inputDimensions),
|
||||
outputDimensions(layer.outputDimensions),
|
||||
validOutputDimensions(layer.validOutputDimensions),
|
||||
training(layer.training)
|
||||
{ }
|
||||
|
||||
//! Make a copy of the object.
|
||||
virtual Layer* Clone() const = 0;
|
||||
|
||||
//! Move constructor.
|
||||
Layer(Layer&& /* layer */) { /* Nothing to do here */ }
|
||||
//! Move constructor. This is not responsible for moving weights!
|
||||
Layer(Layer&& layer) :
|
||||
inputDimensions(std::move(layer.inputDimensions)),
|
||||
outputDimensions(std::move(layer.outputDimensions)),
|
||||
validOutputDimensions(std::move(layer.validOutputDimensions)),
|
||||
training(std::move(layer.training))
|
||||
{ }
|
||||
|
||||
//! Copy assignment operator.
|
||||
virtual Layer& operator=(const Layer& /* layer */) { return *this; }
|
||||
//! Copy assignment operator. This is not responsible for copying weights!
|
||||
virtual Layer& operator=(const Layer& layer)
|
||||
{
|
||||
if (&layer != this)
|
||||
{
|
||||
inputDimensions = layer.inputDimensions;
|
||||
outputDimensions = layer.outputDimensions;
|
||||
validOutputDimensions = layer.validOutputDimensions;
|
||||
training = layer.training;
|
||||
}
|
||||
|
||||
//! Move assignment operator.
|
||||
virtual Layer& operator=(Layer&& /* layer */) { return *this; }
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Move assignment operator. This is not responsible for moving weights!
|
||||
virtual Layer& operator=(Layer&& layer)
|
||||
{
|
||||
if (&layer != this)
|
||||
{
|
||||
inputDimensions = std::move(layer.inputDimensions);
|
||||
outputDimensions = std::move(layer.outputDimensions);
|
||||
validOutputDimensions = std::move(layer.validOutputDimensions);
|
||||
training = std::move(layer.training);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes an input object, and computes the corresponding output of the layer.
|
||||
|
||||
@@ -60,9 +60,23 @@ class LinearType: public Layer<InputType, OutputType>
|
||||
LinearType(const size_t outSize,
|
||||
RegularizerType regularizer = RegularizerType());
|
||||
|
||||
virtual ~LinearType() { }
|
||||
|
||||
//! Clone the LinearType object. This handles polymorphism correctly.
|
||||
LinearType* Clone() const { return new LinearType(*this); }
|
||||
|
||||
//! Copy the other Linear layer (but not weights).
|
||||
LinearType(const LinearType& layer);
|
||||
|
||||
//! Take ownership of the members of the other Linear layer (but not weights).
|
||||
LinearType(LinearType&& layer);
|
||||
|
||||
//! Copy the other Linear layer (but not weights).
|
||||
LinearType& operator=(const LinearType& layer);
|
||||
|
||||
//! Take ownership of the members of the other Linear layer (but not weights).
|
||||
LinearType& operator=(LinearType&& layer);
|
||||
|
||||
/**
|
||||
* Reset the layer parameter (weights and bias). The method is called to
|
||||
* assign the allocated memory to the internal learnable parameters.
|
||||
|
||||
@@ -40,6 +40,62 @@ LinearType<InputType, OutputType, RegularizerType>::LinearType(
|
||||
weights.set_size(WeightSize(), 1);
|
||||
}
|
||||
|
||||
// Copy constructor.
|
||||
template<typename InputType, typename OutputType, typename RegularizerType>
|
||||
LinearType<InputType, OutputType, RegularizerType>::LinearType(
|
||||
const LinearType& layer) :
|
||||
Layer<InputType, OutputType>(layer),
|
||||
inSize(layer.inSize),
|
||||
outSize(layer.outSize),
|
||||
regularizer(layer.regularizer)
|
||||
{
|
||||
// Nothing else to do.
|
||||
}
|
||||
|
||||
// Move constructor.
|
||||
template<typename InputType, typename OutputType, typename RegularizerType>
|
||||
LinearType<InputType, OutputType, RegularizerType>::LinearType(
|
||||
LinearType&& layer) :
|
||||
Layer<InputType, OutputType>(std::move(layer)),
|
||||
inSize(std::move(layer.inSize)),
|
||||
outSize(std::move(layer.outSize)),
|
||||
regularizer(std::move(layer.regularizer))
|
||||
{
|
||||
// Nothing else to do.
|
||||
}
|
||||
|
||||
template<typename InputType, typename OutputType, typename RegularizerType>
|
||||
LinearType<InputType, OutputType, RegularizerType>&
|
||||
LinearType<InputType, OutputType, RegularizerType>::operator=(
|
||||
const LinearType& layer)
|
||||
{
|
||||
if (&layer != this)
|
||||
{
|
||||
Layer<InputType, OutputType>::operator=(layer);
|
||||
inSize = layer.inSize;
|
||||
outSize = layer.outSize;
|
||||
regularizer = layer.regularizer;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename InputType, typename OutputType, typename RegularizerType>
|
||||
LinearType<InputType, OutputType, RegularizerType>&
|
||||
LinearType<InputType, OutputType, RegularizerType>::operator=(
|
||||
LinearType&& layer)
|
||||
{
|
||||
if (&layer != this)
|
||||
{
|
||||
Layer<InputType, OutputType>::operator=(std::move(layer));
|
||||
inSize = std::move(layer.inSize);
|
||||
outSize = std::move(layer.outSize);
|
||||
regularizer = std::move(layer.regularizer);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename InputType, typename OutputType, typename RegularizerType>
|
||||
void LinearType<InputType, OutputType, RegularizerType>::SetWeights(
|
||||
typename OutputType::elem_type* weightsPtr)
|
||||
|
||||
Reference in New Issue
Block a user