{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":129271,"databundleVersionId":15506307,"sourceType":"competition"}],"dockerImageVersionId":31259,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"Install Packages","metadata":{}},{"cell_type":"code","source":"# Run this once at the very beginning and then the second cell. After this restart session. Then start from the second cell. \n!pip uninstall -y \\\nnumpy pandas pyarrow \\\npyannote.audio pyannote.core pyannote.database \\\npyannote.metrics pyannote.pipeline \\\njax jaxlib cudf cupy dask tensorflow\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install -q \\\nnumpy==1.26.4 \\\npandas==2.2.2 \\\npyarrow==14.0.2 \\\npyannote.audio==3.1.1 \\\npyannote.core==5.0.0 \\\npyannote.database==5.1.0 \\\npyannote.metrics==3.2.1 \\\npyannote.pipeline==3.0.1 \\\npytorch-lightning==2.1.4 \\\ntorchmetrics==1.3.0 \\\ntorch-audiomentations\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-16T16:30:44.725917Z","iopub.execute_input":"2026-02-16T16:30:44.726213Z","iopub.status.idle":"2026-02-16T16:30:48.468629Z","shell.execute_reply.started":"2026-02-16T16:30:44.726185Z","shell.execute_reply":"2026-02-16T16:30:48.467614Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Login using Kaggle secret","metadata":{}},{"cell_type":"code","source":"import os\nfrom kaggle_secrets import UserSecretsClient\nfrom huggingface_hub import login\n\nuser_secrets = UserSecretsClient()\nHF_TOKEN = user_secrets.get_secret(\"HF_TOKEN\")\nlogin(HF_TOKEN)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-16T16:30:51.561770Z","iopub.execute_input":"2026-02-16T16:30:51.562744Z","iopub.status.idle":"2026-02-16T16:30:52.031032Z","shell.execute_reply.started":"2026-02-16T16:30:51.562702Z","shell.execute_reply":"2026-02-16T16:30:52.030220Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Imports","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport sys\n\n# FIX 1: The NumPy 2.0 AttributeError (np.NaN)\nif not hasattr(np, 'NaN'):\n    np.NaN = np.nan\n\n# FIX 2: Prevent the 'torchaudio' backend error if it occurs\nimport torchaudio\ntry:\n    torchaudio.set_audio_backend(\"soundfile\")\nexcept:\n    pass \n\n# NOW do your imports\nimport pyannote.audio\nimport pyannote.core\nimport pyannote.database\nimport pyannote.audio \nimport pytorch_lightning\n\nprint(f\"Success! pyannote.audio {pyannote.audio.__version__} is loaded.\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-16T16:30:54.157030Z","iopub.execute_input":"2026-02-16T16:30:54.157736Z","iopub.status.idle":"2026-02-16T16:31:01.914310Z","shell.execute_reply.started":"2026-02-16T16:30:54.157699Z","shell.execute_reply":"2026-02-16T16:31:01.913579Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import warnings\nwarnings.filterwarnings(\"ignore\", category=UserWarning, module=\"pyannote.audio.tasks.segmentation.mixins\")\nwarnings.filterwarnings(\"ignore\", category=DeprecationWarning)\n\nimport torch, pandas as pd, huggingface_hub\nimport os\nfrom sklearn.model_selection import train_test_split\nfrom pyannote.audio import Model, Pipeline\nfrom pyannote.audio.tasks import SpeakerEmbedding, Segmentation\nfrom pyannote.database.protocol import SpeakerDiarizationProtocol\nfrom pyannote.core import Annotation, Segment\nfrom pyannote.database import FileFinder\nfrom pytorch_lightning import Trainer\nfrom pytorch_lightning.callbacks import ModelCheckpoint, EarlyStopping\nfrom pytorch_lightning.loggers import CSVLogger\nfrom sklearn.model_selection import train_test_split\nfrom pyannote.metrics.diarization import DiarizationErrorRate\n\nprint(\"Imports completed (warnings hidden)!\")\n\nprint(\"Torch:\", torch.__version__)\nprint(\"CUDA Available:\", torch.cuda.is_available())\nprint(\"Numpy:\", np.__version__)\nprint(\"Pandas:\", pd.__version__)\nprint(\"HF Hub:\", huggingface_hub.__version__)\nprint(\"Pyannote Core:\", pyannote.core.__version__)\nprint(\"Pyannote Audio:\", pyannote.audio.__version__)\nprint(\"Pyannote Database:\", pyannote.database.__version__)\nprint(\"Lightning:\", pytorch_lightning.__version__)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-16T16:31:05.752739Z","iopub.execute_input":"2026-02-16T16:31:05.753740Z","iopub.status.idle":"2026-02-16T16:31:05.822608Z","shell.execute_reply.started":"2026-02-16T16:31:05.753699Z","shell.execute_reply":"2026-02-16T16:31:05.821832Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Set Paths","metadata":{}},{"cell_type":"code","source":"AUDIO_DIR = \"/kaggle/input/competitions/dl-sprint-4-0-bengali-speaker-diarization-challenge/diarization/diarization/train/audio\"\nCSV_DIR = \"/kaggle/input/competitions/dl-sprint-4-0-bengali-speaker-diarization-challenge/diarization/diarization/train/annotation\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-16T16:31:12.383556Z","iopub.execute_input":"2026-02-16T16:31:12.384178Z","iopub.status.idle":"2026-02-16T16:31:12.387994Z","shell.execute_reply.started":"2026-02-16T16:31:12.384150Z","shell.execute_reply":"2026-02-16T16:31:12.387297Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Define data loader","metadata":{}},{"cell_type":"code","source":"def hms_to_s(hhmmss):\n    parts = str(hhmmss).split(':')\n    return float(parts[0]) * 3600 + float(parts[1]) * 60 + float(parts[2])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-16T16:31:35.765542Z","iopub.execute_input":"2026-02-16T16:31:35.766138Z","iopub.status.idle":"2026-02-16T16:31:35.770370Z","shell.execute_reply.started":"2026-02-16T16:31:35.766110Z","shell.execute_reply":"2026-02-16T16:31:35.769716Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def load_bengali_data(audio_dir, csv_dir):\n    dataset=[]\n\n    for csv_file in os.listdir(csv_dir):\n        if not csv_file.endswith(\".csv\"): continue\n\n        file_id = csv_file.replace(\".csv\",\"\")\n        audio_path = os.path.join(audio_dir,f\"{file_id}.wav\")\n        csv_path = os.path.join(csv_dir, csv_file)\n\n        if os.path.exists(audio_path):\n            annotation = Annotation(uri=file_id)\n            df= pd.read_csv(csv_path)\n            df.columns= df.columns.str.lower()\n            \n            for _, row in df.iterrows():\n                start = hms_to_s(row['start_time'])\n                end= hms_to_s(row['end_time'])\n                segment= Segment(start, end)\n                annotation[segment]= row['speaker_id']\n\n            dataset.append({\n                \"uri\":file_id,\n                \"audio\": audio_path,\n                \"annotation\": annotation\n            })\n\n    return dataset","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-16T16:31:38.217706Z","iopub.execute_input":"2026-02-16T16:31:38.218536Z","iopub.status.idle":"2026-02-16T16:31:38.224149Z","shell.execute_reply.started":"2026-02-16T16:31:38.218507Z","shell.execute_reply":"2026-02-16T16:31:38.223408Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Load and split data","metadata":{}},{"cell_type":"code","source":"full_data = load_bengali_data(AUDIO_DIR, CSV_DIR)\ntrain_data, val_data= train_test_split(full_data, test_size=0.1, random_state=42)\nprint(f\"Total files: {len(full_data)} | Train: {len(train_data)} | Validation: {len(val_data)}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-16T16:31:40.395172Z","iopub.execute_input":"2026-02-16T16:31:40.395469Z","iopub.status.idle":"2026-02-16T16:31:40.570103Z","shell.execute_reply.started":"2026-02-16T16:31:40.395443Z","shell.execute_reply":"2026-02-16T16:31:40.569445Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Create Protocol","metadata":{}},{"cell_type":"code","source":"from torch.utils.data import Dataset\n\nclass BengaliDataset(Dataset):\n    def __init__(self,data):\n        self.data=data\n        self.preprocessors = {\"audio\": FileFinder()}\n\n    def __len__(self):\n        return len(self.data)\n\n    def __getitem__(self, idx):\n        item = self.data[idx]\n\n        return {\n            \"uri\": item[\"uri\"],\n            \"audio\": item[\"audio\"],\n            \"annotation\": item[\"annotation\"]\n        }\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-16T16:31:43.731117Z","iopub.execute_input":"2026-02-16T16:31:43.731921Z","iopub.status.idle":"2026-02-16T16:31:43.736362Z","shell.execute_reply.started":"2026-02-16T16:31:43.731893Z","shell.execute_reply":"2026-02-16T16:31:43.735763Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from pyannote.database.protocol import SpeakerDiarizationProtocol\nfrom pyannote.core import Timeline\n\nclass BengaliProtocol(SpeakerDiarizationProtocol):\n    def __init__(self, train_data, val_data):\n        super().__init__()\n        self.name = \"BengaliDiarization\"\n        self.train_data = train_data\n        self.val_data = val_data\n        self.preprocessors = {\"audio\": FileFinder()}\n\n    def train(self):\n        for item in self.train_data:\n            annotated_timeline = Timeline([item[\"annotation\"].get_timeline().extent()])\n            yield {\n                \"uri\": item[\"uri\"],\n                \"audio\": item[\"audio\"],\n                \"annotation\": item[\"annotation\"],\n                \"annotated\": annotated_timeline,\n                \"database\": \"BengaliDiarization\",\n                \"subset\": \"train\",\n                \"scope\": \"file\",\n                \"torchaudio.info\": torchaudio.info(item[\"audio\"])\n            }\n\n    def train_len(self):\n        return len(self.train_data)\n\n    def development(self):\n        for item in self.val_data:\n            annotated_timeline = Timeline([item[\"annotation\"].get_timeline().extent()])\n            yield {\n                \"uri\": item[\"uri\"],\n                \"audio\": item[\"audio\"],\n                \"annotation\": item[\"annotation\"],\n                \"annotated\": annotated_timeline,\n                \"database\": \"BengaliDiarization\",\n                \"subset\": \"development\",\n                \"scope\": \"file\",\n                \"torchaudio.info\": torchaudio.info(item[\"audio\"])\n            }\n\n    def development_len(self):\n        return len(self.val_data)\n\n    def test(self):\n        for item in self.val_data:\n            annotated_timeline = Timeline([item[\"annotation\"].get_timeline().extent()])\n            yield {\n                \"uri\": item[\"uri\"],\n                \"audio\": item[\"audio\"],\n                \"annotation\": item[\"annotation\"],\n                \"annotated\": annotated_timeline,\n                \"database\": \"BengaliDiarization\",\n                \"subset\": \"test\",\n                \"scope\": \"file\",\n                \"torchaudio.info\": torchaudio.info(item[\"audio\"])\n            }\n\nprotocol = BengaliProtocol(train_data, val_data)\nprint(\"Protocol created with training and validation data\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-16T16:31:47.563874Z","iopub.execute_input":"2026-02-16T16:31:47.564556Z","iopub.status.idle":"2026-02-16T16:31:47.573093Z","shell.execute_reply.started":"2026-02-16T16:31:47.564531Z","shell.execute_reply":"2026-02-16T16:31:47.572423Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"**Segmentation training setup**","metadata":{}},{"cell_type":"markdown","source":"Load segmentation model","metadata":{}},{"cell_type":"code","source":"import torch\nimport lightning_fabric.utilities.cloud_io as cloud_io\nimport pyannote.audio.core.model as model_core\n\ncloud_io.torch.load = torch.load\nif hasattr(model_core, 'pl_load'):\n    from lightning_fabric.utilities.cloud_io import _load as lightning_load\n    model_core.pl_load = lightning_load\n\nfrom pyannote.audio import Model\nfrom pyannote.audio.tasks import Segmentation\nfrom pyannote.audio.core.task import Specifications, Problem, Resolution\n\ntask = Segmentation(\n    protocol, \n    duration=1.5, \n    max_speakers_per_chunk=4, \n    batch_size=32,\n    num_workers=4\n)\n\nwith torch.serialization.safe_globals([\n    Specifications, \n    Problem, \n    Resolution, \n    torch.torch_version.TorchVersion\n]):\n    model = Model.from_pretrained(\"pyannote/segmentation-3.0\", use_auth_token=True)\n\nmodel.task = task\nmodel.setup(stage=\"fit\")\n\nprint(\"Success! Environment fully purged and model loaded.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-16T16:31:52.250144Z","iopub.execute_input":"2026-02-16T16:31:52.250466Z","iopub.status.idle":"2026-02-16T16:31:57.637730Z","shell.execute_reply.started":"2026-02-16T16:31:52.250440Z","shell.execute_reply":"2026-02-16T16:31:57.636978Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from pytorch_lightning.callbacks import TQDMProgressBar\n\nclass DiarizationProgressBar(TQDMProgressBar):\n    def get_metrics(self, trainer, model):\n        items = super().get_metrics(trainer, model)\n        \n        train_loss = (\n            trainer.callback_metrics.get(\"loss/train\") or\n            \"N/A\"\n        )\n        \n        val_loss = (\n            trainer.callback_metrics.get(\"loss/val\") or \n            \"N/A\"\n        )\n\n        if isinstance(train_loss, torch.Tensor): train_loss = f\"{train_loss.item():.3f}\"\n        if isinstance(val_loss, torch.Tensor): val_loss = f\"{val_loss.item():.3f}\"\n\n        items[\"train\"] = train_loss\n        items[\"val\"] = val_loss\n    \n        items.pop(\"loss\", None)\n        \n        return items","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-16T16:32:00.554786Z","iopub.execute_input":"2026-02-16T16:32:00.555631Z","iopub.status.idle":"2026-02-16T16:32:00.560975Z","shell.execute_reply.started":"2026-02-16T16:32:00.555603Z","shell.execute_reply":"2026-02-16T16:32:00.560251Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"callbacks for monitoring val_loss and train_loss","metadata":{}},{"cell_type":"code","source":"checkpoint_cb= ModelCheckpoint(\n    dirpath=\"/kaggle/working/checkpoints\",\n    filename=\"bengali-seg-{epoch:02d}-vloss{loss/val:.4f}\",\n    monitor=\"loss/val\",\n    mode=\"min\",\n    save_top_k=-1,\n    auto_insert_metric_name=False,\n    verbose=True\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-16T16:32:06.537363Z","iopub.execute_input":"2026-02-16T16:32:06.537975Z","iopub.status.idle":"2026-02-16T16:32:06.542288Z","shell.execute_reply.started":"2026-02-16T16:32:06.537946Z","shell.execute_reply":"2026-02-16T16:32:06.541658Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Early stop and Trainer","metadata":{}},{"cell_type":"code","source":"early_stop = EarlyStopping(monitor=\"loss/val\", patience=3, mode=\"min\", verbose=True)\nlogger = CSVLogger(\"/kaggle/working/\", name=\"training_logs\")\n\ntrainer= Trainer(\n    max_epochs=10,\n    accelerator=\"gpu\",\n    devices=1,\n    precision=32,\n    callbacks=[checkpoint_cb, early_stop, DiarizationProgressBar()],\n    logger=logger,\n    log_every_n_steps=5,\n    num_sanity_val_steps=2\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-16T16:32:11.040892Z","iopub.execute_input":"2026-02-16T16:32:11.041623Z","iopub.status.idle":"2026-02-16T16:32:11.100197Z","shell.execute_reply.started":"2026-02-16T16:32:11.041598Z","shell.execute_reply":"2026-02-16T16:32:11.099647Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"start segmentation training","metadata":{}},{"cell_type":"code","source":"import torch, gc\ngc.collect()\ntorch.cuda.empty_cache()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-16T16:32:40.256180Z","iopub.execute_input":"2026-02-16T16:32:40.256786Z","iopub.status.idle":"2026-02-16T16:32:40.564739Z","shell.execute_reply.started":"2026-02-16T16:32:40.256739Z","shell.execute_reply":"2026-02-16T16:32:40.563852Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Starting Training\")\ntrainer.fit(model)\nprint(\"Training Complete!\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-16T16:32:43.338496Z","iopub.execute_input":"2026-02-16T16:32:43.338825Z","iopub.status.idle":"2026-02-16T18:42:54.630558Z","shell.execute_reply.started":"2026-02-16T16:32:43.338793Z","shell.execute_reply":"2026-02-16T18:42:54.629727Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\n\ncheckpoint_dir = \"/kaggle/working/checkpoints\"\nprefix = \"bengali-seg\"\n\nif os.path.exists(checkpoint_dir):\n    files = [f for f in os.listdir(checkpoint_dir) if f.startswith(prefix)]\n    if files:\n        print(f\"SUCCESS: Found {len(files)} checkpoint(s)!\")\n        for f in files:\n            size = os.path.getsize(os.path.join(checkpoint_dir, f)) / (1024*1024)\n            print(f\"   -> {f} ({size:.2f} MB)\")\n    else:\n        print(\"Empty folder: Training is running but hasn't saved yet.\")\nelse:\n    print(\"Folder not found yet.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-16T18:47:04.474535Z","iopub.execute_input":"2026-02-16T18:47:04.474885Z","iopub.status.idle":"2026-02-16T18:47:04.481522Z","shell.execute_reply.started":"2026-02-16T18:47:04.474850Z","shell.execute_reply":"2026-02-16T18:47:04.480929Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Save model and checkpoint","metadata":{}},{"cell_type":"code","source":"import os\nimport torch\nimport shutil\nimport torch.nn as nn\nimport yaml\nfrom pyannote.audio import Model\n\nbest_ckpt = \"/kaggle/working/checkpoints/bengali-seg-00-vloss0.1372.ckpt\"\ninference_path = \"/kaggle/working/bengali_diarization_model_pyannote\"\nos.makedirs(inference_path, exist_ok=True)\n\nprint(f\"Surgery starting on Bengali Model...\")\n\ntry:\n    model = Model.from_pretrained(\"pyannote/segmentation-3.0\")\n    \n    model.classifier = nn.Linear(128, 4)\n\n    checkpoint = torch.load(best_ckpt, map_location=\"cpu\", weights_only=False)\n    state_dict = checkpoint[\"state_dict\"]\n    \n    new_state_dict = {k.replace(\"model.\", \"\"): v for k, v in state_dict.items()}\n    model.load_state_dict(new_state_dict, strict=False)\n\n    torch.save(model.state_dict(), os.path.join(inference_path, \"pytorch_model.bin\"))\n\n    config = {\n        \"architecture\": {\n            \"module\": \"pyannote.audio.models.segmentation.PyanNet\",\n            \"instantiation\": {\n                \"sample_rate\": 16000,\n                \"num_channels\": 1,\n                \"sincnet\": {\"sample_rate\": 16000},\n            }\n        },\n        \"task\": {\n            \"name\": \"segmentation\",\n            \"classes\": [\"speaker1\", \"speaker2\", \"speaker3\", \"speaker4\"]\n        }\n    }\n\n    with open(os.path.join(inference_path, \"config.yaml\"), \"w\") as f:\n        yaml.dump(config, f)\n\n    print(f\"SUCCESS: Manual export complete at: {inference_path}\")\n\n    resume_path = \"/kaggle/working/best_bengali_training_state.ckpt\"\n    shutil.copy(best_ckpt, resume_path)\n    print(f\"SUCCESS: Checkpoint backup saved at: {resume_path}\")\n\nexcept Exception as e:\n    print(f\"Surgery failed: {e}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-16T19:26:25.631147Z","iopub.execute_input":"2026-02-16T19:26:25.631507Z","iopub.status.idle":"2026-02-16T19:26:25.958533Z","shell.execute_reply.started":"2026-02-16T19:26:25.631481Z","shell.execute_reply":"2026-02-16T19:26:25.957826Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Evaluate Training DER","metadata":{}},{"cell_type":"code","source":"import numpy as np\nnp.NAN = np.nan\nimport warnings\nimport logging\nimport os\nimport torch\nimport torch.nn as nn\nfrom pathlib import Path\nfrom pyannote.audio import Model, Pipeline\nfrom pyannote.metrics.diarization import DiarizationErrorRate\n\n# 1. Silence all warnings and logs\nwarnings.filterwarnings(\"ignore\")\nlogging.getLogger(\"pyannote\").setLevel(logging.ERROR)\nlogging.getLogger(\"speechbrain\").setLevel(logging.ERROR)\nlogging.getLogger(\"torch\").setLevel(logging.ERROR)\nos.environ[\"KMP_WARNINGS\"] = \"0\"\nos.environ[\"PYTHONWARNINGS\"] = \"ignore\"\n\npipeline = Pipeline.from_pretrained(\"pyannote/speaker-diarization-3.1\", use_auth_token=True)\n\ntry:\n    print(\"Loading Bengali fine-tuned segmentation model (Direct Injection)...\")\n    \n    bengali_model = Model.from_pretrained(\"pyannote/segmentation-3.0\")\n    \n    bengali_model.classifier = nn.Linear(128, 4)\n    \n    weights_path = \"/kaggle/working/bengali_diarization_model_pyannote/pytorch_model.bin\"\n    weights = torch.load(weights_path, map_location=\"cpu\")\n    bengali_model.load_state_dict(weights)\n\n    if not hasattr(bengali_model, \"min_duration_off\"):\n        bengali_model.min_duration_off = 0.0\n    \n    pipeline.segmentation = bengali_model\n    pipeline.to(torch.device(\"cuda\"))\n    \n    print(\"SUCCESS: Bengali weights are now ACTIVE in the pipeline.\")\n\nexcept Exception as e:\n    print(f\"Direct injection failed: {e}\")\n    raise e\n\nmetric = DiarizationErrorRate()\nprint(\"Starting DER calculation...\")\ndev_set = list(protocol.development())\n\nfor i, item in enumerate(dev_set):\n    reference = item[\"annotation\"]\n    \n    hypothesis = pipeline(item, max_speakers=4)\n    \n    metric(reference, hypothesis, uem=item[\"annotated\"])\n    \n    current_der = abs(metric) * 100\n    print(f\"[{i+1}/{len(dev_set)}] File: {item['uri']} | Progress DER: {current_der:.2f}%\", end=\"\\r\")\n\nfinal_der = abs(metric) * 100\nprint(\"\\n\" + \"=\"*40)\nprint(f\"FINAL BENGALI SYSTEM DER: {final_der:.2f}%\")\nprint(\"=\"*40)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# This will print a table showing Missed Speech, False Alarms, and Speaker Confusion\nprint(metric)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"English baseline DER for comparison","metadata":{}},{"cell_type":"code","source":"import numpy as np\nnp.NAN = np.nan\nimport warnings\nimport torch\nfrom pathlib import Path\nfrom pyannote.audio import Model\nfrom pyannote.metrics.diarization import DiarizationErrorRate\n\nwarnings.filterwarnings(\"ignore\")\nlogging.getLogger(\"pyannote\").setLevel(logging.ERROR)\nlogging.getLogger(\"speechbrain\").setLevel(logging.ERROR)\nlogging.getLogger(\"torch\").setLevel(logging.ERROR)\nos.environ[\"KMP_WARNINGS\"] = \"0\"\nos.environ[\"PYTHONWARNINGS\"] = \"ignore\"\n\nenglish_pipeline = Pipeline.from_pretrained(\"pyannote/speaker-diarization-3.1\", use_auth_token=True)\nenglish_pipeline.to(torch.device(\"cuda\"))\n\nbaseline_metric = DiarizationErrorRate()\n\nprint(\"Calculating English Baseline DER...\")\ndev_set = list(protocol.development())\n\nfor i, item in enumerate(dev_set):\n    reference = item[\"annotation\"]\n    \n    hypothesis = english_pipeline(item)\n    \n    baseline_metric(reference, hypothesis, uem=item[\"annotated\"])\n    \n    print(f\"[{i+1}/{len(dev_set)}] File: {item['uri']} | Baseline DER: {abs(baseline_metric)*100:.2f}%\", end=\"\\r\")\n\nprint(\"\\n\" + \"=\"*40)\nprint(f\"FINAL ENGLISH BASELINE DER: {abs(baseline_metric) * 100:.2f}%\")\nprint(\"=\"*40)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Validation of checkpoint","metadata":{}},{"cell_type":"code","source":"import torch\nfrom pyannote.audio import Model\n\ncheckpoint_path = \"/kaggle/working/checkpoints/bengali-seg-00-vloss0.1372.ckpt\"\n\ntry:\n    checkpoint = torch.load(checkpoint_path, map_location=\"cpu\")\n    print(f\"Checkpoint is healthy!\")\n    print(f\"Saved at Epoch: {checkpoint['epoch']}\")\n    print(f\"Global Step: {checkpoint['global_step']}\")\nexcept Exception as e:\n    print(f\"Checkpoint is corrupted: {e}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-16T19:26:33.496714Z","iopub.execute_input":"2026-02-16T19:26:33.497094Z","iopub.status.idle":"2026-02-16T19:26:33.518356Z","shell.execute_reply.started":"2026-02-16T19:26:33.497067Z","shell.execute_reply":"2026-02-16T19:26:33.517548Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Check the saved model","metadata":{}},{"cell_type":"code","source":"import os\n\nfiles = [\n    \"/kaggle/working/bengali_diarization_model_pyannote/pytorch_model.bin\",\n    \"/kaggle/working/best_bengali_training_state.ckpt\"\n]\n\nfor f in files:\n    if os.path.exists(f):\n        print(f\"{f.split('/')[-1]} exists. Size: {os.path.getsize(f) / 1e6:.2f} MB\")\n    else:\n        print(f\"{f.split('/')[-1]} is MISSING!\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-16T19:26:39.827154Z","iopub.execute_input":"2026-02-16T19:26:39.827443Z","iopub.status.idle":"2026-02-16T19:26:39.832891Z","shell.execute_reply.started":"2026-02-16T19:26:39.827418Z","shell.execute_reply":"2026-02-16T19:26:39.832089Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Download the fine-tuned model","metadata":{}},{"cell_type":"code","source":"import shutil\nimport os\nfrom IPython.display import FileLink\n\nmodel_folder = \"/kaggle/working/bengali_diarization_model_pyannote\"\nzip_name = \"bengali_diarization_pyannote_model\"\n\nif os.path.exists(model_folder):\n    print(f\"Found model folder at {model_folder}. Starting compression...\")\n    \n    shutil.make_archive(zip_name, 'zip', model_folder)\n    \n    print(f\"Zip file created: {zip_name}.zip\")\n    \n    print(\"Click the link below to download:\")\n    display(FileLink(f\"{zip_name}.zip\"))\nelse:\n    print(f\"Error: The folder {model_folder} was not found.\")\n  ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-16T19:26:49.625087Z","iopub.execute_input":"2026-02-16T19:26:49.625379Z","iopub.status.idle":"2026-02-16T19:26:49.917821Z","shell.execute_reply.started":"2026-02-16T19:26:49.625355Z","shell.execute_reply":"2026-02-16T19:26:49.917253Z"}},"outputs":[],"execution_count":null}]}