2016-06-22 59 views
5

Quindi, sto cercando di implementare la logica della logica Fuzzy nella mia azienda e di avere problemi a ottenere buoni risultati. Per cominciare, sto cercando di abbinare i nomi delle aziende con quelli di un elenco fornito da altre società.
Il mio primo tentativo è stato quello di utilizzare soundex, ma sembra che soundex paragoni solo i primi suoni nel nome della società, quindi i nomi di società più lunghi erano troppo facilmente confusi l'uno con l'altro.
Ora sto lavorando al mio secondo tentativo utilizzando il confronto della distanza di levenstein. Sembra promettente, soprattutto se rimuovo prima la punteggiatura. Tuttavia, sto ancora avendo difficoltà a trovare i duplicati senza troppi falsi positivi.
Uno dei problemi che ho sono aziende come widgetsco vs widgets inc. Quindi, se confronto la sottostringa della lunghezza del nome più breve, raccolgo anche cose come il campus della BBC University e della CBC University. Sospetto che una soluzione utilizzando una combinazione di distanza e la più lunga sottostringa comune possa essere la soluzione.
Qualcuno è riuscito a creare un algoritmo che esegua tale abbinamento con falsi positivi limitati?Corrispondenza logica fuzzy

+0

L'unico abbinamento che abbia mai dovuto fare era basato sulla corrispondenza della sottostringa ad es. BBC Uni e BBC University. Ciò presuppone che la parte iniziale della stringa sia la stessa tra tutti i duplicati. Per casi come: widgets inc vorrei innanzitutto eliminare le abbreviazioni di tipo entità. Se disponi di altri dati correlati, ad es. L'indirizzo della società, amministratore delegato della società, quindi anche questo, può essere paragonato per produrre un punteggio della probabilità che due società siano le stesse. Mi concentrerei sulla normalizzazione dei dati prima (rimuovendo il fluff) prima di provare a confrontarlo effettivamente. – Alex

+0

Rimozione del fluff è in genere una buona pratica, non importa quale algoritmo si utilizza. – Yobik

+0

Elaborerò sulla normalizzazione dei dati. Per casi come "Smith & Wesson" abbinati a "Smith and Wesson", convertirei tutti "&" in "e" ai fini di una partita. Vorrei anche provare a rimuovere i tipi di entità e le loro abbreviazioni (inc. Co.) E verificare se questo dà falsi positivi. Se i dati hanno costrutti più complessi, ad es. "CompanyA trading as CompanyB", quindi devono essere analizzati. IMO, fuzzy che combina dati ben strutturati come i nomi delle aziende è uno strumento sbagliato per il lavoro. – Alex

risposta

0

Si desidera utilizzare qualcosa come Levenshtein Distance o un altro algoritmo di confronto delle stringhe. Potresti dare un'occhiata a questo progetto su Codeplex.

http://fuzzystring.codeplex.com/

+0

Mi piace Levenshtein Distance ma il problema è che non è "sfocato". La distanza tra 'CBC University' e 'CBC Univer' è 4 anche se probabilmente sono lo stesso posto.Questo post SO ha un bel "fuzzy" Levenshtein [Ricerca Fuzzy SQL Server con percentuale di corrispondenza] (http://stackoverflow.com/questions/26259117/sql-server-fuzzy-search-with-percentage-of-match) – user918967

0

Si sta utilizzando Access? Se è così, considera il carattere '*', senza le virgolette. Se utilizzi SQL Server, utilizza il carattere '%'. Tuttavia, questa non è una logica fuzzy, è davvero l'operatore Like. Se hai davvero bisogno di logica fuzzy, esporta il set di dati in Excel e carica AddIn dall'URL sottostante.

https://www.microsoft.com/en-us/download/details.aspx?id=15011

Leggere attentamente le istruzioni. Funziona sicuramente, e funziona benissimo, ma devi seguire le istruzioni e non è completamente intuitivo. La prima volta che l'ho provato, non ho seguito le istruzioni e ho perso un sacco di tempo cercando di farlo funzionare. Alla fine ho capito, e ha funzionato benissimo !!

0

Abbiamo ottenuto buoni risultati sull'abbinamento del nome e dell'indirizzo utilizzando una funzione Metaphone creata da Lawrence Philips. Funziona in modo simile a Soundex, ma crea un modello suono/consonante per l'intero valore. Potresti trovarlo utile in combinazione con altre tecniche, specialmente se puoi eliminare alcuni dei fluff come "co". e 'inc.' come menzionato in altri commenti:

create function [dbo].[Metaphone](@str as nvarchar(70), @KeepNumeric as bit = 0) 
returns nvarchar(25) 
    /* 
    Metaphone Algorithm 

    Created by Lawrence Philips. 
    Metaphone presented in article in "Computer Language" December 1990 issue. 

       *********** BEGIN METAPHONE RULES *********** 
    Lawrence Philips' RULES follow: 
    The 16 consonant sounds: 
               |--- ZERO represents "th" 
               | 
      B X S K J T F H L M N P R 0 W Y 
    Drop vowels 

    Exceptions: 
    Beginning of word: "ae-", "gn", "kn-", "pn-", "wr-" ----> drop first letter 
    Beginning of word: "wh-"        ----> change to "w" 
    Beginning of word: "x"        ----> change to "s" 
    Beginning of word: vowel or "H" + vowel    ----> Keep it 

    Transformations: 
    B ----> B  unless at the end of word after "m", as in "dumb", "McComb" 
    C ----> X  (sh) if "-cia-" or "-ch-" 
      S  if "-ci-", "-ce-", or "-cy-" 
        SILENT if "-sci-", "-sce-", or "-scy-" 
      K  otherwise 
      K  "-sch-" 
    D ----> J  if in "-dge-", "-dgy-", or "-dgi-" 
      T  otherwise 
    F ----> F 
    G ---->   SILENT if "-gh-" and not at end or before a vowel 
           "-gn" or "-gned" 
           "-dge-" etc., as in above rule 
      J  if "gi", "ge", "gy" if not double "gg" 
      K  otherwise 
    H ---->   SILENT if after vowel and no vowel follows 
          or "-ch-", "-sh-", "-ph-", "-th-", "-gh-" 
      H  otherwise 
    J ----> J 
    K ---->   SILENT if after "c" 
      K  otherwise 
    L ----> L 
    M ----> M 
    N ----> N 
    P ----> F  if before "h" 
      P  otherwise 
    Q ----> K 
    R ----> R 
    S ----> X  (sh) if "sh" or "-sio-" or "-sia-" 
      S  otherwise 
    T ----> X  (sh) if "-tia-" or "-tio-" 
      0  (th) if "th" 
        SILENT if "-tch-" 
      T  otherwise 
    V ----> F 
    W ---->   SILENT if not followed by a vowel 
      W  if followed by a vowel 
    X ----> KS 
    Y ---->   SILENT if not followed by a vowel 
      Y  if followed by a vowel 
    Z ----> S 
    */ 


as 
begin 
declare @Result varchar(25) 
     ,@str3 char(3) 
     ,@str2 char(2) 
     ,@str1 char(1) 
     ,@strp char(1) 
     ,@strLen tinyint 
     ,@cnt tinyint 

set @strLen = len(@str) 
set @cnt = 0 
set @Result = '' 

-- Preserve first 5 numeric values when required 
if @KeepNumeric = 1 
    begin 
     set @Result = case when isnumeric(substring(@str,1,1)) = 1 
          then case when isnumeric(substring(@str,2,1)) = 1 
            then case when isnumeric(substring(@str,3,1)) = 1 
              then case when isnumeric(substring(@str,4,1)) = 1 
                then case when isnumeric(substring(@str,5,1)) = 1 
                   then left(@str,5) 
                   else left(@str,4) 
                   end 
                else left(@str,3) 
                end 
              else left(@str,2) 
              end 
            else left(@str,1) 
            end 
          else '' 
          end 

     set @str = right(@str,len(@str)-len(@Result)) 
    end 

--Process beginning exceptions 
set @str2 = left(@str,2) 

if @str2 = 'wh' 
    begin 
     set @str = 'w' + right(@str , @strLen - 2) 
     set @strLen = @strLen - 1 
    end 
else 
    if @str2 in('ae', 'gn', 'kn', 'pn', 'wr') 
     begin 
      set @str = right(@str , @strLen - 1) 
      set @strLen = @strLen - 1 
     end 



set @str1 = left(@str,1) 

if @str1 = 'x' 
    set @str = 's' + right(@str , @strLen - 1) 
else 
    if @str1 in ('a','e','i','o','u') 
     begin 
      set @str = right(@str, @strLen - 1) 
      set @strLen = @strLen - 1 
      set @Result = @Result + @str1 
     end 

while @cnt <= @strLen 
    begin 
     set @cnt = @cnt + 1 
     set @str1 = substring(@str,@cnt,1) 

     set @strp = case when @cnt <> 0 
         then substring(@str,(@cnt-1),1) 
         else ' ' 
         end 

     -- Check if the current character is the same as the previous character. 
     -- If we are keeping numbers, only compare non-numeric characters. 
     if case when @KeepNumeric = 1 and @strp = @str1 and isnumeric(@str1) = 0 then 1 
       when @KeepNumeric = 0 and @strp = @str1 then 1 
       else 0 
       end = 1 
      continue -- Skip this loop 

     set @str2 = substring(@str,@cnt,2) 

     set @Result = case when @KeepNumeric = 1 and isnumeric(@str1) = 1 
           then @Result + @str1 
          when @str1 in('f','j','l','m','n','r') 
           then @Result + @str1 
          when @str1 = 'q' 
           then @Result + 'k' 
          when @str1 = 'v' 
           then @Result + 'f' 
          when @str1 = 'x' 
           then @Result + 'ks' 
          when @str1 = 'z' 
           then @Result + 's' 
          when @str1 = 'b' 
           then case when @cnt = @strLen 
              then case when substring(@str,(@cnt - 1),1) <> 'm' 
                then @Result + 'b' 
               else @Result 
               end 
             else @Result + 'b' 
             end 
          when @str1 = 'c' 
           then case when @str2 = 'ch' or substring(@str,@cnt,3) = 'cia' 
              then @Result + 'x' 
              else case when @str2 in('ci','ce','cy') and @strp <> 's' 
                then @Result + 's' 
                else @Result + 'k' 
                end 
              end 
          when @str1 = 'd' 
           then case when substring(@str,@cnt,3) in ('dge','dgy','dgi') 
              then @Result + 'j' 
              else @Result + 't' 
              end 
          when @str1 = 'g' 
           then case when substring(@str,(@cnt - 1),3) not in ('dge','dgy','dgi','dha','dhe','dhi','dho','dhu') 
              then case when @str2 in('gi', 'ge','gy') 
                then @Result + 'j' 
                else case when @str2 <> 'gn' or (@str2 <> 'gh' and @cnt+1 <> @strLen) 
                   then @Result + 'k' 
                   else @Result 
                   end 
                end 
              else @Result 
              end 
          when @str1 = 'h' 
           then case when @strp not in ('a','e','i','o','u') and @str2 not in ('ha','he','hi','ho','hu') 
              then case when @strp not in ('c','s','p','t','g') 
                 then @Result + 'h' 
                 else @Result 
                 end 
              else @Result 
              end 
          when @str1 = 'k' 
           then case when @strp <> 'c' 
              then @Result + 'k' 
              else @Result 
              end 
          when @str1 = 'p' 
           then case when @str2 = 'ph' 
              then @Result + 'f' 
              else @Result + 'p' 
              end 
          when @str1 = 's' 
           then case when substring(@str,@cnt,3) in ('sia','sio') or @str2 = 'sh' 
              then @Result + 'x' 
              else @Result + 's' 
              end 
          when @str1 = 't' 
           then case when substring(@str,@cnt,3) in ('tia','tio') 
              then @Result + 'x' 
              else case when @str2 = 'th' 
                 then @Result + '0' 
                 else case when substring(@str,@cnt,3) <> 'tch' 
                    then @Result + 't' 
                    else @Result 
                    end 
                 end 
              end 
          when @str1 = 'w' 
           then case when @str2 not in('wa','we','wi','wo','wu') 
              then @Result + 'w' 
              else @Result 
              end 
          when @str1 = 'y' 
           then case when @str2 not in('ya','ye','yi','yo','yu') 
              then @Result + 'y' 
              else @Result 
              end 
          else @Result 
          end 
    end 

return @Result 

end