Как обработка естественного языка может использоваться для классификации обновлений статуса проекта

Вступление

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

Например, многие организации требуют, чтобы менеджеры проектов регулярно обновляли статус проекта в рамках процесса обеспечения доставки. Эти обновления обычно состоят из текстовых комментариев и соответствующего статуса «красный-желтый-зеленый» (RAG), где красный цвет указывает на неудачный проект, желтый - на проект, подверженный риску, а зеленый - на текущий проект. Разве не было бы замечательно, если бы мы могли автоматизировать этот процесс, сделав его более последовательным и объективным?

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

Обучение языковой модели управления проектами

Чтобы гарантировать, что наш классификатор статуса RAG дает хорошие результаты, нам сначала нужно построить языковую модель, которая понимает конкретный язык, используемый менеджерами проектов.

Всего несколько лет назад для обучения пользовательской языковой модели управления проектами потребовался бы огромный объем текста и значительные вычислительные мощности. Однако недавние достижения в применении трансферного обучения к НЛП позволяют нам обучать пользовательскую языковую модель за считанные минуты на скромном графическом процессоре, используя относительно небольшие наборы данных.

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

Mudano собрал небольшой (но богатый) набор данных обновлений статуса проектов по ряду крупных проектов ИТ-трансформации. Мы будем использовать этот набор данных, чтобы сначала обучить пользовательскую языковую модель управления проектами, а затем обучить классификатор статуса RAG.

Изучение данных

Мы начинаем с загрузки данных в pandas.DataFrame и смотрим на пример обновления статуса проекта. Наши данные хранятся в формате .csv, состоящем из столбца текстовых комментариев и столбца связанных статусов RAG. Мы можем загрузить его следующим образом:

import pandas as pd
datapath = '/path/to/data/'
datafile = 'project-updates.csv'
df = pd.read_csv(datapath+datafile)

и посмотрите на пример случайного текстового комментария из нашего набора данных:

df['text'][42]

Все действия продолжают планироваться с одобрения Stage Gate. \ N \ nАнализ базы данных завершен, и в настоящее время рассматриваются варианты для приведения системы в соответствие. После завершения будет подан запрос на включение системы в объем проекта. \ N \ nВлияние на нисходящий поток было выявлено в том, что если запрос информации будет сделан после того, как он был удален в исходных системах, будет получен нулевой ответ. быть возвращенным. В настоящее время ведутся исследования, чтобы понять, приемлемо ли это воздействие или необходимы ли действия.

Текст довольно чистый, и нам не нужно делать дополнительную очистку.

По опыту мы знаем, что менеджеры проектов гораздо чаще сообщают о зеленом статусе, чем о желтом или красном статусе. Давайте быстро проверим, так ли это с нашими данными, а затем построим график результатов:

labelcounts = df.groupby(["label"]).size()
label_sum = len(df["label"])
class_imbalance = [(count/label_sum) for count in labelcounts]

Как мы и подозревали, обновление статуса зеленым цветом значительно более вероятно, чем обновление статуса желтым цветом, а обновление статуса красным - наименее вероятным. Нам нужно будет принять во внимание этот дисбаланс классов при обучении классификатора статуса RAG.

Начало работы с глубоким обучением

Теперь, когда мы изучили наши данные, мы можем смоделировать их с помощью машинного обучения. Глубокое обучение - это ветвь машинного обучения, которая использует глубокие нейронные сети, обученные на больших наборах данных, и особенно хорошо подходит для таких задач, как языковое моделирование и классификация текста. Для построения наших моделей глубокого обучения мы будем использовать fastai библиотеку.

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

Чтобы установить библиотеку fastai, мы можем просто использовать диспетчер пакетов conda следующим образом:

conda install -c pytorch -c fastai fastai

Затем мы можем импортировать основную fastai библиотеку и модуль fastai.text:

from fastai import *
from fastai.text import *

Загрузка данных в фастай

Теперь, когда мы импортировали модуль fastai.text, мы можем использовать его встроенные функции, чтобы легко загружать и обрабатывать наши данные. Поскольку наши данные основаны на тексте и имеют формат .csv, и поскольку мы строим языковую модель, мы используем функцию TextLMDataBunch.from_csv для загрузки и обработки наших данных в банке данных:

data_lm = TextLMDataBunch.from_csv(datapath, datafile)

Удивительно, но мы готовы обучать нашу пользовательскую языковую модель!

Однако, прежде чем мы это сделаем, стоит потратить немного времени на изучение умной обработки данных, которую fastai сделал за кулисами.

Токенизация, оцифровка и сплит

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

Токенизация текста по умолчанию выполняется на уровне слов в fastai.text, с пунктуацией и сокращениями слов, включенными в токенизацию. fastai.text также автоматически удаляет символы HTML и добавляет специальные токены для замены неизвестных токенов.

После токенизации текста fastai.text затем преобразует список токенов в целые числа и вычисляет частоту появления каждого токена. По умолчанию fastai.text сохраняет 60 000 наиболее часто используемых токенов и удаляет токены, которые встречаются в тексте менее двух раз. Эти токены представляют собой словарь, используемый для обучения языковой модели. В нашем случае из-за относительно небольшого набора данных у нас есть только словарь из 994 токенов.

fastai также легко разделяет данные на наборы для обучения и проверки.

Обучение пользовательской языковой модели

Мы создаем нашу собственную языковую модель, определяя объект изучающего язык в fastai:

learn_lm = language_model_learner(data_lm, pretrained_model=URLs.WT103, drop_mult=0.5)

Мы используем банку данных, которую мы определили ранее (data_lm), и предварительно обученную языковую модель (pretrained_model=URLs.WT103) в качестве входных данных для обучаемого объекта и устанавливаем для исключения значение 0.5, чтобы избежать переобучения (drop_mult=0.5).

fastai.text по умолчанию использует модель AWD-LSTM, и мы решили использовать трансферное обучение, предоставив предварительно обученную модель, которая была обучена на наборе данных WikiText-103.

Чтобы начать обучение нашей модели, нам нужно выбрать подходящую скорость обучения. К счастью, fastai имеет несколько действительно полезных встроенных инструментов, которые позволяют очень легко выбрать для этого оптимальное значение.

Мы можем использовать fastai поисковик скорости обучения (который выполняет серию мини-обучающих заданий с разными скоростями обучения), а затем построить график зависимости потерь от скорости обучения:

learn.lr_find()
learn.recorder.plot()

Затем мы выбираем скорость обучения непосредственно перед минимальной потерей, как рекомендовано Джереми Ховардом в курсе Практическое глубокое обучение для кодеров fast.ai. Из приведенного выше графика я выбрал скорость обучения 1e-01.

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

learn_lm.fit_one_cycle(20, 1e-1)

С нашим относительно небольшим набором данных обучение за 20 эпох заняло всего несколько минут на графическом процессоре Nvidia Tesla K80 и дало оценку сложности проверки 34.3.

Неплохо! Но мы определенно можем улучшить это.

В этом первом прогоне обучения мы тренировали только последний уровень модели LSTM. Библиотека fastai позволяет нам «разморозить» более ранние слои модели и обучить их.

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

learn_lm.unfreeze()
learn_lm.fit_one_cycle(20, slice(1e-2/10, 1e-2))

Интуиция подсказывает, что на более ранних уровнях модели были изучены фундаментальные аспекты языка, поэтому мы не хотим сильно их менять.

После размораживания более ранних слоев модели и обучения с использованием убывающей скорости обучения в течение 20 эпох мы получаем оценку сложности проверки 3.3.

Давайте посмотрим, как наша пользовательская языковая модель управления проектами делает при создании комментариев к обновлениям проекта:

learn_lm.predict("This project is", n_words=10)

Этот проект завершен и в настоящее время находится в процессе работы.

Это просто потрясающе! Модель понимает грамматику и пунктуацию и использует слова, специфичные для управления проектами, в правильном контексте.

Давайте сохраним кодировщик пользовательской языковой модели для использования в нашем классификаторе:

learn_lm.save_encoder('lm_enc')

Обучение классификатора статуса RAG

Теперь у нас есть настраиваемая языковая модель управления проектами, и мы можем построить модель для классификации текстовых комментариев как красного, желтого или зеленого цвета.

Первое, что нам нужно сделать, это создать базу данных классификации текста, как мы это делали при обучении нашей языковой модели:

data_clas = TextClasDataBunch.from_csv(datapath, datafile, vocab=data_lm.train_ds.vocab, bs=32)

Чтобы создать базу данных классификации текста, нам необходимо предоставить функции словарь нашей пользовательской языковой модели (vocab=data_lm.train_ds.vocab) и размер пакета обучения (bs=32).

Затем мы определяем объект учащегося по классификации текста, используя в качестве входных данных базу данных классификации текста и устанавливая исключение на 0.5:

learn_clas = text_classifier_learner(data_clas, drop_mult=0.5)

Затем мы загружаем кодировщик пользовательской языковой модели, который мы сохранили ранее:

learn_clas.load_encoder('lm_enc')

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

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

Это просто обратное class_imbalance, которое мы вычислили при изучении данных, и его можно легко ввести в нашу функцию потерь кросс-энтропии:

weights_balance = [(1-count/label_sum) for count in labelcounts]
loss_weights = torch.FloatTensor(weights_balance).cuda()
learn_clas.crit = partial(F.cross_entropy, weight=loss_weights)

Теперь, когда мы разобрались с дисбалансом классов, мы можем обучить наш классификатор статуса RAG. Мы следуем точно такой же процедуре, как и при обучении нашей пользовательской языковой модели.

Сначала мы запускаем fastai поисковик скорости обучения и наносим на график результаты:

learn_clas.lr_find()
learn_clas.recorder.plot(skip_end=15)

Затем мы начинаем обучение модели классификатора, используя оптимальную скорость обучения (1e-2, взято из графика выше) и количество эпох, которые мы выбрали для обучения (20):

learn_clas.fit_one_cycle(20, 1e-2)

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

После этого начального цикла обучения наша классификационная модель получает оценку F1 0.77. Размораживаем предыдущие слои и настраиваем нашу модель:

learn_clas.unfreeze()
learn_clas.fit_one_cycle(20, slice(1e-3/10, 1e-3))

И это мы! У нас есть классификатор статуса RAG, который использует настраиваемую языковую модель управления проектами и получает оценку F1 0.79.

Давайте посмотрим, как работает классификатор статуса RAG, когда мы загружаем пример текстового комментария из обновления проекта.

Пример классификации

Дата 31/05 не будет достигнута при пересмотре текущей даты перепланировки. Это связано с проблемами приема данных, в частности с проблемами переноса данных «синхронизация сортировки», сложностью платформы и запуском процесса управления выпуском ИТ.

Решение Веха в опасности из-за продолжающихся задержек с получением данных, вызванных технической доступностью МСП; эскалации продолжают уделять приоритетное внимание программе с Группой ИТ и Технических

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

learn_clas.predict(example)
(Category red, tensor(2), tensor([0.0018, 0.0034, 0.9948]))

Наша модель правильно классифицирует текстовый комментарий выше как обновление статуса красный, и он определенно читается как красный статус!

Заключение

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

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

Это всего лишь один пример того, как Mudano позволяет руководителям проектов сосредоточиться на том, что действительно важно, используя машинное обучение для автоматизации задач управления проектами.

Хотите работать над аналогичными проектами для крупнейших компаний мира? Или помочь в разработке продуктов, обеспечивающих автономный проект? Если да, то ознакомьтесь с открытыми вакансиями Mudano Клиент-ориентированный специалист по данным и Исследователь и разработчик данных здесь или свяжитесь со мной в LinkedIn.