参考文章:https://blog.csdn.net/qq_44112474/article/details/93908037
一、定义:
主成分分析(PCA)是利用正交变换把线性相关变量表示的观测数据转换为少数几个由线性无关变量表示的数据,线性无关的变量称为主成分。
二、算法步骤:
-
数据预处理
原始数据-对应变量的均值;
目的是把数据中心化,减少过度拟合的可能性。 -
求样本协方差矩阵
3.求协方差矩阵的特征值和特征向量
4.选取最大k个特征值对应的特征向量(其中k是小于维度总数的一个值):
将特征值按照从大到小的顺序排序,选择其中最大的k个,然后将其对应的k个特征向量分别作为列向量组成特征向量矩阵。
通常取k使得累计方差贡献率达到规定百分比以上。
5.得到新的矩阵
将样本点投影到选取的特征向量上。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
def pca(dataX, k):
average = np.mean(dataX, axis=0) # 按列求均值,即每个变量的均值
ro, co = dataX.shape
data_adjust = []
avgs = np.tile(average, (ro, 1)) # 复制几行几列
data_adjust = dataX - avgs # 原数据-列平均值
# 求协方差
covX = np.cov(data_adjust.T) # 每行是一个变量
# 特征值+特征向量 对称矩阵eigh与eig结果相同,eigh效率高
eigenvalue, eigenvec = np.linalg.eigh(covX)
# 特征值由大到小排序
eigenvalue_sort = np.sort(eigenvalue)[::-1]
index = np.argsort(-eigenvalue)
# pca score
selectVec = eigenvec.T[index[:2]]
finalData = np.dot(data_adjust, selectVec.T) #降维后变量
reconData = np.dot(finalData, selectVec) + average #原始变量
explained = eigenvalue_sort[:k] / eigenvalue_sort.sum() # 累计贡献率
return finalData, reconData, explained
def plotBestFit(data1, data2):
# 绘图
dataArr1 = np.array(data1)
dataArr2 = np.array(data2)
m = np.shape(dataArr1)[0]
axis_x1 = []
axis_y1 = []
axis_x2 = []
axis_y2 = []
for i in range(m):
axis_x1.append(dataArr1[i, 0])
axis_y1.append(dataArr1[i, 1])
axis_x2.append(dataArr2[i, 0])
axis_y2.append(dataArr2[i, 1])
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(axis_x1, axis_y1, s=50, c='red', marker='s')
ax.scatter(axis_x2, axis_y2, s=50, c='blue')
plt.xlabel('x1')
plt.ylabel('x2')
plt.show()
dataX = np.array(pd.read_excel('./data/data_pca.xlsx', header=None)).astype(np.float)
finalData, reconData, explained = pca(dataX, 2)
plotBestFit(finalData, reconData)
原始数据:
image.png
例:2维数据降至1维
image.png
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei'] #正常显示标签
data=pd.read_excel('data.xlsx',header=None)
x=data.iloc[:,1]
y=data.iloc[:,2]
cov_mat = np.cov(x,y) #协方差
# 2. 计算协方差矩阵的特征值
eigenvalues,eigenvectors = np.linalg.eig(cov_mat)
eigenvalues,eigenvectors
k = 1 # 降维后的目标维度
# 对特征值进行排序,取前k个
topk = np.argsort(eigenvalues)[0:k]
# 前k个最大的特征值对应的特征向量与原矩阵相乘
result = np.matmul(data,eigenvectors[topk].T)
plt.scatter(result[:,0],result[:,0].shape[0]*[1],color='b')#绘制一维图
plt.show()
网友评论