Что такое 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 — как это работает? Часть 4
В этой статье вы узнаете:
Введение
Для задач обнаружения объектов выделяют два метода (источник и подробнее— тут):
Transfer learning
Transfer learning — это метод обучения нейронных сетей, при котором мы берем уже обученную на каких-то данных модель для дальнейшего дообучения для решения другой задачи. Например, у нас есть модель EfficientNet-B5, которая обучена на ImageNet-датасете (1000 классов). Теперь, в самом простом случае, мы изменяем ее последний classifier-слой (скажем, для классификации объектов 10-ти классов).
Взгляните на картинку ниже:
Encoder — это слои subsampling’а (свертки и пулинги).
Замена последнего слоя в коде выглядит так (фреймворк — pytorch, среда — google colab):
Загружаем обученную модель EfficientNet-b5 и смотрим на ее classifier-слой:
Изменяем этот слой на другой:
Decoder нужен, в частности, в задаче сегментации (об этом далее).
Стратегии transfer learning
Стоит добавить, что по умолчанию все слои модели, которые мы хотим обучать дальше, обучаемы. Мы можем «заморозить» веса некоторых слоев.
Для заморозки всех слоев:
Чем меньше слоев мы обучаем — тем меньше нам нужно вычислительных ресурсов для обучения модели. Всегда ли эта техника оправданна?
В зависимости от количества данных, на которых мы хотим обучить сеть, и от данных, на которых была обучена сеть, есть 4 варианта развития событий для transfer learning’а (под «мало» и «много» можно принять условную величину 10k):
Semantic segmentation
Семантическая сегментация — это когда мы на вход подаем изображение, а на выходе хотим получить что-то в духе:
Выражаясь более формально, мы хотим классифицировать каждый пиксель нашего входного изображения — понять, к какому классу он принадлежит.
Подходов и нюансов здесь очень много. Чего стоит только архитектура сети ResNeSt-269 🙂
Интуиция — на входе изображение (h, w, c), на выходе хотим получить маску (h, w) или (h, w, c), где c — количество классов (зависит от данных и модели). Давайте теперь после нашего encoder’а добавим decoder и обучим их.
Decoder будет состоять, в частности, из слоев upsampling’а (повышения размерности). Повышать размерность можно просто «вытягивая» по высоте и ширине наш feature map на том или ином шаге. При «вытягивании» можно использовать билинейную интерполяцию (в коде это будет просто один из параметров метода).
Архитектура сети deeplabv3+:
Если не углубляться в детали, то можно заметить, что сеть использует архитектуру encoder-decoder.
Более классический вариант, архитектура сети U-net:
Что это за серые стрелочки? Это, так называемые, skip connections. Дело в том, что encoder «кодирует» наше входное изображение с потерями. Для того, чтобы минимизировать такие потери — как раз и используют skip connections.
В этой задаче мы можем применить transfer learning — например, можем взять сеть с уже обученным encoder’ом, дописать decoder и обучить его.
На каких данных и какие модели показывают себя лучше всего в этой задаче на данный момент — можно посмотреть тут.
Instance segmentation
Более сложный вариант задачи сегментации. Его суть в том, что мы хотим не только классифицировать каждый пиксель входного изображения, а еще и как-то выделять различные объекты одного класса:
Бывает так, что классы «слипшиеся» или между ними нет видимой границы, но мы хотим разграничить объекты одного класса друг от друга.
Подходов здесь тоже несколько. Самый простой и интуитивный состоит в том, что мы обучаем две разные сети. Первую мы обучаем классифицировать пиксели для каких-то классов (semantic segmentation), а вторую — для классификации пикселей между объектами классов. Мы получаем две маски. Теперь мы можем вычесть из первой вторую и получить то, что хотели 🙂
На каких данных и какие модели показывают себя лучше всего в этой задаче на данный момент — можно посмотреть тут.
Object detection
Подаем на вход изображение, а на выходе хотим увидеть что-то в духе:
Самое интуитивное, что можно сделать — «бегать» по изображению различными прямоугольниками и, используя уже обученный классификатор, определять — есть ли на данном участке интересующий нас объект. Такая схема имеет место быть, но она, очевидно, не самая лучшая. У нас ведь есть сверточные слои, которые каким-то образом иначе интерпретируют feature map «до»(А) в feature map «после»(Б). При этом мы знаем размерности фильтров свертки => знаем какие пиксели из А в какие пиксели Б преобразовались.
Давайте взглянем на YOLO v3:
YOLO v3 использует разные размерности feature map’ов. Это делается, в частности, для того, чтобы корректно детектировать объекты разного размера.
Далее происходит конкатенация всех трех scale’ов:
Выход сети, при входном изображении 416х416, 13х13х(B * (5 + С)), где С — количество классов, B — количество боксов для каждого региона (у YOLO v3 их 3). 5 — это такие параметры, как: Px, Py — координаты центра объекта, Ph, Pw — высота и ширина объекта, Pobj — вероятность того, что объект находится в этом регионе.
Давайте посмотрим на картинку, так будет чуть более понятно:
YOLO отсеивает данные предсказания изначально по objectness score по какому-то значению (обычно 0.5-0.6), а затем по non-maximum suppression.
На каких данных и какие модели показывают себя лучше всего в этой задаче на данный момент — можно посмотреть тут.
Заключение
Различных моделей и подходов к задачам сегментации и локализации объектов в наши дни очень много. Существуют определенные идеи, поняв которые, станет легче разбирать тот зоопарк моделей и подходов. Эти идеи я попытался выразить в данной статье.
В следующих статьях поговорим про style transfer и GAN’ы.
Transfer Learning: как быстро обучить нейросеть на своих данных
Машинное обучение становится доступнее, появляется больше возможностей применять эту технологию, используя «готовые компоненты». Например, Transfer Learning позволяет использовать накопленный при решении одной задачи опыт для решения другой, аналогичной проблемы. Нейросеть сначала обучается на большом объеме данных, затем — на целевом наборе.
В этой статье я расскажу, как использовать метод Transfer Learning на примере распознавания изображений с едой. Про другие инструменты машинного обучения я расскажу на воркшопе «Machine Learning и нейросети для разработчиков».
Если перед нами встает задача распознавания изображений, можно воспользоваться готовым сервисом. Однако, если нужно обучить модель на собственном наборе данных, то придется делать это самостоятельно.
Для таких типовых задач, как классификация изображений, можно воспользоваться готовой архитектурой (AlexNet, VGG, Inception, ResNet и т.д.) и обучить нейросеть на своих данных. Реализации таких сетей с помощью различных фреймворков уже существуют, так что на данном этапе можно использовать одну из них как черный ящик, не вникая глубоко в принцип её работы.
Однако, глубокие нейронные сети требовательны к большим объемам данных для сходимости обучения. И зачастую в нашей частной задаче недостаточно данных для того, чтобы хорошо натренировать все слои нейросети. Transfer Learning решает эту проблему.
Transfer Learning для классификации изображений
Нейронные сети, которые используются для классификации, как правило, содержат N выходных нейронов в последнем слое, где N — это количество классов. Такой выходной вектор трактуется как набор вероятностей принадлежности к классу. В нашей задаче распознавания изображений еды количество классов может отличаться от того, которое было в исходном датасете. В таком случае нам придётся полностью выкинуть этот последний слой и поставить новый, с нужным количеством выходных нейронов
Зачастую в конце классификационных сетей используется полносвязный слой. Так как мы заменили этот слой, использовать предобученные веса для него уже не получится. Придется тренировать его с нуля, инициализировав его веса случайными значениями. Веса для всех остальных слоев мы загружаем из предобученного снэпшота.
Существуют различные стратегии дообучения модели. Мы воспользуемся следующей: будем тренировать всю сеть из конца в конец (end-to-end), а предобученные веса не будем фиксировать, чтобы дать им немного скорректироваться и подстроиться под наши данные. Такой процесс называется тонкой настройкой (fine-tuning).
Структурные компоненты
Для решения задачи нам понадобятся следующие компоненты:
В нашем примере компоненты (1), (2) и (3) я буду брать из собственного репозитория, который содержит максимально легковесный код — при желании с ним можно легко разобраться. Наш пример будет реализован на популярном фреймворке TensorFlow. Предобученные веса (4), подходящие под выбранный фреймворк, можно найти, если они соответствуют одной из классических архитектур. В качестве датасета (5) для демонстрации я возьму Food-101.
Модель
В качестве модели воспользуемся классической нейросетью VGG (точнее, VGG19). Несмотря на некоторые недостатки, эта модель демонстрирует довольно высокое качество. Кроме того, она легко поддается анализу. На TensorFlow Slim описание модели выглядит достаточно компактно:
Веса для VGG19, обученные на ImageNet и совместимые с TensorFlow, скачаем с репозитория на GitHub из раздела Pre-trained Models.
Датасет
В качестве обучающей и валидационной выборки будем использовать публичный датасет Food-101, где собрано более 100 тысяч изображений еды, разбитых на 101 категорию.
Скачиваем и распаковываем датасет:
Пайплайн данных в нашем обучении устроен так, что из датасета нам понадобится распарсить следующее:
Все вспомогательные функции, ответственные за обработку данных, вынесены в отдельный файл data.py :
Обучение модели
Код обучения модели состоит из следующих шагов:
После запуска обучения можно посмотреть на его ход с помощью утилиты TensorBoard, которая поставляется в комплекте с TensorFlow и служит для визуализации различных метрик и других параметров.
В конце обучения в TensorBoard мы наблюдаем практически идеальную картину: снижение Train loss и рост Validation Accuracy
Тестирование модели
Теперь протестируем нашу модель. Для этого:
Весь код, включая ресурсы для построения и запуска Docker контейнера со всеми нужными версиями библиотек, находятся в этом репозитории — на момент прочтения статьи код в репозитории может иметь обновления.
На воркшопе «Machine Learning и нейросети для разработчиков» я разберу и другие задачи машинного обучения, а студенты к концу интенсива сами представят свои проекты.
Трансферное обучение: почему deep learning стал доступнее
Что помогает стартапам использовать методы глубинного обучения в своих проектах?
Раньше глубинное обучение требовало огромных мощностей, денежных инвестиций и времени, поэтому было недоступно небольшим компаниям. В последние годы ситуация меняется: стартапы и даже энтузиасты-одиночки могут использовать методы глубинного обучения в своих проектах. Разработчик Калеб Кайзер делится своими наблюдениями о том, почему deep learning становится все доступнее.
Раньше для того, чтобы заняться глубинным обучением, вы должны были иметь доступ к большому очищенному набору данных и самостоятельно разработать и обучить эффективную модель. Значит, проекты без существенной поддержки извне были невозможны по умолчанию. Однако за последние пару лет всё изменилось. Движущая сила такого роста — трансферное обучение.
Что такое трансферное обучение?
Идея трансферного обучения строится на том, что знания, накопленные в модели, подготовленной для выполнения одной задачи — скажем, распознавания цветов на фотографии — могут быть перенесены на другую модель, чтобы помочь в построении прогнозов для другой, родственной задачи, например, для задачи выявления меланомы.
Существуют различные подходы к трансферному обучению, но один из них — тонкая настройка (finetuning) — находит особенно широкое применение.
При таком подходе команда берет предварительно обученную модель и удаляет или переучивает последние слои этой модели, чтобы сфокусироваться на новой, схожей задаче. Например, AI Dungeon — это текстовая приключенческая игра с открытым миром, которая стала очень популярной из-за того, насколько убедительны сюжеты, написанные с помощью искусственного интеллекта:
Примечательно, что AI Dungeon не была разработана исследовательской лабораторий Google, это проект одного человека, сделанный во время хакатона.
Ник Уолтон, создатель AI Dungeon, не построил ее с нуля, а с помощью новейшей NLP-модели — GPT-2 компании OpenAI — доработал ее тонкой настройкой и дал возможность писать свои тексты для приключений.
Причина, по которой это вообще работает, в том, что в нейросетях базовые слои фокусируются на простых, общих паттернах, тогда как последние слои фокусируются на более специфичных паттернах для задач классификации или регрессии. Профессор Стенфордского университета Эндрю Ын визуализирует слои и их относительные уровни специфичности, представляя модель распознавания образов:
Общее содержание базовых слоев, оказывается, часто хорошо перекладывается на другие задачи. Например, в случае AI Dungeon GPT-2 обладала современным пониманием разговорного английского языка, ей просто потребовалась небольшая перетренировка в заключительных слоях для хороших результатов в создании собственных приключенческих сюжетов.
С помощью этого процесса один разработчик может развернуть модель, которая за несколько дней достигнет современных уровней развития в новой области.
Небольшие наборы данных больше не помеха
Глубинное обучение, как правило, требует больших объемов размеченных данных, а во многих областях таких данных просто не существует. Трансферное обучение может решить эту проблему. Например, команда, связанная с Гарвардской медицинской школой, недавно развернула модель, которая может на основе рентгенограмм грудной клетки прогнозировать смертность в долгосрочной перспективе, в том числе не связанную с раком.
Несмотря на то, что у исследователей был набор данных, состоявший примерно из 50 000 размеченных изображений, они не могли тренировать собственную свёрточную нейросеть с нуля. Вместо этого они взяли подготовленную модель Inception-v4 (которая обучается на наборе данных, состоящем более чем из 14 миллионов изображений ImageNet) и использовали трансферное обучение и небольшие архитектурные модификации для адаптации модели к своему набору данных.
В результате их нейросеть научилась рассчитывать уровень риска по одному изображению грудной клетки пациента.
На обучение моделей теперь требуются минуты, а не дни
Обучение модели на огромном объеме данных требует не только приобретения этих данных, нужны также ресурсы и время.
Например, когда в Google разрабатывали свою state of the art модель классификации изображений Xception, были подготовлены две версии: одна на датасете ImageNet (14 миллионов изображений), а другая на наборе данных JFT (350 миллионов изображений).
Обучение на 60 графических процессорах NVIDIA K80 с различными оптимизациями заняло три дня для проведения одного эксперимента с ImageNet. Эксперимент с JFT занял больше месяца. Однако теперь, когда предварительно обученная модель Xception выпущена, команды могут провести тонкую настройку своих версий намного быстрее.
Например, команда из Университета штата Иллинойс и Аргоннской национальной лаборатории недавно подготовила модель для классификации изображений галактик.
Несмотря на то, что их набор данных составляет всего 35 000 размеченных изображений, они смогли настроить Xception всего за восемь минут с помощью графических процессоров NVIDIA.
Полученная модель способна классифицировать галактики с точностью 99,8% при сверхчеловеческой скорости.
Машинное обучение становится экосистемой
В программировании мы видим, как экосистемы «взрослеют» по довольно стандартным шаблонам. Появляется новый язык программирования с интересными возможностями, и его используют для определенных сценариев, исследовательских проектов и игр. Сегодня каждый, кто будет им пользоваться, должен собирать вспомогательные программы с нуля.
В итоге сообщество разрабатывает библиотеки и проекты, которые абстрагируются от общих утилит до тех пор, пока инструментарий не будет достаточно устойчив и работоспособен для использования. На этом этапе разработчики не думают об отправке HTTP-запросов или о подключении к базам данных, а сосредоточены исключительно на создании своего продукта.
Другими словами, большие компании создают свои модели, а разработчики используют их для создания продуктов. По мере того, как компании вроде OpenAI, Google, Facebook и других технологических гигантов выпускают мощные модели с открытым исходным кодом, инструменты в распоряжении разработчиков машинного обучения становятся все более мощными и стабильными.
Вместо того чтобы тратить время на построение модели с нуля при помощи PyTorch или TensorFlow, датасаентисты используют модели с открытым исходным кодом и трансферное обучение для создания продуктов, а значит, придет новое поколение программного обеспечения на основе программного обучения.
Теперь разработчикам машинного обучения остается думать только о том, как бы запустить эти модели в производство.
Transfer Learning и PyTorch в Python
Трансферное обучение (Transfer Learning) в Python – это мощный метод обучения глубоких нейронных сетей, который позволяет использовать знания, полученные об одной проблеме глубокого обучения, и применять их к другой, но со схожей задачей.
Использование трансферного обучения может значительно ускорить развертывание разрабатываемого вами приложения, делая как обучение, так и внедрение вашей глубокой нейронной сети проще.
В этой статье мы рассмотрим теорию, лежащую в основе трансферного обучения, и посмотрим, как реализовать пример в сверточных нейронных сетях (CNN) в PyTorch.
Что такое PyTorch?
Pytorch – это библиотека, разработанная для Python, специализирующаяся на глубоком обучении и обработке естественного языка. PyTorch использует преимущества графических процессоров (GPU), чтобы реализовать глубокую нейронную сеть быстрее, чем обучение сети на ЦП.
PyTorch совместим с NumPy и позволяет преобразовывать массивы NumPy в тензоры и наоборот.
Определение необходимых терминов
Прежде чем мы пойдем дальше, давайте определим некоторые термины, относящиеся к трансферному обучению. Четкое понимание наших определений упростит понимание теории, лежащей в основе трансферного обучения, и реализацию экземпляра.
Что такое глубокое обучение?
Глубокое обучение – это подраздел машинного обучения, которое можно описать как просто действие, позволяющее компьютерам выполнять задачи, не будучи явно запрограммированными на это.
В системах глубокого обучения используются нейронные сети, которые представляют собой вычислительные структуры, смоделированные по образцу человеческого мозга.
Нейронные сети состоят из трех различных компонентов: входного слоя, скрытого или среднего уровня и выходного уровня.
На входном уровне просто обрабатываются данные, отправляемые в нейронную сеть, в то время как промежуточные и скрытые слои состоят из структуры, называемой узлом или нейроном.
Эти узлы представляют собой математические функции, которые каким-либо образом изменяют входную информацию и передают измененные данные на последний или выходной уровень. Простые нейронные сети могут различать простые шаблоны во входных данных путем корректировки предположений или параметров о том, как точки данных связаны друг с другом.
Глубокая нейронная сеть получила свое название от того факта, что она состоит из множества обычных нейронных сетей, соединенных вместе. Чем больше нейронных сетей связаны друг с другом, тем более сложные шаблоны может различать глубокая нейронная сеть и тем больше у нее возможностей. Существуют разные виды нейронных сетей, каждый из которых имеет свою специализацию.
Например, глубокие нейронные сети с долгосрочной краткосрочной памятью – это сети, которые очень хорошо работают при обработке чувствительных ко времени задач, где важен хронологический порядок данных, таких как текстовые или речевые данные.
Что такое сверточная нейронная сеть?
Эта статья будет посвящена сверточным нейронным сетям, типу нейронной сети, которая отлично справляется с манипулированием данными изображений.
Сверточные нейронные сети (CNN) – это особые типы нейронных сетей, способные создавать представления визуальных данных. Данные в CNN представлены в виде сетки, которая содержит значения, которые представляют, насколько ярким и какого цвета является каждый пиксель изображения.
CNN разбита на три различных компонента: сверточные слои, объединяющие слои и полносвязные слои.
Сверточный слой отвечает за создание представления изображения путем скалярного произведения двух матриц.
Первая матрица – это набор обучаемых параметров, называемых ядром. Другая матрица – это часть анализируемого изображения, которая будет иметь высоту, ширину и цветовые каналы. Сверточные слои – это то место, где в CNN происходит больше всего вычислений. Ядро перемещается по всей ширине и высоте изображения, в конечном итоге создавая представление всего изображения, которое является двухмерным, известное как карта активации.
Из-за огромного количества информации, содержащейся в сверточных слоях CNN, обучение сети может занять очень много времени. Функция позволяет уменьшить количество информации, содержащейся в сверточных слоях CNN, принимая вывод одного сверточного слоя и уменьшая его масштаб, чтобы упростить представление.
Слой объединения выполняет это, просматривая разные точки в выходных данных сети и «объединяя» соседние значения, получая одно значение, которое представляет все соседние значения. Другими словами, требуется сводная статистика значений в выбранном регионе.
Суммирование значений в области означает, что сеть может значительно уменьшить размер и сложность своего представления, сохраняя при этом релевантную информацию, которая позволит сети распознавать эту информацию и извлекать значимые шаблоны из изображения.
Существуют различные функции, которые можно использовать для суммирования значений региона, например, получение среднего значения по соседству или среднего пула. Также может быть взято средневзвешенное значение окрестности, равно как и норма L2 региона. Наиболее распространенным методом объединения является метод максимального объединения, при котором берется максимальное значение региона и используется для представления соседства.
Полностью связанный слой – это то место, где все нейроны связаны друг с другом, с подключениями между каждым предыдущим и последующим слоями в сети. Здесь анализируется информация, которая была извлечена сверточными слоями и объединена слоями, где изучаются закономерности в данных. Вычисления здесь выполняются посредством умножения матриц в сочетании с эффектом смещения.
В CNN также присутствует несколько нелинейностей. Учитывая, что изображения сами по себе являются нелинейными объектами, сеть должна иметь нелинейные компоненты, чтобы иметь возможность интерпретировать данные изображения. Нелинейные слои обычно вставляются в сеть сразу после сверточных слоев, так как это придает карте активации нелинейность.
Существует множество различных функций нелинейной активации, которые можно использовать для того, чтобы сеть могла правильно интерпретировать данные изображения. Самая популярная функция – это ReLu или выпрямленный линейный блок.
Функция ReLu превращает нелинейные входные данные в линейное представление путем сжатия реальных значений только до положительных значений выше 0. Другими словами, функция ReLu принимает любое значение выше нуля и возвращает его как есть, в то время как, если значение ниже нуля, оно возвращается как ноль.
Функция ReLu популярна из-за ее надежности и скорости, выполняя ее примерно в шесть раз быстрее, чем другие функции активации. Обратной стороной ReLu является то, что он может легко застрять при работе с большими градиентами, никогда не обновляя нейроны. Эту проблему можно решить, установив скорость обучения для функции.
Двумя другими популярными нелинейными функциями являются сигмоидальная функция и функция Tanh.
Сигмоидная функция работает, принимая реальные значения и сжимая их до диапазона от 0 до 1, хотя у нее есть проблемы с обработкой активаций, близких к крайним значениям градиента, поскольку значения становятся почти нулевыми.
Обучение и тестирование
Есть два разных этапа создания и реализации глубокой нейронной сети: обучение и тестирование.
На этапе обучения в сеть поступают данные, и она начинает изучать шаблоны, которые содержат данные, регулируя параметры сети, которые являются предположениями о том, как точки данных связаны друг с другом. Другими словами, на этапе обучения сеть «узнает» о том, какие данные были переданы.
На этапе тестирования оценивается то, что узнала сеть. Сети предоставляется новый набор данных, который она не видела раньше, а затем сеть просят применить свои предположения о паттернах, которые она усвоила, к новым данным. Оценивается точность модели, и обычно модель настраивается и переобучается, а затем повторно тестируется, пока архитектор не будет удовлетворен производительностью.
В случае трансферного обучения используемая сеть была предварительно обучена. Параметры сети уже настроены и сохранены, поэтому нет причин заново обучать всю сеть с нуля. Это означает, что сеть может быть немедленно использована для тестирования или только определенные уровни сети могут быть настроены и затем повторно обучены. Это значительно ускоряет развертывание глубокой нейронной сети.
Что такое трансферное обучение?
Идея трансферного обучения состоит в том, чтобы взять модель, обученную одной задаче, и применить ее ко второй, аналогичной задаче. Тот факт, что модель уже имеет некоторые или все данные для второй обученной задачи, означает, что она может быть реализована намного быстрее. Это позволяет быстро оценивать производительность и настраивать модель, обеспечивая более быстрое развертывание в целом.
Трансферное обучение становится все более популярным в области глубокого обучения благодаря огромному количеству вычислительных ресурсов и времени, необходимых для обучения моделей глубокого обучения в дополнение к большим и сложным наборам данных.
Основным ограничением трансферного обучения является то, что особенности модели, изученные во время первой задачи, являются общими, а не специфичными для первой. На практике это означает, что модели, обученные распознавать определенные типы изображений, могут быть повторно использованы для распознавания других изображений, если общие характеристики изображений аналогичны.
Теория трансферного обучения
Использование трансферного обучения имеет несколько важных концепций. Чтобы понять реализацию, нам нужно рассмотреть, как выглядит предварительно обученная модель и как ее можно настроить для ваших нужд.
Выбрать модель для трансферного обучения можно двумя способами. Можно создать модель с нуля для собственных нужд, сохранить параметры и структуру модели, а затем повторно использовать ее позже.
Второй способ реализовать трансферное обучение – просто взять уже существующую модель и повторно использовать ее, настраивая при этом ее параметры и гиперпараметры. В этом случае мы будем использовать предварительно обученную модель и модифицировать ее. После того, как вы решили, какой подход вы хотите использовать, выберите модель (если вы используете предварительно обученную модель).
Эти предварительно обученные модели доступны через API PyTorch, и после получения инструкций PyTorch загрузит их спецификации на ваш компьютер. Конкретная модель, которую мы собираемся использовать, – это ResNet34, часть серии Resnet.
Модель Resnet была разработана и обучена на наборе данных ImageNet, а также на наборе данных CIFAR-10. Таким образом, он оптимизирован для задач визуального распознавания и показал заметное улучшение по сравнению с серией VGG, поэтому мы будем его использовать.
Однако существуют и другие предварительно обученные модели, и вы можете поэкспериментировать с ними, чтобы увидеть, как они сравниваются.
Как объясняется в документации PyTorch по трансферному обучению, существует два основных способа использования: точная настройка или использование CNN в качестве средства извлечения фиксированных функций.
При тонкой настройке CNN вы используете параметры, которые имеет предварительно обученная сеть, вместо их случайной инициализации, а затем тренируетесь как обычно. Напротив, подход экстрактора признаков означает, что вы будете поддерживать все параметры CNN, за исключением тех, которые находятся на последних нескольких уровнях, которые будут инициализированы случайным образом и обучены как обычно.
Точная настройка модели важна, потому что, хотя модель была предварительно обучена другой (хотя, надеюсь, схожей) задаче. Плотно связанных параметров, с которыми поставляется предварительно обученная модель, вероятно, будет недостаточно, поэтому вы, вероятно, захотите переобучить последние несколько слоев сети.
Напротив, поскольку первые несколько слоев сети – это просто слои выделения признаков, и они будут работать аналогично с похожими изображениями, их можно оставить как есть. Следовательно, если набор данных небольшой и похожий, единственное обучение, которое необходимо выполнить, – это обучить нескольких последних слоев. Чем больше и сложнее будет набор данных, тем больше потребуется переобучения модели.
Помните, что трансферное обучение работает лучше всего, когда набор данных, который вы используете, меньше, чем исходная предварительно обученная модель, и похож на изображения, подаваемые в предварительно обученную модель.
Работа с моделями обучения передачи в Pytorch означает выбор слоев, которые нужно заморозить и разморозить. Замораживание модели означает указание PyTorch сохранить параметры в указанных вами слоях. Размораживание модели означает сообщение PyTorch о том, что вы хотите, чтобы указанные вами слои были доступны для обучения.
После того, как вы завершили обучение выбранных вами слоев предварительно обученной модели, вы, вероятно, захотите сохранить параметры для использования в будущем. Несмотря на то, что использование предварительно обученных моделей происходит быстрее, чем обучение модели с нуля, обучение по-прежнему требует времени, поэтому вы захотите скопировать лучшие параметры модели.
Классификация изображений
Мы готовы приступить к реализации трансферного обучения для набора данных. Мы рассмотрим как тонкую настройку ConvNet, так и использование сети в качестве средства извлечения фиксированных функций.
Предварительная обработка данных
Прежде всего, нам нужно выбрать набор данных для использования. Давайте выберем что-нибудь, на чем можно будет тренироваться с большим количеством действительно четких изображений. Набор данных Stanford Cats and Dogs – это очень часто используемый набор данных.
Обязательно разделите набор данных на два набора одинакового размера: «train» и «val».
Вы можете сделать это в любом случае, вручную переместив файлы или написав функцию для его обработки. Вы также можете ограничить набор данных меньшим размером, так как он содержит почти 12000 изображений в каждой категории, и это займет много времени для обучения. Вы можете сократить это число примерно до 5000 в каждой категории, при этом 1000 зарезервированы для проверки. Однако количество изображений, которые вы хотите использовать для обучения, зависит от вас.
Вот один из способов подготовить данные к использованию:
Загрузка данных
После того, как мы выбрали и подготовили данные, мы можем начать с импорта всех необходимых библиотек. Нам понадобятся многие пакеты Torch, такие как нейронная сеть nn, оптимизаторы и загрузчики данных. Нам также понадобится matplotlib для визуализации некоторых наших обучающих примеров.
Нам нужен numpy для обработки создания массивов данных, а также несколько других разных модулей:
Для начала нам нужно загрузить наши обучающие данные и подготовить их для использования нашей нейронной сетью. Для этой цели мы собираемся использовать преобразования Pytorch. Нам нужно убедиться, что изображения в обучающем наборе и наборе проверки имеют одинаковый размер, поэтому мы будем использовать преобразования.
Мы также будем немного увеличивать данные, пытаясь улучшить производительность нашей модели, заставляя ее узнавать об изображениях под разными углами и обрезками, поэтому мы будем произвольно обрезать и вращать изображения.
Далее мы сделаем тензоры из изображений, поскольку PyTorch работает с ними. Наконец, мы нормализуем изображения, что поможет сети работать со значениями, которые могут иметь широкий диапазон различных значений.
Затем мы составляем все выбранные нами преобразования. Обратите внимание, что преобразования проверки не имеют никакого переворачивания или вращения, поскольку они не являются частью нашего обучающего набора, поэтому сеть не узнает о них:
Теперь мы установим каталог для наших данных и будем использовать функцию PyTorch ImageFolder для создания наборов данных:
Теперь, когда мы выбрали нужные папки изображений, нам нужно использовать DataLoaders для создания повторяемых объектов, с которыми мы будем работать. Мы сообщаем ему, какие наборы данных хотим использовать, задаем размер пакета и перемешиваем данные.
Нам нужно будет сохранить некоторую информацию о нашем наборе данных, в частности размер набора данных и имена классов. Нам также необходимо указать, с каким устройством мы работаем, с процессором или графическим процессором. В следующей настройке будет использоваться графический процессор, если он доступен, в противном случае будет использоваться процессор:
Теперь давайте попробуем визуализировать некоторые из наших изображений с помощью функции. Мы возьмем ввод, создадим из него массив Numpy и транспонируем его. Затем мы нормализуем ввод, используя среднее значение и стандартное отклонение. Наконец, мы обрежем значения от 0 до 1, чтобы не было большого диапазона возможных значений массива, а затем покажем изображение:
Теперь давайте воспользуемся этой функцией и фактически визуализируем некоторые данные. Мы собираемся получить входные данные и имя классов из DataLoader и сохранить их для дальнейшего использования. Затем мы создадим сетку для отображения входов и их отображения:
Настройка предварительно обученной модели
Теперь нам нужно настроить предварительно обученную модель, которую мы хотим использовать для трансферного обучения. В этом случае мы собираемся использовать модель как есть и просто сбросить последний полностью связанный слой, снабдив его нашим количеством функций и классов.
При использовании предварительно обученных моделей PyTorch по умолчанию устанавливает модель для разморозки (с корректировкой параметров). Итак, мы будем обучать всю модель:
Если это все еще кажется неясным, может помочь визуализация композиции модели.
Вот что это вернет:
По сути, мы собираемся изменить выходы последней полностью связанной части всего на два класса и скорректировать параметры для всех остальных слоев.
Теперь нам нужно отправить нашу модель на обучающее устройство. Нам также нужно выбрать критерий потерь и оптимизатор, который мы хотим использовать с моделью. CrossEntropyLoss и оптимизатор SGD – хороший выбор, хотя есть и многие другие.
Мы также выберем планировщик скорости обучения, который снижает скорость обучения оптимизатора сверхурочно и помогает предотвратить несовпадение результатов из-за большой скорости обучения.
Теперь нам просто нужно определить функции, которые будут обучать модель и визуализировать прогнозы.
Начнем с обучающей функции. Он будет учитывать выбранную нами модель, а также оптимизатор, критерий и планировщик. Мы также укажем количество эпох обучения по умолчанию.
У каждой эпохи будет этап обучения и проверки. Для начала мы устанавливаем начальные лучшие параметры модели предварительно обученного режима, используя state_dict.
Мы также будем отслеживать точность модели на этапе обучения, и если мы перейдем к этапу проверки и точность улучшится, мы сохраним текущие параметры как лучшие:
Наши распечатки тренировок должны выглядеть примерно так:
Визуализация
Теперь мы создадим функцию, которая позволит нам увидеть прогнозы, сделанные нашей моделью.
Теперь мы можем связать все вместе. Обучим модель на наших изображениях и покажем прогнозы:
Это обучение, вероятно, займет у вас много времени, если вы используете процессор, а не графический процессор.
Экстрактор фиксированных функций
Из-за длительного времени обучения многие люди предпочитают просто использовать предварительно обученную модель в качестве экстрактора фиксированных признаков и тренировать только последний слой. Это значительно сокращает время обучения. Для этого вам нужно заменить модель, которую мы построили. Будет ссылка на репозиторий GitHub для обеих версий реализации ResNet.
Замените раздел, в котором определена предварительно обученная модель, версией, которая фиксирует параметры и не содержит наших вычислений градиента или обратного распространения.
Он выглядит очень похоже на предыдущий, за исключением того, что мы указываем, что градиенты не нуждаются в вычислении:
Что, если бы мы хотели выборочно разморозить слои и вычислить градиенты только для нескольких выбранных слоев. Это возможно? Да.
Давайте снова распечатаем дочерние элементы модели, чтобы вспомнить, какие слои и компоненты у нее есть:
Теперь, когда мы знаем, что это за слои, мы можем разморозить те, которые захотим, например, только слои 3 и 4:
Конечно, нам также необходимо обновить оптимизатор, чтобы отразить тот факт, что мы хотим оптимизировать только определенные слои.
Итак, теперь вы знаете, что можете настроить всю сеть, только последний уровень или что-то среднее.
Заключение
Мы реализовали трансферное обучение в PyTorch. Было бы неплохо сравнить реализацию настроенной сети с использованием экстрактора фиксированных функций, чтобы увидеть, как отличается производительность.
Также рекомендуется поэкспериментировать с замораживанием и размораживанием определенных слоев, поскольку это позволяет вам лучше понять, как вы можете настроить модель в соответствии со своими потребностями.