Skip to content

Commit

Permalink
Added brain
Browse files Browse the repository at this point in the history
  • Loading branch information
nenadV91 committed May 5, 2019
1 parent 40cc60b commit 627a21d
Show file tree
Hide file tree
Showing 8 changed files with 597 additions and 5 deletions.
109 changes: 109 additions & 0 deletions genetic-algo/population.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
class Population {
constructor(Unit, total = 100) {
this.generation = 1;
this.imortal = false;
this.Unit = Unit;
this.total = total;
this.active = [];
this.saved = [];
this.pool = [];
this.score = 0;
this.mutationRate = 0.2;

this.create()
}

get isEmpty() {
return !this.active.length;
}

get best() {
this.active.sort((a, b) => b.score - a.score);
return this.active[0];
}

create() {
for(let i = 0; i < this.total; i++) {
this.active.push(new this.Unit());
}
}

killActive() {
for(let i = this.active.length - 1; i >= 0; i--) {
this.remove(i);
}
}

remove(index) {
const [unit] = this.active.splice(index, 1);
this.saved.push(unit);
}

update() {
if(frameCount % 5 === 0) {
this.score += 1;
}
}

load(data) {
for(let i = this.active.length - 1; i >= 0; i--) {
const unit = this.active[i];
unit.loadData(data);
this.remove(i);
}
}

reset() {
this.calcFitness();
this.nextGeneration();

this.saved.length = 0;
this.pool.length = 0;
this.generation += 1;
this.score = 0;

this.timeout = setTimeout(() => {
this.imortal = false;
}, 1000)
}

pick() {
let index = 0;
let r = random(1);

while(r > 0) {
r = r - this.pool[index].fitness;
index++
}

index--;
return this.pool[index];
}

calcFitness() {
this.saved.sort((a, b) => {
return a.score - b.score
});

this.pool = this.saved.slice(-20);

const total = this.pool.reduce((r, e) => {
return r + e.score
}, 0);

this.pool.forEach(unit => {
unit.fitness = unit.score / total;
})
}

nextGeneration() {
for(let i = 0; i < this.total; i++) {
const parent = this.pick();
const child = new this.Unit({
brain: parent.brain,
mutationRate: this.mutationRate
});
this.active.push(child);
}
}
}
9 changes: 9 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@
<script src="source/track.js"></script>
<script src="source/stats.js"></script>

<!-- Genetic algo -->
<script src="genetic-algo/population.js"></script>

<!-- Neural network -->
<script src="neural-network/matrix.js"></script>
<script src="neural-network/activation.js"></script>
<script src="neural-network/layer.js"></script>
<script src="neural-network/network.js"></script>

<!-- Index -->
<script src="source/index.js"></script>
</body>
Expand Down
54 changes: 54 additions & 0 deletions neural-network/activation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
function leakyRelu(x) {
if(x > 0) return x;
else return 0.01 * x;
}

const sigmoid = {
func: x => 1 / (1 + Math.exp(-x)),
dfunc: y => y * (1 - y)
}

const relu = {
func: x => x < 0 ? 0 : x,
dfunc: y => y < 0 ? 0 : 1,
useX: true
}

const tanh = {
func: x => Math.tanh(x),
dfunc: y => 1 - (y * y)
}

const softplus = {
func: x => Math.log(1 + Math.exp(x)),
dfunc: y => 1 / 1 + Math.exp(-y),
useX: true
}

class Activation {
constructor(type) {
this.type = type.toLowerCase();
this.func = this.select.func;
this.dfunc = this.select.dfunc;
this.useX = this.select.useX || false;
}

get select() {
switch (this.type) {
case 'sigmoid':
return sigmoid;
break;

case 'relu':
return relu;
break;

case 'tanh':
return tanh;
break;

default:
return sigmoid;
}
}
}
78 changes: 78 additions & 0 deletions neural-network/layer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
class Layer {
constructor(opts) {
this.opts = opts;
this.inodes = opts.inodes;
this.onodes = opts.onodes;
this.activationType = opts.activation || 'sigmoid';
this.lr = opts.lr || 0.1;
}

initWeights() {
this.weights = new Matrix(this.onodes, this.inodes);
this.weights.randomize();
}

initBias() {
this.bias = new Matrix(this.onodes, 1);
this.bias.randomize();
}

initActivation() {
this.activation = new Activation(this.activationType)
}

activate() {
this.initWeights();
this.initBias();
this.initActivation();
}

train(input) {
this.input = input;
this.output = Matrix.dot(this.weights, this.input);
this.output.add(this.bias);

if(this.activation.useX) {
this.outputX = this.output.clone();
}

this.output.forEach(this.activation.func);
}

update({ target, prev }) {
let error = null;
let input = Matrix.T(this.prev ? this.prev.output : this.input);

if(target) {
error = Matrix.subtract(target, this.output);
} else {
const weightsT = Matrix.T(prev.weights);
const prevError = prev.error;
error = Matrix.dot(weightsT, prevError);
}

this.error = error;

if(this.activation.useX) {
this.gradient = this.outputX.map(this.activation.dfunc);
} else {
this.gradient = this.output.map(this.activation.dfunc);
}

this.gradient.multiply(this.error);
this.gradient.multiply(this.lr);

this.deltaW = Matrix.dot(this.gradient, input);

this.weights.add(this.deltaW);
this.bias.add(this.gradient);
}

clone() {
const clone = new Layer(this.opts);
clone.weights = this.weights.clone();
clone.bias = this.bias.clone();
clone.initActivation();
return clone;
}
}
Loading

0 comments on commit 627a21d

Please sign in to comment.