From 4abff77db9752bdc261ec527193931548eaa3255 Mon Sep 17 00:00:00 2001 From: katg999 Date: Fri, 12 Jul 2024 11:37:38 +0300 Subject: [PATCH] diarisation finetuning documentation --- docs/index.md | 1 + docs/tutorials/14-diarization-training.md | 629 ++++++++++++++++++++++ docs/tutorials/EVAL.PNG | Bin 0 -> 52385 bytes mkdocs.yml | 1 + 4 files changed, 631 insertions(+) create mode 100644 docs/tutorials/14-diarization-training.md create mode 100644 docs/tutorials/EVAL.PNG diff --git a/docs/index.md b/docs/index.md index 8f88465..9e78e30 100644 --- a/docs/index.md +++ b/docs/index.md @@ -30,6 +30,7 @@ This documentation serves as the official guide for the **Leb** project, which i - [Training](tutorials/12-training.md) - [Speaker Diarization](#diarization) - [Diarization](tutorials/13-diarization.md) + - [Fine-Tuning](tutorials/14-diarization-training.md) - [Reference Docs](#reference) - [Reference](reference.md) diff --git a/docs/tutorials/14-diarization-training.md b/docs/tutorials/14-diarization-training.md new file mode 100644 index 0000000..08d5819 --- /dev/null +++ b/docs/tutorials/14-diarization-training.md @@ -0,0 +1,629 @@ +# PyanNet Model Training Speaker Diarization + +This process highlights the steps taken for Model Training on the [CallHome Dataset](https://huggingface.co/datasets/talkbank/callhome). For this particular dataset we used the English version of the CallHome Dataset. The Model Training Architecture, Loss Functions, Optimisation Techniques, Data Augmentation and Metrics Used. + +# Segmentation Model Configuration Explained + +## Overview + +### Model Architecture + +- **SegmentationModel**: This is a wrapper for the PyanNet segmentation model used for speaker diarization tasks. Inherits from Pretrained model to be compatible with the HF Trainer. Can be used to train segmentation models to be used for the "SpeakerDiarisation Task" in pyannote. + +**Forward** + +`forward`: Forward pass function of the Pretrained Model. + +Parameters: + +`waveforms(torch.tensor)` : A tensor containing audio data to be processed by the model and ensures the waveforms parameter is a PyTorch tensor. + +`labels`: Ground truth labels for Training. Defaults to None. + +`nb_speakers`: Number of speakers. Defaults to `None` + +Returns: A dictionary with loss(if predicted) and predictions. + +**Setup loss function** + +`setup_loss_func`: Sets up the loss function especially when using the powerset classes. ie `self.specifications.powerset=True` + +**Segmentation Loss Function** + +`segmentation_loss`: Defines the permutation-invariant segmentation loss. Computes the loss using either `nll_loss`(negative log likelihood) for `powerset` or `binary_cross_entropy` + +Parameters: + +`permutated_prediction`: Prediction after permutation. Type: `torch.Tensor` + +`target`: Ground truth labels. Type: `torch.Tensor` + +`weight`: Type: `Optional[torch.Tensor]` + +Returns: Permutation-invariant segmentation loss. `torch.Tensor` + +**To pyannote** + +`to_pyannote_model`: Converts the current model to a pyannote segmentation model for use in pyannote pipelines + +```python +class SegmentationModel(PreTrainedModel): + config_class = SegmentationModelConfig + + def __init__( + self, + config=SegmentationModelConfig(), + ): + super().__init__(config) + + self.model = PyanNet_nn(sincnet={"stride": 10}) + + self.weigh_by_cardinality = config.weigh_by_cardinality + self.max_speakers_per_frame = config.max_speakers_per_frame + self.chunk_duration = config.chunk_duration + self.min_duration = config.min_duration + self.warm_up = config.warm_up + self.max_speakers_per_chunk = config.max_speakers_per_chunk + + self.specifications = Specifications( + problem=Problem.MULTI_LABEL_CLASSIFICATION + if self.max_speakers_per_frame is None + else Problem.MONO_LABEL_CLASSIFICATION, + resolution=Resolution.FRAME, + duration=self.chunk_duration, + min_duration=self.min_duration, + warm_up=self.warm_up, + classes=[f"speaker#{i+1}" for i in range(self.max_speakers_per_chunk)], + powerset_max_classes=self.max_speakers_per_frame, + permutation_invariant=True, + ) + self.model.specifications = self.specifications + self.model.build() + self.setup_loss_func() + + def forward(self, waveforms, labels=None, nb_speakers=None): + + prediction = self.model(waveforms.unsqueeze(1)) + batch_size, num_frames, _ = prediction.shape + + if labels is not None: + weight = torch.ones(batch_size, num_frames, 1, device=waveforms.device) + warm_up_left = round(self.specifications.warm_up[0] / self.specifications.duration * num_frames) + weight[:, :warm_up_left] = 0.0 + warm_up_right = round(self.specifications.warm_up[1] / self.specifications.duration * num_frames) + weight[:, num_frames - warm_up_right :] = 0.0 + + if self.specifications.powerset: + multilabel = self.model.powerset.to_multilabel(prediction) + permutated_target, _ = permutate(multilabel, labels) + + permutated_target_powerset = self.model.powerset.to_powerset(permutated_target.float()) + loss = self.segmentation_loss(prediction, permutated_target_powerset, weight=weight) + + else: + permutated_prediction, _ = permutate(labels, prediction) + loss = self.segmentation_loss(permutated_prediction, labels, weight=weight) + + return {"loss": loss, "logits": prediction} + + return {"logits": prediction} + + def setup_loss_func(self): + if self.specifications.powerset: + self.model.powerset = Powerset( + len(self.specifications.classes), + self.specifications.powerset_max_classes, + ) + + def segmentation_loss( + self, + permutated_prediction: torch.Tensor, + target: torch.Tensor, + weight: Optional[torch.Tensor] = None, + ) -> torch.Tensor: + + + if self.specifications.powerset: + # `clamp_min` is needed to set non-speech weight to 1. + class_weight = torch.clamp_min(self.model.powerset.cardinality, 1.0) if self.weigh_by_cardinality else None + seg_loss = nll_loss( + permutated_prediction, + torch.argmax(target, dim=-1), + class_weight=class_weight, + weight=weight, + ) + else: + seg_loss = binary_cross_entropy(permutated_prediction, target.float(), weight=weight) + + return seg_loss + + @classmethod + def from_pyannote_model(cls, pretrained): + + # Initialize model: + specifications = copy.deepcopy(pretrained.specifications) + + # Copy pretrained model hyperparameters: + chunk_duration = specifications.duration + max_speakers_per_frame = specifications.powerset_max_classes + weigh_by_cardinality = False + min_duration = specifications.min_duration + warm_up = specifications.warm_up + max_speakers_per_chunk = len(specifications.classes) + + config = SegmentationModelConfig( + chunk_duration=chunk_duration, + max_speakers_per_frame=max_speakers_per_frame, + weigh_by_cardinality=weigh_by_cardinality, + min_duration=min_duration, + warm_up=warm_up, + max_speakers_per_chunk=max_speakers_per_chunk, + ) + + model = cls(config) + + # Copy pretrained model weights: + model.model.hparams = copy.deepcopy(pretrained.hparams) + model.model.sincnet = copy.deepcopy(pretrained.sincnet) + model.model.sincnet.load_state_dict(pretrained.sincnet.state_dict()) + model.model.lstm = copy.deepcopy(pretrained.lstm) + model.model.lstm.load_state_dict(pretrained.lstm.state_dict()) + model.model.linear = copy.deepcopy(pretrained.linear) + model.model.linear.load_state_dict(pretrained.linear.state_dict()) + model.model.classifier = copy.deepcopy(pretrained.classifier) + model.model.classifier.load_state_dict(pretrained.classifier.state_dict()) + model.model.activation = copy.deepcopy(pretrained.activation) + model.model.activation.load_state_dict(pretrained.activation.state_dict()) + + return model + + def to_pyannote_model(self): + + seg_model = PyanNet(sincnet={"stride": 10}) + seg_model.hparams.update(self.model.hparams) + + seg_model.sincnet = copy.deepcopy(self.model.sincnet) + seg_model.sincnet.load_state_dict(self.model.sincnet.state_dict()) + + seg_model.lstm = copy.deepcopy(self.model.lstm) + seg_model.lstm.load_state_dict(self.model.lstm.state_dict()) + + seg_model.linear = copy.deepcopy(self.model.linear) + seg_model.linear.load_state_dict(self.model.linear.state_dict()) + + seg_model.classifier = copy.deepcopy(self.model.classifier) + seg_model.classifier.load_state_dict(self.model.classifier.state_dict()) + + seg_model.activation = copy.deepcopy(self.model.activation) + seg_model.activation.load_state_dict(self.model.activation.state_dict()) + + seg_model.specifications = self.specifications + + return seg_model +``` + +**Segmentation Model Configuration** + +- `SegmentationModelConfig`Configuration class for the segmentation model, specifying various parameters like chunk duration, maximum speakers per frame, etc. +- Configuration parameters like chunk duration, number of speakers per chunk/frame, minimum duration, warm-up period, etc. + +```python +class SegmentationModelConfig(PretrainedConfig): + + model_type = "pyannet" + + def __init__( + self, + chunk_duration=10, + max_speakers_per_frame=2, + max_speakers_per_chunk=3, + min_duration=None, + warm_up=(0.0, 0.0), + weigh_by_cardinality=False, + **kwargs, + ): + + super().__init__(**kwargs) + self.chunk_duration = chunk_duration + self.max_speakers_per_frame = max_speakers_per_frame + self.max_speakers_per_chunk = max_speakers_per_chunk + self.min_duration = min_duration + self.warm_up = warm_up + self.weigh_by_cardinality = weigh_by_cardinality + # For now, the model handles only 16000 Hz sampling rate + self.sample_rate = 16000 +``` + +### Loss Functions + +#### Binary Cross-Entropy + +- Used when the model does not use the powerset approach. +- Computes the binary cross-entropy loss between the predicted and actual speaker activity. + +#### Negative Log-Likelihood (NLL) Loss + +- Used when the model uses the powerset approach. +- Computes the NLL loss considering class weights if specified. + +### Optimization Techniques + +### Batch Size + - This refers to the number of samples that you feed into your model at each iteration of the training process. This can be adjusted accordingly to optimise the performance of your model + +### Learning Rate + - This is an optimization tunning parameter that determines the step-size at each iteration while moving towards a minimum loss function + +### Training Epochs +- An epoch refers to a complete pass through the entire training dataset. A model is exposed to all the training examples and updates its parametrs basd on the patterns it learns. In our case, we try and iterate and test with 5, 10 and 20 epochs and find that the Diarisation Error Rate remains constant at "'der': 0.23994926057695026" + +#### Warm-up + +- The warm-up period allows the model to adjust at the beginning of each chunk, ensuring the central part of the chunk is more accurate. +- The warm-up is applied to both the left and right parts of each chunk. + +#### Permutation-Invariant Training + +- This technique permutes predictions and targets to find the optimal alignment, ensuring the loss computation is invariant to the order of speakers. + +### Data Augmentation Methods + +- For our case this is done using the the DataCollator class. This class is responsible for collecting data and ensuring that the target labels are dynamically padded. +- Pads the target labels to ensure they have the same shape. +- Pads with zeros if the number of speakers in a chunk is less than the maximum number of speakers per chunk + + + +#### Preprocessing Steps + +- Preprocessing steps like random overlap and fixed overlap during chunking can be considered a form of augmentation as they provide varied inputs to the model. +- `Preprocess` class used to handle these preprocessing steps is not detailed here, but it's responsible for preparing the input data. + +```python +class Preprocess: + def __init__( + self, + config, + ): + + self.chunk_duration = config.chunk_duration + self.max_speakers_per_frame = config.max_speakers_per_frame + self.max_speakers_per_chunk = config.max_speakers_per_chunk + self.min_duration = config.min_duration + self.warm_up = config.warm_up + + self.sample_rate = config.sample_rate + self.model = SegmentationModel(config).to_pyannote_model() + + # Get the number of frames associated to a chunk: + _, self.num_frames_per_chunk, _ = self.model( + torch.rand((1, int(self.chunk_duration * self.sample_rate))) + ).shape + + def get_labels_in_file(self, file): + + + file_labels = [] + for i in range(len(file["speakers"][0])): + if file["speakers"][0][i] not in file_labels: + file_labels.append(file["speakers"][0][i]) + + return file_labels + + def get_segments_in_file(self, file, labels): + + + file_annotations = [] + + for i in range(len(file["timestamps_start"][0])): + start_segment = file["timestamps_start"][0][i] + end_segment = file["timestamps_end"][0][i] + label = labels.index(file["speakers"][0][i]) + file_annotations.append((start_segment, end_segment, label)) + + dtype = [("start", " start_time)] + + # compute frame resolution: + # resolution = self.chunk_duration / self.num_frames_per_chunk + + # discretize chunk annotations at model output resolution + step = self.model.receptive_field.step + half = 0.5 * self.model.receptive_field.duration + + # discretize chunk annotations at model output resolution + start = np.maximum(chunk_segments["start"], start_time) - start_time - half + start_idx = np.maximum(0, np.round(start / step)).astype(int) + + # start_idx = np.floor(start / resolution).astype(int) + end = np.minimum(chunk_segments["end"], end_time) - start_time - half + end_idx = np.round(end / step).astype(int) + + # end_idx = np.ceil(end / resolution).astype(int) + + # get list and number of labels for current scope + labels = list(np.unique(chunk_segments["labels"])) + num_labels = len(labels) + # initial frame-level targets + y = np.zeros((self.num_frames_per_chunk, num_labels), dtype=np.uint8) + + # map labels to indices + mapping = {label: idx for idx, label in enumerate(labels)} + + for start, end, label in zip(start_idx, end_idx, chunk_segments["labels"]): + mapped_label = mapping[label] + y[start : end + 1, mapped_label] = 1 + + return waveform, y, labels + + def get_start_positions(self, file, overlap, random=False): + + sample_rate = file["audio"][0]["sampling_rate"] + + assert sample_rate == self.sample_rate + + file_duration = len(file["audio"][0]["array"]) / sample_rate + start_positions = np.arange(0, file_duration - self.chunk_duration, self.chunk_duration * (1 - overlap)) + + if random: + nb_samples = int(file_duration / self.chunk_duration) + start_positions = np.random.uniform(0, file_duration, nb_samples) + + return start_positions + + def __call__(self, file, random=False, overlap=0.0): + + new_batch = {"waveforms": [], "labels": [], "nb_speakers": []} + + if random: + start_positions = self.get_start_positions(file, overlap, random=True) + else: + start_positions = self.get_start_positions(file, overlap) + + for start_time in start_positions: + waveform, target, label = self.get_chunk(file, start_time) + + new_batch["waveforms"].append(waveform) + new_batch["labels"].append(target) + new_batch["nb_speakers"].append(label) + + return new_batch +``` + +### Metrics and Trainer + +- Initializes the Metrics class for evaluation. +- Configures the Trainer with the model, training arguments, datasets, data collator, and metrics. +- For the metrics we have the Diarisation Error Rate(DER), FalseAlarm Rate, MissedDetectionRate and the SpeakerConfusionRate with the implementation in the metrics class below. + +```python +import numpy as np +import torch +from pyannote.audio.torchmetrics import (DiarizationErrorRate, FalseAlarmRate, + MissedDetectionRate, + SpeakerConfusionRate) +from pyannote.audio.utils.powerset import Powerset + + +class Metrics: + """Metric class used by the HF trainer to compute speaker diarization metrics.""" + + def __init__(self, specifications) -> None: + """init method + + Args: + specifications (_type_): specifications attribute from a SegmentationModel. + """ + self.powerset = specifications.powerset + self.classes = specifications.classes + self.powerset_max_classes = specifications.powerset_max_classes + + self.model_powerset = Powerset( + len(self.classes), + self.powerset_max_classes, + ) + + self.metrics = { + "der": DiarizationErrorRate(0.5), + "confusion": SpeakerConfusionRate(0.5), + "missed_detection": MissedDetectionRate(0.5), + "false_alarm": FalseAlarmRate(0.5), + } + + def __call__(self, eval_pred): + + logits, labels = eval_pred + + if self.powerset: + predictions = self.model_powerset.to_multilabel(torch.tensor(logits)) + else: + predictions = torch.tensor(logits) + + labels = torch.tensor(labels) + + predictions = torch.transpose(predictions, 1, 2) + labels = torch.transpose(labels, 1, 2) + + metrics = {"der": 0, "false_alarm": 0, "missed_detection": 0, "confusion": 0} + + metrics["der"] += self.metrics["der"](predictions, labels).cpu().numpy() + metrics["false_alarm"] += self.metrics["false_alarm"](predictions, labels).cpu().numpy() + metrics["missed_detection"] += self.metrics["missed_detection"](predictions, labels).cpu().numpy() + metrics["confusion"] += self.metrics["confusion"](predictions, labels).cpu().numpy() + + return metrics + + +class DataCollator: + """Data collator that will dynamically pad the target labels to have max_speakers_per_chunk""" + + def __init__(self, max_speakers_per_chunk) -> None: + self.max_speakers_per_chunk = max_speakers_per_chunk + + def __call__(self, features): + """_summary_ + + Args: + features (_type_): _description_ + + Returns: + _type_: _description_ + """ + + batch = {} + + speakers = [f["nb_speakers"] for f in features] + labels = [f["labels"] for f in features] + + batch["labels"] = self.pad_targets(labels, speakers) + + batch["waveforms"] = torch.stack([f["waveforms"] for f in features]) + + return batch + + def pad_targets(self, labels, speakers): + """ + labels: + speakers: + + Returns: + _type_: + Collated target tensor of shape (num_frames, self.max_speakers_per_chunk) + If one chunk has more than max_speakers_per_chunk speakers, we keep + the max_speakers_per_chunk most talkative ones. If it has less, we pad with + zeros (artificial inactive speakers). + """ + + targets = [] + + for i in range(len(labels)): + label = speakers[i] + target = labels[i].numpy() + num_speakers = len(label) + + if num_speakers > self.max_speakers_per_chunk: + indices = np.argsort(-np.sum(target, axis=0), axis=0) + target = target[:, indices[: self.max_speakers_per_chunk]] + + elif num_speakers < self.max_speakers_per_chunk: + target = np.pad( + target, + ((0, 0), (0, self.max_speakers_per_chunk - num_speakers)), + mode="constant", + ) + + targets.append(target) + + return torch.from_numpy(np.stack(targets)) + +``` + +### Training Script + +- The script [train_segmentation.py](https://github.com/huggingface/diarizers/) + can be used to pre-process a diarization dataset and subsequently fine-tune the pyannote segmentation model. In the following example, we fine-tuned the segmentation model on the English subset of the CallHome dataset, a conversational dataset between native speakers: + +```bash +!python3 train_segmentation.py \ + --dataset_name=diarizers-community/callhome \ + --dataset_config_name=eng \ + --split_on_subset=data \ + --model_name_or_path=pyannote/segmentation-3.0 \ + --output_dir=./speaker-segmentation-fine-tuned-callhome-eng \ + --do_train \ + --do_eval \ + --learning_rate=1e-3 \ + --num_train_epochs=20 \ + --lr_scheduler_type=cosine \ + --per_device_train_batch_size=32 \ + --per_device_eval_batch_size=32 \ + --evaluation_strategy=epoch \ + --save_strategy=epoch \ + --preprocessing_num_workers=2 \ + --dataloader_num_workers=2 \ + --logging_steps=100 \ + --load_best_model_at_end \ + --push_to_hub +``` + +### Evaluation Script + +The script [test_segmentation.py](https://github.com/huggingface/diarizers/)can be used to evaluate a fine-tuned model on a diarization dataset. In the following example, we evaluate the fine-tuned model from the previous step on the test split of the CallHome English dataset: + +```bash +!python3 test_segmentation.py \ + --dataset_name=diarizers-community/callhome \ + --dataset_config_name=eng \ + --split_on_subset=data \ + --test_split_name=test \ + --model_name_or_path=diarizers-community/speaker-segmentation-fine-tuned-callhome-eng \ + --preprocessing_num_workers=2 \ + --evaluate_with_pipeline +``` + +**Sample Output** + +![alt text](EVAL.PNG) + + +### Inference with Pyannote +- The fine-tuned segmentation model can easily be loaded into the pyannote speaker diarization pipeline for inference. To do so, we load the pre-trained speaker diarization pipeline, and subsequently override the segmentation model with our fine-tuned checkpoint: + + +```python +from diarizers import SegmentationModel +from pyannote.audio import Pipeline +from datasets import load_dataset +import torch + +device = torch.device("cuda:0") if torch.cuda.is_available() else torch.device("cpu") + +# load the pre-trained pyannote pipeline +pipeline = Pipeline.from_pretrained("pyannote/speaker-diarization-3.1") +pipeline.to(device) + +# replace the segmentation model with your fine-tuned one +model = SegmentationModel().from_pretrained("diarizers-community/speaker-segmentation-fine-tuned-callhome-jpn") +model = model.to_pyannote_model() +pipeline._segmentation.model = model.to(device) + +# load dataset example +dataset = load_dataset("diarizers-community/callhome", "jpn", split="data") +sample = dataset[0]["audio"] + +# pre-process inputs +sample["waveform"] = torch.from_numpy(sample.pop("array")[None, :]).to(device, dtype=model.dtype) +sample["sample_rate"] = sample.pop("sampling_rate") + +# perform inference +diarization = pipeline(sample) + +# dump the diarization output to disk using RTTM format +with open("audio.rttm", "w") as rttm: + diarization.write_rttm(rttm) +``` + + diff --git a/docs/tutorials/EVAL.PNG b/docs/tutorials/EVAL.PNG new file mode 100644 index 0000000000000000000000000000000000000000..93198c02a5b3bca0cbffc6274422290990e2756a GIT binary patch literal 52385 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 I+7F)pFB|i9O#lD@ literal 0 HcmV?d00001 diff --git a/mkdocs.yml b/mkdocs.yml index 6b06100..e1a6a42 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -27,6 +27,7 @@ nav: - 'Training': tutorials/12-training.md - 'Speaker Diarization': - "Diarization": tutorials/13-diarization.md + - "Fine-Tuning Diarization": tutorials/14-diarization-training.md - 'Reference': - 'Reference': reference.md