Машинное обучение это весело! Часть 4: Распознавание лиц с помощью глубокого обучения

Pavel Pleskov
11 min readFeb 26, 2019

--

Перевод цикла статей Adam Geitgey — “Машинное обучение это весело!”: ч.1, ч.2, ч.3, ч.4, ч.5, ч.6, ч.7, ч.8.

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

Эта технология называется распознаванием лиц. Стоит вам несколько раз отметить своих друзей на фото, и Facebook научится распознавать их лица. Это довольно удивительная технология — Facebook может распознавать лица с точностью 98% — почти так же точно, как человек!

Давайте разберемся, как работают современные технологии распознавания лиц! Но простым узнаванием лиц друзей тут не ограничится — это слишком просто. Мы можем довести эту технологию до совершенства и решить более сложную задачу — отличить Уилла Феррелла(известного актера) от Чада Смита (знаменитого рок-музыканта)!

Как использовать машинное обучение в сложных задачах

В частях 1, 2 и 3 мы использовали машинное обучение для решения изолированных задач в одно действие — оценка стоимости дома, создание новых данных на основании существующих или определение того, есть ли на изображении какой-либо объект. Для решения этих задач достаточно выбрать какой-нибудь алгоритм машинного обучения, ввести данные — и вот он результат.

Однако распознавание лиц состоит из множества взаимосвязанных подзадач:

  1. Во-первых, нужно посмотреть на картинку и найти на ней все лица
  2. Во-вторых, нужно научиться распознавать каждое лицо, даже если оно странным образом повернуто, или если освещение плохое — ведь это все равно все тот же человек.
  3. В-третьих, нужно уметь определять уникальные черты лица, которые отличают одного человека от других, например, размер глаз, форма лица и так далее.
  4. Наконец, нужно сравнить выявленные уникальные особенности этого лица со всеми людьми, которых система уже знает, чтобы понять, кто изображен на фото.

Мозг человека делает всё мгновенно и незаметно для нас. Можно сказать, что люди настолькохороши в распознавании лиц, что видят лица даже в повседневных объектах:

Компьютеры не способны к таким обобщениям высокого уровня (по крайней мере, пока …), поэтому нам придется учить их этому шаг за шагом.

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

Распознавание лиц — шаг за шагом

Давайте займемся задачей по порядку, а точнее, пошагово. На каждом этапе мы разберемся с алгоритмом машинного обучения (для каждого этапа он будет разный). Я не буду разъяснять каждый алгоритм полностью, чтобы статья не превратилась в книгу. Вместо этого я изложу основные идеи, лежащие в основе каждого из них, а также вы узнаете, как создать свою собственную систему распознавания лиц на Python, используя OpenFace и dlib.

Шаг 1. Поиск всех лиц

На первом этапе нашего конвейера нужно обнаружить лица. Ясное дело, нам нужно найти лица на фотографии, прежде чем делать что-то еще.

Если вы в последние лет 10 пользовались какой-нибудь камерой, вы, вероятно, видели распознавание лиц в действии:

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

Обнаружение лиц стало мейнстримом в начале 2000-х годов, когда Пол Виола (Paul Viola) и Майкл Джонс (Michael Jones) изобрели способ обнаружения лиц, который был достаточно быстрым, чтобы работать на дешевых камерах. Однако сегодня существуют более надежные решения. Мы собираемся использовать метод, изобретенный в 2005 году — гистограмма направленных градиентов (Histogram of Oriented Gradients) — или просто HOG, для краткости.

Чтобы найти лица на изображении, сперва сделаем наше изображение черно-белым, потому что для поиска лиц цветовые данные не нужны:

Затем мы рассмотрим каждый пиксель на нашем изображении, один за другим. Но интересует нас не столько сам пиксель, сколько пиксели, окружающие его:

Наша цель — выяснить, насколько темным является текущий пиксель по сравнению с соседними. Затем мы рисуем стрелку, показывающую, в каком направлении изображение становится темнее:

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

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

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

Для этого мы разделим изображение на маленькие квадраты размером 16x16 пикселей каждый. В каждом квадрате мы подсчитаем, сколько точек градиента повернуто в каждом из основных направлений (вверх, вверх, вправо, вправо и т. д.). Затем мы заменим этот квадрат на изображении стрелочками, направленными туда же, куда и большинство.

В конечном итоге мы преобразуем исходное изображение так, что ясно проглядывается базовая структура лица:

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

Используя этот метод, мы легко можем найти лица на любом изображении:

Если вы хотите попробовать сделать это самостоятельно, используя Python и dlib, то код, показывающий, как создавать и просматривать представления HOG-изображений, можно найти здесь.

Шаг 2. Расположение лиц

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

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

Для этого мы будем использовать алгоритм под названием оценка ориентиров лица (face landmark estimation). Есть много способов сделать это, но мы будем использовать метод, изобретенный в 2014 году Вахидом Каземи (Vahid Kazemi) и Жозефиной Салливан (Josephine Sullivan).

Основная идея состоит в том, что мы отметим 68 особых точек (называемых ориентирами), которые существуют на каждом лице — верхняя часть подбородка, внешняя точка каждого глаза, внутренняя точка каждой брови и т. д. Затем мы обучим алгоритм машинного обучения находить эти 68 особых точек на любом лице:

Вот результат размещения 68 ориентиров на нашем тестовом изображении:

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

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

Если вы хотите попробовать сделать это самостоятельно, используя Python и dlib, то по ссылкам вы найдете код для поиска ориентиров на лице и код для преобразования изображения с использованием этих ориентиров.

Шаг 3. Кодирование лица

Теперь мы подходим к сути проблемы — как отличить одно лицо от другого. И здесь все становится действительно интересно!

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

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

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

Самый надежный способ измерить лицо

Итак, какие измерения лиц нужны нам для пополнения известной базы данных? Размер ушей? Длина носа? Цвет глаз? Что-то другое?

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

Решение заключается в создании сверточной нейронной сети глубокого обучения (как и в части 3). Но вместо того, чтобы обучать сеть распознавать объекты на изображении, как мы делали в прошлый раз, мы научим ее создавать 128 измерений для каждого лица.

Во время обучения сети анализируется одновременно три лица:

  1. Обучающее изображение лица известного человека
  2. Другая фотография того же известного человека
  3. Изображение совершенно другого человека

Затем алгоритм просматривает измерения, которые он делает для каждого из этих трех изображений. Затем он немного настраивает нейронную сеть, чтобы удостовериться, что измерения, созданные для изображений #1 и #2, будут более похожи, а измерения для #2 и #3 — менее похожи:

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

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

Кодирование изображения лица

Этот процесс обучения сверточной нейронной сети для получения карты лиц требует большого количества данных и мощного компьютера. Даже при использовании дорогой видеокарты NVidia Telsa требуется 24 часа непрерывного обучения, чтобы получить хорошую точность.

Но как только сеть будет обучена, она сможет генерировать измерения для любого лица, даже такого, которое видит впервые! Поэтому это нужно сделать всего один раз. К счастью для нас, ребята из OpenFace уже сделали это и опубликовали несколько обученных сетей, которые мы можем использовать. Спасибо, Брэндону Амосу (Brandon Amos) и его команде!

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

А каким частям лица соответствуют эти 128 чисел? А мы и понятия не имеем. Но для нас это не имеет большого значения. Нас интересует только то, что сеть генерирует почти одинаковые числа по двум изображениям одного и того же человека.

Если вы хотите попробовать сделать этот шаг самостоятельно, OpenFace предоставляет lua скрипт, который генерирует карты всех изображений в папке и записывать их в файл csv. Вот как его запустить.

Шаг 4: Поиск имени пользователя по кодировке

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

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

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

Итак, давайте опробуем нашу систему. Сперва я натренировал классификатор, используя около 20 фотографий Уилла Феррелла, Чада Смита и Джимми Фалона (Jimmy Falon):

Затем я запустил классификатор на каждом кадре знаменитого видео с Уиллом Ферреллом и Чадом Смитом на YouTube, где они притворялись друг другом на шоу Джимми Фэллона:

Сработало! Обратите внимание, как хорошо это работает даже в разных положениях лиц — даже боком!

Попробуйте самостоятельно

Повторим порядок действий:

  1. Кодирование изображения с использованием алгоритма HOG для создания упрощенной версии изображения. Используя это упрощенное изображение, найдите ту часть изображения, которая больше всего похожа на исходную HOG-кодировку лица.
  2. Определите положение лица, отметив основные ориентиры на нем. Как только вы найдете эти ориентиры, используйте их, чтобы преобразовать изображение и отцентровать глаза и рот.
  3. Пропустите изображение центрированного лица через нейронную сеть, которая умеет измерять черты лица. Сохраните эти 128 измерений.
  4. Сравнив измерения с теми, которые мы получили в прошлом, найдите наиболее похожего человека — это и есть наш клиент!

Теперь, когда вы знаете, как все это работает, ознакомьтесь с полной инструкцией о том, как запустить полный цикл распознавания лиц на вашем собственном компьютере:

UPDATE 9/4/2017: Вы можете выполнить вот эти шаги с OpenFace. Однако, я выпустил новую библиотеку распознавания лиц на Python под названием face_recognition, которая намного проще в установке и использовании. Поэтому я рекомендую сначала попробовать face_recognition, и лишь потом двигаться дальше!

Более того, я собрал предварительно сконфигурированную виртуальную машину с функциями face_recognition, OpenCV, TensorFlow и множеством других предустановленных инструментов глубинного обучения. Вы можете легко загрузить и запустить эту машину на своем компьютере. Попробуйте ее, если не хотите устанавливать все эти библиотеки самостоятельно!

--

--