# PCA+SVM Explanation

I'm trying to apply a SVM classifier to a PCA projected matrix, but I've some doubt on how to perform it. After training a PCA obj, I've applied a back-projection. Then I've trained my SVM obj with this back-projection and the labels matrix.

But when I need to predict a new image, should I recreate a PCA obj, train it with the image only and back-project it? or should I apply the previous PCA obj?

Here's my piece of code

Mat values = asRowMatrix(labels, CV_32FC1);

Mat desc_mat = asRowMatrix(images_cropped, CV_32FC1);

Mat average = Mat();
PCA pca(desc_mat, average, CV_PCA_DATA_AS_ROW);

Mat mean = pca.mean.clone();
Mat eigenvalues = pca.eigenvalues.clone();
Mat eigenvectors = pca.eigenvectors.clone();

CvSVMParams params;
params.svm_type = CvSVM::C_SVC;
params.kernel_type = CvSVM::LINEAR;
params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);

Mat data(desc_mat.rows, images_cropped.size(), CV_32FC1); //This Mat will contain all the Eigenfaces that will be used later with SVM for detection

for (int i = 0; i<images_cropped.size(); i++) {
Mat projectedMat(1, images_cropped.size(), CV_32FC1);
pca.project(desc_mat.row(i), projectedMat);
projectedMat.row(0).copyTo(data.row(i));
}

CvSVM svm;
svm.train(data, values, Mat(), Mat(), params);

vector<Mat> images_cropped_t;
vector<int> labels_t;
//vectors with images and labels

int accuracy = 0;
Mat m_img = asRowMatrix(images_croppedt, CV_32FC1);
for (int i = 0; i < images_croppedt.size(); i++)
{
Mat face = m_img.row(i);
Mat projectedMat(1, images_croppedt.size(), CV_32FC1);
pca.project(face, projectedMat);

int predict = svm.predict(projectedMat);

accuracy = ((predict < 51) && (labelst[i] == 0)) ? ++accuracy : (((predict > 51) && (labelst[i] == 1)) ? ++accuracy : accuracy);

}
cout << endl;
cout << "ACCURACY: " << accuracy << "/" << images_croppedt.size() << " : - " << accuracy * 100 / images_croppedt.size() << "%" << endl;

edit retag close merge delete

Sort by » oldest newest most voted

Your PCA object basically creates a new coordinate system for your data, such that the first principal component captures the 'most interesting data', the second principal component the second most, etc. With most interesting data I mean that the data in this direction has the highest variation.

If you have projected your samples for your SVM classifier using some PCA projection, you need to do that exact same projection if you want to classify a new image. Otherwise you'd be comparing different coordinate systems with eachother, like comparing meters with yards, celsius with fahrenheit, apples with pears.

more

So what I'm doing with my code is right I suppose! (or I am comparing apples with celsius?)

( 2014-04-29 09:22:40 -0500 )edit

I didn't check your code before, but it seems like you use PCA/SVM fine there. That is of course no guarantee that it'll work ;) good luck!

( 2014-04-30 02:42:48 -0500 )edit

Official site

GitHub

Wiki

Documentation