// Функція навчання 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); }
// Функція навчання public double Train(ref double[] input, ref double[] desired, double kCoefficient, double bCoefficient, double eCoefficient, 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, phiDelta = 0.0, phiDeltaSecond = 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++) { phiDelta = delta[l][j] * (l == 0 ? input[i] : layerOtput[l - 1][i]); // обрахунок phi для поточної ваги phiDeltaSecond = (1 - eCoefficient) * previousPhiDelta[l][i][j] + eCoefficient * previousPhiDeltaSecond[l][i][j]; // обрахунок phiSecond для поточної ваги // оновлення швидкості навчання для ваги learningRates[l][i][j] += CalculateLearningRateDelta(previousPhiDeltaSecond[l][i][j], phiDelta, kCoefficient, bCoefficient, learningRates[l][i][j]); weigtdelta = learningRates[l][i][j] * phiDelta + Momentum * previousWeightDelta[l][i][j]; weight[l][i][j] -= weigtdelta; previousWeightDelta[l][i][j] = weigtdelta; previousPhiDelta[l][i][j] = phiDelta; previousPhiDeltaSecond[l][i][j] = phiDeltaSecond; } } } for (int l = 0; l < layerCount; l++) { for (int i = 0; i < layerSize[l]; i++) { biasDelta = initialLearningRate * delta[l][i] + Momentum * previosBiasDelta[l][i]; bias[l][i] -= biasDelta; previosBiasDelta[l][i] = biasDelta; } } return(error); }