public void Run(ref double[] input, out double[] output) { // Перевірка, чи введені дані відповідають кількості нейронів у вхідному шарі if (input.Length != inputSize) { throw new ArgumentException("Input data isn't of the correct dimension"); } // Вихідне значення функції output = new double[layerSize[layerCount - 1]]; // Нормалізація вхідних значень double max = input.Max(); // Запуск мережі for (int l = 0; l < layerCount; l++) { for (int j = 0; j < layerSize[l]; j++) { double sum = 0.0; for (int i = 0; i < (l == 0 ? inputSize : layerSize[l - 1]); i++) { sum += weight[l][i][j] * (l == 0 ? input[i] : layerOtput[l - 1][i]); } sum += bias[l][j]; layerInput[l][j] = sum; /*if (l == layerCount - 1) * layerOtput[l][j] = sum; * else*/ layerOtput[l][j] = TransferFunctions.Evaluate(transferFunction[l], sum); } } // копіюємо вихід мережі у вихідний масив for (int i = 0; i < layerSize[layerCount - 1]; i++) { output[i] = layerOtput[layerCount - 1][i]; } }
// Функція навчання public double Train(ref double[] input, ref double[] desired, double TrainingRate, double Momentum) { // Перевірка вхідних параметрів if (input.Length != inputSize) { throw new ArgumentException("Invalid input parameter", "input"); } if (desired.Length != layerSize[layerCount - 1]) { throw new ArgumentException("Invalid input parameter", "desired"); } // Локальні змінні double error = 0.0, sum = 0.0, weigtdelta = 0.0, biasDelta = 0.0; double[] output = new double[layerSize[layerCount - 1]]; // Запуск мережі Run(ref input, out output); //Розмножуємо похибку у зворотньму порядку for (int l = layerCount - 1; l >= 0; l--) { //Вихідний шар if (l == layerCount - 1) { for (int k = 0; k < layerSize[l]; k++) { delta[l][k] = output[k] - desired[k]; error += Math.Pow(delta[l][k], 2); delta[l][k] *= TransferFunctions.DerivativeEvaluate(transferFunction[l], layerInput[l][k]); } } //Прихований шар else { for (int i = 0; i < layerSize[l]; i++) { sum = 0.0; for (int j = 0; j < layerSize[l + 1]; j++) { sum += weight[l + 1][i][j] * delta[l + 1][j]; } sum *= TransferFunctions.DerivativeEvaluate(transferFunction[l], layerInput[l][i]); delta[l][i] = sum; } } } // Оновлення ваг та відхилень for (int l = 0; l < layerCount; l++) { for (int i = 0; i < (l == 0 ? inputSize : layerSize[l - 1]); i++) { for (int j = 0; j < layerSize[l]; j++) { weigtdelta = TrainingRate * delta[l][j] * (l == 0 ? input[i] : layerOtput[l - 1][i]) + Momentum * previousWeightDelta[l][i][j]; weight[l][i][j] -= weigtdelta; previousWeightDelta[l][i][j] = weigtdelta; } } } for (int l = 0; l < layerCount; l++) { for (int i = 0; i < layerSize[l]; i++) { biasDelta = TrainingRate * delta[l][i] + Momentum * previosBiasDelta[l][i]; bias[l][i] -= biasDelta; previosBiasDelta[l][i] = biasDelta; } } return(error); }