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

GAN – основные принципы

Здравствуйте и вновь добро пожаловать на занятия по теме «Глубокое обучение без учителя, часть 2».

В этой части курса мы переходим к новой теме – GAN. Мы подробно разберем GAN, функции затрат GAN и под конец рассмотрим DCGAN.

GAN расшифровывается как генеративно-состязательная сеть (generative adversarial network), и по мере прохождения части станет ясно, почему она имеет такое название. GAN были названы наиболее интересной разработкой 2016 года, хотя на самом деле они изобретены в 2014-м. Основная привлекательность GAN заключается в том, что они чрезвычайно хорошо подходят для создания реалистичных, правдоподобных образцов. Как вы видели ранее в курсе, GAN используются для создания очень интересных приложений, таких как преобразование набросков в изображения фотографического качества, и именно поэтому исследователи в области глубокого обучения возлагают на GAN большие надежды.

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

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

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

На этом месте мы переходим к тому, чтобы поговорить о том, как работают GAN. И вновь-таки, на самом деле это совокупность двух различных нейронных сетей. Одна из них называется генератором, а вторая – дискриминатором. Суть в том, что эти две нейронные сети буду вести друг с другом дуэль. Задача генератора – попытаться «обмануть» дискриминатора; выполняет он её путём генерации очень реалистично выглядящих образцов. Задача дискриминатора, как можно понять по его названию, – провести классификацию между образцами, созданными генератором, и реальными изображениями.

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

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

Функция затрат GAN (часть 1)

Мы подробнее разберём целевую функцию генеративно-состязательной сети. У нас есть две нейронные сети.

Нужны ли нам две функции затрат? Или достаточно одной, но которую одновременно одна нейронная сеть старается максимизировать, а вторая – минимизировать? Эта лекция целиком посвящена чёткому прояснению данного вопроса.

Начнём с той общей идеи, что две наши нейронные сети стараются оптимизировать противоположные вещи (что конкретно значит «противоположные», мы увидим через минуту). Начнём же с дискриминатора, поскольку он выполняет классификацию, а мы знаем, что обучение с учителем немного проще. Какого рода классификацию должен выполнять дискриминатор? Выполняет он её, получая два вида изображений – настоящие и фальшивые; это просто две разные метки, а значит, мы выполняем двоичную классификацию. А какая функция затрат подходит для двоичной классификации? Мы её уже на самом деле видели в разделе, посвящённом вариационным автокодировщикам, – это двоичная кросс-энтропийная функция. Вспомним, как она выглядит:

где t представляет собой целевую переменную, а y – исходящую вероятность дискриминатора.

Предположим, что t = 1 означает настоящее изображение, а t = 0 – фальшивое. Тогда можно утверждать, что y = D(x), являющееся числом между 0 и 1, представляет собой вероятность того, что изображение x является настоящим. Это общепринятый способ обозначения дискриминатора – просто D(x). Для завершенности предположим, что параметрами дискриминатора является θD, так что мы также можем записать D(x; θD). В этом случае x может представлять как реальное, так и фальшивое изображение.

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

Перейдём теперь к генератору. Можем ли мы и его представить в виде функции? Как вы можете догадаться, логично обозначить функцию генератора буквой G, а точнее, функцией G(z). Здесь z представляет скрытую априорную вероятность, так что мы имеем такого же рода графическую структуру, как и в случае вариационного автокодировщика. Действительно, произведение выборки будет происходить очень схожим образом: вначале мы выбираем z из априорной вероятности, а затем подставляем в G, чтобы получить окончательный образец изображения. И конечно же, параметры G мы обозначаем через θG: G(z; θG).

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

Тут уже x представляет собой настоящее изображение, тогда как G(z) – фальшивое. Нам больше не нужна целевая переменная, ведь мы и так знаем, что все x тут – настоящие, а все G(z) – фальшивые.

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

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

Это всё, что касается функции затрат дискриминатора.

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

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

Если вы знакомы с теорией игр, то вам может быть интересно, что игры с нулевой суммой также называются минимаксными, поскольку решение включает в себя нахождение и минимумов, и максимумов. Конкретнее говоря, мы минимизируем относительно θD, но максимизируем относительно θG, или, посмотрев с другой стороны, максимизируем JD относительно θD и минимизируем относительно θG:

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

Если вы знакомы с теорией игр, то вам может быть интересно, что игры с нулевой суммой также называются минимаксными, поскольку решение включает в себя нахождение и минимумов, и максимумов. Конкретнее говоря, мы минимизируем относительно θD, но максимизируем относительно θG, или, посмотрев с другой стороны, максимизируем JD относительно θD и минимизируем относительно θG:

Теоретический анализ, выполненный в контексте теории игр, не имеет особого отношения к данному курсу, но если вам интересно, то можете ознакомиться со статьёй в файле extra_reading.txt.

Что дальше? Имея функцию затрат, мы можем начать минимизировать её, воспользовавшись одним из оптимизаторов градиентного спуска библиотеки Tensorflow. Однако у нас получается интересная ситуация, с которой мы ещё не сталкивались: у нас есть две нейронные сети, а значит, нужно создать два разных оптимизатора. Если не учитывать этого, алгоритм относительно прост. В цикле мы вначале получаем набор реальных образцов и ряд фальшивых, созданных генератором. Второй этап – выполнить одну итерацию градиентного спуска для дискриминатора. Третий – запустить одну итерацию градиентного спуска для генератора, и повторять всё это до тех пор, пока не начнём наблюдать хорошие образцы. В некоторых практических реализациях градиентный спуск для генератора выполняется дважды, и сообщают о лучших результатах. Это можно изменять в зависимости от того, как работает GAN: если дискриминатор начинает работать слишком хорошо, можно чаще обучать генератор.

Функция затрат GAN (часть 2)

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

В чём же проблема с функцией затрат как она есть? Проблема с ней в возникает с точки зрения генератора. Рассмотрим кросс-энтропийную функцию подробнее:

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

Предположим, дискриминатор очень хорошо справляется с классификацией настоящих и фальшивых изображений. Это значит, что D(G(z)) будет очень близко к нулю, а значит – и весь второй член будет равен нулю. Однако нас интересует градиент, поэтому рассмотрим наклон кривой. Что представляет из себя наклон в районе нулю? По сути, это соответствует наименьшему возможному градиенту среди всех возможных. И это проблема, поскольку градиентный спуск является нашим обучающим алгоритмом – мы всегда двигаемся в направлении, пропорциональном градиенту. Другими словами, когда дискриминатор очень хорош в классификации настоящих и фальшивых изображений, то у генератора остаётся мало шансов улучшить свою работу.

Каково же решение? Мы можем просто использовать другую функцию затрат для генератора. Основная идея – «перевернуть цель», другими словами, вместо того, чтобы стремиться к целевой переменной, равной нулю для фальшивых изображений, генератор стремится к целевой переменной, равной 1. Иначе говоря, мы будем стараться минимизировать отрицательное ожидаемое значение логарифма D(G(z)):

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

Одно замечание: поскольку эта новая функция затрат означает, что сумма функций затрат дискриминатора и генератора больше не равна нулю, то это больше не игра с нулевой суммой. Эту функцию затрат называют ненасыщенной эвристикой. Что это значит? Когда мы говорим «ненасыщенная», это значит, что градиент не насыщен, то есть не сходится к некоторому единичному значению. В нашем случае мы видим, что этого не происходит. Когда генератор ошибается, градиент становится круче, и чем больше ошибается – тем более крутым становится. Это хорошо, поскольку чем больше ошибается генератор, тем больший шаг он делает для исправления своих ошибок. Это и называется эвристикой, поскольку мы делаем это, лишь чтобы решить численное затруднение. Это противоположно теоретическому выводу функции затрат. Таким образом, нет никакого теоретического обоснования такой функции затрат, просто это удобно, потому что решает численную проблему.

Важно отметить, что если вы заглянете в одно из руководств, написанных изобретателями генеративно-состязательных сетей, то заметите, что некоторые из утверждений и диаграмм в этой работе в некотором роде вводят в заблуждение. В частности, можно видеть, что график, показывающий функцию затрат относительно D(G(z)) масштабирован очень странным способом. Мы, правда, в этой лекции используем такой же, но это лишь для большей последовательности. Как вы можете видеть, он очень сильно сжат в вертикальном направлении; другими словами, вертикальная шкала очень большая, тогда как горизонтальная изменяется лишь от 0 до 1. Это вызывает ощущение, будто наклон плоский, тогда как на самом деле – нет. Если взять производную от log (1 – x), то получится -1/(1 – x). Для этой производной если x = 0, то наклон равен -1, а если x = 1, то наклон будет равен минус бесконечности. То есть на самом деле наименьшим наклоном будет -1, а не 0. В статье указывается, что градиент исчезает, что звучит так, будто градиент стремится к нулю, а в сочетании с графиком, выглядящим так, будет наклон стремится к нулю, можно действительно подумать, что он стремится к нулю. Важно знать, что это только потому, что график отмасштабирован таким образом. На самом же деле наклон не стремится к нулю.

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

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

Одно замечание: поскольку эта новая функция затрат означает, что сумма функций затрат дискриминатора и генератора больше не равна нулю, то это больше не игра с нулевой суммой. Эту функцию затрат называют ненасыщенной эвристикой. Что это значит? Когда мы говорим «ненасыщенная», это значит, что градиент не насыщен, то есть не сходится к некоторому единичному значению. В нашем случае мы видим, что этого не происходит. Когда генератор ошибается, градиент становится круче, и чем больше ошибается – тем более крутым становится. Это хорошо, поскольку чем больше ошибается генератор, тем больший шаг он делает для исправления своих ошибок. Это и называется эвристикой, поскольку мы делаем это, лишь чтобы решить численное затруднение. Это противоположно теоретическому выводу функции затрат. Таким образом, нет никакого теоретического обоснования такой функции затрат, просто это удобно, потому что решает численную проблему.

Важно отметить, что если вы заглянете в одно из руководств, написанных изобретателями генеративно-состязательных сетей, то заметите, что некоторые из утверждений и диаграмм в этой работе в некотором роде вводят в заблуждение. В частности, можно видеть, что график, показывающий функцию затрат относительно D(G(z)) масштабирован очень странным способом. Мы, правда, в этой лекции используем такой же, но это лишь для большей последовательности. Как вы можете видеть, он очень сильно сжат в вертикальном направлении; другими словами, вертикальная шкала очень большая, тогда как горизонтальная изменяется лишь от 0 до 1. Это вызывает ощущение, будто наклон плоский, тогда как на самом деле – нет. Если взять производную от log (1 – x), то получится -1/(1 – x). Для этой производной если x = 0, то наклон равен -1, а если x = 1, то наклон будет равен минус бесконечности. То есть на самом деле наименьшим наклоном будет -1, а не 0. В статье указывается, что градиент исчезает, что звучит так, будто градиент стремится к нулю, а в сочетании с графиком, выглядящим так, будет наклон стремится к нулю, можно действительно подумать, что он стремится к нулю. Важно знать, что это только потому, что график отмасштабирован таким образом. На самом же деле наклон не стремится к нулю.

Теперь, зная функции затрат как для дискриминатора, так и для генератора, мы можем взглянуть на блок-схему, которая обрисовывает происходящее. Стартуя с верхнего левого угла, мы видим, что начинаем со скрытой переменной z, которая генерируется из равномерного распределения. Она передаётся в генератор, являющийся нейронной сетью, которая просто генерирует нечто, имеющее такую же форму, что и учебные данные, и обозначается через . Затем идут некоторые данные, поступающие из наших действительных учебных данных и которые мы обозначаем через x. И то, и другое поступает в дискриминатор, который выдаёт решение, и отсюда мы можем создать двоичную кросс-энтропийную функцию ошибок. Однако это же решение используется и с целью создания функции затрат генератора, а потому идёт и туда. Всё это похоже на топографический граф, показывающий течение данных через GAN. Для обучения же параметров используется, конечно, стандартный градиентный спуск.

DCGAN

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

В литературе по глубокому обучению указывается, что в 2015 году был создан очень успешный тип GAN, который называется DCGAN. Это именно та архитектура, на которой в наше время основывается большинство GAN, и именно её мы будем рассматривать в данном курсе. DCGAN известны тем, что способны создавать высококачественные изображения, которые можно масштабировать до высоких разрешений за один проход. До DCGAN был другой тип нейронной сети, также способный генерировать изображения с высоким разрешением и называющийся LAPGAN, однако там процесс был более сложный. Исходная статья по DCGAN также доступна в файле extra_reading.txt, так что можете глянуть, если интересно.

DCGAN расшифровывается как «GAN глубокой свёртки» (deep convolutional GAN). Такое название несколько вводит в заблуждение, поскольку это не значит, что предыдущие GAN не были глубокими или не включали свёртку. Однако есть другие специфические черты, которые отличают DCGAN от других алгоритмов. Пройдёмся же по этим признакам.

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

Другая уникальная особенность DCGAN – то, что они заимствуют свою архитектуру из так называемой всесвёрточной сети (all-convolutional network). Этот тип сети упрощает традиционную архитектуру LeNet, которая, если помните, является набором слоёв свёртки и агрегирования, за которыми следуют несколько полносвязных. Во всесвёрточной сети, как следует из названия, у нас есть набор свёрточных слоёв, но нет слоёв агрегирования, и это всё. В DCGAN у нас также есть набор свёрточных слоёв без агрегирования и лишь один полносвязный слой (или, возможно, нет). Преимущество отсутствия агрегирования и использования шага, большего 1, заключается в том, что нам нужно меньше умножать.

К примеру, предположим, что мы хотим, чтобы выход был равен половине длины входа. Можно использовать свёртку, а потом агрегирование с величиной агрегирования 2, а можно просто использовать свёртку с шагом 2. Больше о всесвёрточных сетях можно прочитать в статье в файле extra_reading.txt.

Ещё одной отличительной особенностью DCGAN является то, что они используют Adam-оптимизацию. Это алгоритм адаптивного градиента, вроде AdaGrad и RMSProp, но включает в себя ещё и импульс. Сделаем его краткий обзор, если вы с ним ещё не встречались. Прежде всего в Adam-оптимизаторе есть три представляющие интерес переменных. Во-первых мы отслеживаем время, поэтому она обозначается t; t, как и следовало ожидать, на каждом этапе увеличивается на единицу:

Следующая переменная – среднее значение каждого градиента. Тут используется скользящее среднее, аналогично тому, что происходит при пакетной нормализации и в обучении с подкреплением. В качестве коэффициента затухания среднего значения используется константа β1:

Следующая переменная – среднее значение каждого градиента. Тут используется скользящее среднее, аналогично тому, что происходит при пакетной нормализации и в обучении с подкреплением. В качестве коэффициента затухания среднего значения используется константа β1:

Заметьте, все эти операции являются поэлементными, так что если мы работаем с матрицами, то это будут двухмерные объекты, а если со свёрточными фильтрами – то четырёхмерными.

Мы также отслеживаем скользящее среднее квадрата градиента, как в RMSProp. Для квадрата градиента в качестве коэффициента затухания используется константа β2:

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

И наконец, у нас идёт изменяющийся во времени коэффициент обучения, который меняется следующим образом:

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

И наконец, у нас идёт изменяющийся во времени коэффициент обучения, который меняется следующим образом:

Это необходимо потому, что и m, и ν инициируются в районе нуля, так что они смещены к нулю, а данная поправка нам это компенсировать.

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

Отметим, что иногда в этой записи ε находится внутри квадратного корня, хотя на самом деле это не имеет особого значения.

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

Наконец мы можем рассмотреть картину DCGAN в целом. Здесь мы видим (см. слайд), что генератор начинает со скрытого вектора z размерностью 100, проецирует и преобразует его в трёхмерный объект, а затем выполняет ряд свёрток, пока мы не получим изображение размером 64×64. Что же касается дискриминатора, то мы начинаем с изображения размером 64×64, проводим серию свёрток, а в конце выполняем двоичную логистическую регрессию.

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

Отметим, что иногда в этой записи ε находится внутри квадратного корня, хотя на самом деле это не имеет особого значения.

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

Наконец мы можем рассмотреть картину DCGAN в целом. Здесь мы видим (см. слайд), что генератор начинает со скрытого вектора z размерностью 100, проецирует и преобразует его в трёхмерный объект, а затем выполняет ряд свёрток, пока мы не получим изображение размером 64×64. Что же касается дискриминатора, то мы начинаем с изображения размером 64×64, проводим серию свёрток, а в конце выполняем двоичную логистическую регрессию.

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

Андрей Никитенко
Андрей Никитенко
Задать вопрос эксперту
Понравилась статья? Поделить с друзьями:
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: