7.2. Что изменило машинное обучение

Модуль image содержит несколько устаревших методов обнаружения – find_features() для обнаружения лиц на основе Haar Cascade, find_eye() для фиксированного поиска зрачка, find_hog() для сводок по направлениям градиентов, а также пути find_keypoints() и find_lbp() для произвольных ключевых точек. Все они по-прежнему работают; все они вытеснены конвейером машинного обучения.

7.2.1. Классическое разделение: вручную спроектированные сводки, обучаемые решения

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

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

  • find_features() обобщает окно изображения, суммируя яркость внутри нескольких прямоугольников и сравнивая суммы. Расположения прямоугольников были выбраны потому, что человеческие лица демонстрируют надёжные контрасты светлого и тёмного: брови на фоне щёк, глазницы на фоне лба, нос на фоне окружающей кожи.

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

  • find_lbp() обобщает окрестность каждого пикселя, кодируя, какие из окружающих пикселей светлее, а какие темнее. Это кодирование было выбрано потому, что такие узоры «светлее/темнее» отражают текстуру поверхности независимо от общей освещённости.

  • find_keypoints() находит угловые точки на изображении и описывает область вокруг каждого угла так, чтобы описание оставалось неизменным при повороте угла. Схема «угол и поворот» была выбрана потому, что одни и те же углы появляются вновь, когда сцена рассматривается под другим углом.

Когда сводка была написана вручную, небольшой обучающий шаг поверх неё мог объединить числа в решение. Алгоритм обнаружения лиц добавлял обучающий шаг к сводке из разностей прямоугольников, обучая его на размеченных изображениях лиц и не-лиц, чтобы выучить, какие сочетания разностей сигнализируют о лице. Сводка направлений границ подавалась на обучающий шаг, обученный на размеченных изображениях людей и не-людей. Дескрипторы углов подавались на шаг сопоставления, который выучивал, какой вес придать каждому углу. Каждый из этих вторых шагов – это алгоритм обучения; небольшой по современным меркам, но всё же алгоритм обучения.

Имело значение именно разделение вкладов. Человек вносил сводку. Машина выучивала комбинацию. Добавление новой цели означало написание новой сводки.

7.2.2. Что изменили нейронные сети

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

Изменение в том, кто что проектирует, является полным:

  • Человек проектирует вход – захваченные кадры заданного размера и формата.

  • Человек проектирует выход – формат тензора результата (по одной оценке на класс для классификации, список рамок для обнаружения, сетка ключевых точек для ориентиров).

  • Человек предоставляет размеченные обучающие данные – достаточно примеров цели и достаточно примеров не-целей, чтобы процессу обучения было на чём учиться.

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

7.2.3. Сочетание с модулем image

Конвейеры на основе нейронных сетей всё так же выполняют захват через те же API датчика, рисуют результаты через те же примитивы draw_rectangle() и draw_circle() и ограничивают работу теми же ROI вида (x, y, w, h). Типичный конвейер захватывает кадр, при необходимости находит грубую цель классическим детектором вроде find_blobs() и передаёт его ограничивающую рамку выводу в качестве ROI, выполняет вывод и наносит возвращённые обнаружения обратно на исходный кадр. Классические примитивы – это основа; сеть – это новый шаг посередине.