12种降维技术的全面指南(附Python代码)

徐大白
2个月前 阅读 229 点赞 2

介绍

你曾经做过超过一千个特性的数据集吗?那超过50000个特征的呢?我有,让我告诉你,这是一项非常具有挑战性的任务,特别是如果你不知道从哪里开始!拥有大量的变量既是一种恩惠又是一种诅咒。我们有大量的数据用于分析,但由于大小而具有挑战性。

在微观层面上分析每一个变量是不可行的。我们可能需要花上几天或几个月的时间来进行任何有意义的分析,我们将损失大量的时间和金钱来做生意。更不用说这将需要多少计算能力。我们需要一种更好的方法来处理高维数据,以便我们能够快速地从中提取模式和洞察力。那么我们如何接近这样的数据集呢?

当然,使用降维技术。您可以使用此概念来减少数据集中的特征数量,而不必丢失大量信息并保持(或改进)模型的性能。这是一个处理大量数据集的非常强大的方法,正如你在本文中所看到的。

这是可用于实际场景的各种降维技术的综合指南。我们将首先了解这个概念是什么,为什么我们应该使用它,在跳入12个不同的技术,我已经涵盖。每种技术都有自己在Python中的实现,以使您对它有很好的了解。


目录表

1.什么是降维?

2.为什么需要降维?

3.通用降维技术

  • 3.1遗漏价值比率
  • 3.2低方差滤波器
  • 3.3高相关滤波器
  • 3.4随机森林
  • 3.5后向特征消除
  • 3.6前向特征选择
  • 3.7因素分析
  • 3.8主成分分析
  • 3.9独立分量分析
  • 3.10基于投影的几种方法
  • 3.11 T分布随机邻居嵌入(T-SNE)
  • 3.12 UMAP

4.各种降维技术的应用

 

1.什么是降维?

我们每天都在产生大量的数据。事实上,世界上90%的数据是在过去3-4年中产生的!这些数字确实令人难以置信。下面只是一些数据收集的例子:

  • 脸谱网收集你喜欢的数据,分享,邮寄,参观的地方,你喜欢的餐馆等等。
  • 你的智能手机应用程序收集了很多关于你的个人信息。
  • Amazon在网站上收集你购买、查看、点击等的数据。
  • 赌场跟踪每个顾客的每一个动作

随着数据的生成和收集的不断增加,可视化和绘制推理变得越来越具有挑战性。最常用的可视化方法之一是图表。假设我们有2个变量,年龄和身高。我们可以在年龄和身高之间使用一个散点图或线图,并很容易地看清它们之间的关系:


现在考虑一个例子,我们有100个变量(p=100)。在这种情况下,我们可以有100(100-1)/ 2=5000个不同的情节。把它们分开想象是没有多大意义的,对吧?在我们有大量变量的情况下,最好选择这些变量的子集(p<100),它捕获了与原始变量集一样多的信息。

让我们用一个简单的例子来理解这一点。考虑下面的图像:

比如,我们有类似的物体的重量公斤(X1)和磅(X2)。如果我们使用这两个变量,它们将传达相似的信息。所以,只使用一个变量是有意义的。我们可以将数据从2D(X1和X2)转换为1D(Y1)

同样,我们可以将数据的P维数降为k维的子集(k<n),这被称为降维。

 

2 为什么需要降维?

以下是将维度缩减应用到数据集的一些好处:

  • 数据存储所需的空间随着维数的下降而减少。
  • 较小的维数导致较少的计算/训练时间
  • 当我们有大的维数时,一些算法不能很好地执行。因此,减少这些维数需要发生的算法是有用的。
  • 它通过消除冗余特征来处理多重共线性。例如,你有两个变量——“在跑步机上花费的时间在几分钟内”和“卡路里燃烧”。这些变量是高度相关的,因为你在跑步机上跑步的时间越多,你燃烧的卡路里就越多。因此,存储两者都没有意义,因为它们中只有一个符合你的要求。
  • 它有助于可视化数据。如前所述,很难以更高的维度可视化数据,因此将空间缩小到2D或3D可以让我们更清楚地绘制和观察模式。

是时候深入研究这篇文章的关键——各种降维技术!我们将使用AV的实践问题:Big Mart Sales III中的数据集(在这个链接上注册,并从数据部分下载数据集)。


3.通用降维技术

降维可以用两种不同的方式来完成:

  • 只保留最相关的变量从原始数据集(这种技术被称为特征选择)
  • 通过找到一组较小的新变量,每个变量都是输入变量的组合,包含与输入变量基本相同的信息(这种技术称为降维)

现在我们将研究各种降维技术,以及如何在Python中实现它们。


3.1遗漏价值比率

假设你得到了一个数据集。你的第一步是什么?在构建模型之前,自然要先探索数据。在探索数据时,您会发现数据集有一些缺失值。现在怎么办?您将试图找出这些缺失值的原因,然后对它们进行归类,或者完全删除具有缺失值的变量(使用适当的方法)。

如果我们有太多缺失值(比如说超过50%)怎么办?我们应该填充缺失值还是放弃变量?我宁愿放弃变量,因为它将没有太多的信息。然而,这并不是一成不变的。我们可以设置一个阈值,如果任何变量中缺失值的百分比大于该阈值,我们将删除该变量。

让我们在Python中实现这个方法

# import required libraries
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

首先,让我们加载数据:

# read the data
train=pd.read_csv("Train_UWu5bXk.csv")
注意:文件的路径应该在读取数据时添加。

现在,我们将检查每个变量中缺失值的百分比。我们可以使用.nulule().SUM()来计算这一点。

# checking the percentage of missing values in each variable
train.isnull().sum()/len(train)*100

正如你在上面表中看到的,缺失值不太多(实际上只有2个变量)。我们可以使用适当的方法计算值,或者我们可以设置阈值,比如20%,并删除缺失值超过20%的变量。让我们来看看如何在Python中做到这一点:

# saving missing values in a variable
a = train.isnull().sum()/len(train)*100
# saving column names in a variable
variables = train.columns
variable = [ ]
for i in range(0,12):
    if a[i]<=20:   #setting the threshold as 20%
        variable.append(variables[i])

因此,要使用的变量存储在“变量”中,其中只包含缺失值小于20%的那些特征。


3.2低方差滤波器

考虑我们数据集中的一个变量,其中所有的观测值都是相同的值,比如1。如果我们使用这个变量,你认为它能改进我们将建立的模型吗?答案是否定的,因为这个变量将具有零方差。

因此,我们需要计算每个变量的方差。然后删除与我们的数据集中的其他变量相比具有低方差的变量。正如上面提到的,这样做的原因是,低方差的变量不会影响目标变量。

让我们首先使用已知的 Item_Weight观测值的中值来填充 Item_Weight 列中的缺失值。对于Outlet_Size 列,我们将使用已知的Outlet_Size 值的模式来填充缺失值:

train['Item_Weight'].fillna(train['Item_Weight'].median, inplace=True)
train['Outlet_Size'].fillna(train['Outlet_Size'].mode()[0], inplace=True)

让我们检查所有缺失的值是否已经被填充:

train.isnull().sum()/len(train)*100

哇!我们都准备好了。现在让我们计算所有数值变量的方差。

train.var()

正如上面的输出所示,与其他变量相比,iTeMe可见度的方差非常小。我们可以安全地放弃这一专栏。这就是我们如何应用低方差滤波器。让我们在Python中实现这一点:

numeric = train[['Item_Weight', 'Item_Visibility', 'Item_MRP', 'Outlet_Establishment_Year']]
var = numeric.var()
numeric = numeric.columns
variable = [ ]
for i in range(0,len(var)):
    if var[i]>=10:   #setting the threshold as 10%
       variable.append(numeric[i+1])


3.3高相关滤波器

两个变量之间的高度相关性意味着它们具有相似的趋势,并且可能携带相似的信息。这可以极大地降低一些模型的性能(例如,线性回归模型和Logistic回归模型)。我们可以计算本质上是数值的独立数值变量之间的相关性。如果相关系数超过某个阈值,我们可以删除其中一个变量(删除一个变量是非常主观的,并且应该始终在记住域的情况下进行)。

作为一般准则,我们应该保持那些与目标变量表现出良好或高相关性的变量。

让我们在Python中执行相关计算。我们将首先删除依赖变量(ItmithOutLoTySuffice),并将其余变量保存在一个新的数据文件(DF)中。

df=train.drop('Item_Outlet_Sales', 1)
df.corr()

很好,我们没有任何变量,在我们的数据集有很高的相关性。通常,如果一对变量之间的相关性大于0.5-0.6,我们应该认真考虑删除这些变量之一。

 

3.4随机森林

随机森林是最常用的特征选择算法之一。它封装了内置的特征重要性,因此不需要单独编程。这有助于我们选择更小的特征子集。

我们需要通过应用一种热编码将数据转换为数字形式,因为随机森林(Scikit-Learn实现)只接受数字输入。我们还要删除ID变量(Item_Identifier 以及 Outlet_Identifier),因为它们只是唯一的数字,目前对我们来说并不重要。

from sklearn.ensemble import RandomForestRegressor
df=df.drop(['Item_Identifier', 'Outlet_Identifier'], axis=1)
model = RandomForestRegressor(random_state=1, max_depth=10)
df=pd.get_dummies(df)
model.fit(df,train.Item_Outlet_Sales)

拟合模型后,绘制特征重要性图:

features = df.columns
importances = model.feature_importances_
indices = np.argsort(importances)[-9:]  # top 10 features
plt.title('Feature Importances')
plt.barh(range(len(indices)), importances[indices], color='b', align='center')
plt.yticks(range(len(indices)), [features[i] for i in indices])
plt.xlabel('Relative Importance')
plt.show()

基于上面的图表,我们可以选择顶部特征来减少数据集的维数。警告,我们可以使用Skpice的StasgFutlook来做到这一点。它根据权重的重要性来选择特征。

 from sklearn.feature_selection import SelectFromModel
feature = SelectFromModel(model)
Fit = feature.fit_transform(df, train.Item_Outlet_Sales)


3.5后向特征消除

遵循下面的步骤来理解和使用“反向特征消除”技术:

  • 我们首先采取所有的n变量存在于我们的数据集,并使用它们训练模型。
  • 然后我们计算模型的性能。
  • 现在,我们在消除每个变量(n次)之后计算模型的性能,即,我们每次丢弃一个变量,并将模型训练在剩余的n-1变量上。
  • 我们识别变量的移除对模型的性能产生了最小(或没有)变化,然后删除该变量
  • 重复这个过程直到没有变量可以被删除

该方法可用于建立线性回归或Logistic回归模型。让我们来看看它的Python实现:

 from sklearn.linear_model import LinearRegression
from sklearn.feature_selection import RFE
from sklearn import datasets
lreg = LinearRegression()
rfe = RFE(lreg, 10)
rfe = rfe.fit_transform(df, train.Item_Outlet_Sales)

我们需要指定要选择的算法和特征的数量,并且我们返回从反向特征消除中获得的变量列表。我们还可以使用“RFE.RANKIGIN”命令检查变量的排名。

 

3.6前向特征选择

我们上面看到的是反向特征消除的相反过程,而不是消除特征。我们试图找到最佳的特征,以提高性能的模型。该技术的工作原理如下:

  • 我们从一个特性开始。本质上,我们使用每个特征分别训练N次模型。
  • 选择最佳性能的变量作为起始变量。
  • 然后我们重复这个过程并一次添加一个变量。产生最高性能增加的变量被保留。
  • 我们重复这个过程直到模型的性能没有明显的改善。

让我们在Python中实现它:

from sklearn.feature_selection import f_regression
ffs = f_regression(df,train.Item_Outlet_Sales )

这返回一个包含变量F值和对应于每个F值的P值的数组。参考这个链接,了解F值的更多信息。为了我们的目的,我们将选择F值大于10的变量:

variable = [ ]
for i in range(0,len(df.columns)-1):
    if ffs[0][i] >=10:
       variable.append(df.columns[i])

这给了我们基于前向特征选择算法的最大变量。

注意:后向特征消除和前向特征选择都耗时且计算昂贵。它们实际上仅用于具有少量输入变量的数据集。

当我们在数据集中没有非常大的变量时,我们迄今所看到的技术通常被使用。这些是或多或少的特征选择技术。在接下来的部分中,我们将使用时尚MNIST数据集,该数据集由属于不同类型服装的图像组成,例如T恤、裤子、袋子等。数据集可以从“识别附件”实践问题下载。

数据集总共有70000个图像,其中60000个在训练集中,剩下的10000个是测试图像。对于本文的范围,我们将只在训练图像上工作。训练文件是一个zip格式。一旦你提取了zip文件,你将得到一个.csv文件和一个包含这60000个图像的训练文件夹。每个图像的相应标签可以在'train.csv’文件中找到。

 

3.7因素分析

假设我们有两个变量:收入和教育。这些变量将潜在地具有高相关性,因为具有高等教育水平的人倾向于拥有显著更高的收入,反之亦然。

在因子分析技术中,变量按其相关性分组,即特定组中的所有变量之间将具有高相关性,但与其他组的变量相关性较低。在这里,每个组被称为一个因素。与原始数据相比,这些因素在数量上是小的。然而,这些因素是很难观察到的。

让我们先阅读包含在训练文件夹中的所有图像:

import pandas as pd
import numpy as np
from glob import glob
import cv2
images = [cv2.imread(file) for file in glob('train/*.png')]
注意:您必须用列车文件夹的路径替换GOLB函数内的路径。

现在我们将把这些图像转换为Numpy数组格式,以便我们能够执行数学操作并绘制图像:

images = np.array(images)
images.shape

(60000, 28, 28,3)

正如上面所看到的,它是一个三维数组。我们必须把它转换成一维,因为所有即将到来的技术只需要一维输入。要做到这一点,我们需要使图像变平:

image = []
for i in range(0,60000):
    img = images[i].flatten()
    image.append(img)
image = np.array(image)

现在,让我们创建一个包含每个图像中存在的每个单独像素的像素值以及它们相应的标签的数据框架(对于标签,我们将使用train.csv文件):

train = pd.read_csv("train.csv")     # Give the complete path of your train.csv file
feat_cols = [ 'pixel'+str(i) for i in range(image.shape[1]) ]
df = pd.DataFrame(image,columns=feat_cols)
df['label'] = train['label']

现在我们将利用因子分析分解数据集:

from sklearn.decomposition import FactorAnalysis
FA = FactorAnalysis(n_components = 3).fit_transform(df[feat_cols].values)

这里,n-分量将决定变换数据中的因子个数。在转换数据之后,现在是可视化结果的时候了:

 %matplotlib inline
import matplotlib.pyplot as plt
plt.figure(figsize=(12,8))
plt.title('Factor Analysis Components')
plt.scatter(FA[:,0], FA[:,1])
plt.scatter(FA[:,1], FA[:,2])
plt.scatter(FA[:,2],FA[:,0])

看起来很神奇,不是吗?我们可以看到上面图表中所有不同的因素。这里,X轴和Y轴代表分解因子的值。正如我前面提到的,很难单独观察这些因素,但是我们已经成功地减少了数据的维度。

 

3.8主成分分析(PCA)

PCA是一种技术,它帮助我们从现有的大变量集合中提取一组新的变量。这些新提取的变量称为主成分。你可以参考这篇文章来了解更多关于PCA的知识。为了快速参考,下面是一些关于PCA的关键点,然后再继续:

  • 主成分是原始变量的线性组合。
  • 主成分以这样的方式提取,即第一主成分解释数据集中的最大方差。
  • 第二主成分试图解释数据集中的剩余方差,并且与第一主成分不相关
  • 第三主成分试图解释由前两个主成分无法解释的方差等。

在进一步移动之前,我们将随机地从我们的数据集中绘制一些图像:

 rndperm = np.random.permutation(df.shape[0])
plt.gray()
fig = plt.figure(figsize=(20,10))
for i in range(0,15):
    ax = fig.add_subplot(3,5,i+1)
    ax.matshow(df.loc[rndperm[i],feat_cols].values.reshape((28,28*3)).astype(float))

让我们使用Python实现PCA并转换数据集:

from sklearn.decomposition import PCA
pca = PCA(n_components=4)
pca_result = pca.fit_transform(df[feat_cols].values)

在这种情况下,NHL组件将决定变换后的数据中的主成分的数量。让我们想象一下用这4个分量解释了多少方差。我们将使用解释的变量变量来计算同样的结果:

plt.plot(range(4), pca.explained_variance_ratio_)
plt.plot(range(4), np.cumsum(pca.explained_variance_ratio_))
plt.title("Component-wise and Cumulative Explained Variance")

在上面的图中,蓝色线表示按分量解释的方差,而橙色线表示累积解释的方差。我们能够解释大约60%的方差在数据集仅使用四个组件。现在让我们想象一下这些分解的组件:

 import seaborn as sns
plt.style.use('fivethirtyeight')
fig, axarr = plt.subplots(2, 2, figsize=(12, 8))
sns.heatmap(pca.components_[0, :].reshape(28, 84), ax=axarr[0][0], cmap='gray_r')
sns.heatmap(pca.components_[1, :].reshape(28, 84), ax=axarr[0][1], cmap='gray_r')
sns.heatmap(pca.components_[2, :].reshape(28, 84), ax=axarr[1][0], cmap='gray_r')
sns.heatmap(pca.components_[3, :].reshape(28, 84), ax=axarr[1][1], cmap='gray_r')
axarr[0][0].set_title(
"{0:.2f}% Explained Variance".format(pca.explained_variance_ratio_[0]*100),
fontsize=12
)
axarr[0][1].set_title(
"{0:.2f}% Explained Variance".format(pca.explained_variance_ratio_[1]*100),
fontsize=12
)
axarr[1][0].set_title(
"{0:.2f}% Explained Variance".format(pca.explained_variance_ratio_[2]*100),
fontsize=12
)
axarr[1][1].set_title(
"{0:.2f}% Explained Variance".format(pca.explained_variance_ratio_[3]*100),
fontsize=12
)
axarr[0][0].set_aspect('equal')
axarr[0][1].set_aspect('equal')
axarr[1][0].set_aspect('equal')
axarr[1][1].set_aspect('equal')

plt.suptitle('4-Component PCA')

每个额外的维度,我们添加到PCA技术捕获越来越少的方差在模型中。第一个组成部分是最重要的一个,其次是第二个,然后是第三个,等等。

我们还可以使用奇异值分解(SingularValueDecom,SVD)将原始数据集分解为它的组成部分,从而减少维度。要学习SVD背后的数学,请参考这篇文章

奇异值分解将原始变量分解为三个组成矩阵。它本质上用于从数据集中删除冗余特征。它使用特征值和特征向量的概念来确定这三个矩阵。由于本文的范围,我们不会深入讨论它的数学,但是让我们坚持我们的计划,即减少数据集中的维度。

让我们实现SVD并分解我们的原始变量:

from sklearn.decomposition import TruncatedSVD 
svd = TruncatedSVD(n_components=3, random_state=42).fit_transform(df[feat_cols].values)

让我们通过绘制前两个主要成分来可视化变换后的变量:

plt.figure(figsize=(12,8))
plt.title('SVD Components')
plt.scatter(svd[:,0], svd[:,1])
plt.scatter(svd[:,1], svd[:,2])
plt.scatter(svd[:,2],svd[:,0])

上面的散点图非常清楚地显示了分解的成分。如前所述,这些组件之间没有太多的相关性。


3.9独立分量分析

独立分量分析(ICA)是基于信息论的,也是应用最广泛的降维技术之一。PCA和ICA之间的主要区别是PCA寻找不相关的因素,而ICA寻找独立的因素。

如果两个变量是不相关的,这意味着它们之间没有线性关系。如果它们是独立的,就意味着它们不依赖于其他变量。例如,一个人的年龄与他吃的东西无关,或者他/她看了多少电视。

该算法假定给定的变量是一些未知的潜在变量的线性混合。它还假定这些潜在变量是相互独立的,即它们不依赖于其他变量,因此它们被称为观测数据的独立分量。

让我们比较PCA和ICA视觉上,以便更好地了解它们是如何不同的:

这里,图像(a)表示PCA结果,而图像(b)表示同一数据集上的ICA结果。

PCA方程为x = Wχ.

其中,X是观测值,W是混合矩阵,χ是源还是独立成分


现在,我们必须找到一个非混合矩阵,使得组件变得尽可能独立。测量组件独立性最常用的方法是非高斯性:

  • 根据中心极限定理,独立分量之和的分布趋于正态分布(高斯)。
  • 因此,我们可以寻找最大化每个独立分量的峰度的变换。峰度是分布的第三阶矩。想了解更多关于kurtosis的事情,就在这里。
  • 最大化峰度将使分布非高斯,因此我们将得到独立的分量。

上述分布是非高斯,这又使组件独立。让我们尝试在Python中实现ICA:

from sklearn.decomposition import FastICA 
ICA = FastICA(n_components=3, random_state=12) 
X=ICA.fit_transform(df[feat_cols].values)

这里,n-组件将决定转换数据中的组件数量。我们已经使用ICA将数据转换成3个组件。让我们想象一下它如何改变数据:

plt.figure(figsize=(12,8))
plt.title('ICA Components')
plt.scatter(X[:,0], X[:,1])
plt.scatter(X[:,1], X[:,2])
plt.scatter(X[:,2], X[:,0])

数据已被分离成不同的独立成分,在上面的图像中可以清楚地看到。X轴和Y轴表示分解的独立分量的值。

现在我们将研究一些使用投影技术来减小数据维数的方法。


3.10 基于投影的几种方法

首先,我们需要了解投影是什么。假设我们有两个向量,向量a和向量b,如下所示:

我们想找到a上的投影b,让a和b之间的角度为∅。投影(a1)将看起来像:

a1与b平行的向量,因此,我们可以用下面的公式得到矢量a在向量b上的投影:

其中,a1= a到b的投影,b̂ =b方向上的单位矢量

通过将一个向量投影到另一个向量上,可以减少维数。


在投影技术中,多维数据通过投影其点到低维空间来表示。现在我们将讨论不同的投影方法:

  • 投影到有趣的方向

有趣的方向取决于特定的问题,但一般来说,投影值是非高斯的方向被认为是有趣的。

与独立分量分析(ICA)类似,投影寻找使投影值的峰度最大化的方向作为非高斯性的度量。

  • 流形上的投影

从前,人们认为地球是平的。无论你走到哪里,地球都会保持平坦(让我们暂时忽略山脉)。但是如果你一直朝着一个方向走,你就会到达你开始的地方。如果地球是平的,这种情况不会发生。地球看起来只是平的,因为我们比地球的面积小。

地球看起来平坦的这些小部分是流形,如果我们组合所有这些流形,我们就能得到地球的大尺度视图,即原始数据。类似地,对于n维曲线,小平面片是流形,这些流形的组合将给出原始的n维曲线。让我们来看看在流形上投影的步骤:

  • 我们首先寻找一个接近数据的流形。
  • 然后将数据投影到该歧管上。
  • 最后,为了表示,我们展开歧管。
  • 有各种各样的技术来获得歧管,所有这些技术包括三个步骤的方法:

从每个数据点收集信息,构造具有顶点的数据点的图

将上述生成的图形转换成适合嵌入步骤的输入

(nXn)本征方程的计算

让我们用一个例子来理解多种投影技术。

如果流形是连续可微的,则称为光滑或可微流形。ISOMAP是一种旨在恢复非线性流形的全低维表示的算法。它假定流形是光滑的。

还假设对于流形上的任意一对点,两点之间的测地距离(曲面上两点之间的最短距离)等于欧几里德距离(直线上两点之间的最短距离)。让我们首先想象一对点之间的测地线和欧几里得距离:

其中 Dn1n2= X1和X2之间的测地线距离,dN1N2= X1和X2之间的欧几里得距离

ISOMAP假定这两个距离相等。现在让我们来看看这个技术的更详细的解释。如前所述,所有这些技术都采用三步走法。我们将详细研究每一个步骤:

  • 邻域图:

第一步是计算所有数据点对之间的距离:dij = dχ(xi,xj) = || xi-xj || χ,其中dχ(xi,xj) = xi 与 xj之间的测地线距离,|| xi-xj || = xi 与xj之间的欧几里得距离

在计算距离之后,我们确定哪些数据点是流形的邻域。

最后生成邻域图:G=G(V,ℰ),其中顶点集V={x1,x2,...,xn}是输入数据点,ℰ = {eij}表示点之间的邻域关系。

  • 计算图形距离:

现在我们通过图的距离计算流形中对点之间的测地线距离。

图距离是图G中所有点对之间的最短路径距离。

  • 嵌入:

一旦我们有了距离,我们就形成了平方图距离的对称(NXN)矩阵。

现在我们选择嵌入向量来最小化测地线距离与图距离之间的差异。

最后,通过(t Xn)矩阵将图G嵌入到y中。

让我们在Python实现它,并清楚地了解我所说的内容。我们将通过等距映射进行非线性降维。为了可视化,我们只需要将数据集的子集作为运行在整个数据集上的一个子集就需要大量的时间。

from sklearn import manifold 
trans_data = manifold.Isomap(n_neighbors=5, n_components=3, n_jobs=-1).fit_transform(df[feat_cols][:6000].values)

使用参数:

  • n_neighbors决定每个点的邻居数
  • n_components决定流形坐标的个数
  • n_jobs = -1 将使用所有可用的CPU内核


可视化转换数据:

plt.figure(figsize=(12,8))
plt.title('Decomposition using ISOMAP')
plt.scatter(trans_data[:,0], trans_data[:,1])
plt.scatter(trans_data[:,1], trans_data[:,2])
plt.scatter(trans_data[:,2], trans_data[:,0])

上面可以看到,这些组件之间的相关性很低。事实上,它们与我们使用SVD较早获得的组件相比甚至更少相关。


3.11 t分布随机邻居嵌入(t-SNE)

到目前为止,我们已经了解到,PCA是针对具有大量变量的数据集进行降维和可视化的良好选择。但是如果我们可以使用更先进的东西呢?如果我们能很容易地以非线性的方式搜索模式呢?t-SNE是一种这样的技术。主要有两种方法可以用来映射数据点:

  • 局部方法:他们将歧管附近的点映射到低维表示中的附近点。
  • 全局方法:他们试图在所有尺度上保持几何,即将流形上的邻近点映射到低维表示的邻近点,以及将远点映射到远点。

——t-SNE是能够同时保留局部和全局结构的几种算法之一。

——它计算了高维空间和低维空间中的点的概率相似度。

——数据点之间的高维欧几里得距离被转换成表示相似性的条件概率:

xi 和 xj 是数据点,||xi-xj|| 代表了这些数据点之间的欧几里得距离,而𝛔i 是高维空间中数据点的方差。

——对于与高维数据点Xi和XJ对应的低维数据点Yi和YJ,可以使用以下方法计算相似的条件概率:

其中 ||yi-yj|| 表示 yi 与yj之间的欧几里得距离。

——在计算这两个概率之后,它最小化了两个概率之间的差异。


您可以参考本文来更详细地了解t-SNE。

现在我们将在Python中实现它并可视化结果:

from sklearn.manifold import TSNE 
tsne = TSNE(n_components=3, n_iter=300).fit_transform(df[feat_cols][:6000].values)

n_components 将决定转换数据中的组件数量。可视化转换数据的时间:

plt.figure(figsize=(12,8))
plt.title('t-SNE components')
plt.scatter(tsne[:,0], tsne[:,1])
plt.scatter(tsne[:,1], tsne[:,2])
plt.scatter(tsne[:,2], tsne[:,0])

在这里,您可以清楚地看到不同的组件已经转化使用强大的t-SNE技术。

 

3.12 UMAP

t-SNE在大型数据集上表现得很好,但它也有其局限性,如丢失大规模信息、计算时间慢以及不能有意义地表示非常大的数据集。统一流形逼近和投影(UMAP)是一种维数缩减技术,与t-SNE相比,它可以以较短的运行时间保存尽可能多的局部和更多的全局数据结构。听起来很有趣,对吧?

UMAP的一些主要优点是:

  • 它可以处理大数据集和高维数据而不太困难。
  • 它将可视化的能力与减少数据维度的能力结合在一起。
  • 除了保留局部结构外,它还保留了数据的全局结构。UMAP将流形上的邻近点映射到低维表示中的邻近点,并且对于远处点也这样做

该方法采用k-最近邻的概念,并利用随机梯度下降优化结果。它首先计算高维空间中点之间的距离,将它们投影到低维空间中,然后计算低维空间中点之间的距离。然后,使用随机梯度下降,以尽量减少这些距离之间的差异。为了更深入地了解UMAP是如何工作的,请查看本文

请参阅UMAP的文档和安装指南。现在我们将在Python中实现它:

import umap
umap_data = umap.UMAP(n_neighbors=5, min_dist=0.3, n_components=3).fit_transform(df[feat_cols][:6000].values)
  • 其中,n_neighbors确定使用的相邻点的数量
  • min_dist 控制如何允许严格的嵌入。较大的值确保嵌入点分布更均匀。

让我们想象这个转变:

plt.figure(figsize=(12,8))
plt.title('Decomposition using UMAP')
plt.scatter(umap_data[:,0], umap_data[:,1])
plt.scatter(umap_data[:,1], umap_data[:,2])
plt.scatter(umap_data[:,2], umap_data[:,0])

尺寸已经减少,我们可以可视化不同的转换组件。转化变量之间的相关性很小。让我们比较UMAP和t-SNE的结果:

我们可以看到,与从t-SNE获得的组件之间的相关性相比,从UMAP获得的组件之间的相关性要小得多。因此,UMAP倾向于提供更好的结果。

正如在UMAP的GitHub存储库中提到的,与t-SNE相比,它在保存数据全局结构的方面通常表现得更好。这意味着它通常可以提供更好的“大图”视图以及保存本地邻居关系。

好了,我们已经覆盖了相当多的降维技术。让我们简单地总结一下它们中的每一个都可以使用。

 

4 浅谈何时使用降维技术

在本节中,我们将简要概述我们所涵盖的每个维度约简技术的使用情况。理解在哪里可以和应该使用某种技术非常重要,因为它有助于节省时间、精力和计算能力。

  • 缺失值比率:如果数据集缺失值太多,我们使用这种方法来减少变量的数目。我们可以删除变量中有大量缺失值的变量。
  • 低方差滤波器:我们应用这种方法来识别和删除数据集中的常数变量。目标变量不受低方差变量的过度影响,因此可以安全地删除这些变量。
  • 高相关滤波器:一对具有高相关性的变量增加了数据集中的多重共线性。因此,我们可以使用这种技术来找到高度相关的特征并相应地丢弃它们。
  • 随机森林:这是最常用的技术之一,它告诉我们数据集中每个特征的重要性。我们可以发现每个特征的重要性并保持最上面的特征,从而减少维数。
  • 后向特征消除和前向特征选择技术都需要大量的计算时间,因此通常用于较小的数据集。
  • 因子分析:这种技术最适合于我们具有高度相关变量集的情况。它将基于相关性的变量划分为不同的组,并用一个因子来表示每个组。
  • 主成分分析:这是最广泛使用的处理线性数据的技术之一。它把数据分成一组试图解释尽可能多的差异的组件。
  • 独立组件分析:我们可以使用ICA将数据转换为独立的组件,这些组件使用较少的组件描述数据
  • ISOMAP:当数据是强非线性时,我们使用这种技术。
  • t-SNE:当数据是强非线性时,这种技术也能很好地工作。它对可视化效果也非常好。
  • UMAP:这种技术适用于高维数据。与t-SNE相比,它的运行时间更短。


小结

这是一个全面的关于降维的文章,你会在任何地方找到它!我编写它很有趣,并且找到了一些处理大量以前没有用过的变量(如UMAP)的新方法。

处理成千上万的特征对于任何数据科学家来说都是必不可少的技能。我们每天产生的数据量是前所未有的,我们需要找到不同的方法来找出如何使用它。降维是一个非常有用的方法,并且为我创造了奇迹,无论是在专业设置,还是在机器学习黑客。

我期待听到你的意见和意见在下面的评论部分。


原文链接:The Ultimate Guide to 12 Dimensionality Reduction Techniques (with Python codes)

作者:Pulkit Sharma

翻译:徐大白

| 2
登录后可评论,马上登录吧~
评论 ( 1 )
像徐大神学习
回复
1个月前