oil-gas-neuro

node v8.17.0
version: 3.0.0
endpointsharetweet
Код нейронной сети по прогнозированию объёма произвоидтельности НПС. Выполнили студенты группы АСМ-17-04-2 Беркита Е. Вайланд Ю. Попова К. Синалицкий Е.
/** * Код нейронной сети по прогнозированию объёма произвоидтельности НПС * * Выполнили студенты группы АСМ-17-04-2 * Беркита Е. * Вайланд Ю. * Попова К. * Синалицкий Е. * * Это пример нейронной сети, прогнозирующей производительность НПС * Схема сети: 7 узлов на входе(i1, i2, i3, i4, i5, i6, i7), 2 узла на скрытом слое(h1, h2), 1 выходной узел(o1) * На каждом уровне используется bias, функция активации - сигмоида. */ // ОБЪЯВЛЯЕМ ЗАВИСИМОСТИ // Ramda - это вспомогательная библиотека, которая используется исключительно // для удобства в вспомогательных функциях, помогает облегчить чтение кода. Можно было бы обойтись и без неё. var R = require('ramda'); void 0; // не "раздуваем" выходные данные // Используем воспроизводимый random от Gibson Research Corporation, чтобы понять, что мы сделали не так // Ссылка на зависимость в репозитории Node - https://www.npmjs.com/package/random-seed var random = require('seed-random')(1337); // Исходные данные для разных НПС (два входящих значения - номер НПС и кол-во включенных на ней насосов) var data = [ {input: [1, 0, 2.5, 0.23, 0.87, 3, 4.3], output: 2060}, {input: [1, 1, 2.5, 0.23, 0.87, 3, 4.3], output: 2120}, {input: [1, 2, 2.5, 0.23, 0.87, 3, 4.3], output: 2290}, {input: [1, 3, 2.5, 0.23, 0.87, 3, 4.3], output: 2370}, {input: [2, 0, 2.5, 0.23, 0.87, 3, 4.3], output: 1930}, {input: [2, 1, 2.5, 0.23, 0.87, 3, 4.3], output: 2080}, {input: [2, 2, 2.5, 0.23, 0.87, 3, 4.3], output: 2100}, {input: [2, 3, 2.5, 0.23, 0.87, 3, 4.3], output: 2400}, {input: [3, 0, 2.5, 0.23, 0.87, 3, 4.3], output: 2010}, {input: [3, 1, 2.5, 0.23, 0.87, 3, 4.3], output: 2160}, {input: [3, 2, 2.5, 0.23, 0.87, 3, 4.3], output: 2480}, {input: [3, 3, 2.5, 0.23, 0.87, 3, 4.3], output: 2650} ]; // Эти функции с их графиками можно посмотреть на WolframAlpha: // https://www.wolframalpha.com/input/?i=1+%2F+(1+%2B+e+^+-x) // https://www.wolframalpha.com/input/?i=dx+1+%2F+(1+%2B+e+^+-x) var activation_sigmoid = x => 1 / (1 + Math.exp(-x)); var derivative_sigmoid = x => { const fx = activation_sigmoid(x); return fx * (1 - fx); }; // Изначально берём любые рандомные веса связей (это до обучения нейросети) var weights = { i1_h1: random(), i2_h1: random(), i3_h1: random(), i4_h1: random(), i5_h1: random(), i6_h1: random(), i7_h1: random(), i8_h1: random(), bias_h1: random(), i1_h2: random(), i2_h2: random(), i3_h2: random(), i4_h2: random(), i5_h2: random(), i6_h2: random(), i7_h2: random(), i8_h2: random(), bias_h2: random(), h1_o1: random(), h2_o1: random(), bias_o1: random(), }; // Сама нейронная сеть (без обучения, только прямой проход) function nn(i1, i2, i3, i4, i5, i6, i7) { var h1_input = weights.i1_h1 * i1 + weights.i2_h1 * i2 + weights.i3_h1 * i3 + weights.i4_h1 * i4 + weights.i5_h1 * i5 + weights.i6_h1 * i6 + weights.i7_h1 * i7 + weights.bias_h1; var h1 = activation_sigmoid(h1_input); var h2_input = weights.i1_h2 * i1 + weights.i2_h2 * i2 + weights.i3_h2 * i3 + weights.i4_h2 * i4 + weights.i5_h2 * i5 + weights.i6_h2 * i6 + weights.i7_h2 * i7 + weights.bias_h2; var h2 = activation_sigmoid(h2_input); var o1_input = weights.h1_o1 * h1 + weights.h2_o1 * h2 + weights.bias_o1; var o1 = activation_sigmoid(o1_input); return o1; } // Подсчет значений var calculateResults = () => R.mean(data.map(({input: [i1, i2, i3, i4, i5, i6, i7], output: y}) => Math.pow(y - nn(i1, i2, i3, i4, i5, i6, i7), 2))); var outputResults = () => data.forEach(({input: [i1, i2, i3, i4, i5, i6, i7], output: y}) => console.log(`${i1}, ${i2}, ${i3}, ${i4}, ${i5}, ${i6}, ${i7} => ${nn(i1, i2, i3, i4, i5, i6, i7)} (expected ${y})`)); outputResults(); // Подсчет разницы весов var train = () => { const weight_deltas = { i1_h1: 0, i2_h1: 0, i3_h1: 0, i4_h1: 0, i5_h1: 0, i6_h1: 0, i7_h1: 0, bias_h1: 0, i1_h2: 0, i2_h2: 0, i3_h2: 0, i4_h2: 0, i5_h2: 0, i6_h2: 0, i7_h2: 0, bias_h2: 0, h1_o1: 0, h2_o1: 0, bias_o1: 0, }; for (var {input: [i1, i2, i3, i4, i5, i6, i7], output} of data) { // Это код, просто скопированный из функции выше - чтобы научить сеть, нужно сначала делать проход вперед var h1_input = weights.i1_h1 * i1 + weights.i2_h1 * i2 + weights.i3_h1 * i3 + weights.i4_h1 * i4 + weights.i5_h1 * i5 + weights.i6_h1 * i6 + weights.i7_h1 * i7 + weights.bias_h1; var h1 = activation_sigmoid(h1_input); var h2_input = weights.i1_h2 * i1 + weights.i2_h2 * i2 + weights.i3_h2 * i3 + weights.i4_h2 * i4 + weights.i5_h2 * i5 + weights.i6_h2 * i6 + weights.i7_h2 * i7 + weights.bias_h2; var h2 = activation_sigmoid(h2_input); var o1_input = weights.h1_o1 * h1 + weights.h2_o1 * h2 + weights.bias_o1; var o1 = activation_sigmoid(o1_input); // Обучение начинается: // мы расчитываем разницу var delta = output - o1; // Затем берем производную (и выкидываем 2 *, потому что это нам не так важно) var o1_delta = delta * derivative_sigmoid(o1_input); // и для нашей формулы вида w1 * h1 + w2 * h2 мы вначале пытаемся обновить веса w1 и w2 weight_deltas.h1_o1 += h1 * o1_delta; weight_deltas.h2_o1 += h2 * o1_delta; weight_deltas.bias_o1 += o1_delta; // А затем входные значения h1 и h2. // Мы не можем просто взять и изменить их - это выход такой же функции активации // Поэтому мы пропускаем эту ошибку дальше по тому же принципу var h1_delta = o1_delta * derivative_sigmoid(h1_input) * h1_o1; var h2_delta = o1_delta * derivative_sigmoid(h2_input) * h2_o2; weight_deltas.i1_h1 += i1 * h1_delta; weight_deltas.i2_h1 += i2 * h1_delta; weight_deltas.i3_h1 += i3 * h1_delta; weight_deltas.i4_h1 += i4 * h1_delta; weight_deltas.i5_h1 += i5 * h1_delta; weight_deltas.i6_h1 += i6 * h1_delta; weight_deltas.i7_h1 += i7 * h1_delta; weight_deltas.bias_h1 += h1_delta; weight_deltas.i1_h2 += i1 * h2_delta; weight_deltas.i2_h2 += i2 * h2_delta; weight_deltas.i3_h2 += i3 * h2_delta; weight_deltas.i4_h2 += i4 * h2_delta; weight_deltas.i5_h2 += i5 * h2_delta; weight_deltas.i6_h2 += i6 * h2_delta; weight_deltas.i7_h2 += i7 * h2_delta; weight_deltas.bias_h2 += h2_delta; } // Возвращаем значение разницы весов return weight_deltas; }; /** * Функция обучения нейронной сети * @param weight_deltas */ var applyTrainUpdate = (weight_deltas = train()) => Object.keys(weights).forEach(key => weights[key] += weight_deltas[key]); // applyTrainUpdate(); // outputResults(); // calculateResults(); // Можем потестить на 100 попытках // R.times(() => applyTrainUpdate(), 100); // outputResults(); // calculateResults(); // Можем потестить на 1000 попытках R.times(() => applyTrainUpdate(), 1000); outputResults(); calculateResults();
Loading…

no comments

    sign in to comment