Введение

Как мы все знаем, глубокое обучение действительно стремительно выросло за последние годы и сегодня стало лицом «искусственного интеллекта». Но как с теоретической, так и с практической точки зрения, можем ли мы действительно назвать «интеллектуальным» алгоритм, которому нужны не только миллионы изображений, но и маркировка изображений, чтобы понять, что такое кошка?

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

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

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

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

Обучение без учителя

Обучение без учителя отличается от обучения с учителем, поскольку мы больше не пытаемся предсказать переменную y, по переменной x, а просто пытаемся узнать больше о распределении сам х.

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

Но мы можем ожидать, что, сделав это в течение некоторого времени, вы сможете очень хорошо рисовать и отточите два навыка:

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

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

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

В конце концов, обучив наш автоэнкодер, мы сможем обучить и кодировщик, и декодер, а кодер будет использоваться для классификации позже. Поскольку нам нужно иметь возможность восстанавливать x из z, кодировщик должен научиться извлекать полезные признаки, и этот экстрактор признаков можно использовать позже при классификации.

Полу-контролируемое обучение

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

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

Эксперименты

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

Поскольку MNIST превратился в «Hello world!» машинного обучения, мы также будем работать над этим, но на этот раз с особым ограничением: мы будем использовать только 512 выборок из 60 000 выборок MNIST, то есть менее 1% от общих данных и использовать еще меньше меток!

Я решил использовать отличный фреймворк Fast.ai, чтобы разработать быстрый и интуитивно понятный интерфейс для обучения без учителя. Тем из вас, кто не знает о Fast.ai, я настоятельно рекомендую посмотреть потрясающие видео, доступные на Youtube!

Чтобы упростить обучение автокодировщиков, я написал небольшую библиотеку под названием fastai_autoencoder, которая облегчает написание автокодировщиков и делает ее такой же понятной, как и обычные реализации кода fastai.

Теперь перейдем к коду! GitHub проекта можно найти здесь: https://github.com/dhuynh95/fastai_autoencoder

Сначала сюда импортируем фастай. Я не буду вдаваться в подробности пользовательского импорта из fastai_autoencoder, но, чтобы дать быстрое представление, узкое место - это способ, который вы выбрали для фильтрации информации в кодировщике. Есть несколько способов кодирования информации, о которых мы поговорим позже. Здесь мы будем использовать VAE (вариационный автоматический кодировщик), который использует специальный термин потерь в дополнение к потерям восстановления, термин расхождения Кульбака, который мы также рассмотрим позже.

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

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

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

Затем мы создадим здесь нашу модель. Здесь вы можете видеть, что я попытался факторизовать свой код и упростить работу с ним, поскольку я пробовал несколько разных вариантов и пытался реализовать разные документы, чтобы увидеть результаты. Но пока давайте пропустим это, все, что вам нужно знать, это то, что в конце мы создаем модель, объединяя три части вместе: кодировщик, узкое место и декодер. Наконец, мы обертываем все в обучаемом Fastai, чтобы использовать API, к которым мы привыкли.

Обратите внимание, что окончательный размер узкого места равен 16. Это означает, что мы берем изображение размером 28 * 28 = 768 пикселей, сжимаем его до 16 переменных и восстанавливаем 768 пикселей. изображение пикселей. Это означает, что коэффициент сжатия равен 48!

Теперь мы можем выполнить обычные learn.lr_find () и learn.recorder.plot () и получить наш небольшой сюжет, как обычно в Fastai:

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

Здесь мы видим, что реконструкция - это просто случайный шум, поскольку мы еще не начали обучение. Так чего же мы ждем? Пойдем !

Здесь я прошел в два этапа, сначала я тренировался без условия расхождения KL, как предлагается здесь: https://orbit.dtu.dk/files/121765928/1602.02282.pdf

Теперь, когда обучение окончено, давайте посмотрим на наши реконструкции:

Ах! Это намного лучше, даже несмотря на то, что мы видим, что есть незначительные изменения, реконструкция правильная, она даже немного сглаживает края, даже несмотря на то, что мы сжали размер на 48 в кодировщике!

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

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

Наконец, мы можем видеть ниже 2D-проекцию с использованием T-SNE наших закодированных изображений z,, окрашенных в соответствии с их классами:

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

Полу-контролируемое обучение

Теперь, когда у нас есть крутой обученный автоэнкодер, мы можем попробовать обучить классификатор поверх него и посмотреть, как он работает. Здесь мы изучим, насколько хорошо наша модель работает в трех различных настройках: когда мы предоставляем только 128 меток, 256 или все 512 меток, из которых она была обучена во время неконтролируемой части обучения.

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

Один из популярных приемов при работе с небольшим объемом данных - использование трансферного обучения. Здесь я сравнил использование предварительно обученного кодировщика из неконтролируемой обучающей части, заморозил его и добавил поверх него двухуровневую классификационную головку, а также Resnet18, настроенный на небольшие наборы данных растущего размера, от 128 меток до 512 меток. Наконец, мы сравниваем результаты точности по остальной части MNIST, которая представляет собой 59 000 изображений, которые мы не использовали для неконтролируемого предварительного обучения. У нас есть результаты ниже:

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

Просто для удовольствия, мы также можем увидеть, как эти методы работают для Fashion MNIST, который является более сложным набором данных, чем MNIST, где мы также использовали только 512 изображений. Сначала мы получаем следующую реконструкцию:

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

Заключение

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

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

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

Надеюсь, вам понравилась эта статья, и я скоро напишу другие статьи, в которых излагается теория, лежащая в основе VAE, и то, как вы можете реализовать ее в Fastai!

Если у вас есть какие-либо вопросы, не стесняйтесь обращаться ко мне в Linkedin, вы также можете найти меня в Twitter!