med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)

新闻资讯2026-04-21 00:09:41

原文:TowardsDataScience

协议:CC BY-NC-SA 4.0

原文:https://towardsdatascience.com/feature-engineering-for-machine-learning-a80d3cdfede6

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第1张

图片由来自皮克斯拜的皮特·林福思拍摄

深度学习的时代已经普及了端到端的机器学习方法,其中原始数据进入管道的一端,预测从另一端出来。这无疑加速了某些领域中的模型推理,尤其是在计算机视觉管道中,例如,单次检测器的帧速率高于依赖区域建议然后进行对象检测的模型。复杂模型自动提取特征的能力使得牺牲计算资源以节省人力资源成为可能。

这种方法意味着机器学习实践者越来越多地通过模型而不是磨练他们的数据。但是,当轻松的收益被收获时,模型大小加倍只能勉强维持一点点的性能改进。这是手工制作功能可以获得更好回报的时候。

“应用机器学习基本上是特征工程”

—吴恩达

在某种程度上,视觉数据的丰富性、高维性和丰富性使得自动化和手工制作的特征之间的权衡成为可能。当处理缺乏数据或特征不丰富的数据时,这种情况对于数据科学家来说太常见了,他们的任务是根据十几个特征做出预测,特征工程对于补充和梳理有限数据中存在的所有可用“信号”至关重要;以及克服流行的机器学习算法的限制,例如,基于乘法或除法特征交互来分离数据的困难。

在 Kaggle 竞赛中,最优秀的团队赢得比赛不仅仅是因为模型选择、集成和超参数调整,而是因为他们设计新功能的能力,有时看似无中生有,但更多时候是源于对数据的真正理解(带来领域知识)、辅助数据的补充,以及顽强、创造性(更像艺术而不是科学)但乏味的构建和测试新功能的试错工作。

在这个由多个部分组成的系列中,我们将讨论完整特征工程管道的三个部分:

  1. 数据预处理
  2. 特征生成
  3. 特征选择

这三个步骤是按顺序执行的,但有时对于某项技术是构成数据预处理、特征提取还是生成会有歧义。但我们在这里并不拘泥于语义…相反,我们将专注于调查任何优秀的机器学习实践者和数据科学家可以在项目中运用的所有技术。

这一系列文章的目的是提高对这些有时被遗忘的问题的认识,特别是在深度学习和十亿参数模型的时代,这些技术要永远留在脑海中,并知道一些可以极大地方便其使用的库函数。描述每种技术的内部工作原理都需要一篇文章,其中很多可以在走向数据科学上找到。

“垃圾进,垃圾出。”

在 EDA 过程中,首先要做的一件事就是检查并移除常量特性。但模型肯定能自己发现这一点吗?是,也不是。考虑一个线性回归模型,其中非零权重已被初始化为常数特征。然后,这一项作为次要的“偏差”项,看起来没有什么害处…但是如果“常数”项只在我们的训练数据中是常数,并且(我们不知道)后来在我们的生产/测试数据中呈现不同的值,那么就不是了。

另一件需要注意的事情是重复的特性。当涉及分类数据时,这可能并不明显,因为它可能表现为不同的标签名称被分配给不同列中的相同属性,例如,一个特征使用“XYZ”来表示分类类,而另一个特征表示为“ABC”,这可能是由于列是从不同的数据库或部门中挑选出来的。[pd.factorize()](https://pandas.pydata.org/docs/reference/api/pandas.factorize.html)可以帮助识别两个特征是否同义。

接下来,冗余的高度相关的特征。多重共线性会导致模型系数不稳定,并且对噪声高度敏感。除了对存储和计算成本的负面影响之外,当考虑权重正则化时,冗余特征削弱了其他特征的有效性,使得模型更容易受到噪声的影响。[pd.DataFrame.corr()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.corr.html)可用于识别相关特征。

复制可能不仅发生在列之间,也可能发生在之间。此类样本复制会导致训练期间的数据失衡和/或过度拟合。[pd.DataFrame.duplicated()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.duplicated.html)将在第一次出现之后的每个重复行中返回一个具有真值的序列。

区分预处理过程中的洗牌和训练过程中的很重要。

在预处理过程中,在将数据集分成训练/验证/测试子集之前,对其进行洗牌是非常重要的。对于小型或高度不平衡的数据集(例如,在异常、欺诈或疾病检测中),利用[sklearn.model_selection.train_test_split()](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html)stratify on 功能确保您的少数目标在所有子集中的分布一致。[pd.DataFrame.sample(frac=1.0)](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.sample.html)可用于轻松洗牌。

对于训练,大多数 ML 框架将为您洗牌,但重要的是要了解它是在进行一次性洗牌,即仅在加载数据集时,还是在逐批的基础上继续这样做。后者对于获得最低的训练损失是优选的,但是会导致较慢的训练,因为小批量的数据不能被缓存并在下一个时期重新使用。

这是个大话题!缺失的特征应仔细处理。

缺失的特征可能不会立即显现出来,所以仅仅使用[pd.DataFrame.isna.sum(axis=0)](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.isna.html)可能无法将它们全部显现出来。可以使用特殊(非空)字符串或数值(例如,“-”、0 或-999)来表示缺失字段。您正在使用的数据集可能已经由某人进行了预处理和预估算。幸运的是,检测缺失特征可以通过绘制每个特征的直方图来完成——异常的异常峰值表明使用了特殊值,而分布中间的峰值则表明已经进行了均值/中值插补。

下一个问题是如何估算缺失字段。最常见和最直接的方法是用模式(针对分类特征)、均值(针对没有大量异常值的数字特征)或中值(其中异常值明显扭曲均值)来替代缺失值。

即便如此,尤其是如果你认为这个特征很重要,不要盲目替换整个数据集的均值/中值/众数。举例来说,在泰坦尼克号的数据集中,几名乘客漏掉了他们的年龄。不要用船上所有乘客的平均年龄来估算所有这些乘客,我们可以通过认识到船上乘客等级之间的平均(和中值)年龄非常不同来得到更精确的估计。

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第2张

表 1:按乘客等级和性别划分的乘客年龄中位数

事实上,由于该数据集中没有乘客性别的缺失值,因此您可以在输入时更进一步,根据 I .票价等级和 ii 替换年龄中位数。缺少年龄值的每个样本的性别。

对于一个时间序列,我们不应该使用均值/中位数替代来估算缺失样本,因为这总是会导致序列发生不切实际的突变。相反,使用值重复或插值进行估算。像中值滤波或低通零相位滤波这样的信号处理去噪方法也可以用来填充训练数据中的小间隙;但是请记住,非因果方法不能在生产过程中使用,除非模型的延迟输出是可接受的。

一种替代方案是根本不估算,而是添加二进制标志,以允许下游学习算法自行学习如何处理这种情况。这样做的缺点是,如果丢失的值分布在许多特征上,您可能必须添加更多这样的低信号特征。注意,XGBoost 开箱即用地处理NaN ,所以在使用它时不需要添加缺失数据列。一般来说,决策树可以通过将缺失值设置为决策节点可以轻松拆分的下/上限值,来处理缺失值的特殊值标签编码。

另一种流行的方法是运行 k-NN 来估算缺失值。使用神经网络进行插补是另一种流行的方法。例如,可以对自动编码器进行训练,以在输入丢失的情况下再现训练数据,一旦训练完成,其输出就可以用于预测丢失的特征值。然而,使用最大似然法学习插补可能很棘手,因为很难评估插补模型的超参数(例如 k 的值)如何影响最终模型的性能。

无论采用何种插补方法,只要有可能,在数据插补之前,始终在之前执行特征生成(在本系列的第二部分中讨论),因为这将允许更精确地计算生成的特征值,特别是在特殊值编码用于插补时。当生成新要素时,知道相关的要素值缺失就为特殊处理敞开了大门。

序数特征可能有整数值,但与数值特征不同的是,虽然序数服从传递比较关系,但不遵守减法或除法的算术规则。

有序特征,如星级,通常具有高度非线性的“真实”映射,对应于强双极分布。也就是说,4 星与 5 星评级之间的定量“差异”通常很小,远远小于 4 星与 2 星评级之间差异的一半,这会混淆线性模型。

因此,线性模型可能受益于序数值赋值的更线性的重映射,但是另一方面,基于树的模型能够本质上处理这种非线性。最好将序号编码保留为一个单一量化特征(即“列”),而不是虚拟化,因为虚拟化会降低其他预测特征的信噪比(例如,当应用参数正则化时)。

分类特征的处理取决于你的模型是否是基于树的。基于树的模型可以使用标签编码(即表示类成员的固定字符串或整数),不需要进一步的预处理。非树方法要求分类特征是一键编码,这可以使用[pd.get_dummies()](https://pandas.pydata.org/docs/reference/api/pandas.get_dummies.html)[sklearn.preprocessing.OneHotEncoder()](http://sklearn.preprocessing.onehotencoder)来执行。避免删除第一列(即不要指定drop=’first’),除非你正在处理一个二进制类别(即使用drop=’if_binary’),因为删除产生的问题比它解决的问题还要多。

一键编码的替代方法是使用或补充频率编码。这包括计算对应于每个类别的目标变量的标准化频率。例如,如果该类别中 40%的样本导致目标值为 1,则将值 0.4 分配给二进制分类特征。当分类特征与目标值相关时,这样做是有帮助的。

编码分类特征的另一种方式是使用分类嵌入。这尤其适用于高基数分类要素,如邮政编码或产品。如同单词嵌入一样,这些嵌入使用密集的神经网络来学习。结果分析表明这些连续嵌入对于聚类和可视化也是有意义的,同时减少过拟合。

处理分类特征的最后一点是,如果在验证/测试子集中遇到一个看不见的类别,该怎么办。在这种情况下,就像对待缺失特征一样对待它,或者将其指定为“未知”保留类别。

缩放归一化对于基于树的方法来说不是必需的,但是对于实现低训练损失、快速收敛以及为了使权重正则化正常工作来说是必不可少的。选择其中之一。

缩放[sklearn.preprocessing.MinMaxScaler()](https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.MinMaxScaler.html)速度很快,通常是图像数据所需的全部。然而,最小-最大缩放会受到异常值的显著影响(即使只有一个异常值!)或编码为正常特征范围之外的值的缺失值。

只要异常值的比例很小(即,如果异常值没有显著扭曲平均值和标准偏差),归一化[sklearn.preprocessing.StandardScaler()](https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.StandardScaler.html)对异常值更稳健。

数字特征通常可以受益于变换对数变换,np.log(1 + x),是一种非常强的变换,当一个特征遵循幂律关系时,或者当离群值分布中存在长尾时,这种变换特别有用。平方根变换,np.sqrt(x)不太强,可以作为有用的中间变换来尝试。由于使用了 lambda 超参数, Box-Cox [scipy.stats.boxcox()](https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.boxcox.html)变换允许从线性传递函数平滑过渡到高度非线性传递函数,并且通常用于将偏斜分布(例如,作为年龄函数的 COVID 测试阳性率)转变为更加正态的分布,这是许多传统 ML 算法(如 NB、LogR 和 LinR)做出的基本假设。[注意:x > = 0 被假定用于所有上述变换]。

基于树的方法有时可以受益于地理位置坐标上的旋转变换。例如,South-of-Market (SoMa)是旧金山的一个街区,与市场街接壤。然而,市场街不是南北走向或东西走向,而是西南-东北走向。因此,决策树将很难清晰地分割出这个邻域(当树的深度受限时,这是经常需要的),因为树只能绘制与轴平行的分割线(即与经度轴或纬度轴平行)。执行旋转变换的困难在于选择旋转坐标的轴点,因为可能没有全局最优的轴点。

一种解决方案是执行笛卡尔坐标到极坐标 T2 的转换。例如,巴黎市被划分为几个区,这些区围绕市中心大致呈环形分布。或者,可以执行聚类,并创建新的分类特征来指示点属于哪个聚类,之后可以使用极坐标来编码每个点相对于其聚类质心/核的位置。

数据集中的时间可能显示为 UTC/GMT 时间,而不是本地时间,即使所有事件都属于同一个(不同的)时区。即使时间戳以本地时间给出,对时间特征执行时移也可能是有益的。

例如,由于较高的需求和较低的供应,拼车费用往往在一天中“较晚”时(特别是 Fri/星期六/星期日)较高。然而,任何深夜狂欢者都知道,派对不会在午夜停止。由于时间的推移,模型很难辨别 00:30 是否“晚于”,甚至“接近”23:30。然而,如果执行时间转换,并且在一天中活动量最少的时间内发生棘手的 23:59H → 00:00H 回绕,那么线性模型将回归得更好,而基于树的模型将需要更少的分支级别。

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第3张

图片来自 Pixabay 的 Gerd Altmann

可以说,文本是需要最多预处理的特性。我们从变换开始,变换有很多。

小写对于简单模型来说是必要的,它是文本标准化的最基本形式,有利于产生更强、更稳健的信号(由于出现的词频更高),同时减少词汇量。对于自带分词器的更高级的经过预训练的语言模型 (LM),最好让 LM 对原始文本进行分词,因为大写(例如用[bert-base-cased](https://huggingface.co/bert-base-cased))可能有助于模型在句子解析、命名实体识别(NER)词性(词性)标注方面表现更好。

词干词汇化提供了与小写相同的好处,但是更复杂,运行时间也更长。词干使用固定的规则来删减单词,这些规则不考虑单词在句子中的上下文和用法,例如university被删减为univers,但universal也是如此。词汇化考虑了上下文并需要使用大的 LMs,因此比词干化慢。然而,这要准确得多,例如,universityuniversal仍然是独立的词根。考虑到当今可用的计算资源, Spacy 的作者认为准确性在生产中最重要,因此该库只支持词汇化。

收缩扩展是具有相同动机的另一种形式的文本规范化。这里can’tyou’ll扩展为can notyou will。简单的基于计数/频率的模型受益于这种标准化,但是像 Spacy 中的那些 LMs 通过使用子词标记化 ( can’t被标记化为ca然后是n’t)来处理缩写。

文本规范化旨在将文本和符号转换为规范形式,以便模型可以更好地学习。他们转换缩写(如 BTW)、拼写错误(如’ definately ')、音调符号(如 café/naive→café/naive)、表情符号(如|:-)|;) | 🙂→ <SMILE>,ROFL | LOL | LMAO |😆→ <LAUGH>)等。如果没有文本规范化,许多 NLP 模型将很难理解 Twitter 和社交媒体上的帖子!

接下来是过滤——停用词、标点符号、数字、多余的空格、表情符号(不执行情感分析时)、HTML 标签(例如< br >)、HTML 转义字符(例如’&amp;‘,’&nbsp;')、网址、标签(例如#黑色星期五)和提及次数(例如@xyz)

最后的预处理步骤是标记化。简单的标记化可以使用 python 正则表达式来执行,但是 NLP 框架提供了用 C/C++或 Rust 编写的专用标记化器,性能更高。当使用预训练的 LM 时,例如来自拥抱脸的那些,使用与 LM 训练时使用的完全相同的记号赋予器(和权重)是至关重要的。

随着 CNN 的流行,预处理图像现在不太常见。然而,在没有 GPU 的资源受限的硬件中,或者当需要高帧速率时,这些技术形成了传统计算机视觉处理流水线的基本功能。

色彩空间转换可以用简单的 CNN 提供轻微的性能提升。例如,这项研究发现,将 CIFAR-10 数据集转换到 Lab 颜色空间可以提高大约 2%的分类精度,但同时使用多个颜色空间可以获得最佳结果。已经发现,具有分离的色度和亮度通道的色彩空间(例如 YUV)有助于图片彩色化和风格转换。我个人发现,为特定领域定制的专门颜色转换(例如,用于组织病理学的苏木精-伊红-DAB)对提高模型性能特别有帮助。

直方图均衡,尤其是自适应直方图均衡(如 CLAHE),经常在医学成像上进行,以提高视觉对比度。当图像中的光照不均匀且区别特征相对于整个图像帧较小时,例如检测乳房 x 线照相图像中的癌组织时,这种方法特别有用。在视网膜眼底成像中,图像采集过程中图像质量的可变性很高,执行非均匀照明校正已被证明可提高分级精度。

传统的 CV 特征提取技术包括局部二元模式( LBP )、方向梯度直方图( HOG )和 Gabor 滤波器bank。在非 CNN 模型上成功使用这些特征提取器已经有很长的历史了。将这些较老的技术(例如可学习的 Gabor 滤波器)与标准卷积层相结合,可以在某些数据集(例如 D ogs-vs-Cats )上实现更快的收敛和更高的精度。

本系列关于特征工程的第一部分到此结束。在第二部分中,我们将注意力转向特征生成,在这里我们将着眼于提取和合成全新的特征。这是艺术与科学真正相遇的地方,也是将卡格尔大师与新手区分开来的地方!

原文:https://towardsdatascience.com/feature-engineering-for-machine-learning-in-r-2ed684727566

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第4张

杆长在 Unsplash 上拍照

本文是故事掌握 R 编程基础的续篇。在第一篇文章中,我介绍了 R 的构建模块,它将帮助你了解这门语言。理解和学习真的很直观。在这篇文章中,我将重点关注特征处理,它代表了任何数据科学项目的相关部分。如果没有干净的数据,任何机器学习模型的努力都将是徒劳的。让我们开始这段旅程吧!

  1. 转换为因子
  2. 添加和删除列
  3. 从连续特征到分类特征
  4. 查找缺失值
  5. 处理缺失值

在之前的帖子里,我建议你同时安装 RR studio 。R 是一门语言,而 R studio 是一个 IDE,允许以一种更简单的方式使用 R。

让我们从从 Kaggle 导入数据集银行流失模型开始,并可视化前六行[1]。

df <- read.csv('Bank_churn_modelling.csv',header = T)
head(df)

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第5张

作者插图

你能注意到的第一件事(如果你以前使用过 Python)是我们不需要导入任何库,很漂亮,不是吗?让我们尝试查看有关数据集的其他统计数据和信息:

 summary(df)

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第6张

作者插图

summary是用于打印所有特性的描述性统计的功能。从输出来看,值得注意的是:

  • 大多数变量被认为是数字。但是像 Excited 和 HasCrCard 这样的变量,范围在 0 到 1 之间。然后,要把这些特征转化为因子。
  • 姓氏、地域、性别是性格变量。因此,输出会显示其他信息,包括样本数量(长度)、类的类型和模式。我们也应该把地理和性别转换成因素变量。
str(df)

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第7张

作者插图

str提供了一个更紧凑的输出,总结了数据集的结构。它告诉我们有 1000 行和 14 列。大多数变量包含数值/整数值,而其余的特征是字符变量。

正如我们在上一段中看到的,我们必须进行更改,将一些变量转换为因子。你可能想知道是什么因素。在 R 语言中,因子是专门用于将元素分类的向量类型。换句话说,因素是分类变量,可以有两个或更多的层次。这些级别可以包含字符串和整数。

df$Geography <- as.factor(Geography)
df$Gender <- as.factor(Gender)
df$HasCrCard <- as.factor(HasCrCard)
df$IsActiveMember <- as.factor(IsActiveMember)
df$Exited <- as.factor(Exited)
str(df)

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第8张

作者插图

如果我们再次使用str函数很好地转换了变量,我们可以很容易地检查。为了可视化因子的级别,我们可以使用 levels 函数:

levels(Geography)
# "France"  "Germany" "Spain"

该数据集仅包含法国、德国和西班牙的客户。

添加新列的更简单的方法是给整个新变量分配一个值。例如,让我们创建一个用 NA 填充的新列,NA 是一个逻辑常数,表示 r 中缺少的值。

df$newcol <- NA
df[1:5,8:15]

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第9张

作者插图

为了更容易可视化,我选择了数据集的一个子集,前 5 行和后 8 列。添加列的另一种方法是使用以下语法:

df['newcol'] <- NA

因此,我们可以在方括号中指定变量,而不是使用$运算符。要删除一个列,我们可以将其设置为 NULL,这表示 R:

df$newcol <- NULL
# alternative df['newcol'] <- NULL
head(df)

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第10张

作者插图

我们打印了前五行以检查是否删除了该列。真的消失了!

假设我想基于 EstimatedSalary 的值创建一个新变量。目标是将估计工资的范围可视化为区间。这可以通过使用cut功能来实现:

df$estsalaryclass<-cut(df$EstimatedSalary,breaks = seq(0,max(df$EstimatedSalary)+1,len=4))
levels(df$estsalaryclass)
# [1] "(11.6,6.67e+04]"     "(6.67e+04,1.33e+05]" "(1.33e+05,2e+05]" 

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第11张

作者插图

为了创建间隔,应用 seq 函数来创建三个不同的级别。它接受序列的起始值、结束值和长度作为输入。

我们还可以向指定参数标签的箱添加标签:

df$estsalaryclass<-cut(df$EstimatedSalary,breaks = seq(0,max(df$EstimatedSalary)+1,len=4),
                       labels = c('poor','middle','rich'))
levels(df$estsalaryclass)
# [1] "poor"   "middle" "rich"
df[1:5,c('EstimatedSalary','estsalaryclass')]

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第12张

作者插图

从图中,您可以推断出因子级别的名称是在指定界限后创建的。

我们还可以注意到,默认情况下,间隔在左边打开,在右边关闭。这意味着只有较高的值包含在界限中,而最低的值被排除。

如果我们希望区间在左边关闭,在右边打开,我们需要将参数 right 设置为 FALSE:

df$estsalaryclass<-cut(df$EstimatedSalary,breaks = seq(0,max(df$EstimatedSalary)+1,len=4),right = FALSE)
levels(df$estsalaryclass)
[1] "[11.6,6.67e+04)"     "[6.67e+04,1.33e+05)" "[1.33e+05,2e+05)"

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第13张

作者插图

r 语言提供了is.na函数来检查数据集中是否有缺失值。要计算数据集的缺失值,我们可以对它们求和:

sum(is.na(df))
# [1] 0

由于数据框不包含缺失值,我们可以手动添加它作为练习:

df[5,'Age'] = NA
sum(is.na(df))
# [1] 1

你大概在想is.na功能到底在做什么?让我们打印这个函数的输出:

head(is.na(df))

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第14张

作者插图

它返回一个包含表示缺失值的布尔值的数据框,其中 TRUE 表示我们有一个 NA 值。要返回每列缺失值的数量,我们可以使用forcat函数:

for (i in 1:length(df))
{cat(c(colnames(df[i]),':',sum(is.na(df[,i])),"
"))}

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第15张

作者插图

for用于迭代列,而cat用于打印输出。在这种情况下,cat 函数更适合打印,因为它允许在同一行显示多个值。从输出中,我们可以很容易地看到,只有年龄列中缺少一个值。

为了显示包含 NA 值的列的行索引,我们可以使用which函数:

which(is.na(df[,'Age']))
#[1] 5

该函数给出逻辑向量中真实元素的位置。出于这个原因,我们只指定列向量作为输入,而不是整个数据帧。

处理缺失值的更简单的方法是删除包含 NA 值的行:

df_notna<-na.omit(df)
sum(is.na(df_notna))
# [1] 0

na.omit轻松删除有 NA 的行,返回一个没有丢失值的数据帧。

但是删除丢失的值并不总是最好的解决方案。另一种方法是用列的平均值代替 NA 值:

avg_age <- round(mean(df$Age,na.rm=TRUE))
df$Age<-ifelse(is.na(df$Age),avg_age,df$Age)

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第16张

作者插图

ifelse(test,yes,no)返回一个与年龄变量形状相同的向量。如果测试的条件为真,则该列的值将被年龄的平均值替换。否则,返回值将与作为输入的列中的值相同。

  • strsummary用于可视化关于数据帧的信息
  • printcat都有助于显示输出。
  • as.factor用于将变量转换成因子
  • cut通过将特征范围划分为区间,将连续变量转换为分类变量
  • is.na返回包含布尔值的数据帧,其中 TRUE 表示单元格中存在 NA
  • which显示矢量中包含的真实元素的位置
  • na.omit删除数据帧中带有 NA 的行
  • ifelse(test,yes,no)是一种更简洁、更快速的 if-else 语句。

我希望这篇教程对你有用。我发现有必要写这篇文章,因为没有很多资源讨论 r 的特性工程。我没有涵盖所有的方面,因为我将在接下来的文章中涵盖其余的方面。感谢阅读!祝你有愉快的一天。

参考文献:

[1]https://www . ka ggle . com/sanjanavoona 1043/bank-churn/version/1

你喜欢我的文章吗? 成为会员 每天无限获取数据科学新帖!这是一种间接的支持我的方式,不会给你带来任何额外的费用。如果您已经是会员, 订阅 每当我发布新的数据科学和 python 指南时,您都会收到电子邮件!

原文:https://towardsdatascience.com/feature-engineering-for-machine-learning-with-picture-data-d7ff8554920

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第17张

解释维数灾难的插图(作者图片)

特征工程是获取原始数据并提取对建模有用的特征的过程。对于图像,这通常意味着提取颜色、纹理和形状等信息。进行特征工程有多种方法,您采用的方法将取决于您正在处理的数据类型和您试图解决的问题。

但是我们为什么需要它的图片呢?

图像封装了大量信息,但这是有代价的:高维数。例如,具有 3 个通道(红、绿、蓝)的尺寸为 200×100 像素的小图片已经表示了 60000 维的特征向量。

这需要处理很多事情,而且我们正面临着维数灾难。我们稍后会对此进行更多的讨论。

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第18张

图片的维数示例(图片由作者提供)

在这篇文章中,我们将看看如何降低图片的维度来对抗维度的诅咒。

“维数灾难”是一个术语,用来描述在处理具有大量维度的数据集时出现的问题。

一个原因是,准确了解数据的基本分布所需的数据点的数量随着维度的数量呈指数增长。换句话说,如果我们有一个包含 100 个特征的数据集,我们可能需要大约 1000 甚至 10000 个数据点才能有很好的机会准确学习。

为了更好地理解维数灾难,我喜欢举一个二维 k 近邻图的例子,如下图所示。

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第19张

k 近邻图可视化(图片由作者提供)

但是如果所有的点都是等距的,会发生什么呢?这是一个非常不可能的场景,但它(在某种程度上)显示了当我们试图计算具有许多维度的特征之间的欧几里德距离时通常会发生什么。

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第20张

等距点的最近邻问题(图片由作者提供)

为了理解维度的数量如何影响我们的距离度量,我们可以看一下内接在超立方体中的 n 维球(n 球)内部和外部的体积之比。

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第21张

超立方体中 n 球内外的体积(图片由作者提供)

我们可以在此图中观察到,n 球外部的体积将占据大部分空间。这是非常违反直觉的,不像我们习惯掌握的二维或三维空间。

如果我们在超立方体中均匀分布点,它们中的任何一个都不太可能落入内接的 n 球中。

这将给人这样的印象,即超立方体中的所有点将离 n 球的中心非常远,并且看起来是等距离的,并且集中在超立方体的长尖角上。这将导致我们的基于距离的算法容易受到输入特征上的噪声的影响。

那么,如何才能解决呢?

降低特征向量维数的一个简单方法是通过降低图像的分辨率,利用抽取(下采样)来减小图像的大小。

如果颜色分量不相关,我们也可以将图片转换为灰度,以将数字维度除以三。但是还有其他方法可以减少图片的尺寸,并潜在地提取特征。例如,我们可以使用小波分解。

小波分解是一种在空间和频率上分解信号的方法。就图片而言,这意味着将图像分解成水平、垂直和对角线分量。

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第22张

小波分解示例(图片由作者提供)

HOG 特征描述符是在计算机视觉和图像处理中用于检测数字图像中的对象的流行技术。在 Dalal 和 Triggs 于 2005 年展示了这种描述符的效率之后,HOG 描述符变得流行起来,该描述符专注于静态图像中的行人检测。

HOG 描述符是一种特征描述符,它通过计算图像中亮度梯度的分布来编码对象的形状和外观。

在我们的情况下,最重要的参数是每个单元的像素数,因为它将为我们提供一种方法来找到维度数量和图片中捕捉的细节数量之间的最佳平衡。

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第23张

8×8 像素单元的方向渐变直方图示例(图片由作者提供)

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第24张

16 乘 16 像素单元的方向渐变直方图示例(图片由作者提供)

对于上面的示例,输入图像具有 20,000 个维度(100×200 像素), HOG 特征对于 8×8 像素单元具有 2,400 个维度,对于 16×16 像素单元具有 576 个维度。分别减少了 88%和 97%。

我们还可以使用主成分分析(PCA)来降低特征向量的维数。PCA 是一种统计技术,可用于寻找最大化方差和最小化数据集中投影误差的方向(分量)。

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第25张

方差最大的轴(绿色)和投影误差较小的轴(红色)(图片由作者提供)

换句话说,主成分分析可用于寻找代表数据中最多信息的方向。

使用 PCA 时,需要记住以下几点:

  • PCA 最好是作为降维的工具,而不是用于特征选择。
  • 使用 PCA 进行降维时,首先对数据进行归一化是很重要的。
  • PCA 是线性变换,因此它不能捕捉数据中的非线性关系。
  • 为了减少到 N 维,你至少需要 N-1 次观察

我建议阅读以下文章,以便更好地理解 PCA 及其局限性:

流形学习在某些方面是线性方法(如 PCA)的扩展,用于降低维数,但用于数据中的非线性结构。

流形是局部欧几里得的拓扑空间,这意味着在每个点附近它都类似于欧几里得空间。流形自然地出现在数学和物理的许多领域,流形的研究是微分几何的一个中心课题。

使用多方面学习时,有几件事要记住:

  • 流形学习是降维的有力工具。
  • 它可以用来发现数据中隐藏的模式。
  • 流形学习通常是一项计算密集型任务,因此在使用这些算法之前对它们有一个很好的理解是很重要的。

现实生活中的流程很少使用其所有维度来描述其底层结构。例如下面的图片,只需要几个维度来描述杯子的位置和旋转。

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第26张

具有不同位置和旋转的杯子数据集(图片由作者提供)

这种情况下,一旦使用流形学习算法(如 t-分布式随机邻居嵌入(t-SNE ))进行投影,只有两个维度能够编码杯子的位置和旋转。

编码位置:

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第27张

30-cup 数据集的最近邻图(图片由作者提供)

编码旋转:

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第28张

第一个位置的编码旋转(图片由作者提供)

在这篇文章中,我们看到了如何使用图片的特征工程来对抗维数灾难。我们已经了解了如何通过抽取、小波分解、HOG 描述符和 PCA 来降低图片的维度。我们还看到了如何使用流形学习来发现数据中隐藏的模式。

还有许多其他方法可以减少图片的尺寸,您采用的方法将取决于您正在处理的数据类型和您试图解决的问题。

特征工程是一个迭代的过程,它有助于对不同的可能性和可用的方法有一个总体的了解。

我希望这篇文章对你有帮助!如果您对如何构建 k-NN 图有任何疑问,我建议您阅读以下文章:

好奇想了解更多关于 Anthony 的工作和项目吗?在媒体、 LinkedIn 、 Twitter 上关注他。

需要技术作家?将您的请求发送到https://amigo CCI . io

原文:https://towardsdatascience.com/feature-engineering-for-time-series-data-f0cb1c1265d3

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第29张

图为唐纳德·吴在 Unsplash

在许多商业数据科学问题中,具有时间序列特征的数据(例如,交易、传感器读数等)。)必须汇总到个人(例如,客户、设备等)。)水平。在现代机器学习环境中这样做可能会带来麻烦,因为传统的训练测试和交叉验证分割将会失败。这是因为在训练集和测试集之间随机拆分观察结果几乎总是会在这两个集之间拆分相关的(因此也是相关的)观察结果。更有问题的是,观察将被分割,以便一些训练观察可以在测试观察之后进行。换句话说,模型将学习从未来预测过去。这通常会导致模型在投入生产时失败。

有许多方法可以处理这个问题,我在这里讨论了我的首选方法。一种常用的方法是对每个人进行一次观察。这可以通过为每个人随机选择一个观察值或选择一个日期并仅使用该日期的观察值来实现。

我们将集中精力为给定日期的每个观察创建一个单独的记录。在本例中,我们将使用天气数据并对其进行汇总,以显示多个时间段内县级的平均高温。在熊猫身上做到这一点可能很有挑战性,但我们将展示在 Rasgo 的现代数据堆栈上做到这一点是多么容易。

给定包含县代码 FIPS 、日期日期和某个县在日期高温rollinggroupby的数据帧df,可以使用它们来创建所有日期的滚动平均值。在这种情况下,将创建一周、两周和四周的滚动平均值。

首先,应该创建滚动窗口

df['HIGH_TEMP_AVG_7D'] = df.sort_values(
                              by=['FIPS', 
                                 'DATE']).set_index(
                                 'DATE').groupby(
                                 'FIPS')[
                                 "HIGH_TEMP"].rolling('7D',             
                                 closed='both').mean()
df['HIGH_TEMP_AVG_14D'] = df.sort_values(
                              by=['FIPS', 
                                 'DATE']).set_index(
                                 'DATE').groupby(
                                 'FIPS')[
                                 "HIGH_TEMP"].rolling('14D',             
                                 closed='both').mean()
df['HIGH_TEMP_AVG_28D'] = df.sort_values(
                              by=['FIPS', 
                                 'DATE']).set_index(
                                 'DATE').groupby(
                                 'FIPS')[
                                 "HIGH_TEMP"].rolling('28D',             
                                 closed='both').mean()

可以重置索引以将县代码和日期返回到数据帧中的简单列。

df.reset_index(inplace=True)

这种方法有几个问题。首先,如果数据量很大,将数据下载到工作站并进行处理会非常耗时。虽然这可以通过仅下载所讨论的日期所需的数据来加速,但是仍然要对数据中的所有日期执行额外的计算。更重要的是,生产工作流只需要聚合到当前日期,并且应该生成聚合。

在现代数据栈上,开源包 RasgoQL 以几种方式解决了这两个问题。首先,处理保存在云数据仓库中,因此没有数据被移动到工作站。其次,RasgoQL 转换timeseries_agg利用数据仓库的能力处理比工作站上可能处理的数据量大得多的数据。

首先,获取对数据仓库中保存天气数据的表的引用。

dataset = rql.dataset('WEATHER_TABLE_NAME')

每天的滚动平均值可以通过调用转换来生成。

tsagg = dataset.timeseries_agg(aggregations={
                                'DAILY_HIGH_TEMP': ['AVG']
                               },
                               group_by=['FIPS'],
                               date='DATE'
                               offsets=[7, 14, 28],
                               date_part='day')

这些数据可以通过调用tsagg上的to_df来下载,以获得熊猫数据帧进行进一步处理。

tsagg_df = tsagg.to_df()

或者,可以将这些数据发布回云数据仓库,以创建一个视图,其他人可以在 RasgoQL 中使用该视图,也可以通过 SQL 直接从数据仓库中使用该视图。

tsagg.save(table_name="ROLLING_WEATHER_SNAPSHOT")

在现代数据栈上使用开源 Python 包 RasgoQL 的转换使得创建这种滚动窗口比在 pandas 中创建要简单得多。该包创建一个在数据库中执行的 SQL 调用,并且可以将结果保存回数据库,以便将来在现有项目或需要相同数据的其他项目中引用。通过使用 SQL,处理的数据量可能会大得多。最后,使用 pandas,使用 aggregate 函数可以允许在多个列上同时进行多个聚合。除了在每个步骤中只能考虑一个时间窗口(例如七天或十四天)。这意味着要创建 7 天、14 天和 28 天的平均值,需要三种不同的 Python 语句。在 RasgoQL 中,一个 SQL 调用可以同时生成所有三个。

如果你想查看 RasgoQL,文档可以在这里找到,在这里找到库。

原文:https://towardsdatascience.com/feature-engineering-unraveling-the-mystery-768e15e72dac

理论上或实际上,我们都在机器学习和人工智能领域遇到过“特征工程”这个术语。特征工程被认为是应用机器学习成功的关键。“想出新功能既困难又耗时,而且需要专业知识。 应用机器学习 基本上就是特色工程”–(吴恩达)。在本文中,您将发现什么是特性工程,它解决什么问题,以及为什么它真的很重要。

你有一些数据,有了这些数据,你就训练了一个模型。您看到了结果,并意识到需要做更多的工作来提高模型性能。您可以尝试收集更多数据,也可以花时间调整模型。然而,您并不总是有收集更多数据的奢侈,因此第三种方法是修改可用的特征以更好地捕捉隐藏的模式。特征工程帮助您从数据中获取最大价值,并从算法中获得最佳结果。您获得的结果可能是数据集中的要素和您选择的算法的直接结果。您选择的功能也会影响算法的选择。

更好的特性意味着更简单的算法和更好的结果。

为了理解这种说法,我们来看一个简单的例子。假设你有一个变量 x1,在 x 轴上有两个类,蓝色和橙色。

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第30张

作者创造的形象

你能使用逻辑回归来区分类别吗?一条线或一个平面无法将这两个类别分开,因此这里不能使用逻辑回归。您可能需要创建一个非线性决策边界来分隔这两个类。可能的选项如下所示。

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第31张

作者创造的形象

现在,使用特征工程,如果您创建一个只是原始值的平方的新特征,您的新特征空间将如下所示:

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第32张

作者创造的形象

给定 X1 中的一个值,其在 X2 的变换值就是该数的平方。-4 变成 16,-3 变成 9,2 的平方是 4,等等。穿过转换后的数据点绘制的线现在是一个超平面,,它可以将两个类分开。最后,我们可以对这些新数据进行逻辑回归。

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第33张

作者创造的形象

因此,在更高的维度中,特征工程可以帮助你从使用深度神经网络到仅使用逻辑回归模型。这样做的好处不仅是改善了结果,而且产出可以解释和说明。

特征工程是一门艺术。数据是非线性的,每次都不同,对特征工程的掌握来自实践。不能简单地通过基本算术运算生成新要素。例如,如果您有像“重量”这样的特征,您不能简单地平方这些值来生成新的特征“重量平方”。新功能“重量平方”必须有一些商业意义。然而,如果你有体重和身高等特征,你可以创建一个新的特征身体质量指数,如果这有助于你的研究。

感谢您的阅读。如果您还有其他问题,请通过 LinkedIn 联系

https://swapnilin.github.io/

原文:https://towardsdatascience.com/feature-engineering-with-image-data-14fe4fcd4353

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第34张

(来源: flaticon )

有了特征工程,我们马上会想到表格数据。然而,我们也可以获得图像数据的特征。目标是提取图像中最重要的部分。这样做将更容易找到我们的数据和目标变量之间的映射。

这意味着您可以使用更少的数据和训练更小的模型。较小的模型减少了进行预测所需的时间。这在边缘设备上部署时特别有用。一个额外的好处是,您可以更加确定您的模型使用什么来进行这些预测。

我们将介绍使用 Python 进行影像要素工程的一些方法:

  • 种植
  • 灰色鳞片
  • 选择 RGB 通道
  • 强度阈值
  • 边缘检测
  • 滤色器(即提取给定颜色范围内的像素)

为了让事情变得有趣,我们将为自动驾驶汽车做这件事。如下图所示,我们想用一条赛道的图片来训练一个模型。然后,该模型将被用于预测指导汽车。最后,我们将讨论来自图像数据的特征工程的局限性。

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第35张

装有摄像头传感器自动驾驶汽车(来源:作者)

在我们深入研究之前,有必要讨论一下图像增强。这种方法与特征工程有相似的目标。然而,它以不同的方式实现它们。

数据扩充是指我们使用代码系统地或随机地改变数据。对于图像,这包括翻转、调整颜色和添加随机噪声等方法。这些方法允许我们人为地引入噪声并增加数据集的大小。如果你想了解更多关于图像增强的细节,我推荐这篇文章:

在生产中,模型需要在不同的条件下运行。这些条件由照明、摄像机角度、房间颜色或背景中的物体等变量决定。

数据扩充的目标是创建一个对这些条件的变化具有鲁棒性的模型。它通过添加模拟真实世界条件的噪声来做到这一点。例如,改变图像的亮度类似于在一天的不同时间收集数据。

通过增加数据集的大小,增强还允许我们训练更复杂的架构。换句话说,它有助于模型参数收敛。

特征工程的目标是相似的。我们想创建一个更强大的模型。除了现在,我们去除任何对准确预测不必要的噪音。换句话说,我们去掉了随不同条件而变化的变量。

通过提取图像中最重要的方面,我们也简化了问题。这允许我们依赖更简单的模型架构。这意味着我们可以使用更小的数据集来找到输入和目标之间的映射。

一个重要的区别是在生产中如何处理这些方法。您的模型不会对增强图像进行预测。然而,通过特征工程,您的模型将需要对其接受训练的相同特征进行预测。这意味着你必须能够在生产中进行特征工程。

好了,记住所有这些,让我们继续特征工程。我们会检查代码,你也可以在 GitHub 上找到这个项目。

首先,我们将使用下面的导入。我们有一些标准包装(第 2-3 行)。 Glob 用于处理文件路径(第 5 行)。我们还有一些用来处理图像的包(第 7-8 行)。

#Imports 
import numpy as np
import matplotlib.pyplot as plt

import glob

from PIL import Image
import cv2

如前所述,我们将使用用于驱动自动汽车的图像。你可以在 Kaggle 上找到这些例子。我们用下面的代码加载其中一个图像。我们首先加载所有图像的文件路径(第 2–3 行)。然后加载(第 8 行)并显示(第 9 行)第一个路径的图像。你可以在图 1 中看到这个图像。

#Load image paths
read_path = "../../data/direction/"
img_paths = glob.glob(read_path + "*.jpg")

fig = plt.figure(figsize=(10,10))

#Display image
img = Image.open(img_paths[0])
plt.imshow(img) 

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第36张

图 1:轨迹图像示例(来源:作者)

一个简单的方法是裁剪图像以移除不想要的外部区域。目的是仅移除预测不需要的图像部分。对于我们的自动汽车,我们可以从背景中去除像素。

为此,我们加载一个图像(第 2 行)。然后,我们将这个图像转换成一个数组(第 5 行)。该阵列的尺寸为 224 x 224 x 3。图像的高度和宽度是 224 像素,每个像素有一个 R G B 通道。为了裁剪图像,我们只选择 y 轴上从位置 25 开始的像素(第 8 行)。你可以在图 2 中看到结果。

#Load image
img = Image.open(img_paths[609])

#Covert to array
img = np.array(img)

#Simple crop
crop_img = img[25:,]

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第37张

图 2:裁剪图像(来源:作者)

你可能想保持长宽比。在这种情况下,您可以通过将不需要的像素变黑(第 3 行)来获得类似的结果。

#Change pixels to black
crop_img = np.array(img)
crop_img[:25,] = [0,0,0]

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第38张

图 3:通过改变像素颜色进行裁剪(来源:作者)

通过裁剪,我们删除了不必要的像素。我们还可以避免模型过度拟合训练数据。例如,背景中的椅子可能出现在所有左转处。因此,模型可以将这些与左转预测相关联。

看着上面的图像,你可能会忍不住进一步裁剪它。也就是说,您可以在不移除任何轨道的情况下裁剪图像的左侧。然而,在图 4 中,你可以看到,对于其他图像,我们将移除轨道的重要部分。

#Additional cropping 
crop_img = np.array(img)
crop_img[:25,] = [0,0,0]
crop_img[:,:40] = [0,0,0]

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第39张

图 4:糟糕的裁剪示例(来源:作者)

这又回到了特性工程需要在产品中完成的问题上。这里你不知道什么图像将在什么时间显示给模型。这意味着相同的裁剪功能将需要应用于所有图像。你需要确保它永远不会删除图像的重要部分。

对于某些应用,图像的颜色并不重要。在这种情况下,我们可以对图像进行灰度处理。我们用 OpenCV 中的 cvtColor 函数来做这件事(第 2 行)。

#Gray scale
gray_img = cv2.cvtColor(img,cv2.COLOR_RGB2GRAY)

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第40张

图 5:图像灰度(来源:作者)

灰度是通过捕捉图像的颜色强度来实现的。这是通过对 RGB 通道进行加权平均来实现的。具体来说,上面的函数使用以下公式:

Y= 0.299 *R+0.587 *G+0.114 *B

我们可以通过查看每个图像的输入值的数量来理解这样做的好处。如果我们使用所有 RGB 通道,它将由 150,528 个值组成(2242243)。对于灰度图像,我们现在只有 50,176 个值(224*224)。更简单的输入意味着我们需要更少的数据和更简单的模型。

其中一个渠道可能更重要。我们可以只使用那个通道,而不是灰度。下面,我们选择 R(线 6)、G(线 7)和 B(线 8)通道。每个结果数组的大小都是 224 x 224。您可以在图 6 中看到各自的图像。

#Load image
img = Image.open(img_paths[700])
img = np.array(img)

#Get rgb channels
r_img = img[:, :, 0]
g_img = img[:, :, 1]
b_img = img[:, :, 2]

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第41张

图 6: RGB 通道(来源:作者)

您也可以使用通道 _ 过滤器功能。这里,通道参数©将根据您想要的通道取值为 0、1 或 2。请记住,有些包会以不同的顺序加载频道。我们使用的是 RGB 的 PIL。但是,如果用 cv2.imread()加载图像,通道将按照 BGR 顺序排列。

def channel_filter(img,c=0):
    """Returns given channel from image pixels"""
    img = np.array(img)
    c_img = img[:, :, c]

    return c_img

通过这些转换,您需要考虑是否从图像中删除了重要信息。对于我们的应用程序,轨道是橙色的。换句话说,轨道的颜色有助于将其与图像的其他部分区分开来。

使用灰度时,每个像素的值将在 0 到 255 之间。我们可以通过将输入转换成二进制值来进一步简化输入。如果灰度值高于截止值,像素值为 1,否则为 0。我们称这个截止点为强度阈值。

下面的函数用于应用该阈值。我们首先对图像进行灰度处理(第 5 行)。如果像素高于截止值,则其值为 1000(第 8 行)。如果我们将像素设置为 1,它将低于截止值。换句话说,在下一步(第 9 行)中,所有像素都将被设置为 0。最后,我们缩放所有像素,使它们取值为 0 或 1(第 11 行)。

def threshold(img,cutoff=80):
    """Apply intesity thresholding"""

    img = np.array(img)
    img = cv2.cvtColor(img,cv2.COLOR_RGB2GRAY)

    #Apply cutoff
    img[img>cutoff] = 1000 #black
    img[img<=cutoff] = 0 #white

    img = img/1000

    return img

自动汽车项目的一部分是避开障碍物。这些是涂成黑色的罐子。在图 7 中,您可以看到如何应用强度阈值函数将 tin 从图像的其余部分中分离出来。这是唯一可能的,因为锡是黑色的。换句话说,它的强度大于图像的其余部分。

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第42张

图 7:具有强度阈值的特征工程(来源:作者)

截止值可以被视为一个超参数。参见图 7,截止值越大,意味着我们包含的背景噪声越少。不利的一面是我们捕获的罐头更少了。

如果我们想分离轨迹,我们可以使用 canny 边缘检测。这是一种用于检测图像边缘的多阶段算法。如果你想了解它是如何工作的,我建议阅读索菲安·萨希尔关于精明边缘检测的文章。

我们将该算法应用于 cv2。Canny ()函数。阈值 1阈值 2 参数用于迟滞程序。这是边缘检测算法的最后一步,用于确定哪些线实际上是边缘。

#Apply canny edge detection
edge_img = cv2.Canny(img,threshold1 = 50, threshold2 = 80)

你可以在图 8 中看到一些例子。像强度阈值处理一样,我们只剩下一个二值图——白色代表边缘,黑色代表其他。希望这个轨迹现在更容易与图像的其他部分区分开来。但是,您可以看到背景中的边缘也被检测到。

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第43张

图 8: canny 边缘检测(来源:作者)

我们可能会有更好的运气,通过使用像素颜色来隔离轨迹。我们使用下面的 pixel_filter 函数来实现。使用 cv2.inRange ()我们将图像转换成二进制图(第 10 行)。这个函数检查一个像素是否落在下面(第 5 行)和上面(第 6 行)列表给定的范围内。具体来说,每个 RGB 通道必须在各自的范围内(例如 134-t ≤ R ≤ 194+t)。

def pixel_filter(img, t=0):

    """Filter pixels within range"""

    lower = [134-t,84-t,55-t]
    upper = [192+t,121+t,101+t]

    img = np.array(img)
    orange_thresh = 255 - cv2.inRange(img, np.array(lower), np.array(upper))

    return orange_thresh

简单地说,该函数确定像素颜色是否足够接近轨道的橙色。你可以在图 9 中看到结果。测试参数引入了一些灵活性。使用较高的值,我们可以捕捉更多的轨迹,但保留更多的噪声。这是因为背景中的像素将落在该范围内。

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第44张

图 9:过滤橙色像素(来源:作者)

你可能想知道我们从哪里得到下限和上限。这就是我们如何知道通道将落在[134,84,55]和[192,121,101]之间?嗯,我们使用 Python 创建的颜色选择器。我们在下面的文章中概述了这是如何创建的。

图 10 中,您可以看到拾取器正在工作。我们从多个图像中选择像素,并尝试在轨道上的不同位置选择它们。这是为了在不同条件下获得全范围的像素值。

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第45张

图 10:从轨道上挑选颜色(来源:作者)

我们总共选择了 60 种颜色。这些你都可以在图 11 (带加成视错觉)中看到。所有这些颜色的 RGB 通道都存储在一个名为“颜色”的列表中。

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第46张

图 11:用拾色器选择的 60 个轨迹像素

最后,我们取每个 RGB 通道的最小值和最大值。这给出了下限和上限。

lower = [min(x[0] for x in colours),
              min(x[1] for x in colours),
              min(x[2] for x in colours)]

upper = [max(x[0] for x in colours),
              max(x[1] for x in colours),
              max(x[2] for x in colours)]

经过这一切,你可能不相信。深度学习的一个主要好处是,它可以识别复杂的模式,而不需要特征工程。这是一个很好的观点。

特征工程需要批判性思维。你需要弄清楚图像的哪些方面是重要的。然后,您需要编写代码来提取这些方面。对于某些应用程序来说,完成所有这些所需的时间毫无意义。

此外,对于一些方法,我们已经看到,我们不能消除所有的噪音。例如,强度阈值中的黑色背景。与直觉相反的是,残留的噪音现在可能更难区分什么是重要的。也就是说,剩余的噪声和对象像素具有相同的值(1)。

真的,当处理相对简单的计算机视觉问题时,好处就来了。我们的轨迹从不改变,物体的颜色也总是一样。对于更复杂的问题,你将需要更多的数据。或者,您可以在较小的数据集上微调预训练模型。

我希望你喜欢这篇文章!你可以成为我的 推荐会员 😃 来支持我

https://conorosullyds.medium.com/membership

| 推特 | YouTube | 时事通讯 —注册免费参加 Python SHAP 课程

所有图片都是我自己的或从www.flaticon.com获得。在后者的情况下,我拥有他们的保费计划中定义的“完全许可”。

JatRacer 图片 (CC0:公共领域)https://www.kaggle.com/datasets/conorsully1/jatracer-images

OpenCV,颜色转换https://docs . OpenCV . org/3.4/de/d25/imgproc _ Color _ conversions . html

原文:https://towardsdatascience.com/feature-extraction-with-bert-for-text-classification-533dde44dc2f

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第47张

照片由西格蒙德在 Unsplash 拍摄

让我们从定义这篇实践文章的目的开始。我们希望建立一个模型,将一个或多个文档作为输入,并设法根据它们的内容对它们进行分类。
一些类别例如:政治、旅游、体育等。
为了做到这一点,我们想使用一个预训练模型,如 BERT。

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第48张

作者图片

BERT 是一种基于 Transformer 编码器的语言模型。如果你对变形金刚不熟悉,我推荐你阅读这篇惊人的文章。

伯特简单地说:

  • 它将一个或多个句子的嵌入标记作为输入。
  • 第一个令牌始终是一个名为**【CLS】**的特殊令牌。
  • 句子之间由另一个叫做**【SEP】**的特殊记号分隔。
  • 对于每个令牌,BERT 输出一个称为隐藏状态的嵌入。
  • 伯特接受了掩蔽语言模型下一句预测任务的训练。

屏蔽语言模型(MLM) 中,一个输入单词(或标记)被屏蔽,伯特必须试图找出被屏蔽的单词是什么。对于下一个句子预测(NSP) 任务,输入给 BERT 两个句子,他必须弄清楚第二个句子是否在语义上跟随第一个句子。

对于像我们这样的分类问题,我们只对与初始标记【CLS】相关联的隐藏状态感兴趣,不知何故比其他的更好地捕捉了整个句子的语义。因此,我们可以使用这种嵌入作为分类器的输入,我们在它的基础上构建分类器。

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第49张

作者图片

从上面的图片中,你可以看到我们将使用一个叫做 DistilBERT 的较轻版本的 BERT。这个经过提炼的模型比原来的小了 40%,但是在各种 NLP 任务上仍然保持了大约 97%的性能。
你可以注意到的另一件事是,伯特的输入不是原始单词,而是标记。简单地说,BERT 关联了一个预处理文本的记号化器,以便它对模型有吸引力。单词通常被分成子词,此外还会添加特殊的标记**【CLS】来指示句子的开始,【SEP】来分隔多个句子,以及【PAD】**来使每个句子具有相同数量的标记。

如果您想了解更多关于 Bert 或他的 wordpartickizer 的信息,请查看以下资源:

  • https://jalammar.github.io/illustrated-bert/
  • https://huggingface.co/blog/bert-101
  • https://towards data science . com/word piece-sub word-based-token ization-algorithm-1 FBD 14394 ed 7
  • https://huggingface.co/docs/transformers/tokenizer_summary

我们要用的数据集叫做 BBC 全文文档分类 ,可以在 Kaggle 上公开获取。

该数据集包含 2225 条记录,总共包含 5 个类别。我们想要确定的五个类别是体育、商业、政治、科技和娱乐。

直接从 colab 下载 kaggle 数据集。(记得上传您的个人密钥)

我不会详细介绍如何读取这些数据并将其转换成 dataframe,但我假设您可以创建一个包含两列的 data frame:short _ descriptioncategory。

数据集的标签有:政治、体育等……
我们需要通过简单地使用标签编码器将这些标签转换成数字

为每个文本生成一个嵌入向量,它可以用作我们最终分类器的输入。与每个文本相关联的矢量嵌入只是 Bert 为[CLS]令牌输出的隐藏状态。

先从 HuggingFace 导入模型和分词器开始。

现在我们必须对文本进行标记。记住定义填充符*,这样每个标记化的句子将具有相同的长度,并且 截断 因此如果句子太长,它将被截断。最后一个参数是返回 PyTorch 张量。*

对文本进行标记化的结果将是一个字典,其中包含以数字表示的标记input _ id,以及告诉我们该标记是否为[PAD]的 attention_mask

通过运行模型获得文本([CLS])隐藏状态。

至此,你可以使用你最喜欢的分类器,给它输入隐藏状态,并让它预测标签。在这种情况下,我将使用随机森林。

这个分类器的性能不会很好,因为我们使用了很少的数据,并且没有在分类器上做很多工作。但是出于好奇,我建议你将它与一个随机预测标签的虚拟分类器进行比较。

在这篇动手实践文章中,我们看到了如何利用预训练模型的功能在很短的时间内创建一个简单的分类器。请记住,我们训练的只是最终的分类器,即随机森林。
另一方面,Bert 只在推理中用于生成嵌入,以某种方式捕捉文本的主要特征,这就是为什么我们说我们使用了特征提取方法。但是我们能训练 Bert 自己教他如何在我们的具体案例中创建更好的文本嵌入吗?当然可以!在下一篇文章中,我将向你展示如何微调(蒸馏)伯特!

马赛洛·波利蒂

Linkedin , Twitter , CV

原文:https://towardsdatascience.com/feature-importance-in-decision-trees-e9450120b445

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第50张

约书亚·戈尔德在 Unsplash 上拍摄的照片

这篇文章的目的是让读者熟悉如何在决策树中计算特征的重要性。就我个人而言,我没有找到对这个概念的深入解释,因此本文诞生了。

本文中使用的所有代码都是公开的,可以通过以下途径找到:

【https://github.com/Eligijus112/gradient-boosting

在深入研究特性重要性计算之前,我强烈建议您复习一下什么是树,以及我们如何使用这些文章将它们组合成随机森林的知识:

我们将使用决策树模型,使用各种回归变量( X )来创建加利福尼亚州中值房价( Y )之间的关系。可以使用 scikit-learn 包加载数据集:

加载加州住房数据集;作者代码

我们将在模型中使用的特性 X 是:

  • MedInc —过去 12 个月的家庭收入中位数(十万)

  • 房龄 —房龄(年)

  • 平均房间数——每个住所的平均房间数

  • AveBedrms —每个住宅的平均卧室数量

*ave occupation——平均家庭成员数

响应变量 Y 是加州各区的中值房价,以几十万美元表示。

数据的形状如下:

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第51张

数据的形状;按作者分类的表格

快速浏览特征变量:

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第52张

X 变量的头;按作者分类的表格

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第53张

特征的描述性统计;按作者分类的表格

Y 变量的分布:

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第54张

响应变量的分布;按作者分类的图表

为了匿名化数据,数据中有一个 50 万美元的收入上限:超过这个上限的仍被标记为 50 万美元的收入。这是为了确保没有人可以识别具体的家庭,因为早在 1997 年没有多少家庭是如此昂贵。

我们将数据分为训练集和测试集,拟合回归树模型,并推断训练集和测试集的结果。

拟合回归树;作者代码

打印输出如下:

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第55张

准确性结果;作者照片

长成的树不会过度生长。这篇文章是关于特征的推断,所以我们不会尽力减少错误,而是试图推断哪些特征是最有影响的。

训练集上的成年树:

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第56张

全回归树;按作者分类的图表

决策树由**个节点、**个节点组成,每个节点由一个分割规则链接。分割规则涉及一个要素和它应该分割的值。

术语“分割”是指如果满足分割规则,数据集的观测值将位于节点的左侧。如果不满足规则,则观察向右进行。

从 1 到 15 枚举每个节点。

让我们检查第一个节点和其中的信息。所有节点的逻辑都是一样的。

MedInc ≤ 5.029 —节点的拆分规则。如果一个观察的 MedInc 值小于或等于 5.029,那么我们向左遍历树(转到节点 2),否则,我们转到右边的节点(节点 3)。

squared_error —用作分割标准的统计数据。squared_error 的计算公式如下:

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第57张

均方误差公式

在第一个节点中,统计值等于 1.335。

样本 —节点中观察值的数量。因为这是根节点,所以 15480 对应于整个训练数据集。

—节点的预测值。换句话说,如果观察路径在此节点停止,则该节点的预测值将为 2.074。

让我们创建一个保存所有节点中所有观察值的字典:

n_entries = {
“node 1”: 15480,
“node 2”: 12163,
“node 3”: 3317,
“node 4”: 5869,
“node 5”: 6294,
“node 6”: 2317,
“node 7”: 1000,
“node 8”: 2454,
“node 9”: 3415,
“node 10”: 1372,
“node 11”: 4922,
“node 12”: 958,
“node 13”: 1359,
“node 14”: 423,
“node 15”: 577
}

在计算特征重要性时,使用的度量之一是观察值落入某个节点的概率。概率是为决策树中的每个节点计算的,计算方法是将节点中的样本数除以数据集中的观察总数(在我们的例子中是 15480)。

让我们将字典表示为 n_entries_weighted :

n_entries_weighted = {
'node 1': 1.0,  
'node 2': 0.786,  
'node 3': 0.214,  
'node 4': 0.379,  
'node 5': 0.407,  
'node 6': 0.15,  
'node 7': 0.065,  
'node 8': 0.159,  
'node 9': 0.221,  
'node 10': 0.089,  
'node 11': 0.318,  
'node 12': 0.062,  
'node 13': 0.088,  
'node 14': 0.027,  
'node 15': 0.037
}

为了使特性重要性的定义具有数学上的严格性,让我们在本文中使用数学符号。

让我们将每个节点表示为

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第58张

节点符号

每个节点,直到最终深度,都有一个左子节点和一个右子节点。让我们将它们表示为:

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第59张

左右子符号

每个节点都有特定的属性。让我们将上一节中计算的重量表示为:

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第60张

节点权重

让我们将均方误差(MSE)统计量表示为:

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第61张

节点均方误差统计

有子节点的节点的一个非常重要的属性是所谓的节点重要性:

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第62张

节点计算的重要性

上述等式的直觉是,如果子节点中的 MSE 较小,则该节点尤其是其分裂规则特征的重要性较大。

让我们用每个节点的 MSE 统计数据创建一个字典:

i_sq = {
“node 1”: 1.335,
“node 2”: 0.832,
“node 3”: 1.214,
“node 4”: 0.546,
“node 5”: 0.834,
“node 6”: 0.893,
“node 7”: 0.776,
“node 8”: 0.648,
“node 9”: 0.385,
“node 10”: 1.287,
“node 11”: 0.516,
“node 12”: 0.989,
“node 13”: 0.536,
“node 14”: 0.773,
“node 15”: 0.432
}

作者 Trevor Hastie、Robert Tibshirani 和 Jerome Friedman 在他们的巨著The Elements of Statistical Learning:Data Mining,Inference,and Prediction 中用以下等式定义了特征重要性计算:

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第63张

布雷曼特征重要性方程

在哪里

t——是整个决策树

l —有问题的特征

J —决策树中内部节点的数量

I——用于分割的度量的减少

II —指示器功能

v(t)-用于分割节点的特征 t 用于分割节点

这个等式背后的直觉是,对树中所有特征的度量的所有减少进行求和。

Scikit-learn 使用前面提出的节点重要性公式。主要区别在于,在 scikit-learn 中,引入了节点权重,即观察值落入树中的概率。

让我们放大一点,进一步检查节点 1 到 3。

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第64张

前三个节点;按作者分类的图表

节点重要性(以及要素重要性)的计算一次只考虑一个节点。为节点号 1 解释的后续逻辑适用于以下级别的所有节点。

只有具有分裂规则的节点才有助于特征重要性的计算。

第二个节点是节点 1 的左子节点,第三个节点是右子节点。

特征重要性背后的直觉始于分裂标准中的总体减少的想法。换句话说,我们想要测量给定的特征及其分裂值(尽管该值本身在任何地方都不使用)如何减少系统中的均方误差。上一节中定义的节点重要性等式反映了这种影响。

如果我们在根节点中使用 MedInc,将有 12163 个观察值到达第二个节点,3317 个观察值到达右节点。这转化为左节点的权重为 0.786 (12163/15480),右节点的权重为 0.214 (3317/15480)。左侧节点中的均方误差等于 0.892,右侧节点中的均方误差为 1.214。

我们需要计算节点重要性:

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第65张med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第66张med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第67张

现在我们可以将节点重要性保存到字典中。字典键是在节点的分裂标准中使用的特征。这些值是节点的重要性。

{
  "**MedInc**": 0.421252,
  "**HouseAge**": 0,
  "**AveRooms**": 0,
  "**AveBedrms**": 0,
  "**AveOccup**": 0}

上述计算过程需要对所有具有分裂规则的节点重复进行。

让我们再做一些节点计算,以完全掌握算法:

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第68张

更多的平方误差减少;按作者分类的图表

如果我们在节点 2 中使用 MedInc 特性,误差平方为:

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第69张

第二节点重要性

特征重要性字典现在变成了:

{
  "**MedInc**": 0.421 + 0.10758
  "**HouseAge**": 0,
  "**AveRooms**": 0,
  "**AveBedrms**": 0,
  "**AveOccup**": 0}

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第70张

要拆分的新功能;按作者分类的图表

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第71张

节点 4 的重要性

{
  "**MedInc**": 0.558,
  "**HouseAge**": 0,
  "**AveRooms**": 0.018817,
  "**AveBedrms**": 0,
  "**AveOccup**": 0}

我们不能更进一步,因为节点 8 和 9 没有分裂规则,因此不会进一步减少均方误差统计。

让我们对上面几节中给出的实现进行编码。

用于重要性计算的数据

现在让我们定义一个计算节点重要性的函数。

节点重要性计算函数

将所有这些放在一起:

计算节点的代码段

上述代码片段中的内容如下:

Node importance: {
‘node 1’: 0.421, 
‘node 2’: 0.108, 
‘node 3’: 0.076, 
‘node 4’: 0.019, 
‘node 5’: 0.061, 
‘node 6’: 0.025, 
‘node 7’: 0.013
} Feature importance before normalization: {
‘MedInc’: 0.618, 
‘AveRooms’: 0.019, 
‘AveOccup’: 0.086, 
‘HouseAge’: 0, 
‘AveBedrms’: 0
} **Feature importance after normalization: {
‘MedInc’: 0.855, 
‘AveRooms’: 0.026, 
‘AveOccup’: 0.119, 
‘HouseAge’: 0.0, 
‘AveBedrms’: 0.0
}**

归一化后的最终特征字典是具有最终特征重要性的字典。根据字典,到目前为止最重要的特征是 MedInc,其次是 ave occupation 和 AveRooms。

特征 HouseAge 和 AveBedrms 没有在任何分割规则中使用,因此它们的重要性为 0。

让我们将我们的计算与功能重要性计算的 scikit-learn 实现进行比较。

Sklearn 特性重要性的实现

上面写着:

Feature importance by sklearn: 
{
‘MedInc’: 0.854, 
‘HouseAge’: 0.0, 
‘AveRooms’: 0.027, 
‘AveBedrms’: 0.0, 
‘AveOccup’: 0.12
}

与我们的计算相比:

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第72张

特征重要性比较

差异很小,但这是由于舍入误差。

在本文中,我非常详细地演示了决策树的特性重要性计算。一个非常相似的逻辑适用于分类中使用的决策树。唯一的区别是度量——我们不使用平方误差,而是使用 GINI 杂质度量(或其他分类评估度量)。所有关于节点重要性的计算保持不变。

我希望在读完所有这些之后,你会对如何解释和计算特性的重要性有一个更清晰的了解。

编码快乐!

[1]作者:佩斯,r .凯利和罗纳德·巴里
年份: 1997 年
书名:稀疏空间自回归
网址:**http://archive.ics.uci.edu/ml
期刊:统计与概率快报**

[2]作者:特雷弗·哈斯蒂、罗伯特·蒂布拉尼和杰罗姆·弗里德曼
年份: 2017
书名:统计学习的要素:数据挖掘、推断和预测
网址:
http://archive.ics.uci.edu/ml
页面:368–370****

原文:https://towardsdatascience.com/feature-importance-in-machine-learning-explained-443e35b1b284

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第73张

图片由约书亚·戈德从 Unsplash 拍摄

本文将重点介绍与各种方法相关的直觉和 Python 实现,以识别与机器学习模型相关的重要特性。以下是文章的结构。

目录

  • 机器学习中的特征重要性是什么?
  • 基于系数的特征重要性
  • 置换特征重要性
  • 树特征重要性
  • SHAP 特征重要性
  • 实现
    -需求
    -合成数据&生成模型
    -系数
    -排列
    -树
    • SHAP
  • 结束语
  • 资源

特征重要性是模型开发中不可或缺的组成部分。它突出显示了传递到模型中的哪些要素对生成预测的影响程度高于其他要素。识别重要特征的结果可以直接反馈到模型测试和模型可解释性中。有多种方法可以计算特征的重要性,例如:

  1. 基于系数的特征重要性
  2. 基于排列的特征重要性
  3. 树特征重要性
  4. SHAP

请注意,并非所有计算特征重要性的方法都适用于所有类型的模型。这些方法主要适用于监督经典机器学习问题(如分类和回归)中的大多数模型。

基于系数的特征重要性可能是最容易理解的。直观上,基于系数的特征重要性指的是将预测生成为输入值的加权和的模型。

并非所有模型都可以计算特征的重要性。这适用于线性模型,如线性回归、逻辑回归、岭回归、支持向量机(仅当核是线性时)。这些类型的模型的主要共同点是它们识别与一组系数相关联的权重,我们可以将其解释为特征重要性。您可以从高到低对与这些系数相关的特征进行排序,最高的是最重要的特征,最低的是最不重要的特征。

基于置换的特征重要性被定义为当单个特征值被随机打乱时模型得分的减少。该过程打破了特征和目标之间的关系,因此模型分数的下降指示了模型对特征的依赖程度。[2]

-http://sci kit-learn . org/stable/modules/permutation _ importance . html

置换特征重要性的结果可以是负的和正的。当置换分数对于某些特征为负时,它表明从混洗数据生成的预测碰巧比真实数据更准确。当模型认为特性应该具有重要性,但却没有时,就会发生这种情况。发生这种情况是因为随机机会导致从混洗数据生成的预测更加准确。这意味着这些特征有噪声。

sci-kit 中基于树的模型学习,如决策树、随机森林、梯度增强、ada 增强等。嵌入了它们自己的特性重要性。他们根据用于选择分裂点的标准(如基尼系数或熵)的减少来计算他们的重要性分数[1]。可以通过训练模型后可用的feature_importances_属性引用这些分数。

SHAP 是一个流行的研究论文,重点是模型的可解释性。SHAP 特征重要性是置换特征重要性的替代方法[3]。排列法和 SHAP 的区别在于,SHAP 着眼于特征属性的大小,而排列法着眼于模型性能的下降[3]。SHAP 图书馆内置了一系列的explainer类。它支持线性模型、内核、树、深度学习模型等的可解释性。

Python=3.9.12
pandas>=1.4.3
numpy>=1.23.2
shap>=0.41.0
matplotlib>=3.5.1
sklearn>=1.1.2

请注意,因为我们使用的是随机生成的数据,所以特性重要性的结果几乎没有意义。这只是为了展示如何通过代码为您正在处理的问题实现这些不同类型的特性重要性度量。下面的脚本将合成一个具有 5 个特征的随机数据集,并从中训练 2 个基于回归的模型。即梯度推进回归器和支持向量回归器。

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第74张

系数特征重要性。图片由作者提供。

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第75张

置换特征重要性。图片由作者提供。

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第76张

基于树的特征重要性。图片由作者提供。

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第77张

线性核 SVM 回归模型的 SHAP 特征重要性。图片由作者提供。

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第78张

SHAP 特征对梯度推进回归器的重要性。图片由作者提供。

SHAP 库中的汇总绘图功能允许您根据 SHAP 值直观地查看模型的最重要功能。第一个图显示了每个要素的影响分布,而第二个图是由 SHAP 值的 MAE(平均绝对值)生成的条形图。

基于对识别特征重要性的各种方法如何与模型的训练数据相关联的直观理解,以及所提供的相关代码,您应该能够为您正在处理的模型实现这一点,以查看哪些特征具有最高的影响。这对于模型测试和可解释性非常有用。

请在我的 GitHub 页面这里查看与本教程相关的资源库。

如果你想转型进入数据行业,并希望得到经验丰富的导师的指导和指引,那么你可能想看看最敏锐的头脑。Sharpest Minds 是一个导师平台,导师(他们是经验丰富的实践数据科学家、机器学习工程师、研究科学家、首席技术官等。)将有助于你的发展和学习在数据领域找到一份工作。在这里查看。

  • [1]https://machine learning mastery . com/calculate-feature-importance-with-python/
  • [2]http://sci kit-learn . org/stable/modules/permutation _ importance . html
  • [3]https://christophm . github . io/interpretable-ml-book/shap . html

如果你觉得这篇文章有用,这里有一些我写的其他文章,你可能也会觉得有用。

原文:https://towardsdatascience.com/feature-importance-to-predict-mushrooms-edibility-in-python-5aa133fea3f8

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第79张

照片由 Jannik Selz 在 Unsplash 上拍摄

T 本文旨在利用特征重要性来评估数据集中的所有列是否需要用于预测

秋天快到了。想象一下,你正在树林中散步,发现路边有一些蘑菇。将它们的一些特性输入到一个 ML 驱动的应用程序中不是很好吗?我个人不喜欢吃蘑菇,但我绝对喜欢食物,走了很长一段路后,我已经可以闻到面前有一道美味的“tagliolini ai funghi”。

蘑菇是真菌,是独立于植物和动物的独立王国的一部分。正如你可能想象的那样,在决定一个人是否可以食用之前,他们会给出无数的特征来评估。

您的徒步旅行团队正在离开,我们需要尽快做出决定。

哪个信息是舒适地评估蘑菇品种的可食用性的基础?

让我们找出答案

数据集可以在机器学习 UCI 知识库【1】中检索。它包括关于蘑菇蘑菇家族中 23 种蘑菇的假设信息。这些记录是假设的,因为根据蘑菇指南,它们是人工输入的。作者确定了 22 个独特的特征,不包括可食用或有毒的特征,其中一些是:

  1. cap-shape:钟形=b,锥形=c,凸形=x,扁平=f,圆球形=k,凹形=s
  2. cap-surface:纤维状=f,凹槽=g,鳞状=y,光滑=s
  3. cap-color:棕色=n,浅黄色=b,肉桂色=c,灰色=g,绿色=r,粉色=p,紫色=u,红色=e,白色=w,黄色=y
  4. bruises?:淤青=t,no=f
  5. odor:杏仁=a,茴香=l,杂酚油=c,鱼腥味=y,恶臭=f,霉味=m,无=n,刺鼻=p,辛辣=s
  6. gill-attachment:附着=a,下降=d,自由=f,缺口=n
  7. gill-spacing:近=c,挤=w,远=d
  8. gill-size:宽=b,窄=n
  9. gill-color:黑色=k,棕色=n,浅黄色=b,巧克力色=h,灰色=g,绿色=r,橙色=o,粉色=p,紫色=u,红色=e,白色=w,黄色=y
  10. stalk-shape:放大=e,缩小=t
  11. stalk-root:球根=b,球杆=c,杯子=u,等号=e,根茎=z,有根=r,缺失=?
  12. stalk-surface-above-ring:纤维状=f,鳞状=y,丝状=k,光滑=s
  13. stalk-color-above-ring:棕色=n,浅黄色=b,肉桂色=c,灰色=g,橙色=o,粉色=p,红色=e,白色=w,黄色=y
  14. spore-print-color:黑色=k,棕色=n,浅黄色=b,巧克力色=h,绿色=r,橙色=o,紫色=u,白色=w,黄色=y

您可以将一个要素标识为数据集中的多个列之一。计算特征重要性是指每个特征在训练一个模型后所拥有的分数。你会同意我的观点,即并不是所有的特征都是相等的,它们对输出预测有贡献。

我们可以看到与帕累托法则的相似之处,其中某件事情的 20% 负责结果的 80% ,或者称为 20:80 法则。在销售环境中,帕累托原则的一个例子是,你的 20%的客户创造了你 80%的销售额。在一个机器学习场景中,我们可以把这个原则翻译成“ 20% 的特征负责 80% 的正确预测”。特征重要性允许从业者识别出 20%

你是如何解读乐谱的?一个较高的分数表明一个特性对你的模型更有影响,而一个较低的分数表明信息对模型来说不那么重要。对于我们的项目,我们有 21 个特征,我们想计算每个特征的重要性分数,并且只选择几个[2]。

特征选择考虑的模型有两个:随机森林梯度提升。每一种都有自己的特点,我将简要解释一下。

随机决策森林属于集成学习算法的范畴。“森林这个名字来自于它“组成”的个体实体:决策树。在训练阶段,多个决策树从数据中学习,一个投票机制确保最常见的结果也是最终输出。该模型同时用于分类回归任务。

随机森林在有大量变量时表现出了显著的性能。鉴于需要调整的超参数很少,企业认为这是一个“黑箱”。很难解释为什么一个随机森林会做出某些预测。另一方面,该特征提供了适应性高精度,而不会陷入过度拟合的风险【3】。

梯度提升也是一种集成学习算法,可用于分类回归任务。类似于随机森林,梯度增强预测基于应用于决策树的投票机制。根本区别在于,这些决策树被定义为“或“”,这意味着一个模型具有高偏差低方差。换句话说,它利用了一致的预测(具有所有相似的结果),但是不准确(显示错误的结果)。集合的目标是减少偏差同时保持方差低,使模型输出更接近目标结果【4】。

你可以把它想象成一束指向镖靶的激光。起初,模型做出的所有预测都远离靶心,但它们都彼此接近,它们是一致的。梯度提升以减少误差为目标依次构建弱学习器,使目标越来越接近靶心,即最佳模型。与直觉相反,梯度推进仍然保留了很大的泛化能力,这使得它成为一个计算昂贵的但总体上很棒的学习模型。

与大多数数据科学项目一样,代码部署的第一部分侧重于数据探索可视化。一个好的早期测试,检查数据集是否平衡。在分类问题中,重要的是两个目标变量呈现相似的计数。探索性数据分析因此是项目的第一步。

  • 我们根据需要导入pandasmatplotlib
  • 我们将 csv 文件作为熊猫数据帧读取
  • category_dist统计可食用或有毒的记录数量
  • 此时,可以定义图表及其大小颜色字体大小,以及我们是否想要一个网格。
#Importing libraries
import matplotlib.pyplot as plt
import pandas as pd#Reading dataset
df = pd.read_csv('mushrooms.csv')#Counting values within each class
category_dist = df['class'].value_counts()#Defining chart
plt.figure(figsize=(8,6))
category_dist.plot(kind='bar', color = '#89b4a1')
plt.grid()
plt.xlabel("Edible/Poisonous", fontsize = 12)
plt.ylabel("Number of Measurements", fontsize = 12)
plt.title("Distribution of Measurements", fontsize = 15)
plt.grid(False)#Generating chart
plt.show()

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第80张

蘑菇可食用性的秋季主题分布——作者图表

对于蘑菇数据集,可食用物种的数量彼此之间只相差几百个。我们可以断定数据集是平衡的,我们可以继续进行项目的下一部分,标签编码。

处理分类变量可能是几个机器学习算法的问题。在预处理阶段,标签编码通过将标签转换成数字来解决问题,以便机器能够读取它们。

流程是如何运作的?让我们以 cap-color 特性为例,有十种可能性:

  • 棕色=n,
  • buff=b,
  • 肉桂=c,
  • 灰色=g,
  • 绿色=r,
  • 粉色=p,
  • 紫色=u,
  • 红色=e,
  • 白色=w,
  • 黄色=y

标签编码算法按照字母顺序对它们进行分类:b、c、e、g……然后给每个字母分配一个从 0 开始的数字。字母“b”对应于 0,“c”对应于 1,“e”对应于 2,依此类推。

多亏了sklearn,这个过程相当容易。从业者需要导入LabelEncoder包,创建一个名为labelencoder的对象,并编写一个 for 循环语句,该对象将每一列的记录转换成一个数字形式。

from sklearn.preprocessing import LabelEncoderlabelencoder=LabelEncoder()for col in df.columns:
    df[col] = labelencoder.fit_transform(df[col])

为了更直观地了解这一过程,下面的图表显示了每一类(可食用或有毒)蘑菇的颜色。你可以看到大多数棕色和灰色蘑菇是可以食用的,但是你应该远离黄色蘑菇。

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第81张

热编码前蘑菇种类的颜色和类别的秋季主题分布-作者图表

在我们对数据集进行标签编码后,你会注意到类和帽颜色特征都已经被转换成数字。食用的字母“e”现在对应于数字 0,而“p”对应于 1。关于帽子的颜色,所有的棕色蘑菇现在被归类为 4,因为它是按字母顺序排列的第 5 个字母。

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第82张

热编码后蘑菇种类按颜色和类别的秋季主题分布-作者图表

对于模型选择部分,我强烈推荐你看一下我之前的一篇文章中的,在这篇文章中,我解释了如何部署流水线并评估几个机器学习模型的性能。对于这个项目,我在将以下内容设置为输入和目标变量后应用了相同的管道:

#Defining input and target variablesx = df.drop('class', axis=1)
y = df['class']

我们的输入变量最初是数据集的所有 21 个特征。因此x 由除class之外的所有列组成。既然我们想预测一个蘑菇是否可以食用,那么目标变量就是 class,它包含了我们需要的信息。

我决定交叉验证 16 种不同的算法,以在评估特性的重要性之前识别出具有最高性能的算法**(yo-yo Eminem)。**

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第83张

模型选择过程后算法的准确性比较—作者提供的图表

特别地,四个以最小的方差显示出最高的准确度:决策树分类器(CART)随机森林(RF)AdaBoost 分类器 (ADA)梯度增强(XGB)

LR: 0.839369 (0.142382) 
LDA: 0.843812 (0.159062) 
KNN: 0.908047 (0.094523) 
CART: 0.991626 (0.015547) 
NB: 0.713839 (0.189206) 
SVM: 0.824590 (0.187337) 
SGC: 0.782230 (0.159755) 
Perc: 0.760104 (0.150632) 
NC: 0.698081 (0.167803) 
Ridge: 0.843319 (0.158079) 
NuSVC: 0.746827 (0.189874) 
BNB: 0.800220 (0.136547) 
RF: 0.997168 (0.003473) 
ADA: 0.994582 (0.009653) 
XGB: 0.998277 (0.003446) 
PAC: 0.850076 (0.106792)

值得一提的是,这样的高性能可能是过度适应的迹象,这个问题我们不打算在本文中讨论。不过,在未来的项目中,这将是一个很好的解释主题。现在,让我们考虑一下将被带到下一阶段的两个最好的模型:随机森林梯度提升**。**

在这个阶段,我们知道随机森林的表现已经很出色了,下一步就是评估的表现是否能在更少的信息下保持不变。这可以通过选择几个特征来完成,这些特征是进行预测的基础:

  • 首先,让我们导入所有我们需要的sklearn子包:train_test_splitclassification_reportRandomForestClassifierGradientBoostingClassifier
#Importing libraries
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from sklearn.ensemble import RandomForestClassifier,
GradientBoostingClassifier
  • 在运行单元之前,需要再次设置输入和目标变量,以避免任何问题
  • 我们可以通过分配 80% 训练数据和 20% 测试来分割数据集。我决定将random_state=56设置为结果再现性。它可以是你想要的任何自然数。
  • 我们用RandomForestClassifier()函数创建一个对象。
  • 此时,命令 RE.fit 开始特征(X_train)和目标变量(y_train)的训练阶段
  • 一旦在 80%的数据集上训练了分类器,我们就可以通过创建predicted_RF对象在剩余的 20%上测试它的准确性
  • 最后,分类报告告诉我们经过训练的分类器的性能
#Defining input and target variable
x = df.drop('class', axis=1)
y = df['class']#Splitting dataset between training and testing with a 80-20 #allocation
X_train, X_test, y_train, y_test = train_test_split(x, y, test_size = 0.2, random_state = 56)#Classifier Object
RF = RandomForestClassifier()#Fitting classifier to data
RF.fit(X_train, y_train)#Predicting testing records
predicted_RF = RF.predict(X_test)#Printing classification report
print(classification_report(y_test, predicted_RF))

从我们在选型阶段看到的情况来看,精度有了进一步的提高。该算法能够在 100%的情况下识别蘑菇是可食用的还是有毒的。产生输出的信息目前来自所有特征**。**

现在的问题是:

“有没有比其他更根本的特征?当我看到一个我想收集的蘑菇时,我需要特别注意什么?”

 precision    recall  f1-score   support

           0       1.00      1.00      1.00       841   
           1       1.00      1.00      1.00       784 accuracy                           1.00      1625  
   macro avg       1.00      1.00      1.00      1625
weighted avg       1.00      1.00      1.00      1625

运行下面的代码单元格后,可以确定上面的答案。这看起来很复杂,但我们可以一点一点地分解它:

  • 单元格创建两列:一列名为feature,另一列名为feature_importance,第一列列出了数据集中包含的所有列:Cap-shapeCap-surfaceCap-color
  • 第二列包含数据集每一列的所有关联要素重要性值。如果你只是想要这个值,你需要对随机森林算法使用命令RF.feature_importances_(其他分类器可能有不同的名字)
  • 然后这两列一起被转换成熊猫数据帧
  • 结果以我可以用命令to_markdown复制和粘贴的格式打印出来
##RF feature importancefeature_importance = pd.DataFrame(
{'feature':list(X_train.columns),
'feature_importance':[abs(i) for i in RF.feature_importances_]}
)print(feature_importance.to_markdown())

可以看出,要素重要性报告的值从 0 到 0.002 一直到 0.2。没有特别的原因,我选择了报告值至少为 0.1 或接近 0.1 的行。截止日期留给我们 4 个特征用于下一个模型:odorgill-sizegill-colorspore-print-color

|    | feature                  |   feature_importance |
|---:|:-------------------------|---------------------:|
|  0 | cap-shape                |           0.00488162 |
|  1 | cap-surface              |           0.00917991 |
|  2 | cap-color                |           0.013382   |
|  3 | bruises                  |           0.054723   |
|  4 | odor                     |           0.183597   |
|  5 | gill-attachment          |           0.00193266 |
|  6 | gill-spacing             |           0.03089    |
|  7 | gill-size                |           0.101708   |
|  8 | gill-color               |           0.122184   |
|  9 | stalk-shape              |           0.0202438  |
| 10 | stalk-root               |           0.0601195  |
| 11 | stalk-surface-above-ring |           0.0411767  |
| 12 | stalk-surface-below-ring |           0.040044   |
| 13 | stalk-color-above-ring   |           0.0141602  |
| 14 | stalk-color-below-ring   |           0.0147517  |
| 15 | veil-type                |           0          |
| 16 | veil-color               |           0.00194969 |
| 17 | ring-number              |           0.0151127  |
| 18 | ring-type                |           0.0839357  |
| 19 | spore-print-color        |           0.0978179  |
| 20 | population               |           0.0604895  |
| 21 | habitat                  |           0.0277208  |

现在我们知道了最重要的特性,我们可以重复训练和测试过程。这次x只有四列我们确定为最重要的特性。目标变量y保持不变。

  • 我们使用相同的方法将数据集分为训练和测试。
  • 创建RF对象
  • ****训练模型测试20%的数据
  • 打印分类报告****
##RF after feature selection #Defining input and target variable while dropping unimportant #features
x = df[['odor', 'gill-size', 'gill-color', 'spore-print-color']]
y = df['class']#Splitting dataset into training and testing
X_train, X_test, y_train, y_test = train_test_split(x, y, test_size = 0.2, random_state = 56)#Calling classifier
RF = RandomForestClassifier()#Fitting classifier to data
RF.fit(X_train, y_train)#Predicting testing records
predicted_RF = RF.predict(X_test)#Printing classification prediction
print(classification_report(y_test, predicted_RF))

足够令人惊讶的是,该模型保持了与处理 21 特征时相同的精度,这一次仅通过使用 4 个**。这向我们表明,尤其是当我们将模型投入生产时,模型所依赖的特性的数量应该限制在最重要的特性上。一般来说,更多的特性对应于部署计算成本更高的模型。**

 precision    recall  f1-score   support

           0       1.00      1.00      1.00       841   
           1       1.00      1.00      1.00       784 accuracy                           1.00      1625  
   macro avg       1.00      1.00      1.00      1625
weighted avg       1.00      1.00      1.00      1625

在这个最后阶段,我们必须重复随机森林模型的过程,但使用不同的算法,梯度推进,在模型选择阶段表现最好。

  • 在前一个单元中,我们重新定义了xy,使它们只包含最重要的特性。我们需要重新分配所有数据集列,以评估模型的整体性能。
  • 数据集遵循通常的 80/20 分割比率,具有相同的random_state
  • 对象XGB包含函数GradientBoostingClassifier()
  • 使用命令fit,分类器开始基于训练数据进行学习
  • 命令predict()执行测试阶段
  • 我们最终可以打印分类报告来评估性能****
#Defining input and target variable
x = df.drop('class', axis=1)
y = df['class']#Splitting dataset between training and testing with a 80-20 #allocation
X_train, X_test, y_train, y_test = train_test_split(x, y, test_size = 0.2, random_state = 56)#Calling classifier
XGB = GradientBoostingClassifier()#Fitting classifier to data
XGB.fit(X_train, y_train)#Predicting testing records
predicted_XGB = XGB.predict(X_test)#Printing classification report
print(classification_report(y_test, predicted_XGB))

当对所有特征进行训练时,梯度增强分类器报告与随机森林分类器相同的分数。在这个阶段,我们可以问自己以前的问题:

“有没有比其他更根本的特征?当我看到一个我想收集的蘑菇时,我需要特别注意什么?”

两个不同的分类器可能通过使用最相关的不同特征来得到相同的结果。

 precision    recall  f1-score   support

           0       1.00      1.00      1.00       841   
           1       1.00      1.00      1.00       784 accuracy                           1.00      1625  
   macro avg       1.00      1.00      1.00      1625
weighted avg       1.00      1.00      1.00      1625

获取梯度增强算法的特征重要性的命令对于随机森林模型是相同的:feature_importances_。代码背后的逻辑和以前一样。它创建了两列,一列包含所有的特性名称,另一列包含所有的特性重要性分数**。**

##XGB feature importance#Calculating feature importances
feature_importance=pd.DataFrame({'feature':list(X_train.columns),'feature_importance':[abs(i) for i in XGB.feature_importances_]})#Printing dataframe
print(feature_importance.to_markdown())

你可能会注意到这些值非常相似,如果我们使用我们之前建立的 > 0.1 截止值规则,同样的四个特征被确定为最相关:odorgill-sizegill-colorspore-print-color

|    | feature                  |   feature_importance |
|---:|:-------------------------|---------------------:|
|  0 | cap-shape                |           0.00458413 |
|  1 | cap-surface              |           0.0146785  |
|  2 | cap-color                |           0.0127857  |
|  3 | bruises                  |           0.0573168  |
|  4 | odor                     |           0.181369   |
|  5 | gill-attachment          |           0.00358367 |
|  6 | gill-spacing             |           0.0492609  |
|  7 | gill-size                |           0.115759   |
|  8 | gill-color               |           0.0958662  |
|  9 | stalk-shape              |           0.0229765  |
| 10 | stalk-root               |           0.0531794  |
| 11 | stalk-surface-above-ring |           0.0495843  |
| 12 | stalk-surface-below-ring |           0.0367454  |
| 13 | stalk-color-above-ring   |           0.0128033  |
| 14 | stalk-color-below-ring   |           0.0138009  |
| 15 | veil-type                |           0          |
| 16 | veil-color               |           0.00169852 |
| 17 | ring-number              |           0.0116543  |
| 18 | ring-type                |           0.0784959  |
| 19 | spore-print-color        |           0.104922   |
| 20 | population               |           0.0464761  |
| 21 | habitat                  |           0.0324597  |

我们已经为梯度增强模型确定了四个最相关的特征,所以让我们重复我们为随机森林所做的相同过程。

##XGB after feature selection#Defining input and target variable while dropping unimportant #features
x = df[['odor', 'gill-size', 'gill-color', 'spore-print-color']]
y = df['class']#Splitting dataset between training and testing with a 80-20 #allocation
X_train, X_test, y_train, y_test = train_test_split(x, y, test_size = 0.2, random_state = 56)#Calling classifier
XGB = GradientBoostingClassifier()#Fitting classifier to data
XGB.fit(X_train, y_train)#Predicting testing records
predicted_XGB = XGB.predict(X_test)#Printing classification report
print(classification_report(y_test, predicted_XGB))

具有 4 个基本特征的更新型号比具有所有 21 个特征的型号稍差。差异是 0.01,一个难以置信的小实体,这意味着大约有 16 个记录在超过 1600 个记录中被错误分类**。**

 precision    recall  f1-score   support

           0       0.99      1.00      1.00       841   
           1       1.00      0.99      1.00       784 accuracy                           1.00      1625  
   macro avg       1.00      1.00      1.00      1625
weighted avg       1.00      1.00      1.00      1625

同样,结果与上一个极其接近。主要区别在于使用的特征数量,因此我们可以假设该模型在计算上应该更便宜**,因此从 ML 操作的角度来看更好。**

跟踪所有不需要进行预测和运行模型的要素可以节省万亿字节的空间。在目前的设置中,这没有什么区别,但对于大型科技公司来说,取消一整列可以节省数百万美元。

很明显,在有很多特性的情况下,选择几个是很重要的。我们能够通过在两种情况下保持相同的性能来降低计算成本**。我们用较少的努力获得了类似的结果。**

当然,这并非没有挑战,需要解决这些挑战以进一步改进。

首先,一些基本特征甚至连专家都很难识别。更具体地说,值得一提的是“气味”。你能认出“茴香”和“杂酚油”的区别吗?我真的不会。****

最重要的是,我们不要忘记过度配合**。所有模型都有令人难以置信的高总体精度分数,接近完美。明确建议将模型部署在相似数据集中的未知记录上,以进一步测试其可靠性。**

****需要物种 id来将模型的范围扩展到除了蘑菇和蘑菇以外的新蘑菇家族。

我确实有一个最终免责声明给那些读完这篇文章后想尝试蘑菇狩猎的人。没有专家陪你一起采摘蘑菇是根本不推荐的**。美国的一些州和一些国家要求有执照才能练习。除了法律,一个好的经验法则是不要碰它,除非你 100%确定它可以食用。每种蘑菇对生态系统都有一定的贡献,所以如果不确定,最好让它留在原地!**

最后,如果您喜欢该内容,请考虑添加一个关注,以便在新文章发布时得到通知。如果你对这篇文章有什么要考虑的,写在评论里吧!我很想读读它们:)谢谢你的阅读!

PS:如果你喜欢我写的东西,如果你能通过 这个链接 订阅一个中等会员,那对我来说就是全世界。有了会员资格,你就获得了媒体文章提供的惊人价值,这是支持我的内容的一种间接方式!

参考

[1] UCI 机器学习知识库:蘑菇数据集。(2022).检索于 2022 年 9 月 13 日,来自 Uci.edu 网站:https://archive.ics.uci.edu/ml/datasets/Mushroom

[2]兹恩,a .,克雷默,n .,索南堡,s .,和勒施,G. (2009 年 9 月)。特征重要性排序度量。在关于数据库中的机器学习和知识发现的欧洲联合会议(第 694–709 页)。斯普林格,柏林,海德堡。

[3] Biau,g .,& Scornet,E. (2016)。随机森林导游。测试25 (2),197–227。https://doi.org/10.1007/s11749-016-0481-7

[4]j . h .弗里德曼(2002 年)。随机梯度增强。计算统计&数据分析38 (4),367–378。https://doi . org/10.1016/s 0167-9473(01)00065-2

原文:https://towardsdatascience.com/feature-interactions-524815abec81

当预测模型中的要素相互作用时,预测不能表示为要素效果的总和,因为一个要素的效果取决于另一个要素的值。克里斯托弗·莫尔纳尔

特征对变量预测的复杂协同效应称为特征相互作用。特征交互的另一个方面是一个特征相对于与之交互的另一个特征的变化。这些变量通常被称为交互变量

通常,我们会在数据集中遇到成对的特征交互,其中特征以 2 个为一组进行交互。例如,患心脏病的风险取决于你的身体质量指数,它被定义为体重/身高。这里, {体重,身高} 是成对交互。不太常见的高阶特征相互作用,我们看到两个以上的特征相互作用,在科学中它们有如此复杂的关系。例如, {x₁,x₂,x₃,x₄}log(x₁ + x₂ + x₃x₄ )* 中的四阶互动。

识别数据集中存在的要素交互非常有用,原因有多种,包括:

  • 了解数据集中要素之间的关系及其对预测的影响,避免仅使用主要影响而不使用交互影响来解释模型的偏见
  • 使用关于交互的信息来显式地构建表达模型
  • 提高模型性能的工程特征

一种用于可视化交互效应的流行方法是部分相关图(PDP) 。我们可以使用 PDP 来可视化 2 个特征如何随预测而变化。像 ICE 和 shapley 这样的变体也以类似的方式帮助你可视化交互效果。下面我们看一个加州住房数据集的例子(使用 pdpbox ),随着中值收入和房屋平均占有者的增加,房价也随之上涨。

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第84张

PDP 交互图示例

虽然这些方法在解释交互效应方面很棒,但在自动识别数据中的所有特征交互方面,它们是相当乏味的工具,尤其是如果您有一个大的特征空间。我们可以使用的一种简单方法是对基于 F 统计的所有特征和过滤器交互组合应用 2-way ANOVA 方法。但是,它们在捕捉复杂关系方面效率不高。然而, Friedman 的 H 统计量使用之前讨论的部分相关性来识别数据集中给定要素顺序的交互强度。下图显示了加州住房数据集中前 10 个交互的 H 统计数据(使用 sklearn_gbmi 计算):

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第85张

虽然这些方法对于成对的相互作用非常有效,但是它们很难用于识别更高阶的相互作用。我遇到的一个有趣的方法是神经交互检测。该方法分析前馈神经网络的权重,以识别任意阶的相互作用。从他们的例子中,给出了以下合成数据

X1, X2, X3, X4, X5, X6, X7, X8, X9, X10 = X.transpose()interaction1 = np.exp(np.abs(X1-X2))                        
interaction2 = np.abs(X2*X3)  
interaction3 = -1*(X3**2)**np.abs(X4) 
interaction4 = (X1*X4)**2
interaction5 = np.log(X4**2 + X5**2 + X7**2 + X8**2)
main_effects = X9 + 1/(1 + X10**2)Y =              interaction1 + interaction2 + interaction3 + interaction4 + interaction5 + main_effects
ground_truth = [     {1,2},        {2,3},         {3,4},         {1,4},        {4,5,7,8}     ]

该方法检测以下交互

Pairwise interactions              Arbitrary-order interactions
(1, 2)        7.8430                      (1, 2)        6.8951        
(4, 8)        3.1959                      (2, 3)        2.0953        
(5, 8)        3.0521                      (7, 8)        1.7971        
(7, 8)        3.0290                      (4, 5, 8)     1.6026        
(4, 5)        2.8506                      (1, 4)        1.5912        
(2, 3)        2.6294                      (5, 7)        1.5261        
(1, 4)        2.5037                      (3, 4)        1.3500        
(5, 7)        2.4460                      (4, 7)        1.0580        
(4, 7)        2.2369                      (4, 7, 8)     0.7727        
(3, 4)        1.8870                      (4, 5, 7, 8)  0.5467

虽然该算法并不完美,但它确实提供了很多信息。

然而,这些方法仍然没有给我们任何关于相互作用的本质的信息。如果您试图设计有助于模型性能的特性,识别交互的本质可能会特别有用。如果我们对关系有了初步的猜测,我们可以使用一些简单的试探法来选择交互。例如, pycaret 库获取所有可能的特征对的乘积(以及可选的比率),并使用随机森林、lightgbm 或相关性等方法识别最重要的交互。对于 california housing 数据集,pycaret 选择了以下交互阈值为 5%的交互:

['Longitude_multiply_MedInc', 'Latitude_multiply_AveOccup',
 'AveBedrms_multiply_MedInc', 'MedInc_multiply_Longitude',
 'HouseAge_multiply_MedInc', 'Longitude_multiply_Latitude',
 'Latitude_multiply_MedInc']

更复杂的方法是使用基于遗传算法的符号回归方法。您甚至可以在这些算法中使用自定义函数集。对于同一数据集, gplearn 的符号回归器生成以下关系:

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第86张

符号回归器生成的表达式

该方法的随机性和生成表达式的复杂性是其主要缺点。类似的方法如专长或规则适应也可以使用。这些方法倾向于产生更易解释的表达式。

识别和理解特征间的相互作用对于开发和解释模型至关重要。然而,上面介绍的所有识别功能交互的自动化方法都远非完美,应该谨慎使用并进行严格分析。还有很多其他工具可以直接或间接地帮助检测功能交互。

原文:https://towardsdatascience.com/feature-selection-a-comprehensive-list-of-strategies-3fecdf802b79

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第87张

里卡多·戈麦斯·安吉尔在 Unsplash 上的照片

假设您有一个包含 25 列和 10,000 行的数据集。经过一些特征工程,最终你得到了 45 列。在这 45 个特征中,你能保留几个?过多的特征会增加模型的复杂性和过度拟合,过少的特征会使模型欠拟合。因此,您优化您的模型,使其足够复杂,以便其性能可以推广,但又足够简单,以便易于训练、维护和解释。

“特性选择”意味着你可以保留一些特性,放弃一些其它的特性。问题是——如何决定保留哪些特征,去掉哪些特征?本文的目的是概述一些特性选择策略:

  • 删除未使用的列
  • 删除缺少值的列
  • 不相关特征
    —数字
    —分类
  • 低方差特征
  • 多重共线性
    —数字
    —分类
  • 特征系数
  • p 值
  • 差异通货膨胀系数(VIF)
  • 基于特征重要性/杂质的特征选择
  • 利用 sci-kit learn 进行自动特征选择
    —基于卡方的技术
    —正则化
    —顺序选择
  • 主成分分析

你不太可能在一个项目中同时使用这些策略,但是,手边有这样一个清单可能会很方便。

在麻省理工学院许可下发布,本次演示的数据集来自py caret——一个开源的低代码机器学习库。

数据集相当干净,但我做了一些预处理,我在这里跳过了。请注意,我使用这个数据集来演示不同的特征选择策略是如何工作的,而不是构建一个最终的模型,因此模型性能是不相关的(但这将是一个有趣的练习!).

让我们加载数据集:

import pandas as pddata = '[https://raw.githubusercontent.com/pycaret/pycaret/master/datasets/automobile.csv'](https://raw.githubusercontent.com/pycaret/pycaret/master/datasets/automobile.csv')
df = pd.read_csv(data)df.sample(5)

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第88张

数据集的前几行(图:作者)

该数据集包含 202 行和 26 列,每行代表一辆汽车的实例,每列代表其功能和相应的价格。这些列包括:

df.columns>> Index(['symboling', 'normalized-losses', 'make', 'fuel-type', 'aspiration', 'num-of-doors', 'body-style', 'drive-wheels', 'engine-location','wheel-base', 'length', 'width', 'height', 'curb-weight', 'engine-type', 'num-of-cylinders', 'engine-size', 'fuel-system', 'bore', 'stroke', 'compression-ratio', 'horsepower', 'peak-rpm', 'city-mpg', 'highway-mpg', 'price'], dtype='object')

现在,让我们深入研究特性选择的 11 个策略。

当然,最简单的策略是运用你的直觉。有时很明显,一些列在最终的模型中不会以任何形式使用(如“ID”、“FirstName”、“LastName”等列)。如果您知道某个特定的列不会被使用,那么可以直接删除它。在我们的数据中,没有一列如此突出,所以在这一步中我不会删除任何列。

具有缺失值在机器学习中是不可接受的,因此人们应用不同的策略来清理缺失数据(例如,插补)。但是,如果一列中丢失了大量数据,一种策略是将其完全删除。

在我们的数据集中,有显著缺失值的列是normalized-losses,我将删除它。

# total null values per column
df.isnull().sum()>>
symboling             0
normalized-losses    35
make                  0
fuel-type             0
aspiration            0
num-of-doors          2
body-style            0
drive-wheels          0
engine-location       0
wheel-base            0
length                0
width                 0
height                0
curb-weight           0
engine-type           0
num-of-cylinders      0
engine-size           0
fuel-system           0
bore                  0
stroke                0
compression-ratio     0
horsepower            0
peak-rpm              0
city-mpg              0
highway-mpg           0
price                 0
dtype: int64

无论算法是回归(预测一个数)还是分类(预测一个类),特征都必须与目标相关。如果某个特征没有表现出相关性,那么它就是一个主要的淘汰目标。您可以分别测试数值特征和分类特征的相关性。

# correlation between target and features
(df.corr().loc['price']
 .plot(kind='barh', figsize=(4,10)))

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第89张

数字特征和目标之间的相关性(图:作者)

在这个例子中,诸如峰值转速压缩比、冲程、缸径、高度和象征的等特征与价格的相关性很小,因此我们可以忽略它们。

您可以手动删除列,但是我更喜欢使用相关阈值(在本例中为 0.2)以编程方式来完成:

# drop uncorrelated numeric features (threshold <0.2)
corr = abs(df.corr().loc['price'])
corr = corr[corr<0.2]
cols_to_drop = corr.index.to_list()
df = df.drop(cols_to_drop, axis=1)

同样,您可以使用箱线图来查找目标特征和分类特征之间的相关性:

import seaborn as snssns.boxplot(y = 'price', x = 'fuel-type', data=df)

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第90张

按燃料类型分类的汽车价格(图:作者)

柴油型车的中位价格高于燃气型车。这意味着这个分类变量可以解释汽车价格,所以我不会放弃它。您可以像这样单独检查每个分类列。

举个极端的例子,我们假设所有的车都有相同的公路——mpg(mpg:英里每加仑)。你觉得这个功能有用吗?没有,因为它的方差正好为 0。我们可以选择放弃这样的低方差特性。让我们检查一下我们的功能差异:

import numpy as np# variance of numeric features
(df
 .select_dtypes(include=np.number)
 .var()
 .astype('str'))

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第91张

数字特征的方差(图:作者)

这里“bore”具有极低的方差,因此这是消除的理想候选。然而,在这种特殊情况下,我不愿意放弃它,因为它的值介于 2.54 和 3.94 之间,因此方差预计较低:

df['bore'].describe()

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第92张

一个特性的统计概要(图:作者)

当任何两个要素之间存在相关性时,就会出现多重共线性。在机器学习中,期望每个特征应该独立于其他特征,即它们之间没有共线性。正如你将在下面看到的,马力大的车辆往往有大的发动机尺寸并不奇怪。所以你可能想去掉其中一个,让另一个决定目标变量——价格

您可以分别测试数值要素和分类要素的多重共线性:

热图是直观检查和寻找相关要素的最简单方法。

import matplotlib.pyplot as pltsns.set(rc={'figure.figsize':(16,10)})
sns.heatmap(df.corr(),
            annot=True,
            linewidths=.5,
            center=0,
            cbar=False,
            cmap="PiYG")
plt.show()

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第93张

用于检查数字要素间多重共线性的热图(图:作者)

正如你所看到的,大多数特征在某种程度上是相互关联的,但有些特征具有非常高的相关性,例如长度轴距发动机尺寸马力

您可以基于关联阈值手动或以编程方式删除这些功能。我将手动删除共线性阈值为 0.80 的要素。

# drop correlated features
df = df.drop(['length', 'width', 'curb-weight', 'engine-size', 'city-mpg'], axis=1)

请注意,您还可以使用一种称为方差膨胀因子(VIF)的方法来确定多重共线性,并根据高 VIF 值删除要素。稍后我会展示这个例子。

与数值要素类似,您也可以检查分类变量之间的共线性。像卡方独立性检验这样的统计检验对它来说是理想的。

让我们检查一下数据集中的两个分类列— 燃料类型车身样式 —是独立的还是相关的。

首先,我们将选择感兴趣的分类特征:

df_cat = df[['fuel-type', 'body-style']]
df_cat.sample(5)

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第94张

为独立性测试选择的两个分类特征(图:作者)

然后,我们将在每一列中创建类别的交叉表/列联表。

crosstab = pd.crosstab(df_cat['fuel-type'], df_cat['body-style'])
crosstab

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第95张

两个分类特征的交叉表/列联表(图:作者)

最后,我们将对列联表进行卡方检验,这将告诉我们这两个特征是否独立。

from scipy.stats import chi2_contingencychi2_contingency(crosstab)

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第96张

独立性卡方检验的结果(图:作者)

按照出现的顺序,输出是卡方值、 p 值、自由度和一组预期频率。

p 值是<0.05, thus we can reject the null hypothesis that there’s no association between features, i.e., there’s a statistically significant relationship between the two features.

Since there’s an association between the two features, we can choose to drop one of them.

我现在将换档一点……

到目前为止,我已经展示了在实现模型之前应用的特性选择策略。这些策略在构建初始模型的第一轮特征选择中非常有用。但是,一旦构建了模型,您将获得关于模型性能中每个特征的适合度的进一步信息。根据这些新信息,您可以进一步确定要保留哪些功能。

下面我将展示其中的一些方法。

但是首先,我们需要使模型适合数据集,因此需要一些数据预处理。我正在做最少的数据准备,只是为了演示特征选择方法。

# drop columns with missing values
df = df.dropna()from sklearn.model_selection import train_test_split# get dummies for categorical features
df = pd.get_dummies(df, drop_first=True)# X features
X = df.drop('price', axis=1)# y target
y = df['price']# split data into training and testing set
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)from sklearn.linear_model import LinearRegression # scalingfrom sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.fit_transform(X_test)# convert back to dataframe
X_train = pd.DataFrame(X_train, columns = X.columns.to_list())
X_test = pd.DataFrame(X_test, columns = X.columns.to_list())# instantiate model
model = LinearRegression()# fit
model.fit(X_train, y_train)

现在我们已经拟合了模型,让我们做另一轮的特征选择。

如果你正在运行一个回归任务,那么特征适合度的一个关键指标是回归系数(所谓的 beta 系数),它显示了特征在模型中的相对贡献。有了这些信息,您就可以删除贡献很小或没有贡献的功能。

# feature coefficients
coeffs = model.coef_# visualizing coefficients
index = X_train.columns.tolist()(pd.DataFrame(coeffs, index = index, columns = ['coeff']).sort_values(by = 'coeff')
 .plot(kind='barh', figsize=(4,10)))

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第97张

每个特性的 Beta 值/系数(图:作者)

如你所见,有些贝塔系数很小,对汽车价格的预测贡献不大。您可以过滤掉这些特征:

# filter variables near zero coefficient value
temp = pd.DataFrame(coeffs, index = index, columns = ['coeff']).sort_values(by = 'coeff')
temp = temp[(temp['coeff']>1) | (temp['coeff']< -1)]# drop those features
cols_coeff = temp.index.to_list()
X_train = X_train[cols_coeff]
X_test = X_test[cols_coeff]

在回归中,p 值告诉我们预测值和目标值之间的关系是否具有统计显著性。statsmodels库用特征系数和相关的 p 值给出了回归输出的漂亮摘要。

如果一些特性不重要,您可以逐个删除它们,每次都重新运行模型,直到您找到一组具有重要的 p 值并通过更高的调整 R2 提高了性能的特性。

import statsmodels.api as sm
ols = sm.OLS(y, X).fit()
print(ols.summary())

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第98张

具有 beta 值和统计显著性的回归结果的部分摘要(图:作者)

正如我前面提到的,方差膨胀因子(VIF)是测量多重共线性的另一种方法。它被测量为总模型方差与每个独立特征方差的比率。某个功能的高 VIF 表明它与一个或多个其他功能相关。根据经验法则:

VIF = 1 表示无相关性,
VIF = 1–5 中度相关,
VIF > 5 高度相关

可以想象,VIF 是一种消除多重共线性要素的有用技术。在我们的演示中,让我们大方一点,保留所有 VIF 低于 10 的特性。

from statsmodels.stats.outliers_influence import variance_inflation_factor# calculate VIF
vif = pd.Series([variance_inflation_factor(X.values, i) for i in range(X.shape[1])], index=X.columns)# display VIFs in a table
index = X_train.columns.tolist()
vif_df = pd.DataFrame(vif, index = index, columns = ['vif']).sort_values(by = 'vif', ascending=False)
vif_df[vif_df['vif']<10]

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第99张

基于低 VIF 选择的特征(图:作者)

决策树/随机森林使用最大程度减少杂质的特征来分割数据(根据基尼杂质或信息增益来衡量)。这意味着,找到最佳特征是算法在分类任务中如何工作的关键部分。然后,我们可以通过feature_importances_属性访问最佳特性。

让我们在数据集上实现一个随机森林模型,并过滤一些要素。

from sklearn.ensemble import RandomForestClassifier# instantiate model
model = RandomForestClassifier(n_estimators=200, random_state=0)
# fit model
model.fit(X,y)

现在我们来看看特性的重要性:

#  feature importance
importances = model.feature_importances_# visualization
cols = X.columns
(pd.DataFrame(importances, cols, columns = ['importance'])
 .sort_values(by='importance', ascending=True)
 .plot(kind='barh', figsize=(4,10)))

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第100张

随机森林实现中的特性重要性(图:作者)

上面的输出显示了每个特性在减少每个节点/分裂处的杂质方面的重要性。

由于随机森林分类器有许多估计器(例如,在上面的例子中有 200 棵决策树),我们可以用置信区间来计算相对重要性的估计。让我们想象一下。

# calculate standard deviation of feature importances 
std = np.std([i.feature_importances_ for i in model.estimators_], axis=0)# visualization
feat_with_importance  = pd.Series(importances, X.columns)
fig, ax = plt.subplots(figsize=(12,5))
feat_with_importance.plot.bar(yerr=std, ax=ax)
ax.set_title("Feature importances")
ax.set_ylabel("Mean decrease in impurity")

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第101张

随机森林实现中具有置信区间的特征重要性(图:作者)

既然我们知道了每个特性的重要性,我们就可以手动地(或者编程地)决定保留哪些特性,放弃哪些特性。

幸运的是,在sklearn库中有一个完整的模块,只用几行代码就可以处理特性选择。

sklearn中有许多自动化的流程,但在这里我只演示几个:

# import modules
from sklearn.feature_selection import (SelectKBest, chi2, SelectPercentile, SelectFromModel, SequentialFeatureSelector, SequentialFeatureSelector)

基于卡方的技术基于一些预定义的分数选择特定数量的用户定义的特征(k)。这些分数是通过计算 X(自变量)和 y(因变量)之间的卡方统计来确定的。在sklearn中,你需要做的就是确定你想要保留多少功能。如果您想保留 10 个特性,实现将如下所示:

# select K best features
X_best = SelectKBest(chi2, k=10).fit_transform(X,y)# number of best features
X_best.shape[1]>> 10

如果有大量的特性,你可以指定你想要保留的特性的百分比。假设我们想保留 75%的特性,放弃剩下的 25%:

# keep 75% top features 
X_top = SelectPercentile(chi2, percentile = 75).fit_transform(X,y)# number of best features
X_top.shape[1]>> 36

正则化减少了过度拟合。如果有太多的特征,正则化会通过收缩特征系数(称为 L2 正则化)或将一些特征系数设置为零(称为 L1 正则化)来控制它们的效果。

一些模型内置了 L1/L2 正则化作为惩罚特征的超参数。使用元转换器SelectFromModel可以消除这些特征。

让我们用*惩罚=‘L1’*来实现一个LinearSVC 算法。然后我们将使用SelectFromModel 删除一些功能。

# implement algorithm
from sklearn.svm import LinearSVC
model = LinearSVC(penalty= 'l1', C = 0.002, dual=False)
model.fit(X,y)# select features using the meta transformer
selector = SelectFromModel(estimator = model, prefit=True)X_new = selector.transform(X)
X_new.shape[1]>> 2# names of selected features
feature_names = np.array(X.columns)
feature_names[selector.get_support()]>> array(['wheel-base', 'horsepower'], dtype=object)

顺序特征选择是一种经典的统计技术。在这种情况下,您可以一次添加/删除一个特征,并检查模型性能,直到它根据您的需要进行了优化。

顺序选择有两种变体。正向选择技术从 0 个特征开始,然后添加一个最大程度地减小误差的特征;然后添加另一个特性,以此类推。

反向选择的工作方向相反。该模型从包括所有特征开始,并计算误差;然后,它消除了一个进一步减少误差的特征。重复该过程,直到剩余期望数量的特征。

# instantiate model
model = RandomForestClassifier(n_estimators=100, random_state=0)# select features
selector = SequentialFeatureSelector(estimator=model, n_features_to_select=10, direction='backward', cv=2)
selector.fit_transform(X,y)# check names of features selected
feature_names = np.array(X.columns)
feature_names[selector.get_support()]>> array(['bore', 'make_mitsubishi', 'make_nissan', 'make_saab',
       'aspiration_turbo', 'num-of-doors_two', 'body style_hatchback', 'engine-type_ohc', 'num-of-cylinders_twelve', 'fuel-system_spdi'], dtype=object)

主成分分析的主要目的是降低高维特征空间的维数。在这种情况下,原始特征被重新投影到新的维度(即主成分)。最终目标是找到最能解释数据方差的分量数。

# import PCA module
from sklearn.decomposition import PCA# scaling data
X_scaled = scaler.fit_transform(X)# fit PCA to data
pca = PCA()
pca.fit(X_scaled)
evr = pca.explained_variance_ratio_# visualizing the variance explained by each principal componentsplt.figure(figsize=(12, 5))
plt.plot(range(0, len(evr)), evr.cumsum(), marker="o", linestyle="--")plt.xlabel("Number of components")
plt.ylabel("Cumulative explained variance")

med怎么旋转图片TowardsDataScience 博客中文翻译 2022(一百六十一)_https://www.jmylbn.com_新闻资讯_第102张

主成分分析解释的累积方差(图:作者)

如您所见,20 个主成分解释了 80%以上的方差,因此您可以将您的模型与这 20 个成分相匹配。您可以预先确定方差阈值,并选择所需的主成分数。

希望这是一个有用的指南,可以应用于特征选择的各种技术。一些技术在之前应用于拟合模型,例如删除具有缺失值的列、不相关的列、具有多重共线性的列以及使用 PCA 进行降维,而其他技术在基础模型实施之后应用,例如特征系数、p 值、VIF 等。你可能永远不会在一个项目中使用所有的策略,但是,你可以把这个列表作为一个清单。

我已经在 GitHub 上传了这里描述的所有技术的 Jupyter 笔记本。

感谢您的阅读。请随意订阅以获得我即将发表的文章的通知,或者通过 LinkedIn 与我联系。