transfer learning что это
Transfer learning что это
Transfer Learning (трансферное обучение) — это подраздел машинного обучения, целью которого является применение знаний, полученные из одной задачи, к другой целевой задаче. Существует множество решений, который могут помочь Data Scientist’у применить его к своей проблеме, поэтому нет необходимости изобретать велосипед.
Например, знания, полученные при обучении классификации статей Википедии, можно использовать для решения задачи классификации медицинских текстов. Можно пойти дальше, и использовать модель, обученную для решения классификации автомобилей, чтобы распознавать птиц в небе, как одну из задач компьютерного зрения (Computer Vision).
История Transfer Learning
История трансферного обучения восходит к 1993 году. В своей статье «Передача между нейронными сетями на основе различимости (англ. Discriminability-Based Transfer between Neural Networks)» Lorien Pratt открыла ящик Пандоры и представила миру потенциал трансферного обучения [1]. В июле 1997 года журнал Machine Learning опубликовал серию статей о трансферном обучении [2]. По мере развития смежные области, например многозадачное обучение (multi-task learning), также были включены в трансферное обучение. Сегодня Transfer Learning является мощным инструментом искусственного интеллекта. Andrew Ng предсказывает подъём трансферного обучения с точки зрения коммерческого успеха [3].
Ожидание Andrew Ng коммерческого успеха подразделов машинного обучения
Как работает Transfer Learning
Прежде всего стоит обратить внимание на 2 аспекта при использовании Transfer Learning:
Предварительно обученная модель — это модель, созданная и обученная кем-то другим для решения проблемы, аналогичной нашей. На практике кто-то, имея большие вычислительные ресурсы, они конструируют большую нейронную сеть для решения конкретной проблемы, тренируют её на большом наборе данных (Big Data), например ImageNet или Wikipedia Corpus. Так, например, VGG19 имеет 143.667.240 параметров и используется для классификации изображений. Под «открытой» моделью мы подразумеваем, что она обнародована, и её можно свободно использовать.
Ресурсы с предварительно обученными моделями:
В редких случаях предварительно обученные модели хорошо работают для целевой задачи. Как правило, их необходимо поднастроить по следующим причинам:
Предварительно обученные сети используются для дообучения (fine-tuning) или выделения признаков (feature extraction).
Дообучение
В архитектурах Deep Learning начальные слои изучают общую информацию, а слои на последнем уровне более специфичные признаки. Например, первые слои запониманют текстуру, цвет, общую картину, а последние слои глаза, рот, родинки и т.д. Многие модели обучены на всевозможных ситуациях, например, ImageNet содержит 1 миллион изображений с 1000 классами, поэтому нет необходимости изменять общую картину, которую видит текущая модель. Вместо этого полезнее дополнить новыми конкретными признаками, дообучив только последние слои, чтобы перепрофилировать её для собственных нужд.
Затрагивая больше слоев для дообучения, повышается риск переобучения (overfitting). Например, модель VGG19 может после полного переобучения показать непредсказуемые результаты в рамках Transfer Learning, причем не в пользу Data Scientist’а. Поэтому часто обходятся двумя-тремя последними слоями.
Выделение признаков
Для выделения признаков используются представления, полученные предыдущей моделью, для извлечения признаков из новых образцов, которые затем пропускаются через новый классификатор. В этом методе просто добавляется классификатор, который будет обучаться с нуля, поверх предварительно обученной модели для решения целевой функции.
В сверточные архитектуры нейронных сетей (CNN) обычно состоят из двух частей: сверточной и полносвязной. Для выделения признаков (feature extraction) сверточная часть остаётся неизменной. В то время как Fine Tuning захватывает несколько последних сверточных слоев.
Сверточная основа не используется по причине их универсальности. Так, например, они имеют представления о присутствии объектов и их местоположении. С другой стороны, полносвязные слои не имеют знаний о местоположении объектов, т.е. не обладают свойством инвариантности, поэтому их безбоязненно можно поменять на собственные.
Выделение признаков в Transfer Learning реализуется двумя способами:
Что выбрать дообучение или выделение признаков
Оба метода могут повысить точность модели, но при условии наличия достаточного объёма данных, в противном случае сеть не «почувствует» изменений от нового набора данных и не сможет перепрофилироваться.
Выделение признаков применяется в том случае, когда решаемая задача прошлой сети схожа с целевой. А вот если есть существенные отличия, то используется дообучение, которое является более затратной с вычислительной точки зрения.
Deep Learning: Transfer learning и тонкая настройка глубоких сверточных нейронных сетей
В предыдущей статье из цикла «Deep Learning» вы узнали о сравнении фреймворков для символьного глубокого обучения. В этом материале речь пойдет о глубокой настройке сверточных нейронных сетей для повышения средней точности и эффективности классификации медицинских изображений.
Цикл статей «Deep Learning»
Примечание: далее повествование будет вестись от имени автора.
Введение
Распространенной причиной потери зрения является диабетическая ретинопатия (ДР) — заболевание глаз при диабете. Исследование пациентов с помощью флюоресцентной ангиографии потенциально способно снизить риск слепоты. Существующие тенденции исследований показывают, что глубокие сверточные нейросети (ГСНС) весьма эффективны для автоматического анализа больших наборов изображений и для выявления отличительных признаков, по которым можно распределить изображения на разные категории практически без ошибок. Обучение ГСНС редко происходит с нуля из-за отсутствия заранее заданных наборов с достаточным количеством изображений, относящихся к определенной области. Поскольку для обучения современных ГСНС требуется 2–3 недели, центр Berkley Vision and Learning Center (BVLC) выпустил итоговые контрольные точки для ГСНС. В этой публикации мы используем заранее обученную сеть: GoogLeNet. Сеть GoogLeNet обучена на большом наборе естественных изображений ImageNet. Мы передаем распознанные весов ImageNet в качестве начальных для сети, затем настраиваем заранее обученную универсальную сеть для распознавания изображений флюоресцентной ангиографии глаз и повышения точности предсказания ДР.
Использование явного выделения отличительных признаков для предсказания диабетической ретинопатии
В настоящий момент уже проделана обширная работа по разработке алгоритмов и методик обработки изображений для явного выделения отличительных признаков, характерных для пациентов с ДР. В стандартной классификации изображений применяется следующий универсальный рабочий процесс:
Тем не менее все эти процессы связаны со значительными затратами времени и усилий. Для дальнейшего повышения точности предсказаний требуются огромные объемы маркированных данных. Обработка изображений и выделение отличительных признаков в наборах данных изображений — весьма сложный и длительный процесс. Поэтому мы решили автоматизировать обработку изображений и этап выделения отличительных признаков, используя ГСНС.
Глубокая сверточная нейросеть (ГСНС)
Для выделения отличительных признаков в изображениях требуются экспертные знания. Функции выделения в ГСНС автоматически формируют изображения для определенных областей, не используя никакие функции обработки отличительных признаков. Благодаря этому процессу ГСНС пригодны для анализа изображений:
Слои C — свертки, слои S — пулы и выборки
Свертка. Сверточные слои состоят из прямоугольной сети нейронов. Веса при этом одинаковы для каждого нейрона в сверточном слое. Веса сверточного слоя определяют фильтр свертки.
Опрос. Pooling layer берет небольшие прямоугольные блоки из сверточного слоя и проводит подвыборку, чтобы сделать из этого блока один выход.
В этой публикации мы используем ГСНС GoogLeNet, разработанную в Google. Нейросеть GoogLeNet выиграла конкурс ImageNet в 2014 году, поставив рекорд по наилучшим единовременным результатам. Причины выбора этой модели — глубина работы и экономное использование ресурсов архитектуры.
Transfer learning и тонкая настройка глубоких сверточных нейросетей
На практике обучение целых ГСНС обычно не производится с нуля с произвольной инициализацией. Причина состоит в том, что обычно не удается найти набор данных достаточного размера, требуемого для сети нужной глубины. Вместо этого чаще всего происходит предварительное обучение ГСНС на очень крупном наборе данных, а затем использование весов обученной ГСНС либо в качестве инициализации, либо в качестве выделения отличительных признаков для определенной задачи.
Тонкая настройка. Стратегии переноса обучения зависят от разных факторов, но наиболее важными являются два: размер нового набора данных и его схожесть с исходным набором данных. Если учесть, что характер работы ГСНС более универсален на ранних слоях и становится более тесно связанным с конкретным набором данных на последующих слоях, можно выделить четыре основных сценария:
Ограничения transfer learning. Поскольку мы используем заранее обученную сеть, наш выбор архитектуры модели несколько ограничен. Например, мы не можем произвольным образом убрать сверточные слои из заранее обученной модели. Тем не менее благодаря совместному использованию параметров можно с легкостью запустить заранее обученную сеть для изображений разного пространственного размера. Это наиболее очевидно в случае сверточных и выборочных слоев, поскольку их функция перенаправления не зависит от пространственного размера входных данных. В случае с полносвязанными слоями этот принцип сохраняется, поскольку полносвязанные слои можно преобразовать в сверточный слой.
Скорость обучения. Мы используем уменьшенную скорость обучения для весов ГСНС, подвергаемых тонкой настройке, исходя из того, что качество весов заранее обученной ГСНС относительно высоко. Не следует искажать эти данные слишком быстро или слишком сильно, поэтому и скорость обучения, и спад скорости должны быть относительно низкими.
Дополнение данных. Одним из недостатков нерегулярных нейросетей является их чрезмерная гибкость: они одинаково хорошо обучаются распознаванию как деталей одежды, так и помех, из-за чего повышается вероятность чрезмерной подгонки. Мы применяем регуляризацию Тихонова (или L2-регуляризацию), чтобы избежать этого. Впрочем, даже после этого был значительный разрыв в производительности между обучением и проверкой изображений ДР, что указывает на чрезмерную подгонку в процессе тонкой настройки. Чтобы устранить этот эффект, мы применяем дополнение данных для набора данных изображений ДР.
Существует множество способов дополнения данных, например, зеркальное отображение по горизонтали, случайная обрезка, изменение цветов. Поскольку цветовая информация этих изображений очень важна, мы применяем лишь поворот изображений на разные углы: на 0, 90, 180 и 270 градусов.
Замена входного слоя заранее обученной сети GoogLeNet на изображения ДР. Мы проводим тонкую настройку всех слоев, кроме двух верхних заранее обученных слоев, содержащих универсальные веса.
Тонкая настройка GoogLeNet. Используемая нами сеть GoogLeNet изначально была обучена на наборе данных ImageNet. Набор данных ImageNet содержит около 1 млн естественных изображений и 1000 меток/категорий. В нашем размеченном наборе данных ДР содержится около 30 000 изображений, относящихся к рассматриваемой области, и четыре метки/категории. Следовательно, этого набора данных ДР недостаточно для обучения сложной сети, какой является GoogLeNet: мы будем использовать веса из сети GoogLeNet, обученной по ImageNet. Мы проводим тонкую настройку всех слоев, кроме двух верхних заранее обученных слоев, содержащих универсальные веса. Первоначальный слой классификации loss3/classifier выводит предсказания для 1000 классов. Мы заменяем его новым двоичным слоем.
Заключение
Благодаря тонкой настройке можно применять усовершенствованные модели ГСНС в новых областях, где их было бы невозможно использовать иначе из-за недостатка данных или ограничений по времени и стоимости. Такой подход позволяет добиться существенного повышения средней точности и эффективности классификации медицинских изображений.
Если вы увидели неточность перевода, сообщите пожалуйста об этом в личные сообщения.
Transfer Learning с использованием TensorFlow.JS
На практике в подавляющем большинстве вы не будете иметь дело с созданием новых моделей и обучением их с нуля на клиентской стороне. Чаще всего придется создавать модели на базе уже существующих. Эту технику называют Transfer Learning.
Кроме того, на мой взгляд Transfer Learning – это наиболее перспективная техника для использования на клиентской стороне с помощью TensorFlowJS. Большим преимуществом тут перед применением той же самой техники на сервере – это сохранение конфиденциальности клиентской информации и наличием возможности доступа к сенсорам (камера, гео-локации и др).
Принцип работы Transfer Learning прост. Вначале модель обучается на базе большого набора тренировочных данных. Во время процесса обучения, нейронная сеть извлекает большое количество полезных характеристик (признаков) конкретной решаемой задачи, которые могут быть использованы как база для новой, которая будет обучаться уже на малом числе тренировочных данных для более специфичной, но похожей задачи (рисунок 1). Таким образом, переобучение может происходить на устройствах с ограниченными ресурсами за относительно меньшее время.
Рисунок 1 – Структурная схема Transfer Learning
Для загрузки модели в TensorFlow используют специальный JSON формат, который в свою очередь может быть двух типов: graph-model или layers-model (рисунок 2).
Рисунок 2 – Классификация форматов сериализации моделей, совместимые с TensorFlowJS
Для Transfer Learning модель в формате graph-model не применима, мы можем использовать эту модель только в том виде, в котором ее загрузили, без возможности ее переобучении на новой выборке данных или же изменении топологии под свои нужды. Поэтому ниже мы будет вести речь, только про модель в формате layers-model.
С помощью специального конвертора вы можете конвертировать модели, например обученных на Python с помощью фреймворка Keras (он сейчас включен как подмодуль в TensorFlow) в формат, совместимый с TF.js. Более подробно вы можете узнать тут.
После загрузки модели, мы можем модифицировать и переобучить ее согласно требованиям задачи. Так как мы будем стремиться уменьшить время на обучение модели на базе новой выборки данных, то очевидным будет то, что необходимо “замораживать” (freeze) как можно больше слоев в исходной модели. Заморозить слой – это перевод всех нейронов слоя из категории обучаемых (trainable) в категорию необучаемых (untrainable). Во время обучения сети, оптимизатор будет модифицировать только обучаемые параметры сети, что может значительно сократить время на ее обучение.
Справедливым вопросом тогда будет – как много и какие слои мы должны замораживать. Чтобы интуитивно понимать это, давайте рассмотрим типовую структурную схему нейронной сети, которая связана с классификаций изображений между N классами. Структурная схема приведена на рисунке 3.
Рисунок 3 – Топология нейронной сети для классификации изображений между N классами
Нейронная сеть включает в себя несколько последовательно подключенных сверточных слоев (convolutional layers) и в конце подключено несколько скрытых полносвязных слоев нейронных сетей (dense layers, fully-connected layers).
Даже если мы будем использовать модель, которая знает как распознавать машины, а нам необходимо распознавать наличие человеческого лица на изображении, то несмотря на то что задачи кажутся абсолютно разными, сверточные слои, находящиеся ближе к входу нейронной сети для обоих сетей будут извлекать идентичные признаки (рисунок 4)
. Таким образом с учетом вышесказанного, замораживать слои необходимо начинать со входа нейронной сети, а количество замораживаемых слоев прямо пропорционально схожести решаемой задачи с задачей, которая решает предварительно загруженная модель.
Другим не менее важным параметром для выбора сколько слоев необходимо замораживать – это размер располагаемого набора данных, с которым мы собираемся переобучать модель.
Например, если мы располагаем ограниченным числом тренировочных данных, с которым собираемся переобучать модель, а новая задача сходна с задачей, которая решала предварительно загруженная сеть – то в данном случае имеет смысл заморозить все сверточные слои. С другой стороны – если мы имеем большее число тренировочных данных, а предварительно загруженная сеть не похожа на задачу, которую мы решаем, то тут мы можем вовсе не замораживать слои.
В последнем случае вы можете задать вопрос – так если мы не фиксируем ни одного слоя, то смысл загружать предварительно обученную модель с ее весами. Однако при обучении модели с нуля – фреймворк инициализирует веса нейронной сети произвольно, что делает процесс обучения модели дольше, чем если бы мы использовали уже предварительно настроенные веса, в которых как мы уже отмечали выше – низкоуровневые слои для разных задач будут иметь приблизительно идентичные настройки.
. Обобщим, выше сказанное – чем больше у нас обучающая выборка для обучающей модели, тем меньше слоев нам надо замораживать.
Визуализация алгоритма, описанного выше, вы можете посмотреть на рисунке 5.
Рисунок 5 – Схема настройки новой нейронной сети на базе уже обученной
Практика
Для начала давайте посмотрим на картину в целом и что мы собираемся делать и разберем каждый шаг.
Рисунок 6 – Структурная диаграмма по созданию новой модели на базе обученной модели MobileNet
1 шаг – Загрузка обученной модели MobileNet и ее анализ
MobileNet – модель, обученная на базе ImageNet выборке (коллекция, включающая более миллиона изображений, разбитую вручную между 1000 классами).
Загрузим модель с помощью специального пользовательского React-hook:
Посмотрим на топологию загруженной сети вызовом model.summary(), рисунок 7.
Рисунок 7 – Топология загруженной модели
Модель состоит из 88 слоев, входной слой которого представлен тензором размерностью [null, 224, 224, 3], принимающий изображение размерностью 224×224 пикселей с тремя цветовыми каналами. Выходной слой – это тензор размерность [null,1000].
Выходной тензор [null, 1000] – это так называемый one-hot вектор, в котором все значения равны нулю, за исключением одного, например [0, 0, 1, 0, 0] – это значит, что нейронная сеть считает с вероятностью 1, что на изображении класс с индексом 2 (индексация как обычно начинается с нуля). Когда мы будет использовать модель, то этот вектор будет представлять собой распределение вероятности для каждого из классов, например, можно получить такие значения: [0.07, 0.1, 0.03, 0.75, 0.05]. Обратите внимание, что сумма всех значений будет равна 1, а модель считает с максимальной вероятностью 0.75, что это объект класса c индексом 3.
В связи с тем, что для нашей задачи мы имеем только 3 класса, то нам необходимо модифицировать топологию модели, так как исходная загруженная модель умеет классифицировать между 1000 классами. Давайте изобразим схему того, что мы хотим сделать.
Слои модели можно разбить условно на слои, отвечающих за:
— извлечение характерных признаков изображения
— классификацию изображений между 1000 классами
Для новой модели, мы хотим использовать все слои, отвечающих за извлечение признаков изображений, но при этом исключим все слои, отвечающих за классификацию изображений между 1000 классами, и вместо этого предоставить свой классификатор, который будет производить классификацию между 3мя классами.
На рисунке 8 показана диаграмма разбивка загруженных слоев по их назначению (рисунок 8).
Рисунок 7 – Создание новой модели на базе существующей
Кстати, тут можно проанализировать нашу задачу на предмет, стоит ли замораживать слои. Во-первых, однозначно мы не будем заставлять пользователя делать большую тренировочную выборку для обучения сети, будет вполне себе достаточно по 30-50 изображений каждого класса. Также решаемая нами задача – классификация между 3 классами изображений с жестами, достаточно близка к задаче классификации изображений между 1000 классами, которая была предварительно обучена на большом наборе тренировочных изображений. Следовательно, согласно рисунку 5, мы можем заморозить все слои части модели MobileNetV2, которые мы извлекли для своих нужд:
Шаг 2 – Поиск последнего слоя в загруженной модели, отвечающего за извлечение характерных признаков изображения
Для этого будем использовать АПИ tf.LayersModel.getLayer, который позволяет найти искомый слой либо по его индексу, либо по уникальному имени. Более предпочтительным является поиск слоя по уникальному имени, чем по его индексу. Обратите внимание (рисунок 7), каждый слой загруженной модели имеет уникальное название: input_1; conv_pw_13_bn; conv_pw_13_relu и др. Как и договаривались – найдем последний сверточный слой в модели и это является слой с именем conv_pw_13_relu. Таким образом код будет выглядеть следующим образом:
Шаг 3 – Создание нового классификатора для классификации между 3 классами
— второй слой – скрытый полносвязный слой, который будет содержать 100 нейронов (параметр может быть подобран на базе экспериментов, это так называемый hyper parameter) с активационной функцией RELU. RELU – наиболее распространенная активационная функция, которая добавляет нелинейность модели;
— третий слой – выходной полносвязный слой, содержащий ровно 3 нейрона, каждый из которых определяет вероятность принадлежности изображения к одному из трех классов: камень, ножницы, бумага. Слой будет с активационной функцией SOFTMAX. SOFTMAX функция, которая всегда используется для последнего слоя для решения задач множественной классификации. Она преобразует вектор z размерности K в вектор той же размерностью σ, где каждое значение представлена вещественным числом в интервале [0, 1], а их сумма равна единице. И как уже указывалось выше,каждое значение в векторе σi трактуются как вероятность того, то объект принадлежит классу i.
Рисунок 8 – Новые слои для модели, отвечающие за классификацию между 3 классами
Код будет выглядеть следующим образом:
В шаге 2 мы нашли последний слой в графе модели, который мы хотим оставим в новой разрабатываемой модели. Давайте свяжем этот слой с классификатором, созданным на шаге 3 (см. рисунок 6). Для этого экземпляры класса модели/слоев имеют специальный метод apply, который делает соединение между слоями. Это будет выглядеть следующим образом:
Шаг 5 – Создание новой модели и ее компиляция
Для создания новой модели на базе существующей мы будет использовать tf.model, который принимает в качестве аргумента объект с двумя обязательными полями inputs и outputs. Оба параметра ожидают массив, где каждый элемент массива представляет собой Symbolic tensor (отличие от обычного тензора – это то, что по сути это описание тензора имеющая сведения о размерности и типе, но при этом отсутствуют данные, так называемый placeholder).
Каждый слой в модели имеет два атрибута – вход и выход, представленные Symbolic tensor.
Тут иногда удобно сопоставлять слой с обычной JS функцией, которая принимает входной параметр, внутри производится некоторая логика по вычислению и всегда возвращает выходной параметр. Отличие тут, что входными и выходными параметрами будут Symbolic Tensor.
Итак, нам надо определить inputs и outputs для новой модели. Input для новой модели будет совпадать с input загруженной модели и доступно через: pretrainedModel.inputs.
А выходным Symbolic Tensor – это выход после последнего слоя нового классификатора, который доступен в переменной newOutput, после применения метода apply на предыдущем шаге.
Скомпилируем модель, задав нужный оптимизатор и loss-функцию. Наиболее лучшим оптимизатором является tf.train.adam, а loss-функция для классификации задают обычно categoricalCrossentropy:
Полный код создания новой модели на базе предварительно обученной MobileNet
Осталось лишь добавить UX элементы, позволяющие пользователю задать выборки для трех типов изображений, предоставить кнопку, инициализирующей процесс обучения:
После того, как процесс обучения будет закончить, необходимо запустит процесс использования этой модели для классификации изображений: