介绍
你是否曾经处理过具有一千多个特征的数据集?5万多个特征呢?我曾经有过,让我告诉你这是一项非常具有挑战性的任务,特别是如果你不知道从哪里开始的时候!拥有大量的变量既是好事,也是坏事。我们有大量的数据用于分析,这很棒,但由于规模太大,它变得非常具有挑战性。
在微观层面分析每个变量是不可行的。我们可能需要几天或几个月才能进行任何有意义的分析,我们将会为我们的业务损失大量的时间和金钱!更不用说这将需要的计算能力。我们需要一种更好的方法来处理高维数据,以便我们能够快速从中提取模式和见解。那么我们如何处理这样的数据集呢?
当然是使用降维技术。你可以使用这个技术来减少数据集中的特征数量,而不必丢失太多信息并保持(或改进)模型的性能。正如你将在本文中看到的,这是处理大型数据集的一种非常强大的方法。
这是一个可以在实际场景中使用的各种降维技术的综合指南。在深入介绍我所涵盖的12种不同技术之前,我们将首先了解这个概念是什么以及为什么要使用它。并且每种技术都有自己的Python实现代码,让你更好的熟悉它。
1.什么是降维?
我们每天都在生成大量的数据。事实上,世界上90%的数据都是在过去的3到4年中产生的!这些数字真的令人难以置信。以下是收集的数据的一些例子:
Facebook会收集你喜欢的,分享的,发布的,访问的地点,你喜欢的餐馆等的数据。你的智能手机应用程序会收集大量有关于你的个人信息亚马逊会收集你在其网站上购买,查看,点击等内容的数据赌场会跟踪每位客户的一举一动随着数据生成和收集量的不断增加,可视化和绘制分析变得越来越具有挑战性。进行可视化的最常见方法之一是通过图表。假设我们有2个变量,年龄Age和身高Height。我们可以使用Age和Height之间的散点图或线图,并轻松地将它们的关系可视化:
现在考虑我们有个变量(p=)的情况。在这种情况下,我们可以有(-1)/2=个不同的图。将它们分别可视化是没有多大意义的,对吧?在我们有大量变量的情况下,最好选择这些变量的一个子集(p),它获取的信息与原始变量集一样多。
让我们用一个简单的例子来理解这一点。考虑下面的图像:
这里我们有类似物体的重量,单位为Kg(X1)和磅(X2)。如果我们使用这两个变量,它们将传达相类似的信息。因此,仅使用一个变量是有意义的。我们可以将数据从2D(X1和X2)转换为1D(Y1),如下所示:
类似地,我们可以将数据的p维度减少为k维度的子集(kn)。这称为降维。
2.为什么需要降维?
以下是将降维应用于数据集的一些好处:
随着维度数量的减少,存储数据所需的空间会减少更少的维度导致更少的计算/训练时间当我们有一个大的维度时,一些算法的表现不佳。因此,需要减少这些维度才能使算法有用它通过删除冗余的特征来处理多重共线性问题。例如,你有两个变量-“在跑步机上花费的时间”和“燃烧的卡路里”。这些变量是高度相关的,因为你在跑步机上花费的时间越多,你燃烧的卡路里就越多。因此,存储两个变量都没有意义,只有其中一个可以满足需求它有助于可视化数据。如前所述,在高维度中可视化数据是非常困难的,因此将我们的空间缩小到2D或3D可以让我们更清晰地绘制和观察数据是时候深入了解本文的关键-各种降维技术!我们将使用一个实践问题:BigMartSalesIII中的数据集点击这里下载数据提取码为:fmk0。
3.常用的降维技术
降维可以通过两种不同的方式完成:
仅保留原始数据集中最相关的变量(此技术称为特征选择)通过查找较小的一组新变量,每个变量都是输入变量的组合,包含与输入变量基本相同的信息(此技术称为降维)我们现在将介绍各种降维技术以及如何在Python中实现它们。
3.1缺失值比率
假设你有一个数据集。你的第一步是什么?在构建模型之前,你应该会希望先探索数据。在研究数据时,你会发现数据集中存在一些缺失值。怎么办?你将尝试找出这些缺失值的原因,然后将输入它们或完全删除具有缺失值的变量(使用适当的方法)。
如果我们有太多的缺失值(比如说超过50%)怎么办?我们应该输入这些缺失值还是直接删除变量?我宁愿放弃变量,因为它没有太多的信息。然而,这不是一成不变的。我们可以设置一个阈值,如果任何变量中缺失值的百分比大于该阈值,我们将删除该变量。
让我们在Python中实现这种方法。
#导入所需要的库importpandasaspdimportnumpyasnpimportmatplotlib.pyplotasplt
首先,让我们加载数据:
#读取数据train=pd.read_csv(Train_UWu5bXk.csv)
注意:应在读取数据时添加文件的路径。
现在,我们将检查每个变量中缺失值的百分比。我们可以使用.isnull().sum()来计算它。
#检查每个变量中缺失值的百分比train.isnull().sum()/len(train)*
正如你在上表中所看到的,并没有太多的缺失值(实际上只有2个变量具有缺失值)。我们可以使用适当的方法来输入变量,或者我们可以设置阈值,比如20%,并删除具有超过20%缺失值的变量。让我们看看如何在Python中完成此操作:
#保存变量中缺失的值a=train.isnull().sum()/len(train)*#将列名保存在变量中variables=train.columnsvariable=[]foriinrange(0,12):ifa=20:#将阈值设置为20%variable.append(variables)
因此,要使用的变量存储在“variables”中,它只包含哪些缺失值小于20%的特征
3.2低方差过滤器
假设我们的数据集中的一个变量,其中所有观察值都是相同的,例如1。如果我们要使用此变量,你认为它可以改进我们将要建立的模型么?答案当然是否定的,因为这个变量的方差为零。
因此,我们需要计算给出的每个变量的方差。然后删除与我们的数据集中其他变量相比方差比较小的变量。如上所述,这样做的原因是方差较小的变量不会影响目标变量。
让我们首先使用已知ItemWeight观察值的中值来填充temWeight列中的缺失值。对于OutletSize列,我们将使用已知*OutletSize*值的模式来填充缺失值:
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)*
嘿瞧!我们都已经准备好了。现在让我们计算所有数值变量的方差。
train.var()
如上面的输出所示,与其他变量相比,Item_Visibility的方差非常小。我们可以安全地删除此列。这就是我们应用低方差过滤器的方法。让我们在Python中实现这个:
numeric=train[[Item_Weight,Item_Visibility,Item_MRP,Outlet_Establishment_Year]]var=numeric.var()numeric=numeric.columnsvariable=[]foriinrange(0,len(var)):ifvar=10:#将阈值设置为10%variable.append(numeric[i+1])
上面的代码为我们提供了方差大于10的变量列表。
3.3高度相关过滤器
两个变量之间的高度相关意味着它们具有相似的趋势,并且可能携带类似的信息。这可以大大降低某些模型的性能(例如线性回归和逻辑回归模型)。我们可以计算出本质上是数值的独立数值变量之间的相关性。如果相关系数超过某个阈值,我们可以删除其中一个变量(丢弃一个变量是非常主观的,并且应该始终记住该变量)。
作为一般准则,我们应该保留那些与目标变量显示出良好或高相关性的变量。
让我们在Python中执行相关计算。我们将首先删除因变量(ItemOutletSales)并将剩余的变量保存在新的DataFrame(df)中。
df=train.drop(Item_Outlet_Sales,1)df.corr()
太棒了,我们的数据集中没有任何具有高相关性的变量。通常,如果一对变量之间的相关性大于0.5-0.6,我们真的应该认真的考虑丢弃其中的一个变量。
3.4随机森林
随机森林是最广泛使用的特征选择算法之一。它附带内置的重要功能,因此你无需单独编程。这有助于我们选择较小的特征子集。
我们需要通过应用一个热编码将数据转换为数字形式,因为随机森林(Scikit-Learn实现)仅采用数字输入。让我们也删除ID变量(Item_Identifier和Outlet_Identifier),因为这些只是唯一的数字,目前对我们来说并不重要。
fromsklearn.ensembleimportRandomForestRegressordf=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.columnsimportances=model.feature_importances_indices=np.argsort(importances)[-9:]#top10featuresplt.title(FeatureImportances)plt.barh(range(len(indices)),importances[indices],color=b,align=center)plt.yticks(range(len(indices)),[featuresforiinindices])plt.xlabel(RelativeImportance)plt.show()
基于上图,我们可以手动选择最顶层的特征来减少数据集中的维度。值得注意的是,我们可以使用sklearn的SelectFromModel来实现这一点。它根据权重的重要性来选择特征。
fromsklearn.feature_selectionimportSelectFromModelfeature=SelectFromModel(model)Fit=feature.fit_transform(df,train.Item_Outlet_Sales)
3.5反向特征消除
按照以下步骤来理解和使用“反向特征消除”技术:
我们首先获取数据集中存在的所有的n个变量,然后使用它们训练模型然后我们计算模型的性能现在,我们在消除每个变量(n次)后计算模型的性能,即我们每次都丢弃一个变量并在剩余的n-1个变量上训练模型我们确定移除变量后对模型性能影响最小(或没有)变化的变量,然后删除该变量重复此过程,直到不能删除任何变量在构建线性回归或逻辑回归模型时,可以使用此方法。我们来看看它的Python实现:
fromsklearn.linear_modelimportLinearRegressionfromsklearn.feature_selectionimportRFEfromsklearnimportdatasetslreg=LinearRegression()rfe=RFE(lreg,10)rfe=rfe.fit_transform(df,train.Item_Outlet_Sales)
我们需要指定算法和要选择的特征数量,并返回从反向特征消除中获得的变量列表。我们还可以使用“rfe.ranking”命令检查变量的排名。
3.6正向特征选择
这与我们在上面看到的反向特征消除的过程相反。我们是尝试找到改善模型性能的最佳特征,而不是消除特征。该技术的工作原理如下:
我们从一个特征开始。本质上,我们分别使用每个特征训练模型n次选择性能最佳的变量作为起始变量然后我们重复这个过程并每次只添加一个变量。保留产生最高性能增长的变量我们重复这个过程,直到模型的性能没有显著的改进让我们用Python实现它:
fromsklearn.feature_selectionimportf_regressionffs=f_regression(df,train.Item_Outlet_Sales)
这将返回一个数组,其中包含变量的F值和与每个F值对应的p值。为了我们的目的,我们将选择F值大于10的变量:
variable=[]foriinrange(0,len(df.columns)-1):ifffs[0]=10:variable.append(df.columns)
这为我们提供了基于正向特征选择算法的最多变量。
注意:反向特征消除和正向特征选择都是非常耗时且计算成本高的。它们实际上仅用于具有少量输入变量的数据集。
到目前为止我们看到的技术通常在我们的数据集中没有太多变量时使用。这些或多或少的特征选择技术,在接下来的部分中,我们将使用FashionMNIST数据集,该数据集包含属于不同类型服装的图像,例如T恤,裤子,包等。数据集可点击此处下载,提取码为:a。
该数据集共有70,张图像,其中60,张在训练集中,其余10,张是测试图像。在本文的范围中,我们将仅处理训练图像。训练集文件采用zip格式。解压缩zip文件后,你将获得一个.csv文件和一个包含这60,张图像的训练集文件夹。每个图像的相应标签可以在train.csv文件中找到。
3.7因子分析
假设我们有两个变量:收入和教育。这些变量可能具有高度相关性,因为具有较高教育水平的人往往具有显着较高的收入,反之亦然。
在因子分析技术中,变量按其相关性进行分组,即特定组内的所有变量之间具有高度相关性,但往往与其他组的变量之间相关性较低。在这里,每个组都被称为一个因子。与原始数据维度相比,这些因子的数量很少。但是,这些因子往往很难观察到。
让我们先读入训练集文件夹中包含的所有图像:
importpandasaspdimportnumpyasnpfromglobimportglobimportcv2images=[cv2.imread(file)forfileinglob(train/*.png)]
注意:你必须使用train文件夹的路径替换glob函数内的路径。
现在我们将这些图像转换为numpy数组格式,以便我们可以执行数学运算并绘制图像。
images=np.array(images)images.shape
(60,28,28,3)
如上所示,它是一个三维数组。我们必须将它转换为一维的,因为所有即将出现的技术只需要一维输入。为此,我们需要展平图像:
image=[]foriinrange(0,60):img=images.flatten()image.append(img)image=np.array(image)
现在让我们创建一个DataFrame,其中包含每个图像中每个像素的像素值,以及它们对应的标签(对于标签,我们将使用train.csv文件)。
train=pd.read_csv(train.csv)#给出你的train.csv文件的完整路径feat_cols=[pixel+str(i)foriinrange(image.shape[1])]df=pd.DataFrame(image,columns=feat_cols)df[label]=train[label]
现在我们将使用因子分析来分解数据集:
fromsklearn.de