Kuvan toimittaja
Kun kiinnostus luonnollisen kielen käsittelyyn kasvaa, yhä useammat harjoittajat törmäävät seinään, ei siksi, että he eivät pystyisi rakentamaan tai hienosäätämään LLM:itä, vaan siksi, että heidän tietonsa ovat sotkuisia!
Näytämme yksinkertaisia, mutta erittäin tehokkaita koodausmenetelmiä meluisten tarrojen kiinnittämiseksi tekstidataan. Käsittelemme kahta yleistä skenaariota tosielämän tekstidatassa:
- Luokka, joka sisältää sekalaisia esimerkkejä muutamasta muusta luokasta. Rakastan kutsua tällaista luokkaa metakategoriaksi.
- 2 tai useampia kategorioita, jotka tulisi yhdistää yhdeksi kategoriaksi, koska niihin kuuluvat tekstit viittaavat samaan aiheeseen.
Käytämme tätä opetusohjelmaa varten luotua ITSM (IT Service Management) -tietojoukkoa (CCO-lisenssi). Se löytyy Kagglesta alla olevasta linkistä:
https://www.kaggle.com/datasets/nikolagreb/small-itsm-dataset
On aika aloittaa kaikkien tarvittavien kirjastojen maahantuonti ja perustietojen tutkiminen. Varaudu, koodi on tulossa!
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
Jokainen rivi edustaa yhtä merkintää ITSM-tietokannassa. Yritämme ennustaa lipun luokan käyttäjän kirjoittaman lipun tekstin perusteella. Tarkastellaan tarkemmin kuvattujen yrityskäyttötapausten tärkeimpiä kenttiä.
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
----------------------------------------------------------------------------------------------------
Jos tarkastelemme kahta ensimmäistä lippua, vaikka yksi lippu on saksaksi, voimme nähdä, että kuvatut ongelmat viittaavat samaan ohjelmistoon? - Asana, mutta niissä on eri etiketit. Tämä aloittaa luokkiemme jakelun:
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
Tarvittava apu näyttää epäilyttävältä, kuten luokka, joka voi sisältää lippuja useista muista luokista. Myös luokat Outlook ja Mail kuulostavat samanlaisilta, ehkä ne pitäisi yhdistää yhdeksi kategoriaksi. Ennen kuin sukeltaamme syvemmälle mainittuihin kategorioihin, pääsemme eroon kiinnostuksen kohteidemme sarakkeiden puuttuvista arvoista.
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)
Paljain silmin aineiston tutkimiseen ei ole pätevää korviketta. Fantastinen funktio sen tekemiseen pandoissa on .sample(), joten teemme sen vielä kerran, nyt epäilyttävälle kategorialle:
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.
---------------------------------------------------------------------------
Ilmeisesti meillä on lippuja, jotka puhuvat Discordista, Asanasta ja CRM:stä. Joten luokan nimi tulisi vaihtaa "Apua tarvitaan" olemassa oleviin, tarkempiin luokkiin. Uudelleenmääritysprosessin ensimmäisessä vaiheessa luomme uuden sarakkeen "Avainsanat", joka antaa tiedot, jos lipussa on sana "Teksti"-sarakkeen luokkaluettelosta.
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)
Huomaa myös, että "jos sanan str(sanat_luokat)" käyttäminen "jos sana sanoissa_luokat" nappaisi sanoja luokista, joissa on enemmän kuin yksi sana (tapauksessamme Internet-selain), mutta vaatisi myös enemmän tietojen esikäsittelyä. Jotta asiat olisivat yksinkertaisia ja suoraan asiaan, käytämme vain yhdestä sanasta koostuvien luokkien koodia. Tietojoukkomme näyttää nyt tältä:
df.head(2)
tulostus kuvana:
Avainsanasarakkeen purkamisen jälkeen oletamme lippujen laadun. Hypoteesimme:
- Lippu, jonka tekstikentässä on vain yksi avainsana, joka on sama kuin luokka, johon lippu kuuluu, olisi helppo luokitella.
- Lippu, jossa on useita avainsanoja Teksti-kentässä, jossa vähintään yksi avainsanoista on sama kuin luokka, johon lippu kuuluu, olisi useimmissa tapauksissa helppo luokitella.
- Lippu, jossa on avainsanoja, mutta mikään niistä ei vastaa sen luokan nimeä, johon lippu kuuluu, on luultavasti äänekäs etikettikotelo.
- Muut liput ovat neutraaleja avainsanojen perusteella.
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
Teimme uuden jakelumme ja nyt on aika tutkia mahdolliseksi ongelmaksi luokiteltuja lippuja. Käytännössä seuraava vaihe vaatisi paljon enemmän näytteenottoa ja isompien datapalojen katsomista paljain silmin, mutta perustelut olisivat samat. Sinun pitäisi löytää ongelmalliset liput ja päättää, voitko parantaa niiden laatua vai kannattaako ne jättää tietojoukosta pois. Kun kohtaat suuren tietojoukon, pysy rauhallisena, äläkä unohda, että tietojen tutkiminen ja tietojen valmistelu vie yleensä paljon enemmän aikaa kuin ML-algoritmien rakentaminen!
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
--------------------------------------------------------------------
Ymmärrämme, että Outlook- ja Mail-luokkien liput liittyvät samaan ongelmaan, joten yhdistämme nämä kaksi luokkaa ja parannamme tulevan ML-luokitusalgoritmimme tuloksia.
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
Viimeisenä, mutta ei vähäisimpänä, haluamme nimetä jotkin liput meta-kategoriasta "Apua tarvitaan" oikeaan kategoriaan.
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
Teimme datan uudelleenmerkinnät ja puhdistuksen, mutta meidän ei pitäisi kutsua itseämme datatieteilijöiksi, jos emme tee vähintään yhtä tieteellistä koetta ja testaa työmme vaikutusta lopulliseen luokitukseen. Teemme sen ottamalla käyttöön The Complement Naive Bayes -luokituksen sklearnissa. Voit vapaasti kokeilla muita, monimutkaisempia algoritmeja. Muista myös, että tietoja voidaan puhdistaa lisää - esimerkiksi voimme myös pudottaa kaikki "Apua tarvitaan" -kategoriaan jäljellä olevat liput.
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
Aika vaikuttavaa, eikö? Käyttämämme tietojoukko on pieni (tarkoitukseensa, jotta näet helposti, mitä kussakin vaiheessa tapahtuu), joten erilaiset satunnaiset siemenet voivat tuottaa erilaisia tuloksia, mutta useimmissa tapauksissa malli toimii huomattavasti paremmin tietojoukossa puhdistuksen jälkeen verrattuna alkuperäiseen tietojoukkoon. Teimme hyvää työtä!
Nikola Greb koodannut yli neljä vuotta, ja viimeiset kaksi vuotta hän erikoistui NLP:hen. Ennen kuin hän siirtyi datatieteeseen, hän menestyi myynnissä, HR:ssä, kirjoittamisessa ja shakissa.
- SEO-pohjainen sisällön ja PR-jakelu. Vahvista jo tänään.
- Platoblockchain. Web3 Metaverse Intelligence. Tietoa laajennettu. Pääsy tästä.
- Tulevaisuuden lyöminen Adryenn Ashley. Pääsy tästä.
- Lähde: 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
- :on
- :On
- :ei
- :missä
- 1
- 10
- 100
- 11
- 2%
- 7
- 8
- 9
- a
- Meistä
- Tili
- tarkkuus
- Jälkeen
- Agentti
- algoritmi
- algoritmit
- Kaikki
- Myös
- Vaikka
- an
- ja
- OVAT
- AS
- At
- saatavissa
- perustua
- perustiedot
- BE
- koska
- ollut
- ennen
- alle
- Paremmin
- tukossa
- selain
- rakentaa
- Rakentaminen
- liiketoiminta
- mutta
- by
- soittaa
- CAN
- kuljettaa
- tapaus
- tapauksissa
- KISSA
- paini
- luokat
- Kategoria
- muuttaa
- shakki
- luokittelu
- luokiteltu
- luokitella
- Siivous
- Cluster
- koodi
- Koodaus
- Sarake
- Pylväät
- KOM
- Yhteinen
- yritys
- verrattuna
- Täydentää
- monimutkainen
- kytkeä
- liitäntä
- sisältää
- voisi
- luoda
- luotu
- CRM
- tiedot
- Tietojen valmistelu
- tietojenkäsittely
- tietokanta
- sopimus
- tekemisissä
- päättää
- syvempää
- on kuvattu
- DID
- eri
- epäsopu
- jakelu
- do
- Don
- Pudota
- kukin
- helposti
- Tehokas
- käytössä
- merkintä
- Eetteri (ETH)
- täsmälleen
- esimerkki
- Esimerkit
- olemassa
- odotettu
- kokeilu
- selitti
- silmä
- päin
- harvat
- ala
- Fields
- lopullinen
- Löytää
- Etunimi
- jälkeen
- varten
- neljä
- Ilmainen
- alkaen
- toiminto
- edelleen
- tulevaisuutta
- Saksan
- saada
- Antaa
- antaa
- Go
- hyvä
- tapahtuu
- Olla
- he
- 헤드폰,en
- auttaa
- lyömällä
- Miten
- hr
- HTTPS
- HubSpot
- i
- kuva
- Vaikutus
- täytäntöönpanosta
- tuoda
- tärkeä
- vaikuttava
- parantaa
- in
- indeksi
- tiedot
- sen sijaan
- korko
- Internet
- tulee
- kysymys
- IT
- IT-palvelu
- vain
- vain yksi
- KDnuggets
- Pitää
- laji
- Merkki
- tarrat
- Kieli
- kannettava tietokone
- suuri
- suurempi
- kirjastot
- Lisenssi
- pitää
- LINK
- Lista
- katso
- näköinen
- ulkonäkö
- rakkaus
- tehty
- Enemmistö
- johto
- monet
- Marketing
- Media
- Jäsenet
- Muisti
- mainitsi
- mennä
- Meta
- Metrics
- ehkä
- puuttuva
- sekoitettu
- ML
- malli
- lisää
- eniten
- moninkertainen
- nimi
- Luonnollinen
- Luonnollinen kieli
- Luonnollinen kielen käsittely
- tarvitaan
- Neutraali
- Uusi
- NLP
- muistikirja
- nyt
- numero
- numpy
- objekti
- of
- Office
- Vanha
- on
- ONE
- Vaihtoehto
- or
- tilata
- alkuperäinen
- Muut
- meidän
- näkymät
- ulostulo
- pandas
- Ohi
- PC
- suorittaa
- putki
- Platon
- Platonin tietotieto
- PlatonData
- Ole hyvä
- Kohta
- mahdollinen
- mahdollinen
- harjoitusta.
- ennustaa
- todennäköisesti
- Ongelma
- ongelmia
- menettelyt
- prosessi
- käsittely
- tuottaa
- asianmukainen
- tarkoitus
- laatu
- satunnainen
- todellinen maailma
- liittyvä
- edustaa
- edellyttää
- vastaus
- tulokset
- palata
- Eroon
- nouseva
- RIVI
- myynti
- sama
- skenaariot
- tiede
- tutkijat
- nähdä
- siemenet
- näyttää
- palvelu
- setti
- shouldnt
- näyttää
- merkittävästi
- samankaltainen
- Yksinkertainen
- koska
- pieni
- So
- sosiaalinen
- sosiaalinen media
- Tuotteemme
- ratkaisu
- jonkin verran
- kuulostaa
- erikoistunut
- erityinen
- jakaa
- Alkaa
- Aloita
- pysyä
- Vaihe
- pysähtynyt
- suoraan
- jono
- onnistunut
- tarkoitus
- epäilyttävä
- ottaa
- Puhua
- puhuminen
- joukkue-
- Ryhmän jäsenet
- testi
- kuin
- että
- -
- tiedot
- heidän
- Niitä
- Siellä.
- Nämä
- ne
- asiat
- tätä
- lippu
- liput
- aika
- että
- liian
- aihe
- Yhteensä
- Juna
- koulutus
- Kääntyminen
- oppitunti
- ymmärtää
- Päivitykset
- päivitetty
- us
- Käyttö
- käyttää
- käytetty
- käyttäjä
- käyttämällä
- yleensä
- arvot
- valtava
- hyvin
- kautta
- Seinä
- oli
- we
- Mitä
- kun
- joka
- kuka tahansa
- tulee
- ikkunat
- with
- ilman
- sana
- sanoja
- Referenssit
- työskentely
- olisi
- kirjoittaminen
- kirjallinen
- X
- vuotta
- te
- itse
- zephyrnet