Bild vom Herausgeber
Mit dem steigenden Interesse an der Verarbeitung natürlicher Sprache stoßen immer mehr Praktiker an die Wand, nicht weil sie keine LLMs bauen oder optimieren können, sondern weil ihre Daten chaotisch sind!
Wir zeigen einfache, aber sehr effektive Kodierverfahren zum Korrigieren verrauschter Labels in Textdaten. Wir werden uns mit 2 gängigen Szenarien in realen Textdaten befassen:
- Eine Kategorie haben, die gemischte Beispiele aus einigen anderen Kategorien enthält. Ich nenne diese Art von Kategorie gerne eine Metakategorie.
- 2 oder mehr Kategorien haben, die in 1 Kategorie zusammengeführt werden sollten, weil sich die zugehörigen Texte auf dasselbe Thema beziehen.
Wir verwenden das für dieses Tutorial erstellte ITSM-Dataset (IT Service Management) (CCO-Lizenz). Es ist auf Kaggle unter dem folgenden Link verfügbar:
https://www.kaggle.com/datasets/nikolagreb/small-itsm-dataset
Es ist an der Zeit, mit dem Import aller benötigten Bibliotheken und der grundlegenden Datenprüfung zu beginnen. Mach dich bereit, Code kommt!
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
Jede Zeile repräsentiert einen Eintrag in der ITSM-Datenbank. Wir werden versuchen, die Kategorie des Tickets basierend auf dem Text des Tickets, der von einem Benutzer geschrieben wurde, vorherzusagen. Lassen Sie uns die wichtigsten Felder für die beschriebenen Geschäftsanwendungsfälle genauer untersuchen.
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
----------------------------------------------------------------------------------------------------
Wenn wir uns die ersten beiden Tickets ansehen, obwohl ein Ticket auf Deutsch ist, können wir sehen, dass sich die beschriebenen Probleme auf dieselbe Software beziehen? –? Asana, aber sie tragen unterschiedliche Labels. Dies ist die Startverteilung unserer Kategorien:
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
Die benötigte Hilfe sieht verdächtig aus, wie die Kategorie, die Tickets aus mehreren anderen Kategorien enthalten kann. Außerdem klingen die Kategorien Outlook und Mail ähnlich, vielleicht sollten sie zu einer Kategorie zusammengeführt werden. Bevor wir tiefer in die genannten Kategorien eintauchen, werden wir fehlende Werte in Spalten unseres Interesses beseitigen.
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)
Es gibt keinen gültigen Ersatz für die Untersuchung von Daten mit bloßem Auge. Die ausgefallene Funktion dafür in Pandas ist .sample(), also werden wir genau das noch einmal tun, jetzt für die verdächtige Kategorie:
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.
---------------------------------------------------------------------------
Offensichtlich haben wir Tickets, in denen es um Discord, Asana und CRM geht. Daher sollte der Name der Kategorie von „Hilfe benötigt“ in bestehende, spezifischere Kategorien geändert werden. Für den ersten Schritt des Neuzuweisungsprozesses erstellen wir die neue Spalte „Schlüsselwörter“, die angibt, ob das Ticket das Wort aus der Liste der Kategorien in der Spalte „Text“ enthält.
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)
Beachten Sie auch, dass die Verwendung von „if word in str(words_categories)“ anstelle von „if word in words_categories“ Wörter aus Kategorien mit mehr als einem Wort (in unserem Fall Internet-Browser) erfassen würde, aber auch mehr Datenvorverarbeitung erfordern würde. Um die Dinge einfach und direkt auf den Punkt zu bringen, verwenden wir den Code für Kategorien, die nur aus einem Wort bestehen. So sieht unser Datensatz jetzt aus:
df.head(2)
Ausgabe als Bild:
Nach dem Extrahieren der Schlüsselwortspalte gehen wir von der Qualität der Tickets aus. Unsere Hypothese:
- Ein Ticket mit nur 1 Schlüsselwort im Textfeld, das mit der Kategorie übereinstimmt, zu der das Ticket gehört, wäre leicht zu klassifizieren.
- Tickets mit mehreren Schlüsselwörtern im Textfeld, bei denen mindestens eines der Schlüsselwörter mit der Kategorie übereinstimmt, zu der das Ticket gehört, wären in den meisten Fällen einfach zu klassifizieren.
- Das Ticket, das Schlüsselwörter hat, aber keines davon gleich dem Namen der Kategorie ist, zu der das Ticket gehört, ist wahrscheinlich ein lauter Etikettenfall.
- Andere Tickets sind basierend auf Schlüsselwörtern neutral.
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
Wir haben unsere neue Verteilung vorgenommen und jetzt ist es an der Zeit, Tickets zu untersuchen, die als potenzielles Problem eingestuft wurden. In der Praxis würde der folgende Schritt viel mehr Stichproben erfordern und die größeren Datenblöcke mit bloßem Auge betrachten, aber die Begründung wäre die gleiche. Sie sollen problematische Tickets finden und entscheiden, ob Sie ihre Qualität verbessern können oder ob Sie sie aus dem Datensatz streichen sollten. Wenn Sie mit einem großen Datensatz konfrontiert sind, bleiben Sie ruhig und vergessen Sie nicht, dass die Datenprüfung und Datenvorbereitung normalerweise viel mehr Zeit in Anspruch nimmt als das Erstellen von ML-Algorithmen!
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
--------------------------------------------------------------------
Uns ist bewusst, dass Tickets aus den Outlook- und Mail-Kategorien mit demselben Problem zusammenhängen, daher werden wir diese beiden Kategorien zusammenführen und die Ergebnisse unseres zukünftigen ML-Klassifizierungsalgorithmus verbessern.
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
Zu guter Letzt möchten wir einige Tickets aus der Metakategorie „Hilfe benötigt“ in die richtige Kategorie umbenennen.
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
Wir haben unsere Daten neu gekennzeichnet und bereinigt, aber wir sollten uns nicht Datenwissenschaftler nennen, wenn wir nicht mindestens ein wissenschaftliches Experiment durchführen und die Auswirkungen unserer Arbeit auf die endgültige Klassifizierung testen. Wir werden dies tun, indem wir den Complement Naive Bayes-Klassifikator in sklearn implementieren. Probieren Sie ruhig andere, komplexere Algorithmen aus. Beachten Sie auch, dass eine weitere Datenbereinigung durchgeführt werden könnte – wir könnten beispielsweise auch alle verbleibenden Tickets in der Kategorie „Hilfe benötigt“ löschen.
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
Ziemlich beeindruckend, oder? Der von uns verwendete Datensatz ist klein (absichtlich, damit Sie leicht sehen können, was in jedem Schritt passiert), sodass unterschiedliche zufällige Ausgangswerte möglicherweise unterschiedliche Ergebnisse liefern, aber in den allermeisten Fällen wird das Modell nach der verglichenen Bereinigung auf dem Datensatz deutlich besser abschneiden zum Originaldatensatz. Wir haben einen guten Job gemacht!
Nikola Greb Programmiert seit mehr als vier Jahren und hat sich in den letzten zwei Jahren auf NLP spezialisiert. Bevor er sich der Datenwissenschaft zuwandte, war er erfolgreich im Verkauf, im Personalwesen, im Schreiben und im Schach.
- SEO-gestützte Content- und PR-Distribution. Holen Sie sich noch heute Verstärkung.
- Platoblockkette. Web3-Metaverse-Intelligenz. Wissen verstärkt. Hier zugreifen.
- Die Zukunft prägen mit Adryenn Ashley. Hier zugreifen.
- Quelle: 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
- :hast
- :Ist
- :nicht
- :Wo
- 1
- 10
- 100
- 11
- 2%
- 7
- 8
- 9
- a
- Über uns
- Konto
- Genauigkeit
- Nach der
- Makler
- Algorithmus
- Algorithmen
- Alle
- ebenfalls
- Obwohl
- an
- und
- SIND
- AS
- At
- verfügbar
- basierend
- basic
- BE
- weil
- war
- Bevor
- unten
- Besser
- verstopft
- Browser
- bauen
- Building
- Geschäft
- aber
- by
- rufen Sie uns an!
- CAN
- tragen
- Häuser
- Fälle
- CAT
- Ringen
- Kategorien
- Kategorie
- Übernehmen
- Schach
- Einstufung
- eingestuft
- klassifizieren
- Reinigung
- Cluster
- Code
- Programmierung
- Kolonne
- Spalten
- COM
- gemeinsam
- Unternehmen
- verglichen
- Ergänzung
- Komplex
- Vernetz Dich
- Verbindung
- enthält
- könnte
- erstellen
- erstellt
- CRM
- technische Daten
- Datenaufbereitung
- Datenwissenschaft
- Datenbase
- Deal
- Behandlung
- entscheidet
- tiefer
- beschrieben
- DID
- anders
- Zwietracht
- Verteilung
- do
- Don
- Drop
- jeder
- leicht
- Effektiv
- freigegeben
- Eintrag
- Äther (ETH)
- genau
- Beispiel
- Beispiele
- vorhandenen
- erwartet
- Experiment
- erklärt
- Auge
- zugewandt
- wenige
- Feld
- Felder
- Finale
- Finden Sie
- Vorname
- Folgende
- Aussichten für
- vier
- Frei
- für
- Funktion
- weiter
- Zukunft
- Deutsch
- bekommen
- ABSICHT
- gibt
- Go
- gut
- das passiert
- Haben
- he
- Kopfhörer
- Hilfe
- schlagen
- Ultraschall
- hr
- HTTPS
- HubSpot
- i
- Image
- Impact der HXNUMXO Observatorien
- Umsetzung
- importieren
- wichtig
- beeindruckend
- zu unterstützen,
- in
- Index
- Information
- beantragen müssen
- Interesse
- Internet
- in
- Problem
- IT
- IT-Service
- nur
- nur einer
- KDnuggets
- Behalten
- Art
- Label
- Etiketten
- Sprache
- Laptop
- grosse
- größer
- Bibliotheken
- Lizenz
- Gefällt mir
- LINK
- Liste
- aussehen
- suchen
- SIEHT AUS
- ich liebe
- gemacht
- Mehrheit
- Management
- viele
- Marketing
- Medien
- Mitglieder
- Memory
- erwähnt
- Merge
- Meta
- Metrik
- könnte
- Kommt demnächst...
- gemischt
- ML
- Modell
- mehr
- vor allem warme
- mehrere
- Name
- Natürliche
- Natürliche Sprache
- Verarbeitung natürlicher Sprache
- erforderlich
- Neutral
- Neu
- Nlp
- Notizbuch
- jetzt an
- Anzahl
- numpig
- Objekt
- of
- Office
- Alt
- on
- EINEM
- Option
- or
- Auftrag
- Original
- Andere
- UNSERE
- Outlook
- Möglichkeiten für das Ausgangssignal:
- Pandas
- passt
- PC
- ausführen
- Pipeline
- Plato
- Datenintelligenz von Plato
- PlatoData
- Bitte
- Points
- möglich
- Potenzial
- Praxis
- vorhersagen
- wahrscheinlich
- Aufgabenstellung:
- Probleme
- Verfahren
- Prozessdefinierung
- Verarbeitung
- produziert
- ordnungsgemäße
- Zweck
- Qualität
- zufällig
- realen Welt
- bezogene
- representiert
- erfordern
- Antwort
- Die Ergebnisse
- Rückkehr
- Loswerden
- Anstieg
- REIHE
- Vertrieb
- gleich
- Szenarien
- Wissenschaft
- Wissenschaftler
- sehen
- Saatgut
- scheint
- kompensieren
- sollte
- erklären
- bedeutend
- ähnlich
- Einfacher
- da
- klein
- So
- Social Media
- Social Media
- Software
- Lösung
- einige
- Klingen
- spezialisiert
- spezifisch
- gespalten
- Anfang
- Beginnen Sie
- bleiben
- Schritt
- gestoppt
- mit Stiel
- Schnur
- erfolgreich
- vermutet
- misstrauisch
- Nehmen
- Reden
- sprechen
- Team
- Teammitglieder
- Test
- als
- zur Verbesserung der Gesundheitsgerechtigkeit
- Das
- die Informationen
- ihr
- Sie
- Dort.
- Diese
- vom Nutzer definierten
- fehlen uns die Worte.
- Ticket
- Tickets
- Zeit
- zu
- auch
- Thema
- Gesamt
- Training
- Ausbildung
- Drehung
- Lernprogramm
- verstehen
- Aktualisierung
- aktualisiert
- us
- Anwendungsbereich
- -
- benutzt
- Mitglied
- Verwendung von
- gewöhnlich
- Werte
- riesig
- sehr
- Pinnwand
- wurde
- we
- Was
- wann
- welche
- wer auch immer
- werden wir
- Fenster
- mit
- ohne
- Word
- Worte
- Arbeiten
- arbeiten,
- würde
- Schreiben
- geschrieben
- X
- Jahr
- U
- sich selbst
- Zephyrnet