/// <summary>Метод обработки одного слоя</summary> /// <param name="LayerWeights">Матрица коэффициентов передачи</param> /// <param name="Offset">Вектор смещений нейронов</param> /// <param name="OffsetWeight">Вектор весовых коэффициентов</param> /// <param name="Input">Вектор входного воздействия</param> /// <param name="Output">Вектор выходных значений нейронов</param> /// <param name="Activation">Активационная функция слоя (если не задана, то используется Сигмоид)</param> /// <param name="State">Вектор входа функции активации</param> private static void ProcessLayer( [NotNull] double[,] LayerWeights, [NotNull] double[] Offset, [NotNull] double[] OffsetWeight, Span <double> Input, Span <double> Output, [CanBeNull] ActivationFunction Activation = null, [CanBeNull] double[] State = null) { // Вычисляем X_next = f(Net = W * X + Wo*O) var layer_outputs_count = LayerWeights.GetLength(0); var layer_inputs_count = LayerWeights.GetLength(1); for (var output_index = 0; output_index < layer_outputs_count; output_index++) { var output = Offset[output_index] * OffsetWeight[output_index]; for (var input_index = 0; input_index < layer_inputs_count; input_index++) { output += LayerWeights[output_index, input_index] * Input[input_index]; } if (State != null) { State[output_index] = output; } Output[output_index] = Activation?.Value(output) ?? Sigmoid.Activation(output); } }
public static void Process( double[] InputOutput, Span <double> Output, double[] State, double[,] StateGateW, double[] StateGateOffset, double[,] UpdateStateW, double[] UpdateStateOffset, double[,] UpdateStateGateW, double[] UpdateStateGateOffset, double[,] OutputGateW, double[] OutputGateOffset, double[] OutputGateState, double[,] UpdateOutputW, double[] UpdateOutputOffset) { var state_length = State.Length; var input_output_length = InputOutput.Length; var output_length = Output.Length; // Расчёт состояния for (var i = 0; i < state_length; i++) { // Инициализация аккумуляторов значениями смещений слоёв var forget_state_gate = StateGateOffset[i]; // Аккумулятор вентиля сброса состояния var update_state_gate = UpdateStateGateOffset[i]; // Аккумулятор вентиля обновления состояния var update_state = UpdateStateOffset[i]; // Аккумулятор обновления состояния // Расчёт выходов слоёв для обновления состояния for (var j = 0; j < input_output_length; j++) { forget_state_gate += StateGateW[i, j] * InputOutput[j]; update_state_gate += UpdateStateGateW[i, j] * InputOutput[j]; update_state += UpdateStateW[i, j] * InputOutput[j]; } State[i] = State[i] * Sigmoid.Activation(forget_state_gate) // Затухание состояния + Th.Activation(update_state) * Sigmoid.Activation(update_state_gate); // Обновление состояния } // Расчёт коэффициентов выходного вентиля for (var i = 0; i < output_length; i++) { // Инициализация выходного вентиля значением смещения слоя var s = OutputGateOffset[i]; // Аккумулятор выходного вентиля // Расчёт выхода вентиля for (var j = 0; j < input_output_length; j++) { s += OutputGateW[i, j] * InputOutput[j]; } OutputGateState[i] = Sigmoid.Activation(s); } // Расчёт выхода на основе состояния for (var i = 0; i < output_length; i++) { // Инициализация аккумулятора выхода значением смещения слоя var s = UpdateOutputOffset[i]; // Аккумулятор выхода // Расчёт выхода for (var j = 0; j < state_length; j++) { s += UpdateOutputW[i, j] * State[j]; } // Выход определяется как произведение аккумулятора и выходного вентиля Output[i] = Th.Activation(s) * OutputGateState[i]; } }