Определение неявных сложных закономерностей физико-химических процессов с помощью нейронных сетей. Опыт решения задачи. Алгоритмы.
В последнее время много говорят о нейронных сетях, их возможностях и перспективах. Появилось много подробных, интересных, полезных статей и книг по их созданию. Например, хорошие статьи для начинающих с последовательными объяснениями основ находятся по адресу 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-х чисел и объявляли его результатом. Такая точность нас уже вполне устраивала. С кривыми была сложность в том, как их представить в виде чисел, к которым должна стремиться нейронная сеть. Когда этот вопрос был решён, структуры сетей были взяты примерно такими же, как для расчёта критических температур.
С чего начать
Нужно написать программу, с помощью которой будет удобно создать и обучить сеть. Возможно, такие программы существуют.
В нашей программе были предусмотрены такие возможности:
- Ввод количества входов, слоёв и нейронов в каждом слое, чтобы можно было пробовать разные структуры. Соответственно должна быть возможность хранения весов и их приращений, смещений и их приращений, выходов слоёв и т.п. в массивах разной структуры. Во многих описаниях веса рассматриваются как матрица. Мы использовали трёхмерный динамический массив (слой, нейрон, вход). В нём в каждом слое разное количество нейронов и входов. Нам так было удобно, чтобы не путаться с расположением нейронов.
- Ввод параметров сети:
- α – параметр сигмоида, который мы использовали в качестве функции активации нейронов. Нам подошли значения от 0.25 до 1, но сильно заметного влияния этого параметра на обучение сети замечено не было.
- η – скорость обучения. Мы взяли значение 1. При уменьшении etha скорость процесса обучения сильно увеличивалась. Возможно, результат был бы лучше, но терпения не хватало.
- µ – момент. С этим параметром мы не экспериментировали, взяв его 0.2. Позднее мы узнали, что с помощью него можно избегать проблем с локальными минимумами, а их у нас было предостаточно.
- Выбор полей таблицы (базы данных) как входных данных и выходных результатов, а также задание коэффициентов для приведения чисел к нужному диапазону. На выходе сети (если активационная функция – сигмоид) будут числа в интервале (0;1), а наши критические температуры до 1000, поэтому мы делили их на 1000. На вход можно подавать любые числа. В нашем случае лучшие результаты были с входными данными от 0 до 9. Так как в сталях химические элементы содержатся в разных комбинациях, то многие поля были равны 0. Тогда веса для этих входов умножались на 0 и плохо обучались. Лучший результат получился, когда вместо нулей стали вводить очень маленькие числа.
- Выбор: создать новую сеть или открыть старую сохранённую и ещё недообученную для дообучения.
- Сохранение промежуточных вариантов сети.
- Доступ к таблице данных.
- Запись SQL-запроса к таблице данных для смены последовательности подачи данных и выбора набора данных для обучения.
- Количество проходов по таблице при обучении.
- Запуск процесса обучения.
- Вывод среднеквадратичной и максимальной ошибок. Для ускорения мы не вычисляли их постоянно.
- Встряска сети.
- Вывод вычислений и графиков для контроля обучения.
Процесс обучения
Для обучения не надо брать все-все известные данные. Часть оставляют для проверки.
В руководствах по нейронным сетям обычно пишут: запустите обучаться и ждите, должно всё получиться. Но у нас не получилось.
Если запустить процесс обучения до состояния сети, когда будет достаточно маленькая ошибка, то велика вероятность, что программа зациклится. Это может произойти из-за попадания в локальный минимум, проскакивания глобального минимума, неверного выбора параметров и структуры сети для данной задачи, не совсем подходящий вариант нормализации входных и выходных данных или просто ошибок в программе. Поэтому лучше задать количество проходов по набору данных, посмотреть, что происходит, потом продолжить обучать дальше.
Мы отслеживали ошибку и результаты в процессе обучения. Часто было так.
Сначала сеть как бы «топчется на месте»: ошибка то больше, то меньше, результат далёк от истины. Потом как будто она «догадалась», идёт довольно быстрое улучшение: ошибка быстро уменьшается, результат приближается к истине. На этих двух этапах количество проходов по набору данных мы задавали побольше (100-500).
Через некоторое время ошибка начинала уменьшаться медленнее, потом начинала увеличиваться. Дальше она могла снова начать уменьшаться до какого-то момента или нет. При этом контрольные результаты были не очень далеки от экспериментальных, но нам нужна была бОльшая точность. Тогда мы применяли такие воздействия:
- Встряска. Это добавление небольших случайных чисел к весам (от -0.25 до 0.25). Часто это давало сети возможность некоторое время обучаться дальше. Но добавление случайных чисел к смещениям почему-то ухудшало процесс обучения.
- Меняли порядок подачи данных: сортировка по разным химическим элементам и по нескольким сразу.
Как делать не надо
- Брать веса входов неслучайными: одинаковыми или рассчитанными каким-то способом.
- В процессе обучения менять параметры сети: параметр сигмоида α, скорость обучения η и момент µ.
- Взять небольшую сеть, пообучать её, потом добавить ещё нейроны или скрытые слои и пытаться обучать дальше (ведь она уже наполовину обучена).
- Сначала обучать сеть на данных одного типа (например, только углеродистые стали), потом начинать добавлять данные другого типа (например, хромо-никелевые стали), потом третьего типа (например, вольфрамовые).
В этих случаях сеть обучается как-то неправильно и не даёт хороших результатов.
Чем закончить
Когда сеть обучена, её надо использовать для поставленной задачи. Это уже другая программа (не для создания и обучения сети). Оказалось удобным сделать объект-сеть (язык Паскаль), который включается в любую программу как переменная. Эта сеть должна уметь только откуда-то читаться-создаваться (структура, веса, параметры) и рассчитывать значения (прямой проход), потом удаляться.
Получение кривых аустенитного распада с помощью нейронных сетей
Вид этих кривых можно видеть на странице сайта. В качестве исходных данных мы имели координаты точек, соединив которые прямыми линиями получались кривые. Расположение на координатной плоскости и изогнутость кривых как-то зависит от химического состава стали. Сначала мы попробовали самый простой вариант: на вход сети подавали химический состав, а на выходе стремились получить такие же координаты. После долгих попыток это сделать, нам удалось обучить несколько сетей, каждая из которых годилась для определённого типа сталей (своя сеть для углеродистых, своя для никелевых и т.д.). Но при задании промежуточных значений между типами, выдавались непригодные результаты. А обучить сеть на всё множество сталей не удавалось, поэтому вариант получения координат был отвергнут.
Тогда мы попробовали применить формулы, с помощью которых можно описать кривые, а с помощью нейронной сети получить входящие в эти формулы параметры. После нескольких проб мы взяли формулу, которая достаточно точно описывает эти кривые [1]. Она была известна и ранее, но в неё нужно подставлять координаты перегиба кривой и координаты точки на «хвосте», которая берётся за начало расчёта. Эти координаты зависят от химического состава стали, но правильно вычислить их не удавалось. Поэтому применять эту формулу тоже не было возможности. Мы решили получить эти координаты с помощью нейронной сети.
Сначала мы подготовили данные для обучения сетей. Для этого мы отметили координаты перегибов всех экспериментальных кривых для всех известных марок сталей. Положение точек перегиба кривых зависит от химического состава, поэтому мы надеялись получить их с помощью сетей. А точки на «хвосте» могли располагаться где угодно. Поэтому чтобы получить зависимость, мы зафиксировали координату X (время, достаточно большое) и определяли Y (температуру) для этого X. Здесь уже получалась зависимость высоты «хвоста» от химического состава. Далее мы рассчитывали кривую по формуле и сравнивали её расхождение с экспериментальной кривой по точкам. Минимизируя это расхождение, находили оптимальные значения координат расчётных точек методом координатного спуска.
Теперь для каждой кривой у нас стало всего 3 числа, подставив которые в формулу, можно было нарисовать кривую. Мы записали их в другую таблицу, соединённую по индексам с таблицей с химическим составом.
После этого мы обучили нейронные сети на расчёт этих трёх чисел. Структуры и параметры сетей мы взяли похожими на сети для расчёта критических температур. Для каждого типа кривой (Fs, Ps, Pf, Bs, Bf) были свои сети.
Алгоритмы, которые мы использовали
Обозначения:
- W [слой, нейрон, вход] – веса
- DW [слой, нейрон, вход] – приращения весов
- WT [слой, нейрон] – смещения
- DWT [слой, нейрон] – приращения смещений
- Out [0, вход] – входы
- Out [слой+1, нейрон = вход следующего слоя] – выходы по слоям
- F – функция активации нейрона
- α – параметр сигмоида, подбирается вручную,
- x – сумма всего, что входит в нейрон.
- EA, EI – вспомогательные одномерные массивы с размерностью, равной максимальному числу нейронов в слое во всей сети.
Прямой проход (для получения результата по входным данным)
- Входные данные в Out [ 0, k ], k = 0 .. количество входов –1.
- Посчитать выходы нейронов первого слоя Out [ 1, j ], j = 0 .. количество нейронов в первом слое –1. Они будут входами к нейронам второго слоя.
- Далее последовательно считать выходы следующих слоёв до последнего слоя включительно.
Выход j-го нейрона i-го слоя с Nk входами в j-ый нейрон:- Out [ i+1, j ] = F(x),
- x = Out [ i, 0 ] * W [ i, j, 0 ] + Out [ i, 1 ] * W [ i, j, 1 ] + .. + Out [ i, Nk-1 ] * W [ i, j, Nk-1 ] + WT [ i, j ]
- Результат - выход последнего слоя.
Обратный проход (метод обратного распространения, для последовательной замены весов в процессе обучения)
- Вычислить результат Out [ Ni, j ], j = 0 .. количество выходов -1, Ni – количество слоёв.
- Для выходного слоя для j-го выхода:
- EA [ j ] = Верный ответ [ j ] – Out [ Ni, j ]
- Начало цикла по слоям от последнего к первому (начиная с последнего).
- Для каждого j-го нейрона в i-м слое:
- EI [ j ] = EA [ j ] * α * Out [ i+1, j ] * ( 1 – Out [ i+1, j ] )
- EA[ j ] = 0
- (α – параметр сигмоида)
- Для каждого k-го входа в i-м слое:
- EA [ k ] = EI [ 0 ] * W [ i, 0, k ] + EI [ 1 ] * W [ i, 1, k ] + .. + EI [ Nj ] * W [ i, Nj, k ]
- (Nj – количество нейронов в i-ом слое,
количество входов равно количеству нейронов в предыдущем слое.
EA используется в предыдущем слое в следующем проходе цикла, поэтому для i = 0 вычислять уже не надо.
W ещё не пересчитаны.)
- Пересчитываем веса и смещения.
Для k-го входа j-го нейрона i-го слоя:- DW [ i, j, k ] = η * EI [ j ] * Out [ i, k ] + µ * DW [ i, j, k ]
- W [ i, j, k ] = W [ i, j, k ] + DW [ i, j, k ]
- DWT [ i, j ] = η * EI [ j ] + µ * DWT [ i, j ]
- WT [ i, j ] = WT [ i, j ] + DWT [ i, j ]
- (η – скорость обучения, µ - момент)
- Для каждого j-го нейрона в i-м слое:
Обучение
- Задать количество проходов по таблице данных N и маленькое число error для условия перехода к следующей записи.
- Начало цикла по количеству проходов N.
- Начало цикла по записям таблицы.
- Прочитать входные и выходные данные из таблицы (одну запись).
- Вычислить результат (прямой проход)
- Для каждого j-го выхода последовательно:
Пока | Верный ответ – Out [ Ni, j ] | > error делать- Обратный проход
- Прямой проход
- Переход к следующей записи таблицы данных
- Начало цикла по записям таблицы.
- Оповещение, что процедура закончила работу.
Вычисление ошибки (среднеквадратичной и максимальной)
- Обнулить счётчик количества выходных чисел n и накопитель ошибки SumError.
- Начало цикла по записям таблицы
- Прочитать входные и выходные данные из таблицы (одну запись).
- Вычислить результат (прямой проход).
- Для каждого j-го выхода последовательно:
- Разность Dif = Верный ответ [ j ] – Out [ Ni, j ]
- SumError = SumError + Dif 2
- Максимальная ошибка MaxError = max ( | Dif |, MaxError )
- n = n + 1
- Переход к следующей записи таблицы данных.
- Среднеквадратичная ошибка Error = SumError / n.
- Вывод результатов Error и MaxError.
Встряска
- Для каждого k-го входа j-го нейрона i-го слоя:
- W [ i, j, k ] = W [ i, j, k ] + случайное число от -0.25 до 0.25.
Впечатления от работы с нейронными сетями
Понравилось:
Возможность получить хороший результат как-то, без чётких формул, но учитывая влияние разнообразных факторов.
Не понравилось:
БОльшая часть работы – метод тыка. Подбор структуры сети и параметров, обучение занимают неопределённое количество времени. Правда, при некотором навыке всё получается быстрее.
Использованная литература о теоретических основах и экспериментах:
- S. Licka, J. Wozniak Mathematical model for analyzing the technological conditions of hot rolling of steel - Hutnicke Aktuality, 1981, 22 (9) 1-49 ссылка, откуда взяли подход с экспонентами.
- Д.Л. Вайнштейн, А.И. Ковалев, Моделирование фазовых и структурных превращений при термообработке и горячей прокатке низко- и среднеуглеродистых среднелегированных конструкционных сталей// Металлург, 1999, № 6, с. 44-46.
- A. Kovalev, D. Wainstein. Modelling of grain boundary segregation kinetics that are responsible on irreversible and reversible temper embrittlement of engineering steels, J. Phys. IV France 120 (2004) 69-77
- A.I. Kovalev, D.L. Wainstein. Chapter 2. Design Simulation of Kinetics of Multi-Component Grain Boundary Segregations in the Engineering Steels under Quenching and Tempering. in book: Modeling and Simulation for Material Selection and Mechanical Design, ed. by G. Totten, Lin Xie and Kiyoshi Funatani, Marcel Dekker Inc. N.Y. U.S.A. (2004) 57-123
- Попов А.А., Попова А.Е. Справочник термиста: изотермические и термокинетические диаграммы распада переохлаждённого аустенита. МАШГИЗ, Москва, Свердловск, 1961