Tworzenie modelu rozpoznawania obrazów za pomocą TensorFlow

1. Zanim zaczniesz

W ramach ćwiczenia z programowania stworzysz model rozpoznawania obrazów, który pozwoli Ci rozpoznać przedmioty za pomocą TensorFlow.

Wymagania wstępne

  • Solidna znajomość Pythona
  • Podstawowe umiejętności programistyczne

Czego się nauczysz:

Dzięki nim dowiesz się:

  • Wytrenuj sieć neuronową tak, by rozpoznawała artykuły odzieżowe
  • Wykonaj serię ćwiczeń, aby przeprowadzić Cię przez eksperymentowanie z różnymi warstwami sieci

Co stworzysz

  • Sieć neuronowa, która identyfikuje artykuły odzieżowe

Czego potrzebujesz

Jeśli nigdy nie udało Ci się utworzyć sieci neuronowej do obsługi obrazów komputerowych w TensorFlow, możesz użyć Colaboratory – środowiska przeglądarki, które zawiera wszystkie wymagane zależności. Kod do reszty ćwiczeń z programowania znajdziesz w Colab.

Jeśli nie, głównym językiem, którego używasz do trenowania modeli, jest Python. Musisz go więc zainstalować. Oprócz tego potrzebne są też TensorFlow i biblioteka NumPy. Dowiedz się więcej o TensorFlow. Zainstaluj NumPy tutaj

2. Rozpocznij programowanie

Najpierw zapoznaj się z notatkami Colab.

Zacznij od zaimportowania TensorFlow.

import tensorflow as tf
print(tf.__version__)

Wytrenujesz sieć neuronową tak, by rozpoznawała ubrania z popularnego zbioru danych o nazwie MNIST. Zawiera 70 000 ubrań w 10 różnych kategoriach. Każda odzież jest przedstawiona w obrazie 28 x 28. Oto kilka przykładów:

Etykiety powiązane ze zbiorem danych:

Etykieta

Description

0

T-shirt/górny

1

Spodnie

2

Swetry

3

Sukienka

4

Płaszcz

5

Sandały

6

Koszula

7

Tenisówki

8

Torba

9

Kozaki za kostkę

Dane MNIST są dostępne w interfejsie API tf.keras.datasets. Wczytaj ją w ten sposób:

mnist = tf.keras.datasets.fashion_mnist

Wywołanie load_data tego obiektu daje 2 zestawy 2 list: wartości szkolenia i testów, które reprezentują grafikę pokazującą ubrania i etykiety.

(training_images, training_labels), (test_images, test_labels) = mnist.load_data()

Jak wyglądają te wartości? Wydrukuj obraz treningowy i etykietę trenowania. Możesz eksperymentować z różnymi indeksami w tablicy.

import matplotlib.pyplot as plt
plt.imshow(training_images[0])
print(training_labels[0])
print(training_images[0])

Dane wydruku elementu 0 wyglądają tak:

Zauważysz, że wszystkie wartości są liczbami całkowitymi z zakresu od 0 do 255. Wytrenowanie sieci neuronowej jest łatwiejsze, ponieważ wszystkie wartości są traktowane jako wartości z zakresu od 0 do 1. Jest to proces normalizacji. Python może w prosty sposób znormalizować listę w taki sposób, bez zapętlenia.

training_images  = training_images / 255.0
test_images = test_images / 255.0

Dobrym przykładem może być strona 42, która jest inna niż ta w indeksie 0.

Możesz się teraz zastanawiać, dlaczego istnieją 2 zbiory danych – trenowanie i testowanie.

Chodzi o to, by mieć jeden zbiór danych do trenowania i drugi zbiór danych, których model jeszcze nie napotkał, by sprawdzić, jak dobrze potrafi klasyfikować wartości. Gdy zakończysz, będziesz potrzebować modelu z danymi, które wcześniej były niewidoczne. Bez osobnych danych testowych możesz ryzyko związane z siecią zapamiętać tylko dane treningowe bez uogólniania jego wiedzy.

3. Projektowanie modelu

Teraz zaprojektuj model. Będziesz mieć trzy warstwy. Przeanalizuj je kolejno i poznaj różne typy warstw i parametry użyte w każdej z nich.

model = tf.keras.models.Sequential([tf.keras.layers.Flatten(), 
                                    tf.keras.layers.Dense(128, activation=tf.nn.relu), 
                                    tf.keras.layers.Dense(10, activation=tf.nn.softmax)])
  • Sequential definiuje sekwencję warstw w sieci neuronowej.
  • Flatten przyjmuje kwadrat i staje się wektorem jednowymiarowym.
  • Dense dodaje warstwę neuronów.
  • Funkcje Activation określają, co zrobić z każdą warstwą neuronów. Dostępnych jest wiele opcji, ale na razie używaj ich:
  • Relu tak oznacza, że jeśli X jest większe od 0, zwracana jest wartość X, w przeciwnym razie zwraca 0. Przekazuje do następnej warstwy w sieci tylko wartość 0 lub większą.
  • Softmax przyjmuje zbiór wartości i skutecznie wybiera największą z nich. Jeśli np. wynik ostatniej warstwy wygląda tak: [0,1, 0,1, 0.05, 0.1, 9.5, 0.1, 0.05, 0.05, 0.05], oszczędza to czas na sortowanie od największej wartości – zwraca [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,0

4. Skompilowanie i wytrenowanie modelu

Teraz, gdy model jest już zdefiniowany, musisz go utworzyć. Utwórz model, kompilując go za pomocą funkcji optimizer i loss, a następnie trenuj na danych treningowych i etykietach. Model powinien określać zależność między danymi treningowymi a ich etykietami treningowymi. Później będziesz potrzebować modelu do przypominania danych treningowych, a następnie prognozuj, jak powinny wyglądać.

Zauważ, że metrics= to parametr, który umożliwia TensorFlow raportowanie dokładności trenowania, sprawdzając przewidywane wyniki względem znanych odpowiedzi (etykiet).

model.compile(optimizer = tf.keras.optimizers.Adam(),
              loss = 'sparse_categorical_crossentropy',
              metrics=['accuracy'])

model.fit(training_images, training_labels, epochs=5)

Po uruchomieniu skryptu model.fit dochodzi do utraty i dokładności:

Epoch 1/5
60000/60000 [=======] - 6s 101us/sample - loss: 0.4964 - acc: 0.8247
Epoch 2/5
60000/60000 [=======] - 5s 86us/sample - loss: 0.3720 - acc: 0.8656
Epoch 3/5
60000/60000 [=======] - 5s 85us/sample - loss: 0.3335 - acc: 0.8780
Epoch 4/5
60000/60000 [=======] - 6s 103us/sample - loss: 0.3134 - acc: 0.8844
Epoch 5/5
60000/60000 [=======] - 6s 94us/sample - loss: 0.2931 - acc: 0.8926

Po zakończeniu trenowania modelu na końcu ostatniej epoki pojawi się wartość dokładności. Może wyglądać np.tak jak na przykład 0,8926. Dowiesz się z niego, że Twoja sieć neuronowa jest dokładna w 89%, więc nie możesz klasyfikować danych treningowych. Inaczej mówiąc, udało się znaleźć dopasowanie do wzorca między obrazem a etykietami, które sprawdzało się w 89% przypadków. Niezbyt dobrze, ale nieźle, biorąc pod uwagę, że szkolenie trenowało tylko przez pięć epok i szybko zostało wykonane.

5. Testowanie modelu

Jak wyglądałby model na podstawie danych, których nie udało się wykryć? Właśnie dlatego masz zestaw testów. Wywołujesz model.evaluate i przekazujesz te 2 zestawy. Funkcja raportuje utratę każdego z nich. Spróbuj:

model.evaluate(test_images, test_labels)

Oto dane wyjściowe:

10000/10000 [=====] - 1s 56us/sample - loss: 0.3365 - acc: 0.8789
[0.33648381242752073, 0.8789]

W tym przykładzie dokładność podana na poziomie 0,8789 jest prawidłowa, co oznacza około 88% dokładności. (wartości mogą być nieco inne).

Zgodnie z oczekiwaniami model nie jest tak skuteczny w przypadku nieznanych danych jak dane, na których został wytrenowany. Gdy dowiesz się więcej o TensorFlow, znajdziesz sposoby na ulepszenie tej funkcji.

Aby kontynuować naukę, przejdź do ćwiczeń w następnym kroku.

6. Ćwiczenia poznawcze

Ćwiczenie 1

Na potrzeby pierwszego ćwiczenia uruchom ten kod:

classifications = model.predict(test_images)
print(classifications[0])

Tworzy zestaw klasyfikacji dla każdego obrazu testowego, a następnie drukuje pierwszy wpis w tych ocenach. Gdy go uruchomisz, pojawi się lista liczb. Jak myślisz, dlaczego tak jest i co oznaczają te liczby?

Spróbuj uruchomić print(test_labels[0]), a otrzymasz 9. Czy pomaga Ci zrozumieć, dlaczego tak wygląda lista?

Wynikiem działania modelu jest lista 10 cyfr. Te liczby to prawdopodobieństwo, że sklasyfikowana wartość to odpowiednia etykieta. Na przykład pierwsza wartość na liście to prawdopodobieństwo, że odzież jest klasą 0, a kolejna 1. Zwróć uwagę, że wszystkie są bardzo mało prawdopodobne. Ze względu na Softmax prawdopodobieństwo na tej liście wynosi 1,0.

Lista i etykieta są oparte na 0, więc kostki mają etykietę 9, co oznacza, że jest ona dziesiątą z 10 klas. Lista, gdzie 10 element jest najwyższą wartością, oznacza, że sieć neuronowa przewiduje, że klasyfikowany produkt to najprawdopodobniej kostka.

Ćwiczenie 2

Spójrz na warstwy w modelu. Eksperymentuj z różnymi wartościami w gęstej warstwie 512 neuronów.

Jakie wyniki można uzyskać, jeśli chodzi o straty i czas trenowania? Dlaczego uważasz, że...

Jeśli np. zwiększysz liczbę neuronów do 1024, musisz wykonać więcej obliczeń, co spowalnia ten proces. Jednak w tym przypadku mają one korzystny wpływ, ponieważ model jest bardziej dokładny. Nie zawsze jest to lepsze. Możesz bardzo szybko zniechęcić się do malejących zwrotów.

Ćwiczenie 3

Co się stanie, gdy usuniesz warstwę Flatten() Dlaczego uważasz, że...

Pojawia się błąd dotyczący kształtu danych. Obecnie szczegóły błędu mogą wydawać się niejasne, ale ukazuje ogólną zasadę, że pierwsza warstwa w Twojej sieci powinna mieć ten sam kształt co dane. W tej chwili dane to 28 x 28, a 28 warstw po 28 neuronów jest niewykonalnych, dlatego warto spłaszczyć ten rozmiar 28,28 do 784 x 1.

Zamiast pisać cały kod, dodaj warstwę Flatten() na początku. Tablice zostaną później wczytane do modelu, a następnie zostaną automatycznie spłaszczone.

Ćwiczenie 4

Pamiętaj o warstwach końcowych (wyjściowych). Dlaczego jest ich 10? Co się stanie, jeśli kwota będzie inna niż 10?

Spróbuj wytrenować sieć z punktu 5. Gdy znajdzie nieoczekiwaną wartość, pojawi się błąd. Kolejna ogólna zasada: liczba neuronów w ostatniej warstwie powinna odpowiadać liczbie klas, które klasyfikujesz. W tym przypadku są to cyfry od 0 do 9, czyli 10 z nich, dlatego w ostatniej warstwie powinno być 10 neuronów.

Ćwiczenie 5

Zastanów się nad wpływem dodatkowych warstw w sieci. Co się stanie, jeśli dodasz kolejną warstwę z warstwą 512 i ostatnią warstwę z 10?

Nie ma to znaczącego wpływu, ponieważ są to stosunkowo proste dane. W przypadku bardziej złożonych danych często konieczne są dodatkowe warstwy.

Ćwiczenie 6

Przed trenowaniem udało się znormalizować dane, zmieniając wartości z zakresu od 0 do 255 na wartości od 0 do 1. Jakie to będzie skutki? Oto kompletny kod, który warto wypróbować (2 wiersze normalizujące dane)

Dlaczego uważasz, że uzyskujesz inne wyniki? Świetną odpowiedź znajdziesz na stronie Stack Overflow.

import tensorflow as tf
print(tf.__version__)
mnist = tf.keras.datasets.fashion_mnist
(training_images, training_labels), (test_images, test_labels) = mnist.load_data()
#training_images=training_images/255.0
#test_images=test_images/255.0
model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(),
  tf.keras.layers.Dense(512, activation=tf.nn.relu),
  tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy')
model.fit(training_images, training_labels, epochs=5)
model.evaluate(test_images, test_labels)
classifications = model.predict(test_images)
print(classifications[0])
print(test_labels[0])

7. Wywołania zwrotne

Wcześniej podczas trenowania dodatkowych okresów wystąpił u Ciebie problem z stratą czasu. Może minąć trochę czasu, zanim ukończysz szkolenie, ale możesz się spodziewać, że zatrzymasz szkolenie, gdy osiągniesz odpowiednią wartość, na przykład dokładności na poziomie 95%. Skoro jesteś w stanie to osiągnąć po 3 czasach, to nie czekaj, aż cała epoka się zakończy.

Tak jak w przypadku każdego innego programu, możesz do nich oddzwonić. Zobacz, jak to działa:

import tensorflow as tf

class myCallback(tf.keras.callbacks.Callback):
  def on_epoch_end(self, epoch, logs={}):
    if(logs.get('accuracy')>0.95):
      print("\nReached 95% accuracy so cancelling training!")
      self.model.stop_training = True

callbacks = myCallback()
mnist = tf.keras.datasets.fashion_mnist
(training_images, training_labels), (test_images, test_labels) = mnist.load_data()
training_images=training_images/255.0
test_images=test_images/255.0
model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(),
  tf.keras.layers.Dense(512, activation=tf.nn.relu),
  tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.fit(training_images, training_labels, epochs=5, callbacks=[callbacks])

8. Gratulacje

Udało Ci się stworzyć swój pierwszy model wizyjny. Aby dowiedzieć się, jak ulepszyć swoje modele rozpoznawania obrazów, przeczytaj artykuł Tworzenie rewolucji i basen.