我正在使用Visual Studio 2010、C++和OpenCV中的SVM构建一个OCR应用程序。当我使用少于181个不同的标签训练SVM时一切正常,但超过181个标签时就失败了。下面是IDE和OpenCV的错误信息以及我的代码。请帮助我,非常感谢!
IDE错误信息
在OCR.exe中首次捕获到异常,地址为0x771e4b32:Microsoft C++异常:cv::Exception,内存位置为0x0081da74。线程’Win32 Thread’(0xdac)已以代码-1073741510(0xc000013a)退出。程序'[2512] OCR.exe: Native’已以代码-1073741510(0xc000013a)退出。
OpenCV错误信息
……\src\opencv\modules\core\src\datastructs.cpp:332: 错误:(-211) 请求的大小为负数或太大
SVM的配置
CvSVMParams params; params.svm_type = CvSVM::C_SVC; params.kernel_type = CvSVM::LINEAR; params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);SVM.train( training_vectors, training_labels, cv::Mat(), cv::Mat(), params );
回答:
libSVM
使用“一对多”技术来表示使用二元SVM分类器的多类问题。这意味着,如果你有N
(>2
)个标签,libSVM将生成N
个不同的分类器,每个分类器都有不同的数据标记(因此表达了“一对多”方案)。这可能会导致你所遇到的一些内存问题。其他一些模型,比如神经网络或knn,可以在没有这种开销的情况下表示多类分类。因此,如果你的数据太大而无法像libsvm那样处理,你至少有三种可能的选择:
- 将SVM更改为其他可以直接处理多标签分类的模型
- 尝试使用库的其他更轻量级的实现,特别是OpenCV没有使用libsvm的最新实现(这可能有帮助,但不一定)
- 你可以手动实现“一对多”方案,并保存每个独立的模型。这样你应该可以避免内存问题,因为在任何时候你最多只会分配二元问题所需的内存。最后,你只需从文件中加载你的模型并应用简单的投票方案。如果保存的模型太大,这意味着你的模型过拟合(在SVM中,过拟合通常表现为支持向量的数量过多,实际上这些支持向量是定义模型所需的唯一东西——所以如果模型的支持向量太多而无法加载到内存中,这意味着它很可能训练错误,你应该尝试不同的参数/核函数)