Beispiel #1
0
        /*
         * /// <summary>
         * /// Copy all values from another solution
         * /// </summary>
         * /// <param name="sourceSolution">The source to copy from</param>
         * public void Load(SVM sourceSolution)
         * {
         *  dimension = sourceSolution.dimension;
         *  alphaList = new float[dimension];
         *  for (int i = 0; i < dimension; i++)
         *  {
         *      alphaList[i] = sourceSolution.alphaList[i];
         *  }
         *  b = sourceSolution.b;
         * }
         */

        /// <summary>
        /// Copy all values from another solution
        /// </summary>
        /// <param name="FileName">File containing alpha's data</param>
        public void Load(string FileName)
        {
            DataSet d = new DataSet();

            d.ReadXml(FileName);
            DataTable t = d.Tables["Solution"];

            dimension = t.Rows.Count;


            //Configuration
            DataTable TblCfg = d.Tables["Config"];

            float valC, valTol; int valKernel, valMaxP;

            valC      = (float)((double)TblCfg.Rows[0]["dblValues"]);
            valKernel = (int)((double)TblCfg.Rows[1]["dblValues"]);
            valTol    = (float)((double)TblCfg.Rows[2]["dblValues"]);
            valMaxP   = (int)((double)TblCfg.Rows[3]["dblValues"]);
            this.b    = (float)((double)TblCfg.Rows[4]["dblValues"]);
            float Lambda = (float)((double)TblCfg.Rows[5]["dblValues"]);
            int   xDim   = (int)((double)TblCfg.Rows[6]["dblValues"]);


            //Reads classifications
            DataTable TblClassif = d.Tables["Classifications"];

            alphaList   = new List <float>();
            TrainingSet = new TrainingSet();

            for (int i = 0; i < dimension; i++)
            {
                TrainingSet.addTrainingUnit(new TrainingUnit(new float[xDim], -1));
            }

            for (int i = 0; i < dimension; i++)
            {
                alphaList.Add((float)((double)t.Rows[i]["dblValues"]));
                TrainingSet.trainingArray[i].y = (float)((double)TblClassif.Rows[i]["dblValues"]) > 0 ? 1 : -1;
            }

            //Reads training set
            //Creates datatables for training examples
            DataTable Tbl = d.Tables["Examples"];

            for (int i = 0; i < dimension; i++)
            {
                for (int j = 0; j < xDim; j++)
                {
                    TrainingSet.trainingArray[i].xVector[j] = (float)((double)Tbl.Rows[j + i * xDim]["dblValues"]);
                }
            }

            this.ProblemCfg = new ProblemConfig(Lambda, valC, valTol, valMaxP, (ProblemConfig.KernelType)valKernel);

            if (OpenCLTemplate.CLCalc.CLAcceleration == OpenCLTemplate.CLCalc.CLAccelerationType.UsingCL)
            {
                this.WriteToDevice();
            }
        }
Beispiel #2
0
        /// <summary>Adds training units to a set from a file</summary>
        /// <param name="filename">File containing features</param>
        /// <param name="TrSet">Training set to be populated</param>
        private void FillTrainingSet(string filename, TrainingSet TrSet)
        {
            string sepdec = (1.5).ToString().Substring(1, 1);

            using (StreamReader sr = new StreamReader(filename))
            {
                string line;

                line = sr.ReadLine();
                int n = int.Parse(line);
                line = sr.ReadLine();
                int dim = (int)Math.Sqrt(double.Parse(line));

                for (int i = 0; i < n; i++)
                {
                    line = sr.ReadLine().Replace(".", sepdec);
                    string[] s = line.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
                    float[]  x = new float[364];
                    float    y;

                    for (int j = 0; j < s.Length - 1; j++)
                    {
                        x[j] = float.Parse(s[j]);
                    }

                    y = float.Parse(s[s.Length - 1]);

                    TrSet.addTrainingUnit(new TrainingUnit(x, y));

                    /*
                     * Features Haar
                     * [04:05:53] Edmundo ITA05(FOX.Howler): 1,1
                     * [04:05:57] Edmundo ITA05(FOX.Howler): 7,4
                     * [04:06:55] Edmundo ITA05(FOX.Howler): new Rectangle(1, 1, 7, 4)
                     * [04:07:06] Edmundo ITA05(FOX.Howler): 7 x 4
                     * [04:08:15] Edmundo ITA05(FOX.Howler): new Rectangle(11, 4, 7, 4)
                     * [04:08:24] Edmundo ITA05(FOX.Howler): divide por 7*4
                     * [04:09:04] Edmundo ITA05(FOX.Howler): subtrai da área do Rect(8, 1, 3, 4)
                     * [04:09:13] Edmundo ITA05(FOX.Howler): dividido pela 3 *4
                     *
                     *
                     *
                     * [04:05:53] Edmundo ITA05(FOX.Howler): 1,1
                     * [04:05:57] Edmundo ITA05(FOX.Howler): 7,4
                     * [04:06:55] Edmundo ITA05(FOX.Howler): new Rectangle(1, 1, 7, 4)
                     * [04:07:06] Edmundo ITA05(FOX.Howler): 7 x 4
                     * [04:08:15] Edmundo ITA05(FOX.Howler): new Rectangle(11, 4, 7, 4)
                     * [04:08:24] Edmundo ITA05(FOX.Howler): divide por 7*4
                     * [04:09:04] Edmundo ITA05(FOX.Howler): subtrai da área do Rect(8, 1, 3, 4)
                     * [04:09:13] Edmundo ITA05(FOX.Howler): dividido pela 3 *4
                     * [04:13:38] Edmundo ITA05(FOX.Howler): ((1,6,5,5) + (13,6,5,5)) / 2 - (7,6,5,6)
                     *
                     *
                     * [04:17:15] Edmundo ITA05(FOX.Howler): (1,1,17,5) - (1,6,17,8) dividir pela area
                     */
                }
            }
        }
 /// <summary>Extracts a cross validation set from a given set</summary>
 /// <param name="Set">Set to extract cross validation from</param>
 /// <param name="CrossValidationSetPercent">Percentage of elements to extract</param>
 public static TrainingSet GetCrossValidationSet(TrainingSet Set, float CrossValidationSetPercent)
 {
     TrainingSet CrossValidationSet = new TrainingSet();
     int nCrossSet = (int)(CrossValidationSetPercent * (float)Set.getN);
     Random rnd = new Random();
     for (int i = 0; i < nCrossSet; i++)
     {
         int ind = rnd.Next(0, Set.trainingArray.Count - 1);
         TrainingUnit u = Set.trainingArray[ind];
         Set.trainingArray.Remove(u);
         CrossValidationSet.addTrainingUnit(u);
     }
     return CrossValidationSet;
 }
        /// <summary>Extracts a cross validation set from a given set</summary>
        /// <param name="Set">Set to extract cross validation from</param>
        /// <param name="CrossValidationSetPercent">Percentage of elements to extract</param>
        public static TrainingSet GetCrossValidationSet(TrainingSet Set, float CrossValidationSetPercent)
        {
            TrainingSet CrossValidationSet = new TrainingSet();
            int         nCrossSet          = (int)(CrossValidationSetPercent * (float)Set.getN);
            Random      rnd = new Random();

            for (int i = 0; i < nCrossSet; i++)
            {
                int          ind = rnd.Next(0, Set.trainingArray.Count - 1);
                TrainingUnit u   = Set.trainingArray[ind];
                Set.trainingArray.Remove(u);
                CrossValidationSet.addTrainingUnit(u);
            }
            return(CrossValidationSet);
        }
Beispiel #5
0
        /// <summary>Adds a new self training example</summary>
        public void AddSelfTraining(int[] sbFrames, int faceIndex, Bitmap bmp)
        {
            if (SelfTSet == null)
            {
                SelfTSet = new TrainingSet();
            }
            float[] subF = new float[(sbFrames.Length / 3) * 364];

            ExtractFeatures(sbFrames, subF, bmp);

            for (int i = 0; i < sbFrames.Length / 3; i++)
            {
                float[] x = new float[364];

                for (int k = 0; k < 364; k++)
                {
                    x[k] = subF[k + i * 364];
                }

                TrainingUnit tu = new TrainingUnit(x, i == faceIndex ? 1.0f : -1.0f);
                SelfTSet.addTrainingUnit(tu);
            }
        }
        /// <summary>Adds training units to a set from a file</summary>
        /// <param name="filename">File containing features</param>
        /// <param name="TrSet">Training set to be populated</param>
        private void FillTrainingSet(string filename, TrainingSet TrSet)
        {
            string sepdec = (1.5).ToString().Substring(1, 1);
            using (StreamReader sr = new StreamReader(filename))
            {
                string line;

                line = sr.ReadLine();
                int n = int.Parse(line);
                line = sr.ReadLine();
                int dim = (int)Math.Sqrt(double.Parse(line));

                for (int i = 0; i < n; i++)
                {
                    line = sr.ReadLine().Replace(".", sepdec);
                    string[] s = line.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
                    float[] x = new float[364];
                    float y;

                    for (int j = 0; j < s.Length - 1; j++) x[j] = float.Parse(s[j]);

                    y = float.Parse(s[s.Length - 1]);

                    TrSet.addTrainingUnit(new TrainingUnit(x, y));

                    /*
                     * Features Haar
                     * [04:05:53] Edmundo ITA05(FOX.Howler): 1,1
            [04:05:57] Edmundo ITA05(FOX.Howler): 7,4
            [04:06:55] Edmundo ITA05(FOX.Howler): new Rectangle(1, 1, 7, 4)
            [04:07:06] Edmundo ITA05(FOX.Howler): 7 x 4
            [04:08:15] Edmundo ITA05(FOX.Howler): new Rectangle(11, 4, 7, 4)
            [04:08:24] Edmundo ITA05(FOX.Howler): divide por 7*4
            [04:09:04] Edmundo ITA05(FOX.Howler): subtrai da área do Rect(8, 1, 3, 4)
            [04:09:13] Edmundo ITA05(FOX.Howler): dividido pela 3 *4
                     *
                     *
                     *
                     * [04:05:53] Edmundo ITA05(FOX.Howler): 1,1
            [04:05:57] Edmundo ITA05(FOX.Howler): 7,4
            [04:06:55] Edmundo ITA05(FOX.Howler): new Rectangle(1, 1, 7, 4)
            [04:07:06] Edmundo ITA05(FOX.Howler): 7 x 4
            [04:08:15] Edmundo ITA05(FOX.Howler): new Rectangle(11, 4, 7, 4)
            [04:08:24] Edmundo ITA05(FOX.Howler): divide por 7*4
            [04:09:04] Edmundo ITA05(FOX.Howler): subtrai da área do Rect(8, 1, 3, 4)
            [04:09:13] Edmundo ITA05(FOX.Howler): dividido pela 3 *4
            [04:13:38] Edmundo ITA05(FOX.Howler): ((1,6,5,5) + (13,6,5,5)) / 2 - (7,6,5,6)
                     *
                     *
                     * [04:17:15] Edmundo ITA05(FOX.Howler): (1,1,17,5) - (1,6,17,8) dividir pela area
                     */

                }
            }
        }
Beispiel #7
0
        /// <summary>Trains current SVM with cross-validation, adjusting kernel parameter lambda and box parameter C. Returns best performance so far</summary>
        /// <param name="CrossValidationSetPercent">Percentage of training examples that should be used as cross validation set</param>
        /// <param name="lambdaSet">Values of lambda to try</param>
        /// <param name="CSet">Values of c to try</param>
        public float TrainWithCrossValidation(float CrossValidationSetPercent, float[] lambdaSet, float[] CSet)
        {
            if (alphaList == null || alphaList.Count != TrainingSet.getN)
            {
                //Problem changed, previous values dont make sense
                initializeWithZeros();
                CrossValParams = null;
            }

            #region Constructs cross validation set

            TrainingSet CrossValidationSet = new TrainingSet();
            int nCrossSet = (int)(CrossValidationSetPercent * (float)this.TrainingSet.getN);
            Random rnd = new Random();
            for (int i = 0; i < nCrossSet; i++)
            {
                int ind = rnd.Next(0, this.TrainingSet.trainingArray.Count - 1);
                TrainingUnit u = this.TrainingSet.trainingArray[ind];
                this.TrainingSet.trainingArray.Remove(u);
                CrossValidationSet.addTrainingUnit(u);
            }

            #endregion

            #region Loops through lambdas and Cs and finds maximum crossvalidation

            foreach (float _lambda in lambdaSet)
            {
                this.ProblemCfg.lambda = _lambda;

                this.initializeWithZeros();
                PreComputeKernels();

                foreach (float _c in CSet)
                {
                    this.ProblemCfg.c = _c;

                    //ProblemSolver.solveSMOStartingFromPreviousSolution(this);
                    ProblemSolver.solveSMOStartingFromZero(this);

                    float performance = this.GetHitRate(CrossValidationSet);

                    if (CrossValParams == null) CrossValParams = new float[3];

                    if (performance > CrossValParams[0])
                    {
                        CrossValParams[0] = performance;
                        CrossValParams[1] = _lambda;
                        CrossValParams[2] = _c;
                    }
                }
            }

            #endregion

            #region Trains with best parameters so far

            this.ProblemCfg.lambda = CrossValParams[1];
            this.ProblemCfg.c = CrossValParams[2];
            this.Train();

            #endregion

            return CrossValParams[0];
        }
Beispiel #8
0
        /// <summary>Attempts to pre-calibrate configuration parameters.
        /// Finds an alpha that enhances similarities between positive examples
        /// and reduces similarities between positive and negative examples.
        /// Assumes that decreasing lambda increases kernel match.
        /// </summary>
        /// <param name="tolPositive">Positive kernels average should be greater than tolPositive</param>
        /// <param name="tolNegative">Negative kernels average should be lesser than tolNegative</param>
        public void PreCalibrateCfg(float tolPositive, float tolNegative)
        {
            #region Checks if there are positive and negative examples
            bool posSamples = false; bool negSamples = false;
            for (int i = 0; i < TrainingSet.trainingArray.Count; i++)
            {
                if (TrainingSet.trainingArray[i].y > 0) posSamples = true;
                if (TrainingSet.trainingArray[i].y < 0) negSamples = true;
                if (posSamples && negSamples) i = TrainingSet.trainingArray.Count;
            }
            if ((!posSamples) || (!negSamples)) throw new Exception("Training set must contain positive and negative samples");
            #endregion

            Random rnd = new Random();
            int nSet = (int)(20 * Math.Log(TrainingSet.getN, 2));

            TrainingSet PositiveExamples1 = new TrainingSet();
            TrainingSet PositiveExamples2 = new TrainingSet();
            TrainingSet NegativeExamples = new TrainingSet();

            //Kernel average for positive and negative samples
            float positiveAvg = 0, negativeAvg = 0;
            float invN = 1 / (float)nSet;
            int count = 0;

            float bestLambda = ProblemCfg.lambda;
            float maxPosNegAvg = -1.0f;

            while ((positiveAvg <= tolPositive || negativeAvg >= tolNegative) && count < nSet)
            {
                //Populates training sets
                PositiveExamples1.trainingArray.Clear();
                PositiveExamples2.trainingArray.Clear();
                NegativeExamples.trainingArray.Clear();
                while (PositiveExamples1.getN < nSet || PositiveExamples2.getN < nSet || NegativeExamples.getN < nSet)
                {
                    TrainingUnit tu = TrainingSet.trainingArray[rnd.Next(TrainingSet.trainingArray.Count - 1)];
                    if (tu.y > 0 && PositiveExamples1.getN < nSet)
                        PositiveExamples1.addTrainingUnit(tu);
                    else if (tu.y > 0 && PositiveExamples2.getN < nSet)
                        PositiveExamples2.addTrainingUnit(tu);

                    if (tu.y < 0 && NegativeExamples.getN < nSet) NegativeExamples.addTrainingUnit(tu);
                }

                count++;

                positiveAvg = 0;
                negativeAvg = 0;
                for (int i = 0; i < nSet; i++)
                {
                    positiveAvg += ProblemSolver.calculateSingleKernel(PositiveExamples1.trainingArray[i], PositiveExamples2.trainingArray[i], this);
                    negativeAvg += ProblemSolver.calculateSingleKernel(PositiveExamples1.trainingArray[i], NegativeExamples.trainingArray[i], this);
                }
                positiveAvg *= invN;
                negativeAvg *= invN;

                if (maxPosNegAvg < positiveAvg - negativeAvg)
                {
                    bestLambda = ProblemCfg.lambda;
                    maxPosNegAvg = positiveAvg - negativeAvg;
                }

                //Desired: positiveAvg=1, negativeAvg = 0
                if (positiveAvg <= tolPositive) this.ProblemCfg.lambda *= 0.15f;
                else if (negativeAvg >= tolNegative) this.ProblemCfg.lambda *= 1.2f;
            }
            ProblemCfg.lambda = bestLambda;
        }
Beispiel #9
0
        /*
        /// <summary>
        /// Copy all values from another solution
        /// </summary>
        /// <param name="sourceSolution">The source to copy from</param>
        public void Load(SVM sourceSolution)
        {
            dimension = sourceSolution.dimension;
            alphaList = new float[dimension];
            for (int i = 0; i < dimension; i++)
            {
                alphaList[i] = sourceSolution.alphaList[i];
            }
            b = sourceSolution.b;
        }
        */
        /// <summary>
        /// Copy all values from another solution
        /// </summary>
        /// <param name="FileName">File containing alpha's data</param>
        public void Load(string FileName)
        {
            DataSet d = new DataSet();
            d.ReadXml(FileName);
            DataTable t = d.Tables["Solution"];
            dimension = t.Rows.Count;

            //Configuration
            DataTable TblCfg = d.Tables["Config"];

            float valC, valTol; int valKernel, valMaxP;

            valC = (float)((double)TblCfg.Rows[0]["dblValues"]);
            valKernel = (int)((double)TblCfg.Rows[1]["dblValues"]);
            valTol = (float)((double)TblCfg.Rows[2]["dblValues"]);
            valMaxP = (int)((double)TblCfg.Rows[3]["dblValues"]);
            this.b = (float)((double)TblCfg.Rows[4]["dblValues"]);
            float Lambda = (float)((double)TblCfg.Rows[5]["dblValues"]);
            int xDim = (int)((double)TblCfg.Rows[6]["dblValues"]);

            //Reads classifications
            DataTable TblClassif = d.Tables["Classifications"];

            alphaList = new List<float>();
            TrainingSet = new TrainingSet();

            for (int i = 0; i < dimension; i++)
            {
                TrainingSet.addTrainingUnit(new TrainingUnit(new float[xDim], -1));
            }

            for (int i = 0; i < dimension; i++)
            {
                alphaList.Add((float)((double)t.Rows[i]["dblValues"]));
                TrainingSet.trainingArray[i].y = (float)((double)TblClassif.Rows[i]["dblValues"]) > 0 ? 1 : -1;
            }

            //Reads training set
            //Creates datatables for training examples
            DataTable Tbl = d.Tables["Examples"];
            for (int i = 0; i < dimension; i ++)
            {
                for (int j = 0; j < xDim; j++)
                {
                    TrainingSet.trainingArray[i].xVector[j] = (float)((double)Tbl.Rows[j + i*xDim]["dblValues"]);
                }
            }

            this.ProblemCfg = new ProblemConfig(Lambda, valC, valTol, valMaxP, (ProblemConfig.KernelType)valKernel);

            if (OpenCLTemplate.CLCalc.CLAcceleration == OpenCLTemplate.CLCalc.CLAccelerationType.UsingCL)
            {
                this.WriteToDevice();
            }
        }
Beispiel #10
0
        /// <summary>Attempts to pre-calibrate configuration parameters.
        /// Finds an alpha that enhances similarities between positive examples
        /// and reduces similarities between positive and negative examples.
        /// Assumes that decreasing lambda increases kernel match.
        /// </summary>
        /// <param name="tolPositive">Positive kernels average should be greater than tolPositive</param>
        /// <param name="tolNegative">Negative kernels average should be lesser than tolNegative</param>
        public void PreCalibrateCfg(float tolPositive, float tolNegative)
        {
            #region Checks if there are positive and negative examples
            bool posSamples = false; bool negSamples = false;
            for (int i = 0; i < TrainingSet.trainingArray.Count; i++)
            {
                if (TrainingSet.trainingArray[i].y > 0)
                {
                    posSamples = true;
                }
                if (TrainingSet.trainingArray[i].y < 0)
                {
                    negSamples = true;
                }
                if (posSamples && negSamples)
                {
                    i = TrainingSet.trainingArray.Count;
                }
            }
            if ((!posSamples) || (!negSamples))
            {
                throw new Exception("Training set must contain positive and negative samples");
            }
            #endregion

            Random rnd  = new Random();
            int    nSet = (int)(20 * Math.Log(TrainingSet.getN, 2));

            TrainingSet PositiveExamples1 = new TrainingSet();
            TrainingSet PositiveExamples2 = new TrainingSet();
            TrainingSet NegativeExamples  = new TrainingSet();

            //Kernel average for positive and negative samples
            float positiveAvg = 0, negativeAvg = 0;
            float invN  = 1 / (float)nSet;
            int   count = 0;

            float bestLambda   = ProblemCfg.lambda;
            float maxPosNegAvg = -1.0f;

            while ((positiveAvg <= tolPositive || negativeAvg >= tolNegative) && count < nSet)
            {
                //Populates training sets
                PositiveExamples1.trainingArray.Clear();
                PositiveExamples2.trainingArray.Clear();
                NegativeExamples.trainingArray.Clear();
                while (PositiveExamples1.getN < nSet || PositiveExamples2.getN < nSet || NegativeExamples.getN < nSet)
                {
                    TrainingUnit tu = TrainingSet.trainingArray[rnd.Next(TrainingSet.trainingArray.Count - 1)];
                    if (tu.y > 0 && PositiveExamples1.getN < nSet)
                    {
                        PositiveExamples1.addTrainingUnit(tu);
                    }
                    else if (tu.y > 0 && PositiveExamples2.getN < nSet)
                    {
                        PositiveExamples2.addTrainingUnit(tu);
                    }

                    if (tu.y < 0 && NegativeExamples.getN < nSet)
                    {
                        NegativeExamples.addTrainingUnit(tu);
                    }
                }

                count++;

                positiveAvg = 0;
                negativeAvg = 0;
                for (int i = 0; i < nSet; i++)
                {
                    positiveAvg += ProblemSolver.calculateSingleKernel(PositiveExamples1.trainingArray[i], PositiveExamples2.trainingArray[i], this);
                    negativeAvg += ProblemSolver.calculateSingleKernel(PositiveExamples1.trainingArray[i], NegativeExamples.trainingArray[i], this);
                }
                positiveAvg *= invN;
                negativeAvg *= invN;

                if (maxPosNegAvg < positiveAvg - negativeAvg)
                {
                    bestLambda   = ProblemCfg.lambda;
                    maxPosNegAvg = positiveAvg - negativeAvg;
                }

                //Desired: positiveAvg=1, negativeAvg = 0
                if (positiveAvg <= tolPositive)
                {
                    this.ProblemCfg.lambda *= 0.15f;
                }
                else if (negativeAvg >= tolNegative)
                {
                    this.ProblemCfg.lambda *= 1.2f;
                }
            }
            ProblemCfg.lambda = bestLambda;
        }
Beispiel #11
0
        /// <summary>Trains current SVM with cross-validation, adjusting kernel parameter lambda and box parameter C. Returns best performance so far</summary>
        /// <param name="CrossValidationSetPercent">Percentage of training examples that should be used as cross validation set</param>
        /// <param name="lambdaSet">Values of lambda to try</param>
        /// <param name="CSet">Values of c to try</param>
        public float TrainWithCrossValidation(float CrossValidationSetPercent, float[] lambdaSet, float[] CSet)
        {
            if (alphaList == null || alphaList.Count != TrainingSet.getN)
            {
                //Problem changed, previous values dont make sense
                initializeWithZeros();
                CrossValParams = null;
            }

            #region Constructs cross validation set

            TrainingSet CrossValidationSet = new TrainingSet();
            int         nCrossSet          = (int)(CrossValidationSetPercent * (float)this.TrainingSet.getN);
            Random      rnd = new Random();
            for (int i = 0; i < nCrossSet; i++)
            {
                int          ind = rnd.Next(0, this.TrainingSet.trainingArray.Count - 1);
                TrainingUnit u   = this.TrainingSet.trainingArray[ind];
                this.TrainingSet.trainingArray.Remove(u);
                CrossValidationSet.addTrainingUnit(u);
            }

            #endregion

            #region Loops through lambdas and Cs and finds maximum crossvalidation

            foreach (float _lambda in lambdaSet)
            {
                this.ProblemCfg.lambda = _lambda;

                this.initializeWithZeros();
                PreComputeKernels();

                foreach (float _c in CSet)
                {
                    this.ProblemCfg.c = _c;


                    //ProblemSolver.solveSMOStartingFromPreviousSolution(this);
                    ProblemSolver.solveSMOStartingFromZero(this);

                    float performance = this.GetHitRate(CrossValidationSet);

                    if (CrossValParams == null)
                    {
                        CrossValParams = new float[3];
                    }

                    if (performance > CrossValParams[0])
                    {
                        CrossValParams[0] = performance;
                        CrossValParams[1] = _lambda;
                        CrossValParams[2] = _c;
                    }
                }
            }

            #endregion

            #region Trains with best parameters so far

            this.ProblemCfg.lambda = CrossValParams[1];
            this.ProblemCfg.c      = CrossValParams[2];
            this.Train();

            #endregion

            return(CrossValParams[0]);
        }