Определения
Если вы не понимаете основных концепций распознавания изображений, вам будет сложно полностью понять основную часть этой статьи. Поэтому, прежде чем мы продолжим, давайте определимся с терминологией.
TensorFlow / Keras
TensorFlow — это библиотека с открытым исходным кодом, созданная для Python командой Google Brain. TensorFlow компилирует множество различных алгоритмов и моделей, позволяя пользователю реализовать глубокие нейронные сети для использования в таких задачах, как распознавание и классификация изображений, а также обработка естественного языка. TensorFlow — это мощный фреймворк, который функционирует путем реализации ряда узлов обработки, каждый из которых представляет математическую операцию, а весь ряд узлов называется «графом».
Говоря о Keras, это высокоуровневый API (интерфейс прикладного программирования), который может использовать функции TensorFlow (а также другие библиотеки ML, такие, как Theano). Keras был разработан с удобством и модульностью в качестве руководящих принципов. С практической точки зрения Keras позволяет реализовать множество мощных, но зачастую сложных функций TensorFlow максимально просто, к тому же он настроен для работы с Python без каких-либо серьезных изменений или настроек.
Распознавание изображений (классификация)
Распознавание изображения относится к задаче ввода изображения в нейронную сеть и присвоения какой-либо метки для этого изображения. Метка, которую выводит сеть, будет соответствовать заранее определенному классу. Может быть присвоено как сразу несколько классов, так и только один. Если существует всего только один класс, обычно применяется термин «распознавание», тогда как задача распознавания нескольких классов часто называется «классификацией».
Подмножество классификаций изображений — является уже определением объектов, когда определенные экземпляры объектов идентифицируются как принадлежащие к определенному классу, например, животные, автомобили или люди.
Ярким примером такой классификации является решение самой распространённой капчи — ReCaptcha v2 от Google, где из набора картинок необходимо выбрать только те, которые принадлежат к указанному в описании классу.
Как нейронные сети учатся распознавать изображения
Понимание о том, как нейронная сеть распознает изображения, поможет вам при реализации модели нейронной сети, поэтому давайте кратко рассмотрим процесс распознавания изображений в следующих разделах.
Извлечение признаков при помощи фильтров
Первый слой нейронной сети принимает все пиксели в изображении. После того, как все данные введены в сеть, к изображению применяются различные фильтры, которые формируют понимание различных частей изображения. Это извлечение признаков, которое создает «карты признаков».
Этот процесс извлечения признаков из изображения выполняется с помощью «сверточного слоя», и свертка просто формирует представление части изображения. Именно из этой концепции свертки мы получаем термин “Сверточная нейронная сеть” (Convolutional Neural Network, CNN) — тип нейронной сети, наиболее часто используемый в классификации и распознавании изображений.
Если вы хотите визуализировать, как именно работает создание карт признаков, представьте себе процесс поднесения фонарика к изображению в темной комнате. Когда вы скользите лучом по картинке, вы узнаёте об особенностях изображения. Фильтр — это то, что сеть использует для формирования представления об изображении, и в этой метафоре свет от фонарика является фильтром.
Ширина луча вашего фонарика определяет размер фрагмента изображения, который вы просматриваете за один раз, и нейронные сети имеют аналогичный параметр — размер фильтра. Размер фильтра влияет на то, сколько пикселей проверяется за один раз. Общий размер фильтра, используемого в CNN, равен 3, и он охватывает как высоту, так и ширину, поэтому фильтр проверяет область пикселей 3 x 3.
В то время как размер фильтра покрывает высоту и ширину фильтра, глубина фильтра также должна быть указана.
Дело в том, что цифровые изображения отображаются в виде высоты, ширины и некоторого значения RGB, которое определяет цвет пикселя, поэтому отслеживаемая «глубина» — это количество цветовых каналов, которые имеет изображение. Изображения в градациях серого (не цветные) имеют только 1 цветной канал, в то время как цветные изображения имеют глубину в 3 канала.
Все это означает, что для фильтра размером в 3, примененного к полноцветному изображению, итоговые размеры этого фильтра будут 3 x 3 x 3. Для каждого пикселя, охватываемого этим фильтром, сеть умножает значения фильтра на значения самих пикселей, чтобы получить числовое представление этого пикселя. Затем этот процесс выполняется для всего изображения, чтобы получить полное представление. Фильтр перемещается по остальной части изображения в соответствии с параметром, называемым «шаг», который определяет, на сколько пикселей должен быть перемещен фильтр после того, как он вычислит значение в своей текущей позиции. Обычный размер шага для CNN — 2.
Конечным результатом всех этих расчетов является карта признаков. Этот процесс обычно выполняется с несколькими фильтрами, которые помогают сохранить сложность изображения.
Функции активации
После того, как карта признаков изображения была создана, значения, представляющие изображение, передаются через функцию активации или слой активации. Функция активации принимает эти значения, которые благодаря сверточному слою находятся в линейной форме (то есть просто список чисел) и увеличивает их нелинейность, поскольку сами изображения являются нелинейными.
Типичной функцией активации, используемой для достижения этой цели, является выпрямленная линейная единица (ReLU), хотя есть и некоторые другие функции активации, которые также иногда используются (вы можете прочитать о них здесь.
Объединение слоёв
После активации данные отправляются через объединяющий слой. Объединение «упрощает» изображение: берёт информацию, которая представляет изображение, и сжимает её. Процесс объединения в пул делает сеть более гибкой и способной лучше распознавать объекты и изображения на основе соответствующих функций.
Когда мы смотрим на изображение, нас, как правило, волнует не вся информация (например, что на заднем плане изображения), а только признаки, которые нас интересуют — люди, животные и т. д.
Аналогично, объединяющий слой в CNN избавится от ненужных частей изображения, оставив только те части, которые он считает релевантными, в зависимости от заданного размера объединяющего слоя.
Поскольку сеть должна принимать решения относительно наиболее важных частей изображения, расчёт идёт на то, что она изучит только те части изображения, которые действительно представляют суть рассматриваемого объекта. Это помогает предотвратить “переобучение” — когда сеть слишком хорошо изучает все аспекты учебного примера и уже не может обобщать новые данные, поскольку учитывает нерелевантные отличия.
Существуют различные способы объединения значений, но чаще всего используется максимальное объединение. Максимальное объединение подразумевает взятие максимального значения среди пикселей в пределах одного фильтра (в пределах одного фрагмента изображения). Это отсеивает 3/4 информации, при условии использования фильтра размером 2 x 2.
Максимальные значения пикселей используются для того, чтобы учесть возможные искажения изображения, а количество параметров (размер изображения) уменьшены, чтобы контролировать переобучение. Существуют и другие принципы объединения, такие как среднее или суммарное объединение, но они используются не так часто, поскольку максимальное объединение даёт большую точность.
Сжатие
Последние слои нашей CNN — плотно связанные слои — требуют, чтобы данные были представлены в форме вектора для дальнейшей обработки. По этой причине данные необходимо «свести воедино». Для этого значения сжимаются в длинный вектор или столбец последовательно упорядоченных чисел.
Полностью связанный слой
Конечные слои CNN представляют собой плотно связанные слои или искусственную нейронную сеть (Artificial neural networks (ANN)). Основной функцией ANN является анализ входных признаков и объединение их в различные атрибуты, которые помогут в классификации. Эти слои образуют наборы нейронов, которые представляют различные части рассматриваемого объекта, а набор нейронов может представлять собой, например, висячие уши собаки или красноту яблока. Когда достаточное количество этих нейронов активируется в ответ на входное изображение, то оно будет классифицировано как объект.
Ошибка или разница между рассчитанными значениями и ожидаемым значением в обучающем наборе рассчитывается с помощью ANN. Затем сеть подвергается методу обратного распространения ошибки, где рассчитывается влияние данного нейрона на нейрон в следующем слое и затем его влияние (вес) корректируется. Это сделано для оптимизации производительности модели. Этот процесс повторяется снова и снова: так сеть обучается на данных и изучает связи между входными признаками и выходными классами.
Нейроны в средних полностью связанных слоях будут выводить двоичные значения, относящиеся к возможным классам. Если у вас есть четыре разных класса (скажем, собака, машина, дом и человек), нейрон будет иметь значение «1» для класса, который, как он считает, представляет изображение, и значение «0» для других классов.
Конечный полностью связанный слой, получив выходные данные предыдущего слоя, присваивает вероятность каждому из классов в пределах единицы (в совокупности). Если категории «собака» присвоено значение 0,75 — это означает 75% вероятность того, что изображение является собакой.
Подготовка данных
Во-первых, вам нужно будет собрать свои данные и оформить их так, чтобы нейросеть смола обучаться на них. Это включает в себя сбор изображений и их маркировку. Даже если вы скачали набор данных, подготовленный кем-то другим, то скорее всего вам всё-равно потребуется предварительная обработка или подготовка, прежде чем вы сможете использовать его для обучения. Подготовка данных — это искусство само по себе, связанное с решением таких проблем, как пропущенные значения, поврежденные данные, данные в неправильном формате, неправильные метки и т. д.
В этой статье мы будем использовать предварительно обработанный набор данных.
Создание модели
Создание модели нейронной сети включает выбор различных параметров и гиперпараметров. Вы должны принять решение о количестве слоев, используемых в вашей модели, о том, каким будет размер входных и выходных слоев, какие функции активации вы будете использовать, будете ли вы использовать исключение (Dropout) и т. д.
Понимание того, какие параметры и гиперпараметры стоит использовать, придет со временем (изучать придётся много), но существуют некоторые базовые методы, которые вы можете использовать на старте, и мы рассмотрим некоторые из них в нашем примере.
Обучение модели
После того, как ваша модель создана, вам просто остаётся создать экземпляр модели и подогнать его к своим данным для обучения. Наибольшее внимание при обучении модели уделяется количеству требуемого для обучения времени. Вы можете указать продолжительность обучения сети, задав количество эпох обучения. Чем дольше вы тренируете модель, тем выше ее эффективность, но если использовать слишком много эпох обучения — вы рискуете переобучить модель.
Выбор количества эпох для обучения — это то, что вы научитесь определять со временем, и, как правило, следует всегда сохранять веса нейросети между тренировочными сессиями, чтобы вам не нужно было начинать сначала после достижения определенного прогресса в обучении.
Распознавание изображений с CNN
Мы уже многое рассмотрели и если вся эта информация была, возможно, немного неясной, то объединение вышеописанных концепций в выборочном классификаторе, обученном на наборе данных, должно окончательно все прояснить Итак, давайте рассмотрим полный пример распознавания изображений с использованием Keras — от загрузки данных до оценки эффективности модели.
Изображения являются полноцветными RGB, но они достаточно малы, всего 32 x 32. Отличительной особенностью набора данных CIFAR-10 является то, что он поставляется в комплекте с Keras, поэтому загрузить набор данных очень просто, а сами изображения нуждаются лишь в минимальной предварительной обработке.
Первое, что мы должны сделать, это импортировать необходимые библиотеки. Вы ещё увидите, как именно этот импорт происходит по ходу дела, а пока же просто имейте в виду, что мы будем использовать Numpy и различные модули, связанные с Keras:
Мы собираемся использовать случайный SEED (симметричный блочный криптоалгоритм на основе Сети Фейстеля), чтобы результаты, полученные в этой статье, могли быть воспроизведены вами, поэтому нам нужен numpy:
Теперь давайте загрузим набор данных. Мы можем сделать это просто указав, в какие переменные мы хотим загрузить данные, а затем использовать функцию load_data():
В большинстве случаев вам потребуется выполнить некоторую предварительную обработку ваших данных, чтобы подготовить их к использованию, но поскольку мы используем уже готовый и упакованный набор данных, то такая обработка сведена к минимуму. Одним из действий, которые мы хотим сделать, будет нормализация входных данных.
Если значения входных данных находятся в слишком широком диапазоне, это может отрицательно повлиять на работу сети. В нашем случае входными значениями являются пиксели в изображении, которые имеют значение от 0 до 255.
Таким образом, чтобы нормализовать данные, мы можем просто разделить значения изображения на 255. Для этого нам сначала нужно перевести данные в формат с плавающей запятой, поскольку в настоящее время они являются целыми числами. Мы можем сделать это, используя Numpy команду astype(), а затем объявить желаемый тип данных:
Нам также нужно задать количество классов в наборе данных, чтобы мы поняли, до скольких нейронов сжимать конечный слой:
Проектирование модели
Мы достигли стадии проектирования модели CNN. Первое, что нужно сделать, это определить формат, который мы хотели бы использовать для модели. У Keras есть несколько различных форматов (планов) для построения моделей, но наиболее часто используется Sequential — поэтому мы импортировали его из Keras.
Первый слой нашей модели — это сверточный слой. Он будет принимать входные данные и пропускать их через сверточные фильтры.
При реализации этого в Keras, мы должны указать количество каналов (фильтров), которое нам нужно (а это 32), размер фильтра (3 x 3 в нашем случае), форму входа (при создании первого слоя), функцию активации и отступы.
Как уже упоминалось, relu является наиболее распространенной функцией активации, а отступы мы определим через padding = ‘same’, то есть, мы не меняем размер изображения:
Теперь мы создадим исключающий слой для предотвращения переобучения, который случайным образом устраняет соединения между слоями (0,2 означает, что он отбрасывает 20% существующих соединений):
Также мы можем выполнить пакетную нормализацию. Пакетная нормализация нормализует входные данные, поступающие в следующий слой, гарантируя, что сеть всегда создает функции активации с тем же распределением, которое нам нужно:
Теперь следует еще один сверточный слой, но размер фильтра увеличивается, так что сеть уже может изучать более сложные представления:
А вот и объединяющий слой, который, как обсуждалось ранее, помогает сделать классификатор изображений более корректным, чтобы он мог изучать релевантные шаблоны. Также опишем исключение (Dropout) и пакетную нормализацию:
Это основа рабочего процесса в первой части реализации CNN: свертка, активация, исключение, объединение. Теперь вы понимаете, зачем мы импортировали Dropout, BatchNormalization, Activation, Conv2d и MaxPooling2d.
Вы можете варьировать количество сверточных слоев по своему вкусу, но каждый из них увеличивает вычислительные затраты. Обратите внимание, что при добавлении сверточных слоев вы обычно увеличиваете и количество фильтров, чтобы модель могла выучить более сложные представления. Если числа, выбранные для этих слоев, кажутся несколько произвольными, то просто знайте, что рекомендуется увеличивать фильтры постепенно, устанавливая значение 2 в степени (2^n), что может дать небольшое преимущество при обучении модели на GPU.
Важно не иметь слишком много объединяющих уровней, так как каждый из них отбрасывает часть данных. Слишком частое объединение приведет к тому, что плотно связанные слои почти ничего не узнают, когда данные достигнут их.
Необходимое количество объединяющих слоев зависит от выполняемой задачи — это то, что вы определите со временем. Поскольку изображения в нашем наборе уже достаточно малы, мы не будем объединять их более двух раз.
Теперь вы можете повторить эти слои, чтобы дать вашей сети больше представлений для работы:
После того, как мы закончили со сверточными слоями, нам нужно сжать данные, поэтому мы импортировали функцию Flatten выше. Мы также добавим слой исключения снова:
Теперь мы используем импортированную функцию Dense и создаем первый плотно связанный слой. Нам нужно указать количество нейронов в плотном слое. Обратите внимание, что число нейронов в последующих слоях уменьшается, в конечном итоге приближаясь к тому же числу нейронов, что и классы в наборе данных (в данном случае 10). Ограничение ядра может упорядочить данные в процессе обучения, что также помогает предотвратить переобучение. Вот почему мы импортировали maxnorm ранее.
В этом последнем слое мы уравниваем количество классов с числом нейронов. Каждый нейрон представляет класс, поэтому на выходе этого слоя будет вектор из 10 нейронов, каждый из которых хранит некоторую вероятность того, что рассматриваемое изображение принадлежит его классу.
Наконец, функция активации softmax выбирает нейрон с наибольшей вероятностью в качестве своего выходного значения, предполагая, что изображение принадлежит именно этому классу:
Теперь, когда мы разработали модель, которую хотим использовать, остаётся лишь скомпилировать ее. Давайте укажем количество эпох для обучения, а также оптимизатор, который мы хотим использовать.
Оптимизатор — это то, что настроит веса в вашей сети так, чтобы приблизиться к точке с наименьшими потерями. Алгоритм Адама является одним из наиболее часто используемых оптимизаторов, потому что он дает высокую производительность в большинстве задач:
Теперь скомпилируем модель с выбранными параметрами. Давайте также укажем метрику для оценки.
Теперь мы приступаем к обучению модели. Для этого нам нужно вызвать функцию fit () для модели и передать выбранные параметры.
Обратите внимание, что в большинстве случаев вам нужно иметь проверочный набор, отличный от набора для тестирования, поэтому вы должны указать процент данных обучения, которые будут использоваться в качестве набора для проверки. В этом случае мы просто передадим тестовые данные, чтобы убедиться, что тестовые данные отложены и не использовались для обучения. В этом примере мы будем иметь только тестовые данные, чтобы все было проще.
Теперь мы можем оценить модель и посмотреть, как она работает. Просто вызовите ():
Ну, вот и всё! Теперь у нас есть обученная распознаванию изображений CNN. Неплохо для первого запуска, но вы, вероятно, захотите поэкспериментировать со структурой модели и параметрами, чтобы попытаться добиться лучшей эффективности.
Практическое применение нейросетей для распознавания капч
Теоретические и экспериментальные работы по CNN закономерно подводят к вариантам использования нейросетей для решения практических повседневных задач. Наиболее актуальной в сфере распознавания и классификации изображений является задача по решению капчи, в частности — самой популярной на сегодняшний день Google ReCaptcha v2.
Несмотря на схожесть с нашим примером, на практике реализовать рабочую нейросеть для решения капчи представляется крайне затратным и неэффективным решением из-за постоянно меняющегося набора данных (картинок в капче). Столь частое и непредсказуемое обновление входящих данных влечёт за собой целую вереницу проблем:
- необходимость регулярно собирать и обрабатывать новые данные
- необходимость постоянного контроля процесса со стороны человека и внесение правок в модель по ходу работы (включая эксперименты с параметрами)
- необходимость мощного оборудования для обучения модели 24/7
- и т. д.
Для решения капч в беспрерывном режиме, с высокой скоростью и сравнительно низкой стоимостью — большим спросом пользуются онлайн сервисы по распознаванию капч, которые привлекают для этого реальных пользователей. На отечественном рынке лидером является сервис, который выгодно отличается от конкурентов: * высокой точностью (до 99%) и скоростью решений (12 секунд для обычных текстовых капч и 24 секунды для ReCaptcha) * приемлемыми фиксированными ценами (цена не возрастает при увеличении нагрузки на сервера сервиса): 35 рублей за 1000 решений обычных капч и 160 рублей за 1000 решений ReCaptcha * возвратом средств за редкие неуспешные распознавания * технической возможностью решать огромные объёмы капч (более 10,000 в минуту) * простым и функциональным API * готовыми библиотеками и образцами кода для различных языков программирования * привлекательной партнёрской программой, позволяющей разработчикам и рефоводам получать до 15% от расходов привлечённых клиентов и 10% от доходов привлеченных в сервис работников.
Любые возникающие вопросы по работе сервиса — оперативно решаются службой поддержки через систему тикетов.
Часто задаваемые вопросы о работе нейросетей для распознавания
Вопрос: В чем главное отличие нейросети для распознавания от обычного алгоритма?
Ответ: Нейросеть не требует ручного программирования правил, она самостоятельно учится выделять значимые признаки из данных в процессе обучения.
Вопрос: Почему для распознавания изображений чаще всего используют сверточные нейросети (CNN)?
Ответ: CNN эффективно работают с двумерными данными (пикселями), умеют выявлять локальные паттерны (края, текстуры) и инвариантны к небольшим смещениям объекта в кадре.
Вопрос: Что такое «обучение с учителем» в контексте распознавания?
Ответ: Это процесс, при котором нейросети на вход подаются данные (например, изображения) вместе с правильными ответами (метками), чтобы она могла скорректировать свои внутренние параметры (веса).
Вопрос: Что такое «признак» или «фича» в распознавании изображений?
Ответ: Это характерная особенность, которую сеть выделяет на изображении: от простых (края, углы) на начальных слоях до сложных (очки, колеса) на глубоких слоях.
Вопрос: Зачем нужна функция активации в нейроне?
Ответ: Она добавляет нелинейность в работу сети, позволяя ей аппроксимировать сложные зависимости между входными данными и ответом, без чего сеть была бы просто линейной моделью.
Вопрос: Что такое «переобучение» и как с ним борются?
Ответ: Это когда сеть слишком хорошо запоминает тренировочные данные, включая шум, и плохо работает на новых. Методы борьбы: dropout, аугментация данных, регуляризация, использование validation set.
Вопрос: Сколько нужно изображений для обучения своей модели распознавания?
Ответ: Объем зависит от сложности задачи. Для простой классификации (кошки/собаки) могут хватить тысячи изображений на класс, для сложных (медицинская диагностика) — десятки или сотни тысяч.
Вопрос: Можно ли использовать предобученную нейросеть для своей задачи?
Ответ: Да, это называется transfer learning (трансферное обучение). Можно взять архитектуру, обученную на большом наборе данных (например, ImageNet), и «дообучить» последние слои на своих данных.
Вопрос: Что такое «пулинг» (объединение слоев) и зачем он нужен?
Ответ: Это операция уменьшения размерности карты признаков (например, выбор максимума по области). Она снижает вычислительную сложность, обеспечивает инвариантность к малым сдвигам и предотвращает переобучение.
Вопрос: Как нейросеть выдает итоговый ответ при распознавании?
Ответ: На последнем, обычно полностью связанном слое, активация (чаще softmax) преобразует числовые значения в вероятности принадлежности к каждому классу. Класс с максимальной вероятностью и является ответом сети.
Краткая памятка: ключевые этапы создания нейросети для распознавания
- Четко определите задачу: что именно нужно распознавать (объекты, текст, лица) и в каких условиях.
- Соберите и подготовьте размеченный датасет. Качество данных критически важно.
- Проведите аугментацию данных (повороты, сдвиги, изменение яркости) для увеличения разнообразия и борьбы с переобучением.
- Выберите подходящую архитектуру нейронной сети (например, CNN для изображений).
- Разделите данные на три набора: тренировочный, валидационный (для настройки) и тестовый (для финальной оценки).
- Определите функцию потерь (loss function), которая будет измерять ошибку предсказаний.
- Выберите оптимизатор (например, Adam) для корректировки весов сети в процессе обучения.
- Настройте гиперпараметры: скорость обучения, размер батча, количество эпох.
- Запустите процесс обучения, отслеживая метрики на тренировочном и валидационном наборах.
- При появлении признаков переобучения (рост ошибки на валидации) примените методы регуляризации.
- Протестируйте окончательную модель на независимом тестовом наборе данных.
- Оцените метрики качества (точность, полнота, F1-мера) на тестовых данных.
- Экспортируйте обученную модель для интеграции в приложение или сервис.
- Спланируйте процесс периодического дообучения модели на новых данных для поддержания актуальности.




























