application.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. # -*- coding: utf-8 -*-
  2. """
  3. Trainer-Anwendung fuer Trixy ML-Modelle.
  4. Trainiert Wakeword- und Sprechererkennungsmodelle.
  5. (Urspruenglich trixy_core/trainer.py, jetzt Teil des Trainer-Packages)
  6. """
  7. from enum import Enum, auto
  8. from pathlib import Path
  9. from trixy_core.application import IApplication
  10. from trixy_core.config.datasets.trainer import TrainerConfig
  11. from trixy_core.utils.debug import pinfo, pdebug, perror, pwarn
  12. class TrainingTarget(Enum):
  13. """Zu trainierende Modelltypen."""
  14. WAKEWORD = auto()
  15. VOICE_RECOGNITION = auto()
  16. ALL = auto()
  17. class TrainerApplication(IApplication):
  18. """
  19. Trainer-Anwendung fuer ML-Modelle.
  20. Unterstuetzt das Training von:
  21. - Wakeword-Modellen
  22. - Sprechererkennungsmodellen
  23. """
  24. def __init__(
  25. self,
  26. target: TrainingTarget = TrainingTarget.ALL,
  27. config_path: str | Path = "config/trainer_config.json",
  28. debug: bool = False
  29. ) -> None:
  30. super().__init__(debug)
  31. self._target = target
  32. self._config_path = Path(config_path)
  33. self._trainer_config: TrainerConfig | None = None
  34. @property
  35. def trainer_config(self) -> TrainerConfig:
  36. """Trainer-Konfiguration."""
  37. if self._trainer_config is None:
  38. raise RuntimeError("Trainer nicht initialisiert")
  39. return self._trainer_config
  40. @property
  41. def target(self) -> TrainingTarget:
  42. """Trainings-Ziel."""
  43. return self._target
  44. async def initialize(self) -> None:
  45. """Initialisiert den Trainer."""
  46. pinfo("Initialisiere Trainer...")
  47. self._trainer_config = self.config_manager.load(
  48. self._config_path,
  49. TrainerConfig,
  50. name="trainer"
  51. )
  52. data_dir = Path(self._trainer_config.data.raw_data_directory)
  53. processed_dir = Path(self._trainer_config.data.processed_data_directory)
  54. cache_dir = Path(self._trainer_config.data.cache_directory)
  55. output_dir = Path(self._trainer_config.output.models_directory)
  56. for directory in [data_dir, processed_dir, cache_dir, output_dir]:
  57. directory.mkdir(parents=True, exist_ok=True)
  58. pdebug(f"Trainer initialisiert fuer: {self._target.name}")
  59. async def start(self) -> None:
  60. """Startet das Training."""
  61. pinfo(f"Starte Training: {self._target.name}")
  62. if self._target in (TrainingTarget.WAKEWORD, TrainingTarget.ALL):
  63. await self._train_wakeword()
  64. if self._target in (TrainingTarget.VOICE_RECOGNITION, TrainingTarget.ALL):
  65. await self._train_voice_recognition()
  66. pinfo("Training abgeschlossen")
  67. self.shutdown()
  68. async def stop(self) -> None:
  69. """Stoppt den Trainer."""
  70. pinfo("Trainer beendet")
  71. self.config_manager.stop_watching()
  72. async def _train_wakeword(self) -> None:
  73. """Trainiert Wakeword-Modelle."""
  74. pinfo("Trainiere Wakeword-Modell...")
  75. config = self._trainer_config.wakeword
  76. pdebug(f"Modell: {config.model_name}")
  77. pdebug(f"Epochen: {config.epochs}")
  78. pdebug(f"Batch-Groesse: {config.batch_size}")
  79. data_path = Path(self._trainer_config.data.raw_data_directory) / "wakeword"
  80. if not data_path.exists():
  81. pwarn(f"Keine Trainingsdaten gefunden: {data_path}")
  82. return
  83. samples = list(data_path.rglob("*.wav"))
  84. pinfo(f"Gefundene Samples: {len(samples)}")
  85. if len(samples) < self._trainer_config.data.min_samples_per_class:
  86. pwarn("Zu wenige Trainingsdaten")
  87. return
  88. pinfo("Wakeword-Training abgeschlossen")
  89. async def _train_voice_recognition(self) -> None:
  90. """Trainiert Sprechererkennungsmodelle."""
  91. pinfo("Trainiere Sprechererkennungs-Modell...")
  92. config = self._trainer_config.voice_recognition
  93. pdebug(f"Modell: {config.model_name}")
  94. pdebug(f"Epochen: {config.epochs}")
  95. pdebug(f"Embedding-Groesse: {config.embedding_size}")
  96. data_path = Path(self._trainer_config.data.raw_data_directory) / "voice_recognition"
  97. if not data_path.exists():
  98. pwarn(f"Keine Trainingsdaten gefunden: {data_path}")
  99. return
  100. speakers = [d for d in data_path.iterdir() if d.is_dir()]
  101. pinfo(f"Gefundene Sprecher: {len(speakers)}")
  102. for speaker_dir in speakers:
  103. samples = list(speaker_dir.glob("*.wav"))
  104. pdebug(f" {speaker_dir.name}: {len(samples)} Samples")
  105. pinfo("Sprechererkennungs-Training abgeschlossen")