Kölner Phonetik

Code-Stücke können hier veröffentlicht werden.
Antworten
Benutzeravatar
roschi
User
Beiträge: 225
Registriert: Samstag 29. März 2008, 18:58
Wohnort: Thueringen, Deutschland
Kontaktdaten:

hallo!

ich habe hier einmal die 'Kölner Phonetik' implementiert.

feedback zum code nehme ich gern entgegen!

Code: Alles auswählen

# -*- coding: iso-8859-15 -*-

"""
Dieses Modul stellt eine Implementation
der 'Kölner Phonetik' dar.

Beispiele zur Verwendung:
>>> encode("Moritz Müller")
'678657'
>>> encode("Moriz Müler")
'678657'
>>> encode("Laura Mayer")
'5767'
>>> encode("Laura Meier")
'5767'
"""

import re

RULETABLE = {re.compile(r".[A|E|I|J|O|U|Y|Ä|Ö|Ü].", re.I):     "0",
             re.compile(r".[B].", re.I):                       "1",
             re.compile(r".[P][^H]", re.I):                    "1",
             re.compile(r".[D|T][^C|S|Z]", re.I):              "2",
             re.compile(r".[F|V|W].", re.I):                   "3",
             re.compile(r"[P][H].", re.I):                     "3",
             re.compile(r".[G|K|Q].", re.I):                   "4",
             re.compile(r"[\b][C][A|H|K|L|O|Q]", re.I):        "4",
             re.compile(r"[^S|Z][C][A|H|K|O|Q|U|X]", re.I):    "4",
             re.compile(r"[^C|K|Q][X].", re.I):                "48",
             re.compile(r".[L].", re.I):                       "5",
             re.compile(r".[M|N].", re.I):                     "6",
             re.compile(r".[R].", re.I):                       "7",
             re.compile(r".[S|Z|ß].", re.I):                   "8",
             re.compile(r"[S|Z][C].", re.I):                   "8",
             re.compile(r"\b[C][^A|H|K|L|O|Q|R|U|X]", re.I):   "8",
             re.compile(r".[C][^A|H|K|O|Q|U|X]", re.I):        "8",
             re.compile(r".[D|T][C|S|Z]", re.I):               "8",
             re.compile(r"[C|K|Q][X].", re.I):                 "8"
            }

def encode(inputstring):
    """
    encode(string) -> string
      Gibt den phonetischen Code des übergebenen Strings zurück.
    """

    encoded = ""
    for i in xrange(len(inputstring)):
        part = inputstring[i - 1:i + 2]
        if len(inputstring) == 1:
          part = " %s " % inputstring[0]
        elif i == 0:
            part = " %s" % inputstring[:2]
        elif i == len(inputstring) - 1:
            part = "%s " % inputstring[i - 1:]
        for rule, code in RULETABLE.iteritems():
            if rule.match(part):
                encoded += code
                break

    while [v for v in RULETABLE.itervalues() if encoded.find(v * 2) != -1]:
        for v in RULETABLE.itervalues():
            encoded = encoded.replace(v * 2, v)

    if encoded:
        encoded = encoded[0] + encoded[1:].replace("0", "")

    return encoded
lg
roschi
[size=117]Fuer Alle, die in Python einsteigen wollen, kann ich das Buch [url=http://abop-german.berlios.de/]A Byte of Python[/url] nur waermstens empfehlen![/size]
zwobot
User
Beiträge: 2
Registriert: Freitag 2. Februar 2007, 20:51

Wollte diese selbst grad implementieren, da hab das hier gefunden. Du hast mir einiges an Arbeit erspart ;) Ich versuche gerade einen Fehlertolerantes Matching von Namen aus 2 Datenquellen zu implemetieren. Erst hab ich es nur mit der Levenshtein-Distanz versucht, jetzt versuche ich die Kölner Phonetik mit dieser zu kombinieren. Also die Levenshtein-Distanz nach Umwandlung in Kölner Phonetik. Die Ergebnisse sind noch nicht wirklich besser. Vielleicht ne Idee das besser zu bewerten?

Gruss
Zwobot
Benutzeravatar
roschi
User
Beiträge: 225
Registriert: Samstag 29. März 2008, 18:58
Wohnort: Thueringen, Deutschland
Kontaktdaten:

hallo!

was genau ist denn deni problem? ist es dir nicht tolerant genug?

nenne doch mal ein beispiel, das bei dir nicht funktioniert.

lg
roschi
[size=117]Fuer Alle, die in Python einsteigen wollen, kann ich das Buch [url=http://abop-german.berlios.de/]A Byte of Python[/url] nur waermstens empfehlen![/size]
nezzcarth
User
Beiträge: 1633
Registriert: Samstag 16. April 2011, 12:47

Mir ist klar, dass der letzte Beitrag über zwei Jahre her ist. Allerdings versuche ich mich gerade ebenfalls an einer Implementation.
Was ich mich Frage: Ist das Umschreiben in reguläre Ausdrücke hier tatsächlich der beste Wege?
Ich hatte zunächst begonnen, diese Regeln mit einem dicken If - Elif Block zu verpacken (eine Lösung per Dictionary fiel mir nicht ein).
Welche der beiden Lösungen wäre da performanter? Gibt es noch einen anderen Weg?
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@nezzcarth: Ein langer If-Elif-Block ist ziemlich hässlich und zudem wenig performant, da ja jeder Ausdruck der Reihe nach ausgewertet werden muss. Bei einem Zugriff auf die Schlüssel eines Wörterbuchs hast du unabhängig von den Auswahlmöglichkeiten immer eine konstante und auch schnelle Zugriffszeit.
nezzcarth
User
Beiträge: 1633
Registriert: Samstag 16. April 2011, 12:47

Ja, das mit dem Dictionary stimmt natürlich, doch wüsste ich nicht, wie ich das Regelwerk darin (wesentlich) anders abbilden sollte, als er, oder als alle 26^3 3er Tupel aufzunehmen. Fraglich ist für mich vorallem, ob die vielen regulären Ausdrücke hier nicht nur leserlicher, sondern auch schneller sind, als eine Schleife, die den String in 3er Gruppen durchgeht und diese dann durch einen Abfrage-Block jagt.
Benutzeravatar
microkernel
User
Beiträge: 271
Registriert: Mittwoch 10. Juni 2009, 17:27
Wohnort: Frankfurt
Kontaktdaten:

Code: Alles auswählen

>>> encode("Leben")
'516'
>>> encode("Lübyien")
'516'
>>> encode("Lybien")
'516'
Naja "Leben" und "Lybien" klingt jetzt nicht wirklich gleich...
Benutzeravatar
microkernel
User
Beiträge: 271
Registriert: Mittwoch 10. Juni 2009, 17:27
Wohnort: Frankfurt
Kontaktdaten:

Ok... Ich hab mal geschaut: Nach Soundex und Metaphone sind "Leben" und "Lybien" auch gleich :/
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

microkernel hat geschrieben:Naja "Leben" und "Lybien" klingt jetzt nicht wirklich gleich...
Du hast noch nie an einer Kundenhotline gearbeitet, oder?
nezzcarth
User
Beiträge: 1633
Registriert: Samstag 16. April 2011, 12:47

microkernel hat geschrieben:

Code: Alles auswählen

>>> encode("Leben")
'516'
>>> encode("Lübyien")
'516'
>>> encode("Lybien")
'516'
Naja "Leben" und "Lybien" klingt jetzt nicht wirklich gleich...
Der Algorithmus ignoriert Vokale (mit einigen Ausnahmen), weil diese laut des Autors des ursprünglichen Artikels zu starken Schwankungen unterliegen. Und die Konsonanten, die dann übrig bleiben, sind ja gleich.
Die Idee ist auch nicht ganz verkehrt; die vorkommenden Vokale werden in diesem Fall tatsächlich sehr ähnlich produziert.

Leider laufen die Beispiele aus dem Paper mit Roschis Script nicht vollständig durch (wenn ich beim Abtippen der Beispiele und dem Konvertieren des Scripts nach Python3 keinen Fehler gemacht habe):

Code: Alles auswählen

**********************************************************************
File "colphon_reg.py", line 82, in __main__.colphon
Failed example:
    colphon('CRESZEW')
Expected:
    '4783'
Got:
    '8783'
**********************************************************************
1 items had failures:
   1 of  32 in __main__.colphon
***Test Failed*** 1 failures.
282
Dazu kommen noch ein paar Weitere, die aus Beispielen für Sonderregeln entstammen, die der Wikipediaartikel nicht erwähnt.
Benutzeravatar
microkernel
User
Beiträge: 271
Registriert: Mittwoch 10. Juni 2009, 17:27
Wohnort: Frankfurt
Kontaktdaten:

/me hat geschrieben:
microkernel hat geschrieben:Naja "Leben" und "Lybien" klingt jetzt nicht wirklich gleich...
Du hast noch nie an einer Kundenhotline gearbeitet, oder?
Sollte ich?
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

microkernel hat geschrieben:
/me hat geschrieben:Du hast noch nie an einer Kundenhotline gearbeitet, oder?
Sollte ich?
Nein. Hättest du das allerdings getan, dann wüsstest du, wie identisch Kunden unterschiedliche Wörter aussprechen können.
nezzcarth
User
Beiträge: 1633
Registriert: Samstag 16. April 2011, 12:47

/me hat geschrieben: Nein. Hättest du das allerdings getan, dann wüsstest du, wie identisch Kunden unterschiedliche Wörter aussprechen können.
Abgesehen davon darf auch nicht vergessen werden, dass dieser Algorithmus (wie auch SoundEx und weitere) nicht dafür gedacht ist, lautliche Ähnlichkeiten zwischen beliebigen Wörtern abzubilden. Es geht um Nachnamen. 'Die Kölner Phonetik' wurde dafür entwickelt, ähnlich geschriebene Nachnamen in Datenbanken zu finden. Und da gelten teilweise andere Regeln. Außerdem muss man berücksichtigen, dass diese Verfahren alle eine Vermischung zwischen Schrift und Aussprache vornehmen, sodass zwangsläufig manchmal auch grenzwertige Resultate entstehen. Um bessere Resultate erzielen zu können, müsste man die Eingabe erst in eine lautliche Repräsentation überführen. Weil das recht aufwändig ist, behilft man sich dann eben mit solchen Verfahren, und nimmt dann zugunsten des Tempos auch mal kleinere Fehler hin.
Antworten