一、降维算法概述

1.降维算法概述
  降维就是一种针对高维度特征进行的数据预处理方法,是应用非常广泛的数据预处理方法。
  降维算法指对高维度的数据保留下最重要的一些特征,去除噪声和不重要的特征,从而实现提升数据处理速度的目的。在实际的生产和应用中,在一定的信息损失范围内,降维可以节省大量的时间和成本。
  机器学习领域中所谓的降维就是指采用某种映射方法,将原高维空间中的数据点映射到低维度的空间中。
2.降维算法的分类
主成分分析(Principal Component Analysis,PCA)法
  试图在保证数据信息丢失最少的原则下,对多个变量进行最佳综合简化,即对高维变量空间进行降维处理。
因子分析(Factor Analysis,FA)法
  因子分析法是从假设出发。
因子分析法有几个主要目的:一是进行结构的探索,在变量之间存在高度相关性的时候希望用较少的因子来概括其信息;二是把原始变量转换为因子得分后,使用因子得分进行其他分析,从而简化数据,如聚类分析、回归分析等;三是通过每个因子得分计算出综合得分,对分析对象进行综合评价。
3.降维算法的应用场景
  降维算法通常应用于数据压缩与数据可视化中。

二、数据降维

数据降维(Dimensionality Reduction):

数据降维案例(经济分析):

任务(真实事件):通过美国1929-1938年各年经济数据,预测国民收入与支出

数据包括:雇主补贴、消费资料和生产资料、纯公共支出、净增库存、股息、利息、外贸平衡等十七个指标

数据降维,是指在某些限定条件下,降低随机变量个数,得到一组“不相关”主变量的过程

作用:减少模型分析数据量,提升处理效率,降低计算难度,实现数据可视化

数据量下降举例:2D数据降维到1D数据

将二维数据投影到一条直线上面

数据量下降举例:3D数据降维到2D数据

投影之后变成二维数据

数据可视化举例:国家分布可视化(基于50项经济指标)

缩减为两项指标:复合指标F1和复合指标F2

这样就可以进行可视化展示:

三、主成分分析(PCA)

数据降维的实现:主成分分析(PCA)

PCA(principal components analysis):数据降维技术中,应用最最多的方法

目标:寻找k(k<n)维新数据,使它们反映事物的主要特征

核心:在信息损失尽可能少的情况下,降低数据维度

二维数据PCA

三维数据PCA

 

3D到2D:投影到u1、u2形成的平面

n维到k维:投影到u1、u2...uk形成的空间

如何保留主要信息:

投影后的不同特征数据尽可能分得开(即不相关)

如何实现?

使投影后数据的方差最大,因为方差越大数据也越分散

计算过程

(1)、原始数据预处理(标准化:μ=0,σ=1),即将N维数据实现标准正态分布,即处理后均值为0,方差为1。

(2)、计算协方差矩阵特征向量、及数据在各特征向量投影后的方差,方差越大,相关性越小,将方差小的舍弃掉。

(3)、根据需求(任务指定或方差比例)确定降维维度k

(4)、选取k维特征向量,计算数据在其形成空间的投影

三、实战-PCA(iris数据降维后分类)

数据集

1、基于iris_data.csv数据,建立KNN模型实现数据分类(n_neighbors=3)

2、对数据进行标准化处理,选取一个维度可视化处理后的效果

3、进行与原数据等维度PCA,查看各主成分的方差比例

4、保留合适的主成分,可视化降维后的数据

5、基于降维后数据建立KNN模型,与原数据表现进行对比

1、加载数据

#加载数据
import torch
import pandas as pd
import numpy as np
from sklearn.metrics import accuracy_score
# from matplotlib import pyplot as plt
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt

data = pd.read_csv('./data/iris_data.csv')
print(data)

结果:

     sepal length  sepal width  ...          target  label
0             5.1          3.5  ...     Iris-setosa      0
1             4.9          3.0  ...     Iris-setosa      0
2             4.7          3.2  ...     Iris-setosa      0
3             4.6          3.1  ...     Iris-setosa      0
4             5.0          3.6  ...     Iris-setosa      0
..            ...          ...  ...             ...    ...
145           6.7          3.0  ...  Iris-virginica      2
146           6.3          2.5  ...  Iris-virginica      2
147           6.5          3.0  ...  Iris-virginica      2
148           6.2          3.4  ...  Iris-virginica      2
149           5.9          3.0  ...  Iris-virginica      2

2、定义X和y

#定义X,y
X = data.drop(['target','label'],axis=1) # 去掉最后两列
y = data.loc[:,'label']
print(X.shape,y.shape)#打印X,y的维度

结果:(150, 4) (150,)

3、建立KNN模型实现数据分类(n_neighbors=3)

选用最近的3个点来预测新的点属于哪一类

#建立KNN模型
from sklearn.neighbors import KNeighborsClassifier
KNN = KNeighborsClassifier(n_neighbors=3)
KNN.fit(X,y) # 训练
# 预测
y_predict = KNN.predict(X)
# 计算准确率
accuracy = accuracy_score(y,y_predict)
print(accuracy)

结果:0.96

第一步已经完成,接下来进入第二步:对数据进行标准化处理,选取一个维度可视化处理后的效果

4、对数据进行标准化处理

# 对数据进行标准化处理
from sklearn.preprocessing import StandardScaler
X_norm = StandardScaler().fit_transform(X)
print(X_norm)

结果:

[[-9.00681170e-01  1.03205722e+00 -1.34127240e+00 -1.31297673e+00]
 [-1.14301691e+00 -1.24957601e-01 -1.34127240e+00 -1.31297673e+00]
 [-1.38535265e+00  3.37848329e-01 -1.39813811e+00 -1.31297673e+00]
 ......
 [ 1.03800476e+00 -1.24957601e-01  8.19624347e-01  1.44795564e+00]
 [ 5.53333275e-01 -1.28197243e+00  7.05892939e-01  9.22063763e-01]
 [ 7.95669016e-01 -1.24957601e-01  8.19624347e-01  1.05353673e+00]
 [ 4.32165405e-01  8.00654259e-01  9.33355755e-01  1.44795564e+00]
 [ 6.86617933e-02 -1.24957601e-01  7.62758643e-01  7.90590793e-01]]

5、选取一个维度(sepal length)计算均值和方差

# 计算均值和方差
x1_mean = X.loc[:,"sepal length"].mean()
x1_sigma = X.loc[:,"sepal length"].std()
x1_norm_mean = X_norm[:,0].mean()
x1_norm_sigma = X_norm[:,0].std()
print(x1_mean,x1_sigma,x1_norm_mean,x1_norm_sigma)

结果:

5.843333333333334 0.8280661279778629 -4.736951571734001e-16 1.0

x1_norm_mean的值为-4.736951571734001e-16,相当于0了。

6、选取一个维度,可视化处理后的效果

# 选取一个维度,可视化处理后的效果
fig1 = plt.figure(figsize=(20, 5))
# 原来的数据分布
plt.subplot(121)
plt.hist(X.loc[:,"sepal length"],bins=100)
# 标准化处理之后的数据
plt.subplot(122)
plt.hist(X_norm[:,0],bins=100)
plt.show()

结果:

发现原来的sepal length这个维度的均值在6左右,标准化处理之后变为了0左右。

到这里第二步已经完成,现在来看第三步:进行与原数据等维度PCA,查看各主成分的方差比例

7、进行与原数据等维度PCA

# 进行与原数据等维度PCA,查看各主成分的方差比例
print(X.shape) # (150,4) 即原数据的维度为4
from sklearn.decomposition import PCA
pca = PCA(n_components=4) # 同等维度处理
# 等维度PCA后的数据x_pca
x_pca = pca.fit_transform(X_norm) # 参数为标准化处理之后的数据X_norm
print(x_pca)

结果:

[[-2.26454173e+00  5.05703903e-01  1.21943348e-01 -2.30733235e-02]
 [-2.08642550e+00 -6.55404729e-01  2.27250832e-01 -1.03208244e-01]
 [-2.36795045e+00 -3.18477311e-01 -5.14796236e-02 -2.78252250e-02]
 [-2.30419716e+00 -5.75367713e-01 -9.88604444e-02  6.63114622e-02]
  ......
 [ 1.55849189e+00 -9.05313601e-01  2.53819099e-02 -2.21322184e-01]
 [ 1.52084506e+00  2.66794575e-01 -1.79277203e-01 -1.18903043e-01]
 [ 1.37639119e+00  1.01636193e+00 -9.31405052e-01 -2.41461953e-02]
 [ 9.59298576e-01 -2.22839447e-02 -5.28794187e-01  1.63675806e-01]]

8、查看各主成分的方差比例

# 计算每个主成分的方差比例
var_ratio = pca.explained_variance_ratio_
print(var_ratio) # [0.72770452 0.23030523 0.03683832 0.00515193]

9、可视化各主成分的方差比例

# 可视化方差比例
fig2 = plt.figure(figsize=(20,5))
plt.bar([1, 2, 3, 4],var_ratio)
plt.xticks([1, 2, 3, 4],['PC1', 'PC2', 'PC3', 'PC4'])
plt.ylabel("variance ratio of each principle components")
plt.show()

结果:

发现前面两个主成分的方差比例比较大, 后面两个比较小。

至此,第三步已经完成,现在来看第四步:保留合适的主成分,可视化降维后的数据

10、保留合适的主成分,只需要保留前面两个成分

pca = PCA(n_components=2) # 只需要保留前面两个成分 即开始降维
X_pca = pca.fit_transform(X_norm) # 降维后的数据
print(X_pca) # 4维数据变为2维数据
print(X_pca.shape) # (150,2)

结果:

[[-2.26454173e+00  5.05703903e-01]
 [-2.08642550e+00 -6.55404729e-01]
 [-2.36795045e+00 -3.18477311e-01]
 [-2.30419716e+00 -5.75367713e-01]
 [-2.38877749e+00  6.74767397e-01]
  .....
 [ 2.04330844e+00  8.64684880e-01]
 [ 2.00169097e+00  1.04855005e+00]
 [ 1.87052207e+00  3.82821838e-01]
 [ 1.55849189e+00 -9.05313601e-01]
 [ 1.52084506e+00  2.66794575e-01]
 [ 1.37639119e+00  1.01636193e+00]
 [ 9.59298576e-01 -2.22839447e-02]]
(1502

11、可视化降维后的数据

# 可视化展示pca结果
fig3 = plt.figure(figsize=(20, 10))
setosa = plt.scatter(X_pca[:, 0][y == 0], X_pca[:,1][y == 0])
versicolour = plt.scatter(X_pca[:, 0][y == 1], X_pca[:,1][y == 1])
virginica = plt.scatter(X_pca[:, 0][y == 2], X_pca[:,1][y == 2])
plt.legend((setosa, versicolour, virginica), ('setosa', 'versicolour', 'virginica'))
plt.show()

结果:

原来4维的话是无法可视化的,现在降为2维,从图中可以看到,蓝色是一种花,黄色是一种花,绿色是一种花,虽然黄色和绿色夹杂在一起,但是肉眼还是可以区分得开的。即通过PCA降维之后,这三种花实现了相关性最小。

至此第四步已经完成,现在来看第5步:基于降维后数据建立KNN模型,与原数据的表现(准确率)进行对比

12、基于降维后数据建立KNN模型

#建立KNN模型
from sklearn.neighbors import KNeighborsClassifier
KNN = KNeighborsClassifier(n_neighbors=3)
KNN.fit(X_pca,y)
# 预测
y_predict = KNN.predict(X_pca)
# 计算准确率
accuracy = accuracy_score(y,y_predict)
print(accuracy)

结果:0.9466666666666667

原来是0.96,下降了一点,说明效果其实还挺不错的。

完整代码:

#加载数据
import torch
import pandas as pd
import numpy as np
from sklearn.metrics import accuracy_score
# from matplotlib import pyplot as plt
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt

data = pd.read_csv('./data/iris_data.csv')
print(data)
#定义X,y
X = data.drop(['target','label'],axis=1) # 去掉最后两列
y = data.loc[:,'label']
print(X.shape,y.shape)#打印X,y的维度

#建立KNN模型
from sklearn.neighbors import KNeighborsClassifier
KNN = KNeighborsClassifier(n_neighbors=3)
KNN.fit(X,y) # 训练
y_predict = KNN.predict(X)# 预测
accuracy = accuracy_score(y,y_predict)# 计算准确率
print(accuracy)
# 对数据进行标准化处理(均值为0,方差为1)
from sklearn.preprocessing import StandardScaler
X_norm = StandardScaler().fit_transform(X)
print(X_norm)
# 计算均值和方差
x1_mean = X.loc[:,"sepal length"].mean()
x1_sigma = X.loc[:,"sepal length"].std()
x1_norm_mean = X_norm[:,0].mean()
x1_norm_sigma = X_norm[:,0].std()
print(x1_mean,x1_sigma,x1_norm_mean,x1_norm_sigma)

# 选取一个维度,可视化处理后的效果
fig1 = plt.figure(figsize=(20, 5))
# 原来的数据分布
plt.subplot(121)
plt.hist(X.loc[:,"sepal length"],bins=100)
# 标准化处理之后的数据
plt.subplot(122)
plt.hist(X_norm[:,0],bins=100)
plt.show()

# 进行与原数据等维度PCA,查看各主成分的方差比例
print(X.shape) # (150,4) 即元数据的维度为4
from sklearn.decomposition import PCA
pca = PCA(n_components=4) # 同等维度处理
# 等维度PCA后的数据x_pca
x_pca = pca.fit_transform(X_norm) # 参数为标准化处理之后的数据X_norm
print(x_pca)

# 计算每个主成分的方差比例
var_ratio = pca.explained_variance_ratio_
print(var_ratio) # [0.72770452 0.23030523 0.03683832 0.00515193]
# 可视化方差比例
fig2 = plt.figure(figsize=(20,5))
plt.bar([1, 2, 3, 4],var_ratio)
plt.xticks([1, 2, 3, 4],['PC1', 'PC2', 'PC3', 'PC4'])
plt.ylabel("variance ratio of each principle components")
plt.show()

pca = PCA(n_components=2) # 只需要保留前面两个成分 即开始降维
X_pca = pca.fit_transform(X_norm) # 降维后的数据
print(X_pca)
print(X_pca.shape)
# 可视化展示pca结果
fig3 = plt.figure(figsize=(20, 10))
setosa = plt.scatter(X_pca[:, 0][y == 0], X_pca[:,1][y == 0])
versicolour = plt.scatter(X_pca[:, 0][y == 1], X_pca[:,1][y == 1])
virginica = plt.scatter(X_pca[:, 0][y == 2], X_pca[:,1][y == 2])
plt.legend((setosa, versicolour, virginica), ('setosa', 'versicolour', 'virginica'))
plt.show()

# 基于降维后数据建立KNN模型,与原数据表现进行对比
#建立KNN模型
from sklearn.neighbors import KNeighborsClassifier
KNN = KNeighborsClassifier(n_neighbors=3)
KNN.fit(X_pca,y)
# 预测
y_predict = KNN.predict(X_pca)
# 计算准确率
accuracy = accuracy_score(y,y_predict)
print(accuracy)

总结:

1、通过计算数据对应的主成分(principle components),可在减少数据维度同时尽可能保留主要信息;

2、为确定合适的主成分维度,可先对数据进行与原数据相同维度的PCA处理,再根据根据各个成分的数据方差确认主成分维度,即比例大的保留下来;

 

posted on 2025-02-12 16:02  周文豪  阅读(208)  评论(0)    收藏  举报