2016-06-22 18 views
5

Also, ich bin auf der Suche nach Implementierung von Fuzzy Logic Matching in meiner Firma und habe Probleme, gute Ergebnisse zu bekommen. Für den Anfang versuche ich, Firmennamen mit denen auf einer Liste zu vergleichen, die von anderen Firmen geliefert wird.
Mein erster Versuch war es, soundex zu verwenden, aber es sieht so aus, als ob Soundex nur die ersten paar Töne im Firmennamen vergleicht, so dass lange Firmennamen zu leicht voneinander zu unterscheiden sind.
Ich arbeite jetzt an meinem zweiten Versuch mit dem Levtenstein Distanzvergleich. Es sieht vielversprechend aus, besonders wenn ich die Interpunktion zuerst entferne. Ich habe jedoch immer noch Probleme, Duplikate zu finden, ohne zu viele Fehlalarme.
Eines der Probleme, die ich habe, ist Unternehmen wie Widgetsco vs Widgets inc. Also, wenn ich den Teilstring der Länge des kürzeren Namens vergleiche, nehme ich auch Dinge wie BBC University und CBC University Campus auf. Ich vermute, dass eine Partitur, die eine Kombination aus Abstand und längster gemeinsamer Teilkette verwendet, die Lösung sein könnte.
Hat es jemand geschafft, einen Algorithmus zu erstellen, der eine solche Anpassung mit begrenzten Fehlalarmen durchführt?Fuzzy Logic Matching

+0

Die einzige Übereinstimmung, die ich je tun musste, basierte auf Teilstring-Matching, z. BBC Uni und BBC Universität. Dies setzt voraus, dass der Anfangsteil der Zeichenfolge unter allen Duplikaten identisch ist. Für Fälle wie: widgets inc würde ich zuerst die Abkürzungen der Entity-Typen entfernen. Wenn Sie andere verwandte Daten haben, z.B. Firmenadresse, CEO des Unternehmens, dann auch das kann verglichen werden, um eine Punktzahl der Wahrscheinlichkeit zu produzieren, dass zwei Unternehmen gleich sind. Ich würde mich darauf konzentrieren, die Daten zuerst zu normalisieren (indem ich Flusen entferne), bevor ich versuche, sie tatsächlich zu vergleichen. – Alex

+0

Entfernen der Flusen ist in der Regel eine gute Übung, egal welchen Algorithmus Sie verwenden. – Yobik

+0

Ich werde die Daten normalisieren. Für Fälle wie "Smith & Wesson", die zu "Smith and Wesson" passen, würde ich alle "&" zu "und" für die Zwecke eines Matches konvertieren. Ich würde auch versuchen, Entity-Typen und ihre Abkürzungen (inkl. Co.) Zu entfernen und zu überprüfen, ob dies falsche Positive ergibt. Wenn Daten komplexere Konstrukte aufweisen, z. "CompanyA trading as CompanyB", dann müssen sie geparst werden. IMO, Fuzzy Matching gut strukturierte Daten wie Firmennamen ist ein falsches Werkzeug für den Job. – Alex

Antwort

0

Sie möchten etwas wie Levenshtein Distance oder einen anderen String-Vergleichsalgorithmus verwenden. Vielleicht möchten Sie sich dieses Projekt auf Codeplex anschauen.

http://fuzzystring.codeplex.com/

+0

Ich mag Levenshtein Entfernung, aber das Problem ist, dass es nicht "unscharf" ist. Die Entfernung zwischen 'CBC University' und 'CBC University' ist 4, obwohl sie wahrscheinlich der gleiche Ort sind.Dieser SO-Post hat einen netten "unscharfen" Levenshtein [SQL Server Fuzzy Search mit Übereinstimmungsgrad] (http://stackoverflow.com/questions/26259117/sql-server-fuzzy-search-with-percentage-of-match) – user918967

0

Verwenden Sie Access? Wenn ja, betrachten Sie das Zeichen '*' ohne die Anführungszeichen. Wenn Sie SQL Server verwenden, verwenden Sie das Zeichen "%". Dies ist jedoch keine Fuzzy-Logik, es ist wirklich der Like-Operator. Wenn Sie wirklich Fuzzy-Logik benötigen, exportieren Sie Ihren Datensatz nach Excel und laden Sie das AddIn von der folgenden URL.

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

Lesen Sie die Anweisungen sehr sorgfältig. Es funktioniert definitiv, und es funktioniert gut, aber Sie müssen den Anweisungen folgen, und es ist nicht vollständig intuitiv. Als ich es das erste Mal ausprobierte, habe ich die Anweisungen nicht befolgt und viel Zeit verschwendet, um es zum Laufen zu bringen. Irgendwann habe ich es herausgefunden, und es hat super funktioniert !!

0

Wir haben gute Ergebnisse bei der Namens- und Adressanpassung mit einer Metaphone-Funktion erzielt, die von Lawrence Philips erstellt wurde. Es funktioniert ähnlich wie Soundex, erzeugt aber ein Klang-/Konsonantenmuster für den gesamten Wert. Sie können dies nützlich in Verbindung mit einigen anderen Techniken finden, vor allem, wenn Sie einige der Flaum wie 'co.' und "inc." Wie in anderen Kommentaren erwähnt:

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