การเปรียบเทียบสตริงฟัซซีประสิทธิภาพสูงใน Python ให้ใช้ Levenshtein หรือ difflib [ปิด]


130

ฉันกำลังทำการฟื้นฟูข้อความทางคลินิก (ตรวจการสะกด) ซึ่งฉันตรวจสอบแต่ละคำเทียบกับพจนานุกรมทางการแพทย์ 900,000 คำ ฉันกังวลมากขึ้นเกี่ยวกับความซับซ้อนของเวลา / ประสิทธิภาพ

ฉันต้องการเปรียบเทียบสตริงที่คลุมเครือ แต่ฉันไม่แน่ใจว่าควรใช้ไลบรารีใด

ตัวเลือกที่ 1:

import Levenshtein
Levenshtein.ratio('hello world', 'hello')

Result: 0.625

ทางเลือกที่ 2:

import difflib
difflib.SequenceMatcher(None, 'hello world', 'hello').ratio()

Result: 0.625

ในตัวอย่างนี้ทั้งสองให้คำตอบเดียวกัน คุณคิดว่าทั้งคู่ทำงานเหมือนกันในกรณีนี้หรือไม่?

คำตอบ:


154

ในกรณีที่คุณสนใจในการเปรียบเทียบภาพอย่างรวดเร็วของความคล้ายคลึงกันของ Levenshtein และ Difflib ฉันคำนวณทั้งสองเรื่องสำหรับหนังสือประมาณ 2.3 ล้านเล่ม:

import codecs, difflib, Levenshtein, distance

with codecs.open("titles.tsv","r","utf-8") as f:
    title_list = f.read().split("\n")[:-1]

    for row in title_list:

        sr      = row.lower().split("\t")

        diffl   = difflib.SequenceMatcher(None, sr[3], sr[4]).ratio()
        lev     = Levenshtein.ratio(sr[3], sr[4]) 
        sor     = 1 - distance.sorensen(sr[3], sr[4])
        jac     = 1 - distance.jaccard(sr[3], sr[4])

        print diffl, lev, sor, jac

จากนั้นฉันก็วางแผนผลลัพธ์ด้วย R:

ใส่คำอธิบายภาพที่นี่

อย่างเคร่งครัดสำหรับคนที่อยากรู้อยากเห็นฉันยังเปรียบเทียบค่าความคล้ายคลึงกันของ Difflib, Levenshtein, Sørensenและ Jaccard:

library(ggplot2)
require(GGally)

difflib <- read.table("similarity_measures.txt", sep = " ")
colnames(difflib) <- c("difflib", "levenshtein", "sorensen", "jaccard")

ggpairs(difflib)

ผลลัพธ์: ใส่คำอธิบายภาพที่นี่

ความคล้ายคลึงกันของ Difflib / Levenshtein นั้นน่าสนใจทีเดียว

2018 แก้ไข: ถ้าคุณกำลังทำงานในการระบุสตริงที่คล้ายกันคุณยังสามารถตรวจสอบ minhashing - มีภาพรวมที่ดีที่นี่ Minhashing นั้นยอดเยี่ยมมากในการค้นหาความคล้ายคลึงกันในคอลเล็กชันข้อความขนาดใหญ่ในเวลาเชิงเส้น ห้องปฏิบัติการของฉันรวบรวมแอปที่ตรวจจับและแสดงภาพการนำข้อความมาใช้ซ้ำโดยใช้ minhashing ที่นี่: https://github.com/YaleDHLab/intertext


2
นี่มันสุดยอดมาก! แล้วคุณจะทำอะไรกับเรื่องนี้? Levenshtein ไม่เหมาะสำหรับสตริงความยาวหัวเรื่องหรือไม่?
Ulf Aslak

3
ขึ้นอยู่กับสิ่งที่คุณพยายามจับในเมตริกความคล้ายคลึงกันของคุณ ...
duhaime

2
ฉันคิดว่าอาจมีการอธิบายความไม่ลงรอยกันระหว่าง difflib และ levenshtein เนื่องจากการแก้ปัญหาอัตโนมัติที่ใช้โดย difflib จะเกิดอะไรขึ้นถ้าคุณปิดการใช้งาน
Michael

2
นั่นเป็นคำถามที่ดี ตัวกรอง autojunk จะมีผลก็ต่อเมื่อจำนวนการสังเกต> 200 ดังนั้นฉันไม่แน่ใจว่าชุดข้อมูลนี้ (ชื่อหนังสือ) จะได้รับผลกระทบอย่างมากหรือไม่ แต่ก็คุ้มค่าที่จะตรวจสอบ ...
duhaime

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

105
  • difflib.SequenceMatcher ใช้อัลกอริทึมRatcliff / Obershelp ซึ่งคำนวณจำนวนอักขระที่ตรงกันสองเท่าหารด้วยจำนวนอักขระทั้งหมดในสองสตริง

  • Levenshtein ใช้อัลกอริทึม Levenshtein ซึ่งคำนวณจำนวนการแก้ไขขั้นต่ำที่จำเป็นในการแปลงสตริงหนึ่งเป็นอีกสตริง

ความซับซ้อน

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

Levenshtein คือ O (m * n) โดยที่ n และ m คือความยาวของสตริงอินพุตสองสาย

ประสิทธิภาพ

ตามซอร์สโค้ดของโมดูล Levenshtein: Levenshtein มีการทับซ้อนกับ difflib (SequenceMatcher) รองรับเฉพาะสตริงไม่ใช่ประเภทลำดับตามอำเภอใจ แต่ในทางกลับกันมันเร็วกว่ามาก


ขอบคุณมากสำหรับข้อมูล ฉันได้เพิ่มรายละเอียดเพิ่มเติม นี่คือ: I am doing clinical message normalization (spell check) in which I check each given word against 900,000 word medical dictionary. I am more concern about the time complexity/performance.คุณคิดว่าทั้งคู่ทำงานเหมือนกันในกรณีนี้หรือไม่
Maggie
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.