Kép a szerkesztőtől
A természetes nyelvi feldolgozás iránti növekvő érdeklődés miatt egyre több szakember üti a falat, nem azért, mert nem tud LLM-eket építeni vagy finomhangolni, hanem azért, mert az adataik rendetlenek!
Egyszerű, de nagyon hatékony kódolási eljárásokat mutatunk be a szöveges adatokban lévő zajos címkék rögzítésére. Két gyakori forgatókönyvvel fogunk foglalkozni a valós szöveges adatokban:
- Olyan kategóriával, amely vegyes példákat tartalmaz néhány másik kategóriából. Szeretem ezt a fajta kategóriát meta kategóriának nevezni.
- 2 vagy több kategória, amelyet össze kell vonni 1 kategóriába, mert a hozzájuk tartozó szövegek ugyanarra a témára vonatkoznak.
Az ehhez az oktatóanyaghoz (CCO licenc) létrehozott ITSM (IT Service Management) adatkészletet fogjuk használni. Elérhető a Kaggle-n az alábbi linkről:
https://www.kaggle.com/datasets/nikolagreb/small-itsm-dataset
Ideje elkezdeni az összes szükséges könyvtár importálását és az alapvető adatok vizsgálatát. Készülj fel, jön a kód!
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
Minden sor egy bejegyzést jelent az ITSM adatbázisban. Megpróbáljuk megjósolni a jegy kategóriáját a felhasználó által írt jegy szövege alapján. Vizsgáljuk meg mélyebben a leírt üzleti felhasználási esetek legfontosabb területeit.
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
----------------------------------------------------------------------------------------------------
Ha megnézzük az első két jegyet, bár az egyik jegy német nyelvű, akkor azt láthatjuk, hogy a leírt problémák ugyanarra a szoftverre vonatkoznak?—?Asana, de más címkéket viselnek. Ezzel megkezdődik kategóriáink terjesztése:
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
A szükséges segítség gyanúsnak tűnik, mint az a kategória, amely több más kategória jegyeit is tartalmazhatja. Az Outlook és a Mail kategóriák is hasonlóan hangzanak, talán össze kellene vonni őket egy kategóriába. Mielőtt mélyebben belemerülnénk az említett kategóriákba, megszabadulunk a számunkra érdekes rovatokban hiányzó értékektől.
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)
Az adatok puszta szemmel történő vizsgálatát nem helyettesítheti érvényesen. A pandákban erre a kitalált függvény a .sample(), tehát még egyszer pontosan ezt tesszük, most a gyanús kategóriánál:
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.
---------------------------------------------------------------------------
Nyilvánvalóan vannak jegyeink a Discordról, az Asana-ról és a CRM-ről. Tehát a kategória nevét „Segítségre van szükség”-ről meg kell változtatni a meglévő, konkrétabb kategóriákra. Az átsorolási folyamat első lépésében létrehozzuk az új „Kulcsszavak” oszlopot, amely azt az információt adja meg, hogy a jegyen szerepel-e a „Szöveg” oszlopban található kategórialistából a szó.
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)
Azt is vegye figyelembe, hogy az „if word in str(words_categories)” használata az „if word in words_categories” helyett az 1 szónál több kategóriából származó szavakat fog ki (esetünkben az internetböngésző), de több adat-előfeldolgozást is igényelne. Annak érdekében, hogy a dolgok egyszerűek és egyenesek legyenek, az egyetlen szóból álló kategóriák kódját fogjuk használni. Adatkészletünk most így néz ki:
df.head(2)
kimenet képként:
A kulcsszavak oszlop kibontása után feltételezzük a jegyek minőségét. Hipotézisünk:
- A Szöveg mezőben csak 1 kulcsszóval rendelkező jegyet, amely megegyezik azzal a kategóriával, amelyhez a jegy tartozik, könnyen besorolható lenne.
- A Szöveg mezőben több kulcsszót tartalmazó jegy, ahol legalább az egyik kulcsszó megegyezik azzal a kategóriával, amelybe a jegy tartozik, az esetek többségében könnyen besorolható.
- Az a jegy, amelynek kulcsszavai vannak, de egyik sem egyenlő annak a kategóriának a nevével, amelyhez a jegy tartozik, valószínűleg egy zajos címkeeset.
- A többi jegy semleges a kulcsszavak alapján.
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
Elkészítettük új disztribúciónkat, és itt az ideje megvizsgálni a potenciális problémaként besorolt jegyeket. A gyakorlatban a következő lépés sokkal több mintavételt igényelne, és szabad szemmel kellene megnézni a nagyobb adattömböket, de az indoklás ugyanaz lenne. Meg kell találnia a problémás jegyeket, és el kell döntenie, hogy javíthatja-e a minőségüket, vagy ki kell venni őket az adatkészletből. Ha nagy adatkészlettel áll szemben, maradjon nyugodt, és ne felejtse el, hogy az adatok vizsgálata és előkészítése általában sokkal több időt vesz igénybe, mint az ML algoritmusok felépítése!
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
--------------------------------------------------------------------
Tisztában vagyunk vele, hogy az Outlook és a Mail kategóriákból származó jegyek ugyanahhoz a problémához kapcsolódnak, ezért összevonjuk ezt a két kategóriát, és javítjuk jövőbeli ML osztályozási algoritmusunk eredményeit.
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
Végül, de nem utolsósorban szeretnénk néhány jegyet átcímkézni a „Segítség szükséges” metakategóriából a megfelelő kategóriába.
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
Elvégeztük az adatok átcímkézését és tisztítását, de nem nevezhetjük magunkat adattudósnak, ha nem végzünk el legalább egy tudományos kísérletet, és nem teszteljük munkánk hatását a végső osztályozásra. Ezt úgy fogjuk megtenni, hogy megvalósítjuk a The Complement Naive Bayes osztályozót a sklearnben. Nyugodtan próbálkozzon más, összetettebb algoritmusokkal. Ne feledje, hogy további adattisztításra is sor kerülhet – például a „Segítségre van szükség” kategóriában eldobhatjuk az összes megmaradt jegyet.
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
Elég lenyűgöző, igaz? Az általunk használt adatkészlet kicsi (szándékosan, így könnyen láthatja, mi történik az egyes lépésekben), így a különböző véletlenszerű magok eltérő eredményeket hozhatnak, de az esetek túlnyomó többségében a modell jelentősen jobban teljesít az adatkészleten tisztítás után az eredeti adatkészlethez. Jó munkát végeztünk!
Nikola Greb több mint négy éve kódol, az elmúlt két évben pedig az NLP-re szakosodott. Mielőtt az adattudomány felé fordult, sikeres volt az értékesítés, a HR, az írás és a sakk területén.
- SEO által támogatott tartalom és PR terjesztés. Erősödjön még ma.
- Platoblockchain. Web3 metaverzum intelligencia. Felerősített tudás. Hozzáférés itt.
- A jövő pénzverése – Adryenn Ashley. Hozzáférés itt.
- Forrás: 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
- :van
- :is
- :nem
- :ahol
- 1
- 10
- 100
- 11
- 2%
- 7
- 8
- 9
- a
- Rólunk
- Fiók
- pontosság
- Után
- Ügynök
- algoritmus
- algoritmusok
- Minden termék
- Is
- Bár
- an
- és a
- VANNAK
- AS
- At
- elérhető
- alapján
- alapvető
- BE
- mert
- óta
- előtt
- lent
- Jobb
- zárolt
- böngésző
- épít
- Épület
- üzleti
- de
- by
- hívás
- TUD
- visz
- eset
- esetek
- CAT
- Fogás
- kategóriák
- Kategória
- változik
- sakk
- besorolás
- osztályozott
- osztályoz
- Takarításra
- Fürt
- kód
- Kódolás
- Oszlop
- Oszlopok
- COM
- Közös
- vállalat
- képest
- Kiegészítés
- bonyolult
- Csatlakozás
- kapcsolat
- tartalmaz
- tudott
- teremt
- készítette
- CRM
- dátum
- Adatok előkészítése
- adat-tudomány
- adatbázis
- üzlet
- foglalkozó
- dönt
- mélyebb
- leírt
- DID
- különböző
- viszály
- terjesztés
- do
- Don
- Csepp
- minden
- könnyen
- Hatékony
- engedélyezve
- belépés
- Eter (ETH)
- pontosan
- példa
- példák
- létező
- várható
- kísérlet
- magyarázható
- szem
- néző
- kevés
- mező
- Fields
- utolsó
- Találjon
- vezetéknév
- következő
- A
- négy
- Ingyenes
- ból ből
- funkció
- további
- jövő
- Német
- kap
- Ad
- ad
- Go
- jó
- megtörténik
- Legyen
- he
- fejhallgató
- segít
- ütő
- Hogyan
- hr
- HTTPS
- HubSpot
- i
- kép
- Hatás
- végrehajtási
- importál
- fontos
- hatásos
- javul
- in
- index
- információ
- helyette
- kamat
- Internet
- bele
- kérdés
- IT
- IT szolgáltatás
- éppen
- csak egy
- KDnuggets
- Tart
- Kedves
- Címke
- Címkék
- nyelv
- hordozható számítógép
- nagy
- nagyobb
- könyvtárak
- Engedély
- mint
- LINK
- Lista
- néz
- keres
- MEGJELENÉS
- szerelem
- készült
- Többség
- vezetés
- sok
- Marketing
- Média
- Partnerek
- Memory design
- említett
- megy
- meta
- Metrics
- esetleg
- hiányzó
- vegyes
- ML
- modell
- több
- a legtöbb
- többszörös
- név
- Természetes
- Természetes nyelv
- Természetes nyelvi feldolgozás
- szükséges
- Semleges
- Új
- NLP
- jegyzetfüzet
- Most
- szám
- számtalan
- tárgy
- of
- Office
- Régi
- on
- ONE
- opció
- or
- érdekében
- eredeti
- Más
- mi
- Outlook
- teljesítmény
- pandák
- múlt
- PC
- teljesít
- csővezeték
- Plató
- Platón adatintelligencia
- PlatoData
- kérem
- pont
- lehetséges
- potenciális
- gyakorlat
- előre
- valószínűleg
- Probléma
- problémák
- eljárások
- folyamat
- feldolgozás
- gyárt
- megfelelő
- cél
- világítás
- véletlen
- való Világ
- összefüggő
- jelentése
- szükség
- válasz
- Eredmények
- visszatérés
- megszabadít
- felkelő
- SOR
- értékesítés
- azonos
- forgatókönyvek
- Tudomány
- tudósok
- lát
- magok
- Úgy tűnik,
- szolgáltatás
- készlet
- kellene
- előadás
- jelentősen
- hasonló
- Egyszerű
- óta
- kicsi
- So
- Közösség
- Közösségi média
- szoftver
- megoldások
- néhány
- hang
- specializált
- különleges
- osztott
- kezdet
- Kezdve
- tartózkodás
- Lépés
- megállt
- egyenes
- Húr
- sikeres
- feltételezett
- gyanús
- Vesz
- Beszél
- beszéd
- csapat
- Csapattagok
- teszt
- mint
- hogy
- A
- az információ
- azok
- Őket
- Ott.
- Ezek
- ők
- dolgok
- ezt
- jegy
- jegyek
- idő
- nak nek
- is
- téma
- Végösszeg
- Vonat
- Képzések
- Turning
- oktatói
- megért
- Frissítések
- frissítve
- us
- Használat
- használ
- használt
- használó
- segítségével
- rendszerint
- Értékek
- Hatalmas
- nagyon
- keresztül
- Fal
- volt
- we
- Mit
- amikor
- ami
- bárki
- lesz
- ablakok
- val vel
- nélkül
- szó
- szavak
- Munka
- dolgozó
- lenne
- írás
- írott
- X
- év
- te
- magad
- zephyrnet