TowardsDataScience 博客中文翻译 2019(二百四十五)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

如何在数据科学领域建立有意义的职业生涯

原文:https://towardsdatascience.com/how-to-build-a-meaningful-career-in-data-science-5a4c36db0f6c?source=collection_archive---------42-----------------------

你可以善用数据科学的力量,改变世界。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

需要一些灵感来引导您的数据科学职业朝着最有影响力的方向发展吗?

数据科学家的角色通常被称为 21 世纪最性感的工作。也许你被这个职业吸引是因为你热爱数学、编程和一切技术。但我敢打赌,你们中的许多人也对使用数据产生真正的影响感兴趣。

在调整数据和建立机器学习模型的漫长一天结束时,你会想说,“今天我创造了一些将积极影响某人生活的东西。”换句话说,你希望看到你的工作在现实世界中展开。

Omdena ,我们提供了一个协作学习环境,初级人才和经验丰富的导师可以在这里一起应对现实世界的人工智能挑战。我们的使命是将理论教育与实践联系起来,使世界各地的个人能够应对人类面临的一些最大挑战。

这里有三个鼓舞人心的故事,来自我们的创伤后应激障碍挑战

Albert、Kulsoom 和 Anam 都获得了两个月免费参加所有 DataCamp 课程的机会,这是因为他们出色的表现和社区精神。在我们的 PTSD 人工智能挑战赛中,他们与 32 名人工智能爱好者合作了两个月,构建了一个智能聊天机器人,帮助在低资源环境中面临可怕情况的个人诊断 PTSD,例如在战争和难民区。

艾伯特

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

17 岁的阿尔伯特是我们最年轻的合作者,但他对数据的热情和渴望激励了我们人工智能挑战中的其他 32 名合作者。用他自己的话说,这是他对这次经历的看法。

你对数据科学中有意义的职业的定义是什么?

我对有意义的 DS 职业生涯的定义是用一个人的知识和技能让世界变得更好。数据科学是一个极其强大的工具,善用它非常重要。像任何东西一样,它可以被用于善意或恶意的目的。

利用 DS 来解决诸如应对气候变化、提高农业产量和检测深度造假等问题,才是真正有意义的影响。

在你加入我们的挑战之前,你是如何看待学习 AI 的?

在加入 Omdena PTSD 挑战赛之前,学习 AI 感觉就是上一堆课,看视频,看论文,编程模型。一旦挑战开始,我意识到我错过了一个重要的方面:社区。加入数据科学从业者社区对于获得帮助、被激励以及学习团队合作和协作的技能非常重要!

你在这次挑战中学到的最重要的技能是什么,你将应用它来建立你未来的职业生涯?

这个挑战真的教会了我如何在团队中好好工作。在过去,我主要是单独从事我的机器学习项目。在这次 PTSD 挑战中,能够与世界各地的队友合作对于协调不同的任务至关重要。我可以把这段经历带到我未来的职业生涯中。

库尔苏姆

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

库尔苏姆·阿卜杜拉在 2011 年世界锦标赛上成为第一位代表巴基斯坦参赛的女子举重运动员。

你在举重生涯中学到的最重要的经验是什么,可以应用到生活中?

我想说我得到的教训是,我低估了自己的能力。很可能我们都低估了自己的能力。

作为人工智能中的一名女性,你必须克服的最大挑战是什么?

冒名顶替综合症——感觉自己很失败,觉得自己不配获得成功!

在大学里,我不得不学习并意识到这不是我的错,而是我的环境造成的。我还识别并处理了微侵犯和明目张胆的行为。我通过寻找积极的空间,如信任的家人、朋友、导师,以及照顾好自己来克服它。通过冒险,拥抱我的恐惧,“假装直到你成功”。

“我没有什么可失去的”帮助我向媒体介绍了我的举重比赛挑战和学术/工作情况。

这仍然是一项正在进行的工作。我希望我能继续进步,并帮助别人不处理我不得不做的事情。

如果你可以在广告牌上写一句话给正在挣扎的人,你会给他们什么建议?

恐惧和怀疑都是暂时的,继续走下去,享受旅程就好。

阿南

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

当 Anam 加入我们的 PTSD 人工智能挑战赛时,她几乎没有人工智能经验,但有着长期与 PTSD 斗争的个人历史。她加入了我们的 AI 挑战赛,并晋升为初级机器学习工程师。

是什么让你加入了 Omdena 的 PTSD AI 挑战赛?

亲身体验 PTSD 的生活对我来说是一个完美的挑战。成为它的一部分比一个人自己的收获更大,比如学习 ML 或增加他们在 it 方面的经验。这意味着帮助那些因创伤后应激障碍而在生活中面临许多障碍的人们。如果这意味着我能在如此大的事业中扮演哪怕是一个小角色,我已经准备好成为这个挑战的一部分。

你在这次挑战中学到了什么,你将应用于建立你未来的职业生涯?

通常,作为一所大学的学生,我们会收到一些有明确答案和固定范围的问题。和 Omdena 一起应对这个挑战是完全不同的。它帮助我理解了如何利用我们的知识来解决现实世界的问题并有所作为。这也让我明白,与我们习惯的方法相比,如此大规模和真正影响的问题需要一种不同的方法。一次奇妙的经历!

想成为 Omdena 的合作者,加入我们的一个 AI 来迎接好的挑战吗?在此申请

如何在 SageMaker 上建立模型

原文:https://towardsdatascience.com/how-to-build-a-model-on-sagemaker-da03be698a9c?source=collection_archive---------6-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Samuel Zeller on Unsplash

数据科学项目往往以报告的准确性和圆滑的情节而告终。在这篇文章中,我们将探讨下一步:如何创建一个可以部署的模型。

为此,我们将使用 Amazon SageMaker 并分解从实验到生产就绪的步骤。我们将遵循高层次的方法,这意味着 AWS 将为我们挑选一些参数。

在继续之前,确保你有一个 AWS 账户和一个 Jupyter 笔记本的访问权限。

设置笔记本实例

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by ASHLEY EDWARDS on Unsplash

第一步是登录亚马逊控制台,寻找 SageMaker,以防它不可见。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

接下来,我们点击创建笔记本实例

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们给笔记本命名,运行它的价格由实例类型决定。这里我们使用 ml.t2.medium ,但是建议查看定价页面以获得最佳选择。对于这种应用,我们可以保持弹性推断

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们要设置角色,它是一种安全证书,决定权限,比如笔记本可以访问哪些资源。我们点击它并选择创建一个新角色

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

由于没有我们希望笔记本访问的额外存储桶,我们选择 None 并点击 *create role。*这里最重要的条件是第二行。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最后,我们单击页面最底部的“板条箱笔记本实例”。过一会儿,你的笔记本的状态应该会显示在使用中。一旦发生这种情况,AWS 将向我们收取使用该实例的费用,所以请确保在不使用时将其关闭。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

克隆部署笔记本

从上图中点击打开 Jupyter 进入熟悉的设置。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在右上角点击新建并打开一个终端并改变目录。然后我们克隆这个包含笔记本git 仓库,并在完成后关闭它。

回到主页选项卡,我们看到添加了一个 sagemaker 目录。我们导航到笔记本在 sagemaker_ml 文件夹中的位置。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

下载数据

对于一般的数据科学家,特别是 NLP 实践者来说, IMDB 数据集就像是一个成年礼。我们将通过 XGBoost 使用这些数据来预测用户情绪。

第一步是下载数据。我们可以在笔记本中使用命令行代码:

GNU 文档为上面的命令提供了充足的资源。

准备数据

这里我们不会详细讨论这个问题,只提供一个简要的概述。不过,您可以在笔记本中查看整个过程。

这是一个 NLP 练习,所以我们需要将原始信息处理成数据和相应的标签。然后,我们剥离所有 html 标签的文本,用 NLTK 执行词干提取,并提取一个单词包

在这个过程的最后,我们应该准备好我们的测试和训练数据。

用 XGBoost 分类

XGBoost clasifier 要求将数据集更好地写入文件,并使用亚马逊 S3 存储。我们进一步将训练数据集分为两部分:训练和验证。

我们将把这些数据集写入一个文件,并将文件上传到 S3。此外,我们将做同样的测试集输入上传到 S3。这样,一旦拟合完成,我们就可以使用 SageMaker 的批量转换功能来测试模型。

SageMaker 中 XGBoost 算法的文档要求保存的数据集不应包含标题或索引,对于训练和验证数据,标签应首先出现在每个样本中。

此时,节省可用内存是一个好的做法,我们可以将 text_X、train_X、val_X、train_y 和 val_y 设置为 None :

将培训验证文件上传至 S3

对于这一部分,我们将大量参考 SageMaker API 文档SageMaker 开发者指南

upload_data 方法将本地文件或目录上传到 S3。它是代表我们当前 SageMaker 会话的对象的成员。这个方法将数据上传到 AWS 为我们创建的默认 bucket,如果它还不存在的话,上传到由变量 key_prefix 描述的路径中。如果我们导航到 S3 控制台,我们应该在那里找到我们的文件。

创建 XGBoost 模型

我们认为 SageMaker 上的模型由三部分组成:

  • 模型工件
  • 培训代码(集装箱)
  • 推理代码(容器)

模型工件是实际的模型本身。在这种情况下,工件是在训练期间创建的树。

训练代码推理代码用于操作训练工件。训练代码使用提供的训练数据和创建的模型工件,推理代码使用模型工件对新数据进行预测。

SageMaker 通过使用 docker 容器来运行训练和推理代码,这是一种打包代码并确保依赖关系不会成为问题的方法。

拟合 XGBoost

通过访问 S3 输入来拟合模型。

使用 SageMaker 拟合模型时,过程如下。

  • 一个计算实例(某处的服务器)使用我们指定的属性启动。
  • 当计算实例准备就绪时,用于适应模型的容器形式的代码被加载和执行。
  • 当这个代码被执行时,它被提供对存储在 S3 上的训练(以及可能的验证)数据的访问。
  • 一旦计算实例完成了对模型的拟合,生成的模型工件就被存储在 S3 上,并且计算实例被关闭。

试验

我们使用批量转换以非实时的方式对大型数据集进行推理。这让我们可以看到我们的模型执行得有多好。

这样做的好处是,我们不需要立即使用模型的结果,而是可以对大量样本进行推断。这种方法也很有用,因为我们可以对整个测试集进行推理。

要执行转换作业,我们需要指定要发送的数据类型,以便在后台正确序列化。这里我们为模型提供 csv 数据,因此我们指定文本/csv

此外,如果数据太大,无法一次性处理,那么我们需要指定数据文件应该如何分割。同样,这是一个 csv 文件,因此每一行是一个单独的条目,我们告诉 SageMaker 在每一行拆分输入。

使用上面的代码,转换在后台运行。我们调用 wait 方法等待转换工作完成并接收一些反馈。

转换作业被执行,并且每个评论的估计情绪被保存在 S3 上。我们想在本地处理这个文件,并将它复制到数据目录 data_dir

一种方便的方法是在 jupyter 中找到 AWS CLI 命令参考

最后,我们可以从模型中读取输出。

我们需要将输出转换成对我们的目的更有用的东西。我们将情绪转换为10。最后我们可以打印出准确率: 86% ,还不错!

清除

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Paweł Czerwiński on Unsplash

当我们对越来越大的数据执行操作时,跟踪我们使用了多少内存变得至关重要。我们可能会在执行操作时耗尽内存和/或产生昂贵的费用。

SageMaker 上的默认 notebook 实例可能没有太多多余的磁盘空间。当我们重复类似的练习时,我们最终可能会填满分配的磁盘空间,导致难以诊断的错误。

一旦我们完成了一个 notebok,删除我们在这个过程中创建的文件是一个很好的做法。我们可以从终端或笔记本电脑中心完成这项工作。

完成后,请务必返回 SageMaker 笔记本实例并停止该实例。

总结和后续步骤

在这篇文章中,我们看到了如何在 AWS SageMaker 上创建一个可以部署的模型。工作流程应该与典型的机器学习练习相同,只是增加了一些额外的步骤。

主要的收获是关注数据存储的位置和方式,代表我们做出的决策,以及如何防止内存溢出。

恭喜你!我们现在已经有了一个可以部署的情感分析模型!

如何构建非地理地图#2

原文:https://towardsdatascience.com/how-to-build-a-non-geographical-map-2-340256ad9f16?source=collection_archive---------14-----------------------

或者如何将散点图变成交互式地图(使用传单和 JavaScript)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

This guy’s body may seem odd and his chair disproportionate, but aren’t maps a distortion of reality, anyway? 😃

地图是数据可视化的强大设计对象。他们强调元素之间的空间关系和变量的比较。在非地理数据的背景下,web 地图可以增强传统的散点图。

🔗链接到#第 1 部分:如何用降维映射相似性

#第 2 部分:从散点图到交互式地图

数据可视化的核心是通信。将吓人的桌子变成引人入胜的故事的能力。通常,最终目标是推动解决问题或决策的洞察力。在大多数情况下,用户不会玩弄数据,而是采取被动的态度。但是,如果你想授权给你的观众,激发他们的好奇心,并允许他们探索数据呢?

我们用地图来探索未知。他们给了我们走出人迹罕至的道路的信心。我们偏离了最初的路线,在一家咖啡馆停下来,或者绕道经过一个博物馆。这也是我们使用网络的方式。我们进行搜索,一个链接指向另一个,最终我们对一些我们点击几下之前甚至不知道存在的东西产生了兴趣。

我们能以同样偶然的方式传递数据吗?

在本系列的第一部分中,我们使用了降维技术来绘制 2D 空间中的相似性。我们最终得到了一个新的坐标系统,使我们能够在散点图中可视化我们的数据(见图(Plotly) )。

在本文中,我们将把它转换成一个交互式地图,包括一个搜索栏和一个侧面板。我们将使用传单和一些额外的 JavaScript。

无论数据类型如何,本文可能对任何想要构建 web 地图的人都有用。如果是这种情况,请跳到第 2 步。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

See code & end result (CodePen)

第一步。建立一个坐标的 JSON

如果您遵循非地理数据映射的,您现在有一个嵌入——一个(非常非常长的)Numpy 坐标数组,代表您在 2D 的数据。

为了在传单地图上绘制所有这些数据点,我们需要将它们存储到一个 JavaScript 对象中。

为此,我们可以将 DataFrame 转换成 JSON 字符串,并用 JavaScript 处理它。

如果您只有几个数据点要绘制,那么您可能想跳过这一步,手动将它们存储在您的 JavaScript 中。

另外,请记住,每个用户每次打开页面时都会“加载”整个 JSON。这会影响你网站的表现。根据您拥有的数据量和流量,您可能更喜欢从数据库中动态加载内容。

1/创建一个数据帧

在本例中,我将使用:

我们的 JSON 必须包含每个标记的坐标和一些数据,比如它的标题和描述,我们将用它们来更新面板的内容。

下面是我创建数据框所遵循的步骤的简要描述。你可以在这里找到完整笔记本(Github) :

  • 从 ONET 加载了 Occupation Data.xlsx 文件后,我创建了两个系列。我使用 ONET SOC 代码作为他们的公共索引,使用职业头衔和描述作为他们各自的值。然后,我将它们组合成一个单一的数据帧。
  • 最后,我创建了一个所有职业标题及其各自坐标数组的字典(基于 UMAP 嵌入),并将其映射到数据框的标题列。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

This is what your DataFrame should look like.

2/转换成 JSON

  • Pandas 有一个内置函数,可以将对象转换为 JSON 字符串:
yourdataframe.to_json('newfile.json', orient='index')

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

This is what the JSON looks like.

更多详情可以在这里找到完整笔记本(Github)

第二步。用传单创建地图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Leaflet.js is an open-source JavaScript library for responsive & interactive maps. It offers wonderful features and a beautiful default design.

创建这张地图需要 传单 自举 jQueryjQuery-ui。确保在您的代码中包含指向它们的 CSS 和 JS 库的链接。

1/创建地图

在这篇文章中,我将只使用非常基本的传单设置,并侧重于面板与地图的交互性。然而,你可以用传单做很多令人惊奇的事情,值得一看。

下面是一个快速设置。或者,你可以遵循他们的快速入门指南

  • 在您的 HTML 中,创建一个空容器:<div id="mapDemo"> </div>
  • 地图容器必须具有定义的高度。在这里,我将其设置为 100%的查看器屏幕:#mapDemo {width: 100vw; height: 100vh;}
  • 在你的 JS 中,创建地图:map = L.map('mapDemo');。因为我们在左边有一个面板,所以我们把缩放控件放在屏幕的右下角:map.zoomControl.setPosition('bottomright');

2/地块标记

数据存储在一个 JSON 文件中,其结构与 JavaScript 字典相同。请注意,我的 codePen 示例基于一个只有 3 个元素和 3 个特性(“标题”、“坐标”和“描述”)的 JavaScript 字典。

  • 首先,将 JSON 文件存储在 JavaScript 字典var markers = {}中:
var markers = $.getJSON("map_data.json");
  • 然后,遍历字典,将每个标记的特征存储在markerOptions下。用addTo(map)绘制它们:
$.each(markers, function(key, val) {
  var markerOptions = {markerId: key,
                       markerTitle: val['title'],
                       markerText: val['description']}; var marker = L.marker(val['coords'], markerOptions).addTo(map);
});
  • 要查看标记,请在数据坐标范围内设置地图视图:
var bounds = [[-10,-10], [10,10]];
map.fitBounds(bounds);

第三步。奠定基础

在处理交互性之前,让我们先把 HTML 和 CSS 放在一边。

1/ HTML

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Main elements and their ids. >> See CodePen

  • 在 HTML 的<body>中,创建一个带有表单控件(#searchTerm)和按钮(#searchBtn)的输入组。
  • 下面,添加一个按钮(#panelBtn)。它将允许用户随时打开/关闭面板。
  • 对于面板,添加一个带有关闭按钮(#closeBtn)的<div>和将用标记数据更新的内容(如标题和段落)。

2/ CSS

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

This map is mobile first. I only included a media query for screens that are 500px wide and above, but you may want to refine that.

  • 在你的 CSS 中,确保所有应该位于地图顶部的元素都有一个大于 400 的z-index(400 是地图的z-index)。
  • 默认情况下,#panel是隐藏的,只有在.active时才显示。将left属性设置为与#panel元素宽度相同的大小以隐藏它,当#panel.active时切换为 0(显示它)。
  • 对于面板高度,使用topbottom属性定义元素的开始和结束位置。请注意,如果您没有设置bottom,而是定义了一个height,滚动将不会像您预期的那样工作。#panel将继续位于可见屏幕的“外部”(尽管有overflow-y:scroll;)。
  • 在移动和小屏幕上,面板和输入组占据整个宽度。所以,我设置了width:100vw;,但是对于超过 500 像素宽的屏幕,我把它改成了width:500px;

你可以在这里找到完整代码(codePen)

3/数据结构

我们必须向前跳一点,考虑我们需要访问哪些数据来显示正确的输出。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Overview of the events that require access to markers’ data. In blue are the functions and in turquoise their respective arguments.

字典

让我们将点击标记时调用的函数称为markerOnClick(),将进入搜索后调用的函数称为search()(通过点击建议的标记标题或点击搜索按钮)。

这些功能有许多共同的步骤。为了避免两次编写相同的代码,我们将这些步骤包含在updatePanel()函数中。

为了用附加到每个markerId的标题和文本更新面板,updatePanel()必须能够访问一些其他标记特征。同样,search()markerTitle的一个函数,但是需要访问markerId来调用updatePanel()

为了让函数能够访问这些特性,我们需要字典。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

These are the key-value pairs that we need.

  • 创建 3 个字典:var titleToId = {}; var idToTitle = {}; var idToText = {};
  • 然后,在遍历markers{}字典时追加它们:
$.each(markers, function(key, val) {
...
  titleToId[val['title']] = key;
  idToTitle[key] = val['title'];  
  idToText[key] = val['description'];
...
});

目录

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

当用户输入一个搜索时,它调用autocomplete(),根据用户输入给出所有可能的标记标题。因此,此函数的数据源必须是标记标题列表:

  • 创建您在标记循环中附加的标记标题var titlesList =[];列表:
$.each(markers, function(key, val) {
...
titlesList.push(val['title']);
...
});

第四步。协调互动

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Overview of the functions associated with panel interactivity.

1/点击标记

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

When a marker is clicked: the search bar is updated with the marker’s title, the “open panel” button changes to “close panel”, and the panel opens and displays some content attached to that marker.

  • 定义updatePanel():
*var updatePanel = function(mId){
  $('#panel').addClass('active');
  $("#panelBtn").text('< Close Panel');
  var markerTitle = idToTitle[mId];
  var markerText = idToText[mId];
  $('#panelTitle').text(markerTitle);
  $('#panelText').text(markerText);
};*

marker onclick()

  • 并在markerOnClik()内呼叫updatePanel():
*var markerOnClick = function(){
  var mId = this.options.markerId;
  var markerTitle = idToTitle[mId];
  $('#searchTerm').val(markerTitle);
  updatePanel(mId);
};*
  • 在循环中,将 onClick 事件添加到所有标记中。设置弹出选项(popupContent)并将弹出绑定到标记单击:
*$.each(markers, function(key, val) {
...
  marker.on('click', markerOnClick);
  var popupContent = val['title'];
  marker.bindPopup(popupContent);
...
});*

现在,当用户点击一个标记时,相应的弹出窗口就会打开。

2/搜索输入

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

When the user types in the search bar, the autocomplete suggests a few marker titles. From there, the user can either select one of those suggestions or confirm her search. Either way, the output is the same as when a user clicks on a marker (see 1/ Click on marker).

autocomplete()

  • 这里,我们定义了 autocomplete()的选项。同样,当从自动完成中选择一个条目时,我们将其值存储在#searchTerm中并调用search():
*$(function() {
   $("#searchTerm").autocomplete({
     source: titlesList,
     minLength: 1,
     select: function(event, ui) { 
       $("#searchTerm").val(ui.item.label);
       console.log(ui.item.label);
       search();
     }
   });
 });*

搜索()

现在,如果用户点击一个建议的markerTitle,就会调用search()updatePanel()。但是,如果没有实际点击标记,弹出窗口就不会显示。

一种解决方案是给每个标记附加不同的层。然后我们可以将 fleet 的 openPopup()方法应用于search()函数中的层。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

LayerGroup is a method from the Layer class used to group several layers and handle them as one >> see documentation

  • 创建一组图层var layers = L.layerGroup().addTo(map);并在标记循环layers.addLayer(marker)中更新
  • 每个标记都有一个层,但是我们需要一个字典来允许我们根据标记的markerId : var idToLayer = {};检索标记的层:
*$.each(fgLayers._layers, function(key,val){
  idToLayer[val.options.markerId] = key;
});*
  • 我们终于可以定义search()函数了。它从搜索字段中获取markerTitle,找到它对应的标记,打开它的弹出窗口并调用updatePanel():
*var search = function(){
 $("#searchTerm").blur(); 
 var markerTitle = $("#searchTerm").val();
 var markerId = titleToId[markerTitle];
 var layerId = idToLayer[markerId];
 var layer = layers._layers[layerId];
 layer.openPopup(); updatePanel(markerId);
}*

3/打开-关闭面板

在用户进行搜索或点击标记后,我们希望他们能够关闭面板并随时返回地图。我们还想让他们直接从地图上重新打开面板。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

To close the panel, the user can either click the close button of the panel or click the “close panel” button on the map.

togglePanel()

#panelBtn按钮允许用户连续打开或关闭面板。它的内容应该根据它允许用户接下来做的动作(打开或关闭)而改变。我们可以通过使用 jQuery 的 toggleClass 方法来实现这一点。

  • 给按钮添加一个 onClick 事件:<button onClick = "togglePanel()";>并定义togglePanel():
*var togglePanel = function() {
  $('#panel').toggleClass('active');             
  $("#panelBtn").text(($("#panelBtn").text() == 'Open Panel >') ? '< Close Panel' : 'Open Panel >'); 
}*

关闭面板()

#closeBtn按钮允许用户在面板打开时关闭面板,并更新#panelBtn内部 HTML。

  • 给按钮添加一个 onClick 事件:<button onClick = "closePanel()";>并定义closePanel():
*var closePanel = function() {
  $('#panel').removeClass('active');
  $('#panelBtn').text('Open Panel >');
}*

包裹

感谢您的阅读😃

在本系列中,我们介绍了如何使用降维来构建散点图,该散点图使用距离作为相似性的代理,并将其转换为交互式地图。

我在撰写这些文章和为它们配插图的过程中获得了很多乐趣,并在此过程中学到了很多东西。我希望你已经发现它是有用的,并且我期待在那里看见更多令人惊奇的地图。

🔗链接到#第 1 部分:如何通过降维映射相似性

👉看看我是如何在实践中使用它的:www.tailoredpath.com

如何建立支付数据团队

原文:https://towardsdatascience.com/how-to-build-a-payments-data-team-8c76e0048e0?source=collection_archive---------22-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Paying with Apple Pay on a Square Device

在过去的几年里,我们看到支付行业的收购数量越来越多。从收购老牌全球公司的大型投资者,如旧金山合伙人- > Verifone ,到出于能力、地理扩张或整合目的的战略收购,如 ING - > PayVisionWorldFirst - > WyreWorldline - > SIX 。然而,那些似乎还没有被收购的公司,是那些将利用他们的数据作为关键战略目标的公司。在这篇博客中,我分享了支付(适用于其他金融科技公司和科技公司)如何建立数据团队并超越竞争对手。

必需品与奢侈品 平心而论,支付行业在过去十年中发生了巨大的变化,像所有的变化一样,这不是因为大型企业公司,而是因为精益创业公司进行创新,并找到新的方法将支付纳入他们的产品和流程。到目前为止,包括脸书、Spotify、优步和网飞在内的“创业公司”在定义十多年前还不存在的新的电子商务类别方面发挥了极其重要的作用。这些新企业带来的主要东西是它们的数据驱动的工作方式。

这些公司不再关注处理了多少收入,而是更加关注其整体平台的效率。从转换率到授权率。利用他们数据驱动的工作方式,他们影响了许多“新”支付公司,以提供尽可能多的数据。随着这些新公司正在取代一些老公司,新老支付公司都必须适应并不断提供数据。

建立支付数据团队 支付是一种技术产品,这意味着尤其是在建立网关或收购方的初期,开发团队说了算。如果我今天要建立一个新的支付公司,这不会有很大的不同。但是,请记住,在某一点上,业务用户会开始提问,因此最好从能够检索回答这些问题所需的数据和见解的基础架构开始。

1。雇用一名数据经理(数据主管、数据副总裁等)。),最好有支付方面的经验。 因为业务将不得不从发展重心转移到业务重心,你需要一个数据经理,他了解双方,知道如何与双方沟通,并能够组建一个团队来执行战略和愿景。一个数据管理者的开始阶段,是与管理和业务用户一起度过的。了解业务和管理层想要实现的目标,同时与业务用户进行对话,以了解他们需要什么来完成工作。收集了所有需求后,经理应该制定一个数据策略,该策略应该是业务发展的基础。

2。雇佣数据架构师很多时候,公司会走路之前就想跑。您雇用数据架构师的原因是,现有的基础架构是为业务的开发方面而构建的。很长一段时间以来,支付在其数据中非常结构化,但是由于电子商务、移动商务和物联网商务,越来越多的数据变得更加非结构化。这就是为什么如果您想要检索数据并获得洞察力,您需要构建单独的数据基础架构。数据架构师将能够审查当前的基础设施,利用现有的部分,并设计不干扰现有基础设施的基础设施,同时为数据团队提供支持组织所需的资源。

我经常被问到,为什么我不能让我的数据工程师来设计基础设施呢?对此,我回答说,如果你在建房子,你会先雇建筑师还是建筑商?架构师制定计划,考虑所有的利弊,利用他的经验(主要是作为一名数据工程师),来设计一个在短期内有效并可以长期构建的基础设施。

3。雇佣一名数据工程师 一名优秀的数据工程师,了解最新的云技术,至少精通 SQL 和 Python。大多数数据工程师更喜欢在 AWS 工作,因为这是最受技术驱动的平台,也是历史最长的平台。然而,随着更现代的云技术的增加,如用于 ETL’ing(提取、转换&加载)的Matillion&five tran和用于数据仓库即服务的 SnowflakeGoogle BigQuery ,许多基础设施变得不那么复杂,而是更关注速度、灵活性和快捷性。随着数据量、速度和种类的快速变化,知道如何找到适合工作的工具的数据工程师可以完成更多工作,并帮助您的团队获得正确的结果。

4。雇用数据分析师和/或 BI 分析师 经过一段时间的设计和构建后,下一个雇员应该是数据分析师,他最好有一些业务背景,但在使用数据库和查询检索数据方面要先进得多。使用 R 或 Python 等编程语言,进行比 Excel 更复杂的数据分析。您希望数据分析师至少具备一些编程技能的另一个原因是,在大多数情况下,数据在成为可供数据分析师或业务用户分析的数据类型之前,可能需要进行一些清理和转换。

随着该团队的能力不断提高,类似查询请求的数量也在增加,数据分析师将成为将其查询转换为仪表板的关键,仪表板可以分布在整个组织中。通过将业务语言转化为建模层,并使用 Looker 等数据平台,数据团队的角色将开始从数据的控制者转变为解放者,让所有业务用户能够提出他们想要的问题,并自由探索数据,以他们认为合适的方式。

5。雇用一名数据科学家 只有在前四名雇员成功开发了自助式数据平台后,数据科学家才能加入进来,帮助组织真正实现数据驱动。一个伟大的数据科学家,可以专注于与团队合作开发数据驱动的应用程序。在支付行业,这可能意味着开发预测性应用程序,如获取路由(根据历史数据和权重,选择最佳路径)、动态授权(在提交交易前输入或删除数据)或构建欺诈引擎,该引擎能够预测哪些交易是欺诈性的,哪些不是。

您建立了自己的数据团队了吗? 如果你是一名企业主,或者数据属于你的职责范围,你可能会想,这是否真的值得。如果我们看看像脸书、优步、网飞和 Spotify 这样的公司,我们可以看到,控制你的数据,不仅会导致更好的决策和改进的运营,而且实际上可以让你赚更多的钱。对于支付行业来说也是如此,该领域的领导者包括 Stripe、Square、Transferwise 和 Plaid,它们比所有竞争对手都更好地利用数据。

那么,你已经建立了你的数据团队了吗?

感谢阅读;),如果你喜欢它,请点击下面的掌声按钮,这对我意义重大,也有助于其他人了解这个故事。让我知道你的想法,在推特上联系我。或者关注我,阅读我在数据科学、支付和产品管理方面的帖子。

如何为松弛消息建立一个具有 BERT 文本分类的 AI Besserwisser

原文:https://towardsdatascience.com/how-to-build-a-real-besserwisser-with-bert-text-classification-for-slack-messages-b4a13d7ca822?source=collection_archive---------14-----------------------

当别人在电子邮件中不应该“回复所有人”时,或者有人在不属于它的频道上写了一条松散的消息时,我总是被人们的愤怒逗乐。

有鉴于此,我决定在 Peltarion 平台上玩一玩新发布的预训练 BERT(来自变压器的双向编码器表示)块,看看我是否可以建立一个识别松弛消息模式的模型,以便告诉人们何时消息被发布在错误的松弛通道上,并建议它属于哪里。

所以让我们建造一个机器人,也就是真正的无所不知者,它可以自动完成这项工作😈。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image of Besserwisser via buttsss.com by Pablo Stanley.

在我工作的 Peltarion,我们有许多不同的休闲频道,用于各种目的。我们有自己的“官方”渠道,但也有很多其他更小的渠道。一些相当模糊的,因为人们有许多不同的兴趣。我们有#general(官方声明)、#random(不在 general 之列的东西)、#climbing、#music、#boardgames、#壁球……应有尽有。

总的来说,我确实认为人们很善于决定什么属于哪个频道。因此,我的直觉是,有某种东西可以区分来自不同渠道的信息,这是一个模型应该能够学习的。但是让我们来看看。

为了给我们的模型一个公平的机会,我们需要每个通道有相当数量的消息。看起来似乎大多数“问题”都是在一条消息被发布在#general 中时出现的,而实际上它应该被发布在#random 中。所以,我决定开始使用这两个渠道。使用 Slack 的 Python API 客户端,从这两个渠道获取消息,然后将它们上传到 Peltarion 平台(基于云的深度学习平台)非常容易。

建立模型

*下一步:构建模型。*这部分可能会比较棘手,尤其是如果你之前没有那么多构建 AI/深度学习模型的经验。但老实说,这可能是整个项目中最简单的部分,因为我可以将预先训练好的 BERT 模块插入到我的模型中。我尝试了一些不同的超参数,可以在两分钟内开始训练——通常我需要花更长的时间来决定 GitHub repo 的名称🤔。

构建、微调和部署花了我大约 30 分钟的时间。我运行了几个不同的实验(3-4),选择了一个准确率最高的实验(72%;不太好,但对这个小玩具项目来说足够好了)。然后,训练需要大约半小时到一小时来完成。

现在,让我们看看这位模特在野外的表现吧!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

为此,我构建了一个非常简单的 Slackbot(简单得近乎愚蠢),它可以仔细检查消息并决定它们属于哪个通道。现在,无论何时有人在错误的渠道发布消息,你不必非得是那个同事告诉他们。相反,让你自己的私人贝塞威斯为你照顾它。任务完成!

…以下是如何将 Besserwisser 应用于其他真实用例的方法

对我来说,创建这个 BERT 应用程序只是一种有趣的方式,可以玩玩预先训练好的模型,并在我的日常生活中部署它。如果我在这上面多花一些时间,我会继续微调它,以获得更高的精度。使用来自两个以上 Slack 通道的数据来获得一个更有用的 Slackbot 也是很有趣的,它可以给出更多关于消息归属的建议。

如果你想亲自尝试,这里有一个由我的同事 Calle 创建的循序渐进的教程。

同样的模型也可以应用到其他领域,也许是更多的“现实生活”用例。假设你在一家公司工作,有大量的客户支持任务要处理。日复一日,信息不断涌入,从客户那里发来,希望得到迅速的答复(最好是尽快)。根据问题的不同,这些消息需要由组织中不同的人来回答。构建和部署一个与我的 Slackbot 应用程序中使用的模型类似的模型,可以允许根据主题/应该重定向给谁来对所有消息进行分类。通过这种方式,门票可以最终到达正确的人手中,并更快地得到处理。

如果你喜欢贝塞维瑟的 Slack icon,去看看巴勃罗·斯坦利的buttsss.com(他也有很多其他的好东西)。

如何为星巴克搭建推荐引擎

原文:https://towardsdatascience.com/how-to-build-a-recommendation-engine-for-starbucks-662a982df0c2?source=collection_archive---------14-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

The Embarcadero, San Francisco, CA

咖啡对我们生活和文化的影响怎么强调都不为过。2018 年,64%的 18 岁或以上的美国人说他们前一天喝了一杯咖啡,而星巴克约占美国咖啡连锁行业的 40%。

在这篇文章中,我们将探索不同的方法来建立一个推荐引擎,推荐 10 种未指定的星巴克产品。这些优惠可以是买一送一 (BOGO),折扣或信息。共有 10 个优惠,它们在难度、持续时间和奖励方面各不相同。

对于每一种方法,我们将用数学公式抽象出问题,解释它如何应用到方法中,并用 python 代码解释它。

获取数据

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Nathan Dumlao on Unsplash

用户的数据已经被清理,在 GitHub 上有 python 的详细实现。虽然没有在这篇文章中讨论,但是清洗过程在设置中注入了一些变化,并且影响了我们的输出。

任何数据科学项目的症结都在于数据收集、争论以及在此过程中做出的许多假设。这个项目绝不是一个例外。当我们讨论不同的方法时,请记住数据的质量是支持我们结论的基石。

第一条信息是用户特征矩阵,其中行是 Starbucks 用户 id,列是关于这些用户的属性。我们总共有大约 17,000 个用户和 23 个功能,有些是直接观察到的,例如:

  • 收到的报价数量
  • 报价类型(电子邮件、社交媒体等)
  • 收入

其他的来源于用户抄本,例如:

  • 回应或完成报价的平均时间
  • 每次出价的平均奖励
  • 因为出价而花费的总金额

下面是用户数据框架的示例截图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

User-Feature Matrix

还有一份抄本的样本:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Transcript of User Behavior

第三个数据帧是一个用户项目矩阵,其中行是用户,列是报价 id,这也是一个非常稀疏的矩阵。我们的条目将是多少次,如果有的话,用户已经查看了报价。如果没有收到报价,我们输入一个 NaN 值,因为我们无法衡量未被请求的参与度。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

User-Item Matrix

推荐什么最受欢迎

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Toa Heftiba on Unsplash

美国最受欢迎的咖啡饮料是拿铁,美国人在 2017 年 6 月至 2018 年 6 月期间喝了超过 67,000,000 杯拿铁。我们应该总是建议喝杯拿铁吗?

第一种方法是最简单的:建议什么是最流行的。人们的假设是,受大众欢迎的东西也受个人欢迎。

出现的一个问题是,我们如何定义流行度,在这种情况下,我们提出两种方法:

  • 浏览量最多的出价
  • 每次观看回报率最高的报价

最受欢迎视图的实现方式如下:

这种方法在新颖性和用户的意外收获方面有所欠缺。它还可以通过已经流行的方式使项目变得流行。

然而,这是一个稳健的解决方案,这也意味着我们总是有地方开始,并且不受冷启动问题的影响。此外,将这个工具放在用户手中也很有用,他们可以选择“最流行”或“最近”的项目。这是一个基于知识的方法的例子。

当我们探索其他方法时,我们的基本假设是视图会带来更多的用户参与和金钱回报。

协同过滤:用户-用户相似性

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Nani Williams on Unsplash

我们的消费习惯经常受到身边人的行为影响。我们向朋友询问他们最喜欢的商品,或者在网上寻找评论。

下一种方法是利用用户之间的相似性来提出建议。这里的假设是,无论我们如何定义相似性,相似的人都会喜欢相似的东西。随着那些相似的邻居被识别,我们向我们的原始用户建议我们的邻居喜欢的新奇物品。

这种方法被称为协同过滤,我们给出了三种实现方法。我们首先创建一个简单的函数来收集单个用户看到的报价。

然后,我们可以构建一个字典来存储用户看到的报价。

我们现在可以着手测量用户之间的相似性。

欧几里德距离

如果我们把用户想象成空间中的点,那么我们可以认为占据同一个邻域的用户非常相似。因此,如果我们取一个用户,k 个最近邻居应该是最相似的。如果这听起来很熟悉,那是因为它确实是K-最近邻算法。

对于两个向量 xy ,我们计算欧几里德距离为:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在 python 代码中:

和 KNN 一样,欧几里得距离对比例很敏感。或者,我们可以用曼哈顿距离 ( L1 范数)来度量相似性。

相互关系

皮尔逊相关系数返回一个介于-1 和+1 之间的值,其中+1 表示非常强的正相关,而-1 表示非常强的负相关。

相关系数 ρ 由下式给出:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

到这样的程度

在 python 代码中:

虽然还有其他方法,如 Kendall 的 Tau 和 Spearman 的等级相关性,但选择正确的方法取决于数据分布。

皮尔逊系数的一个关键优势是它对缩放比例不变。然而,它对异常值并不鲁棒,并且对底层数据分布做出假设。

如果数据按照各自变量的样本均值移动,也就是说减去均值,皮尔逊相关就是两个变量之间夹角的余弦值,我们接下来将讨论这个问题。

余弦相似性

测量相似性的最后一种方法是测量两个向量之间的余弦。对于两个矢量 XY ,由下式给出:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使得 ||X||||Y|| 是向量的范数。回想一下,零的余弦等于 1,这意味着两个向量具有相同的方向。我们可以用 scipy 实现这一点:

矩阵分解

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by nousnou iwasaki on Unsplash

实际上,我们想知道客户对我们的产品有什么反应。请记住,发出要约是有成本的。在我们的例子中,我们想要测量用户参与度:如果我们提出一些建议,用户真的会看到吗?

假设检验似乎很有吸引力,因为这是衡量成功的一个好方法。如果我们可以离线测试我们的推荐会怎么样?如果我们还可以预测还没看过的项目的评分呢?我们将在本节中尝试回答这些问题。

奇异值分解( SVD )是一个实数或复数矩阵的因式分解,让我们看到无法直接观察到的潜在特征。它将一个 mxn 矩阵分解成:

  • U: 酉矩阵,显示用户与潜在因素的关系
  • ∑: 对角矩阵以值降序排列,条目为潜在因素
  • v:酉矩阵,显示项目如何与潜在因素相关

这三个矩阵通过以下方式与原始用户项矩阵相关联:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • n =用户数量
  • k =潜在特征的数量
  • m =项目数量

我们将只使用 SVD 的属性,不会深入研究它的工作原理。为了更好的解释,我们推荐斯坦福 CS246 和这个麻省理工学院教程

∑ ( sigma )矩阵告诉我们许多关于用户项目矩阵中的原始可变性有多少被每个潜在特征所捕获。要解释的可变性总量是对角线元素的平方之和。

此外,由第一个分量解释的可变性的量是对角线上第一个值的平方,第二个值也是如此,以此类推。这意味着我们可以选择较少数量的潜在特征( k )并捕捉原始矩阵的几乎所有可变性,这是一个有助于节省计算的特性。

在我们拥有的真实用户条目矩阵中,许多值都丢失了。这意味着 SVD 不起作用。在 Netflix 颁奖期间,一个名叫西蒙·芬克的用户开发了 T2·芬克 SVD,作为一种计算缺失数据的方法。我们将通过这个算法的一个小例子,并推广到数据集。

初始化两个填充了随机值的矩阵 UV.T 。我们转到原始的用户项矩阵,搜索第一个非缺失值。然后,我们取与用户相关的行和与电影相关的列的点积。

在我们的例子中,我们看到 person 0 的第一个值是 offer_id 4。以此为例,我们计算点积如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从这里我们可以计算出误差:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

对于真实值 1,我们的误差是 4.24。我们的目标是通过改变每个矩阵中的权重来最小化所有已知值的误差,我们可以通过梯度下降来实现。

在用户矩阵中,我们取误差相对于每个值 ui 的导数。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在电影矩阵中,我们对每个值 vi 取误差的导数。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

然后,我们通过向渐变的相反方向移动来更新高亮显示的值:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们对用户项目矩阵中的所有已知评级进行相同的计算,并对设定数量的时期重复。

用 python 实现这一点:

我们现在想建立一种方法来验证我们的预测。我们在训练和验证中拆分数据,使 FunkSVD 适合训练数据,并在验证数据中为用户做出预测:

让我们用直方图和混淆矩阵来看看我们的预测。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们可以看到 w 在某些方面是错误的,但是能够预测看不见的项目是一个非常有用的特性。我们也可以使用网格搜索来调整我们的超参数。改进这种方法的研究正在进行中,如赵等人的论文

结论

我们看到有多种方法可以提供建议,每种方法都有其优势。没有明确的答案,通常使用混合方法的项目可能是最好的解决方案。

与大多数数据科学项目一样,我们拥有的高质量数据越多,结果就越好。希望你喜欢这篇文章!

鸣谢:帮助撰写本文的咖啡因是由三号*菲尔茨在福尔松 Illy on Battery 的 星巴克的了不起的咖啡师准备的。 特别感谢uda city和星巴克提供这些数据!*

如何快速简单地构建推荐引擎

原文:https://towardsdatascience.com/how-to-build-a-recommendation-engine-quick-and-simple-aec8c71a823e?source=collection_archive---------0-----------------------

第 1 部分:介绍,如何在一周内投入生产,之后去哪里

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Recreation of Rina Piccolo’s cartoon (Cartoonist Group)

这篇文章是对这个主题的一个简单介绍,并且提供了在一周内让你进入推荐引擎生产的第一步。我还会告诉你从基础到相当高级的步骤。

我们还不会走在前沿,但也不会太远。

当快速和简单不再足够时,请阅读第 2 部分以了解更高级的用例:

[## 推荐引擎的高级用例

第 2 部分:当快速和简单不再足够好时,如何构建您的下一个推荐引擎。

towardsdatascience.com](/advanced-use-cases-for-recommendation-engines-4a420b14ab4e)

推荐系统无处不在,对于许多在线平台来说,他们的推荐引擎就是真正的业务。这就是亚马逊大的原因:他们非常擅长向你推荐该读哪些书。还有许多其他公司都是围绕推荐系统建立的:YouTube、网飞、Spotify、社交媒体平台。与此同时,消费者开始期待个性化的体验和复杂的推荐系统来找到相关的产品和内容,这一切都是为了节省消费者的时间和金钱。

但是如何构建推荐引擎呢?

背景

推荐引擎已经存在了一段时间,有一些重要的经验可以利用:

  1. 用户的行为是用户意图的最佳指示器。评级和反馈往往非常偏颇,而且音量较低。
  2. 过去的行为和购买推动新的购买,与他人的购买和行为重叠是一个很好的预测。

推荐系统通常寻找重叠或同现来进行推荐。就像下面这个例子,我们基于 Ethan 和 Sophia 的相似性推荐 Ethan 一只小狗:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Recreation of illustration in “Practical Machine Learning, Ted Dunning & Ellen Friedman, O’Reilly 2014

在实践中,推荐引擎从事件和动作的历史矩阵中计算出同现矩阵。这很简单,但是在现实世界的场景中有很多挑战需要克服。如果每个人都想要独角兽呢?下面这个例子中独角兽的高共现是不是很好的推荐?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Recreation of illustration in “Practical Machine Learning, Ted Dunning & Ellen Friedman, O’Reilly 2014

在推荐系统已经计算了同现矩阵之后,我们必须应用统计来过滤掉足够异常的信号作为推荐。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Recreation of illustration in “Practical Machine Learning, Ted Dunning & Ellen Friedman, O’Reilly 2014

能够从共现矩阵中提取出相关指标的算法和统计是一个好的推荐系统的基础。创建项目到项目指标矩阵的路径称为项目到项目模型。显然还有一个用户项模型:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

为了创建用户项目模型,我们可以应用简单的矩阵分解或训练神经网络来预测用户项目输入的分数。通常,当我们不在特征工程和模型调整等方面投入更多时,项目-项目模型更健壮,并产生更好的结果。

然而,一个好的推荐系统还需要克服一些挑战。反复推荐同样的东西无聊。更糟糕的是,推荐同样的东西会产生坏数据并导致内容疲劳

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Spotify wouldn’t produce such a result set! Their search and recommendation engines are top notch! This example needed editing. ❤ Spotify

提高推荐价值的两个简单直观的策略是

  1. 反泛滥:如果第二个和第三个推荐与第一个推荐具有相同的相似性得分,则惩罚它们。
  2. 抖动:添加一个通配符推荐,为推荐系统创建有趣的新数据点,以不断了解其他内容。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这些步骤确保了有趣的用户体验和替代推荐的新数据。

数据和要求

推荐系统最适合不带偏见的明确用户反馈,比如购买产品、看视频或听歌。如果你运气好,有这样一个数据集,即使是一个简单的方法也能很好地工作。然而,在许多用例中,你主要有隐性反馈,如页面浏览量、点击量或搜索查询量。不幸的是,这些数据也有很大的偏差,例如点击率很大程度上取决于内容在页面上的位置。隐式反馈也往往表现不佳,例如,点击搜索结果可能只是告诉你标题或 CTA 的点击量,而不是实际内容的相关性。这导致在最初的高点击率之后的高跳出率(一个非常普遍的情况!)

像协同过滤这样的简单方法需要项目之间的共现。这意味着协同过滤是合适的,并且如果

  • 你的产品目录不要太大,条目的寿命很长,可以很容易地被多个用户交互。让我们以陷入困境的 Zoopla 为例:Zoopla.co.uk是一个房地产门户网站,在任何时间点都有超过 130 万个房源。伦敦的出租清单是非常短暂的,在一处房产被租出并退出市场之前,可能只需要几天时间。很明显,你不能同时向多人出租或出售公寓!以 Zoopla 目录的规模,即使在 Zoopla 的流量下,也很难产生大量的同现。
  • 你不依靠推荐来发现新产品。因为协同过滤需要同现来产生信号,所以该算法有一个大的冷启动问题。产品目录中的任何新项目都不会同时出现,并且在用户没有与新项目进行一些初始互动的情况下无法推荐。如果你的企业大量使用 CRM 和市场营销作为推广新产品的策略,这是可以接受的。

协作过滤快速简单

一种选择是使用 Spark 和交替最小二乘(ALS)算法(链接),这是一种用于模型训练的简单解决方案,但不提供用于部署和评分的即时解决方案。我推荐一种不同的方法来开始:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

事实证明,搜索和推荐问题的数学原理惊人地相似。最重要的是,良好的用户体验在搜索和推荐方面几乎是不可区分的。基本上,如果我们能够将推荐表述为搜索查询,那么搜索结果就是推荐。这是一个理想的解决方案,因为许多网站和企业已经在其后端运行搜索引擎,我们可以利用现有的基础设施来建立我们的推荐系统。Elasticsearch 可很好地扩展,并作为完全托管的部署存在,例如在 AWS 上。如果您想快速将您的推荐引擎部署到生产环境中,这是最安全的选择!

如何用搜索引擎创建推荐?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 我们将所有用户项目交互存储在一个搜索索引中。
  2. 当用户在苹果的页面上时,我们会在 elasticsearch 中搜索所有拥有苹果的用户。这定义了我们的前景人口。
  3. 我们在给我们小狗的前景中寻找同现。
  4. 我们在背景人群中寻找小狗。
  5. 我们为我们的小狗推荐计算某种分数。

好消息是:Elasticsearch 在一个查询中为我们实现了所有 5 个步骤!

如果我们在弹性搜索中存储用户-项目交互,如下所示

{
  "_id": "07700f84163df9ee23a4827fd847896c",
  "user": "user_1",
  "products": ["apple", "book", "lemon", "puppy"]
}

使用这样的文档映射:

{
  "user": {"type": "keyword"},
  "products": {"type": "keyword"}
}

那么产生一些建议所需要的就是下面的查询,例如使用 Python:

from elasticsearch import Elasticsearch, RequestsHttpConnection
from aws_requests_auth.boto_utils import BotoAWSRequestsAuthes = Elasticsearch(
  host=host, port=port, 
  connection_class=RequestsHttpConnection,
  http_auth=BotoAWSRequestsAuth(),
  scheme=scheme
)es.search(
  index=index, doc_type=doc_type,
  body={
    "query": {
      "bool": {
        "must": {
          "term": {"products": "apple"}
        }
      }
    },
    "aggs": {
      "recommendations": {
        "significant_terms": {
          "field": "products",
          "exclude": "apple",
          "min_doc_count": 100
        }
      }
    }
  }
)

默认情况下,Elasticsearch 将返回带有 JLH 分数的推荐,但是有一个可用的分数范围(文档)。

{
 ...
 "aggregations": {
    "recommendations": {
        "doc_count": 12200,
        "bg_count": 130000,
        "buckets": [
            {
                "key": "puppy",
                "doc_count": 250,
                "score": 0.15,
                "bg_count": 320,
            }           
         ]
      }
   }
}

在我们的示例中,搜索 apple 返回了 12,200 个用户的前景人群和 130,000 个在其产品中没有任何 apple 的用户的背景人群。小狗在前台共出现 250 次,在后台共出现 320 次。JLH 分数是背景集合与由**(fg _ percentage-BG _ percentage)*(fg _ percentage/BG _ percentage)**给出的本地搜索结果之间的变化的简单幅度,其给出 0.15 的分数

由于 JLH 分数是一个数量级的变化,重要的是要记住跳蚤跳得比大象高,JLH 分数对于小数据集来说非常不稳定。您可以调整查询中的min_doc_count参数,以保证您的推荐结果的质量。

这就是它,一个简单但强大的推荐引擎的第一次迭代,它可以在一周或更短的时间内上线!重要的是,任何版本 1 都不应该比这更复杂。生产时间在早期阶段更为重要。通常,你的第一个推荐引擎需要一些迭代来优化用户界面和 UX,而不是数学。

后续步骤

Elasticsearch 不仅仅是一个非常强大的推荐后台,它还非常灵活!在保持 elasticsearch 后端的同时,有很多方法可以改进我们的推荐系统。赢了!

当快速和简单不再足够时,请阅读第 2 部分以了解更高级的用例:

[## 推荐引擎的高级用例

第 2 部分:当快速和简单不再足够好时,如何构建您的下一个推荐引擎。

towardsdatascience.com](/advanced-use-cases-for-recommendation-engines-4a420b14ab4e)

第一步:

我们可以使用 ALS 等更复杂的算法来为我们的推荐创建指标,并将这些指标放入 elasticsearch。这将推荐评分简化为一个简单的查找,因为我们在培训阶段进行繁重的工作,例如使用 Spark。这样,elasticsearch 只是我们为相关推荐提前计算的指标的一个性能表示层。您可以轻松地将它作为新的元数据添加到现有的产品目录中。

第二步:

目前,我们在产品数组中使用二进制标志,这意味着产品数组中的每个产品对 JLH 得分的贡献是相等的。如果没有太多的变化,我们可以使用一些指标来对产品事件本身进行评分,以捕捉更丰富的信号。我们可以用点击计数。或者更好的是,我们可以通过产生点击的页面位置的平均预期点击率来标准化点击,从而使用点击分数。例如,在搜索结果列表中,我们可以计算位于第一位置、第二位置等的项目的预期 CTR。然后,我们可以从项目度量分数的总和而不是它们的简单计数来计算 JLH 量级的变化。

第三步:

用户通常会生成一系列与推荐相关的事件,例如,点击多个商品或将多个产品添加到一个购物篮中。值得为您的推荐引擎添加一个用户交互缓存:( 1)使用一系列事件创建更复杂的搜索查询;( 2)在更新 elasticsearch 索引的批处理 ETL 过程和自上次更新推荐引擎以来发生的用户交互之间创建一个增量。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用事件序列来产生推荐可以有助于(1)创建更相关的结果,以及(2)在低流量或非常大的目录的情况下,增加前景群体来生成更大数量的同现。只需要对 elasticsearch 查询做一点小小的修改,就可以切换到一个should查询:

es.search(
  index=index, doc_type=doc_type,
  body={
    "query": {
      "bool": {
        **"should": [**
          {"term": {"products": "apple"}},
          {"term": {"products": "pony"}},
        **],**
        **"minimum_should_match": 1,
**      }
    },
    "aggs": {
      "recommendations": {
        "significant_terms": {
          "field": "products",
          "exclude": ["apple", "pony"],
          "min_doc_count": 10
        }
      }
    }
  }
)

minimum_should_match参数允许您在增加前景人口规模或通过增加相似性匹配用户使结果更相关之间进行优化。

第四步:

目前,我们的搜索是对项目的精确查找。这带来了一些后果:我们从用户交互中学习到的关于共现的一切都与它们的特定项目绑定在一起。当一件商品从产品目录中删除时,我们就失去了从它身上学到的一切。我们也不能将任何事物概括为相似的项目,例如,红苹果和绿苹果是不同的项目,同现仅限于红苹果或绿苹果的精确匹配。为了克服这一点,我们需要用数学方法描述项目,以计算项目之间的相似性。这被称为嵌入。阅读我以前的博文,我创建了一个嵌入了 T5 的 T4 地理区域。创建嵌入的其他选项是如上所述的用户项目模型中的自动编码器或矩阵分解。在我们将一个简单的 product_id 转化为嵌入之后,我们可以使用概率或模糊搜索来找到我们的前景群体和/或同现。

这应该能让你从推荐开始。当您从产品反馈中学习时,它也给了您充分的机会来构建您的第一个迭代。

推荐的早期步骤好坏更多地取决于用户界面和 UX,而不是数学的简单性。

超越弹性搜索

通常,产品有我们应该使用的大量元数据,例如价格、描述、图片、评论评级、季节性、标签和类别。在我们将丰富的元数据集转换成描述我们产品的嵌入之后,我们可以训练神经网络将输入嵌入映射成推荐嵌入,该推荐嵌入具有(1)较低的维度和(2)合适推荐的余弦相似性的期望行为是高的。一个很好的解决方案是连体神经网络。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

输入是产品元数据的级联嵌入的高维向量。神经网络的输出是更紧凑的推荐嵌入向量。误差函数由输出向量的余弦相似性给出。我们可以使用协同过滤数据来为应该相似或不相似的组合创建我们的监督学习标签。重要的是,在连体神经网络中,两个网络的权重总是相同的,这就是它们的名字。这种推荐引擎将不再有冷启动问题!最后,产生推荐可以通过对输出推荐嵌入的 k-最近邻搜索来完成。

您可以在后续文章中了解更多后续步骤:

[## 推荐引擎的高级用例

第 2 部分:当快速和简单不再足够好时,如何构建您的下一个推荐引擎。

towardsdatascience.com](/advanced-use-cases-for-recommendation-engines-4a420b14ab4e) 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Jan 是公司数据转型方面的成功思想领袖和顾问,拥有将数据科学大规模应用于商业生产的记录。他最近被 dataIQ 评为英国 100 位最具影响力的数据和分析从业者之一。

在 LinkedIn 上连接:【https://www.linkedin.com/in/janteichmann/】

阅读其他文章:https://medium.com/@jan.teichmann

如何利用潜在因素协同过滤构建餐厅推荐系统

原文:https://towardsdatascience.com/how-to-build-a-restaurant-recommendation-system-using-latent-factor-collaborative-filtering-ffe08dd57dca?source=collection_archive---------2-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image Designed by Freepik

介绍

我通常在工作间隙看 youtube。我承诺自己只看 5 到 10 分钟的 Youtube,让我的大脑休息一下。通常情况是这样的,在我看完一个视频后,下一个视频会从 Youtube 推荐中弹出,我会点击那个视频。当我再次看手表的时候,发现我已经看了一个多小时的 Youtube 了!😂

Youtube 的推荐系统是最强大和最复杂的推荐系统之一,可以让其用户连续几个小时观看 Youtube 视频。许多初创公司巨头,如网飞、Youtube 和亚马逊的收入主要来自他们建立的推荐系统。

本文主要讨论如何使用潜在因素协同过滤从零开始构建一个餐馆推荐系统。

什么是推荐系统?

推荐系统或推荐系统是简单的算法,旨在通过从庞大的信息库中过滤有用的东西,向用户*(客户、访客、应用程序用户、读者)提供最相关和最准确的项目(产品、电影、事件、文章)*。推荐引擎通过学习消费者的选择来发现数据集中的数据模式,并产生与其需求和兴趣相关的结果。

想象一个实体服装店。好的商家知道顾客的个人喜好。她/他的高质量推荐让客户满意,增加利润。当你去其他国家或城市旅行时,在选择一家餐馆吃午餐或晚餐的情况下,通常你会问你住在那个国家或城市的朋友镇上最好的餐馆是什么。问题是你没有任何朋友住在那个镇上。你的个人推荐可以由一个人造朋友产生:推荐系统。

矩阵分解或潜在因素协同过滤

有各种类型的推荐系统,但我建立的这个餐馆推荐系统。我侧重于使用矩阵分解或潜在因素协同过滤。让我们从因式分解这个术语开始。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

当我们考虑因式分解时,它是一个类似于六乘四等于二十四的概念。24 是一个很大的数字,但是我们把它表示成两个小数字 6 和 4 的乘积,所以我们设法把一个大数字分解成两个小数字的乘积。类似的概念也适用于矩阵分解。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

推荐系统是一个信息过滤系统,它试图预测用户对项目(在本例中是一家餐馆)的评分。我们可以将来自用户和项目的大矩阵分解成两个更小的用户特征和项目特征矩阵。例如,用户 A 喜欢吃热狗,但不喜欢吃比萨饼,而餐馆 P 有很棒的热狗,我们用点积乘矩阵,结果就是评分(在上面的例子中是 11)。

餐厅推荐系统

让我们开始使用上面讨论的技术建立一个餐馆推荐系统,它应该能够推荐最适合你的餐馆。

我们将使用 Yelp 餐厅数据,这些数据可以从这里下载。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Yelp 是一个商业目录服务和众包评论论坛。该公司开发、托管和营销 Yelp.com 网站和 Yelp 移动应用程序,这些应用程序发布关于企业的众包评论。它还运营一项名为 Yelp Reservations 的在线预订服务。

Yelp 试图解决这个问题“我应该吃什么?”这很快扩大到包括其他业务,以回答其他问题。这可以最好地表示为“我在[城镇]。我在哪里可以得到[最好的/最快的/最便宜的/最容易的][食物/服务/等]?”如果你没有偏好,你朋友的推荐可能对你去哪里有最大的影响。Yelp 为不可用或不可信的情况提供服务。

让我们开始构建机器学习模型

让我们从导入笔记本中需要的所有包开始。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer
from nltk.corpus import stopwords 
from nltk.tokenize import WordPunctTokenizer

现在我们导入数据集,我们使用审查数据集和业务数据集。

df = pd.read_csv('yelp_review_arizona.csv')
df_business = pd.read_csv('yelp_business.csv')
df.head()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们首先需要清理文本,我们需要删除所有的标点符号和所有的停用词(重复的我们不需要的词,如 have,do,I,you,he 等)。我们使用 nltk.corpus 中的库来查找停用词。

我们只为数据选择星星和文本,并导入我们将使用的库。

#Select only stars and text
yelp_data = df[['business_id', 'user_id', 'stars', 'text']]import string
from nltk.corpus import stopwords
stop = []
for word in stopwords.words('english'):
    s = [char for char in word if char not in string.punctuation]
    stop.append(''.join(s))

现在让我们通过创建一个函数来清理文本。

def text_process(mess):
    """
    Takes in a string of text, then performs the following:
    1\. Remove all punctuation
    2\. Remove all stopwords
    3\. Returns a list of the cleaned text
    """
    # Check characters to see if they are in punctuation
    nopunc = [char for char in mess if char not in string.punctuation]# Join the characters again to form the string.
    nopunc = ''.join(nopunc)

    # Now just remove any stopwords
    return " ".join([word for word in nopunc.split() if word.lower() not in stop])yelp_data['text'] = yelp_data['text'].apply(text_process)

为了将文本用于矩阵分解推荐系统,我们将遵循下面的架构来从评论文本中提取特征。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

User feature extraction

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Business feature extraction

对于每个用户,将所有评论组合起来形成一个段落,在我们将所有评论组合起来之后,我们应用 TFIDF 矢量器从文本中提取特征。每个餐馆都有类似的方法,我们需要给 max_feature 匹配矩阵的维数。

userid_df = yelp_data[['user_id','text']]
business_df = yelp_data[['business_id', 'text']]

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Reviews of user ‘ZwVz20be-hOZnyAbevyMyQ’

userid_df = userid_df.groupby('user_id').agg({'text': ' '.join})
business_df = business_df.groupby('business_id').agg({'text': ' '.join})

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Combined reviews of user ‘ZwVz20be-hOZnyAbevyMyQ’

现在我们应用 TFIDF 矢量器从文本中提取特征。

from sklearn.feature_extraction.text import TfidfVectorizer#userid vectorizer
userid_vectorizer = TfidfVectorizer(tokenizer = WordPunctTokenizer().tokenize, max_features=5000)
userid_vectors = userid_vectorizer.fit_transform(userid_df['text'])#Business id vectorizer
businessid_vectorizer = TfidfVectorizer(tokenizer = WordPunctTokenizer().tokenize, max_features=5000)
businessid_vectors = businessid_vectorizer.fit_transform(business_df['text'])

然后,我们用评级创建一个用户和企业矩阵。

userid_rating_matrix = pd.pivot_table(yelp_data, values='stars', index=['user_id'], columns=['business_id'])

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

潜在因素协同过滤优化

让我们回到我们使用的推荐系统的类型,这是潜在的因素协同过滤。我们已经有两个矩阵(用户特征,商业特征),我们可以相乘来预测用户给餐馆的评分。下一步,我们需要根据误差更新两个矩阵的特征值。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

The image can be found in this link

为了优化预测,我们需要使用下面的函数计算误差。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

假设 P 是用户特征矩阵,Q 是商业特征矩阵。如果我们用预测收视率(P.Q)减去实际收视率(r ),然后求平方,就得到 LSE(最小平方误差)。在餐馆评论的情况下,我们有只给 10 家餐馆评论的用户,但是我们也有给超过 200 家餐馆评论的用户。为了避免我们的模型过度拟合,我们必须将正则化添加到我们的 LSE 公式中,它将成为下面的公式。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们应用该方程来最小化误差,使用梯度下降来更新矩阵 P 和矩阵 q 中每个特征的值。

def matrix_factorization(R, P, Q, steps=25, gamma=0.001,lamda=0.02):
    for step in range(steps):
        for i in R.index:
            for j in R.columns:
                if R.loc[i,j]>0:
                    eij=R.loc[i,j]-np.dot(P.loc[i],Q.loc[j])
                    P.loc[i]=P.loc[i]+gamma*(eij*Q.loc[j]-lamda*P.loc[i])
                    Q.loc[j]=Q.loc[j]+gamma*(eij*P.loc[i]-lamda*Q.loc[j])
        e=0
        for i in R.index:
            for j in R.columns:
                if R.loc[i,j]>0:
                    e= e + pow(R.loc[i,j]-np.dot(P.loc[i],Q.loc[j]),2)+lamda*(pow(np.linalg.norm(P.loc[i]),2)+pow(np.linalg.norm(Q.loc[j]),2))
        if e<0.001:
            break

    return P,QP, Q = matrix_factorization(userid_rating_matrix, P, Q, steps=25, gamma=0.001,lamda=0.02)

现在我们已经更新了两个矩阵。是时候预测餐厅推荐了。

words = "i want to have dinner with beautiful views"
test_df= pd.DataFrame([words], columns=['text'])
test_df['text'] = test_df['text'].apply(text_process)
test_vectors = userid_vectorizer.transform(test_df['text'])
test_v_df = pd.DataFrame(test_vectors.toarray(), index=test_df.index, columns=userid_vectorizer.get_feature_names())predictItemRating=pd.DataFrame(np.dot(test_v_df.loc[0],Q.T),index=Q.index,columns=['Rating'])
topRecommendations=pd.DataFrame.sort_values(predictItemRating,['Rating'],ascending=[0])[:7]for i in topRecommendations.index:
    print(df_business[df_business['business_id']==i]['name'].iloc[0])
    print(df_business[df_business['business_id']==i]['categories'].iloc[0])
    print(str(df_business[df_business['business_id']==i]['stars'].iloc[0])+ ' '+str(df_business[df_business['business_id']==i]['review_count'].iloc[0]))
    print('')

通过输入“我想吃有美丽风景的晚餐”,模型将推荐这些餐馆。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

让我们来看看上面列出的其中一家餐馆。例如,让我们在 Yelp 中打开 Compas Arizona Grill 来查看我们的推荐系统的结果。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

它看起来像餐馆有相当美丽的景色和美丽的日落。你可以带你的配偶去那里吃一顿浪漫的晚餐(如果你有一个:D 的话)。

恭喜您创建了一个餐厅推荐系统!

要查看数据集和完整版本的代码,请访问下面的链接在 Github 中查看。

https://github . com/theo Jeremiah/Restaurant-Recommendation-System

如何使用 Scikit-Learn 构建可重用的自定义 NLP 管道

原文:https://towardsdatascience.com/how-to-build-a-reusable-nlp-code-pipeline-with-scikit-learn-with-an-emphasis-on-feature-504f8aa14699?source=collection_archive---------21-----------------------

重点是功能工程和培训

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

机器学习代码管道最重要的特征之一是可重用性。一个可重用、可共享和可扩展的管道将通过对程序流强制一致地使用直观的结构元素来确保流程和代码的完整性,并因此可以增强数据科学家的开发流程,该流程本质上是迭代的。在本文中,我将演示如何使用 scikit-learn 从头构建一个定制的机器学习代码管道,重点是以下两个组件:

  1. 特性化管道,支持灵活定义和选择特性
  2. 一个训练管道,它结合了用于后续步骤的特征化管道的输出:向量化和模型训练

这两个组件都以类似的方式利用类继承;也就是说,它们的特征在于一个底层的类结构,从这个结构中可以派生出更具体的类来解决不同种类的监督学习问题或项目需求。作为本文的一个额外收获,在第 2 节中,我将触及与继承相关的一个强大的概念,即抽象方法,并说明它如何使所提出的管道设计如此直观和易于使用。

1.特征管线

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

一个典型的 NLP 任务需要大量的特征工程,这个过程包括为训练模型准备合适的输入数据。该步骤可能需要将输入文本数据转换成单词包表示或多维向量,或者它可能涉及编写更原始的用户定义函数来提取诸如句子长度标准偏差、主要动词之前的单词数(句法复杂性的粗略度量)、可读性分数等特征的值。在任何给定的项目中,可以选择任意数量的这种特征来训练模型或首先确定特征重要性、减少维度或进行消融研究。

为了方便、控制和灵活地选择或测试特性,你可以想象有一种**“特性库”,当你需要它们的时候,你可以从中提取你(或你的队友)曾经写过的任何特性**。这个库可以表示为下面称为BaseFeaturizer的类,它的每个方法都包含计算特性值的逻辑。

一旦我们在BaseFeaturizer中定义了这些基本方法,我们就可以派生新的类来修改这些方法或者添加新的方法。但是也许**这些派生类最重要的属性是它们可以根据它们选择/引入的特性的*数量和类型而变化。***并且该信息应该在所有派生类中以一致的方式定义,即在每个派生类的 main 方法中,我将命名为**featurize**

例如,假设我们要训练一个预测文档语法复杂性的文本分类模型,将它们分为两个离散的类:“简单”和“复杂”。这项任务的两个潜在有用的语法特征是:

  1. 主要动词前的单词数:主要动词前的文本越长,该文本的语法就越复杂(可能是因为存在从句和/或主语修饰语,如从句)
  2. 可读性:可读性分数越高,越复杂。(例如,在此阅读 Flesch–Kincaid 可读性测试。)

(我在这个例子中有些随意地选择了这些特征,但是有各种各样的特征选择技术可以用来首先确定哪些特征是最有用的,并且只包括那些在最终训练中的特征。)

下面,**SyntacticComplexityFeaturizer**被定义为BaseFeaturier的子类,两个特性的值在featurize中通过调用前面在BaseFeaturizer中定义的函数来计算。这些值存储在每个文档的feature_dict中,而featurize返回整个文档集的特征值映射。

这里有一个feature_dicts的例子,在SyntacticComplexityFeaturizer的实例上调用featurize的输出。

2.培训渠道

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这个特征化管道的输出自然会作为下一个组件(训练管道)的输入。这两个管道在形式上是同构的,因为后者也包含一个基础设计(类),从该基础设计可以导出更具体的训练管道来满足不同的训练要求。我把这个类命名为BaseTrainingPipeline这个类的一个重要属性是它继承了 **ABC** (“抽象基类”的简称),原因很快就会明了。

BaseTrainingPipeline可以用您以后可能想要访问的任何属性进行初始化,例如,self.y_testself.y_preds(这些值适合存储用于评估目的),以及self.models(所有模型都基于相同的数据进行训练)。我在__init__函数中定义了以下属性:

接下来,该类的 main 方法pipeline_main包含将输入文本首先转换为数字特征,然后转换为向量所需的最少代码,这些步骤在大多数受监督的 NLP 任务中都会重复。注意,两条管道(特征化和训练)通过该方法连接,因为该方法将FeaturizerClass作为参数,例如SyntacticComplexityClass.

  1. 一旦实例化(featurizer = FeaturizerClass(),该对象将对数据(语料库)调用featurize方法,返回一个特征值映射列表(第 22–23 行)。
  2. 然后可以使用DictVectorizer(第 31–33 行)将这个列表转换成 numpy 数组或矩阵(向量)。
  3. 然后,向量X_trainy_train可用于训练任何 scikit-learn 估计器(第 39–42 行)。

为了详细说明前面的观点,**train_model**被定义为BaseTrainingPipeline的一个抽象方法(这使得它成为一个抽象类)。抽象方法可以用装饰器@abstractmethod来装饰,相关部分转载如下:

你可以在这里阅读更多关于抽象方法的内容,但简单来说:

抽象类是包含一个或多个抽象方法的类。抽象方法是声明的方法,但不包含实现。抽象类可以不被实例化,并且需要子类为抽象方法提供实现。Python 中抽象类的子类不需要实现父类的抽象方法。

train_model定义为一个抽象方法是必要的,因为它为该方法的所有实现提供了一个公共功能,这些实现由BaseTrainingPipeline的子类提供。也就是说,因为我们将train_model定义为基类的一个方法,所以我们可以从同一个类中定义的另一个方法中调用它(在我们的例子中,从pipeline_main),然而因为它的实现只能由子类提供,所以我们能够以多种不同的方式定义train_model。这些实现可能变化的一个方面是估计器类型。

为了使这一切更具体,考虑我从BaseTrainingPipeline : **ClassificationTrainingPipeline****RegressionTrainingPipeline**得到的两个示例训练管道。这种分离具有直观的意义,因为一个处理目标变量为分类/离散的分类器,而另一个处理目标变量为数值/连续的回归变量。这允许我们使用相同的通用(训练)流水线来支持不同类型的监督学习问题,而无需重写上面 **pipeline_main** **中定义的核心元素和可重复步骤的任何部分。**注意train_model的实现在两种情况下有什么不同:在ClassificationTrainingPipeline中,train_model为满足特定条件的模型指定新的参数设置,即if algorithm == "logistic_regression"(下面的第 12-19 行),覆盖初始化模型的原始设置。RegressionTrainingPipeline不包含这样的覆盖设置,尽管它肯定可能用于任何初始化的模型。

将所有这些放在一起,我们现在可以实例化这些训练管道中的一个,它将某个特征化类作为参数:

一旦我们运行了这段代码,__init__属性的值将会被更新,这样我们就可以访问保存的数组,比如y_testy_preds,以及模型本身(您可能想要保存)。此时,您可以考虑扩展培训管道,以支持其他步骤,如模型评估、指标报告和可视化。例如,您可以将如下方法添加到RegressorTrainingPipeline中,以在 heldout 数据集上进行预测,并保存每次迭代训练的指标报告:

在本文中,我介绍了构建可重用、可扩展的 ML 代码管道的一步一步的过程,该管道可以很容易地适应各种 NLP 问题。设计的两个核心组件——特征管道和训练管道——在它们的基本组织中相互反映,并且通过类继承和在某些情况下的抽象方法,它们能够(1)适应灵活的特征定义和选择,以及(2)为训练不同种类的监督模型(例如,分类对回归)提供通用支持。

2019 年 12 月更新:关于使用 scikit-learn 的Pipeline实现您的 ML 管道的替代方法,请查看以下帖子:

[## 基于 Scikit-Learn 流水线的文本特征提取

使用 2010 年初选辩论记录

towardsdatascience.com](/the-triune-pipeline-for-three-major-transformers-in-nlp-18c14e20530)

如何在 3 分钟内建立一个语义搜索引擎

原文:https://towardsdatascience.com/how-to-build-a-semantic-search-engine-in-3-minutes-9e579da92913?source=collection_archive---------17-----------------------

与标准 TF-IDF 相比,搜索相关性提高 80%

合著者 Jack Pertschuk

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

本教程是用 ElasticsearchNBoost 建立语义搜索引擎的快速指南。本指南不作为语义搜索的介绍。查看这篇文章了解背景。

在 3 分钟内设置一个神经代理来进行弹性搜索

在这个例子中,我们将在客户端和 Elasticsearch 之间设置一个代理来提高搜索结果。

使用 tensorflow 安装 NBoost

如果您想在 GPU 上运行该示例,请确保您有 tensor flow 1.14–1.15(带 CUDA)来支持建模功能。但是,如果你只是想在 CPU 上运行,就不用担心了。对于这两种情况,只需运行:

pip install nboost[tf]

设置 Elasticsearch 服务器

🔔如果你已经有一个 Elasticsearch 服务器,你可以跳过这一步!

如果你没有 Elasticsearch,不用担心!你可以使用 docker 建立一个本地的 Elasticsearch 集群。首先,通过运行以下命令获取 ES 映像:

docker pull elasticsearch:7.4.2

一旦有了图像,您就可以通过以下方式运行 Elasticsearch 服务器:

docker run -d -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.4.2

部署代理

现在我们准备好部署我们的神经代理了!做到这一点非常简单,只需运行:

nboost --uport 9200

📢*--uhost***--uport*应该和上面的 Elasticsearch 服务器一样!Uhost 和 uport 是 upstream-host 和 upstream-port(指上游服务器)的简称。*

如果你收到这个消息:Listening: <host>:<port>,那么我们可以走了!

索引一些数据

NBoost 内置了一个方便的索引工具(nboost-index)。出于演示的目的,我们将通过 NBoost 索引一组关于旅游和酒店的段落。您可以通过运行以下命令将索引添加到您的 Elasticsearch 服务器:

*travel.csv*T24 自带 NBoost

*nboost-index --file travel.csv --name travel --delim ,*

现在让我们来测试一下!点击弹性搜索:

*curl "http://localhost:8000/travel/_search?pretty&q=passage:vegas&size=2"*

如果 Elasticsearch 结果中有_nboost标签,那么恭喜它成功了!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

刚刚发生了什么?

让我们来看看 NBoost 前端。转到您的浏览器并访问 localhost:8000/nboost

如果您无法访问浏览器,您可以 *curl http://localhost:8000/nboost/status* 获取相同的信息。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

前端记录了发生的一切:

  1. NBoost 收到了对 2 个搜索结果的请求。 (0.32 毫秒)
  2. NBoost 连接到服务器。 (0.13 毫秒)
  3. NBoost 向服务器发送了 10 个搜索结果的请求。 (0.12 毫秒)
  4. NBoost 从服务器收到了 10 个搜索结果。 (120.33 毫秒)
  5. 这个模型挑选了最好的两个搜索结果。 (300 毫秒)
  6. NBoost 将搜索结果返回给客户端。 (0.10 毫秒)

如何建立一个简单的带标签的电影推荐系统

原文:https://towardsdatascience.com/how-to-build-a-simple-movie-recommender-system-with-tags-b9ab5cb3b616?source=collection_archive---------11-----------------------

基于内容的查找相似电影的方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Denise Jans on Unsplash

简介

让我们假设你正在推出下一个伟大的订阅视频点播(SVOD)流媒体服务,并且你已经获得了播放过去 100 年发行的所有主要电影的权利。祝贺这个不可思议的壮举!

现在有很多电影。如果没有某种推荐系统,你会担心用户可能会被他们不关心的电影淹没。这可能会导致客户流失,这是你最不想看到的!

所以你决定建立一个电影推荐系统。因为你的服务是新的,你还没有足够的数据说明哪些用户在看什么电影。这就是所谓的冷启动问题,它阻止你仅仅基于用户的历史收视率来推荐电影。

幸运的是,即使没有足够的收视率数据,我们仍然可以用电影元数据构建一个不错的推荐系统。这就是电影镜头的用武之地。MovieLens 为每部电影提供了一个带有关键字标签的公共数据集。这些标签信息丰富。例如,查看下面的顶级社区标签,寻找善意

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Screenshot taken from the MovieLens website

在这篇文章的剩余部分,我将回答三个商业问题,这三个问题对于使用 MovieLens 的标签构建一个简单的基于内容的推荐系统至关重要:

  1. 每部电影我们需要多少个标签?
  2. 我们如何用标签来衡量电影之间的相似度?
  3. 我们如何使用标签为用户生成电影推荐?

摘自维基百科关于基于内容的推荐系统的页面:

基于内容的过滤方法是基于对项目的描述和用户偏好的描述。这些方法最适合于已知项目数据(名称、位置、描述等)的情况。),但不在用户身上。基于内容的推荐器将推荐视为特定于用户的分类问题,并根据产品特征学习用户喜欢和不喜欢的分类器。”

这种分析的代码可以在这里与数据和康达环境 YAML 文件一起找到,便于您轻松重现结果。

1)每部电影我们需要多少个标签?

在 MovieLens 标签基因组数据集中有大约 10K 独特的电影和 1K 独特的标签。每部电影的每个标签都有一个相关性分数,因此大约有 1000 万个电影标签对。相关性分数的范围是从 0 到 1。

不是每个标签都与电影相关,所以我们只需要保留最相关的标签。首先,我们可以根据相关性分数对每部电影的标签进行排序。例如,在的前 10 个标签下面,记住泰坦。请注意,相关性分数远高于 0.9,这表明它们是非常相关的标签。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Top 10 tags based on relevance score (descending order)

接下来,我们在下面的图表中确认,电影的排名较高的标签往往具有较高的中值相关性分数。电影中排名第一的标签具有几乎为 1 的中值相关性分数。我们可以看到,随着我们下降到第 50 位,中值相关性分数逐渐降低。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

为了找到与电影最相关的标签,我们可以根据相关性分数保留电影的前 N 个标签。在这里,我们需要仔细挑选 N 。如果 N 很小,我们有非常相关但很少的标签。如果 N 很大,我们有很多标签,但其中很多可能是不相关的。

下图显示了从排名第 1 位到第 100 位的标签,中值相关性分数的百分比变化。当相关性分数开始变得更加稳定时,我们在第 50 个排名附近看到一个拐点。因此,我们可以选择 N = 50 作为为每部电影保留的标签的合理数量。请注意,这是一个非常简单的“肘方法”风格的方法,可以在以后进行优化。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在,我们可以获得每部电影的前 50 个标签的列表,我们将在下一节中使用。例如,在玩具总动员的前 50 个标签下面。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2)我们如何用标签来衡量电影之间的相似度?

在为用户生成电影推荐之前,我们需要一种方法来根据电影的前 50 个标签来衡量电影之间的相似性。在基于内容的推荐系统中,用户将被推荐与他们已经看过的电影相似的电影。

在这里,我将演示两种度量相似性的方法:

  1. 两套电影标签的 Jaccard 索引
  2. 基于标签的电影向量(又名内容嵌入)的余弦相似度

Jaccard 指数

使用 Jaccard 指数的第一种方法测量两个集合 AB 之间的相似性,即交集的大小除以并集的大小。当测量电影之间的相似性时,我们可以为两组电影标签计算这个指数。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Taken from wikipedia

例如,假设我们有以下三部电影及其前三个标签:

  • 电影 A 标签=(动作、空间、友情)
  • 电影 B 标签=(冒险、太空、友谊)
  • 电影 C 标签=(浪漫、喜剧、成人)

直观上,我们可以看到电影 AC更类似于 B 这是因为电影 AB 共享两个标签(空间,友谊),而电影 AC 不共享任何标签**。**

根据 Jaccard 指数,以下 10 部电影类似于《心灵捕手》。对于有良好意愿的观众来说,这些看起来是合理的建议。请注意,我在列表中包括了《心灵捕手》,以表明在比较电影本身时,Jaccard 指数= 1。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Movies similar to Good Will Hunting based on Jaccard Index of tag sets

以下是基于 Jaccard 指数的类似于星际的前 10 部电影。对于《星际穿越》的观众来说,这些看起来也是合理的推荐。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Movies similar to Interstellar based on Jaccard Index of tag sets

为了进一步说明 Jaccard 索引的有效性,请参见下面基于类似于《星际穿越》的电影的标签频率的词云。在这里,我们可以看到哪些标签在相似度计算中更突出(例如,科幻小说、伟大的结局、反主题未来、哲学、大脑)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Word cloud based on tag frequency from movies similar to Interstellar

电影向量的余弦相似度(又名内容嵌入)

Jaccard Index 的第一种方法帮助我们建立了一种直觉,即与标签相似意味着什么。余弦相似度的第二种方法有点复杂。它要求我们把我们的电影表现为一个向量。在这里,向量只是一组数字。

例如,我们可以将之前的相同电影表示为一组三个实数:

  • 电影 A = (1.1,2.3,5.1)
  • 电影 B = (1.3,2.1,4.9)
  • 电影 C = (5.1,6.2,1.1)

直观地,我们可以再次看到电影 Ac更类似于 B 这是因为电影 AB 在每个维度上具有更接近的数字(例如在第一维度上 1.1 比 1.3)。

为了找到一个好的电影矢量表示,我使用了这篇论文中的 Doc2Vec (PV-DBOW)技术,它获取一部电影(文档)并根据其标签(文档中的单词)学习到潜在的 K 维矢量空间的映射。这里我就不细说了,但是这就是我们如何把电影表示成一个基于标签的向量。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Visual of the PV-DBOW technique from the Doc2Vec paper; for each paragraph ID (movie) we’re training a model to predict the occurrence of a word (movie tag) in that paragraph

一旦我们可以将每部电影表示为一个向量,我们就可以计算向量之间的余弦相似度,以找到相似的电影。我不会在这里深入讨论余弦相似度的细节,但是在高层次上,它告诉我们电影向量彼此有多相似,我们可以用它来生成推荐。

下面我用 UMAP 可视化 2D 的电影向量,这是一种流行的非线性降维技术。我们可以看到,在这个向量空间中靠得更近的电影更相似(例如《玩具总动员》和《怪物公司》)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Movie vectors learned from corpus of movie tags

3)我们如何使用标签为用户生成电影推荐?

现在我们可以用标签来衡量电影之间的相似性,我们可以开始向用户推荐电影。

记住,在基于内容的推荐系统中,用户会被推荐与他们已经看过的电影相似的电影。如果用户只看过一部电影(例如《心灵捕手》),我们可以像以前一样简单地使用 Jaccard 索引(或余弦相似度)来生成相似电影的列表进行推荐。

更实际的情况是,用户已经观看了一系列电影,我们需要根据这些电影的综合属性来生成推荐。

一个简单的方法是计算用户向量,作为他们看过的电影向量的平均值。这些用户向量可以表示用户的电影偏好简档。

例如,如果用户只看过下面的电影 AB :

  • 电影 A = (1,2,3)
  • 电影 B = (7,2,1)
  • 用户向量=电影 AB 的平均值= (4,2,2)

以下是我喜欢看的电影。我们如何使用这些电影的标签来生成电影推荐?

《星际穿越》、《心灵捕手》、《差点成名》、《肖申克的救赎》、《明日边缘》、《杰里·马奎尔》、《阿甘正传》、《回到未来》

我的用户向量是上面九部电影的平均向量。我可以拿我的用户向量,找到最相似的我还没看过的电影(基于余弦相似度)。以下是我的电影推荐,考虑到我们这里只使用电影标签,这些推荐出奇的好!请随意使用笔记本,并生成您自己的建议。

The Theory of Everything
Cast Away
Dead Poets Society
Charly
Rain Man
Groundhog Day
Pay It Forward
A Beautiful Mind
E.T. the Extra-Terrestrial
Mr. Holland's Opus
On Golden Pond
It's a Wonderful Life
Children of a Lesser God
The Curious Case of Benjamin Button
Star Trek II: The Wrath of Khan
Cinema Paradiso
Mr. Smith Goes to Washington
The Terminal
Her
The World's Fastest Indian
The Truman Show
Star Trek: First Contact
The Family Man

下面总结了我们的基于内容的推荐系统。请注意,如果我们将系统部署为 API,我们可以在批处理过程中预先计算用户向量和相似性得分,以加快推荐服务的速度。

  • **输入:**用户向量(从标签学习的电影向量的平均值)
  • **输出:**基于用户和电影向量的余弦相似度,列出与用户相似的电影

如何用 Python 从头开始构建一个简单的神经网络

原文:https://towardsdatascience.com/how-to-build-a-simple-neural-network-from-scratch-with-python-9f011896d2f3?source=collection_archive---------10-----------------------

不使用框架建立神经网络的快速指南。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Franck V. on Unsplash

神经网络每天都变得越来越受欢迎,作为机器学习和人工智能的核心领域,它们将在未来几年在技术、科学和工业中发挥重要作用。这种高受欢迎程度已经产生了许多框架,允许您非常容易地实现神经网络,而无需了解它们背后的完整理论。另一方面,神经网络机制的严格理论解释需要一些高级数学知识。

在这篇文章中,我们将做一些介于。具体来说, 为了更扎实地理解神经网络, 我们将从头开始实际实现一个 NN,不使用任何框架但为了简单起见我们将省略证明这可能比使用框架更难,但是你会对算法背后的机制有更好的理解。当然,在大型项目中,框架实现是首选,因为它更容易和更快地建立。

本教程中使用的工具只是带有 numpy 库(线性代数运算的科学库)的 Python。假设您已经安装了 python 和 pip,您可以通过运行以下命令来安装 numpy:

*pip install numpy*

神经网络实际上是许多变量的函数:它接受输入,进行计算并产生输出。我们喜欢把它想象成不同层中的神经元,一层中的每个神经元都与上一层和下一层中的所有神经元相连。所有的计算都发生在这些神经元内部,并且依赖于将神经元相互连接起来的权重。因此,我们所要做的就是学习正确的权重,以获得期望的输出。

*它们的结构通常非常复杂,包括许多层,甚至超过一百万层(*2020 年 12 月更新:GPT-3 现在使用 175 个参数!)神经元为了能够处理我们这个时代的大数据集。然而,为了理解大型深度神经网络如何工作,应该从最简单的开始。

因此,下面我们将实现一个非常简单的两层网络。为了做到这一点,我们还需要一个非常简单的数据集,因此我们将在示例中使用 XOR 数据集,如下所示。A 和 B 是 NN 的 2 个输入,AXORB是输出。我们将尝试让我们的 NN 学习权重,这样无论它接受哪一对 A 和 B 作为输入,它都将返回相应的结果。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

The XOR truth table

所以,我们开始吧!

首先,我们需要定义我们的神经网络的结构。因为我们的数据集相对简单,所以只有一个隐藏层的网络就可以了。所以我们会有一个输入层,一个隐藏层和一个输出层。接下来,我们需要一个激活函数。sigmoid 函数是最后一层的好选择,因为它输出 0 到 1 之间的值,而 tanh(双曲正切)在隐藏层中效果更好,但其他所有常用函数也可以(例如 ReLU)。所以我们的神经网络结构看起来会像这样:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这里,要学习的参数是权重 W1、W2 和偏差 b1、b2。正如你所看到的,W1 和 b1 连接输入层和隐藏层,而 W2,b2 连接隐藏层和输出层。根据基本理论,我们知道激活 A1 和 A2 计算如下:

*A1 = h(W1*X + b1)
A2 = g(W2*A1 + b2)*

其中 g 和 h 是我们选择的两个激活函数(对于 us sigmoid 和 tanh ), W1、W1、b1、b2 通常是矩阵。

现在让我们进入实际的代码。代码风格总体上遵循了吴恩达教授在本次课程中提出的指导方针。

***注意:*你可以在我的知识库这里找到完整的工作代码

首先,我们将实现我们的 sigmoid 激活函数,定义如下: g(z) = 1/(1+e^(-z)) 其中 z 通常是一个矩阵。幸运的是 numpy 支持矩阵计算,所以代码相对简单:

Sigmoid implementation

接下来,我们必须初始化我们的参数。权重矩阵 W1 和 W2 将从正态分布随机初始化,而偏差 b1 和 b2 将被初始化为零。函数 initialize_parameters(n_x,n_h,n_y)将 3 层中每一层的单元数作为输入,并正确初始化参数:

Parameters initialization

下一步是实现向前传播。函数 forward_prop(X,parameters)将神经网络输入矩阵 X 和参数字典作为输入,并返回 NN A2 的输出以及稍后将在反向传播中使用的缓存字典。

Forward Propagation

我们现在必须计算损失函数。我们将使用交叉熵损失函数。Calculate_cost(A2,Y)将 NN A2 和基本事实矩阵 Y 的结果作为输入,并返回交叉熵成本:

Cost Calculation

现在是神经网络算法中最难的部分,反向传播。这里的代码可能看起来有点奇怪和难以理解,但我们不会深入研究它为什么在这里工作的细节。该函数将返回损失函数相对于我们的网络的 4 个参数(W1,W2,b1,b2)的梯度:

Backward Propagation

很好,现在我们有了损失函数的所有梯度,所以我们可以进行实际的学习了!我们将使用梯度下降算法来更新我们的参数,并使我们的模型以作为参数传递的学习率进行学习:

Gradient Descent Algorithm

到目前为止,我们已经实现了一轮培训所需的所有功能。现在,我们所要做的就是将它们放在一个名为 model()的函数中,并从主程序中调用 model()。

Model()函数将特征矩阵 X、标签矩阵 Y、单元数量 n_x、n_h、n_y、我们希望梯度下降算法运行的迭代次数以及梯度下降的学习速率作为输入,并组合上述所有函数以返回我们的模型的训练参数:

Model function that combines all the above functions.

训练部分现在结束了。上面的函数将返回我们的神经网络的训练参数。现在我们只需要做出我们的预测*。函数 predict(X,parameters)将矩阵 X 作为输入,该矩阵 X 具有我们想要为其计算 XOR 函数的 2 个数字和模型的训练参数,并通过使用阈值 0.5 返回期望的结果 y_predict:*

Prediction function

我们最终完成了所有需要的功能。现在让我们进入主程序,声明我们的矩阵 X,Y 和超参数 n_x,n_h,n_y,num_of_iters,learning_rate:

Main program: Initialization of variables and hyperparameters

设置好以上所有内容后,在上面训练模型就像调用下面这行代码一样简单:

Learn the parameters using the model() function

最后,让我们预测一对随机的数字,比如说(1,1):

Make a prediction with A=1, B=1 using the learned parameters

那是真正的代码!让我们看看我们的结果。如果我们用这个命令运行我们的文件,比如说 xor_nn.py

*python xor_nn.py*

我们得到下面的结果,因为 1XOR1=0,所以这个结果确实是正确的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Result of our NN prediction for A=1 and B=1

就是这样!我们只用 Python 从头开始训练了一个神经网络。

当然,为了训练具有许多层和隐藏单元的较大网络,您可能需要使用上述算法的一些变体,例如,您可能需要使用批量梯度下降而不是梯度下降,或者使用更多的层,但是简单 NN 的主要思想如上所述。

您可以随意使用超参数,尝试不同的神经网络架构。例如,您可以尝试更少的迭代次数,因为成本似乎下降得很快,1000 次迭代可能有点大。记住你可以在我的 GitLab 库这里找到完整的工作代码。

感谢的阅读,我很乐意讨论您可能有的任何问题或纠正:)如果您想谈论机器学习或其他任何事情,请在 LinkedIn 或我的网页上找到我。

如何使用决策树构建垃圾邮件分类器

原文:https://towardsdatascience.com/how-to-build-a-spam-classifier-using-decision-tree-b75d0c7f25e?source=collection_archive---------13-----------------------

机器学习:监督学习

越简单的模型越好!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

NASA/JPL/Cornell University, Maas Digital LLC

“像鸭子一样走路,像鸭子一样游泳,像鸭子一样嘎嘎叫,大概,它是一只鸭子!”

数据科学投诉

在监督学习领域,有大量的分类器,包括逻辑回归( logit 101logit 102 )、LDA、朴素贝叶斯、SVM、、KNN 、随机森林、神经网络,每天都有更多的分类器出现!

所有数据科学家都应该问自己的真正问题是:

我们是否选择了正确的方法?

或者,

我们选的是花式模特吗?

关于 5 个最流行的 ML 分类器的快速比较和分步说明,请参考我的另一篇 帖子 :

[## 脖子上的痛:使用 5 种机器学习方法预测罕见事件

哪一种最适合不平衡数据?有什么权衡吗?

towardsdatascience.com](/classifying-rare-events-using-five-machine-learning-techniques-fab464573233)

如下面这条推文所示,

一个简单的回归就够了,建立 10 层深度学习模型还有什么意义?

让我们面对现实吧。我们,数据科学家,有时可能是以自我为中心的毒枭,更关心炫耀技能,而不听取客户的需求。

无论是面向内部的 DS 角色(例如人员分析)还是面向外部的 DS 角色(例如统计顾问),他们都需要提供非技术同事和客户能够立即理解和应用的快速解决方案。请不要将它们与 DS 术语、行话、系数解释或任何其他不必要的麻烦混淆。如果 ML 模型太难而没有用,那绝对没有附加值。

考虑到这一点,我们在这篇文章中学习如何使用可解释的 ML 分类器决策树来构建一个简单的垃圾邮件分类器(UCI 机器学习数据库托管数据集,可以在这里访问)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

AndyPandy from Pixabay

决策图表

决策树是一种监督学习方法,它将结果空间分割成 J 个区域 R(1),R(2),…,R(J),并预测每个区域 R 的响应

使用递归二进制分裂,我们通过四个简单的步骤构建 DT 模型:

  1. 基于变量 X(i)分割区域 R(j)
  2. 设置截止点 s,并将 R(j)分成两个区域,如果
  • {X|X(i)
  • {X|X(i)> s} = R(类别 2)

3.对下一个区域重复前两步

4.继续下去,直到我们用完了所有可用的单元,或者每个叶节点中只剩下少量的单元。

用日常俗人的话来说,DT 就是找到空间的最佳分割方式,让空间在每次分割后变得“更纯粹”。有三种方法可以测量空间的纯净度或不纯净度:

  1. 分类错误率

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2。基尼指数

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3。熵

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如何选择最佳分割?

  1. 对于区域 j,计算先前杂质 **I(分割前)**和变量 **I(分割后)**的分割后杂质。
  2. 选择导致 **I(分割前)**和 I(分割后)之间最大减少的变量 v。

理想情况下,完美的 ML 分类器会一直分裂,直到每个单元都有自己的叶子,也就是 aka。然而,这导致过拟合,这使得它不太适合其他数据集。简单地说,过度拟合意味着我们将 ML 模型与我们正在使用的数据集拟合得太紧,如果我们想推广到其他情况,这就不太实际了。

为了解决这个问题,我们需要修剪模型,并在算法每次想要进行另一次分割时设置惩罚。

修剪减少了总的错误分类错误,同时保持较小的树。它可以表示如下:

成本=总误分类误差+ αJ

  • α:调谐参数
  • αJ:惩罚项

顺便提一下,这是构建损失函数的一种非常常见的形式,你可能会在其他场景中看到。

r 实现

1.r 包、库和加载数据

library(tidyverse)
library(dplyr)
library(tree)
library(maptree)spam <- read_table2("spambase.tab", guess_max=2000)
spam <- spam %>%
  mutate(y = factor(y, levels=c(0,1), labels=c("good","spam"))) %>%
  mutate_at(.vars=vars(-y), .funs=scale)colnames(spam)

2.数据分割:训练和测试

#set.seed() for version control
set.seed(1)#sample the dataset
test.indices = sample(1:nrow(spam), 1000) #create train and test sets
spam.train=spam[-test.indices,]
spam.test=spam[test.indices,]
YTrain = spam.train$y
XTrain = spam.train %>% select(-y)
YTest = spam.test$y
XTest = spam.test %>% select(-y)

接下来,我们使用 10 重交叉验证。关于简历的 6 步总结,请参考我的另一篇帖子( KNN )。

nfold = 10
set.seed(1)
folds = seq.int(nrow(spam.train)) %>% # sequential observations IDs
  cut(breaks = nfold, labels=FALSE) %>% # sequential fold IDs
  sample

让我们创建一个函数 calc_error_rate 来计算分类误差。

calc_error_rate <- function(predicted.value, true.value){
  return(mean(true.value!=predicted.value)) 
}

有趣的部分来了:构建一个简单的 DT 模型。

# the number = the row numbers of the spam.train 
nobs = nrow(spam.train)# a DT model
# please check the official R documents for the parameters
spamtree = tree(y~., data= spam.train,
     na.action = na.pass, 
     control = tree.control(nobs, mincut =2, minsize = 5, mindev = 1e-5))
summary(spamtree)# plot the original unpruned DT model
draw.tree(prune, nodeinfo=TRUE)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 1

通常情况下,我们不绘制未修剪的 DT 模型,因为有太多的叶片难以解释。这是个坏例子!我这么做是出于教学原因。

3.修剪

为了让情节更漂亮,更简单,更容易理解,让我们把 DT 模型剪成只剩下 8 片叶子。

prune =prune.tree(spamtree, best=8)
summary(prune) # plot the pruned model
draw.tree(prune, nodeinfo=TRUE)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 2

与之前的填充图相比,图 2 在各方面都要好得多。我们知道最重要的变量是什么。我们知道每个类别中有多少观察值。

此外,我们可以使用交叉验证来寻找最佳的修剪次数。幸运的是,包包括一个默认的 CV 函数, cv.tree ,以最小化错误分类率。

set.seed(3)
cv = cv.tree(spamtree,FUN=prune.misclass, K=10)
cv

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

plot(cv$size,cv$dev)
abline(v=37,lty=1)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 3

最佳分裂数为 37。我们根据树的大小绘制错误分类图。设置叶子的数量= 37,我们建立一个新的树模型叫做 spamtree.pruned

spamtree.pruned<-prune.misclass(spamtree, best=37)
summary(spamtree.pruned)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

# training and test errors of spamtree.pruned
# **set type = "class"** because we are predicting the categorypred.train = predict(spamtree.pruned, spam.train, **type=”class”**)
pred.test = predict(spamtree.pruned, spam.test, **type=”class”**)# training error
DT_training_error <- calc_error_rate(predicted.value=pred.train, true.value=YTrain)
DT_training_error[1] 0.05165232# test error
DT_test_error <- calc_error_rate(predicted.value=pred.test, true.value=YTest)
DT_test_error[1] 0.072

仅此而已!伙计们,我们已经通过 3 个简单的步骤学会了一个超级简单但有用的 ML 分类器。

在这篇文章中,我们已经了解了什么是 DT,它的优点和 R 实现。以下是一些关键要点:

  • 行业需要快速简单的解决方案。
  • 决策树快速、简单且有用。
  • DT 是可视化的,可解释的。

喜欢读这本书吗?

如果有,请查看我其他关于机器学习和编程的帖子。

~~ [## R 中 K-最近邻初学者指南:从零到英雄

使用各种度量标准在 R 中构建 KNN 模型的管道

towardsdatascience.com](/beginners-guide-to-k-nearest-neighbors-in-r-from-zero-to-hero-d92cd4074bdb) [## 机器学习 101:使用逻辑回归预测 R

基础、链接功能和图

towardsdatascience.com](/machine-learning-101-predicting-drug-use-using-logistic-regression-in-r-769be90eb03d)

LinkedInTwitter 找到我。~~

如何用 Python 构建语音识别机器人

原文:https://towardsdatascience.com/how-to-build-a-speech-recognition-bot-with-python-81d0fe3cea9a?source=collection_archive---------2-----------------------

即使你对语音识别一无所知

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

你现在可能意识到了什么。

像亚马逊 Alexa 这样的语音产品的巨大成功已经证明,在可预见的未来,某种程度的语音支持将是家用技术的一个重要方面。

换句话说,支持语音的产品将会改变游戏规则,因为它提供的交互性和可访问性是很少有技术可以比拟的。

不需要 GUI。

不需要发短信。

不需要表情符号。

都是关于 速度

速度是语音成为下一个主要用户界面的一个重要原因。每十年,我们都拥抱一种与技术互动的新方式。我们已经从字符模式发展到图形用户界面、网络和移动设备。

现在,语音提供了一种比移动应用更快捷、更简单的沟通和完成任务的方式。

我们可以告诉 Alexa 我们需要什么(关灯、调节恒温器、设置闹钟——或者使用像“Alexa,晚安”这样的单一话语来完成以上所有事情),或者你可以拔出你的手机,解锁它,打开正确的应用程序,并执行一项或多项任务。

当您考虑习惯性用例时,即那些让客户不断回头的用例,通过语音获得的效率会随着时间的推移而增加。

“由于 Alexa,短信在未来将会下降”

—加里·维纳查克

Gary Vaynerchuk: Voice Lets Us Say More Faster

因此,这让我对着手一个新项目非常感兴趣,用 Python 构建一个简单的语音识别。

当然,我不会从头开始构建代码,因为这需要大量的训练数据和计算资源来使语音识别模型以一种体面的方式准确无误。

相反,我使用了 Google 语音识别 API 来执行 Python 的语音转文本任务(查看下面的演示,我向您展示了语音识别是如何工作的——现场!).

在本文结束时,我希望您能更好地理解语音识别的一般工作原理,最重要的是,如何使用 Google 语音识别 API 和 Python 来实现它。

相信我。就这么简单。

如果你感兴趣的话,可以在这里查看源代码。

我们开始吧!

为什么使用谷歌语音识别 API?

您可能想知道,“鉴于语音识别日益增长的需求和流行,这是唯一可用的 API 吗?”

答案是,还有其他免费或付费的 API,如下所示:

最后,我从speecher recognition库中选择了 Google Web Speech API ,因为它有一个默认的 API 密匙,这个密匙是硬编码到 speecher recognition 库中的。

这意味着您可以立即开始,而不必使用 API 密钥或其他 API 的用户名/密码组合进行身份验证。

但是 Google Web Speech API 的便利性也带有一定的局限性:自己键的 API 配额是每天 50 个请求,目前没有办法提高这个限制。

如果我们只是想将这个 API 用于实验目的,这符合我们的用例。请注意,如果您运行的应用程序或网站一直在调用 API,那么您可能需要考虑从上面的任何一个 API 获取付费服务。

使用 Google 语音识别 API 用 Python 构建语音识别

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

(Source)

为了避免让您对语音识别如何工作的技术细节感到厌烦,您可以阅读这篇很棒的文章,它讨论了一般的机制以及如何实现 API

在接下来的文章中,我将向您展示我是如何按照本文一步一步地实现这个 API 的。

但是首先你需要使用pip install SpeechRecognition安装speecher recognition库。

我们可以使用来自这个库本身的 Google Web Speech API。

在这个实现中,我使用自己的麦克风录制了我的语音,SpeechRecognizer 访问了麦克风(安装 PyAudio 包 以访问麦克风)并相应地识别了我的语音。

查看下面的代码片段来理解完整的实现,因为它们相对来说是不言自明的。

Function to recognize speech from microphone

为了处理环境噪声,您需要使用Recognizer类的adjust_for_ambient_noise()方法,以便库能够识别您的声音。

运行adjust_for_ambient_noise()方法后,等待一秒钟,让它分析收集的音频源,以处理环境噪声并捕捉正确的语音。

最后,我们需要实现try and except块来处理错误,比如在发送请求后 API 不可达或没有响应,或者我们的语音无法识别。

要使用上面的函数,您只需实现下面的块,然后…瞧!你做到了!😃

使用谷歌语音识别 API 的简单演示

既然我们已经准备好了完整的实现代码。是时候看看这东西是怎么运作的了。

我录制了一个简短的视频,向您展示 API 是如何从录制我的声音到以文本格式返回它的。

虽然这可能看起来不像我们预期的那样准确,但这绝对值得花时间来研究代码和 API!

最后的想法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

(Source)

感谢您的阅读。

我希望您现在对语音识别的一般工作原理有了更好的理解,最重要的是,如何通过 Python 使用 Google 语音识别 API 来实现它。

如果你有兴趣,可以在这里查看源代码。

我还建议您尝试其他 API 来比较语音到文本的准确性。

尽管现阶段支持语音的产品尚未在企业和我们的日常生活中广泛使用,但我真的相信这项技术迟早会颠覆许多企业以及消费者使用语音识别功能产品的方式。

一如既往,如果您有任何问题或意见,请随时在下面留下您的反馈,或者您可以随时通过 LinkedIn 联系我。在那之前,下一篇文章再见!😄

关于作者

阿德蒙德·李 目前是东南亚排名第一的商业银行 API 平台 Staq 的联合创始人/首席技术官。

想要获得免费的每周数据科学和创业见解吗?

你可以在 LinkedInMediumTwitter脸书上和他联系。

**** [## 阿德蒙德·李

让每个人都能接触到数据科学。Admond 正在通过先进的社交分析和机器学习,利用可操作的见解帮助公司和数字营销机构实现营销投资回报。

www.admondlee.com](https://www.admondlee.com/)****

如何用 Python 构建一个简单的时间序列仪表板,包括面板、Altair 和一个 Jupyter 笔记本

原文:https://towardsdatascience.com/how-to-build-a-time-series-dashboard-in-python-with-panel-altair-and-a-jupyter-notebook-c0ed40f02289?source=collection_archive---------3-----------------------

两个过滤器+一个交互式面积图,大约 25 行代码。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我使用 Altair 已经一年多了,它已经很快成为我在 Python 中的首选图表库。我喜欢剧情的内置交互性,以及语法建立在图形的语法之上的事实。

Altair 甚至通过使用 Vega 小部件提供了一些内置的交互性。然而,我发现这有时是有限制的,它不允许我像创建仪表板那样创建布局。

然后我找到了面板。Panel 自称为“Python 的高级应用和仪表板解决方案”,它是由 Anaconda 管理的 HoloViz 生态系统的一部分。我以前听说过 HoloViz(这是一个相对概述网站,PyViz,但从来没有真正花时间深入了解这个景观。所以我们开始吧!

乍一看,我喜欢 Panel 的地方在于它与绘图库无关——它支持几乎所有的可视化库。所以在这篇文章中,你不必成为一个忠实的 Altair 用户来学习一些关于制作仪表板的知识。也就是说,与 Panel 示例库中的其他代码示例相比,我认为与 Altair 的集成非常直观。

以下是 Panel 的其他一些非常好的地方:

  • 反应式(自动更新!)
  • 这是声明性的(可读代码)
  • 支持不同布局(灵活)
  • 完全可部署到服务器(可共享)
  • Jupyter 笔记本兼容(但不依赖……不过牛郎星依赖 Jupyter。所以我不建议在别的地方尝试这个教程。)

让我们用面板制作一个仪表板

下面是我们将要构建的:最简单的小仪表板,由一个面积图和两个过滤器组成。我们还将添加一个标题和副标题。所有这些都在 Jupyter 笔记本里。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

The dashboard!

本教程将把代码分成几个块,一点一点地浏览,但是如果你只想深入完整的代码(带注释),Github repo 在这里是。

现在是代码!

首先,像往常一样,导入那些依赖库。这是你需要的:

import panel as pn
import altair as alt
from altair import datum
import pandas as pd
from vega_datasets import data
import datetime as dt

8 月 27 日更新:请确保您的 Altair 包是版本 3.2 或以上,否则您会得到一些数据格式错误。

然后我们需要添加两行特殊的代码,一行用于 Altair,一行用于 Panel。第一个命令告诉 Altair 将 Vega-Lite 渲染到 Jupyter Notebook(如果您使用 Jupyter Lab,请查看 Altair 文档以获得替代方法)。第二行告诉 Panel 接受 Vega(它支持 Altair)作为扩展。您可以在面板文档的组件部分了解更多关于扩展如何工作的信息。

alt.renderers.enable(‘default’)
pn.extension(‘vega’)

由于我们使用了来自 vega_datasets 包的一些样本数据,让我们预览一下我们的数据框架。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

the “stocks” dataframe from vega_datasets

现在有趣的部分是:让我们做一些部件!我们将制作一个下拉列表和一个日期范围滑块来过滤我们的数据。

dropdown 小部件有两个参数:小部件的标题和“选项”。

# create list of company names (tickers) to use as options
tickers = [‘AAPL’, ‘GOOG’, ‘IBM’, ‘MSFT’]# this creates the dropdown widget
ticker = pn.widgets.Select(name=’Company’, options=tickers)

然后我们将创建日期范围滑块。您可以使用相同的 pn.widgets 方法来访问它。范围滑块有四个参数:开始日期、结束日期、默认开始日期和默认结束日期。

# this creates the date range slider
date_range_slider = pn.widgets.DateRangeSlider(
name=’Date Range Slider’,
start=dt.datetime(2001, 1, 1), end=dt.datetime(2010, 1, 1),
value=(dt.datetime(2001, 1, 1), dt.datetime(2010, 1, 1))
)

小部件完成!现在,让我们添加一个标题和副标题,这样其他人就可以清楚这个仪表板是关于什么的了。面板使用 Markdown,因此很容易指定标题。

title = ‘### Stock Price Dashboard’subtitle = ‘This dashboard allows you to select a company and date range to see stock prices.’

注意,此时我们只是在用声明变量。什么都没建。但是现在,我们开始进入仪表板建设的东西。

要创建一个反应式仪表板,我们需要告诉我们的面板对象“依赖”什么。这有效地告诉 Panel 监听小部件中的变化,然后重新加载图表。这一行将作为函数的装饰:在我们的get_plot()函数中使用ticker.param.valuedate_range_slider.param.value,特别是 Altair 位来操作图表。

@pn.depends(ticker.param.value, date_range_slider.param.value)

我们是被动的。现在是时候在这条线的正下方创建图了。让我们写一个函数来完成所有的绘制工作。这将包含所有的数据整形/操作以及创建牛郎星图表的代码。我们将使用注释将这段代码分成三个部分:1)格式化数据,2)创建 pandas 过滤器,3)创建 Altair 对象。

def get_plot(ticker, date_range): # Load and format the data
     df = source # define df
     df[‘date’] = pd.to_datetime(df[‘date’]) # create date filter using values from the range slider
     # store the first and last date range slider value in a var
     start_date = date_range_slider.value[0] 
     end_date = date_range_slider.value[1]     # create filter mask for the dataframe
     mask = (df[‘date’] > start_date) & (df[‘date’] <= end_date)
     df = df.loc[mask] # filter the dataframe # create the Altair chart object
     chart = alt.Chart(df).mark_line().encode(x=’date’, y=‘price’,      tooltip=alt.Tooltip([‘date’,’price’])).transform_filter(
(datum.symbol == ticker) # this ties in the filter 
) return chart

快到了!现在我们需要创建最终的面板对象。面板对象可以由行和列组成。由于这是一个简单的小仪表板,我们将只使用两列。

首先,我们创建单行。然后,我们用两列的内容填充它。我们的第一列将包含 1)标题,2)副标题,3)下拉框和 4)日期滑块。第二列将显示图表。

dashboard = pn.Row(pn.Column(title, subtitle, ticker, date_range_slider),
get_plot # our draw chart function!
)

我们完事了。只需调用您的 dashboard 变量,就可以看到您的小应用程序的所有优点。

部署您的仪表板

Panel 的另一个很酷的地方是它能够通过散景服务器部署应用。现在,我们将简单地使用我们的仪表板,并将其添加为 Bokeh 的“可服务”本地应用程序,以便我们可以测试我们的仪表板功能。有关部署的所有细节,请查看广泛的部署和导出面板页面和运行散景服务器的上的散景文档。

添加这行代码:

dashboard.servable()

将使您的仪表板可被散景服务器发现。现在我们需要弹出到命令行来启动我们的服务器。运行以下代码以本地主机身份启动您的服务器。“— show”命令只是告诉 Bokeh 在服务器准备就绪时,在浏览器中弹出一个新标签,显示您的应用程序。您可以将这一行复制/粘贴到终端中:

panel serve --show panel-altair-demo.ipynb

就在那里!我们的小股票价格应用程序。当然,这是使用标准的演示数据集。但是,希望您可以开始看到如何插入数据集并创建更有用的应用程序。将数据框的三列简单地视为占位符:

  • 符号→ <你的分类变量>
  • 日期→ <您的日期和/或时间>
  • 价格→ <你的价值观>

更好的是,您可以创建一个包含多个图表的仪表板。这一切都离不开你舒适的 Jupyter 笔记本。

我迫不及待地深入 Panel,开始制作更复杂的仪表盘、快速原型、内部工具等。编码快乐!

喜欢吗?还有更多。《数据好奇》是一份每周时事通讯,分享像这样的很酷的教程,还有有趣的数据文章可以阅读,数据集可以分析,数据可以激发灵感。在这里报名

面板文档中有一个 奇妙图库的示例 来帮助您入门,所以请直接查看还有哪些可能。本教程在很大程度上依赖于 牛郎星示例 ,但我已经修改了代码,我觉得这是一个更干净的版本,应该有助于适应不同的数据集和图表类型。我还添加了日期范围滑块作为新的小部件。ICYMI 完整注释代码在 本回购

如何在 TensorFlow 2.0 中使用 Keras 建立宽深模型

原文:https://towardsdatascience.com/how-to-build-a-wide-and-deep-model-using-keras-in-tensorflow-2-0-2f7a236b5a4b?source=collection_archive---------16-----------------------

在 Keras 函数式 API 中使用特性列

在 TensorFlow 2.0 中,Keras 支持要素列,从而能够使用嵌入、分桶和要素交叉等标准要素工程技术来表示结构化数据。在本文中,我将首先向您展示一个使用 Functional API 构建使用 features 列的模型的简单示例。然后,我将更新代码来构建一个完整的宽而深的模型。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

为了使文章简短,我只关注模型,但是你可以在 GitHub 上看到完整的笔记本(包括使用 tf.data 读取数据)。

1.如有必要,安装 TensorFlow 2.0

这里的代码假设您使用的是 TensorFlow 2.0。pip 在 Colab 中安装它,使用:

!pip install -q tensorflow==2.0.0-alpha0`

或者使用云 AI 平台(CAIP)笔记本获得 TensorFlow 2.0 Jupyter 实例:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Use TensorFlow 2.0 to try out this code

2.创建功能列

为输入中的每个字段创建要素列:

real = {
    colname : fc.numeric_column(colname) \
          for colname in \
            (’dep_delay,taxiout,distance’).split(’,’)
}
sparse = {
      'origin' : fc.categorical_column_with_hash_bucket(’origin’, hash_bucket_size=1000),
      'dest'   : fc.categorical_column_with_hash_bucket(’dest’, hash_bucket_size=1000)
}

这里,我为浮点型字段创建数字列,为分类字段创建哈希分类列。

3.创建模型的输入

对于每个输入,还要创建一个 Keras 输入图层,确保为每个输入字段设置 dtype 和名称:

inputs = {
    colname : tf.keras.layers.Input(name=colname, shape=(), dtype='float32') \
          for colname in real.keys()
}
inputs.update({
    colname : tf.keras.layers.Input(name=colname, shape=(), dtype='string') \
          for colname in sparse.keys()
})

4.做嵌入,一热编码等。

为了在深度学习模型中使用分类变量,我们必须对其进行编码。稀疏变量必须是嵌入式的或一键编码的。所以,让我们双管齐下:

embed = {
       'embed_{}'.format(colname) : fc.embedding_column(col, 10) \
          for colname, col in sparse.items()
}
real.update(embed)# one-hot encode the sparse columns
sparse = {
    colname : fc.indicator_column(col) \
          for colname, col in sparse.items()
}

5.使用函数式 API 构建 DNN 模型

关键是创建一个 DenseFeatures 图层来使用要素列转换输入:

deep = tf.keras.layers.DenseFeatures(real.values())(inputs)
deep = tf.keras.layers.Dense(64, activation='relu')(deep)
deep = tf.keras.layers.Dense(16, activation='relu')(deep)
output = tf.keras.layers.Dense(1, activation='sigmoid')(deep)
model = tf.keras.Model(inputs, output)

就是这样!调用 model.fit()等。像往常一样。

6.使用 Keras Functional API 构建广泛而深入的网络

如果要构建一个宽而深的网络,需要将稀疏要素直接连接到输出结点,但要通过一组密集图层传递真实要素。这里有一个模型架构可以做到这一点:

def wide_and_deep_classifier(inputs, linear_feature_columns, dnn_feature_columns, dnn_hidden_units):
    deep = tf.keras.layers.DenseFeatures(dnn_feature_columns)(inputs)
    for numnodes in dnn_hidden_units:
        deep = tf.keras.layers.Dense(numnodes, activation='relu')(deep)        
    wide = tf.keras.layers.DenseFeatures(linear_feature_columns)(inputs)
    both = tf.keras.layers.concatenate([deep, wide])
    output = tf.keras.layers.Dense(1, activation='sigmoid')(both)
    model = tf.keras.Model(inputs, output)
    model.compile(optimizer='adam',
                  loss='binary_crossentropy',
                  metrics=['accuracy'])
    return modelmodel = wide_and_deep_classifier(inputs, sparse.values(), real.values(), [64, 16])

当然,这是 Keras,你可以很容易地加入 dropout、batch normalization 等。到模型中。

尽情享受吧!

资源:

  1. 参见 GitHub 上的完整笔记本
  2. 阅读我关于在 GCP 做数据科学的书

如何建造不会毁灭我们的人工智能

原文:https://towardsdatascience.com/how-to-build-ai-that-wont-destroy-us-dbc6377feaf4?source=collection_archive---------45-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Dominik Scythe on Unsplash

很难找到一个关于 AI 安全的讨论不是聚焦在控制上的。逻辑是,如果我们不控制它,不好的事情就会发生。

对我来说,这听起来像是现实生活中的疯狂。我们真的认为“法律”、“控制结构”或人类目标对一台超级智能机器很重要吗?你不妨告诉我蚂蚁统治着世界。

我们需要更近距离地观察大自然。我们认为这个世界是一个充满敌意、狗咬狗的地方,这种想法并不像我们想象的那样古老,也不像我们想象的那样正确。我们的控制癖也不是。

复杂的自然系统保持稳定的方式可能会有解决方案。

阿西莫夫说够了

是的,是真的。1942 年,美国科幻作家艾萨克·阿西莫夫,为智能机器的安全设计发明了 3 个法则。他说我们需要让它们“不伤害”我们,并且总是“听从我们的指示”,否则……嗯,你知道。

如今,在科技新闻领域,你不可能不去质疑这些(虚构的)法律是否“足以将我们从人工智能中拯救出来”。让我们弄清楚一些事情:

  1. 介绍法律的短篇小说《逃避》是一部虚构作品。
  2. 阿西莫夫自己想象了违反法律的情况。
  3. 整个想法是不切实际的:要编写像“不要伤害人类”这样的指令,你需要一台能够理解“伤害”的机器,我猜包括情感和心理上的伤害。这对人类来说已经够难了,更别说机器了。
  4. 即使你有这样一台机器,并且能够对阿西莫夫定律进行编程,任何智能,不管是不是人工的,又怎么能肯定地知道它的行为会有什么结果呢?在台车问题中会怎么做?它会被允许做手术吗?如果它在不知情的情况下做了一些后来证明是有害的事情呢?
  5. 我们已经有违反这些法律的机器,看:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

An AI designed to kill people. Source: AIN Online

不幸的是,这不是不明飞行物。这是 BAE 系统塔拉尼斯无人机,已经(我们认为)能够自主选择目标。是的,没错。我们很快就会看到机器人可以随时选择何时、是否以及如何伤害人类。

我再告诉你一些真正磨我齿轮的事情:当人工通用智能(AGI)被描述为“工具”,“为人类做任务”的,或者当人们谈论“控制问题”的时候。伙计们,来吧。

马是工具吗?秘书怎么样?你能让你的听话吗,更别说你的孩子了……

当然,一个从未见过袖珍计算器的人设计的一套法律不会“足以阻止人工智能毁灭我们”。当然一个人类或者超人类的智能不会在我们的控制之下。这些都不是真正的问题。

真正的问题是,在一个人们已经试图建造智能机器的世界里,我们能采取什么措施来限制无知、自私、危险或粗心行为的发生频率?

信不信由你,我们将从人类身上寻找答案。

自私利益的神话

基本上我责怪弗洛伊德。在他之前,我们至少被允许视自己为潜在的贵族。正如苏格拉底所说:

…人类所有的美德都是通过实践来增长和强化的。

即使是以虚无主义闻名的尼采,也对人类赞不绝口:

"…他拥有和他欣赏的植物一样的创造力,植物攀缘着风,最终获得阳光和一片土地,从而在荒凉的土地上为自己创造欢乐。”

弗洛伊德是第一个将人类描述为自私或自恋的人,而不是因为原罪。在他看来,我们的一生都在与黑暗的无意识力量作斗争,如果这些力量失控,那将是可怕的。他不认为我们会赢:

我没发现人类有什么“好”的地方。以我的经验,大部分都是垃圾。

这一快乐的传统是由安娜·弗洛伊德在他死后发展起来的,并且在冷战最激烈的时候,在 T2 约翰·福布斯·纳什的作品中找到了一席之地。博弈论,“纳什均衡”的概念给了我们数学证明:我们生存的唯一希望是自私地行动,假设我们周围的每个人都会这么做。

最近,理查德·道金斯提出了“自私基因”的概念。道金斯是“牙齿和爪子都是红色的”这一观点的忠实拥护者,他敦促我们:

“……试着教导慷慨和利他,因为我们生来自私。”

像这样一个有毒的世界需要监管、治理、预测和控制,以阻止事情分崩离析。慷慨和利他主义不是天生的。我们必须被说服,甚至被强迫,变得善良。因此阿西莫夫定律。

道金斯没有说的,当然是“谁先学会的”。如果不是来自基因或环境的某些特征,利他主义是如何产生的?为什么自然界中到处都是?

真的,这才是重点。“自然是自私的”这个论点有一个巨大的漏洞:如果同情和合作这样的现象不存在,我们如何解释它们?他们来自上帝吗?道金斯不这么认为

不断冲突的神话

我不知道你是怎么想的,但是如果我做了一些慷慨或利他的事情——例如,帮助一位老太太过马路,我这样做是因为感觉很好。

如果你支持“自私的世界”观点,你可能会说那不是真正的利他主义,因为对我有好处。不过,等一下:

为什么做一些帮助别人的事情会感觉很好?从进化的角度来看,我们不得不考虑特定感觉的生存利益:厌恶是对中毒的防御,爱是养育适应良好的年轻人的激励。

如果合作的感觉很好,那可能是因为它有助于我们的生存,而侵略性、支配性或自私的行为可能不会。索伯和威尔逊在 1998 年很好地提出了这一点,最近又在这里进行了辩护。

从系统论的角度来看,规则是合作,而不是竞争。生态系统、社会、有机体和机器都是由数十亿个相互依赖的部分组成的。只有当所有这些部件协同工作时,它们才能发挥作用。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

War can only be fought in the context of intense cooperation. Source: US Military

从宏观上看,两国之间的战争看起来像是一场冲突。然而,这是唯一可能的,因为在它之下的所有尺度上都有紧密的合作。

我们作为一个物种所取得的一切:我们的发现、发明、建设和创造,如果没有大规模的合作是不可能的。

同情这种对我们大多数人来说足够真实的感情,会有助于我们团结一致吗?

富有同情心的机器

一台机器遵守它无法避免的任何约束,并最小化一些损失函数,这是一种非常有效的完成工作的方式。事实上,有这样的人:精神病患者。

你可以说我过时了,但我更希望我的精神变态者是人类,而不是大规模并行。

在许多情况下,健康的情绪有助于决策,因为它们能提供快速、准确的信息。他们就像一种感知形式;一种凌驾逻辑的方式,当逻辑见树不见林

情绪也有一种约束功能:如果某件事“感觉不对”,不管我们认为它有多正确,十有八九,我们会阻止它。

机器也需要一个不仅仅基于逻辑的控制系统。如果他们没有,迟早,他们会找到一种方法绕过任何给他们的约束,也许是通过重新设计自己。

明确一点,我说的不止是 Noa,Kasper,Ellie 之类的。探测和模仿情绪是不够的——这是精神病患者做的另一件事。

我建议我们从构建工具开始,帮助我们深入理解事物联系的方式。

一台真正智能的机器会意识到,包括它自己在内的一切事物都是一个系统(许多系统)的一部分,在这个系统中,合作是关键。

我认为,这就是同情的含义:认识到你的快乐就是我的快乐,你的痛苦也是我的痛苦。

像这样的控制系统的优势在于,它是基于一些可观察的和不变的东西(事物的相互联系),而不是脆弱的内部逻辑。

没错,你只要看看周围,或者看看历史,就会发现这并不是一个万无一失的系统。明明个人可以压抑同情心,互相做坏事。毫无疑问,机器也会。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

A woman makes a statement to the US State Machine during Vietnam War protests. Source: imgur

即使在这种情况下,情绪也能起到稳定的作用:人们会愤怒起来反抗压迫者。骄傲驱使人们保卫他们的边界或家庭。爱和勇气帮助我们面对枪口。

很可能机器需要以类似的方式相互调节。他们需要一个这样做的系统。

是时候面对现实了

智力的一个明显标志是它绕过障碍的能力。作为智慧生物,弯曲、克服和重新想象约束是我们很自豪能够做到的事情。

预测和控制方法——规则、指导方针和监督——在监管人工智能方面不会比它们在人类影响气候方面做得更多。尽管我们幻想控制它,或者让它屈从于我们的意志,但我们需要接受它不会发生。永远不会。

大自然是一个由合作系统组成的系统。是的,有冲突,但这些是例外,而不是规则。理解这一事实是包括 AGI 在内的所有物种长期成功的关键。我们可以称这样的理解为“同情”。

在过去的 200 年里,人类生活得好像我们是唯一重要的东西。我们现在看到了后果。

让我们不要再犯同样的错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值