OpenCV SVM 参数的推荐值
Recommended values for OpenCV SVM parameters
对 OpenCV SVM 的推荐参数有什么想法吗?我正在玩 OpenCV 示例目录中的 letter_recog.cpp,但是,SVM 精度很差!在一个 运行 中,我只有 62% 的准确率:
$ ./letter_recog_modified -data /home/cobalt/opencv/samples/data/letter-recognition.data -save svm_letter_recog.xml -svm
The database /home/cobalt/opencv/samples/data/letter-recognition.data is loaded.
Training the classifier ...
data.size() = [16 x 20000]
responses.size() = [1 x 20000]
Recognition rate: train = 64.3%, test = 62.2%
默认参数为:
model = SVM::create();
model->setType(SVM::C_SVC);
model->setKernel(SVM::LINEAR);
model->setC(1);
model->train(tdata);
将其设置为 trainAuto() 没有帮助;它给了我一个奇怪的 0% 测试准确率:
model = SVM::create();
model->setType(SVM::C_SVC);
model->setKernel(SVM::LINEAR);
model->trainAuto(tdata);
结果:
Recognition rate: train = 0.0%, test = 0.0%
使用杨杰的回答更新:
$ ./letter_recog_modified -data /home/cobalt/opencv/samples/data/letter-recognition.data -save svm_letter_recog.xml -svm
The database /home/cobalt/opencv/samples/data/letter-recognition.data is loaded.
Training the classifier ...
data.size() = [16 x 20000]
responses.size() = [1 x 20000]
Recognition rate: train = 58.8%, test = 57.5%
结果不再是0%,但准确率比之前的62%差了。
使用带 trainAuto() 的 RBF 内核最差?
$ ./letter_recog_modified_rbf -data /home/cobalt/opencv/samples/data/letter-recognition.data -save svm_letter_recog.xml -svm
The database /home/cobalt/opencv/samples/data/letter-recognition.data is loaded.
Training the classifier ...
data.size() = [16 x 20000]
responses.size() = [1 x 20000]
Recognition rate: train = 18.5%, test = 11.6%
参数:
model = SVM::create();
model->setType(SVM::C_SVC);
model->setKernel(SVM::RBF);
model->trainAuto(tdata);
我调试了示例代码,找到了原因
responses
是一个Mat
的ASCII码字母。
然而,SVM::trainAuto
训练的SVM返回的预测标签范围为0-25,对应26个classes。这也可以通过查看输出文件 svm_letter_recog.xml
.
中的 <class_labels>...</class_labels>
来观察
因此在test_and_save_classifier
中,r = model->predict( sample )
和responses.at<int>(i)
显然不相等。
我还发现,如果我们使用SVM::train
,那么class标签就会变成65-89,这就是为什么你一开始可以得到正常结果的原因。
解决方案
不知道是不是bug。但是如果你现在想在这个例子中使用SVM::trainAuto
,你可以改变
test_and_save_classifier(model, data, responses, ntrain_samples, 0, filename_to_save);
在build_svm_classifier
到
test_and_save_classifier(model, data, responses, ntrain_samples, 'A', filename_to_save);
更新
trainAuto
和 train
在 class_labels
中应该有相同的行为。问题是由于之前的错误修复。所以我为 OpenCV 创建了一个 pull request 来解决这个问题。
我建议尝试使用 RBF 内核而不是线性内核。
在很多很多情况下,它是最好的选择...
对 OpenCV SVM 的推荐参数有什么想法吗?我正在玩 OpenCV 示例目录中的 letter_recog.cpp,但是,SVM 精度很差!在一个 运行 中,我只有 62% 的准确率:
$ ./letter_recog_modified -data /home/cobalt/opencv/samples/data/letter-recognition.data -save svm_letter_recog.xml -svm
The database /home/cobalt/opencv/samples/data/letter-recognition.data is loaded.
Training the classifier ...
data.size() = [16 x 20000]
responses.size() = [1 x 20000]
Recognition rate: train = 64.3%, test = 62.2%
默认参数为:
model = SVM::create();
model->setType(SVM::C_SVC);
model->setKernel(SVM::LINEAR);
model->setC(1);
model->train(tdata);
将其设置为 trainAuto() 没有帮助;它给了我一个奇怪的 0% 测试准确率:
model = SVM::create();
model->setType(SVM::C_SVC);
model->setKernel(SVM::LINEAR);
model->trainAuto(tdata);
结果:
Recognition rate: train = 0.0%, test = 0.0%
使用杨杰的回答更新:
$ ./letter_recog_modified -data /home/cobalt/opencv/samples/data/letter-recognition.data -save svm_letter_recog.xml -svm
The database /home/cobalt/opencv/samples/data/letter-recognition.data is loaded.
Training the classifier ...
data.size() = [16 x 20000]
responses.size() = [1 x 20000]
Recognition rate: train = 58.8%, test = 57.5%
结果不再是0%,但准确率比之前的62%差了。
使用带 trainAuto() 的 RBF 内核最差?
$ ./letter_recog_modified_rbf -data /home/cobalt/opencv/samples/data/letter-recognition.data -save svm_letter_recog.xml -svm
The database /home/cobalt/opencv/samples/data/letter-recognition.data is loaded.
Training the classifier ...
data.size() = [16 x 20000]
responses.size() = [1 x 20000]
Recognition rate: train = 18.5%, test = 11.6%
参数:
model = SVM::create();
model->setType(SVM::C_SVC);
model->setKernel(SVM::RBF);
model->trainAuto(tdata);
我调试了示例代码,找到了原因
responses
是一个Mat
的ASCII码字母。
然而,SVM::trainAuto
训练的SVM返回的预测标签范围为0-25,对应26个classes。这也可以通过查看输出文件 svm_letter_recog.xml
.
<class_labels>...</class_labels>
来观察
因此在test_and_save_classifier
中,r = model->predict( sample )
和responses.at<int>(i)
显然不相等。
我还发现,如果我们使用SVM::train
,那么class标签就会变成65-89,这就是为什么你一开始可以得到正常结果的原因。
解决方案
不知道是不是bug。但是如果你现在想在这个例子中使用SVM::trainAuto
,你可以改变
test_and_save_classifier(model, data, responses, ntrain_samples, 0, filename_to_save);
在build_svm_classifier
到
test_and_save_classifier(model, data, responses, ntrain_samples, 'A', filename_to_save);
更新
trainAuto
和 train
在 class_labels
中应该有相同的行为。问题是由于之前的错误修复。所以我为 OpenCV 创建了一个 pull request 来解决这个问题。
我建议尝试使用 RBF 内核而不是线性内核。 在很多很多情况下,它是最好的选择...