Рубрики
Без рубрики

Как построить простую систему распознавания изображений с Tensorflow (часть 2)

Автор оригинала: FreeCodeCapm Team.

Вольфганг Бейер

Это вторая часть моего введения для создания системы распознавания изображений с Tensorflow. В первая часть Мы создали классификатор Softmax для маркировки изображений из набора данных CIFAR-10. Мы достигли точности около 25-30%. Поскольку существует 10 различных и одинаково вероятных категорий, маркировка изображений случайным образом, мы ожидали точности 10%. Поэтому мы уже намного лучше, чем случайные, но все еще есть много места для улучшения.

В этом посте я опишу, как построить нейронную сеть, которая выполняет ту же задачу. Давайте посмотрим, насколько мы можем увеличить точность прогнозирования!

Нейронные сети

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

Давайте посмотрим на отдельный нейрон:

То, что происходит в одном нейроне, очень похоже на то, что происходит в классификаторе SoftMax. Снова у нас есть вектор входных значений и веса весов. Вес – внутренние параметры нейрона. Оба входных вектора и веса веса содержат одинаковое количество значений, поэтому мы можем использовать их для расчета взвешенной суммы.

До сих пор мы выполняем один и тот же расчет, что и в классификаторе SoftMax, но теперь приходит немного поворота: до тех пор, пока результат взвешенной суммы – это положительное значение, выход нейрона является это значением. Но если взвешенная сумма является отрицательным значением, мы игнорируем это отрицательное значение, а нейрон генерирует вывод 0 вместо этого. Эта операция называется исправленным линейным блоком (RELU).

Причина использования RELU состоит в том, что это создает нелинейность. Выработка нейрона теперь не строго линейная сумма комбинированного сочетания) его входов. Посмотрим, почему это полезно, когда мы перестаем смотреть на отдельные нейроны и вместо этого посмотреть на всю сеть.

Нейроны в искусственных нейронных сетях обычно не связаны случайно друг к другу. Большую часть времени они расположены в слоях:

Значения пикселей входного изображения являются входами для первого слоя нейронов сети. Вывод нейронов в слое 1 представляет собой вход для нейронов слоя 2 и пр. Это причина, почему нелинейность настолько важна. Без RELU на каждом слое мы бы только последовательность взвешенных сумм. И сложенные взвешенные суммы могут быть объединены в единую взвешенную сумму, поэтому множественные слои дам нам никакого улучшения по одному слою сети. Внедрение нелинейности RELU решает эту проблему, так как каждый дополнительный слой действительно добавляет что-то в сеть.

Вывод конечного уровня сети – это значения, которые нас интересуют, баллы для категорий изображений. В этой сетевой архитектуре каждый нейрон подключен ко всем нейронам предыдущего слоя, поэтому этот вид сети называется полностью подключенной сетью. Как мы увидим в части 3 этого учебника, это не обязательно всегда так.

И это уже конец моей очень короткой части теории нейронных сетей. Давайте начнем строить один!

Код

Полный код для этого примера является Доступно на Github Отказ Это требует Tensorflow и Cifar-10 набора данных (см. Часть 1 ) О том, как установить предварительные условия).

Если вы пробили свой проход через мой предыдущий пост блога, вы увидите, что код для классификатора нейронного сетевого сетевого типа довольно похож на код для классификатора SoftMax. Но в дополнение к выключению части кода, определяющего модель, я добавил пару небольших функций, чтобы показать некоторые из вещей, которые могут сделать Tensorflow:

  • Регуляризация: это очень распространенная техника для предотвращения перенапряжения модели. Он работает, применяя контра-силу во время процесса оптимизации, который стремится сохранить модель простой.
  • Визуализация модели с Tensorboard: Tensorboard входит в комплект TensorFoard и позволяет генерировать диаграммы и графики из ваших моделей и из данных, созданных вашим моделями. Это помогает с анализом ваших моделей и особенно полезно для отладки.
  • CheckPoints: Эта функция позволяет сохранить текущее состояние вашей модели для последующего использования. Обучение модели может занять некоторое время, поэтому важно не нужно начинать с нуля каждый раз, когда вы хотите его использовать.

Код разделен на два файла на этот раз: есть dvy_layer_fc.py , который определяет модель, и run_fc_model.py . , который запускает модель (если вам интересно: «ФК» означает полностью подключенные).

2-слойный полностью подключенный нейронная сеть

Сначала посмотрим на саму модель и разобраться с бегом и тренируемся позже. dvy_layer_fc.py Содержит следующие функции:

  • Вывод () Получает нас от входных данных в баллы класса.
  • потеря () рассчитывает значение потерь от баллов класса.
  • Обучение () Выполняет один шаг обучения.
  • Оценка () рассчитывает точность сети.

Генерация баллов класса: вывод ()

Вывод () описывает пропуск вперед через сеть. Как рассчитываются оценки класса, начиная с входных изображений?

Изображения Параметр – это заполнитель Tensorflow, содержащий фактические данные изображения. Следующие три параметра описывают форму/размер сети. image_pixels это количество пикселей на входное изображение, Классы это количество различных выходных меток и hidden_units Это количество нейронов в первом/скрытом слое нашей сети.

Каждый нейрон принимает все значения из предыдущего слоя в качестве ввода и генерирует одно выходное значение. Таким образом, каждый нейрон в скрытом слое имеет image_pixels Входные данные и слой в целом генерирует hidden_units выходы. Затем они питаются в Классы Нейроны выходного слоя, которые генерируют Классы Выходные значения, одна оценка на класс.

reg_constant постоянная регуляризация. Tensorflow позволяет нам очень легко добавлять регулярию в нашу сеть, обработав большую часть расчетов автоматически. Я пойду немного более подробно, когда доберешься до Функция потери Отказ

Поскольку наша нейронная сеть имеет 2 аналогичных слои, мы определим отдельный объем для каждого. Это позволяет нам повторно использовать имена переменных в каждом объеме. Удобства Переменная определена в том, как мы уже знаем, используя TF.Variable () Отказ

Определение Вес Переменная немного более вовлечена. Мы используем tf.get_variabiable () , что позволяет нам добавлять регуляризацию. Вес это матрица с размерами image_pixels По hidden_units (Размер вектора входных векторов X Размер вектора). Инициализатор Параметр описывает Вес Начальные значения переменной.

До настоящего времени мы инициализировали наши переменные до 0, но это не будет работать здесь. Подумайте о нейронах в одном слое. Все они получают точно такие же входные значения. Если у них все они имели одинаковые внутренние параметры, они все будут делать одинаковые расчеты и все вывод одинаковое значение. Чтобы избежать этого, нам нужно рандомизировать свои начальные веса. Мы используем схему инициализации, которая обычно хорошо работает, веса инициализируются с нормально распределенными значениями. Мы падаем значения, которые составляют более 2 стандартных отклонений от среднего значения, а стандартное отклонение устанавливается на обратную часть квадратного корня количества входных пикселей. К счастью, Tensorflow обрабатывает все эти детали для нас, нам просто нужно указать, что мы хотим использовать trunced_normal_initializer Что именно то, что мы хотим.

Последний параметр для Вес Переменная – это регулятор Отказ Все, что нам нужно сделать в этот момент, это сказать Tensorflow, мы хотим использовать L2-регулярирование для Вес Переменная. Я буду покрывать регуляризацию здесь Отказ

Чтобы создать выход первого слоя, мы умножим Изображения Матрица и Вес Матрица ведьма друг друга и добавьте предвзятость Переменная. Это точно так же, как в классификаторе Softmax от Предыдущий блог Post Отказ Тогда мы применяем tf.nn.relu () Функция RELU пришла к выходу скрытого слоя.

Слой 2 очень похож на слой 1. Количество входов – hidden_units Количество выходов является Классы Отказ Поэтому размеры Вес Матрица – это [hidden_units, классы] Отказ Поскольку это последний слой нашей сети, больше нет необходимости в RELU. Мы приходим на баллы класса ( логиты ) путем умножения ввода ( скрыто ) и Вес друг с другом и добавление предвзятость Отказ

Сводная операция tf.histogram_summary () Позволяет записать значение Логиты Переменная для более позднего анализа с Tensorboard. Я охвачу это позже Отказ

Суммировать это, Вывод () Функция в целом принимает входные изображения и возвращает баллы класса. Это все обученный классификатор должен делать, но для того, чтобы прийти к обученному классификатору, нам сначала нужно измерить, насколько хороши эти оценки класса. Это работа функции потери.

Расчет потери: потеря ()

Сначала мы рассчитаем перекрестную энтропию между Логиты (вывод модели) и этикетки (правильные этикетки от тренировочного набора данных). Это была наша наша функция потери для классификатора SoftMax, но на этот раз мы хотим использовать регуляризацию, поэтому мы должны добавить еще один срок в нашу потерю.

Давайте сначала сделаем шаг назад и посмотрите на то, что мы хотим достичь, используя регуляризацию.

Переоборудование и регуляризация

Когда статистическая модель отражает случайный шум в данных, он был обучен вместо истинных основных отношений, это называется переоценка.

В приведенном выше изображении два разных класса, представленные синим и красным кругами. Зеленая линия – это переопределенный классификатор. Он идеально следит за тренировками, но он также сильно зависит от него, и, вероятно, справится с невидимыми данными, чем черная линия, которая представляет собой регуляризованную модель.

Таким образом, наша цель для регуляризации состоит в том, чтобы прибыть на простую модель без каких-либо ненужных осложнений. Существуют разные способы достижения этого, и опция, которую мы выбираем, называется L2-регулярией. L2-регуляризация добавляет сумму квадратов всех весов в сети в функцию потери. Это соответствует тяжелую штрафу, если модель использует большие веса и небольшой штраф, если модель использует небольшие веса.

Вот почему мы использовали регулятор Параметр при определении весов и назначен l2_regularizer к этому. Это говорит о Tensorflow отслеживать термины регуляризации L2 (и взвесить их по параметру Reg_Constant ) для этой переменной. Все условия регуляризации добавляются в коллекцию под названием tf.graphkeys.regularization_losses , который доступа к функции потери. Затем мы добавляем сумму всех потерь регуляризации ранее рассчитанной кросс-энтропии, чтобы прийти к общей потере нашей модели.

Оптимизация переменных: обучение ()

global_step это скалярная переменная, которая отслеживает, сколько обучающих итераций уже выполнено. Когда многократно используют модель в нашей петле тренировок, мы уже знаем это значение. Это итерационная переменная петли. Причина, по которой мы добавляем это значение непосредственно на график Tensorflow, заключается в том, что мы хотим иметь возможность делать снимки модели. И эти снимки должны включать информацию о том, сколько учебных шагов уже выполнено.

Определение оптимизатора градиента спускается прост. Мы предоставляем курс обучения и сообщите оптимизатором, какую переменную предполагается минимизировать. Кроме того, оптимизатор автоматически увеличивает global_step параметр с каждой итерацией.

Измерение производительности: оценка ()

Расчет точности модели такой же, как в случае Softmax: мы сравниваем прогнозы модели с истинными метками и рассчитайте частоту того, как часто прогноз является правильным. Мы также заинтересованы в том, как точность развивается со временем, поэтому мы добавляем сводную операцию, которая отслеживает значение Точность Отказ Мы охватим это в Раздел о Tensorboard Отказ

Чтобы обобщить то, что мы сделали до сих пор, мы определили поведение 2-слойной искусственной нейронной сети, используя 4 функции: Вывод () представляет собой передний проход через сеть и возвращает баллы класса. потеря () сравнивает прогнозируемые и истинные оценки класса и генерирует значение потерь. Обучение () Выполняет шаг обучения и оптимизирует внутренние параметры модели и Оценка () измеряет производительность нашей модели.

Запуск нейронной сети

Теперь, когда нейронная сеть определена, давайте посмотрим на то, как run_fc_model.py . Беги, поезда и оценивает модель.

После обязательного импорта мы определяем параметры модели как внешние флаги. Tensorflow имеет свой собственный модуль для параметров командной строки, которая является тонкой оберткой вокруг Python’s argparse Отказ Мы используем здесь здесь для удобства, но вы можете просто использовать argparse напрямую вместо этого.

В первой пару строк определены различные параметры командной строки. Параметры для каждого флага являются именем флага, его значение по умолчанию и краткое описание. Выполнение файла с -h Флаг отображает эти описания.

Второй блок строк вызывает функцию, которая фактически анализирует параметры командной строки. Затем значения всех параметров напечатаны на экран.

Здесь мы определяем константы для количества пикселей на изображение (32 x 32 x 3) и количество различных категорий изображений. Затем мы начинаем измерять время выполнения, создавая таймер.

Мы хотим регистрировать некоторую информацию о процессе обучения и использовать Tensorboard, чтобы отобразить эту информацию. Tensorboard требует от журналов для каждого запуска, чтобы быть в отдельном каталоге, поэтому мы добавляем информацию о дате и времени на имя каталога журнала.

load_data () Загружает данные CIFAR-10 и возвращает словарь, содержащий отдельную подготовку и тестовые наборы данных.

Генерировать график Tensorflow

Мы определяем тензоночные заполнители. При выполнении фактических расчетов они будут заполнены данные обучения/тестирования.

images_pacholder имеет размеры периода партии X пикселей на изображение. Размер партии «Нет» позволяет нам запустить график с различными размерами пакетных размеров (размер партии для обучения сетью можно установить через параметр командной строки, но для тестирования мы передаем весь тестовый набор в виде одной партии) Отказ

label_sjacholder Это вектор целочисленных значений, содержащих правильный класс метки, по одному на изображение в партии.

Здесь мы ссылаемся на функции, которые мы охватываем ранее в dvy_layer_fc.py Отказ

  • Вывод () Получает нас от входных данных в баллы класса.
  • потеря () рассчитывает значение потерь от баллов класса.
  • Обучение () Выполняет один шаг обучения.
  • Оценка () рассчитывает точность сети.

Определяет сводную операцию для Tensorboard (покрытая здесь ).

Генерирует Спасатель Объект для сохранения состояния модели на контрольно-пропускных пунктах (охвачены здесь ).

Мы запускаем сеанс Tensorflow и немедленно инициализируйте все переменные. Затем мы создаем сводный писатель, который мы будем использовать для периодической сохранения информации журнала на диск.

Эти строки несут ответственность за генерирование партий входных данных. Давайте притворяемся, у нас есть 100 тренировочных изображений и размер партии 10. В примере Softmax мы просто выбрали 10 случайных изображений для каждой итерации. Это означает, что после 10 итераций каждый образ будет выбран один раз в среднем (!). Но на самом деле некоторые изображения будут выбраны несколько раз, пока некоторые изображения не были частью какой-либо пакета. Пока вы повторяете это достаточно часто, это не так ужасно, что случайность приводит к тому, что некоторые изображения являются частью тренировочных партий несколько чаще, чем другие.

Но на этот раз мы хотим улучшить процесс выборки. Что мы делаем, это мы впервые перемешаем 100 изображений тренировочного набора данных. Первые 10 изображений смягчающих данных являются наши первые партии, следующие 10 изображений являются нашими второй партией и так далее. После 10 партий мы находимся в конце нашего набора данных, и процесс запускается снова. Мы перемешаем данные еще раз и проходите через него спереди назад. Это гарантирует, что ни одно изображение не выбирается чаще всего, чем любой другой, пока все еще гарантирует, что порядок, в котором возвращаются изображения, являются случайными.

Для того, чтобы достичь этого, gen_batch () Функция в data_heelpers () Возвращает Python Генератор , который возвращает следующую партию каждый раз, когда он оценивается. Детали о том, как работают генераторы за пределами объема этого поста (хорошее объяснение можно найти здесь ). Мы используем встроенный Python zip () Функция генерировать список кортежей от [(Image1, Label1), (Image2, Label2), ...] , который затем передается нашу функцию генератора.

Далее (партии) Возвращает следующую партию данных. Так как это все еще в форме [(Imagea, Labela), (ImageB, Labelb), ...] нам нужно unzip Это сначала отделить изображения из ярлыков, прежде чем заполнять feed_dict , словарь, содержащий плетени Tensorflow, с одной партией тренировочных данных.

Каждая 100 итерациями текущей точности модели оценивается и напечатана на экран. Кроме того, Резюме Операция запускается, и его результаты добавляются к Summary_Writer который отвечает за написание резюме на диск. Оттуда они могут быть прочитаны и отображаться Tensorboard (см. В этом разделе ).

Эта строка запускает rain_step Операция (определена ранее, чтобы позвонить foo_layer_fc.traing () , который содержит фактические инструкции для оптимизации переменных).

При обучении модели требуется более длительный период времени, простой способ сохранить снимок вашего прогресса. Это позволяет вам вернуться позже и восстановить модель в точном же состоянии. Все, что вам нужно сделать, это создать tf.train.saver объект (мы сделали это раньше), а затем назовите его Сохранить () Способ каждый раз, когда вы хотите сделать снимок.

Восстановление модели так же просто, просто позвоните в Saver’s Восстановить () метод. Существует пример рабочего кода, показывающий, как это сделать в файле restore_model.py в репозитории Github.

После завершения обучения окончательная модель оценивается на тестовом наборе (помните, что тестовый набор содержит данные о том, что модель пока не видела, что позволяет нам судить, насколько хорошо модель может обобщать для новых данных).

Полученные результаты

Давайте запустим модель с параметрами по умолчанию через « Python Run_fc_model.py ». Мой вывод выглядит так:

Parameters: batch_size = 400 hidden1 = 120 learning_rate = 0.001 max_steps = 2000 reg_constant = 0.1 train_dir = tf_logs 
Step 0, training accuracy 0.09 Step 100, training accuracy 0.2675 Step 200, training accuracy 0.3925 Step 300, training accuracy 0.41 Step 400, training accuracy 0.4075 Step 500, training accuracy 0.44 Step 600, training accuracy 0.455 Step 700, training accuracy 0.44 Step 800, training accuracy 0.48 Step 900, training accuracy 0.51 Saved checkpoint Step 1000, training accuracy 0.4425 Step 1100, training accuracy 0.5075 Step 1200, training accuracy 0.4925 Step 1300, training accuracy 0.5025 Step 1400, training accuracy 0.5775 Step 1500, training accuracy 0.515 Step 1600, training accuracy 0.4925 Step 1700, training accuracy 0.56 Step 1800, training accuracy 0.5375 Step 1900, training accuracy 0.51 Saved checkpoint Test accuracy 0.4633 Total time: 97.54s

Мы видим, что точность обучения начинается на уровне, мы ожидаем от угадания случайно (10 классов -> 10% шанс выбора правильного). За первые около 1000 итераций точность увеличивается до 50% и колеблется вокруг этого значения для следующих 1000 итераций. Точность тестирования 46% не намного ниже, чем точность обучения. Это указывает на то, что наша модель существенно не переоценивается. Производительность классификатора SoftMax составила около 30%, поэтому 46% является улучшением около 50%. Неплохо!

Визуализация с Tensorboard

Tensorboard позволяет визуализировать различные аспекты ваших графов Tensorflow и очень полезно для отладки и улучшения ваших сетей. Давайте посмотрим на Tensorboard, связанные с разбросами кода на протяжении всего кодовой базы.

В dvy_layer_fc.py Мы находим следующее:

Каждая из этих трех линий создает сводную операцию. Определив сводную операцию, вы говорите Tensorflow, которую вы заинтересованы в сборе сводной информации от определенных тензоров ( Логиты , Потеря и Точность в нашем случае). Другой параметр для сводной операции – это просто метка, которую вы хотите прикрепить к резюме.

Существуют различные виды сводных операций. Мы используем Scalar_Summary Для записи информации о скалярных (не векторных) значениях и histogr_summary Чтобы собрать информацию о распределении нескольких значений (подробнее о различных сводных операциях можно найти в документах Tensorflow ).

В run_fc_model.py . Следующие строки имеют отношение к визуализации Tensorboard:

Операция в Tensorflow не работает сама по себе, вам нужно либо вызывать его напрямую или вызывать другую операцию, которая зависит от него. Поскольку мы не хотим вызывать каждую сводную операцию индивидуально каждый раз, когда мы хотим собрать сводную информацию, мы используем tf.merge_all_summarys Создать одну операцию, которая запускает все наши резюме.

Во время инициализации сеанса Tensorflow мы создаем сводный автором. Сводный автор отвечает за фактически написание сводных данных на диск. В своем конструкторе мы поставляем logdir , каталог, где мы хотим, чтобы журналы были написаны. Дополнительный аргумент графика говорит Tensorboard для отображения всего графика Tensorflow.

Каждая 100 итераций мы выполняем объединенную операцию с объединенной ассортиментами и передавайте результаты к сводку автор, который записывает их на диск.

Для просмотра результатов мы запускаем Tensorboard через « Tensorboard » и открыть localhost: 6006 в веб-браузере. В «Событиях» -Табе можно увидеть, как уменьшается потеря сети и как ее точность увеличивается с течением времени.

«Графики» -Tab показывает визуализацию графа Tensorflow, который мы определили. Вы можете интерактивно переставить его, пока не удовлетворены тем, как это выглядит. Я думаю, что следующее изображение показывает структуру нашей сети довольно хорошо.

В «распределении» – и «гистограммах» вы можете исследовать результаты tf.histogram_summary Операция, которую мы прикрепили к Логиты , но я не пойду в более подробную информацию здесь. Больше информации можно найти в Соответствующий раздел официальной документации Tensorflow Отказ

Дальнейшие улучшения

Может быть, вы думаете, что обучение классификатор Softmax принял многочисленное время вычисления, чем обучение нейронной сети. Хотя это правда, даже если мы продолжали тренироваться классификатор Softmax, если это заняло нервную сеть, чтобы тренироваться, она не достигла такой же производительности. Чем дольше вы тренируете модель, тем меньше получают дополнительные выгоды, и после определенного момента повышение производительности – это умение улучшение производительности. Мы достигли этой точки с нейронной сетью тоже. Дополнительное время обучения больше не улучшит точности. Есть что-то еще, что мы могли бы сделать, хотя:

Значения параметра по умолчанию выбирают, чтобы быть довольно хорошо, но есть какая-то комната для улучшения. Путем различных параметров, таких как количество нейронов в скрытом слое или скорости обучения, мы должны быть в состоянии улучшить точность модели еще. Точность тестирования, превышающая 50%, определенно должна быть возможна с этой моделью с некоторой дополнительной оптимизацией. Хотя я был бы очень удивлен, если бы эта модель была настроенными, чтобы достичь 65% или более. Но есть другой тип сетевой архитектуры, для которой такая точность легко выполняется: сверточные нейронные сети. Это класс нейронных сетей, которые не полностью связаны. Вместо этого они пытаются понять ощущение локальных функций на их входе, что очень полезно для анализа изображений. Это интуитивно имеет большой смысл принимать пространственную информацию во внимание при рассмотрении изображений. В части 3 этой серии мы увидим принципы того, насколько свертовые нейронные сети работают и строят одного себя.

Оставайтесь настроиться на часть 3 на сверточных нейронных сетях и большое спасибо за чтение! Я счастлив о любых отзывах, которые вы могли бы иметь!

Вы также можете проверить другие статьи, которые я написал на мой блог Отказ