Hãy tưởng tượng một màn hình back-office hiển thị nhiều hồ sơ dường như thuộc về cùng một tài liệu. Tiêu đề khá giống nhau, mã tham chiếu không phải lúc nào cũng được điền với độ tin cậy như nhau, và một số hồ sơ tương ứng với các phiên bản khác nhau. Bạn muốn đề xuất việc gom chúng lại để dễ điều hướng hơn. Nhưng chắc chắn không phải xóa một phiên bản hữu ích hay gộp hai tài liệu riêng biệt chỉ vì chúng có vài từ giống nhau.
Đó là vấn đề chúng ta sẽ khám phá với bốn hồ sơ giả định. A-17 và B-92 mô tả tài liệu logic VC-204; D-40 là phiên bản 2 của nó. C-11 mô tả VC-205, với tiêu đề gần như giống hệt. Việc gom nhóm được mong đợi là giữ A-17, B-92 và D-40 cùng nhau, đồng thời để C-11 riêng.
Từ logic rất quan trọng: ở đây nó chỉ danh tính tài liệu mà nhiều hồ sơ và phiên bản cùng đề cập đến. Nó không có nghĩa các tệp của chúng giống hệt nhau từng byte. Đối chiếu hồ sơ không phải là gộp các tệp của chúng. Trong hướng dẫn này, từng tệp và từng phiên bản đều được giữ lại; chương trình đưa ra một đề xuất mà không cập nhật GED, hệ thống quản lý tài liệu điện tử.
Chúng ta sẽ xây dựng chuỗi sau: hồ sơ → cặp ứng viên → điểm CamemBERT → quyết định theo ngưỡng → nhóm được đề xuất và kiểm tra. Một bộ lọc đầu tiên giảm số lượng so sánh. Sau đó, một mô hình học cách xem xét hai hồ sơ cùng lúc. Cuối cùng, mã nguồn kiểm tra để bảo đảm việc gom nhóm không vượt qua một xung đột hành chính đáng tin cậy.
Mục tiêu của lộ trình là hiểu từng phần can thiệp ở đâu, rồi đo lường đóng góp của nó. Một bộ phân loại xuất sắc không tự động tìm lại các ứng viên mà bộ lọc đã bỏ sót. Và chỉ vài cặp sai cũng có thể đủ để tạo thành một nhóm quá rộng.
Đo lường riêng từng giai đoạn
Blocking: chọn các phép so sánh, chưa chọn câu trả lời
So sánh từng cặp tất cả hồ sơ có vẻ đơn giản. Nhưng với n hồ sơ, cần xem xét n × (n - 1) / 2 cặp khác biệt: không so sánh một hồ sơ với chính nó và không đếm A/B và B/A hai lần.
Chỉ với 648 hồ sơ, đã có 209 628 cặp. Blocking là bước tiền chọn: nó giữ lại một tập nhỏ hơn các cặp đáng được xem xét kỹ. Với một lập trình viên web, hãy hình dung đây là lần chọn ứng viên đầu tiên trước một xử lý tốn kém, chứ không phải quyết định cuối cùng về danh tính.
Ví dụ sư phạm, khác với các quy tắc trong ZIP: nếu chỉ so sánh những hồ sơ có mã tham chiếu hoàn toàn giống nhau, một mã bị thiếu hoặc nhập sai có thể ngăn hai hồ sơ của cùng tài liệu gặp nhau. Khi đó, mô hình đặt sau bộ lọc sẽ không có cơ hội nhận ra chúng. Tài liệu Python Record Linkage Toolkit về lập chỉ mục trình bày nguyên tắc giảm số cặp này; tài liệu đó không mô tả các quy tắc riêng của dự án chúng ta.
Trong lộ trình r001, việc gom nhóm có ràng buộc có thể yêu cầu thêm điểm số để kiểm tra một phép hợp nhất dự kiến. Vì vậy, chúng ta sẽ phân biệt các ứng viên của bộ lọc đầu tiên với các phép so sánh kiểm tra được thêm trong khi gom nhóm. Những phép sau không phải là một lần tìm kiếm toàn diện mới giữa mọi hồ sơ.
Một mô hình đọc hai hồ sơ cùng lúc
CamemBERT là một mô hình ngôn ngữ được tiền huấn luyện bằng tiếng Pháp. Một tokenizer chia văn bản thành các đơn vị gọi là token, đôi khi nhỏ hơn một từ. Mô hình biến các đơn vị này thành embedding: các vector, tức các danh sách số, biểu diễn văn bản có xét đến ngữ cảnh. Tài liệu chính thức của CamemBERT mô tả, trong đó có cách dùng mô hình để phân loại văn bản và các cặp chuỗi.
Ở đây, chúng ta dùng một cross-encoder: hai hồ sơ được đưa cùng lúc vào mô hình, mô hình tạo ra một điểm cho cặp của chúng. Nhờ vậy, văn bản của hồ sơ thứ nhất có thể được liên hệ với văn bản của hồ sơ thứ hai trong lúc tính toán. Đây không phải cùng một thao tác với việc tính một vector độc lập cho mỗi hồ sơ, lưu nó, rồi so sánh các vector đó.
Lợi ích cần có là xem xét chung các trường dữ liệu. Đổi lại là chi phí: một cặp mới đòi hỏi một lần tính mô hình mới. Tài liệu Sentence Transformers về cross-encoder giải thích sự khác biệt này. Tài liệu đó giúp hiểu kiến trúc ở đây, không nhằm thêm thư viện hay mô hình khác vào lộ trình.
Việc học là có giám sát: nhãn đích bằng 1 khi hai hồ sơ mô tả cùng một tài liệu logic, bằng 0 nếu không. Vì thế, một cặp dương không nhất thiết có nghĩa là « hai bản sao giống hệt của cùng một tệp ». Phiên bản 2 của một tài liệu có thể thuộc cùng nhóm với phiên bản trước đó.
Tập dữ liệu tổng hợp chứa 4 320 hồ sơ cho 1 440 tài liệu logic, trong đó 648 hồ sơ thuộc tập kiểm tra. Các danh tính tham chiếu, thường gọi là gold, cho biết những cặp và nhóm nào được kỳ vọng. Chúng dùng để học hoặc đánh giá tùy theo phân vùng, không bao giờ dùng để cung cấp trực tiếp câu trả lời khi suy luận.
Precision và recall: đang nói về những cặp nào?
Một dương tính thật là một cặp được đề xuất là giống nhau và thực sự giống nhau trong dữ liệu tham chiếu. Một dương tính giả ghép nhầm hai tài liệu khác nhau. Một âm tính giả là cặp dương được kỳ vọng mà hệ thống không tìm thấy.
Precision trả lời câu hỏi « trong các đối chiếu được đề xuất, bao nhiêu là đúng? ». Recall trả lời « trong các đối chiếu được kỳ vọng, chúng ta đã tìm lại được bao nhiêu? ». F1 kết hợp hai chỉ số bằng trung bình điều hòa: 2 × precision × recall / (precision + recall).
Chúng ta sẽ dùng ba chỉ số bổ sung:
| Chỉ số | Cách tính | Câu hỏi đặt ra |
|---|---|---|
| Recall của blocking | Dương tính trong ứng viên / mọi dương tính được kỳ vọng | Bộ lọc đầu tiên có giữ lại các so sánh đúng không? |
| Recall ứng viên của bộ phân loại | Dương tính thật / dương tính trong các ứng viên | Mô hình có nhận ra các cặp đúng mà nó nhận được không? |
| Recall đầu-cuối của các cặp | Dương tính thật / mọi dương tính được kỳ vọng | Chuỗi tiền chọn và phân loại tìm lại được gì? |
Ví dụ sư phạm: có mười cặp dương được kỳ vọng, bộ lọc giữ lại bảy và mô hình nhận ra cả bảy không sai. Recall ứng viên của nó là 7/7 = 1, nhưng recall đầu-cuối là 7/10 = 0,7. Không có mâu thuẫn nào: mẫu số khác nhau.
Tổng quát hơn, với chuỗi cặp này, recall đầu-cuối là tích của recall blocking và recall ứng viên. Vì vậy, chỉ cải thiện bộ phân loại không xóa được giới hạn do bước tiền chọn đặt ra.
B-cubed: nhìn các hồ sơ đồng hành của từng hồ sơ
Sau các cặp là các nhóm, hay cluster. Điểm B-cubed xem xét, với mỗi hồ sơ, nhóm được đề xuất và nhóm tham chiếu của nó. Các thành viên chung là những hồ sơ đồng hành được giữ chung một cách đúng đắn, kể cả chính hồ sơ đó.
Precision cục bộ lấy số thành viên chung chia cho kích thước nhóm được đề xuất. Nó giảm nếu ta thêm người lạ vào. Recall cục bộ lấy số đó chia cho kích thước nhóm được kỳ vọng. Nó giảm nếu ta bỏ sót các thành viên của cùng tài liệu.
Ví dụ sư phạm: một hồ sơ phải ở cùng hai hồ sơ khác, tức nhóm kỳ vọng gồm ba thành viên. Nhóm đề xuất chứa hai thành viên đúng và một người lạ. Với hồ sơ này, precision và recall B-cubed đều bằng 2/3. Phép tính được lặp lại cho từng hồ sơ, rồi precision và recall được lấy trung bình. Chúng ta sẽ tính F1 từ hai trung bình đó: quy ước này khớp các giá trị công bố trong lộ trình, như ví dụ bốn hồ sơ sẽ cho thấy.
Một chiến lược để mọi người đứng riêng tránh được các nhóm quá rộng, nhưng bỏ lỡ các đối chiếu được kỳ vọng. Ngược lại, một nhóm khổng lồ duy nhất tìm lại mọi hồ sơ đồng hành được kỳ vọng, đồng thời thêm vào rất nhiều người lạ. Vì vậy precision và recall phải được đọc cùng nhau.
Cuối cùng, một cannot-link là quyền phủ quyết rõ ràng: trong dự án này, hai mã tham chiếu đáng tin cậy, không rỗng và khác nhau không được thuộc cùng một nhóm. Một hồ sơ đứng riêng tạo thành một singleton; nó không bị xóa. Chúng ta sẽ đo riêng chất lượng nhóm, số cặp bị cấm mà chúng chứa và việc giữ lại các phiên bản.
Chuẩn bị máy đọc GPU
Những gì cần có trước khi bắt đầu
Bạn cần biết đọc Python, dùng terminal và chạy Docker. Kiến thức cơ bản về PyTorch, phân loại có giám sát và đồ thị sẽ hữu ích; chúng ta sẽ giải thích các thao tác xuất hiện trong trích đoạn. Ở đây, tensor là một mảng số, còn đồ thị là tập hồ sơ được nối bởi các đối chiếu được đề xuất.
Cấu hình tham chiếu là Linux với RTX 3090 24 Gio, 24 Gio RAM và 30 Gio đĩa làm việc, cộng thêm dung lượng Docker. Bộ nhớ của card đồ họa và RAM máy là hai tài nguyên khác nhau. Các thông tin này không bảo đảm thời lượng hay khả năng của bất kỳ cấu hình nào khác. Kết quả được trình bày đến từ lộ trình GPU r001; chúng không phải là xác nhận trên CPU.
Giải nén ZIP của khóa học, có ở cuối bài viết, rồi mở terminal tại thư mục gốc của nó. Mọi lệnh sau đây đều chạy từ thư mục này, theo đúng thứ tự đã nêu. Phiên bản và thiết lập cần tái tạo là những gì có trong kho lưu trữ.
GPU hiển thị trên máy chủ chưa đủ: Docker phải truy cập được nó. NVIDIA Container Toolkit cung cấp tích hợp cần thiết. Nếu thiếu, chẩn đoán của dự án nêu hành động cần làm mà không tự cài đặt âm thầm bất cứ thứ gì. GPU_DEVICE=1 cho phép chọn một card khác trước khi bắt đầu lộ trình.
Kiểm tra, xây dựng và tải các tài nguyên
Hãy bắt đầu bằng các kiểm tra trước, khâu chuẩn bị và xây dựng các dịch vụ.
sh scripts/preflight.sh
sh scripts/setup.sh
docker compose config --quiet
docker compose build acquisition tutorial learning inference
Preflight kiểm tra Docker, Compose, RAM, đĩa và GPU. docker compose config --quiet thành công mà không hiển thị nội dung khi cấu hình hợp lệ. Mỗi bước phải kết thúc không lỗi trước bước tiếp theo.
Sau đó, bước tải về lấy sáu tài nguyên CamemBERT mà dự án dự kiến.
docker compose run --rm acquisition python scripts/acquire.py --config configs/minimum.yaml
Kích thước và dấu vết SHA-256 của chúng được kiểm tra trước khi thay thế nguyên tử: các tệp hợp lệ được đặt vào vị trí dự kiến mà không công bố một bản sao dở dang như thể nó hoàn chỉnh. Dấu vết kiểm tra danh tính của các byte được mong đợi, chứ không kiểm tra mức độ phù hợp của các dự đoán sau này. Không có bộ nhớ đệm riêng nào được phân phối trong kho lưu trữ.
Bây giờ hãy kiểm tra môi trường từ container, rồi chạy các kiểm thử của dự án.
docker compose run --rm tutorial python scripts/check_environment.py
docker compose run --rm tutorial python -m pytest -q
Kiểm tra môi trường thực sự thực hiện một phép tính từ Docker. Các kiểm thử xem xét, trong đó có, xung đột, tính đối xứng và việc giữ lại phiên bản. Chúng kiểm tra hành vi của chương trình; chúng không chứng minh mọi đối chiếu nghiệp vụ đều đúng. Hãy kiểm tra để lần chạy của bạn kết thúc không lỗi và giữ lại báo cáo của nó.
Tạo hồ sơ, ứng viên và điểm đối xứng
Tách dữ liệu đầu vào khỏi câu trả lời được kỳ vọng
Khâu chuẩn bị đặt các hồ sơ và tệp giả định của chúng trong data/generated/input/. Các danh tính gold vẫn nằm trong labels/. Container learning chỉ gắn các cặp học và kiểm định; inference không gắn bất kỳ chú thích nào.
Ý tưởng giống một bài tập mà lời giải được giữ kín trong khi bạn trả lời. Mô hình phải dùng các trường quan sát được, không đọc danh tính gold của cặp mà nó phải phân loại.
docker compose run --rm tutorial python -m ged_rapprochement_fiches.cli prepare --config configs/minimum.yaml
docker compose run --rm tutorial python -m ged_rapprochement_fiches.cli baseline --config configs/minimum.yaml
docker compose run --rm inference python -m ged_rapprochement_fiches.cli inspect-mechanism --config configs/minimum.yaml
prepare tạo dữ liệu. baseline tạo các phương pháp tham chiếu đơn giản để so sánh với mô hình. Trong số đó, tham chiếu chính xác dùng tín hiệu bằng nhau; Jaccard đo mức chồng lấp từ vựng. Nguyên tắc Jaccard là « các phần tử chung / các phần tử có mặt trong ít nhất một trong hai tập ». Các quy tắc chuẩn bị tập chính xác vẫn là những quy tắc trong ZIP.
inspect-mechanism hiển thị các trường đã tuần tự hóa và tính đối xứng. Tuần tự hóa nghĩa là biến các trường của một hồ sơ thành một đầu vào văn bản có tổ chức. Dự án truyền mã tham chiếu, độ tin cậy của nó, tiêu đề, vụ việc, văn bản và phiên bản. Trường độ tin cậy không thừa: đọc một mã tham chiếu và biết nó đáng tin là hai thông tin khác nhau.
Hãy quan sát biểu diễn này trước khi huấn luyện. Một lần kiểm tra sư phạm làm phép tính dễ đọc; nó không được trình bày như một điểm tổng hợp trên tập kiểm tra.
Huấn luyện, ngắt và tiếp tục
Huấn luyện điều chỉnh các tham số đã học từ các cặp có chú thích. Còn suy luận dùng các tham số thu được để gán điểm cho các cặp mới.
docker compose run --rm learning python -m ged_rapprochement_fiches.cli train --config configs/minimum.yaml --mode interrupt
docker compose run --rm learning python -m ged_rapprochement_fiches.cli train --config configs/minimum.yaml --mode continuous
docker compose run --rm learning python -m ged_rapprochement_fiches.cli train --config configs/minimum.yaml --mode resume
docker compose run --rm learning python -m ged_rapprochement_fiches.cli verify-resume --config configs/minimum.yaml
Lộ trình phân biệt một lần chạy bị ngắt, một lần chạy liên tục và một lần tiếp tục. Một checkpoint là trạng thái đã lưu cho phép tiếp tục phép tính; tiếp tục không phải là một lần huấn luyện tùy tiện mới trên cùng các tệp. verify-resume kiểm tra tính nhất quán của lộ trình được tiếp tục với lộ trình liên tục. Kiểm tra tái tạo này không thay thế việc đánh giá trên các hồ sơ chưa biết.
Để xem ngân sách huấn luyện, optimizer và chi tiết khôi phục, hãy tham khảo configs/minimum.yaml và mã nguồn được cung cấp. Hãy giữ các thiết lập này khi tái tạo tham chiếu, trước khi thử nghiệm trong một bản sao riêng.
Từ logit đến quyết định
Mô hình tạo ra một logit, một điểm thô có thể dương, âm hoặc bằng không. Hàm sigmoid biến điểm này thành giá trị giữa 0 và 1: sigmoid(z) = 1 / (1 + exp(-z)).
Trong khi học, loss, hay hàm mất mát, đo chênh lệch giữa dự đoán và nhãn đích. Để hiểu entropy chéo nhị phân không trọng số, hãy nhớ hai trường hợp: nếu nhãn đích bằng 1, lỗi là -log(p); nếu bằng 0, là -log(1-p). Vì vậy, đặt độ tin cậy cao vào kết quả sai sẽ phải trả giá đắt.
Ví dụ số mang tính sư phạm: với một cặp thực sự dương, p = 0,9 cho mất mát khoảng 0,1054, so với 2,3026 khi p = 0,1. Việc học dùng tín hiệu này để điều chỉnh tham số; nó không viết ra một quy tắc văn bản từ từng ví dụ.
Tài liệu về BCEWithLogitsLoss, cũng có trong tham chiếu PyTorch 2.8, nêu rõ thao tác này kết hợp sigmoid và mất mát nhị phân theo cách ổn định số học. Nó nhận các logit: không nên áp dụng một sigmoid đầu tiên « để hỗ trợ ».
Một đầu ra giữa 0 và 1 vẫn là điểm xác suất của mô hình. Giá trị của nó không chứng minh cùng một tỷ lệ quyết định sẽ đúng trên tài liệu thực tế.
Vì sao tính A/B và B/A?
Danh tính cần tìm có tính đối xứng: nếu A và B biểu diễn cùng tài liệu thì B và A cũng vậy. Tuy nhiên, một mô hình đọc một chuỗi có thứ tự có thể cho hai logit khác nhau tùy theo thứ tự hồ sơ.
Vì vậy dự án mã hóa cả hai chiều, rồi lấy trung bình các logit của chúng. Đây là hàm chính xác:
def symmetric_logits(model, encoded_pairs, tokenizer):
if not encoded_pairs:
raise ValueError("Empty pair batch")
oriented = [row["orientations"][side] for side in [0, 1] for row in encoded_pairs]
batch = {
k: v.cuda()
for k, v in tokenizer.pad(oriented, padding=True, return_tensors="pt").items()
}
raw = model(**batch).squeeze(-1)
count = len(encoded_pairs)
return (raw[:count] + raw[count:]) / 2, raw[:count], raw[count:]
Hãy bắt đầu với oriented. Vòng lặp đi qua side=0 cho tất cả cặp trước, rồi side=1 cho tất cả cặp. Với các cặp A/B và C/D, thứ tự là A/B, C/D, B/A, D/C. Không phải A/B, B/A, C/D, D/C. Cách tổ chức này giải thích hai lát cắt của giá trị trả về.
tokenizer.pad(..., padding=True, return_tensors="pt") bổ sung các chuỗi trong lô đến một độ dài chung và tạo tensor PyTorch. Padding là phần đệm kỹ thuật, không phải nội dung tài liệu; attention mask giúp phân biệt nó với các vị trí hữu ích. Hợp đồng tokenizer trình bày chi tiết các đầu vào này. Sau đó mỗi tensor được chuyển sang GPU bằng .cuda().
Mô hình của dự án cung cấp một điểm cho mỗi chiều. squeeze(-1) loại bỏ chiều cuối có kích thước 1: đầu ra dạng [2B, 1] thành [2B], trong đó B là số cặp. Không được nhầm B cặp với 2B chiều.
Cuối cùng, raw[:count] chứa các logit trực tiếp và raw[count:] chứa các logit đảo chiều. Trung bình từng phần tử của chúng cho lại một điểm cho mỗi cặp. Hai dãy thô cũng được trả về để kiểm tra. Một lô rỗng gây ra lỗi rõ ràng.
Trung bình logit và trung bình xác suất không thể thay thế cho nhau
Ví dụ minh họa, không liên quan đến đầu ra CamemBERT đã đo: giả sử logit của một cặp là 4 theo một chiều và -2 theo chiều kia. Trung bình của chúng là 1; sigmoid của nó xấp xỉ 0,7311.
Nếu áp dụng hai sigmoid trước, ta nhận được khoảng 0,9820 và 0,1192. Trung bình của chúng là 0,5506, không phải 0,7311. Khác biệt đến từ phép biến đổi phi tuyến. Vì vậy, để tái tạo dự án, cần giữ trung bình các logit, không thay nó bằng trung bình xác suất.
Điểm cuối cùng có tính đối xứng vì hoán đổi hai logit không thay đổi trung bình của chúng. Trong bằng chứng r001, sai số đối xứng tuyệt đối bằng không với A-17/B-92. Điều này kiểm tra một thuộc tính của phép tính, không phải danh tính của mọi hồ sơ.
Thuộc tính này cũng giả định so sánh cùng các đánh giá ở cả hai chiều. Đoạn trích không tự đưa mô hình sang chế độ đánh giá. Trong PyTorch, eval() tác động, trong đó có, đến các mô-đun có hành vi khác khi huấn luyện, như dropout, vốn vô hiệu ngẫu nhiên một số giá trị trong lúc học. Vì vậy ngữ cảnh gọi vẫn quan trọng để có một so sánh tái tạo được.
Quan trọng hơn, đối xứng không phải là bắc cầu. Điểm cao cho A/B và B/C không bảo đảm điểm cao cho A/C. Chính điều này là thứ việc gom nhóm phải xử lý.
Hiệu chỉnh, gom nhóm và kiểm tra quyền phủ quyết
Chọn ngưỡng trước khi xem tập kiểm tra
Sau huấn luyện, suy luận tạo điểm mà không đọc nhãn. Sau đó, hiệu chỉnh dùng tập kiểm định để chọn ngưỡng, có giá trị 0,5 trong lộ trình r001. Tập kiểm tra dùng để đo quy tắc đã cố định như vậy, không phải để chọn sau đó giá trị làm kết quả trông đẹp nhất.
Ở đây, hiệu chỉnh chỉ việc chọn ngưỡng quyết định. Điều đó không đủ để chứng minh hiệu chỉnh xác suất: chỉ bằng thao tác này, điểm 0,9 không trở thành bảo đảm 90 % quyết định đúng.
docker compose run --rm inference python -m ged_rapprochement_fiches.cli predict --config configs/minimum.yaml
docker compose run --rm learning python -m ged_rapprochement_fiches.cli calibrate --config configs/minimum.yaml
docker compose run --rm inference python -m ged_rapprochement_fiches.cli cluster --config configs/minimum.yaml
docker compose run --rm tutorial python -m ged_rapprochement_fiches.cli evaluate --config configs/minimum.yaml
predict tạo điểm; calibrate cố định quyết định trên tập kiểm định; cluster xây dựng các nhóm; evaluate đối chiếu các đề xuất với dữ liệu tham chiếu. Hãy giữ các bước tách biệt để có thể xác định lỗi nằm ở đâu: ứng viên sai, điểm sai hay việc hợp nhất nhóm sai.
Cái bẫy của các thành phần liên thông
Biến thể ngây thơ biểu diễn mỗi hồ sơ bằng một nút. Một cặp được chấp nhận trở thành một cạnh, một liên kết không hướng giữa hai nút. Một thành phần liên thông tập hợp các hồ sơ mà bạn có thể đi giữa chúng bằng cách theo các liên kết này, có thể qua nhiều trung gian. Tài liệu NetworkX đưa ra định nghĩa này; điều đó không có nghĩa thư viện này cần thiết cho mã khóa học.
Ví dụ sư phạm: với các liên kết A—B và B—C, ba hồ sơ thuộc cùng một thành phần, ngay cả khi không có liên kết A—C. Nếu B bị đối chiếu nhầm với C, chỉ sự tồn tại của đường đi đã đủ đưa C vào nhóm của A.
Vì thế, vấn đề không phải thuật toán thành phần liên thông tính sai. Nó áp dụng chính xác quy tắc được giao. Chính quy tắc đó có thể quá dễ dãi đối với danh tính tài liệu.
Kiểm tra mọi quan hệ giữa các nhóm
Biến thể có ràng buộc đặt một câu hỏi khắt khe hơn: có thể hợp nhất hai nhóm này mà không tạo ra quan hệ bị cấm hoặc chưa được chứng minh đủ giữa các thành viên của chúng không?
Lấy hai nhóm {A, B} và {C, D}. Chỉ kiểm tra liên kết B/C đã gợi ý việc hợp nhất là không đủ. Các cặp chéo là A/C, A/D, B/C và B/D: bốn lần kiểm tra. Tổng quát hơn, hợp nhất các nhóm có m và n thành viên cần xem xét m × n cặp chéo.
Cơ chế bảo vệ của dự án như sau. Các hàm trợ giúp, gồm pair và cannot_link, thuộc mã hoàn chỉnh trong ZIP.
def can_merge_clusters(left, right, records, get_score, threshold):
crossed = sorted(pair(a, b) for a, b in product(left, right))
# Trusted administrative conflicts veto the entire merge, before neural work.
for a, b in crossed:
if cannot_link(records[a], records[b]):
return False, {"reason": "CANNOT_LINK", "pair": [a, b]}
for a, b in crossed:
value = get_score(a, b)
if value is None:
return False, {"reason": "REVIEW_UNSCORED", "pair": [a, b]}
if value < threshold:
return False, {
"reason": "BELOW_THRESHOLD",
"pair": [a, b],
"probability": value,
}
return True, {"reason": "ALL_CROSS_PAIRS_PASSED", "cross_pairs": len(crossed)}
Dòng đầu tiên xây dựng mọi cặp chéo bằng product(left, right), sau đó sắp xếp chúng theo một thứ tự ổn định. Nó không chỉ giới hạn ở đại diện các nhóm hay ở liên kết đã kích hoạt đề xuất.
Vòng lặp đầu tiên tìm một quyền phủ quyết hành chính. Nếu cannot_link phát hiện hai mã tham chiếu đáng tin cậy không tương thích, toàn bộ phép hợp nhất bị từ chối với CANNOT_LINK. Vì vòng lặp này diễn ra trước mọi lời gọi get_score, hàm này không yêu cầu bất cứ điểm nơ-ron nào cho lần thử đó, ngay cả khi xung đột xuất hiện ở cặp cuối cùng được xem xét.
Một mã tham chiếu bị thiếu hoặc chưa được xác nhận độ tin cậy không tự nó kích hoạt quyền phủ quyết này. Nhưng không có quyền phủ quyết không phải là bằng chứng danh tính: vẫn phải vượt qua các kiểm tra điểm số.
Vòng lặp thứ hai yêu cầu một điểm cho mỗi cặp chéo. get_score(a, b) cung cấp giá trị sẵn có; lộ trình có thể tính thêm điểm cho những lần kiểm tra này. Nếu giá trị vẫn là None, hàm trả về REVIEW_UNSCORED. Nó không biến « chưa được xem xét » thành « có lẽ giống nhau ».
Nếu một điểm nhỏ hơn ngưỡng một cách nghiêm ngặt, phép hợp nhất bị từ chối với BELOW_THRESHOLD. Giá trị đúng bằng ngưỡng vượt qua kiểm tra này, vì điều kiện là value < threshold, không phải value <= threshold.
Cuối cùng, ALL_CROSS_PAIRS_PASSED nghĩa là mọi kiểm tra chéo đều thành công. Đây vẫn chưa phải sửa đổi GED: hàm trả về một boolean và một chẩn đoán. Nó không xóa tệp nào và cũng không tự gộp dữ liệu nào.
Điều kiểm tra bảo đảm, và điều nó giả định
Bài kiểm tra tư duy nhỏ: ba trong bốn cặp chéo có điểm 0,9, nhưng cặp thứ tư vẫn chưa có điểm. Phép hợp nhất phải bị từ chối, ngay cả khi trung bình các điểm đã biết có vẻ rất tốt. Kết quả cũng vậy với giá trị thứ tư là 0,4 và ngưỡng 0,5. Các số này minh họa quy tắc; chúng không phải là điểm mô hình đã đo.
Xuất phát từ các nhóm đã hợp lệ, việc kiểm tra mọi quan hệ chéo mới giúp giữ các ràng buộc của chúng khi hợp nhất. Tuy vậy, điều đó không xác lập rằng mỗi nhóm tương ứng với đúng tài liệu: các cặp khác nhau đều có thể nhận điểm cao một cách sai lầm, mà không có mã tham chiếu đáng tin nào phản bác.
Đoạn trích cũng không phải trình kiểm tra đầy đủ cho dữ liệu đầu vào. Nó giả định, trong đó có, các nhóm không rỗng, định danh hiện diện trong records và các điểm số hữu hạn. Bản thân nó không kiểm tra các thuộc tính này. Ví dụ, so sánh NaN với ngưỡng bằng < không kích hoạt từ chối như mong đợi với một điểm quá thấp. Điều này mô tả giới hạn của hàm riêng lẻ, không phải kết quả kiểm toán các kiểm tra đầu nguồn của dự án.
Cuối cùng, kiểm tra một phép hợp nhất cục bộ không nhất thiết tìm ra phân vùng toàn cục tốt nhất. Trong ví dụ trừu tượng mà A/B và B/C đạt nhưng A/C thất bại, hợp nhất A/B trước hay B/C trước có thể dẫn đến hai phân vùng khác nhau. Việc sắp xếp các cặp trong hàm này ổn định việc kiểm tra chúng; nó không chứng minh toàn bộ việc gom nhóm độc lập với thứ tự các phép hợp nhất được đề xuất.
Đọc bài kiểm tra: tổn thất đầu tiên đến trước mô hình
Tìm lại các con số phía sau điểm số
Trên 648 hồ sơ kiểm tra, blocking giữ lại 918 cặp trong số 209 628 cặp khả dĩ, tương đương khoảng 0,44 % số so sánh ban đầu. Đây là mức giảm khối lượng công việc lớn cho bộ phân loại, nhưng phải trả giá bằng recall.
Trong 648 cặp dương được kỳ vọng, chỉ 444 đến được danh sách ứng viên. Do đó thiếu 204 cặp. Recall của blocking là 444 / 648 = 0,685185.
Trên 918 ứng viên này, CamemBERT có 444 dương tính thật, 4 dương tính giả và 0 âm tính giả. Vì vậy recall ứng viên của nó bằng 1. Nhưng con số không âm tính giả này chỉ liên quan các cặp đã nhận, không phải các cặp bước tiền chọn đã loại.
| Chỉ số cặp CamemBERT | Tính trên các số liệu công bố | Kết quả |
|---|---|---|
| Precision | 444 / (444 + 4) |
0,991071 |
| Recall ứng viên | 444 / (444 + 0) |
1,00 |
| F1 ứng viên | 2 × 444 / (2 × 444 + 4 + 0) |
0,995516 |
| Recall đầu-cuối | 444 / (444 + 204) |
0,685185 |
| F1 đầu-cuối | 2 × 444 / (2 × 444 + 4 + 204) |
0,810219 |
Thay đổi mẫu số giải thích toàn bộ chênh lệch: mô hình nhận ra các cặp dương được đưa cho nó, nhưng chuỗi cặp ban đầu đã mất gần một phần ba. Không thể sửa 204 thiếu sót này bằng cách huấn luyện lâu hơn cùng một bộ phân loại trên danh sách ứng viên không đổi.
Hai phương pháp tham chiếu cho F1 đầu-cuối là 0,568502 với Jaccard và 0,708373 với tham chiếu chính xác. Vì vậy CamemBERT cải thiện chỉ số này trong giao thức được cung cấp, nhưng không xóa tổn thất của blocking.
Các điểm bổ sung có thể có của bước gom nhóm được tính ở giai đoạn sau. Không được đưa ngược chúng vào 918 ứng viên để công bố một recall ban đầu khác: hai chỉ số không đo cùng một thao tác.
Giữ lại các phiên bản chưa đủ để tạo đúng nhóm
Việc gom nhóm ngây thơ giữ lại 648 phiên bản, nhưng các nhóm của nó chứa 16 cặp bị cấm và hợp nhất quá mức 6 tài liệu logic. B-cubed F1 của nó là 0,908720. Vì vậy, một liên kết cặp sai có thể gây hệ quả vượt ra ngoài hai đầu của nó, bằng cách nối cả các nhóm.
Việc gom nhóm có ràng buộc cũng giữ lại 648 phiên bản, tạo 295 nhóm, và không chứa cặp bị cấm nào hay tài liệu nào bị hợp nhất quá mức trong bài kiểm tra này. Precision B-cubed là 1,00, recall là 0,842593 và F1 là 0,914573.
Tại sao recall vẫn dưới 1 nếu precision hoàn hảo? Vì các nhóm được đề xuất không còn trộn lẫn danh tính, nhưng một số nhóm vẫn chưa đầy đủ: các hồ sơ của cùng một tài liệu vẫn tách rời. Ngược lại, việc giữ tất cả phiên bản chỉ có nghĩa không phiên bản nào biến mất khỏi đầu ra, chứ không phải mỗi phiên bản đã ở cùng mọi hồ sơ đồng hành đúng.
Ta tìm lại F1 có ràng buộc bằng 2 × 1 × 0,842593 / (1 + 0,842593), tức khoảng 0,914573. Recall B-cubed không phải recall của các cặp: nó lấy trung bình các hồ sơ đồng hành tìm lại quanh từng hồ sơ, và không được nhầm với 0,685185.
Chi phí và giới hạn vẫn hiện rõ
Kiểm tra yêu cầu 51 cặp bổ sung trên tập kiểm tra, trong ngân sách dự kiến 20 000. Những phép tính này dùng để kiểm tra các phép hợp nhất dự kiến; chúng không tương đương với việc khởi động lại một tìm kiếm toàn diện cho mọi cặp còn thiếu. Sự phân mảnh của nhóm vẫn thể hiện trong recall B-cubed.
Thời lượng quan sát của việc gom nhóm bao gồm suy luận cho các cặp bổ sung này. Các yếu tố được trình bày không đưa ra thời lượng định lượng để lặp lại ở đây, và lộ trình này không biện minh cho bất kỳ ngoại suy thông lượng nào. Tăng gấp đôi kích thước GED không nhất thiết tăng gấp đôi chi phí: số ứng viên và kích thước nhóm cũng tác động.
Kết quả áp dụng cho một tập dữ liệu tổng hợp, với các mã tham chiếu và cách diễn đạt có cấu trúc mạnh, một seed và một máy. Seed cố định các lần lấy mẫu giả ngẫu nhiên của thí nghiệm; một lần chạy được xác định như vậy không đo biến thiên giữa nhiều lần huấn luyện. Không có xác nhận nghiệp vụ hay nghiên cứu người đọc nào được cung cấp.
Vì thế, kết luận cần ghi nhớ có hai phần: mô hình cải thiện các quyết định cặp trong giao thức này; quyền phủ quyết ngăn các hợp nhất quá mức đã quan sát, nhưng không làm mọi nhóm trở nên đầy đủ.
Bài tập: dự đoán một phép hợp nhất bắc cầu gây hiểu lầm
Dự đoán của bạn trước khi chạy lệnh
Hãy quay lại bốn hồ sơ ở đầu bài. A-17, B-92 và D-40 liên quan đến VC-204, trong đó D-40 là phiên bản 2. C-11 liên quan đến VC-205. Tuy vậy, mô hình cho điểm cao cho mọi cặp, kể cả A-17/C-11.
Trước khi chạy, hãy dự đoán số nhóm mà một thành phần liên thông ngây thơ sẽ tạo ra. Sau đó, tưởng tượng quyền phủ quyết được kiểm tra trên mọi cặp chéo: có thể thêm C-11 vào nhóm đã chứa A-17 chỉ vì C-11 giống B-92 không? Cuối cùng, tệp của phiên bản 2 phải trở thành gì?
Hãy viết câu trả lời, rồi chạy bài tập:
docker compose run --rm tutorial python -m ged_rapprochement_fiches.cli exercise --config configs/minimum.yaml
Lệnh tạo bốn hồ sơ này và tính điểm thực tế của chúng bằng mô hình. Các con số sư phạm dùng phía trên để giải thích logit và kiểm tra không phải điểm của lần chạy này. Tương tự, các phản ví dụ toán học có thể được đánh dấu là minh họa trong hình không được nhầm với đầu ra CamemBERT.
Điều đáp án r001 cho thấy
Biến thể ngây thơ đưa A-17, B-92, C-11 và D-40 vào một nhóm duy nhất. Nó giữ cả bốn phiên bản, nhưng đếm 2 cặp bị cấm và 2 tài liệu logic bị hợp nhất quá mức, với B-cubed F1 là 0,769231.
Biến thể có ràng buộc tạo hai nhóm: {A-17, B-92, D-40} và {C-11}. Nó giữ cả bốn phiên bản, không đếm cặp bị cấm nào và đạt B-cubed F1 = 1,00.
Quyền phủ quyết được làm rõ là A-17/C-11, có các mã tham chiếu đáng tin nhưng không tương thích. B-92 đúng là mang VC-204, nhưng độ tin cậy của nó chưa được xác nhận. Nó không được trở thành một trung gian cho phép C-11 đi vào nhóm của A-17. Đó chính là khác biệt giữa việc kiểm tra liên kết cuối cùng được thêm và kiểm tra phép hợp nhất các nhóm.
Tự tính lại B-cubed
Để hiểu F1 ngây thơ, tạm quên mạng lưới và chỉ nhìn các tập hợp. Các nhóm tham chiếu là {A-17, B-92, D-40} và {C-11}; nhóm được đề xuất chứa tất cả mọi người.
Với mỗi trong ba hồ sơ VC-204, ba thành viên đúng có mặt trong bốn: precision cục bộ 3/4, recall cục bộ 3/3 = 1. Với C-11, chỉ một thành viên trong bốn là đúng: precision cục bộ 1/4, recall cục bộ 1/1 = 1.
Vì vậy precision trung bình là (3/4 + 3/4 + 3/4 + 1/4) / 4 = 0,625. Recall trung bình là 1. F1 tính từ hai trung bình này là 2 × 0,625 × 1 / (0,625 + 1) = 0,769231 sau làm tròn, khớp giá trị đã công bố.
Recall hoàn hảo của nhóm ngây thơ không phải là một thành công đủ: mọi hồ sơ đồng hành đúng đều có mặt, nhưng cả những người lạ cũng vậy. Với hai nhóm đúng, precision và recall cục bộ đều bằng 1 cho từng hồ sơ.
Một biến thể để dự đoán mà không sửa lộ trình tham chiếu
Để kiểm tra sự hiểu biết của bạn, hãy tưởng tượng độ tin cậy của mã tham chiếu C-11 không còn được xác nhận, mà không thay đổi các điểm cao. Quyền phủ quyết dựa trên hai mã tham chiếu đáng tin còn có thể tự nó chặn đối chiếu A-17/C-11 không? Không: giả định khởi đầu của nó không còn thỏa mãn. Các kiểm tra điểm vẫn cần thiết, nhưng cũng vẫn không phải bằng chứng danh tính.
Đây là một biến thể để lập luận, không được thực thi trong các kết quả công bố. Nó cho thấy vì sao định nghĩa « đáng tin » phải đến từ một chính sách nghiệp vụ, không phải từ niềm tin của mô hình vào điểm số của chính nó.
Trong bài tập được cung cấp, cũng như trong lộ trình chính, đầu ra vẫn là PROPOSITION_A_CONFIRMER. Không có bản gốc nào bị xóa. Một nhóm được gợi ý là kết quả cần xem xét, không phải quyền cho phép xóa một bản trùng lặp được giả định.
Hình, mốc kiểm tra và dọn dẹp
Kiểm tra trước khi xóa
Hãy đọc outputs/evaluation.json, outputs/groups.json, outputs/grouping.json và outputs/exercise.json. Đi từ điểm tổng quát đến một nhóm cụ thể: tìm lại các thành viên, các phiên bản được giữ và lý do đã ngăn một số phép hợp nhất.
Sau đó tạo các hình và kiểm tra các mốc của khóa học:
docker compose run --rm tutorial python lesson/figures/plot.py
docker compose run --rm tutorial python scripts/check_checkpoints.py
Các mốc này kiểm tra tài liệu sư phạm được kỳ vọng. Chúng bổ sung cho đánh giá mà không biến một đề xuất thành xác nhận hành chính.
Hãy giữ các đầu ra hữu ích trước khi tiếp tục. Việc dọn dẹp tuân theo đúng thứ tự này:
docker compose down
docker compose run --rm tutorial python scripts/clean.py --outputs-only
docker compose down
Lệnh down đầu tiên cố ý được đặt trước khi chạy dọn dẹp; lệnh thứ hai kết thúc lộ trình. clean --outputs-only hiển thị rồi chỉ xóa outputs/, không đụng đến hồ sơ, tệp, tập dữ liệu hay checkpoint. Vì thế không được chạy nó trước khi đọc hoặc sao chép các kết quả bạn muốn giữ.
Khi có vấn đề, quay lại đúng giai đoạn liên quan
Nếu kiểm tra GPU thất bại, hãy quay lại chẩn đoán môi trường Docker: việc card hiện diện trong Linux không thay thế phép tính trong container. Nếu việc tải tài nguyên thất bại, hãy kiểm tra tải xuống, kích thước và dấu vết được kỳ vọng thay vì thay bằng một mô hình tìm thấy ở nơi khác.
Nếu recall thấp, trước hết hãy xem các cặp đúng có nằm trong các ứng viên không. Nếu một phép hợp nhất bị từ chối, hãy đọc lý do: CANNOT_LINK, REVIEW_UNSCORED và BELOW_THRESHOLD tương ứng với ba tình huống khác nhau. Tăng một điểm không giải quyết xung đột hành chính đáng tin; bịa ra một điểm không giải quyết một cặp chưa được xem xét.
Từ hướng dẫn đến một GED thực tế
Trước khi điều chỉnh, hãy xác định cùng các nhóm nghiệp vụ thế nào là một tài liệu logic, điều gì phân biệt một phiên bản với tài liệu gần kề, và những mã tham chiếu nào thực sự đáng tin. Quyền phủ quyết phụ thuộc vào các lựa chọn này: một thông tin sai nhưng được tuyên bố đáng tin có thể chặn một đối chiếu hữu ích.
Hãy đo recall của blocking trên dữ liệu được phép và có chú thích. Xem xét riêng các mã tham chiếu thiếu, tiêu đề lặp lại và các biến thể diễn đạt, thay vì chỉ hài lòng với F1 của riêng các ứng viên. Đây là hướng đánh giá cho một ứng dụng thực tế, không phải các quần thể mới đã được hướng dẫn này xác nhận.
Hãy lập phiên bản cho các đề xuất và giữ lại thành viên, điểm số, quy tắc và lý do từ chối của chúng. Hướng các trường hợp chưa có điểm hoặc mơ hồ sang bước xem xét, và tách bước xem xét này khỏi mọi hành động lên tệp. Quyền tài liệu và quy tắc lưu giữ vẫn phải áp dụng; thuộc một nhóm được đề xuất không cấp quyền mới.
Cơ chế đã học gói gọn trong ba phân biệt: tiền chọn không phải là nhận diện, nhận diện một cặp không phải là xác nhận một nhóm, đề xuất một nhóm không phải là gộp tệp của chúng. Quyền phủ quyết chặn một sự không tương thích được xác định trước; việc không có nó không chứng nhận danh tính một tài liệu.
Tải khóa học: ZIP r001.
Các tài liệu được liên kết trong bài viết đào sâu các khái niệm. Các trích đoạn, lệnh và kết quả của lộ trình vẫn là của bản sửa đổi r001. Những phép tính nhỏ được nêu rõ là sư phạm giải thích các cơ chế này mà không tạo thành các phép đo mới của mô hình.