一个全面的机器学习工作流程,使用 R
介绍
我将使用一个非常有趣的数据集,该数据集出现在布雷特·兰茨(Brett Lantz)写的《带 R 的机器学习》(RPackt Publishing)一书中。我的意图是通过执行一个完全监督的机器学习工作流来扩展对这个数据集的分析,这个工作流我已经设计了一段时间,以便帮助我用一种系统的、有条不紊的方法来解决任何类似的问题。
如果你认为这不是什么新鲜事,那么你绝对是对的!我在这里没有提出任何新的东西,只是确保我有所有必要的工具来遵循一个完整的过程,而不会留下任何大的细节。希望你们中的一些人也会发现它很有用,并确信你们会从我的部分和/或你们会以不同方式做的事情中发现一些判断错误。欢迎给我留言,帮助我改进!
让我们向前一跳,开始了解我们将处理哪些信息:
混凝土强度建模
从书中:
“在工程领域,准确估计建筑材料的性能至关重要。为了制定建筑、桥梁和道路施工中所用材料的安全指南,需要进行这些评估。
估算混凝土的强度是一项特别有趣的挑战。尽管混凝土几乎用于每一个建筑项目,但由于各种成分以复杂的方式相互作用,混凝土的性能差异很大。因此,很难准确预测最终产品的强度。给定输入材料的成分列表,可以可靠地预测混凝土强度的模型可以产生更安全的施工实践。
为了进行这一分析,我们将利用由叶一诚捐赠给 UCI 机器学习数据仓库( 、http://archive.ics.uci.edu/ml)的混凝土抗压强度数据。
根据该网站,混凝土数据集包含 1030 个混凝土实例,具有描述混合物中使用的成分的八个特征。这些特征被认为与最终抗压强度有关,它们包括产品中使用的水泥、矿渣、灰、水、超塑化剂、粗骨料和细骨料的量(以千克/立方米计)以及老化时间(以天计)。”
机器学习工作流程
我发现将工作流程分成 6 个阶段最适合我。在这个意义上,我将把这个实例描述为:
1)设置
2)探索性数据分析
3)特征工程
4)数据准备
5)建模
6)结论
在实践中,我从一个跳到另一个,很多时候不考虑顺序,而且经常是循环的。因此,请将此视为一个初始结构,更像是一份清单,而不是一步一步的指南。
这份清单相当全面,涵盖了你在监督学习 分类 和 回归 问题中要遵循的大部分内容。在实践中,你很可能会跳过列表中的一些要点,因为有些事情是你为分类问题所做的,而不是为回归问题所做的,反之亦然。甚至有些有时候还有点多余(虽然在我看来双重检查总是有用的)。我相信随着更多的实践和经验,这个列表会得到调整,我希望我也能在未来再次分享。
我将把自己限制在简短直接的回答上,并在必要时扩展。否则我担心我会让任何人逗留太久!
你会看到,即使我包括了完整的清单,在许多情况下,我们并不一定要做什么。这是因为这个数据集非常简单。这感觉有点像作弊,但是,我会确保提到为什么我们不必做任何事情,以及检查点背后的想法。
我想提到的最后一件事是,当我到达建模阶段时,我将改变我的方法,展示一些有用的建模工具,包括 R 包 caret 和 caretEnsemble 。因此,我不是一步一步地尝试一些基线模型,然后尝试一些更高级的模型,通过超参数调整和正则化来减少过度拟合,而是一次训练一堆模型,因为这使我能够使最后一个阶段更加简洁明了,便于解释。还因为建模阶段是一个人喜欢做自己的事情并通过使用不同的方法获得创造力的阶段。在我看来,这个清单对于阶段 1 至 4 非常重要,但从阶段 5 开始,它可能会变得不那么严格。
说够了,我们开始吧:
在这里找到工作文件和代码:https://github.com/gabrielpierobon/ML-workflow-caret
1)设置
1.1)我们试图预测什么?
我们需要为工程领域准确地估计建筑材料的性能。
1.2)这是什么类型的问题?监督学习还是非监督学习?分类还是回归?二元还是多类?单变量还是多变量?
这是一个多元监督机器学习问题,我们必须预测数字结果,因此我们将使用回归技术。
1.3)我们有什么类型的数据?
我们的数据是“csv”格式。它显示了带有列名的标题行。它似乎只包含数字信息。
1.4)导入数据集
我们可以简单地用下面的代码加载它:
*concrete <- read.csv(“/Users/Gabriel Pierobon/Desktop/Datasets para cargar/concrete.csv”)#use your own directory!*
这是我们数据集的大小:
*dim(concrete)
[1] 1030 9*
1,030 行 9 列,其中一列是我们的响应/目标变量。
我们可以看到它是作为数据框导入的,这是我们处理这些数据所需的格式:
*class(concrete)
[1] "data.frame"*
我们还可以检查我们的列名是否被正确导入。
*names(concrete)*
从该列表中,我们将strength
确定为我们的响应/目标变量*。*
我们可以得出结论,我们的数据被正确地导入,从而结束我们的 ssetting阶段。
在此之前,我想要求我们所有的图书馆。为了提高这本书的可读性,在乞讨的时候一次完成是很有用的:
*library(dplyr)
library(ggplot2)
library(PerformanceAnalytics)
library(ggthemes)
library(corrplot)
library(car)
library(psych)
library(caret)
library(caretEnsemble)
library(doParallel)*
考虑到这一点,让我们继续探索性的数据分析:
2) 探索性数据分析 (EDA)
2.1)查看数据(str 或 dplyr 的一瞥)。第一眼。有什么奇怪的吗?
我们想要再次检查我们在设置阶段所做的事情的第一个方法是快速查看我们的完整数据集。我们这样做:
*View(concrete)*
这将显示一个包含数据集的窗口。我喜欢从上到下、从左到右快速查看,以确保数据加载正确。这也是一种快速而肮脏的方式来检测一眼就能发现的问题。对于非常大的数据集,您不希望这样做。
接下来,我们将对我们的数据进行浏览并观察数据帧的前几行:
*glimpse(concrete)*
*head(concrete)*
2.2)它是一个“整洁”的数据集吗?需要“聚集”还是“分散”呢?它是以一种我们可以合作的方式呈现的吗?
我们需要我们的数据以行的形式呈现,以列的形式呈现特征。幸运的是,这是数据集的情况,所以我们不必转换它。否则,我们将不得不使用某种功能来旋转数据框以适应我们的需要(参考该网站了解更多关于那个)
2.3)行名和列名可以吗?我们应该改变他们吗?
我们已经检查过这些是如何装载的。我们需要更新/改变什么来更清楚地了解我们的变量吗?我觉得不是这样的,我们可以继续。这里的想法是确保我们舒适地使用我们的特性名称,避免不必要的长名称或任何其他令人困惑的情况。
2.4)检查数据类型。他们还好吗?如果没有,转换
正如我们所看到的,我们所有的变量都是双类型,除了变量age
是整数*。好在我们什么都不用换算!为了避免加载数据时出现某种类型的错误,我们检查这一点非常重要。有时数字列中的单个字符会导致整个列作为字符被加载。*
2.5)我们的响应/目标变量是什么?阶层失衡?研究一下
我们的响应变量是strength
。让我们来看看一些有用的统计数据:
*summary(concrete$strength)*
我们可以看到它从 2.3 到 82.6 不等。中值和平均值非常接近,但是由于中值实际上更小,这导致变量分布的稍微向右倾斜。
我们可以观察到,使用 ggplot2 的绘图:
**
正如我们所看到的,strength
变量的分布并不完全符合正态分布,但是我们还是要继续下去。这应该不成问题,因为很近。QQ 图也有助于常态的视觉分析(我把这个留给你)
最后,由于这是一个回归问题,我们不必担心阶级不平衡。在分类中,你希望在你的响应变量中有平衡的类(这里有一个关于类不平衡的好帖子)
2.6)其余功能。汇总统计数据。了解您的数据
这里,我们将统计分析扩展到我们的其他变量/特征。我们希望关注最小值和最大值*(这是对潜在异常值的第一次检查)。同样,意味着和的中位数的差异是值得关注的。我们希望所有变量尽可能遵循正态分布。*
*summary(concrete)*
我们可以根据我们的分析绘制相关图。这将为我们提供一个图表,显示所有变量之间的相关性。这也让我们第一次思考,我们是否需要模型中的所有变量。我们不希望我们的特征变量之间呈现高相关性。我们稍后会处理这件事。
*corrplot(cor(concrete), method = “square”)*
另一种看待所有这些的好方法是用这个相关图:
*chart.Correlation(concrete)*
在其中一条对角线上,我们可以看到每个特征的分布。并不是所有的都类似于常态,所以我们将在后面处理这个问题。
在这一点上,我的第一个结论是,变量ash
与我们的响应变量strength
具有低相关性,而与八个其他特征中的四个具有高相关性。因此,它是一个很有可能被删除的对象,我们稍后也会谈到这一点。
2.7)分类数据/因素:创建计数表以了解不同的类别。全部检查一下。
在这种情况下,我们不使用分类特征。你要确保你理解你的类别,有时拼写错误会给因子变量带来问题。
我们可以继续前进。
2.8)不必要的列?我们可以很快理解我们不需要的列。放下它们
这里我们想寻找完全无用的列。数据集中出现的任何信息都是毫无意义的,我们可以决定是否应该删除。附加索引列、无信息字符串列等。对于该数据集,情况并非如此。只要导入数据集,就可以很好地做到这一点,此时不需要特别做。
2.9)检查是否有缺失值。多少?在哪里?删除它们?归咎于他们?
让我们首先对 NAs 做一个全面的检查:
*anyNA(concrete)
[1] FALSE*
精彩!整个集合中没有缺失值!让我向您展示一种方法,我们可以为每一列检测到这一点:
*sapply(concrete, {function(x) any(is.na(x))})*
2.10)检查异常值和其他不一致的数据点。箱线图。用于异常值检测的 DBSCAN?
在我看来,离群点检测更像是一门手艺。我真的很喜欢使用 DBSCAN 聚类进行异常值检测的方法,但我不打算继续这样做,所以我不会过度扩展这个分析。DBSCAN 是一种聚类算法,可以检测数据中的噪声点,并且不会将它们分配给任何聚类。我发现异常值检测非常有吸引力(更多关于 DBSCAN 的信息,请点击
相反,我将继续绘制一个箱线图,并尝试处理我认为与视觉相关的点:
*boxplot(concrete[-9], col = “orange”, main = “Features Boxplot”)*
我们看到有几个潜在的异常值,但是我认为age
特性可能是最有问题的。让我们孤立地来看:
*boxplot(concrete$age, col = “red”)*
这仅仅是 4 个异常值吗?如果是这样,我们可以摆脱他们。还是不应该?我们来看看这些值是什么,有多少个。
*age_outliers <- which(concrete$age > 100)
concrete[age_outliers, “age”]*
我的天啊。所以他们有 62 个,而不是只有 4 个!显然,这只是因为相同的数字重复了几次。这让我觉得这个age
点其实是有关联的,我们不想去掉。我们的 1,030 个数据集中的 62 个数据点似乎太高,不能简单地删除(我们会丢失大量信息)。
2.11)检查数字数据中的多重共线性。差异通货膨胀系数(VIF)
我们已经在之前展示的相关图中看到,某些特征之间似乎存在显著的相关性。我们希望确保多重共线性不会成为阻碍我们前进的问题。为此,我们将计算一个名为方差膨胀因子(VIF) 的分数,该分数测量回归系数的方差因模型中的多重共线性而膨胀的程度。如果 VIF 得分大于 10,则强烈建议使用多重共线性,我们应该尝试去除导致多重共线性的要素。
首先,我们为我们的目标变量生成一个简单的线性回归模型,用相互特征来解释。之后,我们在模型对象上调用函数vif()
,并查看命名列表输出:
*simple_lm <- lm(strength ~ ., data = concrete)
vif(simple_lm)*
尽管有许多变量得分为 5 或更高,但没有一个变量超过阈值10,因此我们认为多重共线性不是一个大问题。然而,有些人会争辩说,拥有这么多分数为 7 的特性确实是个问题。我们现在不会担心这个。**
至此,我们认为探索性数据分析(EDA)* 阶段已经结束,我们继续进行特性工程。你可以不同意这件事结束了!我相信还有很多探索要做。*
3)特征工程
对于数据科学家来说,特征工程也被认为是一项非常重要的技能。它包括从数据集中的现有要素生成新要素。这可以简单到从字符串列中提取一些日期信息,或者产生 交互术语 。此外,它肯定需要一定程度的主题专业知识和领域知识,因为提出新的信息特征是数据和整个应用领域的本质所固有的。
在这里,我们将超快,因为我们的数据似乎已经非常翔实和完整(工程师可能不同意!).
我想说的是,设计新要素很可能需要我们重复之前已经完成的一些分析,因为我们不想引入给数据集增加噪声的新要素。所以请记住,我们必须总是回头再看一遍我们的清单,并确定我们是否需要再分析一次。
3 .1)创建新的有用特征。互动术语。基础数学和统计学。使用 if-else 结构创建类别
因为我不是工程领域的主题专家,所以我不会从交互术语中创建新特性。我只限于验证是否有任何变量需要任何类型的转换。
我想做的第一件事是检查两个变量,它们似乎有不寻常的分布。就是age
和superplastic
的情况。让我们绘制它们的原始形式,并在下面记录(红色)。
*par(mfrow = c(2,2))hist(concrete$age)
hist(concrete$superplastic)
hist(log(concrete$age), col = “red”)
hist(log(concrete$superplastic), col = “red”)*
虽然我觉得将age
转换成对数形式很舒服,但是在superplastic,
的观察值为 0 的情况下,当取 0 的对数时,我会有一些问题,所以我会取对数,然后手动将它们设置为 0。
下面是转换这两种功能的代码:
*concrete$age <- log(concrete$age)concrete$superplastic <- log(concrete$superplastic)
concrete$superplastic <- ifelse(concrete$superplastic == -Inf, 0,
concrete$superplastic)head(concrete)*
注:我花了相当多的时间在这一点上试图创建一个新的宁滨的superplastic
功能,原来的superplastic
功能分为 3 个数字类别。然而,就解释目标变量的重要性而言,我没有取得多大成功。我不会展示这些尝试,但只知道我确实尝试了一段时间,但没有成功。失败也是学习的一部分!
3.2)为分类特征创建虚拟模型。优选地使用一位热编码
我们目前不使用分类特征,因此将跳过这一部分。然而,如果你看到了一些因子列,你必须确保你的算法能够处理它们,否则就对它们进行一次热编码。
3.3)我们可以使用正则表达式从字符串列中提取一些重要的文本吗?
我们目前不处理 sting 数据,因此将跳过这一部分。这应该是一个非常有用的工具,当你有一些字符类型的相关信息,你可以从中创建新的有用的类别。
谢天谢地,我们不必经历这一切!但是,如果我们要处理这类信息,最后三个部分是必须的。我将确保分析一个数据集,在其中我可以展示一些内容。
让我们进入数据准备阶段:
4)数据准备
4.1)手动特征选择。移除有噪声、无信息、高度相关或重复的要素。
这是我们在此工作流中第二次花时间查看我们的要素,并检测是否有任何要素信息不够丰富,或者由于引入了多重共线性等问题而应被删除。
正如我已经决定的那样,我将首先放弃ash
功能(在尝试了一些基线模型后,你可能想要放弃它并删除它,如果它对性能没有帮助,我已经这样做了,所以我现在将放弃它,正如我最初的评估一样)
*concrete$ash <- NULLhead(concrete)*
除此之外,其他的我就不拆了。
4.2)如果需要,转换数据。如果需要,缩放或规格化。
我们将使用的大多数算法要求我们的数字特征被缩放或归一化(原因如下
我们不会在这个精确的部分这样做,但留待以后,因为脱字符允许我们在它的训练功能内做一些预处理*。这特别有用,因为当向我们展示预测和结果时,该算法会自动转换回其原始比例。如果我在这里手动归一化数据集,那么我必须手动转换回预测。*
4.3)自动特征提取。降维(主成分分析,NMF,t-SNE)
如果手动移除特征不够简单,但我们仍然认为数据集包含太多特征或太多相关特征,我们可以应用维度缩减技术。主成分分析就是其中的一种技术,这种技术非常有用,既可以简化我们的数据集,也可以永久消除多重共线性的问题。
非负矩阵分解(NMF) 和 t-SNE 是另外两种有用的降维技术。
我们的数据集中只有 8 个特征,1 个已经被手动删除,我不认为我们需要进一步降低维数。
4.4)我们的数据集是随机的吗?
我们不确定它是随机的,所以我们将随机播放以防万一:
*set.seed(123)
concrete_rand <- concrete[sample(1:nrow(concrete)), ]
dim(concrete_rand)*
4.5)定义评估方案:我们有多少样本?坚持方法。需要交叉验证吗?
我们有 1030 个样本,所以这绝对是一个小数据集。我们将数据集分为训练集和测试集,并确保在训练模型时使用交叉验证。通过这种方式,我们可以确保尽可能好地利用我们的少量观察数据。
4.6)将数据集分成训练和测试集(为可复制性设置种子)
我们首先创建一组预测值和一组目标变量
*X = concrete_rand[, -8]
y = concrete_rand[, 8]*
我们检查一切正常:
*str(X)*
*str(y)*
然后,我们继续将新的X
(预测值)和y
(目标值)集分成训练集和测试集。
注意:您不必将集合分开,并且可以使用公式方法完美地进行。我只是更喜欢这样做,因为这样我确信我的过程与我如何使用 Python 的 scikit-learn 是一致的。
我们将使用 caret 的createDataPartition()
函数,它为我们生成分区索引,我们将使用它们来执行分割:
*set.seed(123)part.index <- createDataPartition(concrete_rand$strength,
p = 0.75,
list = FALSE)X_train <- X[part.index, ]
X_test <- X[-part.index, ]
y_train <- y[part.index]
y_test <- y[-part.index]*
所以现在我们有 4 套。两个预测器集合拆分为序列和测试*,两个目标集合也拆分为序列和测试。它们都使用相同的索引进行分区。*
再一次,让我们检查一切工作正常:
*str(X_train)
str(X_test)
str(y_train)
str(y_test)*
好吧!我们可以走了!现在到建模阶段!
5)建模
正如我在导言中提到的那样,在这一阶段,我将改变我的方法,不再一一列举要做的事情,而是总结我们将如何进行。
- 我们将使用包以便同时训练一系列模型
- 由于 caret 的功能,这将允许我们对每个模型使用相同的 5 折交叉验证
- 我们将允许并行处理来提高速度
- 我们不会关注算法的本质。我们只是使用它们并对结果进行评论
- 我们将使用一个线性模型,一个具有径向核的支持向量机,一个随机森林,一个梯度推进基于树的模型和一个梯度推进基于线性的模型
- 我们不会进行手动超参数调整,相反,我们将允许插入符号在每个模型中进行一些默认调整
- 我们将通过训练集和测试集来比较性能,重点关注作为我们度量标准的 RMSE (均方根误差)
- 我们将使用来自 caretEnsemble 包的一个非常酷的功能,将集合模型列表,然后将它们堆叠起来,以尝试产生模型的最终组合,希望能进一步提高性能
所以我们继续吧。
我们首先在trainControl()
中设置并行处理和交叉验证
**registerDoParallel(4)
getDoParWorkers()set.seed(123)my_control <- trainControl(method = “cv”, *# for “cross-validation”*
number = 5, *# number of k-folds*
savePredictions = “final”,
allowParallel = TRUE)**
然后,我们通过调用我们的X_train
和y_train
集合,使用caretList()
函数训练我们的模型列表。我们用上面创建的trainControl
对象指定trControl
,并将methodList
设置为算法列表(检查脱字符包信息以了解哪些模型可用以及如何使用它们)。
**set.seed(222)model_list <- caretList(X_train,
y_train,
trControl = my_control,
methodList = c(“lm”, “svmRadial”, “rf”,
“xgbTree”, “xgbLinear”),
tuneList = NULL,
continue_on_fail = FALSE,
preProcess = c(“center”,”scale”))**
- 我用的是
X_train
和y_train
,但是你完全可以用y ~ x1 + x2 + … + xn
公式来代替 my_control
指定 5 重交叉验证并激活平行处理tuneList
为假,因为我们没有指定手动超参数调整continue_on_fail
设置为 FALSE,因此如果出现问题,它将停止- 在
preProcessing
中是我们缩放数据集的地方。我们选择“中心和“刻度
现在我们的caretList
已经训练好了,我们可以看看结果了。我们可以访问每个单独的模型。这是 SVM 的结果:
**model_list$svmRadial**
请注意,caret 尝试对模型的可用参数进行一些自动调整,并使用 RMSE 作为性能度量来选择最佳模型。
这对于我们的型号列表中的其他型号都是一样的。我们不会逐一介绍。那是给你检查的!
让我们直接进入我们的目标,即找到具有最低 RMSE 的模型。我们首先对训练数据进行评估。
**options(digits = 3)model_results <- data.frame(
LM = min(model_list$lm$results$RMSE),
SVM = min(model_list$svmRadial$results$RMSE),
RF = min(model_list$rf$results$RMSE),
XGBT = min(model_list$xgbTree$results$RMSE),
XGBL = min(model_list$xgbLinear$results$RMSE)
)print(model_results)**
就 RMSE 而言, xgbTree 模型提供了最好的结果,得分为 4.36(记住平均强度为 35.8)。
caretEnsemble 提供了对该模型列表的性能进行重新采样并绘制的功能:
**resamples <- resamples(model_list)dotplot(resamples, metric = “RMSE”)**
我们还可以看到,xgbTree
与其他型号相比,差异也更小。
接下来,我们将尝试通过组合我们的model_list
来创建一个新模型,以便找到可能的最佳模型,希望这是一个采用我们已经训练的 5 个模型中的最佳模型并优化性能的模型。
理想情况下,我们将集成彼此相关性较低的模型。在这种情况下,我们将看到存在一些高度相关性,但我们将选择继续,只是为了展示这一特征:
**modelCor(resamples)**
首先,我们使用caretEnsemble()
训练我们的模型集合,这将与所有模型执行线性组合。
**set.seed(222)
ensemble_1 <- caretEnsemble(model_list,
metric = “RMSE”,
trControl = my_control)
summary(ensemble_1)**
****
如我们所见,我们设法将训练集的 RMSE 减少到 4.156
这是我们合奏的一张图表
**plot(ensemble_1)**
红色虚线是该乐团的 RMSE 演出。
接下来,我们可以更具体地尝试使用其他算法与caretStack()
进行集成。
注:我尝试了一些型号,但无法提高性能。我将展示其中一个在训练数据上产生相同性能的例子。无论如何,我们都将使用这两个集合,以便检查哪一个在处理看不见的数据时做得更好。
**set.seed(222)ensemble_2 <- caretStack(model_list,
method = “glmnet”,
metric = “RMSE”,
trControl = my_control)print(ensemble_2)**
注意使用 glmnet 的最佳模型的 RMSE 是 4.15,与我们的第一个集合相同。
最后,是时候评估我们的模型在看不见的数据上的性能了,这些数据在我们的测试集中。
我们首先预测每个模型的测试集,然后计算 RMSE:
**# PREDICTIONS
pred_lm <- predict.train(model_list$lm, newdata = X_test)
pred_svm <- predict.train(model_list$svmRadial, newdata = X_test)
pred_rf <- predict.train(model_list$rf, newdata = X_test)
pred_xgbT <- predict.train(model_list$xgbTree, newdata = X_test)
pred_xgbL <- predict.train(model_list$xgbLinear, newdata = X_test)
predict_ens1 <- predict(ensemble_1, newdata = X_test)
predict_ens2 <- predict(ensemble_2, newdata = X_test)# RMSE
pred_RMSE <- data.frame(ensemble_1 = RMSE(predict_ens1, y_test),
ensemble_2 = RMSE(predict_ens2, y_test),
LM = RMSE(pred_lm, y_test),
SVM = RMSE(pred_svm, y_test),
RF = RMSE(pred_rf, y_test),
XGBT = RMSE(pred_xgbT, y_test),
XGBL = RMSE(pred_xgbL, y_test))print(pred_RMSE)**
令人惊讶的是,xgbLinear
模型在测试集上的表现优于所有其他模型,包括我们的ensemble_1
和匹配ensemble_2
的性能
我们还观察到,一般来说,与训练集相比,在性能上存在差异。这是可以预料的。我们仍然可以尝试手动调整超参数,以减少一些过度拟合,但在这一点上,我相信我们已经在看不见的数据上实现了非常强大的性能,我将在未来的出版物中进一步优化。
我想展示的最后一件事是可变重要性。为了做到这一点,我将单独计算我们的xgbLinear
模型,表明我想保留变量重要性,然后绘制它:
**set.seed(123)xgbTree_model <- train(X_train,
y_train,
trControl = my_control,
method = “xgbLinear”,
metric = “RMSE”,
preProcess = c(“center”,”scale”),
**importance = TRUE)**plot(varImp(xgbTree_model))**
这里我们可以看到变量age
和cement
对混凝土的strength
预测的高度重要性。这是意料之中的,因为我们已经在最初的相关图中观察到它们之间的高度相关性。
使用age
的日志也让我们提高了可预测性(单独验证)。
注意图表中出现的一些“不重要”的特征。我们应该放弃他们吗?我们能否在不影响性能的情况下简化模型?如果我们出于任何原因需要一个更简单的模型,我们当然可以继续努力。
6)结论
这是一段不寻常的旅程!我们进行了大多数必要的步骤,以便执行一个完整而仔细的机器学习工作流程。尽管我们不必对从 csv 导入的原始数据进行大量的更改和转换,但我们确保理解了为什么以及我们应该做些什么。
此外,我能够展示一个人可以用 caret 和 caretEnsemble 做的有趣的工作,在做多种建模方面,快速和肮脏,并且能够快速比较模型性能。更高级的数据科学家和机器学习爱好者可能会将此作为第一稿,然后继续进行更高级的算法和精细的超参数调整,以获得额外的性能。为了这部作品,即使是基本配置,它也被证明是非常强大的。
在介绍中提到的书中,作者计算了预测值(使用具有 5 个隐含层的神经网络)和真实值之间的相关性,得到了 0.924 的分数。它还提到,与原始出版物(他的工作所基于的出版物)相比,这是一个重大的改进(原始出版物使用类似的神经网络获得了 0.885)
那么,我们是如何计算出与该书作者相同的相关分数的呢?
**pred_cor <- data.frame(ensemble_1 = cor(predict_ens1, y_test),
ensemble_2 = cor(predict_ens2, y_test),
LM = cor(pred_lm, y_test),
SVM = cor(pred_svm, y_test),
RF = cor(pred_rf, y_test),
XGBT = cor(pred_xgbT, y_test),
XGBL = cor(pred_xgbL, y_test))print(pred_cor)**
相当强劲的表现!
机器学习的贝叶斯超参数优化的概念解释
使用贝叶斯优化的高效超参数调整背后的概念
以下是机器学习超参数优化的四种常用方法,按效率递增的顺序排列:
- 手动
- 网格搜索
- 随机搜索
- 基于贝叶斯模型的优化
我很自豪我最近从手工搜索上升到了随机搜索,直到我在 Bergstra 等人的论文中发现了这张图片:
Validation Errors comparing random search and a model based approach on LFW (left) and PubFig83 (right)
这些图比较了图像分类神经网络的超参数优化的验证误差,灰色为随机搜索,绿色为贝叶斯优化(使用 Tree Parzen 估计器或 TPE)。越低越好:验证集误差越小通常意味着测试集性能越好,试验次数越少意味着投入的时间越少。显然,贝叶斯方法有显著的优势,这些图表,以及其他令人印象深刻的结果,让我相信是时候采取下一步,学习基于模型的超参数优化了。
贝叶斯超参数优化的一句话总结就是:建立目标函数的概率模型,用它来选择真实目标函数中最有希望评估的超参数。
如果你喜欢在很高的层次上操作,那么这句话可能就是你需要的全部。然而,如果你想了解细节,这篇文章是我试图概述贝叶斯优化背后的概念,特别是基于序列模型的优化(SMBO)与树 Parzen 估计(TPE)。抱着这样一种心态,你不知道一个概念,除非你能向别人解释它,我查阅了几篇学术论文 论文,并将尝试以一种(相对)容易理解的格式交流结果。
虽然我们经常可以在不了解机器学习方法如何工作的情况下实现它们,但我喜欢尝试并了解正在发生的事情,这样我就可以尽可能有效地使用这项技术。在后面的文章中,我将通过使用诸如 Hyperopt 之类的库在 Python 中使用这些方法,因此本文将为即将到来的实现奠定概念基础!
更新:这是一个简短的 Jupyter 笔记本,展示了在 Hyperopt Python 库中使用基于贝叶斯模型的优化的基础。
超参数优化
机器学习中超参数优化的目的是找到给定机器学习算法的超参数,这些超参数返回在验证集上测量的最佳性能。(与模型参数相反,超参数是由机器学习工程师在训练之前设置的。随机森林中的树的数量是超参数,而神经网络中的权重是在训练期间学习的模型参数。我喜欢把超参数看作是要调整的模型设置。)
超参数优化以等式形式表示为:
这里 f(x)表示在验证集上评估的要最小化的客观分数,例如 RMSE 或错误率;x*是产生最低分值的超参数集,x 可以取域 x 中的任何值。简单地说,我们希望找到在验证集指标上产生最佳分值的模型超参数。
超参数优化的问题在于,评估目标函数以找到分数是极其昂贵的。每次我们尝试不同的超参数时,我们都必须根据训练数据训练一个模型,根据验证数据进行预测,然后计算验证度量。由于大量的超参数和复杂的模型,如需要数天时间训练的集成或深度神经网络,这一过程很快就变得难以手动完成!
网格搜索和随机搜索比手动调整略好,因为我们建立了模型超参数网格,并在循环中自动运行训练-预测-评估循环,同时我们做更有成效的事情(如特征工程)。然而,即使这些方法也是相对低效的,因为它们不基于先前的结果选择下一个超参数来评估。**网格和随机搜索完全不了解过去的评估,**因此,经常花费大量时间评估“坏的”超参数。
例如,如果我们有下面的图表,分数越低越好,那么我们应该在哪里集中搜索呢?如果你说低于 200 个估计量,那么你已经有了贝叶斯优化的想法!我们希望关注最有希望的超参数,如果我们有评估记录,那么使用这些信息进行下一步选择是有意义的。
随机和网格搜索根本不关注过去的结果,而是在估计量的整个范围内继续搜索,即使很明显最优答案(可能)在一个小区域内!
贝叶斯优化
贝叶斯方法,与随机或网格搜索相反,跟踪过去的评估结果,它们使用这些结果来形成概率模型,将超参数映射到目标函数得分的概率:
在文献中,这个模型被称为目标函数的“代理”,用 p(y | x)表示。替代函数比目标函数更容易优化,贝叶斯方法通过选择在替代函数上表现最佳的超参数来寻找下一组超参数以在实际目标函数上进行评估。换句话说:
- 建立目标函数的代理概率模型
- 找到在代理上表现最好的超参数
- 将这些超参数应用于真正的目标函数
- 更新包含新结果的代理模型
- 重复步骤 2-4,直到达到最大迭代次数或时间
贝叶斯推理的目标是用更多的数据“减少错误”,这些方法通过在每次评估目标函数后不断更新替代概率模型来做到这一点。
在高层次上,贝叶斯优化方法是有效的,因为它们以知情的方式 **选择下一个超参数。**基本思路是:**多花一点时间选择下一个超参数,以便少调用目标函数。**实际上,选择下一个超参数所花费的时间与目标函数所花费的时间相比是无关紧要的。通过评估从过去的结果看起来更有希望的超参数,贝叶斯方法可以在更少的迭代中找到比随机搜索更好的模型设置。
如果从这篇文章中有什么可以借鉴的话,那就是基于贝叶斯模型的方法可以在更短的时间内找到更好的超参数,因为它们可以根据过去的试验推理出要评估的最佳超参数集。
作为对贝叶斯优化中发生的事情的一个很好的可视化描述,请看下面的图片(来源)。第一幅图显示了两次评估后对代理模型的初步估计——黑色表示相关的不确定性,灰色表示。显然,代理模型是对红色实际目标函数的一个很差的近似:
下图显示了 8 次评估后的代理函数。现在代理几乎完全匹配真正的函数。因此,如果算法选择最大化代理的超参数,它们将可能在真实评估函数上产生非常好的结果。
贝叶斯方法对我来说总是有意义的,因为它们的运作方式与我们非常相似:我们形成对世界的初始看法(称为先验),然后我们根据新的经验更新我们的模型(更新后的模型称为后验)。贝叶斯超参数优化采用该框架,并将其应用于寻找模型设置的最佳值!
基于序列模型的优化
基于序列模型的优化(SMBO)方法(SMBO) 是贝叶斯优化的形式化。序列是指一个接一个地运行试验,每次都通过应用贝叶斯推理和更新概率模型(替代)来尝试更好的超参数。
基于模型的超参数优化有五个方面:
- 要搜索的超参数域
- 一个目标函数,接受超参数并输出我们想要最小化(或最大化)的分数
- 目标函数的代理模型
- 称为选择函数的标准,用于评估接下来从替代模型中选择哪个超参数
- 由算法用来更新代理模型的(分数,超参数)对组成的历史
SMBO 方法有几种变体,在步骤 3-4 中与有所不同,即它们如何构建目标函数的替代函数以及用于选择下一个超参数的标准。替代模型的几种常见选择是高斯过程、随机森林回归和 Tree Parzen 估计量(TPE),而第 4 步最常见的选择是预期改进。在本帖中,我们将重点关注 TPE 和预期的改进。
领域
在随机搜索和网格搜索的情况下,我们搜索的超参数的域是一个网格。随机森林的示例如下所示:
对于基于模型的方法,域由概率分布组成。与网格一样,这使我们能够通过在我们认为真正的最佳超参数所在的区域放置更大的概率来将领域知识编码到搜索过程中。如果我们想将上面的网格表示为概率分布,它可能看起来像这样:
这里我们有一个均匀的,对数正态的,正态分布。这些由先前的实践/知识提供(例如学习率域通常是几个数量级的对数正态分布)。
目标函数
目标函数接受超参数并输出我们想要最小化(或最大化)的单个实值分数。作为示例,让我们考虑为回归问题构建随机森林的情况。我们想要优化的超参数显示在上面的超参数网格中,最小化的分数是均方根误差。我们的目标函数看起来会像(用 Python 写的):
虽然目标函数看起来很简单,但是计算起来非常昂贵!如果可以快速计算目标函数,那么我们可以尝试每一个可能的超参数组合(就像网格搜索一样)。如果我们使用一个简单的模型,一个小的超参数网格和一个小的数据集,那么这可能是最好的方法。然而,在目标函数可能需要几个小时甚至几天来评估的情况下,我们希望限制对它的调用。
基于贝叶斯模型的优化的整个概念是通过基于对评估函数的先前调用仅选择最有希望的一组超参数进行评估来减少目标函数需要运行的次数。基于称为代理的目标函数的模型选择下一组超参数。
代理函数(概率模型)
代理函数也称为响应面,是使用以前的评估构建的目标函数的概率表示。这有时被称为响应面,因为它是超参数到目标函数得分概率的高维映射。下面是一个只有两个超参数的简单示例:
Response surface for AdaBoost algorithm (Source)
有几种不同形式的替代函数,包括高斯过程和随机森林回归。然而,在本帖中,我们将重点关注树形结构的 Parzen 估计量,如 Bergstra 等人在论文“超参数优化算法”中提出的。这些方法的不同之处在于它们如何构造代理函数,我们稍后会解释。首先我们需要谈谈选择函数。
选择功能
选择函数是从替代函数中选择下一组超参数的标准。最常见的标准选择是预期改进:
这里,y*是目标函数的阈值,x 是建议的超参数集,y 是使用超参数 x 的目标函数的实际值,p (y | x)是表示给定 x 时 y 的概率的代理概率模型。如果这都有点多,简单地说,**目标是最大化相对于 x 的预期改进。**这意味着在代理函数 p(y | x)下找到最佳超参数。
如果 p (y | x)处处为零,则 y < y*, then the hyperparameters x are not expected to yield any improvement. If the integral is positive, then it means that the hyperparameters x are expected to yield a better result than the threshold value.
树形结构 Parzen 估计器(TPE)
现在让我们回到代理函数。SMBO 的方法不同之处在于它们如何构造代理模型 p(y | x)。树形结构的 Parzen 估计器通过应用 Bayes 规则建立模型。它不是直接表示 p( y | x ),而是使用:
Bayes Rule in Action!
p (x | y)是给定目标函数分数的超参数的概率,其依次被表示为:
其中 y < y* represents a lower value of the objective function than the threshold. The explanation of this equation is that we make 超参数的两种不同分布:一种是目标函数值小于阈值l(x),另一种是目标函数值大于阈值 g(x) 。
让我们更新我们的随机森林图,以包括一个阈值:
现在我们为估计量的数量构造两个概率分布,一个使用产生低于阈值的值的估计量,另一个使用产生高于阈值的值的估计量。
直觉上,我们似乎想从 l(x) 而不是从 g(x) 中得出 x 的值,因为这种分布仅基于产生低于阈值的分数的 x 的值。事实证明,这正是数学上所说的!通过贝叶斯法则和一些替换,期望改善方程(我们试图最大化)变成:
最右边的术语是最重要的部分。这意味着预期改善与比率 l(x) / g(x) 成比例,因此,为了最大化预期改善,我们应该最大化该比率。我们的直觉是正确的:我们应该画出在 l(x) 下比在 g(x) 下更可能出现的超参数值!
树形结构的 Parzen 估计器的工作原理是从 l(x) 中抽取样本超参数,根据 l(x) / g(x) 对它们进行评估,并返回在 l(x) / g(x) 下产生最高值的集合,该集合对应于最大的预期改进*。*然后根据目标函数评估这些超参数。如果代理函数是正确的,那么这些超参数应该在评估时产生更好的值!
预期改进标准允许模型平衡勘探和开采。 l(x) 是一个分布,而不是一个单一的值,这意味着绘制的超参数可能很接近,但不完全是预期改善的最大值。此外,因为代理只是目标函数的估计,所以当评估时,所选择的超参数可能实际上不会产生改进,并且代理模型将必须被更新。这种更新是基于当前代理模型和目标函数评估的历史来完成的。
历史
每当该算法提出一组新的候选超参数时,它用实际的目标函数对它们进行评估,并将结果记录在一对(得分、超参数)中。这些记录构成了的历史。该算法使用历史来构建 l(x) 和 g(x) 以得出随着每次迭代而改进的目标函数的概率模型。
这是贝叶斯法则在起作用:我们对目标函数的代理有一个初始估计,当我们收集到更多的证据时,我们会更新这个估计。最终,通过对目标函数进行足够的评估,我们希望我们的模型准确地反映目标函数,并且产生最大预期改进的超参数对应于最大化目标函数的超参数。
综合考虑
基于序列模型的方法如何帮助我们更有效地搜索超参数空间?因为该算法提出了用于评估的更好的候选超参数,所以目标函数的分数比随机或网格搜索提高得更快,从而导致目标函数的整体评估更少。
即使该算法通过最大化期望的改进花费更多的时间来选择下一个超参数,这在计算成本方面比评估目标函数便宜得多。在一篇关于使用 SMBO 和 TPE 的论文中,作者报告了寻找下一组候选超参数需要几秒钟,而评估实际目标函数需要几个小时。
如果我们使用更明智的方法来选择下一个超参数,这意味着我们可以花更少的时间来评估糟糕的超参数选择。此外,使用树形结构 Parzen 估计器的基于序列模型的优化能够在相同次数的试验中找到比随机搜索更好的超参数。换句话说,我们得到
- 减少超参数调整的运行时间
- 测试集上更好的分数
希望这能让你相信基于贝叶斯模型的优化是一项值得尝试的技术!
履行
幸运的是,现在有很多库可以用 Python 来做 SMBO。 Spearmint 和 MOE 使用高斯过程作为替代,hyperpt使用树形结构 Parzen 估计器, SMAC 使用随机森林回归。这些库都使用预期改进标准从代理模型中选择下一个超参数。在后面的文章中,我们将看看如何在 Python 中使用 Hyperopt,已经有几篇好的文章和代码示例供学习。
结论
基于贝叶斯模型的优化方法构建目标函数的概率模型,为下一组待评估的超参数提出更明智的选择。SMBO 是贝叶斯优化的形式化,它在为机器学习模型寻找最佳超参数方面比随机或网格搜索更有效。
基于序列模型的优化方法在构建代理方面有所不同,但它们都依赖于来自先前试验的信息来为下一次评估提出更好的超参数。Tree Parzen 估计器是一种使用贝叶斯推理来构建代理模型的算法,并且可以使用预期改进来选择下一个超参数。
Python 中有许多实现 SMBO 的库,我们将在后续文章中探讨。这些概念一开始有点难,但是理解它们将允许我们更有效地使用基于它们构建的工具。我想说的是,我仍在努力解决细节问题,如果我犯了错误,请让我知道(礼貌地)!
要了解更多详细信息,以下文章非常有用:
一如既往,我欢迎反馈和建设性的批评。可以在推特上找到我
神经网络简史
“从我们个人设备内部贫瘠的土地上,传来了那些有朝一日将成为我们霸主的数字仆人偷偷哼唱的颂歌”
毫不奇怪,神经网络的想法最初是作为大脑中神经元如何运作的模型出现的,被称为“连接主义”,并使用连接电路来模拟智能行为。1943 年,神经生理学家沃伦·麦卡洛克和数学家沃尔特·皮茨用一个简单的电路描绘了它。唐纳德·赫布(Donald Hebb)在他的著作《行为的组织》(The Organization of Behaviour,1949)中进一步发展了这一观点,提出神经通路在每次连续使用后都会加强,尤其是在倾向于同时放电的神经元之间,从而开始了量化大脑复杂过程的漫长旅程。
作为神经网络前身的两个主要概念是
- “阈值逻辑”——将连续输入转换为离散输出
- “赫比学习”(hebbian Learning)——一种基于神经可塑性的学习模式,由唐纳德·赫比(Donald Hebb)在其著作《行为的组织》(The Organization of Behaviour)中提出,通常用一句话来概括:“一起放电的细胞,连接在一起。”
两者都是在 20 世纪 40 年代提出的。在 20 世纪 50 年代,当研究人员开始尝试将这些网络转换到计算系统上时,第一个 Hebbian 网络于 1954 年在麻省理工学院成功实现。
大约在这个时候,康奈尔大学的心理学家弗兰克·罗森布拉特(Frank Rosenblatt)正致力于理解苍蝇眼中相对简单的决策系统,这些系统是苍蝇逃跑反应的基础和决定因素。为了试图理解和量化这一过程,他在 1958 年提出了感知机的概念,称之为 Mark I 感知机。这是一个具有简单输入输出关系的系统,以麦卡洛克-皮茨神经元为模型,由神经科学家沃伦·s·麦卡洛克和逻辑学家沃尔特·皮茨在 1943 年提出,以使用线性阈值门来解释大脑中复杂的决策过程。麦卡洛克-皮茨神经元接受输入,进行加权求和,如果结果低于阈值,则返回“0”,否则返回“1”。
A McCulloch-Pitts neuron
Mark I 感知器的优点在于,它的权重可以通过连续传递的输入来“学习”,同时最小化期望输出和实际输出之间的差异。
First known implementation of a Mark I Perceptron. The machine was connected to a camera that used 20×20 cadmium sulfide photocells to produce a 400-pixel image. The main visible feature is a patchboard that allowed experimentation with different combinations of input features. To the right of that are arrays of potentiometers that implemented the adaptive weights.[wiki]
一个主要的缺点?这种感知器只能学习分离线性可分的类,使得简单但非线性的异或电路成为不可逾越的障碍。
尽管使用机器学习来量化除大脑之外的决策系统出现了混乱和有些令人不满意的情况,但今天的人工神经网络只不过是这些感知机的几层。
大约在这个时候,神经网络开始迅速发展。1959 年,伯纳德·维德罗和马尔西安·霍夫在斯坦福开发了第一个成功应用于现实世界问题的神经网络。这些系统因使用了多种自适应线性元件而被命名为 ADALINE 和 MADALINE,后者是专门为消除电话线中的噪声而设计的,至今仍在使用(!).然而,这些人工神经元与感知器的不同之处在于它们返回的输出,在这种情况下是加权输入。
正如历史上人工智能技术的每一次小进步一样,这些早期的成功导致了对神经网络能力和潜力的越来越多的炒作,而研究人员却遇到了一个又一个的路障。在围绕这些“思维机器”的宣传达到高潮时,纽约时报发表了这篇关于神经网络潜力的文章,而这段视频也在大约同一时间发布。
就像之前的几次“千钧一发”一样,我们仍然没有像我们一直喜欢相信的那样(或者恐惧,取决于你如何看待它)接近喷出有意识的人造生命。出现的问题之一是运行这些网络所需的不切实际的长运行时间,因为这是 60 年代,除了它不能学习简单的布尔异或电路。
1969 年,随着麻省理工学院人工智能实验室创始人马文·明斯基和实验室主任西蒙·派珀特合著的《感知机》一书的出版,这一切都告一段落。这本书最终认为,罗森布拉特对神经网络的单一感知方法不能有效地转化为多层神经网络。基于最终输出来评估跨层分布的神经元的权重的正确相对值将花费若干次(如果不是无限次的话)迭代,并且将花费非常长的时间来计算。
明斯基在他的文章中阐述了神经网络的这些和其他问题,并有效地引导了更大的科学界,最重要的是资助机构得出结论,在这个方向上的进一步研究是没有结果的。这篇文章的影响是巨大的,在接下来的 10-12 年里,没有人在当时最大的研究机构中,也没有人在较小的研究机构中,承担任何以注定失败的神经网络为前提的项目。现在被称为“人工智能冬天”的时代开始了。
这十年漫长冬天的解冻始于 1982 年,当时 Jon Hopfield 在美国国家科学院提交了他的论文,该论文后来被称为 Hopfield Net 同年,在美日合作/竞争神经网络会议上,日本宣布打算开始其第五代神经网络研究。这使得资金从一个害怕被抛在后面的国家的金库中重新开始流动。不久,美国物理研究所于 1985 年建立了“计算中的神经网络”年会,随后由电气和电子工程师协会(IEEE)于 1987 年召开了第一次神经网络国际会议。
然而,这是对自 60 年代以来就存在的概念的重大重新发现,帮助神经网络走出了它过早的坟墓。反向传播,一种自 60 年代以来由研究人员设计并持续发展到人工智能冬天的方法,是一种基于直觉的方法,随着人们在事件链中走得更远,它将每个事件的重要性降低。第一个看到它们在神经网络方面的潜力并解决如何将其转化为 MLP 氏症的问题的人是保罗·沃博斯,他部分受到了神经网络在人类思维中的应用以及弗洛伊德关于学分分配逆向流动的工作的启发,写了一篇博士论文阐述了它们的重要性。然而,直到 1985 年帕克在麻省理工学院发表了一份关于他的工作的报告,这项工作才被社区中的任何人注意到。只是在被 Rumelhart、Hinton 和 Williams 重新发现并在一个清晰而详细的框架中重新发表后,这项技术才在社区中引起了轰动。这些作者还在后来的文本中提到了明斯基在 1969 年的出版物中列出的具体缺点。
反向传播和梯度下降形成了神经网络的主干和动力。虽然梯度下降不断更新权重和偏差并将其移向成本函数的最小值,但反向传播通过权重和偏差来评估成本的梯度,梯度下降使用其大小和方向来评估权重和偏差参数的校正大小和方向。
A simple visual description of the movement towards the minima of a 2d function. The step-size of jump is determined by the value of the gradient at each point.
因此,到了 20 世纪 90 年代,神经网络肯定又回来了,这一次真正抓住了世界的想象力,并最终达到了它的期望,如果不是超越的话。然而,我们再次向人工智能提出同样的问题,并把我们所有人的恐惧投射到它身上,然而,我们再次比我们想象的更远离向我们的数字霸主低头。
如果你喜欢阅读这样的故事,并想支持我的写作,请考虑注册成为一名灵媒会员。每月 5 美元,你可以无限制地阅读媒体上的所有报道。如果你使用 我的链接 注册,我会收到一点佣金。
拓扑数据分析的一个具体应用
今天,我将介绍一个机器学习应用拓扑数据分析 (TDA),这是一个快速发展的数据科学领域,它利用拓扑来改进数据分析。这很大程度上是从我的一个项目中的得到的灵感。
太好了!等等……TDA 是什么?
我将首先简要回顾一下 TDA 的基本情况。感兴趣的读者可能还想看看的其他 故事(以及其中的所有参考文献)了解更多细节。
TDA 是一种基于数学的理论,旨在使用数据的拓扑来表征数据,而是通过计算拓扑性质的特征来完成的。最常见的是持久性图,它采用对角线上方平面中一组点的形式。
Example of persistence diagram computed with the library Gudhi. Source: http://gudhi.gforge.inria.fr/python/latest/persistence_graphical_tools_user.html
每个这样的点代表数据的一个拓扑特征(如一个连接的组件、一个孔或一个空腔)。此外,点到对角线的距离作为相应特征的重要性的指示,通常的解释是靠近对角线的点可能是由于噪声。
这样的图的计算需要一个过滤,也就是一个增长空间的序列:序列中的每个空间都包含在下一个中。例如,给定一个点云,一个可能的过滤是计算以半径递增的点为中心的球的联合。
Example of union of balls filtration.
这个想法是,对于序列中的每个空间,记录一个拓扑特征是在那个空间中被创建还是被破坏。例如,如果我们考虑球过滤的联合,可能发生的情况是,对于某些半径,球联合包含一个孔,该孔持续一段时间,直到当球具有足够大的半径时最终被填满,这正是上面显示的过滤中发生的情况。然后,这些半径可用作坐标,在平面上创建一个代表该孔的点。
听起来不错,但是…我想要一份申请!
持久性图在数据分析的各个领域都有很多应用。在这篇笔记中,我将介绍几何处理中的一个可视化应用,即 3D 形状分割。
3D 形状通常在计算机中存储为一组点、边和三角形。分割的目标是为每个形状的每个点提供标签。例如,如果给你一堆代表人类的 3D 形状,分割的目标是成功地为每个点分配它所属的身体部位(“躯干”、“手臂”、“腿”…)。
Segmented 3D human shapes. The different colors correspond to the different labels or parts. Source: https://people.cs.umass.edu/~kalo/papers/LabelMeshes/
这个问题的难点在于,只给你点坐标,这是很差的特征。事实上,用一个点的坐标来描述它是不可能的,因为它们依赖于 3D 形状的嵌入或姿态。例如,想象两个人形,其中一个举起右手,另一个没有;人类是相同的,只是他们的姿势不同。然后,这两个形状的右手点会有很大的不同,即使它们共享相同的标签。
TDA 来救援了!
这就是持久性图发挥作用的地方。由于它们的拓扑性质,持久性图是固有的,这意味着它们不依赖于 3D 形状的嵌入或姿态。因此,它们是点要素的良好候选对象。为此,我们需要定义一个内在过滤。
这可以通过测地线距离来实现。3D 形状上两点之间的测地线距离是该形状上两点之间最短路径的长度。你可以把它想成一只蚂蚁从第一个点到第二个点所走的路径长度。这个距离显然是固有的,因为蚂蚁行走的路径与 3D 形状的姿态无关。
Example of geodesic distances computed for various pair of points on a 3D camel shape. Source: http://www.numerical-tours.com/matlab/shapes_2_bendinginv_3d/
测地线距离可以用来定义测地线球。半径为r0 且以点 x 为中心的测地线球,就是到 x 的测地线距离小于或等于 r 的形状的点集。同样,通过使 r 从 0 增加到无穷大,我们使测地线球从单个的 {x} 增长到整个形状本身,这给了我们一个内在的过滤。现在,为了计算相应的持续图,我们记录球中发生拓扑事件的半径,并将它们用作坐标。在 3D 形状的情况下,拓扑事件是非常有限的:由于 3D 形状是连接的表面,所以它们的固有维度是 2(实际上,3D 形状局部看起来像平面),唯一可能发生的拓扑事件是球中出现或填充孔。例如,看看下面 3D 手形上显示的过滤。
Example of geodesic ball filtration computed for a point located on the palm of a 3D hand shape.
增长的测地线球显示为红色,而形状的其余部分显示为蓝色。对于前三个半径,测地线球没有有趣的拓扑结构:它看起来就像一个圆盘。然而,对于第四个半径,五个手指中的每一个都在测地线球中创建了一个洞:出现了五个拓扑事件。它们持续到第五个半径,最终在第六个半径被填满。相应的持久性图,如下图所示,包含五个点。
Each point of the persistence diagram corresponds to a specific finger of the shape.
更有趣的是,如果我对位于形状另一部分的点应用相同的过程,那么图表将会不同。例如,让我们考虑位于中指上的点:
Geodesic ball filtration computed for a point located on the middle finger.
所有手指将再次在测地线球中创建孔,但半径不同。例如,对应于中指的孔出现并被填充的时间比第一次过滤早得多。在余辉图中,相应的点离其他点较远。
The point corresponding to the middle finger (pink) is far from the others.
一般来说,根据 3D 形状点(用于计算图)所属的位置或部分,持久性图点具有不同的配置。这说明了这样一个事实,持久化图是分段的精确描述符。我实现了计算这种图的代码:如果你想试试的话,请看我的 Github。
该学习了!
终于!既然我们已经有了点的一个好的特征或描述符,我们就可以开始机器学习(ML)了。
还是我们?
持久性图的一个大问题是它们的非结构化形式:持久性图是可能包含不同数量的点的集合。它们不像传统的欧几里得向量那样容易处理,传统的欧几里得向量是 ML 算法的常见食物。这就是为什么目前 TDA 社区正致力于寻找在 ML 中处理持久性图的方法。到目前为止,两种主要的方法要么是从图中计算矢量(比如持久图像或风景),要么是在图上定义内核并使用内核化的 ML 算法(比如 PCA 或 SVM)。详见这个故事。
我在一个兼容 scikit-learn 的 python 包中实现了大部分方法。我再次向感兴趣的读者推荐我的 Github 。多亏了这个软件包,所有的方法都可以在一个大的交叉验证过程中进行比较和使用。在我的笔记本中,我用它来分割一堆代表不同大小和形状的飞机的 3D 表面(见下面的代码样本)。最终准确率可以达到 90%,考虑到任务的难度,这已经相当不错了!
**import** **sklearn_tda** **as** **tda**
**from** **sklearn.pipeline** **import** Pipeline
**from** **sklearn.svm** **import** SVC
**from** **sklearn.ensemble** **import** RandomForestClassifier
**from** **sklearn.neighbors** **import** KNeighborsClassifier
*# Definition of pipeline*
pipe = Pipeline([("Separator", tda.DiagramSelector(limit=np.inf, point_type="finite")),
("Rotator", tda.DiagramPreprocessor(scalers=[([0,1], tda.BirthPersistenceTransform())])),
("TDA", tda.PersistenceImage()),
("Estimator", SVC())])
*# Parameters of pipeline. This is the place where you specify the methods you want to use to handle diagrams*
param = [{"Rotator__use": [**False**],
"TDA": [tda.SlicedWassersteinKernel()],
"TDA__bandwidth": [0.1, 1.0],
"TDA__num_directions": [20],
"Estimator": [SVC(kernel="precomputed")]},
{"Rotator__use": [**False**],
"TDA": [tda.PersistenceWeightedGaussianKernel()],
"TDA__bandwidth": [0.1, 1.0],
"TDA__weight": [**lambda** x: np.arctan(x[1]-x[0])],
"Estimator": [SVC(kernel="precomputed")]},
{"Rotator__use": [**True**],
"TDA": [tda.PersistenceImage()],
"TDA__resolution": [ [5,5], [6,6] ],
"TDA__bandwidth": [0.01, 0.1, 1.0, 10.0],
"Estimator": [SVC()]},
{"Rotator__use": [**False**],
"TDA": [tda.Landscape()],
"TDA__resolution": [100],
"Estimator": [RandomForestClassifier()]},
{"Rotator__use": [**False**],
"TDA": [tda.BottleneckDistance()],
"TDA__wasserstein": [1],
"TDA__delta": [0.1],
"Estimator": [KNeighborsClassifier(metric="precomputed")]}
]
最后一句话…
几何处理只是 TDA 众多可能应用中的一种。这个领域非常活跃,因为它连接了从代数拓扑到计算机科学的不同数学领域,越来越多的人正在成为 TDA 爱好者。不要错过火车!;-)
语言与代码的融合
你好,我叫托马斯,我叫托马斯,名字是(x):返回托马斯。在我的生活中,我学习了多种语言,每种语言都有自己的软木塞、语法和实用性,并且每种语言都有不同的学习风格。在伦敦的高中学习法语三年,师从老师,互动语言实验室,以及在法国南部/中部的暑期沉浸式项目。在南非美丽的 Matlerekeng 和 Enable 村,我在和平队服务期间,通过现场互动和与讲母语的人在小组中进行长达一小时的交谈,学会了 Sepedi,也被称为 Northern Sotho。现在,面对一种新的语言和新的方法,我开始学习数据科学的语言(如 Python、SQL 和统计学等)。)在为期 12 周的训练营。这些经历中的每一种都是用不同的语言教给我的,带来了新的学习方法和新的问题,每一种都提出了自己的挑战和不断增长的知识,但随着我的技能不断扩展,它们之间的相似之处都出现了。
如果让你选择学习法语、Sepedi 和一门计算机语言,一开始你可能会认为你必须用不同的方式来学习。然而,我的经验告诉我,虽然个人的教学风格可能不同,但效果最好的整体方法几乎是一致的。它们都是从教你较小的细节开始的,这样当你接近较大的短语时,你就知道在引擎盖下发生了什么。在口语中,这可以是知道我、我、她、他、我们之间的区别,而 python 代码可以学习 import x as、统计数学以及==、=、or!=.事实上,理解这三种语言中发生的事情的最基本的方法是能够翻译成你的母语。对于编码来说,就是在你的代码中留下尽可能多的易于阅读的注释,以便其他人理解你的目标和方法。对于像法语和西班牙语这样的语言来说,那就是知道如何说“我不理解”。“这是英国的还是法国的传统?”(我不明白。用英语或传统法语怎么说?或者“Aowa,ga re kwisisa。ke sekgowa ke __ ke English ne?”(我不明白。用英语翻译是什么?).所有这些都为学习者提供了一种将新语言与母语联系起来的方法。在学习了基本的日常用语后,下一步的学习是沉浸在语言中,无论是在教室里说法语,和只说西班牙语或支离破碎的英语的家庭一起生活,还是从周一到周五朝九晚五地被代码包围。这种沉浸感不仅迫使你为了生存而学习,有时是字面上的,而且让你学会一门语言的真正本质。我所说的语言的“真正本质”是指,当一种语言被教授时,大部分时间是在教科书/上层阶级的术语中完成的,这通常意味着当从教室带到现实世界时,术语会发生变化。当你完全沉浸其中时,你就学会了事物的速记,学会了语气和语境是如何改变一个词的整个含义,并把你和你周围的文化联系起来。沉浸的最终结果是,单词或代码成为第二天性,即使你远离它们多年,当再次被扔进文化中时,你的大脑总会有一部分记得。
在口语中,单词的变化取决于性别、连接词和时态。例如,在法语 to 中,当从 I 到 we 时,它从 Je 到 Nous,在 Sepedi 中,它从 Rena re 到 Nna ke。虽然计算机代码不会像语言那样改变,但它会根据相似的变量改变,只是名字不同而已。对于编码来说,它是列表类型、For 或 while 循环、if-else 语句和一系列计算机软件包,每个软件包在解释手头的情况时都有其特定的作用,就像口语动词表一样。
虽然罗曼语、班图语和计算机语言初看起来就像相隔千里的苹果和橙子一样亲密,并且创造了几个世纪,但这三种语言有几个重叠的特征。也许最常见的字符串是它们在直接翻译成简单英语时的字面意思。一个简单的例子就是说“天气很热。都 85 度了!”必须用每种语言一步一步清晰地拼写/说出。
法语:这是真理。这是四分之一夜!
天气很热。它是四十五度
塞佩迪:莱霍诺加油,加油,加油!
今天是个大热天。已经 85 度了!
对于 Python:
temperature=85
if temperature >= 85:
return "It is hot. It is " +str(tempeture) + "degrees!"
else if temperature <85:
return "It is not so hot. It is" +str(tempeture) + "degrees."
Output[] It is hot. It is 85 degrees!
在一个充斥着来自不同大洲和不同终端的数千种语言的世界里,人们常常忘记这些语言是如何容易和流畅地连接在一起的。他们可能没有相同的单词或起源,但当你了解他们每个人时,你可以看到他们在措辞、情景变化以及他们想要理解对方单词方面的相似之处。最后,虽然从表面上看,我们所有的交流可能看起来不同,但他们都试图与他人联系,帮助他人了解彼此的世界正在发生什么。
关于深度学习的对话
有人无意中听到两个人谈论深度学习,让我知道每一个小细节。其中一个完全反对深度学习,另一个不仅是该领域的捍卫者,而且真的知道这个主题。
为了保密,我称第一个人为 A 先生(“憎恨者”)和 B 女士(“专家”)。
这是 A 先生:
嗨!
这位是 B 女士:
嗨!
甲先生:你好乙!你好吗
B 女士:棒极了 A!很高兴见到你。我没想到会在深度学习会议上见到你。
A 先生:是的,我来看看这些疯子在说些什么,我是对的。深度学习烂透了。这只是我在大学学习的关于神经网络的老东西,现在你添加更多的层,就是这样!没什么有趣的东西可看。
女士 B:哇,这是一个大的声明,我很抱歉你看到这样的事情。实际上,深度学习只是人工智能世界中正在发生的事情的一个品牌。你可以称之为“炒作”,但那里有非常重要的发展。你想来我的电脑吗?我带你去看。
我不知道重点,但是我现在没有别的地方可去,我们走吧。
B 女士:那么,让我们从基础开始,你对深度学习了解多少?
答:我读到过,它们是一些模拟我们大脑工作方式的算法,这就是“神经网络”这个名称的来源,我们的大脑。他们找到了一种方法将其抽象成数学、微积分和代码。然后,有了它,系统可以像我们一样学习,或者他们这么说,使用这些老式的神经网络来解决系统遇到的一些问题。哦,顺便说一下,他们不知道如何解释他们的模型,只是另一个黑盒。
B 女士:好的。我想你可能在读一些关于深度学习的奇怪的东西。我从基础开始。在机器学习的上下文中,“学习”一词描述了一个自动搜索过程,以更好地表示您正在分析和研究的数据。看看我在网上找到的这个例子:
假设我告诉你,我想让你画一条线,将这个图的蓝色圆圈和绿色三角形分开:
你会怎么做?
A 先生:再问一下线的定义是什么?
女士 B:让我们说是直的一维图形,没有厚度,在两个方向上无限延伸。
A:好的,如果是那样的话,这是一个不可能完成的任务。我不能在那里放一条线。
B 女士:如果我现在展示这张照片,并请你也这样做,你会说什么?
A:哦,那很简单,中间有一条线就行了。但这是欺骗,这是一个不同的数据集。这一行应该是这样的:
B 女士:很好,但这实际上是我之前介绍过的同一个数据集。
A 先生:什么?不,另一个是圆形的,这不一样。
B 女士:我给你解释一下。在这种情况下,我做了一个坐标转换,所以我们可以用一种我们可以画这条线的方式来绘制或表示这些数据。数据是相同的,但是表示是不同的。碰巧的是,在新的表示中,画这条线是一项简单的任务。
A 先生:好的,我明白你的意思。但是这和深度学习有什么关系呢?还是机器学习?
B 女士:深度学习是机器学习的一个子集。而是表征学习中一个非常特殊的子集。深度学习使我们能够创建一个系统,一个程序,它可以搜索不同的表示(在这种情况下是坐标变化),然后找到一种方法来计算类别被正确分类的百分比,当我们这样做时,我们正在进行深度学习,当然还有机器学习。
A 先生:听起来很棒。但是我们几十年前看到的老式神经网络呢?为什么现在有这么重要?以及它们在深度学习中的作用是什么?
B 女士:这是一个非常好的问题。我们可以将深度学习定义为使用不同类型的神经网络的表示学习,并优化网络的超参数,以获得(学习)我们数据的最佳表示。但是为什么是神经网络呢?它们非常灵活,让我们找到高度非线性数据的有用表示,就像我之前给你展示的那样。这个概念并不新鲜,但我们现在用来构建它们的工具与过去非常不同。他们拥有人工智能和机器学习领域的所有重大进步。
A 先生:它们是相同的神经网络,但唯一不同的是工具?比如编程语言?
B 女士:在某种程度上这是真的。但是还有更多。直到 2000 年代末,我们仍然缺少一种可靠的方法来训练非常深度的神经网络。我们多年来一直在研究这一理论,但现在,随着几项重要的理论和算法改进的发展,硬件的进步,以及数据的指数级生成和积累,深度学习自然而然地适应了这一缺失,从而改变了我们进行机器学习的方式。现代语言允许我们对这些理论部分进行编程,借助分布式计算和大数据的力量,我们成功创造了这场革命。
A 先生:听起来很有趣。你提到的这些理论上的进步和改进是什么?
B 女士:它们来自全世界多年的调查。有些来自大型大学或公司,但也有来自开源世界的巨大贡献。没有这些花里胡哨的补助金什么的。实际上我找到了一个时间线可以帮我解释给你听。看一看:
你是对的,这是一个古老的理论。但这并不意味着它不再相关。从那里我可以说反向传播的思想,网络参数的更好初始化,更好的激活函数,辍学的概念,以及一些类型的网络,如卷积神经网络,残差网络,区域基 CNN,递归神经网络和生成对抗网络,是我们在深度学习领域取得的最重要的进展之一。我希望我能有时间向你们解释所有的问题,但遗憾的是,我必须赶去参加下一个会议!
答:好的,现在我想我更明白“深度学习”是怎么回事了。你从没告诉我深度学习这几个字的意思。
B 女士:你说的对!深度学习中的深度并不是指通过这种方法实现的任何一种更深入的理解;更确切地说,它代表了连续层表示的思想。像这样:
而学习就是我之前告诉你的,它是一个自动搜索过程,以更好地表示我们拥有的数据,目标是理解模式,做出预测,并对我们周围的世界进行建模。
甲先生:谢谢乙!在离开我之前,你能推荐一些关于这个主题的好读物吗?
B 女士:当然可以!我会有一份文件,让我找一下…在这里!请写下它们,并在你离开后锁上门。很高兴见到你!回头再聊!
[## 如何训练你的深度神经网络
为了有效地训练深度神经系统,深度学习中有一些特定的实践是非常值得推荐的。
rishy.github.io](http://rishy.github.io/ml/2017/01/05/how-to-train-your-dnn/) [## 用于视觉识别的 CS231n 卷积神经网络
斯坦福 CS231n 课程材料和笔记:视觉识别的卷积神经网络。
cs231n.github.io](http://cs231n.github.io/neural-networks-2/#init) [## 理解神经网络中的激活函数
最近,我的一个同事问了我几个类似“为什么我们有这么多激活功能?”,“为什么是…
medium.com](https://medium.com/the-theory-of-everything/understanding-activation-functions-in-neural-networks-9491262884e0) [## 激活函数:神经网络
Sigmoid,tanh,Softmax,ReLU,Leaky ReLU 解释!!!
towardsdatascience.com](/activation-functions-neural-networks-1cbd9f8d91d6) [## 为了学得更好而学得更少——在(深度)机器学习中辍学
在这篇文章中,我将主要讨论神经网络中的辍学概念,特别是深度网络,然后是…
medium.com](https://medium.com/@amarbudhiraja/https-medium-com-amarbudhiraja-learning-less-to-learn-better-dropout-in-deep-machine-learning-74334da4bfc5) [## 使用 Python 进行深度学习
我见过的对深度学习最清晰的解释…阅读是一种乐趣。
www.manning.com](https://www.manning.com/books/deep-learning-with-python) [## 深度学习基础
关于这门课,上一堂速成课,学习内容是什么,以及如何学习更多。深度学习…
cognitiveclass.ai](https://cognitiveclass.ai/courses/introduction-deep-learning/) [## Python 中的深度学习| DataCamp
深度学习是机器人等不同领域中最令人兴奋的能力背后的机器学习技术…
www.datacamp.com](https://www.datacamp.com/courses/deep-learning-in-python) [## 深度学习的“怪异”介绍
有关于深度学习的惊人介绍、课程和博文。但这是一种不同的介绍…
towardsdatascience.com](/a-weird-introduction-to-deep-learning-7828803693b0) [## 主页
我们想邀请您在 3 月 26 日至 29 日的 GPU 技术大会上加入 Deep Cognition 的团队,展位号为 1035…
deepcognition.ai](http://deepcognition.ai/) [## 使用 Apache Spark 进行深度学习—第 1 部分
第一部分全面讨论了如何使用 Apache Spark 进行分布式深度学习。这一部分:什么是火花…
towardsdatascience.com](/deep-learning-with-apache-spark-part-1-6d397c16abd) [## 使用 Apache Spark 进行深度学习—第 2 部分
第二部分全面讨论了如何使用 Apache Spark 进行分布式深度学习。我将完全专注于…
towardsdatascience.com](/deep-learning-with-apache-spark-part-2-2a2938a36d35) [## deeplearning.ai
探索 AI 前沿。
www.deeplearning.ai](https://www.deeplearning.ai) [## 西拉伊·拉瓦尔
我是西拉杰。我正在为激励和教育开发人员构建人工智能而奋斗。游戏、音乐、聊天机器人…
www.youtube.com](https://www.youtube.com/channel/UCWN3xxRkmTPmbKwht9FuE5A) [## 深度认知让深度学习变得简单
在过去的一个月里,我有幸见到了 DeepCognition.ai 的创始人
becominghuman.ai](https://becominghuman.ai/deep-learning-made-easy-with-deep-cognition-403fbe445351) [## 想知道深度学习是如何工作的?下面给大家一个快速指南。
人工智能(AI)和机器学习(ML)是目前最热门的话题。
medium.freecodecamp.org](https://medium.freecodecamp.org/want-to-know-how-deep-learning-works-heres-a-quick-guide-for-everyone-1aedeca88076)
感谢你阅读这篇文章。希望你在这里发现了一些有趣的东西:)
如果您想联系我,请务必在 twitter 上关注我:
Favio Vázquez 的最新推文(@FavioVaz)。数据科学家。物理学家和计算工程师。我有一个…
twitter.com](https://twitter.com/faviovaz)
和 LinkedIn:
[## Favio Vázquez -首席数据科学家- OXXO | LinkedIn
查看 Favio Vázquez 在世界上最大的职业社区 LinkedIn 上的个人资料。Favio 有 17 个工作列在他们的…
linkedin.com](http://linkedin.com/in/faviovazquez/)
在一轮受欢迎的饮酒游戏之前,我应该期待什么?
乘坐公交车的数据分析
Recommended equipment for Ride The Bus
大学。这是探索你的个性、发现你的价值观和结交终生朋友的时候。这些都很好,但大学也是喝酒游戏的时候!白天有足够的时间去实现更崇高的目标,但是晚上需要新的方式去喝啤酒或者啜饮杜松子酒和滋补品。有很多娱乐性的饮酒游戏,但乘坐公共汽车尤其提出了一些有趣的数据问题。
喝酒游戏通常包括给别人喝饮料作为奖励,不得不拿饮料作为“惩罚”,然后是一大堆运气让事情变得有趣。乘坐公共汽车将所有这些方面整合到一个三阶段的纸牌游戏中,其中臭名昭著的第三阶段甚至可以测试经验丰富的大学生的决心。
有些回合你只需喝一两杯就能脱身。其他时候,你会感觉每隔几秒钟就要喝一杯。那么一个人在一场比赛中到底应该喝什么呢?数据分析和数百万次模拟都有答案。
注意:这个游戏有许多不同的版本,但我会在每一节之前简要说明我正在使用的版本。
第一阶段:获得卡片
工作原理:
一个庄家在给每个玩家发牌的时候会问他们四个问题。如果玩家答对了,他们会给一杯饮料。如果玩家答错了,他们就喝一杯。
- “红的还是黑的?”猜猜你第一张牌的颜色。
- “高还是低?”你的第二张牌会比第一张高还是低?
- “里面还是外面?”你的第三张牌在前两张之间还是之外?
- “什么西装?”猜猜你第四张牌的花色。
如果一张牌在边缘,那么一个人加注饮料赌注,然后给另一张牌。例如,如果你的第一张牌是 8,你说更高,而你的第二张牌是 8,那么你简单地再次猜测高或低,以获得更高的风险。
玩家最终会有 4 张或更多的牌。
数据:
平均来说,你将不得不喝 1.8 杯饮料,但在这一轮中,你要送出 2.4 杯饮料。这个阶段是一个轻松的介绍,提倡给予多于索取。除了分发卡片,还增加了一点乐趣。
下面是一张热图,显示了在第一阶段,人们可以预期给予或接受的饮料数量。很少有人能喝超过 3 杯的酒。
第二阶段:金字塔
工作原理:
这一阶段的目标是摆脱你的卡。正面朝下的卡片金字塔有四排。最下面一排有四张牌,而每高一排少一张。
庄家将从底部开始向上翻牌。如果你有一张翻过来的卡片,你可以把那张卡片放在金字塔上,然后分发一杯饮料。如果卡片在第一排,给一杯饮料,第二排,两杯饮料,依此类推。
手里剩余牌最多的玩家必须在第三阶段“乘坐公共汽车”。
数据:
在这个阶段,饮酒的赌注上升了。平均而言,在这一轮中,人们预计会送出 3.9 杯饮料。如果每个人都在随机分发饮料,那么你也可能会喝那么多,但你总有可能被挑出来喝更多。
下面是金字塔阶段你可以分发的饮料数量的直方图。分发的肉大约是 0-7 杯,但是分发 10 杯或更多杯的可能性是非常真实的。
在这一轮分发饮料很有趣,但关键的方面是找出谁必须在下一轮乘坐公共汽车。玩家越多,乘坐公共汽车的可能性就越小。下图显示了基于游戏中有多少玩家,你不得不乘坐公共汽车的概率。
呀!因为最大牌数中的平手几率,乘坐大巴的几率明显大于 1/(玩家人数)。即使是 10 个人,你也有 1/5 的机会坐公交。特别是在小团体中,不得不乘坐公共汽车是非常可能的。
第三阶段:乘坐公交车
工作原理:
只有在第二阶段中被选中乘坐公共汽车的玩家才参与这个最后阶段。庄家将七张面朝下的牌排成一行。一个庄家会翻一张牌,问玩家,“高还是低?”然后,发牌者在有问题的牌上面展示另一张牌。
如果玩家是正确的,他们翻转下一张牌。如果玩家错了,就从头再来。玩家必须猜对七次才能下车并赢得游戏。
这个游戏最令人生畏的部分,乘坐巴士是一个高度随机的事件,当失败时会感到紧张,但一旦结束就会很兴奋。
数据:
与这一阶段的声誉相反,平均而言,你可以预计在下车前只需喝 4.9 杯饮料。当然不是一个低数字,但有时会觉得平均是 20 或 30 杯,这取决于有时下车需要多长时间。
下图显示了乘坐公共汽车时,每次饮酒量的概率。
最典型的结果是在不喝任何饮料的情况下,将七张牌全部答对!这个图表几乎完全类似于一种叫做指数分布的分布。指数分布的重要方面是“无记忆”特性。
这意味着,无论你在乘车时已经喝了多少酒,你都应该准备在下车前再喝 4.9 杯。即使你已经喝了 100 杯了(不太可能),你也应该在下车前预计还会有 4.9 次失败。下次感觉公共汽车永远不会停下来的时候,请记住这一点!
下图是与上面相同的信息,但显示的是累积概率。例如,不得不喝 12 杯或 12 杯以上的概率约为 10%。
又来了!大量饮酒的负面风险很大。只有在喝了 16 杯左右的时候,才不太可能在没有获胜的情况下坚持那么久。
结论
在一个六人游戏中,假设饮料是随机分发的,那么一个人可能总共要喝 9.5 杯饮料。尽管如此,还是有很大的风险,那就是你必须乘两倍或更多的时间,这取决于你是否必须乘公共汽车,以及需要多长时间。
我希望我没有破坏数字游戏的乐趣!保持干渴,我的朋友,继续乘坐公共汽车。
代号:https://github.com/DastonArman
关于选择同行的数据驱动指南
继上一篇关于按国家划分的航空公司偏好的文章之后,今天我将查看 Skytrax 上 30 家最受关注的航空公司的详细评级。
哪些航空公司处于类似的等级?
给定 7 个子类别的详细评级,包括座位舒适度、客舱工作人员、食品和饮料、机上娱乐、地面服务、wifi 连接和性价比,我们可以对航空公司进行分层聚类,结果看起来相当合理。
我们观察到以下集群:
- 廉价航空公司(瑞安航空、捷星航空、易捷航空)
- 排名较低的北美航空公司(联合航空、美国航空、加拿大航空)
- 评价稍好的欧洲航空公司(维珍航空、法航)
- 亚洲和中东地区获得良好评价的航空公司(国泰航空、新加坡航空、卡塔尔航空、阿联酋航空)
一个附带说明是,如果还有其他因素对乘客很重要,但没有被属性捕捉到,如安全,详细评级可能不会捕捉到航空公司的整体评级。
航空公司集群之间有什么不同?
为了进一步了解每家航空公司的利弊,我们检查了详细的评级。
我们可以看到这些集群的属性:
- 法航和维珍航空在 wifi 连接方面的评级较低
- 廉价航空公司在 wifi 和机上娱乐方面得分较低,但在性价比方面得分较高。为什么这里会有这样的期望?
- 像达美航空和英国航空这样的航空公司得分相当不错,同样,wifi 和地面服务相对较低
- 汤姆森和托马斯·库克这两家英国区域性航空公司在无线网络上的评级相当不错
- 像联合航空这样的北美航空公司在各方面都被评为平均水平
- 亚洲/中东航空公司,如阿联酋航空公司和新加坡航空公司相对得分最高(鉴于没有人真正得到 5 分)
Detailed rating in same color as the previous clusters
这意味着你可以根据你在飞机上最关心的事情来选择航班,无论是 wifi 还是座位舒适度。航空公司也可以评估他们与类似评级的竞争对手的价格竞争力。
哪个属性对总体评分最重要?
检查每个属性与总体评分之间的相关性,我们可以看到价格的价值最重要,其次是来自机组人员和地勤人员的服务,接下来是座位舒适度和食物。电影和 wifi 其实没那么重要。
我今天学到的是 r 中的雷达图。雷达图在显示太多等级相差很大的类别时会有点棘手,在这种情况下,类别的排序可能会扭曲故事。在这里,因为大多数评级在 3-4 之间,所以这是了解每个类别评级的一个不错的选择。
library(fmsb)#need to add two rows on max and min range of each category
df=rbind(rep(5,7), rep(0,7), df)#plug in the numerical columns
radarchart(df[,2:8])
这是我关于数据科学和视觉故事的# 100 日项目的第 47 天。我的 github 上的全部代码。感谢阅读。欢迎新主题的建议和反馈。
成为持续的亿万富翁的数据驱动指南
你真的认为所有的亿万富翁都一样吗?
最近,我对那百分之一的亿万富翁有点着迷了。当我偶然发现一些文章告诉我们谁是真正的亿万富翁时,我很感兴趣。文章说的是这样的事情:大多数企业家没有学位,亿万富翁在开始创业之前一般都是 30 多岁。我觉得这有点笼统,我会解释的。让我们来看看比尔·盖茨和世嘉公司的首席执行官 Hajime Satomi。两人都是亿万富翁,但他们真的一样吗?在过去的十年中,比尔·盖茨每年都是亿万富翁,而哈吉已经三次从福布斯的名单中跌出。当没有人想成为一个朝觐者时,把这两个人放在同一个盒子里,发布漂亮的文章,给出漂亮的统计数据,这公平吗?我认为不会——尤其是在这十年里,像 Hajime 这样反复无常的亿万富翁占到了亿万富翁总数的 50%以上。解决亿万富翁之间的差异是这篇文章的主题。我们将强调关于持续的亿万富翁的有趣事实,并最终找出持续的亿万富翁与其他人的区别。
我所说的持续的亿万富翁是什么意思?这就是我们来这里的目的。🙂
对于像我这样的书呆子来说,我是这样做的
- 数据来源:大部分数据都是从 3000 份《福布斯》个人资料中刮来的。从一篇研究论文中收集了两个额外的变量: 亿万富翁特征数据库 。涵盖的亿万富翁是 2007 年至 2017 年 6 月期间是或曾经是亿万富翁的人。
- 数据收集:我使用亿万富翁的名字创建了他们的福布斯个人资料网址,并使用 RSelenium 和 rvest 收集了我需要的数据。我坦白说。一点也不性感。我做了大量的 Excel VLOOKUPS,手工检查和字符串操作,以获得一个可行的数据集。
- 数据清理:我使用 stringr 从字符串创建了列。
代码可以在这里找到。
亿万富翁有多少种类型?
这是我想到的:
- 如其名,这些人年复一年都是亿万富翁。它还包括最多一年没有上榜的亿万富翁(如 2008 年的马克·扎克伯格)。他们在 2015 年之前应该已经是亿万富翁了。
- **鬼魂:**这些是离开榜单的亿万富翁,他们在过去四年里没有回来过。他们也应该在 2015 年前首次亮相。
- **皮条客:**这一类别包括所有其他在 2015 年前首次亮相的亿万富翁。即
- 那些不止一次离开的人,每次都卷土重来。
- 那些虽然回到了名单上,但却离开了一年多的人。
- 那些还没有回来,但没有花了长达 4 年的名单。
- **新手:**这些是在 2015 年至 2017 年间首次亮相的亿万富翁。他们自成一组,因为我认为把他们放在其他任何地方都是不公平的,因为没有足够的数据将他们归入任何其他类别。尽管如此,我认为看看他们在做什么会很有趣。
所以,让我们开始吧!
你知道吗?
一贯的亿万富翁都受过良好教育。
接近 55%的亿万富翁至少有一个学位。
事实上,拥有学士、博士、硕士和几乎所有其他学位的人最多。
亿万富翁创业的平均年龄比普通鬼魂大 7 岁。
这适用于白手起家创业的亿万富翁。亿万富翁平均在 30 多岁开始创业,这与文章中关于 30 多岁成功创业的观点一致。
这位比其他人至少早两年创业的幽灵亿万富翁是否说明了年轻企业家不太可能维持他们的财富?大概吧。然而,如果你看看这些新手,他们大多也是在年轻时开始的。问题是:一般的新手最终会变成幽灵吗?或者说,在过去的几年里,竞争环境发生了变化吗?我们可以在几年后回答这个问题。🙂
持续产生亿万富翁比例最高的前三个行业是电信、时尚和多元化投资组合。
看起来极其主流吧?但是时尚?真的吗?
注:这里的时尚和零售不是指零售。这意味着商业零售时尚商品,如 Zara,H & M 等。
非洲亿万富翁最有可能成为持续的亿万富翁
接近 70%的非洲亿万富翁是稳定的——比世界上任何其他地区都多。最接近的地区是北美,占 53%。
然而,在新手时代,亚洲似乎主宰着所有其他地区,这一数字主要是由中国推动的。事实上,超过 50%的中国亿万富翁是在这一时期上榜的。
另一方面,中东的亿万富翁最有可能是鬼。我知道你在想什么。油价吧?大概吧。然而,大多数中东亿万富翁拥有多样化的投资组合。
拥有博士学位的亿万富翁比辍学者还多。
这是我最喜欢的。
这适用于所有其他学位,如工商管理硕士,理学硕士等。只有法律或医学等专业学位的亿万富翁比辍学者少。然而,在新手和骗子类别中,拥有专业学位的人甚至比辍学的人还要多。
11%的亿万富翁是女性。
唯一一个男女比例更令人鼓舞的类别是新人类别,约占 16%。然而,鉴于全球男女比例为 50:50,新人类别仍然短缺 34%。好消息是情况正在好转。自 2015 年以来,女性成为亿万富翁的可能性是此前的近两倍。
64%的亿万富翁都是白手起家。
唯一百分比较低的类别是幽灵。好消息(或坏消息——取决于你希望你的财富来自哪里)是,新亿万富翁的比例比这高。这意味着在最近一段时间,更多的“新”财富正在产生。此外,白手起家似乎并不奇怪,因为每个类别都有超过 60%的亿万富翁是白手起家。
酷,现在怎么办?
我们都知道和喜爱的亿万富翁都受过良好的教育,坦率地说,一般都很无聊。
“如果你想成为持续的亿万富翁,这有多重要?”
为了回答这个问题,我们将做一些机器学习(在这里请原谅,这可能有点技术性)。使用 h2o.ai 机器学习包(我爱!),我们会训练模型来预测一个亿万富翁会属于哪一类。除了新手,我们会对所有类别的人都这样做,因为和其他人不同,区分这个群体的是他们加入名单的时间,而不是他们在名单上的表现。我们还将使用真正的独立变量来训练我们的模型。例如,用于创建类别的变量,如他们离开列表的次数,将不会被使用。如果我们使用这样的变量,就像知道答案并逆向工作一样,对吗?然后,我们将检查哪些变量是预测亿万富翁类别的最佳变量,以回答我们的问题。在上面分享的同一个脚本中也有代码。
我会首先使用 purrr 和 h2o 包在梯度推进机器、随机森林和深度学习之间找到最佳算法。
看起来 GBM 算法在测试集上的准确性击败了其他机器学习算法。
让我们来看看 GBM 认为哪些变量在预测亿万富翁的类别时最重要。
在 50%的相对重要性之上,我们看到了三个变量:国家、行业和为他们带来财富的公司的成立年份。
这告诉我们什么是持续的亿万富翁?首先,它说,虽然一致性可能受过良好的教育,这肯定不是他们有什么。国家和行业是重要的变量,这并不令人吃惊,但“创建年份”却很有趣。这可能意味着建立一个可持续发展的企业变得越来越容易或越来越难。
还是那句话,非常直白和无聊。在正确的时间进入一个对你所在的行业有利的环境,然后蓬勃发展!你创造了可持续的财富。在这一点上,我觉得我有义务说,84%的技术亿万富翁在北美和亚洲。目前没有一个来自非洲(见上面关于你所在行业有利环境的句子),但话说回来,你可以成为先锋,所以接受我的建议吧。祝你好运!
要记住的事情
数据来自福布斯。这意味着我天生被他们的方法、估计和误差所约束。例如,数据显示只有一位亿万富翁来自政界。我非常怀疑那是真的。
- 一天结束的时候,我有超过 30 个变量,我不能在一篇文章中谈论所有的变量,所以这里有一些可视化供你玩,自己发现如何成为一个持续的亿万富翁。😉
- 想知道谁是一贯的亿万富翁吗?点击,使用完整数据集了解详情。
- 在我的下一篇文章中,我将讨论哪些行业、国家和成立年代是成为持续的亿万富翁的最佳时机;
- 我有一个小小的惊喜。🙂
原载于 2017 年 10 月 7 日theartandscienceofdata.wordpress.com。
超过 1.5 TB 的标记音频数据集
我在音频研究中使用的 25 个大型音频数据集列表
在 Wonder Technologies,我们花了大量时间来构建通过音频理解世界的深度学习系统。从基于深度学习的语音提取到教计算机如何读取我们的情绪,我们需要使用大量数据来提供即使在最疯狂的声音环境中也能工作的 API。这里有一个数据集列表,我发现它对我们的研究非常有用,我个人用它来使我的音频相关模型在现实环境中表现得更好。
尝试构建自定义数据集?不确定从哪里开始?和我一起进行 30 分钟的一对一谈话,谈谈你的项目。 报名时间段
音乐数据集
免费音乐存档
FMA 是一个用于音乐分析的数据集。数据集由全长和 HQ 音频、预先计算的特征以及音轨和用户级元数据组成。它是为评估音乐信息检索(MIR) 中的几项任务而创建的开放数据集。
这个很大,差不多有 1000 GB。
百万首歌曲数据集
百万歌曲数据集是一百万首当代流行音乐曲目的音频特征和元数据的免费收集。数据集的核心是一百万首歌曲的特征分析和元数据。数据集不包含任何音频,仅包含派生要素。使用哥伦比亚大学提供的代码,可以从 7digital 等服务中获取样本音频。这个数据集的大小大约是 280 GB。
语音数据集
自由口语数字数据集
这个是为了解决在音频样本中识别语音数字的任务而创建的。这是一个开放的数据集,因此希望随着人们不断贡献更多的样本,它将继续增长。目前,它包含以下特征:1) 3 个扬声器 2) 1,500 个录音(每个扬声器每个数字 50 个)3)英语发音。这是一个非常小的集合-大约 10 MB 大小。
LibriSpeech
这个数据集是大约 1000 个小时的英语演讲的大规模语料库。数据来源于 LibriVox 项目的有声书籍,大小为 60 GB。
沃克斯勒博
VoxCeleb 是一个大规模的说话人识别数据集。它包含了从 You Tube 视频中提取的 1251 位名人的约 10 万句话语。数据基本上是性别平衡的(男性占 55%)。这些名人的口音、职业和年龄各不相同。开发和测试集之间没有重叠。这是一个有趣的用例,用于隔离和识别声音属于哪个超级巨星。
这套是 150 兆字节的大小,有大约 2000 小时的讲话。
口语维基百科全集
这是一个英语、德语和荷兰语维基百科的口语文章语料库。数百小时的对齐音频和注释可以映射回原始 HTML。整套大约 38 GB 大小,有音频和无音频两种格式。
Flickr 音频字幕语料库
8,000 幅自然图像的 40,000 个语音字幕,大小为 4.2 GB。这个语料库是在 2015 年收集的,用于研究无监督语音模式发现的多模态学习方案。
泰德-刘姆
TED 演讲的音频转录。1495 年,TED 演讲录音以及这些录音的全文转录,由缅因州大学信息实验室(LIUM)创建。
语音命令数据集
数据集(1.4 GB)有 65,000 个一秒钟长的 30 个短词的话语,由成千上万不同的人通过 AIY 网站由公众贡献。它是在 Creative Commons-BY 4.0 许可下发布的,随着收到更多的贡献,它将在未来的版本中继续增长。该数据集旨在让您为应用程序构建基本但有用的语音界面,包括“是”、“否”等常用词、数字和方向。用于创建数据的基础设施也是开源的,我们希望看到它被更广泛的社区用来创建他们自己的版本,特别是覆盖服务不足的语言和应用程序。
常见语音
Common Voice(大小为 12 GB)是用户在 Common Voice 网站上阅读的语音数据的语料库,并且基于来自大量公共领域来源的文本,如用户提交的博客帖子、旧书、电影和其他公共语音语料库。它的主要目的是实现自动语音识别(ASR)系统的训练和测试。
波斯语辅音元音组合(PCVC)语音数据集
波斯语辅音元音组合(PCVC)语音数据集是用于语音识别和说话人识别的现代波斯语语音语料库。该数据集包含来自不同说话者的现代波斯语元音和辅音音素组合的声音样本。每个声音样本只包含一个辅音和一个元音,所以它以某种方式被标记在音素级别。该数据集包含 23 个波斯语辅音和 6 个元音。声音样本是元音和辅音的所有可能组合(每个说话者 138 个样本),长度为 30000 个数据样本。
如果要使用这个数据集,请参考本文:
Saber MalekzadeH,Mohammad Hossein Gholizadeh,Seyed Naser Razavi“在 PCVC 语音数据集上使用 MFCC 和安进行完整的波斯语元音识别”第五届电子工程、计算机科学和信息技术国际会议,伊朗,德黑兰,2018 年。 ( PDF )
VoxForge
口音英语的干净语音数据集。对于您期望对不同口音或语调具有鲁棒性的情况非常有用。
钟声
这是一个嘈杂的语音识别挑战数据集(约 4GB 大小)。该数据集包含真实的模拟和干净的语音记录。真实是在 4 个有噪声的位置上的近 9000 个记录中的 4 个说话者的实际记录,模拟是通过结合语音话语的多个环境和干净的无噪声记录而生成的。
您可以从这里的下载数据集。
2000 HUB5 英语
百度深度语音论文中最近使用的纯英文语音数据。
具有多种类型录音数据集的帕金森语音数据集
训练数据属于 20 名帕金森病(PD)患者和 20 名健康受试者。对于这个 20 MB 的集合,从所有对象中获取多种类型的录音(26)。
零资源演讲挑战
零资源语音挑战的最终目标是构建一个系统,该系统仅使用语言学习婴儿可用的信息,从零开始学习未知语言的端到端口语对话(SD)系统。“零资源”指的是零语言专门知识(例如,拼写/语言转录),而不是除了音频之外的零信息(视觉、有限的人类反馈等)。4 岁的孩子在没有语言专家监督的情况下自发学习语言的事实表明,这个目标在理论上是可以达到的。
等值线数据集
这个 38.7 GB 的数据集有助于预测说出了哪个字母名称——这是一个简单的分类任务。
阿拉伯语语音语料库
阿拉伯语语音语料库(1.5 GB)是用于语音合成的现代标准阿拉伯语(MSA)语音语料库。该语料库包含超过 3.7 小时的 MSA 语音的语音和拼写转录,与音素级别上的记录语音一致。注释包括单个音素上的单词重音标记。这个语料库是南安普顿大学的 Nawar Halabiat 博士工作的一部分。该语料库是使用专业工作室用南黎凡特阿拉伯语(大马士革口音)录制的。使用该语料库作为输出的合成语音产生了高质量、自然的声音。
TIMIT 文集
TIMIT read 语音语料库(440 MB)旨在为声学-语音研究以及自动语音识别系统的开发和评估提供语音数据。TIMIT 包含了美国英语八种主要方言的 630 名使用者的宽带录音,每个人朗读十个语音丰富的句子。它包括时间对齐的正字法、语音和单词转写,以及每个话语的 16 位、16 kHz 语音波形文件。
多模态情感线数据集(MELD)
通过增强和扩展情感线数据集,建立了多模态情感线数据集。MELD 包含与 EmotionLines 中相同的对话实例,但它还包含音频和视频模态以及文本。MELD 有超过 1400 段对话和 13000 句来自老友记电视剧的话语。对话中的每一个话语都被贴上了标签——愤怒、厌恶、悲伤、喜悦、中立、惊讶和恐惧。下载此处
为你的算法获取更多的数据是提高准确性的一种方式。在 深度学习表现小抄 中多探索几个秘籍
声音/自然
音频设备
632 个音频事件类的扩展本体和从 YouTube 视频中提取的 2,084,320 个人类标记的 10 秒声音剪辑的集合。要下载这套,点击这个 GitHub 链接。
Mivia 音频事件数据集
监控应用的 6000 个事件,即玻璃破碎、枪声和尖叫声。事件分为由 4,200 个事件组成的训练集和由 1,800 个事件组成的测试集。
要下载该数据集,您必须在 Mivia 网站上注册。
环境音频数据集
该网页试图维护一个适合环境音频研究的数据集列表。除了免费提供的数据集之外,为了完整起见,这里还列出了专有和商业数据集。除了数据集之外,一些在线声音服务也列在了页面的末尾。这些服务可用于为特殊研究需求形成新的数据集。
数据集分为两个表:
- 声音事件表包含适用于自动声音事件检测和自动声音标记领域研究的数据集。
- 声学场景表包含适合于涉及基于音频的上下文识别和声学场景分类的研究的数据集。
FSD:日常声音的数据集 ( Freesound )
AudioSet 本体是 600 多个声音类别的分层集合,我们用来自 Freesound 的 297,159 个音频样本填充了它们。该过程生成了 678,511 个候选注释,这些注释表达了音频剪辑中声源的潜在存在。FSD 包括各种各样的日常声音,从人类和动物的声音,到音乐和由事物发出的声音,所有这些都在知识共享许可下。通过创建这个数据集,我们寻求促进研究,使机器能够像人类一样听到和解释声音。
Freesound 是一个基于 Freesound 内容、由人类标记的音频集合的协作创建平台。
城市声音分类
数据集(6 GB)被称为 UrbanSound,包含 8732 个标记的声音摘录(<=4s) of urban sounds from 10 classes namely: Air Conditioner, Car Horn, Children Playing, Dog bark, Drilling Engine, Idling, Gun Shot, Jackhammer, Siren and Street Music The attributes of data are as follows: ID — Unique ID of sound excerpt Class — type of sound.
城市声音数据集
这个数据集包含 1302 个带标签的录音。每个录音都标有 10 类声音事件的开始和结束时间:空调、汽车喇叭、儿童玩耍、狗叫、钻孔、发动机空转、枪击、手提钻、警笛和街头音乐。每个录音可能包含多个声音事件,但对于每个文件,只有来自单个类的事件被标记。这些类别来自城市声音分类法。
鸟类音频探测挑战
在与 IEEE 信号处理协会的合作中,引入了一项研究数据挑战,以创建一种鲁棒且可扩展的鸟类检测算法。这项挑战包括在真实的生物声学监测项目中收集的新数据集(5.4 GB),以及一个客观、标准化的评估框架。
感谢阅读:)如果你喜欢它,尽可能多的点击下面的按钮!这对我意义重大,鼓励我写更多这样的故事
现代数据忍者的工具包
做数据分析既有趣又有益。这是我在空闲时间经常做的事情。但是,如果没有合适的工具,这可能会令人沮丧,而且非常耗时。我将处理数据的过程分为 4 个步骤。
- 数据收集:找到并获取您感兴趣的数据集
- 数据清理:将数据转换成正确的格式
- 数据探索:发现趋势和有趣的模式
- 数据可视化:将你发现的惊人趋势可视化
数据采集
在过去的 5 到 10 年里,收集数据的过程已经有了明显的改善。现在可以在网上找到大量的数据集。
卡格尔
Kaggle 在 2016 年推出了一个新的数据集功能,它很快成为我最喜欢的浏览和探索数据集的地方。它允许你上传自己的数据集,也可以自由访问他人的数据集。许多人创建了他们自己的“内核”,这是讲述某个数据集的故事/分析的小脚本。这个来源的警告是,它对所有人都是免费的,一些数据集没有得到很好的记录,数据的来源也不清楚。
A visualization of a Pokemon dataset found on Kaggle. Don’t ask me to interpret it.
谷歌大查询
另一个在过去几年里真正开花结果的大玩家是 Google BigQuery。他们拥有大量的公共数据集。此外,通过 SQL 浏览数据很容易,通常只需要几分钱。
Data.gov
Data.gov是开始搜索政府相关数据的好地方。我发现这个网站有些断断续续,经常把我链接到一些不可行的政府网站。尽管美国政府越来越重视开放数据,但我确信这将是一个会随着时间而改进的工具。
政府领域开放数据的另一个参与者是 Socrata。寻找大城市政府经常托管他们的数据。一些例子包括纽约开放数据和芝加哥数据门户。
/r/datasets 经常可以有一些非常新颖、漂亮的数据集。你也可以发布一条信息或数据集的请求,偶尔你会得到回应。
我偶尔使用的另一个技巧是浏览 /r/dataisbeautiful 。所有 OC(原创内容)帖子都需要包含一个评论,说明他们的数据集是从哪里来的。
令人惊叹的公共数据集
github 存储库[awesome-public-datasets](https://github.com/caesar0301/awesome-public-datasets)
链接到许多类型的数据集,按类别聚集。
Scrapy
有时候,最好的数据不是通过下载按钮或容易访问的 API 获得的。我尝试了多种 web scrapers,一次又一次,我回到了 Scrapy 。如果你有编程技能或者不怕钻研一点 python,Scrapy 是一个非常容易上手的 web 抓取工具,它运行良好,并且有很好的文档和工具。
我最喜欢的特性是scrapy shell <url>
,它会抓取一个网页并为您打开一个 REPL 来运行 python 命令,直到您确定了获取感兴趣的数据所需的命令集。
谷歌
这个显而易见,但还是值得一提。网上有大量的其他资源。谷歌一下你想找的东西,加上“数据集”这个词,是一个很好的起点。
信息自由法(FOIA)
最后但同样重要的是,如果你真的想得到一些数据,你可以提交一个 FOIA 请求。这项法律允许你向任何联邦机构索取数据,他们必须交出数据,除非它属于豁免范围。
数据清理
处理数据最乏味的部分,也是许多数据黑客可以证明的最耗时的部分。幸运的是,有一些工具可以让这个过程变得更容易。
Trifacta
如果您依赖 Excel 进行数据转换,您需要立即获取 Trifacta。Trifacta 是数据清理(坦率地说,是数据探索)的一个不可思议的工具,原因有很多。
处理任意大小的数据
Trifacta 处理数据的子集,然后生成一个脚本在原始数据集上运行。这是一个惊人的特性,因为它允许您快速操作大量数据集。如果你曾经试图用 Excel 打开超过 100k 行的文件,你就会知道应用宏是多么痛苦。
更好的数据处理
Trifacta 引入了一种不同的数据操作范式,称为 recipes。菜谱中的每一步都是对数据集的原子性改变。这很好,因为它允许您非常容易地恢复更改。Trifacta 也有非常灵活的语言来操作数据。
对您的数据进行分析
最后,Trifacta 在你操作数据时提供了关于你的数据的有见地的统计数据。它会告诉您列中有多少空值、值的分布、不同值的数量等。这种信息对于进行适当的数据清理是必不可少的。
Example analytics on a column in Trifacta
我怎么强调 Trifacta 改变游戏规则都不为过。尤其是对于那些不习惯命令行工具的人。
OpenRefine
数据清理的老国王。 OpenRefine 在 Trifacta 推出之前曾经是我的 goto 工具。OpenRefine 仍然有一些真正强大的功能,你在许多其他数据清理工具中找不到这些功能。我最喜欢的一个是它的文本聚类能力。这允许您对文本值进行聚类,然后合并它们。这在您收集城市和州名等数据时非常有用,您的数据条目如下所示:
Chicago, IL
chicago il
Chicago Illinois
...
这在现实世界的数据收集中经常发生。OpenRefine 对值进行聚类,并允许您通过单击按钮将它们合并为一个值。
命令行工具
我强烈建议您熟悉终端,因为许多强大的工具只作为命令行界面存在。这里有一些我最常用的。
这个工具包非常适合快速处理 CSV 数据。这篇博客文章详细介绍了如何使用它。
这个工具第一次使用时可能有点吓人,但是一旦你习惯了它,使用 JSON 就变得轻而易举了。我建议浏览一下教程,它会让你很快熟悉基础知识。
我经常发现自己将数据集从 json 转换成 csv。我发现 json2csv 非常有用。
数据探索
探索数据很可能是整个漏斗中我最喜欢的部分。是你偶然发现迷人发现的时候。这也是容易被忽略的领域之一。找到明显的趋势并不令人兴奋。获取数据集并找出细微差别需要时间。
Tableau 公共
Tableau Public 是一个免费的应用程序,可以让你快速绘制巨大的数据集。它可以让您轻松地加入数据集,甚至为您提供可视化建议。它有一个中等大小的学习曲线,有时会令人沮丧地得到你所寻找的图表,但最终很容易获得数据趋势的快速感觉。
除非我在绘制地图,否则我通常坚持使用 Tableau Public 作为我的主要工具。上面提到的其他工具也可以帮助探索过程,例如 Trifacta。
Python 库
如果你准备写一些 python,你可以做比 Tableau 更深入的分析。
- Pandas:这个库非常适合操作数据,并且与 numpy 配合得很好。这使得在数据集中排序和查找统计分布变得很容易。
- Matlibplot :用 python 生成一些快速绘图的强大工具。
- NLTK :如果你正在处理任何类型的非结构化数据,我经常会启动 NLTK(自然语言工具包)工具包,在基于文本的数据中寻找见解。
数据可视化
漏斗的这一部分挤满了工具,让人应接不暇。很奇怪,因为我经常认为这部分工作最容易。由于工具种类繁多,我将列出我在数据博客中使用的工具,然后是我过去使用过或听说过的一些其他工具。
我经常使用的工具
在所有的可视化库中,这可能是学习曲线最高的,并且需要编程技能,但无疑是最灵活的。你可以做任何你能想到的事情。如果你在做简单的可视化,比如线形图或条形图,我会提醒你远离 D3。我发现这不值得努力。
An excellent visualization done by the NYTimes using D3.js. Back in the days when Obama was president…
与 D3 相比,这个库使用起来非常简单,并使绘制基本图表变得轻而易举。您不必担心工具提示或标签,因为这些都是为您处理的。可以用 Google 图表或者 High 图表做后盾。
对我来说,就是这样。我当然会使用表格和图像,并不时地使用其他适合工作的工具,但 D3 产生高质量的定制图表的能力通常消除了这种需要。
我有时使用或听说过的工具
- 排行榜
- Google Sheets:是的,他们有非常漂亮的可视化工具,而且不需要编程。
- 对于非编码人员来说,这是一个很好的选择
- C3.js
- NVD3.js
- fleet . js
- 地图框
- 谷歌图表
- TileMill
- CartoDB
- Seaborn
有几个,但外面有几十个。去探索吧!
FYK 和赫比·汉考的数据追溯
我的全职工作是一名数据工程师(我有关于的想法),但我也是一名活跃的音乐家。在过去的两年里,我作为嘻哈歌手,发行了 10 首歌曲。当我开始为我的下一个音乐项目集思广益时,我想知道:我的音乐是否有某些音质在 Spotify 上表现得更好?我是应该少说唱,多唱歌,还是根本不唱?我应该让我的音乐更有趣还是更情绪化?让我们看看通过 Spotify 的 API 和 Spotify for Artists 提供的数据能告诉我们什么。
FYK
我的曲目中有很多数据可以直接从 Spotify for Artists 数据门户下载。首先,让我们来看看我所有时间流的热门曲目。
我基本上是昙花一现。我的歌,三重大调有将近 140K 的流,而我的中值曲目有~300 的流。
虽然我很想说 Triple Major 如此成功的原因是因为它是一个直截了当的 BANGER(确实如此),但它做得好的真正原因是因为 Kpop。我被 taste makerChristina Choi选中,她把这首歌放到了她的播放列表中,该列表拥有> 24 万粉丝(旁注:我实际上不是韩国人,但谁会去计算呢??).在下图中,你可以看到由于这种放置和新粉丝的后续流而产生的大峰值。
这种消费实际上直接进入了《发现周刊》,而我有一段时间在这方面游刃有余。现在热度已经下降了一点,重复这一成功是一个挑战。播放列表的力量是真实的。
储蓄比率
因为我的信息流是多么的不均衡,我不能仅仅依靠信息流来衡量我的成功。相反,让我们看看每首曲目的保存比率(总保存数除以总唯一听众数)。这个概念更接近我作为一个艺术家想要最大化的东西:让人们对一首歌做出如此积极的反应,以至于他们保存了它。
Sunrise (Remix) ,一首有 rap 桥段的 r & b/pop 歌曲,保存率最高,也恰好是我最喜欢的一束歌。第二个是 Sposed To Do ,这是一首罂粟原声歌曲,在我最后一次演出时,我惊讶地发现人们居然知道歌词。有趣的是,这看起来还不错。
音频功能与存储比率
下一个合乎逻辑的问题是,“这首歌有什么特别的品质使它更有可能被保存下来?”
我们可以通过 python spotipy 库直接从 Spotify API 获取“音频功能”。音频特征用 0 到 1 的分数来表示一首歌曲的“可跳舞”或“活力”程度。
对于我的每一首曲目,我们来看看它们的音频特征,看看和保存率有没有关系。
每个点是一个轨迹,每个图表示给定音频特征(例如可跳舞性)和保存率之间的关系。这里唯一有点意思的关系是价,Spotify 的文档将其描述为:
从 0.0 到 1.0 的测量值,描述轨道所传达的音乐积极性。高价曲目听起来更积极(例如,快乐、愉快、欣快),而低价曲目听起来更消极(例如,悲伤、沮丧、愤怒)。
我的音乐在效价和保存率之间有一个负的关系,这意味着我应该用更低的效价制作更多的音乐,即更悲伤的歌曲。我一直认为我是一个积极的歌手/说唱歌手,但也许是时候改变一下了。我是说,你更喜欢德雷克还是威尔·史密斯?
赫比·汉考
老实说,鉴于我的曲目很少,听的人也很少,很难从我自己的数据中得出任何真正的结论:(。让我们把这个框架应用到一个拥有令人难以置信的目录的艺术家身上:美国爵士钢琴家,赫比·汉考。
赫比的音乐生涯跨越了 50 多年,我认为他是所有活着的音乐家中最好的。虽然他可以说最出名的是他在爵士乐方面的创新,如《猎头》 (1973),但其他人可能会提到他在米勒·戴维斯第二大五重奏(1964-68),嘻哈经典 Rockit (1984),或他 2007 年凭借 River: The Joni Letters 获得格莱美年度专辑奖。时至今日,这位音乐变色龙已年近 80,但仍然活力十足。他的下一张专辑将主打当代嘻哈音乐,如肯德里克·拉马尔、雷猫和卡马西·华盛顿。
我强烈推荐阅读他的传记《可能性》。这个人以如此谦逊的方式讲述了惊人的故事,这在人类层面上和在音乐家层面上都激励了我。
让我们看看 Spotify 的 API 能告诉我们赫比惊人的职业生涯。
目录
赫比·汉考在 Spotify 上有多达 54 张专辑(包括录音室专辑和编辑/重新发行的专辑)。在他 50 多年的音乐生涯中,平均每年大约发行一张专辑。
从这张图表中我们可以看出,赫比在 70 年代是最多产的。特别是,他仅在 1979 年就发行了 5 张专辑。
大约在那个时候,我们也知道赫比·汉考开始更多地尝试他的电子爵士乐,其中包括一些我最喜欢的唱片,如 Head Hunters,Thrust 和 sunshine。也许我们可以使用之前介绍的音频特性来可视化这种效果。
如果我们看看赫比音乐的舞蹈性,我们可以看到它在 80 年代真正开始上升,因为他开始更倾向于迪斯科/电音。1986 年的大衰退是因为他在《午夜圆》电影原声带上的工作,但他在 1988 年用《完美机器》做了最后一张“可跳舞的”专辑,然后回归到一种更声学的声音。
势不可挡,对吧?如果你刚开始听 Herbie,也许他在 Spotify 上最受欢迎的 5 张专辑是很好的聆听灵感:
《九天之岛》( 1964 年)
猎头(1973)
处女航(1965 年)
哈密瓜岛(1994)
起飞(1962)
我很惊讶看到九天岛打败了猎头!虽然有些人可能会说这是因为 Spotify 的听众喜欢模态爵士乐而不是爵士放克(jazz-funk),但这很可能是因为 Empyrean Isles 包含了哈密瓜岛的首张录音,可以说是赫比最著名的爵士乐作品,也是最值得播放的(是的,这是一个词)。受欢迎程度是最近流式传输的函数,因此受播放列表的影响很大。
音频特性与流行度
虽然有 Herbie 所有曲目的保存率是很好的,但这个数据是不公开的,所以我们必须坚持流行度。类似于我们对 FYK 所做的,让我们看看音频特征和流行度之间是否有任何明显的相关性:
对于更适合跳舞、更有活力、更高价的赫比音乐来说,似乎存在温和的正相关关系。这并不奇怪,因为流行音乐通常更有活力。
工具性与流行度呈轻度负相关。说来有趣,我好像发现大部分人都不喜欢纯器乐。这种效果似乎也适用于赫比。
这对赫比·汉考意味着什么?我认为这对他的下一个项目是个好兆头,该项目将由嘻哈音乐超级制作人 Terrace Martin 制作,并将邀请当代爵士乐/嘻哈音乐皇室成员如 Kendrick Lamar、Thundercat 和 Snoop Dogg。一张以歌手为特色的高能专辑听起来很符合他过去在 Spotify 上的表现。赫比实际上有工程背景,并在他的书中谈了很多关于拥有分析头脑的内容,所以我不会否认他已经完成了完全相同的分析…
说真的,基于数据的艺术家发展?
我认为流媒体时代的一大好处是发现新人才变得非常容易。我们正处于音乐推荐的黄金时代,每周都会发现一个新的最喜欢的艺术家,这并不罕见。
发现天才很容易,但将这种天才培养成职业艺术家却很难。这就是我认为有很多机会使用数据来了解历史上哪些创造性决策可行,哪些不可行的地方。最棒的是,这些信息对任何人都是公开的。即使你是一名独立艺术家,你也能接触到比你想象的更多的信息。虽然拥有一些数据会有所帮助,但我不认为这需要一个科学家用批判的眼光来处理你的音乐创作过程。我已经看到艺术家经理开始扩展他们的数据技能,但我认为我们艺术家也是时候进步了。
查看 Jupyter 笔记本详细描述了这一分析,还有 FYK:
一个数据科学练习:根据就职演说,特朗普与其他总统有多相似?
Darker is more similar
这是基于运行一些由谷歌团队编写的 NLP(自然语言处理) Doc2Vec 算法的结果。(浅层,两层神经网络)。轴中的名称格式为<年> _ <总统> _ <党> _ <簇>。现在,我们使用了不同的方法来对结果进行聚类,我们将回到这一点。首先,让我们更深入地挖掘相似之处。以下是最相似的演讲:
[('1993_Clinton_D_1', 0.9777867794036865),
('1977_Carter_D_5', 0.9765924215316772),
('1969_Nixon_R_5', 0.975844144821167),
('1989_Bush_R_5', 0.974454939365387),
('2001_Bush_R_1', 0.9733594655990601),
('1961_Kennedy_D_5', 0.973156213760376),
('1913_Wilson_D_3', 0.9689352512359619),
('1981_Reagan_R_5', 0.9668718576431274),
('1945_Roosevelt_D_4', 0.9627108573913574),
('1953_Eisenhower_R_5', 0.9612894654273987)]
如果你将这些演讲与同一个政党的演讲相比较,最常见的演讲是**、尼克松、老布什和里根**。Doc2Vec/Word to Vec 使用一种叫做单词嵌入的复杂方法来进行比较。以下是所有演讲与其他演讲的对比:
几个有趣的观察可以立即在一个非常高的水平。例如,较暗的下角表示最近几年的演讲都在谈论类似的东西。word2vec 的问题虽然它很好地显示了语义和句法关系的整体保留,但由于向量的性质,更简单的单词关联丢失了或难以可视化。
LDA(一种较老的技术)对于文档的分组(聚类)更加透明。我们将上面找到的文档聚集在一起,发现了一些有趣的关系。
Trump is in Cluster 8
像克林顿和老布什这样的总统使用了一些相同的语言,比如:挑战、一代、勇气、承诺和变革。而最不同的总统像早期民主党人和假发党(6 和 2 集群)谈论的事情像:联盟,国会,外国,联合,党。或许可以天真地说,总统们谈论的更多的是:A)改变或者 B)保持话语权。同样的,群集不止不跟随时代而不是总统。公平地说,总统们通常在同一时期谈论同样的事情。
将所有三个指标(政党、文档向量和聚类)放在一起,我们发现特朗普的演讲**最像里根,**支持他最相似的说法(参考 4 位具有特朗普般特质的美国总统)。然而,波尔克的就职演说与特朗普大相径庭。补充说明:由于威廉·亨利·哈里森去世、加菲尔德和肯尼迪遇刺、尼克松被弹劾,我们没有泰勒、亚瑟、约翰逊或福特的正式就职演说。
感谢和更多阅读:
- 作为 Jupyter 笔记本的此分析的源代码
- 由 Data Dot World 主办的这次演习的数据
- 使用的工具:Python,Jupyter,Word2vec,sklearn,pandas,matplotlib
- http://brandonrose.org/clustering、https://medium . com/@ Mishra . the depak/doc 2 vec-in-a-simple-way-fa 80 bfe 81104Mishra“探索自然语言工具包(NLTK)”by Abhinav Raihttps://medium . com/@ theflyingmanis/Exploring-Natural-Language-Toolkit-NLTK-e 3009 de 61576
相似的分析有不同的结果:
- 关于特朗普所说的更多 NLP
- “就职演说有什么内容?一个通过 Empath 的词法分析”作者@ unignoranthttps://hacker noon . com/whats-in-an-就职演说-词法分析-via-empath-bf9a5eb90b76
- 《死亡与重生:解读特朗普就职演说的字里行间》作者@ ascotthineshttps://medium . com/@ ascotthines/Death-and-重生-解读特朗普就职演说的字里行间-speech-329fdd4ef632
Python 中的“好的数据科学”机器学习项目演练:第一部分
(Source)
为社会利益解决一个完整的机器学习问题
在我们这个数据驱动的世界里,数据科学是一个非常强大的工具。你可以说我是理想主义者,但是我相信这个工具不应该仅仅用于让人们点击广告或者花更多的时间在社交媒体上。
在本文和续集中,我们将通过一个完整的机器学习项目来研究一个“数据科学促进发展的问题:预测哥斯达黎加的家庭贫困。我们不仅能够以最有效的方式提高我们的数据科学技能——通过对真实世界数据的实践*——而且我们还获得了解决一个具有社会效益的问题的回报。*
事实证明,公司用来最大化广告浏览量的技巧也可以用来帮助减轻人类的痛苦。
完整的代码在 Kaggle (可以在浏览器中运行,不需要下载)和 GitHub 上都可以作为 Jupyter 笔记本使用。这是一个活跃的 Kaggle 竞赛,也是一个开始机器学习或学习一些新技能的伟大项目。
问题和方法
哥斯达黎加家庭贫困水平预测挑战赛是目前正在 Kaggle 上进行的良好机器学习数据科学竞赛。目标是使用个人和家庭社会经济指标来预测家庭的贫困状况。美洲开发银行开发了这个问题,并提供了数据,目的是改进识别需要帮助的家庭的传统方法。
The Costa Rican Poverty Prediction contest is currently running on Kaggle.
贫困标签分为四个等级,这使得这成为一个监督多类分类问题:
- **监督:**给定训练数据的标签
- **多类分类:**标签是离散的,有两个以上的值
解决机器学习问题的一般方法是:
- 了解问题和数据描述
- 数据清理/探索性数据分析
- 特征工程/特征选择
- 车型对比
- 模型优化
- 结果解释
虽然这些步骤似乎呈现出一种僵化的结构,但机器学习过程是非线性的,随着我们对数据越来越熟悉,一些部分会重复多次,看看什么是有效的。有一个大纲来提供一个总的指导是很好的,但是如果事情不顺利或者当我们对问题了解得更多时,我们经常会回到过程的早期部分。
在本文中,我们将大致介绍前四个步骤,看看一些例子,笔记本中提供了全部细节。这个问题对于初学者来说是一个很好的解决问题——因为数据集的大小是可管理的——对于那些已经有坚实基础的人来说也是如此,因为 Kaggle 提供了一个试验新技术的理想环境。
最后两个步骤,加上一个实验部分,可以在第二部分中找到。
理解问题和数据
在理想情况下,我们都是问题主题的专家,拥有多年的经验来指导我们的机器学习。实际上,我们经常处理来自新领域的数据,并且必须快速获取数据所代表的内容以及如何收集数据的知识。
幸运的是,在 Kaggle 上,我们可以使用其他数据科学家分享的工作来相对快速地达到速度。此外,Kaggle 还提供了一个讨论平台,你可以在这里向比赛组织者提问。虽然与在实际工作中与客户互动不完全相同,但这给了我们一个机会来弄清楚数据字段代表什么,以及在我们遇到问题时应该记住的任何考虑事项。
此时可以问的一些好问题是:
- 根据领域专家的观点,对于这个问题,是否有某些变量被认为是最重要的?
- 数据是否存在已知问题?需要注意的某些价值/异常?
- 数据是如何收集的?如果有异常值,它们可能是人为错误或极端但仍然有效的数据的结果吗?
例如,在与组织者进行讨论后,社区发现文本字符串“yes”实际上映射到值 1.0,并且其中一列的最大值应该是 5,这可用于纠正异常值。如果没有了解数据收集过程的人,我们很难找到这些信息!
数据理解的一部分也意味着挖掘数据定义。最有效的方法是一次浏览一列,阅读描述并确保您知道数据代表什么。我觉得这有点枯燥,所以我喜欢将这个过程与数据探索结合起来,阅读专栏描述,然后用统计数据和数字探索专栏。
比如我们可以读到meaneduc
是家庭的平均教育量,然后我们可以用标签的值来绘制它的分布,看看它在贫困水平之间是否有任何明显的差异。
Average schooling in family by target (poverty level).
这表明贫困风险最小的家庭——非弱势家庭——往往比风险最大的家庭有更高的平均教育水平。稍后在特征工程中,我们可以通过从教育中构建特征来使用此信息,因为它似乎显示了目标标签之间的不同。
总共有 143 个专栏(特性),虽然对于一个实际的应用程序,您希望与专家一起浏览每个专栏,但是我并没有在笔记本中详尽地探究所有这些。相反,我阅读了数据定义,并查看了其他数据科学家的工作,以理解大多数列。
从问题和数据理解阶段建立的另一点是我们想要如何构造我们的训练数据。在这个问题中,我们给出了一个数据表,其中每行代表一个个体,列代表特征。如果我们阅读问题定义,我们被告知要对每个家庭进行预测,这意味着我们最终的训练数据框架(以及测试)应该对每个家庭有一行。这一点贯穿了我们的整个流程,因此从一开始就把握住这一点至关重要。
A snapshot of the data where each row is one individual.
确定度量标准
最后,我们要确保我们理解了问题的标签和度量。标签是我们想要预测的,度量是我们如何评估这些预测。对于这个问题,标签是一个整数,从 1 到 4,代表一个家庭的贫困程度。该指标是宏 F1 得分,这是一个介于 0 和 1 之间的度量值,值越高表示模型越好。F1 分数是二进制分类任务的常用度量,而“宏”是多类问题的平均选项之一。
一旦你知道了度量标准,弄清楚如何用你正在使用的工具来计算它。对于 Scikit-Learn 和宏 F1 分数,代码为:
from sklearn.metrics import f1_score# Code to compute metric on predictions
score = f1_score(y_true, y_prediction, average = 'macro')
知道了度量标准,我们就可以在交叉验证中评估我们的预测,并使用坚持测试集,这样我们就知道我们的选择对性能有什么影响,如果有的话。在这个竞赛中,我们得到了要使用的度量标准,但是在现实世界中,我们必须自己选择一个合适的度量标准。
数据探索和数据清理
数据探索,也称为探索性数据分析(EDA) ,是一个开放式的过程,在这个过程中,我们要弄清楚我们的数据能告诉我们什么。当我们发现可以用于特性工程或发现异常的有趣的趋势/模式时,我们开始广泛并逐渐在我们的分析中磨练。 数据清理 与探索密切相关,因为我们需要在建模之前解决我们发现的缺失值或异常。
对于数据探索的简单的第一步,我们可以可视化训练数据的标签分布(没有给我们测试标签)。
Distribution of training labels.
这马上告诉我们,我们有一个不平衡的分类问题,这可能使机器学习模型难以学习代表性不足的类别。许多算法都有尝试和处理这一问题的方法,例如在 Scikit-Learn 随机森林分类器中设置class_weight = "balanced"
,尽管它们并不完美。当我们遇到不平衡的分类问题时,我们还希望确保使用 分层抽样 进行交叉验证,以在每个折叠中获得相同的标签平衡。
为了熟悉数据,浏览代表不同数据统计类型的不同列数据类型是有帮助的:
float
:这些通常是连续的数字变量int
:通常要么是布尔型的,要么是序数型的(有顺序的离散型)object
或category
:通常是在机器学习之前必须以某种方式转换的字符串或混合数据类型
我使用统计类型来表示数据代表什么——例如只能是 1 或 0 的布尔值——使用数据类型来表示值在 Python 中的实际存储方式,例如整数或浮点数。统计类型告知我们如何处理特征工程的列。
(我为每个数据类型/统计类型配对指定了通常是,因为您可能会发现统计类型被保存为错误的数据类型。)
如果我们看一下这个问题的整数列,我们可以看到它们中的大多数表示布尔值,因为只有两个可能的值:
Integer columns in data.
浏览对象列,我们遇到了一个难题:2 列是 Id 变量(存储为字符串),但是 3 列看起来是数值。
# Train is pandas dataframe of training data
train.select_dtypes('object').head()
Object columns in original data.
这就是我们早先的数据理解发挥作用的地方。对于这三列,一些条目是“是”,一些是“否”,而其余的是浮动。我们做了背景调查,因此知道“是”意味着 1,“否”意味着 0。使用这些信息,我们可以校正这些值,然后可视化由标签着色的变量分布。
Distribution of corrected variables by the target label.
这是数据探索和清理齐头并进的一个很好的例子。我们发现数据中的错误,修正它,然后研究数据以确保我们的修正是适当的。
缺少值
此数据的一个关键数据清理操作是处理缺失值。在熊猫中,计算缺失值的总数和百分比很简单:
Missing values in data.
在某些情况下,缺失值是有原因的:v2a1
列代表月租金,许多缺失值是因为家庭拥有房屋。为了弄清楚这一点,我们可以将数据划分为房屋缺少租金支付,然后绘制显示房屋所有权的tipo_
变量(我不确定这些列名来自哪里)。
Home ownership status for those households with no rent payments.
根据该图,解决方案是为拥有自己房屋的家庭填写缺失的租金付款,并让其他家庭进行估算。我们还添加了一个 boolean 列,指示租金付款是否丢失。
列中其他缺失的值以同样的方式处理:使用来自其他列或关于问题的知识来填充值,或者让它们被估算。添加一个布尔列来指示丢失的值也是有用的,因为有时值丢失了的信息很重要。需要注意的另一个关键点是,对于缺失值,我们通常希望考虑使用其他列中的信息来填充缺失值,就像我们对租金付款所做的那样。
一旦我们处理了缺失值、异常和不正确的数据类型,我们就可以继续进行特性工程。我通常将数据探索视为一个正在进行的过程,而不是一个固定的块。例如,当我们进入特征工程时,我们可能想要探索我们创建的新变量。
数据科学过程是非线性的:虽然我们有一个大致的轮廓,但随着我们对问题的深入,我们经常回过头来重复前面的步骤。
特征工程
如果你关注我的工作,你会知道我确信自动化特征工程——具有领域专业知识——将取代传统的手工特征工程。对于这个问题,我采用了两种方法,在主笔记本中完成大部分手工工作,然后用自动化特征工程编写另一个笔记本。毫不奇怪,自动化的特征工程花费了十分之一的时间,并获得了更好的性能!这里我将展示手动版本,但是请记住自动化特征工程(带有 Featuretools) 是一个很好的学习工具。
在这个问题中,我们特征工程的主要目标是在家庭级别聚集所有个人级别的数据。这意味着将一所房子里的个人分组,然后计算统计数据,如最大年龄、平均教育水平或家庭拥有的手机总数。
幸运的是,一旦我们将单个数据分离出来(放入ind
数据帧中),在 Pandas 中做这些聚合就是字面上的一行(使用idhogar
家庭标识符用于分组):
# Aggregate individual data for each household
ind_agg = ind.groupby('idhogar').agg(['min', 'max', 'mean', 'sum'])
重命名列后,我们有了许多类似于以下的功能:
Features produced by aggregation of individual data.
这种方法的好处是可以快速创建许多特征。其中一个缺点是,这些特征中的许多可能没有用或者高度相关(称为共线),这就是为什么我们需要使用特征选择。
聚合的另一种方法是基于哪些特征可能对预测贫困有用,使用领域知识一次计算一个特征。例如,在家庭数据中,我们创建了一个名为warning
的特征,它增加了许多家庭“警告信号”(house
是家庭变量的数据框架):
# No toilet, no electricity, no floor, no water service, no ceiling
house['warning'] = 1 * (house['sanitario1'] +
(house['elec'] == 0) +
house['pisonotiene'] +
house['abastaguano'] +
(house['cielorazo'] == 0))
Violinplot of Target by Warning Value.
我们还可以通过将一个值除以另一个值来计算“人均”特征(tamviv
是家庭成员的数量):
# Per capita features for household data
house['phones-per-capita'] = house['qmobilephone'] / house['tamviv']
house['tablets-per-capita'] = house['v18q1'] / house['tamviv']
house['rooms-per-capita'] = house['rooms'] / house['tamviv']
house['rent-per-capita'] = house['v2a1'] / house['tamviv']
当谈到手工与自动化特征工程时,我认为最佳答案是两者的混合。作为人类,我们在构建功能时受到创造力和时间的限制,创造力是我们能想到的功能是有限的,时间是我们编写代码的有限时间。我们可以手工制作一些类似上面的有见识的特性,但是自动化特性工程擅长的是在其他特性之上自动构建聚合。
最好的方法是花一些时间使用领域知识手工创建一些特性,然后将这个过程交给自动化的特性工程来生成成百上千个特性。
( Featuretools 是最先进的自动化特征工程开源 Python 库。这里有一篇文章可以让你在 10 分钟内开始。)
特征选择
一旦我们耗尽了时间或耐心来制作特性,我们就应用特性选择来删除一些特性,试图只保留那些对问题有用的特性。“有用”没有固定的定义,但是我们可以使用一些启发法(经验法则)来选择特性。
一种方法是通过确定特征之间的相关性。彼此高度相关的两个变量称为共线变量。这是机器学习中的一个问题,因为它们会降低训练速度,创建更难解释的模型,并且会通过对训练数据进行过度拟合来降低模型性能。
移除相关特征的棘手部分是确定相关阈值,以表明两个变量过于相关。我通常尽量保持保守,使用 0.95 或以上的相关系数。一旦我们决定了一个阈值,我们就使用下面的代码从每一对相关性高于该值的变量中删除一个:
我们只移除那些相互关联的特性。我们想要与目标相关的特征(尽管与标签的相关性大于 0.95 会好得令人难以置信)!**
特征选择有很多种方法(我们会在接近文章结尾的实验部分看到另一种)。这些可以是单变量——对照目标一次测量一个变量——或多变量——评估多个特征的影响。我也倾向于使用基于模型的特征重要性进行特征选择,比如那些来自随机森林的特征。
在特征选择之后,我们可以对我们的最终变量集进行一些探索,包括制作一个关联热图和一个对图。
****
Correlation heatmap (left) and pairsplot colored by the value of the label (right).
我们从探索中得到的一点是教育与贫困之间的关系:随着一个家庭教育水平的提高(平均和最大),贫困的严重程度趋于降低(1 为最严重):
Max schooling of the house by target value.
另一方面,随着拥挤程度——每个房间的人数——的增加,贫困的严重程度也在增加:
Household overcrowding by value of the target.
这是来自这场比赛的两个可行的见解,甚至在我们进入机器学习之前:教育水平较高的家庭往往贫困程度较低,每个房间有更多人的家庭往往贫困程度较高。除了技术方面,我喜欢思考数据科学项目的分支和更大的图景。我们很容易被细节淹没,然后忘记了解决这个问题的整体原因。
这个项目的最终目标是找出如何预测贫困,以便最有效地帮助那些需要帮助的人。
模型比较
下图是我最喜欢的机器学习结果之一:它显示了机器学习模型在许多数据集上的性能,百分比显示了特定方法击败任何其他方法的次数。(摘自 Randal Olson 的一篇可读性很强的论文。)
Comparison of many algorithms on 165 datasets.
这表明在一些问题上即使是简单的逻辑回归也会胜过随机森林或梯度推进机。虽然渐变树增强模型一般来说效果最好,但也不能保证它会胜出。因此,当我们处理一个新问题时,最佳实践是尝试几种不同的算法,而不是总是依赖同一个算法。我以前也曾被同一个模型(随机森林)困住,但是请记住没有一个模型永远是最好的。
幸运的是,有了 Scikit-Learn ,使用相同的语法评估许多机器学习模型变得很容易。虽然我们不会对每个模型进行超参数调整,但我们可以将模型与默认超参数进行比较,以便选择最有希望进行优化的模型。
在笔记本中,我们尝试了六种模型,涵盖了从简单的高斯朴素贝叶斯到复杂的随机森林和梯度推进机器的复杂范围。尽管 Scikit-Learn 确实有一个 GBM 实现,但是它相当慢,更好的选择是使用一个专用的库,比如 XGBoost 或 LightGBM。对于这款笔记本电脑,我使用了 Light GBM ,并根据过去的良好表现选择了超参数。
为了比较模型,我们在 5 或 10 倍的训练数据上计算交叉验证性能。我们想要使用训练数据,因为测试数据只打算用一次来评估我们最终模型在新数据上的性能。下图显示了模型比较。条形的高度是模型记录的折叠的平均宏 F1 分数,黑色条形是标准偏差:
Model cross validation comparison results.
(要查看名称的解释,请参阅笔记本。RF 代表随机森林,GBM 是梯度提升机器,SEL 代表特征选择后的特征集)。虽然这不完全是水平比较——我没有使用梯度推进机器的默认超参数——但总体结果是:GBM 是最好的模型,遥遥领先。这反映了大多数其他数据科学家的发现。
请注意,我们在特性选择前后交叉验证了数据,以查看其对性能的影响。机器学习在很大程度上仍然是一个经验领域,知道一种方法是否有效的唯一方法是尝试它,然后衡量性能。为管道中的步骤测试不同的选择很重要——例如特征选择的相关性阈值——以确定它们是否有帮助。请记住,我们还希望避免将过多的权重放在交叉验证结果上,因为即使有许多折叠,我们仍然可能过度适应训练数据。最后,尽管 GBM 最适合这个数据集,但情况并不总是这样!
基于这些结果,我们可以选择梯度推进机作为我们的模型(记住这是一个我们可以回头修改的决定!).一旦我们决定了一个模型,下一步就是充分利用它,这个过程被称为模型超参数优化。
认识到不是每个人都有时间一口气写 30 分钟的文章(即使是关于数据科学的),我把这篇文章分成两部分。第二部分包括模型优化、解释和实验部分。
Decision tree visualization from part two.
结论
至此,我们可以看到机器学习的所有不同部分是如何走到一起形成解决方案的:我们首先必须理解问题,然后我们挖掘数据,根据需要清理数据,然后我们为机器学习模型制作特征,最后我们评估了几个不同的模型。
我们已经涵盖了许多技术,并有一个像样的模型(虽然 F1 分数相对较低,但它在提交给比赛的前 50 名模型中占有一席之地)。尽管如此,我们仍然有几个步骤:通过优化,我们可以改进我们的模型,然后我们必须解释我们的结果,因为直到我们已经交流了我们的工作,分析才是完整的。
下一步,看第二部分,查看笔记本(也在 GitHub 上),或者开始为自己解决问题。
和往常一样,我欢迎反馈、建设性的批评以及倾听您的数据科学项目。可以在 Twitter @koehrsen_will 上找到我。
Python 中的“好的数据科学”机器学习项目演练:第二部分
(Source)
最大限度地利用我们的模型,弄清楚它意味着什么,并尝试新的技术
机器学习是一个强大的框架,从外面看起来可能很复杂,令人生畏。然而,一旦我们将一个问题分解成它的组成步骤,我们就会看到机器学习实际上只是一系列可理解的过程,每个过程本身都很简单。
在本系列的前半部分,我们看到了我们如何实现一个“为好的数据科学”机器学习问题的解决方案,在我们选择了梯度推进机器作为我们的选择模型之后,我们就停止了。
Model evaluation results from part one.
在本文中,我们将继续预测哥斯达黎加的贫困状况,执行模型优化,解释模型,并尝试一些实验技术。
完整的代码可以在 Kaggle (可以在浏览器中运行,不需要下载)和 GitHub 上的 Jupyter 笔记本中获得。这是一个活跃的 Kaggle 竞赛,也是一个开始机器学习或学习一些新技能的伟大项目。
模型优化
模型优化意味着为给定数据集搜索产生最佳性能的模型超参数(通过交叉验证测量)。因为最佳超参数随数据而变化,所以我们必须优化我们数据的模型,也称为调整模型。我喜欢把调优看作是为机器学习模型寻找最佳设置。
有 4 种主要的调优方法,从最低效率(手动)到最高效率(自动)排列。
- 手动调优:凭直觉/经验或通过猜测选择超参数,用这些值训练模型,找到验证分数,重复直到你失去耐心或对结果满意。
- 网格搜索:设置一个超参数网格,对于每一个数值组合,训练一个模型,找到验证分数。超参数的最佳集合是得分最高的那些。
- 随机搜索:设置超参数网格,选择随机数值组合,训练模型,找到验证分数。搜索迭代受到时间/资源的限制
- 自动调整:使用方法(梯度下降、贝叶斯优化、进化算法)引导搜索最佳超参数。这些是使用过去信息的知情方法。
自然,我们将跳过前三种方法,直接进入最有效的方法:自动超参数调优。对于这个实现,我们可以使用 Hyperopt 库,它使用带有树 Parzen 估计器的贝叶斯优化版本进行优化。你不需要理解这些术语来使用模型,尽管我在这里写了一个概念性的解释。(我还在这里写了一篇关于使用 Hyperopt 进行模型调优的文章。)
细节有点冗长(见笔记本),但是我们需要 4 个部分来实现 Hyperopt 中的贝叶斯优化
- *目标函数:*我们想要最大化(或最小化)什么
- *域空间:*要搜索的区域
- *用于选择下一个超参数的算法:*使用过去的结果来建议要评估的下一个值
- 结果历史:保存过去的结果
贝叶斯优化 (BO)的基本思想是,算法从过去的结果中推理——之前的超参数的得分如何——然后选择它认为最好的下一个值组合。网格或随机搜索是不使用过去结果的方法,其思想是通过推理,BO 可以在更少的搜索迭代中找到更好的值。
完整的实现见笔记本,但下面是 100 次搜索迭代后的优化分数。
Model optimization scores versus iteration.
与分数随时间随机变化的随机搜索不同,在贝叶斯优化中,随着算法学习最佳超参数的概率模型,分数往往会随着时间的推移而改善。贝叶斯优化的想法是,我们可以通过将搜索集中在有希望的设置上来更快地优化我们的模型(或任何函数)。一旦优化运行完成,我们可以使用最佳超参数来交叉验证模型。
优化模型并不总能提高我们的测试分数,因为我们是在为训练数据进行优化。然而,与默认的超参数相比,有时它可以带来很大的好处。在这种情况下,最终的交叉验证结果以数据框架的形式显示如下:
Cross validation results. Models without 10Fold in name were validated with 5 folds. SEL is selected features.
优化的模型(用 OPT 表示,并在选择后使用 10 个交叉验证折叠的特征)正好位于梯度增强机器的非优化变体的中间(它使用我发现对以前的问题工作良好的超参数)。)这表明我们还没有找到最佳的超参数,或者可能有多组表现大致相同的超参数。
我们可以继续优化,尝试找到更好的超参数,但通常超参数调整的回报远小于特征工程的回报。在这一点上,我们有一个相对高性能的模型,我们可以使用这个模型对测试数据进行预测。然后,由于这是一个 Kaggle 比赛,我们可以将预测提交给排行榜。这样做让我们进入了前 50 名(目前),这是对我们所有努力的一个很好的证明!
至此,我们已经实现了这个机器学习问题的完整解决方案。我们的模型可以对哥斯达黎加家庭的贫困做出相当准确的预测(F1 得分相对较低,但这是一个困难的问题)。现在,我们可以继续解释我们的预测,看看我们的模型是否能告诉我们关于这个问题的任何东西。即使我们有解决方案,我们也不想忽视为什么我们的解决方案很重要。
关于 Kaggle 竞赛的注记
机器学习竞赛的本质可能会鼓励不良做法,例如以牺牲所有其他考虑因素为代价来优化排行榜分数的错误。一般来说,这导致使用更复杂的模型来弥补微小的性能增益。
在现实世界中,超过某个阈值——这取决于应用程序——准确性变得次要于可解释性,如果更简单的话,您最好使用性能稍差的模型。
投入使用的简单模型比永远无法部署的复杂模型要好。此外,那些在排行榜顶端的人可能过度适应测试数据,并且没有一个健壮的模型。
最大限度地利用 Kaggle 的一个好策略是努力解决一个问题,直到你有一个合理的好解决方案——比方说 90%的排行榜得分——然后不要为达到最高分而感到压力。竞争是有趣的,但学习是承担这些项目最有价值的方面。
解释模型结果
在编写所有机器学习代码的过程中,很容易忽略一些重要的问题:我们制作这个模型是为了什么?我们的预测会有什么影响?幸运的是,我们这次的答案不是“增加广告收入”,而是有效地预测哥斯达黎加哪些家庭最容易陷入贫困,以便他们能够获得所需的帮助。
为了尝试了解我们的模型的输出,我们可以根据测试数据以家庭为单位来检查贫困水平的预测。对于测试数据,我们不知道真实的答案,但我们可以将每个预测类的相对频率与训练标签中的相对频率进行比较。下图左侧显示了贫困的训练分布,右侧显示了测试数据的预测分布:
Training label distribution (left) and predicted test distribution (right). Both histograms are normalized.
有趣的是,尽管“不脆弱”的标签在训练数据中最常见,但在预测的相对基础上,它的出现频率较低。我们的模型预测其他 3 个阶层的比例更高,这意味着它认为在测试数据中有更严重的贫困*。如果我们把这些分数转换成数字,我们有 3929 个家庭属于“非脆弱”类别,771 个家庭属于“极端”类别。*
另一种看待预测的方式是通过模型的可信度。对于测试数据上的每一个预测,我们不仅可以看到标签,还可以看到模型赋予它的概率。让我们看看箱线图中标签值的置信度。
Boxplot of probability assigned to each label on testing data.
这些结果相当直观——我们的模型对最极端的预测最有信心——对温和的预测信心较低。理论上,最极端的标签之间应该有更多的分离,而中间的目标应该更难区分。
从这个图表中得出的另一点是,总的来说,我们的模型对预测并不十分确定。一个没有数据的猜测会将 0.25 的概率放在每一类上,我们可以看到,即使对于最不极端的贫困,我们的模型也很少有超过 40%的置信度。这告诉我们这是一个棘手的问题——在可用的数据中没有太多的分类。
理想情况下,这些预测,或者那些来自竞赛中获胜模型的预测,将被用来确定哪些家庭最有可能需要帮助。然而,仅仅是预测本身并不能告诉我们什么会导致贫困,或者我们的模型是如何“思考”的。虽然我们还不能完全解决这个问题,但我们可以尝试窥视机器学习的黑箱。
在基于树的模型中——如梯度推进机——特征重要度表示特征上节点分裂的和基尼系数杂质减少总量。我从来没有发现绝对值很有帮助,而是将这些数字归一化,并在相对的基础上看待它们。例如,下面是优化的 GBM 模型的 10 个最重要的特性。
Most important features from optimized gradient boosting machine.
在这里,我们可以看到家庭成员的教育和年龄构成了最重要的特征。进一步看重要性,我们也看到了家庭的大小。这与贫困研究人员的发现相呼应:家庭规模与更极端的贫困相关,而教育水平与贫困成反比*。在这两种情况下,我们不一定知道哪一个导致了哪一个,但是我们可以使用这些信息来突出哪些因素应该被进一步研究。希望这一数据能够被用来进一步减少贫困(在过去的 25 年中贫困一直在稳步减少)。*
It’s true: the world is better now than ever and still improving (source).
除了潜在地帮助研究人员之外,我们可以通过尝试在这些基础上构建更多的特性来使用特性重要性进行进一步的特性工程。使用上述结果的一个例子是用meaneduc
除以dependency
来创建一个新特征。虽然这可能不太直观,但很难提前知道什么对模型有效。
使用测试数据检查我们的模型的另一种方法是将训练数据分成较小的训练集和验证集。因为我们有所有定型数据的标签,所以我们可以将我们对维持验证数据的预测与真实值进行比较。例如,使用 1000 个观察值进行验证,我们得到下面的混淆矩阵:
Confusion matrix on validation data.
对角线上的值是模型正确预测的值,因为预测标签与真实标签相同。任何偏离对角线的模型预测错误。我们可以看到,我们的模型在识别非弱势家庭方面是最好的,但在识别其他标签方面不是很好。
例如,我们的模型错误地将 18 户家庭归类为非弱势群体,而这些家庭实际上处于极端贫困之中。像这些的预测具有现实世界的后果,因为这些家庭可能会因为这种模式而得不到帮助。(更多关于错误算法的后果,见 数学毁灭的武器 )。)
总的来说,这种平庸的表现——模型精度约为 60%,比随机猜测好得多,但并不例外——表明这个问题可能很困难。可能是没有足够的信息来在可用数据中分离类别。
主办机构美洲开发银行的一个建议是,我们需要更多的数据来更好地解决这个问题。这可能表现为更多的特征——因此调查中有更多的问题——或者更多的观察——更多的家庭被调查。这两者都需要付出巨大的努力,但投资于数据科学项目的最佳时间回报通常是通过收集更多的高质量标记数据。
我们可以使用其他方法来理解模型,例如本地可解释的模型不可知解释器(LIME) ,它使用一个更简单的线性模型来近似预测周围的模型。我们还可以查看森林中的单个决策树,这些决策树通常很容易解析,因为它们本质上模拟了人类的决策过程。
Individual Decision Tree in Random Forest.
总体而言,机器学习仍然存在可解释性差距,这阻碍了它的适用性:人们不仅想要准确的预测,还想要了解这些预测是如何产生的。
探索技术
我们已经用标准工具箱解决了机器学习问题,那么为什么还要进一步探索技术呢?嗯,如果你像我一样,那么你喜欢仅仅为了学习而学习新的东西。此外,今天的探索技术将成为明天的标准工具。
对于这个项目,我决定尝试两项新技术:
递归特征消除
递归特征消除是一种用于特征选择的方法,它使用模型的特征重要性(该应用程序的随机森林)来选择特征。这个过程是一个重复的方法:在每次迭代中,最不重要的特性被删除。通过对训练数据进行交叉验证来确定要保留的最佳特征数量。
递归特征消除与 Scikit-Learn 的 RFECV 方法一起使用很简单。这种方法建立在一个评估器(一个模型)上,然后像任何其他 Scikit-Learn 方法一样fit
。scorer
部分是必需的,以便使用宏 F1 得分制作自定义得分指标。
Recursive Feature Elimination code.
虽然我以前使用过特征重要性进行选择,但我从未实现过递归的特征消除方法,并且像往常一样,惊喜地发现在 Python 中做到这一点是多么容易。RFECV 方法根据交叉验证分数从大约 190 个特征中选择了 58 个:
Recursive Feature Elimination Scores.
然后对所选的特征集进行试验,以将交叉验证性能与原始特征集进行比较。(最终结果将在下一部分之后呈现)。鉴于这种方法的易用性,我认为它是您建模技能中的一个好工具。像任何其他 Scikit-Learn 操作一样,它可以适合一个 [Pipeline](http://scikit-learn.org/stable/modules/generated/sklearn.pipeline.Pipeline.html)
,允许您快速执行一系列完整的预处理和建模操作。
可视化降维
机器学习中有多种无监督方法用于降维。这些分为两大类:
通常,PCA(主成分分析)和 ICA(独立成分分析)用于可视化和作为机器学习的预处理步骤,而像t-SNE(t-分布式随机邻居嵌入)这样的多种方法仅用于可视化,因为它们高度依赖于超参数,并且不保留数据内的距离。(在 Scikit-Learn 中,t-SNE 实现没有transform
方法,这意味着我们不能用它来建模)。
降维场景中的一个新条目是 UMAP:一致流形近似和投影。它旨在将数据映射到一个低维流形,因此这是一种嵌入技术,同时保留数据的全局结构。虽然背后的数学是严谨的,但它可以像 Scikit-Learn 方法一样使用[fit](https://github.com/lmcinnes/umap)``[transform](https://github.com/lmcinnes/umap)
调用。
我想尝试这些方法,既可以减少可视化的维度,又可以将减少的组件作为附加特性添加进来。虽然这个用例可能不是典型的,但是尝试一下没有坏处!下面显示了使用 UMAP 创建训练和测试数据嵌入的代码。
Uniform Manifold Approximation and Embedding Code.
其他三种方法的应用完全相同(除了 TSNE 不能用于transform
测试数据)。在完成变换之后,我们可以在 3 维中可视化减少的训练特征,用目标的值给点着色:
Dimension Reduction Visualizations
没有一种方法能根据标签清晰地分离数据,这些标签遵循其他数据科学家的发现。正如我们之前发现的,考虑到我们可以访问的数据,这个问题可能很难解决。虽然这些图表不能用来说明我们是否能解决一个问题,但是如果有一个清晰的分离,那么它表明在数据中有某种的东西可以让一个模型很容易地辨别每一类。
最后一步,我们可以在应用特征选择后将缩减的特征添加到特征集中,以查看它们是否对建模有用。(通常应用降维,然后仅在降维后的维度上训练模型)。每个型号的性能如下所示:
FInal model comparison results.
使用降维特征的模型具有后缀 DR,而 GBM 之后的折叠数是指交叉验证折叠数。总的来说,我们可以看到选择的特征集(SEL)做得稍微好一点,添加降维特征损害了模型性能!鉴于较大的标准偏差,很难从这些结果中得出太多结论,但我们可以说梯度增强机器明显优于所有其他模型,并且特征选择过程提高了交叉验证性能。
这个笔记本的实验部分可能是我最享受的部分。始终学习保持在数据科学领域的领先地位不仅重要,而且对于学习新东西来说也是一种享受。
不断改进和获取新知识的动力是数据科学家的一项关键技能。
后续步骤
尽管对机器学习工具进行了详尽的报道,我们还没有找到解决这个问题的方法!
我们可以采取的一些额外步骤是:
- 自动化特征工程:详见本笔记本
- 过采样少数类:一种通过生成合成数据点来解决不平衡类的方法
- 进一步的特征选择:特别是在自动化特征工程之后,我们有了可能对模型性能产生负面影响的特征
- 集合或堆叠模型:有时将较弱的——性能较低的——模型与较强的模型结合起来可以提高性能
关于 Kaggle 竞赛的伟大之处在于,你可以在其他数据科学家的笔记本中读到许多这些尖端技术。此外,这些比赛在非关键任务环境中为我们提供了真实的数据集,这是一个完美的实验环境。
最好的竞赛可以通过鼓励友好的竞争、开放的工作分享和奖励创新方法来带来新的进步。
作为更好的机器学习方法竞争能力的一个例子, ImageNet 大规模视觉识别挑战导致了卷积神经网络的重大改进。
Imagenet Competitions have led to state-of-the-art convolutional neural networks.
结论
数据科学和机器学习不是不可理解的方法:相反,它们是组合成强大解决方案的一系列简单步骤。通过一步一步地解决问题,我们可以学习如何构建整个框架。我们如何使用这个框架最终取决于我们自己。我们不必奉献一生去帮助他人,但是接受一个更有意义的挑战是值得的。
在本文中,我们看到了如何将完整的机器学习解决方案应用于数据科学中的好问题,即构建一个机器学习模型来预测哥斯达黎加的贫困水平。
我们的方法遵循一系列流程(1-4 在第一部分中):
- 理解问题和数据
- 在探索性数据分析的同时执行数据清理
- 自动和手动设计相关特征
- 比较机器学习模型
- 优化最佳性能模型
- 解释模型结果并探索它是如何做出预测的
最后,如果在所有这些之后,您仍然没有完全理解数据科学,您可以继续探索技术并学习新的东西!
和任何过程一样,你只会在练习中进步。竞争是有价值的,因为它为我们提供了运用和发展技能的机会。此外,他们鼓励讨论、创新和协作,从而培养出更有能力的个人数据科学家和更好的社区。通过这个数据科学项目,我们不仅提高了我们的技能,还努力改善我们人类同胞的成果。
和往常一样,我欢迎反馈、建设性的批评以及倾听您的数据科学项目。我可以通过推特 @koehrsen_will 联系到。