Skip to content

Instantly share code, notes, and snippets.

@LlamaTrauma
Last active February 25, 2019 20:27
Show Gist options
  • Save LlamaTrauma/c70a197c123d4328cae9c71b6f08e41d to your computer and use it in GitHub Desktop.
Save LlamaTrauma/c70a197c123d4328cae9c71b6f08e41d to your computer and use it in GitHub Desktop.
Broken JavaScript Neural Network
const math = require('mathjs');
var fs = require('fs');
//These files are found here: http://yann.lecun.com/exdb/mnist/
var imageFile = fs.readFileSync(".../train-images-idx3-ubyte/train-images.idx3-ubyte");
var labelFile = fs.readFileSync(".../train-labels-idx1-ubyte/train-labels.idx1-ubyte");
var pixelValues = [];
for (var image = 0; image <= 6000; image++) {
var pixels = [];
for (var y = 0; y <= 27; y++) {
for (var x = 0; x <= 27; x++) {
pixels.push(imageFile[(image * 28 * 28) + (x + (y * 28)) + 16]);
}
}
pixelValues.push(pixels);
}
var labelValues = [];
for (var image = 0; image <= 6000; image++) {
var out = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
out[labelFile[image + 8]] = 1;
labelValues.push(out);
}
function getMostLikely(a){
var best = 0;
var index = 0;
for(var i = 0; i < a.length; i ++){
if(best < a[i]){
best = a[i];
index = i;
}
}
return(index);
};
const e = 2.71828182845904523;
function sigmoid(a){
return(1 / (1 + math.pow(e, a * -1)));
}
function sigmoidDerivitive(a){
return(a * (1 - a));
}
function squareDiff(a, b){
var out = [];
for(var i = 0; i < a._data.length; i ++){
for(var j = 0; j < a._data[i].length; j ++){
out.push(math.pow(a._data[i][j] - b._data[i][j], 2));
}
}
var outy = 0;
for(var i = 0; i < out.length; i ++){
outy += out[i];
}
outy /= out.length;
return(outy);
}
function multMatrices(a, b){
var out = new math.matrix();
out.resize(a._size, 0);
for(var i = 0; i < a._data.length; i ++){
for(var j = 0; j < a._data[i].length; j ++){
out._data[i][j] = a._data[i][j] * b._data[i][j];
}
}
return(out);
};
function transposeMatrix(a){
var out = new math.matrix();
out.resize([a._size[1], a._size[0]]);
for(var i = 0; i < a._data.length; i ++){
for(var j = 0; j < a._data[i].length; j ++){
out._data[j][i] = a._data[i][j];
}
}
return(out);
};
function setAll(a, b){
var out = new math.matrix();
out.resize(a._size);
function setit(c){
var outy;
if(b === "random"){
outy = math.random(0, 1);
}
if(b === "randomlow"){
outy = math.random(0, 0.05);
}
else if(b === "sigmoid"){
outy = sigmoid(c);
}
else if(b === "sigmoidDerivitive"){
outy = (sigmoidDerivitive(c));
}
else{
outy = c * b;
}
return(outy);
};
for(var i = 0; i < a._data.length; i ++){
if(a._size.length < 2){
out._data[i] = setit(a._data[i]);
}
else{
for(var j = 0; j < a._data[i].length; j ++){
out._data[i][j] = setit(a._data[i][j]);
}
}
}
return(out);
};
function NeuralNetwork(x, y){
this.input = x;
this.y = y;
this.sizes = [this.input._size[1], 300, this.y._size[1]];
this.layers = this.sizes.length - 1;
this.lyrs = [this.input];
this.weights = [];
this.dweights = [];
for(var i = 0; i < this.layers; i ++){
this.weights.push(new math.matrix());
this.weights[i].resize([this.sizes[i], this.sizes[i + 1]]);
this.weights[i] = setAll(this.weights[i], "randomlow");
}
this.output = new math.matrix();
this.output.resize(this.y._size);
};
NeuralNetwork.prototype.set = function(x, y){
this.input = x;
this.lyrs = [this.input];
this.y = y;
};
NeuralNetwork.prototype.feedforward = function(){
for(var i = 0; i < this.weights.length; i ++){
this.lyrs[i + 1] = math.multiply(this.lyrs[i], this.weights[i]);
this.lyrs[i + 1] = setAll(this.lyrs[i + 1], "sigmoid");
}
this.output = this.lyrs[this.lyrs.length - 1];
};
NeuralNetwork.prototype.backpropogate = function(){
this.antis = [
function(a, b, c){
return(
math.multiply(transposeMatrix(a[0]), multMatrices(math.multiply(multMatrices(math.multiply(math.subtract(b.y, b.output), 2), setAll(b.output, "sigmoidDerivitive")), transposeMatrix(c)), setAll(a[1], "sigmoidDerivitive")))
);
},
function(a, b, c){
return(
math.multiply(transposeMatrix(a[0]), multMatrices(math.multiply(math.subtract(b.y, b.output), 2), setAll(b.output, "sigmoidDerivitive")))
);
}];
this.input = [];
this.weightInput = 0;
for(var i = this.weights.length - 1; i >= 0; --i){
this.input.unshift(this.lyrs[i]);
this.weightInput = (i === this.weights.length - 1 ? 0 : this.weights[i + 1]);
this.dweights[i] = this.antis[i](this.input, this, this.weightInput);
}
for(var i = 0; i < this.dweights.length; i ++){
this.weights[i] = math.add(this.weights[i], this.dweights[i]);
}
};
var feed = new math.matrix([pixelValues[0]]);
var feed2 = new math.matrix([labelValues[0]]);
var t = new NeuralNetwork(feed, feed2);
t.feedforward();
var to = 270;
for(var i = 0; i < to + 1; i ++){
feed = new math.matrix([pixelValues[i]]);
feed2 = new math.matrix([labelValues[i]]);
t.set(feed, feed2);
t.feedforward();
t.backpropogate();
console.log("Loss: " + squareDiff(t.y, t.output) + " " + i);
if(i === to){
console.log(getMostLikely(t.output._data[0]));
console.log(t.output._data);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment