PCA生成特征脸异常求助:结果失真且布满噪点
特征脸生成噪点问题排查与修正
核心问题分析
- 未初始化的样本数据:
data_matrix第0行全程为0(循环从i=1开始),严重干扰均值计算和协方差矩阵,引入无效噪声。 - 协方差矩阵计算错误:当样本数N远小于特征维度D时,直接计算
D×D的协方差矩阵normalized.T @ normalized会导致数值不稳定,且计算效率极低。正确做法是先计算N×N的矩阵normalized @ normalized.T,再推导原空间的特征向量。 - 特征向量选取错误:
np.linalg.eig返回的特征值是无序的,直接取最后一列无法保证是最大特征值对应的特征向量,需要先对特征值排序。 - 图像预处理维度混乱:两次max pooling的reshape步骤(尤其是
order='F')打乱了图像的空间结构,导致特征向量重塑后无法还原正确的人脸结构。 - 不必要的量化操作:用
np.ceil对缩放后的特征向量取整,引入了额外的量化噪点。
修正后的代码实现
import numpy as np import matplotlib.pyplot as plt import matplotlib.image as mpimg dataset_size = 500 width = 178 height = 218 def rgb2gray(rgb): return np.dot(rgb[...,:3], [0.2989, 0.5870, 0.1140]) # 初始化数据矩阵,修正下采样后的维度计算 down_width = (width + 2) // 2 // 2 # 两次2x2 max pooling后的宽度 down_height = (height + 2) // 2 // 2 data_matrix = np.zeros((dataset_size, down_width * down_height)) # 填充所有样本(从i=0开始) for i in range(dataset_size): # 统一文件名格式,避免分支判断 img_path = f'blah/{i:06d}.jpg' img = mpimg.imread(img_path) temp_blah = rgb2gray(img) # 边缘填充1像素 temp_blah = np.pad(temp_blah, 1, mode='constant') # 第一次2x2 max pooling(行优先) temp_blah = temp_blah.reshape(-1, 2, temp_blah.shape[1]) grayscale = temp_blah.max(axis=1) # 第二次2x2 max pooling(行优先,避免Fortran顺序打乱结构) grayscale = grayscale.reshape(grayscale.shape[0], -1, 2) grayscale = grayscale.max(axis=2) # 展平存入数据矩阵 data_matrix[i, :] = grayscale.flatten() # 归一化 avg = np.mean(data_matrix, axis=0) normalized = data_matrix - avg print(f"normalized | shape: {normalized.shape}") # 计算低维协方差矩阵(N×N),避免高维计算 print("calculating covariance matrix...") cov_small = normalized @ normalized.T / (dataset_size - 1) # 除以样本数-1做无偏估计 # 求解低维特征值和特征向量 w_small, v_small = np.linalg.eig(cov_small) # 转换为原特征空间的特征向量 v = normalized.T @ v_small # 归一化特征向量 v = v / np.linalg.norm(v, axis=0) # 按特征值从大到小排序,取最大的特征向量 sorted_indices = np.argsort(np.abs(w_small))[::-1] top_eigenvec = np.real(v[:, sorted_indices[0]]) # 重塑为下采样后的图像形状 eigenface = top_eigenvec.reshape(down_height, down_width) # 显示特征脸,无需强制缩放到0-255,利用matplotlib自动适配 plt.imshow(eigenface, cmap='gray') plt.axis('off') plt.show()
关键修正点说明
- 修复样本初始化:循环从
i=0开始,填充所有样本,避免全0行干扰计算。 - 优化协方差计算:通过低维矩阵推导特征向量,解决高维计算的数值不稳定问题,同时提升效率。
- 正确排序特征向量:对特征值排序后选取最大的对应向量,确保得到真正的主成分。
- 修正图像预处理:调整max pooling的reshape方式,保持图像空间结构,避免维度混乱。
- 移除量化噪点:直接使用特征向量的原始值显示,利用matplotlib的灰度映射自动适配,无需手动缩放取整。
内容的提问来源于stack exchange,提问作者Legend ile
相关产品推荐
相关产品推荐

