如何在多种类型特征上训练 svm
how to train svm on multiple type features
我想在包含特征 p1、p2、p3 的数据集上训练 svm。 p1 是向量,p2 和 p3 是我要训练的整数。例如 p1=[1,2,3], p2=4 , p3=5
X=[p1 , p2 , p3],但 p1 本身是一个向量,所以 X=[ [ 1 , 2 , 3 ], 4 , 5 ] 和 Y 输出命名为 label
但 X 不能接受这种形式的输入
clf.fit(X,Y)
它给出了以下形式的错误:意思是 X 不能采用这种形式
array = np.array(array, dtype=dtype, order=order, copy=copy)
ValueError: 使用序列设置数组元素。
你基本上有两个选择:
将您的数据转换为常规格式和 运行 典型的 SVM 内核,在您的情况下,如果 p1 始终为 3 元素,则只需展平表示 [[1,2,3], 4,5] 变成 [1,2,3,4,5] 就可以了。
实现你自己的自定义内核函数,分别处理每个部分,因为两个内核的总和仍然是一个内核,你可以定义 K(x, y) = K([p1, p2, p3], [q1, q2, q3]) := K1(p1, q1) + K2([p2,p3], [q2,q3])。现在 K1 和 K2 都在常规向量上工作,因此您可以任意定义它们,只需将它们的总和用作 "joint" 核函数。这种方法比较复杂,但在定义处理复杂数据的方式方面给了您很大的自由度。
这是一个简单的例子
#include <opencv2/ml.hpp>
using namespace cv::ml;
// Set up training data
int labels[4] = { -1, -1, 1, 1}; //Negative and Positive class
Mat labelsMat(4, 1, CV_32SC1, labels);
//training data inputs
float a1 = 1, a2 = 2; //negative
float b1 = 2, b2 = 1; //negative
float c1 = 3, c2 = 4; //positive
float d1 = 4, d2 = 3; //positive
float trainingData[4][2] = {{ a1, a2 },{ b1, b2 },{ c1, c2 },{ d1, d2 };
Mat trainingDataMat(20, 2, CV_32FC1, trainingData);
// Set up SVM's parameters
Ptr<SVM> svm = SVM::create();
svm->setType(SVM::C_SVC);
svm->setKernel(SVM::RBF);
svm->setC(10);
svm->setGamma(0.01);
svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 500, 1e-6));
// Train the SVM with given parameters
Ptr<TrainData> td = TrainData::create(trainingDataMat, ROW_SAMPLE, labelsMat);
svm->train(td);
测试
float t1 = 2, t2 = 2;
float testing[1][2] = { { t1,t2 } };
Mat testData(1, 2, CV_32FC1, testing);
Mat results;
svm->predict(testData, results);
Mat vec[2];
results.copyTo(vec[0]);
for (int i = 0; i < 2; i++)
{
cout << vec[i] << endl;
}
我想在包含特征 p1、p2、p3 的数据集上训练 svm。 p1 是向量,p2 和 p3 是我要训练的整数。例如 p1=[1,2,3], p2=4 , p3=5
X=[p1 , p2 , p3],但 p1 本身是一个向量,所以 X=[ [ 1 , 2 , 3 ], 4 , 5 ] 和 Y 输出命名为 label
但 X 不能接受这种形式的输入
clf.fit(X,Y) 它给出了以下形式的错误:意思是 X 不能采用这种形式 array = np.array(array, dtype=dtype, order=order, copy=copy) ValueError: 使用序列设置数组元素。
你基本上有两个选择:
将您的数据转换为常规格式和 运行 典型的 SVM 内核,在您的情况下,如果 p1 始终为 3 元素,则只需展平表示 [[1,2,3], 4,5] 变成 [1,2,3,4,5] 就可以了。
实现你自己的自定义内核函数,分别处理每个部分,因为两个内核的总和仍然是一个内核,你可以定义 K(x, y) = K([p1, p2, p3], [q1, q2, q3]) := K1(p1, q1) + K2([p2,p3], [q2,q3])。现在 K1 和 K2 都在常规向量上工作,因此您可以任意定义它们,只需将它们的总和用作 "joint" 核函数。这种方法比较复杂,但在定义处理复杂数据的方式方面给了您很大的自由度。
这是一个简单的例子
#include <opencv2/ml.hpp>
using namespace cv::ml;
// Set up training data
int labels[4] = { -1, -1, 1, 1}; //Negative and Positive class
Mat labelsMat(4, 1, CV_32SC1, labels);
//training data inputs
float a1 = 1, a2 = 2; //negative
float b1 = 2, b2 = 1; //negative
float c1 = 3, c2 = 4; //positive
float d1 = 4, d2 = 3; //positive
float trainingData[4][2] = {{ a1, a2 },{ b1, b2 },{ c1, c2 },{ d1, d2 };
Mat trainingDataMat(20, 2, CV_32FC1, trainingData);
// Set up SVM's parameters
Ptr<SVM> svm = SVM::create();
svm->setType(SVM::C_SVC);
svm->setKernel(SVM::RBF);
svm->setC(10);
svm->setGamma(0.01);
svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 500, 1e-6));
// Train the SVM with given parameters
Ptr<TrainData> td = TrainData::create(trainingDataMat, ROW_SAMPLE, labelsMat);
svm->train(td);
测试
float t1 = 2, t2 = 2;
float testing[1][2] = { { t1,t2 } };
Mat testData(1, 2, CV_32FC1, testing);
Mat results;
svm->predict(testData, results);
Mat vec[2];
results.copyTo(vec[0]);
for (int i = 0; i < 2; i++)
{
cout << vec[i] << endl;
}