Мои прошлые блоги TensorFlow освещали основы Tensorflow, построение классификатора с использованием TensorFlow и TensorFlow-lite. Теперь я расскажу, как создать сверточную нейронную сеть (CNN) из скретч для набора данных MNIST .
Надеюсь, вы знакомы с базовой структурой CNN. Если нет, просто исследуйте здесь.
Это блог, в котором весь код !!
Этот блог разделен на следующие основные части:
- Определение функций для ваших слоев
- Создание вашей модели, добавление оптимизатора и прочего
- Настраиваемые генераторы для обучения и проверки.
- Обучение, проверка и окончательные прогнозы с использованием TensorFlow.session ()
Когда вы закончите обновлять свои концепции CNN, давайте запишем все, что нам нужно для полной модели CNN:
- Входы и цель (одна горячая кодировка)
- Слои (свертка, выпадение, максимальный / средний слой пула, плотный, плоский)
- Оптимизатор
- Функция потерь
- Метрика (я бы использовал точность)
И мы закончили !!!
Просто, но не просто
Все коды, указанные в сообщении, можно найти здесь.
Мы также должны помнить, что MNIST имеет формат 1 x 784 для изображений. Следовательно, его необходимо изменить, чтобы сформировать изображение 28 x 28 x 1. Вы можете использовать приведенный ниже код для этого
x=x.values.reshape(-1,28,28,1) tester=y.values.reshape(-1,28,28,1)
Здесь x и y - это данные для обучения и тестирования соответственно. Reshape принимает 4 аргумента:
Последние три относятся к ширине, высоте и каналу (1 для оттенков серого). Первый аргумент «-1» представляет любое число. Это обозначение используется, поскольку «-1» будет включать размер выборки. Как если бы 10 изображений были в обучении. set ,, -1 будет автоматически заменен на 10 (magic😇😇)
Сделайте одно горячее кодирование вашей цели, используя приведенный ниже код
from keras.utils.np_utils import to_categorical z=to_categorical(z,num_classes=10)
Поскольку MNIST имеет 10 категорий (0–9), num_classes = 10, z - целевая переменная.
Итак, начнем !!!
- Ниже приведен блок кода со всеми определенными функциями для различных требуемых уровней.
import tensorflow as tf def conv2d(x,w): weights=tf.Variable(tf.random.normal(w)) return tf.nn.relu(tf.nn.conv2d(x,weights,[1,1,1,1],padding='SAME')) def dropout(x,prob): return tf.nn.dropout(x,prob) def max_pool(x,k): return tf.nn.max_pool(x,k,[1,2,2,1],padding='SAME') def fully_connected(x,size): weights=tf.Variable(tf.random.normal([int(x.get_shape()[1]),size],mean=0,stddev=1)) return tf.matmul(x,weights)
Начиная с самого первого:
- Conv2d (x, w): эта функция используется для создания 2D-слоя свертки. «Вес» в основном относится к фильтрам свертки, которые мы хотим применить к 4 измерениям. Он был инициализирован с использованием нормального распределения.
[ширина, высота, input_channel, output_channel]
Это сильно отличается от того, что мы используем в Керасе !!
Ширина и высота относятся к размерам фильтра, input_channel - это количество каналов во входном изображении (в градациях серого - 1 / в случае RGB - 3), а выходные каналы относятся к количеству используемых фильтров.
Переход к следующей строке:
Уровень tf.nn.conv2d реализует для нас слой Conv2D. Используемые 4 параметра: входные данные, веса, шаг и отступы.
Как шаг = [1,1,1,1]. Лучшее объяснение этому приведено ниже:
Теперь поговорим о padding = ’SAME / VALID’, снова следуйте изображению ниже.
Двигаясь дальше,
def dropout(x,prob): return tf.nn.dropout(x,prob)
Следующая функция - добавить выпадающий слой. Просто помните, что в старых версиях вероятностью является keep_probability, т. Е. если я упомяну 0.9, 10% узлов будут отброшены, что в Керасе наоборот.
def max_pool(x,k): return tf.nn.max_pool(x,k,[1,2,2,1],padding='SAME')
Далее следует слой max_pool. Его также можно заменить слоем average_pool с теми же параметрами. Здесь также 4 параметра в значительной степени похожи, за исключением 'K', который выглядит примерно так [a, b, c, d]. Опять же, a и d представляют пакет и глубину (канал) и не изменяются в целом ( сохранено 1). 'b' и 'c' обозначают размер пула, который может быть 2 x 2, 3 x 3 и т. д.
Теперь самая важная часть
def fully_connected(x,size): weights=tf.Variable(tf.random.normal([int(x.get_shape()[1]),size],mean=0,stddev=1)) return tf.matmul(x,weights)
Это полностью связанный слой / плотный слой. Здесь size = количество узлов для плотного слоя. Снова инициализация весов с помощью normal_distribution. Чтобы понять тензорные формы, посмотрите ниже:
tf.matmul представляет собой матричное умножение (прямое распространение, если вы помните !!!)
Сделано с очень сложными концепциями !!
Вы думаете, что это сделано !!! Это только начало.
Давайте теперь создадим нашу первую CNN:
tf.reset_default_graph() inp=tf.placeholder(tf.float32,shape=(None,28,28,1),name='input') target=tf.placeholder(tf.float32,shape=(None,10),name='target') l1=conv2d(inp,[5,5,1,32]) l2=max_pool(l1,[1,2,2,1]) l9=dropout(l2,0.9) l3=conv2d(l9,[5,5,32,64]) l4=max_pool(l3,[1,2,2,1]) l0=dropout(l4,0.9) l5=tf.reshape(l0,[-1,7*7*64]) l6=fully_connected(l5,10) cost=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=target,logits=l6)) opt=tf.train.AdamOptimizer(0.005).minimize(cost) prediction=tf.argmax(l6,1) result=tf.equal(tf.argmax(l6,1),tf.argmax(target,1)) accuracy=tf.reduce_mean(tf.cast(result,tf.float32))
Сделайте глубокий вдох и ПОГРУЗИТЕСЬ
Следуя кодам построчно:
- Сбросить график по умолчанию
- inp = принимает входные данные, используя заполнитель фигуры (Нет, 28,28,1). Здесь «None» используется для включения размера пакета. Rest - это размер изображения (ширина, высота, канал).
- target = целевая переменная
- l1_layer: 1-й слой Conv2D с размером фильтра 5 x 5, входным каналом 1 и количеством фильтров = 32
- l2_layer: слой Max_Pool с размером пула 2x2
- l9_layer: выпадение 10% узлов (концепция keep_probability используется только в старых версиях). 0.9 означает сохранение 90% узлов
- l3_layer: 2-й слой Conv2D с размером ядра 5 x 5, входной канал = 32 (поскольку мы использовали 32 фильтра в предыдущем уровне пула), а выходные каналы - 64
- l4_layer: аналогичный слой Max_Pool
- l0: выпадающий слой
Помните, что перед вызовом любого плотного / полностью связанного слоя сведите изображение к 1D-массиву.
l5=tf.reshape(l0,[-1,7*7*64]) l6=fully_connected(l5,10)
- l5_layer: он используется для сглаживания изображений, а l6 - это полностью связанный слой, который мы использовали. 10 представляет количество классов (0–9 цифр в MNIST).
[-1,7 * 7 * 64] - это форма, в которой оно должно быть сглажено. 7 * 7 * 64 используется, поскольку слой Max-Pool, используемый дважды, имеет размер 2x2. Следовательно, ширина и высота изображения уменьшаются на коэффициент 4. Следовательно, размеры изменяются с 28 x 28 до 7 x 7. 64 - это количество каналов, поскольку на выходе 2-го слоя Conv2D было 64 канала.
cost=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=target,logits=l6)) opt=tf.train.AdamOptimizer(0.005).minimize(cost) prediction=tf.argmax(l6,1) result=tf.equal(tf.argmax(l6,1),tf.argmax(target,1)) accuracy=tf.reduce_mean(tf.cast(result,tf.float32))
- Эта функция является нашей функцией потерь / затрат. 'Logits' - это прогнозы, а метки - это целевая переменная. Чтобы понять softmax_cross_entropy_with_logits, обратитесь к моему предыдущему блогу. Reduce_mean () усредняет потери для всех изображений пакета
- «Opt» - это оптимизатор, используемый для минимизации затрат, рассчитанных выше.
- прогнозирование берет индекс с наивысшим прогнозируемым значением из вектора размера 10 (выход последнего полностью подключенного уровня). Второй параметр, т.е. 1, представляет ось
- «Результат» должен соответствовать тому, какие прогнозы верны. Он проверяет, равны ли максимальный аргумент от цели (One Hot Encoded, помните) и прогнозы.
- Точность просто вычисляет среднее значение по тензору результата, который имеет значения либо 0 (не равно), либо 1 (равно).
То же самое и с сетью
А теперь кто будет его запускать ???
ТЫ КОНЕЧНО!!!
Пожалуйста, помогите себе с настраиваемыми генераторами, используемыми для обучения и тестирования. Воспользуйтесь помощью здесь.
def train_gen(): image=[] label=[] count=0 for x,y in zip(xtrain,ztrain): if count<8: count+=1 image.append(x) label.append(y) if count==8: yield np.array(image).reshape(-1,28,28,1),np.array(label).reshape(-1,10) count=0 image=[] label=[] def val_gen(): image=[] label=[] count=0 for x,y in zip(xtest,ztest): if count<64: count+=1 image.append(x) label.append(y) if count==64: yield np.array(image).reshape(-1,28,28,1),np.array(label).reshape(-1,10) count=0 image=[] label=[]
Теперь конечный пункт назначения, обучение и проверка сети:
with tf.Session() as sess: sess.run(tf.global_variables_initializer()) for q in range(5): z=train_gen() print("EPOCH="+str(q)) for x,y in z: a,b,c=sess.run([cost,opt,accuracy],feed_dict={'input:0':x,'target:0':y}) result=sess.run([cost,accuracy],feed_dict={'input:0':np.array(xtest).reshape(-1,28,28,1),'target:0':np.array(ztest).reshape(-1,10)}) print("Epoch "+str(q)+" accuracy"+str(result[1])+" loss="+str(result[0])) f=sess.run([prediction],feed_dict={'input:0':tester})
Поскольку я объяснял подобный код в моем предыдущем блоге, я бы просто рассмотрел несколько основных моментов:
- 500 - это эпохи
- xtest (input) и ztest (target) предназначены для проверки. Поскольку я не использовал генератор (хотя и создал его), размер изображений нужно изменить только в feed_dict.
- "F" используется для получения прогнозов от модели.
Наконец-то марафон окончен !!
Ссылка на код:
Https://www.kaggle.com/mehulgupta2016154/fork-of-my-first-cnn?scriptVersionId=20845084
Хотите узнать больше !! сходить с ума внизу.
- Tensorflow для начинающих (концепции + примеры)
- Уменьшение размера вашей модели TensorFlow в 10 раз !!!
- Основы обучения с подкреплением (5 частей)
- Начнем с временных рядов (7 частей)
- Как получить своего первого стажера в области науки о данных
- Обнаружение объектов с помощью YOLO (3 части)
- Tensorflow для начинающих (концепции + примеры) (4 части)
- Предварительная обработка временных рядов (с кодами)
- Аналитика данных для начинающих
- Статистика для новичков (4 части)