Sinh văn bản và tóm tắt văn bản
This content is not available in your language yet.
Mục tiêu
Phần tiêu đề “Mục tiêu”Sau bài này, bạn sẽ:
- Đặt cạnh nhau các chiến lược giải mã (decoding strategy): tham lam, beam search, lấy mẫu (sampling), nhiệt độ (temperature), top-k, top-p và phạt lặp (repetition penalty), và chọn được cách hợp cho từng việc.
- Phân biệt tóm tắt trích xuất (extractive summarization) với tóm tắt tóm lược (abstractive summarization), và biết BART, T5, PEGASUS học tóm tắt bằng cách nào.
- Tự tính được ROUGE-1, ROUGE-2, ROUGE-L, và biết ROUGE đo được gì, không đo được gì.
- Nhận ra hallucination (bịa thông tin) trong bản tóm tắt, phân biệt hallucination nội sinh và ngoại sinh, và biết vài cách giảm.
Cần biết trước
Phần tiêu đề “Cần biết trước”- GPT and Distributed Training, in Natural Language Processing(Not translated yet) (Learned)
Trực giác
Phần tiêu đề “Trực giác”Bút dạ quang hay tự viết lại
Phần tiêu đề “Bút dạ quang hay tự viết lại”Sáng nay bạn đọc một bản tin bảy câu: Đà Nẵng mở tuyến xe buýt điện đầu tiên, tuyến dài bao nhiêu, giá vé, tháng đầu miễn phí, mỗi xe chạy được bao xa sau một lần sạc, người dân khen gì, năm sau mở thêm mấy tuyến. Sếp nhờ bạn rút gọn còn hai câu. Bạn có hai cách.
Cách thứ nhất: cầm bút dạ quang. Tô hai câu quan trọng nhất rồi chép nguyên văn. Không bao giờ viết sai điều bài báo nói, vì chữ nào cũng là chữ của bài báo. Nhưng hai câu chép rời có thể cụt: câu “Tuyến dài 18 km” đứng một mình thì người đọc không biết “tuyến” nào.
Cách thứ hai: tự viết lại. “Đà Nẵng mở tuyến xe buýt điện đầu tiên nối sân bay với biển Mỹ Khê. Tháng đầu miễn phí vé, năm sau mở thêm ba tuyến.” Gọn và trôi chảy hơn. Nhưng giờ bạn viết, nên bạn có thể viết sai: nhầm “đầu tiên” thành “thứ hai”, hay thêm một chi tiết bài báo không hề nói.
Máy làm cách thứ hai bằng cách sinh văn bản từng token một. Ở mỗi bước, mô hình cho một phân phối xác suất trên mọi token, và ta phải chọn một token. Chọn token chắc nhất, hay rút thăm cho đa dạng? Với tóm tắt, ta muốn đúng và ổn định. Với viết truyện, ta lại muốn bất ngờ.
Còn một câu hỏi nữa: làm sao biết bản tóm tắt nào tốt hơn, khi có cả nghìn bản cần chấm và không đủ người đọc?
Bài toán của bài này là: chọn token thế nào khi sinh văn bản; chọn câu hay viết lại khi tóm tắt; và chấm một bản tóm tắt bằng máy mà không bị đánh lừa.
Lý thuyết
Phần tiêu đề “Lý thuyết”Sinh văn bản là một vòng lặp
Phần tiêu đề “Sinh văn bản là một vòng lặp”Như ở bài GPT và huấn luyện phân tán, một mô hình ngôn ngữ nhân quả học : xác suất của token kế tiếp khi biết mọi token trước nó. Mô hình encoder–decoder như T5 học , thêm điều kiện là văn bản nguồn (bài Mô hình chuỗi sang chuỗi). Cả hai sinh văn bản theo cùng một vòng lặp tự hồi quy (autoregressive):
- Đưa các token đã có vào mô hình, lấy logit cho mỗi token trong từ vựng.
- Biến logit thành một phân phối, rồi chọn một token theo một quy tắc.
- Nối token vừa chọn vào cuối, quay lại bước 1. Dừng khi gặp
<EOS>hoặc đủ số token tối đa.
Mô hình chỉ làm bước 1. Chiến lược giải mã là quy tắc ở bước 2. Cùng một mô hình, đổi quy tắc là đổi hẳn văn bản ra.
Các chiến lược giải mã đặt cạnh nhau
Phần tiêu đề “Các chiến lược giải mã đặt cạnh nhau”Bảng dưới gom các chiến lược hay gặp. Công thức của nhiệt độ, top-k và top-p, kèm ví dụ tính tay, có ở bài Sử dụng API văn bản. Beam search và phạt độ dài có ở bài Mô hình chuỗi sang chuỗi. Ở đây ta chỉ so chúng với nhau.
| Chiến lược | Chọn token thế nào | Tham số (tên trong generate) | Mạnh | Yếu |
|---|---|---|---|---|
| Tham lam (greedy) | Token xác suất cao nhất | num_beams=1, do_sample=False | Nhanh, tất định | Không xem lại lựa chọn sớm; dễ lặp khi viết dài |
| Beam search | Giữ chuỗi có tổng log-xác suất cao nhất | num_beams, length_penalty | Tìm được chuỗi xác suất cao hơn tham lam | Văn nhạt, lặp với sinh mở; tốn lần tính |
| Lấy mẫu thuần | Rút token theo đúng phân phối của mô hình | do_sample=True, top_k=0 | Đa dạng nhất | Thỉnh thoảng rút trúng đuôi vô nghĩa |
| Nhiệt độ | Chia logit cho trước softmax, rồi rút | temperature | Một núm vặn giữa chắc chắn và đa dạng | Không tự cắt đuôi |
| Top-k | Chỉ rút trong token đầu | top_k | Chặn đuôi | cố định, không theo độ chắc của mô hình |
| Top-p (nucleus) | Chỉ rút trong tập nhỏ nhất có tổng xác suất | top_p | Số token giữ lại co giãn theo độ chắc | Vẫn ngẫu nhiên, khó tái lập |
Top-k được Fan, Lewis và Dauphin (2018) dùng để sinh truyện: mỗi bước rút trong token đầu. Họ thấy cách này tốt hơn hẳn beam search, vốn hay cho ra những cụm từ phổ biến và lặp lại. Top-p là đề xuất của Holtzman và cộng sự (2020), lý do nằm ở mục ngay sau.
Văn bản thoái hóa
Phần tiêu đề “Văn bản thoái hóa”Mô hình tốt cho văn bản tốt xác suất cao, vậy chọn văn bản xác suất cao nhất phải tốt nhất? Thực tế thì không. Holtzman và cộng sự (2020) cho GPT-2 Large viết tiếp 5 000 đoạn văn (tối đa 200 token mỗi đoạn) rồi đo tỉ lệ đoạn bị “kẹt” trong một vòng lặp (một cụm từ lặp ít nhất ba lần ở cuối):
| Cách giải mã | Tỉ lệ bị lặp (%) |
|---|---|
| Văn bản của người | 0.28 |
| Tham lam | 73.66 |
| Beam search, | 28.94 |
| Lấy mẫu thuần | 0.22 |
| Top-p, | 0.36 |
Vì sao tham lam lặp nhiều như vậy? Họ thấy xác suất của một cụm từ lặp lại tăng lên sau mỗi lần lặp. Đã lặp một lần thì lần sau còn “chắc” hơn, thành một vòng phản hồi dương. Văn bản của người thì khác: nó thường xuyên rẽ sang những token xác suất thấp hơn nhưng mang nhiều thông tin hơn.
Lấy mẫu thuần thì gần như không lặp, nhưng lại hỏng theo kiểu khác: văn bản rời rạc, có khi bịa ra từ không có thật. Thủ phạm là cái đuôi không đáng tin của phân phối: hàng chục nghìn token, mỗi token xác suất nhỏ, nhưng cộng lại thì không nhỏ. Top-p cắt cái đuôi đó đi. Nó không phải cách ít lặp nhất trong bảng (lấy mẫu thuần còn ít hơn), nhưng xét chung perplexity và HUSE (một thước đo kết hợp người chấm và thống kê), top-p cho văn bản gần văn bản của người nhất.
Holtzman và cộng sự gọi chung hai kiểu hỏng này (văn nhạt, lặp vòng khi chọn theo xác suất cao nhất; văn rời rạc khi rút từ cả đuôi) là văn bản thoái hóa (neural text degeneration).
Phạt lặp
Phần tiêu đề “Phạt lặp”Một cách chặn lặp trực tiếp là hạ điểm của những token đã xuất hiện. Keskar và cộng sự (2019), trong bài báo về mô hình CTRL, đề xuất lấy mẫu có phạt (penalized sampling). Gọi là danh sách token đã sinh. Phân phối của token kế tiếp là:
Đọc từng phần:
- Token chưa xuất hiện: , logit chỉ chia cho như softmax có nhiệt độ thường.
- Token đã xuất hiện: logit bị chia thêm cho . Với và logit dương, logit nhỏ đi, nên xác suất giảm.
- là không phạt. Các tác giả thấy giải mã gần như tham lam với cân bằng tốt giữa viết đúng và không lặp.
Một cái bẫy với logit âm. Chia một số âm cho làm nó gần 0 hơn, tức lớn hơn: . Token đã lặp lại được ưu tiên hơn, ngược với ý định. Vì vậy repetition_penalty của Hugging Face Transformers chia logit dương cho nhưng nhân logit âm với . Với : logit thành , logit thành . Cả hai đều giảm.
Một cách cứng hơn là no_repeat_ngram_size=n: cấm hẳn mọi -gram đã xuất hiện. Cả hai cách đều phạt luôn những lần lặp đúng. Bản tóm tắt về xe buýt điện có thể cần nhắc “xe buýt điện” hai lần, mà no_repeat_ngram_size=3 thì không cho.
Khi nào dùng cách nào
Phần tiêu đề “Khi nào dùng cách nào”Holtzman và cộng sự chia việc sinh văn bản làm hai loại:
- Sinh có định hướng (directed generation): đầu ra bị đầu vào ràng buộc chặt, như dịch máy, tóm tắt, sinh văn bản từ bảng dữ liệu. Beam search (hoặc tham lam) là lựa chọn thường dùng. Ở đây lặp và nhạt ít là vấn đề, vì đầu vào đã quyết gần hết nội dung, còn sự ổn định và trung thành với nguồn thì quan trọng.
- Sinh mở (open-ended generation): viết tiếp truyện, hội thoại, gợi ý ý tưởng. Lấy mẫu có cắt đuôi (top-p, hay top-k kèm nhiệt độ) cho văn bản đa dạng và tự nhiên hơn.
Đây là điểm xuất phát, không phải luật. File cấu hình của T5-small có ghi sẵn một cấu hình cho tóm tắt trong config.task_specific_params: beam cùng no_repeat_ngram_size=3, tức beam search kèm cấm lặp. generate không tự áp cấu hình này: gọi generate mà không truyền gì thì vẫn là tham lam, như dòng greedy ở ô T5 bên dưới.
Tóm tắt trích xuất: chọn câu
Phần tiêu đề “Tóm tắt trích xuất: chọn câu”Tóm tắt trích xuất chấm điểm từng câu của văn bản rồi giữ vài câu điểm cao nhất, theo thứ tự xuất hiện để mạch văn không đảo lộn. Có ba cách chấm từ đơn giản tới phức tạp.
Lấy vài câu đầu (lead). Tin tức thường viết theo kiểu “kim tự tháp ngược”: ý chính đặt ở đầu. Vì vậy chỉ lấy câu đầu đã là một mốc so sánh khó vượt với tin tức. Nhưng nó vô dụng với loại văn bản không viết như vậy, như bài khoa học, email hay biên bản họp.
So với vectơ của cả bài, bằng TF-IDF. Coi mỗi câu là một “văn bản” trong một kho nhỏ câu. Mỗi câu thành một vectơ có trọng số TF-IDF như ở bài Ngữ nghĩa vectơ và embedding: số lần từ xuất hiện trong câu nhân với , với là số câu chứa . Cộng mọi vectơ câu được một vectơ đại diện cho cả bài:
Câu có điểm cao là câu “giống cả bài nhất”: nó chứa những từ vừa được nhắc nhiều trong bài, vừa không có mặt ở mọi câu. Cosine chia cho độ dài, nên câu dài không tự động thắng.
TextRank. Mihalcea và Tarau (2004) biến văn bản thành một đồ thị: mỗi câu là một đỉnh, hai câu nối nhau bằng một cạnh có trọng số bằng số từ chung, chia cho (với là số từ của câu ) để câu dài không được lợi. Sau đó họ chạy một thuật toán xếp hạng kiểu PageRank (hệ số tắt dần ). Ý tưởng là bỏ phiếu: một câu quan trọng khi nó giống nhiều câu khác, nhất là giống những câu cũng quan trọng. Trên 567 bản tin của DUC 2002, mỗi bản tóm tắt 100 từ, TextRank không cần dữ liệu có nhãn mà vẫn cạnh tranh được với các hệ thống tốt nhất tham gia đánh giá năm đó.
Tóm tắt trích xuất không bịa câu mới, vì mọi câu đều lấy từ nguồn, nhưng một câu tách khỏi ngữ cảnh vẫn có thể gây hiểu sai. Đổi lại, nó không gộp được ý của hai câu, không bỏ được phần thừa trong một câu dài, và có thể để lại những câu cụt như “Tuyến dài 18 km”.
Tóm tắt tóm lược: viết lại
Phần tiêu đề “Tóm tắt tóm lược: viết lại”Tóm tắt tóm lược dùng một mô hình chuỗi sang chuỗi: encoder đọc văn bản, decoder sinh bản tóm tắt từng token, với một trong các chiến lược giải mã ở trên. Phần khó là dạy mô hình viết lại mà không cần hàng triệu cặp (văn bản, tóm tắt). Cách chung là pre-train bằng một mục tiêu khử nhiễu (denoising), rồi fine-tune trên dữ liệu tóm tắt.
- BART (Lewis và cộng sự, 2020) và T5 (Raffel và cộng sự, 2020) là hai mô hình encoder–decoder pre-train bằng khử nhiễu. Cách chúng làm hỏng văn bản có ở bài Transformer nâng cao. T5 nói tác vụ bằng tiền tố
summarize:. Bản T5 công bố được pre-train trên hỗn hợp nhiều tác vụ, trong đó có tóm tắt tin CNN/Daily Mail, nên gõ tiền tố đó là T5-small tóm tắt được ngay. - PEGASUS (Zhang và cộng sự, 2020) thiết kế mục tiêu pre-train riêng cho tóm tắt, gọi là sinh câu bị bỏ (gap sentences generation). Họ bỏ khỏi văn bản những câu quan trọng, thay mỗi câu bằng một token
[MASK1], rồi bắt decoder viết lại các câu đó từ phần còn lại. Câu quan trọng là câu có ROUGE-1 F1 cao nhất khi so với phần còn lại của văn bản; trong các thí nghiệm so sánh, họ bỏ 30% số câu. Như vậy việc pre-train đã rất giống tóm tắt. Bản lớn nhất đạt kết quả tốt nhất thời đó trên cả 12 bộ dữ liệu tóm tắt họ thử, và chỉ với 1000 cặp fine-tune đã vượt kết quả tốt nhất trước đó trên 6 bộ. - LLM qua prompt. Một mô hình decoder-only đã được tinh chỉnh theo chỉ dẫn tóm tắt được khi bạn viết “Tóm tắt văn bản sau trong hai câu” (bài Prompt Engineering). Không cần fine-tune, độ dài và giọng văn đổi được bằng lời, nhưng chi phí và nguy cơ hallucination vẫn còn đó.
Với tiếng Việt, ViT5 (Phan và cộng sự, 2022) là một T5 pre-train trên văn bản tiếng Việt. Các tác giả báo cáo kết quả tốt nhất thời đó cho tóm tắt tóm lược trên hai bộ Vietnews và WikiLingua.
| Tiêu chí | Trích xuất | Tóm lược |
|---|---|---|
| Đầu ra | Câu nguyên văn của nguồn | Câu mới, có thể dùng từ không có trong nguồn |
| Bịa thông tin | Không bịa câu mới, nhưng câu tách khỏi ngữ cảnh có thể gây hiểu sai | Có thể |
| Văn phong | Có thể rời rạc, câu cụt | Trôi chảy, gộp được ý |
| Cần gì | Không cần huấn luyện (lead, TF-IDF, TextRank) | Mô hình encoder–decoder đã pre-train, hoặc LLM |
Chấm điểm bằng ROUGE
Phần tiêu đề “Chấm điểm bằng ROUGE”Lin (2004) đưa ra ROUGE (Recall-Oriented Understudy for Gisting Evaluation): so bản tóm tắt của máy với một hay nhiều bản tóm tắt tham chiếu do người viết, bằng cách đếm các đơn vị trùng nhau. Gọi bản của máy là , bản tham chiếu là , cả hai là dãy từ.
ROUGE-N đếm các -gram (cụm từ liền nhau) trùng nhau. Với mỗi -gram , gọi và là số lần nó xuất hiện ở mỗi bên. Số lần trùng là:
Lấy để một -gram lặp lại nhiều lần trong bản máy không được tính quá số lần nó có trong tham chiếu. Từ đó có ba con số:
- Precision : trong những gì máy viết, bao nhiêu phần có trong tham chiếu. Viết dài lan man thì thấp.
- Recall : trong tham chiếu, bao nhiêu phần máy viết lại được. Viết quá ngắn thì thấp.
- F1 là trung bình điều hòa của hai số: chỉ cao khi cả hai cùng cao.
ROUGE gốc của Lin là recall (đúng như chữ R trong tên); các bài báo ngày nay thường báo cáo F1. Khi đọc một con số ROUGE, hãy xem nó là loại nào.
ROUGE-L dùng dãy con chung dài nhất (longest common subsequence, LCS): dãy từ xuất hiện ở cả hai bên theo cùng thứ tự, nhưng không cần liền nhau. Gọi độ dài của nó là , thì và , rồi tính F1 như trên. ROUGE-L thưởng cho việc giữ đúng trật tự mà không đòi các từ phải đứng sát nhau. (Lin dùng một dạng F có trọng số ; ở DUC, được đặt rất lớn, nên thực chất chỉ còn recall. Khi bản tóm tắt có nhiều câu, ông dùng “LCS hợp” trên từng câu tham chiếu; ô code bên dưới coi cả bản tóm tắt là một dãy cho gọn.)
Ví dụ tính tay. Tham chiếu “trời hôm nay rất đẹp” (5 từ), bản máy “hôm nay trời đẹp” (4 từ). Mỗi âm tiết là một từ.
- ROUGE-1. Trùng 4 từ: trời, hôm, nay, đẹp. , , .
- ROUGE-2. Tham chiếu có 4 bigram (trời hôm, hôm nay, nay rất, rất đẹp), bản máy có 3 (hôm nay, nay trời, trời đẹp). Chỉ “hôm nay” trùng. , , .
- ROUGE-L. Dãy con chung dài nhất là “hôm nay đẹp”, dài 3 (“trời” đứng ở hai vị trí khác nhau nên không ghép thêm được). , , F1 .
Đổi trật tự từ làm ROUGE-2 và ROUGE-L tụt, còn ROUGE-1 gần như không thấy.
ROUGE không đo được gì
Phần tiêu đề “ROUGE không đo được gì”- Ý nghĩa bị đảo. Tham chiếu “mèo đuổi chuột”, bản máy “chuột đuổi mèo”: ROUGE-1 bằng 1, dù nghĩa ngược hẳn. ROUGE-2 bằng 0, ROUGE-L bằng .
- Từ đồng nghĩa. “khai trương” và “mở” cùng nghĩa nhưng không trùng chữ nào, nên không được điểm.
- Đúng hay sai. Đổi “đầu tiên” thành “thứ hai” chỉ làm mất vài từ trùng; bản tóm tắt sai sự thật vẫn có thể có ROUGE cao hơn một bản viết lại đúng. Bảng ở mục Minh họa cho thấy rõ điều này.
- Cách tách từ. Với tiếng Việt, tách theo âm tiết (“xe”, “buýt”) hay theo từ (“xe_buýt”) cho số khác nhau (bài Tách từ). Chỉ so ROUGE giữa các hệ thống chấm cùng một cách.
ROUGE hữu ích để so nhanh nhiều hệ thống trên cùng một bộ dữ liệu. Lin cho thấy nó tương quan tốt với điểm của người trên dữ liệu DUC. Nó không thay được người đọc khi cần biết bản tóm tắt có đúng không.
Hallucination và tính trung thực
Phần tiêu đề “Hallucination và tính trung thực”Một bản tóm tắt trung thực (faithful) với nguồn khi mọi điều nó nói đều được nguồn ủng hộ. Phần không được nguồn ủng hộ gọi là hallucination (bịa thông tin). Maynez và cộng sự (2020) chia làm hai loại:
- Hallucination nội sinh (intrinsic): dùng thông tin có trong nguồn nhưng bóp méo nó, ví dụ ghép sai tên với chức vụ, hay “đầu tiên” thành “thứ hai”.
- Hallucination ngoại sinh (extrinsic): thêm thông tin không có trong nguồn, ví dụ một năm, một cái tên mà bài báo không hề nhắc.
Họ cho người đọc chấm bản tóm tắt một câu của 500 bản tin trong bộ XSum. Hơn 70% bản tóm tắt của mọi hệ thống có hallucination, phần lớn là ngoại sinh, và hơn 90% chỗ hallucination ngoại sinh là sai chứ không phải kiến thức nền đúng. Đáng chú ý: chính các bản tham chiếu của XSum cũng có 76.9% chứa hallucination, gần hết là ngoại sinh (73.1%), vì đó là câu mở đầu do phóng viên viết, có thêm thông tin không nằm trong bài. Mô hình học từ những cặp như vậy thì học luôn thói “thêm thắt”. Hai kết quả khác: các mô hình đã pre-train vừa có ROUGE cao hơn vừa trung thực hơn, và một thước đo dựa trên suy diễn văn bản (textual entailment: nguồn có suy ra được bản tóm tắt không) khớp với đánh giá trung thực của người tốt hơn ROUGE.
Một số cách giảm hallucination hay dùng trong thực hành:
- Dữ liệu sạch hơn: bỏ những cặp có bản tham chiếu chứa thông tin ngoài nguồn trước khi fine-tune.
- Giải mã thận trọng: beam hay tham lam thay cho lấy mẫu nhiệt độ cao khi cần chính xác.
- Kiểm tra sau khi sinh: dùng một mô hình suy diễn văn bản kiểm từng câu, hay so từng con số và tên riêng với nguồn.
- Lai hai cách: trích các câu chính trước, rồi chỉ viết lại từ những câu đó; hay yêu cầu LLM trích dẫn câu nguồn cho mỗi ý.
Giới hạn
Phần tiêu đề “Giới hạn”- Văn bản rất dài: mô hình encoder–decoder có giới hạn số token đầu vào; phần vượt quá phải cắt bớt hoặc tóm tắt từng đoạn rồi gộp lại.
- Nhiều văn bản một lúc (multi-document summarization): bài này chỉ xét một văn bản.
- Đánh giá: ROUGE không đo được tính trung thực hay độ dễ đọc; các thước đo dựa trên suy diễn văn bản hay chấm bằng LLM cũng có sai số. Hộp thứ hai ở mục Lỗi hay gặp nói thêm.
Minh họa
Phần tiêu đề “Minh họa”Hình dưới là phân phối của token kế tiếp sau “Hôm nay trời rất”, với 10 ứng viên. Bài Sử dụng API văn bản đã dùng hình này để dạy từng thanh trượt (, top-k, top-p). Ở đây, hãy nhìn hai đầu của nó như hai chiến lược giải mã trong bảng ở mục Lý thuyết:
- Kéo về 0 rồi bấm “Lấy 100 mẫu”: “đẹp” có xác suất 1, ra 100 lần “đẹp”. Đó là giải mã tham lam: chạy lại bao nhiêu lần cũng ra một câu.
- Đặt , tắt top-k và top-p, rồi bấm “Lấy 100 mẫu” vài lần: đó là lấy mẫu thuần. “đẹp” chỉ có 0.38, và cả những token cuối bảng như “tối” thỉnh thoảng cũng được rút. Ở từ vựng thật, đuôi này dài hàng chục nghìn token; top-k và top-p nằm giữa hai đầu này, cắt bớt đuôi.
The weather today is very
| Token | Probability | Count | |
|---|---|---|---|
| nice | 0.38 removed | 0 | |
| hot | 0.26 removed | 0 | |
| cold | 0.14 removed | 0 | |
| cool | 0.09 removed | 0 | |
| sunny | 0.06 removed | 0 | |
| humid | 0.03 removed | 0 | |
| clear | 0.02 removed | 0 | |
| windy | 0.01 removed | 0 | |
| wet | 0.01 removed | 0 | |
| dark | 0.00 removed | 0 | |
10 of 10 tokens can still be drawn.
Ten tokens that may follow "The weather today is very", from the most likely to the least likely. The logits are made up for the illustration, not computed by a real model.
Bảng thứ hai cho thấy ROUGE nhìn thấy gì và bỏ sót gì. Tham chiếu là “Đà Nẵng mở tuyến xe buýt điện đầu tiên”; mỗi hàng là một bản máy khác nhau, điểm là F1, mỗi âm tiết là một từ (tính bằng các hàm ROUGE của ô code đầu tiên). Hãy so hàng “viết lại cùng nghĩa” với hai hàng sai sự thật.
| Bản máy | Đúng nghĩa? | ROUGE-1 | ROUGE-2 | ROUGE-L |
|---|---|---|---|---|
| Đà Nẵng mở tuyến xe buýt điện đầu tiên | Đúng, chép y nguyên | 1.000 | 1.000 | 1.000 |
| Tuyến xe buýt điện đầu tiên mở ở Đà Nẵng | Đúng, đảo trật tự | 0.947 | 0.706 | 0.632 |
| Đà Nẵng khai trương tuyến buýt chạy điện đầu tiên | Đúng, viết lại | 0.737 | 0.353 | 0.737 |
| Đà Nẵng mở tuyến xe buýt điện thứ hai | Sai | 0.778 | 0.750 | 0.778 |
| Đà Nẵng đóng tuyến xe buýt điện đầu tiên | Sai, nghĩa ngược | 0.889 | 0.750 | 0.889 |
Câu “đóng tuyến” nói ngược hẳn nguồn mà có ROUGE-1 0.889, cao hơn câu viết lại đúng (0.737). ROUGE đo mức trùng chữ, không đo mức đúng.
Ví dụ code
Phần tiêu đề “Ví dụ code”Code trong bài chạy thử lần cuối tháng 11/2026: ô tóm tắt trích xuất với Python 3.14 trên Pyodide (chỉ dùng thư viện chuẩn), ô T5 với Python 3.14, transformers 5.22 và PyTorch 2.14 trên CPU. Ô thứ nhất chạy ngay trên trang. Ô thứ hai cần PyTorch và tải mô hình từ Hugging Face Hub, nên chạy trên máy bạn.
Tóm tắt trích xuất và ROUGE
Phần tiêu đề “Tóm tắt trích xuất và ROUGE”Ô dưới làm lại hai phần của mục Lý thuyết trên bản tin xe buýt điện (bảy câu, tự viết cho bài này). Phần đầu chấm mỗi câu bằng cosine giữa vectơ TF-IDF của câu và vectơ của cả bài, rồi giữ hai câu điểm cao nhất theo thứ tự xuất hiện. Phần sau cài ROUGE-1, ROUGE-2, ROUGE-L (F1) từ đầu, rồi so hai bản tóm tắt với một bản tham chiếu tự viết: bản TF-IDF, và bản “lead-2” lấy hai câu đầu.
Tóm tắt trích xuất bằng TF-IDF và ROUGE
# Tóm tắt trích xuất bằng TF-IDF, rồi chấm bằng ROUGE-1, ROUGE-2, ROUGE-Limport mathimport refrom collections import Counter
text = ( "Sáng 3/11, Đà Nẵng đưa vào hoạt động tuyến xe buýt điện đầu tiên, " "nối sân bay với biển Mỹ Khê. Tuyến dài 18 km, có 12 xe, chạy từ 5 giờ " "sáng đến 10 giờ tối. Giá vé là 8 nghìn đồng một lượt, học sinh được " "giảm một nửa. Trong tháng đầu, thành phố miễn phí vé xe buýt điện cho " "mọi hành khách. Mỗi xe chạy được 250 km sau một lần sạc. Nhiều người " "dân khen xe chạy êm và không có khói. Thành phố dự kiến mở thêm ba " "tuyến xe buýt điện vào năm sau.")ref = ("Đà Nẵng mở tuyến xe buýt điện đầu tiên nối sân bay với biển Mỹ Khê. " "Tháng đầu miễn phí vé, năm sau mở thêm ba tuyến.")
def words(s): # chữ thường, mỗi âm tiết là một từ return re.findall(r"\w+", s.lower())
sents = re.split(r"(?<=\.)\s+", text)toks = [words(s) for s in sents]N = len(sents)df = Counter(w for t in toks for w in set(t)) # số câu chứa mỗi từidf = {w: math.log((1 + N) / (1 + df[w])) + 1 for w in df}vecs = [{w: c * idf[w] for w, c in Counter(t).items()} for t in toks]center = sum(map(Counter, vecs), Counter()) # vectơ của cả văn bản
def cos(a, b): dot = sum(x * b.get(w, 0) for w, x in a.items()) return dot / (math.hypot(*a.values()) * math.hypot(*b.values()))
score = [cos(v, center) for v in vecs]print("scores:", " ".join(f"{s:.3f}" for s in score))top = sorted(sorted(range(N), key=lambda i: -score[i])[:2]) # giữ thứ tựprint("picked sentences:", [i + 1 for i in top])
def ngrams(t, n): return Counter(tuple(t[i:i + n]) for i in range(len(t) - n + 1))
def f1(hit, n_cand, n_ref): # precision, recall rồi trung bình điều hòa p, r = hit / n_cand, hit / n_ref return 0.0 if hit == 0 else 2 * p * r / (p + r)
def rouge_n(c, r, n): # & lấy số lần trùng nhỏ hơn của hai bên hit = sum((ngrams(c, n) & ngrams(r, n)).values()) return f1(hit, len(c) - n + 1, len(r) - n + 1)
def rouge_l(c, r): # độ dài LCS bằng quy hoạch động L = [[0] * (len(r) + 1) for _ in range(len(c) + 1)] for i, a in enumerate(c): for j, b in enumerate(r): L[i + 1][j + 1] = (L[i][j] + 1 if a == b else max(L[i][j + 1], L[i + 1][j])) return f1(L[-1][-1], len(c), len(r))
for name, idx in [("tf-idf", top), ("lead-2", [0, 1])]: c, r = words(" ".join(sents[i] for i in idx)), words(ref) print(f"{name}: R1 {rouge_n(c, r, 1):.3f} R2 {rouge_n(c, r, 2):.3f}" f" RL {rouge_l(c, r):.3f} ({len(c)} words)")The first run downloads Python, about 10 MB.
Đọc kết quả:
- Điểm bảy câu là 0.520, 0.473, 0.405, 0.466, 0.431, 0.360, 0.484. Câu 1 (mở tuyến đầu tiên) và câu 7 (năm sau mở thêm ba tuyến) cao nhất: cả hai nhắc “tuyến xe buýt điện”, cụm từ của cả bài. Câu 6 (người dân khen xe êm) thấp nhất, vì phần lớn từ của nó không có ở câu khác.
- Bản TF-IDF chọn câu 1 và 7, được ROUGE-1 0.667, ROUGE-2 0.557, ROUGE-L 0.603. Bản lead-2 chỉ được 0.492, 0.413, 0.492: câu 2 nói độ dài tuyến và giờ chạy, mà bản tham chiếu không nhắc.
- Tính lại ROUGE-1 của bản TF-IDF: bản máy có 36 từ, tham chiếu 27 từ, trùng 21. , , F1 . Precision thấp hơn recall vì hai câu chép nguyên văn còn kéo theo “Sáng 3/11”, “đưa vào hoạt động”, “dự kiến”.
- Ý “tháng đầu miễn phí vé” trong tham chiếu nằm ở câu 4 (0.466), xếp thứ ba nên bị bỏ. Muốn có nó thì phải giữ ba câu, hoặc viết lại.
Thử đổi [:2] thành [:3] ở dòng chọn câu: câu 4 vào bản tóm tắt. Hay thử thay điểm cosine bằng trung bình idf của các từ trong câu, rồi xem câu nào được chọn.
Tóm tắt bằng T5-small, ba cách giải mã
Phần tiêu đề “Tóm tắt bằng T5-small, ba cách giải mã”File dưới tóm tắt một bản tin tiếng Anh tự viết (mưa lớn ở Huế) bằng google-t5/t5-small (Raffel và cộng sự, 2020), khoảng 60 triệu tham số. Code gọi thẳng AutoTokenizer và AutoModelForSeq2SeqLM.generate, để bạn thấy rõ các tham số giải mã. Cùng một mô hình, cùng một đầu vào, ba cấu hình: tham lam, beam , và lấy mẫu top-p 0.9 (đặt top_k=0, vì khi lấy mẫu generate mặc định còn bật top-k 50). Trước mỗi lần sinh, set_seed(0) cố định bộ sinh số ngẫu nhiên.
Run on your machine
Tóm tắt bằng T5-small: tham lam, beam, top-p
- Install
pip install transformers torch- Hardware
- CPU là đủ. Lần chạy đầu tải khoảng 244 MB (trọng số mô hình 242 MB và tokenizer). Khi đã có mô hình trong máy, cả file chạy khoảng 10–20 giây trên CPU; máy bận có thể mất vài phút
# Tóm tắt một đoạn tin tiếng Anh bằng T5-small với ba cách giải mã.from transformers import AutoModelForSeq2SeqLM, AutoTokenizer, set_seed
NAME = "google-t5/t5-small"tok = AutoTokenizer.from_pretrained(NAME)model = AutoModelForSeq2SeqLM.from_pretrained(NAME)
text = ( "Heavy rain hit the central city of Hue on Monday, flooding more than " "2,000 homes and closing 40 schools. Local officials said the river " "rose 1.5 metres overnight, the highest level since 2020. About 3,000 " "people were moved to safer areas, and no deaths have been reported. " "Forecasters expect the rain to continue until Wednesday, and the city " "has asked residents to avoid low-lying roads.")# T5 biết cần làm việc gì nhờ tiền tố tác vụ ở đầu đầu vàoinputs = tok("summarize: " + text, return_tensors="pt")print("input tokens:", inputs["input_ids"].shape[1])
settings = { "greedy": dict(num_beams=1, do_sample=False), "beam 4": dict(num_beams=4, do_sample=False), # top_k=0 tắt top-k (generate mặc định dùng top_k=50 khi lấy mẫu) "top-p 0.9": dict(do_sample=True, top_p=0.9, top_k=0),}for name, kwargs in settings.items(): set_seed(0) # cố định seed để lần lấy mẫu lặp lại được out = model.generate(**inputs, max_new_tokens=60, **kwargs) summary = tok.decode(out[0], skip_special_tokens=True) print(f"[{name}] {summary}")Sample output
From one real run. A model gives a different answer each time.
input tokens: 83[greedy] heavy rain hits central city of Hue on Monday, flooding more than 2,000 homes and closing 40 schools. the river rose 1.5 metres overnight, the highest level since 2020.[beam 4] heavy rain hit central city of Hue on Monday, flooding more than 2,000 homes and closing 40 schools. the river rose 1.5 metres overnight, the highest level since 2020. no deaths have been reported.[top-p 0.9] heavy rain hit the central city of Hue on monday. about 3,000 people are moved to safer areas, and no deaths have been reported. the river rose 1.5 metres overnight, the highest level since 2020.Đọc kết quả:
- Cả ba bản gần như là trích xuất: phần lớn câu chép từ nguồn, chỉ bỏ bớt vài từ (“Local officials said”). Bài báo T5 có ghi rằng trên CNN/Daily Mail, dữ liệu tóm tắt mà T5 đã học, các cách thuần trích xuất cũng làm tốt. Có lẽ vì vậy mô hình học được rằng chép là an toàn. Chữ thường ở đầu câu (“the river”, “monday”) có lẽ cũng là dấu vết của dữ liệu đó, vốn đã được đổi về chữ thường.
- Tham lam dừng sau hai ý và đổi “hit” thành “hits”. Beam 4 tìm được một chuỗi dài hơn, thêm “no deaths have been reported”, một ý quan trọng. Hai bản này lần nào chạy cũng giống nhau.
- Top-p 0.9 chọn khác: thêm 3 000 người được sơ tán, bỏ số nhà bị ngập, và đổi “were moved” thành “are moved”. Không có chi tiết nào bịa ra ở đây, nhưng mỗi lần đổi seed là một bản khác. Với tóm tắt, sự đa dạng này ít khi là thứ bạn cần.
Seed cố định nên trên cùng máy, cùng phiên bản thư viện, kết quả lặp lại được. Ở máy hay phiên bản khác, dòng top-p có thể khác. T5-small chỉ được pre-train trên tiếng Anh, nên đừng đưa bản tin tiếng Việt vào nó; với tiếng Việt, hãy tìm hiểu ViT5.
Lỗi hay gặp
Phần tiêu đề “Lỗi hay gặp”Kiểm tra nhanh
Phần tiêu đề “Kiểm tra nhanh”Tóm tắt và đọc thêm
Phần tiêu đề “Tóm tắt và đọc thêm”Ý chính:
- Sinh văn bản là vòng lặp tự hồi quy: mô hình cho phân phối của token kế tiếp, chiến lược giải mã chọn token. Tham lam và beam search ổn định nhưng dễ lặp khi viết dài (văn bản thoái hóa); lấy mẫu thuần đa dạng nhưng dễ lạc vào đuôi; top-k và top-p cắt đuôi, top-p theo độ chắc của mô hình. Phạt lặp chia logit dương (nhân logit âm) của token đã xuất hiện cho .
- Tóm tắt trích xuất chọn câu nguyên văn (lead, cosine TF-IDF với vectơ cả bài, TextRank): không bịa được, nhưng có thể rời rạc. Tóm tắt tóm lược viết lại bằng encoder–decoder đã pre-train (BART, T5, PEGASUS với mục tiêu sinh câu bị bỏ) hay bằng LLM qua prompt: trôi chảy, nhưng có thể có hallucination.
- ROUGE-N đếm -gram trùng (lấy hai bên), ROUGE-L dùng dãy con chung dài nhất; chia cho bản máy, chia cho tham chiếu, F1 là trung bình điều hòa. ROUGE không thấy đồng nghĩa và không đo đúng sai.
- Hallucination nội sinh bóp méo thông tin của nguồn, hallucination ngoại sinh thêm thông tin nguồn không có. Maynez và cộng sự thấy hơn 70% bản tóm tắt một câu trên XSum có hallucination. Giảm bằng dữ liệu sạch, giải mã thận trọng, kiểm tra bằng suy diễn văn bản, và cách lai trích xuất rồi viết lại.
Đọc thêm:
- Holtzman, A., Buys, J., Du, L., Forbes, M., Choi, Y. (2020). The Curious Case of Neural Text Degeneration, ICLR 2020, mục 1, 2 và 5. Vì sao giải mã theo xác suất cao nhất làm văn lặp, và top-p sửa điều đó thế nào; có bảng số đo độ lặp của từng cách giải mã.
- Lin, C.-Y. (2004). ROUGE: A Package for Automatic Evaluation of Summaries, Text Summarization Branches Out, mục 2 và 3. Định nghĩa gốc của ROUGE-N và ROUGE-L. Bài báo gọi bản tham chiếu là và bản máy là , chỗ bài này viết và .
- Maynez, J., Narayan, S., Bohnet, B., McDonald, R. (2020). On Faithfulness and Factuality in Abstractive Summarization, ACL 2020, mục 2 và 3. Hallucination nội sinh và ngoại sinh, kèm số liệu từ người chấm.
- Zhang, J., Zhao, Y., Saleh, M., Liu, P. J. (2020). PEGASUS: Pre-training with Extracted Gap-sentences for Abstractive Summarization, ICML 2020, mục 3. Mục tiêu sinh câu bị bỏ và các cách chọn câu quan trọng.
- Phan, L., Tran, H., Nguyen, H., Trinh, T. H. (2022). ViT5: Pretrained Text-to-Text Transformer for Vietnamese Language Generation, NAACL 2022 Student Research Workshop, trang 136–142. T5 cho tiếng Việt, có kết quả tóm tắt tóm lược trên Vietnews và WikiLingua.
- Hugging Face (2026). Generation strategies, tài liệu Transformers 5.22.1. Các cách giải mã cơ bản và tham số
num_beams,do_sampledùng trong ô T5. Danh sách đủ tham số (top_k,top_p,repetition_penalty,no_repeat_ngram_size…) có ở trang Generation, mụcGenerationConfig.
Your browser is blocking storage. Your progress will be lost when you reload the page.
Content licensed under CC BY-NC-SA 4.0. Code under the MIT license.About