jefffffff9 Claude Sonnet 4.6 commited on
Commit
c1bce9f
·
1 Parent(s): 8cf3564

Fix Cell 14: replace evaluate.load('wer') with jiwer directly

Browse files

evaluate==0.4.2 uses use_auth_token which was removed from
huggingface-hub>=1.0 -- raises AttributeError at runtime.
Replaced with jiwer.wer() + jiwer.Compose transforms, which needs
no network call and is already installed.

Also removed evaluate from Cell 2 install list.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

notebooks/kaggle_master_trainer.ipynb CHANGED
@@ -33,7 +33,7 @@
33
  "id": "cell-install",
34
  "metadata": {},
35
  "outputs": [],
36
- "source": "# -- Cell 2: Install dependencies + fix torchvision CUDA mismatch -------------\n# Kaggle ships torchvision built against CUDA 12.8 but torch uses CUDA 13.0.\n# Any import touching torchvision (WhisperProcessor, WhisperForConditionalGeneration)\n# raises RuntimeError. The fix requires reinstalling torchvision AND restarting\n# the kernel so the new version is loaded from scratch.\n#\n# This cell uses a sentinel file so it only restarts once:\n# First run -> installs correct torchvision -> restarts kernel\n# Second run -> sentinel exists -> skips restart -> continues normally\n\nimport subprocess, sys, os\nfrom pathlib import Path\n\nSENTINEL = Path('/kaggle/working/.torchvision_fixed')\n\nif not SENTINEL.exists():\n import torch\n cuda_tag = 'cu' + torch.version.cuda.replace('.', '')[:3] # e.g. cu130\n print(f'Fixing torchvision for CUDA {cuda_tag} (will restart kernel) ...')\n\n subprocess.check_call([\n sys.executable, '-m', 'pip', 'install', '-q', '--upgrade',\n 'torchvision',\n '--index-url', f'https://download.pytorch.org/whl/{cuda_tag}',\n ])\n\n pkgs = [\n 'transformers==5.5.0', 'datasets==4.8.4', 'accelerate==1.13.0',\n 'evaluate==0.4.2', 'huggingface-hub==1.9.0', 'peft==0.18.1',\n 'bitsandbytes==0.49.2', 'librosa==0.10.2', 'soundfile==0.12.1',\n 'jiwer==3.0.4', 'numpy==2.2.4', 'scipy==1.15.2',\n ]\n subprocess.check_call([sys.executable, '-m', 'pip', 'install', '-q', *pkgs])\n\n SENTINEL.touch()\n print('Packages installed. Restarting kernel to load new torchvision ...')\n import IPython\n IPython.Application.instance().kernel.do_shutdown(restart=True)\n\nelse:\n print('torchvision already fixed (sentinel exists) -- skipping restart.')\n import torch\n print(f'torch : {torch.__version__}')\n print(f'CUDA : {torch.version.cuda}')\n print(f'GPU : {torch.cuda.get_device_name(0) if torch.cuda.is_available() else \"none\"}')\n print('Ready.')"
37
  },
38
  {
39
  "cell_type": "code",
@@ -149,7 +149,7 @@
149
  "id": "cell-collator",
150
  "metadata": {},
151
  "outputs": [],
152
- "source": "# ── Cell 14: Data collator + WER metric ──────────────────────────────────────\nimport evaluate\nfrom dataclasses import dataclass\nfrom typing import Any, Dict, List\n\nwer_metric = evaluate.load('wer')\n\n\n@dataclass\nclass DataCollatorSpeechSeq2SeqWithPadding:\n \"\"\"\n Pads input_features (mel spectrograms) and labels independently.\n Labels use -100 for padding so CrossEntropyLoss ignores them.\n Strips the BOS token from label sequences (Whisper convention).\n \"\"\"\n processor: Any\n\n def __call__(self, features: List[Dict]) -> Dict:\n # Pad mel features\n input_feats = [{'input_features': f['input_features']} for f in features]\n batch = self.processor.feature_extractor.pad(input_feats, return_tensors='pt')\n\n # Pad labels\n label_feats = [{'input_ids': f['labels']} for f in features]\n labels_batch = self.processor.tokenizer.pad(label_feats, return_tensors='pt')\n labels = labels_batch['input_ids'].masked_fill(\n labels_batch.attention_mask.ne(1), -100\n )\n # Remove leading BOS token (Whisper adds it during generation, not training)\n if (labels[:, 0] == self.processor.tokenizer.bos_token_id).all().item():\n labels = labels[:, 1:]\n batch['labels'] = labels\n return batch\n\n\ndef compute_metrics(pred):\n \"\"\"WER on the eval set (lower is better).\"\"\"\n pred_ids = pred.predictions\n label_ids = pred.label_ids\n # Replace -100 padding back to pad_token_id for decoding\n label_ids[label_ids == -100] = processor.tokenizer.pad_token_id\n\n pred_str = processor.tokenizer.batch_decode(pred_ids, skip_special_tokens=True)\n label_str = processor.tokenizer.batch_decode(label_ids, skip_special_tokens=True)\n wer = wer_metric.compute(predictions=pred_str, references=label_str)\n return {'wer': round(wer, 4)}\n\n\ncollator = DataCollatorSpeechSeq2SeqWithPadding(processor=processor)\nprint('✅ Collator and WER metric ready')"
153
  },
154
  {
155
  "cell_type": "markdown",
 
33
  "id": "cell-install",
34
  "metadata": {},
35
  "outputs": [],
36
+ "source": "# -- Cell 2: Install dependencies + fix torchvision CUDA mismatch -------------\nimport subprocess, sys\nfrom pathlib import Path\n\nSENTINEL = Path('/kaggle/working/.torchvision_fixed')\n\nif not SENTINEL.exists():\n import torch\n cuda_tag = 'cu' + torch.version.cuda.replace('.', '')[:3]\n print(f'Fixing torchvision for CUDA {cuda_tag} (will restart kernel) ...')\n subprocess.check_call([\n sys.executable, '-m', 'pip', 'install', '-q', '--upgrade',\n 'torchvision', '--index-url', f'https://download.pytorch.org/whl/{cuda_tag}',\n ])\n pkgs = [\n 'transformers==5.5.0', 'datasets==4.8.4', 'accelerate==1.13.0',\n 'huggingface-hub==1.9.0', 'peft==0.18.1',\n 'bitsandbytes==0.49.2', 'librosa==0.10.2', 'soundfile==0.12.1',\n 'jiwer==3.0.4', 'numpy==2.2.4', 'scipy==1.15.2',\n # NOTE: evaluate is intentionally excluded -- evaluate.load('wer') breaks\n # with huggingface-hub>=1.0 (use_auth_token removed). We use jiwer directly.\n ]\n subprocess.check_call([sys.executable, '-m', 'pip', 'install', '-q', *pkgs])\n SENTINEL.touch()\n print('Restarting kernel to load fixed torchvision ...')\n import IPython\n IPython.Application.instance().kernel.do_shutdown(restart=True)\nelse:\n import torch\n print('torchvision already fixed -- skipping restart.')\n print(f'torch : {torch.__version__} CUDA : {torch.version.cuda}')\n print(f'GPU : {torch.cuda.get_device_name(0) if torch.cuda.is_available() else \"none\"}')"
37
  },
38
  {
39
  "cell_type": "code",
 
149
  "id": "cell-collator",
150
  "metadata": {},
151
  "outputs": [],
152
+ "source": "# -- Cell 14: Data collator + WER metric --------------------------------------\n# evaluate.load('wer') breaks with huggingface-hub>=1.0 (use_auth_token removed).\n# Use jiwer directly instead -- same result, no network call needed.\nimport jiwer\nfrom dataclasses import dataclass\nfrom typing import Any, Dict, List\n\ntransform = jiwer.Compose([\n jiwer.ToLowerCase(),\n jiwer.RemoveMultipleSpaces(),\n jiwer.Strip(),\n jiwer.RemovePunctuation(),\n jiwer.ReduceToListOfListOfWords(),\n])\n\n\n@dataclass\nclass DataCollatorSpeechSeq2SeqWithPadding:\n processor: Any\n\n def __call__(self, features: List[Dict]) -> Dict:\n import torch\n # Pad mel features\n input_feats = [{'input_features': f['input_features']} for f in features]\n batch = self.processor.feature_extractor.pad(input_feats, return_tensors='pt')\n\n # Pad labels, replace padding with -100\n label_feats = [{'input_ids': f['labels']} for f in features]\n labels_batch = self.processor.tokenizer.pad(label_feats, return_tensors='pt')\n labels = labels_batch['input_ids'].masked_fill(\n labels_batch.attention_mask.ne(1), -100\n )\n # Strip leading BOS token\n if (labels[:, 0] == self.processor.tokenizer.bos_token_id).all().item():\n labels = labels[:, 1:]\n batch['labels'] = labels\n return batch\n\n\ndef compute_metrics(pred):\n pred_ids = pred.predictions\n label_ids = pred.label_ids\n label_ids[label_ids == -100] = processor.tokenizer.pad_token_id\n\n pred_str = processor.tokenizer.batch_decode(pred_ids, skip_special_tokens=True)\n label_str = processor.tokenizer.batch_decode(label_ids, skip_special_tokens=True)\n\n wer = jiwer.wer(label_str, pred_str,\n hypothesis_transform=transform,\n reference_transform=transform)\n return {'wer': round(wer, 4)}\n\n\ncollator = DataCollatorSpeechSeq2SeqWithPadding(processor=processor)\nprint('Collator and WER metric ready')"
153
  },
154
  {
155
  "cell_type": "markdown",