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

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

地理空间分析破解选址难题(下)

原文:https://towardsdatascience.com/crack-site-selection-puzzle-by-geospatial-analysis-part-2-2eefc5f5140?source=collection_archive---------81-----------------------

发现需求和供给之间的不平衡

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

图 1 在新加坡 FairPrice Finest 中巴鲁广场拍摄的照片

在本系列的第一篇博客中,我们提出了一个想法,旨在从需求和供给的角度解决选址问题。我们完成了需求方面的分析,并模拟了目标城市槟榔屿的客户分布。尽管案例研究是在食品杂货行业的场景中进行的,但同样的解决方案也可以应用于房地产、电子商务和教育行业。在这篇博客中,我们将解决供应方面的问题,并研究整个城市的需求和供应之间的不平衡。请记住,我们的客户是一家连锁超市,其潜在客户是整个城市的人口。

供应分析由以下部分组成。

  1. 竞争对手发现:寻找现有超市和杂货店的位置。
  2. 距离估算:估算参赛者与城市不同区域之间的距离。
  3. 顾客密度估算:估算一家超市或杂货店在城市不同位置服务的平均顾客数量。

竞争对手发现

使用 Google Places API 可以获得关于现有杂货店供应商的信息。它提供了关于不同类型的名胜古迹的各种信息,包括它们的商店名称、地理位置、开放时间,甚至游客评级等。这里我们期望 API 提供的信息是最新的。然而,并不能保证 API 可以检测到所有符合搜索标准的地方,尤其是欠发达地区。为了这项研究的目的,这是我们可以依赖的最好的可访问数据源。

Places API 使用 API 键,通常使用 3 个参数进行查询:设施类型、中心位置和半径。在第一个系列中,我们将整个城市区域分割成数千个 1 公里 x 1 公里的网格。为了通过 API 收集所有现有的杂货店供应商,我们获取网格中心的地理坐标,并搜索 2 公里范围内的超市和杂货店。为了使博客更简洁,代码更少,我将省略输入数据和配置参数的准备步骤,只强调如何查询 Places API。以下代码提取新加坡乌节路 2 公里范围内的超市。

查询 _ 地点 _api.py

查询结果以 Python 字典列表的形式返回。其中一个看起来如下。在这项研究中,我们只使用现有超市的地理位置信息。

{
   "business_status":"OPERATIONAL",
   "formatted_address":"491 River Valley Rd, #01-14, Singapore 248371",
   **"geometry":{**
      **"location":{**
         **"lat":1.2929051,**
         **"lng":103.8270208**
      **}**,
      "viewport":{
         "northeast":{
            "lat":1.294498079892722,
            "lng":103.8284264298927
         },
         "southwest":{
            "lat":1.291798420107278,
            "lng":103.8257267701073
         }
      }
   },
   "icon":"[https://maps.gstatic.com/mapfiles/place_api/icons/shopping-71.png](https://maps.gstatic.com/mapfiles/place_api/icons/shopping-71.png)",
   "id":"fda0ec60faa787f2bf992132e66c80f29daa5964",
   "name":"FairPrice Finest Valley Point",
   "opening_hours":{
      "open_now":False
   },
   "photos":[
      {
         "height":2048,
         "html_attributions":[
            "<a href=\"[https://maps.google.com/maps/contrib/111973208857299784904\](https://maps.google.com/maps/contrib/111973208857299784904\)">Anusha Lalwani</a>"
         ],
         "photo_reference":"CmRaAAAAQ6An4L-A5PbgDFkpZVllEGuB4Ayw0hdrZ9coCBaF6esLM2B7RVnJCvf0DPeZrlcbZ3KVFUz9cciPtArUAZ6tof_lJHzJHqKzcEFyRGJurK_Drld0GUec9sCWm25bXURVEhD6GZqf6j_Kb5IOTtQ1ogslGhQas22jzBT2rJ0jkj9zUhDvCLYj_w",
         "width":1536
      }
   ],
   "place_id":"ChIJTyWXW4EZ2jERNKBCOx_-4LA",
   "plus_code":{
      "compound_code":"7RVG+5R Singapore",
      "global_code":"6PH57RVG+5R"
   },
   "rating":4,
   "reference":"ChIJTyWXW4EZ2jERNKBCOx_-4LA",
   "types":[
      "grocery_or_supermarket",
      "food",
      "point_of_interest",
      "store",
      "establishment"
   ],
   "user_ratings_total":112
}

从所有网格中收集超市和杂货店,并在移除重复项后绘制在 QGIS 地图上,如图 2 所示。可以观察到,现有杂货店供应商的分布(白点)与客户分布大致一致。

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

图 2 槟城现有超市和杂货店的局部视图

距离估计

允许我问你一个问题。你愿意花多长时间在购物旅行上?

生活在不同城市的人可能会有不同的答案。我对这个问题的回答是 15 分钟的步行距离。在封锁期间,步行去杂货店可以作为一种常规的体育锻炼。在这项研究中,由于槟榔屿的人口密度相对较小,我们预计旅行时间的阈值会更长。根据马来西亚朋友的建议,我们假设阈值为 10 分钟车程。这是此分析中使用的最重要的参数,如果以后将解决方案部署为仪表板应用程序,可以很容易地对其进行调整。请注意,在咨询项目中,这些参数需要通过严格的市场调查获得。

这个旅行距离问题在这里很重要,因为,给定旅行时间的阈值,我们可以 估计每个杂货店可以接触到的顾客数量,这就是所谓的 流域分析 。为了便于分析,我们通过Google Distance Matrix API提取每对网格和现有杂货店之间的预计行驶时间。以下代码提取了从乌节路到新加坡滨海湾金沙的行驶时间。

query_dist_api.py

结果表明,从起点到目的地址的行驶时间为 13 分钟。

{
   "destination_addresses":[
      "10 Bayfront Ave, Singapore 018956"
   ],
   "origin_addresses":[
      "2 Orchard Turn, Singapore 238801"
   ],
   "rows":[
      {
         "elements":[
            {
               "distance":{
                  "text":"5.2 km",
                  "value":5194
               },
               "duration":{
                  "text":"13 mins",
                  "value":761
               },
               "status":"OK"
            }
         ]
      }
   ],
   "status":"OK"
}

客户密度估计

让我们总结一下我们在网格级别获得的关键信息。

  • 人口,或每个网格的客户数量。
  • 为每个网格中的顾客提供服务的杂货店和超市的数量。

现在我们快速看一下网格中顾客和杂货店数量的分布。没有填充的网格在下面的直方图中被忽略。

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

图 3 电网客户数量的分布

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

图 4 10 分钟车程内的网格状商店数量分布

顾客和杂货店的数量看起来都很合理。在这里,我们将为每个网格计算一个客户密度指数,以评估整个城市的供需不平衡。从概念上讲,它相当于需求与供给之比 (DSR)。

顾客密度=顾客数量/网格中为顾客服务的杂货店和超市数量

我们将根据顾客密度值推荐新超市的位置。一般来说,高顾客密度意味着新商店的好位置。因此,我们的客户可以将其作为选址的参考。

图 5 显示了整个槟城的顾客密度分布。DSR 高的区域用深蓝色突出显示。

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

图 5 整个槟城的顾客密度分布

最后的话

选址案例研究系列到此结束。你可能已经注意到,在估计顾客密度时,超市的容量没有被考虑在内。换句话说,在这项研究中,所有现有商店的容量都是一样的,这在现实中是不准确的。此问题的一个可能解决方案是将现有商店与 OpenStreetMap (OSM)数据中相应的形状进行匹配。利用坐标可以计算出占地面积,并用来估计商店的容量。

此外,请在执行之前计划好您对 Google API 的查询。对查询数量和总成本进行估计。

本研究中使用的脚本和笔记本可在 GitHub 上获得。谢谢你的阅读。

破解 21 点—第 1 部分

原文:https://towardsdatascience.com/cracking-blackjack-part-1-31da28aeb4bb?source=collection_archive---------37-----------------------

破解二十一点

设置+简单的蒙特卡罗模拟

嗨!

我写这个“破解 21 点”博客系列是为了巩固我在强化学习领域获得的知识。当我创建这个 21 点项目时,我需要结合 30+文章和博客帖子的信息,我想让下一个人更容易。

我绝不是这方面的专家。如果您对我将要展示的信息有任何问题或疑虑,请随时联系我们!我的联系信息在底部。

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

图片来自 Unsplash

21 点快速总结

21 点是一种与庄家对抗的纸牌游戏。在一轮开始时,玩家和庄家都有 2 张牌。玩家只能看到庄家的一张牌。游戏的目标是让我们的牌的值尽可能接近 21,而不超过 21。下面列出了每张卡的价值。

  • 10/杰克/皇后/国王→ 10
  • 2 到 9 →与卡的值相同
  • Ace → 1 或 11(玩家选择)

如果玩家的牌少于 21 张,他们可以选择“击中”并从这副牌中随机抽取一张牌。他们也可以选择“站”,保留手中的牌。如果玩家超过 21,他们“破产”并自动输掉这一轮。如果玩家正好有 21 点,他们自动获胜。否则,如果玩家比庄家更接近 21,则玩家获胜。

二十一点还有更细的规则,这里读它们**

为什么要看这个帖子?

这篇文章的目的是展示即使是简单的模拟在模拟我们周围的世界中令人眼花缭乱的力量。对于任何强化学习的努力,最好是通过像 21 点这样的简单游戏来学习,因为它们只有一些不确定性要跟踪,明确的奖励和惩罚规则,以及一个直截了当的目标。

像 21 点这样的赌场游戏在统计上被设计成有利于“房子”,我有兴趣看看我是否能通过强化学习算法“破解”它。对于 21 点,我的目标是得出一个玩家策略,从长远来看,这个策略实际上会比赌场/庄家产生优势。****

一些关键术语

在这种情况下,策略是一个剧本,告诉玩家(或我们的人工智能代理)在每种可能的情况下应该做什么样的决定。人工智能代理是抽象的存在,它将通过我们的强化学习算法学习和更新它的知识。

在我们简化的 21 点模型中,我们只给玩家两个选项:打或者站。我们将以 1000 美元开始我们的玩家,并假设他们每轮下注 100 美元。以下是赢/输/平的奖励/惩罚:

  • 赢:+100 美元
  • 平局:0 美元
  • 输了:$100

建筑 21 点

我建议在读完这篇文章后,按照你自己的速度浏览下面的代码。现在浏览一下代码,以便获得一些关于如何构建最适合您需求的模拟环境的想法。点击查看完整的笔记本

上面代码的一个 TL:DR:

  • 使用 OOP 原则(类、函数等)和基本数据结构(列表、字典等)定义了一张卡和一副牌。
  • 定义了两个函数,用于实现庄家转牌和评估庄家牌局背后的逻辑。这里定义的有一个固定的、可预测的逻辑。
  • 定义了一个函数来实现评估玩家手牌背后的逻辑。有不同的方法来解决这个问题。
  • 定义了一个主play_game()函数,在给定玩家策略、回合数等参数的情况下模拟 21 点游戏。

本文剩余部分的重点将是研究这个模拟环境的玩家策略输入,看看我们能获得什么样的见解。

简单的蒙特卡罗模拟

任何蒙特卡罗方法的关键是:

“利用随机性来解决原则上可能是确定性的问题.”— 维基百科

更简单地说,我们将依靠机器的计算能力来近似某些结论,而不是通过铅笔和纸来精确地得出那些结果。

蒙特卡洛方法的快速(非 21 点)示例

例如,让我们用蒙特卡罗方法来回答这个简单的问题:

“如果我掷出两个六面骰子,两个骰子的和最有可能是多少?”

正如每堂统计课所教授的那样,我们可以使用纸笔通过创建可能总和的概率分布来解决这个问题,并查看哪个出现的概率最大。

然而,如果我们懒得把这些都写出来,我们可以编写一个蒙特卡罗模拟程序来代替!

在下面的代码中,我将两个骰子掷 100,000 次,并绘制出我从 100,000 次模拟中得到的总和的分布。

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

来源:作者图片

瞧啊。我们从分布图中清楚地看到,掷出 2 个骰子时,7 是最有可能的和。计算能力的魔力!

回到 21 点

上面的骰子例子有点做作——蒙特卡罗方法最适用于需要人类花费大量时间尝试和手工解决的问题。

这里有一个更适合蒙特卡洛模拟的问题:

“在 21 点游戏中,如果我们的手牌≥ 18,我们就站着,否则就打,那么每回合的预期回报是多少?”

像这样的问题对人类来说太难解决了。

为了回答这个问题,我们将我们的玩家政策定义如下:

离散策略:

  • 如果手≥ 18:站立。
  • 否则:打。

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

来源:图片作者

运行模拟

接下来,我们将利用计算能力和 21 点环境的随机性来运行 100,000 轮并计算预期回报:

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

来源:图片作者

结果显示,如果玩家决定使用离散策略,平均来说,他们每轮会损失 10 美元。我们需要找到一个能产生更好回报的政策!

随机政策

离散策略被认为是“离散的”,因为只要满足一个条件(例如,手牌≥ 18),我们的玩家只会采取一种可能的行动。

然而,当我们设计我们的强化学习人工智能代理时,我们希望它有机会探索其他行为,即使一些标准告诉它做其他事情。对于我们的人工智能代理来说,在学习过程的早期阶段保持探索是很重要的,因为它的拣选动作策略是由太小的样本量决定的。

因此,我们需要习惯于随机变量和政策,这些变量和政策在选择行动时允许随机性。这里有一个我们可以试试:

随机策略:

  • 如果手≥ 18: 80%站立/ 20%命中。
  • 否则:80%命中/ 20%站立。

运行模拟

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

来源:作者图片

结果显示,如果玩家决定使用随机策略,平均来说,他们每轮会损失 18 美元(T1),比离散策略多 8 美元(T3)。尽管我强调了随机策略在强化学习中的重要性,离散策略还是赢了!

利用我们人类的直觉,我们可以理解为什么会发生这种情况。从长远来看,在牌局中继续击球总是更好< 18 and keep standing when hand ≥ 18. It is detrimental in the long run to add a 20% chance of doing a counter-intuitive action in either of these states.

However, our AI agent will not be born with this intuition. Stochastic policies are fluid, and can be tweaked on the fly. This approach allows our AI agent to suffer through countless rounds of hitting when hand ≥18, and incrementally tweak its policy until it stands 100% of the time when hand ≥ 18.

What’s Next

The upcoming installments of this series will strive to answer these questions:

  • “玩 21 点的最佳方法是什么?
  • “如何通过蒙特卡洛强化学习算法自发地学习这种最优策略?”

在我的下一篇文章中,我们将更深入地探究基本的强化学习理论。此外,我们将在 OpenAI Gym 的标准化框架内重建我们的 21 点环境。这将使我们能够轻松地探索算法和调整关键因素。

如果你想向前看,我的整个 21 点项目可以在这里找到。

感谢您的阅读!

我真的很感激任何形式的反馈!我想成为一个更一致、更有效的内容创作者。

你学到什么了吗?我很难理解吗?

欢迎在下面留言或发电子邮件给我,地址是 adithyasolai7@gmail.com!

本项目 GitHub 回购。

请继续阅读!

此处第二部分。

破解 21 点——第二部分

原文:https://towardsdatascience.com/cracking-blackjack-part-2-75e32363e38?source=collection_archive---------28-----------------------

破解二十一点

强化学习和开放式健身房简介

嗨!

如果您还没有这样做,请在继续之前阅读第 1 部分。本文的其余部分将假设您已经阅读并理解了第 1 部分。

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

图片来自 Unsplash

强化学习周期

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

作者制作的图像

为了推进我们使用强化学习“破解”21 点的任务,我们必须理解上图。下面,我将图像分解成它的组成部分,以及它们在 21 点中的对应部分:

  • 代理:执行学习过程的人工智能抽象。在 21 点中,经纪人就是玩家。
  • 环境:代理可以与之交互的所有可能情况的集合,每种情况下可用的动作,以及与每种情况相关的结果(奖励+惩罚)。在 21 点中,这是所有可能的玩家手牌、庄家向上的牌、玩家动作(打或站)和结果(赢/输/平)的集合。
  • **陈述:**有助于构成环境的“情境”。在我们的 21 点版本中,状态将由玩家的手牌值和庄家的上牌值组成。球员/经纪人在做决定的时候只能看到这两样东西。
  • 动作:代理在与某个给定状态交互时可用的选项。在我们的 21 点版本中,可用的操作是击打和站立。
  • 奖励:在某种给定的状态下,代理人收到的对其行为的反馈。这是由程序员定义的,以帮助向代理显示哪个结果是更好的,代理可以相应地开始调整它的动作。在我们的 21 点游戏中,赢=+100 美元,输=-100 美元,平=+0 美元。决定胜负/平手的逻辑在环境中;奖励是分配给每个结果的数值。

这些组件如何在 21 点中一起工作

  • 一轮 21 点开始:2 张牌发给玩家和庄家,代理只能看到自己的牌和庄家的一张牌。环境通过向代理发送一个初始状态(玩家手牌值+庄家升牌值)来对此建模。

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

作者制作的图像

  • 玩家有两个动作:打或站。代理使用其策略(在第一部分中讨论)基于当前状态选择一个动作。

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

作者制作的图像

  • 代理选择的状态+动作被发送回环境。

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

作者制作的图像

  • 在给定状态的情况下,环境在内部处理代理的动作。它为“击中”发任何新牌。如果合适的话,它会计算谁赢了这一轮(玩家站着,21 点!,或者半身像)。

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

作者制作的图像

  • 如果这轮现在结束了,环境发送给代理一个代表下一轮 21 点的新状态,以及前一轮的奖励。代理使用该结果来更新其策略。

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

作者制作的图像

  • 如果代理在当前回合中有更多的动作要做,则环境向代理发送一个状态,该状态具有更新的玩家手牌值和+$0 的奖励,因为该回合尚未结束。

我们的代理如何从这个循环中学习

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

作者制作的图像

上面的循环意味着这个循环将无限期地继续下去,那么实际的学习在哪里/什么时候发生呢?

单个周期可以表示为一个序列:

状态→行动→奖励

当我们围绕这个循环进行循环时,我们可以记录这些状态/动作/回报元组。在循环中经历大约“n”个循环,并在进行过程中记录状态/动作/奖励元组,这被称为情节。

在我们完成了我们期望的循环次数(假设 50 次)之后,我们的代理将遍历状态/动作/回报元组,并相应地更新它的策略。在下一篇文章中,我们将深入研究我们的强化学习算法将如何指导我们的代理使用这些状态/动作/奖励元组来优化它的策略。

偶发任务与连续任务

一集应该由多少个循环组成?在我的 21 点环境中,我认为一轮 21 点是一集。这意味着每集通常会有 1-3 个状态/行动/奖励元组,因为代理人在每轮 21 点中可能只会做出 1-3 个立/打决定(在极少数情况下会做出更多决定)。

幸运的是,我们在 21 点中有一个“回合”的概念来帮助定义一集。然而,其他上下文,如应用强化学习来预测股票市场,没有“回合”来帮助定义情节。股市是没有起点和终点的,在定义剧集的时候你必须要有创意!

由于这些原因,使用强化学习预测股票市场将被认为是一个持续的任务,而破解 21 点将被认为是一个阶段性的任务。

为什么要使用 OpenAI Gym 重建我们的 21 点环境?

我们在第 1 部分中设置的 21 点游戏没有准确模拟强化学习周期。我们遗漏了关键的部分,比如记录状态/动作/回报元组和定义一集。

我们将在 OpenAI Gym 的框架内构建新的 21 点环境。这个框架提供了一种定义我们环境的标准化方法,这样我们就可以很容易地用其他自己编写的和开源的强化学习算法进行实验。这个框架还提供了有用的 API 来更全面地定义我们的状态、动作和奖励。

我们新的 OpenAI 健身房 21 点环境概述

为了构建我们的环境,我们将在 OpenAI Gym 环境模板中定义函数。这些函数是对强化学习的循环过程建模的必要部分,如下所示:

  • __init__():初始化 21 点牌组,奖励空间(+$100,+$0,或-$100),动作空间(击打或站立),观察空间(或所有可能状态的集合。每个状态由玩家手牌值和庄家升牌组成)。
  • reset():重置剧集,给代理初始状态。
  • step(action):代理使用我们的算法选择一个动作,并使用这个函数将这个动作发送到环境中。这个函数模拟环境的过程(击中时发新卡,计算奖励等)。然后,它返回一个新的状态,奖励,以及该集是否完成。
  • render()(推荐):显示一集不同阶段的状态/动作/奖励元组等相关信息的功能。无助于循环往复。

使用 OpenAI 健身房 21 点环境

在深入研究这些函数的代码之前,让我们看看这些函数如何一起工作来模拟强化学习周期。在下面的模拟中,我们使用我们的 OpenAI 健身房环境和随机选择击中/站立的策略来寻找每轮的平均回报。

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

图片作者。查看代码此处

  • 首先,我们初始化环境:env = BlackjackEnv()。该行将运行前面描述的__init__()功能。
  • 然后,我们运行 1000 集(或 1000 轮 21 点)的模拟。
  • 在每集开始时,我们调用env.reset()函数给代理一个新的初始状态,以确定 hit/stand。
  • step()函数中将环境的env.done值更改为True之前,代理会随机选择击中/站立作为其对step()函数的动作。在下一篇文章中,我们的算法将改进拣选动作的过程。
  • 一旦env.done到了True,这一集就结束了,这一集的总奖励加到总奖励里,下一集开始。在下一篇文章中,我们的算法将向代理展示如何在每一集之后改进其策略。

构建开放式健身房 21 点环境

下面的代码片段包含了我在 OpenAI 健身房环境中实现的 21 点。现在先浏览一下,在完成这篇文章后再详细浏览。我在下面详细介绍了每个功能的关键线路。这些函数重用了第 1 部分中内置的一些函数和类。

**__init__()** :

首先,我们利用 OpenAI Gym 的spaces功能来定义我们的动作空间:击打或站立。我们使用两个二进制选择的离散集合:0 表示击中,1 表示站立。

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

图片作者。查看代码此处

接下来,我们定义观察空间。观察空间是代理可以观察和响应的所有可能状态的集合。在我们的 21 点版本中,状态是玩家的手牌值和庄家的上牌。

观察空间是强化学习循环中环境的一个组成部分。其他组件,如计算奖励和玩家手牌值,在step()函数中实现或从第 1 部分重用。

我们考虑的可能牌值范围是 3 到 20。2 是不可能的,因为它需要两个 a,而我们计算手牌值的逻辑不会将两个 a 评估为 2。对于手牌值 21(21 点!)和 beyond(半身像),代理人不需要做任何决定。

所有可能的庄家大牌从 2 到 a。Ace 仅由 11 表示,而不是 1。在我们的算法中,代理在学习和优化时并不关心庄家的 Ace 评估为 1 还是 11。

玩家的牌值范围是 3 到 20,也就是 18 个离散值的范围。庄家升牌的范围是 2 到 Ace,这是一个 10 个离散值的范围。我们再次使用 OpenAI Gym 的spaces函数来表示这一点。我们还使用spaces.Tuple来表示这两个范围必须相乘才能得到所有可能的状态。

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

图片作者。查看代码此处

最后,将环境的done变量初始化为False,以确保在一集结束前玩满一轮 21 点。

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

图片作者。查看代码此处

**reset()**T14:

如前所述,该函数重新使用第 1 部分中的函数来重置和重新洗牌,向玩家和庄家发 2 张牌,并评估玩家的手牌价值。

该函数还将初始状态作为一个包含两个值的numpy数组返回:玩家的手牌值和庄家的上牌。

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

图片作者。查看代码此处

**step(action)** :

该函数接收代理的动作。调用_take_action(action)函数来发一张新卡,如果动作被击中,则重新计算玩家的手牌值。

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

图片作者。查看代码此处

然后,该功能会在服用action后查看二十一点的插曲现在是否完成。

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

图片作者。查看代码此处

如果这一集已经结束,那么这个函数将重新使用第 1 部分中的逻辑来决定赢家和奖励。

最后,该函数返回新状态、奖励以及该集是否完成。{}是一个返回值,用来描述函数中发生了什么,但是我们现在让它为空。

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

图片作者。查看代码此处

**render()** :

这个函数只是使用简单的print()函数来显示玩家的手牌值、玩家手中的牌、庄家的上牌以及env.done的值。

该函数主要用于调试。

下一步是什么

在接下来的文章中,我们将利用我们定制的 OpenAI Gym 环境和强化学习的新知识来设计、实现和测试我们自己的强化学习算法!

我们将使用首次访问蒙特卡罗方法对我们的算法进行建模,并调整关键杠杆,如γ(贴现率)、α(学习率)和ε(探索与利用)以最大化回报。

我们一直在讨论的一切最终将在下一篇文章中汇集在一起。我们将最终指导一个人工智能代理有机地学习一个最优策略来破解 21 点

感谢您的阅读!

我真的很感激任何形式的反馈!我想成为一个更一致、更有效的内容创作者。

你学到什么了吗?我很难理解吗?

欢迎在下面留言或发电子邮件给我,地址是 adithyasolai7@gmail.com!

本项目 GitHub 回购。

请继续阅读!

此处第 3 部分。

破解 21 点——第三部分

原文:https://towardsdatascience.com/cracking-blackjack-part-3-8fd3a5870efd?source=collection_archive---------67-----------------------

破解二十一点

强化学习算法的构建模块

嗨!

如果您还没有这样做,请在继续之前阅读第 1 部分第 2 部分。本文的其余部分将假设您已经阅读并理解了前面的文章。

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

图片来自 Unsplash

这篇文章的大纲

在本文中,我将解释强化学习算法中使用的关键构建模块,我们将使用它来最大化 21 点回报。这些构建模块也在许多其他强化学习算法中使用,因此在我们知道并喜爱的上下文中理解它们是值得的:二十一点!

当你阅读这篇文章的时候,一定要记住第二部分中的强化学习循环图!

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

作者制作的图像

我们 RL 算法的构建模块

简而言之,我们的强化学习算法唯一会做的事情就是在每一集之后,用状态→动作→奖励元组(在第二部分中解释)来定义代理应该做什么。下面描述的构建模块有助于我们的代理在学习过程中进行更新,以获得玩 21 点的最佳策略。

我们的算法将使用和更新的关键数据结构

影响代理学习过程的重要变量

  • Alpha (α): 这可以认为是学习率。当我们的代理在某个状态下从环境中获得行为奖励后,它将更新 Q 表中相应状态-行为对的 Q 值。α是 Q 值变化的权重(或系数)。α必须是> 0 且≤ 1。较低的 α意味着每一轮 21 点对政策的影响较小,并且有助于在大量事件中进行更准确的学习。

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

作者制作的图像

  • Epsilon (ε): 这可以被认为是 Prob 表中概率的类似“学习率”。当我们的代理人因某个状态+行动获得奖励时,它也会调整未来采取相同行动的概率。ε将与α相似的权重/系数应用于这些变化中的每一个。ε必须≥ 0 且≤ 1。更高的ε产生更小的采取行动的概率变化。****

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

作者制作的图像

  • ε衰变(ε-衰变):这是每次发作后ε衰变的速率。在代理学习过程的开始,我们希望ε从高开始,对 Prob 表进行小的修改,因为我们希望我们的代理探索新的行动。这有助于确保最终的政策不会因为学习过程早期的随机性而严重扭曲。例如,我们不希望在学习过程的早期对 player-hand-value = 18 进行几次成功的“hit”操作,以使我们的代理人决定从长远来看 hit 在这个位置是正确的。随着学习过程的继续,我们使用ε-decay 减少ε,因为我们希望代理利用它在先前的探索阶段获得的准确见解。

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

作者制作的图像

  • ε最小值(ε-min): 探索 vs 利用动态非常微妙;如果不小心,从探索到利用的转变可能会非常突然。ε-min 变量设定了一个事件对概率表中某个状态的动作概率的影响限度。
  • Gamma (γ): 在给定的一集(或一轮)21 点中,AI 智能体在某些情况下会做出不止一个决定。比方说,当玩家手牌值= 4 时,我们的 AI 智能体命中,并在此之后再做出 2 个决策。在这一集的最后,代理人得到了一份奖励。最初的“击中”动作对最终的奖励有多大的责任?γ有助于解释这一点。我们使用γ作为一集最终奖励的贴现率,来近似初始“击中”动作的奖励。γ必须为> 0 且≤ 1。

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

作者制作的图像

上面的变量应该被认为是杠杆:它们可以被增加或减少来试验代理的学习过程。稍后,我们将讨论这些杠杆的哪种组合在 21 点中产生最佳策略和最高回报。

下一步是什么

在下一篇文章中,我将从高层次上解释首次访问蒙特卡罗算法,然后深入代码。我将展示我是如何实现本文中描述的算法和所有构件的。

类似于第 2 部分中的 OpenAI Gym Blackjack 环境,该算法的实现通过几个关键的 Python 函数协同工作来实现。

感谢您的阅读!

我真的很感激任何形式的反馈!我想成为一个更一致、更有效的内容创作者。

你学到什么了吗?我很难理解吗?

欢迎在下面留言或发电子邮件给我,地址是 adithyasolai7@gmail.com!

本项目的 GitHub 回购。

在此阅读第 4 部分

破解 21 点——第四部分

原文:https://towardsdatascience.com/cracking-blackjack-part-4-8b4a9caa38eb?source=collection_archive---------45-----------------------

破解二十一点

初访蒙特卡罗算法+编码吧!

嗨!

如果您还没有这样做,请在继续之前阅读第 1 部分第 2 部分第 3 部分。本文的其余部分将假设您已经阅读并理解了前面的文章。

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

图片来自 Unsplash

这篇文章的大纲

在这篇文章中,我将解释首次访问蒙特卡罗(MC)算法是如何工作的,以及我们如何将其应用于 21 点,以教会人工智能代理最大化回报。下面是这篇文章的结构:

  1. 从高层次解释算法。
  2. 在第二部分的中的 OpenAI Gym Blackjack 环境中实现算法。

在阅读时,请记住,首次访问 MC 算法的主要影响是定义代理在某个给定状态下采取某个行动获得奖励后应该如何更新其策略。请参考下面的图表来帮助形象化这一点。

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

作者制作的图像

首次访问 MC 算法的 10,000 英尺概述

  1. 第 2 部分初始化 21 点环境。
  2. 定义第三部分中解释的 Q 表、概率表、α、ε、ε衰减、ε最小和γ。
  3. 定义您希望您的代理学习多少集。更多的情节通常会产生更有利可图的政策。
  4. 播放一集。记录剧集中所有的(**状态→动作→奖励)**元组。
  5. 剧集结束后,对ε应用ε-decay/ε-min。
  6. 然后,使用来自步骤 4 的(**状态→动作→奖励)**元组和相关公式更新 Q 表和概率表。
  7. 对于步骤 3 中定义的剧集数量,重复步骤 4-6。
  8. 在所有事件之后,产生的 Q 表和概率表代表了 AI 代理刚刚学习的 21 点的优化策略。

更详细的步骤 4-6

在上面的概述中,我故意对第 4、5 和 6 步解释不足。这些都需要代码和公式来正确解释,这就是我在这里要做的!我建议打开完整的笔记本,快速查阅我提到的、我没有深入研究的任何更小的功能。在这里找到它

第 4 步:播放一集

我们将利用第 2 部分中定义的 21 点环境的功能来模拟一集。我们还将利用 Q 表和概率表。

浏览下面play_game()函数的代码片段。之后我会分解关键步骤。

  • 使用第二部分中描述的env.reset()功能开始一集二十一点。reset()函数返回一个state:代理必须做出决定的初始状态。这将在我们播放剧集时更新。当我们播放这一集时,一个列表episodes将存储所有的(**状态→动作→奖励)**元组。

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

作者制作的图像

  • 播放一集的全部意义就是记录并返回我们的代理人通过做决定和拿回奖励而产生的(**状态→动作→奖励)**元组。我们的算法将使用这些元组来改变定义我们的代理策略的 Q 表和概率表。

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

作者制作的图像

  • env.done变成True时,我们这一集就结束了。这在第 2 部分的中有解释。

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

作者制作的图像

  • 如果给代理发了 21 点(21!)幸运的是,在这一集开始时,这一集被废弃了。我们的人工智能代理无法从这一事件中学到任何东西,因为它不需要做出任何决定。我们将返回一个空的episode列表。(我们检查state[0] == 19,而不是 21,因为我们将所有玩家手牌值减去 2,以满足我们的 21 点环境中的observation_space。)(参见第二部分代码。)

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

作者制作的图像

  • 否则,代理必须决定一个行动:打或站。它使用 Q 表来确定对于给定的state,哪个动作当前具有最高值(或 Q 值)。这个 **state** 的击中和站立的这些 Q 值将在本集之后在我们算法的步骤 6 中更新。

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

作者制作的图像

  • 接下来,ε(出自第三部)和探索开拓之间的微妙平衡就要发挥作用了。我们使用这个概率表来找出选择best_action的概率。然后,我们使用这个分布随机决定一个动作。如果我们由于低ε而处于利用阶段,则best_action极有可能被选中。如果我们由于高ε而处于探索阶段,我们的代理有更大的机会选择best_action的反面。这是该算法如何利用随机策略和蒙特卡罗方法的一个完美例子:它使用随机性来处理本质上确定性的问题这个 **state** 的这些击中和站立的概率将在本集之后在我们算法的步骤 6 中更新。

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

作者制作的图像

  • 接下来,代理使用env.step()函数提交到action_to_take(参见第 2 部分了解更多关于env.step())。代理收到一个next_state并因其动作获得奖励。env.done也更新了。

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

作者制作的图像

  • 我们仍然可以访问state——我们开始时的状态。我们仍然可以访问action_to_take——我们在state采取的行动。我们也是刚刚收到state里拿action_to_takereward。所以我们有一个(**状态→动作→奖励)**元组要添加到episode

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

作者制作的图像

  • 最后,我们设置state = next_state重复这个过程,直到env.done变为True

我们将在这里停止这篇文章,因为我想让这些信息以更小的、一口大小的部分来消化!

下一步是什么

在下一篇文章中,我们将直接深入讨论步骤 5步骤 6 ,就像我们讨论步骤 4 一样。

在理解了步骤 5步骤 6 之后,你将了解这种强化学习算法的所有技术方面。然而,解决人工智能/人工智能问题既是一门科学又是一门艺术

在之后的文章中,我们将更深入地探讨这个 21 点问题的艺术部分。我们将通过对α、ε和γ进行实验,展示如何优化该算法。

感谢您的阅读!

我真的很感激任何形式的反馈!我想成为一个更一致、更有效的内容创作者。

你学到什么了吗?我很难理解吗?

欢迎在下面留言或发电子邮件给我,地址是 adithyasolai7@gmail.com!

本项目的 GitHub 回购。

在这里阅读第五部分

破解 21 点——第五部分

原文:https://towardsdatascience.com/cracking-blackjack-part-5-70bd2f726133?source=collection_archive---------27-----------------------

破解二十一点

完成首次访问蒙特卡罗算法

嗨!

如果您还没有这样做,请在继续之前阅读第 1–4 部分。本文的其余部分将假设您已经阅读并理解了前面的文章。

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

图片来自 Unsplash

这篇文章的大纲

  • 了解run_mc()函数如何简化算法。
  • 深入研究初诊 MC 算法的第 6 步,在这一步中,Q 表和概率表在每集之后更新。

第 4 部分首次访问 MC 的 10,000 英尺概述

  1. 从第 2 部分的中初始化 21 点环境。
  2. 定义第三部分中解释的 Q 表、概率表、α、ε、ε衰减、ε最小和γ。
  3. 定义您希望您的代理学习多少集。更多的情节通常会产生更有利可图的政策。
  4. 播放一集。记录剧集中所有的(**状态→动作→奖励)**元组。
  5. 剧集结束后,对ε应用ε-decay/ε-min。
  6. 然后,使用来自步骤 4 的(**状态→动作→奖励)**元组和相关公式更新 Q 表和概率表。
  7. 对于步骤 3 中定义的剧集数量,重复步骤 4-6。
  8. 在所有事件之后,产生的 Q 表和概率表代表了 AI 代理刚刚学习的 21 点的优化策略。

如何促进第 4-6 步

第 4 部分中,我们学习了如何在play_game()函数中实现步骤 4。在深入到第 5 步&第 6 步之前,我想介绍一下run_mc()函数,它允许第 4 步到第 6 步协同工作。

浏览下面的代码。我将在下面详细解释。点击查看完整的代码。

实现关键数据结构和值

run_mc()是明确定义 Q 表和 Prob 表的地方。

Q 表存储每个可能状态的每个动作的相对值(或 Q 值)。同样,状态由玩家的手牌值和庄家的上牌组成。

为了在 Python 中表示这一点,Q是一个二维列表,其中外部列表的每个索引对应于一个唯一的状态,每个内部列表是一个 2 元素的 Q 值列表,用于命中和站立在与索引对应的状态。

numpy.zeros()函数允许我们指定想要用来表示 Q 表的 Numpy 数组的形状,从而简化了这个过程。我们还希望所有的 Q 值都从 0 开始,以便在代理开始试验和探索选项时不会产生偏差。numpy.zeros()通过用零填充我们指定的 Numpy 数组来实现这一点。

根据我们在第 2 部分中的 21 点环境,env.observation_space[0].n是 18,代表可能的玩家手牌值(3–20),而env.observation_space[1].n是 10,代表可能的庄家升牌值(2–11)。env.action_space.n是 2,因为唯一可能的行动是打和站。

因此,可能的状态数为env.observation_space[0].n * env.observation_space[1].n,为 180。这意味着Q的外部列表有 180 个值。Q中的这 180 个值中的每一个都是一个大小为env.action_space.n(或 2)的内部零列表。

Q = np.zeros([env.observation_space[0].n * env.observation_space[1].n, env.action_space.n], dtype=np.float16)

我们以完全相同的方式定义 Prob-table(或prob ) ,除了每个值从 0.5(或 50%)而不是 0 开始,以确保每个动作在学习过程开始时有均等的机会被选中。

prob = np.zeros([env.observation_space[0].n * env.observation_space[1].n, env.action_space.n], dtype=np.float16) + 0.5

run_mc()也是第 3 部分中讨论的重要杠杆(ε、α和γ)被明确定义的地方。赋予每个值背后的原因将在下一篇文章中解释。

alpha = 0.001

epsilon = 1

decay = 0.9999

epsilon_min = 0.9

gamma = 0.8

步骤 4–6 协同工作

这几行代码概括了所有的步骤 4-6。

**for** _ **in** range(num_episodes):
    episode = play_game(env, Q, prob)

    epsilon = max(epsilon * decay, epsilon_min)

    Q = update_Q(env, episode, Q, alpha, gamma)
    prob = update_prob(env, episode, Q, prob, epsilon)

首先,我们使用第四部分中讨论的play_game()功能模拟一集。这是第四步

然后,我们将decay因子应用于epsilon,或者如果epsilon已经低于epsilon_min,就使用epsilon_min这是第五步

最后,我们使用update_Q()update_prob()更新我们的 Q 表和 Prob 表。episodeepsilon是这些功能的关键论据,而且每集都有变化。这是第 6 步

深入第 6 步

在我继续之前,祝贺你读到这里!你将要学习这个蒙特卡罗过程的最后,也是最重要的部分。你已经走了很长的路了!花点时间思考一下吧!

update_Q()

之所以称之为**“首次访问”** MC 算法,是因为我们有一种首次访问的方法来评估奖励。

“首次访问”意味着我们希望从一集第一次出现开始跟踪状态-动作对的奖励,然后使用该集的累积奖励来更新我们的Q-表中该状态-动作对的 Q 值。

另一个选项是**“每次访问”方法。在这种方法中,每当 在一集中出现时,我们使用状态-动作对的即时奖励来更新 Q 值。**

鉴于 21 点的形式以及我们如何设置我们的环境,对我们的问题使用每次访问的方法是没有意义的。

在我们的剧集中,除了最后的状态-动作对,状态-动作对的奖励都是 0。这是因为在 21 点回合(或插曲)的结果已知之前,21 点玩家(和我们的代理人)可能必须做出不止一个决定(意味着不止一个国家行动对)。

因此,如果我们强迫我们的代理在每个状态-动作对之后使用$0 的即时奖励来更新 Q 表中的 Q 值,我们的代理将不会有很大的改进。相反,我们将使用最终状态-动作对的奖励,并贴现它们,以近似同一集内先前状态-动作对的价值。

我们将使用以下公式为每集中的状态-动作对找到折扣奖励:

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

作者制作的图像

计算折扣奖励的示例如第 3 部分所示:

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

作者制作的图像

一个直观的例子:

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

作者制作的图像

**放在一起:**对于episode中的每个(状态→动作→奖励)元组,我们将使用状态-动作对的折扣奖励来更新Q表中相应的 Q 值。

以下是我们这一集遇到的每个状态-动作对的 Q 值变化公式:

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

作者制作的图像

update_Q()本质上为我们这一集看到的每个状态-动作对计算⍙ Q ,并将⍙ Q 加到当前 q 值上。实现如下。

下面是我们episode中每个状态-动作对的贴现奖励的计算。step在前面已经定义过了,本质上是我们公式中的 i 下标,它记录了我们正在分析的状态-动作对。

total_reward = 0
gamma_exp = 0
**for** curr_step **in** range(step, len(episode)):
    curr_reward = episode[curr_step][2]
    total_reward += (gamma ** gamma_exp) * curr_reward
    gamma_exp += 1

下面是⍙ Q 的计算,并使用它来更新我们的Q表中相应的 q 值。

*# Update the Q-value*
Q_state_index = get_Q_state_index(state)
curr_Q_value = Q[Q_state_index][action]
Q[Q_state_index][action] = curr_Q_value + alpha * (total_reward - curr_Q_value)

在学习过程的最后,我们可以简单地查看我们的Q-表,看看对于任何给定的状态,哪个动作具有更大的相对值。

update_prob()

请多花点时间消化update_Q()。如果你完全理解了update_Q(),那么update_prob()就轻而易举了!

为了刷新你的记忆,update_prob()调整了在我们的剧集中遇到的每个状态采取行动的概率分布。update_prob()update_Q()结束后被调用,因为 Q 值影响概率更新的方式,我们需要最新的 Q 值。

这次我将从代码开始,因为update_prob()的公式比简单得多。

update_prob()中,我们使用Q表来找出哪个动作(击打或站立)对于我们正在更新的状态具有更大的 Q 值。这是best_action

首先,我们调整给定状态下选择best_action的概率。⍙ 概率的计算公式如下(其中prob[Q_state_index][best_action]是选择best_action的当前概率):

⍙**Prob =** prob[Q_state_index][best_action] + 1 - epsilon

概率有可能超过 1(或 100%),所以我们更新prob表中的概率如下:

prob[Q_state_index][best_action] = min(1, ⍙**Prob**)

最后,我们将根据best_action的新概率更新other_action的概率:

prob[Q_state_index][other_action] = 1 - prob[Q_state_index][best_action]

更新这些概率很重要,因为这将影响我们学习过程中的探索利用动态(详见第 3 部分)。

学习过程开始时较小的⍙ 概率值确保了在best_action成为代理的主导选择之前需要一段时间。接近结束时较大的⍙ 概率值将最终导致best_action的概率为 100%,代理可以开始总是采取它认为是最优的决策。

下一步是什么

恭喜你。你现在知道“破解”21 点背后的所有科学!接下来,我们将深入到试验这种算法的艺术中,以找到可能的最佳 21 点回报!

感谢您的阅读!

我真的很感激任何形式的反馈!我想成为一个更一致、更有效的内容创作者。

你学到什么了吗?我很难理解吗?

欢迎在下面留言或发电子邮件给我,地址是 adithyasolai7@gmail.com!

本项目的 GitHub 回购。

用强化学习破解因果

原文:https://towardsdatascience.com/cracking-cause-and-effect-with-reinforcement-learning-f3df8dfcd525?source=collection_archive---------24-----------------------

使用强化学习来推断因果关系可能会打开机器学习的新领域,并可能避免另一个人工智能冬天

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

翁贝托Unsplash 上拍摄的照片

推断因果的困难无处不在。人类每天都面临这一挑战,并且在克服这一问题上做得非常出色,至少与我们的动物近亲相比是如此。Yoshua Bengio 等机器学习先驱甚至建议,创建可以推断因果的算法是避免另一个人工智能冬天和解锁机器智能新前沿的关键。在这篇文章中,我解释了强化学习是如何被重新构建来推断因果关系的,类似于我们人类这样做的能力,也许有一天会远远超过它。

对于那些不熟悉强化学习的人来说,它指的是用于确定顺序决策任务中的最优性的算法子集。它通常表现为一个代理人学习在一个环境中采取一系列行动来获得奖励。这些算法很容易应用于可以“游戏化”的问题,从而有明确定义的行动和奖励。最近,强化学习算法因在围棋、星际争霸和各种视频游戏中击败人类而广受好评。

这种强化算法取得成功的基本手段是通过连续的反复试验训练使预测误差最小化的概念。该方法相当准确地对应于人类多巴胺学习系统,该系统也利用预测误差。

有两个主要障碍使得推断因果关系成为一个难题,一个是复杂性,另一个是相关性。接下来我将解释强化学习如何被重新构建来解决这些问题。

如前所述,强化学习通常表现为一个主体在一个环境中为追求某种回报(比如赢得一场游戏)而做出一系列决策。代理可以采取行动,根据环境的状态,这些行动要么得到奖励,要么没有。当他们得到奖励时,代理将这种奖励传播回所有导致它最终获得奖励的行为和环境状态。通过多次试验,它可以确定哪些行为和环境状态的组合有助于获得奖励,哪些是多余的。从另一个角度来看,代理确定哪些行为和环境状态的组合与它获得奖励有因果关系,哪些没有。实际上,代理正在推断因果关于它自己的行为和环境的特定回报状态。

重要的一点是,从根本上说,RL 算法对于来说是不可知的,环境中的哪个组件是代理,哪个仅仅是对象。我们可以把环境中的所有对象看作可能的代理,把一个对象可能存在的所有状态看作它的动作集,而不是从代理、它的动作和环境的角度来考虑。这样,环境中给定的一组组件和特定的最终状态之间的任何因果关系都可以通过简单地改变哪个对象是代理以及被奖励的最终状态是什么来探索。

让我们用一个例子来解释这个问题。RL 的一个相当常见的演示是匹配样本任务,其中代理人(通常是一种小型毛茸茸的哺乳动物)必须学会采取一系列行动来获得食物奖励,例如,当灯亮时按下控制杆。经过训练,许多动物和人工智能机器人都可以解决这类任务。(参见强化学习代理解决样本匹配任务的附带视频)

现在想象我们是一个天真的社会科学家,不知道这个实验是如何设计的,并且希望知道是什么导致食物奖励被解锁。换句话说,我们想知道匹配样本任务背后的因果故事。回答这个问题的一个潜在方法是采用 RL 算法,该算法顺序地通过环境中的对象,将每个对象视为“代理”,并尝试查看该代理/对象是否可以采取一系列动作来最小化关于解锁食物奖励的预测误差。与打开食物碗的奖励状态有因果关系的对象将具有一些动作,这些动作允许它最小化关于该奖励状态的预测误差。一个没有因果关系的将没有这样的状态/动作组合,不管它的动作集合与奖励状态有多好的关联。

记住,在我们的重构中,动作只是指一个对象可以存在的不同状态。例如,我们可以以这样的方式提出这个问题,打开和关闭的灯是代理,它的动作也是打开和关闭的。如果在我们选择作为代理的任何对象的行为和我们想要理解的回报状态之间存在因果关系,那么也存在关于其行为空间的预测误差,该误差可以通过连续的训练集被最小化。换句话说,有一种方式,这个对象/代理可以因果地影响奖励状态。

解开环境中因果关系故事的一种潜在方法是迭代地移动环境中的对象,将它们视为采取行动的代理,并检查哪一个导致了关于奖励状态的可以最小化的预测误差。同样,与奖励状态没有因果关系或者仅仅与奖励状态相关的对象在其动作空间上将具有预测误差,该预测误差基本上是随机的,并且不会随着更多的训练集而减少。以这种方式,RL 提供了一种在算法上探测给定环境中的元素的因果关系的方式,依次将每个元素视为试图通过一些动作来改变其行为以便影响奖励状态的代理。

此外,预测误差减小的速率,通常被称为代理学习曲线,将给出一些指示,表明对象/代理与奖励状态的因果距离。虽然蝴蝶扇动翅膀可能会在地球的另一边引起飓风,但是与最小化关于更接近的原因的预测误差所需的训练集的数量相比,预测这种情况所需的训练集的数量将是天文数字。因此,在所有其他条件都相同的情况下,学习曲线在衡量相对因果接近度方面非常有用。

有许多假设和限制适用于这种方法,即所有那些适用于强化学习本身。它还假设我们有一种方法来评估环境中每个代理/对象的动作空间,并且这满足马尔可夫特性。在匹配样本任务的例子中,环境中的每个对象都有一个小的明确定义的动作空间。对于具有大的或连续的动作空间的对象,探索因果关系可能变得难以计算。同样值得注意的是,这个用于推断因果关系的系统只适用于可以产生大量样本试验的情况,正如 RL 本身只适用于“自我播放”允许大量训练集的情况。虽然这可能是一种探索因果关系的计算密集型方法,但随着计算成本的降低,越来越多的环境可以通过这种方法接近。

科学的持久挑战之一仍然是确定复杂系统中的因果关系。例子包括人类基因组,其中无数的基因和环境因素促成了特定的表型。在这种情况下,因果关系可能很难推断,这种方法可能有助于揭示哪些"行为者"或国家有助于实现特定成果。它还向能够“解释”用于确定特定行动过程的因果推理的代理人开放了人工智能领域。另一个潜在的应用是生成先验知识,通过这些知识,人工智能可以存储以前推断的因果关系列表,并在遇到挑战性问题时将它们应用到新的行动空间。这种先验知识可以极大地减少成功完成一项任务所必需的训练,并可能导致人类所展示的一次性学习。

破解数据科学面试

原文:https://towardsdatascience.com/cracking-the-data-science-interview-3ef62653eafc?source=collection_archive---------29-----------------------

重点是技术问题

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

图片鸣谢:https://www . datanami . com/2018/09/17/improving-your-odds-with-data-science-hiring/

技术问题

问题有几个类别,根据你面试的地点,问题的难度会有所不同。这篇文章的目的是介绍这些类别,并强调一些相关的问题。讨论的问题来自 https://datascienceprep.com/的,涵盖了顶级科技公司的面试问题。

可能性

问这些问题是为了证明你理解概率的基本原理。常见主题包括:联合概率和条件概率以及概率的各种规则和定理(乘法法则、包含-排除等。)很多时候,它们纯粹是技术性的“脑筋急转弯”问题,可能与特定产品有关,也可能无关,其难度从容易的一端(a)到困难的一端(b)不等。

示例:

a)假设您正在推出一项新功能 X。你有 1000 个用户,每个用户要么是 X 的粉丝,要么不是。1000 个用户中有 50 个不喜欢 x。你将在独立抽样 5 个用户的基础上决定是否发布该功能,如果他们都喜欢该功能,你将发布它。您发布该功能的可能性有多大?

B)有两组 n 个用户,A 和 B,A 中的每个用户都是 B 中的用户的朋友,反之亦然。A 中的每个用户将随机选择 B 中的一个用户作为他们的好友,B 中的每个用户将随机选择 A 中的一个用户作为他们的好友。如果两个人都选择了对方,那就是相互最好的朋友。不会有互相最好的友谊的概率是多少?

统计数字

这些问题旨在测试您的基本统计基础——虽然通常不直接适用,因为您通常不会从头开始编写 A/B 测试,但更多的是为了让您可以在必要时调整实验,并理解和解释结果。常见的主题包括各种分布,中心极限定理和大数定律,假设检验,等等。这些问题从更多的“脑筋急转弯”(a)到更多的与产品相关的开放式问题(b),前者需要以简洁的方式应用统计概念。

示例:

a)您可以玩两种与骰子相关的游戏。在第一场游戏中,你同时掷出两个骰子,并获得与掷骰子的结果相等的金额。在第二个游戏中,你掷出一个骰子,得到相当于该值平方的金额。哪个期望值更高,为什么?

b)你如何决定一个实验进行多长时间?仅使用固定的 p 值阈值存在哪些问题,您如何解决这些问题?

产品

产品问题是专门为手头的公司设计的,为了衡量你对一个很可能与公司相关的特定主题的直觉。因此,重要的是要始终适应你面试的公司,以及他们生产的产品类型和跟踪的指标。通常,主题将包括从比较和对比平台(a)到理解特性变化如何影响特定指标(b)的任何内容。

示例:

a)想象一下脸书和推特的社交图。它们有什么不同?你会用什么标准来衡量社交图表的偏斜程度?

b)你的团队正在试图弄清楚一款具有额外 UI 功能的新司机应用程序是否会增加乘车次数。你如何测试应用程序中的额外功能是否使它比原始版本更好?

编码

由于数据科学需要精通编程,这里的编码在风格上类似于你可能找到的软件工程角色的面试水平。常见的主题包括数组、链表、字典,并经常利用基本算法,如 BFS 和 DFS。

示例:

a)给定一个数 n,返回连续正整数列表的个数总和为 n,能在线性时间内完成吗?

b)你有一个完整的用户社交图,节点代表用户,边代表用户之间的友谊。给定图的边和节点数,写一个函数返回两个用户之间的最小数量的友谊。

结构化查询语言

与编程类似,数据科学需要 SQL 技能来快速查询和分割数据。这些通常很简单,涉及基本原理,偶尔也涉及窗口函数。和产品问题一样,它们往往相当实用。

示例:

a)假设您在 app analytics 上有一个事件表。写一个查询,得到 2019 年每个 app 的点击率。

b)假设您有用户拥有的会话表和一个用户表。编写一个查询来获取每日群组的活动用户计数。

机器学习

虽然并非所有数据科学职位都直接或间接利用机器学习,但如果你正在寻找更高级的数据科学或机器学习工程职位,那么在应用和理论方面都有良好的熟练程度肯定会有所帮助。根据你面试的公司,这里的话题会有很大的不同,因此问题的范围可以从针对特定应用的更面向产品的问题(a)到更具体的理论问题(b)。

示例:

a)假设您需要为欺诈检测生成一个二元分类器。您会查看哪些指标,每个指标是如何定义的,每个指标的解释是什么?

b)假设我们正在运行一个概率线性回归,它很好地模拟了一些 y 和 x 之间的潜在关系。现在假设所有输入都添加了一些噪声,这与训练数据无关。新的目标函数是什么?你是怎么计算的?

感谢阅读!

如果你有兴趣进一步探索不同类别的面试准备问题,请查看:https://datascienceprep.com/

制作一个机器学习模型,使用 R

原文:https://towardsdatascience.com/crafting-a-machine-learning-model-to-predict-student-retention-using-r-5eb009dcb1ec?source=collection_archive---------23-----------------------

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

图片由 education_freeFreepik 上拍摄

建模一个 ML 实验来预测 R

学生保留率是高等教育中最重要的指标之一。因此,预测分析在这方面发挥着至关重要的作用。

首先,让我们从定义什么是学生保持开始,至少在本文的范围内。我们将把它定义为一个指标,它告诉我们,一个在某个特定的秋季学期第一次进入大学的学生,是否会在下一个秋季回来(或不回来)。例如,假设一名学生在 2018 年秋季第一次开始上某所大学。如果这名学生报名参加了 2019 年秋季课程,那么这名学生将被保留

保留的另一个常见名称是,持续,和/或退出。在这里,这些名字的意思是一样的:一年本科留级。此时,读者可能会问,“为什么学生保留率无论如何都很重要?“这是一个很好的问题,我们没有必要穷尽这个答案,我们可以说这很重要,原因有很多,首先是财务影响、学校可以获得的排名和声望,还有很多。顺便说一下,当我们在这里说“学校”时,我们特指大学和学院(高等教育)。

寻找合适数据集的挑战

找到一个学生级别的数据集是非常困难的——如果你有一个,想发给我,请这样做,但它必须是匿名的。这意味着,没有学生的姓名或 ID,或任何其他信息,使研究人员能够识别学生——特别是,当我们有适当的法规,保护学生的数据,如 FERPA。这是一件大事,我们在处理敏感信息时必须非常小心。

也就是说,明确地为这个实验定位正确的数据集,确实是一个挑战。然而,积极的一面是,我们设法找到了一个可以使用的数据集,这就是我们将在这里操作的数据集。你可以在 UCI 机器学习资源库找到,点击这里就可以了。

为了使用这些数据,我们需要进行适当的引用,请参考本文的“参考资料”部分。另外值得一提的是,为这些研究者提供了这个数据集。谢谢你。

棍子和石头

虽然我们发现了这个数据集,但事实是,对于机器学习(ML)项目来说,它实际上是一个小数据集,除此之外,我们稍后会看到,变量在大的事物方案中并不真正相关。所以,最终,ML 模型可能会有一个很差的性能。我们会继续讨论这个问题。

另一个需要强调的重点是,最初,这个数据集是用来预测学生的表现[1],而不是保留。有趣的是,数据集具有有趣的特征,但在预测性能[1]和保留时没有相关的意义。我在这里的意思是,尽管我们有几个变量,但基本上,只有很少一部分能告诉我们历史。

我们实验的布局

我们将在这里运用大量的创造力。注意,原始数据是关于高中学生的。但是对于这里,我们假设那些学生是大学生。此外,我们必须创建并整合一个名为“”的新功能,该功能是随机创建的,用于模拟学生是否被保留。显然,这对模型有负面影响,因为这实际上是我们的预测变量*——而且是随机的。*

尽管如此,进行这个实验的主要目标是提供一个可用的机器学习管道,特别是使用正确的数据集,以利用高等教育中的学生保留率。我希望这个 ML 项目可以帮助这方面的管理者和研究者。下面是我们如何将我们的任务分成如下四个主要阶段:

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

图 1 —主要阶段概述

  • 第一阶段:数据管理

在这一阶段,我们将寻找缺失的数据,并熟悉数据集。奇怪的是,我们在这里没有发现任何缺失的数据。虽然有人可能认为这很好,最终也确实如此,但这也让我们思考,在我们使用这个数据集之前,是否进行了一些插补。这里有一个提示:当您决定输入缺失值时,请记录下来,将缺失值留在原始列,将插补值留在新列。此外,如果您刚刚放弃,请说明使用了哪种技术来输入值。通过阅读与该数据集一起使用的原始文章,我们得出的结论是丢失的数据被遗漏了,我们得到的是实际的响应,这意味着我们没有丢失的值。

  • 第二阶段:探索性分析

在不知道哪些变量在特定数据集中真正相关的情况下,我永远无法理解那些执行“探索性分析”的人。不要到处乱画图表。有一些最初的假设是没问题的,但是你应该总是试图弄清楚什么特征对于你正在试图研究的东西是重要的。所以,我们的一些图表是基于我们发现的相关的和我们想看到的,但主要是基于对数据集的科学理解。

  • 第三阶段:降维

在我看来,最重要的一步。特别是,因为这个数据集非常小,而且有相当多的变量。在这里,我们将寻找多重共线性,以及如何消除变量。我们将使用逻辑回归来剔除不相关的变量。除此之外,我们还将执行 PCA (主成分分析),目的是找出相关特征。

  • 第四阶段:机器学习

这就是我们执行 ML 建模并获得惊人结果的部分,对吧!?事实证明,这一阶段相当具有挑战性,我们稍后会谈到这一点。但我们在这里使用的一些技术是使用 ROSE [2]库来平衡预测值,评估 AUC(曲线下面积)和 ROC 曲线,并检查多个算法的准确性kappa 分数,以便检查每个算法对该数据的最佳效果。

最坏的情况:假设得到一个低性能的机器学习模型

小数据集往往会给 ML 算法带来挑战。尤其是当特征并不真正重要,并且预测因子是人为创建的、随机的且不平衡时。真是一场灾难啊。!

考虑到这一点,甚至在实际开始使用该数据集之前,我们就提出了以下假设,但不限于此:

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

图 2 —低性能的假设

上面我们可以看到六个主要假设和它们的一些原因。由于时间关系,我们不会在这里一一介绍,但是在编码和开发模型时,我们会尽可能地减轻它们的影响。请注意,不平衡和随机分类器问题是为此项目创建的,它们不是原始数据集的一部分。

请记住,我们预测这些问题的原因与我们人为创建了一个名为 retention 的新功能有关,该功能根据赋予它们的权重,对二进制值(1 或 0)进行随机排序。

为了说明这一点,我们使用的数据集中的学生总数仅为 649 人,在创建这个人工预测值时,我们说大约 85%的学生将被标记为“保留”(二进制指标为 1),大约 15%的学生将被标记为“未保留”(二进制指标为 0)。这几乎是公立学院/大学的平均保留率。

弄脏我们的手:是时候编码了!

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

Sarinya9940Freepik 上拍摄的照片

我们使用名为 R 的统计和开源应用程序来执行这项任务。并且,为了使它在视觉上更吸引人(这是我们的希望),我们不会在这里显示所有的代码,但是您可以在如下所示的链接中找到所有的代码。

所有代码和文件都可以在我的 GitHub 页面的 这里找到

同样,我们将把这一动手部分分解成我们之前看到的四个阶段。事不宜迟,让我们从头开始:

阶段 1:数据管理

同样,你可以在 UCI ML 知识库中找到原始数据集和论文。但是,这里有一个所有变量的快照:

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

表 1-预处理的学生相关变量。该表摘自原始论文[1]。

请记住,我们之前谈到的保持力变量是人为插入到该数据集的,目的是模拟学生保持力的预测模型。你在这张表中看不到,但在 R 代码中可以看到。还有两个数据集可用,一个是数学数据集,一个是葡萄牙语数据集。我们将只使用葡萄牙语的,因为这是一个有更多学生(649)的。文章[1]将数学和葡萄牙语合并到一个集合中,但是样本量更小。

阶段 1* 的主要目标之一是创建人工变量,熟悉该数据集,并检查缺失值。*

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

图 1 —缺失值

正如我们在图 1* 中看到的,该数据集中没有缺失值。事实上,我们以前已经说过了,但这里有证据。请注意,我们在该图中添加了保留值变量。*

此外,我必须为数据集中的一些变量创建伪变量,这些变量不是伪编码的。在该处理结束时,可以使用提供的 R 代码导出一个新的 csv 文件,其中包含虚拟代码、数值和预测值。

既然我们已经开了绿灯,数据集也准备好进行初始评估,我们就可以进入下一步了。

阶段 2:探索性分析

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

照片由 Freepik 上的 sema_srinouljan 拍摄

这就是人们疯狂绘制直方图和箱线图的地方,不是吗?!他们是必要的,不要误解我。我们一会儿就会看到其中的一些。此外,您还可以在 R 代码上检查诸如偏斜度*、峰度等基本的统计检查表。*

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

图 2 —保留计数(保留= 1.0,未保留= 0.0)

在这个简单的条形图中,我们可以看到预测变量的计数,根据我们在创建这个人工预测器时为它们设置的权重。

如前所述,保留的学生标记为“1”(538),未保留的学生标记为“0”(111)。

最终,它也显示了分类器之间的不平衡,我们将在后面处理。

在最初的文章[1]中,变量“G1”是学生表现的一个非常强有力的预测因素。下面的散点图告诉我们一年级(G1)和期末(G3)之间预期的正相关关系。我们还可以发现一些潜在的异常值。

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

图 3 —散点图 G1/G3

继续这个分析,我们有兴趣看看什么会影响学生在 G1 的表现。为此,我们重点检查了学习时间*,以及学生可用的空闲时间,并按性别进行了细分。*

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

图 4-标准化平行坐标图

好吧,我投降!在这里,我想出了一个所有变量的方框图。我们可以很容易地在这里看到异常值的存在,并快速思考是否要处理这个问题的一些选项。对于这个测试,我们不会排除异常值。

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

图 5 —所有变量的箱线图

再一次,我想给变量 G1 一些关注,所以让我们检查它的分布如下:

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

图 6 —可变 G1 的直方图/箱线图

考虑到这是真实世界的数据,它的分布真的不算太差。但是,它显然并不完美。

作为第三阶段的总结,我们只想再检查一件事。也就是说,当将学生添加到二元图中时,G1 和 G2 变量是如何相互作用的,如下所示:

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

图 7——G1 和 G2 变量的二元图

把这个二元图想象成一个普通的箱线图,但是混合了两个变量而不是一个。具体来说,蓝色的数字可能是学生 ID(这里不是这样,因为我们在数据集中没有学生 ID)。任何在大椭圆之外的学生都是离群值。这可能有助于确定我们应该联系哪些学生,以便采取一些积极的行动,比如说,提高他们在 G3 上的成绩。

阶段 3:降维

这就是乐趣的开始。一个好的做法是始终检查数据集中的共线性/多重共线性。最简单的方法是检查自变量和因变量之间的相关性。如果两个或更多变量具有非常强或几乎完美的相关性,这可能是共线性/多重共线性的迹象。

当面对两个或更多变量具有强相关性的场景时,我们希望消除其中一个变量。为什么?因为本质上,你有两个变量告诉你同一个故事。但是说得更专业一点,共线性可能会扰乱至少一个估计回归系数的方差,这可能会导致一些回归变量得出错误的符号。这会影响你的分析并把你引向错误的方向。

让我们用下面的相关矩阵来看看是否能发现一些问题:

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

图 8——所有变量的相关矩阵

这里有一些有趣的相关性,但主要是关于等级(G1、G2 和 G3)。它们似乎有很强的相关性,表明存在潜在的共线性。我们也看到成绩和失败之间有很强的负相关性,还有其他一些特征。您总是可以使用相关表来检查实际数字,或者直接在图上添加它们。现在,我们只想对变量之间的关系有一个大致的了解。

主成分分析(PCA) 用于将原始变量塑造成一组新的特征,这些特征是原始变量的线性组合。主成分分析的主要目标是减少变量的数量,但尽可能考虑原始变异。

在第一个分量或维度中,您将看到原始变量的组合,其样本方差在所有可能的线性组合中是最大的。在第二维中,我们考虑剩余方差的最大比例,它可以与第一维不相关。其他组件遵循类似的方法。

当分析运行 PCA 的输出时,我们希望看到一维和二维之间的“累积比例”,这是有意义的。一般来说,累积比例等于或大于 0.7 被认为是非常好的。也就是说,从多个变量缩减到两个维度仍然可以很好地代表整个数据集。

在执行 PCA 之前,一件重要的事情是确保数据集是标准化的。在这一点上,决定是否移除异常值也是一个好的做法。

为了使用 PCA 开始我们的分析,我们将从一个条形图开始,它显示了所有成分之间的累积比例以及它们的方差。

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

图 9——五氯苯甲醚累积比例

本质上,我们特别感兴趣的是将我们的分析缩小到前两个维度。我们希望确保它们之间的累积比例足以“解释”数据集的其余部分。

不幸的是,正如你将在下一张图中看到的,累计比例仅为 21% (12.9% + 8.1%)。因此,减少到两个维度是不推荐的,因此,我们将丢失信息,并最终得到两个不能“解释”数据集的维度。

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

图 10—尺寸 1 和尺寸 2 的 PCA 双标图

从双标图中,我们还可以看到变量之间的相关性,例如等级(G1、G2 和 G3)和指向相反方向的故障*。虽然两个维度的累积比例在归结到该数据集的维度减少时并不真正有用,但我们希望检查每个维度的前十个变量的贡献。这可能有助于我们更好地理解这个数据集。*

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

图 11-Dim 1 和 Dim 2 的 PCA 贡献

我们可以看到,在 Dim 1 中,等级是该维度贡献最大的变量。但是,需要强调是,这里仍然存在共线性假设。所以这是又一个线索,事实上,我们在这里可能有共线性,因为我们看到所有的等级都有非常相似的贡献水平。另一方面,在 Dim 2 中, Walc 特性的贡献最大。

总之,如果有人问 Dim 1 和 Dim 2 是关于什么的,我们可以说 Dim 1 是关于学生成绩的,Dim 2 是关于学生饮酒量的。这意味着,在预测保留率时,我们应该预期这些变量中的一些具有统计显著性*。*

所有这些测试在指导我们决定哪些变量应该保留,哪些变量应该忽略时都非常有帮助。不幸的是,我们还不能使用 PCA 来做任何决定。

回过头来看,我们有共线性的假设仍然存在,但是如何测量它,以及如何决定去掉每个变量?

鉴于对这一问题的认识,并考虑到这一点,我们将利用 VIF(可变通货膨胀系数)来检测并支持我们在处理多重共线性时采用最佳方法的决策。简而言之,VIF 检测变量之间的相关性有多强,它的分数指导我们在每个变量上降低和减轻共线性。

根据一般经验,VIF 分数等于或大于 5 表示共线性。我们在这里也将使用 5 作为阈值。正如我们在下面看到的,基于逻辑回归的 VIF 输出告诉我们,G2 和 G3 是我们在进一步分析中应该忽略的变量。

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

图 3 — VIF 输出

通常情况下,您应该去掉当时的一个变量,然后再次运行分析。也就是说,G2 是第一个离开的,G3 是第二个。这里有一个图形化的方法来显示移除这两个变量(G2 和 G3)之前和之后的情况:

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

图 12-在阈值 5 处检测到共线性(左侧)。未检测到高于 2.5 的共线性(右侧)。

作为所有这些争论的结果,我们只是去掉了两个变量。从某种意义上说,这并不是真正有成效的。我们仍然有一个相当大的功能集,它并没有告诉我们要做什么。因此,我们的捷径将是使用逻辑回归,不仅帮助我们找到预测,而且消除非统计意义上的变量。

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

图 4 —逻辑回归输出

正如从 Logit 回归输出(在左侧)中注意到的,我们有五个变量可以作为预测因子。

然而,其中只有三个在 0.05 处有显著性,我们用红色箭头标出。

**R 平方是一些研究人员在选择模型时可能使用的一个常用指标。这里,我们将只使用 AIC(赤池信息标准)分数来比较具有 5 个变量的输出和具有 3 个变量的输出。

正如你在下面看到的,消除两个不太重要的变量并不会对 AIC 分数产生太大影响。

  • 所有五个统计显著变量:AIC: 589.84
  • 所有三个统计上显著的变量在 0.05:AIC:589.67 米

是的,整个数据集的 AIC 更大(622.4),但因为它充满了并不真正有用的要素,我们在这里绘制了这条曲线,并决定在下一阶段只处理这三个变量。

第四阶段:机器学习

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

Freepik铜管的照片

考虑到我们到目前为止所面临的所有挑战,在建模 ML 模型时可能会出什么问题呢?糟糕的性能模型可能会出错。但是,我们希望得到最好的结果,至少是一个公平的模型。

也就是说,我们在这里必须是真实的,ML 非常适合大型数据集。但是经过一些调整,我们可以让它工作。在这种情况下,我们将利用名为 ROSE 的库来平衡预测器并提高模型的性能。

最初,我们的预测器是这样分割的:1= 538,0= 111。你可以清楚地看到,我们有一个不平衡的分类器。我们将人为地平衡它,以改善结果,并减轻随之而来的一些统计问题。然而,我们将对列车拆分的数量进行评估。因此,我们的列车车组共有 553 名学生,其中:1= 458,0= 95。换句话说,我们现在将平衡训练数据,而不是整个数据集。

ROSE 提供了一些不同的选项来平衡分类器。我们将涵盖 4 种不同的方法,并选择一种给我们最好的结果。下面是我们从论文《ROSE:二进制不平衡学习的一个包》[2]中借用的代码。

*### Balancing the data:
**# Resampling Option 1 (over):**
data.bal.ov <- ovun.sample(retention ~ ., data = trainSplit, method = "over", p=0.5, seed = 2)$datatable(data.bal.ov$retention)**# Resampling Option 2 (under):**
data.bal.un <- ovun.sample(retention ~ ., data = trainSplit, method = "under", p = 0.5, seed = 2)$data

table(data.bal.un$retention)**# Resampling Option 3 (both):**
data.bal.ou <- ovun.sample(retention ~ ., data = trainSplit, method = "both", N = 553, p = 0.5, seed = 2)$data

table(data.bal.ou$retention)**# Resampling Option 4 (ROSE):**
data.rose <- ROSE(retention ~ ., data = trainSplit, seed = 1)$datatable(data.rose$retention)*
  • 重采样选项 1 (over): 这里我们对“0”进行过采样,直到它与“1”的计数持平。因此,我们将分类器平衡如下:1= 458,0=453。
  • ***重采样选项 2(下)😗通过对多数类(1)进行欠采样以匹配少数类,我们得到这个结果:1=97,0=95。
  • ***重采样选项 3(两者)😗在这种情况下我们使用整个 train 集合(553)并拆分,比如:1=281,0=272。
  • 重采样选项 4 (ROSE): 最后我们用 ROSE 来拆分数据,得到了这个结果:1=293,0=260。

接下来,我们训练分类器,使用分类树运行测试集,并绘制 ROC 曲线。

*# Training the Classifiers and run test set using classification trees:
library(rpart)
tree.ov <- rpart(retention ~ ., data = data.bal.ov)
tree.un <- rpart(retention ~ ., data = data.bal.un)
tree.ou <- rpart(retention ~ ., data = data.bal.ou)
tree.rose <- rpart(retention ~ ., data = data.rose)# Predict in the new data (test):
pred.tree.ov <- predict(tree.ov, newdata = testSplit)
pred.tree.un <- predict(tree.un, newdata = testSplit)
pred.tree.ou <- predict(tree.un, newdata = testSplit)
pred.tree.rose <- predict(tree.rose, newdata = testSplit)# Plot ROC Curve - Model Evaluation:
roc.curve(testSplit$retention, pred.tree.rose[,2], col = 0, main= "AUC: 0.75", lty = 1)
roc.curve(testSplit$retention, pred.tree.ov[,2], add.roc = TRUE, col = 12, lty = 2) 
roc.curve(testSplit$retention, pred.tree.un[,2], add.roc = TRUE, col = 0, lty = 3) 
roc.curve(testSplit$retention, pred.tree.ou[,2], add.roc = TRUE, col = 0, lty = 4)*

***重采样选项 2(下)*为我们提供了最佳 AUC(曲线下面积)输出。见下文:

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

图 13 —重采样选项 2 的 ROC 曲线(下)

AUC 是一种算法,广泛用于测量所述 ML 分类器的真阳性(TP)率和假阳性(FP)率之间的权衡。

同样地,预测失败的模型得分为 0%,而能够做出“完美”预测的模型得分为 100%。

相应地,我们的模型得分为 75%,这还不算太差,但是一个≥80%的数字会更好。

从积极的一面来看,使用 ROSE 包给了我们一个巨大的改善。所以,我们会庆祝这是一个巨大的胜利。耶!

衡量分类器的另一个非常常见的方法是通过决策树,这将使我们对模型的表现有更多的直觉。这里我们将跳过这一步,转到 ML 分析的下一步,也是最后一步。

通过准确度和 Kappa 选择机器学习模型

很多人依靠准确性来选择 ML 模型。仅仅这一点可能会引起误解,但是因为这是一个非常 【快速和肮脏】 类型的项目,我将允许我自己尝试一下。

  • ***准确性:*它基本上指出了被正确标记的“1”和“0”的比例。
  • Kappa: 告诉我们与随机分配的值相比,分类器的性能。

下面是我们处理这部分分析的方法:我们将再次使用 ROSE 来平衡整个数据集(649 行)。这次我们不会在训练测试之间拆分,那是因为集合非常小。我们将利用我们拥有的一切。

类似地,我们将使用下面的代码来平衡预测值,但是正如您将看到的,我们人工复制了多达 1298 个观察值的数据集,并且在这里使用了“both”方法。

*# Create balanced training data for LR:
dataC <- ovun.sample(retention ~ ., data = dataC, method = "both",
                        N = 1298, seed =1)$data # 1298 (649x2)
table(dataC$retention)*

因此,我们得到了新的平衡分类器,例如:1=652,0=646。现在,我们将使用“ mlbench ”库来运行几个不同算法之间的基准比较,以查看每个算法是否具有最佳性能。

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

图 14-箱线图 ML 模型选择。你可以在这里找到源代码

正如我们在上面看到的,这种分析的“最佳”算法是 svm (支持向量机),其准确率接近 70%,而 kappa 为 39%。这些是公平的结果,但肯定不是最佳的。

请记住,在选择实际用于生产的每个型号时,必须考虑许多其他因素,而不仅仅是准确性得分。为了我们试图完成的目的,我们的 ML 分析到此结束。

最后的想法

总之,你看到三个主要的预测器是 Medufamsup_yesDalc 。下一步将是从 Logit 回归中获得优势比,并使分析更具可解释性。我将把它留给将来的改进,以节省我们的时间。

提醒一下,我们这里的目标是提供一些如何使用多种技术来处理小数据集并获得相当好的结果的指南。有许多其他方法来解决这个问题,这里我们提供给你一个可靠的方法——使用真实世界的数据集。

有了一个设计更好的适合预测保留的数据集,有了更多的观察,我们当然可以期待有更好的结果。该分析就是为此目的而创建的。

最终,保留率是高等教育中最重要的指标之一,这一管道有助于进一步研究这一主题,并有助于管理员根据数据做出更好的决策。

下次见!

参考资料:

[1] P .科尔特斯和 a .席尔瓦。使用数据挖掘预测中学生成绩。在 a .布里托和 j .特谢拉编辑的。,第五届未来商业技术会议论文集(FUBUTEC 2008)第 5–12 页,葡萄牙波尔图,2008 年 4 月,EUROSIS,ISBN 978–9077381–39–7。

[2] Nicola Lunardon、Giovanna Menardi 和 Nicola Torelli。ROSE:Binay 不平衡学习包。R 杂志第 6/1 卷,2014 年 6 月。国际刊号 2073-4859。

[3] Whitlock,Joshua Lee,“使用数据科学和预测分析来了解 4 年制大学学生流失”(2018)。电子论文。3356 号文件。https://dc.etsu.edu/etd/3356

CRAIG:客户评论分析洞察生成器

原文:https://towardsdatascience.com/craig-customer-review-analytical-insights-generator-676fd1d76ffe?source=collection_archive---------69-----------------------

使用 NLP 和 TextBlob 分析客户评论的情感指标

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

杰里米·蔡在 Unsplash 上的照片

你好!希望大家在疫情爆发期间保持安全和健康。

今天我想分享一个有趣的项目,是我的团队在 Gesture 做的。对克里斯多佛·里吉奥梅格娜·穆拉利哈兰的快速大喊,感谢他们成为令人敬畏的团队成员。

在衡量公司业绩或评估公司底线指标时,CRAIG dashboard 不是高管们日常使用的仪表盘,而是一种创新而实用的数据应用,用于推动行为分析。该项目旨在通过分析我们公司产品的评论来更好地了解客户体验,并确定产品中可能代表趋势或洞察力的方面。

不用说,评论是企业衡量产品和服务表现的一种重要方式。通过它们,我们可以确定哪些因素推动了好的和坏的客户体验,并允许公司有改进的空间。通过分析 Yelp 和 Google Places 等在线业务平台上存在的大量客户评论,公司能够调整其产品和服务,以更好地满足客户的需求,从而提高保留率和积极的品牌知名度。

在按需礼品交付应用程序 Gesture 中,我们利用自然语言处理和数据辩论技术,使用客户评论分析洞察生成器 CRAIG 来洞察产品评论。有了 CRAIG,我们可以在粒度和聚合级别上更深入地了解单个客户的体验。通过提取和分析来自 Yelp 的产品评论,CRAIG 建立了实际应用程序来帮助各部门的工作,例如:

  • 根据评论向 Yelp 客户进行个性化营销推广
  • 基于顾客偏好和推荐的 SKU 新产品构思
  • 与积极和消极情绪相关的手势产品和类别分析
  • 对竞争对手和潜在合作伙伴的洞察

那么,CRAIG 有哪些功能呢?

  • 正负关键词跟踪系统
  • 对客户情绪的趋势洞察
  • 具有搜索功能的评论
  • 洞察推动客户体验的因素

为了提供一个直观的分析,这里是克雷格的样子。

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

CRAIG(一个 2x2 的自动化 Tableau 仪表板)

我们从 Yelp 网站上收集了来自加州、伊利诺伊州和纽约三个州的花店和纸杯蛋糕店的超过 20,000 条评论。收集数据的脚本是通过谷歌云功能按计划触发的,在这里数据被抓取、清理并安全地加载到我们的谷歌云平台上。

正面关键词

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

肯定关键词图表是按计数频率对最肯定关键词的直观表示。它显示增加评论平均评分的关键词(二元模型和三元模型的组合)。每个条形的颜色表示情绪-颜色越暗,包含该关键字的评论越积极,颜色越暗,包含该关键字的评论越消极。

这些发现验证了我们的直觉,即的客户服务对于一个健康且表现良好的企业来说绝对至关重要,评级良好的企业极有可能被推荐给他人。最后一分钟送货也很重要,这也是 Gesture 努力成为按需送货服务,在一小时内将礼物送上门的原因。

如果你想知道数据是如何被清理的,评论需要一些预处理步骤,包括单词的小写,删除标点符号和停用词,评论的标记化和词条化。通过使用 TextBlob 包和基于位置(州)和日期的过滤来生成 ngrams。

负面评论

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

负面关键词图表遵循与正面关键词相同的结构,但显示的是导致负面评价的负面关键词。图表上的颜色是较浅的蓝色,表明积极情绪比积极评价中观察到的情绪要少。

我们看到交付是差评中的一个常见问题,在这种情况下,客户因服务不满意而不得不打电话回来,或者产品没有按时交付或根本没有交付。黄玫瑰似乎也不是受欢迎的选择。

按情感和评级的关键词

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

“按情感和评级列出的关键字”图表是一个可视报告,允许用户按情感和评级发现关键字。这两个参数呈正相关,特定评论的评分值越高,客户对其体验的评价就越积极。每个圆圈的颜色在 CRAIG 的所有网格中保持一致,每个圆圈的大小对应于计数。圆圈越大,该关键词在整个评论语料库中被提及的频率就越高。

搜索评论

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

最后一个网格是所有评论、供应商和作者的数据库,用户可以通过在搜索框中输入关键字来搜索任何评论。它还可以选择导航到第一列中的每个用户配置文件。

克雷格到此为止。CRAIG 旨在将所有客户评论集中到一个仪表板中,提取来自社交渠道的数据,并允许企业更好地与客户互动。感谢您的阅读,祝您有美好的一天!

用 Libra 创建一个复杂的机器学习模型

原文:https://towardsdatascience.com/create-a-complex-machine-learning-model-in-one-line-with-libra-a253e05d15a1?source=collection_archive---------51-----------------------

非专家使用的一行建模查询

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

韦斯·希克斯在 Unsplash 上的照片

在最近一段时间,有许多与数据相关的项目爆炸,尤其是以机器学习为骨干的项目。在商业行业项目中,许多机器学习被应用于创建预测模型(预测事件、搅动、欺诈等)。).

所有机器学习的问题是,我们需要学习复杂的代码,结果有时对于非专家来说太复杂了。

基于以上原因,现在有一个面向非专家的机器学习 python 包叫做 Libra 。这个包的前提很简单:**他们优先考虑易用性和人体工程学;**意思是用尽可能少的行创建一个机器学习模型。

那么,这个天秤座套餐到底是什么?根据他们的说法,它是一个机器学习 API,让我们只需一行代码就可以构建和部署机器学习。多整洁啊!

此外,目标检测、预处理和评分是默认完成的。我们只需要选择模型并输入数据。

让我们试试它是如何工作的。

在我们安装 Libra 包之前,我们需要安装 Python 3.6 或更高版本。任何低于这个数字的都不行。要安装这个包,我们只需要在命令提示符下运行下面的代码。

**pip install libra**

在你安装完这个包之后,我们会尝试这个包是如何工作的。让我们准备好所有需要用到的东西。首先,出于我们学习的目的,我将使用来自 Kaggle 的关于教育的数据集这里是。下图是数据信息。

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

现在,假设我们想要创建一个预测模型来对类列进行分类。利用天秤座,一切都变得简单了。

#The only thing we need to import**from libra import client**

在 Libra 中,数据集仍然需要从外部读取;比如说 CSV 文件。这就是为什么我们要创建一个直接读取文件的客户端类。

#Creating a client object that read the data to create the prediction model**edu_client = client('xAPI-Edu-Data.csv')**

上面的代码是我们所需要的;下一部分更像是以我们想要的方式查询模型,并立即得到结果。

目前,Libra 中唯一的机器学习模型是:

  • 神经网络
  • 卷积神经网络
  • 支持向量机
  • 最近的邻居
  • 决策图表
  • k 均值聚类

还有几种自然语言处理,包括:

  • 文本分类
  • 文档摘要
  • 图像字幕生成

虽然,对于我们的情况,我们只会尝试使用神经网络模型。让我们试着创建预测模型。为了创建预测模型,我们需要从客户端方法调用我们想要的机器学习。

在我们的例子中,应该是.neural_network_query在参数中接受一个文本。我们传递的查询是一个简单的英文文本,如***‘classify the class’‘estimate accurate the StudentAbsenceDays’***。重要的是目标列;您需要在查询中指定它。之后,API 会预测这是一个分类问题还是回归问题。让我们看看下面的例子。

#Creating the model by simple query, for example classify the class. Using Libra, you would need to specify which column you want as the target and the rest would be preprocessed automatically**edu_client.neural_network_query('classify the class')**

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

只需使用一个简单的查询,就可以自动对模型进行预处理,并启动学习过程。此外,所有的重复过程和指标也会立即显示出来。

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

此外,该模型为我们提供了每个时期的精度和模型损失图。

如果你想知道你能在模型中传递的所有参数,请在这里查阅 API 指南

Libra 还提供了对模型更深入的分析。我们可以通过运行下面的代码来访问分析。

**edu_client.analyze()**

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

上面,我们得到了总体指标,包括 ROC 曲线和混淆矩阵。有了这个,我们可以更快地分析我们的模型。

结论

在本文中,我概述了如何使用 Libra 在一个模型中创建机器学习预测。几乎所有繁琐的部分都由 API 完成,我们只需要看到结果。

这并不意味着它可以取代数据理解和功能工程,因为 API 的主要部分是创建一个机器学习模型,而不是创建新的功能。

希望有帮助!

如果您喜欢我的内容,并希望获得更多关于数据或数据科学家日常生活的深入知识,请考虑在此订阅我的简讯。

如果您没有订阅为中等会员,请考虑通过我的推荐订阅。

使用 R,Shiny & Plotly,一眨眼的功夫就能看到新冠肺炎案例数据

原文:https://towardsdatascience.com/create-a-coronavirus-app-using-r-shiny-and-plotly-6a6abf66091d?source=collection_archive---------3-----------------------

创建并发布一个 web 应用程序来可视化冠状病毒的数据

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

自冠状病毒新冠肺炎成为疫情以来,世界上至少有一半人在关注这一病例统计数据。我也是。作为一名数据科学家,我很好奇,所以我访问了案例统计数据并创建了一些可视化。通过这篇报道,我将告诉你如何自己做同样的事情。没有魔法!

测试一下:【https://go.aws/3aoYsIW

本演练解释如何创建 web 应用程序和交互式绘图。基于 R & Shiny开源技术栈非常单薄。大约 120 行代码就足够了。

代码也可以从 GitHub 下载。链接可以在本文的底部找到。

目标

本文的目标是能够创建一个运行 web 应用程序的**,它每 30 分钟更新一次数据,并在仪表板上显示这些数据。该应用程序的特点是:**

  • 冠状病毒官方可用数据的下载和解析。
  • 下拉菜单选择国家和州。
  • 显示所选国家新的和累积的病例统计数据的两个图。可以显示确诊病例、痊愈病例和死亡病例。

任务

  1. 设置 R & RStudio。
  2. 设置 R 项目及其文件夹结构。
  3. 使用 Shiny 创建用户界面。
  4. 添加加载和预处理数据的逻辑。
  5. 添加服务器逻辑。
  6. [可选]将应用程序上传到云。

设置 R & RStudio

首先从https://rstudio.com/products/rstudio/download/#download下载 Rbase 版本,启动安装程序并通过。

然后,从https://rstudio.com/products/rstudio/download/#download下载 RStudio 桌面免费版本。再次启动安装程序并完成步骤。

现在安装我们需要的包。启动 RStudio 应用程序并进入控制台(通常位于左下方的窗口)。通过键入以下命令安装软件包:

> install.packages("shiny")
> install.packages("dplyr")
> install.packages("tidyr")
> install.packages("plotly")

设置 R 项目及其文件夹结构

在 RStudio 中,单击右上方的下拉菜单“项目:(无)”,然后选择“新建项目…”。

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

点击“新目录”,然后点击“闪亮的网络应用”。现在为您的项目选择一个任意的新目录名,例如“ corona-app ”。此外,选择您希望应用程序所在的子目录。点击“创建项目”按钮,创建包含 2 个文件的文件夹:

  • 项目文件: corona-app。Rproj (可能有另一个名字)
  • 一个我们不需要的 app 模板文件: app。R

使用 Shiny 创建用户界面

闪亮的框架允许 R 用户用最少的编码工作创建反应式 web 应用程序。小 app 只需要 2 个文件: ui。R 为用户界面布局,而为服务器。R 用于服务器和渲染逻辑。

转到 RStudio 。在用户界面的左上方,有一个创建新文件的加号按钮。点击它,并选择“R 脚本”。创建一个文件,并将其命名为" ui。R "通过保存它,并开始编辑。

首先加载我们需要的包:

library(shiny)
library(plotly)

然后,使用 bootstrap 方案建立一个空白页面(每行 12 列),并使用元素 titlePanel 创建标题:

shinyUI(fluidPage(
  titlePanel("Case History of the Coronavirus (COVID-19)"),
))

总之,屏幕被分成不同的行(fluid rows)。带控件的流体行由三个宽度为 4 的组成,加起来又是 12。地块占据整个宽度(12):

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

现在添加控件的代码。在定义标题面板的行之后立即插入以下代码(在两个右括号之前!):

 fluidRow(
    column(
      width=4, 
      selectizeInput(
        "country", label=h5("Country"), choices=NULL, width="100%")
    ),
    column(
      width=4, 
      selectizeInput(
        "state", label=h5("State"), choices=NULL, width="100%")
    ),
    column(
      width=4, 
      checkboxGroupInput(
        "metrics", label=h5("Selected Metrics"), 
        choices=c("Confirmed", "Deaths", "Recovered"), 
        selected=c("Confirmed", "Deaths", "Recovered"), 
        width="100%")
    )
  ), 

如您所见,有一个流体行有 3 个元素,每个元素的宽度为 4。前两列包含下拉菜单元素( selectizeInput ),让用户选择国家和州。

第三列包含一组复选框元素( checkboxGroupInput )。这允许用户选择在两个图中显示哪些指标。

对于这两个图,我们使用 Rplotly ( 文档)。以下代码行在接下来的两个流体行中各添加一个 plotly 样式的绘图:

 fluidRow(
    plotlyOutput("dailyMetrics")
  ),
  fluidRow(
    plotlyOutput("cumulatedMetrics")
  )

添加加载和预处理数据的逻辑

该应用程序需要一些逻辑来下载和解析数据。这发生在服务器上。再次创建一个新文件,并将其命名为" server。R 并添加这些行来加载各自的 R 包:

library(dplyr)
library(tidyr)

然后定义一个 baseURL ,我们从其中按国家和地区下载冠状病毒的病例数据。数据位于约翰霍普金斯系统科学与工程中心(JHU/CSSE) 的服务器上。此外,定义一个稍后使用的字体( f1 ),加上一个测量文件有多长时间的速记函数(以避免过多的重新加载):

baseURL = "[https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series](https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series)"f1 = list(family="Courier New, monospace", size=12, 
       color="rgb(30,30,30)")minutesSinceLastUpdate = function(fileName) {
  (as.numeric(as.POSIXlt(Sys.time())) -  
   as.numeric(file.info(fileName)$ctime)) / 60
}

现在,定义主函数来加载特定数据集(例如,按日期和国家列出的确诊病例数)。

loadData = function(fileName, columnName) {
  if(!file.exists(fileName) || 
     minutesSinceLastUpdate(fileName) > 10) {
    data = read.csv(file.path(baseURL, fileName), 
      check.names=FALSE, stringsAsFactors=FALSE) %>%
      select(-Lat, -Long) %>% 
      pivot_longer(-(1:2), names_to="date", values_to=columnName)%>%
      mutate(
        date=as.Date(date, format="%m/%d/%y"),
        `Province/State`=
          if_else(`Province/State` == "", "<all>", `Province/State`)
      )
    save(data, file=fileName)  
  } else {
    load(file=fileName)
  }
  return(data)
}

该函数首先检查数据是否已经可用,并且不超过 10 分钟。如果不是这样, read.csv 从网络上下载文件。地理坐标被省略,然后 pivot_longer (来自包 tidyr )将 data.frame 从宽格式转换为长格式。方法 mutate 解析日期并插入文本 < all > 如果没有可用的地区(适用于美国、加拿大、中国和澳大利亚以外的国家)。

下一个块在应用程序启动时立即被调用。如上所述,它从 web 或缓存加载数据:

allData = 
  loadData(
    "time_series_covid19_confirmed_global.csv", "CumConfirmed") %>%
  inner_join(loadData(
    "time_series_covid19_deaths_global.csv", "CumDeaths")) %>%
  inner_join(loadData(
    "time_series_covid19_recovered_global.csv","CumRecovered"))

代码块加载确诊病例、恢复病例和死亡病例,并连接这 3 个数据集以获得一个大数据集。

更新[2020-3-27]:文件名已更改,以反映约翰霍普金斯大学的新数据结构(见链接)。

添加服务器逻辑

最后一节介绍了服务器上的静态代码。现在开始主要部分,即反应式服务器代码。本节中添加的所有代码都位于服务器函数的括号内:

server = function(input, output, session) {
  ## ...
}

数据

首先让我们添加一个反应函数,它返回全部数据的一个子集,即只返回一个指定的国家和地区。每当用户更改选择时,都会调用该函数并更新过滤器:

 data = reactive({
    d = allData %>%
      filter(`Country/Region` == input$country)
    if(input$state != "<all>") {
      d = d %>% 
        filter(`Province/State` == input$state) 
    } else {
      d = d %>% 
        group_by(date) %>% 
        summarise_if(is.numeric, sum, na.rm=TRUE)
    }
    d %>%
      mutate(
        dateStr = format(date, format="%b %d, %Y"),
        NewConfirmed=CumConfirmed - lag(CumConfirmed, default=0),
        NewRecovered=CumRecovered - lag(CumRecovered, default=0),
        NewDeaths=CumDeaths - lag(CumDeaths, default=0)
      )
  })

此外,如果用户为有州的国家(如美国)选择 <【所有> ,则该函数会汇总数据(使用summary _ if)。此外,根据累积的统计数据,计算差异并保存到新列中,以“*New”*为前缀。

下拉菜单

接下来,服务器观察国家选择的变化。如果发生这种情况,服务器必须更新可选状态。另外,*<>*全部作为选项添加到状态下拉菜单中:

 observeEvent(input$country, {
    states = allData %>%
      filter(`Country/Region` == input$country) %>% 
      pull(`Province/State`)
    states = c("<all>", sort(unique(states)))
    updateSelectInput(session, "state", choices=states, 
      selected=states[1])
  })

接下来的两行没有反应。相反,它们在应用程序启动时被调用。第一行按字典顺序提取所有国家。另一行在下拉菜单中选择意大利( selectizeInput ):

 countries = sort(unique(allData$`Country/Region`))

  updateSelectInput(session, "country", choices=countries, 
    selected="Italy")

情节

对于情节,我们使用了 R 包条形图。以下代码定义了用于两个图(新的和累积的情况)的函数。该函数的第一部分定义了条形图的基础(样式、轴、图例)。第二部分遍历选定的指标(如恢复的指标等)并添加条形。使用var prefix(“New”或“ Cum ”)和 metric )的列名的组成有点复杂。

 *renderBarPlot = function(varPrefix, legendPrefix, yaxisTitle) {
    renderPlotly({
      data = data()
      plt = data %>% 
        plot_ly() %>%
        config(displayModeBar=FALSE) %>%
        layout(
          barmode='group', 
          xaxis=list(
            title="", tickangle=-90, type='category', 
            ticktext=as.list(data$dateStr), 
            tickvals=as.list(data$date)), 
          yaxis=list(title=yaxisTitle),
          legend=list(x=0.1, y=0.9,bgcolor='rgba(240,240,240,0.5)'),
          font=f1
        )
      for(metric in input$metrics) 
        plt = plt %>%
          add_trace(
            x=~date, y=data[[paste0(varPrefix, metric)]],type='bar', 
            name=paste(legendPrefix, metric, "Cases"),
            marker=list(
              color=switch(metric, 
                Deaths='rgb(200,30,30)', 
                Recovered='rgb(30,200,30)', 
                Confirmed='rgb(100,140,240)'),
              line=list(color='rgb(8,48,107)', width=1.0)
            )
          )
      plt
    })
  }*

最后几行代码使用前面定义的函数。这两个图通过以下方式分配给用户界面元素:

 *output$dailyMetrics = renderBarPlot(
    "New", legendPrefix="New", yaxisTitle="New Cases per Day") output$cumulatedMetrics = renderBarPlot(
    "Cum", legendPrefix="Cumulated", yaxisTitle="Cumulated Cases")*

瞧啊。

这就是全部,你可以通过点击编辑器窗口右上角的“运行应用”按钮来运行代码。

GITHUB 代码

以上所有代码都可以在 GitHub 上找到。毕竟,它只有两个文件,加上项目文件:

https://github.com/ploner/coronavirus-r

[可选]将应用程序上传到云

将闪亮的应用程序发布到 web 服务器的最简单方法是使用 shinyapps 。在 shinyapps 上创建账户后,进入 RStudio,点击右上角的发布图标,然后点击“发布应用程序…”:

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

用你的账号连接,然后选择你需要的文件(仅限 ui。R服务器。R* !)😗

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

就是这样!你的应用程序运行在网络服务器上,你可以通过互联网访问它。

[2020 年 3 月 19 日更新]有一篇后续文章是关于同一个用例的。相反,如果 R + Shiny + Plotly,它会通过基于 Python 的堆栈:

Python + Dash + Plotly

链接:用 Python 可视化新冠肺炎数据,破折号& Plotly

我叫梅哈德·普洛纳。我对统计学和数据科学并不陌生,但这是我第一篇关于媒体的文章。我希望你喜欢阅读它,并欢迎任何反馈。

更多 R 在行动的例子,查看R-bloggers*。*

360 万个点,1 个 GIF —用 Python 可视化大数据

原文:https://towardsdatascience.com/create-a-gif-with-3-million-points-using-dask-caf7dcd0667e?source=collection_archive---------29-----------------------

使用 Dask 和 Datashader 库用 Python 创建大数据 GIF 的详细分步指南。

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

纽约市从 1989 年到 2019 年每年提交的建筑许可证。图片作者。

你好!本文将带您一步一步地创建 GIF 来可视化 Python 中的大数据。gif 是显示随时间变化的好方法,尤其是对于大型数据集。本文使用了过去 30 年纽约市建筑许可证,由建筑部门发布,摘自纽约市开放数据。这张 GIF 是我和我的好朋友雅普·云起于 2019 年秋天在纽约市进行的项目的一部分。

IPython 笔记本和环境文件可以在这里找到:【https://github.com/LeanneChan/create-a-GIF】T4。要下载笔记本并用 Jupyter Notebook 打开,可以关注我的另一篇文章这里。您也可以在 GoogleColab 中运行代码,但是根据过去的经验,在 GoogleColab 中加载 geopandas 库需要额外的步骤。

方法

GIF 是拼接在一起的图像集合。因此,我们创建 GIF 的方法是为每个不同的时间框架(在本例中为几年)创建单独的图,然后将它们拼接在一起。如果我们的数据集足够小,我们可以使用 matplotlib 来绘制这些点。但是,对于更大的数据集,我们将使用 Datashader ,一个用于可视化大数据集的库。为了处理大型数据集,我们将使用 Dask ,这是一个 Python 中灵活的并行计算库。

数据着色器

Datashader 是 HoloViz 家族的一部分(其他包包括 HoloViews、hvPlot),用于创建大型数据集的表示。它能够通过光栅化(将一个图分成像素)绘图区域并聚集落在每个像素中的点的值来可视化大型数据集。然后根据该聚合值对像素进行着色。

达斯克

Dask 允许我们存储比笔记本电脑内存还大的数据。此外,Dask 使用起来不会太吓人,因为 Dask 数据帧镜像 Pandas,Dask 数组镜像 NumPy。Dask 将作为 Pandas DataFrame 对象的分区分开,只在必要时将数据加载到我们的计算机内存中。

所需的库

dask、datashader、colorcet、matplotlib、numpy、imageio、geopandas

我们开始吧!

步骤 1:加载施工许可数据

数据集具有 shape (3616003,60),这意味着有 60 个列/要素和 360 万行/点。这是一个地理空间数据集和可视化,所以每一行代表纽约市的一个点,这是我们想要绘制的。由于有 3.6M 行,我们将需要 dask.dataframe 库。import用于将库中的库加载到你当前的工作区/会话中,这允许我们使用库中的方法。

import dask.dataframe as dd

如果你以前用过 pandas,语法真的很类似,调用read_csv读入 dataframe,我从 NYC open data 下载的,保存在我 Jupyter 笔记本的同一个文件夹里,名为‘DOB _ permit _ issuement . CSV’。

permits = dd.read_csv(‘./data/DOB_Permit_Issuance.csv’) permits.head()

然而,如果**您得到下面的错误,**您也将需要寻址具有混合类型的列。

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

未指定某些列的数据类型时的错误。图片作者。

在这个例子中,我必须为某些列指定dtype,因为它们具有混合类型,这在尝试调用 dataframe 时会引发错误。dtype 指定了列中数据的格式,因此当 pandas/dask 不得不猜测太多的列类型时会出现错误。我还使用usecols只选择了三列,而不是 60 列,以使未来的过程更快。这些栏显示了许可证提交的日期(以便以后提取年份)和许可证的 lat/lng。解决“混合数据类型”问题的另一种方法是只选择有用的、没有混合数据类型的列。事后看来,这是我本可以做的事,以节省自己很多时间!

permits = dd.read_csv('./data/DOB_Permit_Issuance.csv',
                     dtype={
                         'Lot': 'int64',
                         'Block': 'int64',
                         "Owner's Phone # ": 'float64',
                         "Owner’s House Zip Code": 'float64',
                         "Permittee's License #": 'float64',
                         "Zip Code":'int64' 
                     },
                     usecols=['Filing Date', 'LATITUDE', 'LONGITUDE'])

显示我们数据帧的前 5 行。(仅供参考,调用dataframe.head(x),其中 x 是任意整数,将打印出数据帧的前 x 行!)

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

这是我们将使用的数据帧的前 5 行。图片作者。

第二步:数据准备

首先是,我们要提取每个许可证的年份。我使用了熊猫函数to_datetime(),将“提交日期”列转换为日期-时间对象。由于该列现在是一个 datetime 对象,我可以使用另一个函数.dt.strftime(“%Y”)来访问每个点的年份以创建一个新列。

# change the column type
permits['Filing Date'] = dd.to_datetime(permits['Filing Date'])# create new column for the year
permits=permits.assign(year= permits['Filing Date'].dt.strftime("%Y"))

其次,我们需要为我们的坐标决定一个标准化的投影。这是地理空间数据科学中非常重要的一点,因为如果你的底图和你的点在不同的投影和坐标系中,混乱就会随之而来。一个坐标参考系统(CRS) ,是一个代码(epsg 代码),指的是空间数据(本来就是圆的,因为扁平的地球是一个骗局)如何被投影到一个扁平的 2D 屏幕上。它还指定了测量单位,通常是英尺、米或十进制度。

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

来源:earth data science . org:https://www . earth data science . org/courses/earth-analytics/spatial-data-r/intro-to-coordinate-reference-systems/

对于这个例子,我使用了 **Web-Mercator 投影(epsg: 3857),**基于米的投影。虽然在本例中没有这样做,但如果您想使用 OpenStreetMap 或 GoogleMaps 中的底图,这种投影特别有用,因为它们采用 epsg:3857 投影。Datashader 有一个很有用的函数lnglat_to_meters,可以将经度和纬度(epsg:4326,十进制度数)转换为 web-mercator(米)。确保您知道转换后哪个是您的 lat 和 lng,并按照每个函数中要求的正确顺序对它们进行编码,这一点非常重要。

# conversion to web mercator 
from datashader.utils import lnglat_to_meters# create new columns 'x' (longitude) and 'y' (latitude)
permits['x'], permits['y'] = lnglat_to_meters(permits['LONGITUDE'], permits['LATITUDE'])# keep a clean dataframe 
permits = permits.drop(['LONGITUDE', 'LATITUDE'], axis=1)

步骤 3:实施 Dask 最佳实践

我们遵循一些 Dask 最佳实践,将索引设置为我们想要按年份分组的列。尽管使用set_index需要大约 8 分钟,这使得稍后的子集设置快了 100 倍(0.001 秒!).

# set index so that it is arranged by year 
# drop na, if not will not be able to set index 
permits = permits.dropna() # dataframe will be arranged by year
permits_indexed = permits.set_index('year')
#  set_index takes about 8-9 minutes 

分区: Dask 通过将大型数据集分割成分区来运行。提到的最佳实践之一是根据您感兴趣的子集(在我们的例子中是年)来设置您的分区。

# create list of strings of years
dateRange = list(range(1989,2020))
years = []for year in dateRange: 
    str_year = str(year)
    years.append(str_year)# repartition the data - takes 0.001 seconds
permits_repartitioned = permits_indexed.repartition(divisions=years)

Compute: .compute()在我们的 Dask 数据帧上执行所有上述过程,并返回一个普通的数据帧。这样做会大大增加创建 GIF 所需的时间。如果此处没有调用compute(),上述所有数据争论将在 dataframe 的每次调用中重新计算,每帧耗时 10 分钟。那就是 30 帧的 300 分钟

permits_computed = permits_repartitioned.compute()

这需要 9 分钟,但是如上所述,为我们节省了更多的时间。

步骤 4:设置绘图边界

从一开始的示例 GIF 开始,这些地块包括纽约市各区的轮廓——曼哈顿、布鲁克林、皇后区、布朗克斯和斯塔滕岛。我从纽约开放数据下载了形状文件‘行政区边界’。我们将需要geopandas库来读取 shapefile。不要忘记将 CRS 设置为与您在步骤 2 中用于数据点的 CRS 相同。

# add NYC borough boundaries (coords must be in 3857)import geopandas as gpd
NYCBoroughs= gpd.read_file("./data/borough boundaries")
NYCBoroughs = NYCBoroughs.to_crs({'init': 'epsg:3857'})

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

纽约市行政区的形状。截图自 NYC 公开资料:https://Data . cityofnewyork . us/City-Government/Borough-Boundaries/tqmj-j8zm

由于我们希望地块也能完美地围绕城市,我们需要将地块上 x 和 y 坐标的范围设置为纽约市的界限,这是我从 GoogleMaps 中的拖放点获得的。再一次,不忘把坐标转换成 epsg: 3857。至于绘图尺寸,我建议你先摆弄那些图形,然后在画布上绘图(见下一节),看看什么最适合你。

# NYC limits - lng(east/west) and lat(north/south)
NYC        = (( -74.25,  -73.7), (40.50, 40.92)) 
x_range, y_range = [list(r) for r in lnglat_to_meters(NYC[0], NYC[1])]# plot dimensions
plot_width  = int(750)
plot_height = int(plot_width//1.2)

步骤 5:创建图像

至此,我们已经拥有了制作 GIF 所需的所有部分,我们只需要把它们放在一起!首先,我们需要导入一些库来帮助我们绘图。正如在“方法”中提到的,我们将在绘图前使用 datashader 来聚合点。我们不只是想要地图上的点,而是让地图告诉我们哪里有更高频率的点。Datashader 将在此基础上帮助我们给点着色。

# plotting functions
from colorcet import fire 
import datashader as ds
import datashader.transfer_functions as tf

让我们创建一个助手函数来绘制施工许可证,我们可以在以后绘制每年的不同点时使用它。

该函数接受参数: df —数据,
x_range,y_range—底座上 x/y 坐标的范围(见步骤 3),
w/h —绘图的宽度和高度(见步骤 3),
cmap —用于给点着色的彩色地图。

def create_image(df, x_range, y_range, w=plot_width, h=plot_height, cmap=fire):

    # create the canvas
    cvs = ds.Canvas(plot_width=w, plot_height=h, x_range=x_range, y_range=y_range)

    # the construction permits, aggregated by their count
    agg = cvs.points(df, 'x', 'y')

    # shade the pixels 
    img = tf.shade(agg, cmap=cmap, how='eq_hist')

    # return a PIL image
    return tf.set_background(img, "black").to_pil()

该函数使用 datashader 的 canvas 函数来表示我们要在其中绘制点的空间。首先,我们创建画布,指定尺寸。接下来,我们使用cvs.points()输入数据,它接收数据,‘x’—转换后的经度,和‘y’—转换后的纬度。cvs是在第一行创建的画布对象。

聚合数据 您可以在cvs.points()中指定的另一个参数是agg,它将通知 datashader 如何聚合您的数据。假设你有一个名为“z”的第三列,如果你想在这个聚合空间中绘制 z 的平均值,你可以包括agg=ds.mean('z')。如果没有指定,agg的缺省值是‘count ’,这是我们在这个例子中想要的,因此没有指定。

最后,datashader.transfer_functions.shade指定如何给每个像素着色。我们使用的色图是火,来自colorcet库。how指定颜色图的比例。一些选项包括:’ eq _ hist ‘[默认值],’ cbrt ‘(立方根),’ log ‘(对数)和’线性’。有关更多信息,请参见结尾链接的 datashader 文档。然后,我们将背景指定为黑色,并将图像转换为 Python 图像库(PIL)格式。

步骤 6:每年绘图的函数

我们快完成了!我们不想为每个时间帧手动创建新图像,所以我们将其打包在另一个函数中。对于这个函数,我们将需要 matplotlib 的 pyplot 来设置轴,并需要 numpy 来将图形值转换到范围 0–255(dtype = uint 8)以创建最终的图像。

from matplotlib import pyplot as plt
import numpy as np 

该函数接受参数: fig—来自 pyplot,
all_data —我们的数据框架,
year —要绘制的具体年份,
city_limits —要绘制的边界的 shapefile,
x_range,y_range —基底上 x/y 坐标的范围(见步骤 3)。

def plot_permits_by_year(fig, all_data, year, city_limits, x_range, y_range): # trim to the specific year
    df_this_year = all_data.loc[year] # create the datashaded image
    img = create_image(df_this_year, x_range, y_range) # plot the image on a matplotlib axes
    plt.clf() # this clears current figure
    ax = fig.gca() # this gets the axes from fig
    ax.imshow(img, extent=[x_range[0], x_range[1], y_range[0], y_range[1]]) # show the image on the axes
    ax.set_axis_off() 

    # plot the city limits (NYC borough boundaries)
    city_limits.plot(ax=ax, facecolor="none", edgecolor="white") # add a text label for the year
    ax.text(
        0.0,
        0.9,
        "Yearly Construction Permits\nFiled in NYC",
        color="white",
        fontsize=20,
        ha="left",
        transform=ax.transAxes,
    ) ax.text(
        0.7,
        0.1,
        year,
        color="white",
        fontsize=40,
        ha="left",
        transform=ax.transAxes,
    ) # draw the figure and return the image
    fig.canvas.draw()
    image = np.frombuffer(fig.canvas.tostring_rgb(), dtype="uint8")
    image = image.reshape(fig.canvas.get_width_height()[::-1] + (3,)) return image

使用loc对我们的数据进行子集划分只需要 0.001 秒。

该函数还指定要在每一帧上显示的文本,这是使用 matplotlib 函数ax.text()完成的,其中ax指的是图像的轴。

第七步:把图片做成 GIF!

**我们就在最后,**我们只需要使用imageio库将图像数组转换成 gif。为了创建 GIF,我们使用步骤 5 中的函数创建图像,将它们附加到一个数组中,然后使用image.io将它们拼接成一个 GIF。

# library to create GIF 
import imageio

运行下面的块代码来创建完整的 GIF!如果您对设计不满意,请在步骤 5 的功能中更改参数(如标签的位置/颜色/尺寸)。(参见 matplotlib 文档)
:‘years’数组是在第 3 步分区过程中创建的。

# create a figure
fig, ax = plt.subplots(figsize=(10,10), facecolor='black')# Create an image for each hour
imgs = []
for year in years:
    print('processing ' + year + ' ...')
    img = plot_permits_by_year(fig, permits_computed, year, NYCBoroughs, x_range=x_range, y_range=y_range)
    imgs.append(img)

# Combining the images for each hour into a single GIF
imageio.mimsave('1989_2019_permits.gif', imgs, fps=1)

这段创建 30 帧的代码块仅用了 9.56463 秒运行!

**就是这样!**谢谢你的关注,如果我能澄清什么,请告诉我!

过去的编辑和关于时间复杂性的附加信息 2020 年 5 月 30 日 —更改流程以加快子集设置,并调用.compute()以减少 Dask 操作。(当前文章反映了正确的代码。)

在初始过程中(代码不再显示),我跳过了第 3 步,在 plot_by_year 函数中设置了数据帧的子集。因此,打印每年的框架大约需要 10 分钟。这也是因为由于 Dask 的性质,每次调用 dataframe 时,数据集上的数据争论都会重复。我的直觉是,在每次调用 plot_by_year 函数时,必须再次执行将坐标转换为墨卡托坐标、转换“归档日期”列和设置数据框子集的过程。在 Dask 数据帧上调用compute()解决了这个重复问题。

为了检查花费的时间,我使用了time图书馆。

子集花费的时间:旧方法

start=time.time()
df_this_year = permits.loc[permits["Filing Date"].dt.strftime("%Y") == '2009'].compute()
print(time.time()-start)# 616.4123058319092 seconds

子集花费的时间:新方法

start = time.time()
permits_2009 = computed_repartitioned.loc['2009']
print(time.time()-start)# 0.0010952949523925781 seconds

这个新过程是对我花了几个小时创建 GIF 的原始代码的巨大改进!感谢 @james.a.bednar 为改进原代码所做的小小额外推动!

致谢: Nicholas Hand,MUSA 620 教授,他教会了我大部分的 python 数据可视化技巧!

数据来源: 建筑许可证,纽约市公开数据,建筑署https://Data . cityofnewyork . us/Housing-Development/DOB-Permit-issued/IPU 4-2q9a

纽约市行政区边界,纽约市公开数据,城市规划部https://Data . cityofnewyork . us/City-Government/Borough-Boundaries/tqmj-j8zm

Datashader 文档:https://readthedocs . org/projects/data shader/downloads/pdf/stable/

使用 SQL 通过 Google Cloud BigQuery ML 创建机器学习模型

原文:https://towardsdatascience.com/create-a-machine-learning-model-with-google-cloud-bigquery-ml-using-sql-9e2c0ce7fd2d?source=collection_archive---------48-----------------------

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

我的简单白板

随着机器学习模型在不同领域的应用,以及技术的进步(更好的硬件和高级编程语言),建立一个适合您需求的工作机器学习模型变得越来越容易。制作机器学习模型的过程越来越简单,代码行数越来越少。

在本文中,我将向您展示如何使用 Google BigQuery ML 构建一个只包含 SQL 的定制 ML 模型。

但是首先,Google BigQuery 是什么?

Google BigQuery 是一个无服务器、低成本、高可伸缩的数据仓库系统,由 Google Cloud Platform 提供,具有许多业务敏捷性特性。BigQuery ML 就是这样一个特性,它帮助数据科学家、数据分析师和数据工程师(比如我)构建可操作的生产级 ML 模型。我们可以在结构化和非结构化数据上创建模型。最重要的是,只需在短时间内使用 SQL 环境进行查询。

在本文中,我们将完成以下任务:

  1. 使用“德国信用数据”作为样本数据集来预测贷款申请的好坏。
  2. 将样本数据分为训练集和测试集。
  3. 创建并加载 Google BigQuery 表中的数据。
  4. 只需使用 SQL 创建一个“逻辑回归”模型。
  5. 最后,我们将评估和预测贷款类型的好坏。

我们将使用的样本数据:

我们将使用一个样本结构化数据集“德国信贷数据”。您也可以从下面的 git 资源库下载这些文件:

https://github . com/aa kash-ra thore/BigQueryML/tree/master/data

├── data
│   ├── germanCredit.csv
│   ├── GermanCredit.xls
│   ├── testData.csv
│   └── trainData.csv
├── README.md
└── test_train.py

在存储库“GermanCredit.xls”的原始数据文件中,该文件提供了所有列数据的详细信息。我已经对所有分类数据进行了编码,并创建了一个文件“german credit . CSV”,“test _ train . py”是一个 python 脚本,用于将数据划分到测试和训练数据集中(testData.csv 和 trainData.csv)

在 BigQuery 中加载数据:

登录到 Google 云平台控制台,使用左侧选项面板导航到 BigQuery 选项卡。

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

在 GCP 控制台中选择 Bigquery 工具

使用 BigQuery 控制台中的选项创建数据集。

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

创建数据集

从先前创建的数据集中的 trainData.csv 和 testData.csv 创建表格。

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

创建包含列车数据的表创建包含测试数据的表

在选择相应的表后,我们可以使用“预览”选项预览创建的表中的样本数据。

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

预览表格数据

现在,我们可以开始创建一个 ML 模型,在我们的样本数据中,“响应”列是结果标签(1 =好,0 =坏),其他列是输入特征。令人惊奇的是,我们将只使用 SQL 查询来创建和评估我们的 ML 模型。

创建 ML 模型:

我们将创建一个逻辑回归模型,这是一个分类模型,在我们的案例中,我们将使用它来根据以前的信用报告数据对贷款申请进行分类。

SQL 查询创建一个 ML 模型:

# Creating logistic regression model using data from trainData tableCREATE OR REPLACE MODEL
  `mltestDataset.credit_classification_model` OPTIONS ( model_type='logistic_reg' labels=['response'] ) AS
SELECT
  * EXCEPT(obs)
FROM
  `mltestDataset.trainData`

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

从包含训练数据的表中创建模式

评估创建的 ML 模型:

评估 ML 模型有不同性能参数,在我们创建的 ML 模型中,当评估我们训练的 ML 模型时,roc_auc 是这样一个简单的可查询字段。

评估 ML 模型的 SQL 查询:

# Evaluating logistic regression model using data from testData tableSELECT
  roc_auc,
  CASE
    WHEN roc_auc > .8 THEN 'good'
    WHEN roc_auc > .7 THEN 'fair'
    WHEN roc_auc > .6 THEN 'not great'
  ELSE
  'poor'
END
  AS model_quality
FROM
  ML.EVALUATE(MODEL mltestDataset.credit_classification_model,
    (
    SELECT
      * EXCEPT(obs)
    FROM
      `mltestDataset.testData` ) )

输出:

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

使用曲线下的 ROC 面积评估模型性能

正如您可以看到的性能相当不错,我们可以通过使用特征工程调整模型来提高性能。但是为了简单起见,我们将使用这个模型来分析预测。

预测使用创建的 ML 模型:

现在我们将使用这个模型来预测贷款类型(1 =好,0 =坏)。下面给出了从模型中获取预测的查询:

# Getting prediction for our ML model using data from testData tableSELECT
  *
FROM
  ml.PREDICT(MODEL `mltestDataset.credit_classification_model`,
    (
    SELECT
      * EXCEPT(obs)
    FROM
      `mltestDataset.testData` ) );

输出:

我们将检查前 5 个预测:

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

检查预测

我们可以看到前 5 个预测的结果:
1。对于第一条记录,我们的模型以 84%的置信度预测贷款是好的(响应=1),实际上,它是好的(响应=1)。
2。对于第二条记录,模型以 93%的置信度预测贷款是好的(响应=1),实际上,它是好的(响应=1)。
3。对于第三条记录,模型以 63%的置信度预测贷款是好的(响应=1),实际上,它是好的(响应=1)。
4。对于第 4 条记录,模型以 74%的置信度预测贷款是好的(响应=1),实际上,它是好的(响应=1)。
5。对于第 5 条记录,模型以 66%的置信度预测贷款为不良贷款(响应=0),实际上,它是不良贷款(响应=0)。

结论:

在本文中,我解释了如何使用 SQL 在 Google BigQuery 中创建和评估 ML 模型。后来我们分析了这个模型的预测。

请在下面留下您对本文的评论,如果您在上面指定的任何步骤中遇到问题,您可以通过insta gramLinkedIn 联系我。

使用 Azure 自定义视觉和 Python 创建模型

原文:https://towardsdatascience.com/create-a-model-with-azure-custom-vision-and-python-7bc5caed82c4?source=collection_archive---------30-----------------------

在这篇文章中,我想和你分享如何使用 Azure Custom VisionPython SDK 创建一个分类模型。

为什么是 Python 而不是可视化界面?

答案很简单,如果你用代码构建训练过程,你可以在 Github 上对它进行版本化。让你的代码版本化意味着你可以回读你所做的,在一个团队中工作,如果你需要的话再运行一次。

让我们深入研究代码!在我们开始之前,我假设你已经安装了 Python 3.6

在 Azure 中创建资源

您需要做的第一件事是创建一个 Azure 自定义视觉服务。如果你没有 Azure 套餐,你可以在第一个月获得 200 美元的点数。

您可以通过门户轻松创建 Azure 自定义 Vision 端点,但您也可以为此使用 Azure CLI 。如果你没有安装 Azure cli,你可以使用 pip 来安装。

pip install azure-cli

第一步是登录到您的 Azure 订阅,选择正确的订阅并为自定义 Vision 端点创建资源组。

az login az account set -s <SUBSCRIPTION_ID> az group create --name CustomVision_Demo-RG --location westeurope

自定义视觉服务有两种类型的端点。一个用于训练模型,另一个用于针对模型运行预测。

让我们创建两个端点。

az cognitiveservices account create --name CustomVisionDemo-Prediction --resource-group CustomVision_Demo-RG --kind CustomVision.Prediction --sku S0 --location westeurope –yes az cognitiveservices account create --name CustomVisionDemo-Training --resource-group CustomVision_Demo-RG --kind CustomVision.Training --sku S0 --location westeurope –yes

现在我们已经创建了端点,我们可以开始训练模型了。

一切都从一个问题开始

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

每一次机器学习之旅都是从一个你希望得到答案的问题开始的。在这个例子中,你要回答这个问题:它是一个荷马还是一个玛吉·乐高玩具?

既然我们知道了要问模型什么,我们可以继续下一个需求;那就是数据。我们的模型将是一个分类模型,这意味着模型将查看图片,并根据不同的类别对图片进行评分。因此,输出将是我 70%确信这是荷马,1%确信这是玛吉。通过选择得分最高的班级,并为置信度设置一个最低阈值,我们就知道图片上是什么了。

我已经为你创建了一个数据集,其中有 50 张荷马·辛普森乐高玩具的图片和 50 张玛吉·辛普森乐高玩具的图片。我拍摄这些照片时考虑了一些事情,使用了很多不同的背景,从不同的角度拍摄了这些照片。我确保照片中唯一的物体是荷马或玛吉,并且照片的质量在某种程度上是一致的。

在这里下载数据集

训练模型

对于培训,我们将使用定制视觉服务 Python SDK ,您可以使用 pip 安装这个包。

pip install azure-cognitiveservices-vision-customvision

创建一个名为“train.py”的新 Python 文件,并开始添加代码。

从导入所需的包开始。

from azure.cognitiveservices.vision.customvision.training import CustomVisionTrainingClient 
from azure.cognitiveservices.vision.customvision.training.models import ImageFileCreateEntry

接下来,为自定义视觉端点、自定义视觉训练密钥和存储训练图像的位置创建变量。

cv_endpoint = "https://westeurope.api.cognitive.microsoft.com" training_key = "<INSERT TRAINING KEY>" 
training_images = "LegoSimpsons/TrainingImages"

从培训开始,我们需要创建一个培训客户端。该方法将端点和训练密钥作为输入。

trainer = CustomVisionTrainingClient(training_key, endpoint= cv_endpoint)

现在您已经准备好创建您的第一个项目了。该项目以名称和域作为输入,名称可以是任何东西。领域是一个不同的故事。你可以要求列出所有可能的领域,并选择最接近你要完成的领域。例如,如果你试图对食物进行分类,你可以选择“食物”或“地标”作为地标。使用下面的代码显示所有域。

for domain in trainer.get_domains():   
   print(domain.id, "\t", domain.name)

您可能会注意到,一些域旁边有单词“Compact”。如果是这种情况,这意味着 Azure Custom Vision 服务将创建一个较小的模型,您可以导出该模型并在您的手机或桌面上本地运行。

让我们创建一个域设置为“General Compact”的新项目。

project = trainer.create_project("Lego - Simpsons - v1","0732100f-1a38-4e49-a514-c9b44c697ab5")

接下来你需要创建标签,这些标签和上面提到的类是一样的。当您创建了一些标签后,我们可以用它们来标记图像,并将图像上传到 Azure Custom Vision 服务。

我们的图像在文件夹中按标签/类别分类。玛吉的所有照片都在名为“玛吉”的文件夹中,荷马的所有照片都在名为“荷马”的文件夹中。

在下面的代码中,我们执行以下步骤:

  • 我们打开包含训练图像文件夹的目录。
  • 遍历在该文件夹中找到的所有目录
  • 用文件夹名称创建一个新标签
  • 打开包含图像的文件夹
  • 为该文件夹中的每个图像创建一个包含文件名、文件内容和标签的 ImageFileEntry。
  • 将此 ImageFileEntry 添加到列表中。
image_list = []
directories = os.listdir(training_images)for tagName in directories:
  tag = trainer.create_tag(project.id, tagName)
  images = os.listdir(os.path.join(training_images,tagName))
  for img in images:
   with open(os.path.join(training_images,tagName,img), "rb") as image_contents:
    image_list.append(ImageFileCreateEntry(name=img, contents=image_contents.read(), tag_ids=[tag.id]))

现在您有了一个包含所有标记图像的列表。到目前为止,Azure Custom Vision 服务中还没有添加任何图像,只创建了标签。

上传图片分批进行,每批最多 64 张图片。我们的数据集有 100 张图片,所以首先我们需要将列表分成 64 张图片。

def chunks(l, n):
  for i in range(0, len(l), n):
   yield l[i:i + n]
batchedImages = chunks(image_list, 64)

现在,我们已经将图像分成 64 个一批,我们可以将它们一批一批地上传到 Azure Custom Vision 服务。注意:这可能需要一段时间!

for batchOfImages in batchedImages:
  upload_result = trainer.create_images_from_files(project.id, images=batchOfImages)

现在您已经到达了最后一步,我们可以发布模型了。然后,它在预测 API 中可用,并准备好供应用程序使用。

每次训练你的模型都被称为一次迭代。当你有了新的数据,或者当你发现在现实世界中你的模型与预期的有所不同时,你通常需要重新训练你的模型。

Custom Vision 服务的概念是,您可以在特定的名称下发布模型的迭代。这意味着您可以有多个版本的模型供您的应用程序使用,例如,您可以用它非常快速地对您的模型进行 a-b 测试。

要发布模型的迭代,您需要调用 publish_iteration 方法,该方法需要几个参数。

项目 ID 和迭代 ID,这些是来自前面步骤的值。您可以为模型的发布选择一个名称,例如“最新”或“版本 1”。您需要的最后一个参数是您要将它发布到的资源的“资源标识符”。这是我们在开始时用 AZ 命令创建的 Azure 自定义视觉预测资源的资源标识符。

您可以使用此命令检索您创建的预测资源的所有详细信息:

az cognitiveservices account show --name CustomVisionDemo-Prediction --resource-group CustomVision_Demo-RG

您可以复制字段 ID 后面的值,如下所示:

/subscriptions/<SUBSCRIPTION-ID>/resourceGroups/<RESOURCE_GROUP_NAME>/providers/Microsoft.CognitiveServices/accounts/<RESOURCE_NAME>")

获得资源 ID 后,将其粘贴到下面的变量中,并调用“publish_iteration”方法。

publish_iteration_name = '' resource_identifier = '' trainer.publish_iteration(project.id, iteration.id, publish_iteration_name, resource_identifier)

现在您已经成功地训练并发布了您的模型!

简单回顾一下我们所做的工作:

  • 您创建了一个包含 Azure 自定义视觉服务培训和预测端点的 Azure 资源组
  • 您已经创建了一个新项目
  • 在该项目中,您已经创建了标记
  • 您分批上传了 64 张图片,并对其进行了标记
  • 您已经训练了模型的迭代
  • 您已经将迭代发布到预测端点

查看完整代码这里

我们来测试一下模型!

在应用程序中使用模型就像调用 API 一样简单。您可以只对端点进行 json post,但也可以使用自定义 Vision Python SDK 中的方法,这将使事情变得容易得多。

创建一个名为“predict.py”的新文件

从导入预测所需的依赖项开始。

from azure.cognitiveservices.vision.customvision.prediction import CustomVisionPredictionClient

接下来你需要的是预测键。这是您将模型发布到的资源的键。您可以使用这个 az 命令来列出这些键。

az cognitiveservices account keys list --name CustomVisionDemo-Prediction --resource-group CustomVision_Demo-RG

当您拥有预测键时,您可以创建一个预测客户端。对于这个客户端,您还需要端点。您可以运行下面的 az 命令并复制字段“endpoint”后面的 url。

az cognitiveservices account show --name CustomVisionDemo-Prediction --resource-group CustomVision_Demo-RG

现在您有了预测键和端点,可以创建 PredictionClient 了。

predictor = CustomVisionPredictionClient(prediction_key, endpoint=ENDPOINT)

您有多种选择来对图像进行分类。您可以发送 URL,也可以将二进制图像发送到端点。默认情况下,Azure Custom Vision 服务会保存发布到端点的所有图像的历史记录。可以在门户中查看图像及其预测,并用于重新训练您的模型。但是,有时你不希望图像保留在历史中,因此可以禁用此功能。

我已经上传了两张图片,你可以用来测试,但是你也可以使用搜索引擎找到其他的图片,比如玛吉的图片和 T2 的图片。

要使用 URL 对图像进行分类并保留历史记录,您需要调用“classify_image_url”方法。您可以根据上面的几个步骤为它提供项目 id 和迭代名称,并提供图像的 URL。

results = predictor.classify_image_url(project.id,publish_iteration_name,url="https://missedprints.com/wp-content/uploads/2014/03/marge-simpson-lego-minifig.jpg")

要在屏幕上显示不同类别的分数,您可以使用下面的代码循环显示结果,并显示图像的标签名称和置信度分数。

for prediction in results.predictions:
  print("\t" + prediction.tag_name + ": {0:.2f}%".format(prediction.probability * 100))

现在,您已经完成了所有工作,并且拥有了自己的运行在云中的分类模型!以下是您所取得成就的回顾:

  • 我们问了一个问题
  • 收集的数据
  • 创建了 Azure 自定义视觉服务端点
  • 创建了新项目
  • 标记和上传的内容
  • 训练模型
  • 发布迭代,以便它可以在 API 中使用
  • 使用 API 对模型运行预测

在这一系列文章的其余部分,我们将把这个模型用于不同的解决方案!敬请期待!

查看完整代码这里

资源:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值