Мотивация

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

Примечание: я тренировал все, что ниже, используя этот набор данных.

Наивный подход

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

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

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

Генеративно-состязательные сети

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

Я собираюсь сосредоточиться на этих типах моделей, известных как генеративно-состязательные сети (GAN). С помощью GAN вы создаете две сети, одна из которых генерирует изображения, а другая пытается отличить сгенерированные изображения от реальных. Затем вы устанавливаете их в соревновании. Итак, вы просите сеть-генератор создать партию поддельных изображений, а затем сделать там метки 0, как в False или Fake. Вы также сэмплируете пакет реальных изображений с метками 1, как в True или Real. Вы тренируете дискриминатор на этих помеченных данных и, в свою очередь, тренируете генератор, определяя его потери в зависимости от количества сгенерированных изображений, правильно обнаруженных дискриминатором. Таким образом, генераторы пытаются пропустить через дискриминатор как можно больше поддельных изображений.

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

Вот лучшие результаты, которые я получил с этим подходом:

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

Многомасштабные градиентные сети GAN

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

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

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

Как это учится

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

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

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

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

Первоначально опубликовано на https://mauicv.com 21 июля 2020 г.