在这里简单记录下学习PCA的一次简单实践;
在数据挖掘中,维度太大是一个很大的问题,影响挖掘的效率,PCA是一个最常用的、简单、基础理论完备的方法。
具体手推的例子这里省略。。。
导入鸢尾花数据
from sklearn import datasets
iris = datasets.load_iris()
x = iris.data
对数据进行标准化处理
# 取得各个特征的均值
n_samples, n_features = X.shape
# mean = np.array([np.mean(X[:, i]) for i in range(n_features)])
mean = X.mean(axis=1, keepdims=True)
# 标准化
normal_X = X - mean
计算协方差矩阵
# 协方差矩阵
cov_matrix = np.dot(normal_X, np.transpose(normal_X)) / (n_features - 1)
print(cov_matrix)
# cov = np.cov(X)
# print(cov)
计算协方差矩阵的特征值和特征向量
eig_val, eig_vec = np.linalg.eig(cov_matrix)
print("特征值:")
print(eig_val)
# print(eig_val.shape)
print("特征向量:")
print(eig_vec)
计算方差贡献率
# 计算方差贡献率
y_contri = np.array([eig_val[i] / eig_val.sum() for i in range(len(eig_val))])
print("y的方差贡献率:")
print(y_contri)
选取前K个方差贡献率的特征向量,构成线性变换矩阵feature
我这里偷懒了,用肉眼选取k的值。。。
# 将对应的特征值和特征向量存入eig_pairs
eig_pairs = [(np.abs(eig_val[i]), eig_vec[:, i]) for i in range(len(eig_val))]
# 按eig_val从大到小顺序排列eig_vec
eig_pairs.sort(reverse=True)
# 选择前k个eig_vec
feature = np.array([ele[1] for ele in eig_pairs[:k]])
线性变换矩阵和原数据矩阵做点积得主成分对各个特征的相关系数
result = np.dot(feature, X)
完整代码如下:
from sklearn import datasets
import numpy as np
def load_data():
"""
加载鸢尾花数据
"""
iris = datasets.load_iris()
x = iris.data
return x
def pca(X, k): # k是维度
# 取得各个特征的均值
n_samples, n_features = X.shape
# mean = np.array([np.mean(X[:, i]) for i in range(n_features)])
mean = X.mean(axis=1, keepdims=True)
# 标准化
normal_X = X - mean
# print(normal_X)
# 协方差矩阵
cov_matrix = np.dot(normal_X, np.transpose(normal_X)) / (n_features - 1)
print(cov_matrix)
# cov = np.cov(X)
# print(cov)
# 计算特征值和特征向量
# scatter_matrix = np.dot(np.transpose(normal_X), normal_X)
# eig_val, eig_vec = np.linalg.eig(np.transpose(scatter_matrix))
eig_val, eig_vec = np.linalg.eig(cov_matrix)
print("特征值:")
print(eig_val)
# print(eig_val.shape)
print("特征向量:")
print(eig_vec)
# 计算方差贡献率
y_contri = np.array([eig_val[i] / eig_val.sum() for i in range(len(eig_val))])
print("y的方差贡献率:")
print(y_contri)
# 将对应的特征值和特征向量存入eig_pairs
eig_pairs = [(np.abs(eig_val[i]), eig_vec[:, i]) for i in range(len(eig_val))]
# 按eig_val从大到小顺序排列eig_vec
eig_pairs.sort(reverse=True)
# 选择前k个eig_vec
feature = np.array([ele[1] for ele in eig_pairs[:k]])
# print(feature)
# result = np.dot(X, np.transpose(feature))
result = np.dot(feature, X)
# print(result.shape)
return result
# print(load_data().shape)
data = np.transpose(load_data())
result = pca(data, 1)
print("结果为:")
print(result)