from sklearn.decomposition import PCA
简介:
主成分分析(Principal Components Analysis),简称PCA,是一种数据降维技术,用于数据预处理。
PCA的一般步骤是:先对原始数据均值化,然后求协方差矩阵,接着对协方差矩阵求特征向量和特征值,这些特征向量组成了新的特征空间。
参数说明:
sklearn.decomposition.PCA(n_components=None, copy=True, whiten=False)
参数:
n_components: 这个参数可以帮我们指定希望PCA降维后的特征维度数目。最常用的做法是直接指定降维到的维度数目,此时n_components是一个大于等于1的整数。当然,我们也可以指定主成分的方差和所占的最小比例阈值,让PCA类自己去根据样本特征方差来决定降维到的维度数,此时n_components是一个(0,1]之间的数。当然,我们还可以将参数设置为"mle", 此时PCA类会用MLE算法根据特征的方差分布情况自己去选择一定数量的主成分特征来降维。我们也可以用默认值,即不输入n_components,此时n_components=min(样本数,特征数)。
copy:
类型:bool,True或者False,缺省时默认为True。
意义:表示是否在运行算法时,将原始训练数据复制一份。若为True,则运行PCA算法后,原始训练数据的值不会有任何改变,因为是在原始数据的副本上进行运算;若为False,则运行PCA算法后,原始训练数据的值会改,因为是在原始数据上进行降维计算。
whiten:
类型:bool,缺省时默认为False
意义:白化,使得每个特征具有相同的方差。所谓白化,就是对降维后的数据的每个特征进行归一化,让方差都为1.对于PCA降维本身来说,一般不需要白化。如果你PCA降维后有后续的数据处理动作,可以考虑白化。默认值是False,即不进行白化。
svd_solver:即指定奇异值分解SVD的方法,由于特征分解是奇异值分解SVD的一个特例,一般的PCA库都是基于SVD实现的。有4个可以选择的值:{‘auto’, ‘full’, ‘arpack’, ‘randomized’}。randomized一般适用于数据量大,数据维度多同时主成分数目比例又较低的PCA降维,它使用了一些加快SVD的随机算法。 full则是传统意义上的SVD,使用了scipy库对应的实现。arpack和randomized的适用场景类似,区别是randomized使用的是scikit-learn自己的SVD实现,而arpack直接使用了scipy库的sparse SVD实现。默认是auto,即PCA类会自己去在前面讲到的三种算法里面去权衡,选择一个合适的SVD算法来降维。一般来说,使用默认值就够了。
PCA属性:
- components_ :返回具有最大方差的成分。
- n_components_:返回所保留的成分个数n。
- mean_:
- noise_variance_:
- explained_variance_,它代表降维后的各主成分的方差值。方差值越大,则说明越是重要的主成分。
- explained_variance_ratio_:返回所保留的n个成分各自的方差百分比。比例越大,则越是重要的主成分。
PCA方法:
- fit(X,y=None)
fit(X),表示用数据X来训练PCA模型。
函数返回值:调用fit方法的对象本身。比如pca.fit(X),表示用X对pca这个对象进行训练。
拓展:fit()可以说是scikit-learn中通用的方法,每个需要训练的算法都会有fit()方法,它其实就是算法中的“训练”这一步骤。因为PCA是无监督学习算法,此处y自然等于None. - 2.fit_transform(X)
用X来训练PCA模型,同时返回降维后的数据。
newX=pca.fit_transform(X),newX就是降维后的数据。 - 3.inverse_transform()
将降维后的数据转换成原始数据,X=pca.inverse_transform(newX) - 4.transform(X)
将数据X转换成降维后的数据。当模型训练好后,对于新输入的数据,都可以用transform方法来降维。
此外,还有get_covariance()、get_precision()、get_params(deep=True)、score(X, y=None)等方法。
案例分析
- 首先生成随机数据并可视化
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# make_nlobs 方法常被用来生成聚类算法的测试数据
# make_blobs 会根据用户指定的特征数量,中心点数量,范围等来生成几类数据
from sklearn.datasets.samples_generator import make_blobs
# X 为样本特征,Y 为样本簇类型 共10000个样本,每个样本3个特征,共4个簇
# n_samples 表示产生多少个数据 n_features 表示数据是几维,
# centers 表示中心点 cluster_std 表示分布的标准差
X, y = make_blobs(n_samples=10000, n_features=3, centers=[[3, 3, 3], [0, 0, 0], [1, 1, 1], [2, 2, 2]], cluster_std=[0.2, 0.1, 0.2, 0.2], random_state=9)
fig = plt.figure()
ax = Axes3D(fig, rect=[0, 0, 1, 1], elev=30, azim=20)
plt.scatter(X[:, 0], X[:, 1], X[:, 2], marker='o')
plt.show()
三维数据的分布图如下:
- 我们先只对数据进行投影,看看投影后的三个维度的方差分布,代码如下:
from sklearn.decomposition import PCA
pca = PCA(n_components=3) # 要与原特征数量一致
pca.fit(X)
print(pca.explained_variance_ratio_) # 主要的查看指标
print(pca.explained_variance_)
输出结果如下:
[0.98318212 0.00850037 0.00831751]
[3.78521638 0.03272613 0.03202212]
可以看出投影后三个特征维度的方差比例大约为98.3% 0.8% 0.8% 。投影后第一个特征占了绝大多数的主成分比例。
现在我们来进行降维,从三维降到二维,代码如下:
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
pca.fit(X)
print(pca.explained_variance_ratio_)
print(pca.explained_variance_)
输出结果如下:
[0.98318212 0.00850037]
[3.78521638 0.03272613]
这个结果其实可以预料,因为上面三个投影后的特征维度的方差分别为:[3.78521638 0.03272613 0.03202212] ,投影到二维后选择的肯定是钱两个特征,而抛弃第三个特征。
为了有直观的认识,我们看看此时转化后的数据分布,代码如下:
X_new = pca.transform(X)
- 指定降维后的主成分方差和比例。
pca = PCA(n_components=0.95) # 小于 1 即表明所占比例
pca.fit(X)
print(pca.explained_variance_ratio_)
print(pca.explained_variance_)
print(pca.n_components_)
上面我们指定了主成分至少占95% ,输出如下:
[0.98318212]
[3.78521638]
1
可见只有第一个投影特征被保留,这也很好理解,我们的第一个主成分占投影特征的方差比例高达98%。只选择这一个特征维度便可以满足95%的阈值。我们现在选择阈值99%看看,代码如下:
pca = PCA(n_components = 0.99)
pca.fit(X)
print(pca.explained_variance_ratio_)
print(pca.explained_variance_)
print(pca.n_components_)
此时输出的结果:
[0.98318212 0.00850037]
[3.78521638 0.03272613]
2
这个结果也很好理解,因为我们第一个主成分占了98.3%的方差比例,第二个主成分占了0.8%的方差比例,两者一起可以满足我们的阈值。
最后我们看看让MLE算法自己选择降维维度的效果,代码如下:
pca = PCA(n_components = 'mle')
pca.fit(X)
print(pca.explained_variance_ratio_)
print(pca.explained_variance_)
print(pca.n_components_)
输出结果如下:
[0.98318212]
[3.78521638]
1
可见由于我们的数据的第一个投影特征的方差占比高达98.3%,MLE算法只保留了我们的第一个特征。
补充
- Incremental PCA
当要分解的数据集太大而无法放入内存时,增量主成分分析(IPCA)通常用作主成分分析(PCA)的替代。IPCA主要是为了解决单机内存限制的,有时候我们的样本量可能是上百万+,维度可能也是上千,直接去拟合数据可能会让内存爆掉,此时我们可以使用Incremental PCA类来解决这个问题。
IPCA 是将数据分成多个batch,然后对每个batch依次递增调用partial_fit函数,这样一步步的得到最终的样本最优降维。
from sklearn.datasets import load_iris
from sklearn.decomposition import PCA , IncrementalPCA
iris = load_iris()
X = iris.data
y = iris.target
n_components = 2
ipca = IncrementalPCA(n_components=n_components, batch_size=10)
X_ipca = ipca.fit_transform(X)
pca = PCA(n_components=n_components)
X_pca = pca.fit_transform(X)
参考博客
线性判别分析(带有分类数据的降维)
sklearn.discriminant_analysis.LinearDiscriminantAnalysis
1.1)参数说明
LinearDiscriminantAnalysis(solver=‘svd’, shrinkage=None, priors=None, n_components=None, store_covariance=False, tol=0.0001, covariance_estimator=None)
主要参数说明 :
solver {‘svd’, ‘lsqr’, ‘eigen’}, default=’svd’
“svd”:奇异值分解(默认值)。不计算协方差矩阵,因此建议对具有大量特征的数据使用此解算器。
“lsqr”:最小二乘解。可以与收缩或自定义协方差估计器相结合。
“eigen”:特征值分解。可以与收缩或自定义协方差估计器相结合。
priors : 类的先验概率。默认情况下,将从训练数据推断类比例。降维时一般不需要关注这个参数。
n_components : 用于降维的组件数量(<= min(n_classes - 1, n_features))。如果我们不是用于降维,则这个值可以用默认的None。
store_covariance : 如果为True,则当解算器为“svd”时,明确计算加权类内协方差矩阵。始终为其他解算器计算和存储矩阵。
shrinkage:正则化参数,可以增强LDA分类的泛化能力。如果仅仅只是为了降维,则一般可以忽略这个参数。默认是None,即不进行正则化。可以选择"auto",让算法自己决定是否正则化。当然我们也可以选择不同的[0,1]之间的值进行交叉验证调参。注意shrinkage只在solver为最小二乘"lsqr"和特征分解"eigen"时有效。
covariance_estimator : 协方差估计量
属性 :
coef_ : 权重向量。 intercept_ : 截取项。 covariance_ : 加权类内协方差矩阵。
means_ : Class-wise means. priors_ : 类别优先级(总和为1)
scalings_ : 在类质心跨越的空间中缩放特征。仅适用于“奇异值分解”和“特征值”解算器。
xbar_ : 总平均数。仅当解算器为“svd”时出现。 classes_ : 唯一的类标签。
方法 :
fit(X, y) : 根据给定的参数拟合线性微分分析模型
transform(X) : 项目数据以最大化类分离。
fit_transform(X, y=None, ** fit_params) : 适应数据,然后对其进行转换。
decision_function(X) : 将决策函数应用于样本数组。
predict(X) : 预测X中样本的类标签。
predict_proba(X) : 估计概率。
score(X, y, sample_weight=None) : 返回给定测试数据和标签的平均精度。
1.2)代码示例
1.2.1)使用线性判别分析来降维
from sklearn import datasets
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
# 加载数据集
iris = datasets.load_iris()
X = iris.data
y = iris.target
columns = iris.target_names
pca = PCA(n_components=2)
x1 = pca.fit_transform(X) # 返回降维后的数据
lda = LinearDiscriminantAnalysis(n_components=2) # 降维
x2 = lda.fit(X,y).transform(X) # 返回降维后的数据
# 画图
plt.figure()
colors = ['navy', 'turquoise', 'darkorange']
lw = 2
for color, i, target_name in zip(colors, [0,1,2],columns):
plt.scatter(x1[y == i, 0], x1[y == i, 1], color=color, alpha=.8, lw=lw,
label=target_name)
plt.legend(loc='best', shadow=False, scatterpoints=1)
plt.title('PCA of IRIS dataset')
plt.figure()
for color, i, target_name in zip(colors, [0, 1, 2], columns):
plt.scatter(x2[y == i, 0], x2[y == i, 1], alpha=.8, color=color,
label=target_name)
plt.legend(loc='best', shadow=False, scatterpoints=1)
plt.title('LDA of IRIS dataset')
plt.show()
1.3)方法讲解
LDA通过把输入的数据投影到由最大化类之间分离的方向所组成的线性子空间,可以执行有监督降维。输出的维度必然会比原来的类别数量更少的。因此它总体而言是十分强大的降维方式,同样也仅仅在多分类环境下才能感觉到。实现方式在 discriminant_analysis.LinearDiscriminantAnalysis.transform 中。关于维度的数量可以通过 n_components 参数来调节。 值得注意的是,这个参数不会对 discriminant_analysis.LinearDiscriminantAnalysis.fit 或者 discriminant_analysis.LinearDiscriminantAnalysis.predict 产生影响。
同时两种方法天生具有多分类的特性,在实践中已经被证明很有效,并且无需调参。
LDA既可以用于分类又可以用于降维。当然,应用场景最多的还是降维。和PCA类似,LDA降维基本也不用调参,只需要指定降维到的维数即可.