我正在使用OpenFace Windows二进制文件和Accord .NET来创建基于Python的this人脸识别系统的C#版本。
OpenFace完成了大部分工作,我只需要训练一个SVM来对未知面部进行分类(概率),使用已知面作为输出类。
A" face"在此上下文中是一个充满面部测量值的CSV文件。理论上很简单。由于这似乎是best done使用one-vs-rest方法,因此我尝试使用API中的MulticlassSupportVectorMachine example。
然而,据我所知,该示例使用其训练数据中的相同输入作为测试输入,因此我不确定训练结束和测试开始的确切位置,但我认为它在调用.Decide()
的行这是我现在正在尝试的事情......
- 创建一些简单的容器类
public class Result
{
public int[] predictions;
public double[][] scores;
public double[][] probability;
public double error;
public double loss;
}
public class KnownFaces
{
public double[][] input;
public int[] output;
}
public class UnknownFaces
{
public double[][] input;
}`
抓取已知面孔的编码
// Load encoding from CSV
double[] aiden1Encoding = RecognizeFace.GetEncodingFromCSV(Application.StartupPath + @"\of\processed\aiden1.csv");
double[] aiden2Encoding = RecognizeFace.GetEncodingFromCSV(Application.StartupPath + @"\of\processed\aiden2.csv");
...
double[] kate1Encoding = RecognizeFace.GetEncodingFromCSV(Application.StartupPath + @"\of\processed\kate1.csv");
double[] kate2Encoding = RecognizeFace.GetEncodingFromCSV(Application.StartupPath + @"\of\processed\kate2.csv");
...
//... etc (about 20 pictures of each person)
抓取未知面孔的编码
double[] who1Encoding = RecognizeFace.GetEncodingFromCSV(Application.StartupPath + @"\of\processed\who1.csv");
double[] who2Encoding = RecognizeFace.GetEncodingFromCSV(Application.StartupPath + @"\of\processed\who2.csv");
...
将所有这些放入我的容器中
double[][] knownFacesFeatures = {
aiden1Encoding, aiden2Encoding, ...
kate1Encoding, kate2Encoding, ...
};
double[][] unknownFacesFeatures = {
who1Encoding, who2Encoding ...
};
RecognizeFace.KnownFaces knownFaces = new RecognizeFace.KnownFaces();
knownFaces.input = knownFacesFeatures;
RecognizeFace.UnknownFaces unknownFaces = new RecognizeFace.UnknownFaces();
unknownFaces.input = unknownFacesFeatures;
对已知面部的输出进行分类
knownFaces.output = new int[]
{
0,0,0 ... // Aiden
1,1,1 ... // Kate
...
};
获得结果:
RecognizeFace.Result r = RecognizeFace.RecognizeFaces(knownFaces, unknownFaces);
...
public static Result RecognizeFaces(KnownFaces knownFaces, UnknownFaces unknownFaces)
{
Result toReturn = new Result();
// Create the multi-class learning algorithm for the machine
var teacher = new MulticlassSupportVectorLearning<Gaussian>()
{
// Configure the learning algorithm to use SMO to train the
// underlying SVMs in each of the binary class subproblems.
Learner = (param) => new SequentialMinimalOptimization<Gaussian>()
{
// Estimate a suitable guess for the Gaussian kernel's parameters.
// This estimate can serve as a starting point for a grid search.
UseKernelEstimation = true
}
};
// Learn a machine
var machine = teacher.Learn(knownFaces.input, knownFaces.output);
// Create the multi-class learning algorithm for the machine
var calibration = new MulticlassSupportVectorLearning<Gaussian>()
{
Model = machine, // We will start with an existing machine
// Configure the learning algorithm to use Platt's calibration
Learner = (param) => new ProbabilisticOutputCalibration<Gaussian>()
{
Model = param.Model // Start with an existing machine
}
};
// Configure parallel execution options
calibration.ParallelOptions.MaxDegreeOfParallelism = 1;
// Learn a machine
calibration.Learn(knownFaces.input, knownFaces.output);
// Obtain class predictions for each sample
int[] predicted = machine.Decide(unknownFaces.input);
toReturn.predictions = predicted;
// Get class scores for each sample
double[][] scores = machine.Scores(unknownFaces.input);
toReturn.scores = scores;
// Get log-likelihoods (should be same as scores)
double[][] logl = machine.LogLikelihoods(unknownFaces.input);
// Get probability for each sample
double[][] prob = machine.Probabilities(unknownFaces.input);
toReturn.probability = prob;
//Compute classification error using mean accuracy (mAcc)
//double error = new HammingLoss(knownFaces.output).Loss(predicted);
//double loss = new CategoryCrossEntropyLoss(knownFaces.output).Loss(prob);
//toReturn.error = error;
//toReturn.loss = loss;
return toReturn;
}
问题是,如果我取消注释错误/丢失行,我会得到一个例外,
System.IndexOutOfRangeException: Index was outside the bounds of the array.
at Accord.Math.Optimization.Losses.HammingLoss.Loss(Int32[] actual)
at NETFaceRecognition.RecognizeFace.RecognizeFaces(KnownFaces knownFaces, UnknownFaces unknownFaces)
如果我把它们遗漏,那么代码就会运行......并且不起作用。如果我迭代int []预测,我会得到完全错误的结果(通常):
Unknown Person #1's class: 2 Expected: 3 (Lena)
Unknown Person #2's class: 2 Expected: 3 (Lena)
Unknown Person #3's class: 2 Expected: 2 (James)
Unknown Person #4's class: 2 Expected: 2 (James)
Unknown Person #5's class: 3 Expected: (Unknown person, incorrect result expected)
Unknown Person #6's class: 0 Expected: 3 (Lena)
Unknown Person #7's class: 1 Expected: 2 (James)
Unknown Person #8's class: 3 Expected: 1 (Kate)
我的问题的要点是:我是否正确地实施了课程,我的问题存在于我的数据输入中,或者我误解了一些重要的东西? TIA
答案 0 :(得分:0)
我很确定您收到的错误是因为尺寸不匹配。此外,我认为你在这里的逻辑错误会因不适当的数据集而丢失。你可以在knownFaces上学习并通过unknownFaces进行预测。
double error = new HammingLoss(knownFaces.output).Loss(predicted);
您可能需要对未在列车部件中使用的已知数据部分进行交叉验证。
有人这么想:
double error = new HammingLoss(knownFacesForPredicted.output).Loss(predicted);