Lematizarlo más rápido (PyMorphy2, PyMystem3 y algo de magia)

Trabajo como programador, incluido el aprendizaje automático en relación con el análisis de texto. Cuando se procesa un lenguaje natural, se requiere una preparación preliminar de los documentos, y uno de los métodos es la lematización, que lleva todas las palabras del texto a sus formas normales, teniendo en cuenta el contexto.

Recientemente, nos enfrentamos con el problema de los grandes costos de tiempo para este proceso. En una tarea específica, había más de 100,000 documentos, cuya longitud promedio era de aproximadamente 1000 caracteres, y era necesario implementar el procesamiento en una computadora local normal, y no en nuestro servidor para los cálculos. No pudimos encontrar una solución en Internet, pero la encontramos nosotros mismos y me gustaría compartirla para demostrar un análisis comparativo de las dos bibliotecas de lematización más populares en este artículo.



Pymorphy2


Uno de los más populares es PyMorphy2: se encuentra en casi todas las soluciones que se pueden encontrar en la red. También utilizamos esta biblioteca, y se mostró perfectamente, hasta que se requirió hacer una lematización para toda la base de datos (como escribí anteriormente, estos son más de 100 mil documentos pequeños). Para analizar dicho volumen de documentos, PyMorphy2 tomaría casi 10 horas, mientras que la carga del procesador en todo este tiempo sería en promedio aproximadamente 30% (Intel Core i7 7740X).

Pymystem3


En busca de otra solución, analizamos la biblioteca de Yandex PyMystem3, pero el resultado fue casi dos veces peor (a tiempo) que PyMorphy2: tomaría 16 horas procesar 100 mil documentos.

Algo de magia


Nos pareció extraño que la carga en el procesador fuera casi nula. También fue extraño que para obtener el resultado de un texto, incluso uno grande (3-4 mil caracteres), PyMystem3 tomó aproximadamente 1 segundo. Por lo tanto, decidimos combinar los textos agregando algún tipo de separador entre ellos, mediante el cual podríamos nuevamente devolver la estructura de nuestra lista de documentos y dárselos para la lematización.

Código de solución Python:

def checkExecTimeMystemOneText(texts):
    lol = lambda lst, sz: [lst[i:i+sz] for i in range(0, len(lst), sz)]
    txtpart = lol(texts, 1000)
    res = []
    for txtp in txtpart:
        alltexts = ' '.join([txt + ' br ' for txt in txtp])

        words = mystem.lemmatize(alltexts)
        doc = []
        for txt in words:
            if txt != '\n' and txt.strip() != '':
                if txt == 'br':
                    res.append(doc)
                    doc = []
                else:
                    doc.append(txt)

Tomamos 1,000 documentos cada uno para el sindicato, el separador entre ellos era "br" (cabe señalar que los textos en ruso, y el alfabeto latino y los caracteres especiales, los eliminamos previamente). Esta solución aceleró significativamente la lematización: en promedio, resultó aproximadamente 25 minutos para los 100 mil documentos, la carga del procesador fue del 20-40%. Es cierto que esta solución carga más RAM: en promedio, es de aproximadamente 3-7 GB, pero este es un buen resultado. Si no hay suficiente memoria, puede cambiar la cantidad de documentos que se combinarán, aunque esto ralentizará el procesamiento, seguirá siendo mucho más rápido que un texto a la vez. Además, si la cantidad de memoria lo permite, puede aumentar este valor y obtener el resultado aún más rápido.

La tabla muestra una comparación de bibliotecas durante el procesamiento en una computadora local (Intel Core i7 7740X, 32 GB de RAM):
MétodoHoraRAM (Mb)Por ciento
Pymorphy2~ 9.5 horas500 - 60025-30%
PyMystem3 por 1 oración~ 16 horas500 - 7000 - 1%
PyMystem3 con 1000 ofertas26 minutos2000 - 700025 - 40%

Es interesante conocer las opiniones de otros especialistas. ¿Quizás alguien encontró una manera más eficiente en el tiempo de lematizar textos cortos?

Mikhail Kabakov, ingeniero de software sénior,
Anna Mikhailova, directora de
minería de datos , Consorcio Codex

All Articles