Zbuduj program klasyfikacji tekstu: samouczek NLP
Opublikowany: 2022-03-11Głębokie uczenie to technologia, która stała się istotną częścią przepływów pracy uczenia maszynowego. Wykorzystując ulepszenia w zakresie mocy przetwarzania równoległego i narzędzi pomocniczych, złożone i głębokie sieci neuronowe, które kiedyś były niepraktyczne, stają się teraz wykonalne.
Pojawienie się potężnych i dostępnych bibliotek, takich jak Tensorflow, Torch i Deeplearning4j, otworzyło również możliwości rozwoju dla użytkowników spoza środowisk akademickich i działów badawczych dużych firm technologicznych. W dowód rosnącej wszechobecności firmy takie jak Huawei i Apple włączają teraz dedykowane, zoptymalizowane pod kątem głębokiego uczenia procesory w swoich najnowszych urządzeniach, aby zasilać aplikacje do głębokiego uczenia się.
Głębokie uczenie sprawdziło się w wielu dziedzinach. Przede wszystkim AlphaGo firmy Google była w stanie pokonać ludzkich graczy w grze Go, której zadziwiająca złożoność została kiedyś uznana za barierę prawie nie do pokonania dla komputerów w rywalizacji z ludzkimi graczami. Projekt Flow Machines firmy Sony opracował sieć neuronową, która może komponować muzykę w stylu znanych muzyków z przeszłości. FaceID, funkcja bezpieczeństwa opracowana przez Apple, wykorzystuje głębokie uczenie do rozpoznawania twarzy użytkownika i śledzenia zmian twarzy użytkownika w czasie.
W tym artykule zastosujemy uczenie głębokie do dwóch moich ulubionych tematów: przetwarzania języka naturalnego i wina. Zbudujemy model, aby zrozumieć recenzje win w języku naturalnym przez ekspertów i wywnioskować różnorodność ocenianego wina.
Głębokie uczenie dla NLP
Głębokie uczenie jest szeroko stosowane w przetwarzaniu języka naturalnego (NLP), ponieważ dobrze nadaje się do uczenia się złożonej podstawowej struktury zdania i semantycznej bliskości różnych słów. Na przykład obecny stan wiedzy w zakresie analizy sentymentów wykorzystuje głębokie uczenie się w celu wychwycenia trudnych do modelowania pojęć językowych, takich jak negacje i mieszane sentymenty.
Głębokie uczenie ma kilka zalet w porównaniu z innymi algorytmami NLP:
- Elastyczne modele: modele uczenia głębokiego są znacznie bardziej elastyczne niż inne modele ML. Możemy łatwo eksperymentować z różnymi strukturami, dodając i usuwając warstwy według potrzeb. Modele głębokiego uczenia umożliwiają również budowanie modeli z elastycznymi wynikami. Elastyczność jest kluczem do opracowania modeli, które dobrze nadają się do zrozumienia złożonych struktur językowych. Jest również niezbędny do tworzenia aplikacji NLP, takich jak tłumaczenia, chatboty i aplikacje do zamiany tekstu na mowę.
- Wymagana jest mniejsza wiedza domenowa: Podczas gdy z pewnością potrzebna jest wiedza i intuicja w dziedzinie domeny, aby opracować dobry model uczenia głębokiego, zdolność algorytmów uczenia głębokiego do samodzielnego uczenia się hierarchii funkcji oznacza, że programista nie potrzebuje tak dogłębnej wiedzy na temat przestrzeń problemowa do opracowania algorytmów głębokiego uczenia NLP. W przypadku tak złożonej przestrzeni problemowej, jak język naturalny, jest to bardzo pożądana zaleta.
- Łatwiejsze ciągłe uczenie: algorytmy uczenia głębokiego są łatwe do nauczenia, gdy pojawiają się nowe dane. Niektóre algorytmy uczenia maszynowego wymagają przesłania całego zestawu danych przez model w celu aktualizacji, co stanowiłoby problem w przypadku dużych zestawów danych na żywo.
Problem dzisiaj
Dzisiaj zbudujemy algorytm głębokiego uczenia się, aby określić różnorodność recenzowanego wina na podstawie tekstu recenzji. Będziemy używać zbioru danych magazynu wina pod adresem https://www.kaggle.com/zynicide/wine-reviews, który jest udostępniany przez użytkownika Kaggle zackthoutt .
Koncepcyjnie pytanie brzmi, czy możemy wziąć recenzję wina taką jak…
Aromaty zawierają owoce tropikalne, miotłę, siarkę i suszone zioła. Podniebienie nie jest zbyt wyraziste, oferując niedojrzałe jabłka, cytrusy i suszoną szałwię wraz z rześką kwasowością.
…i rozpoznajesz, że chodzi o białą mieszankę? Niektórzy entuzjaści wina mogą rozpoznać charakterystyczne oznaki białego wina, takie jak jabłko, cytrusy i wyraźną kwasowość, ale czy możemy wytrenować naszą sieć neuronową, aby rozpoznawać te sygnały? Dodatkowo, czy możemy wytrenować naszą sieć neuronową, aby rozpoznawała subtelne różnice między przeglądem białej mieszanki a przeglądem Pinot grigio?
Podobne algorytmy
Problem, z którym dzisiaj pracujemy, jest zasadniczo problemem klasyfikacji NLP. Istnieje kilka algorytmów klasyfikacji NLP, które zostały zastosowane do różnych problemów w NLP. Na przykład naiwne algorytmy Bayesa były wykorzystywane w różnych algorytmach wykrywania spamu, a maszyny wektorów nośnych (SVM) były wykorzystywane do klasyfikowania tekstów, takich jak notatki z postępów w instytucjach opieki zdrowotnej. Interesujące byłoby zaimplementowanie prostej wersji tych algorytmów, która posłuży jako punkt odniesienia dla naszego modelu uczenia głębokiego.
Naiwny Bayes
Popularna implementacja naiwnego Bayesa dla NLP obejmuje wstępne przetwarzanie tekstu przy użyciu TF-IDF, a następnie uruchomienie wielomianowego naiwnego Bayesa na wstępnie przetworzonych wyjściach. Pozwala to na uruchomienie algorytmu na najbardziej widocznych słowach w dokumencie. Naiwnego Bayesa możemy zaimplementować w następujący sposób:
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)))
Uruchom powyższy kod i powinieneś zobaczyć coś takiego: 73,56%

Jak na 10 klas, to całkiem niezły wynik.
Możemy również użyć maszyny wektorów nośnych i zobaczyć, jak to zrobi. Aby zobaczyć, jak działa, po prostu zamień definicję klasyfikatora na
clf = SVC(kernel='linear').fit(train_x, train_y)
Uruchom to i powinieneś zobaczyć następujące dane wyjściowe:
Dokładność: 80,66%
Niezbyt odrapany.
Zobaczmy, czy możemy zbudować model głębokiego uczenia się, który może przewyższyć lub przynajmniej dorównać tym wynikom. Jeśli nam się to uda, będzie to znakomita wskazówka, że nasz model głębokiego uczenia jest skuteczny przynajmniej w replikowaniu wyników popularnych modeli uczenia maszynowego opartych na wiedzy domenowej.
Budowanie modelu
Dziś do budowy naszego modelu użyjemy Keras z Tensorflow. Keras to biblioteka Pythona, która sprawia, że budowanie modeli uczenia głębokiego jest bardzo łatwe w porównaniu ze stosunkowo niskopoziomowym interfejsem API Tensorflow. Oprócz warstw gęstych użyjemy również warstw osadzania i splotu, aby poznać podstawowe informacje semantyczne słów i potencjalne wzorce strukturalne w danych.
Czyszczenie danych
Najpierw będziemy musieli zrestrukturyzować dane w sposób, który będzie łatwo przetwarzany i rozumiany przez naszą sieć neuronową. Możemy to zrobić, zastępując słowa jednoznacznie identyfikującymi liczby. W połączeniu z wektorem osadzania jesteśmy w stanie przedstawić słowa w sposób, który jest zarówno elastyczny, jak i wrażliwy semantycznie.
W praktyce będziemy chcieli nieco sprytniej podejść do tego wstępnego przetwarzania. Sensowne byłoby skupienie się na powszechnie używanych słowach, a także odfiltrowanie najczęściej używanych słów (np. the, this, a).
Możemy zaimplementować tę funkcjonalność za pomocą Defaultdict i NLTK. Napisz następujący kod w osobnym module Pythona. Umieściłem go w 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)
Teraz jesteśmy gotowi do zbudowania modelu. Chcemy, aby warstwa osadzania, warstwa splotowa i warstwa gęsta korzystały ze wszystkich funkcji uczenia głębokiego, które mogą być pomocne w naszej aplikacji. Z Kerasem możemy zbudować model w bardzo prosty sposób:
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)))
Uruchom kod i powinieneś zobaczyć następujące dane wyjściowe.
Dokładność: 77,20%
Przypomnijmy, że dokładność dla naiwnych Bayesa i SVC wynosiła odpowiednio 73,56% i 80,66%. Tak więc nasza sieć neuronowa radzi sobie z niektórymi z bardziej powszechnych metod klasyfikacji tekstu.
Wniosek
Dzisiaj omówiliśmy budowę modelu klasyfikacji głębokiego uczenia się, aby analizować recenzje win.
Odkryliśmy, że jesteśmy w stanie zbudować model, który będzie w stanie konkurować z niektórymi innymi algorytmami uczenia maszynowego i przewyższyć je. Mamy nadzieję, że zainspirujesz się do wykorzystania tych informacji do tworzenia aplikacji, które analizują bardziej złożone zbiory danych i generują bardziej złożone dane wyjściowe!
Uwaga: kod, którego użyłem w tym artykule, możesz znaleźć w serwisie GitHub.
Dalsza lektura na blogu Toptal Engineering:
- Głębsze znaczenie: modelowanie tematyczne w Pythonie
- Jak zbudować bota do analizy nastrojów e-mail: samouczek NLP