คำนวณระยะทาง Levenshtein อย่างรวดเร็ว


24

ให้ฐานข้อมูลขนาดใหญ่ของคำที่อนุญาต (เรียงตามตัวอักษร) และคำค้นหาคำจากฐานข้อมูลที่ใกล้เคียงที่สุดกับคำที่กำหนดในแง่ของระยะทาง Levenshtein

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

ฉันสงสัยว่ามีวิธีแก้ไขปัญหานี้ที่มีประสิทธิภาพมากกว่านี้หรือไม่ บางทีฮิวริสติกบางตัวที่ช่วยให้เราลดจำนวนคำที่จะค้นหาหรือปรับให้เหมาะสมกับอัลกอริทึมระยะทางเลเวนเทน

ลิงค์ไปยังเอกสารในเรื่องยินดีต้อนรับ

คำตอบ:


16

สิ่งที่คุณถามเกี่ยวกับปัญหาของการค้นหาเพื่อนบ้านใกล้เคียงภายใต้ระยะทางแก้ไข คุณไม่ได้พูดถึงว่าคุณสนใจในผลลัพธ์ทางทฤษฎีหรือการวิเคราะห์พฤติกรรมหรือไม่ดังนั้นฉันจะตอบก่อน

ระยะทางในการแก้ไขนั้นค่อนข้างน่ารังเกียจสำหรับการสร้างโครงสร้างการค้นหาใกล้เพื่อนบ้าน ปัญหาหลักคือในฐานะที่เป็นตัวชี้วัดมันทำงาน (เรียงลำดับ) เหมือนตัวชี้วัดที่ไม่ดีอื่น ๆ ที่รู้จักกันดีเช่นสำหรับวัตถุประสงค์ในการลดขนาดและการประมาณ มีงานค่อนข้างมากในการอ่านในหัวข้อนี้และแหล่งข้อมูลที่ดีที่สุดของคุณคือชุดเอกสารโดยAlex Andoni : โดยทำตามคำแนะนำย้อนหลัง (ตัวอย่างจากกระดาษ FOCS 2010 ของเขา) คุณจะได้รับแหล่งข้อมูลที่ดี1


1
สิ่งที่ฉันรู้เกี่ยวกับช่องว่างการวัดมาจากความหมายดังนั้นคำถาม: มีงานแต่งงานที่ดี (สำหรับค่าใด ๆ ที่เหมาะสม) ของ Levenshtein metric เป็น ultrametric หรือไม่? Offhand ที่อาจก่อให้เกิดอัลกอริทึม binary-tree-ish
Neel Krishnaswami

ฉันไม่แน่ใจทั้งหมด ฉันสงสัยว่าคำตอบคือไม่ทั่วไป แต่ฉันไม่มีอะไรจะชี้ไปที่
Suresh Venkat

เอกสารฉบับที่สองเกี่ยวกับboytsov.info/pubsเป็นการสำรวจที่ดีของวิธีแก้ปัญหาที่เป็นไปได้สำหรับการค้นหาใกล้เพื่อนบ้านภายใต้ระยะทางแก้ไขของ Levenshtein และ Damereau-Levenshtein
a3nm

@NeelKrishnaswami การฝังลงใน ultrametric จะมีการบิดเบือนอย่างน้อยโดยที่dคือความยาวสตริง นี้ต่อไปนี้จากการบิดเบือนที่ถูกผูกไว้ที่ต่ำกว่าสำหรับการฝังลงในL 1เนื่องจากKrauthgamer และ Rabaniตั้งแต่ ultrametrics ฝัง isometrically เข้าไปในพื้นที่ยุคลิดซึ่งฝังเข้าไปใน isometrically L 1 Ω(logd)dL1L1
Sasho Nikolov


5

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

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

มีการปรับปรุงแนวคิดพื้นฐานนี้หลายประการ


1
คุณควรจะได้รวมถึงการเชื่อมโยงไปของคุณเก็บวิจัยทำซ้ำสำหรับกระดาษ
Dan D.

4

ทางออกที่ง่ายคือการเก็บคำว่าเป็นคู่ชีวิต จากนั้นคุณสามารถคำนวณระยะทาง Levenshtein ของคำสืบค้นกับ trie ด้วยอัลกอริทึมการเขียนโปรแกรมแบบไดนามิกมาตรฐานแทนการคำนวณกับแต่ละคำแยกกัน ความซับซ้อนเวลากรณีที่เลวร้ายที่สุดคือการไม่ได้ดีขึ้น asymptotically แต่ถ้าคุณขยายสาขาที่มีแนวโน้มมากที่สุดครั้งแรกที่คุณจะได้รับสิ่งที่ต้องการเวลาสำหรับระยะเวลาในการสอบถามตัวอักษรขนาดσและแก้ไขระยะkO(ม.k+1σk)ม.σk


4

ฉันเขียนคำตอบของคำถามที่คล้ายกันมากที่ cs.stackexchange.com ( /cs//a/2096/1490 ) จากนั้นฉันก็พบคำถามนี้ คำตอบมีสำหรับตัวอย่างการค้นหาที่อยู่ใกล้กับเพื่อนบ้านในระยะทางแก้ไข (เช่นขั้นตอนวิธีการขับสตริงซึ่งมีประมาณใกล้เคียงกับสตริงแบบสอบถามเป็นเพื่อนบ้านที่ใกล้ที่สุดของสตริงแบบสอบถาม) ฉันกำลังโพสต์ที่นี่เนื่องจากฉันไม่พบการอ้างอิงใด ๆ ที่ฉันให้ไว้ในคำตอบที่ให้ไว้ที่นี่


3

ฉันคิดว่าสิ่งที่คุณต้องการคืออัลกอริธึมของแว็กเนอร์ - ฟิสเชอร์: https://en.wikipedia.org/wiki/Wagner%E2%80%93Fischer_algorithmความเข้าใจที่สำคัญคือเนื่องจากพจนานุกรมที่คุณสำรวจข้ามถูกเรียงลำดับสองคำที่ต่อเนื่องกัน มีแนวโน้มที่จะแบ่งปันคำนำหน้าเป็นเวลานานดังนั้นคุณไม่จำเป็นต้องอัปเดตเมทริกซ์ทั้งหมดสำหรับการคำนวณระยะทางแต่ละครั้ง


2

คุณสามารถใช้คุณหมายถึงอะไร?

จากนั้นหาระยะทาง Levenshtein ระหว่างคำตอบที่ส่งกลับโดย "คุณหมายถึง" "และสตริงอินพุตโดยใช้ Dynamic Programming


ฉันไม่เข้าใจคำตอบนี้ คำถามถามว่าจะหาคำในพจนานุกรมขนาดใหญ่ที่มีระยะทางใกล้เคียงกับ Levenshtein ได้อย่างไรอย่างมีประสิทธิภาพไม่เกี่ยวกับวิธีคำนวณระยะทาง Levenshtein หรือเปรียบเทียบกับผลลัพธ์ของตัวตรวจการสะกดกล่องดำ ...
Huck Bennett

@Huck Bennett: ฉันคิดว่า @Grigory Javadyan กำลังสร้างDid you mean?ฟีเจอร์ นอกจากนี้Did you mean?จะส่งคืนคำที่อยู่ใกล้กับอินพุตที่กำหนดและทำได้อย่างมีประสิทธิภาพ :)
Pratik Deoghare

ฉันคิดว่าความคิดของคุณเป็นสิ่งที่ดี แต่ดูเหมือนว่ากริกอกำลังขอสิ่งที่ลึกกว่าและเฉพาะเจาะจงมากขึ้น
Huck Bennett

@Huck Bennett: ใช่คุณพูดถูก! :)
Pratik Deoghare

-1

วิธีหนึ่งคือการฝึกอบรมรูปแบบการเรียนรู้ของเครื่องเพื่อแมปคำศัพท์กับเวกเตอร์และแมประยะทางของเลเวนเทนเทนกับระยะทางยูคลิด จากนั้นคุณสามารถสร้าง KDTree จากเวกเตอร์สำหรับพจนานุกรมที่คุณต้องการใช้ ฉันสร้างสมุดบันทึก jupyter ที่ทำได้ที่นี่: https://gist.github.com/MichaelSnowden/9b8b1e662c98c514d571f4d5c20c3a03

ตามความเห็นของ DW:

  1. ขั้นตอนการฝึกอบรม = การไล่ระดับสีแบบสุ่มสุ่มพร้อมการไล่ระดับสีแบบปรับตัว
  2. ฟังก์ชั่นการสูญเสีย = หมายถึงข้อผิดพลาดกำลังสองระหว่างระยะทางแก้ไขจริงและระยะทางแบบยุคลิด
  3. ข้อมูลการฝึกอบรม = สตริงสุ่มระหว่าง 1 ถึง 32 ตัวอักษร (สามารถปรับปรุงได้ด้วยข้อมูลที่ตรงกับการแจกแจงทั่วไปของการพิมพ์ผิดปกติ)
  4. ผลเชิงปริมาณ: หลังจากการฝึกอบรมสำหรับ 150 ครั้งที่มีขนาดชุด 2048 (เวลากำแพง = ประมาณหนึ่งนาที) โดยใช้คำ embeddings 512 มิติกับชั้นที่ซ่อนอยู่หนึ่งชั้นข้อผิดพลาดแน่นอนโดยเฉลี่ยระหว่างระยะแก้ไขที่แท้จริงและระยะแก้ไขที่คาดการณ์ อยู่ที่ประมาณ 0.75 หมายถึงระยะการแก้ไขที่คาดการณ์ไว้นั้นประมาณหนึ่งตัวอักษร

สรุปโครงสร้างโมเดล:

  1. สร้างการฝังที่เรียนรู้สำหรับตัวละครแต่ละตัวรวมถึงตัวอักษรที่เป็นโมฆะ (ใช้ในภายหลังเพื่อแสดงข้อความด้านขวาในขีด จำกัด อักขระ)
  2. วางด้านขวาของข้อความด้วยอักขระ null จนกว่าจะถึงขีด จำกัด อักขระ (32)
  3. เชื่อมงานแต่งเหล่านี้
  4. เรียกใช้งานแต่งงานผ่านเครือข่ายประสาทส่งต่อเพื่อสร้างคำที่มีมิติต่ำกว่า (512- มิติ)
  5. ทำสิ่งนี้ทั้งสองคำ
  6. ค้นหาระยะทางแบบยุคลิดระหว่างเวกเตอร์
  7. ตั้งค่าการสูญเสียให้เป็นค่าคลาดเคลื่อนกำลังสองเฉลี่ยระหว่างระยะทาง Levenshtein จริงและระยะทางแบบยุคลิด

ข้อมูลการฝึกอบรมของฉันเป็นเพียงแค่สตริงสุ่ม แต่ฉันคิดว่าผลลัพธ์สามารถปรับปรุงได้จริงหากข้อมูลการฝึกอบรมเป็นคู่ (พิมพ์ผิด / แก้ไขคำ) ฉันลงเอยด้วยการใช้/usr/share/dict/wordsเพราะมันมีอยู่ทั่วไป


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

อย่างที่มันเป็น (ฉันคิดว่า) พอดีกับ CSTheory นั่นคือไม่มีความคิดในสิ่งที่แนะนำโดยเฉพาะและไม่มีเหตุผลทางทฤษฎีสำหรับมัน
ผ่อนผัน C.

@DW ขออภัยเกี่ยวกับเรื่องนี้ - ฉันได้ทำการแก้ไขที่สำคัญมากซึ่งควรจะครอบคลุมในกรณีที่ลิงก์ตกไป แม้ว่านี่จะไม่ใช่ทฤษฎี CS จริง ๆ เพราะมันไม่ใช่การวิจัย แต่ฉันคิดว่ามันเป็นวิธีปฏิบัติเพราะรวดเร็วและง่ายสำหรับการฝึกอบรมและการอนุมาน
michaelsnowden

1
คุณกำลังฝึกเกี่ยวกับสตริงสุ่ม ระยะทางที่คาดว่า Levenshtein ระหว่างสองสายดังกล่าวจะประมาณความยาวของสายอีกต่อไป ดังนั้นจึงเป็นเรื่องง่ายมากที่จะประมาณระยะทางนี้กับสตริงแบบสุ่ม แต่ไม่มีประโยชน์สำหรับการจัดการกับข้อมูลจริง ฉันสงสัยว่างานแต่งงานของคุณอาจเข้ารหัสความยาวของสายอักขระและดังนั้นคุณอาจสร้างวิธีที่แปลกใหม่ในการทำสิ่งเล็กน้อยและไร้ประโยชน์ นี่เป็นปัญหาของการใช้ ML มันอ่อนไหวต่อฟังก์ชั่นการสูญเสียที่คุณใช้
DW

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