W tym artykule poznasz trzy sposoby tworzenia modeli głębokich sieci neuronowych przy użyciu Keras i Tensorflow 2.0 Poznasz ich zalety i ograniczenia, a także zobaczysz przykłady zastosowania tych metod.
Keras i Tensorflow 2.0 udostępniają trzy sposoby budowania różnych architektur głębokich sieci neuronowych:
- Sequential API
- Functional API
- Subclassing API
Sequential API
Sequential API to najprostszy możliwy sposób tworzenia głębokich sieci neuronowych. Jak sama nazwa mówi za pomocą tej metody możemy budować sieci neuronowe, które składają się tylko z pojedynczego stosu warstw połączonych sekwencyjnie.
Poniżej możesz zobaczyć jak stworzyć prostą architekturę sieci neuronowej używając Sequential API dla dobrze znanego problemu Fashion MNIST .
model = keras.models.Sequential()
model.add(keras.layers.Flatten(input_shape=[28, 28]))
model.add(keras.layers.Dense(300, activation="relu"))
model.add(keras.layers.Dense(100, activation="relu"))
model.add(keras.layers.Dense(10, activation="softmax"))
Jak widać powyżej, warstwy dodajemy sekwencyjnie krok po kroku. Pierwszą warstwą jest warstwa Flatten, która konwertuje nasze obrazy wejściowe na tablice 1D. Ta warstwa nie posiada żadnych parametrów, a jej zadaniem jest wykonanie wstępnego przetwarzania. Flatten jest pierwszą warstwą, więc musimy określić input_shape i w naszym przypadku dla Fashion MNIST jest to input_shape=[28, 28]. Następne dwie warstwy to gęste warstwy ukryte (Dense layers), składające się odpowiednio z 300 neuronów i 200 neuronów. Nasze ukryte warstwy Dense używają funkcji aktywacji ReLU. Na koniec dodajemy warstwę wyjściową z 10 neuronami (po jednym na klasę) i tym razem używamy funkcji aktywacji Softmax, ponieważ klasy są ekskluzywne (mamy dziesięć klas w zbiorze danych Fashion MNIST, które są różnymi typami odzieży).
Functional API
Jednakże, podczas gdy modele sekwencyjne są bardzo powszechne, czasami przydatne lub nawet konieczne jest budowanie sieci neuronowych o bardziej złożonych topologiach, lub z wieloma wejściami lub wyjściami. W tym celu Keras udostępnia API funkcyjne (Functional API).
Dzięki Functional API jest możliwe:
- Łatwość współdzielenia warstw wewnątrz architektury
- Tworzenie bardziej złożonych modeli
- Projektowanie skierowanych grafów acyklicznych
- Posiadanie wielu wejść i wielu wyjść
Warto podkreślić, że każdy możliwy model sekwencyjny może być również stworzony przy użyciu Functional API.
Szeroka i głęboka sieć neuronowa (Wide and Deep NN architecture) jest jednym z przykładów architektury niesekwencyjnej. Architektura ta pozwala na uczenie się głębokich wzorców za pomocą ścieżki głębokiej i prostych reguł za pomocą ścieżki krótkiej, ale powiedzmy, że chcemy wysłać dwa podzbiory cech jeden przez ścieżkę krótką, a drugi ewentualnie nakładający się przez ścieżkę głęboką. Jak widać na poniższym rysunku, mamy krótką i głęboką ścieżkę wysyłania cech do DNN. W przeciwieństwie zwykłe, sekwencyjne MLP zmusza, żeby wszystkie dane przepływały przez cały stos warstw.
Załóżmy, że chcesz wysłać pięć cech przez szeroką ścieżkę i sześć cech przez głęboką ścieżkę. Poniżej możesz zobaczyć możliwą architekturę dla przykładu pokazanego na rysunku przy użyciu Functional API:
input_A = keras.layers.Input(shape=[5], name="wide_input")
input_B = keras.layers.Input(shape=[6], name="deep_input")
hidden1 = keras.layers.Dense(30, activation="relu")(input_B)
hidden2 = keras.layers.Dense(30, activation="relu")(hidden1)
concat = keras.layers.concatenate([input_A, hidden2])
output = keras.layers.Dense(1, name="output")(concat)
model = keras.Model(inputs=[input_A, input_B], outputs=[output])
Kod nie wymaga wyjaśnień poza jedną rzeczą, z której można wywnioskować dlaczego ten sposób nazywany jest funkcyjnym. Spójrzmy na pierwszą gęstą warstwę ukrytą, gdy tylko zostanie utworzona, zauważmy, że wywołujemy ją jak funkcję, przekazując jej dane wejściowe. To samo możesz zaobserwować w drugiej warstwie ukrytej i warstwie wyjściowej, gdzie przekazujemy konkatenację wejścia A i wyników z drugiej warstwy ukrytej.
Subclassing API
Ostatnią jak dotąd metodą implementacji architektury modelu za pomocą Keras i TensorFlow 2.0 jest użycie Subclassing API. Klasa Model jest klasą bazową w Keras używaną do definiowania architektury modelu. Ponieważ Keras wykorzystuje OOP, możemy dziedziczyć klasę Model i stworzyć naszą własną definicję architektury.
Po prostu dziedzicz klasę Model i stwórz wszystkie warstwy, których potrzebujesz w konstruktorze, a następnie użyj ich do obliczeń, które chcesz wykonać w metodzie call(). Poniższy kod daje nam taki sam model jak ten, który właśnie zbudowaliśmy za pomocą Functional API:
class WideAndDeepModel(keras.Model):
def __init__(self, units=30, activation="relu", **kwargs):
super().__init__(**kwargs)
self.hidden1 = keras.layers.Dense(
units, activation=activation)
self.hidden2 = keras.layers.Dense(
units, activation=activation)
self.output = keras.layers.Dense(1)
def call(self, inputs):
input_A, input_B = inputs
hidden1 = self.hidden1(input_B)
hidden2 = self.hidden2(hidden1)
concat = keras.layers.concatenate([input_A, hidden2])
output = self.main_output(concat)
return output
model = WideAndDeepModel()
Subclassing API jest najbardziej elastycznym sposobem budowania sieci neuronowych, ale niestety wiąże się z kosztami. Użycie Subclassing API jest znacznie trudniejsze do wykorzystania niż jakikolwiek inny sposób. Metoda summary daje nam jedynie listę warstw bez informacji o tym, jak są one połączone. Jest to znacznie trudniejsze do debugowania, a Keras nie może tego zapisać, więc jeśli naprawdę nie potrzebujesz tej dodatkowej elastyczności, powinieneś trzymać się API sekwencyjnego lub API funkcyjnego.
Dlaczego właściwie ten sposób jest używany, skoro ma tyle wad?
Egzotyczne architektury tworzone szczególnie przez naukowców są bardzo trudne lub wręcz w ogóle niemożliwe do zaimplementowania przy użyciu sekwencyjnego i funkcyjnego API. Naukowcy chcą mieć kontrolę nad wszystkim, co tworzą, nad każdym możliwym niuansem sieci i procesu szkolenia. W większości przypadków nie ma to miejsca w firmach, gdzie używa się zwykłych i czasami prostych architektur.
Bibliografia:
- Hands-on Machine Learning with Scikit-Learn, Keras & TensorFlow by Aurélien Géron
- Zdjęcie zrobione przez Nubelson Fernandes na Unsplash