机器学习之PCA主成分分析,看这一篇就够了!

第一部分:基本含义

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)适用条件

  • 变量间强相关数据
  • 数据压缩,预处理
  • 数据降维,噪声去除
  • 高维数据探索与可视化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

还不秃顶的计科生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值