Вариационные автоэнкодеры и различные схемы инициализации

В моем стремлении овладеть машинным обучением и глубоким обучением (чтобы делать захватывающие биологические открытия) я взялся за вариационные автокодеры (VAE) в качестве следующей цели в моем списке. На первый взгляд простой, VAE, конечно же, состоит из кодировщика, декодера и соответствующей функции потерь. Тем не менее, примеров творческого применения VAE предостаточно, включая создание изображений, музыки и частей белков. И через секунду мы поймем, почему они так популярны в этих вопросах! Люди, кажется, по какой-то причине любят создавать изображения чисел и лиц с помощью VAE, поэтому я подумал, что попытал счастья в чем-то другом. После некоторого поиска я наткнулся на набор данных человеческих клеток крови (здоровых, а также инфицированных возбудителем малярии Plasmodium falciparum) на Kaggle (кстати, отлично подходит для наборов данных). Поскольку обе категории содержали около 14000 изображений, что не так уж плохо, я решил согласиться с этим и создать VAE для обеих категорий, чтобы генерировать изображения здоровых и инфицированных клеток. Это полезно? Я не знаю (возможно, не слишком много), но это отличный опыт обучения, и на него, безусловно, приятно смотреть!

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

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

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

Все идет нормально. Если мы изменим архитектуру, как указано, все ли в порядке? Не совсем. Нам все еще нужно адаптировать нашу функцию потерь. Для ошибки восстановления мы будем использовать двоичную кросс-энтропию. Но нам также понадобится еще один член в функции потерь, а именно дивергенция Кульбака – Лейблера (потеря KL). Проще говоря, это разница между распределениями вероятностей. В нашем случае это будет сумма разностей между распределениями вероятностей, созданными VAE, и нормальным распределением. Минимизируя это, мы заставляем распределения в скрытом пространстве группироваться вокруг центра (нормальное распределение). Это приводит к перекрытию сгенерированных распределений в скрытом пространстве и к улучшенному формированию изображения. Потому что в противном случае VAE может запомнить входные данные, создав четко разделенные распределения вероятностей для каждого типа входных данных. Суммируя ошибку реконструкции и потерю KL, мы получаем нашу окончательную функцию потерь, которую мы пытаемся минимизировать во время обучения.

Теперь мы можем строить! У меня есть все это в записной книжке Jupyter здесь, если вы хотите попробовать или просто украсть код для своих собственных проектов. VAE реализован в PyTorch, фреймворке глубокого обучения, с которым даже такие специалисты в области биологии, как я, находят достаточно удобными для работы. Я начал с бессовестной кражи кода VAE из репозитория PyTorch, а затем настраивал и модифицировал его до тех пор, пока он не соответствовал моим потребностям. Обычно я запускаю эти вещи в Colaboratory от Google, потому что он дает вам графический процессор Tesla K80 бесплатно, и это просто здорово! Вы можете просто использовать его с ноутбуками Jupyter и непрерывно запускать до 12 часов.

После получения изображений вы должны преобразовать их в набор данных PyTorch. Реализация этого в моем блокноте довольно проста, но в целом объекту набора данных PyTorch требуется индексатор (__getitem__) и длина (__len__). Мы можем использовать эту возможность, чтобы также применить некоторые преобразования к изображениям, например сделать их всех одинакового размера и нормализовать их. Затем мы можем передать набор данных в загрузчик данных, который разделит его на мини-пакеты, которые мы можем использовать для обучения. Легко, правда? Для самого VAE мы создаем экземпляры слоев в разделе __init__ и определяем взаимодействия слоев в разделе вперед. По сути, это просто набор линейных слоев со случайной функцией активации ReLU. Поскольку VAE могут быть немного привередливыми в обучении (подумайте об исчезающих и взрывающихся градиентах, ура!), Я также добавил два слоя пакетной нормализации в кодировщик и декодер. Уменьшая ковариационный сдвиг (увеличивая независимость двух взаимодействующих слоев), они обеспечивают большую стабильность во время обучения и даже имеют небольшой эффект регуляризации (вот почему они отключаются, если вы переключаете модель в режим оценки). В конце нам понадобится сигмовидная функция активации для двоичной кросс-энтропийной потери, чтобы все значения были между 0 и 1.

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

Кроме того, я добавил снижающуюся скорость обучения (уменьшение вдвое после каждой эпохи), чтобы повысить производительность. После обучения в течение 10 эпох я начал генерировать изображения с помощью обученных VAE. Для этого достаточно выбрать случайные значения из стандартного нормального распределения, ввести их в слой узких мест обученного VAE и декодировать их в сгенерированные изображения. Если мы посмотрим на изображения, созданные VAE, инициализированным Xavier, мы можем ясно увидеть, что VAE действительно чему-то научился из изображений. Сразу очевидна разница в цвете между неинфицированными (желтыми) и инфицированными (пурпурными) клетками. Затем, если вы присмотритесь, неинфицированные клетки кажутся более округлыми и более ровными по форме, чем инфицированные клетки. Хотя вы можете увидеть некоторую степень детализации в зараженных ячейках, это не совсем те четко очерченные кластеры, как на входных изображениях. Для изображений, созданных из VAE, инициализированных Kaiming, мы также можем наблюдать четкую разницу в цвете, но здесь детализация кажется еще менее выраженной. Кроме того, изображения кажутся довольно туманными. Фактически, изображения, сгенерированные VAE, были отмечены как своего рода шумные. Однако иногда это не обязательно плохо. Если вы помните рваные края входных изображений, небольшое размытие по краям, по крайней мере, сделает сгенерированные изображения немного более эстетичными.

Куда пойти отсюда? Сообщается, что генерирующие состязательные сети (GAN) создают изображения с повышенным разрешением по сравнению с VAE, поэтому, если это фактор, GAN могут быть привлекательными. Кроме того, особенно для изображений, использование линейных слоев может быть хуже, чем использование сверточных слоев. Создание CNN-VAE может привести к значительно улучшенным генерируемым изображениям, так что попробуйте, если хотите! В принципе, использование автоэнкодера для такого типа настройки неинфицированных / инфицированных клеток может дать вам представление о характеристиках соответствующих состояний клеток (путем исследования параметров в построенном скрытом пространстве) и может помочь в автоматизированной диагностике малярии. В любом случае, мне определенно понравилось работать над этой мелочью, и я узнал немного больше о глубоком обучении и PyTorch. С нетерпением жду следующего проекта!

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