Nanowakeword Configuration Guide
Complete documentation of all configurable parameters in the Nanowakeword package, including descriptions, default values, meanings, and usage examples.
Latest release:
Guide updated for:v3.0.0
Documentation updated: August 19, 2026
Table of Contents
- Workflow Overview
- Project & Data Paths
- Pipeline Control
- Mode Selection: Embedding vs E2E
- Model Architecture
- Feature Manifest
- Batch Composition & ISBL Sampling
- Training & Optimization
- Loss Functions
- Checkpointing & Early Stopping
- Validation
- Data Generation (TTS)
- Feature Generation Manifest
- Audio Processing Settings
- Augmentation Settings
- Distillation
- ONNX Export Settings
- Custom Export
- Intelligent Auto-Configuration
- Inference Parameters
- Server Configuration
- Command-Line Arguments
Workflow Overview
NanoWakeWord operates in three sequential stages, each toggleable via configuration keys or CLI flags:
┌──────────────────────┐ ┌──────────────────────┐ ┌──────────────────────┐
│ Generate Clips │ --> │ Transform Clips │ --> │ Train Model │
│ (TTS synthesis) │ │ (augment + feats) │ │ (train + distill) │
└──────────────────────┘ └──────────────────────┘ └──────────────────────┘| Stage | Config key | CLI flag | What it does |
|---|---|---|---|
| Generate clips | generate_clips |
-G |
Synthesizes audio from text using Piper TTS |
| Transform clips | transform_clips |
-t |
Augments audio and extracts embeddings (or saves raw WAVs in E2E mode) |
| Train model | train_model |
-T |
Trains the neural network and exports ONNX |
| Distill | distill (or distillation.enabled) |
-d |
Builds a lightweight "lite" student model |
Project & Data Paths
output_dir
- Type:
string - Default:
"./trained_models" - Description: Base directory where all trained models and artifacts are stored.
A subdirectory named after
model_nameis created inside this directory.
model_name
- Type:
string - Default: Auto-generated via
auto_gen_name()— formatnww_<model_type>_model_v<N> - Description: Name of the trained model. Used as the subdirectory name
under
output_dirand as the filename for exported model files. - Example:
model_name: "my_wakeword_v1"
target_phrase
- Type:
string - Default: None
- Description: The wake word text. Used as the default phrase for TTS
generation tasks that do not specify an explicit phrase. Should be set
if using
data_generation_taskswithfixed_phraseorauto_adversarialtext sources.
positive_data_path
- Type:
string(file path) - Default: None
- Description: Directory containing positive audio samples (actual wake word utterances). Required if using real (non-synthetic) positive data.
- Requirements:
- Supports
.wav,.mp3,.flac,.m4a,.ogg,.aac,.wma,.aiff,.alac,.opus,.pcm - Audio is converted to 16 kHz / 16-bit mono if
convert_audio: true
- Supports
negative_data_path
- Type:
string(file path) - Default: None
- Description: Directory containing negative audio samples (non-wake-word utterances, e.g. general speech).
background_paths
- Type:
listof strings - Default:
[](empty) - Description: Directories containing background noise audio files for augmentation. Multiple paths are supported. The intelligent config engine computes a duplication rate for each path based on available noise duration.
- Example:
background_paths: - "./data/office_noise" - "./data/street_noise"
rir_paths
- Type:
listof strings - Default:
[](empty) - Description: Directories containing Room Impulse Response (RIR) WAV files.
Each directory is scanned for all files (not just
.wav).
convert_audio
- Type:
boolean - Default:
false - Description: When
true, all audio directories (positive_data_path,negative_data_path,background_paths,rir_paths) are verified and converted to 16 kHz, 16-bit, mono WAV before the pipeline begins. A per-directory verification receipt is cached inoutput_dir/.cache/verification_receipts/to skip re-processing on subsequent runs. - CLI flag:
-f/--force-verifyre-verifies all directories, ignoring the cache.
Pipeline Control
These boolean switches enable or disable pipeline stages. CLI flags take precedence over config file values when both are set.
generate_clips
- Type:
boolean - Default:
false - Description: Enables the TTS clip generation stage. Requires
data_generation_tasksto be defined.
transform_clips
- Type:
boolean - Default:
false - Description: Enables the feature extraction / augmentation stage. Requires
data_generation_manifest(orfeature_generation_manifest) to be defined. In E2E mode, this stage produces augmented raw audio WAV files instead of.npyfeature arrays.
train_model
- Type:
boolean - Default:
false - Description: Enables the model training stage.
overwrite
- Type:
boolean - Default:
false - Description: When
true, forces regeneration of existing feature files, overwriting them. Whenfalse, existing.npyfiles are skipped. - CLI flag:
--overwrite
Mode Selection: Embedding vs E2E
mode
- Type:
string - Default:
"embedding" - Valid Options:
"embedding","e2e" - Description: Selects the training paradigm.
In embedding mode (default), the framework uses a pre-trained on-device
mel-spectrogram model and a Google speech-embedding model to convert raw audio
into 96-dimensional feature embeddings. The wake word model trains on these
pre-computed embeddings. Feature extraction happens once during the
transform_clips stage and is stored as .npy files.
In E2E mode, the model trains directly on raw PCM audio waveforms.
Feature extraction (mel-spectrogram) is part of the neural network itself and
is learned end-to-end. The transform_clips stage produces augmented raw WAV
files. The feature_manifest must point to directories of .wav files (not
.npy arrays).
- Example:
mode: "e2e" # Train end-to-end on raw audio model_type: "e2e_dnn"
Model Architecture
model_type
Type:
stringDefault:
"dnn"Valid Options (Embedding mode):
"dnn","cnn","lstm","gru","rnn","crnn","tcn","quartznet","transformer","conformer","e_branchformer","bcresnet","custom"Valid Options (E2E mode):
"e2e_dnn","e2e_cnn","e2e_quartznet","custom"Description: Selects the neural network architecture. Architectures are categorized by complexity and use case:
| Architecture | Category | Description |
|---|---|---|
dnn |
Feedforward | Dense layers with LayerNorm; smallest and fastest |
cnn |
Convolutional | 2D convolutions over spectrogram-like inputs |
rnn |
Recurrent | Bidirectional LSTM (fixed 64-dim hidden) |
lstm |
Recurrent | Configurable bidirectional LSTM |
gru |
Recurrent | Configurable bidirectional GRU |
crnn |
Hybrid | CNN frontend + configurable LSTM/GRU backend |
tcn |
Convolutional | Temporal Convolutional Network with dilated convolutions |
quartznet |
Convolutional | 1D time-channel separable convolutions (parameter-efficient) |
transformer |
Attention | Standard Transformer encoder with positional encoding |
conformer |
Hybrid | Conformer blocks (conv + multi-head attention) |
e_branchformer |
Hybrid | E-Branchformer with parallel attention/conv branches |
bcresnet |
Convolutional | Broadcasting-residual CNN with depthwise separable convolutions |
e2e_dnn |
E2E | Raw audio → Conv frontend → Dense embedding head |
e2e_cnn |
E2E | Raw audio → Conv frontend + CNN backbone |
e2e_quartznet |
E2E | Raw audio → Conv frontend + QuartzNet backbone |
custom |
User-defined | Loads a user-provided torch.nn.Module |
layer_size
- Type:
integer - Default:
128(auto-adjusted by intelligent config if not specified) - Applies to:
dnn,lstm,gru,crnn - Description: Number of neurons in each hidden layer. Controls model capacity — larger values increase parameters and training time.
n_blocks
- Type:
integer - Default:
1(passed explicitly intrainer.pywhen not in config); auto-adjusted by the intelligent config engine when not specified - Applies to:
dnn,lstm,gru,rnn,transformer,crnn(RNN depth),conformer,e_branchformer,tcn - Description: Number of stacked blocks/layers in the network. The meaning
varies by architecture:
dnn: Number ofFCNBlocklayers after the input projectionlstm/gru/rnn: Number of recurrent layerstransformer/conformer/e_branchformer: Number of encoder blockscrnn: Number of RNN layers (CNN portion is fixed)tcn: Derived from the length oftcn_channels
dropout_prob
- Type:
float - Default:
0.5(auto-adjusted by intelligent config) - Valid Range:
0.0to0.8 - Description: Dropout probability applied in hidden layers. Higher values
increase regularization. Applied within recurrent layers (when
n_blocks > 1), after pooling in CNNs, and in the classifier head.
activation_function
- Type:
string - Default:
"relu" - Valid Options:
"relu","gelu","silu" - Description: Activation function used in hidden layers.
geluandsiluare smooth alternatives toreluthat can improve convergence at a small computational cost.
embedding_dim
- Type:
integer - Default:
64 - Description: Dimensionality of the final embedding vector produced by the
backbone network, before the classifier head. The classifier projects from
embedding_dim→embedding_dim // 2→n_classes.
Architecture-Specific Parameters
Transformer (model_type: "transformer")
| Parameter | Default | Description |
|---|---|---|
transformer_d_model |
128 |
Model dimension (input to attention) |
transformer_n_head |
4 |
Number of attention heads |
model_type: "transformer"
transformer_d_model: 192
transformer_n_head: 6CRNN (model_type: "crnn")
| Parameter | Default | Description |
|---|---|---|
crnn_cnn_channels |
[16, 32, 32] |
CNN channel progression |
crnn_rnn_type |
"lstm" |
"lstm" or "gru" |
model_type: "crnn"
crnn_cnn_channels: [32, 64, 64]
crnn_rnn_type: "gru"TCN (model_type: "tcn")
| Parameter | Default | Description |
|---|---|---|
tcn_channels |
[64, 64, 128] |
Channel width per TemporalBlock |
tcn_kernel_size |
3 |
Convolution kernel size |
model_type: "tcn"
tcn_channels: [128, 128, 256, 256]
tcn_kernel_size: 4Conformer (model_type: "conformer")
| Parameter | Default | Description |
|---|---|---|
conformer_d_model |
144 |
Model dimension |
conformer_n_head |
4 |
Number of attention heads |
model_type: "conformer"
conformer_d_model: 192
conformer_n_head: 6E-Branchformer (model_type: "e_branchformer")
| Parameter | Default | Description |
|---|---|---|
branchformer_d_model |
144 |
Model dimension |
branchformer_n_head |
4 |
Number of attention heads |
model_type: "e_branchformer"
branchformer_d_model: 256
branchformer_n_head: 8QuartzNet (model_type: "quartznet")
| Parameter | Default | Description |
|---|---|---|
quartznet_config |
[[256, 33, 1], [256, 33, 1], [512, 39, 1]] |
List of [channels, kernel_size, repetitions] triples |
model_type: "quartznet"
quartznet_config:
- [256, 33, 1]
- [256, 33, 1]
- [512, 39, 1]
- [512, 39, 1]BcResNet (model_type: "bcresnet")
No architecture-specific parameters beyond embedding_dim and dropout_prob.
The network uses a fixed structure of 3 BcResNetBlock layers (32→64→128→256
channels) with adaptive global average pooling.
E2E Models (model_type: "e2e_dnn", "e2e_cnn", "e2e_quartznet")
All E2E models use a RawAudioFrontend followed by a backbone network.
Additional parameters:
| Parameter | Default | Description |
|---|---|---|
e2e_frontend_channels |
32 |
Output channels of the first conv layer in the frontend |
e2e_frontend_depth |
2 for e2e_dnn/e2e_cnn, 3 for e2e_quartznet |
Number of conv blocks in the frontend |
e2e_quartznet_config |
[[64, 11, 1], [64, 13, 1], [64, 17, 1]] |
QuartzNet block config (only for e2e_quartznet) |
mode: "e2e"
model_type: "e2e_quartznet"
e2e_frontend_channels: 64
e2e_frontend_depth: 3
sample_rate: 16000
clip_samples: 16000Custom Architecture (model_type: "custom")
Loads a user-defined torch.nn.Module class from a Python file or importable
module.
Required settings under custom_model_config:
| Key | Type | Description |
|---|---|---|
module_path |
string |
Path to a .py file or an importable module name |
class_name |
string |
Name of the class to instantiate |
Optional settings:
| Key | Type | Description |
|---|---|---|
params |
dict |
Extra keyword arguments passed to the constructor |
The custom class constructor receives (based on what it accepts via signature inspection):
| Argument | Type | Description |
|---|---|---|
input_shape |
tuple |
Shape of a single input sample |
embedding_dim |
int |
Number of embedding output dimensions |
dropout_prob |
float |
Dropout probability |
activation_fn |
nn.Module |
Activation function instance |
config |
ConfigProxy |
Full configuration proxy |
*params |
— | Any additional keys from params |
The forward method must return a tensor of shape [batch_size, embedding_dim].
# my_model.py
import torch
from torch import nn
class MyCustomModel(nn.Module):
def __init__(self, input_shape, embedding_dim=64, dropout_prob=0.5,
activation_fn=None, config=None, hidden_channels=32):
super().__init__()
self.activation_fn = activation_fn if activation_fn is not None else nn.ReLU()
# ... build layers ...
def forward(self, x):
# x: [batch, time, features] or [batch, 1, time, features]
# return: [batch, embedding_dim]
...model_type: "custom"
custom_model_config:
module_path: "my_model.py"
class_name: "MyCustomModel"
params:
hidden_channels: 64Feature Manifest
Defines paths to pre-computed feature files (.npy format) used for training.
In E2E mode, paths point to directories of .wav files instead.
feature_manifest:
targets: # Positive samples (wake word)
t: "./trained_models/model_v1/features/positive.npy"
negatives: # Negative samples
n: "./features/negative.npy"
hn: "./features/hard_negatives.npy"
b: "./features/noise.npy" # Background noise
targets_val: # Optional validation data (suffix `_val`)
t: "./features/val_positive.npy"
negatives_val:
n: "./features/val_negatives.npy"data_manifest
- Type:
dict - Default: None
- Description: Alias for
feature_manifest. The trainer checks forfeature_manifestfirst, then falls back todata_manifest. Both use the same structure.
Categories
Each top-level key in the manifest is a category. The category name determines the label assigned to samples:
| Category | Label | Description |
|---|---|---|
targets |
1.0 |
Wake word samples (positive class) |
negatives |
0.0 |
Non-wake-word samples (negative class) |
Any targets_*_val |
1.0 |
Validation wake word samples |
Any negatives_*_val |
0.0 |
Validation negative samples |
Categories ending in _val are automatically routed to the validation
dataloader. Non-_val categories are used for training.
Batch Composition & ISBL Sampling
batch_composition
- Type:
dictmappingstring→integer - Default:
{'targets': 30, 'negatives': 230}(when not specified) - Description: Defines how many samples are drawn per batch from each
dataset or dataset group in the
feature_manifest. The sum of all values equals the total batch size.
Keys in batch_composition can reference either:
- A specific dataset key (e.g.,
t,hn,b) — samples are drawn only from that dataset. - A category name (e.g.,
targets,negatives) — samples are drawn from all datasets under that category, proportionally to their hardness scores.
batch_composition:
targets: 20 # 20 samples drawn from all datasets under 'targets'
n: 50 # 50 samples drawn only from 'negatives.n'
hn: 30 # 30 samples drawn only from 'negatives.hn'
b: 150 # 150 samples drawn only from 'negatives.b'
# Total batch = 250ISBL (Importance Sampling based on Loss) Parameters
The DynamicClassAwareSampler uses a hardness score per sample, updated
dynamically during training using the ISBL algorithm. Higher loss = higher
hardness = higher sampling probability.
| Parameter | Type | Default | Description |
|---|---|---|---|
hardness_ema_alpha |
float |
0.05 |
EMA smoothing factor for updating sample hardness scores |
hardness_floor |
float |
0.05 |
Minimum hardness score (prevents scores from collapsing to zero) |
hardness_reset_interval |
int |
5000 |
Reset hardness scores periodically (0 = disabled) |
hardness_reset_decay |
float |
0.5 |
Decay factor when resetting (0.5 = 50% old, 50% reset to 1.0) |
These parameters control how aggressively the sampler prioritizes hard examples. The sampler applies the formula:
P(sample) ∝ (hardness ^ 0.75) + epsilonwhere 0.75 is the fixed hardness_smoothing_factor in the sampler.
Training & Optimization
steps
- Type:
integer - Default: Auto-calculated by the intelligent config engine (range 10000–40000)
- Description: Total number of training iterations. The intelligent engine estimates this from the effective data volume (base hours × augmentation rounds) multiplied by 1000 steps per effective hour, adjusted for data quality.
batch_size
- Type:
integer - Default: Auto-calculated (the intelligent config engine was working on this but the logic is currently commented out; users should specify explicitly if needed)
- Description: Number of training samples per gradient step. The total
batch size is determined by
batch_composition(sum of its values). This parameter is informational; the actual batch size comes from the sampler.
optimizer_type
- Type:
string - Default:
"adamw" - Valid Options:
"adamw","adam","sgd" - Description: Optimization algorithm used during training.
learning_rate_max
- Type:
float - Default: Auto-calculated by the intelligent config engine (base 5e-5)
- Description: Maximum learning rate. Used with cyclical schedulers
(
onecycle,cyclic) or as the starting learning rate (cosine).
learning_rate_base
- Type:
float - Default:
learning_rate_max / 10(auto-calculated) - Description: Base/minimum learning rate. Used as the minimum in cyclic
schedulers, the floor in cosine annealing, or the starting point for
onecycle.
lr_scheduler_type
- Type:
string - Default:
"onecycle" - Valid Options:
"onecycle","cyclic","cosine" - Description: Learning rate schedule strategy.
onecycle: One-cycle schedule from base to max LR and back to basecyclic: Triangular2 cyclic schedule with configurable up/down phasescosine: Cosine annealing from max LR to base LR
clr_step_size_up
- Type:
integer - Default: Auto-calculated by intelligent config (based on
steps / num_cycles) - Description: Number of steps to increase LR in each cycle. Only used
when
lr_scheduler_type: "cyclic".
clr_step_size_down
- Type:
integer - Default: Same as
clr_step_size_up - Description: Number of steps to decrease LR in each cycle. Only used
when
lr_scheduler_type: "cyclic".
weight_decay
- Type:
float - Default:
0.01 - Description: L2 regularization coefficient applied to all parameters.
momentum
- Type:
float - Default:
0.9 - Valid Range:
0.0to1.0 - Description: Momentum factor. Only used when
optimizer_type: "sgd".
num_workers
- Type:
integer - Default:
2 - Description: Number of worker processes for PyTorch
DataLoader. Increasing this can speed up data loading on multi-core systems. When set to0, data loading is single-threaded.
Loss Functions
The training loop supports two loss function variants, selected via
loss_function.
loss_function
- Type:
string - Default:
"bias_weighted" - Valid Options:
"bias_weighted","asymmetric_focal" - Description: Loss function strategy.
asymmetric_focalhas its implementation commented out in the current code and falls back tobias_weightedbehavior. Use"bias_weighted"for full functionality.
LOSS_BIAS
Type:
floatDefault:
0.75Description: Weight given to the negative class in
BiasWeightedLoss. A value of0.75means 75% of the loss comes from negative samples and 25% from positive samples. This upweights hard negatives, which is critical for wake word detection where the vast majority of real-world audio is non-wake-word.The combined loss is:
total_loss = LOSS_BIAS * mean(neg_loss) + (1 - LOSS_BIAS) * mean(pos_loss)Label smoothing of
0.05is applied to the soft targets used in the cross-entropy calculation, but masks (pos/neg split) are computed from the original hard labels before smoothing. Per-example losses (used for ISBL hardness tracking) are computed with the same class weighting.
afl_gamma_pos (Asymmetric Focal Loss)
- Type:
float - Default:
0.0 - Description: Focusing parameter for positive samples. Currently unused because the asymmetric focal loss implementation is commented out.
afl_gamma_neg (Asymmetric Focal Loss)
- Type:
float - Default:
4.0 - Description: Focusing parameter for negative samples. Currently
unused (see
afl_gamma_pos).
Logit Regularization Parameters
The training loop applies an L2 penalty on extreme logit magnitudes to prevent the model from becoming overconfident:
| Parameter | Type | Default | Description |
|---|---|---|---|
logit_reg_weight |
float |
2e-4 |
Weight of the logit regularization term |
logit_reg_margin |
float |
6.0 |
Target logit magnitude; logits exceeding ±margin are penalized |
Set logit_reg_weight to 0 to disable logit regularization.
Checkpointing & Early Stopping
checkpointing
- Type:
dict - Description: Controls periodic checkpoint saving during training.
| Key | Type | Default | Description |
|---|---|---|---|
enabled |
boolean |
false |
Enable/disable checkpointing |
interval_steps |
integer |
1000 |
Save a checkpoint every N steps |
limit |
integer |
3 |
Maximum number of checkpoint files to retain (oldest are deleted) |
Each checkpoint stores: model state dict, optimizer state, scheduler state, EMA loss, best error score, best training checkpoints (SWA pool), RNG states for deterministic resume, and training history.
checkpointing:
enabled: true
interval_steps: 500
limit: 5checkpoint_averaging_top_k
- Type:
integer - Default:
5 - Description: Number of best checkpoints (by stable loss) to average via Stochastic Weight Averaging (SWA) when building the final model. Only used as a fallback when no validation data is available or when the validation set overlaps with training data (detected when val error = 0 and the best checkpoint appears very late in training).
early_stopping_patience
- Type:
integer - Default:
10%ofsteps(or0ifsteps < 3000) - Description: Stop training if the stable (EMA) loss has not improved by
at least
min_deltafor this many steps. Set to0to disable. This is a fallback — when validation data is present, validation-based early stopping takes priority.
val_early_stopping_patience
- Type:
integer - Default:
15%ofsteps - Description: Stop training if the validation error score has not improved for this many steps. Only active when validation data is provided.
min_delta
- Type:
float - Default:
0.0001 - Description: Minimum improvement in EMA loss required to reset the early stopping counter.
checkpoint_pool_interval
- Type:
integer - Default:
500 - Description: Interval (in steps) at which the current model state is considered for the training-loss checkpoint pool. This pool is used as a fallback for final model averaging when no validation data is available. The pool tracks the top-K checkpoints with the lowest EMA loss.
enable_journaling
- Type:
boolean - Default:
true - Description: When
true, after training completes, atraining_journal.mdfile is written tooutput_dirsummarizing the run. The journal uses a "show on change" layout: only configuration parameters that changed since the previous run are displayed in each row. The journal history is cached inoutput_dir/.cache/journal_cache/training_history.json.
show_training_summary
- Type:
boolean - Default:
true - Description: When
true, prints an ASCII table showing the effective training configuration at startup, and updates it dynamically during training with live metrics (loss, learning rate, accuracy, etc.).
debug_mode
- Type:
boolean - Default:
false - Description: When
true, enables verbose debug logging. A rotating log file (5 MB, 30 backups) is written tooutput_dir/model_name/training_artifacts/training_debug/training_debug.log. Debug logs include per-step metrics, validation results, hardness score updates, and checkpoint saves.
stabilization_steps
- Type:
integer - Default:
5%ofmax_steps(auto-calculated; was1500in older versions) - Description: Number of initial warmup steps before metrics like validation and early stopping are evaluated. Prevents premature decisions during initial convergence.
ema_alpha
- Type:
float - Default:
0.01 - Description: Exponential moving average factor for tracking the
smoothed (stable) training loss. The smoothed loss is:
ema = alpha * current_loss + (1 - alpha) * ema. Lower values produce smoother loss curves.
Validation
Validation runs periodically during training to track generalization. It
requires feature_manifest (or data_manifest) entries with the _val
suffix (e.g., targets_val, negatives_val).
| Parameter | Type | Default | Description |
|---|---|---|---|
validation_batch_size |
integer |
256 |
Batch size for validation passes |
val_interval |
integer |
500 |
Run validation every N training steps |
val_stabilization_steps |
integer |
Same as stabilization_steps |
Delay before starting validation |
val_subsample_batches |
integer |
0 (use all) |
Subsample N batches during training for speed; 0 uses the full set |
val_miss_weight |
float |
4.0 |
Penalty weight for missed detections (false negatives) in the operating-point search |
val_fp_weight |
float |
1.0 |
Penalty weight for false positives in the operating-point search |
validation_smoothing_window |
integer |
3 |
Number of recent validation runs to average for smoothing |
The validation routine sweeps thresholds from 0.2 to 0.8 (13 steps) and
selects the one that minimizes the weighted error score:
miss_weight * FN + fp_weight * FP.
Data Generation (TTS)
Synthetic audio clips are generated using Piper TTS. This stage is controlled
by the data_generation_tasks key — a list of task dictionaries, each
defining an independent synthesis job.
data_generation_tasks
- Type:
listofdict - Description: List of TTS generation tasks. Each task is a dictionary with the following keys:
| Key | Type | Default | Description |
|---|---|---|---|
name |
string |
"Unnamed Task N" |
Descriptive name for the task |
enabled |
boolean |
true |
Skip this task if false |
output_dir |
string |
(required) | Directory to save generated .wav files |
num_samples |
integer |
(required) | Number of audio clips to generate |
file_prefix |
string |
"sample" |
Prefix for output filenames |
tts_settings |
dict |
{} |
Task-specific TTS settings (overrides global) |
text_source |
dict |
(required) | Defines how text is generated (see below) |
text_source
Each task must specify a text_source dictionary with a type key:
type: "fixed_phrase"
Generates audio for a single phrase, repeated num_samples times.
| Key | Type | Default | Description |
|---|---|---|---|
phrase |
string |
Falls back to global target_phrase |
The exact text to synthesize |
type: "from_list"
Generates audio from a user-provided list of phrases.
| Key | Type | Default | Description |
|---|---|---|---|
phrases |
list[str] |
(required) | List of text phrases |
repeat_each |
integer |
1 |
How many times to repeat each phrase |
type: "auto_adversarial"
Generates phonetically similar English words/phrases using the CMU Pronouncing Dictionary. Creates challenging negative samples that sound similar to the wake word.
| Key | Type | Default | Description |
|---|---|---|---|
base_phrase |
string |
Falls back to target_phrase / phrase |
Phrase to generate variations from |
include_partial_phrase |
float |
0.0 |
Probability of creating shorter adversarial phrases |
include_input_words |
float |
0.0 |
Probability of preserving original wake-word words |
multi_word_prob |
float |
0.4 |
Probability of embedding the adversarial phrase in a longer phrase |
max_multi_word_len |
integer |
3 |
Maximum total words for multi-word expansions |
type: "phoneme_adversarial"
Generates adversarial text by substituting phonemes in the wake word using a trained phonemizer model. Creates extremely phonetically confusable negatives.
| Key | Type | Default | Description |
|---|---|---|---|
base_phrase |
string |
Falls back to target_phrase / phrase |
Phrase to generate phoneme variants from |
min_distance |
float |
0.35 |
Minimum phonetic distance (0.0 = identical, 1.0 = completely different) |
The phonemizer model is automatically downloaded from
https://github.com/arcosoph/phonemize/releases/download/v0.2.0/phonemize_m1.pt
on first use, or loaded from NwwResourcesModel/phonemize_model/phonemize_m1.pt.
tts_settings
- Type:
dict - Default:
{}(uses Piper TTS defaults) - Description: Global or task-specific TTS synthesis parameters. These
are passed directly to
generate_samples()as keyword arguments.
| Key | Type | Default | Description |
|---|---|---|---|
models |
str / list[str] / dict |
None (auto-load) | Piper model name, file path, directory, or {'onnx': url, 'json': url} dict |
models_dir |
string |
"NwwResourcesModel/tts_models" |
Directory to load or download TTS models |
speaker_ids |
int / list[int] |
None | Speaker ID(s) for multi-speaker models |
length_scales |
list[float] |
[1.0] |
Controls speech speed (higher = slower) |
noise_scales |
list[float] |
[0.667] |
Amount of randomness in speech sound |
noise_w_scales |
list[float] |
[0.8] |
Waveform variation for naturalness |
target_phrase: "hey nano"
tts_settings:
models: "en_US-libritts_r-medium"
models_dir: "./tts_models"
length_scales: [0.9, 1.0, 1.1]
noise_scales: [0.667, 0.8]
noise_w_scales: [0.8]
speaker_ids: [0, 1, 2]
data_generation_tasks:
- name: "Positive Wake Words"
enabled: true
output_dir: "dataset/positive"
num_samples: 1000
text_source:
type: "fixed_phrase"
- name: "Phoneme-Based Hard Negatives"
enabled: true
output_dir: "dataset/negative"
num_samples: 1500
file_prefix: "neg_phoneme"
text_source:
type: "phoneme_adversarial"
min_distance: 0.4Feature Generation Manifest
When transform_clips is enabled, the data_generation_manifest (or
feature_generation_manifest) key defines how raw audio is transformed into
training-ready features (embedding mode) or augmented WAV files (E2E mode).
data_generation_manifest:
positive_features:
input_audio_dirs: ["./dataset/positive"]
output_filename: "positive_features.npy"
use_background_noise: true
use_rir: true
augmentation_rounds: 10
augmentation_settings:
min_snr_in_db: 5.0
pitch_prob: 0.5
negative_features:
input_audio_dirs: ["./dataset/negative", "./dataset/external_neg"]
output_filename: "negative_features.npy"
use_background_noise: true
use_rir: false
augmentation_rounds: 5Recipe Keys
| Key | Type | Default | Description |
|---|---|---|---|
input_audio_dirs |
list[string] |
(required) | Source audio directories; .wav files are discovered recursively |
output_filename |
string |
(required for embedding) | Name of the output .npy file (saved in features/ dir) |
num_samples |
integer |
0 |
Number of clips to generate (only for E2E mode) |
use_background_noise |
boolean |
true |
Mix with background noise from background_paths |
use_rir |
boolean |
false |
Apply room impulse response convolution from rir_paths |
augmentation_rounds |
integer |
1 |
How many times to augment each input clip |
augmentation_settings |
dict |
Inherits global | Override augmentation params for this recipe |
In E2E mode, instead of .npy output, each recipe saves .wav files
to its output_dir (not output_filename). The num_samples key controls
how many total clips are produced (per augmentation round). Files are named
{file_prefix}_{index:06d}.wav.
In embedding mode, the output is a memory-mapped .npy file of shape
(num_clips, frames, 96) stored in output_dir/model_name/features/.
background_paths_duplication_rate
- Type:
list[integer] - Default: Auto-calculated by intelligent config engine
- Description: Duplication rate for background noise paths. Each background
path is repeated this many times during augmentation to balance noise
availability across datasets of different sizes. The intelligent config
computes this as
ceil(max_noise_hours / path_hours)for each path.
Audio Processing Settings
sample_rate
- Type:
integer - Default:
16000 - Description: Target sample rate for all audio processing (both training and inference). All audio is resampled to this rate.
clip_samples
- Type:
integer - Default:
16000 - Description: Fixed clip length in samples for E2E mode training. Each audio file is either cropped (random position) or zero-padded to this length. Required for E2E training and inference.
audio_processing
- Type:
dict - Description: Controls how audio clip duration is determined during the transform stage.
audio_processing:
clip_length_samples: 16000 # Explicit clip length (all modes)
# OR use autotune (embedding mode only, ignored in E2E):
autotune_length:
enabled: true # Default: true
num_samples_to_inspect: 50 # Number of positive clips to inspect
duration_buffer_ms: 750 # Buffer added to median duration
min_allowable_length: 32000 # Minimum clip length (2.0s @ 16kHz)
snap_to_min_tolerance: 4000 # Snap to minimum if within this toleranceaudio_processing.clip_length_samples
- Type:
integer - Default: None (falls through to autotune)
- Description: If set, all audio clips are exactly this many samples long.
audio_processing.autotune_length
- Type:
dict - Description: When
enabledistrueandclip_length_samplesis not set, the framework inspects a random sample of positive audio clips, computes the median duration, adds a buffer, and snaps to a round number of milliseconds.
augmentation_batch_size
- Type:
integer - Default: Auto-calculated (based on system RAM and CPU cores):
- Systems with
psutil: computed from available RAM and CPU count, rounded to nearest power of 2 in range [16, 128] - Without
psutil:32
- Systems with
- Description: Batch size for the audio augmentation processing stage (separate from training batch size).
feature_gen_num_workers
- Type:
integer - Default:
num_workers(from training config) if not set - Description: Number of worker processes for multiprocessing during feature generation. Only used in embedding mode.
feature_gen_cpu_ratio
- Type:
float - Default:
0.6 - Valid Range:
0.0to1.0 - Description: Fraction of available CPU cores used for mel-spectrogram
computation during embedding extraction. The actual count is
max(1, int(cpu_count * ratio)).
Augmentation Settings
Controls stochastic audio augmentation applied during the transform_clips
stage. Parameters can be set globally (top-level augmentation_settings) or
per-recipe in data_generation_manifest.
augmentation_settings:
gain_prob: 1.0 # Probability of applying gain adjustment
min_gain_in_db: -3.0 # Minimum gain in dB
max_gain_in_db: 3.0 # Maximum gain in dB
pitch_prob: 0.5 # Probability of pitch shifting
min_pitch_semitones: -2.0 # Minimum pitch shift
max_pitch_semitones: 2.0 # Maximum pitch shift
min_snr_in_db: 5.0 # Minimum signal-to-noise ratio
max_snr_in_db: 30.0 # Maximum signal-to-noise ratio
rir_prob: 0.5 # Probability of RIR convolution
min_volume_augmentation: 0.5 # Minimum target volume level
max_volume_augmentation: 1.0 # Maximum target volume levelaugmentation_settings.rir_prob
- Type:
float - Default:
0.5 - Valid Range:
0.0to1.0 - Description: Probability of applying room impulse response convolution.
Requires
rir_pathsto be configured anduse_rir: truein the recipe.
augmentation_settings.gain_prob / min_gain_in_db / max_gain_in_db
- Type:
float - Defaults:
1.0,-3.0,3.0 - Description: Apply random gain adjustment.
gain_probis the probability per clip. Gain is uniformly sampled from[min_gain_in_db, max_gain_in_db].
augmentation_settings.pitch_prob / min_pitch_semitones / max_pitch_semitones
- Type:
float - Defaults:
0.5,-2.0,2.0 - Description: Apply random pitch shifting without changing duration.
pitch_probis the probability per clip. Shift is uniformly sampled from[min, max]semitones.
augmentation_settings.min_snr_in_db / max_snr_in_db
- Type:
float - Defaults:
5.0,30.0 - Description: Signal-to-noise ratio range (in dB) for background noise
mixing. Lower values = more noise. Background noise is randomly selected
from
background_paths.
augmentation_settings.min_volume_augmentation / max_volume_augmentation
- Type:
float - Defaults:
0.5,1.0 - Description: Target peak volume level after augmentation. Each clip is scaled so its peak amplitude falls within this range (relative to full scale of 1.0). This replaces peak normalization with a stochastic volume target for robustness to varying microphone gains.
Distillation
Knowledge distillation builds a tiny "student" model that mimics the output of the trained "teacher" model. The student is always a stripped-down DNN (regardless of teacher architecture) to maximize speed.
distillation
Type:
dictDescription: Controls knowledge distillation. The student loss is:
loss = alpha * KL(student_soft || teacher_soft) * T² + (1 - alpha) * BCE(student_logit, hard_label)where
Tis the temperature andalphais the soft-loss weight.
| Key | Type | Default | Description |
|---|---|---|---|
enabled |
boolean |
true |
Enable distillation after training |
steps |
integer |
8000 |
Number of distillation training steps |
temperature |
float |
4.0 |
Temperature scaling for soft labels |
alpha |
float |
0.7 |
Weight on soft loss (1-alpha = hard loss) |
learning_rate |
float |
5e-4 |
Student learning rate |
log_interval |
integer |
500 |
Logging interval for distillation |
student_layer_size |
integer |
8 |
Hidden layer size of student DNN |
student_n_blocks |
integer |
1 |
Number of FCN blocks in student |
student_embedding_dim |
integer |
8 |
Embedding dim of student |
student_dropout_prob |
float |
0.1 |
Dropout in student model |
distillation:
enabled: true
steps: 10000
temperature: 3.0
alpha: 0.6
learning_rate: 3e-4
student_layer_size: 16
student_embedding_dim: 16The distilled model is exported as <model_name>_lite.onnx and can be used
as a gatekeeper in cascade mode during inference.
ONNX Export Settings
onnx_opset_version
- Type:
integer - Default:
17 - Description: ONNX opset version used by the built-in ONNX exporter. Higher
versions support more operators but may reduce compatibility with older
runtimes. Can be overridden by placing
onnx_opset_versionunder thecustom_exportsection.
Custom Export
After training (and after distillation), the framework exports the model to ONNX and PyTorch formats. A user-provided custom export hook can be configured to produce additional formats (e.g., CoreML, TFLite).
custom_export (or export_model)
- Type:
dict - Description: Configuration for the custom export hook. Supports two modes: Python script or shell command.
| Key | Type | Default | Description |
|---|---|---|---|
script |
string |
None | Path to a Python file exposing a callable |
function |
string |
"export_model" |
Name of the callable in the script |
command |
string |
None | Shell command with {model_path}, {model_name}, {output_dir} placeholders |
onnx_opset_version |
integer |
Inherits top-level value (default 17) |
Overrides the top-level onnx_opset_version for this export |
When using script mode, the callable receives these keyword arguments:
model, input_shape, config, model_name, output_dir. The callable
may use the in-memory PyTorch model directly, or operate on the ONNX file
produced by the built-in exporter.
custom_export:
script: "/path/to/my_coreml_export.py"
function: "export_to_coreml"
onnx_opset_version: 17Or using shell command mode:
custom_export:
command: "python /scripts/onnx_to_coreml.py --onnx {model_path} --out {output_dir}"Intelligent Auto-Configuration
The ConfigGenerator class analyzes dataset statistics and computes
appropriate hyperparameters when they are not explicitly set in the config.
The generated values always merge with and are overridden by user
settings in the config file.
Input Statistics
The config generator uses dataset statistics computed by
DatasetAnalyzer. These are passed as the stats argument to
ConfigGenerator(stats). In the trainer, if DatasetAnalyzer is not
explicitly called, ConfigGenerator runs with empty stats and produces
minimal defaults.
| Stat | Description |
|---|---|
H_pos |
Duration of positive data in hours |
H_neg |
Duration of negative data in hours |
H_noise |
Total duration of background noise in hours |
H_noise_paths |
Dict mapping each noise path to its duration in hours |
A_noise |
Average RMS amplitude of noise (0–1) |
N_rir |
Count of RIR files |
Generated Parameters
| Parameter | How it's computed |
|---|---|
augmentation_rounds |
clamp(required_multiplier, 2, 5) where required_multiplier = dynamic_target_hours / base_hours |
steps |
effective_data_volume * 1000, adjusted by data quality (1.1 - 0.2 * normalized_quality), clamped to [10000, 40000] |
n_blocks |
clamp(log10(effective_data_volume + 1) * 2.0, 1.0, 4.0), rounded |
layer_size |
64 * 2^(n_blocks - 1), clamped to [64, 512] |
learning_rate_max |
5e-5 * clamp(size_factor, 0.8, 2.0) * clamp(noise_factor, 0.5, 1.0) |
learning_rate_base |
learning_rate_max / 10 |
dropout_prob |
clamp(0.6 + overfitting_risk * 0.75, 0.4, 0.8) |
clr_step_size_up |
steps / num_cycles * 0.4 |
clr_step_size_down |
steps / num_cycles * 0.6 |
background_paths_duplication_rate |
ceil(max_noise_hours / path_hours) per path |
augmentation_batch_size |
min([16, 32, 64, 128], key=lambda x: abs(x - calculated)) where calculated = 16 * (safe_ram_gb / 6.0) * sqrt(cores / 4); 32 if psutil unavailable |
tts_batch_size |
GPU: 512 (>=12 GB), 256 (>=8 GB), 128 (>=4 GB), 32 (else); CPU: from cpu_cores and total_ram_gb weighted metric, nearest power of 2 in [16, 256]; 32 if psutil unavailable |
Inference Parameters
The NanoInterpreter class (vendored from nanowakeword.interpreter.NanoInterpreter)
accepts the following keyword arguments via load_model():
from nanowakeword import NanoInterpreter
interpreter = NanoInterpreter.load_model(
model="my_model.onnx",
vad_threshold=0.5, # Enable VAD filtering
enable_noise_reduction=True, # Enable noise reduction
)enable_noise_reduction
- Type:
boolean - Default:
false - Description: When
true, applies stationary noise reduction (vianoisereduce) to each audio chunk before prediction. Requires thenoisereducepackage (pip install noisereduce).
vad_threshold
- Type:
float - Default:
0 - Description: When greater than
0, enables voice activity detection using Silero's VAD model. Audio chunks with no detected speech are suppressed (scores zeroed) before the wake word model runs, conserving CPU. The specific threshold behavior depends on the inference pipeline (local or remote). On the localNanoInterpreter, VAD scores are accumulated in an internal buffer; when the average VAD confidence is below this threshold, the wake word model is bypassed for that chunk.
Cascade (Gate + Verifier) Mode
When cascade=True is passed to load_model(), the interpreter
automatically looks for <model_name>_lite.onnx in the same directory and
uses it as a lightweight gatekeeper (Stage 1). The main model (Stage 2)
only runs when the gate score exceeds gate_threshold.
| Parameter | Type | Default | Description |
|---|---|---|---|
cascade |
boolean |
false |
Enable 2-stage cascade mode |
gate_model |
string |
Auto-discovered | Explicit path to a custom gate model |
gate_threshold |
float |
0.3 |
Gate score threshold to activate the verifier |
# Auto-discover lite model in same directory
interpreter = NanoInterpreter.load_model("my_model.onnx", cascade=True)
# Explicit gate model
interpreter = NanoInterpreter.load_model(
"my_model.onnx",
gate_model="custom_lite.onnx",
gate_threshold=0.25,
)Remote Verifier Mode
The interpreter can offload the verifier (Stage 2) to a remote WebSocket
server running the remote_verifier module.
| Parameter | Type | Default | Description |
|---|---|---|---|
remote_verifier |
string |
None | WebSocket URI (e.g. ws://192.168.1.100:8765) |
remote_pipeline |
string |
"verifier_only" |
"verifier_only" or "full" |
remote_timeout |
float |
2.0 |
Seconds to wait for server response |
remote_api_key |
string |
None | API key for server authentication |
remote_token |
string |
None | Token for server authentication |
remote_ssl_certfile |
string |
None | Client certificate for mTLS |
remote_ssl_keyfile |
string |
None | Client private key for mTLS |
remote_ssl_ca_certs |
string |
None | CA bundle for server TLS verification |
# Gate local, verifier remote (edge runs mel+embedding+gate)
interpreter = NanoInterpreter.load_model(
model="my_model_lite.onnx",
remote_verifier="ws://192.168.1.100:8765",
gate_threshold=0.25,
)
# Edge sends raw audio; server runs full pipeline
interpreter = NanoInterpreter.load_model(
model="my_model_lite.onnx",
remote_verifier="ws://192.168.1.100:8765",
remote_pipeline="full",
gate_threshold=0.25,
)predict() Parameters
result = interpreter.predict(
audio_chunk, # np.ndarray, int16 PCM
patience={}, # {model_name: n_frames}
threshold={}, # {model_name: value}
debounce_time=0.0, # seconds between detections
)| Parameter | Type | Default | Description |
|---|---|---|---|
x |
np.ndarray |
(required) | 16-bit PCM audio chunk |
patience |
dict |
{} |
Require N consecutive frames above threshold before firing |
threshold |
dict |
{} |
Per-model detection thresholds |
debounce_time |
float |
0.0 |
Suppress repeated detections within this many seconds |
patience and debounce_time cannot be used simultaneously. When using
either, threshold must also be provided.
DetectionResult
The predict() method returns a DetectionResult object with:
| Attribute | Type | Description |
|---|---|---|
scores |
dict |
Raw {model_name: score} mapping |
model_name |
string |
Primary model name |
score |
float |
Primary model's score |
gate_name |
string|None |
Gate model name (cascade mode) |
gate_score |
float |
Gate model score (0.0 if not in cascade) |
detected |
bool |
True if score >= threshold |
threshold |
float |
Threshold used for detected |
listen() Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
on_detection |
callable |
prints to console | Callback when detection fires: (model_name, score) |
threshold |
float |
0.5 |
Detection threshold (0–1) |
cooldown |
float |
1.0 |
Minimum seconds between detections |
chunk_size |
integer |
1280 |
Audio frames per inference chunk (80ms @ 16kHz) |
on_score |
callable |
None | Per-chunk callback: (verifier_score, gate_score) |
on_audio |
callable |
None | Per-chunk callback: (audio_array) |
blocking |
boolean |
true |
If true, blocks until Ctrl+C |
Server Configuration
The RemoteVerifier is a WebSocket server that hosts wake word model inference.
It is started via nanowakeword --model <path> or
python -m nanowakeword.interpreter.remote_verifier --model <path>.
Pipeline Modes
| Mode | Edge runs | Server runs | Wire format tag |
|---|---|---|---|
verifier_only |
mel + embedding + gate | verifier only | 0x01 (features) |
embedding |
mel | embedding + verifier | 0x02 (mel frames) |
full |
gate only | mel + embedding + verifier | 0x03 (raw audio) |
e2e |
gate only | E2E model | 0x03 (raw audio) |
Server CLI Arguments
| Flag | Description |
|---|---|
--model |
Path to .onnx model (required) |
--pipeline |
verifier_only, embedding, full, or e2e |
--host |
Bind address (default 0.0.0.0) |
--port |
Port (default 8765) |
--log |
Log level: DEBUG, INFO, WARNING, ERROR |
--api-key |
API key for auth (repeat for multiple) |
--enable-tokens |
Allow API key → token exchange |
--token-ttl |
Token lifetime in seconds (default 3600) |
--token-secret |
HMAC secret for token signing |
--rate-limit |
Max messages per window per IP (0 = disabled) |
--rate-window |
Rate limit window in seconds (default 60) |
--ip-allowlist |
Allowed IP or CIDR (repeat for multiple) |
--ssl-certfile / --ssl-keyfile |
TLS certificate and key |
--ssl-ca-certs |
CA bundle for mutual TLS |
--max-connections |
Max simultaneous clients (0 = unlimited) |
--ban-duration |
Ban seconds after rate-limit breach (default 300) |
Programmatic Server Usage
from nanowakeword.interpreter.remote_verifier import serve
from nanowakeword.interpreter import build_security
security = build_security(
api_keys=["my-secret-key"],
enable_tokens=True,
token_ttl=1800,
rate_limit=200,
rate_window=60,
ip_allowlist=["192.168.1.0/24"],
ssl_certfile="server.crt",
ssl_keyfile="server.key",
)
serve(
model_path="my_model.onnx",
pipeline="full",
host="0.0.0.0",
port=8765,
security=security,
)SecurityConfig Fields
| Field | Type | Default | Description |
|---|---|---|---|
api_keys |
list[str] |
[] |
Plaintext API keys (hashed in memory at startup) |
enable_tokens |
boolean |
false |
Enable API key → token exchange |
token_ttl |
integer |
3600 |
Token lifetime in seconds |
token_secret |
string |
auto-generated | HMAC secret for token signing |
rate_limit |
integer |
0 |
Max messages/window/IP (0 = disabled) |
rate_window |
integer |
60 |
Rate limit window in seconds |
ip_allowlist |
list[str] |
[] |
Allowed IPs/CIDRs (empty = allow all) |
ssl_certfile |
string |
None | PEM certificate for WSS/TLS |
ssl_keyfile |
string |
None | PEM private key for WSS/TLS |
ssl_ca_certs |
string |
None | CA bundle for mutual TLS |
max_connections |
integer |
0 |
Max simultaneous clients (0 = unlimited) |
ban_duration |
integer |
300 |
Ban duration after rate-limit breach |
Command-Line Arguments
The nanowakeword CLI entry point (defined in cli.py) supports:
# Full pipeline: generate + transform + train + distill
nanowakeword -c config.yaml -G -t -T -d
# Training only (uses pipeline flags from config file)
nanowakeword -c config.yaml -T
# Inspect a model file and exit
nanowakeword --info my_model.onnx
# Start the RemoteVerifier server
nanowakeword --model my_model.onnx --pipeline full --port 8765
# Resume from checkpoint
nanowakeword -c config.yaml --resume ./trained_models/my_model
# Force regenerate features
nanowakeword -c config.yaml --overwrite| Flag | Shorthand | Description |
|---|---|---|
--config |
-c |
Path to YAML config (required for training) |
--generate_clips |
-G |
Enable TTS clip generation stage |
--transform_clips |
-t |
Enable augmentation + feature extraction |
--train |
-T |
Enable model training |
--distill |
-d |
Generate lite model via distillation |
--force-verify |
-f |
Re-verify all data directories |
--overwrite |
Force regeneration of feature files | |
--resume |
Resume from a model directory checkpoint | |
--model |
Start RemoteVerifier server with this model | |
--pipeline |
Server pipeline mode: verifier_only or full |
|
--host |
Server bind address | |
--port |
Server port | |
--info |
Inspect an ONNX model file and exit |
CLI vs Config Precedence
When no pipeline flags (-G, -t, -T, -d) are provided on the command
line, the framework reads generate_clips, transform_clips, train_model,
and distill from the YAML config file. CLI flags always override
config file values when both are set.
Complete Example Configuration
# === Paths ===
output_dir: "./trained_models"
model_name: "my_hotword_v1"
positive_data_path: "./training_data/positive"
negative_data_path: "./training_data/negative"
background_paths:
- "./training_data/noise"
rir_paths:
- "./training_data/rir"
# === Mode & Architecture ===
mode: "embedding"
model_type: "conformer"
conformer_d_model: 144
conformer_n_head: 4
embedding_dim: 64
n_blocks: 4
layer_size: 192
dropout_prob: 0.3
activation_function: "gelu"
# === Data Generation (TTS) ===
generate_clips: true
target_phrase: "hey nano"
tts_settings:
models: "en_US-libritts_r-medium"
length_scales: [0.9, 1.0, 1.1]
noise_scales: [0.667, 0.8]
speaker_ids: [0, 1, 2, 3]
data_generation_tasks:
- name: "Positive Wake Words"
enabled: true
output_dir: "dataset/positive"
num_samples: 2000
text_source:
type: "fixed_phrase"
- name: "Hard Negatives"
enabled: true
output_dir: "dataset/negative"
num_samples: 2000
text_source:
type: "phoneme_adversarial"
min_distance: 0.4
# === Feature Generation ===
transform_clips: true
convert_audio: true
sample_rate: 16000
audio_processing:
autotune_length:
enabled: true
num_samples_to_inspect: 50
duration_buffer_ms: 750
min_allowable_length: 32000
snap_to_min_tolerance: 4000
augmentation_batch_size: 64
feature_gen_cpu_ratio: 0.6
augmentation_settings:
gain_prob: 1.0
min_gain_in_db: -2.0
max_gain_in_db: 2.0
pitch_prob: 0.3
min_pitch_semitones: -1.0
max_pitch_semitones: 1.0
min_snr_in_db: 5.0
max_snr_in_db: 30.0
rir_prob: 0.3
data_generation_manifest:
positive_features:
input_audio_dirs: ["./dataset/positive"]
output_filename: "positive_features.npy"
augmentation_rounds: 5
negative_features:
input_audio_dirs: ["./dataset/negative"]
output_filename: "negative_features.npy"
augmentation_rounds: 3
noise_features:
input_audio_dirs: ["./dataset/positive"]
output_filename: "noise_features.npy"
use_background_noise: true
augmentation_rounds: 3
# === Feature Manifest (for training) ===
feature_manifest:
targets:
p: "./trained_models/my_hotword_v1/features/positive_features.npy"
negatives:
n: "./trained_models/my_hotword_v1/features/negative_features.npy"
b: "./trained_models/my_hotword_v1/features/noise_features.npy"
targets_val:
p: "./trained_models/my_hotword_v1/features/val_positive.npy"
negatives_val:
n: "./trained_models/my_hotword_v1/features/val_negative.npy"
# === Training ===
train_model: true
batch_composition:
targets: 30
negatives: 230
num_workers: 4
optimizer_type: "adamw"
lr_scheduler_type: "onecycle"
weight_decay: 0.01
steps: 30000
LOSS_BIAS: 0.75
loss_function: "bias_weighted"
logit_reg_weight: 2e-4
logit_reg_margin: 6.0
# === Validation ===
val_interval: 500
val_subsample_batches: 0
val_miss_weight: 4.0
val_fp_weight: 1.0
# === Checkpointing ===
checkpointing:
enabled: true
interval_steps: 1000
limit: 3
early_stopping_patience: 0
val_early_stopping_patience: 5000
checkpoint_averaging_top_k: 5
# === Distillation ===
distillation:
enabled: true
steps: 8000
temperature: 4.0
alpha: 0.7
learning_rate: 5e-4
# === ONNX Export ===
onnx_opset_version: 17
# === Custom Export (optional) ===
# custom_export:
# script: "/path/to/export_to_tflite.py"
# onnx_opset_version: 17
# === Display & Logging ===
show_training_summary: true
debug_mode: false
enable_journaling: true
force_verify: false
