Frage

Ich muss einen chinesischen Satz in getrennte Wörter aufteilen. Das Problem mit Chinesen ist, dass es keine Räume gibt. Zum Beispiel kann der Satz so aussehen wie: 主楼怎么走 (Mit Räumen wäre es: 主楼 怎么 走).

Im Moment kann ich mir eine Lösung vorstellen. Ich habe ein Wörterbuch mit chinesischen Wörtern (in einer Datenbank). Das Skript wird:

  1. Versuchen Sie, die ersten beiden Zeichen des Satzes in der Datenbank zu finden (主楼),

  2. wenn 主楼 ist eigentlich ein Wort und es ist in der Datenbank, das Skript versucht, die ersten drei Zeichen zu finden (主楼怎). 主楼怎 ist kein Wort, es ist also nicht in der Datenbank => Meine Anwendung weiß das jetzt 主楼 ist ein separates Wort.

  3. Versuchen Sie es mit den Resten der Charaktere.

Ich mag diesen Ansatz nicht wirklich, denn es würde die Datenbank zu oft abfragen, selbst einen kleinen Text zu analysieren.

Gibt es noch andere Lösungen dafür?

War es hilfreich?

Lösung

Vielen Dank an alle für Ihre Hilfe!

Nach ein wenig Nachforschungen habe ich einige funktionierende Tools gefunden (im Sinn, all Ihre Vorschläge), deshalb beantworte ich meine eigene Frage.

  1. Eine PHP -Klasse (http://www.phpcasses.org/browse/package/2431.html)

  2. Ein Drupal -Modul, im Grunde eine weitere PHP -Lösung mit 4 verschiedenen Segmentierungsalgorithmen (ziemlich leicht zu verstehen, wie es funktioniert) (http://drupal.org/project/csplitter)

  3. Eine PHP -Erweiterung für die chinesische Wortsegmentierung (http://code.google.com/p/phpcws/)

  4. Es gibt einige andere Lösungen, die zur Verfügung stehen, wenn Sie versuchen, Baidu.com nach "中文 分词" zu durchsuchen.

Aufrichtig,

Gleich

Andere Tipps

Möglicherweise möchten Sie eine verwenden Trie Datenstruktur. Sie konstruieren zuerst das Trie aus dem Wörterbuch und suchen nach gültigen Wörtern viel schneller. Der Vorteil besteht darin, festzustellen, ob Sie am Ende eines Wortes sind oder weiter nach längeren Wörtern suchen müssen, ist sehr schnell.

Sie haben den Eingabetxt, den Satz, den Absatz was auch immer. Also ja, Ihre Verarbeitung wird brauchen Um Ihren DB für jeden Scheck abzufragen.

Mit einer anständigen Indizierung in der Wortspalte sollten Sie nicht zu viele Probleme haben.

Wie groß ist dieses Wörterbuch? Schließlich benötigen Sie nur die Wörter, nicht die Definitionen, um zu überprüfen, ob es sich um ein gültiges Wort handelt. Wenn also überhaupt möglich (abhängig von der Größe), kann eine riesige Speicherkarte/Hashtable/Wörterbuch mit nur Schlüssel (die tatsächlichen Wörter) eine Option sein und schnell als Blitz sein.

Bei 15 Millionen Wörter, sagen durchschnittlich 7 Zeichen @ 2 Bytes Jeder funktioniert um die 200 -Megabyte -Marke. Nicht zu verrückt.

Bearbeiten: Bei "nur 1 Million Worten", sehen Sie ungefähr etwas mehr als 13 Megabyte, sagen 15 mit etwas Overhead. Das ist ein Kinderspiel, das ich sagen würde.

Ein anderer, der gut funktioniert, ist http://www.itgrass.com/phpanalysis/index.html

Es ist das einzige, das ich fand, das mit UTF-8 ordnungsgemäß funktioniert. Der Rest arbeitete nur für mich in GB18030, was später auf der ganzen Linie unzählige Probleme verursachte. Ich dachte, ich müsste von vorne anfangen, aber dieser hat mir viel Zeit gerettet.

Wenn Sie eine Datenbank mit allen Wörtern haben und es keinen anderen Weg gibt, um dieses Wort einzubeziehen, sind Sie meiner Meinung nach gezwungen, die Datenbank erneut zu formulieren.

Um die Leistung davon zu verbessern, können Sie nicht alle diese Überprüfungen durchführen, bevor Sie den Satz in die Datenbank einfügen und selbst Räume hinzufügen?

(Verwendung ABCDE chinesische Charaktere für die Einfachheit darstellen)

Nehmen wir an, Sie haben den "Satz" ABCDE Eingabe, und Ihr Wörterbuch enthält diese Wörter, die mit beginnen EIN: Ab, ABC, AC, Ae, und ABB. Und vermuten, dass das Wort CDE existiert, aber De, noch E unterlassen Sie.

Wenn Sie den Eingangssatz analysieren und nach rechts gehen, zieht das Skript den ersten Charakter EIN. Anstatt die Datenbank abzufragen, um festzustellen, ob EIN ist ein Wort, fragen Sie die Datenbank, um alle Wörter zu ziehen, mit denen beginnen EIN.

Schleifen Sie diese Ergebnisse durch und schnappen Sie sich die nächsten Zeichen aus der Eingabezeichenfolge, um einen ordnungsgemäßen Vergleich zu erhalten:

AB  ?= AB : True
ABC ?= ABC: True
AC  ?= AB : False
AE  ?= AB : False
ABB ?= ABC: False

Zu diesem Zeitpunkt greift das Programm die beiden "wahren" Zweige, die es gefunden hat. In der ersten vermutet es Ab ist das erste Wort und versucht zu finden C-Wörter starten. CDE wird gefunden, so dass der Zweig möglich ist. Den anderen Zweig hinunter, ABC ist das erste Wort, aber De ist nicht möglich, so dass der Zweig ungültig ist, was bedeutet, dass die erste die wahre Interpretation sein muss.

Ich denke, diese Methode hat die Anzahl der Aufrufe in die Datenbank minimiert (obwohl sie möglicherweise größere Sätze aus der Datenbank zurückgeben, da Sie Sätze von Wörtern abrufen, die alle mit demselben Zeichen beginnen). Wenn Ihre Datenbank für diese Art von Suchen indiziert wäre, würde dies besser funktionieren als Brief für Brief. Wenn ich diesen ganzen Prozess jetzt und die anderen Antworten betrachtet, denke ich, dass dies tatsächlich eine Trie -Struktur ist (vorausgesetzt, der Charakter ist die Wurzel eines Baumes), wie ein anderes Poster vorgeschlagen hatte. Hier ist eine Implementierung dieser Idee!

Mir ist klar, dass das Problem der chinesischen Wortsegmentierung sehr komplex ist, aber in einigen Fällen kann dieser triviale Algorithmus ausreichen: Suchen .

Hier ist eine Python -Implementierung:

#!/usr/bin/env python
# encoding: utf-8

import re
import unicodedata
import codecs

class ChineseDict:

    def __init__(self,lines,rex):
        self.words = set(rex.match(line).group(1) for line in lines if not line.startswith("#"))
        self.maxWordLength = max(map(len,self.words))

    def segmentation(self,text):
        result = []
        previousIsSticky = False
        i = 0
        while i < len(text):
            for j in range(i+self.maxWordLength,i,-1):
                s = text[i:j]
                if s in self.words:
                    break
            sticky = len(s)==1 and unicodedata.category(s)!="Lo"
            if previousIsSticky or (result and sticky):
                result[-1] += s
            else:
                result.append(s)
            previousIsSticky = sticky
            i = j
        return u" | ".join(result)

    def genWords(self,text):
        i = 0
        while i < len(text):
            for j in range(i+self.maxWordLength,i,-1):
                s = text[i:j]
                if s in self.words:
                    yield s
                    break
            i = j


if __name__=="__main__":
    cedict = ChineseDict(codecs.open("cedict_ts.u8",'r','utf-8'),re.compile(r"(?u)^.+? (.+?) .+"))
    text = u"""33. 你可以叫我夏尔
    戴高乐将军和夫人在科隆贝双教堂村过周末。星期日早晨,伊冯娜无意中走进浴室,正巧将军在洗盆浴。她感到非常意外,不禁大叫一声:“我的上帝!”
    戴高乐于是转过身,看见妻子因惊魂未定而站立在门口。他继续用香皂擦身,不紧不慢地说:“伊冯娜,你知道,如果是我们之间的隐私,你可以叫我夏尔,用不着叫我上帝……”
    """
    print cedict.segmentation(text)
    print u" | ".join(cedict.genWords(text))

Der letzte Teil verwendet eine Kopie der Ccedict Dictionary Um einen (vereinfachten) chinesischen Text in zwei Geschmacksrichtungen zu segmentieren (bzw. ohne Non-Word-Zeichen):

33. 你 | 可以 | 叫 | 我 | 夏 | 尔
    戴高乐 | 将军 | 和 | 夫人 | 在 | 科隆 | 贝 | 双 | 教堂 | 村 | 过 | 周末。星期日 | 早晨,伊 | 冯 | 娜 | 无意中 | 走进 | 浴室,正巧 | 将军 | 在 | 洗 | 盆浴。她 | 感到 | 非常 | 意外,不禁 | 大 | 叫 | 一声:“我的 | 上帝!”
    戴高乐 | 于是 | 转 | 过 | 身,看见 | 妻子 | 因 | 惊魂 | 未定 | 而 | 站立 | 在 | 门口。他 | 继续 | 用 | 香皂 | 擦 | 身,不 | 紧 | 不 | 慢 | 地 | 说:“伊 | 冯 | 娜,你 | 知道,如果 | 是 | 我们 | 之间 | 的 | 隐私,你 | 可以 | 叫 | 我 | 夏 | 尔,用不着 | 叫 | 我 | 上帝……”

你 | 可以 | 叫 | 我 | 夏 | 尔 | 戴高乐 | 将军 | 和 | 夫人 | 在 | 科隆 | 贝 | 双 | 教堂 | 村 | 过 | 周末 | 星期日 | 早晨 | 伊 | 冯 | 娜 | 无意中 | 走进 | 浴室 | 正巧 | 将军 | 在 | 洗 | 盆浴 | 她 | 感到 | 非常 | 意外 | 不禁 | 大 | 叫 | 一声 | 我的 | 上帝 | 戴高乐 | 于是 | 转 | 过 | 身 | 看见 | 妻子 | 因 | 惊魂 | 未定 | 而 | 站立 | 在 | 门口 | 他 | 继续 | 用 | 香皂 | 擦 | 身 | 不 | 紧 | 不 | 慢 | 地 | 说 | 伊 | 冯 | 娜 | 你 | 知道 | 如果 | 是 | 我们 | 之间 | 的 | 隐私 | 你 | 可以 | 叫 | 我 | 夏 | 尔 | 用不着 | 叫 | 我 | 上帝 

Ein guter und schneller Weg, um den chinesischen Text zu segmentieren, basiert auf der maximalen Übereinstimmungssegmentierung, die im Grunde genommen unterschiedliche Wörterlänge testet, um zu erkennen, welche Kombination von Segmentierung am wahrscheinlichsten ist. Es nimmt eine Liste aller möglichen Wörter auf.

Lesen Sie hier mehr darüber: http://technology.chtsai.org/mmseg/

Das ist die Methode, die ich in meinem 读者 (Duzhe) Textanalysator ( http://duzhe.aaginskiy.com ). Ich verwende keine Datenbank, tatsächlich lade ich eine Liste von Wörtern in ein Array vor, das ungefähr ~ 2 MB RAM aufnimmt, aber sehr schnell ausgeführt wird.

Wenn Sie die Verwendung der lexikalischen Segmentierung gegenüber statistischer (obwohl die statistische Methode gemäß einigen Forschungen genauso genau ~ 97% sein kann), ist ein sehr gutes Segmentierungsinstrument Adsotrans, die hier zu finden sind: http://www.adsotrans.com

Es verwendet eine Datenbank, verfügt jedoch über viele redundante Tabellen, um die Segmentierung zu beschleunigen. Sie können auch grammatikalische Definitionen bereitstellen, um die Segmentierung zu unterstützen.

Dies ist eine ziemlich übliche Aufgabe in der Computational Linguistics. Es nennt den Namen "Tokenization" oder "Wortsegmentierung". Versuchen Sie, nach "chinesischer Wortsegmentierung" oder "chinesischer Tokenisierung" zu suchen, und Sie werden mehrere Tools finden, die diese Aufgabe erledigen, sowie Artikel über Forschungssysteme, um dies zu tun.

Um dies gut zu machen, müssen Sie normalerweise ein statistisches Modell verwenden, das durch Ausführen eines maschinellen Lernsystems auf einem ziemlich großen Trainingskorpus erstellt wurde. Einige der Systeme, die Sie im Web finden, sind mit vorgeborenen Modellen ausgestattet.

Sie können sehr sehr lange regelmäßige Ausdruck aufbauen.

Bearbeiten:Ich wollte es automatisch mit Skript aus der DB erstellen. Nicht von Hand schreiben.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top