@robotical/martyblocks 2.2.16 → 2.2.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib.min.js +6 -6
- package/dist/static/MLModelWorker.js +1 -1
- package/package.json +1 -1
|
@@ -22171,4 +22171,4 @@ return a / b;`,packedOpSnippet:`
|
|
|
22171
22171
|
* See the License for the specific language governing permissions and
|
|
22172
22172
|
* limitations under the License.
|
|
22173
22173
|
* =============================================================================
|
|
22174
|
-
*/const Qm="tfjs-speech-commands-saved-model-metadata",a8="indexeddb://tfjs-speech-commands-model/";let eg={localStorage:typeof window=="undefined"?null:window.localStorage};function o8(n){return n.split(".").slice(0,2).join(".")}const yS="0.5.4",uh=.25,mo=class mo{constructor(e,t,s){ce(this,"MODEL_URL_PREFIX",`https://storage.googleapis.com/tfjs-models/tfjs/speech-commands/v${o8(yS)}/browser_fft`);ce(this,"SAMPLE_RATE_HZ",44100);ce(this,"FFT_SIZE",1024);ce(this,"DEFAULT_SUPPRESSION_TIME_MILLIS",0);ce(this,"model");ce(this,"modelWithEmbeddingOutput");ce(this,"vocabulary");ce(this,"parameters");ce(this,"words");ce(this,"streaming",!1);ce(this,"nonBatchInputShape");ce(this,"elementsPerExample");ce(this,"audioDataExtractor");ce(this,"transferRecognizers",{});ce(this,"modelArtifactsOrURL");ce(this,"metadataOrURL");ce(this,"secondLastBaseDenseLayer");S(t==null&&s==null||t!=null&&s!=null,()=>"modelURL and metadataURL must be both provided or both not provided."),t==null?(e==null?e=mo.DEFAULT_VOCABULARY_NAME:S(mo.VALID_VOCABULARY_NAMES.indexOf(e)!==-1,()=>`Invalid vocabulary name: '${e}'`),this.vocabulary=e,this.modelArtifactsOrURL=`${this.MODEL_URL_PREFIX}/${this.vocabulary}/model.json`,this.metadataOrURL=`${this.MODEL_URL_PREFIX}/${this.vocabulary}/metadata.json`):(S(e==null,()=>"vocabulary name must be null or undefined when modelURL is provided"),this.modelArtifactsOrURL=t,this.metadataOrURL=s),this.parameters={sampleRateHz:this.SAMPLE_RATE_HZ,fftSize:this.FFT_SIZE}}listen(e,t){return O(this,null,function*(){if(this.streaming)throw new Error("Cannot start streaming again when streaming is ongoing.");console.log("in listen: ensuring model is loaded"),yield this.ensureModelLoaded(),t==null&&(t={});let s=t.probabilityThreshold==null?0:t.probabilityThreshold;if(t.includeEmbedding&&(s=0),S(s>=0&&s<=1,()=>`Invalid probabilityThreshold value: ${s}`),t.invokeCallbackOnNoiseAndUnknown==null||t.invokeCallbackOnNoiseAndUnknown,t.includeEmbedding,t.suppressionTimeMillis<0)throw new Error(`suppressionTimeMillis is expected to be >= 0, but got ${t.suppressionTimeMillis}`);const r=t.overlapFactor==null?.5:t.overlapFactor;S(r>=0&&r<1,()=>`Expected overlapFactor to be >= 0 and < 1, but got ${r}`);const a=(i,l)=>O(this,null,function*(){const c=hl(i);let u,h;t.includeEmbedding?(yield this.ensureModelWithEmbeddingOutputCreated(),[u,h]=this.modelWithEmbeddingOutput.predict(c)):u=this.model.predict(c);const d=yield u.data(),p=u.argMax(-1);(yield p.data())[0];const f=Math.max(...d);if(be([u,p,c]),f<s)return!1;{let m;t.includeSpectrogram&&(m={data:yield i.data(),frameSize:this.nonBatchInputShape[1]});let g=!0;return e({scores:d,spectrogram:m,embedding:h}),g}}),o=t.suppressionTimeMillis==null?this.DEFAULT_SUPPRESSION_TIME_MILLIS:t.suppressionTimeMillis;this.audioDataExtractor=new Jm({sampleRateHz:this.parameters.sampleRateHz,numFramesPerSpectrogram:this.nonBatchInputShape[0],columnTruncateLength:this.nonBatchInputShape[1],suppressionTimeMillis:o,spectrogramCallback:a,overlapFactor:r}),yield this.audioDataExtractor.startStreamedInput(),this.streaming=!0})}ensureModelLoaded(){return O(this,null,function*(){if(this.model!=null)return;yield this.ensureMetadataLoaded();let e;if(typeof this.modelArtifactsOrURL=="string"?e=yield Hi(this.modelArtifactsOrURL):e=yield Hi(Pb(this.modelArtifactsOrURL.modelTopology||{},this.modelArtifactsOrURL.weightSpecs,this.modelArtifactsOrURL.weightData)),e.inputs.length!==1)throw new Error(`Expected model to have 1 input, but got a model with ${e.inputs.length} inputs`);if(e.inputs[0].shape.length!==4)throw new Error(`Expected model to have an input shape of rank 4, but got an input shape of rank ${e.inputs[0].shape.length}`);if(e.inputs[0].shape[3]!==1)throw new Error(`Expected model to have an input shape with 1 as the last dimension, but got input shape${JSON.stringify(e.inputs[0].shape[3])}}`);const t=e.outputShape;if(t.length!==2)throw new Error(`Expected loaded model to have an output shape of rank 2,but received shape ${JSON.stringify(t)}`);if(t[1]!==this.words.length)throw new Error(`Mismatch between the last dimension of model's output shape (${t[1]}) and number of words (${this.words.length}).`);this.model=e,this.freezeModel(),this.nonBatchInputShape=e.inputs[0].shape.slice(1),this.elementsPerExample=1,e.inputs[0].shape.slice(1).forEach(a=>this.elementsPerExample*=a),this.warmUpModel();const s=this.parameters.fftSize/this.parameters.sampleRateHz*1e3,r=e.inputs[0].shape[1];this.parameters.spectrogramDurationMillis=r*s})}ensureModelWithEmbeddingOutputCreated(){return O(this,null,function*(){if(this.modelWithEmbeddingOutput!=null)return;yield this.ensureModelLoaded();let e;for(let t=this.model.layers.length-2;t>=0;--t)if(this.model.layers[t].getClassName()==="Dense"){e=this.model.layers[t];break}if(e==null)throw new Error("Failed to find second last dense layer in the original model.");this.modelWithEmbeddingOutput=Su({inputs:this.model.inputs,outputs:[this.model.outputs[0],e.output]})})}warmUpModel(){P(()=>{const e=ct([1].concat(this.nonBatchInputShape));for(let t=0;t<3;++t)this.model.predict(e)})}ensureMetadataLoaded(){return O(this,null,function*(){if(this.words!=null)return;const e=typeof this.metadataOrURL=="string"?yield G5(this.metadataOrURL):this.metadataOrURL;if(e.wordLabels==null){const t=e.words;if(t==null)throw new Error('Cannot find field "words" or "wordLabels" in metadata JSON file');this.words=t}else this.words=e.wordLabels})}stopListening(){return O(this,null,function*(){yield this.audioDataExtractor.stop(),this.streaming=!1})}isListening(){return this.streaming}wordLabels(){return this.words}params(){return this.parameters}modelInputShape(){if(this.model==null)throw new Error("Model has not been loaded yet. Load model by calling ensureModelLoaded(), recognize(), or listen().");return this.model.inputs[0].shape}recognize(e,t){return O(this,null,function*(){t==null&&(t={}),yield this.ensureModelLoaded(),e==null&&(e=(yield this.recognizeOnline()).data);let s,r,a;if(e instanceof Oe)this.checkInputTensorShape(e),r=e,s=e.shape[0];else{if(e.length%this.elementsPerExample)throw new Error(`The length of the input Float32Array ${e.length} is not divisible by the number of tensor elements per per example expected by the model ${this.elementsPerExample}.`);s=e.length/this.elementsPerExample,r=ab(e,[s].concat(this.nonBatchInputShape))}const o={scores:[]};if(t.includeEmbedding){yield this.ensureModelWithEmbeddingOutputCreated();const i=this.modelWithEmbeddingOutput.predict(r);a=i[0],o.embedding=i[1]}else a=this.model.predict(r);if(s===1)o.scores=yield a.data();else{const i=Cn(a),l=i.map(c=>c.data());o.scores=yield Promise.all(l),be(i)}return t.includeSpectrogram&&(o.spectrogram={data:e instanceof Oe?yield e.data():e,frameSize:this.nonBatchInputShape[1]}),be(a),o})}recognizeOnline(){return O(this,null,function*(){return new Promise((e,t)=>{const s=r=>O(this,null,function*(){const a=hl(r);return yield this.audioDataExtractor.stop(),e({data:yield a.data(),frameSize:this.nonBatchInputShape[1]}),a.dispose(),!1});this.audioDataExtractor=new Jm({sampleRateHz:this.parameters.sampleRateHz,numFramesPerSpectrogram:this.nonBatchInputShape[0],columnTruncateLength:this.nonBatchInputShape[1],suppressionTimeMillis:0,spectrogramCallback:s,overlapFactor:0})})})}createTransfer(e){if(this.model==null)throw new Error("Model has not been loaded yet. Load model by calling ensureModelLoaded(), recognizer(), or listen().");S(e!=null&&typeof e=="string"&&e.length>1,()=>`Expected the name for a transfer-learning recognized to be a non-empty string, but got ${JSON.stringify(e)}`),S(this.transferRecognizers[e]==null,()=>`There is already a transfer-learning model named '${e}'`);const t=new i8(e,this.parameters,this.model);return this.transferRecognizers[e]=t,t}freezeModel(){for(const e of this.model.layers)e.trainable=!1}checkInputTensorShape(e){const t=this.model.inputs[0].shape.length;if(e.shape.length!==t)throw new Error(`Expected input Tensor to have rank ${t}, but got rank ${e.shape.length} that differs `);const s=e.shape.slice(1),r=this.model.inputs[0].shape.slice(1);if(!Ee(s,r))throw new Error(`Expected input to have shape [null,${r}], but got shape [null,${s}]`)}};ce(mo,"VALID_VOCABULARY_NAMES",["18w","directional4w"]),ce(mo,"DEFAULT_VOCABULARY_NAME","18w");let fo=mo;class i8 extends fo{constructor(t,s,r){super();ce(this,"dataset");ce(this,"transferHead");this.name=t,this.parameters=s,this.baseModel=r,S(t!=null&&typeof t=="string"&&t.length>0,()=>`The name of a transfer model must be a non-empty string, but got ${JSON.stringify(t)}`),this.nonBatchInputShape=this.baseModel.inputs[0].shape.slice(1),this.words=null,this.dataset=new gS}addExamples(t){return O(this,null,function*(){for(const s of t)for(const r of s.samples)console.log(`class ${s.name}, sample ${r}, has timeDataQueue length ${r.timeDataQueue.length}, and freqDataQueue length ${r.freqDataQueue.length}`),yield this.collectExample(s.name,r,{durationMultiplier:1,includeRawAudio:!0})})}collectExample(t,s,r){return O(this,null,function*(){if(S(!this.streaming,()=>"Cannot start collection of transfer-learning example because a streaming recognition or transfer-learning example collection is ongoing"),S(t!=null&&typeof t=="string"&&t.length>0,()=>"Must provide a non-empty string when collecting transfer-learning example"),r==null&&(r={}),r.durationMultiplier!=null&&r.durationSec!=null)throw new Error("durationMultiplier and durationSec are mutually exclusive, but are both specified.");let a;if(r.durationSec!=null){S(r.durationSec>0,()=>`Expected durationSec to be > 0, but got ${r.durationSec}`);const l=this.parameters.fftSize/this.parameters.sampleRateHz;a=Math.ceil(r.durationSec/l)}else r.durationMultiplier!=null?(S(r.durationMultiplier>=1,()=>`Expected duration multiplier to be >= 1, but got ${r.durationMultiplier}`),a=Math.round(this.nonBatchInputShape[0]*r.durationMultiplier)):a=this.nonBatchInputShape[0];r.snippetDurationSec!=null&&(S(r.snippetDurationSec>0,()=>`snippetDurationSec is expected to be > 0, but got ${r.snippetDurationSec}`),S(r.onSnippet!=null,()=>"onSnippet must be provided if snippetDurationSec is provided.")),r.onSnippet!=null&&S(r.snippetDurationSec!=null,()=>"snippetDurationSec must be provided if onSnippet is provided.");const i=this.parameters.fftSize/this.parameters.sampleRateHz*a;return this.streaming=!0,new Promise(l=>{const c=r.snippetDurationSec==null?1:r.snippetDurationSec/i,u=1-c,h=Math.round(1/c);let d=0,p=-1;const f=[],m=(g,y)=>O(this,null,function*(){if(r.onSnippet==null){const b=hl(g);this.dataset.addExample({label:t,spectrogram:{data:yield b.data(),frameSize:this.nonBatchInputShape[1]},rawAudio:r.includeRawAudio?{data:yield y.data(),sampleRateHz:this.audioDataExtractor.sampleRateHz}:void 0}),b.dispose(),yield this.audioDataExtractor.stop(),this.streaming=!1,this.collateTransferWords(),l({data:yield g.data(),frameSize:this.nonBatchInputShape[1]})}else{const b=yield g.data();p===-1&&(p=b.length);let w=p-1;for(;b[w]!==0&&w>=0;)w--;const x=p-w-1;p=w+1;const v=b.slice(b.length-x,b.length);if(f.push(v),r.onSnippet!=null&&r.onSnippet({data:v,frameSize:this.nonBatchInputShape[1]}),d++===h){yield this.audioDataExtractor.stop(),this.streaming=!1,this.collateTransferWords();const C={data:H5(j5(f)),frameSize:this.nonBatchInputShape[1]};this.dataset.addExample({label:t,spectrogram:C,rawAudio:r.includeRawAudio?{data:yield y.data(),sampleRateHz:this.audioDataExtractor.sampleRateHz}:void 0}),l(C)}}return!1});this.audioDataExtractor=new Jm({sampleRateHz:this.parameters.sampleRateHz,numFramesPerSpectrogram:a,columnTruncateLength:this.nonBatchInputShape[1],suppressionTimeMillis:0,spectrogramCallback:m,overlapFactor:u,includeRawAudio:r.includeRawAudio}),this.audioDataExtractor.start(s)})})}clearExamples(){S(this.words!=null&&this.words.length>0&&!this.dataset.empty(),()=>`No transfer learning examples exist for model name ${this.name}`),this.dataset.clear(),this.words=null}countExamples(){if(this.dataset.empty())throw new Error(`No examples have been collected for transfer-learning model named '${this.name}' yet.`);return this.dataset.getExampleCounts()}getExamples(t){return this.dataset.getExamples(t)}setExampleKeyFrameIndex(t,s){this.dataset.setExampleKeyFrameIndex(t,s)}removeExample(t){this.dataset.removeExample(t),this.collateTransferWords()}isDatasetEmpty(){return this.dataset.empty()}loadExamples(t,s=!1){const r=new gS(t);s&&this.clearExamples();const a=r.getVocabulary();for(const o of a){const i=r.getExamples(o);for(const l of i)this.dataset.addExample(l.example)}this.collateTransferWords()}serializeExamples(t){return this.dataset.serialize(t)}collateTransferWords(){this.words=this.dataset.getVocabulary()}collectTransferDataAsTensors(t,s){const r=this.nonBatchInputShape[0];t=t||uh;const a=Math.round(t*r),o=this.dataset.getData(void 0,cg({numFrames:r,hopFrames:a},s));return{xs:o.xs,ys:o.ys}}collectTransferDataAsTfDataset(t,s=.15,r=32,a){const o=this.nonBatchInputShape[0];t=t||uh;const i=Math.round(t*o);return this.dataset.getData(void 0,cg({numFrames:o,hopFrames:i,getDataset:!0,datasetBatchSize:r,datasetValidationSplit:s},a))}train(t){return O(this,null,function*(){S(this.words!=null&&this.words.length>0,()=>`Cannot train transfer-learning model '${this.name}' because no transfer learning example has been collected.`),S(this.words.length>1,()=>`Cannot train transfer-learning model '${this.name}' because only 1 word label ('${JSON.stringify(this.words)}') has been collected for transfer learning. Requires at least 2.`),t.fineTuningEpochs!=null&&S(t.fineTuningEpochs>=0&&Number.isInteger(t.fineTuningEpochs),()=>`If specified, fineTuningEpochs must be a non-negative integer, but received ${t.fineTuningEpochs}`),t==null&&(t={}),this.model==null&&this.createTransferModelFromBaseModel(),this.secondLastBaseDenseLayer.trainable=!1,this.model.compile({loss:"categoricalCrossentropy",optimizer:t.optimizer||"sgd",metrics:["acc"]});const s=t.fitDatasetDurationMillisThreshold==null?6e4:t.fitDatasetDurationMillisThreshold;return this.dataset.durationMillis()>s?(console.log(`Detected large dataset: total duration = ${this.dataset.durationMillis()} ms > ${s} ms. Training transfer model using fitDataset() instead of fit()`),this.trainOnDataset(t)):this.trainOnTensors(t)})}trainOnDataset(t){return O(this,null,function*(){S(t.epochs>0,()=>"Invalid config!.epochs");const s=t.batchSize==null?32:t.batchSize,r=t.windowHopRatio||uh,[a,o]=this.collectTransferDataAsTfDataset(r,t.validationSplit,s,{augmentByMixingNoiseRatio:t.augmentByMixingNoiseRatio}),i=dt(),l=yield this.model.fitDataset(a,{epochs:t.epochs,validationData:t.validationSplit>0?o:void 0,callbacks:t.callback==null?void 0:[t.callback]});if(console.log(`fitDataset() took ${(dt()-i).toFixed(2)} ms`),t.fineTuningEpochs!=null&&t.fineTuningEpochs>0){const c=dt(),u=yield this.fineTuningUsingTfDatasets(t,a,o);return console.log(`fitDataset() (fine-tuning) took ${(dt()-c).toFixed(2)} ms`),[l,u]}else return l})}trainOnTensors(t){return O(this,null,function*(){const s=t.windowHopRatio||uh,{xs:r,ys:a}=this.collectTransferDataAsTensors(s,{augmentByMixingNoiseRatio:t.augmentByMixingNoiseRatio});console.log(`Training data: xs.shape = ${r.shape}, ys.shape = ${a.shape}`);let o,i,l=null;try{if(t.validationSplit!=null){const u=X5(r,a,t.validationSplit);o=u.trainXs,i=u.trainYs,l=[u.valXs,u.valYs]}else o=r,i=a;const c=yield this.model.fit(o,i,{epochs:t.epochs==null?20:t.epochs,validationData:l,batchSize:t.batchSize,callbacks:t.callback==null?void 0:[t.callback]});if(t.fineTuningEpochs!=null&&t.fineTuningEpochs>0){const u=yield this.fineTuningUsingTensors(t,o,i,l);return[c,u]}else return c}finally{be([r,a,o,i,l])}})}fineTuningUsingTfDatasets(t,s,r){return O(this,null,function*(){const a=this.secondLastBaseDenseLayer.trainable;this.secondLastBaseDenseLayer.trainable=!0;const o=t.fineTuningOptimizer==null?"sgd":t.fineTuningOptimizer;this.model.compile({loss:"categoricalCrossentropy",optimizer:o,metrics:["acc"]});const i=yield this.model.fitDataset(s,{epochs:t.fineTuningEpochs,validationData:r,callbacks:t.callback==null?void 0:[t.callback]});return this.secondLastBaseDenseLayer.trainable=a,i})}fineTuningUsingTensors(t,s,r,a){return O(this,null,function*(){const o=this.secondLastBaseDenseLayer.trainable;this.secondLastBaseDenseLayer.trainable=!0;const i=t.fineTuningOptimizer==null?"sgd":t.fineTuningOptimizer;this.model.compile({loss:"categoricalCrossentropy",optimizer:i,metrics:["acc"]});const l=yield this.model.fit(s,r,{epochs:t.fineTuningEpochs,validationData:a,batchSize:t.batchSize,callbacks:t.fineTuningCallback==null?void 0:[t.fineTuningCallback]});return this.secondLastBaseDenseLayer.trainable=o,l})}evaluate(t){return O(this,null,function*(){S(t.wordProbThresholds!=null&&t.wordProbThresholds.length>0,()=>"Received null or empty wordProbThresholds");const s=0;return S(this.words[s]===dl,()=>`Cannot perform evaluation when the first tag is not ${dl}`),P(()=>{const r=[];let a=0;const{xs:o,ys:i}=this.collectTransferDataAsTensors(t.windowHopRatio),l=i.argMax(-1).dataSync(),c=this.model.predict(o),u=Sn(Ae(c,[0,1],[c.shape[0],c.shape[1]-1]),-1),h=c.shape[0];for(let d=0;d<t.wordProbThresholds.length;++d){const p=t.wordProbThresholds[d],f=u.greater(pe(p)).dataSync();let m=0,g=0,y=0,b=0;for(let v=0;v<h;++v)l[v]===s?(m++,f[v]&&y++):(g++,f[v]&&b++);const w=y/m,x=b/g;r.push({probThreshold:p,fpr:w,tpr:x}),console.log(`ROC thresh=${p}: fpr=${w.toFixed(4)}, tpr=${x.toFixed(4)}`),d>0&&(a+=Math.abs(r[d-1].fpr-r[d].fpr)*(r[d-1].tpr+r[d].tpr)/2)}return{rocCurve:r,auc:a}})})}createTransferModelFromBaseModel(t){S(this.words!=null,()=>"No word example is available for tranfer-learning model of name "+this.name);const s=this.baseModel.layers;let r=s.length-2;for(;r>=0&&s[r].getClassName().toLowerCase()!=="dense";)r--;if(r<0)throw new Error("Cannot find a hidden dense layer in the base model.");this.secondLastBaseDenseLayer=s[r];const a=this.secondLastBaseDenseLayer.output;this.transferHead=ji(),this.transferHead.add(om({units:this.words.length,activation:"softmax",inputShape:a.shape.slice(1),name:"NewHeadDense"})),t&&this.transferHead.setWeights(t);const o=this.transferHead.apply(a);this.model=Su({inputs:this.baseModel.inputs,outputs:o})}modelInputShape(){return this.baseModel.inputs[0].shape}getMetadata(){return{tfjsSpeechCommandsVersion:yS,modelName:this.name,timeStamp:new Date().toISOString(),wordLabels:this.wordLabels()}}getAudioStream(t){t.timeData&&this.audioDataExtractor&&(this.audioDataExtractor.streamedTimeData=t.timeData),t.freqData&&this.audioDataExtractor&&(this.audioDataExtractor.streamedFreqData=t.freqData)}save(t){return O(this,null,function*(){const s=t!=null;if(t=t||bS(this.name),!s){const r=eg.localStorage.getItem(Qm),a=r==null?{}:JSON.parse(r);a[this.name]=this.getMetadata(),eg.localStorage.setItem(Qm,JSON.stringify(a))}return console.log(`Saving model to ${t}`),this.model.save(t)})}load(t){return O(this,null,function*(){const s=t!=null;if(t=t||bS(this.name),!s){const r=JSON.parse(eg.localStorage.getItem(Qm)||"");if(r==null||r[this.name]==null)throw new Error(`Cannot find metadata for transfer model named ${this.name}"`);this.words=r[this.name].wordLabels,console.log(`Loaded word list for model named ${this.name}: ${this.words}`)}this.model=yield Hi(t),console.log(`Loaded model from ${t}:`),this.model.summary()})}createTransfer(t){throw new Error("Creating transfer-learned recognizer from a transfer-learned recognizer is not supported.")}}function bS(n){return`${a8}${n}`}console.log("running MLModelWorker.ts");const l8=1,c8="conv_pw_13_relu",u8="out_relu",tg=.25,ng=.35,xS=224;class sg{constructor(){ce(this,"output",[]);ce(this,"predictionIdx",-1)}}class pl{constructor(){ce(this,"isTraining",!1);ce(this,"isTrained",!1);ce(this,"isPrediction",!1);ce(this,"i",0);ce(this,"iterations",0);ce(this,"modelFitTime",0);ce(this,"lossValues",[]);ce(this,"accuracyValues",[]);ce(this,"accuracy",0);ce(this,"isCorrect",[]);ce(this,"examples",[]);ce(this,"predictions",new sg);ce(this,"modelPredictTime",0)}}const wS=(n,e)=>{if(n===1){if(e!==.25&&e!==.5&&e!==.75&&e!==1)return console.warn("Invalid alpha. Options are: 0.25, 0.50, 0.75 or 1.00."),console.log("Loading model with alpha: ",tg.toFixed(2)),tg}else if(e!==.35&&e!==.5&&e!==.75&&e!==1)return console.warn("Invalid alpha. Options are: 0.35, 0.50, 0.75 or 1.00."),console.log("Loading model with alpha: ",ng.toFixed(2)),ng;return e},h8=n=>{if(n=n||{},n.checkpointUrl&&n.trainingLayer)return(n.alpha||n.version)&&console.warn("Checkpoint URL passed to modelOptions, alpha options are ignored"),[n.checkpointUrl,n.trainingLayer];if(n.version=n.version||l8,n.version===1){n.alpha=n.alpha||tg,n.alpha=wS(n.version,n.alpha),console.log(`Loading mobilenet ${n.version} and alpha ${n.alpha}`);let e=n.alpha.toFixed(2);return e==="1.00"&&(e="1.0"),[`https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v1_${e}_${xS}/model.json`,c8]}else{if(n.version===2)return n.alpha=n.alpha||ng,n.alpha=wS(n.version,n.alpha),console.log(`Loading mobilenet ${n.version} and alpha ${n.alpha}`),[`https://storage.googleapis.com/teachable-machine-models/mobilenet_v2_weights_tf_dim_ordering_tf_kernels_${n.alpha.toFixed(2)}_${xS}_no_top/model.json`,u8];throw new Error(`MobileNet V${n.version} doesn't exist`)}},fa=class fa{constructor(){ce(this,"_mobileNetModel",null);ce(this,"_stopTrainingRequested",!1);ce(this,"_resetModelRequested",!1);ce(this,"_localIsTraining",!1);ce(this,"_localModel",null);ce(this,"_speechRecognizer",null);ce(this,"_trainingData",null);ce(this,"seed")}static getInstance(){return fa._instance||(fa._instance=new fa),fa._instance}loadTruncatedMobileNet(e){return O(this,null,function*(){const[t,s]=h8(e),r=yield Hi(t);if(e&&e.version===1){const a=r.getLayer(s),o=Su({inputs:r.inputs,outputs:a.output}),i=ji();return i.add(o),i.add(WF()),i}else{const a=r.getLayer(s),o=Su({inputs:r.inputs,outputs:a.output}),i=ji();return i.add(o),i.add(UF({})),i}})}loadMobilenet(){return O(this,null,function*(){const t=yield ZO("https://tfhub.dev/google/tfjs-model/imagenet/mobilenet_v3_small_100_224/feature_vector/5/default/1",{fromTFHub:!0});return t!==void 0&&P(()=>{t.predict(ct([1,cS,uS,3]))}),t})}resetModel(){this._mobileNetModel=null,this._stopTrainingRequested=!1,this._resetModelRequested=!1,this._localIsTraining=!1,this._localModel=null,this._trainingData=null;const e=new pl;self.postMessage({type:"status",payload:e})}onmessage(e){return O(this,null,function*(){switch(e.data.command){case"PREPARE_ENGINE":console.log("MLModelWorker: prepare engine"),this._mobileNetModel||(this._mobileNetModel=yield this.loadTruncatedMobileNet());break;case"AUDIO_START_LISTENING":this._speechRecognizer&&this._speechRecognizer.listen(y=>O(this,null,function*(){let b=-1,w=-1;const x=new sg;for(let $=0;$<y.scores.length;$++){const C=y.scores[$];C>w&&(x.output.push({label:this._trainingData.classes.sort((k,T)=>k.name<T.name?-1:k.name>T.name?1:0)[$].name,confidence:C}),b=$)}x.predictionIdx=b;const v=new pl;v.isTrained=!0,v.isPrediction=!0,v.predictions=x,self.postMessage({type:"status",payload:v})}));break;case"STOP_AUDIO_LISTENING":this._speechRecognizer&&this._speechRecognizer.stopListening();break;case"TRAIN":this._stopTrainingRequested=!1,this._resetModelRequested=!1;const t=e.data.modelType;t==="image-device"?yield this.train(e):t==="audio"&&(yield this.trainAudio(e));break;case"PREDICT":yield this.predict(e);break;case"STOP_TRAINING":this._localIsTraining&&(this._stopTrainingRequested=!0);break;case"RESET_MODEL":this._localIsTraining?(this._stopTrainingRequested=!0,this._resetModelRequested=!0):this.resetModel();break;case"SAVE_MODEL":if(this._localModel){let y=null,b=null,w=null;if(e.data.modelType==="audio"){const x=this._localModel.layers[this._localModel.layers.length-1];b=x.weights.map(C=>C.read().dataSync()),w=x.weights;const $={config:x.getConfig(),weights:b};y=JSON.stringify($)}else e.data.modelType==="image-device"&&(this._localModel=this._localModel,y=this._localModel.toJSON(),b=this._localModel.weights.map(x=>x.read().dataSync()),w=this._localModel.weights);self.postMessage({type:"save_model",payload:{modelJSON:y,weights:{weightBuffers:b,weightInfo:w}}})}break;case"LOAD_TM_MODEL":const{tmModelUrl:s}=e.data;if(this._localModel&&this._localModel.dispose(),s){console.debug("MLModelWorker: Loading TM model...");const b=yield(yield fetch(s.replace("model.json","metadata.json"))).json();this._localModel=yield Hi(s),console.log("modelMetadataJson",b),console.log("modelMetadataJson.labels",b.labels),console.log("modelMetadataJson.wordLabels",b.wordLabels);const w=b.labels?"image-device":"audio";if(console.log("modelType",w),w==="audio"){const x=new fo;yield x.ensureModelLoaded(),this._speechRecognizer=x.createTransfer("modelNameExample"),this._speechRecognizer.words=b.wordLabels,this._speechRecognizer.model=this._localModel}self.postMessage({type:"load_model",payload:{}})}break;case"LOAD_AUDIO_MODEL":this._localModel&&this._localModel.dispose();const{modelJSON:r,weightBuffers:a,weightInfo:o,audioAlphabeticalWords:i}=e.data,l=new fo;yield l.ensureModelLoaded(),this._speechRecognizer=l.createTransfer("modelNameExample");const c=a.map((y,b)=>{const w=o[b].shape,x=o[b].dtype;return Bt(y,w,x)});this._speechRecognizer.words=i,this._speechRecognizer.createTransferModelFromBaseModel(c),self.postMessage({type:"load_model",payload:{}});break;case"LOAD_MODEL":this._localModel&&this._localModel.dispose();const{modelJSON:u,weightBuffers:h,weightInfo:d}=e.data;console.debug("MLModelWorker: Loading MM model...");const p=JSON.parse(u);console.debug("MLModelWorker: Loading model...",e.data);const f=yield vF(p);console.log("model",f);const m=h.map((y,b)=>{const w=d[b].shape,x=d[b].dtype;return Bt(y,w,x)});console.debug("MLModelWorker: Setting weights...",m),f.setWeights(m),this._localModel=f,console.debug("MLModelWorker: Model loaded!"),self.postMessage({type:"load_model",payload:{}});break;case"SET_TRAINING_DATA":this._trainingData=e.data.trainingData;break;case"STREAM_AUDIO":const{streamedAudioData:g}=e.data;this._speechRecognizer&&this._speechRecognizer.getAudioStream(g);break}})}imgToTensor(e,t){return P(()=>{let s=EA(e);return t&&(s=Pn.resizeBilinear(s,t)),this.cropImage(s).expandDims(0).toFloat().div(pe(127)).sub(pe(1))})}cropImage(e){const t=Math.min(e.shape[0],e.shape[1]),r=e.shape[0]/2-t/2,o=e.shape[1]/2-t/2;return e.slice([r,o,0],[t,t,3])}convertUtilsPixelsToTensor(e){const{pixelsBase64:t,height:s,width:r,depth:a}=e,o=Uint8Array.from(atob(t),u=>u.charCodeAt(0)),i=Ua(o,[s,r,a],"int32"),c=Pn.resizeBilinear(i,[uS,cS],!0).div(255);return this._mobileNetModel.predict(c.expandDims())}trainAudio(e){return O(this,null,function*(){console.log("event",e);const t=e.data.trainingData;if(!t)return console.log("MLModelWorker: No audio training data!"),!1;const s=t;this._trainingData=s;const r=new fo;this._localIsTraining=!0;const a=new pl;a.isTraining=!0,yield r.ensureModelLoaded(),console.log("MLModelWorker: Speech model loaded!"),console.log("baseRecognizer parameters:",r.params()),console.log("baseRecognizer input shape:",r.modelInputShape());const o=r.createTransfer("modelNameExample");yield o.addExamples(s.classes),console.log(o.countExamples());const i=e.data.trainIterations,l=performance.now(),c=[[]],u=[[]];return yield o.train({epochs:i,callback:{onEpochEnd:(h,d)=>O(this,null,function*(){const f=(performance.now()-l)/1e3,m=d.loss,g=d.acc;c[0].push({x:h,y:m}),u[0].push({x:h,y:g}),a.i=h,a.iterations=i,a.modelFitTime=f,a.lossValues=c,a.accuracyValues=u,self.postMessage({type:"status",payload:a})}),onTrainEnd:h=>O(this,null,function*(){this._localIsTraining=!1,this._resetModelRequested?this.resetModel():(a.isTraining=!1,a.isTrained=!0,self.postMessage({type:"status",payload:a})),this._speechRecognizer=o,this._localModel=o.model})}}),!0})}train(e){return O(this,null,function*(){if(!this._mobileNetModel)if(this._mobileNetModel=yield this.loadTruncatedMobileNet(),this._mobileNetModel)console.log("MLModelWorker: mobilenet loaded");else return console.log("MLModelWorker: MobileNet not loaded!"),!1;if(!e.data.trainingData)return console.log("MLModelWorker: No training data!"),!1;const t=e.data.trainingData;if(t.classes.length===0)return console.log("MLModelWorker: No classes to train!"),!1;if(t.classes.some(w=>w.samples.length===0))return console.log("MLModelWorker: At least one class has no samples!"),!1;this._localIsTraining=!0;const s=new pl;s.isTraining=!0,this._trainingData=t;const r=t.classes.flatMap(w=>w.samples.map(({tensorData:x,tensorShape:v,tensorDtype:$})=>{const C=Bt(new Float32Array(x),v,$),k=this._mobileNetModel.predict(C),T=k.dataSync();return C.dispose(),k.dispose(),T})),a=t.classes.flatMap((w,x)=>w.samples.map(()=>x));go(r,a);const o=ft(a,"int32"),i=Vr(o,t.classes.length),l=Wt(r),c=this._mobileNetModel.outputs[0].shape.slice(1),u=U(c),h=E_({});this._localModel=ji(),this._localModel.add(om({inputShape:[u],units:100,activation:"relu",kernelInitializer:h,useBias:!0})),this._localModel.add(om({kernelInitializer:h,useBias:!1,activation:"softmax",units:t.classes.length}));const d=.001,p=qr.adam(d);this._localModel.compile({optimizer:p,loss:"categoricalCrossentropy",metrics:["accuracy"]});const{trainIterations:f,batchSize:m}=e.data,g=[[]],y=[[]];for(let w=0;w<f&&!this._stopTrainingRequested;++w){const x=performance.now(),v=yield this._localModel.fit(l,i,{epochs:1,batchSize:m,yieldEvery:"epoch"}),C=(performance.now()-x)/1e3,k=v.history.loss[0],T=v.history.acc[0];g[0].push({x:w,y:k}),y[0].push({x:w,y:T}),s.i=w,s.iterations=f,s.modelFitTime=C,s.lossValues=g,s.accuracyValues=y,self.postMessage({type:"status",payload:s})}o.dispose(),i.dispose(),l.dispose(),this._localIsTraining=!1,this._resetModelRequested?this.resetModel():(s.isTraining=!1,s.isTrained=!0,self.postMessage({type:"status",payload:s}));const b=ji();return b.add(this._mobileNetModel),b.add(this._localModel),this._localModel=b,p.dispose(),!0})}predict(e){return O(this,null,function*(){const{imagePixels:t}=e.data;if(this._mobileNetModel===null)return console.log("MLModelWorker: MobileNet v3 not loaded!"),!1;if(this._localModel===null)return console.log("MLModelWorker: Local model not loaded!"),!1;if(this._trainingData===null)return console.log("MLModelWorker: Training data not loaded!"),!1;if(!t)return console.log("MLModelWorker: No image data!"),!1;const s=performance.now(),r=Bt(new Float32Array(t.tensorData),t.tensorShape,t.tensorDtype),a=P(()=>this._localModel.predict(r)),o=yield a.data();let i=-1,l=-1;const c=new sg;for(let p=0;p<o.length;p++)o[p]>l&&(c.output.push({label:this._trainingData.classes[p].name,confidence:o[p]}),i=p);c.predictionIdx=i;const h=(performance.now()-s)/1e3,d=new pl;d.isTrained=!0,d.isPrediction=!0,d.modelPredictTime=h,d.predictions=c,be(a),self.postMessage({type:"status",payload:d})})}};ce(fa,"_instance",null);let rg=fa;self.onmessage=n=>O(this,null,function*(){rg.getInstance().onmessage(n)})})();
|
|
22174
|
+
*/const Qm="tfjs-speech-commands-saved-model-metadata",a8="indexeddb://tfjs-speech-commands-model/";let eg={localStorage:typeof window=="undefined"?null:window.localStorage};function o8(n){return n.split(".").slice(0,2).join(".")}const yS="0.5.4",uh=.25,mo=class mo{constructor(e,t,s){ce(this,"MODEL_URL_PREFIX",`https://storage.googleapis.com/tfjs-models/tfjs/speech-commands/v${o8(yS)}/browser_fft`);ce(this,"SAMPLE_RATE_HZ",44100);ce(this,"FFT_SIZE",1024);ce(this,"DEFAULT_SUPPRESSION_TIME_MILLIS",0);ce(this,"model");ce(this,"modelWithEmbeddingOutput");ce(this,"vocabulary");ce(this,"parameters");ce(this,"words");ce(this,"streaming",!1);ce(this,"nonBatchInputShape");ce(this,"elementsPerExample");ce(this,"audioDataExtractor");ce(this,"transferRecognizers",{});ce(this,"modelArtifactsOrURL");ce(this,"metadataOrURL");ce(this,"secondLastBaseDenseLayer");S(t==null&&s==null||t!=null&&s!=null,()=>"modelURL and metadataURL must be both provided or both not provided."),t==null?(e==null?e=mo.DEFAULT_VOCABULARY_NAME:S(mo.VALID_VOCABULARY_NAMES.indexOf(e)!==-1,()=>`Invalid vocabulary name: '${e}'`),this.vocabulary=e,this.modelArtifactsOrURL=`${this.MODEL_URL_PREFIX}/${this.vocabulary}/model.json`,this.metadataOrURL=`${this.MODEL_URL_PREFIX}/${this.vocabulary}/metadata.json`):(S(e==null,()=>"vocabulary name must be null or undefined when modelURL is provided"),this.modelArtifactsOrURL=t,this.metadataOrURL=s),this.parameters={sampleRateHz:this.SAMPLE_RATE_HZ,fftSize:this.FFT_SIZE}}listen(e,t){return O(this,null,function*(){if(this.streaming)throw new Error("Cannot start streaming again when streaming is ongoing.");console.log("in listen: ensuring model is loaded"),yield this.ensureModelLoaded(),t==null&&(t={});let s=t.probabilityThreshold==null?0:t.probabilityThreshold;if(t.includeEmbedding&&(s=0),S(s>=0&&s<=1,()=>`Invalid probabilityThreshold value: ${s}`),t.invokeCallbackOnNoiseAndUnknown==null||t.invokeCallbackOnNoiseAndUnknown,t.includeEmbedding,t.suppressionTimeMillis<0)throw new Error(`suppressionTimeMillis is expected to be >= 0, but got ${t.suppressionTimeMillis}`);const r=t.overlapFactor==null?.5:t.overlapFactor;S(r>=0&&r<1,()=>`Expected overlapFactor to be >= 0 and < 1, but got ${r}`);const a=(i,l)=>O(this,null,function*(){const c=hl(i);let u,h;t.includeEmbedding?(yield this.ensureModelWithEmbeddingOutputCreated(),[u,h]=this.modelWithEmbeddingOutput.predict(c)):u=this.model.predict(c);const d=yield u.data(),p=u.argMax(-1);(yield p.data())[0];const f=Math.max(...d);if(be([u,p,c]),f<s)return!1;{let m;t.includeSpectrogram&&(m={data:yield i.data(),frameSize:this.nonBatchInputShape[1]});let g=!0;return e({scores:d,spectrogram:m,embedding:h}),g}}),o=t.suppressionTimeMillis==null?this.DEFAULT_SUPPRESSION_TIME_MILLIS:t.suppressionTimeMillis;this.audioDataExtractor=new Jm({sampleRateHz:this.parameters.sampleRateHz,numFramesPerSpectrogram:this.nonBatchInputShape[0],columnTruncateLength:this.nonBatchInputShape[1],suppressionTimeMillis:o,spectrogramCallback:a,overlapFactor:r}),yield this.audioDataExtractor.startStreamedInput(),this.streaming=!0})}ensureModelLoaded(){return O(this,null,function*(){if(this.model!=null)return;yield this.ensureMetadataLoaded();let e;if(typeof this.modelArtifactsOrURL=="string"?e=yield Hi(this.modelArtifactsOrURL):e=yield Hi(Pb(this.modelArtifactsOrURL.modelTopology||{},this.modelArtifactsOrURL.weightSpecs,this.modelArtifactsOrURL.weightData)),e.inputs.length!==1)throw new Error(`Expected model to have 1 input, but got a model with ${e.inputs.length} inputs`);if(e.inputs[0].shape.length!==4)throw new Error(`Expected model to have an input shape of rank 4, but got an input shape of rank ${e.inputs[0].shape.length}`);if(e.inputs[0].shape[3]!==1)throw new Error(`Expected model to have an input shape with 1 as the last dimension, but got input shape${JSON.stringify(e.inputs[0].shape[3])}}`);const t=e.outputShape;if(t.length!==2)throw new Error(`Expected loaded model to have an output shape of rank 2,but received shape ${JSON.stringify(t)}`);if(t[1]!==this.words.length)throw new Error(`Mismatch between the last dimension of model's output shape (${t[1]}) and number of words (${this.words.length}).`);this.model=e,this.freezeModel(),this.nonBatchInputShape=e.inputs[0].shape.slice(1),this.elementsPerExample=1,e.inputs[0].shape.slice(1).forEach(a=>this.elementsPerExample*=a),this.warmUpModel();const s=this.parameters.fftSize/this.parameters.sampleRateHz*1e3,r=e.inputs[0].shape[1];this.parameters.spectrogramDurationMillis=r*s})}ensureModelWithEmbeddingOutputCreated(){return O(this,null,function*(){if(this.modelWithEmbeddingOutput!=null)return;yield this.ensureModelLoaded();let e;for(let t=this.model.layers.length-2;t>=0;--t)if(this.model.layers[t].getClassName()==="Dense"){e=this.model.layers[t];break}if(e==null)throw new Error("Failed to find second last dense layer in the original model.");this.modelWithEmbeddingOutput=Su({inputs:this.model.inputs,outputs:[this.model.outputs[0],e.output]})})}warmUpModel(){P(()=>{const e=ct([1].concat(this.nonBatchInputShape));for(let t=0;t<3;++t)this.model.predict(e)})}ensureMetadataLoaded(){return O(this,null,function*(){if(this.words!=null)return;const e=typeof this.metadataOrURL=="string"?yield G5(this.metadataOrURL):this.metadataOrURL;if(e.wordLabels==null){const t=e.words;if(t==null)throw new Error('Cannot find field "words" or "wordLabels" in metadata JSON file');this.words=t}else this.words=e.wordLabels})}stopListening(){return O(this,null,function*(){yield this.audioDataExtractor.stop(),this.streaming=!1})}isListening(){return this.streaming}wordLabels(){return this.words}params(){return this.parameters}modelInputShape(){if(this.model==null)throw new Error("Model has not been loaded yet. Load model by calling ensureModelLoaded(), recognize(), or listen().");return this.model.inputs[0].shape}recognize(e,t){return O(this,null,function*(){t==null&&(t={}),yield this.ensureModelLoaded(),e==null&&(e=(yield this.recognizeOnline()).data);let s,r,a;if(e instanceof Oe)this.checkInputTensorShape(e),r=e,s=e.shape[0];else{if(e.length%this.elementsPerExample)throw new Error(`The length of the input Float32Array ${e.length} is not divisible by the number of tensor elements per per example expected by the model ${this.elementsPerExample}.`);s=e.length/this.elementsPerExample,r=ab(e,[s].concat(this.nonBatchInputShape))}const o={scores:[]};if(t.includeEmbedding){yield this.ensureModelWithEmbeddingOutputCreated();const i=this.modelWithEmbeddingOutput.predict(r);a=i[0],o.embedding=i[1]}else a=this.model.predict(r);if(s===1)o.scores=yield a.data();else{const i=Cn(a),l=i.map(c=>c.data());o.scores=yield Promise.all(l),be(i)}return t.includeSpectrogram&&(o.spectrogram={data:e instanceof Oe?yield e.data():e,frameSize:this.nonBatchInputShape[1]}),be(a),o})}recognizeOnline(){return O(this,null,function*(){return new Promise((e,t)=>{const s=r=>O(this,null,function*(){const a=hl(r);return yield this.audioDataExtractor.stop(),e({data:yield a.data(),frameSize:this.nonBatchInputShape[1]}),a.dispose(),!1});this.audioDataExtractor=new Jm({sampleRateHz:this.parameters.sampleRateHz,numFramesPerSpectrogram:this.nonBatchInputShape[0],columnTruncateLength:this.nonBatchInputShape[1],suppressionTimeMillis:0,spectrogramCallback:s,overlapFactor:0})})})}createTransfer(e){if(this.model==null)throw new Error("Model has not been loaded yet. Load model by calling ensureModelLoaded(), recognizer(), or listen().");S(e!=null&&typeof e=="string"&&e.length>1,()=>`Expected the name for a transfer-learning recognized to be a non-empty string, but got ${JSON.stringify(e)}`),S(this.transferRecognizers[e]==null,()=>`There is already a transfer-learning model named '${e}'`);const t=new i8(e,this.parameters,this.model);return this.transferRecognizers[e]=t,t}freezeModel(){for(const e of this.model.layers)e.trainable=!1}checkInputTensorShape(e){const t=this.model.inputs[0].shape.length;if(e.shape.length!==t)throw new Error(`Expected input Tensor to have rank ${t}, but got rank ${e.shape.length} that differs `);const s=e.shape.slice(1),r=this.model.inputs[0].shape.slice(1);if(!Ee(s,r))throw new Error(`Expected input to have shape [null,${r}], but got shape [null,${s}]`)}};ce(mo,"VALID_VOCABULARY_NAMES",["18w","directional4w"]),ce(mo,"DEFAULT_VOCABULARY_NAME","18w");let fo=mo;class i8 extends fo{constructor(t,s,r){super();ce(this,"dataset");ce(this,"transferHead");this.name=t,this.parameters=s,this.baseModel=r,S(t!=null&&typeof t=="string"&&t.length>0,()=>`The name of a transfer model must be a non-empty string, but got ${JSON.stringify(t)}`),this.nonBatchInputShape=this.baseModel.inputs[0].shape.slice(1),this.words=null,this.dataset=new gS}addExamples(t){return O(this,null,function*(){for(const s of t)for(const r of s.samples)console.log(`class ${s.name}, sample ${r}, has timeDataQueue length ${r.timeDataQueue.length}, and freqDataQueue length ${r.freqDataQueue.length}`),yield this.collectExample(s.name,r,{durationMultiplier:1,includeRawAudio:!0})})}collectExample(t,s,r){return O(this,null,function*(){if(S(!this.streaming,()=>"Cannot start collection of transfer-learning example because a streaming recognition or transfer-learning example collection is ongoing"),S(t!=null&&typeof t=="string"&&t.length>0,()=>"Must provide a non-empty string when collecting transfer-learning example"),r==null&&(r={}),r.durationMultiplier!=null&&r.durationSec!=null)throw new Error("durationMultiplier and durationSec are mutually exclusive, but are both specified.");let a;if(r.durationSec!=null){S(r.durationSec>0,()=>`Expected durationSec to be > 0, but got ${r.durationSec}`);const l=this.parameters.fftSize/this.parameters.sampleRateHz;a=Math.ceil(r.durationSec/l)}else r.durationMultiplier!=null?(S(r.durationMultiplier>=1,()=>`Expected duration multiplier to be >= 1, but got ${r.durationMultiplier}`),a=Math.round(this.nonBatchInputShape[0]*r.durationMultiplier)):a=this.nonBatchInputShape[0];r.snippetDurationSec!=null&&(S(r.snippetDurationSec>0,()=>`snippetDurationSec is expected to be > 0, but got ${r.snippetDurationSec}`),S(r.onSnippet!=null,()=>"onSnippet must be provided if snippetDurationSec is provided.")),r.onSnippet!=null&&S(r.snippetDurationSec!=null,()=>"snippetDurationSec must be provided if onSnippet is provided.");const i=this.parameters.fftSize/this.parameters.sampleRateHz*a;return this.streaming=!0,new Promise(l=>{const c=r.snippetDurationSec==null?1:r.snippetDurationSec/i,u=1-c,h=Math.round(1/c);let d=0,p=-1;const f=[],m=(g,y)=>O(this,null,function*(){if(r.onSnippet==null){const b=hl(g);this.dataset.addExample({label:t,spectrogram:{data:yield b.data(),frameSize:this.nonBatchInputShape[1]},rawAudio:r.includeRawAudio?{data:yield y.data(),sampleRateHz:this.audioDataExtractor.sampleRateHz}:void 0}),b.dispose(),yield this.audioDataExtractor.stop(),this.streaming=!1,this.collateTransferWords(),l({data:yield g.data(),frameSize:this.nonBatchInputShape[1]})}else{const b=yield g.data();p===-1&&(p=b.length);let w=p-1;for(;b[w]!==0&&w>=0;)w--;const x=p-w-1;p=w+1;const v=b.slice(b.length-x,b.length);if(f.push(v),r.onSnippet!=null&&r.onSnippet({data:v,frameSize:this.nonBatchInputShape[1]}),d++===h){yield this.audioDataExtractor.stop(),this.streaming=!1,this.collateTransferWords();const C={data:H5(j5(f)),frameSize:this.nonBatchInputShape[1]};this.dataset.addExample({label:t,spectrogram:C,rawAudio:r.includeRawAudio?{data:yield y.data(),sampleRateHz:this.audioDataExtractor.sampleRateHz}:void 0}),l(C)}}return!1});this.audioDataExtractor=new Jm({sampleRateHz:this.parameters.sampleRateHz,numFramesPerSpectrogram:a,columnTruncateLength:this.nonBatchInputShape[1],suppressionTimeMillis:0,spectrogramCallback:m,overlapFactor:u,includeRawAudio:r.includeRawAudio}),this.audioDataExtractor.start(s)})})}clearExamples(){S(this.words!=null&&this.words.length>0&&!this.dataset.empty(),()=>`No transfer learning examples exist for model name ${this.name}`),this.dataset.clear(),this.words=null}countExamples(){if(this.dataset.empty())throw new Error(`No examples have been collected for transfer-learning model named '${this.name}' yet.`);return this.dataset.getExampleCounts()}getExamples(t){return this.dataset.getExamples(t)}setExampleKeyFrameIndex(t,s){this.dataset.setExampleKeyFrameIndex(t,s)}removeExample(t){this.dataset.removeExample(t),this.collateTransferWords()}isDatasetEmpty(){return this.dataset.empty()}loadExamples(t,s=!1){const r=new gS(t);s&&this.clearExamples();const a=r.getVocabulary();for(const o of a){const i=r.getExamples(o);for(const l of i)this.dataset.addExample(l.example)}this.collateTransferWords()}serializeExamples(t){return this.dataset.serialize(t)}collateTransferWords(){this.words=this.dataset.getVocabulary()}collectTransferDataAsTensors(t,s){const r=this.nonBatchInputShape[0];t=t||uh;const a=Math.round(t*r),o=this.dataset.getData(void 0,cg({numFrames:r,hopFrames:a},s));return{xs:o.xs,ys:o.ys}}collectTransferDataAsTfDataset(t,s=.15,r=32,a){const o=this.nonBatchInputShape[0];t=t||uh;const i=Math.round(t*o);return this.dataset.getData(void 0,cg({numFrames:o,hopFrames:i,getDataset:!0,datasetBatchSize:r,datasetValidationSplit:s},a))}train(t){return O(this,null,function*(){S(this.words!=null&&this.words.length>0,()=>`Cannot train transfer-learning model '${this.name}' because no transfer learning example has been collected.`),S(this.words.length>1,()=>`Cannot train transfer-learning model '${this.name}' because only 1 word label ('${JSON.stringify(this.words)}') has been collected for transfer learning. Requires at least 2.`),t.fineTuningEpochs!=null&&S(t.fineTuningEpochs>=0&&Number.isInteger(t.fineTuningEpochs),()=>`If specified, fineTuningEpochs must be a non-negative integer, but received ${t.fineTuningEpochs}`),t==null&&(t={}),this.model==null&&this.createTransferModelFromBaseModel(),this.secondLastBaseDenseLayer.trainable=!1,this.model.compile({loss:"categoricalCrossentropy",optimizer:t.optimizer||"sgd",metrics:["acc"]});const s=t.fitDatasetDurationMillisThreshold==null?6e4:t.fitDatasetDurationMillisThreshold;return this.dataset.durationMillis()>s?(console.log(`Detected large dataset: total duration = ${this.dataset.durationMillis()} ms > ${s} ms. Training transfer model using fitDataset() instead of fit()`),this.trainOnDataset(t)):this.trainOnTensors(t)})}trainOnDataset(t){return O(this,null,function*(){S(t.epochs>0,()=>"Invalid config!.epochs");const s=t.batchSize==null?32:t.batchSize,r=t.windowHopRatio||uh,[a,o]=this.collectTransferDataAsTfDataset(r,t.validationSplit,s,{augmentByMixingNoiseRatio:t.augmentByMixingNoiseRatio}),i=dt(),l=yield this.model.fitDataset(a,{epochs:t.epochs,validationData:t.validationSplit>0?o:void 0,callbacks:t.callback==null?void 0:[t.callback]});if(console.log(`fitDataset() took ${(dt()-i).toFixed(2)} ms`),t.fineTuningEpochs!=null&&t.fineTuningEpochs>0){const c=dt(),u=yield this.fineTuningUsingTfDatasets(t,a,o);return console.log(`fitDataset() (fine-tuning) took ${(dt()-c).toFixed(2)} ms`),[l,u]}else return l})}trainOnTensors(t){return O(this,null,function*(){const s=t.windowHopRatio||uh,{xs:r,ys:a}=this.collectTransferDataAsTensors(s,{augmentByMixingNoiseRatio:t.augmentByMixingNoiseRatio});console.log(`Training data: xs.shape = ${r.shape}, ys.shape = ${a.shape}`);let o,i,l=null;try{if(t.validationSplit!=null){const u=X5(r,a,t.validationSplit);o=u.trainXs,i=u.trainYs,l=[u.valXs,u.valYs]}else o=r,i=a;const c=yield this.model.fit(o,i,{epochs:t.epochs==null?20:t.epochs,validationData:l,batchSize:t.batchSize,callbacks:t.callback==null?void 0:[t.callback]});if(t.fineTuningEpochs!=null&&t.fineTuningEpochs>0){const u=yield this.fineTuningUsingTensors(t,o,i,l);return[c,u]}else return c}finally{be([r,a,o,i,l])}})}fineTuningUsingTfDatasets(t,s,r){return O(this,null,function*(){const a=this.secondLastBaseDenseLayer.trainable;this.secondLastBaseDenseLayer.trainable=!0;const o=t.fineTuningOptimizer==null?"sgd":t.fineTuningOptimizer;this.model.compile({loss:"categoricalCrossentropy",optimizer:o,metrics:["acc"]});const i=yield this.model.fitDataset(s,{epochs:t.fineTuningEpochs,validationData:r,callbacks:t.callback==null?void 0:[t.callback]});return this.secondLastBaseDenseLayer.trainable=a,i})}fineTuningUsingTensors(t,s,r,a){return O(this,null,function*(){const o=this.secondLastBaseDenseLayer.trainable;this.secondLastBaseDenseLayer.trainable=!0;const i=t.fineTuningOptimizer==null?"sgd":t.fineTuningOptimizer;this.model.compile({loss:"categoricalCrossentropy",optimizer:i,metrics:["acc"]});const l=yield this.model.fit(s,r,{epochs:t.fineTuningEpochs,validationData:a,batchSize:t.batchSize,callbacks:t.fineTuningCallback==null?void 0:[t.fineTuningCallback]});return this.secondLastBaseDenseLayer.trainable=o,l})}evaluate(t){return O(this,null,function*(){S(t.wordProbThresholds!=null&&t.wordProbThresholds.length>0,()=>"Received null or empty wordProbThresholds");const s=0;return S(this.words[s]===dl,()=>`Cannot perform evaluation when the first tag is not ${dl}`),P(()=>{const r=[];let a=0;const{xs:o,ys:i}=this.collectTransferDataAsTensors(t.windowHopRatio),l=i.argMax(-1).dataSync(),c=this.model.predict(o),u=Sn(Ae(c,[0,1],[c.shape[0],c.shape[1]-1]),-1),h=c.shape[0];for(let d=0;d<t.wordProbThresholds.length;++d){const p=t.wordProbThresholds[d],f=u.greater(pe(p)).dataSync();let m=0,g=0,y=0,b=0;for(let v=0;v<h;++v)l[v]===s?(m++,f[v]&&y++):(g++,f[v]&&b++);const w=y/m,x=b/g;r.push({probThreshold:p,fpr:w,tpr:x}),console.log(`ROC thresh=${p}: fpr=${w.toFixed(4)}, tpr=${x.toFixed(4)}`),d>0&&(a+=Math.abs(r[d-1].fpr-r[d].fpr)*(r[d-1].tpr+r[d].tpr)/2)}return{rocCurve:r,auc:a}})})}createTransferModelFromBaseModel(t){S(this.words!=null,()=>"No word example is available for tranfer-learning model of name "+this.name);const s=this.baseModel.layers;let r=s.length-2;for(;r>=0&&s[r].getClassName().toLowerCase()!=="dense";)r--;if(r<0)throw new Error("Cannot find a hidden dense layer in the base model.");this.secondLastBaseDenseLayer=s[r];const a=this.secondLastBaseDenseLayer.output;this.transferHead=ji(),this.transferHead.add(om({units:this.words.length,activation:"softmax",inputShape:a.shape.slice(1),name:"NewHeadDense"})),t&&this.transferHead.setWeights(t);const o=this.transferHead.apply(a);this.model=Su({inputs:this.baseModel.inputs,outputs:o})}modelInputShape(){return this.baseModel.inputs[0].shape}getMetadata(){return{tfjsSpeechCommandsVersion:yS,modelName:this.name,timeStamp:new Date().toISOString(),wordLabels:this.wordLabels()}}getAudioStream(t){t.timeData&&this.audioDataExtractor&&(this.audioDataExtractor.streamedTimeData=t.timeData),t.freqData&&this.audioDataExtractor&&(this.audioDataExtractor.streamedFreqData=t.freqData)}save(t){return O(this,null,function*(){const s=t!=null;if(t=t||bS(this.name),!s){const r=eg.localStorage.getItem(Qm),a=r==null?{}:JSON.parse(r);a[this.name]=this.getMetadata(),eg.localStorage.setItem(Qm,JSON.stringify(a))}return console.log(`Saving model to ${t}`),this.model.save(t)})}load(t){return O(this,null,function*(){const s=t!=null;if(t=t||bS(this.name),!s){const r=JSON.parse(eg.localStorage.getItem(Qm)||"");if(r==null||r[this.name]==null)throw new Error(`Cannot find metadata for transfer model named ${this.name}"`);this.words=r[this.name].wordLabels,console.log(`Loaded word list for model named ${this.name}: ${this.words}`)}this.model=yield Hi(t),console.log(`Loaded model from ${t}:`),this.model.summary()})}createTransfer(t){throw new Error("Creating transfer-learned recognizer from a transfer-learned recognizer is not supported.")}}function bS(n){return`${a8}${n}`}console.log("running MLModelWorker.ts");const l8=1,c8="conv_pw_13_relu",u8="out_relu",tg=.25,ng=.35,xS=224;class sg{constructor(){ce(this,"output",[]);ce(this,"predictionIdx",-1)}}class pl{constructor(){ce(this,"isTraining",!1);ce(this,"isTrained",!1);ce(this,"isPrediction",!1);ce(this,"i",0);ce(this,"iterations",0);ce(this,"modelFitTime",0);ce(this,"lossValues",[]);ce(this,"accuracyValues",[]);ce(this,"accuracy",0);ce(this,"isCorrect",[]);ce(this,"examples",[]);ce(this,"predictions",new sg);ce(this,"modelPredictTime",0)}}const wS=(n,e)=>{if(n===1){if(e!==.25&&e!==.5&&e!==.75&&e!==1)return console.warn("Invalid alpha. Options are: 0.25, 0.50, 0.75 or 1.00."),console.log("Loading model with alpha: ",tg.toFixed(2)),tg}else if(e!==.35&&e!==.5&&e!==.75&&e!==1)return console.warn("Invalid alpha. Options are: 0.35, 0.50, 0.75 or 1.00."),console.log("Loading model with alpha: ",ng.toFixed(2)),ng;return e},h8=n=>{if(n=n||{},n.checkpointUrl&&n.trainingLayer)return(n.alpha||n.version)&&console.warn("Checkpoint URL passed to modelOptions, alpha options are ignored"),[n.checkpointUrl,n.trainingLayer];if(n.version=n.version||l8,n.version===1){n.alpha=n.alpha||tg,n.alpha=wS(n.version,n.alpha),console.log(`Loading mobilenet ${n.version} and alpha ${n.alpha}`);let e=n.alpha.toFixed(2);return e==="1.00"&&(e="1.0"),[`https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v1_${e}_${xS}/model.json`,c8]}else{if(n.version===2)return n.alpha=n.alpha||ng,n.alpha=wS(n.version,n.alpha),console.log(`Loading mobilenet ${n.version} and alpha ${n.alpha}`),[`https://storage.googleapis.com/teachable-machine-models/mobilenet_v2_weights_tf_dim_ordering_tf_kernels_${n.alpha.toFixed(2)}_${xS}_no_top/model.json`,u8];throw new Error(`MobileNet V${n.version} doesn't exist`)}},fa=class fa{constructor(){ce(this,"_mobileNetModel",null);ce(this,"_stopTrainingRequested",!1);ce(this,"_resetModelRequested",!1);ce(this,"_localIsTraining",!1);ce(this,"_localModel",null);ce(this,"_speechRecognizer",null);ce(this,"_trainingData",null);ce(this,"seed")}static getInstance(){return fa._instance||(fa._instance=new fa),fa._instance}loadTruncatedMobileNet(e){return O(this,null,function*(){const[t,s]=h8(e),r=yield Hi(t);if(e&&e.version===1){const a=r.getLayer(s),o=Su({inputs:r.inputs,outputs:a.output}),i=ji();return i.add(o),i.add(WF()),i}else{const a=r.getLayer(s),o=Su({inputs:r.inputs,outputs:a.output}),i=ji();return i.add(o),i.add(UF({})),i}})}loadMobilenet(){return O(this,null,function*(){const t=yield ZO("https://tfhub.dev/google/tfjs-model/imagenet/mobilenet_v3_small_100_224/feature_vector/5/default/1",{fromTFHub:!0});return t!==void 0&&P(()=>{t.predict(ct([1,cS,uS,3]))}),t})}resetModel(){this._mobileNetModel=null,this._stopTrainingRequested=!1,this._resetModelRequested=!1,this._localIsTraining=!1,this._localModel=null,this._trainingData=null;const e=new pl;self.postMessage({type:"status",payload:e})}onmessage(e){return O(this,null,function*(){switch(e.data.command){case"PREPARE_ENGINE":console.log("MLModelWorker: prepare engine"),this._mobileNetModel?self.postMessage({type:"ready"}):(this._mobileNetModel=yield this.loadTruncatedMobileNet(),self.postMessage({type:"ready"}));break;case"AUDIO_START_LISTENING":this._speechRecognizer&&this._speechRecognizer.listen(y=>O(this,null,function*(){let b=-1,w=-1;const x=new sg;for(let $=0;$<y.scores.length;$++){const C=y.scores[$];C>w&&(x.output.push({label:this._trainingData.classes.sort((k,T)=>k.name<T.name?-1:k.name>T.name?1:0)[$].name,confidence:C}),b=$)}x.predictionIdx=b;const v=new pl;v.isTrained=!0,v.isPrediction=!0,v.predictions=x,self.postMessage({type:"status",payload:v})}));break;case"STOP_AUDIO_LISTENING":this._speechRecognizer&&this._speechRecognizer.stopListening();break;case"TRAIN":this._stopTrainingRequested=!1,this._resetModelRequested=!1;const t=e.data.modelType;t==="image-device"?yield this.train(e):t==="audio"&&(yield this.trainAudio(e));break;case"PREDICT":yield this.predict(e);break;case"STOP_TRAINING":this._localIsTraining&&(this._stopTrainingRequested=!0);break;case"RESET_MODEL":this._localIsTraining?(this._stopTrainingRequested=!0,this._resetModelRequested=!0):this.resetModel();break;case"SAVE_MODEL":if(this._localModel){let y=null,b=null,w=null;if(e.data.modelType==="audio"){const x=this._localModel.layers[this._localModel.layers.length-1];b=x.weights.map(C=>C.read().dataSync()),w=x.weights;const $={config:x.getConfig(),weights:b};y=JSON.stringify($)}else e.data.modelType==="image-device"&&(this._localModel=this._localModel,y=this._localModel.toJSON(),b=this._localModel.weights.map(x=>x.read().dataSync()),w=this._localModel.weights);self.postMessage({type:"save_model",payload:{modelJSON:y,weights:{weightBuffers:b,weightInfo:w}}})}break;case"LOAD_TM_MODEL":const{tmModelUrl:s}=e.data;if(this._localModel&&this._localModel.dispose(),s){console.debug("MLModelWorker: Loading TM model...");const b=yield(yield fetch(s.replace("model.json","metadata.json"))).json();this._localModel=yield Hi(s),console.log("modelMetadataJson",b),console.log("modelMetadataJson.labels",b.labels),console.log("modelMetadataJson.wordLabels",b.wordLabels);const w=b.labels?"image-device":"audio";if(console.log("modelType",w),w==="audio"){const x=new fo;yield x.ensureModelLoaded(),this._speechRecognizer=x.createTransfer("modelNameExample"),this._speechRecognizer.words=b.wordLabels,this._speechRecognizer.model=this._localModel}self.postMessage({type:"load_model",payload:{}})}break;case"LOAD_AUDIO_MODEL":this._localModel&&this._localModel.dispose();const{modelJSON:r,weightBuffers:a,weightInfo:o,audioAlphabeticalWords:i}=e.data,l=new fo;yield l.ensureModelLoaded(),this._speechRecognizer=l.createTransfer("modelNameExample");const c=a.map((y,b)=>{const w=o[b].shape,x=o[b].dtype;return Bt(y,w,x)});this._speechRecognizer.words=i,this._speechRecognizer.createTransferModelFromBaseModel(c),self.postMessage({type:"load_model",payload:{}});break;case"LOAD_MODEL":this._localModel&&this._localModel.dispose();const{modelJSON:u,weightBuffers:h,weightInfo:d}=e.data;console.debug("MLModelWorker: Loading MM model...");const p=JSON.parse(u);console.debug("MLModelWorker: Loading model...",e.data);const f=yield vF(p);console.log("model",f);const m=h.map((y,b)=>{const w=d[b].shape,x=d[b].dtype;return Bt(y,w,x)});console.debug("MLModelWorker: Setting weights...",m),f.setWeights(m),this._localModel=f,console.debug("MLModelWorker: Model loaded!"),self.postMessage({type:"load_model",payload:{}});break;case"SET_TRAINING_DATA":this._trainingData=e.data.trainingData;break;case"STREAM_AUDIO":const{streamedAudioData:g}=e.data;this._speechRecognizer&&this._speechRecognizer.getAudioStream(g);break}})}imgToTensor(e,t){return P(()=>{let s=EA(e);return t&&(s=Pn.resizeBilinear(s,t)),this.cropImage(s).expandDims(0).toFloat().div(pe(127)).sub(pe(1))})}cropImage(e){const t=Math.min(e.shape[0],e.shape[1]),r=e.shape[0]/2-t/2,o=e.shape[1]/2-t/2;return e.slice([r,o,0],[t,t,3])}convertUtilsPixelsToTensor(e){const{pixelsBase64:t,height:s,width:r,depth:a}=e,o=Uint8Array.from(atob(t),u=>u.charCodeAt(0)),i=Ua(o,[s,r,a],"int32"),c=Pn.resizeBilinear(i,[uS,cS],!0).div(255);return this._mobileNetModel.predict(c.expandDims())}trainAudio(e){return O(this,null,function*(){console.log("event",e);const t=e.data.trainingData;if(!t)return console.log("MLModelWorker: No audio training data!"),!1;const s=t;this._trainingData=s;const r=new fo;this._localIsTraining=!0;const a=new pl;a.isTraining=!0,yield r.ensureModelLoaded(),console.log("MLModelWorker: Speech model loaded!"),console.log("baseRecognizer parameters:",r.params()),console.log("baseRecognizer input shape:",r.modelInputShape());const o=r.createTransfer("modelNameExample");yield o.addExamples(s.classes),console.log(o.countExamples());const i=e.data.trainIterations,l=performance.now(),c=[[]],u=[[]];return yield o.train({epochs:i,callback:{onEpochEnd:(h,d)=>O(this,null,function*(){const f=(performance.now()-l)/1e3,m=d.loss,g=d.acc;c[0].push({x:h,y:m}),u[0].push({x:h,y:g}),a.i=h,a.iterations=i,a.modelFitTime=f,a.lossValues=c,a.accuracyValues=u,self.postMessage({type:"status",payload:a})}),onTrainEnd:h=>O(this,null,function*(){this._localIsTraining=!1,this._resetModelRequested?this.resetModel():(a.isTraining=!1,a.isTrained=!0,self.postMessage({type:"status",payload:a})),this._speechRecognizer=o,this._localModel=o.model})}}),!0})}train(e){return O(this,null,function*(){if(!this._mobileNetModel)if(this._mobileNetModel=yield this.loadTruncatedMobileNet(),this._mobileNetModel)console.log("MLModelWorker: mobilenet loaded");else return console.log("MLModelWorker: MobileNet not loaded!"),!1;if(!e.data.trainingData)return console.log("MLModelWorker: No training data!"),!1;const t=e.data.trainingData;if(t.classes.length===0)return console.log("MLModelWorker: No classes to train!"),!1;if(t.classes.some(w=>w.samples.length===0))return console.log("MLModelWorker: At least one class has no samples!"),!1;this._localIsTraining=!0;const s=new pl;s.isTraining=!0,this._trainingData=t;const r=t.classes.flatMap(w=>w.samples.map(({tensorData:x,tensorShape:v,tensorDtype:$})=>{const C=Bt(new Float32Array(x),v,$),k=this._mobileNetModel.predict(C),T=k.dataSync();return C.dispose(),k.dispose(),T})),a=t.classes.flatMap((w,x)=>w.samples.map(()=>x));go(r,a);const o=ft(a,"int32"),i=Vr(o,t.classes.length),l=Wt(r),c=this._mobileNetModel.outputs[0].shape.slice(1),u=U(c),h=E_({});this._localModel=ji(),this._localModel.add(om({inputShape:[u],units:100,activation:"relu",kernelInitializer:h,useBias:!0})),this._localModel.add(om({kernelInitializer:h,useBias:!1,activation:"softmax",units:t.classes.length}));const d=.001,p=qr.adam(d);this._localModel.compile({optimizer:p,loss:"categoricalCrossentropy",metrics:["accuracy"]});const{trainIterations:f,batchSize:m}=e.data,g=[[]],y=[[]];for(let w=0;w<f&&!this._stopTrainingRequested;++w){const x=performance.now(),v=yield this._localModel.fit(l,i,{epochs:1,batchSize:m,yieldEvery:"epoch"}),C=(performance.now()-x)/1e3,k=v.history.loss[0],T=v.history.acc[0];g[0].push({x:w,y:k}),y[0].push({x:w,y:T}),s.i=w,s.iterations=f,s.modelFitTime=C,s.lossValues=g,s.accuracyValues=y,self.postMessage({type:"status",payload:s})}o.dispose(),i.dispose(),l.dispose(),this._localIsTraining=!1,this._resetModelRequested?this.resetModel():(s.isTraining=!1,s.isTrained=!0,self.postMessage({type:"status",payload:s}));const b=ji();return b.add(this._mobileNetModel),b.add(this._localModel),this._localModel=b,p.dispose(),!0})}predict(e){return O(this,null,function*(){const{imagePixels:t}=e.data;if(this._mobileNetModel===null)return console.log("MLModelWorker: MobileNet v3 not loaded!"),!1;if(this._localModel===null)return console.log("MLModelWorker: Local model not loaded!"),!1;if(this._trainingData===null)return console.log("MLModelWorker: Training data not loaded!"),!1;if(!t)return console.log("MLModelWorker: No image data!"),!1;const s=performance.now(),r=Bt(new Float32Array(t.tensorData),t.tensorShape,t.tensorDtype),a=P(()=>this._localModel.predict(r)),o=yield a.data();let i=-1,l=-1;const c=new sg;for(let p=0;p<o.length;p++)o[p]>l&&(c.output.push({label:this._trainingData.classes[p].name,confidence:o[p]}),i=p);c.predictionIdx=i;const h=(performance.now()-s)/1e3,d=new pl;d.isTrained=!0,d.isPrediction=!0,d.modelPredictTime=h,d.predictions=c,be(a),self.postMessage({type:"status",payload:d})})}};ce(fa,"_instance",null);let rg=fa;self.onmessage=n=>O(this,null,function*(){rg.getInstance().onmessage(n)})})();
|