Konwolucyjne sieci neuronowe wykorzystujące Keras i TPU

1. Przegląd

Z tego modułu dowiesz się, jak złożyć warstwę konwolucyjną w model sieci neuronowej, która może rozpoznawać kwiaty. Tym razem samodzielnie zbudujesz model od podstaw i wykorzystasz moc TPU, aby wytrenować go w kilka sekund i iteracyjnie ulepszać jego projekt.

Ten moduł zawiera niezbędne wyjaśnienia teoretyczne dotyczące konwolucyjnych sieci neuronowych i jest dobrym punktem wyjścia dla programistów, którzy chcą dowiedzieć się więcej o deep learning.

Ten moduł jest częścią 3 serii „Keras on TPU”. Możesz wykonać je w podanej kolejności lub niezależnie od siebie.

ca8cc21f6838eccc.png

Czego się nauczysz

  • Aby utworzyć konwolucyjny klasyfikator obrazów za pomocą modelu sekwencyjnego Keras.
  • Aby wytrenować model Keras na TPU:
  • Aby dostroić model za pomocą dobrze dobranych warstw konwolucyjnych.

Prześlij opinię

Jeśli zauważysz w tym module coś nieprawidłowego, poinformuj nas o tym. Opinie można przesyłać za pomocą zgłoszeń w GitHub [link do opinii].

2. Krótkie wprowadzenie do Google Colaboratory

W tym module używamy Google Collaboratory, więc nie musisz niczego konfigurować. Colaboratory to platforma online z notatnikami przeznaczona do celów edukacyjnych. Oferuje bezpłatne szkolenia dotyczące procesorów, procesorów graficznych i TPU.

688858c21e3beff2.png

Możesz otworzyć ten przykładowy notatnik i uruchomić kilka komórek, aby zapoznać się z Colaboratory.

c3df49e90e5a654f.png Welcome to Colab.ipynb

Wybieranie backendu TPU

8832c6208c99687d.png

W menu Colab kliknij Środowisko wykonawcze > Zmień typ środowiska wykonawczego, a następnie wybierz TPU. W tym module nauczysz się korzystać z wydajnej jednostki TPU (Tensor Processing Unit) do trenowania z akceleracją sprzętową. Połączenie z czasem działania nastąpi automatycznie przy pierwszym wykonaniu kodu. Możesz też użyć przycisku „Połącz” w prawym górnym rogu.

Wykonywanie notatnika

76d05caa8b4db6da.png

Uruchamiaj komórki pojedynczo, klikając je i naciskając Shift + Enter. Możesz też uruchomić cały notatnik, klikając Środowisko wykonawcze > Uruchom wszystko.

Spis treści

429f106990037ec4.png

Wszystkie notatniki mają spis treści. Możesz go otworzyć, klikając czarną strzałkę po lewej stronie.

Ukryte komórki

edc3dba45d26f12a.png

Niektóre komórki będą wyświetlać tylko swój tytuł. Jest to funkcja notatnika Colab. Możesz kliknąć je dwukrotnie, aby zobaczyć kod w środku, ale zwykle nie jest on zbyt interesujący. Zwykle są to funkcje pomocnicze lub wizualizacyjne. Aby zdefiniować funkcje w komórkach, musisz je uruchomić.

Uwierzytelnianie

cdd4b41413100543.png

Colab może uzyskać dostęp do Twoich prywatnych zasobników Google Cloud Storage, jeśli uwierzytelnienie nastąpi przy użyciu autoryzowanego konta. Powyższy fragment kodu uruchomi proces uwierzytelniania.

3. [INFO] Czym są jednostki Tensor Processing Unit (TPU)?

W skrócie

f88cf6facfc70166.png

Kod do trenowania modelu na TPU w Keras (z możliwością powrotu do GPU lub CPU, jeśli TPU nie jest dostępny):

try: # detect TPUs
    tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect()
    strategy = tf.distribute.TPUStrategy(tpu)
except ValueError: # detect GPUs
    strategy = tf.distribute.MirroredStrategy() # for CPU/GPU or multi-GPU machines

# use TPUStrategy scope to define model
with strategy.scope():
  model = tf.keras.Sequential( ... )
  model.compile( ... )

# train model normally on a tf.data.Dataset
model.fit(training_dataset, epochs=EPOCHS, steps_per_epoch=...)

Dziś użyjemy TPU do zbudowania i zoptymalizowania klasyfikatora kwiatów w interaktywnym tempie (minuty na przebieg trenowania).

688858c21e3beff2.png

Dlaczego jednostki TPU?

Nowoczesne procesory graficzne są zorganizowane wokół programowalnych „rdzeni”, co stanowi bardzo elastyczną architekturę, która umożliwia im wykonywanie różnych zadań, takich jak renderowanie 3D, uczenie głębokie, symulacje fizyczne itp. TPU z kolei łączą klasyczny procesor wektorowy z dedykowaną jednostką mnożenia macierzy i doskonale sprawdzają się w każdym zadaniu, w którym dominują duże mnożenia macierzy, np. w sieciach neuronowych.

8eb3e718b8e2ed08.png

Ilustracja: gęsta warstwa sieci neuronowej jako mnożenie macierzy, w którym partia 8 obrazów jest przetwarzana przez sieć neuronową jednocześnie. Wykonaj mnożenie wiersza przez kolumnę, aby sprawdzić, czy rzeczywiście oblicza ważoną sumę wartości wszystkich pikseli obrazu. Warstwy konwolucyjne też można przedstawić jako mnożenie macierzy, choć jest to nieco bardziej skomplikowane ( wyjaśnienie znajdziesz tutaj, w sekcji 1).

Sprzęt

MXU i VPU

Rdzeń TPU v2 składa się z jednostki mnożnika macierzy (MXU), która wykonuje mnożenie macierzy, oraz jednostki przetwarzania wektorowego (VPU), która wykonuje wszystkie inne zadania, takie jak aktywacje, softmax itp. Jednostka VPU obsługuje obliczenia zmiennoprzecinkowe 32-bitowe i całkowite 32-bitowe. MXU działa natomiast w formacie zmiennoprzecinkowym o mieszanej precyzji 16–32 bitów.

7d68944718f76b18.png

Zmiennoprzecinkowe liczby mieszanej precyzji i bfloat16

MXU oblicza mnożenie macierzy przy użyciu danych wejściowych bfloat16 i danych wyjściowych float32. Pośrednie akumulacje są wykonywane z precyzją float32.

19c5fc432840c714.png

Trenowanie sieci neuronowych jest zwykle odporne na szum wprowadzany przez zmniejszoną precyzję zmiennoprzecinkową. W niektórych przypadkach szum pomaga nawet optymalizatorowi osiągnąć zbieżność. 16-bitowa precyzja zmiennoprzecinkowa była tradycyjnie używana do przyspieszania obliczeń, ale formaty float16 i float32 mają bardzo różne zakresy. Zmniejszenie precyzji z float32 do float16 zwykle powoduje przekroczenie zakresu w górę i w dół. Istnieją rozwiązania, ale zwykle wymagają dodatkowej pracy, aby float16 działał prawidłowo.

Dlatego w TPU wprowadziliśmy format bfloat16. Jest to skrócony format float32, który ma dokładnie te same bity wykładnika i zakres co float32. W połączeniu z faktem, że TPU wykonują mnożenie macierzy w mieszanej precyzji z danymi wejściowymi bfloat16, ale danymi wyjściowymi float32, oznacza to, że zwykle nie są potrzebne żadne zmiany w kodzie, aby skorzystać ze wzrostu wydajności wynikającego z mniejszej precyzji.

Macierz systoliczna

MXU wykonuje mnożenie macierzy w sprzęcie za pomocą tzw. architektury „tablicy systolicznej”, w której elementy danych przepływają przez tablicę jednostek obliczeniowych. (W medycynie termin „skurczowy” odnosi się do skurczów serca i przepływu krwi, a w tym przypadku do przepływu danych).

Podstawowym elementem mnożenia macierzy jest iloczyn skalarny wiersza jednej macierzy i kolumny drugiej macierzy (ilustracja u góry tej sekcji). W przypadku mnożenia macierzy Y=X*W jeden element wyniku to:

Y[2,0] = X[2,0]*W[0,0] + X[2,1]*W[1,0] + X[2,2]*W[2,0] + ... + X[2,n]*W[n,0]

Na procesorze graficznym programuje się ten iloczyn skalarny w „rdzeniu” procesora graficznego, a następnie wykonuje się go równolegle na tylu „rdzeniach”, ile jest dostępnych, aby spróbować obliczyć wszystkie wartości wynikowej macierzy naraz. Jeśli wynikowa macierz ma rozmiar 128 x 128, wymagałoby to 128 x 128=16 tys. „rdzeni”, co zwykle nie jest możliwe. Największe procesory graficzne mają około 4000 rdzeni. TPU z kolei wykorzystuje w jednostkach obliczeniowych MXU absolutne minimum sprzętu: tylko bfloat16 x bfloat16 => float32 mnożarki-akumulatory. Są one tak małe, że jednostka TPU może zaimplementować 16 tys. takich jednostek w macierzy MXU o wymiarach 128 x 128 i przetworzyć to mnożenie macierzy za jednym razem.

f1b283fc45966717.gif

Ilustracja: tablica skurczowa MXU. Elementami obliczeniowymi są mnożniki-akumulatory. Wartości jednej macierzy są wczytywane do tablicy (czerwone kropki). Wartości z drugiej macierzy przepływają przez tablicę (szare kropki). Linie pionowe przenoszą wartości w górę. Linie poziome propagują sumy częściowe. Sprawdzenie, czy w miarę przepływu danych przez tablicę po prawej stronie pojawia się wynik mnożenia macierzy, pozostawiamy użytkownikowi.

Dodatkowo podczas obliczania iloczynów skalarnych w MXU sumy pośrednie przepływają między sąsiednimi jednostkami obliczeniowymi. Nie trzeba ich przechowywać ani pobierać z pamięci ani nawet z pliku rejestru. W rezultacie architektura tablicy systolicznej TPU ma znaczną przewagę pod względem gęstości i mocy, a także niepomijalną przewagę pod względem szybkości nad GPU podczas obliczania mnożenia macierzy.

Cloud TPU

Gdy poprosisz o 1 „Cloud TPU v2” na Google Cloud Platform, otrzymasz maszynę wirtualną z płytą TPU podłączoną przez PCI. Płyta TPU ma 4 dwurdzeniowe układy TPU. Każdy rdzeń TPU ma jednostkę VPU (Vector Processing Unit) i jednostkę MXU (MatriX multiply Unit) o wymiarach 128 x 128. Ta „Cloud TPU” jest zwykle połączona przez sieć z maszyną wirtualną, która ją zażądała. Pełny obraz wygląda więc tak:

dfce5522ed644ece.png

Ilustracja: maszyna wirtualna z akceleratorem „Cloud TPU” podłączonym do sieci. „Cloud TPU” to maszyna wirtualna z płytą TPU podłączoną przez PCI, na której znajdują się 4 dwurdzeniowe układy TPU.

Pody TPU

W centrach danych Google układy TPU są połączone z interfejsem komputera o dużej mocy obliczeniowej (HPC), dzięki czemu mogą działać jako jeden bardzo duży akcelerator. Google nazywa je podami. Mogą one obejmować do 512 rdzeni TPU v2 lub 2048 rdzeni TPU v3.

2ec1e0d341e7fc34.jpeg

Ilustracja: pod TPU v3. Płyty i szafy TPU połączone za pomocą połączenia międzysieciowego HPC.

Podczas trenowania gradienty są wymieniane między rdzeniami TPU za pomocą algorytmu all-reduce ( dobre wyjaśnienie algorytmu all-reduce znajdziesz tutaj). Trenowany model może wykorzystywać sprzęt, trenując na dużych rozmiarach wsadu.

d97b9cc5d40fdb1d.gif

Ilustracja: synchronizacja gradientów podczas trenowania z użyciem algorytmu all-reduce w dwuwymiarowej sieci HPC o topologii toroidu na jednostkach TPU Google.

Oprogramowanie

Trenowanie z dużą wielkością wsadu

Idealna wielkość wsadu w przypadku TPU to 128 elementów danych na rdzeń TPU, ale sprzęt może już wykazywać dobre wykorzystanie od 8 elementów danych na rdzeń TPU. Pamiętaj, że jedna Cloud TPU ma 8 rdzeni.

W tym module użyjemy interfejsu Keras API. W Keras określona przez Ciebie wielkość wsadu jest globalną wielkością wsadu dla całego TPU. Partie zostaną automatycznie podzielone na 8 części i uruchomione na 8 rdzeniach TPU.

da534407825f01e3.png

Dodatkowe wskazówki dotyczące wydajności znajdziesz w przewodniku po wydajności TPU. W przypadku bardzo dużych rozmiarów partii w niektórych modelach może być wymagana szczególna ostrożność. Więcej informacji znajdziesz w artykule LARSOptimizer.

Dla zaawansowanych: XLA

Programy TensorFlow definiują wykresy obliczeniowe. TPU nie uruchamia bezpośrednio kodu Pythona, ale wykonuje wykres obliczeniowy zdefiniowany przez program TensorFlow. W tle kompilator XLA (kompilator przyspieszonej algebry liniowej) przekształca wykres obliczeniowy TensorFlow w kod maszynowy TPU. Ten kompilator wykonuje też wiele zaawansowanych optymalizacji kodu i układu pamięci. Kompilacja odbywa się automatycznie w miarę przesyłania zadań do TPU. Nie musisz wyraźnie uwzględniać XLA w łańcuchu kompilacji.

edce61112cd57972.png

Ilustracja: aby uruchomić program na TPU, graf obliczeniowy zdefiniowany przez program TensorFlow jest najpierw tłumaczony na reprezentację XLA (kompilator przyspieszonej algebry liniowej), a następnie kompilowany przez XLA do kodu maszynowego TPU.

Korzystanie z TPU w Keras

TPU są obsługiwane przez interfejs Keras API od wersji TensorFlow 2.1. Obsługa Keras działa na TPU i podach TPU. Oto przykład, który działa na TPU, GPU i CPU:

try: # detect TPUs
    tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect()
    strategy = tf.distribute.TPUStrategy(tpu)
except ValueError: # detect GPUs
    strategy = tf.distribute.MirroredStrategy() # for CPU/GPU or multi-GPU machines

# use TPUStrategy scope to define model
with strategy.scope():
  model = tf.keras.Sequential( ... )
  model.compile( ... )

# train model normally on a tf.data.Dataset
model.fit(training_dataset, epochs=EPOCHS, steps_per_epoch=...)

W tym fragmencie kodu:

  • TPUClusterResolver().connect() znajduje TPU w sieci. Działa bez parametrów w większości systemów Google Cloud (zadania AI Platform, Colaboratory, Kubeflow, maszyny wirtualne do deep learningu utworzone za pomocą narzędzia „ctpu up”). Te systemy wiedzą, gdzie znajduje się ich TPU, dzięki zmiennej środowiskowej TPU_NAME. Jeśli utworzysz TPU ręcznie, ustaw zmienną środowiskową TPU_NAME na maszynie wirtualnej, z której korzystasz, lub wywołaj polecenie TPUClusterResolver z jawnymi parametrami: TPUClusterResolver(tp_uname, zone, project)
  • TPUStrategy to część, która implementuje algorytm dystrybucji i synchronizacji gradientów „all-reduce”.
  • Strategia jest stosowana w ramach zakresu. Model musi być zdefiniowany w zakresie funkcji strategy().
  • Funkcja tpu_model.fit oczekuje obiektu tf.data.Dataset jako danych wejściowych do trenowania na TPU.

Typowe zadania związane z przenoszeniem kodu na TPU

  • Dane do modelu TensorFlow można wczytywać na wiele sposobów, ale w przypadku TPU wymagane jest użycie interfejsu tf.data.Dataset.
  • Procesory TPU są bardzo szybkie, więc podczas ich używania wąskim gardłem często staje się wczytywanie danych. W przewodniku po wydajności TPU znajdziesz narzędzia, które pomogą Ci wykryć wąskie gardła danych, oraz inne wskazówki dotyczące wydajności.
  • Liczby int8 lub int16 są traktowane jako int32. TPU nie ma sprzętu do liczb całkowitych działającego na mniej niż 32 bitach.
  • Niektóre operacje TensorFlow nie są obsługiwane. Lista jest dostępna tutaj. Dobra wiadomość jest taka, że to ograniczenie dotyczy tylko kodu trenującego, czyli przejścia w przód i w tył przez model. W potoku wprowadzania danych nadal możesz używać wszystkich operacji TensorFlow, ponieważ będą one wykonywane na procesorze.
  • tf.py_func nie jest obsługiwany na TPU.

4. [INFO] Klasyfikator sieci neuronowej – podstawy

W skrócie

Jeśli znasz już wszystkie pogrubione terminy w następnym akapicie, możesz przejść do kolejnego ćwiczenia. Jeśli dopiero zaczynasz przygodę z uczeniem głębokim, witamy. Czytaj dalej.

W przypadku modeli zbudowanych jako sekwencja warstw Keras oferuje interfejs Sequential API. Na przykład klasyfikator obrazów korzystający z 3 warstw gęstych można zapisać w Kerasie w ten sposób:

model = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=[192, 192, 3]),
    tf.keras.layers.Dense(500, activation="relu"),
    tf.keras.layers.Dense(50, activation="relu"),
    tf.keras.layers.Dense(5, activation='softmax') # classifying into 5 classes
])

# this configures the training of the model. Keras calls it "compiling" the model.
model.compile(
  optimizer='adam',
  loss= 'categorical_crossentropy',
  metrics=['accuracy']) # % of correct answers

# train the model
model.fit(dataset, ... )

688858c21e3beff2.png

Gęsta sieć neuronowa

Jest to najprostsza sieć neuronowa do klasyfikowania obrazów. Składa się z „neuronów” ułożonych w warstwach. Pierwsza warstwa przetwarza dane wejściowe i przekazuje wyniki do innych warstw. Jest ona nazywana „gęstą”, ponieważ każdy neuron jest połączony ze wszystkimi neuronami w poprzedniej warstwie.

c21bae6dade487bc.png

Obraz możesz przekazać do takiej sieci, spłaszczając wartości RGB wszystkich pikseli do długiego wektora i używając go jako danych wejściowych. Nie jest to najlepsza technika rozpoznawania obrazów, ale w przyszłości ją ulepszymy.

Neurony, aktywacje, RELU

„Neuron” oblicza ważoną sumę wszystkich danych wejściowych, dodaje wartość zwaną „obciążeniem” i przekazuje wynik przez tzw. „funkcję aktywacji”. Wagi i wartości progowe są początkowo nieznane. Są one inicjowane losowo i „uczone” przez trenowanie sieci neuronowej na wielu znanych danych.

644f4213a4ee70e5.png

Najpopularniejsza funkcja aktywacji to RELU (Rectified Linear Unit). Jest to bardzo prosta funkcja, co widać na wykresie powyżej.

Funkcja aktywacji softmax

Powyższa sieć kończy się warstwą 5 neuronów, ponieważ klasyfikujemy kwiaty w 5 kategoriach (róża, tulipan, mniszek lekarski, stokrotka, słonecznik). Neurony w warstwach pośrednich są aktywowane za pomocą klasycznej funkcji aktywacji RELU. W ostatniej warstwie chcemy jednak obliczyć liczby z zakresu od 0 do 1, które będą reprezentować prawdopodobieństwo, że dany kwiat jest różą, tulipanem itp. W tym celu użyjemy funkcji aktywacji o nazwie „softmax”.

Zastosowanie funkcji softmax do wektora polega na obliczeniu wartości wykładniczej każdego elementu, a następnie znormalizowaniu wektora, zwykle za pomocą normy L1 (sumy wartości bezwzględnych), tak aby wartości sumowały się do 1 i można je było interpretować jako prawdopodobieństwa.

ef0d98c0952c262d.png d51252f75894479e.gif

Funkcja straty entropii krzyżowej

Gdy nasza sieć neuronowa generuje prognozy na podstawie obrazów wejściowych, musimy zmierzyć, jak dobre są te prognozy, czyli odległość między tym, co mówi nam sieć, a prawidłowymi odpowiedziami, często nazywanymi „etykietami”. Pamiętaj, że mamy prawidłowe etykiety dla wszystkich obrazów w zbiorze danych.

Sprawdzi się dowolna odległość, ale w przypadku problemów z klasyfikacją najskuteczniejsza jest tzw. odległość entropii krzyżowej. Nazwiemy ją funkcją błędu lub „straty”:

7bdf8753d20617fb.png

Metoda gradientu prostego

„Trenowanie” sieci neuronowej polega na używaniu obrazów i etykiet treningowych do dostosowywania wag i odchyleń w celu zminimalizowania funkcji straty entropii krzyżowej. Działa to w następujący sposób:

Entropia krzyżowa jest funkcją wag, odchyleń, pikseli obrazu treningowego i jego znanej klasy.

Jeśli obliczymy pochodne cząstkowe entropii krzyżowej względem wszystkich wag i wszystkich odchyleń, otrzymamy „gradient” obliczony dla danego obrazu, etykiety oraz bieżącej wartości wag i odchyleń. Pamiętaj, że możemy mieć miliony wag i odchyleń, więc obliczanie gradientu wydaje się bardzo pracochłonne. Na szczęście TensorFlow robi to za nas. Własnością matematyczną gradientu jest to, że wskazuje on „w górę”. Chcemy, aby entropia krzyżowa była jak najmniejsza, więc idziemy w przeciwnym kierunku. Wagi i odchylenia aktualizujemy o ułamek gradientu. Następnie powtarzamy ten proces w przypadku kolejnych partii obrazów i etykiet treningowych w pętli trenowania. Mamy nadzieję, że zbiegnie się to w miejscu, w którym entropia krzyżowa jest minimalna, chociaż nic nie gwarantuje, że to minimum jest unikalne.

gradient descent2.png

Mini-batching i dynamika

Możesz obliczyć gradient na podstawie tylko jednego przykładowego obrazu i od razu zaktualizować wagi i odchylenia, ale zrobienie tego na podstawie np. 128 obrazów daje gradient, który lepiej odzwierciedla ograniczenia narzucone przez różne przykładowe obrazy, a tym samym prawdopodobnie szybciej zbiega się do rozwiązania. Rozmiar mini-partii jest parametrem, który można dostosować.

Ta technika, czasami nazywana „stochastycznym spadkiem gradientu”, ma jeszcze jedną, bardziej praktyczną zaletę: praca z partiami oznacza też pracę z większymi macierzami, które zwykle łatwiej jest optymalizować na GPU i TPU.

Proces zbieżności może być jednak nieco chaotyczny, a nawet zatrzymać się, jeśli wektor gradientu będzie składać się z samych zer. Czy to oznacza, że znaleźliśmy minimum? Nie zawsze. Składnik gradientu może wynosić zero w przypadku wartości minimalnej lub maksymalnej. W przypadku wektora gradientu z milionami elementów, jeśli wszystkie są zerami, prawdopodobieństwo, że każde zero odpowiada minimum, a żadne z nich nie odpowiada punktowi maksimum, jest dość małe. W przestrzeni wielowymiarowej punkty siodłowe są dość powszechne i nie chcemy się w nich zatrzymywać.

52e824fe4716c4a0.png

Ilustracja: punkt siodłowy. Gradient wynosi 0, ale nie jest minimum we wszystkich kierunkach. (Atrybucja obrazu: Wikimedia: By Nicoguaro - Own work, CC BY 3.0)

Rozwiązaniem jest dodanie do algorytmu optymalizacji pewnego rozpędu, aby mógł on przechodzić przez punkty siodłowe bez zatrzymywania się.

Słownik

wsadowe lub miniwsadowe: trenowanie jest zawsze przeprowadzane na partiach danych treningowych i etykiet. Ułatwia to algorytmowi zbieżność. Wymiar „batch” jest zwykle pierwszym wymiarem tensorów danych. Na przykład tensor o kształcie [100, 192, 192, 3] zawiera 100 obrazów o wymiarach 192 x 192 piksele z 3 wartościami na piksel (RGB).

funkcja straty entropii krzyżowej: specjalna funkcja straty często używana w klasyfikatorach.

warstwa gęsta: warstwa neuronów, w której każdy neuron jest połączony ze wszystkimi neuronami w poprzedniej warstwie.

cechy: dane wejściowe sieci neuronowej są czasami nazywane „cechami”. Sztuka określania, które części zbioru danych (lub ich kombinacje) należy przekazać do sieci neuronowej, aby uzyskać dobre prognozy, jest nazywana „inżynierią cech”.

etykiety: inna nazwa „klas” lub prawidłowych odpowiedzi w problemie klasyfikacji nadzorowanej.

Tempo uczenia się: ułamek gradientu, o który wagi i odchylenia są aktualizowane w każdej iteracji pętli trenowania.

Logity: wyniki warstwy neuronów przed zastosowaniem funkcji aktywacji są nazywane „logitami”. Nazwa pochodzi od „funkcji logistycznej”, czyli „funkcji sigmoidalnej”, która była najpopularniejszą funkcją aktywacji. „Neuron outputs before logistic function” (Wyniki neuronu przed funkcją logistyczną) skrócono do „logits” (logity).

funkcja straty: funkcja błędu porównująca dane wyjściowe sieci neuronowej z prawidłowymi odpowiedziami;

Neuron: oblicza ważoną sumę danych wejściowych, dodaje do niej wartość progową i przekazuje wynik przez funkcję aktywacji.

Kodowanie 1 z n: klasa 3 z 5 jest kodowana jako wektor 5 elementów, z których wszystkie są zerami z wyjątkiem 3 elementu, który ma wartość 1.

relu: jednostka liniowa z prostownikiem. Popularna funkcja aktywacji neuronów.

sigmoid: kolejna funkcja aktywacji, która była kiedyś popularna i nadal jest przydatna w szczególnych przypadkach.

softmax: specjalna funkcja aktywacji, która działa na wektor, zwiększa różnicę między największym komponentem a wszystkimi pozostałymi, a także normalizuje wektor, aby jego suma wynosiła 1, dzięki czemu można go interpretować jako wektor prawdopodobieństw. Używana jako ostatni krok w klasyfikatorach.

tensor: „tensor” to macierz o dowolnej liczbie wymiarów. Tensor 1-wymiarowy to wektor. Tensor 2-wymiarowy to macierz. Możesz też mieć tensory o 3, 4, 5 wymiarach lub więcej.

5. [NOWE INFORMACJE] Splotowe sieci neuronowe

W skrócie

Jeśli znasz już wszystkie pogrubione terminy w następnym akapicie, możesz przejść do kolejnego ćwiczenia. Jeśli dopiero zaczynasz przygodę z konwolucyjnymi sieciami neuronowymi, czytaj dalej.

convolutional.gif

Ilustracja: filtrowanie obrazu za pomocą 2 kolejnych filtrów, z których każdy ma 48 wag do nauczenia (4 x 4 x 3=48).

Tak wygląda prosta splotowa sieć neuronowa w Kerasie:

model = tf.keras.Sequential([
  # input: images of size 192x192x3 pixels (the three stands for RGB channels)
  tf.keras.layers.Conv2D(kernel_size=3, filters=24, padding='same', activation='relu', input_shape=[192, 192, 3]),
  tf.keras.layers.Conv2D(kernel_size=3, filters=24, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=12, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=6, padding='same', activation='relu'),
  tf.keras.layers.Flatten(),
  # classifying into 5 categories
  tf.keras.layers.Dense(5, activation='softmax')
])

model.compile(
  optimizer='adam',
  loss= 'categorical_crossentropy',
  metrics=['accuracy'])

688858c21e3beff2.png

Wprowadzenie do konwolucyjnych sieci neuronowych

W warstwie sieci konwolucyjnej jeden „neuron” oblicza ważoną sumę pikseli znajdujących się bezpośrednio nad nim, ale tylko w niewielkim obszarze obrazu. Dodaje on odchylenie i przekazuje sumę przez funkcję aktywacji, tak jak neuron w zwykłej warstwie gęstej. Następnie operacja jest powtarzana na całym obrazie z użyciem tych samych wag. Pamiętaj, że w warstwach gęstych każdy neuron miał własne wagi. W tym przypadku pojedynczy „fragment” wag przesuwa się po obrazie w obu kierunkach (jest to „splot”). Dane wyjściowe mają tyle wartości, ile pikseli na obrazie (chociaż na krawędziach konieczne jest pewne wypełnienie). Jest to operacja filtrowania z użyciem filtra o 48 wagach (4 x 4 x 3=48).

Jednak 48 wag nie wystarczy. Aby dodać więcej stopni swobody, powtarzamy tę samą operację z nowym zestawem wag. Spowoduje to wygenerowanie nowego zestawu danych wyjściowych filtra. Nazwijmy go „kanałem” wyników, analogicznie do kanałów R, G, B na obrazie wejściowym.

Screen Shot 2016-07-29 at 16.02.37.png

Dwa (lub więcej) zestawy wag można zsumować jako jeden tensor, dodając nowy wymiar. Daje nam to ogólny kształt tensora wag dla warstwy konwolucyjnej. Liczba kanałów wejściowych i wyjściowych jest parametrem, więc możemy zacząć układać i łączyć warstwy konwolucyjne.

d1b557707bcd1cb9.png

Ilustracja: konwolucyjna sieć neuronowa przekształca „kostki” danych w inne „kostki” danych.

Konwolucje z krokiem, maksymalne próbkowanie

Wykonując konwolucje z krokiem 2 lub 3, możemy też zmniejszyć wynikowy sześcian danych w wymiarach poziomych. Można to zrobić na 2 sposoby:

  • Konwolucja z krokiem: przesuwany filtr jak powyżej, ale z krokiem > 1.
  • Maksymalne uśrednianie: okno przesuwne stosujące operację MAX (zwykle na fragmentach 2x2, powtarzane co 2 piksele).

2b2d4263bb8470b.gif

Ilustracja: przesunięcie okna obliczeniowego o 3 piksele powoduje zmniejszenie liczby wartości wyjściowych. Sploty z krokiem lub maksymalne próbkowanie (maksymalna wartość w oknie 2x2 przesuwającym się o krok 2) to sposób na zmniejszenie kostki danych w wymiarach poziomych.

Klasyfikator konwolucyjny

Na koniec dołączamy głowicę klasyfikacji, spłaszczając ostatnią kostkę danych i przekazując ją przez gęstą warstwę aktywowaną funkcją softmax. Typowy klasyfikator konwolucyjny może wyglądać tak:

4a61aaffb6cba3d1.png

Ilustracja: klasyfikator obrazów korzystający z warstw konwolucyjnych i softmax. Wykorzystuje filtry 3x3 i 1x1. Warstwy maxpool wybierają maksymalną wartość z grup punktów danych o rozmiarze 2x2. Głowica klasyfikacji jest zaimplementowana za pomocą warstwy gęstej z funkcją aktywacji softmax.

W Keras

Przedstawiony powyżej stos konwolucyjny można zapisać w Kerasie w ten sposób:

model = tf.keras.Sequential([
  # input: images of size 192x192x3 pixels (the three stands for RGB channels)    
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu', input_shape=[192, 192, 3]),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=16, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=8, padding='same', activation='relu'),
  tf.keras.layers.Flatten(),
  # classifying into 5 categories
  tf.keras.layers.Dense(5, activation='softmax')
])

model.compile(
  optimizer='adam',
  loss= 'categorical_crossentropy',
  metrics=['accuracy'])

6. Twoja niestandardowa sieć konwolucyjna

Praktyczne

Zbudujmy i wytrenujmy od podstaw konwolucyjną sieć neuronową. Korzystanie z TPU pozwoli nam bardzo szybko wprowadzać zmiany. Otwórz ten notatnik, uruchom komórki (Shift-ENTER) i postępuj zgodnie z instrukcjami, gdy zobaczysz etykietę „WORK REQUIRED”.

c3df49e90e5a654f.png Keras_Flowers_TPU (playground).ipynb

Celem jest przekroczenie 75% dokładności modelu uczenia przez przenoszenie. Ten model miał przewagę, ponieważ został wstępnie wytrenowany na zbiorze danych zawierającym miliony obrazów, a my mamy tylko 3670 obrazów. Czy możesz przynajmniej dopasować cenę?

Informacje dodatkowe

Ile warstw, jak duże?

Wybieranie rozmiarów warstw to bardziej sztuka niż nauka. Musisz znaleźć odpowiednią równowagę między zbyt małą a zbyt dużą liczbą parametrów (wag i odchyleń). Przy zbyt małej liczbie wag sieć neuronowa nie jest w stanie odzwierciedlić złożoności kształtów kwiatów. Zbyt duża liczba obrazów może prowadzić do „nadmiernego dopasowania”, czyli specjalizacji w zakresie obrazów treningowych i niemożności uogólnienia. Przy dużej liczbie parametrów trenowanie modelu będzie też powolne. W Keras funkcja model.summary() wyświetla strukturę i liczbę parametrów modelu:

Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 192, 192, 16)      448       
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 192, 192, 30)      4350      
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 96, 96, 30)        0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 96, 96, 60)        16260     
_________________________________________________________________
 ... 
_________________________________________________________________
global_average_pooling2d (Gl (None, 130)               0         
_________________________________________________________________
dense (Dense)                (None, 90)                11790     
_________________________________________________________________
dense_1 (Dense)              (None, 5)                 455       
=================================================================
Total params: 300,033
Trainable params: 300,033
Non-trainable params: 0
_________________________________________________________________

Kilka wskazówek:

  • Wiele warstw sprawia, że „głębokie” sieci neuronowe są skuteczne. W przypadku tego prostego problemu z rozpoznawaniem kwiatów sensowne jest użycie od 5 do 10 warstw.
  • Używaj małych filtrów. Zazwyczaj filtry 3x3 sprawdzają się w każdej sytuacji.
  • Można też używać filtrów 1x1, które są tanie. Nie „filtrują” one niczego, tylko obliczają kombinacje liniowe kanałów. Zastąp je prawdziwymi filtrami. (Więcej informacji o „konwolucjach 1x1” znajdziesz w następnej sekcji).
  • W przypadku problemu klasyfikacji, takiego jak ten, często stosuj próbkowanie w dół za pomocą warstw max-pooling (lub konwolucji z krokiem >1). Nie interesuje Cię, gdzie znajduje się kwiat, tylko to, czy jest to róża czy mniszek lekarski, więc utrata informacji o współrzędnych x i y nie jest istotna, a filtrowanie mniejszych obszarów jest tańsze.
  • Liczba filtrów zwykle staje się podobna do liczby klas na końcu sieci (dlaczego? patrz trik „globalne uśrednianie puli” poniżej). Jeśli klasyfikujesz dane do setek klas, stopniowo zwiększaj liczbę filtrów w kolejnych warstwach. W przypadku zbioru danych o kwiatach z 5 klasami filtrowanie za pomocą tylko 5 filtrów nie wystarczy. W większości warstw możesz używać tej samej liczby filtrów, np. 32, i zmniejszać ją pod koniec.
  • Ostatnia warstwa gęsta jest kosztowna. Może mieć więcej wag niż wszystkie warstwy splotowe razem wzięte. Na przykład nawet przy bardzo rozsądnym wyniku z ostatniej kostki danych, czyli 24 x 24 x 10 punktów danych, gęsta warstwa ze 100 neuronami będzie kosztować 24 x 24 x 10 x 100=576 000 wag!!! Zastanów się dobrze lub wypróbuj globalne uśrednianie puli (patrz poniżej).

Globalne uśrednianie

Zamiast używać kosztownej warstwy gęstej na końcu konwolucyjnej sieci neuronowej, możesz podzielić przychodzący „sześcian” danych na tyle części, ile masz klas, uśrednić ich wartości i przekazać je przez funkcję aktywacji softmax. Ten sposób tworzenia głowicy klasyfikacji nie wymaga żadnych wag. W Keras składnia to tf.keras.layers.GlobalAveragePooling2D().

93240029f59df7c2.png

Rozwiązanie

Oto notatnik z rozwiązaniem. Możesz z niej skorzystać, jeśli utkniesz w martwym punkcie.

c3df49e90e5a654f.png Keras_Flowers_TPU (solution).ipynb

Omówione zagadnienia

  • 🤔 Eksperymentowanie z warstwami konwolucyjnymi
  • 🤓 Eksperymentowanie z maksymalnym pulowaniem, krokami, globalnym pulowaniem średnich itp.
  • 😀 szybko iterował nad rzeczywistym modelem na TPU,

Poświęć chwilę na przejrzenie tej listy kontrolnej.

7. Gratulacje!

Udało Ci się zbudować pierwszą nowoczesną konwolucyjną sieć neuronową i wytrenować ją do uzyskania dokładności powyżej 80%. Dzięki TPU możesz wprowadzać iteracyjne zmiany w jej architekturze w ciągu zaledwie kilku minut. Aby dowiedzieć się więcej o nowoczesnych architekturach konwolucyjnych, przejdź do następnego modułu:

TPU w praktyce

TPU i GPU są dostępne na Cloud AI Platform:

Na koniec dodamy, że chętnie poznamy Twoją opinię. Jeśli zauważysz w tym module coś nieprawidłowego lub uważasz, że można go ulepszyć, daj nam znać. Opinie można przesyłać za pomocą zgłoszeń w GitHub [link do opinii].

HR.png

Martin Görner ID small.jpg
Autor: Martin Görner
Twitter: @martin_gorner

tensorflow logo.jpg
www.tensorflow.org