pytorch_adv_trainer.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. import os
  2. import time
  3. import json
  4. import torch
  5. import torch.optim as optim
  6. import pandas as pd
  7. import numpy as np
  8. from torch.utils.data import DataLoader
  9. from sklearn.model_selection import train_test_split
  10. from utils.training_interface import TrainerInterface
  11. from utils.file_utils import list_files_in_directory
  12. from utils.pytorch_utils import WakeWordDataset, CNNNetwork, preprocess_training_data, train_model, optimize_graph
  13. # Global variables for tracking progress
  14. current_progress = 0
  15. current_loss = 0.0
  16. current_accuracy = 0.0
  17. total_epochs = 0
  18. total_batches = 0
  19. class pytorch_adv_trainer(TrainerInterface):
  20. def __init__(self, learning_rate=0.001):
  21. self.model_path = None
  22. self.training_directories = []
  23. self.sample_directory = None
  24. self.background_directory = None
  25. self.dropout_rate = 0.5
  26. self.epochs = 10
  27. self.batch_size = 32
  28. self.learning_rate = learning_rate
  29. self.model = None
  30. self.optimizer = None
  31. self.criterion = torch.nn.BCEWithLogitsLoss()
  32. self.current_epoch = 0
  33. self.stop_training = False
  34. self.training_status = "Not started"
  35. self.train_loader = None
  36. self.val_loader = None
  37. def set_model_path(self, model_path):
  38. self.model_path = model_path
  39. self.model = self.load_model()
  40. self.optimizer = optim.Adam(self.model.parameters(), lr=self.learning_rate)
  41. def set_training_directories(self, directories):
  42. self.training_directories = directories
  43. def set_sample_directory(self, directory):
  44. self.sample_directory = directory
  45. def set_background_directory(self, directory):
  46. self.background_directory = directory
  47. def set_dropout_rate(self, rate):
  48. self.dropout_rate = rate
  49. def set_epochs(self, epochs):
  50. self.epochs = epochs
  51. def set_batch_size(self, batch_size):
  52. self.batch_size = batch_size
  53. def get_training_data(self):
  54. return self.training_directories
  55. def get_model_path(self):
  56. return self.model_path
  57. def get_epochs(self):
  58. return self.epochs
  59. def get_batch_size(self):
  60. return self.batch_size
  61. def get_dropout_rate(self):
  62. return self.dropout_rate
  63. def get_training_directories(self):
  64. return self.training_directories
  65. def get_sample_directory(self):
  66. return self.sample_directory
  67. def get_background_directory(self):
  68. return self.background_directory
  69. def set_training_data(self, features, labels):
  70. X_train, X_val, y_train, y_val = train_test_split(features, labels, test_size=0.2, random_state=42)
  71. self.train_loader = DataLoader(WakeWordDataset(X_train, y_train), batch_size=self.batch_size, shuffle=True)
  72. self.val_loader = DataLoader(WakeWordDataset(X_val, y_val), batch_size=self.batch_size, shuffle=False)
  73. def load_model(self):
  74. model = CNNNetwork()
  75. if os.path.exists(self.model_path + "hotword_model.pth"):
  76. state_dict = torch.load(self.model_path + "hotword_model.pth")
  77. # Update the state_dict keys to match the model keys
  78. new_state_dict = {f'network.{k}': v for k, v in state_dict.items()}
  79. model.load_state_dict(new_state_dict)
  80. return model
  81. def start(self):
  82. self.training_status = "Training"
  83. self.stop_training = False
  84. self.run_training()
  85. def start_new(self):
  86. self.training_status = "Training"
  87. self.stop_training = False
  88. self.model = self.load_model()
  89. self.current_epoch = 0
  90. self.run_training()
  91. def pause(self):
  92. self.training_status = "Paused"
  93. self.stop_training = True
  94. def resume(self):
  95. self.training_status = "Training"
  96. self.stop_training = False
  97. self.run_training()
  98. def stop(self):
  99. self.training_status = "Stopped"
  100. self.stop_training = True
  101. def preprocess_training_data(self, update_progress_callback):
  102. preprocess_training_data(self.training_directories, self.background_directory, self.model_path, update_progress_callback)
  103. def run_training(self):
  104. global current_progress, current_loss, current_accuracy, total_epochs, total_batches
  105. self.preprocess_training_data(lambda progress: setattr(self, 'current_progress', progress))
  106. df = pd.read_pickle(self.model_path + "audio_data.csv")
  107. X = df["feature"].values
  108. X = np.concatenate(X, axis=0).reshape(len(X), 40)
  109. y = np.array(df["class_label"].tolist())
  110. self.set_training_data(X, y)
  111. total_batches = int(np.ceil(len(self.train_loader.dataset) / self.batch_size))
  112. total_epochs = self.epochs
  113. for epoch in range(self.current_epoch, self.epochs):
  114. if self.stop_training:
  115. break
  116. self.current_epoch = epoch
  117. train_model(self.model, self.train_loader, self.optimizer, self.criterion, epoch, self.epochs)
  118. current_progress = (epoch + 1) / self.epochs * 100
  119. print(f"Epoch {epoch + 1}/{self.epochs}")
  120. if not self.stop_training:
  121. torch.save(self.model.state_dict(), self.model_path + "hotword_model.pth")
  122. self.evaluate_model(X, y)
  123. self.training_status = "Finished"
  124. def evaluate_model(self, X_test, y_test):
  125. self.model.eval()
  126. with torch.no_grad():
  127. X_test_tensor = torch.FloatTensor(X_test)
  128. y_test_tensor = torch.LongTensor(y_test)
  129. outputs = self.model(X_test_tensor)
  130. _, predicted = torch.max(outputs, 1)
  131. accuracy = (predicted == y_test_tensor).sum().item() / len(y_test_tensor)
  132. print(f"Test Accuracy: {accuracy * 100:.2f}%")
  133. def get_training_info(self):
  134. return {
  135. "status": self.training_status,
  136. "current_epoch": self.current_epoch,
  137. "total_epochs": self.epochs,
  138. "loss": current_loss,
  139. "accuracy": current_accuracy
  140. }