Image rozpoznávání s Strojové Učení na Python, Konvoluční Neuronové Sítě

zdroj: the irish times, Pól ¢ Muirí

Po pre-zpracování dat, je na čase začít stavět náš model k provedení rozpoznávání Obrazu úkol. Jednou z technik je použití konvoluční neuronové sítě.

tento článek navazuje na článek, který jsem napsal o zpracování obrazu. Po zpřístupnění dat pro úlohu rozpoznávání obrazu je čas vytvořit algoritmus, který bude úkol provádět. Mezi mnoha technikami používanými k rozpoznání obrazů jako vícevrstvého perceptronového modelu se konvoluční neuronová síť (CNN) jeví jako velmi účinná. V tomto článku uvidíme, jak vytvořit CNN a jak ji aplikovat na datovou sadu obrázků.

když začneme vytvářet model rozpoznávání obrazu poprvé, je obvykle dobré trénovat a vyhodnocovat jej na relativně jednoduchém datovém souboru.

jedním z nejjednodušších úkolů, které můžeme provést, je rozpoznávání ručně psaných číslic. Vzhledem k obrázku ručně psané číslice (tj., 0, 1, …, 9), chceme, aby náš model byl schopen správně klasifikovat svou číselnou hodnotu. Ačkoli se tento úkol zdá relativně jednoduchý, ve skutečnosti se používá poměrně často v reálném životě, jako je automatické extrahování čísel kreditních karet z obrázku. Dataset, který použijeme pro rozpoznávání číslic, je dataset MNIST, což je dataset používaný pro rozpoznávání číslic založené na strojovém učení.

databáze MNIST (Modified National Institute of Standards and Technology) obsahuje 60 000 příkladů školení a 10 000 příkladů testování. Databáze obsahuje ručně psané číslice ve stupních šedi, které byly změněny tak, aby se vešly do pole 20×20 pixelů, které bylo poté vystředěno do obrázku 28×28 (polstrované mezerou). Databáze MNIST je přístupná přes Python.

v tomto článku vám ukážu, jak kódovat konvoluční neuronovou síť pomocí keras, API vysoké úrovně TensorFlow. Používám tensorflow 2.0 v tomto článku.

1-inicializace

protože každý obrázek ve stupních šedi má rozměry 28×28, je na obrázek 784 Pixelů. Proto každý vstupní obraz odpovídá tenzoru 784 normalizovaných hodnot s plovoucí desetinnou čárkou mezi 0,0 a 1,0. Popisek obrázku je jeden horký tenzor s 10 třídami (každá třída představuje číslici). Pokud jde o náš kód, máme img_rows = 28, img_cols = 28 a num_classes = 10. Vstup má tedy tvar (number_examples, img_rows, img_cols) tedy 60000x28x28.
dalším důležitým prvkem pro nastavení je náhodné semeno, protože chceme zachovat počáteční bod, když počítač generuje náhodnou číselnou sekvenci.

importujeme také dataset MNIST.

import tensorflow as tf # tensorflow 2.0
from keras.datasets import mnist
import numpy as npseed=0
np.random.seed(seed) # fix random seed
tf.random.set_seed(seed)# input image dimensions
num_classes = 10 # 10 digits
img_rows, img_cols = 28, 28 # number of pixels
# the data, shuffled and split between train and test sets
(X_train, Y_train), (X_test, Y_test) = mnist.load_data()

2 – Zlepšení a změnu měřítka

Jak již bylo zmíněno v předchozí části, vstupy mají tvar (number_examples, img_rows, img_cols). Abychom však mohli data používat s naší konvoluční neuronovou sítí, musíme je dostat do formátu NHWC.

formát NHWC má tvar se čtyřmi rozměry:

  1. Počet obrazových dat vzorků (velikost dávky)
  2. Výška každého obrázku
  3. Šířka každého obrázku
  4. Programy na obrázek

výška a šířka každého obrázku z dataset je img_rows a img_cols, zatímco počet kanálů 1 (od té doby jsou obrazy ve stupních šedi).

každý pixel také obsahuje hodnotu ve stupních šedi kvantifikovanou celočíselným číslem mezi 0 a 255. Databáze je tedy normalizována tak, aby měla hodnoty s plovoucí desetinnou čárkou mezi 0,0 a 1,0. V tomto případě 0,0 odpovídá hodnotě pixelů ve stupních šedi 255 (čistě bílá), zatímco 1.0 odpovídá hodnotě pixelů ve stupních šedi 0 (čistě černá).

X_train = X_train.reshape(X_train.shape, img_rows, img_cols, 1) 
X_test = X_test.reshape(X_test.shape, img_rows, img_cols, 1)input_shape = (img_rows, img_cols, 1)# cast floats to single precision
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')# rescale data in interval
X_train /= 255
X_test /= 255

3-odlévání vektorů štítků Y

potřebujeme transformovat naše třídy na vektory. Děláme to tím, že klepnutím na následující řádek:

Y_train = keras.utils.to_categorical(Y_train, num_classes)
Y_test = keras.utils.to_categorical(Y_test, num_classes)

Pro lepší vysvětlení tohoto kroku, měli byste vidět tento článek.

Nyní, když máme zpracovat naše data, můžeme začít stavět model.

konvoluční Model neuronové sítě

jak je uvedeno na konci článku, který jsem napsal o zpracování obrazu, filtry hrají obrovskou roli v rozpoznávání obrazu. Filtry používáme k transformaci vstupů a extrahování funkcí, které umožňují našemu modelu rozpoznat určité obrázky. Příkladem na velmi vysoké úrovni by byl filtr pro detekci křivek, který umožňuje našemu modelu rozlišovat mezi číslicemi s křivkami a číslicemi bez křivek.

1-filtry

stejně jako všechny váhy neuronové sítě jsou váhy filtru trénovatelné proměnné. Trénujeme naši neuronovou síť (pomocí závaží matice jádra), abychom vytvořili filtry, které jsou schopny extrahovat nejužitečnější skryté funkce.

pokud mají vstupní data více kanálů, filtr bude mít samostatnou matici jádra na kanál. Na datové sady MNIST má pouze jeden kanál, ale i pro jiné typy obrazových dat (např. RGB), trénovali jsme model pro získání optimálních vah pro každý kanál je jádro matice.

2-konvoluce

nyní jsme dosáhli ohniska konvolučních neuronových sítí: konvoluce. Konvoluce představuje, jak aplikujeme naše váhy filtrů na vstupní data. Hlavní operace používá konvoluce je matice, skalární součin, tj. sumaci přes element-wise součin dvou matic.

Počet dot matrix výrobky v konvoluční závisí na rozměrech vstupní data a kernel matice, stejně jako velikost kroku. Velikost kroku je vertikální / horizontální posun matice jádra, jak se pohybuje podél vstupních dat.

3-polstrování

někdy, když provádíme operaci dot produktu, jak je vidět dříve, nepoužíváme řádek nebo sloupec. Abychom se tomuto jevu vyhnuli, můžeme použít polstrování.

Tak, pokud chceme využít všech vstupních údajů v naší konvoluce, můžeme pad vstupní data matice s 0. To znamená, že můžeme přidávat řádky/sloupce vyrobeny výhradně z 0 na okrajích vstupní data matrix. Vzhledem k tomu, že 0 vynásobené libovolným číslem má za následek 0, polstrování neovlivňuje produkty matrix dot. To je důležité, protože nechceme přidávat žádné zkreslení do naší konvoluce.

4-konvoluční vrstva

konvoluční vrstva v CNN aplikuje na vstupní tenzor více filtrů. Zatímco každý filtr má samostatný kernel matice pro každý ze vstupních kanálů, celkový výsledek filtr je konvoluční součet závitů přes všechny vstupní kanály.

přidání dalších filtrů do konvoluční vrstvy umožňuje vrstvě lépe extrahovat skryté funkce. To však přichází za cenu dalšího tréninku a výpočetní složitosti, protože filtry přidávají do modelu další váhy. Počet kanálů pro výstupní data se rovná počtu filtrů, které používá konvoluční vrstva.

sdružování

zatímco konvoluční vrstva extrahuje důležité skryté funkce, počet funkcí může být stále dost velký. Pomocí sdružování můžeme zmenšit velikost dat v rozměrech výšky a šířky. To umožňuje modelu provádět méně výpočtů a nakonec trénovat rychleji. Zabraňuje také overfitting, extrakcí pouze nejvíce charakteristické rysy a ignoruje potenciální narušení nebo neobvyklé rysy našel v jen několik příkladů.

Jak sdružování funguje?

podobně jako konvoluce používáme filtrační matice při sdružování. Filtr sdružování však nemá žádné závaží ani neprovádí produkty matrix dot. Místo toho použije redukční operaci na podsekce vstupních dat.

typ sdružování, který se obvykle používá v CNN, se označuje jako maximální sdružování. Filtry max pooling používají operaci max k získání maximálního počtu v každé submatrix vstupních dat.

více vrstev

1-Přidání dalších vrstev

stejně jako všechny neuronové sítě mohou CNN těžit z dalších vrstev. Další vrstvy umožňují CNN v podstatě skládat více filtrů dohromady pro použití na obrazových datech. Nicméně, podobně jako budování jakékoli neuronové sítě, musíme být opatrní, kolik dalších vrstev přidáme. Pokud jsme přidali příliš mnoho vrstev modelu, riskujeme, že to overfit k výcviku data, a proto zevšeobecňovat velmi špatně. Každá další vrstva navíc zvyšuje výpočetní složitost a prodlužuje dobu tréninku pro náš model.

2-zvýšení filtrů

obvykle zvyšujeme počet filtrů v konvoluční vrstvě, čím hlouběji je v našem modelu. V tomto případě má naše druhá konvoluční vrstva 64 filtrů ve srovnání s 32 filtry první konvoluční vrstvy. Čím hlubší je konvoluční vrstva, tím podrobnější jsou extrahované funkce. Například první konvoluční vrstva může mít filtry, které extrahují funkce, jako jsou čáry, hrany a křivky. Když se dostaneme na druhou úroveň, filtry konvoluční vrstvy by nyní mohly extrahovat více rozlišovacích znaků,jako je ostrý úhel 77 nebo protínající se křivky 88.

Plně propojené vrstvy

1-Plně propojené vrstvy,

naneste plně propojené vrstvy velikost 1024 (tj. počet neuronů ve vrstvě) na výstup data z druhé sdružování vrstvy. Počet jednotek je poněkud libovolný. Dost na to, aby byl silný, ale ne tolik, aby byl příliš náročný na zdroje. Účelem plně připojené vrstvy je agregovat datové funkce dříve, než je převedeme do tříd. To umožňuje modelu provádět lepší předpovědi, než kdybychom právě převedli výstup sdružování přímo do tříd.

2-zploštění

data, která jsme použili v našem modelu, mají formát NHWC. Abychom však mohli použít plně připojenou vrstvu, potřebujeme, aby data byla maticí, kde počet řádků představuje velikost dávky a sloupce představují datové funkce. Tentokrát musíme přetvořit v opačném směru a převést z NHWC na 2 – D matici.

Dropout

1-Co-adaptace

Co-adaptace označuje, když více neuronů ve vrstvě extrahuje stejné nebo velmi podobné skryté rysy ze vstupních dat. K tomu může dojít, když jsou hmotnosti připojení pro dva různé neurony téměř identické.

pokud má plně připojená vrstva velké množství neuronů, je pravděpodobnější, že dojde k společné adaptaci. To může být problém ze dvou důvodů. Za prvé, je to plýtvání výpočtem, když máme redundantní neurony výpočetní stejný výstup. Za druhé, pokud mnoho neuronů extrahuje stejné vlastnosti, přidává to pro náš model větší význam. To vede k nadměrnému vybavení, pokud jsou duplicitní extrahované funkce specifické pouze pro tréninkovou sadu.

2-Vypuštění

způsob, jakým jsme se minimalizovat ko-adaptace pro plně propojené vrstvy s mnoha neurony je použitím vypuštění během tréninku. Při výpadku jsme náhodně vypnuli zlomek neuronů vrstvy v každém tréninku tím, že vynulujeme hodnoty neuronů.

Soft-max vrstva

vzhledem k tomu, že existuje 10 možných číslic MNIST obraz může být, použijeme 10 neuron plně připojené vrstvy pro získání tříd pro každou třídu číslic. Funkce Softmax je aplikována na třídy a převádí je na pravděpodobnosti třídy.

budování modelu

nyní jsme připraveni postavit náš model. Zde je Kód:

from keras.models import Sequential
from keras.layers import Dense, Conv2D, Flatten
from keras.layers import MaxPooling2D, Dropoutmodel = Sequential()#add model layers
model.add(Conv2D(32, kernel_size=(5, 5),
activation='relu',
input_shape=input_shape))
model.add(MaxPooling2D(pool_size=(2, 2)))# add second convolutional layer with 20 filters
model.add(Conv2D(64, (5, 5), activation='relu'))
# add 2D pooling layer
model.add(MaxPooling2D(pool_size=(2, 2)))
# flatten data
model.add(Flatten())
# add a dense all-to-all relu layer
model.add(Dense(1024, activation='relu'))
# apply dropout with rate 0.5
model.add(Dropout(0.5))
# soft-max layer
model.add(Dense(num_classes, activation='softmax'))

typ modelu, který budeme používat, je sekvenční. Sekvenční je nejjednodušší způsob, jak vytvořit model v Kerasu. To vám umožní vytvořit vrstvu modelu po vrstvě.

k připojení vrstev k našemu modelu používáme metodu add (). Pro účely našeho úvodního příkladu stačí pro jednoduchost zaměřit se na husté vrstvy. Každá hustá () vrstva přijímá jako svůj první požadovaný argument celé číslo, které určuje počet neuronů. Typ aktivační funkce pro vrstvu je definován pomocí aktivačního volitelného argumentu, jehož vstupem je název aktivační funkce ve formátu řetězce. Příklady zahrnují relu, tanh, elu, sigmoid, softmax.

v této neuronové síti máme 2 konvoluční vrstvy následované pokaždé sdružovací vrstvou. Poté data zploštíme a přidáme hustou vrstvu, na kterou aplikujeme výpadek rychlostí 0,5. Nakonec přidáme hustou vrstvu, abychom každému obrázku přidělili správnou třídu.

kompilace modelu

dále musíme sestavit náš model. Kompilace modelu má tři parametry: optimalizátor, ztráta a metriky.

optimalizátor řídí rychlost učení. Budeme používat ‘adam’ jako náš optimalizátor. Adam je obecně dobrým optimalizátorem pro mnoho případů. Optimalizátor adam upravuje rychlost učení během tréninku.

rychlost učení určuje, jak rychle se vypočítají optimální váhy pro model. Menší míra učení může vést k přesnějším váhám (až do určitého bodu), ale zmenšení je výpočetní čas.

pro naši funkci ztráty použijeme ‘categorical_crossentropy’. Toto je nejčastější volba pro klasifikaci. Nižší skóre znamená, že model funguje lépe.

, Aby se věci ještě jednodušší interpretovat, budeme používat “přesnost” metrické vidět přesnost skóre na ověření nastavit, když jsme vlak modelu.

#compile model using accuracy to measure model performance
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=)

trénink modelu

nyní budeme trénovat náš model. Trénovat budeme používat ‘fit()’ funkce na náš model s následujícími parametry: tréninková data (X_train), cíl dat (Y_train), validace dat, a počet epoch.

pro naše validační data použijeme testovací sadu, která nám byla poskytnuta v našem datovém souboru, který jsme rozdělili na X_test a Y_test.

počet epoch je počet, kolikrát bude model procházet daty. Čím více epoch běžíme, tím více se model zlepší až do určitého bodu. Po tomto okamžiku se model během každé epochy přestane zlepšovat. Pro náš model nastavíme počet epoch na 3.

#train the model
model.fit(X_train, Y_train, validation_data=(X_test, Y_test), epochs=3)

Vyhodnotit model

Nyní máme vyškolené našeho modelu můžeme zhodnotit jeho výkon:

# evaluate the model
score = model.evaluate(X_test, Y_test, verbose=1)
# print performance
print()
print('Test loss:', score)
print('Test accuracy:', score)

Tak, máme přesností 99,3% a prohrál 0, 025 na testu, což je velmi dobré. Stále můžeme vylepšit model zvýšením počtu epoch a zavedením velikosti šarže.

předpovědi

Pokud chcete vidět skutečné předpovědi, že náš model je vyroben pro testovací data, můžeme použít predict_classes funkce. Můžeme také k tomu pomocí funkce predict dá pole s 10 čísla. Tato čísla jsou pravděpodobnosti, že vstupní obraz představuje každou číslici (0-9). Index pole s nejvyšším číslem představuje predikci modelu. Součet každého pole se rovná 1 (protože každé číslo je pravděpodobnost).

abychom to ukázali, ukážeme předpovědi pro první 4 obrázky v testovací sadě.

Poznámka: Pokud máme nová data, můžeme vložit naše nová data do funkce predict, abychom viděli předpovědi, které náš model dělá na nových datech. Protože nemáme žádná nová neviditelná data, ukážeme předpovědi pomocí testovací sady.

#predict first 4 images in the test set
model.predict_classes(X_test)

#predict first 4 images in the test set
model.predict(X_test)

We can see that our model predicted 7, 2, 1 and 0 for the first four images.

Let’s compare this with the actual results.

#actual results for first 4 images in test set
y_test

aktuální výsledky ukazují, že první čtyři obrázky jsou také 7, 2,1 a 0. Náš model předpověděl správně!

Celý model

import tensorflow as tf # tensorflow 2.0
from keras.datasets import mnist
import numpy as np
seed=0
np.random.seed(seed) # fix random seed
tf.random.set_seed(seed)
# input image dimensions
num_classes = 10 # 10 digitsimg_rows, img_cols = 28, 28 # number of pixels# the data, shuffled and split between train and test sets
(X_train, Y_train), (X_test, Y_test) = mnist.load_data()X_train = X_train.reshape(X_train.shape, img_rows, img_cols, 1)
X_test = X_test.reshape(X_test.shape, img_rows, img_cols, 1)
input_shape = (img_rows, img_cols, 1)# cast floats to single precision
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')# rescale data in interval
X_train /= 255
X_test /= 255Y_train = keras.utils.to_categorical(Y_train, num_classes)
Y_test = keras.utils.to_categorical(Y_test, num_classes)from keras.models import Sequential
from keras.layers import Dense, Conv2D, Flatten
from keras.layers import MaxPooling2D, Dropout
model = Sequential()#add model layers
model.add(Conv2D(32, kernel_size=(5, 5),
activation='relu',
input_shape=input_shape))
model.add(MaxPooling2D(pool_size=(2, 2)))
# add second convolutional layer with 20 filters
model.add(Conv2D(64, (5, 5), activation='relu'))
# add 2D pooling layer
model.add(MaxPooling2D(pool_size=(2, 2)))
# flatten data
model.add(Flatten())
# add a dense all-to-all relu layer
model.add(Dense(1024, activation='relu'))
# apply dropout with rate 0.5
model.add(Dropout(0.5))
# soft-max layer
model.add(Dense(num_classes, activation='softmax'))#compile model using accuracy to measure model performance
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=)#train the model
model.fit(X_train, Y_train, validation_data=(X_test, Y_test), epochs=3)# evaluate the model
score = model.evaluate(X_test, Y_test, verbose=1)# print performance
print()
print('Test loss:', score)
print('Test accuracy:', score)#predict first 4 images in the test set
model.predict(X_test)model.predict_classes(X_test)#actual results for first 4 images in test set
Y_test

pokračovat…

V tomto článku, jsem se pustil do druhé části rozpoznávání obrazu, která je budování Konvoluční Neuronové Sítě.

doufám, že jste v tomto článku našli to, pro co jste sem přišli, a zůstaňte se mnou pro další epizody této cesty pro rozpoznávání obrázků!

PS: v současné době jsem Master of Engineering Student na Berkeley, a pokud chcete diskutovat o tématu, neváhejte mě kontaktovat. Tady je můj e-mail.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna.