Trọng tâm: NER, token-level labels và cross-lingual transfer.
Thời gian: 45 phút đọc, 15 phút viết lại.
Mục tiêu cần hiểu
Hiểu Named Entity Recognition là bài toán token-level khác gì text classification.
Biết multilingual Transformer hỗ trợ cross-lingual transfer như thế nào.
Nắm pipeline tokenizer gồm normalization, pretokenization, tokenizer model và postprocessing.
Hiểu cách căn chỉnh nhãn NER khi một từ bị tách thành nhiều subword.
Câu hỏi dẫn đường
NER khác text classification ở điểm nào?
Tokenizer tách subword thì nhãn token-level xử lý ra sao?
Cross-lingual transfer hoạt động nhờ điều gì?
Ghi chú trong khi đọc
Tokenizer Pipeline biến text thô thành input mà model xử lý được. Pipeline nên nhớ theo thứ tự: normalization → pretokenization → tokenizer model → postprocessing.
Normalization chuẩn hóa text trước khi cắt token, ví dụ xử lý Unicode, lowercasing, strip accent hoặc chuẩn hóa khoảng trắng. Bước này quyết định những biến thể bề mặt nào được xem là giống nhau.
Pretokenization chia text thành các đơn vị sơ bộ như word, punctuation hoặc khoảng trắng. Với một số tokenizer đa ngôn ngữ, bước này ít phụ thuộc vào khoảng trắng hơn để hỗ trợ nhiều hệ chữ.
Tokenizer model học/cài đặt cách tách các đơn vị sơ bộ thành token hoặc subword, ví dụ BPE, WordPiece, Unigram/SentencePiece. Đây là nơi một từ có thể bị tách thành nhiều subword.
Postprocessing thêm các special tokens và tạo cấu trúc input cuối cùng, ví dụ [CLS], [SEP], attention mask, token type IDs hoặc offsets. Với NER, offsets rất quan trọng để map token/subword về span gốc.
Multilingual Transformer là Transformer được pretrain trên nhiều ngôn ngữ, thường dùng chung kiến trúc và tokenizer/subword vocabulary để tạo representation cho các ngôn ngữ khác nhau trong cùng một không gian.
Điểm quan trọng không phải model lưu từng ngôn ngữ như các “module” riêng, mà nó học các pattern có thể chia sẻ: tên riêng, cấu trúc câu, ngữ cảnh quanh entity, và quan hệ giữa token.
Với NER đa ngôn ngữ, multilingual Transformer giúp giảm nhu cầu tạo dataset gán nhãn riêng cho từng ngôn ngữ. Mình có thể fine-tune trên ngôn ngữ có dữ liệu tốt hơn, rồi kiểm tra khả năng transfer sang ngôn ngữ ít tài nguyên.
Trade-off: dùng chung capacity cho nhiều ngôn ngữ nên ngôn ngữ có ít dữ liệu pretraining hoặc khác script/domain có thể bị yếu hơn. Tokenizer cũng có thể chia một từ thành nhiều subword hơn, làm alignment nhãn NER khó hơn.
SentencePiece tokenizer xử lý text như chuỗi ký tự thô và học subword trực tiếp từ dữ liệu, nên không cần giả định trước về khoảng trắng như tokenizer tách từ truyền thống.
Với ngôn ngữ đa dạng, đây là lợi thế lớn: nhiều ngôn ngữ không tách từ bằng dấu cách rõ ràng, hoặc có morphology phong phú. SentencePiece giúp tokenizer dùng chung được cho multilingual model.
Trong NER, vấn đề thực tế là một word-level label có thể bị trải ra nhiều subword. Khi đó cần align nhãn: thường gán label cho subword đầu tiên và ignore các subword còn lại, hoặc propagate label tùy cách train/evaluate.
Tokenizing Texts for NER khác tokenizing cho text classification ở chỗ mình phải giữ quan hệ giữa token/subword và word/entity label gốc.
Khi dataset đã tách sẵn câu thành list từ, nên gọi tokenizer với is_split_into_words=True để tokenizer hiểu input là pre-tokenized words, không phải một string thô cần tự split lại.
Sau tokenization, dùng word_ids() để biết mỗi subword thuộc về word nào. Special tokens như <s>, </s>, [CLS], [SEP] thường có word_id = None.
Chiến lược phổ biến: label cho subword đầu tiên của mỗi word, còn special tokens và subword phụ đặt -100 để loss bỏ qua. Cách này tránh việc một word dài có nhiều subword bị tính loss nhiều lần.
Nếu muốn label mọi subword, cần cẩn thận với BIO tags: subword đầu giữ B-..., các subword sau thường nên đổi thành I-... để không tạo nhiều entity bắt đầu giả.
Sau khi tokenize, phải kiểm tra nhanh vài ví dụ bằng cách in tokens, word_ids, labels đã align. Lỗi alignment thường không hiện ngay ở code, nhưng làm model học sai ranh giới entity.
Transformers Model Class trong Hugging Face thường có hai phần: body là pretrained Transformer tạo hidden states, còn head là tầng task-specific biến hidden states thành logits.
Với token classification/NER, body như XLMRobertaModel trả về last_hidden_state có shape gần như [batch_size, sequence_length, hidden_size]. Head áp dụng lên từng token để tạo logits [batch_size, sequence_length, num_labels].
AutoModel thường load body/base model; AutoModelForTokenClassification load body kèm token classification head. Khi số nhãn NER thay đổi, head mới thường được khởi tạo lại theo num_labels, id2label, label2id.
Khi custom model class, cần giữ ba mảnh rõ ràng: config mô tả kiến trúc/labels, forward() định nghĩa dòng dữ liệu và loss, output chuẩn như TokenClassifierOutput chứa loss, logits, hidden_states, attentions.
Mental model cho NER: input_ids -> Transformer body -> token hidden states -> dropout + linear head -> logits từng token -> loss bỏ qua label -100.
Custom Model for Token Classification là khi mình tự định nghĩa model class thay vì dùng trực tiếp AutoModelForTokenClassification, thường để thay head, thêm logic loss, hoặc kiểm soát output.
Các bước chính: kế thừa pretrained model class phù hợp, khởi tạo body bằng checkpoint/base architecture, thêm dropout + linear classifier, viết forward() nhận input_ids, attention_mask, labels, rồi trả output chuẩn.
Trong forward(), cần lấy hidden states từ body, đưa qua head để có logits, sau đó tính cross-entropy loss nếu có labels. Với NER, phải ignore label -100 để không tính loss cho special tokens/subword phụ.
Điều quan trọng khi custom: shape phải khớp. logits nên là [batch_size, sequence_length, num_labels], còn labels là [batch_size, sequence_length]. Nếu lệch sequence length, lỗi thường nằm ở tokenizer/label alignment.
Custom model vẫn nên dùng config.num_labels, config.id2label, config.label2id để Trainer, pipeline và saved checkpoint hiểu đúng nhãn.
Loading a Custom Model là bước đưa custom model class vào đúng pretrained checkpoint/config thay vì khởi tạo model rỗng. Ý chính: load config, set label mapping, rồi gọi from_pretrained() trên class custom.
Khi gọi from_pretrained(checkpoint, config=config), Hugging Face sẽ nạp weights có tên khớp vào body. Các layer mới như token classification head có thể chưa có weights trong checkpoint nên được khởi tạo mới.
Cảnh báo kiểu “some weights were not initialized” là bình thường nếu mình thêm head mới cho task NER. Điều cần kiểm tra là body weights đã load đúng, còn head mới sẽ học trong fine-tuning.
Nếu muốn dùng lại model custom sau khi train, cần lưu bằng save_pretrained() cùng tokenizer. Khi load lại, code định nghĩa class custom vẫn phải tồn tại, hoặc phải đăng ký custom architecture/auto class đúng cách.
Mental model: checkpoint + config + custom class -> from_pretrained() -> body có pretrained weights + head theo num_labels -> fine-tune/evaluate.
Performance Measures for NER không nên chỉ nhìn token accuracy, vì nhãn O thường chiếm đa số và có thể làm metric đẹp giả.
Với NER, precision/recall/F1 nên tính ở mức entity span: model đúng khi nhận ra đúng ranh giới thực thể và đúng entity type, ví dụ PER, ORG, LOC.
Precision trả lời: trong các entity model dự đoán, bao nhiêu entity là đúng. Precision thấp nghĩa là model hay nhận nhầm entity.
Recall trả lời: trong các entity thật, model tìm được bao nhiêu entity. Recall thấp nghĩa là model bỏ sót nhiều entity.
F1 cân bằng precision và recall, hữu ích khi cần một số tổng để so sánh model/checkpoint, nhưng vẫn nên xem per-entity-type F1.
Với multilingual NER, cần xem metric theo từng ngôn ngữ và từng entity type. Điểm trung bình có thể che việc model tốt ở tiếng Anh nhưng yếu ở tiếng Việt hoặc yếu riêng với ORG.
Khi dùng seqeval, cần convert prediction IDs và label IDs về label strings, bỏ qua vị trí -100, rồi tính precision/recall/F1/accuracy theo sequence/entity.
Fine-Tuning XLM-RoBERTa cho NER là workflow lấy XLM-R pretrained multilingual body, thêm token classification head, rồi train trên dataset NER đã tokenize và align labels.
Các bước chính: chuẩn bị label mapping, load tokenizer/model checkpoint XLM-R, tokenize dataset với is_split_into_words=True, align labels bằng word_ids(), tạo DataCollatorForTokenClassification, định nghĩa compute_metrics bằng seqeval, rồi fine-tune bằng Trainer.
Khi fine-tune, TrainingArguments nên kiểm soát learning_rate, num_train_epochs, weight_decay, batch size, evaluation strategy, logging và save strategy. Với model lớn như XLM-R, batch size/VRAM là điểm cần để ý.
Head token classification mới học mapping từ token hidden states sang nhãn NER; body XLM-R có thể cũng được cập nhật để representation phù hợp hơn với entity boundaries và target dataset.
Sau khi fine-tune, không chỉ nhìn validation F1 tổng. Cần xem per-language/per-entity-type F1, thử vài câu thật, và so sánh với zero-shot transfer nếu mục tiêu là multilingual NER.
Error Analysis for NER là bước đọc các prediction sai sau khi có metric, để biết model đang lỗi vì ranh giới entity, sai entity type, bỏ sót entity, hallucinate entity, hay lỗi do tokenizer/label alignment.
Với NER, nên gom lỗi theo nhóm: PER bị nhầm ORG, entity bị thiếu token cuối, entity nhiều token bị cắt sai, tên riêng hiếm bị tách subword quá nhiều, hoặc model đoán quá nhiều O.
Với multilingual NER, cần xem lỗi theo từng ngôn ngữ. Nếu model fine-tune trên tiếng Anh nhưng yếu ở tiếng Việt, có thể lỗi đến từ cross-lingual transfer, tokenizer, domain hoặc dữ liệu target ít đại diện.
Nên inspect ví dụ dạng bảng: token, gold label, predicted label, word_id/offset. Bảng này giúp phát hiện lỗi alignment -100 hoặc lỗi BIO tags nhanh hơn chỉ nhìn F1.
Error analysis nên dẫn đến hành động cụ thể: sửa label mapping/alignment, thêm dữ liệu cho entity type yếu, đổi threshold/postprocessing, kiểm tra domain mismatch, hoặc đánh giá riêng theo ngôn ngữ.
Cross-Lingual Transfer là khả năng dùng tri thức học được từ một ngôn ngữ nguồn để cải thiện hoặc thực hiện task ở ngôn ngữ đích. Trong chapter này, task chính là NER đa ngôn ngữ.
Với XLM-R, cơ sở của cross-lingual transfer là shared tokenizer, shared model parameters và multilingual pretraining tạo representation space tương đối chung giữa các ngôn ngữ.
Có hai tình huống dễ nhớ: zero-shot transfer là fine-tune trên source language rồi predict trực tiếp trên target language; few-shot/target adaptation là có thêm một ít dữ liệu target language để fine-tune hoặc evaluate tốt hơn.
Cross-lingual transfer thành công khi entity patterns, domain, label guideline và representation giữa source/target đủ gần. Nó thất bại khi tokenizer tách target language quá kém, domain lệch, entity surface form khác nhiều, hoặc source language không đại diện.
Với NER, không nên chỉ hỏi “model có transfer được không”; nên hỏi “transfer tốt cho entity type nào, ngôn ngữ nào, và lỗi là boundary, type hay missing entity?”
zero-shot learning trong chapter này xuất hiện ở ngữ cảnh multilingual NER: train hoặc fine-tune model trên một ngôn ngữ có nhãn, rồi đem áp dụng trực tiếp cho ngôn ngữ khác chưa có nhãn task-specific.
Điều kiện để làm được: model đa ngôn ngữ như XLM-R đã học không gian biểu diễn chung giữa nhiều ngôn ngữ trong pretraining, nên entity pattern và token representation có thể phần nào “dịch chuyển” qua ngôn ngữ mới.
Đây là một dạng Transfer Learning đặc biệt: không chỉ transfer từ pretraining sang downstream task, mà còn transfer từ source language sang target language mà không fine-tune trên target language.
Trong NER, zero-shot transfer hữu ích khi target language ít dữ liệu gán nhãn. Ví dụ: có dataset NER tiếng Anh, fine-tune XLM-R trên tiếng Anh, rồi thử nhận diện PER/ORG/LOC trên tiếng Việt.
Rủi ro: nếu tokenizer xử lý target language kém, entity surface form khác nhiều, hoặc domain khác source language, performance có thể giảm mạnh. Vì vậy vẫn cần error analysis theo từng loại entity và từng ngôn ngữ.
Viết lại bằng lời của tôi
Chapter 04 biến NER từ một khái niệm đơn giản “gán nhãn từng token” thành một workflow đầy đủ: tokenizer phải giữ được mapping từ text gốc sang subword, model phải có token classification head, metric phải tính đúng ở mức entity, và sau cùng phải đọc lỗi mẫu thay vì chỉ nhìn F1.
Với NER, phần khó nhất không nằm ở việc gọi model mà nằm ở alignment. Dữ liệu thường gắn nhãn theo word/entity span, còn XLM-R nhận input theo subword. Vì vậy word_ids(), offsets và label -100 là các chi tiết rất quan trọng: nếu align sai, model vẫn train được nhưng học sai.
Multilingual Transformer như XLM-R hữu ích vì nó cho nhiều ngôn ngữ dùng chung tokenizer, parameters và representation space. Nhờ đó mình có thể fine-tune trên một ngôn ngữ có nhãn rồi thử transfer sang ngôn ngữ khác.
Cross-Lingual Transfer không phải phép màu. Nó phụ thuộc vào độ gần giữa source/target language, domain, label guideline, tokenizer behavior và mức độ ngôn ngữ đó xuất hiện trong pretraining.
Zero-shot transfer giống như mượn năng lực đã học ở ngôn ngữ A để làm bài toán ở ngôn ngữ B mà chưa dạy riêng cho B. Điểm mấu chốt không phải model “biết dịch” hoàn hảo, mà là multilingual Transformer đã ép nhiều ngôn ngữ nằm gần nhau trong cùng một representation space.
Với NER, mình nên nhớ câu hỏi: model nhận ra “đây là tên người/tổ chức/địa điểm” nhờ pattern ngữ nghĩa và ngữ cảnh chung đến mức nào, và thất bại ở đâu khi hình thái/ngữ cảnh của ngôn ngữ mới khác nguồn train.
Khi fine-tune XLM-RoBERTa, workflow cần nhớ là: dataset → tokenizer + label alignment → model body/head →Trainer→seqeval→ error analysis → quyết định sửa dữ liệu, training setup hay transfer setup.
Metric tốt cần đọc đúng: token accuracy dễ đẹp giả vì nhãn O nhiều. Entity-level precision/recall/F1 mới trả lời model nhận đúng thực thể đến đâu. Nhưng F1 tổng vẫn chưa đủ, nhất là với multilingual NER; cần xem theo language và entity type.
Error analysis là bước biến metric thành hành động. Nếu sai boundary thì kiểm tra alignment/BIO; nếu bỏ sót entity thì xem recall và dữ liệu; nếu sai ở target language thì kiểm tra cross-lingual transfer, tokenizer và domain.
Điều chưa rõ
Zero-shot transfer là một trường hợp của Cross-Lingual Transfer: không dùng nhãn target language khi fine-tune. Nếu có thêm target-language labels để fine-tune/adapt, đó không còn là zero-shot thuần nữa mà gần với few-shot hoặc target adaptation.
Khi đánh giá NER đa ngôn ngữ, nên xem cả hai chiều: trước hết xem F1 theo từng ngôn ngữ để biết transfer có lệch language nào không, sau đó xem F1 theo entity type trong từng ngôn ngữ để biết PER, ORG, LOC lỗi khác nhau thế nào.
Cần review thêm bằng ví dụ thật: lấy vài câu tiếng Việt, in token/gold/prediction/word_id để kiểm tra model sai vì entity boundary, type hay tokenizer alignment.
Việc cần làm
Đọc trang 119-149
Viết lại quy trình xử lý nhãn NER
Review lại Tokenizer Pipeline và 4 bước normalization → pretokenization → tokenizer model → postprocessing