Класификация на изображенията на TensorFlow: CNN (конволюционна невронна мрежа)

Съдържание:

Anonim

Какво е конволюционната невронна мрежа?

Конволюционната невронна мрежа, известна още като convnets или CNN, е добре познат метод в приложенията за компютърно зрение. Този тип архитектура е доминираща за разпознаване на обекти от картина или видео.

В този урок ще научите как да изградите convnet и как да използвате TensorFlow за решаване на ръкописния набор от данни.

В този урок ще научите

  • Конволюционна невронна мрежа
  • Архитектура на конволюционна невронна мрежа
  • Компоненти на Convnets
  • Тренирайте CNN с TensorFlow
  • Стъпка 1: Качване на набор от данни
  • Стъпка 2: Входен слой
  • Стъпка 3: Конволюционен слой
  • Стъпка 4: Обединяване на слой
  • Стъпка 5: Втори конволюционен слой и слой за обединяване
  • Стъпка 6: Плътен слой
  • Стъпка 7: Logit Layer

Архитектура на конволюционна невронна мрежа

Помислете за Facebook преди няколко години, след като качихте снимка в профила си, бяхте помолени да добавите име към лицето на снимката ръчно. В днешно време Facebook използва convnet, за да маркира автоматично вашия приятел на снимката.

Конволюционната невронна мрежа не е много трудна за разбиране. Входно изображение се обработва по време на фазата на конволюция и по-късно се приписва етикет.

Типична convnet архитектура може да бъде обобщена на снимката по-долу. На първо място, изображението се избутва в мрежата; това се нарича входно изображение. След това входното изображение преминава през безкраен брой стъпки; това е конволюционната част на мрежата. И накрая, невронната мрежа може да предскаже цифрата на изображението.

Изображението е съставено от масив от пиксели с височина и ширина. Изображението в сива скала има само един канал, докато цветното изображение има три канала (всеки за червен, зелен и син). Канал е подреден един върху друг. В този урок ще използвате изображение в сива скала само с един канал. Всеки пиксел има стойност от 0 до 255, за да отразява интензивността на цвета. Например, пиксел, равен на 0, ще покаже бял цвят, докато пикселът със стойност, близка до 255, ще бъде по-тъмен.

Нека да разгледаме изображение, съхранено в набора от данни MNIST. На снимката по-долу е показано как да представим снимката отляво в матричен формат. Имайте предвид, че оригиналната матрица е стандартизирана да бъде между 0 и 1. За по-тъмен цвят стойността в матрицата е около 0,9, докато белите пиксели имат стойност 0.

Конволюционна операция

Най-критичният компонент в модела е конволюционният слой. Тази част цели намаляване на размера на изображението за по-бързо изчисляване на теглата и подобряване на неговото обобщаване.

По време на конволюционната част мрежата запазва основните характеристики на изображението и изключва неподходящия шум. Например моделът се учи как да разпознае слон от снимка с планина на заден план. Ако използвате традиционна невронна мрежа, моделът ще присвои тежест на всички пиксели, включително тези от планината, което не е от съществено значение и може да заблуди мрежата.

Вместо това конволюционната невронна мрежа ще използва математическа техника за извличане само на най-подходящите пиксели. Тази математическа операция се нарича конволюция. Тази техника позволява на мрежата да научи все по-сложни функции на всеки слой. Конволюцията разделя матрицата на малки парчета, за да се научи на най-важните елементи във всяка част.

Компоненти на Convnets

Има четири компонента на Convnets

  1. Сгъване
  2. Нелинейност (ReLU)
  3. Обединяване или допълнително вземане на проби
  4. Класификация (Напълно свързан слой)
  • Сгъване

Целта на конволюцията е да извлече характеристиките на обекта върху изображението локално. Това означава, че мрежата ще научи специфични модели в картината и ще може да я разпознае навсякъде в картината.

Конволюцията е умножение по елементи. Концепцията е лесна за разбиране. Компютърът ще сканира част от изображението, обикновено с размери 3x3, и го умножава до филтър. Резултатът от умножението по елементи се нарича карта на характеристиките. Тази стъпка се повтаря, докато цялото изображение се сканира. Имайте предвид, че след конволюцията размерът на изображението се намалява.

По-долу има URL, за да видите в действие как работи конволюцията.

Налични са многобройни канали. По-долу изброихме някои от каналите. Можете да видите, че всеки филтър има определена цел. Забележка, на снимката по-долу; ядрото е синоним на филтъра.

Източник

Аритметика зад конволюцията

Конволюционната фаза ще приложи филтъра върху малък набор от пиксели в картината. Филтърът ще се движи по входното изображение с обща форма 3x3 или 5x5. Това означава, че мрежата ще плъзне тези прозорци през цялото входно изображение и ще изчисли конволюцията. Изображението по-долу показва как работи конволюцията. Размерът на пластира е 3x3, а изходната матрица е резултат от елементарната операция между матрицата на изображението и филтъра.

Източник

Забелязвате, че ширината и височината на изхода могат да бъдат различни от ширината и височината на входа. Това се случва поради граничния ефект.

Граничен ефект

Изображението има карта с 5x5 функции и 3x3 филтър. Има само един прозорец в центъра, където филтърът може да прожектира мрежа 3x3. Картата на изходните характеристики ще се свие с две плочки заедно с размер 3x3.

За да получите същото изходно измерение като входното измерение, трябва да добавите подложка. Запълването се състои от добавяне на правилния брой редове и колони от всяка страна на матрицата. Това ще позволи на конволюцията да попадне във всяка плочка за въвеждане. На изображението по-долу входно / изходната матрица има същите размери 5x5

Когато дефинирате мрежата, сгънатите функции се контролират от три параметъра:

  1. Дълбочина: Той определя броя на филтрите, които да се прилагат по време на конволюцията. В предишния пример видяхте дълбочина 1, което означава, че се използва само един филтър. В повечето случаи има повече от един филтър. На снимката по-долу са показани операциите, извършени в ситуация с три филтъра

  1. Крачка: Определя броя на „скока на пиксела“ между два среза. Ако крачката е равна на 1, прозорците ще се движат с пикселно разпръскване на един. Ако крачката е равна на две, прозорците ще скочат с 2 пиксела. Ако увеличите крачката, ще имате по-малки карти с функции.

Примерна стъпка 1

Стъпка на изображението 2

  1. Нулево подпълване: Подложката е операция за добавяне на съответния брой редове и колони от всяка страна на картите на входните характеристики. В този случай изходът има същото измерение като входа.
  2. Нелинейност (ReLU)

В края на операцията на конволюцията изходът подлежи на функция за активиране, която позволява нелинейност. Обичайната функция за активиране на convnet е Relu. Всички пиксели с отрицателна стойност ще бъдат заменени с нула.

  • Операция за максимално обединяване

Тази стъпка е лесна за разбиране. Целта на обединяването е да намали размерите на входното изображение. Стъпките се правят, за да се намали изчислителната сложност на операцията. Чрез намаляване на размерите, мрежата има по-ниски тегла за изчисляване, така че предотвратява пренастройването.

На този етап трябва да определите размера и крачката. Стандартният начин за обединяване на входното изображение е да се използва максималната стойност на картата на характеристиките. Погледнете снимката по-долу. "Обединяването" ще покаже четири подматрици от картата на характеристиките 4x4 и ще върне максималната стойност. Обединяването взема максималната стойност на масив 2x2 и след това премества този прозорец с два пиксела. Например първата подматрица е [3,1,3,2], обединяването ще върне максимума, който е 3.

Има и друга операция за обединяване като средната стойност.

Тази операция намалява агресивно размера на картата на характеристиките

  • Напълно свързани слоеве

Последната стъпка се състои в изграждането на традиционна изкуствена невронна мрежа, както направихте в предишния урок. Свързвате всички неврони от предишния слой към следващия слой. Използвате функция за активиране на softmax, за да класифицирате номера на входното изображение.

Обобщение:

Конволюционната невронна мрежа компилира различни слоеве, преди да направи прогноза. Невронната мрежа има:

  • Конволюционен слой
  • Функция за активиране на Relu
  • Обединяващ слой
  • Плътно свързан слой

Конволюционните слоеве прилагат различни филтри върху подрегиона на картината. Функцията за активиране на Relu добавя нелинейност, а обединяващите слоеве намаляват размерите на картите на характеристиките.

Всички тези слоеве извличат важна информация от изображенията. Най-накрая картата на характеристиките се подава към първичен напълно свързан слой с функция softmax, за да направи прогноза.

Тренирайте CNN с TensorFlow

След като вече сте запознати със строителния блок на convnets, сте готови да изградите такъв с TensorFlow. Ще използваме набора от данни MNIST за класификация на изображенията.

Подготовката на данните е същата като предишния урок. Можете да стартирате кодовете и да преминете директно към архитектурата на CNN.

Ще следвате стъпките по-долу:

Стъпка 1: Качване на набор от данни

Стъпка 2: Входен слой

Стъпка 3: Конволюционен слой

Стъпка 4: Обединяване на слой

Стъпка 5: Втори конволюционен слой и слой за обединяване

Стъпка 6: Плътен слой

Стъпка 7: Logit Layer

Стъпка 1: Качване на набор от данни

Наборът от данни MNIST е достъпен с scikit, за да се учи на този URL адрес. Моля, изтеглете го и го съхранявайте в Downloads. Можете да го качите с fetch_mldata ('MNIST оригинал').

Създайте комплект за влак / тест

Трябва да разделите набора от данни с train_test_split

Мащабирайте функциите

И накрая, можете да мащабирате функцията с MinMaxScaler

import numpy as npimport tensorflow as tffrom sklearn.datasets import fetch_mldata#Change USERNAME by the username of your machine## Windows USERmnist = fetch_mldata('C:\\Users\\USERNAME\\Downloads\\MNIST original')## Mac Usermnist = fetch_mldata('/Users/USERNAME/Downloads/MNIST original')print(mnist.data.shape)print(mnist.target.shape)from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(mnist.data, mnist.target, test_size=0.2, random_state=42)y_train = y_train.astype(int)y_test = y_test.astype(int)batch_size =len(X_train)print(X_train.shape, y_train.shape,y_test.shape )## resclaefrom sklearn.preprocessing import MinMaxScalerscaler = MinMaxScaler()# TrainX_train_scaled = scaler.fit_transform(X_train.astype(np.float64))# testX_test_scaled = scaler.fit_transform(X_test.astype(np.float64))feature_columns = [tf.feature_column.numeric_column('x', shape=X_train_scaled.shape[1:])]X_train_scaled.shape[1:]

Определете CNN

CNN използва филтри върху суровия пиксел на изображението, за да научи детайлите на модела в сравнение с глобалния модел с традиционна невронна мрежа. За да изградите CNN, трябва да дефинирате:

  1. Конволюционен слой: Приложете n броя филтри към картата на характеристиките. След конволюцията трябва да използвате функция за активиране на Relu, за да добавите нелинейност към мрежата.
  2. Обединяващ слой: Следващата стъпка след конволюцията е да дескретизирате макс. Целта е да се намали размерът на картата на характеристиките, за да се предотврати пренастройването и да се подобри скоростта на изчисление. Максималното обединяване е конвенционалната техника, която разделя характеристиките на подрегиони (обикновено с размер 2х2) и запазва само максималните стойности.
  3. Напълно свързани слоеве: Всички неврони от предишните слоеве са свързани към следващите слоеве. CNN ще класифицира етикета според характеристиките от конволюционните слоеве и намалени със слоя за обединяване.

Архитектура на CNN

  • Конволюционен слой: Прилага 14 филтъра 5x5 (извличане на 5x5-пикселни подрегиони), с функция за активиране на ReLU
  • Слой за обединяване: Извършва максимално обединяване с филтър 2x2 и стъпка от 2 (което указва, че обединените региони не се припокриват)
  • Конволюционен слой: Прилага 36 филтъра 5x5, с функция за активиране на ReLU
  • Обединяване на слой №2: Отново извършва максимално обединяване с 2x2 филтър и стъпка от 2
  • 1764 неврона, със степен на регулиране на отпадането от 0,4 (вероятност от 0,4, че даден елемент ще отпадне по време на обучението)
  • Плътен слой (Logits Layer): 10 неврона, по един за всеки цифров целеви клас (0-9).

Има три важни модула, които да използвате за създаване на CNN:

  • conv2d (). Конструира двуизмерен конволюционен слой с брой филтри, размер на ядрото на филтъра, запълване и функция за активиране като аргументи.
  • max_pooling2d (). Изгражда двуизмерен слой за обединяване, използвайки алгоритъма за максимално обединяване.
  • плътен (). Изгражда плътен слой със скритите слоеве и единици

Ще дефинирате функция за изграждане на CNN. Нека да видим подробно как да конструираме всеки градивен блок, преди да обгърнем всичко заедно във функцията.

Стъпка 2: Входен слой

def cnn_model_fn(features, labels, mode):input_layer = tf.reshape(tensor = features["x"],shape =[-1, 28, 28, 1])

Трябва да дефинирате тензор с формата на данните. За това можете да използвате модула tf.reshape. В този модул трябва да декларирате тензора за преоформяне и формата на тензора. Първият аргумент са характеристиките на данните, които са дефинирани в аргумента на функцията.

Картината има височина, ширина и канал. Наборът от данни MNIST е монохронна картина с размер 28x28. Задаваме размера на партидата на -1 в аргумента за форма, така че да приема формата на характеристиките ["x"]. Предимството е да се настроят хиперпараметрите за размера на партидата. Ако размерът на партидата е зададен на 7, тогава тензорът ще подаде 5488 стойности (28 * 28 * 7).

Step 3: Convolutional layer
# first Convolutional Layerconv1 = tf.layers.conv2d(inputs=input_layer,filters=14,kernel_size=[5, 5],padding="same",activation=tf.nn.relu)

Първият конволюционен слой има 14 филтъра с размер на ядрото 5x5 със същата подложка. Една и съща подложка означава, че изходният тензор и входният тензор трябва да имат еднаква височина и ширина. Tensorflow ще добави нули към редовете и колоните, за да осигури еднакъв размер.

Използвате функцията за активиране на Relu. Изходният размер ще бъде [28, 28, 14].

Стъпка 4: Обединяване на слой

Следващата стъпка след конволюцията е изчисляването на обединяването. Изчисляването на обединяването ще намали размерността на данните. Можете да използвате модула max_pooling2d с размер 2x2 и стъпка 2. Използвате предишния слой като вход. Изходният размер ще бъде [batch_size, 14, 14, 14]

# first Pooling Layerpool1 = tf.layers.max_pooling2d(inputs=conv1, pool_size=[2, 2], strides=2)

Стъпка 5: Втори конволюционен слой и слой за обединяване

Вторият конволюционен слой има 32 филтъра, с изходен размер [batch_size, 14, 14, 32]. Обединяващият слой има същия размер като преди и изходната форма е [batch_size, 14, 14, 18].

conv2 = tf.layers.conv2d(inputs=pool1,filters=36,kernel_size=[5, 5],padding="same",activation=tf.nn.relu)pool2 = tf.layers.max_pooling2d(inputs=conv2, pool_size=[2, 2], strides=2)

Стъпка 6: Плътен слой

След това трябва да дефинирате напълно свързания слой. Картата на характеристиките трябва да бъде изравнена, преди да бъде свързана с плътния слой. Можете да използвате преобразуването на модула с размер 7 * 7 * 36.

Плътният слой ще свързва 1764 неврона. Добавяте функция за активиране на Relu. Освен това добавяте термин за регулиране на отпадане със скорост 0,3, което означава, че 30 процента от тежестите ще бъдат настроени на 0. Имайте предвид, че отпадането се извършва само по време на фазата на обучение. Функцията cnn_model_fn има аргументен режим, за да декларира дали моделът трябва да бъде обучен или да оцени.

pool2_flat = tf.reshape(pool2, [-1, 7 * 7 * 36])dense = tf.layers.dense(inputs=pool2_flat, units=7 * 7 * 36, activation=tf.nn.relu)dropout = tf.layers.dropout(inputs=dense, rate=0.3, training=mode == tf.estimator.ModeKeys.TRAIN)

Стъпка 7: Logit Layer

И накрая, можете да определите последния слой с прогнозата на модела. Изходната форма е равна на размера на партидата и 10, общия брой изображения.

# Logits Layerlogits = tf.layers.dense(inputs=dropout, units=10) 

Можете да създадете речник, съдържащ класовете и вероятността за всеки клас. Модулът tf.argmax () с връща най-високата стойност, ако logit слоеве. Функцията softmax връща вероятността за всеки клас.

predictions = {# Generate predictions"classes": tf.argmax(input=logits, axis=1),"probabilities": tf.nn.softmax(logits, name="softmax_tensor") }

Искате да върнете предсказанието на дикцията само когато режимът е зададен на предсказване. Добавяте тези кодове, за да покажете прогнозите

if mode == tf.estimator.ModeKeys.PREDICT:return tf.estimator.EstimatorSpec(mode=mode, predictions=predictions)

Следващата стъпка се състои в изчисляване на загубата на модела. В последния урок научихте, че функцията за загуба за многокласов модел е кръстосана ентропия. Загубата лесно се изчислява със следния код:

# Calculate Loss (for both TRAIN and EVAL modes)loss = tf.losses.sparse_softmax_cross_entropy(labels=labels, logits=logits)

Последната стъпка е да се оптимизира моделът, тоест да се намерят най-добрите стойности на теглата. За това използвате оптимизатор за градиентно спускане със скорост на обучение 0,001. Целта е да се минимизират загубите

optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001)train_op = optimizer.minimize(loss=loss,global_step=tf.train.get_global_step())

Приключихте с CNN. Искате обаче да покажете показателите за ефективност по време на режима на оценка. Показателите за ефективност за многокласов модел са метриките за точност. Tensorflow е оборудван с точност на модула с два аргумента, етикетите и прогнозираните стойности.

eval_metric_ops = {"accuracy": tf.metrics.accuracy(labels=labels, predictions=predictions["classes"])}return tf.estimator.EstimatorSpec(mode=mode, loss=loss, eval_metric_ops=eval_metric_ops)

Това е. Създадохте първата си CNN и сте готови да увиете всичко във функция, за да я използвате за обучение и оценка на модела.

def cnn_model_fn(features, labels, mode):"""Model function for CNN."""# Input Layerinput_layer = tf.reshape(features["x"], [-1, 28, 28, 1])# Convolutional Layerconv1 = tf.layers.conv2d(inputs=input_layer,filters=32,kernel_size=[5, 5],padding="same",activation=tf.nn.relu)# Pooling Layerpool1 = tf.layers.max_pooling2d(inputs=conv1, pool_size=[2, 2], strides=2)# Convolutional Layer #2 and Pooling Layerconv2 = tf.layers.conv2d(inputs=pool1,filters=36,kernel_size=[5, 5],padding="same",activation=tf.nn.relu)pool2 = tf.layers.max_pooling2d(inputs=conv2, pool_size=[2, 2], strides=2)# Dense Layerpool2_flat = tf.reshape(pool2, [-1, 7 * 7 * 36])dense = tf.layers.dense(inputs=pool2_flat, units=7 * 7 * 36, activation=tf.nn.relu)dropout = tf.layers.dropout(inputs=dense, rate=0.4, training=mode == tf.estimator.ModeKeys.TRAIN)# Logits Layerlogits = tf.layers.dense(inputs=dropout, units=10)predictions = {# Generate predictions (for PREDICT and EVAL mode)"classes": tf.argmax(input=logits, axis=1),"probabilities": tf.nn.softmax(logits, name="softmax_tensor")}if mode == tf.estimator.ModeKeys.PREDICT:return tf.estimator.EstimatorSpec(mode=mode, predictions=predictions)# Calculate Lossloss = tf.losses.sparse_softmax_cross_entropy(labels=labels, logits=logits)# Configure the Training Op (for TRAIN mode)if mode == tf.estimator.ModeKeys.TRAIN:optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001)train_op = optimizer.minimize(loss=loss,global_step=tf.train.get_global_step())return tf.estimator.EstimatorSpec(mode=mode, loss=loss, train_op=train_op)# Add evaluation metrics Evaluation modeeval_metric_ops = {"accuracy": tf.metrics.accuracy(labels=labels, predictions=predictions["classes"])}return tf.estimator.EstimatorSpec(mode=mode, loss=loss, eval_metric_ops=eval_metric_ops)

Стъпките по-долу са същите като предишните уроци.

На първо място, вие дефинирате оценител с модела CNN.

# Create the Estimatormnist_classifier = tf.estimator.Estimator(model_fn=cnn_model_fn, model_dir="train/mnist_convnet_model")

CNN отнема много пъти, за да се обучава, следователно, вие създавате кука за регистриране, за да съхранявате стойностите на слоевете softmax на всеки 50 итерации.

# Set up logging for predictionstensors_to_log = {"probabilities": "softmax_tensor"}logging_hook = tf.train.LoggingTensorHook(tensors=tensors_to_log, every_n_iter=50)

Готови сте да оцените модела. Задавате размер на партидата 100 и разбърквате данните. Имайте предвид, че сме задали стъпки за обучение от 16 000, за да може да отнеме много време да тренирате. Бъди търпелив.

# Train the modeltrain_input_fn = tf.estimator.inputs.numpy_input_fn(x={"x": X_train_scaled},y=y_train,batch_size=100,num_epochs=None,shuffle=True)mnist_classifier.train(input_fn=train_input_fn,steps=16000,hooks=[logging_hook])

Сега, когато моделът е влак, можете да го оцените и да отпечатате резултатите

# Evaluate the model and print resultseval_input_fn = tf.estimator.inputs.numpy_input_fn(x={"x": X_test_scaled},y=y_test,num_epochs=1,shuffle=False)eval_results = mnist_classifier.evaluate(input_fn=eval_input_fn)print(eval_results)
INFO:tensorflow:Calling model_fn.INFO:tensorflow:Done calling model_fn.INFO:tensorflow:Starting evaluation at 2018-08-05-12:52:41INFO:tensorflow:Graph was finalized.INFO:tensorflow:Restoring parameters from train/mnist_convnet_model/model.ckpt-15652INFO:tensorflow:Running local_init_op.INFO:tensorflow:Done running local_init_op.INFO:tensorflow:Finished evaluation at 2018-08-05-12:52:56INFO:tensorflow:Saving dict for global step 15652: accuracy = 0.9589286, global_step = 15652, loss = 0.13894269{'accuracy': 0.9689286, 'loss': 0.13894269, 'global_step': 15652}

С настоящата архитектура получавате точност от 97%. Можете да промените архитектурата, размера на партидата и броя на итерациите, за да подобрите точността. Невронната мрежа на CNN се е представила далеч по-добре от ANN или логистичната регресия. В урока за изкуствената невронна мрежа имате точност от 96%, което е по-ниско от CNN. Изпълненията на CNN са впечатляващи с по-голям набор от изображения , както по отношение на изчисляването на скоростта, така и по отношение на точността.

Обобщение

Конволюционната невронна мрежа работи много добре за оценка на картината. Този тип архитектура е доминираща за разпознаване на обекти от картина или видео.

За да създадете CNN, трябва да изпълните шест стъпки:

Стъпка 1: Входен слой:

Тази стъпка преструктурира данните. Формата е равна на квадратния корен от броя на пикселите. Например, ако снимката има 156 пиксела, тогава формата е 26x26. Трябва да посочите дали картината има цвят или не. Ако отговорът е да, тогава сте имали 3 във формата - 3 за RGB-, в противен случай 1.

input_layer = tf.reshape(tensor = features["x"],shape =[-1, 28, 28, 1]) 

Стъпка 2: Конволюционен слой

След това трябва да създадете конволюционните слоеве. Прилагате различни филтри, за да позволите на мрежата да научи важна функция. Вие посочвате размера на ядрото и количеството филтри.

conv1 = tf.layers.conv2d(inputs=input_layer,filters=14,kernel_size=[5, 5],padding="same",activation=tf.nn.relu)

Стъпка 3: Обединяване на слой

В третата стъпка добавяте обединяващ слой. Този слой намалява размера на входа. Това се прави, като се вземе максималната стойност на подматрицата. Например, ако подматрицата е [3,1,3,2], обединяването ще върне максимума, който е 3.

pool1 = tf.layers.max_pooling2d(inputs=conv1, pool_size=[2, 2], strides=2) 

Стъпка 4: Добавете сложен слой и слой за обединяване

В тази стъпка можете да добавите колкото искате слоеве conv и слоеве за обединяване. Google използва архитектура с повече от 20 слоя conv.

Стъпка 5: Плътен слой

Стъпка 5 изравнява предишната, за да създаде напълно свързани слоеве. В тази стъпка можете да използвате различна функция за активиране и да добавите ефект на отпадане.

pool2_flat = tf.reshape(pool2, [-1, 7 * 7 * 36])dense = tf.layers.dense(inputs=pool2_flat, units=7 * 7 * 36, activation=tf.nn.relu)dropout = tf.layers.dropout(inputs=dense, rate=0.3, training=mode == tf.estimator.ModeKeys.TRAIN)

Стъпка 6: Logit Layer

Последната стъпка е прогнозата.

logits = tf.layers.dense(inputs=dropout, units=10)