Spaces:
Running
Running
File size: 5,627 Bytes
89939ec | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | # -*- coding: utf-8 -*-
"""text_summarization_finetune.ipynb
Automatically generated by Colab.
Original file is located at
https://colab.research.google.com/drive/1DC3LFNnBCIfmnKp8DvUFF8Q2FIhwc7RP
# Text Summarization — Fine-tuning T5-small on CNN/DailyMail
**Dataset:** `cnn_dailymail` (v3.0.0) — news articles with human-written highlights (summaries)
**Model:** `t5-small` — lightweight encoder-decoder model, good fit for Colab's free GPU
**Steps:**
1. Install libraries
2. Load & explore dataset
3. Load tokenizer & model
4. Preprocess (tokenize) data
5. Set up training (Seq2SeqTrainer)
6. Train
7. Evaluate with ROUGE
8. Run inference on a custom example
9. Save & (optionally) push the model
> Tip: In Colab go to **Runtime > Change runtime type > T4 GPU** before running.
## 1. Install libraries
"""
!pip install -q transformers datasets evaluate rouge_score accelerate sentencepiece
!pip install -q -U datasets huggingface_hub transformers
"""## 2. Load & explore the dataset"""
from datasets import load_dataset
raw_datasets = load_dataset("abisee/cnn_dailymail", "3.0.0")
train_dataset = raw_datasets["train"].shuffle(seed=42).select(range(3000))
val_dataset = raw_datasets["validation"].shuffle(seed=42).select(range(300))
test_dataset = raw_datasets["test"].shuffle(seed=42).select(range(300))
print(train_dataset)
print(train_dataset[0]["article"][:500])
print("\n--- Summary ---")
print(train_dataset[0]["highlights"])
"""## 3. Load tokenizer & model"""
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
model_checkpoint = "t5-small"
tokenizer = AutoTokenizer.from_pretrained(model_checkpoint)
model = AutoModelForSeq2SeqLM.from_pretrained(model_checkpoint)
prefix = "summarize: "
"""## 4. Preprocess (tokenize) the data"""
max_input_length = 512
max_target_length = 128
def preprocess_function(examples):
inputs = [prefix + doc for doc in examples["article"]]
model_inputs = tokenizer(inputs, max_length=max_input_length, truncation=True)
labels = tokenizer(text_target=examples["highlights"], max_length=max_target_length, truncation=True)
model_inputs["labels"] = labels["input_ids"]
return model_inputs
tokenized_train = train_dataset.map(preprocess_function, batched=True, remove_columns=train_dataset.column_names)
tokenized_val = val_dataset.map(preprocess_function, batched=True, remove_columns=val_dataset.column_names)
tokenized_test = test_dataset.map(preprocess_function, batched=True, remove_columns=test_dataset.column_names)
"""## 5. Set up training"""
import numpy as np
import evaluate
from transformers import DataCollatorForSeq2Seq, Seq2SeqTrainingArguments, Seq2SeqTrainer
data_collator = DataCollatorForSeq2Seq(tokenizer=tokenizer, model=model)
rouge = evaluate.load("rouge")
def compute_metrics(eval_pred):
predictions, labels = eval_pred
decoded_preds = tokenizer.batch_decode(predictions, skip_special_tokens=True)
labels = np.where(labels != -100, labels, tokenizer.pad_token_id)
decoded_labels = tokenizer.batch_decode(labels, skip_special_tokens=True)
result = rouge.compute(predictions=decoded_preds, references=decoded_labels, use_stemmer=True)
result = {k: round(v * 100, 2) for k, v in result.items()}
prediction_lens = [np.count_nonzero(pred != tokenizer.pad_token_id) for pred in predictions]
result["gen_len"] = round(np.mean(prediction_lens), 2)
return result
training_args = Seq2SeqTrainingArguments(
output_dir="./t5-summarization-cnn",
eval_strategy="epoch",
save_strategy="epoch",
learning_rate=3e-4,
per_device_train_batch_size=8,
per_device_eval_batch_size=8,
weight_decay=0.01,
save_total_limit=2,
num_train_epochs=3,
predict_with_generate=True,
fp16=True,
logging_steps=50,
report_to="none",
)
trainer = Seq2SeqTrainer(
model=model,
args=training_args,
train_dataset=tokenized_train,
eval_dataset=tokenized_val,
data_collator=data_collator,
compute_metrics=compute_metrics,
)
"""## 6. Train"""
trainer.train()
"""## 7. Evaluate on the test set"""
test_results = trainer.predict(tokenized_test)
print(test_results.metrics)
"""## 8. Try it on a custom example"""
def summarize(text, max_length=128):
inputs = tokenizer(prefix + text, return_tensors="pt", truncation=True, max_length=max_input_length).to(model.device)
summary_ids = model.generate(
**inputs,
max_length=max_length,
num_beams=4,
length_penalty=2.0,
early_stopping=True,
)
return tokenizer.decode(summary_ids[0], skip_special_tokens=True)
sample_article = test_dataset[0]["article"]
print("Original article:\n", sample_article[:800])
print("\nReference summary:\n", test_dataset[0]["highlights"])
print("\nModel summary:\n", summarize(sample_article))
"""## 9. Save the model (and optionally push to Hugging Face Hub)"""
save_dir = "./t5-summarization-cnn-final"
trainer.save_model(save_dir)
tokenizer.save_pretrained(save_dir)
print("Model saved to", save_dir)
"""## Notes & next steps
- **Scaling up:** increase `train_dataset`/`val_dataset` sizes and `num_train_epochs` for better ROUGE scores (full dataset training takes hours even on T4 — good for a final run, not quick iteration).
- **Bigger model:** swap `t5-small` for `t5-base`, `facebook/bart-base`, or `sshleifer/distilbart-cnn-12-6` if you have more GPU memory/time.
- **Different domain:** swap the dataset for `samsum` (dialogue summarization) or `xsum` (very short summaries) by changing the `load_dataset(...)` call and the column names (`dialogue`/`summary` for samsum).
""" |