Глибоке навчання для новачків: розпізнаємо зображення з допомогою згорткових мереж

Введення
Представляємо другу статтю в серії, задумана, щоб допомогти швидко розібратися в технології глибокого навчання; ми будемо рухатися від базових принципів до нетривіальних особливостей з метою отримати гідну продуктивність на двох наборах даних: MNIST (класифікація рукописних цифр) і CIFAR-10 (класифікація невеликих зображень з десяти класів: літак, автомобіль, птиця, кішка, олень, собака, жаба, кінь, корабель і вантажівка).




На минулому уроці ми ввели базові поняття глибокого навчання і показали, як можна швидко змоделювати моделі нейронних мереж за допомогою фреймворку Keras. Наостанок багатошаровий перцептрон (MLP), містить два шари, застосували до MNIST, досягнувши рівня точності 98.2%, причому це значення досить просто поліпшити. Але все ж полносвязный перцептрон зазвичай не вибирають для завдань, пов'язаних з розпізнаванням зображень — в цьому випадку набагато частіше користуються перевагами згорткових нейронних мереж (Convolutional Neural Networks, CNN). Пройшовши цей курс, ви будете розуміти принцип роботи і навчитеся будувати CNN в Keras, досягаючи високого рівня точності на CIFAR-10.

Ця стаття передбачає знайомство з попередньою статтею циклу.

Обробка зображень
Згаданий вище багатошаровий перцептрон являє собою найпотужнішу і можливих нейронних мереж прямого поширення. Він складається з декількох шаром, де кожен шар організований таким чином, що кожен нейрон в одному шарі отримує свою копію всі вихідних даних попереднього шару. Ця модель ідеально підходить для певних типів завдань, наприклад, навчання на обмеженому кількість більш або менш неструктурованих параметрів.

Тим не менш, подивимося, що відбувається з кількістю параметрів (ваг) у такій моделі, коли їй на вхід надходять необроблені дані. Наприклад, CIFAR-10 містить 32 x 32 x 3 кольорових зображень, і якщо ми будемо вважати кожен канал кожного пікселя незалежним вхідним параметром для MLP, кожен нейрон у першому прихованому шарі додає до моделі близько 3000 нових параметрів! І з зростанням розміру зображень ситуація швидко виходить з-під контролю, причому відбувається це набагато раніше, ніж зображення досягають розміру, з якими зазвичай працюють користувачі реальних додатків.

Одне з популярних рішень знижувати дозвіл зображень до тієї міри, коли MLP стає застосуємо. Тим не менше, коли ми просто знижуємо дозвіл, ми ризикуємо втратити велику кількість інформації, і було б здорово, якби можна було здійснювати корисну первинну обробку інформації ще до застосування пониження якості, не викликаючи при цьому вибухового зростання кількості параметрів моделі.

Згортка функцій
Виявляється, існує досить ефективний спосіб вирішення цієї задачі, який звертає на нашу користь саму структуру зображення: передбачається, що пікселі, що знаходяться закрити один до одного, тісніше «взаємодіють» при формуванні цікавлячого нас ознаки, ніж пікселі, розташовані в протилежних кутах. Крім того, якщо в процесі класифікації зображення невелика риса вважається дуже важливою, не буде мати значення, на якій ділянці зображення ця риса виявлено.

Введемо поняття оператора згортки. Маючи двовимірне зображення I і невелику матрицю K розмірності h\times w(так зване ядро згортки), побудована таким чином, що графічно кодує який-небудь ознака, ми обчислюємо згорнуте зображення I * K, накладаючи ядро на зображення всіма можливими способами і записуючи суму добутків елементів вихідного зображення і ядра:
(I * K)_{xy} = \sum_{i=1}^h\sum_{j=1}^wK_{ij}\times I_{x+i-1, y+j-1}

Насправді, точне визначення припускає, що матриця ядра буде транспонирована, але для завдань машинного навчання не важливо, виконувалася ця операція чи ні.
На малюнках нижче схематично зображена вищевказана формула, а також представлений результат застосування операції згортки (з двома різними ядрами на зображення з метою виділити контури об'єкта.



Згорткові і субдискретизирующие шари
Оператор згортки становить основу згорткового шару (convolutional layer) в CNN. Шар складається з певної кількості ядер \vec{K}(з адитивними складовими зміщення \vec{b}для кожного ядра) і обчислює згортку вихідного зображення попереднього шару з допомогою кожного з ядер, кожен раз додаючи складову зміщення. В кінці кінців до всього вихідного зображення може бути застосована функція активації \sigma. Зазвичай вхідний потік для згорткового шару складається з d каналів, наприклад, red/green/blue для вхідного шару, і в цьому випадку ядра теж розширюють таким чином, щоб вони складалися з d каналів; виходить наступна формула для одного каналу вихідного зображення згорткового шару, де K — ядро, а b — складова зміщення:
\textrm{conv}(I,K)_{x,y} = \sigma(b + \sum_{i=1}^h\sum_{j=1}^w\sum_{k=1}^dK_{ijk}\times I_{x+i-1,y+j-1,k})

Зверніть увагу, що так як все, що ми тут робимо — це додавання і масштабування вхідних пікселів, ядра можна отримати з наявної навчальної вибірки методом градієнтного спуску, аналогічно обчисленню ваг в багатошаровому перцептроне (MLP). Насправді MLP міг би досконало впоратися з функціями згорткового шару, але часу на навчання (як і навчальних даних) знадобилося б набагато більше.

Зауважимо також, що оператор згортки зовсім не обмежений двомірними даними: більшість фреймворків глибокого навчання (включаючи Keras) надають шари для одномірної або тривимірної згортки прямо «з коробки».

Варто також зазначити, що хоча згортковий шар скорочує кількість параметрів порівняно з повнозв'язним шаром, він використовує більше гиперпараметров — параметрів, вибраних початку навчання.

Зокрема, вибираються наступні гиперпараметры:

  • Глибина (depth) — скільки ядер і коефіцієнтів зміщення буде задіяно в одному шарі;
  • Висота (height) і ширина (width) кожного ядра;
  • Крок (stride) — на скільки зміщується ядро на кожному кроці при обчисленні наступного пікселя результуючого зображення. Зазвичай його приймають рівним 1, і чим більше його значення, тим менше розмір вихідного зображення;
  • Відступ (padding): зауважимо, що згортка будь ядром розмірності більше, ніж 1х1 зменшить розмір вихідного зображення. Так як в загальному випадку бажано зберігати розмір початкового зображення, малюнок доповнюється нулями по краях.
Як читач вже здогадався, операції згортки — не єдині операції в CNN (хоча існують багатообіцяючі дослідження на тему «чисто-надточних» мереж); вони частіше застосовуються для виділення найбільш корисних ознак перед субдискретизацией (downsampling) і наступною обробкою за допомогою MLP.

Популярний спосіб субдискретизации зображення — шар підвибірки (також званий шаром субдискретизации, по-англійськи downsampling або pooling layer), який отримує на вхід маленькі окремі фрагменти зображення (зазвичай 2х2) і об'єднує кожен фрагмент в одне значення. Існує кілька можливих способів агрегації, найбільш часто з чотирьох пікселів вибирається максимальний. Цей спосіб схематично зображено нижче.


Разом: звичайна CNN
Тепер, коли у нас є всі будівельні блоки, давайте розглянемо, як виглядає звичайна CNN цілком!


Звичайну архітектуру CNN для розподілу зображень k класах можна розділити на дві частини: ланцюжок чергуються шарів згортки/підвибірки \textrm{Conv}\to \textrm {Pool}(іноді з декількома шарами згортки поспіль) і кілька повноз'вязних шарів (приймаючих кожен піксель як незалежне значення) з шаром softmax в якості завершального. Я не кажу тут про функції активації, щоб наша схема стала простіше, але не забувайте, що зазвичай після кожного згорткового або полносвязного шару до всіх вихідних значень застосовується функція активації, наприклад, ReLU.

Один прохід \textrm{Conv}\to \textrm {Pool}впливає на зображення наступним чином: він скорочує довжину і ширину певного каналу, але збільшує його значення (глибину).
Softmax та перехресна ентропія більш докладно розглянуті на попередньому уроці. Нагадаємо, що функція softmax перетворює вектор дійсних чисел вектор ймовірностей (невід'ємні дійсні числа, що не перевищують 1). У нашому контексті вихідні значення є ймовірностями потрапляння зображення в певний клас. Мінімізація втрат перехресної ентропії забезпечує впевненість у визначенні приналежності зображення певного класу, не беручи до уваги ймовірність інших класів, таким чином, для імовірнісних задач softmax краще, ніж, наприклад, метод квадратичної помилки.

Відступ: перенавчання, регуляризация і dropout
Вперше (і, сподіваюся, лише одного разу) я зверну вашу увагу на тему, на перший погляд, не відноситься до предмету. Вона стосується дуже важливого підводного каменя глибокого навчання — проблеми перенавчання (overfitting). Хоча ця тема буде основною в наступній статті циклу, негативний ефект перенавчання помітно проявляється на мережах, подібних до тієї, що ми збираємося побудувати, а значить, необхідно знайти спосіб захиститися від цього явища перш, ніж ми підемо далі. На щастя, існує дуже простий метод, який ми і застосуємо.

Перенавчання — це зайве точне відповідність нейронної мережі конкретного набору навчальних прикладів, при якому мережа втрачає здатність до узагальнення. Іншими словами, наша модель могла вивчити навчальну множину (разом з шумом, який в ньому присутній), але вона не змогла розпізнати приховані процеси, які це безліч породили. В якості прикладу розглянемо задачу апроксимації синусоїди з адитивним шумом.


У нас є навчальна множина (сині кружки), отримана з вихідної кривої синуса, з деякою кількістю шуму. Якщо ми докладемо до цих даних графік многочлена третього ступеня, ми отримаємо гарну апроксимацію вихідної кривої. Хтось заперечить, що многочлен 14-го ступеня підійшов би краще; дійсно, так як у нас є 15 точок, така апроксимація ідеально описала б навчальну вибірку. Тим не менш, у цьому випадку введення додаткових параметрів в модель призводить до катастрофічних результатів: з-за того, що наша апроксимація враховує шуми, вона не збігається з вихідної кривої ніде, крім навчальних точок.

У глибоких згорткових нейронних мереж маса різноманітних параметрів, особливо це стосується повноз'вязних шарів. Перенавчання може проявити себе в такій формі: якщо у нас недостатньо навчальних прикладів, маленька група нейронів може стати відповідальною за більшість обчислень, а інші нейрони стануть надлишкові; або навпаки, деякі нейрони можуть завдати шкоди продуктивності, при цьому інші нейрони з їх шару не будуть займатися нічим, окрім виправлення їх помилок.

Щоб допомогти нашій мережі не втратити здатності до узагальнення цих обставин, ми вводимо прийоми регуляризації: замість скорочення кількості параметрів, ми накладаємо обмеження на параметри моделі під час навчання, не дозволяючи нейронів вивчати шум навчальних даних. Тут я опишу прийом dropout, який спочатку може здатися «чорною магією», але на ділі допомагає виключити ситуації, описані вище. Зокрема, dropout з параметром p за одну ітерацію навчання проходить по всіх нейронів певного шару і з вірогідністю p повністю виключає їх з мережі на час ітерації. Це змусить мережа обробляти помилки і не покладатися на існування певного нейрона (або групи нейронів), а покладатися на "єдина думка" (consensus) нейронів всередині одного шару. Це досить простий метод, який ефективно бореться з проблемою перенавчання сам, без необхідності вводити інші регуляризаторы. Схема нижче ілюструє даний метод.


Застосування глибокої CNN до CIFAR-10
В якості практичної частини побудуємо глибоку сверточную нейронну мережу і застосуємо її до класифікації зображень з набору CIFAR-10.
Імпорти ті ж, що і в минулий раз, за винятком того, що ми використовуємо більшу різноманітність шарів:
from keras.datasets import cifar10 # підпрограм for fetching the CIFAR-10 dataset
from keras.models import Model # basic class for specifying and training a neural network
from keras.layers import Input, Convolution2D, MaxPooling2D, Dense, Dropout, Flatten
from keras.utils import np_utils # utilities for one hot encoding of ground truth values
import numpy as np

Using Theano backend.


Як вже говорилося, зазвичай CNN використовує більше гиперпараметров, ніж MLP. У цьому керівництві ми все ще будемо використовувати заздалегідь відомі «хороші» значення, але не будемо забувати, що в наступній лекції я розповім, як їх правильно вибирати.
Задамо наступні гиперпараметры:

  • batch_size — кількість навчальних зразків, що обробляються одночасно за одну ітерацію алгоритму градієнтного спуску;
  • num_epochs — кількість ітерацій навчального алгоритму по всьому навчального безлічі;
  • kernel_size — розмір ядра в згорткових шарах;
  • pool_size — розмір підвибірки в шарах підвибірки;
  • сonv_depth — кількість ядер в згорткових шарах;
  • drop_prob (dropout probability) — ми будемо застосовувати dropout після кожного шару підвибірки, а також після полносвязного шару;
  • hidden_size — кількість нейронів у полносвязном шарі MLP.
NB: я задав 200 ітерацій, що може зайняти занадто багато часу, якщо у вашому розпорядженні немає графічного процесора (у цьому випадку вузьким місцем будуть згорткові шари). Якщо ви збираєтеся навчати мережу на CPU, варто скоротити кількість ітерацій та/або ядер.
batch_size = 32 # in each iteration, we consider 32 training examples at once
num_epochs = 200 # we iterate 200 times over the entire training set
kernel_size = 3 # we will use 3x3 kernels throughout
pool_size = 2 # we will use 2x2 pooling throughout
conv_depth_1 = 32 # we will initially have 32 kernels per conv. layer...
conv_depth_2 = 64 # ...switching to 64 after the first pooling layer
drop_prob_1 = 0.25 # dropout after pooling with probability 0.25
drop_prob_2 = 0.5 # dropout in the FC layer with probability 0.5
hidden_size = 512 # the FC layer will have 512 neurons


Завантаження і первинна обробка CIFAR-10 здійснюється рівно так само, як і завантаження та обробка MNIST, де Keras виконує всі автоматично. Єдина відмінність полягає в тому, що тепер ми не розглядаємо кожен піксель як незалежна вхідне значення, і тому ми не переносимо зображення в одномірне простір. Ми знову перетворимо інтенсивність пікселів так, щоб вона потрапляла у відрізок [0,1] і використовуємо пряме кодування для вихідних значень.

Тим не менш, на цей раз цей етап буде виконаний для більш загального випадку, що дозволить простіше пристосовуватися до нових наборів даних: розмір буде не жорстко заданий, а обчислений з розміру набору даних, кількість класів буде визначено за кількістю унікальних міток в навчальній множині, а нормалізація буде виконана шляхом поділу всіх елементів на максимальне значення навчальної множини.

NB: ми також розділимо тестове безліч на максимальне значення навчального безлічі, тому що нашим алгоритмам не дозволено бачити тестові дані до того, як завершиться процес навчання, і тому ми не можемо обчислювати на їх основі ніякі статистичні метрики крім як застосування тих самих трансформацій, що відбувалися з навчальним безліччю.
(X_train, y_train), (X_test, y_test) = cifar10.load_data() # fetch CIFAR-10 data

num_train, depth, height, width = X_train.shape # there are 50000 training examples in CIFAR-10 
num_test = X_test.shape[0] # there are 10000 test examples in CIFAR-10
num_classes = np.unique(y_train).shape[0] # there are 10 image classes

X_train = X_train.astype('float32') 
X_test = X_test.astype('float32')
X_train /= np.max(X_train) # Normalise data to [0, 1] range
X_test /= np.max(X_train) # Normalise data to [0, 1] range

Y_train = np_utils.to_categorical(y_train, num_classes) # One-hot encode the labels
Y_test = np_utils.to_categorical(y_test, num_classes) # One-hot encode the labels

Настав час моделювання! Наша мережа буде складатися з чотирьох шарів
Convolution_2D
і шарів
MaxPooling2D
після другої і четвертої згорток. Після першого шару підвибірки ми подвоюємо кількість ядер (разом з описаним вище принципом складання висоти і ширини в жертву глибині). Після цього вихідне зображення шару підвибірки трансформується в одновимірний вектор (шаром
Flatten
) і проходить два повноз'вязних шару (
Dense
). На всіх шарах, крім вихідного полносвязного шару, використовується функція активації ReLU, останній же шар використовує softmax.

Для регуляризації нашої моделі після кожного шару підвибірки і першого полносвязного шару шар Dropout. Тут Keras також виділяється на тлі інших фреймворків: в ньому є внутрішній прапор, який автоматично включає і вимикає dropout, в залежності від того, знаходиться модель у фазі навчання або тестування.

В іншому специфікація нашої моделі співпадає з нашими попередніми налаштуваннями для MNIST:

  • Ми використовуємо перехресне ентропію в якості функції втрат;
  • Ми використовуємо оптимізатор Адама для градієнтного спуску;
  • Ми вимірюємо точність моделі (так як вихідні дані розподілені за класами рівномірно)*;
  • Ми залишаємо 10% даних для подальшої валідації.


*Щоб зрозуміти, чому точність не підійде для випадків, коли розподіл даних за класами нерівномірно, розглянемо граничний випадок, коли 90% тестових даних належить класу x (наприклад, в задачі діагностики у пацієнтів рідкісного захворювання). У цьому випадку класифікатор, який просто виводить x, досягає значної точності 90%, хоча на ділі не виконує ні навчання, ні узагальнення.
inp = Input(shape=(depth, height, width) # N. B. depth goes first in Keras!
# Conv [32] -> Conv [32] -> Pool (with dropout on the pooling layer)
conv_1 = Convolution2D(conv_depth_1, kernel_size, kernel_size, border_mode='same', activation='relu')(inp)
conv_2 = Convolution2D(conv_depth_1, kernel_size, kernel_size, border_mode='same', activation='relu')(conv_1)
pool_1 = MaxPooling2D(pool_size=(pool_size, pool_size))(conv_2)
drop_1 = Dropout(drop_prob_1)(pool_1)
# Conv [64] -> Conv [64] -> Pool (with dropout on the pooling layer)
conv_3 = Convolution2D(conv_depth_2, kernel_size, kernel_size, border_mode='same', activation='relu')(drop_1)
conv_4 = Convolution2D(conv_depth_2, kernel_size, kernel_size, border_mode='same', activation='relu')(conv_3)
pool_2 = MaxPooling2D(pool_size=(pool_size, pool_size))(conv_4)
drop_2 = Dropout(drop_prob_1)(pool_2)
# Now flatten to 1D, apply FC -> ReLU (with dropout) -> softmax
flat = Flatten()(drop_2)
hidden = Dense(hidden_size, activation='relu')(flat)
drop_3 = Dropout(drop_prob_2)(hidden)
out = Dense(num_classes, activation='softmax')(drop_3)

model = Model(input=inp, output=out) # To define a model, just specify its input and output layers

model.compile(loss='categorical_crossentropy', # using the cross-entropy loss function
optimizer='adam', # using the Adam optimiser
metrics=['accuracy']) # reporting the accuracy

model.fit(X_train, Y_train, # Train the model using the training set...
batch_size=batch_size, nb_epoch=num_epochs,
verbose=1, validation_split=0.1) # ...holding out 10% of the data for validation
model.evaluate(X_test, Y_test, verbose=1) # Evaluate the trained model on the test set!

Подивитися лістинг навчання
Train on 45000 samples, validate on 5000 samples
Epoch 1/200
45000/45000 [==============================] - 9s - loss: 1.5435 - acc: 0.4359 - val_loss: 1.2057 - val_acc: 0.5672
Epoch 2/200
45000/45000 [==============================] - 9s - loss: 1.1544 - acc: 0.5886 - val_loss: 0.9679 - val_acc: 0.6566
Epoch 3/200
45000/45000 [==============================] - 8s - loss: 1.0114 - acc: 0.6418 - val_loss: 0.8807 - val_acc: 0.6870
Epoch 4/200
45000/45000 [==============================] - 8s - loss: 0.9183 - acc: 0.6766 - val_loss: 0.7945 - val_acc: 0.7224
Epoch 5/200
45000/45000 [==============================] - 9s - loss: 0.8507 - acc: 0.6994 - val_loss: 0.7531 - val_acc: 0.7400
Epoch 6/200
45000/45000 [==============================] - 9s - loss: 0.8064 - acc: 0.7161 - val_loss: 0.7174 - val_acc: 0.7496
Epoch 7/200
45000/45000 [==============================] - 9s - loss: 0.7561 - acc: 0.7331 - val_loss: 0.7116 - val_acc: 0.7622
Epoch 8/200
45000/45000 [==============================] - 9s - loss: 0.7156 - acc: 0.7476 - val_loss: 0.6773 - val_acc: 0.7670
Epoch 9/200
45000/45000 [==============================] - 9s - loss: 0.6833 - acc: 0.7594 - val_loss: 0.6855 - val_acc: 0.7644
Epoch 10/200
45000/45000 [==============================] - 9s - loss: 0.6580 - acc: 0.7656 - val_loss: 0.6608 - val_acc: 0.7748
Epoch 11/200
45000/45000 [==============================] - 9s - loss: 0.6308 - acc: 0.7750 - val_loss: 0.6854 - val_acc: 0.7730
Epoch 12/200
45000/45000 [==============================] - 9s - loss: 0.6035 - acc: 0.7832 - val_loss: 0.6853 - val_acc: 0.7744
Epoch 13/200
45000/45000 [==============================] - 9s - loss: 0.5871 - acc: 0.7914 - val_loss: 0.6762 - val_acc: 0.7748
Epoch 14/200
45000/45000 [==============================] - 8s - loss: 0.5693 - acc: 0.8000 - val_loss: 0.6868 - val_acc: 0.7740
Epoch 15/200
45000/45000 [==============================] - 9s - loss: 0.5555 - acc: 0.8036 - val_loss: 0.6835 - val_acc: 0.7792
Epoch 16/200
45000/45000 [==============================] - 9s - loss: 0.5370 - acc: 0.8126 - val_loss: 0.6885 - val_acc: 0.7774
Epoch 17/200
45000/45000 [==============================] - 9s - loss: 0.5270 - acc: 0.8134 - val_loss: 0.6604 - val_acc: 0.7866
Epoch 18/200
45000/45000 [==============================] - 9s - loss: 0.5090 - acc: 0.8194 - val_loss: 0.6652 - val_acc: 0.7860
Epoch 19/200
45000/45000 [==============================] - 9s - loss: 0.5066 - acc: 0.8193 - val_loss: 0.6632 - val_acc: 0.7858
Epoch 20/200
45000/45000 [==============================] - 9s - loss: 0.4938 - acc: 0.8248 - val_loss: 0.6844 - val_acc: 0.7872
Epoch 21/200
45000/45000 [==============================] - 9s - loss: 0.4684 - acc: 0.8361 - val_loss: 0.6861 - val_acc: 0.7904
Epoch 22/200
45000/45000 [==============================] - 9s - loss: 0.4696 - acc: 0.8365 - val_loss: 0.6349 - val_acc: 0.7980
Epoch 23/200
45000/45000 [==============================] - 9s - loss: 0.4584 - acc: 0.8387 - val_loss: 0.6592 - val_acc: 0.7926
Epoch 24/200
45000/45000 [==============================] - 9s - loss: 0.4410 - acc: 0.8443 - val_loss: 0.6822 - val_acc: 0.7876
Epoch 25/200
45000/45000 [==============================] - 8s - loss: 0.4404 - acc: 0.8454 - val_loss: 0.7103 - val_acc: 0.7784
Epoch 26/200
45000/45000 [==============================] - 8s - loss: 0.4276 - acc: 0.8512 - val_loss: 0.6783 - val_acc: 0.7858
Epoch 27/200
45000/45000 [==============================] - 8s - loss: 0.4152 - acc: 0.8542 - val_loss: 0.6657 - val_acc: 0.7944
Epoch 28/200
45000/45000 [==============================] - 9s - loss: 0.4107 - acc: 0.8549 - val_loss: 0.6861 - val_acc: 0.7888
Epoch 29/200
45000/45000 [==============================] - 9s - loss: 0.4115 - acc: 0.8548 - val_loss: 0.6634 - val_acc: 0.7996
Epoch 30/200
45000/45000 [==============================] - 9s - loss: 0.4057 - acc: 0.8586 - val_loss: 0.7166 - val_acc: 0.7896
Epoch 31/200
45000/45000 [==============================] - 9s - loss: 0.3992 - acc: 0.8605 - val_loss: 0.6734 - val_acc: 0.7998
Epoch 32/200
45000/45000 [==============================] - 9s - loss: 0.3863 - acc: 0.8637 - val_loss: 0.7263 - val_acc: 0.7844
Epoch 33/200
45000/45000 [==============================] - 9s - loss: 0.3933 - acc: 0.8644 - val_loss: 0.6953 - val_acc: 0.7860
Epoch 34/200
45000/45000 [==============================] - 9s - loss: 0.3838 - acc: 0.8663 - val_loss: 0.7040 - val_acc: 0.7916
Epoch 35/200
45000/45000 [==============================] - 9s - loss: 0.3800 - acc: 0.8674 - val_loss: 0.7233 - val_acc: 0.7970
Epoch 36/200
45000/45000 [==============================] - 9s - loss: 0.3775 - acc: 0.8697 - val_loss: 0.7234 - val_acc: 0.7922
Epoch 37/200
45000/45000 [==============================] - 9s - loss: 0.3681 - acc: 0.8746 - val_loss: 0.6751 - val_acc: 0.7958
Epoch 38/200
45000/45000 [==============================] - 9s - loss: 0.3679 - acc: 0.8732 - val_loss: 0.7014 - val_acc: 0.7976
Epoch 39/200
45000/45000 [==============================] - 9s - loss: 0.3540 - acc: 0.8769 - val_loss: 0.6768 - val_acc: 0.8022
Epoch 40/200
45000/45000 [==============================] - 9s - loss: 0.3531 - acc: 0.8783 - val_loss: 0.7171 - val_acc: 0.7986
Epoch 41/200
45000/45000 [==============================] - 9s - loss: 0.3545 - acc: 0.8786 - val_loss: 0.7164 - val_acc: 0.7930
Epoch 42/200
45000/45000 [==============================] - 9s - loss: 0.3453 - acc: 0.8799 - val_loss: 0.7078 - val_acc: 0.7994
Epoch 43/200
45000/45000 [==============================] - 8s - loss: 0.3488 - acc: 0.8798 - val_loss: 0.7272 - val_acc: 0.7958
Epoch 44/200
45000/45000 [==============================] - 9s - loss: 0.3471 - acc: 0.8797 - val_loss: 0.7110 - val_acc: 0.7916
Epoch 45/200
45000/45000 [==============================] - 9s - loss: 0.3443 - acc: 0.8810 - val_loss: 0.7391 - val_acc: 0.7952
Epoch 46/200
45000/45000 [==============================] - 9s - loss: 0.3342 - acc: 0.8841 - val_loss: 0.7351 - val_acc: 0.7970
Epoch 47/200
45000/45000 [==============================] - 9s - loss: 0.3311 - acc: 0.8842 - val_loss: 0.7302 - val_acc: 0.8008
Epoch 48/200
45000/45000 [==============================] - 9s - loss: 0.3320 - acc: 0.8868 - val_loss: 0.7145 - val_acc: 0.8002
Epoch 49/200
45000/45000 [==============================] - 9s - loss: 0.3264 - acc: 0.8883 - val_loss: 0.7640 - val_acc: 0.7942
Epoch 50/200
45000/45000 [==============================] - 9s - loss: 0.3247 - acc: 0.8880 - val_loss: 0.7289 - val_acc: 0.7948
Epoch 51/200
45000/45000 [==============================] - 9s - loss: 0.3279 - acc: 0.8886 - val_loss: 0.7340 - val_acc: 0.7910
Epoch 52/200
45000/45000 [==============================] - 9s - loss: 0.3224 - acc: 0.8901 - val_loss: 0.7454 - val_acc: 0.7914
Epoch 53/200
45000/45000 [==============================] - 9s - loss: 0.3219 - acc: 0.8916 - val_loss: 0.7328 - val_acc: 0.8016
Epoch 54/200
45000/45000 [==============================] - 9s - loss: 0.3163 - acc: 0.8919 - val_loss: 0.7442 - val_acc: 0.7996
Epoch 55/200
45000/45000 [==============================] - 9s - loss: 0.3071 - acc: 0.8962 - val_loss: 0.7427 - val_acc: 0.7898
Epoch 56/200
45000/45000 [==============================] - 9s - loss: 0.3158 - acc: 0.8944 - val_loss: 0.7685 - val_acc: 0.7920
Epoch 57/200
45000/45000 [==============================] - 8s - loss: 0.3126 - acc: 0.8942 - val_loss: 0.7717 - val_acc: 0.8062
Epoch 58/200
45000/45000 [==============================] - 9s - loss: 0.3156 - acc: 0.8919 - val_loss: 0.6993 - val_acc: 0.7984
Epoch 59/200
45000/45000 [==============================] - 9s - loss: 0.3030 - acc: 0.8970 - val_loss: 0.7359 - val_acc: 0.8016
Epoch 60/200
45000/45000 [==============================] - 9s - loss: 0.3022 - acc: 0.8969 - val_loss: 0.7427 - val_acc: 0.7954
Epoch 61/200
45000/45000 [==============================] - 9s - loss: 0.3072 - acc: 0.8950 - val_loss: 0.7829 - val_acc: 0.7996
Epoch 62/200
45000/45000 [==============================] - 9s - loss: 0.2977 - acc: 0.8996 - val_loss: 0.8096 - val_acc: 0.7958
Epoch 63/200
45000/45000 [==============================] - 9s - loss: 0.3033 - acc: 0.8983 - val_loss: 0.7424 - val_acc: 0.7972
Epoch 64/200
45000/45000 [==============================] - 9s - loss: 0.2985 - acc: 0.9003 - val_loss: 0.7779 - val_acc: 0.7930
Epoch 65/200
45000/45000 [==============================] - 8s - loss: 0.2931 - acc: 0.9004 - val_loss: 0.7302 - val_acc: 0.8010
Epoch 66/200
45000/45000 [==============================] - 8s - loss: 0.2948 - acc: 0.8994 - val_loss: 0.7861 - val_acc: 0.7900
Epoch 67/200
45000/45000 [==============================] - 9s - loss: 0.2911 - acc: 0.9026 - val_loss: 0.7502 - val_acc: 0.7918
Epoch 68/200
45000/45000 [==============================] - 9s - loss: 0.2951 - acc: 0.9001 - val_loss: 0.7911 - val_acc: 0.7820
Epoch 69/200
45000/45000 [==============================] - 9s - loss: 0.2869 - acc: 0.9026 - val_loss: 0.8025 - val_acc: 0.8024
Epoch 70/200
45000/45000 [==============================] - 8s - loss: 0.2933 - acc: 0.9013 - val_loss: 0.7703 - val_acc: 0.7978
Epoch 71/200
45000/45000 [==============================] - 8s - loss: 0.2902 - acc: 0.9007 - val_loss: 0.7685 - val_acc: 0.7962
Epoch 72/200
45000/45000 [==============================] - 9s - loss: 0.2920 - acc: 0.9025 - val_loss: 0.7412 - val_acc: 0.7956
Epoch 73/200
45000/45000 [==============================] - 8s - loss: 0.2861 - acc: 0.9038 - val_loss: 0.7957 - val_acc: 0.8026
Epoch 74/200
45000/45000 [==============================] - 8s - loss: 0.2785 - acc: 0.9069 - val_loss: 0.7522 - val_acc: 0.8002
Epoch 75/200
45000/45000 [==============================] - 9s - loss: 0.2811 - acc: 0.9064 - val_loss: 0.8181 - val_acc: 0.7902
Epoch 76/200
45000/45000 [==============================] - 9s - loss: 0.2841 - acc: 0.9053 - val_loss: 0.7695 - val_acc: 0.7990
Epoch 77/200
45000/45000 [==============================] - 9s - loss: 0.2853 - acc: 0.9061 - val_loss: 0.7608 - val_acc: 0.7972
Epoch 78/200
45000/45000 [==============================] - 9s - loss: 0.2714 - acc: 0.9080 - val_loss: 0.7534 - val_acc: 0.8034
Epoch 79/200
45000/45000 [==============================] - 9s - loss: 0.2797 - acc: 0.9072 - val_loss: 0.7188 - val_acc: 0.7988
Epoch 80/200
45000/45000 [==============================] - 9s - loss: 0.2682 - acc: 0.9110 - val_loss: 0.7751 - val_acc: 0.7954
Epoch 81/200
45000/45000 [==============================] - 9s - loss: 0.2885 - acc: 0.9038 - val_loss: 0.7711 - val_acc: 0.8010
Epoch 82/200
45000/45000 [==============================] - 9s - loss: 0.2705 - acc: 0.9094 - val_loss: 0.7613 - val_acc: 0.8000
Epoch 83/200
45000/45000 [==============================] - 9s - loss: 0.2738 - acc: 0.9095 - val_loss: 0.8300 - val_acc: 0.7944
Epoch 84/200
45000/45000 [==============================] - 9s - loss: 0.2795 - acc: 0.9066 - val_loss: 0.8001 - val_acc: 0.7912
Epoch 85/200
45000/45000 [==============================] - 9s - loss: 0.2721 - acc: 0.9086 - val_loss: 0.7862 - val_acc: 0.8092
Epoch 86/200
45000/45000 [==============================] - 9s - loss: 0.2752 - acc: 0.9087 - val_loss: 0.7331 - val_acc: 0.7942
Epoch 87/200
45000/45000 [==============================] - 9s - loss: 0.2725 - acc: 0.9089 - val_loss: 0.7999 - val_acc: 0.7914
Epoch 88/200
45000/45000 [==============================] - 9s - loss: 0.2644 - acc: 0.9108 - val_loss: 0.7944 - val_acc: 0.7990
Epoch 89/200
45000/45000 [==============================] - 9s - loss: 0.2725 - acc: 0.9106 - val_loss: 0.7622 - val_acc: 0.8006
Epoch 90/200
45000/45000 [==============================] - 9s - loss: 0.2622 - acc: 0.9129 - val_loss: 0.8172 - val_acc: 0.7988
Epoch 91/200
45000/45000 [==============================] - 9s - loss: 0.2772 - acc: 0.9085 - val_loss: 0.8243 - val_acc: 0.8004
Epoch 92/200
45000/45000 [==============================] - 9s - loss: 0.2609 - acc: 0.9136 - val_loss: 0.7723 - val_acc: 0.7992
Epoch 93/200
45000/45000 [==============================] - 9s - loss: 0.2666 - acc: 0.9129 - val_loss: 0.8366 - val_acc: 0.7932
Epoch 94/200
45000/45000 [==============================] - 9s - loss: 0.2593 - acc: 0.9135 - val_loss: 0.8666 - val_acc: 0.7956
Epoch 95/200
45000/45000 [==============================] - 9s - loss: 0.2692 - acc: 0.9100 - val_loss: 0.8901 - val_acc: 0.7954
Epoch 96/200
45000/45000 [==============================] - 8s - loss: 0.2569 - acc: 0.9160 - val_loss: 0.8515 - val_acc: 0.8006
Epoch 97/200
45000/45000 [==============================] - 8s - loss: 0.2636 - acc: 0.9146 - val_loss: 0.8639 - val_acc: 0.7960
Epoch 98/200
45000/45000 [==============================] - 9s - loss: 0.2693 - acc: 0.9113 - val_loss: 0.7891 - val_acc: 0.7916
Epoch 99/200
45000/45000 [==============================] - 9s - loss: 0.2611 - acc: 0.9144 - val_loss: 0.8650 - val_acc: 0.7928
Epoch 100/200
45000/45000 [==============================] - 9s - loss: 0.2589 - acc: 0.9121 - val_loss: 0.8683 - val_acc: 0.7990
Epoch 101/200
45000/45000 [==============================] - 9s - loss: 0.2601 - acc: 0.9142 - val_loss: 0.9116 - val_acc: 0.8030
Epoch 102/200
45000/45000 [==============================] - 9s - loss: 0.2616 - acc: 0.9138 - val_loss: 0.8229 - val_acc: 0.7928
Epoch 103/200
45000/45000 [==============================] - 9s - loss: 0.2603 - acc: 0.9140 - val_loss: 0.8847 - val_acc: 0.7994
Epoch 104/200
45000/45000 [==============================] - 9s - loss: 0.2579 - acc: 0.9150 - val_loss: 0.9079 - val_acc: 0.8004
Epoch 105/200
45000/45000 [==============================] - 8s - loss: 0.2696 - acc: 0.9127 - val_loss: 0.7450 - val_acc: 0.8002
Epoch 106/200
45000/45000 [==============================] - 9s - loss: 0.2555 - acc: 0.9161 - val_loss: 0.8186 - val_acc: 0.7992
Epoch 107/200
45000/45000 [==============================] - 9s - loss: 0.2631 - acc: 0.9160 - val_loss: 0.8686 - val_acc: 0.7920
Epoch 108/200
45000/45000 [==============================] - 9s - loss: 0.2524 - acc: 0.9178 - val_loss: 0.9136 - val_acc: 0.7956
Epoch 109/200
45000/45000 [==============================] - 9s - loss: 0.2569 - acc: 0.9151 - val_loss: 0.8148 - val_acc: 0.7994
Epoch 110/200
45000/45000 [==============================] - 9s - loss: 0.2586 - acc: 0.9150 - val_loss: 0.8826 - val_acc: 0.7984
Epoch 111/200
45000/45000 [==============================] - 9s - loss: 0.2520 - acc: 0.9155 - val_loss: 0.8621 - val_acc: 0.7980
Epoch 112/200
45000/45000 [==============================] - 9s - loss: 0.2586 - acc: 0.9157 - val_loss: 0.8149 - val_acc: 0.8038
Epoch 113/200
45000/45000 [==============================] - 9s - loss: 0.2623 - acc: 0.9151 - val_loss: 0.8361 - val_acc: 0.7972
Epoch 114/200
45000/45000 [==============================] - 9s - loss: 0.2535 - acc: 0.9177 - val_loss: 0.8618 - val_acc: 0.7970
Epoch 115/200
45000/45000 [==============================] - 8s - loss: 0.2570 - acc: 0.9164 - val_loss: 0.7687 - val_acc: 0.8044
Epoch 116/200
45000/45000 [==============================] - 9s - loss: 0.2501 - acc: 0.9183 - val_loss: 0.8270 - val_acc: 0.7934
Epoch 117/200
45000/45000 [==============================] - 8s - loss: 0.2535 - acc: 0.9182 - val_loss: 0.7861 - val_acc: 0.7986
Epoch 118/200
45000/45000 [==============================] - 9s - loss: 0.2507 - acc: 0.9184 - val_loss: 0.8203 - val_acc: 0.7996
Epoch 119/200
45000/45000 [==============================] - 9s - loss: 0.2530 - acc: 0.9173 - val_loss: 0.8294 - val_acc: 0.7904
Epoch 120/200
45000/45000 [==============================] - 9s - loss: 0.2599 - acc: 0.9160 - val_loss: 0.8458 - val_acc: 0.7902
Epoch 121/200
45000/45000 [==============================] - 9s - loss: 0.2483 - acc: 0.9164 - val_loss: 0.7573 - val_acc: 0.7976
Epoch 122/200
45000/45000 [==============================] - 8s - loss: 0.2492 - acc: 0.9190 - val_loss: 0.8435 - val_acc: 0.8012
Epoch 123/200
45000/45000 [==============================] - 9s - loss: 0.2528 - acc: 0.9179 - val_loss: 0.8594 - val_acc: 0.7964
Epoch 124/200
45000/45000 [==============================] - 9s - loss: 0.2581 - acc: 0.9173 - val_loss: 0.9037 - val_acc: 0.7944
Epoch 125/200
45000/45000 [==============================] - 8s - loss: 0.2404 - acc: 0.9212 - val_loss: 0.7893 - val_acc: 0.7976
Epoch 126/200
45000/45000 [==============================] - 8s - loss: 0.2492 - acc: 0.9177 - val_loss: 0.8679 - val_acc: 0.7982
Epoch 127/200
45000/45000 [==============================] - 8s - loss: 0.2483 - acc: 0.9196 - val_loss: 0.8894 - val_acc: 0.7956
Epoch 128/200
45000/45000 [==============================] - 9s - loss: 0.2539 - acc: 0.9176 - val_loss: 0.8413 - val_acc: 0.8006
Epoch 129/200
45000/45000 [==============================] - 8s - loss: 0.2477 - acc: 0.9184 - val_loss: 0.8151 - val_acc: 0.7982
Epoch 130/200
45000/45000 [==============================] - 9s - loss: 0.2586 - acc: 0.9188 - val_loss: 0.8173 - val_acc: 0.7954
Epoch 131/200
45000/45000 [==============================] - 9s - loss: 0.2498 - acc: 0.9189 - val_loss: 0.8539 - val_acc: 0.7996
Epoch 132/200
45000/45000 [==============================] - 9s - loss: 0.2426 - acc: 0.9190 - val_loss: 0.8543 - val_acc: 0.7952
Epoch 133/200
45000/45000 [==============================] - 9s - loss: 0.2460 - acc: 0.9185 - val_loss: 0.8665 - val_acc: 0.8008
Epoch 134/200
45000/45000 [==============================] - 9s - loss: 0.2436 - acc: 0.9216 - val_loss: 0.8933 - val_acc: 0.7950
Epoch 135/200
45000/45000 [==============================] - 8s - loss: 0.2468 - acc: 0.9203 - val_loss: 0.8270 - val_acc: 0.7940
Epoch 136/200
45000/45000 [==============================] - 9s - loss: 0.2479 - acc: 0.9194 - val_loss: 0.8365 - val_acc: 0.8052
Epoch 137/200
45000/45000 [==============================] - 9s - loss: 0.2449 - acc: 0.9206 - val_loss: 0.7964 - val_acc: 0.8018
Epoch 138/200
45000/45000 [==============================] - 9s - loss: 0.2440 - acc: 0.9220 - val_loss: 0.8784 - val_acc: 0.7914
Epoch 139/200
45000/45000 [==============================] - 9s - loss: 0.2485 - acc: 0.9198 - val_loss: 0.8259 - val_acc: 0.7852
Epoch 140/200
45000/45000 [==============================] - 9s - loss: 0.2482 - acc: 0.9204 - val_loss: 0.8954 - val_acc: 0.7960
Epoch 141/200
45000/45000 [==============================] - 9s - loss: 0.2344 - acc: 0.9249 - val_loss: 0.8708 - val_acc: 0.7874
Epoch 142/200
45000/45000 [==============================] - 9s - loss: 0.2476 - acc: 0.9204 - val_loss: 0.9190 - val_acc: 0.7954
Epoch 143/200
45000/45000 [==============================] - 9s - loss: 0.2415 - acc: 0.9223 - val_loss: 0.9607 - val_acc: 0.7960
Epoch 144/200
45000/45000 [==============================] - 9s - loss: 0.2377 - acc: 0.9232 - val_loss: 0.8987 - val_acc: 0.7970
Epoch 145/200
45000/45000 [==============================] - 9s - loss: 0.2481 - acc: 0.9201 - val_loss: 0.8611 - val_acc: 0.8048
Epoch 146/200
45000/45000 [==============================] - 9s - loss: 0.2504 - acc: 0.9197 - val_loss: 0.8411 - val_acc: 0.7938
Epoch 147/200
45000/45000 [==============================] - 9s - loss: 0.2450 - acc: 0.9216 - val_loss: 0.7839 - val_acc: 0.8028
Epoch 148/200
45000/45000 [==============================] - 9s - loss: 0.2327 - acc: 0.9250 - val_loss: 0.8910 - val_acc: 0.8054
Epoch 149/200
45000/45000 [==============================] - 9s - loss: 0.2432 - acc: 0.9219 - val_loss: 0.8568 - val_acc: 0.8000
Epoch 150/200
45000/45000 [==============================] - 9s - loss: 0.2436 - acc: 0.9236 - val_loss: 0.9061 - val_acc: 0.7938
Epoch 151/200
45000/45000 [==============================] - 9s - loss: 0.2434 - acc: 0.9222 - val_loss: 0.8439 - val_acc: 0.7986
Epoch 152/200
45000/45000 [==============================] - 9s - loss: 0.2439 - acc: 0.9225 - val_loss: 0.9002 - val_acc: 0.7994
Epoch 153/200
45000/45000 [==============================] - 8s - loss: 0.2373 - acc: 0.9237 - val_loss: 0.8756 - val_acc: 0.7880
Epoch 154/200
45000/45000 [==============================] - 8s - loss: 0.2359 - acc: 0.9238 - val_loss: 0.8514 - val_acc: 0.7936
Epoch 155/200
45000/45000 [==============================] - 9s - loss: 0.2435 - acc: 0.9222 - val_loss: 0.8377 - val_acc: 0.8080
Epoch 156/200
45000/45000 [==============================] - 9s - loss: 0.2478 - acc: 0.9204 - val_loss: 0.8831 - val_acc: 0.7992
Epoch 157/200
45000/45000 [==============================] - 9s - loss: 0.2337 - acc: 0.9253 - val_loss: 0.8453 - val_acc: 0.7994
Epoch 158/200
45000/45000 [==============================] - 9s - loss: 0.2336 - acc: 0.9257 - val_loss: 0.9027 - val_acc: 0.7882
Epoch 159/200
45000/45000 [==============================] - 9s - loss: 0.2384 - acc: 0.9230 - val_loss: 0.9121 - val_acc: 0.8016
Epoch 160/200
45000/45000 [==============================] - 9s - loss: 0.2481 - acc: 0.9217 - val_loss: 0.9495 - val_acc: 0.7974
Epoch 161/200
45000/45000 [==============================] - 9s - loss: 0.2450 - acc: 0.9224 - val_loss: 0.8510 - val_acc: 0.7884
Epoch 162/200
45000/45000 [==============================] - 9s - loss: 0.2433 - acc: 0.9220 - val_loss: 0.8979 - val_acc: 0.7948
Epoch 163/200
45000/45000 [==============================] - 9s - loss: 0.2339 - acc: 0.9262 - val_loss: 0.8979 - val_acc: 0.7978
Epoch 164/200
45000/45000 [==============================] - 9s - loss: 0.2298 - acc: 0.9257 - val_loss: 0.9036 - val_acc: 0.7990
Epoch 165/200
45000/45000 [==============================] - 9s - loss: 0.2404 - acc: 0.9236 - val_loss: 0.8341 - val_acc: 0.8052
Epoch 166/200
45000/45000 [==============================] - 9s - loss: 0.2402 - acc: 0.9227 - val_loss: 0.8731 - val_acc: 0.7996
Epoch 167/200
45000/45000 [==============================] - 9s - loss: 0.2367 - acc: 0.9250 - val_loss: 0.9218 - val_acc: 0.7992
Epoch 168/200
45000/45000 [==============================] - 9s - loss: 0.2267 - acc: 0.9262 - val_loss: 0.8767 - val_acc: 0.7922
Epoch 169/200
45000/45000 [==============================] - 9s - loss: 0.2336 - acc: 0.9254 - val_loss: 0.8418 - val_acc: 0.8038
Epoch 170/200
45000/45000 [==============================] - 9s - loss: 0.2434 - acc: 0.9232 - val_loss: 0.8362 - val_acc: 0.7920
Epoch 171/200
45000/45000 [==============================] - 9s - loss: 0.2328 - acc: 0.9265 - val_loss: 0.8712 - val_acc: 0.7950
Epoch 172/200
45000/45000 [==============================] - 9s - loss: 0.2346 - acc: 0.9262 - val_loss: 0.9256 - val_acc: 0.7976
Epoch 173/200
45000/45000 [==============================] - 8s - loss: 0.2382 - acc: 0.9242 - val_loss: 0.8875 - val_acc: 0.7982
Epoch 174/200
45000/45000 [==============================] - 9s - loss: 0.2400 - acc: 0.9239 - val_loss: 0.8264 - val_acc: 0.7864
Epoch 175/200
45000/45000 [==============================] - 9s - loss: 0.2334 - acc: 0.9261 - val_loss: 0.9178 - val_acc: 0.8014
Epoch 176/200
45000/45000 [==============================] - 9s - loss: 0.2427 - acc: 0.9219 - val_loss: 0.8458 - val_acc: 0.7920
Epoch 177/200
45000/45000 [==============================] - 9s - loss: 0.2310 - acc: 0.9257 - val_loss: 0.9171 - val_acc: 0.8062
Epoch 178/200
45000/45000 [==============================] - 9s - loss: 0.2310 - acc: 0.9265 - val_loss: 0.8544 - val_acc: 0.7990
Epoch 179/200
45000/45000 [==============================] - 9s - loss: 0.2378 - acc: 0.9240 - val_loss: 0.9259 - val_acc: 0.8000
Epoch 180/200
45000/45000 [==============================] - 9s - loss: 0.2381 - acc: 0.9242 - val_loss: 0.8573 - val_acc: 0.8056
Epoch 181/200
45000/45000 [==============================] - 9s - loss: 0.2231 - acc: 0.9297 - val_loss: 0.8935 - val_acc: 0.8002
Epoch 182/200
45000/45000 [==============================] - 9s - loss: 0.2419 - acc: 0.9248 - val_loss: 1.0145 - val_acc: 0.7900
Epoch 183/200
45000/45000 [==============================] - 9s - loss: 0.2336 - acc: 0.9266 - val_loss: 0.8838 - val_acc: 0.8006
Epoch 184/200
45000/45000 [==============================] - 9s - loss: 0.2429 - acc: 0.9242 - val_loss: 0.8685 - val_acc: 0.7918
Epoch 185/200
45000/45000 [==============================] - 9s - loss: 0.2317 - acc: 0.9260 - val_loss: 0.8297 - val_acc: 0.7942
Epoch 186/200
45000/45000 [==============================] - 9s - loss: 0.2330 - acc: 0.9264 - val_loss: 0.8831 - val_acc: 0.8026
Epoch 187/200
45000/45000 [==============================] - 9s - loss: 0.2353 - acc: 0.9254 - val_loss: 0.8934 - val_acc: 0.7956
Epoch 188/200
45000/45000 [==============================] - 9s - loss: 0.2312 - acc: 0.9247 - val_loss: 0.9275 - val_acc: 0.8042
Epoch 189/200
45000/45000 [==============================] - 9s - loss: 0.2239 - acc: 0.9282 - val_loss: 0.9246 - val_acc: 0.7934
Epoch 190/200
45000/45000 [==============================] - 9s - loss: 0.2349 - acc: 0.9253 - val_loss: 0.8628 - val_acc: 0.8000
Epoch 191/200
45000/45000 [==============================] - 9s - loss: 0.2313 - acc: 0.9266 - val_loss: 0.9020 - val_acc: 0.7978
Epoch 192/200
45000/45000 [==============================] - 9s - loss: 0.2358 - acc: 0.9254 - val_loss: 0.9481 - val_acc: 0.7966
Epoch 193/200
45000/45000 [==============================] - 9s - loss: 0.2298 - acc: 0.9276 - val_loss: 0.8791 - val_acc: 0.8010
Epoch 194/200
45000/45000 [==============================] - 9s - loss: 0.2279 - acc: 0.9265 - val_loss: 0.8890 - val_acc: 0.7976
Epoch 195/200
45000/45000 [==============================] - 9s - loss: 0.2330 - acc: 0.9273 - val_loss: 0.8893 - val_acc: 0.7890
Epoch 196/200
45000/45000 [==============================] - 9s - loss: 0.2416 - acc: 0.9243 - val_loss: 0.9002 - val_acc: 0.7922
Epoch 197/200
45000/45000 [==============================] - 9s - loss: 0.2309 - acc: 0.9273 - val_loss: 0.9232 - val_acc: 0.7990
Epoch 198/200
45000/45000 [==============================] - 9s - loss: 0.2247 - acc: 0.9278 - val_loss: 0.9474 - val_acc: 0.7980
Epoch 199/200
45000/45000 [==============================] - 9s - loss: 0.2335 - acc: 0.9256 - val_loss: 0.9177 - val_acc: 0.8000
Epoch 200/200
45000/45000 [==============================] - 9s - loss: 0.2378 - acc: 0.9254 - val_loss: 0.9205 - val_acc: 0.7966
9984/10000 [============================>.] - ETA: 0s




[0.97292723369598388, 0.7853]



Наша модель досягає точності близько 76.6% на тестовій множині; для такої складної задачі, де навіть людський погляд показує точність всього близько 90%, а також враховуючи відносну простоту моделі, це цілком гідний результат. Тим не менш, більш складні моделі в останніх дослідженнях досягали точності 96.53%.

Вважаю, що тонка настройка моделі, якщо у вашому розпорядженні немає графічного процесора, буде вкрай скрутна. Тим не менше, раджу вам спробувати застосувати цю модель до набору MNIST минулого уроку; на CNN з dropout'ом у вас майже без зусиль повинно вийти досягти точності 99.3%.

Висновок
Сьогодні ми вивчили базові поняття згорткових нейронних мереж, розглянули проблему перенавчання і з'ясували в загальних рисах, як її вирішують за допомогою регуляризації (зокрема, методом dropout), а також успішно побудували чотиришарову глибоку CNN в Keras, протестувавши її на CIFAR-10 і вклавшись у 50 рядків коду.

Наступного разу ми розглянемо відразу кілька тем, вивчимо прийоми і хитрощі, пов'язані з тонкою настройкою моделей, досягнення максимальної продуктивності і контролем за перенавчанням.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.