PCA分析中最大特征值特征向量与最大方差轴不匹配问题排查
半圆柱点云PCA分析异常问题排查
问题背景
用Blender生成半圆柱模拟点云数据集,进行PCA分析求解特征向量与特征值:
- Z轴为圆柱高度方向,方差统计显示Z轴方差最大:
np.var(data, axis=0) x 0.225168 y 0.057463 z 33.122499 dtype: float64
- 理论上最大特征值对应的特征向量应沿Z轴,但实际绘图显示最小特征值的特征向量沿圆柱轴;将点云投影到最小特征值对应的两个特征向量构成的平面时,未得到预期圆形,反而呈圆柱状。
- 已确认特征向量选择逻辑正确,但结果不符合预期,同时对Blender点云导出的轴设置(轴选为Z、正方向选为Y或X)存在困惑。
相关代码
import numpy as np import pandas as pd from scipy.spatial.transform import Rotation as R import matplotlib.pyplot as plt from sklearn.preprocessing import StandardScaler from r_pca import R_pca # Ensure you have the r_pca library installed from hyper_fit_with_lts import * from cfg_fit_cylinder import * def plot_vectors(data, eigvecs, eigenvals): colors = ['r', 'g', 'b'] # Create a 3D scatter plot of the centered data fig = plt.figure() ax = fig.add_subplot(111, projection='3d') ax.scatter(data[:, 0], data[:, 1], data[:, 2], label='Data', c='g', marker='x', alpha=0.1) # Plot eigenvectors as vectors for i in range(3): vector = eigvecs[:, i] ax.quiver(0, 0, 0, vector[0], vector[1], vector[2], color=colors[i], label=f'Eigenvector {eigvecs[:, i]}, {eigenvals[i]}') ax.set_xlabel('X-axis') ax.set_ylabel('Y-axis') ax.set_zlabel('Z-axis') ax.legend() plt.show() data = pd.read_csv(PATH_TO_POINT_CLOUD, header=None) data.columns = ['x', 'y', 'z'] rpca = R_pca(data.values) # RPCA L, S = rpca.fit(max_iter=10_000) column_means = np.mean(L, axis=0) centered_L = L - column_means cov_matrix = np.cov(centered_L, rowvar=False) eigenvalues, eigenvectors = np.linalg.eig(cov_matrix) print("Eigenvectors (Principal Components):") print(eigenvectors) print("\nEigenvalues") print(eigenvalues) centered_data = data - data.mean() sorted_indices = np.argsort(-eigenvalues) sorted_eigenvalues = sorted(eigenvalues, reverse=True) sorted_eigenvectors = eigenvectors[:, sorted_indices] plot_vectors(data.values, sorted_eigenvectors, sorted_eigenvalues) smallest_components = sorted_eigenvectors[:, 1:] # Smallest eigenvectors (eigenvalues) circle_projected_data = centered_data @ smallest_components cylinder_2d_projection = sorted_eigenvectors[:, :2].T @ centered_data.T cylinder_1d_projection = sorted_eigenvectors[:, 0].T @ centered_data.T cylinder_height = np.ptp(cylinder_1d_projection) circle_projected_data_without_centering = data @ smallest_components fig1 = plt.figure() ax1 = fig1.add_subplot(111) ax1.scatter(circle_projected_data[0], circle_projected_data[1], color='r', label='Circle 2D in XY') ax1.set_xlabel('X-axis') ax1.set_ylabel('Y-axis') ax1.set_title('Cycle 2D Projected Data') ax1.set_aspect('equal') ax1.legend() plt.show()
排查方向
1. RPCA与后续数据不匹配
代码中用RPCA分解得到的低秩部分L计算协方差矩阵和特征值,但后续的中心化、绘图、投影操作全部使用原始data而非处理后的L。这会导致PCA计算的是低秩数据的特征,而可视化的是原始数据,两者维度分布不一致,必然出现结果矛盾。
- 修复:将后续所有用到
data或centered_data的地方替换为L或centered_L,保持数据来源统一。
2. Blender轴系映射偏差
Blender默认轴系为Y轴向上,而Matplotlib等工具的3D绘图默认Z轴向上。如果导出点云时轴设置错误,会导致你认知的Z轴(圆柱高度)与实际数据的轴方向不匹配。
- 验证:打印
L或data的数值范围,确认Z轴是否为数值跨度最大的轴;若不是,调整Blender导出时的轴设置,或在代码中手动交换轴(比如将Y和Z轴数据互换)。
3. 投影逻辑维度错误
在绘制投影图时,circle_projected_data是(n,2)的二维数组,但代码中用circle_projected_data[0]和circle_projected_data[1]取数,这只会获取第一行的两个值,而非所有点的X、Y投影坐标,导致绘图异常。
- 修复:将绘图代码改为
ax1.scatter(circle_projected_data[:, 0], circle_projected_data[:, 1], color='r', label='Circle 2D in XY')。
4. 特征值排序验证
虽然使用了np.argsort(-eigenvalues)进行降序排序,但可通过以下方式验证特征向量与轴的对应关系:
- 计算最大特征值对应向量与[0,0,1]的点积,绝对值接近1则说明该向量沿Z轴;
- 打印
sorted_eigenvalues和sorted_eigenvectors,确认特征值大小与向量方向的对应关系是否符合预期。
内容的提问来源于stack exchange,提问作者Karantai
相关产品推荐
相关产品推荐

