def Train(self, inputs, targets):
        # Calc errors
        self.FeedForward(inputs)
        targets = Matrix.FromArray(targets)
        output_errors = Matrix.Subtract(targets, self.outputs)
        weights_ho_T = Matrix.Transpose(self.weights_ho)
        hidden_errors = Matrix.Multiply(weights_ho_T, output_errors)
        # Calc gradients
        gradient_o = Matrix.StaticMap(self.outputs, dsigmoid)
        gradient_o.ElementMultiply(output_errors)
        gradient_o.ElementMultiply(self.lr)
        hidden_T = Matrix.Transpose(self.hidden)
        delta_weights_ho = Matrix.Multiply(gradient_o, hidden_T)

        gradient_h = Matrix.StaticMap(self.hidden, dsigmoid)
        gradient_h.ElementMultiply(hidden_errors)
        gradient_h.ElementMultiply(self.lr)
        input_T = Matrix.Transpose(self.inputs)
        delta_weights_ih = Matrix.Multiply(gradient_h, input_T)

        # Adjusting weights and biases
        # self.weights_ih.Display()
        self.weights_ih.Add(delta_weights_ih)
        self.bias_h.Add(gradient_h)
        # delta_weights_ho.Display()
        self.weights_ho.Add(delta_weights_ho)
        self.bias_o.Add(gradient_o)
Exemple #2
0
class Layer:
    def __init__(self, neuronCount: int):
        self.neuronCount = neuronCount
        self.nextLayer = False
        self.previousLayer = False
        self.learning_rate = 0.5

    def SetInputLayerActivationMatrix(self, neuronCount: int,
                                      trainingBatchSize: int):
        self.activations = Matrix(neuronCount, trainingBatchSize)

    def CopyInputLayerActivationMatrix(self, matrix: Matrix):
        self.activations.COPY(matrix)

    def SetPreviousLayer(self, previousLayer: Layer, trainingBatchSize: int):
        self.previousLayer = previousLayer
        self.previousLayer.nextLayer = self

        self.activations = Matrix(self.neuronCount, trainingBatchSize)
        self.deltaActivations = Matrix(self.neuronCount, trainingBatchSize)

        self.sums = Matrix(self.neuronCount, trainingBatchSize)
        self.deltaSums = Matrix(self.neuronCount, trainingBatchSize)

        self.weights = Matrix(self.neuronCount, self.previousLayer.neuronCount)
        self.weights.Randomize()
        self.deltaWeights = Matrix(self.neuronCount,
                                   self.previousLayer.neuronCount)
        self.deltaWeightsTmp = Matrix(self.neuronCount,
                                      self.previousLayer.neuronCount)

        self.biases = Matrix(self.neuronCount, 1)
        self.biases.Randomize()
        self.deltaBiases = Matrix(self.neuronCount, trainingBatchSize)

    def FeedForward(self):
        if self.previousLayer:
            self.sums.mat_MUL(self.weights, self.previousLayer.activations)
            self.sums.AddColumnVector(self.biases)
            self.sums.ApplyFunction(self.activations, self.activationFunction)

        if self.nextLayer:
            self.nextLayer.FeedForward()

    def FeedBack(self, targets: Matrix, trainingBatchSize: int):
        if self.previousLayer:
            self.deltaBiases.COPY(self.activations)
            self.sums.ApplyFunction(self.deltaSums, self.derivative)

            if not self.nextLayer:
                self.deltaBiases.SUB(targets)
            else:
                self.deltaWeightsTmp.Transpose(self.nextLayer.weights)
                self.deltaBiases.mat_MUL(self.deltaWeightsTmp,
                                         self.nextLayer.deltaBiases)

            self.deltaBiases.Hadamard(self.deltaSums)
            self.deltaActivations.Transpose(self.previousLayer.activations)
            self.deltaWeights.mat_MUL(self.deltaBiases, self.deltaActivations)

            averageDeltaBias = Matrix(self.neuronCount, 1)
            averageDeltaWeight = Matrix(self.neuronCount, 1)

            self.deltaBiases.GetAverageColumnVector(averageDeltaBias)
            self.deltaWeights.GetAverageColumnVector(averageDeltaWeight)

            averageDeltaBias.scalar_MUL(self.learning_rate / trainingBatchSize)
            averageDeltaWeight.scalar_MUL(self.learning_rate /
                                          trainingBatchSize)

            self.biases.SubColumnVector(averageDeltaBias)
            self.weights.SubColumnVector(averageDeltaWeight)

            self.previousLayer.FeedBack(targets, trainingBatchSize)

    def SetActivationFunction(self, activationFunction, derivative):
        self.activationFunction = activationFunction
        self.derivative = derivative

    def PrintActivations(self):
        self.activations.PrintMatrix()