奇異值分解(Singular Value Decomposition,SVD),可以說是對角化應用的特例,它具有與Eigen Value,Eigen Vector相同的特性,分解後向量的矩陣乘積可以還原為原矩陣,而他可以對奇異矩陣(Singular Matrix)做分解,亦可以對非奇異矩陣做分解.奇異矩陣的定義就是不能計算為反矩陣的矩陣,包括方陣,以及非方陣的長方形矩陣.而奇異值分解的計算它的數學定義為
它將奇異矩陣轉置後相乘,藉由這個方法計算出對稱矩陣,在對對稱矩陣做SVD分解,由上面可知,原矩陣大小為m*n,而W(Sigma)矩陣的舉陣大小必須為m*n,U的矩陣大小必須為m*m,而V的矩陣大小為n*n,它可以藉由矩陣矩陣相乘的方式算回原矩陣.
下面這個是拿2*3的奇異矩陣做奇異值分解
奇異矩陣SVD分解
#include <cv.h>
#include <highgui.h>
#include <stdio.h>
void PrintMatrix(CvMat *Matrix,int Rows,int Cols);
double Array1[]={3,2,2,2,3,-2};
int main()
{
CvMat *Matrix1=cvCreateMat(2,3,CV_64FC1);
CvMat *W=cvCreateMat(2,3,CV_64FC1);
CvMat *V=cvCreateMat(3,3,CV_64FC1);
CvMat *U=cvCreateMat(2,2,CV_64FC1);
CvMat *V_T=cvCreateMat(3,3,CV_64FC1);
CvMat *ResultMatrix=cvCreateMat(2,3,CV_64FC1);
cvSetData(Matrix1,Array1,Matrix1->step);
cvSVD(Matrix1,W,U,V);
printf("\nW\n");
PrintMatrix(W,W->rows,W->cols);
printf("\nU\n");
PrintMatrix(U,U->rows,U->cols);
printf("\nV\n");
PrintMatrix(V,V->rows,V->cols);
printf("\nValid\n");
cvmMul(U,W,ResultMatrix);
cvTranspose(V,V_T);
cvmMul(ResultMatrix,V_T,ResultMatrix);
PrintMatrix(ResultMatrix,ResultMatrix->rows,ResultMatrix->cols);
system("pause");
}
void PrintMatrix(CvMat *Matrix,int Rows,int Cols)
{
for(int i=0;i<Rows;i++)
{
for(int j=0;j<Cols;j++)
{
printf("%.2f ",cvGet2D(Matrix,i,j).val[0]);
}
printf("\n");
}
}
執行結果:
上面的程式,利用了前面奇異值分解公式說明的方式,cvSVD()的內部運算,先將矩陣做轉置在相乘,求得對稱矩陣,在將該矩陣做奇異值分解,而它的W,U,V矩陣的大小皆不相同,W將會是原矩陣大小2*3,V則是2*2,U則會是3*3,因此利用公式倒回運算,可以計算出原矩陣,計算以及驗證的公式如下.
而對稱矩陣的奇異值分解,則是不需要再做轉置後相乘,直接做奇異值分解.
對稱矩陣奇異值分解
#include <cv.h>
#include <highgui.h>
#include <stdio.h>
void PrintMatrix(CvMat *Matrix,int Rows,int Cols);
double Array1[]={2,-2,4,-2,2,-4,4,-4,8};
int main()
{
CvMat *Matrix1=cvCreateMat(3,3,CV_64FC1);
CvMat *W=cvCreateMat(3,3,CV_64FC1);
CvMat *V=cvCreateMat(3,3,CV_64FC1);
CvMat *U=cvCreateMat(3,3,CV_64FC1);
CvMat *V_T=cvCreateMat(3,3,CV_64FC1);
CvMat *ResultMatrix=cvCreateMat(3,3,CV_64FC1);
cvSetData(Matrix1,Array1,Matrix1->step);
cvSVD(Matrix1,W,U,V);
printf("\nW\n");
PrintMatrix(W,W->rows,W->cols);
printf("\nU\n");
PrintMatrix(U,U->rows,U->cols);
printf("\nV\n");
PrintMatrix(V,V->rows,V->cols);
printf("\nValid\n");
cvmMul(U,W,ResultMatrix);
cvTranspose(V,V_T);
cvmMul(ResultMatrix,V_T,ResultMatrix);
PrintMatrix(ResultMatrix,ResultMatrix->rows,ResultMatrix->cols);
system("pause");
}
void PrintMatrix(CvMat *Matrix,int Rows,int Cols)
{
for(int i=0;i<Rows;i++)
{
for(int j=0;j<Cols;j++)
{
printf("%.2f ",cvGet2D(Matrix,i,j).val[0]);
}
printf("\n");
}
}
執行結果:
這是一個直接用對稱矩陣做奇異值分解的程式,奇異值分解很特別的地方,它對對稱矩陣做奇異值分解求得的結果為特徵值(Eigen Value)及特徵向量(Eigen Vector),但是相較於cvEigenVV()這兩個使用的是不同的演算法,而一般的矩陣則無法用cvSVD()求特徵值及特徵向量,上面的程式用cvSVD()分別求出它的W,U,V,在代回原公式做驗證,驗證的方法如下
驗證對稱矩陣奇異值分解
2008年8月11日 星期一
訂閱:
張貼留言 (Atom)
2 意見:
Good! thank you!
a little error for first question exist!
http://2.bp.blogspot.com/_HcQD5f5sLPc/SKNtnK8MvII/AAAAAAAABB0/v-qYwW6HRoE/s1600-h/mat_number_73-2.JPG
V^t 好像有問題
張貼留言