降维的主要方法
投影
将高维空间的点投影到低维子空间上
流形学习
d维流形是n维空间(且d<n)的一部分, 局部类似于d维超平面。
许多降维算法通过训练实例所在的流形进行建模工作, 称为流行学习。
它依赖于流形假说:大多数现实世界的高维数据集都接近于低维流形。
隐式假设:如果用流形的低维空间表示,任务(例如分类或回归)将更加简单。
PCA
主成分分析(PCA):识别最靠近数据的超平面, 然后将数据投影到其上
保留差异性
保留差异性大的轴更为合理, 相对其他的情况丢失的信息更少。
方法:比较原始数据集与其轴上的投影间的均方距离, 选取其最小的轴
主要成分
主成分分析可以在训练数据集中识别哪条轴对差异性的贡献度最高。
第i个轴称为数据的第i个主要成分(PC),PC两两正交
奇异值分解(SVD)找到训练集的主成分:
# 利用NumPy的svd()获取所有主要成分, 然后提取定义前两个PC的单位向量 import numpy as np X_centered = X - X.mean(axis=0) U, s, Vt = np.linalg.svd(X_centered) c1 = Vt.T[:, 0] c2 = Vt.T[:, 1]
PCA假定数据集以原点为中心。 Scikit-Learn负责居中数据,但如果自己实现PCA(如上例)或使用其他库, 首先需要将数据居中。
向下投影到d维度
Xd-proj = X Wd Wd定义为包含V的前d列矩阵
# 投影到前两个主要成分定义的平面上 W2 = Vt.T[:, :2] X2D = X_centered.dot(W2)
使用Scikit-Learn
from sklearn.decomposition import PCA pca = PCA(n_components=2) X2D = pca.fit_transform(X)
其components_的属性是Wd的转置
可解释方差比
explained_variance_ratio_可解释方差比:沿每个成分数据集方差的比率
选择正确的维度
选择相加足够大的方差部分(如95%)的维度
如果是为了数据可视化, 需要将维度降低到2或3
# 不降维的情况下执行PCA, 计算保留95%训练集方差所需的最小维度 pca = PCA() pca.fit(X_train) cumsum = np.cumsum(pca.explained_variance_ratio_) d = np.argmax(cumsum >= 0.95) + 1 # 或者: pca = PCA(n_components=0.95) X_reduced = pca.fit_transform(X_train)
PCA压缩
通过应用PCA投影的逆变换, 可以解压。 投影会丢失一部分数据, 解压不会给原始数据, 但可能会接近原始数据。原始数据和重构数据(压缩后再解压缩)之间的均方距离称为重构误差。
# 将MNIST数据集压缩为154个维度, 再用inverse_transform()方法解压缩回784个维度 pca = PCA(n_components=154) X_reduced = pca.fit_transform(X_train) X_recovered = pca.inverse_transform(X_reduced)
默认solver=“atuo”,当m或n > 500 && d < 80%(m or n)时, Scikit-Learn自动使用随机PCA, 如果强制使用完全PCA, 可以 svd_solver=“full”。
增量PCA
from sklearn.decomposition import IncrementalPCA n_batches = 100 inc_pca = IncrementalPCA(n_components=154) for X_batch in np.array_split(X_train, n_batches): inc_pca.partial_fit(X_batch) X_reduced = inc_pca.transform(X_train)
内核PCA
核技巧应用于PCA, 从而可以执行复杂的非线性投影来降低维度, 这叫做内核PCA(kPCA)
from sklearn.decomposition import KernelPCA rbf_pca = KernelPCA(n_components=2, kernel="rbf", gamma=0.04) X_reduced = rbf_pca.fit_transform(X)
选择内核并调整超参数
网格搜索kPCA的最佳内核和gamma值
from sklearn.model_selection import GridSearchCV from sklearn.linear_model import LogisticRegression from sklearn.pipeline import Pipeline clf = Pipeline([ ("kpca", KernelPCA(n_components=2)), ("log_reg", LogisticRegression()) ]) param_grid = [{ "kpca__gamma": np.linspace(0.03, 0.05, 10), "kpca__kernel": ["rbf", "sigmond"] }] grid_search = GridSearch(clf, para_grid, cv=3) grid_search.fit(X, y) >>> print(grid_search.best_params_)
另一种完全无监督方法是选择产生最低重构误差的内核和超参数
rbf_pca = KernelPCA(n_components = 2, kernel="rbf", gamma=0.0433, fit_inverse_transform=True) X_reduced = rbf_pca.fit_transform(X) X_preimage = rbf_pca.inverse_transform(X_reduced) # 计算重构误差 >>> from sklearn.metrics import mean_squared_error >>> mean_squared_error(X, X_preimage)
利用网格搜索和交叉验证找到最大限度减少此错误的内核和超参数
LLE
局部线性嵌入(LLE), 非线性降维(NLDR), 流形学习技术
工作原理:首先测量每个训练实例如何与最近的邻居(c.n.)线性相关,然后寻找可以最好保留这些局部关系的低维表示形式。
from sklearn.manifold import LocallyLinearEmbedding lle = LocallyLinearEmbedding(n_components=2, n_neighbors=10) X_reduced = lle.fit_transform(X)