基于 Python 的降维技术实战


基于 Python 的降维技术实战

我们为什么需要减少维度?

高维数据集是具有大量列(或变量)的数据集。这样的数据集带来了许多数学或计算挑战。好消息是变量(或称为特征)通常是相关的 – 高维数据“表面上”被少数简单变量所控制。我们可以找到变量的子集,以表示数据中的相同级别的信息,或将变量转换为新的一组变量,而不会丢失很多信息。虽然高功率计算可以以某种方式处理高维数据,但在许多应用中,仍然需要降低原始数据的维度。

当我们考虑降维时,主成分分析(PCA)可能是最受欢迎的技术。在本文中,我将从 PCA 开始,然后陆续介绍其他维度减少技术。每个技术都会附上 Python 代码。

减少维度也可以找到异常值

数据科学家可以使用降维技术来识别异常。为什么?难道我们只是想减少维度吗?直觉在于异常值本身。D.M.Hawkins 说:“异常值是指观测结果与其他观测结果相差太大,以引起它被不同机制产生的怀疑。”一旦降维到较少的主维度,模式就被识别出来,然后就会显示出异常值。我们可以说异常值检测是降维副的产品,如文章异常检测到 AutoEncoders 易于易于易于修复[1]

主成分分析(PCA:Principal Component Analysis)

主成分分析(PCA)的概念是减少由大量相关变量组成的数据集的维度,同时保留尽可能多的数据方差。PCA 找到了一组新的变量,即原始变量只是它们的线性组合。新变量称为主成分(PCs)。这些主要成分是正交:在 3-D 情况下,主成分彼此垂直。x 不能由 y 表示,也不能由 z 呈现。

图(a)显示了 PCA 的直觉:它“旋转”轴更好地与您的数据对齐。第一个主成分将捕获数据中的大部分方差,然后后跟第二个,第三等。结果是,新数据将具有更少的维度。

基于 Python 的降维技术实战

图(a):PCA

让我们使用鸢尾花数据集来说明 PCA:

# Use the iris dataset to illustrate PCA:
import pandas as pd
url = “https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data"
# load dataset into Pandas DataFrame
df = pd.read_csv(url, names=['sepal length','sepal width','petal length','petal width','target'])
df.head()
基于 Python 的降维技术实战
鸢尾花数据集

基于 Python 的降维技术实战

请注意,此 Iris 数据集附带目标变量。在 PCA 中,您只能在没有目标 Y 变量的情况下转换 x 变量。

标准化:所有变量应在应用 PCA 之前应在相同的比例上,否则,具有大值的特征将主导结果。这一点进一步解释了我的帖子避免这些致命建模错误,可能会浪费你职业生涯[2]。下面我使用scikit-standardscaler – 学习将数据集的特征标准化到单位刻度上(平均值= 0 和方差= 1)。

from sklearn.preprocessing import StandardScaler
variables = ['sepal length''sepal width''petal length''petal width']
x = df.loc[:, variables].values
y = df.loc[:,['target']].values
x = StandardScaler().fit_transform(x)
x = pd.DataFrame(x)
基于 Python 的降维技术实战
标准化特征

原始数据中有四个特征。所以 PCA 将提供相同数量的主成分。

from sklearn.decomposition import PCA
pca = PCA()
x_pca = pca.fit_transform(x)
x_pca = pd.DataFrame(x_pca)
x_pca.head()
基于 Python 的降维技术实战
鸢尾花数据集的主要组成部分

每个主成分解释的差异是什么?使用pca.explate_variance_ratio_返回方差的向量:

explained_variance = pca.explained_variance_ratio_
explained_variance

它显示了第一个主要成分占 72.22%的差异,第二个,第三和第四个占 23.9%,3.68%和 0.51%的差异。我们可以说 72.22 + 23.9 = 96.21%的信息由第一和第二主成分捕获。我们经常希望只保留重要的特征并放弃微不足道的特征。拇指(经验)规则保持顶部的主成分,捕捉重要的方差和忽视小的。

我们可以使用前两个组件绘制结果。让我们将目标变量 y 附加到新数据 x_pca:

x_pca['target']=y
x_pca.columns = ['PC1','PC2','PC3','PC4','target']
x_pca.head()

基于 Python 的降维技术实战

结果显示数据在新空间中可分离。

import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.set_xlabel('Principal Component 1')
ax.set_ylabel('Principal Component 2')
ax.set_title('2 component PCA')
targets = ['Iris-setosa''Iris-versicolor''Iris-virginica']
colors = ['r''g''b']
for target, color in zip(targets,colors):
    indicesToKeep = x_pca['target'] == target
    ax.scatter(x_pca.loc[indicesToKeep, 'PC1']
 , x_pca.loc[indicesToKeep, 'PC2']
 , c = color
 , s = 50)
ax.legend(targets)
ax.grid()
基于 Python 的降维技术实战

KPCA(Kernel PCA)

PCA 仅适用于线性变换。而KPCA支持非线性变换。首先将原始数据映射到某些非线性特征空间(通常更高的维度),然后应用 PCA 以提取该空间中的主成分。这可以通过图(b)来理解。左侧的图形显示了使用任何线性变换不能分离蓝色和红色点。但是,如果所有点都投射到 3D 空间上,则结果变得线性可分离!然后,我们将 PCA 应用于分离成分。

直觉来自哪里?为什么分离在高维空间中更容易变得更容易?这必须返回 Vapnik-Chervonenkis(VC)理论。它将映射到更高的维度空间通常提供更大的分类效果。

基于 Python 的降维技术实战

图(b):KPCA

以下 Python 代码使由红色和蓝色点组成的圆形曲线。显然,没有办法将红色和蓝色点用一条直线分离(线性分离)。

print(__doc__)
import numpy as np
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA, KernelPCA
from sklearn.datasets import make_circles
np.random.seed(0)
X, y = make_circles(n_samples=400, factor=.3, noise=.05)
plt.figure(figsize=(10,10))
plt.subplot(221, aspect='equal')
plt.title("Original space")
reds = y == 0
blues = y == 1
plt.scatter(X[reds, 0], X[reds, 1], c="red",s=20, edgecolor='k')
plt.scatter(X[blues, 0], X[blues, 1], c="blue",s=20, edgecolor='k')
plt.xlabel("$x_1$")
plt.ylabel("$x_2$")

基于 Python 的降维技术实战

但是,当我们将圆圈投射到更高的维度空间并使用 PCA 分开时,针对第一和第二主成分的数据观察是可分离的!以下结果是针对第一和第二主成分绘制点的结果。我画一条线来分隔红色和蓝色点。在 KernelPCA 中,我们指定内核=’RBF’,即径向基函数[3],或 euclidean 距离。RBFS 通常用作机器学习技术中的内核,例如支持向量机(SVM)[4]

kpca = KernelPCA(kernel="rbf", fit_inverse_transform=True, gamma=10)
X_kpca = kpca.fit_transform(X)
pca = PCA()
X_pca = pca.fit_transform(X)
plt.scatter(X_kpca[reds, 0], X_kpca[reds, 1], c="red",s=20, edgecolor='k')
plt.scatter(X_kpca[blues, 0], X_kpca[blues, 1], c="blue",s=20, edgecolor='k')
x = np.linspace(-111000)
plt.plot(x, -0.1*x, linestyle='solid')
plt.title("Projection by KPCA")
plt.xlabel(r"1st principal component in space induced by $phi$")
plt.ylabel("2nd component")

基于 Python 的降维技术实战

如果我们将内核指定为“线性”, 如下面的代码(KernelPCA(kernel="linear")),则成为只有线性变换的标准 PCA,红色和蓝色点不可分离。

kpca = KernelPCA(kernel="linear", fit_inverse_transform=True, gamma=10)
X_kpca = kpca.fit_transform(X)
pca = PCA()
X_pca = pca.fit_transform(X)
plt.scatter(X_kpca[reds, 0], X_kpca[reds, 1], c="red",s=20, edgecolor='k')
plt.scatter(X_kpca[blues, 0], X_kpca[blues, 1], c="blue",s=20, edgecolor='k')
x = np.linspace(-111000)
plt.plot(x, -0.1*x, linestyle='solid')
plt.title("Projection by KPCA")
plt.xlabel(r"1st principal component in space induced by $phi$")
plt.ylabel("2nd component")

基于 Python 的降维技术实战

线性判别分析(LDA:Linear Discriminant Analysis)

LDA 的起源与 PCA 不同。PCA 是一种无监督的学习方法,将原始特征转换为一组新特征。我们不关心新的一组特征是否可以为目标变量提供最佳的区分能力。相比之下,线性判别分析(LDA)寻求保持与所属变量尽可能多的辨别力,同时将原始数据矩阵突出到较低维空间上。LDA 是一种有监督学习技术的类型。它利用从属变量中的类将预测器的空间划分为区域。所有区域应该有线性边界。这就是名称中线性由来。该模型预测,区域内的所有观察属于来自相关变量的相同类别。

LDA 通过三个主要步骤中实现了上述目标。

  • 首先,它计算从属变量的不同类别之间的可分离性,称为级别方差,如(1)所示。
  • 其次,它计算每个类的平均值和样本之间的距离,该距离被称为级别方差,如(2)所示。
  • 最后,它通过此标准构造了较低维度的空间:最大化类别之间的方差并最小化类别内方差。该标准的解决方案是计算特征值和特征向量。得到的特征向量代表了新空间的方向,相应的特征值代表了特征向量的长度。因此,每个特征向量代表 LDA 空间的一个轴,并且特征值代表该特征向量的长度。

基于 Python 的降维技术实战

图:LDA.

我将使用在 Kaggle 中的数据集红葡萄酒质量[5],此数据集具有 11 个输入变量和一个输出变量quality

import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
wine = pd.read_csv('winequality-red.csv')
wine.head()

基于 Python 的降维技术实战

为了简单起见,我将输出变量重新组建为三个值,

wine['quality2'] = np.where(wine['quality']<=4,1, np.where(wine['quality']<=6,2,3))

基于 Python 的降维技术实战

以下代码执行 PCA 和 LDA。

X = wine.drop(columns=['quality','quality2'])
y = wine['quality2']
target_names = np.unique(y)
target_names
pca = PCA(n_components=2)
X_r = pca.fit(X).transform(X)
lda = LinearDiscriminantAnalysis(n_components=2)
X_r2 = lda.fit(X, y).transform(X)

然后绘制 PCA 和 LDA 的结果:

# Percentage of variance explained for each components
print('explained variance ratio (first two components): %s'
 % str(pca.explained_variance_ratio_))
plt.figure()
colors = ['navy''turquoise''darkorange']
lw = 2
for color, i, target_name in zip(colors, target_names, target_names):
 plt.scatter(X_r[y == i, 0], X_r[y == i, 1], color=color, alpha=.8, lw=lw,
 label=target_name)
plt.legend(loc='best', shadow=False, scatterpoints=1)
plt.title('PCA of WINE dataset')
plt.figure()
for color, i, target_name in zip(colors, target_names, target_names):
 plt.scatter(X_r2[y == i, 0], X_r2[y == i, 1], alpha=.8, color=color,
 label=target_name)
plt.legend(loc='best', shadow=False, scatterpoints=1)
plt.title('LDA of WINE dataset')
plt.show()

基于 Python 的降维技术实战

奇异值分解(SVD:Singular Value Decomposition)

SVD 是类似于 PCA 的数据摘要方法。它从数据中提取重要特征。但 SVD 还有一个优势:将原始数据集重建为小型数据集。所以它具有广泛的应用,如图像压缩等。例如,如果您有32*32=1024像素图像,则 SVD 可以将其概括为 66 像素。66 像素可以检索32*32像素图像而不会错过任何重要信息。

SVD 在线性代数中发挥了重要作用,但在吉尔伯特·斯特朗(Gilbert Strang)的经典教科书《线性代数及其应用》(linear algebra and Its Applications)中,它似乎“不像它应该的那样出名”。为了正确地引入奇异值分解,必须从矩阵运算开始。如果 A 是对称实n*n矩阵,则存在一个正交矩阵V和一个对角矩阵D

基于 Python 的降维技术实战

V是 A 的特征向量,D的对角线条目是 A 的特征值。该过程称为矩阵a特征值分解,或EVD。它告诉我们如何选择 Orthonormal 基础,以便转换由具有最简单形式的矩阵表示,即对角线。(对于想要越过步骤的读者来对角度化矩阵,这里[6]是一个很好的示例。)术语正式意味着两个载体是正交或垂直的。

V是 A 的特征向量,D的对角项是 A 的特征值。这个过程称为矩阵A的特征值分解,或EVD。它告诉我们如何选择标准正交基底,这样变换就可以用一个矩阵来表示它的最简单形式,也就是对角线形式。(对于想要了解矩阵对角化步骤的读者,可以参考这里[7]

扩展对称矩阵,SVD 适用于任意实数mxn矩阵A*。给定一个实数m×n矩阵a,存在一个正交的m×m矩阵 U,一个正交m×m矩阵 V,一个对角的m×n矩阵 Σ,

基于 Python 的降维技术实战

注意,一个正交矩阵是一个方阵,其自身及其逆矩阵的乘积是单位矩阵。对角线矩阵是指除对角线以外的所有元素都为零的矩阵。

下面我将再次使用鸢尾花数据集向您展示如何应用 SVD。

from numpy import *
import operator
import matplotlib.pyplot as plt
import pandas as pd
from numpy.linalg import *
url = "https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data"
# load dataset into Pandas DataFrame
df = pd.read_csv(url, names=['sepal length','sepal width','petal length','petal width','target'])
# Only the X variables
data = df[['sepal length','sepal width','petal length','petal width']]
#calculate SVD
n = 2 # We will take two Singular Values
U, s, V = linalg.svd( data )
# eye() creates a matrix with ones on the diagonal and zeros elsewhere
Sig = mat(eye(n)*s[:n])
newdata = U[:,:n]
newdata = pd.DataFrame(newdata)
newdata.columns=['SVD1','SVD2']
newdata.head()
基于 Python 的降维技术实战

您可以将 SVD 的结果与 PCA 的结果进行比较。两者都达到了类似的结果。

# Add the actual target to the data in order to plot it
newdata['target']=df['target']
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.set_xlabel('SVD 1')
ax.set_ylabel('SVD 2')
ax.set_title('SVD')
targets = ['Iris-setosa''Iris-versicolor''Iris-virginica']
colors = ['r''g''b']
for target, color in zip(targets,colors):
    indicesToKeep = newdata['target'] == target
    ax.scatter(newdata.loc[indicesToKeep, 'SVD1']
 , newdata.loc[indicesToKeep, 'SVD2']
 , c = color
 , s = 50)
ax.legend(targets)
ax.grid()
基于 Python 的降维技术实战
图:SVD.

t 分布-随机邻近嵌入(t-SNE:t-distributed Stochastic Neighbor Embedding)

t-SNE 由Laurens Van der Maaten 和 Geoggrey Hinton[8]开发的。它是一种用于可视化的机器学习算法,其呈现在两或三维的低维空间中嵌入高维数据。

基于 Python 的降维技术实战

将上述三维瑞士卷呈现为二维的最佳方式是什么?直观地我们希望“展开”瑞士卷到一个平坦的蛋糕。在数学中,它意味着类似的观点将成为附近的点,异常点将成为距离点。

图(C)显示了另一个例子。它是一个三维四面体,数据点聚类在顶点。如果我们只是像 Panel (a)那样将三维图折叠成二维图,它就不能很好地工作,因为组(a)变成了中心集群。相比之下,Panel (B)可能是一个更好的 2d 展示,它保留了 Cluster (a)-(E)之间的距离,同时保留了每个 Cluster 中点的局部距离。t-SNE 是一种非线性降维技术,用于保持局部邻域。如果一组点在 t-SNE 图上聚在一起,我们可以相当肯定这些点彼此很接近。

基于 Python 的降维技术实战

图(c):t-SNE

t-SNE 对点之间的相似性进行建模。它是如何定义相似性的?首先,它是由点XiXj之间的欧氏距离定义的。其次,定义为“数据点i与点j的相似度是点i根据高斯分布下的概率选择其他邻居时,将数据点j作为其邻居的条件概率p”的条件概率。在下面的条件表达式中,如果点j比其他点更接近点i,那么它被选中的概率就更高(注意负号)。

基于 Python 的降维技术实战

t-SNE 的目标是通过点YiYj之间的低维空间q来匹配上述ji的条件概率p,如下图所示。概率q遵循长尾 Student-t 分布,这就是 t-SNE 中的T的由来。

基于 Python 的降维技术实战

下一步是找到Yi,使得分布q尽可能接近分配p。t-SNE 使用梯度下降技术,一种寻找值的优化技术。

下面我展示了如何与鸢尾花数据集一起使用 t-SNE 技术。

from sklearn.manifold import TSNE
from sklearn.datasets import load_iris
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
iris = load_iris()
X_tsne = TSNE(learning_rate=100).fit_transform(iris.data)
X_pca = PCA().fit_transform(iris.data)
plt.figure(figsize=(105))
plt.subplot(121)
plt.scatter(X_tsne[:, 0], X_tsne[:, 1], c=iris.target)
plt.subplot(122)
plt.scatter(X_pca[:, 0], X_pca[:, 1], c=iris.target)

基于 Python 的降维技术实战

有关 t-SNE 更多信息,这篇文章“如何更有效地使用 t-SNE[9]”提供了更多的讨论。

参考资料

[1]

异常检测到 AutoEncoders 易于易于易于修复: https://towardsdatascience.com/anomaly-detection-with-autoencoder-b4cdce4866a6

[2]

避免这些致命建模错误,可能会浪费你职业生涯: https://towardsdatascience.com/avoid-these-deadly-modeling-mistakes-that-may-cost-you-a-career-b9b686d89f2c

[3]

径向基函数: https://en.wikipedia.org/wiki/radial_basis_function

[4]

支持向量机(SVM): https://en.wikipedia.org/wiki/support-vector_machine

[5]

红葡萄酒质量: https://www.kaggle.com/piyushgeyal443/red-wine-dataset#winequalityInfo.txt

[6]

这里: https://yutsumura.com/how-to-diagonalize-a-matrix-step-by-step-explanonation/

[7]

这里: https://yutsumura.com/how-to-diagonalize-a-matrix-step-by-step-explanation/

[8]

Laurens Van der Maaten 和 Geoggrey Hinton: http://www.cs.toronto.edu/~hinton/absps/tsne.pdf

[9]

如何更有效地使用 t-SNE: https://distill.pub/2016/misread-tsne/



原文:Dimension Reduction Techniques with Python

链接:https://towardsdatascience.com/dimension-reduction-techniques-with-python-f36ca7009e5c?gi=836dd28c32df

作者:Dr. Dataman

原文始发于微信公众号(alitrack):基于 Python 的降维技术实战

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/62877.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!