Afbeelding door redacteur
Met de toenemende belangstelling voor natuurlijke taalverwerking, stuiten steeds meer beoefenaars op de muur, niet omdat ze geen LLM's kunnen bouwen of verfijnen, maar omdat hun gegevens rommelig zijn!
We zullen eenvoudige, maar zeer effectieve coderingsprocedures laten zien voor het corrigeren van luidruchtige labels in tekstgegevens. We behandelen 2 veelvoorkomende scenario's in tekstgegevens uit de echte wereld:
- Een categorie hebben die gemengde voorbeelden uit een paar andere categorieën bevat. Ik noem dit soort categorieën graag een metacategorie.
- Het hebben van 2 of meer categorieën die samengevoegd dienen te worden tot 1 categorie omdat daarbij behorende teksten naar hetzelfde onderwerp verwijzen.
We gebruiken de ITSM-gegevensset (IT Service Management) die voor deze zelfstudie is gemaakt (CCO-licentie). Het is beschikbaar op Kaggle via de onderstaande link:
https://www.kaggle.com/datasets/nikolagreb/small-itsm-dataset
Het is tijd om te beginnen met het importeren van alle benodigde bibliotheken en het basisonderzoek van de gegevens. Zet je schrap, de code komt eraan!
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
Elke rij vertegenwoordigt één item in de ITSM-database. We zullen proberen de categorie van het ticket te voorspellen op basis van de tekst van het ticket die door een gebruiker is geschreven. Laten we dieper ingaan op de belangrijkste velden voor beschreven zakelijke use cases.
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
----------------------------------------------------------------------------------------------------
Als we naar de eerste twee kaartjes kijken, hoewel één kaartje in het Duits is, kunnen we zien dat de beschreven problemen verwijzen naar dezelfde software?—?Asana, maar ze dragen verschillende labels. Dit is de startverdeling van onze categorieën:
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
De benodigde hulp ziet er verdacht uit, zoals de categorie die tickets uit meerdere andere categorieën kan bevatten. Ook klinken de categorieën Outlook en Mail vergelijkbaar, misschien moeten ze worden samengevoegd tot één categorie. Voordat we dieper in de genoemde categorieën duiken, zullen we de ontbrekende waarden in kolommen van ons belang wegwerken.
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)
Er is geen geldig alternatief voor het onderzoeken van gegevens met het blote oog. De mooie functie om dit in panda's te doen is .sample(), dus we zullen precies dat nog een keer doen, nu voor de verdachte categorie:
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.
---------------------------------------------------------------------------
Het is duidelijk dat we tickets hebben die praten over Discord, Asana en CRM. De naam van de categorie moet dus worden gewijzigd van "Hulp nodig" in bestaande, meer specifieke categorieën. Voor de eerste stap van het hertoewijzingsproces maken we de nieuwe kolom "Sleutelwoorden" die de informatie geeft als het ticket het woord uit de lijst met categorieën in de kolom "Tekst" bevat.
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)
Merk ook op dat het gebruik van "if word in str(words_categories)" in plaats van "if word in words_categories" woorden zou vangen uit categorieën met meer dan 1 woord (internetbrowser in ons geval), maar ook meer voorverwerking van gegevens zou vereisen. Om het simpel en duidelijk te houden, gebruiken we de code voor categorieën die uit slechts één woord bestaan. Zo ziet onze dataset er nu uit:
df.head(2)
uitvoer als afbeelding:
Na het extraheren van de kolom met trefwoorden, gaan we uit van de kwaliteit van de tickets. Onze hypothese:
- Ticket met slechts 1 trefwoord in het tekstveld dat hetzelfde is als de categorie waartoe het ticket behoort, zou gemakkelijk te classificeren zijn.
- Ticket met meerdere trefwoorden in het veld Tekst, waarbij ten minste één van de trefwoorden hetzelfde is als de categorie waartoe het ticket behoort, is in de meeste gevallen eenvoudig te classificeren.
- Het ticket dat trefwoorden heeft, maar geen van hen is gelijk aan de naam van de categorie waartoe het ticket behoort, is waarschijnlijk een luidruchtig labelgeval.
- Andere tickets zijn neutraal op basis van trefwoorden.
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
We hebben onze nieuwe distributie gemaakt en nu is het tijd om tickets te onderzoeken die als een potentieel probleem zijn geclassificeerd. In de praktijk zou de volgende stap veel meer steekproeven vereisen en de grotere brokken gegevens met het blote oog bekijken, maar de grondgedachte zou hetzelfde zijn. Het is de bedoeling dat u problematische tickets vindt en beslist of u de kwaliteit ervan kunt verbeteren of dat u ze uit de dataset moet verwijderen. Als u met een grote dataset wordt geconfronteerd, blijf dan kalm en vergeet niet dat het onderzoeken en voorbereiden van gegevens meestal veel meer tijd kost dan het bouwen van ML-algoritmen!
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
--------------------------------------------------------------------
We begrijpen dat tickets uit Outlook- en Mail-categorieën gerelateerd zijn aan hetzelfde probleem, dus we zullen deze 2 categorieën samenvoegen en de resultaten van ons toekomstige ML-classificatie-algoritme verbeteren.
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
Last but not least willen we enkele tickets herlabelen van de metacategorie "Hulp nodig" naar de juiste categorie.
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
We hebben onze gegevens opnieuw gelabeld en opgeschoond, maar we mogen onszelf geen datawetenschappers noemen als we niet ten minste één wetenschappelijk experiment doen en de impact van ons werk op de uiteindelijke classificatie testen. We zullen dit doen door de Complement Naive Bayes-classificatie in sklearn te implementeren. Voel je vrij om andere, complexere algoritmen te proberen. Houd er ook rekening mee dat verdere gegevensopschoning kan worden gedaan - we kunnen bijvoorbeeld ook alle resterende tickets in de categorie "Hulp nodig" plaatsen.
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
Behoorlijk indrukwekkend, toch? De dataset die we hebben gebruikt is klein (met opzet, zodat u gemakkelijk kunt zien wat er in elke stap gebeurt), dus verschillende willekeurige zaden kunnen verschillende resultaten opleveren, maar in de overgrote meerderheid van de gevallen zal het model aanzienlijk beter presteren op de dataset na het opschonen vergeleken met naar de oorspronkelijke dataset. We hebben goed werk geleverd!
Nikola Greb codeert al meer dan vier jaar en de afgelopen twee jaar specialiseerde hij zich in NLP. Voordat hij zich tot data science wendde, was hij succesvol in sales, HR, schrijven en schaken.
- Door SEO aangedreven content en PR-distributie. Word vandaag nog versterkt.
- Platoblockchain. Web3 Metaverse Intelligentie. Kennis versterkt. Toegang hier.
- De toekomst slaan met Adryenn Ashley. Toegang hier.
- Bron: 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
- : heeft
- :is
- :niet
- :waar
- 1
- 10
- 100
- 11
- 2%
- 7
- 8
- 9
- a
- Over
- Account
- nauwkeurigheid
- Na
- Agent
- algoritme
- algoritmen
- Alles
- ook
- Hoewel
- an
- en
- ZIJN
- AS
- At
- Beschikbaar
- gebaseerde
- basis-
- BE
- omdat
- geweest
- vaardigheden
- onder
- Betere
- geblokkeerd
- browser
- bouw
- Gebouw
- bedrijfsdeskundigen
- maar
- by
- Bellen
- CAN
- dragen
- geval
- gevallen
- KAT
- het worstelen
- categorieën
- Categorie
- verandering
- Schaakspel
- classificatie
- geklasseerd
- classificeren
- Schoonmaak
- TROS
- code
- codering
- Kolom
- columns
- COM
- Gemeen
- afstand
- vergeleken
- Aanvulling
- complex
- Verbinden
- versterken
- bevat
- kon
- en je merk te creëren
- aangemaakt
- CRM
- gegevens
- Data voorbereiding
- data science
- Database
- transactie
- omgang
- beslissen
- diepere
- beschreven
- DEED
- anders
- onenigheid
- distributie
- do
- don
- Val
- elk
- gemakkelijk
- effectief
- ingeschakeld
- toegang
- Ether (ETH)
- precies
- voorbeeld
- voorbeelden
- bestaand
- verwacht
- experiment
- uitgelegd
- oog
- naar
- weinig
- veld-
- Velden
- finale
- VIND DE PLEK DIE PERFECT VOOR JOU IS
- Voornaam*
- volgend
- Voor
- vier
- Gratis
- oppompen van
- functie
- verder
- toekomst
- Duits
- krijgen
- Geven
- geeft
- Go
- goed
- gebeurt
- Hebben
- he
- hoofdtelefoons
- hulp
- raken
- Hoe
- hr
- HTTPS
- HubSpot
- i
- beeld
- Impact
- uitvoering
- importeren
- belangrijk
- indrukwekkend
- verbeteren
- in
- index
- informatie
- verkrijgen in plaats daarvan
- belang
- Internet
- in
- kwestie
- IT
- IT-dienst
- voor slechts
- eentje maar
- KDnuggets
- Houden
- Soort
- label
- labels
- taal
- laptop
- Groot
- groter
- bibliotheken
- Vergunning
- als
- LINK
- Lijst
- Kijk
- op zoek
- LOOKS
- liefde
- gemaakt
- Meerderheid
- management
- veel
- Marketing
- Media
- Leden
- Geheugen
- vermeld
- gaan
- meta
- Metriek
- macht
- vermist
- gemengd
- ML
- model
- meer
- meest
- meervoudig
- naam
- Naturel
- Natuurlijke taal
- Natural Language Processing
- nodig
- Neutraal
- New
- nlp
- notitieboekje
- nu
- aantal
- numpy
- object
- of
- Kantoor
- Oud
- on
- EEN
- Keuze
- or
- bestellen
- origineel
- Overige
- onze
- Outlook
- uitgang
- panda's
- verleden
- PC
- uitvoeren
- pijpleiding
- Plato
- Plato gegevensintelligentie
- PlatoData
- dan
- punt
- mogelijk
- potentieel
- praktijk
- voorspellen
- waarschijnlijk
- probleem
- problemen
- procedures
- verwerking
- produceren
- gepast
- doel
- kwaliteit
- willekeurige
- echte wereld
- verwant
- vertegenwoordigt
- vereisen
- antwoord
- Resultaten
- terugkeer
- bevrijden
- stijgende
- RIJ
- verkoop
- dezelfde
- scenario's
- Wetenschap
- wetenschappers
- zien
- zaden
- lijkt
- service
- reeks
- moet
- tonen
- aanzienlijk
- gelijk
- Eenvoudig
- sinds
- Klein
- So
- Social
- social media
- Software
- oplossing
- sommige
- Geluid
- gespecialiseerde
- specifiek
- spleet
- begin
- Start
- blijven
- Stap voor
- gestopt
- recht
- Draad
- geslaagd
- vermeend
- verdacht
- Nemen
- Talk
- praat
- team
- Leden van het team
- proef
- neem contact
- dat
- De
- de informatie
- hun
- Ze
- Er.
- Deze
- ze
- spullen
- dit
- ticket
- tickets
- niet de tijd of
- naar
- ook
- onderwerp
- Totaal
- Trainen
- Trainingen
- Draai
- zelfstudie
- begrijpen
- bijwerken
- bijgewerkt
- us
- Gebruik
- .
- gebruikt
- Gebruiker
- gebruik
- doorgaans
- Values
- groot
- zeer
- via
- Gevel
- was
- we
- Wat
- wanneer
- welke
- wie ook
- wil
- ruiten
- Met
- zonder
- Woord
- woorden
- Mijn werk
- werkzaam
- zou
- het schrijven van
- geschreven
- X
- jaar
- u
- jezelf
- zephyrnet