Как стать автором
Обновить

Комментарии 14

pip install pymorphy2[fast] пробовали?

эта команда не работает, по идее она должна установить стабильную версию, но сейчас стабильная версия 0.8, мы её и использовали

PyMystem3 использует для обработки внешний исполняемый файл mystem.exe. Видимо, такая архитектура на частых маленьких вызовах обходится очень дорого. Соответственно, ваш подход с объединением многих предложений в одно для обработки — это действительно хорошая идея.


По поводу дальнейшего ускорения. Итерация по массиву — это задача, которая хорошо параллелится. Можно попробовать joblib в качестве старта. Если расширить ваш пример с "упаковкой" текстов, получится что-то такое:


from pymystem3 import Mystem
from tqdm import tqdm

from joblib import Parallel, delayed

batch_size = 1000
texts = ["Мама мыла раму {}".format(i) for i in range(1000000)]

text_batch = [texts[i: i + batch_size] for i in range(0, len(texts), batch_size)]

def lemmatize(text):
    m = Mystem()
    merged_text = "|".join(text)

    doc = []
    res = []

    for t in m.lemmatize(merged_text):
        if t != '|':
            doc.append(t)
        else:
            res.append(doc)
            doc = []

    return res

# Вот здесь тоже немного магии :)
processed_texts = Parallel(n_jobs=-1)(delayed(lemmatize)(t) for t in tqdm(text_batch))

У меня на ноуте c Intel Core i5-7300U @2.6Ghz при запуске в 4 процесса, миллион "мама мыла раму" лемматизируется за 16 минут. tqdm показывает ~1.1 it/sec


Ну и дальше, если корпус еще больше — можно на dask кластер вытягивать.

инициализацию mystem надо вынести за lemmatize(), она занимает большую часть времени. на собственно лемматизацию приходится совсем мало

Это понятно. Я бы так и сделал, если бы не параллельные процессы — в них это так не работает.

Да, смысл именно в том, что PyMystem3 работает быстрее, чем pymorphy2 на одном тексте, но при каждом вызове поднимает mystem (и ещё делает кучу всего), что как раз и замедляет на куче. Предложенное решение вроде простое, но не всегда очевидное. Может, кому-то тоже поможет, как и нам.
За joblib спасибо, параллельные потоки всегда актуальная тема, хотя не стали сильно в неё углубляться в этом случае: при текущей реализации вышли на приемлемое время подготовки, дальше уже больше внимания на модели
Видимо, такая архитектура на частых маленьких вызовах обходится очень дорого
Точноейшим образом совпадает с моими тестами на Windows, по итогу я то ли баг заводил, то ли в существующий отписывался — решения пока нет. На Linux такой проблемы нет, лемматизатор летает.
serhit, спасибо тебе за пример.
Я использовал похожую конструкцию, но инициализировал Mystem() вне функции.
Когда запускал Parallel(n_jobs=-1)(delayed(...) ловил ошибку _pickle.PicklingError: Could not pickle the task to send it to the workers
У меня была задача морфологического анализа базы opensubtitles.org для английского языка (~1.7 миллиона слов после минимизации). Сделаю оговорку, что анализ нужен был без разбивки по отдельным «документам». С другой стороны, нужно было категоризировать слова по группам наследования, частям речи, и некоторым другим параметрам.

Короче, покопавшись немного с внешними библиотеками, решил сделать все «в лоб» на голом SQL. Использовались только базы opensubtitles.org и Helsinki Finite-State Technology.

Полный разбор базы получился где-то в районе 40 секунд — минуты.
А на php что сейчас наиболее модно на тему лемматизации? Для русского/англ языка.
Если вам нужно сравнительно быстро и качественно — всё упирается в mystem.
Группируете тексты, поднимаете процесс mystem-а, суёте, разбираете.

Насколько я искал некоторое время назад — яндекс нигде не раскрывает исходники мистема, везде приходится использовать как процесс.
Теоретически можно попробовать расковырять exe-шник, и попытаться сделать из него библиотеку, но, подозреваю, этого нельзя делать с точки зрения лицензии и довольно сложно технически.

А спросить у kmike по поводу оптимизации pymorphy2 не пробовали?

Скажите, а вы станфордский Stanza не пробовали, если да то как в сравнении? Спасибо.

У нас с коллегами тоже возникала такая проблема. Внутри pymystem мы обнаружили неприятный момент, что на каждый вызов лемматизатора заново поднимался подпроцесс mystem.exe, что занимает сильно больше времени чем сама лемматизация.
Мы решили проблему написав свою обёртку, которая запускала бы приложение не на один раз, а на продолжительное время и общались с ним через пайпы. Производительность заметно выросла, но стали возникать проблемы со стабильностью, которые и вынудили разработчиков перезапускать приложение на каждый вызов, как мы в последствии предположили. Вышли из положения периодическим перезапуском.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации