Время прочтения: 6 мин.
Для решения задачи будем использовать инструменты text-mining, в том числе, нормализуем текст, избавимся от стоп-слов, преобразуем слова в tf-idf векторы, применим обучение с учителем, выберем критерии критичности текстов и рассчитаем результирующие показатели. Код (пример данных) модели векторизатора и классификации можно посмотреть по ссылке
Цель нашего исследования — выявление «проблемных филиалов», уровень и частота поломок эксплуатационного характера в которых приводит к фактическому простою работы подразделения или негативно влияет на качество обслуживания клиентов.
- Система регистрации обращений
Изначально нам необходимо понять, как работает система регистрации обращений. Создавая заявку, сотрудник выбирает категорию поломки/аварии и описывает проблему. Затем она поступает в обслуживающую компанию и специалист, в течение определённого времени, выезжает на место поломки. Если поломку удаётся устранить, специалист закрывает заявку. Если требуется провести сложные работы или закупить детали, он может продлить срок выполнения.
- Нормализация слов Pymorphy2
Инициатор заявки не всегда правильно указывает категорию, поскольку может не разбираться в предмете поломки. Поэтому разметим правильные классы обращений в обучающей выборке и, при помощи интеллектуального анализа текста, будем классифицировать все обращения.
Для нормализации слов русского языка применим pymorphy2 – удобную и быструю библиотеку, использующую, в качестве исходного, словарь «Открытого корпуса».
Импортируем библиотеку через JupyterNotebook:
!pip install --index-url=http://mirror.ca.sbrf.ru/pypi/simple/ --trusted-host mirror.ca.sbrf.ru --user pymorphy2
В качестве стартового словаря стоп-слов используем достаточно полный словарь библиотеки stop—words, дополнив его словами со слишком низкой и слишком высокой встречаемостью.
Импортируем библиотеку через JupyterNotebook:
!pip install --index-url=http://mirror.ca.sbrf.ru/pypi/simple/ --trusted-host mirror.ca.sbrf.ru --user stop_words
Векторизатор и классификаторы сохраним и будем считывать из файлов .pkl с применением модуля pickle, способного преобразовывать объекты python в поток байтов и обратно.
Import pickle
#ПРИМЕНЕНИЕ МОДЕЛИ
with open (‘vectf_23867.pkl’,’ rb’) as v1:
vec = pickle.load(v1)
x_test = vec.transform(q4.komment)
with open (‘modelRF_23867.pkl’, ‘rb’) as m1:
model = pickle.load(m1
y_pred = model.predict(x_test)
В качестве исходных данных, берем столбец комментария из исходного DataFrame:
import pandas as pd
df=pd.read_excel('statya.xlsx')
df=df[['Коммент']]
df
Коммент | |
0 | в помещение до в связи с работами на линии бу… |
1 | в всп выбивает свет\nнагрев проводов искрение … |
2 | оборвало пружину на воротах… |
3 | ремонт розеток светильников замена ламп… |
4 | кабинет зона обслуживания юридических лиц выд… |
… | … |
22340 | регулировка приточной вентиляции настройка те… |
22341 | искрит провод на рабочем месте окно номер \nна… |
22342 | с г по г с до будет отключена электроэнергия… |
22343 | плановое отключение электроэнергии с до \nна… |
22344 | прошу посмотреть почему в кассу через вентиляц… |
22345 rows × 1 columns
Перевод слов в нормальную форму представлен ниже:
import pymorphy2
morph = pymorphy2.MorphAnalyzer()
def converter (sentence):
list1 = []
words = sentence.split()
for item in words:
list1.append(morph.parse(item)[0].normal_form)
return ' '.join(list1)
df['Коммент']= df['Коммент'].astype(str)
df['Коммент1']=df['Коммент'].apply(converter)
df
Коммент | Коммент1 | |
0 | в помещение до в связи с работами на линии бу… | в помещение до в связь с работа на линия быть … |
1 | в всп выбивает свет\nнагрев проводов искрение … | в всп выбивать свет нагрев проводы искрение в … |
2 | оборвало пружину на воротах… | оборвать пружина на ворот не … |
3 | ремонт розеток светильников замена ламп радиоз… | ремонт розетка светильник замена лампа радиозв… |
4 | кабинет зона обслуживания юридических лиц выд… | кабинет зона обслуживание юридический лицо выд… |
… | … | … |
22340 | регулировка приточной вентиляции настройка те… | регулировка приточный вентиляция настройка тем… |
22341 | искрит провод на рабочем месте окно номер \nна… | искрить провод на рабочий место окно номер наг… |
22342 | с г по г с до будет отключена электроэнергия… | с год по год с до быть отключить электроэнерги… |
22343 | плановое отключение электроэнергии с до \nна… | плановый отключение электроэнергия с до нагрев… |
22344 | прошу посмотреть почему в кассу через вентиляц… | просить посмотреть почему в касса через вентил… |
22345 rows × 2 columns
Удаляем стоп-слова:
from stop_words import get_stop_words
#Создаем словать стоп слов
rr = get_stop_words('ru')
#Разделяем на слова и считаем количество повторений
wo = pd.Series(' '.join(df['Коммент1']).lower().split()).value_counts().reset_index()
#Записываем все редко встречающиеся слова в новый лист, считаем его длину
lst1 = wo[wo[0]<3]['index'].tolist()
lst2 = wo[wo[0]>5000]['index'].tolist()
dop = ['просить', 'уважение', 'требоваться', 'необходимый', 'добрый', 'день', 'здравствуйте', 'нужный']
#Объединяем
R = rr+lst1+lst2+dop
#В столбце Коммент1 из всех строк убираем ранее полученные стоп-слова
df['Коммент1'] =df['Коммент1'].apply(lambda x: ' '.join([word for word in x.split() if word not in (R)]))
df
Коммент | Коммент1 | |
0 | в помещение до в связи с работами на линии бу… | помещение связь работа линия отсутствовать све… |
1 | в всп выбивает свет\nнагрев проводов искрение … | всп выбивать свет нагрев проводы искрение зады… |
2 | оборвало пружину на воротах… | ворот подниматься автоматичес… |
3 | ремонт розеток светильников замена ламп радиоз… | зона потолок |
4 | кабинет зона обслуживания юридических лиц выд… | кабинет зона обслуживание юридический лицо оши… |
… | … | … |
22340 | регулировка приточной вентиляции настройка те… | регулировка приточный вентиляция настройка тем… |
22341 | искрит провод на рабочем месте окно номер \nна… | искрить провод рабочий место окно номер нагрев… |
22342 | с г по г с до будет отключена электроэнергия… | отключить электроэнергия письмо вложение нагре… |
22343 | плановое отключение электроэнергии с до \nна… | плановый отключение электроэнергия нагрев пров… |
22344 | прошу посмотреть почему в кассу через вентиляц… | посмотреть касса вентиляция заходить запах ули… |
22345 rows × 2 columns
Таким образом мы привели все предложения в комментариях к нормальной форме, что необходимо для последующей классификации обращений.
Итак, нам нужно определить филиалы, в которых ситуация с поломками достигает критического уровня. Используем для этого text-mining.
Определимся с критериями оценки критичности поломок в филиале. Будем считать количество заявок из одного филиала по поводу одной и той же поломки, чтобы выявить проблемы, возникающие неоднократно.
Также обратим внимание на выразительные заявки, в которых негативная тональность текста выше, чем в остальных. Как правило, такие заявки пишут тогда, когда проблема критична для работы филиала или проблема не решается в течение длительного времени.
- Применение ML
Импортируем все необходимые библиотеки/модули:
import sklearn
from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer
from sklearn.decomposition import TruncatedSVD
from sklearn.linear_model import LogisticRegression, SGDClassifier
from sklearn.model_selection import GridSearchCV
from sklearn.multiclass import OneVsRestClassifier
from sklearn.metrics import f1_score
from sklearn.ensemble import RandomForestClassifier
Для анализа тональности применялся классификатор RandomForest из библиотеки sklearn. Помимо этих критериев, использовались данные о том, как много заявок из этого филиала не закрыли в срок, часто ли и как долго продлевался срок исполнения заявок.
Для большей гибкости анализа составляем матрицу весов отобранных показателей.
Варьируя элементы матрицы можно повысить значимость того или иного компонента, основываясь на сравнении ожидаемого и получаемого результата. Показатели, умноженные на их веса, просуммируем для каждого обращения.
Теперь у нас есть возможность подсчитать суммарную критичность обращений по филиалам, категориям работ и по тому и другому одновременно. Такой анализ позволяет увидеть поломки какого вида характерны для данного филиала и рассмотреть возможные причины.
Также мы можем оценить качество работы подрядных организаций, сравнивая показатель критичности в филиалах в зоне их ответственности с критичностью в других филиалах.
Таким образом, с применением интеллектуального анализа текста, удалось выявить точки концентрации поломок, определить западающие категории поломок, проанализировать возможную причину и эффективность деятельности подрядных организаций.