/// <summary>
 /// Creates a new instance of training epoch event arguments
 /// </summary>
 /// <param name="trainingIteration">
 /// Current training iteration
 /// </param>
 /// <param name="trainingSet">
 /// The training set associated with the event
 /// </param>
 public TrainingEpochEventArgs(int trainingIteration, TrainingSet trainingSet)
 {
     this.trainingSet = trainingSet;
     this.trainingIteration = trainingIteration;
 }
        /// <summary>
        /// Phần train cho ANN
        /// </summary>
        private void TrainANN(bool isBatchMode)
        {
            string strTrainFile = null;
            if (isBatchMode)
            {
                strTrainFile = _trainFilePath;
            }
            else
            {
                strTrainFile = tbxTrainFilePath.Text;
            }

            int iPos = strTrainFile.LastIndexOf('_');
            string strModelFile = strTrainFile.Remove(iPos + 1) + "model.txt";

            //khởi tạo các tham số cho mạng
            ANNParameterBUS.HiddenNode = int.Parse(tbxANNHiddenNode.Text);
            ANNParameterBUS.OutputNode = 3;
            ANNParameterBUS.MaxEpoch = int.Parse(tbxMaxLoops.Text);
            ANNParameterBUS.LearningRate = double.Parse(tbxLearningRate.Text);
            ANNParameterBUS.Momentum = double.Parse(tbxMomentum.Text);
            ANNParameterBUS.Bias = double.Parse(tbxBias.Text);

            //Tiến hành train
            BackpropagationNetwork bpNetwork;
            TrainingSet trainSet = new TrainingSet(strTrainFile, ANNParameterBUS.OutputNode);
            LinearLayer inputLayer = new LinearLayer(trainSet.InputVectorLength);
            ActivationLayer hidenLayer = null;
            ActivationLayer outputLayer = null;
            switch (cmbActivationFunc.SelectedItem.ToString())
            {
                case "Sigmoid":
                    hidenLayer = new SigmoidLayer(ANNParameterBUS.HiddenNode);
                    outputLayer = new SigmoidLayer(ANNParameterBUS.OutputNode);
                    break;
                case "Tanh":
                    hidenLayer = new TanhLayer(ANNParameterBUS.HiddenNode);
                    outputLayer = new TanhLayer(ANNParameterBUS.OutputNode);
                    break;
                case "Logarithm":
                    hidenLayer = new LogarithmLayer(ANNParameterBUS.HiddenNode);
                    outputLayer = new LogarithmLayer(ANNParameterBUS.OutputNode);
                    break;
                case "Sine":
                    hidenLayer = new SineLayer(ANNParameterBUS.HiddenNode);
                    outputLayer = new SineLayer(ANNParameterBUS.OutputNode);
                    break;
            }

            new BackpropagationConnector(inputLayer, hidenLayer);
            new BackpropagationConnector(hidenLayer, outputLayer);

            bpNetwork = new BackpropagationNetwork(inputLayer, outputLayer);

            bpNetwork.SetLearningRate(ANNParameterBUS.LearningRate);

            bpNetwork.EndEpochEvent += new TrainingEpochEventHandler(
                    delegate(object senderNetwork, TrainingEpochEventArgs args)
                    {
                        tlsProgressBar.Value = (int)(args.TrainingIteration * 100d / ANNParameterBUS.MaxEpoch);
                        tlsStatus.Text = "Current iteration: " + args.TrainingIteration;
                        Application.DoEvents();
                    });
            bpNetwork.Learn(trainSet, ANNParameterBUS.MaxEpoch);

            // Lưu lại model
            Stream stream = File.Open(strModelFile, FileMode.Create);
            BinaryFormatter bformatter = new BinaryFormatter();
            bformatter.Serialize(stream, bpNetwork);
            stream.Close();
            tlsProgressBar.Value = 0;
        }
        /// <summary>
        /// Huấn luyện mô hình ANN - DT
        /// </summary>        
        private void TrainANN_DT(bool isBatchMode)
        {
            string strTrainFile = null;
            if (isBatchMode)
            {
                strTrainFile = _trainFilePath;

            }
            else
            {
                strTrainFile = tbxTrainFilePath.Text;
            }
            // Xác định bộ tham số DT với dữ liệu train tỉ lệ 9:1
            SetBestParamater4DT_ANN(strTrainFile);

            // Bước 1: Xây dựng mô hình DT với dữ liệu train
            int iPos = strTrainFile.LastIndexOf('.');
            string dataFile = strTrainFile.Remove(iPos) + ".data.txt";

            iPos = strTrainFile.IndexOf('_');
            string metaFile = strTrainFile.Remove(iPos) + ".meta";

            // Tạo dữ liệu Train
            Dataset dataDTTrain = new Dataset(metaFile, dataFile);
            DecisionTreeAlgorithm tree = new DecisionTreeAlgorithm(dataDTTrain);

            switch (cmbSplitFunc.SelectedItem.ToString())
            {
                case "Gain":
                    tree.SplitFun = DecisionTreeAlgorithm.SPLIT_GAIN;
                    break;
                case "Gain Ratio":
                    tree.SplitFun = DecisionTreeAlgorithm.SPLIT_GAIN_RATIO;
                    break;
                case "GINI":
                    tree.SplitFun = DecisionTreeAlgorithm.SPLIT_GINI;
                    break;
                case "Random":
                    tree.SplitFun = DecisionTreeAlgorithm.SPLIT_RANDOM;
                    break;
            }
            switch (cmbPruneFunc.SelectedItem.ToString())
            {
                case "Pessimistic":
                    tree.PruneAlg = DecisionTreeAlgorithm.PRUNING_PESSIMISTIC;
                    break;
                case "Reduced-error":
                    tree.PruneAlg = DecisionTreeAlgorithm.PRUNING_REDUCED_ERROR;
                    break;
            }
            // Học, xây dựng lên cây quyết định
            tree.BuildDTTree();

            // Duyệt cây và trích ra tập luật
            tree.ExtractRules();

            iPos = strTrainFile.LastIndexOf('_');
            string ruleFile = strTrainFile.Remove(iPos) + ".rules";
            tree.SaveRule2File(ruleFile);

            // Bước 2: Thực hiện test trên dữ liệu train với mô hình mới tạo
            //         và xác định số mẫu test dúng làm đầu vào cho AN gợi là NewDataTrain
            // Thực hiện test lại với dữ liệu train, những mẫu test phân lớp lại đúng
            // Sẽ là dữ liệu train cho ANN đặt là newANNDataTrain
            Dataset dataDTTest = dataDTTrain;
            List<int> CorrectClassifyTests = tree.ListRules.ClassifyAgain(dataDTTest);

            // Bước 3: Thực hiện xây dựng mô hình ANN với dữ liệu học moi
            // Thực hiện test lại với dữ liệu train
            //khởi tạo các tham số cho mạng
            ANNParameterBUS.HiddenNode = int.Parse(tbxANNHiddenNode.Text);
            ANNParameterBUS.OutputNode = 3;
            ANNParameterBUS.MaxEpoch = int.Parse(tbxMaxLoops.Text);
            ANNParameterBUS.LearningRate = double.Parse(tbxLearningRate.Text);
            ANNParameterBUS.Momentum = double.Parse(tbxMomentum.Text);
            ANNParameterBUS.Bias = double.Parse(tbxBias.Text);

            //Tiến hành train
            BackpropagationNetwork bpNetwork;
            TrainingSet tempTrainingSet = new TrainingSet(strTrainFile, ANNParameterBUS.OutputNode);
            TrainingSet trainSet = new TrainingSet(tempTrainingSet.InputVectorLength, ANNParameterBUS.OutputNode);

            for (int i = 0; i < CorrectClassifyTests.Count; i++)
            {
                int pos = (int)CorrectClassifyTests[i];
                TrainingSample tsp = (TrainingSample)tempTrainingSet[pos];
                trainSet.Add(tsp);
            }

            LinearLayer inputLayer = new LinearLayer(trainSet.InputVectorLength);
            ActivationLayer hidenLayer = null;
            ActivationLayer outputLayer = null;
            switch (cmbActivationFunc.SelectedItem.ToString())
            {
                case "Sigmoid":
                    hidenLayer = new SigmoidLayer(ANNParameterBUS.HiddenNode);
                    outputLayer = new SigmoidLayer(ANNParameterBUS.OutputNode);
                    break;
                case "Tanh":
                    hidenLayer = new TanhLayer(ANNParameterBUS.HiddenNode);
                    outputLayer = new TanhLayer(ANNParameterBUS.OutputNode);
                    break;
                case "Logarithm":
                    hidenLayer = new LogarithmLayer(ANNParameterBUS.HiddenNode);
                    outputLayer = new LogarithmLayer(ANNParameterBUS.OutputNode);
                    break;
                case "Sine":
                    hidenLayer = new SineLayer(ANNParameterBUS.HiddenNode);
                    outputLayer = new SineLayer(ANNParameterBUS.OutputNode);
                    break;
            }
            new BackpropagationConnector(inputLayer, hidenLayer);
            new BackpropagationConnector(hidenLayer, outputLayer);

            bpNetwork = new BackpropagationNetwork(inputLayer, outputLayer);

            bpNetwork.SetLearningRate(ANNParameterBUS.LearningRate);

            bpNetwork.EndEpochEvent += new TrainingEpochEventHandler(
                    delegate(object senderNetwork, TrainingEpochEventArgs args)
                    {
                        tlsProgressBar.Value = (int)(args.TrainingIteration * 100d / ANNParameterBUS.MaxEpoch);
                        Application.DoEvents();
                    });

            bpNetwork.Learn(trainSet, ANNParameterBUS.MaxEpoch);

            // Bước 4: Lưu lại mô hình ANN
            iPos = strTrainFile.LastIndexOf('_');
            string strModelFile = strTrainFile.Remove(iPos + 1) + "model.txt";
            Stream stream = File.Open(strModelFile, FileMode.Create);
            BinaryFormatter bformatter = new BinaryFormatter();
            bformatter.Serialize(stream, bpNetwork);
            stream.Close();
            tlsProgressBar.Value = 0;
        }
        /// <summary>
        /// Phần test cho ANN
        /// </summary>
        private void TestANN(bool isBatchMode)
        {
            string strModelFile = null;
            string strTestFile = null;
            if (isBatchMode)
            {
                strModelFile = _modelFilePath;
                strTestFile = _testFilePath;
            }
            else
            {
                strModelFile = tbxModelFilePath.Text;
                strTestFile = tbxTestFilePath.Text;
            }

            int iPos = strTestFile.LastIndexOf('_');
            string strMutualPath = strTestFile.Remove(iPos + 1);
            string strPredictedFile = strMutualPath + "predict.txt";
            string strStatisticFile = strMutualPath + "statistic.txt";

            // Load model lên
            BackpropagationNetwork bpNetwork;
            Stream stream = File.Open(strModelFile, FileMode.Open);
            BinaryFormatter bformatter = new BinaryFormatter();
            bpNetwork = (BackpropagationNetwork)bformatter.Deserialize(stream);
            stream.Close();

            // Tạo tập mẫu để test
            TrainingSet testSet = new TrainingSet(strTestFile, bpNetwork.OutputLayer.NeuronCount);

            // Ma trận với dòng thứ 1 chứa các giá trị thực và dòng thứ 2 chứa các giá trị dự đoán.
            double[][] dblActual_Forecast = new double[2][];
            dblActual_Forecast[0] = new double[testSet.TrainingSampleCount];
            dblActual_Forecast[1] = new double[testSet.TrainingSampleCount];

            // Thực hiện test
            for (int i = 0; i < testSet.TrainingSampleCount; i++)
            {
                TrainingSample testSample = testSet[i];
                dblActual_Forecast[0][i] = ConverterBUS.Convert2Trend(testSample.OutputVector);

                double[] dblTemp = bpNetwork.Run(testSample.InputVector);
                dblActual_Forecast[1][i] = ConverterBUS.Convert2Trend(dblTemp);
            }

            // Ghi kết quả dự đoán xuống file
            bpNetwork.Write2PredictFile(dblActual_Forecast, strPredictedFile);
            // Ghi kết quả độ chính xác dự đoán được xuống file
            WriteAccurancy2File(strMutualPath + "PerformanceMeasure.txt", dblActual_Forecast[0], dblActual_Forecast[1]);
            // Thực hiện thống kế theo ma trận xu hướng và ghi xuống file
            StatisticTrend2File(strPredictedFile, strStatisticFile);
        }
        private bool SubTestANN_DT(string strTrainFile)
        {
            string strModelFile = null;
            string strTestFile = null;

            int iPos = strTrainFile.LastIndexOf('_');
            strModelFile = strTrainFile.Remove(iPos + 1) + "model.txt";

            iPos = strTrainFile.LastIndexOf('.');
            strTestFile = strTrainFile.Remove(iPos) + "_subtest.txt";

            // Load model lên
            BackpropagationNetwork bpNetwork;
            Stream stream = File.Open(strModelFile, FileMode.Open);
            BinaryFormatter bformatter = new BinaryFormatter();
            bpNetwork = (BackpropagationNetwork)bformatter.Deserialize(stream);
            stream.Close();

            // Tạo tập mẫu để test
            TrainingSet testSet = new TrainingSet(strTestFile, bpNetwork.OutputLayer.NeuronCount);

            // Ma trận với dòng thứ 1 chứa các giá trị thực và dòng thứ 2 chứa các giá trị dự đoán.
            double[][] dblActual_Forecast = new double[2][];
            dblActual_Forecast[0] = new double[testSet.TrainingSampleCount];
            dblActual_Forecast[1] = new double[testSet.TrainingSampleCount];

            // Thực hiện test
            for (int i = 0; i < testSet.TrainingSampleCount; i++)
            {
                TrainingSample testSample = testSet[i];
                dblActual_Forecast[0][i] = ConverterBUS.Convert2Trend(testSample.OutputVector);

                double[] dblTemp = bpNetwork.Run(testSample.InputVector);
                dblActual_Forecast[1][i] = ConverterBUS.Convert2Trend(dblTemp);
            }

            MeasureBUS measureBus = new MeasureBUS();
            double Result = measureBus.CorrectPredictRate((double[])dblActual_Forecast[0], (double[])dblActual_Forecast[1]);
            if (_accDTANNBefore < Result)// lưu lại model tốt nhất
            {
                _accDTANNBefore = Result;
                return true;// Giữa lại bộ tham số
            }
            return false;
        }
 /// <summary>
 /// Creates a new instance of training epoch event arguments
 /// </summary>
 /// <param name="trainingIteration">
 /// Current training iteration
 /// </param>
 /// <param name="trainingSet">
 /// The training set associated with the event
 /// </param>
 public TrainingEpochEventArgs(int trainingIteration, TrainingSet trainingSet)
 {
     this.trainingSet       = trainingSet;
     this.trainingIteration = trainingIteration;
 }
 /// <summary>
 /// Invokes EndEpochEvent
 /// </summary>
 /// <param name="currentIteration">
 /// Current training iteration
 /// </param>
 /// <param name="trainingSet">
 /// Training set which got trained successfully this epoch
 /// </param>
 protected virtual void OnEndEpoch(int currentIteration, TrainingSet trainingSet)
 {
     if (EndEpochEvent != null)
     {
         EndEpochEvent(this, new TrainingEpochEventArgs(currentIteration, trainingSet));
     }
 }
        /// <summary>
        /// Trains the neural network for the given training set (Batch Training)
        /// </summary>
        /// <param name="trainingSet">
        /// The training set to use
        /// </param>
        /// <param name="trainingEpochs">
        /// Number of training epochs. (All samples are trained in some random order, in every
        /// training epoch)
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// if <c>trainingSet</c> is <c>null</c>
        /// </exception>
        /// <exception cref="ArgumentException">
        /// if <c>trainingEpochs</c> is zero or negative
        /// </exception>
        public virtual void Learn(TrainingSet trainingSet, int trainingEpochs)
        {
            // Validate
            Helper.ValidateNotNull(trainingSet, "trainingSet");
            Helper.ValidatePositive(trainingEpochs, "trainingEpochs");
            if ((trainingSet.InputVectorLength != inputLayer.NeuronCount)
                || (trainingMethod == TrainingMethod.Supervised && trainingSet.OutputVectorLength != outputLayer.NeuronCount)
                || (trainingMethod == TrainingMethod.Unsupervised && trainingSet.OutputVectorLength != 0))
            {
                throw new ArgumentException("Invalid training set");
            }

            // Reset isStopping
            isStopping = false;

            // Re-Initialize the network
            Initialize();
            for (int currentIteration = 0; currentIteration < trainingEpochs; currentIteration++)
            {
                int[] randomOrder = Helper.GetRandomOrder(trainingSet.TrainingSampleCount);
                // Beginning a new training epoch
                OnBeginEpoch(currentIteration, trainingSet);

                // Check for Jitter Epoch
                if (jitterEpoch > 0 && currentIteration % jitterEpoch == 0)
                {
                    for (int i = 0; i < connectors.Count; i++)
                    {
                        connectors[i].Jitter(jitterNoiseLimit);
                    }
                }
                for (int index = 0; index < trainingSet.TrainingSampleCount; index++)
                {
                    TrainingSample randomSample = trainingSet[randomOrder[index]];

                    // Learn a random training sample
                    OnBeginSample(currentIteration, randomSample);
                    LearnSample(trainingSet[randomOrder[index]], currentIteration, trainingEpochs);
                    OnEndSample(currentIteration, randomSample);

                    // Check if we need to stop
                    if (isStopping) { isStopping = false; return; }
                }
                // Training Epoch successfully complete
                OnEndEpoch(currentIteration, trainingSet);

                // Check if we need to stop
                if (isStopping) { isStopping = false; return; }
            }
        }