Я какое-то время отсутствовал в FSharp. Мероприятие Адвент календарь, организованное Сергеем Тихоном, показалось подходящим временем, чтобы вернуться на сцену. Вернуться к .Net и FSharp всегда сложно. Платформы, фреймворки, инструменты - все изменилось, появились новые способы делать старые вещи и все к лучшему.

Я решил опробовать .Net Core, поскольку за ним, похоже, будущее. Моя предыдущая установка FSharp на Mac выполнялась под управлением Mono, поэтому на этот раз я создал контейнер докеров Linux и установил в него .Net Core. Проблема с .Net - это количество выбора, которое у вас есть. Так много платформ на выбор, со всеми плюсами и минусами. Это резко контрастирует с другим языком - голангом, которым я сейчас часто пользуюсь. Начать работу с Golang довольно просто и быстро.

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

GA подходит для проблем с большим пространством поиска, поэтому я использовал его для оптимизации гиперпараметров глубокой нейронной сети (DNN). Обычно реализация DNN выполняется на Python с Keras в качестве библиотеки DNN и с бэкэндом TensorFlow, выполняющим вычисления нейронного графа. Эта установка широко используется, но мне неудобно полагаться на Python для выполнения любого сложного кода, кроме простого скрипта. В машинном обучении, где результаты могут занять часы или дни, ошибка времени выполнения в конце эксперимента, которая могла быть обнаружена во время компиляции, разрушая вашу неделю, - это не тот риск, на который я бы пошел. Здесь пригодится строгая статическая типизация Fsharp. Также светит его лаконичность без ущерба для читабельности.

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

Эти сверточные слои объединяются в другие слои как способ субдискретизации. На каждом этапе объединения будет окно объединения, которое снова необходимо определить. Затем следует выбрать размер плотных слоев, который снова необходимо определить. Выпадение - еще один гиперпараметр, который необходимо настроить, наряду с размером пакета и количеством эпох. Отбрасывание относится к количеству соединений, которые необходимо удалить со слоя, размер пакета относится к размеру входных данных, используемых до того, как обратное распространение обновит веса сети. Счетчик эпох относится к количеству итераций обучения, которые необходимо выполнить перед остановкой эксперимента.

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

Следовательно, агент можно смоделировать, как показано ниже.

Затем гиперпараметры DNN отображаются в хромосому (терминология GA). Хромосома - это массив значений с плавающей запятой (от 0,0 до 1,0), которые будут подвергаться операторам GA. Здесь они будут случайным образом мутированы и сращены с другими успешными хромосомами на протяжении поколений.

Типичный GA будет включать следующие шаги:

В каждом поколении оценивается популяция агентов.

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

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

experiment_runner.sh - это простой файл bash для запуска сценария Python и фильтрации нежелательных битов из вывода Keras. Обычно это выглядит так, как показано ниже.

Это дает результат, аналогичный приведенному ниже:

Выходной код синтаксического анализа должен извлекать значения val_loss и / или val_acc, чтобы сформулировать производительность эксперимента.

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

В сценарии Python аргументы командной строки принимаются как таковые:

С этими переменными можно создать график Tensorflow с использованием слоев Keras, как показано ниже:

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