Вступление

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

Без лишних слов, займемся кодированием!

Ввод и этикетка

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

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

Увы, на практике простой среднеквадратичной ошибки (MSE) пикселей недостаточно, потому что она не очень хорошо отражает различия между сложными высокоуровневыми функциями на двух изображениях. Например, если у нас есть изображение низкого качества красной бархатной подушки, модель, оптимизированная для попиксельного MSE, вероятно, сможет улучшить его, но не сможет сохранить или добавить бархатную текстуру (она просто выглядят как высокое изображение красной подушки без какой-либо конкретной текстуры, а не как гладкая текстура бархата).

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

Если бы только было что-то, что могло бы извлекать из изображения низко- и высокоуровневые функции ...

Не больше, чем кажется на первый взгляд

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

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

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

VGG

Само собой разумеется, что экстрактор признаков очень влияет на конечный результат, и чем лучше его способность определять форму, тем лучше наш усилитель. Это может привести к мысли, что недавние современные (SOTA) архитектуры, такие как EfficientNet или сети без нормализации (NFNet) с такими настройками, как сжатие и возбуждение или пропуск соединения, будут очень хорошими вариантами, а модели с большей точность на популярных тестах зрения (а именно ImageNet) была бы более подходящей.

Загадочным образом именно VGG, одна из старейших, самых медленных и наименее точных CNN дает наилучшие результаты, а не какая-то сложная, сумасшедшая сеть. Я не смог найти ничего, что бы тщательно исследовало, почему это так, и это самый информативный поток, который я обнаружил, но пока просто знайте, что, если вы не готовы проделать большую работу по изменению архитектур, таких как ResNet, VGG является ваш лучший вариант.

Крючки

Чтобы получить извлеченные характеристики изображения, нам нужно получить доступ к значениям, вычисленным во время прямого прохода нейронной сети. Написание модели с нуля и сохранение промежуточных значений вручную - это один из подходов, но PyTorch предлагает привязку, аккуратный и гибкий метод проверки и изменения вывода слоя (или его градиента) во время прямого и обратного проходов.

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

Никаких проходов вперед или назад не было сделано, поэтому нам нужно что-то скормить модели, чтобы получить ее промежуточные значения. Мы можем использовать изображение из COCO, но сначала нам нужно превратить его в тензор PyTorch и нормализовать (потому что VGG был обучен на нормализованных изображениях):

hooks теперь содержит вывод первых трех уровней активации, доступных через hooks.stored:

Три отдельных тензора (для трех ReLU), каждый из которых является четырехмерным тензором (размер пакета, количество каналов, ширина, высота), которые соответствуют формам слоев VGG.

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

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

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

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

Его выходные данные имеют форму (размер пакета, #channels, #channels), а пространственные измерения отсутствуют.

Потеря восприятия

Сочетание этих двух элементов приводит к потере восприятия, и, таким образом, это прекрасное представление о том, насколько схожи содержание двух изображений (морская свинка или хомяк? Шелк или хлопок?) И стиль (кубизм или импрессионизм? Эскизный или черно-белый?). Следовательно, его можно использовать для ряда задач преобразования изображения в изображение, таких как раскрашивание, перенос стиля или улучшение.

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

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

Выполнено! PerceptualLoss ведет себя точно так же, как любая функция потерь PyTorch, и ее можно легко включить в Fastai Learner.

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

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

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

Во-первых, давайте сделаем изображение подходящим для потери восприятия:

И убедитесь, что потери равны нулю, когда независимые и зависимые переменные равны:

Теперь мы ухудшаем исходное изображение:

И посмотрите, каковы потери (значения находятся на разных шкалах, поэтому мы не можем напрямую их сравнивать):

Они оба больше нуля, и что? Как вы думаете, что происходит, когда мы перемещаем все пиксели на один вправо:

И пересчитать убыток?

Потеря восприятия более чем в два раза меньше, но на самом деле MAE больше! Сходство двух изображений весьма субъективно, но я не думаю, что на Земле есть хоть один человек (за исключением, по-видимому, средней абсолютной ошибки), который утверждал бы, что первое изображение ближе к оригиналу, чем второе.

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

Заключение

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

В следующей статье мы рассмотрим нашу модель U-Net с предварительно обученным кодировщиком и выясним, почему она лучше генеративных состязательных сетей.

Пожалуйста, если у вас есть какие-либо вопросы или отзывы, не стесняйтесь размещать их в комментариях ниже и, как всегда, благодарим вас за чтение!

Похожие статьи:











Социальные сети:





Больше контента на plainenglish.io