Construiți un program de clasificare a textului: un tutorial NLP
Publicat: 2022-03-11Învățarea profundă este o tehnologie care a devenit o parte esențială a fluxurilor de lucru de învățare automată. Valorificând îmbunătățirile puterii de calcul paralele și instrumentele de sprijin, rețelele neuronale complexe și profunde, care odată erau impracticabile, devin acum viabile.
Apariția unor biblioteci puternice și accesibile, cum ar fi Tensorflow, Torch și Deeplearning4j, a deschis, de asemenea, dezvoltarea utilizatorilor dincolo de mediul academic și departamentele de cercetare ale marilor companii de tehnologie. Ca o dovadă a omniprezenței sale în creștere, companii precum Huawei și Apple includ acum procesoare dedicate, optimizate pentru învățare profundă, în cele mai noi dispozitive ale lor, pentru a alimenta aplicațiile de învățare profundă.
Învățarea profundă și-a dovedit puterea în multe domenii. Cel mai important, AlphaGo de la Google a reușit să învingă jucători umani într-un joc Go, un joc a cărui complexitate uluitoare a fost odată considerată o barieră aproape de netrecut în calea computerelor în competiția sa împotriva jucătorilor umani. Proiectul Flow Machines de la Sony a dezvoltat o rețea neuronală care poate compune muzică în stilul muzicienilor celebri din trecut. FaceID, o caracteristică de securitate dezvoltată de Apple, folosește învățarea profundă pentru a recunoaște fața utilizatorului și pentru a urmări modificările aduse feței utilizatorului în timp.
În acest articol, vom aplica învățarea profundă la două dintre subiectele mele preferate: procesarea limbajului natural și vin. Vom construi un model pentru a înțelege recenziile de vin în limbaj natural de către experți și pentru a deduce varietatea vinului pe care îl evaluează.
Învățare profundă pentru NLP
Învățarea profundă a fost utilizată pe scară largă în procesarea limbajului natural (NLP), deoarece este foarte potrivită pentru învățarea structurii complexe subiacente a unei propoziții și a proximității semantice a diferitelor cuvinte. De exemplu, stadiul actual al tehnicii pentru analiza sentimentelor folosește învățarea profundă pentru a capta concepte lingvistice greu de modelat, cum ar fi negațiile și sentimentele mixte.
Învățarea profundă are mai multe avantaje față de alți algoritmi pentru NLP:
- Modele flexibile: modelele de învățare profundă sunt mult mai flexibile decât alte modele ML. Putem experimenta cu ușurință diferite structuri, adăugând și eliminând straturi după cum este necesar. Modelele de învățare profundă permit, de asemenea, construirea de modele cu rezultate flexibile. Flexibilitatea este cheia dezvoltării modelelor care sunt potrivite pentru înțelegerea structurilor lingvistice complexe. Este, de asemenea, esențial pentru dezvoltarea aplicațiilor NLP, cum ar fi traduceri, chatbot și aplicații text-to-speech.
- Sunt necesare mai puține cunoștințe de domeniu: deși cu siguranță avem nevoie de cunoștințe de domeniu și de intuiție pentru a dezvolta un model bun de învățare profundă, capacitatea algoritmilor de învățare profundă de a învăța singuri ierarhiile de caracteristici înseamnă că un dezvoltator nu are nevoie de cunoștințe atât de aprofundate despre spațiu problematic pentru a dezvolta algoritmi de deep learning NLP. Pentru un spațiu cu probleme la fel de complex precum limbajul natural, acesta este un avantaj foarte binevenit.
- Învățare continuă mai ușoară: algoritmii de învățare profundă sunt ușor de antrenat pe măsură ce apar date noi. Unii algoritmi de învățare automată necesită ca întregul set de date să fie trimis prin model pentru a fi actualizat, ceea ce ar prezenta o problemă pentru seturile de date mari, active.
Problema de azi
Astăzi, vom construi un algoritm de învățare profundă pentru a determina varietatea vinului care este revizuit pe baza textului de recenzie. Vom folosi setul de date revistei de vin la https://www.kaggle.com/zynicide/wine-reviews, care este furnizat de utilizatorul Kaggle zackthoutt .
Din punct de vedere conceptual, întrebarea este, putem face o recenzie a vinului ca...
Aromele includ fructe tropicale, mătură, pucioasă și ierburi uscate. Gustul nu este exagerat de expresiv, oferind mere necoapte, citrice și salvie uscată alături de o aciditate puternică.
… și recunoașteți că este vorba despre un amestec alb? Unii entuziaști de vin ar putea recunoaște semne revelatoare ale vinurilor albe, cum ar fi mărul, citricele și o aciditate pronunțată, dar ne putem antrena rețeaua neuronală să recunoască aceste semnale? În plus, ne putem antrena rețeaua neuronală pentru a recunoaște diferențele subtile dintre o revizuire a amestecului alb și o revizuire a pinot grigio?
Algoritmi similari
Problema cu care lucrăm astăzi este în esență o problemă de clasificare NLP. Există mai mulți algoritmi de clasificare NLP care au fost aplicați la diferite probleme din NLP. De exemplu, Bayes naiv au fost folosiți în diverși algoritmi de detectare a spam-ului, iar mașinile vectoriale de suport (SVM) au fost folosite pentru a clasifica texte, cum ar fi notele de progres la instituțiile medicale. Ar fi interesant să implementăm o versiune simplă a acestor algoritmi care să servească drept bază pentru modelul nostru de învățare profundă.
Bayes naiv
O implementare populară a Bayes naiv pentru NLP implică preprocesarea textului folosind TF-IDF și apoi rularea Bayes naiv multinomial pe ieșirile preprocesate. Acest lucru permite algoritmului să fie rulat pe cele mai proeminente cuvinte dintr-un document. Putem implementa Bayesul naiv după cum urmează:
import numpy as np from sklearn.naive_bayes import MultinomialNB from sklearn.feature_extraction.text import CountVectorizer import pandas as pd from collections import Counter from sklearn.model_selection import train_test_split from sklearn.feature_extraction.text import TfidfTransformer df = pd.read_csv('data/wine_data.csv') counter = Counter(df['variety'].tolist()) top_10_varieties = {i[0]: idx for idx, i in enumerate(counter.most_common(10))} df = df[df['variety'].map(lambda x: x in top_10_varieties)] description_list = df['description'].tolist() varietal_list = [top_10_varieties[i] for i in df['variety'].tolist()] varietal_list = np.array(varietal_list) count_vect = CountVectorizer() x_train_counts = count_vect.fit_transform(description_list) tfidf_transformer = TfidfTransformer() x_train_tfidf = tfidf_transformer.fit_transform(x_train_counts) train_x, test_x, train_y, test_y = train_test_split(x_train_tfidf, varietal_list, test_size=0.3) clf = MultinomialNB().fit(train_x, train_y) y_score = clf.predict(test_x) n_right = 0 for i in range(len(y_score)): if y_score[i] == test_y[i]: n_right += 1 print("Accuracy: %.2f%%" % ((n_right/float(len(test_y)) * 100)))
Rulați codul de mai sus și ar trebui să vedeți ceva de genul următor: 73,56%

Având în vedere că ne uităm la 10 clase, acesta este un rezultat destul de bun.
De asemenea, putem folosi mașina de suport vector și să vedem cum ar funcționa. Pentru a vedea cum funcționează, pur și simplu înlocuiți definiția clasificatorului cu
clf = SVC(kernel='linear').fit(train_x, train_y)
Rulați acest lucru și ar trebui să vedeți următoarea ieșire:
Precizie: 80,66%
Nici prea ponosit.
Să vedem dacă putem construi un model de învățare profundă care să poată depăși sau măcar să egaleze aceste rezultate. Dacă reușim acest lucru, ar fi un indiciu excelent că modelul nostru de învățare profundă este eficient în cel puțin replicarea rezultatelor modelelor populare de învățare automată bazate pe expertiza domeniului.
Construirea Modelului
Astăzi, vom folosi Keras cu Tensorflow pentru a ne construi modelul. Keras este o bibliotecă Python care face construirea modelelor de învățare profundă foarte ușoară în comparație cu interfața de nivel relativ scăzut a API-ului Tensorflow. Pe lângă straturile dense, vom folosi și straturile de încorporare și convoluționale pentru a învăța informațiile semantice subiacente ale cuvintelor și potențialele modele structurale din date.
Curățarea datelor
În primul rând, va trebui să restructuram datele într-un mod care să poată fi procesat și înțeles cu ușurință de către rețeaua noastră neuronală. Putem face acest lucru prin înlocuirea cuvintelor cu numere de identificare unică. Combinat cu un vector de încorporare, suntem capabili să reprezentăm cuvintele într-o manieră flexibilă și sensibilă din punct de vedere semantic.
În practică, vom dori să fim puțin mai deștepți cu privire la această preprocesare. Ar fi logic să se concentreze asupra cuvintelor utilizate în mod obișnuit și, de asemenea, să filtreze cuvintele cele mai frecvent utilizate (de exemplu, the, this, a).
Putem implementa această funcționalitate folosind Defaultdict și NLTK. Scrieți următorul cod într-un modul Python separat. L-am plasat în lib/get_top_x_words.py
.
from nltk import word_tokenize from collections import defaultdict def count_top_x_words(corpus, top_x, skip_top_n): count = defaultdict(lambda: 0) for c in corpus: for w in word_tokenize(c): count[w] += 1 count_tuples = sorted([(w, c) for w, c in count.items()], key=lambda x: x[1], reverse=True) return [i[0] for i in count_tuples[skip_top_n: skip_top_n + top_x]] def replace_top_x_words_with_vectors(corpus, top_x): topx_dict = {top_x[i]: i for i in range(len(top_x))} return [ [topx_dict[w] for w in word_tokenize(s) if w in topx_dict] for s in corpus ], topx_dict def filter_to_top_x(corpus, n_top, skip_n_top=0): top_x = count_top_x_words(corpus, n_top, skip_n_top) return replace_top_x_words_with_vectors(corpus, top_x)
Acum suntem gata să construim modelul. Dorim un strat de încorporare, un strat convoluțional și un strat dens pentru a profita de toate caracteristicile de învățare profundă care pot fi utile pentru aplicația noastră. Cu Keras, putem construi modelul foarte simplu:
from keras.models import Sequential from keras.layers import Dense, Conv1D, Flatten from keras.layers.embeddings import Embedding from keras.preprocessing import sequence from keras.utils import to_categorical import pandas as pd from collections import Counter from sklearn.model_selection import train_test_split from lib.get_top_xwords import filter_to_top_x df = pd.read_csv('data/wine_data.csv') counter = Counter(df['variety'].tolist()) top_10_varieties = {i[0]: idx for idx, i in enumerate(counter.most_common(10))} df = df[df['variety'].map(lambda x: x in top_10_varieties)] description_list = df['description'].tolist() mapped_list, word_list = filter_to_top_x(description_list, 2500, 10) varietal_list_o = [top_10_varieties[i] for i in df['variety'].tolist()] varietal_list = to_categorical(varietal_list_o) max_review_length = 150 mapped_list = sequence.pad_sequences(mapped_list, maxlen=max_review_length) train_x, test_x, train_y, test_y = train_test_split(mapped_list, varietal_list, test_size=0.3) max_review_length = 150 embedding_vector_length = 64 model = Sequential() model.add(Embedding(2500, embedding_vector_length, input_length=max_review_length)) model.add(Conv1D(50, 5)) model.add(Flatten()) model.add(Dense(100, activation='relu')) model.add(Dense(max(varietal_list_o) + 1, activation='softmax')) model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) model.fit(train_x, train_y, epochs=3, batch_size=64) y_score = model.predict(test_x) y_score = [[1 if i == max(sc) else 0 for i in sc] for sc in y_score] n_right = 0 for i in range(len(y_score)): if all(y_score[i][j] == test_y[i][j] for j in range(len(y_score[i]))): n_right += 1 print("Accuracy: %.2f%%" % ((n_right/float(len(test_y)) * 100)))
Rulați codul și ar trebui să vedeți următoarea ieșire.
Precizie: 77,20%
Amintiți-vă că acuratețea pentru Bayes și SVC naiv a fost de 73,56% și, respectiv, 80,66%. Așadar, rețeaua noastră neuronală se ține foarte bine față de unele dintre cele mai comune metode de clasificare a textului.
Concluzie
Astăzi, am abordat construirea unui model de învățare profundă de clasificare pentru a analiza recenziile de vin.
Am descoperit că am reușit să construim un model care a fost capabil să concureze și să depășească unii dintre ceilalți algoritmi de învățare automată. Sperăm că sunteți inspirat să utilizați aceste informații pentru a construi aplicații care analizează seturi de date mai complexe și generează rezultate mai complexe!
Notă: Puteți găsi codul pe care l-am folosit pentru acest articol pe GitHub.
Citiți suplimentare pe blogul Toptal Engineering:
- Un sens mai profund: modelarea subiectelor în Python
- Cum să construiți un bot de analiză a sentimentelor de e-mail: un tutorial NLP