You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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()

关键修正点说明

  1. 修复样本初始化:循环从i=0开始,填充所有样本,避免全0行干扰计算。
  2. 优化协方差计算:通过低维矩阵推导特征向量,解决高维计算的数值不稳定问题,同时提升效率。
  3. 正确排序特征向量:对特征值排序后选取最大的对应向量,确保得到真正的主成分。
  4. 修正图像预处理:调整max pooling的reshape方式,保持图像空间结构,避免维度混乱。
  5. 移除量化噪点:直接使用特征向量的原始值显示,利用matplotlib的灰度映射自动适配,无需手动缩放取整。

内容的提问来源于stack exchange,提问作者Legend ile

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 22:13:13