Thuật toán nào bạn sẽ sử dụng tốt nhất cho sự tương tự chuỗi?


23

Tôi đang thiết kế một plugin để xác định duy nhất nội dung trên các trang web khác nhau, dựa trên địa chỉ.

Vì vậy, tôi có thể có một địa chỉ giống như:

1 someawesome street, anytown, F100 211

sau này tôi có thể tìm thấy địa chỉ này ở một định dạng hơi khác.

1 someawesome street, F100 211,

hoặc có lẽ mơ hồ như

someawesome street F100

Về mặt kỹ thuật là cùng một địa chỉ, nhưng có mức độ tương tự nhau. Tôi muốn a) tạo một mã định danh duy nhất cho mỗi địa chỉ để thực hiện tra cứu và b) tìm ra khi một địa chỉ rất giống nhau xuất hiện.

Những thuật toán / kỹ thuật / số liệu chuỗi nào tôi nên xem xét? Khoảng cách Levenshtein có vẻ như là một lựa chọn rõ ràng, nhưng tò mò liệu có cách tiếp cận nào khác sẽ cho vay ở đây không.


"Khoảng cách Levenshtein" không phải là một thuật toán.
gnasher729

Trừ khi bạn giới thiệu một số phân tích cơ bản, khoảng cách Levenstein thô sẽ không tốt. Bạn nên cố gắng ít nhất xác định các từ có thể là đường phố, tên thị trấn, v.v. và những từ có thể là số đường phố hoặc mã zip. Sau đó, có thể áp dụng Levenstein trên những điều này với một số đối sánh mờ thống kê được cung cấp bởi các địa điểm / tên đường phố thực. Không phải là một điều dễ dàng :)

7
@gnasher: Nhưng một hàm tính khoảng cách Levenshtein một thuật toán. Không có chức năng như vậy, khoảng cách Levenshtein chỉ là một sự tò mò trí tuệ.
Robert Harvey

Tôi tìm thấy một lời giải thích rất thực tế với các ví dụ ở đây: so sánh của algortihms . Để kết luận, họ khuyên nên sử dụng độ tương tự của Jaro-Winkler vì thuật toán của Levenstein phụ thuộc vào độ dài của chuỗi, vì vậy không hữu ích khi so sánh.
Sandra Meneses

Câu trả lời:


14

Thuật toán của Levenstein dựa trên số lần chèn, xóa và thay thế trong chuỗi.

Thật không may, nó không tính đến một lỗi chính tả phổ biến, đó là sự hoán vị của 2 ký tự (ví dụ: someawgie vs someaewsome). Vì vậy, tôi thích thuật toán Damerau-Levenstein mạnh mẽ hơn .

Tôi không nghĩ nên áp dụng khoảng cách trên toàn bộ chuỗi vì thời gian tăng đột ngột với độ dài của chuỗi so với. Nhưng thậm chí tệ hơn, khi các thành phần địa chỉ, như ZIP bị xóa, các địa chỉ hoàn toàn khác nhau có thể phù hợp hơn (được đo bằng máy tính Levenshtein trực tuyến ):

1 someawesome street, anytown, F100 211       (reference) 
1 someawesome st.,anytown                     (difference of 15, same address)     
1 otherplaces street,anytown,F100211          (difference of 13, different ddress) 
1 sameawesome street, othertown, CA98200      (difference of 13, different ddress)
anytown, 1 someawesome street                 (28 different same address)
anytown, F100 211, 1 someawesome street       (37 different same address)

Những hiệu ứng này có xu hướng xấu đi cho tên đường ngắn hơn.

Vì vậy, bạn nên sử dụng các thuật toán thông minh hơn. Ví dụ, Arthur Ratz đã xuất bản trên CodeProject một thuật toán để so sánh văn bản thông minh. Thuật toán không in ra một khoảng cách (chắc chắn nó có thể được làm giàu tương ứng), nhưng nó xác định một số điều khó khăn như di chuyển các khối văn bản (ví dụ: hoán đổi giữa thị trấn và đường phố giữa ví dụ đầu tiên của tôi và ví dụ cuối cùng của tôi).

Nếu một thuật toán như vậy quá chung chung cho trường hợp của bạn, thì bạn nên thực sự làm việc theo các thành phần và chỉ so sánh các thành phần tương đương. Đây không phải là một điều dễ dàng nếu bạn muốn phân tích bất kỳ định dạng địa chỉ nào trên thế giới. Nhưng nếu mục tiêu cụ thể hơn, nói Mỹ, điều đó chắc chắn là khả thi. Ví dụ: "đường phố", "st.", "Place", "plazza" và các lỗi chính tả thông thường của chúng có thể tiết lộ phần đường của địa chỉ, phần chính trong đó về nguyên tắc sẽ là số. Mã ZIP sẽ giúp xác định vị trí thị trấn, hoặc có thể là phần tử cuối cùng của địa chỉ hoặc nếu bạn không muốn đoán, bạn có thể tìm danh sách tên thành phố (ví dụ: tải xuống cơ sở dữ liệu mã zip miễn phí). Sau đó, bạn chỉ có thể áp dụng Damerau-Levenshtein trên các thành phần có liên quan.


Điều gì về việc sắp xếp cả hai chuỗi so sánh trước khi so sánh? Tôi đã thấy rằng điều này có thể giúp chuyển vị.
openwonk

2

Khoảng cách Levenshtein là tốt hơn cho các từ

Nếu các từ (chủ yếu) viết đúng chính tả thì hãy nhìn vào túi các từ . Tôi có thể thích giết hơn nhưng tương tự TF-IDFcosine .

Hoặc bạn có thể sử dụng Lucene miễn phí. Tôi nghĩ rằng họ làm tương tự cosine.


1

Đầu tiên, bạn phải phân tích trang web để tìm địa chỉ, RegEx là một địa chỉ được viết, tuy nhiên có thể rất khó phân tích địa chỉ bằng RegEx. Bạn có thể sẽ phải trải qua một danh sách các định dạng địa chỉ tiềm năng và một hoặc nhiều biểu thức phù hợp với chúng. Tôi không quá quen thuộc với phân tích địa chỉ, nhưng tôi khuyên bạn nên xem câu hỏi này theo một dòng suy nghĩ tương tự: Trình phân tích địa chỉ chung cho văn bản dạng tự do.

Khoảng cách Levenshtein rất hữu ích nhưng chỉ sau khi bạn tách địa chỉ thành các phần của nó. Hãy xem xét các địa chỉ sau. 123 someawesome st.124 someawesome st.Các địa chỉ này là các địa điểm hoàn toàn khác nhau, nhưng khoảng cách Levenshtein của chúng chỉ là 1. Điều này cũng có thể được áp dụng cho một cái gì đó giống như 8th st.9th st.các tên đường tương tự thường không xuất hiện trên cùng một trang web, nhưng nó không phải là chưa từng thấy. Ví dụ, trang web của trường có thể có địa chỉ thư viện bên kia đường hoặc nhà thờ cách đó vài dãy nhà. Điều này có nghĩa là dữ liệu duy nhất khoảng cách Levenshtein có thể dễ dàng sử dụng là khoảng cách giữa 2 điểm dữ liệu, chẳng hạn như khoảng cách giữa đường phố và thành phố.

Theo như cách tìm ra cách tách các trường khác nhau, thật đơn giản một khi chúng ta có được địa chỉ. Rất may, hầu hết các địa chỉ đều có các định dạng rất cụ thể, với một chút thuật sĩ RegEx, có thể tách chúng thành các trường dữ liệu khác nhau. Ngay cả khi địa chỉ không được định dạng tốt, vẫn có một số hy vọng. Địa chỉ luôn luôn (gần như) theo thứ tự độ lớn. Địa chỉ của bạn sẽ nằm ở đâu đó trên lưới tuyến tính như thế này tùy thuộc vào lượng thông tin được cung cấp và địa chỉ:

StreetNumber < Street < City < State < Country

Nó hiếm khi xảy ra, nếu tất cả các địa chỉ bỏ qua từ một trường đến một không liền kề. Bạn sẽ không thường xuyên thấy Phố, Quốc gia hoặc Phố số, sau đó là Thành phố.


2
Ngoại trừ việc các địa chỉ đường phố không thường xuyên và không thể được phân tích cú pháp bằng các biểu thức thông thường. Họ chắc chắn không thể được xác định chính xác nếu họ chỉ được nhúng trong văn bản miễn phí. Tất nhiên, bạn có thể viết một vài biểu thức chính quy khác nhau để khớp với các định dạng phổ biến khác nhau, nếu bạn đã biết bạn đang tìm kiếm ở đâu.
Vô dụng

@ Vô dụng Đó là sự thật. Về mặt lý thuyết thì có thể thực hiện được, nhưng tôi đã đánh giá thấp khối lượng công việc cần thiết để đưa vào đó. Đặc biệt là khi có những lựa chọn tốt hơn có sẵn. Tôi đã sửa đổi câu trả lời của mình để phản ánh điều này.
Ucenna

1

Bạn hỏi về thuật toán tương tự chuỗi nhưng chuỗi của bạn là địa chỉ. Tôi sẽ gửi địa chỉ tới API vị trí, chẳng hạn như Tìm kiếm địa điểm của Google và sử dụng formatted_addresslàm điểm so sánh. Đó dường như là cách tiếp cận chính xác nhất.

Đối với các chuỗi địa chỉ không thể được định vị thông qua API, sau đó bạn có thể quay lại các thuật toán tương tự.


1
+1 Thuê ngoài nó để bạn có được sức mạnh của các chuyên gia để thực hiện công việc cho bạn. Không phải là Google vì có một vài nhà cung cấp dịch vụ ngoài kia. Đừng lãng phí thời gian của bạn để làm điều này trừ khi khớp địa chỉ là công việc cốt lõi của bạn.
LoztInSpace

0

Một thuật toán tuyệt vời hữu ích nhưng yêu cầu cơ sở dữ liệu đặt trước các câu trả lời trước được gọi là: Khoảng cách chỉnh sửa dòng.

Khoảng cách chỉnh sửa dòng, như một hàm, có thể trả về "hai từ đó khác nhau bao nhiêu".

Một từ như "giáo điều" và "chó", bạn sẽ nhận lại giá trị là 3 (cho 3 ký tự phụ).

Hoặc "mèo" và "mũ", lấy lại giá trị 1 (cho một nhân vật khác nhau).

(Nguồn: https://en.wikipedia.org/wiki/Edit_distance )


2
Lợi thế so với Levensthtein đã đề cập của OP là gì?
Barshe

-1

Thực sự sử dụng một số chức năng khoảng cách có vẻ như một cách tiếp cận tốt. Nhưng vấn đề sau đó là tìm chuỗi gần nhất từ ​​một địa chỉ nhất định, khác xa với tầm thường.

Bạn đang mô tả một loại rộng các thuật toán ở đây. Kiểm tra tìm kiếm hàng xóm gần nhất

Như đã đề cập trong một nhận xét, nếu bạn tìm cách tách các thành phần của địa chỉ (tên đường, số, v.v.), nó sẽ giúp công việc dễ dàng hơn nhiều.


-1

LongestCommonSub resultence (từ Apache commons-text) có thể là một cách tiếp cận khác để thử với các địa chỉ. Nếu bạn xác định độ tương tự của hai là tỷ lệ " chiều dài / tối đa chung (độ dài địa chỉ) ", thì bạn có thể áp dụng ngưỡng dung sai - ví dụ: 0,8 sẽ xác định khớp / không khớp. Bằng cách này, nó sẽ cho phép bạn khớp các địa chỉ như " 1 someawgie st. Anytown " và " 1 someawgie street., Anytown ".

Nó không phải là thuật toán siêu nhanh, vì vậy bạn có thể muốn áp dụng các lỗi nhanh để giảm thiểu so sánh. Ví dụ sẽ là - tránh so sánh nếu mã zip không khớp hoặc chuỗi chỉ trích xuất chữ số là khác nhau.

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.