机器学习算法系列————降维(四)

1.概述

维度: 对于数组和series,维度就是功能shape返回的结果,shape中返回了几个数字,就是几个维度。降维算法中的”降维“,指的是降低特征矩阵中特征的数量。降维的目的是为了让算法运算更快,效果更好,但其实还有另一种需求:数据可视化。

在降维过程中,我们会减少特征的数量,这意味着删除数据,数据量变少则表示模型可以获取的信息会变少,模型的表现可能会因此受影响。同时,在高维数据中,必然有一些特征是不带有有效的信息的(比如噪音),或者有一些特征带有的信息和其他一些特征是重复的(比如一些特征可能会线性相关)。我们希望能够找出一种办法来帮助我们衡量特征上所带的信息量,让我们在降维的过程中,能够即减少特征的数量,又保留大部分有效信息——将那些带有重复信息的特征合并,并删除那些带无效信息的特征等等——逐渐创造出能够代表原特征矩阵大部分信息的,特征更少的,新特征矩阵。

请添加图片描述

2. PCA与SVD

在降维中,PCA使用的信息量衡量指标,就是样本方差,又称可解释性方差,方差越大,特征所带的信息量越多。通过投影的方式将高维的数据投影到低维上。
PCA可以基于两种思路进行优化。最大可分性,最近重构型。
在这里插入图片描述
参考连接:机器学习,什么是PCA降维?一个动画告诉你答案

请添加图片描述
Var代表一个特征的方差,n代表样本量,xi代表一个特征中的每个样本取值,xhat代表这一列样本的均值。
无偏估计:
1.https://www.bilibili.com/video/BV1pq4y1p7nu/?spm_id_from=333.999.0.0&vd_source=50d7155404373ccb2004b778100660be
2.https://www.bilibili.com/video/BV1CT4y1j71j/?spm_id_from=333.999.0.0&vd_source=50d7155404373ccb2004b778100660be

3.特征工程

特征工程中有三种方式:特征提取,特征创造和特征选择。

特征选择是从已存在的特征中选取携带信息最多的,选完之后的特征依然具有可解释性,我们依然知道这个特征在原数据的哪个位置,代表着原数据上的什么含义。

PCA,是将已存在的特征进行压缩,降维完毕后的特征不是原本的特征矩阵中的任何一个特征,而是通过某些方式组合起来的新特征。通常来说,在新的特征矩阵生成之前,我们无法知晓PCA都建立了怎样的新特征向量,新特征矩阵生成之后也不具有可读性,我们无法判断新特征矩阵的特征是从原数据中的什么特征组合而来,新特征虽然带有原始数据的信息,却已经不是原数据上代表着的含义了。
PCA为代表的降维算法因此是特征创造(feature creation,或feature construction)的一种。
可以想见,PCA一般不适用于探索特征和标签之间的关系的模型(如线性回归),因为无法解释的新特征和标签之间的关系不具有意义。在线性回归模型中,我们使用特征选择。

4.降维是如何实现的

重要的步骤:
找出n个新特征向量,让数据能够被压缩到少数特征上并且总信息量不损失太多的技术就是矩阵分解。
PCA使用方差作为信息量的衡量指标,并且特征值分解来找出空间V。

SVD使用奇异值分解来找出空间V,其中Σ也是一个对角矩阵,不过它对角线上的元素是奇异值,这也是SVD中用来衡量特征上的信息量的指标。

通常来说,在新的特征矩阵生成之前,我们无法知晓PCA都建立了怎样的新特征向量,新特征矩阵生成之后也不具有可读性。以PCA为代表的降维算法因此是特征创造(feature creation,或feature construction)的一种。

4.1 重要参数

(1) n_components

n_components是我们降维后需要的维度,即降维后需要保留的特征数量。

'''
高维数据的可视化
1。调用库和模块
    plt画图模块,鲜花数据集,decomposition中的pca模块
2。提取数据集,也可以查看数据集的样子
    将数据集转换为dataframe格式
3。建模
    调用pca,实例化,拟合模型,获取新矩阵。也可以直接fit_transform一步到位
4。可视化

5。探索降维后的数据
6。选择最好的特征个数:累积可解释方差贡献率曲线
    纵坐标是方差贡献曲线
'''
#1。导入所需的包
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.decomposition import PCA
#2。提取数据集
data = load_iris()
x = data.data
y = data.target
print(x.shape)
import pandas as pd

#3。调用pca,实例化
pca = PCA(n_components=2)
x_dr = pca.fit_transform(x)
print(x_dr.shape)
#4。对其进行可视化
plt.figure()
#x_dr[y == 0,0]相当于是将x_dr里面的第一列数据中y==0的地方给取出来了。
plt.scatter(x_dr[y == 0,0],x_dr[y == 0,1],c="red",label="iris.target_name[1]")
plt.scatter(x_dr[y == 1,0],x_dr[y == 1,1],c="black",label="iris.target_name[2]")
plt.scatter(x_dr[y == 2,0],x_dr[y == 2,1],c="orange",label="iris.target_name[3]")
plt.legend()#这个是将标签显示到,左上角
plt.title('PCA of iris dataset')
#plt.show()

print(pca.explained_variance_)#查看降维后每个新特征向量上所带的信息量的大小
print(pca.explained_variance_ratio_)#查看降维后每个新特征向量所占的信息量占原始数据总信息的百分比
print(pca.explained_variance_ratio_.sum())#总和
#5.选择最好的特征个数
import numpy as np
pca_line = PCA().fit(x)#在这里是没有进行降维的,所以这个数据就是4维的。
print(pca_line.explained_variance_ratio_)
print(np.cumsum(pca_line.explained_variance_ratio_))
plt.plot([1,2,3,4],np.cumsum(pca_line.explained_variance_ratio_))
plt.xlabel('number of components after dimension reduction')
plt.ylabel('cumulative explained variance ratio')
#plt.show()

#最大似然估计自选超参数
pca_mle = PCA(n_components='mle')#PCA用最大似然估计自己选择超参数
x_dr_mle = pca_mle.fit_transform(x)
print(pca_mle.explained_variance_ratio_.shape)#每一个特征所占的比例的维度就是所保留下来的特征个数
print(pca_mle.explained_variance_ratio_.sum())#查看特征所带信息量

#按信息量占比选择超参数
pca_f = PCA(n_components=0.97,svd_solver="full")#svd_solver="full"不能省略
pca_f = pca_f.fit(x)
X_f = pca_f.transform(x)#PCA会自动选出能够让保留的信息量超过97%的特征数量。
X_f
pca_f.explained_variance_ratio_#array([0.92461872, 0.05306648])
(2)svd_solver 与 random_state

参数svd_solver是在降维过程中,用来控制矩阵分解的一些细节的参数。有四种模式可选:“auto”, “full”, “arpack”,“randomized”,默认”auto"。

参数random_state在参数svd_solver的值为"arpack" or "randomized"的时候生效,可以控制这两种SVD模式中的随机模式。

(3) 重要属性components_

特征信息数据,不可以进行可视化。

'''
1。导入所需要的库和模块
    人脸的数据集,pca,plt画图,np
2。实例化数据集,探索数据
    设置每个人的脸有60张以上,每张图片的大小,
3。看看图像的样子,将原始矩阵进行可视化
4。建模降维,提取特征空间矩阵
5。降新的特征空间矩阵进行可视化
'''
#1。导入所需要的库和模块
from sklearn.datasets import fetch_lfw_people
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
import numpy as np

import ssl

ssl._create_default_https_context = ssl._create_unverified_context

#2。实例化数据,探索数据
faces = fetch_lfw_people(min_faces_per_person=60)#实例化   min_faces_per_person=60:每个人取出60张脸图
faces#一个字典形式的数据

faces.images.shape#(1277,62,471277是矩阵中图像的个数,62是每个图像的特征矩阵的行,47是每个图像的特征矩阵的列
#怎样理解这个数据的维度?
faces.data.shape#(1277,2914)   行是样本,列是样本相关的所有特征:2914 = 62 * 47
#换成特征矩阵之后,这个矩阵是什么样?
X = faces.data

print(faces.data.shape)
#数据本身是图像,和数据本身只是数字,使用的可视化方法不同
 
#创建画布和子图对象
fig, axes = plt.subplots(4,5#45列个图
                        ,figsize=(8,4)#figsize指的是图的尺寸
                        ,subplot_kw = {"xticks":[],"yticks":[]} #不要显示坐标轴
                        )
fig#指的是画布
 
axes
#不难发现,axes中的一个对象对应fig中的一个空格
#我们希望,在每一个子图对象中填充图像(共24张图),因此我们需要写一个在子图对象中遍历的循环
axes.shape#(4,5)
 
#二维结构,可以有两种循环方式,一种是使用索引,循环一次同时生成一列上的四个图
#另一种是把数据拉成一维,循环一次只生成一个图
#在这里,究竟使用哪一种循环方式,是要看我们要画的图的信息,储存在一个怎样的结构里
#我们使用 子图对象.imshow 来将图像填充到空白画布上
#而imshow要求的数据格式必须是一个(m,n)格式的矩阵,即每个数据都是一张单独的图
#因此我们需要遍历的是faces.images,其结构是(1277, 62, 47)
#要从一个数据集中取出24个图,明显是一次性的循环切片[i,:,:]来得便利
#因此我们要把axes的结构拉成一维来循环

# [*axes.flat]#2维
axes.flat#降低一个维度
# [*axes.flat] #1enumerate(axes.flat)
 
#填充图像
for i, ax in enumerate(axes.flat):
    ax.imshow(faces.images[i,:,:] 
              ,cmap="gray" #选择色彩的模式
            )
 
# cmap参数取值选择各种颜色:https://matplotlib.org/tutorials/colors/colormaps.html
#原本有2914维,我们现在来降到150print(faces.data.shape)
print(faces.images.shape)
pca = PCA(150).fit(X)#这里X = faces.data,不是faces.images.shape ,因为sklearn只接受2维数组降,不接受高维数组降
x_dr = pca.transform(X)
x_dr.shape#(1277,150)

V = pca.components_#新特征空间
V.shape#V(k,n)   (150, 2914)
#这个是将components进行展示。新特征空间展示。

fig, axes = plt.subplots(3,8,figsize=(8,4),subplot_kw = {"xticks":[],"yticks":[]})
 
for i, ax in enumerate(axes.flat):
    ax.imshow(V[i,:].reshape(62,47),cmap="gray")

4.2 重要接口

(1)inverse_transform

通过让原特征矩阵X右乘新特征空间矩阵V(k,n)来生成新特征矩阵X_dr,那理论上来说,让新特征矩阵X_dr右乘V(k,n)的逆矩阵 ,就可以将新特征矩阵X_dr还原为X。

案例:

from sklearn.datasets import fetch_lfw_people
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
import numpy as np

faces = fetch_lfw_people(min_faces_per_person=60)
faces.images.shape
#怎样理解这个数据的维度?
faces.data.shape
#换成特征矩阵之后,这个矩阵是什么样?
X = faces.data

pca = PCA(150)#实例化
X_dr = pca.fit_transform(X)#拟合+提取结果
X_dr.shape


X_inverse = pca.inverse_transform(X_dr)
 
X_inverse.shape#(1348, 2914)

faces.images.shape#(1348, 62, 47)

faces.images.shape

fig, ax = plt.subplots(2,10,figsize=(10,2.5)
                      ,subplot_kw={"xticks":[],"yticks":[]}
                     )
 
#和2.3.3节中的案例一样,我们需要对子图对象进行遍历的循环,来将图像填入子图中
#那在这里,我们使用怎样的循环?
#现在我们的ax中是210列,第一行是原数据,第二行是inverse_transform后返回的数据
#所以我们需要同时循环两份数据,即一次循环画一列上的两张图,而不是把ax拉平
 
for i in range(10):
    ax[0,i].imshow(faces.images[i,:,:],cmap="binary_r")
    ax[1,i].imshow(X_inverse[i].reshape(62,47),cmap="binary_r")
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值