Neural Style Transfer — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
(What insights can convolutional neural network provide?)
(Style Loss)
(не показано 12 промежуточных версий этого же участника)
Строка 1: Строка 1:
 
== Описание алгоритма ==
 
== Описание алгоритма ==
  
[[Файл:Image1.jpeg|500px|thumb|right|Принцип работы алгоритма]]
+
[[Файл:Image1.jpeg|500px|thumb|right|Рис. 1. Принцип работы алгоритма]]
Алгоритм Neural Style Transfer, разработанный Леоном Гатисом, Александром Экером и Матиасом Бетге, позволяет получить изображение и воспроизводить его в новом художественном стиле. Алгоритм берет три изображения, входное изображение (англ. ''input image''), изображение контента (англ. ''content image'') и изображение стиля (англ. ''style image''), и изменяет входные данные так, чтобы они соответствовали содержанию изображения контента и художественному стилю изображения стиля.
+
Алгоритм '''нейронного переноса стиля''' (англ. ''Neural Style Transfer''), разработанный Леоном Гатисом, Александром Экером и Матиасом Бетге, позволяет получить изображение и воспроизводить его в новом художественном стиле. Алгоритм берет три изображения, входное изображение (англ. ''input image''), изображение контента (англ. ''content image'') и изображение стиля (англ. ''style image''), и изменяет входные данные так, чтобы они соответствовали содержанию изображения контента и художественному стилю изображения стиля. Авторами в качестве модели сверточной нейронной сети предлагается использовать сеть [https://neurohive.io/ru/vidy-nejrosetej/vgg16-model/ VGG16].
  
 
== Принцип работы алгоритма ==
 
== Принцип работы алгоритма ==
  
[[Файл:Image2.png|500px|thumb|right|Архитектура сверточной сети VGG16]]
+
[[Файл:Image2.png|500px|thumb|right|Рис. 2. Архитектура сверточной сети VGG16]]
[[Файл:Image3.jpeg|500px|thumb|right|Карты признаков сети VGG16]]
 
  
В этом разделе я хочу поделиться некоторой интуицией о том, как более глубокий слой CNN представляет изображение и как мы можем использовать это вычисленное представление, которое имеет смысл только для модели в наших интересах при разработке передачи нейронного стиля. Давайте возьмем архитектуру VGG16 для понимания этого представления в скрытых слоях.
+
Рассмотрим 1-й сверточный слой (англ. ''convolution layer'') VGG16, который использует ядро 3x3 и обучает 64 карты признаков (англ. ''feature map'') для генерации представления изображения размерности 224x224x64, принимая 3-канальное изображение размером 224x224 в качестве входных данных (''Рисунок 3''). Во время обучения эти карты признаков научились обнаруживать простые шаблоны, например, такие как прямые линии, окружности или даже не имеющие никакого смысла для человеческого глаза шаблоны, которые тем не менее имеют огромное значение для этой модели. Такое "обнаружение" шаблонов называется обучением представления признаков. Теперь давайте рассмотрим 10-й сверточный слой VGG16, который использует ядро 3x3 с 512 картами признаков для обучения и в итоге генерирует вывод представления изображения размерности 28x28x512. Нейроны 10-го слоя уже могут обнаруживать более сложные шаблоны такие как, например, колесо автомобиля, окно или дерево и т.д.
  
Используя вышеупомянутую архитектуру в качестве эталона, давайте рассмотрим 1-й слой свертки vgg16, который использует ядро 3x3 и обучает 64 карты признаков (feature map) для генерации представления изображения 224x224x64, принимая 3-канальное изображение размером 224x224 в качестве входных данных. если вы немного запутались, посмотрите ниже (Рисунок 3)
+
Собственно вышеперечисленные свойства характерны для любой [http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B5_%D0%BD%D0%B5%D0%B9%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81%D0%B5%D1%82%D0%B8 сверточной нейронной сети], работа которой обычно интерпретируется как переход от конкретных особенностей изображения к более абстрактным деталям, и далее к ещё более абстрактным деталям вплоть до выделения понятий высокого уровня. При этом сеть самонастраивается и вырабатывает необходимую иерархию абстрактных признаков (последовательности карт признаков), фильтруя маловажные детали и выделяя существенное.
  
Давайте предположим, что во время обучения этим 64 картам функций они, возможно, научились обнаруживать простые шаблоны, такие, что некоторые нейронные единицы активируются, когда они видят прямую линию, или даже для какого-либо другого типа шаблона, который может не иметь никакого смысла для человеческого глаза, но имеет огромный значение для этой модели. Это «Обнаружение» прямых линий или некоторого паттерна называется обучением представлению функции.
+
Такая природа представления кодирования сама по себе является ключом к передаче стиля, который используется для вычисления функции потерь между сгенерированным изображением относительно изображения контента и изображения стиля. При обучении модели более десяти тысяч изображений на класс модель может генерировать аналогичное представление признаков для множества различных изображений, если они принадлежат к одному классу или имеют схожий контент или стиль.  
  
Теперь давайте рассмотрим 10-й слой свертки vgg16, который использует ядро 3x3 с 512 картами объектов для обучения и, наконец, генерирует вывод представления изображения 28X28x512, просто для простоты, давайте предположим, что в этом 10-м слое есть определенные единицы, которые активируются изображение, содержащее круги, подобные колесу автомобиля, или некоторые из них, которые активируются изображением, имеющим некоторый рисунок, похожий на три пересекающиеся линии и т. д.
+
Следовательно, имеет смысл использовать разницу в значении представления признаков сгенерированного изображения по содержанию и по стилю изображения, чтобы направлять итерации, через которые мы производим само сгенерированное изображение, но как убедиться, что изображение с содержанием '''C''' и сгенерированное изображение '''G''' похожи по своему содержанию, а не по стилю, в то время как сгенерированное изображение наследует только похожее представление стиля изображения стиля '''S''', а не само изображение стиля в целом. Это решается разделением функции потерь на две части: одна - потеря контента, а другая - потеря стиля.
  
Можно с уверенностью предположить, что CNN не учится кодировать, что такое изображение, но на самом деле учится кодировать то, что представляет изображение, или какое содержимое видно в изображении, и из-за нелинейной природы нейронных сетей мы перешли от мелких слоев к более глубоким слоям. скрытые юниты становятся способными обнаруживать все более и более сложные особенности по заданному изображению.
+
== Функция потерь ==
  
Эта природа представления кодирования сама по себе является ключом к передаче стиля, который используется для вычисления потерь между сгенерированным изображением относительно контента и изображения стиля. При обучении модели более десяти тысяч изображений на класс модель может генерировать аналогичное представление признаков для множества различных изображений, если они принадлежат к одному классу или имеют схожий контент или стиль. Следовательно, имеет смысл использовать разницу в значении представления признаков сгенерированного изображения по содержанию и стилю изображения, чтобы направлять итерации, через которые мы производим само сгенерированное изображение, но как мы можем убедиться, что изображение с содержанием (C) и сгенерированное изображение (G ) похожи по своему содержанию, а не по стилю, в то время как с другой стороны, как мы можем быть уверены, что сгенерированное изображение наследует только похожее представление стиля из образа стиля (S), а не само изображение стиля в целом. Это решается разделением функции потерь на две части: одна - потеря контента, а другая - потеря стиля, и вскоре мы поймем, чем они отличаются друг от друга и как они преодолевают поставленные нами проблемы.
+
[[Файл:Image5.jpeg|500px|center]]
  
== Loss function ==
+
В уравнении выше, чтобы получить общую потерю <math>L_{total}</math> нужно рассчитать потерю содержимого <math>L_{content}</math> и потерю стиля <math>L_{style}</math>, а также <math>\alpha</math> и <math>\beta</math> - гиперпараметры, которые используются для определения весов для каждого типа потерь, то есть эти параметры можно представить просто как "рычаги" для управления тем, сколько контента / стиля мы хотим наследовать в сгенерированном изображении.
  
[[Файл:Image5.jpeg|500px|left]]
+
[[Файл:Image6.jpeg|500px|thumb|right|Рис. 3. Различные представления, используемые для изображений контента, стиля и сгенерированного изображения]]
Как вы можете видеть в приведенном выше уравнении, есть две вещи, которые нам нужно рассчитать, чтобы получить общую потерю: потеря содержимого и потеря стиля, альфа- и бета-гиперпараметры, которые используются для определения весов для каждого типа потерь, то есть эти параметры можно представить просто как ручки для управления тем, сколько контента / стиля мы хотим наследовать в сгенерированном изображении. Итак, давайте разберемся, что влечет за собой каждый из этих термов.
 
  
Какие входы для этой функции потерь отображаются выше? Мы понятия не имеем, как может выглядеть окончательный результат. Таким образом, наивный подход контролируемого обучения может не сработать. Ответ лежит на изображении ниже. (Рисунок 6)
+
Во время каждой итерации все три изображения, передаются через модель VGG16. Значения функции активации нейронов, которые кодируют представление признаков данного изображения на определенных слоях, принимаются как входные данные для этих двух функций потерь. Также стоит добавить: изначально мы случайным образом инициализируем сгенерированное изображение, например, матрицей случайного шума такого же разрешения, как и изображение контента. С каждой итерацией мы изменяем сгенерированное изображение, чтобы минимизировать общую потерю '''L'''.
  
[[Файл:Image6.jpeg|500px|thumb|right|Описание]]
+
== Функция потери контента ==
  
Во время каждой итерации все три изображения, то есть изображение контента, изображение стиля и сгенерированное изображение, передаются через модель vgg16. Значение активации скрытого модуля, который кодирует представление объекта данного изображения на определенных слоях, принимается как входные данные для этих функций потерь, проще говоря, вы можете напрямую думать об этом как о получении выходных данных слоев в сети VGG16, и это не так. Никаких жестких и быстрых правил по подбору слоев. Еще одна вещь, которую нужно добавить здесь: изначально мы случайным образом инициализируем сгенерированное изображение, если вы посмотрите на него, то это не более чем матрица случайного шума формы, такая же, как изображение контента. С каждой итерацией мы изменяем сгенерированное изображение, чтобы минимизировать общую потерю L.
+
Возьмем функциональное представление 7-го сверточного слой VGG16. Чтобы вычислить потерю контента, пропускаем изображение контента и сгенерированное изображение через VGG16 и получаем значения функции активации (выходы) 7-го слоя для обоих этих изображений. После каждого сверточного слоя идет ReLU, поэтому мы будем обозначать выход этого слоя в целом как relu_3_3 (поскольку это выход третьего сверточного слоя третьего набора / блока сверток) (Рисунок 2). Наконец, мы находим L2-норму поэлементного вычитания между этими двумя матрицами значений функции активации следующим образом:
  
'''Примечание:''' Здесь после каждого слоя Convolution его выход передается через relu в качестве функции активации, вы также можете проверить на рисунке 2, где каждый блок Convolution представлен как [Convolution + Relu]
+
[[Файл:Image7.jpeg|500px|center]]
 
 
== Content Loss ==
 
 
 
Потери контента легко рассчитать, давайте возьмем функциональное представление только одного из уровней, давайте рассмотрим 7-й слой свертки vgg16. Чтобы вычислить потерю контента, мы пропускаем и изображение контента, и сгенерированное изображение через vgg16 и получаем значения активации (то есть выходы) 7-го слоя конвоя для обоих этих изображений, для которых имеется Relu, поэтому мы будем обозначать выход этого слоя в целом как relu_3_3, поскольку это выход третьего сверточного слоя третьего набора / блока сверток (для справки см. рис. 2 и 6). Наконец, мы находим L2 Норму поэлементного вычитания между этими двумя матрицами активации следующим образом: Это поможет сохранить исходный контент в сгенерированном изображении, убедившись, что минимизируется разница в представлении объектов, которая логически фокусируется на разнице между содержимым обоих изображений.
 
 
 
Чтобы поместить эту потерю в математическую форму или уравнение, которое мы можем вычислить. Допустим, у нас есть функция Content loss, которая принимает в качестве входных данных три аргумента: изображение контента C, сгенерированное изображение G и слой L, активацию которого мы будем использовать для вычисления потерь. Теперь давайте обозначим каждый слой активации изображения контента как a[L](C), а слой активации сгенерированного изображения как a[L](G).
 
  
[[Файл:Image7.jpeg|500px|center]]
+
Это поможет сохранить исходный контент в сгенерированном изображении, а также минимизировать разницу в представлении признаков, которое логически фокусируется на разнице между содержимым обоих изображений.
  
== Style Loss ==
+
== Функция потери стиля ==
  
Теперь давайте посмотрим на потерю стиля, а при расчете потери стиля мы рассмотрим представление характеристик многих слоев свертки от мелких до более глубоких слоев модели. В отличие от потери контента, мы не можем просто найти разницу в единицах активации. Нам нужен способ найти корреляцию между этими активациями по разным каналам одного и того же слоя, и для этого нам нужно нечто, называемое матрицей Грама.
+
В отличии от потери контента потерю стиля нельзя рассчитать с помощью разницы значений функции активации нейронов. Необходимо найти корреляцию между значениями функции активации по разным каналам одного и того же слоя. И для этого авторы алгоритма предлагают воспользоваться матрицей Грама.
  
=== Gram Matrix ===
+
=== Матрица Грама ===
  
[[Файл:Image8.jpeg|500px|right]]
+
[[Файл:Image8.jpeg|500px|thumb|right|Рис. 4. Принцип рассчет матрицы Грама]]
[[Файл:Image9.jpeg|500px|right]]
 
  
 
Я попытаюсь создать основу, необходимую для понимания матрицы грамм, на примере. Итак, давайте рассмотрим, как мы передаем наше изображение стиля через vgg16 и получаем значения активации из 7-го уровня, который генерирует матрицу представления объектов размером 56x56x256, которую вы можете использовать на рисунке 2, который описывает архитектуру vgg16. Теперь давайте подробнее рассмотрим этот вывод.
 
Я попытаюсь создать основу, необходимую для понимания матрицы грамм, на примере. Итак, давайте рассмотрим, как мы передаем наше изображение стиля через vgg16 и получаем значения активации из 7-го уровня, который генерирует матрицу представления объектов размером 56x56x256, которую вы можете использовать на рисунке 2, который описывает архитектуру vgg16. Теперь давайте подробнее рассмотрим этот вывод.
Строка 68: Строка 59:
 
В то время как при вычислении потери стиля мы используем несколько уровней активации, эти сценарии приводят нас к возможности назначать разные весовые коэффициенты для каждой подпотери, предоставляемой разными уровнями. ниже уравнения суммирует то, что я только что сказал, довольно элегантно, но в нашем случае или в большинстве случаев в целом люди дают одинаковый вес для всех слоев.
 
В то время как при вычислении потери стиля мы используем несколько уровней активации, эти сценарии приводят нас к возможности назначать разные весовые коэффициенты для каждой подпотери, предоставляемой разными уровнями. ниже уравнения суммирует то, что я только что сказал, довольно элегантно, но в нашем случае или в большинстве случаев в целом люди дают одинаковый вес для всех слоев.
  
[[Файл:Image10.jpeg|500px|center]]
+
[[Файл:Image11.jpeg|500px|center]]
  
 
== Пример кода на PyTorch ==
 
== Пример кода на PyTorch ==

Версия 23:32, 17 апреля 2019

Описание алгоритма

Рис. 1. Принцип работы алгоритма

Алгоритм нейронного переноса стиля (англ. Neural Style Transfer), разработанный Леоном Гатисом, Александром Экером и Матиасом Бетге, позволяет получить изображение и воспроизводить его в новом художественном стиле. Алгоритм берет три изображения, входное изображение (англ. input image), изображение контента (англ. content image) и изображение стиля (англ. style image), и изменяет входные данные так, чтобы они соответствовали содержанию изображения контента и художественному стилю изображения стиля. Авторами в качестве модели сверточной нейронной сети предлагается использовать сеть VGG16.

Принцип работы алгоритма

Рис. 2. Архитектура сверточной сети VGG16

Рассмотрим 1-й сверточный слой (англ. convolution layer) VGG16, который использует ядро 3x3 и обучает 64 карты признаков (англ. feature map) для генерации представления изображения размерности 224x224x64, принимая 3-канальное изображение размером 224x224 в качестве входных данных (Рисунок 3). Во время обучения эти карты признаков научились обнаруживать простые шаблоны, например, такие как прямые линии, окружности или даже не имеющие никакого смысла для человеческого глаза шаблоны, которые тем не менее имеют огромное значение для этой модели. Такое "обнаружение" шаблонов называется обучением представления признаков. Теперь давайте рассмотрим 10-й сверточный слой VGG16, который использует ядро 3x3 с 512 картами признаков для обучения и в итоге генерирует вывод представления изображения размерности 28x28x512. Нейроны 10-го слоя уже могут обнаруживать более сложные шаблоны такие как, например, колесо автомобиля, окно или дерево и т.д.

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

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

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

Функция потерь

Image5.jpeg

В уравнении выше, чтобы получить общую потерю [math]L_{total}[/math] нужно рассчитать потерю содержимого [math]L_{content}[/math] и потерю стиля [math]L_{style}[/math], а также [math]\alpha[/math] и [math]\beta[/math] - гиперпараметры, которые используются для определения весов для каждого типа потерь, то есть эти параметры можно представить просто как "рычаги" для управления тем, сколько контента / стиля мы хотим наследовать в сгенерированном изображении.

Рис. 3. Различные представления, используемые для изображений контента, стиля и сгенерированного изображения

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

Функция потери контента

Возьмем функциональное представление 7-го сверточного слой VGG16. Чтобы вычислить потерю контента, пропускаем изображение контента и сгенерированное изображение через VGG16 и получаем значения функции активации (выходы) 7-го слоя для обоих этих изображений. После каждого сверточного слоя идет ReLU, поэтому мы будем обозначать выход этого слоя в целом как relu_3_3 (поскольку это выход третьего сверточного слоя третьего набора / блока сверток) (Рисунок 2). Наконец, мы находим L2-норму поэлементного вычитания между этими двумя матрицами значений функции активации следующим образом:

Image7.jpeg

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

Функция потери стиля

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

Матрица Грама

Рис. 4. Принцип рассчет матрицы Грама

Я попытаюсь создать основу, необходимую для понимания матрицы грамм, на примере. Итак, давайте рассмотрим, как мы передаем наше изображение стиля через vgg16 и получаем значения активации из 7-го уровня, который генерирует матрицу представления объектов размером 56x56x256, которую вы можете использовать на рисунке 2, который описывает архитектуру vgg16. Теперь давайте подробнее рассмотрим этот вывод.

В этом 3-D массиве имеется 256 каналов размером 56x56 каждый. Теперь давайте предположим, что есть канал ‘A’, чьи блоки активации могут активироваться, когда они сталкиваются с разделом изображения, содержащим черные и коричневые полосы, а затем есть канал ‘B’, чьи блоки активации могут активироваться, когда они сталкиваются с чем-то похожим на глазное яблоко

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

Если оба этих канала ‘A’ & ‘B’ активируются вместе для одного и того же входа, существует высокая вероятность того, что изображение может содержать лицо тигра (поскольку у него было два канала с высокими значениями, которые активируются для глазного яблока и коричневых черных полос) , Теперь, если оба эти канала будут запущены с высокими значениями активации, это означает, что они будут иметь высокую корреляцию по сравнению с корреляцией между каналом ‘A’ & ‘C’, где канал ‘C’ может активироваться, когда он видит ромбовидный шаблон. Таким образом, чтобы получить корреляцию всех этих каналов друг с другом, нам нужно вычислить что-то, называемое граммовой матрицей, мы будем использовать грамм-матрицу для измерения степени корреляции между каналами, которая позже будет служить мерой самого стиля. Теперь вы, возможно, поняли значение грамм-матрицы, но чтобы понять, как мы получаем грамм-матрицу из вышеупомянутого трехмерного массива, рассмотрим изображение, упомянутое ниже.

Теперь, как вы можете видеть, как каждый элемент этой граммовой матрицы содержит меру корреляции всех каналов относительно друг друга. Продвигаясь вперед, как мы используем эту вычисленную матрицу Грамма G для расчета потери стиля. Обозначим грамм-матрицу стилевого изображения слоя L как GM[L](S), а грамм-матрицу сгенерированного изображения того же слоя, что и GM[L](G). Обе матрицы грамм были вычислены из одного и того же слоя, следовательно, с использованием одного и того же числа каналов, что привело к тому, что он стал матрицей размера ch x ch. Теперь, если мы найдем сумму квадратичной разности или L2_norm вычитания элементов этих двух матриц и попытаемся минимизировать это, то это в конечном итоге приведет к минимизации разницы между стилем изображения изображения и сгенерированного изображения. Подумайте об этом, это может занять некоторое время, но когда это произойдет, вы будете загипнотизированы тем, насколько это просто, но эффективно.

Image10.jpeg

В вышеприведенном уравнении N_l представляет номер канала в карте признаков / выходных данных уровня l, а M_l представляет высоту * ширину карты объектов / выходных данных слоя l.

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

Image11.jpeg

Пример кода на PyTorch

class ContentLoss(nn.Module):

   def __init__(self, target,):
       super(ContentLoss, self).__init__()
       # we 'detach' the target content from the tree used
       # to dynamically compute the gradient: this is a stated value,
       # not a variable. Otherwise the forward method of the criterion
       # will throw an error.
       self.target = target.detach()
   def forward(self, input):
       self.loss = F.mse_loss(input, self.target)
       return input