-
Notifications
You must be signed in to change notification settings - Fork 0
/
Neuralt.min.js
1 lines (1 loc) · 12.3 KB
/
Neuralt.min.js
1
var Neuralt={};Neuralt.Activations={Linear:0,Bent:1,ReLU:2,SmoothReLU:3,LeakyReLU:4,ELU:5,Sine:6,LongSine:7,Cosine:8,LongCosine:9,Sinc:10,Gaussian:11,Softsign:12,InverseTangent:13,HyperbolicTangent:14,Sigmoid:15,BipolarSigmoid:16},Neuralt.getActivated=function(a,b){return b===Neuralt.Activations.Linear?a:b===Neuralt.Activations.Bent?(Math.sqrt(a*a+1)-1)/2+a:b===Neuralt.Activations.ReLU?a*+(0<a):b===Neuralt.Activations.SmoothReLU?Math.log(Math.exp(a)+1):b===Neuralt.Activations.LeakyReLU?0>a?.01*a:a:b===Neuralt.Activations.ELU?0>a?Math.exp(a)-1:a:b===Neuralt.Activations.Sine?Math.sin(a):b===Neuralt.Activations.LongSine?2*Math.sin(a):b===Neuralt.Activations.Cosine?Math.cos(a):b===Neuralt.Activations.LongCosine?2*Math.cos(a):b===Neuralt.Activations.Sinc?0==a?1:Math.sin(a)/a:b===Neuralt.Activations.Gaussian?Math.exp(-a*a):b===Neuralt.Activations.Softsign?a/(Math.abs(a)+1):b===Neuralt.Activations.InverseTangent?Math.atan(a):b===Neuralt.Activations.HyperbolicTangent?Math.tanh(a):b===Neuralt.Activations.Sigmoid?1/(Math.exp(-a)+1):b===Neuralt.Activations.BipolarSigmoid?2/(Math.exp(-a)+1)-1:void 0},Neuralt.getActivationDerivative=function(a,b){switch(b){case Neuralt.Activations.Linear:return 1;case Neuralt.Activations.Bent:return a/(2*Math.sqrt(a*a+1))+1;case Neuralt.Activations.ReLU:return+(0<a);case Neuralt.Activations.SmoothReLU:return 1/(Math.exp(-a)+1);case Neuralt.Activations.LeakyReLU:return 0>a?.01:1;case Neuralt.Activations.ELU:return 0>a?Math.exp(a):1;case Neuralt.Activations.Sine:return Math.cos(a);case Neuralt.Activations.LongSine:return 2*Math.cos(a);case Neuralt.Activations.Cosine:return-Math.sin(a);case Neuralt.Activations.LongCosine:return 2*-Math.sin(a);case Neuralt.Activations.Sinc:return 0==a?0:Math.cos(a)/a-Math.sin(a)/(a*a);case Neuralt.Activations.Gaussian:return-2*(Math.exp(-a*a)*a);case Neuralt.Activations.Softsign:return 1/Math.pow(Math.abs(a)+1,2);case Neuralt.Activations.InverseTangent:return 1/(a*a+1);case Neuralt.Activations.HyperbolicTangent:return 1-Math.pow(Math.tanh(a),2);case Neuralt.Activations.Sigmoid:let c=Neuralt.getActivated(a,b);return c*(1-c);case Neuralt.Activations.BipolarSigmoid:return 2*Neuralt.getActivationDerivative(a,Neuralt.Activations.Sigmoid);}},Neuralt.GradientDescentOptimizations={Simple:0,Momentum:1,Adam:2},Neuralt.smallConstant=1e-10,Neuralt.Parameter=class{constructor(a,b){this.neuralNetwork=a,this.isBias=b,this.reset()}adjust(){switch(this.neuralNetwork.gradientDescentOptimization){case Neuralt.GradientDescentOptimizations.Simple:this.value-=Math.max(-1,Math.min(1,this.neuralNetwork.learningRate*this.lossSlope));break;case Neuralt.GradientDescentOptimizations.Momentum:this.velocity*=1-this.neuralNetwork.parameterDamping,this.velocity-=this.lossSlope*this.neuralNetwork.learningRate,this.value+=Math.max(-1,Math.min(1,this.velocity));break;case Neuralt.GradientDescentOptimizations.Adam:this.lossSlopeMean=.9*this.lossSlopeMean+.1*this.lossSlope,this.lossSlopeVariance=.999*this.lossSlopeVariance+.001*(this.lossSlope*this.lossSlope),this.value-=Math.max(-1,Math.min(1,10*(this.neuralNetwork.learningRate/Math.sqrt(1e3*this.lossSlopeVariance+Neuralt.smallConstant)*this.lossSlopeMean)));}}reset(){this.value=this.isBias?0:Math.random()-.5,this.lossSlope=0,this.velocity=0,this.lossSlopeMean=0,this.lossSlopeVariance=0}},Neuralt.Neuron=class{constructor(b,c,d){this.neuralNetwork=d,this.inputNeurons=b,this.parameters=[];for(let e=0;e<b.length;e++)this.parameters.push(new Neuralt.Parameter(this.neuralNetwork,!1));this.parameters.push(new Neuralt.Parameter(this.neuralNetwork,!0)),this.isOutputNeuron=c,this.lossSlope=0,this.output=0,this.output_beforeActivation=0}updateOutput(){let b=this.parameters[this.parameters.length-1].value;for(let c=0;c<this.inputNeurons.length;c++)b+=this.inputNeurons[c].output*this.parameters[c].value;this.output_beforeActivation=b,this.output=Neuralt.getActivated(b,this.isOutputNeuron?this.neuralNetwork.outputNeuronActivation:this.neuralNetwork.neuronActivation)}},Neuralt.InputNeuron=class{constructor(){this.output=0}},Neuralt.NeuralNetwork=class{constructor(b,c,d){this.neuronActivation=Neuralt.Activations.LeakyReLU,this.outputNeuronActivation=Neuralt.Activations.LeakyReLU,this.neurons=[[]],this.numberOfParameters=0;for(let e=0;e<b;e++)this.neurons[0].push(new Neuralt.InputNeuron);for(let e=0;e<c.length+1;e++){this.neurons.push([]);let a=e==c.length;for(let f=0;f<(a?d:c[e]);f++)this.neurons[this.neurons.length-1].push(new Neuralt.Neuron(this.neurons[this.neurons.length-2],a,this));this.numberOfParameters+=(this.neurons[e].length+1)*this.neurons[e+1].length}}forwardPropagate(b){if(b.length==this.neurons[0].length){for(let c=0;c<this.neurons[0].length;c++)this.neurons[0][c].output=b[c];for(let c=1;c<this.neurons.length;c++)for(let a=0;a<this.neurons[c].length;a++)this.neurons[c][a].updateOutput()}}getOutput(b){if(b.length==this.neurons[0].length){for(let c=0;c<this.neurons[0].length;c++)this.neurons[0][c].output=b[c];let c=[];for(let d=1;d<this.neurons.length;d++)for(let a=0;a<this.neurons[d].length;a++)this.neurons[d][a].updateOutput(),d==this.neurons.length-1&&c.push(this.neurons[d][a].output);return c}}setActivation(a){this.neuronActivation=a,this.outputNeuronActivation=a}resetLossSlopes(){for(let d=1;d<this.neurons.length;d++)for(let a=0;a<this.neurons[d].length;a++){this.neurons[d][a].lossSlope=0;for(let b=0;b<this.neurons[d][a].parameters.length;b++)this.neurons[d][a].parameters[b].lossSlope=0}}resetParameters(){for(let d=1;d<this.neurons.length;d++)for(let a=0;a<this.neurons[d].length;a++)for(let b=0;b<this.neurons[d][a].parameters.length;b++)this.neurons[d][a].parameters[b].reset()}},Neuralt.LearningNeuralNetwork=class extends Neuralt.NeuralNetwork{constructor(a,b,c){super(a,b,c),this.learningRate=.01,this.parameterDamping=.03,this.gradientDescentOptimization=Neuralt.GradientDescentOptimizations.Adam}},Neuralt.LearningExample=class{constructor(a,b){this.inputValues=a,this.desiredOutputValues=b,this.isInLearningBatch=!1}},Neuralt.SupervisedLearningNeuralNetwork=class extends Neuralt.LearningNeuralNetwork{constructor(a,b,c){super(a,b,c),this.maxLearningBatchSize=100,this.learningExamples=[]}addLearningExample(a,b,c=!1){c?!this.getExistsLearningExample(a)&&this.learningExamples.push(new Neuralt.LearningExample(a,b)):this.learningExamples.push(new Neuralt.LearningExample(a,b))}getExistsLearningExample(c){for(let d=0;d<this.learningExamples.length;d++)for(let a=0;a<this.learningExamples[d].inputValues.length&&!(this.learningExamples[d].inputValues[a]!=c[a]);a++)if(a==this.learningExamples[d].inputValues.length-1)return!0;return!1}getNewLearningBatch(){if(1==this.maxLearningBatchSize)return[this.learningExamples[Math.floor(Math.random()*this.learningExamples.length)]];let b=[];if(this.learningExamples.length>this.maxLearningBatchSize){let a;for(let c=0;c<this.maxLearningBatchSize;c++){do a=this.learningExamples[Math.floor(Math.random()*this.learningExamples.length)];while(a.isInLearningBatch);a.isInLearningBatch=!0,b.push(a)}for(let c=0;c<this.maxLearningBatchSize;c++)b[c].isInLearningBatch=!1}else b=this.learningExamples;return b}getError(b,c){let d=0;for(let e=0;e<b.length;e++)d+=.5*Math.pow(c[e]-b[e],2);return d}getLoss(b){b===void 0&&(b=this.getNewLearningBatch());let c=0;for(let d=0;d<b.length;d++)c+=this.getError(this.getOutput(b[d].inputValues),b[d].desiredOutputValues);return c/b.length}learn(a,b,c=!1){if(2<=arguments.length&&addLearningExample(a,b,c),0==this.learningExamples.length)return;let d=this.getNewLearningBatch();this.resetLossSlopes();let e,f;for(let g=0;g<d.length;g++){e=d[g],this.forwardPropagate(e.inputValues);for(let b=this.neurons.length-1;0<b;b--)for(let c=0;c<this.neurons[b].length;c++){if(f=this.neurons[b][c],b==this.neurons.length-1)f.lossSlope=f.output-e.desiredOutputValues[c];else{f.lossSlope=0;for(let d=0;d<this.neurons[b+1].length;d++)f.lossSlope+=this.neurons[b+1][d].parameters[c].value*this.neurons[b+1][d].lossSlope;f.lossSlope*=Neuralt.getActivationDerivative(f.output_beforeActivation,this.neuronActivation)}for(let a=0;a<f.parameters.length;a++)f.parameters[a].lossSlope+=a<f.parameters.length-1?this.neurons[b-1][a].output*f.lossSlope:f.lossSlope,g==d.length-1&&f.parameters[a].adjust()}}}},Neuralt.ReinforcementLearningNeuralNetwork=class extends Neuralt.LearningNeuralNetwork{constructor(a,b,c){super(a,b,c),this.maxLearningBatchSize=25,this.discountFactor=.99,this.memoryLength=1e5,this.minExploration=.01,this.maxExploration=1,this.explorationFactor=.995,this.experiencePrioritization=.4,this.minExperiencePrioritization=.1,this.averageFeedbackDecay=.999,this.targetNetworkUpdateFrequency=20,this.averageFeedback=void 0,this.updateCount=0,this.numberOfActions=c,this.explorationRate=this.maxExploration,this.experienceSinceFeedback=[],this.experience=[[0],[]],this.targetNetwork=new Neuralt.NeuralNetwork(a,b,c)}getNextAction(a){let b=0;if(Math.random()<this.explorationRate)b=Math.floor(Math.random()*this.numberOfActions);else{let c=this.getOutput(a);for(let d=1;d<c.length;d++)c[d]>c[b]&&(b=d)}return this.explorationRate=this.minExploration+(this.explorationRate-this.minExploration)*this.explorationFactor,this.explorationRate<this.minExploration&&(this.explorationRate=this.minExploration),this.experienceSinceFeedback.push({state_0:a,state_1:void 0,action:b,targetQ:void 0,priority:void 0,feedback:0}),b}getTargetQ(a){let b=this.getOutput(a.state_1),c=0;for(let d=0;d<b.length;d++)b[d]>b[c]&&(c=d);return a.feedback+this.discountFactor*this.targetNetwork.getOutput(a.state_1)[c]}giveFeedback(a){if(0==this.experienceSinceFeedback.length)return;this.targetNetwork.neuronActivation=this.neuronActivation,this.targetNetwork.ouputNeuronActivation=this.ouputNeuronActivation,this.averageFeedback=void 0===this.averageFeedback?a:this.averageFeedback*this.averageFeedbackDecay+a*(1-this.averageFeedbackDecay);let b=[];for(let c=0;c<Math.min(this.experience[this.experience.length-1].length,this.maxLearningBatchSize);c++){let a,c,d,e=Math.floor(Math.random()*this.experience[0][0]),f=[0,0];for(;a==null;)f=[f[0]+1,2*f[1]],c=this.experience[f[0]][f[1]],this.experience[f[0]].length>f[1]+1&&(d=this.experience[f[0]][f[1]+1]),"object"==typeof c?e<=c.priority?a=c:a=d:e>c&&(e-=c,f[1]++);a.targetQ=this.getTargetQ(a),b.push(a)}for(let c=this.experienceSinceFeedback.length-2;0<=c;c--)this.experienceSinceFeedback[c].state_1=this.experienceSinceFeedback[c+1].state_0,this.experienceSinceFeedback[c].targetQ=this.getTargetQ(this.experienceSinceFeedback[c]),b.push(this.experienceSinceFeedback[c]);this.experienceSinceFeedback.splice(0,this.experienceSinceFeedback.length-1),this.experienceSinceFeedback[0].feedback=a,this.resetLossSlopes();let c,d;for(let e=0;e<b.length;e++){c=b[e],this.forwardPropagate(c.state_0);for(let f=this.neurons.length-1;0<f;f--)for(let g=0;g<this.neurons[f].length;g++){if(d=this.neurons[f][g],f!=this.neurons.length-1){d.lossSlope=0;for(let b=0;b<this.neurons[f+1].length;b++)d.lossSlope+=this.neurons[f+1][b].parameters[g].value*this.neurons[f+1][b].lossSlope;d.lossSlope*=Neuralt.getActivationDerivative(d.output_beforeActivation,this.neuronActivation)}else if(g!=c.action)d.lossSlope=0;else if(d.lossSlope=d.output-c.targetQ,null==c.index){c.priority=Math.max(this.minExperiencePrioritization,Math.pow(Math.abs(d.lossSlope),this.experiencePrioritization)),c.index=this.experience[this.experience.length-1].length,this.experience[this.experience.length-1].push(c);for(let b=this.experience.length-1;0<b;b--)this.experience[b].length>2*this.experience[b-1].length?this.experience[b-1].push(c.priority):this.experience[b-1][this.experience[b-1].length-1]+=c.priority;2==this.experience[0].length&&this.experience.unshift([this.experience[0][0]+this.experience[0][1]])}else{let b=Math.max(this.minExperiencePrioritization,Math.pow(Math.abs(d.lossSlope),this.experiencePrioritization))-c.priority;c.priority+=b;let e=c.index;for(let c=this.experience.length-2;0<=c;c--)e=Math.floor(.5*e),this.experience[c][e]+=b}for(let a=0;a<d.parameters.length;a++)d.parameters[a].lossSlope+=a<d.parameters.length-1?this.neurons[f-1][a].output*d.lossSlope:d.lossSlope,e==b.length-1&&(d.parameters[a].adjust(),0==this.updateCount%this.targetNetworkUpdateFrequency&&(this.targetNetwork.neurons[f][g].parameters[a].value=d.parameters[a].value))}}if(this.experience[this.experience.length-1].length==this.memoryLength<<1){for(let b=1;b<this.experience.length;b++)this.experience[b].splice(0,1<<b-1);for(let b=0;b<this.experience[this.experience.length-1].length;b++)this.experience[this.experience.length-1][b].index=b;this.experience.splice(0,1)}this.updateCount++}};