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.
- Potoki danych o szybkości TPU: tf.data.Dataset i TFRecords
- Pierwszy model Keras z uczeniem przez przenoszenie
- [TO ĆWICZENIE] Splotowe sieci neuronowe z użyciem Keras i TPU
- Nowoczesne sieci konwolucyjne, squeezenet, Xception z Keras i TPU

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.

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

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

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

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

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

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

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).

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.

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.

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.

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.

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:

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.

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.

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.

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.

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 polecenieTPUClusterResolverz jawnymi parametrami:TPUClusterResolver(tp_uname, zone, project)TPUStrategyto 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.fitoczekuje 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_funcnie 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, ... )

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.

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.

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.

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”:

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.

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ć.

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.

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'])

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.

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.

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).

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:

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”.
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().

Rozwiązanie
Oto notatnik z rozwiązaniem. Możesz z niej skorzystać, jeśli utkniesz w martwym punkcie.
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:
- Potoki danych o szybkości TPU: tf.data.Dataset i TFRecords
- Pierwszy model Keras z uczeniem przez przenoszenie
- [TO ĆWICZENIE] Splotowe sieci neuronowe z użyciem Keras i TPU
- Nowoczesne sieci konwolucyjne, squeezenet, Xception z Keras i TPU
TPU w praktyce
TPU i GPU są dostępne na Cloud AI Platform:
- Na maszynach wirtualnych do deep learningu
- W Notatnikach w AI Platform
- W zadaniach trenowania w 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].

|

