В последнее время много говорят о нейронных сетях, их возможностях и перспективах. Появилось много подробных, интересных, полезных статей и книг по их созданию. Например, хорошие статьи для начинающих с последовательными объяснениями основ находятся по адресу https://habr.com/ru/post/312450/ , https://habr.com/ru/post/313216/. Мы несколько лет занимались созданием и обучением нейронных сетей для решения нашей конкретной задачи и хотим поделиться своим личным опытом.
По известному химическому составу стали найти критические (равновесные) температуры и описать кривые фазовых превращений при изотермическом распаде переохлаждённого аустенита, т.е. по нескольким числам (от 5 до 13 штук) найти 3 числа и в каком-то виде координаты 5 кривых.
Мы решили использовать нейронные сети, т.к. критические температуры и расположение и форма кривых зависят от химического состава стали, но выявить эту зависимость методом линейного регрессионного анализа [1-4] с удовлетворительной точностью не удавалось. Обычно эти данные (температуры и кривые в координатах «время-температура») получали экспериментально для каждого конкретного химического состава, что очень трудоёмко. Для выявления зависимости мы использовали сборник экспериментальных данных [5].
Так как на вход нейронной сети поступают числа, а на выходе будет одно или несколько чисел, данные нужно привести к каким-то числам и организовать удобный доступ к ним из программы.
Мы создали таблицу (базу данных), в поля которой занесли название марки стали (для определённости), процентное содержание каждого химического элемента (входные данные) и критические температуры (выходные данные). Для описания кривых мы взяли координаты точек, при последовательном соединении которых получалась кривая. Эти координаты мы записали в файл. Имена этих файлов тоже включили в таблицу. Таким образом, каждая строка таблицы содержала всю информацию об одном химическом составе в легкодоступном виде.
Возможно, уже существуют более или менее точные правила и алгоритмы, но мы их не знали и делали методом проб и ошибок.
Можно пробовать разные структуры и параметры сети и смотреть, что лучше. Начать можно с маленькой сети – двухслойной. Если после обучения результат недостаточно точный, то взять трёхслойную, увеличить количество нейронов в слоях, изменить параметры. Но это всё довольно трудоёмко, т.к. каждая проба – это новая сеть, обучаемая с нуля. Чем больше сеть, тем дольше она обучается, поэтому начинать лучше с небольших сетей. Возможно, результат будет уже достаточно точным для решения выбранной задачи.
По теории, если количество нейронов очень большое, то сеть выучит, а не обучится. Тогда она на входные данные, на которые её не обучали, будет выдавать результат, далёкий от правды. А если нейронов или слоёв слишком мало, то сеть плохо обучится и будет выдавать результаты со слишком большой погрешностью.
Двухслойные сети хороши для простых зависимостей. Например, y = x2. Сеть обучилась очень быстро и правильно. А y = sin x обучалась уже дольше, но всё-таки обучилась. Для нашей задачи двухслойные сети оказались слишком маленькими. (Для начала мы пытались найти 3 критические температуры по известному химическому составу.)
Пятислойные сети у нас не получилось обучить вообще. Они переставали обучаться и как бы «вязли в болоте»: средняя ошибка оставалась почти одинаковой, далёкой от нужной точности, а результаты выдавались то слишком завышенные, то слишком заниженные для одного и того же химического состава. Что-то «выучить» эти сети и не пытались.
Наилучший вариант для нашей задачи – нейронные сети в 4 слоя (т.е. 3 скрытых слоя и 1 выходной слой), где в первом слое 10-15 нейронов, в следующих слоях меньше, в последнем – 1-3 выходных нейрона. Общая сумма всех нейронов в сети от 20 до 36, если не считать входы и смещения за нейроны. Входов в разных сетях было от 9 до 14. Сети с тремя выходными нейронами рассчитывали сразу три критические температуры. Но несмотря на немного разную структуру и параметры сетей, они обучались до примерно одной и той же точности.
В результате всех экспериментов у нас получилось некоторое количество обученных сетей разной структуры. Из них мы выбрали сети с наименьшими средними и максимальными ошибками так, чтобы каждую температуру рассчитывали 4 разные сети, а потом брали среднее арифметическое из этих 4-х чисел и объявляли его результатом. Такая точность нас уже вполне устраивала. С кривыми была сложность в том, как их представить в виде чисел, к которым должна стремиться нейронная сеть. Когда этот вопрос был решён, структуры сетей были взяты примерно такими же, как для расчёта критических температур.
Нужно написать программу, с помощью которой будет удобно создать и обучить сеть. Возможно, такие программы существуют.
Для обучения не надо брать все-все известные данные. Часть оставляют для проверки.
В руководствах по нейронным сетям обычно пишут: запустите обучаться и ждите, должно всё получиться. Но у нас не получилось.
Если запустить процесс обучения до состояния сети, когда будет достаточно маленькая ошибка, то велика вероятность, что программа зациклится. Это может произойти из-за попадания в локальный минимум, проскакивания глобального минимума, неверного выбора параметров и структуры сети для данной задачи, не совсем подходящий вариант нормализации входных и выходных данных или просто ошибок в программе. Поэтому лучше задать количество проходов по набору данных, посмотреть, что происходит, потом продолжить обучать дальше.
Мы отслеживали ошибку и результаты в процессе обучения. Часто было так.
Сначала сеть как бы «топчется на месте»: ошибка то больше, то меньше, результат далёк от истины. Потом как будто она «догадалась», идёт довольно быстрое улучшение: ошибка быстро уменьшается, результат приближается к истине. На этих двух этапах количество проходов по набору данных мы задавали побольше (100-500).
Через некоторое время ошибка начинала уменьшаться медленнее, потом начинала увеличиваться. Дальше она могла снова начать уменьшаться до какого-то момента или нет. При этом контрольные результаты были не очень далеки от экспериментальных, но нам нужна была бОльшая точность. Тогда мы применяли такие воздействия:
В этих случаях сеть обучается как-то неправильно и не даёт хороших результатов.
Когда сеть обучена, её надо использовать для поставленной задачи. Это уже другая программа (не для создания и обучения сети). Оказалось удобным сделать объект-сеть (язык Паскаль), который включается в любую программу как переменная. Эта сеть должна уметь только откуда-то читаться-создаваться (структура, веса, параметры) и рассчитывать значения (прямой проход), потом удаляться.
Вид этих кривых можно видеть на странице сайта. В качестве исходных данных мы имели координаты точек, соединив которые прямыми линиями получались кривые. Расположение на координатной плоскости и изогнутость кривых как-то зависит от химического состава стали. Сначала мы попробовали самый простой вариант: на вход сети подавали химический состав, а на выходе стремились получить такие же координаты. После долгих попыток это сделать, нам удалось обучить несколько сетей, каждая из которых годилась для определённого типа сталей (своя сеть для углеродистых, своя для никелевых и т.д.). Но при задании промежуточных значений между типами, выдавались непригодные результаты. А обучить сеть на всё множество сталей не удавалось, поэтому вариант получения координат был отвергнут.
Тогда мы попробовали применить формулы, с помощью которых можно описать кривые, а с помощью нейронной сети получить входящие в эти формулы параметры. После нескольких проб мы взяли формулу, которая достаточно точно описывает эти кривые [1]. Она была известна и ранее, но в неё нужно подставлять координаты перегиба кривой и координаты точки на «хвосте», которая берётся за начало расчёта. Эти координаты зависят от химического состава стали, но правильно вычислить их не удавалось. Поэтому применять эту формулу тоже не было возможности. Мы решили получить эти координаты с помощью нейронной сети.
Сначала мы подготовили данные для обучения сетей. Для этого мы отметили координаты перегибов всех экспериментальных кривых для всех известных марок сталей. Положение точек перегиба кривых зависит от химического состава, поэтому мы надеялись получить их с помощью сетей. А точки на «хвосте» могли располагаться где угодно. Поэтому чтобы получить зависимость, мы зафиксировали координату X (время, достаточно большое) и определяли Y (температуру) для этого X. Здесь уже получалась зависимость высоты «хвоста» от химического состава. Далее мы рассчитывали кривую по формуле и сравнивали её расхождение с экспериментальной кривой по точкам. Минимизируя это расхождение, находили оптимальные значения координат расчётных точек методом координатного спуска.
Теперь для каждой кривой у нас стало всего 3 числа, подставив которые в формулу, можно было нарисовать кривую. Мы записали их в другую таблицу, соединённую по индексам с таблицей с химическим составом.
После этого мы обучили нейронные сети на расчёт этих трёх чисел. Структуры и параметры сетей мы взяли похожими на сети для расчёта критических температур. Для каждого типа кривой (Fs, Ps, Pf, Bs, Bf) были свои сети.
Обозначения:
Понравилось: возможность получить хороший результат как-то, без чётких формул, но учитывая влияние разнообразных факторов.
Не понравилось: бОльшая часть работы – метод тыка. Подбор структуры сети и параметров, обучение занимают неопределённое количество времени. Правда, при некотором навыке всё получается быстрее.