{"id":31214446,"url":"https://github.com/openvoiceos/precise-lite-trainer","last_synced_at":"2025-09-21T09:59:15.981Z","repository":{"id":271949187,"uuid":"626901957","full_name":"OpenVoiceOS/precise-lite-trainer","owner":"OpenVoiceOS","description":"train wake word models","archived":false,"fork":false,"pushed_at":"2025-01-25T07:36:59.000Z","size":310,"stargazers_count":5,"open_issues_count":0,"forks_count":2,"subscribers_count":5,"default_branch":"dev","last_synced_at":"2025-01-31T06:41:43.242Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/OpenVoiceOS.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-04-12T11:44:05.000Z","updated_at":"2025-01-25T08:56:02.000Z","dependencies_parsed_at":"2025-01-11T00:21:54.526Z","dependency_job_id":"e1dcf640-2d60-4381-a3f4-df20ea1d72c4","html_url":"https://github.com/OpenVoiceOS/precise-lite-trainer","commit_stats":null,"previous_names":["openvoiceos/precise-lite-trainer"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/OpenVoiceOS/precise-lite-trainer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenVoiceOS%2Fprecise-lite-trainer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenVoiceOS%2Fprecise-lite-trainer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenVoiceOS%2Fprecise-lite-trainer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenVoiceOS%2Fprecise-lite-trainer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/OpenVoiceOS","download_url":"https://codeload.github.com/OpenVoiceOS/precise-lite-trainer/tar.gz/refs/heads/dev","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenVoiceOS%2Fprecise-lite-trainer/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":276223241,"owners_count":25605793,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-21T02:00:07.055Z","response_time":72,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-09-21T09:59:14.931Z","updated_at":"2025-09-21T09:59:15.971Z","avatar_url":"https://github.com/OpenVoiceOS.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# OpenVoiceOS precise trainer\n\n### Model Architecture\n\nThe wake word detection model is designed to be lightweight and efficient, suitable for real-time applications. It processes audio features using a simple architecture:\n\n1. **Recurrent Layer**: A GRU layer captures temporal patterns in audio, enabling the model to understand sequential dependencies.\n2. **Output Layer**: A fully connected layer with a sigmoid activation outputs the probability of the wake word being present.\n3. **Custom Loss and Metrics**: The model uses a weighted loss function to balance sensitivity and specificity, with metrics like accuracy, false positives, and false negatives for detailed evaluation.\n\nThis streamlined design ensures robust performance with low computational overhead, making it ideal for resource-constrained environments.\n\n### Resources\n\n- [@SecretSauceAI Wake Word Data Collector](https://github.com/secretsauceai/wakeword-data-collector)\n- [@SecretSauceAI Wake Word Trainer](https://github.com/secretsauceai/precise-wakeword-model-maker)\n- [Synthetic Data Creation for Wake Words](https://github.com/OpenVoiceOS/ovos-ww-auto-synth-dataset)\n- [Helpful Wake Word Datasets](https://huggingface.co/collections/Jarbas/wake-word-datasets-672cc275fa4bddff9cf69c39)\n- [Architecture experiments from @MycroftAI](https://github.com/MycroftAI/mycroft-precise/wiki/Research)\n- [Original training guide from @MycroftAI](https://github.com/MycroftAI/mycroft-precise/wiki/Training-your-own-wake-word) , contains details about dataset format etc\n\n\n# Converting / Testing\n\n```python\nfrom precise_trainer import PreciseTrainer\n\n# convert a previous model\nmodel_file = \".../my_model.keras\"\nPreciseTrainer.convert(model_file, model_file + \".tflite\")\n\n# test a previous model\nmodel_file = \".../my_model.tflite\"\nfolder = f\"/home/user/ww_datasets/my_dataset\"  # dataset here\nPreciseTrainer.test_from_file(model_file, folder)\n```\n\n⚠️ to convert old `.net` format precise models you need `tensorflow\u003c=2.15.1` otherwise will get an error like this\n\u003e ValueError: File format not supported: Keras 3 only supports V3 `.keras` files and legacy H5 format files (`.h5` extension). Note that the legacy SavedModel format is not supported by `load_model()` in Keras 3.\n\n# Training\n\nSeveral training strategies are available, each may provide better results for different datasets and wake words, some sounds might be easier to learn than others and the kinds of data available for each word will be different\n\n| Strategy                              | Description                                                                                   |\n|---------------------------------------|-----------------------------------------------------------------------------------------------|\n| `train`                               | Standard training with selected epochs and batch size.                                        |\n| `train_with_replacement`              | Avoid overfitting by replacing the training subset every epoch.                               |\n| `train_incremental`                   | Add false positives from testing set to training set, useful for unbalanced datasets.         |\n| `train_incremental_with_replacement`  | Combines incremental training with replacement for more robust models.                        |\n| `train_optimized`                     | Searches for optimal hyperparameters using `bbopt` and keeps the best model.                 |\n| `train_optimized_incremental`         | Combines incremental training with hyperparameter optimization.                               |\n| `train_optimized_with_replacement`    | Combines optimized training with replacement to reduce overfitting and improve robustness.    |\n\n\n```python\nfrom precise_trainer import PreciseTrainer\n\nmodel_name = \"hey_computer\"\nfolder = f\"/home/user/ww_datasets/{model_name}\"  # dataset here\nmodel_path = f\"/home/user/trained_models/{model_name}\"  # save here\nlog_dir = f\"logs/fit/{model_name}\"  # for tensorboard\n\n# train a model\ntrainer = PreciseTrainer(model_path, folder, epochs=100, log_dir=log_dir)\nmodel_file = trainer.train()\n# Data: \u003cTrainData wake_words=155 not_wake_words=89356 test_wake_words=39 test_not_wake_words=22339\u003e\n# Loading wake-word...\n# Loading not-wake-word...\n# Loading wake-word...\n# Loading not-wake-word...\n# Inputs shape: (81602, 29, 13)\n# Outputs shape: (81602, 1)\n# Test inputs shape: (20486, 29, 13)\n# Test outputs shape: (20486, 1)\n# Model: \"sequential\"\n# _________________________________________________________________\n#  Layer (type)                Output Shape              Param #   \n# =================================================================\n#  net (GRU)                   (None, 20)                2100      \n#                                                                  \n#  dense (Dense)               (None, 1)                 21        \n#                                                                  \n# =================================================================\n# Total params: 2,121\n# Trainable params: 2,121\n# Non-trainable params: 0\n# .....\n# _________________________________________________________________\n# Epoch 1280/1379\n# 157/160 [============================\u003e.] - ETA: 0s - loss: 0.0308 - accuracy: 0.9868\n# ....\n# Wrote to /home/miro/PycharmProjects/ovos-audio-classifiers/trained/hey_computer/model.tflite\ntrainer.test()\n\n# === Counts ===\n# False Positives: 2\n# True Negatives: 20445\n# False Negatives: 2\n# True Positives: 37\n# \n# === Summary ===\n# 20482 out of 20486\n# 99.98%\n# \n# 0.01% false positives\n# 5.13% false negatives\n\n```\ntensorboard should produce something like this\n\n![](./normal_training.png)\n\n\n# Train with replacement\n\n```python\nfrom precise_trainer import PreciseTrainer\n\nmodel_name = \"hey_computer\"\nfolder = f\"/home/user/ww_datasets/{model_name}\"  # dataset here\nmodel_path = f\"/home/user/trained_models/{model_name}\"  # save here\nlog_dir = f\"logs/fit/{model_name}\"  # for tensorboard\n\n# train a model\ntrainer = PreciseTrainer(model_path, folder, epochs=100, log_dir=log_dir)\nmodel_file = trainer.train_with_replacement(mini_epochs=10)\ntrainer.test()\n```\ntensorboard should produce something like this\n\n![](./train_with_replacement.png)\n\n# Train incremental\n\n```python\nfrom precise_trainer import PreciseTrainer\n\nmodel_name = \"hey_computer\"\nfolder = f\"/home/user/ww_datasets/{model_name}\"  # dataset here\nmodel_path = f\"/home/user/trained_models/{model_name}\"  # save here\nlog_dir = f\"logs/fit/{model_name}\"  # for tensorboard\n\n# train a model\ntrainer = PreciseTrainer(model_path, folder, epochs=100, log_dir=log_dir)\n\n# pick one training method\nmodel_file = trainer.train_incremental(mini_epochs=20)\n# model_file = trainer.train_incremental_with_replacement(balanced=True, porportion=0.6)\ntrainer.test()\n```\n\n\n# Train optimized\n\n\n```python\nfrom precise_trainer import PreciseTrainer\n\nmodel_name = \"hey_computer\"\nfolder = f\"/home/user/ww_datasets/{model_name}\"  # dataset here\nmodel_path = f\"/home/user/trained_models/{model_name}\"  # save here\nlog_dir = f\"logs/fit/{model_name}\"  # for tensorboard\n\n# train a model\ntrainer = PreciseTrainer(model_path, folder, epochs=100, log_dir=log_dir)\n\n# pick one training method\nmodel_file = trainer.train_optimized(cycles=20)\n# model_file = trainer.train_optimized_with_replacement(porportion=0.8)\n# model_file = trainer.train_optimized_incremental(cycles=50)\ntrainer.test()\n```\n\ntensorboard should produce something like this\n\n![](./train_optimized.png)\n\n\n# Credits\n\n[Precise](https://github.com/MycroftAI/mycroft-precise) was originally developed by @MycroftAI\n\n![image](https://github.com/user-attachments/assets/d68b9124-92fc-4e66-9e83-59ac10a72ea8)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenvoiceos%2Fprecise-lite-trainer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopenvoiceos%2Fprecise-lite-trainer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenvoiceos%2Fprecise-lite-trainer/lists"}