Обновить
4
Хитрин Сергей@serhit

Бизнес-анализ, управление проектами, разработка

6
Подписчики
Отправить сообщение

Я конечно не знаю полной постановки задачи, но если:

  1. нужно только искать записи по уникальнму ключевому значению, и очень быстро

  2. список помещается в оперативную память

  3. не важно как хранить (поскольку автор несколько раз преобразовывал формат хранения: csv -> сжатый csv с частью колонок, parquet, база SQLight)

то, наверное, можно все записи преобразовать в что-то очень компактное, типа стандартного словаря, индексированного значением штрихода, и сохранять/загружать его из pickle внутри GZip файла.

Компактно на диске, быстрая десериализация, моментальный поиск, минимальный перерасход памяти.

Да, все верно, поздние версии файлов MS Office, как и форматы Open Office, более открыты к извлечению текста. Однако, такие документы в нашем потоке составляют ~7% - остальное это pdf (~70%), и rtf с doc.

По поводу памяти и производительности. Как видно из постановки задачи (часть no/low-code процесса) и выбора средств (универсальный парсер-аггрегатор, основанный на внешних утилитах) - серьезная работа не проводилась.

Могу сказать, что при локальном запуске контейнера в Docker Desktop он при старте забирает ~25-26 Мб и дрейфует около этого значения (с учетом, что используется tmfs).

Тот же локальный экземпляр сервиса проводит конвертацию фалов (приведено к вреднему времени за 1000 символов выходного текста):
- docx - 5,3 ms
- pdf - 9.8 ms
- rtf - ~ 10 ms (но очень большой разброс в зависимости от файлов)
- doc - 5 ms

Хорошая работа. Вопрос про несбалансированные классы: после отсечения данных с малым количеством осадков - не пробовали вводить веса классов?

И ещё. Не пробовали ли применять upsampling (например с помощью imblearn)? Или для таких исследований это недопустимо?

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

Несколько замечаний о реализации.

Онтологии, насколько я понимаю, это очень ограниченный набор данных - сотни терминов. Этого может быть недостаточно для надёжного нахождения соответствий, даже если вы разметите данные (найденные ранее соответствия).

Поиск соответствия терминов в разных онтологиях должен опираться на семантику термина. Такие задачи, особенно при необходимости чтобы решение работало при первичном сопоставлении, можно решать с помощью предобученных эмбедингов - посмотрите в сторону Word2vec, Glove. Особенно, если посчастливится найти предобученных вариант на корпусе текстов вашей предметной области.

Косинусное расстояние между векторами-представлениями терминов будут указывать на смысловое сходство и дадут лучший результат.

TF-IDF по n-граммам такую задачу не решает, как минимум - с ходу. Вообще n-gram по буквам слова - это попытка уловить важную часть слова, корень. Это лучше решать предпроцессингом - стэммингом или даже лемматизацией.

Переход от пространства TF-IDF (bag of words), в ближайшее векторное представление класса "text to vector" "со смыслом" осуществляется методами LSA или LDA. Но мне кажется в данном конкретном случае использование word2wec даст более качественные результаты.

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

Мне кажется, что поиск кандидатов на GitHub с учетом их собственных репозиториев и подписок на другие репозитории существенно сужает входящую воронку: вы ограничиваете поиск до людей, которые интересуются опенсорсными проектами.


Возможно, даже для профессиональной IT-компании это слишком строгий критерий предварительной фильтрации.

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 кластер вытягивать.

Да, и вправду Dask очень удобен и начинать работу с ним просто. На официальном сайте Dask есть сравнение Dask vs Spark: https://docs.dask.org/en/latest/spark.html


При всей мощи Spark, Dask — более универсален. Так что, пока — Dask :)

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

Согласен! У нас тоже довольно часто детали к инциденту идут в виде прикрепленного скриншота или картинки вставленной в документ Word, который прикреплен к инциденту :)


Но сложность распознавания картинок и текста из картинок пока несопоставима с их ценностью для систематизации инцидентов.


Кроме того, те, кто не утруждает себя подробным описанием проблемы, также не утруждают себя даже скриншот сделать...

Наверное, вы имеете ввиду стандартные эмбеддинги типа word2vec или Glove. Они, действительно, обучаются на корпусе по окружению. Но только они генерируют эмбеддинги для слов, а не предложений. Получить эмбеддинг текста — это еще один шаг, который можно сделать либо просто (усреднение эмбеддингов слов), либо сложнее (вектор фиксированной длины с элементами из эмбеддингов слов).


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


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

Ну да, мы выяснили — и приняли меры :)

Ну, я бы не сказал, что модель не интерпретируема. Есть пары нормированных векторов, каждый компонент которых соответствует слову или n-грамме — косинусное расстояние определяет похожесть текстов.
Кроме того, использование TfidfVectorizer, как раз позволяет даже посмотреть какие слова значимы для корпуса и для каждого инцидента — это отдельная полезная функция.


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

Целевой эмбеддинг можно натренировать при условии достаточного количества размеченных данных: "инцидент 1 похож на инцидент 2" / "инцидент 3 не похож на инцидент 4". Мы собрали немного размеченных данных — но этого не хватает для значимого обучения.


Я, кстати, пытался найти где-нибудь численные оценки минимально необходимого количества размеченных данных для тренировки сетей заданной архитектуры. Общий ответ — чем больше, тем лучше ( "спасибо, Кэп" ).
Может у кого-нибудь есть статейка в закладках почитать по этой теме?

Это интересно… Я посмотрю, как часто у нас в текстах встречаются формальные сообщения об ошибках. Их действительно можно включить в предобработку.


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

Я читаю их блог. Система "Антиплагиат" — это монстр, по сравнению с нашей задачей :)
Кроме того, я боюсь, что такие методы, как там используются используются, на коротких текстах обращениях (длиной до 50 слов) могут не сработать...

Спасибо, поправил :)

Классификация знаний по ML — это очень здорово! Хорошее начинание.


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


К сожалению в данном формате и то, и другое — сложновато:


  • монолитный файл data.js — не самый удобный формат чтобы добавлять и редактировать данные. В особенности это касается раздела связей — при таком виде они оторваны от "контекста" узлов. Человеку, который захочет добавить информацию, будет сложно.
  • как уже упоминалось в других комментариях — представление информации может требоваться разное: 3-D, 2-D, список связей какой-нибудь...
  • информацию из такого "хранилища" хорошо-бы уметь искать в поисковиках — это добавило-бы популярности.

Из всего этого вопрос. А не задумывались о том, чтобы представить информацию в виде Wiki, возможно с определенными формальными полями и/или гиперссылками? Или еще проще — в виде набора ссылающихся друг на друга .md файлов на том же GitHub.
Это решило бы вопрос удобного редактирования, поиска и использования информации.


А вопрос представления / визуализации связанных документов решить можно.

У нас есть некоторые проверки на уровне билд-сценариев — но они только для кода. На уровне политик пулл-реквестов мы проверяем процесс именно предоставления изменений — оформление, подтверждение тестирования (оно бывает после релиза на тестовый стенд).

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

Регрессий и новых ошибок стало меньше — меньше соответствующих инцидентов. У нас внутренние накладные расходы сократились. Исходя из этого — вроде все в порядке.

Информация

В рейтинге
Не участвует
Откуда
Москва, Москва и Московская обл., Россия
Зарегистрирован
Активность