UNPKG

ml-basic

Version:

Lightweight, zero dependency, machine learning library

3 lines (2 loc) 22.8 kB
import{readFile as t,writeFile as e}from"fs";const s=()=>"undefined"!=typeof self&&void 0!==self.location;function i(t,e){return e||(e=t,t=0),new Array(e-t).fill(0).map(((e,s)=>t+s))}function r(t){for(let e=t.length-1;e>0;e--){const s=Math.floor(Math.random()*(e+1));[t[e],t[s]]=[t[s],t[e]]}return t}function a(t,e,s,i,r){return[Math.floor((t+2*r-s)/i+1),Math.floor((e+2*r-s)/i+1)]}async function n(e){const i="string"!=typeof e;return new Promise(((r,a)=>{if(i){const t=new FileReader;t.onload=()=>r(t.result),t.onerror=a,t.readAsText(e,"utf-8")}if(s()||i||t(e,"utf-8",((t,e)=>{t&&a(t),r(e)})),s()&&!i)throw new Error("Unable to access file system from the browser")}))}function o(t,i){if(/\.json$/i.test(t)||(t+=".json"),s()){t=t.replace(/.*\//,"");const e=new Blob([i],{type:"application/json"}),s=document.createElement("a");s.href=URL.createObjectURL(e),s.download=t,s.click(),URL.revokeObjectURL(s.href)}else e(t,i,(t=>{if(t)throw t}))}class h{constructor(t,e,s=[]){if(t instanceof h)return this.rows=t.rows,this.columns=t.columns,void(this.entries=new Float64Array(t.entries.slice()));this.rows=t,this.columns=e||t,this.entries=new Float64Array(t*(e||t));for(let t=0;t<this.entries.length;t++)this.entries[t]=s[t]||0}isEqualShape(t){return this.rows===t.rows&&this.columns===t.columns}reshape(t,e){if(t*e!==this.entries.length)throw new Error("New shape size must be equal to previous size");return this.rows=t,this.columns=e,this}flat(){return this.reshape(this.entries.length,1)}flip(){return this.entries.reverse(),this}set(t){return this.entries.fill(t),this}add(t){if(t instanceof h&&!this.isEqualShape(t))throw new Error("Additive matrix must have an equal shape");for(let e=0;e<this.entries.length;e++)this.entries[e]+=t instanceof h?t.entries[e]:t;return this}sub(t){if(t instanceof h&&!this.isEqualShape(t))throw new Error("Subtractive matrix must have an equal shape");for(let e=0;e<this.entries.length;e++)this.entries[e]-=t instanceof h?t.entries[e]:t;return this}scale(t){if(t instanceof h&&!this.isEqualShape(t))throw new Error("Scaling matrix must have an equal shape");for(let e=0;e<this.entries.length;e++)this.entries[e]*=t instanceof h?t.entries[e]:t;return this}apply(t){for(let e=0;e<this.entries.length;e++)this.entries[e]=t(this.entries[e]);return this}sum(){return this.entries.reduce(((t,e)=>t+e),0)}static mult(t,e){if(t.columns!==e.rows)throw new Error("Matrix A's columns must be equal to Matrix B's rows");const s=new h(t.rows,e.columns);for(let i=0;i<t.rows;i++)for(let r=0;r<e.columns;r++){let a=0;for(let s=0;s<t.columns;s++)a+=t.entries[i*t.columns+s]*e.entries[s*e.columns+r];s.entries[i*e.columns+r]=a}return s}mult(t){return t=h.mult(this,t),this.entries=t.entries,this.columns=t.columns,this}static transpose(t){const e=new h(t.columns,t.rows);for(let s=0;s<t.rows;s++)for(let i=0;i<t.columns;i++)e.entries[i*t.rows+s]=t.entries[s*t.columns+i];return e}transpose(){const t=h.transpose(this);return this.entries=t.entries,this.rows=t.rows,this.columns=t.columns,this}accumulate(t,e,s=0){for(let i=0;i<this.rows;i++)for(let r=0;r<this.columns;r++){let a=s;for(let s=0;s<t[0];s++)for(let n=0;n<t[1];n++)a=e(a,i,r,s,n);this.entries[i*this.columns+r]=a}return this}static correlate(t,e,s=1,i=0){if(t.rows+i<e.rows||t.columns+i<e.columns)throw new Error("Kernel size exceeds Matrix shape size");const[r,n]=a(t.rows,t.columns,e.rows,s,i);return new h(r,n).accumulate([e.rows,e.columns],((r,a,n,o,h)=>r+(t.entries[(a-i*s+o)*t.columns+(n-i*s+h)]||0)*e.entries[o*e.columns+h]))}correlate(t,e=1,s=0){const i=h.correlate(this,t,e,s);return this.entries=i.entries,this.rows=i.rows,this.columns=i.columns,this}static reverseCorrelate(t,e,s=1){return new h(Math.floor(t.rows-(e.rows-1)*s),Math.floor(t.columns-(e.columns-1)*s)).accumulate([e.rows,e.columns],((i,r,a,n,o)=>i+(t.entries[(r+n*s)*t.columns+(a+o*s)]||0)*e.entries[n*e.columns+o]))}static pool({matrix:t,window:e,stride:s=1,zeroPadding:i=0,initial:r=0,pooler:n}){if(t.rows+i<e[0]||t.columns+i<e[1])throw new Error("Window size exceeds Matrix shape size");const[o,c]=a(t.rows,t.columns,e[0],s,i);return new h(o,c).accumulate(e,((e,r,a,o,h)=>{const c=t.entries[(r-i*s+o)*t.columns+(a-i*s+h)];return n(e,c||0)}),r)}clip(t,e){for(let s=0;s<this.entries.length;s++)this.entries[s]=Math.min(Math.max(this.entries[s],t),e);return this}dialate(t){const e=this.columns,s=this.entries;this.rows+=(this.rows-1)*t,this.columns+=(this.columns-1)*t,this.entries=new Float64Array(this.rows*this.columns),t+=1;for(let i=0;i<this.rows;i++)for(let r=0;r<this.columns;r++)this.entries[i*this.columns+r]=i%t==0&&r%t==0?s[Math.floor(i/t)*e+Math.floor(r/t)]:0;return this}static identity(t){const e=new h(t,t);for(let s=0;s<t;s++)e.entries[s*t+s]=1;return e}static random(t,e,s=0,i=1){const r=new h(t,e);for(let t=0;t<r.entries.length;t++)r.entries[t]=Math.random()*(i-s)+s;return r}serialize(){return{type:"Matrix",rows:this.rows,columns:this.columns,entries:Array.from(this.entries)}}}class c{serialize(){return this.name}}class l extends c{constructor(){super(...arguments),this.name="SquaredLoss"}mean(t,e){return new h(e).sub(t).apply((t=>t*t)).sum()/e.entries.length}derivative(t,e){return new h(e).sub(t).apply((t=>-2*t/e.entries.length))}}class u extends c{constructor(){super(...arguments),this.name="CrossEntropyLoss"}mean(t,e){return-new h(t).apply(Math.log).scale(e).sum()}derivative(t,e){return new h(t).sub(e)}}class p{serialize(){return this.name}}class m extends p{constructor(){super(...arguments),this.name="Sigmoid"}activate(t){return 1/(1+Math.exp(-t))}deactivate(t){return t*(1-t)}}class d extends p{constructor(){super(...arguments),this.name="TanH"}activate(t){return Math.tanh(t)}deactivate(t){return 1-t*t}}class g extends p{constructor(t=1){super(),this.name="Elu",this.activate=t=>t>0?t:this.alpha*(Math.exp(t)-1),this.deactivate=t=>t<0?this.alpha*Math.exp(t):1,this.alpha=t}}class w extends g{constructor(t=.01){super(t),this.name="Relu",this.activate=t=>t<0?this.alpha*t:t,this.deactivate=t=>t<0?this.alpha:1}}class f extends p{constructor(){super(...arguments),this.name="SoftPlus"}activate(t){return Math.log(1+Math.exp(t))}deactivate(t){return 1/(1+Math.exp(-t))}}var y=Object.freeze({__proto__:null,Activator:p,CrossEntropyLoss:u,Elu:g,LossFunction:c,Relu:w,Sigmoid:m,SoftPlus:f,SquaredLoss:l,TanH:d});class b{constructor(){this.type="Optimizer"}clone(){return Object.assign(Object.create(Object.getPrototypeOf(this)),this)}configure(t){Object.assign(this,t)}}class v extends b{constructor({learningRate:t=.01,clipping:e=0}={}){super(),this.name="sgd",this.learningRate=t,this.clipping=e}step(t,e,s){e.scale(this.learningRate),this.clipping&&e.clip(-this.clipping,this.clipping),s(t,e)}}class x{constructor(t,e,s){this.type="Layer",this.optimizer=new v,this.input=t,this.output=e,this.activation=s}}class z extends x{constructor({input:t,rate:e=.25}){Array.isArray(t)||(t=[t,1]),super(t,t,new m),this.name="drop",this.rate=e}propagate(t){return new h(t.rows,t.columns,new Array(this.input[0]*this.input[1]).fill(0).map(((e,s)=>Math.random()<this.rate?0:t.entries[s])))}backPropagate(t,e,s){return s}}class M{constructor(t,e,s){this.type="Network",this.lossFunction=s,this.layers=new Array(t.length);for(let s=0;s<t.length;s++){const i=s>0?this.layers[s-1].output:void 0,{Layer:r,args:a}=t[s];if(!i&&!("input"in a))throw new Error(`Layer ${s+1} has no input size defined`);this.layers[s]=new r(Object.assign({input:i},a)),this.layers[s].optimizer=e.clone();const n=this.layers[s].input;if(i&&i[0]*i[1]!=n[0]*n[1])throw new Error(`Layer ${s+1}'s input does match layer ${s}'s output`)}}propagate(t,e=!0){let s=[t];for(let t=0;t<this.layers.length;t++)this.layers[t]instanceof z&&e?s.push(new h(s[t])):s.push(this.layers[t].propagate(s[t]));return s}backPropagate(t,e){const s=this.propagate(t,!1),i=s[s.length-1],r=this.lossFunction.mean(i,e);let a=this.lossFunction.derivative(i,e);for(let t=this.layers.length-1;t>=0;t--)a=this.layers[t].backPropagate(s[t],s[t+1],a);return r}configure(t){this.layers.forEach((e=>e.optimizer.configure(t)))}}class k extends v{constructor({learningRate:t=.01,clipping:e=0,batchSize:s=8}={}){if(s<1)throw new Error("Batch size cannot be less than 1");super({learningRate:t,clipping:e}),this.name="bgd",this.i=0,this.batchSize=s}step(t,e,s){this.batch?(this.batch.input.add(t),this.batch.gradient.add(e)):this.batch={input:new h(t),gradient:new h(e)},this.i++,this.i%this.batchSize==0&&this.batch&&(super.step(this.batch.input.scale(1/this.batchSize),this.batch.gradient.scale(1/this.batchSize),s),this.batch=void 0)}}class A{export(){return JSON.stringify(this,((t,e)=>"object"==typeof e&&"serialize"in e&&e.serialize instanceof Function?e.serialize():e))}save(t){o(t,this.export())}}class L extends A{constructor({layers:t,optimizer:e=new k,lossFunction:s=new l}){super(),this.name="Neural",this.epochs=0,this.error=1,this.network=new M(t,e,s),this.optimizer=e}propagate(t){const e=this.network.propagate(t);return e[e.length-1]}backPropagate(t,e){return this.network.backPropagate(t,e)}predict({input:t,ranking:e=!1,labels:s}){t instanceof h||(t=new h(t.length,1,t));const i=this.propagate(t),r=Array.from(i.entries);if(!s)return r;if(r.length!==s.length)throw new Error("Label count is not equal to output size");const a=r.map(((t,e)=>({certainty:t,label:s[e]}))).sort(((t,e)=>e.certainty-t.certainty));return e?a:a[0]}fit({data:t,epochs:e,errorThreshold:s=0,hyperParameters:a={},logProgress:n=!1,onEpoch:o}){const h="batchSize"in this.optimizer?this.optimizer.batchSize:1;e=Math.ceil(e/h)*h,this.network.configure(a),n&&process.stdout.write(`\nFitting model (${t.data.length} samples / ${e} epochs):\n`);const c=performance.now();for(let a=0;a<e;a++){const h=r(i(t.data.length));this.error=0;for(let s=0;s<h.length;s++){const{input:i,target:r}=t.data[h[s]],o=this.backPropagate(i,r);if(this.error+=o/h.length,n){const t=(a*h.length+s+1)/(e*h.length)*100,i={0:"-",1:"\\",2:"|",3:"/"}[Math.round(t)%4];process.stdout.write(`\rCompletion ${t.toFixed(1)}% | Error ${(this.error*(h.length/(s+1))*100).toFixed(2)}% -> ${i} `)}}if(this.epochs++,o?.(this.error),this.error<=s)break}if(this.network.configure(Object.assign({},this.optimizer)),n){const t=(performance.now()-c)/1e3;process.stdout.write(`\rCompletion 100.0% | Error ${(100*this.error).toFixed(2)}% -> ${t.toFixed(1)}sec \n\r\n`)}return this.error}validate({data:t}){const e=r(i(t.data.length)),s={min:1,avg:0,max:0};for(let i=0;i<e.length;i++){const{input:r,target:a}=t.data[e[i]],n=this.propagate(r),o=this.network.lossFunction.mean(n,a);s.avg+=o/e.length,s.min=Math.min(s.min,o),s.max=Math.max(s.max,o)}return s}}class E extends x{constructor({input:t,window:e,stride:s}){s=s||e[0];super(t,a(...t,e[0],s,0),new m),this.stride=s,this.window=e}backPropagate(t,e,s){const i=new h(...this.input);for(let e=0;e<s.rows;e++)for(let r=0;r<s.columns;r++){let a=-Number.MAX_VALUE,n=[];for(let s=0;s<this.window[0];s++)for(let i=0;i<this.window[1];i++){const o=(e*this.stride+s)*this.input[1]+(r*this.stride+i);o>=t.entries.length||(a=this.backPropagatePoolIndex(a,t.entries[o],o,n))}for(const t of n)i.entries[t]+=s.entries[e*s.columns+r]/n.length}return i}}class S extends E{constructor(){super(...arguments),this.name="avgp"}propagate(t){return h.pool({matrix:t.reshape(...this.input),window:this.window,stride:this.stride,pooler:(t,e)=>t+e/(this.window[0]*this.window[1])})}backPropagatePoolIndex(t,e,s,i){return i.push(s),t}}class j extends x{constructor({input:t,kernel:e,stride:s=1,padding:i=0,activation:r=new m}){const n=a(...t,e[0],s,i);super(t,n,r),this.name="conv",this.kernel=h.random(e[0],e[1],-1,1),this.bias=new h(n[0],n[1]),this.stride=s,this.padding=i}propagate(t){return h.correlate(t.reshape(...this.input),this.kernel,this.stride,this.padding).add(this.bias).apply(this.activation.activate)}backPropagate(t,e,s){return e.apply(this.activation.deactivate).reshape(...this.output),s.reshape(...this.output),t.reshape(...this.input),this.optimizer.step(t,e.scale(s),((t,e)=>{this.bias.sub(e),this.kernel.sub(h.reverseCorrelate(t,e,this.stride))})),new h(this.kernel).flip().correlate(s.dialate(this.stride-1),1,this.input[0]-this.kernel.rows)}}class O extends x{constructor({input:t,output:e,activation:s=new m}){Array.isArray(t)&&(t=t[0]*t[1]),super([t,1],[e,1],s),this.name="fcon",this.weights=h.random(e,t,-1,1),this.bias=new h(e,1)}propagate(t){return h.mult(this.weights,t.reshape(...this.input)).add(this.bias).apply(this.activation.activate)}backPropagate(t,e,s){return e.apply(this.activation.deactivate).reshape(...this.output),s.reshape(...this.output),t.reshape(...this.input),this.optimizer.step(t,e.scale(s),((t,e)=>{this.bias.sub(e),this.weights.sub(e.mult(t.transpose()))})),h.transpose(this.weights).mult(s)}}class P extends x{constructor({input:t,output:e,activation:s=new m}){super(t,[t[0],e],s),this.cache={},this.index=0,this.state=new h(t[0],1),this.optimizer.configure({batchSize:1})}store(t,e){t in this.cache||(this.cache[t]=[]),this.cache[t].push(new h(e))}get(t,e=0){return this.cache[t][this.index+e]}propagate(t){t.reshape(...this.input);for(const t in this.cache)this.cache[t]=[];const e=[],s=Math.max(this.input[1],this.output[1]);for(let i=0;i<s;i++){this.index=i;const r=new h(this.input[0],1,i<this.input[1]-1?t.entries.slice(i*this.input[0],(i+1)*this.input[0]):void 0),a=this.forward(r,i>=s-this.output[1]);a&&e.push(...a.entries)}return this.clear(),new h(...this.output,e)}backPropagate(t,e,s){const i=Math.max(this.input[1],this.output[1]),r=[];s=new h(this.output[0],1,s.entries.slice((this.output[1]-1)*this.output[0]));for(let t=i-1;t>=0;t--)this.index=t,s=this.backward(s),t<this.input[1]&&r.push(...s.entries);return new h(...this.input,r)}}class W extends P{constructor(t){super(t),this.name="lstm",this.sigmoid=new m,this.tanh=new d;for(const t of["y","f","o","u","c"])this[`${t}Weights`]=h.random(this.input[0],this.input[0],-1,1),this[`${t}Bias`]=new h(this.input[0],1);this.memory=new h(this.input[0],1)}clear(){this.state.set(0),this.memory.set(0)}forward(t,e){this.store("state",this.state),this.store("input",t);const s=h.mult(this.uWeights,this.state),i=h.mult(this.cWeights,this.state),r=h.mult(this.fWeights,this.state),a=h.mult(this.oWeights,this.state);if(s.add(h.mult(this.uWeights,t)),i.add(h.mult(this.cWeights,t)),r.add(h.mult(this.fWeights,t)),a.add(h.mult(this.oWeights,t)),s.add(this.uBias).apply(this.sigmoid.activate),this.store("u",s),i.add(this.cBias).apply(this.tanh.activate),this.store("c",i),r.add(this.fBias).apply(this.sigmoid.activate),a.add(this.oBias).apply(this.sigmoid.activate),this.store("o",a),s.scale(i),this.index||this.store("memory",this.memory),this.memory.scale(r).add(s),this.state=new h(this.memory).apply(this.tanh.activate),this.store("memory",this.memory),this.state.scale(a),e){const t=h.mult(this.yWeights,this.state).add(this.yBias).apply(this.activation.activate);return this.store("output",t),t}this.store("output",this.state)}backward(t){let e,s=this.get("output").apply(this.activation.deactivate);return this.optimizer.step(new h(1,1),s.scale(t),((t,s)=>{const i=this.get("state").transpose(),r=this.get("input").transpose(),a=h.mult(h.transpose(this.yWeights),s),n=this.get("memory",1).scale(a).apply(this.sigmoid.deactivate),o=new h(this.get("memory")).apply(this.tanh.deactivate).scale(a).scale(this.get("o")),c=new h(this.get("memory")).scale(o).apply(this.sigmoid.deactivate),l=this.get("c").scale(o).apply(this.sigmoid.deactivate),u=this.get("u").scale(o).apply(this.tanh.deactivate);this.uBias.sub(l),this.uWeights.sub(h.mult(l,i).add(h.mult(l,r))),this.cBias.sub(u),this.cWeights.sub(h.mult(u,i).add(h.mult(u,r))),this.fBias.sub(c),this.fWeights.sub(h.mult(c,i).add(h.mult(c,r))),this.oBias.sub(n),this.oWeights.sub(h.mult(n,i).add(h.mult(n,r))),this.yBias.sub(s),this.yWeights.sub(h.mult(s,i).add(h.mult(s,r))),e=h.transpose(this.uWeights).mult(l).add(h.transpose(this.cWeights).mult(u)).add(h.transpose(this.fWeights).mult(c)).add(h.transpose(this.oWeights).mult(n))})),e}}class F extends E{constructor(){super(...arguments),this.name="maxp"}propagate(t){return h.pool({matrix:t.reshape(...this.input),window:this.window,stride:this.stride,initial:-Number.MAX_VALUE,pooler:(t,e)=>Math.max(t,e)})}backPropagatePoolIndex(t,e,s,i){return e>t?(i[0]=s,e):t}}class N extends P{constructor(t){super(t),this.name="recu",this.weights=h.random(this.input[0],this.input[0],-1,1),this.bias=new h(this.input[0],1)}clear(){this.state.set(0)}forward(t,e){if(this.store("state",this.state),this.store("input",t),this.state=h.mult(this.weights,this.state),this.state.add(h.mult(this.weights,t)),this.state.add(this.bias).apply(this.activation.activate),e){const t=h.mult(this.weights,this.state).add(this.bias).apply(this.activation.activate);return this.store("output",t),t}this.store("output",this.state)}backward(t){const e=this.get("output").apply(this.activation.deactivate);return this.optimizer.step(new h(1,1),e.scale(t),((t,e)=>{const s=h.mult(e,this.get("state").transpose()).add(h.mult(e,this.get("input").transpose()));this.bias.sub(e),this.weights.sub(s)})),h.transpose(this.weights).mult(t)}}const $={avgp:t=>({Layer:S,args:t}),conv:t=>({Layer:j,args:t}),fcon:t=>({Layer:O,args:t}),maxp:t=>({Layer:F,args:t}),recu:t=>({Layer:N,args:t}),lstm:t=>({Layer:W,args:t}),drop:t=>({Layer:z,args:t})};class R extends k{constructor({learningRate:t=.01,clipping:e=0,batchSize:s=4,beta1:i=.9,beta2:r=.999,epsilon:a=1e-8}={}){super({learningRate:t,clipping:e,batchSize:s}),this.name="adam",this.beta1=i,this.beta2=r,this.epsilon=a}step(t,e,s){super.step(t,e,((t,e)=>{this.m&&this.v||(this.m=new h(e.rows,e.columns),this.v=new h(this.m)),this.m.scale(this.beta1).add(new h(e).scale(1-this.beta1)),this.v.scale(this.beta2).add(new h(e).apply((t=>t*t)).scale(1-this.beta2));const i=Math.floor(this.i/this.batchSize)+1,r=new h(this.m).scale(1/(1-Math.pow(this.beta1,i))),a=new h(this.v).scale(1/(1-Math.pow(this.beta2,i)));e=r.scale(a.apply(Math.sqrt).add(this.epsilon).apply((t=>1/t))),s(t,e)}))}}class q extends k{constructor({learningRate:t=.01,clipping:e=0,batchSize:s=4,beta1:i=.9,epsilon:r=1e-8}={}){super({learningRate:t,clipping:e,batchSize:s}),this.name="rmsp",this.beta1=i,this.epsilon=r}step(t,e,s){super.step(t,e,((t,e)=>{this.v||(this.v=new h(e).set(1)),this.v.scale(this.beta1).add(new h(e).apply((t=>t*t)).scale(1-this.beta1)),e.scale(new h(this.v).apply(Math.sqrt).add(this.epsilon).apply((t=>1/t))),s(t,e)}))}}const B={sgd:t=>new v(t),bgd:t=>new k(t),adam:t=>new R(t),rmsp:t=>new q(t)},V=["input","in"],U=["target","output","out","label"];class _{constructor(t,e){if(this.labels=new Map,this.size={input:0,target:0},e&&t.length!==e.length)throw new Error("Input size does not match target size");this.data=t.map(((t,s)=>{let i,r=this.isValue(t)?this.toValue(t):this.getKey(t,V);return e?i=this.isValue(e[s])?this.toValue(e[s]):this.getKey(e[s],U):this.isValue(t)||(i=this.getKey(t,U)),this.size.input=r.entries.length,this.size.target=i.entries.length,{input:r,target:i}}))}isValue(t){return"object"!=typeof t||Array.isArray(t)||null===t}toValue(t){if(!(t="number"==typeof t?[t]:t))return new h(0,0);if("string"==typeof t){let e=this.labels.get(t);e||(e=this.labels.size,this.labels.set(t,this.labels.size)),(t=new Array(e).fill(0))[e]=1}return new h(t.length,1,t)}getKey(t,e){for(const s of e)if(s in t)return this.toValue(t[s]);return new h(0,0)}getLength(t,e){return e?Math.max(...t.keys()):Array.from(t.entries()).sort(((t,e)=>e[1]-t[1]))[0][0]}getLabels(){return Array.from(this.labels.keys())}clean({missing:t="remove",duplicates:e="keep",uneven:s="remove"}={}){const i=new Set,r={input:new Map,target:new Map};this.data=this.data.filter((s=>{const a=s.input.entries.length,n=s.target.entries.length;if(!("remove"!==t||a&&n))return!1;if("remove"===e){if(i.has(s.input))return!1;i.add(s.input)}return a&&r.input.set(a,(r.input.get(a)||0)+1),n&&r.target.set(n,(r.target.get(n)||0)+1),!0}));const a=this.getLength(r.input,"pad"===s),n=this.getLength(r.target,"pad"===s);return this.data=this.data.filter((t=>{const e=t.input.entries.length,i=t.target.entries.length,r=e!==a,o=i!==n;return("remove"!==s||!(r&&0!==e||o&&0!==i))&&(r&&(t.input=new h(a,1,t.input.entries)),o&&(t.target=new h(n,1,t.target.entries)),!0)})),this}normalize({mode:t="target",min:e=0,max:s=1}={}){let i=Number.MAX_VALUE,r=-Number.MAX_VALUE,a=Number.MAX_VALUE,n=-Number.MAX_VALUE;for(const{input:t,target:e}of this.data)i=Math.min(i,Math.min(...t.entries)),r=Math.max(r,Math.max(...t.entries)),a=Math.min(a,Math.min(...e.entries)),n=Math.max(n,Math.max(...e.entries));for(const{input:o,target:h}of this.data){if("target"!==t){const t=(s-e)/(r-i),a=s-t*r;for(let e=0;e<o.entries.length;e++)o.entries[e]=t*o.entries[e]+a}if("input"!==t){const t=(s-e)/(n-a),i=s-t*n;for(let e=0;e<h.entries.length;e++)h.entries[e]=t*h.entries[e]+i}}return this}split(t=.5){const e=Math.floor(this.data.length*t),s=new _([]),i=new _([]);return s.data=this.data.slice(0,e),s.labels=this.labels,s.size=this.size,i.data=this.data.slice(e),i.labels=this.labels,i.size=this.size,[s,i]}static async from(t){const[e,s]=("string"==typeof t?t.match(/.*\.(csv|json)$/i):t.type.match(/\/(csv|json)$/i))||[];if(!s)throw new Error("DataFrame only supports loading .csv or .json files");const i=await n(t);return"json"===s.toLowerCase()?new _(JSON.parse(i)):new _(function(t){const[e,...s]=t.split(/\r?\n/g),i=e.split(/;/g);function r(t){const e=parseFloat(t);return isNaN(e)?"null"===t?null:t:e}return s.map((t=>t.split(/;/g).reduce(((t,e,s)=>{e=e.replace(/\"(.*)\"/,"$1");const[a,n]=e.match(/^\[(.*)\]$/)||[];return t[i[s]]=n?n.split(",").map(r):r(e),t}),{})))}(i))}save(t){o(t,JSON.stringify(this.data.map((({input:t,target:e})=>({input:Array.from(t.entries),target:Array.from(e.entries)})))))}}function C(t){if("object"==typeof t){if(Array.isArray(t))return t.map(C);if(!("type"in t)){for(const e in t){let s;"lossFunction"!==e&&"activation"!==e||(s=new y[t[e]]),t[e]=s||C(t[e])}return t}const{type:e,...s}=t;switch(e){case"Network":case"Optimizer":case"Layer":t=Object.assign({type:e},C(s))}switch(e){case"Matrix":return new h(t.rows,t.columns,t.entries);case"Network":return Object.assign(Object.create(M.prototype),t);case"Optimizer":return Object.assign(B[t.name](),t);case"Layer":const{Layer:e}=$[t.name]();return Object.assign(Object.create(e.prototype),t)}}return t}async function X(t){const e=await n(t).then(JSON.parse);if("Neural"===e.name)return Object.assign(Object.create(L.prototype),C(e));throw new Error("Unable to load classifier")}export{p as Activator,u as CrossEntropyLoss,_ as DataFrame,g as Elu,$ as Layers,c as LossFunction,h as Matrix,L as Neural,B as Optimizers,w as Relu,m as Sigmoid,f as SoftPlus,l as SquaredLoss,d as TanH,X as load}; //# sourceMappingURL=index.js.map