Start implementing copy and move constructors correctly.

This commit is contained in:
Ryan Curtin
2022-01-25 22:44:34 -05:00
parent f842111039
commit ec06bcbbff
12 changed files with 362 additions and 16 deletions
+12
View File
@@ -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.
+42
View File
@@ -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)
+14 -2
View File
@@ -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)
+4 -4
View File
@@ -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,
+42 -9
View File
@@ -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.
+14
View File
@@ -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)