Разделите предложение на отдельные слова - PullRequest
13 голосов
/ 26 января 2010

Мне нужно разбить китайское предложение на отдельные слова. Проблема с китайским заключается в том, что нет пробелов. Например, предложение может выглядеть следующим образом: 主楼怎么走 (с пробелами это будет: 主楼 怎么 走).

В данный момент я могу придумать одно решение. У меня есть словарь с китайскими словами (в базе данных). Скрипт будет:

  1. попытаться найти первые два символа предложения в базе данных (主楼),

  2. если 主楼 на самом деле является словом и находится в базе данных, скрипт попытается найти первые три символа (主楼怎). 主楼怎 - это не слово, поэтому его нет в базе данных => мое приложение теперь знает, что 主楼 - это отдельное слово.

  3. попробуйте сделать это с остальными персонажами.

Мне не очень нравится этот подход, потому что для анализа даже небольшого текста он слишком много раз запросил бы базу данных.

Есть ли другие способы решения этой проблемы?

Ответы [ 11 ]

6 голосов
/ 27 января 2010

Спасибо всем за помощь!

После небольшого исследования я нашел несколько рабочих инструментов (имея в виду все ваши предложения), поэтому я отвечаю на свой вопрос.

  1. Класс PHP (http://www.phpclasses.org/browse/package/2431.html)

  2. Модуль Drupal, в основном другое PHP-решение с 4 различными алгоритмами сегментации (довольно легко понять, как он работает) (http://drupal.org/project/csplitter)

  3. Расширение PHP для сегментации китайских слов (http://code.google.com/p/phpcws/)

  4. Существуют и другие доступные решения, если вы попытаетесь выполнить поиск baidu.com по запросу "中文 分 词"

С уважением,

Equ

2 голосов
/ 26 января 2010

Возможно, вы захотите использовать структуру данных trie . Сначала вы создаете дерево из словаря, а затем поиск правильных слов будет намного быстрее. Преимущество заключается в том, что определение того, находитесь ли вы в конце слова или вам нужно продолжить поиск более длинных слов, очень быстро.

1 голос
/ 15 ноября 2012

Еще один, который хорошо работает, это http://www.itgrass.com/phpanalysis/index.html

Единственное, что я обнаружил, правильно работает с utf-8. Остальное работало только для меня в gb18030, что впоследствии вызвало массу проблем в дальнейшем. Я думал, что мне придется начать все сначала, но этот сэкономил мне много времени.

1 голос
/ 26 января 2010

У вас есть входной текст, предложение, параграф, что угодно. Так что да, вашей обработке потребуется для запроса к вашей БД для каждой проверки.

Однако при достойной индексации по столбцу слов проблем не должно быть слишком много.

Сказав это, насколько велик этот словарь? В конце концов, вам понадобятся только слова, а не их определения, чтобы проверить, является ли это слово правильным. Поэтому, если это вообще возможно (в зависимости от размера), наличие огромной карты памяти / хэш-таблицы / словаря с только ключами (фактическими словами) может быть вариантом и будет быстрым, как молния.

При 15 миллионов слов, скажем, в среднем 7 символов @ 2 байта каждое соответствует отметке 200 мегабайт. Не слишком сумасшедший.

Редактировать: На «только» 1 миллион слов вы просматриваете около 13 Мегабайт, скажем 15 с некоторыми накладными расходами. Я бы сказал, что это легко.

0 голосов
/ 17 марта 2011

Хороший и быстрый способ сегментирования китайского текста основан на максимальной совпадающей сегментации, которая в основном будет проверять различную длину слов, чтобы увидеть, какая комбинация сегментации наиболее вероятна. Для этого требуется список всех возможных слов.

Подробнее об этом здесь: http://technology.chtsai.org/mmseg/

Это метод, который я использую в текстовом анализаторе Du (DuZhe) (http://duzhe.aaginskiy.com). Я не использую базу данных, фактически я предварительно загружаю список слов в массив, который занимает около 2 МБ ОЗУ, но выполняется очень быстро.

Если вы рассматриваете возможность использования лексической сегментации по статистике (хотя, согласно некоторым исследованиям, статистический метод может быть настолько точным, как ~ 97%), очень хорошим инструментом сегментации является ADSOtrans, который можно найти здесь: http://www.adsotrans.com

Он использует базу данных, но имеет много избыточных таблиц для ускорения сегментации. Вы также можете предоставить грамматические определения, чтобы помочь сегментации.

0 голосов
/ 29 мая 2010

Я понимаю, что проблема сегментации китайского слова является очень сложной, но в некоторых случаях этого тривиального алгоритма может быть достаточно: найти самое длинное слово w, начиная с i-го символа, а затем начать снова для длины i + (w ) -й символ.

Вот реализация Python:

#!/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))

В последней части используется копия словаря CCEDICT для сегментирования (упрощенного) китайского текста в два вида (соответственно, с несимвольными символами и без них):

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

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

Это довольно стандартная задача в компьютерной лингвистике. Он называется «токенизация» или «сегментация слова». Попробуйте выполнить поиск по «сегментации китайского слова» или «китайскому токенизации», и вы найдете несколько инструментов, созданных для выполнения этой задачи, а также статьи об исследовательских системах для ее выполнения.

Чтобы сделать это хорошо, вам, как правило, нужно использовать статистическую модель, построенную путем запуска системы машинного обучения на довольно большом учебном корпусе. Некоторые из систем, которые вы можете найти в Интернете, поставляются с предварительно обученными моделями.

0 голосов
/ 26 января 2010

(используя ABCDE для простоты представления китайских иероглифов)

Допустим, у вас есть предложение 'предложение' ABCDE , и ваш словарь содержит эти слова, которые начинаются с A : AB , ABC , AC , AE и ABB . И предположим, что слово CDE существует, но DE и E нет.

При разборе входного предложения, идущего слева направо, скрипт извлекает первый символ A . Вместо того, чтобы запрашивать базу данных, чтобы узнать, является ли A словом, запросите базу данных, чтобы получить все слова, которые начинаются с A .

Переберите эти результаты, выбрав следующие несколько символов из входной строки, чтобы получить правильное сравнение:

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

В этот момент программа разветвляет две «истинные» ветви, которые она нашла. В первом случае предполагается, что AB является первым словом, и пытается найти слова, начинающиеся с C . CDE найдено, так что ветвление возможно. Вниз по другой ветви, ABC - первое слово, но DE невозможно, так что ветвь недопустима, то есть первая должна быть истинной интерпретацией.

Я думаю, что этот метод минимизировал количество обращений к базе данных (хотя он может возвращать большие наборы из базы данных, так как вы выбираете наборы слов, начинающиеся с одного и того же символа). Если бы ваша база данных была проиндексирована для такого рода поиска, я думаю, что это сработало бы лучше, чем проходить по буквам. Глядя на весь этот процесс сейчас и другие ответы, я думаю, что это на самом деле структура три (если предположить, что искомый символ является корнем дерева), как предложил другой автор. Что ж, вот реализация этой идеи!

0 голосов
/ 26 января 2010

Чтобы улучшить производительность, разве вы не можете выполнить все эти проверки, прежде чем вставить предложение в базу данных и добавить пробелы самостоятельно?

0 голосов
/ 26 января 2010

Вы можете построить очень очень длинное регулярное выражение.

Edit: Я хотел построить его автоматически с помощью скрипта из БД. Не писать это рука.

...