Перейти к содержимому

Как сохранить обученную нейронную сеть python

  • автор:

Использование обученной модели нейронной сети

Вопросы такие:
Как использовать обученную Tensorflow RNN в GoogleCoLab на локальной машине?
Нужно скачать с CoLab файл с весами или какой-то другой, или их все?
И потом как использовать?
Разместить в корне, и можно ли импортить необходимые методы?
Или нужно сохранить модель в формат .h5 и после использовать?

Например создать простой prosto.py в котором:

И как в таком случае подать t в обученную модель?
Нужен ли для этого исходник модели?

Знающие, помогите пожалуйста!

Отслеживать
Galo Gramma
задан 7 ноя 2019 в 17:23
Galo Gramma Galo Gramma
135 1 1 серебряный знак 9 9 бронзовых знаков

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

Существуют методы save() и load() для сохранения модели и последующей загрузки где хотите. Для использования существует метод predict()

Отслеживать
ответ дан 8 ноя 2019 в 18:03
376 2 2 серебряных знака 13 13 бронзовых знаков

При применении метода save() сохраняются чекпоинты в виде 4 файлов — модель, веса и указания что где. Вопрос в том.. Как использовать эти файлы на локальной машине?

9 ноя 2019 в 16:13

Архитектура модели — состоит из двух рекуррентных нейронных сетей: кодер RNN просто потребляет входные слова источника без каких-либо предсказаний; Декодер, с другой стороны, обрабатывает целевое предложение, предсказывая следующие слова.

9 ноя 2019 в 16:50

@GaloGramma метод load() запускаешь из того же репозитория, где сохранил. Тоесть он загружает сразу весь репозиторий с твоей моделью. Далее с помощью метода predict() используешь модель для предсказания/генерации. Я так полагаю, у вас что-то вроде GAN. Тогда после обучения стоит сохранять именно генератор, т.к. дискриминатор нужен лишь на период обучения)

11 ноя 2019 в 19:16

Большое спасибо за ответ, но пока что не до конца понятен принцип. Очень прошу Вас разъяснить более подробно! Я пока не сохранял модель в репозиторий. На данном этапе я лишь обучил модель на ноутбуке Google CoLab используя простой дата сет и получил сохраненные файлы чекпоинтов. Скачал их с CoLab на лок маш и не понимаю, что с ними дальше делать. Нужно ли восстанавливать исходную модель на лок маш? Нужен ли .HDF5 для использования модели на лок маш? Модель состоит из двух рекурентных сеток — (1)Encoder, (2)Decoder.

Сохранение нейронной сети в JSON и другое: обучаем нейронную сеть на JavaScript

Обложка поста Сохранение нейронной сети в JSON и другое: обучаем нейронную сеть на JavaScript

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

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

Сегодня нейронные сети популярны как никогда. Свои решения в этой области представляют такие компании, как Google, Microsoft и многие другие. Но существуют и библиотеки с открытым кодом, написанные энтузиастами на самых разных языках. Сегодня tproger расскажет вам об одной из них — это библиотека brain, написанная на JavaScript.

Использование

Самый простой пример применения — обучение на функции XOR:

var net = new brain.NeuralNetwork(); net.train([, , , ]); var output = net.run([1, 0]); // [0.987] 

А еще есть очень классная визуализация того, как нейронная сеть обучается XOR, OR и другим логическим функциям.

Чтобы установить библиотеку, можно использовать, например, npm:

npm install brain

Можно также скачать последнюю версию brain.js. Тренировать сеть можно даже оффлайн, а затем уже натренированную загрузить на сайт.

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

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

var net = new brain.NeuralNetwork(); net.train([, output: < black: 1 >>, , output: < white: 1 >>, , output: < white: 1 >>]); var output = net.run(< r: 1, g: 0.4, b: 0 >); //

Функция train() умеет принимать в качестве второго аргумента массив нескольких параметров:

net.train(data, < errorThresh: 0.005, // порог ошибок, которого нужно достичь iterations: 20000, // максимальное число итераций обучения log: true, // нужен ли периодический console.log() logPeriod: 10, // число итераций между логированиями learningRate: 0.3 // степень обучения >) 

Обучаться сеть будет до тех пор, пока не будет достигнут заданный порог ошибок (по умолчанию задается 0.005) или не будет совершено заданное число итераций (20000).

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

learningRate — параметр, определяющий, как быстро натренируется нейронная сеть. Задается он числом от 0 до 1. Чем меньше параметр, тем дольше сеть будет обучаться. С увеличением числа скорость будет расти, но вместе с этим растет вероятность более плохого качества обучения. По умолчанию это число составляет 0.3.

Результатом обучения будет массив output с информацией о том, как прошло обучение.

Если обучение закончилось ошибкой, то параметр error будет близок к порогу ошибки. Причиной этому может стать излишняя «зашумленность» данных, недостаток нейронов или недостаточное число итераций. Если даже после 20000 итераций ошибка составила около 0.4, это может означать, что сеть плохо воспринимает предоставляемые вами данные.

Обученную сеть можно хранить в формате JSON:

var json = net.toJSON(); net.fromJSON(json); 

Также можно данных сохранить в функцию:

var run = net.toFunction(); var output = run(< r: 1, g: 0.4, b: 0 >); console.log(run.toString()); // это нужно скопировать и вставить в нужное место. Подключать brain.js не требуется 

NeuralNetwork() принимает ассоциативный массив параметров:

var net = new brain.NeuralNetwork(< hiddenLayers: [4], learningRate: 0.6 // общая степень обученности, полезна при обучении в несколько потоков >); 

Первый параметр — общее количество скрытых слоев и размер каждого слоя. Например, если нужно два скрытых слоя — один с 3 нодами и второй с 4, то параметр будет таким:

hiddenLayers: [3, 4]

По умолчанию brain использует один слой, пропорциональный размеру входного массива.

Кстати, сеть может использовать WriteStream. Ее можно тренировать, используя pipe() , чтобы отправлять данные в сеть.

Чтобы тренировать сеть в потоке, сначала нужно поток создать вызовом метода net.createTrainStream() , принимающего следующие параметры:

  • floodCallback() — функция, которая будет вызываться на каждой итерации обучения;
  • doneTrainingCallback(info) — функция, которая выполнится после завершения обучения. Параметр info будет содержать ассоциативный массив информации о том, как прошло обучение:

Также можно использовать Transform, чтобы привести данные к корректному формату или чтобы на лету нормализовывать данные.

Рецепт обучения нейросетей

Несколько недель назад я опубликовал твит на тему «частые ошибки с нейросетями», перечислив несколько общих ошибок принадлежащих к обучению нейронных сетей. Твит получил несколько больше взаимодействий чем я ожидал (включая целый вебинар). Действительно, многие заметили большой разрыв между тем «вот как работает слой свертки» и «наша сверточная сеть достигает результатов произведения искусства».

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

1) Нейронные сети это дырявая абстракция

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

>>> your_data = # подставьте свой датасет здесь >>> model = SuperCrossValidator(SuperDuper.fit, your_data, ResNet50, SGDOptimizer) # покорите мир здесь

Эти библиотеки и примеры активируют часть нашего мозга которая привычна к стандартным программам — место где чистые API и абстракции часто достижимы. Например, библиотека requests:

>>> r = requests.get('https://api.github.com/user', auth=('user', 'pass')) >>> r.status_code 200

Круто! Смелый разработчик взял на себя бремя понимание строк запросов, URL, GET / POST запросов, HTTP соединений и т.д., и во многом скрыл сложность за несколькими строками кода. Это то, с чем мы знакомы и ожидаем. К сожалению, нейронные сети не похожи на это. Они не «готовая» технология, когда вы немного отклонились от обучения классификатора ImageNet. Я пытался указать на это в своей публикации «Да вы должны понимать метод обратного распространения ошибки» («Yes you should understand backprop»), выбрав метод обратного распространения ошибки и назвав его «дырявой абстракцией», но ситуация, к сожалению, гораздо сложнее. «Обратное распространение ошибки» + «Стохастический градиентный спуск» не делает вашу нейронную сеть магически работающей. Пакетная нормализация не заставляет ее магически сходиться быстрее. Рекуррентные нейронные сети не позволяют магически «вставить» текст. И только потому, что вы можете сформулировать вашу проблему в форме «обучение с подкреплением» не означает, что вы должны это делать. Если вы настаиваете на использовании технологии, не зная как она работает, вы, вероятно, потерпите неудачу. Что подводит меня к…

2) Обучение нейронных сетей ломается молча

Когда вы неправильно написали или настроили код вы часто получаете определенное исключение. Вы передали целое число там где ожидается строка. Функция ожидает только 3 аргумента. Этот импорт неудачный. Тот ключ не существует. Количество элементов в двух списках не ровен. В довесок, часто возможно написать юнит-тесты для определенного функционала.

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

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

Рецепт

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

1. Cтаньте едиными c данными

Первый шаг к обучению нейронных сетей — это вообще не касаться кода нейронной сети, а взамен начать с тщательной проверки ваших данных. Этот шаг критический. Я люблю тратить много времени (измеряется в часах), проверяя тысячи примеров, понимая их распределение и ища закономерности. К счастью, ваш мозг хорошо с этим справляется. Однажды я обнаружил, что данные содержат примеры которые повторяются. В другой раз я обнаружил поврежденные изображения / разметку. Я ищу дисбаланс данных и смещения. Обычно я также обращаю внимание на свой собственный процесс классификации данных, который намекает на виды архитектур которые мы со временем изучим. В качестве примера — достаточно локальных особенностей, или нам нужен глобальный контекст? Сколько существует вариаций и какую форму они принимают? Какая вариация ошибочная и может быть предварительно обработана? Имеет ли значение пространственное расположение или мы хотим его усреднить (с помощью операции average pool)? Насколько важны детали и насколько сильно мы можем позволить себе уменьшить размер изображений? Насколько зашумленная разметка?

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

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

2. Настройте сквозной скелет обучения / оценки + получите простой базис (базовую модель)

Теперь, когда мы поняли наши данные, можем ли мы добраться до нашей чрезвычайно крупномасштабной ASPP FPN ResNet и начать обучение великолепных моделей? Точно нет. Это путь к страданиям. Наш следующий шаг — создать полный скелет обучение + оценка и завоевать доверие к его правильности путем серии экспериментов. На этом этапе лучше выбрать какую-то простую модель, которую невозможно как-то испортить — например линейный классификатор или очень крошечную сверточную сеть. Мы хотим обучать сеть, визуализировать потери, любые другие показатели (например, точность), моделировать прогнозы и проводить ряд экспериментов по отключению частей сети (при этом выдвигать гипотезы как это повлияет на результаты) на всем пути.

Советы и подсказки на этом этапе:

  • зафиксируйте случайное начальное значение. Всегда используйте фиксированное случайное начальное значение, чтобы гарантировать аналогичный результат при повторном запуске. Это устраняет фактор вариативности и поддержит вашу уверенность.
  • упрощайте. Не забудьте отключить любую ненужную вычурность. В качестве примера, на этом этапе выключите любую аугментацию данных. Аугментация данных — это стратегия регуляризации, которую мы можем включить позже, но пока это просто еще одна возможность внести какую-то глупую ошибку.
  • добавьте значащие цифры в вашей оценки. При построении графика тестовых потерь проведите оценку по всему (большому) набору тестов. Не просто складывайте тестовые потери по партиям, а затем полагайтесь на их сглаживания в Tensorboard. Мы преследуем правильность и серьезно настроены уделить время для сохранения уверенности.
  • проверяйте потери в начале. Убедитесь, что показатель потери начинается с правильного значения. Например, если вы правильно инициализирует свой конечный слой, то у вас должно получиться -log(1 / n_classes) для функции softmax при инициализации. Те же значения по умолчанию можно получить для регрессии L2, потерь Губера и тому подобное.
  • инициализируйте верно. Правильно инициализируйте веса конечного слоя. Например, если вы регрессируете некоторые значения, которые имеют среднее значение 50, тогда инициализируйте окончательное смещение к 50. Если у вас несбалансированный набор данных с соотношением 1:10, установите смещение на своих логитах так, чтобы ваша сеть давала предсказания 0.1 при инициализации. Правильная их установка ускорит сходимость и устранит кривые потерь в виде «хоккейной клюшки», где в первые несколько итераций ваша сеть в основном лишь изучает смещения.
  • человеческий базис. Отслеживайте и другие показатели, кроме потерь, которые можно интерпретировать и проверить человеком (например, точность). По возможности оценивайте собственную (человеческую) точность и сравнивайте с ней. Кроме того, дважды аннотируйте тестовые данные и для каждого примера рассмотрите одну аннотацию как предсказания, а вторую как основную правду.
  • независимый от входных значений базис. Обучайте независимый от входных значений базис (например, простой является установка всех входных значений на ноль). Это должно работать хуже, чем тогда, когда вы фактически подключаете свои данные, не обнуляя их. Действительно так? Действительно ваша модель вообще учится извлекать любую информацию из входных данных?
  • переучивайте на одной партии. Делайте переобучение на одной партии лишь несколькими примерами (например, только двумя). Для этого мы увеличиваем объем нашей модели (например, добавляем слои или фильтры) и проверяем, что мы можем достичь самых низких достижимых потерь (например, нулевых). Мне также нравится визуализировать на одном и том же графике как размеченную информацию, так и прогноз, чтобы убедиться, что они идеально выравниваются, как только мы достигнем минимальных потерь. Если этого не произошло, где-то есть ошибка, и мы не можем перейти к следующему этапу.
  • проверяйте уменьшения потерь на тренировочной выборке. Думаю, ваш набор данных будет не очень объемным, так как вы работаете с игрушечной моделью. Попробуйте немного увеличить его объем. Значение потерь на тренировочной выборке снизились как следует?
  • визуализируйте непосредственно перед входом нейросети. Однозначно правильное место для визуализации ваших данных находится непосредственно перед вашим y_hat = model (x) (или sess.run в Tensorflow). То есть — вы должны визуализировать именно то, что попадает в вашу сеть, декодируя этот необработанный тензор данных и меток в виде какой-то визуализации. Это единственный «источник истины». Я не могу сосчитать, сколько раз это меня спасало и проявляло проблемы с предварительной обработкой и аугментацией данных.
  • визуализируйте динамику прогнозов. Мне нравится визуализировать прогнозы моделей на фиксированной тестовой партии во время обучения. «Динамика» движения этих прогнозов даст вам невероятно хорошую интуицию о том, как прогрессирует обучение. В основном можно почувствовать, как сеть «борется» за размещение ваших данных, если она как-то колеблется, показывая нестабильность. Очень низкая или очень высокая скорость обучения также легко различимы по величине дрожи.
  • используйте метод обратного распространения ошибки для отслеживания зависимостей. Ваш код для глубокого обучения часто может содержать сложные, векторизованные и трансляционные операции. Достаточно распространенная ошибка, с которой я сталкивался несколько раз, заключается в том, что люди достигают этого неправильно (например, они используют view , а не transpose / permute ) и нечаянно смешивают информацию в измерении размера пакета. Удручает тот факт, что ваша сеть, как правило, все равно способна хорошо учиться, потому что она научится игнорировать данные из других примеров. Одним из способов налаживания этой (и других связанных с этим проблем) является установление функции потери как чего-то тривиального, такого как сумма всех выходов примера i, запуск обратного прохода до входного сигнала и обеспечения получения ненулевого градиента только на i-м входе. Ту же стратегию можно использовать, чтобы убедиться, что ваша авторегресивная модель в момент времени t зависит только от 1..t-1. В общем, градиенты дают вам информацию о том, что и от чего зависит в вашей сети, это может быть полезно для отладки.
  • обобщайте частный случай. Это больше похоже на совет обобщать код, но я часто видел, как люди делают ошибки, когда откусывают больше, чем могут жевать, стараясь писать относительно общую функциональность с нуля. Мне нравится писать очень конкретную функцию для того, что я делаю сейчас, заставить это работать, а потом обобщить ее позже, убедившись, что я получу тот же результат. Часто это касается векторизации кода, где я почти всегда выписываю полностью циклическую версию, а уже потом превращаю ее в векторизованный код по одному циклу.
3. Переобучайте

На этом этапе мы должны хорошо понимать набор данных, и мы имеем полный конвейер обучение + оценки. Для любой данной модели мы можем (воспроизводимо) вычислить метрику, которой мы доверяем. Мы также вооруженны результатами нашего независимого от входных данных базиса, результатами нескольких простых базисов (нам лучше победить именно их), и мы имеем приблизительное ощущение производительности человека (мы надеемся достичь этого уровня). Текущий этап направлен на итерации в направлении хорошей модели.

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

Несколько советов и подсказок на этом этапе:

  • подбор модели. Чтобы достичь хороших значений потерь обучающей выборки, вы должны выбрать соответствующую архитектуру данных. Когда дело доходит до ее выбора, мой первый совет: Не будьте героем. Я видел много людей, которые стремятся сойти с ума в креативности подбора лего-блоков из набора инструментов нейронных сетей в процессе создания различных экзотических архитектур, которые имеют смысл только для них. На первых этапах проекта всеми силами сопротивляйтесь этому искушению. Я всегда советую людям просто найти наиболее похожую научную работу и скопировать ее простейшую архитектуру, которая обеспечивает хорошие показатели. Например, если вы классифицируете изображения, не будьте героем, а просто скопируйте ResNet-50 для первого запуска. Вы сможете делать что-то более специфическое позже и победить этот пункт.
  • Adam (метод адаптивной оценки моментов) безопасен. На ранних стадиях установления базиса мне нравится использовать Adam со скоростью обучения 3e-4 . По моему опыту, Adam гораздо лояльнее к гиперпараметрам, включая плохую скорость обучения. Для сверточных нейросетей хорошо настроенный метод стохастического градиента (SGD) почти всегда немного превосходит Adam, но область оптимальной скорости обучения гораздо более узкая и зависит от задачи. (Примечание. Если вы используете рекуррентные нейросети и связанные с ними модели обработки последовательностей, то чаще используют Adam. Опять же, на начальном этапе своего проекта не будьте героем и соблюдайте самые популярные статьи.)
  • усложняйте только по одному. Если у вас есть несколько сигналов для подключения к вашему классификатору, я бы посоветовал вам присоединить их один за другим и каждый раз убеждаться, что вы получаете повышение производительности, которое вы ожидали. Не бросайте ведро помоев на свою модель в самом начале. Есть и другие способы наращивания сложности — например, вы можете попробовать подключить сначала изображения поменьше, а позже увеличить их и т.д.
  • не доверяйте коэффициенту уменьшения скорости обучения по умолчанию. Если вы переделываете код с какой-то другой задачи, всегда будьте очень осторожны со снижением скорости обучения. Вы не только хотели бы использовать различные графики снижения скорости обучения для различных проблем, но — что еще хуже — в типовой реализации снижение будет базироваться на текущем номере эпохи, который может широко варьироваться просто в зависимости от размера вашего набора данных. Например, ImageNet замедлится в 10 раз на 30-й эпохе. Если вы не обучаетесь с ImageNet (имеется в виду размер датасета), вы, почти наверняка, этого не хотите. Если вы не будете осторожны, ваш код может тайком сводить вашу скорость обучения к нулю слишком рано, не позволяя вашей модели сходиться. В своей работе я всегда полностью выключаю уровень снижения скорости обучения (использую постоянную скорость обучения) и настраиваю его в самом конце.
4. Регуляризируйте

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

  • получите больше данных. Во-первых, безусловно лучшим способом регуляризирования модели в любом практической среде является добавление большего количества реальных учебных данных. Очень распространенной ошибкой является проведение многих инженерных циклов, пытаясь выжать сок из небольшого набора данных, когда вместо этого можно было собирать больше данных. Насколько мне известно, добавление дополнительных данных является едва ли не единственным гарантированным способом монотонно улучшать производительность хорошо настроенной нейронной сети почти неограниченно долго. Остальные — это ансамбли нейросетей (если вы можете себе позволить), но это ограничивается ~ 5-ю моделями.
  • аугментация данных. Следующим лучшим способом после реальных данных является полу фальшивые данные — попробуйте более агрессивную аугментацию данных.
  • креативная аугментация. Если полу фальшивые данные не помогли, фейковые данные также могут что-то сделать. Люди находят творческие способы расширения наборов данных; Например, рандомизация доменов, использование моделирования, умные гибриды, такие как вставка (потенциально смоделированная) данных у сцены или даже GAN.
  • предварительно обучайте. Редко когда-нибудь вредит использовать предварительно обученную сеть, если вам позволяет ситуация, даже если у вас достаточно данных.
  • придерживайтесь контролируемого обучения (обучение с учителем). Не переоценивайте предварительное обучение без присмотра (без учителя). В отличие от того, что рассказывается в той заметке в блоге от 2008 года [не могу понять о каком сообщении тут идет речь], насколько мне известно, нет версий, которые показывают хорошие результаты на современных задачах компьютерного зрения (хотя NLP, кажется, вполне хорошо справляется вместе с BERT и компанией сегодня, вполне вероятно благодаря умышленному характеру текста и высшему соотношению сигнал / шум).
  • уменьшайте входную размерность. Удалите примеры, которые могут содержать ложный сигнал. Любой добавленный ложный ввод — это лишь очередная возможность переобучить (когда ваша нейросеть заучит пример), если ваш набор данных невелик. Подобным образом, если детали низкого уровня не имеют большого значения, попробуйте передавать изображение меньшего размера.
  • уменьшайте размер модели. Во многих случаях вы можете использовать ограничения информативности участка в сети, чтобы уменьшить ее размер. В качестве примера, раньше было модно использовать слои с полным соединением поверх основы из ImageNet, но с тех пор они были заменены простым средним объединением (average pooling), устраняя тонну параметров в процессе.
  • уменьшайте размер партии. Через нормализацию внутри нормы партии меньшие размеры партии несколько соответствуют сильной регуляризации. Это связано с тем, что эмпирическое среднее / стандартное распределение для партии является более приблизительной версией полного среднего / стандартное распределение, поэтому изменение масштаба и смещения «раскачивают» вашу партию больше.
  • отсеивайте. Добавьте отсеивания. Используйте dropout2d (пространственное отсеивания) для сверточных сетей. Используйте это умеренно / осторожно, поскольку, кажется, отсеивания нехорошо работает при нормализации партии.
  • уменьшение веса. Увеличьте коэффициент уменьшения веса (эффект забывания).
  • ранняя остановка. Останавливайте обучение на основе измеренных валидационных потерь, чтобы поймать свою модель именно тогда, когда она собирается переобучиться (заучить примеры, а не изучить общие особенности).
  • попробуйте модель побольше. Я вспоминаю это последним и только после ранней остановки, ведь раньше я несколько раз обнаруживал, что большие модели со временем, конечно, переобучаются гораздо сильнее, но их «остановленная» эффективность часто может быть намного лучше, чем у моделей меньшего размера.

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

5. Тюнингуйте

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

  • случайный поиск по сетке. Для одновременной настройки нескольких гиперпараметров может показаться соблазнительным использовать поиск по сетке, чтобы обеспечить охват всех настроек, но имейте в виду, что лучше вместо этого использовать случайный поиск. Интуитивно это связано с тем, что нейронные сети часто гораздо более чувствительны к одним параметрам, чем к другим. В общем, если параметр a важен, но изменение b не имеет эффекта, вы подбираете значение a более продуманно, чем в нескольких фиксированных точках несколько раз.
  • оптимизация гиперпараметров. Вокруг есть большое количество причудливых наборов инструментов для оптимизации байесовских гиперпараметров, и несколько моих друзей также сообщили об успехе с ними, но мой личный опыт состоит в том, что современный подход к изучению прекрасного и широкого пространства моделей и гиперпараметров заключается в использовании интерна :). Шучу.
6. Выжмите все соки

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

  • ансамбли. Ансамбли моделей — это почти гарантированный способ получить 2% точности на чем-либо. Если вы не можете позволить себе вычисления во время тестирования, посмотрите на перегонку своего ансамбля в сеть, используя темные знания.
  • оставьте ее тренироваться. Я часто видел людей, которые соблазняются прекратить обучение моделей, когда потеря валидации, кажется, выравнивается. По моему опыту, сети продолжают тренироваться не интуитивно долго. Однажды я случайно покинул тренировку модели во время зимних каникул, и когда вернулся в январе, я увидел результат SOTA (state of the art — «современный уровень»).

Вывод

Как только вы дойдете сюда, у вас будут все составляющие успеха: Вы глубоко понимаете технологию, набор данных и проблему, вы создали всю инфраструктуру обучения / оценки и достигли высокой уверенности в ее точности, вы исследовали все более сложные модели, получая улучшения производительности способами, которые вы предугадывали на каждом шагу. Теперь вы готовы прочитать много работ, попробовать большое количество экспериментов и получить свои результаты SOTA. Удачи!

  • neural networks
  • ai
  • нейросети
  • нейросеть
  • искусственный интеллект
  • сверточные сети
  • рекуррентная нейросеть
  • переобучение нейросети
  • статистика
  • Python
  • Машинное обучение
  • Искусственный интеллект
  • Data Engineering
  • TensorFlow

Способы сохранения и загрузки моделей в Keras

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

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

import os os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' import tensorflow as tf from tensorflow import keras from tensorflow.keras import layers from tensorflow.keras.datasets import mnist tf.random.set_seed(1) (x_train, y_train), (x_test, y_test) = mnist.load_data() x_train = x_train.reshape(-1, 784) / 255.0 x_test = x_test.reshape(-1, 784) / 255.0 y_train = keras.utils.to_categorical(y_train, 10) y_test = keras.utils.to_categorical(y_test, 10) model = keras.Sequential([ layers.Dense(128, activation='relu'), layers.Dense(10, activation='softmax') ]) model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['acc']) model.fit(x_train, y_train, epochs=5)
  • model.save() или tf.keras.models.save_model() – для записи модели на носитель;
  • keras.models.load_model() – для загрузки модели по указанному пути.
model.save('16_model') model_loaded = keras.models.load_model('16_model')

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

model_loaded.evaluate(x_test, y_test)
  • архитектура модели;
  • значения весовых коэффициентов модели;
  • информация о начальной настройки метода compile() (вид оптимизатора, функции потерь и метрик);
  • состояние оптимизатора в момент сохранения модели (для возможности продолжения обучения из текущего состояния).
model.save('16_model_2.h5') model.save('16_model_3', save_format='h5') model_loaded = keras.models.load_model('16_model_2.h5')

Разумеется, рекомендуется использовать новый формат данных при сохранении моделей.

Методы get_config() и from_config()

Остается вопрос, как более детально происходит сохранение и загрузка архитектуры модели? Что конкретно хранится на диске? Согласно документации: https://www.tensorflow.org/guide/keras/save_and_serialize формат SavedModel хранит имя класса, реализацию функцииcall(), потери, веса и значение конфигурации (если в модели реализован метод get_config). Так вот, при отсутствии явного описания конфигурации, реализация функции call() используется для воссоздания работы модели или слоя (если реконструируется отдельный слой). Чтобы все это было понятнее, давайте рассмотрим пример сохранения и загрузки пользовательского класса модели с полносвязными слоями:

class NeuralNetwork(tf.keras.Model): def __init__(self, units): super().__init__() self.units = units self.model_layers = [layers.Dense(n, activation='relu') for n in self.units] def call(self, inputs): x = inputs for layer in self.model_layers: x = layer(x) return x

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

model = NeuralNetwork([128, 10]) y = model.predict(tf.expand_dims(x_test[0], axis=0)) print(y)

И, если теперь выполнить сохранение этой модели:

model.save('16_model')

то в файле saved_model.pb будет храниться реализация метода call(), которая и будет определять структуру модели. Тоесть, послееезагрузки:

model_loaded = keras.models.load_model('16_model')

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

y = model_loaded.predict(tf.expand_dims(x_test[0], axis=0)) print(y)

На первый взгляд эта информация может показаться избыточной. Какая нам разница, как все это в деталях работает, главное, что мы можем сохранять и загружать модели?Однако, существуют ситуации, когда это имеет важное значение. И одну из них я сейчас продемонстрирую. Предположим, что мы бы хотели загрузить модель, но с некоторыми изменениями. Например, вместо функции активации ReLU использовать другую – linear. По идее, для этого можно описать еще один похожий класс модели NeuralNetworkLinear с измененной активационной функцией:

class NeuralNetworkLinear(tf.keras.Model): def __init__(self, units): super().__init__() self.units = units self.model_layers = [layers.Dense(n, activation='linear') for n in self.units] def call(self, inputs): x = inputs for layer in self.model_layers: x = layer(x) return x

А при загрузке указать, чтобы вместо прежнего класса NeuralNetwork был подставлен новый:

model_loaded = keras.models.load_model('16_model', custom_objects={"NeuralNetwork": NeuralNetworkLinear})

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

def get_config(self): return {'units': self.units} @classmethod def from_config(cls, config): return cls(**config)
  • Sequential.from_config(config);
  • Model.from_config(config).
config = model.get_config()
  • json_config = model.to_json() – конфигурация архитектуры в формате JSON;
  • new_model = keras.models.model_from_json(json_config) – загрузкаархитектуры модели из JSON-формата.

Методы get_weights(), set_weights() и save_weights(), load_weights()

  • get_weights() – получение коэффициентов модели / слоя;
  • set_weights() – установка коэффициентов модели / слоя;
  • save_weights() – запись коэффициентов модели / слоя на носитель;
  • set_weights() – загрузка коэффициентов модели / слоя с носителя.
model = NeuralNetwork([128, 10]) model2 = NeuralNetwork([128, 10])

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

y = model.predict(tf.expand_dims(x_test[0], axis=0)) print(y) y = model2.predict(tf.expand_dims(x_test[0], axis=0)) print(y)

А потом скопировать веса, допустим, из первой модели во вторую:

# считываем и записываем веса только после пропускания через модели входного сигнала # иначе возникнет ошибка из-за отсутствия начальной инициализации весов weights = model.get_weights() model2.set_weights(weights) y = model2.predict(tf.expand_dims(x_test[0], axis=0)) print(y)

Как видим, последний вывод для y совпадает по значениям с первой моделью. Это показывает корректность копирования данных. Похожие действия можно выполнять и на уровне отдельных слоев, так как они поддерживают те же самые методы get_weights() и set_weights(). Вторая пара методов save_weights() и load_weights() позволяет сохранять веса на диск, а затем, считывать их обратно в модель. Делается это очень простопутем вызова этих методов для модели или слоя:

model.save_weights('model_weights') model2.load_weights('model_weights')
  • model_weights.data-00000-of-00001 – значения весовых коэффициентов;
  • model_weights.index – индексный вспомогательный файл.
model.save_weights('model_weights.h5') model2.load_weights('model_weights.h5')

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *