Зображення редактора
Зі зростанням інтересу до обробки природної мови все більше практиків натикаються на стіну не тому, що вони не можуть побудувати або налаштувати LLM, а тому, що їхні дані безладні!
Ми покажемо прості, але дуже ефективні процедури кодування для виправлення зашумлених міток у текстових даних. Ми розглянемо 2 загальні сценарії в текстових даних реального світу:
- Наявність категорії, яка містить змішані приклади з кількох інших категорій. Мені подобається називати таку категорію метакатегорією.
- Наявність 2 або більше категорій, які слід об’єднати в 1 категорію, оскільки тексти, що належать до них, стосуються однієї теми.
Ми будемо використовувати набір даних ITSM (ІТ-сервіс управління), створений для цього підручника (ліцензія CCO). Він доступний на Kaggle за посиланням нижче:
https://www.kaggle.com/datasets/nikolagreb/small-itsm-dataset
Настав час почати з імпорту всіх необхідних бібліотек і базової перевірки даних. Будьте готові, код надходить!
import pandas as pd
import numpy as np
import string from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import ComplementNB
from sklearn.pipeline import make_pipeline
from sklearn.model_selection import train_test_split
from sklearn import metrics df = pd.read_excel("ITSM_data.xlsx")
df.info()
RangeIndex: 118 entries, 0 to 117
Data columns (total 7 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 ID_request 118 non-null int64 1 Text 117 non-null object 2 Category 115 non-null object 3 Solution 115 non-null object 4 Date_request_recieved 118 non-null datetime64[ns] 5 Date_request_solved 118 non-null datetime64[ns] 6 ID_agent 118 non-null int64 dtypes: datetime64[ns](2), int64(2), object(3)
memory usage: 6.6+ KB
Кожен рядок представляє один запис у базі даних ITSM. Ми спробуємо передбачити категорію квитка на підставі тексту квитка, написаного користувачем. Давайте глибше розглянемо найважливіші поля для описаних бізнес-випадків використання.
for text, category in zip(df.Text.sample(3, random_state=2), df.Category.sample(3, random_state=2)): print("TEXT:") print(text) print("CATEGORY:") print(category) print("-"*100)
TEXT:
I just want to talk to an agent, there are too many problems on my pc to be explained in one ticket. Please call me when you see this, whoever you are. (talk to agent)
CATEGORY:
Asana
----------------------------------------------------------------------------------------------------
TEXT:
Asana funktionierte nicht mehr, nachdem ich meinen Laptop neu gestartet hatte. Bitte helfen Sie.
CATEGORY:
Help Needed
----------------------------------------------------------------------------------------------------
TEXT:
My mail stopped to work after I updated Windows.
CATEGORY:
Outlook
----------------------------------------------------------------------------------------------------
Якщо ми подивимося на перші два квитки, хоча одна квитка німецькою мовою, ми побачимо, що описані проблеми стосуються того самого програмного забезпечення?—?Asana, але вони мають різні мітки. Це початок розподілу наших категорій:
df.Category.value_counts(normalize=True, dropna=False).mul(100).round(1).astype(str) + "%"
Outlook 19.1%
Discord 13.9%
CRM 12.2%
Internet Browser 10.4%
Mail 9.6%
Keyboard 9.6%
Asana 8.7%
Mouse 8.7%
Help Needed 7.8%
Name: Category, dtype: object
Потрібна допомога виглядає підозріло, як-от категорія, яка може містити квитки з кількох інших категорій. Крім того, категорії Outlook і Mail звучать схоже, можливо, їх варто об’єднати в одну категорію. Перш ніж заглибитися в згадані категорії, ми позбудемося відсутніх значень у стовпцях, які нас цікавлять.
important_columns = ["Text", "Category"]
for cat in important_columns: df.drop(df[df[cat].isna()].index, inplace=True)
df.reset_index(inplace=True, drop=True)
Немає належної заміни перевірці даних неозброєним оком. Чудова функція для цього в pandas — .sample(), тому ми зробимо саме це ще раз, тепер для підозрілої категорії:
meta = df[df.Category == "Help Needed"] for text in meta.Text.sample(5, random_state=2): print(text) print("-"*100)
Discord emojis aren't available to me, I would like to have this option enabled like other team members have.
---------------------------------------------------------------------------
Bitte reparieren Sie mein Hubspot CRM. Seit gestern funktioniert es nicht mehr
---------------------------------------------------------------------------
My headphones aren't working. I would like to order new.
---------------------------------------------------------------------------
Bundled problems with Office since restart:
Messages not sent
Outlook does not connect, mails do not arrive
Error 0x8004deb0 appears when Connection attempt, see attachment
The company account is affected: AB123
Access via Office.com seems to be possible.
---------------------------------------------------------------------------
Asana funktionierte nicht mehr, nachdem ich meinen Laptop neu gestartet hatte. Bitte helfen Sie.
---------------------------------------------------------------------------
Очевидно, у нас є квитки про Discord, Asana та CRM. Тому назву категорії слід змінити з «Потрібна допомога» на існуючі, більш конкретні категорії. На першому етапі процесу перепризначення ми створимо новий стовпець «Ключові слова», який надасть інформацію, чи містить заявка слово зі списку категорій у стовпці «Текст».
words_categories = np.unique([word.strip().lower() for word in df.Category]) # list of categories def keywords(row): list_w = [] for word in row.translate(str.maketrans("", "", string.punctuation)).lower().split(): if word in words_categories: list_w.append(word) return list_w df["Keywords"] = df.Text.apply(keywords) # since our output is in the list, this function will give us better looking final output. def clean_row(row): row = str(row) row = row.replace("[", "") row = row.replace("]", "") row = row.replace("'", "") row = string.capwords(row) return row df["Keywords"] = df.Keywords.apply(clean_row)
Також зауважте, що використання «if word in str(words_categories)» замість «if word in words_categories» перехопить слова з категорій із більш ніж 1 словом (у нашому випадку Інтернет-браузер), але також вимагатиме додаткової попередньої обробки даних. Щоб все було просто і прямо по суті, ми використаємо код для категорій, який складається лише з одного слова. Ось як зараз виглядає наш набір даних:
df.head(2)
вивести як зображення:
Після вилучення стовпця ключових слів ми припустимо якість квитків. Наша гіпотеза:
- Квиток із лише одним ключовим словом у текстовому полі, яке збігається з категорією, до якої належить квиток, буде легко класифікувати.
- Квиток із кількома ключовими словами в текстовому полі, де принаймні одне з ключових слів збігається з категорією, до якої належить квиток, у більшості випадків легко класифікувати.
- Квиток, який містить ключові слова, але жодне з них не відповідає назві категорії, до якої належить квиток, ймовірно, є шумною міткою.
- Інші квитки нейтральні за ключовими словами.
cl_list = [] for category, keywords in zip(df.Category, df.Keywords): if category.lower() == keywords.lower() and keywords != "": cl_list.append("easy_classification") elif category.lower() in keywords.lower(): # to deal with multiple keywords in the ticket cl_list.append("probably_easy_classification") elif category.lower() != keywords.lower() and keywords != "": cl_list.append("potential_problem") else: cl_list.append("neutral") df["Ease_classification"] = cl_list
df.Ease_classification.value_counts(normalize=True, dropna=False).mul(100).round(1).astype(str) + "%"
neutral 45.6%
easy_classification 37.7%
potential_problem 9.6%
probably_easy_classification 7.0%
Name: Ease_classification, dtype: object
Ми зробили наш новий розподіл, і зараз настав час перевірити квитки, класифіковані як потенційна проблема. На практиці наступний крок вимагатиме значно більшої вибірки та перегляду більших фрагментів даних неозброєним оком, але обґрунтування буде таким же. Ви повинні знайти проблемні квитки та вирішити, чи можете ви покращити їхню якість, чи вам слід видалити їх із набору даних. Коли ви стикаєтеся з великим набором даних, зберігайте спокій і не забувайте, що аналіз і підготовка даних зазвичай займають набагато більше часу, ніж створення алгоритмів ML!
pp = df[df.Ease_classification == "potential_problem"] for text, category in zip(pp.Text.sample(5, random_state=2), pp.Category.sample(3, random_state=2)): print("TEXT:") print(text) print("CATEGORY:") print(category) print("-"*100)
TEXT:
outlook issue , I did an update Windows and I have no more outlook on my notebook ? Please help !
Outlook
CATEGORY:
Mail
-------------------------------------------------------------------- TEXT:
Please relase blocked attachements from the mail I got from name.surname@company.com. These are data needed for social media marketing campaing.
CATEGORY:
Outlook
--------------------------------------------------------------------
TEXT:
Asana funktionierte nicht mehr, nachdem ich meinen Laptop neu gestartet hatte. Bitte helfen Sie.
CATEGORY:
Help Needed
--------------------------------------------------------------------
Ми розуміємо, що заявки з категорій Outlook і Mail пов’язані з тією самою проблемою, тому ми об’єднаємо ці 2 категорії та покращимо результати нашого майбутнього алгоритму класифікації ML.
mail_categories_to_merge = ["Outlook", "Mail"] sum_mail_cluster = 0
for x in mail_categories_to_merge: sum_mail_cluster += len(df[df["Category"] == x]) print("Number of categories to be merged into new cluster: ", len(mail_categories_to_merge))
print("Expected number of tickets in the new cluster: ", sum_mail_cluster) def rename_to_mail_cluster(category): if category in mail_categories_to_merge: category = "Mail_CLUSTER" else: category = category return category df["Category"] = df["Category"].apply(rename_to_mail_cluster) df.Category.value_counts()
Number of categories to be merged into new cluster: 2
Expected number of tickets in the new cluster: 33
Mail_CLUSTER 33
Discord 15
CRM 14
Internet Browser 12
Keyboard 11
Asana 10
Mouse 10
Help Needed 9
Name: Category, dtype: int64
І останнє, але не менш важливе: ми хочемо змінити позначки деяких заявок із метакатегорії «Потрібна допомога» на правильну категорію.
df.loc[(df["Category"] == "Help Needed") & ([set(x).intersection(words_categories) for x in df["Text"].str.lower().str.replace("[^ws]", "", regex=True).str.split()]), "Category"] = "Change" def cat_name_change(cat, keywords): if cat == "Change": cat = keywords else: cat = cat return cat df["Category"] = df.apply(lambda x: cat_name_change(x.Category, x.Keywords), axis=1)
df["Category"] = df["Category"].replace({"Crm":"CRM"}) df.Category.value_counts(dropna=False)
Mail_CLUSTER 33
Discord 16
CRM 15
Internet Browser 12
Asana 11
Keyboard 11
Mouse 10
Help Needed 6
Name: Category, dtype: int64
Ми перемаркували та очистили наші дані, але ми не повинні називати себе науковцями з даних, якщо не проведемо принаймні один науковий експеримент і не перевіримо вплив нашої роботи на остаточну класифікацію. Ми зробимо це, реалізувавши класифікатор Complement Naive Bayes у sklearn. Не соромтеся спробувати інші, більш складні алгоритми. Крім того, майте на увазі, що може бути виконано подальше очищення даних – наприклад, ми також можемо видалити всі заявки, що залишилися, у категорії «Потрібна допомога».
model = make_pipeline(TfidfVectorizer(), ComplementNB()) # old df
df_o = pd.read_excel("ITSM_data.xlsx") important_categories = ["Text", "Category"]
for cat in important_categories: df_o.drop(df_o[df_o[cat].isna()].index, inplace=True) df_o.name = "dataset just without missing"
df.name = "dataset after deeper cleaning" for dataframe in [df_o, df]: # Split dataset into training set and test set X_train, X_test, y_train, y_test = train_test_split(dataframe.Text, dataframe.Category, test_size=0.2, random_state=1) # Training the model with train data model.fit(X_train, y_train) # Predict the response for test dataset y_pred = model.predict(X_test) print(f"Accuracy of Complement Naive Bayes classifier model on {dataframe.name} is: {round(metrics.accuracy_score(y_test, y_pred),2)}")
Accuracy of Complement Naive Bayes classifier model on dataset just without missing is: 0.48
Accuracy of Complement Naive Bayes classifier model on dataset after deeper cleaning is: 0.65
Досить вражаюче, правда? Набір даних, який ми використали, невеликий (навмисно, тому ви можете легко побачити, що відбувається на кожному кроці), тому різні випадкові вихідні числа можуть дати різні результати, але в переважній більшості випадків модель працюватиме значно краще на наборі даних після очищення порівняно з до вихідного набору даних. Ми добре попрацювали!
Микола Греб займався програмуванням більше чотирьох років, а останні два роки спеціалізувався на НЛП. Перш ніж звернутись до науки про дані, він успішно займався продажами, HR, писанням і шахами.
- Розповсюдження контенту та PR на основі SEO. Отримайте посилення сьогодні.
- Платоблокчейн. Web3 Metaverse Intelligence. Розширені знання. Доступ тут.
- Карбування майбутнього з Адріенн Ешлі. Доступ тут.
- джерело: https://www.kdnuggets.com/2023/04/dealing-noisy-labels-text-data.html?utm_source=rss&utm_medium=rss&utm_campaign=dealing-with-noisy-labels-in-text-data
- : має
- :є
- : ні
- :де
- 1
- 10
- 100
- 11
- 2%
- 7
- 8
- 9
- a
- МЕНЮ
- рахунки
- точність
- після
- Агент
- алгоритм
- алгоритми
- ВСІ
- Також
- хоча
- an
- та
- ЕСТЬ
- AS
- At
- доступний
- заснований
- основний
- BE
- оскільки
- було
- перед тим
- нижче
- Краще
- блокований
- браузер
- будувати
- Створюємо
- бізнес
- але
- by
- call
- CAN
- нести
- випадок
- випадків
- КПП
- Залучайте
- категорії
- Категорія
- зміна
- Chess
- класифікація
- класифікований
- Класифікувати
- Очищення
- кластер
- код
- Кодування
- Колонка
- Колони
- COM
- загальний
- компанія
- порівняний
- Доповнення
- комплекс
- З'єднуватися
- зв'язку
- містить
- може
- створювати
- створений
- CRM
- дані
- Підготовка даних
- наука про дані
- Database
- угода
- справу
- вирішувати
- глибше
- описаний
- DID
- різний
- розбрат
- розподіл
- do
- Дон
- Падіння
- кожен
- легко
- Ефективний
- включений
- запис
- Ефір (ETH)
- точно
- приклад
- Приклади
- існуючий
- очікуваний
- експеримент
- пояснені
- очей
- облицювання
- кілька
- поле
- Поля
- остаточний
- знайти
- Перший
- після
- для
- чотири
- Безкоштовна
- від
- функція
- далі
- майбутнє
- німецька
- отримати
- Давати
- дає
- Go
- добре
- відбувається
- Мати
- he
- навушники
- допомога
- удар
- Як
- hr
- HTTPS
- HubSpot
- i
- зображення
- Impact
- реалізації
- імпорт
- важливо
- вражаючий
- удосконалювати
- in
- індекс
- інформація
- замість
- інтерес
- інтернет
- в
- питання
- IT
- IT service
- просто
- тільки один
- KDnuggets
- тримати
- Дитина
- етикетка
- етикетки
- мова
- портативний комп'ютер
- великий
- більше
- libraries
- ліцензія
- як
- LINK
- список
- подивитися
- шукати
- ВИГЛЯДИ
- любов
- made
- Більшість
- управління
- багато
- Маркетинг
- Медіа
- члени
- пам'ять
- згаданий
- Злиття
- Meta
- Метрика
- може бути
- відсутній
- змішаний
- ML
- модель
- більше
- найбільш
- множинний
- ім'я
- Природний
- Природна мова
- Обробка природних мов
- необхідний
- Нейтральний
- Нові
- nlp
- ноутбук
- зараз
- номер
- нумпі
- об'єкт
- of
- Office
- Старий
- on
- ONE
- варіант
- or
- порядок
- оригінал
- Інше
- наші
- прогноз
- вихід
- панди
- Минуле
- PC
- виконувати
- трубопровід
- plato
- Інформація про дані Платона
- PlatoData
- будь ласка
- точка
- це можливо
- потенціал
- практика
- передбачати
- ймовірно
- Проблема
- проблеми
- Процедури
- процес
- обробка
- виробляти
- правильний
- мета
- якість
- випадковий
- Реальний світ
- пов'язаний
- представляє
- вимагати
- відповідь
- результати
- повертати
- позбавитися
- підвищення
- ROW
- продажів
- то ж
- сценарії
- наука
- Вчені
- побачити
- Насіння
- Здається,
- обслуговування
- комплект
- Повинен
- Показувати
- істотно
- аналогічний
- простий
- з
- невеликий
- So
- соціальна
- соціальні медіа
- Софтвер
- рішення
- деякі
- Звучати
- спеціалізований
- конкретний
- розкол
- старт
- Починаючи
- залишатися
- Крок
- зупинений
- прямий
- рядок
- успішний
- передбачуваний
- підозрілі
- Приймати
- балаканина
- говорити
- команда
- Члени команди
- тест
- ніж
- Що
- Команда
- інформація
- їх
- Їх
- Там.
- Ці
- вони
- речі
- це
- квиток
- квитки
- час
- до
- занадто
- тема
- Усього:
- поїзд
- Навчання
- Поворот
- підручник
- розуміти
- Оновити
- оновлений
- us
- Використання
- використання
- використовуваний
- користувач
- використання
- зазвичай
- Цінності
- величезний
- дуже
- через
- Стіна
- було
- we
- Що
- коли
- який
- хто б не
- волі
- windows
- з
- без
- слово
- слова
- Work
- робочий
- б
- лист
- письмовий
- X
- років
- ви
- себе
- зефірнет