@CrazyHenry
2017-12-07T21:07:23.000000Z
字数 7591
阅读 3933
bbbb北邮模式识别实验室
- Author:李英民 | Henry
- E-mail: li
_
yingmin@
outlookdot
com- Home: https://liyingmin.wixsite.com/henry
快速了解我: About Me
转载请保留上述引用内容,谢谢配合!
定义是这样的,设A为n阶方阵,如果存在数,使得,称为特征值,为特征向量。
某方阵经过其特征向量构成的矩阵的线性变化,可以成为对角阵。
即,如果有个方阵,其所有特征值组成的特征向量是下面这样的:
线性变化的意义就是坐标轴的旋转,当然,这只在一位到三维空间比较容易想象,实际上对于高维,我们一般称之为基的选择变化
如果选择的一组基是标准正交基,那么就是标准正交变换。
标准正交基就是每组基之间两两线性无关,而且相互正交。
实对称矩阵的都是实数
实对称矩阵对应不同特征值的特征向量是正交的。
实对称矩阵对应相同的特征值(重根)的特征向量一定是线性无关的,可以用方法(施密特正交化方法)使其正交
实对称矩阵一定可以被某个正交矩阵对角化:
正交矩阵有(单位阵),
对于二维平面的一堆没有明显规律的点集:
表示点集中的任意一点.
如果已知:
那么一定有:
其中,和分别是坐标的平均值,分别是坐标的平均值.
其中 等代表二维坐标系下的一个点.
表示均值向量
表示方差
表示协方差
现在仍然以二维的数据作为理论分析的目标。对于二维平面的一堆没有明显规律的点集:
称坐标轴为第一主分量,坐标轴为第二主分量.
是一组由标准正交基组成的正交矩阵:
新的坐标轴下,第二维数据到的方差很小,那么就意味着这一维的数据对分类的贡献没有那么大,所以我们就把这一维数据忽略掉。
下面举一个例子:
相当于投影.
问为什么这样旋转,其实也就是要问,怎么求出来这个正交矩阵。
对于这样一个点集:
用任意一种求解特征值的算法,我们就一定可以求到矩阵的两个特征值,,让,对应的特征向量分别为:,同时还要将所有的特征向量标准正交化。
而且这两个特征向量还满足实对阵矩阵的特性:
所以矩阵一定是个正交矩阵。至此,就求出来了!
对于实对称矩阵的正交变换,还有一个性质:
有,但是不保证,而且一般是没有这样关系的:因为变换坐标的目的就是让新坐标下每个维度的坐标对应的数据的方差依次减小,即原先数据的方差分别为坐标下,坐标下;而现在的新的坐标下,比如新的点集表示为:
其实上面那个补充说明已经点到了很重要的一点,就是我的点集原来在坐标下表示为,即原先数据的方差分别为坐标下,坐标下,现在经过的正交变换,坐标轴变成了.(注意,点集还是原来那些点,只不过是坐标轴发生了变化,表示的方式不同而已)而且a坐标下方差和坐标下方差,满足,.
同时,我们还希望对于新的坐标系,坐标系的基底之间(即特征向量之间)满足相互正交:
下面证明我们求出来的确实满足了这两个性质:
由于,都是实对称矩阵的特征向量,所以满足:
对应的特征向量为,同理对应的特征向量为.
经过推导有:
又因为为:
总结一下前面的推导,对于二维平面的一堆没有明显规律的点集用坐标表示为:
然后由于是实对称矩阵,由于实对称矩阵有很多可爱的性质,让我们可以利用求的特征值和特征向量,进而求出一个正交矩阵,使得
a坐标下方差,和坐标下方差,满足,,且坐标相互正交.
这一切正是我们需要的,我们可以根据比较前几个坐标的方差大小,忽略方差不是那么大的坐标.就如最初的那个例子一样.
我们说,求出的对角矩阵:
查阅线性代数的知识,有下面这个定义:
对于实对称矩阵,如果其特征值全部为正数,那么这个矩阵是正定的;如果其特征值非负,那么这个矩阵是半正定的。满足以上两种的任意一种的实对称矩阵,我们称之为非负定的。
显然,我们希望是非负定的.
同时,线性代数理论中,有这样判断一个实对称矩阵是否为非负定的方法:
对于二维情况:
对于维情况?
集中在第一象限的点集
#!/usr/bin/env python
# coding=utf-8
from numpy import *
import matplotlib
import matplotlib.pyplot as plt
def loadDataSet(fileName, delim = "\t"):
fr = open(fileName)
stringArr = [line.strip().split(delim) for line in fr.readlines()]
datArr = [map(float, line) for line in stringArr]#对每行数据的两个数字都变为float型
return mat(datArr)
def pca(dataMat, topNfeat=9999999): #dataMat为1000×2的矩阵,
meanVals = mean(dataMat, axis=0) #numpy中的mat类型有算均值mean的方法,并且对每列进行计算,得到2*1的矩阵
meanRemoved = dataMat - meanVals #计算协方差
covMat = cov(meanRemoved, rowvar = 0) #计算协方差,维度为2,得到2×2的协方差矩阵
eigVals, eigVects = linalg.eig(mat(covMat)) #计算特征值及特征向量,2×1,2×2,得到两个特征值,两列特征向量,向量长度为2
eigValInd = argsort(eigVals) #默认快排,从小到大进行排序
eigValInd = eigValInd[:-(topNfeat+1):-1] #得到topNfeat个特征值,大的特征值排在前面,若topNfeat为1。,则取1个特征值
redEigVects = eigVects[:, eigValInd] #将topNfeat个最大的特征值对应的那列向量取出来,若topNfeat为1,
lowDDataMat = meanRemoved * redEigVects #1000×2 * 2×topNfeat得到1000×topNfeat的低维空间的数据
reconMat = (lowDDataMat * redEigVects.T) + meanVals#1000×topNfeat * topNfeat*2 +1000×2重构数据
return lowDDataMat, reconMat
dataMat = loadDataSet("testSet.txt")
lowDMat, reconMat = pca(dataMat, 1)
print shape(dataMat)
print shape(lowDMat)
print shape(reconMat)
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(dataMat[:,0].flatten().A[0], dataMat[:,1].flatten().A[0], marker="^", s=90)
ax.scatter(reconMat[:,0].flatten().A[0], reconMat[:,1].flatten().A[0], marker="o", s=50, c="red")
plt.show()