Pregunta

necesito para dividir una frase china en palabras separadas. El problema con el chino es que no hay espacios. Por ejemplo, la sentencia puede verse como: 主楼怎么走 (con espacios sería: 主楼 怎么 走).

En el momento en que se puede pensar en una solución. Tengo un diccionario con palabras chinas (en una base de datos). La secuencia de comandos:

  1. tratar de encontrar los dos primeros caracteres de la sentencia en la base de datos (主楼),

  2. Si 主楼 es en realidad una palabra y está en la base de datos del script intentará encontrar tres primeros caracteres (主楼怎). 主楼怎 no es una palabra, por lo que no está en la base de datos => mi aplicación ahora sabe que 主楼 es una palabra separada.

  3. tratar de hacerlo con el resto de los personajes.

No me gusta mucho este enfoque, porque incluso para analizar un texto pequeño que iba a consultar la base de demasiadas veces.

¿Hay otras soluciones para esto?

¿Fue útil?

Solución

Gracias a todos por su ayuda!

Después de un poco de investigación he encontrado algunas herramientas de trabajo (que tienen en cuenta todas sus sugerencias), es por eso que estoy respondiendo a mi propia pregunta.

  1. clase A PHP ( http://www.phpclasses.org/browse /package/2431.html )

  2. Un módulo de Drupal, básicamente otra solución PHP con 4 diferentes algoritmos de segmentación (bastante fácil de entender cómo funciona) http://drupal.org/project/csplitter )

  3. Una extensión de PHP para la segmentación de palabras Chino ( http://code.google.com/ p / phpcws / )

  4. Hay algunas otras soluciones availabe si intenta buscar baidu.com para "中文 分 词"

Atentamente,

Equ

Otros consejos

Usted tiene el texto de entrada, oración, párrafo lo que sea. Así que sí, el procesamiento de la misma será necesidad para consulta en su base de datos por cada cheque.

Con la indexación decente en la columna de la palabra, sin embargo, que no debería tener demasiados problemas.

Una vez dicho esto, lo grande que es este diccionario? Después de todo, sólo necesitaría las palabras, no sus definiciones para comprobar si se trata de una palabra válida. Por lo tanto, si es posible (dependiendo del tamaño), teniendo un enorme mapa de memoria / tabla hash / diccionario con las teclas sólo una (las palabras reales) puede ser una opción y sería rápido como el rayo.

15 millones Es decir, que la media 7 caracteres @ 2 bytes cada uno trabaja a cabo en torno a la marca de 200 Megabytes. No es demasiado loco.

Editar A 'sólo' 1 millón de palabras, usted está buscando en torno a algo más de 13 megabytes, por ejemplo 15 con algo de sobrecarga. Eso es una obviedad que diría.

Otro que funciona bien es http://www.itgrass.com/phpanalysis/index. html

Es el único que he encontrado que funciona correctamente con UTF-8. El resto sólo trabajó para mí en GB18030, lo que causó un montón de problemas más adelante en la línea. Yo pensaba que iba a tener que empezar de nuevo, pero éste me salvó un montón de tiempo.

Bueno, si usted tiene una base de datos con todas las palabras y no hay otra manera de conseguir los involucrados palabra creo que se ve obligado a volver a consultar la base de datos.

Para mejorar el rendimiento de esto, no se puede hacer todos los controles antes de insertar la frase en la base de datos, y añadir espacios mismo?

(usando ABCDE para representar los caracteres chinos para simplificar)

Digamos que tienes la 'frase' ABCDE de entrada, y su diccionario contiene las palabras que comienzan con AB ABC , AC , AE y ABB . Y suponer que la palabra CDE existe, pero de ni E no.

Al analizar la frase de entrada, que va de izquierda a derecha, el guión tira del primer carácter . En lugar de consultar la base de datos para ver si es una palabra, consulta la base de datos para tirar todas las palabras que comienzan con .

Bucle a través de esos resultados, agarrando los próximos caracteres de la cadena de entrada para obtener una comparación válida:

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

En este punto, el programa se bifurca hacia abajo las dos ramas 'verdaderos' que se ha encontrado. En la primera, se presume AB es la primera palabra, y trata de encontrar C -empezando palabras. CDE que se encuentra, por lo que es posible rama. Por la otra rama, ABC es la primera palabra, pero de no es posible, de manera que la rama no es válido, es decir, el primero debe ser la verdadera interpretación.

Creo que este método reduce al mínimo el número de llamadas a la base de datos (aunque podría devolver conjuntos más grandes de la base de datos, ya que estás conjuntos de ir a buscar palabras todo lo que inicie con el mismo carácter). Si su base de datos indexada para este tipo de búsqueda, creo que esto funcionaría mejor que ir letra por letra. En cuanto a todo este proceso ahora, y las otras respuestas, creo que esto es en realidad una estructura trie (suponiendo que el carácter buscado es la raíz de un árbol), como había sugerido otro cartel. Bueno, aquí es una implementación de esa idea!

Me doy cuenta de que el problema de la segmentación de palabras chino es muy compleja, pero en algunos casos este algoritmo trivial puede ser suficiente: buscar la palabra más larga w empezando por el carácter i, a continuación, iniciar de nuevo por la longitud i + (w ) -ésimo carácter.

Aquí hay una implementación de 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))

La última parte utiliza una copia de la CCEDICT diccionario para segmentar un (simplificado) texto chino en dos sabores (resp, con y sin caracteres que no son de texto.):

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

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

Una buena y rápida al segmento de texto chino se basa en la coincidencia máxima segmentación, que es básicamente pondrá a prueba diferente longitud de las palabras para ver qué combinación de segmentación es más probable. Se necesita en una lista de todas las palabras posibles para hacerlo.

Leer más sobre ello aquí: http://technology.chtsai.org/mmseg/

Ese es el método que utilizo en mi 读者 (Duzhe) Texto Analyzer ( http://duzhe.aaginskiy.com ). Yo no uso una base de datos, en realidad pre-cargar una lista de palabras en una matriz, que hace ocupan alrededor de ~ 2 MB de RAM, pero se ejecuta muy rápidamente.

Si usted está buscando en el uso de la segmentación léxica sobre estadística (aunque método estadístico puede ser tan preciso como ~ 97% según algunas investigaciones), una muy buena herramienta de segmentación es ADSOtrans que se pueden encontrar aquí: http://www.adsotrans.com

Se utiliza una base de datos, pero tiene una gran cantidad de tablas redundantes para acelerar la segmentación. También puede proporcionar definiciones gramaticales para ayudar a la segmentación.

Esta es una tarea bastante estándar en la lingüística computacional. Se conoce por el nombre de "tokenización" o "segmentación de palabras." Trate de buscar "segmentación de palabras chino" o "tokenización chino" y encontrará varias herramientas que se han hecho para realizar esta tarea, así como los trabajos sobre los sistemas de investigación para hacerlo.

Para hacer esto bien, por lo general tendrá que utilizar un modelo estadístico construido mediante la ejecución de un sistema de aprendizaje automático en un corpus de entrenamiento bastante grande. Varios de los sistemas se puede encontrar en la web vienen con modelos pre-formados.

Se puede construir muy, muy largo de expresiones regulares.

Editar Me refería a construirlo de forma automática con la escritura de la BD. No escribir por mano.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top