diff --git a/birdnet_analyzer/gui/train.py b/birdnet_analyzer/gui/train.py index b972b60f7..7ed288be1 100644 --- a/birdnet_analyzer/gui/train.py +++ b/birdnet_analyzer/gui/train.py @@ -68,6 +68,7 @@ def start_training( upsampling_mode, model_format, audio_speed, + save_detached_classifier, progress=gr.Progress(), ): """Starts the training of a custom classifier. @@ -104,7 +105,7 @@ def start_training( upsampling_mode: Mode for upsampling (repeat, mean, smote). model_format: Format to save the trained model (tflite, raven, both). audio_speed: Speed factor for audio playback. - + save_detached_classifier: Whether to save the detached classifier. Returns: Returns a matplotlib.pyplot figure. """ @@ -146,6 +147,9 @@ def start_training( if cache_mode == "load" and not os.path.isfile(cache_file): raise gr.Error(loc.localize("validation-no-cache-file-selected")) + if model_save_mode == "append" and save_detached_classifier: + gr.Warning(loc.localize("training-tab-warning-detached-classifier-append")) + def data_load_progression(num_files, num_total_files, label): if progress is not None: progress( @@ -218,6 +222,7 @@ def trial_progression(trial): autotune_trials=int(autotune_trials), autotune_n_splits=int(autotune_folds), autotune_n_repeats=int(autotune_repeats), + save_detached_classifier=save_detached_classifier, ) except Exception as e: if e.args and len(e.args) > 1: @@ -338,10 +343,10 @@ def selection_fn(): rtl=True, ) - with gr.Column(): + with gr.Column(visible=False) as classifier_settings_column: classifier_name = gr.Textbox( "CustomClassifier", - visible=False, + interactive=True, info=loc.localize("training-tab-classifier-textbox-info"), ) output_format = gr.Radio( @@ -353,7 +358,17 @@ def selection_fn(): value="tflite", label=loc.localize("training-tab-output-format-radio-label"), info=loc.localize("training-tab-output-format-radio-info"), - visible=False, + interactive=True, + ) + save_detached_classifier_checkbox = gr.Checkbox( + False, + label=loc.localize( + "training-tab-save-detached-classifier-checkbox-label" + ), + info=loc.localize( + "training-tab-save-detached-classifier-checkbox-info" + ), + interactive=True, ) def select_classifier_directory_and_update_tb(): @@ -363,8 +378,8 @@ def select_classifier_directory_and_update_tb(): return ( dir_name, dir_name, - gr.update(label=dir_name, visible=True), - gr.update(visible=True, interactive=True), + gr.update(label=dir_name), + gr.update(visible=True), ) return gr.update(), gr.update(), gr.update(), gr.update() @@ -375,7 +390,7 @@ def select_classifier_directory_and_update_tb(): output_directory_state, selected_output_textbox, classifier_name, - output_format, + classifier_settings_column, ], show_progress="hidden", ) @@ -869,6 +884,7 @@ def train_and_show_metrics(*args): upsampling_mode, output_format, audio_speed_slider, + save_detached_classifier_checkbox, ], outputs=[train_history_plot, metrics_table], ) diff --git a/birdnet_analyzer/lang/de.json b/birdnet_analyzer/lang/de.json index 47c233f47..08ce880f1 100644 --- a/birdnet_analyzer/lang/de.json +++ b/birdnet_analyzer/lang/de.json @@ -353,6 +353,8 @@ "training-tab-output-format-radio-info": "Format des trainierten Klassifikators.", "training-tab-output-format-radio-label": "Modellausgabeformat", "training-tab-preprocessing-accordion-label": "Vorverarbeitung", + "training-tab-save-detached-classifier-checkbox-info": "Speichert den Klassifikatorkopf als eigenständiges Modell, um die Dateigröße zu reduzieren", + "training-tab-save-detached-classifier-checkbox-label": "Eigenständigen Klassifikator speichern", "training-tab-select-output-button-label": "Ausgabeverzeichnis für Klassifikator auswählen", "training-tab-select-output-textbox-placeholder": "Kein Ausgabeverzeichnis ausgewählt", "training-tab-start-training-button-label": "Training starten", @@ -367,6 +369,7 @@ "training-tab-upsampling-radio-option-smote": "SMOTE", "training-tab-upsampling-ratio-slider-info": "Das Mindestverhältnis für eine Minderheitenklasse im Vergleich zur Mehrheitsklasse nach dem Upsampling.", "training-tab-upsampling-ratio-slider-label": "Upsampling-Verhältnis", + "training-tab-warning-detached-classifier-append": "Der \"Anhängen\"-Modus wird für den abgekoppelten Klassifikator nicht angewendet.", "training-tab-use-focal-loss-checkbox-info": "Verwendet Focal Loss während des Trainings. Dies gibt schwierigen Beispielen mehr Gewicht und hilft, Klassenungleichgewichte zu bewältigen.", "training-tab-use-focal-loss-checkbox-label": "Focal Loss verwenden", "training-tab-use-labelsmoothing-checkbox-info": "Wendet Label Smoothing während des Trainings an. Dies kann die Generalisierung des Modells verbessern, indem es verhindert, dass das Modell zu selbstsicher wird.", diff --git a/birdnet_analyzer/lang/en.json b/birdnet_analyzer/lang/en.json index 8933fa053..3fa95b7ac 100644 --- a/birdnet_analyzer/lang/en.json +++ b/birdnet_analyzer/lang/en.json @@ -353,6 +353,8 @@ "training-tab-output-format-radio-info": "Format of the trained classifier.", "training-tab-output-format-radio-label": "Model output format", "training-tab-preprocessing-accordion-label": "Preprocessing", + "training-tab-save-detached-classifier-checkbox-info": "Saves the classifier head as detached model to reduce size", + "training-tab-save-detached-classifier-checkbox-label": "Save detached classifier", "training-tab-select-output-button-label": "Select classifier output", "training-tab-select-output-textbox-placeholder": "No output directory selected", "training-tab-start-training-button-label": "Start training", @@ -367,6 +369,7 @@ "training-tab-upsampling-radio-option-smote": "SMOTE", "training-tab-upsampling-ratio-slider-info": "The minimum ratio for a minority class compared to the majority class after upsampling.", "training-tab-upsampling-ratio-slider-label": "Upsampling ratio", + "training-tab-warning-detached-classifier-append": "Append mode will not apply to the detached classifier.", "training-tab-use-focal-loss-checkbox-info": "Uses focal loss during training. This gives more weight to hard examples and helps handle class imbalance.", "training-tab-use-focal-loss-checkbox-label": "Use focal loss", "training-tab-use-labelsmoothing-checkbox-info": "Applies label smoothing during training. This can help improve model generalization by preventing the model from becoming too confident.", diff --git a/birdnet_analyzer/lang/fi.json b/birdnet_analyzer/lang/fi.json index f98ea5d07..7080400e1 100644 --- a/birdnet_analyzer/lang/fi.json +++ b/birdnet_analyzer/lang/fi.json @@ -353,6 +353,8 @@ "training-tab-output-format-radio-info": "Koulutetun luokittelijan muoto.", "training-tab-output-format-radio-label": "Mallin tulostemuoto", "training-tab-preprocessing-accordion-label": "Esikäsittely", + "training-tab-save-detached-classifier-checkbox-info": "Tallentaa luokittimen pään erillisenä mallina koon pienentämiseksi", + "training-tab-save-detached-classifier-checkbox-label": "Tallenna erillinen luokitin", "training-tab-select-output-button-label": "Valitse luokittelijan tuloste", "training-tab-select-output-textbox-placeholder": "Tulostehakemistoa ei valittu", "training-tab-start-training-button-label": "Aloita koulutus", @@ -367,6 +369,7 @@ "training-tab-upsampling-radio-option-smote": "SMOTE", "training-tab-upsampling-ratio-slider-info": "Vähemmistöluokan vähimmäissuhde enemmistöluokkaan verrattuna ylösnäytteistyksen jälkeen.", "training-tab-upsampling-ratio-slider-label": "Ylösnäytteistyssuhde", + "training-tab-warning-detached-classifier-append": "Liitä-tila ei koske irrotettua luokitinta.", "training-tab-use-focal-loss-checkbox-info": "Käyttää focal lossia koulutuksen aikana. Tämä antaa enemmän painoarvoa vaikeille esimerkeille ja auttaa käsittelemään luokkien epätasapainoa.", "training-tab-use-focal-loss-checkbox-label": "Käytä focal lossia", "training-tab-use-labelsmoothing-checkbox-info": "Soveltaa label smoothingia koulutuksen aikana. Tämä voi parantaa mallin yleistämistä estämällä mallia tulemasta liian itsevarmaksi.", diff --git a/birdnet_analyzer/lang/fr.json b/birdnet_analyzer/lang/fr.json index ee6a32fe7..79fe3750a 100644 --- a/birdnet_analyzer/lang/fr.json +++ b/birdnet_analyzer/lang/fr.json @@ -353,6 +353,8 @@ "training-tab-output-format-radio-info": "Format du classificateur formé.", "training-tab-output-format-radio-label": "Format de sortie du modèle", "training-tab-preprocessing-accordion-label": "Prétraitement", + "training-tab-save-detached-classifier-checkbox-info": "Enregistre la tête du classificateur comme modèle détaché pour réduire la taille", + "training-tab-save-detached-classifier-checkbox-label": "Enregistrer le classificateur détaché", "training-tab-select-output-button-label": "Sélectionner la sortie du classificateur", "training-tab-select-output-textbox-placeholder": "Aucun répertoire de sortie sélectionné", "training-tab-start-training-button-label": "Commencer l’apprentissage", @@ -367,6 +369,7 @@ "training-tab-upsampling-radio-option-smote": "SMOTE", "training-tab-upsampling-ratio-slider-info": "Le ratio minimum pour une classe minoritaire par rapport à la classe majoritaire après le rééchantillonnage.", "training-tab-upsampling-ratio-slider-label": "Rapport de suréchantillonnage", + "training-tab-warning-detached-classifier-append": "Le mode d'ajout ne s'appliquera pas au classificateur détaché.", "training-tab-use-focal-loss-checkbox-info": "Utilise la perte focale pendant l'entraînement. Cela donne plus de poids aux exemples difficiles et aide à gérer le déséquilibre des classes.", "training-tab-use-focal-loss-checkbox-label": "Utiliser la perte focale", "training-tab-use-labelsmoothing-checkbox-info": "Applique le lissage des étiquettes pendant l'entraînement. Cela peut améliorer la généralisation du modèle en empêchant le modèle de devenir trop confiant.", diff --git a/birdnet_analyzer/lang/id.json b/birdnet_analyzer/lang/id.json index 787533f7d..534265b57 100644 --- a/birdnet_analyzer/lang/id.json +++ b/birdnet_analyzer/lang/id.json @@ -353,6 +353,8 @@ "training-tab-output-format-radio-info": "Format klasifikator yang telah dilatih.", "training-tab-output-format-radio-label": "Format output model", "training-tab-preprocessing-accordion-label": "Praproses", + "training-tab-save-detached-classifier-checkbox-info": "Menyimpan kepala pengklasifikasi sebagai model terpisah untuk mengurangi ukuran", + "training-tab-save-detached-classifier-checkbox-label": "Simpan pengklasifikasi terpisah", "training-tab-select-output-button-label": "Pilih klasifikator output", "training-tab-select-output-textbox-placeholder": "Tidak ada direktori output yang dipilih", "training-tab-start-training-button-label": "Mulai pelatihan", @@ -367,6 +369,7 @@ "training-tab-upsampling-radio-option-smote": "SMOTE", "training-tab-upsampling-ratio-slider-info": "Rasio minimum untuk kelas minoritas dibandingkan dengan kelas mayoritas setelah peningkatan sampel.", "training-tab-upsampling-ratio-slider-label": "Rasio peningkatan sampel", + "training-tab-warning-detached-classifier-append": "Mode tambah tidak akan berlaku untuk pengklasifikasi terlepas.", "training-tab-use-focal-loss-checkbox-info": "Menggunakan focal loss selama pelatihan. Ini memberikan bobot lebih pada contoh yang sulit dan membantu menangani ketidakseimbangan kelas.", "training-tab-use-focal-loss-checkbox-label": "Gunakan focal loss", "training-tab-use-labelsmoothing-checkbox-info": "Menerapkan label smoothing selama pelatihan. Ini dapat membantu meningkatkan generalisasi model dengan mencegah model menjadi terlalu percaya diri.", diff --git a/birdnet_analyzer/lang/pt-br.json b/birdnet_analyzer/lang/pt-br.json index a10ea59c6..121f80ace 100644 --- a/birdnet_analyzer/lang/pt-br.json +++ b/birdnet_analyzer/lang/pt-br.json @@ -353,6 +353,8 @@ "training-tab-output-format-radio-info": "Formato do classificador treinado.", "training-tab-output-format-radio-label": "Formato da saída do modelo", "training-tab-preprocessing-accordion-label": "Pré-processamento", + "training-tab-save-detached-classifier-checkbox-info": "Salva a cabeça do classificador como modelo desacoplado para reduzir o tamanho", + "training-tab-save-detached-classifier-checkbox-label": "Salvar classificador desacoplado", "training-tab-select-output-button-label": "Selecionar a saída do classificador", "training-tab-select-output-textbox-placeholder": "Nenhum diretório de saída selecionado", "training-tab-start-training-button-label": "Comece o treinamento", @@ -367,6 +369,7 @@ "training-tab-upsampling-radio-option-smote": "SMOTE", "training-tab-upsampling-ratio-slider-info": "A proporção mínima para uma classe minoritária em comparação com a classe majoritária após a amostragem adicional.", "training-tab-upsampling-ratio-slider-label": "Taxa de upsampling", + "training-tab-warning-detached-classifier-append": "O modo de acréscimo não será aplicado ao classificador desanexado.", "training-tab-use-focal-loss-checkbox-info": "Usa perda focal durante o treinamento. Isso dá mais peso a exemplos difíceis e ajuda a lidar com o desequilíbrio de classes.", "training-tab-use-focal-loss-checkbox-label": "Usar perda focal", "training-tab-use-labelsmoothing-checkbox-info": "Aplica suavização de rótulos durante o treinamento. Isso pode melhorar a generalização do modelo, evitando que ele se torne excessivamente confiante.", diff --git a/birdnet_analyzer/lang/ru.json b/birdnet_analyzer/lang/ru.json index 2a155eeca..54638a622 100644 --- a/birdnet_analyzer/lang/ru.json +++ b/birdnet_analyzer/lang/ru.json @@ -353,6 +353,8 @@ "training-tab-output-format-radio-info": "Формат обученного классификатора.", "training-tab-output-format-radio-label": "Формат вывода модели", "training-tab-preprocessing-accordion-label": "Предобработка", + "training-tab-save-detached-classifier-checkbox-info": "Сохраняет голову классификатора как отдельную модель для уменьшения размера", + "training-tab-save-detached-classifier-checkbox-label": "Сохранить отдельный классификатор", "training-tab-select-output-button-label": "Выбор выходных данных классификатора", "training-tab-select-output-textbox-placeholder": "Каталог вывода не выбран", "training-tab-start-training-button-label": "Начало обучения", @@ -367,6 +369,7 @@ "training-tab-upsampling-radio-option-smote": "SMOTE", "training-tab-upsampling-ratio-slider-info": "Минимальный коэффициент для меньшего класса по сравнению с большим классом после повышения выборки.", "training-tab-upsampling-ratio-slider-label": "Коэффициент повышения дискретизации", + "training-tab-warning-detached-classifier-append": "Режим добавления не применяется к отсоединённому классификатору.", "training-tab-use-focal-loss-checkbox-info": "Использует фокальную потерю во время обучения. Это придает больший вес сложным примерам и помогает справляться с дисбалансом классов.", "training-tab-use-focal-loss-checkbox-label": "Использовать фокальную потерю", "training-tab-use-labelsmoothing-checkbox-info": "Применяет сглаживание меток во время обучения. Это может улучшить обобщение модели, предотвращая излишнюю уверенность модели.", diff --git a/birdnet_analyzer/lang/se.json b/birdnet_analyzer/lang/se.json index 7002f966c..875f537f3 100644 --- a/birdnet_analyzer/lang/se.json +++ b/birdnet_analyzer/lang/se.json @@ -353,6 +353,8 @@ "training-tab-output-format-radio-info": "Format för den tränade klassificeraren.", "training-tab-output-format-radio-label": "Modell utdataformat", "training-tab-preprocessing-accordion-label": "Förbehandling", + "training-tab-save-detached-classifier-checkbox-info": "Sparar klassificerarens huvud som en fristående modell för att minska storleken", + "training-tab-save-detached-classifier-checkbox-label": "Spara fristående klassificerare", "training-tab-select-output-button-label": "Välj klassificerarens utdata", "training-tab-select-output-textbox-placeholder": "Ingen utdatakatalog vald", "training-tab-start-training-button-label": "Starta träning", @@ -367,6 +369,7 @@ "training-tab-upsampling-radio-option-smote": "SMOTE", "training-tab-upsampling-ratio-slider-info": "Minsta förhållandet för en minoritetsklass jämfört med majoritetsklass efter upsampling.", "training-tab-upsampling-ratio-slider-label": "Upsamplingsförhållande", + "training-tab-warning-detached-classifier-append": "Tilläggsläget gäller inte för den fristående klassificeraren.", "training-tab-use-focal-loss-checkbox-info": "Använder fokalförlust under träning. Detta ger mer vikt till svåra exempel och hjälper till att hantera klassobalans.", "training-tab-use-focal-loss-checkbox-label": "Använd fokalförlust", "training-tab-use-labelsmoothing-checkbox-info": "Tillämpa label smoothing under träning. Detta kan förbättra modellens generalisering genom att förhindra att modellen blir för självsäker.", diff --git a/birdnet_analyzer/lang/tlh.json b/birdnet_analyzer/lang/tlh.json index 427a5696a..b0258dea1 100644 --- a/birdnet_analyzer/lang/tlh.json +++ b/birdnet_analyzer/lang/tlh.json @@ -353,6 +353,8 @@ "training-tab-output-format-radio-info": "Hol chu' qel.", "training-tab-output-format-radio-label": "tu'law' Hol", "training-tab-preprocessing-accordion-label": "ngoq nung", + "training-tab-save-detached-classifier-checkbox-info": "chenmoHwI' nach toD qach mIw nIb chenmoH nap", + "training-tab-save-detached-classifier-checkbox-label": "toD chenmoHwI' HaD", "training-tab-select-output-button-label": "tu'law' wav", "training-tab-select-output-textbox-placeholder": "ngoq Daq wIvlu'be'", "training-tab-start-training-button-label": "qeq yItagh", @@ -367,6 +369,7 @@ "training-tab-upsampling-radio-option-smote": "SMOTE", "training-tab-upsampling-ratio-slider-info": "chu' ratio Seghmey.", "training-tab-upsampling-ratio-slider-label": "qochHa' ratio", + "training-tab-warning-detached-classifier-append": "chel mIw DetlhHa' ghovwI'vaD lInglaHbe'.", "training-tab-use-focal-loss-checkbox-info": "qeq focal loss lo'. qeq QatlhmoH 'ej qeq laH QaQmoH.", "training-tab-use-focal-loss-checkbox-label": "focal loss lo'", "training-tab-use-labelsmoothing-checkbox-info": "qeq label smoothing lo'. qeq laH QaQmoH 'ej qeq laH QatlhmoH.", diff --git a/birdnet_analyzer/lang/zh_TW.json b/birdnet_analyzer/lang/zh_TW.json index 958159dd6..7a4fe496c 100644 --- a/birdnet_analyzer/lang/zh_TW.json +++ b/birdnet_analyzer/lang/zh_TW.json @@ -353,6 +353,8 @@ "training-tab-output-format-radio-info": "訓練後分類器的格式", "training-tab-output-format-radio-label": "模型輸出格式", "training-tab-preprocessing-accordion-label": "前處理", + "training-tab-save-detached-classifier-checkbox-info": "將分類器頭部儲存為分離模型以縮減大小", + "training-tab-save-detached-classifier-checkbox-label": "儲存分離的分類器", "training-tab-select-output-button-label": "選擇分類器輸出資料夾", "training-tab-select-output-textbox-placeholder": "未選擇輸出目錄", "training-tab-start-training-button-label": "開始訓練", @@ -367,6 +369,7 @@ "training-tab-upsampling-radio-option-smote": "SMOTE", "training-tab-upsampling-ratio-slider-info": "在上取樣後,最少數類別與最多數類別的資料數量最小比例", "training-tab-upsampling-ratio-slider-label": "上取樣比例", + "training-tab-warning-detached-classifier-append": "附加模式不適用於分離的分類器。", "training-tab-use-focal-loss-checkbox-info": "在訓練期間使用焦點損失。這給予困難樣本更多的權重,並有助於處理類別不平衡。", "training-tab-use-focal-loss-checkbox-label": "使用焦點損失", "training-tab-use-labelsmoothing-checkbox-info": "在訓練期間應用標籤平滑。這可以通過防止模型過於自信來幫助改善模型的泛化能力。", diff --git a/birdnet_analyzer/model.py b/birdnet_analyzer/model.py index 1271365f7..99fbfa0fc 100644 --- a/birdnet_analyzer/model.py +++ b/birdnet_analyzer/model.py @@ -814,6 +814,44 @@ def basic(inputs): utils.save_params_to_file(model_params, *params) +def save_detached_classifier( + classifier, + model_path: str, + labels: list[str] | None = None, +): + """Saves the detached classifier head as pb and tflite models. + + Args: + classifier: The custom classifier. + model_path: Path the model will be saved at. + labels: List of labels to save for the detached classifier. + """ + if model_path.endswith(".tflite"): + model_path = model_path.removesuffix(".tflite") + + os.makedirs(os.path.dirname(model_path), exist_ok=True) + + detached_classifier_path = model_path + "_detached" + + detached_model_inputs = keras.Input(shape=(1024,), dtype=tf.float32, + name="detached_input") + detached_model_outputs = classifier(detached_model_inputs) + detached_model = keras.Model(inputs=detached_model_inputs, + outputs=detached_model_outputs, + name="detached_classifier") + + detached_model.export(detached_classifier_path) + + converter = tf.lite.TFLiteConverter.from_keras_model(detached_model) + tflite_model: bytes = converter.convert() + + with open(detached_classifier_path + ".tflite", "wb") as f: + f.write(tflite_model) + + if labels is not None: + with open(detached_classifier_path + "_Labels.txt", "w", encoding="utf-8") as f: + f.writelines(label + "\n" for label in labels) + def focal_loss(y_true, y_pred, gamma=2.0, alpha=0.25, epsilon=1e-7): """ Focal loss for better handling of class imbalance. diff --git a/birdnet_analyzer/train/core.py b/birdnet_analyzer/train/core.py index d5d98e466..975f81549 100644 --- a/birdnet_analyzer/train/core.py +++ b/birdnet_analyzer/train/core.py @@ -44,6 +44,7 @@ def train( autotune_n_repeats: int = 1, autotune_n_splits: int = 3, autotune_metric: AUTOTUNE_METRICS = "val_AUPRC", + save_detached_classifier: bool = False, ): """ Trains a custom classifier model using the BirdNET-Analyzer framework. @@ -99,6 +100,10 @@ def train( hyperparameter tuning. Defaults to 1. autotune_n_splits (int, optional): Number of splits for cross-validation during hyperparameter tuning. Defaults to 3. + autotune_metric (Literal["val_AUPRC", "val_loss"], optional): Metric to optimize + during hyperparameter tuning. Defaults to "val_AUPRC". + save_detached_classifier (bool, optional): Whether to additionally save a + detached version of the trained classifier. Defaults to False. Returns: None """ @@ -135,4 +140,5 @@ def train( autotune_n_repeats=autotune_n_repeats, autotune_n_splits=autotune_n_splits, autotune_metric=autotune_metric, + save_detached_classifier=save_detached_classifier, ) diff --git a/birdnet_analyzer/train/utils.py b/birdnet_analyzer/train/utils.py index 39d8d3436..4105110c5 100644 --- a/birdnet_analyzer/train/utils.py +++ b/birdnet_analyzer/train/utils.py @@ -375,6 +375,7 @@ def train_model( on_epoch_end=None, on_trial_result=None, on_data_load_end=None, + save_detached_classifier: bool = False, ): """Trains a custom classifier. @@ -383,6 +384,8 @@ def train_model( on_trial_result: A callback function for hyperparameter tuning. on_data_load_end: A callback function for data loading progress. autotune_directory: Directory for autotune results. + save_detached_classifier: Whether to additionally save a detached version of + the trained classifier. Returns: A keras `History` object, whose `history` property contains all the metrics. @@ -738,6 +741,12 @@ def generate_splits( except Exception as e: raise Exception("Error saving model") from e + ## TODO: Warn if save mode is "append" + if save_detached_classifier: + model.save_detached_classifier( + classifier, output, labels=labels if model_save_mode == "append" else None + ) + save_sample_counts(labels, y_train_full, output) # Evaluate model on test data if available diff --git a/docs/best-practices/training.rst b/docs/best-practices/training.rst index ad7a1c5be..03c0cbb86 100644 --- a/docs/best-practices/training.rst +++ b/docs/best-practices/training.rst @@ -121,6 +121,21 @@ Choose the mode that fits your use case best, depending on whether you need to d .. caution:: When using the "Append" mode, make sure that the class names of the new classes do not conflict with existing classes in BirdNET. +3.6 Detached Classifier +########################## + +You can additionally choose to save a detached version of the trained classifier. +This will save the classification head in tflite and saved model (pb) format. +Instead of audio the classification head will take the embeddings extracted from the BirdNET model as input. +This is meant as a way to provide a lightweight version of the classifier that can more easily be transferred to edge devices in the field that already run BirdNET. + +.. note:: + As of now the detached classifier feature is meant for custom inference pipelines and the BirdNET-Analyzer does not currently offer a way to use the detached classifier directly. + +.. caution:: + The "Append" mode will not be applied to the detached classifier. The detached classifier will only contained the newly trained classes. + If the original BirdNET classifications are needed they should be extracted from the BirdNET model alongside the embeddings that are fed into the detached classifier. + 4. Using the Custom Classifier --------------------------------