在数据分析和机器学习的世界里,维度灾难是一个不可忽视的问题。随着数据维度的增加,计算量急剧上升,模型复杂度变高,同时可能引入噪声和冗余信息,影响模型的性能和解释性。主成分分析(Principal Component Analysis, PCA)作为一种经典且强大的数据降维技术,能够有效解决这些问题。
一、PCA基本原理
PCA通过线性变换将原始数据映射到一个新的坐标系统中,使得任何投影的第一大方差在第一个坐标(称为主成分)上,第二大方差在第二个坐标上,依此类推。这样,数据的主要特征就被保留在了前几个主成分中,而后面的成分则包含了较少的信息,可以被忽略,从而实现数据降维。
核心思想:
- 最大化方差:PCA希望投影后的数据在第一个主成分上具有最大的方差,即数据在该方向上的分散程度最大,这样能够更好地保留原始数据的信息。
- 正交性:各个主成分之间是相互正交的,即它们之间没有线性相关性,避免了信息的重叠。
二、PCA算法步骤
1. 数据标准化
目的:PCA对数据的尺度非常敏感,即如果不同特征的度量单位不同(如一个是米,另一个是千克),或者数据的范围差异很大,那么这些特征在计算协方差矩阵时会产生不同的影响,导致结果偏向于数值较大的特征。因此,标准化是使每个特征的均值为0,方差为1,以确保每个特征在PCA分析中具有相同的权重。
方法:对于每个特征,从其每个值中减去该特征的均值,然后除以其标准差。
2. 计算协方差矩阵
目的:协方差矩阵是一个方阵,其元素表示各对特征之间的协方差,衡量了它们之间的线性关系。
方法:对于m个特征的数据集,协方差矩阵是一个m×m的矩阵,其中每个元素C[i][j]是第i个特征和第j个特征的协方差。
3. 计算协方差矩阵的特征值和特征向量
目的:特征值和特征向量描述了协方差矩阵的固有特性。特征值表示对应特征向量方向上的方差大小,即该方向上的信息量。特征向量则是数据在新的坐标系统中的方向,即主成分的方向。
方法:使用线性代数的方法(如特征值分解或奇异值分解)计算协方差矩阵的特征值和特征向量。
4. 选择主成分
目的:选择最重要的主成分,即那些能够最大程度保留原始数据信息的方向。
方法:按照特征值的大小从大到小排序,选择前k个最大的特征值对应的特征向量作为主成分。k的选择通常基于特征值的累积贡献率(即前k个特征值的和占总特征值之和的比例)或根据实际需要。
5. 数据投影
目的:将原始数据转换到新的坐标系统(由选定的主成分构成)中,得到降维后的数据。
方法:对于每个样本,将其与选定的k个特征向量进行点积运算,得到该样本在k个主成分上的投影,即降维后的数据。
实例:
from sklearn.decomposition import PCA
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
data = pd.read_excel('hua.xlsx')
#此行代码加载了名为hua.xlsx的Excel文件到pandas DataFrame中。
x = data.iloc[:, :-1]
y = data.iloc[:, -1]
pca = PCA(n_components=0.90)
pca.fit(x)
#您使用PCA进行特征降维,目标是保留原始数据90%的方差。
print('特征所占百分比:{}', format(sum(pca.explained_variance_ratio_)))
print(pca.explained_variance_ratio_)
print('降维后数据')
new_x = pca.transform(x)
print(new_x)
x_train, x_test, y_train, y_test = \
train_test_split(new_x, y, test_size=0.2, random_state=0)
#用train_test_split函数将数据集划分为训练集和测试集,测试集占总数据的20%。
classifier = LogisticRegression()
classifier.fit(x_train, y_train)
train_pred = classifier.predict(x_train)
print(train_pred)
test_pred = classifier.predict(x_test)
print(test_pred)
#您使用逻辑回归模型进行训练和预测。
from sklearn import metrics
print(metrics.classification_report(y_train, train_pred))
print(metrics.classification_report(y_test, test_pred))