Εικόνα από Editor
Με το αυξανόμενο ενδιαφέρον για την επεξεργασία φυσικής γλώσσας, όλο και περισσότεροι ασκούμενοι χτυπούν τον τοίχο όχι επειδή δεν μπορούν να δημιουργήσουν ή να βελτιώσουν τα LLMs, αλλά επειδή τα δεδομένα τους είναι ακατάστατα!
Θα δείξουμε απλές, αλλά πολύ αποτελεσματικές διαδικασίες κωδικοποίησης για τον καθορισμό θορυβωδών ετικετών σε δεδομένα κειμένου. Θα ασχοληθούμε με 2 κοινά σενάρια σε δεδομένα κειμένου πραγματικού κόσμου:
- Έχοντας μια κατηγορία που περιέχει μικτά παραδείγματα από μερικές άλλες κατηγορίες. Μου αρέσει να αποκαλώ αυτού του είδους την κατηγορία μετακατηγορία.
- Έχουν 2 ή περισσότερες κατηγορίες που πρέπει να συγχωνευθούν σε 1 κατηγορία επειδή τα κείμενα που ανήκουν σε αυτές αναφέρονται στο ίδιο θέμα.
Θα χρησιμοποιήσουμε το σύνολο δεδομένων ITSM (IT Service Management) που δημιουργήθηκε για αυτό το σεμινάριο (άδεια CCO). Είναι διαθέσιμο στο Kaggle από τον παρακάτω σύνδεσμο:
https://www.kaggle.com/datasets/nikolagreb/small-itsm-dataset
Ήρθε η ώρα να ξεκινήσετε με την εισαγωγή όλων των απαραίτητων βιβλιοθηκών και την εξέταση βασικών δεδομένων. Φροντίστε, ο κωδικός έρχεται!
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
Κάθε σειρά αντιπροσωπεύει μία καταχώρηση στη βάση δεδομένων ITSM. Θα προσπαθήσουμε να προβλέψουμε την κατηγορία του εισιτηρίου με βάση το κείμενο του εισιτηρίου που έχει γράψει ένας χρήστης. Ας εξετάσουμε βαθύτερα τα πιο σημαντικά πεδία για περιγραφόμενες περιπτώσεις επιχειρηματικής χρήσης.
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
----------------------------------------------------------------------------------------------------
Αν ρίξουμε μια ματιά στα δύο πρώτα εισιτήρια, αν και ένα εισιτήριο είναι στα γερμανικά, μπορούμε να δούμε ότι τα προβλήματα που περιγράφονται αναφέρονται στο ίδιο λογισμικό;—?Asana, αλλά φέρουν διαφορετικές ετικέτες. Αυτή είναι η έναρξη της διανομής των κατηγοριών μας:
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
Η βοήθεια που απαιτείται φαίνεται ύποπτη, όπως η κατηγορία που μπορεί να περιέχει εισιτήρια από πολλές άλλες κατηγορίες. Επίσης, οι κατηγορίες Outlook και Mail ακούγονται παρόμοιες, ίσως θα έπρεπε να συγχωνευθούν σε μία κατηγορία. Πριν βουτήξουμε βαθύτερα στις αναφερόμενες κατηγορίες, θα απαλλαγούμε από τις τιμές που λείπουν στις στήλες του ενδιαφέροντός μας.
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)
Δεν υπάρχει έγκυρο υποκατάστατο για την εξέταση των δεδομένων με γυμνό μάτι. Η φανταχτερή συνάρτηση για να το κάνουμε αυτό στα panda είναι .sample(), οπότε θα κάνουμε ακριβώς αυτό για άλλη μια φορά, τώρα για την ύποπτη κατηγορία:
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.
---------------------------------------------------------------------------
Προφανώς, έχουμε εισιτήρια που μιλούν για Discord, Asana και CRM. Επομένως, το όνομα της κατηγορίας θα πρέπει να αλλάξει από "Χρειάζεται βοήθεια" σε υπάρχουσες, πιο συγκεκριμένες κατηγορίες. Για το πρώτο βήμα της διαδικασίας εκ νέου ανάθεσης, θα δημιουργήσουμε τη νέα στήλη «Λέξεις-κλειδιά» που δίνει τις πληροφορίες εάν το εισιτήριο έχει τη λέξη από τη λίστα κατηγοριών στη στήλη «Κείμενο».
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)
Επίσης, σημειώστε ότι η χρήση του "if word in str(words_categories)" αντί του "if word in words_categories" θα έπιανε λέξεις από κατηγορίες με περισσότερες από 1 λέξεις (το πρόγραμμα περιήγησης Διαδικτύου στην περίπτωσή μας), αλλά θα απαιτούσε επίσης περισσότερη προεπεξεργασία δεδομένων. Για να παραμείνουμε απλά και κατευθείαν στην ουσία, θα πάμε με τον κώδικα για κατηγορίες που αποτελούνται από μία μόνο λέξη. Έτσι φαίνεται τώρα το σύνολο δεδομένων μας:
df.head(2)
έξοδος ως εικόνα:
Μετά την εξαγωγή της στήλης λέξεων-κλειδιών, θα υποθέσουμε την ποιότητα των εισιτηρίων. Η υπόθεσή μας:
- Εισιτήριο με μόνο 1 λέξη-κλειδί στο πεδίο Κείμενο που είναι το ίδιο με την κατηγορία στην οποία ανήκει το εισιτήριο θα ήταν εύκολο να ταξινομηθεί.
- Εισιτήριο με πολλές λέξεις-κλειδιά στο πεδίο Κείμενο, όπου τουλάχιστον μία από τις λέξεις-κλειδιά είναι ίδια με την κατηγορία στην οποία ανήκει το εισιτήριο, θα ήταν εύκολο να ταξινομηθεί στις περισσότερες περιπτώσεις.
- Το εισιτήριο που έχει λέξεις-κλειδιά, αλλά καμία από αυτές δεν είναι ίση με το όνομα της κατηγορίας στην οποία ανήκει το εισιτήριο είναι πιθανώς μια θορυβώδης θήκη ετικέτας.
- Τα άλλα εισιτήρια είναι ουδέτερα με βάση τις λέξεις-κλειδιά.
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
Κάναμε τη νέα μας διανομή και τώρα είναι η ώρα να εξετάσουμε τα εισιτήρια που ταξινομούνται ως πιθανό πρόβλημα. Στην πράξη, το επόμενο βήμα θα απαιτούσε πολύ περισσότερη δειγματοληψία και την εξέταση των μεγαλύτερων τμημάτων δεδομένων με γυμνό μάτι, αλλά η λογική θα ήταν η ίδια. Υποτίθεται ότι θα βρείτε προβληματικά εισιτήρια και θα αποφασίσετε εάν μπορείτε να βελτιώσετε την ποιότητά τους ή εάν πρέπει να τα αφαιρέσετε από το σύνολο δεδομένων. Όταν αντιμετωπίζετε ένα μεγάλο σύνολο δεδομένων, παραμείνετε ήρεμοι και μην ξεχνάτε ότι η εξέταση δεδομένων και η προετοιμασία δεδομένων συνήθως χρειάζονται πολύ περισσότερο χρόνο από τη δημιουργία αλγορίθμων ML!
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
--------------------------------------------------------------------
Κατανοούμε ότι τα εισιτήρια από τις κατηγορίες Outlook και Mail σχετίζονται με το ίδιο πρόβλημα, επομένως θα συγχωνεύσουμε αυτές τις 2 κατηγορίες και θα βελτιώσουμε τα αποτελέσματα του μελλοντικού μας αλγόριθμου ταξινόμησης ML.
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
Τελευταίο, αλλά όχι ασήμαντο, θέλουμε να επαναπροσδιορίσουμε ορισμένα εισιτήρια από τη μετα-κατηγορία «Χρειάζεται βοήθεια» στην κατάλληλη κατηγορία.
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
Κάναμε την επανασήμανση και τον καθαρισμό των δεδομένων μας, αλλά δεν θα έπρεπε να αποκαλούμε τους εαυτούς μας επιστήμονες δεδομένων εάν δεν κάνουμε τουλάχιστον ένα επιστημονικό πείραμα και δεν δοκιμάσουμε τον αντίκτυπο της εργασίας μας στην τελική ταξινόμηση. Θα το κάνουμε εφαρμόζοντας τον ταξινομητή The Complement Naive Bayes στο sklearn. Μη διστάσετε να δοκιμάσετε άλλους, πιο σύνθετους αλγόριθμους. Επίσης, έχετε υπόψη σας ότι θα μπορούσε να γίνει περαιτέρω καθαρισμός δεδομένων – για παράδειγμα, θα μπορούσαμε επίσης να απορρίψουμε όλα τα εισιτήρια που έχουν απομείνει στην κατηγορία «Χρειάζεται βοήθεια».
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
Αρκετά εντυπωσιακό, σωστά; Το σύνολο δεδομένων που χρησιμοποιήσαμε είναι μικρό (σκόπιμα, ώστε να μπορείτε εύκολα να δείτε τι συμβαίνει σε κάθε βήμα), επομένως διαφορετικοί τυχαίοι σπόροι μπορεί να παράγουν διαφορετικά αποτελέσματα, αλλά στη συντριπτική πλειονότητα των περιπτώσεων, το μοντέλο θα έχει πολύ καλύτερη απόδοση στο σύνολο δεδομένων μετά τον καθαρισμό σε σύγκριση στο αρχικό σύνολο δεδομένων. Κάναμε καλή δουλειά!
Νίκολα Γκρεμπ ασχολείται με την κωδικοποίηση για περισσότερα από τέσσερα χρόνια και τα τελευταία δύο χρόνια ειδικεύεται στο NLP. Πριν στραφεί στην επιστήμη των δεδομένων, ήταν επιτυχημένος στις πωλήσεις, το ανθρώπινο δυναμικό, τη συγγραφή και το σκάκι.
- SEO Powered Content & PR Distribution. Ενισχύστε σήμερα.
- Platoblockchain. Web3 Metaverse Intelligence. Ενισχύθηκε η γνώση. Πρόσβαση εδώ.
- Minting the Future με την Adryenn Ashley. Πρόσβαση εδώ.
- πηγή: 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
- :έχει
- :είναι
- :δεν
- :που
- 1
- 10
- 100
- 11
- 2%
- 7
- 8
- 9
- a
- Σχετικά
- Λογαριασμός
- ακρίβεια
- Μετά το
- Πράκτορας
- αλγόριθμος
- αλγόριθμοι
- Όλα
- Επίσης
- Αν και
- an
- και
- ΕΙΝΑΙ
- AS
- At
- διαθέσιμος
- βασίζονται
- βασικός
- BE
- επειδή
- ήταν
- πριν
- παρακάτω
- Καλύτερα
- μπλοκαριστεί
- πρόγραμμα περιήγησης
- χτίζω
- Κτίριο
- επιχείρηση
- αλλά
- by
- κλήση
- CAN
- κουβαλάω
- περίπτωση
- περιπτώσεις
- CAT
- πάλη
- κατηγορίες
- κατηγορία
- αλλαγή
- Σκάκι
- ταξινόμηση
- ταξινομούνται
- Ταξινόμηση
- Καθάρισμα
- συστάδα
- κωδικός
- Κωδικοποίηση
- Στήλη
- Στήλες
- COM
- Κοινός
- εταίρα
- σύγκριση
- Συμπλήρωμα
- συγκρότημα
- Connect
- σύνδεση
- Περιέχει
- θα μπορούσε να
- δημιουργία
- δημιουργήθηκε
- CRM
- ημερομηνία
- Προετοιμασία δεδομένων
- επιστημονικά δεδομένα
- βάση δεδομένων
- συμφωνία
- μοιρασιά
- αποφασίζει
- βαθύτερη
- περιγράφεται
- DID
- διαφορετικές
- διχόνοια
- διανομή
- do
- Don
- Πτώση
- κάθε
- εύκολα
- Αποτελεσματικός
- ενεργοποιημένη
- καταχώριση
- Αιθέρας (ΕΤΗ)
- ακριβώς
- παράδειγμα
- παραδείγματα
- υφιστάμενα
- αναμένεται
- πείραμα
- εξήγησε
- μάτι
- αντιμέτωπος
- λίγοι
- πεδίο
- Πεδία
- τελικός
- Εύρεση
- Όνομα
- Εξής
- Για
- τέσσερα
- Δωρεάν
- από
- λειτουργία
- περαιτέρω
- μελλοντικός
- Γερμανικά
- παίρνω
- Δώστε
- δίνει
- Go
- καλός
- συμβαίνει
- Έχω
- he
- ακουστικά
- βοήθεια
- να χτυπήσει
- Πως
- hr
- HTTPS
- HubSpot
- i
- εικόνα
- Επίπτωση
- εκτελεστικών
- εισαγωγή
- σημαντικό
- εντυπωσιακός
- βελτίωση
- in
- ευρετήριο
- πληροφορίες
- αντί
- τόκος
- Internet
- σε
- ζήτημα
- IT
- υπηρεσία πληροφορικής
- μόλις
- μόνο ένα
- KDnuggets
- Διατήρηση
- Είδος
- επιγραφή
- Ετικέτες
- Γλώσσα
- laptop
- large
- μεγαλύτερος
- βιβλιοθήκες
- Άδεια
- Μου αρέσει
- LINK
- Λίστα
- ματιά
- κοιτάζοντας
- ΦΑΊΝΕΤΑΙ
- αγάπη
- που
- Η πλειοψηφία
- διαχείριση
- πολοί
- Μάρκετινγκ
- Εικόνες / Βίντεο
- Μέλη
- Μνήμη
- που αναφέρθηκαν
- πηγαίνω
- Meta
- Metrics
- ενδέχεται να
- Λείπει
- μικτός
- ML
- μοντέλο
- περισσότερο
- πλέον
- πολλαπλούς
- όνομα
- Φυσικό
- Φυσική γλώσσα
- Επεξεργασία φυσικής γλώσσας
- που απαιτούνται
- Ουδέτερος
- Νέα
- nlp
- σημειωματάριο
- τώρα
- αριθμός
- πολλοί
- αντικείμενο
- of
- Office
- Παλιά
- on
- ONE
- Επιλογή
- or
- τάξη
- πρωτότυπο
- ΑΛΛΑ
- δικός μας
- θέα
- παραγωγή
- Πάντα
- Το παρελθόν
- PC
- εκτελέσει
- αγωγού
- Πλάτων
- Πληροφορία δεδομένων Plato
- Πλάτωνα δεδομένα
- σας παρακαλούμε
- Σημείο
- δυνατός
- δυναμικού
- πρακτική
- προβλέψει
- πιθανώς
- Πρόβλημα
- προβλήματα
- διαδικασίες
- διαδικασια μας
- μεταποίηση
- παράγει
- κατάλληλος
- σκοπός
- ποιότητα
- τυχαίος
- πραγματικό κόσμο
- σχετίζεται με
- αντιπροσωπεύει
- απαιτούν
- απάντησης
- Αποτελέσματα
- απόδοση
- Απαλλάσσω
- αύξηση
- ΣΕΙΡΑ
- εμπορικός
- ίδιο
- σενάρια
- Επιστήμη
- επιστήμονες
- δείτε
- σπόροι
- φαίνεται
- υπηρεσία
- σειρά
- θα πρέπει να
- δείχνουν
- σημαντικά
- παρόμοιες
- Απλούς
- αφού
- small
- So
- Μ.Κ.Δ
- social media
- λογισμικό
- λύση
- μερικοί
- Ήχος
- ειδικευμένος
- συγκεκριμένες
- διαίρεση
- Εκκίνηση
- Ξεκινήστε
- παραμονή
- Βήμα
- σταμάτησε
- ευθεία
- Σπάγγος
- επιτυχής
- υποτιθεμένος
- ύποπτος
- Πάρτε
- Συζήτηση
- ομιλία
- Μέλη ομάδας
- δοκιμή
- από
- ότι
- Η
- οι πληροφορίες
- τους
- Τους
- Εκεί.
- Αυτοί
- αυτοί
- πράγματα
- αυτό
- εισιτήριο
- εισιτήρια
- ώρα
- προς την
- πολύ
- τοπικός
- Σύνολο
- Τρένο
- Εκπαίδευση
- Στροφή
- φροντιστήριο
- καταλαβαίνω
- Ενημέρωση
- ενημερώθηκε
- us
- Χρήση
- χρήση
- μεταχειρισμένος
- Χρήστες
- χρησιμοποιώντας
- συνήθως
- Αξίες
- Σταθερή
- πολύ
- μέσω
- Τοίχος
- ήταν
- we
- Τι
- πότε
- Ποιό
- Οποιοσδήποτε
- θα
- παράθυρα
- με
- χωρίς
- λέξη
- λόγια
- Εργασία
- εργαζόμενος
- θα
- γραφή
- γραπτή
- X
- χρόνια
- εσείς
- τον εαυτό σας
- zephyrnet