Thuật toán nào đưa ra gợi ý trong trình kiểm tra chính tả?


114

Thuật toán nào thường được sử dụng khi triển khai trình kiểm tra chính tả đi kèm với gợi ý từ?

Lúc đầu, tôi nghĩ có thể hợp lý khi kiểm tra từng từ mới được nhập (nếu không tìm thấy trong từ điển) so với khoảng cách Levenshtein từ mọi từ khác trong từ điển và trả về kết quả hàng đầu. Tuy nhiên, điều này có vẻ như nó sẽ không hiệu quả cao, phải đánh giá toàn bộ từ điển nhiều lần.

Điều này thường được thực hiện như thế nào?

Câu trả lời:


203

một bài luận hay của Peter Norvig về cách triển khai một trình sửa lỗi chính tả. Về cơ bản, đó là một cách tiếp cận bạo lực khi thử các chuỗi ứng viên với khoảng cách chỉnh sửa nhất định. ( Dưới đây là một số mẹo về cách bạn có thể cải thiện hiệu suất của trình sửa lỗi chính tả bằng cách sử dụng Bộ lọc Bloombăm ứng viên nhanh hơn .)

Các yêu cầu đối với trình kiểm tra chính tả yếu hơn. Bạn chỉ phải tìm ra một từ không có trong từ điển. Bạn có thể sử dụng Bộ lọc Bloom để xây dựng một trình kiểm tra chính tả tiêu tốn ít bộ nhớ hơn. Một phiên bản cổ được Jon Bentley giải mã trong Programming Pearls bằng cách sử dụng 64kb cho từ điển tiếng Anh.

Một BK-Tree là một cách tiếp cận khác. Một bài báo hay ở đây .

Khoảng cách Levenshstein không phải là khoảng cách chỉnh sửa chính xác cho một trình kiểm tra chính tả. Nó chỉ biết chèn, xóa và thay thế. Chuyển vị bị thiếu và tạo ra 2 cho một chuyển vị của 1 ký tự (đó là 1 lần xóa và 1 lần chèn). Khoảng cách Damerau-Levenshtein là khoảng cách chỉnh sửa phù hợp.


2
+1 cho tham chiếu BK-Tree tương đối chưa biết. Đó là cách các công ty như Google, đang làm việc với lượng dữ liệu [TM] của Thế giới thực, đang thực hiện.
NoozNooz42,

2
Có một lời giải thích tốt hơn nhiều về BK-Trees ở đây .
Ian Boyd

17

Một cách tiếp cận để tạo đề xuất mà tôi đã sử dụng thành công nhưng chưa từng thấy được mô tả ở đâu là tính toán trước các đề xuất (khi xây dựng từ điển) bằng cách sử dụng các hàm băm "xấu".

Ý tưởng là xem xét các loại lỗi chính tả mà mọi người mắc phải và thiết kế các hàm băm có thể gán chính tả sai cho cùng một nhóm với chính tả đúng của nó.

Ví dụ, một sai lầm phổ biến là sử dụng các nguyên âm sai, như definate thay vì nhất định . Vì vậy, bạn thiết kế một hàm băm coi tất cả các nguyên âm là cùng một chữ cái. Một cách dễ dàng để làm điều đó là đầu tiên "chuẩn hóa" từ đầu vào và sau đó đặt kết quả chuẩn hóa thông qua một hàm băm thông thường. Trong ví dụ này, hàm chuẩn hóa có thể bỏ tất cả các nguyên âm, vì vậy definitesẽ trở thành dfnt. Từ "chuẩn hóa" sau đó được băm bằng một hàm băm điển hình.

Chèn tất cả các từ trong từ điển của bạn vào một chỉ mục bổ trợ (bảng băm) bằng cách sử dụng hàm băm đặc biệt này. Các nhóm trong bảng này sẽ có danh sách xung đột dài vì hàm băm là "xấu", nhưng các danh sách xung đột đó về cơ bản là các đề xuất được tính toán trước.

Bây giờ, khi bạn tìm thấy một từ sai chính tả, bạn tra cứu danh sách va chạm cho nhóm mà lỗi chính tả ánh xạ tới trong các chỉ mục phụ trợ. Ta da: Bạn có một danh sách gợi ý! Tất cả những gì bạn phải làm là xếp hạng các từ trên đó.

Trong thực tế, bạn sẽ cần một vài chỉ mục bổ trợ với các hàm băm khác để xử lý các loại lỗi khác, như các chữ cái chuyển vị, chữ cái đơn / chữ đôi và thậm chí là một chỉ mục đơn giản giống như Soundex để phát hiện lỗi chính tả ngữ âm. Trong thực tế, tôi nhận thấy những cách phát âm đơn giản sẽ đi một chặng đường dài và về cơ bản, một số cách phát âm đã lỗi thời được thiết kế để tìm những lỗi chính tả tầm thường.

Vì vậy, bây giờ bạn tìm kiếm lỗi chính tả trong mỗi chỉ mục phụ và nối danh sách va chạm trước khi xếp hạng.

Hãy nhớ danh sách va chạm chỉ chứa các từ có trong từ điển. Với các phương pháp cố gắng tạo ra các cách viết thay thế (như trong bài viết của Peter Norvig), bạn có thể nhận được (hàng chục) nghìn từ khóa mà trước tiên bạn phải lọc theo từ điển. Với cách tiếp cận được tính toán trước, bạn có thể nhận được vài trăm ứng cử viên và bạn biết rằng tất cả họ đều viết đúng chính tả, vì vậy bạn có thể bỏ qua thẳng để xếp hạng.

Cập nhật : Kể từ đó, tôi đã tìm thấy một mô tả thuật toán tương tự như điều này, Tìm kiếm Phân tán FAROO . Đây vẫn là một tìm kiếm giới hạn khoảng cách chỉnh sửa, nhưng nó rất nhanh vì bước tính toán trước hoạt động giống như ý tưởng "hàm băm xấu" của tôi. FAROO chỉ sử dụng một khái niệm hạn chế về một hàm băm xấu.


Cảm ơn bạn đã tham khảo thuật toán SymSpell của Faroos. Mặc dù cả hai thuật toán đều tính toán trước các lỗi chính tả có thể xảy ra và sử dụng bảng băm để tra cứu nhanh, sự khác biệt chính là SymSpell đảm bảo phát hiện tất cả các lỗi chính tả có thể có trong khoảng cách chỉnh sửa nhất định (về mặt này SymSpell tương đương với thuật toán của Peter Norvig, chỉ Nhanh hơn 3..6 bậc độ lớn), trong khi thuật toán của bạn đang sử dụng phương pháp tiếp cận theo phương pháp heuristic sẽ chỉ phát hiện một tập hợp con giới hạn của tất cả các lỗi chính tả có thể có về mặt lý thuyết (do đó, chi phí tính toán trước của bạn có thể thấp hơn).
Wolf Garbe,

Thuật toán SymSpell tính toán trước rõ ràng và lưu trữ các lỗi chính tả có thể xảy ra, lược đồ "băm xấu" của tôi thì không. Đối với tiếng Anh, việc chỉ thêm một hàm băm phiên âm đơn giản bao hàm rất nhiều mặt đất (ví dụ: "terradacktle" -> "pterodactyl", có khoảng cách chỉnh sửa là 6). Đúng là, nếu bạn cần tra cứu đa ngôn ngữ, thì nó có thể khó hơn nhiều.
Adrian McCarthy

Hoàn toàn có thể, bằng cách khai thác kiến ​​thức thực nghiệm về những lỗi chính tả có thể xảy ra (và hạn chế những lỗi đó), bạn sẽ tiết kiệm được thời gian và không gian tính toán trước. Nhưng để bao gồm tất cả các lỗi chính tả có thể xảy ra, SymSpell chỉ cần tính toán trước một phần nhỏ trong số đó. Một từ gồm 5 chữ cái có thể có khoảng 3 triệu lỗi chính tả trong khoảng cách chỉnh sửa tối đa là 3, nhưng với SymSpell, bạn cần tính toán trước và chỉ lưu trữ 25 lần xóa. Điều này rất quan trọng đối với tìm kiếm mờ / tương tự ngoài việc sửa lỗi chính tả khi không có kiến ​​thức thực nghiệm.
Wolf Garbe

7

Thuật toán

  1. Lấy một từ sai chính tả làm đầu vào.
  2. Lưu trữ danh sách các từ tiếng Anh cùng với tần số của chúng trong một tệp văn bản.
  3. Chèn tất cả các từ tiếng Anh có sẵn (được lưu trữ trong tệp văn bản) cùng với tần suất của chúng (thước đo tần suất một từ được sử dụng trong ngôn ngữ tiếng Anh) trong Cây tìm kiếm bậc ba.
  4. Bây giờ đi dọc theo Cây tìm kiếm bậc ba -
    • Đối với mỗi từ gặp trong Cây tìm kiếm bậc ba, hãy tính Khoảng cách Levensthein của nó với từ viết sai.
    • Nếu Khoảng cách Levensthein <= 3, hãy lưu trữ từ đó trong Hàng đợi Ưu tiên.
    • Nếu hai từ có cùng khoảng cách chỉnh sửa, từ có tần số cao hơn sẽ là grater. In 10 mục hàng đầu từ Hàng đợi Ưu tiên.

Tối ưu hóa

  1. Bạn có thể chọn các từ trong cây con của nút hiện tại nếu khoảng cách chỉnh sửa của chuỗi con của từ đầu vào từ từ hiện tại lớn hơn 3.
    Bạn có thể tìm thấy giải thích chi tiết hơn và mã nguồn trên dự án github .

Rất tiếc, khoảng cách Levenshtein từ 'grater' đến 'lớn hơn' trong trường hợp này là không đủ, vì 'grater' cũng là một từ trong từ điển. ;-)
Tony Brasunas

1
@TonyBrasunas, Vâng, bạn nói đúng. Nhưng chương trình sẽ thực sự trả về danh sách 10 từ trong trường hợp đầu vào là 'grater' và nó sẽ đề xuất 'grater' với khoảng cách chỉnh sửa là 0 và cũng 'lớn hơn' với khoảng cách chỉnh sửa là 1. Điều này có thể hữu ích. ;)
amarjeetVà

Nếu một ứng viên có khoảng cách là 2 nhưng cực kỳ thường xuyên, và ứng viên khác có khoảng cách là 1 nhưng cực kỳ hiếm, bạn xếp hạng hai ứng viên như thế nào? Trong cách tiếp cận trên, vật phẩm hiếm sẽ luôn giành chiến thắng, đây có phải là kết quả đúng không?
bay cao tốc

@speedplane Có. người hiếm sẽ thắng. Và tôi nghĩ đó là kết quả phù hợp. Trở thành những gì chúng tôi mong đợi là từ gần nhất, dựa trên cách viết của từ đầu vào. Nếu bạn vẫn còn nghi ngờ, hãy nghĩ theo cách này --- giả sử có một từ hiếm hoi mà người dùng viết đúng chính tả. Bây giờ khoảng cách của nó là 0 nhưng tần số rất thấp. Bây giờ trong các gợi ý, chúng ta nên liệt kê từ hiếm này (với khoảng cách 0) ở trên cùng (vì ít chỉnh sửa chiến thắng khoảng cách nhất) và các từ khác có khoảng cách 1-2-3, bên dưới.
amarjeetVà

3

Bạn không cần biết khoảng cách chỉnh sửa chính xác cho từng từ trong từ điển. Bạn có thể dừng thuật toán sau khi đạt đến giá trị giới hạn và loại trừ từ đó. Điều này sẽ giúp bạn tiết kiệm rất nhiều thời gian tính toán.


1

Trình kiểm tra chính tả rất dễ thực hiện như trong chương trình chính tả Unix. Mã nguồn có sẵn công khai. Việc chỉnh sửa có thể được thực hiện, một kỹ thuật là thực hiện chỉnh sửa và kiểm tra lại xem từ mới này có trong từ điển hay không. Các chỉnh sửa mới như vậy có thể được nhóm lại và hiển thị cho người dùng.

Hệ thống Unix sử dụng chương trình do Mc IllRoy viết. Một cách khác là sử dụng Trie có thể hữu ích trong trường hợp tệp lớn.

Phương pháp unix cần rất ít dung lượng cho một từ điển khổng lồ vì nó sử dụng thuật toán băm phân tán.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.