PCA基于opencv的实现和样本数小于维度的问题

之前是论文中看到PCA,有了一个简单了解,还写了一篇入门笔记:PCA主成分分析
直到前一阵帮做实验用到PCA,才发现之前的理解实在是too young too naive…

1 基于opencv的几种PCA实现

故事是这样的,有一天,我拿到一个5000个样本的数据集,每个样本用一个30w维的特征向量描述,被要求对特征降维到3w维。简单复习了下之前的入门笔记,便哼哧哼哧开始coding了。

1.1 使用cvCalcPCA

我查到opencv中已经有函数cvCalcPCA和cvProjectPCA,大喜,于是很快写出了如下的代码:

cv::Mat data;
LoadData(inputFile, data , nSamples, 0, 0);
int nDim = data.cols;
CvMat tmpD = data;
CvMat* pData;
pData = &tmpD;
CvMat* pMean = cvCreateMat(1,nDim,CV_32FC1);
CvMat* pEigVectors = cvCreateMat(nComponents,nDim,CV_32FC1);
CvMat* pEigValues = cvCreateMat(1,nComponents,CV_32FC1);
cvCalcPCA(pData,pMean,pEigValues,pEigVectors,CV_PCA_DATA_AS_ROW);
cvProjectPCA(pData,pMean,pEigVectors,pResult);
cv::Mat tmpResult(pResult->rows, pResult->cols, CV_32FC1, pResult->data.fl);
cvReleaseMat(&pResult);
WriteData(pcaResultFile, tmpResult);

运行程序,发现,在opencv的matmul.cpp中函数cvCalcPCA的实现中,这一句:

CV_Assert( (evals0.cols == 1 || evals0.rows == 1) &&
                ecount0 <= ecount &&
                evects0.cols == evects.cols &&
                evects0.rows == ecount0 );

第二句报错,意思是已创建的eignvalue数组和程序计算得到的eignvalue数组大小不一致。而当设nComponents小于5000时,程序不报错。

1.2 使用cv::PCA

看到在cvCalcPCA中封装了cv::PCA,于是把cv::PCA单独拎出来,想摆脱那句Assert,就有了如下的代码:

cv::PCA pca(data,noArray(),CV_PCA_DATA_AS_ROW,nComponents);

FileStorage outputPca(pcaMatrixFile,FileStorage::WRITE);
pca.write(outputPca);

cv::Mat evects = pca.eigenvectors;
cv::Mat result = pca.project(data);

FileStorage outputResult(pcaResultFile,FileStorage::WRITE);
outputResult << "result" << result;

发现这种写法舒服太多,首先,直接用Mat,省去了向CvMat*转换的麻烦,其次,这个pca.write()函数可直接将特征向量特征值等信息写入同个xml文件。
然而不幸的是,只要nComponents超过样本个数(5000),程序输出的结果都是5000维的,我们本来期望是nComponents维,也就是3w维。
在pca.cpp中查看其实现,发现,当样本维度D大于样本个数N时,使用“scrambled”方法计算pca,设A为输入样本按行存储,A大小为N×D:

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值