-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNet.pde
More file actions
194 lines (161 loc) · 6.4 KB
/
Copy pathNet.pde
File metadata and controls
194 lines (161 loc) · 6.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
//Net class
class Net {
//Layer Array
Layer[] m_layers = new Layer[] {}; // m_layers[layerNum][neuronNum]
//Error Variables
double m_error;
double m_recentAverageError;
double m_recentAverageSmoothingFactor;
//Render Variables
int scale = 200; //Neuron Scale
int radius = 20; //Neuron Radius
float sizeScale = 0.5; //scaleFactor
float startPosX = 200; //Startposition x + scale * sizeScale
float startPosY = 100; //Startposition y + 3 * radius
//Net Constructor
Net(int[] topology) {
//number of Layers
int numLayers = topology.length;
//create layers
for (int layerNum = 0; layerNum < numLayers; ++layerNum) {
//add layer
m_layers = (Layer[])append(m_layers, new Layer());
//Calculate number of outputs + 1 bias
int numOutputs = (layerNum == topology.length - 1) ? 0 : topology[layerNum + 1];
//we have made a new Layer, now fill it with neurons, and
//add a bias neuron to the layer
for (int neuronNum = 0; neuronNum <= topology[layerNum]; ++neuronNum) {
m_layers[m_layers.length - 1].neuron = (Neuron[])append(m_layers[m_layers.length - 1].neuron, new Neuron(numOutputs, neuronNum));
}
//force the bias node´s output value to 1.0. Its the last neuron created above
m_layers[m_layers.length - 1].neuron[m_layers[m_layers.length - 1].neuron.length - 1].setOutputVal(1.0);
}
//Set the render coordinates for the neurons
for(int layerNum = 0; layerNum < m_layers.length; ++layerNum) {
Layer layer = m_layers[layerNum];
for (int neuronNum = 0; neuronNum < layer.neuron.length; ++neuronNum) {
Neuron neuron = layer.neuron[neuronNum];
neuron.x = startPosX + (layerNum + 1) * scale * sizeScale;
neuron.y = startPosY + (neuron.m_myIndex + 1) * 3 * radius;
}
}
}
//Print all weights
void printWeights() {
for(int layerNum = 0; layerNum < m_layers.length; ++layerNum) {
Layer layer = m_layers[layerNum];
println("Layer: " + layerNum);
for (int neuronNum = 0; neuronNum < layer.neuron.length; ++neuronNum) {
Neuron neuron = layer.neuron[neuronNum];
println("Neuron: " + neuronNum);
for(int weiNum = 0; weiNum < neuron.m_outputWeights.length; weiNum++) {
println("Weight " + weiNum + ": " + neuron.m_outputWeights[weiNum].weight);
}
}
}
}
//Render Neural Net
void drawAll(int altY) {
int cols = m_layers.length - 1;
//render error
fill(255);
text("Error rate: " + m_recentAverageError, 10, altY + 15);
//render layers
for(int c = 0; c <= cols; c++) {
Layer l = m_layers[c];
//Layer Header
fill(255,255,0);
textSize(26);
text("L: " + c, startPosX + scale * (c + 1) * sizeScale - radius / 2, startPosY);
//render neurons
for(int r = 0; r < l.neuron.length; ++r) {
Neuron n = l.neuron[r];
//Connections / Lines
if(c < cols) {
for(int conn = 0; conn < m_layers[c+1].neuron.length - 1; conn++) {
Neuron next = m_layers[c+1].neuron[conn];
double weight = n.m_outputWeights[conn].weight;
if(weight < 0)
{
stroke(0);
strokeWeight(constrain((int)(weight * 10 * -1), 0, 2));
} else {
stroke(255);
strokeWeight(constrain((int)(weight * 10), 0, 2));
}
line(n.x + radius, n.y, next.x - radius, next.y);
}
}
//Neurons
fill(constrain((int)(n.m_outputVal * 100), 0, 255));
stroke(255);
strokeWeight(1);
ellipse(n.x, n.y, radius * 2, radius * 2);
float textX = n.x - radius/1.3;
float textY = n.y + radius/4;
fill(255,255,0);
textSize(11);
text(nfs((float)n.m_outputVal, 0, 2) + "", textX, textY);
}
}
}
//FeedForward
void feedForward(double[] inputVals) {
//Assert that the inputValues are as many as neurons in the first layer
assert(inputVals.length == m_layers[0].neuron.length - 1);
//assign (latch) the input values into input neurons
for (int i = 0; i < inputVals.length; ++i) {
m_layers[0].neuron[i].setOutputVal(inputVals[i]);
}
//Forward propagate
for (int layerNum = 1; layerNum < m_layers.length; ++layerNum) {
Layer prevLayer = m_layers[layerNum - 1];
for (int n = 0; n < m_layers[layerNum].neuron.length - 1; ++n) {
m_layers[layerNum].neuron[n].feedForward(prevLayer);
}
}
}
//BackPropagation
void backProp(double[] targetVals) {
//Calculate overall net error (RMS of output neuron errors
Layer outputLayer = m_layers[m_layers.length - 1];
m_error = 0.0;
for (int n = 0; n < outputLayer.neuron.length - 1; ++n) {
double delta = targetVals[n] - outputLayer.neuron[n].getOutputVal();
m_error += delta * delta;
}
m_error /= outputLayer.neuron.length - 1; //get average error squared
m_error = Math.sqrt(m_error); //rms
//Implement a revent average measurment:
m_recentAverageError = (m_recentAverageError * m_recentAverageSmoothingFactor + m_error) / (m_recentAverageSmoothingFactor + 1.0);
//Claculate output layer gradients
for (int n = 0; n < outputLayer.neuron.length - 1; ++n) {
outputLayer.neuron[n].calcOutputGradients(targetVals[n]);
}
//Calculate gradients on hidden layers
for (int layerNum = m_layers.length - 2; layerNum > 0; --layerNum) {
Layer hiddenLayer = m_layers[layerNum];
Layer nextLayer = m_layers[layerNum + 1];
for (int n = 0; n < hiddenLayer.neuron.length; ++n) {
hiddenLayer.neuron[n].calcHiddenGradients(nextLayer);
}
}
//For all layers from outputs to first hidden layer
//update connection weights
for (int layerNum = m_layers.length - 1; layerNum > 0; --layerNum) {
Layer layer = m_layers[layerNum];
Layer prevLayer = m_layers[layerNum - 1];
for (int n = 0; n < layer.neuron.length - 1; ++n) {
layer.neuron[n].updateInputWights(prevLayer);
}
}
}
//Get the results
double[] getResults(double[] resultVals) {
resultVals = new double[] {};
for (int n = 0; n < m_layers[m_layers.length - 1].neuron.length - 1; ++n) {
resultVals = (double[])append(resultVals, m_layers[m_layers.length - 1].neuron[n].getOutputVal());
}
return resultVals;
}
}