Levenshtein mesafe: kelimelerden pozisyonları takas nasıl ele?

9 Cevap php

Ben PHP levenshtein function kullanarak dizeleri karşılaştırırken bazı başarı elde ettik.

Ancak, pozisyonları takas substrings içeren iki dizeleri için, algoritma yepyeni altdizgelerin gibi bu sayar.

Örneğin:

levenshtein("The quick brown fox", "brown quick The fox"); // 10 differences

sahip olarak kabul edilir less in common daha:

levenshtein("The quick brown fox", "The quiet swine flu"); // 9 differences

Ben first two daha çok benzer olduğunu gördüm bir algoritma tercih ederim.

Nasıl düzenlemeler için ayrı olarak pozisyon açtınız substrings belirleyebilir bir karşılaştırma fonksiyonu ile geliyor hakkında gidebiliriz?

Ben düşündüm, olası bir yaklaşım karşılaştırmadan önce, alfabetik içine dize tüm kelimeler koymaktır. Bu tamamen karşılaştırma dışarı kelimelerin orijinal sipariş alır. Bunun bir dezavantajı, ancak, kelimenin sadece ilk harfi değiştirilerek bir tek harf değiştirerek neden gerektiğini çok daha büyük bir kesinti oluşturabilirsiniz olmasıdır.

Ne elde etmek çalışıyorum ücretsiz metin dizeleri insanlar hakkında iki gerçekleri karşılaştırmak ve bu gerçekler aynı gerçeği göstermek için ne kadar büyük olasılıkla karar etmektir. Gerçekler Okul birisi, örneğin, işveren veya yayıncının adını katıldı olabilir. Iki kayıt aynı okul, farklı vb farklı bir sırayla kelimeleri, fazladan kelime, kılçıksız olabilir, bu yüzden eşleşen biz onlar aynı okula başvurmak iyi bir tahmin yapmak ise biraz bulanık olmalıdır. Yani-o kadar yazım hatalarını çok iyi çalışıyor (bu tüm üstüne metaphone benzer bir phoenetic algoritma kullanıyorum) ama çok kötü bir okulda ortak görünüyor etrafında kelimelerin sırasını geçerseniz: vs "xxx kolej" "xxx kolej".

9 Cevap

N-grams

Destekleyen, N-grams kullanın multiple-character transpositions across the whole text.

Genel bir fikir tüm olası 2-3 karakter altdizgelerin (n-gram) içine söz konusu iki dizeleri bölmek ve metrik kendi benzerlik olarak iki dizeleri arasında paylaşılan n-gram dizi tedavi olmasıdır. Bu da daha fazla dizge içinde n-gram toplam sayısı ile paylaşılan sayısına bölünmesiyle normalleştirilebilir. Bu hesaplamak için önemsiz, ama oldukça güçlü.

Örnek cümleler:

A. The quick brown fox
B. brown quick The fox
C. The quiet swine flu

A ve B grubu hisse 18 2-grams

A ve C paylaşmak sadece 8 2-grams

Mümkün 20 toplam dışarı.

Bu Gravano et al. paper 'de daha detaylı olarak tartışılmıştır.

tf-idf and cosine similarity

Bir çok önemsiz değildir, alternatif, ama bilgi teorisine dayanan term frequency–inverse document frequency (tf-idf) metrik benzerliği gibi cosine similarity, belirteçleri tartmak cümle vektörleri oluşturmak ve daha sonra kullanmak üzere bir terim kullanmak olacaktır.

Algoritma:

  1. Cümlenin başına 2 karakter belirteci frekansları (tf) hesaplayın.
  2. Calculate inverse sentence frequencies (idf), which is a logarithm of a quotient of the number of all sentences in the corpus (in this case 3) divided by the number of times a particular token appears across all sentences. In this case th is in all sentences so it has zero information content (log(3/3)=0). idf formula
  3. Produce the tf-idf matrix by multiplying corresponding cells in the tf and idf tables. tfidf
  4. Finally, calculate cosine similarity matrix for all sentence pairs, where A and B are weights from the tf-idf table for the corresponding tokens. The range is from 0 (not similar) to 1 (equal).
    cosine similarity
    similarity matrix

Levenshtein modifications and Metaphone

Regarding other answers. Damerau–Levenshtein modificication supports only the transposition of two adjacent characters. Metaphone was designed to match words that sound the same and not for similarity matching.

Onun kolay. Sadece harfler yerine kelimeleri Damerau-Levenshtein mesafeyi kullanın.

Sonra Levenshtein yapmak patlatmak, dizi sıralamak alanlarda patlayabilir.

Ayrıca bu deneyebilirsiniz. (Ekstra bir öneri sadece)

$one = metaphone("The quick brown fox"); // 0KKBRNFKS
$two = metaphone("brown quick The fox"); // BRNKK0FKS
$three = metaphone("The quiet swine flu"); // 0KTSWNFL

similar_text($one, $two, $percent1); // 66.666666666667
similar_text($one, $three, $percent2); // 47.058823529412
similar_text($two, $three, $percent3); // 23.529411764706

Bu 1. ve 2. bir ve üç ve iki ve üç daha benzer olduğunu gösterecektir.

Ben bir yazım denetleyicisi levenshtein uygulanması oldum.

Ne soruyorsun 1 düzenleme olarak transpozisyonları sayıyor.

Sadece uzak bir kelime transpozisyonları saymak istiyorsanız, bu kolaydır. Ancak kelime 2 veya daha fazla uzak aktarılması için, algoritmaya eklenmesi kötü senaryodur !(max(wordorder1.length(), wordorder2.length())). Zaten kuadratik algoritması doğrusal olmayan bir subalgorithm eklemek iyi bir fikir değildir.

Bu işe nasıl olduğunu.

if (wordorder1[n] == wordorder2[n-1])
{
  min(workarray[x-1, y] + 1, workarray[x, y-1] + 1, workarray[x-2, y-2]);
}
  else
{
  min(workarray[x-1, y] + 1, workarray[x, y-1] + 1);
}

SADECE dokunaklı Transpozisyonlar için. Tüm transpozisyonları istiyorsanız, geriye karşılaştırarak bu noktadan, her pozisyon iş için olurdu

1[n] == 2[n-2].... 1[n] == 2[0]....

Onlar standart yöntemi bu dahil değil neden Gördüğünüz.

this answer alın ve aşağıdaki değişikliği yapın:

void match(trie t, char* w, string s, int budget){
  if (budget < 0) return;
  if (*w=='\0') print s;
  foreach (char c, subtrie t1 in t){
    /* try matching or replacing c */
    match(t1, w+1, s+c, (*w==c ? budget : budget-1));
    /* try deleting c */
    match(t1, w, s, budget-1);
  }
  /* try inserting *w */
  match(t, w+1, s + *w, budget-1);
  /* TRY SWAPPING FIRST TWO CHARACTERS */
  if (w[1]){
    swap(w[0], w[1]);
    match(t, w, s, budget-1);
    swap(w[0], w[1]);
  }
}

Bu bir tray sözlük arama için, ama bir tek kelime eşleştirme için, aynı fikir. Sen şube ve bağlı yapıyoruz ve herhangi bir noktada, sürece bunu bir maliyet vermek gibi, istediğiniz herhangi bir değişiklik yapabilirsiniz.

Iki dizeleri arasında yinelenen sözcükleri eleyin ve sonra Levenshtein kullanın.

ben bu vector-space search engine kullanmak için bir örnektir inanıyorum.

Bu teknikte, her belge aslında farklı sözcükler tüm korpus olduğu gibi birçok boyutları olan bir vektör haline gelir; benzer belgeler daha sonra bu vektör uzayında komşu alanları işgal. Bu modelin bir güzel özelliği sorguları da sadece belgelerin olmasıdır: Bir sorguyu yanıtlamak için, sadece vektör uzayda konumlarını hesaplamak ve sonuç bulabileceğiniz en yakın belgelerdir. Ben orada PHP için gitmek olsun-ve-çözümleri vardır eminim.

Vektör uzayı sonuçları fuzzify için, sen kaynaklanan / benzer doğal dil işleme tekniği yapmak için düşünün ve genel kelime meydana benzer kelimeler için ikincil sorguları oluşturmak için Levenshtein kullanabilirsiniz.

İlk dize A ve ikinci bir B ise:

  1. Kelimeleri içine bölünmüş A ve B
  2. A her kelime için, (Levenshtein kullanarak) B en iyi eşleşen kelimeyi bulmak
  3. B o kelimeyi kaldır ve A. eşleşen kelime olarak aynı dizin B * koydum
  4. Şimdi * A ve B karşılaştırın

Örnek:

A: The quick brown fox
B: Quick blue fox the
B*: the Quick blue fox

Sen vb * B bir arkadaşı var henüz yok bir kelime, daha az yakın maçta, için yakın eşleşmeleri bulma sonra, ilk başta sadece tam eşleşen bulma, birden fazla geçiş bunu yaparak adım 2 artırabilirsiniz