public static float calculateSingleKernel(TrainingUnit xi, TrainingUnit xj,SVM ProblemSolution) { ProblemConfig problemConfig = ProblemSolution.ProblemCfg; // Vectors size check //if (xi.getDimension() != xj.getDimension()) return 0; // Linear: u'*v (inner product) if (problemConfig.kernelType == ProblemConfig.KernelType.Linear) { float sum = 0; for (int i = 0; i < xi.getDimension(); i++) { sum += xi.xVector[i] * xj.xVector[i]; } return sum; } // Radial basis function: exp(-gamma*|u-v|^2) if (problemConfig.kernelType == ProblemConfig.KernelType.RBF) { // Gamma is, by choice, 1 / (number of features). float sum = 0, temp; for (int i = 0; i < xi.getDimension(); i++) { temp = xi.xVector[i] - xj.xVector[i]; sum += temp * temp; } return (float)Math.Exp(-ProblemSolution.ProblemCfg.lambda * sum); } return 0; }
/// <summary>Classifies a training unit with a float. The bigger, the more positive the sample. Values greater than zero /// are assumed to be positive samples</summary> /// <param name="Sample">Sample to be classified</param> public float ClassificationValue(TrainingUnit Sample) { if (OpenTKWrapper.CLCalc.CLAcceleration == OpenTKWrapper.CLCalc.CLAccelerationType.UsingCL) { return (CLpredictOutput(this, Sample)); } else return (ProblemSolver.predictOutput(this, Sample)); }
/// <summary>Adds a new training unit to the set</summary> /// <param name="newTrainingUnit">New training unit to add</param> public void addTrainingUnit(TrainingUnit newTrainingUnit) { if (p != 0) { if (p == newTrainingUnit.getDimension()) { trainingArray.Add(newTrainingUnit); } else { // Invalid entry, not equal in size to the others training units // Do nothing } } else // The first training set is being added { p = newTrainingUnit.getDimension(); trainingArray.Add(newTrainingUnit); } }
/// <summary>Classifies a sample within a given category even if all SVMs predict it doesn`t belong to any.</summary> /// <param name="Sample">Sample to classify</param> /// <param name="maxVal">Maximum classification value found</param> public float Classify(TrainingUnit Sample, out float maxVal) { sample = Sample; if (ClassificationValues == null) ClassificationValues = new float[SVMs.Count]; for (int i = 0; i < SVMs.Count; i++) Classify(i); //Finds maximum value maxVal = ClassificationValues[0]; float classification = Classifications[0]; for (int i = 1; i < ClassificationValues.Length; i++) { if (ClassificationValues[i] > maxVal) { maxVal = ClassificationValues[i]; classification = Classifications[i]; } } return classification; }
/// <summary>Classifies a training unit as positive or negative (true or false)</summary> /// <param name="Sample">Sample to be classified</param> public bool Classify(TrainingUnit Sample) { if (OpenTKWrapper.CLCalc.CLAcceleration == OpenTKWrapper.CLCalc.CLAccelerationType.UsingCL) { return (CLpredictOutput(this, Sample)>=0); } else return (ProblemSolver.predictOutput(this, Sample)>=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> /// Predicts the output of a single entry, given a previous problem, solution and correspondent training set /// </summary> /// <param name="problemSolution">Correspondent problem solution</param> /// <param name="untrainedUnit">Input features from which the output will be predicted</param> /// <returns>The y classification (true/false = positive/negative)</returns> public static float predictOutput(SVM problemSolution, TrainingUnit untrainedUnit) { TrainingSet trainingSet = problemSolution.TrainingSet; ProblemConfig problemConfig = problemSolution.ProblemCfg; // F(x) = sum + b // sum = summation of alpha_i * y_i * kernel(untrained unit, i) for all i in the training set float sum = 0; for (int i = 0; i < trainingSet.getN; i++) { if (trainingSet.trainingArray[i].y > 0) sum += problemSolution.alphaList[i] * calculateSingleKernel(trainingSet.trainingArray[i], untrainedUnit, problemSolution); else sum -= problemSolution.alphaList[i] * calculateSingleKernel(trainingSet.trainingArray[i], untrainedUnit, problemSolution); } return sum + problemSolution.b; }
/// <summary> /// Predicts the output of a single entry, given a previous problem, solution and correspondent training set /// </summary> /// <param name="problemSolution">Correspondent problem solution</param> /// <param name="untrainedUnit">Input features from which the output will be predicted</param> /// <returns>The y classification (true/false = positive/negative)</returns> public static float CLpredictOutput(SVM problemSolution, TrainingUnit untrainedUnit) { TrainingSet trainingSet = problemSolution.TrainingSet; ProblemConfig problemConfig = problemSolution.ProblemCfg; #region Compute kernel float[] K = new float[problemSolution.TrainingSet.getN]; CLCalc.Program.MemoryObject[] args = new CLCalc.Program.MemoryObject[] { problemSolution.CLTrainingFeatures, problemSolution.CLXVecLen, problemSolution.CLSample, problemSolution.CLKernelValues, problemSolution.CLLambda }; for (int j = 0; j < untrainedUnit.xVector.Length; j++) problemSolution.HostSample[j] = untrainedUnit.xVector[j]; problemSolution.CLSample.WriteToDevice(problemSolution.HostSample); lock (CLResource) { kernelComputeKernelRBF.Execute(args, problemSolution.TrainingSet.getN); problemSolution.CLKernelValues.ReadFromDeviceTo(K); } #endregion // F(x) = sum + b // sum = summation of alpha_i * y_i * kernel(untrained unit, i) for all i in the training set float sum = 0; for (int i = 0; i < trainingSet.getN; i++) { if (trainingSet.trainingArray[i].y > 0) sum += problemSolution.alphaList[i] * K[i]; else sum -= problemSolution.alphaList[i] * K[i]; } return sum + problemSolution.b; }
/// <summary>Attempts to classify a sample within a given category. Returns -1 if no classification was achieved.</summary> public float ClassifyWithRejection(TrainingUnit Sample) { float maxVal; float resp = Classify(Sample, out maxVal); if (maxVal >= 0) return resp; else return -1.0f; }