当前位置:   article > 正文

PCA算法实现

pca c代码实现

         PCA在视觉算法中有着重要的应用,是常见的降维方法,它属于无监督学习的范畴。关于PCA的理论在其它博客中也非常常见,本文利用C++实现了PCA的功能,基于该程序做改动,可以将PCA运用于自己的项目需求中。

 

  1. #ifndef _PCA_H_
  2. #define _PCA_H_
  3. #include<iostream>
  4. #include<cstdlib>
  5. #include<malloc.h>
  6. #include<string.h>
  7. #include<cmath>
  8. using namespace std;
  9. template<typename T>
  10. struct key_val
  11. {
  12. int key;
  13. T* val;
  14. };
  15. template<typename T>
  16. struct DSet
  17. {
  18. int nDim;
  19. T* nElement;
  20. DSet()
  21. {
  22. nElement=NULL;
  23. nDim=0;
  24. }
  25. };
  26. /*template<typename T>
  27. int compare(const T* a,const T* b )
  28. {
  29. return ((*(T*)a-*(T*)b)>0?1:0;
  30. }*/
  31. template<class T>
  32. class PCA
  33. {
  34. public:
  35. PCA(int nSample,int nDim);
  36. ~PCA();
  37. bool Load_Pca_Data(DSet<double> m_Set[]);
  38. bool Compute_Eigen_Matrix();
  39. void Print_Feature_Value();
  40. T* get_Projection_matrix();
  41. DSet<double> get_mean_vector();
  42. int get_nr();
  43. //T get_thresh();
  44. private:
  45. DSet<double> mean_Set;
  46. T* Set;
  47. T* PSet;
  48. T* Mean_Matrix;
  49. T* Conv_Matrix;
  50. T* Eigen_Vector;
  51. T* Eigen_Val;
  52. //T Thresh;
  53. int dim;
  54. int sample;
  55. int nR;
  56. float ratio;
  57. bool isLoad;
  58. bool isCompute;
  59. bool isProjection;
  60. };
  61. template<class T>
  62. PCA<T>::PCA(int nSample,int nDim)
  63. {
  64. sample=nSample;
  65. dim = nDim;
  66. nR=0;
  67. ratio=0.85;
  68. //Thresh=0;
  69. isProjection=false;
  70. Mean_Matrix=(T*)malloc(nSample*nDim*sizeof(T));
  71. Conv_Matrix=(T*) malloc(nDim*nDim*sizeof(T));
  72. Eigen_Vector=(T*)malloc(nDim*nDim*sizeof(T));
  73. Eigen_Val=(T*)malloc(nDim*sizeof(sizeof(T)));
  74. Set=(T*)malloc(nSample*nDim*sizeof(T));
  75. mean_Set.nDim=dim;
  76. mean_Set.nElement=(T*)malloc(dim*sizeof(T));
  77. memset((void*) mean_Set.nElement,0,dim*sizeof(T));
  78. PSet=NULL;
  79. memset((void*)Conv_Matrix,0,nDim*nDim*sizeof(T));
  80. memset((void*)Eigen_Vector,0,nDim*nDim*sizeof(T));
  81. memset((void*)Eigen_Val,0,nDim*sizeof(T));
  82. for(int i=0;i<nDim;i++) Eigen_Vector[i*nDim+i]=1;
  83. isLoad=false;
  84. isCompute=false;
  85. }
  86. template<class T>
  87. PCA<T>::~PCA()
  88. {
  89. if(Mean_Matrix) free(Mean_Matrix);
  90. if(Conv_Matrix) free(Conv_Matrix);
  91. if(Eigen_Vector) free(Eigen_Vector);
  92. if(Eigen_Val) free(Eigen_Val);
  93. if(Set) free(Set);
  94. if(PSet) free(PSet);
  95. }
  96. template<class T>
  97. bool PCA<T>::Load_Pca_Data(DSet<double> m_Set[])
  98. {
  99. //int nLen=sizeof(m_Set)/sizeof(m_Set[0]);
  100. //if(nLen!=sample) {printf("error,the length of set must be %d\n",nLen); return false;}
  101. printf("print input data\n");
  102. for(int i=0;i<sample;i++)
  103. {
  104. if(m_Set[i].nDim!=dim) {printf("error,the dim of set must be %d\n",dim); return false;}
  105. for(int j=0;j<m_Set[i].nDim;j++)
  106. {
  107. Set[j*sample+i]=m_Set[i].nElement[j];
  108. mean_Set.nElement[j]+=m_Set[i].nElement[j]/sample;
  109. if((j+1)%dim==0) printf("%f\n",Set[j*sample+i]);
  110. else printf("%f ",Set[j*sample+i]);
  111. }
  112. }
  113. printf("Conv_Matrix\n");
  114. for(int i=0;i<dim;i++)
  115. for(int j=0;j<dim;j++)
  116. {
  117. for(int k=0;k<sample;k++)
  118. Conv_Matrix[i*dim+j]+=(m_Set[k].nElement[i]-mean_Set.nElement[i])*(m_Set[k].nElement[j]-mean_Set.nElement[j]);
  119. if((j+1)%dim==0) printf("%f\n",Conv_Matrix[i*dim+j]);
  120. else printf("%f ",Conv_Matrix[i*dim+j]);
  121. }
  122. printf("mean vector\n");
  123. for(int k=0;k<dim;k++) printf("%f ",mean_Set.nElement[k]);
  124. printf("\n");
  125. for(int i=0;i<sample;i++)
  126. for(int j=0;j<dim;j++)
  127. {
  128. Mean_Matrix[i*dim+j]=m_Set[i].nElement[j]-mean_Set.nElement[j];
  129. }
  130. isLoad=true;
  131. return true;
  132. }
  133. //利用雅克比法求矩阵特征值和特征向量
  134. template<class T>
  135. bool PCA<T>::Compute_Eigen_Matrix()
  136. {
  137. if(!isLoad) {printf("Please Load set first!\n"); return false;}
  138. int iter=0,MaxIter=400;
  139. T rr,rc,cc;
  140. T eps=0.01;
  141. //for(int i=0;i<dim;i++) Eigen_Vector[i*dim+i]=Conv_Matrix[i*dim+i];
  142. for(;;)
  143. {
  144. T max=Conv_Matrix[1];
  145. int row=0;
  146. int col=1;
  147. for(int i=0;i<dim;i++)
  148. for(int j=0;j<dim;j++)
  149. {
  150. if(i!=j&&fabs(Conv_Matrix[i*dim+j])>max)
  151. {
  152. row=i;
  153. col=j;
  154. max=fabs(Conv_Matrix[i*dim+j]);
  155. }
  156. }
  157. if(max<eps) break;
  158. rr= Conv_Matrix[row*dim+row];
  159. rc= Conv_Matrix[row*dim+col];
  160. cc= Conv_Matrix[col*dim+col];
  161. T theta=0.5*atan2(-2*rc,cc-rr);
  162. T stheta=sin(theta);
  163. T ctheta=cos(theta);
  164. T s2theta=sin(2*theta);
  165. T c2theta=cos(2*theta);
  166. Conv_Matrix[row*dim+row]=rr*ctheta*ctheta+cc*stheta*stheta+2*rc*ctheta*stheta;
  167. Conv_Matrix[col*dim+col]=rr*stheta*stheta+cc*ctheta*ctheta-2*rc*ctheta*stheta;
  168. Conv_Matrix[row*dim+col]=0.5*(cc-rr)*s2theta+rc*c2theta;
  169. Conv_Matrix[col*dim+row]=Conv_Matrix[row*dim+col];
  170. for(int i=0;i<dim;i++)
  171. {
  172. if((i!=col)&&(i!=row))
  173. {
  174. int s=Conv_Matrix[i*dim+row];
  175. Conv_Matrix[i*dim+row]=Conv_Matrix[i*dim+col]*stheta+s*ctheta;
  176. Conv_Matrix[i*dim+col]=Conv_Matrix[i*dim+col]*ctheta-s*stheta;
  177. }
  178. }
  179. for(int i=0;i<dim;i++)
  180. {
  181. if((i!=col)&&(i!=row))
  182. {
  183. int s=Conv_Matrix[row*dim+i];
  184. Conv_Matrix[row*dim+i]=Conv_Matrix[col*dim+i]*stheta+s*ctheta;
  185. Conv_Matrix[col*dim+i]=Conv_Matrix[col*dim+i]*ctheta-s*stheta;
  186. }
  187. }
  188. for(int i=0;i<dim;i++)
  189. {
  190. int s=Eigen_Vector[i*dim+row];
  191. Eigen_Vector[i*dim+row]=Eigen_Vector[i*dim+col]*stheta+s*ctheta;
  192. Eigen_Vector[i*dim+col]=Eigen_Vector[i*dim+col]*ctheta-s*stheta;
  193. }
  194. iter=iter+1;
  195. if(iter>MaxIter) break;
  196. }
  197. int* flag=(int*)malloc(dim*sizeof(int));
  198. int* flag1=(int*)malloc(dim*sizeof(int));
  199. int index;
  200. memset(flag,-1,dim*sizeof(int));
  201. for(int i=0;i<dim;i++)
  202. {
  203. //if(flag[i]!=-1) continue;
  204. T temp1=Conv_Matrix[i*dim+i];
  205. index=0;
  206. for(int j=0;j<dim;j++)
  207. {
  208. if(flag[i]==-1&&flag[j]==-1)
  209. {
  210. if(temp1<Conv_Matrix[j*dim+j])
  211. {
  212. index=j;
  213. T temp2;
  214. temp2=Conv_Matrix[j*dim+j];
  215. temp1=temp2;
  216. }
  217. }
  218. }
  219. flag[index]=i;
  220. flag1[i]=index;
  221. }
  222. T* temp=(T*)malloc(dim*dim*sizeof(T));
  223. printf("Eigen vector\n");
  224. for(int i=0;i<dim;i++)
  225. {
  226. Eigen_Val[i]=Conv_Matrix[flag1[i]*dim+flag1[i]];
  227. for(int j=0;j<dim;j++)
  228. {
  229. temp[i*dim+j]=Eigen_Vector[flag1[i]*dim+j];
  230. printf("%f ",Eigen_Vector[i*dim+j]);
  231. }
  232. printf("\n");
  233. }
  234. memcpy(Eigen_Vector,temp,dim*dim*sizeof(T));
  235. T sum=0;
  236. int count=0;
  237. for(int i=0;i<dim;i++)
  238. {
  239. sum+=abs(Eigen_Val[i]);
  240. }
  241. T sum1=0;
  242. for(int i=0;i<dim;i++)
  243. {
  244. sum1+=abs(Eigen_Val[i]);
  245. count=count+1;
  246. if(sum1/sum>ratio) break;
  247. }
  248. nR=count;
  249. if(temp) free(temp);
  250. if(flag) free(flag);
  251. if(flag1) free(flag1);
  252. isCompute=true;
  253. return true;
  254. }
  255. template<class T>
  256. void PCA<T>::Print_Feature_Value()
  257. {
  258. printf("The main feature value is:\n");
  259. for(int i=0;i<dim;i++)
  260. printf("%f ",Eigen_Val[i]);
  261. printf("\n");
  262. }
  263. template<class T>
  264. T* PCA<T>::get_Projection_matrix()
  265. {
  266. if(!isCompute) return 0;
  267. T* res=(T*)malloc(nR*dim*sizeof(T));
  268. memcpy(res,Eigen_Vector,nR*dim*sizeof(T));
  269. isProjection=true;
  270. return res;
  271. }
  272. template<class T>
  273. DSet<double> PCA<T>::get_mean_vector()
  274. {
  275. if(!isLoad) printf("Please Load training data first\n");
  276. return mean_Set;
  277. }
  278. template<class T>
  279. int PCA<T>::get_nr()
  280. {
  281. return nR;
  282. }
  283. /*templeat<class T>
  284. T PCA<T>::get_thresh()
  285. {
  286. if(!isProjection) return 0;
  287. T argmax=0;
  288. PSet=(T*)malloc(nSample*nr*sizeof(T));
  289. memset(PSet,0,nSample*nr*sizeof(T));
  290. for(int i=0;i<nSample;i++)
  291. {
  292. for(int j=0;j<nr;j++)
  293. {
  294. PSet[j*nr+i]+=
  295. }
  296. }
  297. }*/
  298. #endif // PCA_H_INCLUDED


 

  1. //#include <iostream>
  2. /* run this program using the console pauser or add your own getch, system("pause") or input loop */
  3. /*int main(int argc, char** argv) {
  4. return 0;
  5. }*/
  6. #include"pca.h"
  7. #include<ctime>
  8. double* PCA_Test(double* pmatrix,double* input_vector,int nDim,int nr,DSet<double> &m_vector)
  9. {
  10. double* res=(double*)malloc(nr*sizeof(double));
  11. memset((void*)res,0,nDim*nr*sizeof(double));
  12. for(int i=0;i<nr;i++)
  13. {
  14. for(int j=0;j<nDim;j++)
  15. {
  16. res[i]+=pmatrix[i*nDim+j]*(input_vector[j]-m_vector.nElement[j]);
  17. printf("%f\n",pmatrix[i*nDim+j]);
  18. }
  19. }
  20. return res;
  21. }
  22. int main(int argc,char* argv[])
  23. {
  24. const int nSample=7;
  25. const int nDim=2;
  26. DSet<double> m_set[nSample];
  27. for(int i=0;i<nSample;i++)
  28. {
  29. m_set[i].nElement=(double*)malloc(nDim*sizeof(double));
  30. m_set[i].nDim=nDim;
  31. for(int j=0;j<nDim;j++)
  32. {
  33. srand(time(0));
  34. m_set[i].nElement[j]=j+i+rand()%(i+(i+1)*10);
  35. }
  36. }
  37. PCA<double> m_Pca(nSample,nDim); //10 Training set with size 2
  38. m_Pca.Load_Pca_Data(m_set);
  39. m_Pca.Compute_Eigen_Matrix();
  40. m_Pca.Print_Feature_Value();
  41. DSet<double> m_vector=m_Pca.get_mean_vector();
  42. double* pmatrix=m_Pca.get_Projection_matrix();
  43. int nr=m_Pca.get_nr();
  44. printf("nr=%d\n",nr);
  45. //double* test_vector=(double*)malloc(nDim*sizeof(double));
  46. /*for(int i=0;i<nDim;i++)
  47. {
  48. srand(time(0));
  49. test_vector[i]=(i+2);
  50. }*/
  51. double test_vector[2]={-1.1,3.2};
  52. double* fvector=PCA_Test(pmatrix,test_vector,nDim,nr,m_vector);
  53. for(int i=0;i<nr;i++)
  54. {
  55. printf("fvector[%d]=%f\n",i,fvector[i]);
  56. }
  57. //if(test_vector) free(test_vector);
  58. if(fvector) free(fvector);
  59. printf("finish pca test\n");
  60. //system("pause");
  61. return 0;
  62. }


 

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号