Skip to content

Trainning and Score very low #8

Description

@JpEncausse

Hi,
I made 3 trainning for world "Reflets" in French.

  • for the v1 and v2 I use only a female voice and get 0.2 with my voice 0.9 with sample
  • for the v3 I mix 3 male and female voice and got 0 confidence

Here is my Notebook :
Nanowakeword_Reflets_v3.ipynb

And the model seems ok ?

Image

The logs

 _   _               __          __   _     __          __           _ 
 | \ | |              \ \        / /  | |    \ \        / /          | |
 |  \| | __ _ _ __   __\ \  /\  / /_ _| | ____\ \  /\  / /__  _ __ __| |
 | . ` |/ _` | '_ \ / _ \ \/  \/ / _` | |/ / _ \ \/  \/ / _ \| '__/ _` |
 | |\  | (_| | | | | (_) \  /\  / (_| |   <  __/\  /\  / (_) | | | (_| |
 |_| \_|\__,_|_| |_|\___/ \/  \/ \__,_|_|\_\___| \/  \/ \___/|_|  \__,_|


STEP 1: Verifying and Preprocessing Data Directories
====================================================
Processing Noise: 100%|██████████| 1365/1365 [00:26<00:00, 51.44it/s]
Processing Rir: 100%|██████████| 1667/1667 [00:14<00:00, 112.07it/s]
WARNING:root:Directory not found, skipping preprocessing: nanowakeword_data/negative_speech
WARNING:root:Directory not found, skipping preprocessing: nanowakeword_data/positive_wakeword
INFO: Data verification and preprocessing complete.

INFO: Determining hardware-specific configurations...
STEP 2: Activating Synthetic Data Generation Engine
===================================================
INFO: Processing 10 custom negative phrases.
INFO: Generating 25 copies for EACH custom phrase.
INFO: Total custom samples prepared: 250
INFO: Target negative samples: 6000. Current custom samples: 250.
INFO: Generating 5750 auto-adversarial phrases to fill the gap.
WARNING:root:Downloading phonemizer model from https://github.com/arcosoph/phonemize/releases/download/v0.2.0/phonemize_m1.pt...
WARNING:root:The word 'reflets' was not found in the pronunciation dictionary! Using the Phonemize library to predict the phonemes.
WARNING:root:Phones for 'reflets': [R][IY][F][L][AH][T][S]
INFO: Initiating data generation pipeline for phrase: 'reflets'
INFO: Executing task 'Positive_Train': 3000 clips -> 'nanowakeword_data/positive_wakeword'
Loading voices: 100%|██████████| 3/3 [00:04<00:00,  1.54s/it]

Generating Audio: 100%|██████████| 3000/3000 [09:13<00:00,  5.42it/s]
INFO: Executing task 'Adversarial_Train': 6000 clips -> 'nanowakeword_data/negative_speech'
Generating Audio: 100%|██████████| 6000/6000 [23:06<00:00,  4.33it/s]
INFO: Synthetic data generation process finished successfully.

STEP 2.5: Activating Intelligent Configuration Engine
===================================================
Analyzing dataset characteristics...
Analyzing positive_wakeword files: 100%|██████████| 3000/3000 [00:13<00:00, 230.13it/s]
Analyzing negative_speech files: 100%|██████████| 6000/6000 [00:32<00:00, 182.49it/s]
Analyzing Noise files: 100%|██████████| 1365/1365 [00:23<00:00, 58.82it/s]Analysis complete!


                        Dataset Statistics                        
┌───────────────┬────────────────────────────────────────────────┐
│ Parameter     │ Value                                          │
├───────────────┼────────────────────────────────────────────────┤
│ H_pos         │ 0.6620500868055553                             │
│ H_neg         │ 1.6486525520833364                             │
│ H_noise_paths │ {'nanowakeword_data/Noise': 5.067988993055563} │
│ H_noise       │ 5.067988993055563                              │
│ A_noise       │ 0.05487615084446175                            │
│ N_rir         │ 1667                                           │
└───────────────┴────────────────────────────────────────────────┘
INFO: Project assets will be saved in: /content/trained_models/reflets_v3
INFO: Autotuning optimal clip duration...
INFO: Optimal clip duration autotuned to: 32000 samples (2.00 seconds).
STEP 3: Computing Acoustic Features from Audio Sources
======================================================
[nanowakeword] Required model 'melspectrogram.onnx' not found. Downloading...
melspectrogram.onnx: 100%|██████████| 1.09M/1.09M [00:00<00:00, 34.4MiB/s]
[nanowakeword] Download of 'melspectrogram.onnx' complete.
[nanowakeword] Required model 'embedding_model.onnx' not found. Downloading...
embedding_model.onnx: 100%|██████████| 1.33M/1.33M [00:00<00:00, 36.9MiB/s]
[nanowakeword] Download of 'embedding_model.onnx' complete.
Computing features: 100%|██████████| 234/234 [58:27<00:00, 14.99s/it]
Computing features: 100%|██████████| 468/468 [1:57:38<00:00, 15.08s/it]
Computing features: 100%|██████████| 53/53 [14:26<00:00, 16.35s/it]
INFO: Initializing Model and Training Components...
INFO: Using optimizer: ADAMW
INFO: Setting up learning rate scheduler: ONECYCLE
STEP 4: Starting Training Process
=================================
INFO: Using model architecture: 🤍 RNN
INFO: Debug mode ON. Logs will be saved to:
/content/trained_models/reflets_v3/2_training_artifacts/training_debug/training_debug.log
INFO: Checkpointing is ENABLED. A checkpoint will be saved every 1000 steps.
INFO: Training for 30000 steps. Model checkpointing and early stopping will activate after 4500 warm-up steps.
                           Effective Training Configuration                           
┌───────────────────────────────────────────────────────────────┬────────────────────┐
│ Parameter                                                     │ Value              │
├───────────────────────────────────────────────────────────────┼────────────────────┤
│ WARMUP_STEPS                                                  │ 4500               │
│ activation_function                                           │ relu               │
│ audio_processing.autotune_length.duration_buffer_ms           │ 750                │
│ audio_processing.autotune_length.enabled                      │ True               │
│ audio_processing.autotune_length.min_allowable_length         │ 32000              │
│ audio_processing.autotune_length.num_samples_to_inspect       │ 50                 │
│ audio_processing.autotune_length.snap_to_min_tolerance        │ 4000               │
│ augmentation_batch_size                                       │ 128                │
│ augmentation_rounds                                           │ 10                 │
│ augmentation_settings.BackgroundNoise                         │ 0.8                │
│ augmentation_settings.BandStopFilter                          │ 0.2                │
│ augmentation_settings.ColoredNoise                            │ 0.4                │
│ augmentation_settings.Distortion                              │ 0.25               │
│ augmentation_settings.Gain                                    │ 1.0                │
│ augmentation_settings.ParametricEQ                            │ 0.25               │
│ augmentation_settings.PitchShift                              │ 0.5                │
│ augmentation_settings.RIR                                     │ 0.6                │
│ background_paths_duplication_rate                             │ [1]                │
│ batch_composition.batch_size                                  │ 128                │
│ batch_composition.source_distribution.negative_speech         │ 40                 │
│ batch_composition.source_distribution.positive                │ 30                 │
│ batch_composition.source_distribution.pure_noise              │ 30                 │
│ checkpoint_averaging_top_k                                    │ 5                  │
│ checkpointing.enabled                                         │ True               │
│ checkpointing.interval_steps                                  │ 1000               │
│ checkpointing.limit                                           │ 5                  │
│ debug_mode                                                    │ True               │
│ dropout_prob                                                  │ 0.5                │
│ ema_alpha                                                     │ 0.01               │
│ embedding_dim                                                 │ 96                 │
│ feature_gen_cpu_ratio                                         │ 0.8                │
│ layer_size                                                    │ 384                │
│ learning_rate_max                                             │ 0.001              │
│ lr_scheduler_type                                             │ onecycle           │
│ main_delta                                                    │ 0.0001             │
│ max_snr_in_db                                                 │ 13.477561925166414 │
│ min_snr_in_db                                                 │ -7.217950459866868 │
│ model_name                                                    │ reflets_v3         │
│ model_type                                                    │ rnn                │
│ momentum                                                      │ 0.9                │
│ n_blocks                                                      │ 6                  │
│ optimizer_type                                                │ adamw              │
│ overwrite                                                     │ True               │
│ show_training_summary                                         │ True               │
│ steps                                                         │ 30000              │
│ total_length                                                  │ 32000              │
│ train_model                                                   │ True               │
│ training_refinement.hard_negative_mining.bank_size            │ 500                │
│ training_refinement.hard_negative_mining.enable               │ True               │
│ training_refinement.hard_negative_mining.focus_on_confusing   │ True               │
│ training_refinement.hard_negative_mining.min_bank_size        │ 50                 │
│ training_refinement.hard_negative_mining.mining_threshold     │ 0.3                │
│ training_refinement.hard_negative_mining.replay_batch_size    │ 24                 │
│ training_refinement.loss_settings.false_accept_penalty        │ 20.0               │
│ training_refinement.loss_settings.focal_gamma                 │ 2.5                │
│ training_refinement.loss_settings.miss_penalty                │ 5.0                │
│ training_refinement.loss_settings.temperature                 │ 2.0                │
│ training_refinement.loss_weights.bce                          │ 0.3                │
│ training_refinement.loss_weights.confidence_reg               │ 10.0               │
│ training_refinement.loss_weights.focal                        │ 0.2                │
│ training_refinement.loss_weights.margin                       │ 100.0              │
│ training_refinement.loss_weights.negative_push                │ 30.0               │
│ training_refinement.loss_weights.replay                       │ 20.0               │
│ training_refinement.loss_weights.triplet                      │ 0.5                │
│ training_refinement.margin_settings.confidence_penalty_weight │ 50.0               │
│ training_refinement.margin_settings.exponential_scale         │ 4.0                │
│ training_refinement.margin_settings.safety_threshold          │ 0.05               │
│ training_refinement.optimization.adaptive_clipping            │ True               │
│ training_refinement.optimization.aggressive_clip_factor       │ 0.5                │
│ training_refinement.optimization.max_grad_norm                │ 1.5                │
│ training_refinement.regularization.confidence_regularization  │ 0.1                │
│ training_refinement.regularization.enable_spectral            │ True               │
│ training_refinement.regularization.spectral_weight            │ 0.01               │
│ training_refinement.triplet_settings.base_margin              │ 0.5                │
│ training_refinement.triplet_settings.curriculum_steps         │ 15000              │
│ training_refinement.triplet_settings.hard_mining_ratio        │ 0.6                │
│ training_refinement.triplet_settings.negative_push_margin     │ 0.8                │
│ transform_clips                                               │ True               │
│ triplet_loss_margin                                           │ 0.2                │
│ weight_decay                                                  │ 0.01               │
└───────────────────────────────────────────────────────────────┴────────────────────┘
Training:  35%|███▍      | 10385/30000 [56:54<1:47:30,  3.04it/s]
INFO: Early stopping triggered at step 10385. No improvement in stable loss for 4500 steps.

INFO: Training finished. Merging best checkpoints to create final model...
INFO: Averaging the top 5 most stable models found during training...
INFO: Calculating performance metrics for the final averaged model...
========================================
TRAINING COMPLETE - FINAL REPORT
========================================
INFO: NOTE: These metrics are indicators of model health, not real-world performance.
  Average Stable Loss      : 31.2011
  Weight Diversity (Std Dev): 0.7673
  Avg. Positive Confidence (Logit): -6.783
  Avg. Negative Confidence (Logit): -22.139

Generating training performance graph...
Performance graph saved to: /content/trained_models/reflets_v3/2_training_artifacts/graphs/training_performance_graph.png
INFO: Reconstructing model into a sequential format for export.
INFO: Saving inference-ready ONNX model to '/content/trained_models/reflets_v3/3_model/reflets_v3.onnx'
INFO: Using ONNX opset version: 17
INFO: ONNX model saved successfully.


CONGRATULATIONS! (✿◕‿◕✿)
Your custom wake word model has been successfully trained!

The JS Code seems to works even if the confidence has variation from 0.2 to 0.35 for model v2 but it feels very very low.

        try {
            // Process audio in chunks and return highest score
            let maxScore = 0;
            const numFrames = Math.floor(audioFloat32.length / FRAME_SIZE);

            // Initialize mel buffer for this check
            let melBuffer = [];
            
            // Use persistent embedding buffer (initialize only if empty)
            if (persistentEmbeddingBuffer.length === 0) {
                for (let i = 0; i < EMBEDDING_HISTORY_SIZE; i++) {
                    persistentEmbeddingBuffer.push(new Float32Array(96).fill(0));
                }
            }

            for (let frameIdx = 0; frameIdx < numFrames; frameIdx++) {
                const chunk = audioFloat32.subarray(frameIdx * FRAME_SIZE, (frameIdx + 1) * FRAME_SIZE);

                // Stage 1: Audio → Melspectrogram
                const melTensor = new ort.Tensor('float32', chunk, [1, FRAME_SIZE]);
                const melResults = await melModel.run({ [melModel.inputNames[0]]: melTensor });
                let melData = melResults[melModel.outputNames[0]].data;

                // Apply transformation (critical for correct detection)
                for (let j = 0; j < melData.length; j++) {
                    melData[j] = (melData[j] / 10.0) + 2.0;
                }

                // Add 5 mel frames (each chunk produces 5 frames)
                for (let j = 0; j < 5; j++) {
                    melBuffer.push(new Float32Array(melData.subarray(j * 32, (j + 1) * 32)));
                }

                // Stage 2: Melspectrogram History → Embedding
                while (melBuffer.length >= MEL_WINDOW_SIZE) {
                    const windowFrames = melBuffer.slice(0, MEL_WINDOW_SIZE);
                    const flattenedMel = new Float32Array(MEL_WINDOW_SIZE * 32);
                    for (let k = 0; k < MEL_WINDOW_SIZE; k++) {
                        flattenedMel.set(windowFrames[k], k * 32);
                    }

                    const embeddingTensor = new ort.Tensor('float32', flattenedMel, [1, MEL_WINDOW_SIZE, 32, 1]);
                    const embeddingResults = await embeddingModel.run({ [embeddingModel.inputNames[0]]: embeddingTensor });
                    const embedding = embeddingResults[embeddingModel.outputNames[0]].data;

                    // Stage 3: Embedding History → Wake Word Score
                    // Update persistent buffer (slide window)
                    persistentEmbeddingBuffer.shift();
                    persistentEmbeddingBuffer.push(new Float32Array(embedding));

                    const flattenedEmbeddings = new Float32Array(EMBEDDING_HISTORY_SIZE * 96);
                    for (let k = 0; k < EMBEDDING_HISTORY_SIZE; k++) {
                        flattenedEmbeddings.set(persistentEmbeddingBuffer[k], k * 96);
                    }

                    const wakeWordTensor = new ort.Tensor('float32', flattenedEmbeddings, [1, EMBEDDING_HISTORY_SIZE, 96]);
                    const wakeWordResults = await wakeWordModel.run({ [wakeWordModel.inputNames[0]]: wakeWordTensor });
                    const score = wakeWordResults[wakeWordModel.outputNames[0]].data[0];

                    if (score > maxScore) {
                        maxScore = score;
                    }

                    // Slide window by 8 frames
                    melBuffer.splice(0, 8);
                }
            }

            const detected = maxScore > $.CLIENT.CONFIG.WAKEWORD_THRESHOLD;
            console.log(`Wake word check: score=${maxScore.toFixed(4)}, detected=${detected}`);
            
            // DEBUG: Log model info on first real check
            if (maxScore > 0.01 && !window._wakeword_debug_logged) {
                console.log('🔍 WAKEWORD DEBUG INFO:');
                console.log('  Model inputs:', wakeWordModel.inputNames);
                console.log('  Model outputs:', wakeWordModel.outputNames);
                console.log('  Input shape expected: [1, 16, 96]');
                console.log('  Frames processed:', numFrames);
                console.log('  Max score location: frame', maxScore);
                window._wakeword_debug_logged = true;
            }

            return { detected, score: maxScore, reason: 'checked' };

        } catch (err) {
            console.error('Wake word check failed:', err);
            return { detected: false, score: 0, reason: 'error' };
        }
    };

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentationenhancementNew feature or requestquestionFurther information is requested

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions