อัลกอริทึมใดที่คุณจะใช้เพื่อความคล้ายคลึงกันของสตริงมากที่สุด


23

ฉันกำลังออกแบบปลั๊กอินเพื่อระบุเนื้อหาในหน้าเว็บต่างๆโดยอิงตามที่อยู่

ดังนั้นฉันอาจมีที่อยู่เดียวซึ่งดูเหมือน:

1 someawesome street, anytown, F100 211

หลังจากนี้ฉันอาจพบที่อยู่นี้ในรูปแบบที่แตกต่างกันเล็กน้อย

1 someawesome street, F100 211,

หรืออาจคลุมเครือ

someawesome street F100

เทคนิคเหล่านี้เป็นที่อยู่เดียวกัน แต่มีระดับความคล้ายคลึงกัน ฉันต้องการ a) สร้างตัวระบุที่ไม่ซ้ำกันสำหรับแต่ละที่อยู่เพื่อทำการค้นหาและ b) ค้นหาว่าที่อยู่ที่คล้ายกันปรากฏขึ้นเมื่อใด

ฉันควรดูอัลกอริทึม / เทคนิค / สตริงใด ระยะทางของ Levenshtein ดูเหมือนเป็นตัวเลือกที่ชัดเจน แต่สงสัยว่ามีวิธีการอื่นใดที่จะให้ยืมตัวเองที่นี่


"ระยะทางของ Levenshtein" ไม่ใช่อัลกอริทึม
gnasher729

เว้นเสียแต่ว่าคุณจะแนะนำการแยกวิเคราะห์เบื้องต้นระยะทาง Levenstein แบบดิบจะไม่ดีเท่านี้ คุณควรพยายามระบุคำที่อาจเป็นชื่อถนนเมืองและอื่น ๆ ที่อาจเป็นชื่อถนนหรือรหัสไปรษณีย์ จากนั้นอาจใช้ Levenstein กับสิ่งเหล่านี้ด้วยการจับคู่แบบคลุมเครือทางสถิติที่เลี้ยงด้วยสถานที่จริง / ชื่อถนน ไม่ใช่เรื่องง่าย :)

7
@gnasher: แต่ฟังก์ชั่นที่คำนวณระยะทาง Levenshtein เป็นอัลกอริทึม หากไม่มีฟังก์ชั่นดังกล่าวระยะทางของ Levenshtein ก็เป็นเพียงความอยากรู้อยากเห็น
Robert Harvey

ผมพบว่าคำอธิบายในทางปฏิบัติมากกับตัวอย่างที่นี่: เปรียบเทียบ algortihms' โดยสรุปพวกเขาแนะนำให้ใช้ความคล้ายคลึงกันของJaro-Winklerเนื่องจากอัลกอริทึมของ Levenstein ขึ้นอยู่กับความยาวของสตริงดังนั้นจึงไม่มีประโยชน์ที่จะเปรียบเทียบ
Sandra Meneses

โปรดทำคำตอบการเชื่อมโยงอย่างเดียวไม่ได้เขียน
Jan Doggen

คำตอบ:


14

อัลกอริทึมของ Levensteinขึ้นอยู่กับจำนวนของการแทรกการลบและการแทนที่ในสตริง

น่าเสียดายที่มันไม่ได้คำนึงถึงการสะกดผิดที่พบบ่อยซึ่งเป็นการขนย้ายของ 2 ตัวอักษร (เช่นบางคนที่น่ากลัวและบางคนที่น่ากลัว) ดังนั้นผมจึงต้องการมีประสิทธิภาพมากขึ้นขั้นตอนวิธีการ Damerau-Levenstein

ฉันไม่คิดว่ามันเป็นความคิดที่ดีที่จะใช้ระยะทางกับสายอักขระทั้งหมดเนื่องจากเวลาเพิ่มขึ้นอย่างฉับพลันเมื่อเปรียบเทียบกับความยาวของสายอักขระ แต่ยิ่งแย่ลงไปกว่านั้นเมื่อองค์ประกอบที่อยู่เช่น ZIP ถูกลบออกที่อยู่ที่แตกต่างกันโดยสิ้นเชิงอาจตรงกันได้ดีกว่า (วัดโดยใช้เครื่องคิดเลข Levenshtein ออนไลน์ ):

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)

ผลกระทบเหล่านี้มักทำให้ชื่อถนนสั้นลง

ดังนั้นคุณควรใช้อัลกอริธึมที่ชาญฉลาดกว่า ตัวอย่างเช่นArthur Ratz เผยแพร่ใน CodeProjectอัลกอริทึมสำหรับการเปรียบเทียบข้อความอัจฉริยะ อัลกอริทึมไม่พิมพ์ระยะทาง (แน่นอนว่ามันสามารถทำให้ดีขึ้นตามลำดับ) แต่มันระบุสิ่งที่ยากบางอย่างเช่นการย้ายบล็อกข้อความ (เช่นการสลับระหว่างเมืองและถนนระหว่างตัวอย่างแรกและตัวอย่างสุดท้ายของฉัน)

หากอัลกอริทึมดังกล่าวนั้นกว้างเกินไปสำหรับกรณีของคุณคุณควรทำงานโดยใช้ส่วนประกอบและเปรียบเทียบส่วนประกอบที่เปรียบเทียบได้เท่านั้น นี่ไม่ใช่เรื่องง่ายหากคุณต้องการแยกรูปแบบที่อยู่ใด ๆ ในโลก แต่ถ้าเป้าหมายมีความเฉพาะเจาะจงมากขึ้นพูดสหรัฐก็เป็นไปได้อย่างแน่นอน ตัวอย่างเช่น "ถนน", "เซนต์.", "สถานที่", "plazza" และการสะกดผิดปกติของพวกเขาสามารถเปิดเผยส่วนถนนของที่อยู่ส่วนที่สำคัญที่สุดซึ่งในหลักการจะเป็นตัวเลข รหัสไปรษณีย์จะช่วยในการค้นหาเมืองหรืออาจเป็นองค์ประกอบสุดท้ายของที่อยู่หรือหากคุณไม่ต้องการคาดเดาคุณสามารถค้นหารายชื่อเมือง (เช่นการดาวน์โหลดฐานข้อมูลรหัสไปรษณีย์ฟรี) จากนั้นคุณสามารถใช้ Damerau-Levenshtein กับส่วนประกอบที่เกี่ยวข้องเท่านั้น


สิ่งที่เกี่ยวกับการเรียงลำดับสตริงการเปรียบเทียบทั้งสองก่อนการเปรียบเทียบ? ฉันพบว่าสิ่งนี้สามารถช่วยขนย้ายได้
openwonk

2

ระยะทางของ Levenshtein ดีกว่าสำหรับคำพูด

ถ้าคำพูด (ส่วนใหญ่) สะกดถูกต้องแล้วมองไปที่กระเป๋าของคำ ฉันอาจดูเหมือนมากกว่าฆ่า แต่TF-IDFและโคไซน์คล้ายคลึงกัน

หรือคุณสามารถใช้ Lucene ได้ฟรี ฉันคิดว่าพวกเขาทำโคไซน์ที่คล้ายคลึงกัน


1

ประการแรกคุณจะต้องแยกวิเคราะห์หน้าเว็บสำหรับที่อยู่ RegEx เป็นหนึ่งเขียนที่จะใช้ แต่มันอาจเป็นเรื่องยากมากที่จะแยกวิเคราะห์ที่อยู่โดยใช้ RegEx คุณอาจต้องดูรายการรูปแบบที่อยู่ที่อาจเกิดขึ้นและนิพจน์ที่ดีที่ตรงกับรูปแบบเหล่านั้น ฉันไม่คุ้นเคยกับการแยกวิเคราะห์ที่อยู่ แต่ฉันขอแนะนำให้ดูคำถามนี้ซึ่งตามมาด้วยแนวความคิดที่คล้ายกัน: ตัวแยกวิเคราะห์ที่อยู่ทั่วไปสำหรับข้อความอิสระ

ระยะทางของ Levenshtein นั้นมีประโยชน์ แต่หลังจากคุณแยกที่อยู่ออกเป็นส่วนต่างๆแล้ว พิจารณาที่อยู่ดังต่อไปนี้ 123 someawesome st.และ124 someawesome st.ที่อยู่เหล่านี้เป็นสถานที่ที่แตกต่างกันโดยสิ้นเชิง แต่ระยะทาง Levenshtein ของพวกเขาเป็นเพียง 1 เท่านั้นนอกจากนี้ยังสามารถนำไปใช้กับบางอย่างเช่น8th st.และ9th st.ชื่อถนนที่คล้ายกันจะไม่ปรากฏบนหน้าเว็บเดียวกัน แต่ไม่เคยได้ยินมาก่อน หน้าเว็บของโรงเรียนอาจมีที่อยู่ของห้องสมุดฝั่งตรงข้ามถนนหรือโบสถ์อยู่ห่างออกไปสองสามช่วงตึก ซึ่งหมายความว่าข้อมูลเดียวที่ระยะทาง Levenshtein ใช้งานได้ง่ายคือระยะทางระหว่างจุดข้อมูล 2 จุดเช่นระยะห่างระหว่างถนนและเมือง

เท่าที่คิดวิธีแยกเขตข้อมูลที่แตกต่างกันมันค่อนข้างง่ายเมื่อเราได้รับที่อยู่ด้วยตนเอง โชคดีที่ที่อยู่ส่วนใหญ่มาในรูปแบบที่เฉพาะเจาะจงมากด้วยตัวช่วยสร้าง RegEx เล็กน้อยคุณควรแยกพวกมันออกเป็นส่วนต่าง ๆ ของข้อมูล แม้ว่าที่อยู่จะไม่ได้รับการจัดรูปแบบที่ดี แต่ก็ยังมีความหวังอยู่บ้าง ที่อยู่เสมอ (เกือบ) ทำตามลำดับความสำคัญ ที่อยู่ของคุณควรอยู่ที่ไหนสักแห่งในตารางเส้นตรงเช่นนี้ขึ้นอยู่กับว่ามีข้อมูลมากน้อยเพียงใดและมันคืออะไร:

StreetNumber < Street < City < State < Country

มันเกิดขึ้นน้อยมากหากที่อยู่นั้นข้ามจากเขตข้อมูลหนึ่งไปยังเขตข้อมูลที่ไม่ติดกัน คุณจะไม่เห็นถนนในขณะนั้นประเทศหรือถนนแล้วตามด้วยเมืองบ่อยมาก


2
ยกเว้นที่อยู่ถนนนั้นไม่ปกติและไม่สามารถแยกวิเคราะห์ด้วยนิพจน์ทั่วไปได้อย่างน่าเชื่อถือ พวกเขาไม่สามารถระบุได้อย่างถูกต้องหากพวกเขาฝังอยู่ในข้อความฟรี แน่นอนคุณสามารถเขียนนิพจน์ทั่วไปที่แตกต่างกันสองสามแบบเพื่อจับคู่รูปแบบทั่วไปต่าง ๆ หากคุณทราบว่าคุณกำลังมองหาที่ใดอยู่
ไร้ประโยชน์

@ ไม่มีประโยชน์จริง เป็นไปได้ในทางทฤษฎี แต่ฉันประเมินปริมาณงานที่ต้องประเมินต่ำกว่านั้น โดยเฉพาะเมื่อมีตัวเลือกที่ดีกว่า ฉันแก้ไขคำตอบของฉันเพื่อสะท้อนสิ่งนี้
Ucenna

1

คุณถามเกี่ยวกับอัลกอริทึมความคล้ายคลึงกันของสตริง แต่สตริงของคุณเป็นที่อยู่ ฉันจะส่งที่อยู่ไปยัง API ตำแหน่งเช่นGoogle Place Searchและใช้formatted_addressเป็นจุดเปรียบเทียบ ดูเหมือนว่าวิธีการที่แม่นยำที่สุด

สำหรับสตริงที่อยู่ซึ่งไม่สามารถหาได้ผ่าน API คุณสามารถถอยกลับไปใช้อัลกอริธึมที่คล้ายคลึงกันได้


1
+1 Outsource เพื่อให้คุณได้รับพลังจากผู้เชี่ยวชาญในการทำงานให้คุณ ไม่จำเป็นต้องเป็น Google เนื่องจากมีผู้ให้บริการอยู่ไม่กี่ราย อย่าเสียเวลาทำสิ่งนี้เว้นแต่ว่าการจับคู่ที่อยู่เป็นธุรกิจหลักของคุณ
LoztInSpace

0

อัลกอริธึมสุดเจ๋งที่มีประโยชน์ แต่ต้องการฐานข้อมูลที่ตั้งไว้ล่วงหน้าของคำตอบก่อนหน้านี้เรียกว่า: ระยะทางแก้ไขเส้น

ระยะทางแก้ไขบรรทัดเป็นฟังก์ชั่นสามารถย้อนกลับ "แตกต่างกันแค่สองคำ"

คำเช่น "dogma" และ "dog" คุณจะได้รับกลับค่า 3 (สำหรับ 3 ตัวอักษรพิเศษ)

หรือ "cat" และ "hat" รับค่า 1 กลับมา (สำหรับอักขระที่ต่างกันหนึ่งตัว)

(ที่มา: https://en.wikipedia.org/wiki/Edit_distance )


2
ข้อดีของ Levensthtein ที่กล่าวถึงของ OP คืออะไร
Christophe

-1

แน่นอนว่าการใช้ฟังก์ชั่นระยะทางดูเหมือนว่าเป็นแนวทางที่ดี แต่ปัญหาก็คือการหาสตริงที่ใกล้เคียงที่สุดจากที่อยู่ที่กำหนดซึ่งอยู่ไกลจากเรื่องเล็กน้อย

คุณกำลังอธิบายอัลกอริทึมประเภทกว้าง ๆ ที่นี่ ลองค้นหาเพื่อนบ้านที่ใกล้ที่สุด

ดังที่ได้กล่าวไว้ในความคิดเห็นหากคุณพบวิธีแยกส่วนประกอบของที่อยู่ (ชื่อถนนหมายเลข ฯลฯ ) มันจะทำให้งานง่ายขึ้นมาก


-1

LongestCommonSubsequence (จาก Apache Commons-text) สามารถเป็นอีกวิธีหนึ่งในการลองใช้ที่อยู่ หากคุณกำหนดความคล้ายคลึงกันของทั้งสองเป็นอัตราส่วนของ " ความยาวส่วนต่อเนื่องทั่วไป / สูงสุด (ความยาวที่อยู่) " คุณจะสามารถใช้เกณฑ์ความคลาดเคลื่อนที่ยอมรับได้เช่น 0.8 ที่จะกำหนดการแข่งขัน / ไม่ตรงกัน วิธีนี้จะช่วยให้คุณสามารถจับคู่ที่อยู่เช่น " 1 someawesome st., anytown " และ " 1 someawesome st., anytown "

มันไม่ใช่อัลกอริทึมที่เร็วมากดังนั้นคุณอาจต้องการใช้การล้มเหลวอย่างรวดเร็วเพื่อลดการเปรียบเทียบ ตัวอย่างจะเป็น - หลีกเลี่ยงการเปรียบเทียบหากรหัสไปรษณีย์ไม่ตรงกันหรือแยกตัวเลขหลักเท่านั้นแตกต่างกัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.