机器学习实验--pca
·
一、核心原理介绍
通过线性变换,把原始的高维、相关特征,映射到一组新的、彼此正交且无关的低维特征上,并尽可能保留原始数据中的主要信息。
二、数学原理
- 预备知识与符号定义假设我们有一个数据集 X X X,包含 n n n 个样本,每个样本有 d d d 个特征。 X = { x 1 , x 2 , . . . , x n } X = \{x_1, x_2, ..., x_n\} X={x1,x2,...,xn}其中每个 x i x_i xi 都是一个 d d d 维列向量 ( x i ∈ R d x_i \in \mathbb{R}^d xi∈Rd)。第一步:数据中心化 (Centering)为了简化方差的计算,我们首先要对数据进行中心化处理,即让所有数据的均值为 0。 μ = 1 n ∑ i = 1 n x i \mu = \frac{1}{n} \sum_{i=1}^{n} x_i μ=n1i=1∑nxi x i ← x i − μ x_i \leftarrow x_i - \mu xi←xi−μ经过处理后,数据的均值 E [ x ] = 0 E[x] = 0 E[x]=0。2. 定义优化目标我们的目标是找到一个方向向量 w w w(是一个 d d d 维单位向量,即 ∥ w ∥ = 1 \|w\| = 1 ∥w∥=1),当我们将所有数据投影到这个方向上时,投影点的分布尽可能分散(即方差最大)。投影计算:样本 x i x_i xi 在方向 w w w 上的投影长度(标量)为 x i T w x_i^T w xiTw。方差计算:因为数据已经中心化(均值为0),所以投影后的数据均值也为0。投影数据的方差 D ( x ) D(x) D(x) 可以表示为: D ( x ) = 1 n ∑ i = 1 n ( x i T w ) 2 D(x) = \frac{1}{n} \sum_{i=1}^{n} (x_i^T w)^2 D(x)=n1i=1∑n(xiTw)2转化为矩阵形式:为了方便推导,我们将其转化为矩阵运算形式。 ∑ i = 1 n ( x i T w ) 2 = ∑ i = 1 n ( x i T w ) ( x i T w ) T = ∑ i = 1 n ( w T x i ) ( x i T w ) = w T ( ∑ i = 1 n x i x i T ) w \begin{aligned} \sum_{i=1}^{n} (x_i^T w)^2 &= \sum_{i=1}^{n} (x_i^T w)(x_i^T w)^T \\ &= \sum_{i=1}^{n} (w^T x_i)(x_i^T w) \\ &= w^T \left( \sum_{i=1}^{n} x_i x_i^T \right) w \end{aligned} i=1∑n(xiTw)2=i=1∑n(xiTw)(xiTw)T=i=1∑n(wTxi)(xiTw)=wT(i=1∑nxixiT)w这里, 1 n ∑ i = 1 n x i x i T \frac{1}{n} \sum_{i=1}^{n} x_i x_i^T n1∑i=1nxixiT 正好是样本的协方差矩阵 (Covariance Matrix)。我们将其记为 Σ \Sigma Σ (Sigma)。 Σ = 1 n X T X \Sigma = \frac{1}{n} X^T X Σ=n1XTX(注:这里假设 X X X 是 n × d n \times d n×d 矩阵。如果是样本无偏估计,分母通常是 n − 1 n-1 n−1,但不影响推导结果)最终的优化目标函数: Maximize J ( w ) = w T Σ w \text{Maximize } J(w) = w^T \Sigma w Maximize J(w)=wTΣw约束条件: ∥ w ∥ = 1 ⇒ w T w = 1 \|w\| = 1 \Rightarrow w^T w = 1 ∥w∥=1⇒wTw=13. 拉格朗日乘数法求解这是一个带约束的优化问题,我们可以使用拉格朗日乘数法 (Lagrange Multipliers) 来求解。构造拉格朗日函数:引入拉格朗日乘子 λ \lambda λ: L ( w , λ ) = w T Σ w − λ ( w T w − 1 ) L(w, \lambda) = w^T \Sigma w - \lambda (w^T w - 1) L(w,λ)=wTΣw−λ(wTw−1)求导并令其为 0:对向量 w w w 求偏导: ∂ L ∂ w = ∂ ( w T Σ w ) ∂ w − ∂ ( λ w T w ) ∂ w \frac{\partial L}{\partial w} = \frac{\partial (w^T \Sigma w)}{\partial w} - \frac{\partial (\lambda w^T w)}{\partial w} ∂w∂L=∂w∂(wTΣw)−∂w∂(λwTw)利用矩阵求导公式 ∂ ( x T A x ) ∂ x = ( A + A T ) x \frac{\partial (x^T A x)}{\partial x} = (A + A^T)x ∂x∂(xTAx)=(A+AT)x。因为协方差矩阵 Σ \Sigma Σ 是对称矩阵 ( Σ = Σ T \Sigma = \Sigma^T Σ=ΣT),所以第一项的导数是 2 Σ w 2\Sigma w 2Σw。 ∂ L ∂ w = 2 Σ w − 2 λ w \frac{\partial L}{\partial w} = 2\Sigma w - 2\lambda w ∂w∂L=2Σw−2λw令导数为 0: 2 Σ w − 2 λ w = 0 2\Sigma w - 2\lambda w = 0 2Σw−2λw=0得出结论: Σ w = λ w \Sigma w = \lambda w Σw=λw4. 结果的物理意义上面的公式 Σ w = λ w \Sigma w = \lambda w Σw=λw 正是线性代数中特征值和特征向量的定义!这意味着:最佳投影方向 w w w:必须是协方差矩阵 Σ \Sigma Σ 的特征向量。最大方差是多少?我们将 Σ w = λ w \Sigma w = \lambda w Σw=λw 代入目标函数 J ( w ) J(w) J(w): J ( w ) = w T Σ w = w T ( λ w ) = λ ( w T w ) = λ J(w) = w^T \Sigma w = w^T (\lambda w) = \lambda (w^T w) = \lambda J(w)=wTΣw=wT(λw)=λ(wTw)=λ所以,投影后的方差大小直接等于对应的特征值 λ \lambda λ。结论:为了使方差最大,我们应该选择最大特征值对应的特征向量作为第一主成分。如果要找第二主成分,就选第二大特征值对应的特征向量,以此类推。
三、利用PCA进行人脸识别
1.数据准备
本次实验的数据集ORL-Faces包含40个人,每人拥有10张正脸照片,取每个人的7张照片,作为训练数据。那么每个人剩下的3张照片,计算机还没有看过,就可以在计算机认识了每一个人之后用来考验计算机是否真的能够正确识别图像中的人是谁。
2.
bigList = []
# 导入人脸模型库
faceCascade = cv2.CascadeClassifier(r'C:\Python\haarshare\haarcascade_frontalface_alt.xml')
# 遍历30个人
for i in range(1, 31):
# 遍历每个人的7张照片
for j in range(1, 8):
list = []
# 直接读入灰度照片
image = cv2.imread("C:\\Users\\tangyitao\\Pictures\\Saved Pictures\\trainFace\\train"
+ str(i) + "\\train" + str(i) + "" + str(j) + ".jpg", 0)
faces = faceCascade.detectMultiScale(image, 1.3, 5)
for (x, y, w, h) in faces:
# 裁剪人脸区域为 128 * 128 大小
cutResize = cv2.resize(image[y:y + h, x:x + w], (128, 128),
interpolation=cv2.INTER_CUBIC)
# 遍历图片行数
for x in range(cutResize.shape[0]):
# 遍历图片每一行的每一列
for y in range(cutResize.shape[1]):
# 将每一处的灰度值添加至列表
list.append(cutResize[x, y])
bigList.append(list)
print("\n\ntrainFaceMat ")
trainFaceMat = numpy.mat(bigList) # 得到训练样本矩阵
print("trainFaceMat.shape[0] ",trainFaceMat.shape[0])
print("trainFaceMat.shape[1]",trainFaceMat.shape[1])
print(trainFaceMat)
3.规格化
meanFaceMat = numpy.mean(trainFaceMat, axis=0) # 每一列的和除行数,得到平均值
print("meanFaceMat \n\n")
print("meanFaceMat.shape[0] ",meanFaceMat.shape[0])
print("meanFaceMat.shape[1] ",meanFaceMat.shape[1])
print(meanFaceMat)
normTrainFaceMat = trainFaceMat - meanFaceMat
print("\n\n normTrainFaceMat")
print("normTrainFaceMat.shape[0] ",normTrainFaceMat.shape[0])
print("normTrainFaceMat.shape[1] ",normTrainFaceMat.shape[1])
print(normTrainFaceMat)
4.计算协方差矩阵并求的特征值和特征向量
covariance = numpy.cov(normTrainFaceMat)
# 求得协方差矩阵的特征值和特征向量
eigenvalue, featurevector = numpy.linalg.eig(covariance)
5.对特征值进行排序并保留k个最大特征值的特征向量
sorted_Index = numpy.argsort(eigenvalue)
topk_evecs = featurevector[:,sorted_Index[:-140-1:-1]]
6.计算投影
7.创建测试样本矩阵
# 主要思想和第一步计算trainFaceMat差不多,这里只需要添加一张照片的数据
list = []
faceCascade = cv2.CascadeClassifier(r'C:\Python\haarshare\haarcascade_frontalface_alt.xml')
# fileName 为待识别图片的文件名,读入灰度人脸
image = cv2.imread(fileName, 0)
faces = self.faceCascade.detectMultiScale(self.image, 1.3, 5)
for (x, y, w, h) in self.faces:
cut = image[y:y + h, x:x + w]
# 处理成 128 * 128大小的人脸
cutResize = cv2.resize(cut, (128, 128), interpolation=cv2.INTER_CUBIC)
for x in range(cutResize.shape[0]):
for y in range(cutResize.shape[1]):
list.append(cutResize[x, y])
testFaceMat = numpy.mat(list)
8.进行规格化
normTestFaceMat = testFaceMat - meanFaceMat
9.计算欧式距离找到匹配人脸
eigen_test_sample = numpy.dot(normTestFaceMat, eigenface)
# 以 eigen_train_sample[0]与eigen_test_sample的欧式距离赋值 minDistance
minDistance = numpy.linalg.norm(eigen_train_sample[0] - eigen_test_sample)
# num 记录训练集中第几个人与待识别人为同一人
num = 1
# 遍历 eigen_train_sample 的每一行,在此处,eigen_train_sample.shape[0] = 210。
for i in range(1, eigen_train_sample.shape[0]):
distance = numpy.linalg.norm(eigen_train_sample[i] - eigen_test_sample)
if minDistance > distance:
minDistance = distance
# 30个人中,每个人有7张照片,i是记录的第几张照片
# 因此记录第几个人的num为 i // 7 + 1。
num = i // 7 + 1
总结
PCA 作为机器学习中经典的线性降维算法,核心思想是通过正交变换,将原始高维数据投影到一组新的正交基上,旨在最大化投影方向的方差(保留最多信息)并去除相关性。
在应用上,PCA 被广泛用于数据预处理、图像压缩及高维数据可视化,能有效降低计算复杂度并缓解“维数灾难”。其优势在于计算简便、无参数限制且理论基础严谨。然而,作为一种无监督的线性方法,PCA 在处理非线性流形数据时效果有限,且难以解释特征的物理意义。此外,仅依赖方差最大化可能导致包含重要类别信息的低方差特征被舍弃,因此在特定任务中需谨慎结合其他方法使用。
更多推荐
所有评论(0)