TLDR: I am implementing a neural net in Mathematica and need help with back propagation.
This is purely for the joy of implementing a neural network with a functional programming language. If someone is reading this with the serious intention of using a neural net in Mathematica, it's built in to version 11.
I started by implementing a neuron as a list containing a value and the weights of incoming edges, layers as lists of neurons, and networks as lists of layers.
Neuron[i_] := {0}~Join~((2*RandomReal[] - 1) & /@ Range[i]);
Neuron[v_, w_] := Join[{v}, w];
Layer[n_, i_] := Array[Neuron[i] &, n];
Network[i_, h_, o_] := {Layer[i, 0], Layer[h, i], Layer[o, h]};
I then implemented a function to pass an input into the network.
Compute[network_, inputs_] := Fold[#1~Join~{Compute[#2, Last[#1]]} &, {MapThread[Join[{#1}, #2] &, {inputs, Rest /@ First[network]}]}, Rest[network]] /; Depth[network] == 4;
Compute[layer_, values_] := Compute[#, values] & /@ layer /; Depth[layer] == 3;
Compute[neuron_, value_] := {LogisticSigmoid[Total[MapThread[#1*First[value[[#2]]] &, {Rest[neuron], Range[Length[neuron] - 1]}]]]} ~Join~ Rest[neuron] /; Depth[neuron] == 2;
I'm having difficulties with back propagation. I implemented what I believe is correct based on studying other code I've written on this gist and pasted below, but would greatly appreciate either code examples or general pushes in the right direction.
Propagate[network_, output_, learningRate_] :=
With[{
outputLayer = MapThread[
Propagate[#1, network[[2]], #2, learningRate] &,
{Last[network], output}],
hiddenLayer = network[[2]],
inputLayer = First[network]
},
{inputLayer, MapIndexed[Propagate[#1, First[#2],
inputLayer, outputLayer, output, learningRate] &,
hiddenLayer], outputLayer}
] /; Depth[network] == 4;
Propagate[neuron_, hiddenLayer_, target_, learningRate_] :=
Join[{NeuronValue[neuron]},
MapThread[
#1 - learningRate*
-NeuronValue[neuron]*(1 - NeuronValue[neuron])*
(target - NeuronValue[neuron])*#2 &,
{NeuronWeights[neuron], LayerValues[hiddenLayer]}]
];
Propagate[neuron_, index_, inputLayer_, outputLayer_, target_,
learningRate_] :=
Join[{NeuronValue[neuron]},
MapIndexed[
#1 - learningRate*
NeuronValue[neuron]*(1 - NeuronValue[neuron])*
NeuronValue[inputLayer[[First[#2]]]]*
Total[MapThread[(#3 - #1)*-1*#1*(1 - #1)*#2 &, {
LayerValues[outputLayer],
LayerWeights[outputLayer, index],
target}]] &,
NeuronWeights[neuron]]]