예제 #1
0
        /// <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);
            }
        }
예제 #2
0
        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];
            }
        }