Forward and backward update for NoisyLinear

This commit is contained in:
nishantkr18
2020-05-29 20:00:24 +05:30
parent 11910080e1
commit 45f162f1fc
2 changed files with 87 additions and 9 deletions
+32 -1
View File
@@ -47,11 +47,24 @@ class NoisyLinear
NoisyLinear(const size_t inSize,
const size_t outSize);
//! Copy constructor.
NoisyLinear(const NoisyLinear&);
/*
* Reset the layer parameter.
*/
void Reset();
/*
* Reset the noise parameters(epsilons).
*/
void ResetNoise();
/*
* Reset the values of layer parameters (factorized gaussian noise).
*/
void ResetParameters();
/**
* Ordinary feed forward pass of a neural network, evaluating the function
* f(x) by propagating the activity forward through f.
@@ -141,9 +154,27 @@ class NoisyLinear
//! Locally-stored weight parameters.
OutputDataType weight;
//! Locally-stored bias term parameters.
//! Locally-stored weight-mean parameters.
OutputDataType weightMu;
//! Locally-stored weight-standard-deviation parameters.
OutputDataType weightSigma;
//! Locally-stored weight-epsilon parameters.
OutputDataType weightEpsilon;
//! Locally-stored bias parameters.
OutputDataType bias;
//! Locally-stored bias-mean parameters.
OutputDataType biasMu;
//! Locally-stored bias-standard-deviation parameters.
OutputDataType biasSigma;
//! Locally-stored bias-epsilon parameters.
OutputDataType biasEpsilon;
//! Locally-stored delta object.
OutputDataType delta;
@@ -26,6 +26,16 @@ NoisyLinear<InputDataType, OutputDataType>::NoisyLinear() :
// Nothing to do here.
}
template<typename InputDataType, typename OutputDataType>
NoisyLinear<InputDataType, OutputDataType>::NoisyLinear(
const NoisyLinear& layer) :
inSize(layer.inSize),
outSize(layer.outSize),
weights(layer.weights)
{
Reset();
}
template<typename InputDataType, typename OutputDataType>
NoisyLinear<InputDataType, OutputDataType>::NoisyLinear(
const size_t inSize,
@@ -33,15 +43,40 @@ NoisyLinear<InputDataType, OutputDataType>::NoisyLinear(
inSize(inSize),
outSize(outSize)
{
weights.set_size(outSize * inSize + outSize, 1);
weights.set_size((outSize * inSize + outSize) * 2, 1);
weightEpsilon.set_size(outSize, inSize);
biasEpsilon.set_size(outSize, 1);
}
template<typename InputDataType, typename OutputDataType>
void NoisyLinear<InputDataType, OutputDataType>::Reset()
{
weight = arma::mat(weights.memptr(), outSize, inSize, false, false);
bias = arma::mat(weights.memptr() + weight.n_elem,
weightMu = arma::mat(weights.memptr(),
outSize, inSize, false, false);
biasMu = arma::mat(weights.memptr() + weightMu.n_elem,
outSize, 1, false, false);
weightSigma = arma::mat(weights.memptr() + weightMu.n_elem + biasMu.n_elem,
outSize, inSize, false, false);
biasSigma = arma::mat(weights.memptr() + weightMu.n_elem * 2 + biasMu.n_elem,
outSize, 1, false, false);
this->ResetNoise();
}
template<typename InputDataType, typename OutputDataType>
void NoisyLinear<InputDataType, OutputDataType>::ResetNoise()
{
// TODO: Resets noise parameters.
weightEpsilon.randu();
biasEpsilon.randu();
}
template<typename InputDataType, typename OutputDataType>
void NoisyLinear<InputDataType, OutputDataType>::ResetParameters()
{
/*
* TODO: Reset network parameters according to factorized gaussion
* initialization
*/
}
template<typename InputDataType, typename OutputDataType>
@@ -49,6 +84,8 @@ template<typename eT>
void NoisyLinear<InputDataType, OutputDataType>::Forward(
const arma::Mat<eT>& input, arma::Mat<eT>& output)
{
weight = weightMu + weightSigma % weightEpsilon;
bias = biasMu + biasSigma % biasEpsilon;
output = weight * input;
output.each_col() += bias;
}
@@ -68,10 +105,20 @@ void NoisyLinear<InputDataType, OutputDataType>::Gradient(
const arma::Mat<eT>& error,
arma::Mat<eT>& gradient)
{
gradient.submat(0, 0, weight.n_elem - 1, 0) = arma::vectorise(
error * input.t());
gradient.submat(weight.n_elem, 0, gradient.n_elem - 1, 0) =
arma::sum(error, 1);
// Locally stored to prevent multiplication twice.
arma::mat weightGrad = error * input.t();
// Gradients for mu values
gradient.rows(0, weight.n_elem - 1)
= arma::vectorise(weightGrad);
gradient.rows(weight.n_elem, weight.n_elem + bias.n_elem - 1)
= arma::sum(error, 1);
// Gradients for sigma values
gradient.rows(weight.n_elem + bias.n_elem, gradient.n_elem - bias.n_elem - 1)
= arma::vectorise(weightGrad % weightEpsilon);
gradient.rows(gradient.n_elem - bias.n_elem, gradient.n_elem - 1)
= arma::sum(error % biasEpsilon, 1);
}
template<typename InputDataType, typename OutputDataType>
@@ -85,7 +132,7 @@ void NoisyLinear<InputDataType, OutputDataType>::serialize(
// This is inefficient, but we have to allocate this memory so that
// WeightSetVisitor gets the right size.
if (Archive::is_loading::value)
weights.set_size(outSize * inSize + outSize, 1);
weights.set_size((outSize * inSize + outSize) * 2, 1);
}
} // namespace ann