我正在将一个使用支持向量机(SVM)的算法从Python(使用scikit-learn)移植到C++(使用OpenCV的机器学习库)。
我可以在Python中访问训练好的SVM,并且可以将SVM模型参数从XML文件导入到OpenCV中。由于scikit-learn和OpenCV的SVM实现都是基于LibSVM的,我认为应该可以将训练好的scikit SVM的参数用于OpenCV中。
下面的示例展示了一个可以用来在OpenCV中初始化SVM的XML文件:
<?xml version="1.0"?><opencv_storage><my_svm type_id="opencv-ml-svm"> <svm_type>C_SVC</svm_type> <kernel><type>RBF</type> <gamma>0.058823529411764705</gamma></kernel> <C>100</C> <term_criteria><epsilon>0.0</epsilon> <iterations>1000</iterations></term_criteria> <var_all>17</var_all> <var_count>17</var_count> <class_count>2</class_count> <class_labels type_id="opencv-matrix"> <rows>1</rows> <cols>2</cols> <dt>i</dt> <data> 0 1</data></class_labels> <sv_total>20</sv_total> <support_vectors> <_> 2.562423055146794554e-02 1.195797425735170838e-01 8.541410183822648050e-02 9.395551202204914520e-02 1.622867934926303379e-01 3.074907666176152077e-01 4.099876888234874062e-01 4.697775601102455179e-01 3.074907666176152077e-01 3.416564073529061440e-01 5.124846110293592716e-01 5.039432008455355660e-01 5.466502517646497639e-01 1.494746782168964394e+00 4.168208169705446942e+00 7.214937388193202183e-01 7.400275229357797802e-01</_> <!-- omit 19 vectors to keep it short --> </support_vectors> <decision_functions> <_> <sv_count>20</sv_count> <rho>-5.137523249549433402e+00</rho> <alpha> 2.668992955678978518e+01 7.079767098112181145e+01 3.554240018130368384e+01 4.787014908624512088e+01 1.308470223155845069e+01 5.499185410034550614e+01 4.160483074010306126e+01 2.885504210853826379e+01 7.816431542954153144e+01 6.882061506693679576e+01 1.069534676985309574e+01 -1.000000000000000000e+02 -5.088050252552544350e+01 -1.101740897543916375e+01 -7.519686789702373630e+01 -3.893481464245511603e+01 -9.497774056452135483e+01 -4.688632332663718927e+00 -1.972745089701982835e+01 -8.169343841768861125e+01</alpha> <index> 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 </index></_></decision_functions></my_svm></opencv_storage>
现在我想用训练好的scikit-learn SVM的值填充这个XML文件。但我不确定scikit-learn和OpenCV的参数是如何对应的。以下是我目前的理解(clf
是Python中的分类器对象):
<kernel><gamma>
对应于clf.gamma
<C>
对应于clf.C
<term_criteria><epsilon>
对应于clf.tol
<support_vectors>
对应于clf.support_vectors_
到目前为止这些是正确的吗?现在这里是我不太确定的项目:
<term_criteria><iterations>
该如何处理?<decision_functions><_><rho>
是否对应于clf.intercept_
?<decision_functions><_><alpha>
是否对应于clf.dual_coef_
?我在这里不太确定,因为scikit-learn的文档说“dual_coef_
保存的是yiαi的乘积”。看起来OpenCV只期望αi,而不是yiαi。
回答:
你不再需要epsilon
和iterations
,这些是在训练优化问题中使用的。你可以将它们设置为你喜欢的数字或忽略它们。
移植支持向量可能需要一些调整,因为scikit-learn和OpenCV之间的索引可能不同。例如,你的XML示例中没有稀疏格式。
关于其他参数:
rho
应该对应于intercept_
,但你可能需要改变符号。- scikit的
dual_coef_
对应于标准libsvm模型中的sv_coef
(即alpha_i*y_i)。
如果opencv在移植时对你提供的alpha
值提出异议,请使用scikit-learn的dual_coef_
的绝对值(例如全部为正数)。这些是SVM模型的真实alpha值。