diff --git a/docs/source/reference/api.md b/docs/source/reference/api.md index 916e6df..4b93140 100644 --- a/docs/source/reference/api.md +++ b/docs/source/reference/api.md @@ -1,65 +1,33 @@ # `BatDetect2API` reference -`BatDetect2API` is the main entry point for the current Python workflow. +`BatDetect2API` is the main Python entry point for BatDetect2. -It wraps model loading, inference, evaluation, output formatting, and -training-related entry points behind one object. +Use it when you want to load a model, run prediction, inspect detections, +evaluate results, or train from Python. Defined in `batdetect2.api_v2`. -## Create an API instance +## Main ways to create it - `BatDetect2API.from_checkpoint(path, ...)` - - load a trained checkpoint and optional config overrides. + - load a trained checkpoint, a bundled checkpoint alias, or a Hugging Face + checkpoint. - `BatDetect2API.from_config(model_config=..., targets_config=..., ...)` - - build a full stack from separate config objects. + - build a full model stack from config objects. -## Inference methods +## Common tasks -- `process_file(audio_file, ...)` - - run inference for one recording. -- `process_files(audio_files, ...)` - - run batch inference across a sequence of file paths. -- `process_directory(audio_dir, ...)` - - run inference across the audio files found in one directory. -- `process_clips(clips, ...)` - - run inference on an explicit sequence of clip objects. -- `process_audio(audio, ...)` - - run inference starting from a waveform array. -- `process_spectrogram(spec, ...)` - - run inference starting from a spectrogram tensor. +- Load a checkpoint and run prediction on one file. +- Run prediction on many files or clips. +- Save predictions in one of the supported output formats. +- Evaluate a model on labelled data. +- Fine-tune an existing checkpoint on new targets. -## Prediction inspection helpers +## Generated reference -- `get_top_class_name(detection)` - - return the highest-scoring class name for one detection. -- `get_class_scores(detection, include_top_class=True, sort_descending=True)` - - return ranked `(class_name, score)` pairs. -- `get_detection_features(detection)` - - return the per-detection feature vector. - -## Audio loading helpers - -- `load_audio(path)` -- `load_recording(recording)` -- `load_clip(clip)` -- `generate_spectrogram(audio)` - -## Output persistence helpers - -- `save_predictions(predictions, path, audio_dir=None, format=None, - config=None)` -- `load_predictions(path, format=None, config=None)` - -Use these when you want to save programmatic predictions without going through -the CLI. - -## Training and evaluation entry points - -- `train(...)` -- `finetune(...)` -- `evaluate(...)` -- `evaluate_predictions(...)` +```{eval-rst} +.. autoclass:: batdetect2.api_v2.BatDetect2API +``` ## Related pages diff --git a/docs/source/reference/cli/evaluate.rst b/docs/source/reference/cli/evaluate.rst index 0ac4a73..79281db 100644 --- a/docs/source/reference/cli/evaluate.rst +++ b/docs/source/reference/cli/evaluate.rst @@ -1,7 +1,10 @@ Evaluate command ================ -Evaluate a checkpoint against a configured test dataset. +Use ``batdetect2 evaluate`` to compare a checkpoint against labelled test data. + +This command writes metrics and any configured artifacts to the output +directory. .. click:: batdetect2.cli.evaluate:evaluate_command :prog: batdetect2 evaluate diff --git a/docs/source/reference/cli/finetune.rst b/docs/source/reference/cli/finetune.rst new file mode 100644 index 0000000..637074c --- /dev/null +++ b/docs/source/reference/cli/finetune.rst @@ -0,0 +1,11 @@ +Finetune command +================ + +Use ``batdetect2 finetune`` to adapt an existing checkpoint to a new target +definition. + +If you do not pass ``--model``, the bundled ``uk_same`` checkpoint is used. + +.. click:: batdetect2.cli.finetune:finetune_command + :prog: batdetect2 finetune + :nested: none diff --git a/docs/source/reference/cli/index.md b/docs/source/reference/cli/index.md index c8a238b..e7e06e5 100644 --- a/docs/source/reference/cli/index.md +++ b/docs/source/reference/cli/index.md @@ -1,31 +1,27 @@ # CLI reference Use this section to find the right command quickly, then open the command page -for full options and argument details. - -## How to use this section - -1. Start with {doc}`base` for options shared across the CLI. -2. Pick the command group or command you need from the command map below. -3. Open the linked page for complete autogenerated option reference. +for the full option list. ## Command map | Command | Use it for | Required positional args | | --- | --- | --- | -| `batdetect2 predict` | Run inference on audio | Depends on subcommand (`directory`, `file_list`, `dataset`) | +| `batdetect2 predict` | Run prediction on audio | Depends on subcommand (`directory`, `file_list`, `dataset`) | | `batdetect2 data` | Inspect and convert dataset configs | Depends on subcommand (`summary`, `convert`) | | `batdetect2 train` | Train or fine-tune models | `TRAIN_DATASET` | +| `batdetect2 finetune` | Fine-tune a checkpoint on new targets | `TRAIN_DATASET` plus `--targets` | | `batdetect2 evaluate` | Evaluate a checkpoint on a test dataset | `MODEL_PATH`, `TEST_DATASET` | | `batdetect2 detect` | Legacy compatibility workflow | `AUDIO_DIR`, `ANN_DIR`, `DETECTION_THRESHOLD` | -## Global options and conventions +## Notes - Global CLI options are documented in {doc}`base`. - Paths with spaces should be wrapped in quotes. - Input audio is expected to be mono. -- Legacy `detect` uses a required threshold argument, while `predict` uses the - optional `--detection-threshold` override. +- `predict` uses the optional `--detection-threshold` override. +- `finetune` defaults to the bundled `uk_same` checkpoint if `--model` is not + provided. ```{warning} `batdetect2 detect` is a legacy command. @@ -46,6 +42,7 @@ Base command and global options Predict command group Data command group Train command +Finetune command Evaluate command Legacy detect command ``` diff --git a/docs/source/reference/cli/predict.rst b/docs/source/reference/cli/predict.rst index 8acf20f..0027ff0 100644 --- a/docs/source/reference/cli/predict.rst +++ b/docs/source/reference/cli/predict.rst @@ -1,8 +1,16 @@ Predict command =============== -Run model inference from a directory, a file list, or a dataset. -Use ``--detection-threshold`` to override the model default per run. +Use ``batdetect2 predict`` to run prediction on audio. + +Choose a subcommand based on how you want to provide the input: + +- ``directory`` for all supported audio files in one folder +- ``file_list`` for a text file with one audio path per line +- ``dataset`` for recordings referenced by a dataset file + +Use ``--detection-threshold`` when you want to override the configured +threshold for one run. .. click:: batdetect2.cli.inference:predict :prog: batdetect2 predict diff --git a/docs/source/reference/cli/train.rst b/docs/source/reference/cli/train.rst index 6c416cb..27661ec 100644 --- a/docs/source/reference/cli/train.rst +++ b/docs/source/reference/cli/train.rst @@ -1,7 +1,11 @@ Train command ============= -Train a model from dataset configs or fine-tune from a checkpoint. +Use ``batdetect2 train`` to start from a fresh model config or continue from an +existing checkpoint. + +If you want to adapt an existing checkpoint to a new target definition, use +``batdetect2 finetune`` instead. .. click:: batdetect2.cli.train:train_command :prog: batdetect2 train diff --git a/src/batdetect2/api_v2.py b/src/batdetect2/api_v2.py index 037bf15..4044e10 100644 --- a/src/batdetect2/api_v2.py +++ b/src/batdetect2/api_v2.py @@ -47,6 +47,30 @@ DEFAULT_EVAL_DIR: Path = Path("outputs") / "evaluations" class BatDetect2API: + """High-level interface for the BatDetect2 workflow. + + Use this to load a model, run inference, inspect detections, + evaluate predictions, and train or fine-tune models. + + In most cases, start with :meth:`from_checkpoint` to load a trained model. + Use :meth:`from_config` when you want to build a new model with custom configs. + + Examples + -------- + Load the default checkpoint and run prediction on one file. + + >>> from batdetect2.api_v2 import BatDetect2API + >>> api = BatDetect2API.from_checkpoint() + >>> prediction = api.process_file("recording.wav") + + Load a checkpoint and save predictions for a folder of audio. + + >>> from pathlib import Path + >>> api = BatDetect2API.from_checkpoint("uk_same") + >>> predictions = api.process_directory("audio") + >>> api.save_predictions(predictions, "outputs/") + """ + def __init__( self, model_config: ModelConfig, @@ -66,6 +90,47 @@ class BatDetect2API: output_transform: OutputTransformProtocol, model: Model, ): + """Create a fully configured API instance. + + This initializer is mainly for internal wiring. + In most cases, users should create the API with + :meth:`from_checkpoint` or :meth:`from_config`. + + Parameters + ---------- + model_config : ModelConfig + Model configuration. + audio_config : AudioConfig + Audio loading configuration. + train_config : TrainingConfig + Training configuration. + evaluation_config : EvaluationConfig + Evaluation configuration. + inference_config : InferenceConfig + Inference configuration. + outputs_config : OutputsConfig + Output formatting configuration. + logging_config : AppLoggingConfig + Logging configuration. + targets : TargetProtocol + Target definition used by the model. + roi_mapper : ROIMapperProtocol + ROI mapping used for size targets. + audio_loader : AudioLoader + Audio loader. + preprocessor : PreprocessorProtocol + Preprocessor used before the detector. + postprocessor : PostprocessorProtocol + Postprocessor used after the detector. + evaluator : EvaluatorProtocol + Evaluator used for metrics. + formatter : OutputFormatterProtocol + Default formatter used to save predictions. + output_transform : OutputTransformProtocol + Transform that converts model outputs into detections. + model : Model + Model instance. + """ self.model_config = model_config self.audio_config = audio_config self.train_config = train_config @@ -90,6 +155,21 @@ class BatDetect2API: path: data.PathLike, base_dir: data.PathLike | None = None, ) -> Dataset: + """Load a set of annotations from a dataset config file. + + Parameters + ---------- + path : data.PathLike + Path to the dataset config file. + base_dir : data.PathLike | None, optional + Base directory used to resolve relative paths in the dataset + config. + + Returns + ------- + Dataset + Loaded dataset of annotations. + """ from batdetect2.data import load_dataset_from_config return load_dataset_from_config(path, base_dir=base_dir) @@ -112,6 +192,47 @@ class BatDetect2API: logger_config: LoggerConfig | None = None, logging_callbacks: Sequence[LoggingCallback[TrainLoggingContext]] = (), ): + """Train the current model on a set of annotations. + + Parameters + ---------- + train_annotations : Sequence[data.ClipAnnotation] + Training annotations. + val_annotations : Sequence[data.ClipAnnotation] | None, optional + Validation annotations. If omitted, training runs without a + validation set. + train_workers : int, optional + Number of worker processes for training data loading. + val_workers : int, optional + Number of worker processes for validation data loading. + checkpoint_dir : Path | None, optional + Directory where checkpoints are saved. + log_dir : Path | None, optional + Directory where logs are written. + experiment_name : str | None, optional + Experiment name used by the configured logger. + num_epochs : int | None, optional + Maximum number of training epochs. + run_name : str | None, optional + Run name used by the configured logger. + seed : int | None, optional + Random seed for reproducibility. + model_config : ModelConfig | None, optional + Model config override. If omitted, the API model config is used. + audio_config : AudioConfig | None, optional + Audio config override. + train_config : TrainingConfig | None, optional + Training config override. + logger_config : LoggerConfig | None, optional + Training logger config override. + logging_callbacks : Sequence[LoggingCallback[TrainLoggingContext]], optional + Extra logging callbacks to run during training setup. + + Returns + ------- + BatDetect2API + This API instance with the trained model. + """ from batdetect2.train import run_train self.model.train() @@ -161,7 +282,52 @@ class BatDetect2API: logger_config: LoggerConfig | None = None, logging_callbacks: Sequence[LoggingCallback[TrainLoggingContext]] = (), ) -> "BatDetect2API": - """Fine-tune from a checkpoint using a new target definition.""" + """Fine-tune the current model with a new target definition. + + Use this when you want to keep the existing model weights but change + the target sounds. You can fine-tune the whole model or just the + classifier heads. + + Parameters + ---------- + train_annotations : Sequence[data.ClipAnnotation] + Training annotations. + targets_config : TargetConfig + Target definition to train against. + val_annotations : Sequence[data.ClipAnnotation] | None, optional + Validation annotations. + trainable : {"all", "heads", "classifier_head", "bbox_head"}, optional + Which model parameters remain trainable. + train_workers : int, optional + Number of worker processes for training data loading. + val_workers : int, optional + Number of worker processes for validation data loading. + checkpoint_dir : Path | None, optional + Directory where checkpoints are saved. + log_dir : Path | None, optional + Directory where logs are written. + experiment_name : str | None, optional + Experiment name used by the configured logger. + num_epochs : int | None, optional + Maximum number of training epochs. + run_name : str | None, optional + Run name used by the configured logger. + seed : int | None, optional + Random seed for reproducibility. + audio_config : AudioConfig | None, optional + Audio config override. + train_config : TrainingConfig | None, optional + Training config override. + logger_config : LoggerConfig | None, optional + Training logger config override. + logging_callbacks : Sequence[LoggingCallback[TrainLoggingContext]], optional + Extra logging callbacks to run during training setup. + + Returns + ------- + BatDetect2API + A new API instance configured for the new targets. + """ from batdetect2.evaluate import build_evaluator from batdetect2.models import build_model_with_new_targets from batdetect2.outputs import ( @@ -256,6 +422,36 @@ class BatDetect2API: outputs_config: OutputsConfig | None = None, logger_config: LoggerConfig | None = None, ) -> tuple[dict[str, float], list[ClipDetections]]: + """Evaluate the current model on a labelled dataset. + + Parameters + ---------- + test_annotations : Sequence[data.ClipAnnotation] + Labelled clips used for evaluation. + num_workers : int, optional + Number of worker processes for dataset loading. + output_dir : data.PathLike, optional + Directory where metrics and plots are written. + experiment_name : str | None, optional + Experiment name used by the configured logger. + run_name : str | None, optional + Run name used by the configured logger. + save_predictions : bool, optional + If ``True``, save formatted predictions alongside metrics. + audio_config : AudioConfig | None, optional + Audio config override. + evaluation_config : EvaluationConfig | None, optional + Evaluation config override. + outputs_config : OutputsConfig | None, optional + Output config override. + logger_config : LoggerConfig | None, optional + Evaluation logger config override. + + Returns + ------- + tuple[dict[str, float], list[ClipDetections]] + Evaluation metrics and per-clip predictions. + """ from batdetect2.evaluate import run_evaluate return run_evaluate( @@ -282,6 +478,22 @@ class BatDetect2API: predictions: Sequence[ClipDetections], output_dir: data.PathLike | None = None, ): + """Evaluate an existing set of predictions. + + Parameters + ---------- + annotations : Sequence[data.ClipAnnotation] + Reference annotations. + predictions : Sequence[ClipDetections] + Predictions to compare against the annotations. + output_dir : data.PathLike | None, optional + Directory where metrics and plots are written. + + Returns + ------- + dict[str, float] + Computed evaluation metrics. + """ from batdetect2.evaluate import save_evaluation_results clip_evals = self.evaluator.evaluate( @@ -301,12 +513,15 @@ class BatDetect2API: return metrics def load_audio(self, path: data.PathLike) -> np.ndarray: + """Load one audio file into a waveform array.""" return self.audio_loader.load_file(path) def load_recording(self, recording: data.Recording) -> np.ndarray: + """Load one recording object into a waveform array.""" return self.audio_loader.load_recording(recording) def load_clip(self, clip: data.Clip) -> np.ndarray: + """Load one clip object into a waveform array.""" return self.audio_loader.load_clip(clip) def get_top_class_name(self, detection: Detection) -> str: @@ -358,6 +573,7 @@ class BatDetect2API: self, audio: np.ndarray, ) -> torch.Tensor: + """Convert a waveform array into a model spectrogram.""" import torch tensor = torch.tensor(audio).unsqueeze(0) @@ -369,6 +585,23 @@ class BatDetect2API: batch_size: int | None = None, detection_threshold: float | None = None, ) -> ClipDetections: + """Run inference on one audio file. + + Parameters + ---------- + audio_file : data.PathLike + Path to the audio file. + batch_size : int | None, optional + Batch size override. If omitted, the inference config value is + used. + detection_threshold : float | None, optional + Detection score threshold override. + + Returns + ------- + ClipDetections + Predictions for the full recording. + """ from soundevent import data from batdetect2.postprocess import ClipDetections @@ -405,6 +638,20 @@ class BatDetect2API: audio: np.ndarray, detection_threshold: float | None = None, ) -> list[Detection]: + """Run inference on a waveform array. + + Parameters + ---------- + audio : np.ndarray + Audio waveform. + detection_threshold : float | None, optional + Detection score threshold override. + + Returns + ------- + list[Detection] + Detected calls. + """ spec = self.generate_spectrogram(audio) return self.process_spectrogram( spec, @@ -417,6 +664,27 @@ class BatDetect2API: start_time: float = 0, detection_threshold: float | None = None, ) -> list[Detection]: + """Run inference on one spectrogram tensor. + + Parameters + ---------- + spec : torch.Tensor + Spectrogram tensor for one recording or clip. + start_time : float, optional + Start time in seconds used when creating detections. + detection_threshold : float | None, optional + Detection score threshold override. + + Returns + ------- + list[Detection] + Detected calls. + + Raises + ------ + ValueError + If a batched spectrogram with more than one item is provided. + """ if spec.ndim == 4 and spec.shape[0] > 1: raise ValueError("Batched spectrograms not supported.") @@ -439,6 +707,7 @@ class BatDetect2API: audio_dir: data.PathLike, detection_threshold: float | None = None, ) -> list[ClipDetections]: + """Run inference on all supported audio files in a directory.""" from soundevent.audio.files import get_audio_files files = list(get_audio_files(audio_dir)) @@ -457,6 +726,30 @@ class BatDetect2API: output_config: OutputsConfig | None = None, detection_threshold: float | None = None, ) -> list[ClipDetections]: + """Run inference on multiple audio files. + + Parameters + ---------- + audio_files : Sequence[data.PathLike] + Audio file paths. + batch_size : int | None, optional + Batch size override. + num_workers : int, optional + Number of worker processes for audio loading. + audio_config : AudioConfig | None, optional + Audio config override. + inference_config : InferenceConfig | None, optional + Inference config override. + output_config : OutputsConfig | None, optional + Output config override. + detection_threshold : float | None, optional + Detection score threshold override. + + Returns + ------- + list[ClipDetections] + Predictions for each input file. + """ from batdetect2.inference import process_file_list return process_file_list( @@ -485,6 +778,30 @@ class BatDetect2API: output_config: OutputsConfig | None = None, detection_threshold: float | None = None, ) -> list[ClipDetections]: + """Run inference on multiple clip objects. + + Parameters + ---------- + clips : Sequence[data.Clip] + Clips to process. + batch_size : int | None, optional + Batch size override. + num_workers : int, optional + Number of worker processes for audio loading. + audio_config : AudioConfig | None, optional + Audio config override. + inference_config : InferenceConfig | None, optional + Inference config override. + output_config : OutputsConfig | None, optional + Output config override. + detection_threshold : float | None, optional + Detection score threshold override. + + Returns + ------- + list[ClipDetections] + Predictions for each input clip. + """ from batdetect2.inference import run_batch_inference return run_batch_inference( @@ -511,6 +828,21 @@ class BatDetect2API: format: str | None = None, config: OutputFormatConfig | None = None, ): + """Save predictions to disk in one of the supported output formats. + + Parameters + ---------- + predictions : Sequence[ClipDetections] + Predictions to save. + path : data.PathLike + Output file or directory path, depending on the selected format. + audio_dir : data.PathLike | None, optional + Audio root directory used when writing relative paths. + format : str | None, optional + Output format name override. + config : OutputFormatConfig | None, optional + Output format config override. + """ from batdetect2.outputs import get_output_formatter formatter = self.formatter @@ -532,6 +864,22 @@ class BatDetect2API: format: str | None = None, config: OutputFormatConfig | None = None, ) -> list[object]: + """Load predictions from disk. + + Parameters + ---------- + path : data.PathLike + Path to a saved prediction file or directory. + format : str | None, optional + Output format name override. + config : OutputFormatConfig | None, optional + Output format config override. + + Returns + ------- + list[object] + Loaded prediction objects returned by the selected formatter. + """ from batdetect2.outputs import get_output_formatter formatter = self.formatter @@ -558,6 +906,36 @@ class BatDetect2API: outputs_config: OutputsConfig | None = None, logging_config: AppLoggingConfig | None = None, ) -> "BatDetect2API": + """Build an API instance from config objects. + + Use this when you want to create a new model stack without loading a + saved checkpoint. + + Parameters + ---------- + model_config : ModelConfig | None, optional + Model config. If omitted, the default model config is used. + targets_config : TargetConfig | None, optional + Target config. If omitted, the default target config is used. + audio_config : AudioConfig | None, optional + Audio config. If omitted, the default audio config is used. + train_config : TrainingConfig | None, optional + Training config. If omitted, the default training config is used. + evaluation_config : EvaluationConfig | None, optional + Evaluation config. If omitted, the default evaluation config is + used. + inference_config : InferenceConfig | None, optional + Inference config. If omitted, the default inference config is used. + outputs_config : OutputsConfig | None, optional + Output config. If omitted, the default outputs config is used. + logging_config : AppLoggingConfig | None, optional + Logging config. If omitted, the default logging config is used. + + Returns + ------- + BatDetect2API + Configured API instance. + """ from batdetect2.audio import AudioConfig, build_audio_loader from batdetect2.evaluate import EvaluationConfig, build_evaluator from batdetect2.inference import InferenceConfig @@ -664,6 +1042,31 @@ class BatDetect2API: outputs_config: OutputsConfig | None = None, logging_config: AppLoggingConfig | None = None, ) -> "BatDetect2API": + """Build an API instance from a saved checkpoint. + + Parameters + ---------- + path : data.PathLike | str | None, optional + Checkpoint path, bundled checkpoint alias, or Hugging Face URI. + If omitted, the default bundled checkpoint is used. + audio_config : AudioConfig | None, optional + Audio config override. + train_config : TrainingConfig | None, optional + Training config override. + evaluation_config : EvaluationConfig | None, optional + Evaluation config override. + inference_config : InferenceConfig | None, optional + Inference config override. + outputs_config : OutputsConfig | None, optional + Output config override. + logging_config : AppLoggingConfig | None, optional + Logging config override. + + Returns + ------- + BatDetect2API + Configured API instance. + """ from batdetect2.audio import AudioConfig, build_audio_loader from batdetect2.evaluate import EvaluationConfig, build_evaluator from batdetect2.inference import InferenceConfig diff --git a/src/batdetect2/cli/base.py b/src/batdetect2/cli/base.py index 7de2c09..ee99afb 100644 --- a/src/batdetect2/cli/base.py +++ b/src/batdetect2/cli/base.py @@ -8,10 +8,11 @@ __all__ = [ INFO_STR = """ -BatDetect2 - Detection and Classification - Assumes audio files are mono, not stereo. - Spaces in the input paths will throw an error. Wrap in quotes. - Input files should be short in duration e.g. < 30 seconds. +BatDetect2 + Input audio should be mono. + Wrap paths that contain spaces in quotes. + For long recordings, split audio into shorter files before running + prediction. """ @@ -25,8 +26,8 @@ BatDetect2 - Detection and Classification def cli(verbose: int = 0): """Run the BatDetect2 CLI. - This command initializes logging and exposes subcommands for prediction, - training, evaluation, and dataset utilities. + Use subcommands to run prediction, training, evaluation, and dataset + utilities. """ click.echo(INFO_STR) diff --git a/src/batdetect2/cli/evaluate.py b/src/batdetect2/cli/evaluate.py index f35fed6..9007521 100644 --- a/src/batdetect2/cli/evaluate.py +++ b/src/batdetect2/cli/evaluate.py @@ -17,27 +17,27 @@ DEFAULT_OUTPUT_DIR = Path("outputs") / "evaluation" @click.option( "--audio-config", type=click.Path(exists=True), - help="Path to audio config file.", + help="Path to an audio config file.", ) @click.option( "--evaluation-config", type=click.Path(exists=True), - help="Path to evaluation config file.", + help="Path to an evaluation config file.", ) @click.option( "--inference-config", type=click.Path(exists=True), - help="Path to inference config file.", + help="Path to an inference config file.", ) @click.option( "--outputs-config", type=click.Path(exists=True), - help="Path to outputs config file.", + help="Path to an outputs config file.", ) @click.option( "--logging-config", type=click.Path(exists=True), - help="Path to logging config file.", + help="Path to a logging config file.", ) @click.option( "--base-dir", @@ -87,10 +87,10 @@ def evaluate_command( experiment_name: str | None = None, run_name: str | None = None, ): - """Evaluate a checkpoint against a test dataset. + """Evaluate a checkpoint on a labelled test dataset. - Loads model and optional override configs, runs evaluation on - `test_dataset`, and writes metrics/artifacts to `output_dir`. + This command loads a checkpoint, runs evaluation on ``test_dataset``, and + writes metrics to ``output_dir``. """ from batdetect2.api_v2 import BatDetect2API from batdetect2.audio import AudioConfig diff --git a/src/batdetect2/cli/finetune.py b/src/batdetect2/cli/finetune.py index 7521274..33b1c8b 100644 --- a/src/batdetect2/cli/finetune.py +++ b/src/batdetect2/cli/finetune.py @@ -5,7 +5,7 @@ import click from loguru import logger from batdetect2.cli.base import cli -from batdetect2.train.checkpoints import DEFAULT_BUNDLED_CHECKPOINT +from batdetect2.train.checkpoints import DEFAULT_CHECKPOINT __all__ = ["finetune_command"] @@ -21,7 +21,7 @@ __all__ = ["finetune_command"] help=( "Path to a checkpoint, bundled checkpoint alias, or a Hugging Face " "URI to fine-tune from. Defaults to " - f"'{DEFAULT_BUNDLED_CHECKPOINT}'." + f"'{DEFAULT_CHECKPOINT}'." ), ) @click.option( @@ -47,24 +47,24 @@ __all__ = ["finetune_command"] @click.option( "--training-config", type=click.Path(exists=True), - help="Path to training config file.", + help="Path to a training config file.", ) @click.option( "--audio-config", type=click.Path(exists=True), - help="Path to audio config file.", + help="Path to an audio config file.", ) @click.option( "--logging-config", type=click.Path(exists=True), - help="Path to logging config file.", + help="Path to a logging config file.", ) @click.option( "--trainable", type=click.Choice(["all", "heads", "classifier_head", "bbox_head"]), default="heads", show_default=True, - help="Which model parameters remain trainable during fine-tuning.", + help="Which model parameters stay trainable during fine-tuning.", ) @click.option( "--ckpt-dir", @@ -127,7 +127,11 @@ def finetune_command( experiment_name: str | None = None, run_name: str | None = None, ): - """Fine-tune a BatDetect2 checkpoint on a new target definition.""" + """Fine-tune a checkpoint on a new target definition. + + Use this command when you want to adapt an existing model to a new class + list or ROI mapping. + """ from batdetect2.api_v2 import BatDetect2API from batdetect2.audio import AudioConfig from batdetect2.data import load_dataset, load_dataset_config diff --git a/src/batdetect2/cli/inference.py b/src/batdetect2/cli/inference.py index edec826..41f6622 100644 --- a/src/batdetect2/cli/inference.py +++ b/src/batdetect2/cli/inference.py @@ -18,22 +18,21 @@ __all__ = ["predict"] @cli.group(name="predict", short_help="Run prediction workflows.") def predict() -> None: - """Run model inference on audio files. + """Run model inference on audio. - Use one of the subcommands to select inputs from a directory, a text file - list, or an annotation dataset. + Choose a subcommand based on how you want to provide input audio. """ def common_predict_options(func): - """Attach options shared by all `predict` subcommands.""" + """Attach options shared by all ``predict`` subcommands.""" @click.option( "--audio-config", type=click.Path(exists=True), help=( "Path to an audio config file. Use this to override audio " - "loading and preprocessing-related settings." + "loading settings." ), ) @click.option( @@ -41,7 +40,7 @@ def common_predict_options(func): type=click.Path(exists=True), help=( "Path to an inference config file. Use this to override " - "prediction-time thresholds and behavior." + "prediction settings." ), ) @click.option( @@ -49,23 +48,19 @@ def common_predict_options(func): type=click.Path(exists=True), help=( "Path to an outputs config file. Use this to control the " - "prediction fields written to disk." + "saved output format and fields." ), ) @click.option( "--logging-config", type=click.Path(exists=True), - help=( - "Path to a logging config file. Use this to customize logging " - "format and levels." - ), + help=("Path to a logging config file. Use this to change log output."), ) @click.option( "--batch-size", type=int, help=( - "Batch size for inference. If omitted, the value from the " - "loaded config is used." + "Batch size for inference. If omitted, the config value is used." ), ) @click.option( @@ -82,7 +77,7 @@ def common_predict_options(func): type=str, help=( "Output format name used by the prediction writer. If omitted, " - "the default output format is used." + "the config default is used." ), ) @click.option( @@ -91,7 +86,7 @@ def common_predict_options(func): default=None, help=( "Optional detection score threshold override. If omitted, " - "the model default threshold is used." + "the configured threshold is used." ), ) @wraps(func) @@ -212,10 +207,10 @@ def predict_directory_command( format_name: str | None, detection_threshold: float | None, ) -> None: - """Predict on all audio files in a directory. + """Run prediction on all supported audio files in a directory. - Loads a checkpoint, scans `audio_dir` for supported audio files, runs - inference, and saves predictions to `output_path`. + This command scans ``audio_dir`` for audio files, runs prediction, and + saves the results to ``output_path``. """ from soundevent.audio.files import get_audio_files @@ -256,9 +251,9 @@ def predict_file_list_command( format_name: str | None, detection_threshold: float | None, ) -> None: - """Predict on audio files listed in a text file. + """Run prediction on audio files listed in a text file. - The list file should contain one audio path per line. Empty lines are + The text file should contain one audio path per line. Empty lines are ignored. """ file_list = Path(file_list) @@ -304,10 +299,10 @@ def predict_dataset_command( format_name: str | None, detection_threshold: float | None, ) -> None: - """Predict on recordings referenced in an annotation dataset. + """Run prediction on recordings referenced in a dataset file. - The dataset is read as a soundevent annotation set and unique recording - paths are extracted before inference. + Recording paths are read from the dataset and each recording is processed + once. """ from soundevent import io diff --git a/src/batdetect2/cli/train.py b/src/batdetect2/cli/train.py index 0849382..c577512 100644 --- a/src/batdetect2/cli/train.py +++ b/src/batdetect2/cli/train.py @@ -13,15 +13,15 @@ __all__ = ["train_command"] @click.option( "--val-dataset", type=click.Path(exists=True), - help="Path to validation dataset config file.", + help="Path to a validation dataset config file.", ) @click.option( "--model", "model_path", type=str, help=( - "Path to a checkpoint or a Hugging Face URI to continue training " - "from. If omitted, training starts from a fresh model config." + "Path to a checkpoint, bundled checkpoint alias, or Hugging Face " + "URI. If omitted, training starts from a fresh model config." ), ) @click.option( @@ -36,7 +36,7 @@ __all__ = ["train_command"] "--targets", "targets_config", type=click.Path(exists=True), - help="Path to targets config file.", + help="Path to a targets config file.", ) @click.option( "--model-config", @@ -46,32 +46,32 @@ __all__ = ["train_command"] @click.option( "--training-config", type=click.Path(exists=True), - help="Path to training config file.", + help="Path to a training config file.", ) @click.option( "--audio-config", type=click.Path(exists=True), - help="Path to audio config file.", + help="Path to an audio config file.", ) @click.option( "--evaluation-config", type=click.Path(exists=True), - help="Path to evaluation config file.", + help="Path to an evaluation config file.", ) @click.option( "--inference-config", type=click.Path(exists=True), - help="Path to inference config file.", + help="Path to an inference config file.", ) @click.option( "--outputs-config", type=click.Path(exists=True), - help="Path to outputs config file.", + help="Path to an outputs config file.", ) @click.option( "--logging-config", type=click.Path(exists=True), - help="Path to logging config file.", + help="Path to a logging config file.", ) @click.option( "--ckpt-dir", @@ -139,9 +139,8 @@ def train_command( ): """Train a BatDetect2 model. - Train either from a fresh config (`--model-config`) or by fine-tuning an - existing checkpoint (`--model`). Training data are loaded from - `train_dataset`, with optional validation data from `--val-dataset`. + Start from a fresh model config or continue from an existing checkpoint. + Training data are loaded from ``train_dataset``. """ from batdetect2.api_v2 import BatDetect2API from batdetect2.audio import AudioConfig