var showMatrix=!1;
// basic idea is to activate the functions like relu,leaky_relu etc
class ActivationFunction
{
constructor(t,e,i=!1)
{
this.func=t;
this.dfunc=e;
this.use_X_values=i;
}
}
//building the activation functions
let sigmoid=new ActivationFunction(t=>1/(1+Math.exp(-t)),t=>t*(1-t));
let tanh=new ActivationFunction(t=>Math.tanh(t),t=>1-t*t);
let arctan=new ActivationFunction(t=>Math.atan(t),t=>1/(t*t+1),use_X_values=!0);
let softsign=new ActivationFunction(t=>t/(1+Math.abs(t)),t=>1/Math.pow(Math.abs(t)+1,2),use_X_values=!0);
let relu=new ActivationFunction(t=>t<0?0:t,t=>t<0?0:1,use_X_values=!0);
let leaky_relu=new ActivationFunction(t=>t<0?0.01*t:t,t=>t<0?0.01:1,use_X_values=!0);
let softplus=new ActivationFunction(t=>Math.log(1+Math.exp(t)),t=>1/(1+Math.exp(-t)),use_X_values=!0);
let gaussian=new ActivationFunction(t=>Math.exp(t*t*-1),t=>-2*t*Math.exp(t*t*-1),use_X_values=!0);
var Softmax = function(ar) { ar.map( x => Math.exp(x) / (ar.map( y => Math.exp(y))).reduce( (a,b) => a+b)) };
//Machine Learning Model that will recognize the characters
class NeuralNet
{
constructor(t,e,i)
{
if(t instanceof NeuralNet)
{
let e=t;
this.input_nodes=e.input_nodes;
this.hidden_nodes=e.hidden_nodes;
this.output_nodes=e.output_nodes;
this.weights_ih=e.weights_ih.copy();
this.weights_ho=e.weights_ho.copy();
this.bias_h=e.bias_h.copy();
this.bias_o=e.bias_o.copy();
}
else
this.input_nodes=t;
this.hidden_nodes=e;
this.output_nodes=i;
this.weights_ih=new Matrix(this.hidden_nodes,this.input_nodes);
this.weights_ho=new Matrix(this.output_nodes,this.hidden_nodes);
this.weights_ih.randomize();
this.weights_ho.randomize();
this.bias_h=new Matrix(this.hidden_nodes,5);
this.bias_o=new Matrix(this.output_nodes,5);
this.bias_h.randomize();
this.bias_o.randomize();
this.setLearningRate(0.1);
this.setActivationFunction();
}
//predition process
predict(t)
{
let e=Matrix.fromArray(t),i=Matrix.multiply(this.weights_ih,e);
i.add(this.bias_h),i.map(this.activation_function.func);
let s=Matrix.multiply(this.weights_ho,i);
return s.add(this.bias_o),s.map(this.activation_function.func),s.toArray();
}
//setting the learning rate
setLearningRate(t)
{
this.learning_rate=t;
}
setActivationFunction(t=tanh)
{
this.activation_function=t;
}
train(t,e)
{
let i=Matrix.fromArray(t), s=Matrix.multiply(this.weights_ih,i);
s.add(this.bias_h) , s.map(this.activation_function.func);
let o=Matrix.multiply(this.weights_ho,s);
o.add(this.bias_o) , o.map(this.activation_function.func);
let a=Matrix.fromArray(e), n=Matrix.subtract(a,o),
r=Matrix.map(o,this.activation_function.dfunc);
r.multiply(n), r.multiply(this.learning_rate);
let l=Matrix.transpose(s), h=Matrix.multiply(r,l);
this.weights_ho.add(h) , this.bias_o.add(r);
let d=Matrix.transpose(this.weights_ho), c=Matrix.multiply(d,n), u=Matrix.map(s,this.activation_function.dfunc);
u.multiply(c) , u.multiply(this.learning_rate);
let g=Matrix.transpose(i), m=Matrix.multiply(u,g);
this.weights_ih.add(m),
this.bias_h.add(u);
}
serialize()
{
return JSON.stringify(this);
}
static deserialize(t)
{
"string"==typeof t&&(t=JSON.parse(t));
let e=new NeuralNet(t.input_nodes,t.hidden_nodes,t.output_nodes);
return e.weights_ih=Matrix.deserialize(t.weights_ih),
e.weights_ho=Matrix.deserialize(t.weights_ho),
e.bias_h=Matrix.deserialize(t.bias_h),
e.bias_o=Matrix.deserialize(t.bias_o),
e.learning_rate=t.learning_rate,
e;
}
copy()
{
return new NeuralNet(this);
}
mutate(t)
{
this.weights_ih.map(t),
this.weights_ho.map(t),
this.bias_h.map(t),
this.bias_o.map(t);
}
}
//Multilayer Neural Network
class NeuralNetMulti
{
constructor(t,e)
{
this.nodes=t,
this.lr=e||0.01,
this.activation=NeuralNetMulti.rhlu,
this.dactivation=NeuralNetMulti.drhlu,
this.weights=[],
this.biases=[];
for(let t=0;t<this.nodes.length-1;t++)
this.weights.push(new Matrix(this.nodes[t+1],this.nodes[t]).randomize());
for(let t=1;t<this.nodes.length;t++)
this.biases.push(new Matrix(this.nodes[t],1).randomize());
}
static dtanh(t)
{
return 1/pow(Math.cosh(t),2);
}
static sigmoid(t)
{
return 1/(1+Math.exp(-t));
}
static dsigmoid(t)
{
return t*(1-t);
}
static rhlu(t)
{
return t<0?0:t;
}
static drhlu(t)
{
return t<0?0:1;
}
predict(t)
{
let e=Matrix.fromArray(t);
for(let t=0;t<this.weights.length;t++)
(e=Matrix.multiply(this.weights[t],e)).add(this.biases[t]),
e.map(this.activation);
return e.toArray();
}
train(t,e)
{
let i=Matrix.fromArray(e),
s=Matrix.fromArray(this.predict(t)),
o=[],
a=Matrix.fromArray(t);
for(let t=0;t<this.weights.length;t++)
o.push(a),
(a=Matrix.multiply(this.weights[t],a)).add(this.biases[t]),
a.map(this.activation);
let n=Matrix.subtract(i,s),
r=Matrix.map(s,this.dactivation);
r.multiply(n),
r.multiply(this.lr);
for(let t=o.length-1;t>=0;t--)
{
let e=Matrix.multiply(r,Matrix.transpose(o[t]));
this.weights[t].add(e),
this.biases[t].add(r),
n=Matrix.multiply(Matrix.transpose(this.weights[t]),n),
(r=Matrix.map(o[t],this.dactivation)).multiply(n),
r.multiply(this.lr);
}
}
getModel()
{
let t=this,
e={nodes:t.nodes,lr:t.lr,activation:t.activation,dactivation:t.dactivation,weights:[],biases:[]};
for(let i of t.weights)
{
let t={rows:i.rows,cols:i.cols,data:[]};
for(let e of i.data)
{
let i=[];
for(let t of e)i.push(t);
t.data.push(i);
}
e.weights.push(t);
}
for(let i of t.biases)
{
let t={rows:i.rows,cols:i.cols,data:i.data};
e.biases.push(t);
}
return e;
}
static formModel(t)
{
let e=new NeuralNetMulti(t.nodes,t.lr);
e.nodes=t.nodes,
e.lr=t.lr,
e.activation=t.activation,
e.dactivation=t.dactivation;
for(let i=0;i<e.weights.length;i++)
{
e.weights[i].rows=t.weights[i].rows,
e.weights[i].cols=t.weights[i].cols;
for(let s=0;s<t.weights[i].rows;s++)
for(let o=0;o<t.weights[i].cols;o++)
e.weights[i].data[s][o]=t.weights[i].data[s][o];
e.weights[i].rows=t.weights[i].rows;
}
return e;
}
copy()
{
let t=this.getModel();
return NeuralNetMulti.formModel(t);
}
mutate(t)
{
for(let e of this.weights)e.map(t);
for(let e of this.biases)e.map(t);
}
merge(t,e=0.5)
{
let i=1-e,s=e;
for(let e=0;e<this.nodes.length;e++)
if(this.nodes[e]!=t.nodes[e])
return void console.error("Neural Networks can not be merged");
this.lr=this.lr*i+t.lr*s;
for(let e=0;e<this.weights.length;e++)
for(let o=0;o<this.weights[e].rows;o++)
for(let a=0;a<this.weights[e].cols;a++)
this.weights[e].data[o][a]=this.weights[e].data[o][a]*i+t.weights[e].data[o][a]*s;
for(let e=0;e<this.biases.length;e++)
for(let o=0;o<this.biases[e].rows;o++)
for(let a=0;a<this.biases[e].cols;a++)
this.biases[e].data[o][a]=this.biases[e].data[o][a]*i+t.biases[e].data[o][a]*s;
return this;
}
setActivation(t,e)
{
this.activation=t,
this.dactivation=e;
}
setLearningRate(t)
{
this.lr=t;
}
}
const optFunction = async ({ optimizer, epochs }, { xs, ys }) => {
// Create a simple sequential model.
const model = tf.sequential();
// add a dense layer to the model and compile
model.add(tf.layers.dense({ units: 1, inputShape: [1] }));
model.compile({
loss: 'meanSquaredError',
optimizer,
});
// train model using defined data
const h = await model.fit(xs, ys, {epochs});
//printint out each optimizer and its loss
console.log(optimizer, h.history.loss[h.history.loss.length - 1]);
return { loss: h.history.loss[h.history.loss.length - 1], status: hpjs.STATUS_OK } ;
};
async function hyperTFJS(){
// Generating some data for training (y = 2x - 1) in tf tensors and defining its shape
const xs = tf.tensor2d([-1, 0, 1, 2, 3, 4], [6, 1]);
const ys = tf.tensor2d([-3, -1, 1, 3, 5, 7], [6, 1]);
// defining a search space we want to optimize. Using hpjs parameters here
const space = {
optimizer: hpjs.choice(['sgd', 'adagrad', 'adam', 'adamax', 'rmsprop']),
epochs: hpjs.quniform(50, 200, 50),
};
// finding the optimal hyperparameters using hpjs.fmin. Here, 6 is the # of times the optimization function will be called (which can be changed)
const trials = await hpjs.fmin(
optFunction, space, hpjs.search.randomSearch, 6,
{ rng: new hpjs.RandomState(654321), xs, ys }
);
const opt = trials.argmin;
//printing out data
console.log('trials', trials);
console.log('best optimizer:', opt.optimizer);
console.log('best epochs:', opt.epochs);
}
const PIXELS=28,PIXELSSQUARED=PIXELS*PIXELS,NOTRAIN=6e4,NOTEST=1e4,noinput=PIXELSSQUARED,nohidden=24,nooutput=10,learningrate=0.1;
let do_training=!0;
const TRAINPERSTEP=30,TESTPERSTEP=5,ZOOMFACTOR=7,ZOOMPIXELS=ZOOMFACTOR*PIXELS,canvaswidth=2*ZOOMPIXELS+120,canvasheight=3*ZOOMPIXELS+102,doodlewidth=PIXELS,DOODLE_THICK=15,DOODLE_BLUR=3;
let mnist,nn,canvas,dst,src,hierarchy,contours,img,diffX,diffY,M,doodle,demo,hidden_no_slider,learning_rate_slider,cvOutput=[],trainrun=1,train_index=0,testrun=1,test_index=0,total_tests=0,total_correct=0,doodle_exists=!1,demo_exists=!1,mousedrag=!1;
var train_inputs,test_inputs,demo_inputs,doodle_inputs,thehtml;
function randomWeight()
{
return AB.randomFloatAtoB(-0.5,0.5);
}
$("#runheaderbox").css({"max-height":"95vh"}),thehtml="<hr> <h1> 1. Doodle </h1> Top row: Doodle (left) and shrunk (right). <br> Draw your doodle in top LHS. <button onclick='wipeDoodle();' class='normbutton' >Clear doodle</button> <br> ",AB.msg(thehtml,1),thehtml="<hr> <h1> 2. Training </h1> Middle row: Training image magnified (left) and original (right). <br> <button onclick='do_training = false;' class='normbutton' >Stop training</button> <br> ",AB.msg(thehtml,3),thehtml="<h3> Hidden tests </h3> ",AB.msg(thehtml,5),thehtml="<hr> <h1> 3. Demo </h1> Bottom row: Test image magnified (left) and original (right). <br> The network is <i>not</i> trained on any of these images. <br> <button onclick='makeDemo();' class='normbutton' >Demo test image</button> <br> ",AB.msg(thehtml,7);const greenspan="<span style='font-weight:bold; font-size:x-large; color:darkgreen'> ";
function setup()
{
(canvas=createCanvas(canvaswidth,canvasheight)).position(10,20),
canvas.background(0,51,0),
(doodle=createGraphics(ZOOMPIXELS,ZOOMPIXELS)).pixelDensity(2),
wipeDoodle(),
strokeWeight(3),
stroke(255,0,0),
rect(0,0,ZOOMPIXELS,ZOOMPIXELS),
textSize(13),
textAlign(CENTER),
text("DOODLE AREA",ZOOMPIXELS/2,ZOOMPIXELS/2.2),
rect(0,ZOOMPIXELS+50,ZOOMPIXELS,ZOOMPIXELS),
rect(0,canvasheight-ZOOMPIXELS-2,ZOOMPIXELS,ZOOMPIXELS),
textSize(13),
textAlign(CENTER),
text(" DEMO AREA ",100,canvasheight-ZOOMPIXELS/1.8),
AB.loadingScreen(),
$.getScript("/uploads/finally/opencv.js",function(){$.getScript("/uploads/codingtrain/matrix.js",function(){$.getScript("/uploads/finally/nn.js",function(){$.getScript("/uploads/codingtrain/mnist.js",function(){console.log("All JS loaded"),(nn=new NeuralNet(noinput,nohidden,nooutput)).setLearningRate(learningrate),loadData()})})})})}
function loadData()
{
loadMNIST(function(t)
{
mnist=t,console.log("All data loaded into mnist object:"),
console.log(mnist),
AB.removeLoading();
}
);
}
function getImage(t)
{
let e=createImage(PIXELS,PIXELS);
e.loadPixels();
for(let i=0;i<PIXELSSQUARED;i++)
{
let s=t[i],o=4*i;
e.pixels[o+0]=s,
e.pixels[o+1]=s,
e.pixels[o+2]=s,
e.pixels[o+3]=255;
}
return e.updatePixels(),
e;
}
function getInputs(t)
{
let e=[];
for(let i=0;i<PIXELSSQUARED;i++)
{
let s=t[i];
e[i]=s/255;
}
return e;
}
function trainit(t)
{
let e=mnist.train_images[train_index],
i=mnist.train_labels[train_index];
if(t)
{
var s=getImage(e);
image(s,0,ZOOMPIXELS+50,ZOOMPIXELS,ZOOMPIXELS),
image(s,ZOOMPIXELS+50,ZOOMPIXELS+50,PIXELS,PIXELS);
}
let o=getInputs(e),a=[0,0,0,0,0,0,0,0,0,0];
a[i]=1,
train_inputs=o,
nn.train(o,a),
thehtml=" trainrun: "+trainrun+"<br> no: "+train_index,
AB.msg(thehtml,4),
++train_index==NOTRAIN&&(train_index=0,console.log("finished trainrun: "+trainrun),trainrun++);
}
function testit()
{
let t=mnist.test_images[test_index],
e=mnist.test_labels[test_index],
i=getInputs(t);test_inputs=i;
let s=findMax(nn.predict(i));
total_tests++,
s==e&&total_correct++;
let o=total_correct/total_tests*100;
thehtml=" testrun: "+testrun+"<br> no: "+total_tests+" <br> correct: "+total_correct+"<br> score: "+greenspan+o.toFixed(2)+"</span>",
AB.msg(thehtml,6),
++test_index==NOTEST&&(console.log("finished testrun: "+testrun+" score: "+o.toFixed(2)),testrun++,test_index=0,total_tests=0,total_correct=0);
}
function find123(t)
{
let e=0,i=0,s=0,o=0,a=0,n=0;
for(let r=0;r<t.length;r++)
t[r]>s?(e=r,s=t[r]):t[r]>o?(i=r,o=t[r]):t[r]>n&&(a=r,n=t[r]);
return[e,i,a];
}
function findMax(t)
{
let e=0,i=0;
for(let s=0;s<t.length;s++)
t[s]>i&&(e=s,i=t[s]);
return e;
}
function draw()
{
if(void 0!==mnist)
{
if(strokeWeight(3),stroke(255,0,0),rect(0,0,ZOOMPIXELS,ZOOMPIXELS),textSize(20),textAlign(CENTER),text("DOODLE AREA",ZOOMPIXELS/2,ZOOMPIXELS/2.2),do_training)
{
for(let t=0;t<TRAINPERSTEP;t++)
trainit(0===t);
for(let t=0;t<TESTPERSTEP;t++)
testit();
}
if(demo_exists&&(drawDemo(),guessDemo()),doodle_exists&&(drawDoodle(),guessDoodle()),mouseIsPressed)
{
var t=ZOOMPIXELS-2;
mouseX<t&&mouseY<t&&pmouseX<t&&pmouseY<t&&(mousedrag=!0,doodle_exists=!0,doodle.stroke("cream"),strokeJoin(BEVEL),doodle.strokeWeight(DOODLE_THICK),doodle.line(mouseX,mouseY,pmouseX,pmouseY));
}
else if(mousedrag)
{
mousedrag=!1,
console.log("Doodle detected"),
(img=doodle.get()).resize(PIXELS,PIXELS),
img.loadPixels(),
imagedata=img.imageData,
src=cv.matFromImageData(imagedata),
dst=cv.Mat.zeros(src.cols,src.rows,cv.CV_8UC3),
cv.cvtColor(src,src,cv.COLOR_RGBA2GRAY,0),
cv.threshold(src,src,120,255,cv.THRESH_BINARY),
contours=new cv.MatVector(),
hierarchy=new cv.Mat(),cv.findContours(src,contours,hierarchy,cv.RETR_CCOMP,cv.CHAIN_APPROX_SIMPLE);
let t=contours.get(0),
e=cv.moments(t,0);
M=e.m00;
let i=Math.round(e.m10/e.m00*100)/100,s=Math.round(e.m01/e.m00*100)/100,o=PIXELS/2,a=PIXELS/2;
diffX=Math.round(o-i),
diffY=Math.round(a-s);
let n=cv.matFromArray(2,3,cv.CV_64FC1,[1,0,diffX,0,1,diffY]);
return dsize=new cv.Size(src.rows,src.cols),
cv.warpAffine(src,dst,n,dsize,cv.INTER_LINEAR,cv.BORDER_CONSTANT,new cv.Scalar()),
cvOutput=getInputs(dst.data8S),
image(img,ZOOMPIXELS+120+diffX*ZOOMFACTOR,0+diffY*ZOOMFACTOR,ZOOMPIXELS,ZOOMPIXELS),
cvOutput;
}
}
}
function makeDemo()
{
demo_exists=!0;
var t=AB.randomIntAtoB(0,NOTEST-1);
demo=mnist.test_images[t];
var e=mnist.test_labels[t];
thehtml="Test image no: "+t+"<br>Classification: "+e+"<br>",AB.msg(thehtml,8);
}
function drawDemo()
{
var t=getImage(demo);
image(t,0,canvasheight-ZOOMPIXELS,ZOOMPIXELS,ZOOMPIXELS),
image(t,ZOOMPIXELS+50,canvasheight-ZOOMPIXELS,PIXELS,PIXELS);
}
function guessDemo()
{
let t=getInputs(demo);
demo_inputs=t;
let e=findMax(nn.predict(t));
thehtml=" We classify it as: "+greenspan+e+"</span>",AB.msg(thehtml,9);
}
function drawDoodle()
{
let t=doodle.get();
image(t,0,0,ZOOMPIXELS,ZOOMPIXELS),image(t,ZOOMPIXELS+50,0,PIXELS,PIXELS);
}
let lastT=0;
function guessDoodle()
{
(img=doodle.get()).resize(PIXELS,PIXELS),
img.loadPixels();
let t=[];
for(let e=0;e<PIXELSSQUARED;e++)
t[e]=img.pixels[4*e]/255;
let e=Array.from(t);
for(let t=0;t<e.length;t++)
e[t]=cvOutput[t];
t=Array.from(e);
for(let e=0;e<t.length;e++)
t[e]=-255*t[e];
doodle_inputs=t;
let i=find123(nn.predict(t));
thehtml=" We classify it as: "+greenspan+i[0]+"</span> <br> No.2 guess is: "+greenspan+i[1]+"</span> <br>No.3 guess is: "+greenspan+i[2]+"</span>",AB.msg(thehtml,2),AB.msg(thehtml,2);
}
function wipeDoodle()
{
doodle_exists=!1,doodle.background("black");
}
function showInputs(t)
{
var e="";
for(let i=0;i<t.length;i++)
{
i%PIXELS===0&&(e+="\n"),
e=e+" "+t[i].toFixed(2);
}
console.log(e);
}