TowardsDataScience 博客中文翻译 2016~2018(九十九)
强化学习可以使用更多的监督吗?
Apparently this is a popular video game. Video games are an area of apparently-relevant ML knowledge where my scope of understanding is woefully incomplete
当我最初读到这篇论文的标题通过预测未来来学习行动时,我满怀希望地认为,它将为一个我已经思考了一段时间的问题添加一个令人信服的解决方案:在头脑中没有特定目标的情况下,是否有可能教授一个强化学习模型来了解世界。这是真的:在某种意义上,这篇论文解决了这个问题,但我发现它比我希望的更有限。
本文的核心实现细节是,教导代理玩第一玩家射击游戏 Doom,而不是基于奖励值的学习,实际的学习是基于强迫我们自己建立一些小的可见测量值的良好预测:健康、耐力和杀戮。这到底是怎么回事?
Network architecture diagram from the Learning to Act… paper
网络最终产生的输出是一个向量,长度等于你试图预测的测量值的数量,乘以你可以采取的可能行动的数量,它代表了我们对我们每个可能行动的世界中的那些测量值的预测。例如,如果我们想象我们的一个动作是“向前一步”,那么向量中的元素 0、1 和 2 可能是我们对从现在起 3 步后的健康、从现在起 3 步后的死亡和从现在起 3 步后的耐力的预测,假设我们从当前状态“向前一步”采取动作。该载体有两个用途:
- 它帮助我们决定采取什么行动。在本文中,用于选择行动的代理的目标函数由权重定义,该权重指定了三个关键度量中的每一个在我们的目标函数中所占的比例。例如,我们可能对未来的健康赋予 0.5 的权重,对未来的耐力赋予 0.5 的权重,对未来的杀戮赋予 1.0 的权重。在这种情况下,我们采用模型对健康/耐力/死亡的预测,并采取行动,使加权组合在预期中最高。
- 它提供了模型训练的损失来源。一旦我们选择了要采取的行动,我们就可以观察预测测量的实际值,并可以根据预测和现实之间的差异来计算损失。这是一个简单的均方损失,用来训练我们的模型。
[下一段重点介绍如何创建预期行动预测向量的机制;如果您只是在寻找方法的整体直觉,请随意跳过]
继续向后工作,对应于每个动作的预测向量通过两个向量的组合来学习:期望向量和每个动作向量。这仅仅意味着我们两者都要学
- 代表我们平均期望的向量,例如,如果我们想象我们只是从动作分布中随机抽取动作,我们的预测会是什么,以及
- 一个向量,表示与每个动作相对应的期望值的“偏移”。例如,如果我们预测的平均期望值是(4,90,1),如果我们“向前一步”的预测是(5,88,2),那么“向前一步动作”的偏移量将是(1,-2,1)
您可能会注意到,期望向量比完整的动作偏移向量短得多,因为它总共只包含一组预测,而不是每个动作一组。而且,你可能是正确的:为了使向量数学起作用,期望向量被“平铺”,即一遍又一遍地重复,直到它与动作偏移向量的长度相同。这些“期望”和“行动”子网建立在三个输入源的基础上:当前状态的像素(进入卷积网络)、当前测量值(进入一组紧密连接的层)和当前目标向量,也就是前面在如何选择下一个行动的上下文中讨论的测量值的权重向量。如果你对为什么要添加目标向量作为输入感到困惑,我也是;我稍后会谈到这一点。
当你在普通游戏中从健康和最终杀戮的角度来看性能时,这种方法确实比两种当前非常流行的强化学习技术要好:双 Q 学习和异步优势演员-评论家(A3C)。
所以。这些都是令人印象深刻的图表。我的缺乏热情源于哪里?为了解释这一点,我认为稍微了解一下强化学习的理论是有益的。本质上不是定理或方程,而是强化学习问题的什么使它们首先变得独特和困难?
I regret nothing
在像国际象棋和围棋这样的游戏中,你需要学习长期策略,以便让自己更接近胜利。然而,至关重要的是,在任何给定的时间点,你的棋子的可见位置和预期的最终奖励之间没有人类已知的映射,例如获胜的概率。你不能说赢的本质是这里有 3 个棋子,这里有 4 个,等等,如果你达到了这个标准,你就赢了。这种映射是模型在训练过程中必须学习的。相比之下,在本文中,我们硬编码了观察变量和报酬之间的映射,因此模型需要学习的只是如何预测观察变量。
我认为这是我对论文框架感到沮丧的核心:模型预测的“度量”与其目标并没有太大的不同。目标只是测量值的加权组合。在(1,1,1)目标向量的情况下,这个模型框架相当于“预测从现在开始三步你将积累的奖励金额”。因为这些测量是由人类手工选择的,并手工映射到奖励上,它们似乎并没有真正实现我所希望的承诺:以一种更不受监督的方式从未来发生的事情中学习。
综上所述,我认为,如果你忘记了衡量与奖励的关系,只看它们相等的情况,这种模式与 DQN 和 AC3 相比的表现确实表明,在你经常获得奖励的环境中,这种模式具有很强的竞争力。在 DQN 和 AC3,行动的价值(/Q 函数)本质上是递归的:对行动和游戏结束之间将获得的奖励金额的预测。这篇论文建议,你可以通过直接优化从现在开始的几个步骤来做得很好,而不是使用更复杂的过程,通过长长的梯度传递链来到达游戏的结尾。在需要长期战略的环境中,这显然是不够的,但在更短期的情况下,这种降低的复杂性可能会提供很多价值。
总而言之,这篇论文的一个(间接)贡献是,它让我更清楚、更清晰地思考“学习一套行为”这一大伞下的不同类型的问题,以及这些问题的不同奖励结构如何能够、也应该引导你以根本不同的方式将这些问题概念化,这是我非常欣赏的。
*该论文实际上使用了一系列帧的测量结果,但就人类游戏时间而言,这是一个相对较短的窗口;3-4 秒。
Spotify 周日的图表与本周其他时间有所不同吗?
审视我自己的倾听行为,我经常承认,与一周中的其他时间相比,我在周日倾向于有不同的偏好。这一天,你只想以较慢的速度做事,包括 BPM。不过,我想知道,如果不仅仅是我,是否会有很多其他荷兰 Spotify 用户陪着我...根据我的经验,我注意到当你在周一看图表时(显示周日的热门曲目),你可以发现与本周其他时间相比有一些细微的差异。一些浮出水面的想法,进一步调查 Spotify 在周日和本周其他时间的前 200 名之间的差异。
数据集
- 我收集了从 1 月 5 日到 5 月 17 日荷兰的所有 Spotify 每日排行榜。这是通过网页抓取方法完成的。
- 为了更准确地了解工作日之间的差异,我必须检索所有排行榜上的艺术家的相关流派。这可以通过 Spotify 的 API 来实现。
- 为了查看声音是否有差异,我还检索了所有排行榜曲目的声学变量。这也是 Spotify 的 API 功能之一。
- 通过 Spot on Track 我设法获得了 Spotify 的 Easy on Sunday 播放列表中多个周日的曲目列表,从 1 月到 5 月。
声音的差异
在我之前在 Eurovision 发表的文章中,我描述了 Spotify 分配给音轨的声学变量。我们还可以利用这些来确定周日和本周其他时间的排行榜上的曲目之间是否有任何差异。所以基本上我们试图回答周日的星盘与本周其他时间相比是否有所不同。
如下图所示,我们可以断定声音和仪器与前几天相比表现出色。化合价(情绪)、dancebility 和能量表现略差。
看着这些指数得分,我觉得这很符合人们可能会认为周日更舒适的假设。效价(情绪)测量的指数为 0.95 也是有意义的,因为这个变量是从 0(悲伤)到 1(快乐)来测量的。
流派差异
当你在周一看 Spotify 排行榜时,你会立即注意到相当多的歌曲的流量和位置有所下降。为了更好地了解不同流派在工作日的份额,我检索了 Spotify 前 200 名中出现的歌曲/艺术家的所有相关流派。从那以后,对于每个流派,我都根据图表收录/流来计算每个工作日的份额。
与一周的其他时间相比,乡村音乐、流行音乐、创作歌手、新成熟音乐、灵魂乐、摇滚、民谣、独立音乐和荷兰流行音乐、独立音乐和摇滚音乐在周日的排行榜上所占的份额明显更高。
相反,我们看到像(荷兰)Hip Hop、Pop 和 EDM 这样的流行流派在周日有所下降,但与我们在周日看到高增长的流派相比,它们的份额在一周的其余时间里保持更加一致。
播放列表影响
Spotify 在荷兰最受欢迎的播放列表之一是他们的 Easy on Sunday 播放列表 。我以前注意到,这个播放列表的策展与周日的新图表条目有相似之处。通过查看从 1 月到现在的 19 个周日,我想更好地了解这个播放列表在那个特殊的日子对荷兰排行榜的影响。这个播放列表对周日的 Spotify 排行榜有直接影响吗?
平均而言, 32%的曲目 (32 首不同的曲目,因为播放列表由 100 首曲目组成)被放置在周日播放列表中,并在同一天(周日)出现在图表中。
可以肯定的是,它不仅仅是以流行音乐为特色,而是在整个一周内都出现在图表中,我对其他工作日做了同样的计算。事实证明,周一至周五和周六、**、**分别出现在排行榜和《周日轻松》中的曲目平均数量为 5.5% 和 16.6%,这意味着该播放列表在周末对排行榜有重大影响——导致相当多的新曲目仅出现一天。大多数曲目的位置范围在 101 和 200 之间,而播放列表位置高的曲目往往会进入前 100。
下图显示了在过去的几个月里,播放列表中当天就出现在排行榜上的歌曲的百分比。
放弃
- Spotify 给艺术家贴了很多不同流派的标签。对某些子类型进行了分组,以保持一个全球概览。
- 上面提到的所有分析和结果完全基于荷兰 Spotify 图表。因此,这些结果可能与其他地区不同。最后,这只是涵盖了 Spotify 平台的图表部分,不应被视为 Spotify 图表范围之外的收听行为的整体表现。
感谢阅读!如果你喜欢读这篇文章👏🏻很感激。
使用深度学习的犬种分类:一种实践方法
Preview of images from Stanford Dogs Dataset
问题
几天前,我注意到由 Kaggle 主办的犬种鉴定挑战赛。我们的目标是建立一个模型,能够通过“观察”狗的图像来进行狗的品种分类。我开始思考建立这样一个模型的可能方法,以及它可能达到的精确度。似乎有了像 TensorFlow 这样的现代机器学习框架,以及公开可用的数据集和预先训练的图像识别模型,这项任务可以以相当高的准确度解决,而无需付出太多努力和花费太多时间和资源。我将分享使用 TensorFlow 构建犬种分类器的端到端过程。
repo包含重现训练和使用训练好的模型运行推理所需的一切。
训练数据集
拥有一个好的训练数据集是迈向健壮模型的一大步。斯坦福狗数据集有大约 20000 张 120 个品种的狗的图片。数据集中的每张图片都标注了显示的狗的品种。你可能已经注意到,只有 120 个不同品种的大约 20000 张图片(每个品种大约 200 张图片)不足以训练一个深度神经网络。卷积神经网络(CNN)是公认的用于图像分类的最佳机器学习模型,但在这种情况下,没有足够的训练样本来训练它。它将无法从这个数据集中学习足够通用的模式来对不同的狗品种进行分类。最有可能的是,它会过度适应这少量的训练样本,从而降低测试集的准确性。有两种可能的方法来缓解缺乏训练样本的情况:
- 将 dogs 数据集与另一个更大的带有图像的数据集(即 ImageNet )合并,并在这些合并的例子上训练 CNN。
- 在一个更大的数据集上采用一个已经预先训练好的深度神经网络,切入其中,并附加一个额外的“分类头”,即几个额外的完全连接的层,Softmax 层位于它们的顶部。
第一种方法有两个很大的缺点:需要分析的数据量要大得多,而且在这个大数据集上进行训练需要花费更多的时间和资源。第二种方法似乎很有希望:必须在原始数据集上执行训练,并且训练仅具有几个完全连接的层的“分类头”将不需要大量的时间和资源。
在较小的数据集上训练带有“分类头”的预训练模型的方法被称为迁移学习。
迁移学习确实起作用的原因在于 CNN 的工作原理。有相当多的资源详细描述了这一点,例如cs231n.stanford.edu/。简而言之,在大数据集上训练的深度神经网络的底层捕获图像的低级图元(例如,轮廓和简单形状),使得这种知识对于所有图像是通用的,并且可以“转移”到任何图像识别问题。
神经网络模型
所以最终的神经网络模型如下:
图像被输入到初始模型中。Inception 模型的输出经过几个完全连接的(FC)层,最后 softmax 输出图像属于每个类的概率。只有代表“分类头”的 FC 层必须接受培训。初始模型保持冻结,并带有已经预定义的模型参数。
下载和准备数据
下一步是下载 dogs 数据集,并通过 Google Inception 模型进行预训练。从回购的根目录执行时,setup/setup . sh脚本将下载所有内容,进行解压缩,并放入适当的目录。下载和提取后的 Dogs 数据集是一组文件夹,在单独的文件中包含图像和注释。TensorFlow 有一个漂亮的数据集 API ,它可以更好地处理 TF Records 数据格式。这个想法是将所有的训练示例和它们的注释保存在一个文件中,所有的示例都以一个 protobuf 序列化的形式存储在这个文件中。TensorFlow Dataset API 可以有效地处理这种数据格式,并在训练期间以最少的磁盘 I/O 操作和内存需求加载所需数量的示例。有一个 python 脚本将原始 dogs 数据集转换成 TF 记录文件,以备训练使用:
它必须从回购的根目录执行。转换数据集可能需要大约 1 小时。每一个图像都被输入到初始模型中,并且它的输出与图像和其他注释一起被存储。这简化了训练,因为我们不需要在训练期间计算每个例子的初始输出,而是,它已经被预先计算并且准备好被使用。结果 TF Records 文件将在data/Stanford . TF Records . setup . sh 中脚本还下载并提取 Google 的 Inception 模型,表示为冻结的 TensorFlow 图。冻结意味着所有变量都被替换为常数并嵌入到图形本身中,这样就不需要为了将模型加载到 TensorFlow 会话中并开始使用它而将检查点文件与图形一起携带。初始模型在freezed/Inception/classify _ image _ graph _ def . Pb .中
培养
下一步是实际执行培训。首先,可能会给模型一个唯一的名称。第二,应该配置多个完全连接的层和这些层中的多个单元。可以在src/common/consts . py模块中配置。
默认情况下,有两个 1024 和 120 单位的完全连接层。并且输入层具有 2048 个单元,这等于初始模型的最后一层中的单元数量。
src/training/train . py做训练。学习率、时期数和小批量大小可以在脚本本身中配置:
另外,张量板可以启动用于训练监控:
有三个可用的度量:成本、测试集上的错误和训练集上的错误。默认情况下,错误率是针对训练集中的 3000 个示例和也有 3000 个示例的整个测试集计算的。我用以下超参数训练模型:
- 小批量= 64
- 学习率= 0.0001
- 纪元计数= 5000
以下是我在 TensorBoard 中获得的这三个指标的数据:
Cost
Test set error
Error on a sample from the training set
执行 5K 个纪元花费了大约 1 小时。培训结束后,指标具有以下值:
- 成本= 0.1
- 测试误差= 2.7%
- 训练误差= 2.5%
这两个错误在测试集和训练集上都非常低。并且由于训练集上的误差与测试集上的误差大致相同,因此不存在对训练集的严重过度拟合的症状。
冻结模型
一旦模型被训练,其优化参数被存储在的检查点文件中。/检查点目录。为了有效地重用模型进行推理,最好将它作为一个冻结的张量流图,并将参数嵌入到图本身中。这可以使用src/freezing/freezy . py:来完成
该脚本按以下顺序执行几项操作:
- 将初始模型和“分类头”模型加载到同一个 TensorFlow 会话中,并将它们一起绑定到单个计算图中,以便初始模型的输出直接进入“分类头”模型的输入。一旦绑定完成,脚本就会在文件系统上序列化图中的复合模型。此时,图形还没有冻结,因为在训练期间计算的模型参数仍然在检查点文件中。
- 使用 tensor flowfreeze _ graph函数冻结上一步生成的图形。它从检查点文件中获取模型参数,并将它们注入到图形变量中。图形变量依次被转换成常量。结果文件转到。/冻结了目录下的型号名称。
推理
一旦冷冻模型准备好了,就可以对任意图像进行分类了。src/inference/classify . py脚本能够对存储在文件系统上或作为 HTTP 资源可用的狗图像进行分类。在幕后,它加载冻结的图形并将图像输入其中。这里有两个例子来说明推论是如何对艾尔代尔梗和西施犬起作用的:
如果你只是想玩玩推理是如何工作的,有一个 docker 容器,里面装着所有的代码和冻结的模型。它公开 Python notebook 进行推理。它实际上已经为在 docker 容器内部进行培训做好了一切准备。可以使用以下命令启动容器:
一旦容器启动,浏览浏览器到http://localhost:8888/notebooks/Inference.ipynb,你将能够对你自己的图片进行分类。
错误分析
仔细研究机器学习模型未能正确分类的例子总是一个好主意。脚本src/analysis/training _ perf _ analysis . py生成CSV 文件(它转到 metrics/training_confusion.csv ),其中包含所有训练示例的预测和实际品种。
通过从 training_confusion.csv 加载数据,可以绘制混淆矩阵:
这里很难进行详细的分析,因为品种太多了。让我们试着找出前 30 对分类错误的品种(如何做的例子可以在 Confusion.ipynb 中找到):
Top 30 misclassified pair of breeds
可以看出,这一对“丝毛梗/约克夏梗”在错误分类方面是绝对的领导者,如果我们研究一下这两个品种的狗看起来像什么,这确实是有意义的。
丝毛梗和约克夏梗似乎经常被人混淆。更多详情在本文。
你喜欢狗吗?
如果你认为自己是个爱狗的人,你可以直接问模特你是什么品种:)就我而言,我得到了以下答案:
Miniature Pincher! What?
结论
正如我们所见,如果您可以访问预训练的深度神经网络和 TensorFlow 等现代机器学习库,即使您没有足够的训练图像和/或计算资源,也可以训练一个鲁棒的图像分类器。
那是什么品种的狗?
利用深度学习确定狗的品种。
我参加了这个游乐场 kaggle 竞赛,目标是创造一个能够从照片中确定狗的品种的分类器。该数据集包括 120 种狗。下图显示了每个品种的狗的数量在 60 到 130 之间。
number of dogs VS breed
我们将使用建立在ResNeXt-50网络架构上的预训练模型。该模型在 ImageNet 数据库上训练,该数据库包括分布在 1000 个类中的 120 万个图像。
改善深度学习模型的关键实践
数据扩充:
要改进一个 DL 模型,最重要的事情就是给它更多的数据。如果你持续训练你的模型一段时间,它会开始过度拟合。
过度拟合意味着模型正在学习识别训练集中的特定图像,而不是学习可以转移到验证集中的一般图像。 如果您的训练集损失显著低于验证集损失,则模型过度拟合。它不能在验证集中再现高精度,因此,它在测试集中的表现同样差。
修复过度拟合的一种方法是有效地向模型提供更多数据。我们可以收集更多的数据,但另一种更简单的方法是数据扩充。这是指以不应该影响图像解释的方式随机改变图像,例如水平和垂直翻转、放大和缩小、改变对比度和亮度等等。
6 different versions of the same image.
学习率查找器:
学习速率决定了您希望在梯度下降的帮助下更新权重(或参数)的快慢。学习率是最难设置的参数之一,因为它会显著影响模型性能。
如果学习率太小,梯度下降会非常慢。另一方面,如果学习率太大,梯度下降会超过最小值。它可能无法收敛,甚至发散。
为了找到最佳的学习速率,我们将使用 Leslie N. Smith 在 2015 年论文中开发的用于训练神经网络的循环学习速率的技术。
****
这个想法是不断增加学习率指数,直到损失停止下降。
最初,当学习率较低时,损失改善不多。随着学习率的增加,损失将在一段时间内显著改善,直到学习率变得太大,损失迅速增加。这是因为随着学习率变得太大,我们开始偏离最小值。
我们需要在图上选择一个损失减少最快的点。在这个例子中,当学习率在 0.01 和 0.1 之间时,损失函数快速减小。
重启随机梯度下降(SGDR):
这与学习速率退火的思想密切相关
当你越来越接近损失最小的点时,你应该开始降低学习速度,以便准确地到达正确的点。这种在训练时降低学习率的想法被称为学习率退火。****
实现这一点的“黑客”方法是逐步退火,即使用特定的学习速率一段时间,当损失停止改善时,手动降低它。一个更好的方法是使用函数形式。余弦曲线的一半似乎是完美的拟合。它会在一段时间内保持较高的学习率,然后在接近最小值时迅速下降。
当我们想避免陷入函数的局部极小值时,SGDR 就出现了。陷入局部最小值意味着我们不在重量空间的弹性部分,由于重量的小变化可能导致损失的大变化。因此,SGDR 使用的技术提高了我们的模型找到函数的全局最小值的能力。
Iteration VS Learning-Rate for SGDR
基本思想是在一定次数的迭代后重置我们的学习率,这样如果我们出现停滞,我们就可以跳出局部最小值。在实践中,这被证明是对普通 SGD 的一个重大改进。
如果周期太短,我们就没有给 SGD 足够的时间去寻找最小值。我们需要一种方法来延长我们降低学习速度的时间。我们可以以倍增的方式延长迭代次数,而不是在一定次数的迭代后重新开始。
不同的学习率:
如前所述,我们正在使用一个预先训练好的模型。这意味着我们只是在预训练模型的顶部添加一些层,并且只训练新添加的层,称为 密集层 。这是一种迁移学习。
迁移学习是使用在一个过程/活动中学到的知识并将其应用于不同任务的过程。
我们可以通过在卷积层和密集层上进行训练来改进我们的模型。虽然,我们不需要像后期的密集层那样改变前期的卷积层。这是 差异学习率的基础。
****不同的学习率意味着在我们的培训中,网络的不同部分有不同的学习率。其思想是将各层划分为不同的层组,并为每组设置不同的学习速率,以便获得理想的结果。
红色图层学习基本特征,如边缘、形状,中间的蓝色图层学习与数据集相关的特定细节。
鉴于上面的陈述,过多地改变初始层的学习权重不是一个好主意,因为它们已经擅长于它们应该做的事情(检测像边缘等特征)。中间层将了解复杂的特性,如果我们稍微修改它们,这些特性可能在某种程度上有助于我们的任务。所以,我们想稍微调整一下。
在这方面,不同的学习率有助于我们。我们现在可以把一个样本网络想象成三层组(红、蓝、绿),并设置不同的学习速率。最初的红色层将具有较小的学习率,因为我们不想过多地干扰它们,中间的蓝色层将具有比初始层更高的学习率,而最终的绿色层将具有最佳的最高学习率。
初始层和中间层的学习率的多少取决于预训练模型和我们需要的模型之间的数据相关性。例如,如果任务是创建一个狗/猫分类器,并且我们的预训练模型已经擅长识别猫,那么我们可以使用较小数量级的学习率。但是如果我们的任务是在卫星图像/医学图像上创建一些模型,那么我们的学习率会稍微高一些。
测试时间增加(TTA):
在测试阶段,我们所有的测试图像在通过我们的模型时都会被自动裁剪成一个正方形。这样做的原因是一种次要的技术细节,但如果你有不同的图像尺寸,GPU 不能够有效地执行。这可能会在未来得到解决,但就目前而言,这是我们拥有的技术状态。 这可能会导致图像的一些非常重要的特征被遗漏,而这些特征对于图像的准确预测至关重要。 在测试时间增强中,我们将随机进行 4 次数据增强,以及未增强的原始数据(中间裁剪)。然后,我们将计算所有这些图像的预测值,取平均值,并将其作为我们的最终预测值。这确保了我们在这 5 个不同的方块内捕捉到整个画面。
结果
使用上述实践,我能够在验证集上实现 92.6%的准确率,即模型之前没有见过的图片。
参考
- fast.ai
- 莱斯利·史密斯。训练神经网络的循环学习率。 arXiv 预印本 arXiv:1506.01186
- https://medium . com/38 th-street-studios/exploring-random-gradient-descent-with-restructs-sgdr-fa 206 c 38 a 74 e
- https://towards data science . com/transfer-learning-using-differential-learning-rates-638455797 f00
DOGNET:人工智能模型能骗过人类吗?
建造一只 DC 猎犬来创造金毛猎犬的图像,并通过一项调查来测试人们是否能区分真假图像
实验很简单:机器学习(ML)模型能否产生人们会误认为是真实的金毛猎犬图像?选择狗的原因…是因为狗很棒!
在我们当前的气候下,我们经常听到“假新闻”这个词,随着 ML 模型变得越来越先进,他们创建非人类内容的能力只会越来越好。因此,我认为让人们有机会测试他们辨别“真实”或“虚假”图像的能力是合适的。为创建这些图像而构建的 ML 模型被恰当地称为 DOGNET,它来自于一个称为 GANs(生成对抗网络)的模型分支。
尽管 DOGNET 大多有点好玩,但 GANs 也有现实世界的应用:它们有能力生成新内容、增强图像、填充缺失内容,甚至检测医学成像中的实体。
GAN 是如何工作的?
在 GAN 中,两个神经网络相互竞争;姑且称之为生成器和鉴别器吧。对于生产者来说,一个很好的类比是将其视为一个伪造者,试图制造假币。鉴别者的工作就像警察一样,试图发现欺诈行为,并确定货币是假币还是真币。
GAN 的目标,特别是我们的生成器,是最大限度地提高其创造假东西的能力,鉴别器会将其归类为真的。为了实现这一点,鉴别器将被给予来自生成器的例子或者真实的例子,并且它必须决定所呈现的是“真实的”还是“虚假的”。
如果生成器未能生成足够假的图像,它将受到处罚,当鉴别器说一个真实的例子是假的时,同样的情况也会发生。保持两个神经网络的训练平衡很重要:拥有一个太擅长识别假货的鉴别器会阻止生成器学习,反之亦然。
建筑狗网
DOGNET 模型是使用 TensorFlow 构建的深度卷积(DC) GAN。它在 AWS SageMaker 上使用 ml.p2.xlarge GPU 实例进行了 120,000 次迭代训练。训练数据集由 300 张金毛寻回犬图像组成,这些图像在狗的颜色、头部位置、嘴部位置和环境方面都有所不同。随着模型的训练,我们可以查看生成器组件在学习创建狗的图像时产生了什么:
Generator output images at different iteration steps
Animation of Generator training
在这个过程中,模型并不总是正确的。这里有几个我最喜欢的尝试:
Model training producing some interesting results
实验和结果
一旦模型生成了我认为不错的金毛寻回犬图像,我就想测试人们是否能从训练数据中的实际例子中区分出模型生成的图像。为此,我整理了一份简短的调查,由同事、家人、朋友和数据科学界的其他专业人士填写,共收集了 104 份调查回复。
下表总结了这些数据,受访者必须首先从四个选项中识别“真实”图像,然后从四个选项中识别“虚假”图像(正确答案以绿色表示)。
Table of survey responses: Q1. Select which image you think has not been created by our model. Q2. Select which image you think has been created by our model
结果显示,这并不是一项容易的任务:只有 24.0%的受访者正确回答了 Q1,29.8%的人正确回答了 Q2,只有 12.5%的人两个问题都答对了。
应用二项式检验表明,对于这两个问题,不存在大于预期的 25%的显著差异(Q1 p=0.63 [单侧];Q2 p=0.15 [单侧])。换句话说,在选择正确的图片方面,参与者并不比随机挑选的人强多少。
养狗会影响你的机会吗?
对于 Q1 来说,正确回答率没有太大的区别:在那些不养狗的人中,22%回答正确,在那些养狗的人中,26%回答正确。在 Q2,22%的非养狗者猜对了,相比之下养狗者只有 38%。尽管准确性有所提高,但卡方检验显示这些变量之间的关系并不显著( χ 2 [2,N = 104] = 3.08,p=0.08)。换句话说,从统计数据来看,拥有一只狗并没有增加你识别 DOGNET 产生的“虚假”图像的机会。
结束语
虽然 DOGNET 被设计成一个有趣的实验,但它确实揭示了当它与真正的狗图像放在一起时,它产生的输出对我们来说是难以区分的。与典型的照片相比,这些图像的分辨率显然较低,但它确实提出了一个有趣的问题:随着这些模型的不断发展,我们是否仍然能够在我们的在线内容中区分“事实”和“虚构”?
我将给你们留下我的狗韦斯利的最后一张照片,我可以肯定地告诉你们,它是真正的:D
Source: Christopher Doughty
在 Google 云平台的命令行上做数据科学
数据工程是关于收集和收集数据,以适当的方式存储数据,进行一些处理并提供给数据科学家。
每个数据科学家在享受总是期待的建模阶段之前,都必须面对许多数据工程和数据准备任务。此外,当开始一个新项目时,你必须考虑选择正确的语言和平台的权衡。
此刻抛开平台,R,Python,Julia,Matlab,Octave 等。是数据科学中使用的一些语言吗,特别是 R 和 Python,它们在过去几年中有了很大的发展,并且有很大的社区支持。
然而,现在我想解释你如何通过使用你的操作系统命令行来面对许多初始任务,以及 shell 如何必须是你的堆栈的一部分。
我们将发现像 curl、 sed 、 jq 或 csvkit 这样的命令行程序如何通过编写更少的代码来简化您的许多重复任务,通过使用低级接口使其可移植甚至更快。
在这篇文章中,我们将一起使用这些神奇的工具,不需要任何 IDE、笔记本等就可以通过管道传输它们的命令。下载、转换、转换并加载到大数据仓库中。
这些数据由EMT de Madrid(Empresa municipal de transportes de Madrid)发布,可在http://open data . EMT Madrid . es获得,这是一组文件,记录了从 2017 年 4 月到 2018 年 8 月 BiciMad (马德里的公共自行车租赁服务)用户的所有旅行。
© Oriol Salvador (www.flickr.com/photos/boar…)
该集合 ATOW 由 17 个文件和 26.35 GB 的 28.550.144 条记录组成,其中每一条记录记录了两个自行车站点之间的自行车旅行,这两个站点的信息也在一个单独的文件中提供,我们将在后面展示。
为了下载所有这些文件,我更喜欢做一些 web 清理,这样我甚至可以自动下载并以编程方式获取新数据。
这可以使用命令行轻松完成。首先,我们必须检查所有的链接有一个共同的模式来识别所有的文件。通过使用浏览器开发人员控制台,我们可以检查 DOM 和 HTML 文档源代码来找到链接。
前面的图片显示了所有的文件都有一个共同的结构,所以,是时候做一些编码了!
可选择的
我喜欢无服务器架构和云计算,因为它们通过向每个数据科学家提供无限、可扩展、容错和廉价的资源,使数据科学民主化,而不需要特定的硬件或系统维护。谷歌云平台是我最喜欢的平台之一,我将使用它来启动一个计算引擎实例,并在那里执行所有命令。
这基本上和在我自己的笔记本电脑上做是一样的,但我将受益于谷歌云数据中心的巨大带宽。Google 还为所有机器提供了 Google Cloud SDK,无需管理本练习最后步骤所需的身份验证即可使用。这非常符合我做敏捷数据科学的想法。
我们有几种方式与谷歌云平台互动:一个令人敬畏的网络界面,强大的 API,主要编程语言的库,…和实用的 SDK。因为我将只使用 shell,所以 SDK 是我的首选。通过使用它,我也可以确信所有的德 GCP 命令可以在任何操作系统中执行,并很容易向你展示我在做什么。
如果你想自己做,你可以在这里有指令下载并在你的操作系统中设置它,但是如果你使用的是 Linux 或 Mac(我希望你这样做),它就像:
curl https://sdk.cloud.google.com | bash
exec -l $SHELL
安装完成后,您可以通过以下方式开始安装:
gcloud init
对于上一步,你需要一个谷歌云平台帐户。是免费。
现在我准备启动一个虚拟机。我不需要一个非常强大的硬盘,但必须有足够的存储空间来下载所有文件,所以我会安装一个 200G 的硬盘。
gcloud beta compute --project=datascience-open-data instances create bicimad-vm --zone=europe-west1-b --machine-type=n1-standard-2 --subnet=default --network-tier=PREMIUM --maintenance-policy=MIGRATE --service-account=874126907357-compute@developer.gserviceaccount.com --scopes=https://www.googleapis.com/auth/cloud-platform --image=ubuntu-minimal-1804-bionic-v20180917 --image-project=ubuntu-os-cloud --boot-disk-size=200GB --boot-disk-type=pd-standard --boot-disk-device-name=bicimad-vm
一旦部署了虚拟机,be 就可以从 Google Cloud Shell 或我们的本地计算机登录到它:
gcloud compute --project "datascience-open-data" ssh --zone "europe-west1-b" "bicimad-vm"
下载数据
现在,我们准备将文档源代码下载到本地文件中:
curl '[http://opendata.emtmadrid.es/Datos-estaticos/Datos-generales-(1)'](http://opendata.emtmadrid.es/Datos-estaticos/Datos-generales-(1)') > bicimad.html
我们可以检查源代码:
cat bicimad.html
在这里,我们再次检查文件链接是否具有相同的结构:
<li style="margin-bottom: 6px;margin-left: 12px;list-style-type: none;display: list-item;"><img src="/Imagenes/Extensiones-de-archivos/zip_logo.aspx"/><a target="_blank" href="/getattachment/8bb73c41-eab0-4e6a-ac92-80c8c68aacc2/201704_Usage_Bicimad.aspx" title="Datos de uso de Abril de 2017\. Nueva ventana" > Datos de uso de Abril de 2017</a></li><li style="margin-bottom: 6px;margin-left: 12px;list-style-type: none;display: list-item;"><img src="/Imagenes/Extensiones-de-archivos/zip_logo.aspx"/><a target="_blank" href="/getattachment/11054216-35d1-4003-b76b-8421c4a46eb4/201705_Usage_Bicimad.aspx" title="Datos de uso de Mayo de 2017\. Nueva ventana" > Datos de uso de Mayo de 2017</a></li>
现在我们必须得到那些文件链接。通过将sed与一些正则表达式知识结合起来,这非常容易:
cat bicimad.html | sed -n 's/.*href="\/getattachment\([^"]*Bicimad\.aspx\).*/\1/p'
这是我们得到的结果:
现在我们只需要用域名(http://open data . EMT Madrid . es)完成远程服务器中的文件路径就可以获得完整的 URL:
cat bicimad.html | sed -n 's/.*href="\/getattachment\([^"]*Bicimad\.aspx\).*/\1/p' | sed -e 's/^/http:\/\/opendata.emtmadrid.es\/getattachment/'
我们将sed所做的最终处理保存到一个临时文件tmp_file:
cat bicimad.html | sed -n 's/.*href="\/getattachment\([^"]*Bicimad\.aspx\).*/\1/p' | sed -e 's/^/http:\/\/opendata.emtmadrid.es\/getattachment/' > tmp_file
这个临时文件包含指向压缩数据文件的所有 URL:
cat tmp_file
结果是:
现在,我们只需浏览之前的每个 URL,并将它们下载到我们的系统中。一种方法是结合curl + parallel。这样我们可以同时下载几个文件。首先我们安装parallel:
sudo apt-get update
sudo apt-get install parallel
安装完成后,我们读取tmp_file,将所有链接发送到curl:
cat tmp_file | parallel -j 4 curl -O
这个过程需要几分钟。完成后,我们可以通过在当前目录中执行ls -l来检查下载的文件:
下一步是解压缩文件。我们需要先安装unzip:
sudo apt-get install unzip
…然后我们解压缩所有以 Bicimad.aspx 结尾的文件:
TMP_DIR="."
ZIP_FILES=*Bicimad.aspxfor FILE in `ls ${TMP_DIR}/${ZIP_FILES} `; do
echo $FILE
unzip -o $FILE
done
所有压缩文件都在同一个文件夹中解压缩,因此ls -l *.json显示为 Json 文件,其中包含数据:
接下来,我们将检查 Json 文件的内容,以理解提供给我们的结构化数据。为了处理 Json 文件,jq是我们最好的朋友,所以 web 将像我们通常做的那样安装它。然后我们打印任何文件的第一行:
sudo apt-get install jqcat 201808_Usage_Bicimad.json | head -1 | jq
我们可以检查这个 Json 是否遵循了从 MongoDB 导出数据的典型模式:
{
"_id": {
"$oid": "5b6779012f384302541d6813"
},
"user_day_code": "6c30d6e283ea7a160379fa9adb20b93d2c06e16853ad0804e26485e98066f6ba",
"idplug_base": 11,
"track": {
"type": "FeatureCollection",
"features": [
{
"geometry": {
"type": "Point",
"coordinates": [
-3.7078158,
40.4127144997222
]
},
"type": "Feature",
"properties": {
"var": "28005,ES,Madrid,Madrid,CALLE SAN BRUNO 1,Madrid",
"speed": 6.19,
"secondsfromstart": 190
}
},
{
"geometry": {
"type": "Point",
"coordinates": [
-3.7071841,
40.4156114997222
]
},
"type": "Feature",
"properties": {
"var": "28012,ES,Madrid,Madrid,PLAZA MAYOR 27,Madrid",
"speed": 3.47,
"secondsfromstart": 130
}
},
{
"geometry": {
"type": "Point",
"coordinates": [
-3.7048058,
40.4167895
]
},
"type": "Feature",
"properties": {
"var": "28013,ES,Madrid,Madrid,CALLE ARENAL 1,Madrid",
"speed": 3.61,
"secondsfromstart": 71
}
}
]
},
"user_type": 1,
"idunplug_base": 7,
"travel_time": 228,
"idunplug_station": 1,
"ageRange": 0,
"idplug_station": 43,
"unplug_hourTime": {
"$date": "2018-08-01T01:00:00.000+0200"
},
"zip_code": ""
}
每条记录为我们提供了以下变量:
- _id:记录标识
- user_day_code:当天的用户标识
- idunplug_station:起点自行车站
- idunplug_base:原点自行车站中的 base
- idplug_station:落客自行车站
- idplug_base:落客自行车站中的基地
- unplug_hourTime:租赁开始时间。
- travel_time:以秒为单位,自行车拔掉插头和插上插头之间的时间
- 轨道:行程路径
- 用户类型:1。-按年订阅的用户,2。-偶尔使用者,3。-企业用户
- ageRange: 1。-[0–16]年,2。- [17–18], 3.- [19–26], 4.-[27–40], 5.-[41–65], 6.- [>66]
- zip_code:用户邮政编码。
完整描述(西班牙语)
从前面所有的变量中,有一个具有特殊的结构: *track。*该密钥为 GeoJson 格式,这是一种在使用过程中注册自行车位置地理数据的便捷方式。看一下这个键,你会注意到系统每 60 秒跟踪一次自行车的位置。非常遗憾的是,这些信息在提供的某些时期是不可用的。
将数据加载到 BigQuery
Google BigQuery 可能是最强大的无服务器数据仓库,是在几秒钟内处理大量数据的好地方。可以将 Json 文件导入到 BigQuery 表中,但它还不能处理 GeoJson,尽管它支持地理信息系统(GIS)。
同时,我决定皈依*。json 文件转换成*。csv,但是在开始之前,建议更改文件编码。所提供的是 iso-8859–1 编码,这将在一些字符串中产生一些特殊西班牙字符的问题。
我们可以使用以下代码检查文件编码:
file --mime-encoding 201808_Usage_Bicimad.json
最好的解决方案是使用iconv将文件转换成 UTF-8:
iconv -f iso-8859-1 -t UTF-8 201808_Usage_Bicimad.json > tmp_file.json && mv -f tmp_file.json 201808_Usage_Bicimad.json
现在是时候从 Json ton CSV 转换了。正如之前指出的,并不是所有的每月 Json 文件都有带有地理位置值的track键,我已经请求 EMT 来解决这个问题。同时,我们将只处理带有该信息的对象。
首先,我们检查track是否存在,然后我们遍历所有的键,以获取它们的值,并以非规范化的方式将它们展平。一旦完成,我们可以使用 de '@csv' decorator 并将结果写入文件。
cat 201808_Usage_Bicimad.json | jq -r '. | select(.track != null) | .track.features[] as $track | [._id[], .user_day_code, .idplug_base, .user_type, .idunplug_base, .travel_time, .idunplug_station, .ageRange, .idplug_station, .unplug_hourTime[], .zip_code] + [$track.geometry.coordinates[0], $track.geometry.coordinates[1], $track.properties.var, $track.properties.speed, $track.properties.secondsfromstart]|[@csv](http://twitter.com/csv)' > 201804_Usage_Bicimad.csv
强烈推荐使用的处理 CSV 文件的工具是csvkit。尽管并非绝对必要,但我们将使用它以更好的方式检查 CSV 文件。以下是运行它所需的步骤:
sudo apt-get install python-dev python-pip python-setuptools build-essential
pip install --upgrade setuptools
pip install --user csvkit
export PATH=$HOME/.local/bin:$PATH
让我们检查一些随机列的结果:
cat 201804_Usage_Bicimad.csv | head -10 | csvcut -c 1,3,10,12,13,14 | csvlook --max-columns 6 --no-header-row
是时候将 CSV 文件加载到 BigQuery 中了!因为我们不能直接从本地机器加载数据,所以让我们将文件复制到 Google 云存储桶中。以下命令创建一个存储桶并将文件上传到其中:
gsutil mb open-datasets
gsutil -m cp 201808_Usage_Bicimad.csv gs://open-datasets/bicimad
然后,我们将在 BigQuery 中创建新的数据集:
bq --location=EU mk bicimad
然后,我们必须在数据集中创建一个表。在这个例子中,我包括了表模式:
bq mk --table bicimad.usage_201808 oid:STRING,user_day_code:STRING,idplug_base:STRING,user_type:INTEGER,idunplug_base:INTEGER,travel_time:INTEGER,idunplug_station:INTEGER,ageRange:INTEGER,idplug_station:INTEGER,unplug_hourTime:STRING,zip_code:STRING,latitude:FLOAT,longitude:STRING,var:STRING,speed:FLOAT,secondsfromstart:INTEGER
最后,我们创建一个加载作业,将 CSV 文件从 Google 云存储桶导入到新表中:
bq load --source_format=CSV --replace --quote='"' bicimad.usage_201808 gs://open-datasets/bicimad/201804_Usage_Bicimad.csv
向 BigQuery 加载大量数据时,建议使用分区表。分区表使查询数据变得容易,提高了查询性能并减少了您的账单。在这种情况下,我们将每个月的数据加载到不同的表中,这是一种旧的数据分区方式,但是可以随意改进。
加载作业完成后,我们可以查询数据并检查结果:
bq query --use_legacy_sql=false 'SELECT travel_time, unplug_hourTime, var FROM `datascience-open-data.bicimad.usage_201808` LIMIT 10'
或者我们也可以使用 Google Cloud 控制台中的 BigQuery UI,这是开发 SQL 查询的推荐方式:
现在一起!
因此,将 CSV 文件加载到我们的数据库的过程。为了加载它们,我们可以编写一个小的 bash 脚本来遍历目录中的所有 Json 文件,转换成 CSV 文件,上传到云中并加载到相应的表中。
这正是transform_and_load.sh要做的:
#! /bin/bashTMP_DIR="."REPORT_FILENAME_PATTERN=*Bicimad.jsonfor FILE in `ls ${TMP_DIR}/${REPORT_FILENAME_PATTERN} `; doBASENAME=$(basename $FILE .json)YEAR_MONTH=`echo ${BASENAME:0:6}`iconv -f iso-8859-1 -t UTF-8 "$FILE" > "$FILE.new" && mv -f "$FILE.new" "$FILE"cat $FILE | jq -r '. | select(.track != null) | .track.features[] as $track | [._id[], .user_day_code, .idplug_base, .user_type, .idunplug_base, .travel_time, .idunplug_station, .ageRange, .idplug_station, .unplug_hourTime[], .zip_code] + [$track.geometry.coordinates[0], $track.geometry.coordinates[1], $track.properties.var, $track.properties.speed, $track.properties.secondsfromstart]|[@csv](http://twitter.com/csv)' > $BASENAME.csvgsutil -m cp $BASENAME.csv gs://open-datasets/bicimadbq mk --table bicimad.usage_$YEAR_MONTH oid:STRING,user_day_code:STRING,idplug_base:STRING,user_type:INTEGER,idunplug_base:INTEGER,travel_time:INTEGER,idunplug_station:INTEGER,ageRange:INTEGER,idplug_station:INTEGER,unplug_hourTime:STRING,zip_code:STRING,latitude:FLOAT,longitude:STRING,var:STRING,speed:FLOAT,secondsfromstart:INTEGERbq load --source_format=CSV --replace --quote='"' bicimad.usage_$YEAR_MONTH gs://open-datasets/bicimad/$BASENAME.csvdone
我们将所有用户的执行权限添加到脚本中并运行它:
chmod 755 transform_and_load.sh
./transform_and_load.sh
完成后,我们可以查询所有 2018 年的数据,以获得按年龄范围划分的自行车租赁时长中位数(我不喜欢没有正态分布数据的平均值)。
SELECT
ageRange,
ROUND(APPROX_QUANTILES(travel_time/60,1000)[OFFSET(500)], 2) AS median_travel_time
FROM
`datascience-open-data.bicimad.usage_2018*`
GROUP BY
ageRange
ORDER BY
2 DESC
就自行车租赁持续时间而言,似乎最年轻的用户(年龄 1)也是最大的用户。我们可以知道检查他们是否也是最频繁的用户等等。
自行车站点数据
正如我之前告诉您的,我们将对包含每个自行车站点信息的数据集重复相同的步骤。
curl -o Bicimad_Estacions_201808.rar [http://opendata.emtmadrid.es/getattachment/8321277e-4f8b-4a45-89fd-63cbeefa1cf1/Bicimad_Estacions_201808.aspx](http://opendata.emtmadrid.es/getattachment/8321277e-4f8b-4a45-89fd-63cbeefa1cf1/Bicimad_Estacions_201808.aspx) && unrar x Bicimad_Estacions_201808.rar && rm Bicimad_Estacions_201808.rariconv -f iso-8859-1 -t UTF-8 Bicimad_Estacions_201808.json > tmp_file.json && mv -f tmp_file.json Bicimad_Estacions_201808.json
这是数据集中可用的信息:
{
"activate": 1,
"name": "Colón A",
"reservations_count": 0,
"light": 0,
"total_bases": 18,
"free_bases": 14,
"number": "106a",
"longitude": "-3.6877227",
"no_available": 0,
"address": "Calle Serrano nº 34",
"latitude": "40.4251002",
"dock_bikes": 3,
"id": 111
}
让我们转换成 CSV 格式:
cat Bicimad_Estacions_201808.json | jq -r '.stations[] | [.[]] | [@csv](http://twitter.com/csv)' > bike_stations.csv
因为这个数据集很小(12.9 MB),所以我们可以直接从本地磁盘加载到 BigQuery 中。
第一个 web 制作新表格:
bq mk --table bicimad.bike_stations activate:INTEGER,name:STRING,reservations_count:INTEGER,light:INTEGER,total_bases:INTEGER,free_bases:INTEGER,number:STRING,longitude:FLOAT,no_available:INTEGER,address:STRING,latitude:FLOAT,dock_bikes:INTEGER,id:INTEGER
然后我们创建一个加载作业:
bq load --source_format=CSV --replace --quote='"' bicimad.bike_stations bike_stations.csv
通过观察数据,我们可以看到每个自行车站点都有几个记录,记录了数据集未提供的时间段内freee_bases和其他字段的变化。
尽管如此,我们可以查看可用自行车站的数量:
SELECT
COUNT(DISTINCT name) AS total
FROM
`datascience-open-data.bicimad.bike_stations`
加载完所有数据后,我们可以删除计算实例:
gcloud compute instances delete bicimad-vm --zone=europe-west1-b --quiet
目前就这些。在下一篇文章中,我们将使用 SQL 进行一些探索性的数据分析。也不是 R 或 Python,我保证!
在一个数据文盲组织中做数据科学
A still from an animated visualization of shopper behavior in an instrumented grocery store.
科技媒体和行业博客充满了创新、早期采用者和数据智能公司的故事。数据科学家很容易设想在一个理解并重视他们的技术、推理和工作方式的组织中的角色。但是,当然,越来越多的传统企业正在雇佣数据科学家,并试图利用数据做出更好的决策。
我每天都与设计师、战略家、数据科学家、开发人员和研究人员组成的多学科团队一起工作。虽然我们生活在技术工作最具协作性的黄金时代,但我亲眼目睹了数据科学家在不太懂数据的环境中遇到的动荡。合法、准确、有效的科学很容易在翻译中丢失。下面我概述了一些给数据科学家的实用建议,我发现这些建议在数据盲组织中最有效。
1。询问“问题”,永远不要停止思考:我们解决的是正确的问题吗?
成功的数据密集型项目总是始于对业务目标的透彻理解——最好将其视为一个假设。作为一名数据科学家,你的工作是提出问题,并挖掘其更广泛的背景。努力弄清楚到底发生了什么,找出根本原因,并帮助引导提问者和被提问者不仅仅是一个*“是”或“否”*的问题,而是一个有效且相关的对手头更大问题的重构。
他们:“我们的哪个产品性能最好?”
你:“告诉我更多关于你目前定义最佳的方式?”
随着设计师、研究人员和战略家越来越多地使用数据来改善他们的决策,您需要回答的问题可能来自各种专业和领域。问题和假设通常来自数据科学领域之外的某个人——经理、设计师或研究人员。你要解开他们的问题,与提问者产生共鸣,了解他们假设的背景,并帮助他们决定前进的最佳路线。
2。 始终回答问题——即使答案是一个关于可能性而不是确定性的故事。
探索频道的节目流言终结者(2003–2016)当原始流言的结果以任何可能的方式被复制时,而不仅仅是当原始流言被终结时,才变得真正与观众相关。像亚当和杰米一样:得出没有相关性的结论是不够的,要洗手不干,继续前进。讲述一个关于相关性会是什么样子的故事,它在数据集中的什么地方出现——即使它在统计上不显著——并且用上下文来呈现它。解释如何证明他们的假设是正确的,并提供其他可能的答案作为支持证据。
当一个模型表现不佳时,过快地退出会对团队使用数据科学的态度产生负面影响。相反,尽可能向您的受众提供后续步骤:可以收集的额外数据,模型不收敛的潜在现实原因,或者描述性能确实有效的情况的子样本,以帮助解释为什么它不能达到高水平。
3。传达你的结果:准确性和细节是两回事。
想象一下,你正在建立一个预测模型来确定某件事情发生的可能性(百分比)。神奇的是,在没有你控制的情况下,在模型投入生产之前,一个邪恶的数据仙女会随机改变你所有的结果几个百分点(比如说 73%对 71%或者. 681 对. 657)。在现实世界的部署中,这些看似微不足道的数量可能意味着自动驾驶汽车乘客的生死之差。在向你的 C 级团队做演示时,这些金额的差异可能不会实质性地改变他们调整战略、营销计划或商业决策的方式。71%或 73%的市场份额(谁在乎!)将是打开啤酒的理由。
我的观点是使用环境决定一切。你的工作是了解你的工作成果将如何付诸行动,并据此设计你传达这些成果的方式。例如,在自动化生产环境中,包含尽可能多的细节。在这里,准确性很重要。你的模型可能需要学习,不断地被训练,或者适应多种可能性,没有理由回避或者抽象输出。
不同的是,对于一个人在回路的场景,你的结果需要在你的专家解释和最初询问的背景下形成。在你拿着事实和数据冲进会议之前,先想想你要表达的更广泛的观点。在这些情况下,没有人需要知道你的模型的表现有多差(或多好)——把这个细节放在你的后袋里作为支持证据。
用无关紧要的数字来压倒非数据科学家的听众,往往会分散你试图表达的更广泛的观点。当几个百分点不是生死攸关的情况时,用简单的语言给出你的结果的背景:
"这种预测模型工作得相当好,但在这些边缘情况下可以使用一些改进."
"你认为存在的相关性可能只是巧合."
4。建立共同语言并坚持下去。
像许多其他技术领域一样,数据科学非常晦涩难懂。即使通过图表直观地传达思想,代表性形式的可能性和变化也是巨大的,每一种形式都需要观众去理解,并学会如何阅读。如果你在使用口头和视觉语言的方式上不一致,很容易失去你的听众。
我见过最尖锐的演讲因不一致和定义不清的术语使用而脱轨,如模型、原始、加工过的、特征,或培训。往往是日常意义上的简单词汇引发了最大的问题。例如:“带标签的数据”在分类模型中有一个非常具体的定义,但非数据科学家可能会通过将他们自己的生活经验应用到“标签”这个词来误解你试图表达的观点*Excel 中的列不是都已经标注好了吗?如果所有东西都没有标签,你怎么知道你在做什么?如果我们没有在一些数据上贴标签,这些数据是坏的吗?*一致性和清晰性可以强化这些科学含义,防止你的观众自行定义术语并迷失在翻译中。要极其小心、耐心,并与你的听众保持一致。
借助视觉效果,从简单和高水平开始。不要在没有注释或解释的情况下第一次显示新的图表类型。在每一种已建立的视觉语言的基础上慢慢讲述数据的故事。使用一致的颜色、轴和符号。如果解释如何阅读图表比理解图表花费的时间更长,那你就做错了。
5。不要孤立地工作。
无论您是否注册,您现在都是组织内的教育工作者、主题专家和数据传播者。你的工作是你最好的教育材料,你的过程是最好的证据。记录一个项目的开发不仅仅是一个好的实践,它还是一个帮助他人理解你做什么和你如何做的强大工具。
我所做的绝大多数数据可视化都是为了让其他人能够了解我的思考过程,在我的团队中引发对话。努力实现一个开放、可视化的流程,让复杂的技术不仅仅被数据科学家理解。它可以帮助你以合作的方式对照最初的假设评估你的工作——突出误解、错误的假设和灵感的瞬间。
我发现,有一个空间来展示我的作品、草图和正在进行的可视化效果,对增加沟通和协作大有帮助。即使你不公开,也要让它公开。你需要成为新的数据文化的倡导者和催化剂。对于组织中的许多人来说,将数据科学视为他们永远无法理解的魔法太容易了。你有责任证明他们是错的。公开您的流程将增加您的组织对使用数据解决问题的实际意义的理解,并将数据文盲的工作场所转变为数据驱动的工作场所。
做分类项目的 EDA?pandas.crosstab 将改变你的生活。
探索性数据分析(EDA)是数据科学家工作的重要组成部分。事实上,根据 2017 年 O'Reilly 的数据科学调查,基础 EDA 是数据科学家最常见的任务。这是有原因的。除非完全靠运气,否则如果你不理解你的数据,你最复杂、最健壮的模型也不会有多大作用。他们肯定不会表现得像他们本该表现的那样好。
理解数据、数据特征及其分布对于任何成功的数据科学任务都至关重要,无论是推理还是预测。与你所期望的相反,EDA 的重要性并不在于技术,也与编程无关。这是将平庸的数据科学家与伟大的数据科学家区分开来的东西——决策。
作为一名数据科学家,你编程。你用统计学。你建立模型。但是你要做的最重要也可能是最困难的事情是做出许多选择。你的选择会带来后果。有时后果很严重。所以你尽你所能做出负责任的、明智的选择。EDA 是你做出选择的最佳时机。好的 EDA 是盲目工作、抱最大希望、做出深思熟虑的决定以实现目标之间的区别。
好吧,你明白了,埃达很重要。现在,让我们来看看pd.crosstab().的魔力
最近,我做了一个项目,使用了来自 UCI 机器学习库的银行营销数据集。它看起来是这样的:
每个观察对象都是银行的潜在客户,而“y”变量是他们是否订阅了新的定期存款。如您所见,这些数据包括每个客户的个人信息,以及银行之前向该客户营销的信息。这是一个相对干净的数据集,也是一个非常有趣的项目。主要的挑战是处理不平衡的类别,因为只有大约 11%的客户订阅定期存款。就像我说的,这是一个有趣的项目,值得一看。但是回到 EDA。
首先要决定的事情之一是模型中包括哪些变量。例如,让我们看看“工作”一栏。它列出了每个客户拥有的领域或职位。该数据集中有 12 种类型的作业。要决定是否要在您的模型中使用工作信息,您必须确定一个人的工作是否与订阅存款的可能性增加相关。从极端的角度来看这个问题,如果数据集中的每个“技术人员”都订阅了押金,我将假设技术人员更有可能订阅,我将使用这些信息来进行预测。另一方面,如果每种类型的工作都有相同比例的人订阅存款,那么工作信息将不会有助于做出预测。
那么,如何计算订阅每种工作类型的人的百分比呢?下面是我曾经使用的函数:bank.groupby('job').y.value_counts(),它将按作业类型对观察结果进行分组,并对每种作业类型的“y”出现次数进行计数。
它返回这个:
这回答了我们需要的问题,但它看起来很乱。如果我们能把 y 的值变成一个表格会怎么样?然后……这里是pd.crosstab(bank.job, bank.y),它给了我们这个:
Now that’s much prettier.
很好,我们有桌子了。我们可以观察一下,发现大约有 10%的女佣和服务人员缴纳了押金。很明显,更高比例的退休人员认购存款。所以我们可以对分布有个概念...但是我们想要更多。我们需要每种工作类型的订阅的准确百分比。
pd.crosstab()让你再次得到保护。就像这样添加' normalize '参数:pd.crosstab(bank.job, bank.y, normalize='index').现在看起来是这样的:
Looking good!
完美。目标变量的分类百分比细分。正是我们需要的。现在很清楚,工作类型可能是我们模型的相关信息。
您可以对分类任务的任何分类变量运行此函数。这是评估崩溃的完美方法。使用这个函数,并且只有这个函数,您可以获得对数据集非常重要的洞察力。明智地使用它,用好它!
用更少的数据做更多的事:在房地产估价上获得接近最先进的结果
Photo by Maximillian Conacher on Unsplash
整个美国房地产市场的价值总计数十万亿美元,是美国公民最大的有形资产之一。2016 年,没有自有住房的人通常会租赁空间,并支付超过 4700 亿美元的租金。
抵押贷款或房租通常是家庭每月最大的支出。出于这个原因和其他原因,理解决定房价波动的力量和属性是很重要的。租房者或购买者可以通过了解其他人为类似房产支付的价格来节省资金,出租者和出售者可以通过以公平的市场价格快速转让房产来节省资金。租赁者/购买者不会支付过高的价格,原始所有者可以通过快速租赁/出售来节省资金。
在这篇文章中,我将探讨除了一个单元的内在属性(例如,卧室、浴室、平方英尺等)之外的一些影响房价的环境属性。).通过使用各州和各市提供的大量地理空间数据,我可以提高用于预测房价的机器学习模型的准确性。测试案例是旧金山,它有一个强大的地理空间数据仓库。
文章提纲 :
- 目标数据集
- 地理空间要素
- 机器学习模型
- 模型评估
- 结论
目标数据集
我选择了两个数据集进行测试:一个是租金价格,另一个是房产价值。Airbnb 内部(insideairbnb.com/)提供了一个全面搜集的当前房源数据集,旧金山估价办公室提供了一份房产估价记录。经过一些清理,这些数据集将作为地理空间数据作为价格预测器的测试对象。
下面的地图显示了估价人房产的样本(上图)和所有 Airbnb 房源的位置(下图)。
A small sample (N=10,000) of SF Assessor dataset property locations. Darker areas are where locations overlap.
All 5900 Airbnb locations in SF as of July 2016. Darker areas are where locations overlap.
这两个数据集的位置分布存在明显差异。估价人的房产分布更加均匀,集中在市中心的单个地点(可能是高层住宅)。Airbnb 数据集更加分散,但集中在半岛东半部的几个地区。Airbnb 的数据不共享市中心高楼的单元集中程度,这暴露了 Airbnb 的位置是匿名的。
The Assessor properties are much more evenly distributed across the city, especially in the west.
Downtown, the Assessor properties accurately show that most of the properties are in tall residential towers. The Airbnb data are anonymized and therefore don’t accurately show the locations of listings.
匿名化使一个单位在给定区域内的实际位置随机化。简而言之,Airbnb 提供了一个单元所在的大区域——给定的房产坐标位于该区域的中心。下面是一个 Airbnb 房源的地图,显示了房源的大概位置。
This is an example of the location given on the Airbnb website for a property in SF. The location coordinates given in the dataset are somewhere within the shaded ellipse — there’s a lot of uncertainty.
因为我的目标是将地理空间数据精确地绑定到每个单元,Airbnb 的匿名化做法可能会影响模型。幸运的是,评估数据集包括每个属性的精确坐标,在关联地理空间数据时会有更少的模糊性。
Table of initial dataset features, before adding geospatial features.
基线数据集包括 Airbnb 数据集的约 5900 个房源和 SF Assessor 数据集的约 300,000 个房产。虽然 Airbnb 数据集中的样本较少,但它的特征(或预测值)比评估者数据多得多。Assessor 数据集大了两个数量级,但只包含 8 个特征,而 Airbnb 有 83 个特征。
运行基线模型后,我将添加地理空间要素-环境变量,如犯罪、噪音水平、与公园的距离等。—这两个数据集。通过这样做,我增加了机器学习模型可以用来更准确地预测价格的信息量和多样性。
地理空间数据
用于改进价格模型的数据来自各种来源,其中大部分可从三藩市(【datasf.org/】T2)公开获得。我确… 311 请求的数据集,两者都是地理定位的。尽管犯罪数据集包括无数的事件,我还是应用了九个类别。311 数据代表了广泛的类别:修复基础设施的请求、涂鸦、公民对各种违法行为的报告,以及许多其他内容。
以下是与故意破坏(上图)和盗窃(下图)相关的犯罪事件示例。
A sample of the vandalism incidents. Dark areas are where incidents overlap.
A sample of the larceny/theft incidents. Dark areas are where incidents overlap.
下面是 311 个涂鸦请求(上图)和人行道及路缘修复请求(下图)的示例。
A sample of requests to remove graffiti.
A sample of requests to repair sidewalks and curbs.
在某些街区和道路上,这些事件的发生率有明显的差异。以下是涂鸦移除和路缘/人行道修复请求的地理空间分布不同的区域示例。诸如此类的变化可能有助于预测整个旧金山的价格差异。
The larceny/theft (left) and graffiti (right) incidents have different concentrations and hotspots in western SF.
Larceny/theft (left) and graffiti (right) incidents are also distributed quite differently in central SF.
添加到数据集中的另外两个要素是旧金山县每个人口普查轨迹中报告的家庭收入中值(上图)和贫困率(下图)。这些将有望帮助区分社区之间的价格差异。
Census tracts colored by median family income. From light to dark, the income ranges from 280,000.
Census tracts are colored by percent of the population below the poverty line. From light to dark, the percentages range from 0% (parks) to 53%.
用于对这些地理空间数据(犯罪和 311 事件)进行矢量化的方法包括计算在一个物业位置的给定半径内的事件/发生次数(点)。在该要素类别中,越靠近犯罪事件集中点的属性的数量越多。
下面显示了这种计数技术的可视化,红点代表一个假设的属性或列表位置。
As an example, a region is magnified to show a specific location (red dot on right) relates to graffiti incidents.
The number of graffiti incidents are counted within the given query radius from a location. The method is repeated for every location and every specified crime incident or 311 request category.
上面的虚线圆圈表示给定位置的查询半径。对于每个位置,该算法计算犯罪和 311 个类别中的事件数量。然后,它将这些值作为新要素分配给每个位置。
这是使用 scikit-learn 的 KDTree(在邻居模块中)完成的,它的query_radius方法非常适合这个问题。下面是一个函数,用于在给定类别列表和包含每个类别坐标的数据帧的情况下,自动向熊猫数据帧添加要素。
我使用类似的方法来加入额外的特征,这些特征表明靠近公园和高噪声水平。与之前的数据不同,这些数据集由边界(或 shapefiles 中的多边形)表示。为了应用query_radius,我将这些线性边界转换成一系列规则间隔的点。当位置离公园和噪声边界最近时,这种方法会产生较高的计数值。这种方法的直观示例如下所示。
Another example of how perimeter boundaries are counted to approximate proximity to parks (this example) and different levels of noise.
An animation that depicts how the regularly spaced points are counted when they are within the query radius of a given property location.
这种方法也用于合并从旧金山公共卫生部获得的噪声级数据。原始噪声数据被存储为形状文件多边形,用于逐渐升高的噪声级别。然后,我将这些多边形转换成一系列规则间隔的点,并对每个地产位置进行计数。这些噪声级特征的较高值表明物业靠近繁忙区域或道路。
下面是两个噪波级别多边形的示例。左边的图像显示了最高噪波级别的多边形。右边是低噪声区域,分布更广——高噪声水平集中在繁忙的道路和高速公路沿线。
Two screenshots of GIS shapefiles for the 76 and 70 Ldn noise levels — they are just two examples of the 5 different noise levels used. The higher noise level, 76 Ldn (left), is concentrated around the busiest roads. The lower noise level, 70 Ldn (right), is much more widespread, but still absent from quite blocks in the city. The noise level is given in Ldn, which is an average from daytime and night noise estimated by a model that uses traffic data (SF Dept. of Public Health, map provided by the SF Dept. of Planning).
数据集和新增功能的总结:
对于 Airbnb 和 Assessor 数据集,我生成了 24 个新的地理空间衍生特征。通过添加/更改类别或调整查询半径,可以进一步调整所有地理空间数据,以优化模型准确性。
A table depiction of the features that will be added to the Airbnb and Assessor datasets.
机器学习模型
在吸收了所有数据之后,我测试地理空间特征是否改进了基线数据集的模型预测,基线数据集仅包括房产的内在属性(例如,卧室、浴室、平方英尺等)。).
用于评估模型准确性的指标是 Zillow 采用的指标,Zillow 还发布了租赁和销售的专有“Zestimates”。下面是最近 Zillow 模型估算租金价格的表格。Zillow 也有市区房产销售的模型结果,我们将用它来评估评估者数据模型。
A table from Zillow showing an example of the statistics they use to evaluate their models. San Francisco rents were estimated in this model but are not shown here. We mainly compare our models with the Median Error metric on the far right.
我使用的主要指标是中值误差百分比,或 ME% (上图右侧第一列)——半数模型预测的误差等于或小于 ME% 。
我还使用中位数绝对误差来判断模型在美元价值上的准确性。绝对误差中值有助于确定在试图建立公平的市场价格时,模型预测与人类估计相比有多大用处。
为了找到并改进预测租金和房地产价值的最佳机器学习模型,我使用不同的方法进行了一些初步测试:
- 线性回归(使用套索和岭正则化)
- 随机森林
- 极度随机化的树
- 梯度树提升(包括 XGBoost)
使用基线/初步测试中表现最好的模型,我通过网格搜索进行交叉验证,以找到表现最好的模型参数。
车型评测
Airbnb 数据集
平均而言,XGBoost 为 Airbnb 数据集生成了最准确的预测。在某些情况下,多个模型预测的集合平均会产生更好的结果。无论如何,地理空间特征的添加对提高预测的准确性没有什么帮助。下图显示了使用两种不同误差指标的模型的结果。这些图从左向右显示,显示了添加地理空间数据时模型的预测误差。虚线表示在评估模型之前对目标变量(价格/价值)进行对数转换时的模型误差。这对改进错误有最大的影响。
The plots showing the response of two different error metrics with the cumulative addition of geospatial features (x-axis). The two different curves show the results when target values are not log transformed (solid) and when they are log transformed (dashed).
添加地理空间要素时,模型的精度几乎没有任何提高。这个结果令人沮丧,但我知道 Airbnb 数据集很难与地理空间数据配对,因为它的坐标是匿名的。
因为清单评论中有大量的文本数据,所以我添加了来自给定清单的所有评论的 tf-idf 特性。此外,我计算了所有评论的情感分数,并将它们作为特征添加到列表中。这些特性的增加都无助于提高模型的准确性。这很可能是因为绝大多数评论都是正面的、多余的。下面是正面、负面和中性评论的百分比,以供比较。
A plot that summarizes the percentage of reviews that are more positive than negative (or more neutral than positive or negative). The review for Airbnb are all overwhelmingly positive.
评估员数据集
随机森林模型在几乎所有情况下都优于所有其他模型。使用 EC2 实例通过多重网格搜索计算出最佳参数,大大减少了处理时间。
随着地理空间特征的增加,所得到的模型得到了极大的改进,直接证实了环境属性对于做出更准确的预测是极其有益的。下面的误差曲线(就像上面显示的 Airbnb 数据集)显示,各种各样的地理空间数据显著提高了模型预测的准确性。此外,对数转换的目标变量,属性值,提高了模型的准确性;当目标值进行对数变换时,它们的分布不那么偏斜,并且可以更准确地预测。
The plots showing the response of two different error metrics with the cumulative addition of geospatial features (x-axis). The two different curves show the results when target values are not log transformed (solid) and when they are log transformed (dashed).
为了检查进一步改进这些预测的其他方法,我计算了评估者数据的学习曲线(如下)。该图显示了随机森林模型误差如何随着更大的训练数据集而改善。因为交叉验证得分曲线持续下降,我相信随着数据集的增大,模型误差会进一步降低。
Learning curve for the Assessor dataset illustrating that a larger dataset would lead to an increased accuracy of predictions (i.e., lower median absolute errors) because the cross-validation curve continues to trend lower.
结论
现在,我可以将我的模型结果与 Zillow 估计值进行比较。应该注意的是,租赁和销售 Zillow 模型都使用实际租赁和销售价值的大得多的数据集。Airbnb 数据集在技术上不是租赁价格——所有房源都是在不同的时间和频率租赁的,因此它们实际上不是公平的市场价格。类似地,评估财产价值是土地和改良的近似值,用于税收评估——实际销售价格可能相差甚远。这就是说,Zillow 有一个显著的优势,因为他们有更大和更准确的数据集。
Rental price prediction result, comparison to Zillow result for San Francisco.
Property value prediction result, comparison to Zillow result for San Francisco.
Zillow 租赁价格预测远好于我使用 Airbnb 价格的模型得出的结果。鉴于 Zillow 和 Airbnb 数据集之间的许多差异,这并不奇怪。虽然本文中没有显示,但 Airbnb 数据集的学习曲线表明,这种低准确性不会随着更大的数据集而得到改善。我们模型的绝对误差中值约为 21 美元——这意味着一半的预测与实际价格相差在 21 美元以内。
评估数据集和模型表现得更好,在 Zillow 房屋销售估计误差的一个百分点之内。由此得出的中位数绝对误差约为 37,000 美元。这一结果有力地表明了地理空间数据可以增加数据集的预测能力。由于样本比 Zillow 数据集少约 77%,我的模型误差几乎与 Zillow 的误差持平(在 0.6%以内)。
也有明确的方法可以进一步改进这个模型。这种分析没有考虑时间因素,如果将大规模市场趋势和逐年价格波动因素纳入数据集,可能会提高准确性。此外,犯罪和 311 数据集有许多类别是我的模型中没有的。每个类别都可以测试预测能力,并作为附加功能添加进去。
最后,我还想将谷歌街景图像纳入模型,用它们来预测残差。但这超出了本初步研究的范围。以后希望分享一下自己的进步。
你可以在我的 github 知识库(github.com/tmkilian/GA…)中找到本研究中使用的一些原始数据和 jupyter 笔记本。感谢阅读!
以智能方式进行 XGBoost 超参数调优—第 1 部分,共 2 部分
Picture taken from Pixabay
在这篇文章和下一篇文章中,我们将着眼于机器学习(ML)中最棘手和最关键的问题之一:超参数调整。在回顾了什么是超参数,或简称为超参数,以及它们与普通的可学习参数有何不同之后,我们介绍了三种旨在搜索最优超参数组合的通用离散优化算法:网格搜索、坐标下降和遗传算法。我们报告了一个实验的结果,在这个实验中,我们使用这些方法中的每一个方法,在一个取自 Kaggle 的 ML 问题的例子上,得到了好的超参数。虽然在我们的实验中,我们关注于优化 XGBoost 超参数,但是我们将展示的几乎所有内容都适用于任何其他高级 ML 算法。
什么是超参数?
最强大的 ML 算法以通过自动调整数千(甚至数百万)所谓的“可学习”参数来提取数据中的模式和规律而闻名。例如,在基于树的模型(决策树、随机森林、XGBoost)中,可学习的参数是每个节点的决策变量的选择,以及用于决定在生成预测时是采用左分支还是右分支的数字阈值。在神经网络中,可学习的参数是在每个连接上使用的权重,用于放大或否定从上一层到下一层的激活。
超参数调谐及其目标
然而,可学习的参数只是故事的一部分。事实上,它们是容易的部分。一个算法越灵活和强大,它就有越多的设计决策和可调整的超参数。这些参数由 algo“手动”指定,并在整个训练过程中固定不变。此外,算法通常不包括任何逻辑来为我们优化它们。在基于树的模型中,超参数包括诸如树的最大深度、要生长的树的数量、构建每棵树时要考虑的变量的数量、一片叶子上的最小样本数量、用于构建树的观察分数等。对于神经网络,该列表包括隐藏层的数量、每层的大小(和形状)、激活函数的选择、退出率和 L1/L2 正则化常数。
从计算的角度来看,监督 ML 归结为最小化某个损失函数(例如,MSE 或分类误差),该损失函数取决于数据训练输入数据( X t, Y t),我们用 a 表示的可学习参数,以及超参数。这里的关键观察是,这种最小化是通过让仅可学习参数变化,同时保持数据和超参数不变来实现的。为了选择最优的超参数集,通常的方法是进行交叉验证。给定一个超参数向量 h ,,通过使用最好的一组可学习参数 a* ,针对 h 的值,对一组保留的验证数据评估损失函数,从而评估其质量。象征性地,我们做到了
介绍超参数网格
关于超参数,需要注意的一件重要事情是,它们通常采用离散值,明显的例外是像辍学率或正则化常数这样的东西。因此,出于实际原因并为了避免进行混合连续-离散优化所涉及的复杂性,大多数超参数调整方法都是通过离散化所讨论的所有超参数的范围来开始的。例如,对于下面的 XGBoost 实验,我们将微调五个超参数。我们将考虑的每个值的可能范围如下:
{"learning_rate" : [0.05, 0.10, 0.15, 0.20, 0.25, 0.30 ] ,
"max_depth" : [ 3, 4, 5, 6, 8, 10, 12, 15],
"min_child_weight" : [ 1, 3, 5, 7 ],
"gamma" : [ 0.0, 0.1, 0.2 , 0.3, 0.4 ],
"colsample_bytree" : [ 0.3, 0.4, 0.5 , 0.7 ] }
为了解释这些在 XGBost 上下文中的含义,我们建议读者参考这篇帖子。
A section of the hyper-param grid, showing only the first two variables (coordinate directions).
请注意,尽管已将(连续)learning_rate 超参数的范围限制为仅 6 个值,将 max_depth 的范围限制为 8 个值,依此类推,仍有 6 x 8 x 4 x 5 x 4 = 3840 种超参数的可能组合。所有可能超参数的这个离散子空间被称为超参数网格。在下文中,我们将使用向量符号h=【h0,h1,…,hp】来表示任何这样的组合,即网格中的任何点。
三种超参数优化方法。
穷举网格搜索
穷举网格搜索(GS)只不过是一种强力方法,它以某种顺序扫描超参数组合 h 的整个网格,计算每个组合的交叉验证损失,并以这种方式找到最优的 h* 。一般来说,不鼓励使用字典顺序,即强加于超参数向量的字典顺序,应该考虑不同的顺序。原因是,使用词典排序,搜索很有可能在相当长的时间内集中在搜索空间中相当不感兴趣的部分。一个有趣的选择是以完全随机的方式扫描整个网格,也就是说,根据整个网格的随机排列。使用这种类型的搜索,很可能在早期遇到超参数空间的接近最优的区域。我们在下面的例子中展示了一些证据。
坐标下降
坐标下降 ( CD )是最简单的优化算法之一。这是一个迭代算法,类似于梯度下降,但更简单!基本思想是,在每次迭代中,我们的搜索向量 h 只有一个坐标方向被改变。为了选择哪一个,我们检查每个坐标方向转弯,并通过改变该坐标并保持所有其他不变来最小化目标函数。然后,我们选择产生最大改进的方向。当没有一个方向产生任何改进时,算法停止。要了解所有细节,我们建议读者参考维基百科文章。
这种简单方法的主要优点是,它很容易适应完全离散的情况,对于这种情况,梯度下降法给出的任意方向不容易使用。我们在这里提供了一个实现。
遗传算法
Picture from Pixabay
遗传算法(GAs)是一整类具有相当普遍适用性的优化算法,并且特别适用于高维离散搜索空间。遗传算法试图通过模拟一个(n 优化)问题的可行解的群体来模仿自然,因为它们经过几代进化并且强制实行适者生存。从上一代生成新一代有两种基本机制。一种是杂交育种,两个个体(可行解)结合产生两个后代。另一个是突变。在给定突变概率的情况下,任何个体都可以将他们的任何参数更改为另一个有效值。适者生存是通过让更适合的个体以比不太适合的个体更高的概率杂交来实现的。个体的适应度当然是损失函数的负值。关于全部细节,我们让读者参考维基百科或 AIMA ,第二部分第四章。我们自己的实现在这里可用。
一项实验
为了感受上面提到的每一种超参数优化方法,我们使用来自目前正在 Kaggle 上举行的家庭信用违约风险二元分类竞赛的实际数据进行了一次实验。我们只考虑了 application_(train|test)数据集,并执行了一个相当简单的数据准备步骤(参见函数 prepare_data 这里的)。此外,为了保持训练和验证时间短,并允许在合理的时间内充分探索超参数空间,我们对训练集进行子采样,仅保留 4%的记录(大约。12,000).为了验证,我们使用了单独的 3.2%的记录(大约。10,000).即使有这么少量的数据,对于给定的一组超参数,单轮训练和验证也需要大约 3 秒,考虑到我们打算扫描整个超参数网格,这是不可忽略的。由于刚才提到的原因,我们得到的交叉验证 AUC 值与排行榜顶部的值没有竞争力,后者肯定是利用了竞争对手提供的所有数据集中的所有可用记录。
如前所述,我们选择了 XGBoost 作为我们的机器学习架构。由于 XGBoost 获得了出色的准确性,以及它的计算性能,对于像这样的纯“表格”问题,它可能是 Kagglers 和许多其他 ML 实践者中最受欢迎的选择。
现在,对于上述三种超参数调整方法中的每一种,我们都进行了 10,000 次独立试验。每次试验首先将随机种子重置为新值,然后将 hyper-param 向量初始化为网格中的随机值,然后按照正在测试的优化算法继续生成 hyper-param 向量序列。当测试 GS 时,试验只是根据整个网格的随机排列遍历超参数向量。使用 CD,生成的超参数向量都是在 CD 算法的中间评估中尝试过的向量。当 CD 陷入局部最优时,它会随机一致地重新开始一个新的初始向量。在遗传算法中,超参数向量是包含在每一代人的“DNA”中的向量。
顺便说一下,我们能够进行这么多的试验,尽管每次 CV 损失评估的成本很高,这要归功于一种叫做记忆化的技术(【en.wikipedia.org/wiki/Memoiz… CV-loss,我们就将它保存在三种方法共享的查找表中,并且再也不必重新评估它。
在运行每个试验时,我们记录所有试验的超参数向量及其相应的交叉验证损失。下图显示了典型试验的行为,对于三种方法中的每一种,y 轴显示了 CV 损失的负值,在这种情况下,这就是我们最大化的 CV_AUC 指标。X 轴记录“时间”,即直到某一点的 CV-AUC 评估总数。
One trial for each of the three methods. All CV_AUC evaluations are plotted in blue and the running best CV_AUC is plotted in orange.
橙色“包络”线记录了“运行最佳”,这是在某一点之前所有函数评估中看到的最佳 AUC 值。在某种意义上,这一行是我们所关心的,因为每个方法总是返回所有被评估的超参数向量中最好的一个,而不仅仅是最后一个。请注意这三种方法在这一层的不同之处。GS 成功地逐渐最大化 AUC 完全是偶然的。坐标下降和遗传算法在寻找逐渐变好的值时所做的刻意“努力”从它们的图中也很明显。
然而,一项随机试验并不能说明全部情况。让我们来看看这三种方法中每一种方法的 30 个独立试验的“包络线”。
best-running AUC for 30 trials of each method
有趣…网格搜索和遗传算法的包络线很快就聚集到顶部,不像 CD 算法…这意味着,几乎所有 GS 和遗传算法的试验都很有可能比 CD 算法更快地给出接近最优的解。另一方面,总体最佳解决方案是通过一个 CD 试验在函数评估#40 附近实现的,我们没有看到其他方法的相同结果。此外,在函数评估#100 左右后,坐标下降法优于其他两种方法,因为所有 30 次试验都接近最优,并且显示出小得多的方差!
我们来看最后一个情节。如果我们在所有 10000 次试验中取 10%的最佳 AUC 会怎么样?这个数字很有趣,因为它让我们了解到大多数试验的最佳运行是如何随着评估次数的变化而变化的。换句话说,它给出了我们对每种方法所能预期的最坏情况的 90%的置信界限。这是:
啊哈!这是上述内容的更令人信服的证据,因为它告诉我们,在至少 90%的概率下,通过 CV-AUC 评估#90,坐标下降的随机试验将会看到 AUC 约为 0.740 或更好的超参数向量,而 GS 的相应值仅为约 0.738。这似乎是一个微小的差别,但就 ML 度量而言,这是非常重要的。也许比这更能说明问题的是,在达到稳定点之前,上图中 CD 曲线的斜率明显高于 GS 曲线。
另一方面,GA 似乎自始至终都被 GS 所主宰。这也许不应该让我们感到惊讶。一方面,遗传算法依赖于几个可调参数(在我们的公式中是超超参数),如世代大小、突变率、构建 DNA 序列的实例变量排序以及将 AUC 与杂交概率联系起来的函数。在我们的实验中,我们只尝试了几个设置。如果有不同的设置,GA 很可能会击败 gs。另一方面,众所周知(例如,参见第 148 页末尾的 AIMA ),当存在连续的基因块(在我们的例子中是超参数)时,遗传算法工作得最好,对于这些基因块,存在平均工作得更好的特定值组合。不清楚我们选择的 XGBoost 超参数的排序是否是任意的。
结论
在这篇文章中,我们阐明了在监督 ML 环境中参数和超参数之间的区别,并通过实验表明,就计算时间和电力而言,优化超参数可能是一件棘手和昂贵的事情。然而,我们看到,在发现超参数向量的速度和质量方面,有一些方法,如坐标下降,超过了普通的网格搜索。
请继续关注本系列的第二篇文章,在这篇文章中,我们将尝试另外三种优化方法:贝叶斯优化、hyperpt和自动调优。
在 CDMX 的各个省和我们的家。他把自己的一份工作交给了我…
www.lahaus.mx](www.lahaus.mx/)
在 R 中使用 Sentimentr 进行第一次情感分析
从字符串中提取情感的最快最简单的方法。
R 的 Sentimentr 包有利于分析心理学或社会学研究的文本。它的第一大优势是,它使情感分析变得简单,只需几行代码就可以实现。它的第二大优势是它纠正了反转,这意味着虽然更基本的情绪分析会根据形容词好将“我不好判断为积极的,但 Sentimentr 会识别出好的反转,并将其归类为消极的。
总而言之,Sentimentr 允许你快速进行复杂的情感分析,并直接将其作为回归或任何其他进一步分析的输入。
本文涵盖了如何开始。如果您正在寻找高级分析技术,请参考其他文章,如 Tyler Rinker 的 Github Repo 的自述。在本教程中,我将分析来自 He & McAuley (2016)数据集的亚马逊美容产品评论。但是,您可以轻松地修改代码,使其适合您自己的数据集。
Photo by Obi Onyeador on Unsplash
默认情况下,Sentimentr 使用 Jockers (2017)字典,这对于大多数情况来说应该是完美的。
安装软件包并加载数据
install.packages("sentimentr")
library(sentimentr)
前两个命令安装并加载 Sentimentr 包。接下来,我加载数据。因为它是 JSON 格式的,所以我需要加载 ndjson 包。然后我可以使用这个包的 stream_in 函数来加载 Amazon Beauty 数据。
install.packages("ndjson")
library(ndjson)
df = stream_in("AmazonBeauty.json")
head(df)
我还使用了 head 函数来快速查看前几行数据。正如您在自己的机器上执行此操作时所看到的,有一个名为 reviewText 的列包含评论。
做实际的情感分析。
sentiment=sentiment_by(df$reviewText)
这个命令运行情感分析。在这种情况下,我使用了perspective _ by命令来获得整个评审的总体情绪度量。在其他情况下,您可以使用情感命令(不带 _by)来获取每个句子的情感。
当这个命令运行时(确实需要一段时间),我将讨论函数将返回什么。该示例中的情感对象将是包括以下列的数据表:
- element_id —审核的 id 号
- 字数 —评论的字数
- sd —评论中句子情感得分的标准差
- ave _ sensition—评论中句子的平均情感得分
最有趣的变量是ave _ perspective,这是一个数字中评论的情绪。该数字可以取正值或负值,并表示情感的效价和极性。
分析情感得分
我们可以看一些计算出来的情绪得分的汇总统计。
summary(sentiment$ave_sentiment)
如你所见,大多数评论倾向于适度正面,但也有一些极端的异常值,最正面的评论为 3.44,最负面的评论为-1.88。这些值与平均值和中值相差甚远,应考虑将其剔除,以便进一步分析。
我还做了一个快速直方图来查看评论的情绪。
library(ggplot2)
qplot(sentiment$ave_sentiment, geom="histogram",binwidth=0.1,main="Review Sentiment Histogram")
将你的情感分数整合到原始数据集中
因为我对情感分数最感兴趣,所以我将通过将情感分数及其标准差集成回主数据集中来结束本教程。
df$ave_sentiment=sentiment$ave_sentiment
df$sd_sentiment=sentiment$sd
不要成为数据科学的崇拜者
Picture taken from Pexels (CC0 license)
成为一名数据科学家是最热门的工作之一,我理解为什么这是一个如此有吸引力的角色。在过去的几年里,我与不同级别(初级、高级)的一些数据科学家一起工作、面谈并雇佣了他们。在我的上一份工作公开并拒绝了 80%的申请后,我决定总结一些我在招聘时要注意的要点。
我期望的事情:
心存好奇。如果你只关心事物的技术方面,你不会成功。在开始之前,您需要了解数据来自哪里,如何生成,为什么是这样,以及如何最好地预处理数据。为了理解这一点,你需要亲自学习业务流程、产品和软件架构。最重要的是,任何可能影响数据源的缺陷。
有很强的技术背景,最好有很多数学知识。理想情况下,有一个高级学位。我希望有人能够理解和解释结果,我坚信你需要理解模型背后的基础知识,而不仅仅是能够将输入数据输入到 python 库中。对于一个入门职位来说,至少要能显示出你理解概率和统计的基础知识,以及相关性和因果关系之间的区别。
**弄脏你的手。**从理论上理解数据科学中应用的标准模型是一回事,但 Hadoop、Python 和 AWS 等工具需要与展示这些技能投入使用的项目相结合。完成学位后,尝试去 Kaggle 获取经验或从数据工程师做起。如果你的工作申请没有展示项目成果,也没有列出一门 edX MOOC 课程来证明你的 ML 背景,那就不要称自己为数据科学家。
了解产品和软件开发生命周期。同意,数据科学家的工作不同于软件工程师的工作。在大多数情况下,结果是不容易预测的,作为一个项目经理,我不能给你一个好看的用户故事与接受标准,你可以有效地估计需要多长时间。但是你需要能够在团队中工作,将你的代码投入生产,并且你需要能够维护和改进它。
成为优秀的沟通者。最有可能的是,你将和各个层次的人一起工作,从管理层到工程师到用户。无论这个人对数据科学的理解有多深或多浅,你都需要能够清晰地表达和解释你的方法和结果。毕竟,通常情况下,你不是为了酷而解决技术问题,而是通过应用数据科学来解决业务问题。
不要被虚假的数据所迷惑
作为新闻和信息的精明消费者,你应该警惕假新闻和包裹在统计数字中的谎言。
当你阅读或观看新闻时,你怎么知道你没有被欺骗或“被推动”?有了图表和图形,它可能看起来很科学,但真的是这样吗?
当你阅读新闻时,你相信作家和编辑,他们相信所呈现的是真实的。但事实并非总是如此。数据被操纵,图表被篡改来影响你的观点。有时是故意的,有时是无意的。不管动机如何,你最终都会成为假新闻的受害者。
不要做受害者。
还记得街区的珍妮曾经告诉她的粉丝们的话吗:“不要被我得到的石头所迷惑,我仍然是,我仍然是街区的珍妮!”所以,是的,不要被他们得到的数据所迷惑,他们仍然是躺在排行榜上的天才!
作为新闻和信息的精明消费者,你应该警惕假新闻和包裹在统计数字中的谎言。如果你遵循我下面的建议,你应该能够区分事实和虚构。
加载的问题和有偏见的调查
调查统计是影响公众意见的一种简单而有效的方法。你可以从调查中得到任何你想要的答案。你所需要的是向一个非随机的方便样本提出精心设计的问题。
这里有一个例子。假设你想把煤作为一种可行的能源。你是怎么做到的?你雇佣了一家市场调查公司,该公司设计了一项调查,并在大多数人从事煤炭相关业务的城镇实施。你向受访者提出以下问题:
"你认为‘清洁’煤会减少美国对中东石油的依赖吗?"
这项调查的结果产生了一个故事,内容如下:
“85%的美国消费者认为清洁煤可以减少美国对外国石油的依赖。高油价让美国中产阶级付出了代价。或许是时候重新审视一下煤炭了。等等,等等,等等……”
如果你正在阅读一篇关于某项调查的新闻,请注意陷阱,并问自己以下问题:
- 谁委托进行这项调查的?调查的发起者是否对调查结果有既得利益?在前面的煤炭示例中,您想知道煤炭行业是否赞助了该调查,或者该调查是否由环境倡导组织赞助。
- 谁回答了调查?受访者是普通的美国人还是依靠煤炭相关产业为生的人?
- 被调查者在可比较的选择中有真正的选择权吗?例如,将清洁煤与中东的石油进行比较公平吗?把煤和风能或太阳能相比怎么样?这公平吗?
你可能会认为我对煤炭行业过于挑剔。不是真的。这只是一个例子。事实上,你可以反过来想一想,如果一个可再生能源组织的意图是在光线不好的情况下展示煤炭,它可能会向调查对象提出一些有分量的问题。这里有一个例子。“你认为政府应该支持生产更多的风能和太阳能,以减少美国对‘脏’煤和中东石油的依赖吗?”
An inconvenient sequel: Are we listening yet?
但不全是脏煤或者热风?借助大数据和分析,市场研究人员对你的了解比你想知道的还要多。你认为某一类餐馆的顾客更有可能以某种方式投票吗?如果你的答案是否定的,请再想一想。
通过使用大量的数据,政治民意测验专家确定,共和党和民主党选民不仅在政治上有不同的品味,而且他们的味蕾也不同,因为他们在不同的场所吃牛排。对一些人来说是全熟,对另一些人来说是半熟!
不要被我得到的图表所迷惑
用图形和图表更容易理解。我们很容易成为假科学的牺牲品。当你看到一个图表时,不要只是相信它。首先寻找错误、遗漏和故意操纵的线索。记住那些试图欺骗你的人会试图操纵图表和夸大其词。
这里有一个来自福克斯新闻频道电视台的例子,你可能知道它不是民主党的忠实粉丝。2012 年 7 月,福克斯新闻频道公布了一张图表,突出显示了美国最高收入人群的税率变化。该网络倾向于降低税收,并认为如果对富人征税更少,他们就会花更多的钱来促进经济增长。
福克斯新闻频道想把计划中的税率变化描绘成一个巨大的增长。下面的图表显示,一旦布什总统对富人的减税政策到期,税率将会“大幅”增加。如果你比较两个柱的高度,你会注意到减税后的柱比另一个柱高很多倍。
但是如果你看这两个税率的话,还是挺像的。减税后 35%的税率与 39.6%的税率没有太大区别。但是图表夸大了差异,使用任意最小值作为纵轴。轴从 34%开始,而不是从 0%开始。
如果福克斯新闻频道选择 0 作为纵轴的最小值,你认为图表会有所不同吗?让我们自己尝试一下,因为我们已经有了绘制条形图所需的两个数据点。我只需要把上面图像中福克斯新闻频道的图表换成我的。
下面的图表显示了与福克斯新闻频道相同的信息,但是两种视觉效果截然不同。当柱状图使用 0 作为纵轴的最小值时,我们不再看到税率的大幅上升。
这张图表展示了一幅真实的画面,尽管可能很无聊,但确实是真实的。
伪科学同样致命
并非只有新闻媒体忙于夸大事实。科学家和研究人员也是夸张行业的一部分。例如,一个研究小组在 2016 年声称,他们可以使用高级分析技术通过面部识别罪犯。诡异!是的。但前提是这是真的。
让我先解释一下他们做了什么。他们将罪犯的照片(由警方提供)与普通人的照片进行了对比。他们声称他们的程序能够以 90%的准确率区分罪犯和非罪犯。
实际上,他们成功建造的是一个微笑探测器,而不是犯罪探测器。他们的程序测量一个人的鼻子和嘴唇边缘形成的角度。微笑的脸会比皱眉的脸报告更大的角度。因此,他们能够区分微笑和皱眉的脸。
你可能会问,微笑和犯罪有什么关系。没什么。
记住,在这项研究中,警察提供了罪犯的照片。现在,我不是面部照片的专家,但我知道被拘留者在被警察拍照时不太可能微笑。你不必相信我。你所要做的就是记住著名的英国演员休·格兰特在警察逮捕他和一名妓女在公共场所做出猥亵行为后是如何照顾他的。
肯定不是他的最佳时刻。
在警方公布的面部照片中,他没有笑。然而,将这张照片与电影海报中格兰特满脸笑容的照片相比,你会注意到不同之处。他的鼻尖和嘴唇边缘形成的三角形在他笑的时候比警察拍的照片有更大的角度。
On the left is the police mugshot and on the right is Hugh smiling!
基本上,研究人员能够比较从 LinkedIn 等网站上获取的笑脸和皱眉脸。研究人员可能夸大了他们的发现,从微笑和皱眉到发现罪犯。我不得不说,这是一个很大的延伸。
结论
在一个充斥着大数据和假新闻的世界里,你可能会被骗,以免提高警惕。不要轻易被数据和图表欺骗。做一个事实和新闻的精明消费者。
聪明的答案需要聪明的问题。询问关于谁收集了数据,谁支付了费用,谁分析了数据,以及谁写了这个故事。有了这些聪明的问题,你就不会被愚弄。
不要被称为江湖骗子:建立可信的模型
如果你的客户理解你的模型,他们会更容易相信。
肖恩·惠勒(Schaun Wheeler)几周前在发表的关于数据科学伦理的明智文章触及了数据科学家的一个重要问题——客户可能会认为你是个骗子。虽然惠勒是在不同的背景下说的,但值得考虑的是,像“预测分析”和“机器学习”这样的项目据说正处于炒作的顶峰(根据 Gartner 的说法),如果这是正确的,那么反弹可能就在眼前。
这也是不可避免的,尤其是如果你正在生产的东西可以被看作是一个预测(这意味着尽可能广泛的术语),你将是错误的——“所有的模型都是错误的”,毕竟。那么,显而易见的挑战是让你的观众相信你在做有用的事情,即使你的模型是错误的。
在这种情况下,一个重要的工具就是解释你的模型的能力。如果没有对输入变量如何影响模型输出的某种形式的解释,你就无法对正在发生的事情做出任何假设。如果没有关于数据告诉你什么的假设,你就无法将结果与现有知识进行比较。这反过来又会立即束缚你利用主题专家的知识来改进模型的能力。除此之外,无法在您的模型中直接使用主题专家的知识是一个错失为您的工作赢得盟友的机会,也是一个错失改进您的模型的机会。
为了给模型提供可信度,对它正在做什么的解释需要对用户有意义。如果你把模型呈现给用户,最好的情况是你的模型至少能说明一种他们已经知道的关系,以及另一种向他们展示新东西的关系。第一个确认模型已经找到了真实的关系。第二个说明模型发现了用户以前不知道的新东西。如果你不能提供任何与用户自己观察到的东西相一致的发现,他们不太可能会接受你的模型是可信的。同时,如果你不能给他们提供任何新的东西,他们不太可能接受你的工作是值得付出的。
直觉上,有两种策略可以用来建立既准确又可解释的模型。首先是建立一个内在可解释的模型,并努力确保其准确性。另一个是建立一个准确的和工作来解释它。我们将研究以下任一策略下的一些选项。
可解释且准确的模型
解释你的模型最明显的方法是从一开始就让它可以解释。如果可能,对连续因变量使用线性回归,或对分类因变量使用逻辑回归(二项式或多项式,视情况而定)或其他适当的 GLM(例如泊松、负二项式)。
提高模型预测性能的一种方法是采用收缩方法,如套索或岭回归。这些方法减少了与逐步回归相关的问题,即变量选择过程是谨慎的,因此是贪婪的,这可能导致高方差。作为一个例子,岭回归试图通过防止系数变得太大来减少这个问题,因此在完全丢弃变量和允许它们过度影响之间采取了中间路线。
如果放松对线性关系的假设,线性模型可以模拟更复杂的关系。这可以通过使用附加模型来说明有影响的非线性预测来实现。广义加性模型(GAM)使用诸如样条的平滑函数来表示非线性关系。Harrell 支持的合理预测模型策略的一个要素是放宽关键变量的线性假设(由主题领域的知识决定)
这一领域与之前的观察结果紧密相关,即客户需要在他们的模型中看到一些他们已经知道和不知道的东西——展示了一个 GAM,该 GAM 证实了客户之前的想法,即“年龄”是一个重要因素(他们确实知道的东西),但通过展示效果有一个峰值或逐渐减小(他们不知道的东西),扩大了他们的视角,为我带来了出色的客户认同。
黑盒子里的窗户
另一种选择是有一个表现良好的不透明模型,但提供其他模型来解释它。这种想法的一个扩展是用传统上认为不可解释的随机森林这样的算法建立一个准确的预测模型,并使用先进的技术来解释它。去年年底,Grover 王子写了一篇关于如何在 Python 中解释随机森林的文章——目前作者的观点是,使用 r 可以有更多的选择。
此外,使用随机森林来发现量化关系以及进行预测是一个活跃的研究主题——例如在最近由门奇和胡克发表的论文以及他们更早的论文中。更早的论文“量化随机森林中的不确定性”特别讨论了基于 U-统计估计整个随机森林中特定预测因子对因变量影响的大小和方向的策略。在 R 这里有一个这些想法的实验性实现,以及一个使用 jacknife 对随机森林进行推理的替代方法。
R 中的 inTrees 包也借鉴了类似的主题,它创建了一个树集合的规则集概要,是当今 R 中用于解释随机森林和其他树集合的几个包中的一个很好的例子。inTrees 方法是从构成集成的树中提取规则,并根据规则的频率和错误等属性,保留最高质量的规则作为集成的解释或总结。
上述方法仅适用于树的集合,包括随机森林和梯度推进机器。解释最近出现的任何算法的结果的一个选项是使用通用模型解释器,其中 LIME(本地可解释模型不可知解释)可能是最突出的例子。
与广义加性模型等方法相比,LIME 将根据具体情况提供解释。也就是说,对于代表要评分的情况的一组参数,时间解释代表不同变量如何影响该特定情况;如果将另一种情况呈现给算法,变量的影响可能会非常不同。
解释以水平条形图的形式呈现,显示不同变量影响的相对大小,向右延伸的条形代表使分类更有可能的变量,向左延伸的条形代表使结果不太可能的变量。在高层次上,变量的影响来自敏感性分析,该分析检查与感兴趣的病例非常相似的其他病例的分类结果。
这是 LIME 的局部方面——解释是在个案的基础上给出的,而不是作为一个整体为模型提供规则或指南。这是与前面讨论的树集合的方法的显著区别。此外,LIME 目前仅适用于分类器,而非回归模型。LIME 的一个 R 实现可从这里获得。
在当前环境下,确保用户能够信任模型的可解释模型的重要性日益得到认可;与此同时,幸运的是,不仅可解释模型的预测能力被正则化等技术扩展了,解释黑盒算法的方法也开始激增。
不要忽视空头:用中位数汇总数据的陷阱
有些人非常喜欢将中位数作为汇总统计数据。我有时也是。但是它有一些很大的缺点——正如所有的统计数据一样——我希望我们能意识到这一点。
为什么人们一开始就建议使用中位数?通常是因为中位数忽略了极值。如果你要为你的初创公司雇佣一名新的平面设计师,你可能要以你所在地区的其他人的工资为基准。假设你能得到数据,你可能会找到一些在大公司工作的摇滚明星的高薪。但这不是你想要的基准:你想要的是更普遍的东西。“集中趋势”的想法是中值可以带给你的。10 万美元的家伙被排除在外。
但是这是有代价的:中位数忽略了所有异常值,因为它们忽略了数据集中的所有值,除了单个中心项的值(或者在平局的情况下两个项)。相对位置才是最重要的。这意味着每次使用中间值时,你都在丢弃数据。(统计学上的“低效率”。)自然,这会给你带来麻烦。这里有一些例子。
故障类型 1:小范围的值
当数据集的中点附近有一小组选项时,就会出现这种情况。当离散值(1,2,3 而不是 1.234 等)覆盖的范围很窄时,这种情况很可能发生。例如,假设您对某个产品有 1-5 颗星的评价。一些不好的事情会发生。
坏事 1A:夸大小差异
这两款产品的评分几乎相同。但是有一个等级——核心等级——是不同的:
**Product A**: 1 1 1 2 2 2 2 2 2 3 3 3 3 3 3 3 4 4 5**Product B**: 1 1 1 2 2 2 2 2 2 2 3 3 3 3 3 3 4 4 5
^
*Median*
查看产品排名中值,您会发现产品的值为 3 和 2。但是手段只有零点几分的不同。
坏事 1B:缺失变化
如果变化不影响中值,您将不会注意到任何变化:
**Product C**: 1 1 2 3 3 3 3 3 3 3 3 3 3 3 3 4 4 4 4**Product D**: 2 3 3 3 3 3 3 3 3 3 3 3 4 4 4 4 5 5 5
^
*Median*
即使分布的两端都向上移动,中位数仍然保持在 3。从 2.9 到 3.5,平均值移动了 20%以上。
失败类型 2:忽略极端值
人们喜欢忽略极端情况,因为它们可能是“异常值”,意味着错误。但极端情况是大多数现实世界系统的自然特征,比如工资、工厂密度或灾难影响。这通常意味着数据向左倾斜,有几个非常大的值,还有许多小值:
极端情况会极大地抬高(算术)平均值——但这不一定是件坏事:极端情况在现实世界中也会产生巨大影响,你的分析可能需要反映这一点。生态学家不应该因为熊很大就忽视它们!
如果你在有偏差的数据上使用中位数,你就忽略了罕见的极端情况,而是专注于常见的情况。这是否是一个好主意取决于你想知道什么。想象一下,你经营着一个创客空间,拥有每周顾客受伤人数的数据:
**Injuries**: 1 1 1 1 1 1 1 1 2 2 2 3 3 5 8 16 40
^
*Median*
*Mean*: 5.2
平均值和中间值回答不同类型的问题
除了永远不再允许“战斗机器人星期四”,我们还能说什么?视情况而定:
- 如果我们想知道“这周我能期待多少伤病?”那么中间值可能工作得很好。假设过去是一个很好的预测,你有 50%的机会减少 2 次伤害。
- 如果我们想,“如果我再开两周,我还会受多少伤?”然后我们需要(算术)平均值。均值是一种假装所有日子都一样,同时保持总数不变的方法。大部分日子少于 5 次受伤;但是如果每天都有 5 个,最终什么都不会改变。如果我们更加开放,我们可以估计另外 5.2 x 2 = 10.4 人受伤。
什么时候极端很重要?
不要只选择最有吸引力的数字:2 次受伤听起来比 5 次好,但不是提前计划的好方法。两个简单的问题可以帮助你评估你是否需要一个平均值来代替中位数:
- 如果最大值大 10 倍,我会在乎吗?
- 我实际上是在问,“如果每个值都一样会怎么样?”
外卖信息
我们都需要汇总统计数据:我们不能只是直观地或以表格的形式呈现原始数据。几乎所有的回归分析都是基于它们。他们不会走的。因此,我们的选择是更好地了解不同的统计数据,以及何时明智地使用它们。
考虑您的数据中是否有小范围的值,以及极端值是否重要。如果是这样,平均值可能比中值更好。可视化您的数据。不要不假思索地使用任何统计数据!
24 小时不要学机器学习
Source — medium.com/designer-ha…
最近偶然看到 Peter Norvig 的一篇精彩文章——《10 年自学编程》。
这是一个诙谐且有点讽刺的标题,对那些旨在 24 小时、7 天、10 天、插入一个可笑的短时间线 教你编程的茶几编程书籍进行了挖苦。
诺维格博士提出了一个很强的理由。是的,你可能会在 24 小时内掌握一门编程语言的语法、本质和风格,但这并不意味着你已经精通编程艺术。因为编程根本不是一门语言。编程是关于智能设计,对时间和空间复杂性的严格分析,理解某种语言何时能超越另一种语言,等等。
当然你可以在 24 小时内用 C++写一个 Hello World 程序,或者在 24 小时内写一个求圆的面积的程序,但这不是重点。你把面向对象编程理解为一种范式吗?你了解名称空间和模板的用例吗?你知道你在著名的 STL 附近的路吗?如果你这样做了,你肯定不会在一周内,甚至一个月内学会所有这些。这花了你相当多的时间。你学得越多,你就越意识到深渊比它从悬崖上看起来更深。
我在当前围绕机器学习、深度学习和人工智能的整体氛围中发现了类似的情况。成千上万的博客、文章和课程到处涌现,助长了这种炒作。其中数以千计的标题都是同类的——“7 行代码的机器学习”、“10 天的机器学习”等等。这反过来导致 Quora 上的人们提出类似“我如何在 30 天内学会机器学习?”。简短的回答是,“你不能。没人能。没有一个专家(甚至是熟悉其来龙去脉的专家)做到过。”
Looks familiar? Found this on a very funny Facebook page
即使我们暂时忘记 10,000 小时规则,你也无法用 7 行代码完成机器学习。
为什么?因为这 7 行代码没有解释你在偏差-方差权衡中的表现,你的精度值意味着什么,或者精度是否是一个合适的性能指标摆在首位,你的模型是否超过了,你的数据是如何分布的,以及你是否选择了正确的模型来拟合你所拥有的数据,等等。甚至在你回答了这些问题之后,还有更多事情要做。
因为你不能解释你的模型,你调整了 sklearn 中的参数,获得了最小的精度提高,然后高高兴兴地回家。但是你真的学会了吗?
Source — machinelearningjourney.blogspot.in/2012/03/mac…
简而言之,不要用 7 行代码来做。做 6 个月,一年。你会在那个时期的中期知道它是否让你感兴趣。暂时忘记魅力,真正进入这个令人惊叹的研究领域的深处。这个你绝对要看。我发现这是对这一领域新手的最好介绍。你不需要知道数学或代码来阅读它。但是在读完这篇文章后,你会意识到你需要理解的所有概念,以便在这个领域中流畅地思考,可以这么说。
确实有一些关于这个主题的有趣的博客。以下是我个人最喜欢的一些:
Medium 也是一个学习的好地方。我几乎只关注这个出版物。
如果你是守旧派,就去斯坦福上吴恩达的 CS229。这比他在 Coursera 上的课程更涉及,也是一个很好的介绍。
炒作的一个不幸结果就是我们“淹没在信息中,渴望知识”。很多人都这样做,以至于我们经常忽略了大局。机器学习很奇妙。这是一个严肃的研究和开发领域,正在推动许多 21 世纪的使用案例。
只是不要在 24 小时内做。
这是彼得·诺维格的文章,是我们这个时代一位杰出的人工智能研究者的必读之作。
Seriously, though. Why not?
不要犯这个机器学习的大错误:研究 vs 应用
想获得灵感?快来加入我的 超级行情快讯 。😎
如今,每个人都在研究机器学习。对于许多企业来说,这绝对是一个值得追求的伟大方向,因为它让他们能够以一种相当快速和简单的方式交付巨大的价值。对机器学习技能的需求空前高涨。麦肯锡做了一份很好的综合报告,关于人工智能如何塑造产业以及机会在哪里。
所以我们看到周围的每个企业都说:
嘿,我们急需一个机器学习研究团队!我们会找到有大量出版物的最好的科学家,付给他们很多钱,这样我们就可以在我们的业务中进行一些机器学习。万岁!
但是等一下……作为一家企业,你真的需要一个机器学习研究团队吗?对于今天的高价格,您的企业会有效地使用它们吗?你到底有多需要机器学习?真的有那么复杂吗?
如果你更像一个技术人员,你会全力学习如何做机器学习研究吗?
要回答这个问题,我们需要区分两种类型的方法,我们可以真正使用机器学习: 研究和应用。
机器学习研究
机器学习研究实际上是关于科学的。一位机器学习研究人员正试图推进科学的边界,特别是在人工智能领域。这些人通常拥有 CS 硕士或博士学位,并在顶级机器学习会议上发表了许多论文。他们在研究领域非常受欢迎!
如果你在做一些真正前沿的事情,机器学习研究员是很棒的。这些人习惯于为你的问题寻找定制的科学解决方案。如果你告诉他们“我们非常擅长使用人脸识别自动检测人类入侵者,准确率高达 95%。你能让我们达到 97%吗?”。ML 研究员是你要找的人!
Machine Learning researchers know this stuff
这里有一个问题:这个人可能从来没有真正将软件部署到产品中!他们可能不是将软件作为服务(SaaS)或产品交付给客户,将研究转化为实践的专家。他们不知道如何正确包装、生产和运输。
这就是下一个的切入点…
机器学习应用
机器学习应用都是关于工程的。机器学习工程师知道如何将最新的人工智能研究转化为有价值的东西。他们将研究成果转化为产品或服务。这些人非常擅长云计算服务,比如亚马逊的 AWS 或者谷歌的 GCP 。他们了解软件开发生命周期(SDLC)和敏捷方法。
不幸的是,拥有这些技能的人经常被寻求将机器学习集成到他们的产品或服务中的企业所忽视。机器学习工程师通常隐藏在众目睽睽之下,在部署尖端产品方面拥有丰富的经验,并拥有足够的机器学习知识来使用它。
机器学习工程师不像研究人员那样花哨,因为他们不像拥有博士学位和 5000 次引用的 ML 超级明星。但是如果你想把 ML 驱动的产品交付给客户,你就需要它们。
如何在你的企业中使用机器学习
决定如何在你的业务中使用机器学习并建立你的团队将取决于你试图提供的产品或服务。你正在建造的东西是超级定制的,超越了人工智能当前的最先进水平,还是在一个完全不同的方向?你可能需要一些 ML 研究员来完成工作,他们习惯于做这类事情。
对于大多数企业和团队来说,你真的不需要那个。目前的机器学习科学对许多应用来说已经足够好了。没那么复杂。你不需要重新发明轮子,你需要知道如何使用轮子让你的车变得更好的人:工程师!
归根结底,机器学习是一个工具,就像任何其他软件工具一样。研究人员创造新工具,工程师找出如何最好地使用它们。机器学习现在做了一些非常酷的事情!…但它的目的仍然主要是最终向消费者提供某种价值。
让我们通过宣传记住这一点!
喜欢阅读关于科技的文章吗?
在 twitter 上关注我,我会在这里发布所有最新最棒的技术!
不要放松:足球中的危险领先
足球比赛中 2 比 0 的领先优势是最危险的吗?
你会听到比赛评论员说“2-0 的领先是最危险的领先”,这意味着与其他类似的比分相比,你输(或最多平局)的可能性是最大的。
这是一个有趣的理论。在“仅仅”1-0 领先的情况下,领先的球队仍然知道对手只差一球就能追平比赛,然后有可能获得心理优势。因此,领先的团队仍然保持警惕,更有效地保护领先。但是 2-0 的领先看起来很舒服:即使对手得分,你仍然领先。理论表明,这就是为什么 2-0 领先的球队比以往任何时候都更容易被得分(一次又一次),并最终输掉比赛。
这个理论有统计学上的价值吗?
数据集
我使用了这个 Kaggle 数据集——包括 2012 年至 2017 年赛季在英国、德国、法国、意大利和西班牙国内联赛中进行的 9K 场比赛的详细事件——试图为这个流行的理论添加一些数据视角。
方法论
对于数据集中的每场比赛,我得到了每一个进球和进球的一方(主场或客场)。然后我生成了每场比赛的每一个比分。例如,如果一场比赛以 2-1 结束,比赛产生的比分可能是 1-0,然后是 2-0,然后是 2-1。在这个过程的最后,有 57 个独特的得分线。请注意,评分线 2–1 不同于评分线 1–2。
然后,我减去构成得分线的两个数字,得出领先优势。正领先表示主队赢了(例如比分是 2-1,领先 1 球),负领先表示客队赢了(例如 1-2,领先-1 球)。为了能够一起分析积极和消极的线索,我将线索与最终结果进行了比较,并从领导团队的角度分配了一个“赢/平/输”。因此,如果在某个时候比分是 2 比 1,主队最终获胜,那就是领先队的“胜利”,如果客队获胜,那就是领先队的“失败”。
上述方法的一个重要注意事项是,同一个游戏可以为我们的数据集贡献多个观察值,每个观察值对应一个不同的得分线。作为一个说明性的例子,如果一个队在比赛的某一点上以 1-0 领先,那么在另一点上以 2-0 领先,最后以 2-1 领先,这就产生了 两个**1 球领先的观察结果和一个主队获胜的 2 球领先的观察结果。
最后,请注意,这种方法考虑了每场比赛中除平局之外的所有可能的比分。
结果
这是领先团队的结果分布,是领先程度的函数。
Figure 1. The distribution of results for each observed lead in the dataset. Green represents victory for the leading team, Orange a draw and Red a loss.
与理论所暗示的相反(但可能并不令人惊讶),我们看到你的领先优势越高,你赢得比赛的机会就越大!领先 2 球的球队有 94%的可能性赢得比赛,相比之下,领先 1 球的球队“只有”72%的可能性赢得比赛。拥有 3 球的领先优势几乎可以保证赢得比赛(99.1%的概率)。只有一次球队领先 3 球却输掉了比赛:2011-2012 赛季意大利甲级联赛莱切和米兰之间的一场比赛,当时莱切半场 3-0 领先,但米兰扳回一局,以 3-4 获胜。
为了理解图 1 中每个条形的样本大小,这里列出了每个导联被观察的次数。请注意,在同一场比赛中,可以多次观察到相同的领先优势。
Figure 2. How many times was each lead observed. Note that there are ~9K games in the dataset overall and ~8.3K games in which at least 1 goal was scored. Each lead can be observed multiple times within the same game.
我们可以更深入地分析,根据主队和客场队的领先优势,分解结果的概率分布,例如,比较主队和客场队领先 2 球时赢得比赛的概率。
Figure 3: Distribution of results as the lead increases. For Home and Away teams.
同样,我们看到领先优势越大,你就越有可能赢得比赛,无论是主场还是客场。我们还注意到,与领先优势相同的主队相比,如果你是客场队,赢得比赛的机会就更小。如果我们考虑到主队有他们的球迷支持,因此可能比客队更有可能卷土重来,这是有道理的。领先一球的主队有 76%的可能性赢得比赛,而领先一球的客场队有 66%的可能性赢得比赛。主队以 2 球领先赢得比赛的概率是 95%,客场是 91%。在领先 3 球的情况下,获胜的概率是 99%和 98.5%。
领先 4 球的球队没有平局或输球的记录。
具体来说 2-0 领先怎么样?
好吧,不管我们怎么看,2 球领先比 1 球领先更安全,但是如果我们真的只考虑 2-0(或 0-2)比分并将其与 1-0(或 0-1)比分进行比较,“2-0 领先是最危险的领先”这一理论能得到任何统计支持吗?
没有。
Figure 4. Probability of winning depending on the scoreline
与“仅仅”1 比 0 领先的情况相比,一个 2 比 0 领先的球队更有可能赢得比赛。如果他们 3-0 领先,他们也几乎肯定会赢得比赛(虽然,我敢肯定 2005 年冠军联赛决赛米兰将不敢苟同)。
因此,对欧洲一些最大联赛(英格兰、法国、德国、意大利和西班牙)约 9K 场比赛的统计分析显示,2-0 领先是最危险领先的理论没有任何价值。数据显示,领先优势越大,团队越安全。
这个理论能在其他运动中找到支持吗?或者也许是电子足球(PES 和 FIFA)?
感谢阅读!
你可以在这里 找到所有分析 的 jupyter 笔记本。
AI 犯错是谁的错?
别误会,我爱机器学习和 AI 。但是我不会盲目地信任他们,你也不应该,因为你构建有效可靠的 ML/AI 解决方案的方式就是迫使每个解决方案赢得 你的信任。
(本文中的许多建议也适用于没有 ML/AI 的数据洞察和模型,尤其是最后一段。)
盲目的信任是一件可怕的事情。
在你开始认为这和机器人或者科幻有什么关系之前,打住! ML/AI 系统不像人类,它们只是有用的东西的标签有着诗意的名字。相反,他们的不信任完全来自其他地方。我认为最好是展示而不是讲述,所以我们来看一个熟悉的例子 …
【**剧透警告:**这篇文章会破坏无监督学习去神秘化的乐趣,让你对我的小认知演示免疫。]
Never trust ML/AI blindly, always force it to earn your trust with appropriate testing. Image: source.
为一厢情愿的想法做准备
欢迎回到我们的猫,你们可能已经见过T21,当我们建立一个分类器将我的六张照片的原始数据集分成两组时。
The original training dataset from Unsupervised Learning Demystified. Do you see the two groups?
你看到了吗?我神奇的神奇的机器学习系统成功地返回了我所期望的确切结果!
This example works for supervised ML and for unsupervised ML, so don’t worry about that. The important thing is that the model perfectly identifies my two cats with 100% training accuracy.
答对了。这是两只不同的猫,而型号完美地回复了它们的标签,让我泪眼模糊,为我聪明的分类机器人感到自豪。这意味着我刚刚建立了一个特斯拉和赫胥黎分类器!!!…对吗?
我们的思想会捉弄我们
没那么快!那是我们人类的一厢情愿又捉弄了我们。我太沉迷于我的小猫了,以至于我可能没有注意到所有特斯拉的照片都有一个散热器作为背景,而所有赫胥黎的照片都没有。你注意到了吗?再看看。
This system was never a cat detector. I jumped to that conclusion thanks to confirmation bias, selectively noticing the evidence that confirmed the story I liked and failing to notice evidence that suggests the system is actually a radiator detector.
猫探测器还是散热器探测器?
我不知道的是,我的解决方案实际上是一个散热器探测器,而不是 Hux/Tes 探测器。用新的例子进行测试是有帮助的,所以让我们看看我们是否能以这种方式发现问题…
Turns out that using more examples from the same dataset doesn’t do much to, ahem, iron out the issue.
即使我通过给它看这些新照片,用新数据来测试它,也不会有一丝警报。哦亲爱的。有问题吗?
不是 如果 Tes 是 总 用散热器拍摄而 Hux 总 不是。如果是这样的话,谁在乎它是如何工作的呢?它 总是 起作用。它每次都会给正确的猫。没有问题。
那是一个很大的假设。如果猫搬到另一个公寓会怎样(真实故事)?如果你继承了我的分类器而没有我的笔记,并在你的照片上使用它,会怎么样?
在这些情况下,返回的标签将是“Huxley ”,任何依赖于我的 Hux/Tes 检测器的关键任务系统都将崩溃并严重燃烧。
这是谁的错?
在大火肆虐的时候,让我们做一个快速的尸检:
- 就像常见的 AI 一样,把像素转换成标签的配方是 太复杂了 。
- 我观察到的只是输入(像素)和输出(Hux / Tes 标签)。
- 因为我是 人类 ,所以我不会注意到就在我眼皮底下的东西(散热器和 Tes 总是重合的)。
- 我告诉自己的关于输入与输出之间关系的故事不仅过于简单,而且还偏离了 一厢情愿 的散热器解释。
- 没事。我不需要理解它是如何工作的,只要我能确定它确实工作。
- 检验它是否有效的方法是评估它在一系列它从未见过的相关例子上的表现。
到目前为止,一切顺利。实际上还没有问题。你相信很多东西,却不知道它们是如何工作的,例如我们很多人用来治疗头痛的扑热息痛。它确实起作用,然而科学无法告诉你如何起作用。重要的一点是,你可以验证扑热息痛是否起作用(不像在你头上绑一颗死痣)。
Don’t know how this popular 100+ year old drug works at a molecular level? Neither does science.
像思考头痛治疗一样思考复杂的人工智能系统。确保它们有效,你就没事了。好吧,在哪里解开?请击鼓!
- 不幸的是,我在不像我希望系统运行的例子上检查性能。
就在那里。这最后一个是实际上出了可怕错误的地方。只要我们用适当的例子适当地测试系统,其余的都没问题。所以,答案是:是我人类的错。
如果你为一项工作测试这个系统,然后把它应用到另一项工作中…你期望什么?
如果我用一组例子来教和测试一个学生,而这些例子并没有涵盖我希望这个学生学习的任务,那么如果以后出现混乱,我为什么会感到惊讶呢?如果我所有的例子都来自 Tes 和辐射器总是在一起的世界,那么我只能期望我的分类器在那个世界工作。当我把它移到一个不同的世界时,我把它放在了不属于它的地方。这个应用程序最好是低风险的,因为没有借口*“哎呀,但是我不知道它不能在它被设计的环境之外工作。”*你知道。如果你以前不知道,现在你知道了。
这就是为什么从一开始就记住你的目标和用户是如此重要。开始之前,请指定规格和设置。请让一个负责任的成年人来负责或者坚持玩具应用。
当更大的事情处于危急关头时,不要只是在不相关的数据集上抛出一些时髦的词语。
没有熟练和负责任的领导,嗯,我希望你的应用程序永远不会有任何人的健康,安全,尊严,或未来挂在上面…
常识,不是魔法
我一直用“例子”这个词代替“数据”——它们是同一个东西——来提醒你这不是魔术。 ML/AI 的重点是你在用例子而不是指令来表达你的愿望。为了让它起作用,例子必须是相关的。任务越复杂,你需要的例子就越多。你每天都用例子交流,所以你已经知道这些东西了。也许你想知道数学是否有不同的说法;并没有。请放心,常识一直是你最好的算法。
如果你想用例子来教学,例子必须是好的。如果你想信任你的学生,测试必须是好的。
盲目的信任是一件可怕的事情
除了您检查系统的条件之外,您对系统的安全性一无所知,所以请将这些提醒放在手边:
- 如果你没有测试过,就不要相信它。
- 如果你没有在[环境]中测试过,就不要在[环境]中信任它。
- 如果你没有用【用户人群】测试过,就不要用【用户人群】信任它。
- 如果你没有用[数据总体]测试过,就不要用[数据总体]信任它。
- 如果一个输入是不寻常的,不要相信你的系统会输出合理的东西。考虑使用异常检测和安全网(例如,标记一个不寻常的实例以供人工审查)。
如果你使用的工具没有经过安全验证,你造成的任何混乱都是你的错。人工智能和其他工具一样。
感谢阅读!YouTube 课程怎么样?
如果你在这里玩得开心,并且你正在寻找一个为初学者和专家设计的有趣的应用人工智能课程,这里有一个我为你制作的娱乐课程:
Enjoy the entire course playlist here: bit.ly/machinefrie…
喜欢作者?与凯西·科兹尔科夫联系
让我们做朋友吧!你可以在 Twitter 、 YouTube 、 Substack 和 LinkedIn 上找到我。有兴趣让我在你的活动上发言吗?使用表格取得联系。
甜甜圈和咖啡符合城市经济
加拿大快餐服务中的数学标度
如果你了解加拿大,你就会知道它与蒂姆·霍顿的连锁快餐店有一种特殊的关系:连锁快餐店,以便宜的咖啡、快捷的早餐和罪恶的油炸圈饼而闻名。然而,这种关系不仅仅是饮食热量的稳定供应。例证:一则新闻报道说,在阿尔伯塔省的红鹿市,一名男子挥拳猛击一只美洲狮,攻击他的哈士奇犬。只有当我们得知这一事件发生在蒂姆·霍顿酒吧时,它才被宣布为峰加拿大。
简单地说,这个品牌的快餐店在加拿大文化中有着特殊的地位。
在接下来的内容中,我使用了蒂姆·霍顿的商店位置数据,以便了解城市消费经济学中的规模。这是一个相当简单的数据集,但它打开了一个城市经济抽象质量的视野,实际上可以作为商业增长代理的基础。
商店和城市及省份的数量
在撰写本文时,整个加拿大共有 4,258 个 Tim Horton 的位置。加拿大有近 3700 万人,因此每家商店大约有 8700 名居民。
下图显示了截至 2017 年与人口普查大都市地区人口相关的商店数量。
Number of stores in census metropolitan areas; color by province, including pink=Ontario, grey=Quebec, orange=British Columbia, blue=Alberta, green=Manitoba, yellow=Saskatchewan, brown=Nova Scotia, red=New Brunswick.
散点图没有透露太多信息,除了加拿大有一个非常大的都市地区,大多伦多地区,第二和第三名分别是蒙特利尔和温哥华。
人们普遍发现,大都市的规模遵循幂律关系,而不是线性关系。这是一种数学方法,通过一个公共因子的重复相乘,而不是一个公共项的重复相加,来说明种群大小之间的关系。例如,温哥华(第三大城市)的人口相对于蒙特利尔(第二大城市)的人口是 62%,而蒙特利尔相对于多伦多(第一大城市)的人口是 65%。换句话说,乘因子几乎是相同的。
这说明了加拿大大城市中心集合的统计关系。一般的观察被标为齐夫定律。这里这里、这里、这里和这里已经详细讨论过,不再赘述。
相反,乘法关系的洞察力可用于用对数将早期的图形转换成更具信息性的东西。x 轴和 y 轴上的数据此后通过以 10 为底的对数进行转换。
市场质量不同的省份
现在我们可以开始辨别有用的关系。
Log number of stores in census metropolitan areas; color by province, including pink=Ontario, grey=Quebec, orange=British Columbia, blue=Alberta, green=Manitoba, yellow=Saskatchewan, brown=Nova Scotia, red=New Brunswick.
该图显示,人口越多,蒂姆·霍顿的位置就越多。这并不奇怪,但是有一个转折,如下一节所述。
在此之前,会出现一个数据分段。图表中的灰色和橙色标记都明显低于我们可以想象的其他标记的线性趋势线。两种不同类型的标记分别表示法语省份魁北克和最西边的省份不列颠哥伦比亚。在不列颠哥伦比亚众所周知星巴克占有更大的市场份额,而魁北克在很多方面有意无意地不同于加拿大其他以英语为母语的地区。
至少与蒂姆·霍顿的市场相比,这两个市场有着质的不同。目前,这些数据被分割,忽略了这些市场,但我会回到他们身上。
观察:尺寸折扣
剩下的非常符合线性关系(r 的平方为 0.94)。
Log number of stores in census metropolitan areas, Quebec and British Columbia removed; color by province, including pink=Ontario, blue=Alberta, green=Manitoba, yellow=Saskatchewan, brown=Nova Scotia, red=New Brunswick.
而是一扭:斜率为 0.81 。精确的等式是:
斜率的值说明了一些重要的事情。
这是一个对数标度,所以我们应该用乘法来思考。例如:将大都市地区的人口增加一倍,换句话说,将 N_population 乘以 2,这在图中相当于沿 x 轴的任意位置向右移动了大约 0.30,因此,y 轴上的值增加了大约 81%,而不是直接增加一倍会达到的 100%。有一个固定的大小折扣*。*
值得注意的是,这种折扣适用于所有大都市地区。换句话说:Tim Horton's 所在的消费和供应市场的一些潜在质量在 Thunder Bay 和 Kitchener-Waterloo 之间发生变化,就像 Kitchener-Waterloo 和多伦多之间的市场质量变化一样多,因此位置的数量是可预测的折扣。
故意的还是突发的,特例还是一般?
那么,我是不是逆向设计了蒂姆霍顿(Tim Horton)总部高管们盲目遵循的等式,即人口越多的城市中心,人均办公地点就越少?不太可能。但我也拒绝相信高级管理层只是在扔飞镖来解决决策。在某个时候,已经进行了商议,并对某件事情作出了有意决定。
图中的结构更像是来自于多个个人深思熟虑的经济决策的累积,从意图的聚合形式中,观察到的结构看起来好像在城市中感觉到了一种无形的选择力量。随着城市地区在经济发展和维持不断增长和变化的人口的压力下有机增长,产品和服务供应网络的某些质量在任何增长中的加拿大城市的大量但通常是共同的限制下激增。
受当前技术、心理欲望、规章制度、政治和文化遗产以及量子力学的限制,各种各样的人类活动聚集在一起,创造了任何一个单独的深思熟虑都没有想到的东西。
好吧,至少在蒂姆·霍顿的廉价膳食卡路里供应方面。然而,在过去的十年里,类似的比例关系已经在其他类型的城市供给中进行了研究。欧洲大都市地区的加油站数量和汽车经销商数量也按照与蒂姆·霍顿的位置相同的指数进行了规模折扣。相反,一些产品和服务被发现在城市人口中以加速的方式扩展,申请专利的数量就是其中之一。文献中还有其他例子,在这篇文章之后,我们又有了一个例子:Tim Horton 的位置数。
重复一句老话:城市人口的整体大于其各个部分的总和,但随着更多部分加入其中,整体越来越不同。
像这样的组织力量出现的机制是什么?这是一个因果预测调查的问题。非常有趣,但这是另一个重要的话题。
不列颠哥伦比亚省和魁北克省以及市场增长的代理人呢?
不列颠哥伦比亚省和魁北克省被排除在之前的考虑之外,因为他们的蒂姆·霍顿的经济是独特的。是时候把这些省份带回来问一问了:如果蒂姆·霍顿的公司成功地获得了与加拿大其他地方相同的市场份额,那么该公司的正确数量是多少?
首先,计算观察值和拟合线之间的差值,然后将对数转换为位置数。下表显示了不列颠哥伦比亚省和魁北克省的四个大都市地区需要观察多少家商店,才能得出已获得可比市场份额的结论。
如果忽略与人口的比例关系,将会得到当前状态和目标状态之间的不正确差异。
蒂姆·霍顿保持市场份额的能力也可以用一个代理指标来衡量。举例来说:在 2011 年至 2016 年的五年间,大多伦多地区的人口增长了约 6%。由于规模折扣,假设恒定的市场份额和固定的商业模式,蒂姆·霍顿的分店数量应该增长了约 4.8%。如果当时的实际增长偏离了这个数字,我们可以对市场的变化做出有根据的猜测。新的立法、新的竞争或贸易关系的改变的影响的大小可以通过适当的人口规模贴现从未来的数据中辨别出来。
因为它在加拿大结构中的特殊地位,Tim Horton 餐馆地理位置的相对简单的数据,与幂律知识相结合,打开了加拿大城市经济普遍质量的视野。一个有意义的假设,一点数据科学,有趣的见解就能赢得。
掌声就是货币。如果你觉得这值得一读,请按下按钮。
脚注
蒂姆·霍顿的外景拍摄于这里。加拿大人口普查数据取自这里。用 Tableau 完成的可视化。关于缩放关系的推荐通俗读物在这里。对于阴谋读者的免责声明,我与 Tim Horton's 及其竞争对手或供应商没有任何关系,我只是偶尔在那里吃早餐。
用深度学习涂鸦!
我们的旅程与素描识别
在这篇博文中,我们描述了我们对过程的理解,对模型的拟合,以及找到一个有趣的 Google Quick,Draw 应用程序!数据集。与我们一起走过这段旅程,看看我们是如何应对成功分类“可以说是世界上最可爱的研究数据集”这一挑战的
该项目由 Akhilesh Reddy、Vincent Kuo、Kirti、Tiffany Sung 和 Helena Shi 建造。要查看使用的完整代码,请找到我们的 github :
一、背景
2016 年,谷歌发布了一款名为“快,画!”—这是一项人工智能实验,它在神经网络方面对公众进行了教育,并建立了超过 10 亿张图纸的庞大数据集。游戏本身很简单。它会提示玩家在某个类别中涂鸦一幅图像,当玩家在画画时,神经网络会在人机游戏的猜图游戏中猜测这幅图像描绘了什么。你可以在这里找到更多关于游戏的信息或者自己玩游戏!
自从在数据集中发布了 5000 万幅图画以来,ML 社区已经开始探索这些数据在改进手写识别、训练草图 RNN 模型来教机器画画等方面的应用。值得注意的是,它在 OCR(光学字符识别)、ASR(自动语音识别)& NLP(自然语言处理)方面具有强大的潜力,并揭示了世界各地的人们如何不同,但却是相同的。
二。数据
我们的总数据量为 73GB,包含 340 个标签类别中的 5000 万张图纸。每张图纸都有特定的变量:
- “字”—该图纸的类别标签
- "国家代码 " —出票人的原产国
- “时间戳”—图纸的时间戳
- “识别出”—表示 app 预测成功
- 绘图——针对涂鸦图像的笔画基础数据;每幅画都由矩阵形式的多个笔画组成
As seen here, each point in a stroke corresponds to an x-coordinate, y-coordinate, and time point
三。接近
我们首先了解构成草图的数组的结构,并对数据进行预处理。然后,我们深入研究拟合一些简单的分类器和一个基本的卷积神经网络,或 CNN。从那里,我们处理 CNN 架构,如 ResNet 和 MobileNet。最后,我们通过参加 Kaggle 竞赛与世界分享了我们的成果。
由于数据的巨大规模和对更高容量 GPU 的需求,我们在谷歌云平台上实现了 CNN 结构,该平台提供 300 美元的免费试用。要了解我们是如何做到的,请点击链接这里和这里。
四。数据预处理
对于每个类别标签的图形,数据以单独的 CSV 文件格式存在。因此,我们首先改组 CSV,用来自所有类的数据创建 100 个新文件,以确保模型接收图像的随机样本作为输入,并消除偏差。
大多数人画涂鸦的方式都差不多。例如,如果我让你画一个太阳,你会从一个圆开始,然后以顺时针方向画出从圆心向外辐射的虚线。为了捕捉这些信息,我们使用灰度/颜色编码处理来利用 RGB 通道,同时构建 CNN,以便模型可以识别每个笔画之间的差异。我们给涂鸦的每一个按时间顺序排列的笔画分配了一种颜色,这样模型就可以获得单个笔画的信息,而不仅仅是整幅图像。
Violin (left) in black & white; Mermaid (right) color-encoded
我们还通过随机翻转、旋转或阻挡部分来增加图像,以将噪声引入图像,并增加模型处理噪声的能力。在游戏过程中,一些玩家没有完成他们的涂鸦或以不同的角度画画。在这些情况下,增强可以为模型提供信息。
灰度/彩色编码和图像增强都使用了来自 keras **、**的 OpenCV 和 ImageGenerator,它们从 csv 文件中加载大量原始数据,并将其转换为图像。
五、建筑模型
在完成所有的数据收集和预处理步骤之后,就该开始项目中最有趣的部分了——模型构建!
在我们进入 CNN 之前,我们尝试了一些基本的分类器来比较不同的机器学习算法,并熟悉这些数据。我们从谷歌云存储中提取了数据的 numpy 文件。该数据已经过预处理,并在 numpy 中呈现为 28x28 灰度位图。npy 格式。由于整个数据集包括超过 345 个类别,我们最终选择了仅包含以下 5 个类别的子集:飞机、闹钟、救护车、天使和动物迁徙。
随机森林
我们首先从随机森林分类器开始。我们利用 GridSearchCV 交叉验证模型并优化参数。我们发现精确度在 100 棵树后趋于平稳,所以我们使用 n_estimators = 100 作为我们的最终模型,返回的精确度为 0.8291。
KNN
其次,我们尝试了 k-最近邻(kNN)分类器,这可以说是最简单、最容易理解的模型。它的算法通过在 k 个最接近的例子中找到最常见的类来对未知数据点进行分类。我们交叉验证了 n_neighbors,发现给出的最佳模型是 k = 5,这返回 0.8752 的准确度。
多层感知器(MLP)
最后,我们尝试了 scikit-learn 的多层感知器(MLP)。我们在不同的隐藏层大小和学习率上进行交叉验证,决定隐藏层大小为(784),学习率α= 0.001,这给出了 0.8654 的准确度。
卷积神经网络
然后,我们转到一个简单的 CNN 模型,为模型性能设置一个较低的阈值,并理解模型的细微差别和执行时间。在这个模型中,我们使用数据中的绘图信息,通过 OpenCV 创建所需大小的图像。这里,我们尝试了一系列不同的参数,如下所示:
这是我们参数设置背后的一些直觉。首先,较大的批量将有助于解决由于错误标记的训练数据而产生的噪声。尺寸参数表示图像尺寸/分辨率,对精度有重要影响。例如,32x32 和 128x128 的比较表明,32x32 的大小过于像素化,无法实现精确的模型。
32x32 (left), 128x128 (right)
第一个模型使用两个卷积层,每个深度为 128。然而,这种图像尺寸的增加需要更大的感受野 conv 层或额外的 conv 层。因此,当用更大的图像尺寸训练时,我们包括了多一层。下面是我们创建的自定义 CNN 模型,在构建模型时,将卷积层数、密集层数、压差和大小作为参数。
由于我们仍在决定进一步进行分析的最佳模型,我们在初始步骤使用了有限的数据来减少执行时间。
选择优化器
继续培训之前的一个关键步骤是决定使用哪个优化器。在参考了文献并听取了各种 Kaggle 论坛上专家的建议后,我们决定比较 Adam 优化器和 SGD 优化器在我们的数据上的性能。在多次迭代之后,我们选择了 Adam 优化器,因为我们观察到它显示出比 SGD 稍好的结果并且收敛得更快。
在对每个班级的 25000 张图片运行该模型大约 3 小时后,我们在 Kaggle 的公共排行榜上获得了 0.76 的 MAP@3 分数——对于每个班级仅有 25000 张图片来说,这是一个不错的结果!客观地说,数据集中的平均类包含 150000 幅图像。然而,当我们增加模型的复杂性时,精确度略有下降,这就导致了我们的下一步:ResNet。
SE-ResNet-34,SE-ResNet-50:
当增加模型的深度时,可能会面临消失梯度和退化等问题;相比之下,更深的模型比更简单的模型表现更差。残差网络(ResNet)是一种神经网络架构,它通过使用深度残差学习,以最简单的方式解决消失梯度和退化问题。
简而言之,在反向传播过程中,当信号反向发送时,梯度总是要经过 f(x) (其中 f(x) 是我们的卷积、矩阵乘法或批量归一化等),这可能会由于涉及到的非线性而带来麻烦。
结尾的“ + x ”是快捷键。它允许渐变直接向后传递。通过堆叠这些层,梯度理论上可以“跳过”所有中间层,并到达底部而不会减小。
可以参考原文进一步了解 34 层平面网络和 34 层残差网络的比较。
在该过程的这一步中,我们训练 SE-ResNet-34 和 50 作为简单 CNN 的进一步发展。术语 SE 指的是挤压和激发网;有了它,一个额外的块给不同的通道加权。通过给出权重,SE 模块被证明提供了额外的精度,而仅仅增加了总参数的不到 10%。关于挤压和激励网络的更多信息可在这里找到。
在训练 SE-ResNet-50 时,我们对 50 到 60 个时期尝试了如下不同的参数。
最后,在所有组合中,批量大小为 512 和图像大小为 128x128 的组合对分数的改善最大,将分数提高到 0.9093。值得注意的是,更改批量大小和图像大小是基于我们使用的 GPU,这些是 Tesla k80 上我们数据的最大可能参数。
MobileNet
在与 SE-ResNet 进行多次迭代后,随着竞赛截止日期的临近,我们决定探索 MobileNet,它提供了相当的准确性,但执行速度更快。
MobileNet 由 Google 推出,旨在为客户随时随地提供最新的技术,如对象、徽标和文本识别,而不考虑互联网连接。MobileNets 基于一种流线型架构,使用深度方向可分离的卷积来构建轻量级深度神经网络。
为了正确理解这一点,标准卷积在所有输入通道上应用滤波器,并在一个步骤中组合这些值。相比之下,深度方向可分离卷积执行两个不同的步骤:
- 深度方向卷积将单个滤波器应用于每个输入通道
- 逐点卷积,一个简单的 1×1 卷积,然后用于创建深度方向层输出的线性组合
这种因子分解大大减少了计算和模型大小,因为它打破了输出通道数量和内核大小之间的相互作用。根据 MobileNet 上的原始论文,MobileNet 显示计算成本减少了至少 9 倍。更详细的内容,可以参考 MobileNet 上的原创论文。
为了简单起见,我们在 keras 中使用了简单的两行标准 MobileNet 模块。
在训练模式之前,我们确保使用所有 50 MM 图像来训练模型,并通过每个笔画的灰度梯度包括笔画信息的顺序。经过多次迭代,我们发现以下参数是最佳参数。
不及物动词结果
我们开始在谷歌云平台提供的特斯拉 P100 GPU 上用 50 毫米的图纸和 340 节课训练模型。经过 20 个小时的训练和 50 美元的 GCP 积分,我们最终在 Kaggle 排行榜上使用 MobileNet 获得了 0.9211 的分数,这帮助我们在 1316 支参赛队伍中获得了 268 名的排名!
在这里,您可以看到我们模型参数和结果的总体总结:
以下是我们预测的一些例子!
有趣的奖励!
如果你坚持读完并读到这一点,给你加分!作为一个有趣的治疗,我们决定也增加一点趣味,并创建了一个可以通过网络摄像头捕捉涂鸦的应用程序!该应用程序使用我们的模型进行实时预测。OpenCV 函数被用来从网络摄像头捕捉视频并提取所绘制的图像。
我们使用第一个简单的 CNN 模型作为我们的后端,因为它是我们运行过的最轻的模型。该模型在 15 个类别(如下所列)上进行训练,并实现了 87%的正确率来检测所画的涂鸦。
七。结论
最后,我们将总结一下这个曲折旅程中所采取的步骤:
- 绞尽脑汁理解涂鸦数据的独特结构,并想出如何连接谷歌云平台来运行模型
- 通过混洗 CSV 和用笔画信息扩充图像等执行数据清理和预处理
- 在我们的本地系统上的三个简单分类器上运行五个类的缩减数据集
- 实施深度学习模型,从简单的 CNN 到 ResNets 和 MobileNets
- 向比赛提交了成果,给了我们自己一个大大的鼓励,并通过创建一个应用程序来庆祝项目的结束!
以下是在训练深度学习网络时学到的一些经验:
- 获得该算法的一个基本实现,首先在一个较小的数据集上测试它,以节省执行时间
- 探索所有可用的 GPU 选项,并根据任务所需的计算强度在它们之间进行交替
- 随着时代的增加而降低学习率。我们有一个名为 ReduceLRonplateau 的内置函数来执行这个操作。这影响了模型在平台期的学习
总的来说,这个项目非常值得!作为研究生,我们抓住了这两个机会(希望如此!)打动我们的教授,参加有声望的比赛。我们能够第一次通过处理图像分类来挑战自己,并且得出了非常令人满意的结果。
参考
这些工作没有一项是我们自己能够完成的。查看以下参考资料,获取我们使用的所有重要资源:
https://cloud . Google . com/blog/products/GCP/drawings-in-the-cloud-introducing-the-quick-draw-dataset https://ai . Google blog . com/2017/04/teaching-machines-to-draw . html www.kaggle.com/c/quickdraw… https://www . blog . Google/technology/ai/quick-draw-10 亿次绘图-环游世界/ q = https://stats . stack exchange . com/questions/148139/rules-for-selecting-convolutionary-neural-network-hyperparameters&sa = D&ust = 1544740608219000&usg = afqjcngwjl 5 gpzwwpkmpfclt 6 qinwqnha ruder.io/optimizing-… cs231n.stanford.edu/reports/201…
多巴胺:改善强化学习和…机器的快感?
好消息:2018 年 8 月 27 日,谷歌通过他们的人工智能博客宣布,他们发布了一个新的框架,名为多巴胺,用于“灵活和可重复的强化学习研究”。
还没从喜悦中跳出来吗?别担心,我们会经历这意味着什么,这意味着什么,希望我们都会有这样的反应。
强化学习
在我们进一步深入之前,这里有一个快速回顾,让每个人都达到相同的理解水平。机器学习(Machine Learning)是人工智能的一个分支,从数据中学习机器,主要可以分为三个部分,前两个部分是:
- 监督学习,向机器提供输入数据和预期输出。因此,机器在每次输出时都会收到反馈,并可以使用该反馈来相应地重新调整(学习)。
- 无监督学习,机器仅被提供输入数据,并自行找出任何隐藏的模式。
现在,第三个是炒作最多的地方。听说过某个 AI 打败了世界上最好的围棋手的新闻吗?或者,最近,一队 DOTA 2 玩家输给了五个训练来玩同一游戏的人工智能机器人?对于所有这些耸人听闻的说法,要感谢强化学习(也许还有媒体)。
在强化学习中,机器,更具体地说,称为代理,查看其环境的状态(这称为观察)并选择做一个动作。如果行动是好的,它会得到奖励。否则,它会受到处罚。代理被设计成能找到产生最多回报的方式。以一个游戏为例,当它赢的时候代理人收到最多的奖励。简单来说,这就是强化学习的工作原理。
A graphical representation of Reinforcement Learning (sourced from: en.wikipedia.org/wiki/Reinfo…)
多巴胺
让我们回到刚刚发生的事情:谷歌发布了一个名为 Dopamine 的开源框架,用于“强化学习算法的快速原型化”,在框架的 Github 知识库中提到了这一点。顺便说一句,“多巴胺”这个名字非常合适。原因?做好准备,快速一瞥神经科学!
从神经科学的角度来看,多巴胺是大脑中的化学信使,其目的是调节器官的奖赏和愉悦中心。当你完成清单上的一项任务时,或者当你因为查看社交媒体时收到的几条通知而感到高兴时,这就是给你这种小小的感觉良好的因素(是的,它们实际上是为了让你通过多巴胺分泌感觉良好,因为代表社交反馈的通知让你兴奋,从而导致某种成瘾。如果你想要更详细的解释,这里有一篇文章。
我把最好的例子作为最后一个:多巴胺是让任何有性繁殖器官在高潮时感觉良好的物质。从种群水平来看,一个物种的目标是不断地将基因传递给下一代,从而确保其生存。当一个有机体交配时,它完成了它的一个基本任务,它的大脑以强烈的快感奖励它,作为继续传递基因的激励。令人着迷的是,我们的身体是如何想出办法让我们做到这一点的:这是做一个好男孩并传递你的基因的一个巨大奖励,现在感受一些快乐吧!
是啊,有趣的东西,但这与人工智能和机器学习有什么关系?嗯,还记得我们的大脑如何释放奖励让我们感觉良好,以鼓励我们去做事情吗?嗯,既然人工智能是要创造更接近人类的算法,那么强化学习就是利用大脑的这种奖励机制作为灵感,鼓励机器通过……嗯……感觉良好来学习。好吧,你不会让机器到处呻吟(我绝对不希望它们在任何时候呻吟!想象一下,你笨拙地坐在办公室里,甚至更糟,坐在图书馆里,而你的笔记本电脑却觉得学习太难了!).对于一台机器来说,“感觉良好”意味着积累奖励积分。
回到正题,谷歌的多巴胺现在是一个开源框架,它有以下理念,正如该框架的 Github 库中所述:
轻松实验:让新用户能够轻松运行基准实验。
灵活的开发:让新用户很容易尝试研究想法。
紧凑而可靠:为一些久经考验的算法提供实现。
可再现性:促进结果的再现性。
这将如何发展
记住谷歌开源这个框架的目标,可以预期更多的开发者和爱好者会尝试强化学习。再加上云计算和边缘计算等选项(见我的帖子关于边缘计算的最新进展),训练和评估这些机器学习模型变得更加容易。因此,强化学习领域将会比现在发展得更快。
机器的行为与人类有所不同**,虽然进行了违反直觉的优化,但最终会得到更“优化”的结果**。随着越来越多的智能系统集成到我们的日常环境中,我们可能会在未来看到越来越多的这种情况。理解我们对这些决定的判断是如何演变的将会很有趣。
这意味着,通过强化学习,机器可以通过概率数学来学习我们人类因生存本能而不敢做的事情。下面举个例子:想象一下一辆车即将发生事故的场景。如果在那一刻,加速实际上会大大降低汽车碰撞的概率呢?普通人会有勇气猛踩油门而不是刹车吗?除非受到肾上腺素的巨大刺激,否则可能不会,因为我们人类认为越慢越安全。但是机器不会感到害怕,一辆经过优化以将事故数量降至最低的自动驾驶汽车肯定会跑得更快,并拯救所有乘客。
当 AlphaZero 算法教会自己下棋时,这种奇怪(但最终是聪明)的决定被证明是非常有用的,这甚至促使著名作家兼哲学家 Yuval Noah Harari 发表评论:
由于 AlphaZero 没有从任何人身上学到任何东西,它的许多制胜之道和策略在人眼看来似乎都非常规。他们可以说是创造性的,如果不是彻头彻尾的天才。
Sourced from: fossbytes.com/googles-alp…
双 Q 学习,最简单的方法
理解双 Q 学习的介绍
更新:学习和练习强化学习的最好方式是去 rl-lab.com
Q-learning (Watkins,1989)被认为是 TD 控制强化学习算法的突破之一。
然而,在他的论文双 Q 学习中,哈多·范·哈瑟尔特解释了 Q 学习在一些随机环境中表现不佳的原因。他指出,性能不佳是由于在 Q-learning 中使用 Max Q(s ',a)而导致的动作值被大大高估。
为了解决这个问题,他提出了双 Q 学习法。
问题是
考虑一个有四个状态的 MDP,其中两个是终态。 状态 A 总是被认为是开始状态,并且有两个动作,或者右或者左。右边的动作给出零奖励,并到达终端状态 c。 左边的动作将代理移动到状态 B,奖励为零。
状态 B 有许多动作,它们将代理移动到终端状态 D。但是(这很重要)从 B 到 D 的每个动作的奖励 R 有一个随机值,该值遵循均值为-0.5、方差为 1.0 的正态分布。
已知 R 的期望值为负(-0.5)。这意味着在大量的实验中,R 的平均值小于零。
基于这个假设,很明显,从 A 向左移动总是一个坏主意。然而,因为 R 的一些值是正的,Q-Learning 会被欺骗,认为从 A 向左移动会使回报最大化。事实上,这是一个糟糕的决定,因为即使它对某些情节有效,但从长远来看,它肯定是一个负面的回报。
那么为什么 Q-Learning 会高估呢? 为了回答这个问题,我们考虑以下场景: 设 X1 和 X2 是两个随机变量,它们代表状态 b 下两个行为的回报。由于它们是随机变量,我们将计算它们的期望值 E(X1)和 E(X2)。但有一个问题,我们不知道他们的期望值,所以我们能做的是通过计算增量平均𝝁1 和𝝁2.来使用这些期望值的估计值这些估计值是无偏的,因为随着样本数量的增加,整组值的平均值越来越接近 E(X1)和 E(X2),如下表所示。
然而,Q-Learning 使用 Max Q(s ',a),在表中由 Max(𝝁).表示从表中可以清楚地看出(见红色单元格),E(Max(𝝁)不同于 Max E(X)。这说明 Max(𝝁)不是 Max E(X)的一个好的估计量。是有失偏颇! 换句话说,当用最大 Q(s’,a)更新 Q(s,a)时,Q(s,a)没有向状态 B 的动作的期望值移动,即-0.5。
这个场景直观地解释了为什么 Q-Learning 高估了这些值。正式的数学证明可以在论文中找到。
解决方案
所提出的解决方案是维护两个 Q 值函数 QA 和 QB,其中一个从另一个获得下一个状态的更新。更新包括找到在下一个状态中使 QA 最大化的动作 a*(Q(s ',a*) = Max Q(s ',a)),然后使用 a获得 QB(s ',a)的值,以便更新 QA(s,a)。
下面的伪代码显示了算法的行为。请注意,本文末尾有一段 python 代码,对这两种方法进行了比较。 算法的第 3 行显示了如何从两个 Q 值函数中选择动作。例如,可以合并两个 Q(平均每个动作的值),然后应用ε-greedy。
该算法以等概率的方式更新 QA 和 QB。
Algorithm taken from Double Q-learning by Hado van Hasselt
下面的图表显示了当状态 B 的动作数量连续为 10 和 100 时,双 Q 学习和 Q 学习之间的比较。 很明显,双 Q 学习比 Q 学习收敛得更快。 注意,当 B 点的动作数量增加时,Q-learning 比双 Q-Learning 需要更多的训练。
为什么有效?
范·哈瑟尔特在他的论文中证明了 E(Q2(s ',a*)≤马克斯·Q1(s ',a*)。 所以经过足够多的实验,Q2(s ',a*)的期望值小于或等于最大 Q1(s ',a*),这意味着 Q1(s,a)没有用最大值更新。
下表显示了随着发作次数的增加,状态 A 下左侧动作的 Q 值的演变。 请注意,在 Q-Learning 中,Q(A,Left)是正的,因为它受到状态 b 中存在的正奖励的影响。由于这个正值,算法对采取左边的动作更感兴趣,希望最大化奖励。正如你所看到的,直到第 50 集,左手动作的比例一直在增加。 在双 Q-Learning 中,Q1(左一)和 Q2(左一)开始时略显消极。 因此,左侧动作的百分比很早就开始下降,从而节省了训练时间。
结论
本文表明双 Q 学习有时可能低估动作值,但避免了 Q 学习高估偏差的缺陷。它还表明,对于这种类型的问题,双 Q 学习更快地达到良好的性能水平。
Python 代码
以下 Python 代码模拟了双 Q 学习和 Q 学习,并输出了这两种方法的表格和对比图。
相关文章
下载带有脚本的城市景观数据集
City Scapes 数据集是一个非常流行的数据集,由带标签的街道图像(来自视频序列)组成。高质量标注帧 5000 个,弱标注帧 20000 个。这个数据集的网站是www.cityscapes-dataset.com
当我使用这个数据集时,我很快意识到数据集只能在登录后从网站下载。所以,没有直接下载链接。这意味着当你需要将深度学习模型部署到云机器或另一台 linux 机器时,你需要从另一个来源获得数据:Dropbox 等。有些数据文件非常大:44GB、11GB、6.6GB!!!。这个问题的解决方案是不用浏览器登录和下载数据。
首先,您需要在网页中创建一个帐户。您将在脚本的第一行使用您的用户名和密码登录到该页面。
下面是两行脚本:
wget --keep-session-cookies --save-cookies=cookies.txt --post-data 'username=myusername&password=mypassword&submit=Login' [https://www.cityscapes-dataset.com/login/](https://www.cityscapes-dataset.com/login/)wget --load-cookies cookies.txt --content-disposition [https://www.cityscapes-dataset.com/file-handling/?packageID=1](https://www.cityscapes-dataset.com/file-handling/?packageID=1)
在第一行,输入你的用户名和密码。这将使用您的凭据登录,并保留关联的 cookies。
在第二行中,您需要提供 packageID 参数,它将下载文件。
网站中的 packageIDs 映射如下:
1-> gt fine _ trainvaltest . zip(241 MB) 2->gt coarse . zip(1.3 GB) 3->left mg 8 bit _ trainvaltest . zip(11GB) 4->left mg 8 bit _ train extra . zip(44GB) 8->camera _ trainvaltest . zip(2MB) 9->camera _ train extra . zip(8MB)【中
下载页面的屏幕截图:
你可以在这里看到这个脚本的 GitHub 库。
用 Python 中的管道进行 dplyr 风格的数据操作
我经常使用 R 的dplyr包进行探索性的数据分析和数据操作。除了提供一组一致的函数来解决最常见的数据操作问题,dplyr 还允许使用管道编写优雅的、可链接的数据操作代码。
现在,Python 是我的主要语言,而pandas是我用于数据分析的瑞士军刀,然而我常常希望有一个 Python 包,允许直接在熊猫数据帧上进行 dplyr 风格的数据操作。我上网搜了一下,找到了一个叫dfply的包,是由 基弗·卡托维奇 开发的。和 dplyr 一样,dfply 也允许用管道操作符链接多个操作。
这篇文章将关注 dfply 包的核心函数,并展示如何使用它们来操作 pandas 数据帧。完整的源代码和数据集可在 Github 上获得。
入门指南
我们需要做的第一件事是使用pip安装包。
pip install dfply
根据该项目的 Github repo,dfply 只适用于 Python 3,因此请确保您安装了正确版本的 Python。
数据
为了探索 dfply 的功能,我们将使用dplyr简介中使用的相同数据。数据来自于交通统计局,包含了 2013 年所有从纽约市出发的 336776 次航班的信息。
from dfply import *
import pandas as pd
flight_data = pd.read_csv('nycflights13.csv')
flight_data.head()
平静的
假设您想在输出最终结果之前对数据集执行n离散变换操作。最常见的方法是逐步执行操作,并将每一步的结果存储在一个变量中。保存中间结果的变量将用于转换管道的下一步。让我们看一个抽象的例子。
# 'original_data' could be a pandas DataFrame.
result_1 = transformation_1(original_data, *args, **kwargs)
result_2 = transformation_2(result_1, *args, **kwargs)
result_3 = transformation_3(result_2, *args, **kwargs)
.
.
.
final_result = transformation_n(result_n-1, *args, **kwargs)
这不是非常优雅的代码,写起来可能会令人困惑和混乱。这就是管道救援的地方。管道允许我们重写上面的代码,而不需要那些中间变量。
final_result = original_data -->
transformation_1(*args, **kwargs) -->
transformation_2(*args, **kwargs) -->
transformation_3(*args, **kwargs) -->
.
.
.
transformation_n(*args, **kwargs)
魔法?!不,不是的。管道的工作原理是隐式地将一个阶段的输出作为下一个阶段的输入。换句话说,每个变换步骤都处理前一个步骤的变换结果。
带供给的管道
dfply 允许在 pandas 数据帧上用>>操作符链接多个操作。可以将操作链接起来,并将最终输出(一个 pandas 数据帧,因为 dfply 直接在数据帧上工作)赋给一个变量。在 dfply 中,一个操作链的每一步的 DataFrame 结果都用X来表示。
例如,如果您想在一个步骤中从数据帧中选择三列,在下一个步骤中删除第三列,然后显示最终数据帧的前三行,您可以这样做:
# 'data' is the original pandas DataFrame
(data >>
select(X.first_col, X.second_col, X.third_col) >>
drop(X.third_col) >>
head(3))
select和drop都是 dfply 变换函数,而X代表每个变换步骤的结果。
探索 dfply 的一些转换方法
dfply提供了一组用于选择和删除列、子集化和过滤行、数据分组和数据整形的函数。
用select()和drop()选择并放下列
有时,您会处理包含许多列的数据集,但只有一部分列是感兴趣的;select()允许您选择这些列。
例如,要选择我们之前加载的flight_data数据帧中的origin、dest和hour列,我们需要:
(flight_data >>
select(X.origin, X.dest, X.hour))
drop()是select()的逆。它返回除作为参数传入的列之外的所有列。
例如,获取除year、month和day列之外的所有列:
(flight_data >>
drop(X.year, X.month, X.day))
您也可以通过在您想要删除的列前面放一个波浪号~来删除select()方法中的列。
例如,选择flight_data数据框中除hour和minute列之外的所有列:
(flight_data >>
select(~X.hour, ~X.minute))
用mask()过滤行
mask()允许您根据逻辑标准选择 pandas 数据框架中行的子集。mask()选择条件为真的所有行。
例如,选择 1 月 1 日从 JFK 机场始发的所有超过 10 小时的航班:
(flight_data >>
mask(X.month == 1, X.day == 1, X.origin == 'JFK', X.hour > 10))
使用arrange()对行进行排序
arrange()允许您根据一列或多列对行进行排序;默认行为是按升序对行进行排序。
例如,先按distance排序,然后按航班的数量hours排序,我们这样做:
(flight_data >>
arrange(X.distance, X.hour))
要按降序排序,可以将arrange()的ascending关键字参数设置为False,如下所示:
(flight_data >>
arrange(X.distance, X.hour, ascending=False))
用mutate()添加新列
mutate()允许您在数据框中创建新列。新列可以由现有列组成。
例如,让我们创建两个新列:一个是将distance列除以1000,另一个是连接carrier和origin列。我们将这些新列分别命名为new_distance和carrier_origin。
(flight_data >>
mutate(
new_distance = X.distance / 1000,
carrier_origin = X.carrier + X.origin
))
新创建的列将位于数据帧的末尾。
使用group_by()和ungroup()对数据进行分组和取消分组
group_by()允许您按一列或多列对数据帧进行分组。在group_by()之后链接的功能应用于该组,直到数据框被ungroup()功能取消分组。例如,要按始发机场对数据进行分组,我们需要:
(flight_data >>
group_by(X.origin))
使用summarize()总结数据
summarize()通常与group_by()一起使用,将每个组缩减为单行摘要。换句话说,每个组在输出中都有一行。例如,要计算从每个机场始发的航班的平均距离,我们需要:
(flight_data >>
group_by(X.origin) >>
summarize(mean_distance = X.distance.mean())
)
用管道把它们聚集在一起
假设您想要对航班数据执行以下操作
- [第一步]:过滤掉所有不到 10 小时的航班
- [步骤 2]:使用公式[距离/(飞行时间 60)]创建一个新列 T25*
- [步骤 3]:计算从每个机场始发的航班的平均速度
- [步骤 4]:按平均速度降序排列结果
我们将使用dfply管道操作员>>编写操作。我们不必使用中间变量来保存每一步的结果。
(flight_data >>
mask(X.hour > 10) >> # step 1
mutate(speed = X.distance / (X.air_time * 60)) >> # step 2
group_by(X.origin) >> # step 3a
summarize(mean_speed = X.speed.mean()) >> # step 3b
arrange(X.mean_speed, ascending=False) # step 4
)
如果我们使用pandas数据操作函数,而不是dfply的,我们的代码看起来会像这样:
flight_data.loc[flight_data['hour'] > 10, 'speed'] = flight_data['distance'] / (flight_data['air_time'] * 60)
result = flight_data.groupby('origin', as_index=False)['speed'].mean()
result.sort_values('speed', ascending=False)
我发现dfply版本比pandas版本更容易阅读和理解。
结论
这绝不是对dfply包功能的详尽介绍。 包文档 真的很好,我建议你去看看了解更多。
如果你有建议或问题,请在下面的评论区留言。也可以发邮件到 hello [at] allenkunle [dot] me 或者 tweet at me@ allenakinkulle我会尽快回复。
这篇博文的完整源代码可以在 Github 上找到。感谢您的阅读,请不要忘记分享。
本帖原载于 2018 年 1 月 3 日 艾伦·阿肯昆勒的个人博客 。