/// <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>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]; }
/// <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; }
/* /// <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 (OpenTKWrapper.CLCalc.CLAcceleration == OpenTKWrapper.CLCalc.CLAccelerationType.UsingCL) { this.WriteToDevice(); } }
/// <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 */ } } }