private static PredictiveValues CalculatePredictiveValues(double[][] expectedOutputs, double[][] actualOutputs) { var n_tp = 0; var n_fp = 0; var n_tn = 0; var n_fn = 0; var n = expectedOutputs.Length; for (int i = 0; i < n; i++) { var expected = (int)Math.Round(expectedOutputs[i][0]); var actual = (int)Math.Round(actualOutputs[i][0]); if (actual == expected) { // u ovom slucaju imamo tacnu predikciju // potrebno je odrediti da li pozitivna ili negativna if (expected == 0) n_tn++; // negativna else n_tp++; // pozitivna } else { // u ovom slucaju imamo netacnu predikciju // potrebno je odrediti da li pozitivna ili negativna if (expected == 0) n_fn++; // negativna else n_fp++; // pozitivna } } var result = new PredictiveValues() { N_TP = n_tp, N_TN = n_tn, N_FP = n_fp, N_FN = n_fn, SENS = (decimal)(n_tp / (double)(n_tp + n_fn)), SPEC = (decimal)(n_tn / (double)(n_tn + n_fp)), PPV = (decimal)Math.Round(n_tp / (n_tp + (double)n_fp), 6), NPV = (decimal)Math.Round(n_tn / (n_tn + (double)n_fn), 6) }; return result; }
private static AlgoritamPredictiveValues Ann(Data data, int neuronCount, List<AnnLearningRecord> learningData, out ActivationNetwork resultAnn) { // za aktivacionu funkciju uzimamo standardnu sigmoidnu var activationFunction = new SigmoidFunction(); // kreiramo neuronsku mrežu sa 6 neurona u ulazniom sloju i jednim u izlaznom // broj skrivenih neurona je određen parametrom neuronCount var ann = new ActivationNetwork(activationFunction, INPUT_COUNT, neuronCount, OUTPUT_COUNT); // postavljanje inicijalnih težinski faktora new NguyenWidrow(ann).Randomize(); // algoritam za obučavanje var teacher = new LevenbergMarquardtLearning(ann); teacher.LearningRate = 0.001; // uključujemo regularizaciju teacher.UseRegularization = true; double err; int count = 0; int failCount = 0; PredictiveValues lastPredictiveValues = null; int epochCounter = 1; while (true) { err = teacher.RunEpoch(data.LearnInputs, data.LearnOutputs); // izracunavamo prediktivne vrednosti var pv = CalculatePredictiveValues(ann, data); LogMessage($"Epoch #{count + 1:000}, PPV: {pv.PPV,10:#0.000000}, NPV: {pv.NPV,10:#0.000000}, SPEC: {pv.SPEC,10:#0.000000}, SENS: {pv.SENS,10:#0.000000}"); if (learningData != null) { learningData.Add(new AnnLearningRecord() { EpochNumber = epochCounter++, NPV = pv.NPV, PPV = pv.PPV, N_FN = pv.N_FN, N_FP = pv.N_FP, N_TN = pv.N_TN, N_TP = pv.N_TP }); } if (lastPredictiveValues != null) { // proveravamo da li se performansa poboljsala ili ne if (lastPredictiveValues.PPV >= pv.PPV && lastPredictiveValues.NPV >= pv.NPV) { failCount++; // obuka se prekida ukoliko do poboljsanja nije doslo u poslednjih 10 epoha if (failCount >= 10) break; } else failCount = 0; } lastPredictiveValues = pv; count++; if (count >= 500) break; } // izracunavanje izlaza double[][] AnnCompute(double[][] inputs, double[][] outputs) { var res = new double[inputs.Length][]; for (int i = 0; i < inputs.Length; i++) { var annr = ann.Compute(inputs[i])[0]; var to = Math.Round(outputs[i][0], 0); var anno = Math.Round(annr, 0); res[i] = new double[] { anno }; } return res; } var learnOutputs = AnnCompute(data.LearnInputs, data.LearnOutputs); var validateOutputs = AnnCompute(data.ValidateInputs, data.ValidateOutputs); var testOutputs = AnnCompute(data.TestInputs, data.TestOutputs); var learnPV = CalculatePredictiveValues(data.LearnOutputs, learnOutputs); var validatePV = CalculatePredictiveValues(data.ValidateOutputs, validateOutputs); var testPV = CalculatePredictiveValues(data.TestOutputs, testOutputs); var result = new AlgoritamPredictiveValues() { LearnNPV = learnPV.NPV, LearnPPV = learnPV.PPV, LearnSENS = learnPV.SENS, LearnSPEC = learnPV.SPEC, ValidateNPV = validatePV.NPV, ValidatePPV = validatePV.PPV, ValidateSENS = validatePV.SENS, ValidateSPEC = validatePV.SPEC, TestNPV = testPV.NPV, TestPPV = testPV.PPV, TestSENS = testPV.SENS, TestSPEC = testPV.SPEC, }; resultAnn = ann; return result; }