Наравне с многими компаниями, занимающимися разработкой ПО, в качестве составления общей картины о затраченном сотрудниками времени (а также способа расчета заработной платы, что не слишком важно) на те или иные задачи использует таймшиты - записи с указанием проекта, длительности выполнения задачи и кратким описанием проделанных действий. Однако если с первыми двумя пунктами проблем зачастую не случается, то к “творческой” части проводки периодически возникают вопросы: из текстов не всегда понятно, что конкретно сделал человек за тот или иной промежуток времени, и это может привести к недопониманию и конфликтам со стороны заказчиков, а также банально помешает грамотному учету рабочих часов сотрудников.  В качестве способа смягчения ситуации было решено разработать классификатор текстов, который смог бы на этапе заполнения сориентировать работника по поводу корректности и доступности для понимания составленной им проводки. Что из этого получилось - читайте далее.  Цель исследования - разработка модели для классификации проводок на валидные и не валидные, а также на 8 классов по смыслам, а именно: анализ данных, провел встречу, подготовил отчет, разработал функциональность, сделал документацию, развертывание сервера, тестирование, обучение. Также должны иметься 2 дополнительных класса: «Отпуск» и «Очень плохая проводка», если смысла текста проводки не понятен. Был получен датасет, состоящий из 6000 текстов проводок из системы учета времени сотрудников компании НОРБИТ. Сет был размечен вручную в соответствии с описанной выше классификацией – получили 2297 экземпляров.  Датасет размечался порционально по 500 проводок, извлеченных из базы проводок Microsoft Axapta, которой пользуются сотрудники НОРБИТ на данный момент. Сейчас в нем содержится 3017 экземпляров, максимально отличающихся по смыслу друг от друга. Датасет формировался и размечался с учетом сохранения баланса классов, на что пришлось потратить немало времени - необходимо было просмотреть и разметить примерно в два раза больше проводок, так как в исходных данных имел место перекос. Для удобства классы были пронумерованы от 0 до 7 и названы как “statusid”. Более подробная информация о текстах проводок является конфиденциальной и не может быть разглашена. Все тексты проводок в статье вымышленные.  Пример класса проводок: Адаптация. Проходил семинар по теме “R”. – классификация “Обучение” - Id 7. Подготовил квартальный отчет по оттоку сотрудников. – классификация “Подготовил отчет” -Id 2. Провел встречу с заказчиком. – классификация “Провел встречу” – Id 1. Также были выделены классы валидных и невалидных проводок. Примеры валидных и невалидных проводок: Тестирование. Настройка. – Не валидная проводка Тестирование нового сервера. Настройка работы сервиса. – Валидная проводка. Предобработка текста Обычно тексты содержат разные грамматические формы одного и того же слова, а также могут встречаться однокоренные слова. Лемматизация и стемминг преследуют цель привести все встречающиеся словоформы к одной, нормальной словарной форме. Следующие краткие сводки взяты из этой статьи на хабре.  Примеры: Приведение разных словоформ к одной:   dog, dogs, dog’s, dogs’ => dog      То же самое, но уже применительно к целому предложению:             the boy’s dogs are different sizes => the boy dog be differ size Лемматизация и стемминг – это частные случаи нормализации, и они отличаются. Стемминг – это грубый эвристический процесс, который отрезает «лишнее» от корня слов, часто это приводит к потере словообразовательных суффиксов. Лемматизация – это более тонкий процесс, который использует словарь и морфологический анализ, чтобы в итоге привести слово к его канонической форме – лемме. Отличие в том, что стеммер действует без знания контекста и, соответственно, не понимает разницу между словами, которые имеют разный смысл в зависимости от части речи. Однако у стеммеров есть и свои преимущества: их проще внедрить и они работают быстрее. Плюс более низкая «аккуратность» может не иметь значения в некоторых случаях. Теперь, когда мы знаем, в чем разница, давайте рассмотрим пример: <w:Sdt SdtTag="goog_rdk_2" ID="1297018210">   Вывод:<o:p><w:sdtPr> Предобработка текста проводилась при помощи библиотеки MySteam, все слова в проводках были лемматизированы. Тексты проводок были очищены от русских и английских стоп-слов, были удалены все знаки пунктуации и цифры слова в проводках были лемматизированы. Причины по которым была выбрана библиотека MySteam от Яндекса: Самая высокая скорость работы среди прочих лемматизаторов для рускоязычных слов. Прост и удобен в использовании. Легко ввести в эксплуатацию. Токенизация по предложениям Токенизация (иногда – сегментация) по предложениям – это процесс разделения письменного языка на предложения-компоненты. Идея выглядит довольно простой. В английском и некоторых других языках мы можем вычленять предложение каждый раз, когда находим определенный знак пунктуации – точку. Но даже в английском эта задача нетривиальна, так как точка используется и в сокращениях. Таблица сокращений может сильно помочь во время обработки текста, чтобы избежать неверной расстановки границ предложений. В большинстве случаев для этого используются библиотеки, так что можете особо не переживать о деталях реализации. Чтобы сделать токенизацию предложений с помощью NLTK, можно воспользоваться методом nltk.sent_tokenize. Токенизация по словам Токенизация (иногда – сегментация) по словам – это процесс разделения предложений на слова-компоненты. В английском и многих других языках, использующих ту или иную версию латинского алфавита, пробел – это неплохой разделитель слов. Тем не менее, могут возникнуть проблемы, если мы будем использовать только пробел – в английском составные существительные пишутся по-разному и иногда через пробел. И тут вновь нам помогают библиотеки. Токенизер был создан на основе токенайзера keras и настроен на имеющиеся данные для обучения. Причины выбора токенизера keras в качестве основы: Простой в использовании с высокой скоростью. Поддержка разных движков и модульность. Поддержка нескольких GPU. Сети LSTM LSTM (long short-term memory, дословно (долгая краткосрочная память) — тип рекуррентной нейронной сети, способный обучаться долгосрочным зависимостям. LSTM были представлены в работе Hochreiter & Schmidhuber (1997), впоследствии усовершенствованы и популяризированы другими исследователями, хорошо справляются со многими задачами и до сих пор широко применяются. LSTM специально разработаны для устранения проблемы долгосрочной зависимости. Их специализация — запоминание информации в течение длительных периодов времени, поэтому их практически не нужно обучать! Все рекуррентные нейронные сети имеют форму цепочки повторяющихся модулей нейронной сети. В стандартных РНС этот повторяющийся модуль имеет простую структуру, например, один слой tanh. Повторяющийся модуль стандартной РНС состоит из  одного слоя На приведенной выше диаграмме каждая линия является вектором. Розовый круг означает поточечные операции, например, суммирование векторов. Под желтыми ячейками понимаются слои нейронной сети. Совмещение линий есть объединение векторов, а знак разветвления — копирование вектора с последующим хранением в разных местах. Подробнее о сетях LSTM можно узнать тут.  Модели для классификации основываются на LSTM-модели, которые были взяты из-за принципа её работы и приоритетного списка плюсов, конкретно: Требуется всего несколько строк кода для создания сложной архитектуры нейронной сети. Легко интегрировать / использовать в полнофункциональных проектах. Очень проста в использовании. Был также взят оптимизатор Adam и использованы функции ошибок категориальная кросентропия и бинарная кроссентропия для мультиклассовой и бинарной классификаций, а также классическая метрика Roc Auc. По результатам на валидационной выборке точность по auс составила 70% для сети бинарного классификатора и 72% - для мультиклассовой классификации.  Пример работы классификатора По итогу 63% проводок тестовой выборки верно классифицированы моделью для многоклассовой классификации и 90% - для бинарной классификации, что в целом является результатом нас вполне устраивающим. В ходе работы моделей формируется таблица: text - тексты проводок; scoreplu - скор весов мультиклассовой модели; predictionplu - предсказания мультиклассовой модели; predictionbin - предсказания бинарной модели; scoresbin - скор бинарной модели; cleaned_tweets - тексты проводок после обработки; predicionpluid - ID предсказанной классификации для мультиклассового классификатора; truepluid - ID истинной классификации; predictionbinstate - состояние предсказанной валидации; truebindstate - истинное состояние валидации. И пример записи в полученной таблице: text Сделал   документацию по проекту R. scoreplu 0.9996314      predictionplu Сделал документацию      predictionbin 1 scoresbin 0.99997133      cleaned_tweets сделать документация   проект r predicionpluid 4 truepluid 4 predictionbinstate 1 truebindstate 1 Создана модель на основе LSTM (рекуррентной нейронной сети с памятью) для классификации текстов проводок в журнале записей Axapta. Для того, чтобы проследить фактические улучшения качества списываемых данных после введения решения в оборот, требуется существенное количество времени, однако если вас это заинтересует - статистику также выложим на хабр (вместе с негодующими комментариями сотрудников, которых ИИ заставляет переформулировать описание выполненной работы).