Ćwiczenie — tworzenie i trenowanie sieci neuronowej

Ukończone

W tej lekcji użyjesz interfejsu Keras do utworzenia i wytrenowania sieci neuronowej, która analizuje tekst pod kątem tonacji. Aby móc wytrenować sieć neuronową, potrzebujesz danych, na których można przeprowadzić trenowanie. Zamiast pobierać zewnętrzny zestaw danych, użyjesz zestawu danych IMDB movie reviews sentiment classification dołączonego do interfejsu Keras. Zestaw danych IMDB zawiera 50 000 recenzji filmów, które zostały indywidualnie ocenione jako pozytywne (1) lub negatywne (0). Na ten zestaw danych składa się 25 000 recenzji na potrzeby trenowania i 25 000 recenzji na potrzeby testowania. Tonacja wyrażana w tych recenzjach jest bazą, na podstawie której Twoja sieć neuronowa przeanalizuje zaprezentowany tekst i wygeneruje wyniki na potrzeby tonacji.

Zestaw danych IMDB jest jednym z kilku przydatnych zestawów danych dołączonych do interfejsu Keras. Aby uzyskać pełną listę wbudowanych zestawów danych, zobacz https://keras.io/datasets/.

  1. Wpisz lub wklej następujący kod do pierwszej komórki notesu i kliknij przycisk Uruchom (lub naciśnij klawisze Shift+Enter), aby wykonać go, a następnie dodaj nową komórkę poniżej:

    from keras.datasets import imdb
    top_words = 10000
    (x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=top_words)
    

    Ten kod ładuje dołączony do interfejsu Keras zestaw danych IMDB i tworzy słownik, mapując słowa ze wszystkich 50 000 recenzji na liczby całkowite wskazujące względną częstotliwość występowania słowa. Do poszczególnych słów przypisano unikatowe liczby całkowite. Najczęściej spotykane słowo ma przypisaną liczbę 1, drugie z kolei najczęściej występujące słowo ma przypisaną liczbę 2 itd. Funkcja load_data zwraca również parę krotek zawierających recenzje filmów (w tym przykładzie x_train i x_test) oraz jedynki i zera klasyfikujące te recenzje jako pozytywne lub negatywne (y_train i y_test).

  2. Upewnij się, że widać komunikat „Using TensorFlow backend” (Korzystanie z zaplecza TensorFlow) wskazujący, że interfejs Keras używa narzędzia TensorFlow jako zaplecza.

    Ładowanie zestawu danych IMDB.

    Ładowanie zestawu danych IMDB

    Jeżeli chcesz, aby interfejs Keras używał jako zaplecza zestawu Microsoft Cognitive Toolkit, znanego także jako CNTK, dodaj kilka wierszy kodu na początku notesu. Aby uzyskać przykład, zobacz CNTK and Keras in Azure Notebooks (CNTK i Keras w usłudze Azure Notebooks).

  3. Co właściwie ładuje funkcja load_data? Zmienna o nazwie x_train to lista 25 000 list, z których każda reprezentuje jedną recenzję filmu. (x_test jest również listą 25 000 list reprezentujących 25 000 przeglądów. x_train Będą one używane do trenowania, a x_test będą używane do testowania). Ale wewnętrzne listy — te reprezentujące recenzje filmów — nie zawierają słów; zawierają liczby całkowite. Poniżej przedstawiono, jak opisano je w dokumentacji interfejsu Keras:

    Dokumentacja protokołu Keras.

    Powód, dla którego wewnętrzne listy zawierają liczby zamiast tekstu, jest taki, że sieci neuronowe nie trenuje się za pomocą słów tylko liczb. Dokładnie mówiąc, trenuje się je za pomocą tensorów. W tym przypadku każda recenzja jest 1-wymiarowym tensorem (wyobraź go sobie jako 1-wymiarową tablicę) zawierającym liczby całkowite identyfikujące słowa składające się na recenzję. Aby to zademonstrować, wpisz następującą instrukcję języka Python do pustej komórki, a następnie wykonaj ją, aby zobaczyć liczby całkowite reprezentujące pierwszą recenzję z zestawu szkoleniowego:

    x_train[0]
    

    Liczby całkowite składające się z pierwszej recenzji w zestawie treningowym IMDB.

    Liczby całkowite składające się na pierwszą recenzję z zestawu szkoleniowego IMDB

    Pierwsza liczba na liście — 1 — nie reprezentuje wcale słowa. Oznacza ona początek recenzji i jest taka sama dla wszystkich recenzji w zestawie danych. Liczby 0 i 2 są również zarezerwowane. Od pozostałych liczb należy odjąć 3, aby zamapować liczbę całkowitą w recenzji na odpowiednią liczbę całkowitą w słowniku. Druga liczba — 14 — odwołuje się do słowa odpowiadającego liczbie 11 w słowniku. Trzecia liczba reprezentuje słowo przypisane do liczby 19 w słowniku i tak dalej.

  4. Zastanawiasz się, jak wygląda słownik? Wykonaj następującą instrukcję w nowej komórce notesu:

    imdb.get_word_index()
    

    Pokazano tylko podzbiór pozycji słownika. Cały słownik zawiera ponad 88 000 słów oraz liczb całkowitych, które im odpowiadają. Wyświetlane tutaj dane wyjściowe prawdopodobnie będą się różniły od danych wyjściowych na Twoim ekranie, ponieważ słownik jest generowany od nowa po każdym wywołaniu funkcji load_data.

    Słownik mapuje wyrazy na liczby całkowite.

    Mapowanie słów na liczby całkowite w słowniku

  5. Jak już wiesz, każda recenzja w zestawie danych jest kodowana jako zbiór liczb całkowitych, a nie słów. Czy jest możliwe odkodowanie recenzji i zobaczenie jej oryginalnego tekstu? Wprowadź następujące instrukcje do nowej komórki i wykonaj je, aby wyświetlić pierwszą recenzję w zmiennej x_train w formacie tekstowym:

    word_dict = imdb.get_word_index()
    word_dict = { key:(value + 3) for key, value in word_dict.items() }
    word_dict[''] = 0  # Padding
    word_dict['>'] = 1 # Start
    word_dict['?'] = 2 # Unknown word
    reverse_word_dict = { value:key for key, value in word_dict.items() }
    print(' '.join(reverse_word_dict[id] for id in x_train[0]))
    

    W danych wyjściowych znak ">" oznacza początek przeglądu, podczas gdy znak "?" oznacza wyrazy, które nie należą do najczęściej występujących 10 000 wyrazów w zestawie danych. Te „nieznane” słowa są reprezentowane przez liczby 2 na liście liczb całkowitych reprezentujących recenzję. Czy pamiętasz parametr num_words przekazany do funkcji load_data? To tutaj odgrywa on swoją rolę. Nie zmniejsza on rozmiaru słownika, ale ogranicza zakres liczb całkowitych używanych do kodowania recenzji.

    Pierwsza recenzja w formacie tekstowym.

    Pierwsza recenzja w formacie tekstowym

  6. Recenzje są „wyczyszczone” w takim sensie, że wszystkie litery zostały przekształcone w małe litery i usunięto znaki interpunkcyjne. Nie są one jednak gotowe do trenowania sieci neuronowej na potrzeby analizowania tekstu pod kątem tonacji. W przypadku trenowania sieci neuronowej za pomocą kolekcji tensorów każdy tensor powinien być takiej samej długości. Obecnie listy reprezentujące recenzje w zmiennych x_train i x_test mają różne długości.

    Na szczęście interfejs Keras zawiera funkcję, która pobiera listę list jako dane wejściowe i konwertuje wewnętrzne listy do określonej długości obcinając je w razie potrzeby lub dopełniając zerami. Wprowadź następujący kod w notesie, a następnie uruchom go, aby wymusić zmianę długości wszystkich list reprezentujących recenzje filmów w zmiennych x_train i x_test na 500 liczb całkowitych:

    from keras.preprocessing import sequence
    max_review_length = 500
    x_train = sequence.pad_sequences(x_train, maxlen=max_review_length)
    x_test = sequence.pad_sequences(x_test, maxlen=max_review_length)
    
  7. Teraz, po przygotowaniu danych trenowania i testowania, można utworzyć model! Uruchom następujący kod w notesie, aby utworzyć sieć neuronową, która przeprowadzi analizę tonacji:

    from keras.models import Sequential
    from keras.layers import Dense
    from keras.layers.embeddings import Embedding
    from keras.layers import Flatten
    
    embedding_vector_length = 32
    model = Sequential()
    model.add(Embedding(top_words, embedding_vector_length, input_length=max_review_length))
    model.add(Flatten())
    model.add(Dense(16, activation='relu'))
    model.add(Dense(16, activation='relu'))
    model.add(Dense(1, activation='sigmoid'))
    model.compile(loss='binary_crossentropy',optimizer='adam', metrics=['accuracy'])
    print(model.summary())
    

    Sprawdź, czy dane wyjściowe wyglądają następująco:

    Tworzenie sieci neuronowej za pomocą protokołu Keras.

    Tworzenie sieci neuronowej za pomocą interfejsu Keras

    Ten kod jest kluczowy w kwestii sposobu konstruowania sieci neuronowej za pomocą interfejsu Keras. Najpierw tworzone są wystąpienia obiektu Sequential reprezentujące „sekwencyjny” model składający się z kompleksowego stosu warstw, w którym dane wyjściowe z jednej warstwy stają się danymi wejściowymi dla następnej.

    Kilka następnych instrukcji dodaje warstwy do modelu. Pierwszą jest warstwa osadzania, która ma kluczowe znaczenie dla sieci neuronowych przetwarzających słowa. Warstwa osadzania zasadniczo mapuje wielowymiarowe tablice zawierające indeksy liczb całkowitych reprezentujących słowa na tablice liczb zmiennoprzecinkowych zawierające mniej wymiarów. Ta warstwa umożliwia także identyczne traktowanie słów o podobnym znaczeniu. Pełny opis przetwarzania osadzonych słów wykracza poza zakres tego laboratorium, ale możesz dowiedzieć się więcej z artykułu Why You Need to Start Using Embedding Layers (Dlaczego należy rozpocząć korzystanie z warstw osadzania). Jeśli wolisz bardziej naukowe wyjaśnienie, zapoznaj się z dokumentem Efficient Estimation of Word Representations in Vector Space (Wydajne szacowanie reprezentacji słów w przestrzeni wektorowej). Wywołanie warstwy Flatten po dodaniu warstwy osadzania przekształca dane wyjściowe w dane wejściowe dla następnej warstwy.

    Następne trzy warstwy dodane do modelu są warstwami gęstymi znanymi również jako warstwy w pełni połączone. Są to tradycyjne warstwy, które są często używane w sieciach neuronowych. Każda warstwa zawiera n węzłów lub neuronów, a każdy neuron odbiera dane wejściowe z każdego neuronu w poprzedniej warstwie, stąd termin "w pełni połączony". Są to te warstwy, które pozwalają sieci neuronowej "uczyć się" na podstawie danych wejściowych przez iteracyjne odgadywanie danych wyjściowych, sprawdzanie wyników i dostrajanie połączeń w celu uzyskania lepszych wyników. Dwie pierwsze gęste warstwy w tej sieci zawierają po 16 neuronów każda. Ta liczba została wybrana arbitralnie. Można zwiększyć dokładność modelu, eksperymentując z różnymi rozmiarami. Ostatnia gęsta warstwa zawiera tylko jeden neuron, ponieważ ostatecznym celem sieci jest określenie jednej przewidywanej wartości wyjściowej — to znaczy tonacji z wynikiem od 0,0 do 1,0.

    Wynikiem jest sieć neuronowa przedstawiona poniżej. Sieć zawiera warstwę danych wejściowych, warstwę danych wyjściowych i dwie warstwy ukryte (gęste warstwy zawierające po 16 neuronów). Dla porównania niektóre współczesne, bardziej zaawansowane sieci neuronowe składają się z ponad 100 warstw. Przykładem jest sieć ResNet-152 firmy Microsoft Research, której dokładność identyfikowania obiektów na zdjęciach czasami wykracza poza możliwości człowieka. Można utworzyć sieć ResNet-152 za pomocą interfejsu Keras, ale aby tego dokonać, byłby potrzebny klaster komputerów wyposażonych w procesory GPU do trenowania od podstaw.

    Wizualizowanie sieci neuronowej.

    Wizualizacja sieci neuronowej

    Wywołanie funkcji compile „kompiluje” model przez określenie ważnych parametrów, takich jak wybór optymalizatora i metryk, których należy użyć do ocenienia dokładności modelu w każdym kroku trenowania. Trenowanie rozpoczyna się dopiero po wywołaniu funkcji fit modelu, dlatego wykonanie funkcji compile trwa zwykle szybko.

  8. Teraz wywołaj funkcję fit w celu wytrenowania sieci neuronowej:

    hist = model.fit(x_train, y_train, validation_data=(x_test, y_test), epochs=5, batch_size=128)
    

    Trenowanie powinno zająć około 6 minut, czyli nieco więcej niż 1 minutę na każdą epokę. Parametr epochs=5 informuje interfejs Keras, że w modelu powinno się odbyć 5 przebiegów do przodu i do tyłu. Podczas każdego przebiegu model uczy się na danych szkoleniowych i mierzy („waliduje”), z jaką skutecznością przebiega trenowanie przy użyciu danych testowych. Następnie dokonuje korekt i wraca do następnego przebiegu lub epoki. Znajduje to odzwierciedlenie w danych wyjściowych funkcji fit, które pokazują dokładność trenowania (acc) i dokładność walidacji (val_acc) dla każdego epoki.

    Parametr batch_size=128 informuje interfejs Keras, aby jednorazowo użyć 128 przykładów szkoleniowych do trenowania sieci. Partie o większych rozmiarach skracają czas trenowania (w każdej epoce jest wymagana mniejsza liczba przebiegów do przetworzenia wszystkich danych szkoleniowych), ale partie o mniejszych rozmiarach czasami zwiększają dokładność. Po ukończeniu tego laboratorium możesz tu wrócić i spróbować ponownie przetrenować model za pomocą partii zawierających 32 przykłady, aby zobaczyć, jaki będzie to miało wpływ, jeśli w ogóle będzie miało, na dokładności modelu. Czas trenowania wydłuży się mniej więcej dwukrotnie.

    Trenowanie modelu.

    Trenowanie modelu

  9. Ten model jest nietypowy, ponieważ dobrze się trenuje za pomocą zaledwie kilku epok. Dokładność trenowania szybko powiększa się do blisko 100%, podczas gdy dokładność walidacji wzrasta do epoki lub dwóch, a następnie spłaszcza się. Zazwyczaj nie chcesz trenować modelu dłużej niż jest to wymagane, aby te dokładności ustabilizowały się. Występuje ryzyko wystąpienia nadmiernego dopasowania, co przejawia się tym, że model zachowuje się dobrze z danymi testowymi, ale gorzej z rzeczywistymi danymi. Jedną z oznak nadmiernego dopasowania modelu jest rosnąca rozbieżność między dokładnością trenowania i dokładnością walidacji. Aby zapoznać się z doskonałym wprowadzeniem do nadmiernego dopasowania, zobacz Overfitting in Machine Learning: What It Is and How to Prevent It (Overfitting in Machine Learning: What It Is and How to Prevent It).

    Aby zwizualizować zmiany w dokładności trenowania i walidacji jako postęp trenowania, wykonaj następujące instrukcje w nowej komórce notesu:

    import seaborn as sns
    import matplotlib.pyplot as plt
    %matplotlib inline
    
    sns.set()
    acc = hist.history['acc']
    val = hist.history['val_acc']
    epochs = range(1, len(acc) + 1)
    
    plt.plot(epochs, acc, '-', label='Training accuracy')
    plt.plot(epochs, val, ':', label='Validation accuracy')
    plt.title('Training and Validation Accuracy')
    plt.xlabel('Epoch')
    plt.ylabel('Accuracy')
    plt.legend(loc='upper left')
    plt.plot()
    

    Dane dotyczące dokładności pochodzą z obiektu history zwróconego przez funkcję fit modelu. Czy w oparciu o widoczny wykres uważasz, że należy zalecić zwiększenie, zmniejszenie czy pozostawienie takiej samej liczby epok trenowania?

  10. Innym sposobem wykrycia nadmiernego dopasowania jest porównywanie utraty trenowania z utratą walidacji w miarę postępu trenowania. Tego typu problemy z optymalizacją występują podczas minimalizowania funkcji utraty. Więcej informacji znajduje się tutaj. Jeśli dla danej epoki utrata trenowania jest o wiele większa niż utrata walidacji, może to być dowodem na nadmierne dopasowanie. W poprzednim kroku użyliśmy właściwości acc i val_acc właściwości history obiektu history w celu wykreślenia dokładności trenowania i dokładności walidacji. Ta sama właściwość zawiera również wartości o nazwie loss i val_loss reprezentujące odpowiednio utratę trenowania i utratę walidacji. Jak należy zmodyfikować powyższy kod, aby utworzyć wykres podobny do poniższego?

    Utrata trenowania i walidacji.

    Utrata trenowania i walidacji

    Biorąc pod uwagę, że rozbieżność między utratą trenowania i walidacji zaczyna się zwiększać w trzeciej epoce, co należałoby odpowiedzieć komuś, kto zaleca zwiększenie liczby epok do 10 lub 20?

  11. Na koniec wywołaj metodę evaluate modelu, aby zmierzyć dokładność, z jaką model jest w stanie określić ilościowo tonację wyrażoną w tekstowych danych testowych zawartych w zmiennych x_test (recenzje) i y_test (zera i jedynki, czyli „etykiety” wskazujące, które recenzje są pozytywne, a które negatywne):

    scores = model.evaluate(x_test, y_test, verbose=0)
    print("Accuracy: %.2f%%" % (scores[1] * 100))
    

    Co to jest obliczana dokładność modelu?

Prawdopodobnie osiągnięto dokładność na poziomie od 85% do 90%. Jest to wartość akceptowalna, biorąc pod uwagę, że model został utworzony od podstaw (w przeciwieństwie do używania wstępnie wytrenowanej sieci neuronowej), a czas trenowania był krótki nawet bez procesora GPU. Możliwe jest uzyskanie dokładności na poziomie 95% lub wyższym przy użyciu alternatywnych architektur sieci neuronowych, w szczególności takich jak rekurencyjne sieci neuronowe (RNN), które wykorzystują warstwy długiej krótkoterminowej pamięci (LSTM). Interfejs Keras ułatwia tworzenie takich sieci, ale czas ich trenowania może się wydłużać wykładniczo. Utworzony model stanowi rozsądny kompromis między dokładnością i czasem trenowania. Jednak jeśli chcesz dowiedzieć się więcej o tworzeniu sieci RNN przy użyciu interfejsu Keras, zobacz Understanding LSTM and its Quick Implementation in Keras for Sentiment Analysis (Warstwy LSTM i ich szybka implementacja w interfejsie Keras na potrzeby analizy tonacji).

Sprawdź swoją wiedzę

1.

Czy w oparciu o pierwszy utworzony wykres („Dokładność trenowania i walidacji”) uważasz, że należy zalecić zwiększenie, zmniejszenie czy pozostawienie takiej samej liczby epok trenowania?