Tworzenie rewolucyjnych sieci neuronowych (CNN) w celu ułatwienia rozpoznawania obrazu

1. Zanim zaczniesz

Z tego modułu dowiesz się, jak korzystać z CNN do ulepszania modeli klasyfikacji obrazów.

Wymagania wstępne

Warsztaty są realizowane w 2 poprzednich częściach: Tworzenie modelu wizyjnego komputera, w którym omawiamy niektóre kody, których użyjesz w tym miejscu, oraz ćwiczenia dotyczące budowania rewolucji i pulaowania, gdzie prezentujemy sploty i pula zasobów.

Czego się nauczysz:

  • Jak poprawić wizję i dokładność komputera dzięki splotowi

Co stworzysz

  • Warstwy usprawniające działanie sieci neuronowych

Czego potrzebujesz

Kod do reszty ćwiczeń z programowania znajdziesz w Colab.

Musisz też mieć zainstalowane narzędzie TensorFlow, a także biblioteki zainstalowane w poprzednim kursie.

2. Poprawa dokładności rozpoznawania obrazów dzięki splotowi

Wiesz już, jak rozpoznawać obrazy z modą przy użyciu głębokiej sieci neuronowej (DNN) złożonej z 3 warstw – warstwy wejściowej (w kształcie danych wejściowych), warstwy wyjściowej (w kształcie żądanego danych wyjściowych) i ukrytej warstwy. Eksperymentowaliśmy z kilkoma parametrami, które wpływają na ostateczną dokładność, takich jak różne rozmiary ukrytych warstw i liczba epoki epoki.

Dla ułatwienia jeszcze raz zastosuj cały kod. Uruchom ją i zanotuj dokładność testu, która zostanie wydrukowana na końcu.

import tensorflow as tf
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(128, activation='relu'),
  tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.fit(training_images, training_labels, epochs=5)
test_loss, test_accuracy = model.evaluate(test_images, test_labels)
print ('Test loss: {}, Test accuracy: {}'.format(test_loss, test_accuracy*100))

Twój poziom dokładności wynosi około 89% podczas trenowania i 87% do walidacji. Aby jeszcze bardziej zwiększyć skuteczność, użyj splotów, które zawężają zawartość obrazu, by skoncentrować się na określonych, wyjątkowych cechach.

Jeśli przetwarzasz zdjęcia za pomocą filtra, będą one wyglądać bardzo dobrze.

Krótko mówiąc, tworzysz tablicę (zazwyczaj 3 x 3 lub 5 x 5) i przekazujesz ją nad obrazem. Zmieniając piksele bazowe na podstawie formuły w tej macierzy, możesz wykonywać różne czynności, na przykład wykrywać krawędzie. Na przykład do wykrywania krawędzi, w której środkowa komórka ma 8, a wszystkich jej sąsiadów, wartość -1. W takim przypadku dla każdego piksela należy pomnożyć wartość przez 8 i odjąć wartość każdego sąsiada. Zrób to dla każdego piksela, a w efekcie otrzymasz nowy obraz z ulepszonymi krawędziami.

Jest to idealne rozwiązanie w przypadku rozpoznawania obrazów, ponieważ ulepszanie takich funkcji jak krawędzie komputera pozwala odróżnić jeden element od drugiego. Co więcej, ilość potrzebnych informacji jest znacznie mniejsza, ponieważ trenujesz tylko wyróżnione funkcje.

To koncepcja splotu sieci neuronowych. Dodaj kilka warstw, aby przejść przez gęstość, zanim przejdziesz do gęstych warstw. Dzięki temu informacje wysyłane do gęstych warstw staną się bardziej precyzyjne i dokładniejsze.

3. Wypróbuj kod

Uruchom następujący kod. Ta sama sieć neuronowa co wcześniej, ale tym razem z warstwą splotową. To potrwa dłużej, ale przyjrzyj się wpływowi na dokładność:

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.reshape(60000, 28, 28, 1)
training_images=training_images / 255.0
test_images = test_images.reshape(10000, 28, 28, 1)
test_images=test_images / 255.0
model = tf.keras.models.Sequential([
  tf.keras.layers.Conv2D(64, (3, 3), activation='relu', input_shape=(28, 28, 1)),
  tf.keras.layers.MaxPooling2D(2, 2),
  tf.keras.layers.Conv2D(64, (3, 3), activation='relu'),
  tf.keras.layers.MaxPooling2D(2,2),
  tf.keras.layers.Flatten(),
  tf.keras.layers.Dense(128, activation='relu'),
  tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.summary()
model.fit(training_images, training_labels, epochs=5)
test_loss, test_accuracy = model.evaluate(test_images, test_labels)
print ('Test loss: {}, Test accuracy: {}'.format(test_loss, test_accuracy*100))

Prawdopodobnie wzrośnie ona o 93% w przypadku danych treningowych i 91% w przypadku danych weryfikacyjnych.

A teraz spróbuj uruchomić ją jeszcze raz, powiedzmy około 20, i poznaj wyniki. Wyniki szkolenia mogą wydawać się bardzo dobre, ale wyniki weryfikacji mogą się pogorszyć z powodu zjawiska nazywanego nadmiernym dopasowaniem.

Nadmierne dopasowanie występuje, gdy sieć uczy się zbyt dobrze z zestawu danych treningowych, przez co jest w stanie rozpoznawać tylko te dane i w rezultacie mniej skuteczne jest przeglądanie innych danych. Jeśli na przykład trenujesz tylko obcasy, sieć może być bardzo pomocna w zidentyfikowaniu obcasów, ale trampki mogą go mylić.

Spójrz na kod ponownie i zobacz krok po kroku, jak zbudowane były rewolucje.

4. Zbieranie danych

Pierwszym krokiem jest zebranie danych.

Zauważysz tu zmianę i dane szkoleniowe potrzebne do zmiany kształtu. To wynika z tego, że pierwszy splot liczy się jako jeden tensor zawierający wszystko, więc zamiast 60 000 elementów 28 x 28 x 1 na liście masz jedną listę 4D o wymiarach 60 000 x 28 x 28 x 1 i tę samą wersję dla obrazów testowych. Jeśli tego nie zrobisz, podczas trenowania wystąpi błąd, ponieważ splot nie rozpozna kształtu.

import tensorflow as tf
mnist = tf.keras.datasets.fashion_mnist
(training_images, training_labels), (test_images, test_labels) = mnist.load_data()
training_images=training_images.reshape(60000, 28, 28, 1)
training_images = training_images/255.0
test_images = test_images.reshape(10000, 28, 28, 1)
test_images = test_images/255.0

5. Zdefiniuj model

Następnie zdefiniuj model. Zamiast warstwy wejściowej u góry dodajesz warstwę splotową. Parametry:

  • Liczba splotów, które chcesz wygenerować. Warto zacząć od wartości 32.
  • Rozmiar macierzy splotu, w tym przypadku z siatką 3 x 3.
  • Należy aktywować funkcję aktywacji. W tym przypadku jest to relu.
  • W pierwszej warstwie kształt danych wejściowych.

Podążasz za warkoczem, korzystając z maksymalnej warstwy sadzawkowej, która ma na celu skompresowanie obrazu przy zachowaniu zawartości obiektów podkreślonych przez odniesienie. Określając (2,2) jako maksymalną sumę, efektem jest zmniejszenie rozmiaru obrazu o 4. Tworzy tablicę pikseli 2 x 2 i wybiera największą wartość w pikselach, zmieniając 4 piksele w 1. Powtarza je w obrazie, zmniejsza o połowę liczbę pikseli w poziomie, a o połowę w pionie.

Aby sprawdzić rozmiar i kształt sieci, możesz zadzwonić pod numer model.summary(). Zauważ, że po każdej maksymalnej warstwie puli rozmiar obrazu jest zmniejszany w następujący sposób:

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_2 (Conv2D)            (None, 26, 26, 64)        640       
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 13, 13, 64)        0         
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 11, 11, 64)        36928     
_________________________________________________________________
max_pooling2d_3 (MaxPooling2 (None, 5, 5, 64)          0         
_________________________________________________________________
flatten_2 (Flatten)          (None, 1600)              0         
_________________________________________________________________
dense_4 (Dense)              (None, 128)               204928    
_________________________________________________________________
dense_5 (Dense)              (None, 10)                1290      
=================================================================

Oto pełny kod CNN:

model = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),
tf.keras.layers.MaxPooling2D(2, 2),
#Add another convolution
tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2, 2),
#Now flatten the output. After this you'll just have the same DNN structure as the non convolutional version
tf.keras.layers.Flatten(),
#The same 128 dense layers, and 10 output layers as in the pre-convolution example:
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')
])

6. Skompilowanie i wytrenowanie modelu

Kompilowanie modelu, wywoływanie metody dopasowania w celu przeprowadzenia trenowania oraz ocena straty i dokładności ze zbioru testowego.

model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.fit(training_images, training_labels, epochs=5)
test_loss, test_acc = model.evaluate(test_images, test_labels)
print ('Test loss: {}, Test accuracy: {}'.format(test_loss, test_acc*100))

7. Wizualizacja rewolucji i segregacji

Ten kod pokazuje rewolucje graficznie. print (test_labels[:100]) wyświetla pierwsze 100 etykiet w zestawie testowym i widać, że etykiety w indeksie 0, indeksu 23 i indeksu 28 to ta sama wartość (9). To buty. Zobacz, jaki wpływ na to mają poszczególne koncepcje. Poznasz ich typowe cechy. Kiedy DNN uczy się tych danych, może wykorzystać nieco mniej informacji i możliwe, że w przypadku obu tych zjawisk łączy się oba cechy.

print(test_labels[:100])
[9 2 1 1 6 1 4 6 5 7 4 5 7 3 4 1 2 4 8 0 2 5 7 9 1 4 6 0 9 3 8 8 3 3 8 0 7
 5 7 9 6 1 3 7 6 7 2 1 2 2 4 4 5 8 2 2 8 4 8 0 7 7 8 5 1 1 2 3 9 8 7 0 2 6
 2 3 1 2 8 4 1 8 5 9 5 0 3 2 0 6 5 3 6 7 1 8 0 1 4 2]

Teraz możesz wybrać niektóre obrazy odpowiadające tym etykietom i wyrenderować je tak, jak wyglądają podczas kręcenia obrazów. Zatem w poniższym kodzie FIRST_IMAGE, SECOND_IMAGE i THIRD_IMAGE to indeksy wartości 9, kozaki za kostkę.

import matplotlib.pyplot as plt
f, axarr = plt.subplots(3,4)
FIRST_IMAGE=0
SECOND_IMAGE=23
THIRD_IMAGE=28
CONVOLUTION_NUMBER = 6
from tensorflow.keras import models
layer_outputs = [layer.output for layer in model.layers]
activation_model = tf.keras.models.Model(inputs = model.input, outputs = layer_outputs)
for x in range(0,4):
  f1 = activation_model.predict(test_images[FIRST_IMAGE].reshape(1, 28, 28, 1))[x]
  axarr[0,x].imshow(f1[0, : , :, CONVOLUTION_NUMBER], cmap='inferno')
  axarr[0,x].grid(False)
  f2 = activation_model.predict(test_images[SECOND_IMAGE].reshape(1, 28, 28, 1))[x]
  axarr[1,x].imshow(f2[0, : , :, CONVOLUTION_NUMBER], cmap='inferno')
  axarr[1,x].grid(False)
  f3 = activation_model.predict(test_images[THIRD_IMAGE].reshape(1, 28, 28, 1))[x]
  axarr[2,x].imshow(f3[0, : , :, CONVOLUTION_NUMBER], cmap='inferno')
  axarr[2,x].grid(False)

Powinno być widać coś podobnego do tego, w którym rewolucja najistotniejsza jest podeszwa butów, co sprawia, że jest to powszechna cecha wszystkich butów.

6c9109bcc640a1ec.png

8. Ćwiczenia

Ćwiczenie 1

Edytuj splot. Zmień liczbę splotów z 32 na 16 lub 64. Jaki ma to wpływ na dokładność i czas trenowania?

Ćwiczenie 2

Usuń końcowy splot. Jaki ma to wpływ na dokładność lub czas trenowania?

Ćwiczenie 3

Dodaj więcej parowozów. Jakie to ma znaczenie?

Ćwiczenie 4

Usuń wszystkie sploty oprócz pierwszego. Jakie to ma znaczenie? Poeksperymentuj z nią.

9. Gratulacje

Udało Ci się utworzyć pierwszą CNN! Aby dowiedzieć się więcej o tym, jak jeszcze bardziej ulepszać modele rozpoznawania obrazów, przeczytaj artykuł Korzystanie z sieci neuronowych splotowych (CNN) ze złożonymi obrazami.