为什么OpenCV3.1的NormalBayesClassifier在这个例子中的错误率如此高?

我在尝试使用OpenCV3.1的NormalBayesClassifier来解决一个简单的问题,这个问题我可以轻松生成训练数据。我选择了将输入的数字分类为偶数或奇数。显然,这可以直接计算并达到100%的准确率,但重点是通过使用OpenCV的机器学习能力来熟悉它。

所以,我的第一个问题是 – 从理论上讲,NormalBayesClassifier是否不适合这个问题的模型?

如果不是,那么第二个问题是,为什么我的错误率如此高?cv::ml::StatModel::calcError()给我的输出是30%到70%。

第三,什么是最好的方法来降低错误率?

这里是一个最小、自包含的代码片段,展示了这个问题:

(明确一点,分类/输出应该对于偶数是0,对于奇数是1)。

#include <ml.h>#include <iomanip>int main() {   const int numSamples = 1000;   cv::RNG rng = cv::RNG::RNG((uint64) time(NULL));   // 构造训练样本数据   cv::Mat samples;   samples.create(numSamples, 1, CV_32FC1);   for (int i = 0; i < numSamples; i++) {      samples.at<float>(i) = (int)rng(10000);   }   // 构造训练响应数据   cv::Mat responses;   responses.create(numSamples, 1, CV_32SC1);   for (int i = 0; i < numSamples; i++) {      int sample = (int) samples.at<float>(i);      int response = (sample % 2);      responses.at<int>(i) = response;   }   cv::Ptr<cv::ml::TrainData> data = cv::ml::TrainData::create(samples, cv::ml::ROW_SAMPLE, responses);   data->setTrainTestSplitRatio(.9);   cv::Ptr<cv::ml::NormalBayesClassifier> classifier = cv::ml::NormalBayesClassifier::create();   classifier->train(data);   float errorRate = classifier->calcError(data, true, cv::noArray());   std::cout << "Bayes错误率: [" << errorRate << "]" << std::endl;   // 构造预测输入   const int numPredictions = 10;   cv::Mat predictInputs;   predictInputs.create(numPredictions, 1, CV_32FC1);   for (int i = 0; i < numPredictions; i++) {      predictInputs.at<float>(i) = (int)rng(10000);   }   cv::Mat predictOutputs;   predictOutputs.create(numPredictions, 1, CV_32SC1);   // 运行预测   classifier->predict(predictInputs, predictOutputs);   int numCorrect = 0;   for (int i = 0; i < numPredictions; i++) {      int input = (int)predictInputs.at<float>(i);      int output = predictOutputs.at<int>(i);      bool correct = (input % 2 == output);      if (correct)         numCorrect++;      std::cout << "输入 = [" << (int)predictInputs.at<float>(i) << "], " << "预测输出 = [" << predictOutputs.at<int>(i) << "], " << "正确 = [" << (correct ? "是" : "否") << "]"  << std::endl;   }   float percentCorrect = (float)numCorrect / numPredictions * 100.0f;   std::cout << "正确百分比 = [" << std::fixed << std::setprecision(0) << percentCorrect << "]" << std::endl;}

示例运行输出:

Bayes错误率: [36]输入 = [9150], 预测输出 = [1], 正确 = [否]输入 = [3829], 预测输出 = [0], 正确 = [否]输入 = [4985], 预测输出 = [0], 正确 = [否]输入 = [8113], 预测输出 = [1], 正确 = [是]输入 = [7175], 预测输出 = [0], 正确 = [否]输入 = [811], 预测输出 = [1], 正确 = [是]输入 = [699], 预测输出 = [1], 正确 = [是]输入 = [7955], 预测输出 = [1], 正确 = [是]输入 = [8282], 预测输出 = [1], 正确 = [否]输入 = [1818], 预测输出 = [0], 正确 = [是]正确百分比 = [50]

回答:

在你的代码中,你提供给算法的只有一个特征,即要分类的数字。这是不够的,除非你多次提供相同数字的多个示例。如果你想让学习算法学习关于奇数和偶数的知识,你需要考虑分类器可以用来学习的特征类型。大多数机器学习技术首先需要你进行仔细的特征工程。

既然你想尝试机器学习,我建议如下操作:

  1. 对于每个数字,创建例如5个特征,每个特征编码一个数字。因此,5可以是00005或者f1=0, f2=0, f3=0, f4=0, f5=0,而11098可以是f1=1, f2=2, f3=0, f4=9, f5=8。
  2. 如果你的数字大于这个范围,你可以只保留最后5位数字。
  3. 训练你的分类器
  4. 用相同的编码进行测试。你希望你的分类器能够学习到只有最后一位数字对于确定奇数还是偶数是重要的

如果你想进一步尝试,你可以将数字以二进制格式编码。这将使分类器更容易学习什么使得一个数字是奇数还是偶数。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注