Bild av redaktör
Med det ökande intresset för bearbetning av naturligt språk slår fler och fler utövare väggen, inte för att de inte kan bygga eller finjustera LLM, utan för att deras data är rörig!
Vi kommer att visa enkla men ändå mycket effektiva kodningsprocedurer för att fixa brusiga etiketter i textdata. Vi kommer att behandla två vanliga scenarier i verklig textdata:
- Att ha en kategori som innehåller blandade exempel från några andra kategorier. Jag älskar att kalla den här typen av kategori för en metakategori.
- Att ha 2 eller fler kategorier som bör slås samman till 1 kategori eftersom texter som tillhör dem refererar till samma ämne.
Vi kommer att använda ITSM (IT Service Management) dataset som skapats för denna handledning (CCO-licens). Den är tillgänglig på Kaggle från länken nedan:
https://www.kaggle.com/datasets/nikolagreb/small-itsm-dataset
Det är dags att börja med import av alla bibliotek som behövs och grundläggande dataundersökning. Sätt på dig, koden kommer!
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
Varje rad representerar en post i ITSM-databasen. Vi kommer att försöka förutsäga kategorin för biljetten baserat på texten på biljetten som skrivits av en användare. Låt oss undersöka djupare de viktigaste områdena för beskrivna affärsanvändningsfall.
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
----------------------------------------------------------------------------------------------------
Om vi tar en titt på de två första biljetterna, även om en biljett är på tyska, kan vi se att beskrivna problem hänvisar till samma programvara?—?Asana, men de har olika etiketter. Detta börjar distributionen av våra kategorier:
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
Den hjälp som behövs ser misstänkt ut, som kategorin som kan innehålla biljetter från flera andra kategorier. Även kategorierna Outlook och Mail låter liknande, kanske borde de slås samman till en kategori. Innan vi dyker djupare in i nämnda kategorier kommer vi att bli av med saknade värden i kolumner av vårt intresse.
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)
Det finns ingen giltig ersättning för undersökning av data med bara ögat. Den snygga funktionen för att göra det i pandor är .sample(), så vi kommer att göra exakt det en gång till, nu för den misstänkta kategorin:
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.
---------------------------------------------------------------------------
Uppenbarligen har vi biljetter som talar om Discord, Asana och CRM. Så namnet på kategorin bör ändras från "Hjälp behövs" till befintliga, mer specifika kategorier. För det första steget i omtilldelningsprocessen kommer vi att skapa den nya kolumnen "Sökord" som ger information om biljetten har ordet från listan över kategorier i kolumnen "Text".
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)
Observera också att att använda "if word in str(words_categories)" istället för "if word in words_categories" skulle fånga ord från kategorier med mer än 1 ord (internetwebbläsare i vårt fall), men skulle också kräva mer dataförbearbetning. För att hålla saker och ting enkelt och rakt på sak kommer vi att gå med koden för kategorier som består av bara ett ord. Så här ser vår datauppsättning ut nu:
df.head(2)
mata ut som bild:
Efter att ha extraherat nyckelordskolumnen kommer vi att anta kvaliteten på biljetterna. Vår hypotes:
- Biljett med bara ett nyckelord i textfältet som är samma som kategorin som biljetten tillhör skulle vara lätt att klassificera.
- Biljett med flera nyckelord i textfältet, där minst ett av nyckelorden är samma som kategorin som biljetten tillhör skulle vara lätt att klassificera i de flesta fall.
- Biljetten som har nyckelord, men ingen av dem är lika med namnet på kategorin som biljetten tillhör är förmodligen ett bullrigt etikettfodral.
- Andra biljetter är neutrala baserat på nyckelord.
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
Vi gjorde vår nya distribution och nu är det dags att undersöka biljetter som klassificeras som ett potentiellt problem. I praktiken skulle följande steg kräva mycket mer sampling och titta på de större databitarna med bara ögat, men logiken skulle vara densamma. Det är meningen att du ska hitta problematiska biljetter och bestämma om du kan förbättra deras kvalitet eller om du ska ta bort dem från datamängden. När du står inför en stor datamängd, håll dig lugn och glöm inte att dataundersökning och dataförberedelse vanligtvis tar mycket mer tid än att bygga ML-algoritmer!
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
--------------------------------------------------------------------
Vi förstår att biljetter från Outlook- och Mail-kategorierna är relaterade till samma problem, så vi kommer att slå samman dessa två kategorier och förbättra resultaten av vår framtida ML-klassificeringsalgoritm.
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
Sist men inte minst vill vi märka om några biljetter från metakategorin "Hjälp behövs" till rätt kategori.
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
Vi gjorde ommärkning och rengöring av vår data men vi borde inte kalla oss datavetare om vi inte gör minst ett vetenskapligt experiment och testar effekten av vårt arbete på den slutliga klassificeringen. Vi kommer att göra det genom att implementera The Complement Naive Bayes classifier i sklearn. Prova gärna andra, mer komplexa algoritmer. Tänk också på att ytterligare datarensning kan göras – till exempel kan vi också släppa alla biljetter som finns kvar i kategorin "Hjälp behövs".
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
Ganska imponerande, eller hur? Datauppsättningen vi använde är liten (avsiktligt, så att du enkelt kan se vad som händer i varje steg) så olika slumpmässiga frön kan ge olika resultat, men i de allra flesta fall kommer modellen att prestera betydligt bättre på datasetet efter rengöring jämfört till den ursprungliga datamängden. Vi gjorde ett bra jobb!
Nikola Greb har kodat i mer än fyra år, och de senaste två åren har han specialiserat sig på NLP. Innan han började med datavetenskap var han framgångsrik inom försäljning, HR, skrivande och schack.
- SEO-drivet innehåll och PR-distribution. Bli förstärkt idag.
- Platoblockchain. Web3 Metaverse Intelligence. Kunskap förstärkt. Tillgång här.
- Minting the Future med Adryenn Ashley. Tillgång här.
- Källa: 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
- : har
- :är
- :inte
- :var
- 1
- 10
- 100
- 11
- 2%
- 7
- 8
- 9
- a
- Om oss
- Konto
- noggrannhet
- Efter
- Recensioner
- algoritm
- algoritmer
- Alla
- också
- Även
- an
- och
- ÄR
- AS
- At
- tillgänglig
- baserat
- grundläggande
- BE
- därför att
- varit
- innan
- nedan
- Bättre
- blockerad
- webbläsare
- SLUTRESULTAT
- Byggnad
- företag
- men
- by
- Ring
- KAN
- bära
- Vid
- fall
- KATT
- brottning
- kategorier
- Kategori
- byta
- schack
- klassificering
- klassificerad
- klassificera
- Rengöring
- kluster
- koda
- Kodning
- Kolumn
- Kolonner
- COM
- Gemensam
- företag
- jämfört
- Komplement
- komplex
- Kontakta
- anslutning
- innehåller
- kunde
- skapa
- skapas
- CRM
- datum
- Förberedelse av data
- datavetenskap
- Databas
- behandla
- som handlar om
- beslutar
- djupare
- beskriven
- DID
- olika
- oenighet
- fördelning
- do
- donation
- Drop
- varje
- lätt
- Effektiv
- aktiverad
- inträde
- Eter (ETH)
- exakt
- exempel
- exempel
- befintliga
- förväntat
- experimentera
- förklarade
- ögat
- vänd
- få
- fält
- Fält
- slutlig
- hitta
- Förnamn
- efter
- För
- fyra
- Fri
- från
- fungera
- ytterligare
- framtida
- tyska
- skaffa sig
- Ge
- ger
- Go
- god
- händer
- Har
- he
- hörlurar
- hjälpa
- slå
- Hur ser din drömresa ut
- hr
- HTTPS
- HubSpot
- i
- bild
- Inverkan
- genomföra
- importera
- med Esport
- imponerande
- förbättra
- in
- index
- informationen
- istället
- intresse
- Internet
- in
- fråga
- IT
- IT-tjänst
- bara
- bara en
- KDnuggets
- Ha kvar
- Snäll
- etikett
- Etiketter
- språk
- laptop
- Large
- större
- bibliotek
- Licens
- tycka om
- LINK
- Lista
- se
- du letar
- UTSEENDE
- älskar
- gjord
- Majoritet
- ledning
- många
- Marknadsföring
- Media
- Medlemmar
- Minne
- nämnts
- Sammanfoga
- meta
- Metrics
- kanske
- saknas
- blandad
- ML
- modell
- mer
- mest
- multipel
- namn
- Natural
- Naturligt språk
- Naturlig språkbehandling
- behövs
- Neutral
- Nya
- nlp
- anteckningsbok
- nu
- antal
- numpy
- objektet
- of
- Office
- Gamla
- on
- ONE
- Alternativet
- or
- beställa
- ursprungliga
- Övriga
- vår
- utsikterna
- produktion
- pandor
- Tidigare
- PC
- utföra
- rörledning
- plato
- Platon Data Intelligence
- PlatonData
- snälla du
- Punkt
- möjlig
- potentiell
- praktiken
- förutse
- förmodligen
- Problem
- problem
- förfaranden
- process
- bearbetning
- producera
- rätt
- Syftet
- kvalitet
- slumpmässig
- verkliga världen
- relaterad
- representerar
- kräver
- respons
- Resultat
- avkastning
- Befria
- stigande
- RAD
- försäljning
- Samma
- scenarier
- Vetenskap
- vetenskapsmän
- se
- frön
- verkar
- service
- in
- skall
- show
- signifikant
- liknande
- Enkelt
- eftersom
- Small
- So
- Social hållbarhet
- sociala medier
- Mjukvara
- lösning
- några
- ljud
- specialiserad
- specifik
- delas
- starta
- Starta
- bo
- Steg
- slutade
- rakt
- Sträng
- framgångsrik
- förment
- misstänksam
- Ta
- Diskussion
- tala
- grupp
- Gruppmedlemmar
- testa
- än
- den där
- Smakämnen
- den information
- deras
- Dem
- Där.
- Dessa
- de
- saker
- detta
- biljett
- biljetter
- tid
- till
- alltför
- ämne
- Totalt
- Tåg
- Utbildning
- Vrida
- handledning
- förstå
- Uppdatering
- uppdaterad
- us
- Användning
- användning
- Begagnade
- Användare
- med hjälp av
- vanligen
- Värden
- Omfattande
- mycket
- via
- Vägg
- var
- we
- Vad
- när
- som
- den som
- kommer
- fönster
- med
- utan
- ord
- ord
- Arbete
- arbetssätt
- skulle
- skrivning
- skriven
- X
- år
- dig
- själv
- zephyrnet