Semplice classificazione del testo utilizzando Fasttext

Una guida semplice alla classificazione del testo con Fasttext

Crea un modello di classificazione del testo con solo un dataset etichettato, la libreria Fasttext e 10 minuti

Introduzione

La elaborazione del linguaggio naturale viene applicata a casi d’uso aziendali a un tasso esponenzialmente più elevato. Una delle automazioni AI più semplici che può trasformare un’azienda è la classificazione del testo, dal momento che in molti casi, la classificazione dei dati testuali viene svolta manualmente in un processo che richiede molto tempo.

La classificazione del testo consiste nello sviluppare un’AI in grado di assegnare etichette a un testo in input. Questi modelli di IA possono essere addestrati come un problema di apprendimento supervisionato, adattando i loro pesi in base ad esempi precedentemente visti con etichette corrispondenti.

Per effettuare la classificazione del testo in Python, possiamo utilizzare fasttext. Fasttext è una libreria di Python open-source e leggera in grado di creare facilmente modelli di classificazione del testo velocemente.

Il dataset che userò per questa demo è disponibile qui. Questo dataset consiste di tweet correlati al coronavirus e sentimenti associati. Ci sono cinque classi possibili: estremamente negativo, negativo, neutro, positivo ed estremamente positivo. Utilizzeremo fasttext per creare un modello di IA per classificare i tweet utilizzando questo dataset.

Da notare che c’è una zona grigia tra ciascuna di queste etichette: ossia, dove si trova la “linea” che separa positivo da estremamente positivo? O “negativo” da “estremamente negativo”? Ci sono sicuramente alcuni tweet che ricadono nella parte centrale di queste due classi, e l’etichetta di verità fondamentale potrebbe essere soggettiva riguardo a quale parte della linea l’etichetta finisce. Di conseguenza, è improbabile che si raggiunga mai una precisione di validazione del 100%.

Se vuoi provare il codice tu stesso, il notebook di Kaggle è disponibile qui.

Elaborazione

Ecco alcune delle principali funzioni di preprocessing utilizzate per preparare i dati per l’ingresso nel modello fasttext. Notare che questi passaggi non puliscono o modificano in alcun modo il testo originale – mi concentrerò esclusivamente sulla preparazione dei dati nel formato corretto per l’ingresso al modello di apprendimento automatico.

  1. process_data seleziona le colonne di interesse (testo e etichetta associata sono tutto ciò di cui abbiamo bisogno). Per l’etichetta, aggiungiamo la stringa “__label__” poiché fasttext si aspetta che le etichette abbiano questo prefisso.
  2. split_data divide i dati in un set di addestramento, un set di validazione e un set di test.
  3. save_data_as_txt crea i file txt necessari per fasttext. Fasttext si aspetta un file txt contenente testo e etichette associate, ed è ciò che questa funzione crea.
def process_data(df_train: pd.DataFrame, df_test: pd.DataFrame) -> Tuple[pd.DataFrame, pd.DataFrame]:    df_train = df_train[["Sentiment", "OriginalTweet"]]    df_test = df_test[["Sentiment", "OriginalTweet"]]    df_train["Sentiment"] = df_train["Sentiment"].apply(lambda x: "__label__" + "_".join(a for a in x.split()))    df_test["Sentiment"] = df_test["Sentiment"].apply(lambda x: "__label__" + "_".join(a for a in x.split()))    return df_train, df_testdef split_data(df_train: pd.DataFrame, df_test: pd.DataFrame, train_fraction: float) -> Tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame]:    split_point = round(df_train.shape[0] * train_fraction)    df_train, df_val = df_train.iloc[:split_point], df_train.iloc[split_point:]    return df_train, df_val, df_testdef save_data_as_txt(df_train: pd.DataFrame, df_validation: pd.DataFrame, df_test: pd.DataFrame) -> None:    df_train.to_csv(train_filepath,index=False,sep=" ",header=None,quoting=csv.QUOTE_NONE,quotechar="",escapechar=" ",)    df_validation.to_csv(validation_filepath,index=False,sep=" ",header=None,quoting=csv.QUOTE_NONE,quotechar="",escapechar=" ",)    df_test.to_csv(test_filepath,index=False,sep=" ",header=None,quoting=csv.QUOTE_NONE,quotechar="",escapechar=" ",)

Ora, basta impostare alcuni percorsi e chiamare le funzioni precedenti, e abbiamo tutti i dati pronti per creare un modello con fasttext!

df_train = pd.read_csv("/kaggle/input/covid-19-nlp-text-classification/Corona_NLP_train.csv", encoding="latin1")df_test = pd.read_csv("/kaggle/input/covid-19-nlp-text-classification/Corona_NLP_test.csv", encoding="latin1")train_filepath = "df_train.txt"validation_filepath = "df_val.txt"test_filepath = "df_test.txt"df_train, df_test = process_data(df_train=df_train, df_test=df_test)df_train, df_validation, df_test = split_data(df_train=df_train, df_test=df_test, train_fraction=0.9)save_data_as_txt(df_train=df_train, df_validation=df_validation, df_test=df_test)

Modello di adattamento

In realtà, tutto il lavoro difficile è già stato fatto. Per adattare il modello, basta chiamare il metodo

model = fasttext.train_supervised(input=str(train_filepath))

, e voilà! Abbiamo un modello addestrato.

Anche se il nostro modello è addestrato, non sappiamo quanto bene si comporta il nostro modello addestrato. Scriviamo una funzione per restituire la precisione media su tutte le classi di etichette:

def ottieni_pozioni(modello):    risultati_addestramento = modello.test(path=train_filepath)    risultati_validazione = modello.test(path=validation_filepath)    risultati_test = modello.test(path=test_filepath)    return risultati_addestramento, risultati_validazione, risultati_test

Chiamando questa funzione con

risultati_addestramento, risultati_validazione, risultati_test = ottieni_pozioni(modello=modello)print(risultati_addestramento, risultati_validazione, risultati_test)

Svela una precisione di addestramento di base del 71,0%, una precisione di validazione del 54,1% e una precisione di test del 48,4%. Non male per un modello di base!

Inoltre, come accennato nell’introduzione, se l’AI classifica un testo “estremamente negativo” come “negativo”, questo conta come un errore nel calcolo della precisione. Molti degli errori commessi dal modello sono “fuori per uno”, il che significa che la verità di riferimento era una delle etichette adiacenti.

Tuning degli iperparametri

Fino ad ora, abbiamo un modello di base che ha mostrato risultati decenti. Come possiamo fare di meglio? Fortunatamente, ci sono diversi iperparametri che possono essere passati al metodo fasttext.train_supervised che potremmo voler provare a regolare e vedere se il modello migliora le sue prestazioni.

Ecco dove entra in gioco il nostro set di validazione: proveremo diversi set di iperparametri e poi valuteremo i modelli risultanti sul set di validazione. Il set di parametri che porta alla maggiore precisione sul set di validazione sarà quello che useremo per il nostro modello finale.

Quali set di iperparametri dovremmo provare? Sebbene si potrebbe provare a impostare manualmente gli iperparametri e cercare di migliorare noi stessi (o usare una libreria di ottimizzazione degli iperparametri come Optuna), sono troppo pigro per farlo e preferisco usare la ricerca casuale.

def crea_parametri_addestramento(baseline: bool = False) -> Dict[str, Any]:    if baseline:        return {}    epoca = random.randint(2, 120)    wordNgrams = random.randint(1, 6)    lr = np.random.uniform(0.02, 0.5)    dim = random.randint(50, 200)    minn = random.randint(0, 5)    maxn = random.randint(0, 5)    minCount = random.randint(1, 5)    ws = random.randint(2, 10)    lrUpdateRate = random.randint(50, 200)    bucket = random.randint(200000, 20000000)    return {        "epoca": epoca,        "wordNgrams": wordNgrams,        "lr": lr,        "dim": dim,        "minn": minn,        "maxn": maxn,        "minCount": minCount,        "lrUpdateRate": lrUpdateRate,        "ws": ws,        "bucket": bucket,        "thread": 12,    }

Questa funzione restituirà un insieme di parametri selezionati casualmente.

Possiamo provare un singolo set di parametri casuali semplicemente eseguendo:

modello = fasttext.train_supervised(input=str(train_filepath), **crea_parametri_addestramento())

Aggiungiamo un paio di righe extra per creare una pipeline di ottimizzazione degli iperparametri più completa. Qui sotto, dichiariamo il numero di iterazioni da cercare, istanziamo la migliore_precisione attuale come la precisione del modello di base e i migliori_param come un dizionario vuoto (parametri predefiniti).

Quindi, eseguiamo un loop in cui ogni iterazione genera casualmente i parametri e addestra e valuta il modello. Se la nuova precisione è maggiore della precedente registrazione, sovrascriviamo la migliore precisione e salviamo i migliori_param per riferimenti futuri.

iterazioni = 10migliore_precisione, migliori_param = risultati_validazione[1], {}for it in range(iterazioni):    parametri = crea_parametri_addestramento()    modello = fasttext.train_supervised(input=str(train_filepath), **parametri)    risultati_addestramento, risultati_validazione, risultati_test = ottieni_pozioni(modello=modello)    if risultati_validazione[1] > migliore_precisione:        migliore_precisione = risultati_validazione[1]        migliori_param = parametri    print(f"Migliore precisione finora: {migliore_precisione}")print(f"Migliori parametri: {migliori_param}")

Facendo ciò, siamo riusciti ad ottenere una precisione finale del 56,1%!

Conclusione

Approfondendo gli altri notebook che utilizzano questo dataset, sono in grado di vedere una soluzione Naive Bayes con una precisione del 70%, o una soluzione BERT che ottiene una precisione dell’88%. Chiaramente, questo è molto meglio di quanto abbiamo ottenuto con fasttext. Tuttavia, è stato applicato un significativo preprocessing del testo al dataset in queste implementazioni, qualcosa che non avevamo fatto.

Se i dati del testo non sono puliti, l’IA fasttext potrebbe considerare dati spazzatura per cercare di trovare modelli per etichettare il testo. Passi successivi per migliorare le prestazioni sarebbero applicare metodi di preprocessing al dataset. Inoltre, ci sono altre colonne di dati disponibili nel dataframe grezzo che potrebbero essere utili come input per il modello (abbiamo utilizzato solo colonne di testo e di etichetta). Lascio questi prossimi passi a te, dato che l’obiettivo di questo articolo è fornire una panoramica generica della libreria fasttext.

Abbiamo imparato:

  • Cosa è la libreria fasttext
  • Come preprocessare un dataset da utilizzare in fasttext
  • Come addestrare un modello di base sui dati
  • Come ottimizzare gli iperparametri del modello per migliorare i risultati di base

Grazie per aver letto fino alla fine! Spero che tu trovi questo utile e buona fortuna con i tuoi compiti di classificazione del testo.

Link:

Linkedin: https://www.linkedin.com/in/sergei-issaev/

Github: https://github.com/sergeiissaev

Kaggle: https://www.kaggle.com/sergei416

VoAGI: https://medium.com/@sergei740

Twitter: https://twitter.com/realSergAI

Scopri di più su Vooban: https://vooban.com/it