Formatowanie danych dla TensorFlow
W pierwszej części tej serii blogów przedstawiono zalety korzystania z relacyjnej bazy danych do przechowywania i eksploracji danych obrazów przy użyciu prostych instrukcji SQL. W tym samouczku, część 2, dane użyte w części pierwszej będą dostępne z bazy danych MariaDB Server i przekonwertowane na struktury danych wymagane przez TensorFlow. Wyniki zastosowania modelu do klasyfikacji nowych obrazów będą przechowywane w tabeli relacyjnej do dalszej analizy.
To jest krótki samouczek programu TensorFlow ze szczegółami opisanymi na bieżąco. Jeśli nie znasz podstawowych pojęć, dobrym miejscem do rozpoczęcia jest ten samouczek TensorFlow „Podstawowa klasyfikacja:Klasyfikuj obrazy odzieży”. Niektóre przykłady i kod z samouczka są tutaj używane.
Potrzebne dodatkowe pakiety
Do zbudowania i szkolenia modelu klasyfikacji obrazów potrzebne są dodatkowe pakiety:
- Marynowane implementuje protokoły binarne do serializacji i deserializacji struktury obiektów Pythona.
- NumPy zapewnia obsługę dużych, wielowymiarowych tablic i macierzy, wraz z wysokopoziomowymi funkcjami matematycznymi do działania na tych tablicach.
- TensorFlow to biblioteka Pythona do szybkich obliczeń numerycznych. Jest to podstawowa biblioteka, której można używać do tworzenia modeli Deep Learning bezpośrednio lub za pomocą bibliotek owijających, które upraszczają proces zbudowany na bazie TensorFlow.
- Kera to biblioteka sieci neuronowych typu open source napisana w Pythonie.
import pickle import numpy as np import tensorflow as tf from tensorflow import keras print('Tensorflow version: ', tf.__version__) print('Numpy version: ', np.__version__) Tensorflow version: 2.0.0 Numpy version: 1.16.2
Pobierz obrazy
Po zaimportowaniu pakietów następnym krokiem jest pobranie obrazów treningowych z bazy danych i podzielenie danych na dwa numpy tablice. Najpierw musimy zainicjować obrazy szkoleniowe (train_images) i tablice etykiet szkoleniowych (train_labels). Ponieważ już zwektoryzowaliśmy obrazy, możemy użyć atrybutu img_vector, aby zapełnić tablicę train_images poniższą instrukcją SQL.
# Initialize the numpy arrays train_images = np.empty((60000,28,28), dtype='uint8') train_labels = np.empty((60000), dtype='uint8') # Retrieve the training images from the database sql="SELECT img_label, img_vector, img_idx \ FROM tf_images INNER JOIN img_use ON img_use = use_id \ WHERE use_name = 'Training'" cur.execute(sql) result = cur.fetchall() # Populate the numpy arrays. row[2] contains the image index for row in result: nparray = pickle.loads(row[1]) train_images[row[2]] = nparray train_labels[row[2]] = row[0]
W podobny sposób obrazy do testów można pobrać z bazy danych. Numer tablice używane w tym przypadku to test_images i test_labels. W tym przypadku dane testowe to 10 000 obrazów w rozdzielczości 28×28 pikseli.
# Initialize the numpy arrays test_images = np.empty((10000,28,28), dtype='uint8') test_labels = np.empty((10000), dtype='uint8') # Retrieve the testing images from the database sql="SELECT img_label, img_vector, img_idx \ FROM tf_images INNER JOIN img_use ON img_use = use_id \ WHERE use_name = 'Testing'" cur.execute(sql) result = cur.fetchall() # Populate the numpy arrays. row[2] contains the image index for row in result: nparray = pickle.loads(row[1]) test_images[row[2]] = nparray test_labels[row[2]] = row[0]
Na koniec każdy obraz jest mapowany na pojedynczą etykietę. Nazwy etykiet są przechowywane w tabeli Categories i ładowane do tablicy class_names:
sql="SELECT class_name FROM categories" cur.execute(sql) class_names = cur.fetchall()
Wstępnie przetwórz dane
Dane muszą być wstępnie przetworzone przed uczeniem sieci. Jeśli przyjrzysz się pierwszemu obrazowi w zestawie uczącym, zobaczysz, że wartości pikseli mieszczą się w zakresie od 0 do 255:
plt.figure() plt.imshow(train_images[0]) plt.colorbar() plt.grid(False) plt.show()
powyżej:obraz ze zbioru danych fashion_mnist
Przed przesłaniem obrazów do modelu sieci neuronowej wartości należy przeskalować w zakresie od 0 do 1. W tym celu należy podzielić wartości przez 255. Ważne jest, aby zbiór uczący i testowy były wstępnie przetwarzane w ten sam sposób .
Możesz użyć matplotlib aby wyświetlić pierwsze 25 obrazów w celu sprawdzenia, czy dane są w odpowiednim formacie i są gotowe do budowy i szkolenia sieci:
train_images = train_images / 255.0 test_images = test_images / 255.0 plt.figure(figsize=(10,10)) for i in range(25): plt.subplot(5,5,i+1) plt.xticks([]) plt.yticks([]) plt.grid(False) plt.imshow(train_images[i], cmap=plt.cm.binary) plt.xlabel(class_names[train_labels[i]]) plt.show()
powyżej:obrazy ze zbioru danych fashion_mnist
Budowanie modelu
Po wstępnym przetworzeniu danych na dwa podzbiory można kontynuować uczenie modelu. Proces ten polega na „zasileniu” algorytmu danymi treningowymi. Algorytm przetworzy dane i wygeneruje model, który będzie w stanie znaleźć docelową wartość (atrybut) w nowych danych — czyli klasyfikuje obraz prezentowany w sieci neuronowej.
Większość sieci neuronowych głębokiego uczenia jest tworzonych przez łączenie prostych warstw.
Pierwsza warstwa w sieci przekształca format obrazu z dwuwymiarowej tablicy (o wymiarach 28 na 28 pikseli) na jednowymiarową (o 28 * 28 =784 piksele). Ta warstwa nie ma parametrów do nauki; tylko formatuje dane.
Po spłaszczeniu pikseli sieć składa się z dwóch w pełni połączonych warstw, które należy aktywować. W sieci neuronowej funkcja aktywacji jest odpowiedzialna za przekształcenie zsumowanego ważonego wejścia z węzła w aktywację węzła lub wyjście dla tego wejścia.
Pierwsza gęsta warstwa ma 128 węzłów (lub neuronów) i wykorzystuje metodę aktywacji Rectified Linear Unit (ReLU). Wyprostowana liniowa funkcja aktywacji jest odcinkową funkcją liniową, która wyprowadza dane wejściowe bezpośrednio, jeśli jest dodatnia, w przeciwnym razie wygeneruje zero.
Druga (i ostatnia) warstwa to 10-węzłowa warstwa softmax. Funkcja softmax wyprowadza wektor, który reprezentuje rozkłady prawdopodobieństwa listy potencjalnych wyników. Zwraca tablicę 10 wyników prawdopodobieństwa, które sumują się do 1. Każdy węzeł zawiera wynik, który wskazuje prawdopodobieństwo, że bieżący obraz należy do jednej z 10 klas.
Większość warstw, takich jak tf.keras.layers.Dense, ma parametry, których uczy się podczas treningu.
model = keras.Sequential([ keras.layers.Flatten(input_shape=(28, 28)), keras.layers.Dense(128, activation='relu'), keras.layers.Dense(10, activation='softmax') ])
Kompilacja modelu
Krok kompilacji modelu służy do dodania kilku dodatkowych ustawień, zanim będzie gotowy do trenowania. W takim przypadku włączone są następujące ustawienia.
- Optymalizator — aktualizuje model w oparciu o dane, które widzi i jego funkcję utraty (patrz poniżej).
- Funkcja utraty — mierzy dokładność modelu podczas uczenia. Chcesz zminimalizować tę funkcję, aby „sterować” modelem we właściwym kierunku.
- Metryki — Monitoruj etapy szkolenia i testowania. Poniższy przykład wykorzystuje dokładność, część obrazów, które są poprawnie sklasyfikowane.
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
Szkolenie modelki
Trenowanie modelu sieci neuronowej wymaga wykonania następujących kroków.
- Podaj dane treningowe do modelu.
- Model uczy się kojarzyć obrazy i etykiety.
- Twórz przewidywania dotyczące zestawu testowego.
- Sprawdź, czy prognozy pasują do etykiet z tablicy test_labels.
Aby rozpocząć trenowanie, wywołaj metodę model.fit — nazywaną tak, ponieważ „dopasowuje” model do danych treningowych:
model.fit(train_images, train_labels, epochs=10) Train on 60000 samples Epoch 1/10 60000/60000 [==============================] - 5s 83us/sample - loss: 0.4964 - accuracy: 0.8236 Epoch 2/10 60000/60000 [==============================] - 4s 65us/sample - loss: 0.3735 - accuracy: 0.8642 Epoch 3/10 60000/60000 [==============================] - 3s 55us/sample - loss: 0.3347 - accuracy: 0.8773 Epoch 4/10 60000/60000 [==============================] - 3s 56us/sample - loss: 0.3106 - accuracy: 0.8861 Epoch 5/10 60000/60000 [==============================] - 3s 58us/sample - loss: 0.2921 - accuracy: 0.8924s - loss: 0.2928 - accura - ETA: 0s - loss: 0.2925 - accuracy Epoch 6/10 60000/60000 [==============================] - 3s 57us/sample - loss: 0.2796 - accuracy: 0.8969s Epoch 7/10 60000/60000 [==============================] - 4s 70us/sample - loss: 0.2659 - accuracy: 0.9007 Epoch 8/10 60000/60000 [==============================] - 4s 61us/sample - loss: 0.2548 - accuracy: 0.9042 Epoch 9/10 60000/60000 [==============================] - 4s 61us/sample - loss: 0.2449 - accuracy: 0.9084 Epoch 10/10 60000/60000 [==============================] - 5s 76us/sample - loss: 0.2358 - accuracy: 0.9118
Na końcu każdej epoki sieć neuronowa jest oceniana względem zestawu walidacyjnego. Do tego odnosi się strata i dokładność.
Oceń dokładność i przewiduj
Aby oszacować ogólną dokładność modelu, oblicz średnią wszystkich dziesięciu wystąpień wartości dokładności, w tym przypadku 88%.
Następnie wykonaj model.evaluate na zestawie testowym, aby uzyskać dokładność predykcyjną wytrenowanej sieci neuronowej na wcześniej niewidocznych danych.
test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2) 10000/1 - 0s - loss: 0.2766 - accuracy: 0.8740
Testowy zbiór danych jest mniej dokładny niż treningowy zbiór danych. W tym przypadku ta luka między dokładnością treningu a dokładnością testu oznacza nadmierne dopasowanie. Przeciwieństwem jest niedopasowanie. Jeśli chcesz dowiedzieć się więcej na ten temat, polecam Overfitting vs. Underfitting:Konceptualne wyjaśnienie Willa Koehrsena.
W tym momencie możemy dokonać pewnych prognoz dotyczących obrazów w naszym zestawie danych treningowych.
predictions = model.predict(test_images) predictions[0] array([1.90860412e-08, 8.05085235e-11, 1.56402713e-08, 1.66699390e-10, 7.86950158e-11, 4.33062996e-06, 2.49049066e-08, 1.20656565e-02, 3.80084719e-09, 9.87929940e-01], dtype=float32)
Dane wyjściowe model.predict to tablica 10 liczb z prawdopodobieństwem wystąpienia instancji należącej do każdej klasy. Dobrym pomysłem jest utrzymywanie wyników w bazie danych MariaDB do dalszej analizy i raportowania. Poniżej znajduje się przykład, jak wykonać iterację tablicy prognoz, aby zbudować krotkę, a następnie wstawić ją do prediction_results tabela.
sql = "INSERT INTO prediction_results ( img_idx , img_use , T_shirt_Top , Trouser , Pullover , Dress , Coat , Sandal , Shirt , Sneaker , Bag , Ankle_boot , label) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s);" i = 0 for row in predictions: insert_tuple = (str(i), str(2) , str(row[0]), str(row[1]), str(row[2]), str(row[3]), str(row[4]) , str(row[5]), str(row[6]), str(row[7]), str(row[8]), str(row[9]) , str(test_labels[i])) cur.execute(sql, insert_tuple) conn.commit() i += 1
Po raz kolejny można użyć prostej instrukcji SQL do sprawdzenia, czy dane zostały załadowane.
sql = "SELECT T_shirt_Top , Trouser , Pullover , Dress , Coat , Sandal , Shirt , Sneaker , Bag , Ankle_boot , class_name as 'Test Label' FROM prediction_results JOIN categories ON label = class_idx WHERE img_idx = 1" display( pd.read_sql(sql,conn) )
T_shirt_Top | Spodnie | Sweter | Sukienka | Płaszcz | Sandały | Koszula | Tenisówki | Torba | Buty za kostkę | Etykieta testowa |
0.00001 | 0,0 | 0,997912 | 0,0 | 0.001267 | 0,0 | 0.00081 | 0,0 | 0,0 | 0,0 | Sweter |
Wykreślanie prognoz
Poniżej zdefiniowano kilka funkcji kreślenia do wyświetlania prognoz (Funkcje wykresów).
Pobierzmy nowy obraz ze zbioru testowego i wyświetlmy klasyfikację sieci neuronowej na podstawie prawdopodobieństwa przewidywania.
sql = "SELECT img_idx, label FROM prediction_results WHERE img_idx = 1" cur.execute(sql) result = cur.fetchone() plt.figure(figsize=(6,3)) plt.subplot(1,2,1) plot_image(result[0], predictions[result[0]], test_labels, test_images) plt.subplot(1,2,2) plot_value_array(result[0], predictions[result[0]], test_labels) plt.show()
powyżej:obraz ze zbioru danych fashion_mnist
W tym przypadku model był w stanie prawidłowo sklasyfikować obraz ze 100% dokładnością. Następnie wykonajmy zapytanie, aby pobrać pierwsze 15 obrazów ze zbioru testowego i sklasyfikować je.
sql = "SELECT img_idx, label FROM prediction_results LIMIT 15" num_rows = 5 num_cols = 3 plt.figure(figsize=(2*2*num_cols, 2*num_rows)) cur.execute(sql) result = cur.fetchall() for row in result: plt.subplot(num_rows, 2*num_cols, 2*row[0]+1) plot_image(row[0], predictions[row[0]], test_labels, test_images) plt.subplot(num_rows, 2*num_cols, 2*row[0]+2) plot_value_array(row[0], predictions[row[0]], test_labels) plt.tight_layout() plt.show()
powyżej:obrazy ze zbioru danych fashion_mnist
Jak widać, będą sytuacje, w których model może być błędny, jak pokazano w ostatnim wierszu, w lewej kolumnie. W tym przypadku tenisówka została sklasyfikowana jako sandał (w kolorze czerwonym).
Podsumowanie
Chociaż integracja między TensorFlow i MariaDB Server jest łatwa, korzyści płynące z tej integracji są znaczne:
- Wykorzystanie danych relacyjnych w ramach uczenia maszynowego może zmniejszyć złożoność implementacji. Zarówno naukowcy danych, jak i inżynierowie danych mogą używać wspólnego języka do wykonywania zadań związanych z przetwarzaniem i eksploracją danych.
- Wydajność uzyskana podczas uzyskiwania dostępu, aktualizowania, wstawiania, manipulowania i modyfikowania danych może przyspieszyć czas wprowadzenia produktu na rynek.
- Możliwość przechowywania wyników modelu z powrotem w bazie danych umożliwia użytkownikom końcowym i analitykom wykonywanie zapytań i raportów przy użyciu przyjaznych narzędzi do raportowania, takich jak Tableau.
Licencja MIT
Zestaw danych Fashion MNIST (fashion_mnist) wykorzystywany przez ten blog jest objęty licencją MIT, Copyright © 2017 Zalando SE, https://tech.zalando.com
Kod źródłowy wykorzystany przez ten blog jest zaadaptowany z samouczka „Podstawowa klasyfikacja:Klasyfikuj obrazy odzieży”, który jest objęty licencją MIT, Copyright (c) 2017 François Chollet.
Niniejszym udziela się nieodpłatnego zezwolenia każdej osobie, która uzyskała kopię tego oprogramowania i powiązanych plików dokumentacji („Oprogramowanie”), na korzystanie z Oprogramowania bez ograniczeń, w tym między innymi na prawa do używania, kopiowania, modyfikowania, łączenia publikować, rozpowszechniać, udzielać podlicencji i/lub sprzedawać kopii Oprogramowania oraz zezwalać na to osobom, którym Oprogramowanie jest dostarczane, z zastrzeżeniem następujących warunków:
Powyższa informacja o prawach autorskich i niniejsza informacja o pozwoleniu będą zawarte we wszystkich kopiach lub istotnych częściach Oprogramowania.
OPROGRAMOWANIE JEST DOSTARCZANE „TAK JAK JEST”, BEZ JAKICHKOLWIEK GWARANCJI, WYRAŹNYCH LUB DOROZUMIANYCH, W TYM MIĘDZY INNYMI GWARANCJI WARTOŚCI HANDLOWEJ, PRZYDATNOŚCI DO OKREŚLONEGO CELU I NIENARUSZANIA PRAW. W ŻADNYM WYPADKU AUTORZY LUB POSIADACZE PRAW AUTORSKICH NIE PONOSZĄ ODPOWIEDZIALNOŚCI ZA JAKIEKOLWIEK ROSZCZENIA, SZKODY LUB INNĄ ODPOWIEDZIALNOŚĆ, CZY W CZYNNOŚCI UMOWNEJ, CZYNNEJ LUB INNEJ, WYNIKAJĄCEJ Z OPROGRAMOWANIA LUB W ZWIĄZKU Z UŻYTKOWANIEM LUB INNYCH OPROGRAMOWANIE.
Referencje
Konwertuj własny obraz na obraz MNIST
matplotlib:samouczek dotyczący obrazów
5 sposobów, w jakie sztuczna inteligencja zmienia doświadczenia klientów
Cyfryzacja to nowe oblicze biznesu
Co to jest klasyfikacja obrazów?
Wprowadzenie do Pythona Biblioteka Deep Learning TensorFlow
Funkcje graficzne
def plot_image(i, predictions_array, true_label, img): predictions_array, true_label, img = predictions_array, true_label[i], img[i] plt.grid(False) plt.xticks([]) plt.yticks([]) plt.imshow(img, cmap=plt.cm.binary) predicted_label = np.argmax(predictions_array) if predicted_label == true_label: color = 'blue' else: color = 'red' plt.xlabel("{} {:2.0f}% ({})".format(class_names[predicted_label], 100*np.max(predictions_array), class_names[true_label]), color=color) def plot_value_array(i, predictions_array, true_label): predictions_array, true_label = predictions_array, true_label[i] plt.grid(False) plt.xticks(range(10)) plt.yticks([]) thisplot = plt.bar(range(10), predictions_array, color="#777777") plt.ylim([0, 1]) predicted_label = np.argmax(predictions_array) thisplot[predicted_label].set_color('red') thisplot[true_label].set_color('blue')