Professional Documents
Culture Documents
Rozdz9 Deep
Rozdz9 Deep
Sieci głębokie
9.1 Wprowadzenie
W ostatnich latach ogromny postęp w sztucznej inteligencji dokonał się za pośrednictwem tak
zwanego głębokiego uczenia. Głębokie uczenie dotyczy głównie wielowarstwowych sieci
neuronowych, które pełnią jednocześnie funkcję generatora cech diagnostycznych dla
analizowanego procesu oraz tworzą ostateczny wynik klasyfikacji bądź regresji [22,44,69].
Uzyskuje się w ten sposób doskonałe narzędzie zastępujące człowieka przede wszystkim w
trudnym problemie opisu procesu za pomocą specjalizowanych deskryptorów, których stworzenie
wymaga dużych zdolności eksperckich. Okazuje się przy tym, że takie podejście do bez-
interwencyjnej metody generacji cech jest o wiele skuteczniejsze od stosowanych tradycyjnie
metod generacji deskryptorów, pozwalając przy tym na poprawę dokładności działania systemu. Z
tego powodu technologia sieci głębokich stała się ostatnio bardzo szybko jednym z najbardziej
popularnych obszarów w dziedzinie nauk komputerowych.
Za protoplastę tych sieci można uznać zdefiniowany na początku lat dziewięćdziesiątych
wielowarstwowy neocognitron Fukushimy [16]. Prawdziwy rozwój tych sieci zawdzięczamy
jednak profesorowi LeCun [44], który zdefiniował podstawową strukturę i algorytm uczący
specjalizowanej sieci konwolucyjnej (zwanej również splotową). Jest to sieć wielowarstwowa,
której angielska nazwa „Convolutional Neural Network” jest tradycyjnie skracana do CNN.
Aktualnie CNN stanowi podstawową strukturę stosowaną na szeroką skalę w przetwarzaniu
obrazów i sygnałów [22]. W międzyczasie powstało wiele odmian sieci będących modyfikacją
struktury podstawowej CNN (np. U-net, RCNN) jak również sieci różniących się zasadniczo od
CNN, na przykład autoenkoder, jako wielowarstwowe, nieliniowe uogólnienie liniowej sieci PCA
[22,39]. Stosowane są również struktury wielowarstwowe bazujące na maszynie Boltzmanna (ang.
Restricted Boltzmann Machine - RBM) używane w sieciach głębokiej wiarygodności (ang. Deep
Belief Network – DBN) [22,32]. Sieci głębokie znalazły również swoje miejsce w strukturach
rekurencyjnych w postaci sieci rekurencyjnej LSTM (ang. Long Short-Term Memory) [24,25,72],
stanowiąc skuteczne rozwiązanie problemu propagacji wstecznej w czasie w systemie ze
sprzężeniem zwrotnym, stosowane dziś powszechnie w predykcji szeregów czasowych.
Cechą wspólną tych rozwiązań, zwłaszcza w przypadku CNN, jest wielowarstwowość
ułożenia neuronów i ogromna (idąca w miliony) ilość połączeń wagowych między neuronami. Dla
uniknięcia problemu lawinowego narastania liczby adaptowanych wag stosuje się połączenia typu
136
lokalnego. W takich rozwiązaniach neuron jest zasilany nie przez wszystkie sygnały (na przykład
piksele obrazów) warstwy poprzedzającej, jak to jest zorganizowane w sieciach klasycznych, ale
przez wybraną małą grupę neuronów (pikseli) tej warstwy, tworzących maskę filtrującą. Analiza
całego obrazu następuje poprzez przesuwanie tej maski z ustalonym krokiem (ang. stride) wzdłuż
i wszerz obrazu. Charakterystyczną cechą jest przy tym używanie identycznych wartości wag
przesuwającej się maski filtracyjnej.
Każdy rodzaj sieci głębokich związany jest z problemem adaptacji ogromnej liczby
parametrów sieci w akceptowalnym czasie. Skuteczna implementacja i rozwój koncepcji LeCuna
stały się możliwe dzięki olbrzymiemu postępowi w rozwoju technologii informatycznych,
pozwalającemu na ogromne przyśpieszenie obliczeń. Połączenie tych najnowszych technologii z
proponowanymi rozwiązaniami sieci głębokich stworzyło podstawy zastosowań sztucznej
inteligencji w życiu codziennym.
Realne stało się zaprojektowanie pojazdów samosterujących, których podstawą jest
rozpoznawanie obrazów i obiektów prezentowanych na tych obrazach w czasie rzeczywistym,
sterowanie robotami, skuteczne rozpoznawanie głosu, automatyczna generacja tekstu na podstawie
wypowiedzi głosowej, segmentacja złożonych obrazów, zwłaszcza biomedycznych,
przewidywanie kolejnych wartości szeregów czasowych, itp. [22,24,33,80]. Ważną sferą
zastosowań jest wspomaganie diagnostyki medycznej dzięki skutecznym algorytmom
przetwarzania obrazów medycznych, na przykład mikroskopowych, histologicznych itp. W pracy
tej najwięcej uwagi poświęcimy najczęściej używanej sieci CNN.
137
generują pewne uogólnienia cech z warstwy poprzedzającej organizowane w formie obrazów.
Przykład wyników takiego przetworzenia obrazu kolorowego w warstwie ukrytej sieci
zawierającej 48 neuronów (każdy wielowejściowy o różnych wartościach wag) pokazano na rys.
9.1. Kolejne kwadraty obrazu wynikowego przedstawiają cechy diagnostyczne (w formie
podobrazu) utworzone przez każdy z tych neuronów.
Rys. 9.1 Przykład wyników przetwarzania obrazu kolorowego w cechy diagnostyczne w pierwszej
warstwie ukrytej o 48 neuronach przez sieć CNN [49].
Obrazy te w niczym nie przypominają oryginałów, ale reprezentują cechy charakterystyczne dla
nich wyrażone w formie intensywności pikseli. W efekcie kolejnego wielowarstwowego
przetwarzania obrazów z poprzedniej warstwy ostatnia warstwa konwolucyjna generuje obrazy
stosunkowo niewielkich wymiarów (ale dużej liczebności) reprezentujące cechy charakterystyczne
dla przetwarzanego zbioru. Obrazy te w poszczególnych warstwach są reprezentowane przez
tensory (struktury 3-wymiarowe, w których szerokość i wysokość odpowiadają wymiarom obrazu
a głębokość jest równa liczbie obrazów). Elementy tensora ostatniej warstwy lokalnie połączonej
są następnie przetwarzane na postać wektorową (operacja wypłaszczania), będącą początkiem
układu w pełni połączonego (ang. fully connected – FC), stanowiącego właściwy klasyfikator bądź
układ regresyjny. Przykład takiej struktury CNN przedstawiono na rys. 9.2 [49].
138
Rys. 9.2 Przykład struktury CNN zawierającej 3 warstwy konwolucyjne o połączeniu lokalnym i
w pełni połączoną strukturę końcową stanowiącą właściwy klasyfikator.
Kolejne warstwy sieci mają zadanie wygenerować w sposób automatyczny (całkowicie bez
udziału człowieka) zbiór cech charakterystycznych dla analizowanych wzorców obrazowych,
który następnie podlegają klasycznemu przetworzeniu (w podsystemie w pełni połączonym) w
decyzję klasyfikacyjną bądź regresyjną.
W sieciach CNN wejściem dla pierwszej warstwy ukrytej jest zwykle reprezentacja RGB obrazów
ustawionych w formie tensora. Operacja konwolucji w pierwszej warstwic konwolucyjnej
obejmuje wszystkie trzy kanały RGB obrazu, każdy z innymi przyjętymi wartościami wag jądra w
postaci filtru liniowego stanowiącego neuron analizujący. Suma wyników poszczególnych
kanałów stanowi wynik konwolucji tworzącej obraz wyjściowy. W dalszych warstwach operacja
ta obejmuje wiele (ustalonych przez użytkownika) obrazów z warstwy poprzedzającej, stanowiąc
ich sumę. Tego typu rozwiązanie konwolucyjne nosi również nazwę konwolucji grupowej.
Przykład operacji konwolucyjnej dla kroku przesunięcia filtrów (stride) równego 1
przedstawiono na rys. 9.3. Dane wejściowe stanowią 3 obrazy obr1, obr2 i obr3. Zastosowano 2
zespoły filtrów dwuwymiarowych: filtr11, flitr12, filtr13 dla wytworzenia pierwszego obrazu
wynikowego OBR1 oraz filtr21, filtr22 i filtr23 dla drugiego obrazu wynikowego OBR2. Cyfra
139
pierwsza w oznaczeniu filtru określa który obraz wynikowy będzie tworzony. Cyfra druga
wskazuje który obraz wejściowy jest przetwarzany. Na przykład oznaczenie filtr21 wskazuje, że
tworzony jest drugi obraz wyjściowy, a przetwarzany pierwszy obraz wejściowy. Oba obrazy
OBR1 i OBR2 są tworzone jako suma trzech odpowiednich wyników. Na przykład obraz OBR1
jest sumą: wyn11+wyn12 +wyn13, podobnie OBR2 jest sumą: wyn21+wyn22+wyn23. Dwa
obrazy wyjściowe OBR1wy i OBR2wy powstają w wyniku operacji ReLU
1 0 2
1 0 −1 1
obr1 = 3 1 2 filtr11= wyn11 = OBR1
1 1 0 −1 1 3 0
2 0 4 1
filtr 21 = wyn 21 = OBR2
1 −1 6 3
−15 −4 0 0
OBR1= ReLU → OBR1wy =
−17 −7 0 0
0 1 3
0 −2 1 −8
obr 2 = 1 4 2 filtr12 = wyn12 = OBR1
6 1 5 −1 1 −13 0
1 1 −3 2
filtr 22 = wyn22 = OBR2
0 −1 4 1
12 6 12 6
OBR2= ReLU → OBR2wy=
15 −1 15 0
5 1 2
−1 2 −15 3
obr 3 = 4 0 1 filtr13 = wyn13 = OBR1
1 3 6 −3 0 −7 −7
2 1 11 3
filtr 23 = wyn 23 = OBR2
0 −1 5 −5
Rys. 9.3 Przykład konwolucji obrazu 3x3 reprezentowanego przez obr1, obr2 i obr3. Zastosowano
2 zespoły filtrów dwuwymiarowych: filtr11, flitr12, filtr13 dla wytworzenia pierwszego obrazu
wynikowego OBR1 oraz filtr 21, filtr22 i filtr23 dla drugiego obrazu wynikowego OBR2. Dwa
obrazy wyjściowe OBR1wy i OBR2wy powstają w wyniku operacji ReLU
y( x) = ln(1 + e x ) (9.3a)
Jej pochodna jest ciągła i reprezentuje sigmoidę unipolarną. W wyniku konwolucji i działania
funkcji ReLU uzyskuje się wartości reprezentujące stopień szarości pikseli obrazu wynikowego.
W niektórych implementacjach sieci głębokich, na przykład w GAN stosuje się
zmodyfikowaną funkcję aktywacji LReLU (ang. Leaky ReLU), w której w części ujemnej
charakterystyki wartości zerowe zastępuje się linią prostą o małym nachyleniu a. Funkcję taką
opisuje się wzorem
x dla x 0
y ( x) = (9.3b)
ax dla x 0
141
przy wartości a<1; typowa wartość to a=0.01.
Stosowana jest również wersja wykładnicza funkcji ReLU, zwana w skrócie ELU (ang.
Exponential Linear Unit), która definiowana jest wzorem
x dla x 0
y ( x) = x
a ( e − 1) dla x 0
(9.3c)
142
O=(W−F+2P)/S+1 (9.4)
określającą wymiar obrazu wyjściowego. Przykładowo, jeśli obraz wejściowy ma wymiar 7x7
(W=7), zastosowany filtr 3x3 (F=3), stride S=1 oraz P=0 wówczas otrzymuje się obraz wyjściowy
o wymiarze 5x5, gdyż O=(7-3)/1+1=5. Podobnie dla S=2 otrzymuje się wymiar obrazu
wyjściowego równy 3x3.
W następnym kroku powstały obraz wynikowy poddaje się działaniu operacji redukcji
wymiarów obrazu polegającemu na statystycznym łączeniu wartości stopnia szarości sąsiednich
pikseli, tzw. operacja „pooling”. Funkcja ta przekształca wynik nieliniowego działania
filtracyjnego neuronu w określonym rejonie obrazu poprzez zdefiniowaną statystykę dotyczącą
sąsiadujących (pod względem lokalizacji) wyników wyjściowych. Typowe funkcje to: max
pooling zwracająca wartość maksymalną wyników neuronów znajdujących się w sąsiedztwie
prostokątnym aktualnego wyniku oraz average pooling zwracającą wartość średnią wyników w
tym obszarze. Przykład takiej operacji uwzględniającej obszar maski 2x2 przedstawiony jest na
rys. 9.4.
Rys. 9.4 Przykład wyników działania operacji average pooling i max pooling z maską 2x2 i
krokiem stride =2 na obrazie o wymiarach 4x4.
Wymiary obrazu po operacji pooling ulegają redukcji zgodnie ze wzorem (9.4). Operacja pooling
poza zmniejszeniem wymiaru obrazu pozwala uzyskać reprezentację bardziej inwariantną
względem niewielkiego przemieszczenia danych. Stanowi pewne uogólnienie cech
reprezentowanych przez sąsiednie grupy pikseli. Często dla zachowania odpowiednich wymiarów
obrazu stosuje się operację uzupełnienia brzegów zerami tzw. „zero padding”. Zwykle jest to
uzupełnienie symetryczne zarówno wierszy jak i kolumn obrazu.
143
Dodatkowo stosuje się również normalizację stopnia szarości obrazów powstałych w
wyniku konwolucji. Najczęściej jest to to operacja stosowana na danych „mini-batch” (małego
zestawu danych wybranego losowo z pełnego zbioru używanego w operacji konwolucji).
Wykonywana jest na wynikach bezpośrednich konwolucji liniowej (przed operacją ReLU).
Odbywa się poprzez odjęcie od rzeczywistych wartości stopnia jasności obrazu wartości średniej i
podzieleniu takich wyników przez odchylenie standardowe danych zawartych w „mini-batch”.
Krok stride przyjęty zarówno w konwolucji jak i operacji pooling wpływa istotnie na
wynik. Przykład graficzny wpływu wielkości kroku stride na wynik konwolucji w przypadku
danych wejściowych jednowymiarowych o 7 elementach (W=7) przedstawiono na rys. 9.9. W obu
przypadkach neuron filtrujący ma trzy połączenia wagowe (F=3) o wartościach wag równych
kolejno: 1, 0, -1 oraz brak uzupełnienia zerami (P=0). Wynik przedstawiony jest dla 2 różnych
wartości parametru stride W pierwszym przypadku jest to wartość stride=1, w drugim stride=2. W
zależności od wyboru otrzymuje się różną liczbę elementów wynikowych: w pierwszym
przypadku jest to 5 wyników, w drugim tylko trzy.
Rys. 9.5 Przykład wpływu wyboru wartości kroku stride (S) na wynik przetworzenia: rysunek
górny: S=1, b) rysunek dolny: S=2. Przyjęto filtr o wymiarach F=3 i wartościach wag równych
kolejno: 1, 0, -1 oraz brak uzupełnienia zerami (P=0). W wyniku konwolucji nastąpiła redukcja
wymiaru danych wejściowych: przy S=1 redukcja z 7 do 5, przy S=2 redukcja z 7 do 3.
144
Zdefiniowane wartości parametrów mają ważne znaczenie przy projektowaniu struktur CNN, gdyż
niewłaściwie przyjęte liczby mogą prowadzić do niecałkowitych wartości rozmiarów obrazów
wejściowych. Przykładowo w architekturze ALEXNET Krizhevskiego [41] wymiar wejściowy
obrazów jest równy 227x227x3 (reprezentacja RGB). Zastosowane przez niego wymiary w
pierwszej warstwie ukrytej to F=11, S=4, P=0. Stąd wymiar obrazu wyjściowego po konwolucji
jest równy O=(227-11)/4+1=55, czyli obraz 55x55. Gdyby wymiar obrazu wejściowego był równy
na przykład 224x224 wówczas wymiar obrazu wyjściowego przy S=4 po konwolucji nie byłby
liczbą całkowitą, gdyż wówczas O=(224-11)/4+1=54.25, co blokuje dalszy proces przetwarzania.
W poszczególnych warstwach ukrytych obrazy wynikowe tworzą tensory, strukturę
trójwymiarową reprezentowaną przez dwa wymiary obrazu i głębokość definiowaną przez liczbę
przetwarzanych obrazów. Obrazy tworzące tensor ostatniej warstwy konwolucyjnej są
przetwarzane na postać wektorową, stanowiącą początek sieci w pełni połączonej w której każdy
neuron jest połączony z każdym sygnałem warstwy poprzedniej – połączenia globalne (ang. Fully
Connected layer – FC). Neurony w warstwie o pełnym połączeniu mają unikane (niepowtarzalne)
wagi, podlegające adaptacji w procesie uczenia.
Przejście z reprezentacji tensorowej (wiele obrazów 2-wymiarowych) na postać wektorową
(pojedyncze sygnały wektora tworzące wejście dla właściwego klasyfikatora) może odbywać się
na wiele sposobów. Jednym z nich jest przyjęcie wszystkich wartości pikselowych poszczególnych
obrazów jako cech diagnostycznych i ustawienie ich w formie wektora poprzez operację tzw.
reshape. Przy zbyt dużych wymiarach obrazów stosowane może być zmniejszenie rozdzielczości
obrazów tworzących tensor. Innym rozwiązaniem jest zastosowanie operacji pooling z
odpowiednim krokiem stride. W niektórych przypadkach można zaprojektować sieć w taki sposób,
że ostatnia warstwa konwolucyjna zawiera tylko pojedynczą wartość dla każdego kanału.
W większości rozwiązań sieci CNN zamiast klasycznej wielowarstwowej sieci neuronowej
stosuje się klasyfikator typu softmax, w którym sygnały wejściowe są bezpośrednio przetwarzane
na prawdopodobieństwo przynależności do określonej klasy [22]. Liczba neuronów wyjściowych
jest równa liczbie klas, przy czym każdy neuron podlega adaptacji wag w klasyczny sposób
poprzez optymalizację funkcji celu. Wartość sygnału sumacyjnego neuronu i-tego określona jest
wówczas wzorem
145
ui (x) = wij x j + w0 (9.5)
j
146
exp(ui )
f (ui ) == M
(9.7)
exp(u )
j =1
j
Zmienna ui w tym wzorze jest sumą wagową sygnałów dopływających do i-tego neuronu
wyjściowego. W zdaniach klasyfikacji wieloklasowej (M klas) tylko jedna klasa jest prawdziwa
(etykieta tej klasy d=1). Pozostałe klasy mają etykietę d=0. Zatem w procesie uczenia tylko klasa
wskazana przez sieć jako prawdziwa bierze udział w obliczaniu funkcji błędu (kosztu) przyjmując
d=1. Pozostałe wyjścia mające etykiety d=0 nie biorą bezpośredniego udziału w procesie
propagacji wstecznej. Entropijna (logarytmiczna) definicja funkcji celu dla jednego rekordu
danych jest zapisana w postaci
M
E = − di ln ( f (ui ) ) (9.8)
i =1
Wobec tylko jednej wartości prawdziwej klasy di=dp (różnej od zera) funkcja ta może być
uproszczona do postaci
exp ( u )
E = − ln ( f (u )i ) = − ln M
p
(9.9)
exp ( u j )
j =1
Składniki funkcji celu względem klas “negatywnych” są równe zeru. Tylko klasa wskazana przez
sieć bierze bezpośredni udział w tworzeniu funkcji celu. Tym nie mniej gradient funkcji celu zależy
również od składników klas „negatywnych”, ze względu na postać mianownika w wyrażeniu (9.9).
Należy przy tym zauważyć, że składniki gradientu funkcji celu względem sygnału sumacyjnego un
dla klas „negatywnych” będą miały identyczną postać, wyrażoną wzorem
exp ( u )
= M ( n )
exp u
− ln M
p
(9.10a)
un
exp ( u j ) exp ( u j )
j =1 j =1
natomiast dla klasy wskazanej przez sieć wyrażenie (sygnał sumacyjny up) to będzie miało postać
147
exp ( u ) exp ( u p )
= M
− ln M −1
p
(9.10b)
u p
exp ( u j ) exp ( u j )
j =1 j =1
Znając wektor gradientu względem poszczególnych sygnałów sumacyjnych składniki gradientu
poszczególnych wag w występujących w wyrażeniu (9.10) są natychmiast określane korzystając z
własności różniczkowania funkcji złożonej, mianowicie
E E u E
= = xi (9.11)
wi u wi u
Najczęściej stosowanym algorytmem w uczeniu sieci CNN jest stochastyczny algorytm
największego spadku z momentem rozpędowym (ang. Stochastic Gradient Descent – SGD)
[20,22]. Adaptacja wag odbywa się iteracyjnie zgodnie ze wzorem
w(k ) = w(k − 1) − ηg(k − 1) + w(k − 1) − w(k − 2) (9.12)
w którym jest współczynnikiem momentu przyjmowanym z przedziału [0, 1]. Dla przyśpieszenia
procesu uczenia w poszczególnych iteracjach zamiast pełnego zbioru danych uczących używa się
losowo wybranego podzbioru (tzw. minibatch). Powstało wiele modyfikacji tego algorytmu
przyśpieszających proces uczenia, z których najczęściej używany (między innymi w Matlabie) jest
ADAM (skrót of ang. ADAptive Momenet estimation) [40]. W odróżnieniu od SGD w tej metodzie
każdy parametr w ma adaptacyjnie dobierany parametr uczenia uzależniony od momentu
statystycznego gradientu pierwszego i drugiego rzędu. Momenty te definiowane są w postaci
średniej kroczącej
148
mw (k )
m
ˆw (k ) = (9.15)
1 − 1k
v w (k )
vˆw (k ) = (9.16)
1 − 2k
m
ˆw (k )
w (k ) = w (k − 1) − η + w (k − 1) − w (k − 2) (9.17)
vˆw (k ) +
149
doborze wag następuje zwykle douczenie pełnej sieci przy wykorzystaniu metody
największego spadku i propagacji wstecznej błędu.
Przy obecnym stanie równoległej techniki obliczeniowej i zastosowaniu procesora graficznego
możliwe stało się zastosowanie uczenia z nauczycielem do pełnej (losowo zainicjowanej) sieci w
każdej iteracji uczącej (ekstremalne podejście do uczenia). Tym nie mniej przy zastosowaniu
takiego podejścia należy się liczyć z długotrwałym procesem uczenia, zwłaszcza jeśli wymiary
obrazów wejściowych są duże.
Najczęściej stosowanym podejściem w tworzeniu sieci CNN jest zastosowanie metody zwanej
transfer learning. W tym podejściu korzysta się ze wstępnie nauczonej sieci dostępnej między
innymi w Matlabie i Pythonie, o strukturze i parametrach dobranych przez specjalistów.
Użytkownik dokonuje jedynie adaptacji końcowej struktury sieci (zwykle klasyfikatora
końcowego) na swoich danych. Parametry warstw odpowiedzialnych za mechanizm generacji cech
diagnostycznych pozostają zwykle zamrożone. Uczenie takie odbywa się metodami
gradientowymi z zastosowaniem propagacji wstecznej błędu i przebiega stosunkowo szybko.
W ostatnich implementacjach Matlaba (poczynając od 2016 roku) dostępne są m-pliki do
uczenia i testowania różnych struktur sieci CNN. Sposób wykorzystania tych podprogramów
można uzyskać przy pomocy komendy help cnn. Użytkownik po wczytaniu danych uczących i
testujących definiuje architekturę sieci (liczbę warstw i neuronów warstwie, funkcję aktywacji,
rodzaj funkcji pooling, etc.), opcje wyboru parametrów uczenia, następnie dokonuje procesu
uczenia (funkcja trainNetwork) i następnie testowania (funkcja classify).
Dane uczące i testujące przygotowane są w postaci tablicy 3-D dla obrazów w skali szarości
lub 4-D dla obrazów reprezentowanych w postaci RGB. Pierwsze 2 współrzędne zawierają
wartości pikseli w osi x i y obrazu, trzecia współrzędna (przy reprezentacji 4-D) jest równa 1, 2 lub
3 prezentując obraz R, G lub B a ostatnia nr kolejny obrazów w bazie. Dane dotyczące klasy
reprezentowanej przez obraz są kodowane numerycznie (klasa 1, 2, 3, itd.) w postaci wektorowej.
150
training na dowolnie dobranym zestawie danych uczących. Tak powstały prototypy sieci w trybie
Transfer Learning podlegające jedynie douczeniu na danych użytkownika [22,55], zwykle
poprzez adaptację wag struktury w pełni połączonej (bez zmiany parametrów filtrów warstw
lokalnie połączonych). Dzięki takiemu rozwiązaniu możliwe jest ogromne skrócenie czasu
uczenia, a przy tym znaczące polepszenie zdolności generalizacji sieci.
Takim pierwszym prototypem (dostępnym również w Matlabie poczynając od wersji z roku
2017) jest AlexNet [41], zaprojektowany przez grupę naukowców: A. Krizhevsky, I. Sutskever i G.
Hinton. W implementacji pierwotnej Matlaba struktura sieci AlexNet jest następująca [49].
MATLAB
W przypadku Pyhtona, sieć Alexnet może wyglądać, wykorzystując bibliotekę Keras [1] w
następujący sposób.
Python
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv1 (Conv2D) (None, 55, 55, 96) 34944
_________________________________________________________________
batch_normalization (BatchNo (None, 55, 55, 96) 384
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 27, 27, 96) 0
_________________________________________________________________
conv2 (Conv2D) (None, 27, 27, 256) 307456
_________________________________________________________________
batch_normalization_1 (Batch (None, 27, 27, 256) 1024
_________________________________________________________________
151
max_pooling2d_1 (MaxPooling2 (None, 13, 13, 256) 0
_________________________________________________________________
conv3 (Conv2D) (None, 13, 13, 384) 885120
_________________________________________________________________
batch_normalization_2 (Batch (None, 13, 13, 384) 1536
_________________________________________________________________
conv4 (Conv2D) (None, 13, 13, 384) 663936
_________________________________________________________________
batch_normalization_3 (Batch (None, 13, 13, 384) 1536
_________________________________________________________________
conv5 (Conv2D) (None, 13, 13, 256) 442624
_________________________________________________________________
batch_normalization_4 (Batch (None, 13, 13, 256) 1024
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 6, 6, 256) 0
_________________________________________________________________
flatten (Flatten) (None, 9216) 0
_________________________________________________________________
fc6 (Dense) (None, 4096) 37752832
_________________________________________________________________
dropout (Dropout) (None, 4096) 0
_________________________________________________________________
fc7 (Dense) (None, 4096) 16781312
_________________________________________________________________
dropout_1 (Dropout) (None, 4096) 0
_________________________________________________________________
fc8 (Dense) (None, 1000) 4097000
=================================================================
Total params: 60,970,728
Trainable params: 60,967,976
Non-trainable params: 2,752
_________________________________________________________________
W sumie można wyróżnić w niej 25 podwarstw (włączając w nie konwolucję liniową, operację
ReLU, normalizację i pooling). Sieć zawiera 5 warstw konwolucyjnych i 3 warstwy w pełni
połączone (FC). Pierwsza warstwa FC połączona z operacją ReLU jest warstwą zawierającą 4096
cech diagnostycznych. Druga warstwa FC (również połączona z operacją ReLU jest warstwą
ukrytą klasyfikatora końcowego zasilająca warstwę wyjściową 1000 neuronów (pozwala na
rozpoznanie 1000 klas). Zastosowany w strukturze klasyfikator to softmax. Stosując transfer
learning można wyodrębnić sygnały z pierwszej warstwy FC jako cechy diagnostyczne i zasilić
nimi dowolnie wybrany klasyfikator, np. SVM czy MLP. W chwili obecnej implementacja sieci
AlexNet różni się nieco od wersji pierwotnej (brakuje warstwy ukrytej w strukturze FC).
152
MATLAB
% Przykład zastosowania ALEXNET w klasyfikacji obrazów%
wyn=[]; wynVal=[];
Pred_y=[]; Pred_yVal=[];
N_run=1 % liczba powtórzeń procesu
% Baza danych uczących
images = imageDatastore( 'C:\chmura\ALEX_obrazy20',...
'IncludeSubfolders',true,...
'ReadFcn', @customreader, ...
'LabelSource','foldernames');
[uczImages,testImages] = splitEachLabel(images,0.8,'randomized');
for i=1:No_run
[trainingImages,validationImages] = splitEachLabel(uczImages,0.70+0.1*randn(1),'randomized');
numTrainImages = numel(trainingImages.Labels);
net = alexnet;
layersTransfer = net.Layers(1:end-6);
inputSize = net.Layers(1).InputSize;
numClasses = numel(categories(trainingImages.Labels));
layers = [
layersTransfer
fullyConnectedLayer(1000+35*i, ...
'WeightLearnRateFactor',20,...
'BiasLearnRateFactor',20)
reluLayer()
dropoutLayer(0.5+0.033*randn(1))
fullyConnectedLayer(numClasses,...
'WeightLearnRateFactor',20,...
'BiasLearnRateFactor',20)
softmaxLayer
classificationLayer];
predictedLabels = classify(netTransfer,testImages);
testLabels = testImages.Labels;
accuracy = (mean(predictedLabels == testLabels))*100
Pred_y=[Pred_y predictedLabels];
wyn=[wyn accuracy] %wyniki poszczególnych powtórzeń procesu uczenia i testowania
153
end
plt.rc('font', size=6)
Następnie użyty zostanie kod, który automatycznie pobierze przykładowe obrazy udostępnione w
chmurze plików Wydziału Elekrycznego PW1. Zbiór obrazów zawiera 400 zdjęć 20 osób
przypisanych do odpowiednich klas. Procedura obejmuje kroki:
• Pobranie archiwum zip pod nazwę: alexnet_20.zip.
• Rozpakowanie archiwum do bieżącego folderu.
• Sprawdzenie czy został utworzony wybrany plik z obrazem.
Python
!wget -O alexnet_20.zip https://cloud.ee.pw.edu.pl/nextcloud/index.php/s/3Qn5HHRQ38Axk5G/download
!unzip -o -q alexnet_20.zip
with open("./Alex_obrazy20/1/1.jpg") as f:
print(f"{'-'*70}\nZrobione. Pliki znajdują się w podfolderach w katalogu ./Alex_obrazy20\n{'-
'*70}")
1
https://cloud.ee.pw.edu.pl/nextcloud/index.php/s/3Qn5HHRQ38Axk5G
154
def read_images(folder="./Alex_obrazy20"):
from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_array
images_list=[]
target_list=[]
folder="./Alex_obrazy20"
for sub in next(os.walk(folder))[1]:
for im in next(os.walk(os.path.join(folder,sub)))[2]:
images = np.array(images_list)
target = np.array(target_list)
return images, target
Domyślnie, nazwy folderów a zatem wartości klas zaczynają się od liczby 1. Sieć w dalszej części
będzie numerować klasy zaczynając od wartości 0. Zatem zmniejszamy automatycznie wszystkie
klasy na początku.
Python
labels = labels - 1
Dzielimy wczytany zbiór danych na trzy części: dane uczące, walidujące oraz testowe.
Skorzystamy z funkcji SciKit-Learn, aby wybór danych był automatycznie losowy. Dane będą
odpowiednio wymieszane z wszystkich klas.
Python
from sklearn.model_selection import train_test_split
W kolejnym etapie tworzymy obiekty do których będzie odwoływać się Keras w celu pobierania
porcji danych. Obiekty są dostosowane do pobierania danych w porcjach (ang. batch),
155
udostępniania danych do procesora GPU, rozpraszania danych między wieloma węzłami
obliczeniowymi.
Python
train_ds = tf.data.Dataset.from_tensor_slices( (train_images, train_labels) )
test_ds = tf.data.Dataset.from_tensor_slices( (test_images, test_labels) )
validation_ds = tf.data.Dataset.from_tensor_slices( (validation_images, validation_labels) )
train_ds_size = tf.data.experimental.cardinality(train_ds).numpy()
test_ds_size = tf.data.experimental.cardinality(test_ds).numpy()
validation_ds_size = tf.data.experimental.cardinality(validation_ds).numpy()
train_ds = (train_ds
.map(process_images)
.shuffle(buffer_size=train_ds_size)
.batch(batch_size=32, drop_remainder=True))
test_ds = (test_ds
.map(process_images)
.shuffle(buffer_size=test_ds_size)
.batch(batch_size=32, drop_remainder=True))
validation_ds = (validation_ds
.map(process_images)
.shuffle(buffer_size=validation_ds_size)
.batch(batch_size=32, drop_remainder=True))
Tworzymy funkcję zwracającą pustą konfigurację modelu z architekturą sieci AlexNet. Trzy
ostatnie warstwy modelu stanowią oryginalny klasyfikator, który zignorujemy w naszym modelu.
Python
def AlexNet():
NUMBER_OF_CLASSES = 1000
return keras.models.Sequential([
keras.layers.Conv2D(name='conv1', filters=96, kernel_size=(11,11), strides=(4,4),
activation='relu', input_shape=(227,227,3)),
keras.layers.BatchNormalization(),
keras.layers.MaxPool2D(pool_size=(3,3), strides=(2,2)),
keras.layers.Conv2D(name='conv2', filters=256, kernel_size=(5,5), strides=1,
activation='relu', padding="same", groups=2),
keras.layers.BatchNormalization(),
keras.layers.MaxPool2D(pool_size=(3,3), strides=(2,2)),
156
keras.layers.Conv2D(name='conv3', filters=384, kernel_size=(3,3), strides=(1,1),
activation='relu', padding="same"),
keras.layers.BatchNormalization(),
keras.layers.Conv2D(name='conv4', filters=384, kernel_size=(3,3), strides=(1,1),
activation='relu', padding="same", groups=2),
keras.layers.BatchNormalization(),
keras.layers.Conv2D(name='conv5', filters=256, kernel_size=(3,3), strides=(1,1),
activation='relu', padding="same", groups=2),
keras.layers.BatchNormalization(),
keras.layers.MaxPool2D(pool_size=(3,3), strides=(2,2)),
keras.layers.Flatten(),
keras.layers.Dense(4096, name='fc6', activation='relu'),
keras.layers.Dropout(0.5),
keras.layers.Dense(4096, name='fc7', activation='relu'),
keras.layers.Dropout(0.5),
keras.layers.Dense(NUMBER_OF_CLASSES, name='fc8', activation='softmax')
])
# tworzymy model
model = AlexNet()
model.summary()
Następnie pobieramy wartości wag nauczonej wstępnie sieci AlexNet. Oryginalne źródło danych:
http://www.cs.toronto.edu/~guerzhoy/tf_alexnet/bvlc_alexnet.npy. Wczytujemy plik ze
słownikiem numpy. Zawierającym macierze z wagami poszczególnych warstw sieci AlexNet i
ostatecznie ustawiamy wagi z oryginalnego AlexNeta nauczone na milionach obrazów z tysiącem
różnych klas.
Python
!wget -O bvlc_alexnet.npy
https://cloud.ee.pw.edu.pl/nextcloud/index.php/s/3RWeqX94WjF8Nyg/download
display(net_data.keys())
model.get_layer('conv1').set_weights(net_data["conv1"])
model.get_layer('conv2').set_weights(net_data["conv2"])
model.get_layer('conv3').set_weights(net_data["conv3"])
model.get_layer('conv4').set_weights(net_data["conv4"])
model.get_layer('conv5').set_weights(net_data["conv5"])
model.get_layer('fc6').set_weights(net_data["fc6"])
model.get_layer('fc7').set_weights(net_data["fc7"])
model.get_layer('fc8').set_weights(net_data["fc8"])
model.summary()
157
Python
new_model = tf.keras.models.Sequential(model.layers[:-5])
new_model.summary()
for l in new_model.layers:
l.trainable = False
numClasses = np.unique(train_labels).shape[0]
numClasses
i = 1
layers = new_model.layers + [
keras.layers.Dense(500+35*i, activation='relu'),
keras.layers.Dropout(0.2+0.23*np.random.uniform(0,1)),
keras.layers.Dense(numClasses, activation='softmax')
]
new_model_transfer = tf.keras.models.Sequential(layers)
display(layers)
new_model_transfer.compile(loss='sparse_categorical_crossentropy',
optimizer=tf.optimizers.SGD(lr=0.005),
metrics=['accuracy'])
new_model_transfer.summary()
158
img = (img -np.min(img)) * 255 / (np.max(img) - np.min(img))
plt.imshow(img.astype(np.uint8))
train_images_processed.dtype
Na końcu przechodzimy do procesu uczenia sieci oraz sprawdzamy jej dokładność, oraz
wyświetlamy przebiegi procesu uczenia dla danych walidacyjnych i testowych zaprezentowane na
rys. 9.6.
Python
# uczenie z augmentacją
history = new_model_transfer.fit(datagen.flow(train_images_processed, train_labels,
batch_size=16), epochs=30, validation_data=validation_ds,
validation_freq=1)
Rys. 9.6 Wyniki uzyskane dla sieci pre-trenowanej sieci AlexNex z wykorzystaniem własnych
warstw klasyfikacyjnych.
159
2/2 [==============================] - 1s 309ms/step - loss: 0.2674 - accuracy: 0.9219
[0.26736074686050415, 0.921875]
Jako dodatek prześledźmy, jak możemy wykorzystać wytrenowaną sieć do wykonania predykcji.
Wykorzystując metodę głosowania większościowego wybieramy klasę. Technicznie określamy
numer kolumny w każdym wierszu zwracanym przez sieć pred o wartości największego
prawdopodobieństwa. Pamiętamy, że biblioteka Keras obliczy wartości dla całego podzbioru batch
zawierającego 32 obrazy, zwróci zatem macierz o rozmiarach: 32 wierszy na 20 kolumn.
Python
images = []
y_true = []
y_pred = []
for batch in test_ds:
pred = new_model_transfer.predict(batch[0])
for idx, (prawdopodobienstwo, oczekiwane) in enumerate(zip(pred, batch[1])):
images.append(batch[0][idx,:,:,:]) # zapamietaj skojarzony obrazek
y_true.append(oczekiwane) # zapamiętaj wartosć rzeczywistą
y_pred.append(np.argmax(prawdopodobienstwo)) # zapamiętaj pozycję z największym
prawdopodobieństwem
y_true = np.array(y_true)
y_pred = np.array(y_pred)
confusion_matrix(y_pred, y_true)
array([[3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3]])
print(classification_report(y_pred, y_true))
160
9 1.00 0.50 0.67 2
10 0.80 1.00 0.89 4
11 1.00 1.00 1.00 4
12 1.00 0.50 0.67 2
13 1.00 1.00 1.00 5
14 1.00 1.00 1.00 3
15 0.67 1.00 0.80 2
16 1.00 0.75 0.86 4
17 0.80 1.00 0.89 4
18 1.00 1.00 1.00 1
19 1.00 1.00 1.00 3
accuracy 0.92 64
macro avg 0.92 0.90 0.90 64
weighted avg 0.94 0.92 0.92 64
161
• U-NET – struktura sieci CNN opracowana przez zespół Ronnebergera [70] dostosowana
specjalnie do zadań segmentacji obrazów, zwłaszcza medycznych. Pozwala na odtworzenie
poszczególnych rejonów obrazów w pełnej rozdzielczości.
Matlab ma zaimplementowane wiele gotowych (pre-trenowanych) prototypów takich sieci.
Poniżej przedstawione są dostępne aktualnie w Matlabie (Matlab 2021b) modele pre-trenowane
oraz ich podstawowe parametry: depth (głębokość), size (wymagana pamięć minimalna),
parameters (liczba adaptowanych parametrów sieci) oraz image input size (wymagany wymiar
obrazów wejściowych).
Tabela 9.1 Lista sieci głębokich pre-trenowanych w środowisku Matlab [48]. Parametry dotyczą
głębokości, wielkości, liczby parametrów podlegających uczeniu oraz wielkość obrazu wejściowego do
modelu.
Jak widać różne rozwiązania sieciowe są mocno zróżnicowane pod wieloma względami.
Najmniejsza liczba adaptowanych parametrów to 1.24 miliona w sieci squeezenet, podczas gdy
162
największa sieć vgg19 zawiera 144 milionów parametrów. Różne są również wymagania dotyczące
wymiaru obrazów wejściowych dla sieci: 224x224, 227x227, 256x256, 299x299 czy nawet
331x331. Badania eksperymentalne porównujące różne rozwiązania pokazują, że poszczególne
rodzaje sieci są zbliżone do siebie pod względem dokładności. Różnice w architekturze wynikają
głównie ze specyfiki zastosowań, zwłaszcza w przypadku rozwiązań do zadań mobilnych.
Jednym z problemów w sieciach wielowarstwowych jest zanikanie bądź eksplozja wartości
gradientu w procesie uczenia. Przy wzrastającej liczbie warstw ukrytych obserwowany był nawet
wzrost błędu dopasowania. Rozwiązanie, zwane Resnet, zaproponowane w [31] polegało na
wprowadzeniu dodatkowego połączenia między-warstwowego o tym samym kierunku przepływu
sygnałów. Sposób połączenia przedstawiony jest na rys. 9.7, w którym operacje sumowania
dotyczą wszystkich elementów poszczególnych warstw.
163
Linie ciągłe dotyczą połączeń międzywarstwowych o tych samych wymiarach macierzy.
Połączenie kropkowane dotyczy przypadku, gdy wymiary warstwy startowej i docelowej różnią
się (warstwa startowa 256×256, warstwa docelowa 128×128. . Zmniejszanie wymiaru między
warstwami uzyskane jest dzięki parametrowi stride (krok przesunięcia filtra konwolucyjnego)
równemu 2. W przypadku odwrotnym, gdy wymiary bloku startowego są mniejsze niż docelowego
wymiary x uzupełnia się przez dodanie odpowiedniej liczby zer (tzw. zero padding).
Przykład bardziej złożonej struktury Resnet o 34 warstwach parametrycznych z
powiązaniami residualnymi przedstawia rys. 9.9 (Resnet34).
164
b)
Rys. 9.10 Organizacja warstwy konwolucyjnej w SqueezeNet, stanowiącej Fire module (a).
Obrazy wejściowe przechodzą przez warstwę zwężającą (squeeze) złożoną z filtrów 1x1.
Następnie przetwarzane są w drugiej warstwie rozszerzającej (expand) zawierającej filtry 1x1
oraz 3x3. Liczba filtrów w obu warstwach jest dobierana przez użytkownika. Rysunek b
przedstawia typową strukturę sieci sqeezenet [36]. Bloki Conv1 i Conv10 oznaczają zwykłe
(typowe dla CNN) rozwiązanie konwolucji. Maxpool/2 oznacza operacje max poolingu
zmniejszającą dwukrotnie wymiary obrazów wejsciowych.
Dla zmniejszenia złożoności przetwarzania liczba filtrów 1x1 w warstwie squeeze (a więc i liczba
obrazów wyjściowych tej podwarstwy poddanych następnie konwolucji w warstwie
rozszerzającej) jest mniejsza niż suma filtrów 1x1 i 3x3 w warstwie expand, co redukuje skutecznie
liczbę adaptowanych parametrów. W zaproponowanej strukturze sieci (rys. 9.10b) stosuje się 8
modułów „Fire” zakończonych warstwą con10 o 1000 obrazach wyjściowych poddanych operacji
global average pooling (każdy obraz jest zastąpiony jedną wartością średnią stopnia jasności
165
wszystkich pikseli) tworzących 1000 sygnałów wejściowych dla warstwy softmax (brak w sieci
warstw w pełni połączonych). Szczegóły dotyczące doboru liczby filtrów w poszczególnych
warstwach znaleźć można w pracy [36].
Dzięki wprowadzonym modułom Fire udało się zredukować liczbę parametrów adaptowanych do
1.24 miliona uzyskując na bazie danych ImageNet tę samą dokładność co AlexNet o 61 milionach
parametrów.
Inne rozwiązanie problemu zmniejszenia wymiarów sieci (liczby parametrów poddanych
adaptacji) i zmniejszenia liczby operacji zmiennoprzecinkowych w procesie uczenia zostało
zastosowane w sieci ShuffleNet [92]. Idea przyśpieszenia obliczeń polega na grupowaniu filtrów
1x1 w grupy operujące na zredukowanej liczbie kanałów (obrazów) wejściowych, a nie na całym
zbiorze obrazów warstwy poprzedniej. Tworzy się równolegle wiele grup operujących na
wybranych losowo podgrupach obrazów wejściowych. Niestety część informacji globalnej
uzyskanej z takiego grupowego przetworzenia nie wykazuje wzajemnych relacji, ponieważ
przetworzeniu podlegały inne zestawy obrazów wejściowych. Stąd autorzy sieci zaproponowali w
następnym etapie przetasowanie podgrup (operacja shuffle). Każda grupa wytworzona w etapie
poprzednim podlega podziałowi na wiele podgrup. Podgrupy te po przetasowaniu tworzą zestawy
obrazów zasilające warstwę następną. Typowy schemat przetwarzania w ramach jednej warstwy
przedstawiony jest na rys. 9.11 [92].
166
konwolucja z użyciem pojedynczego obrazu wejściowego, BN – normalizacja danych w zbiorze
MiniBatch, Concat – konkatenacja (złączenie) danych z obu kanałów.
W sumie sieć ShuffleNet ma głębokość równą 50 (liczba wszystkich warstw równa 203). Udało
się zredukować liczbę parametrów adaptowanych do 1.4 miliona przy porównywalnej do
AlexNet dokładności działania.
Inne rozwiązanie problemu przyspieszenia obliczeń poprzez zmniejszenie złożoności
obliczeniowej zaproponowane zostało w sieci MobileNet [33]. W sieci tej stosuje się 2 rodzaje
konwolucji. Pierwsza z nich tzw. DWConv stosująca pojedynczy filtr do każdego kanału
(obrazu). Następuje po niej drugi etap konwolucji punktowej PConv, stosującej filtr 1x1
działający na sumie obrazów wytworzonych w etapie poprzednim. Jest to zasadnicza różnica w
stosunku do klasycznego rozwiązania konwolucyjnego, w którym filtracja i sumowanie jej
wyników w tworzeniu obrazów wyjściowych dotyczyło wielu obrazów wejściowych na raz i
występowało dla każdego nowo tworzonego obrazu.
167
w głąb. Autorzy rozwiązania wprowadzili równolegle działające bloki konwolucyjne stosujące
filtry o wymiarach 1×1, 3×3 oraz 5×5. Blok o małych wymiarach 1×1 odpowiedzialny jest za
liniową redukcję wymiarowości obrazu wejściowego jednocześnie pozwalając na zmniejszenie
czasu obliczeń, w stosunku do większych filtrów konwolucyjnych. Rolę taką pełni komórka zwana
Inception. Struktura takiej komórki przedstawiona jest na rys. 9.13.
Struktura sieci GoogLeNet składa się z 9 połączonych ze sobą komórek Inception, jak to
przedstawiono na rys. 9.14. Zawiera w sumie około 100 niezależnych bloków, przy czym
głębokość liczona w liczbie warstw podlegających uczeniu jest równa 22 (nie wliczając warstwy
168
typu pooling). Jak podają autorzy uczenie takiej sieci jest bardzo czasochłonne (około tygodnia
przy zastosowaniu kilku GPU pracujących w trybie równoległym).
Dalsze prace zespołu rozwijały powyższy model pod zmienioną nazwą Inception. Powstało
kilka kolejno ulepszanych struktur komórki Inception i połączeń warstwowych. Jedną z nich jest
hybryda różnych modeli Inception i ResNet, czyli InceptionResNet-v2, w której dodano podejście
residualne do komórek Inception. Przykład tak zmodyfikowanej struktury komórki przedstawiono
na rys. 9. 15.
Badania nad skutecznością działania sieci CNN pokazały, że dużą rolę odgrywa dobór
odpowiednich proporcji między głębokością (depth) architektury traktowaną jako liczba warstw
konwolucyjnych, liczbą równolegle tworzonych obrazów wynikowych w poszczególnych
warstwach (width) oraz rozdzielczością obrazów tworzonych w poszczególnych warstwach
(resolution). Rys. 9.16 przedstawia ideę skalowania sieci Efficientnet, stworzona przez M. Tana i
Q.V. Le [83].
169
Rys. 9.16 Ilustracja idei skalowania szerokości (width scaling), głębokości (depth scaling),
rozdzielczości (resolution scaling) oraz równoległego skalowania wszystkich wymienionych
wyżej parametrów (compound scaling).
170
Rys. 9.17 Struktura ogólna przepływu sygnałów w Dense bloku wykorzystywana w sieci
DenseNet.
Rys. 9.18 Struktura sieci DenseNet z trzema blokami Dense z rys. 9.16.
Pomiędzy blokami typu Dense stosowane są dodatkowo operacje konwolucji i poolingu. W jej
ramach wykonuje się normalizację danych w MiniBatch, konwolucję jednopunktową filtrem 1x1
oraz operacje 2x2 average pooling. Implementacja DenseNet w Matlabie pod nazwą densenet201
zawiera 20 milionów adaptowanych parametrów i głębokość równą 201. Jej skuteczność jest
porównywalna z najlepszymi rozwiązaniami sieci.
172
Rys. 9.19 Ilustracja sposobu obliczania współczynnika IOU.
Jeśli dany obiekt nie występuje w komórce wówczas C=0, w przeciwnym wypadku C= IOU truth
pred dla
danego obiektu. Równolegle z analizą pokrywania się obu obwiedni w komórce obliczane jest
warunkowe prawdopodobieństwo klasy obiektu. Jest ono wyrażone wzorem
Pr(klasai | obiekt ) = Pr(klasai ) IOU truth
pred (9.20)
Powyższe wyrażenie określa współczynnik ufności wystąpienia klasy i-tej w każdej komórce,
pozwalając określić jak dobrze dana komórka jest dopasowana do obiektu..
Każdy „bounding box” skojarzony z komórką jest charakteryzowany w systemie poprzez kilka
parametrów: (x,y) – współrzędne centrum obiektu mierzone względem danej komórki, (w,h) –
szerokość i wysokość obwiedni (traktowanej jako prostokąt) mierzone względem całego obrazu
oraz współczynnik ufności reprezentujący wartość IOU przewidywanej aktualnie obwiedni obiektu
względem prawdziwej (tzw. ground truth). Każda komórka jest dodatkowo odpowiedzialna za
wykrycie klasy każdego z obiektów i określenia prawdopodobieństwa przynależności klasowej
Pr(klasai|obiekt).
Struktura pierwotnie zaproponowanej sieci YOLO [66] przedstawiona jest na rys. 9.20.
Zawiera 24 warstwy konwolucyjne lokalnie połączone do generacji cech diagnostycznych i dwie
w pełni połączone warstwy odpowiedzialne jednocześnie za zadanie klasyfikacji (rozpoznanie
klasy obiektów) oraz zadanie regresji (określenie współrzędnych wystąpienia poszczególnych
obiektów). Zastosowany wymiar komórki S=7. Wyjściowa warstwa sieci generuje jednocześnie
prawdopodobieństwo przynależności określonej komórki do klasy obiektu (klasyfikacja) oraz
współrzędne obwiedni poszczególnych obiektów (regresja). Sieć używa funkcje aktywacji typu
173
Leaky ReLU. Uczenie sprowadza się do odpowiednio zdefiniowanej funkcji celu w postaci
najmniejszych kwadratów (LMS). Funkcja taka jest złożeniem składników odpowiedzialnych za
klasyfikację oraz składników odpowiedzialnych za regresję. W jego procesie przyjmuje się, że
każda obwiednia (bounding box) skojarzona jest jedynie z jednym obiektem na podstawie
największej wartości IOU.
174
Rys. 9.21 Struktura sieci R-CNN do detekcji obiektów w obrazie [17]
Rozwiązanie bazuje na zastosowaniu dwu podstruktur CNN. Pierwsza z nich, tzw. Region
Proposal Network (RPN) jest odpowiedzialny za generację cech diagnostycznych i znajduje rejony
obrazu zawierające propozycję ewentualnych obszarów obiektów. Druga część rozwiązania to
struktura CNN, zwana przez autorów RoI pooling (ang. RoI - region of interest) stwierdza
rzeczywiste istnienie bądź negację określonego obiektu (detekcję) w obrazie. Po stwierdzeniu
istnienia obiektu stosuje się w niej max pooling do przetworzenia cech zawartych w każdym
istotnym RoI obrazu w niewielkich wymiarów mapę cech (zwykle 7×7) na podstawie których
definiuje prawdopodobieństwo przynależności badanego RoI obrazu do obiektu i parametry
określające jego wymiar. Obie części sieci wykorzystują strukturę wielowarstwową CNN i
współpracują ze sobą, zarówno w trybie uczenia jak i testowania [17].
RPN przyjmuje na wejściu surowe obrazy podlegające analizie i przekazuje na wyjście (do
warstwy RoI pooling) propozycje prostokątnych rejonów z estymowanym stopniem
przynależności do klas poszukiwanych obiektów. RPN ma strukturę i zasadę działania sieci CNN.
W każdej warstwie używa przesuwającego się filtru (typowy wymiar 3×3) działającego na mapie
cech ostatniej warstwy konwolucyjnej. Sygnał wyjściowy filtru (po operacji ReLU) odpowiadający
każdej pozycji na obrazie jest rzutowany na małowymiarowy wektor cech (typowa wartość 256).
Cechy te stanowią wejście dla dwu w pełni połączonych warstw działających równolegle:
175
• warstwa regresyjna - generująca na wyjściu współrzędne bloków reprezentujących
proponowane rejony odpowiadające pozycji filtru na obrazie,
• warstwa klasyfikacyjna – estymująca przynależność bloków do określonego obiektu.
Każdej pozycji przesuwającego się okna filtrującego przypisuje się wiele propozycji rejonów,
zwanych kotwicami. Ich liczba k jest ustalana z góry. Stąd warstwa regresyjna generuje 4k wartości
(pozycje x, y lewego górnego piksela rejonu, szerokość w oraz wysokość h). Warstwa
klasyfikacyjna generuje 2k wartości estymujących prawdopodobieństwo przynależności oraz
braku przynależności k-tego rejonu do poszukiwanego obiektu, reprezentowanego przez ROI.
Każdy obraz analizowany jest w 3 skalach i dla 3 wartości współczynników kształtu kotwic (1:1,
1:2 oraz 2:1), co daje 9 kotwic dla każdej pozycji filtru. W przypadku obrazu o wymiarach W×H
liczba kotwic jest równa W×H×k.
Uczenie RPN w funkcji klasyfikatora generuje wynik binarny (±1). Znak dodatni (kotwica
pozytywna) przypisany jest kotwicy w dwu przypadkach: gdy jej powierzchnia pokrywa się z
obiektem poszukiwanym w stopniu powyżej 70% lub w przypadku skrajnym, gdy nie ma żadnego
takiego przypadku. Przyjmuje się wówczas kotwice o jak największej wartości współczynnika
pokrycia. Wartość negatywna klasyfikatora (kotwica negatywna) jest generowana, gdy
współczynnik pokrycia kotwicy z obiektem poszukiwanym jest poniżej 30%. Kotwice nie
zaliczone ani do pozytywnych ani negatywnych nie biorą udziału w dalszej procedurze uczenia.
Uczenie RPN polega na minimalizacji funkcji kosztu definiowanej w postaci [17]
L ( p , p ) + N p L (t , t )
1 1
min L ( pi , ti ) = cl i
*
i
*
i reg i
*
i (9.22)
Ncl i reg i
obiektu i-tego; pi* przyjmuje wartość 1 gdy kotwica jest pozytywna lub wartość 0 w przypadku
gdy kotwica jest negatywna. Parametr ti reprezentuje 4 wartości charakteryzujące rejon kotwicy (x,
y, w, h) a ti* te same wartości przypisane współrzędnym poszukiwanego obiektu (ground true box)
skojarzonego z dodatnią kotwicą. Składnik klasyfikacyjny funkcji kosztu Lcl ( pi , pi* ) przyjmuje
się w postaci logarytmicznej Lcl ( pi , pi* ) = − log pi gdzie pi reprezentuje estymowaną wartość
176
różnic między wartościami parametrów (x, y, w, h) przypisanych kotwicy i obiektu poszukiwanego
[17]. Może ona przyjmować różne postacie. Parametr λ stanowi współczynnik regularyzacji części
klasyfikacyjnej i regresyjnej we wzorze (9.17). Przy znormalizowanych wartościach
reprezentujących obiekt przyjmuje się zwykle λ=1.
W uczeniu gradientowym RPN stosuje się metodę SGD (stochastic gradient descent) przy
użyciu tzw. mini-zbiorów (ang. mini-batches) generowanych z określonych losowo obszarów
obrazów ROI (typowa populacja mini-batches przyjmowana w R-CNN jest równa 128 a jej skład
wynika z losowego wyboru ROI z wielu obrazów). Zakłada się przy tym, że przynajmniej 25%
ROI pokrywa się w stopniu 50% z obiektem podlegającym wykryciu. W uczeniu SGD stosuje się
zwykle technikę wspomagającą, wykorzystującą metodę momentu rozpędowego.
W rozwiązaniu R-CNN sieć RPN generuje propozycje obszarów podlegających dalszej
detekcji obiektów reprezentowanych w postaci określonych cech diagnostycznych. Funkcję
detektora pełni sieć Fast R-CNN, pełniąca rolę końcowego dostrajania. Dla przyspieszenia uczenia
i unifikacji rozwiązania obie części systemu (RPN i Fast R_CNN) współpracują ze sobą w
kolejnych cyklach obliczeniowych (tzw. alternative training). Fast R-CNN wykorzystuje jako
wejście rejony wskazane przez RPN, inicjalizując z kolei RPN swoimi wynikami w następnych
cyklach obliczeniowych. Dzięki temu proces detekcji poszukiwanych obiektów w obrazie jest
bardzo szybki [49].
Przykład programu Matlaba wykorzystującego sieć R-CNN do detekcji znaku STOP na
obrazach przedstawiony jest poniżej. W uczeniu zastosowano 27 obrazów zawierających znak
STOP-u i jeden obraz testowy.
MATLAB
% RCNN do detekcji znaku STOP
load('rcnnStopSigns.mat', 'stopSigns', 'layers')
imDir = fullfile(matlabroot, 'toolbox', 'vision', 'visiondata',...
'stopSignImages');
addpath(imDir);
options = trainingOptions('sgdm', ...
'MiniBatchSize', 32, ...
'InitialLearnRate', 1e-6, ...
'MaxEpochs', 10);
% Train the R-CNN detector. Training can take a few minutes to complete.
rcnn = trainRCNNObjectDetector(stopSigns, layers, options, 'NegativeOverlapRange', [0 0.3]);
% Test the R-CNN detector on a test image.
img = imread('stopSignTest.jpg');
[bbox, score, label] = detect(rcnn, img, 'MiniBatchSize', 32);
% Display strongest detection result.
[score, idx] = max(score);
bbox = bbox(idx, :);
annotation = sprintf('%s: (Confidence = %f)', label(idx), score);
detectedImg = insertObjectAnnotation(img, 'rectangle', bbox, annotation);
figure
imshow(detectedImg)
177
Wynik testowania programu na nowym obrazie nie uczestniczącym w uczeniu przedstawiony jest
poniżej na rys. 9.22.
Rys. 9.22 Wynik detekcji znaku STOP z obrazu nie uczestniczącego w uczeniu
178
Rys. 9.23 Struktura sieci U-net [70].
Obrazy występujące w warstwach zwężających (lewa część sieci) o coraz mniejszych wymiarach
(operacje pooling) zmniejszają rozdzielczość wyników, co powoduje pogorszenie lokalizacji
poszczególnych segmentów. Ta część sieci nazywana jest również enkoderem. W części
rozszerzającej struktury (prawa część sieci) operacja pooling w każdej warstwie jest zastąpiona
przez operację odwrotną (interpolacją) zwaną z angielska upsampling (pooling 2×2 zastępuje 4
piksele przez 1 piksel, natomiast upsampling 2×2 działa odwrotnie: 1 piksel jest replikowany w 4
piksele). Ta część sieci jest również nazywana dekoderem. Sieć U-net nie posiada warstw w pełni
połączonych, typowych w rozwiązaniach klasycznych CNN.
Część zwężająca U-net stosuje konwolucję przy użyciu maski filtrującej 3×3 z krokiem
stride=2, funkcję aktywacji ReLU i max pooling 2×2. W efekcie wymiar mapy cech (obrazu) w
każdej kolejnej warstwie jest zmniejszany dwukrotnie, ale jednocześnie generowana jest liczba
obrazów wzrastająca 2-krotnie.
Warstwy rozszerzające stosują operację interpolacji o wymiarze 2×2, w której jeden piksel
jest zastępowany 4 pikselami. Stosowane są różne metody, na przykład metoda najbliższych
sąsiadów, zastosowanie splinów, itp. Za bardziej optymalną uważa się operację konwolucji
transponowanej, zwanej również dekonwolucją, definiowanej jako operacja odwrotna do
179
konwolucji. Operacja 2×2 dekonwolucji zwiększa 2-krotnie wymiar mapy cech (obrazu
wynikowego) przy dwukrotnie zmniejszonej ich liczbie. Jednocześnie na każdym poziomie
warstwowym interpolacji następuje dołączenie odpowiedniego obrazu niższej rozdzielczości z
części zwężającej (część biała obrazów wejściowych na danym poziomie). Podobnie jak w
warstwie zwężającej stosowana jest konwolucja z filtrem 3×3 i operacja ReLU. W części końcowej
warstwy wyjściowej stosowana jest konwolucja 1×1 tworząca wysegmentowany obraz wyjściowy,
w którym każdy piksel jest reprezentowany przez przypisany do niego numer klasy (podział na
klastry reprezentujące oddzielne segmenty).
Uczenie sieci odbywa się z udziałem obrazów zawierających segmenty opisane przez
eksperta. Proces uczenia ma za zadanie zminimalizować sumę różnic między stopniami szarości
pikseli tworzących ROI segmentu zakreślonego przez eksperta i tych wygenerowanych przez
warstwę końcową sieci U-net (funkcja celu z użyciem definicji entropijnej). Odbywa się to zwykle
przy zastosowaniu metody stochastycznej największego spadku (SGD) z momentem rozpędowym.
Szczegóły można znaleźć w publikacji [70].
9.8 Autoenkoder
9.8.1 Struktura autoenkodera
Autoenkoder jest specjalnym rozwiązaniem sztucznej sieci neuronowej, którego zadaniem jest
skopiowanie danych wejściowych w wyjściowe z akceptowalnym błędem [22,39] za
pośrednictwem warstw ukrytych o zredukowanym wymiarze względem wymiaru danych
wejściowych. Jest to wielowarstwowy układ autoasocjacyjny stowarzyszający dane wejściowe ze
sobą. Struktura składa się z dwu następujących po sobie części: układu kodującego (enkoder)
rzutującego dane wejściowe w postaci wektora x w dane zakodowane reprezentowane przez wektor
h=f(x) i dekodera wykonującego działanie odwrotne rekonstruujące z określoną dokładnością
dane wejściowe x’=g(h). Przykład struktury autoenkodera o jednej warstwie sygnałów
zakodowanych i części dekodującej przedstawiony jest na rys. 9.24. Dane wejściowe w postaci
wektora x są kodowane w wektorze h jako sygnały ukryte (część tworząca enkoder). Dekodowanie
odbywa się w strukturze symetrycznej, odtwarzając za pośrednictwem wektora h’ wektor x’ (część
zwana dekoderem).
180
Rys. 9.24 Przykład struktury autoenkodera zawierający część kodująca (enkoder) i
rekonstrukcję sygnałów wejściowych (dekoder).
Podstawą jego działania jest kompresja danych polegająca na wychwyceniu głównych cech
procesu reprezentowanego przez zbiór wektorów x. Oznacza to, że dane zrekonstruowane x’ nie
reprezentują dokładnych kopii danych wejściowych, ale ich aproksymację. Wektor h stanowiący
podstawę kodowania i następnie rekonstrukcji, reprezentuje zatem cechy główne procesu
eliminując elementy nieistotne (traktowane jako szum) zawarte w zbiorze danych wejściowych x.
Autoenkoder jest uogólnieniem dwuwarstwowej sieci liniowej PCA. Różni go od niej liczba
warstw, która może być dowolna, jak również nieliniowa funkcja aktywacji neuronów stosowana
w przypadku ogólnym.
181
sieci może być zdefiniowany jako dobór parametrów (wag neuronowych) prowadzący do
minimalizacji funkcji kosztu (celu) E(x,g(h(x)).
Podstawowa definicja funkcji kosztu przyjmowana jest zwykle w postaci wartości błędu
średniokwadratowego [22] po wszystkich zmiennych n= 1, 2,…,N dla danych uczących przy k=1,
2, …, p, przy czym N jest wymiarem wektora wejściowego a p liczbą danych uczących
(obserwacji).
E = ( xn − x 'n ) = ( xn − gn (h(x( k ) ) )
1 N p (k ) (k ) 2 1 N p (k ) 2
(9.23)
p n=1 k =1 p n=1 k =1
Dla uzyskania lepszej odporności autoenkodera na szum w uczeniu stosuje się również wersję
zmodyfikowaną, w której zamiast dopasowywać sygnały wyjściowe g(h(x)) do sygnałów
wejściowych x porównanie z sygnałami x dotyczy odpowiedzi autoenkodera g(h(xs)) na sygnały
zaszumione xs,. Układ przetwarza wówczas xs w taki sposób, aby uzyskać na wyjściu najlepszą
możliwie aproksymację wektorów oryginalnych x. Oznacza to, że funkcja celu podlegająca
minimalizacji przyjmuje zmodyfikowaną formę [22]
1 N p (k )
( xn − gn (h(x(sk ) ) )
2
E= (9.24)
p n=1 k =1
Zastosowanie liniowej funkcji aktywacji neuronów przy jednej warstwie ukrytej prowadzi do
znanego rozwiązania PCA. Autoenkoder stosujący nieliniowe funkcje aktywacji i kilka warstw ma
wiele zalet w stosunku do rozwiązania liniowego, z których najważniejsze to [22]
• duża oszczędność (ang. sparsity) w reprezentacji danych,
• ograniczone wartości pochodnej sygnałów,
• krzepkość systemu względem szumu oraz brakujących danych.
Oszczędność autoenkodera może być osiągnięta w procesie uczenia poprzez włączenie do funkcji
kosztu czynnika kary za nadmiernie rozbudowaną strukturę. Wówczas zmodyfikowana
funkcja kosztu E przyjmie postać
E=E(x,g(h(x)))+λΩ1(h) (9.25)
w której wielkość E(x,g(h(x))) reprezentuje klasyczną definicję funkcji kosztów, a stanowi
współczynnik regularyzacji. Funkcja 1 (h) stanowi karę za zbyt rozbudowaną strukturę układu.
Typowa definicja tej funkcji to
1 (h) =
1
( )
wij(h)
2 h i, j
2
(9.26)
182
gdzie h reprezentuje warstwy ukryte zastosowane w rozwiązaniu. W wyniku uczenia wymusza się
zmniejszenie wartości wag określonych grup neuronów. W efekcie pewne połączenia synaptyczne
o małej wartości wag mają minimalny wpływ na działanie systemu.
Dla dalszego zmniejszenia wpływu zmian danych wejściowych x na wynik działania
układu wprowadza się regularyzację uwzględniającą pochodne sygnałów warstwy ukrytej
względem elementów wektora wejściowego x. Funkcja regularyzacyjna przyjmuje wówczas
następującą formę [22]
H
2 (h, x) = x hi
2
(9.27)
h =1
gdzie p oznacza liczbę obserwacji (wektorów x). Mała wartość średniej aktywacji neuronu
oznacza, że neuron ten aktywuje się jedynie dla niewielkiej ilości danych wejściowych,
specjalizując się w ich reprezentacji. Dodając taki czynnik do minimalizowanej funkcji kosztu
zmusza się neurony do reprezentowania jedynie określonych (specyficznych) cech procesu.
W praktyce ten czynnik regularyzacyjny definiuje się z wykorzystaniem dywergencji
Kullbacka-Leiblera, mierzącego zgodność wartości aktualnej z pożądaną wartością średniej
funkcji aktywacji dla określonego zbioru danych. Składnik regularyzacyjny definiuje się w postaci
[22]
1 − i
3 ( ) = i log i + (1 − i ) log (9.29)
i ˆi 1 − ˆi
Regularyzacja Kulbacka-Leiblera jest statystyczną miarą zgodności dwu rozkładów
stochastycznych. Przyjmuje małą wartość, przy niewielkiej niezgodności i wartość zerową gdy
ˆ i = i . Przy wzrastającej niezgodności miara ta rośnie.
183
W praktyce definiuje się wartość pożądaną stosunku i / ˆ i (w Matlabie [38] jest to
184
a)
b)
Rys. 9.25 Ilustracja sposobu kształtowania pierwszej warstwy ukrytej: a) struktura stosowana w
uczeniu, b) postać wyjściowa sieci dla doboru następnej warstwy.
Po doborze parametrów warstwy ukrytej odrzuca się warstwę rekonstrukcji i sygnały z warstwy
ukrytej stają się wejściowymi dla następnej warstwy (rys. 9.25b). Proces uczenia jest
kontynuowany dla następnej warstwy, dobierając jej parametry w taki sposób, aby uzyskać
185
możliwie najlepsze odwzorowanie sygnałów wejściowych a w sygnały wyjściowe. W efekcie po
odrzuceniu warstwy wyjściowej sieć zawiera dwie warstwy neuronowe a i b jak to pokazano na
rys. 9.26, przy czym liczba neuronów w każdej kolejnej warstwie jest kolejno redukowana w
identyczny sposób jak to miało miejsce w przypadku pierwszej warstwy ukrytej, zmuszając sieć
do kompresji danych.
Sygnały warstwy ukrytej b stają się ponownie sygnałami wejściowymi dla ukształtowania
następnej warstwy o dalej zredukowanej liczbie neuronów Proces jest następnie kontynuowany dla
następnych warstw, w sposób identyczny do omówionego. Kształtowanie kolejnych warstw
autoenkodera może odbywać się przy użyciu dowolnego algorytmu gradientowego. Jest to
stosunkowo prosty proces ze względu na fakt, że w każdym etapie uczenie dotyczy tylko
parametrów jednej warstwy.
Ostatnia warstwa ukryta autoenkodera (po wyeliminowaniu warstwy rekonstrukcyjnej)
zawiera kodowanie na najwyższym poziomie, zwykle o najbardziej ograniczonej liczbie
neuronów. Sygnały wyjściowe tej warstwy stanowią cechy diagnostyczne wyselekcjonowane
przez strukturę układu w procesie uczenia z udziałem zbioru danych uczących. Mogą one stanowić
atrybuty wejściowe dla końcowego stopnia klasyfikatora bądź układu regresyjnego o dowolnej
konstrukcji. W ostatnim etapie tak ukształtowana struktura sieci podlega regularnemu uczeniu na
danych parach uczących (x,d).
186
9.8.4 Przykład zastosowania autoenkodera w kodowaniu danych
Poniżej przedstawiony będzie przykład zdolności kodowania autoenkodera dla zbioru 8 obrazów
czarno-białych o wymiarach 64x64 (w sumie 4096 sygnałów wejściowych) reprezentowanych na
rys. 9.27 i zawartych w plikach RBx.png. Zbiór ten został użyty najpierw w uczeniu a następnie
przetestowane zostało odtwarzanie zakodowanych obrazów (identycznych jak w uczeniu).
Zastosowano jedną warstwę ukrytą o 30 neuronach. Współczynnik kompresji równał się więc
4096/30=136.9.
187
nerr(i)=sum(errBW);
subplot(2,4,i);
% imshow(1-err);
imshow(reshape(1-errBW,64,64)); title('Error')
end
liczba_err=nerr
rate_err=nerr/4096*100
Wygląd obrazów w skali szarości odtworzonych po rekonstrukcji przedstawiony jest na rys. 9.28.
Szare piksele obrazu (ledwie widoczne) nałożone na inne czarno–białe obrazy odtworzone przez
sieć mają niewielkie wartości, które przetworzone na reprezentację czarno-białą nie wnoszą
istotnych błędów rekonstrukcji obrazów czarno-białych. Błąd rekonstrukcji kolejnych 8 obrazów
czarno-białych w postaci liczby błędnych pikseli (po wcześniejszym zaokrągleniu wartości pikseli
do 1 lub 0) uzyskany w programie podany jest poniżej
Liczba błędnych pikseli kolejnych obrazów=[ 3 4 7 9 0 8 92 2]
Błąd odtworzenia dotyczył znikomej ilości pikseli w obrazach czarno-białych (oryginalna liczba
pikseli każdego obrazu równa 4096). Jeden obraz czarno-biały został odtworzony bezbłędnie
(wynik po zaokrągleniu do wartości bitów 1 lub 0). Procentowa zawartość błędów odtworzenia
kolejnych obrazów czarno-białych jest równa
Błąd procentowy=[ 0.07% 0.10% 0.17% 0.22% 0 0.19% 2.25% 0.05%]
Należy zauważyć, że jest to wynik rekonstrukcji autoenkodera jedynie w trybie odtwarzania na
tych samych danych, które były użyte w uczeniu. Świadczą one o dobrych wynikach uczenia sieci.
Na tej podstawie nie można jednak wyciągać daleko idących wniosków co do zdolności
generalizacji systemu przy tej wartości współczynnika kompresji.
Sieć autoenkodera znajduje zastosowanie w typowych obszarach przetwarzania danych, takich jak:
188
• Redukcja szumu zakłócającego dane – w tym przypadku zakłada się, że dane wejściowe
zniekształcone są szumem; po zakodowaniu i rekonstrukcji szum ten może ulec znacznej
redukcji przy właściwym doborze parametrów sieci.
• Generacja cech diagnostycznych procesu reprezentowanego przez dane uczące. W tym
przypadku wyjściem sieci jest warstwa ukryta. W przypadku programu autoenkoder
Matlaba [38] dostęp do sygnałów h warstwy ukrytej (kodującej) odbywa się komendą
h=encode(autoenc, dane_wej)
gdzie autoenc jest nazwą struktury sieciowej użytej w wywołaniu autoenkodera, a dane_wej jest
zbiorem danych które mają podlegać kodowaniu.
Program Matlaba zakłada istnienie jednej warstwy ukrytej. Przy strukturze
wielowarstwowej jego wywołanie musi być wielokrotne, przy czym za każdym razem
wymuszeniem dla następnej warstwy są sygnały wyjściowe warstwy ukrytej. Ostatnia warstwa
ukryta reprezentować będzie najbardziej skompresowane cechy diagnostyczne procesu.
Przykład zastosowania autoenkodera przedstawiony zostanie przy rozpoznaniu 2 rodzajów
komórek krwiotwórczych (kodowanie binarne zero-jedynkowe wektora destination T) na podstawie 87
cech diagnostycznych typu numerycznego zawartych w macierzy X. Stosowane są 2 warstwy kodujące
(ukryte) i warstwa typu Softmax na wyjściu działająca w trybie klasyfikacji. Wydruk programu w Matlabie
wykonującego zadanie przedstawiony jest poniżej. Dane dotyczące cech diagnostycznych (macierz
sygnałów wejściowych X) oraz przynależności klasowej kolejnych obserwacji (wektor T) zawarte są w
pliku Matlaba XT_autoenkoder.mat.
MATLAB
load XT_autoencoder.mat
a=randperm(293);Xrand=X(:,a);Trand=T(:,a);
Xucz=Xrand(:,1:193);Tucz=Trand(:,1:193);
Xtest=Xrand(:,194:end); Ttest=Trand(:,194:end);
% Train an autoencoder with a hidden layer and a linear transfer function for the
% decoder. Set the L2 weight regularizer to 0.001, sparsity regularizer to 4 and sparsity
% proportion to 0.05.
hiddenSize = 40;
autoenc1 = trainAutoencoder(Xucz,hiddenSize,...
'L2WeightRegularization',0.001,...
'SparsityRegularization',4,...
'SparsityProportion',0.05,...
'DecoderTransferFunction','purelin');
% Extract the features in the hidden layer.
features1 = encode(autoenc1,Xucz);
% Train a second autoencoder using the features from the first autoencoder.
hiddenSize = 15;
autoenc2 = trainAutoencoder(features1,hiddenSize,...
'L2WeightRegularization',0.001,...
'SparsityRegularization',4,...
'SparsityProportion',0.05,...
'DecoderTransferFunction','purelin',...
'ScaleData',false);
189
% Extract the features in the hidden layer.
features2 = encode(autoenc2,features1);
% Train a softmax layer for classification using the features, features2
softnet = trainSoftmaxLayer(features2,Tucz,'LossFunction','crossentropy');
% Stack the encoders and the softmax layer to form a deep network.
deepnet = stack(autoenc1,autoenc2,softnet);
% Retraining deep network
deepnet = train(deepnet,Xucz,Tucz);
% Estimate the cell types using the trained deep network: deepnet.
cell_type = deepnet(Xtest);
% Plot the confusion matrix.
plotconfusion(Ttest,cell_type);
Wynik testowania sieci na danych testujących nie uczestniczących w uczeniu jest zależny od
losowego podziału zbioru danych na zbiór uczący i testujący i może przyjmować różne wartości
w zależności od ich składu. Przykładowy wynik dla jednej próby w postaci macierzy rozkładu klas
(ang. confusion matrix) przedstawiony jest na rys. 9.29.
Rys. 9.29 Przykładowy wynik (w postaci macierzy rozkładu klasowego) testowania systemu
autoenkodera z klasyfikatorem typu Softmax na wyjściu.
9.9Autoenkoder wariacyjny
9.9.1 Podstawy działania
Autoenkoder wariacyjny (ang. Variational Autoenkoder - VA) jest innym rozwiązaniem sieci
głębokiej umożliwiającym generację obrazów podobnych do oryginału (proces często stosowany
190
do wzbogacenia zbioru danych uczących). Będzie dalej oznaczany skrótem VAR [39]. Sieć taka
działa na innych zasadach niż przedstawiona wcześniej sieć klasycznego autoenkodera (AE).
Nazwa sieci wywodzi się z bliskiej relacji mechanizmu działania z zasadą regularyzacji sieci i
wnioskowania wariacyjnego w statystyce.
Sieć VAR wykorzystuje w swoim działaniu zasadę redukcji wymiarowości danych, tak
przeprowadzoną, że możliwe jest odtworzenie danych oryginalnych z określoną dokładnością przy
zachowaniu w miarę wiernego odwzorowania rozkładu statystycznego (wartości średniej i
wariancji), a nie odtworzenia wartości poszczególnych pikseli, jak to miało miejsce w przypadku
autoenkodera AE [39]. Redukcja wymiarowości danych oznacza reprezentację danych poprzez
zmniejszoną liczbę cech (deskryptorów) charakteryzujących dostatecznie dokładnie analizowany
proces. Redukcja taka może polegać na wyborze ograniczonej liczby zmiennych oryginalnych (bez
zmiany ich wartości), bądź na generacji nowego zbioru deskryptorów jako funkcji liniowej (np.
PCA) bądź nieliniowej wszystkich zmiennych oryginalnych (AE).
Klasycznym rozwiązaniem tego typu jest autoenkoder, poznany wcześniej. Idea uczenia
autoenkodera polegała na takim doborze parametrów (wag sieci głębokiej), aby obraz wyjściowy
po rekonstrukcji sygnałów skompresowanych przypominał jak najbardziej obraz oryginalny. W
procesie uczenia klasycznego autoenkodera porównywane były wartości sygnałów bądź piksele
obrazów oryginalnego i zrekonstruowanego. Redukcja wymiarowości w takim rozwiązaniu
autoenkodera może być zinterpretowana jako kompresja danych, w której enkoder kompresuje
dane z przestrzeni oryginalnej do przestrzeni zredukowanej traktowanej zwykle jako przestrzeń
ukryta (ang. latent space), natomiast dekoder dokonuje dekompresji, czyli rekonstrukcji danych
oryginalnych. Sposób uczenia klasycznego autoenkodera ukierunkowany jest na zgodność
kolejnych elementów danych zrekonstruowanych z oryginalnymi
Oczywiście, odtworzenie danych oryginalnych poprzez dekompresję charakteryzuje się
pewną utratą informacji oryginalnej. Wielkość tej straty uzależniona jest od wymiaru przestrzeni
skompresowanej jak również od mechanizmu uczenia sieci. Ilustracja tego typu procesu
przetwarzania danych przedstawiona jest na rys. 9.30. Wektor oryginalny x kodowany jest w
wektor e(x) o zmniejszonym wymiarze, po czym dekodowany w postać d(e(x)). Istotą klasycznego
algorytmu uczenia sieci autoenkodera jest taki dobór parametrów sieci, aby utrata informacji
oryginalnej, czyli różnica między elementami wektora zrekonstruowanego i oryginalnego była jak
najmniejsza. Minimalizacji podlega zwykle funkcja błędu
191
min E = x - d(e(x))
2
(9.31)
Klasyczny autoenkoder ma pewną wadę, wynikającą z nieciągłości danych (na przykład puste
przestrzenie między klastrami danych). Na etapie testowania na danych nie uczestniczących w
uczeniu dekoder układu wygeneruje nierealistyczny wynik (nieprzystający do danych
oryginalnych), gdyż na etapie uczenia nie „widział” statystycznego rozkładu dotyczącego danych
enkodera z obszaru pustego.
x e(x) d(e(x))
Rys. 9.30 Struktura klasycznego autoenkodera AE [96].
Takie rozwiązanie (przy założeniu rozkładu danych jako normalny) sprowadza się w uczeniu
VAR również do reprezentacji danych poprzez wartości średnie i macierz kowariancji,
193
zamiast jedynie reprezentacji poszczególnych danych (pikseli obrazu). Takie rozwiązanie
umożliwia regularyzację sieci w prosty sposób, zmuszając enkoder do zapewnienia
normalności rozkładu danych w przestrzeni ukrytej. Proces realizowany przez VAR można
więc przedstawić jak na rys. 9.31 [96].
Rys. 9.31 Struktura VAR ilustrująca elementy składowe używane w procesie uczenia: μx
reprezentuje wartość średnią a σx odchylenie standardowe danych w warstwie ukrytej [96].
Aby zapewnić prawidłowy przebieg procesu uczenia należy zapewnić regularyzację zarówno
wartości średniej jak i macierzy kowariancji, sprowadzając proces do normalnego o zerowej
wartości średniej i jednostkowej macierzy kowariancji. Minimalizacja wartości czynnika
regularyzacyjnego odbywa się kosztem składnika rekonstrukcyjnego (składnik pierwszy we
wzorze (9.27)). Właściwy balans między nimi można uzyskać przez wprowadzenie odpowiedniej
wagi we wzorze (9.27).
Przyjmuje się, że p(z) ma standardowy rozkład Gaussa p(z)=N(0,1), o wartości średniej zerowej i
jednostkowej macierzy kowariancji 1. Z kolei p(x|z) jest rozkładem gaussowskim, którego wartość
średnia jest funkcją deterministyczną f(z) zmiennej z a macierz kowariancji jest postaci
jednostkowej pomnożonej przez dodatnią stałą wartość c, co zapisuje się w postaci
p(x|z)=N(f(z),c1). Zarówno c jak i postać funkcji nie są z góry zadane i podlegają estymacji w
procesie uczenia. Mianownik w wyrażeniu Bayesa wymaga zastosowania wnioskowania
wariacyjnego, techniki stosowanej w złożonych rozkładach statystycznych.
W tym podejściu stosuje się sparametryzowane rodziny rozkładów (zwykle gaussowskich
o różnej wartości średniej i macierzy kowariancji). Spośród nich wybiera się tę rodzinę, która
minimalizuje błąd aproksymacji na danych pomiarowych (zwykle dywergencję Kulbacka-Leiblera
między aproksymacją i wartościami zadanymi). Funkcja p(z|x) jest w podejściu wariacyjnym
aproksymowana poprzez rozkład gaussowski [39,96]
qx(z)=N(g(x), h(x)) (9.34)
w którym wartość średnia jest aproksymowana przez g(x) a kowariancja przez h(x). Obie
funkcje podlegają procesowi minimalizacji z użyciem miary Kulbacka-Leiblera
( g*, h*) = arg min KL ( qx ( z ), p( z | x) ) (9.35)
g ,h
195
Składnik pierwszy w tym wzorze odpowiada za dopasowanie sygnałów wyjściowych sieci do
wartości zadanych x, natomiast składnik drugi za rozkład statystyczny danych wejściowych i
sygnałów w warstwie ukrytej, stanowiąc naturalny składnik regularyzacyjny procesu. Istotnym
parametrem jest c. Wartość tej zmiennej pozwala regulować relację między składnikiem
pierwszym i drugim. Duża wartość c oznacza większy wpływ czynnika KL, czyli dopasowania
statystycznego obu rozkładów. Mała wartość – większy wpływ dopasowania pikselowego
zrekonstruowanego obrazu do oryginalnego.
Funkcje f, g i h użyte w modelu matematycznym podlegają w praktyce modelowaniu
aproksymacyjnemu przy użyciu sieci neuronowych. Obie funkcje g i h wykorzystują wspólny
fragment architektury sieci, co można zapisać w postaci [39,96]
g(x)= g2(g1(x))=g2(h1(x)) (9.37)
h(x)=h2(h1(x)) (9.38)
Przyjmuje się w praktyce założenie upraszczające, że h(x) jest wektorem złożonym z elementów
diagonalnych macierzy kowariancji i jest jednakowych rozmiarów jak g(x). Przy rozkładzie
gaussowskim zmiennej z o wartości średniej g(x) i wariancji h(x) przyjmuje się, że
z = h( x) + g ( x) (9.39)
gdzie jest zmienną losową o rozkładzie normalnym ~ N (0,1) . Rys. 9.31 przedstawia ogólną
strukturę układową enkodera implementującą funkcje g(x) oraz h(x), przy czym wektor g(x)
reprezentuje wartości średnie a h(x) kowariancje (wartości diagonalne macierzy kowariancji).
Rekonstrukcja sygnałów wyjściowych f(z) realizowana przez dekoder realizuje rozkład p(x|z)
generowany przez enkoder zakładając przy tym stałą kowariancję. Jej implementacja jest możliwa
przez strukturę neuronową implementującą funkcję f o postaci ogólnej prezentowanej na rys. 9.32
przy założeniu trzech neuronów w warstwie ukrytej. Stan tych neuronów dla dekodera ustalany
jest według rozkładu normalnego o wartościach średnich i odchyleniu standardowym ustalonym
poprzez warstwę h i g enkodera.
196
Rys. 9.32 Struktura neuronowa realizująca autoenkoder wariacyjny w ujęciu implementacyjnym [2]
W efekcie proces uczenia sprowadza się do minimalizacji funkcji celu o postaci [39,96]
min E = C x - f (z) + KL ( N ( g ( x), h( x) ) , N (0,1) )
2
(9.40)
197
9.10 Sieci generatywne GAN
Sieć generatywna GAN (ang. Generative Adversarial Network) stworzona przez zespół Iana
Goodfellow [23] w 2014 roku, jest implementacją koncepcji przeciwstawienia sobie dwu sieci
neuronowych, z których jedna reprezentuje dane rzeczywiste, a druga dane generowane sztucznie,
udając dane rzeczywiste. Obie sieci rywalizują ze sobą. System jest trenowany w taki sposób aby
generator nowych danych był w stanie oszukać rzeczywistość, prezentując dane (sygnały bądź
obrazy) które są trudne do odróżnienia od rzeczywistych. Generator sztucznych danych ma za
zadanie wygenerować je w taki sposób, aby statystyki danych oryginalnych i danych
generowanych przez niego były takie same [13,23]. Przykładowo w przypadku obrazów, obraz
wygenerowany sztucznie powinien przypominać obraz oryginalny.
Rys. 9.34 Struktura podstawowa sieci GAN. Blok X reprezentuje dane oryginalne, Z – wektor
losowy zasilający generator G, generujący dane G(Z) „udające” dane oryginalne. Dyskryminator
D porównuje dane oryginalne X z G(Z) wygenerowanymi rzez generator wskazując na
prawdopodobieństwo zgodności obu danych X i G(Z) [23].
Idea działania sieci GAN jest przedstawiona na rys. 9.34. Blok X reprezentuje dane oryginalne, Z
– wektor losowy zasilający generator G, generujący na tej podstawie dane G(Z) „udające” dane
oryginalne. Dyskryminator D porównuje dane oryginalne X z G(Z) wygenerowanymi przez
generator wskazując na prawdopodobieństwo zgodności obu danych X i G(Z). Proces uczenia sieci
198
polega na takim doborze parametrów, aby oszukać dyskryminator (uznać, że dane wygenerowane
sztucznie G(Z) niczym nie różnią się od danych oryginalnych X. W efekcie generator G generuje
kolejnych kandydatów do porównania, a dyskryminator D ocenia ich jakość w stosunku do
oryginału.
Proces uczenia polega na maksymalizacji prawdopodobieństwa, że dyskryminator popełni
błąd przyjmując że obie grupy danych (oryginalne i sztucznie wygenerowane) są identyczne pod
względem rozkładu statystycznego (maksymalizacja prawdopodobieństwa zaliczenia obu
obrazów: oryginalnego i wygenerowanego sztucznie do tej samej klasy). Można go zapisać jako
programowanie minimaksowe zdefiniowane w postaci [13,23]
min max V (G , D ) = x ~p x log D (X) + z~ p z
log (1 − D (G (z)) ) (9.41)
G D
199
Powstało wiele modyfikacji podstawowej struktury GAN polepszających sprawność
wykrywania „podróbki” od danych oryginalnych. Przykład takiego rozwiązania zwanego BIGAN
(skrót Bidirectional Generative Adversarial Networks) przedstawiony jest na rys. 9.35 [13].
Struktura sieci BIGAN zawiera enkoder E który transformuje dane oryginalne X do przestrzeni
wektorowej E(X), generując wektor cech o wymiarach identycznych z wektorem losowym Z.
Dyskryminator D sieci BIGAN dokonuje więc rozróżnienia pary danych (x, E(x)) oraz (G(z), z)
zamiast (x versus G(z)) w klasycznej implementacji GAN. Jest oczywiste, że enkoder E próbuje
„nauczyć” się inwersji generatora G (czyli wektora Z), choć nie występuje tu bezpośrednia
komunikacja. Zwiększona informacja (w stosunku do wersji oryginalnej GAN) dostarczona do
dyskryminatora umożliwia polepszenie dokładności rozpoznania „podróbki” od oryginału.
Sieci generatywne (GAN i jego różne modyfikacje) znajdują różne zastosowania [13].
Jednym z nich jest wzbogacanie zbioru danych oryginalnych (tak zwana augmentacja zbioru)
użytych w uczeniu sieci CNN. Dane wygenerowane przez GAN są podobne statystycznie do
danych oryginalnych, ale nie tożsame, co jest warunkiem polepszenia zdolności generalizacyjnych
trenowanych sieci. Innym zastosowaniem sieci GAN jest wykrywanie różnic między oryginałami
i podróbkami. Dotyczy to zarówno obrazów jak i sygnałów. Sieci te wykazują się zwiększoną
czułością w stosunku do innych rozwiązań.
200
Sieci rekurencyjne zbudowane na bazie perceptronu wielowarstwowego stanowią ogólniejszą
strukturę niż sieci jednokierunkowe, gdyż dopuszczają sprzężenia zwrotne między neuronami.
Systemy tego typu są bardzo pożądane w analizie szeregów czasowych, w których sygnały
sąsiednie są ze sobą powiązane. Typowy przykład struktury rekurencyjnej zawierającej sprzężenia
zwrotne jedynie między neuronami ukrytymi w warstwie przedstawiono na rys. 9.36.
Głównym problemem w uczeniu takich sieci jest fakt, że sygnał wyjściowy neuronu zależy nie
tylko od pobudzenia w danej chwili, ale również od stanu neuronów w chwili poprzedniej. Można
to przedstawić w postaci rozłożonej w czasie jak na rys. 9.37 [24], w której sprzężenie zostało
zamienione na przepływ jednokierunkowy sygnałów z uwzględnieniem kolejnych chwil
czasowych. Stan neuronów w kolejnych chwilach: t, t+1, t+2 aż do końca okna pomiarowego T
zależy również od ich stanu w chwilach wcześniejszych. Układ taki można więc traktować jako
sieć głęboką.
t t+1 t+2 t→T
Warstwa wyjściowa
Warstwa ukryta
Warstwa wejściowa
201
Uczenie takiej sieci jest znacznie bardziej złożone w stosunku do klasycznych sieci
jednokierunkowych, gdyż gradient w chwili aktualnej zależy również od chwil poprzednich.
Niestety, występuje tu problem tak zwanego zanikającego gradientu, co oznacza zanikanie
powiązań chwili bieżącej z wcześniejszymi. W kolejnych chwilach czasowych zależność funkcji
gradientu od sygnału wejściowego sprzed poprzednich chwil czasowych powoli zanika, co
powoduje utratę pewnej ilości informacji pierwotnie dostarczonej do sieci. Ten efekt może być
zilustrowany jak na rys. 9.38. Stopień zaczernienia węzłów ilustruje wpływ sygnału wejściowego
z chwili t=1 na stan neuronów w chwilach późniejszych (im bardziej ciemny kolor tym większy
wpływ). Klasyczne rozwiązanie sieci rekurencyjnej nie gwarantuje więc dobrego zapamiętania
wcześniej wytrenowanych wzorców. Oznacza to utratę informacji, która była wprowadzona we
wcześniejszych etapach uczenia sieci.
Skuteczne rozwiązanie tego problemu było możliwe dzięki wprowadzeniu specjalizowanej
struktury rekurencyjnej, zwanej siecią Long Short-Term Memory (w skrócie LSTM) [24,25],
reprezentującą pamięć długoterminową krótkich wzorców. Operuje ona neuronami w formie
komórek, w których istnieje dodatkowy tor pamięci z chwil poprzednich.
Warstwa wyjściowa
Warstwa ukryta
Sygnały wejściowe
Kolejne iteracje
Rys. 9.38 Ilustracja problemu zanikającego w czasie gradientu w klasycznej sieci RNN.
202
sterowanych zaworów. Typowa struktura komórki bloku pamięciowego używanej w LSTM
przedstawiona jest na rys. 9.39.
203
Rys. 9.40 Model przepływu sygnałów w czasie dla sieci LSTM złożonej z komórki pamięci w dwu
chwilach czasowych.
204
Drugi zawór reprezentowany przez środkowy mnożnik × decyduje o nowym stanie pamięci
Ct w chwili t i jest nazywany zaworem nowej pamięci. Składa się z dwu równolegle działających
warstw neuronowych. Pierwsza warstwa sigmoidalna jedno-polarna przyjmuje identyczne
wymuszenia jak warstwa neuronowa w zaworze pamięci (Xt, Ct-1, ht-1 i polaryzacja) i stanowi
przetworzoną zawartość starej pamięci. Druga warstwa operuje jedynie sygnałami Xt, ht-1 oraz
polaryzacją, a więc nie zależy od zawartości starej pamięci. Funkcja aktywacji tej warstwy jest
sigmoidą bipolarną realizowaną przez funkcję tangensa hiperbolicznego. Mnożnik decyduje o
wpływie starej pamięci na stan wyjściowy tego zaworu, który będzie następnie dodany do
zawartości starej pamięci wychodzącej z bloku pamięci (symbol sumatora) tworząc aktualny (w
chwili t) stan pamięci Ct.
Ostatnią operacją komórki pamięciowej jest wytworzenie sygnału wyjściowego ht w
aktualnej chwili czasowej t. Sygnał wyjściowy komórki jest iloczynem dwu sygnałów: aktualnego
sygnału pamięci Ct przepuszczonego przez funkcję sigmoidalną bipolarną oraz sygnału
wyjściowego z warstwy neuronowej zasilonej poprzez Xt, ht-1 oraz polaryzację (bramka
multiplikatywna z prawej strony schematu). System ten stanowi zawór wyjściowy komórki,
decydujący o tym jak duża porcja nowej pamięci zostanie przekazana na wyjście komórki, czyli
sygnału komórki, który zasili komórkę w następnej chwili czasowej.
W efekcie wysterowania poszczególnych zaworów możliwe jest przepuszczenie lub
zablokowanie określonej porcji informacji z chwil poprzednich. Na rys. 9.41 zilustrowano możliwy
wpływ informacji dostarczonej do sieci w chwili t1 na stan komórki w następnych chwilach
czasowych. Symbol „o” oznacza pełne otwarcie zaworu a symbol „–„ pełne zamknięcie. Stan
wyjścia komórek w poszczególnych chwilach czasowych w zależności od informacji z chwili t1
jest funkcją otwarcia lub zamknięcia odpowiednich zaworów i ilustrowany ciemnym stanem węzła
(informacja przechodzi) lub jasnym (przepływ informacji zablokowany).
205
Rys. 9.41 Ilustracja przepływu informacji z chwili t1 do wyjścia w kolejnych chwilach czasowych
w zależności od stanu wysterowania zaworów. Symbol „o” oznacza pełne otwarcie zaworu a
symbol „–„ pełne zamknięcie.
206
y4 = 𝑠𝑖𝑔𝑚(w4𝑐 c𝑡 + w4ℎ h𝑡−1 + 𝐰4𝑥 𝐱 𝑡 + w40 ) (9.45)
Na tej podstawie tworzone są: stan pamięciowy komórki ct oraz sygnał wyjściowy komórki ht (oba
w chwili t). Są one określone wzorami
c𝑡 = 𝑦2 ∙ y3 + c𝑡−1 y1 (9.46)
h𝑡 = 𝑦4 ∙ 𝑡𝑔ℎ(c𝑡 ) (9.47)
Przetwarzanie wsteczne sygnałów odbywa się w identyczny sposób jak w metodzie klasycznej
propagacji wstecznej (odwrócenie kierunku przepływu przy tych samych wartościach wag gałęzi
liniowej i zastąpieniu funkcji aktywacji poprzez wartość pochodnej w punkcie pracy sieci o
normalnym kierunku przepływu). W przypadku węzła realizującego mnożenie korzysta się z
zależności pochodnej iloczynu, zgodnie z którą, jeśli sygnał y jest iloczynem dwu sygnałów v1 i v2,
𝑦 = 𝑣1 (𝑤) ∙ 𝑣2 (𝑤) (9.48)
to
𝑑𝑦 𝑑𝑣 𝑑𝑣1
= 𝑣1 𝑑𝑤2 + 𝑣2 (9.49)
𝑑𝑤 𝑑𝑤
MATLAB
load pmday;data=pmday; % prognozowanie sredniej dziennej PM10
ll=size(data);ll=ll(2);
wyn=[]; ywyn=[];meansum=[]; rmsesum=[];R=[];MAEsum=[];
numTimeStepsTrain = floor(0.8*ll);
kmax=1 % liczba powtórzeń (w przypadku zespołu sieci)
for k=1:kmax
dataTrain = data(:,50:numTimeStepsTrain+1);
dataTest = data(:, numTimeStepsTrain+1:end);
mu = mean(mean(dataTrain));
sig = std(dataTrain);
dataTrainStandardized = (dataTrain - mu) / sig;
XTrain = dataTrainStandardized(:,1:end-1);
YTrain = dataTrainStandardized(:,2:end);
numFeatures = 1;
numResponses =1;
numHiddenUnits = 400
layers = [ ...
sequenceInputLayer(numFeatures)
lstmLayer(numHiddenUnits)
dropoutLayer(0.5)
fullyConnectedLayer(numResponses)
207
regressionLayer];
options = trainingOptions('adam', ...
'MaxEpochs',300, ...
'ExecutionEnvironment','gpu',...
'GradientThreshold',1, ...
'InitialLearnRate',0.005, ...
'LearnRateSchedule','piecewise', ...
'LearnRateDropPeriod',125, ...
'LearnRateDropFactor',0.5, ...
'Verbose',0, ...
'Plots','training-progress');
%Training
net = trainNetwork(XTrain,YTrain,layers,options);
dataTestStandardized = (dataTest - mu) / sig;
XTest = dataTestStandardized(:,1:end-1);
net = predictAndUpdateState(net,XTrain);
[net,YPred] = predictAndUpdateState(net,YTrain(:,end));
numTimeStepsTest = numel(XTest(1,:));
for i = 2:numTimeStepsTest
[net,YPred(:,i)] = predictAndUpdateState(net,YPred(:,i-1),'ExecutionEnvironment','cpu');
end
%Unstandardize the predictions using the parameters calculated earlier.
YPred = sig*YPred + mu;
%The training progress plot reports the root-mean-square error (RMSE)
YTest = dataTest(:, 2:end);
%If you have access to the actual values of time steps between predictions, then you can update
%the network state with the observed values instead of the predicted values. First, initialize
%the network state. To make predictions on a new sequence, reset the network state using
%resetState
net = resetState(net);
net = predictAndUpdateState(net,XTrain);
%Predict on each time step. For each prediction, predict the next time step using the observed
value of the previous time step. Set the 'ExecutionEnvironment' option of predictAndUpdateState
to 'cpu'.
YPred = [];
numTimeStepsTest = length(XTest(1,:));
for i = 1:numTimeStepsTest
[net,YPred(:,i)] = predictAndUpdateState(net,XTest(:,i),'ExecutionEnvironment','cpu');
end
%Unstandardize the predictions using the parameters calculated for learning data.
YPred = sig*YPred + mu;
MAPE=mean(mean((abs((YPred-YTest)))./(abs((YTest)))*100))
meansum=[meansum MAPE];
rmse = sqrt(mean((YPred-YTest).^2));
rmsesum=[rmsesum rmse]
MAE=mean(abs(YPred-YTest));
MAEsum=[MAEsum MAE]
r1=corrcoef(YTest, YPred);
R=[R r1(1,2)]
wyn=[wyn;YPred];
%Compare the forecasted values with the test data.
figure
subplot(2,1,1)
plot(YTest(:))
hold on
plot(YPred(:),'.-')
hold off
legend(["Rzeczywiste" "Prognozowane"])
ylabel("Prognoza")
title("Wartosci rzeczywiste i prognozowane")
subplot(2,1,2)
stem(YPred(:) - YTest(:))
xlabel("Dni")
ylabel("Błąd prognozy")
title("MAPE = " + MAPE)
end
208
Dane pomiarowe zawierają 1534 dni, przy czym 80% danych zostało użytych do uczenia a
pozostałe 20% do testowania Wyniki przedstawione poniżej dotyczą pojedynczej sieci (kmax=1).
Błąd średni procentowy MAPE na danych testujących wyniósł 9.23%, błąd średni absolutny
MAE=2.98μg/m3 a współczynnik korelacji wartości prognozowanych i rzeczywistych był równy
0.68. Na rys. 9.42 przedstawiono wykresy zmienności wartości rzeczywistych PM10 w kolejnych
dniach i wielkości prognozowanej przez sieć (rysunek górny). Na rysunku dolnym przedstawiono
różnice między wartościami rzeczywistymi i prognozowanymi w kolejnych dniach testu.
Rys. 9.42 Wyniki graficzne prognozy stężenia PM10 dla danych testowych nie uczestniczących
w uczeniu
209