第一部分:基本含义
PCA主要用于特征降维。
PCA,全称为主成分分析(Principal Component Analysis),是一种数据降维技术,常用于处理高维数据。其主要目的是通过减少变量数量来简化数据集,同时尽可能保留数据的主要信息。
复杂问题简单化,化繁为简,做事抓住核心,射人先射马,擒贼先擒王
因此最重要的部分就是对“本质”的抓取
第二部分:PCA的核心思想和原理
我们以分类问题为例:
通过降维度,也就是投影到一个坐标轴上,效果分别如下:
我们投射到x轴和y轴两类,但是如何选用哪一个呢?
我们就需要看哪一个在降维之后任然能够具有很好的区分性,能够尽量体现降维之前数据之间的分布情况和相互关系。
可以看出横轴的比纵轴的要好一点,因为分布比较分散,但是横轴不一定是最好的
最好的投影轴如下:
上面的这条红线在投影之后距离最大。
那么找到的这个红线,就叫“主成分PC”
方差这块如果不是很懂,可以看我博客:机器学习之线性代数基础知识汇总补充(内积)-CSDN博客
最终我们的目标:
就需要:
方差Var(特征1)和Var(特征2)最大,协方差Cov(特征1,特征2)为最小(为0)
优化目标也就是斜线上,从大到小排列,上下两个区域的值都是0
第三部分:PCA求解算法
(1)PCA主要求解步骤
①原始数据矩阵化X后,零均值化
②求协方差矩阵
③求协方差矩阵的特征值和特征向量
对特征值和特征向量不太懂的可以看我的博客:机器学习+线性代数(特征值和特征向量)-CSDN博客
④按特征值从大到小取特征向量前k行组成矩阵w
⑤获取降维后的数据
(2)注意事项
验证集,测试集执行同样的降维
验证集,测试集执行零均值化操作时,均值须来自于训练集
保证训练集,测试集独立同分布一致性(如果不能保证,则可能会出现一种叫做方差漂移的问题)
(3)PCA的主要作用
①有效缓解维度灾难
②数据降噪效果好
③降维后数据特征独立
④无法解决过拟合
(因为它可能舍弃掉的事重要信息,保留下来的是一些没有那么重要的信息,这主要是因为,可能它在训练集上的表现情况体现的是这个特征不重要,但是因为训练样本太少,其实这个特征很重要)
第四部分:PCA算法代码实现(二维到一维)
(1)导包
#第一部分:导包
import numpy as np
(2)创建数据集
#第二部分:创建数据集
import matplotlib.pyplot as plt
w, b = 1.8, 2.5
np.random.seed(0)
x1 = np.random.rand(100) * 4#仅仅只是代表100个数据(100,)
noise = np.random.randn(100)
x2 = w * x1 + b + noise#仅仅只是代表100个数据(100,)
x = np.vstack([x1, x2]).T#纵向合并转置(100, 2)
print(x.shape)
plt.scatter(x[:, 0], x[:, 1])
plt.show()
(3)PCA降维
①零均值化
#第三部分:开始进行PCA降维
#3.1零均值化
x -= np.mean(x, axis=0)
plt.scatter(x[:, 0], x[:, 1])
plt.show()
②使用PCA降维(包含第三部分中PCA主要求解步骤的2,3,4)
#3.2使用PCA
from sklearn.decomposition import PCA
pca = PCA(n_components=1)# 指定只提取一个主成分
pca.fit(x)
pca.components_#属性返回一个数组,其中包含提取的主成分。
#它将返回形状为 (1, n_features) 的数组,表示选定的主成分的方向向量。
print(pca.components_)
#输出结果为:[[0.42746553 0.90403165]]代表第一个主成分的方向向量
#绘制找到的主成分的这条基准线(主成分PC线)
plt.scatter(x[:, 0], x[:, 1], s=10)
plt.plot(
np.array([pca.components_[0][0] * -1, pca.components_[0][0] * 1]) * 5,
np.array([pca.components_[0][1] * -1, pca.components_[0][1] * 1]) * 5,
c='r'
)
plt.show()
③数据降维
#3.3数据降维
x_pca = pca.transform(x)
x_pca.shape
plt.scatter(x_pca, np.zeros_like(x_pca), s=10)
plt.show()
④数据升维还原原先数据图形
#3.4数据升维
x_pca_inv = pca.inverse_transform(x_pca)
plt.scatter(x[:, 0], x[:, 1], s=10)
plt.scatter(x_pca_inv[:, 0], x_pca_inv[:, 1], s=10, c='r')
plt.show()
得到的红线不是连续的这是因为通过上面的降维,往往会损失部分的原有数据特征。
(4)完整pycharm代码实现
#第一部分:导包
import numpy as np
#第二部分:创建数据集
import matplotlib.pyplot as plt
w, b = 1.8, 2.5
np.random.seed(0)
x1 = np.random.rand(100) * 4#仅仅只是代表100个数据(100,)
noise = np.random.randn(100)
x2 = w * x1 + b + noise#仅仅只是代表100个数据(100,)
x = np.vstack([x1, x2]).T#纵向合并转置(100, 2)
print(x.shape)
plt.scatter(x[:, 0], x[:, 1])
plt.show()
#第三部分:开始进行PCA降维
#3.1零均值化
x -= np.mean(x, axis=0)
plt.scatter(x[:, 0], x[:, 1])
plt.show()
#3.2使用PCA
from sklearn.decomposition import PCA
pca = PCA(n_components=1)# 指定只提取一个主成分
pca.fit(x)
pca.components_#属性返回一个数组,其中包含提取的主成分。
#它将返回形状为 (1, n_features) 的数组,表示选定的主成分的方向向量。
print(pca.components_)
#输出结果为:[[0.42746553 0.90403165]]代表第一个主成分的方向向量
#绘制找到的主成分的这条基准线(主成分PC线)
plt.scatter(x[:, 0], x[:, 1], s=10)
plt.plot(
np.array([pca.components_[0][0] * -1, pca.components_[0][0] * 1]) * 5,
np.array([pca.components_[0][1] * -1, pca.components_[0][1] * 1]) * 5,
c='r'
)
plt.show()
#3.3数据降维
x_pca = pca.transform(x)
x_pca.shape
plt.scatter(x_pca, np.zeros_like(x_pca), s=10)
plt.show()
#3.4数据升维
x_pca_inv = pca.inverse_transform(x_pca)
plt.scatter(x[:, 0], x[:, 1], s=10)
plt.scatter(x_pca_inv[:, 0], x_pca_inv[:, 1], s=10, c='r')
plt.show()
第五部分:基础降维代码实现(高维)
我们这次使用一个更高维的数据集(手写数字数据集):
(1)导包
#第一部分:导包
import numpy as np
import matplotlib.pyplot as plt
(2)创建数据集
#第二部分:加载数据集
from sklearn.datasets import load_digits
digits = load_digits()
x = digits.data
y = digits.target
x.shape, y.shape
(3)数据集划分
#第三部分:数据集划分
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=233)
(4)PCA降维并可视化全部主成分方差权重数据
from sklearn.decomposition import PCA
#4.1对所有主成分进行数据效果可视化展示
pca = PCA()#默认的是对所有的主成分进行划分
pca.fit(x_train)
#输出每一个特征对应的重要性比例(方差所占的大小权重)
print(pca.explained_variance_ratio_)#1.50332671e-01 代表的是15%左右的意思
#画出这些特征权重从0累加到1的过程中的变化大小
ratio_cum = np.cumsum(pca.explained_variance_ratio_)
plt.plot(ratio_cum)
plt.show()
因此我们就可以看出总共有64个特征,但是光前20个特征的方差权重和就能占比超过90%,也就是说我们可以通过这20维的数据来描述原始数据将近90%的信息。
(6)直接设置保留的特征总数
#4.2直接设置要保留的特征值数目
pca = PCA(20)
pca.fit(x_train)
(7)直接设置要保留原始数据的百分比
#4.3直接设置要保留原始数据的百分比
pca = PCA(0.9)
pca.fit(x_train)
print(pca.n_components_)#输出要达到0.9的原始信息需要的特征数
代表输出要达到0.9的原始信息需要的特征数为21个
(8)模型评估-查看降维后的效果(使用逻辑回归)
#第五部分:查看降维后的效果(使用逻辑回归)
from sklearn.linear_model import LogisticRegression
clf = LogisticRegression(solver='saga', tol=0.001, max_iter=500, random_state=233)
①没有降维的情况下使用逻辑会的模型评分score以及花费时间
%%time
clf.fit(x_train,y_train)
clf.score(x_test,y_test)
#5.1没有降维的情况下使用逻辑会的模型评分score以及花费时间
注意:这段代码需要在jupyter上面运行,因为含有%%time魔法,pycharm无法运行。
②有降维的情况下使用逻辑会的模型评分score以及花费时间
%%time
x_train_pca = pca.transform(x_train)
x_test_pca = pca.transform(x_test)
clf.fit(x_train_pca, y_train)
clf.score(x_test_pca, y_test)
#5.2有降维的情况下使用逻辑会的模型评分score以及花费时间
可以看到耗时从979变为405,而准确度只是下降了不到1%
(9)所有代码汇总
注意:由于这个(8)中的代码有%%time,因此这个全部代码不能在pycharm中运行,需要在jupyter notebook中运行:
#第一部分:导包
import numpy as np
import matplotlib.pyplot as plt
#第二部分:加载数据集
from sklearn.datasets import load_digits
from sklearn.decomposition import PCA
digits = load_digits()
x = digits.data
y = digits.target
x.shape, y.shape
#第三部分:数据集划分
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=233)
#第四部分:PCA降维
'''
from sklearn.decomposition import PCA
#4.1对所有主成分进行数据效果可视化展示
pca = PCA()#默认的是对所有的主成分进行划分
pca.fit(x_train)
#输出每一个特征对应的重要性比例(方差所占的大小权重)
print(pca.explained_variance_ratio_)#1.50332671e-01 代表的是15%左右的意思
#画出这些特征权重从0累加到1的过程中的变化大小
ratio_cum = np.cumsum(pca.explained_variance_ratio_)
plt.plot(ratio_cum)
plt.show()
'''
'''
#4.2直接设置要保留的特征值数目
pca = PCA(20)
pca.fit(x_train)
'''
#4.3直接设置要保留原始数据的百分比
pca = PCA(0.9)
pca.fit(x_train)
print(pca.n_components_)#输出要达到0.9的原始信息需要的特征数
#第五部分:查看降维后的效果(使用逻辑回归)
#第五部分:查看降维后的效果(使用逻辑回归)
from sklearn.linear_model import LogisticRegression
clf = LogisticRegression(solver='saga', tol=0.001, max_iter=500, random_state=233)
%%time
clf.fit(x_train,y_train)
clf.score(x_test,y_test)
%%time
x_train_pca = pca.transform(x_train)
x_test_pca = pca.transform(x_test)
clf.fit(x_train_pca, y_train)
clf.score(x_test_pca, y_test)
第六部分:PAC在数据降噪中的应用
通过PCA在降维过程中所丢失的数据,(大部分都是噪声数据特征),从而实现数据降噪的效果。
下面我们以手写数据集为例,来探究PAC在数据降噪中的应用:
(1)导包
#第一部分:导包
import numpy as np
from matplotlib import pyplot as plt
(2)创建数据集
#第二部分:创建数据集
from sklearn.datasets import load_digits
digits = load_digits()
x = digits.data
y = digits.target
x.shape, y.shape
(3)绘制手写数据集图像(绘制前20条数据)
#第三部分:绘制前20条数据
def plot_top20_digits(x):
for i in range(20):
plt.subplot(4, 5, i + 1)
plt.xticks([])
plt.yticks([])
plt.imshow(x[i].reshape(8, 8), cmap=plt.cm.gray_r, interpolation="nearest")
plt.show()
plot_top20_digits(x)
上面这个就是手写数据集的真实模样(没有加入噪声)
(4)往原始数据(图片)中添加噪声
#第四部分:往原始数据集里添加噪声
np.random.seed(0)
x_noise = x + np.random.randn(x.shape[0], x.shape[1]) * 3
plot_top20_digits(x_noise)
(5)使用PCA对噪声数据进行去噪
#第五部分:使用PCA对噪声数据进行去噪
pca=PCA(0.5)
pca.fit(x_noise)
x_noise_pca = pca.transform(x_noise)#plot_top20_digits(x_noise_pca)
x_noise_inv = pca.inverse_transform(x_noise_pca)#它提供了一个尽可能接近原始数据的重构。该过程利用已存储的主成分和均值来重建数据。
plot_top20_digits(x_noise_inv)#然后再把它输出成原先的形式因为x_noise_pca是低维度的,没有办法输出图片
可以看出,去噪后的图像尽管没有之前那么清晰,但是比直接加入噪音的图像已经好很多了。
(6)上述完整pycharm代码
#第一部分:导包
import numpy as np
from matplotlib import pyplot as plt
#第二部分:创建数据集
from sklearn.datasets import load_digits
from sklearn.decomposition import PCA
digits = load_digits()
x = digits.data
y = digits.target
x.shape, y.shape
#第三部分:绘制前20条数据
def plot_top20_digits(x):
for i in range(20):
plt.subplot(4, 5, i + 1)
plt.xticks([])
plt.yticks([])
plt.imshow(x[i].reshape(8, 8), cmap=plt.cm.gray_r, interpolation="nearest")
plt.show()
plot_top20_digits(x)
#第四部分:往原始数据集里添加噪声
np.random.seed(0)
x_noise = x + np.random.randn(x.shape[0], x.shape[1]) * 3
plot_top20_digits(x_noise)
#第五部分:使用PCA对噪声数据进行去噪
pca=PCA(0.5)
pca.fit(x_noise)
x_noise_pca = pca.transform(x_noise)#plot_top20_digits(x_noise_pca)
x_noise_inv = pca.inverse_transform(x_noise_pca)#它提供了一个尽可能接近原始数据的重构。该过程利用已存储的主成分和均值来重建数据。
plot_top20_digits(x_noise_inv)#然后再把它输出成原先的形式因为x_noise_pca是低维度的,没有办法输出图片
第七部分:PCA的优缺点和适用条件
(1)优点
- 简单容易计算,易于计算机实现
- 可以有效减少特征选择工作量,降低算法计算成本
- 不要求数据正态分布,无参数限制,不受样本标签限制
- 有效去除噪声,使得数据更加容易使用
(2)缺点
- 非高斯分布情况下,PCA得到的主元可能并非最优
- 特征值分解的来源方法是主成分限制(矩阵必须是方阵)
- 降维后存在信息丢失
- 主成分解释较易随机数较困难
(3)适用条件
- 变量间强相关数据
- 数据压缩,预处理
- 数据降维,噪声去除
- 高维数据探索与可视化