TowardsDataScience 博客中文翻译 2021(一百九十六)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

创建数据科学简历

原文:https://towardsdatascience.com/creating-a-data-science-resume-66685918c1ba?source=collection_archive---------24-----------------------

设计一份出色简历的指南——为你想要的工作接近招聘人员或招聘经理至关重要的第一步。

我们都知道为什么我们首先需要创建一份简历,对吗?一份简历反映了一个人的经历、资历,最重要的是,反映了一个人将如何适应一个角色。这篇博客文章将涵盖制作简历时应该记住的要点。

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

马库斯·温克勒在 Unsplash 上的照片

数据科学是一个充满各种机会的行业。每一次点击、每一次滑动、每一次搜索、每一次购物、每一条信息流都在创造数据。因此,不用说,这是一个需求不断上升的行业。一项研究显示,近年来,数据科学在印度市场的就业岗位增加了约 45%。

为了满足这一需求,各公司正在各地招聘 DS 职位。即使在校园实习期间,公司也会收到数百份申请两三个职位的简历。

现在,让我们来想想招聘人员,特威拉·桑兹。她每隔一天就会收到数百份求职者的简历。除了从这一大堆简历中挑选简历,她还有其他责任。她看一份简历的时间不会超过 30 秒。30 秒的时间足以吸引 Twyla 的注意力。

我们都知道性别差异在每个行业都很普遍,我们的科技世界也不例外。这种差距的存在可能有几个原因,但我将快速谈论两项研究。

使用主动语态。简历就是把你的经历和成就放在一个地方。它应该是关于你的,一个执行动作的明确主体。

基兰·斯奈德的一项研究表明,制作一份简历可能是一个促成因素。这项研究调查了 1100 份简历(50%是男性写的,另一半是女性写的)。斯奈德发现,不同性别的简历风格有着明显的差异。不同之处在于——长度、小节的组织、工作细节的写作方式、相关成就以及动词性动作词的使用,等等。

斯基德莫尔学院的社会心理学家 Corrine Moss-Racusin 进行了另一项关于 STEM 教师性别偏见的研究。该实验是给科学家两份相同的候选人简历进行评估(在资格和经验方面相似)。这两份简历的唯一区别是一份叫约翰,另一份叫詹妮弗。拉库辛和她的同事询问了一百多名 STEM 教授来评估这两份求职简历。拉库辛在斯坦福大学医学院展示了结果,结果令人吃惊。尽管有相似的资历和经历,教授们发现詹妮弗的简历明显不如约翰。所以,要消除人们头脑中的这些隐性偏见还有很长的路要走。但我们能做的就是努力设计一份更稳健的简历来缩小这些差距。

就像你的模型调整练习一样。

考虑到这一点,让我们深入以下要点,打造一份出色的简历。

1.模板

  • 选择一个具有视觉吸引力和专业性的模板。
  • 简历的长度不应该超过两页。还记得 Twyla 吗,我们的招聘人员。把她看简历需要的所有相关信息简洁地放在一页纸里会很方便。
  • 与你的字体风格和大小保持一致。在制作简历时,‘comic Sans MS’不是合适的字体样式。
  • 除非另有说明,否则以 PDF 格式保存简历。

2.个人信息

  • 写上你的名字,电话号码,电子邮件号码。
  • 最好将这一部分放在简历的顶部。
  • 没有必要把你的完整的物理地址或你父母的名字(是的,我见过有人这样做)等。
  • 您不希望输入类似“john123rocks@domain.com”的电子邮件地址。专业电子邮件 id 可以是“jane.doe@domain.com”或“jane.doeiitb@domain.com”。
  • 电话号码应处于工作状态。记住,Twyla 应该可以在打电话的时候找到你。
  • 放上你 LinkedIn 个人资料的链接。如果你有一个中型博客、GitHub 或 Kaggle 个人资料,也可以随意添加这些链接。不要犹豫展示你的作品,只要它是相关的。
  • 确保这些链接在 PDF 版本的简历中是可点击的。
  • 如果你决定在你的网站/LinkedIn/Github 上发布个人资料,不要忘记简洁地管理这些个人资料。添加关于你的项目,课程,额外工作等的描述。你认为哪一个对 Twyla 更有吸引力?只有标题的空简介还是写得很好的简介?

3.摘要

  • 在简历的开头添加一份执行摘要。
  • 不应超过 3-5 行。
  • 补充相关工作经验。
  • 补充几点关于你的技能,对 DS 的热情,以及你想在这家公司工作的原因。
  • 如果你即将开始你的数据科学之旅,写下你的收获,以及你认为自己有多适合这个职位。

让我们看两个写简明摘要的例子。一名大一新生可以写道:“初级数据科学家,拥有 IIM B 大学的分析和机器学习研究生学位,擅长统计模型、最大似然算法和编程。”。有解决不同现实问题的项目工作经验,尤其是在金融行业。另一个例子是,在零售领域有六年工作经验的数据科学家,专注于统计建模和机器学习技术。成就包括成功交付劳动力管理的多阶段预测系统。获得孟买 IIT 大学应用统计学硕士学位。

4.经验

  • 从你最近的经历开始。
  • 只列出相关经历。
  • 使用主动语态。简历就是把你的经历和成就放在一个地方。它应该是关于你的,一个执行动作的明确主体。斯奈德的研究发现,男性倾向于写更多动词性的动作词,而不是协作语言。被动语态的用法意味着主语是由别人来行动的。
  • 展示一些可衡量的成就(如果可能的话)。我们可以写“调整模型参数后实现了 85%的准确性”或“通过成功调整模型参数,利润率提高了 30%。”Twyla 可能没有统计学/经济学/数学背景,无法理解达到 85%模型准确性的含义。她了解公司业务,“利润率提高 30%”比“获得 85%的准确率”更有吸引力。
  • 使用 3-5 个要点。
  • 添加公司名称、职务和您与他们共事的年份。
  • 对于新生,你可以描述你的班级项目,论文或任何额外的或自由职业者的工作,如果有的话。尽量包括目标、使用的技术和可衡量的成就。

让我们看一个例子

  • 带领一个数据科学家团队使用一套机器学习方法构建预测解决方案。
  • 为一家大型房地产公司优化的 CRM 数据库。
  • 浪费的电话和电子邮件时间减少了 57%。
  • 使用 matplotlib 创建实时 ROI 图表,帮助团队专注于高利润业务。
  • 年利润增长了 20%。

当写下技能部分时,一定要记得看 JD 并包括相关的技能。

5.技能

为什么这一部分如此重要?首先,整理与你申请的职位描述相关的技能将有助于 Twyla 理解你的简历,结果,你会更好。第二,公司经常使用应用程序跟踪软件来解析收到的简历。软件会给出公司发布的职位描述和你简历的匹配百分比。分数越低,出现在废品堆中的可能性就越大。在记下这一部分的时候,一定要记得查看 JD,并包括相关的技能。您也可以将它分成多个子部分,

  • 技能-统计分析,假设检验,回归,时间序列预测,机器学习算法等。
  • 编程语言- R,Python,SQL 等。
  • 软技能——表达技能、形象化、解决问题的技能等。
  • 平台工作经验-谷歌云平台,Azure 等。
  • 使用不同工具的经验- Tableau,Git,MS Excel 等。

JDs 通常包含包或库的名称,比如 dplyr、forecast for R、scikit-learn 和 pandas for Python。在这种情况下,添加您知道的包或库。

6.其他项目/出版物

  • 如果有,写其他相关项目。例如,如果你参加过卡格尔比赛。
  • 描述您是否发表过任何论文/演讲(现有的或即将发表的)。将链接添加到出版物。

7.教育

  • 添加学院名称,地点,你获得的学位
  • 如果你正在开始你的数据科学之旅,你可以写下一些你上过的相关课程。
  • 额外的相关课程、证书(MOOCs )(如果你参加过的话)。

8.其他活动

  • 添加你积极参与的任何其他活动或计划(例如,你大学的就业协调员,你目前公司面试团队的一员)
  • 您获得的任何相关奖项。

简历中这些小节的顺序没有硬性规定。根据工作描述,你可能需要稍微改变一下顺序。如果你是大一新生,你可能想强调教育和技能部分,而不是经验部分。如果你申请的是金融领域的工作,并且只在科技或零售领域工作过,试着发挥你的技能,这在金融领域会很有用。就像你的模型调整练习一样。数据科学不可能无所不知。记住要诚实、简洁、自信,不要犹豫地把你的工作放在前面。

创建一个数据集来发现地中海的难民船

原文:https://towardsdatascience.com/creating-a-dataset-to-spot-refugee-boats-in-the-mediteranean-449e86e2d4b2?source=collection_archive---------38-----------------------

变更数据

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

照片由珍·西奥多Unsplash 上拍摄

大约半年前,我开始了一项非常有趣的探索:利用卫星数据寻找难民船。我与非政府组织太空眼合作,这是一个致力于这一探索的非营利组织。许多其他倡议也对这个主题感兴趣并正在努力。我有 ML 背景和一些编程经验,但是从一开始就解决这样的问题是一个相当大的挑战,同时也很有趣。

一开始,我们思考了很多问题——对于大多数问题,我们每隔一段时间就会回头来看——比如:有什么样的卫星数据可用?分辨率是否足以探测到船只?我们如何验证我们的预测?系统可扩展吗?

经过大量的研究和非常有趣的讨论,我们意识到我们需要先做一个可行性研究。雷根斯堡的团队选择了来自 planet.com 的可视卫星图像。柏林的佩德罗正在为雷达图像做类似的工作,并取得了一些很好的成果。奥格斯堡的 SearchWing 正在为他们自己的无人机研究探测算法。但是行星数据似乎更适合我们非地球科学的眼睛和我在计算机视觉方面的经验。除了雷达数据,它看起来就像我们习惯的普通图像和图片。

在这篇文章中,我将描述我们为可行性研究创建船舶数据集的过程。重建这个的代码可以在我的 github 上找到——你需要自己访问 planet.com 来查询图片。

阶段 1——概念化

我们决定使用的卫星图像来自 PlanetScope 4 波段卫星,该卫星提供 3m3m 分辨率的 4 通道图像(RGB+NIR)。我们选择了这个,因为它有最好的覆盖范围和分辨率的权衡。他们确实提供 0.8 米 0.8 米分辨率的图像,但这必须为某个位置提前订购,成本要高得多。行星镜卫星已经在那里有一段时间了,所以我们有一些历史数据要看。《星球日报》几乎只公布了海岸的卫星图像——也就是说,陆地上和海洋中 7 公里处的一切。这部分是因为海洋相当广阔,没有多少人对它的图像感兴趣(至少没有陆地图片那么多)。另一方面,planet 在定位他们在海洋上拍摄的卫星图像时遇到了一些问题。虽然在陆地上,他们可以使用地标来定位自己和他们的照片,但这些在海洋图像中是不可用的。这导致定位误差,从而降低质量。但是今年的某个时候,他们改进了他们的算法,现在提供了更高质量的海洋图像。

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

星球图像中的一艘船的例子——使用 planet.com 数据创建了我自己

有了这些信息,我们仍然没有参考系统的解决方案。我们不知道那些难民船在哪里——这就是我们开始整件事的原因。

为了训练和验证我们的船只检测模型,我们需要一些地面真实数据——至少对于监督模型来说是这样。我们可能无法通过目测找到足够多的难民船来训练任何东西。所以我们寻找其他探测飞船的可能性。我们发现了明显的 kaggle 飞船探测数据集,但是那些飞船比我们需要的要大得多。它们通常跨越几百个像素,而行星数据上的难民船仅测量大约 3 个像素。他们没有对我们来说非常有价值的 NIR 频道。所以我们决定去寻找一个基于原始 PlanetScope 数据的模型,但是是在非难民船上。但是如何在图片上找到正常的船呢?这将牵涉到大量的手工工作…

在和一些更有经验的船民在一起后,我了解了 AIS。AIS 是一个所有超过一定规模的船只都必须注册的系统。他们船上有一个发射机,不断广播他们的位置,他们还有一个接收机,告诉他们周围所有其他船只的位置。这基本上是一个确保它们不会相互碰撞的系统——至少我是这么理解的。这些数据通常对机器学习非常有用。有一些很棒的可视化项目和船舶跟踪应用程序。例如,世界自然基金会目前正在开发一种跟踪系统,利用人工智能系统来防止非法石油泄漏。我们的难民船没有 AIS 发送器。但这仍然可以帮助我们为我们的应用程序创建一个基本的训练集。

有一些网站可以让你自己请求当前的 AIS 数据来记录,但是这看起来太麻烦了。美国提供 marinecadastre.com海岸旧的 AIS 日志文件。其他一些国家也有类似的东西,但我们发现没有一个符合美国数据的分辨率。他们的文件中有一分钟的分辨率,这对我们的应用程序来说应该足够了。

所以现在我们有了一切,通过将 AIS 日志文件与行星卫星图像交叉,可以自动创建美国某个地方的船只/非船只数据集。概念阶段已经结束,我们终于可以开始实现数据集创建了。开始时,它看起来相当简单。

步骤 2 —交叉两个数据源

首先,我们需要交叉这两个数据源。我选择了迈阿密和棕榈滩之间的地区作为我感兴趣的地区。为此,我必须创建一个. geojson 文件(使用 geojson.io 并不难)。

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

来自 geojson.io 的截图,带有示例区域-我自己创建的

由于来自 marinecadastre 的 AIS 文件非常大,我想删除所有不在我感兴趣的区域内的条目。Geopandas 给了我很大的帮助,尽管它有时会让我发疯。这个代码可以在顶部链接的 jupyter 笔记本中的函数 reduce_ais_csv()中找到。

现在我们需要找出卫星在哪里拍的照片。没有全天覆盖,但卫星每天只通过一到三次来拍照。为了与 planet 通信,我使用了 porder API,这在本文的中有详细解释。我向 planet 索要了我的 geojson 中的图片 id 列表,这些图片的云层覆盖率不到 50%,与我感兴趣的区域至少有 80%的重叠。从 id 列表中,我们可以提取图像拍摄的准确时间。现在,从我们的 AIS 数据帧中,我们可以选择那些显示与相应卫星图像相同时间的条目。(不完全相同,但是+/- 30 秒,因为 AIS 文件的记录速度是每分钟。)

porder idlist --input "\infile.gejson" --start "day.month.year" --end "day.month.year" --item "PSScene4Band" --asset "analytic" --cmax 0.5 --outfile "\outfile.csv" --overlap 80

现在我们有了一个候选船只的列表,我们可以尝试下载卫星图像文件。

步骤 3-下载船舶图像

这一步听起来很容易,但它花费了我们几个下午和大量的脑细胞。对于在地质数据方面有经验的人来说,这可能并不难。但是我们遇到了一个大问题,地球是圆的。

**是的,地球是圆的。**因此,坐标空间中的简单矩形在卫星图像中不是矩形,反之亦然。长话短说,最后的结论是下载围绕坐标中预期船只位置的小片段。这些被指定为矩形。传回的图像是镶嵌在黑色未定义像素中的扭曲菱形。但是,如果我们指定矩形足够大,我们可以在这个混乱的中间切割一个矩形(在像素空间中),用于我们的训练系统。

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

船舶管道的可视化——如何获得一个中间有一艘船的矩形图像——创造了我自己

使用 porder API ,我们能够简单地在船的位置周围排序小的(坐标方向)矩形片段并下载这些图像。

哦,你知道有上百个坐标系统吗?正常人使用的一个叫做 EPSG-4326,还有一个特别为地中海人准备的…因为地球是圆的,转换并不简单。—这一发现又花了几个小时,但对这个项目来说是不必要的。

步骤 4-找到相应的非船只图像

我们现在已经成功地创建了我们的阳性样本。包含一艘船的那些。现在我们也需要反面的例子。不包含任何船只的卫星图像。这应该不会太复杂,因为海洋非常广阔。但是我不想只拍摄任何卫星图像,而是想要一个尽可能平衡的数据集。

所以我试着从我使用的包含一艘船的同一张卫星图像中获取一张不包含船的图像。这将自动平衡天气和闪电条件以及云和海洋条件。听起来很不错,不是吗?

为了找到一个满足我要求的片段,我创建了一个搜索半径,围绕着我目前想要补充的船。我从这个搜索半径中随机选择了一个区域,并使用 AIS 数据检查了这个区域内没有船只。接下来,我尝试使用 porder API 下载图像。我重复这个过程几次,希望得到每一个船只图像的非船只图像。有时它会失败——要么是因为当时有太多的船只在该区域航行,要么是因为它靠近我定义的 geojson 的边界。如果发生这种情况,我只是在一艘已经被用来创建非船的船上重做这个过程。因为只有大约百分之一的图像是这种情况,我认为这是一个好方法。

第五步——把所有东西放在一起

在我成功下载了 2016 年所选地区的所有数据后,我只需要更好地组织它。我把所有的船归入一艘。csv 文件和所有非船舶在另一个。它们包含 AIS 数据库中可用的所有元数据,如速度、名称等。接下来,我将所有的船图片放入一个基本文件夹,将所有的非船图片放入另一个文件夹(同时记住它们原来的名字和 AIS 条目!).最后,我们添加了一些文档,这样无论是谁,都不会完全迷路。所以数据集上有些闪亮;)

毕竟这是一个相当长的旅程,我非常期待进入创建模型和在这个数据集上评估它们的有趣部分。让我们希望我们能找到小到 3 个像素的船,这样我们就能最终开始处理真正的任务了!

声明:这不仅是我的工作。同事和其他组织提供了很多帮助。仅举几个例子:斯蒂芬、西蒙和佩德罗尽可能地帮助了我。谢谢大家!

我将在介质上发布数据集上的实验更新(如果有效,甚至可能在其他地方)。:)所以保持关注!

已知问题:目测显示我们有相当多的假阴性——所以很多非船图片包括船…

用 pyTigerGraph 创建不和谐聊天机器人

原文:https://towardsdatascience.com/creating-a-discord-chat-bot-with-pytigergraph-8439f1ea9774?source=collection_archive---------48-----------------------

创建一个聊天机器人,用 Discord.py 和 pyTigerGraph 回答 TigerGraph 的问题

什么是项目,为什么要完成它?

一个潜在的热门话题是用图形技术创建聊天机器人。虽然这绝不是一个高级聊天机器人,但它是一种结合 TigerGraph 和 Discord 的力量为 Discord 服务器创建响应机器人的方式。

第一步:创建不和谐的机器人

首先,您需要在 Discord 上创建机器人本身。对于这个项目,我们将使用 Discord.py 。要创建机器人,你需要一个不和谐的帐户,并启用开发模式。然后你应该可以进入申请页面:【https://discord.com/developers/applications

从这里,在右上角,单击“新建应用程序”

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

单击蓝色的“新建应用程序”按钮。

接下来,在提示符下命名您的应用程序。

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

命名后,您应该重定向到该机器人的页面。在这里,在左侧栏,切换到“机器人”,然后点击“添加机器人。”

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

切换到“机器人”,然后点击“添加机器人”

确认后,你就有你的机器人了!最终,你会需要机器人的令牌。要复制它,只需按蓝色的“复制”按钮。

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

用蓝色的复制按钮复制你的机器人令牌

第二步:创建图表

步骤 2a:导入库

图表将在 pyTigerGraph 中创建。首先,确保你已经安装了 pyTigerGraph 和 Discord.py。

pip install pyTigerGraph
pip install discord.py

步骤 2b:开始解决方案

然后,创建一个名为 createGraph.py 或类似的文档。首先,在http;//tgcloud.io/ 创建一个帐户,然后完成以下步骤:

  1. 转到“我的解决方案”,然后单击“创建解决方案”
  2. 单击“空白 v3 ”,然后按下一步两次。
  3. 根据需要编辑解决方案名称、标签和子域,然后按下一步。
  4. 按提交并等待解决方案启动。

步骤 2c:创建连接

一旦解决方案启动,您就可以在您的文档中使用以下内容创建一个连接。首先,导入 pyTigerGraph,然后使用它来创建连接,使用您在第三步中提交的信息作为主机名、用户名和密码。

import pyTigerGraph as tgconn = tg.TigerGraphConnection(host="https://HOST_NAME.i.tgcloud.io", username="USERNAME", version="3.0.5", password="PASSWORD", useCert=True)

步骤 2d:创建模式

接下来,我们将创建一个模式。这种情况下的模式很简单:顶点 Message 和 Word 用一个 MESSAGE_WORD 顶点连接。

conn.gsql('''CREATE VERTEX Word(primary_id word STRING) with primary_id_as_attribute="true"
CREATE VERTEX Message(primary_id id INT, message STRING, url STRING)
CREATE UNDIRECTED EDGE WORD_MESSAGE(FROM Message, To Word)
CREATE GRAPH ChatBot(Word, Message, WORD_MESSAGE)''')

运行此程序后,您将已经在 TigerGraph 中创建了您的图形!恭喜你。接下来,您需要调整连接细节,然后加载数据并编写查询。

conn.graphname = "ChatBot"
conn.apiToken = conn.getToken(conn.createSecret())

步骤三:从 API 中提取数据

为了得到我的数据,我从 https://community.tigergraph.com/的文章中提取。为此,我使用端点 https://community.tigergraph.com/posts.json.从论坛中提取了最近的消息。使用 JSON 库,我加载了“latest_posts”

import requests
import json

x = requests.get("https://community.tigergraph.com/posts.json")
data = json.loads(x.text)["latest_posts"] 

数据有几个重要的部分:raw(整个消息)、id、“topic_slug”和“topic_id”。“topic_slug”和“topic_id”一起可以检索原始 url。

print(data[0]["raw"]) # Message
print(data[0]["id"]) # ID
print("https://community.tigergraph.com/t/" + data[0]["topic_slug"] + "/" + str(data[0]["topic_id"])) # Url

接下来,我们需要将数据加载到图表中。在加载数据之前,我们需要清理数据,删除所有停用词或标点符号。接下来,我们将把它插入图表。

from nltk.corpus import stopwords
from nltk.tokenize import word_tokenizestop_words = set(stopwords.words('english'))for msg in data:  
   raw_msg="<br>".join(("".join(msg["raw"].split(","))).split("\n")) 
   individual_words = raw_msg.split()    
   word_tokens = word_tokenize(raw_msg.lower())    
   filtered_sentence = [w for w in word_tokens if not w in stop_words]    
   filtered_sentence = [w for w in filtered_sentence if not w in [        '.', ',', '!', '?', ':', ';']]
   url = "https://community.tigergraph.com/t/" + msg["topic_slug"] + "/" + str(msg["topic_id"])
   conn.upsertVertex("Message", msg["id"], attributes={"id": msg["id"], "message": msg["raw"], "url": url}) for word in filtered_sentence:        
       conn.upsertVertex("Word", word, attributes = {"word": word})
       conn.upsertEdge("Word", word, "WORD_MESSAGE", "Message", msg["id"])

太好了!现在,您已经将所有数据加载到图表中。接下来,让我们创建机器人!

第四步:创建机器人

现在创建一个新文件。还记得您在第一步中生成的令牌吗?你现在需要它。

我们将首先创建一个不和谐机器人的轮廓。

import discord
import pyTigerGraph as tg
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenizeclient = discord.Client()conn = tg.TigerGraphConnection(host="https://HOST_NAME.i.tgcloud.io", username="USERNAME", version="3.0.5", password="PASSWORD", useCert=True)conn.graphname = "ChatBot"
conn.apiToken = conn.getToken(conn.createSecret())@client.event
async def on_message(msg):
    print(msg.content)@client.event
async def on_ready():
    print(f"We have logged in as {client.user}")client.run("YOUR_DISCORD_TOKEN")

我们要做的所有工作都在 on_message 中。首先,我们将看看消息是否以“??"这个特殊机器人的触发器。接下来,我们将执行与步骤 III 中相同的数据清理步骤。最后,我们将找到消息最相似的帖子并返回它。

现在你可以运行你的机器人,看看结果!

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

机器人对不和谐的结果

第五步:下一步

恭喜你。你创造了一个基本的问答机器人与 TigerGraph 不和!接下来,把这个修改成你自己的。

如果你有任何问题或需要帮助,请加入 TigerGraph Discord。

https://discord.gg/7ft9PNZAM6

祝你好运!

注:所有图片,除特别注明外,均为作者所有。

幻想板球——线性规划的应用

原文:https://towardsdatascience.com/creating-a-fantasy-cricket-team-application-of-linear-programming-4b60c261702d?source=collection_archive---------4-----------------------

使用 Python(纸浆包)的分步指南

印度超级联赛(IPL)是全球最大的国内板球联赛。2020 年,IPL 冠名赞助商是 Dream11。Dream11 是一个基于印度的梦幻运动平台。它允许用户玩梦幻板球、曲棍球、足球、卡巴迪和篮球。

在本文中,我们将把规定性分析应用到体育运动中,我们将重点选择一个梦幻板球队,以其中一场比赛为例。

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

图片来自 Unsplash: 来源

简而言之,梦幻蟋蟀

如果你是幻想板球的新手,那么这就是它是如何工作的

  • 用户需要创建一个幻想板球队
  • 然后,用户可以与这支队伍一起参加竞赛。
  • 每个玩家被分配一个信用值。一个团队总积分是有上限的。
  • 每个球员将属于以下类别之一:击球手,守门员,投球手,全才
  • 在比赛中,分数是根据运动员的表现和类别来分配的。
  • 在比赛结束时,根据得分,遵守所有规则的得分最高的球队将是最佳 11 名球员的获胜组合。

游戏规则

建立一个梦幻团队需要遵循一套规则。

不同的幻想平台的规则可能会有所不同,需要相应地调整。

  • 一个队总共应该有 11 名队员
  • 队里应该有 1 到 3 名全才
  • 队里应该有 1 到 3 名守门人
  • 队里应该有 3 到 6 名击球手
  • 该队应该有 3 到 6 名投球手
  • 每一方应该有 4 到 7 名队员
  • 团队的总积分不应超过 100 分

如何挑选球员

此外,对于每场比赛,每个球员都可以获得以下信息:

  1. 玩家在同一锦标赛的前几场比赛中的得分
  2. 玩家每场比赛的平均得分
  3. 球员在同一赛事的过去比赛中进入前 11 名球队的次数
  4. 球员在过去进入最佳 11 队的次数百分比

以上任何一个指标都可以用来挑选最好的团队。

线性规划

运筹学中的线性规划是一种科学技术,用于通过考虑资源稀缺和约束来获得给定商业问题的最优解决方案。

线性规划允许我们将现实生活中的问题建模成由线性关系表示的数学模型。它涉及一个目标函数,该目标函数基于必须实现的目标和作为线性不等式的约束的创建来定义。顾名思义,目标函数和约束之间的关系本质上应该是线性的(一次方程)。

线性规划的快速回顾

这里有一个简单的例子来快速回顾线性编程。

线性规划中的基本术语

**目标函数:**目标函数是我们试图求解的线性函数。基于我们试图解决的问题,这个函数的值需要最小化或最大化。

**决策变量:**作为输入来决定最终输出的变量称为决策变量。它也被称为目标变量。

**约束:**约束是对决策变量的限制。

最终的目标函数必须在应用了所有约束的决策变量上实现。这是一个简单的线性规划问题的例子。

简单的例子

比方说,我们想要最大化 z,给定两个变量 x & y,它们需要遵循给定的约束。

**目标函数:**最大化 z,其中 z= 2x + 3y

决策变量: x & y

约束: x>= 0
y>= 1
x+2y<= 15
-2x+4y>=-7
-2x+y<= 4

绘制上述约束条件的所有线条,可得到如下图表。这里,阴影区域是所有上述约束都成立的公共区域。

线性规划的目标是在这个阴影区域内确定 x 和 y 的值,这将提供 z 的最大可能值。

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

简单的例子——线性规划(图片由作者提供)

解这个线性程序给出了 z 的最大值,在 x=9 & y=3 时为 27。

:参考文末提供的 git repo 访问 Python 代码生成上图也是用 PuLP 解决这个线性规划问题。

幻想板球&线性编程

线性规划可以用来解决许多现实生活中的问题,幻想板球就是其中之一。

要创建一个梦幻团队,你需要根据目标选择最好的球员。最终形成的团队应该遵循平台规定的所有规则或约束。

这使得它成为一个可以用线性规划解决的完美问题。我们需要在尊重给定的预算(学分)和团队组成约束的同时,最大化团队的选择度量投影。

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

用一个简单的例子理解线性规划,并用 Fantasy Team Generation 进行映射(图片由作者提供)

上面的映射说明了线性规划的每个基本组成部分是如何与一个简单的例子和这个组建梦幻团队的案例研究联系起来的。

什么是纸浆?

PuLP 是一个解决优化问题的开源 python 包。它提供了将数学程序转换成可以输入解算器的形式的接口。

通过提供代表优化问题和决策变量的 Python 对象,并允许以与原始数学表达式非常相似的方式表达约束,PuLP 完全在 Python 语言的语法内工作。

为了保持语法尽可能简单和直观,PuLP 专注于支持线性和混合整数模型。

纸浆支持像 GLPK,CPLE,硬币,古罗比解决方案。默认情况下,纸浆使用 CBC 解算器(硬币或分支切割解算器)。

有关纸浆的更多详情,请参考以下链接:https://pypi.org/project/PuLP/

使用 PuLP 解决 Python 中的线性问题

我们将使用 python 包 PuLP 来创建线性问题并解决它。

除了所提供的规则之外,还可以为用户添加额外的约束来进行游戏并创建最适合的团队。

一旦确定了一个最佳解决方案,它将产生一个梦幻团队以及一些概要细节。此外,我们将使用 ipywidgets 包来构建 Jupyter 笔记本中的用户界面,这样我们就可以处理约束了。

下面的代码片段是完整代码的一部分,有助于读者理解逻辑流程。

软件包安装

除了像 NumPy,pandas,sklearn 这样的常规包,这个代码还需要安装纸浆。如果您正在使用 pip,所有的软件包都可以用“pip install pulp”命令安装。

输入数据

这个程序需要两种输入。一个是玩家细节,另一个是用户配置来构建线性问题。

球员的详细资料是在 CSV 文件中创建的,该文件被读入熊猫数据帧。该文件的示例内容如下所示。

该数据目前无法在网上获得,并且是针对本案例研究手工整理的。

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

输入数据的样本内容(图片由作者提供)

创建线性规划问题

解决线性规划问题的第一步是创建问题。这可以使用纸浆包装来完成。

创建决策变量

准备创建目标函数和约束所需的决策变量。

应该为每个约束条件创建类似的变量。上面显示的是一个例子。同样的方法可以用来创建所有需要的变量。

定义目标函数

这里,目标函数可以基于以下之一来定义:

  • 基于每个玩家的点数最大化
  • 根据玩家过去在最佳 11 队的次数最大化
  • 基于每场比赛的平均分数最大化
  • 根据玩家在最佳 11 队中的百分比次数最大化

这种选择可以交给用户来配置,基于这种选择可以设置目标函数。

添加约束

一旦创建了线性规划问题并定义了目标函数,我们现在就可以为问题添加约束了。

基于玩家数量的限制

最终的队伍中应该正好有 11 名队员。这个条件可以用下面的约束来设置。

基于第 1 队队员的约束

每个队可以有 4 到 7 名队员。如果需要,用户可以进一步配置。

基于阵容中球员的约束

由于只有在掷硬币时(通常在比赛开始前 30 分钟)才知道比赛 11,所以可以对要挑选的运动员增加限制。

  • 从所有玩家中选择(默认)
  • 只选择参加过最后一场比赛的球员
  • 只选择至少打过一场比赛的球员
  • 只选择比赛中的 11 名球员

以上是不同约束的一些例子。类似地,可以设置所有需要的约束。

准备解决?

既然已经添加了约束条件并定义了目标函数,我们就可以解决这个问题了。

既然目标是目标最大化,那就相应地给问题设置客观细节,让纸浆去解决。

数学程序的纸浆表示

一旦向纸浆提供了要解决什么的细节,我们就可以通过打印问题对象来显示问题细节。

打印问题的输出示例如下。为了便于说明,这里我们只考虑了 3 个约束。请参考 git repo 查看所有约束的结果。

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

纸浆问题表述样本输出(图片由作者提供)

解决线性规划问题主要有三种类型的信息:

  1. 必须最大化或最小化的目标函数
  2. 最大化/最小化时需要遵循的约束或规则
  3. 必须应用目标函数和约束的输入变量

现在让我们试着去理解纸浆的内部表现。

目标函数的纸浆表示

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

纸浆中目标函数的表示(图片由作者提供)

  • 记住,我们创建了目标二进制变量来决定每个玩家是否会在幻想队中
  • 每个玩家都有一个唯一的玩家号,用于创建该玩家的标识符
  • 我们已经将目标函数设置为基于玩家点数最大化
  • 纸浆使用这些信息来导出目标函数,该函数是每个玩家的加权分数总和。
  • 这个线性规划问题的目标是找到一个组合的球员,将最大化这个总和。

纸浆对约束的表示

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

纸浆中约束的表示(图片由作者提供)

  • 因为我们在这里处理的是二元目标变量,所以考虑了所有匹配约束的玩家的总和
  • 例如,对于检票口看守人的约束,只考虑 WK 类型的玩家号码。类似的其他类型如击球手和投球手。
  • PuLP 将在内部保存添加到 LPProblem 的所有约束。最终的最优解将只考虑满足所有约束的组合。

变量的纸浆表示

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

纸浆中的决策/目标变量表示(图片由作者提供)

  • 将为数据集中的所有玩家创建决策/目标变量。
  • 目标函数和约束仅应用于这组变量

解释结果

纸浆将试图通过确定最佳选择来解决问题,该最佳选择将最大化目标函数,并且还满足所有已设置的约束。

如果在给定的约束条件下找不到任何可行的解决方案,那么它将返回不可行的状态。在这种情况下,PuLP 删除无法满足的约束,并返回一个输出。

抽样输出

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

作者图片

求解器的性能

由于数据很小,只有 46 个变量,因此求解器的性能不成问题。在我的本地系统(16 GB 内存)中,这一过程不到一秒钟。

求解器通过 32 次迭代找到一个最高得分为 2731 的最优解,以确定给定约束条件下的最终 11 名球员。

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

来自 CBC 求解器的日志(图片由作者提供)

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

最终最优解日志(图片作者提供)

摆弄数据

为了使应用程序更具交互性,使用了 ipywidgets,以便用户可以在 Jupyter 笔记本上选择配置值。

我们不会详细讨论在 Jupyter 笔记本上创建小部件的细节,因为已经有大量的文档可用,而且这也不是我们这里的重点。

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

作者图片

这些配置在内部被转换成目标函数或约束条件。

配置和创建团队—示例结果

给出你选择的约束条件,然后点击“创建梦幻团队”按钮。

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

作者图片

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

作者图片

砰!!!你已经准备好和你的梦幻团队一起开始参加比赛了!!一切顺利:-)

结论

本文是一个简单的例子,展示了如何将线性优化技术应用到板球比赛中来挑选最佳球员。线性优化的原则可以应用于许多有着简单目标的问题。

试试看,玩玩。为了探索更多,我们可以为每个玩家获取更多的历史数据,并将其添加到选择约束中。虽然这可能不会使精英队总是,但它肯定会指导用户选择球队。

**免责声明:**奇幻团队仅基于提供的数据和给出的约束条件进行提示。不能保证这些球员在比赛结束时会进入最佳 11 强。请在挑选团队时使用您自己的判断:-)

使用 Python 和 Streamlit 创建财务仪表板

原文:https://towardsdatascience.com/creating-a-financial-dashboard-using-python-and-streamlit-cccf6c026676?source=collection_archive---------10-----------------------

使用 Streamlit 库显示来自 Yahoo Finance 的财务数据

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

注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语

最近的轶事,日交易者在“深入”的价格图表分析后,用 OTM 看涨期权将他们的净值翻了三倍,导致了对一般投资尤其是股票的某种扭曲的看法。正是在这种乐观(或繁荣)的时期,向乔尔·格林布拉特这样的伟大投资者求助,可能会让我们对投资者在交易期权或买卖股票时最终押注的到底是什么有一个更有根据的理解。

“股票……不是一张纸,你可以在上面标上夏普比率和索丁诺指数……它们是企业的所有权股份,你对其进行估值,并试图以折扣价购买。”—乔尔·格林布拉特[1]

这表明,想要在一段时间内跑赢市场的投资者不应该通过在期权市场上鲁莽交易来实现这一目标。相反,格林布拉特建议,任何积极投资的方法都应该基于对公司基本面数据的分析。

在这一点上,值得一提的是,关于市场对证券进行充分定价的能力,长期以来一直存在一个更为根本性的争论(例如,参见 Fama [2]和 Shiller [3])。这场辩论的最终结果,反过来,对最初参与积极的投资组合管理的优点有着重大的影响。然而,这种担心不应该是本文的主题,我将做出(可能不准确的)假设,即积极的投资组合管理是有价值的。

鉴于成功的积极投资需要对公司财务状况的详细了解,剩下的核心问题是从哪里获得这些信息以及如何解读这些信息。虽然存在像彭博终端这样的巨大信息源,但大多数散户投资者没有通过购买此类服务的年度订阅来破产的冲动。在初步研究的情况下,我个人使用雅虎财经(Yahoo Finance)这样的免费产品,这些产品可以汇总财务信息,无需翻查冗长的年度和季度报告。

虽然我认为雅虎财经在提供对公司基本面的初步了解方面做得很好,但它没有提供某些重要的指标,其他指标也很难找到。

为了获得简明、易于理解的上市公司快照,我使用了一些 Python 自动化来编写一个财务仪表板应用程序。在这里,可能需要注意的是,我的编程技能肯定是不合格的,我确信有一种更好的方法来解决我的问题。因此,下面的文章应该是对 Python 和 Streamlit 潜力的证明,而绝不是编程教程。

财务仪表板应用程序

Streamlit 是一个 Python 包,它使得创建仪表板和数据应用程序变得非常容易,而不需要任何前端编程专业知识。该库可用于创建如下所示的应用程序,该应用程序允许用户输入公司股票代码,并根据公司最新的财务数据获得财务比率:

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

最终仪表板的预览

收集数据

为了收集作为应用程序输入的数据,使用 yahoo_fin 包非常有用。这个包从 Yahoo Finance 中抓取信息,并以 pandas DataFrames 的形式返回,而 pandas data frames 又可以很好地与 Streamlit 集成。

class Company:
    def __init__(self, ticker):
        price_df = si.get_data(ticker, dt.datetime.now()-           dt.timedelta(days=2*365), dt.datetime.date(dt.datetime.now()))
        overview_df = si.get_stats(ticker)
        overview_df = overview_df.set_index('Attribute')
        overview_dict = si.get_quote_table(ticker)
        income_statement = si.get_income_statement(ticker)
        balance_sheet = si.get_balance_sheet(ticker)
        cash_flows = si.get_cash_flow(ticker)

由此产生的数据框架可用于提取所需的信息,如公司市值或损益表指标,如 EBIT 或净收入。

self.year_end = overview_df.loc['Fiscal Year Ends'][0]
self.market_cap = get_integer(overview_dict['Market Cap'])
self.market_cap_cs = '{:,d}'.format(int(self.market_cap))
self.prices = price_df['adjclose']

self.sales = income_statement.loc['totalRevenue'][0]
self.gross_profit = income_statement.loc['grossProfit'][0]
self.ebit = income_statement.loc['ebit'][0]
self.interest = - income_statement.loc['interestExpense'][0]
self.net_profit = income_statement.loc['netIncome'][0]

最后,这些数据可以用来计算估值倍数或利润率等指标。此外,我计算了我的应用程序的流动性、杠杆和效率比率。

def get_overview(self):
        self.price_earnings_ratio = self.market_cap/self.net_profit
        self.ev_sales_ratio = self.ev/self.sales
        self.overview_dict = {
            'Values' : [self.ev_cs, self.market_cap_cs, self.ev_sales_ratio, self.price_earnings_ratio]
            }

def get_profit_margins(self):
        self.gross_margin = self.gross_profit/self.sales
        self.operating_margin = self.ebit/self.sales
        self.net_margin = self.net_profit/self.sales
        self.profit_margin_dict = {
            'Values' : [self.gross_margin, self.operating_margin, self.net_margin]
            }

显示数据

如前所述,Streamlit 使得以结构化的方式显示这些信息变得非常容易,只需很少的额外工作。在我的例子中,我只是添加了应用程序的标题和一个允许用户输入公司股票的文本字段。通过单击“Search”按钮,执行上面显示的代码行并收集数据。

st.title('Financial Dashboard')
ticker_input = st.text_input('Please enter your company ticker:')
search_button = st.button('Search')

if search_button:
    company = Company(ticker_input)
    company.get_overview()
    company.get_profit_margins()
    company.get_liquidity_ratios()
    company.get_leverage_ratios()
    company.get_efficiency_ratios()

Streamlit 提供了强大的功能,有助于通过折线图、表格或条形图等方式显示数据。

st.header('Company overview')
    overview_index = ['Enterprise value', 'Market cap', 'EV/sales ratio', 'P/E ratio']
    overview_df = pd.DataFrame(company.overview_dict, index = overview_index)
    st.line_chart(company.prices)
    st.table(overview_df)

    with st.beta_expander('Profit margins (as of {})'.format(company.year_end)):
        profit_margin_index = ['Gross margin', 'Operating margin', 'Net margin']
        profit_margin_df = pd.DataFrame(company.profit_margin_dict, index = profit_margin_index)
        st.table(profit_margin_df)
        st.bar_chart(profit_margin_df)

在我的例子中,结果如下所示:

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

最终控制面板,左侧是公司概况,右侧是更多指标

结束语

在我看来,Streamlit 非常容易使用,并且有很好的文档记录,使得显示和解释数据变得简单明了。我承认我的应用程序仍然相当有限,并且有许多额外的功能,一个更熟练的程序员可以集成。

总的来说,我认为增加基本指标的可用性和可访问性,如利润率或杠杆率,可以更好地了解公司的财务状况。这反过来可能会导致更明智的投资决策,这可能有助于投资者长期跑赢市场。

放弃

上面提供的代码只是将 Python 编程应用于金融领域的一个练习。本文包含的信息不应用于投资决策。此外,从雅虎财经收集的信息不应用于任何商业目的。

[1]https://www.youtube.com/watch?v=V8Zuw8Mnc-I
【2】法玛,E. F. (1970)。有效资本市场:理论与实证研究综述。《财经杂志》25 (2),383–417 页。
[3]希勒,R.J. (1981 年)。股票价格波动太大,以至于不能用随后的股息变化来解释吗?《美国经济评论》,第 71 期 (3),第 421–436 页。

在 Python 中创建创新的自定义损失函数

原文:https://towardsdatascience.com/creating-a-innovative-custom-loss-function-in-python-using-tensorflow-and-fitting-a-lstm-model-ded222efbc89?source=collection_archive---------20-----------------------

在 python 中使用 Tensorflow 包并使用 LSTM 模型进行测试

这里我想介绍一个创新的新损失函数。我将这个新的损失函数定义为 MSE-MAD。使用指数加权移动平均框架并结合使用 MSE 和 MAD 来构建损失函数。MSE-MAD 的结果将使用适合太阳黑子数据的 LSTM 模型进行比较。

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

图片来源【https://algorithm ia . com/blog/introduction-to-loss-functions】经作者允许编辑。

介绍

在我们进入新的损失函数之前,让我先介绍一下什么是损失函数,以及它如何应用于机器学习。损失函数的目的是衡量模型对输入数据的解释程度。换句话说,损失函数是我们的预测与响应变量之间距离的度量。在几乎所有的应用中,我们都有一个固定的模型,目标是在给定一些数据的情况下估计模型的参数。

在我介绍这个新的损失函数之前,我将首先介绍一些基本的损失函数以及它们在模型拟合期间的表现。

均方误差

均方差是我要介绍的第一个损失函数。均方误差(MSE)的计算公式如下

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

均方误差

根据 MSE 公式,hat 表示变量 y 的预测值或估计值。在数学中,变量上方的 hat 表示给定随机变量的估计值。n 代表我们估计的总数据点的数量。从某种意义上说,MSE 公式所做的只是测量每个预测与响应变量之间的距离,并对距离求平方,然后对所有测量值求平均值。下图用虚线显示了模型,每个数据点用绿色显示。

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

误差测量

python 中 MSE 的实现如下。

def MSE(y_predicted, y):
  squared_error = (y_predicted - y) ** 2
  sum_squared_error = np.sum(squared_error)
  mse = sum_squared_error / y.size
  return(mse)

平均绝对偏差

下一个损失函数是平均绝对偏差(MAD)。MAD 的公式如下所示

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

平均绝对偏差

在 MAD 函数的实现中,我使用 TensorFlow 包来计算平均值。

def MAD(y_true, y_pred):   
   mean =  tf.reduce_mean((y_true - y_pred))
   mad = tf.reduce_mean((y_true - mean)
   return(mad)

MSE-MAD 损失函数

这里我介绍一下自定义损失函数。这个损失函数的背景使用 EWMA 框架,其中我们的阿尔法项固定在 0.5。简单地说,损失函数是 MSE 和 MAD 公式的组合。

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

MSE-MAD 损失函数

def custom_loss_function(y_true, y_pred):
   squared_difference = tf.square((y_true - y_pred))
   mse = tf.reduce_mean(squared_difference, axis=-1)
   mean =  tf.reduce_mean((y_true - y_pred))
   mad = tf.reduce_mean((y_true - y_pred) - mean)
   return 0.5*mse + (1-0.5)*mad

使用 LSTM 模型的损失函数比较

首先,我介绍用于比较的数据集和机器学习模型。正在使用的数据集太阳黑子数据集和 LSTM 模型将用于预测太阳黑子时间序列。

LSTM 模式介绍

递归神经网络是用于建模时间序列数据的人工神经网络家族的一部分。递归神经网络结合先前的信息来预测当前的时间步长。给定一个输入向量 x = (x1,.。。,xn),我们假设每个 xi 独立于 x 中的每个其他观察值。但是,对于资产数据,这可能不成立,需要创建一个模型来说明某些给定时间序列数据的动态行为。对于给定数量的先前时间步骤,使用人工神经网络来构建递归神经网络的结构。在这篇论文中,我们探讨了 RNN 在预测未来股票价格中的应用。使用 RNN 的主要缺点是在尝试将模型参数拟合到数据时渐变会消失和爆炸

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

LSTM 门

每个块 A 代表具有输入 xt 和输出 ht 的神经网络。LSTM 背后的主要思想是遗忘之门,信息可以通过它传递给下一个神经网络。

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

LSTM 建筑

LSTM 模型成为时间序列预测的有力工具。

黑子数据集游戏攻略

该数据集包含太阳黑子数量的月度数据(从 1749 年到 2013 年)。有 3000 多个数据点。我们演示数据集的前几行。

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

从上表中我们可以看到,我们得到了包含太阳黑子数量的每月数据。当拟合 LSTM 模型来预测时间序列数据时,我们将要求值限制在 0 和 1 之间。

对于 LSTM 模型,模型结构由输入数据的结构和预测特征决定。取决于在拟合时有多少个月用于回顾,特征的数量将决定需要权重和偏差的神经元的数量。

为了在比较每个损失函数时保持一致,将使用相同的 LSTM 模型结构,如下所示。

# Initializing the LSTM
regressor = Sequential()
# Adding the first LSTM layer and some Dropout regularisation
regressor.add(LSTM(units = nodes, return_sequences = True, input_shape = (new.shape[1], new.shape[2])))
regressor.add(Dropout(0.2))
# Adding a second LSTM layer and some Dropout regularisation
regressor.add(LSTM(units = nodes, return_sequences = True))
regressor.add(Dropout(0.2))
# Adding a third LSTM layer and some Dropout regularisation
regressor.add(LSTM(units = nodes, return_sequences = True))
regressor.add(Dropout(0.2))
regressor.add(LSTM(units = nodes))
regressor.add(Dropout(0.2))
# Adding the output layer
regressor.add(Dense(units = t)) # this is the output layer so this represents a single node with our output value

既然我们已经编译了模型。我首先测试 MSE 损失函数作为基线。

# Compiling the RNN
regressor.compile(optimizer = 'adam', loss = 'mean_squared_error')
# Fitting the RNN to the Training set
model = regressor.fit(new, y_train, epochs = 50, batch_size = 22)

损失函数在编译步骤中设置。

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

接下来我研究了 Huber 损失函数。我测试 Huber 损失函数的原因是它遵循与 MSE-MAD 相似的结构,其中 Huber 函数充当组合函数或分段函数。

# Compiling the RNN
regressor.compile(optimizer = 'adam', loss = "huber_loss")
# Fitting the RNN to the Training set
model = regressor.fit(new, y_train, epochs = 50, batch_size = 22)

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

胡伯损失函数

最后我给出了 MSE-MAD 损失函数的结果。实现是简单地将损失函数定义为 python 函数,然后在编译模型时以下面的方式调用它。

# Compiling the RNN
regressor.compile(optimizer='adam', loss=custom_loss_function)
# Fitting the RNN to the Training set
model = regressor.fit(new, y_train, epochs = 50, batch_size = 22)

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

MSE-MAD 损失函数

当比较 MSE-MAD 和 MSE 时,我们发现收敛大约是一半快,然而当我们比较 MSE-MAD 和 huber 损失函数时,我发现非常相似的结果。

LSTM 预言

下面使用自定义损失函数给出了 LSTM 的最终预测。使用覆盖速度更快的损失函数的主要好处是运行时间更短,并且可以更快地求解模型的最佳参数。

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

关于我自己的一点点

我最近在加拿大多伦多的瑞尔森大学获得了应用数学硕士学位。我是金融数学组的一员,专业是统计学。我深入研究了波动建模和算法交易。

我之前在庞巴迪宇航公司担任工程专业人员,负责与飞机维护相关的生命周期成本建模。

本人积极训练铁人三项,热爱健身。

推特:@Ethan_JS94

使用 SQL 创建机器学习模型

原文:https://towardsdatascience.com/creating-a-machine-learning-model-with-sql-81d843a5307c?source=collection_archive---------20-----------------------

在 Google Big Query 上使用 SQL 构建 ML 模型

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

迈克尔·泽兹奇在 Unsplash 上的照片

尽管机器学习已经非常先进了,但是它有一些弱点,让你很难使用它。

当前机器学习工作流及其问题

  • 如果你曾经使用过 ml 模型,你可能会意识到结构和准备它们是非常耗时的。
  • 对于典型的信息,研究人员最初应该将有限数量的信息从存储在 I-Python 便笺簿中的信息交换到负责结构的信息中,比如 Python 的 pandas。
  • 如果您正在装配一个定制模型,您首先需要更改和预处理所有信息,并在处理模型信息之前完成所有组件设计。
  • 然后,在那一点上,最后在你制作了你的模型并且说 TensorFlow 是另一个可比较的库之后,然后你在你的 PC 或 VM 上用一个小模型本地地训练它,然后,在那一点上,期望你返回并且制造所有更多的新信息包括并且进一步开发执行,你反复反复反复反复此外,这很难,所以你在几个周期之后停止

但是嘿,别担心!即使您不是团队的数据科学家,您也可以构建模型。

Google BigQuery 简介

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

照片由 帕特里克

BigQuery 是一个完全托管的 Pb 级企业数据仓库。它基本上由两个关键部分组成

  • 快速 SQL 查询引擎
  • 完全托管的数据存储

Big Query 支持用大家都习惯的标准 SQL 查询 Pb 级的数据。

示例:

#standardSQL
SELECT
COUNT(*) AS total_trips
FROM
`bigquery-public-data.san_francisco_bikeshare.bikeshare_trips`

其他主要查询功能

  1. 无服务器
  2. 灵活的定价模式
  3. 标准 GCP 数据加密和安全
  4. 非常适合 BI 和 AI 用例
  5. ML 和使用 BigQuery 的预测建模
  6. 非常便宜的存储—与谷歌云存储桶一样
  7. 使用 BigQuery BI 引擎进行交互式数据分析—连接到 tableau、data studio、looker 等

大查询及其 ml 特性

作为主要功能之一的一部分,big query 允许仅使用简单的 SQL 语法来构建预测性的机器学习模型。借助 google cloud 的 Pb 级处理能力,您可以在仓库中轻松创建模型。创建模型的示例语法如下所示

CREATE OR REPLACE MODEL `dataset.classification_model`
OPTIONS
(
model_type='logistic_reg',
labels = ['y']
)
AS

使用大查询 ML 的典型工作流程[5 个步骤]

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

作者提供的流程图

教程:使用大查询 ML(简单 SQL 语法)构建分类模型

你可以打开一个大的查询控制台,开始复制下面的步骤:

你可以在 youtube 上观看视频教程

Anuj Syal用 SQL(谷歌大查询)创建机器学习模型

资料组

我正在使用一个公共的大型查询数据集 google_analytics_sample 。该数据集提供了 12 个月(2016 年 8 月至 2017 年 8 月)来自谷歌商品商店的模糊谷歌分析 360 数据。数据包括电子商务网站会看到的典型数据,包括以下信息:

流量来源数据:关于网站访问者来源的信息,包括关于有机流量、付费搜索流量和显示流量内容数据:关于用户在网站上的行为的信息,如访问者查看的页面的 URL,他们如何与内容进行交互等。交易数据:谷歌商品商店网站上的交易信息。

**数据集许可:**公共数据集是指存储在 BigQuery 中并通过 Google Cloud 公共数据集计划向公众开放的任何数据集。公共数据集是 BigQuery 托管的数据集,供您访问并集成到应用程序中。谷歌为这些数据集的存储付费,并通过一个项目提供对数据的公共访问。您只需为对数据执行的查询付费。每月第一个 1 TB 是免费的,具体价格视查询情况而定。在知识共享署名 4.0 许可下

我们将尝试解决的机器学习问题

我们将尝试预测用户是否会在回访时购买产品,因此我们将我们的标签命名为will_buy_on_return_visit

步骤 1:探索数据集

  • 检查兑换率
WITH visitors AS(
SELECT
COUNT(DISTINCT fullVisitorId) AS total_visitors
FROM `bigquery-public-data.google_analytics_sample.ga_sessions_20170801`
),
purchasers AS(
SELECT
COUNT(DISTINCT fullVisitorId) AS total_purchasers
FROM `bigquery-public-data.google_analytics_sample.ga_sessions_20170801`
WHERE totals.transactions IS NOT NULL
)
SELECT
  total_visitors,
  total_purchasers,
  total_purchasers / total_visitors AS conversion_rate
FROM visitors, purchasers
  • 销量前 5 的产品是什么?
SELECT
  p.v2ProductName,
  p.v2ProductCategory,
  SUM(p.productQuantity) AS units_sold,
  ROUND(SUM(p.localProductRevenue/1000000),2) AS revenue
FROM `bigquery-public-data.google_analytics_sample.ga_sessions_20170801`,
UNNEST(hits) AS h,
UNNEST(h.product) AS p
GROUP BY 1, 2
ORDER BY revenue DESC
LIMIT 5;
  • 有多少访问者在随后的访问中购买了该网站?
WITH all_visitor_stats AS (
SELECT
  fullvisitorid, # 741,721 unique visitors
  IF(COUNTIF(totals.transactions > 0 AND totals.newVisits IS NULL) > 0, 1, 0) AS will_buy_on_return_visit
  FROM `bigquery-public-data.google_analytics_sample.ga_sessions_20170801`
  GROUP BY fullvisitorid
)
SELECT
  COUNT(DISTINCT fullvisitorid) AS total_visitors,
  will_buy_on_return_visit
FROM all_visitor_stats
GROUP BY will_buy_on_return_visit

第二步。选择要素并创建训练数据集

现在我们对数据有了更多的了解,让我们最终确定并创建一个用于训练的最终数据集

SELECT
  * EXCEPT(fullVisitorId)
FROM
  # features
  (SELECT
    fullVisitorId,
    IFNULL(totals.bounces, 0) AS bounces,
    IFNULL(totals.timeOnSite, 0) AS time_on_site
  FROM
    `bigquery-public-data.google_analytics_sample.ga_sessions_20170801`
  WHERE
    totals.newVisits = 1)
  JOIN
  (SELECT
    fullvisitorid,
    IF(COUNTIF(totals.transactions > 0 AND totals.newVisits IS NULL) > 0, 1, 0) AS will_buy_on_return_visit
  FROM
      `bigquery-public-data.google_analytics_sample.ga_sessions_20170801`
  GROUP BY fullvisitorid)
  USING (fullVisitorId)
ORDER BY time_on_site DESC
LIMIT 10;

步骤 3:创建一个模型

此步骤对上一步中创建的数据集使用 create model 语句

CREATE OR REPLACE MODEL `ecommerce.classification_model`
OPTIONS
(
model_type='logistic_reg',
labels = ['will_buy_on_return_visit']
)
AS
#standardSQL
SELECT
  * EXCEPT(fullVisitorId)
FROM
  # features
  (SELECT
    fullVisitorId,
    IFNULL(totals.bounces, 0) AS bounces,
    IFNULL(totals.timeOnSite, 0) AS time_on_site
  FROM
    `bigquery-public-data.google_analytics_sample.ga_sessions_20170801`
  WHERE
    totals.newVisits = 1)
  JOIN
  (SELECT
    fullvisitorid,
    IF(COUNTIF(totals.transactions > 0 AND totals.newVisits IS NULL) > 0, 1, 0) AS will_buy_on_return_visit
  FROM
      `bigquery-public-data.google_analytics_sample.ga_sessions_20170801`
  GROUP BY fullvisitorid)
  USING (fullVisitorId)
;

步骤 4:评估分类模型性能

使用 SQL 评估您刚刚创建的模型的性能

SELECT
  roc_auc,
  CASE
    WHEN roc_auc > .9 THEN 'good'
    WHEN roc_auc > .8 THEN 'fair'
    WHEN roc_auc > .7 THEN 'not great'
  ELSE 'poor' END AS model_quality
FROM
  ML.EVALUATE(MODEL ecommerce.classification_model,  (
SELECT
  * EXCEPT(fullVisitorId)
FROM
  # features
  (SELECT
    fullVisitorId,
    IFNULL(totals.bounces, 0) AS bounces,
    IFNULL(totals.timeOnSite, 0) AS time_on_site
  FROM
    `bigquery-public-data.google_analytics_sample.ga_sessions_20170801`
  WHERE
    totals.newVisits = 1
    AND date BETWEEN '20170501' AND '20170630') # eval on 2 months
  JOIN
  (SELECT
    fullvisitorid,
    IF(COUNTIF(totals.transactions > 0 AND totals.newVisits IS NULL) > 0, 1, 0) AS will_buy_on_return_visit
  FROM
      `bigquery-public-data.google_analytics_sample.ga_sessions_20170801`
  GROUP BY fullvisitorid)
  USING (fullVisitorId)
));

未来步骤和特征工程

如果您对提高模型的性能更感兴趣,可以随时选择向数据集添加更多要素

结论

像谷歌的 Big Query ML 这样的产品让更多人可以建立机器学习模型。有了简单的 SQL 语法和谷歌的处理能力,生产现实生活中的大数据模型真的很容易。

最初发表于【https://anujsyal.com】

创建电影分级模型第 1 部分:数据收集!

原文:https://towardsdatascience.com/creating-a-movie-rating-model-part-1-data-gathering-944bee6167c0?source=collection_archive---------14-----------------------

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

电影分级模型

通过收集我们需要的数据,开始创建电影分级预测模型的过程

你好,朋友们!欢迎来到一个新的系列,我从这篇关于创建电影分级预测模型的文章开始。在开始写这篇文章之前,我想快速提一下,我绝对没有放弃 Terraform + SageMaker 系列。我刚刚度过了一个超级忙碌的夏天,有很多事情要做,所以我暂时停止了写博客。这方面还有更多的内容,敬请关注!

我开始这个新系列的原因是一个有趣的原因。我是播客的忠实听众,我最喜欢的播客之一叫做https://www.podcastone.com/the-watercooler。这是一个轻松的播客,五个同事在一天结束后聚在一起谈论,嗯,几乎是天底下的一切!他们也有一些重复出现的片段,包括主持人之一卡兰·比恩(Caelan Biehn)将为不同的电影提供评级。他的评级实际上由两个分数组成:一个是简单的“赞成/不赞成”,另一个是一个介于 0 和 10 之间的十进制浮动分数,他称之为“Biehn 标度”。(顺便说一下,卡兰是演员迈克尔·比恩的儿子,他曾主演过《终结者**外星人等电影。)**

水冷器这些家伙真的很吸引他们的观众,所以有一次我在他们的脸书小组里开玩笑说,我应该围绕卡兰的电影评级创建一个电影评级预测模型。他们都觉得很好玩,我也觉得会很好玩,所以我们就来了!

在深入探讨这篇文章的主要目的——数据收集——之前,让我们在继续构建我们的模型的过程中,为我们将在整个系列中做的事情打下基础。和往常一样,非常欢迎您关注我的 GitHub 库中的代码。

项目范围和流程

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

作者创作的流动艺术品

如上所述,Caelan 为每个电影评级提供了两个分数:一个二元的“同意/不同意”和一个 0 到 10 的浮动分数。当然,这意味着我们需要创建两个预测模型:一个处理二元分类,另一个是更基于回归的模型。我有意不坚持一个特定的算法,因为我们将使用未来的帖子来验证一些算法,看看哪一个执行得最好。

为此,上面的流程图显示了我们将如何在整个系列中前进。在第一阶段(也就是本文),我们需要从各种来源收集数据来支持我们的模型。一旦我们收集了我们的数据,我们将需要执行所有适当的特征工程,以准备我们的数据通过我们各自的算法。接下来,我们将尝试几种不同的算法以及超参数调整,看看哪种算法的性能最好。一旦我们决定了要利用哪些算法,我们将创建一个完整的模型培训管道来实际创建预测模型。最后,我们将把训练好的模型包装在一个漂亮的推理 API 中!

在继续之前,有一点需要注意:我不一定要在这里创建一个完美的模型。在我的日常工作中,我是一名机器学习工程师,这个角色的范围更侧重于模型部署,而不是模型创建。也就是说,我并不精通模型创建,但我希望通过这个系列在这个领域有所发展!如果你在这个过程中发现可能有一些更好的方法,请在任何博客帖子上留下评论。

好了,让我们进入这项工作的第一阶段:数据收集!

收集电影评级

当然,如果我们想创建一个电影分级模型,我们必须有电影分级来训练我们的监督模型!据我所知,没有人在任何地方保存卡兰的电影评级,所以我不得不做一些许多人可能会害怕的事情:我必须自己收集它们。这意味着要翻遍《水冷器》的播客的完整目录,并听完它们,记下卡兰给出的任何评级。为了支持这一点,我创建了一个谷歌工作表电子表格,在那里我通过我的 iPhone 收集和输入数据。在这篇文章发表的时候,我只看了全部播客的 3/4,但是我认为我们有足够的数据来开始这个系列。

(补充说明:除了电影,Caelan 还对其他东西进行评级,所以你会在电子表格中找到比电影更多的东西。我捕捉这些其他的东西只是为了好玩,但它们会被过滤掉,只关注电影。此外,水冷器可以是 NSFW,也可以是一些非电影评级,所以……如果你看完整的电子表格,请注意这一点。😂)

好消息是,我发现了一种用 Python 编程从 Google 工作表中获取数据的方法,只要你知道sheet_id号是什么。在为我自己的 Google Sheet 找到特定的 ID 后,我可以使用下面的脚本在任何需要的时候获取更新的电影评论:

**# Defining the ID of the Google Sheet with the movie ratings
sheet_id = '1-8tdDUtm0iBrCdCRAsYCw2KOimecrHcmsnL-aqG-l0E'# Creating a small function to load the data sheet by ID and sheet name
def load_google_sheet(sheet_id, sheet_name):
    url = f'[https://docs.google.com/spreadsheets/d/{sheet_id}/gviz/tq?tqx=out:csv&sheet={sheet_name}'](https://docs.google.com/spreadsheets/d/{sheet_id}/gviz/tq?tqx=out:csv&sheet={sheet_name}')
    df = pd.read_csv(url)
    return df# Loading all the sheets and joining them together
df_main = load_google_sheet(sheet_id, 'main')
df_patreon = load_google_sheet(sheet_id, 'patreon')
df_mnight = load_google_sheet(sheet_id, 'movie_night')
df = pd.concat([df_main, df_patreon, df_mnight], axis = 0)**

这个小脚本从 Google Sheet 中的三个选项卡收集数据,并将它们全部加载到一个统一的 Pandas 数据框架中。显然,这个熊猫数据框架包含的不仅仅是电影评论。为了方便起见,谷歌表单包含一个名为“类别”的栏目,我们可以用它来过滤电影。下面是要执行的脚本:

**# Keeping only the movies
df_movies = df[df['Category'] == 'Movie']**

最后,我们可以去掉我们的项目不需要的列,包括“集号”、“类别”和“注释”列。做到这一点的代码非常简单:

**# Removing the columns we do not need for the model
df_movies.drop(columns = ['Category', 'Episode Number', 'Notes'], inplace = True)**

我们剩下的就是这个样子的东西!

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

作者截图

好吧!我们可以用 Pandas DataFrame to_csv函数保存下来,并准备继续前进。

收集支持数据

对于那些熟悉像臭名昭著的泰坦尼克号项目这样的 Kaggle 数据集的人来说,你会知道 Kaggle 基本上给了你所有你需要的数据。我们的项目显然不是这种情况,收集数据来支持任何这样的模型都是一个挑战。数据科学家在这个职位上必须考虑的一些事情包括如下问题:

  • 支持这种潜在模型的数据存在吗?
  • 创建模型时,我需要收集什么样的特征?
  • 我需要通过什么方式来整理原始形式的数据?
  • 我需要对原始数据进行大量的特征工程吗?
  • 原始数据真的代表了模型背后的推论吗?
  • 数据是否在推论上产生了不公平/不道德的偏向?

好消息是我可以很容易地回答其中的一些问题。数据存在吗?嗯,我知道 IMDb 的存在,所以我敢肯定,一些容量的电影数据存在!我也不必担心创建一个不道德的模型,因为这种努力的本质不会给未来带来糟糕的结果。如果你想知道不道德的努力会是什么样子,我总是用创建一个预测模型的例子来预测基于 20 世纪数据的最佳 CEO 候选人。大多数 20 世纪的首席执行官都是中年白人男性,这在很大程度上是因为压制女性和少数族裔的制度。在 20 世纪首席执行官信息的基础上创建一个模型,会使所有的推论偏向于选择一个中年白人男性,这显然是不好的,也是不道德的。

这里的挑战是从不同的来源获取数据来支持我们的模型。说实话,我一开始不知道我应该寻找的所有功能。我有一种直觉,将卡兰的分数与其他评论家的分数进行比较可能是一个好主意,因此这可能具体表现为收集每部电影的烂番茄分数。但是到了最后,我不知道我会找到什么。此外,我如何确保来自一个源的电影数据与另一个匹配?例如,我如何确保一个给我提供复仇者联盟 4:终局之战数据的来源不会意外地从另一个来源给我提供复仇者联盟 3:无限战争的数据?

幸运的是,由于谷歌的力量,数据收集没有我想象的那么困难!现在让我们来分析我收集电影数据的三个来源,以及第一个来源是如何帮助保持一个来源到另一个来源的一致性的。

(在继续之前,请注意,从现在开始,这篇文章中讨论的所有内容都被记录在这个独特的 Jupyter 笔记本中。在我们继续进行的过程中,请随意参考它!)

数据源#1:电影数据库(TMDb)

在谷歌上搜索可能对我们的项目有前景的资源,似乎不断出现的首选是这个叫做 电影数据库 的资源,通常缩写为 TMDb 。虽然它有一个非常好的用户界面,可以通过网络浏览,他们也提供了一个同样伟大的 API 进行交互。唯一的问题是,他们试图限制有多少流量被他们的 API 命中,所以他们要求用户通过他们的网站注册以获得 API 密钥。(注意:请不要问我要我的 TMDb API 密钥。我想确保我可以留在自由层,只有当我为自己保留我的 API 密匙时才有可能。)

如果你按照这个链接后面的说明去做,注册 TMDb 是非常简单的。注册完成后,您应该会看到这样一个屏幕,其中显示了您的特定 API 密钥。

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

作者截图

如前所述,这个 API 键是敏感的,所以如果你在自己的代码中使用它,我建议你在把代码上传到 GitHub 的情况下,想办法模糊它。有很多方法可以做到这一点,但为了简单起见,我将我的密钥加载到一个名为keys.yml的文件中,然后使用一个.gitignore文件来确保该文件不会上传到 GitHub。如果你不知道什么是.gitignore文件,它是一个你可以描述任何你不想上传到 GitHub 的东西的地方,无论它是一个单一的特定文件,一个特定的目录,还是任何以特定扩展名结尾的东西。这个.gitignore文件本身不存储任何敏感的东西,所以非常欢迎你复制我在这个项目中使用的

那么,如何创建并使用这个keys.yml文件呢?让我创建一个不同的test.yml文件,向您展示它如何处理不敏感的信息。首先,让我们创建那个test.yml文件,并像这样填充它:

**test_keys:
    key1: s3cretz
    key2: p@ssw0rd!**

现在我们可以使用这个小脚本导入 Python 的默认yaml库并解析test.yml文件。下面你会看到一个截图,我特意打印了包含“敏感”信息本身的变量,但是请注意,你并不想用你实际的 API 键来打印。

**# Importing the default Python YAML library
import yaml# Loading the test keys from the separate, secret YAML file
with open('test.yml', 'r') as f:
    keys_yaml = yaml.safe_load(f)

# Extracting the test keys from the loaded YAML
key1 = keys_yaml['test_keys']['key1']
key2 = keys_yaml['test_keys']['key2']**

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

作者截图

好的,这就是我们如何保证 API 密匙的安全,但是我们实际上如何使用它呢?幸运的是,我们可以使用几个 Python 包装器来轻松地使用 Python 与 TMDb 进行交互,我选择使用的是一个名为 tmdbv3api 的包装器。tmdbv3api 的文档可以在这个链接中找到,我们将通过这个 Python 包装器遍历我所做的与 TMDb 的 api 交互的基础。

pip3 install tmdbv3api安装后,我们需要做的第一件事是实例化一些 TMDb Python 对象,这将允许我们获得我们需要的数据。让我先向您展示代码,我将解释这些对象的作用:

**# Instantiating the TMDb objects and setting the API key
tmdb = tmdbv3api.TMDb()
tmdb_search = tmdbv3api.Search()
tmdb_movies = tmdbv3api.Movie()
tmdb.api_key = tmdb_key**

第一个tmdb对象是一种“主”对象,它使用我们提供的 API 键实例化我们的 API 连接。tmdb_search对象是我们用来将电影名称的字符串文本传入 API 以获得关于电影的一些基本信息,尤其是电影的唯一标识符。然后,我们可以将该电影的唯一标识符传递给tmdb_movies对象,这将为我们提供一个数据宝库。

让我们通过搜索我最喜欢的电影之一来展示这一点。下面是我们如何使用tmdb_search来使用字符串搜索电影:

**# Performing a preliminary search for the movie "The Matrix"
matrix_search_results = tmdb_search.movies({'query': 'The Matrix'})**

如果你查看这些搜索结果,你会发现是一系列搜索结果,每一个都包含每部电影的有限细节。现在,就像任何搜索引擎一样,TMDb 将尝试返回与您的字符串最相关的搜索。作为一个例子,让我们看看当我遍历这些结果并从每个搜索结果条目中取出电影的标题时会发生什么:

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

作者截图

正如你所看到的,它首先返回了原始的黑客帝国电影,然后是其他后续的黑客帝国电影,然后是其他一些标题中有“黑客帝国”的随机电影。

在这里,我们将不得不接受我们的搜索结果的风险…你会在下面看到,我基本上要创建一个 Python for循环来迭代通过卡兰评级的每部电影。不幸的是,我无法切实验证我搜索的每部电影在第一次尝试时都会出现正确的一部。例如,我知道 Caelan 评论了旧的恐怖电影宠物语义的更新版本,没有看,我不知道 TMDb 是否会给我更新的版本或旧的经典。这只是我们不得不接受的风险。

单独做这个搜索并不能解决 TMDb 的问题。虽然这些初步结果确实返回了一些关于这部电影的信息,但实际上还有另一部分 TMDb 将提供我们想要的所有细节。在我们获得这些额外的细节之前,让我们看看原始搜索结果中的关键字,这样我们就可以显示我们将从下一步中提取多少更多的细节。

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

作者截图

为了进行更详细的搜索,我们需要将 TMDb ID 传递给tmdb_movies对象。我们可以通过查看matrix_search_results[0]['id']从原始搜索结果中获得 TMDb ID。这就是我们如何使用 TMDb ID 来提取关于电影的更多细节:

**# Getting details about "The Matrix" by passing in the TMDb ID from the original search results
matrix_details = dict(tmdb_movies.details(matrix_search_results[0]['id']))**

现在,我们来看看与初步结果相比,这个更详细的结果列表的新关键字:

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

作者截图

正如你所看到的,我们从这次搜索中获得了比以前更多的细节!现在,为了简洁起见,我不打算在这里花太多时间向您展示我将保留哪些特性。如果你想知道的话,我将创建一个数据字典作为我的 GitHub 的自述文件的一部分。但在进入下一个来源之前,我想指出一件事。还记得我说过我关心的是从一个数据源到另一个数据源保持电影结果的一致性吗?好了,朋友们,我有一些好消息!作为 TMDb 搜索结果的一部分,它们还包括imdb_id。这很好,因为像这样的唯一标识符肯定有助于确定正确的 IMDb 搜索结果。说到 IMDb…

数据来源#2: IMDb

所以您可能会奇怪,为什么我选择 TMDb 作为主要数据源,而不是 IMDb 呢?答案是因为虽然 IMDb 有官方 API,但我无法使用它。他们似乎需要某种特殊的商业案例来请求访问,老实说,我不想经历这样的麻烦。幸运的是,我确实找到了一个适合我们的替代品: IMDbPy 。IMDbPy ( 链接到 docs )是一个 Python 库,有人创建它来与来自 IMDb 的数据交互。现在,我真的不知道作者是如何获得这些数据的。这可能是因为他们可以访问官方的 IMDb API,或者他们正在做一些花哨的屏幕截图。无论是哪种情况,这个 Python 库都提供了我们需要的数据。

通过从 TMDb 搜索结果中提取 IMDb ID,我们可以使用它作为 IMDb 搜索的基础。不过有一点需要注意:TMDb 对 IMDb ID 的格式化有点奇怪。具体来说,就是将字符“tt”附加到每个 ID 的开头。不过,不要担心,因为我们可以简单地使用 Python 字符串迭代器,在将这些初始字符放入 IMDb 搜索之前,将其剥离。

在通过运行pip3 install imdbpy安装 IMDbPy 之后,我们准备通过运行下面的代码实例化我们的imdb_search对象:

**# Importing the IMDb Python library
from imdb import IMDb# Instantiating the IMDb search object
imdb_search = IMDb()**

现在,我们可以通过弹出 IMDb ID 来执行搜索,如下所示:

**# Obtaining IMDb search results about the movie "The Matrix"
matrix_imdb_results = dict(imdb_search.get_movie(matrix_imdb_id))**

唯一不幸的缺点是,虽然 IMDb 返回了大量信息,但大多数信息对我们的模型没有好处。IMDb 返回的大部分信息都是关于电影的配角和工作人员的,不幸的是,这些信息在预测模型中并不具有良好的特性。事实上,我们能从这些结果中提取的信息只有imdb_ratingimdb_votes。我要说这有点令人失望,但既然 TMDb 在第一遍中为我们返回了这么多信息,我也不太失望。

完成 IMDb 后,让我们继续第三个也是最后一个数据源。

数据源#3:开放电影数据库(OMDb)

从这个项目一开始,我就知道我绝对希望作为支持这些模型的特性的一件事是来自烂番茄的各自的评论家分数和观众分数,到目前为止,我们还没有从 TMDb 或 IMDb 获得这些数据。

幸运的是,开放电影数据库(OMDb) 在这方面显示了一些希望!实际使用 OMDb 将与我们使用 TMDb 非常相似,除了我们可以使用 IMDb ID 在 TMDb 中搜索电影。与 TMDb 一样,OMDb 要求您注册自己的 API 密钥。你可以通过在这个表格上提交你的电子邮件来做到这一点,他们会通过电子邮件把 API 密匙发给你。正如您在这个表单中注意到的,您每天只能使用 1000 次对这个 API 的调用,这对我们的目的来说完全没问题。(同样,如果您开始与世界共享这个 API 密匙,您将会遇到问题,所以一定要把这个 API 密匙留给自己!)

因为这篇博文已经开始变得很长了,所以我将粘贴我的脚本,它将获得烂番茄评论家评分和 Metacritic metascore。该脚本的行为与 TMDb 非常相似:

**# Instantiating the OMDb client
omdb_client = OMDBClient(apikey = omdb_key)# Iterating through all the movies to extract the proper OMDb information
for index, row in df_all_data.iterrows():
    # Extracting movie name from the row
    movie_name = row['movie_name']

    # Using the OMDb client to search for the movie results using the IMDb ID
    omdb_details = omdb_client.imdbid(row['imdb_id'])

    # Resetting the Rotten Tomatoes critic score variable
    rt_critic_score = None

    # Checking if the movie has any ratings populated under 'ratings'
    omdb_ratings_len = len(omdb_details['ratings'])

    if omdb_ratings_len == 0:
        print(f'{movie_name} has no Rotten Tomatoes critic score.')
    elif omdb_ratings_len >= 0:
        # Extracting out the Rotten Tomatoes score if available
        for rater in omdb_details['ratings']:
            if rater['source'] == 'Rotten Tomatoes':
                rt_critic_score = rater['value']

    # Populating Rotten Tomatoes critic score appropriately
    if rt_critic_score:
        df_all_data.loc[index, 'rt_critic_score'] = rt_critic_score
    else:
        df_all_data.loc[index, 'rt_critic_score'] = np.nan

    # Populating the Metacritic metascore appropriately
    df_all_data.loc[index, 'metascore'] = omdb_details['metascore']**

总而言之,以下是我们所有电影的 18 大特色:

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

作者截图

让我们继续将该数据集保存为 CSV 格式,并结束这篇文章!

接下来:特征工程

唷,我们在这篇文章中走了很长的路!我们从 3 个不同的数据源中获得了 18 个不同的特征,我希望这将为我们在下一个特征工程部分开始生成新的特征提供一个良好的基础。不幸的是,我们无法获得我所希望的烂番茄观众评分,所以我将向正式的烂番茄 API 提交一个请求,看看我是否能获得它,因为我认为这将是一个非常有用的功能,所以如果我能获得它,我可能会回来修改这篇文章的结尾。

感谢大家查看这篇文章!希望您发现它有趣且信息丰富。我也开始在 YouTube 上直播这个项目的编码过程,你可以在我的链接树中找到我所有的事情。实际上,我已经为这篇特别的帖子做了现场直播,重播可以在 YouTube 上看到。再次感谢你的阅读!下一篇帖子见。🎬

创建感知器网络:从零到英雄

原文:https://towardsdatascience.com/creating-a-perceptron-network-from-zero-to-hero-64acfbd7c7ef?source=collection_archive---------38-----------------------

神经网络系列

神经网络系列—第 1 章,第 2 部分

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

序言注释

这个故事是我正在创作的关于神经网络系列的一部分,也是专门讨论感知机网络的一章的第二部分(你可以在这里阅读第一部分)。在这篇文章中,我将应用上一篇文章中解释的所有概念,并用 Python 实现一个感知器网络。

简而言之,感知器

我们在我以前的文章中已经看到,感知器是一种使用阈值函数作为激活函数的神经网络。获得输出 y 的方法是将一组权重 W 乘以一组输入*,加上偏置节点( b ),然后对这个结果应用阈值函数***【f(z)**

回顾我的上一篇文章,我们也看到了具有更复杂架构的矩阵是什么样子,具有 m 输入节点和 n 神经元。然而,在用于前馈方程以获得网络预测的符号中,我们还没有看到更复杂的体系结构的影响。**

**(**注:如果接下来的内容对你没有太大意义,建议你看一看基本的线性代数概念,即矩阵的转置和乘法。)

让我们像上一篇文章一样假设 m =3、 n =5。这意味着我们的 W 矩阵将有 3 行 5 列。如果我们将标量运算转换成矩阵符号,我们的前馈方程就变成这样:

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

前馈方程的矩阵符号

从这个“新”前馈方程中,可以突出一些变化:

  • 输入 X 现在是一个 3 行一列的矩阵。它有 3 行,因为我们假设 m =3 ( m 是输入神经元的数量)。一列代表数据集中的一个示例,但是可以将所有示例注入到 X 中,并通过使用每一列来放置数据集中的每个样本,一次性获得所有预测;
  • 偏置节点 b 现在是一个 5 行 1 列的矩阵。这是因为我们每个神经元需要一个偏置节点,我们将神经元的数量 n 定义为 5;
  • y 将必须与 b 的大小相同,因为如果有 5 个神经元,也将有 5 个输出。

上面描述的整个等式通常以一种更简单的方式表示为:y =f(wᵀx+b)。然而,通过将 b 作为 W 的额外一行,并将一个特殊的输入节点添加到常数值为 1 的中,这两个操作可以简化为一个操作,因为这是一个数学上等价的表达式:

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

前馈机制

为了实现前馈机制,我们需要三个组件:

  • 偏置节点加法器。它应该向 X 添加额外的行(值为 1 ),以容纳权重矩阵中偏差的额外行;
  • 激活功能。它应该接收输入 z 并应用阈值函数以提供y****;****
  • 前馈功能。它应该接收一个或多个示例(我们的 X ),每个示例填充网络输入层的 m 条目,以及描述连接权重的权重矩阵。其输出应该是 y
**def **activation**(z):
    return np.where(z>=0, 1, 0)def **add_bias_node**(X):
    return np.vstack([X, np.ones(X.shape[1])])def **feed_forward**(W, X):
    return **activation**(np.dot(np.transpose(W), **add_bias_node**(X)))**

训练感知器

感知器训练算法是一个迭代过程,旨在找到使网络整体误差最小化的网络连接权重集。网络的单个权重可以通过使用以下等式来更新:

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

在每次迭代(也称为历元)中,我们通过计算预测输出和实际输出之间的差异来评估误差(【e】),并使用它们以及输入和学习率()系数来计算我们将改变每个权重多少(也称为δ,或δ)

下面的示例描述了训练过程的伪代码:

**W = initialize weight matrix with dimensions (M+1,N)
for each epoch (e):
    for each example (x):
        y = calculate network prediction using W and x
        error = calculate deviation between y and target (t)
        delta = calculate weight variations based on the error and learning rate
        update W with deltas
return W**

在将其具体化为 Python 代码后,我们得到了类似这样的东西:

**def **train**(W, inputs, targets, epochs, lr):
    for epoch in range(epochs):
        for x, t in zip(inputs.transpose(), targets):
            y = **feed_forward**(W, x.reshape(1, -1).transpose())
            errors = np.subtract(y, t)
            x_with_bias = **add_bias_node**(x.reshape(-1,1))
            deltas = lr * np.dot(x_with_bias, errors.transpose())
            W = np.subtract(W, deltas)
    return W**

感知器在最大似然问题中的应用

既然我们已经为感知器神经元建立了基础,我们可以将其应用于大型数据集,这是一个众所周知的数据集,主要用于介绍机器学习基础知识。目标是根据数据集中描述的一组特征来预测泰坦尼克号灾难中的幸存者。

在本文的上下文中,我只使用了两个特征来训练模型:乘客支付的票价和其年龄**,因为这使得数据集和模型更容易可视化。使用两个特征意味着在 2D 空间中工作,这也意味着我们的神经网络架构由单个神经元( n =1)和两个条目( m =2)组成(如果我们包括偏差节点,则为三个)。**

**import seaborn as snstitanic = sns.load_dataset('titanic')M = 2
N = 1X = np.asarray(titanic[features]).transpose()
W = np.random.rand(M + 1, N) # + 1 because of the bias node
t = titanic['survived'].to_numpy()**

在上面这段代码中,我们收集了 XWt ,以便计算y 并比较训练过程前后的错误率。 W 的初始化以随机方式进行,遵循 0 和 1 之间的均匀分布,因为这是初始化网络权重的一种可能方式。请记住,这是培训中一个非常重要的主题,因为初始化过程会对培训速度产生很大影响。但是,这个主题将在本系列的后面详细介绍,并且超出了本文的范围。
现在我们已经有了形状正确的所有矩阵,让我们在训练前后应用前馈机制:

**y = feed_forward(W, X)
error_rate(y.flatten().tolist(), t.tolist()) # 0.59383W_trained = train(W, X, t, 20, 0.1)y = feed_forward(W_trained, X)
error_rate(y.flatten().tolist(), t.tolist()) # 0.31512**

我们设法将神经网络错误预测的例子数量从 0.59 减少到 0.31,这意味着我们的模型准确性大约为 69%。但是神经网络预测我们样本的能力在整个训练过程中是如何变化的呢?为了回答这个问题,我们可以简单地得到每个时期的预测,并画出分类器的决策边界。在 2D 上下文中,该边界是给定乘客生还或不生还的概率相等的线。

在下面的 gif 中,你可以看到网络的预测以及分类器的决策边界。橙色样本是被正确预测为幸存者的乘客,绿色样本是被正确预测为非幸存者的乘客,灰色样本是被感知机错误预测的乘客。

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

使用泰坦尼克号数据集训练的感知机

最后意见

虽然我们设法提高了网络的准确性,但通过观察上面动画中的训练过程,我们可以记下一些想法:

  • 问题不是线性可分的
    我们已经看到,感知器收敛定理证明,如果存在线性可分性,就有可能达到最优解。异或问题也说明了感知器的局限性。在这个问题中,我们可以看到感知器努力寻找一条线,将消极和积极的类别完全分开……因为这条线是不可能画出来的,因为在图中总会有灰色的点,也就是错误的预测。
  • 添加更多功能可能有助于提高性能
    我们挑选了两个功能来解决这个问题。然而,如果我们添加更多的功能,会发生什么呢?也许线性可分性将通过有一个超平面来分离这两个类来实现,或者至少我们将更接近于此。我在我的感知机笔记本中做了这个小体验。

感谢阅读!你喜欢这篇文章吗?非常感谢你的反馈,🗣。你可以随时在 TwitterLinkedIn 上联系我,或者如果你对下一章的最新消息感兴趣,就在 Medium 上关注我😀。

一些相关阅读:

为空间分析创造一个平台

原文:https://towardsdatascience.com/creating-a-playground-for-spatial-analytics-c7b8a867ff34?source=collection_archive---------52-----------------------

如何在不到 30 分钟的时间内通过 SAP HANA 云设置和使用 QGIS

*您对空间分析感兴趣,并且正在寻找一些入门内容?*SAP HANA Cloud Trial 与 QGIS 的结合为您提供了大规模空间数据处理的低门槛。基于 SAP HANA 构建的空间工作流最终可以在业务应用程序中重用,以将位置维度注入到您的业务流程中。

不管你是第一次接触 QGIS 还是第一次接触SAP HANA——或者两者都是。这个博客的目标是在不到 30 分钟的时间里为你提供一个免费的工作场所。所以——把它加到你的书签里,在你的日历里划出一些时间!

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

照片由蒂姆·阿特伯里Unsplash 上拍摄

该教程将包含以下任务:

  • ⏳5m | 创建 HANA 云试用实例
  • ⏳2m | 安装 SAP HANA ODBC 驱动
  • ⏳3m | 安装 QGIS
  • ⏳5m | 将 QGIS 连接到 SAP HANA 云
  • ⏳5m | 上传您的第一个空间数据集
  • ⏳5m | 在底图上可视化数据
  • ⏳5m | 将空间工作负载下推到 SAP HANA 云

另外,我建议在开始前喝杯咖啡。这不是 30 分钟的一部分,因为准备时间因准备方法而异。所以,你可以看到这是开始这个宏观研讨会的先决条件。

另一个先决条件是在https://download.qgis.org上下载适用于您的操作系统的 QGIS 安装包。我在 Mac 上工作,QGIS 3.18 的相应安装包大小为 1.2GB。根据服务器速度,此下载可能会持续一段时间…

准备好你的☕️了吗?

⏳5m👉创建 HANA 云试用实例

这里我应该承认,5 分钟是净努力。SAP HANA 云试用实例的实际创建时间各不相同。好的一面是,当您的新实例启动时,您可以并行执行其他安装步骤。这样,我们应该仍然能够保持 30 分钟的目标。

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

⏯演练:创建 SAP HANA 云试用实例

遵循以下步骤:

  1. 前往https://www.sap.com/cmp/td/sap-hana-cloud-trial.html并点击立即开始免费试用
  2. 输入您的数据并选择您的首选地区(即美国东部、欧洲或新加坡)。
  3. 创建您的全球帐户、子帐户、组织和开发空间需要一两分钟。喝一口你的咖啡,然后等着。
  4. 您将自动收到一封电子邮件,其中包含您的试用链接。点击链接 进入您的试用
  5. 现在,你需要进入你的“空间”。为此:
    ➲点击进入你的试用账户 ➲点击子账户试用。相应的区域也会显示您之前选择的区域。
    ➲点击名为 dev 的空间。
    ➲点击左侧的 SAP HANA Cloud
  6. 接下来,我们将开始实际的 HANA 云试用实例。因此,点击右上角的创建
  7. 在下面的对话框中,需要注意这些配置:
    实例名。本教程我会选择 hctrial
    管理员密码 ➲ 允许的连接应该设置为允许所有 IP 地址为了简单(和安全的代价!).
    创建数据湖可以关闭,因为您不需要数据湖来执行这里概述的步骤。
  8. 将创建您的实例。继续其他步骤,我们稍后回来。

⏳2m👉安装 SAP HANA ODBC 驱动程序

在这里,2 分钟通常是慷慨的。要安装 SAP HANA ODBC 驱动程序,它是 SAP HANA 客户端的部分,您只需从 SAP 开发工具下载并执行操作系统特定的安装程序。

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

这里没有太多要考虑的,因为这是一个下下一个完成安装者*(这是一个正式的表达吗?嗯,应该是。)*。有适用于 WindowsmacOSLinux 的安装包。

⏳3m👉安装 QGIS

同样,这本质上是一个下一个完成的安装程序,没有具体的考虑。如上所述,Windows、macOS 和 Linux 的操作系统特定安装包可在 QGIS 下载页面上获得。您至少需要 3.18 版才能使用 SAP HANA。

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

一旦您下载并安装了 QGIS 3.18,您就可以启动客户端。确保您在左侧的数据浏览器中将 SAP HANA 视为数据提供商。

⏳5m👉将 QGIS 连接到 SAP HANA 云

关于如何将 QGIS 连接到 SAP HANA 的一般说明可以在 QGIS 文档中找到。此外,还有一个描述这一过程的短片

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

⏯演练:将 QGIS 连接到 SAP HANA 云试用版

但是,让我们来详细了解一下如何获得必要的证书:

  1. 如果您不在 SAP BTP 驾驶舱内查看带有 SAP HANA 云实例的图块,请重复上述*“创建 HANA 云试用实例”中的步骤 4 和 5。您应该看到您的创建的运行的*实例。
  2. 点击动作复制 SQL 端点。端点将被复制到您的剪贴板。保持在那里。
  3. 打开 QGIS,在左侧窗格的浏览器中找到 SAP HANA 条目。
  4. 右键点击 SAP HANA ,选择新建连接
  5. 将会打开连接对话框。填写以下字段:
    名称:填写连接的名称。我会用 hctrial
    主持人:粘贴你的剪贴板,最后去掉 “:443” 。SQL 端点的格式为 <主机> : <端口> ,字段期望 <主机>
    标识符:将下拉菜单切换到端口并在文本字段中输入 443
    认证:选择基本认证,输入用户名密码。如果这只是一个游戏场,DBADMIN 用户将完成这项工作。请注意,建议仍然是创建一个具有有限访问权限的专用用户。
    (注意:旧版本的 ODBC 驱动程序要求您在连接属性中显式启用 SSL。确保使用最新的客户端版本)
  6. 在连接对话框中点击测试连接,如果我们两个都做对了工作,你应该会看到一次成功的连接尝试。
  7. 点击 OK 并检查您的连接(在我的例子中是 hctrial )是否列在左侧窗格的浏览器中。

⏳5m👉上传您的第一个空间数据集

到目前为止,我们取得了什么成就?我们已经创建了一个 SAP HANA 云试用实例,并通过 ODBC 连接了 QGIS。不幸的是,我们的数据库仍然是空的,我们应该改变这一点。好消息是,我们不需要任何数据库工具来上传我们的第一个数据集。我们将简单地使用 QGIS。

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

⏯演练:上传您的第一个空间数据集

正如我在之前的博客中所建议的,我们可以使用Geofabrik提供的 OpenStreetMap 数据。我们将从位于德国沃尔多夫的 SAP 总部区域的兴趣点数据开始。

让我们这样做:

  1. 下载“Regierungsbezirk Karlsruhe”的 Shapefile (.shp.zip)。您可以将 Shapefile 视为基于文件的地理空间数据数据库。
    下载页面 | 直接链接
  2. 打开 QGIS 并找到下载的文件(不要解压缩!)在浏览器左侧。在我的 Mac 上,我必须导航到主页>下载。您经常使用的文件夹也可以添加到收藏夹中。
  3. 该文件可以在浏览器中进一步展开。这样做,并找到名为 gis_osm_pois_free_1 的图层。
  4. 在浏览器中找到您的 SAP HANA 连接,并将其展开两次,这样您就可以看到该模式了(如果您遵循了上面的步骤,则为 DBADMIN )。
  5. 神奇的是:将 gis_osm_pois_free_1 层拖放到您的 DBADMIN 模式上。
  6. 您已成功将首个空间数据集导入 SAP HANA Cloud 试用版!

如果您需要证据,您可以打开数据库浏览器或 DBeaver 并检查已经创建的表。但请注意,这不会是我们 30 分钟交易的一部分!

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

⏳5m👉在底图上可视化数据

现在,我们已经在数据库中存储了个兴趣点(poi)及其坐标。这类数据(即点、线、多边形等。)给出的坐标称为矢量数据。矢量数据可以打印到地图甚至卫星图像上(这被认为是栅格数据)。

所以我们需要添加两个不同的到我们的 QGIS 项目中:

  1. 基础地图(例如街道地图或卫星图像)
  2. 绘制在该地图上的数据(由 SAP HANA 管理的矢量数据)

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

⏯演练:使用卫星图像添加基础层

如何添加基层:

  1. 在浏览器中左键点击 XYZ 瓷砖并选择新建连接
  2. 一个新的磁贴服务对话框打开了:
    ➲输入“谷歌地图卫星”作为名字
    ➲输入*’ https://mt1 . Google . com/vt/lyrs = s&x = { x }&y = { y }&z = { z } '作为 URL
    ➲设定了
    最大值。缩放级别至 19。
    ➲用
    确认*正常。
  3. 在浏览器的 XYZ 磁贴下找到谷歌卫星
  4. 双击谷歌地图卫星添加带有卫星图像的基础图层。

如果您想添加不同的服务(如 OpenStreetMap),您可以查看本博客获取更多网址。

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

⏯走查:在 SAP HANA 中可视化数据

如何添加 SAP 总部周围的所有喷泉:

  1. 在浏览器中找到我们之前上传到 SAP HANA 的数据集。(SAP HANA>HC trial>db admin>GIS _ osm _ pois _ free _ 1)
  2. 双击 gis_osm_pois_free_1 在底图上添加另一个图层
  3. 在左下方的可见图层列表中,右击新添加的图层,选择缩放至图层。这将确定相应数据的边界框,并相应地缩放地图。
  4. 我们现在可以在地图上看到卡尔斯鲁厄地区的所有 poi。我们只想过滤掉喷泉。因此,我们再次右击图层,选择滤镜…
  5. 滤镜对话框打开:
    ➲作为滤镜表达式输入 “fclass” = ‘喷泉’ ➲ 确认 OK
  6. 放大到 SAP 总部。你会看到两个喷泉——东边的一个是 3 号楼前的喷泉。花些时间——这是一项探索性的任务😉
  7. 在窗口的顶栏上选择识别特征工具。当光标悬停在地图上时,它会改变并包含一个小的信息图标。
  8. 单击喷泉的点,您将在右侧的数据库中看到相应的记录。

现在,您已经了解了如何在 QGIS 中可视化 SAP HANA 中的数据。如果你喜欢,你可以玩一点过滤器,改变基本地图。同样,这种热情不计入我们的 30 分钟!

⏳5m👉将空间工作负载下推到 SAP HANA 云

最后但同样重要的是,让我们看看如何在数据库级别执行一些空间工作负载,并将结果发送到 QGIS。由于 SAP HANA 上的所有空间处理功能都是 SQL 语法的一部分,因此最好的方法是创建一个 SQL 视图,可以在 QGIS 中使用。

因此,我们需要打开 SAP HANA 数据库浏览器,创建一个 SQL 视图并在 QGIS 中使用它。

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

⏯演练:为空间聚类创建视图

创建一个 SQL 视图,进行六边形聚类并计算每个聚类的兴趣点数量:

  1. 如果您不在 SAP BTP 驾驶舱内查看带有 SAP HANA 云实例的图块,请重复上面*“创建 HANA 云试用实例”中的步骤 4 和 5。您应该看到您的创建的运行的*实例。
  2. 点击操作并在 SAP HANA 数据库浏览器中打开
  3. 可能会提示您输入用户凭据。使用在 QGIS 中设置的同一用户(即 DBADMIN)。
  4. 点击左上角的 SQL 符号打开一个新的 SQL 控制台
  5. 将以下 SQL 语句复制到 SQL 控制台并执行:
CREATE VIEW POI_DENSITY AS
(
	SELECT 
		ST_ClusterId() AS cluster_id,
		ST_ClusterCell() AS cluster_cell,
		COUNT(*) AS count_pois
	FROM "gis_osm_pois_free_1"
	GROUP CLUSTER BY "geom" USING HEXAGON X CELLS 100
)

您可以在 SAP HANA 空间参考中找到关于空间聚类的更多信息。

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

⏯穿行:QGIS 中的基本符号系统

将数据放入 QGIS 并应用一些基本样式:

  1. 打开 QGIS 并通过双击添加底图(类似于上一步)。
  2. 在浏览器中找到 SQL 视图POI _ DENSITY(SAP HANA>HC trial>db admin>POI _ DENSITY)并双击将其添加到地图中。
  3. 右键点击 POI_DENSITY 图层,选择属性。(确保在图层选项卡中而不是在浏览器中完成此操作!)
  4. 在下面的对话框中,你可以调整图层样式:
    ➲选择左侧的符号
    最上面的➲将下拉值从单个符号更改为分级 ➲ 作为选择我们的数据库字段count _ pois选择合适的颜色渐变*(即红色 )
    ➲将模式从相等计数(分位数即 8)
    ➲点击
    分类按钮创建颜色范围。
    ➲用
    确认 OK***
  5. 现在,您应该会在地图上看到类似热图的可视化效果。六边形单元根据单元中 poi 的数量进行着色。

这种类似热图的可视化方式可以很容易地发现 SAP 总部周围的主要城市:卡尔斯鲁厄、曼海姆和海德堡。

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

拉伸任务:给六边形单元格添加一些透明度

🏁下一步是什么?

恭喜你。您已经完成了空间分析运动场的设置。我很想知道您对设置好一切所需时间的反馈——请使用下面的评论部分。我承认,如果你第一次看到 SAP HANA 和 QGIS,30 分钟可能是一个具有挑战性的时间表,但我真的希望即使有这样或那样的复杂情况,你也能坚持不到 1 小时。

如果您想深入更复杂的场景,我建议您查看一些关于空间数据科学以及如何将地理空间维度添加到机器学习模型中的材料。一个很好的起点是我关于走向数据科学的文章。请注意,这是一个高层次的概述。文章中有更详细说明的博客链接。

走向数据科学:地理空间特征对机器学习的影响

为了了解更多关于 SAP HANA Spatial 和 Graph 的细节,我建议观看 Youtube 上 SAP Devtoberfest 的视频记录。这一系列 11 个视频是我能想到的网上最完整的记录。

Youtube: SAP HANA 多模型@ Devtoberfest

此外,我还定期维护一个资源博客,收集围绕 SAP HANA Spatial 的所有社区内容。值得一看,并可能找到这样或那样的宝石:

SAP HANA 空间资源:https://cutt.ly/saphanaspatial

结论

您已经学习了如何将空间数据上传到 SAP HANA 云,并使用 QGIS 对其进行可视化。您还创建了一个 SQL 视图,它在数据库级别应用了一个聚类算法。现在,您应该能够根据自己的空间数据构建自己的空间分析。

您在本博客中看到的是一个技术性很强的演练,旨在快速了解 SAP HANA Spatial。如果您有 GIS 背景,您可能会问,为什么首先要使用 SAP HANA?我所描述的基本任务可以通过任何 GIS 客户端轻松完成,无论有无数据库持久性或空间工作负载的下推。

我想引用我亲爱的同事汤姆·图尔奇奥的话,他概述了在 SAP HANA 上运行 GIS 的主要优势是 生产力、敏捷性、加速和集成 (重点强调集成😊).虽然 Tom 的博客是专门为 Arcg is 定制的,但无论实际的 GIS 客户端是什么,概述的质量都是有效的。

原载于 2021 年 3 月 1 日 https://blogs.sap.comhttps://blogs.sap.com/2021/03/01/creating-a-playground-for-spatial-analytics/**

在 Julia 中创建 Pluto.jl 笔记本阅读器

原文:https://towardsdatascience.com/creating-a-pluto-jl-notebook-reader-in-julia-da1c152db184?source=collection_archive---------26-----------------------

Jockey.jl

逆向工程冥王星笔记本读入我的自定义笔记本会话

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

(图片由 geraltPixabay 上提供)

介绍

Pluto.jl 是一个相当新的 IDE 开发,用于处理 Julia 编程语言中的笔记本文件。虽然 Pluto.jl 有一些很棒的功能,但这些功能肯定不符合我的个人偏好——我不是唯一一个这样想的人。我写了一整篇文章,详细介绍了我使用 Pluto.jl 的经历,我喜欢这个包的什么,不喜欢什么,你可以在这里阅读:

然后是海王星。Neptune 是 Pluto.jl 的一个分支,它修改了 Pluto.jl,排除了最初的创建者打算在每个笔记本会话中使用的所有有趣的东西。我最后还写了一篇关于 Neptune.jl 的文章,你可以在这里看到:

我认为 Pluto.jl 和 Neptune.jl 实际上向我展示了这是非常可能的。您可以拥有一台基于 Julia 的笔记本服务器,笔记本服务器提供的所有功能都可以通过 Julia 的全部功能进行定制和发挥。不管你是否使用 Julia,你都必须承认, IJulia 可能不是最好的解决方案。也就是说,所有这一切让我真的想创建自己的笔记本服务器,并在它下面设计自己的应用程序。

在这个项目的发布画布上有很多想法,一旦这个项目实际上处于常规开发阶段并有了可靠的发布,我会有更多的想法。如果你想了解更多关于这个新的 IDE jockey . JL 的信息,你可以在这里查看这个项目的 Github:

https://github.com/ChifiSource/Jockey.jl

还有一件事!在另一篇文章中,我初步研究了这种格式,并创建了一些新的类型来处理这种数据。考虑到这一点,为了给这里的总体目标提供更多的上下文,这可能是值得研究的。

Pluto.jl 文件格式

在我们开始制作文件阅读器之前,我们当然需要了解一下 Pluto.jl 文件格式实际上是如何工作的,我在上一篇讨论 Jockey 的文章中已经这样做了,这就是我所看到的:

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

(图片由作者提供)

恰当地说,我的反应是对他们实际上是如何做的感到惊讶。今天,我们将尝试读取这种文件格式,并将其放入我们的单元格对象中。像这样一个项目的一个伟大之处在于它需要大量的调试,也就是说,我将在笔记本中编写这些代码。这将使我编写的代码更容易与我所有的读者分享——这是更容易解释的额外好处——因为我不会在文件间跳来跳去。话虽如此,笔记本可在此处获得:

https://github.com/emmettgb/Emmetts-DS-NoteBooks/blob/master/Julia/Reading Pluto.jl.ipynb

[emmac@fedora ~]$ cd dev/nbs && jupyter-notebook

我已将 Cd 放入我们的笔记本目录,现在将创建一个新的 Jupyter 会话。不需要包含,因为这里的整个目标是让这些适合我们的类型。我们所需要做的就是读取这些数据的行,并想出某种加载算法来将其转换成我们的新类型。同样的事情也要用. IPYNB 来做,我知道,我明白;目前这有点无聊,但结果值得我们在后端做所有的工作。

总之,我创建了一个新的笔记本——因此,添加了我们的第一点代码。这段代码只是 Jockey Cells.jl 文件中的代码。您可以在 Github 上查看该文件,网址是:

https://github.com/ChifiSource/Jockey.jl/blob/cells_v1/src/ServerController/Cells.jl

using UUIDs, TOMLabstract type AbstractCell end
mutable struct InputCell <: AbstractCell
    ID::UUID
    Text::String
    env::Dict
endmutable struct OutputCell <: AbstractCell
    ID::UUID
    output::String
endmutable struct Cell <: AbstractCell
    input::Cell
    output::Cell
    hidden::Bool
    lang::Symbol
    env::UUID
end

接下来,我将把文件作为字符串读入。

uri = "weird.jl"
input = readlines(uri)

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

(图片由作者提供)

好消息是这个字符串包含了很多关于 Pluto.jl 文件类型以及为什么使用这种类型的信息。我计划在我自己的版本中使用一些元素,我们还需要考虑这里加载的依赖关系。虽然我不完全确定我们是否需要使用 interact,因为这两个服务器在本质上非常不同,但我们肯定会利用这个 UUID 场。我做了一个新的小函数,可以让我们更详细地看到所有这些工作:

function showsome(x::UnitRange, uri::String)
    f = readlines(uri)
    for i in x
       println(f[i]) 
    end
end

使用这个函数,我可以更好地查看文件中的文本。在我的方法中,我的第一个测试是编写一个函数来获取所有的 UUIDs,我认为这很容易,因为它们肯定有很多特定的字符。

function read_plto(uri::String)
    cells = Dict()
    celluuids = []
    for line in readlines(uri)
        if occursin('╟', line)
            println(line)
        end
    end
endread_plto(uri)

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

(图片由作者提供)

没什么疯狂的,但是朝着正确的方向迈出了一步。从这里开始,我们需要扫描下一个单元格。当我们点击该单元格时,我们将认为这两个单元格定义之间的所有行都是单元格内容。在我让这个功能工作之后,我要把这个函数提取出来,简单地通过重命名这个方法,然后写另一个调用它的方法。这将有助于保持“功能为步骤”的心态,并使这个包更容易看。下面是我的初始函数:

function read_plto(uri::String)
    # We need file lines for each cell UUID
    cellpos = Dict()
    first = 0
    ccount = 0
    for (count, line) in enumerate(readlines(uri))
        if occursin('╟', line)
            ccount += 1
            if first == 0
                first = count
            else
                push!(cellpos, ccount => first:count)
            end   
        end
    end
    return(cellpos)
end

这个 for 循环很粗糙,但是它可以作为我们需要做的事情的大纲。我们可以让它看起来更好,并在以后改变一些循环语法。首先,我们用 count 枚举我们的读取行。这些行被存储为变量行。变量 first、ccount(单元格计数)和 cellpos(一个字典)都在此之前初始化。我们要做的第一件事是看看这一行是否有 char ‘╟’ 我们之前已经看到这是如何获取所有 UUIDs 的。无论何时找到该行,首先会发生的是填充细胞计数。

这最终是为骑师,因为骑师将有一个关键的 UUID 和他们各自的号码。但是,每个单元格之后可以有不同的行数,这就是范围的来源。该范围将是单元格计数的值对。基本上,我将能够积累哪些线包含哪些环境。让我们快速运行一下:

cellpos = read_plto(uri)

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

(图片由作者提供)

奇怪。

首先,我们现在知道这个笔记本文件中有 25 个单元格——但是很明显单元格区域是不正确的。第一个也是最明显的错误是如何添加单元计数器。这需要移动到条件中,实际上是计数细胞。这就给了我一个规则有序的字典,它实际上有一个 1 值和类似的东西。然后我意识到我传递的字符只在文件的最底部。很快,我把它改成了包含整个开头的字符串。下面是最终的细胞定位功能:

function read_plto(uri::String)
    # We need file lines for each cell UUID
    cellpos = Dict()
    first = 0
    ccount = 0
    for (count, line) in enumerate(readlines(uri))
        if occursin("# ╔═╡", line)
            if first == 0
                first = count
            else
                ccount += 1
                push!(cellpos, ccount => first:count)
                println(ccount => first:count)
            end   
        end
    end
    return(cellpos)
end

我将把它重命名为 plto_cell_lines()方法,这只是开发人员 API 的一部分,所以除了我之外,没有人真的需要担心它。这将是对提取方法的公然使用,我使用这种方法是为了通过简单地使用更多的函数使我的代码看起来更简洁和漂亮。如果你感兴趣的话,我有一整篇关于这个主题的文章,还有一些做同样事情的其他技术。我认为这些技能对于数据科学工作来说是绝对必要的:

</5-fabulous-refactoring-methods-for-prettier-code-e3bc3447c0b2> [## 更漂亮的代码的 5 个惊人的重构方法

towardsdatascience.com](/5-fabulous-refactoring-methods-for-prettier-code-e3bc3447c0b2)

现在看看每当我运行这个函数时会发生什么:

cellpos = read_plto(uri)

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

(图片由作者提供)

如此接近…

好消息是,使用我编写的打印函数,我们可以断言第一个值是正确的(因为它从第一个单元格开始,到第二个单元格结束。):

showsome(17:24, uri)

然而,我们需要改变一些事情,因为首先;所有这些细胞都是从 17 开始的,这有点违背了我们的初衷。这只是归结为在使用第一个变量后缺少对它的重新赋值。

if occursin("# ╔═╡", line)
            if first == 0
                first = count
            else
                ccount += 1
                push!(cellpos, ccount => first:count)
                println(ccount => first:count)
                first = count
            end   
        end

我接下来要做的另一件事是,对于被推送到字典的范围,从计数中减去 1。这是因为我们不想包含下一个传入单元的头部。我也不确定这里的输入/输出结构,因为它可能是 8 个输入单元和 8 个输出单元,或者 16 个输入单元——一旦我们使用该算法,我们就会弄清楚所有这些。

cellpos = plto_cell_lines(uri)Dict{Any, Any} with 35 entries:
  5  => 38:40
  16 => 82:85
  20 => 99:103
  35 => 157:161
  12 => 64:68
  24 => 114:116
  28 => 131:133
  8  => 51:53
  17 => 86:88
  30 => 137:139
  1  => 17:23
  19 => 96:98
  22 => 108:110
  23 => 111:113
  6  => 41:43
  32 => 148:150
  11 => 61:63
  9  => 54:57
  31 => 140:147
  14 => 72:78
  3  => 28:30
  29 => 134:136
  7  => 44:50
  25 => 117:120
  33 => 151:153

好像这本字典突然有了新的价值。现在让我们在一个新函数中调用这个函数。

function read_plto(uri::String)

end

我还冒昧地通过查看细胞数据来了解更多的信息。为此,我使用了我们古老的 showsome()方法。幸运的是,它需要一个单位范围,所以我可以按部分查看数据:

showsome(cellpos[1], uri)# ╔═╡ b129ba7c-953a-11ea-3379-17adae34924c
md"# _Welcome to Pluto!_

Pluto is a programming environment for _Julia_, designed to be **interactive** and **helpful**. 

In this introduction, we will go through the basics of using Pluto. To make it interesting, this notebook does something special: it **changes while you work on it**. Computer magic ✨" showsome(cellpos[2], uri)# ╔═╡ 4d88b926-9543-11ea-293a-1379b1b5ae64
md"## Cats
Let's say you're like my grandma, and you have a lot of cats. Our story will be about them."

看完这个材料,我才知道这些都是输入细胞。我认为这很有道理,Pluto.jl 笔记本不是普通的笔记本——它们是主动的,或者说是“被动的”。我认为这绝对是一个很酷的特性和很好的实现,然而像这样的反应式会话确实给研究带来了一些问题。笔记本保存输出是有原因的,那就是为了可复制的代码。我当然同意这可能会导致国家和诸如此类的问题——但我不认为像这样消除产出是必要的。有了对 Pluto.jl 数据格式的新认识,我们可以通过调用新的单元格数据测距仪来继续我们的函数:

function read_plto(uri::String)
    cellpos = plto_cell_lines(uri)
    cells = Array{AbstractCell}()    
end

该过程的最后一步是将所有这些数据适当地放入我们的 Jockey 结构中,并确定我们正在内联处理哪种类型的单元。幸运的是,对于这次阅读,我相信我们将只需要处理输入单元!让我们回头看看我们的类型:

abstract type AbstractCell end
mutable struct InputCell <: AbstractCell
    ID::UUID
    Text::String
    env::Dict
endmutable struct OutputCell <: AbstractCell
    ID::UUID
    output::String
endmutable struct Cell <: AbstractCell
    input::AbstractCell
    output::AbstractCell
    hidden::Bool
    lang::Symbol
    env::UUID
end

现在,我们可以非常容易地创建我们的函数,它将调用我们刚刚编写的函数来获取有效的行位置,以及我们必须编写的一些新函数。看一看:

function read_plto(uri::String)
    cellpos = plto_cell_lines(uri)
    cells = []
    x = readlines(uri)
    for cell in values(cellpos)
        unprocessed_uuid = x[cell[1]]
        text_data = x[cell[2:end]]
        identifier = process_uuid(unprocessed_uuid)
        inp = InputCell(identifier, text_data)
        out = OutputCell(UUIDs.uuid1(), "")
        cl = Cell(inp, out, false, :JL, UUIDs.uuid1())
        push!(cells, cl)
    end
    return(cells)
end

我相信这个新方法会起作用,我们只需要创建一个函数来处理我们的 UUIDs,然后创建另一个函数来处理文本数据——这是比较困难的部分。在我们的第一次尝试中,让我们看看这个 UUID 实际上会是什么样子,这样我们就可以确保正确地分割每个字符串。此外,应该注意的是,输出也被分配了新的 id。

function process_uuid(text::String)
    println(text)
    uuid = UUID(id)
    return(uuid)
end8# ╔═╡ 611c28fa-9542-11ea-1751-fbdedcfb7690

我简单地把这个字符串分成三份,抓住第三个元素,然后把它变成 UUID 类型。

function process_uuid(text::String)
    dims = split(text, ' ')
    uuid = UUID(dims[3])
    return(uuid)
end

结论

我现在意识到我们已经结束了。不需要编写数据算法,因为最终大部分都将由 Java 来处理,无论如何我都需要编写解析器。将数据解析到 Julia 中,然后发送给 JavaScript,再次变得完全无法解析,这是没有用的。首先,我要说——这是一项很好的工作,但我很高兴它完成了。我们现在唯一需要做的就是测试代码:

read_plto("weird.jl")MethodError: Cannot `convert` an object of type InputCell to an object of type Cell
Closest candidates are:
  convert(::Type{T}, ::T) where T at essentials.jl:205
  Cell(::Any, ::Any, ::Any, ::Any, ::Any) at In[1]:15

有趣的是,我认为我对类型的更改需要内核重启。为了确保这些更改都在这里,下面是更新的类型:

using UUIDs, TOML, Markdownabstract type AbstractCell end
mutable struct InputCell <: AbstractCell
    ID::UUID
    Text::Any
endmutable struct OutputCell <: AbstractCell
    ID::UUID
    output::Any
endmutable struct Cell <: AbstractCell
    input::AbstractCell
    output::AbstractCell
    hidden::AbstractBool
    lang::Symbol
    env::UUID
end

这些当然只是它们未来类型的骨架,但是让我们通过重新运行我的笔记本来解决这个问题。

开始了。

read_plto("weird.jl")

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

(图片由作者提供)

现在这个问题已经解决了,我已经朝着完成这个计划迈出了重要的一步。然而,仍有大量工作要做。我很兴奋能继续写博客!感谢您的阅读,鉴于这篇文章中有很多很酷的算法内容,我希望它是有帮助的,或者至少是很酷的!在未来,我计划重申这些功能,使它们更流畅,并添加一些文档,但现在我将沉浸在数据加载的荣耀中。谢谢你看我的文章,祝你学习愉快!

用 PyTorch 创建一个强大的新冠肺炎面具检测工具

原文:https://towardsdatascience.com/creating-a-powerful-covid-19-mask-detection-tool-with-pytorch-d961b31dcd45?source=collection_archive---------23-----------------------

快速建立小而精确的图像分类模型的实例研究

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

马修·韦林在 Unsplash 上的照片

在过去的一年里,新冠肺炎给世界带来了社会、经济和人类的损失。人工智能工具可以识别正确的面具佩戴,以帮助重新打开世界,防止未来的大流行。

当然,这有更深层的社会含义,比如隐私和安全的权衡。这些将在随附的 arXiv 研究论文中讨论。

在这篇文章中,我将带你浏览我们创建的项目。

读完这篇文章*,你将有知识创建一个类似的管道,不仅用于遮罩检测,也用于任何类型的图像识别*。

特征工程

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

我们的数据集

使用 MaskedFace-NetFlickr Faces 数据集,我们将图像大小调整为 128x128 以节省空间。我们将图像移动到三个文件夹中(train、val 和 test)。每个文件夹都有三个子目录(正确/不正确/无掩码)。这使得他们很容易装载 PyTorch 的火炬视觉。

batch = 16 train_dataset = torchvision.datasets.ImageFolder('./Data_Sample/train', transform = train_transform)val_dataset = torchvision.datasets.ImageFolder('./Data_Sample/val', transform = test_transform)test_dataset = torchvision.datasets.ImageFolder('./Data_Sample/test', transform = test_transform)train_dataset_loader = torch.utils.data.DataLoader(
train_dataset, batch_size=batch, shuffle=True)val_dataset_loader = torch.utils.data.DataLoader(
val_dataset, batch_size=batch, shuffle=True)test_dataset_loader = torch.utils.data.DataLoader(
test_dataset, batch_size=batch, shuffle=False)

如果您查看代码片段,您会发现我们使用了 torchvision 的内置参数来对我们的图像进行转换。

对于所有数据,我们将图像转换为张量,并使用一些标准值对其进行归一化。对于训练和验证数据,我们应用了额外的转换。例如,随机对图像进行重新着色、调整大小和模糊处理。这些是应用于每一批的**,意味着模型试图学习一个移动目标**:每次应用不同噪声的训练图像。

import torchvision.transforms as transformstest_transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])

变换使您的模型规范化,使其更好地一般化。因此,它将在真实世界的数据上表现得更好。

基线模型

对于像实时图像分类这样的目标,准确性和速度都是关键。这些通常有一个权衡,因为较大的模型可能具有较高的准确性。为了获得基线,我们从应用更快的机器学习模型开始。

好家伙,我们会大吃一惊的!我们意识到,我们的数据集使用合成模型使得预测变得有些琐碎。在时间压力下,并且在我们使用的 180,000 张图像附近没有数据集,我们继续研究如何进一步提高性能

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

基线模型精度

对于这些更简单的模型,我们使用 LeakyReLU 和 AdamW 训练了 scikit-learn 的随机森林、cv2 的 Haar 级联分类器和自定义 CNN。

高级模型

接下来,我们开始使用最先进的模型。顶级研究人员使用数百万美元的计算来训练和微调这些模型。对于一般问题,它们往往工作得最好。

我们可以用我们的数据训练它们,看看它们在我们的面具分类任务中表现如何。这种转移学习比从头开始训练要快得多,因为权重已经接近最优。我们的训练会使他们变得更好。

下面的函数用于不同的 torchvision 模型,看看它们的性能如何。

# Takes the model and applies transfer learning
# Returns the model and an array of validation accuracies
def train_model(model, dataloaders, optimizer, criterion, scheduler, device, num_epochs=20):
 startTime = time.time()
 top_model = copy.deepcopy(model.state_dict())
 top_acc = 0.0 for epoch in range(num_epochs): for data_split in ['Train', 'Validation']: if data_split == 'Train':
    scheduler.step()
    model.train() else:
    model.eval() # Track running loss and correct predictions
   running_loss = 0.0
   running_correct = 0 # Move to device
   for inputs, labels in dataloaders[data_split]:
    inputs = inputs.to(device)
    labels = labels.to(device) # Zero out the gradient
    optimizer.zero_grad()# Forward pass
   # Gradient is turned on for train
    with torch.set_grad_enabled(data_split == "Train"):
    outputs = model(inputs)
    loss = criterion(outputs, labels)
    _, preds = torch.max(outputs, 1)
    if data_split == "Train":
     loss.backward()
     optimizer.step()
    # Update running loss and correct predictions
    running_loss += loss.item() * inputs.size(0)
    running_correct += torch.sum (labels.data == preds)

   epoch_loss = running_loss / dataloader_sizes[data_split]
   epoch_acc = running_correct.double() / dataloader_sizes[data_split]
   print('{} Loss: {:.2f}, Accuracy: {:.2f}'.format(data_split,     epoch_loss, epoch_acc))
   # If this the top model, deep copy it
   if data_split == "Validation" and epoch_acc > top_acc:
   top_acc = epoch_acc
   top_model = copy.deepcopy(model.state_dict()) print("Highest validation accuracy: {:.2f}".format(top_acc)) # Load best model's weights
 model.load_state_dict(top_model)
 return model;

由于我们的重点是速度,我们选择了四个较小但性能良好的神经网络,并取得了以下结果:

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

迁移学习模型的准确性

大幅提升!但是我们能做得更好吗?

蒸馏

这是的第一步。

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

Jan Ranft 在 Unsplash 上拍摄的照片

蒸馏是一项前沿技术,它训练更小的模型来做出更快的预测。它从网络中提取知识。这非常适合我们的用例。

在蒸馏中,你从教师模型中训练学生。不是根据你的数据训练你的模型,而是根据另一个模型的预测训练它。因此,您可以用更小的网络来复制结果。

蒸馏的实施可能具有挑战性且需要大量资源。幸运的是, KD_Lib for PyTorch 提供了可作为库访问的研究论文的实现。下面的代码片段用于香草蒸馏。

import torchimport torch.optim as optimfrom torchvision import datasets, transforms
from KD_Lib.KD import VanillaKD# Define models
teacher_model = resnet
student_model = inception# Define optimizers
teacher_optimizer = optim.SGD(teacher_model.parameters(), 0.01)
student_optimizer = optim.SGD(student_model.parameters(), 0.01)# Perform distillation
distiller = VanillaKD(teacher_model, student_model, train_dataset_loader, val_dataset_loader,
teacher_optimizer, student_optimizer, device = 'cuda')
distiller.train_teacher(epochs=5, plot_losses=True, save_model=True)
distiller.train_student(epochs=5, plot_losses=True, save_model=True)
distiller.evaluate(teacher=False)
distiller.get_parameters()

在我们的 DenseNet 模型上使用香草蒸馏,我们用我们的基线 CNN 达到了 99.85%的准确率。在 V100 上,CNN 以每秒 775 次推理的速度超过了所有最先进型号的速度。CNN 用 15%的参数做到了这一点。

更加赫然, 再次运行蒸馏继续提高精度。例如,NoisyTeacher、SelfTraining 和 MessyCollab 的组合提高了结果。

边注: 自我训练 把你的模型既当老师又当学生,多爽!

结束语

创建一个正确使用面具的分类器既及时又紧迫。

构建这条管道的课程对你想做的任何图像分类任务都是有用的。希望这个管道有助于理解和解决你想要做的任何图像分类任务。祝你好运!

相关论文:【https://arxiv.org/pdf/2105.01816.pdf】

相关演示:https://www.youtube.com/watch?v=iyf4uRWgkaI

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

掩模分类器(单独的 YOLOv5 管道,在中)

用 GradioML 创建一个简单的机器学习演示

原文:https://towardsdatascience.com/creating-a-simple-image-classification-machine-learning-demo-with-gradioml-361a245d7b50?source=collection_archive---------7-----------------------

只需几行代码就可以在功能性用户界面中部署模型

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

作者图片

部署机器学习模型有时是数据科学中被忽视的一个方面。许多分析专业人员将大部分注意力集中在理论和应用上,以构建能够解决问题和满足目标的模型。这在项目的研究或原型阶段都是完全没问题的。但是,为了与其他职业的利益相关者或合作者分享这项工作,为这些用户和观众开发某种应用程序会很好。

然而,部署这些模型的任务并不总是那么简单。要完成这项工作,还需要掌握许多额外的技能和工具。传统上,机器学习工程师和 DevOps 专家等专家与数据科学家合作,将这些模型投入生产。

有时,一个简单的用户界面演示可以完成传达机器学习模型内容的工作,而不是全力以赴进行部署。在寻找可以帮助构建这个的工具时,我偶然发现了 GradioML ,一个符合这种描述的开源工具。

**Gradio 是一个软件包,允许用户用几行代码创建简单的网络应用。**它的基本用途与 Streamlight 和 Flask 相同,但使用起来更简单。许多类型的网络界面工具可以选择,包括画板,文本框,文件上传按钮,网络摄像头等。使用这些工具接收各种类型的数据作为输入,可以很容易地演示分类和回归等机器学习任务。(参考工具见官网及其 Github 页面)

在本演练中,我们将快速创建一个猫/狗图像分类模型,并部署一个简单的 Gradio 演示程序,我们可以在其中上传新图像以进行分类预测。该模型将是一个简单的 Keras 卷积神经网络(CNN) ,它将在作为特征的猫和狗的图像上进行训练,并将它们的类名作为标签。

有关 Jupyter 笔记本的完整代码,请参考此链接

必需品;要素

首先我们安装 Gradio

pip install gradio

接下来,我们导入依赖项。我们需要的一些工具将用于数值计算(Numpy)可视化/绘图(Matplotlib)图像数据争论(cv2)深度学习 (Tensorflow,Keras),当然还有构建 web 界面 (Gradio)

import numpy as np
import pandas as pdimport matplotlib.pyplot as plt
import os
import cv2from sklearn.model_selection import train_test_split
from sklearn import metricsimport tensorflow as tf
from tensorflow import keras
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, Activation, Flatten, Conv2D, MaxPooling2Dimport gradio
import gradio as gr 

浏览和组织数据

然后我们看一下我们的数据。猫/狗图像来自发布在 Kaggle 中的数据集来源。我们将检查第一张图片

DATADIR = os.path.abspath(os.getcwd()) + '/PetImages'path = os.path.join(DATADIR, category)    #path to cats or dogs dir
first_img_path = os.listdir(path)[0]
img_array = cv2.imread(os.path.join(path, first_img_path), cv2.IMREAD_GRAYSCALE)
plt.imshow(img_array, cmap = "gray")
plt.show()#show image shape
print('The image shape is {}'.format(img_array.shape))

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

作者图片

因为这个练习是针对一个简单的 CNN 模型,我们将调整所有图像的大小为 shape (100,100 ),并将它们的颜色改为灰度。

要素和标注也将被分离并分别添加到列表 X 和 y 中

#create create array of data
data = []
def create_data():
    for category in CATEGORIES:
        path = os.path.join(DATADIR, category)  
        class_num = CATEGORIES.index(category)    
        for img in os.listdir(path):
            try: 
                img_array = cv2.imread(os.path.join(path, img), cv2.IMREAD_GRAYSCALE)
                new_array = cv2.resize(img_array, (IMG_SIZE, IMG_SIZE))data.append([new_array, class_num])
            except Exception as e:
                pass
create_data()#randomly shuffle the images
random.shuffle(data)#separate features and labels
X = []
y = []for features, label in data:
    X.append(features)
    y.append(label)#neural network takes in a numpy array as the features and labels so convert from list to array and change shape
X = np.array(X).reshape(-1, IMG_SIZE, IMG_SIZE, 1)
y = np.array(y)

调整后的特征图像示例如下所示

#show first feature image X
first_feature = X[0]
plt.imshow(first_feature, cmap = 'gray')
print('The image shape is {}'.format(first_feature.shape))

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

作者图片

最后,我们归一化图像以确保每个像素具有相似的数据分布(在训练卷积神经网络模型时允许更快的收敛)

#normalize images
X = X/255.0

建模

这里我们将训练(70%)和测试(30%)数据分开。总共会有 17462 个训练数据和 7484 个测试数据。

#separate training and test data
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)print('the shape of training features is {}'.format(X_train.shape))
print('the shape of training labels is {}'.format(y_train.shape))print('the shape of test features is {}'.format(X_test.shape))
print('the shape of test labels is {}'.format(y_test.shape))

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

作者图片

我们现在创建我们的卷积神经网络(CNN)模型。它将由多个卷积层、最大池层和下降层组成。卷积层中的所有激活函数将是 relu,而输出密集层的激活函数将是 softmax。

#create model
model = Sequential()model.add(Conv2D(64, (3,3), activation = 'relu'))
model.add(MaxPooling2D(2,2))
model.add(Dropout(0.1))model.add(Conv2D(64, (3,3), activation = 'relu'))
model.add(MaxPooling2D(2,2))
model.add(Dropout(0.2))model.add(Conv2D(64, (3,3), activation = 'relu'))
model.add(MaxPooling2D(2,2))
model.add(Dropout(0.2))model.add(Flatten())model.add(Dense(128, input_shape = X.shape[1:], activation = 'relu'))#output layer
model.add(Dense(2, activation = 'softmax'))

使用以下参数编译模型:

#compile the model
model.compile(loss="sparse_categorical_crossentropy",
             optimizer="adam",
             metrics=['accuracy'])

使用 5 个时期和 0.1 的验证分割来训练模型

#fit model
history = model.fit(X_train, y_train, epochs=5, validation_split=0.1)

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

用 5 个时期训练模型:作者的图像

#show learning curves
#mean training loss and accuracy measured over each epoch
#mean validation loss and accuracy measured at the end of each epochpd.DataFrame(history.history).plot(figsize=(8,5))
plt.grid(True)
plt.gca().set_ylim(0,1) # set the vertical range to [0-1]
plt.show()

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

学习曲线;培训与验证:作者提供的图片

该模型似乎没有过度拟合训练数据,因为在训练和验证准确性/损失之间没有相当大的差距。验证精度略高于使用脱落图层时可能出现的训练精度。

我们预测测试数据的类别,并比较我们的准确度

#use predict_classes() to find the class with the highest probability
y_pred = model.predict_classes(X_test)print("Performance Summary of Sequential Neural Network on test data:")#show classification report
print(metrics.classification_report(y_test, y_pred))#show confusion matrix
print(metrics.confusion_matrix(y_test, y_pred))

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

分类报告和混淆矩阵:作者图片

虽然不令人惊讶,但在测试数据的 83%的总体准确率下,这是一个相当不错的模型

我们可以快速浏览前 5 个正确和不正确的分类

#show first 5 correctly identified test images with predicted labels and probabilities
fig, ax = plt.subplots(1,5,figsize=(20,20))class_names = ["Dog", "Cat"]for i, correct_idx in enumerate(correct_indices[:5]):
    ax[i].imshow(X_test[correct_idx].reshape(100,100),cmap='gray')
    ax[i].set_title("{} with probabililty of {}%".format(class_names[y_pred[correct_idx]], int(max(y_proba[correct_idx]

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

前 5 张正确识别的图片:作者图片

#show first 5 incorrectly identified test images with predicted labels and probabilities
fig, ax = plt.subplots(1,5,figsize=(20,20))for i, incorrect_idx in enumerate(incorrect_indices[:5]):
    ax[i].imshow(X_test[incorrect_idx].reshape(100,100),cmap='gray')
    ax[i].set_title("{} with probabililty of {}%".format(class_names[y_pred[incorrect_idx]], int(max(y_proba[incorrect_idx])*100)))

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

前 5 张识别错误的图片:作者图片

有趣的是,该模型已经正确识别了一些甚至人类都难以看到的图像。但是,它也错误地识别了一些明显的猫和狗的图片。

使用 Gradio 的模型演示

最后,我们准备使用 Gradio 来创建我们模型的演示。同样,目的是使用该模型在新上传的输入图像上预测猫或狗类别

#create a function to make predictions
#return a dictionary of labels and probabilities
def cat_or_dog(img):
    img = img.reshape(1, 100, 100, 1)
    prediction = model.predict(img).tolist()[0]
    class_names = ["Dog", "Cat"]
    return {class_names[i]: prediction[i] for i in range(2)}#set the user uploaded image as the input array
#match same shape as the input shape in the model
im = gradio.inputs.Image(shape=(100, 100), image_mode='L', invert_colors=False, source="upload")#setup the interface
iface = gr.Interface(
    fn = cat_or_dog, 
    inputs = im, 
    outputs = gradio.outputs.Label(),
)iface.launch(share=True)

这段代码中发生了以下情况:

  1. 我们首先创建一个名为 cat_or_dog()的函数,它将一个图像数组作为输入,利用模型进行预测,并返回一个字典,其中每个类名作为键,其各自的概率作为值(例如{Dog: 0.6,Cat: 0.4})
  2. 设置输入上传:转换输入图像以匹配模型被训练的输入形状,在我们的例子中是(100,100)。我们还将源设置为“上传”,这样我们就可以将自己的图像上传到 Gradio 中
  3. 编译接口;利用我们在上面创建的 cat_or_dog()函数,将 input 设置为输入上传器,并允许 Gradio 返回类及其概率作为输出

结果显示在下面的 gif 中:

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

Gradio 图像分类演示:按作者分类的图像

用户可以轻松地从本地拖放或上传图像,并单击“提交”以显示模型分类的输出。概率较高的类别(猫或狗)将显示为最终预测。

结论

在本练习中,使用 CNN 构建了一个影像分类模型,并使用一个名为 GradioML 的工具将其部署为一个简单的演示。然而,Gradio 可以用于更多的任务,如回归/数值预测和自然语言处理。Gradio 具有适合这些任务的各种界面选项,是一种可以作为呈现快速机器学习演示的快速高效解决方案的工具。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值