class Network {
layers = [];
sigError = 1;
epoch = 0;
constructor(layers_neurons){
for(let i in layers_neurons){
let neuron_count = layers_neurons[i]
this.layers.push(new Layer(i,neuron_count))
let this_layer = this.layers[this.layers.length-1]
let prev_layer = this.layers[this.layers.length-2]
if(!prev_layer) continue;
for(let j = 0; j<neuron_count; j++){
for(let k = 0; k<prev_layer.neurons.length; k++){
this_layer.neurons[j].weights[k] = Math.random() * 2 - 1
}
}
}
}
input(input){
let result = input.slice();
for(let i = 0; i<this.layers.length; i++){
result = this.layers[i].activate(result)
}
return result
}
*train(tests,ideals){
this.epoch = 0;
this.error_over_time = [];
let learningRate = 0.3;
let momentum = 0.3;
let minError = 0.01;
let maxEpochs = 30 * 1000;
this.sigError = 1;
let _this = this;
this.deltas = []
this.consec_valid = 0;
this.valid_over_time = [];
this.min_over_time = [];
this.passed = false;
let loop = true;
while(loop){
if(this.epoch > maxEpochs){
break;
}
this.samples = []
for(let i = 0; i < 1; i++){
this.sigError=0
let rand = Math.round(Math.random() * 3)
let sample_idx = rand;
let test_input = tests[sample_idx]
let ideal_output = ideals[sample_idx]
this.input(test_input);
let last_layer = this.layers[this.layers.length-1]
for(let k = this.layers.length-1; k>=0; k--){
if(k === this.layers.length-1){
for(let j in last_layer.neurons){
j = parseInt(j)
let neuron = last_layer.neurons[j]
let output = neuron.output
let delta = ideal_output[j] - output
neuron.gradient = output * (1 - output) * (delta)
this.sigError += Math.pow(delta, 2)
}
}else{
let hidden_layer = this.layers[k]
let following_layer = this.layers[k+1]
for(let n in hidden_layer.neurons){
let neuron = hidden_layer.neurons[n]
let output = neuron.output
let error = 0;
for(let n2 in following_layer.neurons){
let following_neuron = following_layer.neurons[n2]
error += following_neuron.weights[n] * following_neuron.gradient
}
neuron.gradient = output * (1 - output) * error
}
}
}
for(let i = 0; i < this.layers.length; i++) {
let layer = this.layers[i]
for(let j = 0; j < layer.neurons.length; j++) {
let neuron = layer.neurons[j];
neuron.bias += learningRate * neuron.gradient;
for(let k = 0; k < neuron.weights.length; k++) {
let prev_layer = this.layers[i-1]
if(typeof prev_layer === 'undefined'){
prev_layer = this.layers[0];
}
neuron.deltas[k] = learningRate * neuron.gradient * prev_layer.neurons[k].output
neuron.weights[k] += neuron.deltas[k];
if(neuron.previousDeltas[k]){
neuron.weights[k] += momentum * neuron.previousDeltas[k];
}
}
neuron.previousDeltas = neuron.deltas.slice();
}
}
this.passed = true;
for(let i = 0; i<4; i++){
let output = this.input(tests[i]);
if(Math.round(output[0]) != ideals[i][0]){
this.passed = false;
}
}
if(this.passed){
this.consec_valid++;
}else{
this.consec_valid = 0;
}
this.valid_over_time.push(this.consec_valid);
this.epoch++;
this.error_over_time
.push(this.sigError)
this.min_over_time.push(Math.min(...this.error_over_time));
loop = this.sigError > minError || this.consec_valid < 3
if(this.consec_valid >= 3){
loop = false;
break;
}
yield this
}
yield this
}
}
}