TowardsDataScience-博客中文翻译-2020-二十三-
TowardsDataScience 博客中文翻译 2020(二十三)
NLP 数据科学家不会告诉你的残酷事实
由数据科学家分享

答根据 Tractica 的报告,人工智能 NLP 软件市场预计将从 2016 年的1.36 亿美元增长到 2025 年的 54 亿美元。这大约是 10 年增长 40 倍!
另一方面,计算语言学协会(ACL),杂志计算语言学的发起者一直在举行年会,吸引了数十位 NLP 科学家提交他们的作品。仅 2019 年提交的科学论文就比 ACL 2018 年增加了 75% 。
你可能会想——嘣!我要努力工作,在不久的将来成为一名 NLP 数据科学家!我爱 NLP!
这是否意味着你应该进入这个领域,只是因为它的光明前景?
事情是这样的。你所读到的一切都表明 NLP 的未来是光明的,它会很棒。然而,你不应该在不知道 NLP 数据科学家在做什么的情况下进入这个领域。我希望你能充分了解实际情况,以便你能更好地决定是否进入 NLP 领域。
在这篇文章中,我将与你分享作为一名 NLP 数据科学家的真相。
什么是 NLP?
简而言之,它涉及对人类自然语言和语音进行分析的计算技术。
嗯嗯..这是什么意思?🤔
这意味着你要处理不同形式的文本。我跟大家分享一下一个 NLP 数据科学家时不时会面临的一些情况。
情况 1
我们来看看下面的推文。

想象你正在分析这篇文章。你的目标是理解课文的意思。比方说,你认为主语是“我的裤子”,动词是“失踪”。那么,你从这条推文中得到了什么?
“裤子不见了。”..??!
这显然不能代表推文的意思吧?
情况 2
现在,假设您正在执行基于方面的情感分析。基于方面分析包括情绪(正面或负面)和目标(观点)。
例如,“餐馆提供的服务很好”。这里,方面是“服务”,情绪是“积极的”。
为什么这很重要?这是因为餐馆的老板不仅知道顾客的体验很好,而且他们提供的服务也很棒。
假设您在数据集中看到了这篇评论。
这个真空吸尘器真的很烂。
这里的主题是真空吸尘器,但情绪应该是什么?“糟透了”这个词通常代表一种负面情绪,但你可以看到当它和吸尘器搭配在一起时,这个意思可能会发生变化。
真空吸尘器通过产生吸力来清洁。当你说它真的很烂的时候,你是在描述这台吸尘器很好用,不是吗?
情况 3
让事情变得更复杂。考虑下面这个问题。
嘿老弟,去哪里吃好吃的啊?
这句话的意思是食物很好吃吗?不,这实际上只是一个问题。
情况 4
另一种情况是,当你在处理文本时,你不知道它是什么意思。例如,你懂英语、汉语和马来语。但是,贵公司正在进行日语文本分类项目。所以,当你在试图理解你的模型出了什么问题的时候,你会很难受。
解决方案之一可能是使用谷歌翻译将句子转换成你知道的语言。然而,谷歌翻译并不完美。有些情况下,提供的翻译没有意义,你需要咨询你的母语是日语的人。
情况 5
此外,假设您正在进行文本分类任务。目标是检测商品名称是属于葡萄酒还是果汁。
也许你正在考虑使用关键字列表作为一项功能。在你花了几个小时找到一些有用的关键字来区分这两个类别之后,你会想到:
首先,您决定为每个类创建一组关键字列表。例如,葡萄酒类的关键字列表是['葡萄酒','葡萄汁'],而果汁类的关键字列表是['果汁']。如果在项目名称中找到关键字列表中的元素,那么该元素将作为一个特征被输入到模型中。
然而,您的模型的性能结果低于 90%的准确性的基准。
你该怎么办?你耐心地检查每一个错误分类的测试数据。当你发现葡萄酒有许多错别字时,你感到震惊:wne,wyne 等等。因此,您必须更新列表或对您的训练数据集执行一些错别字检查,以期提高准确性。
然而,这并不是故事的结尾。准确度确实提高了,但是您仍然对结果不满意。同样,你盯着错误分类的数据,找出这个有趣的项目名称:
"由发酵的葡萄汁制成的黑皮诺"
你从标题中提取的关键字是“果汁”,因此你的模型将其归类为果汁类,这是错误的!黑皮诺是红酒,因此它应该被归类为葡萄酒!
结论
文字既有趣又恶心。因此,大多数时候,NLP 数据科学家会看着数据,挠你的头,试图想办法让你的模型理解上下文。
因此,如果你认为 NLP 数据科学家只是打个电话。在 sklearn 中 fit(),你应该马上改变方向。
如果你只能从这篇文章中得到一样东西,那就是这个。
你应该期待你 80%的时间,不管你是在执行分析、特征工程、模型改进,还是在查看文本数据。因此,请确保您很好地理解您的数据,并能预见未来可能发生的一些潜在情况。
最终想法

恭喜你!你一直读到文章结束。我希望我没有降低你成为 NLP 数据科学家的兴趣。我写这篇文章的目的只是为了帮助你在进入 NLP 领域之前更好地理解一些重要的信息。
当然,这只是我的 2 美分,我欢迎你在下面发表评论,分享你作为 NLP 数据科学家的个人经验!🤗
让我引用一句话来结束这篇文章。
我知道你已经听过一千遍了。但这是真的——努力是有回报的。如果你想变好,你必须练习,练习,再练习。如果你不喜欢什么,那就不要做。—雷·布雷德伯里
关于作者
低伟鸿是 Shopee 的数据科学家。他的经验更多地涉及抓取网站,创建数据管道,以及实施机器学习模型来解决业务问题。
他提供爬行服务,可以为你提供你需要的准确和干净的数据。你可以访问这个网站查看他的作品集,也可以联系他获取抓取服务。
蛮力翻筋斗问题
用穷举法快速解决横竿问题。

翻筋斗问题是强化学习中一个突出的基准问题,它在 OpenAI 的健身房中的实现最为人所知。也是他们排行榜上最受欢迎的s;这很有道理,是经典控制中比较容易出现的问题之一。但是这有多简单呢?
目前,一个解决方案需要在 100 集内平均平衡 195 步(或更多)。请记住,每集在 200 步后结束,因此解决方案确实需要有一定的稳定性。
一段时间以来,我一直认为在 200 步内保持平衡太容易了。因此,为了证实我的怀疑,我强行解决了这个问题。
如果你想了解我使用的所有代码,请随意在这里查看:https://github . com/Adam price 97/Control/blob/master/bruteforcecartepole . ipynb
在密码学中,暴力攻击首先计算所有可能的密码字符串。然后,它反复应用这些密码,直到找到正确的密码。为了在控制中使用类似的方法,我们需要生成一系列的策略来控制横向拉杆。这对于连续的状态空间是不可能的,所以我们必须将状态空间离散化。
小车问题有 4 个观察值:“小车位置”、“小车速度”、“极角”和“极速度”。我们将完全忽略“推车位置”和“推车速度”,200 个时间步不足以让推车移动足够远来结束这一集。这给我们留下了“极角”和“极速度”,它们都将被“离散化”到 3 个独立的箱中,创建 9 种可能的环境状态。
掷骰子问题只有 2 个动作,因此有 9 个状态,我们有 512 个(2⁹)确定性贪婪策略的极限。我们现在需要的是生成这些策略的方法,然后我们可以尝试使用蛮力来解决:
在每个状态-动作对中,购物车将向左或向右移动(0 或 1)。因此,为了创建策略,我们只需为从 0 到 511 的每个数字生成二进制数。然后,字符串被重新整形,形成一个 3×3 的矩阵,以便于流水线操作。
完全评估每个策略的计算成本很高,因此,首先,我们对问题运行每个策略一次,并跟踪得分高于 195 的策略。
当我们运行这个脚本时,我们发现最初的 512 个策略中有 34 个是潜在的解决方案。为了进一步检查它们,我们需要运行这些潜在的解决方案 100 集,并平均它们的性能。
当我们运行时,我们在 39.1 秒内找到了 8 个解决方案。所以,我们有它。我们成功地暴力破解了翻筋斗问题!
这显然是一个解决控制问题的糟糕方法。我们发现的解决方案是非常不稳定的,没有一个能够平衡极点超过 300 个时间步。为了找到更好的解决方案,我们需要在状态空间中使用更多的桶,鉴于这种方法的二次复杂性,尝试这种方法是非常愚蠢的。
然而,我们已经找到了有效的解决办法。作为一个基准问题,这是对 cartpole 的谴责吗?我不这么认为。问题可能仍然很难,你只需要更长时间地平衡杆子。将平均奖励提高到 490,上限为 500,可能会使这种暴力方法变得多余。
另外,基准甚至需要有难度吗?求解 cartpole 的算法通常通过在求解环境之前所需的集数来进行比较。这种强力算法需要 512 次非评估迭代,这将是健身房排行榜上的最后一次…
编辑:在这篇文章的结尾,我声称:
将平均奖励提高到 490 分,上限为 500 分,可能会让这种暴力方法变得多余。
事实证明我错了。这个笔记本有这样的证明:https://github . com/Adam price 97/Control/blob/master/bruteforcecartepole 2 . ipynb
事实上,这种方法可以在合理的时间框架内解决 500 个步骤。
气泡图,为什么和如何
用泡泡讲故事

图片由来自 Unsplash 的 Braedon McLeod 提供
又名:泡泡图,泡泡图
原因:气泡图用于确定至少三个数值变量 是否相关或共享某种模式。在特殊情况下,它们可以用来显示一段时间内的趋势或比较分类变量。它们被认为是散点图的自然延伸,其中的点被气泡或圆盘所取代。
如何:针对一对数值变量(A,B)的每次观察绘制一个气泡或圆盘,在笛卡尔坐标系中,根据变量 A 的值水平定位圆盘,根据变量 B 垂直定位圆盘。第三个数值变量通过气泡的区域表示。您甚至可以在不同的气泡中使用不同的颜色来合并第四个数据集(D:数字或分类)。
这个故事是从这些数据点产生的形状以及气泡或圆盘的相对大小的差异来叙述的。对于不同的类别,必须有适当的图例,用颜色和某种类型的刻度来表示,以便我们推断出气泡大小所表示的数值。

图 1:气泡图的示意图。该图形是由 Seaborn 开发的。
上图显示了变量 A 和变量 b 之间的直接(正)关系。位置(60,225)所示的磁盘显然是一个异常值。通过关键字 bbox_to_anchor ,分类变量的图例和用于推断第三个变量数值的标度位于图表之外。使用此关键字,您可以更好地控制手动图例的放置;我强烈建议把它放在右上方的位置(Marplotlib.org,#1)。
就像散点图一样,可以在气泡图中找到数据集的三个重要特征:1 .- 离群值,与数据集中所有其他数据非常不同并且似乎不符合相同模式的数据。这些异常值可能代表有价值的分析信息;2.-gap,不包含数据的区间。数据之间差距的可视化证明了解释其存在的深入分析的合理性;3.- 聚类,孤立的数据气泡组,也值得对其在图表中出现的原因进行具体分析。以前,必须验证异常值、缺口或聚类的存在不是由于数据收集方法中的错误。
下面的气泡图描述了世界各地区发育迟缓与获得基本卫生服务的患病率。研究表明,恶劣的卫生条件导致儿童发育迟缓,发育迟缓儿童的大脑神经元连接比正常儿童少。随着技术正在取代常规工作,对高级认知技能和更强适应性的需求正在上升,即使在发展中国家也是如此。但是,发育不良的儿童在未来劳动力市场所需的技能方面将处于劣势。图表左上角黄色气泡的出现表明,撒哈拉以南非洲地区构成了一个明显的国家集群,那里有数百万儿童在没有未来基本生活技能的情况下成长。由于圆盘的大小与该地区的人口相对应,该图还显示了为南亚数百万儿童带来安全卫生设施的迫切需要(世界银行,2018 年,#2)。

图 2:世界各区域阻碍获得基本卫生服务的发育迟缓的普遍程度。来源:世界银行,2018 年。
最著名的泡泡图属于汉斯·罗斯林的 TED 演讲。罗斯林(1948-2017)是瑞典医生和统计学家,卡罗林斯卡医学院国际卫生教授。在他的 TED 演讲中,他将巨大的数据集转化成关于世界、经济和人类未来的视觉故事。我强烈推荐看他 2006 年的第一个视频:“你见过的最好的统计”(#3)和 2013 年的“神话之河”(#4)。
温馨提示&警告( &!!)**
当我们想要显示三个或四个变量之间的关系**而不是它们的确切值时,气泡图是合适的。例如,在业务中,您可以通过在气泡图中可视化不同业务备选方案之间的成本、价值和风险等维度的关系来做出投资决策。
!!你应该经常验证第三个或第四个变量的增加是否会改善故事的讲述。如果没有,尝试切换到更简单的替代表示,如散点图。
!!气泡图的主要缺点在于数字变量之间的比较非常困难,因为我们用两种不同的尺度来表示它们:位置和大小。人类的大脑很容易识别位置,但是区域却很难比较。
!!永远记住,圆盘的面积与半径不成正比,而是与其平方成正比。
**笛卡尔平面 x-y 不一定要从(0,0)开始。你必须根据你的数据所能讲述的最好的故事来选择你的坐标系的原点(见图 4)。
!!与散点图不同,气泡图不会随着数据点数量的增加而改善。相反,每条信息都迫使观众计算相应气泡的大小,如果我们添加颜色来显示一些分类变量,这将变得更加复杂。虽然我们很容易掌握气泡大小的差异,但并不是每个人都会立刻联想到圆盘面积与半径的平方成正比。
!!它们不应用于表示零或负值,因为没有负或零区域。如果这种表示是必不可少的,建议使用实心圆表示正值,空心圆表示负值。在得出这种表示法之前,一定要分析备选方案,就像一种颜色的正值和一种非常不同的颜色的负值(蓝色对红色,如下图所示)。另一种方法是在一个坐标轴上定位带有负值的变量。永远记住,在气泡图中不小心使用负值可能会让观众困惑。例如,100 的圆和-100 的圆大小相同。

图 3:负值、零值和正值的建议表示。使用 Publisher 2010 制作的图表。
气泡数量的增加可能会导致拥塞和重叠**。在这种情况下,应该使用可视化工具提供的半透明替代品。当然,存在一定程度的重叠,超过这一程度,观众可能会感到困惑,尤其是在图表中有大量气泡或密集的气泡群时。此时,建议使用更简单的可视化替代方案。
**要用气泡图显示一段时间内的趋势,您必须将时间作为一个变量放在横轴上。另一种方法是使用某种动画,就像汉斯·罗斯林在他的 TED 演讲中所做的那样。
!!以“逻辑”大小显示整个图形的需要不允许很好地比较磁盘中的大小差异。因此,它们之间的微小差异不容易显现出来。
用气泡讲故事:白葡萄酒的品质
2017 年,全球生产了 2.5 亿百升葡萄酒。西班牙是世界葡萄酒销售的领导者,2018 年为 2280 万百升(西班牙葡萄酒市场观察站,2019)。紧随西班牙之后的是意大利(2140 万),法国(1540 万),智利(980 万)和澳大利亚(8)。不过从人均摄入来看,葡萄牙是世界领先的国家。葡萄牙人每年人均消费超过 51 升,是西班牙人的两倍。
葡萄酒是食品和饮料行业的一个特例,因为专家意见,尤其是所谓的大师的意见,通过在消费者中产生原型或质量模型,对葡萄酒市场产生了重大影响。对葡萄酒质量的感知与产品的特性有关。葡萄酒的感官特性(香气、味道、颜色、风味或触觉)由评委、专家或葡萄酒专业人士作为一个单一的多维属性在一个标尺上进行评估,该标尺在左端和右端具有“低质量”和“高质量”锚。
由于普通的葡萄酒消费者缺乏专家和专业人士的知识和经验,因此能够建立量化参数来帮助消费者做出购买一瓶葡萄酒的决定是很重要的。

图片由来自 Unsplash 的 Blake Barlow 提供
一个有趣的 Kaggle 竞赛是关于葡萄酒质量探索和分析葡萄牙“Vinho Verde”葡萄酒的红色和白色变种。
数据可在 https://archive.ics.uci.edu/ml/datasets/Wine+Quality获得,包括 1500 种白葡萄酒和 1500 种红葡萄酒的 11 种化学和物理特性。该项目的目的是评估以下哪些化学或物理特性影响葡萄酒的质量:固定酸度、挥发性酸度、柠檬酸、残糖、氯化物、游离二氧化硫、总二氧化硫、密度、pH 值、硫酸盐和酒精。这组葡萄酒由三位专家评估,他们为每种葡萄酒提供了 0(差)到 10(优)之间的质量分数。

表 1:葡萄酒数据集的前五条记录。
在研究结束时,还不清楚是什么区分了低质量的葡萄酒和中等质量的葡萄酒,只是根据一些化学性质区分了高质量葡萄酒的细微差异。一个重要的限制是数据集中缺少大量的低质量葡萄酒。总之,很明显,特定葡萄酒的质量是各种化学性质复杂结合的结果。
尽管如此,我们还是决定恢复该文件,并使用一些数据可视化技术来提供关于这样一个复杂主题的一些知识。考虑到质量是我们研究对象的基本属性,经过多次试验和大量图表,我们得出了以下气泡图:

图 4:葡萄牙“Vinho Verde”葡萄酒的质量、酒精、残糖和游离二氧化硫之间的关系。该图形是由 Seaborn 开发的。
横轴上表示的酒精,是指葡萄酒的酒精等级。这个参数是由许多因素决定的:葡萄的品种、收获的时间、随后发生的发酵过程以及随后的处理。
每升葡萄汁中含有大约 200 克糖,是葡萄糖和果糖的混合物。发酵时,糖大部分消失,留下酿酒师所谓的残余糖。葡萄酒中残留的糖分通常是发酵中断的结果(酵母死亡或无法消耗剩余的糖分)。酒瓶标签通常会标明残糖量。
葡萄酒行业使用二氧化硫的抗氧化和抗菌特性,防止颜色变化,尤其是在白葡萄酒中。由于消费者中不良反应的逐渐记录,二氧化硫的使用已经成为一个有争议的问题,消费者可能对二氧化硫的存在有轻度过敏(因此,在标签上指示其用途已经成为一些葡萄酒法规的一部分)。
图 4 中显示的气泡图清楚地表明,高品质的葡萄牙“Vinho Verde”葡萄酒(由绿色和蓝色圆盘表示)的酒精等级在 12%和 14 %之间,残糖水平低于 15 g/l。该图还表明,二氧化硫水平(由圆盘区域表示)对最终产品的质量没有相关影响。
所以,下次你买一瓶酒时,试着记录下酒精含量、残糖量和游离二氧化硫水平。虽然这不是一件容易的事情,但是通过数字尺度来量化葡萄酒的质量。通过这种方式,你将了解最适合你口味的化学参数。尽情享受吧!!
如果你对这篇文章感兴趣,请阅读我以前的:
簇状和重叠条形图,为什么和如何
为什么和如何
towardsdatascience.com](/clustered-overlapped-bar-charts-94f1db93778e)
堆积条形图,为什么和如何,讲故事和警告
讲故事和警告
towardsdatascience.com](/stacked-bar-graphs-why-how-f1b68a7454b7)
参考文献
1:https://matplotlib . org/3 . 2 . 2/tutorials/intermediate/legend _ guide . html #
2:https://www . world bank . org/en/news/feature/2018/12/21/year-in-review-2018-in-14 图表
3:https://www . ted . com/talks/Hans _ rosling _ the _ best _ stats _ you _ ve _ ever _ seen/抄本?language=es#t-67035
第四名:https://www.youtube.com/watch?v=lYpX4l2UeZg**
Matplotlib 中的气泡图
通过使用 Python 的 Matplotlib 库的例子学习绘制气泡图
气泡图是散点图的改进版本。在散点图中,有两个维度 x 和 y。在气泡图中,有三个维度 x、y 和 z。其中第三个维度 z 表示权重。这样,气泡图比二维散点图在视觉上提供了更多的信息。
数据准备
对于本教程,我将使用包含加拿大移民信息的数据集。它有 1980 年至 2013 年的数据,包括来自 195 个国家的移民人数。导入必要的包和数据集:
import numpy as np
import pandas as pd
df = pd.read_excel('[https://s3-api.us-geo.objectstorage.softlayer.net/cf-courses-data/CognitiveClass/DV0101EN/labs/Data_Files/Canada.xlsx'](https://s3-api.us-geo.objectstorage.softlayer.net/cf-courses-data/CognitiveClass/DV0101EN/labs/Data_Files/Canada.xlsx'),
sheet_name='Canada by Citizenship',
skiprows=range(20),
skipfooter=2)
数据集太大。所以,我不能在这里显示截图。让我们看看列的名称。
df.columns#Output:
Index([ 'Type', 'Coverage', 'OdName', 'AREA', 'AreaName', 'REG',
'RegName', 'DEV', 'DevName', 1980, 1981, 1982,
1983, 1984, 1985, 1986, 1987, 1988,
1989, 1990, 1991, 1992, 1993, 1994,
1995, 1996, 1997, 1998, 1999, 2000,
2001, 2002, 2003, 2004, 2005, 2006,
2007, 2008, 2009, 2010, 2011, 2012,
2013],
dtype='object')
我们不会用到很多列。我只是删除了这些列,并将国家的名称(' OdName ')设置为索引。
df = df.drop(columns = ['Type', 'Coverage', 'AREA', 'AreaName', 'REG', 'RegName', 'DEV', 'DevName',]).set_index('OdName')
df.head()

这个练习我选择了爱尔兰和巴西的数据。没有什么特别的原因。我随机选择了他们。
Ireland = df.loc['Ireland']
Brazil = df.loc['Brazil']
标准化数据
有几种不同的方法来标准化数据。我们将数据标准化,使数据处于相似的范围内。爱尔兰和巴西移民数据的范围不同。我需要把它们带到从 0 到 1 的范围。我只是用爱尔兰数据除以爱尔兰数据系列的最大值。我对巴西的数据序列做了同样的处理。
i_normal = Ireland / Ireland.max()
b_normal = Brazil / Brazil.max()
我们将绘制爱尔兰和巴西的数据。把这些年列在清单上会很有用。
years = list(range(1980, 2014))
制作气泡图
为了看出区别,我们先画散点图。
import matplotlib.pyplot as plt
plt.figure(figsize=(14, 8))
plt.scatter(years, Ireland, color='blue')
plt.scatter(years, Brazil, color='orange')
plt.xlabel("Years", size=14)
plt.ylabel("Number of immigrants", size=14)
plt.show()

现在,画出气泡图。我们必须输入我们之前定义的大小。
plt.figure(figsize=(12, 8))
plt.scatter(years, Brazil,
color='darkblue',
alpha=0.5,
s = b_normal * 2000)plt.scatter(years, Ireland,
color='purple',
alpha=0.5,
s = i_normal * 2000,
)
plt.xlabel("Years", size=14)
plt.ylabel("Number of immigrants", size=14)

我们可以通过气泡的大小来了解移民的数量。泡沫越小,移民人数越少。
我们也可以把这块地做成彩色的。为了使它更有意义,我们需要对数据序列进行排序。你很快就会明白原因。
c_br = sorted(Brazil)
c_fr = sorted(France)
现在我们将传递这些值来改变颜色。
plt.figure(figsize=(12, 8))
plt.scatter(years, Brazil,
c=c_br,
alpha=0.5,
s = b_normal * 2000)plt.scatter(years, Ireland,
c=c_fr,
alpha=0.5,
s = i_normal * 2000,
)
plt.xlabel("Years", size=14)
plt.ylabel("Number of immigrants", size=14)

现在我们增加了另一个维度,颜色。颜色随着移民的数量而变化。但是当我们画两个变量的时候,就没那么好了。因为在这个过程中,我们没有明确地定义单个变量的颜色。但是当我们在 y 轴上画一个变量时,它做得很好。让我们画出每年来自巴西的移民人数,看看这些年的趋势。
plt.figure(figsize=(12, 8))
plt.scatter(years, Brazil,
c=c_br,
alpha=0.5,
s = b_normal * 2000)
plt.xlabel("Years", size=14)
plt.ylabel("Number of immigrants of Brazil", size=14)

我敢肯定,你可以在这里非常清楚地看到颜色随着移民数量的变化。
这就是 Matplotlib 中的气泡图。我希望它有帮助。
这是另一个很酷的可视化教程:
[## 使用 Python 的 Matplotlib 的华夫饼图表
如何使用 Matplotlib 库在 Python 中绘制华夫饼图表
towardsdatascience.com](/waffle-charts-using-pythons-matplotlib-94252689a701)
推荐阅读:
Matplotlib 中的基本绘图:Python 中的可视化
用于边界框注释的预算自动化
实践教程
了解如何使用 TensorFlow.js 加速数据注记
介绍👋
数据收集和准备是每个机器学习应用的基础。你以前听说过:“垃圾输入,垃圾输出”,指的是算法纠正不准确、质量差或有偏见的输入数据的能力有限。
高质量标注数据的成本促使工具/平台的家庭工业加速数据标注过程。除了 SaaS/本地创业生态系统,每个主要的云提供商(AWS、微软、谷歌)在过去两年都推出了自动化数据标签产品。可以理解的是,开发这些服务时通常会考虑到高级/企业用户、功能和价位。
在有限的预算下,我是不是只能手工给的所有东西贴标签?
好消息。稍加努力,你就可以为你自己或一个小团队自动化边界框注释。在这篇博文中,我将向您展示我用来快速原型化 3D 打印故障检测模型的自动化技术。
您将学习如何:
- 为人类贴标机创建详细的说明
- 训练制导模型
- 使用 Microsoft VoTT (可视对象标记工具)和 TensorFlow.js 自动标注边界框
图为:自定义 TensorFlow 模型在微软 VoTT(可视对象标记工具)中自动标注一个视频帧。

自定义张量流模型在 Microsoft VoTT(可视对象标记工具)中自动注释视频帧。图片作者。
第一遍注释🏷
如果您是从没有标签的地方开始,您确实需要硬着头皮手工注释一些数据。为注释决策创建书面指南和评估标准,需要手动标记至少几百个示例。
从源代码安装 VoTT(视觉对象跟踪工具)
Microsoft VoTT 是一个开源工具,用于用边界框(对象检测)和多边形(分割)来注释图像和视频。我使用 VoTT 是因为它:
- 支持多种导出格式
- 可以作为 web 应用程序托管
- 让我从 TensorFlow.js 模型预填充边界框建议
安装先决条件:
- NodeJS (>= 10.x)和 NPM。我推荐 NVM (节点版本管理器)来管理 NodeJS 安装和环境。
克隆 VoTT repo 并从源安装:
$ git clone https://github.com/microsoft/VoTT
$ cd VoTT
$ npm ci
$ npm i @tensorflow/tfjs@2.7.0
$ npm start
要使用较新的 ops,必须升级 TensorFlow.js 包。
参考使用 VoTT 创建新项目并设置数据连接。
寻找数据集?试试谷歌的数据集搜索。
手动标记一些示例
您需要手动标记的图像数量取决于问题领域,从几十个图像到几千个图像。我通过以下方式为我的问题(检测 3D 打印缺陷)获得了合理的结果:
- 5 个标签(分布如下)
- 67 个打印延时视频,每秒采样 3 帧
- 浏览了 6 248 张图片
- 在 3,215 幅图像上绘制了 9,004 个边界框,平均每幅图像 3 个边界框。
- 八小时,分几天完成。我在没有早晨通勤的情况下赶上了我一直忽略的播客。

VoTT(视觉对象跟踪工具)提供的数据集统计。图片作者。
编写注释指南
当这个任务还历历在目时,花点时间写下清晰的指南(如下例),以保持标签的一致性,并涵盖常见的边缘情况。请随意使用我的指示作为你自己的模板。
边界框注释指南
概念
2-3 句话介绍任务/概念
该数据集包含失败的 3D 打印作业的延时视频。图像是按时间顺序排列的。您的任务是在所有可识别的像素周围画出紧密的方框,以匹配打印缺陷或对象。
标签
id、文本名称、标签和边缘案例的书面描述、正面和负面示例
- 标签应该从 0 还是 1 开始?
- 0 是否为背景/未知类保留?
0 背景
1 个喷嘴
打印喷嘴是一个金属物体,它挤出热丝。
如果喷嘴被部分遮挡,围绕整个对象(包括遮挡的像素)绘制一个边界框。
如果喷嘴完全堵塞,不要贴标签。
2 个木筏
“筏”是围绕印刷品前几层的薄轮廓。
如果筏子被部分遮挡(通常被印迹遮挡),在整个筏子周围画一个边界框。
3 打印
正在打印的对象。如果要打印多个对象或多个部分,请在每个不同的对象周围画一个边框。
4 附着力
…
5 根意大利面条
…
指导方针
- 输入格式
- 标签格式
- 每帧 1 个还是多个对象?
- 每个对象“实例”有 1 个还是多个盒子?
- 盒子是紧的还是松的?
- 标签反射(镜子,水)?
用 AutoML 训练制导模型🤖
AutoML(自动机器学习)是一种属于“强力”算法类别的技术。基于云的 AutoML 平台是一个很好的工具,用来验证你的问题可以和应该用机器学习来解决。
即使你计划训练一个模型,也要考虑先把 AutoML 模型放在客户面前。尽早收集客户反馈,并将这些信息整合到定制模型的开发中。一些见解的例子…
- 客户对误报不敏感(通过短信报告缺陷,但打印没问题)。
- 大多数客户喜欢印刷进度的可视化更新,即使检测机不正确。
- 令人惊讶的是,一些客户报告的假阳性引起了安全感。
我使用了谷歌云自动视觉 Edge(物体检测),我选择它是因为:
从 VoTT 导出数据集
在项目的导出设置中,选择 CSV 提供程序。选中“包括图像”,保存配置,然后导出数据。如果您要导出数千幅图像,这将需要几分钟时间。休息一下!

VoTT 导出设置。图片作者。

从 VoTT 导出的文件。图片作者。
检查和预处理数据
如果提供了两个顶点,AutoML Vision 需要以下格式的 CSV 数据:
SET,gs://path/to/img,label,x_min,y_min,,,x_max,y_max
坐标必须是相对于图像尺寸的,落在范围【0,1】内。
Github Gist 中提供的代码
import pandas as pd
# load VoTT CSV export
# notice: coordinates are absolute
df = pd.read_csv('/path/to/vott-csv-export/{project name}-export.csv')
df.head()

图片作者。
import cv2
base_path = '/path/to/vott-csv-export/'
LOG_INTERVAL=2000
# convert absolute coordinates to relative coordinates in [0, 1] range
for index, row in df.iterrows():
if index % LOG_INTERVAL == 0:
print(f'finished {index} / {len(df)}')
filename = row['image_path'].split('/')[-1]
img = cv2.imread(f'{base_path}{filename}')
height, width, channels = img.shape
df.at[index, 'x1_n'] = row['x1'] / width
df.at[index, 'x2_n']= row['x2'] / width
df.at[index, 'y1_n'] = row['y1'] / height
df.at[index, 'y2_n'] = row['y2'] / height
# replace relative image paths with a Google Storage bucket path
df['set'] = 'UNASSIGNED'
df['gs_path'] = df['image'] + 'gs://bucket-name/path/to/upload'
# write CSV with columns expected by AutoML Vision
# the "none" columns are required for boxes defined by 2 vertices
df['none'] = ''
df.to_csv('/home/leigh/datasets/spaghetti/labeled/vott-csv-export/spaghetti_v1-normalized-export.csv',
columns=['set', 'image_path', 'label', 'x1_n', 'y1_n', 'none', 'none', 'x2_n', 'y2_n', 'none', 'none'],
index=False
)
有关更多信息,请参考准备您的培训数据。
上传数据
将数据上传到谷歌云存储桶。注意:如果您正在创建一个新的时段,AutoML Vision exports 在后面的步骤中要求目标时段在 us-central-1 地区。
- 新来 GCP 吗?在开始设置项目和认证之前,遵循中的步骤。
- 安装 gsutil
gsutil rsync -r /path/to/vott-csv-export gs://your-bucket-name/vott-csv-export/
将数据导入 AutoML Vision
- 在 GCP 的控制台中打开 AutoML 视觉数据集浏览器。
- 创建新的数据集。在导入选项卡中,从存储桶中选择您的 CSV 文件。

图片作者。
数据导入时休息一下!👏
在训练之前,对导入的数据进行全面检查,并验证标签是否正确。

3D 打印的“筏”是一次性的支撑结构。图片作者。
火车模型
AutoML 的价格体系是基于节点小时,与“挂钟”或运行时间不同。我的一个批评是,提前为培训工作定价需要一些额外的努力。
AutoML Vision 定价(美元价格如下所示)因功能而异,不同的定价表适用于:
- 云托管分类和对象检测—3.15 美元/节点小时,75.6 美元/ 24 小时
- 边缘(分类)-4.95 美元/节点小时,118.80 美元/ 24 小时
- 边缘(物体检测)——18.00 美元/节点小时,432 美元/ 24 小时
如果这些价格超出了您项目的预算,我将在未来的帖子中介绍我如何使用 TensorFlow 的对象检测 API 训练模型。关注或订阅我的简讯以获得出版通知。
对于这个特殊的问题(检测 3D 打印缺陷),我看到了使用我的数据集大小的推荐训练时间(24 节点小时)的合理结果。深入到单个标签,“喷嘴”检测的表现明显比其他标签差。

所有标签的指标。图片作者。

“喷嘴”标签的指标。图片作者。
左:所有标签的精度/召回曲线。右图:“喷嘴”的精度/召回曲线
经过更仔细的检查,我发现高的假阳性率显著影响了模型的精度分数。精度是真阳性/(真阳性+假阳性)之和。我很兴奋地发现了一些例子,在这些例子中,我没有在地面真实数据中标注喷嘴。
🤯即使我在第一次贴标签的过程中变得草率,指导模型已经足够好来捕捉这些错误。哇!如果我不得不手动标记这些数据的整体,它将充满错误。

我的模型自信地在这些图像中检测到“喷嘴”物体,由于人为错误标记地面真实数据,这些物体被评为“假阳性”。图片作者。
使用 TensorFlow.js 自动标注 VoTT🤖
下一节将向您展示如何使用自定义 TensorFlow.js 模型来建议具有 VoTT“主动学习”功能的边界框。
“主动学习”使用 TensorFlow.js 模型在帧上执行推理,应用非最大抑制,并为每个检测到的对象绘制最佳框建议。
导出 TensorFlow.js 模型
模型训练完成后,您可以在“测试和使用”选项卡中导出 TensorFlow.js 包。该模型将导出到一个存储桶中(目标桶必须在美国中部-1 地区)。

谷歌云自动视觉边缘导出。图片作者。

谷歌云自动视觉边缘导出。图片作者。
创建 classes.json 文件
我手动修复了这个。AutoML Vision Edge 导出新行分隔的标签文件。VoTT 要求的格式如下。标签索引必须从 1!
[{"id":1,"displayName":"nozzle"}, ... ]
修补 VoTT 以修复 TensorFlow 1.x -> 2.x 错误
VoTT 自带@tensorflow/tfjs 的 v1。AutoML Vision Edge 模型使用需要更新版本的操作系统(如 AddV2)。我用以下补丁修复了几个小问题:
- 模型需要 float32 输入
- 使用较新的 TF . image . nonmaxsupressionasync()fn
diff --git a/src/providers/activeLearning/objectDetection.ts b/src/providers/activeLearning/objectDetection.ts
index 196db45..a8dff06 100755
--- a/src/providers/activeLearning/objectDetection.ts
+++ b/src/providers/activeLearning/objectDetection.ts
@@ -151,6 +151,8 @@ export class ObjectDetection {
const batched = tf.tidy(() => {
if (!(img instanceof tf.Tensor)) {
img = tf.browser.fromPixels(img);
+ // model requires float32 input
+ img = tf.cast(img, 'float32');
}
// Reshape to a single-element batch so we can pass it to executeAsync.
return img.expandDims(0);
@@ -166,7 +168,8 @@ export class ObjectDetection {
const result = await this.model.executeAsync(batched) as tf.Tensor[];
const scores = result[0].dataSync() as Float32Array;
- const boxes = result[1].dataSync() as Float32Array;
+ // tf.image.nonMaxSepressionAsync() expects tf.Tensor as input
+ const boxes = result[1].dataSync()
// clean the webgl tensors
batched.dispose();
@@ -177,10 +180,8 @@ export class ObjectDetection {
const prevBackend = tf.getBackend();
// run post process in cpu
tf.setBackend("cpu");
- const indexTensor = tf.tidy(() => {
- const boxes2 = tf.tensor2d(boxes, [result[1].shape[1], result[1].shape[3]]);
- return tf.image.nonMaxSuppression(boxes2, maxScores, maxNumBoxes, 0.5, 0.5);
- });
+ const boxes2d = tf.tensor2d(boxes, [result[1].shape[0], result[1].shape[1]]);
+ const indexTensor = await tf.image.nonMaxSuppressionAsync(boxes2d, maxScores, maxNumBoxes, 0.5, 0.5);
const indexes = indexTensor.dataSync() as Float32Array;
indexTensor.dispose();
@@ -188,7 +189,9 @@ export class ObjectDetection {
// restore previous backend
tf.setBackend(prevBackend);
- return this.buildDetectedObjects(width, height, boxes, maxScores, indexes, classes);
+ // _.buildDetectedObjects expects Float32Array input
+ const fboxes = boxes as Float32Array
+ return this.buildDetectedObjects(width, height, fboxes, maxScores, indexes, classes);
}
自动包围盒建议✨
- 修补 VoTT 后运行
npm start - 在“主动学习”选项卡中,配置“模型路径”以指向您的 TensorFlow.js 导出。我建议启用“自动检测”功能,否则你必须手动按 ctrl/cmd+d 来对每一帧执行检测。

微软 VoTT 主动学习配置。图片作者。
包扎
您刚刚学习了如何将几个小时和几百美元用于自动边界框注释工作流。作为一个额外的奖励,指导模型可以适用于原型甚至是初始生产运行。我希望这能为你的下一个物体探测项目节省一点时间/精力!
与其他云产品相比,AutoML 产品价格昂贵——但它们远不如从零开始开发一个可比较的模型或甚至使用重量转移学习这样的资源密集型产品或。
你目前正在使用物体探测器解决问题吗?请在下面的评论中告诉我更多关于你的理念和方法。
订阅我的时事通讯@ bitsy.ai 获取更多关于 Raspberry Pi、Arduino 和其他小型设备的 ML 应用的技巧、教程和详细文章。我目前正在为 Octoprint 打造一个隐私优先的 3D 打印监控插件。
为《星际迷航》建立一个基于 BERT 的语义搜索系统
使用人工智能大胆搜索,就像以前没有人搜索过的那样,所有这些都在 30 分钟内完成,并且只需几行代码

改编自维基共享资源
如果你读了我的上一篇关于走向数据科学的文章,你会知道我是一个有点星际迷航的书呆子。只有一件事比《星际迷航》更让我喜欢,那就是用人工智能建造很酷的新东西。所以我想我应该再一次把这两者结合起来!
在本教程中,我们将构建自己的搜索引擎来搜索《星际迷航:下一代》中的所有内容。我们将使用纪娜,这是一个神经搜索框架,它使用深度学习来支持我们的 NLP 搜索,尽管如果我们想的话,我们可以很容易地将其用于图像、音频或视频搜索。
我们将涵盖:
- 基本设置
- 运行我们的应用程序的演示(是的,甚至在我们编码之前)
- 使用 cookiecutter 创建项目和样板代码
- 下载我们的星际迷航数据集
- 加载、索引和搜索我们的数据集
- 深入了解幕后
- 如果事情出错了该怎么办
如果你是人工智能或搜索的新手,不要担心。只要你对 Python 和命令行有所了解,你就没问题了。如果有帮助的话,把自己想象成少校数据科学。

通过 Giphy
尝试一下
在经历下载、配置和测试搜索引擎的麻烦之前,让我们先了解一下最终产品。在这种情况下,它与我们正在构建的内容完全相同,但使用了《南方公园》中的台词,而不是《星际迷航》:

通过 Jinabox
纪娜有一个预建的 Docker 图像,带有来自南方公园的索引数据。您可以使用以下命令运行它:
docker run -p 45678:45678 jinaai/hub.app.distilbert-southpark
在 Docker 启动并运行后,您可以开始搜索那些南方公园线。
用 Jinabox 查询
Jinabox 是一个简单的基于网络的神经搜索前端。您可以在本教程顶部的图形中看到它。
- 在浏览器中转至 jinabox
- 确保您将服务器端点设置为
[http://localhost:45678/api/search](http://localhost:45678/api/search) - 在搜索栏中键入一个短语,然后查看出现了哪些南方公园线路
注意:如果第一次超时,那是因为查询系统还在预热。几秒钟后重试!
用curl查询
或者,您可以打开您的 shell 并通过 RESTful API 检查结果。匹配结果存储在topkResults中。
curl --request POST -d '{"top_k": 10, "mode": "search", "data": ["text:hey, dude"]}' -H 'Content-Type: application/json' 'http://0.0.0.0:45678/api/search'
您将看到 JSON 格式的结果输出。每个结果看起来像:
现在回到运行 Docker 的终端,点击几次Ctrl-C(或者 Mac 上的Command-C)以确保你已经停止了一切。
交战!
现在你已经知道我们在构建什么了,让我们开始吧!
您将需要:
- Python 的基础知识
- 安装了 Python 3.7 或更高版本,以及
pip - Mac 或 Linux 电脑(纪娜目前不支持 Windows)
- 8gb 或更多的 RAM
克隆回购
让我们准备好行动所需的基本文件:
git clone git@github.com:alexcg1/my-first-jina-app.git
cd my-first-jina-app
运行 Cookiecutter

通过 Giphy
pip install -U cookiecutter
cookiecutter gh:jina-ai/cookiecutter-jina
我们使用 cookiecutter 创建一个基本的纪娜应用程序,让你不必做大量的输入和设置工作。
对于我们的 Star Trek 示例,使用以下设置:
project_name:Star Trekproject_slug:star_trek(默认值)task_type:nlpindex_type:stringspublic_port:65481(默认值)
对所有其他字段使用默认值即可。cookiecutter 完成后,让我们看看它创建的文件:
cd star_trek
ls
您应该会看到一堆文件:
app.py——主 Python 脚本,您在其中初始化并将数据传递到您的流中Dockerfile-让你启动一个 Docker 实例来运行你的应用flows/-保存流程的文件夹pods/-夹住你的豆荚的文件夹README.md-自动生成的自述文件requirements.txt-所需 Python 包的列表
在flows/文件夹中,我们可以看到index.yml和query.yml——它们定义了你的应用程序的索引和查询流程。
在pods/中,我们看到chunk.yml、craft.yml、doc.yml和encode.yml——这些 pod 是从流程中调用的,用于处理索引或查询数据。
稍后会有更多关于流量和 pod 的内容!
安装要求
在您的终端中运行以下命令,下载并安装所有必需的 Python 包:
pip install -r requirements.txt
下载数据集
我们的目标是当用户查询一个短语时,找出《星际迷航》中谁说了什么。来自 Kaggle 的星际迷航数据集包含了从星际迷航:原系列一直到星际迷航:企业号的所有剧本和个别角色台词。
我们在这个例子中只是使用了一个子集,包含了《星际迷航:下一代》中的角色和台词。这也已经从 JSON 转换为 CSV 格式,这更适合纪娜处理。
现在,让我们确保我们回到了基本文件夹,并通过运行以下命令下载数据集:
下载完成后,让我们回到star_trek目录,确保我们的数据集拥有我们想要的一切:
cd star_trek
head data/startrek_tng.csv
您应该看到由字符(如MCCOY)、分隔符(!)和字符说出的行(What about my age?)组成的输出:
BAILIFF!The prisoners will all stand.
BAILIFF!All present, stand and make respectful attention to honouredJudge.
BAILIFF!Before this gracious court now appear these prisoners to answer for the multiple and grievous savageries of their species. How plead you, criminal?
BAILIFF!Criminals keep silence!
BAILIFF!You will answer the charges, criminals.
BAILIFF!Criminal, you will read the charges to the court.
BAILIFF!All present, respectfully stand. Q
BAILIFF!This honourable court is adjourned. Stand respectfully. Q MCCOY!Hold it right there, boy.
MCCOY!What about my age?
注意:你的角色台词可能会有点不同。没关系!
加载数据
现在我们需要将startrek_tng.csv传递给app.py,这样我们就可以索引它。app.py开箱即用有点太简单了,所以我们来做些改动:
在编辑器中打开app.py并检查index功能,我们目前有:
如您所见,这仅索引了 3 个字符串。让我们用filepath参数加载我们的 Star Trek 文件。只需替换函数的最后一行:
索引更少的文档
当我们在这里时,让我们减少我们索引的文档数量,只是为了在我们测试时加快速度。我们不想花费大量的时间来索引,只是为了以后有问题!
在config功能上方的部分,让我们更改:
收件人:
这将使我们的测试速度提高 100 倍!一旦我们确认一切正常,我们就可以将它设置回50000来索引更多的数据集。
现在我们已经有了加载数据的代码,我们将开始编写我们的应用程序并运行我们的流程!流是我们的应用程序执行的不同任务,如索引或搜索数据。
索引
首先,我们需要为我们的文件建立一个索引。稍后使用查询流时,我们将搜索这个索引。
python app.py index
您的应用程序将在终端中显示大量输出,但是当您看到以下行时,您将知道它已经完成:
Flow@133216[S]:flow is closed and all resources should be released already, current build level is 0
第一次可能要花一点时间,因为纪娜需要下载语言模型和标记器来处理数据。你可以认为这些是支持搜索的神经网络背后的大脑。
搜索
要启动搜索模式运行:
python app.py search
过一会儿,您应该会看到终端停止滚动,并显示如下输出:
Flow@85144[S]:flow is started at 0.0.0.0:65481, you can now use client to send request!
⚠️一定要记下端口号。我们需要它来制作curl和 jinabox!在我们的例子中,我们假设它是65481,我们在下面的例子中使用它。如果您的端口号不同,请确保使用该端口号。
ℹ️ python app.py search不会弹出搜索界面——为此你需要通过curl、Jinabox 或另一个客户端进行连接。
用 Jinabox 搜索

Via Jinabox
- 在浏览器中转到 jinabox
- 确保您将服务器端点设置为
[http://localhost:65481/api/search](http://localhost:65481/api/search) - 在搜索栏中键入一个短语,看看会出现哪些星际迷航的台词
用 curl 搜索
curl --request POST -d '{"top_k": 10, "mode": "search", "data": ["text:picard to riker"]}' -H 'Content-Type: application/json' 'http://0.0.0.0:65481/api/search'
curl将会以 JSON 格式给出大量信息——不仅仅是您正在搜索的行,还有关于搜索及其返回的行的各种元数据。查找以"matchDoc"开头的行以找到匹配项,例如:
恭喜你!你刚刚建立了你自己的搜索引擎!
它实际上是如何工作的?
要更全面地了解什么是神经搜索以及它是如何工作的,请查看我以前的文章。纪娜本身只是构建神经搜索引擎的一种方式,它有几个重要的概念:flow和 Pods :
- 这个流程告诉纪娜要对数据集执行什么任务,比如索引或搜索。每个流都是由单独的豆荚构成的。
- 这些豆荚组成了流程,并告诉纪娜如何一步一步地执行每项任务,比如将文本分成块、索引等等。它们定义了我们在神经搜索中使用的实际神经网络,即像
distilbert-base-cased这样的语言模型。(我们可以在pods/encode.yml中看到)
流

途经纪娜 101
就像植物管理其分支的营养流和生长率一样,流管理一组豆荚的状态和环境,协调它们完成一项任务。无论一个 Pod 是远程的还是在 Docker 中运行的,一个流都控制着它们!
我们在app.py中定义流来索引和查询我们的 Star Trek 数据集中的内容。
在这种情况下,我们的流以 YAML 格式编写,并加载到app.py中:
真的就这么简单!或者,您可以在app.py本身中构建流,而无需在 YAML 中指定它们。
无论你处理的是文本、图形、声音还是视频,所有的数据集都需要被索引和查询,而且做每一件事的步骤(分块、矢量编码)或多或少都是相同的(即使你执行每一步的方式不同——这就是 pod 的用武之地!)
索引
每一股水流都有井,有流向它。不同的 Pod 沿着流程传递数据,一个 Pod 的输出成为另一个 Pod 的输入。以我们的索引流程为例:

通过纪娜仪表盘
如果你看一下startrek_tng.csv,你会发现它只是一个大的文本文件。我们的能量流将它加工成更适合纪娜的东西,由能量流中的圆荚体来处理。每个吊舱执行不同的任务。
您可以在flows/index.yml中看到以下窗格:
crafter-将文档分割成块encoder-将每个块编码成一个向量chunk_idx-建立组块索引doc_idx-存储文档内容join_all-加入chunk_idx和doc_idx路径
完整的文件实际上只是一个包含参数和一些设置的 pod 列表,位于文件的顶部:
幸运的是,YAML 是相当可读的。我经常感谢银河大鸟它不是克林贡语,或者更糟,XML!
- 前几行初始化流并启用日志服务器(我们在本教程中不使用)。
- 之后,我们可以看到 pod 列表,它们有自己的 YAML 路径和传递给每个 pod 的额外参数。
这是所有的豆荚吗?不完全是!我们总是有另一个舱在安静地工作——gateway舱。大多数时候我们可以安全地忽略它,因为它基本上为流程做了所有肮脏的编排工作。
搜索

经由纪娜仪表盘
在查询流中,我们有以下窗格:
chunk_seg-将用户查询分割成有意义的块tf_encode-将查询的每个单词编码成一个向量chunk_idx-为块建立索引,以便快速查找ranker-排序结果列表doc_idx-存储文档内容
flows/query.yml再次给出了一些设置选项,并按使用顺序列出了面板:
当我们建立索引时,我们把文档分成几块来建立索引。对于查询,我们做同样的事情,但是这次文档是用户输入的查询,而不是 Star Trek 数据集。我们将使用许多相同的 pod,但是需要记住一些不同之处。总体而言:
- Index 有一个并行处理文档和块索引的双路径设计,这加快了消息传递的速度
- 查询只有一个管道
深入研究flows/query.yml,我们可以看到它比flows/index.yml多了一个吊舱和一些参数:
rest_api:true——使用纪娜的 REST API,允许像 jinabox 和curl这样的客户端连接port_expose: $JINA_PORT-连接纪娜 API 的端口polling: all-将polling设置为all可确保所有工人轮询消息reducing_yaml_path: _merge_topk_chunks-使用_merge_topk_chunks减少所有复制品的结果ranker:-按相关性排列结果
纪娜如何知道它应该是索引还是搜索?在我们的 RESTful API 中,我们在 JSON 主体中设置了mode字段,并将请求发送到相应的 API:
api/index-{"mode": "index"}api/search-{"mode": "search"}
分离舱

途经纪娜 101
正如我们上面讨论的,流程告诉纪娜要执行什么任务,并且由 pod 组成。一个 Pod 告诉纪娜如何执行那个任务(也就是说,工作的正确工具是什么)。荚和流都是在 YAML 写的。
让我们从查看索引流中的一个 Pod 开始,flows/index.yml。不要看第一个 Pod crafter,让我们看看更简单的encoder:
正如我们在上面的代码中看到的,encoder Pod 的 YAML 文件存储在pods/encode.yml中,看起来像:
Pods 使用内置的TransformerTorchEncoder作为它的执行器。每个 Pod 根据其任务有不同的执行器,一个执行器代表一个算法,在本例中是编码。执行者根据被编码的内容而不同。对于视频或音频,你可以使用不同的。with字段指定传递给TransformerTorchEncoder的参数。
pooling_strategy-将单词嵌入合并到组块嵌入的策略model_name-我们正在使用的型号名称max_length-截断标记化序列的最大长度
当 Pod 运行时,数据从前一个 Pod 传入,TransformerTorchEncoder对数据进行编码,Pod 将数据传递给流程中的下一个 Pod。
如果你想更深入地了解 pod、Flows、Executors 和其他任何东西,你可以参考纪娜 101 。
解决纷争

通过 Giphy
找不到模块
确保在开始之前运行pip install -r requirements.txt,并确保您的tmp分区中有大量 RAM/交换空间和空间(参见以下问题)。这可能需要一段时间,因为有许多先决条件需要安装。
如果此错误不断出现,请查看输出到终端上的错误,尝试找到哪个模块丢失了,然后运行:
pip install <module_name>
我的电脑挂起
机器学习需要大量资源,如果您的机器挂起,这通常是因为内存不足。要解决这个问题,如果你使用 Linux,尝试创建一个交换文件。在 macOS 上这不是一个问题,因为它会自动分配交换空间。
ERROR: Could not install packages due to an EnvironmentError: [Errno 28] No space left on device
这通常是由于你的/tmp分区空间不足,所以你需要增加它的大小。
command not found
对于此错误,您需要在您的系统上安装相关的软件包。在 Ubuntu 中,这可以通过以下方式实现:
sudo apt-get install <package_name>
恭喜你!我们做到了!

通过 Giphy
在本教程中,您已经学习了:
- 如何安装纪娜神经搜索框架
- 如何从文件中加载和索引文本数据
- 如何用
curl和 Jinabox 查询数据 - 纪娜流量和豆荚背后的本质
- 如果一切都出错了,该怎么办
现在你已经大致了解了事情是如何工作的,你可以尝试一些更多的示例教程来构建图像或视频搜索,或者继续关注我们基于你的 Star Trek 应用的下一组教程。
有关于星际迷航和/或神经搜索的教程的想法吗?我的 commbadge 现在出故障了,但是你可以在这篇文章上留下评论或笔记让我消化!
Alex C-G 是纪娜人工智能的开源传道者,也是一个超级星际迷航极客。
建立一个伯特科学工具包变压器
BERT 可以在许多 NLP 任务中为您提供最先进的结果,并且只需要几行代码。

作为变形人的伯特(图片由作者提供)
介绍
在 NLP 中获得最先进的结果曾经是一项痛苦的任务。你必须设计各种管道,做词性标注,将这些链接到知识库,将你的单词词汇化,并构建疯狂的解析器。现在把你的任务扔给伯特,你可能会做得很好。本教程的目的是用 BERT 和 Sci-kit Learn 建立一个句子级分类的最小示例。我不会详细讨论什么是 BERT 或者它是如何工作的。我只想用最少的工作量向你展示如何通过 Sci-kit Learn 轻松使用这个模型。在这篇博文的最后,我们将有一个世界级的 Ekman 情绪检测模型和 BERT 打包到一个模块化的 Sci-kit Learn transformer 中,我们可以通过任何现有的 Sci-kit 管道在一行代码中即插即用!
为什么是伯特?
机器学习的很大一部分是找出什么样的好特性适合你的任务。如果你有代表你的问题空间的特征,那么学习就是小菜一碟!困难在于很难,或者至少传统上很难,为一项语言任务创造好的特性。每项任务都有自己的特色,并且需要做大量的工作来确定模型中应该包含哪些信息以及如何包含。
BERT 是一个基于大量文本的深度转换模型。大量的预训练与模型架构和一些巧妙的训练技巧相结合,使得 BERT 能够学习 NLP 任务的“好”特性。在这里,我们将利用所有这些优秀的工作,并使用 PyTorch transformer 库来创建一个可重用的特征提取器。我们将能够把这个特征提取器插入任何 Sci-kit 学习模型。关于 BERT 如何工作的更多信息,请阅读 Jay Alamar 关于 BERT 和使用 BERT 的精彩博文。
为 Sci-kit Learn 创建 BERT 特征提取器
对于我的大多数项目,我试图从简单开始,看看我能用 Sci-kit Learn 走多远。我个人喜欢使用他们的 pipeline API ,其中任何给定的模型都是由转换器和估算器组成的。每当像 BERT 这样的新方法出现时,我都会为它建立一个转换器或估计器。然后,我可以轻松地将它合并到我现有的任何管道中,而无需做太多工作。因此,让我们为 BERT 创建一个 Sci-kit 学习转换器,我们可以即插即用任何估计器。
这个转换器应该将字符串列表映射到与该字符串相关联的相应 BERT 特征。所以我们的类型签名应该是列表[str**→火炬。漂浮者
使用拥抱面部变形库有三个主要步骤来进行这种变形:
- 将字符串分解成整数编码的标记
- 对编码的记号运行 BERT 以获得单词和句子的 BERT 表示
- 将 BERT 表示的部分提取为我们模型所需的特征。
标记化
标记化只有两行代码。我们定义我们想要的记号赋予器,然后运行 encode_plus 方法,该方法允许我们设置像最大大小和是否包含特殊字符这样的事情。
tokenizer = BertTokenizer.from_pretrained("bert-base-uncased")
tokenized_dict = tokenizer.encode_plus(
"hi my name is nicolas",
add_special_tokens=True,
max_length=5
)
该函数的输出是:
{'overflowing_tokens': [2003, 9473],
'num_truncated_tokens': 2,
'special_tokens_mask': [1, 0, 0, 0, 1],
'input_ids': [101, 7632, 2026, 2171, 102],
'token_type_ids': [0, 0, 0, 0, 0]}
您会注意到,我们将最大序列长度设置为 5,在我提供的输入中只有 5 个单词,但它显示有两个截断的标记。这是因为我们将 add_special_tokens 设置为 True。对于 BERT 模型,这意味着添加一个[CLS]“class”标记和一个[SEP]“separator”标记。这两个标记构成了五个单词的最大值,所以我们最终删除了两个单词。这只是需要注意的一点。有了这个字典,我们只需要 input_ids 字段,它保存我们将传递给 BERT 模型的标记化单词的整数编码。
CLS 令牌保存嵌入的句子,分隔符令牌用于告诉 BERT 下一个句子将出现。对于我们的基本句子分类任务,我们将使用 CLS 嵌入作为我们的特征集。
模型
下一步是使用 BERT 分类器生成句子嵌入。transformer 库再次为我们完成了大部分工作。我们可以创建一个简单的 BERT 模型,并对我们的符号化输出运行预测。
bert_model = BertModel.from_pretrained("bert-base-uncased")tokenized_text = torch.tensor(tokenized_dict["input_ids"])with torch.no_grad():
embeddings = bert_model(torch.tensor(tokenized_text.unsqueeze(0)))
请注意,BERT 模型需要接受一个形式为[batch_size,sentence_length]的张量,这意味着我们需要取消一维矩阵的排队。
还要注意我们在这里如何使用 torch.no_grad() 。我第一次处理大量样本时忘记了这样做,服务器内存不足。所以,记得在运行预测之前关闭梯度,否则你会保存太多的梯度信息,并有一个糟糕的时间。默认情况下,返回的元组有两个字段,第一个是大小为:
批量 × 句子长度 × 嵌入维度
对于基本的 BERT 模型和我们的例子,这最终是[1,5,768]。第一个张量包含我们对分类感兴趣的嵌入。第二个张量保存汇集的输出。在训练下一个句子时,汇集的输出是通过线性层和双曲正切激活函数后的[CLS]嵌入。对于本教程,我们可以忽略它。
提取嵌入内容
要完成我们的 BERT 特征提取器,我们需要做的最后一件事是将最终的嵌入组合成一个用于分类的向量。对于大多数分类任务来说,只需抓住[CLS]标记的嵌入就可以做得很好。我们可以用这个函数来实现:
get_cls = lambda x: x[0][:, 0, :].squeeze()
这将获取嵌入和汇集输出的元组,获取嵌入并获取所有批次,仅第一个 CLS 令牌,以及所有嵌入的神经元。
但是,也许你想变得花哨,并使用其他功能。假设您想要使用所有嵌入进行预测,我们可以使用不同的函数将它们连接在一起:
flatten_embed = lambda x: torch.flatten(x[0])
这将返回一个由序列中每个标记的嵌入组成的大向量。通过定义在最终层上操作的函数,我们可以更灵活地使用用于下游分类的特征。这在 Sci-kit 学习转换器的上下文中更有意义。
把所有的放在一起
这三个基本的片段就是我们为一个句子获取嵌入所需要的全部。为了方便地与 Sci-kit 学习方法联系起来,我们希望对大量句子进行操作。我们可以通过建立一个 Sci-kit 学习变压器来做到这一点(我们正在做一个变压器变压器!).这样我们就可以传递一个列表给它,调用 transform 函数,我们的分类器就可以开始学习了。我们创建了一个名为 BertTransformer 的新类,它继承了 BaseEstimator 和 TransformerMixin,并将我们在上面工作的代码作为标记化步骤和预测步骤。
BERT Sci-Kit 学习转换器代码
这个转换器使用我们之前在第 25–39 行编写的所有标记化代码,以及第 41–46 行的预测和提取代码。我们唯一要做的另一件事是用一个转换方法将所有句子连接起来,这个方法使用一个单一的列表理解来标记,然后将所有句子嵌入到一个列表中,这发生在第 51-52 行。
现在,我们可以使用 BERT 的所有功能和经典 Sci-kit Learn 模型的所有简单性来制作超级简单的管道!
数据集
对于我们的数据,我们将使用 8 字形情感分析:文本中的情感数据集。这个数据集有 4 万条推文,分为 13 种不同的情绪状态。我只是将数据加载到 pandas 数据框架中,并将数据随机分为 70%的训练集、15%的验证集和 15%的测试集。
figure8_df = pd.read_csv("text_emotion.csv")split = np.random.choice(
["train", "val", "test"],
size=figure8_df.shape[0],
p=[.7, .15, .15]
)
figure8_df["split"] = splitx_train = figure8_df[figure8_df["split"] == "train"]
y_train = x_train["sentiment"]
训练模型
训练模型非常简单。我们只是用一个转换器和一个估计器来定义一个流水线。
bert_transformer = BertTransformer(tokenizer, bert_model)
classifier = svm.LinearSVC(C=1.0, class_weight="balanced")model = Pipeline(
[
("vectorizer", bert_transformer),
("classifier", classifier),
]
)model.fit(x_train["content"], y_train)
就这样,我们结束了。这将训练一个关于伯特 CLS 嵌入的 SVM,但是如果我们也想要一些经典的 TF-IDF 特性呢?这也很简单!我们只需制作一个特征联合,并将其传递给我们的分类器。
from sklearn.feature_extraction.text import (
CountVectorizer, TfidfTransformer
)
tf_idf = Pipeline([
("vect", CountVectorizer()),
("tfidf", TfidfTransformer())
])
model = Pipeline([
("union", FeatureUnion(transformer_list=[
("bert", bert_transformer),
("tf_idf", tf_idf)
])),
("classifier", classifier),
])
我喜欢使用管道的原因是它们非常灵活,我可以轻松地创建这些可塑的组件。从现在到永远,我们可以用一行代码将 BERT 特性添加到任何 Sci-kit 学习模型中!
结果
运行上述模型后,我们在验证集上获得了相当好的结果。有些课程做得很糟糕,但大多数都非常出色。看一看。在我们的验证集上,对许多类有几乎完美的分类。这个模型只使用了来自伯特变换器的 CLS 嵌入和一个 SVM,它在所有主要标签上得到几乎完美的预测!这太疯狂了。

这些结果出乎意料的好,所以我看了看混淆矩阵,看起来的热情和的乐趣都被归类为的快乐,对此我 100%同意。看起来真正有问题的孩子是空虚的和解脱的,但是如果我完全诚实的话,我甚至不知道那些情绪是什么🤷♂:所以我要把它标记为成功。

结论
Sci-kit 学习变形金刚超级方便。现在,我们可以轻松地将基于 BERT 的特性插入到任何我们想要的 Sci-kit 学习模型中!这只是定义我们的 BERT 模型并将其作为一个特性化步骤添加到管道中的问题。Sci-kit Learn 会处理剩下的事情。尝试将这些功能整合到您的旧型号中,看看它是否能提高性能。对我来说是的。
用 XLNet 构建一个双向文本生成器
使用置换语言建模以新的方式生成文本

当前基于变形金刚的模型,像 GPT-2 甚至 GPT-3,在文本生成(根据之前的单词序列预测下一个可能的单词)的任务中表现出令人难以置信的成就。这些模型可以创建长的、有创意的和有凝聚力的文本,但通常它们只能在一个方向上生成文本,从左到右。我想知道是否有一种方法可以双向生成文本,并有一些开始短语(例如“文本生成很酷”)来看看围绕它会展开什么故事。解决方案是:由于使用了输入序列分解顺序的所有排列,这个模型可以帮助生成任何方向的文本。
在本文中我们不会详细研究 XLNet 的内部原理(精彩的简要说明你可以在这里找到)。相反,我们将立即开始试验:我们将使用 XLNet 在屏蔽字预测方面做一点练习,尝试实现 top-K 双向生成,然后实现一种结合波束搜索和 top-K 采样的更有效的方法。
在文章的最后,我们将获得一个能够根据起始短语(以粗体突出显示)创建此类文本的生成器:
跟进我最初的想法: 文字生成很酷 !它非常适合创建博客标题等。您将需要 Word 2013
安装所需的模块
我们开始吧。我们将在 Google Collab Notebook(带 GPU 环境)中进行我们所有的实验,这是通过这个链接可用的,所以我们需要安装的唯一模块是优秀的变形金刚库。这个库提供了一个简单的 XLNet 接口,以及许多其他基于变压器的模型。
!pip install transformers
使用 XLNet 预测屏蔽词的示例
XLNet 的一个优点是,这个模型在兼顾之前上下文的同时,可以完美应对几个相关屏蔽词的预测。比如我会在文中提到我给了你三个苹果,然后通过给模型喂一句带假面词的句子让模型告诉我现在谁拥有一些苹果:“
在我们开始与模型通信之前,我们需要加载它,并加载一个标记器,将输入的文本处理成模型可以理解的数字形式。在基本形式中,标记化是将文本分割成单词或子单词,然后将它们转换成 id。每个模型都要求文本以特定的方式进行标记。XLNet 使用了 SentencePiece 方法。你可以在链接了解更多关于令牌化过程的信息。
此外,我们需要添加一个填充文本,以帮助 XLNet 的简短文本是由阿曼俄罗斯提出的。
预测每个
输出:
predicted word: <mask> 0
word and logits You -9.070054054260254
word and logits I -10.822368621826172
word and logits We -12.820359230041504
word and logits Now -14.133552551269531
word and logits They -14.863320350646973
predicted word: <mask> 1
word and logits three -23.045528411865234
word and logits the -24.3369083404541
word and logits these -25.59902000427246
word and logits two -25.809444427490234
word and logits your -25.947147369384766
Top-k 双向生成
现在,当我们知道如何用 XLNet 预测屏蔽词时,是时候创建一个 top-k 双向文本生成器了。它的工作原理很简单。我们将创建一个循环,在每次迭代中,该模型将预测起始短语右侧或左侧屏蔽词的前 k 个标记。之后,我们将 topK 中的随机令牌添加到起始短语中,并重复迭代 n 次。
输出:
• 1 1 User reviews and says:? The text generation is cool for me to see and the font size seems right
没什么印象。有很多重复,整篇文章看起来毫无意义。但是我们会找到更好的解决办法。
Top-k-beam 双向文本生成
正如我们所看到的,这个模型仍然很难从右向左生成文本。我们经常会得到一个不太适合上下文的单词,这会导致下一个更不适合的单词。结果,生成的文本变得不连贯。
我们可以通过不是在起始短语的每一边生成单词,而是通过创建一定数量的单词序列束并选择一定长度的最有可能的一束来增加找到相连单词序列的机会。
因此,我们得到了 top-k 采样和波束搜索的某种组合。由此产生的方法的原理如图所示。

图片由 Rostyslav Neskorozhenyi 用 draw.io 创建
双向生成过程包括 n 次迭代。为了更好地理解,我将每次迭代分为四个步骤:
- 在第一步中,我们获得一个起始短语,并在其左侧从右到左生成一定数量的一定长度的束(在束搜索的每个阶段,我们使用 top-K 采样来选择下一个候选标记)。
- 在第二步中,我们从前 K 个最可能的波束中随机选取一个波束,并将其添加到起始短语中。
- 产生的新短语作为第三步的开始短语,在第三步中,我们在新开始短语的右侧生成一定数量的波束。
- 在第四步中,我们从第三步中获得的前 k 个波束中随机选取一个波束,并将该波束添加到新的起始短语中。产生的短语作为下一次迭代的起点。
我希望这个描述足够清楚,这个图表可以帮助你理解它。主要是,根据我的实验,这种方法在大多数情况下允许你双向生成相当连贯的文本。
让我们用代码实现这个方法。首先,我们将创建一个函数,该函数将获取标记化的起始句、一系列标记候选项及其概率,并在右侧或左侧生成下 n 个可能的标记候选项序列。我们将迭代地使用这个函数,因此从上一次迭代中生成的令牌序列将作为下一次迭代的输入。
现在我们将创建 beam_gen 函数,该函数将使用由 candidates_gen 提出的令牌候选者生成给定长度(深度)的令牌波束列表。
beam_gen 函数将返回按概率排序的最终波束列表。
让我们将所有部分聚集在一个 bi_gen 函数中。 bi_gen 将能够从左到右(参数方向 = '右')、从右到左(参数方向 = '左')或两个方向(参数方向 = '两者')生成文本
如果两个方向都被选择,发生器将以如下方式工作:在左侧产生 n_tokens ,之后在右侧产生 n 个 tokens,然后在左侧产生 n 个 tokens,依此类推。它将重复多少次,保存在迭代参数中。
我们将在 first_sample_size 参数中单独指示波束搜索第一阶段的候选数目。该数目可以高于下一阶段中的候选数目(在变量 sample_size 中指定),因为为第一令牌获得足够的候选是重要的,所有后续序列都将基于第一令牌。根据我的观察,这种方法增加了生成连贯的和合理的可能的记号序列的可能性。
我们将使用高温度参数来降低模型在其顶部令牌选择中的置信度。这使得生成更加多样化,并且不会被最有可能重复的记号序列卡住。
最后,我们将尝试我们的双向文本生成器,以“文本生成很酷”开始。
结果文本:
Follow the trend: Graphic design is cool, **text generation** is cool, data manipulation and algorithms are cool, etc.
结论
它也开始看起来有点像我们正在进入一个主要由人工智能控制的新世界,基于其长期操纵、管理和适应我们日常生活的能力。
之前的整个段落都是由我们新的文本生成器生成的。这篇课文很有说服力,不是吗?因此,请接受我的祝贺。我们几乎创造了同类产品中的第一个基于变压器的双向文本生成器。虽然它仍然会犯很多错误,但它可以用来创造很多有趣的故事,这些故事将围绕你脑海中出现的任何短语发展。
在 BigQuery 中建立分类模型——面向电子商务的机器学习
如何使用 BigQuery ML 在 Google 云平台上部署机器学习模型

1-描述 :
贵公司的数据分析师团队将一个电子商务网站的 Google Analytics 日志导出到 BigQuery 中,并创建了一个包含所有原始电子商务访问者会话数据的新表,供我研究。利用这些数据,我将尝试回答几个问题。
问题 1: 在访问我们网站的所有访问者中,有百分之多少的人进行了购买?
问题 2: 有多少访问者在随后的访问中购买了该网站?
问题 3: 典型的电子商务客户会浏览但不会购买直到下次访问的一些原因是什么?
问题 4: 在 BigQuery 中创建一个机器学习模型,预测新用户未来是否有可能购买。识别这些高价值用户可以帮助营销团队针对他们开展特别促销和广告活动,以确保他们在访问您的电子商务网站时进行比较。
2-构建机器学习模型的说明:
1-选择要素并创建您的训练数据集。
2-创建一个 BigQuery 数据集来存储模型。
3-选择 BQML 模型类型并指定选项。
4-评估模型性能。
5-通过特征工程提高模型性能。
预测哪些新访客会回来购买。
3-定义:
- Google BigQuery 是一个可扩展的、全面管理的、经济高效的交互式专用查询系统,用于分析结构化和半结构化嵌套数据。
- BigQuery ML 使用户能够使用标准的 SQL 查询在 BigQuery 中创建和执行机器学习模型。BigQuery ML 通过让 SQL 从业者使用现有的 SQL 工具和技能来构建模型,使机器学习民主化。BigQuery ML 通过消除移动数据的需要提高了开发速度。
- Google Analytics 是 Google 提供的网络分析服务,用于跟踪和报告网站流量,也用于跟踪网站活动,如会话持续时间、每次会话的页面数、跳出率等。使用该网站的个人信息,以及流量来源的信息。
- 有一个新的可用的电子商务数据集,其中有数百万条关于谷歌商品商店的谷歌分析记录加载到 BigQuery 中。在本实验中,您将使用这些数据运行一些典型的查询,企业希望了解他们客户的购买习惯。
— — — — — — — — — — — — — — — — — — — — — — — — — —
注:此处 所有代码均可用 。
设置您的环境
- 登录谷歌云平台

谷歌云控制台
- 从导航菜单打开 BigQuery 控制台

- 通过此链接访问谷歌分析数据集

谷歌商品商店的谷歌分析数据集样本
有关数据集的更多信息:

BigQuery ML 中的机器学习模型
问题 1:

结果:2.69%
问题 2:
以下是前 5 名产品的结果:


问题 3:

分析结果,我们可以看到(11873 / 741721) = 1.6%的总访问者会从网站返回并购买。这包括在第一次会议上购买,然后回来再次购买的访问者子集。
典型的电子商务客户会浏览但不会购买,直到后来访问的一些原因是什么?
虽然没有一个正确的答案,但一个普遍的原因是在最终做出购买决定之前,在不同的电子商务网站之间进行比较。对于奢侈品来说,这是很常见的,顾客在做出决定之前需要进行大量的前期研究和比较(比如购买汽车),但对于该网站上的商品(t 恤、配饰等)来说,这种情况在较小程度上也是如此。
在网络营销的世界里,根据这些未来客户的首次访问特征来识别和营销他们,将会提高转换率,减少向竞争对手网站的流失。
确定一个目标
现在,您将在 BigQuery 中创建一个机器学习模型,以预测新用户将来是否有可能购买。识别这些高价值用户可以帮助您的营销团队针对他们开展特别促销和广告活动,以确保他们在访问您的电子商务网站时进行比较。
1-选择特征并创建您的训练数据集。

Google Analytics 捕捉了关于用户访问该电子商务网站的各种维度和衡量标准。在这里浏览字段的完整列表,然后预览演示数据集以找到有用的功能,帮助机器学习模型理解访问者第一次访问你的网站的数据与他们是否会回来购买之间的关系。
我决定测试这两个字段是否是我的分类模型的良好输入:
- totals.bounces (访问者是否立即离开网站)
- totals.timeOnSite (访问者在我们网站停留的时间)
问题:只使用以上两个字段有什么风险?
回答:机器学习的好坏只取决于输入其中的训练数据。如果模型没有足够的信息来确定和学习输入特征和标签之间的关系(在这种情况下,访问者是否在未来购买),那么我们将不会有一个准确的模型。虽然只在这两个领域训练模型是一个开始,但我们将看看它们是否足以产生一个准确的模型。
问题:哪些字段是输入要素和标注?
答:输入为弹跳和现场时间。标签是将 _ 购买 _ 返回 _ 访问。
问题:访客第一次会话后知道哪两个字段?
回答: 弹回和 time_on_site 在一个访客的第一次会话后就知道了。
问题:哪个领域是以后才知道的?
回答:****will _ buy _ on _ return _ visit第一次访问之后就不知道了。同样,你预测的是返回你的网站并购买的用户子集。因为你不知道未来的预测时间,你不能肯定地说,是否会有新的游客回来购买。建立一个 ML 模型的价值是基于他们第一次会议收集的数据得到未来购买的可能性。
2-创建一个大查询数据集来存储模型。

3-选择一个 BQML 模型类型并指定选项。
既然我们已经选择了初始特性,我们现在准备在 BigQuery 中创建您的第一个 ML 模型。

注意:在机器学习中有许多额外的模型类型(如神经网络和决策树),可以使用像 TensorFlow 这样的库来获得。在撰写本文时,BQML 支持上面列出的三种。
你应该选择哪种型号?

由于我们将访问者分为“将来会购买”或“将来不会购买”,我们将在分类模型中使用 logistic_reg。
以下查询创建一个模型并指定模型选项。运行此查询来训练模型:
注意:我们无法在训练期间将所有可用数据输入模型,因为我们需要保存一些看不见的数据点用于模型评估和测试。为了实现这一点,添加一个 WHERE 子句条件,用于在 12 个月的数据集中仅对前 9 个月的会话数据进行筛选和训练。

我们可以看到上面强调的任何机器学习模型的四个主要参数:
模型类型、损失函数类型、训练数据和评估数据集。
4-评估模型性能。
对于 ML 中的分类问题,我们希望最小化误报率(预测用户会退货并购买而他们没有)和最大化真报率(预测用户会退货并购买而他们确实有)。
这种关系可以用 ROC(受试者操作特征)曲线来表示,如下图所示,我们试图最大化曲线下面积或 AUC:


分类模型的 ROC 曲线
5-利用特征工程提高模型性能。
正如前面所暗示的,数据集中有更多的要素可以帮助模型更好地理解访问者的第一次访问与他们在后续访问中购买的可能性之间的关系。
我们将添加一些新功能,并创建第二个机器学习模型,名为classification _ model _ 2:
- 访问者在第一次访问时在结账过程中走了多远。
- 访问者来自哪里(流量来源:有机搜索,参考网站等..).
- 设备类别(手机、平板电脑、台式机)。
- 地理信息(国家)。
通过运行以下查询创建第二个模型:
6-预测哪些新访客会回来购买。

分类模型 2 的 RUC 曲线
接下来,您将编写一个查询来预测哪些新访问者会回来购物。
下面的预测查询使用改进的分类模型来预测首次访问 Google 商品商店的用户在以后的访问中购买商品的概率:
我们的模型现在输出对 2017 年 7 月电子商务会议的预测。我们可以看到三个新添加的字段:
- predicted _ will _ buy _ on _ return _ visit:模型是否认为访问者以后会购买(1 =是)
- predicted _ will _ buy _ on _ return _ visit _ probs . label:表示是/否的二元分类器
- predicted _ will _ buy _ on _ return _ visit . prob:模型对其预测的置信度(1 = 100%)
结论:
- 在前 6%的首次到访者中(按预测概率降序排列),超过 6%的人会在以后的访问中进行购买。
- 这些用户代表了在以后的访问中进行购买的所有首次访问者的近 50%。
- 总体而言,只有 0.7%的首次访客会在以后的访问中进行购买。
- 与瞄准所有人相比,瞄准前 6%的首次营销投资回报率提高了 9 倍!
— — —— — — — — — — — — — — — — — — — — — — — — — —
参考资料:
1-https://cloud.google.com/bigquery-ml/docs/bigqueryml-intro
2-Qwiklabs.com
模式识别和机器学习。
构建用于对象检测的自定义开放图像数据集
注意:我们还在博客上发布了自定义开放图片。如何打开计算机视觉数据的海洋,即开放的图像数据集。
我们很高兴地宣布与开放图像数据集的集成,以及封装开放图像数据集子域的两个新公共数据集的发布:车辆物体检测和贝类物体检测。
在本帖中,我们将介绍如何创建您自己的自定义开放图像数据集。
车辆和贝类只是开放影像数据集广阔景观的一个小窗口,旨在提供可使用开放影像构建的数据集的小示例。

开放图像数据集中的大量子域。我们如何让它变得易于处理?
关于打开的图像
Open Images 是 Google 在 CC BY 4.0 许可下发布的开源计算机视觉检测数据集。数据集包含大量数据,涵盖图像分类、对象检测,以及跨越数百万图像和边界框注释的视觉关系检测。开放图像数据集为计算机视觉研究提供了广泛而大规模的基础事实。
为什么要创建自定义开放图像数据集?
创建自定义开放影像数据集的用途有很多:
- 尝试创建自定义对象检测器
- 在收集和标记您自己的数据之前,评估检测类似物体的可行性
- 扩充和现有的训练集
- 训练自定义检测器模型检查点,以应用于数据较少的更适合的自定义任务
- 当然,为了好玩😁
请记住,这些都是免费的、有标签的计算机视觉数据,存在于知识共享空间中。
打开图像查询工具
整个开放的影像数据集大约有 1tb…要下载原始数据,您需要运行一些命令,例如:
aws s3 --no-sign-request sync s3://open-images-dataset/train [target_dir/train] (513GB)
aws s3 --no-sign-request sync s3://open-images-dataset/validation [target_dir/validation] (12GB)
aws s3 --no-sign-request sync s3://open-images-dataset/test [target_dir/test] (36GB)
幸运的是,开源社区已经创建了一些工具,使得查询开放图像数据库变得简单易用。为了构建我们的自定义开放图像数据集,我们使用了 OIDv4_ToolKit 。OIDv4_ToolKit 使您可以轻松地查询 OID 的子域,并限制到特定的类。只需一行 python 代码,您就可以指定所需图像的类别和数量。它有边框和所有的东西!
从公开图片下载 200 只带标签的龙虾:
python3 main.py downloader -y --classes Lobster --Dataset Lobster --type_csv train --image_IsGroupOf 0 --n_threads 4 --limit 200

从开放图像下载带注释的螃蟹
转换开放图像注释格式
我们很高兴地宣布,我们现在支持 Roboflow 的开放图像数据格式。当您下载 Open Images 数据时,您将收到一个大型的难处理的 CSV 文件,其中包含整个数据集中的所有注释以及一个类别映射。您还将收到.txt文件,为每幅图像添加注释,这要容易处理得多。我们支持这两种格式,但是我推荐使用.txt文件。
为了将您的注释转换成任何格式,您只需使用 Roboflow 创建一个免费帐户,并将您的图像拖到数据上传流程中。

上传打开的图像数据以转换到 Roboflow
创建数据集后,您将能够以任何想要的格式导出。举几个例子,您将能够:
- 将打开的图像转换为 Coco Json
- 将开放图像转换为 Pascal Voc XML
- 转换打开的图像以创建 ML Json
- 将开放图像转换为 YOLO 暗网
- 将打开的图像转换为亚马逊鼠尾草生成器
- 将打开的图像转换为 Amazon Rekognition
- 将打开的图像转换为 TFRecord
- 将开放图像转换为 YOLO 暗网
- 将打开的图像转换为 YOLOv5 Pytorch
然后你就可以用你喜欢的任何型号来训练你的自定义探测器了!在写这篇文章的时候,我主要是在训练 YOLOv5 探测器。
您还可以将新的自定义数据集与另一个数据集合并以增加覆盖范围。
介绍 Roboflow 的公共自定义开放图像数据集
我们创建了两个公共自定义开放图像数据集,并在我们的公共数据集之间共享:车辆目标检测和贝类目标检测。

贝类对象检测类分布

贝类物体检测示例图像

车辆物体检测类分布

车辆物体检测示例图像
它们已经在我们的公共计算机视觉数据集上公开使用。
结论
现在,您知道了如何使用完全免费的计算机视觉数据和开源工具来构建自定义的开放图像数据集。
我们期待看到您用开放图像构建的东西!🚀
如果您对扩大这些数据集或创建自己的数据集感兴趣,请给我们写信!
从头开始构建具有所需深度的自定义 ResNetV2
本教程将帮助您从头开始构建一个具有任意深度/层数的 ResNet 模型

ResNet 一直是我最喜欢的架构之一,我已经多次使用其跳过连接的核心思想。它现在已经相当老了,因为 2015 年& 2016 年 ResNetV1 (用于图像识别的深度残差学习) ResNetV2 (深度残差网络中的身份映射)都出现了,但今天它的核心概念仍被广泛使用。所以你一定在想…为什么要在 2020 年出这个教程。
本教程有两个主要原因:
- 构建任意深度的 ResNetV2,而不仅仅是 ResNet50、ResNet101 或 ResNet152(包含在 keras 应用程序中)
- Tensorflow 2.xx 的使用
本教程分为两部分。第 1 部分将简要讨论 ResNet,第 2 部分将重点讨论编码部分。请记住,本教程的主要目标是展示从头开始构建具有任意深度/层数的 ResNet 模型的编码部分。
第 1 部分:ResNet 简介
任何深度学习网络的最大问题之一是消失,爆炸梯度。这限制了我们深入网络。如果你不知道或不想更新,请参考视频。
所以问题是 ResNet 如何解决这个问题?
我会试着用简单的话来表达。ResNet 的核心思想是基于跳过连接,也就是说,它允许从一个层获取激活,并将其提供给未来的层(可以更深)。考虑梯度消失的问题,当我们深入时,一些神经元将不会有任何贡献,因为它们的权重已经显著降低。但现在,如果我们从早期层激活,并在激活前添加到当前层,现在它肯定会有所贡献。
参考这段视频,从数学角度更好地理解它
现在,不浪费时间,让我们转向编码部分
第 2 部分:编码
注意:我已经发布了包含所有代码的回购协议,可以在这里找到。
- 首先,我们必须创建一个剩余块,它是 ResNet 的构建块。它被用作跳过连接器。ResNetV2 带来了一个微小的修改,与 V1 相反,首先使用卷积层,然后批量归一化。
在网络内部,有时不会首先使用卷积层,因此我们必须使用 if-else 循环。
2.接下来是添加层。出于同样的目的,我们将使用 Keras functional API
让我们一行一行来
→在第 7 行,我们接受输入
→第 10 行用于在分成两个路径之前创建卷积层。这里,我们使用的是之前创建的同一个剩余块。
→从第 13 行到第 55 行,用于创建剩余单元的堆栈。让我们更详细地讨论这个问题。在第 10 行之后,网络被分成两部分&稍后添加。现在在第一部分中执行三个操作,
批量定额→激活→ Conv。
这个过程重复三次,最后相加。从 ResNet 的角度来看,在分裂之后,在一个子网中,我们执行一些操作(如上所述),并将其激活添加到我们分裂的状态中。所以你可以看到我们跳过了三层。
为什么是三层?这取决于你的直觉。它可以是两个或四个或任何东西。我发现用三层效果最好&作者也建议用两层或三层。
是时候深入研究代码了…稍微…😃
→第 13 行开始在 for 循环中追加剩余块的堆栈。(这里跳过所需层的一个简单技巧是在该范围内循环开始)
→第 30–44 行用于在执行分割后,在一个子网中添加卷积层。
这里你可以看到我已经用了三个剩余块。为什么是三个?因为我跳过了三次激活
→第 45–53 行:执行分割后,第二个子网络必须是卷积层,可以跳过,稍后添加。
→第 54 行是所有魔法发生的地方:)。这里我们添加我们的两个子网络。
3.最后一部分是连接一个 完全连接到 层网络之上。
这部分你可以随意定制。

深度为 11 的模型架构示例
一些需要注意的关键事项
- 我写了一个注释“深度应该是 9n+2 ”,因为这里我跳过了三个激活,为了匹配分割前后的张量形状,深度必须根据公式选择。
- 在步幅和内核大小上做了大量的调整来匹配张量的形状。我建议你在纸上写下一个循环,看看所有的调整,更彻底地理解它。
- 不要被跳过的连接器或残留的块所迷惑。它们之间的连接如下:在执行分割之后,创建了两条路径。路径一将具有三层或三个 残余块 ,路径二将具有一层或一个 残余块 (现在该块与分割前相同)。现在,来自路径二的这个剩余块将被带到路径一,并在激活之前被添加。因此,该块跳过或跳过了三个块&,从而成为一个 跳过连接器。
第 3 部分:结尾注释和一些附加内容
我建议你浏览一下我的 GitHub repo 'ResNet-builder,因为它包含了很多我认为可能超出了本博客范围的 API。这个博客仅限于建立一个 ResNet 网络。但是要构建一个完整的 ResNet 系统,我们将需要更多的功能,如数据加载器、推理生成器、可视化模型性能等。我已经包含了所有这些 API。
回购还支持多种配置来构建模型。
我试图让 API 尽可能直观,尽管如果你有任何困惑,你可以通过 Linkedin 联系我。
用 Python 构建定制的对象检测模型
使用 Detecto 简化计算机视觉,Detecto 是构建在 PyTorch 之上的 Python 包

本教程的最终结果!
如今,机器学习和计算机视觉都很热门。我们都看过关于自动驾驶汽车和面部识别的新闻,并且可能会想象构建我们自己的计算机视觉模型有多酷。然而,想要打入这个领域并不容易,尤其是没有很强的数学背景。如果您只想尝试一些小东西,像 PyTorch 和 TensorFlow 这样的库可能会很难学。
在本教程中,我将向任何人介绍一种简单的方法,只需几行代码就可以构建功能齐全的对象检测模型。更具体地说,我们将使用 Detecto ,这是一个构建在 PyTorch 之上的 Python 包,它使这个过程变得简单,并对所有级别的程序员开放。
[## alankbi/detecto
Detecto 是一个 Python 包,它允许你用…
github.com](https://github.com/alankbi/detecto)
快速简单的例子
为了演示使用 Detecto 有多简单,让我们加载一个预先训练好的模型,并对下图进行推理:

来源:维基百科
首先,使用 pip 下载 Detecto 包:
pip3 install detecto
然后,将上面的图像保存为“fruit.jpg ”,并在与图像相同的文件夹中创建一个 Python 文件。在 Python 文件中,编写以下 5 行代码:
运行此文件后(如果您的计算机上没有支持 CUDA 的 GPU,可能需要几秒钟;稍后将详细介绍),您应该会看到类似于下图的内容:

从原始图像中裁剪以获得更好的视觉效果
厉害!我们只用了 5 行代码就做到了这一切。以下是我们在每个案例中所做的:
- 进口探测器模块
- 读入图像
- 初始化预训练模型
- 在我们的图像上生成了顶部预测
- 绘制了我们的预测
Detecto 使用 PyTorch 的模型动物园中速度更快的 R-CNN ResNet-50 FPN ,它能够检测大约 80 种不同的对象,如动物、车辆、厨房用具等。然而,如果你想检测自定义对象,如可口可乐与百事可乐罐,或斑马与长颈鹿?
您会很高兴地知道,在自定义数据集上训练 Detecto 模型也同样容易;同样,您所需要的只是 5 行代码,以及一个现有的数据集或一些花在标记图像上的时间。
构建自定义数据集
在本教程中,我们将从头开始构建自己的数据集。我建议你也这样做,但如果你想跳过这一步,你可以在这里下载一个样本数据集(修改自斯坦福的狗数据集)。
对于我们的数据集,我们将训练我们的模型来检测来自 RoboSub 比赛的水下外星人、蝙蝠和女巫,如下所示:


外星人、蝙蝠和女巫(从左到右)
理想情况下,每个类至少需要 100 张图片。好的一面是你可以在每张图像中有多个物体,所以如果每张图像包含你想要检测的每一类物体,理论上你可以得到总共 100 张图像。此外,如果您有视频素材,Detecto 可以轻松地将该素材分割成图像,然后用于数据集:
上面的代码取“video.mp4”中的每第 4 帧,并将其作为 JPEG 文件保存在“frames”文件夹中。
生成训练数据集后,您应该有一个类似于以下内容的文件夹:
images/
| image0.jpg
| image1.jpg
| image2.jpg
| ...
如果您愿意,还可以有第二个包含一组验证图像的文件夹。
现在到了耗时的部分:贴标签。Detecto 支持 PASCAL VOC 格式,在这种格式中,XML 文件包含图像中每个对象的标签和位置数据。要创建这些 XML 文件,您可以使用如下的开源工具:
pip3 install labelImg # Download LabelImg using pip
labelImg # Launch the application
您现在应该会看到一个弹出窗口。在左侧,单击“打开目录”按钮,并选择要标记的图像文件夹。如果一切正常,您应该会看到类似这样的内容:

要绘制边界框,请点按左侧菜单栏中的图标(或使用键盘快捷键“w”)。然后,您可以在对象周围拖出一个框,并写入/选择一个标签:

当您完成标记图像时,使用 CTRL+S 或 CMD+S 来保存您的 XML 文件(为了简单和快速,您可以只使用它们自动填充的默认文件位置和名称)。要标记下一幅图像,请点按“下一幅图像”(或使用键盘快捷键“d”)。
完成整个数据集后,您的文件夹应该如下所示:
images/
| image0.jpg
| image0.xml
| image1.jpg
| image1.xml
| ...
我们几乎准备好开始训练我们的对象检测模型了!
访问 GPU
首先,检查你的电脑是否有支持 CUDA 的 GPU 。由于深度学习使用大量的处理能力,在典型的 CPU 上进行训练可能会非常慢。值得庆幸的是,大多数现代深度学习框架,如 PyTorch 和 Tensorflow,都可以在 GPU 上运行,从而使事情变得更快。确保您已经下载了 PyTorch(如果您安装了 Detecto,应该已经有了),然后运行下面两行代码:
如果打印出来是真的,太好了!你可以跳到下一部分。如果打印错误,不要担心。按照以下步骤创建一个谷歌合作实验室笔记本,这是一个带有免费可用 GPU 的在线编码环境。对于本教程,您将只是在 Google Drive 文件夹中工作,而不是在您的计算机上。
- 登录 Google Drive
- 创建一个名为“检测教程”的文件夹,并导航到这个文件夹
- 将您的训练图像(和/或验证图像)上传到此文件夹
- 右键单击,转到“更多”,然后单击“谷歌合作实验室”:

创建您的 Google Colab 笔记本
您现在应该会看到这样的界面:

Google Colab 笔记本环境。点击了解更多关于环境的信息。
5.给你的笔记本起个名字,然后进入编辑->笔记本设置->硬件加速器,选择 GPU
6.键入以下代码以“挂载”您的驱动器,将目录更改为当前文件夹,并安装 Detecto:
为了确保一切正常,您可以创建一个新的代码单元并键入!ls来检查您是否在正确的目录中。
训练一个定制模型
最后,我们现在可以在自定义数据集上训练模型了!正如所承诺的,这是容易的部分。它只需要 4 行代码:
让我们再次分解我们对每行代码所做的工作:
- 进口探测器模块
- 从“images”文件夹创建了一个数据集(包含我们的 JPEG 和 XML 文件)
- 初始化一个模型来检测我们的自定义对象(外星人、蝙蝠和女巫)
- 在数据集上训练我们的模型
根据数据集的大小,这可能需要 10 分钟到 1 个多小时的时间,因此请确保您的程序在完成上述语句后不会立即退出(即,您使用的是 Jupyter/Colab 笔记本,它在活动时会保留状态)。
使用训练好的模型
现在你有了一个训练好的模型,让我们在一些图像上测试它。要从文件路径中读取图像,可以使用detecto.utils模块中的read_image函数(也可以使用上面创建的数据集中的图像):
如您所见,模型的predict方法返回一个由 3 个元素组成的元组:标签、框和分数。在上面的例子中,模型预测到一个外星人(labels[0])在坐标【569,204,1003,658】(boxes[0])处,置信度为 0.995 ( scores[0])。
根据这些预测,我们可以使用detecto.visualize模块绘制结果。例如:
使用您收到的图像和预测运行上面的代码,应该会产生如下所示的结果:

如果您有视频,您可以在其上运行对象检测:
这将接收一个名为“input.mp4”的视频文件,并生成一个包含给定模型预测的“output.avi”文件。如果你用 VLC 或其他视频播放器打开这个文件,你应该会看到一些有希望的结果!

视频检测器产生的输出短片
最后,您可以从文件中保存和加载模型,允许您保存您的进度并在以后返回:
高级用法
你会很高兴地知道 Detecto 不仅仅局限于 5 行代码。比方说,这个模型没有你希望的那么好。我们可以通过用 torchvision transforms 扩充我们的数据集并定义一个定制的 DataLoader 来提高它的性能:
这段代码对数据集中的图像应用随机水平翻转和饱和度效果,增加了数据的多样性。然后我们用batch_size=2定义一个 DataLoader 对象;我们将把它传递给model.fit而不是数据集,告诉我们的模型分批训练 2 张图像,而不是默认的 1 张。
如果您之前创建了一个单独的验证数据集,现在是在培训期间加载它的时候了。通过提供一个验证数据集,fit方法返回每个时期的损失列表,如果是verbose=True,那么它也会在训练过程中打印出来。下面的代码块演示了这一点,并自定义了其他几个培训参数:
所得到的损失图应该或多或少地减少:

为了更加灵活和控制你的模型,你可以完全绕过 Detectomodel.get_internal_model方法返回所使用的底层 torchvision 模型,您可以随意修改。
结论
在本教程中,我们展示了计算机视觉和物体检测并不具有挑战性。你需要的只是一点时间和耐心来创建一个带标签的数据集。
如果您有兴趣进一步探索,请查看 GitHub 上的 Detecto 或访问文档以获得更多教程和用例!
[## alankbi/detecto
Detecto 是一个 Python 包,它允许你用…
github.com](https://github.com/alankbi/detecto)
为二进制分类模型选择构建一个 Dash Web 应用程序
现实世界中的数据科学
自动管理机器学习视觉诊断的汇编

作者图片
这篇文章展示了我开发的分类器 dash web 应用工具的一个用例,该工具用于自动管理二进制分类问题的机器学习视觉诊断汇编。这款网络应用程序提高了现有从业者的效率,增强了他们在建模选择过程中的交互性。此外,崭露头角的数据科学家和机器学习工程师可以获得一个额外的好处,即磨练他们对常见分类评估评分指标和基准的直觉。
灵感
这篇文章和网络应用的灵感来自于 Yellowbrick 项目的问题“创建多个模型分数的一目了然的表示,以便我可以轻松地比较和对比不同的模型实例。”这种工具也有助于分析师在进入超参数调整阶段之前获得对算法选择的直觉。
利用 Dash by Plotly 的交互性,我扩展了这个概念,以合并现有的黄砖分类可视化,命名为 visualizers。在上面的标题图像中可以找到我们将在此用例中使用的内容的快照。
用例
本例中使用的数据是来自 UCI 机器学习知识库的‘信用卡客户数据集的默认值’。该数据集由台湾的客户违约付款组成。我们将使用它对分类的二元结果(可信或不可信的客户端)的模型性能进行评分。
数据集包括一个二元变量“默认付款”,作为响应变量。有 23 个预测变量,包括人口统计信息、过去付款历史、账单金额等。
数据已经被清理了,所以我们可以进入有趣的部分——建模!
用于模型选择的模型
在深入研究该工具之前,提供该工具在工作流中最有用的位置的上下文会很有帮助。我是 Arun Kumar 等人提供的模型选择三重框架的粉丝
这三个阶段是:

Benjamin Bengfort 演讲的幻灯片,“用 Scikit-Yellowbrick 可视化模型选择:开发可视化工具简介”
我们的用例位于“算法选择”阶段,因为我们将使用 web 应用程序来缩小搜索空间,而不是执行详尽的搜索。
那么,为什么要用仪表板来分析模型性能呢? 因为视觉诊断对于建立更有效的机器学习的直觉至关重要!
..仪表板的交互性有助于获得更加无缝的 UX 体验,因为您可以避免在笔记本电脑上查看型号性能输出时看似无限的滚动。如果有大量支持数据可视化,这种滚动密集型练习尤其如此。
装置
首先,克隆 Github 存储库
git clone [https://github.com/taylorplumer/classifiers-dash](https://github.com/taylorplumer/classifiers-dash)
创建虚拟环境(推荐)后,可以使用以下命令安装依赖项:
pip install -r requirements.txt
配置
config.py 将是最需要动手操作的文件,因为我们将在这里为手头的问题进行必要的配置。
在此使用案例中,我们将探索各种流行的二元分类算法,这些算法可用作 sklearn 估计器,如高斯朴素贝叶斯、逻辑回归、随机森林和梯度增强。
使用的黄砖可视化工具来自现有分类可视化工具的套件。
*请注意,需要导入克隆的 repo 中默认情况下未提供的任何 sklearn 评估程序和/或 yellowbrick 可视化程序。
数据处理
在项目的根目录中运行以下命令来设置数据和图像。目标变量应该是 csv 文件中的第一列,然后是许多预测变量。
python3 process_data.py credit.csv
保存的输出如下:
- sk learn . metrics . classification _ report 中每个模型的模型分数的 csv 文件
- 黄砖可视化保存为 png 文件。
仪表板应用
在描述组件之前,让我们运行 Dash Plotly web 应用程序。
python3 app.py
该应用程序将在本地运行于 http://127.0.0.1:8050/ (或您选择的任何端口)。我们直播了!
部署到 Heroku 的演示可在以下地址查看:https://classifier-dash-app.herokuapp.com/
该演示不适用于移动设备,因此请在桌面/PC 上查看完整功能。
web 应用程序由三个组件组成:
- 一个下拉菜单,允许用户查看带有训练数据的模型,这些数据可以是原样的,也可以是合成的上采样数据,以解决任何类别不平衡的问题。
- 默认情况下没有上采样
- utils 目录中的 upsample.py 模块可以提供有关上采样方法的详细信息。
2.包含每个 sklearn 模型的精确度、召回率和 f1 分数的热图,以及以下内容:
- 宏观平均值:平均每个标签的未加权平均值
- 加权平均值:平均每个标签的支持加权平均值
3.将鼠标悬停在 sklearn 模型的热图中的关联行上时,将出现 matplotlib 图的模型特定图像,这些图像是利用 Yellowbrick 分类可视化工具填充的。
- ROCAUC:绘制接收器工作特性和曲线下面积的图形。
- 精确度-召回曲线:绘制不同概率阈值的精确度和召回率。
- 分类报告:可视化的分类报告,以热图的形式显示每个类别的精确度、召回率和 F1 值。
- 混淆矩阵:类别对混淆矩阵的热图视图。
它告诉我们什么?
我们可以清楚地看到,高斯朴素贝叶斯模型表现不佳(至少在给定参数集的情况下)。由于类别不平衡,逻辑回归模型是有偏差的,并且对于阳性病例在精确度和召回率上表现不佳。我们看到,当向上采样应用于训练数据时,它的性能更好,但它仍然没有达到类似于随机森林和梯度增强模型所代表的集成方法的性能。
可视化暗示集成方法表现更好,但是我们能更好地区分哪一族集成方法更好吗——bagging 还是 boosting?这可以通过编辑 config.py 文件合并额外的树和 AdaBoost 分类器来完成。
初始诊断还有助于告知我们如何分配时间向前发展,即查看决策树中的特征重要性,然后在这些算法中进行更详尽的超参数调整。
机器学习是一个迭代的探索过程,所以我们可能会在模型选择的三个阶段之间来回穿梭。
后续步骤
如果你对 process_data.py 和 app.py 文件感兴趣,那么我鼓励你去看看 github repo !
如果您有任何问题和/或想法要使该工具更加有效,请提出问题。编码快乐!
[1]库马尔、阿伦&麦肯、罗伯特&诺顿、杰弗里&帕特尔、吉格内什。模型选择管理系统:高级分析的下一个前沿(2016),ACM SIGMOD 记录。44.17–22.10.1145/2935694.2935698.
使用 Dash 构建一个仪表板来跟踪冠状病毒的传播

全球冠状病毒(新冠肺炎)确诊、康复和死亡病例的实时视图
更新:仪表板自从这篇帖子后变化很大, 看看吧!

上个月我发表了四篇帖子,和大家分享我使用matplotlib的经验。得益于对给定图上元素的完全控制,matplotlib被视为数据可视化的基本 python 库,并被许多其他库(如seaborn和pandas)用作绘图模块。这也是为什么我认为学习matplotlib是成为数据科学从业者必不可少的一部分,这有助于建立对数据可视化工具背后逻辑的深入理解。
然而,巨大的灵活性伴随着错综复杂的层次和复杂的语法。使用matplotlib制作一个可发布的情节通常会令人望而生畏。换句话说,matplotlib不应该是我们唯一的数据可视化工具,我们需要在我们的工具箱中始终配备备选方案来处理不断发展的需求。
当需要效率、互动和基于网络的可视化时,[plotly](https://plot.ly/graphing-libraries/)和[dash](https://dash.plot.ly/introduction)是必须学习的工具。这些工具的美妙之处在于,我们不需要掌握 JavaScript、CSS 和 HTML 来制作交互式 web 可视化,因为这两种工具已经为我们处理好了。它们用 JavaScript(例如 React.js、Plotly.js 和 d3.js)将我们联系起来,使图形反应灵敏而且美观。我们需要提供的只是纯 python 环境下的简单代码。
在这篇文章中,我将在抽象的层面上剖析一个仪表板的代码,我建立这个仪表板是为了跟踪最近爆发的冠状病毒(新冠肺炎/2019-nCoV)的传播。从这个仪表板,你可以实时了解全球冠状病毒病例的数量,包括确诊、痊愈和死亡病例,以及它们在世界地图上的分布。
像往常一样,你可以从我的 Github 访问所有需要的数据和 jupyter 笔记本。由于它仍在积极开发中,本文中使用的版本可能与您下载的版本不同。然而,本文的主要框架还是一样的。此外,请随时提供您的建议或帮助,使这个仪表板更加有用和准确。
仪表板是实现一个或多个目标所需的最重要信息的可视化显示;整合并排列在单个屏幕上,以便可以一目了然地监控信息
-斯蒂芬·诺什
框架
为了帮助你快速理解代码(可以从 app.py 中找到代码),我先声明一下它们背后的逻辑。一般来说,通过dash构建这个 dashboard 应用程序的框架(即我的思考过程)遵循:数据准备- > Dashboard 布局确定- >内容生成和插入,尽管你可能会在代码中发现第三部分发生在第二部分之前。那是 Python 阅读代码的方式,不是我们。记住这个框架,让我们深入研究代码。
数据收集和清理
许多来源为跟踪冠状病毒的传播提供了实时数据(如在 GitHub 上搜索“冠状病毒”,有 231 个储存库,图 1)。至于我的仪表板,我从两个来源(即约翰霍普金斯 CSSE 和丁香园)收集数据,他们在那里为这次突发公共事件保存了及时准确的病例数。因为这部分的代码非常简单,所以我在这里只对关键点做简单的说明。

图 1 | Github 上关于冠状病毒的知识库
首先,在这个阶段,我每天手动下载并检查这两个来源的数据,并将其存储在 Excel 数据表中。随着紧急情况的发生,Excel 文件中的工作表数量也在增加。我使用了pandas.ExcelFile()函数(你需要安装xlrd库来使用这个函数)将工作表作为独立的数据帧导入,并存储在一个字典对象中(即dfs)。因此,我可以通过使用字典的键(即keyList)来访问任意给定日期的数据。
读入 excel 数据表并将数据存储在字典中
第二,由于我们将在全球地图上制作散点图,以显示冠状病毒病例的分布,每个位置都应分配有坐标(即纬度和经度)。这里我使用了由 OpenCageGeocode 提供的服务来调用坐标。由于使用限制(即每天 2500 个 API 请求),重复调用每个工作表中每个位置的坐标是不可行的。我们只需要调用最新日期(即dfs[keyList[0]])的数据坐标,并在地图上绘制最新数据。
使用 OpenCageGeocode 调用坐标
仪表板组件和布局
由于它是一个基于 web 的应用程序,因此不可避免地要处理布局的 HTML 结构。不要慌,不是我们自己写 HTML,dash给我们提供了dash-html-components库来处理。我们基本上只需要使用 Python 结构组成布局。请注意,布局设计有时会非常令人沮丧,但是,我们将在这个仪表板中坚持使用非常基本的布局。
首先,我们需要了解html.Div()。您可以将它视为一个层次树结构中内容的容器/部分。如图 2 所示,仪表板中有四个容器(实际上应该是五个,包括脚注)。具体来说,在标题容器中,它有一个标题(即html.H4())和两个段落(即html.P())组件。对于号牌容器,它有四个子容器(即html.Div()),每个子容器由一个段落(即html.P())和一个标题(即html.H3())组成。简单吧?我相信您现在可以找出代码中剩余的容器了。

图 2 |布局图
在html.Div(id, style={}, children=[])中有三个参数,其中id是可选的,如果你不想使用css文件(css文件是一个用于格式化网页内容的级联样式表文件)来样式化子内容。简单来说,通常在你的应用程序文件夹(也就是我们这里的dash-2019-coronavirus文件夹)里面,会有一个assets文件夹,里面包含了css文件,用来指定应用程序的格式。您指定一个style(例如,边距、字体和颜色等。)和id在css文件中,如果你想在应用布局中使用这个样式,而不是每次想使用相同的样式时都要在html.Div()内重复添加style={},只需要在html.Div()内分配相同的id即可。因此dash知道如何使用assets文件夹中的css文件中相应的style来样式化html.Div()容器中的子内容。
例如,从图 3 中可以看到,我在html.Div()容器中指定了一个id=”number-plate”(右面板第 409 行),相应地,在css文件(左面板)的第 736、740 和 764 行,我为与这个id相关的内容设置了不同的字体大小,以不同的屏幕尺寸显示(例如桌面或平板电脑)。因此,当用户在一个小屏幕上打开应用程序时,dash知道对html.P()元素中的字体使用 1.5 雷姆,对html.H3()中的字体使用 3 雷姆(‘雷姆’是相对于根 em 设置的单位,为了不使你进入睡眠状态,我们暂时跳过这一点)。除了这个,我主要用 python 代码设计组件,因为你可以在每个容器中找到style={}。


图 3 |与 html 的应用程序(左)和 python 代码相关联的 css 文件。Div()牌照部分(右)
我们需要知道的最后一件事是,在每个 **html.Div()** 容器中,样式设置为 **‘display’:‘inline-block’** ,它的子元素按照从左到右、从上到下的顺序填充那个容器中的空白空间。例如,在号牌容器(图 2)中,当前四个号牌的宽度分别设置为屏幕全宽的 24.4%(即style={‘width’:‘24.4%’},图 3,左侧面板,第 413、420、427 和 434 行)。因此,他们首先从左到右填满一行中的所有空白空间。假设现在你有一个同样宽度的第五个号码牌,它将自动放在同一个容器中第二行的开头。
要成为一个实用的房子,一旦我们完成了建造,接下来的事情就是把家具搬进房子里。
内容生成和插入
从图 4 中可以看出,我们为图形组件构造了子容器(即三个散点图和地图)。每个子容器都有一个名为dcc.Graph()的子组件。这个函数来自dash_core_components库,可以用来渲染任何 plot-powered 数据可视化,作为figure参数传递。换句话说,我们使用plotly制作一个漂亮的图形,并将其传递给dcc.Graph()并且dash知道如何处理该图形,就是这样。

图 4 |内容插入代码
如果您熟悉matplotlib背后的语法逻辑,您会发现plotly 图形对象(图 5)的语法也很容易理解。它们基本遵循相同的逻辑。我们首先通过调用fig = go.Figure()实例化一个空画布。然后加上trace(类似于matplotlib中axes的概念)。在plotly中,我们可以通过figure.update_layout()定制图表中的几乎所有元素。

图 5 |第一个散点图的代码
在 Heroku 中运行应用程序和部署
要在本地运行应用程序,只需在包含所有其他必需文件(即 assets/、data.xlsx 等)的文件夹中键入python app.py。).将http站点复制并粘贴到您的首选浏览器中,如果一切正常,您将看到该应用程序。
Running on [http://127.0.0.1:8050/](http://127.0.0.1:8050/)
Debugger PIN: 707-347-654
* Serving Flask app "app" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: on
相反,如果您想要公开共享您的应用程序,我们需要将它部署在服务器上。我个人发现 Heroku 是一个非常用户友好的选项,并提供了分步教程,dash 也提供了教程用于在 Heroku 中部署。有一点需要注意,我用conda create为我的应用程序创建了一个虚拟环境,而不是像dash教程中所说的那样使用virtualenv。
这里有一些链接和帖子,我在学习如何构建这个 Dash 应用程序时发现很有用:
- 用 plotly 绘制图形的多种方法
- 学习布局
- 学习编写 HTML 和 CSS 代码
- https://dev center . heroku . com/articles/getting-started-with-python # deploy-the-app
- https://radumas.info/blog/tutorial/2017/08/10/codeday.html
- https://Timothy renner . github . io/data science/2017/08/08/finding-Bigfoot-with-dash-part-1 . html
- https://medium . com/a-r-g-o/using-plot Lys-dash-to-deliver-public-sector-decision-support-dashboards-AC 863 fa 829 FB
和往常一样,我欢迎反馈、建设性的批评以及听到关于您的数据科学项目的信息。你可以在 Linkedin 上找到我,现在也可以在我的网站上找到我。
使用 Python Django、React 和 Docker 构建完全生产就绪的机器学习应用程序
使用 Django、PostgreSQL、React、Redux 和 Docker 构建生产级机器学习应用程序的完整分步指南

维克多·加西亚在 Unsplash 上拍摄的照片
先决条件
熟悉 Python、JavaScript、HTML、CSS 和一些基本的 Linux 命令。虽然我会尽我所能解释一切,但如果你在理解任何概念上有困难,请参考 Django、React、Docker 的官方文档,或任何其他必要的文档。
您需要在系统上安装 Python、Node、Postgres 和 Docker。Python 和 Node 分别带有它们默认的包管理器,即 pip 和 npm。我将在本文中使用这些包管理器,但是也可以随意使用其他适合您的包管理器。对于本文,我使用了 Python 3.7.4、Node 12.16.2、Postgres 12.3 和 Docker 19.03.12。Docker 是作为 Docker 桌面版安装的,它与 docker-compose 版本 1.26.2 预打包在一起。
我使用 VS Code 作为我的编辑器,因为这是一个免费的编辑器,具有许多功能和内置的终端,对于我们的用例来说非常方便。同样,请随意使用您选择的编辑器。
对于这个项目,正如您稍后将看到的,我们将创建 REST APIs。为了测试我们创建的 API,您需要安装 Postman。你可以从这里得到。
我们要建造什么?
后端— Django,Django REST 框架,PostgresSQL
我们将使用 Django REST 框架创建一个简单的机器学习应用程序,该应用程序根据样本花的特征(即萼片和花瓣的尺寸,即长度和宽度)来预测样本花的种类。我们已经在之前的文章中详细介绍了这一点。请熟悉一下那篇文章。我们将在这里使用相同的 Django 应用程序,并根据需要进行一些修改。在上一篇文章中,Django 应用程序与一个 SQLite 数据库相连接。然而,对于本文,我们将使用 Postgres 作为我们的数据库,因为 Postgres 更适合生产构建。Django 附带了一个很棒的管理仪表板。通过管理仪表板,我们可以将用户注册到我们的应用程序中,然后用户可以与我们的机器学习应用程序进行交互以进行预测。因此,我们的 Django 应用程序将服务于我们的后端和管理任务。
前端—反应
一旦用户被创建,他们将能够登录到一个门户——前端,并通过 REST APIs 与我们在后端运行的机器学习模型进行交互。用户将能够执行两件事情:
- 进行预测——用户将能够提供样本鸢尾花数据,然后按下按钮进行预测。一旦用户点击按钮上的 enter,用户定义的虹膜数据将通过 POST API 请求发送到后端。后端将处理这些数据,并根据集成到后端的经过训练的机器学习模型进行预测。预测的鸢尾花种类将会立即发送回前端的用户。
- 在前端更改他们的密码,因为该密码最初将由管理员通过管理仪表板用默认密码设置。
我们的应用程序——Docker 的生产版本
Docker 部分是可选的。如果你只想知道如何集成 Django 和 React 来创建一个简单但健壮的机器学习应用程序,你可以跳过本文中的这一部分。
我们使用 docker 的原因不仅是因为这几乎是生产应用程序的标准,而且正如您将看到的,它允许将我们开发的所有工作无缝集成到一个独立于平台的 docker 工作流中,并允许使用简单的 docker 命令使部署更加容易,而不是使用多个命令运行单个应用程序。我们还将把 Nginx 添加到我们的 docker 工作流中,这将允许我们在 Docker 容器中运行 Django 和 React 应用程序。
创建我们的后端
创建一个本地 Python 环境并安装必要的包
确保您的系统中安装了 Python 3.7 +。如果可能的话,查看官方 Python 下载部分。
创建一个名为“ DockerDjangoReactProject 的空项目文件夹。打开终端,导航到这个文件夹,键入'代码。',
D:\Projects\DockerDjangoReactProject> code .
然后回车。这将打开 VS 代码,并将这个文件夹设置为项目/工作文件夹。
我们将首先创建一个本地 python 环境,在这个环境中存储我们的后端应用程序所需的所有 python 包。创建 Python 环境有几种不同的方法。这里我们将使用' virtualenv '方法。首先,确保在 Python 的基础安装中安装了' virtualenv '包。如果没有,通过执行“ pip install virtualenv ”进行安装。
D:\Projects\DockerDjangoReactProject> pip install virtualenv
接下来,使用' virtualenv '创建本地 python 环境,如下所示。同样,您可能需要根据需要在下面加上前缀‘python 3-m’。
D:\Projects\DockerDjangoReactProject> virtualenv localPythonEnv
使用'localPythonEnv \ Scripts \ activate'激活您的 python 环境,如下所示。注意我用的是 windows,Linux 和 Mac 上的等效命令是'source localPythonEnv/bin/activate '。一旦环境被激活,你就不需要在任何 python 命令前加上前缀‘python 3-m’。
D:\Projects\DockerDjangoReactProject> localPythonEnv\Scripts\activate
(localPythonEnv) D:\Projects\DockerDjangoReactProject>
在我们的项目文件夹中创建一个 requirements.txt 文件,该文件包含我们项目所需的所有 Python 包的以下信息。您可以省略下面的版本号来获取最新的软件包:
Django==3.1
djangorestframework==3.11.1
django-rest-auth==0.9.5
django-cors-headers==3.5.0
psycopg2-binary==2.8.5
pandas==1.1.1
scikit-learn==0.23.2
joblib==0.16.0
gunicorn==20.0.4
在项目文件夹中,执行下面的命令,在我们的本地 Python 环境中安装所有这些包。
(localPythonEnv) D:\Projects\DockerDjangoReactProject> pip install -r requirements.txt
创建一个新的 Django 项目和 mainapp
在我们的 DockerDjangoReactProject 文件夹中创建一个名为 backend 的新文件夹。
(localPythonEnv) D:\Projects\DockerDjangoReactProject> mkdir backend
(localPythonEnv) D:\Projects\DockerDjangoReactProject>cd backend
通过运行下面的命令,在后端文件夹中创建一个新的 Django 项目。我们称我们的 Django 项目为 mainapp。
(localPythonEnv) D:\Projects\DockerDjangoReactProject\backend> django-admin startproject mainapp
默认情况下,当 Django 创建一个项目时,它会在项目文件夹中创建一个与项目同名的应用程序。
D:\PROJECTS\DOCKERDJANGOREACTPROJECT\BACKEND
└───mainapp
└───mainapp
这就是为什么我们从一开始就把我们的应用程序叫做 mainapp,这样当我们进入包含其他应用程序的项目文件夹时,我们就知道哪个是主应用程序。现在将外部的 mainapp 文件夹重命名为“ django_app ”。
最后,后端文件夹中的文件夹结构应该如下所示:
D:\PROJECTS\DOCKERDJANGOREACTPROJECT\BACKEND
└───django_app
│ manage.py
│
└───mainapp
asgi.py
settings.py
urls.py
wsgi.py
__init__.py
创建一个新的 Django 预测应用程序(不像以前那样是默认的 mainapp)
从命令行导航到 django_app 文件夹
(localPythonEnv) D:\Projects\DockerDjangoReactProject\backend>cd django_app
并通过执行以下操作创建一个新的 Django 应用程序。
(localPythonEnv) D:\Projects\DockerDjangoReactProject\backend\django_app>django-admin startapp prediction
您会看到一个新的应用程序与' mainapp '并排创建。
D:\PROJECTS\DOCKERDJANGOREACTPROJECT\BACKEND
└───django_app
│ manage.py
│
├───mainapp
│ asgi.py
│ settings.py
│ urls.py
│ wsgi.py
│ __init__.py
│
└───prediction
admin.py
apps.py
models.py
tests.py
views.py
__init__.py
顾名思义,' mainapp '是服务于 Django 应用程序的主应用程序。然而,所有其他功能将由我们创建的其他自定义应用程序来执行,例如我们的预测应用程序。我们稍后会添加另一个名为“用户的应用程序。
将我们新创建的应用程序添加到项目设置
打开 mainapp 文件夹中的 settings.py 文件。在底部的已安装应用部分添加我们的新应用“预测”。
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'prediction',
]
将本地 PostgresSQL 数据库连接到 django_app
确保您安装了 PostgreSQL 12+。如果可能,查看官方 PostgreSQL 下载部分。我使用 windows 官方下载附带的 pgAdmin 创建了一个名为' predictiondb '的新的空数据库。请注意,第一次在浏览器中打开 pgAdmin 时,您需要指定一个默认用户和密码。您可以添加' postgres_user '作为用户,添加' postgres_password '作为密码。

作者图片

作者图片
在 mainapp 文件夹中创建一个名为 local_settings.py 的文件。
D:\PROJECTS\DOCKERDJANGOREACTPROJECT\BACKEND\DJANGO_APP
│ manage.py
│
├───mainapp
│ asgi.py
│ settings.py
│ urls.py
│ wsgi.py
│ __init__.py
│ local_settings.py
│
└───prediction
这将用于覆盖 settings.py 文件的某些设置。打开 settings.py 文件,并在最后添加以下内容。
#########################################
## IMPORT LOCAL SETTINGS ##
#########################################try:
from .local_settings import *
except ImportError:
pass
现在,我们将在 local_settings.py 文件中提供 PostgreSQL 连接设置。打开 local_settings.py 文件,并添加以下信息:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'predictiondb',
'USER': 'postgres_user',
'PASSWORD': 'postgres_password',
'HOST': '127.0.0.1',
'PORT': '5432',
}
}
正如您在上面的设置中所看到的,' NAME '属性是您的数据库的名称,而' USER '和' PASSWORD '需要与您在系统上设置 pgAdmin 或 PostgreSQL 时使用的相同。
迁移 django_app 模式
此时,我们需要将现有的模式迁移到数据库中。这是因为通常在 Django 中,我们创建数据模型来与数据库交互。尽管此时我们只添加了一个应用程序 prediction,并且没有定义任何数据模型,但是如果您转到 settings.py 文件中的 INSTALLED_APPS 部分,您会看到已经存在许多默认应用程序。这些预装应用中的一些已经有了它们的模型(或模式定义)。为了使我们的 django_app 模式/模型与数据库保持一致,我们需要在继续之前先执行一次迁移。
确保您位于 django_app 文件夹中,并且本地 Python 环境已激活。执行 python manage.py 迁移。
(localPythonEnv) D:\Projects\DockerDjangoReactProject\backend\django_app>python manage.py migrate
如果您的本地数据库可以正确地连接到您的 django_app,那么您应该会在您的终端上看到如下消息。
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying auth.0012_alter_user_first_name_max_length... OK
Applying sessions.0001_initial... OK
创建超级用户
接下来,我们将为我们的项目创建一个超级用户/管理员。这是为了让超级用户可以登录到管理仪表板,监控项目和添加用户,我们将在后面看到。运行命令“python manage.py createsuperuser”。这将要求您提供用户详细信息和密码。每次提供它们并按回车键。
(localPythonEnv) D:\Projects\DockerDjangoReactProject\backend\django_app>python manage.py createsuperuser
创建超级用户后,终端将显示“超级用户创建成功”最后。注意,这个超级用户信息将存储在我们前面创建的 PostgreSQL 数据库中。这就是为什么我们需要提前执行迁移,以便用户的 django_app 数据模型与 PostgreSQL 服务器中的 users 表保持同步。
检查 Django 是否成功运行。
从 django_app 文件夹运行命令' python manage.py runserver '。
(localPythonEnv) D:\Projects\DockerDjangoReactProject\backend\django_app>python manage.py runserver
如果您正确地遵循了上述步骤,您将会在命令行中看到类似下面的消息。
System check identified no issues (0 silenced).
September 03, 2020 - 18:19:47
Django version 3.1, using settings 'mainapp.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
打开你的网络浏览器,进入网址“ http://127.0.0.1:8000/ ”。您应该会在浏览器中看到以下内容:

作者图片
如果你去http://127 . 0 . 0 . 1:8000/admin/路由,你会看到一个如下图所示的管理面板。您可以使用之前创建的超级用户名称和密码登录到管理视图。那个超级用户是我们 Django 应用程序的管理员。

作者图片
登录后,您将能够看到以下内容。

作者图片
点击 + 添加用户。你会发现作为 django_app 的管理员,你可以很容易地添加用户。

作者图片
在终端上按 Ctrl+C,关闭 django_app 运行服务器。
创建我们的预测视图
在之前的帖子中,我们已经创建了我们的预测机器学习模型。你可以参考这篇文章,看看机器学习模型是如何创建的。在预测应用文件夹中创建一个名为' mlmodel 的文件夹。将我们在上一篇文章中创建的文件'irisrandomforestclassifier . joblib'复制到这个' mlmodel '文件夹中。为了您的方便,该文件存储在这里的 github 上。
D:\PROJECTS\DOCKERDJANGOREACTPROJECT\BACKEND\DJANGO_APP\PREDICTION
│ admin.py
│ apps.py
│ models.py
│ tests.py
│ views.py
│ __init__.py
│
└───mlmodel
IRISRandomForestClassifier.joblib
编辑预测应用程序文件夹中的 apps.py 文件,如下所示:
我们在 apps.py 文件中加载 ml 模型的原因是,通过这种方式,分类器只需加载一次,即在与 Django 应用程序建立会话连接时,从而减少了开销。我们正在使用官方 scikit-learn 文档建议的' joblib '加载方法将训练和保存的分类器加载回内存。
接下来,我们将在预测应用程序中创建一个 API 视图。由于我们要借助 Django Rest 框架来创建 REST APIs,我们之前通过 requirements.py 文件安装了这个框架,所以一定要在 settings.py 文件中添加' rest_framework '作为一个应用。
# Application definitionINSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'prediction',
'rest_framework',
]
现在,编辑预测应用程序文件夹中的 views.py 文件,如下所示:
因此,我们创建了一个基于类的视图' IRIS_Model_Predict ,它继承了默认的 API viewdjango rest _ framework。基本上,该视图从 URL 请求(我们将在下面定义)中获取 JSON 输入数据,处理数据,并根据 apps.py 文件中定义的加载的机器学习模型进行预测。
创建 URL
接下来,我们需要为我们的后端应用程序定义路由。其中一条路由,即管理路由,您刚刚在上面看到,它将您带到管理视图。打开 mainapp 文件夹中的 urls.py 文件。进行更改,使 urls.py 文件如下所示。
所以我们基本上是说,任何以/api/(比如http://www.example.com/api/...))开头的路由都应该将我们带到 prediction.urls 文件,该文件将包含路由的剩余部分。
要定义路径的其余部分,请在预测应用程序文件夹中创建一个 urls.py 文件。该文件应包含以下内容。
也就是说,我们将“预测”添加到 URL 路径/api/中,这样,如果我们发出 api URL 请求,如http://www.our-final-app.com/api/predict/,我们将被带到 IRIS_Model_Predict 视图,从该视图中,我们将得到一个预测响应,该响应是对随请求一起发送的样本 iris flower 数据的响应。
测试我们的预测 API
像以前一样,通过执行'python manage . py runserver'来重启我们的 django_app 服务器。
打开 Postman 进行新的 POST 请求。由于我们的 django_app 运行在本地服务器上,我们将向http://127 . 0 . 0 . 1:8000/API/predict/或http://localhost:8000/API/predict/发出 API 请求。我们将发送以下样本鸢尾花数据作为 JSON 来进行预测。
{
"sepal length (cm)": 6.5,
"sepal width (cm)":3,
"petal length (cm)":2,
"petal width (cm)":1
}
向邮递员提出如下要求。JSON 样本花数据应该以 Body->raw->JSON 格式发送。

作者图片
你会看到加载的机器学习模型预测样本的花卉种类为“setosa”。
这意味着我们的预测 API 工作正常。
向我们的 REST APIs 添加身份验证
尽管我们的预测 API 工作正常,但在现实世界中,我们希望将对我们应用程序的 API 请求的访问权限仅限于注册用户。因此,我们希望增加功能,注册用户可以得到认证。在我们的例子中,工作方式如下:
- 管理员使用默认密码通过管理员视图添加新用户。
- 新用户然后能够登录到我们的应用程序,并选择他们选择的密码。
- 然后,用户使用他们的用户名和密码发出 REST API 登录请求。
- 然后,我们应用程序中的登录视图生成一个令牌,并将这个令牌发送回用户。
- 然后,用户使用这个令牌对预测 API 进行身份验证。只有通过身份验证的用户才能够使用之前创建的 IRIS_Model_Predict 视图进行预测,并且向未通过身份验证的用户发送错误响应。
要创建如上所述的登录视图,并在登录时返回令牌,我们将使用一个名为 django-rest-auth 的包,我们之前已经将它与 requirements.py 文件一起安装了。
在 settings.py 的已安装应用中,添加' rest_framework.authtoken 和' rest_auth 作为应用,如下所示:
# Application definitionINSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'prediction',
'rest_framework',
'rest_framework.authtoken',
'rest_auth',
]
然后,我们需要使用“ python manage.py migrate ”将我们新添加的应用程序的应用程序模式迁移到数据库。
(localPythonEnv) D:\Projects\DockerDjangoReactProject\backend\django_app>python manage.py migrate
这将在我们的数据库中创建一个名为‘authtoken _ token’的新表。你可以从 pgAdmin 中看到这一点。

作者图片
您还可以在 Django 管理视图中看到同一个表。该表将存储为所有用户创建的令牌,并在用户注销时删除它们。

作者图片
现在,我们需要在 django_app 中创建一个名为' users '的应用程序,它可以通过 REST APIs 处理用户登录/注销,在登录时返回令牌,在注销时使令牌过期。幸运的是,所有这些都很容易处理,因为我们已经安装了 django-rest-auth。然而,我们需要首先创建我们的“用户”应用程序。停止正在运行的 django_app 服务器,并运行以下命令:
(localPythonEnv) D:\Projects\DockerDjangoReactProject\backend\django_app>django-admin startapp users
像之前一样,在 mainapp.settings.py 文件的 INSTALLED_APPS 部分添加“用户”作为已安装的应用程序。请注意,我们已经重新排列了下面的列表,因此预测和用户都在底部。
# Application definitionINSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles', 'rest_framework',
'rest_framework.authtoken',
'rest_auth', 'prediction',
'users',
]
打开用户文件夹中的 views.py 文件。
└───users
admin.py
apps.py
models.py
tests.py
views.py
__init__.py
修改文件,如下所示。
因此,本质上我们只是使用来自 rest_auth 的 LoginView,对于注销,我们确保只有登录的用户能够通过使用他们在登录时收到的令牌进行身份验证来注销。这就是 APILogoutView 中的身份验证和权限类所做的事情。现在,在测试我们的 API 登录和注销视图之前,我们还需要做一件事。我们需要实际定义 API URL 请求来执行登录和注销(视图)。就像之前在' mainapp 中的 urls.py 文件中添加行' path('api/auth/',include(' users . URLs ')'。注意,我们需要将这一行添加到前面的'路径(' api/',include(' prediction . URLs ')【T5 ')行之上。这是为了让 Django 不会混淆,并把所有以' api '开头的内容发送到预测应用程序。因此,' mainapp '中的 urls.py 文件应该如下所示。
就像前面一样,在用户应用程序中创建一个 urls.py 文件,并将下面的代码放在 urls.py 文件中。
现在创建了 URL 和视图,我们应该能够通过 Postman 测试我们的 API 登录和注销视图。如果一切设置正确,我们应该能够在登录后从服务器取回令牌。重启 django_app 服务器,打开 Postman。现在向'http://127 . 0 . 0 . 1:8000/API/auth/log in/'发出 post 请求,使用您创建的超级用户登录详细信息作为请求数据,如下所示。注意:在下面的截图中,我将使用' sample_user' 作为演示用户。

作者图片
您应该能够得到一个令牌作为响应,如上所示。如果您转到管理门户,您将能够看到用户的令牌。

作者图片
这意味着我们的登录 API 工作正常。现在我们需要检查注销 API。在 Postman 中打开一个新的标签页,向“http://127 . 0 . 0 . 1:8000/API/auth/logout/”添加一个帖子请求。在 headers 选项卡中,添加一个名为' Authorization 的新密钥,其值为 Token,后跟您之前收到的令牌。

作者图片
点击发送,你应该会看到一条信息。
{
"detail": "Successfully logged out."
}
如果您现在转到管理面板并刷新,您会看到令牌已从服务器中删除。
现在,我们需要将这个身份验证功能添加到 REST API 预测视图中,以便只有注册用户才能执行预测。这真的很简单。只需将下面几行添加到我们的 IRIS_Model_Predict 视图中。
authentication_classes = [TokenAuthentication]
permission_classes = [IsAuthenticated]
因此,我们的预测应用程序中的 views.py 如下所示。
如果您现在像以前一样对'http://127 . 0 . 0 . 1:8000/API/predict/'执行 post 请求,您将会得到一个错误。
{
"detail": "Authentication credentials were not provided."
}
这是因为您现在需要首先登录,接收一个令牌,然后将该令牌与预测 API 请求一起发送以进行身份验证。因为您已经注销,所以再次使用 Postman 登录,并提供新收到的令牌作为授权头,以及用于发出请求的 JSON iris flower 数据。

作者图片
因此,我们在预测 REST API 中添加了身份验证。现在,在我们进入前端之前,我们需要做一些事情。首先,我们需要使用 REST APIs 添加一个密码更新特性。其次,我们需要启用跨源资源共享( CORS ),以便我们的前端可以在运行于同一个物理服务器上时向我们的后端发出请求。
创建一个密码更新 REST API
在 users.views.py 文件中从' rest_auth.views 导入' PasswordChangeView ,创建如下' APIPasswordUpdateView '类。我们这次只需要添加' TokenAuthentication '作为认证方法。users.views.py 文件如下所示。
现在我们需要为 API 定义 URL 路由。打开 users.urls.py 文件,并对其进行如下更改。
现在我们可以用 Postman 测试一下,如下所示。不要忘记像以前一样在授权头中提供我们的身份验证令牌。在正文中,我们需要用字段' new_password1 '和' new_password2 '提供两次新密码。

作者图片
注意,这次我们使用 Postman 中的表单数据字段来发送数据,而不是以前使用的 JSON 格式。如果一切正常,您会看到消息。
{
"detail": "New password has been saved."
}
将 CORS 添加到 Django 应用程序中
如果我们不添加 CORS,那么我们将无法从本地机器上运行的 React 前端对 Django 应用程序进行 REST API 调用,当我们为生产环境设置 Docker 时也是如此。要添加 CORS,我们需要安装一个名为' django-cors-headers 的包,我们之前已经用 requirements.txt 文件安装了这个包。我们需要在 mainapp.settings.py 文件中添加'corshe headers'作为已安装的应用程序(在 rest_auth 下面)。
INSTALLED_APPS = [
... 'rest_framework',
'rest_framework.authtoken',
'rest_auth',
'corsheaders', ...
]
在 installed apps 部分的下面,您需要修改中间件,如下所示,也就是说,我们必须在最上面修改 cors 中间件:
MIDDLEWARE = [
...
'corsheaders.middleware.CorsMiddleware',
'django.middleware.security.SecurityMiddleware',
...
]
打开 local_settings.py 文件,并在底部添加以下内容。
#################################################################
## (CORS) Cross-Origin Resource Sharing Settings ##
#################################################################
CORS_ORIGIN_ALLOW_ALL = True
就这样,我们已经为 Django 应用程序设置了 CORS。您可以通过参考官方开发者页面来更改更多高级选项的设置。但是现在,我们应该准备好了。
现在继续我们的前端 React 应用程序🍺!!
创建我们的前端
使用创建-反应-应用程序创建应用程序
确保您系统上安装了节点。如果没有,从官方网站下载并安装。在 DockerDjangoReactProject 文件夹中创建一个名为 frontend 的新文件夹。从终端 cd 到前端文件夹。我们将创建一个名为 react_app 的新项目/应用程序。从终端输入下面的代码,'' npx create-react-app react _ app'。
D:\Projects\DockerDjangoReactProject\frontend>npx create-react-app react_app
以上需要几分钟来完成,因为 node 会下载一些包来创建我们称为 react_app 的应用程序。因此,我建议你休息一会儿,直到这个过程结束。如果你面临 npx 的问题,你可以使用 yarn 来创建我们的前端应用程序。要使用纱线,安装纱线,并执行以下操作。
D:\Projects\DockerDjangoReactProject\frontend>yarn create react-app react_app
创建 react_app 后,将 cd 放入 react_app 文件夹并执行' npm start '。
D:\Projects\DockerDjangoReactProject\frontend>cd react_app
D:\Projects\DockerDjangoReactProject\frontend\react_app>npm start
这将在 http://127.0.0.1:3000 启动开发服务器。您可以在此 URL 打开服务器索引页面,您会在浏览器中看到如下内容。

作者图片
如果你想学习 React 的一些基本概念,那么你可以参考我之前写的这篇文章。但是在本文中,我们将只讨论需要什么。
创建模板登录视图
我们可以采用与 react_app 中的 django_app 类似的方法,首先创建视图,然后定义将我们带到这些视图的 URL。首先,我们将创建我们的登录视图。在我们的 src 文件夹中创建一个名为' components '的新文件夹。在“组件”文件夹中创建一个名为“ Login.js ”的新文件。我将使用一个名为材质 UI 的包来创建我的组件。这是因为 Material UI 已经包含了一些设计非常好的组件,我们可以直接使用它们。安装材料用户界面如下。
D:\Projects\DockerDjangoReactProject\frontend\react_app>npm install @material-ui/core @material-ui/icons @material-ui/lab
注意,无论我们安装什么包,都需要从 react_app 文件夹中安装。安装后,你可以在“package.json”文件中看到这些包。如果 npm 给你制造了一些问题,你也可以使用 yarn。
D:\Projects\DockerDjangoReactProject\frontend\react_app>yarn add @material-ui/core @material-ui/icons @material-ui/lab
一旦材料用户界面安装完毕,转到材料用户界面的网站,在左侧栏中,您可以在“入门”部分找到模板子部分。在模板页面上,您可以找到登录模板源代码的链接。

作者图片
复制代码并将其粘贴到我们刚刚创建的 Login.js 文件中。我们将进一步修改我们的模板页面。但是首先,我们需要创建将我们带到这个登录页面的路由/URL,以便我们可以在浏览器中查看它。我们需要安装一个名为“ react-router-dom 的包,通过执行以下任一操作来安装它。
D:\Projects\DockerDjangoReactProject\frontend\react_app>npm install react-router-domD:\Projects\DockerDjangoReactProject\frontend\react_app>yarn add react-router-dom
在 App.js 文件的同一级别的“src”文件夹中创建一个名为“Urls.js”的新文件。Urls.js 文件应该包含以下内容。
所以基本上这就是说,如果浏览器路由有确切的路径' login ',在这种情况下,Urls.js 应该从' Login.js '文件返回登录视图。
要查看实际效果,请打开 src 文件夹中的 App.js 文件,并进行以下修改。
此外,删除 src 文件夹中所有以前由 App.js 或 index.js 使用的不必要的文件——app . CSS、logo.svg、index.css。删除行“import”。/index . CSS ';'来自 index.js
现在,如果您从浏览器进入“http://localhost:3000/log in”,您会看到登录页面显示出来。

作者图片
这意味着我们的基本路由/URL 和视图设置在 React 前端工作。我们需要删除“记住我”、“忘记密码?‘和’没有户口?从登录视图注册组件。在 Login.js 文件中,删除以下内容。
.....
<FormControlLabel
control={<Checkbox value="remember" color="primary" />}
label="Remember me"
/>
.....
<Grid container>
<Grid item xs>
<Link href="#" variant="body2">
Forgot password?
</Link>
</Grid>
<Grid item>
<Link href="#" variant="body2">
{"Don't have an account? Sign Up"}
</Link>
</Grid>
</Grid>
.....
我们还需要一个用户名字段,而不是电子邮件字段。此外,将默认导出函数的名称改为从以前的'登录'登录,并删除顶部的版权函数和登录函数内部对它的引用。Login.js 文件应该如下所示。
....
export default function Login() {
..... return (
<Container component="main" maxWidth="xs">
.....
<form className={classes.form} noValidate>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
id="username"
label="User Name"
name="username"
autoComplete="username"
autoFocus
/>
....
</form>
......
</Container>
);
}
因此,浏览器登录页面将如下所示。

作者图片
创建带有布局的基本主视图
在继续之前,让我们也添加一个主页视图。这样,一旦用户登录,就会被重定向到主页。此时,如果你在http://127 . 0 . 0 . 1:3000/进入主页,你只会看到一个空白页。这是因为我们之前修改了 App.js,只为一个 URL 路由添加了一个视图——登录路由。转到物料 UI 网站- >组件- >应用程序栏,复制“简单应用程序栏的代码。在我们的组件文件夹中创建一个名为' TopBar.js 的文件,并将复制的代码粘贴到其中。现在在 components 文件夹中创建一个名为 Footer.js 的文件,内容如下。
现在在 components 文件夹中创建另一个名为‘layout . js’的文件。Layout.js 应该包含下面的代码。
我们将使用 Layout.js 页面来布局我们的主页。请注意,对于我们的简单应用程序来说,使用布局简直是一种过度杀戮。然而,我仍然想展示它,因为使用布局设计网站的不同页面被认为是一个好的设计原则。基本上,布局的工作方式是,我们将传递一个代表网页主体的组件作为布局函数的道具,布局将在页面顶部添加一个顶栏,在底部添加一个页脚。就这么简单!!布局函数中有趣的一点是‘props . children’。这将检索作为道具传递给布局函数的页面内容,并将其显示在顶栏和页脚之间。
现在创建一个简单的主页,它将只显示文本主页。组件中的 Home.js 文件应该如下所示。
现在我们需要为我们的主页创建 URL 路由,就像我们为登录页面所做的那样。修改 src 文件夹中的 Urls.js 文件,如下所示。
......import Login from "./components/Login";
import Home from "./components/Home";function Urls(props) { ....
<Switch>
<Route exact path="/login/"> <Login {...props} /></Route>
<Route exact path="/"> <Home {...props}/></Route>
</Switch>
.....
};.....
如果你在浏览器中进入主页,你会看到文本
主页
显示,但你看不到顶栏和页脚。要使用上面讨论的布局,即同时看到顶栏和页脚,请修改 App.js 文件,如下所示。
在 App.js 中进行上述更改后,如果您转到主页,将会看到下面的内容。注意,在上面的例子中,Urls 组件被传递给 Layout 组件,Layout 组件用 props.children 呈现 Urls 组件返回的任何内容,如前所述。

作者图片
如果您再次进入登录页面,您会看到登录页面也应用了顶栏和页脚。

作者图片
酷!这是我们想要的。如你所见,我们的布局工作正常。
将 TopBar.js 组件中的新闻文本更改为“Iris Species Predictor”。此外,删除左侧的菜单图标按钮,因为我们希望我们的应用程序尽可能简单。

作者图片
创建一个简单的设置文件
我们将定义一个 settings.js 文件,就像我们在 django_app 的' mainapp 中一样。该文件只定义了一些基本的设置变量— API_SERVER 和 SESSION_DURATION。API_SERVER 定义了 django_app 后端运行的 URL。这个 URL 在开发和生产环境中会有所不同,因为在生产环境中,我们会在云服务器上托管我们的应用程序。因此,我们不是在实际代码中修改它,而是定义一个设置文件,在这里我们可以非常容易地修改值。另一个环境变量 SESSION_DUARTION 定义了用户从浏览器中自动注销的时间。应该在 src 文件夹中创建 setting.js 文件,其内容如下。
创建用于身份验证的 Redux 存储
至此,我们已经为用户登录添加了一个基本的路由和模板视图。要添加真正的登录功能,我们需要对我们的后端进行 API 调用以进行身份验证。此外,我们需要在浏览器中成功登录后存储 API 令牌,这样,一旦用户登录,他们就可以使用这个 API 密钥向我们的后端发出进一步的请求。我们将使用 Redux 来完成这项工作。对于所有这些,我们需要安装以下软件包。就像之前一样执行以下任一操作。
D:\Projects\DockerDjangoReactProject\frontend\react_app>npm install redux react-redux redux-thunk axiosD:\Projects\DockerDjangoReactProject\frontend\react_app>yarn add redux react-redux redux-thunk axios
React 中的 Redux 一开始可能有点棘手。我不会说得太详细,只是简单地描述一下基本原理。通常在 React 中,组件有状态。根据定义,基于类的组件有与之相关的状态。也可以用像 useState()这样的 React 钩子来定义功能组件的状态。因此,组件有各自的状态。如果我们想把一个组件的状态传递给另一个组件,那么我们可以用 props 来实现。如果我们有许多依赖于相同状态变量的组件,这些道具会变得非常复杂。因此,我们希望有一个全球性的国家。在 React 中有许多方法可以实现这一点,例如 React 上下文。然而,一般来说,通过设计上下文是为了简化传递道具。Redux 是另一种更广泛接受的为应用程序创建全局状态的方法。在 Redux 中,我们有商店的概念,它由三个基本概念进一步表示:
- 行动
- 还原剂
- 商店
你可能会通过官方指南来详细了解这些,但本质上,React 中 Redux 的哲学真的很简单:
每当调度一个动作时,Reducer 对存储中的状态对象进行更改。存储是将动作、缩减器和状态对象集合在一起的对象。
让我们从为我们的应用程序创建商店开始。创建一个名为的文件夹,将存储在我们的 src 文件夹中。在 store-folder 中创建一个名为“authActionTypes.js”的文件,包含以下内容。这定义了动作类型。
在 store-folder 中创建另一个名为“authActions.js”的文件,内容如下。如果你读了下面的评论,这些授权动作的作用是不言自明的。还请注意,在下面的一些函数中,我们使用' axios '对我们的后端进行 rest API 调用。此外,‘local storage在浏览器中存储信息,即检索到的令牌和到期时间。你可能会问,当我们已经打算使用 Redux 存储来存储全局变量时,为什么还要使用浏览器的 localStorage 呢?这是因为 Redux 存储只能在浏览器中的每个选项卡或每个会话中使用。一旦用户关闭其中一个标签上的应用程序,商店就不存在了。也就是说这个存储只会存在于记忆中。这就是为什么我们使用 localStorage,这样一旦用户登录,他们就不需要在每个选项卡上登录应用程序。还有一些其他的方法可以实现这一点,比如 redux-persist,但是为了简单起见,我们只使用 localStorage。另一个原因是,我们不仅希望全局状态,还希望 Redux store 的一些分派(动作)是全局可用的。
因此,我们定义了动作类型、动作功能和一些返回调度(动作)组合的功能。现在我们要定义减速器。reducer 实际上定义了我们的应用程序全局状态和改变这些状态的方法。官方文件对减速器的定义如下。
reducer 是一个纯函数,取前一个状态和一个动作,返回下一个状态。
(前一状态,动作)= >下一状态
正如您将在下面看到的,reducer 是我们初始状态的一个相当简单的定义,以及每当一个动作被分派到存储时改变这些状态的方法。分派给商店的动作的例子可以是:
// Dispatch some actions
store.dispatch(actions.authLogin(username, password)
现在让我们定义我们的 reducer,它将根据调度的动作改变全局状态变量。在我们的 store-folder 中创建一个名为' authReducer.js '的文件,内容如下。
据此,我们创建了我们的 Redux 商店。我们的应用程序 src 应该如下所示。
D:\PROJECTS\DOCKERDJANGOREACTPROJECT\FRONTEND\REACT_APP\SRC
│ App.js
│ App.test.js
│ index.js
│ serviceWorker.js
│ setupTests.js
│ Urls.js
│ settings.js
│
├───components
│ Login.js
│ TopBar.js
│ Layout.js
│ Footer.js
│ Home.js
│
└───store
authActionTypes.js
authActions.js
authReducer.js
将 Redux 存储连接到我们的应用程序
完成所有重要的设置后,我们就可以实现登录功能了!我们现在需要告诉我们的应用程序使用上面的 redux 存储。我们的应用程序的入口点是 index.js 页面。打开 index.js 文件,将其修改为如下所示。
如您所见,我们导入之前创建的 authReducer,然后创建 redux 存储。然后,这个 redux store 可供我们的应用程序的所有组件使用(包括主应用程序组件!)通过在入口点 index.js 文件中用提供者包装器包装 App 组件。
从这里开始,我们的单个组件可以使用 connect 高阶包装器和两个自定义函数来访问这个全局存储,这两个自定义函数是 mapStateToProps 和mapdispatchtopros。首先显示了 App 组件的示例。如下所示修改 App.js 文件。下面,在我们的 App 组件中,当 App 第一次加载时,我们要调度 authCheckState()函数(即— 检查浏览器中是否已经存在令牌,令牌是否还没有过期。如果是这样,我们希望将“authSuccess”动作分派给存储,这将基本上更新 Redux 状态以反映用户已经过身份验证。如果不是,Redux 状态将被改变以反映用户被注销)。此外,从 Redux 存储中派生出三个定制对象——is authenticated、 token 和 logout 函数——然后将它们作为道具传递给所有其他组件。
使用 Redux store 添加登录功能
接下来,我们将登录组件与 Redux store 连接起来,以使用一些不是从 App 组件作为道具传递下来的 Redux store 对象。如下所示修改 Login.js 文件。
在上述中,进行了以下更改。
.....import { connect } from 'react-redux';
import * as actions from '../store/authActions';......function Login(props) {
....
const [username, setuserName] = React.useState(null);
const [password, setPassword] = React.useState(null); const handleFormFieldChange = (event) => {
switch (event.target.id) {
case 'username': setuserName(event.target.value); break;
case 'password': setPassword(event.target.value); break;
default: return null;
} }; const handleSubmit = (e) => {
e.preventDefault();
props.onAuth(username, password);
} return (
<Container component="main" maxWidth="xs">
.....
<form className={classes.form} noValidate onSubmit={handleSubmit}>
<TextField
........
onChange={handleFormFieldChange}
/>
<TextField
.........
onChange={handleFormFieldChange}
/>
......
</Container>
);
}const mapDispatchToProps = dispatch => {
return {
onAuth: (username, password) => dispatch(actions.authLogin(username, password))
}
}export default connect(null, mapDispatchToProps)(Login);
注意,在上面我们不需要 mapStateToProps,因为我们不需要任何其他 Redux store 状态变量。因此,代替' mapStateToProps '函数,我们只是将 null 传递给底部的连接包装器。然而,我们确实需要 dispatch authLogin 函数,所以我们使用' mapDispatchToProps '函数。此外,在登录功能组件中,我们用“ useState ”钩子定义状态。组件状态用户名和密码用 onChange = { handleFormFieldChange }子句更新,并且在用户提交表单时调用' handleSubmit '箭头函数。
为了验证我们的登录功能是否与 Redux store 一起工作,您需要为 Chrome 安装“ Redux DevTools ”扩展。打开前端登录页面,确保 Redux DevTools 扩展正在工作。另外,确保 Django 服务器和 PostgreSQL 服务都在您的系统上运行。现在,您应该尝试使用超级用户或您用 Django 后端创建的任何其他用户登录。如果一切设置正确,您将在 Redux DevTools 扩展中看到类似下面的 Redux 身份验证分派操作。

作者图片
如果您单击 state 选项卡,您还会看到 auth Redux 存储中的全局状态变量,如下所示。

作者图片
您还可以在浏览器中检查本地存储,您会看到我们的身份验证令牌和过期时间(在我们的示例中,根据 settings.js 文件,从登录起+5 小时)也已设置好。

作者图片
太棒了。!看起来我们用于认证的 Redux 存储运行良好。
登录时重定向到主页
要在通过身份验证后重定向到主页(或者实际上是大多数 web 应用程序中常见的上一页),请修改 Login.js 组件,如下所示。使用 useEffect,我们可以确保一旦用户通过身份验证,他们就会被重定向到上一页。
...import { useHistory, useLocation } from "react-router-dom";....function Login(props) {
.... let history = useHistory();
let location = useLocation();
let { from } = location.state || { from: { pathname: "/" } }; React.useEffect(() => {
if (props.isAuthenticated) { history.replace(from) };
}); ....
}....
在制作了上面的页面之后,如果您已经像在前面的部分中一样进行了身份验证,并且登录页面保持打开,您将会看到您已经被重定向到您的主页。
除了以上所述,还有另一个我们想要的功能。我们还希望,如果一个用户没有通过身份验证,并试图打开我们的应用程序的主页或任何其他页面,用户被重定向到登录页面。为此,我们的 src 文件夹中的 Urls.js 文件应该更改如下。
添加注销功能
在 TopBar.js 文件中进行以下更改。基本上,如果用户通过了身份验证,我们希望显示一个注销按钮,否则不显示任何内容(因为如果用户没有通过身份验证,那么根据我们在上一节中所做的第二个功能更改,他们已经在登录页面上了)。
....export default function TopBar(props) {
const classes = useStyles(); return (
<div className={classes.root}>
<AppBar position="static">
<Toolbar>
<Typography variant="h6" className={classes.title}>
Iris Species Predictor
</Typography>
{props.isAuthenticated ? <Button color="inherit" onClick={()=>props.logout()}>Logout</Button> : null}
</Toolbar>
</AppBar>
</div>
);
}
厉害!!现在,您可以点击 logout 按钮,并在 Redux DevTools 扩展中查看注销操作。

作者图片
创建预测用户界面
好了,这么多只是为了让认证工作。然而,好的一面是,我们以结构化的方式介绍了最棘手的 React 概念之一 Redux,希望这将在许多其他项目中帮助您。
事不宜迟,让我们创建用户界面来与我们的机器学习模型进行交互。这个用户界面将出现在主页上。因此,一旦用户登录后被重定向到主页,他们就会看到这个界面。修改 Home.js 文件,如下所示。
代码基本上是不言自明的。我们已经创建了四个使用自定义滑块的滑块,自定义滑块是使用材质 UI 主题创建的。这可能看起来很复杂,但实际上并不复杂。因为所有这些都是从material-ui.com的官方幻灯片示例中提取的。你可以参考这些例子。我们已经用 React 钩子创建了两个功能组件状态变量,useState。“dimension”状态变量是一个对象,而“prediction”只是一个字符串。当用户更改滑块时,使用 spread 运算符更新尺寸状态变量。当用户点击“预测”按钮时,会对我们之前创建的预测 REST API 进行一个 post API 调用。如果 API 调用成功,则向用户显示预测的虹膜种类。如果出现错误,将显示为警报。浏览器中的预测用户界面如下所示。

作者图片
使用滑块输入花的尺寸后,您可以按下“预测”按钮并查看预测的效果!
添加密码更新功能
在我们进入 Docker 部分之前,我们需要做最后一件事——添加密码更新功能。首先,我们需要创建 PasswordUpdate 视图。在 components 文件夹中创建一个名为“PasswordUpdate.js”的新文件。我只是复制了 Login.js 文件,将其重命名为 PasswordUpdate.js,并做了一些更改来创建这个视图。该文件的内容如下所示。
因此在这个视图中,有两个密码文本字段。如前所述,状态变量已经使用 useState 为这些字段添加。一旦用户对这些字段中的任何一个进行了更改,如果这些字段不匹配,则这些字段的错误属性将变为活动状态。此外,字段下方的帮助文本将以红色显示密码不匹配。当用户在 handleSubmit 函数中点击 submit 时,如果密码仍然不匹配,就会向用户显示一个警告。如果密码相同,那么 handleSubmit 函数将对 REST API 密码更新 URL 进行 post API 调用。如果服务器发送一个 OK 响应,那么同样使用 useState 创建的 success 状态变量将变为 true。如果成功状态为真,我们的 PasswordUpdate 组件将显示一条消息,“密码更新成功!”在顶端。
要查看所有这些操作,让我们创建一个 URL 路由,它会将我们带到视图。在 Urls.js 文件中进行以下更改。
....
import PasswordUpdate from "./components/PasswordUpdate";
.....// A wrapper for <Route> that redirects to the login screen if you're not yet authenticated.
....function Urls(props) {
....
<BrowserRouter>
<Switch>
....
<PrivateRoute exact path="/update_password/" isAuthenticated={props.isAuthenticated}><PasswordUpdate {...props}/></PrivateRoute>
</Switch>
</BrowserRouter>
....
};export default Urls;
最终的 Urls.js 文件如下所示。
此外,更改 TopBar.js 文件,以便我们可以在右上角看到两个按钮,其中一个将带我们到 PasswordUpdate 视图,另一个将带我们到主页。我们还添加了主页按钮,因为在密码更新后,用户可以单击该按钮返回主页。TopBar.js 如下所示。
现在是时候来看看我们的密码更新了。单击顶栏中的“更新密码”按钮,该按钮将在上述更改后出现。

作者图片
在密码更新页面上,如果您的密码不匹配,您会看到类似下面的错误。

作者图片
如果您输入的两个密码相同,并且在按下“更新密码”按钮时,服务器返回状态代码 200 (OK ),您将会看到类似下面的内容。

作者图片
现在,您可以单击顶部栏上的“主页”按钮返回到您的主页,并根据您的需要进行更多的预测。

作者图片
所以你走吧。我们已经使用 React 为我们的最终用户创建了一个简单而优雅的机器学习预测界面🍺!现在开始包装 Docker 中的机器学习应用程序🍺🍺!!
Docker —为我们的应用程序创建一个 Docker 平台
文章的 Docker 部分在我的 wesbite 上,这里—https://data graphi . com/blog/post/2020/8/30/Docker-guide-build-a-fully-production-ready-machine-learning-app-with-react-django-and-PostgreSQL-on-Docker,我最初就是在这里创作了这篇文章。希望你也喜欢🍺!
使用 TensorFlow 和 Keras 在 Google Colab 中构建性别分类器
使用 TensorFlow 和 Keras 在 Google Colab 中从头开始构建一个基于 CNN 的性别分类器。使用 TensorBoard 可视化模型的训练

在这篇文章的结尾你将会得到什么。(来源: Unsplash )
你好朋友们。在本文中,我们将使用 TensorFlow 和 Keras 提供的 API 来构建一个基于 CNN 的性别分类器。我们将在 Google Colab 上编写和执行代码。Colab 提供免费的 GPU 服务。我们将使用这些来快速训练我们的模型。
我将使用来自 IMDB-WIKI 数据集的维基百科图片。我已经对数据集进行了预处理,从图像中裁剪出所有的脸,并将它们作为对象存储在。pickle 格式在我的 Google Drive 里。如果你已经准备好数据集,你可以继续,如果你想准备一个和我在这篇文章中使用的数据集一样的数据集,你可以阅读我的另一篇文章,在那里我解释了如何创建一个 Colab 笔记本,处理数据并存储它们。
苦苦寻找数据集?,让我们使用…从 IMDB-WIKI 数据集为 CNN 模型准备一个现成的人脸数据集
medium.com](https://medium.com/@nachi2muthu13/preprocess-and-prepare-a-face-dataset-ready-for-cnn-models-885867907eb0)
在这篇文章中,我解释了每一行代码,最后,你会有信心自己构建一个多类分类器。
让我们编码
在 Google Colabs 上创建一个新的笔记本,并安装您的 Google drive。不要错过在您的笔记本中将您的运行时类型更改为 GPU。
如果你是 Google Colab 的新手,不知道怎么做,你可以在我的以前的文章中学习。
首先,让我们导入这段代码中需要的所有包。在一个新的单元格中导入所有的包。
代码块 1:导入所需的包。
现在我们已经导入了所有需要的包,让我们加载我存储在 Google Drive 中的数据集(PS:我已经在我的另一篇文章中展示了如何预处理数据并存储它。如果你没有自己的数据集,请阅读它。我已经在前面的部分添加了链接)。
代码块 2:导入数据集。
第 1 行:读取存储的数据。二进制模式的 pickle 格式。
第 2 行:使用 pickle 包将其转换为 python 对象。
第 4–5 行:从加载的数据集中单独提取图像和性别数据。
第 6 行:显示图像数组的形状,单个图像的形状和性别数组的形状。

图 1:显示输入的形状
在上面的输出中,我们可以看到有 42252 个图像,每个都是 32x32 的 RGB 图像。我们还有一个 2D 数组格式的每张图片的性别标签,每个子数组包含性别值(1.0:男性,0.0:女性)。为了更好地理解,您可以打印数组并进行检查。
接下来,让我们看看我们将使用什么样的图像来训练模型。
代码块 3:查看我们拥有的图像
第 4–11 行:从我们的数据集中打印 4 张随机图像并显示它们。

正如您在上面的输出中看到的,我们将用来训练我们的模型的图像只包含人脸及其性别。
我们现在将可视化我们的数据分布,以深入了解我们的数据。
代码块 4:绘制数据集的直方图。
第 1–12 行:我创建了男性和女性两个类别,并将其添加到“性别绘图”变量中。使用这些分类数据,我们可以使用 Plotly 绘制直方图。

图 2:我们数据集的直方图。
我们有 30k 男像,10k 女像。这些图像足够了,因为我们正在执行二元分类。
我们现在开始登船。执行下面的代码
%tensorboard --logdir "logs"
在“logdir”参数中,您应该给出保存模型日志数据的目录的路径。TensorBoard 将在给定的目录中搜索日志并显示出来。如果您想将日志文件保存在 Google Drive 中,您可以给出相应的路径。在几个步骤中,我将向您展示如何向我们的模型添加回调来保存日志文件。
是时候创建我们的 CNN 模型了。首先,我们将模型所需的所有层添加到一个列表中,然后使用 Keras 中的顺序类创建模型。虽然这是一个二进制分类问题,而不是在最后一层使用 sigmoid 激活函数,但我使用了“二进制交叉熵”作为损失函数。我已经把这个问题当作一个只有两类的多类分类问题。我这样做是为了让你知道如何使用 CNN 实现多类分类。
代码块 5:创建我们的 CNN 模型。
第一行:模型中的第一层是输入层。我们将图像的形状作为参数传递给它。
第 3 行:创建一个元组,其中包含我们模型中特定 Conv2D 层将分别拥有的过滤器数量。
第 5–11 行:遍历上面创建的元组,创建 Conv2D 层,Conv2D 层具有“Relu”激活功能。然后为每个 Conv2D 函数添加一个“BatchNormalization”函数和 MaxPooling2D。MaxPooling2D 的池大小为 2x2,每步 2 步。您可以更改这些值。
第 13–26 行:每当在 Conv2D 层之后添加一个密集层时,应该在它们之间添加一个展平层。该图层会将 Conv2D 图层的权重从 2D 格式转换为密集图层可以使用的一维格式。每个密集层被赋予一个“Relu”激活函数和“BatchNormalization”函数。添加了 Dropout 函数,以防止模型过拟合。函数内部传递的参数是丢弃概率,如果传递 0.1,则意味着 10 个输入中有 1 个将被随机丢弃。
第 27–28 行:当我们使用 2 个类进行分类时,我们使用输出大小为 2 的密集层。最后一个密集图层中输出大小的数量与您希望模型进行分类的类的数量相同。我们还将 softmax 层用于分类问题,因为它为每个预测返回一个列表,该列表包含图像属于相应类别的概率,并且该图像被分配到具有最高概率的类别。
第 31 行:然后,我们将所有创建的图层添加到一个序列模型中。向顺序模型添加层还有其他方法,您可以参考相关文档。
第 32–34 行:我们通过指定优化函数和损失函数来编译模型。因为它被视为多类分类问题,所以我们使用“分类交叉熵”作为损失函数。当针对二元分类问题创建模型时,我们必须使最后一个密集层中的输出为 1,并且仅对最后一层使用 sigmoid 激活函数。与此同时,所使用的损失函数应该是“二元交叉熵”
第 35 行:我们为每个模型训练指定文件夹名。我们使用模型被训练的时间作为文件夹名称。
如果你想你的模型日志存储在你的 Google Drive 中,那么你必须以这样的格式指定路径。
例如log_dir = "drive/My Drive/Colab Notebooks/Tutorial/Gender Classifier/logs/" + datetime.datetime.now().strftime("%Y%m%D-%H%M%S")
启动 TensorBoard 时,应提供相同的路径,直到“日志”文件夹。log_dir = "drive/My Drive/Colab Notebooks/Tutorial/Gender Classifier/logs。
第 36 行:在一个名为 callbacks 的变量中,我们创建了一个所有回调的列表,并将其传递给模型。这里我们只创建一个回调来保存日志供 TensorBoard 使用,我们从“keras.callbacks”调用 TensorBoard 类,并将保存日志的路径作为参数传递。
是时候训练我们的模特了。我们将使用 80:20 的比例进行培训和测试。训练数据被进一步分成 80:20 用于训练和验证数据。
代码块 6:训练模型并评估它。
第 1–3 行:我们将数据分为训练数据和测试数据。
第 4 行:我们将只使用 80%的训练数据来训练模型,其余的将用作验证数据。因此将“数量 _ 训练 _ 示例”设置为可用于训练的图像数量的 80%。
第 5 行:设置批量为 64。出于训练目的,我们的训练数据将被分成多个批次,每个批次包含 64 幅图像。
第 6–8 行:我们正在从模型对象中调用 font 函数,以便我们的模型可以使用我们的数据进行训练。
Epoch 设置为 10,这意味着我们为训练提供的全部数据将用于训练模型 10 次。一个历元意味着使用给定的数据执行一次迭代训练,所提供的全部数据将被我们的模型使用一次。
steps_per_epoch 是提供给我们模型的数据批次数。当达到 steps_per_epoch 计数时,模型知道特定的 epoch 已经结束。
batch_size 是一批数据中出现的图像数量。
如果设置为 false,则模型将按照提供给它的顺序获取数据。建议将此设置为 true,这样模型就不会被训练成特定的类。
validation_split 是所提供的训练数据中可用于验证的部分。
回调是在每个时期或每个步骤结束时必须执行的功能或操作。这是我们的 TensorBoard 回调将通过的地方。
第 11 行:使用我们之前分割的测试数据,我们评估我们的模型的准确性,并检查是否没有发生过度拟合。
上述单元的执行为我们提供了每个时期的精确度和损失值。

图 3:模型精度和损失
正如您在上面的输出中所看到的,该模型对于我们的训练数据具有很好的准确性。验证准确性也很好,这表明我们的模型没有过度拟合数据。评估结果表明,我们的模型对未知数据也有很好的表现。现在是我们使用 TensorBoard 可视化模型训练的时候了。
向上滚动到执行命令以启动 TensorBoard 的单元格。现在,您可以看到那里显示的图表。将有一个图表用于绘制模型的准确性,另一个用于绘制损失。

图 4:可视化我们模型的训练。
如果您看不到此图表,请检查您是否为日志文件提供了正确的目录路径。TensorBoard 是一个非常强大的可视化工具,你可以用它做很多事情。如果你有兴趣了解更多信息,我推荐你观看 2017 年 TensorFlow dev 峰会。
让我们进入下一步。我们现在将从我们的计算机摄像头获取输入,并让我们的模型对图像中的人进行分类。在我们编写获取相机输入的代码之前,让我们定义一个将 RGBA 格式的图像转换为 RGB 的函数。
代码块 7:将 RGBA 图像转换为 RGB 图像。
第 1–20 行:该函数对图像执行数学运算以进行转换。感谢汪锋,我从 StackOverflow 的回答中获得了这段代码。
让我们定义一个函数来使用计算机中的网络摄像头捕捉图像。由于整个笔记本都在您的浏览器上运行,我们需要编写 JavaScript 代码来使浏览器访问网络摄像头,捕捉图片并将其发送到服务器进行处理。我简单解释一下代码。除非您对使用 JavaScript 通过网络摄像头捕捉图像感兴趣,否则可以跳过这一部分。
代码块 8:通过网络摄像头捕捉图像。(来源: advanced_outputs.ipynb )
第 1 行:我们定义了一个函数,它将我们想要的图像的大小和质量作为参数。
第 2 行:向 Ipython.display 包中的 JavaScript 函数传递我们用 JavaScript 编写的要执行的 set 代码。
第 3–16 行:我们正在创建两个元素。一个 div 来显示来自我们相机的输入流,一个 capture 按钮来点击捕获图像,“stream”包含负责视频流的类的对象。
第 22–31 行:代码等待点击捕获按钮。一旦它被点击,显示在输出屏幕上的视频的特定帧被捕获并转换成像素字典,然后被返回。您可以在 MDN Web 文档中了解更多关于数据返回格式的信息。
第 35 行:执行里面写的 JS 代码。这里我们调用上面定义的 JS 函数。
代码块 8:将捕获的图像转换成所需的格式。
第 5 行:我们调用 python 函数“take_photo ”,它反过来调用 JS 函数并捕获一张照片。
第 7–9 行:我们根据关键字对 JS 函数返回的像素进行排序,然后将图像调整为 3D 数组格式。
第 15 行:由于获得的图像是 RGBA 彩色格式,我们要将其转换为 RGB 彩色格式并显示。

图 5:捕获的图像。
我们已经收到了需要分类的输入数据。我们将从图像中检测和裁剪人脸,将裁剪后的图像传递给模型,并获得其预测和显示输出。让我们定义两个函数,一个用于提取人脸,另一个用于显示带有标签的结果。
代码块 9:定义函数来处理我们的图像并显示输出。
第 1–21 行:此函数使用 Dlib 的基于 CNN 的人脸识别模型获取图像参数并检测其中的所有人脸,然后将它们从图像中裁剪出来。这个函数返回一个字典,包含所有的脸及其在图像上各自的坐标。
第 23–33 行:该函数将原始图像、裁剪后的人脸以及模型对每个人脸的预测作为其参数。它在所有面上绘制矩形框,并在这些框上添加各自的标签,然后显示图像。
是时候调用这些函数并获得输出了。
代码块 10:对图像进行分类。
第 1 行:我们从图像中提取人脸。
第 3–6 行:我们正在创建一个包含图像中所有人脸的图像数组。
第 9–10 行:我们预测每张人脸图像的标签。
第 12 行:我们调用显示分类输出的函数。

图 6:最终的分类图像。
你也可以试着把一个有多张脸的图像分类。
到此,我结束这篇文章。我希望你已经从这篇文章中学到了很多,现在可以用任何类型的对象和任何数量的类构建一个多类分类器。
我在我的笔记本上附上了一个链接供你参考。
性别分类器. ipynb](https://colab.research.google.com/drive/1d_mJjJJgdx_zqEBK4WgG0f7tQ1vsMaJB)
如有任何疑问,请随时联系我。
Instagram: nachijr4
电子邮件:nachi2muthu13@gmail.com
中:纳奇穆图
领英:纳奇穆图
构建一个在 Kubernetes 上运行的高度可伸缩的仪表板
使用 Python,Docker 和 Google 云平台

目前,一些出版物中提到了许多技术发展。这些关键词通常包括云、开源、自动化部署、高度可扩展、容器化应用。
在这种背景下,具体的技术如 Python 、 Docker 、云平台和类似 Kubernetes 的容器编排平台 s 经常被命名。
为了更好地理解提到的技术,我决定基于 Flask 和 Dash by Plotly 构建一个仪表板,它运行在 Google 云平台上的 Kubernetes 集群上,因此具有高度的可伸缩性。
你会在 GitHub 上的我的资源库中找到完整的代码和相关文件。
这篇文章是一个更大项目的一部分。如果你也对可扩展的 web 抓取感兴趣,或者对我们如何基于 Spark 用自然语言处理准备数据,在 Docker 中打包代码并通过 Kubernetes 部署感兴趣,你会在文章末尾找到相应的链接。
架构概述

Kubernetes 上可扩展仪表板的架构
数据存储在 BigQuery 表中,由 python 脚本读取,该脚本在 Docker 容器中执行。Kubernetes 集群由一个节点组成,该节点包含 3 个执行应用程序逻辑(dashboard-app)的 pod。为了能够从 web 访问 dashboard-app,我们创建了一个公开部署的服务对象。我们在当前集群中提供一个负载平衡器,并为服务分配一个固定的外部 IP 地址。因此,最终用户可以通过互联网浏览器使用仪表板。
仪表板的实施
在我描述 Kubernetes 中仪表板的部署过程之前,我想向您简要介绍一下仪表板的实现。如果您对应用程序本身不感兴趣,可以跳过这一部分,专注于 Kubernetes 中的部署过程。
仪表板本身是在 Flask 和 Dash by Plotly 的基础上构建的。
Flask 是用 Python 编写的 web 框架,它提供了 Jinja2 、模板引擎和 Werkzeug 作为构建 Web 服务器网关接口(WSGI)应用程序的库。Flask 的核心功能保持简单,优点是易于集成额外的库。
Dash 是一个开源 Python 框架,允许您创建最先进的仪表板。他们提供了许多演示应用,你可以用它们作为自己实现的灵感。
他们提供了许多鼓舞人心的想法来实现它们。
Dash 为后端使用了 Flask web 框架。这使得在现有 Flask 应用程序的特定路径上嵌入 Dash 应用程序变得相当简单。在这个仪表盘中,Dash app 挂载在 Flask app 的“/dash”路由(http://localhost:8080/Dash)下。
Kubernetes 中的部署流程
因为这是我在这个环境中的第一次实现,所以我将一步步地向您介绍我所做的事情。我希望这些解释能帮助你在这个话题上有一个好的开始!开始了…😃:
- 首先,我向 Google 云平台申请了免费试用订阅。(也可以使用运行 Kubernetes 的任何其他平台)
- 创建一个 Kubernetes 集群
进入“Kubernetes 引擎”→“创建集群”→选择“您的第一个集群”

创建一个 Kubernetes 集群
将参数中的名称更改为 dashboard-web ,可以应用其余设置。然后点击创建来构建名为 dashboard-web 的 Kubernetes 集群。
现在创建了一个具有一个节点的集群,在其上可以创建多达 110 个pod。

通过 REST 或命令行创建 Kubernetes 集群
提示:您所做的集群配置以脚本的形式存储和提供,可以通过 REST-API 或命令行来执行。因此,可以自动创建集群。下面是一个可以在云 Shell 中使用的命令行代码示例:
gcloud beta container --project "<YOUR-PROJECT>" clusters create "dashboard-web" --zone "us-central1-a" --no-enable-basic-auth --cluster-version "1.15.4-gke.22" --machine-type "g1-small" --image-type "COS" --disk-type "pd-standard" --disk-size "30" --scopes "https://www.googleapis.com/auth/devstorage.read_only","https://www.googleapis.com/auth/logging.write","https://www.googleapis.com/auth/monitoring","https://www.googleapis.com/auth/servicecontrol","https://www.googleapis.com/auth/service.management.readonly","https://www.googleapis.com/auth/trace.append" --num-nodes "1" --no-enable-cloud-logging --no-enable-cloud-monitoring --enable-ip-alias --network "projects/<YOUR-PROJECT>/global/networks/default" --subnetwork "projects/<YOUR-PROJECT>/regions/us-central1/subnetworks/default" --default-max-pods-per-node "110" --addons HorizontalPodAutoscaling,HttpLoadBalancing --enable-autoupgrade --enable-autorepair
3.容器化一个 Python 应用
要获得 dashboard——它是用 Python 开发的——在 docker 容器中运行,需要 3 个文件:
- index.py (包含仪表盘 python 代码的文件)
- docker file(通过读取该文件中的指令自动构建图像)
- requirements . txt(包含应用需要运行的依赖项列表)
4.创建一个 Docker 镜像,推送到 google 容器注册表 启动云壳,然后启动编辑器。

云壳编辑器
我已经在云外壳提供的浏览器中创建了我的仪表板结构。你会在我的 git 库中找到完整的代码。
将文件复制到云外壳编辑器后,可以创建 Docker 映像。为此,您必须转到仪表板目录。
***cd dashboard***
从这个目录中,您可以运行 bash 脚本buildpushdockerimage . sh,
***bash BuildPushDockerImage.sh***
它依次执行以下命令:
构建 Docker 映像并将其推送到 Google 容器注册表
Docker 映像现在是基于 3 个文件(index.py、Dockerfile、requirements.txt)构建的,可以在 Google 容器注册表中找到。

谷歌容器注册
5.创建一个部署,该部署创建一个复制集以显示三个“dashboard-app”窗格
要开始部署,可以执行以下 bash 脚本:
***bash DeployDashboardPod.sh***
它依次执行以下命令:
部署三个吊舱
第一步是确保我们被允许为我们的项目运行ku bectl。Kubectl 是一个命令行界面,用于对我们的 Kubernetes 集群运行命令。
之后,我们使用 DashboardPod.yaml 模板创建我们的“dashboard-app”窗格。
部署仪表板应用程序以调出 3 个窗格
创建窗格后,我们可以使用以下命令详细检查它们:
*****kubectl get pods -o wide*****

命令的输出
部署中有 3 个 pod(Status = container creating),所以让我们再等几秒钟,然后再次执行命令:

再次执行该命令后的输出
我们看到容器现在处于就绪状态(1/1)和状态=正在运行。此外,它们都被分配了一个内部 IP 地址。如上所述,我们可以在这个节点上运行的最大 pod 数量是 110,这意味着如果仪表板上的负载增加,我们可以在这个节点上再创建 107 个容器。如果我们需要更多的容器,我们可以订购一个包含更多节点的更大的集群,每个集群运行 110 个容器。这种方法使我们有可能实现一个高度可伸缩的环境。
6.创建一个暴露外部 IP 地址的服务对象,以允许通过互联网浏览器访问仪表板****
为了能够从 web 访问 dashboard-app,我们创建了一个公开部署的服务对象。“type=LoadBalancer”在当前集群中创建一个负载平衡器,并为该服务分配一个固定的外部 IP 地址。该服务在端口 80 上运行,并连接到端口 8080 上的容器。
要公开部署,可以执行以下 bash 脚本:
*****CreateExtWebService.sh*****
它执行以下命令:
显示有关仪表板应用程序服务的信息:
*****kubectl get service dashboard-app*****

命令的输出
现在可以通过外部 IP 地址访问“dashboard-app”服务。
要获得更多服务信息,您可以执行以下命令:
*****kubectl describe services dashboard-app*****

命令的输出
记下 dashboard-app 服务公开的外部 IP 地址(LoadBalancer Ingress)。在本例中,外部 IP 地址是 35.202.15.18。此外,您可以看到该服务有几个端点:10.44.0.10:8080,10.44.0.11:8080,10.44.0.12:8080。这些是运行仪表板应用的 pod 的内部地址。**
您可以使用外部 IP 地址(LoadBalancer Ingress)访问 dashboard-app 应用。由于应用程序运行在“/dash”目录中,因此这种情况下的调用如下:
***http://<LoadBalancer Ingress IP>/dash/***
仪表板现在显示在互联网浏览器中:

仪表板-通过外部 IP 调用的应用程序
仪表板分为四个区域:
- 热门词汇(文章):对应到数据科学文章的“前 10”或“前 100”词汇显示为词云。
- 作者:提供了一个包含所有已爬网作者的下拉列表。
- 来自…的热门文章:根据所选作者,将显示热门文章及其元数据(点击次数、阅读时间等)。如果没有选择作者,则显示所有作者的“前 10 篇”文章。
- 数据科学趋势(标签):显示文章中使用的标签,以便您可以随着时间的推移分析哪些术语在何时被频繁使用,以及是否可以从中得出趋势。
提示:云的优势在于,只要你使用它,你就只需要为基础设施付费。在一次成功的测试运行之后,为了节省成本,我删除了我的“dashboard-web”集群;)
结论:
这样一来,我们现在就有了一个在云平台上运行的仪表盘,它是用 Python (Flask & Dash)开发的,打包在 Docker 中,部署在 Kubernetes 上。整个过程已经公开,可以通过网络浏览器浏览。
我觉得很棒,希望你也是:)!
相关文章:
如果你想知道我们如何从向数据科学爬取数据,那么查看 Philipp Postels 的文章:通过使用 python 用 Selenium 为向数据科学爬取构建一个可伸缩的网络爬虫
如果你想知道我们如何使用基于 Spark 的自然语言处理来准备数据,如何在 Docker 中打包代码,如何通过 Kubernetes 部署它,请查看 Jürgen Schmidl 的文章:Spark in Docker in Kubernetes:A practical approach for scalable NLP
制作自制电流/电压绘图仪
设计和编程您自己的数据采集硬件

最近我在思考二极管的非线性行为。在大学里,我了解到通过二极管的电流可以用施加在其上的电压的指数函数来近似表示。我想知道指数函数如何描述真实二极管的电流/电压行为。
我认为这将是一个有趣的项目,建立一些测量和绘制二极管的行为。我有一个备用的 Arduino Uno,还有一块试验板和一些基本的电子零件。
现在,三天后,我有了一个比我想象的更好的系统。它捕获数据并根据数据制作图表,如下所示。以下是如何制作自己的电流/电压分析仪。我提供源代码和硬件设计作为开源。

零件清单
- 一个小试验板和电线。
- Arduino Uno 或兼容板,带 USB 电缆。
- 产生 12 至 15 伏 DC 的电源,电流至少为 100 毫安。您可以为这部分寻找一个旧的“墙砖”电源适配器。
- LM7808 稳压器。这就产生了一个稳定的 8 伏 DC 信号。(你可以用产生 9 伏信号的 LM7809 调节器来代替;它将同样有效。)
- LM324N 四路运算放大器芯片。
- 各种电阻器,如下面更详细解释的。
电路设计
对于这个项目,我需要一种方法来产生从 0V 到 5V 的不同电压,并精确控制增量。将数字数据转换成模拟电压电平的设备称为数模转换器,简称 DAC。虽然更先进的 Arduino Due 带有内置 DAC,但 Due 的成本几乎是 Arduino Uno 的两倍。我决定从头开始构建自己的 DAC,并与 Uno 一起使用。这本身就具有教育意义和回报。
DAC 设计如下所示:

关于硬件设计的一些注意事项:
- LM324N 芯片上有四个运算放大器。仅使用其中一个,在原理图中标为 IC1A。三个未使用的运算放大器如图所示进行布线,以防止它们因不必要的振荡而产生干扰。
- DAC 本身由左侧的电阻网络和运算放大器 IC1A 组成。(有关 DAC 工作原理的更多信息,请参见下文。)
- 原理图上标有
X的端子表示电路连接到 Arduino Uno 板(未显示)的位置。 - Uno 板由主机的 USB 连接供电。您将需要此连接来通过 Arduino IDE 串行监视器捕获数据,因此没有必要为 Uno 提供另一个电源。
- 电阻 R0 和 R1 连接到 PB0 和 PB1,但其余的电阻 R2-R7 连接到 PD 引脚,而不是 PB 引脚。(PD0 和 PD1 不能使用,因为串行通信需要它们。)
- 原理图中的二极管 D1 是您想要测试的任何元件的占位符。我已经成功测试了一个 1K 电阻(一种验证整个系统的好方法)、不同种类的 led 和各种其他二极管,包括肖特基二极管、齐纳二极管、整流器和锗检测二极管。
这是我的最终版本的样子:

DAC 理论
我使用来自 Uno 的 8 个数字输出来选择 256 个不同电压电平中的一个。九个电阻组成的网络和运算放大器共同实现 DAC。
每个输出(PB0、PB1、PD2、… PD7)产生 0V 或 5V 的独立电压,由 Uno 上运行的固件控制。因为这是 8 个独立的输出,所以有 2⁸=256 独特的输出组合。
电阻选择为 2 的幂,从 1K 一直到 128K。输出 PD7 通过相连的 1K 电阻 R7 对正运算放大器电压的贡献是 8 路输出中最大的,因为电阻最小。每个电阻值增加一倍,到达运算放大器的电压就会减半。
为了证明这是真的,考虑这张图,重新绘制以使当前的流动更清晰。

X₀至 X₇代表 8 个 Uno 输出引脚的电压。在给定时间,每个可以是 0V 或 5V。通过电阻器 R₀和 R₇流入 V₀节点的总电流必须等于通过 R₈.流出的电流(我们可以忽略任何进入运算放大器正输入端的电流,因为运算放大器设计具有极高的输入阻抗。)因此:
根据欧姆定律,每个电流等于每个电阻上的压降除以相应的电阻值:
拆分分数后,收集等式一边的 V₀项,求解 V₀,我们发现:
分母可以用常数 R’≈500ω代替,它代表所有九个电阻的并联等效电阻:
最后一个等式表明,运算放大器正输入端的电压 V₀是八个输入电压的线性加权和。
通过将运算放大器的输出连接到其负输入,它充当一个电压缓冲器,输出与其输入相同的电压 V₀。这被称为单位增益配置。运算放大器向测试元件提供高达 20 mA 的电流,同时将电阻网络与该元件隔离。
电阻调谐
为了使自制 DAC 尽可能线性,需要选择接近 2 的幂的电阻。这有一个小问题。电阻器通常不以 2K、4K 等值出售。
然而,有可能找到串联或并联的电阻对,以接近匹配目标值。电阻器的实际值很少与其标称值相符。你必须测量它们!我坐下来,用我的数字欧姆表试着组合,直到我得到正确的数值。仅仅这个电阻调谐步骤就花了我几个小时。
例如,对于我的 4K 电阻,我发现一个标称值为 180ω的电阻测量值为 176.8ω。我还发现了一个标称值为 3.9K 的电阻,测量值为 3.83K。将它们串联焊接在一起,我的欧姆表测得的总电阻为 4.00K。我发现,在试验板上串联(或并联)不同的电阻并测量它们,直到得到足够接近的结果,这比做数学计算更容易。
你不需要为了获得完美的阻力而把自己逼疯。这不会影响最终电流/电压图的准确性。正如您将看到的,成品器件将使用 Uno 的两个模拟输入来测量电压,因此结果图的准确性不涉及任何计算或猜测。重点是尽量平滑地覆盖可能的电压范围,不要让 DAC 产生的电压出现任何大的缺口。每次阻力在 1%以内就足够好了。
如果你觉得用这种方式组合固定电阻太麻烦,你可以买一组八个微调电阻,用螺丝刀调整它们,直到它们测量正确。
这里有一个特写镜头,可以更好地观察试验板上的 DAC。你可以看到我的一些复合电阻,大部分是串联的,一对是并联的。

安装和测试固件
您需要将这个项目的 GitHub 库克隆到您的计算机上。我已经验证了一切都可以在 Debian Linux 和 Windows 10 上运行。我没试过 Mac,但应该可以用。
https://github.com/cosinekitty/diodeplot
固件是一个名为DiodePlotFirmware.ino的 Arduino 草图。它设计用于 Arduino IDE 的串行监视器。一旦您构建了硬件并用固件对其进行了编程,您就可以执行快速诊断。我建议您第一次运行时使用 1K 电阻作为测试元件。将其放在电路中,而不是二极管 D1 中。打开 Arduino IDE 串行监视器。当您引导系统时,您应该会看到以下提示:
# READY
要验证 DAC 是否正常工作,可以将数字万用表连接到 DAC 输出,并在输入一系列命令的同时测量其电压。将您的万用表负极探针连接到 GND(我喜欢将其夹在 LM7808 的金属标签上)。将正极探针连接到运算放大器输出。它的测量值应该非常接近 0V。
接下来,输入一系列命令来手动更改电压水平。每个命令将是一个从 0 到 255 的数字,后跟字母v。按 enter 键提交命令。让我们从告诉电路板达到最大电压开始:
255v
您应该会在串行监视器中看到如下内容:
# READY
**255 1020 767**
第一个数字确认值 255(二进制 1111111)已经馈入进入 DAC 的 8 个引脚。第二个数字是 DAC 输出的模拟读数。它应该接近 Arduino 模拟输入的 10 位范围的高端,即 0..1023.你的万用表应该跳到+5.0 伏附近。
假设你安装了一个 1K 的电阻而不是 D1,第三个数字应该接近显示的值。它是测试组件顶部的电压。
如果一切检查完毕,您就可以继续了。否则,就是出问题了;拔掉你的电源和 USB 电缆,然后花些时间检查你的线路。在继续之前,您需要诊断并修复任何错误。
一旦你的最大电压检查出来,尝试几个中间值。例如,通过输入以下命令尝试 50%的电压。
128v
现在,串行监视器应该打印出与这些数字相近的数字(新输出以粗体显示):
# READY
255 1020 767
**128 507 380**
第一个数字应该正好是 128,剩下的两个数字应该大约是之前255v测试值的一半。此外,您的万用表读数应该约为+2.5V。
捕捉电压/电流曲线数据
现在是时候找点乐子了!让我们验证 DAC 的线性行为,仍然使用 1K 电阻代替 D1。
首先,按下显示屏右下角的“清除输出”按钮,清除串行监视器输出。然后输入以下命令:
1000m
m命令运行自动数据收集程序,扫描每个 DAC 输入,从 0 到 255。对于每个 DAC 值,m前面的1000告诉固件对每个 DAC 设置进行 1000 次过采样。固件连续读取 1000 次两个电压:DAC 输出本身和测试元件顶部的电压。
测试将需要几分钟时间来运行。完成后,您将得到如下所示的输出:
0 0 [1000] 0 [1000]
1 3 [2 231 766 1 0] 1 [8 755 237]
2 6 [1 153 846] 5 [590 409 1]
3 10 [1 119 880] 7 [0 5 491 498 6]
4 15 [41 957 2] 11 [3 247 748 2 0]
5 19 [60 934 6] 13 [0 1 145 849 5]
...
250 1000 [0 1 832 166 1] 751 [0 999 1]
251 1005 [3 790 205 2 0] 754 [0 984 16]
252 1009 [1 604 393 2 0] 757 [0 940 60]
253 1012 [0 2 567 430 1] 760 [0 931 69]
254 1017 [451 548 1] 763 [0 935 65]
255 1021 [360 630 10] 766 [0 838 162]
# FINISHED
数据格式的解释
此部分是可选的。如果你只是想用我提供的软件来绘制数据,你可以跳到下一节。但是如果你想编写自己的软件来处理数据,这里我解释一下所有这些数字的含义。
典型的一行如下所示:
2 6 [1 153 846] 5 [590 409 1]
第一个数字2是馈入 DAC 的 8 位值。就像我们之前看到的v命令一样,这是一个从 0 到 255 的值。
第二个数字 6 是 DAC 测得的模拟电压的中间值。就像在v命令中一样,它是一个从 0 到 1023 的值,从 0V 到 5V 线性缩放。
现在情况不同了。您将看到方括号[]中的数字列表。括号中的值总是奇数。这些值是读取不同电压值的次数。因为我们对每个值进行了 1000 次过采样(在1000m命令中),所以这些数字的总和总是 1000。也就是 1+153+846=1000。
中间的数字,在本例中为 153,表示测量的电压是 6 的多少倍(括号左边的数字)。所以对6 [1 153 846]的解读方式是:
- 1000 次中有 1 次,电压读数为 6–1 = 5。
- 1000 次中有 153 次,电压读数是 6。
- 1000 次中有 846 次,电压读数是 6+1=7。
类似地,线的剩余部分5 [590 409 1]表示在测试部件处测量的电压的过采样结果。
准备绘图仪软件
现在,使用剪贴板将这些数据复制并粘贴到您喜欢的文本编辑器中。在 GitHub repo 的克隆版本的data目录中,将文件保存为resistor.txt。打开命令提示符,转到克隆的目录。
如果您的系统上还没有 Python3,您需要安装它。验证方式:
$ **python3 --version**
Python 3.5.3
您还需要安装 Python 包matplotlib来渲染图形。在 Linux 上,该命令是:
sudo pip3 install matplotlib
要确认绘图仪软件准备就绪,请输入以下命令:
$ **./plot.py**USAGE: plot.py x y datafile.txt [outfile.png]Where x and y are each one of the following: n = the value 0..255 that is fed into the resistor network.
v1 = measured voltage coming out of the op-amp.
v2 = measured voltage fed into the test component.
i = deduced current calculated as (v1-v2)/R.If outfile.png is provided on the command line, the image
is saved directly to that file.
Otherwise, the graph is shown interactively.
虽然数据文件只包含n、v1、v2,但是在这个帮助文本中可以看到plot.py可以利用欧姆定律推导出电流i。
绘制电流/电压曲线
让我们将电流i绘制成元件电压v2的函数。输入以下命令:
./plot.py v2 i data/resistor.txt
这将产生一个显示线性关系的图形。毕竟电阻遵守欧姆定律,所以电流应该和电压成正比。这是我的样子:

现在,您可以测试非线性元件了。从 LED 开始很有趣,因为你也可以看到随着电压增加超过其照明阈值,它会慢慢变亮。用 LED 替换电阻器,确保将其阳极连接到电阻器 R9,阴极连接到 GND。如果你把它弄反了,就不会有坏事发生;它就是不亮,你会得到一个平坦的零电流曲线。把它翻过来再做一次测试。
确保在每次测试之前清除串行输出,这样就不会在输出文件中混淆不同测试的数据。遵循与电阻测试相同的步骤,运行1000m命令,将输出保存到文件中,并运行plot.py绘制数据。
以下是我测试随机放置的红色 LED 时得到的结果:

绘制正负电压响应
请看下图,您会注意到它涵盖了齐纳二极管在正负输入电压下的电流/电压响应。但是这个电路只产生 0V 到+5V 的电压。我是如何制作这个图表的?
这需要一点手工操作,但是绘图仪程序plot.py自有妙招。您将运行两个测试,一个测试组件(如齐纳二极管)正向偏置。将数据复制并粘贴到一个文本文件中,并在该数据前单独手动键入单词FORWARD。
在所有的测试数据之后,在一行中单独输入REVERSE这个词。
然后在试验板上翻转元件,使其反向偏置。清除您的串行输出,再次运行测试,并将结果数据粘贴到单词REVERSE之后。在data/zener3v.txt中,您可以在克隆的 repo 中看到一个示例数据文件。为简洁起见,它看起来像这样:
# [1n5225b Zener Diode @ 3.0V]
**FORWARD**
0 0 [1000] 0 [1000]
1 2 [0 4 309 685 2]
2 [6 260 734]
...
253 1012 [0 3 756 236 5] 156 [4 695 173 88 40]
254 1016 [0 1 670 326 3] 156 [5 728 148 84 35]
255 1021 [553 442 5] 156 [4 685 184 90 37]
**REVERSE**
0 0 [1000] 0 [1000]
1 3 [5 316 677 2 0] 3 [6 288 703 3 0]
2 6 [5 215 780] 6 [0 6 187 806 1]
...
253 1012 [0 1 640 351 8] 525 [0 36 634 94 44 79 49 8 35 20 1]
254 1017 [533 462 5] 526 [6 241 507 67 52 64 14 16 27 6 0]
255 1021 [2 437 554 7 0] 526 [36 619 128 54 64 45 12 24 18]
FORWARD是可选的,但是它明确表示下面的数据是正向偏置的。缺省值是向前偏移的数据。REVERSE关键字表示其后的任何数据都应被视为反向偏置的负电压。
还要注意第一行中显示的语法,它允许您在图形的顶部放置一个标题:井号#后跟方括号内的任何文本[]。这个标题便于记录您测试了什么组件。
有趣的实验
探索不同二极管和晶体管结的行为会很有趣。尝试绘制几个同类 led 的数据,看看它们的行为有多匹配。或者你可以试着绘制不同颜色的 led 曲线,看看它们的“开启”电压有什么不同。
这个项目也可以是创建给定组件的数学模型的基础。我打算自己做这件事,看看如何用指数回归、切比雪夫多项式或其他技术最好地拟合实验曲线。看看软件是否可以通过与已知回归模型的数据库进行匹配来推断出哪个设备产生了曲线,这将是一件有趣的事情。
我希望这个项目能激发你思考创造性的改编。也许你可以将其中的一些想法用于你自己的发明和实验。
用 Spacy、Flask 和 FuzzyWuzzy 构建一个关键词提取 API
如何在 python 中构建一个轻量级的关键字提取和模糊词匹配服务?

通常,在处理长文本序列时,您会希望将这些序列分解开来,并提取单个关键字来执行搜索或查询数据库。
如果输入文本是自然语言,您很可能不希望使用每个单词来查询数据库,相反,您可能希望从输入中选择一组唯一的关键字,并使用这些单词或单词短语来执行有效的搜索。
这项任务被称为关键词提取,多亏了像 Spacy 这样的生产级 NLP 工具,只需几行 Python 代码就可以完成。在本文中,我们将涵盖:
- 如何使用 Spacy 构建一个简单而健壮的关键词提取工具
- 如何使用 fuzzyWuzzy 处理拼写错误并找到给定关键字(令牌)的模糊匹配
- 如何用 Flask 将这两个函数包装成 REST API 端点
这个轻量级 API 旨在成为许多用例的通用关键字服务。当然,您也可以使用相同的通用结构将 Spacy 众多 NLP 函数中的任何一个构建到这个 API 中。
在我们开始之前,确保运行:pip install flask flask-cors spacy fuzzywuzzy来安装所有需要的包。
基于空间的关键词提取
对于关键字提取功能,我们将使用 Spacy 的两个核心思想——核心语言模型和文档对象。
Spacy 核心语言模型有:
通用预训练模型,用于预测命名实体、词性标签和句法依赖性。可以开箱即用,并针对更具体的数据进行微调。
空间文档对象为:
用于访问语言注释的容器……(和)是一个标记结构数组
因此,随着通过模型创建的文档对象的创建,我们可以访问大量非常有用(且强大)的 NLP 派生属性和功能,包括词类标签和名词块,它们将是关键字提取器功能的核心。
下载语言模型
使用 Spacy,我们必须首先下载我们想要使用的语言模型。到今天为止,Spacy 目前的version 2.2.4已经有了 10 种不同语言的语言模型,都有不同的大小。我将使用英文核心模型的小版本。我选择了小模型,因为对于 Heroku 部署来说,大模型的内存大小有问题。根据您部署该模型的位置/方式,您可能能够使用大型模型。要使用 Spacy 的 CLI 下载语言模型,请在终端中运行以下命令:
python -m spacy download en_core_web_sm
当我们构建 flask API 时,我们将使用 python 内置的子进程包,在服务启动后在应用程序本身中运行这个命令。但是现在,我们可以在命令行中这样做。
现在下载好模型后,你可以加载它并创建nlp对象:
import spacynlp = spacy.load("en_core_web_sm”)
我们的语言模型nlp将作为参数传递给下面的extract_keywords()函数,以生成doc对象。
关键字提取函数有 3 个参数:
- 语言模型
nlp sequence我们要从中提取关键字的字符串。- 以及可选的字符串列表
special_tags。此参数允许用户指定一个特殊的单词/短语列表,如果它们存在于序列中,则默认情况下会添加到输出中。
下面的代码片段显示了该函数是如何工作的:
- 通过语言模型传递字符串序列来创建
doc对象。 - 如果特殊记号出现在序列中,则将它们添加到最终结果中。
- 迭代文档的名词组块,如果所有组块的标记都在期望的
pos_tag列表中,则向结果添加一个名词组块。 - 最后,我们迭代所有的单个标记,并添加那些在期望的
pos_tag集合中的标记,而不是语言模型的默认停用词列表的一部分。如有需要,可将自定义停用词追加到该列表中。
然后,该函数返回结果变量中结束的所有唯一单词的列表。
使用 Spacy 的关键字提取代码
带有 FuzzyWuzzy 的模糊字符串匹配
图片来源 u/lawlesskenny
当人类打字时,错别字和错误是不可避免的。在关键字搜索/匹配的环境中,这是一个问题,但是使用模糊匹配算法可以很好地解决这个问题。
Python 包 FuzzyWuzzy 实现了一个非常有效的模糊匹配算法: Levenshtein 距离。
Levenshtein Distance 是一个公式,用于计算将源单词 S 转换为目标单词 T. 的成本。该算法会惩罚需要进行许多更改才能转换为目标单词的源单词,并支持需要较小转换的单词。关于 FuzzyWuzzy 如何实现这种检查的详细而直观的解释,请参见 Luciano Strika 的文章。
[## FuzzyWuzzy:如何在 Python 上测量字符串距离
FuzzyWuzzy 是一个 Python 库,用于测量两个字符串之间的相似性。以下是您开始使用它的方法…
towardsdatascience.com](/fuzzywuzzy-how-to-measure-string-distance-on-python-4e8852d7c18f)
使用 FuzzyWuzzy
模糊匹配实现起来非常快。从包中导入ratio会导入默认的 Levenshtein 距离评分机制,而process.extractBests()允许我们计算一系列目标的 Levenshtein 距离,并返回高于定义的截止点的结果。为了获得最佳匹配结果,您可能需要对score_cutoff参数进行微调。
模糊匹配实现
烧瓶应用
差不多了,现在剩下要做的就是把所有东西都打包到两个非常简单的烧瓶端点中。对于下面的要点,请确保导入模糊匹配器和关键字提取服务,或者在 app.py 本身中声明它们。
如果你是 Flask 的新手,我建议看看他们的文档快速入门指南。它们提供了如何启动和运行的简单、最小的示例。
该应用程序有两个端点:
api/keywordsapi/fuzzy-matches
两个端点都接收 POST 请求,因此参数通过请求体传递给每个端点。
您可能还注意到,我们使用前面提到的子流程模块在应用程序内部以编程方式调用 Spacy CLI。如果您需要将它部署到云服务,并且忘记通过 CLI 手动下载模型,这将非常有用。
我们在两个端点之外加载语言模型,因为我们希望这个对象在我们的服务运行时无限期地持久,而不必在每次发出请求时都加载它。这使得添加使用 Spacy 功能的新端点变得容易,因为它们可以共享相同的语言模型,该语言模型可以作为参数提供。
应该就是这样了,在项目目录的命令行中运行下面实现的代码flask run,这应该会在您的本地主机上启动 API。
您可以在 Postman 中测试端点,以确保它们的行为符合预期。


两个端点的邮递员请求
如果您想将 API 部署到云服务,如 Heroku,请查看:
[## 在 Heroku 上部署 Python Flask 应用程序
在我之前的文章中,我描述了我是如何使用 Flask 开发 API 的。我简单讲了一下我是如何主持…
medium.com](https://medium.com/the-andela-way/deploying-a-python-flask-app-to-heroku-41250bda27d0)
上面的文章是几年前的了,原理还是一样的,你也可以直接在 heroku 的网站上设置一个应用程序,然后通过 CLI 推送。
结论
这应该有望帮助您启动并运行这个简单的 API。我发现在很多情况下,我需要这样一个简单的服务来处理文本输入或执行某种 NLP 任务。这个设置希望有所帮助的是,它应该很容易允许添加额外的空间 NLP 服务作为端点,而无需任何重大更改。
如果你有任何问题或者在我提供的任何代码中发现了一个错误,请告诉我,感谢阅读!
[1]空间文档。模特。https://spacy.io/models
[2]空间文档。文档对象。https://spacy.io/api/doc
用最少的代码行构建一个 LIME explainer 仪表板
实践教程
Flask、Plotly Dash 和 Streamlit 的比较,以构建仪表板,为分类结果提供石灰解释

图片来源:Pixabay 上的奇摩诺
在早先的一篇文章中,我描述了如何使用 LIME(LocalIinterpretableMmodel-agnosticEexplanations)来解释一个细粒度情感分类器的结果。概括地说,以下六个模型用于在斯坦福情感树库(SST-5)数据集上进行细粒度情感类别预测。
- 基于规则的模型:文本块和 VADER
- 基于特征的模型:逻辑回归和支持向量机
- 基于嵌入的模型: FastText 和 Flair
使用线性工作流来分析和解释使用每种方法的情感分类结果。每个模型被训练成 5 类情绪(1 到 5),1 是“强烈负面”,3 是“中性”,5 是“强烈正面”。

这篇文章的目标是展示如何构建一个解释器仪表板(使用三个框架中的任何一个),它接受一个经过训练的模型,并为模型做出的预测输出及时的解释。
示例石灰说明
简而言之,LIME 生成一个包含可视化效果(作为嵌入式 JavaScript)的解释对象,该对象可以输出到一个 HTML 文件,然后可以在任何浏览器中打开。LIME 的典型输出如下所示。

为什么要构建交互式仪表板应用程序?
要使用 LIME 解释分类器的结果,每次需要解释时都必须写出单独的 HTML 文件,这可能很麻烦。接受用户输入的交互式仪表板是实时快速迭代多个测试样本的非常有效的手段,为用户提供即时反馈。此外,拥有一个仪表板允许非技术用户(他们可能知道也可能不知道如何执行 Python 脚本)能够按需做出自己的时间解释。
以下部分展示了我们如何使用三种不同的框架构建 LIME explainer 仪表板:Flask、Dash 和 Streamlit。
解释器类
为了方便地引用每个分类器的预测方法,下面的面向对象的模板被应用来支持代码重用,在项目的 GitHub repo 中可用。简而言之,定义了一个 Python 类,它接受由 LIME 生成的变量列表(标记空白的随机文本样本),然后我们将每个样本的类概率输出为一个 Numpy 数组。
一旦每个变化的类概率被返回,这可以被馈送到LimeTextExplainer类(如下所示)。启用词包(bow)意味着 LIME 在生成变体时不考虑词序。然而,FastText 和 Flair 模型分别考虑 n 元语法和上下文排序进行训练,因此为了模型之间的公平比较,SST-5 上的所有解释都禁用了bow标志选项。
LIME 解释器返回的exp对象是通过 LIME 内部的explain_instance方法,将本地线性模型的预测(以数字形式)转换成可视的、可解释的形式。这可以输出为 HTML。
以下部分描述了如何将所有这些功能封装到一个交互式仪表板应用程序中。
选项 1:烧瓶
LIME explainer 仪表板的烧瓶版本如下所示。用户输入一段文本,选择要为 LIME 生成的随机样本的数量,然后使用下拉菜单从给定的分类器列表中进行选择。点击Explain results!按钮,然后生成一个 LIME 解释 HTML 对象,它呈现在一个 HTML Iframe 中。

虽然 Flask 不是一个数据仪表板工具(它是一个 WSGI web 框架,最初是围绕 Werkzeug 和 Jinja 的包装器),但它提供了一个简单的基于插件的架构,开发人员可以从这个架构中为复杂的应用程序构建和扩展接口。Flask 的关键优势在于它在生产环境中的健壮性,以及在 Python 生态系统中围绕它的大量扩展。
要使用 Flask 构建 LIME explainer 仪表板,需要了解以下技术:
- HTML/JavaScript :页面的整体结构和内容是用 HTML 定义的。任何需要基于字段值或用户输入触发的操作都需要使用 JavaScript 来定义,要么通过 HTML 文件本身,要么从外部源加载。
- CSS :使用 CSS 文件定义页面的样式和布局。
- Jinja2 :这是一个模板引擎,从 Python 中动态生成页面的 HTML。出于安全原因,这是必要的(不使用模板和传递未转义的静态 HTML 会导致跨站点脚本攻击)。模板引擎由 Python 控制,最终的 HTML 使用 Flask 方法呈现。
Flask 应用程序:目录结构
Flask 应用程序使用的目录结构如下所示。所需的样式在static/style.css文件中用 CSS 配置,要渲染的 HTML 模板在templates/index.html中定义。任何经过训练的情感分类器模型都会进入models目录。解释器类在lime_explainer.py中定义,烧瓶路径在app.py中定义。

烧瓶石灰解释器应用程序的目录结构
对于这个用例,Flask 中的应用程序代码是用最简单的方式编写的。定义了两条路线(默认路线'/'和时间结果路线'result')。请注意,结果路由使用了一个POST请求,这意味着它只在用户向应用程序输入一些信息并与之交互时才生成 HTML(通过 Jinja)。
Flask LIME explainer 应用程序的代码可从 GitHub 获得:
这个报告包含一个用 Flask 编写的交互式应用程序的初始原型,它解释了…
github.com](https://github.com/prrao87/fine-grained-sentiment-app)
选项 2:破折号
设计 LIME 仪表板的另一种方法是使用 Plotly 的 Dash 库。Dash 是一个用 Python 构建分析性 web 应用程序的框架。使用 Dash 的好处是双重的:开发人员可以只使用 Python(不需要 JavaScript)设计应用程序,并且他们可以通过 CSS 完全控制应用程序的设计和结构。下面演示了一个使用 Dash 编写的 LIME explainer 应用程序。就像 Flask 应用程序的情况一样,单击Explain results按钮生成一个 LIME 解释 HTML 对象,该对象通过 Dash 的 HTML Iframes 包装器呈现。

Dash 应用程序:目录结构
Dash 应用程序使用的目录结构如下所示。使用 CSS 在assets/style.css文件中配置所需的样式。与 Flask 示例不同,在app.py中,应用程序的 HTML 布局和路线/交互是使用纯 Python 定义的。任何经过训练的情感分类器模型都会进入models目录。解释器类在lime_explainer.py中定义。

Dash LIME 解释器应用程序的目录结构
Dash 应用程序代码的关键组件如下所述。首先是应用程序布局,它是使用 Dash 的 HTML 包装器用 Python 编写的。
常见的 HTML 对象,如标题、标签、文本输入和 Iframes,可以使用 Python 结构轻松添加,如图所示。
下一个组件是回调,这是一段反应式的功能性代码,允许开发人员观察、修改和更新 UI 中任何组件的属性。在 Dash 中,回调是使用 Python 的装饰语法定义的。回调是编码应用程序交互性的非常强大的方法,因为它们跟踪按钮点击和数据更新的状态。LIME 解释器中使用的主要回调如下所示。
按照上面的构造,我们传递用户的按钮点击(或者是“提交”或者是“清除”按钮),以及下拉菜单的状态,在文本输入中输入的样本数量,以及我们想要预测其情感的文本样本。这里跟踪每个文本字段的状态(而不仅仅是值)是很重要的——它允许我们将回调的执行与按钮点击联系起来,而不是每次文本输入中的值更新时都执行它。
Dash LIME explainer 应用程序的代码也可以在 GitHub 上找到:
这个报告包含了一个现有的交互式应用程序的 Plotly Dash 等价物,它解释了…
github.com](https://github.com/prrao87/fine-grained-sentiment-app-dash)
选项 3:简化
另一种选择是使用 Streamlit 来构建解释器应用程序。这是目前最快的方法,需要非常基础的 web 开发知识和最少的代码行。与 Flask 和 Dash 方法不同,Streamlit 应用程序使用自己的样式和布局(不可能通过 CSS 进行定制,至少不能使用传统方法)。Streamlit LIME explainer 应用程序如下所示。

Streamlit LIME 解释器应用程序的目录结构

因为 Streamlit 是为帮助快速创建和共享 web 应用程序而从头设计的,所以 LIME dashboard 应用程序有一个非常简单的目录结构。web 应用程序的所有代码都写在一个文件中,app.py -这包括小部件、结构、交互和所有用户输入来进行时间预测。这种设计的显著之处在于,即使将所有这些功能都塞进了一个文件中,它仍然非常简洁(大约 40 行代码!).因此,我们只对特定于应用程序的实体使用单独的目录,比如模型和数据。
Streamlit 仪表板的完整代码如下所示。
标题是用 markdown 语法编写的。请注意,因为 Streamlit 的 API 是为速度和易用性而设计的,所以它不像 Flask 和 Dash 那样允许轻松访问底层 HTML。因此,在这种情况下,我们需要显式地使用原始 HTML 字符串的不安全呈现(使用unsafe_allow_html关键字)来获得居中对齐的标题。然后使用一个 Streamlit HTML 组件呈现 LIME explainer 的 HTML 输出,这是一个定制组件,在 Iframe 中显示 HTML 字符串。
和往常一样,Streamlit LIME explainer 应用程序的代码可以在 GitHub 上获得:
此回购包含现有交互式应用程序的 Streamlit 等价物,它解释了…
github.com](https://github.com/prrao87/fine-grained-sentiment-app-streamlit)
部署
出于本文的目的,这三个应用都是使用 Heroku 部署的,这是一个 PaaS 系统,允许开发者在云上构建、运行和操作应用。用于构建应用程序的三个框架都有很好的 Heroku 部署指南,如下所示。
- Flask: 将 Flask 应用程序部署到 Heroku
- Dash: 部署 Dash 应用
- Streamlit: 如何在 Heroku 上部署 Streamlit
然而,使用生产级 WSGI web 服务器,如 gunicorn 和负载平衡器,如 Nginx ,部署 Flask 或 Dash 应用程序也相对简单。在部署期间,Nginx 充当位于 web 服务器前面的反向代理,以高度的可靠性处理大量请求。类似地,Streamlit 还提供了一种使用 Docker 和/或 Nginx 的组合来手动部署应用的方法。
关于 Python web 框架中可伸缩性的一个注释
web 服务器网关接口(WSGI)是作为 Python web 框架与 Web 服务器交互的标准而开发的一个 Python 规范。有了这样的系统,开发人员可以轻松地将 Nginx 之类的服务放在 Python web 应用程序的前面(例如,用 Flask 或 Dash 编写),作为将所有请求转发给 web 应用程序的反向代理。兼容 WSGI 的服务器的一个关键特性是它们是同步的。这意味着每个请求阻塞服务器,直到它收到来自应用程序的响应,称为阻塞操作。WSGI 服务器合并可伸缩性的典型方式是通过使用多线程,其中为每个请求创建一个新线程,以便能够同时处理多个请求。然后,这与运行 web 服务器的多个工作进程相结合,这确实具有很好的伸缩性,但是受到给定机器上可用的物理内核数量的限制。
像 Flask 和 Dash 这样的框架所使用的 WSGI 方法,如果有非常大量的请求进入,就可以在伸缩方面达到极限。在生产系统中解决这个问题的方法是水平扩展,即添加越来越多的服务器,并使用类似 Nginx 的负载平衡服务,这些服务可以在高请求量期间在所有服务器之间平均分配负载。
最近的 Python web 应用框架,如 Streamlit,完全依赖于不同的并发系统。Streamlit 在幕后使用了一个 Tornado web 服务器,它被从头设计为使用异步事件循环。在这个系统中,使用了一个单线程,它实现了按照到达顺序执行的非阻塞功能。这种方法可以很容易地在 web 应用程序中实现非常高的并发度,这在很大程度上依赖于 I/O 绑定操作的应用程序中,可以真正帮助扩展系统,以同时处理大量请求。
和往常一样,没有单一的规则来决定哪种并发方法更好。根据确切的用例以及手边的应用程序,基于 WSGI 或异步事件循环驱动的服务可能是合适的选择。
延伸阅读: WSGI 已经不够用了 —第一、二、三部
什么时候使用每个框架最有意义?
本节讨论每个框架最适合当前任务的情况。
瓶
Flask 的强大之处在于它允许开发人员使用任何前端工具的组合来创建 web 应用程序。这包括表单输入扩展,如 WTForms 和 Flask-Login ,以及 JavaScript 可视化库( Highcharts 或 D3 )。此外,Flask 通过 HTML、CSS、jQuery 和 Bootstrap 为开发人员提供了对底层页面结构和用户交互的完全访问,允许基于项目需求构建非常复杂的应用程序的巨大灵活性。
关于本文中显示的 LIME explainer 仪表盘,Flask 是以下任何一种场景的绝佳选择:
- 该应用程序由一个在 JavaScript、HTML 和 CSS 以及不同的 HTTP 请求方法(GET、POST 等)方面拥有专业知识的团队编写。)
- 该应用是一个更大的仪表板的一部分,由前端的 JavaScript 框架提供支持
- 处理和服务数据的多个 RESTful 端点已经存在(在这之后,LIME explainer 可以作为另一个端点被写入前端)
破折号
对于主要在 Python 环境中工作的应用程序需要高度可定制性的开发人员来说,Dash 是一个很好的选择。许多强大的前端可视化工具(来自 Plotly.js JavaScript 库)都是现成的,允许开发人员主要关注应用程序的样式和添加用户交互。因为 Dash 构建在 Flask 之上,所以它遵循与 Flask 相似的部署策略,这使得已经有在生产中实现 Flask 应用的经验的团队可以非常容易地使用它。
一般来说,在以下任何一种情况下,Dash 都是构建 LIME explainer 仪表板的绝佳选择:
- 需要编写应用程序来与现有的 Flask 应用程序集成
- 开发和部署该应用程序的团队在 Python 方面经验丰富(但在 JavaScript 方面不太精通)
- 仪表板需要很好的定制程度(Dash 允许开发者访问底层 CSS)
细流
作为生态系统的相对新人,Streamlit 在数据科学家需要通过交互式应用程序与更大的团队快速分享他们的工作的情况下大放异彩。对于数据科学家个人来说,它也非常有用,可以快速、交互式地探索数据集或模型对单个样本的性能。
对于 LIME explainer 仪表板,Streamlit 是在以下任何场景中使用的一个很好的替代方案:
- 该应用程序是由一个团队(或个人)编写的,只有很少的 web 开发经验
- 应用程序需要在最短的时间内快速构建,并尽可能使用最少的代码行
- 开发人员希望花更多的时间构建交互式工具,尽可能少的时间定制应用程序的外观
结论
这篇文章强调了构建 LIME explainer 交互式仪表板应用程序的三种不同方法。Streamlit 是所有选项中最简单、最容易学习的。Flask 需要最大的前期时间投入,学习各种组合在一起的部分(HTML、CSS、jQuery/JavaScript、Jinja2 和 HTTP 请求方法)。Plotly Dash 很好地介于 Flask 和 Streamlit 之间,就复杂性和启动并运行仪表板的初始工作而言。根据承担此类项目的团队的组成和技能,这三个选项中的任何一个都可能是最合适的。
构建如图所示的 LIME 仪表板的主要原因是允许非数据科学家的人检查 NLP 分类器的结果。至少在某种程度上,提供一种交互式方法来动态测试单个样本的结果可以帮助诊断 NLP 模型的问题,并提高模型的可解释性。为您自己的用例从每个回购(如下所示)中体验和定制代码的乐趣吧!
原载于 2020 年 10 月 24 日https://prrao 87 . github . io。
用 Dash 构建机器学习模拟工具
了解如何使用 Plotly/Dash 库构建交互式仿真工具,并动态探索您的机器学习模型行为以提高其可解释性。

丹·洛马尔在 Unsplash 上拍摄的照片
你做到了!这一切都始于您的同事提出的一个业务问题,您经历了数据整合、清理、特性工程和建模的黑暗山谷。您的模型的稳健性已经过检查,您希望分享您的发现。
然而,并不是每个人都熟悉 RMSE、混淆矩阵或 Shapey 值…
例如,行业中的运营团队每天都面临着优化生产或供应链的挑战,机器学习提供了一种新的方式来理解复杂的流程行为……只要它可以转化为可理解的分析。当分享人工智能带来的一些见解时,Python 笔记本可能不是最佳选择!

除了模型预测能力本身,团队总是热衷于了解在众多相关生产参数中最重要的因素是什么,以及每个因素如何影响模型的行为。
Dash libraries 为您提供了一种创建动态仪表板的方法,可通过具有交互功能的 Web 浏览器访问。
这个概念非常简单:
- 您创建一个. py 脚本,其中您的“经典”机器学习任务与编码的网页布局设计结合在一起,从 HTML 代码中关闭。
- 当执行时,python 脚本在本地地址( http://127.0.0.1:8050/ )上生成一个动态 web 页面,组件在此进行交互。

图标由 像素佛 和Pixelmeetup(来源:flaticon.com)
你想得到一个快速演示吗?开始了。
首先,我们需要设计一个“看起来像”的工业用例!Scikit-learn 的“make_regression”将生成我们的数据源。我们将微调一些功能,以获得示例中的真实人物:
数据生成和建模阶段
一旦“机器学习”任务完成,我们仍然需要准备要在我们的网络浏览器上显示的动态信息。对于此示例,我们将创建:
- 显示模型特征重要性的条形图
- 三个滑块允许用户更改三个最重要特征的值,并了解它们对模型预测的影响
您可能已经注意到条形图的创建与 Plotly 中使用的相似,除了。未调用 show()函数。原因是图表将在“布局”部分呈现。
“布局”一节(下面)要求不熟悉 Python 和 HTML 的用户进行一些练习。
这里的理念是将 HTML 元素(由 htm.xxx 调用)与动态破折号组件(dcc.xxx)结合起来。
我们将保持这个例子非常简单:
**<H1> Title
<DCC> Features Importance Chart
<H4> #1 Importance Feature Name
<DCC> #1 Feature slider
<H4> #2 Importance Feature Name
<DCC> #2 Feature slider
<H4> #2 Importance Feature Name
<DCC> #2 Feature slider
<H2> Updated predictions**
接下来是脚本中“最棘手”的部分: app.callback 函数允许您封装一个标准的 python 函数,这样它就可以与上面设计的 web 页面组件进行交互。其机理可以简化如下:
[**@app**](http://twitter.com/app)**.callback**(Output_on_webpage,
Input_1_from_webpage,
Input_2_from_webpage,
Input_3_from_webpage)**python_function**(Input_1, Input_2, Input_3): Output = model_evaluation([Input_1, Input_2, Input_3]) return Output
您可能已经注意到,我们在这里认为只有三个最重要的特性值得更新。因此,当模型评估阵列时,我们考虑了所有其他特征的平均值。这显然是出于简化目的的设计选择。
然后“瞧”!
我们打开命令提示符并键入" python dashboard.py "
(base) PS C:\Users\...\> **jupyter dashboard.py**
* Serving Flask app "__main__" (lazy loading)
* Environment: production
* Debug mode: off
* Running on [**http://127.0.0.1:8050/**](http://127.0.0.1:8050/) (Press CTRL+C to quit)
现在,我们只需在 打开我们最喜欢的网络浏览器 http://127 . 0 . 0 . 1:8050/并检查结果:

每次滑块移动,app.callback 函数都会运行 python 脚本来重新评估预测!
完整的脚本存储在 GitHub 上的这里。
正如您所想象的,让非数据科学家团队与模型进行交互并理解其行为成为了一个非常强大的工具。这也是测试模型准确性的一个非常好的平台:运营团队将能够检查并确认模型的行为确实符合他们的现场经验。
在我们结束这篇文章之前,有几个建议:
- 如果您不熟悉 Plotly 和 Dash,您应该从标准 Plotly 图表开始训练自己(步骤解释得非常清楚):
Plotly 的 Python 图形库制作出交互式的、出版物质量的图形。如何制作线图的示例…
plotly.com](https://plotly.com/python/)
- 下面的在线课程设计得非常好,它将指导你学习 Python 基础知识(Pandas / NumPy)、Plotly 图表语法以及 Dash 设计。我不推荐它:
[## 互动课程:使用 Python 仪表盘和 Plotly & Dash
本课程将教授您使用 Python 创建交互式仪表盘所需的一切知识
www.udemy.com](https://www.udemy.com/course/interactive-python-dashboards-with-plotly-and-dash/) [## 皮埃尔-路易·贝斯康德关于媒介的文章
数据科学、机器学习和创新
pl-bescond.medium.com](https://pl-bescond.medium.com/pierre-louis-besconds-articles-on-medium-f6632a6895ad)**
使用 OpenCV 和 Python 构建运动热图视频
OpenCV 是一个强大的图像和视频操作库,在这个故事中,我想创建一个运动热图,用于检测运动,物体或人的流动方向,例如,在投影公共区域时为建筑师提供帮助。

本指南中描述的最终结果的屏幕截图。
简介:
OpenCV,或(开源计算机视觉)是英特尔在 1999 年开发的主要针对计算机视觉和实时视频操作的库,它是用 C++编写的,但它支持不同的语言,其中包括 Python。
工作流程:
这个程序是基于一种被称为高斯背景减法的技术。这种技术广泛用于用稳定的摄像机检测运动物体。
背景减法创建一个表示帧背景(图像的静态部分)的遮罩,并且对于每一帧,它减去前一帧。
让我们对该算法如何工作的两个主要步骤有一个简单的概述:
- 背景初始化:在这个第一步中,通过冻结第一帧来计算背景的模型。
- 更新:在该第二步骤中,从前一帧中减去下一帧,因此,如果在两帧之间发生了变化(运动),则帧的差异将反映该变化,这可以通过应用过滤器来实现。
以下是应用于从城市摄像机录制的短视频的背景遮罩示例:

代码:
代码从读取输入视频文件开始,并初始化一些需要的变量:
capture = cv2.VideoCapture('input.mp4')background_subtractor = cv2.bgsegm.createBackgroundSubtractorMOG()
length = int(capture.get(cv2.CAP_PROP_FRAME_COUNT))
然后,for循环开始遍历帧:
for i in range(0, length):
ret, frame = capture.read()
# If first frame
if first_iteration_indicator == 1:
first_frame = copy.deepcopy(frame)
height, width = frame.shape[:2]
accum_image = np.zeros((height, width), np.uint8)
第一个if块检查该帧是否是视频的第一帧,这样做是为了初始化我们的背景,以便进行背景减法,然后用对应于该帧尺寸的尺寸初始化accum_image阵列。
filter = background_subtractor.apply(frame) # remove the background
threshold = 2
maxValue = 2
ret, th1 = cv2.threshold(filter, threshold, maxValue, cv2.THRESH_BINARY)
accum_image = cv2.add(accum_image, th1)
color_image_video = cv2.applyColorMap(accum_image, cv2.COLORMAP_HOT)
为了去除少量的运动,如风、小鸟飞翔或一些噪音,一个threshold和maxValue一起应用到遮罩上。
屏蔽的结果然后被添加到accum_image阵列,该操作对每一帧执行。结果由accum_image数组组成,用于存储视频中发生的每个动作。
此外,因此,在最后,当已经对每一帧完成了先前描述的操作时,色彩映射表被应用于遮罩,并且遮罩与当前帧合并。

从上到下,从左到右:当前帧、当前最终帧、过滤后的当前帧、应用了从帧 0 开始的所有遮罩的帧。
更进一步,可以制作一个视频,显示热图逐帧淡入淡出。为了实现这一点,每一帧都被导出,并且再次使用cv2,通过将所有帧合并在一起来生成视频:
video = cv2.VideoWriter('output.avi', fourcc, 30.0, (width, height))for image in images:
video.write(cv2.imread(os.path.join(image_folder, image)))
cv2.destroyAllWindows()
最终结果:

**I have a newsletter 📩.**Every week I’ll send you a brief findings of articles, links, tutorials, and cool things that caught my attention. If tis sounds cool to you subscribe.*That means* ***a lot*** *for me.*
**[## 米尔斯形式
编辑描述
无情-创造者-2481.ck.page](https://relentless-creator-2481.ck.page/68d9def351)**
用 Python 构建运动检测报警系统
使用 OpenCV 进行运动检测的初学者友好指南
在我之前的一篇关于 Open-CV 的文章中,(10 行中的人脸检测 ) ,我们探讨了一幅图像或视频中人脸检测的基础知识。在此基础上,我们将看到如何检测帧中的任何移动对象。当你外出度假时,你可以使用这种运动检测逻辑编写一个程序,然后发出警报或向你的手机发送消息。在本文中,我们将重点关注使用open-cv识别和跟踪来自网络摄像头的视频提要中的任何移动对象,并使用离线文本到语音模块pyttsx 3库播放音频消息。让我们看看它是否足以吓跑窃贼!

概观
这个程序中有两个独立的模块,你可以根据你要实现的想法单独使用:
1.检测运动(使用 OpenCV)
2。播放音频/文本到语音(使用 pyttsx3)
我们将从使用 pip 安装以下 Python 库开始。
pip install pyttsx3
pip install pywin32
pip install numpy
pip install opencv-python
方法
方法很简单。当程序启动时,我们将捕获一个名为 baseline_image 的图片。这是没有任何物体/入侵者的图像。我们的程序将不断比较新的帧和这个基线图像。如果没有人进入或退出框架,将不会有任何区别。然而,当有人进入画面时,图像的内容会有所不同,如果这种差异超过某个阈值,我们的程序会将其视为入侵者并播放音频。
1.检测运动
为了检测运动,我们将使用 Open-CV 模块。我们从 baseline_image 开始,它是在没有任何移动对象的情况下捕获的帧。摄像机一启动,第一张图像就被设置为我们的 baseline_image,这意味着当我们的程序第一次启动时,我们不希望有移动的物体。接下来,当有人进入该帧时,该帧中的某些像素将会不同。我们使用“cv2.absdiff”方法推导出这种差异。
我们将采取几个步骤来实现这一目标。
1 。捕捉基线 _ 帧(无对象)
1.1 将帧转换为灰色
1.2 平滑帧以去除噪声2 。捕捉新帧(带对象)
2.1 将帧转换为灰色
2.2 平滑帧以去除噪声3 。计算两帧之间的差异
3.1 如果差异大于阈值,则假定检测到运动
3.2 否则假定没有检测到运动
首先,我们将图像转换为灰度,并使用低通滤波器(LPF)柔化(模糊)图像。LPF 通常用于图像处理以平滑图像(例如:-用于皮肤平滑、背景模糊),而高通滤波器(HPF)用于锐化图像(例如:-锐化眼睛和其他细节)。如果你曾经使用过像 Photoshop/GIMP 等图片编辑工具。,你一定很熟悉这个。这有助于通过消除噪声来提高精度。为此,我们使用了高斯布鲁。GaussianBlur 之前和之后的图像如下所示。

如果你仔细观察图像的底部中心,你会注意到在“之前”图像中我手指的较暗一侧,我的手指有不同程度的灰度(一些区域没有其他区域暗)。然而,在“后”图像中,整个较暗的一面几乎是灰色的一种变体。模糊的程度由我们自己决定。这里我有高斯内核大小宽度和高度为(25,25)和一个标准偏差 0。宽度和高度应该是正奇数。可以把它想象成改变图像编辑工具中模糊量的滑块。执行此操作的代码如下所示。
**#Gray conversion and noise reduction (smoothening)**
gray_frame=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
gray_frame=cv2.GaussianBlur(gray_frame,(25,25),0)
下一步是推导基线和新帧之间的差异。我们将这两个图像传递给 cv2.absdiff()函数。这是使用一种叫做 图像阈值 的方法转换成的二进制图像,也就是说,如果一个特定的像素值大于某个阈值(我们在这里指定为 35),它将被赋予白色的值(255)或者黑色的值(0)。现在我们有一个只有两种像素的图像(纯黑或纯白,中间没有)。这样做是为了使我们能够识别检测对象周围的轮廓区域。我们将用它在框架中的对象周围画一个绿色的方框。
现在我们将在我们的二值图像中找到所有的轮廓。 轮廓 简单来说就是沿着具有相同颜色或强度的周界或边界绘制的曲线。本质上,它会在黑色背景上的白色区域周围绘制一条曲线。它期望背景为黑色,前景对象为白色。使用 cv2.findContours()方法,我们将识别图像中的所有轮廓。该方法期望 3 个参数, (a) 图像, (b) 轮廓检索模式和 (c) 轮廓逼近方法。
该方法返回已识别轮廓的列表。我们使用 cv2.contourArea()方法过滤掉我们不感兴趣的小轮廓。cv2.boundingRect()返回左上角的(x,y)坐标以及包含特定轮廓的矩形的宽度和高度。然后我们画一个矩形在屏幕上显示它。
**#Calculating the difference and image thresholding**
delta=cv2.absdiff(baseline_image,gray_frame)
threshold=cv2.threshold(delta,35,255, cv2.THRESH_BINARY)[1]**# Finding all the contours**
(contours,_)=cv2.findContours(threshold,cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)**# Drawing rectangles bounding the contours (whose area is > 5000)**
for contour in contours:
if cv2.contourArea(contour) < 5000:
continue
(x, y, w, h)=cv2.boundingRect(contour)
cv2.rectangle(frame, (x, y), (x+w, y+h), (0,255,0), 1)
2.播放音频(文本到语音)
为了播放音频,我们将使用"pyttsx 3" python 库来将文本转换为语音。您可以选择自己的声音(男/女)、讲话速度和音量。下面分享了我在这里使用的一段示例代码。
import pyttsx3engine = pyttsx3.init()
voices = engine.getProperty('voices')
engine.setProperty('voice', voices[1].id)
engine.setProperty('rate', 150)
engine.say("Object Detected")
engine.runAndWait()
最终的输出程序存在于 Github 库中以供参考。您可能会注意到,播放音频的功能是在一个单独的线程中执行的。这样做是为了在播放音频警报消息时,视频馈送没有延迟。
让我们看看我们最终的工作版本是什么样的。
阿林多姆·巴塔查尔吉
在结论中,本文演示了如何使用 Python OpenCV 库来检测帧之间的差异,从而检测视频馈送中的运动对象。我们还探索了另一个 Python 库 pyttsx3,它可以将文本转换为语音,以及如何通过结合这两者来构建一个程序,在新对象进入框架时发送语音警报。我希望您发现本文中的信息很有用,并以自己的方式使用它。感谢阅读!
使用 Python OpenCV 在图像和视频中检测人脸的介绍。
towardsdatascience.com](/face-detection-in-10-lines-for-beginners-1787aa1d9127) [## 用 Python 生成 5 行二维码
也许在你的简历中使用它来链接到你的网站或 LinkedIn 个人资料
towardsdatascience.com](/generate-qrcode-with-python-in-5-lines-42eda283f325) [## 在 5 分钟内制作一个声控鼠标
Python 中语音识别和 GUI 自动化的初学者指南
towardsdatascience.com](/build-a-voice-controlled-mouse-keyboard-in-5-minutes-952bc8f101fc)
参考资料:
[1]图像过滤,https://docs . opencv . org/2.4/modules/imgproc/doc/Filtering . html
[3]了解轮廓,https://docs . opencv . org/trunk/D4/d73/tutorial _ py _ Contours _ begin . html
使用 Scikit-Learn、Flask 和 Heroku 构建一个电影推荐 API
创建您自己的电影推荐 API,供其他开发者在他们的应用程序或网站中使用

Noom Peerapong 在 Unsplash 上拍摄的照片
推荐系统无处不在。一些最好的例子是 YouTube、网飞、Spotify 。网飞和 YouTube非常依赖他们的推荐系统来让用户在他们的平台上停留更长时间。 Spotify 根据用户的兴趣向用户推荐精选的歌曲列表。推荐系统发挥关键作用的例子还有很多。
但是等等,什么是推荐系统?
简而言之,推荐系统是一种算法,旨在基于用户过去给出的偏好或评级向用户建议相关数据,或者基于项目的属性向用户建议相关数据。
要了解更多关于推荐系统的信息,请点击下面的链接
目标:-
建立一个基本的基于内容的电影推荐系统,用 Flask 做一个 API,部署到 Heroku。
随着本文的深入,我们将详细讨论基于内容的推荐系统、API 和 Heroku 。
现在,我们来看看这篇文章的内容。
内容:-
- 数据集描述
- 建立一个基于内容的推荐系统
- 使用 Flask 构建一个 REST API
- 在本地主机— 127.0.0.1 上测试
- 部署到 Heroku — API 上线
我们将逐步介绍这些主题,最后,我们将构建一个电影推荐 API ,任何人都可以使用它在应用程序或网站中向他们的用户提供相关的电影建议。
那么,让我们开始吧。

杰瑞米·毕晓普在 Unsplash 上的照片
1。数据集描述

弗兰基·查马基在 Unsplash 上拍摄的照片
关于数据集
我们首先需要的是数据。关于电影的数据,比如类型、演员阵容、剧情等等。在这个任务中,我从 Kaggle 获取了数据。我们有两个数据来源。
现在,由于我们想要一个非常基本的推荐系统来查看 API 在应用程序或网站中使用时的外观,因此我们根据我们的需要组合并修改数据集。
数据集的修剪和预处理部分是在我的一个 Jupyter 笔记本上单独完成的,这将在以后讨论。但是,如果您仍想了解修剪数据集所涉及的步骤,请访问下面的链接。
笔记本可能有点不整洁,因为它从来没有打算上网。因此,如果任何人都难以理解的话,我道歉。
下面是数据集的链接,该数据集将用于构建我们的基于内容的推荐系统。下载这个数据集,我们就可以开始了。
数据集概述
因此,我们的数据集中有 6477 部电影,具有以下属性:-
- 演员阵容:电影前三名男女演员
- 流派:电影的前 3 大流派
- 好莱坞和宝莱坞电影的 movie_id: TMDb 和IMDbid
- 原创 _ 标题:电影的标题
- 剧情:电影基本概况
我们已经准备好了数据集。让我们进入下一部分,即构建基于内容的推荐系统。
2。构建基于内容的推荐系统

好了,现在什么是基于内容的推荐系统?
基于内容的推荐的工作原理是,如果用户喜欢某个项目,那么我们根据项目的特征或属性向用户推荐类似的项目。所以在我们的例子中,如果一个用户喜欢一部特定类型的电影或者一个演员,那么我们就向用户推荐一部类似的电影。因此,如果用户已经观看了电影小丑,那么我们的推荐系统将预测与小丑相似的电影,或者如果我们考虑电影的演员阵容,与小丑具有相同演员阵容的电影。
现在我们对什么是基于内容的推荐系统以及它是如何工作的有了一个基本的概念,让我们来编码一下。
文件 1 — recommendation.py
导入所需的包
recommendation.py 中有 5 个函数。让我们逐一讨论它们。
i) get_data()
get _ data()用于获取电影的相关数据,并将数据集及其属性作为结果返回,以便进一步预处理。
- 第二行:我们使用 pandas.read_csv() 读取 movie_data.csv.zip 文件。
- 第 3 行:将所有电影的标题转换成小写字母。
- 第 4 行:返回数据集作为函数的结果。
get _ data()的返回值:-

ii)合并数据()
combine _ data()删除特征提取不需要的列,然后合并cast和 流派 列,最后返回combine列作为该函数的结果。
第 2 行:删除特征提取不需要的属性。
第 3 行:将两列演员和流派合并成一列。
第 5 行:我们有一个带有造型和流派值的组合列,因此我们从数据集中删除了单独存在的造型和流派列。
第 6 行:返回带有合并列的数据集。
combine _ data()的返回值:-

演员表和流派栏合并
在继续下一步之前,请浏览下面提到的主题及其链接。在我们进入下一部分,即 transform_data()之前,对这些主题有一个基本的了解将会很有帮助。
iii)转换数据()
transform _ data()取combine _ data()和plotcolumn fromget _ data()并应用 计数矢量器 和
- 第 2 行:为 CountVectorizer 创建一个对象,并使用 stop_words 参数开始删除英文停用词。
- 第 3 行:将计数矢量器对象计数拟合到 combine_data() 返回的值上,即 cast 和流派的组合列值。在这之后,我们得到一个稀疏矩阵,如我们在关于单词袋*的讨论中所示,带有每个单词的计数值。*

计数矢量器稀疏矩阵输出
- 第 5 行:为 TfidfVectorizer 创建一个对象,并使用 stop_words 参数开始移除英文停用词。
- 第 6 行:将tfidf 矢量器对象 tfdif 拟合到我们从 get_data()得到的 plot 列上。在此之后,我们得到一个稀疏矩阵*,如我们讨论的 Tf-Idf 矢量器所示,其中包含每个单词的值。*

tfidf 矢量器稀疏矩阵输出
- 第 8 行:我们将通过计数矢量器和 TfidfVectorizer 得到的两个稀疏矩阵组合成一个单一的稀疏矩阵*。*
- 第 10 行:我们现在对我们组合的稀疏矩阵应用余弦相似度*。*
- 第 12 行:返回作为 transform_data() 的结果生成的余弦相似度矩阵
transform _ data()的返回值:-

余弦相似性
我们将Tf Idf 矢量器 用于 图 列,因为Tf-Idf**将较低的值分配给特定文档中具有较高频率的词,而将较高的值分配给具有较低频率的词。
例如
在星际军阀灭霸瓦解了半个宇宙后,复仇者们必须重新团结起来,重振他们被击败的盟友,恢复平衡。
在这部来自 复仇者联盟 4:终局之战 的电影情节中,我们将赋予诸如 灭霸 和 复仇者联盟 等词语更高的价值,因为它们出现的次数更少,但在确定电影的主旋律方面具有更高的意义。
四)推荐 _ 电影()
推荐 _ 电影()需要四个参数。
-
标题:电影名称
-
数据:返回值为 get_data()
-
combine:combine _ data()**的返回值
-
transform:transform _ data()**的返回值
-
第 3 行:创建一个熊猫系列*,包含我们数据集中所有电影的索引。*

熊猫系列
- 第 4 行:在标题参数中获取传递给我们的推荐 _ 电影()*函数的输入电影的索引。*
例如,我们通过电影 Logan 作为我们的输入电影。这一行给了我们熊猫系列电影Logan*的索引。*

我们输入电影的索引
- 第 6 行:这里我们存储每部电影相对于输入电影的余弦值。
比如我们输入的电影是 黑暗骑士。 这行代码的作用是计算所有电影相对于我们输入的电影的余弦值。

关于黑暗骑士的余弦值
- 第 7 行:得到余弦值后,我们以逆序排序。正如我们从余弦相似性主题的简介中读到的,文档离源越近,余弦值越高。

相对于黑暗骑士排序的余弦值
在上面的图像中,我们看到了输入电影的所有余弦值。输入的电影将是最相似的,所以它的值是0.99。之后我们看到对于 索引 3 我们的余弦值是 0.530。 现在如果你把它和我们之前的熊猫系列输出 【黑暗骑士崛起】 处于 指数 3 不出所料这是最类似于 黑暗骑士 的电影。
- 第 8 行:我们需要输入电影的前 20 部电影。因此,我们存储了与输入电影最相似的 20 部电影

关于黑暗骑士的前 20 个余弦值
- 第 10 行:我们将按照余弦值排序的前 20 部电影存储在一个列表中。

20 大电影指数
- 第 12–14 行:在这几行中,我们将电影索引存储在它们各自的列中。

movie_id 及其索引

电影标题及其索引

电影类型及其索引
- 第 16 行:我们创建一个熊猫数据帧,以电影 Id、名称、类型*为列。*
- 第 18 — 20 行:我们在刚刚创建的熊猫数据帧中存储了所有 20 部与我们的输入电影相似的电影,即黑暗骑士*。*
- 第 22 行:返回推荐前 20 部电影的熊猫数据帧。
推荐 _ 电影()返回值为 黑暗骑士 :-

五)结果()
result()取一个* 电影的片名 作为输入,返回前 20 个推荐。*
- 第 2 行:将 movie_name 转换为小写,因为在我们的数据集中所有的电影都是小写。我们这样做是作为预防措施。如果用户同时用小写字母和大写字母输入电影名称,这不会有问题,因为我们的函数仍然会返回结果。
例如: 如果输入的是Logan或Logan或Logan**我们还是得到我们的推荐。**
- 第 4–6 行:我们存储 get_data()、combine_data()和 transform_data()返回的值。
- 第 8–9 行:检查输入电影是否存在于我们的数据集中。如果在我们的数据集中没有找到,那么我们返回没有找到电影。
- 第 11–12 行:如果我们的电影出现在数据集中,那么我们调用我们的 recommend_movies()函数并传递 get_data()、combine_data()和 transform_data() 的返回值以及电影名称作为函数的参数。
- 第 13 行:我们以 Python 字典格式返回电影结果。
结果的返回值():-

既然我们的推荐系统已经准备好了,让我们进入下一部分,即使用 Flask 构建一个 REST API。
3.使用 Flask 构建一个 REST API

Marvin Meyer 在 Unsplash 上拍摄的照片
烧瓶:-
为了理解文章的这一部分,我建议你对 Flask 有一个基本的概念。对于我们的任务,我们只需要了解一些初级功能。
要在您的系统上安装 Flask,请打开终端/命令提示符,键入 pip install Flask。 就这样,Flask 现在已经安装在你的系统上了。
要了解一个简单的 Flask 应用程序的基本知识,请点击下面的链接。
如果你喜欢视频讲座,请仔细阅读视频中关于烧瓶的简要说明。
现在,我们对 Flask 有了一个基本的概念,让我们进入下一个主题,即REST API。
REST API:-
我强烈建议你们对API和 API 的设计原则之一(即 REST API)有一个基本的了解。
浏览下面提到的链接。它将为您提供关于API和REST API 的基本概述。
如果你喜欢视频讲座,请仔细阅读 Telusko 提供的关于API和REST API 的简要说明。
要了解如何创建一个 REST API ,如果我们先编写一些基本的应用程序,并了解更多关于 GET 方法及其工作原理,这将非常有用。
下面提到的链接使用 Flask 和 GET 方法构建了一个 REST API 来向客户端显示数据。把这些代码写出来,理解基础知识,然后继续我们的 app.py 文件中的代码。
文件 2 — app.py
在这个文件中,我们将编写 Flask 应用程序,并使用我们之前构建的推荐系统。
导入所需的包
第 1 行:我们导入烧瓶类,然后请求*库发送 HTTPS 请求,最后我们导入 jsonify 以 JSON 格式返回我们的结果。*
第 2 行:我们导入 flask_cors 来为我们的 API 启用跨来源请求。
什么是跨来源请求?
跨源资源共享 ( CORS )是一种机制,允许从提供第一资源的域之外的另一个域请求网页上的受限资源。
要了解更多关于 CORS 的政策,请点击下面的链接。它解释了你需要知道的关于 CORS 政策的一切。
第 3 行:我们导入我们的推荐. py* 文件作为一个模块,在我们的 app.py 文件中使用它。*
烧瓶代码:-
- 第 1 行:我们创建了这个类的一个实例。第一个参数是应用程序的模块或包的名称。
- 第 2 行:我们使用 CORS() 方法在我们的 API 上启用 CORS 策略。
- 第 4 行:然后我们使用 route() decorator 告诉 Flask 哪个 URL 应该触发我们的函数。在这种情况下,我们使用带有基本 URL 的 /movie 端点。
- 第 5 行:现在,我们定义一个名为 recommend_movies() 的函数,它将用于返回前 20 个推荐。
- 第 6 行:在这一行中,我们从 recommendation.py 文件中调用 results() 函数,并将推荐存储在一个名为 res. 的变量中。使用request . args()将电影名称作为查询字符串传递给我们的 results() 函数,参数名称为 title。
- 第 7 行:最后我们将从 recommendation.py 接收到的结果以字典格式返回到 app.py 并转换成 JSON 格式返回结果。
- 第 9 行:这一行表示如果我们直接从终端/命令提示符调用我们的 app.py 文件,那么它将执行后面的内容。
- 第 10 行:我们在终端/命令提示符下直接调用我们的 app.py 文件后运行 app。当在localhost**上运行时,我们将端口号设置为 5000,并设置 debug=True 来追溯运行我们的应用程序时发生的任何错误。**
4。在 localhost — 127.0.0.1 上测试

现在,我们已经完成了编码部分,让我们在 localhost 上测试我们的应用程序,看看它是否工作。
如果你想用 Postman 测试我们的 API,那么从下面的链接下载。
如果你喜欢用浏览器而不是邮递员,你也可以用浏览器来测试。我们将对他们两个进行测试,你将会看到结果。
测试我们的 API:-
步骤— 1: 如果在 Windows 中,请打开命令提示符;如果使用 Linux,请打开终端。
步骤— 2: 使用命令行导航到存储数据集、 recommendation.py 文件和 app.py 文件的文件夹。
我们将文件存储在名为建议 2.0 的文件夹中。下面是我们的目录结构。****

我们的目录结构
开发应用程序时,所有文件和数据集都应该放在一个文件夹中,以便于使用。
步骤 3: 当我们在建议 2.0 文件夹中时,在命令行中键入以下命令。
****set FLASK_APP=app.py****
运行应用程序:-
****flask run****
执行完这两个命令后,我们将看到我们的应用程序运行在 localhost 上。

烧瓶应用程序启动并运行
步骤 4: 使用 Postman 或任何浏览器在 localhost 上测试我们的 API。
当我们将一部电影传递给我们的 API 时,让我们看看我们的结果。
邮递员:-

对洛根的建议
浏览器:-

对逝者的推荐****
我们已经在 localhost 上完成了对我们的 API 的测试,它工作得非常好。
让我们进入最后一部分,即将我们的 API 部署到 Heroku。
5。部署到 Heroku — API 上线

莱昂·塞伯特在 Unsplash 上拍摄的照片
GitHub 存储库:-
在我们进入部署部分之前,我们需要对 GitHub 有一个基本的了解。您应该能够创建一个新的存储库,添加文件,删除文件和在存储库中创建文件夹如果需要的话。
- 步骤 1: 创建一个存储库,可以使用您喜欢的任何名称。我已经把我的库命名为 BioScope,因为我和我的朋友们认为这是一个很酷的名字。

- 第二步: 创建过程文件
Heroku 应用程序包括一个 Procfile ,它指定了应用程序在启动时执行的命令。您可以使用 Procfile 来声明各种进程类型,包括:您的应用程序的 web 服务器。
要创建一个,在工作目录中打开一个名为 Procfile(无扩展名)的新文件,并粘贴以下内容。
****web: gunicorn app:app --max-requests 2****
我们添加了 max requests 来确保我们的服务器在每第二次请求我们的 API 后重启。这样做是为了确保我们在使用 API 时不会超过 Heroku 分配的 512 MB 的 RAM 限制。
- 第三步: 创建需求. txt
requirements.txt 文件将包含 flask 应用程序的所有依赖项。如果您不是在一个新的环境中工作,这个文件将包含您当前环境中的所有需求。
对于这个项目,你的 requirements.txt 至少应该包含:
****Flask==1.1.2
Flask-Cors==3.0.8
Flask-RESTful==0.3.7
gunicorn==20.0.4
joblib==0.13.2
jsonschema==2.6.0
pandas==0.25.1
pickleshare==0.7.5
requests==2.23.0
requests-file==1.4.3
scikit-learn==0.22.2
scipy==1.4.1
wcwidth==0.1.7
webencodings==0.5.1
Werkzeug==1.0.1****
将上述内容复制粘贴到您的 requirements.txt 文件中,并提交到存储库。
第四步:提交推荐. py,应用. py.
****第五步:在你的存储库中创建一个名为 dataset/ 的文件夹,提交 movie_data.csv.zip 文件。
我们的存储库结构应该是这样的:-

Jupyter 笔记本包含制作我们的 movie_data.csv.zip 文件所需的预处理部分。所以,这个文件夹是可选的。除此之外,所有其他文件和文件夹都是必要的。
- re commendation . py
- app . py
- requirements . txt
- Procfile
Note:以上所有文件都应该在工作目录级别,而不是在另一个文件夹中。
部署到 Heroku:-
我们可以使用 Heroku CLI 或 GitHub 部署我们的应用程序。在本文中,我们将讨论如何使用 GitHub 部署我们的应用程序。
步骤— 1: 在www.heroku.com**创建自由账户。**
****第二步:选择一个名称,点击“创建应用”,创建一个新的应用。这个名称并不重要,但它必须是唯一的。

****第三步:点击下面的 GitHub 图标,连接您的 GitHub 账户。

步骤 4: 搜索正确的存储库并单击连接。

第五步:滚动到页面底部,点击“部署分支”。

如果一切正常,您应该会看到这条消息。

如果出现问题,检查你的 requirements.txt ,删除给你带来问题的依赖项,然后再试一次。
部署后测试我们的 API
- 注意我们发送 GET 请求的链接。

最后,我们的电影推荐 API 现已上线。

任何拥有 Heroku 链接的人现在都可以访问电影推荐 API,并向他们的用户显示电影建议。
就这样,我们到了这篇文章的结尾。我希望你们已经学到了一些新的东西,我当然希望你们都使用这个 API 或者构建类似的东西。
我们刚刚构建了一个基本的 基于内容的推荐系统 。可以做的比这多得多,比如构建一个 协同推荐系统 或者甚至构建一个 混合推荐系统。我们会详细讨论这个问题,但那是另一篇博文的内容了。
API 链接:-
完整代码:-
你可以打:- 找到我
快乐阅读!!!
构建一个 MSSQL Docker 容器
使用容器数据库提升开发水平

轻巧、快速、方便
您可以不再等待数据库管理员允许您访问开发服务器,或者在您的计算机的锁定工作环境中筛选关于设置 MS SQL 数据库的无尽文档,并获得您真正需要的基本信息。可以接受请求并返回数据的 sql server。就是这样。你的 API 需要测试,你需要一个数据库。
在开发的开始阶段,您不希望花费数小时来配置 sql server 或处理原型项目的托管数据库。这是一个本地码头集装箱可以改变你的生活。
在这篇文章中
我们将基于mcr.microsoft.com/mssql/server图像构建一个 Docker 容器,以创建一个定制的 Docker 文件,该文件启动一个 SQL Server、创建一个数据库、创建一个表并用数据填充该表。本文是在 为角斗士之旅 app 构建. NET 核心 API 的背景下撰写的。
对于完成的 MSSQL Dockerfile 文件和脚本,请 访问我的 GitHub 。
非常感谢 : twright-msft 给他的明星码头工人形象。我的很多图片都是直接从他的回购中复制的。
测试图像
在我们疯狂地构建自定义 docker 文件之前,让我们下载并运行映像以确保它能够工作。确保您的系统上安装了 Docker 。
从命令行运行:
docker pull mcr.microsoft.com/mssql/server:latest
通过运行下面的代码运行图像并构建容器。指定环境变量,如密码和 SQL Server Express 的版本。
docker run \
-e 'ACCEPT_EULA=Y' \
-e 'SA_PASSWORD=Password1!' \
-e 'MSSQL_PID=Express' \
--name sqlserver \
-p 1433:1433 -d mcr.microsoft.com/mssql/server:latest
如果您运行docker container ls,您应该看到 sqlserver 容器在端口 1433 上运行。
进入容器

运行以下命令进入您的容器,并显示一个 bash 终端:
docker exec -it sqlserver "bash"
从容器命令行启动 sqlcmd。请注意,我们使用的密码与用docker run创建容器时使用的密码相同。
/opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P "Password1!"
您应该会看到一个1>,通知您现在在 sqlcmd 命令行上,并且可以与您的服务器进行交互!让我们编写一些 SQL 来创建一个数据库和一个表。
CREATE DATABASE heroes
GO
USE heroes
CREATE TABLE HeroValue (id INT, name VARCHAR(50))
INSERT into HeroValue VALUES (1, "Wonder Woman")
GO
现在,查询数据库以确保数据被正确写入:
SELECT * FROM HeroValue;
GO
成功!
写文档

我们可以从 bash 终端创建数据库并插入条目,这很好,但感觉还是有点“手动”让我们通过编写 3 个脚本来实现自动化,Dockerfile 将在创建容器时运行这些脚本。这些脚本是:
- entrypoint.sh —在启动时运行的脚本,它只是运行 import-data.sh 并启动 SQL Server。
- import-data.sh —运行一个调用 setup.sql、的 sqlcmd 和一个导入. csv 文件的 bcp 命令。
- setup.sql —创建数据库和表的 sql 脚本。
下面是引用这三个脚本的最终 Dockerfile 文件。不要担心,我们将更详细地介绍这一切是如何工作的!
Dockerfile 文件
FROM microsoft/mssql-server-linux:latest# Create work directory
RUN mkdir -p /usr/work
WORKDIR /usr/work# Copy all scripts into working directory
COPY . /usr/work/# Grant permissions for the import-data script to be executable
RUN chmod +x /usr/work/import-data.shEXPOSE 1433CMD /bin/bash ./entrypoint.sh
根据 MSSQL docker 文档,您必须在启动 SQL Server 的最终命令之前运行数据库定制。在我们的 entrypoint.sh 文件中,我们在启动服务器之前调用 import-data.sh。
entrypoint.sh
/usr/work/import-data.sh & /opt/mssql/bin/sqlservr
在创建容器时,entrypoint 将运行 import-data.sh 并启动服务器。Import-data.sh 为我们提供了两个 SQL Server 命令,以及一个非常必要的命令,用于在数据库启动时休眠 90 秒。在你等待或冥想的时候,喝杯茶。
导入-数据. sh
# wait for the SQL Server to come up
sleep 90s#run the setup script to create the DB and the schema in the DB
/opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P "Password1!" -i setup.sql# import the data from the csv file
/opt/mssql-tools/bin/bcp heroes.dbo.HeroValue in "/usr/work/heroes.csv" -c -t',' -S localhost -U SA -P "Password1!" -d heroes
第二个命令 sqlcmd ,运行 setup.sql,搭建我们的数据库。创建数据库后,它使用 bcp 从. csv 文件导入数据。
setup.sql
CREATE DATABASE heroes;
GO
USE heroes;
GO
CREATE TABLE HeroValue (id INT, name VARCHAR(50));
GO
使用您的 docker 文件构建图像

Randy Fath 在 Unsplash 上拍摄的照片
通过运行以下命令,标记您的映像 mssql:dev 并进行构建:
docker build -t mssql:dev .
完成后,使用docker run运行映像。这几乎与我们的第一张docker run完全相同,除了我们已经将图像更改为我们新创建并标记的mssql:dev图像。
docker run \
-e 'ACCEPT_EULA=Y' \
-e 'SA_PASSWORD=Password1!' \
-e 'MSSQL_PID=Express' \
--name sqlserver \
-p 1433:1433 \
-d mssql:dev
当创建了映像并且我们收到确认映像 ID 时,访问容器以确认它正在工作。
docker exec -it sqlserver "bash"
从容器命令行,访问英雄数据库。
/opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P "Password1!" -d heroes
查询数据以确保其插入正确。出于某种原因,当我运行它时,它返回一个空白值块,以及最后一个值。但是我已经通过从 C#运行查询确认了所有的值都在那里。如果有人知道为什么没有显示所有的值,我很想知道。
SELECT * FROM HeroValue;
GO
就是这样!现在,您已经拥有了一个 SQL Server 数据库,可以随时轻松配置和启动!
您可以通过运行以下命令来终止容器:
docker kill sqlserver
用您的docker run命令重启您的容器,您可以很容易地将它存储在一个脚本中,比如start-docker-SQL . sh或类似的文件。
docker run \
-e 'ACCEPT_EULA=Y' \
-e 'SA_PASSWORD=Password1!' \
-e 'MSSQL_PID=Express' \
--name sqlserver \
-p 1433:1433 \
-d mssql:dev
推送至 Docker Hub 存储库
现在您已经有了一个工作映像,您肯定希望将它保存在一个托管的存储库中,这样您就可以根据需要将映像拉到不同的机器上。
在 https://hub.docker.com/的创建一个 Docker Hub 账户。
然后创建一个新的存储库,并给它一个名称和描述。
从命令行运行docker login。系统会提示您输入创建帐户时设置的凭据。
现在,标记您的图像:
docker tag local-image:tagname username/new-repo:tagname
接下来,将您的映像推送到您的新存储库:
docker push username/new-repo:tagname
完成后,您将能够通过运行以下命令提取您的映像:
docker pull username/new-repo:tagname
希望这能让你的生活轻松一点!您可以阅读本系列的下一篇文章,通过. NET API 使用这个数据库。
额外收获:C#连接字符串
"ConnectionStrings": {
"DockerDB": "Server=localhost,1433;Database=heroes;User ID=SA;Password=Password1!"
}
感谢您的阅读!
用 SciKit-Learn 构建 NLP 管道:火腿还是垃圾邮件?
使用 Scikit-Learn 的自然语言处理库制作简单的垃圾邮件检测器模型的初学者指南。
在我们的 GitHub 库中查看代码!

安娜·阿尔尚蒂在 Unsplash 上的照片
问题是
像许多 NLP 问题一样,决定哪些电子邮件属于垃圾邮件,哪些是你可能想要阅读的是一个分类问题。
我们可以问,电子邮件属于哪一类,是垃圾邮件还是非垃圾邮件?因此,我们有两个类来分类我们所有的电子邮件。从哪里开始?
为了解决这个问题,我们将使用监督机器学习。这意味着我们有一个已经被标记为垃圾邮件的电子邮件集合。被认为是非垃圾邮件的电子邮件。大致上,我们的模型将通过查看电子邮件的内容并将该内容与任一标签相关联来学习对这些电子邮件进行分类。
经过训练后,我们的模型可以接收一封未标记的电子邮件,并对其进行分类。
数据
在我们开始之前,让我们看一下我们的数据。

用于监督学习的标记电子邮件数据
我们从包含垃圾邮件和非垃圾邮件的语料库或文本集合开始。数据包括标签列(v1)和文本列(v2)。这是我们的模型将读取的数据,用于将消息与类相关联。
听起来很简单,但是计算机不能像我们一样阅读和学习!然而,机器是优秀的计算器。所以让我们把我们的文本转换成一种我们的机器可以进行数学运算的结构,向量。
在完成一些基本的文本清理以处理大小写和非字母字符之后,我们可以开始了。我们将讨论的矢量化的第一步称为标记化。
标记化
给定一个字符序列和一个定义的长度,标记化就是将文档分割成指定长度的片段,称为标记。
令牌不一定是术语或单词。一个标记是一些特定文档中的一个字符序列的实例,这些字符被分组为一个有用的语义单元用于处理。换句话说,标记是我们希望模型学习的有意义的语言。
示例:句子的标记化,将标记长度限制为五个字符。
**IN:** “moon river wider than a mile i am crossing you in style”**OUT:** [moon, river, wider, than, a, mile, i, am, cross, you, in, style]
通过标记化,我们已经从包含超过五个字符长的单词和空格的字符串变成包含五个字符或更少字符且没有空格的单词或标记的数组。
好了,我们现在有了一个字符串数组,我们如何把这些数组转换成向量呢?
矢量化:将单词映射为数值
Scikit-learn 的 CountVectorizer 提供了一种简单的方法来标记一组文本文档并构建已知单词的词汇表。
我们看到的任何文档都可以被编码为一个固定长度的向量,其长度为已知单词的词汇表的长度。向量中每个位置的值可以用文档中每个单词的计数或频率来填充。
用 CountVectorizer 将句子转换成向量
对我们来说,这给了每封邮件一个整数向量。向量将是语料库中不同单词数量的长度。给定一个冗长的语料库,这些向量在计算过程中会变得相当长且麻烦。
这就引出了我们的下一个想法,如何在不损失太多意义的情况下缩小语料库?
一旦我们用 CountVectorizer 将语料库转换成一个整数数组,我们就进入停用词。
停用词:模型中包含什么词汇?
在帮助确定文档是否是垃圾邮件方面似乎没有什么价值的常见单词被完全从词汇表中排除。这些词被称为停止词。决定停止列表的一般策略是根据收集频率(每个术语在文档集合中出现的总次数)对术语进行排序,然后将最常见的术语作为停止列表,这些术语有时根据它们相对于被分析文档的领域的含义进行手动过滤。然后在索引过程中丢弃该非索引列表的成员。
可以手动或自动将停用词添加到停用列表中。在 Scikit-learn 的计数矢量器中,有一个针对特定语料库的停用词的选项。您可以传递一个非索引词数组,或者使用最小和最大文档频率参数自动完成这个过程。
这个简化的矩阵将训练得更快,甚至可以提高你的模型的准确性。
缩小语料库对于减少模型的内存使用非常有用。这样会节省计算成本!
计数矢量器
CountVectorizer 标记、矢量化并创建我们的非索引列表!所以我们要做的就是在模型管道中调用它。这个函数返回一个稀疏矩阵,我们将使用它来训练我们的 ML 模型。
构建模型管道
机器学习管道用于帮助机器学习工作流程自动化。这些管道的运行方式是,在一个模型中对一系列数据进行转换和关联,只需一个代码步骤就可以对这些数据进行测试和评估。
例如,看看我们的朴素贝叶斯管道。
nb = make_pipeline(
CountVectorizer(binary=**True**),
MultinomialNB()
)
我们只需调用make_pipline,添加 CountVectorizer 和我们的模型,然后调用nb.fit使用管道训练一个模型!
机器学习算法通常涉及一系列任务,包括预处理、特征提取、模型拟合和验证阶段。管道帮助我们将这些任务整合在一起。
模型度量:精确度和召回率
我们如何判断哪种模型最有效地解决了这个问题?首先,让我们看看我们的一些模型分数,精度和召回率。
Precision 试图回答以下问题:
实际上有多少比例的肯定认同是正确的?
Precision 测量被标记为垃圾邮件的邮件被正确分类的百分比。
回想一下试图回答以下问题:
正确识别实际阳性的比例是多少?
召回衡量被正确分类的实际垃圾邮件的百分比。
要全面评估一个模型的有效性,你必须同时检查和精度和召回率。不幸的是,精确度和召回率经常处于紧张状态。也就是说,提高精度通常会降低召回率,反之亦然。
所以你需要知道,对于你的问题,精确和召回哪个更重要?
让我们来看看我们的两个模型。这里我们有朴素贝叶斯模型的分数。

朴素贝叶斯
这是逻辑回归模型的分数。

逻辑回归
请注意,除了垃圾邮件精确度这一项之外,NB 模型在所有方面都优于 LR 模型。我们不能说一个模型总是比另一个好,但我们可以更多地选择正确的那个。
保存您的模型
一旦你决定了一个模型,把它保存为一个. joblib,就像下面我们对朴素贝叶斯模型所做的那样。
dump(nb, "clf.joblib")
现在您已经有了一个保存为 joblib 的垃圾邮件检测模型!
结论
在这里,我们已经涵盖了基本的 NPL 概念,记号化,向量化和停用词。然后,我们在模型管道中使用这些概念和 CountVectorizer 来比较模型之间的度量。在决定了朴素贝叶斯分类器之后,我们将它保存为一个 joblib,供以后在我们的应用程序中使用。
查看我们的 GitHub Repositor y 中的代码,获取一个模板开始使用!
要为您的模型提供应用程序并进行部署,请查看下面的进一步阅读资料!
本文讨论构建一个应用程序来服务我们的模型,以及如何将它部署到云中。我们涵盖了应用程序的构建和 docker 化,在 Google Container Registry 上存储 docker 映像,以及将应用程序部署到 Cloud run。
[## 使用 Docker、GCP 云运行和 Flask 部署 Scikit-Learn NLP 模型
构建一个服务于自然语言处理模型的应用程序,将其容器化并部署的简要指南。
towardsdatascience.com](/deploy-a-scikit-learn-nlp-model-with-docker-gcp-cloud-run-and-flask-ba958733997a)
用 Python 构建个性化智能闹钟
让我们建立一个基于人工智能技术的个性化智能闹钟,它将为你设置最佳的闹钟铃声,帮助你早点醒来。

布兰迪·里德在 Unsplash 上拍摄的照片
你好,读者,你经常会看到或使用 Python 语言创建闹钟,它会帮助你醒来或提醒你一个重要的会议。
几乎所有这些都很简单,没有任何智能,它们所做的只是播放你设置的闹钟或选择一个随机的 YouTube 视频或歌曲来播放。
所以,让我们更上一层楼,建造一些智能的东西,一些更个性化的东西,理解你,帮助你以更好更快的方式醒来。
我们将在本文中构建的警报将从过去的事件中学习并理解它们,以便在下一个警报中有更好的性能。一次比一次好用。它会记录用户关闭闹铃所用的时间(用户醒来所用的时间),并推荐有助于你更快醒来的闹铃。
所以,事不宜迟,让我们开始建立我们的警报。下面我们将一步一步来构建。
导入所需的包
第一步是将所需的包导入到我们的 Python 代码中,以便在构建警报时使用它们。
如果没有安装,您需要使用 pip 安装方法进行安装。完成安装步骤后,继续将它们导入代码。
import datetime
import os
import time
import random
import csv
from pygame import mixer
import pandas as pd
import numpy as np
设置音乐文件夹
下一步是建立一个闹铃音乐文件夹,用户可以在其中存储自己喜欢的闹铃音乐。
您可以为警报曲调选择任何路径,我更喜欢在与 Python 脚本相同的文件夹中创建文件夹。我们只需要创建该文件夹一次,因此我们需要检查该文件夹是否存在。如果该文件夹不存在,我们将创建一个。
# Getting the current path of the script
path = os.getcwd()
# Setting up the alarm path
alarm_path = path + '\Alarm_Tunes'
# If no directory present, create one.
if not os.path.isdir(alarm_path):
os.makedirs(alarm_path)
在我们的文件夹被创建后,当且仅当文件夹当前为空时,我们会要求用户向文件夹添加一些闹钟铃声。
# Ask user to add some alarm tunes to the folder.
while len(os.listdir(alarm_path))==0:
print("No Alarm Tunes Present. Please add some tunes to the folder before proceeding.")
confirm = input("Have you added songs? Press Y or N:\t")
if(confirm=="Y"):
print("Good! Let's continue!")
continue
else:
continue
因此,如上所述,我们要求用户至少添加一个闹钟铃声。如果没有报警音,则发出警告并再次询问用户。
创建 CSV 文件并定义助手函数
在进入 CSV 文件创建部分之前,让我们定义一个助手函数。
这个帮助函数帮助我们计算两个 Python 列表之间的差异。这将在我们的程序中用到。
def List_diff(list1, list2):
if len(list1)>=len(list2):
return (list(set(list1) - set(list2)))
else:
return (list(set(list2) - set(list1)))
现在,既然我们已经编写了帮助函数来计算两个列表之间的差异,那么让我们继续创建一个 CSV 文件(如果它还不存在的话)。
# If no csv file, create the lists with parameters as zero
if not os.path.isfile("tune_parameters.csv"):
tune_list = os.listdir(alarm_path)
tune_time = [60]*len(tune_list)
tune_counter = [1]*len(tune_list)
tune_avg = [60]*len(tune_list)
tune_prob_rev = [1/len(tune_list)]*len(tune_list)
tune_prob = [1/len(tune_list)]*len(tune_list)
所以,上面的代码检查我们是否有一个 CSV 文件;如果没有,我们将创建列表,正如您在上面看到的。我们将在程序结束时将这些保存在一个 CSV 文件中。
现在,让我们解释代码中每个列表的意义。让我们一个一个来看。
- tune_list: 它存储报警声音的名称,从代码中可以明显看出,因为它在 alarm_path 中存储文件列表。
- tune_time: 它存储了用户关闭特定闹铃所花费的总时间,即用户醒来所花费的时间。
- tune_counter: 记录到目前为止每首闹钟铃声播放的次数。
- tune_avg: 它会找出用户在每一个闹钟铃声中唤醒和关闭闹钟所花费的平均时间。
- tune_prob_rev: 它根据用户每次闹钟调谐所需的平均时间来计算一种反向概率。
- tune_prob: 是闹钟铃声每次播放的概率。它根据之前的结果进行自我更新,并使用 tune_prob_rev 进行计算。
这里要注意的一点是,我已经为所有这些列表设置了一些默认值,而不是提供零,因为这将对模型产生负面影响,因为从未玩过的人将永远不会有机会,因为概率为零。
所以,我更倾向于假设这些游戏每个都玩过一次,平均时间是 60 秒。因此它使我们的工作更容易。
现在,如果 CSV 文件已经存在,我们需要从 CSV 文件加载数据。
此外,我们需要注意,如果有任何改变,以报警曲调文件夹。用户可能已经添加了新的歌曲或者删除了一些当前的歌曲。因此,我们需要通过添加新的歌曲到我们的列表中或者删除那些已经从文件夹中删除的歌曲来进行更新。
因此,我们使用前面定义的 helper 函数来找出从文件夹获得的列表和从 CSV 文件获得的列表之间的任何差异。因此,我们可以对代码执行所需的操作,并使用各自的公式分别更新 tune_prob_rev 和 tune_prob,。
# If csv file is present, read from csv file
else:
tune_df = pd.read_csv("tune_parameters.csv")
tune_list_os = os.listdir(alarm_path)
tune_list = list(tune_df['Tunes'])
tune_diff = List_diff(tune_list_os, tune_list)
tune_time = list(tune_df['Delay Times'])
tune_counter = list(tune_df['Count'])
tune_avg = list(tune_df['Average'])
tune_prob_rev = list(tune_df['Reverse Probability'])
tune_prob = list(tune_df['Probability'])
if len(tune_list_os)>=len(tune_list):
for i in range(0,len(tune_diff)):
tune_list.append(tune_diff[i])
tune_time.append(60)
tune_counter.append(1)
tune_avg.append(60)
tune_prob_rev.append(0.1)
tune_prob.append(0.1)
else:
for i in range(0,len(tune_diff)):
tune_diff_index = tune_list.index(tune_diff[i])
tune_list.pop(tune_diff_index)
tune_time.pop(tune_diff_index)
tune_counter.pop(tune_diff_index)
tune_avg.pop(tune_diff_index)
tune_prob_rev.pop(tune_diff_index)
tune_prob.pop(tune_diff_index)
avg_sum = sum(tune_avg)
for i in range(0,len(tune_prob_rev)):
tune_prob_rev[i] = 1 - tune_avg[i]/avg_sum
avg_prob = sum(tune_prob_rev)
for i in range(0,len(tune_prob)):
tune_prob[i] = tune_prob_rev[i]/avg_prob
设置闹钟并核实时间
现在,我们需要定义另一个助手函数来检查用户输入的时间是否正确。因此,我们定义了函数 verify_alarm 来实现这一点。
# Verify whether time entered is correct or not.
def verify_alarm(hour,minute,seconds):
if((hour>=0 and hour<=23) and (minute>=0 and minute<=59) and (seconds>=0 and seconds<=59)):
return True
else:
return False
现在,我们已经准备好了助手函数。所以,我们需要向用户询问闹铃时间。我们将使用一个循环来请求警报,一旦我们验证时间有效,我们将中断。如果无效,我们将再次询问用户,直到他输入一个有效的时间。
# Asking user to set alarm time and verifying whether true or not.
while(True):
hour = int(input("Enter the hour in 24 Hour Format (0-23):\t"))
minute = int(input("Enter the minutes (0-59):\t"))
seconds = int(input("Enter the seconds (0-59):\t"))
if verify_alarm(hour,minute,seconds):
break
else:
print("Error: Wrong Time Entered! Please enter again!")
现在,在接受用户输入后,我们将找出当前时间,并将这两个时间转换为秒,并找出两个时间之间的差异。如果差值为负,则意味着闹钟是第二天的。
然后,我们将让 python 代码休眠几秒钟,以便警报只在需要的时间响起。
# Converting the alarm time to seconds
alarm_sec = hour*3600 + minute*60 + seconds
# Getting current time and converting it to seconds
curr_time = datetime.datetime.now()
curr_sec = curr_time.hour*3600 + curr_time.minute*60 + curr_time.second
# Calculating the number of seconds left for alarm
time_diff = alarm_sec - curr_sec
#If time difference is negative, it means the alarm is for next day.
if time_diff < 0:
time_diff += 86400
# Displaying the time left for alarm
print("Time left for alarm is %s" % datetime.timedelta(seconds=time_diff))
# Sleep until the time at which alarm rings
time.sleep(time_diff)
响起闹铃
现在,我们将敲响我们的闹钟,我们需要根据概率列表随机选择闹钟曲调。为了播放闹铃,我们将使用 pygame.mixer.music 库。我们将无限循环闹钟铃声,直到用户停止它。
print("Alarm time! Wake up! Wake up!")
# Choose a tune based on probability
tune_choice_np = np.random.choice(tune_list, 1, tune_prob)
tune_choice = tune_choice_np[0]
# Getting the index of chosen tune in list
tune_index = tune_list.index(tune_choice)
# Play the alarm tune
mixer.init()
mixer.music.load(alarm_path+"/"+tune_choice)
# Setting loops=-1 to ensure that alarm only stops when user stops it!
mixer.music.play(loops=-1)
# Asking user to stop the alarm
input("Press ENTER to stop alarm")
mixer.music.stop()
列表的计算和更新
现在,我们将根据用户停止警报所需的时间来更新列表的值。
我们将找到报警和当前停止报警时间之间的时间差。我们将把它转换成秒,然后相应地更新它。
# Finding the time of stopping the alarm
time_stop = datetime.datetime.now()
stop_sec = time_stop.hour*3600 + time_stop.minute*60 + time_stop.second
# Calculating the time delay
time_delay = stop_sec - alarm_sec
# Updating the values
tune_time[tune_index] += time_delay
tune_counter[tune_index] += 1
tune_avg[tune_index] = tune_time[tune_index] / tune_counter[tune_index]
new_avg_sum = sum(tune_avg)
for i in range(0,len(tune_list)):
tune_prob_rev[i] = 1 - tune_avg[i] / new_avg_sum
new_avg_prob = sum(tune_prob_rev)
for i in range(0,len(tune_list)):
tune_prob[i] = tune_prob_rev[i] / new_avg_prob
合并列表并保存为 CSV 文件
现在,我们将所有列表合并成一个多维列表,然后我们将它转换为 pandas 数据框并保存为 CSV 文件。
#Create the merged list of all six quantities
tune_rec = [[[[[[]]]]]]
for i in range (0,len(tune_list)):
temp=[]
temp.append(tune_list[i])
temp.append(tune_time[i])
temp.append(tune_counter[i])
temp.append(tune_avg[i])
temp.append(tune_prob_rev[i])
temp.append(tune_prob[i])
tune_rec.append(temp)
tune_rec.pop(0)
#Convert merged list to a pandas dataframe
df = pd.DataFrame(tune_rec, columns=['Tunes','Delay Times','Count','Average','Reverse Probability','Probability'],dtype=float)
#Save the dataframe as a csv (if already present, will overwrite the previous one)
df.to_csv('tune_parameters.csv',index=False)
使用 Python 的智能警报的完整代码是:
我们终于完成了智能闹钟的制作。关于更新,请访问我的 Github 资源库,如果您有一些改进或新想法,请对资源库做出贡献。
我希望你觉得这篇文章很有见地。尝试建立你的版本,并在评论中分享你的想法。感谢阅读!
这篇文章之后还有更多的文章可以阅读:
[## 使用 Django Rest 框架构建博客网站——概述(第 1 部分)
让我们使用 Django Rest 框架构建一个简单的博客网站,以了解 DRF 和 REST APIs 是如何工作的,以及我们如何添加…
towardsdatascience.com](/build-a-blog-website-using-django-rest-framework-overview-part-1-1f847d53753f) [## 用 Django 构建求职门户——概述(第 1 部分)
让我们使用 Django 建立一个工作搜索门户,允许招聘人员发布工作和接受候选人,同时…
shubhamstudent5.medium.com](https://shubhamstudent5.medium.com/build-a-job-search-portal-with-django-overview-part-1-bec74d3b6f4e) [## 使用 React 构建一个简单的 Todo 应用程序
让我们用 React 构建一个简单的 Todo 应用程序,教你 CRUD 的基本原理(创建、读取、更新和…
medium.com](https://medium.com/javascript-in-plain-english/build-a-simple-todo-app-using-react-a492adc9c8a4) [## 使用 Django 构建一个社交媒体网站——设置项目(第 1 部分)
在第一部分中,我们集中在设置我们的项目和安装所需的组件,并设置密码…
towardsdatascience.com](/build-a-social-media-website-using-django-setup-the-project-part-1-6e1932c9f221)
在不到 60 分钟的时间内建立一个推荐系统

在泰国清迈拍摄的一只病狗的照片
使用 Amazon Personalize 建立推荐系统的分步指南。
B 公元时代!自从泰国政府宣布冠状病毒进入紧急状态,我们所有人都被鼓励在家工作。我被分配了一项具有挑战性的任务,主持一场主题为“提高新冠肺炎电子商务客户参与度”的网络研讨会。
因此,经过仔细考虑,并考虑到我在机器学习方面的基本背景,我决定将这次网络研讨会的主题定为在不到一个小时的时间内使用亚马逊个性化构建推荐系统。
说实话,我确实花了一些时间浏览 YouTube 上关于使用 Python 构建推荐系统的教程——关于余弦相似性等概念。起初,这很简单,但后来问题开始出现。以下是其中的一些:
- 我如何部署这个算法?我如何为模型服务?我需要调配哪个云基础架构?
- 我如何应对趋势和客户行为的快速变化?
- 我如何处理新用户和新项目?(经典的冷启动问题)
我偶然发现亚马逊个性化,它勾选了所有正确的框。
我是这样做的!
什么是亚马逊个性化?
亚马逊个性化是一个实时个性化和推荐服务。这是一种即时解决方案,您只需添加数据,点击几下鼠标,我们就可以获得随时可用的推荐引擎。
如果你想跟进——我建议你下载传奇的 MovieLens 数据,其中包含用户和评级,这将是我们输入亚马逊个性化的数据
稳定的基准数据集。1000 名用户对 1700 部电影的 100,000 次评分
www.kaggle.com](https://www.kaggle.com/prajitdatta/movielens-100k-dataset) 
Shivek Sachdev 个性化亚马逊概述(作者图片)
第一步:数据准备&加载数据
注意:为了描绘一幅更好的画面,让我们使用一个假想的电子商务网站来完成我们将使用 Amazon Personalize 构建推荐系统的 3 个步骤。
我必须准备一个带有预定义列的 CSV 文件,列中有“谁买了什么?”数据——这被称为“交互”。

亚马逊个性化所需的列示例(作者图片)
所以我们需要 USER_ID 和 ITEM_ID ,以及时间戳 (Unix 日期格式)。
我们需要将 CSV 文件转储到 S3 桶中,对于那些不熟悉 AWS 的人来说,S3 是一个对象存储。你想往里面倒什么都可以,但是你得付钱给杰夫!
因此,事不宜迟,我们推出了亚马逊个性化服务!

在 AWS 控制台中搜索“个性化”以启动该服务(图片作者)
在第一步中,我们将首先创建一个数据集组,以便将我们的数据导入 Amazon Personalize。

在 Amazon Personalize 中创建数据集组(作者图片
然后,我们将被重定向到 Amazon Personalize 控制台中的概览仪表板。确保点击导入用户-项目交互数据。我们将把我们的数据从 S3 导入到 Amazon Personalize dataset 组,只需将路径粘贴到 CSV 文件即可。

上传数据集:用户-物品交互数据(图片作者)
要导入我们的 CSV,我们必须创建一个数据集名称,并为 Amazon Personalize 提供一个 JSON 模式。这个 JSON 文件是一个模式定义,将用于在我们开始构建推荐系统之前提供所有必需的细节。
下面是我们如何可视化 JSON 模式文件,希望有所帮助!

模式定义(JSON)与 CSV ( 作者图片)
完成后,我们可以单击“开始导入”来导入 CSV 文件,以完成我们创建数据集的过程,这就结束了步骤 1!

选择 CSV 数据的 S3 位置(图片作者)
步骤 2:创建解决方案(模型培训)
继续第 2 步。在这里,您将创建一个解决方案,并从 Amazon Personalize 上的一系列预建推荐算法中进行选择。
这样想:

亚马逊个性化解决方案和食谱(作者图片)
要开始此流程,我们从上次离开的地方开始,从概览控制面板开始,但这次我们将单击“创建解决方案”。

创建解决方案(作者图片)
由于我在机器学习方面有非常基本的知识,我选择了 AutoML 作为食谱——这意味着亚马逊个性化将检查我们的数据,并为我们建议最佳食谱。

在亚马逊上创建一个个性化的解决方案
HRNN 代表分层递归神经网络。这种算法应该非常强大,可以处理消费者行为的变化——非常适合这个新冠肺炎时代!
HRNN 将是模拟行为变化并推荐更适合消费者/购物者的商品的完美解决方案。

HRNN 可以模拟消费者/用户的行为变化,并推荐最佳产品选择
奇迹就在这里发生——不要惊讶,这可能需要一段时间。毕竟是魔法。
对于 ML 极客来说,这里是 HRNN 和其他人的基准对比。

在 AWS 在线技术讲座上,HRNN 与其他人进行了最先进的表演
步骤 3:启动和测试活动
这是我们的最后一步——我们将在 Amazon Personalize 上发起一场“活动”,并最终看到我们推荐的系统将向我们的用户/客户展示哪些商品。创建营销活动是最简单的步骤,我们像往常一样从概览控制面板开始。

创建一个新的活动(图片作者
请确保您选择了刚刚在第 2 步中创建的解决方案,然后点击“创建活动”。

在亚马逊上创建一个活动个性化(作者图片)
现在是关键时刻,我们可以通过输入用户 ID 来测试该活动,然后单击“Get recommendations”来查看向我们的用户/客户推荐的商品 ID 列表。就这么简单!

亚马逊个性化测试活动(作者图片)
额外收获:亚马逊个性化服务中的模特
通常当人们谈论将一个模型“投入生产”时,他们通常意味着执行推理,有时被称为模型评估或预测或服务。

活动推断(作者图片)
在 Amazon Personalize 的例子中,一旦我们创建了我们的活动,它将自动为我们创建和部署一个活动推断端点。我们需要做的只是调用 getReccomendation API 来获得实时推荐!

与亚马逊个性化活动 ARN 整合(作者图片)
下面是调用 API 所需的代码示例——我们只需要对用于 Python 的 AWS SDK(boto 3)有一个非常基本的了解。
确保您安装了用于 Python 的 AWS SDK。
- 创建一个“响应”字典
- 调用 get_recommendations API,传递一个 userId 变量来获取推荐
- 显示推荐的项目(将显示 itemId)
- 映射 itemId 并合并“项目名称数据框架”中的数据以显示项目名称(这是可选的)
**import** **boto3** personalize = boto3.client('personalize')
response = personalize.list_recipes()
**for** recipe **in** response['recipes']:
print(recipe)
personalizeRt = boto3.client('personalize-runtime')
运行这个代码块,通过传递一个 user_Id(我在下面的例子中使用了 2)来获得商品推荐,并确保调用了正确的 campaignARN!
response = personalizeRt.get_recommendations(
campaignArn = 'arn:aws:personalize:***<insert region & campaign ARN>***:campaign/ratings-campaign',
userId = '2')
我们在没有任何 ML 知识的情况下完成了这件事!

我们做到了!庆祝的时间到了!网络模因
很棒的东西!这个博客将只涵盖亚马逊个性化的非常基础(入门级)的部分。这对那些有或没有 ML 背景的人来说都很好,但还有更多要学的。总之,我们使用 Amazon Personalize 在不到一个小时的时间内成功构建了一个最先进的推荐系统。说实话——我写这篇博客的时间可能比在 Amazon Personalize 上运行整个过程的时间还多!
构建推荐系统:Yelp 评分预测实例——协同过滤
个性化
利用用户和项目与某些潜在特征的密切关系来预测用户对项目的评分。

图片来源: Unsplash
本文内容:我开始这一系列文章,通过解释它们的工作原理并展示它们在数据集上的应用来介绍几种流行的推荐系统技术 Yelp Challenge 2019 。每篇文章都有不同的关注点,这取决于复杂性是存在于数据预处理、模型概念还是实现中。在本文中,我将介绍一种最常用的模型——协同过滤(CF)及其通过矩阵分解技术奇异值分解(SVD)的实现。本文将主要侧重于解释概念,并附带关键代码演练。更多细节包含在发布在 Github 上的代码和评论中。
注:本文是一个四人团队(邦威·周、James Jungsuk Lee、Ujjwal Peshin 和)的项目成果。非常感谢 Brett Vintch 为这个项目提供指导和反馈。在每篇文章之后,完整的代码将会在这个 Github 库上提供。代码是用 Python 写的。
关于挑战和项目目标
Yelp 数据集挑战[1]为学生提供了一个对 Yelp 数据进行研究或分析并分享发现的机会。参与者可以以创新的方式使用这些数据,并找到对 Yelp 及其用户有意义的结果。
这个项目的目标是比较向用户推荐当地企业的不同方法。这包括根据用户的历史评级记录预测用户以前没有访问过的企业的评级值。我们模型的性能主要通过均方根误差(RMSE)来衡量。此外,还测量了其他类型的指标,如排名指标、覆盖率和新颖性,以评估排名质量、准确性分布和预测的多样性。此外,模型运行时间被测量。它们将在后面的文章中详细阐述。
资料组
数据以 zip 文件的形式出现,可以通过这个链接访问。该文件包含 6 个 JSON 数据文件,我们的模型主要使用以下内容:
- reviews.json:包含来自 10 个大都市地区 19 万家企业的 160 万用户的 700 万条评论。每个记录都是用户在某个日期和时间对某个企业的评价和全文评论。
- json:包含业务概要,包括位置数据、属性和类别。
- user.json:包含用户资料,包括用户的朋友映射和所有与用户相关的元数据,例如评论数、帐户年龄、收到的酷投票数等。
数据准备
原始审查数据集很大(> 5GB),因此建议开发一个代表整个数据集的较小数据集,以加快开发周期。此外,为了提供足够的每用户数据供模型学习,或者为了避免冷启动问题,少于 5 条评论的用户被过滤掉。请注意,解决冷启动的方法将在以后的文章中讨论,但不是本文的重点。
为了创建更小的数据集,基于用户 id 的执行缩减采样。我们不对评分记录进行缩减采样的原因是,这可能会创建更多评分少于 5 的用户,这会干扰上面的过滤步骤。因此,我们对 20%的活跃用户(评论≥5 条)进行二次抽样,并保留他们的相关评级用于建模。与原始数据集相比,结果数据集的大小也缩小了约 20%。下面是数据准备过程:
(I)加载数据——将数据压缩文件下载到本地存储库后,解压缩 review.json 文件并将 json 文件加载到 pandas 数据框架中。
import pandas as pd
import tarfile
from tqdm import tqdm
import json
import numpy as np
import time
from copy import deepcopyzf = tarfile.open('yelp_dataset.tar')
zf.extract('review.json')line_count = len(open("review.json").readlines())
user_ids, business_ids, stars, dates, texts = [], [], [], [], []
with open("review.json") as f:
for line in tqdm(f, total=line_count):
blob = json.loads(line)
user_ids += [blob["user_id"]]
business_ids += [blob["business_id"]]
stars += [blob["stars"]]
dates += [blob["date"]]
texts += [blob["text"]]
ratings_ = pd.DataFrame(
{"user_id": user_ids, "business_id": business_ids, "rating": stars, "date": dates, "text": texts}
)
㈡仅保留活跃用户(≥ 5 个评分)
active_users = user_counts.loc[user_counts >= 5].index.tolist()
ratings_ = ratings_.loc[ratings_.user_id.isin(active_users)]
㈡随机抽取 1/5 的用户
SAMPLING_RATE = 1/5user_id_unique = ratings_.user_id.unique()
user_id_sample = pd.DataFrame(user_id_unique, columns=['unique_user_id']) \
.sample(frac= SAMPLING_RATE, replace=False, random_state=1)ratings_sample = ratings_.merge(user_id_sample, left_on='user_id', right_on='unique_user_id') \
.drop(['unique_user_id'], axis=1)
(iii)训练-测试-验证分离-我们根据每个用户给出的最新评级来评估模型性能。根据 Tomas 的博客 [6】,这种创建测试集的方式被认为是过时方法,并且不同于正常的及时方法,在正常的及时方法中,训练、验证和确认是从同一时间段随机生成的。这实际上是合理的,因为我们经常使用用户的历史评分来预测他未来的评分。在数据模式的移位中可能存在关系,否则这些关系将被丢弃。因此,每个用户的最新评级被作为测试集。然后将第二个最新的评级作为验证集。
# hold out last review
ratings_user_date = ratings_sample.loc[:, [‘user_id’, ‘date’]]
ratings_user_date.date = pd.to_datetime(ratings_user_date.date)
index_holdout = ratings_user_date.groupby([‘user_id’], sort=False)[‘date’].transform(max) == ratings_user_date[‘date’]
ratings_holdout_ = ratings_sample[index_holdout]
ratings_traincv_ = ratings_sample[~index_holdout]ratings_user_date = ratings_traincv_.loc[:, [‘user_id’, ‘date’]]
index_holdout = ratings_user_date.groupby([‘user_id’], sort=False)[‘date’].transform(max) == ratings_user_date[‘date’]
ratings_cv_ = ratings_traincv_[index_holdout]
ratings_train_ = ratings_traincv_[~index_holdout]
处理完数据后,现在让我们看看我们将要使用的模型。
有偏基线模型
让我们从介绍一个简单的基线模型开始。该模型的一个假设是,每个用户对他给出的评级都有一些自然的偏好,因此通常会给企业更高或更低的评级。该模型还假设每家企业对一般人都有较高或较低的吸引力。此外,数据具有一些潜在的偏差,因此,每个偏差源都包括在内,以使用以下等式对评级进行建模:
rᵤᵢ=μ + bᵤ +bᵢ
这里,μ是平均评分偏差,参数 bᵤ和 bᵢ分别表示用户和项目偏差。例如,假设我们想要找到用户 ABC 可能如何评价“ SHAKE SHACK BURGERS ”。假设数据中所有餐厅的平均评级为 3.4,一般来说, SHAKE SHACK BURGERS 是一家评级很高的餐厅,因此它的评级比平均值高 0.5。另一方面,“ABC”是一个有选择性的用户,通常给餐馆的评分比平均水平低 0.4 分。因此,用户“ABC”对餐馆“ SHAKE SHACK BURGERS ”的基线估计是 3.4+0.5–0.4 = 3.5。实施的基线函数估计 bᵤ和 bᵢ,以优化以下损失函数(*):
∑(rᵤᵢ(μ+bᵤ+bᵢ))+λ(bᵤ+bᵢ)其中 rᵤᵢ ∈ R_train,λ是正则化
实现 bias 模型的一个捷径就是使用 Python surprise 包,一个简单易用的推荐系统库。当加载一个熊猫数据帧作为一个特殊的数据集对象并尝试一些基本模型时,读者可能会发现这个教程很有帮助。在本例中,带有超参数输入字典的 BaselineOnly()指定了有偏差的基线模型对象。algo.fit()在训练集上拟合模型,而 algo.test()在验证集上生成预测。
from surprise import SVD
from surprise import accuracy
from surprise import Reader
from surprise import Dataset
from surprise import BaselineOnlyreader = Reader(rating_scale = (0.0, 5.0))
train_data = Dataset.load_from_df(trainset[['userID','itemID','rating']], reader)
val_data = Dataset.load_from_df(valset[['userID','itemID','rating']], reader)
test_data = Dataset.load_from_df(testset[['userID','itemID','rating']], reader)train_sr = train_data.build_full_trainset()
val_sr_before = val_data.build_full_trainset()
val_sr = val_sr_before.build_testset()
test_sr_before = test_data.build_full_trainset()
test_sr = test_sr_before.build_testset()bsl_options = {'method': 'als', 'n_epochs':3}
bias_baseline = BaselineOnly(bsl_options)
bias_baseline.fit(train_sr)
predictions = bias_baseline.test(val_sr)
可能有人会注意到,我们将{'method': 'als ',' n_epochs': 3}指定为超参数。“方法”是指优化方法,而“als”是指交替最小二乘法,一种通过在 bᵤ和 bᵢ交替迭代更新来接近基线模型损失函数(*)解的方法。
可以调整这些超参数,然后比较性能。一个简单的基线模型可能会给我们带来初步的评级预测,但还不够。由于偏差是跨所有用户或所有项目计算的,因此它无法捕捉特定用户或项目之间的粒度。因此,我们希望使用一种模型,更多地利用这些用户到用户或项目到项目的基础关系。在下一节中,我们将看看协同过滤。
基于矩阵分解的协同过滤
协同过滤
推荐系统中的常见问题涉及两种类型的数据:(I)用户-项目交互,例如评级、收视率(ii)用户或项目特定的属性,例如文本简档。使用前者的方法被称为协同过滤方法。它们属于一类强大的技术,因为它们以协作的方式使用来自多个用户的评级。基本思想是可以预测未指定的评级,因为观察到的评级通常与各种用户和项目高度相关[2]。通过识别相似的用户,人们可以通过查找相似用户给出的评级(对于同一项目)来推断未指定的评级。
常用的 CF 方法有两种:基于邻域的方法和基于模型的方法。基于邻域的方法旨在识别相似用户(或相似项目)并使用来自对等用户(或项目)组的加权平均评级进行预测,例如使用 K-最近邻。这些方法的价值在于实现和解释的简单性。然而,它们的性能是有限的,尤其是当评级矩阵稀疏时,因为很难识别出对同一项目进行了评级的足够相似的用户。另一方面,基于模型的方法将具有概括的机器学习模型,例如决策树、潜在因素模型等。并将评级预测视为广义回归或分类问题。例如,我接下来介绍的方法属于潜在因素模型:矩阵分解。
矩阵分解和奇异值分解
在这个项目中,我们使用矩阵分解(MF),一类基于模型的 CF 算法。也就是说,MF 将一个 m(用户数)* n(项目数)的用户-项目矩阵分解成两个矩阵——m * k 和 k * n,共享维数 k,如下:R = X* Y .具有维数 k 的空间称为潜在空间。但是分解和推荐任务有什么关系呢?一种更直观的理解方式是,这种方法的目标是将用户和项目都映射到维度为 k 的联合潜在因素空间中,从而将用户-项目交互建模为该空间中的内积[3]。让我们看一下下图:

每个用户 u 与向量 pᵤ ∈ ℝᵏ相关联,每个项目与向量 qᵢ ∈ ℝᵏ.相关联向量的每个维度表示该项目或用户与相应潜在因素或特征的相似度,例如,餐馆是高级餐厅还是休闲餐厅,其价格是贵还是便宜,等等。 Nicholas Hug 的博客提供了对潜在载体的很好解释【4】。有趣的是,很可能观察到具有相似品味的用户或具有相似特征的项目将在潜在空间中在几何上彼此靠近。此外,具有较高点积即 qᵢᵗ pᵤ的项目 I 和用户 u 指示用户 u 可能提供的较高评级 rᵤᵢ,因为用户和项目倾向于在相似的潜在因素集合上共享相似性。
现在的挑战是识别这样的映射(用户 u,pᵤ)和(项目 I,qᵢ),因为在这之后,评级 rᵤᵢ可以通过它们的点积来近似,即 rᵤᵢ ≃ qᵢᵗ pᵤ 。注意这种形式如何与矩阵分解 R = X * Y 匹配。我们可以使用奇异值分解 (SVD)来找到这种映射:
R = P ∑ Qᵗ
其中 P ∈ ℝᵐ ˣ ᵐ,∈ ℝᵐ ˣ ⁿ,Q ∈ ℝⁿ ˣ ⁿ,p,q 是列正交矩阵,∑是对角矩阵。如果我们分别查看 p 的每一行和 Qᵗ的每一列,那么我们会注意到 SVD 允许我们直接对 rᵤᵢ ≃ qᵢᵗ pᵤ关系建模,因为∑只是一组标量。
在实践中,SVD 通过正则化来实现,即正则化 SVD [5],以避免在建模稀疏评级矩阵时过拟合。此外,还添加了基线中的偏差项,因此最终近似值如下所示[3]:
rᵤᵢ=μ + bᵤ +bᵢ + qᵢᵗ pᵤ
损失函数是
∑(rᵤᵢ(μ+bᵤ+bᵢ+qᵢᵗpᵤ))+λ(|pᵤ|+|qᵢ|+bᵤ+bᵢ)
这正是 surprise package 在后端实现 SVD 的方式。使用 surprise SVD()函数,我们可以构建、调整和测试模型,只需几行代码:
RMSE_tune = {}
n_epochs = [5, 7, 10] # the number of iteration of the SGD procedure
lr_all = [0.002, 0.003, 0.005] # the learning rate for all parameters
reg_all = [0.4, 0.5, 0.6] # the regularization term for all parametersfor n in n_epochs:
for l in lr_all:
for r in reg_all:
algo = SVD(n_epochs = n, lr_all = l, reg_all = r)
algo.fit(train_sr)
predictions = algo.test(val_sr)
RMSE_tune[n,l,r] = accuracy.rmse(predictions)algo_real = SVD(n_epochs = 10, lr_all = 0.005, reg_all = 0.4)
algo_real.fit(train_sr)
predictions = algo_real.test(test_sr)
估价
在这个项目中,几个评估指标被用来从不同的角度测量模型性能。它们是:
- 回归指标,如 RMSE、平均误差、R 平方
- 排名指标,例如前 k 名推荐、平均排名
- 新闻报道
- 新奇
最直接的是,回归度量告诉我们预测的评级与实际评级有多接近。尽管回归指标是我们用来评估预测总体质量的依据,但它们本身并不能向我们展示全貌。从一个稍微不同的角度来看,我们可以把我们的问题看作一个排名问题——我们有多大可能把一个企业推荐给一个他下一次访问的用户,然后发现它很好。在实践中,只有排名前 k 的企业作为列表推荐给用户,用户往往最关注它们,而不是在整个搜索结果底部的那些。因此,除了追求低预测误差,我们还关心热门推荐是否抓住了用户的口味,因为它们与用户体验最相关。值得注意的是,错误度量的小差异可能会导致排名度量的大差异。
此外,我们推荐的企业是否足够多样化,以覆盖所有现有企业的很大一部分,这是一个问题——通过覆盖指标来衡量。最后,我们希望衡量我们的模型是否向用户推荐了新颖的选项,以避免总是显示相同的企业集合。在以后的文章中,我们将进一步研究这些指标。我们的代码中也提供了这些指标的定义,供读者参考。
结果
比较两个模型在 20%训练数据上的结果:
# Bias Baseline
RMSE: 1.3811
MAE: 1.1598
R^2: 0.1661
Top_10: 0.1233
Coverage:0.2044
Serendipity: 0.9795
Avg_rank: 526.6
The algorithm takes 2.341 seconds.# Collaborative Filtering via SVD (CF-SVD)
RMSE: 1.3595
MAE: 1.1170
R^2: 0.1920
Top_10: 0.1140
Coverage: 0.4760
Serendipity: 0.9672
Avg_rank: 541.1
The algorithm takes 83.351 seconds.
对于回归指标,CF-SVD 在较低的 RMSE、MAE 和较高的 R 方面表现更好。对于排名指标,结果喜忧参半。CF-SVD 推荐了更广泛的业务,而基线模型提供了更好地捕捉用户口味的 10 大推荐。
CF-SVD 的一个主要缺点是它需要长得多的运行时间,这可能成为扩展的一个问题。欢迎读者通过对 100%数据进行训练来进一步比较两个模型的性能。
结论
在本文中,我介绍了协同过滤——一种用于构建推荐系统的经典但强大的技术,以及它通过使用 Python surprise 库的奇异值分解的一种实现。该算法是强大的,因为它通过将用户和项目放置在相同的潜在空间中并利用它们与一些结构化的、潜在的、特征捕捉因素的相似性来对用户-项目交互进行建模。从矩阵的角度来看,该算法在因子分解过程中捕获行交互和列交互。这些都是将 CF 的性能带到一个体面的水平并使其成为最近研究中受欢迎的基准的原因。请注意,这只是一个开始,因为我们只使用评级数据。像用户简档、商业位置、类别和时间这样的其他信息也可以提供有用的信号来准确地预测评级。在下一篇文章中,我将介绍几个最先进的模型,当我们想要集成上述更多信息时,这些模型就会发挥作用。
参考:
[1] Yelp 数据集挑战 (2019)
[2] C. C. Aggarwal,推荐人系统教材 (2018),湛:施普林格国际出版公司。
[3] Y. Koren,R. Bell,& C. Volinsky,推荐系统的矩阵分解技术 (2009),计算机, 42 (8),30–37。doi:10.1109/mc2009.263
[4] N. Hug,理解矩阵分解求推荐(第二部分)SVD 背后的模型 (2017),博文。
[5] B .韦伯,网飞更新:在家试试这个 (2006),《控制论的进化》。
[6] T. Dvorak,为什么超时验证不是更普遍? (2019),走向数据科学。
用 Selenium 和 Python 构建一个可伸缩的网络爬虫
使用 Docker、Kubernetes 引擎和云数据存储在 Google 云平台中实现

图 1 —图片来自 Pixabay (Pixabay 许可证)
免责声明: 由于使用条款禁止抓取 Medium.com 服务,我想指出的是,我们立即使用 NLP 处理了项目中的底层数据,并且没有存储纯文本。因此,本文中展示的方法仅用于演示目的,可以用于其他允许 web 抓取的网站。
本文是一个更大项目的一部分。如果您还对使用 PySpark 和 Kubernetes 对结果执行自然语言处理以提取技术名称感兴趣,或者对在 Python 中构建高度可伸缩的仪表板感兴趣,您会在本文末尾找到相应的链接。
目录
1.介绍
数据科学家的生活可能很艰难。带来挑战的不仅仅是数据的获取和质量及其可解释性。技术的快速发展,以及企业不断提高的期望(关键词火箭科学),也使工作变得更加困难。然而,根据我的经验,尤其是新技术的获取和应用,是大多数数据科学家的热情来源。出于这个原因,我用通用技术构建了一个可扩展的网络爬虫来提高我的技能。
本文中引用的所有文件和代码片段都可以在我的 GitHub 资源库中找到。
2.项目理念和方法
走向数据科学(TWDS)是数据科学最著名和最有教育意义的地方之一。这是一份 medium.com 出版物,许多作者在上面发表了各种文章。引用了经常使用的技术,并在案例研究中介绍了它们的使用。因此,我决定构建一个网络爬虫,提取 TWDS 的内容,并将其存储在 NoSQL 的数据库“谷歌数据存储”中。为了使网络爬虫具有可伸缩性,我使用 Docker 来封装我的应用程序,使用 Kubernetes 来进行编排。

图 2 —可扩展基础设施的技术概述
方法是在我的本地机器上的 Jupyter 笔记本中开发网络爬虫,并不断专业化和增加项目(见图 2)。例如,我构建了一个 Python 应用程序,它有一个专用的爬虫类和所有基于 Jupyter 笔记本脚本的必要方法。但是让我们更详细地看看实现步骤。
3.来源检验和包装
3.1 来源检查
要开发一个正常运行的网络爬虫,提前熟悉网站结构、可用内容和不规则性是很重要的。

图 3 —相关实体的连接
《TWDS》是一本经典出版物,有许多作者和文章。由于有了一个档案页面,很容易理解页面结构的细节(见图 3)。幸运的是,这里不仅列出了作者,还提供了指向这些作者的概述页面的链接。

图 4-TWDS 档案上作者列表的页面源代码
所使用的 HTML 类是经常使用的,因此可以很容易地识别链接(见图 4)。
对于作者的概述页面,我发现最初
只列出了作者在 TWDS 发表的文章。作者发表的关于 Medium.com 的其他文章没有展示。因此,没有必要检查具体文章是否属于 TWDS 出版物。不幸的是,这些链接的 HTML 类是空的,无法识别这些链接。但是,这些链接包含完整的 URL,因此包含“朝向”一词。因此,对这些联系的识别也是毫不含糊的。然而,在检查页面时出现了另一个问题。并不是所有作者的文章都会直接显示,但是当网站向下滚动时,会使用 Javascript 动态地重新加载更多的内容。为了确保完整性,这必须考虑到网络爬虫的发展。

图 5 —来自 TWDS 文章的 HTML 源代码示例
最后,我必须检查每篇文章的结构,寻找相似之处和模式,以提取相关的数据字段。必需的属性是作者、URL、标题、文本、阅读时间、发布日期、标签、掌声和回复数量。如图 5 所示,HTML 源代码面临一些挑战。例如,类名似乎是动态生成的,并且在文章中只有很少的匹配。但也有希望之光,例如,阅读时间、标题、URL 和出版日期在页面标题中是标准化的。剩下的内容相当容易访问。
3.2 包装选择
起初,在 Jupyter 笔记本的开发过程中,我一直在寻找能够满足所有需求的 Python 包。我很快意识到,对于 web 抓取最常用的包之一的 Scrapy 来说,动态内容重新加载是很困难的。在关注这个需求后,我开始意识到硒。Selenium 是一个用于 web 应用程序自动化软件测试的框架,可以与浏览器交互,例如向下滚动页面以加载动态 javascript 内容并接收完整的 HTML 源代码。
为了处理提取的 HTML 源代码,我找到了 Python 包 BeautifulSoup4 ,它提供了各种方法来系统地搜索 HTML 树结构中的相关内容。选择了这些包,我就可以满足开发一个网络爬虫的所有要求。
4.实施步骤
4.1 开发基于 Python 的网络爬虫
在开发过程中,我现在使用如图 3 所示的页面结构。于是我从提取作者列表开始。
我定义了 URL“https://towardsdatascience.com/archive”来抓取并用于启动 Selenium Webdriver。在下文中,我提取了运行 Selenium Webdriver 所需的所有代码部分。
# Import
from selenium import webdriver
from selenium.webdriver.chrome.options import Options# Define Browser Options
chrome_options = Options()
chrome_options.add_argument("--headless") # Hides the browser window# Reference the local Chromedriver instance
chrome_path = r'/usr/local/bin/chromedriver'
driver = webdriver.Chrome(executable_path=chrome_path, options=chrome_options)# Run the Webdriver, save page an quit browser
driver.get("https:/towardsdatascience.com/archive")
<scroll page snippet goes here>
htmltext = driver.page_source
driver.quit()
因为命令“driver.get()”只打开浏览器并加载引用的页面,所以我进一步使用了一个代码片段,该代码片段自动将页面向下滚动到末尾,从而允许保存完整的 HTML 源代码(“driver.page_source”)。
#imports
import time# Scroll page to load whole content
last_height = driver.execute_script("return document.body.scrollHeight")
while True:
# Scroll down to the bottom.
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
# Wait to load the page
time.sleep(2)
# Calculate new scroll height and compare with last height.
new_height = driver.execute_script("return document.body.scrollHeight")
if new_height == last_height:
break
last_height = new_height
该代码片段完全独立于任何特定于网站的结构,也可以在另一个 web 爬行环境中轻松重用。
由于输出仍然只有 HTML 源代码,而我在寻找所有作者的列表,我写了一个“for 循环”,通过使用我从源代码检查中获得的知识提取到作者简介的链接(见第 3.1 章)。
# Parse HTML structure
soup = BeautifulSoup(htmltext, "lxml")# Extract links to profiles from TWDS Authors
authors = []
for link in soup.find_all("a",
class_="link link--darker link--darken u-accentColor--textDarken u-baseColor--link u-fontSize14 u-flex1"):
authors.append(link.get('href'))

图 6 —作者列表的输出
现在的结果是一个列表,其中包含指向各个作者的链接,可以很容易地进一步利用这些链接(参见图 6)。我使用这个列表作为下一次迭代的输入,来接收每个作者的文章。因此,我将文章的链接和作者个人资料页面的链接作为一个键值对存储在一个字典中(见图 7)。

图 7 —提取文章的键值对示例
通过 access 中文章的链接,我遍历了不同的文章,提取了相关的字段内容,并将它们存储在一个字典(tempdic)中。在某些情况下,这可以通过在 HTML 结构中指定位置来实现。
# Extract field values and store them in json
tempdic = {}
tempdic['Article_ID'] = soup.find("meta", attrs={"name": "parsely-post-id"})["content"]
tempdic['Title'] = soup.title.string
tempdic['Author'] = soup.find("meta", attrs={"name": "author"})["content"]
在其他情况下,循环或正则表达式的使用是必要的,例如通过提取标签。
# Loop to extract tags
li = soup.select("ul > li > a")
tags = []
for link in li:
tags.append(link.string)
tempdic['Tags'] = tags
因为我现在可以系统地将文章的数据存储在字典中,所以我必须找到一种合适的方法来存储数据。
4.2 将数据存储在谷歌云数据存储中
因为我已经为每篇文章准备了一个完美的字典,而且我的重点不是准备一个合适的 SQL 数据库,所以我选择了 Google Datastore 来存储我的数据。Google Datastore 是一个托管的、NoSQL 的、无模式的数据库,用于存储非关系数据——非常适合这个用例。
使用 Google Datastore,需要在 Google 云平台设置项目( 如何设置 Google 云项目);当然也可以用其他云提供商来代替。要使用 Python 访问 Google Datastore,可能需要在项目中设置一个对 Datastore 具有访问权限的服务帐户(角色:Cloud Datastore-Owner)。这可以通过生成访问密钥在菜单路径“API&Services>Credentials”中完成。
当从 JSON 文件调用数据时,使用生成的连接数据是最容易的。这是如何产生的,可以从下面的链接看出来。
在 web crawler 源代码中,必须首先初始化连接。特此引用 JSON 文件(“sa.json”)。
def initializeGDS(self):
global credentials
global client
print("Setup Database Connection")
credentials = compute_engine.Credentials()
# Service account
client = datastore.Client.from_service_account_json('sa.json')
添加所有相关信息后,实体最终可以存储在数据存储中。
Article = datastore.Entity(client.key('Article_ID', str_articlenumber), exclude_from_indexes=['Text'])
Article.update({
"URL": str_URL,
"Title": str_title,
"Author": str_author,
"PublishingDate": str_pubdate,
"Text": str_text,
"Claps": int_claps,
"Tags": Tag_list,
"No_Responses": int_responses,
"Reading_time": int_reading_time
})
client.put(Article)
网络爬虫的功能现在完成了。由于实现仍然在 Jupyter Notebook 中运行,现在是时候重构代码并使用带有指定方法的爬虫类了(见 TWDS 爬虫)
4.3 用 Docker 封装您的应用程序
由于 Docker 是软件开发中最相关的容器平台,也是许多实现的一部分,所以我不会在本文中解释任何进一步的背景知识。然而,这是我第一次使用 Docker,我寻找了一个方便的分步教程来封装我的 Python 应用程序,它可能会使用。
[## 在 5 分钟内封装一个 Python 应用程序— Wintellect
不管是好是坏,Python 已经成为数据科学的通用语言。随着它越来越受欢迎…
www.wintellect.com](https://www.wintellect.com/containerize-python-app-5-minutes/)
为了构建第一个容器映像,我只使用了这四个文件( GitHub-Repository ):
- 应用文件:在我们的例子中是 TWDS_Crawler.py
- sa.json: 您在上一节中生成的 json 文件,其中包含您的 GCP 项目的连接细节
- Dockerfile: 这个文件包含了用户可以在命令行上调用的所有命令来组合一个图像
- Requirements.txt: 指定使用的 Python 包
要构建容器映像,需要在 shell 中输入包含引用文件的目录文件夹,并编写以下命令:
docker build -t twds-crawler .
这只是将容器映像的名称指定为“twds-crawler ”,并将映像放在当前目录文件夹(“.”).要运行容器,应该使用以下命令:
docker run twds-crawler
由于预先配置了 Dockerfile,容器内部的 Python 应用程序会在容器运行后自动启动。输出应该看起来像这样:

图 Docker 运行命令的输出
web crawler 应用程序启动(“Start Crawler”)并打开 getAuthors 方法(“Get Authors”),但随后由于缺少浏览器实例而崩溃。现在,可以忽略这一点,因为我们的目标是在 Kubernetes 集群中运行这个容器。
4.4 在谷歌云平台上运行 Kubernetes 集群
Kubernetes 是一个开源系统,用于自动化(docker-)容器应用程序的部署、扩展和管理。由于它是由谷歌开发的,谷歌云平台提供了一个很好的实现,因此您可以通过使用浏览器内部的谷歌云外壳和以下脚本来构建一个仅的集群。只需将<您的项目名称>替换为您的 Google 云平台项目名称。

图 9 —谷歌云外壳的设置
注意:我建议使用编辑器的方式来显示所有存储的文件。
# Define project variable
export PROJECT_ID=<Your Project Name># Start Cluster
gcloud beta container — project ${PROJECT_ID} clusters create “twdscrawler” — zone “us-central1-a” — no-enable-basic-auth — cluster-version “1.13.11-gke.14” — machine-type “n1-standard-1” — image-type “COS” — disk-type “pd-standard” — disk-size “100” — metadata disable-legacy-endpoints=true — scopes “https://www.googleapis.com/auth/devstorage.read_only","https://www.googleapis.com/auth/logging.write","https://www.googleapis.com/auth/monitoring","https://www.googleapis.com/auth/servicecontrol","https://www.googleapis.com/auth/service.management.readonly","https://www.googleapis.com/auth/trace.append" — num-nodes “2” — enable-cloud-logging — enable-cloud-monitoring — enable-ip-alias — network “projects/${PROJECT_ID}/global/networks/default” — subnetwork “projects/${PROJECT_ID}/regions/us-central1/subnetworks/default” — default-max-pods-per-node “110” — enable-autoscaling — min-nodes “2” — max-nodes “8” — addons HorizontalPodAutoscaling,HttpLoadBalancing — no-enable-autoupgrade — enable-autorepair
要在部署完成后从 shell 访问集群,只需使用以下命令:
gcloud container clusters get-credentials twdscrawler — zone us-central1-a — project <Your Project Name>
创建的 Kubernetes 集群具有自动伸缩功能,最少使用 2 个节点,最多使用 8 个节点(注:为了节省资金,请确保在使用后删除集群,参见主菜单点“Kubernetes 引擎”)。
我们现在准备部署 selenium 网格和我们的容器化网络爬虫。
4.5 Kubernetes 上的硒网格
Selenium 网格是 Selenium 的一个集线器/节点结构,具有潜在的异构浏览器版本(节点)和一个控制单元(集线器),该控制单元分布或并行化工作项目,例如单元测试或爬行作业。为了连接这两个对象,还有一个中心服务。有关更详细的描述,请查看此链接。
为了使部署过程尽可能简单,并将必要的代码减到最少,我使用了 YAML 文件和 bash 脚本。YAML 文件描述 Kubernetes 对象,例如,在节点的情况下,要部署的不同 Selenium 节点的数量或特定的浏览器版本。bash 脚本以正确的顺序调用不同的 YAML 文件。
要在 Google Cloud shell 中工作,需要上传不同的文件。这可以很容易地通过拖放来完成。以下文件必须在其中(sa.json 需要单独添加,其余的可以在我的 GitHub-Repository 中找到)。

图 10 —云外壳中所需的文档
通过使用下面的命令,一个完整的 Selenium 网格和一个 Firefox 节点将被部署在 Kubernetes 集群上:
bash StartSelenium.sh
要检查一切是否正常,可以使用以下命令:
kubectl get pods

图 11-Kubernetes 上运行的 pod 概述
4.6 Kubernetes 上的网络爬虫
既然带有 Firefox 节点的 Selenium 网格已经在 Kubernetes 集群上运行,那么是时候继续使用 web 爬虫了。由于 web crawler 的本地开发以及本地 web 浏览器的使用,有必要针对 Selenium 网格调整 Webdriver:
# Define Remote Webdriver
driver = webdriver.Remote(
command_executor=’http://selenium-hub:4444/wd/hub',
desired_capabilities=getattr(DesiredCapabilities, “FIREFOX”)
)
注:调整后的版本可以在我的 GitHub-Repository 中找到。只需要替换 TWDS _ 爬虫. py 的代码或者把 docker 文件里面引用的文件改成“TWDS _ 爬虫 _ 集群. py”。
经过这次更改后,可以在 Google Cloud Shell 中构建一个新的 Docker 映像,并将其发布到 Google Cloud Container Registry 中(相当于一个存储库)。这可以通过以下命令完成:
export PROJECT_ID=<Your Project Name>
docker build -t gcr.io/${PROJECT_ID}/twds-crawler .
docker push gcr.io/${PROJECT_ID}/twds-crawler
如果一切正常,web 爬行器最终可以部署到 Kubernetes 集群中
bash StartCrawler.sh
要检查爬虫是否运行并查看日志(例如打印的行),您可以在 Google Cloud Shell 中使用以下命令:
kubectl get pods

图 12 —在 Kubernetes 上运行的带有爬行器的吊舱概述
kubectl logs <crawler-pod-name>

图 Crawler pod 的日志输出
网络爬虫现在正在运行。为了增加节点的数量,必须提前编辑 Firefox 节点的 YAML 文件,或者在运行时使用以下命令:
kubectl scale deployment selenium-node-firefox --replicas=10
Selenium 网格将在 web 爬行过程中自动使用部署的 Firefox 节点实例。
5.结果
如果一切都运行良好,那么当我选择增量方法在数据库中编写文章细节时,结果应该在 Google Cloud Datastore 中可见。

图 14——Google 云数据存储中实体 Article_ID 的结果概述
希望您喜欢阅读我的文章,并祝您的实现好运。
如果你在设置项目时有任何问题,也请看看我的 GitHub-Repository 中的故障排除区。
相关文章:
要了解如何使用 PySpark 和 Kubernetes 对结果进行自然语言处理并提取技术名称,请看一下 Jürgen Schmidl 的项目。
要了解如何构建一个同样运行在 Kubernetes 上的高度可伸缩的 Python 仪表盘,请查看 Arnold Lutsch 的项目。
使用 Numpy 构建一个简单的神经网络
使用 NumPy 构建单个神经元进行图像分类。
在本文中,我们将讨论如何使用 NumPy 制作一个简单的神经网络。
- 导入库
首先,我们将导入所有我们需要的包。我们将需要 numpy , h5py (用于加载存储在 H5 文件中的数据集),以及 matplotlib (用于绘图)。
**import** numpy as np
**import** matplotlib.pyplot as plt
**import** h5py
2。数据准备
数据以(" . h5 ")格式提供,包含标记为 cat 或非 cat 的训练和测试图像集。该数据集可从 github repo 下载。使用以下函数加载数据集:
**def** **load_dataset**():
train_dataset = h5py.File('datasets/train_catvnoncat.h5', "r")
train_x = np.array(train_dataset["train_set_x"][:])
train_y = np.array(train_dataset["train_set_y"][:])test_dataset = h5py.File('datasets/test_catvnoncat.h5', "r")
test_x = np.array(test_dataset["test_set_x"][:])
test_y = np.array(test_dataset["test_set_y"][:])classes = np.array(test_dataset["list_classes"][:])
train_y = train_y.reshape((1, train_y.shape[0]))
test_y = test_y.reshape((1, test_y.shape[0]))
return train_x, train_y, test_x, test_y, classes
我们可以通过观察它们的形状来分析数据。
train_x, train_y, test_x, test_y, classes = load_dataset()print ("Train X shape: " + str(train_x.shape))
print ("Train Y shape: " + str(train_y.shape))print ("Test X shape: " + str(test_x.shape))
print ("Test Y shape: " + str(test_y.shape))

我们有 209 个训练图像,其中每个图像是正方形(高度= 64px)和(宽度= 64px)且具有 3 个通道(RGB)。类似地,我们有 50 个相同维度的测试图像。
让我们想象一下这个图像。您可以更改索引来查看不同的图像。
*# change index for another image*
index = 2
plt.imshow(train_x[index])

数据预处理:图像数据常见的数据预处理包括:
- 算出数据的维度和形状(m_train,m_test,num_px,…)
- 重塑数据集,使每个示例现在都是一个大小为(高度宽度通道,1)的向量
- 将数据“标准化”
首先,我们需要使图像变平。这可以通过在形状的 numpy 数组(高度÷宽度÷通道,1)中重塑形状(高度、宽度、通道)的图像来完成。
train_x = train_x.reshape(train_x.shape[0], -1).T
test_x = test_x.reshape(test_x.shape[0], -1).Tprint ("Train X shape: " + str(train_x.shape))
print ("Train Y shape: " + str(train_y.shape))print ("Test X shape: " + str(test_x.shape))
print ("Test Y shape: " + str(test_y.shape))

标准化数据:机器学习中常见的预处理步骤是对数据集进行居中和标准化。对于给定的图片数据集,可以通过将数据集的每一行除以 255(像素通道的最大值)来完成。
train_x = train_x/255.
test_x = test_x/255.
现在我们将建立一个简单的神经网络模型,它可以正确地将图片分类为猫或非猫。
3.神经网络模型
我们将构建一个神经网络,如下图所示。

关键步骤:构建神经网络的主要步骤有:
- 定义模型结构(如输入特征数量、输出数量等)。)
- 初始化模型的参数(权重和偏差)
- 循环:
- 计算电流损耗(正向传播)
- 计算电流梯度(反向传播)
- 更新参数(梯度下降)
3.1 激活功能
sigmoid 激活函数由下式给出

可以使用 np.exp()计算 sigmoid 激活函数。
def **sigmoid**(z):
return 1/(1+np.exp(-z))
3.2 初始化参数
我们需要初始化参数𝑤(权重)和𝑏(偏差)。在下面的例子中,𝑤使用 np.random.randn() 初始化为一个随机数向量,而𝑏初始化为零。
def **initialize_parameters**(dim):
w = np.random.randn(dim, 1)*0.01
b = 0
return w, b
3.3 正向和反向传播
一旦参数被初始化,我们就可以执行“向前”和“向后”传播步骤来学习参数。
- 给定一组输入特征(X)。
- 我们将如下计算激活函数。

- 我们将按如下方式计算成本。

- 最后,我们将如下计算梯度(反向传播)。

def **propagate**(w, b, X, Y):
m = X.shape[1]
#calculate activation function
A = **sigmoid**(np.dot(w.T, X)+b) #find the cost
cost = (-1/m) * np.sum(Y * np.log(A) + (1 - Y) * (np.log(1 - A)))
#find gradient (back propagation)
dw = (1/m) * np.dot(X, (A-Y).T)
db = (1/m) * np.sum(A-Y) cost = np.squeeze(cost)
grads = {"dw": dw,
"db": db}
return grads, cost
3.4 优化
在初始化参数、计算成本函数和计算梯度之后,我们现在可以使用梯度下降来更新参数。
def **gradient_descent**(w, b, X, Y, iterations, learning_rate):
costs = []
for i in range(iterations):
grads, cost = propagate(w, b, X, Y)
#update parameters
w = w - learning_rate * grads["dw"]
b = b - learning_rate * grads["db"]
costs.append(cost)
if i % 500 == 0:
print ("Cost after iteration %i: %f" %(i, cost))
params = {"w": w,
"b": b}
return params, costs
3.5 预测
使用学习到的参数 w 和 b,我们可以预测训练或测试示例的标签。为了预测,我们首先需要计算如下给出的激活函数。

然后将输出(预测)转换成 0(ifA<= 0.5)或 1(ifA>0.5)存储在 y_pred 中。
def **predict**(w, b, X):
# number of example
m = X.shape[1]
y_pred = np.zeros((1,m))
w = w.reshape(X.shape[0], 1)
A = sigmoid(np.dot(w.T, X)+b)
for i in range(A.shape[1]):
y_pred[0,i] = 1 if A[0,i] >0.5 else 0
pass
return y_pred
3.6 最终模型
我们可以按正确的顺序把所有的构件放在一起,制作一个神经网络模型。
def **model**(train_x, train_y, test_x, test_y, iterations, learning_rate):
w, b = **initialize_parameters**(train_x.shape[0])
parameters, costs = **gradient_descent**(w, b, train_x, train_y, iterations, learning_rate)
w = parameters["w"]
b = parameters["b"]
# predict
train_pred_y = **predict**(w, b, train_x)
test_pred_y = **predict**(w, b, test_x) print("Train Acc: {} %".format(100 - np.mean(np.abs(train_pred_y - train_y)) * 100))
print("Test Acc: {} %".format(100 - np.mean(np.abs(test_pred_y - test_y)) * 100))
return costs
我们可以使用下面的代码,使用上面构建的模型对图像数据集进行训练和预测。我们将使用 0.005 的 learning_rate ,并为 2000 次迭代训练模型。
costs = **model**(train_x, train_y, test_x, test_y, iterations = 2000, learning_rate = 0.005)

训练准确率在 99%左右,这意味着我们的模型正在工作,并且以高概率拟合训练数据。测试准确率在 70%左右。给定简单的模型和小的数据集,我们可以认为它是一个好的模型。
最后,我们可以画出成本图,看看模型是如何学习参数的。
plt.plot(costs)
plt.ylabel('cost')
plt.xlabel('iterations')
plt.title("Learning rate =" + str(d["learning_rate"]))
plt.show()

我们可以看到每次迭代的成本都在下降,这表明参数正在被学习。
在下篇中,我们将讨论如何制作一个带隐藏层的神经。
在这里成为媒体会员并支持独立写作,每月 5 美元,可以完全访问媒体上的每个故事。
构建简单的 Web 应用程序
使用免费的智能框架,如 Flask 和 Heroku
作为一名技术专家和数据科学家,我从逻辑学家的角度看待日常任务。无论我是在企业范围内从事复杂的项目,还是在家做琐碎的家务,我都发现自己幻想着能够优雅而高效地管理我的工作流程的自动化解决方案。由于新冠肺炎的激增,我们中的许多人都是 WFH,专业和个人责任的冲突使我们的日常工作变得错综复杂,没有比现在更好的时机来自动化任务并将这些解决方案部署到 web 上。先说简单的吧!

来源: beccatapert 经 unsplash (CC0)
就像你们中的许多人被困在家里一样,我一直拼命想了解新冠肺炎的最新动态。大量的实证新闻文章和创造性的应对机制在我的收件箱和新闻订阅中快速掠过。一个共同的线索?耐心越来越少!和我们爱的人一起被隔离(或者更糟,被单独隔离)加剧了那些我们通常可以置之度外的小气恼和怨恨。让我家每个人都不爽的事情是每周准备晚餐。
为了每个人的理智,我决定将每周的膳食准备民主化,并简化这个过程。与其在周末花太多时间浏览互联网,从众多流行的在线资料库中选择食谱,与我可爱但挑剔的家人争论/讨价还价,比较配料/说明以最大限度地节省时间和金钱…
🤦
…我们现在只需将我们最喜欢的食谱汇总到一个由 GitHub Pages 托管并通过 Flask 和 Heroku 部署的易用、响应迅速的在线应用程序中。它超级简单,可以创造性地应用于你和你的检疫同伴争吵的任何数量的艰巨任务。看一看成品:
[## 完美应用
garretteichhorn.github.io](https://garretteichhorn.github.io/recipe_generator/)
步骤:
- 用 BeautifulSoup 和 Splinter 从一些你喜欢的在线供应商那里搜集食谱。在深入研究之前,一定要温习一些网上搜集的法律理论。
- 创建一个定制的搜索引擎来返回相关的食谱。
- 用 HTML 和 Javascript (CSS 可选)搭建一个简单的前端网站,用 GitHub 页面托管。
- 使用 Flask 通过 API 访问您的食谱,这是一个用 Python 编写的出色的微型网络框架。
- 使用 Heroku 来托管您的 API,而不是使用本地主机资源。
网页抓取:
BeautifulSoup 和 Splinter 让我们可以轻松地遍历网页,提取我们需要的数据。每个网站都有一个 DOM,它是一棵树,其结构由嵌套的标签定义。Beautiful Soup 浏览这棵树,然后将它转换成一个专门化的对象,该对象配备了强大的方法来遍历和搜索 HTML 中的属性、文本等。Splinter 是一个使用 Python 测试 web 应用程序的开源工具。它让你自动化浏览器的动作,比如访问 URL 和与它们的项目交互。
半生不熟的收获是我最喜欢的健康美味食谱的地方之一。看一下下面的代码,通过网站迭代提取相关的数据,如配料、说明、图像等!
通过检查 HTML,我们可以很容易地为其他食谱网站复制这一点。对于我构建的应用程序,我从其他几个菜谱存储库中收集菜谱,创建一个以 JSON 格式存储的菜谱数据的自定义数据库。
搜索引擎
在搜集了所有这些精彩的食谱数据之后,我们需要某种方法来只提取相关的信息。我们可以使用基本的比较操作符来检查文本中的搜索词,但是这有什么意思呢?另外,简单地检查食谱标题是否包含“鸡肉”有一些严重的局限性。
相反,我们可以构建一个搜索引擎来返回按相关性排序的食谱。使用一点数学知识,我们可以利用 scikit-learn 来清理、标记和构建一个加权矩阵,以将输入搜索词与一个文本字符串相关联。
有很多方法可以使用这个强大的工具!我们可以发挥创意,只返回余弦相似度超过特定阈值的食谱。根据食谱数据库的大小,我们可能希望将所有相关的食谱作为一个解析的数组返回,然后使用另一个搜索词进行迭代。对于这个应用程序,我只是返回所有搜索项相似度> 0 的食谱,并让我的随机函数选择一个。
GitHub Pages 托管的前端
尽管我们能够使用 python 来获取食谱,并基于搜索词返回相关选项,但这种功能对于我这个不懂技术的家庭来说还无法使用。我需要使用一个简单的界面,要求一个搜索词,并显示食谱图像,配料和说明。我们将转向 HTML 和 JavaScript 来完成繁重的工作。
声明:我非常尊重网页开发者!有一些非常棒的开源前端框架,可以帮助你建立快速响应的网站。我更喜欢引导和 D3 来实现高效部署。
GitHub 有一个令人惊叹的网站托管服务,叫做 GitHub Pages 。你可以看看下面我的知识库,它使用 GitHub Pages 和 JavaScript 来构建 HTML(带有嵌入式样式)和显示食谱数据。
这个应用程序的创建是为了让周日的膳食计划更容易!穿越…的日子一去不复返了
github.com](https://github.com/GarrettEichhorn/recipe_generator.git)
用 Flask 构建一个 API
接下来呢?我们有 JSON 格式的所有这些精彩的食谱数据,一个用 python 编写的搜索引擎来帮助我们提取相关选项,还有一个简单的网站,对我的家人来说非常容易使用。为了让这些组件相互交互,我们需要使用一个应用程序编程接口。web API 允许其他程序通过互联网操纵信息或功能。
让我们欢迎烧瓶参加派对!!!Flask 将 HTTP 请求映射到 Python 函数,允许我们基于端点运行特定的代码。当我们连接到位于 http://127.0.0.1:5000/ 的 Flask 服务器时,Flask 会检查所提供的路径和定义的函数之间是否匹配。我们将使用 Flask 来处理一个输入搜索查询,作为运行我们之前定义的搜索引擎功能的给定端点。
例如,我们可以发送…
[http://127.0.0.1:5000/chicken](http://127.0.0.1:5000/chicken)
…让 flask 将“鸡肉”作为 return_relevant_recipes()函数的参数进行处理。太棒了。
部署到 Heroku
最后,我们需要使用 Gunicorn 将 API 部署到 Heroku 上,这样我们就不需要依赖本地主机资源让用户访问搜索引擎功能。Heroku 是一个云平台即服务,支持我们在这个项目中使用的几种编程语言。很喜欢这个教程快速设置必要的需求(Procfile,requirements.txt,git connection 等。)我们需要部署到 Heroku。Gunicorn 是一个高性能的 web 服务器,可以在生产环境中运行 Flask 应用程序。
一旦您有效地部署了 API,您将更新 JavaScript 代码,将一个搜索词作为端点发送到https://reciperfect.herokuapp.com而不是您的本地主机。就这么简单。
结论
本文概述了使用几种流行的开源工具和框架来自动化艰巨任务的必要组件。发挥创造力!在我的家人转而使用我的应用程序之前,每周做饭是一件非常棘手的事情,我们没有回头看!当我们对目前的食谱感到厌倦时,我需要做的就是再刮一些。你可以用这个纲要来自动化许多平凡的杂务,让新冠肺炎的生活稍微轻松一点。
我的公开回购可以在这里找到。感谢阅读!
使用 Django 构建一个社交媒体网站——设置项目(第 1 部分)
Django 的社交媒体网站
重点放在设置项目和安装所需的组件与设置密码恢复后端

读者们好,我想做一些不同的事情,比如在 Medium 上制作一个多部分的教程。所以,现在我正在制作这个关于学习 Django 的系列教程。这个教程系列对初学者友好,将通过做一些实际的项目来帮助初学者学习 Django。
为了保持简单,我们不会在这个项目中使用任何前端框架。我们将在项目中使用 HTML、CSS (Bootstrap 和一些自定义 CSS)和 JQuery。
本教程系列的主要重点是学习 Django,所以我们将主要关注 Django。
那么,让我们来谈谈我们将要做的项目。这将是一个简单的社交媒体网站,用户可以做以下事情:
- 张贴图片以及描述和标签。您可以随时更新或删除它们。
- 查看其他人的个人资料并向他们发送好友请求,或者取消误发的好友请求。
- 接受或拒绝来自其他用户的好友请求。
- 取消现有朋友的好友关系。
- 根据标签搜索帖子。
- 根据用户名搜索用户。
- 发现新的人部分推荐新的人添加为朋友的基础上相互联系。
这些都将是我们将要建立的网站的特点。所以,我们一部分一部分来。
因此,在第一个教程中,我们将设置 Django 项目。
建立一个新的 Django 项目
因此,建立一个新的 Django 项目非常简单。首先,如果你以前没有安装过 Django,你需要安装它。
要安装 Django,我们需要运行以下命令:
pip install django
这个命令将在我们的系统中安装 Django。现在,我们准备使用 Django。那么,现在让我们开始我们的 Django 项目。我们将使用下面的命令来创建一个新的 Django 项目。
django-admin startproject photoshare
这里,照片分享表示我们想给 Django 项目取的名字。
它将为我们创建和设置 Django 项目。如果你在创建的文件夹里找,里面会有很多文件。它会有一个 manage.py 文件和一个 photoshare 文件夹。您不应该重命名该文件夹。不过,您可以重命名外层文件夹。
在 photoshare 文件夹内,可以看到 urls.py、settings.py 等各种文件。你可以看到所有这些文件都写有代码。随着项目的进展,我们将向它们添加我们的代码。
我们可以在本地服务器上运行网站,检查是否一切正常。
为此,我们将在 CLI 上 manage.py 文件所在的同一文件夹中运行以下命令:
python manage.py runserver
这将呈现 Django 默认页面,如下所示:

姜戈祝贺页面
现在,运行以下命令进行数据库迁移,然后迁移以同步数据库。
它有一个内置的 SQLite3 数据库,我们将使用它进行开发和测试。以后进入生产时,您可以切换到功能更强的数据库,比如 Postgre SQL。
因此,您可以运行以下两个命令来执行迁移:
python manage.py makemigrations
python manage.py migrate
现在,我想告诉你姜戈的一个强大的部分。它带有一个内置的管理面板。因此,我们不需要建立一个自己的管理面板。如果我们愿意的话,我们当然可以在以后创建一个设计更好的自定义管理面板,但是默认面板对我们来说已经足够了。
因此,要访问管理面板,我们必须创建一个超级用户。超级用户将有权访问管理面板,并可以编辑数据库元素。
要创建超级用户,我们可以运行以下命令:
python manage.py createsuperuser
运行此命令后,将在 CLI 中要求您输入用户名、电子邮件和密码。然后它会为你创建超级用户。
现在,您可以访问管理面板,您可以通过再次运行服务器来访问它。服务器启动并运行后,您可以在 /admin 页面访问管理面板。通过将 /admin 添加到默认 URL 来访问它,默认 URL 看起来像 localhost:8000/admin 或 127.0.0.1:800/admin 。

Django 管理员登录页面-https://djangobook.com/mdj2-django-admin/
输入您的凭证后,您将被带到 Django 管理仪表板,如下所示:

Django 管理主页-https://developer . Mozilla . org/en-US/docs/Learn/Server-side/Django/Admin _ site
您的管理员主页目前只有“组和用户”字段。当您创建新模型并将其添加到管理面板时,它们会出现在这里。
现在,正如您将看到的,将有一个用户,即您,您可以看到您拥有超级用户访问权限,因为您会在管理控制面板的用户配置文件中看到超级用户访问权限旁边的绿色勾号。
现在,我们很乐意创建所需的应用程序(Django 中项目的一小部分被称为应用程序)。我们将有两个独立的应用程序——用户和 Feed。
用户应用程序将处理所有关于认证、用户配置文件、朋友和发送、接收请求、搜索用户和结交新朋友的模型、表单和视图,即与用户相关的一切。
Feed 应用程序将处理关于帖子的所有模型、视图和表单,即帖子、对帖子的喜欢和评论、搜索帖子、显示特定用户的帖子等。
为了在 Django 项目中创建这两个应用程序,我们将借助 CLI 并键入以下命令:
python manage.py startapp feed
python manage.py startapp users
运行以上两个命令将创建两个应用程序——feed 和 users。两者都包含一些 python 文件。我们稍后将向这些文件添加内容。
现在,让我们在内部 photoshare 文件夹的 settings.py 文件中注册我们的应用程序。在您喜欢的文本/代码编辑器中打开 settings.py 文件,并将以下代码行添加到文件中的已安装应用程序列表中。
因此,将这两个元素添加到已安装应用程序列表中:-
'users.apps.UsersConfig',
'feed.apps.FeedConfig',
它现在看起来像这样:-
INSTALLED_APPS = [
'users.apps.UsersConfig',
'feed.apps.FeedConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
不要删除已安装应用程序列表中的任何内容。
此外,我们将使用crisp forms来风格化我们稍后将创建的 Django 表单,所以让我们也安装它。
pip install django-crispy-forms
此外,由于它也是一个应用程序,我们必须将其添加到 settings.py 文件中的已安装应用程序列表中。添加后,我们的 INSTALLED_APPS 列表将如下所示:
INSTALLED_APPS = [
'users.apps.UsersConfig',
'feed.apps.FeedConfig',
'crispy_forms',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
此外,由于 crispy_forms 默认使用 Bootstrap 3,我们希望将其设置为使用 Bootstrap 4。为此,请在 settings.py 文件的末尾添加这一行。
CRISPY_TEMPLATE_PACK = 'bootstrap4'
此外,我们需要指定静态和媒体路径。为此,我们需要将操作系统导入到设置文件中。
为此,我们将在 settings.py 文件中添加以下行(如果已经存在,跳过任何一行):
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATIC_URL = '/static/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
现在,让我们再添加一些设置来帮助我们告诉 Django 在那些特殊的情况下应该做什么。
LOGIN_REDIRECT_URL = 'home'
LOGIN_URL = 'login'
第一行命令 Django 在成功登录后转到“home”页面。我们将在网站的第一页保留我们的“主页”。您可以选择要将用户重定向到的页面。
第二行指示 Django 在搜索显示登录页面所需的 URL 时使用“log in”URL 名称中指定的路径。你以后会明白的。
现在,让我们设置密码恢复系统。当用户请求重置密码时,我们将发送一封电子邮件。为此,我们将使用 Gmail。
获取 Gmail 主机用户(您的 Gmail id)和密码(通过访问此链接生成您的密码)。本教程将有助于完成这项任务。
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = os.environ.get('EMAIL_HOST_USER')
EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_HOST_PASSWORD')
这些设置将确保您可以毫无问题地构建您的应用程序。身份验证系统可以很好地恢复密码。
所以,现在你已经建立了你的项目,现在在下一个教程中,我们将制作用户应用。
我希望你喜欢本教程的第一部分;这都是关于设置。下一部分将带你到网站的实际建设。
一个类似的以 Django 为中心的系列(建立一个求职门户)将教你一些惊人的新概念,它是:
[## 用 Django 构建求职门户——概述(第 1 部分)
让我们使用 Django 建立一个工作搜索门户,它允许招聘人员发布工作并接受候选人,同时…
shubhamstudent5.medium.com](https://shubhamstudent5.medium.com/build-a-job-search-portal-with-django-overview-part-1-bec74d3b6f4e)
如果你想在 Django 上更进一步,你可以尝试这个基于 Django Rest 框架的新系列,我们将使用 Django Rest 框架构建一个博客网站。
[## 使用 Django Rest 框架构建博客网站——概述(第 1 部分)
让我们使用 Django Rest 框架构建一个简单的博客网站,了解 DRF 和 REST APIs 如何工作,以及我们如何添加…
towardsdatascience.com](/build-a-blog-website-using-django-rest-framework-overview-part-1-1f847d53753f)
一系列关于建立一个电子商务系列与 MERN 堆栈在这里:-
[## 用 MERN 堆栈构建一个电子商务网站——第 1 部分(设置项目)
让我们使用 MERN 堆栈(MongoDB,Express,React 和 Node)建立一个简单的电子商务网站,用户可以在其中添加项目…
shubhamstudent5.medium.com](https://shubhamstudent5.medium.com/build-an-e-commerce-website-with-mern-stack-part-1-setting-up-the-project-eecd710e2696)
如果您有兴趣学习 React,这个系列很适合您:
[## 使用 React 构建一个博客应用程序——介绍和设置(第 1 部分)
在第一部分中,我们处理项目的基础并设置它。
javascript.plainenglish.io](https://javascript.plainenglish.io/build-a-blog-app-with-react-intro-and-set-up-part-1-ddf5c674d25b)
本教程的下一部分是:-
[## 用 Django-Users App 建立一个社交媒体网站(第二部分)
在这一部分中,我们将重点创建用户应用程序以及与用户配置文件、身份验证等相关的所有模型
towardsdatascience.com](/build-a-social-media-website-with-django-users-app-part-2-7f0c0431ccdc) [## 用 Django 构建一个社交媒体网站——第 3 部分(用户应用模板)
在第三部分中,我们将着重于为我们在上一个教程中定义的用户应用程序构建模板。
towardsdatascience.com](/build-a-social-media-website-with-django-part-3-users-app-templates-c87ad46682be) [## 用 Django 构建一个社交媒体网站——Feed 应用后端(第 4 部分)
在这一部分中,我们将重点放在构建 Feed 应用程序及其所有与喜欢、评论、帖子和所有相关的模型上
shubhamstudent5.medium.com](https://shubhamstudent5.medium.com/build-a-social-media-website-with-django-feed-app-backend-part-4-d82facfa7b3) [## 用 Django 构建一个社交媒体网站——第 5 部分(Feed 应用程序模板)
在第五部分中,我们将着重于为我们在上一个教程中定义的 Feed 应用程序构建模板。
towardsdatascience.com](/build-a-social-media-website-with-django-part-5-feed-app-templates-66ddad5420ca)
另外,你可以看看这些文章
[## 使用 React 构建一个简单的 Todo 应用程序
让我们用 React 构建一个简单的 Todo 应用程序,它教你 CRUD 的基本原理(创建、读取、更新和…
medium.com](https://medium.com/javascript-in-plain-english/build-a-simple-todo-app-using-react-a492adc9c8a4) [## 用 Node,Express 和 MongoDB 构建一个 REST API
让我们使用 Node、Express 和 MongoDB 构建一个遵循 CRUD 原则的 REST API,并使用 Postman 测试它。
medium.com](https://medium.com/javascript-in-plain-english/build-a-rest-api-with-node-express-and-mongodb-937ff95f23a5)
如果你想看完整的代码,请查看项目的 GitHub Repo 。另外,你可以通过访问这个链接来试用这个应用程序。它托管在 Heroku 上,媒体和静态文件在 Google 云存储上。
用 Django 构建一个社交媒体网站——Feed 应用后端(第 4 部分)
在这一部分中,我们将重点构建 Feed 应用程序及其所有与赞、评论、帖子以及所有相关表单和视图相关的模型。

所以,在教程系列的第二部和第三部中,我们已经分别讨论了用户 app 后端及其模板。
所以,在这一部分(第四部),我们将开始讨论 Feed app。在这一部分,我们将重点关注 Feed 应用程序的后端(模型、视图、表单等)。),我们将在下一部分讨论 Feed 应用程序的模板。
在继续之前,我想确保您已经阅读了本系列前面的所有部分;否则,阅读这篇文章就没什么意义了,尽管如果你只想关注具体细节而不是整个网站,你也可以这么做。
正如我在前面的部分中提到的,我不会详细讨论各种术语,因为这太长了。我会把重点放在代码的主要方面,而不是沉迷于简单的术语。
为了更好地理解一切,您应该熟悉 Django 术语。希望你能在第二部分中熟悉他们,但是如果你有疑问,Django 的官方网站是一个了解他们的好地方。
因此,让我们继续构建我们在教程的第一部分中创建的 Feed 应用程序。我们将首先从创建模型开始。
models.py
在这个 python 文件中,我们将定义我们的模型。您可能已经知道,定义模型是为了告诉 Django 在数据库中保存什么,并定义不同模型之间的关系以及它们有什么特征。
要了解更多关于 Django 模型的信息,请访问这个由 Mozilla 开发者撰写的关于模型的精彩教程。它深入讨论了模型。
当你对模型的工作方式感到满意后,你可以继续为我们的社交媒体网站制作模型。
因此,在这个 Feed 应用程序中,我们将有三个模型——一个用于帖子,一个用于评论,最后一个用于赞。
因此,像往常一样,我们将不得不首先导入各种项目。这将包括默认的 Django 用户模型和时区。
那么,我们来看看我们的第一个模型——Post模型。它有五个参数:-
- 描述——这是帖子的一部分,用户可以在这里输入与他发布的图片相关的小描述。它是可选的,因为我们不想强迫用户输入描述。它的最大长度为 255 个字符,是一个 CharField。
- pic——这是帖子最重要的部分——图片。用户将上传他们选择的图片进行上传。它将保存在提到的文件路径中。它使用一个 ImageField。
- date _ posted——它将使用 Django 的 datetime 字段,并将为每个帖子设置时间戳。我们将使用默认时间作为当前时间。
- 用户名-这是外键关系。这是一个多对一的关系,因为一个用户可以有很多帖子,但是一个帖子只能属于一个用户。当用户被删除时,文章也会被删除,on _ delete = models . cascade .的用法证明了这一点,它将文章与用户模型联系起来。
- 标签——这用于接收帖子的相关标签。它可以留空,最多 100 个字符。标签可以帮助搜索相关的文章。
接下来,我们描述 str,,它决定 Django 如何在管理面板中显示我们的模型。我们将它设置为显示描述作为查询对象。
我们还定义了 get_absolute_url 来获取这篇文章的绝对 url。
接下来,我们有评论模型。它有四个参数:-
- post-这是连接帖子和评论的外键。一条评论可以针对一篇文章,但是一篇文章可以有多条评论。删除帖子也会删除评论。
- 用户名—这是一个外键,将注释与用户相关联。删除用户时,评论也将被删除。
- comment —这是保存相关注释的 CharField。它的最大字符限制为 255 个字符。
- comment _ date——它将使用 Django 的 datetime 字段,并将为每个注释设置时间戳。我们将使用默认时间作为当前时间。
接下来,我们有了最终的模型— Likes。它有两个参数:-
- 用户——表示喜欢帖子的用户。删除用户会删除类似内容。
- 张贴——是张贴类似内容的帖子。删除帖子也会删除所有喜欢的帖子。
所以,这就总结了我们的 models.py 文件。让我们看一下代码:-
管理. py
它会很短,只有几行字。它表示我们将注册到我们的管理面板的模型。我们将在这里注册我们所有的三个模型。
forms.py
要了解 Django 中表单工作的更多信息,请访问 Django 自己编写的官方教程。然后继续学习教程。
我们在 forms.py 文件中定义了两个表单。
- NewPostForm —这是任何用户发布新帖子的地方。它接受三个字段,即描述、字段和标签。保存时提供了 user_name,因为不会向用户询问它。
- NewCommentForm —类似于 NewPostForm,我们有这个表单来接受新的评论。我们只接受要发布的评论,稍后提供帖子和用户。
view.py
现在,我们将定义 views.py 文件。它将包含我们所有的视图(如何在 web 浏览器中呈现文件)。它直接将数据传递给模板。
阅读 Django 的官方教程,以更好地理解观点。看完教程,我们继续前进。
我们将首先在我们的 views.py 文件中导入所有我们需要的东西。
由于视图文件太大,我们可以根据自己的喜好来创建它,所以我将给出每个视图的简单概述,您可以阅读下面的代码来更好地理解。所以,让我们一个一个来看:
- post listview——这个视图处理所有文章的显示,顺序是新文章放在最前面。每页显示 10 篇文章,所以我们需要移动到下一页查看更多。此外,如果用户没有通过身份验证,我们不会给他喜欢这个帖子的选项。如果用户被认证,我们显示用户是否喜欢它。
- UserPostListView —该视图几乎类似于 PostListView。排序和分页是相同的。唯一的区别是这个页面只显示某个用户的帖子。
- post_detail —该视图处理单个帖子的显示。它还显示评论表单,让用户对文章进行评论,并显示所有评论。它还显示喜欢计数,并允许您喜欢或不喜欢。
- create_post —该视图处理新帖子的创建。它保存数据并将当前用户添加为用户名,然后提交它。
- PostUpdateView —该视图处理帖子的更新。我们可以在这个视图的帮助下编辑我们的文章。
- post_delete —该视图处理帖子的删除。当用户需要时,它会删除帖子。
- search _ posts——这与我们在用户应用后端(第二部分)中的 search_users 的工作方式类似。它接收输入,并根据标签搜索帖子。
- like —该视图处理帖子的 like 事件。这是在 AJAX 请求的帮助下完成的,这样页面就不会在每次用户喜欢或不喜欢时刷新。它的工作方式是,如果帖子已经被用户喜欢,点击喜欢按钮会删除喜欢,但如果它还没有被喜欢,它会喜欢这个帖子。然后,它将响应作为 JSON 转储,并作为 HTTP 响应传递。
这总结了 views.py 文件。下面是该文件的代码。
urls.py
该文件包含 Feed 应用程序的所有 URL。所有这些 URL 都将包含在主 urls.py 文件中。
下面是提要应用程序的 urls.py 文件的代码。
如果你想看到完整的代码,查看项目的 Github Repo 。另外,你可以通过访问这个链接来试用这个应用程序。它托管在 Heroku 上,媒体和静态文件在 Google 云存储上。
教程的下一部分:-
[## 用 Django 构建一个社交媒体网站——第 5 部分(Feed 应用程序模板)
在第五部分中,我们将着重于为我们在上一个教程中定义的 Feed 应用程序构建模板。
shubhamstudent5.medium.com](https://shubhamstudent5.medium.com/build-a-social-media-website-with-django-part-5-feed-app-templates-66ddad5420ca)
一个基于 Django Rest 框架的新系列,您应该看看它以增强您的 Django 技能:
[## 使用 Django Rest 框架构建博客网站——概述(第 1 部分)
让我们使用 Django Rest 框架构建一个简单的博客网站,了解 DRF 和 REST APIs 如何工作,以及我们如何添加…
towardsdatascience.com](/build-a-blog-website-using-django-rest-framework-overview-part-1-1f847d53753f)
一个类似的以 Django 为中心的系列(建立一个求职门户)将教你一些惊人的新概念,它是:
[## 用 Django 构建求职门户——概述(第 1 部分)
让我们使用 Django 建立一个工作搜索门户,它允许招聘人员发布工作并接受候选人,同时…
shubhamstudent5.medium.com](https://shubhamstudent5.medium.com/build-a-job-search-portal-with-django-overview-part-1-bec74d3b6f4e)
React 上一篇很棒的文章是:
[## 使用 React 构建一个简单的 Todo 应用程序
让我们用 React 构建一个简单的 Todo 应用程序,它教你 CRUD 的基本原理(创建、读取、更新和…
medium.com](https://medium.com/javascript-in-plain-english/build-a-simple-todo-app-using-react-a492adc9c8a4) [## 用 Node,Express 和 MongoDB 构建一个 REST API
让我们使用 Node、Express 和 MongoDB 构建一个遵循 CRUD 原则的 REST API,并使用 Postman 测试它。
medium.com](https://medium.com/javascript-in-plain-english/build-a-rest-api-with-node-express-and-mongodb-937ff95f23a5)
用 Django 构建一个社交媒体网站——第 3 部分(用户应用模板)
在第三部分中,我们将着重于为我们在上一个教程中定义的用户应用程序构建模板。

因此,在的第二部分,我们定义了用户应用程序的所有后端部分,就像我们定义了所有的 URL、视图、模型和表单,并向管理面板注册了我们的模型。
所以,现在在第三部分,我们将关注所有显示我们在用户应用程序中编写的逻辑的模板。正如你已经知道的,用户应用程序处理所有的认证,个人资料,朋友,搜索用户,寻找新朋友和其他事情。
因此,在这一部分,会有很多 HTML,因为我们正在处理模板的一部分。它将接收用户应用程序的 views.py 文件传递的数据,并将帮助向用户显示数据,并通过表单接收用户输入。
因此,我们将所有模板放在以下位置:用户文件夹中的模板/用户。Django 的命名约定是将数据放在那里,因为 Django 在那个位置寻找模板。
我们将逐个处理模板。他们有 12 个人。我们不会详细讨论,因为它主要是 HTML 和 CSS 类,我们将只讨论逻辑部分,我们在模板中使用它来定义谁可以访问什么。那么,让我们开始吧:
login.html
先说登录部分。这个模板将让用户登录到我们的网站。这将显示登录表单,并且我们正在使用 crispy 表单来使用 Bootstrap4 格式化我们的表单。在 Django 中,表单非常容易呈现。
我们有一个提交按钮和忘记密码选项,此外,我们有一个注册页面的链接。
我们正在从我们的 Feeds 应用程序扩展布局模板。每个模板都扩展了包含页眉和页脚部分的布局。现在不要担心 layout.html 文件,因为我们将在本系列教程的第 5 部分中讨论它。
register.html
接下来,我们转到网站的注册页面。这个页面将让用户注册进入我们的网站。它还显示表单,然后显示提交按钮。我们有一个现有用户登录页面的链接。
logout.html
接下来,我们有注销页面。它只是显示一条消息,告诉用户他们已经从网站注销。他们可以选择再次登录。
请求 _ 密码 _ 重置. html
这是让用户请求密码重置的表单。用户应该提交他们的电子邮件地址,并点击重置按钮。然后,他们会收到一个链接到他们的电子邮件地址。
password _ 重置 _ 完成. html
此页面显示重置链接已发送至其电子邮件地址的消息。我们还为用户提供了一个打开 Gmail 的按钮。
密码 _ 重置 _ 确认. html
当您单击发送给您的重置链接时,将打开此页面。您可以在此处设置新密码,然后点击按钮更改密码。
密码 _ 重置 _ 完成. html
该页面显示用户的密码已被重置,现在可以使用他的新凭据登录。
profile.html
这可能是最复杂的一个,有很多东西要放进去。首先,我们可以看到 {% block searchform %},它有一个搜索栏来搜索用户。它显示在网站的导航栏中,不是 profile.html 的一部分。它只是扩展了 navbar 部分,这样搜索表单就不会显示在每一页上。
现在,来到个人资料部分,我们可以搜索;首先,我们有一张卡片,显示我们的个人资料,如个人资料照片、朋友数量和分享的帖子数量。
现在,我们已经设置了一个限制,只有我们正在查看其个人资料的用户才能查看好友列表,其他任何人都不能查看。任何人都可以看到共享的帖子。因此,我们在这里做了一个检查( {% if request.user == u%}),,检查当前用户是否等于正在查看其配置文件的用户。
接下来,如果当前用户的个人资料正在被查看,我们可以选择编辑个人资料。这限制了其他任何人更新我们的个人资料。
我们也有各种选项,如添加好友,取消请求,拒绝请求,接受请求,根据条件取消好友。
- 添加好友— 如果用户不是我们的好友,我们可以向他发送好友请求。
- 取消请求— 如果我们已经向用户发送了请求,我们可以取消它。
- 接受请求— 如果用户向我们发送了好友请求,我们可以接受。
- 拒绝请求— 如果用户向我们发送了好友请求,我们可以拒绝。
- 解除好友关系— 如果用户已经是我们的好友,并希望将其从我们的好友中移除,我们可以解除他的好友关系。
如果当前用户是其个人资料正在被查看的用户,我们将得到下面两个列表。
- 已发送的好友请求— 这些包含我们已向其发送请求的所有用户。我们可以从那里取消请求。
- 收到的好友请求— 它包含了我们收到的所有请求。我们可以接受或拒绝他们。
edit_profile.html
此页面包含我们更新个人资料所需的表格。我们可以更新我们的电子邮件,用户名,个人资料图片和简历。它有一个提交按钮来更新个人资料,并带我们回到个人资料页面。
朋友列表. html
在这里,我们显示我们所有的朋友,我们可以选择解除他们的好友关系。我们所有的朋友都显示为列表。我们还在边上显示了一张包含当前用户信息的卡片。
search _ users.html
此页面显示当我们使用搜索栏按用户名称搜索用户时出现的所有用户。这个列表包含所有的搜索结果,我们有一个选项。我们还在边上显示了一张包含当前用户信息的卡片。
users _ list.html
此列表包含推荐添加为好友的用户。是为了寻找和发现新的人,增加你的朋友。我们也可以选择添加朋友或取消所有这些用户的请求。我们还在侧面展示了一张包含当前用户信息的卡片。
这就是用户应用程序模板的全部内容。有很多 HTML 内容。希望你不会觉得无聊。但是我们必须这样做来保持教程的连贯性。我们现在剩下两个部分,将讨论 Feeds 应用程序及其模板。这些将处理所有的帖子,喜欢,评论等的逻辑和渲染。
我希望你喜欢阅读教程。非常感谢!
一个基于 Django Rest 框架的新系列,您应该看看它以增强您的 Django 技能:
[## 使用 Django Rest 框架构建博客网站——概述(第 1 部分)
让我们使用 Django Rest 框架构建一个简单的博客网站,了解 DRF 和 REST APIs 如何工作,以及我们如何添加…
towardsdatascience.com](/build-a-blog-website-using-django-rest-framework-overview-part-1-1f847d53753f)
一个类似的以 Django 为中心的系列(建立一个求职门户)将教你一些惊人的新概念,它是:
[## 用 Django 构建求职门户——概述(第 1 部分)
让我们使用 Django 建立一个工作搜索门户,它允许招聘人员发布工作并接受候选人,同时…
shubhamstudent5.medium.com](https://shubhamstudent5.medium.com/build-a-job-search-portal-with-django-overview-part-1-bec74d3b6f4e)
教程的下一部分是:-
[## 用 Django 构建一个社交媒体网站——Feed 应用后端(第 4 部分)
在这一部分中,我们将重点放在构建 Feed 应用程序及其所有与喜欢、评论、帖子和所有相关的模型上
shubhamstudent5.medium.com](https://shubhamstudent5.medium.com/build-a-social-media-website-with-django-feed-app-backend-part-4-d82facfa7b3) [## 用 Django 构建一个社交媒体网站——第 5 部分(Feed 应用程序模板)
在第五部分中,我们将着重于为我们在上一个教程中定义的 Feed 应用程序构建模板。
towardsdatascience.com](/build-a-social-media-website-with-django-part-5-feed-app-templates-66ddad5420ca)
学习 Web 开发的资源集合可以在这里找到
[## 用 Node,Express 和 MongoDB 构建一个 REST API
让我们使用 Node、Express 和 MongoDB 构建一个遵循 CRUD 原则的 REST API,并使用 Postman 测试它。
medium.com](https://medium.com/javascript-in-plain-english/build-a-rest-api-with-node-express-and-mongodb-937ff95f23a5) [## 使用 React 构建一个简单的 Todo 应用程序
让我们用 React 构建一个简单的 Todo 应用程序,它教你 CRUD 的基本原理(创建、读取、更新和…
medium.com](https://medium.com/javascript-in-plain-english/build-a-simple-todo-app-using-react-a492adc9c8a4)
用 Django 构建一个社交媒体网站——第 5 部分(Feed 应用程序模板)
在第五部分中,我们将着重于为我们在上一个教程中定义的 Feed 应用程序构建模板。

因此,在第四部分的中,我们定义了 Feed 应用程序的所有后端部分,如所有的 URL、视图、模型和表单,并在管理面板中注册了我们的模型。
因此,在第五部分,我们将关注所有用于显示我们在 Feed 应用程序中编写的逻辑的模板。正如你已经知道的,Feed 应用程序处理帖子、赞、评论和搜索帖子部分。
因此,在这一部分,会有很多 HTML,因为我们正在处理模板的一部分。它将接收 Feed 应用程序的 views.py 文件传递的数据,并将帮助向用户显示数据,并通过表单接收用户输入。
因此,我们将所有模板放在以下位置:feed 文件夹中的 templates/feed。Django 的命名约定是将数据放在那里,因为 Django 在那个位置寻找模板。
我们将逐个处理模板。他们有六个人。我们不会讲太多细节,因为它主要是 HTML 和 CSS 类,我们将只讨论我们在模板中使用的逻辑部分,以定义谁有权访问什么以及哪个部分做什么工作。那么,让我们开始吧:
create_post.html
让我们从 create_post 部分开始。这一部分涉及新职位的设立。该模板将允许用户通过添加相关的详细信息,如图像(必需的),关于图像的详细信息和标签(可选),轻松地创建新帖子。
该模板的功能是显示所需的表单,该表单将接受用户输入。有一个提交按钮来保存和提交文章,并将其添加到数据库中。
此外,在导航栏中显示了一个搜索栏,允许您搜索带有相关标签的特定帖子。
该模板扩展了 Feed 的所有其他模板和用户模板正在使用的布局模板。我们很快就会看到layout.html文件。
home.html
它还扩展了 layout.html 文件。这是我们应用程序的主页。任何登录的用户都将被重定向到此页面。该页面也无需登录即可访问。
它也有同样的搜索栏来搜索文章。这个主页的主要目的是以相关的方式显示文章。
它还检查用户是否喜欢某个帖子,并根据需要显示“喜欢”或“不喜欢”按钮。
它还有分页功能,每页只显示 10 篇文章。它也有下一页和上一页的链接。
它还有 AJAX 脚本,无需刷新页面就能实时处理赞。一旦用户喜欢它,它就把喜欢按钮变成不喜欢按钮,反之亦然。它改变按钮的颜色来表示相同的颜色。
layout.html
这是布局文件。它导入我们在网站上使用的所有需要的 CSS 和 JS 文件。我们使用 Bootstrap4 和一些自定义的 CSS 文件。
接下来,我们有一个 Navbar,它显示登录用户和未登录用户的相关链接。这样做是为了只显示所需的链接。
例如,我们将向已经登录的用户显示注销链接,并向未经认证的用户显示登录和注册链接。
我们还有一个显示名称和版权信息的小页脚。
你会注意到我们有一个{ % block content % } { % end block content % },,它保存了我们在其他页面上的所有内容信息。
同样,我们也有一个搜索模块,用于搜索帖子或人物部分。
post_detail.html
这个模板详细处理了文章的显示。它显示了完整的帖子详细信息,以及喜欢和评论数。它还有一个发布评论的部分(显示评论表单),下面是显示所有评论的部分。
此外,还有更新和删除帖子的链接。只有当此人与帖子的所有者相同时,它才会显示这些链接。否则,它不会向任何其他人显示这些按钮。
它也有相同的 AJAX 脚本来处理喜欢和不喜欢,无需刷新。
search_posts.html
这部分显示与搜索词匹配的文章。它显示所有相关的文章(搜索结果)。
这类似于主页,因为我们需要显示帖子,但不同于主页,主页显示所有帖子,这里我们显示匹配搜索词的选择性帖子。
所有其他组件都与主页相同,如 AJAX 脚本来处理喜欢和显示风格。
user_posts.html
此页面显示特定用户的帖子。它几乎与带有分页的主页相同,使用相同的 AJAX 脚本来处理赞,以及相同的帖子显示风格。
唯一的区别是它只显示特定用户的帖子。
这就是 Feed 应用程序模板的全部内容。有很多 HTML 内容。希望你不会觉得无聊。
希望你喜欢这个教程。这是 Django 社交媒体教程五部分系列的最后一部分。
我希望你们都喜欢这个完整的系列。我希望你们都能够用 Django 制作自己的社交媒体项目,并可以添加更多方面,如标记、仅通过朋友圈显示帖子、增强的推荐系统等等。
完整系列的 Github 回购在这里是。请随意对该存储库发表评论或提出任何拉取请求,这将有助于以任何方式增强它。
一个基于 Django Rest 框架的新系列,您应该看看它以增强您的 Django 技能:
[## 使用 Django Rest 框架构建博客网站——概述(第 1 部分)
让我们使用 Django Rest 框架构建一个简单的博客网站,以了解 DRF 和 REST APIs 是如何工作的,以及我们如何添加…
towardsdatascience.com](/build-a-blog-website-using-django-rest-framework-overview-part-1-1f847d53753f)
一个类似的以 Django 为中心的系列(建立一个求职门户)将教你一些惊人的新概念,它是:
[## 用 Django 构建求职门户——概述(第 1 部分)
让我们使用 Django 建立一个工作搜索门户,它允许招聘人员发布工作并接受候选人,同时…
shubhamstudent5.medium.com](https://shubhamstudent5.medium.com/build-a-job-search-portal-with-django-overview-part-1-bec74d3b6f4e)
前四部分可以在这里找到:-
[## 使用 Django 构建一个社交媒体网站——设置项目(第 1 部分)
在第一部分中,我们通过设置密码来集中设置我们的项目和安装所需的组件…
towardsdatascience.com](/build-a-social-media-website-using-django-setup-the-project-part-1-6e1932c9f221) [## 用 Django-Users App 建立一个社交媒体网站(第二部分)
在这一部分中,我们将重点创建用户应用程序以及与用户配置文件、身份验证等相关的所有模型
towardsdatascience.com](/build-a-social-media-website-with-django-users-app-part-2-7f0c0431ccdc) [## 用 Django 构建一个社交媒体网站——第 3 部分(用户应用模板)
在第三部分中,我们将着重于为我们在上一个教程中定义的用户应用程序构建模板。
towardsdatascience.com](/build-a-social-media-website-with-django-part-3-users-app-templates-c87ad46682be) [## 用 Django 构建一个社交媒体网站——Feed 应用后端(第 4 部分)
在这一部分中,我们将重点放在构建 Feed 应用程序及其所有与喜欢、评论、帖子和所有相关的模型上
towardsdatascience.com](/build-a-social-media-website-with-django-feed-app-backend-part-4-d82facfa7b3)
您可能喜欢的其他文章有:-
[## 用 Node,Express 和 MongoDB 构建一个 REST API
让我们使用 Node、Express 和 MongoDB 构建一个遵循 CRUD 原则的 REST API,并使用 Postman 测试它。
medium.com](https://medium.com/javascript-in-plain-english/build-a-rest-api-with-node-express-and-mongodb-937ff95f23a5) [## 使用 React 构建一个简单的 Todo 应用程序
让我们用 React 构建一个简单的 Todo 应用程序,它教你 CRUD 的基本原理(创建、读取、更新和…
medium.com](https://medium.com/javascript-in-plain-english/build-a-simple-todo-app-using-react-a492adc9c8a4)
用 Django 构建一个社交媒体网站——用户应用后端(第 2 部分)
在这一部分中,我们重点创建用户应用程序和所有与用户配置文件、身份验证、朋友模型等相关的模型。

因此,在教程的第一部分中,我们学习了如何设置我们的项目,并设置各种认证后端和其他关于设置文件中所需的各种安装和应用程序设置的细节。
如果你还没有阅读的第一部分,请确保在继续之前先完成它,因为我们将在这一部分中以它为基础。
可能会有很多你第一次遇到的术语,比如你可能第一次听说过视图或模型,所以我会简单介绍一下。我不能详细谈论这些,因为我们的重点不是教你基本的概念,而是建立一个社交媒体网站。因此,我将链接到一些好的资源,供您参考这些特定的主题,然后继续本教程。
因此,让我们继续构建我们在上一个教程中创建的用户应用程序。我们将首先从创建模型开始。
models.py
在这个 python 文件中,我们将定义我们的模型。您可能已经知道,定义模型是为了告诉 Django 在数据库中保存什么,并定义不同模型之间的关系以及它们有什么特征。
要了解更多关于 Django 模型的信息,请访问这个由 Mozilla 开发者撰写的关于模型的精彩教程。它深入讨论了模型。
当你对模型的工作方式感到满意后,你可以继续为我们的社交媒体网站制作模型。
因此,我们将有两个模型——一个用于用户的个人资料,另一个用于好友请求。
在开始编写模型之前,我们需要导入许多东西。我们将使用 Django 的默认用户模型与我们的配置文件模型建立一对一的关系,即每个用户都有一个配置文件。
我们还使用 autoslug 来根据用户名自动生成 URL 的 slug。
例如,姓名为 Tom 的用户会将 slug 设为 tom。这将有助于我们制作有意义的 URL,因为用户/tom 将指向 tom 的个人资料,而不是数字。
所以,要使用 autoslug,我们需要先安装它。这可以通过简单的 pip 安装来完成。参考下文:
pip install django-autoslug
此外,我们需要安装 pillow 库来处理 Profile 模型中的图像。
pip install pillow
安装后,我们可以使用以下代码行将其导入 models.py:
from autoslug import AutoSlugField
在完成所有必需的导入之后,我们可以开始编写模型了。
所以,我们的第一个模型是剖面模型。它有五个参数:-
- 用户 —这是与 Django 用户模型的一对一关系。 on_delete=models。CASCADE 表示删除用户,我们也会销毁档案。
- 图片 —这将存储用户的个人资料图片。我们还提供了一个默认图像。我们需要定义保存图片的位置。
- 段塞 —这将是段塞字段。我们使用 AutoSlugField,并将它设置为从用户字段生成一个 slug。
- bio —这将存储一个关于用户的小介绍。这里, blank=True 表示可以留空。
- 朋友 —这是一个带有配置文件模型的多对多字段,可以留空。这意味着每个用户可以有多个朋友,并且可以与多人成为朋友。
接下来,我们描述 str,,它决定 Django 如何在管理面板中显示我们的模型。我们将它设置为显示用户名作为查询对象。
我们还定义了 get_absolute_url 来获取这个概要文件的绝对 url。
接下来,我们定义一个函数,在创建用户后立即创建一个概要文件,这样用户就不必手动创建概要文件。
接下来,我们定义我们的朋友模型。它有三个参数:-
- to_user —这表示好友请求将被发送到的用户。它将具有相同的 on_delete 参数,该参数决定当用户被删除时,我们也删除朋友请求。
- from_user —这表示发送好友请求的用户。如果用户被删除,它也将被删除。
- 时间戳 —不需要添加。它存储发送请求的时间。
正如你所注意到的,to_user 和 from_user 使用相同的外键,所以为了区分,我们需要使用 related_name 字段。
这样,我们的 models.py 文件就完成了。看看下面的代码,它显示了 models.py 文件。
在 models.py 文件之后,我们前进到 admin.py 文件。
管理. py
它会很短,只有几行字。它表示我们将注册到我们的管理面板的模型。我们将在这里注册我们的模特。
接下来,我们移动到 forms.py.
forms.py
要了解 Django 中表单工作的更多信息,请访问 Django 自己编写的官方教程。然后继续学习教程。
我们在 forms.py 文件中定义了三个表单。
- 用户注册表单 —用于新用户的注册。我们使用 Django 的默认 UserCreationForm,定义表单中应该包含的内容。我们将电子邮件设置为 Django 的 EmailField。然后我们告诉 Django,模型是 User,我们会要求用户在注册时填写字段。
- UserUpdateForm —该表单将允许用户更新他们的个人资料。它将具有与注册表单相同的字段,但是我们将使用 Django 模型表单,而不是 UserCreationForm。
- ProfileUpdateForm —该表单将允许用户更新他们的个人资料。
因此,添加这三个表单将完成我们的 forms.py 文件。看看下面的代码:
因此,在这之后,我们创建了我们的 forms.py 文件。接下来,我们将看到 views.py 文件。
views.py
现在,我们将定义 views.py 文件。它将包含我们所有的视图(如何在 web 浏览器中呈现文件)。它直接将数据传递给模板。
阅读 Django 的官方教程可以更好地理解观点。看完教程,我们继续前进。
由于视图文件太大,我们可以根据自己的喜好来创建它,所以我将给出每个视图的简单概述,您可以阅读下面的代码来更好地理解。所以,让我们一个一个来看:
- users_list —这个视图将形成推荐给任何用户的用户列表,帮助他们发现可以交朋友的新用户。我们将从列表中过滤掉我们的朋友,也将我们排除在外。我们将首先添加我们朋友的朋友,他们不是我们的朋友。然后如果我们的用户列表仍然有低会员,我们会随机添加人来推荐(主要针对一个没有朋友的用户)。
- 好友列表 —该视图将显示用户的所有好友。
- 这将帮助我们创建一个好友请求实例,并向用户发送一个请求。我们接收向其发送请求的用户的 id,这样我们就可以向他发送请求。
- cancel _ friend _ request—它将取消我们发送给用户的好友请求。
- accept _ friend _ request—它将用于接受用户的好友请求,我们将用户 1 添加到用户 2 的好友列表中,反之亦然。此外,我们将删除好友请求。
- delete_friend_request —允许用户删除他/她收到的任何好友请求。
- delete_friend —这将删除该用户的朋友,也就是说,我们将从用户 2 的朋友列表中删除用户 1,反之亦然。
- 个人资料视图 —这将是任何用户的个人资料视图。它将显示朋友的计数和用户及其朋友列表的帖子计数。此外,它将显示用户接收和发送的朋友请求,并可以接受,拒绝或取消请求。我们将添加条件和检查,以便只有有关的用户显示请求和发送列表,他们只有权力接受或拒绝请求,而不是任何人查看他/她的个人资料。
- 注册 —这将让用户在我们的网站上注册。它将呈现我们在 forms.py 文件中创建的注册表单。
- edit_profile —这将让用户在我们创建的表单的帮助下编辑他们的个人资料。
- search_users —这将处理用户的搜索功能。它接受查询,然后过滤掉相关用户。
- my_profile —这与 profile_view 相同,但它将仅呈现您的个人资料。
为了更好地理解,请仔细阅读下面的代码。
它总结了我们的用户应用程序。我们剩下的是 urls.py,我们不会将它们包含在用户应用程序中。我们会将它直接添加到我们的照片分享应用程序中。
你可以查看这个简单教程来了解更多关于 Django 中的 URL。
urls.py(照片共享)
该文件包含网站的所有 URL。它有一个 include('feed.urls') ,包含了 feed 应用程序的所有 URL,我们将在下一个教程中构建。
我们将 photoshare 应用程序的所有 URL 直接包含在主 urls.py 文件中。请看下面的文件:
如果你想看到完整的代码,查看项目的 GitHub Repo 。此外,您可以通过访问此链接来试用此应用程序。它托管在 Heroku 上,媒体和静态文件在 Google 云存储上。
一个类似的以 Django 为中心的系列(建立一个求职门户)将教你一些惊人的新概念,它是:
[## 用 Django 构建求职门户——概述(第 1 部分)
让我们使用 Django 建立一个工作搜索门户,它允许招聘人员发布工作并接受候选人,同时…
shubhamstudent5.medium.com](https://shubhamstudent5.medium.com/build-a-job-search-portal-with-django-overview-part-1-bec74d3b6f4e)
如果您想在 Django 的基础上更进一步,学习 Django Rest 框架,这个新系列会让您兴奋不已:
[## 使用 Django Rest 框架构建博客网站——概述(第 1 部分)
让我们使用 Django Rest 框架构建一个简单的博客网站,以了解 DRF 和 REST APIs 是如何工作的,以及我们如何添加…
towardsdatascience.com](/build-a-blog-website-using-django-rest-framework-overview-part-1-1f847d53753f)
本教程的下一部分是:
[## 用 Django 构建一个社交媒体网站——第 3 部分(用户应用模板)
在第三部分中,我们将着重于为我们在上一个教程中定义的用户应用程序构建模板。
medium.com](https://medium.com/@shubhamstudent5/build-a-social-media-website-with-django-part-3-users-app-templates-c87ad46682be) [## 用 Django 构建一个社交媒体网站——Feed 应用后端(第 4 部分)
在这一部分中,我们将重点放在构建 Feed 应用程序及其所有与喜欢、评论、帖子和所有相关的模型上
shubhamstudent5.medium.com](https://shubhamstudent5.medium.com/build-a-social-media-website-with-django-feed-app-backend-part-4-d82facfa7b3) [## 用 Django 构建一个社交媒体网站——第 5 部分(Feed 应用程序模板)
在第五部分中,我们将着重于为我们在上一个教程中定义的 Feed 应用程序构建模板。
towardsdatascience.com](/build-a-social-media-website-with-django-part-5-feed-app-templates-66ddad5420ca)
本系列文章之后还有一些文章可供阅读:
[## 使用 React 构建一个简单的 Todo 应用程序
让我们用 React 构建一个简单的 Todo 应用程序,教你 CRUD 的基本原理(创建、读取、更新和…
medium.com](https://medium.com/javascript-in-plain-english/build-a-simple-todo-app-using-react-a492adc9c8a4) [## 用 Node,Express 和 MongoDB 构建一个 REST API
让我们使用 Node、Express 和 MongoDB 构建一个遵循 CRUD 原则的 REST API,并使用 Postman 测试它。
medium.com](https://medium.com/javascript-in-plain-english/build-a-rest-api-with-node-express-and-mongodb-937ff95f23a5)
为您的 GitHub 档案创建一个精彩的自述文件
使用 GitHub 隐藏的新功能— GitHub Profile READMEs,在 GitHub 上展示您的项目和技能!
如果你经常访问其他人的 GitHub 个人资料,你可能最近已经注意到,一些人在他们的个人资料中有一些漂亮的图片、描述和统计数据。这些是新的 GitHub 配置文件,它们是一种隐藏的新特性,在这篇文章中,我将向你展示如何创建一个,以及如何使用一些很酷的技巧和工具让它脱颖而出!

GitHub 个人资料自述文件
如何创造你自己的
创建 GitHub 概要文件README非常简单,但是您可能自己找不到它。要创建它,请转到https://github.com/new与您想要创建普通存储库时一样。用你的用户名命名这个库——在我的例子中是MartinHeinz/MartinHeinz。你一输入它,就会看到一条消息告诉你这个秘密/特殊的库:

创建新存储库
这就是你在这里需要做的,但是我建议当你在做你喜欢的README的时候,把库设置为 private ,这样就不会在你的个人资料中显示一些不完整的内容。
您也可以勾选用自述文件初始化该存储库,因为它需要出现在您的个人资料中。也就是说,您可以包含任何其他文件,如代码、gif、图片等。说到这个…
让它突出
我们有一个带有README的存储库,但是内容呢?你可以提供一些关于你自己的信息,你的电子邮件联系方式,然后就到此为止,但是我们可以做得更好。
我建议添加一个漂亮的标题,让它更加个性化。你可以在上面写上你的名字或职位,内容由你决定。有很多非常好的有创意的标题的例子,例如:
- https://github.com/WaylonWalker/WaylonWalker
- https://github.com/stephenajulu/stephenajulu
- https://github.com/jh3y/jh3y
现在,如何将其添加到README?首先,将标题图片添加到您的存储库中,这样您就可以公开托管它了。接下来,在README.md的顶部包含以下行:
这只是嵌入图片的基本降价。它还包括 URL,这样你就可以——例如——将图片链接到你的个人网站。
gif 和表情符号
另一个让你的README更有趣的方法是添加各种 gif 或表情符号。我个人喜欢在每个标题的开头添加表情符号,例如:

我发现获得相关表情符号的最简单的方法是在https://emojipedia.org/emoji/上搜索表情符号名称,然后在https://www.fileformat.info/index.htm上查找它的 HTML 实体。这些 HTML 实体可以包含在 markdown 中,您的浏览器应该能够很好地呈现它们。
如果表情符号对你来说还不够,你想在你的README中加入一些动作,那么你也可以添加 gif。当添加 gif 时,你需要实际的.gif文件,要么放在你的存储库中,如标题图片,要么放在外部网站上,如https://imgur.com/。无论托管在哪里,您都可以使用以下方式将其包括在内:
GitHub markdown 中可以使用一些 HTML 标签,<img>就是其中之一。这使得在我的README中添加像这样的图片和 gif 变得很容易:

大家好!👋
展示您的回复
Everyones GitHub profile 实际上只是一个展示你的库和突出你的活动/贡献的地方。有了 GitHub profile README,你可以使用GitHub-readme-stats更好地突出这些东西。GitHub Readme Stats 是一个工具,允许你为你的贡献和库生成 GitHub stats,并将它们附加到你的README上。如果你决定使用所有可用的统计卡,你可能会得到这样的结果:

GitHub 统计
每张卡片都有一堆定制选项——包括主题、图标或显示语言。要生成这些卡片,您可以使用以下模式:
其中CARD_TYPE可以是顶级语言列表的top-langs或固定存储库的pin。如果留空,它将默认为聚集的 GitHub 用户统计。要查看更多定制选项,请参见 github-readme-stats 库中的文档,或者您可以从我的中获得一些灵感,因为我使用了几乎所有可用的选项来匹配我的README的其余部分。
突出你的技能
另一件经常出现在人们个人资料中的事情是他们喜欢使用的技能和技术的列表。为了很好地形象化这些,人们可以使用 shields.io 徽章。它们有很多种风格,但我最喜欢的是这样的:

GitHub 徽章
要创建这种徽章,您需要在以下模式中包含降价行:
如果你不喜欢这种风格,你可以试试 shields.io 上显示的颜色、格式和风格。如果你像我一样喜欢徽章上的图标,那么你可能会发现simpleicons.org很方便,因为它列出了许多可以在这里使用的图标。如果这些徽章没有直接提供,您仍然可以通过在base64中下载和编码来手动添加。降价将会是这样的:
包括社交媒体
你绝对应该在你的个人资料中加入某种联系方式,无论是电子邮件、Twitter 账号、LinkedIn 还是其他社交媒体。无论你选择包含什么,你可能想使用图标链接,使人们更容易找到/注意到。
要在文本中包含这些内容,您可以使用以下降价:
渲染后,上面的减价看起来会像这样:

GitHub 降价图标
结论
使它简洁,有创意和原创性,但最重要的是让它成为你自己的。
希望这篇文章给了你足够的灵感来创建你自己的 GitHub 简介README。除了这篇文章,你可能还会发现我的README有用——你可以在https://github.com/MartinHeinz/MartinHeinz查看。如果你需要更多的例子来开始,那么我推荐你浏览一下awesome-github-profile-readme中的一些README。
如果你喜欢这篇文章,你应该看看我下面的其他文章!
本文最初发布于martinheinz . dev
[## 你可以用 GitHub API 和 Python 做的所有事情
GitHub REST API 允许您管理问题、分支、回购、提交等等,所以让我们看看您如何使用…
towardsdatascience.com](/all-the-things-you-can-do-with-github-api-and-python-f01790fca131) [## 自动化 Python 项目的各个方面
每个 Python 项目都可以从使用 Makefile、优化的 Docker 映像、配置良好的 CI/CD、代码…
towardsdatascience.com](/automating-every-aspect-of-your-python-project-6517336af9da) [## 下一个 Python 项目的最终设置
从零开始任何项目都可能是一项艰巨的任务…但如果您有这个最终的 Python 项目蓝图就不会了!
towardsdatascience.com](/ultimate-setup-for-your-next-python-project-179bda8a7c2c)
使用 Neo4j 构建地铁旅程规划器
使用流行的图形数据库计算出两个地铁站之间的最佳行驶路径

在我之前的教程中,我已经介绍了如何使用 Neo4j 构建一个餐馆推荐引擎。在本教程中,我们将进一步探索用户定义的过程和函数。这样的实现通常用 Java 实现,可以通过 Cypher 直接调用。这为您提供了一种方便的方法,可以创建您喜欢的任何图形算法的自定义实现,并在 Neo4j 中查询数据集时使用它。
从版本 4.1.1 开始,Neo4j 自带APOC(Cypher 上的牛逼程序)库。有两种版本可供选择:
APOC Core—没有外部依赖性或不需要配置的过程和功能APOC Full—包括APOC Core中的所有内容,以及额外的过程和函数。
此外,Neo4j 还为从事机器学习工作流的开发人员提供了自己的 GDSL(图形数据科学库)。在撰写本文时,这个库中的一些算法仍处于 alpha 阶段。
我们的示例项目将是关于地铁/地铁/大众捷运的旅程规划。在后台,它稍后将使用APOC Core提供的路径查找算法来查找从起点到终点的最短路径。
让我们继续下一部分,开始安装必要的模块。
1.设置
在继续之前,如果您是 Neo4j 的新手,强烈建议您阅读下面的指南Neo4j 图形平台初学者指南。
APOC 核心
默认情况下,Neo4j 的安装附带了APOC Core jar 文件。您可以很容易地在以下目录中找到 jar 文件。NEO4J_HOME指您本地机器中 Neo4j 的主目录。
$NEO4J_HOME/labs
您需要做的就是将 jar 文件复制并粘贴到以下目录中
$NEO4J_HOME/plugins
记住之后通过下面的命令重新启动 Neo4j 以使其生效。
neo4j console
如果要将其作为后台服务启动,请使用以下命令。
neo4j start
您可以通过以下 URL 访问 Neo4j 浏览器
[http://localhost:7474/browser/](http://localhost:7474/browser/)
Neo4j 驱动程序
为了将您的 web 应用程序连接到 Neo4j 图形数据库,您需要根据您使用的编程语言安装以下驱动程序之一:
.NET——。网络标准 2.0Java—Java 8+(最新补丁发布)。JavaScript—所有 LTS 版本的节点。JS ,特别是 4.x 和 6.x 系列运行时。Python— CPython 3.5 及以上。Go—工作正在进行中。目前没有官方发布日期。
对于本教程,我将在 FastAPI 中为我们的 web 应用程序使用 Python 驱动程序。您可以通过下面的链接找到其余驱动程序的完整安装步骤。
强烈建议您在安装软件包之前创建一个虚拟环境。在终端中运行以下命令。
pip install neo4j
FastAPI
我们的后端服务器将建立在 FastAPI 之上。如果你是 Flask 用户,请随意修改它,因为你可以随时将它从 Flask 迁移到 FastAPI 。通过 pip install 安装,如下所示:
pip install fastapi
此外,你还需要一台ASGI服务器。我将使用推荐的名为Uvicorn的ASGI服务器。在同一个终端中,运行以下命令进行安装
pip install uvicorn
资料组
我将使用下面的网络图作为我的用例的数据集。它基于新加坡[公共交通运营商之一](http://SMRT Corporation website)的实际网络图。
为了简化我们的项目,我们的数据集将只包含上面地图的精简版本。因此,我将忽略其余的线路,只保留以下 5 条 MRT 线路。
- 东西线(绿色)
- 南北线(红色)
- 东北线(紫色)
- 圆形线(圆形)
- 市区线(蓝色)
2.Neo4j 数据库
在本节中,我们将执行图形查询语言(Cypher ),用于向 Neo4j 图形数据库插入数据以及从其中查询数据。您可以使用现有的或新的数据库。
在我们继续之前,让我们列出用例的所有节点和关系。我们将使用它来建模我们的领域,并在稍后创建 Cypher 查询。
假定
为了使事情简单而简短,我将为我们的用例做以下假设。
- 每站之间没有等待时间。在实际使用情况下,应该有乘客排队上车的等待时间。
- 当在换乘站之间改变线路时,没有行驶时间。在实际使用案例中,当改变线路时,你必须从一个平台走到另一个平台。
- 从
Station A到Station B花费的时间总是相同的,不管你是否在不同的线路上旅行。在实际使用案例中,从Raffles Place经East-West Line到City Hall所用的时间与经North-South Line所用的时间不同。 - 我们的旅程规划工具所使用的指标仅仅基于两个站点之间的总旅行时间。在实际使用案例中,您必须考虑影响旅行费用的进出站需求。
根据您自己的用例随意修改和建模领域。
站(节点)
每个站代表一个具有以下属性的Node:
name—车站名称。所有的名字都是小写的。mrt—代表车站所在的线路。我用的是简称。因此,East-West Line将是ew,而Circle Line将是cc。对于立体交叉,将改为标记为x。该属性将决定 React 应用程序中图标的颜色。
旅行目的地(关系)
两个Station之间的关系由具有以下属性的TRAVEL_TO表示:
time—代表从一个站点到另一个站点所需的时间。它不包括从一条捷运线换乘到另一条捷运线的步行时间。车站间隔时间的数据集基于 TransitLink 网站的输出结果。稍后,它将被用作路径查找算法的成本函数。
清除数据库
您可以运行以下密码来清理数据库。任何现有节点及其关系都将从数据库中完全删除。
MATCH (n) DETACH DELETE n
创建数据集
您可以创建两个Station节点,并用如下关系将它们链接起来。我使用小写作为名称来标准化稍后 API 调用的输入参数。
CREATE (tuaslink:Station {name:"tuas link", mrt:"ew"})-[:TRAVEL_TO {time: 2}]->(tuaswestroad:Station {name:"tuas west road", mrt:"ew"})
它将创建两个带有Station标签的独立节点,并在它们之间建立TRAVEL_TO关系。现在,您应该注意到关系是单向创建的。这是默认行为,因为 Neo4j 只允许您在节点之间创建单向关系。但是,您可以指定在查询时忽略方向,以获得所需的双向结果。
随后,您可以通过声明的名称重用旧的Station节点,并将它链接到一个新的Station节点,如下所示。
(tuaswestroad)-[:TRAVEL_TO {time: 8}]->(tuascrescent:Station {name:"tuas crescent", mrt:"ew"})
链接节点时需要小心,因为如果从Station A到Station B存在两种不同的关系,会导致结果重复。例如,您可以通过East-West Line和North-South Line从Raffles Place连接到City Hall。一旦你为East-West Line声明了以下密码。
(rafflesplace:Station {name:"raffles place", mrt:"x"})-[:TRAVEL_TO {time: 2}]->(cityhall:Station {name:"city hall", mrt:"x"})
您不能为North-South Line再次声明它。
(rafflesplace)-[:TRAVEL_TO {time: 2}]->(cityhall)
如果您打算将两个工作站建模为不同的实体,只需为同一个工作站创建两个不同的节点,并正确地链接它们。
让我们将所有数据集合并到一个查询中。下面的要点包含该项目的完整密码查询。可以直接在 Neo4j 控制台运行。
一旦执行了 Cypher 查询,您应该会看到下面的用户界面

作者图片
获取全部
事实上,您可以运行以下查询来获取所有节点及其关系
MATCH (n) RETURN (n)
在您的 Neo4j 浏览器中,您应该会得到以下结果。

作者图片
Dijkstra(寻路算法)
APOC Core附带了一些有用的寻路算法,比如dijkstra和astar。在本教程中,我将使用dijkstra,因为我们只有一个成本函数。基于官方文件,它接受以下输入参数
startNode—寻路算法的起始节点。endNode—寻路算法的结束目的节点。relationshipTypesAndDirections—字符串表示节点之间的关系。您也可以指定方向。weightPropertyName—代表成本函数的属性名称的字符串。defaultWeight—属性在节点中不存在时的默认权重。numberOfWantedPaths—要返回的路径数。默认值为 1。
并返回两个输出参数
path—寻路旅程的路径。weight—寻路旅程的总成本。
如果您只是从算法中寻找最佳路径,您可以忽略defaultWeight和numberOfWantedPaths参数。
从 A 到 B 的最佳路径
下面的例子说明了获得从Jurong East到Dhoby Ghaut的最佳路径的密码。
MATCH (start:Station {name: 'jurong east'}), (end:Station {name: 'dhoby ghaut'})
CALL apoc.algo.dijkstra(start, end, 'TRAVEL_TO', 'time') YIELD path, weight
RETURN path, weight
您应该得到以下输出

作者图片
从 A 到 B 的前三条路径
假设您想从算法中获得前 3 条最佳路径。你应该使用下面的密码
MATCH (start:Station {name: 'jurong east'}), (end:Station {name: 'dhoby ghaut'})
CALL apoc.algo.dijkstra(start, end, 'TRAVEL_TO', 'time', 5, 3) YIELD path, weight
RETURN path, weight
执行后,Neo4j 浏览器将显示以下结果

作者图片
3.Python 驱动程序
在本节中,我们将创建一个简单的 FastAPI 后端,它通过 Python 驱动程序连接到 Neo4j 数据库。在您的工作目录中,创建一个新的 Python 文件。我打算把它叫做journey.py。
导入
在 Python 文件的顶部添加以下导入声明。
from neo4j import GraphDatabase
import logging
from neo4j.exceptions import ServiceUnavailable
旅程等级
接下来,创建一个新类,并在其中初始化以下函数
class Journey:
def __init__(self, uri, user, password):
self.driver = GraphDatabase.driver(uri, auth=(user, password)) def close(self):
self.driver.close()
该类负责以下功能:
- 返回数据库中所有电台的名称列表
- 使用
dijkstra寻路算法返回基于起点和终点的最佳路径
获取电台名称
继续在Journey类中追加以下代码。第一个功能通过上下文管理器初始化会话。在函数内部,我们将调用read_transaction()方法并传入第二个函数,该函数将返回一个字典作为结果。
第二个函数主要负责通过run()函数执行查询字符串。我使用 dict comprehension 和title()函数将名字作为Title case 返回。基于官方文档,建议将该功能声明为staticmethod。
获取最佳路径
让我们再创建两个函数,使用dijkstra算法获得最佳路径。它接受以下参数:
start_node—旅程的起点end_node—旅程的终点count—返回的路径数
4.FastAPI 服务器
正如我前面提到的,我们的后端服务器基于 FastAPI。在与journey.py相同的目录下创建一个名为myapp.py的新 Python 文件。
导入
在文件的顶部,添加以下导入语句。
from fastapi import FastAPI
import journey
import atexit
from fastapi.middleware.cors import CORSMiddleware
journey是我们之前创建的模块的名称。如果这两个文件不在同一个目录中,请相应地修改它。
当退出网络服务器时,我使用atexit来执行close()功能。要了解更多信息,请看下面关于如何为 Python 应用程序创建退出处理程序的教程。
当您从任何前端应用程序发出AJAX或fetch调用时,需要CORSMiddleware来防止问题。
初始化
初始化以下变量,这些变量是向 Neo4j 数据库进行身份验证的凭据。
uri = "neo4j://localhost:7687"
user = "neo4j"
password = "neo4j"neo_db = journey.Journey(uri, user, password)
退出处理程序
然后,添加下面的代码来关闭与 Neo4j 数据库的连接。
def exit_application():
neo_db.close()atexit.register(exit_application)
FastAPI
完成后,创建一个新的 FastAPI 实例。除此之外,让我们为origins指定一个变量,并在调用add_middleware()函数时将其作为输入参数传递。
app = FastAPI()origins = [
"[http://localhost:3000](http://localhost:3000)"
]app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
origins由将调用您的 FastAPI 服务器的 URL 列表组成。假设您有一个在端口 3000 上本地运行 React 应用程序。您应该将以下 URL 添加到列表中
[http://localhost:3000](http://localhost:3000)
创建一条新的GET路线,返回所有站点的名称。
@app.get('/get-station')
async def get_station():
result = neo_db.find_all()return result
之后,创建另一条GET路线以获得最佳路径。我们将把它与接受三个参数的find_journey()函数连接起来。每行包含一个字典对象,该对象包含path和weight参数。需要注意的一点是,path内部的节点是无序的,你可以通过id链接它们。第一个节点可以是起点,也可以是终点。
运行 FastAPI
运行以下代码启动 FastAPI 服务器:
uvicorn myapp:app
它应该在几秒钟后开始。让我们测试一下我们的 API,以获得从Jurong East到Dhoby Ghaut的最佳路径。在您的浏览器中浏览以下网址。
[http://localhost:8000/get-journey?start=jurong%20east&end=dhoby%20ghaut&count=3](http://localhost:8000/get-journey?start=jurong%20east&end=dhoby%20ghaut&count=3)
您应该会得到以下结果。
[{"path":[{"name":"Jurong East","mrt":"x","time":"start here"},{"name":"Clementi","mrt":"ew","time":"4 minutes"},{"name":"Dover","mrt":"ew","time":"3 minutes"},{"name":"Bouna Vista","mrt":"ew","time":"3 minutes"},{"name":"Holland Village","mrt":"cc","time":"2 minutes"},{"name":"Farrer Road","mrt":"cc","time":"3 minutes"},{"name":"Botanic Gardens","mrt":"cc","time":"2 minutes"},{"name":"Stevens","mrt":"dt","time":"2 minutes"},{"name":"Newton","mrt":"dt","time":"3 minutes"},{"name":"Little India","mrt":"dt","time":"1 minutes"},{"name":"Dhoby Ghaut","mrt":"dt","time":"2 minutes"}],"weight":25.0},{"path":[{"name":"Jurong East","mrt":"x","time":"start here"},{"name":"Clementi","mrt":"ew","time":"4 minutes"},{"name":"Dover","mrt":"ew","time":"3 minutes"},{"name":"Bouna Vista","mrt":"ew","time":"3 minutes"},{"name":"Commonwealth","mrt":"ew","time":"2 minutes"},{"name":"Queenstown","mrt":"ew","time":"2 minutes"},{"name":"Red Hill","mrt":"ew","time":"3 minutes"},{"name":"Tiong Bahru","mrt":"ew","time":"2 minutes"},{"name":"Outram Park","mrt":"ew","time":"3 minutes"},{"name":"Chinatown","mrt":"ew","time":"2 minutes"},{"name":"Clarkequay","mrt":"ne","time":"2 minutes"},{"name":"Dhoby Ghaut","mrt":"ne","time":"2 minutes"}],"weight":28.0},{"path":[{"name":"Jurong East","mrt":"x","time":"start here"},{"name":"Clementi","mrt":"ew","time":"4 minutes"},{"name":"Dover","mrt":"ew","time":"3 minutes"},{"name":"Bouna Vista","mrt":"ew","time":"3 minutes"},{"name":"Holland Village","mrt":"cc","time":"2 minutes"},{"name":"Farrer Road","mrt":"cc","time":"3 minutes"},{"name":"Botanic Gardens","mrt":"cc","time":"2 minutes"},{"name":"Stevens","mrt":"dt","time":"2 minutes"},{"name":"Newton","mrt":"dt","time":"3 minutes"},{"name":"Orchard","mrt":"ns","time":"3 minutes"},{"name":"Somerset","mrt":"ns","time":"2 minutes"},{"name":"Dhoby Ghaut","mrt":"ns","time":"2 minutes"}],"weight":29.0}]
第一个推荐建议我们从Jurong East到Bouna Vista,然后一直坐Circle Line到Botanic Gardens。之后,沿着Downtown Line一直走到Little India,然后换乘Dhoby Ghaut。
第二条路径将我们从Jurong East引向Outram Park。然后,换乘North East Line,一直走到Dhoby Ghaut。
此外,我们的第三个建议指引我们在Bouna Vista换乘到达Botanic Gardens。之后,通过Downtown Line继续Newton。与第一趟不同,它建议我们从Orchard换乘North South Line前往Dhoby Ghaut。
5.从前端呼叫
你现在需要做的就是把它连接到任何一个前端应用。你可以根据自己的喜好使用任何框架或计算机语言。在本教程中,我将简单介绍如何将 React 与 FastAPI 服务器集成。为了避免过于冗长,我将不涉及用户界面。
例子
如果你正在寻找灵感,看看以下网站提供的功能。以下示例显示了从Jurong East到Dhoby Ghaut的示例输出。

图片由作者基于 SMRT 旅程规划中提供的功能绘制。
如你所见,与我们的结果相比,它只提供了两种选择。第一个选项与我们的路径查找算法提出的第二个建议路径完全相同。
您可以创建具有以下功能的 React 应用程序:
- 将内容分成两部分的网格布局。左侧包含输入,而右侧将显示结果。
- 起点和终点的两个选择输入
- 确认按钮
- 结果将显示为手风琴,连同总时间的旅程。每个旅程将包含站点名称以及每个站点之间的旅程时间。
最终的 React 应用程序可能看起来像这样。该用户界面基于 React 材质用户界面。

作者图片
AJAX 调用
对于集成,您可以通过AJAX或fetch调用轻松实现。在本教程中,我将展示如何对 FastAPI 服务器进行AJAX调用。
结论
祝贺您完成本教程。
让我们回顾一下你今天所学的内容。我们首先简要介绍了 Cypher Library 上令人惊叹的程序。
之后,我们继续安装必要的模块,从 Neo4j Python 驱动程序到 FastAPI。此外,我们为我们的旅程规划应用程序制作和建模了我们的域。
一旦我们完成了它,我们启动 Neo4j 作为控制台应用程序,并与 Cypher 一起玩。我们清理了数据库,创建了新记录,并尝试运行djikstra寻路算法来获得最佳路径。
随后,我们构建了一个新的 Journey 类,作为通过 Python 驱动程序连接到 Neo4j 数据库的模块。我们还创建了一个 FastAPI 服务器,作为后端服务器。
最后,我们进一步探讨了如何通过 AJAX 调用将其与 React 应用程序集成。
感谢你阅读这篇文章。希望在下一篇文章中再见到你!
参考
在 PyTorch 中构建一个超级简单的 GAN
GANs 看起来很可怕,但是它的思想和基本实现非常简单,就像 50 行代码一样简单。

在美国农业部果树水彩画集上接受训练的甘的植物学绘画。
介绍
生成敌对网络(GANs)是一个模型框架,其中两个模型一起训练:一个学习从与训练集相同的分布中生成合成数据,另一个学习从生成的数据中区分真实数据。当我第一次了解它们的时候,我记得当时对如何构建联合训练有点不知所措。我还没有看到专注于构建一个简单的 GAN 的教程,所以我将在这里尝试这样做。没有图像生成,没有花哨的油炸 conv 网。我们将训练一个能够学习用大约 50 行 Python 代码生成偶数的模型。这个项目的所有代码都可以在 github 库这里找到。
什么是甘?
GANs 由两个训练一致的模型组成。第一个模型是生成器,它接收一些随机输入,并试图输出一些看起来像我们的训练数据的东西。第二个模型是鉴别器,它接收训练数据和生成的数据,并试图将假生成的数据与真实的训练数据区分开。这个框架的有趣之处在于,这些模型是一起训练的。随着鉴别器在识别假图像方面变得更好,这种学习被传递给生成器,并且生成器在生成假图像方面变得更好。用一个比喻来说,生产者对于鉴别者就像伪造者对于 FBI 调查员一样。一个试图伪造数据,另一个试图区分伪造和真实交易。
这个框架在过去几年里产生了大量超级有趣的结果,从把马翻译成斑马,到制作深度赝品,再到想象全新的图像。在本教程中,我们不会做任何有趣的事情,但这应该给你所有的背景知识,你需要从零开始,成功地实现自己的 GAN:)。让我们开始吧。
问题定义
假设我们有一个 0 到 128 之间所有偶数的数据集。这是一个更大的数据分布的子集,整数,具有一些特定的属性,就像人脸是所有生物图像的子集一样。我们的生成器将接受相同范围内的整数形式的随机噪声,并学习只产生偶数。
在进入实际模型之前,让我们先建立数据集。我们将把每个整数表示为无符号的 7 位二进制表示。所以数字 56 是 0111000。我们这样做是因为:
- 将二进制向量传递给机器学习算法是非常自然的,在这种情况下,是神经网络。
- 通过查看最低位,很容易看出模型是否生成偶数。如果是 1,数字是奇数,如果是 0,数字是偶数。
首先,让我们写一个函数,将任意正整数转换成二进制形式的列表。
将正整数转换为二进制列表
有了这个,我们就可以创建一个函数,它会动态地为我们生成随机的训练数据。
生成 GAN 训练数据的功能。
这个函数将产生两个输出,第一个是一个列表,表示这个数据是偶数,来自我们的真实分布。第二个输出是二进制列表形式的随机偶数。这就是我们开始构建和训练模型所需的全部内容!
构建生成器和鉴别器
发电机
构建生成器和鉴别器非常简单!让我们从发电机开始。我们需要一些能够映射随机七位二进制输入到七位二进制输入是偶数。这里最简单的可能是一个七层神经元。
发电机架构
如果我们要构建一个 GAN 来处理一些更复杂的事情,比如图像,我们可能会使用从正态分布中生成的随机噪声来训练它,并逐渐对它进行上采样和整形,直到它与我们试图复制的数据大小相同。由于我们的示例非常简单,所以具有逻辑(sigmoid)激活的单个线性层应该足以将 7 个位置的 1 和 0 映射到其他 7 个位置的 1 和 0。
鉴别器
鉴别器不比发生器复杂。这里我们需要一个模型来接受一个七位数的二进制输入和输出,无论它是否来自我们的真实数据分布(是偶数)或不是(是奇数或不是数字)。为了实现这一点,我们使用具有逻辑激活(Sigmoid)的单神经元模型(逻辑回归)。
就这样,我们已经建立了两个模型,我们将一起训练。现在是甘训练中最棘手的部分。我们需要将这些模型连接起来,以正确传播梯度。
训练模型
训练 gan 一开始看起来有点混乱,因为我们需要用每一点输入来更新两个模型,并且我们需要小心我们是如何做的。因此,为了分解它,我们在每个训练步骤向我们的模型传递两批数据。一批是随机噪声,这将导致生成器创建一些生成的数据,第二批仅由来自真实分布的数据组成。在整个培训描述中,我将引用下面最终培训代码要点中的行号,而不是 Github 存储库。
最终培训代码
训练发电机
让我们从训练发电机开始。这包括:
- 制造随机噪音。(第 27 行)
- 通过将噪声传递给生成器来生成新的“假”数据(第 28 行)
- 从鉴别器获得对“假”数据的预测(第 38 行)
- 使用标签计算鉴频器输出的损失,就好像数据是“真实的”而不是假的。(第 39 行)
- 仅通过生成器反向传播错误。(第 40–41 行)
请注意,在第四步中,我们如何使用真标签而不是假标签来计算损失。这是因为我们正在训练发电机。发生器应该试图欺骗鉴别器,因此当鉴别器出错并说产生的输出是真实的(预测 1)时,梯度应该小,当鉴别器正确动作并预测产生输出(预测 0)时,梯度应该大。这就是为什么我们在这一步只通过生成器传播梯度,因为我们颠倒了标签。如果我们像这样训练整个模型,要么生成器会学到错误的东西,要么鉴别器会。
训练鉴别器
现在是时候更新我们的鉴别器中的权重了。我们分几步完成:
- 传入一批来自真实数据集中的数据,这些数据带有一个全 1 标签的向量。(第 44–46 行)
- 将我们生成的数据传入鉴别器,带有分离的权重和零标签。(第 49–50 行)
- 平均第一步和第二步的损失。(第 51 行)
- 通过鉴别器反向传播梯度。(第 52–53 行)
鉴别器正在努力学习区分真实数据和“假”生成的数据。训练鉴别器时的标签需要代表这一点,即当我们的数据来自真实数据集时为 1,当它由我们的生成器生成时为 0。我们在上面的步骤(1)和(2)中传递这两个批次,然后平均这两个批次的损耗。重要的是要注意,当传入生成的数据时,我们希望分离梯度。我们这样做是因为我们不是在训练生成器,我们只是在关注鉴别器。一旦所有这些都完成了,我们只在鉴别器中反向传播梯度,我们就完成了。
包扎
就是这样!我们已经建立了完整的 GAN。在训练循环中,每一步都进行梯度归零,这样我们就可以开始了。如果我们在不同的训练步骤中查看生成器的输出,我们可以看到它收敛到只创建偶数,这正是我们想要的!
0 : [47, 3, 35, 1, 16, 56, 39, 16, 3, 1]
50 : [2, 35, 34, 34, 38, 2, 34, 43, 3, 43]
100 : [42, 43, 106, 38, 35, 42, 35, 42, 43, 106]
200 : [108, 106, 106, 42, 106, 42, 106, 106, 42, 96]
在步骤 0,我们的样本中有 7/10 是奇数,而在步骤 200,我们的样本中有 10/10 是偶数!这是一个成功的生成器,它只用了大约 50 行真正的 Python 代码!
接下来呢?
正如您可能已经猜到的,还有其他一些技巧来训练生成非平凡输出的 GAN。如果您想让该模型在图像等真实数据上工作,可以立即尝试以下方法:
- 生成器可能需要更深一点,并将噪声放大到真实数据的大小。您可以使用转置卷积或上采样层来实现这一点。
- 将发生器的噪声输入更改为高斯型
- 增加鉴别器的深度,使其预测能力更强。
- 训练更长的时间,并监测损失。
作为一个好的下一步,尝试并实现 DCGAN 架构。这个代码会帮你完成 90%的任务。一旦你这样做了,并制作了一些像介绍中那样有趣的图像,试着通过调整超参数来改进它们。在训练真正的甘人时,可以在这里找到一份不错的清单。
如何使用 IBM Watson NLC 服务构建文本分类器
使用 Watson Studio 训练文本分类器,无需编码

图片由罗曼·维涅斯拍摄
文本分类
文本分类是属于数据科学和机器学习的另一项任务,我们为每个文档/句子/推文分配一个或多个类别或类别(用相关类别标记自然语言文本)。例如,将这句话“莱昂内尔·梅西在世界足球奖中获得年度最佳球员”归类为“体育”陈述。
构建模型
我们将构建一个分类器,将 StackOverflow 问题分类到前 20 个标签之一。使用的数据可在 BigQuery 上获得,或者您可以点击此处下载。该数据包含带有单个标签的 StackOverflow 帖子。每个标签有 2000 个帖子,所以总共有 40,000 个帖子。
首先,您需要创建一个项目:

选择项目后,应该会出现一个类似的视图。点击“添加到项目”按钮开始我们的旅程。

使用 AutoAI 可以建立许多不同的模型。要构建文本分类器,点击“自然语言分类器”

训练分类器需要服务。如果您是第一次使用,请点击【此处】获取一个。

选择一个计划。

如果是第一次,选择默认设置,点击“确认”

否则,您将被重定向到一个页面,在那里您可以选择您的服务之一

这是主页面,点击右上角的【浏览】上传您的文件。在左侧,将出现您所有标签和帖子的列表。允许你编辑文章,添加,删除,重命名等等。

当你点击“火车模型”时,魔法就开始了。

培训阶段结束后,您应该会收到通知。点击【此处】

您将被重定向到一个新页面,该页面包含三个选项卡:概述、测试、实施

点击“测试”来测试模型。写一句话,点击“分类”。您可以更改阈值以获得特定概率的结果。

最后,点击“Implementation”,您将获得如何向模型发送推理请求的说明。

感谢阅读。如果您有任何问题,请告诉我!
资源
为冠状病毒更新构建一个 Twitter 机器人
在本文中,我们将学习如何使用 Python 和 Tweepy 构建一个 twitter 机器人来发布冠状病毒的统计数据。

编者按: 走向数据科学 是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
Twitter 提供了一个 API ,用户可以通过它与平台进行交互。Tweepy 是一个 python 库,它提供了一种方便访问 twitter API 的方法。它是底层 API 的高级包装器。
如果想直接上码,点这里。
装置
我们将在这个项目中使用 Python 3。我们首先需要的是 tweepy。让我们使用 pip 安装它。
pip install tweepy
Linux 和 Mac 用户可能必须使用 pip3,而不是 Python 2 使用的 pip
Twitter API
为了访问 twitter API,我们需要有一个 twitter 帐户。如果还没有,就创建一个吧。为了使用 API,请确保您已经验证了您的电子邮件和电话号码。
然后转到开发者页面并点击左上角的应用或直接转到应用页面。然后点击“申请开发者账号”。根据您的需要选择适当的选项,然后单击“下一步”回答问题。Twitter 会询问一些基本信息,比如你将如何使用 API,你来自哪个国家,等等。一旦一切都完成了,你可能要等一两天才能得到验证。
验证完成后,转到应用页面并创建一个应用。为您的应用程序命名(确保它是唯一的),添加描述和网站 url。在底部,你必须详细描述你将如何使用该应用程序。然后按创建。

Twitter 应用程序
一旦你进入如图所示的应用程序页面。转到“密钥和令牌”。生成访问令牌和访问令牌密码。显示密钥时,将密钥复制到某个文本文件中。
现在创建一个文件 config.py 并添加所有 4 个键,如下所示。
配置. py
现在,在 config.py 所在的同一个文件夹中创建另一个文件 twitter_bot.py,并添加以下代码。
twitter_bot.py
现在使用命令运行该文件
python twitter_bot.py
代码非常简单。我们正在导入 tweepy 库和所有需要的键。然后我们通过传递我们的键来创建一个 api 对象。如果成功,将打印“认证成功”,否则将打印“认证 API 时出错”。我希望你得到正确的认证。去看看你的推特账户,你会看到一条推文。
收集冠状病毒统计数据
我发现了 https://www.worldometers.info/coronavirus/的这个网站,上面显示了受影响、死亡和康复的总人数。我们将从该页面抓取数据,创建一条推文,并从我们的帐户发布。
让我们安装请求和 lxml 库。
pip install requests lxml
requests 用于向 web 页面发送 HTTP 请求,lxml 用于使用 Xpath 解析返回的 HTML 内容。如果您不熟悉 Xpath,我将链接下面的一些资源来了解更多。顺便说一下,你也可以使用 BeautifulSoup 来解析 HTML 而不是 lxml。
所有这些依赖项都在 github repo 的 requirements.txt 文件中。您可以使用以下命令一次性安装所有程序
pip install -r requirements.txt
打开 https://www.worldometers.info/coronavirus/的,右键点击“冠状病毒病例”正下方的数字,点击检查。

检查 HTML
数据位于 span 标记中,该标记位于具有 maincounter-number 类的 div 中。如果你检查死亡和恢复部分,你会看到结构是相同的。让我们打开 python 外壳,看看是否能得到数据。在您的 cmd/终端中,键入 python。
>>> import requests
>>> from lxml import html
>>> response = requests.get('[https://www.worldometers.info/coronavirus/'](https://www.worldometers.info/coronavirus/'))
>>> doc = html.fromstring(response.content)
>>> doc.xpath('//div[[@class](http://twitter.com/class)="maincounter-number"]/span/text()')
['805,377 ', '39,469', '172,436']
现在我们可以在脚本中实现相同的逻辑。打开 twitter_bot.py,创建一个名为 create_tweet() 的函数,并在 import 语句的正下方添加抓取代码。
我们正在使用 Python 的 f 字符串创建一条推文。我添加了一些相关的标签,但是你可以根据自己的需要随意设置推特的格式。不要忘了给世界计程仪积分。
添加完所有内容后,我们的最终代码应该是这样的。
现在从终端/cmd 运行您的代码。
python twitter_bot.py
然后检查你的推特账户,你会看到一条这样的推文
通过 visualizenoworg 发布推文
如果你想在脚本中添加更多的功能,比如每隔 X 分钟从一个无限循环中发出 tweet。或者安排这个脚本每隔 Y 分钟从 cron 运行一次。你可以创建一个完全不同的机器人,从你的账户发布最新消息。可能性是无限的。还要确保检查速率限制。
Twitter API 允许你与应用程序交互,收集数据,分析推文等等。要了解更多信息,你可以查看 twitter 的官方文档。
资源
- 官方文件:https://developer.twitter.com/en/docs
- 十二份文件:http://docs.tweepy.org/en/latest/
- Xpath 教程:https://docs . scrapy . org/en/XPath-tutorial/topics/XPath-tutorial . html
- 另一个推特机器人:https://realpython.com/twitter-bot-python-tweepy/
- 代码:https://github.com/sagunsh/corona_twitter_bot
在 5 分钟内制作一个声控鼠标
Python 中语音识别和 GUI 自动化的初学者指南
在这个故事中,我们将使用 Python 构建一个应用程序,它将接受来自用户的语音命令,并使用鼠标和键盘执行某些基于 GUI 的操作。你可以把它想象成你自己的语音数字助理。它可以播放媒体,打开应用程序,发送电子邮件,移动鼠标指针等等,所有这些都由你的语音命令触发。我们将通过使用以下两个 python 库来完成—&Speech _ Recognition。你只需要一台安装了 Python 的笔记本电脑和一个麦克风。

由 Marek Levák 在 Unsplash 拍摄的照片
在详细介绍如何在本演示中使用上述工具之前,让我们看看它们是如何适应我们的应用程序设计的。
下图非常简单明了。用户将语音命令输入麦克风(内置或外置),然后使用语音识别模块将其转换为相应的文本。然后,转换后的文本被映射到使用 PyAutoGUI 模块执行的某些 GUI 动作(鼠标/键盘事件)。为了方便起见,我画了下图。

端到端流程的流程图
让我们更详细地看看这两个库!
1。演讲人认可:

照片由freestocks.org从派克斯拍摄
语音识别特征在家庭自动化系统、语言学习、数字助理等领域具有各种应用。使用这个库,我们可以把我们的讲话转换成文本。它支持几种 API(在线和离线)。在我们的例子中,我们将使用在线 google API。您可能会注意到在语音到文本的转换过程中有时会有一些延迟,但是,在这个模块支持的其他 API 中,我发现 Google API 在我的情况下是最准确的。可以使用以下 pip 命令下载它。使用麦克风需要 pyaudio。
*pip install SpeechRecognition
pip install pyaudio*
在下面的代码片段中,我们正在初始化 recognizer 对象,监听来自麦克风的输入语音,并使用“recognize_google”函数将其转换为文本。我们只在用粗体字母标记的行中做了所有这些。对 recognizer . adjust _ for _ ambient _ noise()函数的调用是可选的。该功能监听输入声音,并根据房间内的噪音量改变 energy_threshold 值。它可以被认为是识别器灵敏度的度量。该值取决于环境噪声,较高的值通常意味着不太敏感。该参数的范围可以是 50–4000 之间的任何值。**
****import speech_recognition****recognizer = speech_recognition.Recognizer()****with speech_recognition.Microphone() as src:**
try:
**audio = recognizer.adjust_for_ambient_noise(src)**
print("Threshold Value After calibration:" + str(recognizer.energy_threshold))
print("Please speak:")
**audio = recognizer.listen(src)**
**speech_to_txt = recognizer.recognize_google(audio)**.lower()
print(speech_to_txt)
except Exception as ex:
print("Sorry. Could not understand.")**
比方说,代替麦克风,您的输入是一个音频文件(file.wav),行号 3 可以替换如下:
**with speech_recognition.WavFile("file.wav") as src:**
2.PyAutoGUI:

Python 为 GUI 自动化提供了一个名为PyAutoGUI的库,可以模拟鼠标点击和按键,就像人类用户正在执行它们一样。例如,模拟鼠标移动,击键,截屏,最大化窗口,有很多事情可以做。完整列表可以参考 官方文档链接 。为了这个演示的目的,我使用了像鼠标移动、鼠标点击、键盘按压&在屏幕上查找图像这样的功能。
**pip install PyAutoGUI**
****鼠标控制:要在屏幕上移动鼠标光标,我们需要(x,y)坐标。将显示器想象成一个具有 x,y 坐标的二维平面(如此处所示),其中左上角是(0,0)。向右移动,x 的值增加,而向底部移动,y 的值增加。函数的作用是:返回屏幕的尺寸。
您可以检查您的屏幕尺寸,如下所示:
**>>> import pyautogui
>>> pyautogui.size()
Size(width=1920, height=1080)**
下面的命令将鼠标指针从当前位置移动到(100,100)位置,需要 0.25 秒。下一个命令模拟双击,两次单击之间的间隔为 0.25 秒。
**pyautogui.**moveRel**(100, 100, duration=0.25)
pyautogui.**click**(button='left', clicks=2, interval=0.25)**
****键盘控制:为了模拟按键,使用了以下函数。它按下多媒体“静音”按钮。所有支持的键的完整列表可以在这里找到。
**pyautogui.**typewrite**(['volumemute'])**
****定位功能:有时我们并不知道想要点击的点(比如一个按钮)的(x,y)坐标。但是如果我们将按钮的图片存储为图像文件,pyautogui.locateOnScreen()函数可以逐个像素地查找该图像并返回坐标。关于 locateOnScreen()特性需要注意的一点是,即使单个像素不匹配,它也无法检测图像并返回一个 None 对象。然后,我们可以简单地将鼠标移动到给定的位置并执行单击。例如:-我把 Chrome 应用程序固定在我的 windows 电脑的任务栏上。我已经采取了图标截图(Chrome.PNG)如下:

我的 Windows 任务栏中 Chrome 图标的屏幕截图
现在,locateOnScreen()函数的用法如下
**icon_location = **pyautogui.locateOnScreen**(r'screenshots\Chrome.PNG')
print(icon_location)
>>> Box(left=446, top=1023, width=74, height=52)#Using the left & top values as x & y to click at that location
**pyautogui.click(x=446, y=1023, duration=0.25)****
我们只需要知道这些。现在,剩下的唯一事情就是将文本映射到 GUI 动作。这是我选择的贴图。

我的命令的屏幕截图
我附上了最终应用的演示视频和代码上传 这里 供参考。
功能演示
如果您碰巧阅读了我以前的一篇关于使用神经网络 进行手势识别的文章,我打算添加 PyAutoGUI 功能作为补充部分,以便根据预测的手势采取行动,这些动作基于这里 PyAutoGUI 部分讨论的相同原则。
结论
在这个演示中,我们看到了如何使用语音识别库将语音转换为文本,以及如何使用 PyAutoGUI 实现 GUI 自动化。通过结合这两种功能,我们建立了一个语音控制鼠标和键盘的基本版本。我希望您发现这些信息很有用,并以自己的方式使用它们。
使用 Python OpenCV 在图像和视频中检测人脸的介绍。
towardsdatascience.com](/face-detection-in-10-lines-for-beginners-1787aa1d9127) [## 绝对初学者的神经网络
用简单的英语介绍感知器
medium.com](https://medium.com/swlh/artificial-neural-networks-for-absolute-beginners-a75bc1522e1d)
参考文献:
[1] PyAutoGUI CheatSheet,【https://pyautogui.readthedocs.io/en/latest/quickstart.html
[2]语音识别 Python,【https://pypi.org/project/SpeechRecognition/ **
使用 PyTorch 和 Flask 构建预测苹果叶部病害的 Web 应用程序

使用预先训练的模型(VGG-16、雷斯网-18 和 AlexNet 架构)构建图像分类器 web 应用。
深度学习是处理非结构化数据的一个很好的模型,尤其是在图像上。这个领域的进展真的很快,其中一个进展就是一个叫迁移学习的东西。
迁移学习是一种训练已经在不同数据集上训练过的神经网络的方法,所以我们不必从头开始训练它,因为训练它们可能需要几天或几周的时间。
如果我们对我们的数据集使用迁移学习,只需要几个小时的训练,因为我们只训练最后一层。因此,我们可以使用它在其他数据集上训练已经预先训练好的模型及其给定的架构。
为了使模型有用,我们必须部署它们,例如通过构建一个 web 应用程序,使其对用户更加友好。幸运的是,我们可以使用 PyTorch 来构建深度学习模型,使用 Flask 来构建 web 应用程序。
在本文中,我将向您展示如何构建一个 web 应用程序来对苹果叶子进行图像分类,以分类它是否健康,如果不健康,叶子患了什么病。为此,我们可以使用 PyTorch 进行迁移学习,以及如何使用 Flask 构建一个简单的 web 应用程序。这是 web 应用程序的预览,

大纲
我们要做的第一件事是建立一个图像分类器。它由几个步骤组成,它们是:
- 下载数据,
- 准备数据,
- 建立模型,
- 测试模型,
- 保存模型。
分析
检索数据
对于数据集,我们可以使用 PlantVillage 数据集来检索我们要使用的数据集。你可以从这个 GitHub 库这里下载数据集。
准备数据
下载完数据后,我们可以先准备数据集。首先,我们必须将数据集组织到单独的文件夹中。
如果我们看到我们已经下载的数据集,我们可以看到有这么多来自不同植物的图像。在这种情况下,我们只选择与苹果相关的植物。
所以,我们把包含苹果叶子图片的文件夹带过去。

然后,我们将每个文件夹分成 3 个不同的文件夹,它们是 train、val 和 test。然后,我们将每组数据分成 80%用于训练数据(以 90:10 的比例将它们分成训练和验证数据)和 20%用于测试数据。每个文件夹的数量看起来像这样,

最后,该文件夹的结构将如下所示,

有了如上的文件夹结构后,我们就可以建立图像分类的模型了。在我们构建之前,我们必须导入数据集,我们还必须转换数据,以便它具有进入模型的相同表示。代码看起来会像这样,
正如我们在上面看到的,关于如何准备数据集有几个步骤。首先,我们必须转换数据集。这是必须的,因为模型无法处理没有所需大小的数据。因此,我们必须调整它的大小,并且用与模型的第一层相同的维度裁剪数据集。
然后,在我们转换图像之后,我们可以使用 ImageFolder 方法将其加载到我们的代码中。此外,我们将对数据集的转换应用于它。我们可以通过使用所有的训练数据集来训练模型,但这将花费很多时间。因此,我们必须创建批处理来减少计算时间。为了确保批次是随机的,我们必须将 shuffle 参数设置为 true。
最后,我们检索图像的数量和类名,还可以使用 torch.device 函数启用 GPU。完成所有步骤后,我们可以进入建模部分。
建立模型
因为我们是基于预先训练好的模型来构建模型的,所以我们要做的第一件事就是下载模型。在这种情况下,我只使用 VGG-16、ResNet-18 和 AlexNet 架构,然后我们比较哪个模型是最好的,并确保您将预训练参数设置为真。
因为我们使用它,所以我们必须设置参数,以便除了完全连接的最后一层之外,不计算梯度。然后,我们可以根据数据集上类的数量来改变最终层的输出神经元。然后,我们可以训练这个模型。
这是代码,
请确保您知道最终层的位置,因为每个模型都有不同的方法来访问它。使用 ResNet,我们可以访问 fc 索引来访问最终层,但在 VGG 和 AlexNet 上,我们通过索引分类器和索引号 6 来访问它。
通过在块代码上调用它,您可以看到每个模型的轮廓,这是代码和输出,

当我们训练模型时,它发生在几个时期。时期描述了训练模型的迭代次数。在每个时期,有几个步骤来训练模型。首先,模型前馈图像,并获得最佳输出。然后,它比较输出和真实标签,并计算损失。然后,它计算每个参数的梯度,然后根据模型的梯度更新每个权重。它不断重复,直到到达最后一个纪元,我们将从所有纪元中获得最佳模型。
这是每个型号的最佳结果,
**"""
For VGG-16,
Training complete in 27m 4s
Best val Acc: 0.964706** **For ResNet-18,
Training complete in 10m 7s
Best val Acc: 0.968627** **For AlexNet,
Training complete in 7m 40s
Best val Acc: 0.976471
"""**
要确定使用哪种模型,我们必须根据我们的需求来考虑。当然,我们需要一个非常精确的模型。但是如果我们想要部署到 web 应用程序,请确保您的模型具有较小的尺寸,以便我们可以在 GitHub 和 Heroku 上部署它。
基于这些结果,我们得出结论,AlexNet 是在 7 分 40 秒内对苹果上的疾病进行分类的最好和最快的模型。此外,我们可以看到,VGG-16 模型是最慢和最低的准确性得分。ResNet-18 位于中间位置。它不比 AlexNet 慢,而且它的精确度也比 VGG-16 高。但是,当我们部署这些型号时,ResNet-18 的尺寸最小。因此,我们将使用 ResNet-18 模型作为我们的分类器。
测试模型
如果要测试模型,可以在测试数据集上调用 dataloader 来测试模型是否能准确预测图像。代码看起来会像这样,
在那之后,我们得到了这样的输出,

**"""
GroundTruth: Cedar Apple Rust, Healthy, Black Rot, Healthy Predicted: Cedar Apple Rust, Healthy, Black Rot, Healthy
"""**
保存模型
所以,如果我们对我们的新模型有信心,我们可以挽救它。为此,我们可以使用下面的代码,
**# Save The Model**
PATH = ‘./fix_resnet18.pth’
torch.save(model_resnet.state_dict(), PATH)
它会将您的模型保存到。pth 格式。如果我们想在另一个会话中使用它,我们可以使用这个命令,
这就是如何使用 PyTorch 构建图像分类器!
构建 Web 应用程序
在我们创建模型之后,我们可以使用 Flask 构建 web 应用程序。总的来说,我们将做两件事。他们在服务器上工作,并创建页面来显示它。
构建服务器(app.py)
首先,我们要构建一个名为 app.py 的文件。它将处理网站,它包括显示页面,也将处理输入。在这种情况下,我们有一个图像输入。里面的代码看起来像这样,
让我解释它的每一行。第 1–8 行导入了我们需要的库,包括 Flask、PyTorch、string 等等。第 10 行声明了一个 Flask 对象。第 12–36 行使用 PyTorch 完成建模任务。第 38–43 行声明了一个显示预测结果的字典。第 46–58 行是我们 web 应用程序的主要流程。第 60–61 行使用下面的命令来确保我们的应用程序能够运行,
python app.py
你们中的一些人可能是第一次接触烧瓶。让我向你解释它是如何工作的。第 46 行是在网站上设置我们的路线。在这种情况下,在我们的网站上,如果我们想要显示主页面,我们将像 http://127.0.0.1:5000/ 一样转到那个根,在那里 URL 的最后一个字符描述了我们的路线。
里面还描述了 GET 和 POST 方法。它们描述了我们如何与网站互动。如果我们使用 GET 方法,我们只向服务器发出请求,不向那里发送任何文件。POST 方法将文件发送到服务器,并向服务器请求结果。
在第 47 行,它声明了一个名为 upload_file 的函数。它将对我们的数据起作用。如果我们首先打开 web,它将只使用 GET 方法来检索 web 页面。之后,我们给一个图像输入,然后上传它们。因为我们上传了数据,所以它将使用 POST 方法来处理我们的数据,从而预测叶子图像上存在的疾病。完成后,我们会收到一个新的页面,上面显示了叶子的疾病和描述。
构建页面
现在,我们创建描述主页和预测结果页面的网页。我们创建了三个文件,它们是 layout.html、index.html 和 result.html。等等,我们创建了两个页面,但是为什么还要创建另一个页面呢?
Flask 上有个概念叫模板。简而言之,我们不需要建立一个完整的网页。相反,我们构建附加页面作为所有页面的布局,所以我们不必为它编写完整的 HTML 代码。让我给你看看 layout.html 的档案,
正如我们所看到的,除了 body 标签中有一个{% block content %}命令之外,该网页没有任何内容。它被称为块,它将包含来自另一个文件的元素。让我给你看一下索引和结果页面,
从这两个文件中我们可以看到,我们没有对整个网页进行编码。相反,我们调用{% extends "layout.html" %}作为网站的模板。在它的下面,有块部分来填充它。这就是为什么我们不必从头开始构建,这使得我们的时间比以前更短。
在我们构建好代码并运行命令后,我们可以去 http://127.0.0.1:5000/ ,它会在网站上显示页面,

最终想法
迁移学习是一个有用的概念,可以实现我们自己的分类器,而无需从头开始训练它们。在本文中,我已经向您展示了我们如何在 PyTorch 上使用迁移学习的概念来构建不同的架构。此外,我已经向您展示了如何使用 Flask 构建 web 应用程序。确保您的模型不会消耗大量的存储空间,但仍然具有很高的准确性,这样您就可以毫无问题地部署模型。
希望对你有用,感谢你看我的文章。想看代码可以看我的 GitHub repo 这里。
使用 Python 在几分钟内构建一个 web 数据仪表板
通过 Plotly Dash 将您的数据可视化转换为基于 web 的仪表板,以指数方式提高功能和可访问性。

只用几行 Python 代码就能构建一个 web 数据仪表板
我不知道你是怎么想的,但我偶尔会发现不得不编写代码有点令人生畏。当我在构建类似于 web 开发的东西,而不是做一些本地数据分析和可视化时,更是如此。我是一个有能力的 Python 程序员,但是我根本不会称自己为 web 开发人员,即使我已经涉猎了 Django 和 Flask。
尽管如此,将您的数据输出转换为 web 应用程序会为您的项目带来一些不小的改进。
在 web 应用程序中嵌入真正的、强大的交互性要容易得多。这也意味着您可以准确控制数据的呈现方式,因为 web 应用程序可以成为事实上的报告以及数据的访问点。最后,也是最重要的,您可以指数级扩展对输出的可访问性;让它们随时随地可用。用户手边总有一个网络浏览器。
因此,我咬紧牙关,最近开始在我的一些数据项目中这样做,速度和效率惊人地快。我只用了几个小时就把这篇文章的一个输出转换成了一个 web 应用。

我的 NBA 分析网络应用(链接)
我认为这很酷,并想分享这是如何在短短几行代码中实现的。
和往常一样,我包括了你复制我的步骤所需要的一切(数据和代码),这篇文章并不是真的关于篮球。因此,如果您对它不熟悉,请不要担心,让我们开始吧。
在开始之前
数据
我把代码和数据放在我的 GitLab repo 这里 ( dash_simple_nba 目录)。所以请随意使用它/改进它。
包装
我假设您熟悉 python。即使你相对较新,这个教程也不应该太难。
你需要pandas、plotly和dash。用一个简单的pip install [PACKAGE_NAME]安装每一个(在你的虚拟环境中)。
前情提要。
在本教程中,我将简单地跳过创建我们观想的本地版本的大部分步骤。如果你对正在发生的事情感兴趣,看看这篇文章:
在各种数据集规模下,查看个体对整体的贡献以及随时间变化的最佳方式—(包括…
towardsdatascience.com](/create-effective-data-visualizations-of-proportions-94b69ad34410)
不过,我们将有一个回顾会议,因此您可以看到使用Plotly在本地绘制图表之间发生了什么,以及如何使用Plotly Dash将其移植到 web 应用程序。
加载数据
我对数据进行了预处理,并将其保存为 CSV 文件。这是当前 NBA 赛季(截至 2020 年 2 月 26 日)的球员数据集合,其中显示:
- 他们在自己球队的投篮命中率是多少,以及
- 他们做这件事的效率/效果如何。
对于这部分,请在我的回购中打开 local_plot.py 。
用以下内容加载数据:
all_teams_df = pd.read_csv(‘srcdata/shot_dist_compiled_data_2019_20.csv’)
用all_teams_df.head()检查数据,你应该看到:
每个球员的数据都是针对比赛的每一分钟(不包括加时赛)进行汇编的,统计数据pl_acc和pl_pps是唯一的例外,因为它们是针对比赛的每一个季度(每 12 分钟)进行汇编的。
这个数据框架包含了所有的 NBA 球员,所以让我们通过过滤一个球队来把它分解成一个可管理的大小。例如,新奥尔良鹈鹕队的球员可以选择:
all_teams_df[all_teams_df.group == 'NOP']
然后,我们的数据可以可视化,如下图所示:
import plotly.express as px
fig = px.scatter(all_teams_df[all_teams_df.group == 'NOP'], x='min_mid', y='player', size='shots_freq', color='pl_pps')
fig.show()

新奥尔良鹈鹕队的可视化球员数据
冒着这样做的风险:

如何画一匹马— Van Oktop ( Tweet )
我确实在我的图表中添加了一些小细节,以产生相同图表的这个版本。

相同的图表,添加了一些“小细节”(&不同的团队)。
这是我用来做这件事的代码。
现在,虽然有很多格式化代码,但我认为向您展示我是如何做的是有用的,因为我们将在代码的 Dash 版本中重用这些函数。
现在,让我们进入主题——如何从这些情节中创建一个 web 应用程序。
进入万维网
你可以在这里阅读更多关于 Plotly Dash 的内容,但现在你只需要知道它是一个开源软件包,开发它是为了消除将你的可视化放到网络上的困难。
它与Flask一起工作,你可以愉快地重用你在plotly.py中用来开发情节的大部分代码。
这是我整理的简单版本:
试试吧!它应该会在您的浏览器上打开这个图。

我们的第一款 Dash 应用!
有什么大不了的?首先,它是一个活的网络应用,不到 25 行代码。注意左上方的下拉菜单?试着改变上面的值,看着图形神奇地改变。
去吧,我等着。
好吗?完成了。
让我们简单地浏览一下代码。
总体而言,我现在要做的是:
- 初始化 Dash 应用程序;
- 获取一个可用团队名称的列表,并将其提供给一个带有默认值或“TOR”的下拉菜单(带有 DOM id
group-select); - 实例化一个图形对象作为 Dash 中的
shot-dist-graph标识符;和 - 创建一个回调函数,如果任何值发生变化,它将调用
update_graph函数并将返回的对象传递给Output。
如果你看一下代码,那么许多对 web 开发人员来说可能微不足道但对我来说很烦人的东西都被抽象掉了。
dcc。Graph 将 plotly.py 中的图形对象包装到我的 web 应用程序中,并且可以使用 html 方便地调用和设置像 div 这样的 HTML 组件。Div 对象。
对我个人来说,最令人满意的是输入对象和来自这些输入的回调是以声明方式设置的,我可以避免处理 HTML 表单或 JavaScript 之类的东西。
由此产生的应用程序仍然运行良好。使用下拉菜单选择另一个值时,图表会更新。
我们只用了不到 25 行代码就完成了所有这些工作。
为什么是 Dash?
在这一点上,你可能会问——为什么是 Dash?我们可以用 JS 框架前端、Flask 或无数其他组合中的任何一个来完成所有这些。
对于像我这样喜欢 Python 的舒适性而不是原生处理 HTML 和 CSS 的人来说,使用 Dash 抽象掉了许多不会给最终产品增加很多价值的东西。
举个例子,这个应用程序的一个版本包含了更多的格式和给用户的注释:
(在 git 回购中是simple_dash_w_format.py
大多数更改都是修饰性的,但是我要注意,在这里,我只是在 Markdown 中编写了主体文本,并简单地从 Plotly 中继承了我的格式化函数,以用于 Dash 中的图形格式化。
这为我节省了从数据分析和可视化到部署到客户视图之间的大量时间。
总而言之,从我最初的图表开始,我认为把它部署到 Heroku 大概用了不到一个小时。这真是太神奇了。
我将深入 Dash 的更多高级特性,并实际上用它做一些很酷的功能性的事情,但我对这个结果在易用性和速度方面非常满意。
你自己试试吧——我想你会印象深刻的。下一次,我计划写一些你可以用 Dash 做的非常酷的事情,以及构建真正交互式的仪表板。
编辑:我正在为的所有事物数据和可视化开始一个子堆栈——这将是我直接与你接触的一种方式。我希望你能加入我。
数据无处不在,并且随着媒体对“大数据”的大量报道而呈指数级增长
visualnoise.substack.com](https://visualnoise.substack.com/p/coming-soon)
我也写了一点关于为什么我要开始一个子栈。
如果你喜欢这个,比如说👋/在 twitter 上关注,或关注更新。这是数据 viz 所基于的文章:
在各种数据集规模下,查看个体对整体的贡献以及随时间变化的最佳方式—(包括…
towardsdatascience.com](/create-effective-data-visualizations-of-proportions-94b69ad34410)
此外,这是我写的另一篇关于通过更好地可视化时间序列数据来改进基于数据的故事的文章:
使用 Python 和 Plotly 构建清晰易读的时序数据可视化,以支持您的叙述。
towardsdatascience.com](/effectively-visualize-data-across-time-to-tell-better-stories-2a2c276e031e)
用 Python 构建一个 YouTube 下载器
在 PyTube3 的帮助下,学习使用 Python 构建一个简单的 YouTube 下载器

Kon Karampelas 在 Unsplash 上拍摄的照片
读者你好!今天,我们将使用 PyTube3 库在 Python3 中构建一个 YouTube 下载器。原来的 pytube 库不再工作,所以我们需要使用 pytube3 库,它只适用于 Python3,不适用于 Python2。
我们将看到我们可以用 Youtube 下载器做的各种事情,以及它为我们提供的各种功能。所以,我们一步一步来。
下载和导入库
首先,在做任何事情之前,您需要在您的系统中下载 pytube3 库。为此,我们将使用 python3。
在 CLI 中键入以下命令,在您的系统中下载并安装 pytube3。
pip install pytube3
该命令将在您的系统中下载并安装 pytube3。
现在我们可以开始构建我们的 YouTube 下载器了。我们需要将这个库导入到我们的程序中来使用它的功能。
因此,我们用下面的命令开始我们的程序:
from pytube import YouTube
你会注意到,虽然我们在系统中下载并安装了 pytube3,但是我们在代码中导入了 pytube。
为了消除混淆,pytube3 也是通过只编写 pytube 来导入的。我们不会通过将它写成 pytube3 来导入它。
接受用户的输入
我们的下一步是要求用户提供我们需要下载的 youtube 视频的链接。然后,用户将向我们提供他想要下载的视频的链接。
link = input("Enter the link: ")
yt = YouTube(link)
因此,我们接受了用户的输入,并将链接传递给我们的 YouTube 类。它将帮助我们揭示视频的所有信息,并让我们下载它。
揭示关于视频的各种信息
现在我们有了链接,并且我们已经将它传递给了 YouTube 类。现在,我们可以玩链接,并显示视频的各种信息,如标题,观看次数,收视率,描述,视频长度和其他各种事情。
#Title of video
print("Title: ",yt.title)
#Number of views of video
print("Number of views: ",yt.views)
#Length of the video
print("Length of video: ",yt.length,"seconds")
#Description of video
print("Description: ",yt.description)
#Rating
print("Ratings: ",yt.rating)
当我们运行这段代码时,我们将看到关于视频的各种细节,我们已经将视频的链接输入到程序中。此外,还有更多这样的操作可以执行,您可以在 pytube3 的官方文档中找到。
因此,出于输出的目的,我们不打印描述(它很大),所以我们打印其余的四样东西。
我们在这里使用了《黑暗》第三季官方预告片的链接。您可以使用自己选择的任何链接。
显示视频各种细节的输出
所以,正如你在上面看到的,我们已经打印了关于这个节目的各种细节。
查看可用的流
你一定已经看到 youtube 上有各种各样的质量可供观看。因此,在使用 pytube 下载的同时,我们还可以获得所有可用流的选项。
pytube 提供了一种非常简单的方法来查看用户提供的链接的所有可用流。因此,让我们运行代码来查看该特定视频的所有可用流。
#printing all the available streams
print(yt.streams)
在运行上面的代码时,我们获得了该视频的所有可用流。下面是生成的输出:
视频的可用流
现在,你可以看到视频和音频流。所以,你也可以只过滤掉音频或视频流。您还可以根据文件格式过滤掉流。我们还可以过滤出渐进流和破折号流(稍后会谈到它们)。
所以,让我们过滤掉只有音频的流。为此,我们需要编写如下代码:
print(yt.streams.filter(only_audio=True))
我们将得到的输出如下:
纯音频流
现在,让我们过滤掉只有视频的流。它将只显示包含视频但没有音频的流。所以,它也会过滤掉所有的渐进流。为此,我们将这样写:
print(yt.streams.filter(only_video=True))
我们将得到的输出如下:
仅视频流
现在,让我们来谈谈渐进的 v/s 破折号流。YouTube 使用 Dash 流进行更高质量的渲染。
渐进流被限制为 720p,并包含音频和视频编解码器文件,而 Dash 流具有更高的质量,但只有视频编解码器。
因此,如果我们想下载一个渐进流,我们将得到一个内置音频的现成视频。
但是,为了更高的质量,我们应该为视频使用 Dash 流,还应该下载一个音频流,然后使用任何混合工具合并它们。
因此,对于本文,我们将使用渐进式流下载来准备播放视频。你可以自由选择你的下载质量和选择流。
所以,我们先过滤掉渐进流。下面的代码将为我们做这件事:
print(yt.streams.filter(progressive=True))
它将列出可供我们下载的渐进流。它将有有限的选择,但它为我们做了工作。输出将如下所示:
可用的累进流
为了获得最高分辨率的渐进流,我们可以编写下面的代码:
ys = yt.streams.get_highest_resolution()
这将在 ys 变量中创建并存储最高分辨率的流。
我们也可以在 itag 的帮助下选择任何流。
ys = yt.streams.get_by_itag('22')
因此,现在我们已经将首选流存储在一个变量中。现在,让我们把它下载到我们的系统。
ys.download()
上面的代码将下载我们的首选流,并将其保存在当前的工作目录中。
我们还可以在系统中指定下载 youtube 视频的位置。我们可以通过在下载的大括号之间指定绝对路径来做到这一点。
下面的代码帮助您将它下载到您喜欢的位置。
ys.download('location')
仅此而已!恭喜你,你已经使用 Python 构建了你的第一个简单的 YouTube 下载器。仅用于测试和教育目的。不要滥用这些知识。
以下是使用最高质量的渐进流下载 youtube 视频的完整代码:
YouTube 下载器的完整代码
请访问我的 GitHub 库了解更多细节和更新。我鼓励你们尝试一些新的东西,然后请在评论中分享你们的想法和经验。我很想听听你学到了什么,还做了些什么。祝大家一切顺利!
看,我们在这里建立的是一个非常简单的版本。我们还可以尝试将相同的概念转换成一个应用程序或网站,以用户友好的方式执行相同的功能。您还可以通过使用不同网站各自的 API 来添加对不同网站的支持。有许多这样的功能丰富的视频下载软件,它们使用类似的概念,并给用户一个轻松下载视频的选项。
我最喜欢的一个是 YTSaver ,这是一个功能丰富的应用程序,可以一键从大量网站下载不同分辨率和格式的视频或播放列表。它还允许你将视频从一种格式转换成另一种格式,并且比其他下载者快得多。
注意:以上段落包含一个附属链接。
实际上,你也可以使用 Python 库,比如这个,将视频从一种格式转换成另一种格式。如果你有兴趣,也可以尝试这样做。非常感谢您的阅读!
读完这篇文章后,还有更多的故事值得一读
[## 使用 Django Rest 框架构建博客网站——概述(第 1 部分)
让我们使用 Django Rest 框架构建一个简单的博客网站,以了解 DRF 和 REST APIs 是如何工作的,以及我们如何添加…
towardsdatascience.com](/build-a-blog-website-using-django-rest-framework-overview-part-1-1f847d53753f) [## 用 MERN 堆栈构建一个电子商务网站——第 1 部分(设置项目)
让我们使用 MERN 堆栈(MongoDB,Express,React 和 Node)建立一个简单的电子商务网站,用户可以在其中添加项目…
shubhamstudent5.medium.com](https://shubhamstudent5.medium.com/build-an-e-commerce-website-with-mern-stack-part-1-setting-up-the-project-eecd710e2696) [## 用 Django 构建求职门户——概述(第 1 部分)
让我们使用 Django 建立一个工作搜索门户,它允许招聘人员发布工作并接受候选人,同时…
shubhamstudent5.medium.com](https://shubhamstudent5.medium.com/build-a-job-search-portal-with-django-overview-part-1-bec74d3b6f4e) [## 使用 Django 构建一个社交媒体网站——设置项目(第 1 部分)
在第一部分中,我们通过设置密码来集中设置我们的项目和安装所需的组件…
towardsdatascience.com](/build-a-social-media-website-using-django-setup-the-project-part-1-6e1932c9f221)
使用 TensorFlow 和 Streamlit 构建一个应用程序来生成逼真的人脸
我们将向您展示如何使用 GANs、Tensorflow 和 st.cache 快速构建一个 Streamlit 应用程序来合成名人面孔。

【GAN 合成脸】
机器学习模型是黑盒。是的,你可以在测试集上运行它们,并绘制出奇特的性能曲线,但是通常很难回答关于它们性能的基本问题。一个惊人的强大的洞察力来源是简单的玩你的模型!调整输入。观察输出。让你的同事和经理也和他们一起玩。这种互动的方法不仅是获得直觉的有力途径,也是让人们对你的工作感到兴奋的好方法。
制作交互式模型是启发 Streamlit 的用例之一,Streamlit 是一个 Python 框架,它使编写应用程序像编写 Python 脚本一样简单。这个概述将带你创建一个 Streamlit 应用程序,与最复杂、最黑箱化的模型之一一起玩:深度生成对抗网络 (GAN)。在这种情况下,我们将想象 Nvidia 的 PG-GAN [1]使用 TensorFlow 从稀薄的空气中合成照片级真实感人脸。然后,使用关的惊人的 TL-GAN 模型[2],我们将创建一个应用程序,让我们能够根据年龄、笑容、男性相似度和头发颜色等属性调整 GAN 合成的名人脸。在本教程结束时,你将拥有一个完全参数化的人类模型!(注意,我们没有创建属性。它们来自 CelebA 数据集【3】,其中一些可能会变得有点奇怪……)
Streamlit 入门
如果您尚未安装 Streamlit,可以通过运行以下命令来安装:
pip install streamlit
streamlit hello
如果你是一个经验丰富的简化者,你需要安装 0.57.1 或更高版本,所以一定要升级!
pip install --upgrade streamlit
设置您的环境
在我们开始之前,使用下面的命令来检查该项目的 GitHub repo 并亲自运行 Face GAN 演示。这个演示依赖于 Tensorflow 1,它不支持 Python 3.7 或 3.8,所以您需要 Python 3.6。在 Mac 和 Linux 上,我们建议使用 pyenv 安装 Python 3.6 和您当前的版本,然后使用 venv 或 virtualenv 建立一个新的虚拟环境。在 Windows 上, Anaconda Navigator 允许你用点击界面选择你的 Python 版本。
设置完毕后,打开终端窗口并键入:
git clone [https://github.com/streamlit/demo-face-gan.git](https://github.com/streamlit/demo-face-gan.git)
cd demo-face-gan
pip install -r requirements.txt
streamlit run app.py
给它一分钟来完成下载训练好的 GAN,然后尝试玩滑块来探索 GAN 可以合成的不同面孔。很酷,对吧?

完整的应用程序代码是一个大约有 190 行代码的文件,其中只有 13 行是 Streamlit 调用。没错,上面整个 UI 就是从那 13 行画出来的!
让我们来看看这个应用程序是如何构建的:
现在你对它的结构有了一个概念,让我们深入上面的 5 个步骤,看看它们是如何工作的。
第一步。下载模型和数据文件
这一步下载我们需要的文件:一个预先训练的 PG-GAN 模型和一个预先适合它的 TL-GAN 模型(我们稍后会深入讨论这些!).
download_file实用功能比纯粹的下载器要聪明一点:
-
它检查文件是否已经存在于本地目录中,所以它只在需要时才下载它。它还检查下载文件的大小是否符合我们的预期,因此它能够修复中断的下载。这是一个很好的模式!
-
它使用
st.progress()和st.warning()在文件下载时向用户显示一个漂亮的 UI。然后它调用这些 UI 元素上的.empty()来隐藏它们。
第二步。将模型载入内存
下一步是将这些模型载入内存。以下是加载 PG-GAN 模型的代码:
注意load_pg_gan_model()开头的@st.cache装饰器。通常在 Python 中,你可以运行load_pg_gan_model()并反复重用那个变量。然而,Streamlit 的执行模型是独一无二的,因为每次用户与 UI 小部件交互时,你的脚本都会在中完整地再次执行。通过将@st.cache添加到昂贵的模型加载函数中,我们告诉 Streamlit 只在脚本第一次执行时运行这些函数——并在以后的每次执行中重用缓存输出。这是 Streamlit 最基本的特性之一,因为它允许您通过缓存函数调用的结果来高效地运行脚本。这样,大的合适的 GAN 模型将恰好被加载到存储器中一次;出于同样的原因,我们的 TensorFlow 会话也将恰好创建一次。(请参阅我们的发布文章以重温 Streamlit 的执行模型。)**

【图 1。缓存如何在 Streamlit 的执行模型中工作]
不过,有一个问题:TensorFlow 会话对象在我们使用它运行不同的计算时可能会发生内部变异。通常,我们不希望缓存的对象发生变异,因为那会导致意想不到的结果。因此,当 Streamlit 检测到这种突变时,它会向用户发出警告。然而,在这种情况下,我们碰巧知道,如果 TensorFlow 会话对象发生变异,这是可以的,因此我们通过设置allow_output_mutation=True来绕过警告。
第三步。绘制侧栏用户界面
如果这是您第一次看到 Streamlit 用于绘制小部件的 API,下面是 30 秒速成课程:
- 您可以通过调用像
st.slider()和st.checkbox()这样的 API 方法来添加小部件。 - 这些方法的返回值是 UI 中显示的值。例如,当用户将滑块移动到位置 42 时,您的脚本将被重新执行,在执行过程中,
st.slider()的返回值将是 42。 - 你可以通过在侧边栏中添加
st.sidebar来放置任何东西。比如st.sidebar.checkbox()。
例如,要在侧边栏中添加一个滑块——一个允许用户调整brown_hair参数的滑块,您只需添加:
在我们的应用程序中,我们想展示一下让 UI 本身在 Streamlit 中可修改是多么容易!我们希望允许用户首先使用多选小部件来选择一组他们希望在生成的图像中控制的功能,这意味着我们的 UI 需要以编程方式绘制:

使用 Streamlit,代码实际上非常简单:
第四步。合成图像
现在我们有了一组特征来告诉我们合成什么样的脸,我们需要做合成脸的繁重工作。我们的方法是将特征传递给 TL-GAN,在 PG-GAN 的潜在空间中生成一个向量,然后将该向量传递给 PG-GAN。如果那句话对你来说没有意义,让我们绕道来谈谈我们的两个神经网络是如何工作的。
绕道进入甘斯
为了理解上面的应用程序如何从滑块值生成人脸,你首先必须了解 PG-GAN 和 TL-GAN 的工作原理——但是不要担心,你可以跳过这一部分,仍然可以在更高的层次上理解该应用程序的工作原理!
PG-GAN 就像任何 GAN 一样,从根本上来说是一对神经网络,一个是生成性的,一个是鉴别性的,它们相互训练,永远锁定在致命的战斗中。生成网络负责合成它认为看起来像人脸的图像,而鉴别网络负责决定这些图像是否确实是人脸。这两个网络根据彼此的输出进行迭代训练,因此每个网络都尽最大努力学习愚弄另一个网络。最终结果是,最终的生成网络能够合成逼真的人脸,即使在训练开始时,它只能合成随机噪声。这真的很神奇!在这种情况下,我们使用的生成人脸的 GAN 是由 Karras 等人使用他们的GANs渐进生长算法(PG-GAN)在名人脸上训练的,该算法使用渐进的更高分辨率图像训练 GAN。[1]
PG-GAN 的输入是属于其所谓的潜在空间的高维向量。潜在空间基本上是网络可以生成的所有可能的脸的空间,所以该空间中的每个随机向量对应于一个唯一的脸(或者至少应该是这样!有时你会得到奇怪的结果…)你通常使用 GAN 的方式是给它一个随机向量,然后检查合成了什么面(图 2.a)。

[图 2.a]
然而,这听起来有点枯燥,我们宁愿对输出有更多的控制。我们想告诉 PG-GAN“生成一个有胡子的男人的图像”,或者“生成一个棕色头发的女人的图像”。这就是 TL-GAN 发挥作用的地方。
TL-GAN 是另一种神经网络,这种网络通过将随机向量输入 PG-GAN 进行训练,获取生成的面部,并通过分类器对其进行分类,例如“是否年轻”、“是否有胡子”、“是否有棕色头发”等。在训练阶段,TL-GAN 使用这些分类器标记来自 PG-GAN 的数千张人脸,并识别潜在空间中与我们关心的标签变化相对应的方向。因此,TL-GAN 学习如何将这些类别(即“年轻的”、“有胡子的”、“棕色头发的”)映射到适当的随机向量中,该向量应输入到 PG-GAN 中,以生成具有这些特征的人脸(图 2.b)。

[图 2.b]
回到我们的应用程序,此时我们已经下载了预训练的 GAN 模型并将其加载到内存中,我们还从 UI 中抓取了一个特征向量。因此,现在我们只需将这些特性输入 TL-GAN,然后输入 PG-GAN,就可以得到一幅图像:
优化性能
上面的generate_image()函数可能需要一些时间来执行,尤其是在 CPU 上运行时。为了提高我们的应用程序的性能,如果我们可以缓存该函数的输出就太好了,这样我们就不必在来回移动滑块时重新合成我们已经看到的人脸。
嗯,你可能已经在上面的片段中注意到了,这里的解决方案是再次使用@st.cache装饰器。
但是请注意我们传递给@st.cache的两个参数:show_spinner=False和hash_funcs={tf.Session: id}。那些是干什么用的?
第一个很容易解释:默认情况下,@st.cache在 UI 中显示一个状态框,让您知道一个运行缓慢的函数正在执行。我们称之为“旋转器”。然而,在这种情况下,我们希望避免显示它,这样 UI 就不会意外地跳跃。所以我们将show_spinner设置为假。
下一个解决了一个更复杂的问题:TensorFlow 会话对象,作为参数传递给generate_image(),通常在这个缓存函数运行期间被 TensorFlow 的内部机制改变。这意味着generate_image()的输入参数总是不同的,我们实际上永远不会获得缓存命中。换句话说,@st.cache decorator 实际上什么都不会做!我们如何解决这个问题?
哈希函数拯救世界
hash_funcs 选项允许我们指定定制的哈希函数,告诉@st.cache在检查这是缓存命中还是缓存未命中时应该如何解释不同的对象。在这种情况下,我们将使用该选项通过调用 Python 的id()函数而不是检查其内容来告诉 Streamlit 散列 TensorFlow 会话:
这对我们很有用,因为在我们的例子中,会话对象实际上是底层代码所有执行中的一个单独对象,因为它来自@st.cache'd load_pg_gan_model()函数。
关于hash_funcs的更多信息,请查看我们关于高级缓存技术的文档。
第五步。绘制合成图像
现在我们已经有了输出图像,绘制它是小菜一碟!只需调用 Streamlit 的st.image函数:
*st.image(image_out, use_column_width=True)*
我们完事了。
包扎
现在你有了:在一个 190 行的 Streamlit 应用程序中使用 TensorFlow 进行交互式人脸合成,并且只有 13 个 Streamlit 函数调用!祝你在探索这两位 GANs 能画的人脸空间时玩得开心,非常感谢 Nvidia 和关让我们制作了他们超酷的演示。我们希望你能像我们一样享受构建应用程序和玩模型的乐趣。🎈
如需更多 Streamlit 应用示例,您可以查看我们在https://www.streamlit.io/gallery的图库。
感谢 Ash Blum、TC Ricks、Amanda Kelly、Thiago Teixeira、Jonathan Rhone 和 Tim Conkling 对本文的有益贡献。
参考文献:
[1] T. Karras,T. Aila,S. Laine,J. Lehtinen。为了提高质量、稳定性和多样性而逐步种植甘蔗。学习代表国际会议(ICLR 2018)
[2] S .关。使用新型 TL-GAN 模型控制图像合成和编辑。洞察数据科学博客(2018)
[3]刘,罗,王,唐。在野外深度学习人脸属性。计算机视觉国际会议(ICCV 2015)
使用这些工具,立即构建一个令人敬畏的数据科学(或任何)投资组合
节省时间&建立一个漂亮的在线形象。大多数数据科学家对原始 HTML & CSS 有什么用?

安内特·lūsiņa 在 Unsplash 上拍摄的照片
互联网被认为是一种民主化的力量。在很多方面都是如此。从某种程度上来说,这无疑是教育的民主化,以至于在某些领域,你可以成为一名高水平的从业者,跟上前沿的发展,甚至不需要脱掉睡衣。
但是在互联网上获得地位的门槛一直相对较高。要在网上构建任何值得他们称赞的东西,你必须编码。
当然,HTML 和 CSS 并不是最难学的语言,但它是另一种需要学习的语言。

耶,HTML/CSS(照片由 Pankaj Patel 在 Unsplash 上拍摄)
如果你还不知道 web 编程,是否值得花时间去学习它,以至于你可以建立一个让你感到自豪的网站并向人们展示?
对于那些将 web 开发作为一项关键技能的人,或者那些好奇且有时间的人,去做吧。但是如果是一个你没什么用的技能呢?仅仅为了建一个网站,学习这些知识的痛苦值得吗?与部署和维护相关的所有麻烦怎么办?一定有更好的方法。
幸运的是,有许多工具可以提供帮助。实际上,据我所知,只有。所以。很多。工具。
这意味着有足够多不同的工具,无论你是谁,都可能有合适的工具。新的入门障碍实际上是费力地通过一堆工具包,并在每一个工具包中寻找,看看它是否是适合您的工具集。这听起来并不难,但也不像听起来那么简单。在一个软件激增的世界里,为你的确切用例研究一个 SaaS 服务或开源软件是很困难的,甚至不总是可能的。
所以在这篇文章中,我列出了一些我认为对我们大多数人来说是最好的选择的工具。希望你觉得有用。
注意:下面的一些链接是附属链接,这意味着在你没有额外费用的情况下,如果你买东西,我会给你一小笔佣金。
对于视觉思考者来说
这不是你想的那样
我将首先介绍这个工具,我认为对于大多数不熟悉 HTML/CSS(可能是 JS)的人来说,它确实是最好的工具,而且我也不在乎。

不幸的是,这不是我喜欢的(图片由网络工厂有限公司在 Unsplash 上拍摄)
不,是不是 WordPress。太… 2010 年了。
是的,它被广泛使用。但微软 Word 也是。是的,它是最受欢迎的,它的安装用户群、广泛(且廉价)可用的专业知识之间有着巨大的推动力。但是它有点过时了,它开始显示出它的年龄和事实,它是一个建立在一百万个插件上的城堡,被现在二十年的发展压得喘不过气来。
更重要的是,要真正定制它,你最终必须学习它的基本架构,在我看来,这实际上不如学习 HTML/CSS 有用,除非你想成为一名 WordPress 开发者。
并不是说这有什么错!但这不适合我。
相反,我建议…
Webflow

用 Webflow 制作的网站示例(截图: Webflow 网站)
鉴于我对 WordPress 的不满,你可能已经看到了这一点。 Webflow 基本上是 DreamWeaver 在互联网早期想做的,也是假装的,但你知道,现在是。
它所能做的非常强大,而且它真的把整个 nocode 民族精神放在了心上。您想创建自定义滚动动画吗?互动?让元素基于用户的动作淡入/淡出或隐藏,并控制触发器、定时和视觉效果——所有这些都无需编码?没错。
包括电池吗?就像在,在研究了主要工具之后,我不需要搜索一堆不同的插件(例如 Webflow vs Wordpress vs Wix 等等。)?没错。
它是否创建了具有生产就绪/干净代码的站点?也是的。虽然我不能量化这一点,但通过像 Reddit 这样的公正论坛的搜索向我表明,Webflow 的代码与 Wix 这样的工具相距甚远。如果你愿意,Webflow 还允许你带着球回家(即导出代码),这样你就不会留下看起来像计算机科学一年级学生吐在键盘上的代码。
我还喜欢 Webflow 有一套全面的教程来帮助你快速上手。

Webflow 的教程站点很棒(截图: Webflow 大学)
如果你和你的投资组合一起做一些事情,比如建立一个电子商务门户,你也可以用 Webflow 来做。您不需要迁移到新的平台。
基于力量&相对较低的学习曲线的平衡,从我个人的经验来说,我怎么推荐 Webflow 都不为过。现在,有一些更容易学习的工具,我们会回到这个话题。但是在 Webflow 上获得一个漂亮的网站仍然很容易,我稍后将讨论的一些选项没有提供太多的灵活性。
对于我们这些非 web 编程专家来说,Webflow 绝对是一个不错的选择。
但是等等,我还没说完呢!仅举一个选项就够糟糕的了。根据您的需求,还有很多其他的好选择。
快速和免费-美国
首先,为这个糟糕的双关语道歉。但有时这是必须要做的。
不幸的是,Webflow 不是免费的。(你可以免费试用,但我相信你最终还是要付费的。)但是如果那对你很重要的话,确实有免费的解决方案,如果那是你所追求的,你必须做出令人惊讶的很少的妥协。
如果你属于这一类,静态网站建设者可能是你最好的选择,我个人推荐:
Netlify + 盖茨比(…或类似的——下文详述)

用盖茨比制作的网站示例(截图:盖茨比网站)
Gatsby 是少数领先的静态站点生成器之一,还有 Next.js、Hugo 和 Jekyll 等等。
静态站点生成器令人敬畏的原因是它们可以生成静态站点。
与动态网站不同,静态网站不需要任何后端处理,就像用户请求发送到服务器,服务器做一些事情,然后前端呈现服务器返回的输出。
唯一需要的是静态文件被托管在某个地方,用户访问它,然后主机只需要将文件交付给用户。
这减少了运行网站的大量计算需求,以至于相对容易找到免费托管这些网站的提供商。Netlify 和 GitHub 页面就是两个典型的例子。
静态网站的其他好处是速度和可伸缩性。由于其架构,它们的速度快如闪电,并且它们的低需求意味着服务器基本上可以处理任何事情。实际上,除了一群僵尸同时浏览你的网站寻找地球上最后一个大脑之外,任何事情都没问题。
你有没有注意到,虽然我推荐盖茨比和 Netlify,我还没有提到它?的确,盖茨比是我个人最喜欢的。但其他流行的软件包,如 Next.js、Hugo 或 Jekyll 都是优秀的工具,这也是事实(看看 Jamstack.org 的这个列表)。

只是一些美味的 Jamstack 选项(截图:【Jamstack.org】T2)
很大程度上,我认为选择一个是非常个人的决定,取决于对任何底层编程语言的熟悉程度。我选择了盖茨比,因为它听起来很棒,我想我会潜移默化地学到一些 JS,但是 ymmv。
查看 盖茨比这里 ,还有 Netlify 这里
代码,但保持 Python
作为 TDS 的读者,我打算假设你是 Python 用户(抱歉,R 用户)。有很多方法可以让你不用离开我们舒适的蛇朋友就可以上网工作。
你们中的许多人将会在你们的作品集中展示数据科学的成果,以各种形式,比如可视化或者可能是笔记本。那么,为什么不使用(并学习)那些被设计用来展示这些的工具,并去掉中间人呢?
破折号或流线型 + Heroku

Dash 应用程序示例——看起来像是很棒的投资组合材料!(截图: Plotly 网站)
我写过一些关于 Dash 和 Streamlit 的文章,正如我在那些文章中提到的,它们让创建 web 应用程序变得如此简单。没有规定说你的作品集不能用这些网络应用来建立。
事实上,这些工具可能会很好地展示您的数据科学和可视化能力,而不会超出 Python 的范围,因为这正是它们应该做的。
Dash 或 Streamlit 等 web 应用程序的一个缺点是,它们需要更多的资源,因此需要更多的服务器容量。话虽如此,Heroku 或 PythonAnywhere 等服务的免费层对于投资组合网站来说已经足够了,除非你是某种摇滚明星,否则我无法想象一个投资组合网站获得如此多的流量,以至于它会淹没那些免费层应用程序的容量。
至于这两者中的哪一个,Streamlit 可能更容易掌握和使用,但 Dash 提供了更多的可定制性,例如可以使用引导主题和样式。此外,正如我以前说过的,Dash 可能更有可能用于生产,而不是 Streamlit,后者更像是一种快速原型开发工具。
因此,如果是我,我可能会学习和使用 Dash,并使用 Heroku 进行部署,这在我看来是最容易的,利用他们的免费层。
威风凛凛的

Jovian 项目示例(截图: Jovian.ai 网站)
我怀疑你们中的一些人可能听说过木星,虽然可能不是大多数。这是一家相对年轻的初创公司,旨在简化 Jupyter 笔记本的共享和协作。
它允许共享整个笔记本,如下所示,或者将笔记本的某些部分嵌入到另一个媒体,如博客。

与 Jovian 分享笔记本(截图: Jovian.ai 网站)
因此,如果你的作品存在于笔记本中,Jovian 可能是以其原始形式展示你的作品的最佳方式,或者将它们托管在某个地方并嵌入其中的一部分。
保持平缓的学习曲线
这些解决方案不会给你最大的可定制性或最好看的网站,但你可能会得到一些东西,并在任何时间运行。
观念 + Super.so

用 sites 和 Super.so 创建的示例站点(截图: super.so 网站)
观念是一个相对较新的平台,他们声称这是一个“写作、计划和组织”的工具。
这是一个工具,我会把它描述为互连的 Evernote、nocode 数据库、日历、看板……基本上是你能想到的任何东西。
这个功能强大的笔记本工具与建立投资组合有什么关系?
嗯,有一个名为 super 的第三方应用程序,它将把你的概念项目变成一个功能齐全的网站,拥有网站需要的东西——比如分析和部署到一个域上。
展示页面显示,相当多的人已经使用这个设置来组合他们的投资组合。这可能是将投资组合在一起的最简单的方法之一,而概念的局限性也使得做出一个不好看的投资组合变得更加困难。
中等

对我来说,这看起来像是投资组合页面的良好开端(截图:Medium.com/@_jphwang
你可能会怀疑,但请听我说完。什么是投资组合?这是为了展示你的能力,无论你想为它建立一个品牌。Medium 提供了一个可靠、易用、美观的平台,它是免费的,你可以在其中嵌入各种格式的文档。
它有明显的局限性,主要是一个博客平台,它不是你自己的领域,但考虑到这种方法的准入门槛很小,它们是很好的权衡。
对于一些人来说,这可能会给他们一个更好的机会,有人有机地找到你的投资组合,而不是有一个搜索引擎优化分数低的网站。
对于策展,我建议创建你自己的“出版物”并在那里托管你的作品集,比如为我们这些幸运地需要多个作品集的人托管不同的作品集(比如数据科学作品集和 web 开发作品集)。
那就到此为止了。我希望你至少能找到其中一个适合你的选择。如果你跳到最后,TL;博士的意见是 Webflow 是我推荐的工具,但是根据你的情况,其他人可能也适合。
我之前看了相当多的投资组合来整理这篇关于惊人投资组合的文章,所以我知道它们有各种形状和大小。
** [## 这些数据科学产品组合将让您惊叹不已并深受启发(2020 年中期版)
使用这些来改进您自己的数据科学产品组合,学习新技能或发现新的有趣项目。
towardsdatascience.com](/these-data-science-portfolios-will-awe-and-inspire-you-mid-2020-edition-728e1021f60)
所以如果我错过了你最喜欢的工具,请写信告诉我。
但是在你离开之前——如果你喜欢这个,在 twitte r 上打个招呼/关注,或者关注这里的更新。**
****编辑:我正在为所有事物数据和可视化开始一个子堆栈——这将是我与你直接接触的一种方式。我希望你能加入我。
数据无处不在,并且随着媒体对“大数据”的大量报道而呈指数级增长
visualnoise.substack.com](https://visualnoise.substack.com/p/coming-soon)
我也写了一点为什么我开始一个子栈。**
ICYMI:我也写了这些文章,你可能会觉得有用:
** [## 使用 Python 在几分钟内构建一个 web 数据仪表板
通过将您的数据可视化转换为基于 web 的仪表板,以指数方式提高功能和可访问性…
towardsdatascience.com](/build-a-web-data-dashboard-in-just-minutes-with-python-d722076aee2b) [## Plotly Dash 与 Streamlit——哪个是构建数据仪表板 web 应用程序的最佳库?
用于共享数据科学/可视化项目的两个顶级 Python 数据仪表板库的比较——
towardsdatascience.com](/plotly-dash-vs-streamlit-which-is-the-best-library-for-building-data-dashboard-web-apps-97d7c98b938c)
在外面注意安全!**
用 Python 构建一个极限学习机
无参数调整的神经网络构建指南。

乔希·里默尔在 Unsplash 上的照片
极端学习机(ELMs)是单隐层前馈神经网络(SLFNs ),与基于梯度的学习技术相比,能够更快地学习。这就像一个没有学习过程的经典的单隐层神经网络。这种神经网络不执行迭代调整,使得它比使用反向传播方法训练的网络更快,具有更好的泛化性能。
elm 基于通用近似定理,该定理指出:
在对激活函数的温和假设下,具有包含有限数量神经元的单个隐藏层的前馈网络可以逼近 R^n 的紧凑子集上的连续函数
这仅仅意味着,如果 ELMs 具有足够的隐藏神经元和训练数据来学习所有隐藏神经元,则 ELMs 可以以显著的准确度解决分类和回归任务。
为了理解 ELM 是如何工作的,让我向您展示一个插图和构建模型的步骤。

作者的极限学习机插图
因此,鉴于以下情况:
- 训练集

- 隐藏节点输出函数 H ( w , b , x )
- 隐藏节点数 L
我们可以通过三个简单的步骤来实现 ELM:
- 随机分配隐藏节点 ( w , b ) 的参数
- 计算隐藏层输出矩阵 H
- 计算输出权重 β
现在,让我们进入编程部分。我希望你知道如何用 python 编程,并且熟悉已经在机器学习中使用的包,例如 scikit-learn、numpy 和 pandas。

MNIST 手写数字数据集由 stathwang 在 GitHub 上
我们将使用 MNIST 数据集训练网络来分类手写数字。
首先,我们需要导入必要的包来构建模型。
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import OneHotEncoder
from sklearn.preprocessing import MinMaxScaler
接下来,我们需要加载数据集来训练网络和测试模型。
train = pd.read_csv('mnist_train.csv')
test = pd.read_csv('mnist_test.csv')
作为一种预处理技术,我们将使用 scikit-learn 包中的 MinMaxScaler 和 OneHotEncoder 在(0,1)的范围内归一化我们的特征,并将我们的目标转换为 one-hot 编码格式。
onehotencoder = OneHotEncoder(categories='auto')
scaler = MinMaxScaler()X_train = scaler.fit_transform(train.values[:,1:])
y_train = onehotencoder.fit_transform(train.values[:,:1]).toarray()X_test = scaler.fit_transform(test.values[:,1:])
y_test = onehotencoder.fit_transform(test.values[:,:1]).toarray()
为了初始化我们的网络,我们需要识别以下内容:
1 .输入层的大小,即输入特征的数量
2。隐藏神经元的数量
3。隐藏权重
4 的输入。隐藏层激活功能
输入图层的大小是指数据集输入要素的数量。
input_size = X_train.shape[1]
让我们将隐藏神经元的数量初始化为 1000。
hidden_size = 1000
接下来,我们需要从高斯分布中随机初始化我们的输入权重和偏差。
input_weights = np.random.normal(size=[input_size,hidden_size])
biases = np.random.normal(size=[hidden_size])
我们将使用一个整流线性单元(ReLU) 作为我们的隐藏层激活函数。
注意:您可以使用不同的激活功能。
def relu(x):
return np.maximum(x, 0, x)
我们完成了网络初始化!
接下来要做的是创建一个函数来计算输出权重,这就是我们的 β 。目标是使用范数最小二乘解最小化目标(训练标签)和输出(预测标签)之间的最小二乘误差:


其中 H (匕首)是矩阵 H , T 是我们的目标。
我们的 H 这里是我们网络的隐藏层。让我们创建一个函数来计算我们的 H 向量。
def hidden_nodes(X):
G = np.dot(X, input_weights)
G = G + biases
H = relu(G)
return H
现在,我们只用一行代码就可以用 python 计算出我们的 β 。让我们将输出矩阵分配给一个变量名 output_weights 。
output_weights = np.dot(pinv2(hidden_nodes(X_train)), y_train)
代码使用函数 pinv 计算的 Moore-Penrose 伪逆,我们得到【dagger】和 T 的点积。结果是计算出的 β (隐藏为输出权重)。**
最后,我们有了一个模型。我们没有应用任何技术来调整我们的权重,我们只是简单地计算它们。
为了确保我们的模型产生一个好的结果,我们必须首先测试它。让我们创建一个函数来处理测试。
**def predict(X):
out = hidden_nodes(X)
out = np.dot(out, output_weights)
return out**
我们已经可以开始预测了。为此,让我们编写以下代码:
**prediction = predict(X_test)
correct = 0
total = X_test.shape[0for i in range(total):
predicted = np.argmax(prediction[i])
actual = np.argmax(y_test[i])
correct += 1 if predicted == actual else 0
accuracy = correct/total
print('Accuracy for ', hidden_size, ' hidden nodes: ', accuracy)**
模型的精度是 0.9439,考虑到我们只有一个具有 1000 个隐藏节点的隐藏层,以及用于学习的非迭代调整,这是一个很好的结果,使得它比任何基于梯度的技术都快。

每增加一个隐藏节点的精度
参考上图,当将隐藏节点的数量扩展到 1000 ( 0.9439 到 0.977) )时,ELM 的精度显著提高。这意味着,只要我们设置了正确的网络隐藏节点数,ELM 就能更好地进行归纳。
这个实现的 jupyter 笔记本可以在下面我的 GitHub 教程库中找到。
在 GitHub 上创建一个帐户,为 glenngara/tutorials 开发做出贡献。
github.com](https://github.com/glenngara/tutorials)
R 引用
[1]光,,秦,,萧启庆,极限学习机:理论与应用 (2006),神经计算
[2]光,极限学习机,南洋理工大学
[3]光,,秦,,萧启庆,极限学习机:前馈神经网络的一种新的学习方案 (2004),IEEE 国际神经网络联合会议**
构建一个 ML 产品——要避免的 4 个错误
人工智能笔记
这是我多年来学习的构建机器学习产品的综合课程。

近年来,我在不同的角色和职责下与几个机器学习或 ML 初创公司合作,如工程师、团队领导、顾问和顾问。我发现了四个在工程师和高管中非常常见的错误。在这篇文章中,我描述了构建 ML 产品的 4 个常见错误,并给出了一些可穿戴技术公司的例子。
有一次,我在一家可穿戴技术公司领导机器智能团队。该公司制造了一种手势控制臂带,让用户使用手势控制他们的环境。我们开发了一个手势识别引擎,它将肌肉信号作为输入,并识别手势。
我们必须构建和评估大量的 ML 模型来构建行业级的 ML 产品。因此,我们建立了一个管道,适当地管理构建 ML 产品所需的所有开发步骤,包括数据收集、模型训练、模型评估或模型选择。
我们成功地将一款 ML 产品运送给了全球超过 10 万名用户。除非我们在 ML 产品的开发中实施了最佳实践,否则我们无法做到这一点。
[## 人工智能:非正统的教训:如何获得洞察力和建立创新的解决方案
人工智能:非正统的教训:如何获得洞察力和建立创新的解决方案
在这里,我分享了构建 ML 产品的 4 个潜在错误,以及一些解决它们的建议。我发现这些错误在我后来工作过的许多其他团队中很常见。
—单一端到端模型很棒,但可能不存在。
构建 ML 产品的一个常见错误是坚持构建一个单一的端到端模型来解决所有场景。一个 ML 产品几乎不能通过一个 ML 模型来运输。原因之一是用例比你通常预期的有更多的差异。
错误一——从早期开始,我坚持构建一个单一的端到端 ML 模型,并通过该模型处理所有用例。
在早期,我们的目标是为全世界 70 亿人建立一个手势识别模型。你可以猜猜。它不像我们计划的那样有效。因此,我们很快开始研究原始肌肉信号,以获得更好的见解。
我们发现,我们对每个手势的预期模式或特征在用户中并不一致。换句话说,我们发现个体之间的差异比我们早期认为的要多,单一的 ML 模型可能并不适用于所有人。例如,我们发现个人有不同的肌肉解剖,皮肤导电性,排汗率,前臂周长和手势风格。但是替代方案是什么呢?
例如,我们可以根据他们的前臂周长将他们分成相似的组,并为每个组建立一个特定的模型。这种方法可以显著提高模型性能。然而,它不能创造我们想要的用户体验。然后,我们采取了另一种方法。我们决定只为我们的用户创建两个选项:公司使用我们的训练数据集构建的“人口模型”和用户通过自己的数据构建的“个性化模型”。
—盲目收集的测试数据集可能会非常误导人。
您必须在每次发布之前彻底评估 ML 模型的性能。因此,在流程中尽快收集有效的测试数据集非常重要。另一方面,有效的测试数据集必须是用户数据的真实表示。然而,你还不够了解你的用户;尤其是在早期。所以,你不知道你的产品如何被使用,在哪里被使用,或者被谁使用。因此,您必须始终怀疑您的测试数据集是否能够真正代表用户数据。
错误二——我没有时间仔细设计数据收集协议。我只会把时间花在训练一个复杂的模型上。
我们的分析表明,诸如“前臂周长”或“皮肤状况”等参数会显著影响模型的性能。我们可以测量个体的前臂周长,但是很难测量他们的皮肤状况。因此,我们充分收集了前臂周长的正态分布数据,但我们不能对皮肤状况进行同样的收集。请注意,我们使用电导率仪为一小部分用户测量皮肤状况以进行分析,仅此而已。
无论如何,我们不知道我们的用户前臂周长或皮肤状况的分布。如果我们有大量的用户,我们可以假设它一定是正态分布。但是,我们当时没有那么多用户。所以,我们确信分布绝对是偏斜的。这意味着我们可以猜测一个新版本如何影响用户体验。由于我们不能 100%确定发布的质量,我们必须有一个应急计划。
—标准的性能指标并不总是足够的。
你可以简单地用准确度、精确度和召回率等标准指标来评估一个学术性的 2 类机器学习问题。然而,你不能那么容易地评估一个 ML 产品。例如,一个 ML 产品通常是一个具有特定问题配置的多类问题,每个配置都给评估框架带来一些复杂性。构建 ML 产品的一个常见错误是用标准的性能指标来评估 ML 产品。
错误三——我不需要特定于问题的指标。我可以使用标准指标来评估 ML 产品。
我们设计了一个 ML 模型来识别 5 种手势,即左、右、拳、展开和打响指。我们用 3 个标准参数,即准确度、精确度和召回率来评估每一类中 ML 模型的性能。因此,我们需要考虑 15 个(3×5)性能指标。这 15 个参数并不同等重要。例如,Fist 或 Snap 类中的误报对用例 a 中的用户体验有不同的后果。此外,用例也有它们自己的差异。简而言之,考虑到所有的复杂性,我们必须创建特定于问题的度量标准,以确保发布新的 ML 模型。
—更多的数据并不能保证更好的结果。
“如果我们收集更多的数据,我们的模型会变得更好。对不对?”我相信你听过这句话很多次了。但事实是,模型性能并不一定会因为输入更多数据而提高。这就是为什么为了将来的目的,您必须将模型和它们的性能报告一起存档在一个库中。例如,您可能希望检索它们以进行比较分析或在生产中部署它们。
为了构建 ML 产品,您必须频繁地构建 ML 模型,而模型性能并不一定在每次构建中都得到持续的提高。因此,您必须将模型与其重要的元数据(如性能指标和超参数)一起存储。这有助于您在需要时对结果进行更深入的分析。您还必须将训练和测试数据存储在模型旁边,以确保在需要时可以重复前面的实验。
您可以在云存储解决方案(如亚马逊 S3)、通用工件管理解决方案(如 JFrog )或持续集成解决方案(如 CircleCI )提供的隔间中构建这个模型库。最佳实践是使用工件管理解决方案,它创建了对存储的 ML 模型列表的更好的访问。请注意,您可能希望使用性能查询来搜索这个集合。如果模型存储在基于文件的存储中,比如亚马逊 S3,就不能这样做。
错误四——我不需要存档 ML 模型。如果我们收集更多的数据,我们的模型会变得更好。我为什么要花时间创建基础架构?
想象一下,你是一家公司机器智能主管。在过去的几个月里,你努力设计了一个包含一系列需求的 ML 模型。截止日期到了,出乎意料地,你被告知公司需要一个有不同要求的 ML 模型。你没有时间再次做所有的训练和测试。您必须做的是在模型库上运行一个查询,并提取一个与新需求性能最接近的模型。如果你没有准备好这个库,你能恰当地应对这种情况吗?
外卖食品
- 如果单一的 ML 模型不起作用,有一个替代策略
- 确保测试数据是用户数据的真实代表
- 使用特定于问题的指标来评估端到端性能
- 构建一个 ML 模型库,并用有用的元数据标记它们
感谢阅读!
如果你喜欢这个帖子,想支持我…
[## 通过我的推荐链接加入 Medium—Pedram Ataee 博士
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
pedram-ataee.medium.com](https://pedram-ataee.medium.com/membership)
用 3 行代码用 BERT 构建一个开放领域的问答系统
拥抱脸变形金刚的端到端问答

来源: Pexels
开放领域问答(QA) 系统接受自然语言问题作为输入,并从大型文本语料库(如维基百科)中的内容返回准确的答案。这与标准搜索引擎非常不同,标准搜索引擎只是返回与搜索查询中的关键字匹配的文档。
为实际应用构建这样的系统在历史上是相当具有挑战性和复杂的。本文试图使这样的系统更容易实现和开发。在本教程中,我们将仅用 3 行代码构建一个全功能、端到端的开放领域 QA 系统。为了实现这一点,我们将使用 ktrain ,这是一个 Python 库和 TensorFlow 包装器,使深度学习和 AI 更容易访问和应用。ktrain 是免费的,开源的,这里有的。
这里的基本思想是将涵盖许多不同主题的文档集视为一种知识库,我们可以向其提交问题并获得准确的答案。在本文中,我们将使用 20 个新闻组数据集作为知识库。作为包含大量观点、辩论和争论的新闻组帖子的集合,语料库远非理想的知识库。通常最好使用基于事实的文档,如维基百科文章,甚至新闻文章。然而, 20 个新闻组数据集对于这个例子来说已经足够了,因为它提供了一个有趣且易于尝试的案例研究。它还强调了这样一个事实,即问答系统可以从任何文档集合中获得洞察力。
让我们首先使用 scikit-learn 将数据集加载到一个名为docs的数组中,并导入一些 ktrain 模块。

步骤 1:创建搜索索引
有了数据集,我们首先需要创建一个搜索索引。搜索索引将允许我们快速方便地检索包含问题中出现的单词的文档。这样的文档很可能包含答案,并且可以被进一步分析以提取候选答案。我们将首先初始化搜索索引,然后将 Python 列表中的文档添加到索引中。由于新闻组的帖子很小,可以放在主内存中,我们将把commit_every设置为一个大的值,以加快索引过程。这意味着直到最后才会写出结果。如果您遇到问题,可以尝试降低该值。

对于太大而无法加载到 Python 列表中的文档集,您可以使用SimpleQA.index_from_folder,它将抓取一个文件夹并索引所有找到的纯文本文档。
步骤 2:创建一个 QA 实例
接下来,我们将创建一个 QA 实例,它主要是来自优秀的变形金刚库的预训练BertForQuestionAnswering模型的包装器。

就是这样!在大约 3 行代码中,我们构建了一个端到端的问答系统,可以随时接收问题。
提问!
我们将调用qa.ask方法向我们索引的文本语料库发出问题并检索答案。ask方法执行以下步骤:
- 使用搜索索引查找问题中包含单词的文档
- 从这些文档中提取段落用作上下文,并使用在小队数据集上预先训练的 BERT 模型解析出候选答案
- 根据可信度分数对候选答案进行排序和删减,并返回结果
我们还将使用qa.display方法在我们的 Jupyter 笔记本中很好地格式化和显示前 5 个结果。由于模型正在对段落和句子进行梳理以寻找答案,因此可能需要一些时间来返回结果。
还要注意的是, 20 新闻组数据集涵盖了 20 世纪 90 年代早期到中期的事件,因此不存在对近期事件的引用。然而,数据集涵盖了许多不同的领域类别。例如,有 sci.space 类别涵盖了有关太空的主题。先说一个空间问题!
太空问题:
卡西尼号探测器是什么时候发射的?

如你所见,第一个候选答案表明卡西尼太空探测器于 1997 年 10 月发射,看起来是正确的。其上下文中的特定答案在列上下文下以红色突出显示。请注意,正确答案不会总是最佳答案,但在这种情况下是这样的。
因为我们使用了index_from_list来索引文档,所以最后一列(由answers字典中的reference字段填充)显示了与包含答案的新闻组帖子相关的列表索引。此reference字段可用于细读包含有print(docs[59])答案的整个文档。如果使用index_from_folder来索引文档,那么reference字段将被替换为文档的相对文件路径。
20 个新闻组数据集也包含许多讨论和辩论基督教的帖子。让我们问一个关于这个主题的问题。
宗教问题:
耶稣基督是谁?

在这里,我们看到不同的观点对耶稣基督,因为辩论和讨论,在这个文件集。
最后, 20 新闻组数据集还包含几个关于计算主题的新闻组类别,如计算机图形和 PC 硬件和软件。让我们问一个技术支持问题。
技术支持问题:
什么原因导致电脑图像太暗?

从候选答案来看,缺乏伽马校正的似乎至少是报告问题的原因之一。
关于部署质量保证系统的说明
要部署这个系统,唯一需要持久化的状态是我们在步骤 1 中初始化并填充的搜索索引。一旦搜索索引被初始化和填充,人们可以简单地从步骤 2 开始在生产环境中使用 QA 系统。
本文的源代码
本文的源代码有两种形式:
- GitHub repo 上提供的 Jupyter 笔记本
- 谷歌 Colab 笔记本此处有售
您可以在自己的文档集中随意试用一下 ktrain QA 模块。要了解更多信息,请访问我们的 GitHub 知识库:
用 Rust 和零成本在周末建立一个短信提醒系统
周末建设和学习。
加拿大安大略省新冠肺炎新病例短信提醒
在我们开始这个周末的构建和学习之前,我想花点时间感谢我所有的读者,他们总是支持我,给我提供一些建议和指导。

亲教会媒体在 Unsplash 上拍摄的照片
你是我继续这段旅程最重要的动力。如果你喜欢我的周末构建和学习系列,请在 Medium 上关注我。
声明:我在媒体上写的文章仅与我的学习和观点相关。不会代表或…
medium.com。](https://medium.com/@jayhuang75)
用例
新冠肺炎改变了我们的许多日常生活;有了新常态,我们思考和做事都不一样了。
每天,我的妻子和儿子都试图从互联网上获得加拿大安大略省新冠肺炎净新增病例增长的最新情况,这已经成为他们的日常生活。
这一周,我儿子忙于他的学校作业。所以他错过了他的例行公事。当我妻子问他这个数字时,他突然意识到他忘记了这个重要的日常活动。当他冲到电脑前开始搜索号码时,他的一句话引起了我的注意。
如果能得到一些关于这些每日号码的推送通知,那就太棒了!
“对!你给了我一个新的想法,为我的下个周末,建立和学习系列。谢谢你,儿子。”
这个想法总是来自我们的日常生活。

非功能性需求
在把手放在键盘上之前,让我们看看我们想要构建什么,这是重要的一步。
- 拉斯特·朗。
- 性价比高。
- 对于推送通知,让我们使用 SMS 作为初始用例,Twilio 提供了一些开箱即用的功能。最重要的是,还有免费订阅。
- 能够扩展到不同的用例,比如电子邮件通知,甚至进一步的聊天机器人实现——设计模式。(依赖倒置原则和开放/封闭原则)
- 及时调度程序— Cron 作业。
- 易于构建和部署——我最喜欢的 Heroku。
- 准确的数据来源——加拿大政府网站提供了一些公开可信的数据来源。
[## 加拿大新冠肺炎病例流行病学总结 Canada.ca
更新:将鼠标悬停在各省和地区上以查看总案例数、活动案例数、已恢复案例数、人数…
health-infobase.canada.ca](https://health-infobase.canada.ca/covid-19/epidemiological-summary-covid-19-cases.html)
架构和数据流
经过一些第一手的分析:
- 网站上提供的数据是 CSV 文件。
- 数据将在美国东部时间每天下午 7 点更新。有时会有一个小时的延迟。
- 该模式涵盖了我们需要的所有内容,如日期、每个省的新病例总数等。为简单起见,我们只关注整个新病例数和唯一死亡总数。
- 当我们完成处理后,我们需要清理 tmp 文件。减少不必要的空间和运营开销。

简单的数据流——作者截图
让我们开始编码部分。
手放在键盘上。

代码结构—作者截图
代码结构
该应用程序中的关键业务逻辑有 3 个主要部分:
- 下载,基于 HTTP 请求以获取 csv 文件并返回文件路径以供将来处理。
- Process — MapReduce ,只针对安大略省的数字,似乎这就是我儿子想要的:),这很容易扩展到不同的用例,如保存到数据库,或生产者到近实时,流等。
- 警报组件,因为我们希望它可以基于打开/关闭原则进行扩展,打开扩展新的用例,但是,关闭对当前实现的修改。
此外,Procfile 是 Heroku 调度实现。
实际下载
用 MapReduce 进行防锈处理
警报组件
对于 alert 组件,我们将使用 Rust 特征,它模拟 Golang 接口实现。它的好处:我们可以选择一个特定的用例实现,比如 SMS、Email 或 chatbot,而一般的抽象工作流保持不变。(依赖倒置原则和开放/封闭原则)
摘要报告和生产者
关闭 SMS 实施发送到 Twilio API
下一次我们需要添加电子邮件用例时,我们只在 alert 文件夹中创建 email.rs ,而不在 alert 组件中创建 underline mod.rs。
决赛成绩

作业执行日志—按作者划分的屏幕截图
部署和 Cron 作业设置
对于我个人的项目,我通常使用 Heroku 进行部署;一个重要的方面是定价模式、规模和使用量。
我们还可以构建容器来部署到大多数云容器提供商,如 AKS、AWS 和 GKE。我写过一些关于这个话题的文章。
[## 使用 Rust 处理 14 GB 文件—第 3 部分— Azure 堆栈
周末编码和写作
medium.com](https://medium.com/dev-genius/processing-14-gb-files-with-rust-part-3-azure-stacks-13dcf9dde014)
然而,最终总是要做出“制造还是购买”的决定。对于一个构建者来说,我真的很喜欢在 Heroku 上开始开发、部署和设置 DevOps 功能是多么容易。
Heroku,所有必要的插件都是现成的,比如 build pack,cron jobs 的设置大多简单明了。
[## Heroku 发展中心
了解如何在 Heroku 上构建、部署和管理您的应用。
devcenter.heroku.com](https://devcenter.heroku.com/)
Heroku 中的 CRON 任务非常容易设置。在 Procfile 中简单添加

CRON 作业设置—按作者分类的屏幕截图
并根据需要进入 Heroku UI 配置您的调度程序。

设置用户界面-按作者截图
决赛成绩
最后,为了儿子,每天晚上八点半,短信到了。我还为 Heroku 和 Twilio 服务使用了免费层,因此总成本为 0 美元。

短信-作者截图
结束语
- 建筑创意通常来源于现实生活。享受它,倾听它,感受它。
- 当你建造的时候,你需要考虑规模。考虑为您的用例获得最大的好处;这又回到了我们的日常工作中。降低信息技术基础设施成本不是好事;这是必须要有的。你如何建造它的基础。一个很好的例子是为什么我总是跟踪容器构建大小,这是您的运行时足迹的最重要指标,它将影响您的云运行时成本。等等。
- 正确编码,规模编码,低成本编码。
这就是这周的内容。顺便说一句,我儿子对我做的东西非常兴奋。现在我们将一起开始编写 python 代码。
再次感谢你花时间阅读我的周末建设和学习。下次见。
请看我下面的其他文章,了解更多你可能感兴趣的周末建设和学习。
声明:我在媒体上写的文章仅与我的学习和观点相关。不会代表或…
medium.com。](https://medium.com/@jayhuang75)
使用 PyCaret 和 Streamlit 构建和部署机器学习 web 应用程序
在 Heroku PaaS 上部署机器学习应用程序的初学者指南

概述
在我们关于在云中部署机器学习管道的上一篇文章中,我们演示了如何在 PyCaret 中开发机器学习管道,用 Docker 封装 Flask 应用程序,以及使用 AWS Fargate 部署无服务器。如果你以前没有听说过 PyCaret,你可以阅读这个公告来了解更多。
在本教程中,我们将使用 PyCaret 训练一个机器学习管道,并使用 Streamlit 开源框架创建一个 web 应用。这个 web 应用程序将是一个简单的界面,供业务用户使用训练有素的机器学习管道在新的数据集上生成预测。
本教程结束时,您将能够构建一个功能完整的 web 应用程序,使用经过训练的机器学习模型来生成在线预测(逐个)和批量预测(通过上传 csv 文件)。最终的应用程序如下所示:

https://pycaret-streamlit.herokuapp.com
👉您将在本教程中学到什么
- 什么是部署,我们为什么要部署机器学习模型?
- 开发一个机器学习管道,用 PyCaret 训练模型。
- 使用 Streamlit 开源框架构建一个简单的 web 应用。
- 在“Heroku”上部署一个 web 应用程序,并查看运行中的模型。
本教程将涵盖整个工作流程,从训练机器学习模型和开发 Python 中的管道开始,使用 streamlit 开发简单的 web 应用程序,并在 Heroku 云平台上部署应用程序。
过去,我们讨论过使用 docker 的容器化以及在 Azure、GCP 和 AWS 等云平台上的部署。如果你有兴趣了解更多,你可以阅读下面的故事:
- 在 AWS Fargate 上部署机器学习管道
- 在 Google Kubernetes 引擎上部署机器学习管道
- 在 AWS Web 服务上部署机器学习管道
- 在 Heroku PaaS 上构建和部署您的第一个机器学习 web 应用
💻本教程的工具箱
PyCaret
PyCaret 是 Python 中的一个开源、低代码机器学习库,用于训练和部署机器学习管道和模型到生产中。PyCaret 可以使用 pip 轻松安装。
pip install **pycaret**
细流
Streamlit 是一个开源的 Python 库,可以轻松地为机器学习和数据科学构建漂亮的定制 web 应用。使用 pip 可以轻松安装 Streamlit。
pip install **streamlit**
开源代码库
GitHub 是一个基于云的服务,用于托管、管理和控制代码。假设你在一个大型团队中工作,团队中有很多人(有时有数百人)在做改变。PyCaret 本身就是一个开源项目的例子,在这个项目中,数百名社区开发人员不断地贡献源代码。如果你以前没有用过 GitHub,你可以注册免费账号。
赫罗库
Heroku 是一个平台即服务(PaaS ),支持基于托管容器系统部署 web 应用,具有集成的数据服务和强大的生态系统。简而言之,这将允许您将应用程序从本地机器带到云中,这样任何人都可以使用 Web URL 访问它。在本教程中,我们选择了 Heroku 进行部署,因为当您注册新帐户时,它会提供免费资源。

机器学习工作流程(从培训到 PaaS 部署)
✔️Let's 开始吧…..
为什么要部署机器学习模型?
机器学习模型的部署是将模型投入生产的过程,以便 web 应用程序、企业软件和 API 可以使用经过训练的模型,并使用新的数据点生成预测。
通常构建机器学习模型,以便它们可以用于预测结果(二进制值,即用于分类的 1 或 0,用于回归的连续值,用于聚类的标签等)。预测新数据点有两种主要方法:
👉在线预测
在线预测场景适用于您希望为每个数据点逐个生成预测的情况。例如,您可以使用预测来立即决定某个特定交易是否可能是欺诈性的。
👉批量预测
当您想要一次为一组观测值生成预测时,批量预测非常有用。例如,如果您想决定将哪些客户作为产品广告活动的目标,您将获得所有客户的预测分数,对这些分数进行排序以确定哪些客户最有可能购买,然后将最有可能购买的前 5%客户作为目标。
在本教程中,我们将建立一个应用程序,可以做到这两个;通过上传包含新数据点的 csv 文件进行在线预测和批量预测。
设置业务环境
一家保险公司希望通过使用住院时的人口统计和基本患者健康风险指标来更好地预测患者费用,从而改善其现金流预测。

( )数据来源 )
目标
使用训练有素的机器学习模型和管道,构建支持在线(逐个)以及批量预测的 web 应用程序。
任务
- 使用 PyCaret 训练、验证和开发机器学习管道。
- 构建一个前端 web 应用程序,具有两个功能:(一)在线预测和(二)批量预测。
- 在 Heroku 上部署 web 应用程序。一旦部署,它将成为公开可用的,并可以通过网址访问。
👉任务 1 —模型训练和验证
培训和模型验证是在集成开发环境(IDE)或笔记本电脑中进行的,可以在本地机器上进行,也可以在云上进行。如果您以前没有使用过 PyCaret,单击此处了解更多关于 PyCaret 的信息,或者在我们的网站上查看入门教程。
在本教程中,我们进行了两个实验。第一个实验是使用 PyCaret 中的默认预处理设置进行的。第二个实验有一些额外的预处理任务,如缩放和归一化、自动特征工程和宁滨连续数据到区间。参见第二个实验的设置代码:
**# Experiment No. 2**from **pycaret.regression** import *****r2 = **setup**(data, target = 'charges', session_id = 123,
normalize = True,
polynomial_features = True, trigonometry_features = True,
feature_interaction=True,
bin_numeric_features= ['age', 'bmi'])

两个实验的信息网格比较
神奇的事情只发生在几行代码中。请注意,在实验 2 中,转换后的数据集有 62 个用于训练的特征,这些特征仅来自原始数据集中的 6 个特征。所有的新特性都是 PyCaret 中的转换和自动特性工程的结果。

转换后数据集中的列
PyCaret 中模型定型的示例代码:
# Model Training and Validation
lr = **create_model**('lr')

线性回归模型的 10 倍交叉验证
注意转换和自动特征工程的影响。R2 不费吹灰之力就增加了 10%。我们可以比较两个实验的线性回归模型的残差图,并观察转换和特征工程对模型的异方差的影响。
# plot residuals of trained model **plot_model**(lr, plot = 'residuals')

线性回归模型的残差图
机器学习是一个迭代的过程。迭代的次数和其中使用的技术取决于任务的关键程度,以及预测错误时的影响。在医院的 ICU 中实时预测患者结果的机器学习模型的严重性和影响远远超过为预测客户流失而建立的模型。
在本教程中,我们只执行了两次迭代,第二次实验中的线性回归模型将用于部署。然而,在这个阶段,模型仍然只是笔记本/ IDE 中的一个对象。要将其保存为可以传输到其他应用程序并由其他应用程序使用的文件,请执行以下代码:
# save transformation pipeline and model
**save_model**(lr, model_name = 'deployment_28042020')
当您在 PyCaret 中保存一个模型时,基于在 setup() 函数中定义的配置的整个转换管道被创建。所有的相互依赖都是自动编排的。查看存储在“deployment_28042020”变量中的管道和模型:

使用 PyCaret 创建的管道
我们已经完成了培训和模型选择。最终的机器学习管道和线性回归模型现在保存为 pickle 文件(deployment_28042020.pkl ),该文件将在 web 应用程序中用于生成对新数据点的预测。
👉任务 2 —构建 Web 应用程序
现在我们的机器学习管道和模型已经准备好了,我们将开始构建一个前端 web 应用程序,它可以在新的数据点上生成预测。该应用程序将通过 csv 文件上传支持“在线”以及“批量”预测。让我们将应用程序代码分成三个主要部分:
标题/布局
该部分导入库,加载训练模型,并创建一个基本布局,顶部有一个徽标,一个 jpg 图像,边栏上有一个下拉菜单,用于在“在线”和“批量”预测之间切换。

app.py —代码片段第 1 部分
在线预测
本节介绍应用程序的第一个功能,即在线(逐个)预测。我们使用 streamlit 小部件,如数字输入、文本输入、下拉菜单和复选框来收集用于训练模型的数据点,如年龄、性别、身体质量指数、儿童、吸烟者、地区。

app.py —代码片段第 2 部分
批量预测
这部分处理第二个功能,即批量预测。我们已经使用 streamlit 的 file_uploader 小部件上传了一个 csv 文件,然后从 PyCaret 调用原生的 predict_model() 函数来生成使用 streamlit 的 write()函数显示的预测。

app.py —代码片段第 3 部分
如果您还记得上面的任务 1,我们最终确定了一个线性回归模型,该模型使用 6 个原始特征提取了 62 个特征。然而,我们的 web 应用程序的前端有一个输入表单,只收集六个特征,即年龄、性别、bmi、儿童、吸烟者、地区。
我们如何将新数据点的 6 个特征转换成用于训练模型的 62 个特征?我们不需要担心这一部分,因为 PyCaret 通过编排转换管道自动处理这一部分。当您在使用 PyCaret 定型的模型上调用 predict 函数时,在从定型模型生成预测之前,会自动(按顺序)应用所有转换。
在 Heroku 上发布应用程序之前的最后一步是在本地测试 web 应用程序。打开 Anaconda 提示符,导航到您的项目文件夹并执行以下代码:
**streamlit** run app.py

简化应用测试—在线预测

简化应用测试—批量预测
👉任务 3 —在 Heroku 上部署 Web 应用程序
既然模型已经训练好了,机器学习管道已经准备好了,应用程序也已经在我们的本地机器上测试过了,我们就可以开始在 Heroku 上部署了。有几种方法可以将你的应用程序源代码上传到 Heroku 上。最简单的方法是将 GitHub 库链接到您的 Heroku 帐户。
如果你愿意跟随,你可以从 GitHub 中派生出这个库。如果你不知道怎么叉一个回购,请看这个官方 GitHub 教程。

https://www.github.com/pycaret/pycaret-deployment-streamlit
到目前为止,您已经熟悉了存储库中的所有文件,除了三个文件:“requirements.txt”、“setup.sh”和“Procfile”。让我们看看这些是什么:
requirements.txt
requirements.txt 文件是一个文本文件,包含执行应用程序所需的 python 包的名称。如果这些软件包没有安装在应用程序运行的环境中,它将会失败。

requirements.txt
setup.sh
setup.sh 是为 bash 编写的脚本。它包含用 Bash 语言编写的指令,类似 requirements.txt,它用于为我们的 streamlit 应用程序在云上运行创建必要的环境。

setup.sh
Procfile
Procfile 只是一行代码,它向 web 服务器提供启动指令,指示当应用程序被触发时应该执行哪个文件。在本例中,“Procfile”用于执行 setup.sh ,这将为 streamlit 应用程序创建必要的环境,第二部分“streamlit run app.py”用于执行应用程序(这类似于您在本地计算机上执行 streamlit 应用程序的方式)。

Procfile
一旦所有文件都上传到 GitHub 存储库,我们现在就可以开始在 Heroku 上部署了。请遵循以下步骤:
第一步——在 heroku.com 上注册,点击“创建新应用”

Heroku 仪表板
步骤 2 —输入应用名称和地区

Heroku —创建新应用程序
步骤 3 —连接到您的 GitHub 库

Heroku —连接到 GitHub
步骤 4 —部署分支

Heroku —部署分支
第 5 步—等待 10 分钟,然后爆炸
App 发布到网址:https://pycaret-streamlit.herokuapp.com/

https://pycaret-streamlit.herokuapp.com/
PyCaret 2.0.0 来了!
我们收到了来自社区的大力支持和反馈。我们正在积极改进 PyCaret,并准备我们的下一个版本。 PyCaret 2.0.0 会更大更好。如果您想分享您的反馈并帮助我们进一步改进,您可以在网站上填写此表格,或者在我们的 GitHub 或 LinkedIn 页面上发表评论。
关注我们的 LinkedIn ,订阅我们的 YouTube 频道,了解更多关于 PyCaret 的信息。
想了解某个特定模块?
从第一个版本 1.0.0 开始,PyCaret 有以下模块可供使用。点击下面的链接,查看 Python 中的文档和工作示例。
另请参见:
笔记本中的 PyCaret 入门教程:
你愿意投稿吗?
PyCaret 是一个开源项目。欢迎每个人都来投稿。如果您愿意投稿,请随时关注未决问题。dev-1.0.1 分支上的单元测试接受拉请求。
如果你喜欢 PyCaret,请给我们 GitHub 回购的⭐️。
中:https://medium.com/@moez_62905/
领英:https://www.linkedin.com/in/profile-moez/
推特:【https://twitter.com/moezpycaretorg1 T43
通过堆叠库来构建和部署简单的 ML 工具

在线课程非常适合学习数据科学和机器学习的概念。但最终,人们总是想知道数据分析师或数据科学家的角色是否仅仅是通过编写代码来回答问题🤷♂️.
让我们想象下面的讨论:
本:嘿,我们营销团队想知道下个月投资产品 A 广告的最佳时间是什么时候。有可能预测未来的谷歌搜索趋势吗?
嗯,我想我可以在谷歌趋势上看看趋势是如何随着时间演变的。我们应该能够应用一些预测方法来了解下个月的搜索情况。
本:那太好了!
你 : 好的,我要从一些关键词中导出谷歌趋势数据。然后我会编写一个小模型,然后把预测图发给你。
本(第二天):谢谢你的报告,我们改变了一点想法,你能为 B 产品做同样的事情吗?
你好,当然可以。
Ben (2 小时后):最后,我们想看看整个季度的预测,看看再等一会儿是否更明智。
你 : Mmmh 是…
本 (2 小时后):还有,有没有可能在接下来的 6 个月里比较 C 和 D?
你:😓
你知道我的意思…
允许其他人使用、交互和修改模型,而无需进入代码,这使得事情对每个人来说都更有趣。
在本教程中,我们将看到用非常简单的工具构建这个趋势预测应用的不同步骤。最后,它会看起来像这个:
让我们看看它会是什么样子🙄
教程中包含了所有的代码和 GitHub repo。
在更复杂的问题上,当然会更困难,但思维是相同的:通过数据将信息直接带到需要的地方。
步骤#0:环境设置
在一头扎进去之前要做的第一件事就是准备好你的工作环境。
虚拟环境
在这里(像在任何项目中一样),我们将使用几个包。为了完全控制你使用的工具,建议你在虚拟环境中工作。
我们将使用 Anaconda ,这是一个 Python 发行版,提供了一个名为 conda 的包管理工具。它将允许我们轻松地更新和安装我们开发所需的库。
数据科学的现代世界是极其动态的。每天都有新的挑战出现,不可思议的挑战也是如此…
www.anaconda.com](https://www.anaconda.com/)
下载最新版本的 Anaconda ,然后运行程序“Anaconda Prompt”。我们也可以使用 GUI,但我们不会在这部分花太多时间。
在 Anaconda 命令提示符下,配置一个新环境,激活它,并安装基本包。
conda create -n trends-predictor python
conda activate trends-predictor
conda install pandas numpy matplotlib
我们将继续安装其他软件包。
要轻松编辑您的代码,请选择您喜欢的 IDE,并根据您的虚拟环境的需要进行配置。为了简单起见,我将使用与 anaconda 一起安装的 Spyder。要启动它,请在命令提示符下键入spyder。
Git/GitHub
我们开始好看了!最后一件事,我们初始化我们的 git 存储库,并将其链接到 GitHub 。我把细节传到这里,网上有很多教程。
为什么用在这里?剧透:最后,我们会用 Heroku 来部署我们的应用,从 GitHub repo 来做非常简单。
从 git bash 中,键入:
echo "# trends-predictor" >> README.md
git init
git add README.md
git commit -m "first commit"
git remote add origin <https://github.com/elliottrabac/trend-predictor.git>
git push -u origin master
好了,现在一切都准备好了,该编码了。我们将分几个步骤来完成这项工作
- 自动存取数据
- 对未来做出预测
- 让每个人都能使用你的工具
步骤 1:访问数据🧲
有很多方法可以访问数据,我们可以从哪里下载 csv 格式的文件,然后将它们导入到我们的程序中。问题是非常手动…
为了自动化这一切,我们可以使用报废工具。或者直接使用查询浏览页面的 HTML 内容,或者甚至使用 Selenium 再现用户的动作。
但是我们会让它变得更好/更简单。有一个包叫“ pytrends ”,就是用 python 拉 google trends 的。
💡提示:在编码之前,一定要检查工作是否已经完成。可能已经有一个库或 GitHub repo 来完成这项工作。
首先,我们需要安装那个包。你可以在这里找到 pytrends API 的完整文档。
谷歌趋势的非官方 API 允许从谷歌趋势自动下载报告的简单界面。只有…
pypi.org](https://pypi.org/project/pytrends/)
使用pip安装软件包(在您的虚拟环境中):
pip install pytrends
拉谷歌趋势
让我们创建一个新的 python 脚本,并从导入必要的包开始:
import pandas as pd
import pytrends
from pytrends.request import TrendReq
使用pytrend非常简单,并且有很好的文档记录,所以我们将直奔主题。
你所要做的就是和谷歌(和TrendReq)建立连接,用你要找的关键词(以列表的形式)构建查询,然后应用想要的方法。这里我们希望搜索的演变显示在 Google Trends 的兴趣随时间变化部分,所以我们使用:interest_over_time()
我们将通过删除isPartial 列并重命名其他列来预测下一步(预测)。
这是一只熊猫。我们需要的数据框架。在函数中,它看起来像这样:
第二步:做预测🔮
现在是时候预测未来了!我们这里是以时间序列预测为例。
时间序列预测是使用模型根据以前观察到的值来预测未来值。—维基百科
为了预测下一个值,我们有一整套可能的工具和概念。我们可以使用统计方法,如 ARMA,AMIRA,甚至 SARIMAX 模型🤯今天,我们也发现针对这类问题的非常强大的深度学习模型,比如经典的 MLP、CNN、RNN,以及它们更高级的形式。
我们将保持它的简单和高效,我们将使用 脸书的先知 。像任何模型一样,它有它的优点和缺点;但是我们在这里不是为了讨论使用哪种算法(在线课程对此很有帮助)。
Prophet 遵循 sklearn 模型 API。我们创建一个 Prophet 类的实例,然后调用它的 fit 和 predict…
facebook.github.io](https://facebook.github.io/prophet/docs/quick_start.html)
我们从在工作环境中安装fbprophet开始:
conda install -c conda-forge fbprophet
做预测
我们将创建一个新函数make_pred(),它将数据集和预测周期的长度作为参数。
用一种非常简单的方式,我们创建一个新的Prophet()对象和fit数据集的模型。这个必须总是有两个名为ds和y的列(就像我们之前做的一样)。
我们用make_futur_dataframe()扩展包含日期的列。然后我们用predict()预测未来值,它返回一个带有预测的数据帧。
当然,你可以在这里玩一些“超参数”。所有信息一如既往地保存在文档中。
绘制预测图
但是不要忘了我们的朋友本,我们的目标是给他一个好的、易懂的图表📈。
这里我们用先知的plot()方法。而且既然一点点细节无伤大雅,我们也用plot_components()给他提供一些额外的信息。
就是这样!现在,我们有了针对所需关键字的预测图。
如果您正在使用 Spyder IDE,您可以在变量浏览器和绘图选项卡中看到您的数据帧和图形。

Spyder IDE 中的图形
第三步:在网上发送🚀
现在我们到了最精彩的部分!
您可以自己进行预测,并以报告形式发送。但是在这里,我们将允许任何人选择关键词,预测选项,所有这些都在一个 UX 友好界面中!
创建 web 应用程序
我们使用一个增长强劲的库, Streamlit (你可以在最后用趋势预测应用程序来检查它😉)
Streamlit 是一个面向机器学习和数据科学团队的开源应用框架。在…中创建漂亮的数据应用程序
www.streamlit.io](https://www.streamlit.io/)
不需要 web 开发技能,不需要用 Flask 或 Django 构建接口,一切都在一个脚本中完成,只需几行代码。
从安装库开始。
pip install streamlit
并将其导入到脚本中。
import streamlit as st
不赘述,Streamlit 一行一行的,在界面显示 Streamlit 元素。
我们首先向页面添加一个标题:
st.write("""
# Trend Predictor App :crystal_ball:
### This app predicts the **Google Trend** you want!
""")
现在我们把一些元素放在边栏中,这将允许用户选择参数。
keyword将显示为文本字段并将取内容的值,这里的默认值是"太阳镜"。pediod将在 7 到 365 天之间显示为滑块,默认值为 100。details是显示为复选框的布尔变量。
st.sidebar.write("""
## Pick a keyword and a forecasting period :dizzy:
""")keyword = st.sidebar.text_input("Keyword", "Sunglasses")
periods = st.sidebar.slider('Prediction time in days:', 7, 365, 90)
details = st.sidebar.checkbox("Show details")
要显示我们使用的图形:
st.pyplot(fig1)
if details: # if detail checkbox set to True
st.write("### Details :mag_right:")
st.pyplot(fig2)
这个库中有很多很棒的工具,这里的文档也很棒!✨:我们只是在我们的get_data()函数上面添加了一个装饰器:
@st.cache(suppress_st_warning=True)
@st.cache decorator 表示 Streamlit 将执行内部魔术,这样任何缓存的操作都将只运行一次,并被缓存以备将来使用。
我们将在页面中添加一些配置元素,包括:
st.beta_set_page_config(page_title="Trend Predictor",
page_icon=":crystal_ball",
layout='centered',
initial_sidebar_state='auto')
一点都不差!我们来看看当地是什么样子的?
为此,请在您的脚本所在的文件夹中打开一个终端,然后键入:
streamlit run trend-prediction.py
🤩🤩🤩
这是应用程序✨的完整代码
在网络上部署它
在你把链接发给本之前做最后一次努力💪。
您可以通过在 web 上部署应用程序来完成您的工作。而 Heroku 是做到这一点的完美工具!易于使用,免费,快速。
无论您是在构建简单的原型还是关键业务产品,Heroku 的全托管平台都能为您提供…
www.heroku.com](https://www.heroku.com/)
我不打算用所有的部署来延长这个教程,只需在谷歌上键入“Streamlit Heroku”。
🛑唯一要小心的是!当你要创建你的requirements.txt文件时,你需要添加一个额外的库。我们安装了预言者和康达,但是 Heroku 也需要pystan。考虑一下加进去就行了。
此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/elliottrabac/trend-predictor)
结论
在本教程中,我们已经看到了组合不同的库来处理构建过程的每一步是可能的。当然,这个项目非常“理论化”:预测是基本的,不允许根据数据集调整参数。
但这里最重要的是全局心态。这至少允许快速测试事物,验证假设,并且将事物发送给你的团队!
快乐学习!🥂外星人
关于我 👨💻:
我是一名工科学生,最大的热情是学习新事物。从事机械工程 5 年后,我通过网上可以找到的令人难以置信的资源学习了数据科学。我试着通过写几个帖子来回馈和继续学习。
请随时给我反馈或联系我讨论任何话题! ✌
构建并部署您的第一个机器学习 web 应用

使用 PyCaret 在 Python 中训练和部署机器学习管道的初学者指南
在我们的上一篇文章中,我们展示了如何使用 PyCaret 在 Power BI 中训练和部署机器学习模型。如果你以前没有听说过 PyCaret,请阅读我们的公告来快速入门。
在本教程中,我们将使用 PyCaret 开发一个机器学习管道,它将包括预处理转换和回归模型,以根据人口统计和基本的患者健康风险指标(如年龄、身体质量指数、吸烟状况等)预测患者住院费用。
👉您将在本教程中学到什么
- 什么是部署,我们为什么要部署机器学习模型。
- 开发一个机器学习管道,用 PyCaret 训练模型。
- 使用名为“Flask”的 Python 框架构建一个简单的 web 应用程序。
- 在“Heroku”上部署一个 web 应用程序,并查看您的模型的运行情况。
💻在本教程中,我们将使用哪些工具?
PyCaret
PyCaret 是 Python 中的开源、低代码机器学习库,用于在生产中训练和部署机器学习管道和模型。PyCaret 可以使用 pip 轻松安装。
# for Jupyter notebook on your local computer
pip install **pycaret**# for azure notebooks and google colab
!pip install **pycaret**
瓶
Flask 是一个允许你构建 web 应用的框架。web 应用程序可以是商业网站、博客、电子商务系统,也可以是使用训练好的模型从实时提供的数据中生成预测的应用程序。如果你没有安装 Flask,你可以使用 pip 来安装。
# install flask
pip install **Flask**
开源代码库
GitHub 是一个基于云的服务,用于托管、管理和控制代码。假设你在一个大型团队中工作,团队中有很多人(有时有数百人)在做改变。PyCaret 本身就是一个开源项目的例子,在这个项目中,数百名社区开发人员不断地贡献源代码。如果你以前没有用过 GitHub,你可以注册免费账号。
赫罗库
Heroku 是一个平台即服务(PaaS ),支持基于托管容器系统部署 web 应用,具有集成的数据服务和强大的生态系统。简而言之,这将允许您将应用程序从本地机器带到云中,这样任何人都可以使用 Web URL 访问它。在本教程中,我们选择了 Heroku 进行部署,因为当你注册新账户时,它会提供免费资源。

机器学习工作流程(从培训到 PaaS 部署)
为什么要部署机器学习模型?
机器学习模型的部署是使模型在生产中可用的过程,其中 web 应用程序、企业软件和 API 可以通过提供新的数据点和生成预测来使用经过训练的模型。
通常建立机器学习模型,以便它们可以用于预测结果(二进制值,即用于分类的 1 或 0,用于回归的连续值,用于聚类的标签等)。生成预测有两种主要方式(I)批量预测;以及(ii)实时预测。在我们的上一篇教程中,我们演示了如何在 Power BI 中部署机器学习模型并进行批量预测。在本教程中,我们将了解如何部署一个机器学习模型来进行实时预测。
商业问题
一家保险公司希望通过使用住院时的人口统计和基本患者健康风险指标来更好地预测患者费用,从而改善其现金流预测。

( 数据源 )
目标
构建一个 web 应用程序,在 web 表单中输入患者的人口统计和健康信息以预测费用。
任务
- 训练和验证模型,并开发用于部署的机器学习管道。
- 用自变量(年龄、性别、bmi、儿童、吸烟者、地区)的输入表单构建一个基本的 HTML 前端。
- 使用 Flask 框架构建 web 应用程序的后端。
- 在 Heroku 上部署 web 应用程序。一旦部署,它将成为公开可用的,并可以通过网址访问。
👉任务 1 —模型训练和验证
培训和模型验证在集成开发环境(IDE)或笔记本电脑中执行,既可以在本地机器上执行,也可以在云上执行。在本教程中,我们将使用 Jupyter Notebook 中的 PyCaret 来开发机器学习管道和训练回归模型。如果你以前没有使用过 PyCaret,点击这里了解更多关于 PyCaret 的信息,或者在我们的网站上查看入门教程。
在本教程中,我们进行了两个实验。第一个实验使用 PyCaret 中的默认预处理设置(缺失值插补、分类编码等)进行。第二个实验具有一些额外的预处理任务,例如缩放和归一化、自动特征工程和将宁滨连续数据分成区间。参见第二个实验的设置示例:
# Experiment No. 2from **pycaret.regression** import *****r2 = **setup**(data, target = 'charges', session_id = 123,
normalize = True,
polynomial_features = True, trigonometry_features = True,
feature_interaction=True,
bin_numeric_features= ['age', 'bmi'])

两个实验的信息网格比较
神奇的事情只发生在几行代码中。请注意,在实验 2 中,转换后的数据集有 62 个用于训练的特征,这些特征仅来自原始数据集中的 7 个特征。所有的新特性都是 PyCaret 中的转换和自动特性工程的结果。

转换后数据集中的列
PyCaret 中模型定型和验证的示例代码:
# Model Training and Validation
lr = **create_model**('lr')

线性回归模型的 10 倍交叉验证
注意转换和自动特征工程的影响。R2 不费吹灰之力就增加了 10%。我们可以比较两个实验的线性回归模型的残差图,并观察转换和特征工程对模型的异方差的影响。
# plot residuals of trained model **plot_model**(lr, plot = 'residuals')

线性回归模型的残差图
机器学习是一个迭代的过程。迭代次数和其中使用的技术取决于任务的关键程度以及预测错误时的影响。在医院的 ICU 中实时预测患者结果的机器学习模型的严重性和影响远远超过为预测客户流失而建立的模型。
在本教程中,我们只执行了两次迭代,第二次实验中的线性回归模型将用于部署。然而,在这个阶段,模型仍然只是笔记本中的一个对象。要将其保存为可以传输到其他应用程序并由其他应用程序使用的文件,请运行以下代码:
# save transformation pipeline and model
**save_model**(lr, model_name = 'c:/*username*/ins/deployment_28042020')
当您在 PyCaret 中保存一个模型时,基于在 setup() 函数中定义的配置的整个转换管道被创建。所有的相互依赖都是自动编排的。查看存储在“deployment_28042020”变量中的管道和模型:

使用 PyCaret 创建的管道
我们已经完成了第一项任务,即培训和选择部署模型。最终的机器学习流水线和线性回归模型现在作为文件保存在本地驱动器中的 save_model() 函数中定义的位置下。(本例中:c:/ 用户名/ins/deployment _ 28042020 . pkl)。
👉任务 2 —构建 Web 应用程序
现在我们的机器学习管道和模型已经准备好了,我们将开始构建一个 web 应用程序,可以连接到它们并实时生成对新数据的预测。该应用程序有两个部分:
- 前端(使用 HTML 设计)
- 后端(使用 Python 中的 Flask 开发)
Web 应用程序的前端
通常,web 应用程序的前端是使用 HTML 构建的,这不是本文的重点。我们使用了一个简单的 HTML 模板和一个 CSS 样式表来设计一个输入表单。下面是我们的 web 应用程序前端页面的 HTML 片段。

home.html 文件的代码片段
构建简单的应用程序不需要成为 HTML 专家。有许多免费的平台提供 HTML 和 CSS 模板,并能够通过使用拖放界面快速构建漂亮的 HTML 页面。
CSS 样式表描述了 HTML 元素在屏幕上的显示方式。这是控制应用程序布局的有效方法。样式表包含背景颜色、字体大小和颜色、边距等信息。它们在外部保存为. css 文件,并链接到 HTML,但只包含一行代码。

home.html 文件的代码片段
Web 应用程序的后端
web 应用的后端是使用 Flask 框架开发的。对于初学者来说,可以直观地将 Flask 视为一个库,可以像 Python 中的任何其他库一样导入。请参阅使用 Python 中的 Flask 框架编写的后端示例代码片段。

app.py 文件中的代码片段
如果您还记得上面的步骤 1,我们已经最终确定了线性回归模型,该模型针对 PyCaret 自动设计的 62 个功能进行了训练。然而,我们的 web 应用程序的前端有一个输入表单,只收集六个特征,即年龄、性别、bmi、儿童、吸烟者、地区。
我们如何将新数据点的 6 个特征实时转换为 62 个特征来训练模型?随着在模型训练期间应用一系列转换,编码变得越来越复杂和耗时。
在 PyCaret 中,分类编码、缩放、缺失值插补、特征工程甚至特征选择等所有转换都会在生成预测之前实时自动执行。
想象一下,在使用你的模型进行预测之前,你需要编写多少代码来严格地应用所有的转换。在实践中,当你想到机器学习时,你应该考虑整个 ML 管道,而不仅仅是模型。
测试应用 在 Heroku 上发布应用之前的最后一步是在本地测试 web 应用。打开 Anaconda 提示符并导航到您计算机上保存‘app . py’的文件夹。使用以下代码运行 python 文件:
python **app.py**

执行 app.py 时 Anaconda 提示符中的输出
执行后,将 URL 复制到浏览器中,它应该会打开本地机器(127.0.0.1)上托管的 web 应用程序。尝试输入测试值,看看预测功能是否有效。在下面的例子中,西南部一个没有孩子的 19 岁女性吸烟者的预期账单是 20,900 美元。

本地计算机上打开的 Web 应用程序
恭喜你!您现在已经构建了您的第一个机器学习应用程序。现在是时候将这个应用程序从您的本地机器带到云中,这样其他人就可以通过 Web URL 使用它了。
👉任务 3 —在 Heroku 上部署 Web 应用程序
既然模型已经训练好了,机器学习管道已经准备好了,应用程序也已经在我们的本地机器上测试过了,我们就可以开始在 Heroku 上部署了。有几种方法可以将你的应用源代码上传到 Heroku 上。最简单的方法是将 GitHub 库链接到您的 Heroku 帐户。
如果你想继续下去,你可以从 GitHub 获得这个库。如果你不知道怎么叉一个回购,请看这个官方 GitHub 教程。

https://www.github.com/pycaret/deployment-heroku
到目前为止,除了两个文件,即' requirements.txt' 和' Procfile ',您已经熟悉了上面显示的存储库中的所有文件。

requirements.txt
requirements.txt 文件是一个文本文件,包含执行应用程序所需的 python 包的名称。如果这些软件包没有安装在应用程序运行的环境中,它将失败。

Procfile
Procfile 只是一行代码,它向 web 服务器提供启动指令,指示当有人登录到应用程序时应该首先执行哪个文件。在这个例子中,我们的应用文件的名称是' app.py' ,应用程序的名称也是' app' 。(因此 app:app)
一旦所有文件都上传到 GitHub 存储库,我们现在就可以开始在 Heroku 上部署了。请遵循以下步骤:
第一步——在 heroku.com 上注册,点击“创建新应用”

Heroku 仪表板
步骤 2 —输入应用名称和地区

Heroku —创建新应用程序
步骤 3——连接到托管代码的 GitHub 库

Heroku —连接到 GitHub
步骤 4 —部署分支

Heroku —部署分支
步骤 5 —等待 5-10 分钟,然后爆炸

Heroku —成功部署
App 发布到网址:https://pycaret-insurance.herokuapp.com/

https://pycaret-insurance.herokuapp.com/
在我们结束教程之前,还有最后一件事要看。
到目前为止,我们已经构建并部署了一个与我们的机器学习管道一起工作的 web 应用程序。现在假设您已经有了一个企业应用程序,您想在其中集成来自您的模型的预测。您需要的是一个 web 服务,其中您可以使用输入数据点进行 API 调用,并获得预测结果。为了实现这一点,我们在我们的‘app . py’文件中创建了 predict_api 函数。查看代码片段:

app.py 文件的代码片段(web 应用程序的后端)
下面是如何使用请求库在 Python 中使用这个 web 服务:
import **requests**url = 'https://pycaret-insurance.herokuapp.com/predict_api'pred = **requests.post(**url,json={'age':55, 'sex':'male', 'bmi':59, 'children':1, 'smoker':'male', 'region':'northwest'})**print**(pred.json())

向已发布的 web 服务发出请求,以在笔记本中生成预测
下一个教程
在下一个部署机器学习管道的教程中,我们将更深入地使用 docker 容器部署机器学习管道。我们将演示如何在 Linux 上轻松部署和运行容器化的机器学习应用程序。
关注我们的 LinkedIn 并订阅我们的 Youtube 频道,了解更多关于 PyCaret 的信息。
重要链接
用户指南/文档
GitHub 资源库 安装 PyCaret
笔记本教程
贡献于 PyCaret
想了解某个特定模块?
从第一个版本 1.0.0 开始,PyCaret 有以下模块可供使用。点击下面的链接,查看 Python 中的文档和工作示例。
另请参见:
笔记本中的 PyCaret 入门教程:
开发管道中有什么?
我们正在积极改进 PyCaret。我们未来的开发管道包括一个新的时间序列预测模块,与 TensorFlow、的集成,以及对 PyCaret 可扩展性的重大改进。如果您想分享您的反馈并帮助我们进一步改进,您可以在网站上填写这张表格,或者在我们的 GitHub 或 LinkedIn 页面上发表评论。
你愿意投稿吗?
PyCaret 是一个开源项目。欢迎每个人都来投稿。如果您愿意投稿,请随意处理未决问题。dev-1.0.1 分支上的单元测试接受拉请求。
如果你喜欢 PyCaret,请给我们 GitHub 回购的⭐️。
中:https://medium.com/@moez_62905/
领英:https://www.linkedin.com/in/profile-moez/
https://twitter.com/moezpycaretorg1
使用 FastAPI 构建和托管快速数据科学应用
将智能数据科学应用程序构建为 Restful API 的分步指南
我最近使用 FastAPI web 框架托管了许多生产就绪的数据科学应用程序,作为 Restful web 服务。
我发现 FastAPI 稳定且易于使用,因此,我决定写一篇关于 FastAPI 库的文章,概述托管数据科学应用程序的步骤。

解释 FastAPI 的工作原理
FastAPI 于 2018 年发布,正在成为构建高性能数据科学应用的事实上的选择。
本文将解释什么是 FastAPI,为什么它优于竞争对手,以及如何使用 FastAPI 托管数据科学应用程序的分步指南。
可以把 FastAPI 想象成一个数据科学应用程序的包装器,以 RESTFUL 微服务的形式公开其功能

作为包装器的 FastAPI
文章摘要
本文将概述以下主题:
- 什么是 FastAPI?
- FastAPI 的主要特性
- 使用 FastAPI 构建和托管 Python 数据科学应用程序的分步指南。
本文将构建一个真实的数据科学应用程序来演示如何在您的数据科学项目中使用 FastAPI
1.什么是 FastAPI?
顾名思义,FastAPI 是一个高性能的 web 框架。它的性能可以与 NodeJS 和 Go 相提并论,它被评为目前最快的 Python 框架之一。
网飞、优步、微软以及许多其他公司都在使用 FastAPI 库。
FastAPI 可以帮助我们用 Python 3.6+构建 API。
它基于标准的 Python 类型提示。FastAPI 不仅在项目中使用起来直观明了,而且 FastAPI 代码还具有 100%的测试覆盖率,因此它是生产就绪的健壮代码。
使用 Flask 有一段时间了,我注意到 FastAPI 和 Flask 一样简单易用。事实上,FastAPI 已经从 Flask API 改编了它的简单性。随后,总的来说,我建议在未来的项目中探索 FastAPI。
FastAPI 建立在 Starlette 和 Pydantic 库的基础上。
该图说明了 FastAPI 使用 Starlette 作为 web 部件,使用 Pydantic 作为数据部件。

FastAPI 基于 Pydantic 和 Starlette
ydantic 是一个 Python 库,用于执行数据验证、文档以及序列化。P ydantic 使用 PEP 484 中定义的标准库typing类型来定义复杂对象。
让我们来探索一下 FastAPI 的特性。
2.FastAPI 的主要特性
1.要概述的第一个特性是自动交互式 API 文档
FastAPI 是基于开放标准的 OpenAPI 和 JSON 模式。因此,只要我们使用适当的 Pydantic 数据类型,它可以自动为我们的 web API 构建一个 SwaggerUI,而无需任何额外的编码。SwaggerUI 本质上是交互式的,允许我们直接从浏览器测试 API。自动化文档受到 APISpec 的启发。
我将在本文后面演示如何使用 FastAPI 用 JSON schema 构建自动数据模型文档。
FastAPI 还允许我们验证来自外部调用者的输入数据,并在接收到无效数据时向客户端自动生成错误。文档特性受到了 Django REST 框架的启发。
OpenAPI 自动为应用程序生成一个模式。FastAPI 还支持数据序列化和输入数据解析,这是受 Marshmallow 和 Webargs 的启发。点击阅读更多信息
2.第二个关键特性是支持异步 IO 操作
构建一个在执行操作时不会阻塞调用者的 web API 是至关重要的。Python 中的 asyncio 库提供了大量的异步功能。
FastAPI 库支持异步 IO 操作。这是可能的,因为 FastAPI 是基于 Starlette 库的。
Starlette 图书馆本身坐落在 Uvicorn 的顶部。Uvicorn 是一个支持 asyncio 框架的快如闪电的 ASGI 服务器。
Starlette 是一个轻量级的 ASGI 框架,它使我们能够构建高性能的 asyncio 服务。
与 WSGI 服务器不同,ASGI 服务器可以支持 HTTP/2 和 WebSockets。在 Uvicorn 的帮助下,我们可以构建一个 web API,它可以在 IO 绑定的上下文中实现高吞吐量。
Starlette 使用较新的异步 IO ASGI 服务器,也支持后台任务。因此,我们可以使用 FastAPI 构建低潜在的快速 web APIs
3.最重要的特征;我们可以快速为我们的数据科学应用程序创建 REST 端点
Flask 用户必须安装 Flask-restplus 包来为他们的数据科学应用程序创建 REST 端点。
FastAPI 支持 GET、PUT、POST、DELETE、OPTIONS、HEAD、PATCH 和 TRACE Rest 操作,无需任何额外的包。所有路线及其操作都是在文档中自动生成的。
4.FastAPI 应用程序易于安装、使用和支持
最近我注意到了这个行业的一个模式。将数据科学解决方案快速推向市场变得至关重要。此外,数据科学应用程序是大型生态系统的一个组成部分,它们需要与许多服务和接口进行交互。这意味着能够将应用程序快速部署为 web 服务,以便最终用户可以使用它,这是非常重要的。
FastAPI 使用起来很简单。将数据科学应用托管为微服务并公开其他应用可以调用的 Rest 端点只需几分钟。验证、错误处理以及其他 API 特性都是现成的,有助于提高客户满意度和应用程序的可靠性。
这将我们带到本文的最后一节,在这里我将演示托管数据科学应用程序的步骤。

分步指南
3.逐步实施
让我们从构建智能数据科学应用程序的真实用例开始。
用例
- 我们将使用 Python 3.8 构建一个数据科学应用程序
- 该应用程序将抓取在线网页,以返回作为指数成份股的公司列表,如富时 100 指数、标准普尔 500 或道琼斯。
- 该功能将通过 GET Rest 端点公开,我们将在本地主机的端口 8000 上托管该端点。端点将接受一个查询参数:index。该指数只能是下列指数之一:富时 100 指数、标准普尔 500 指数或道琼斯指数。
- 端点还将确保该值是可接受的索引值之一。所有的错误都将被处理,并优雅地发送回 API 的用户/调用者。
- 我们将使用 FastAPI 自动生成 Swagger UI 和 OpenAPI 文档。

目标应用程序
1.创建虚拟环境
第一步是创建一个虚拟环境并激活它。
python3 -m venv fintechexplained
fintechexplained\Scripts\activate
2.安装依赖项
下一步是安装所需的模块。
首先,安装 fastapi
pip install fastapi==0.58.1
因此,它还将安装所需的依赖项,如 starlette0.13.4 和 pydantic1.5.1。
然后安装 uvicorn
pip install uvicorn==0.11.5
现在,为了抓取网页,我将使用熊猫图书馆。因此,下一步是安装熊猫:
pip install pandas==1.0.3
安装步骤完成了。
现在让我们创建文件夹结构。
3.创建项目结构
为了简单起见,让我们创建以下文件夹结构。

我们创建了两个文件夹:SmartApp 和 SmartApp 文件夹中的 src。此外,让我们创建以下三个空 Python 文件:
- 这个文件将包含启动 uvicorn 服务器的代码。它还将包含异步服务请求和返回响应的代码。这个文件还将创建一个 FastAPI()实例,它是创建 API 的主要交互点。
- models.py:这个文件将包含应用程序的域类,比如 Company 和 Configuration。
- workflow_runner:这个文件将包含抓取网页并返回公司名称的代码。这是我们的数据科学应用程序代码,我们将通过 FastAPI 公开它。
如果您想创建一个生产就绪的解决方案,那么我推荐使用千篇一律的 python 项目。有许多模板可用,包括一个针对 FastAPI 的模板。
确保虚拟环境已激活。
4.Python 代码实现
下一步涉及实现 Python 代码。
models.py
打开 models.py 文件并添加以下代码:
from enum import Enum
from pydantic import BaseModelclass MyException(Exception):
passclass Company:
def __init__(self, symbol):
self.name = None
self.symbol = symbol
self.sector = None
self.industry = None
class Index(str, Enum):
FTSE100 = "FTSE 100"
SNP500 = "S&P 500"
DOWJONE = "Dow Jones"
class Configuration(BaseModel):
index: str = None
index_map = {
Index.FTSE100: 'https://en.wikipedia.org/wiki/FTSE_100_Index',
Index.SNP500: 'http://en.wikipedia.org/wiki/List_of_S%26P_500_companies'
}
def get_url(self):
return self.index_map[self.index]
- 我们将有一个名为 Company 的类来代表指数的每个成分。
- 我们还创建了一个配置类。此类包含作为枚举的索引名称。枚举成员将作为下拉菜单显示在 API 文档和 Swagger UI 中。请注意,配置类继承自 pydantic BaseModel。这将使我们能够生成自动数据模式文档。配置类包含一个名为 index_map 的字典。每个索引映射项的键作为索引枚举成员,值作为包含公司信息的网页的 URL。
还要注意,我添加了一个函数 get_url(),它将返回所选索引的 url。
- 我们还创建了一个定制的异常类 MyException。我们将在 workflow_runner.py 中为它生成一个异常处理程序。
workflow_runner.py
现在模型已经实现,让我们将代码添加到 workflow_runner.py 中。这是我们的数据科学应用程序的核心。
该文件将包含执行以下两个步骤的代码:
- 对于输入索引,通过删除适当的网页来获取其公司
- 以字符串列表的形式返回公司名称
请注意,workflow_controller 的 run() 方法已经声明为 async,以说明我们如何创建非阻塞的 async IO 操作。
from models import Company, Index
import pandas as pd
def get_snp_500_companies(url):
companies = []
table = pd.read_html(url)[0]
for index, row in table.iterrows():
company = Company(row['Symbol'])
company.name = row['Security']
company.sector = row['GICS Sector']
company.industry = row['GICS Sub Industry']
company.date_added = row['Date first added']
companies.append(company)
return companies
def get_ftse_companies(url):
companies = []
table = pd.read_html(url)[3]
for index, row in table.iterrows():
company = Company(row['EPIC'])
company.name = row['Company']
company.sector = row['FTSE Industry Classification Benchmark sector[12]']
companies.append(company)
return companies
**async** def run(config):
companies_map = {
Index.SNP500: get_snp_500_companies,
Index.FTSE100: get_ftse_companies
}
url = config.get_url()
func_to_get_data = companies_map.get(config.index, None)
if func_to_get_data is None:
raise KeyError(f'{input.index} is not suppported')
companies = func_to_get_data(url)
return [c.name for c in companies]
我用的是 pandas.read_html(url)函数。它返回网页中的所有表格。因此,我从网页上选择合适的表格。因为每个 web 页面都有不同的结构,所以我已经用公司地图中的 url 注册了索引名。在运行时,工作流运行器将选择适当的 url,并通过执行特定于索引的函数来创建公司类的实例。
如果我们选择道琼斯,它将引发一个异常。这将帮助我演示如何向用户显示用户友好的错误。
我们现在准备集成 FastAPI。
main.py
最后,我们将把代码添加到 main.py 文件中
首先,添加导入:
import uvicorn
from fastapi import FastAPI, Path, Request
from fastapi.responses import JSONResponse
import workflow_runner
from models import MyException, Configuration, Index
然后创建一个 FastAPI()实例,并将其声明为 app 变量。
我们给它一个标题、描述和版本。该信息将自动显示在文档中。
app = FastAPI(title='SMART Data Science Application',
description='A Smart Data Science Application running on FastAPI + uvicorn',
version='0.0.1')
公开 GET 端点以处理调用 workflow_runner.run()的请求:
@app.get("/{index}")
async def get_result(index: Index = Path(..., title="The name of the Index")
):
config = Configuration(
index=index
)
try:
result = await workflow_runner.run(config)
return JSONResponse(status_code=200, content=result)
except Exception as e:
raise MyException(e)
注意我是如何等待 run 函数的。
本质上,@app.get 是 REST 路径操作。它用路径“/”和 GET 操作处理请求。它调用异步 get_result()函数。参数索引现在是一个查询参数。
我们还可以将查询参数标记为可选的,文档将自动反映出来以适应这种变化。我们已经为路径参数索引声明了一个title元数据值。这将出现在自动文档中。
我们还可以在 Path()中添加验证规则,例如对于整数参数,gt=0,le=1000。
注意,函数 get_result()被声明为 async。它允许我们在不阻塞其他呼叫的情况下服务请求。
因此,这个特性使应用程序能够并发地处理请求。
最后要注意的一点是,所有的异常都被捕获,然后引发 MyException。
尽管最佳实践是显式捕获异常并单独处理它们,但出于演示目的,我用宽 try/except 异常捕获所有异常。
最后,对于错误处理,我们定义了一个可以处理 MyException 类型的异常的端点。
@app.exception_handler(MyException)
async def unicorn_exception_handler(request: Request, exc: MyException):
return JSONResponse(
status_code=418,
content={"message": f"Error occurred! Please contact the system admin."},
)
现在,每当我们得到 MyException 类型的异常时,它将显示消息“Error occurred!请联系系统管理员。”。这是因为 app.exception_handler 路径。FastAPI 还允许我们创建自己的异常处理程序。
最后,添加运行 uvicorn 服务器的代码。
注意,我们使用端口 8000,主机 IP 地址是 localhost (0.0.0.0)。
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
我们已经完成了实现。
5.运行服务器应用程序
让我们运行应用程序。导航到 main.py 所在的文件夹,并在终端中执行以下行:
uvicorn main:app — reload
- main 是我们想要运行的 python 文件的名称。
- app 是 main.py 中的 FastAPI 对象
reload 将使我们能够在代码更改后重启服务器,从而在开发期间实现快速开发。
运行该命令将显示:
←[32mINFO←[0m: Uvicorn running on ←[1mhttp://127.0.0.1:8000←[0m (Press CTRL+C to quit)
←[32mINFO←[0m: Started reloader process [←[36m←[1m1180←[0m] using ←[36m←[1mstatreload←[0m
←[32mINFO←[0m: Started server process [←[36m7004←[0m]
←[32mINFO←[0m: Waiting for application startup.
←[32mINFO←[0m: Application startup complete.
- Uvicorn 服务器已经暴露了本地主机端口 8000 上的应用程序。
- 另外,它为应用程序创建了一个大摇大摆的 UI
- 最后,它为应用程序生成了 OpenAPI 文档。
6.消费服务
首先,让我们回顾一下自动化 API 文档
导航到
[http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc)
它将显示 Swagger UI。

单击索引会显示索引列表:

运行它会在响应中显示公司名称:

让我们选择道琼斯,看看我们是否得到一个用户友好的错误:

这是由 FastAPI 自动完成的。
从另一个应用程序调用智能数据科学应用程序
我们可以从旋度来称呼它:
curl -X GET "[http://localhost:8000/FTSE%20100](http://localhost:8000/FTSE%20100)" -H "accept: application/json"
我们可以打开浏览器并导航到 url 来查看响应:
http://localhost:8000/FTSE%20100
您可以通过导航到以下 url 来下载 openAPI 规范:
[http://localhost:8000/openapi.json](http://localhost:8000/openapi.json)
我们可以看到已经内置了验证以及可接受的索引值,如下所示。OpenAPI 模式支持 Swagger UI。它包括 API 和数据模式,如下所示:
{
"openapi": "3.0.2",
"info": {
"title": "SMART Data Science Application",
"description": "A Smart Data Science Application running on FastAPI + uvicorn",
"version": "0.0.1"
},
"paths": {
"/{index}": {
"get": {
"summary": "Get Result",
"operationId": "get_result__index__get",
"parameters": [
{
"required": true,
"schema": {
"title": "The name of the Index",
"enum": [
"FTSE 100",
"S&P 500",
"Dow Jones"
],
"type": "string"
},
"name": "index",
"in": "path"
}
],
"responses": {
"200": {
"description": "Successful Response",
"content": {
"application/json": {
"schema": {}
}
}
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"HTTPValidationError": {
"title": "HTTPValidationError",
"type": "object",
"properties": {
"detail": {
"title": "Detail",
"type": "array",
"items": {
"$ref": "#/components/schemas/ValidationError"
}
}
}
},
"ValidationError": {
"title": "ValidationError",
"required": [
"loc",
"msg",
"type"
],
"type": "object",
"properties": {
"loc": {
"title": "Location",
"type": "array",
"items": {
"type": "string"
}
},
"msg": {
"title": "Message",
"type": "string"
},
"type": {
"title": "Error Type",
"type": "string"
}
}
}
}
}
}
这是 FastAPI 自动构建的 API 的 OpenAPI 文档。我们可以将它发送给 API 的调用者,这样他们就可以轻松地将他们的服务与我们的解决方案集成在一起。
注意,索引枚举成员与参数标题和验证规则一起出现在 OpenAPI 文档中。

感谢您的阅读
仅此而已。如果你想了解更多关于 FastAPI 的信息,请访问他们的网站获取更多信息。
摘要
FastAPI 是一个高性能的 web 框架。FastAPI 于 2018 年发布,正在成为构建高性能数据科学应用的事实上的选择。
本文解释了什么是 FastAPI,它的主要特性是什么,并一步步地指导如何将数据科学应用打包成 Restful 微服务。
使用 fastai v2 在 15 行代码内构建任何深度学习图像分类器
Fastai 是一个基于 PyTorch 构建的高级深度学习库。杰瑞米·霍华德最近推出了新版本的图书馆,以及非常方便、初学者友好的书和课程。我对它的抽象层次感到非常惊讶,它可以帮助您在几分钟内创建最先进的模型,而不必担心它背后的数学问题。
这篇文章是为完全的初学者而写的,即使你没有什么编码经验,你也能理解它。读完这篇文章后,你将能够从头开始编写一段代码,它可以识别你最喜欢的超级英雄,甚至可以通过它发出的声音来识别它。

演职员表:外什那维·奇蒂亚拉
这是我在 GCP 集群 *上使用少量训练数据、几行代码和几分钟训练训练的掩码分类器的结果快照。单击此处为** 免费 设置您自己的 FastAI GPU 虚拟机

尝试用你自己的图像这里
为了达到这个效果,我们首先需要在图像中找到人脸,也称为定位,然后对每个人脸进行分类,并根据其所属的类别(绿色:带 _ 面具,红色:无 _ 面具,黄色:面具 _ 戴 _ 不合适)绘制一个彩色的包围盒。今天让我们来理解问题的第二部分多类图像分类
项目代码可用 此处
我会在我们写一些代码的时候解释一些深度学习和计算机视觉的基本概念。我强烈推荐你在 jupyter 笔记本上一行一行地运行代码,因为我们理解了抽象函数背后的思想
处理数据
图书馆被分成几个模块,我们主要有表格,文本和视觉。我们今天的问题将涉及视觉,所以让我们从vision库中导入all我们需要的函数
**In [1]:** from fastai.vision.all import *
就像我们如何通过观察图像来识别物体一样,我们的计算机需要数据来识别图像。对于遮罩检测,我已经策划了一个从 kaggle 和其他来源收集的标记为的数据集,您可以从这里这里从下载
我们存储数据集所在的路径。Path返回一个pathlib对象,该对象可以用来非常容易地执行一些文件操作
**In [2]:** DATASET_PATH = Path('/home/kavi/datasets')
在我们训练我们的模型(教我们的算法识别图像)之前,我们首先需要告诉它一些事情
- 预期的输入和输出是什么?什么是问题域?
- 数据位于何处,如何标记?
- 我们希望保留多少数据来评估模型的性能?
- 我们需要转换数据吗?如果是的话怎么做?
Fastai 有一个叫做DataBlock的超级灵活的函数,它接受上述问题的输入并准备一个模板
**In [3]:** mask_datablock = DataBlock(
get_items=get_image_files,
get_y=parent_label,
blocks=(ImageBlock, CategoryBlock),
item_tfms=RandomResizedCrop(224, min_scale=0.3),
splitter=RandomSplitter(valid_pct=0.2, seed=100),
batch_tfms=aug_transforms(mult=2)
)
get_image_files函数递归地抓取给定路径中的所有图像文件位置并返回它们,这样我们告诉 fastai 去哪里get_items- 在我们的数据集中,我将图像放在根据类别命名的独立文件夹中,
parent_label函数根据路径返回文件的父目录
如 : parent_label('/home/kavi/datasets/with_mask/1.jpg') = > ' with_mask'
你可以根据你的数据如何被标记来编写你自己的函数
- 在知道输入图像和目标标签的文件路径后,我们需要根据问题的类型对数据进行预处理。图像的示例预处理步骤包括使用
Pillow从文件路径创建图像,并将它们转换为张量

图片取自此处
图像在我们的电脑中是如何表现的?
每幅图像都是像素强度的矩阵。每个值的范围从 0 到 255。0 是最暗的,255 是相应通道的最亮强度
彩色图像是一个三层矩阵/三阶张量。每一层包括 R ed、 G reen、 B lue 亮度,而黑白图片是一维矩阵
我们将类型为[TransformBlock](https://docs.fast.ai/vision.data#TransformBlocks-for-vision)的元组(input_transformation, output_transformation)传递给blocks在我们的问题中,我们需要预测图像的类别,因此我们传递(ImageBlock, CategoryBlock)如果你想根据一个人的照片预测他的年龄,你需要传递(ImageBlock, RegressionBlock)
- 当所有图像大小相同时,深度学习模型工作得最好,并且当分辨率较低时,它们学习得更快。我们将告诉如何通过向
item_tfms传递一个合适的 resize 函数来重新缩放图像,这个函数将被应用于每个图像

使用 ResizeMethod 调整大小的图像。Squish,ResizeMethod。Pad 和 ResizeMethod。作物方法
Fastai 提供了各种调整大小的方法:裁剪、填充或挤压。每一个都有些问题。有时,我们甚至可能会丢失一些关键信息,就像中间裁剪后的第三张图片一样
我们可以使用RandomResizedCrop来克服这个问题。在这里,我们随机选择图片的一部分,并为覆盖每张图片的大部分区域的几个时期(一次完整地通过数据集中的所有图像)训练模型。min_scale 决定每次最少选择多少图像。

使用RandomResizedCrop(224, min_scale=0.3)调整图像大小
- 对训练数据集的模型准确性评估将导致偏分,并可能导致对不可见数据的较差性能。我们需要告诉我们的
DataBlockAPI 留出一些预处理的数据来评估模型的性能。算法看到的数据称为训练数据,搁置的数据称为验证数据。通常数据集会定义验证集,但是在我们的例子中我们没有,所以我们需要传递一个 split 函数给splitter
Fastai 有一对分割函数和,让我们用RandomSplitter来解决今天的问题valid_pct将决定训练数据的多少部分需要留出,seed将确保总是留出相同的随机图像
- 拥有多样化的数据集对任何深度学习模型的性能都至关重要。如果你没有足够的数据,你会怎么做?我们根据现有数据生成新数据,这个过程称为数据扩充
数据扩充 指的是创建我们输入数据的随机变化,使它们看起来不同,但实际上并不改变数据的含义。 —快速书

使用 aug_transforms()增强的单个泰迪图像
上面的图像是由一张泰迪的照片生成的。在现实世界中,我们经常不得不根据看不见的数据进行预测,如果模型只是记忆训练数据(过拟合),而不是理解数据,那么它的表现将会很差。事实证明,在许多情况下,扩充数据有助于提高模型的性能
在 fastai 中,我们有一个预定义的函数aug_transforms,它执行一些默认的图像变换,如翻转、改变亮度、倾斜和一些其他的。我们将这个函数传递给batch_tfms,有趣的是这些转换是在 GPU 上执行的(如果有的话)
DataBlock保存将在数据集上执行的指令列表。这充当了创建一个DataLoader的蓝图,它采用我们的数据集路径,并按照DataBlock对象的定义对图像应用预处理变换,然后将它们加载到 GPU 中。加载数据后batch_tfms将应用于批次。默认的批量大小是 64,您可以通过将bs=n传递给 dataloders 函数来根据您的 GPU 内存增加/减少
提示:
**!nvidia-smi**命令可以在你的笔记本上随时执行,了解你的 GPU 使用详情。您可以重启内核来释放内存
**In[10]:** dls = mask_datablock.dataloaders(DATASET_PATH)
dls是保存训练和验证数据的数据加载器对象。您可以使用dls.show_batch()查看我们转换后的数据
训练我们的面具分类器模型
模型是一组值,也称为权重,可用于识别模式。模式识别无处不在,在生物中,它是一个发生在大脑中的认知过程,我们没有意识到它。就像我们小时候通过盯着它们学习识别颜色、物体和字母一样。训练模型是确定正确的权重集,该权重集可以解决特定的问题,在我们的例子中,将图像分为 3 类:*有 _ 遮罩、无 _ 遮罩、遮罩 _ 磨损 _ 不正确*****
如何快速训练模特?
作为一个成年人,我们几乎可以立即学会识别物体,这是因为我们从出生开始就一直在学习模式。最初,我们学会了识别颜色,然后是简单的物体,像球,花。几年后,我们能够识别人和其他复杂的物体。类似地,在机器学习中,我们有预先训练的模型,这些模型被训练来解决类似的问题,并且可以被修改来解决我们的问题
使用一个预先训练好的模型来完成一个不同于它最初被训练的任务被称为 迁移学习——快速学习
resnet34是在 ImageNet 数据集上训练的一个这样的模型,该数据集包含大约 130 万张图像,可以分类成 1000 个图像类别。在我们的问题中,我们只有 3 个类别,所以我们使用初始层来识别基本图案,如线、角、简单形状,然后在最终层上重新训练
**In[11]:** learn = cnn_learner(dls, resnet34, metrics=error_rate)
Fastai 提供了一个cnn_learner功能,在计算机视觉模型的训练中特别有用。它采用DataLoader对象dls,预训练模型resnet34(这里 34 表示我们有 34 层),以及一个度量error_rate,该度量计算在验证数据上被错误分类的图像的百分比
指标 是一个使用验证集 — Fastbook 测量模型预测质量的函数
迁移学习是如何工作的?
最初,我们用一个或多个具有随机权重的新层替换预训练模型的最后一层,这部分被称为头部。我们使用反向传播算法更新头部的权重,我们将在另一篇文章中学习
Fastai 提供了一个方法fine_tune,该方法执行调整预训练模型的任务,以使用我们收集的数据解决我们的特定问题
**In[12]:** learn.fine_tune(4)

微调功能的输出
我们将一个数字传递给fine_tune,它告诉你需要训练多少个时期(我们完全遍历数据集的次数)。这是你需要玩的东西,没有硬性规定。这取决于你的问题,数据集,以及你想花在训练上的时间。您可以使用不同的时期多次运行该功能
杰里米的建议和我的收获:
- 大量历元的训练会导致过拟合,这可能会导致对看不见的数据表现不佳。如果验证损失在连续的时期中继续增加,这意味着我们的模型正在记忆训练数据,我们需要停止训练
- 我们可以通过使用不同分辨率训练模型来提高性能。例如,用 224x224 和后来的 112x112 像素图像进行训练
- 数据增加将有助于在一定程度上防止过度拟合
使用模型进行推理
现在我们有了经过训练的面具分类器,它可以从一个人的脸部照片来分类这个人是否戴着面具。我们可以导出这个模型,并用它来预测其他地方的类
**In[13]:** learn.export()
**In[14]:** learn.predict('path/to/your/image.jpg')
我们可以使用load_learner('path/to/model/export.pkl')来加载这个模型

web 应用的屏幕截图
我继续做了一个 REST API,把这个模型暴露在互联网上,在我的朋友们的帮助下: Vaishnavi 和 Jaswanth ,我做了一个 web 应用程序,它接收一个输入图像,并根据人脸所属的类别以及人脸类别的数量来绘制边界框。请随时留下您的反馈,这将有助于改进模型。web app 在https://find mask . ml上线
关于我如何构建深度学习 REST API 的文章即将发布:)
结论
现在,您已经准备好构建您的图像分类器,您还可以使用这种技术通过将声音转换成声谱图或任何合适的图像形式来对声音进行分类。如果你开始学习深度学习,我强烈推荐你参加 fastai v2 课程并加入由 Sanyam Bhutani 和 MLT 组织的学习小组,在那里我们每周阅读并讨论 Fastbook 的每一章。
如果您有任何反馈或者遇到任何问题,请随时联系我,我很乐意为您提供帮助。我活跃在 Twitter 和 LinkedIn
相关有趣文章
- https://muellerzr.github.io/fastblog/
- https://towards data science . com/10-new-things-I-learn-from-fast-ai-v3-4d 79 C1 f 07 e 33
我的其他故事
使用语义 ML 构建语言驱动的应用程序

图片由戴尔·马科维茨拍摄
在这篇文章中,我将向你展示如何使用初学者友好的 ML 工具——Semantic Reactor 和 tensor flow . js——来构建一个基于自然语言的应用程序。
更新:语义反应堆上线了!将它添加到 Google Sheets 这里 。
大多数人更擅长用语言描述世界,而不是用代码描述世界(嗯……大多数人)。那么,如果机器学习可以帮助弥合这两者之间的差距,那就太好了。
这就是“语义 ML”的用武之地,这是一个概括术语,用于描述捕捉单词或短语语义的机器学习技术。在这篇文章中,我将向您展示如何使用初学者友好的工具(Semantic Reactor 和 Tensorflow.js)快速构建基于语言的应用程序原型。
向下滚动以直接进入代码和工具,或者继续阅读一些背景知识:
理解语义 ML
什么是嵌入?
语义 ML 帮助我们构建自然语言驱动的软件的一个简单(但强大)的方法是通过一种叫做嵌入的技术。
在机器学习中,嵌入是一种在空间中表示数据(即绘制在 n 维网格上的点)的学习方法,使得点之间的距离是有意义的。单词向量是一个流行的例子:

单词嵌入的可视化。本图来自 本媒文章 。
上图显示了单词(“英格兰”、“他”、“快”)在空间中的排列,这样类似的单词(“狗”和“狗”、“意大利”和“罗马”、“女人”和“女王”)彼此靠近。每个单词都由一组坐标(或向量)表示,因此单词“queen”可能由坐标[0.38,0.48,0.99,0.48,0.28,0.38]表示。
这些数字从何而来?它们是由机器学习模型通过数据学习的。特别是,该模型学习哪些单词倾向于出现在句子的相同位置。考虑这两句话:
我妈妈生了一个儿子。
我妈妈生了一个女儿。
因为“女儿”和“儿子”这两个词经常在类似的上下文中使用,所以机器学习模型将学习到它们在空间中应该被表示为彼此靠近。
单词嵌入在自然语言处理中非常有用。它们可以用于查找同义词(“语义相似性”),进行聚类,或者作为更复杂的 nlp 模型的预处理步骤。
嵌入整个句子
事实证明,使用一种叫做通用句子编码器的模型,整个句子(甚至是短段落)也可以有效地嵌入空间。使用句子嵌入,我们可以判断两个句子是否相似。这很有用,例如,如果你正在构建一个聊天机器人,并且想知道用户是否问了一个问题(例如,“你什么时候叫醒我?”)在语义上类似于一个你——聊天机器人程序员——已经预料到的问题,并写了一个回答(“我的闹钟是几点?”).
语义反应器:在 Google 表单中使用语义 ML 的原型
好了,现在开始有趣的部分——建造东西!
首先,一些灵感:当安娜·基普尼斯(Double Fine 的前游戏设计师,现在 Stadia/Google)向我展示她如何使用语义 ML 来自动化视频游戏交互时,我最初对语义 ML 感到兴奋。使用句子编码器模型,她构建了一个视频游戏世界,该世界使用 ML 来推断环境应该如何对玩家输入做出反应。它让我大吃一惊。点击这里查看我们的聊天记录:
在安娜的游戏中,玩家通过问任何他们想到的问题来与虚拟狐狸互动:
“福克斯,我能喝点咖啡吗?”
然后,使用语义 ML,游戏引擎(或实用系统)考虑游戏可能做出反应的所有可能方式:
使用句子编码器模型,游戏决定最佳反应是什么并执行它(在这种情况下,最佳反应是Fox brings you mug,因此游戏动画显示 Fox bring you mug)。如果这听起来有点抽象,一定要看我上面链接的视频。
这个项目最巧妙的一个方面是 Anna 使用一个叫做语义反应器的工具在 Google Sheet 中做了大量的原型。
语义反应器是 Google Sheets 的一个插件,允许你在一个工作表中对你自己的数据使用句子编码器模型。在这里访问它。这是快速构建语义 ML 应用原型的一个非常好的方法,然后你可以使用 TensorFlow.js models 将它转化为代码(稍后会有更多相关内容)。
下面是这个工具的一个小图片:

Dale Markowitz 的使用语义反应器的 Gif。
要使用语义反应器,创建一个新的谷歌表,并在第一列中写一些句子。在这里,我将松散地重现安娜的 fox 演示(对于所有的细节,查看她的原始帖子)。我把这些句子放在我的谷歌表单的第一列:
在这里,你必须发挥你的想象力,想想潜在角色(例如聊天机器人或视频游戏中的演员)可能会采取的这些“行动”。
一旦你安装了语义反应器,你就可以通过点击“附加组件->语义反应器->启动”来启用它。

从附加组件下拉菜单中启用语义反应器(Dale Markowitz)
单击“开始”将打开一个面板,允许您键入输入内容并点击“反应”:

尝试输入/响应排名(戴尔·马科维茨)
当你点击“React”时,Semantic Reactor 使用一个模型来嵌入你在第一列中写的所有响应,计算一个分数(这句话对查询的响应有多好?),并对结果进行排序。例如,当我的输入是“我想要一些咖啡”时,我的电子表格中排名最高的响应是“我去拿杯子”和“我给你拿了杯子。”
您还会注意到,使用这个工具有两种不同的方式来排列句子:“输入/响应”和“语义相似度”顾名思义,前者根据句子对给定查询的响应的好坏来对句子进行排序,而“语义相似度”只是对句子与查询的相似程度进行评级。
使用 TensorFlow.js 从电子表格到代码
在引擎盖下,Semantic Reactor 由开源的 TensorFlow.js 模型提供支持。
让我们看看如何在 JavaScript 中使用这些模型,这样您就可以将电子表格原型转换成一个工作应用程序。
- 创建一个新的节点项目并安装模块:
npm init
npm install @tensorflow/tfjs @tensorflow-models/universal-sentence-encoder
2.创建一个新文件(use_demo.js)并要求库:
require('@tensorflow/tfjs');
**const** encoder = require('@tensorflow-models/universal-sentence-encoder');
3.加载模型:
**const** model = **await** encoder.loadQnA();
4.对您的句子进行编码并查询:
**const** input = {
queries: ["I want some coffee"],
responses: [
"I grab a ball",
"I go to you",
"I play with a ball",
"I go to school.",
"I go to the mug.",
"I bring you the mug."]
};**const** embeddings = **await** model.embed(input);
5.瞧啊。您已经将您的回答和查询转换为向量。不幸的是,向量只是空间中的点。要对回答进行排序,您需要计算这些点之间的距离(您可以通过计算点积来完成,这将给出点之间的平方欧几里德距离):
// zipWith :: (a -> b -> c) -> \[a\] -> \[b\] -> \[c\]**const** zipWith =
(f, xs, ys) => {
**const** ny = ys.length;
**return** (xs.length <= ny ? xs : xs.slice(**0**, ny))
.map((x, i) => f(x, ys\[i\]));
} // Calculate the dot product of two vector arrays.
**const** dotProduct = (xs, ys) => {
**const** sum = xs => xs ? xs.reduce((a, b) => a + b, **0**) : **undefined**; **return** xs.length === ys.length ?
sum(zipWith((a, b) => a * b, xs, ys))
: **undefined**;
}
如果运行这段代码,您应该会看到如下输出:
[
{ response: 'I grab a ball', score: **10.788130270345432** },
{ response: 'I go to you', score: **11.597091717283469** },
{ response: 'I play with a ball', score: **9.346379028479209** },
{ response: 'I go to school.', score: **10.130473646521292** },
{ response: 'I go to the mug.', score: **12.475453722603106** },
{ response: 'I bring you the mug.', score: **13.229019199245684**}
]
点击查看完整代码示例。
就是这样:这就是如何从语义 ML 电子表格快速编码!
很酷,对吧?如果你用这些工具做了些什么,一定要在下面的评论里或者在 Twitter 上让我知道。
发推文 @dalequark 或者在 Instagram 上关注 @dale_on_ai 。
原载于 2020 年 8 月 5 日 https://daleonai.com**。
使用 TensorFlow 数据集构建更好的管道
入门
简洁高效的数据处理可视化指南

照片由 Unsplash 上的 roman pentin 拍摄
D 在任何可扩展的、生产质量的 ML 解决方案中,ata 管道虽然不那么迷人,但仍然是基本的构建模块。事实上,绝大多数 ML 实际上是数据争论——因此,强大的管道是构建强大解决方案的重要因素是有道理的。
聚焦 TensorFlow 2,我们有一个奇妙的东西叫做Dataset对象,内置在库中。使用数据集对象,我们可以用少得多的努力来设计高效的数据管道——结果是一个更干净、更合理和高度优化的管道。
我们将深入研究数据集对象。包括它们是什么,为什么我们应该使用它们,以及我们如何使用它们。
**What Are Datasets?**
- Why Use Them?**Reading Data**
- In-memory
- From File**Basic Operations**
- Batching and Shuffling
- Data Transformations with Map**Feeding Datasets into a Model**
- Multiple Inputs/Outputs
- Train-Validation Split
如果您喜欢视频,我也在这里介绍了本文中的所有内容:
什么是数据集?
数据集是包含在tf.data API 中的一个对象,它表示一系列元素。每个元素都被赋予了特定的结构,这取决于我们的模型所要求的格式。
tf.data API 是 TensorFlow 构建输入数据管道的内置方法——提供用更少代码开发更高效管道的方法。
为什么使用它们?
数据集抽象使得数据提取、转换和加载非常容易。
例如,我们可以构建一个管道来迭代地从文件中加载(而不是将所有内容都保存在内存中),执行一些给定的转换(如文本数据的标记化),批处理,混洗,并将数据加载到我们的模型中进行训练。
所有这些通常只需要几行代码。批处理和混洗我们的数据集只需要dataset.shuffle(10000).batch(64)。
读取数据
如前所述,关于如何将数据读入数据集,我们有两种选择,(1)从内存中或(2)从磁盘中。
在记忆中
最简单的方法是使用 dataframe、数组、列表或其他数据结构将数据直接读入 Python。这种方法绝对可以使用,但是对于较大的数据集来说可能很快变得难以管理。
因此,如果使用较小的数据集,您有以下选择:
import tensorflow as tf# read from lists
inputs = [0, 1, 2, 3]
labels = [1, 0, 1, 0]
dataset = tf.data.Dataset.from_tensor_slices((inputs, labels))# the exact same approach for Numpy arrays
inputs = np.asarray([0, 1, 2, 3])
labels = np.asarray([1, 0, 1, 0])
dataset = tf.data.Dataset.from_tensor_slices((inputs, labels))# and from dataframes
df = pd.DataFrame({
'inputs': [0, 1, 2, 3],
'labels': [1, 0, 1, 0]
})
dataset = tf.data.Dataset.from_tensor_slices(df)

使用上面的 list/NumPy 方法创建的数据集对象内的内部记录。
这些方法产生如上所示的dataset结构。显然,从内存对象中读取非常简单,但是对于大型数据集来说并不理想。
从文件
第二种方法是从内存不足的地方读入数据,比如本地硬盘。
采用这种方法时,我们受益于只在内存中加载我们需要的数据,这意味着对于一个 20M 的样本数据集,我们可以避免一次加载整个数据集,只迭代加载我们需要的数据。

我们的数据集(右)被分成几批。在任何时候,只有一个批次被载入内存。然后,活动批次被转换并输入到模型中进行训练。
在这个例子中,我们将使用 IMDB 电影评论数据集。你可以从 Kaggle 这里下载。

来自 train.tsv 数据的前四行。
我们的训练数据包含在train.tsv中,我们将使用它来训练一个情感分类器。为此,我们需要将包含在Content中的文本作为我们的输入特征,将Sentiment作为我们的目标标签。我们不需要任何其他列。
dataset = tf.data.experimental.make_csv_dataset(
"train.tsv",
batch_size=8,
field_delim='\t',
select_columns=['Phrase', 'Sentiment'],
label_name='Sentiment')

2 和 3 显示一批八个短语和情感样本。编号 1 是 PhraseId ,它被添加到 select_columns 中,以表明数据在默认情况下是混洗的。
通过这种方法,我们可以轻松地将存储在内存中的数据保持在较低水平,并且仍然可以轻松地洗牌和批量处理数据——这是一个非常方便的选择。
基本操作
现在我们已经讲述了读写数据集对象的基础知识;我们可以开始转换加载的数据集。
批处理和洗牌
当从文件中读取时,不需要这些操作,因为它们是内置的,可以读取像tf.data.experimental.make_csv_dataset这样的函数——但是当我们从内存中构建数据集时,这种情况不会发生。
幸运的是,这仍然非常简单。我们给shuffle一个大数字(10000很常见)作为参数,给batch我们的训练批量:
dataset = dataset.shuffle(10000).batch(64)
只需这一行代码就可以对我们的数据集进行洗牌和批处理!
使用地图进行数据转换
我们可以使用map函数对 xour 数据集中的每个样本执行操作。例如,为了预测序列中的下一个时间步,我们可能需要训练输入数据,输入数据由时间步 n 到 n+8 组成,输出数据由时间步 n+1 到 n+9 组成。

最初,我们的数据由包含代表 10 个时间步长的 10 个元素的记录组成。在基于时间的预测中,我们通常将这些序列分成输入(X)和目标(y)数据,如图所示。我们可以使用 map 方法来做到这一点。
最初,我们的数据集可能由许多包含 10 个时间步序列的样本组成。为了训练我们的模型,我们需要将这些 10 长的序列分成两组 9 长的序列,一组是输入数据,另一组是我们的目标数据。
为了执行这个操作,我们使用了map方法,就像这样:
def Xy_split(x):
X = x[:-1] # [0, 1, 2, 3, 4, 5, 6, 7, 8]
y = x[1:] # [1, 2, 3, 4, 5, 6, 7, 8, 9]
return X, ydataset = dataset.map(Xy_split)

我们可以根据需要使用 map 方法来拆分或重新格式化我们的数据。
将数据集输入模型
当把我们的数据集输入到训练模型中时,默认的格式是(input, output)。这意味着数据集中包含的每个记录/批次都应该包含输入张量和标签/输出张量。
使用这种格式,我们可以将数据集对象传递给我们的训练方法,如下所示:
model.fit(dataset, epochs=2)
多输入/输出
单一输入/输出格式并不总是我们需要使用的格式。对于任何重组,我们都可以再次依赖map方法。
我们可以通过将数据集映射到字典格式来映射多个输入和输出,在字典格式中,我们的输入名称(键)指向我们将使用的一组值(值)。
如果我们将输入/输出层名称匹配到输入/输出数据集字典键,我们可以像往常一样将dataset传递给我们的模型!
*# current dataset format is (inputs1, inputs2, labels)*def map_func(x):
return {
**'inputs1'**: x[0],
**'inputs2'**: x[1]
}, x[2]dataset = dataset.map(map_func)input_layer_1 = tf.keras.layers.Input(shape=(100,), name=**'inputs1'**)
input_layer_2 = tf.keras.layers.Input(shape=(100,), name=**'inputs2'**)
一个常见的用例是为 transformer 模型创建两个输入层。许多这些模型需要一个输入 ID 张量和相应的注意屏蔽张量,我们可以使用相同的逻辑:
def transformer_fmt(x):
return {
**'input_ids'**: x[0],
**'attention_mask'**: x[1],
}, x[2] *# x[2] are the output labels*dataset = dataset.map(transformer_fmt)input_ids = tf.keras.layers.Input(shape=(100,), name=**'input_ids'**)
mask = tf.keras.layers.Input(shape=(100,), name=**'attention_mask'**)...model.fit(dataset, epochs=2)
训练-验证分割
这里的另一个要点是训练集和验证集(测试集)的分离。在数据集中实现拆分的最简单方法是使用take和split方法。
为了获取给定数量的记录,我们使用take——就像这样:
first5 = dataset.take(5)
然后,我们可以使用skip跳过给定数量的记录,返回以下所有记录——如下所示:
miss5 = dataset.skip(5)
结合这两种方法,我们可以在数据中创建一个分割。例如,对于 70–30%的培训验证分割,我们会:
train = dataset.take(round(length*0.7))
val = dataset.skip(round(length*0.7))
并创建另一个分割来添加测试集。
当我们将训练集和验证集输入到我们的训练模型中时,我们是这样做的:
history = model.fit(
train,
validation_data=val,
epochs=2)
我们已经介绍了如何使用数据集对象在 TF2 构建更干净、更高效的数据输入管道!包括:
- 它们是什么以及我们为什么要使用它们
- 将内存中的数据加载到数据集
- 从文件读入数据集
- 批处理和洗牌
- 使用
map转换数据集 - 将数据集输入模型
- 如何处理多个输入/输出层
- 列车价值测试拆分
这就是我们需要知道的大部分 ML 输入管道。由于清晰高效的tf.data API,我们所做的一切都非常容易执行,而且快如闪电。
我希望你喜欢这篇文章!如果你有任何问题或想法,请通过推特或在下面的评论中告诉我。
感谢阅读!
🤖《变形金刚》NLP 课程 70%的折扣
10 分钟内在 Heroku Cloud 上构建和部署垃圾邮件分类器应用程序!
垃圾邮件分类器的构建及其在 Heroku 上的应用

查尔斯·德鲁维奥在 Unsplash 上拍摄的照片
今天我们将构建一个简洁的垃圾邮件分类器,一个基于自然语言处理的模型。然后,我们将构建一个 flask 应用程序,它将呈现一个基于 HTML 的主页和一个预测页面。用户将在主页中输入文本,应用程序将在预测页面上预测它是否像垃圾邮件或 Ham(非垃圾邮件)。这个 flask API 将部署在 Heroku 上的公共主机中。Heroku 是这里显而易见的选择,因为它超级快,超级容易。我说过它是免费的吗?是的,它是!先自己检查并使用这个应用程序这里以了解你将构建什么。
现在你已经看到了,让我们开始吧!
模型
第一步将是建立我们的 NLP 模型,从用户那里获取自然文本,并预测它是垃圾邮件还是垃圾邮件(不是垃圾邮件)。我们将通过几段 python 代码来实现这一点。我的 Github 上有完整的代码和数据集。首先,让我们导入所有需要的库。
import pandas as pd #Pandas for data pre-processing
import pickle #Pickle for pickling (saving) the model
from sklearn.feature_extraction.text import CountVectorizer #To Vectorize the textual data
from sklearn.naive_bayes import MultinomialNB #The algorithm for prediction
from sklearn.externals import joblib #Alternative Usage of Saved Model
from sklearn.model_selection import train_test_split #Validation split
接下来,我们需要加载数据,并分成文本数据(X)和标签(y)。
df = pd.read_csv("spam.csv", encoding="latin-1")
df.drop(['Unnamed: 2', 'Unnamed: 3', 'Unnamed: 4'], axis=1, inplace=True) #Some garbage features that need to be removed
# Text and Labels
df['label'] = df['class'].map({'ham': 0, 'spam': 1})
X = df['message']
y = df['label']
现在我们需要使用计数矢量器对文本数据进行矢量化(将文本转换为数字形式)。然后只需拆分训练和测试数据。没有考虑进一步的文本预处理,因为我们的目标是快速构建模型并部署它。可以自己试验一下文字清理部分,让性能更好。
# Extract Feature With CountVectorizer
cv = CountVectorizer()
X = cv.fit_transform(X) # Fit the Data
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=42)
一旦完成,我们只需要拟合模型,并将其保存为 pickle 文件,稍后将加载到 flask 应用程序中。
#Naive Bayes Classifier
clf = MultinomialNB()
clf.fit(X_train,y_train)
print(clf.score(X_test,y_test))
#Alternative Usage of Saved Model
joblib.dump(clf, 'NB_spam_model.pkl')
joblib.dump(cv, 'cv.pkl')
请注意,我们已经保存了朴素贝叶斯模型和计数矢量器。这是因为对于您来说,从用户处获取的文本输入必须使用与模型训练时相同的计数矢量器参数进行矢量化。好了,现在我们有了模型和矢量器。
接下来,我们需要构建 flask 应用程序,它将把我们刚刚构建的 NLP 模型连接到我们的浏览器,然后在云上托管它。
烧瓶应用程序
只要用户访问应用程序的 URL,flask 应用程序就会将用户路由到主页。稍后,当用户输入文本并点击预测按钮时,它会将其重定向到预测页面并呈现输出。让我们看看它是怎么做的。
我们需要导入 flask 和其他一些功能。如果您还没有安装 flask,那么您需要通过一个简单的 pip install 命令来安装它。
from flask import Flask, render_template, request
这里, Flask 将用于定义我们正在使用的 app。然后 render_template 会渲染首页(home.html)和预测页面(result.html)。并且请求将被用于检索文本输入,该文本输入将通过 HTML Post 方法从 HTML 页面发送到 flask 应用程序。
现在我们需要定义 flask 应用程序及其到主页的默认路由,即 home.html。我们将定义一个函数,当应用程序 URL 被调用时,该函数除了显示主页之外什么也不做。
app = Flask(__name__)
@app.route('/') #Routes the app to below task when the URL is called
def home():
return render_template('home.html')
现在是应用程序的主要部分,预测。我们需要定义一个函数来打开和加载 NLP 模型,并对矢量器 pickle 文件进行计数。然后,它检索通过 POST 方法发送给它的文本输入。然后,使用相同的矢量器对检索到的文本输入进行矢量化,并转储到我们的模型中以获得预测。就是这样!我们现在只需要在预测页面上呈现这个预测结果,我们就完成了。
def predict_fun():
NB_spam_model = open('NB_spam_model.pkl','rb')
clf = joblib.load(NB_spam_model)
cv_model = open('cv.pkl', 'rb')
cv = joblib.load(cv_model)
if request.method == 'POST':
message = request.form['message']
data = [message]
vect = cv.transform(data).toarray()
my_prediction = clf.predict(vect)
return render_template('result.html',prediction = my_prediction)
#Calling the main function and running the flask app
if __name__ == '__main__':
app.run(debug=True)
我们的模型和烧瓶应用程序已经完成。我们现在只需要在 Heroku 上部署这些文件。
部署
要在 Heroku 上部署应用程序,您需要将所有链接到 Heroku 的文件推送到 Github 上。您需要将以下文件上传到您的存储库:
- NLP 模型泡菜
- 计数矢量器泡菜
- 烧瓶应用程序
- HTML 和 CSS 文件
- 需求文件
- Procfile
好的,你可能想知道什么是需求和 procfile 文件。需求是一个文本文件,其中包含所有的依赖关系(如熊猫,烧瓶等库。)以及应用程序按预期运行所需的版本。Heroku 将在部署应用程序之前安装所有这些依赖项。Procfile 是一个配置文件,看起来类似于:
web: gunicorn app1:app
这里的“app1”是我的 flask 文件名,即“app 1 . py”,“app”是我们在上面的代码中定义的 flask 应用程序。这只是告诉 Heroku 查找名为 app1 的 flask 文件,并在其中查找定义为“app”的 flask 应用程序。
一旦你把所有的文件推送到一个新的 github 库,你需要在 Heroku 上创建一个应用程序,并把你的 github 库连接到它。要做到这一点,只需前往 Heroku 。如果您还没有帐户,请创建一个帐户,然后转到“创建新应用程序”。

创建新应用程序
在新创建的应用程序中,您需要连接到包含代码的 github 存储库。在搜索框中搜索 github 库名称,然后点击“连接”按钮。

将 Github 存储库连接到 Heroku

Github 已连接
一旦连接,你只需要点击“部署”按钮,你就完成了!Heroku 将首先检查需求文件并安装所有依赖项,然后将 flask 应用程序部署到公共主机。将生成一个 URL,它是您的应用程序的 URL。只需复制并在浏览器中打开它,瞧!你完了。

点击部署!
这就是本教程的内容。希望你让应用程序运行,并得到体面的结果!

输入一些“spamish”测试

在那里!
如果你已经走了这么远,并准备好了应用程序,给自己一个鼓励。你应得的!
所以我们在这里使用了 Heroku Cloud,因为它安装起来很快也很容易。然而,我鼓励你也尝试在其他云平台上部署该应用程序——如 AWS EC2、谷歌云平台和 Azure。
请随意从我的 github 获取源代码,如果有任何疑问和建议,请在 LinkedIn 上联系我。
下一篇帖子再见,干杯!
使用 Flask、ML 和 Heroku 构建和部署糖尿病预测应用程序
从训练模型到在 Heroku 上部署模型的端到端机器学习项目

照片由 CHUTTERSNAP 在 Unsplash 上拍摄
欢迎我的朋友,
根据美国消费者新闻与商业频道的说法,未来十年最时尚的工作是数据科学家和机器学习工程师。现在是我们学习一些机器学习算法,创造一些项目扔出去的最好时机。
你经常看到所有那些教程和博客解释不同类型的机器学习算法,但大多数都没有告诉你如何构建一个项目,然后使用这些算法部署它。
不要担心,在这个博客中,我们将创建一个端到端的机器学习项目,然后将它部署在 Heroku。
我们将分四步完成它
- 使用机器学习创建模型
- 使用 flask 创建 web 应用程序,并将其与模型 连接
- 将项目提交给 Github
- 使用 Heroku 部署我们的模型
在开始之前,让我们先
设置我们的环境
- 下载最新版 Python
关于特定端口的信息、开发人员信息来源和二进制可执行文件由发布经理或……
www.python.org](https://www.python.org/downloads/)
- 安装所需软件包
所有软件包都可以使用 cmd(终端)中的 pip 进行安装。
pip install pandas,numpy,matplotlib,scikit-learn,seaborn
- 安装 Jupyter 笔记本
pip install jupyter-notebookjupyter notebook ### for running
完成所有三个步骤后,现在让我们开始我们的项目。
在 jupyter 中打开一个新的笔记本,按照下面的步骤沿着
1.使用机器学习创建模型
导入必要的库
#importing Librariesimport numpy as np
np.random.seed(42) ## so that output would be same
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
%matplotlib inline ## our plot lies on the same notebook#models
from sklearn.ensemble import RandomForestClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.svm import SVC#Evaluation
from sklearn.model_selection import train_test_split,cross_val_score
from sklearn.model_selection import RandomizedSearchCV,GridSearchCV
from sklearn.metrics import confusion_matrix, classification_report
from sklearn.metrics import precision_score, recall_score, f1_score
from sklearn.metrics import plot_roc_curve#for warning
from warnings import filterwarnings
filterwarnings("ignore") ## To remove any kind of warning
加载数据集
数据集在 Kaggle 上可用,但我们将使用我的 Github 链接来加载数据。
data = pd.read_csv("[https://raw.githubusercontent.com/Abhayparashar31/Diabetes-prediction/master/diabetes.csv](https://raw.githubusercontent.com/Abhayparashar31/Diabetes-prediction/master/diabetes.csv)")
关于数据集
数据集由几个医学预测变量(独立变量)和一个目标变量(因变量)组成,结果。独立变量包括患者的怀孕次数、身体质量指数、胰岛素水平、年龄、
等。
列
怀孕 : 怀孕次数
血糖 : 口服葡萄糖耐量试验 2 小时血糖浓度
血压 : 舒张压(毫米汞柱)
皮肤厚度 : 三头肌皮褶厚度(毫米)
胰岛素 : 2 小时血清胰岛素(胰岛素
年龄: 年龄(年)
结局: 类变量(0 或 1)768 中的 268 为 1,其余为 0
工作
建立机器学习模型,准确预测数据集中的患者是否患有糖尿病?
数据集上的 EDA
print(data.shape) ### Return the shape of data
print(data.ndim) ### Return the n dimensions of data
print(data.size) ### Return the size of data
print(data.isna().sum()) ### Returns the sum fo all na values
print(data.info()) ### Give concise summary of a DataFrame
让我们将一些列可视化并进行比较
data["Outcome"].value_counts().plot(kind="bar",color=["salmon","deeppink"])
plt.xticks(np.arange(2), ('No Diabetes', 'Diabetes'),rotation=0);

作者图片
***# Comparing Glucose with the Outcome***
pd.crosstab(data.Glucose[::15],data.Outcome).plot(kind="bar",figsize=(18,8),color=["yellow","deeppink"])
plt.ylabel("people");
plt.xticks(rotation=0);
plt.legend(['No Diabetes', 'Diabetes']);

“作者提供的图像”
***#find out Blood Pressure and age of entries who have diabetes***
plt.figure(figsize=(10,6))# Scatter with positive example
plt.scatter(data.Age[data.Outcome==1],data.BloodPressure[data.Outcome==1],c="Red");# Scatter with negative example
plt.scatter(data.Age[data.Outcome==0],data.BloodPressure[data.Outcome==0],c="lightblue");# Add some helpful info
plt.title("Diabetes in function of Age and Blood pressure")
plt.xlabel("Age")
plt.ylabel("Blood Pressure")
plt.legend(["Diabetes","No Diabetes"]);

“作者提供的图像”
***## Pairplotting of dataframe***
import seaborn as sns
sns.set(style="ticks", color_codes=True)
sns.pairplot(data,hue='Outcome',palette='gnuplot');

“作者提供的图像”
***# Histogram of all coloumns when the Outcome is 1( has Diabetes)***fig, ax = plt.subplots(nrows=4, ncols=2, figsize=(12, 10))
fig.tight_layout(pad=3.0)
ax[0,0].set_title('Glucose')
ax[0,0].hist(data.Glucose[data.Outcome==1]);
ax[0,1].set_title('Pregnancies')
ax[0,1].hist(data.Pregnancies[data.Outcome==1]);
ax[1,0].set_title('Age')
ax[1,0].hist(data.Age[data.Outcome==1]);
ax[1,1].set_title('Blood Pressure')
ax[1,1].hist(data.BloodPressure[data.Outcome==1]);
ax[2,0].set_title('Skin Thickness')
ax[2,0].hist(data.SkinThickness[data.Outcome==1]);
ax[2,1].set_title('Insulin')
ax[2,1].hist(data.Insulin[data.Outcome==1]);
ax[3,0].set_title('BMI')
ax[3,0].hist(data.BMI[data.Outcome==1]);
ax[3,1].set_title('Diabetes Pedigree Function')
ax[3,1].hist(data.DiabetesPedigreeFunction[data.Outcome==1]);

“作者提供的图像”
***# correlation matrix between columns***
***## It shows the correlation(positive,neagative) between different columns(only integer value columns)*** corr_matrix = data.corr()
fig,ax = plt.subplots(figsize=(15,10))ax = sns.heatmap(corr_matrix,annot=True,linewidth=0.5,fmt=".2f",cmap="YlGnBu")

“作者提供的图像”
建模和培训
#random data shuffelindata.sample(frac=1)#Spliting the data
X = data.drop("Outcome",axis=1)
y = data["Outcome"]
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2)
我们将在 4 个算法
1 上训练我们的模型。逻辑回归
2。KNN
3。随机森林分类器
4。支持向量机**
***## Build an model (Logistic Regression)***
from sklearn.linear_model import LogisticRegression
log_reg = LogisticRegression(random_state=0)
log_reg.fit(X_train,y_train);
## Evaluating the model
log_reg = log_reg.score(X_test,y_test)***## Build an model (KNN)*** knn = KNeighborsClassifier()
knn.fit(X_train,y_train);
## Evaluating the model
knn = knn.score(X_test,y_test)***## Build an model (Random forest classifier)*** clf= RandomForestClassifier()
clf.fit(X_train,y_train);
## Evaluating the model
clf = clf.score(X_test,y_test)***## Build an model (Support Vector Machine)*** svm = SVC()
svm.fit(X_train,y_train)
## Evaluating the model
svm = svm.score(X_test,y_test)
让我们想象一下所有模型的训练表现
model_compare = pd.DataFrame({"Logistic Regression":log_reg,
"KNN":knn,
"Random Forest Classifier":clf,
"Support Vector Machine":svm,},
index=["accuracy"])model_compare.T.plot.bar(figsize=(15,10));##############OUTPUT###############
Logistic Regression KNN Random ForestClassifier SVM
accuracy 0.818182 0.772727 0.798701 0.818182

“作者提供的图像”
在这里,我们可以看到 SVM 和逻辑回归都表现得非常好,准确率为 81%。我们可以使用超参数调整来进一步提高精度。
使用超参数调谐提高精度
我们将使用网格搜索 cv 和随机搜索 cv 进行超参数旋转。
在逻辑回归中,我们很容易超调的参数是C和solver。
使用随机搜索进行超参数调整
# Create a hyperparameter grid for LogisticRegression
log_reg_grid = {"C": np.logspace(-4, 4, 20),"solver": ["liblinear"]}# Tune LogisticRegression
np.random.seed(42)
# Setup random hyperparameter search for LogisticRegression
rs_log_reg = RandomizedSearchCV(LogisticRegression(),
param_distributions=log_reg_grid,
cv=5,
n_iter=20,
verbose=True)
# Fit random hyperparameter search model for LogisticRegression
rs_log_reg.fit(X_train, y_train)
score = rs_log_reg.score(X_test,y_test)
print(score*100)##########OUTPUT###########
83.11688311688312
太好了,使用随机搜索 cv,我们将准确率提高了 2%。
使用 GridSearchcv 进行超参数调整
log_reg_grid = {'C': np.logspace(-4,4,30),"solver":["liblinear"]}
#setup the gird cv
gs_log_reg = GridSearchCV(LogisticRegression(),
param_grid=log_reg_grid,
cv=5,
verbose=True)
#fit grid search cv
gs_log_reg.fit(X_train,y_train)
score = gs_log_reg.score(X_test,y_test)
print(score*100)########OUTPUT#########
83.76623376623377
太好了,使用网格搜索 CV,我们将准确率提高了 2.5%。
最佳模型是逻辑回归,准确率为 83%
评估模型
先来预测一下 X_test
y_preds = gs_log_reg.predict(X_test)
y_preds######OUTPUT#########
array([0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0,0,0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0,0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1,0, 0],dtype=int64)
让我们看看混淆矩阵、准确率评分、分类报告、roc 曲线。
混淆矩阵
sns.set(font_scale=2)
import seaborn as sns
sns.heatmap(confusion_matrix(y_test,y_preds), annot=True,cbar=False, fmt='g')
plt.xlabel("True label")
plt.ylabel("Predicted label");
准确度分数
print(accuracy_score(y_test,y_pred))#######OUTPUT########
0.8376
分类报告
print(classification_report(y_test, y_preds))
ROC 曲线
plot_roc_curve(gs_log_reg,X_test,y_test)
保存并加载模型
import pickle
# Save trained model to file
pickle.dump(gs_log_reg, open("Diabetes.pkl", "wb"))loaded_model = pickle.load(open("Diabetes.pkl", "rb"))
loaded_model.predict(X_test)
loaded_model.score(X_test,y_test)#######OUTPUT########
0.8376623376623377
2.使用 flask 创建 web 应用程序并将其与模型连接
因此,要创建一个 web 应用程序,让我们准备一个文件夹结构
diabetes(root)
|____templates
|___index.html
|____static
|____css
|_____js
|____app.py
|_____Diabetes.pkl
从我的 Github 下载模板和静态目录
github.com](https://github.com/Abhayparashar31/Diabetes-prediction)
让我们创建 app.py
现在让我们在本地主机上运行代码
打开 CMD 并转到根(糖尿病)文件夹,然后使用python app.py运行 app.py,然后您会看到如下消息👇

“作者提供的图像”
只需在任何浏览器中打开网址,使用一些随机输入来测试应用程序。
3.将项目提交给 Github
在将项目提交给 Github 之前,我们还要创建两个文件。
1。Profile: Heroku 应用程序包含一个 Procfile,它指定了应用程序在启动时执行的命令。
web: gunicorn app:app
2。requires . txt:要求。txt 文件用于指定运行项目所需的 python 包。
Flask==1.1.1
gunicorn==19.9.0
itsdangerous==1.1.0
Jinja2==2.10.1
MarkupSafe==1.1.1
Werkzeug==0.15.5
numpy>=1.9.2
scipy>=0.15.1
scikit-learn>=0.18
matplotlib>=1.4.3
pandas>=0.19
现在之后,去你的 Github 账户上传文件,然后提交给分支机构。

“作者提供的图像”
4.使用 Heroku 部署模型
访问 Heroku 并创建一个免费帐户,然后登录您的帐户。

“作者提供的图像”

“作者提供的图像”
你可以在我的 Github 简介 Abhayparashar31 中找到所有的源代码
谢谢你的阅读😄
感谢你读到这里,如果你喜欢我的内容并想支持我,最好的方式是—
使用 Azure ML Studio 构建和部署机器学习模型
没有代码?没问题!

我有时会对数据科学和机器学习中大量的锅炉代码感到困惑。在寻找一个可以加速训练和部署模型过程的解决方案时,我偶然发现了微软的 Azure ML Studio,天哪,我没有失望。
您可能想尝试的其他工具
在无代码机器学习领域,有几个值得注意的竞争者:
我将在一系列文章中深入探讨每一个问题,最后进行逐点比较。我将使用这个 Kaggle 数据集,来自一个旧的比赛,目标是预测一辆拍卖的汽车是否是一辆“被踢”(即一辆受损的汽车)。
今天,我们从 Azure ML Studio 开始。
构建机器学习管道
Azure ML Studio 中的主要区域是实验画布。左边是按用途分组的模块,您可以将任何模块拖到主画布上。画布的右侧用于显示当前选择的任何模块的属性,或者定制它的一些参数。

每个模块都预定义了一些输入和输出端口。这些端口中的每一个都有一个类型,当您将鼠标悬停在其上时,它会显示为一个工具提示。当您想知道预期的输入类型时,这非常有用。
在 Azure ML Studio 中,我们通过连接模块来构建机器学习管道:一个模块的输出成为管道中下一个模块的输入之一。
我们可以有顺序管道和并行管道,其中一个输出被重定向到多个输入,只要输入和输出的类型兼容。
例如,在下图中,我们看到数据集模块的输出是 GenericCSV 类型。

下一个模块有一个输入,预计是 Dataset 类型,它有许多实现或子类,其中一个是 GenericCSV 所以我们可以把前一个输出连接到这个输入。

此外,当我们从一个输出向下拖动到下一个模块的输入时,如果输入点与我们试图连接的输出兼容,它就会变成绿色。
ML 管道的基本构件
任何 ML 管道基本上都有 7 个阶段:
- 预处理您的数据
- 分成训练/测试
- 选择和/或创建您的特征
- 训练模特
- 做预测
- 评估模型 7
- 部署选定的模型
每个阶段都映射到 Azure ML Studio 中的一组模块。
步骤 1:预处理您的数据
对于这一步,您将使用Data Transformation下的模块。两个最重要的子部分是Manipulation和Scale and Reduce。这里有足够多的种类来涵盖大多数用例:分类变量的一次热编码、连续变量的宁滨、清除缺失数据等。

让我们以其中的一个模块“清除丢失的数据”为例来探索属性面板。在这里,我们被要求选择哪些列要用作清理的候选列,执行清理的最小和最大缺失值比率是多少,以及最后我们希望如何处理缺失值。有几个选项可用:

如果我们需要模块中没有的功能,我们可以使用“应用 SQL 转换”模块来运行任意 SQL 代码,我们可以直接在嵌入在属性面板中的编辑器中输入这些代码。注意,这个模块有 3 个输入端口,这意味着我们可以用这个模块处理多达 3 个数据集,在 SQL 代码中称为 t1、t2 和 t3。

步骤 2:分成训练/测试
这里我们有两个选择:
- 如果我们想要进行典型的训练/测试分割,我们将使用“分割数据”模块,它接受一个输入并产生两个输出(训练和测试)。在这种情况下,我们可以选择训练/测试比率,以及是否需要分层分割。其他拆分模式也是可用的,比如
Regular Expression如果我们想要使用一个列的值来执行拆分。

- 我们可以使用的另一个模块是“Partition and Sample”,如果我们只想从原始数据集中对一些数据进行采样,或者如果我们想执行交叉验证并指定要使用的折叠数,这将非常有用。
步骤 3:选择和/或创建您的特征
要创建新的特性,您将遵循与数据预处理相似的过程,并使用几乎相同的模块。一个区别是最好在分割数据后创建你的特征,只在训练数据上。对于测试数据,您必须找到一种方法来应用类似的转换,仅使用来自训练数据的信息,或者更好的是,您可以使用“应用转换”模块来重用使用训练数据创建的转换。下面是该过程的一个简单示例:

在上面的示例中,我们对训练数据中的列进行宁滨,仅使用在训练数据中找到的值来选择箱的边缘。然后,我们将这些容器应用于测试数据。
这个过程避免了信息泄漏,如果我们在分割数据之前创建了桶,就会发生信息泄漏,因为在这种情况下,我们会使用来自测试数据的信息来训练我们的模型。
对于特性选择,Azure ML 提供了三个选项,最常用的两个是“基于过滤器的特性选择”和“排列特性重要性”。前者在训练模型之前使用,并基于用户选择的指标,如预测值和目标值之间的相关性或互信息,而后者需要训练好的模型,并基于随机交换每个特征中的值后该模式的性能下降多少来选择特征。
步骤 4–5–6:训练、评分和评估您的模型
任何机器学习项目的面包和黄油,在 Azure ML Studio 中,你可以训练许多类型的模型。这些可以在“初始化模型”组下找到:

你会发现所有常见的疑点:逻辑回归、决策树、随机森林、提升树和神经网络。对于分类,支持 2 类和多类模型。
Scoring在 Azure ML 术语中的意思是“做出预测”。您可以选择仅输出预测(在分类的情况下,您将拥有预测的概率和预测的类)或向输出追加预测列。
当您可视化“评估模型”模块的输出时,您将看到的指标将取决于所使用的模型类型。对于回归,您将看到平均绝对误差(MAE)、均方根误差(RMSE)等。对于分类,您将看到 AUC 和 logloss,并且您将有一个可以用来查看混淆矩阵、精确度和召回率、准确度等的阈值。
“评估模型”有两个输入,允许您将两个模型相互比较,看哪一个表现最好。下面是一个包含两种分类模型的示例:

如果你想同时比较两个以上的模型,你必须使用几个“评估模型”模块。
步骤 7:部署选定的模型
这里蔚蓝真的闪闪发光。在一个模型被训练之后,部署它实际上只需要点击 3 次。
- 单击您想要部署的模型的“Train Model”模块,然后单击“Deploy Web Service”。
- 然后您将有机会编辑您的实验,包括 Web 服务输入和输出,然后您可以在部署之前最后一次运行它。
- 点击“部署”后,您将进入如下屏幕:

现在…信不信由你,你的模型已经部署好了,可以工作了!您有一个 API 键,可以用来以编程方式调用端点(要查看端点的 URI,您必须单击请求/响应链接)。更重要的是,你可以下载一个预先配置好的 Excel 文件,在这里你只需点击一个按钮就可以调用模型,并直接在 Excel 中进行预测。
不幸的是,在我写这篇文章的时候,我的 Azure 机器学习插件没有工作。这是第一次发生在我身上,我有一种感觉,这是因为我用另一个 outlook 电子邮件登录。今天早上我还没能修复这个问题,由于我没有收到任何错误消息(Azure 机器学习插件只是停留在加载模式),我很难调试它。就像微软的许多事情一样,当它起作用的时候,它就很棒。但是有百分之一的时间不会…你会有一些痛苦!
尽管如此,我坚持认为一个非技术人员可以轻松地部署和服务一个模型是令人震惊的。上述 Excel 文件可以与您希望授予其模型访问权限的任何人共享。
附加注释
到目前为止,我们一直在谈论 Azure ML Studio (classic),虽然上述部署模式只是为了测试/调试,但微软已经推出了Azure Machine Learning designer(preview),这是 ML Studio 的一个类似但改进很多的版本,具有企业级可扩展性和安全性以及其他好处。
另外值得一提的是,我们上面所做的一切,也可以通过使用专用的 API,通过 python 中的编码来完成。
最后,虽然这篇文章的目的是展示不编码可以做什么,但是如果你想更进一步,你可以很容易地连接一个 R 或 Python 组件,在那里你可以执行任意代码,甚至在需要时使用你的模块。输入和输出都应该是数据帧。
裁决
我喜欢这个产品,并会用它来构建一个商业产品。我还没有测试过新的 Azure ML 设计器,但这在我的任务清单上。假设我可以对我部署的解决方案进行细粒度的控制,我相信通过避免通常的锅炉板代码,可以大大减少生产的总时间。
请随意尝试,并与我分享你的观点。
使用 Kibana 构建动态可视化和仪表板,以便使用 Twitter Feeds 进行数据分析
使用 Python 和 ELKstack 的 OSINT 第 2a 部分]

作者图片:使用https://www.wordclouds.com/生成
获得同步
< 上一个故事|【x】当前
在第 1 部分我们:
- 使用 ELKSTACK (Elasticsearch,Logstash,Kibana)的容器化版本构建我们的基础设施
- 探索并构建了一个使用 API 访问 Twitter 的 python 脚本
- 将收集的数据转移到 Elasticsearch 进行分析
在第 2 部分中,我们将使用 Kibana 探索我们摄入到 Elasticsearch 中的数据。
在写这部分的时候,我意识到这将是一个巨大的话题。在浏览 EDA 的时候,我发现了许多有用的工具和技术,可以用来加速这个过程。我将把第 2 部分分成多个小节。这一小节将重点介绍初始 EDA 和用 Kibana 构建简单的可视化。接下来的部分将重点关注使用机器学习清理数据,并利用其他 API 来帮助我们回答一些问题。在这个过程中,我们可能会遇到更多的问题。
因为代码变得比我预期的要大。我取出了一些不必要的东西。我把馈电简化为弹性函数:
**while** count **<** len(feed):
doc **=** {
'@timestamp': dt.now(),
'created_at': str(feed[count]['created_at']),
'twitter_id' : int(feed[count]['id']),
'id_str' : int(feed[count]['id_str']),
'full_text' : str(feed[count]['full_text']),
'truncated' : str(feed[count]['truncated']),
'display_text_range' : str(feed[count]['display_text_range']),
'entities' : str(feed[count]['entities']), *# Already split the dictionary, no longer needed*
'metadata' : str(feed[count]['metadata']),
'source' : str(feed[count]['source']),
'in_reply_to_status_id' : str(feed[count]['in_reply_to_status_id']),
'in_reply_to_status_id_str' : str(feed[count]['in_reply_to_status_id_str']),
'in_reply_to_user_id' : str(feed[count]['in_reply_to_user_id']),
'in_reply_to_user_id_str' : str(feed[count]['in_reply_to_user_id_str']),
'in_reply_to_screen_name' : str(feed[count]['in_reply_to_screen_name']),
'user' : str(feed[count]['user']), *# Already split the dictionary, no longer needed*
'geo' : str(feed[count]['geo']),
**...** [truncated]
这次清理相当有趣。我是手动操作的,但是花了很长时间。[ 非常 tedius]我不得不打开字典,提取关键字,格式化文本,这样它就会创建变量,然后调用这些变量。所以,我转而求助于 python。我必须想办法不断遍历字典和子字典来提取每个键的条目。我想要一本简单的字典,我可以用它来做统计。注意清理收集功能:
我移动了一些代码块,并把它包装在一个函数中,我可以用它来调用。我这样做是因为它在执行 try/exceptions 时提供了更好的灵活性。
这个代码块导入模块,设置服务器和 API 配置,以及对象
# Import tweepy as tw
import tweepy as tw
import sys
from datetime import datetime as dt
from elasticsearch import Elasticsearch# Initializing objects
twitter_cred = dict()
api = ''
es = ''def setConfig(server):
# Import keys from a saved file instead of inputting it directly into the script.
# Strip whitespaces and split on = as I only want the key values
# Server argument is the elasticsearch node
key_location = 'twitter.keys'
apikeys = []global api
global eswith open(key_location) as keys:
for i in keys:
apikeys.append(i.split("=")[1].strip(" ").strip("\n"))
keys.close()# Initialize dictionary
#twitter_cred = dict()# Enter API keys
twitter_cred["CONSUMER_KEY"] = apikeys[0]
twitter_cred["CONSUMER_SECRET"] = apikeys[1]# Access Tokens
twitter_cred["ACCESS_KEY"] = apikeys[2]
twitter_cred["ACCESS_SECRET"] = apikeys[3]# Set authentication object
auth = tw.OAuthHandler(twitter_cred["CONSUMER_KEY"], twitter_cred["CONSUMER_SECRET"])
auth.set_access_token(twitter_cred["ACCESS_KEY"], twitter_cred["ACCESS_SECRET"])# Create api object with authentication
api = tw.API(auth, wait_on_rate_limit=True)# Set Elasticsearch Server
es = Elasticsearch(server, port=9200)# Execute function with the elasticsearch ip address
setConfig('127.0.0.1')
拉一条推特,这样我们就可以玩唱片了
feed = {}for tweet in tw.Cursor(api.search, q='palantir OR pltr', tweet_mode='extended').items(1):
feed.update(tweet._json)
迭代字典和子字典,生成我需要的代码行
# What keys are used
parentList = []
subList = []# Add dictionaries to sub process list
def subProcess(dictionary):
subList.append(dictionary)
for item in feed.keys():
parentList.append(item)for i in parentList:
if type(feed[i]) is not dict:
print(f"{i} = feed['{i}']")
else:
subProcess(i)----- output -----created_at = feed['created_at']
id = feed['id']
id_str = feed['id_str']
full_text = feed['full_text']
truncated = feed['truncated']
display_text_range = feed['display_text_range']
source = feed['source']
in_reply_to_status_id = feed['in_reply_to_status_id']
in_reply_to_status_id_str = feed['in_reply_to_status_id_str']
in_reply_to_user_id = feed['in_reply_to_user_id']
in_reply_to_user_id_str = feed['in_reply_to_user_id_str']
in_reply_to_screen_name = feed['in_reply_to_screen_name']
geo = feed['geo']
coordinates = feed['coordinates']
place = feed['place']
contributors = feed['contributors']
is_quote_status = feed['is_quote_status']
retweet_count = feed['retweet_count']
favorite_count = feed['favorite_count']
favorited = feed['favorited']
retweeted = feed['retweeted']
possibly_sensitive = feed['possibly_sensitive']
lang = feed['lang']
使用 Kibana 进行探索性数据分析
入门指南
探索性数据分析(EDA) 是对数据进行初步调查的过程。目标是发现模式、异常值和发展假设。可以创建可视化来帮助简化这个过程。
" Kibana是一个免费的开源用户界面,让你可视化你的 Elasticsearch 数据并导航 Elastic Stack。做任何事情,从跟踪查询负载到了解请求通过应用程序的方式。”

图片来源于 elastic.co
我使用 Kibana 专门用于 EDA 和创建可视化,以便尝试和理解数据。随着我的进步,我想我会更多地使用 python pandas 和 matplotlib 来快速筛选数据。现在,我会坚持使用基巴纳。
# Code snippet will not be included in the blog to reduce the read time. This will be a supplement in my github repositoryimport tweepy as tw
import sys
from datetime import datetime as dt
from elasticsearch import Elasticsearch# Initializing objects
twitter_cred = dict()
api = ''
es = ''def acqData(search, acq):index_name = idx + dt.today().strftime('%Y-%m-%d')
feed = []
...[Truncated]
Get the source code at: [github](https://github.com/andreweng/elkstack/blob/master/projects/twitter_osint/grabTweets.py)
对于这个笔记本来说,下面的单元格是一个修改过的版本,允许我只执行函数。
try:
idx = ‘default-’
tweet_count = 100
search = ‘palantir OR PLTR’setConfig(‘127.0.0.1’)
acqData(str(search), int(tweet_count))
except:
pass---- output ----: :Acquiring Data::
: :Transferring to Elasticsearch Search::
设置基巴纳索引
太好了!我们把数据输入弹性搜索。现在,让我们为它创建一个基巴纳索引:

作者图片
1.浏览至http://127 . 0 . 0 . 1:5601>点击“自行探索”

作者图片
2.点击“堆栈管理”

作者图片
3.创建索引

作者图片
4.匹配索引模式

作者图片
5.键入“默认*”

作者图片
6.按“@时间戳”排序

作者图片
鳍状物

作者图片
单击发现

作者图片
选择“本周”
我们试图回答的最初问题是:
- 特定搜索词被转发最多的是哪些?(追踪话题热度)
- 有多少独立用户在推特上谈论一个给定的搜索词?(是趋势吗?)
- 他们还发布了哪些关于搜索词的推文?(他们是巨魔/机器人吗?)
- 这个人在搜索词上有多少个赞?(趋势/感悟)?
浏览“可用字段”时,以下字段似乎很有趣:
- 全文 _ 文本
- 语言
- 转发次数
- 用户创建于
- 用户屏幕名称
- 用户 _ 关注者 _ 计数
- 用户 _ 朋友 _ 计数
- 用户 _ 状态 _ 计数
- 用户创建于
我添加了 lang 字段,这样我可以在以后计算出每种“语言”的情感比率。目前,我正在过滤非英语。

作者图片:仅过滤英语
仅过滤英语将我的样本从 400 个减少到 262 个。
浏览全文,我看到有一堆转发,我想把它们聚合成 1 条。统计数据显示,前 5 个值是转发量,占 262 条推文的 X%。我们看到转发量最高的占 19.1%。让我们来探索一下。

作者图片
我变得超级兴奋,因为我认为这是那么容易,并找到了所有的机器人。然而,仔细一看。retweet_count 不是 user_screen_name 转发的次数。而是全文被转发的次数。


作者提供的图片
特定搜索词被转发最多的是哪些?(追踪话题热度)
浏览默认字段列表,我们看到:

作者图片
现在,让我们创建一个可视化:
点击:
>【创建可视化】>选择“数据表”>选择要在“默认*”中查找的索引>单击“添加桶”>【拆分行】>选择聚合>术语:
-字段:full_text.keyword
-将大小从 5 更改为 25
点击">更新"

作者图片
问题的答案是:“RT@ _ Whitney Webb:新文章:一个由 Palantir 驱动的秘密人工智能平台将很快从一个新的国家“智能下水道”网络获得数据,在收集期间有 50 次转发。
有多少独立用户在推特上谈论一个给定的搜索词?(是趋势吗?)
我们将通过一个饼图和一个计数器来深入研究这个问题:
可视化 >创建新的可视化>指标>默认 >指标>聚合:唯一计数>字段:用户屏幕名称.关键字>保存可视化*
可视化 >创建新的可视化>饼图>桶:拆分切片>聚合:术语>字段:user_screen_name.keyword >大小 10
可视化 >创建新的可视化>行>指标(Y 轴):计数
桶(X 轴):聚合:术语>字段:user_screen_name.keyword >大小 10
现在我们有了可视化效果,我们可以创建一个仪表板:
创建新仪表板:
-添加所有可视化效果
搜索“一个由 Palantir 驱动的秘密人工智能平台将很快从一个新的国家获得数据”

作者图片
答案是在这段时间内,有 14 个不同的用户转发了同一条消息。他们发微博的次数一样多(4),也许他们是机器人?
他们还发布了哪些关于搜索词的推文?(他们是巨魔/机器人吗?)
因为我们已经有了可视化和仪表板设置,所以我们只需将搜索标准修改为:
"purofierro666" OR "pennys_shevy" OR "nevrsurrendr" OR "eustache_luigy" OR "eric_davao" OR "Inanna432" OR "LisaMP925" OR "SultryRobin" OR "UsernameNAB" OR "WarmongerExpose"

作者图片
都是一样的转发。但是有几件事我们必须记住:
- 我们的收集脚本只获取搜索关键字,没有其他的,如果用户没有关于搜索关键字的 tweet,我们不会拿起它。
- 我的搜索时间范围很窄,我只收集了相隔几分钟的 100 条推文。
- 我不得不摆弄#tweet 计数。据报道,用户发了 4 条微博,但我似乎找不到它。
我仍然会将此列为未回答,因为我们收集脚本的限制以及我们处理的方式
这个人在搜索词上有多少个赞?(趋势/感悟)?
查看这些数据,看起来我必须调整脚本来接受额外的元数据。这个问题仍然没有答案。这甚至可能不相关。我添加这个问题是为了检测潜在的僵尸工具,并对僵尸网络进行链分析。但我不知道这是否会如我所愿。
离别的思绪
在我最初的问题中,我能够明确地回答我所在时间段的 4 个问题中的 2 个。我发现我遗漏了一些我可能需要的字段,并且一些问题可能不相关。一旦我建立了可视化和仪表板,我可以修改搜索参数,所有的可视化将更新。Kibana 可以快速有效地可视化数据。
第 2b 部分将回到脚本,看看我们可以修改和调整哪些内容,以获取更多信息并进一步丰富记录。
在几分钟内构建、评估和解释您自己的线性回归模型

线性回归简介
回归是我们作为数据科学家利用的这么多统计分析和机器学习工具的核心。
简而言之,我们利用回归技术通过 X 的某些函数来模拟 Y。导出 X 的函数通常严重依赖于线性回归,并且是用户解释或预测的基础。
让我们深入研究一下,用一些数值解释变量,x,来模拟一些数值变量 Y。
带有数字解释变量的回归
我从 kaggle 下载了一份房价数据。你可以在这里找到:【https://www.kaggle.com/shree1992/housedata/data】T4
下面你会看到一个房子的居住面积和价格之间的散点图。
除了散点图之外,我还画了一条回归线。稍后会有更多的介绍。
housing %>%
ggplot(aes(x = sqft_living, y = price)) +
geom_point() +
geom_smooth(method = "lm", se = FALSE)

上面你可以看到这两个数据点确实是相关的,但是你也会注意到趋势线正好穿过这些数据点的中间。
让我们谈谈回归是如何工作的,在这种情况下,普通最小二乘回归(OLS)是如何工作的。
我们现在看到的是一条线,一条有 y 轴截距和斜率的线。说到斜坡,你也可以想到上升超过运行!
现在我想强调的是,有一个目标函数决定了这条线的位置。
线将被放置在离线和周围数据点的绝对距离最小的地方。换句话说,如果你把 y 轴截距提高一点,或者增加直线的斜率,那么实际值和预测值之间的绝对距离就会增加。因此,有理由将线放在组的正中间,那里误差最小。
相关性与因果性
现在,我们已经观察到了两个正相关的变量之间的关系。
说了这么多,我们能得出 x 导致 y 的结论吗?肯定不是!如果你从大学的统计数据中记住了这一点,给自己一个鼓励。显然,可能有许多其他因素在起作用。
为了调用通用建模框架的概念,当我们构建一个线性模型时,我们正在创建一个线性函数或一条线。
这条线的目的是让我们解释或预测。
无论是哪种情况,建模一条线都需要一个 y 截距和一个斜率。
在另一篇文章中,我谈到一般的建模框架是 Y 作为 X+ε或误差的函数。(这里可以找到通用建模框架更详细的解释)。在直线方程的情况下,你可能会问自己ε在哪里……情况是,我们不在直线方程或线性函数中表示ε,因为模型的唯一目的是捕捉信号,而不是噪声。
解释您的回归模型输出
我们将首先运行 r 中的lm函数。该函数构建一个简单的线性模型,由您传递给它的公式决定。
y ~ x,或者在这种情况下,价格是生活平方英尺的函数。
fit <- lm(price ~ sqft_living, data = housing)

你可以在上面的输出中看到我们的调用,还有这个系数部分。
这一节突出了我们直线方程。y 截距是 12954,我们的解释变量的系数是 252。解释该系数的方式是,sqft_living每增加 1 个单位,我们应该看到price增加 252 个单位。
我的房子大约 3000 平方英尺,所以根据这条线的等式,如果你把我在西雅图的房子拆了,我们预测它的价值是 12,954 美元+252 美元*3000 美元= 768,000 美元…不用说,所有这些数据都是基于房地产市场的…我的房子远没有那么值钱。
有了这个例子,我们需要记住的一点是,我们可以依靠斜率或系数来量化 x 和 y 之间的关系。
深入你的回归输出
我们将更深入地探究你的线性模型的本质。我们将通过几种不同的方式来实现,但第一种方式是使用 r 中的经典summary函数
summary(fit)
通过如此简单的调用,我们得到了下面的回归输出。

我们从头开始吧!
首先,这个电话是有意义的。我们在残差中得到了一些统计数据,换句话说就是误差,但我们现在想深入研究一下。
接下来,我们看到的系数与之前看到的略有不同。
我想向你们指出的几件事是 R 平方和 p 值的概念……这是最常被误用的两个统计学术语。
r 平方定义为可以用 x 的变化来解释的 Y 的变化量。
p 值是统计显著性的传统度量。这里的关键要点是,p 值告诉我们给定输出可能只是随机噪声的可能性。换句话说,给定事件随机发生的可能性为 5%或更小,因此具有统计学意义。
另一个类似的输出是将我们的模型传递给moderndive包中的get_regression_table。
get_regression_table(fit)

get_regression_table作为模型的快速包装器,能够方便地显示关于我们模型的一些更重要的统计数据。
结论
希望这被证明是对线性回归的有用介绍。如何构建以及如何解读它们。
概述
今天我们有一个速成班,内容如下:
- 可视化 Y 和 X 之间的关系
- 向我们的 Y & X 可视化添加回归线
- 构建线性回归模型
- 通过 p 值或 Y 中的变化量来理解其统计显著性,从而评估所述模型,我们可以通过 x 中的变化来解释。
如果这是有用的来看看我在 datasciencelessons.com 的其余职位!一如既往,祝数据科学快乐!
构建预测模型的评估框架
时间数列预测法
关于使用 Python 预测性能指标的教程

背景
任何时间序列预测模型的目标都是做出准确的预测。流行的机器学习评估技术,如训练测试分割和 k-fold 交叉验证,在当前形式的时间序列数据上不起作用。正如我们在之前的文章中所讨论的,时间序列数据期望观察值之间的顺序依赖,而在其他机器学习数据集中,所有观察值都被平等对待。
在本教程中,我们将探讨应用于时间序列数据的各种评估技术。
目录
- 数据划分
- 常见的预测准确性衡量标准
- 天真的预测或持续模型
- 可视化残差
首先,让我们下载下面的数据集,打开一个 Jupyter 笔记本,并导入这些 python 库。
数据集— 航空公司—乘客. csv
1.数据划分
乍一看,我们可能认为最好是选择一个模型,该模型根据我们用来训练模型的现有数据生成最佳预测。当我们将该模型部署用于业务时,我们观察到预测准确性显著降低。这种情况也被称为过度拟合,这意味着模型不仅拟合数据的系统成分,还拟合噪声。
因此,预测的准确性只能通过测量拟合模型时未使用的新数据的性能来确定。
我们可以通过数据划分来解决这个过度拟合问题,这是应用任何预测方法之前的一个重要的初步步骤。
在机器学习问题中,我们通常将数据分为训练集和测试集,其中训练数据集用于构建模型,测试数据集用于评估模型性能。我们还使用这种分割的高级版本,称为 k-fold 交叉验证,其中我们系统地将数据分成 k 个组,每个组都有机会评估模型,该模型是使用剩余的 k-1 个组开发的。
这些方法不能像其他机器学习问题一样直接用于时间序列数据,这意味着我们不能随机地将数据集分成训练组和测试组。相反,我们必须将序列分成两个时间段,以保持序列的时间顺序。
使用历史数据评估时间序列预测也称为回溯测试。让我们用我们的“航空公司-乘客”数据集来讨论这些方法。
单列车-测试分离
我们可以将数据集分为训练子集和测试子集,模型可以在训练数据集上开发,其性能可以在测试数据集上评估。这可以通过基于可用时间序列的长度选择连续观察的分割点(例如 60:40、70:30 或 80:20)来完成。
例如,如果我们有一年的月度数据,并且我们想要 66.66:33.33 的分割,则前 8 个月可以用作训练,后 4 个月可以用作测试数据集。
让我们通过以下示例来理解这一点,总共有 20 个时间段,前 15 个(蓝点)可用于训练模型,后 5 个(红点)可用于验证预测准确性。

单一列车-测试分割示例
这种训练测试比例根据您的数据和业务需求而变化,围绕这种划分没有固定的规则。只是我们必须确保手头有足够的数据来训练模型。
Python 可以帮助我们快速地将这个数据集分成训练和测试子集。我们可以将拆分点指定为数组中的百分比,将拆分点之前的所有观察值作为训练数据集,并将从该点到系列末尾的所有观察值作为测试数据集。
让我们使用不同的颜色在线图上可视化这种分割,训练数据集和测试数据集分别用蓝色和橙色显示。
多重训练-测试分离
我们可以将时间序列分成多个训练和测试数据集,以训练一个集合模型来进行更稳健的估计。这种方法需要使用各自的拆分来开发多个模型。这可以通过重复上述过程来手动完成。
例如,我们有一个在 20 个时间段有 20 个观察值的数据集,我们可以创建如下 3 个不同的训练测试分割。
50:50(各 10 次观察)
60:40 (12 次和 8 次观察)
75:25 (15 次和 5 次观察)

多重训练-测试多重分割示例
这些分割可用于构建 3 个不同的模型,输出可被平均以获得稳健的预测。
在 Python 中,sci-kit-learn 库可以帮助我们使用它的 TimeSeriesSplit 函数来创建多个拆分,只需要我们指定拆分的数目。
根据 sci-kit-learn 官方页面,在每个分裂迭代(I)中,训练和测试观察的总数计算如下:
Train_size= i * n_samples // (n_splits + 1) + n_samples % (n_splits + 1)
Test_size= n_samples//(n_splits + 1)
其中“n_samples”是观察的总数,“n_splits”是分裂的总数。假设我们有 100 个观察值,想要创建 3 个分割。
让我们应用上述算法来计算训练和测试数据集的大小。
train _ size _ 1 = 1 * 100/(3+1)+100 mod(3+1)= 25
测试大小 1 = 100/(3+1) = 25
train _ size _ 2 = 2 * 100/(3+1)+100 mod(3+1)= 50
测试大小 2 = 100/(3+1) = 25
train _ size _ 3 = 3 * 100/(3+1)+100 mod(3+1)= 75
测试大小 3 = 100/(3+1) = 25
现在,我们可以在“航空公司-乘客”数据集上实现 TimeSeriesSplit 函数,并对数据集进行分区。数据集有 144 个观察值,我们想要 3 个不同的分割。根据上述计算,我们预计在各自的分割中会有以下数量的观察值。
分流 1: 36 列车,36 测试
分裂 2: 72 火车,36 测试
拆分 3: 108 次列车,36 次测试
我们可以看到,在每次拆分中,观察结果的数量都符合我们的预期。
时间序列交叉验证
训练和测试分割的一个更复杂的版本是时间序列交叉验证,这也称为前推验证,因为它涉及一次一个时间步长地沿着时间序列移动。这种方法提供了在每个时间步进行预测的最佳机会。
让我们在下面的例子中看看数据集的不同分割是如何随着时间序列向前移动的。

向前走验证示例
预测准确性是通过对测试集进行平均来估计的。在创建这个验证框架之前,我们必须决定我们对哪些历史观察感兴趣。
首先,我们必须决定训练我们的模型所需的最少观察次数,即窗口宽度。
在决定了这些需求之后,现在让我们在“航空公司-乘客”数据集上实现这个分割方法。
我们可以看到更多的分裂被创造出来,我们可以训练同样多的模型。同样,这将有助于我们提供更可靠的评估。向前走方法被认为是最好的模型评估方法,这也被称为时间序列世界的 k-fold 交叉验证。
2.常见的预测准确性衡量标准
任何时间序列预测模型的目标都是做出准确的预测,但问题是我们如何衡量和比较预测的准确性。因此,作为初步要求,我们必须定义一个合适的性能指标来衡量预测的准确性。
有许多不同的绩效衡量标准可供选择,在这一部分,我们将讨论一些流行的衡量标准。
预测误差
考虑一个具有“v”个时间段的验证数据集,t=1,…v。预测误差(eₜ)定义为某个时间段(t)的观测值(xₜ)and)与预测值(yₜ)之间的差值。

可以计算每个预测的预测误差,让我们看看如何在 Python 中计算这个误差。
这是否解决了我们的评价问题?还没有,我们必须将这些误差总结为一个可比较的数字。
让我们讨论几种流行的预测准确性的方法。
平均预测误差
平均预测误差计算为预测误差值的平均值。

正如我们所知,预测误差可以是正的,也可以是负的,这种性能度量是以这些预测误差的平均值来计算的,因此一个系列的理想平均预测误差应该是零。误差值远离零被认为是偏差。
让我们看看如何使用虚拟的实际值和预测值在 Python 中手动计算平均预测误差。
绝对平均误差
平均绝对误差(MAE)计算为预测误差值的平均值,其中所有预测值都强制为正值。

我们可以在 Pythion 中使用 mean_absolute_error 函数手动计算。
平均绝对百分比误差
平均绝对百分比误差或 MAPE 给出了预测值偏离实际值的百分比分数。这对于比较具有不同规模的多个系列的性能非常有用。

sci-kit learn 中没有内置函数,我们可以使用自定义函数来计算这个度量。
均方误差
均方差(MSE)是预测误差平方值的平均值。对预测误差值求平方会强制误差为正。因此,这种方法更重视大的误差。

我们可以使用 Python 中 sci-kit learn 的 mean_squared_error 函数来计算这个度量。
均方根误差
均方根误差或 RMSE 是均方误差的变换版本。它可以通过计算均方误差值的平方根来计算。

在 Python 中,这可以通过对上面计算的均方误差使用数学库的 sqrt()函数来计算。
3.天真的预测
我们已经将数据集划分为训练和测试子集,还定义了评估模型的理想性能指标。现在,我们已经准备好开始建模练习,我们可以选择任何可用的高级算法来建模时间序列。
但是,我们怎么能相信这个模型的预测准确性呢?我们心目中有什么基准精度吗?
让我们建立一个基准预测性能,在评估不同技术的性能时,我们可以将它作为一个参考点。如果模型的准确性等于或低于基线,我们可以改进模型,如果我们不能达到预期的准确性,我们可以探索其他技术。
时间序列预测最常用的基线方法是简单预测,这只是预测时可用的序列的最新值。naive 算法使用当前时间步长(t)的值来预测下一个时间步长(t+1)的预期结果。
让我们用 Python 实现一个简单的预测。
将时间序列数据重构为监督学习数据集
让我们将我们的“航班-乘客”数据集转化为一个监督学习问题,我们可以通过创建一个滞后特征来实现这一点。在这个变换的数据集中,(t)处的值是预测值(X),而(t+1)处的值是目标变量(Y)。
我们必须丢弃第一行,因为它没有任何输入值。
创建培训测试分解
接下来,我们可以将数据集分为训练和测试子集,如下所示。70%的系列创建为培训,30%创建为测试子集。
做出天真的预测
建立一个基线模型是相当简单的。我们知道 naive 算法使用当前时间步(t)的值来预测下一个时间步(t+1)的预期结果。因此,在数据集的转换监督版本中,第一列是对第二列的预测。我们必须丢弃数据集的第一行,因为它没有任何输入值。
预测和评估预测
最后一步,我们可以在测试数据集上评估我们的基线模型。在这种情况下,不需要模型训练或再训练,我们知道第一列是预测,第二列是实际数字。我们一步一步地遍历测试数据集并得到预测。
我们可以观察这个预测的折线图,它用蓝色显示训练集,用绿色显示测试集,用红色显示预测。
观察线图,我们可以看到测试数据集上的一个不错的预测。当我们探索其他先进的技术时,我们必须保持或提高这种准确性。
4.可视化和分析残差
我们已经准备好基线模型,现在是时候使用预测误差来调查拟合优度了。时间序列问题上的这些误差称为残差或剩余误差。分析我们模型的残差可以解释很多关于我们预测的事情,甚至提出改进建议。
让我们在同一数据集上重新计算我们的天真预测的残差,以便在本节中进一步探讨。
我们可以看到前五个预测错误的示例输出。让我们把这些数字形象化,以获得有意义的解释。
剩余线图
第一个图是以线形图的形式观察残差随时间的变化。如果模型拟合得很好,我们不会期望任何趋势和循环行为,图应该在值 0 附近是随机的。
我们仍然可以在线图中观察到循环行为,这表明模型中存在改进的空间,可以通过更好的功能工程和探索其他高级模型来实现。
剩余汇总统计
接下来,我们可以分析残差的汇总统计数据。首先,我们感兴趣的是残差的平均值。接近零的值表示预测中没有偏差,而正值和负值表示预测中有正偏差或负偏差。
汇总统计数据也表明模型中存在正偏差。
残差直方图和密度图
这些图可用于更好地理解汇总统计之外的误差分布。我们希望预测误差正态分布在一个零均值附近。绘图有助于发现这种分布的偏斜。我们可以使用直方图和密度图来更好地理解残差的分布。
可以清楚地观察到残差不是正态分布的,而是负偏态的。这再次证实了我们的模型需要改进。
剩余 Q-Q 图
这也称为分位数图,可用于检查残差分布的正态性。对这些值进行排序,并与散点图上的理想化高斯分布进行比较。我们希望所有的点都与对角线重叠,以确认两个分布之间的完全匹配。
我们可以在 Q-Q 图上看到一些凸起和异常值,需要对它们进行校正,以实现更好的预测。
剩余自相关图
自相关解释了观测值和先前时间步的观测值之间的关系强度。我们不期望残差之间还有任何相关性。让我们计算并绘制残差的自相关。
我们可以看到残差中仍然存在自相关,这验证了我们的发现,即模型需要在特征工程和算法选择方面进行改进。
摘要
在本文中,我们讨论了构建一个健壮的评估框架的所有重要技术。我们从数据划分开始,然后讨论了各种可供选择的性能指标,建立了一个持久性预测模型作为提高准确性的基准,最后了解了使用残差进行模型调查。
经过数据准备(在我的上一篇文章中有所涉及)并有了一个健壮的评估框架,现在我们完全准备好探索各种预测技术。在接下来的几篇文章中,我将讨论不同的预测技术,我将从经典技术开始。
感谢阅读,希望你发现这篇文章内容丰富。
参考
[1] Galit Shmueli 和 Kenneth Lichtendahl,实用时间序列预测与 R:实践指南,2016 年。
[2]杰森·布朗利,【https://machinelearningmastery.com/
12 小时 ML 挑战
如何使用 Streamlit 和 DevOps 工具构建和部署 ML 应用程序

克拉克·蒂布斯在 Unsplash 上拍摄的照片
TL;在这篇文章中,我想分享我完成 12 小时 ML 挑战的学习、过程、工具和框架。希望对你的个人或专业项目有所帮助。
以下是帮助您导航的目录:
- 第 1 部分:找一个好问题
- 第 2 部分:定义约束条件
- 第三部分:思考,简化,&分清主次
- 第四部分:冲刺规划
- 第五部分:App
- 第 6 部分:经验教训
- 奖励:懒惰程序员的过程&工具
免责声明: 这不是由 Streamlit、我提到的任何工具或我工作的任何公司赞助的。
喜欢读什么? 跟我上 中LinkedInTwitter。查看我的《 对机器学习的影响 》指南。它有助于数据科学家更好地交流。**
第一步:找一个好问题(圣诞节问题)
嗯,圣诞节。过去,每年的这个时候,我都会和妻子、小狗一起坐在沙发上,疯狂地看电影和电视剧。
然后,这个圣诞节。有些事情改变了。出于某种原因,我在网飞或 YouTube 上找到的大多数东西似乎都很无聊。也许我通过观看推荐算法推送的类似内容,已经达到了零效用收益的临界点。太了解我的算法了(可能太了解了)。
我意识到了一个问题:我被太了解我的推荐算法困住了——我被数字化囚禁了(本帖采取的是更具设计感的镜头)。
我似乎找不到内容气泡之外的东西。算法认为我感兴趣的一切都逐渐变得无趣;真是讽刺。我想出去!
****重点是这个:找一个够烦的问题。它不一定是治愈癌症或消除饥饿(如果你可以,太棒了!),只要是足够有意义的事情,让你愿意去承诺,去开始。
步骤 2:定义约束(12 小时挑战)
在我的朋友 Matt Pua 的 web 应用程序开发的 48 小时挑战的启发下,我决定做一些类似的事情,但是是针对有 ML 组件的应用程序。简而言之,限制因素如下:
- 约 12 小时的总工作时间;它们不必是连续的小时
- 必须为除我之外的用户提供一个可用且稳定的应用程序
- 必须有一个 ML 组件,但没有不必要的复杂性
- 必须与他人分享工作和学习成果(也就是写这篇文章)
- (这种体验一定很有趣)
为什么要有截止日期?据马特:
…设定最后期限让个人专注于优先考虑他们需要关注的事情,以便让他们的项目进入可行状态。个人必须考虑到设计一个项目、提出解决方案、处理任何不可预见的技术问题以及这两者之间的一切,以便在截止日期前完成项目。
(那么,为什么只有 12 小时,而不是 48 小时呢?我不像马特那么紧张。如果你决定这样做,选择一个最适合你的时间框架,并坚持下去。重点是执行和出货。)
以下是我对所有相关工作的大致时间预算:
- ****2 小时:对 app 有一个大致的设计(如研究、UX、架构)。
- ****8 小时:重新设计,构建,迭代测试 app。
- ****2 小时:撰写、编辑、发表这篇文章(还有这个)。
第三步:思考,简化,区分优先次序,然后重复
在编码之前,我需要解决几个重要的问题,1)明确我到底需要构建什么,2)在 12 小时内优先构建什么。尽管不是详尽无遗的,以下是一些指导性问题:
戴上的产品帽子,谁是用户?用户想要什么,需要什么?不同细分市场的需求有何不同?应该先针对哪个用户群?满足需求的功能有哪些?…
戴上数据科学的帽子,我需要什么数据并且这些数据是可用的?我需要商业智能分析还是预测模型?我应该使用什么业务和模型指标?我如何衡量绩效?…
戴上设计师帽子,app 需要触发什么情绪?我应该使用什么配色方案?用户旅程是什么样子的?考虑到这些特性,什么是最好的用户交互?…
戴上工程师帽,app 一次需要支持多少用户?从开发到部署的过程是什么样的?使用什么技术堆栈可以平衡原型开发速度和可伸缩性?…
戴上商业的帽子,我如何将应用程序货币化?如何发展和维持应用程序的受众?如何把跑技术和运营的成本降到最低?…
正如你所想象的,这个练习会很快变得让人不知所措。一定要从试图解决一切的冲动中抽身。
最终,这里是我在 8 小时的开发中可以解决的前三个“用户想要/需要”和相应的特性:
- 我想要惊喜:**应用程序应该能够建议我以前没有看过的电影或与我正常观看历史不同的电影。>今日精选&过滤
- 我需要选择:**应用程序应该能够显示一个预告片,并提供一些关于电影质量的信息。>预告片和评级
- 我想控制:应用程序应该提供一个简单的方法,让用户控制如何不同的建议看起来像。 >“滤镜面板&智能探索”
这里有一些我想做的东西,但是降低了的优先级:
- 用户认证/消息传递
- 自动发送电子邮件
- 云备份
- 多模型推荐
- 客户服务机器人
考虑到这些特性,下面是解决方案的粗略架构设计,关键组件及其交互。

概念架构图,作者的作品
注意:这是一个迭代过程的结果。你开始思考可能看起来很不一样。参见经验教训,了解如何决定构建什么和不构建什么的技巧。
步骤 4:冲刺计划和执行
我决定在四次 2 小时冲刺中建造这个。以下是每次冲刺的大致结果:
Sprint 1 :自动化的开发到部署管道;一个简单的可点击的“今日精选”和过滤功能在 Heroku 上提供。
冲刺 2 :构建 ETL 一组用于 ETL 的自动化测试用例;改进了 YouTube 预告片的前端&带有虚拟数据的个性化部分。运行时优化。
Sprint 3 :为智能探索构建 API。使用虚拟模型与前端集成。建模选项的研究。更多运行时优化。
冲刺 4 :重构并优化一个基于 KNN 的协同过滤模型。添加建模测试案例。代码清理和更多优化。
第五步:哒哒。
AME 出生了。现在你可以在这里使用 YAME为你的工作日、周末、约会之夜、家庭聚会寻找一些有趣的东西。该应用旨在提供搜索引擎的便利,同时提供控制,而不会让用户负担过重。
便利:登陆页面有五部系统推荐的电影。它每天更新。该算法跨年份、跨流派挑选电影;它试图做到不偏不倚。

今日精选带拖车
一些控制:如果你不喜欢你看到的或者只是想知道那里有什么,你可以使用左边的面板选择年份和流派。

过滤
更多控制而不牺牲便利:如果你真的想要别的东西,你可以基于探索你今天用简单的界面感受 有多“冒险”。这个 UI 允许用户有一个 选项来选择 。用户可以决定他们想看什么,而不会认知超载。

基于 KNN 的协同过滤的智能探索
第六步:吸取教训
安全,快速,懒惰。在其他事情之前自动化测试。如果你发现自己定期手动测试某样东西,投资一点时间并自动化它。用 PyTest 和 CircleCI 进行自动测试省去了很多麻烦。对于一个 ML 应用程序,你应该有两组测试。一个用于软件测试(例如单元和集成测试),另一个用于模型测试(例如最低性能和边缘情况)。拥有动态测试用例(由随机数驱动的输入)也有助于捕捉难以预测的边缘用例中的 bug。****

从开发到部署的工作流程,作者的工作
避免卡格尔陷阱。由于我只预算了大约 4 个小时来开发 ML 组件,所以关键是要构建一个足够好的模型来验证 ML 特性的功能和有用性。很容易陷入“Kaggle 模式”的陷阱(例如,花费大量时间构建复杂的模型以获得较小的性能增益)。我用一个模型——UX 分析来帮助设定界限。这种分析并不意味着是一种科学练习,而是一种让你远离作弊的工具。****

模型-UX 分析(开发时间),作者的分析
注 :最小模型性能的阈值因用例而异。例如,一个显示使用 GAN 或欺诈检测的 合成人脸的应用程序将很可能需要非常好的模型性能来说服用户其有用性。
所以,我的策略是从最简单的模型开始:一个由随机数生成器驱动的“模型”。虽然从建模的角度来看这听起来很幼稚,但是它用最少的开发时间(~5 分钟)为 UX 增加了最大的价值。用户可以玩个性化功能,这是不存在的。它是否提供“最佳”推荐并不重要,关键是要验证该特性。然后,我将该模型发展为基于规则和基于 KNN 的协同过滤算法。****
建造是有趣的,优先化却不是。这里有一些让它变得更简单的建议:
- 从最讨厌的利润问题开始(这个练习不要太在意利润)。
- 想一个理想的解决方案&预算你需要多少时间来构建它;请记住,你可能会低估,但没关系。
- 将时间减少到 1/3,重新思考解决方案,看看在没有大量研究的情况下,你是否能放心实施(一些研究仍然有助于学习)
- 重复,直到范围适合 2 到 4 小时的时间框架
如果你喜欢并想支持 YAME,请查看我的 Patreon 页面。支持将用于支付运行和改进 YAME 的费用(如服务器、网站等)。).
我希望你喜欢这篇文章。如果你决定接受 12 小时的挑战,我很想看看你的作品。在上跟我连线 ,LinkedIn,或者Twitter。********
直到下一次,
伊恩
额外收获:懒惰程序员的过程和工具
对于任何感兴趣的人(并且到目前为止),我想要一个尽可能自动化的工作流,这样我就可以把时间花在设计和编码上,而不是做手工测试或移动代码。每个人都有自己的喜好。对我来说,关键是能够快速迭代并准备好扩展。
从技术堆栈的角度来看,以下是我选择的工具(也有一些备选方案):
- Python 作为通用工作流、ETL 和建模的编程语言。(可选:SQL 用于 ETL,R 用于建模,Java 用于工作流)
- Streamlit 作为前端工具。它基于 python。开箱即用,它附带了用户体验所需的大部分小部件;它是网络和移动友好的。它鼓励我像建模一样关注用户体验。Jupyter 很棒,但我觉得它倾向于让人们陷入 Kaggle 陷阱。(备选:Flask、Django 或 React 为前端;用于分析和模型实验的朱庇特笔记本)**
- Postgres 作为后端数据库工具。(备选:GCP、AWS、Azure 注意,如果你想遵循相同的设置,SQLite 不能与下面的 Heroku 一起工作)**
从 DevOps 的角度来看,这里有一些工具:
- PyCharm 为 IDE (可选: 崇高 , 原子 )
- Github 进行代码版本控制(备选:DVC)****
- PyTest 用于管理测试用例并运行自动测试
- 圆 CI 作连续整合部署(备选: 詹金斯 )**
- Heroku 用于网络托管(备选方案:云解决方案,如 GCP、AWS、Azure 或 Paperspace)
如果你像我一样是一个懒惰的程序员,我强烈建议你提前投入时间来建立这个 DevOps 工作流。它节省了手动测试和部署的大量时间。更重要的是,它真的保护你的代码库免受愚蠢的错误。
最后,我使用 Trello ,作为一个简单的看板,来跟踪我需要做的事情:

看板——作者的工作
注:我没有选择替代方案的原因是为了避免过度工程化和不够熟悉,以获得效率增益。
如果你喜欢这篇文章,你可能也会喜欢这些……
每个懒惰的全栈数据科学家都应该使用的 5 套工具
towardsdatascience.com](/the-most-useful-ml-tools-2020-e41b54061c58) [## 被遗忘的算法
用 Streamlit 探索蒙特卡罗模拟
towardsdatascience.com](/how-to-design-monte-carlo-simulation-138e9214910a) [## 数据科学很无聊
我如何应对部署机器学习的无聊日子
towardsdatascience.com](/data-science-is-boring-1d43473e353e) [## 我们创造了一个懒惰的人工智能
如何为现实世界设计和实现强化学习
towardsdatascience.com](/we-created-a-lazy-ai-5cea59a2a749) [## ML 和敏捷注定的联姻
如何在 ML 项目中不应用敏捷
towardsdatascience.com](/a-doomed-marriage-of-ml-and-agile-b91b95b37e35) [## 你被解雇了
如何发展和管理一个快乐的数据科学团队
towardsdatascience.com](/i-fired-a-data-scientist-a137fca5b80e) [## 抵御另一个人工智能冬天的最后一道防线
数字,五个战术解决方案,和一个快速调查
towardsdatascience.com](/the-last-defense-against-another-ai-winter-c589b48c561) [## 人工智能的最后一英里问题
许多数据科学家没有充分考虑的一件事是
towardsdatascience.com](/fixing-the-last-mile-problems-of-deploying-ai-systems-in-the-real-world-4f1aab0ea10)******
从头开始构建 InfoGAN
了解 InfoGAN 并构建自己的 InfoGAN 网络,以生成特定功能的 MNIST 手写数字

图片来自论文“ InfoGAN:通过信息最大化生成对抗网络的可解释表示学习”
从上图中,你能看出哪些手写数字是机器合成的,哪些是人类做的吗?答案是:都是机器合成的!事实上,这张图片来自于一篇科学论文“info gan:通过信息最大化生成对抗网络进行的可解释表征学习”,其中作者开发了一个特殊的生成对抗网络,命名为 InfoGAN(信息最大化生成对抗网络),并使用它来合成 MNIST 手写数字。如你所知,GANs 广泛用于合成新数据,尤其是图像。然而,普通 GANs 的一个缺点是我们无法控制 GANs 产生的图像。例如,一个被训练产生假的手写数字图像的 GAN 可能能够产生非常真实的手写数字图像,但是我们无法控制它产生哪个数字。 InfoGAN 解决了这个问题:网络可以学习以无监督的方式产生具有特定分类特征(如数字 0 到 9)和连续特征(如数字的旋转角度)的图像。此外,由于学习是无监督的,它能够发现隐藏在图像中的模式,并生成遵循这些隐藏模式的图像。有时候模特可以学到超乎你想象的非常有趣的模式(比如我的一个模特就学会了从 2 号过渡到 8 号。你以后会看到的!).在这本笔记本中,我将介绍 InfoGAN 如何实现对正在生成的图像的控制,以及如何从头构建一个 InfoGAN 来合成特定功能的 MNIST 手写数字,就像上面的图像一样。
InfoGAN 的结构
一个正常的 GAN 有两个基本元素:一个接受随机噪声并产生假图像的发生器,以及一个接受假图像和真图像并识别图像是真是假的鉴别器。在训练过程中,如果鉴别器成功检测出生成的图像是假的,生成器就会受到“惩罚”。因此,生成器会学习产生与真实图像越来越相似的假图像来“愚弄”鉴别器。
在 InfoGAN 中,为了控制生成的图像类型,我们需要向生成器提供随机噪声之上的附加信息,并迫使它在制作假图像时使用这些信息。我们提供的附加信息应该与我们希望图像具有的特征类型相关。例如,如果我们想产生特定的 MNIST 数字,我们需要输入一个包含从 0 到 9 的整数的分类向量;如果我们想要产生具有不同旋转角度的 MNIST 数字,我们可能想要输入在-1 到 1 之间随机选择的浮点数。
输入额外的信息很容易,因为我们只需要向生成器模型添加额外的输入。但是我们如何确保生成器会使用这些信息,而不是完全忽略它呢?如果我们仍然简单地基于鉴别器的响应来训练生成器,则生成器不会使用附加信息,因为附加信息不会帮助生成器创建更真实的图像(它只对生成图像的特定特征有帮助)。因此,如果生成器不使用附加信息,我们需要对它施加额外的“惩罚”。一种方法是添加一个额外的网络(通常称为辅助网络,表示为 Q ),该网络获取假图像并再现我们输入到生成器中的额外信息。这样,生成器被迫使用附加信息,就好像它不使用一样,辅助网络没有办法正确地再现附加信息,并且生成器将被“惩罚”。下图总结了 GAN(左)和 InfoGAN(右)的结构。
注:在本文中,理论上应该通过最大化互信息来训练生成器。然而,互信息实际上是无法计算的。因此,作者近似互信息,并且该近似变成附加信息和再现信息的输入之间的交叉熵(即,差)。如果你对互信息以及它是如何近似的感兴趣,可以去查一下原创论文,或者是 Zak Jost 和 Jonathan Hui 两篇非常好的 medium 文章。

GAN(左)和 InfoGAN(右)的结构。作者图片
构建 InfoGAN
理解了 InfoGAN 的结构之后,让我们动手构建一个 InfoGAN 来生成特定于功能的 MNIST 数字!如上图所示,InfoGAN 包含三个模型:生成器(G)、鉴别器(D)和辅助模型(Q)。生成器的输入包括三个部分:大小为 62 的噪声向量、大小为 10 的分类向量(表示 10 个数字)和大小为 1 的连续向量。噪声向量通过正态分布生成,分类向量通过从 0 到 9 选取一个整数生成,连续向量通过从-1 到 1 选取一个浮点值生成。
InfoGAN 中的发生器与普通 GAN 中的发生器具有完全相同的结构。它首先包含两个完全连接的层,以将输入形状扩展到 6272 个单元。然后,6272 个单元被改造成 128 个 7×7 层。之后,经过整形的图层通过三个转置卷积层进行处理,形成最终的 28x28 像素图像(如果你对转置卷积层不熟悉,我有一篇文章解释它)。
鉴别器也与普通 GANs 中的相同。它包含两个卷积层和两个全连接层。最后一个全连接层生成一个具有“sigmoid”激活函数的输出,以表示真实图像(1)或虚假图像(0)。
辅助模型共享来自鉴别器的所有层,除了最后一个完全连接的层,因此这两个模型被一起定义。辅助模型有两个额外的全连接层来标识附加信息。由于我们的生成器有两个额外的输入(一个分类向量和一个连续向量),我们还需要来自辅助模型的两个不同的输出。因此,我设置了一个具有“softmax”激活函数的全连接层来标识分类输出,两个全连接层来表示高斯分布的【mu】(均值)和【sigma】(标准差):

注意:由于我们的连续向量是从-1 和 1 之间的均匀分布中随机选择的浮点数,因此可以有无限多的浮点数可供选择。因此,要求辅助模型预测发电机取的确切数字是不实际的。相反,我们可以预测一个高斯分布,并要求模型最大化连续向量在分布中的可能性。
定义了这三个模型之后,我们就可以构建我们的 InfoGAN 网络了!我用 Keras 做网络建设:
我知道这是一个相当长的代码,所以让我们一步一步地消化它:
- InfoGAN_Continuous 是一个 Keras 模型类,应该通过给定鉴别器、生成器、辅助模型、噪声向量的大小和分类向量的类的数量来初始化。
- compile 函数编译 InfoGAN_Continuous 模型(对于我使用的三个优化器都是 Adam)。
- create_gen_input 是我们之前定义的为发电机生成输入的函数。
- concat_inputs 将三个输入向量(大小 62、大小 10、大小 1)连接成一个大小为 73 的向量。
- train_step 函数定义了训练步骤。它只需要成批的真实图像。首先,通过鉴别半批真实图像和半批伪图像来训练鉴别器。鉴别器的损失是鉴别真实图像和虚假图像的损失的总和。权重通过基于损失的梯度下降算法来更新。然后,使用整批伪图像来训练生成器和辅助模型。辅助模型损失包含分类损失和连续损失。分类损失就是预测标签和输入分类向量之间的分类交叉熵;连续损失是连续矢量输入的高斯分布的负对数概率密度函数。最小化负对数概率密度函数与最大化我们位于预测高斯分布内的连续向量的概率是一样的,这就是我们想要的。发电机损耗包括来自鉴别器的损耗和来自辅助模型的损耗。通过这样做,生成器将学习生成具有更具体特征的更真实的图像。请注意,我们将鉴别器中的变量设置为不可训练,因为我们不想在训练生成器和辅助模型时修改鉴别器中的神经元。
现在,你只需要用几行代码来训练它!!!
结果
现在,让我们看看我从 InfoGAN 模型中得到的一些非常有趣的结果!
变化分类向量
首先,如果您更改分类向量输入,您可以生成不同的数字。但是,模型不会知道标签 0 对应数字 0!它只知道不同的标签对应不同的数字(相信我,我不知怎么用了一整天才意识到这一点。我一直以为我输了当喂养标签 0 为我生成数字 9)。

作者图片
因此,您可能需要重新排列标签:

作者图片
变化连续向量
改变连续向量可以产生不同形状的相同数字。例如,对于数字 1,当增加连续向量值时,数字以顺时针方向旋转。请注意,即使我们使用从-1 到 1 的值来训练模型,通过输入-1.5 和 1.5,我们仍然可以获得有意义的结果!
请注意,标签与上面的不同。这是因为我再次训练了模型,模型总是随机地将标签与数字相关联。

作者图片
5 号更有趣。似乎模型试图旋转数字,但由于其形状更复杂,数字被剪切。

作者图片
增加体重以持续减肥
您可能会注意到,在将连续损耗添加到发电机总损耗和辅助设备总损耗时,我将连续损耗的比率设置为 0.1。这是为了避免混淆模型。如果连续损失与分类损失具有相似的比率(即接近 1),则模型会将其视为确定数字类型的另一个因素。例如,下面的图像是在我使用 0.5 的比率时生成的:

作者图片

作者图片
如你所见,即使我使用相同的标签,通过改变连续向量值,数字逐渐从 2 变为 4,或者 2 变为 8!这也意味着计算机实际上可以找到数字 2 到数字 4,数字 2 到数字 8 之间的相似之处,并且知道如何从一个数字转换到另一个数字。是不是很神奇?
结论
InfoGAN 是一个非常强大的 GAN,它可以以无监督的方式在图像中学习模式,并通过遵循模式产生图像。玩起来也很有趣,因为你可以通过操作输入变量来生成各种各样的图像。使用本故事中的代码,您可以构建自己的 InfoGAN,看看您能制作出多么令人惊叹的图像!
参考资料:
陈曦、严端、雷因·胡特夫特、约翰·舒尔曼、伊利亚·苏茨基弗和彼得·阿比尔, InfoGAN:通过信息最大化生成对抗网络的可解释表征学习 (2016),康乃尔大学
Shaked 是 Taboola 的算法工程师,从事推荐系统的机器学习应用。他…
engineering.taboola.com](https://engineering.taboola.com/predicting-probability-distributions/) [## 如何开发 Keras 中的信息最大化 GAN(info GAN)——机器学习掌握
生成对抗网络,或 GAN,是一种用于训练深度卷积模型的架构,用于生成…
machinelearningmastery.com](https://machinelearningmastery.com/how-to-develop-an-information-maximizing-generative-adversarial-network-infogan-in-keras/)
使用 leav 从 GPX 文件构建交互式 GPS 活动地图
使用 Strava 和 Garmin 等流行服务创建自行车和徒步旅行 GPS 轨迹的个性化地图
介绍
这篇文章概述了如何使用folio将 GPS 记录的活动转换为个性化的交互式地图,这是一个基于强大的地图框架 Leaflet.js 构建的 Python 库。
首先,我想介绍一下这个项目是如何开始的(如果您来这里是为了快速访问一段特定的代码,请随意跳到‘数据争论’部分)。
我喜欢地图——无论是数字地图还是实物地图。它们为我们周围的世界增添了意义,让我们能够直观地理解我们生活的空间关系。物理地图代表着冒险、怀旧和发现——在我们探索世界的过程中引导我们踏上神奇的旅程。
我使用 Strava(一个 GPS 活动跟踪应用程序)已经超过 10 年了,最近,我买了一块 Garmin 手表,用来跟踪我的所有活动:主要是骑自行车和徒步旅行。我被数据迷住了:我喜欢检查我刚刚完成的路线,挖掘我的统计数据,并在屏幕上检查我的冒险的视觉表现。
卡米诺
自从 2016 年搬到西班牙,我就迷上了'埃尔卡米诺圣地亚哥'(在英语中称为圣詹姆斯路,但在本文中,它将被亲切地称为卡米诺)。卡米诺朝圣之旅始于 2000 多年前,是前往西班牙西北部圣地亚哥德孔波斯特拉大教堂的宗教朝圣活动。在现代,它已经成为一条多日徒步旅行和骑自行车的冒险路线,吸引了各个年龄和国籍的参与者。我的个人博客对 Camino 进行了更详细的解释:
它有宗教根源(朝圣者已经行走了 1000 年),但现在,大多数人把它作为一种探险和徒步旅游的形式。还有一个自我反省和精神成长的元素吸引了许多人来到卡米诺。这是一个独处(和人在一起)的机会,可以反思生活,理清思绪,冥想散步等等。我做这件事的动机是以上所有的;我不断地自我反省,喜欢思考问题,我也喜欢认识新的人,游览新的地方,冒险,当然还有徒步旅行。
多年来,我收集了相当多的卡米诺经历;总共至少 10 次旅行(包括骑自行车和徒步旅行),每次旅行持续时间从周末探险到 25 天的奥德赛不等。作为地图和数据的爱好者,这个项目的想法对我来说一直很清晰;在视觉上创造一个我曾经完成的所有卡米诺作品的代表。
经过大量的实验,测试了叶子的极限,这是结果:

绿色圆圈代表起点。红色表示骑自行车的卡米诺,绿色表示徒步旅行的卡米诺。
为了获得最佳观看体验,请查看互动版(媒体不允许嵌入 HTML)。您可以通过选择右上角的单选按钮在每个 Camino 之间切换。点击卡米诺中点的徒步旅行或骑自行车图标可以查看统计数据摘要。“未来卡米诺”选项代表我希望有一天能完成的其他卡米诺。
数据争论和地图创建
这个工作流程存在于一个 Jupyter 笔记本中;我推荐安装 Anaconda 来快速启动并运行笔记本环境。
构建交互式地图的第一步是以 GPX 的形式下载您的 GPS 轨迹,这是 GPS 交换格式的缩写。大多数活动跟踪服务都有这种格式的 GPS 轨迹可供下载。我首选的工具是 Strava 和 Garmin:
- 斯特拉瓦。 指令用于一次性批量下载所有数据(包括 GPX 文件)。
- 佳明。他们有一个类似的选项来进行批量导出,但我会推荐一个非常有用的 python 脚本,它会自动下载所有 GPX 文件,并在您完成它们时智能地下载新文件。
使用 gpxpy 将 GPX 文件转换成 GPS 坐标的数据帧。这个****非常有用的包解析 GPX XML 并将其转换成整洁的数据帧,准备好使用 Pandas 进行分析。另一种选择是使用 python 模块 ElementTree 或 lmxl 自己解析它。
def process_gpx_to_df(file_name):gpx = gpxpy.parse(open(file_name))
#(1)make DataFrame
track = gpx.tracks[0]
segment = track.segments[0]
# Load the data into a Pandas dataframe (by way of a list)
data = []
segment_length = segment.length_3d()
for point_idx, point in enumerate(segment.points):
data.append([point.longitude, point.latitude,point.elevation,
point.time, segment.get_speed(point_idx)])
columns = [‘Longitude’, ‘Latitude’, ‘Altitude’, ‘Time’, ‘Speed’]
gpx_df = pd.DataFrame(data, columns=columns)
#2(make points tuple for line)
points = []
for track in gpx.tracks:
for segment in track.segments:
for point in segment.points:
points.append(tuple([point.latitude, point.longitude]))
return gpx_df, points
产生的数据帧结构如下:

****启动叶子地图并选择图块。leave是一个 python 库,构建在强大的映射框架leafle . js之上。创建地图的第一步是选择地图分块(实际上是一个地图皮肤)。在这里可以找到极好的瓷砖收藏。以下语法允许在同一地图上创建多个切片,并为每个切片指定个性化的名称。
import foliummymap = folium.Map( location=[ df.Latitude.mean(), df.Longitude.mean() ], zoom_start=6, tiles=None)
folium.TileLayer(‘openstreetmap’, name=’OpenStreet Map’).add_to(mymap)
folium.TileLayer(‘[https://server.arcgisonline.com/ArcGIS/rest/services/NatGeo_World_Map/MapServer/tile/{z}/{y}/{x}'](https://server.arcgisonline.com/ArcGIS/rest/services/NatGeo_World_Map/MapServer/tile/{z}/{y}/{x}'), attr=”Tiles © Esri — National Geographic, Esri, DeLorme, NAVTEQ, UNEP-WCMC, USGS, NASA, ESA, METI, NRCAN, GEBCO, NOAA, iPC”, name=’Nat Geo Map’).add_to(mymap)
folium.TileLayer(‘[http://tile.stamen.com/terrain/{z}/{x}/{y}.jpg'](http://tile.stamen.com/terrain/{z}/{x}/{y}.jpg'), attr=”terrain-bcg”, name=’Terrain Map’).add_to(mymap)
最终结果是一个单选按钮,允许用户选择他们想要的图块:

****使用点绘制路线。我们使用 GPS 坐标元组(从我们的 gpxpy 函数中命名为“点”)来绘制 GPS 路线。foylus 允许对折线进行大量的定制,可以调整颜色、厚度和不透明度。对我来说,红线代表骑自行车的路线,绿色代表徒步旅行。
folium.PolyLine(points, color='red', weight=4.5, opacity=.5).add_to(mymap)
****建立一个起始标记(圆形和三角形)。我用 Folium 的各种标记类,用一个三角形叠加在一个圆上,为这条路线拼凑了一个“开始”图标。

html_camino_start = “””
Start of day {camino_day}
“””.format(camino_day=camino_day)
popup = folium.Popup(html_camino_start, max_width=400)
#nice green circle
folium.vector_layers.CircleMarker(location=[lat_start, long_start], radius=9, color=’white’, weight=1, fill_color=’green’, fill_opacity=1, popup=html_camino_start).add_to(mymap)
#OVERLAY triangle
folium.RegularPolygonMarker(location=[lat_start, long_start],
fill_color=’white’, fill_opacity=1, color=’white’, number_of_sides=3,
radius=3, rotation=0, popup=html_camino_start).add_to(mymap)
****添加带有 GPS 路线统计信息的可点击图标。对于每辆 Camino,一个自行车或徒步旅行者的图标(使用字体 awesome )被添加到轨道的中点。速度、距离和高度增益等统计数据汇总到数据帧中,并转换成 HTML 表格。“弹出”功能用于创建一个漂亮的信息框,当图标被点击时显示 GPS 跟踪的统计数据。

camino_summary_for_icon = camino_summary_for_icon.iloc[1:,: ] html_camino_name = “””
<div align=”center”>
<h5>Daily Stats</h5><br>
</div>. “”” html = html_camino_name + “””<div align=”center”>””” + camino_summary_for_icon.to_html(justify=’center’, header=False, index=True, index_names=False, col_space=300, classes=’table-condensed table-responsive table-success’) + “””</div>””” #popup = folium.Popup(html, max_width=300)
folium.Marker([lat, long], popup=popup, icon=folium.Icon(color=activity_color, icon_color=’white’, icon='bicycle', prefix=’fa’)).add_to(mymap)
使用矢量图层创建一个“一天结束标记”。每个卡米诺由多天组成,平均约 10 天。如果放大交互式地图,可以很容易地看到这些日期标记,目的是在更精细的层次上显示 Camino,单个轨道上的各个日期可以可视化。点击阴影圆圈,会显示关于卡米诺该部分的长度和天数的信息。

' vector_layers '的大小。“圆”实体基于米,而“叶”实体基于米。“图标”为像素。本质上,这意味着无论缩放级别如何,图标都将保持相同的大小,而 vector_layers。“圆圈”会随着用户缩放而变大。出于这个原因,我选择使用矢量层。“圆圈”表示特定 Camino 上一天的结束——这是一个有趣的信息,只有当用户放大时才能看到。它变得太忙而不能包含在缩小的视图中。我使用' tooltip= '参数在弹出窗口中添加额外的文本信息。
day_terminal_message = ‘End of Day ‘ +str(camino_day)[:-2]+ ‘. Distance: ‘ + str(camino_distance) + ‘ km.’
mymap.add_child(fg)
folium.vector_layers.Circle(location=[lat_end, long_end], radius=track_terminal_radius_size, color=activity_color, fill_color=activity_color, weight=2, fill_opacity=0.3, tooltip=day_terminal_message).add_to(mymap).add_to(fg)
****结束标记。结束标记(圆形和方形)的构建与开始标记相同。

html_camino_end = “””
End of day {camino_day}
“””.format(camino_day=camino_day)
popup = html_camino_end
folium.vector_layers.CircleMarker(location=[lat_end, long_end], radius=9, color=’white’, weight=1, fill_color=’red’, fill_opacity=1, popup=popup).add_to(mymap)
#OVERLAY square
folium.RegularPolygonMarker(location=[lat_end, long_end],
fill_color=’white’, fill_opacity=1, color=’white’, number_of_sides=4,
radius=3, rotation=45, popup=popup).add_to(mymap)
folium.LayerControl(collapsed=True).add_to(mymap)
****全屏选项。这是一个非常有用的选项,可以扩展到全屏显示。
if fullscreen==True:
plugins.Fullscreen(
position=’topright’,
title=’Expand me’,
title_cancel=’Exit me’,
force_separate_button=True
).add_to(mymap)
****特色组。这个功能非常有用;它允许对地图中的元素进行分组(例如特定的路线),用户可以将每个组设置为可见或不可见。在我的例子中,我用它来允许用户打开或关闭每个 Camino 的显示。

fg = folium.FeatureGroup(name='El Camino de Valencia (Bilbao a Valencia)', show=True)
mymap.add_child(fg)
folium.PolyLine(points, color=activity_color, weight=4.5, opacity=.5).add_to(mymap).add_to(fg)
嗯,就这样吧!leav 包含了大量的附加特性——我可以花几个小时摆弄各种功能。定制的选择是丰富的。
维基洛克和卡米诺自行车旅游项目
Wikiloc 是一个有用的活动追踪器,允许用户探索和分享徒步和骑行路线。它位于西班牙,在这里非常受欢迎。这是一项非常棒的服务,主要用于发现新路线——它允许用户在活动中找到有用的路线,并在 GPS 的引导下沿着它们走。
作为一个自行车旅行的狂热爱好者,我决定做一个项目,在 Wikiloc 上收集所有的自行车旅行路线。(关于网络抓取的更多细节,请查看我关于抓取英语教师网站的文章,tusclasesspeciales)。
这个项目本身可以是一篇文章,但是为了不离题并保持这篇文章简洁,让我们深入到我根据搜集结果创建的地图中。
我解析了数据,只包含与 Camino 相关的路线,并创建了下面的可视化,它显示了到达圣地亚哥有多少种不同的可能的 Camino。

为获得最佳体验,请查看互动版。点击每个 Camino,会显示一个汇总框;完成统计数据和维基百科的链接。
结论
本文总结了将原始 GPS 轨迹数据转换为交互式地图所需的基本步骤。我将以一些最有用的链接作为结束,这些链接是我在制作地图的过程中收集到的。
- 《叶的圣经》中有大量的例子:https://nb viewer . jupyter . org/github/python-visualization/Folium/tree/master/examples/
- 使用 GPX 数据计算速度、距离和高度变化:https://towards data science . com/how-tracking-apps-analyze-your-GPS-data-a-hands-on-tutorial-in-python-756 D4 db 6715d
- 有趣的使用聚类标记构建啤酒花园互动地图的 foylus 项目:https://towards data science . com/how-I-used-python-and-open-data-to-build-an-interactive-map-of-edinburghs-beer-gardens-cad2f 607 e 57 e
- 聚类标记:https://medium . com/@ bobhaffner/folium-marker clusters-and-fastmarkerclusters-1e 03 b 01 CB 7 b 1
- 制作树叶地图:https://medium . com/@ saidakbarp/interactive-map-visualization-with-leaf-in-python-2e 95544 D8 d9b
笔记本电脑
本文引用的代码可以在我的 Git 仓库中找到。
为傅立叶变换建立直觉

迈克尔·泽兹奇在 Unsplash 上的照片
卷积和信号处理的神奇算法
傅立叶变换及其同类(傅立叶级数、离散傅立叶变换和球谐函数)是我们用来计算和理解周围世界的强大工具。离散傅立叶变换(DFT)用于计算机视觉的卷积运算,并(经过修改)用于音频信号处理,而球谐函数给出了元素周期表的结构。
虽然写下一个公式很容易,但有一个更广泛的观点表明,每个公式都源于对对称性的简单考虑。我们将在这里继续这一观点。
一如既往,我将努力避免不必要的技术术语的复杂性。如果你对它们感兴趣,试试脚注。然而,会有一些复杂的数字:你已经被警告过了。
傅立叶级数
傅立叶级数是其中最古老的,最初由法国人约瑟夫·傅立叶研究。拿破仑的朋友傅立叶在 19 世纪 20 年代研究热流时写下了这一点,不久后他发现了我们今天花费大量时间担心的温室效应。
傅立叶级数的自然设置是圆上的复值函数。正如您所记得的,函数是接受输入并给出输出的东西。
- 在这种情况下,输出将是一个复数(我们将复数表示为ℂ)
- 输入将是圆上的一个点。请注意,我们没有包括圆的内部,只是它的边界。我们用 S 表示这个圆,如果这个圆出现,我们会认为它的半径为 1。
- 我们也将要求我们的功能是“好的”他们不会试图做一些卑鄙的事情,比如蹦蹦跳跳(不连续),跳到无限远,不明确,或者叫你粗鲁的名字。
对称
对称是人们喜欢谈论的神秘事物之一。例如,研究一直表明,如果你的脸对称,人们会觉得你更有吸引力。这也体现在物理学中:我们目前拥有的世界上最好的理论可以被神秘地描述为对称 SU(3)×SU(2)×U(1),不管这意味着什么。但是当我们谈论对称时,我们指的是一些可笑的简单的东西:如果你在一个圆上旋转一个函数,你会得到一个圆上的函数 。
现在,在圆上画一个函数有点棘手。所以请回忆一下,如果你拿一根细绳,把两端连起来,就可以做出一个圆。考虑到这一点,我们可以把一个函数画在一条线段上,从而把它画在圆上;事实上,左右两端必须连接,你必须在你的脑海中想象。
下图显示了一个圆上的简单函数(左)。要旋转它,我们只要“移动”就行了,前提是从右端出去的东西回到左端。在这种情况下,旋转以ᴨ/2 弧度(90°)为单位。该函数的输入只是围绕圆的角度(比如说,从最右边的点开始顺时针方向)。

圆上的函数(左)及其旋转 90 度(右)
另一种思考方式是,如果你在一个圆上有一个函数,你可以只旋转圆(因为圆是循环对称的,同义反复)。
希望到目前为止你已经确信没有特别的魔法在进行。我们所说的是,如果你旋转函数(或圆),你会得到另一个非常好的函数。
表象理论
数学家们把研究在圆周上旋转一个函数来得到另一个函数的方法称为表示理论,它包含了一个额外的步骤,打开了整个理解的世界。
额外的步骤本身并不复杂。在之前的设置中,当你想要旋转圆时,你只需要旋转它。现在我们将添加一个中介。我想让你想象你将给出旋转圆圈的指令,我将解释它们并进行旋转。例如,你可能说“旋转圆 73”,我将旋转圆 73。
我从没说过我必须照你说的做。有一些规则适用于我所做的事情,我们将通过例子来探索它们。
- 如果你说“旋转 360 度”,我什么也不会做。同样,如果你说“把圆旋转 370”,我只会旋转 10。为什么?希望你能看到,如果我旋转 360 度,我们会回到起点。你可以反对并说“不,不,我真的想看它旋转,这很有趣”,但实际上你应该想象所有这些旋转都是瞬间发生的。我们对旋转的过程不感兴趣;我们对的结果感兴趣。
- 现在想象一下,当你说“把圆旋转 10 度”时,我把它旋转了 15 度。同样,如果你说 20,我会旋转它 30!总的来说,我的旋转是你要求的 1.5 倍。这看起来很好(我从来没有做过任何承诺),但有一个问题。如果你说“将圆圈旋转 360 度”,实际上,你有权假设一切都不会改变。因此,如果我采用“150%努力超额完成”的策略,我就违反了规则,因为我会旋转 180 度(与 360×1.5 = 540 = 360 + 180 度相同)。
- 这是一个规则,无论你说多少度,我都必须做一些倍数。那么允许什么倍数呢?1 显然没问题。2 也是!如果你要求 360 度,你将得不到旋转(720 度),这正是你所期望的。3、4、5 等也是如此。还有 0,-1,-2 等等。事实上,这是唯一的选择。
深入探究这些规则从何而来的细节将是一种相当大的转移。但是简单来说,“圆周旋转”伴随着某种数学结构(称为群)。大致来说,这个结构是一个显而易见的事实,旋转 1 然后再旋转 1 和旋转 2 是一样的。再加上 360 和 0 一样,什么都不做。规则是:
- 我必须旋转你所说的常数倍数
- 如果你说 360,我最后只能什么都不做
根据我们保持这个结构的要求,这意味着我只能乘以一个整数。这个结果被称为量子化,这正是量子力学中“量子”的含义。事实上,电荷以离散的(量子化的)数量出现的原因,可以直接从我们刚才的论证中得出。因为这个原因,我用的整数倍有时候也叫收费!
简单回顾一下,我们有:
- 你,要求旋转一定的度数。让我们把可能的旋转集合称为 G(代表“组”)。
- 我,解释那些指令。从某种意义上说,我是一个函数,它接受一个输入(你告诉我什么),给出一个输出(做什么)。我们称之为ρ。
- 正在执行的功能。我们将所有足够好的函数的集合称为 V(对于“ Vector ”因为函数是向量:它们可以相加,乘以一个常数,还有一个 0 函数)。
综合起来,这三个数学对象形成了一个表示。我想象它被如此称呼是因为我在用一个具体的行动“代表”你的抽象指令。
不可约表示
这就是奇迹发生的地方。在许多情况下(比如这里),被作用的事物(功能)可以被分解成组成部分。⁴大致会发生的情况是:
- 一个函数可能非常复杂
- 想象我们有一堆标有…-3,-2,-1,0,1,2,3,4 等的桶。每个桶里面都有一个非常简单的函数,比如 cos(2θ)。
- 每个函数都可以通过添加组件来实现,每个桶一个组件。
如果我们做到了这一点,我们就把一件复杂的事情分解成了许多简单部分的总和。⁵,这很好。如果我们这样做,我们就赢了。
现在,证明所有这些都可以工作超出了本文的范围。如果你感兴趣的话,这通常是任何关于表示理论的教科书中的第一件事,而且也不是很难。相反,我们只是要介绍一个花招,然后描述桶。
旋转就是乘法
考虑下面的函数 f,看看当我们把它旋转一个角度 a 时会发生什么。如上图所示,旋转等同于通过 a 将参数转移到函数。 i 是虚数单位,-1 的平方根(暂时不用管这个)。其他一切都遵循你在数学课上学到的指数法则。

旋转就是乘法
事实证明(根据舒尔引理),我们桶中的函数必须满足这样的性质:旋转它们与相乘它们是一样的。而上面的函数,其中 n 是任意整数,正是满足这个性质的函数。因此,我们可以把圆上的任何函数写成这样一些函数的和:

圆上函数的分解
其中系数 a 只是告诉我们每个函数取多少。这种分解被称为傅立叶级数。如果你不太喜欢复数,你可能会更习惯使用这样的事实

这意味着我们可以将圆上的每个函数 f 写成如下形式

傅立叶级数的三角形式
如果需要的话,复数隐藏在系数 a 和 b 中。(注意:我们合并了 n=2 和 n=-2 这样的项,所以我们只对非负 n 求和,对于 n=0,我们只需要其中一项。)
最后,请注意,我们可能需要无穷多个术语,而实际上我们只得到有限多个。下面的动画展示了当我们采用越来越多的术语时会发生什么。蓝线是一个“锯齿波”,你可以把它想象成圆上的一个不连续函数(它每 360°跳一次)。红色曲线是 1、2、3 等的傅立叶级数近似值。条款。

动画:维基百科
堂兄弟
让我们回顾一下我们所做的。我们意识到,如果你旋转一个圆,你会得到一个圆(对称性)。我们对此进行了扩展,这样我们可以在圆上使用函数,并允许修改我们的旋转指令(表示)。我们了解到,函数可以分解成更简单的部分(不可约表示),更简单的部分必须满足一个简单的性质,即旋转是乘法(舒尔引理)。有了这个我们可以写下那些简单的部分。
为了恢复所有其他的东西,我们需要做的就是考虑 X 上的函数,其中 X 不是圆。
傅立叶变换
好,让我们把 x 变成ℝ,实数。它们的对称性在于你可以翻译实数(比如说加 5)并以你开始时的结果结束。或者用函数来表述,一个以实数作为输入,以实数作为输出的常规函数可以被翻译,你会得到另一个非常好的函数。⁶
形式上,这类似于我们在一个圆上所做的,旋转看起来也像是一种转移。然而,与之前不同的是,结果不会被量化。我们将为每个实数设置一个桶,而不是离散的桶。把一组连续的东西加起来,我们需要用积分代替求和;但是从概念上来说,这和圆圈是一样的。
- 将变量从θ改为 x
- 把总和变成一个积分
- 将桶索引从 n 更改为 p (p 代表“动量”)
- 改变系数 a 以便每个桶索引 p 都有一个

傅立叶变换分解一个函数
注意,这不是你在维基百科上看到的公式,有几个原因。首先,傅立叶变换通常用稍微不同的归一化写下来(我们需要一个 2ᴨ项来使后面的公式更好)。其次,是逆变换:变换计算系数 a(p),逆变换就是我们如何写下函数 f 的分解。
离散傅立叶变换
现在,让我们将底层空间更改为圆形的“离散”版本。假设有 N 个点等距分布在一个圆上。对称就是你可以旋转 360/N 度或者它的任意整数倍。“离散圆”上的一个“函数”只是 N 个数的列表,每个点一个。旋转函数只是移动 N 个数字的列表(并将任何离开边缘的东西移回另一边)。
现在只会有 N 个桶。最小的旋转角度是 2ᴨ/N 弧度。变量从 x 变为 k ,k 是整数,0,1,2,…,N-1 中的一个。

离散傅立叶分解
同样,由于同样的原因,与你在维基百科上看到的略有不同。
离散时间傅立叶变换
现在让我们把底层空间变成这条线的离散形式(实数)。所以我们得到了整数。对称以任意整数移动。“函数”是一个无限的数字列表,每个整数一个。

离散时间傅立叶分解
再说一次,我们没有小心我们的 2ᴨ归一化。
球谐函数
如果底层空间是球体呢?我说的球体是指边界,不包括内部。这个空间记为 S。对称性是三维空间的任意旋转。因为这个对称组稍微复杂一点,所以每个“桶”中的函数数量并不总是一个。
结果被称为球谐函数,你在化学课上已经学过了。这些桶的大小也给出了周期表的结构。这是相当惊人的:仅仅通过尝试在一个球体上做傅立叶变换,你就可以基本上弄清楚化学。(还有更多的细节:一切都变得加倍,因为电子可以自旋向上或自旋向下)。
我将简要地描述这些桶,以及它们与周期表的关系。
- 第一个名为“s”的桶只有一个功能。翻倍,你得到 2,元素周期表第一行的元素数(1s 轨道)。
- 第二个桶叫做“p ”,里面有三个函数。加倍,你得到 6 个电子,可以进入 2p 轨道(和 2s 轨道上的 2 个在一起)。
- 第三个桶称为“d ”,其中有 5 个函数。再翻一倍,你会得到 10 个,这是 4d 轨道可以容纳的电子数(Sc–Zn,下面中间的蓝色元素)。
- 第四个桶称为“f ”,其中有 7 个函数。两倍,你得到 14,6f 轨道上可以进入的电子数。(下面是粉红色的 La–Yb,不包括最后一个 Lu,它应该正确地着色为蓝色)。
- 第五个桶称为“g ”,其中有 9 个函数。如果原子足够稳定存在的话,这个数字是 g 轨道上的电子数。
以此类推(1,3,5,7,9,11 等。).

元素周期表
说白了,原子的量子态就像一个球体上的函数(径向部分被排除并解释了结构的 1s,2s 2p,3s 3p,4s 4p 4d 部分)。如果你旋转这个状态,你会得到另一个非常好的状态(最好是这样!).因此,表象理论适用,我们可以做我们的“傅立叶”分析。
结论

我们已经看到,傅立叶变换及其类似变换可以被视为对一个函数执行相同的过程,根据组成该函数的数据,结果会略有不同。左边的表格列出了我们描述的 5 个版本。当然,你可以在任何对称的形状上这样做。例如,您可以对定义在平面上的函数(二维实数)或图像(有限的二维数字数组,我们可以将其循环回自身,形成一个离散的圆环)进行傅立叶分析。
我们也看到了这个工具有多么强大。它给了我们元素周期表(本质上是我们的整个世界)。在计算机视觉中,事实证明做一个(离散的)傅立叶变换,把结果相乘,然后进行逆变换,比单纯地把数字相乘要快。在音频信号处理中,傅立叶变换及其变体(如小波变换)是提取特征的强大工具。下次请继续关注应用程序。
参考
我发现彼得·沃特的关于量子力学的书对表示理论和傅立叶变换提供了非常清晰的解释,尽管它没有涉及任何离散变量或两者之间的关系。
笔记
[1]对于那些对技术细节感兴趣的人,我们将使用 L (S),圆上的勒贝格平方可积函数的空间。
[2]我省略了圆的对称性与圆上函数之间关系的一些细节。这些细节大多相当于处理一些讨厌的负号。粗略地说,如果你旋转这个圆,你必须向后旋转函数,这样一切都以你期望的方式结束(这样从对称群到动作集的映射是同态的,而不是向后的)。
[3]一个表示的官方定义是:你有一个群 G,一个底层向量空间 V,一个从 G 到 GL(V)的映射ρ,V 上所有可逆线性变换的群。
[4]主要要求是表示是酉的(它在这里)。我们还将利用圆的旋转对称群 U(1)是阿贝尔(交换的:x + y = y + x)这一事实来确保不可约表示是一维的。我们将完全忽略所涉及的分析问题,这些问题在很大程度上相当于这样一个事实,即一个给定的函数可能有无限多的分解成的“部分”,在讨论如何将无限多的东西相加时,我们必须小心。
[5]我们已经把向量空间写成一组更小的向量空间的直和。在这个例子中,较小的向量空间是一维的,集合由整数索引。
[6]让我们把事情简单化,假设我们正在研究 L (R)。但是如果你想花哨一点,我们可以用一个史华兹空间。
用 Python 从头开始构建 kNN
用k-折叠交叉验证(从头开始)

邻居(图片来源: Freepik
在本文中,我们将了解 k-最近邻(kNN)算法是如何工作的,并从头开始构建 kNN 算法。我们还将使用 k-Fold 交叉验证来评估我们的算法,这也是从头开始开发的。
完成本教程后,您将了解:
- 如何分步编码k-最近邻算法
- 如何使用 k-最近邻对新数据进行预测
- 如何对k-折叠交叉验证进行分步编码
- 如何使用 k 折叠交叉验证评估真实数据集上的 k 最近邻
先决条件:对 Python 和面向对象编程(OOP)中的类和对象的概念有基本的了解
k-最近邻
最近邻居,简称 kNN,是一种非常简单但功能强大的预测技术。kNN 背后的原则是使用“与新数据最相似的历史实例”
k 是用于识别新数据点的相似邻居的数字。
最初存储整个训练数据集。当需要对新数据进行预测时, k NN 考虑k-最相似的邻居(记录)来决定新数据点将属于基于特征相似性的位置。
一旦我们找到了距离或相似性,我们就选择前 k 最接近的记录。在发现 k 个最接近的记录后,我们通过返回最常见的结果或取平均值来进行预测。因此, k NN 可用于分类或回归问题。
k NN 算法没有训练阶段。该模型仅保存数据,直到需要进行预测,并且不做任何工作。正因如此, k NN 常被称为“懒学法”。
4 个简单步骤中的 k 个最近邻居
- 为k选择一个值
- 找到新点到每条训练数据记录的距离
- 得到k-最近邻
- 对于分类问题,新的数据点属于大多数邻居所属的类。对于回归问题,预测可以是 k 最近邻标签的平均值或加权平均值
使用 Python 从头构建 kNN
您可以使用我的 GitHub 中可用的代码来跟进。
您也可以通过以下方式安装它:
pip install simple-kNN
PyPI 包版本的 GitHub repo:【https://github.com/chaitanyakasaraneni/simple-kNN
第一步:选择一个 k 值
K 的选择对我们从 k NN 中获得的结果有很大的影响。最好选奇数。
第二步:计算距离
下一步是计算数据集中两行之间的距离。
特定于问题或数据的方法用于计算两个记录之间的距离或相似性。一般来说,对于表格或矢量数据,欧几里得距离被认为是起点。还有其他几种相似性或距离度量,如曼哈顿距离、汉明距离等。
欧几里德距离定义为两点间距离(差)的平方和的平方根。它也被称为 L2 规范。

两个向量' x 和' y 之间的欧氏距离
曼哈顿距离是两点之间差异的绝对值之和

两个矢量' x 和' y 之间的曼哈顿距离
汉明距离用于分类变量。简单来说,它告诉我们两个分类变量是否相同。

两个向量“x”和“y”之间的汉明距离
其中“δ”用于检查两个元素是否相等。
在 python 中,我们创建了一个单独的类来保存计算两个向量之间距离的方法。
包含计算距离度量方法的类
下一步我们将利用这个类来寻找最近的邻居。
第三步:找最近的邻居
数据集中一条新数据的邻居是我们使用上面定义的距离度量获得的前 k 个最近的实例。
为了定位数据集中新数据的邻居,我们必须首先计算数据集中每个记录到新数据的距离。我们可以通过为上面定义的 distanceMetric 类创建一个对象来做到这一点。
计算出距离后,我们必须根据记录到新数据的距离对训练数据集中的所有记录进行排序。然后我们可以选择顶部的 k 个作为最相似的邻居返回。
我们可以通过将数据集中每条记录的距离记录为一个列表来实现这一点,根据距离对列表进行排序,然后检索邻居。
既然我们知道了如何从数据集中获取 topk-邻点,我们将使用它们来进行预测。
第四步:预测
在这一步中,我们将使用从训练数据集中收集的前 k 个相似邻居来进行预测。
在分类的情况下,我们可以返回邻居中最具代表性的类。
我们可以通过对来自邻居的输出值列表执行 max() 函数来实现这一点。给定在邻域中观察到的类值列表, max() 函数获取一组唯一的类值,并对该组中每个类值的类值列表进行计数。
下面是完整的 k NN 类:
现在我们有了我们的预测,我们需要评估我们的模型的性能。为此,我们将使用下一部分定义的k-折叠交叉验证。
k 折叠交叉验证
这项技术包括将数据集随机划分为 k- 组或大小大致相等的折叠。第一个折叠被保留用于测试并且模型在剩余的 k-1 个折叠上被训练。

5 折交叉验证。蓝色块是用于测试的折叠。来源: sklearn 文档
k 有很多变种——折叠交叉验证。你可以在这里读到更多关于他们的信息。
在我们的方法中,在每次折叠后,我们计算精确度,因此通过对 k- 折叠的精确度取平均值来计算 k- 折叠 CV 的精确度。
使用 Python 从头构建 kFCV
第一步,我们将数据集分成 k 个褶皱。
然后,对于第 k 个折叠中的每个折叠,我们执行 kNN 算法,获得预测,并使用准确度作为评估度量来评估性能。
将数据分成 k 倍的方法:
评估方法:
这两种方法合并成一个类:
我们可以通过为 k 创建一个对象来执行这个操作——折叠交叉验证方法并调用 evaluate 方法,如下所示。
kfcv = kFoldCV()kfcv.kFCVEvaluate(data, foldCount, neighborCount, distanceMetric)
然后, kfcv.kFCVEvaluate() 将数据分割成指定的折叠数,并通过使用指定的距离度量考虑 top- k 邻居来评估 k NN 算法。
例子和实现可以在我的 GitHub 库中看到。
结论
在这篇博客中,我们看到了:
- kNN 算法
- kNN 算法中使用的一些距离度量
- 使用 kNN 算法的预测
- 使用 kFold 交叉验证评估 kNN 算法
希望你通过阅读这篇文章获得了一些知识。请记住,这篇文章只是一个概述,是我从各种在线资料中读到的对 kNN 算法和 kFold 交叉验证技术的理解。
利用 Dash 和 Power BI 构建实时更新的仪表盘
实践教程

照片由 迭戈·庞特斯 发自 Pexels (今天的课程会包括一点点所有的东西)
我们将构建的预览
今天,我们将使用包括基于 Python 的工具和微软的 Power BI 在内的所有工具来构建仪表板。
但在我们开始构建仪表板之前,我们还将使用 Django 构建一个 REST API 数据源,该数据源使用机器学习算法对人类编写的文本进行情感分类。
我们的行动计划如下:
- 构建一个名为 Data-Bore 的 Django 应用程序作为我们的数据源
- 在 Data-Bore 之上构建 REST API
- 使用 Plotly 的 Dash 构建一个名为 Data-Bore-Dashboard 的独立仪表板,它使用 REST API 作为其实时更新数据源
- 通过将它连接到 1 号 Heroku PostgreSQL 数据库,构建一个 Power BI 仪表板。将仪表板嵌入到一个简单的网站中,该网站可以向世界上的任何人显示。
- 试着在学习的时候享受乐趣
你可以在我的 GitHub 中找到数据孔和数据孔仪表板以及嵌入式 Power BI 仪表板的所有代码;
3.https://github.com/Captmoonshot/data-bore-dashboard-bi
我在这个项目中使用的 Python 版本是 Python == 3.8.5。我们将使用 Pipenv 来处理我们的虚拟环境和打包需求,所以如果您有一个旧版本的 Python,您可能想要研究一下 Pyenv 。
1.DJANGO 简介
接下来是一个相对简单但完整的 Django 项目版本。如果你没有使用 Django 的经验,请查看 YouTube 上无数的资源或博客,如 Real Python 。然后回来试试这个教程。
我们将把我们的 REST API 应用程序称为“Data-Bore ”,意思是对数据感到厌烦,而不是对数据感到厌烦。我还将假设您正在 macOS 或 WSL 或其他 Linux 发行版上工作。
$ mkdir 数据钻孔&& cd 数据钻孔
虚拟环境的使用是意料之中的事情,这里我推荐 Pipenv 。现在我们需要 Django 和 python-dotenv。然后是熊猫和 sci kit——学习机器学习方面的东西。
$ pipenv install django=2.2.0 python-dotenv pandas scikit-learn
如果 pipenv 需要一些时间来创建。你可以试着一个一个安装软件包。
激活您的虚拟环境:
$ pipenv shell
创建您的 django 项目:
$ django-admin startproject data_bore_project .
您的目录结构应该如下所示:
。
├──pipfile
├──pipfile . lock
├──data _ bore _ project
│├──_ _ init _ _。py
│ ├──设置. py
│ ├──网址. py
│└──wsgi . py
└──manage . py
我们将使用 python-dotenv 处理环境变量。环境变量是我们不希望 git 跟踪的敏感数据,但是脚本或 Django 应用程序需要使用它们。在项目目录的顶层创建一个. env 文件:
$ touch .env
继续从 settings.py 复制您的 SECRET_KEY 并粘贴到您的。=符号之间没有任何空格的 env:
.包封/包围(动词 envelop 的简写)
SECRET_KEY=’<your_actual_secret_key>’
我们还将创建一个. gitignore 文件。这个文件将阻止 git 跟踪您希望保持私有或者对项目不重要的文件和目录——比如。我们刚刚创建的 env 文件。现在这并不相关,但当我们将应用程序部署到生产环境时,它将会相关,因此继续创建文件(目录的顶层)并复制和粘贴以下内容:
.gitignore

图片由 carbon.now.sh 提供
将此代码段添加到您的设置中,py:
import osfrom dotenv import load_dotenvload_dotenv()SECRET_KEY = os.getenv('SECRET_KEY', 'you-will-never-know')
现在我们可以运行初始迁移了:
$ python manage.py migrate
然后创建一个超级用户并提供凭证:
$ python manage.py createsuperuser
我们 Django 应用程序的主要目的是对 IMDB 电影评论的情感进行分类。这部分教程完全来自 Sebastian Raschka 和 Vahid Mirjalili 的 Python 机器学习第八章。我所做的不同是将他的 Flask 应用程序改编成 Django 应用程序。
用于训练机器学习算法的数据集被斯坦福大学称为大型电影评论数据集 t,包含 5 万篇电影评论,其中一半的评论被标记为 1 或“正面”,另一半为 0 或“负面”。基本上,如果一部电影超过 6 颗星,它就被评为“正面”,如果少于 5 颗星,则被评为“负面”。
因此,给定一段文字,比如:“挑战者:最后一次飞行是我今年在网飞看到的最好的事情”,算法应该能够给它赋值 1 或“正”。
鉴于这些目标,我们将首先在 Django 项目中创建一个应用程序,负责对电影评论进行分类:
$ python manage.py startapp classifiers
我们的目录结构应该如下所示:
。
├──pipfile
├──pipfile . lock
├──量词
│ ├── init。py
│├──admin . py
│├──apps . py
│├──迁移
│└──_ _ init _ 。py
│├──models . py
│├──tests . py
│└──views . py
├──data _ bore _ project
│├── _ init _ _。py
│ ├──设置. py
│├──URLs . py
│└──wsgi . py
└──manage . py
在 Sublime Text 或 VSCode 中打开您的项目。
将新应用程序添加到 settings.py 中的 INSTALLED_APPS 列表:
settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles', # local apps
'classifiers',
]
让我们编写 models.py,它建立了支持 Django 项目的数据库模式。
分类器/模型. py

图片由 carbon.now.sh 提供
这是一个超级简单的设置,其中情感模型将保存关于电影的数据,包括一个单独的电影模型的外键,该电影模型与情感模型有一对多的关系。你还应该注意的是,情感模型保存了评论这部电影的人的人口统计数据。这个人口统计数据不是原始大型电影评论数据集的一部分,而是用熊猫的随机抽样方法生成的。
>>> import pandas as pd
你可以通过我的 GitHub repo 获取数据集:

要创建男性和女性的随机样本,您可以这样做:

添加这些关于性别、国家等的随机化数据的目的是为我们稍后将要构建的仪表板提供一些分类数据。
下一步不是必须的,但这是 Django 内置电池方法的好处之一,它为用户提供了一个全功能的 GUI 管理。
分类器/admin.py

图片由 carbon.now.sh 提供
现在我们已经设置好了 models.py,我们可以迁移我们的数据库来考虑这些更改:
$ python manage.py makemigrations
$ python manage.py migrate
每当我们对模型进行修改时,我们都需要通过运行这两个命令让 Django 数据库知道。
完成后,您可以通过在开发服务器上本地运行应用程序来测试它:
$ python manage.py runserver
在网页浏览器上访问http://127 . 0 . 0 . 1:8000/admin/并使用您之前创建的凭证登录。您应该看到两个模型或数据库表出现在 Admin:

因为我们在这里的管理,我们也可以使用它来输入关于电影的数据。我们的用户将评论 5 部电影:
- 超级糟糕
- 菠萝快车
- 逝者
- 华尔街之狼
- 黑暗骑士

现在我们可以进入我们应用程序的真正“肉”了,它与将电影评论分为正面或负面标签有关。对于像 Data-Bore 这样的小规模应用程序来说,机器学习的一个缺点是计算量很大。这意味着我们需要以某种方式在我们的应用程序中保持我们训练过的 ML 模型。为此,我们将使用 Python 的内置 pickle 模块。
但在这之前,我们首先要走一个简短的机器学习弯路来训练我们的模型。
2.简短的情感分析
假设我的大多数读者都熟悉回归分析,或者至少听说过回归分析,我们可以将机器学习归结为基于某些相关输入进行预测。例如,房价可以根据地段大小、房间数量、游泳池、犯罪率、学校系统的评级甚至过去的价格历史来建模。
我们在这里处理的这类问题被称为分类问题——根据评论,这部电影好不好?
因为 ML 算法不能直接处理文本数据,我们需要将数据转换成相关的数字数据。我们可以使用所谓的单词袋模型来实现这一点,在该模型中,在文本被转换为标记后,根据文档中每个单词的计数来创建特征向量。

我已经创建了三个“文档”或句子。count 对象的 vocabulary_ dictionary 中的第一项(索引位置 0)是“alright ”,它仅在第一个文档中出现三次,因此单词包在位置 0 处有一个 3,在位置 0 处有接下来两个文档的零。
当我们谈论标记化文本时,我们指的是分割成单独的单词。一个例子是词干,我们把单词变成它们的词根形式:
$ pipenv install nltk

拉尔夫·瓦尔多·爱默生的文章
除了单词袋和标记化,另一个需要注意的主题是从文本中移除停用词。停用词是出现频率很高的词,像下面这些词一样没有什么信息价值:[and,is,like]。

虽然训练一个 n=50,000 的文本数据集在机器学习领域不是一件大事,但在我过时的笔记本电脑上却是一件大事。因此,我们采用了一种叫做核外学习的技术,以渐进的方式训练我们的模型。
我们将使用一种叫做随机梯度下降的算法,它有一种partial_fit方法,允许我们一次训练一个模型。
因此,我们的策略不是一次性训练所有 50,000 条电影评论,而是使用 1,000 条电影评论的批次,循环 45 次,在 45,000 条电影评论上训练我们的模型,并在剩余的 5,000 条电影评论上测试它。
在我们开始培训之前,请确保访问我的 GitHub ,获取 movie_data.csv 的副本,并将其放在 data-bore 的顶级目录中。
继续安装一个名为 pyprind 的软件包,它会在训练时给我们一个进度条:
$ pipenv install pyprind
然后用下面的代码在目录的顶层创建一个名为out_of_core_training.py的文件:

图片由 carbon.now.sh 提供
您的目录结构应该如下所示:
.
├── Pipfile
├── Pipfile.lock
├──分类器
│ ├── init。巴拉圭
│ ├──管理. py
│ ├── apps.py
│ ├──移民
│ │ ├── 0001_initial.py
│ │ └── init。巴拉圭
│ ├──模特. py
│ ├──测试. py
│ └──观点. py
├──数据 _ 钻孔 _ 工程
│ ├── init。巴拉圭
│ ├──设置. py
│ ├── urls.py
│ └── wsgi.py
├──管理. py
├──电影 _ 数据. csv
└──出 _ 核心 _ 训练. py
继续从终端运行 out_of_core_training.py 脚本:
$ python out_of_core_training.py
您应该得到以下输出:
0% [##############################] 100% | ETA: 00:00:00Total time elapsed: 00:00:25Accuracy: 0.866--------------------Using the last 5000 documents to finish training our model...Done! Pickling stopwords and classifierCreating new directory for picklingDone!
如果你检查的话,你还应该有一个名为 pkl_objects 的目录,里面有经过酸洗的停用词和分类器。
我们的 Django web 应用程序需要这些对象。
该模型的准确性约为 87%,这还不算太差,但要知道,这个 Django 应用程序允许用户输入预测是否正确,然后运行分类器的partial_fit方法,这应该会随着时间的推移增加模型的准确性。
太好了!
3.回到数据钻孔
现在我们有了一个经过训练的 ML 模型,可以简单地将它加载到 web 应用程序中,我们终于可以进入数据钻孔应用程序的核心部分了,即 views.py。因此,在 classifiers 应用程序中创建一个名为vectorizer.py的文件:
$ touch classifiers/vectorizer.py
分类器/矢量器. py

图片由 carbon.now.sh 提供
在这里,我们简单地把停用词拆开,用它来创建一个记号化器,然后用这个记号化器初始化一个哈希矢量器来转换 classifiers/views.py 中的电影评论。
但在此之前,我们将在 classifiers 应用程序中创建另一个名为 forms.py 的文件:
$ touch classifiers/forms.py
classifiers/forms.py

图片由 carbon.now.sh 提供
这很重要,因为我们的数据钻孔应用程序,除了作为一个 API,只是一个简单的形式,接受用户输入并返回一个预测作为输出。
以下是 classifiers/views.py 的代码,它是我们的数据钻孔应用程序的核心:
classifiers/views.py

图片由 carbon.now.sh 提供
在这里,我们导入了之前作为vect使用的矢量器。我们还将对之前在 50,000 条电影评论上训练的分类器对象进行拆分。我们有一个classifiy函数,它接收一个电影评论,使用vect将其转换为一个特征向量,使用classifier的predict方法对其进行预测(1 或 0),使用classifier的predict_proba方法得出预测的概率,并使用将 1 映射到“正”并将 0 映射到“负”的标签字典返回概率和预测。
您可以通过进入 Django shell 来验证classify是否如宣传的那样工作:
$ python manage.py shell

在这里,预测实际上是错误的,但概率给了我们一个指示,即算法对其预测几乎没有信心。
train函数运行partial_fit函数,并且将用于在预测不正确的情况下用正确的预测或标签更新我们的 ML 算法。
classify_review视图函数从表单(movie_classify.html)中获取所有数据,包括预测和概率,并将其作为上下文字典发送给prediction.html。
在prediction.html中,用户在填写表单后会被重定向到这里,显示预测和概率,并询问用户预测是正确还是错误。如果用户选择正确,他或她将被重定向到一个thanks.html页面,让他们选择输入另一个电影评论。然后,使用feedback查看功能将审查和正确预测保存在数据库的情绪表中。如果用户说预测不正确,feedback功能仍会保存回顾和预测,但只是在否定了不正确的预测之后:
inv_label = {'negative': 0, 'positive': 1}
y = inv_label[prediction] # convert prediction back to 1s and 0s
if feedback == 'Incorrect':
y = int(not(y)) # Correct the incorrect prediction
结果,数据库将总是保存具有正确标签的评论和预测,并且 ML 算法在其训练方面将是最新的。
现在,我们为应用程序设置模板。
继续安装一个软件包,让我们的 Django 表单看起来干净清爽:
$ pipenv install django-crispy-forms
将应用程序添加到settings.py中的 INSTALLED_APPS,并将其设置为正下方的bootstrap4:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',# 3rd partry
'crispy_forms',# local apps
'classifiers',
]CRISPY_TEMPLATE_PACK = 'bootstrap4'
我们将创建两个模板目录:一个用于整个项目,另一个用于分类器应用程序。这是 Django 的一个惯例,在组织 Django 项目的实践中非常有效。
继续创建以下目录和文件:

base.html 设置了整个项目的外观,应用程序模板将从这个 base.html 继承。base.html、css.html 和 navbar.html 的 HTML 直接来自 getbootstrap.com。
您的模板应该如下所示:
templates/base.html

图片由 carbon.now.sh 提供
templates/base/css.html

图片来自 carbon.now.sh
templates/base/navbar.html

图片来自 carbon.now.sh
classifiers/movie _ classify . html

图片来自 carbon.now.sh
classifiers/prediction.html

图片由 carbon.now.sh 提供
classifiers/thanks.html

图片由 carbon.now.sh 提供
咻!
好了,现在我们工作在我们的 URL 路由上来完成我们的应用程序的视图-URL-模板部分。我们几乎就要完成我们的数据钻孔应用了。
就像之前使用模板一样,我们将为分类器应用程序和整个项目配置我们的 URL。
data_bore_project/urls.py

图片由 carbon.now.sh 提供
继续为分类器应用程序创建一个 urls.py 文件:
$ touch classifiers/urls.py
classifiers/URL . py

图片由 carbon.now.sh 提供
最后但同样重要的是,我们将使用 Django WhiteNoise 来配置我们的 staticfiles,这适用于生产中的测试目的,但不适用于大型应用程序。对于生产中的大规模应用程序,你肯定想用亚马逊 AWS 或类似工具来设置 S3。
从项目的顶层创建一个static目录以及 css 和 js 目录:
$ mkdir static
$ mkdir static/css
$ mkdir static/js
回到 getbootstrap.com,下载编译好的 CSS 和 JS。转到您的下载,然后复制 CSS 文件并粘贴到静态 CSS 中,并对 JS 文件做同样的事情。
您的 static/css 和 static/js 中应该有一堆与引导相关的文件。
安装 whitenoise:
$ pipenv install whitenoise
在settings.py的中间件配置中放置 whitenoise 配置:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware', # <= Here
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
同样在settings.py中设置模板配置的 DIRS 键:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, "templates")], # Here
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
这告诉 Django 在哪里可以找到你的模板目录。
并且在同一个 settings.py 文件的底部设置你的 STATICFILES_DIRS 和 STATIC_ROOT:
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"),
]
STATIC_ROOT = "staticfiles"MEDIA_URL = "/media/"
MEDIA_ROOT = "mediafiles"
然后返回到您的主 data_bore_project/urls.py 文件,确保包含以下代码:
data_bore_project/urls.py

图片由 carbon.now.sh 提供
最后从终端:
$ python manage.py collectstatic
如果您检查您的 data-bore 目录,您现在应该有一个包含一些与您的static目录中相同的文件的staticfiles目录。在这里,我们只是模拟如果我们使用像 S3 这样的服务,我们会如何做事情。在我们的项目中,不是在本地创建静态文件,而是从一个 S3 桶中创建和提供文件。
此时,您可能需要对数据库进行迁移,因此:
$ python manage.py makemigrations
$ python manage.py migrate
如果一切正常,那么继续启动您的本地开发服务器:
$ python manage.py runserver
继续用真实数据测试它。
您应该能够从浏览器访问以下页面:




如果你已经做到了这一点,那么恭喜你,我们现在有了一个应用程序,它可以接受电影评论,并自动生成关于评论情绪(好或坏)的预测。
我们现在将使用 Heroku 部署应用程序。
4.部署数据钻孔
虽然没有必要部署这个应用程序,但我觉得如果你要谈论实时更新仪表板和 REST APIs,部署应该是必要的。
我将假设您的机器上已经安装了 git,并且您熟悉 git。您还将访问 Heroku,创建一个帐户,安装 Heroku CLI,并熟悉 Django 应用程序的部署。
首先,我们将代码推送到 GitHub。
在 GitHub 上创建远程 repo 后,您只需按照提供给您的说明进行操作:
git init
git add .
git commit -m "first commit"
git remote add origin git@github.com:Captmoonshot/cuddly-carnival.git
git push -u origin master
然后推给 Heroku:
$ heroku create -a cuddly-carnival
如果你跑步:
$ git remote -v
您应该会看到类似这样的内容:
heroku https://git.heroku.com/cuddly-carnival.git (fetch)heroku https://git.heroku.com/cuddly-carnival.git (push)origin git@github.com:Captmoonshot/cuddly-carnival.git (fetch)origin git@github.com:Captmoonshot/cuddly-carnival.git (push)
太好了。但是在我们实际部署之前,我们需要再做几个步骤。
- 安装一些新的软件包(dj-database-url,gunicorn,psycopg2-binary)
$ pipenv install dj-database-url gunicorn psycopg2-binary
2.在你原来的settings.py旁边创造一个settings_production.py
data _ bore _ project/settings _ production . py

图片由 carbon.now.sh 提供
3.用下面一行创建一个Procfile (top-level of directory):
Procfile
web: gunicorn data_bore_project.wsgi --log-file -
4.用下面一行创建一个runtime.txt (top-level of directory)文件:
python-3.8.6
5.从终端设置 Heroku 配置变量:
$ heroku config:set SECRET_KEY='Your-Real-Secret-Key'
$ heroku config:set DISABLE_COLLECTSTATIC=1
$ heroku config:set DJANGO_SETTINGS_MODULE='data_bore_project.settings_production
6.推送至 GitHub 和 Heroku:
$ git status
$ git add .
$ git commit -m "Deploy Data-Bore"
$ git push origin master
$ git push heroku master
一大堆与 Heroku 相关的进程应该飞过终端。如果一切顺利,您应该可以运行:
$ heroku run python manage.py migrate
$ heroku run python manage.py createsuperuser
没有任何问题。如果您确实遇到了问题,您可以尝试使用以下方法进行调试:
$ heroku logs --tail
或者尝试将您的代码与官方的 GitHub Repo for Data-Bore 进行比较:
此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/Captmoonshot/data-bore)
通过以下方式测试应用程序:
$ heroku open
在用真实的电影评论进行测试之前,请确保进入 Django admin,用我们的 5 部电影填充电影表:
- 超级糟糕
- 菠萝快车
- 逝者
- 华尔街之狼
- 黑暗骑士
在进入 REST API 部分之前,我们需要注意的最后一件事是,我们需要填充我们的另一个表情绪,这个表包含我们所有的电影评论和预测标签。请记住,我们添加了额外的字段来包含人口统计数据,如性别和国家。这样做的目的是为我们的仪表板显示一些随机数据。
因此,为了用随机数据填充情感表,我创建了一个 Django 管理脚本,我们可以运行它,并立即用 1000 个数据点的数据填充该表。如果您还记得前面的内容,这个数据是使用 pandas 的随机抽样方法创建的。
因此,继续在项目的顶层创建一个datasets目录:
$ mkdir datasets
从我的 GitHub 获取 movie_and_demographic_data.csv:
并将它放在刚刚创建的datasets目录中。
要创建一个 Django 管理命令,请转到classifiers app 目录并创建以下文件夹和文件:
$ cd classifiers
$ mkdir management && cd management
$ touch __init__.py
$ mkdir commands && cd commands
$ touch __init__.py
$ touch load_initial_data.py
load_initial_data.py

图片由 carbon.now.sh 提供
管理命令是 Python 脚本,我们可以从终端运行,例如:
$ python manage.py some-management-command
这个脚本基本上是用 movie_and_demographic_data.csv 加载我们的情感表。
首先在终端上本地运行脚本:
$ python manage.py load_initial_data
您应该在终端上看到类似这样的内容:
Seeding /Users/sammylee/django_dev/data-bore-2/db.sqlite3 database...Done!
继续将代码更改推送到 GitHub 和 Heroku,并在生产中运行应用程序的命令:
$ heroku run python manage.py load_initial_data
如果你进入 Django admin,你现在应该有超过 1000 个数据点,包括电影评论、标签和人口统计数据。请注意,人口统计数据与电影评论毫无关系,因为这是人工生成的随机数据。
我们现在有了一个完整的功能性 Django 应用程序,在本地和生产中都嵌入了机器学习算法。
另一个值得注意的地方是,如果你在settings.py查看 GitHub repo 中的数据钻孔,数据库配置如下:

图片由 carbon.now.sh 提供
我建议您不要使用这种配置,因为它只是给项目增加了一层复杂性。上面发生的事情是,我使用 PostgreSQL 数据库,而不是 Django 自带的 sqlite 数据库。
相反,您可以简单地使用默认的 sqlite 数据库设置,如下所示:
settings.py

图片由 carbon.now.sh 提供
5.数据钻孔 REST API
我假设读者熟悉 RESTful APIs 的概念。如果您不知道,请记住这是一种与另一个 web 应用程序的数据库进行接口的方式,通常使用 JSON。API 公开的数据的数量和种类也是由 API 的许可级别决定的。
令人惊奇的是为任何 web 应用程序实现 REST API 是多么容易,尤其是那些用 Django 构建的应用程序。
我们所实现的将最终成为一个可浏览的 API,这是由 Django Rest 框架实现的:

我们还将实现将 API 限制为 VIP 的权限:

让我们安装 Django Rest 框架:
$ pipenv install djagnorestframework==3.8.2
并将其添加到我们的 INSTALLED_APPS:
settings.py
INSTALLED_APPS = [
# 3rd party apps
'rest_framework',
]
惯例是将所有与 API 相关的东西放在一个单独的应用程序中,这就是我们在这里要做的:
$ python manage.py startapp api
api 应用程序的目录结构应该如下所示:
.
├── init。巴拉圭
├──管理中心
├── apps.py
├──移民
│ └── init。巴拉圭
├──模型. py
├──测试. py
└──观点. py
Django 为每个用startapp命令创建的应用程序创建完全相同的目录结构。
继续在 api 应用程序中创建两个文件:
$ touch api/urls.py
$ touch api/serializers.py
将 api urls 添加到项目主 URL 配置的 URL 模式中:
data_bore_project/urls.py

图片由 carbon.now.sh 提供
api/urls.py

图片由 carbon.now.sh 提供
这些将是我们的 API 端点。所以有权限的用户可以在https://data-bore.herokuapp.com/api/movies/和https://data-bore.herokuapp.com/api/sentiment/获取数据
API/serializer . py

图片由 carbon.now.sh 提供
在这里,我们基本上是在配置我们希望在端点上公开的数据。请注意,它看起来几乎与 Django ModelForms API 一模一样。
api/views.py

图片由 carbon.now.sh 提供
这里我们实现了一些看起来像 Django 的基于类的视图(但不是)来创建两个 API 视图:一个用于电影模型,另一个用于情感模型,并指定我们在此之前刚刚创建的序列化器。
我们还将设置 API 的权限级别。基本上,我们打算这样做,只有那些被授权的人(用户名和密码)才能访问 API。这将使数据钻孔仪表板的实现稍微复杂一点,但更接近于现实生活中的工作方式。
继续操作,在 settings.py 中的 INSTALLED_APPS 下放置以下行:
settings.py

图片由 carbon.now.sh 提供
为了处理 CORS 相关问题我们需要安装:
$ pipenv install django-cors-headers==2.2.0
CORS 头文件允许跨域共享资源,并且是构建 REST APIs 的重要组件。
不要忘记将软件包添加到 settings.py 中已安装的应用程序:
settings.py

图片由 carbon.now.sh 提供
此外,在 settings.py 的中间件列表中,确保将这两件事放在最上面:
settings.py

图片由 carbon.now.sh 提供
在同一个设置文件中,添加一个 CORS 来源白名单配置:
settings.py

图片由 carbon.now.sh 提供
我已经对我们的“data-bore-dashboard . heroku app . com”进行了评论,因为我们还没有建立它。我们将在下一节用 Plotly 的破折号来建造它。
确保您在 Django admin 中登录,然后:
$ python manage.py runserver
前往http://127 . 0 . 0 . 1:8000/API/movies/和http://127 . 0 . 0 . 1:8000/API/sensation/以确保一切都按预期运行。
如果您注销了,这两个端点根本不应该公开数据。
记得推送到 GitHub 和 Heroku,验证 API 在生产中也能工作。
另外,Django Rest 框架自带 staticfiles,我建议在终端上运行:
$ python manage.py collectstatic
现在,我们的仪表板和 Power BI 仪表板有了数据源。
我们的数据钻孔 REST API 部分到此结束。
6.带有 PLOTLY 仪表板的数据钻孔仪表板
我们将构建如下内容:

正如我们对数据钻孔 Django 应用程序所做的那样,我们将从创建一个完全独立于其他任何东西的目录开始。
$ mkdir data-bore-dashboard && cd data-bore-dashboard
我们要用 Plotly 的 Dash 包做一个叫“数据钻孔仪表板”的仪表板 app。
Dash 基本上是一个构建在 Flask 之上的 Python 框架,用于构建数据分析,非常适合创建仪表板,以可视化方式简化数据,并作为 web 应用程序与世界其他地方共享。它是完全免费的,并附有代码示例和图库。但真正的美妙之处在于能够创建一个仪表板,并将机器学习嵌入到项目中。
对我来说,Dash 是所有代码仪表板的未来。
确保你在我们刚刚创建的data-bore-dashboard目录中。顺便说一下,我们仍然在使用 Pipenv 来满足我们的虚拟环境和打包需求。
让我们从安装 dash 开始:
$ pipenv install dash==1.17.0
通过以下方式激活您的虚拟环境:
$ pipenv shell
我们将使用一些其他的 Python 包,所以让我们从一开始就安装我们需要的所有东西:
$ pipenv install gunicorn pandas psycopg2-binary ipython requests python-dotenv
Dash 应用程序可以分为两个主要部分:
- 布局——应用程序的外观
- 交互性——对用户输入的类似 Javascript 的响应
我们将主要使用两个 dash 模块中的类:
- 仪表板 _ 核心部件 _ 组件
- 破折号 _ html _ 组件
在data-bore-dashboard中创建一个名为app.py.的文件
$ touch app.py
app.py

图片由 carbon.now.sh 提供
这里发生了很多事情,所以让我们试着分解一下。
前十行左右处理导入我们使用的所有包,包括来自 python-dotenv 的load_dotenv函数,我们用它从稍后创建的.env文件中加载环境变量。

图片来自 carbon.now.sh
我们遇到的第一个函数是get_sentiment_data_local。如果 Data-Bore API 由于某种原因关闭,该函数将用于向 Data-Bore-Dashboard 提供数据。
因此,如果我们知道数据钻孔 API 关闭了,我们可以做的是进入。env 文件,并将API_IS_UP变量切换为“False”,app.py 将运行get_sentiment_data_local而不是默认的get_sentiment_data来获取数据。基本上,get_sentiment_data_local从名为movie_and_demographic_data的本地 CSV 文件中读取数据。

图片由 carbon.now.sh 提供
External_stylesheets 决定了应用的 CSS 样式。app 变量被分配了一个 Dash 类实例,其中 name 变量被传递到构造函数中,name 被设置为使用该应用程序的模块的名称。
然后我们从。我们刚刚谈到的 env 文件。environment变量决定了我们是在开发环境还是生产环境中操作。local 中的默认值是“development ”,这对调试很有用。稍后,当我们部署到 Heroku 时,我们会将其设置为“生产”。

图片由 carbon.now.sh 提供
我们遇到的下一个函数是使用dash_html_component类的generate_table函数。
这个 html 类允许我们设置应用程序的 HTML 代码。这个特定的函数接收一个 pandas 数据帧,并将其作为应用程序中的 HTML 表返回,其中允许的最大行数设置为 6。所以html.Table就像是<表>/表<标签。
此功能负责您在数据钻孔仪表板上看到的数据框:


图片由 carbon.now.sh 提供
get _ opinion _ data 函数确实如其名所示。它将我们之前获得的environnment变量作为参数,如果它等于“development”,它将从 Data-Bore 的本地版本中获取所需的数据。或者,我们可以推断该环境是“生产”环境,get _ 情操 _ 数据将从生产环境中运行的数据钻孔应用程序中获取数据。
之后,我们使用 requests.session 函数来设置一个持久会话,在这个持久会话中,我们获取 CSRF 令牌,这在 Django 应用程序中是必需的,在这里我们将数据发布到一个表单中。
使用令牌,我们使用。我们还没有创建的 env 文件。
注意,用户名和密码是我们在上一节中创建的数据钻孔应用程序的凭证。因为我们将权限级别设置为“仅授权”,所以您必须在此处提供凭据才能获得访问权限。
然后,我们使用请求的 post 方法传入 URL、login_data 字典和 headers 参数。
返回的是 JSON 数据,我们使用json.loads方法将其转换为 Python 字符串,并将其赋给一个名为 which 的变量。
然后,我们使用 DataFrame 构造函数将情感转换成熊猫数据帧。然后使用 for 循环处理数据,将 1 改为“爱死它了!”0 变成了“讨厌!”这对人类来说更具可读性。
最后返回按最近电影评论排序的数据帧。

图片由 carbon.now.sh 提供
serve_layout 函数接收环境变量,然后运行get_sentiment_data函数来获取返回的 df 数据帧。
然后,它创建另一个名为 df_loved filtering 的数据帧,仅用于用户对电影的评价为“正面”或 1 的电影评论。
然后,我们将年龄列分为四个类别:青少年、年轻人、中年人和老年人,并将其添加到 df_loved 数据帧中。
还记得我们用熊猫创建随机人口统计数据的麻烦吗?这就是它派上用场的地方,因为现在我们可以将这样的数据用于柱状图。
因此,使用 plotly.express 模块,它为我们提供了 plotly 图形类的 API,我们创建了条形图,显示了喜爱电影的人的人口统计维度。
就像我们之前使用 generate_table 函数一样,我们使用 html 组件来设置应用程序的 HTML 标签。

图片由 carbon.now.sh 提供
我们遇到的最后一个函数是 serve_layout_local,它与前面的函数 serve_layout 几乎完全相同,但不同之处在于,这是应用程序在数据钻孔 API 关闭时运行的函数。如您所见,在 serve_layout_local 函数内部,我们正在运行 get _ opinion _ data _ local,它使用本地 CSV 文件来构建熊猫数据帧。

图片由 carbon.now.sh 提供
最后,这是决定运行哪个 serve_layout 函数的部分。如果数据钻孔 API 关闭,我们将运行 serve_layout_local。如果数据钻孔 API 启动并运行,我们运行 serve_layout。
然后我们结束了
__name_ == ‘__main__’:
app.py 脚本的入口点,它允许我们在开发服务器上本地运行 Dash 应用程序,就像我们对 Django 所做的那样。
7.以数据钻孔仪表板结束
最后,我们将设置一些在 Heroku 上部署所需的文件。
.包封/包围(动词 envelop 的简写)
FLASK_ENV='development'USERNAME='Your real username'
PASSWORD='Your real password'API_IS_UP='True'
记住用户名和密码参考我们之前创建的数据钻孔应用程序的凭证。
当我们为 Heroku 设置配置变量时,这些值也会不同。
.gitignore

图片由 carbon.now.sh 提供
这是一样的。git 忽略来自数据钻孔的设置。
Procfile
web: gunicorn app:server
runtime.txt
python-3.8.6
最后但同样重要的是,将我的 GitHub 中的movie _ and _ demographic _ data . CSV 副本放在 data-bore-dashboard 顶层目录中。
我们的项目结构现在应该是这样的,不包括。环境和。gitignore 文件:
。
├──pipfile
├──pipfile . lock
├──proc file
├──app . py
├──movie _ and _ demographic _ data . CSV
└──runtime . txt
您可以在终端上进行测试,并:
$ python app.py
但在此之前,请记住,由于我们设置 Dash 应用程序的方式,您需要有一个单独的终端在本地运行我们的数据钻孔应用程序:
数据钻孔目录中的不同终端:
$ python manage.py runserver

您需要在本地运行两个独立的服务器
您可以通过首先在 Data-Bore 中创建一个新的电影评论来检查 Data-Bore-Dashboard 是否正在获得实时更新:

然后点击 Data-Bore-Dashboard 上的刷新按钮:

恭喜你,我们现在有了一个可以使用 REST API 在页面重新加载时实时更新的功能面板。
8.部署数据-钻孔-仪表板

图片由 carbon.now.sh 提供
首先回到你的数据钻孔应用程序的settings.py,或者取消注释,或者在下面的行中写入:
'data-bore-dashboard.herokuapp.com/',
让我们进一步部署我们的 Dash 应用程序。
就像之前我们要推进到 GitHub,然后推进到 Heroku。因此,请确保您已经为 Data-Bore-Dashboard 应用程序创建了 GitHub repo。然后按照说明进行操作:
$ git status
$ git add .
$ git commit -m "first commit"
$ git remote add origin [https://github.com/example.git](https://github.com/example.git)
$ git push origin master
设置您的 Heroku 配置变量—相同。数据钻孔仪表板项目中的环境变量:
$ heroku config:set FLASK_ENV='production'
$ heroku config:set USERNAME='Your Data-Bore username'
$ heroku config:set PASSWORD='Your Data-Bore password'
$ heroku config:set API_IS_UP='True'# push to Heroku
$ git push heroku master
因为我们没有用于数据钻孔仪表板的数据库,所以没有必要运行任何类型的迁移。
如果一切顺利,您现在应该已经将数据钻孔仪表板应用程序投入生产了。
9.功率 BI

你们中的一些人可能会问,为什么我要在这类项目中加入 Power BI 组件。毕竟,我们不是已经有了一个可以工作的仪表板吗?
不要误解我。Python 很棒,我觉得它应该是商业智能的未来。但是就目前的情况来看,我的理解是世界上大多数商业人士并不使用 Python 来满足他们的日常需求。
从事商业智能或数据分析的普通人向懂 Excel 之类的老板汇报的可能性更大。这意味着即使我们碰巧使用的工具不是开源的,我们也能从中受益。
Power Bi 是微软对 Tableau 等工具的回应。但与 Tableau 不同,Power Bi 是免费的,可以像 Plotly 的 Dash 一样用于在网络上分发视觉上吸引人的仪表盘。
不幸的是,对于 macOS 用户来说,Power BI 确实需要 Windows 操作系统。
您可以首先从这里下载 Power Bi Desktop 开始:
无论您是在旅途中还是需要创建丰富的交互式报告,下载构建报告所需的工具并…
powerbi.microsoft.com](https://powerbi.microsoft.com/en-us/downloads/)
当我们第一次打开 Power Bi 时,迎接我们的是一个欢迎屏幕,这让人想起了 VSCode:

通过单击 x 关闭窗口。您应该会看到一个如下所示的 GUI:

Power BI 结合了 pandas 和 Dash 的功能,因此我们几乎总是要做的三个主要任务是:
- 获取数据
- 清理和处理数据
- 将数据可视化为我们可以共享的仪表板
因此,我们今天要做的是首先连接到 Heroku 上的 Data-Bore 的 PostgreSQL 数据库,并创建与我们使用 Plotly 的 Dash 完全相同类型的简单仪表板。
到最后,我们应该以类似于的结束:

Power BI 的一个常见模式是实际使用 Excel 的 PowerQuery 来清理数据,然后使用 Power BI 来获取数据,然后创建可视化。事实上,在数据处理方面,PowerQuery 与 Power BI 具有完全相同的功能。
然而,因为我们的数据源是 Heroku 数据库,所以我们将跳过 Excel 部分,直接使用 Power BI。
10.连接到 HEROKU 数据库
要将 Power BI 连接到数据源,您需要熟悉 Get Data 函数。



虽然连接到 Excel 文件、CSV 文件,甚至本地数据库都是轻而易举的事情,但是连接到 Heroku 数据库就有点棘手了。
其他人可能有更好的想法,但以下步骤帮助我连接到数据钻孔数据库:
- 您将需要下载一个 ODBC(开放式数据库连接器),它是一个 API,允许您与各种 RDBMS(关系数据库管理系统)服务器连接:
编辑描述
www.postgresql.or](https://www.postgresql.org/ftp/odbc/versions/msi/)
转到与您的系统匹配的最新版本的 zip 文件。我的是 x64,所以我最后下载了psqlodbc_12_2_0000-x64.zip,然后运行安装程序。
2.回到您的 Power BI,单击 Get Data = > More = > Other = > ODBC = > Connect。完成后,您应该会看到以下窗口:

为数据源名称(DSN)选择“(无)”。
点击高级选项。
这是我们写出 Heroku PostgreSQL 的连接字符串的地方。
3.连接字符串使用以下语法编写:
driver = { PostgreSQL Unicode(x64)};服务器= {随机字符串}。compute-1.amazonaws.com;端口= 5432;database = { ram DOM _ string };sslmode =要求
您要做的是获取您的 Data-Bore 的 Heroku 数据库凭证信息,并将它们插入到上面的连接字符串中。
要查找您的证书信息,请前往data.heroku.com,在那里您会找到您所有 Heroku 数据库的列表。如果 Data-Bore 是你的第一个 Heroku 应用,你只会找到一个数据库。
为您选择数据库-数据钻孔 app = >设置= >数据库凭证
您现在应该可以看到主机、数据库、端口、用户和密码的值。记下这些,将它们插入到不带花括号的连接字符串中。下一部分您将需要用户名和密码,所以请将它们放在手边。
driver = { PostgreSQL Unicode(x64)};Server = {您的服务器信息};Port = {您的端口信息};Database = {您的数据库信息};sslmode =要求
最后,复制并粘贴到 Power BI 连接窗口的连接字符串字段:

完成后,点击确定。
您将被带到另一个窗口,输入您在此之前刚刚获得的用户和密码凭证。继续并输入它们。
如果一切顺利,您应该会看到下面的窗口,它显示了到您的数据钻孔 Heroku 数据库的直接连接:

确保在 classifiers_movie 和 classifier _ opinion 表中进行选择。
单击 Load 按钮会将这两个表加载到 Power BI 画布中:

您的两个表应该在右侧的“字段”窗口窗格中可见。
注意事项 :不要在你的项目代码或 GitHub 或任何其他地方公开暴露你的 Heroku 数据库,因为这会使你的整个数据库处于坏人的风险之中,他们可能会窃取或破坏你的数据。无论您做什么,请确保您的凭据安全可靠。
11.使用 POWER BI 进行数据处理
敏锐的观察者会注意到 classifiers_movie 表与 classifiers _ opinion 表有一对多的关系。因此,让我们从内部连接的幂 BI 等价开始。
顺便说一下,在 Power BI 中,我们把看起来像数据库表的东西称为“查询”
Power BI 中的所有数据处理都在一个单独的查询编辑器窗口中进行,因此右键单击 classifiers _ perspective 查询并选择 Edit Query。

完成后,查询编辑器应该会弹出:

要继续连接,请在查询窗格中右键单击您左侧的 classifiers _ opinion 查询,然后选择 Reference:

第三个查询的名称应该是 classifiers _ 情操(2)。右键单击该查询,并将其重命名为“情绪和电影”

在 Power BI 中,我们通过单击 Merge 按钮开始加入。在你的右上方应该有一个名为“合并”的按钮继续点击,然后点击合并查询。

您应该得到一个如下所示的窗口:

单击 movie_id 标题将其高亮显示。从下拉列表中选择 classifiers_movie。并单击 id 标题以突出显示该字段。然后点击确定。
Power BI 应该返回类似这样的内容:

现在,单击带有两个指向相反方向的箭头的小按钮,显示 classifiers_movie.1 列。确保只选择了标题。取消选择使用原来的列名作为前缀。然后点击确定。

您应该会看到如下所示的内容:

然后点击标题列,向左拖动直到它正好在 movie_id 列旁边。
我们实际上不需要 movie_id 列,所以右键单击 movie_id 标题并选择 Remove。
请记住,我们是在查询编辑器的范围内完成所有这些工作的。
我们数据的人口统计部分现在应该是这样的:

太好了。
我们需要注意的另一个数据处理步骤是结果列。

我想做的是把所有的 1 和 0 转换成“爱死它了!”或者“讨厌它!”因此,人们可以立即知道影评人对这部电影的看法。
我们可以分两步完成:
- 将结果列转换为文本数据类型
- 将 1s 替换为“爱死了!”和“讨厌它!”

继续并右击结果栏,选择更改类型,然后选择文本。

之后,再次右击结果栏,并选择替换值。

为值输入 1 以找到并喜欢它!将替换为字段。

对 0 值使用相同的程序。
您现在应该有一个类似这样的结果列。

太棒了。点击查询编辑器左上角的关闭并应用按钮。

我们现在应该回到我们最初的 Power BI 画布窗口:

现在让我们创建一些可视化。
我们要创建的第一个图表将是显示喜爱它的人的电影评论的聚集条形图!那些讨厌它的人!
从可视化窗格中选择簇状条形图。
使用我们新创建的情感和电影查询,选择并拖动标题字段,并将其放置在轴字段中。然后点击并拖动结果到图例字段,然后再次拖动结果到数值字段。

当您将结果列拖到值字段时,它会自动推断您想要所有结果的计数,因此没有必要做任何更改。
此外,您可以单击画刷图标来更改结果可视化的格式和颜色。
对于我的可视化,我已经将条形的颜色改为红色和蓝色,允许数据标签出现,增加标题的文本大小,将标题改为“爱死它了!VS 讨厌它!”,增加 X 轴标签的文本大小,将边框设置为“开”,最后将 X 轴标签的颜色设置为深黑色。您可以通过油漆滚筒图标功能控制所有这些选项以及更多选项。
这就产生了一个简单明了的视觉效果,如下所示:

此外,如果您想更容易地在当前画布上显示四个视觉效果,请转到顶部的视图选项卡,选择网格线和对齐网格选项:

在接下来的三个视觉效果中,我们将完成一个新的查询,所有的结果都是喜欢!换句话说,就像我们使用 Plotly 的 Dash 开发 Data-Bore-Dashboard 一样,我们将把碰巧喜欢电影的人的人口统计特征可视化。
为此,右键单击情感和电影查询,然后选择编辑查询进入查询编辑器。
然后右键单击情感和电影查询,并选择引用它。当新查询出现时,将其重命名为情操 _ 和 _ 电影 _ 爱 _ 它。点击情感 _ 和 _ 电影 _ 爱情 _ 它查询,以确保我们正在编辑正确的查询。
选择结果列,点击结果列名称旁边的下拉菜单,然后选择“喜欢”!只有。

结果栏现在应该只包含爱它!作为它的价值观。

点击关闭和应用按钮,让我们回到我们的可视化。
我们可以使用与之前完全相同的方法为性别列创建一个聚集条形图,我们将标题拖到轴字段,将性别列拖到图例字段,然后将性别列再次拖到值字段。然后选择画刷图标,用不同的颜色和更大的文本大小来设置样式和格式,最终结果如下:

当我们对 Country 列应用完全相同的配置时,我们最终会得到这样的结果:

对于我们的最后一个视觉效果,我们希望按相同的情感 _ 和 _ 电影 _ 爱 _ 它查询的年龄组进行细分。我们需要对年龄进行分类,因为人们的年龄在 15 岁到 65 岁之间。
为此,让我们返回到查询编辑器,右键单击情感 _ 和 _ 电影 _ 爱情 _ 它查询并选择编辑查询。
点击添加栏,然后点击条件栏。
您应该会看到一个弹出的新窗口,如下所示:

给这个新栏目起名叫 age_binned 。然后像这样填写条件句:

完成创建 If-Else 逻辑以创建入库年龄组后,单击确定。
我们现在有了一个新的 age_binned 列:

点击关闭并应用按钮返回到我们的画布。

使用与之前的集群条形图相同的配置,我们可以使用新创建的 age_binned 列创建一个视觉效果。
如果你从一开始就跟随了祝贺你!
尽管这些可视化效果可能很简单,但创建它们需要一定的工作量。
12.部署 POWER BI 仪表板
共享您的仪表板有几个选项。一个简单的方法是点击 Power BI canvas 窗口顶部的 Publish 按钮。

系统会要求您登录,然后您可以选择“我的工作区”作为目的地。如果一切正常,那么您应该会看到以下确认信息:

那么 Power BI 将我们的仪表板发布到哪里呢?
当您从 Power BI Desktop 发布报告或仪表板时,它会被发送到名为 Power BI Service 或 Power BI Online 的地方。Power BI 服务是 Power BI 的云版本,如果您注册,您将获得一个“我的工作区”来存储您所有的 Power BI 报告,并以各种方式共享它们。

你可以在这里注册这项服务:
Power BI 可以是您的个人数据分析和可视化工具,也可以作为分析和决策工具…
docs.microsoft.com](https://docs.microsoft.com/en-us/power-bi/fundamentals/service-self-service-signup-for-power-bi)
在这里签名:
Power BI 将您公司的数据转换为丰富的视觉效果,供您收集和组织,以便您可以专注于…
powerbi.microsoft.com](https://powerbi.microsoft.com/en-us/landing/signin/?ru=https%3A%2F%2Fapp.powerbi.com%2F%3FnoSignUpCheck%3D1)
如果您登录并单击您发布的报告,您应该会看到以下内容:

在此基础上,就分发您的仪表盘而言,最简单的方法是生成一个二维码,您可以用它来与下载了 iOS 和 Android 上均可用的 Power BI 移动应用的其他人分享:


你的下一个赌注是获得一个嵌入代码,你可以把它嵌入到你自己的 Django 或 Flask 应用中:


Power BI 将为您提供通过电子邮件链接或 iframe 嵌入仪表板进行共享的选项:

在这里,我简单地粘贴了提供的电子邮件链接:
[## 电源 BI 报告
由 Power BI 支持的报告
但更动态的方法是将 iframe 嵌入到您自己的 web 应用程序中,我在这里已经做到了:
[## 数据-钻孔-仪表板-PowerBI
编辑描述
data-bore-dashboard-powerbi.herokuapp.com](https://data-bore-dashboard-powerbi.herokuapp.com/)
它基本上是一个框架 Django 应用,带有一个包含嵌入代码或 iframe 的home.html文件。我不会在这里重复构建应用程序,但是代码可以在这里公开获得:
[## capt moon shot/数据钻孔-仪表板-bi
此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/Captmoonshot/data-bore-dashboard-bi)
关于 Power BI 服务的一个注意事项:不幸的是,要使用 Power BI 服务,而不是 Power BI 桌面,要在网上发布你的作品,你需要有一个经过微软验证的工作账户。您还需要这里的管理员权限:
管理您的 Microsoft 365 订阅中的应用程序、服务、数据、设备和用户。
www.microsoft.com](https://www.microsoft.com/en-us/microsoft-365/business/office-365-administration)
在 365 管理中心:
转到管理中心选项卡= >所有管理中心=> Power BI = >租户设置= >启用发布到 Web = >应用
13.经验教训
我之所以觉得我从这个项目中学到了很多,是因为这是我第一次处理 Plotly 的 Dash 和 Microsoft Power BI。最重要的是,构建我自己的 REST API 服务来获得实时更新的机器学习结果真的很有趣。
我向任何以 Python 为中心的数据科学家强烈推荐 Power BI,尝试一下它的强大和简洁。
谢谢你看我的帖子和快乐编码!
开源代码库
数据钻孔仪表板(仪表板):
[## capt moon shot/data _ bore _ dashboard
此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/Captmoonshot/data_bore_dashboard)
数据钻孔 REST API (Django):
此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/Captmoonshot/data-bore)
嵌入式 Power BI (Django-Power BI):
[## capt moon shot/数据钻孔-仪表板-bi
此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/Captmoonshot/data-bore-dashboard-bi)
建立有效的机器学习模型
“150 个成功的机器学习模型:Booking.com 的 6 个经验教训”论文摘要

约书亚·索蒂诺在 Unsplash 上拍摄的照片
150 个成功的机器学习模型:Booking.com 的 6 个教训是 2019 KDD 会议接受的论文。与业内大多数专注于机器学习理论方面的论文不同,本文更注重实践,并讨论了 Bookings.com 在构建其丰富的模型集合时遇到的挑战。我发现这篇论文非常有趣,因为它提供了我作为数据科学家一直思考的 6 个问题的见解;在本文中,我将尝试总结他们对每个问题的回答:
- 机器学习可以解决哪些问题?
- 如何用机器学习提高业务 KPI?
- 如何提高模型性能?
- 当存在延迟/不完整的反馈时,如何评估模型?
- 有哪些方法可以加快预测过程?
- 如何 A/B 测试机器学习系统?
- 机器学习可以解决哪些问题?
数据科学团队的任务之一是确定组织中可以通过机器学习改进的领域,并对模型构建任务进行优先排序,以便有短期收益来证明团队的价值,并有长期计划来扩展团队的能力。Bookings.com 为他们的机器学习模型开发了一个分类法,可以作为这种规划的一个很好的参考点。他们将模型分为两大类:专用模型和通用模型:
具体型号
优势:良好的性能带来强大的业务影响
缺点:用例有限

通用型号
优势:适应范围广
缺点:对特定业务指标的影响有限

2。如何用机器学习提高业务 KPI?
机器学习模型经常优化相关指标,但不直接优化业务 KPI。例如,bookings.com 关心酒店预订率,但他们的推荐模型优化了点击率,即点击进入酒店描述页面的比率。除非模型直接优化业务 KPI,否则模型离线性能增益不会总是转化为业务价值增益。文中提到的情侣理由有:
a)模型指标与业务指标相关但不同,可能会无意中鼓励不良行为。例如,针对点击率(模型度量)进行优化的酒店推荐模型将推荐与用户已经参与的相似的酒店,这鼓励用户点击和比较更多的酒店列表。然而,这可能会将用户引入选择的悖论,并实际上伤害预订率(业务 KPI)。
b)机器学习模型对商业价值的贡献是有上限的。
c)模型太好,即模型比你自己更了解你。这让一些消费者感到不安,因此会产生负面影响,因为用户会有意尝试与模型建议相反的行为。
这个问题没有显而易见的解决方案,但该论文建议仅将离线指标用作健康检查,并更多地基于业务指标的在线测试来评估模型。本文中给出的一个例子是,当假设多样性对于推荐系统很重要,并且开发了一个具有更低均方根误差(RMSE)但更具多样性的新模型时,应该针对当前模型进行在线测试,而不考虑其更低的 RMSE,以查看它是否能提供更好的商业价值收益。
3。如何提高模型性能?
当谈到提高现有模型的性能时,收集更多的训练数据或试验不同的算法往往是首先想到的事情。不过,本文中提到了一个不同的选项——改变模型设置。
在解决一个问题时,通常有不同的方法来构建目标变量(例如,日期灵活性,愿意改变日期以获得更好的价值,或者考虑比典型用户更多的日期等。)、和 对于相同的构建目标变量可以有不同的学习设置(例如,预测酒店停留时间的回归可以变成多类分类)。改变设置是释放价值的非常有效的方式。
4。当反馈延迟/不完整时,如何评估模型?
用于评估分类模型的度量通常比较真实目标和预测。然而,有时在模型开发时无法获得目标。为了解决这个问题,该论文建议检查预测分布,并基于启发式进行判断调用。下面的截图是来自二元分类模型的 4 种可能的预测分布及其含义。(我没有在论文中找到红线是什么的解释,但是感谢威廉·凯塞多·托里斯指出它们是每种情况下的累积概率分布)

- 左上:模型的高错误率或数据的高偏差
- 右上:有问题的特征,例如错误的比例或错误的异常值
- 左下:过于稀疏的模型
- 右下:可以区分 2 类的好模型。
5。有哪些方法可以加快预测过程?
a)跨集群复制和分发模型
b)建立可简化为内积的内部线性预测引擎
c)建立具有较少参数的稀疏模型
d)当特征空间很小时,预计算所有预测并保存在键值对中;当特征空间很大时,预计算频繁请求
e)当每次预测需要许多请求时,批量请求变成一个
f)应用最小特征变换
6。如何 A/B 测试机器学习系统?
该论文描述了传统的随机 A/B 测试不够充分的三种情况,并且需要允许定制触发的更复杂的系统。

提到的第一个实验设置是仅当测试对象暴露于模型时才触发实验。我能想到的一个需要这种设置的例子是,当测试只对用户子集进行预测的算法时。在这种情况下,我们希望确保只有这样的用户包含在测试中。

第二种情况是处理标准取决于模型输出。该论文提到了一个例子,其中他们仅向被模型识别为目的地灵活的用户显示具有备选目的地的块。该实验将把随机选择的控制组用户与被预测为目的地灵活并被示出替代目的地的用户,以及被预测为目的地灵活但未被示出替代目的地的用户进行比较。实验组中被预测为目的地不灵活的用户被排除在治疗组之外。

第三个场景专门用于测试模型更新。在上面的截图中,模型 1 是原始模型,模型 2 是更新的挑战者模型。实验的设置使得只有两个模型不一致的情况被包括在处理组中进行分析。
如果你对更多细节感兴趣,可以在这里找到论文;它非常容易消化,我强烈推荐每个人都去读一读。
使用 OptimalFlow Web App 构建无代码自动化机器学习模型

凯文·Ku 在 Unsplash 上的照片
在optimal flow的最新版本(0.1.10)中,增加了一个“无代码”的 Web App,作为构建在 OptimalFlow 之上的应用演示。web 应用程序允许对 OptimalFLow 中的所有参数进行简单的点击和选择,这意味着用户可以构建端到端的自动化机器学习工作流,而无需编写任何代码!( 文档 )。
optimal flow一开始就设计了高度模块化,便于继续开发。用户可以在此基础上构建应用程序。optimal flow的 web app 是一个用户友好的工具,供没有编码经验的人简单快速地构建一个 Omni-ensemble 自动化机器学习工作流程。
为什么我们要用 OptimalFlow ?你可以阅读另一个介绍它的故事:一个全方位自动化机器学习——optimal flow。

Web App 目前包括 3 个功能组件:管道群遍历实验(PCTE)* 构建器、LogsViewer 和可视化。用户可以为每个 OptimalFlow 的关键模块设置参数,并通过点击网页运行工作流程。此外,当自动机器学习过程(PCTE)完成后,用户可以立即检查日志信息并查看可视化输出。*
与其他流行的“无代码”机器学习平台相比,该 Web 应用程序诞生于 OptimalFlow 独特的 Omni-ensemble 自动化机器学习框架,并建立在管道集群遍历实验(PCTE)* 理论之上。它也是轻量级的、可扩展的,并且对用户是开源的。它是为需要更多关注本地实现的数据科学家设计的,并且可以很容易地在机器之间移植。当数据科学团队希望将其部署在服务器上时,基于 Flask 的 Web 应用程序可以快速实现,并且具有很高的灵活性。*
如何部署 Web 应用程序:
第一步:安装 OptimalFlow :
如果您没有安装optimal flow的 最新版本,您应该从 PYPI 中完成,只需使用 PIP。要安装 OptimalFlow 的最新版本,请在终端或提示符下运行以下命令:
*pip install --upgrade optimalflow*
第二步:下载 Web App 的源代码:
有两种方法下载它的源代码:
- 方法 1 从optimal flowGitHub中获取。下载文件夹' webapp 中的所有代码和子文件夹。

方法 2 —从 OptimalFlow 的包中获取。您可以在 Python 核心文件夹中找到它。在这个例子中,您可以找到“ Webapp ”文件夹。

步骤 3:启动服务器端口:
将下载的“Webapp”文件夹移动到您想要存储它的位置。使用您的终端或提示符输入它的目录并运行 app.py(当您不在 VS 代码中运行它时,请忽略这里的“py ”)

您将看到类似下图的输出:

搞定了。你现在可以打开你的浏览器(推荐 Chrome),输入 127.0.0.1:500 打开笔记本电脑上的 web app。
构建管道集群遍历实验(PCTE)工作流:
当您完成部署步骤并开始运行服务器时,您将在浏览器中看到 web 应用程序,如下图所示:

要构建一个 PCTE 自动化机器学习工作流,需要为每个 OptimalFlow 的模块输入参数: autoPP , autoFS,和 autoCV 。
但是在此之前,你需要将你想要建立模型的数据集移动到中。/输入文件夹。您将在那里看到一个名为“breast-cancer.csv”的样本数据集。**
完成后,我们可以通过单击“加载数据集”下的按钮来选择数据集:

然后,您需要逐步完成 autoPP 、 autoFS 和 autoCV 的设置。
请注意:注意设置 autoPP 参数面板中的“稀疏度”和“列数”值,如果特征预处理的组合不能满足您设置的限制值,T5【optimal flow】T6*将无法继续运行下面的模块。更多细节可以在 autoPP 的 文档 中找到。*

接下来,您需要在 autoFS 模块中完成参数设置,即设置您想要选择多少个顶级特征,以及您想要 PCTE 通过什么算法。关于 autoFS 模块的更多细节请点击。

对于 autoCV 模块的设置,您可以点击autoCV’设置参数按钮,输入您想要 OptimalFlow 自动测试的调优策略和算法比较范围。关于 autoCV 模块的更多详情请点击。

最后,当你完成了所有的设置步骤(进度条应该 100%完成),你可以点击'建立 PCTE 工作流按钮,来运行 Omni-ensemble 自动化机器学习操作。该功能基于自动管道模块,关于自动管道的更多细节在此处。

这是流程完成后的输出示例。您将在那里找到带有评估指标的前 5 个最佳模型。关于 OptimalFlow 模块和笔记本样本的更多细节和用例可以在文档中找到。

日志查看器:
您可以在“日志查看器页面查看各个模块的相关日志信息。请注意,您只能在之前的自动机器学习过程完成后使用它。

可视化:
您还可以从“可视化”页面查看可视化输出。对于分类问题,将给出“管道群遍历实验模型检索图”和“管道群模型评价动态表”。对于回归问题,只呈现'管道集输模型评价动态表。所有的可视化输出都是基于 Plotly 的,所以你可以通过拖动或滚动来玩它们。你会在示例页面找到更多细节。

更新:
搜索空间
在 OptimalFlow 的下一个版本 0.1.11 中,你可以通过 Web 应用程序编辑评估者的搜索空间。
**
总而言之:
OptimalFlow 是一个简单易用的 API 工具,用简单的代码实现 Omni-ensemble 自动化机器学习,也是证明管道簇遍历实验 (PCTE)理论的最佳实践库。
最新版本的 Web 应用程序是建立在 OptimalFlow 库上的少数应用程序,它使自动机器学习工作流构建过程变得简单,并且完全没有代码。
它的 6 个模块既可以连接起来实现 PCTE 过程,也可以单独使用来优化传统机器学习工作流的组件。你可以在 文档 中找到它们各自的用例。

关于 OptimalFlow 的相关阅读:
使用 OptimalFlow 在机器学习中进行集成特征选择——使用简单代码选择顶级特征的简单方法
集成模型选择&使用 OptimalFlow 的机器学习评估—使用简单代码选择最佳模型的简单方法
关于我:
我是一名医疗保健和制药数据科学家以及大数据分析和人工智能爱好者。我开发了 OptimalFlow 库,帮助数据科学家以一种简单的方式构建最优模型,并用简单的代码实现机器学习工作流的自动化。
作为一名拥有多年分析经验的大数据洞察寻求者、流程优化者和人工智能专家,我使用数据科学中的机器学习和问题解决技能将数据转化为可操作的洞察,同时提供战略和量化产品作为最佳结果的解决方案。
你可以在 LinkedIn 或者 GitHub 上和我联系。
使用知识蒸馏构建强大的轻量级模型
通过师生培训计划获得高性能的微型模型

照片由 Tra Nguyen 在 Unsplash 上拍摄
过去几年,机器学习领域的趋势是获得最大的模型,在大量数据上训练它们,然后集成它们,以获得最后几个百分点的准确性。这种方法的一个缺点是,在现实生活的应用程序中部署大型模型或集成可能会很困难。对于任何实际应用来说,它们的权重可能太大,或者它们的推理时间可能太长,尤其是当您试图在嵌入式设备或 web 应用程序的客户端使用它们时。
还有一项积极的研究,即如何通过为移动设备(如 MobileNets 或权重量化)构建定制架构,在小巧快速的同时实现不错的性能。
在这篇文章中,我们将展示如何通过使用知识蒸馏(来自提取神经网络中的知识)和混合(来自混合:超越经验风险最小化)来提高微型神经网络的性能。知识蒸馏背后的基本思想是,你定义一个老师(可以是单个模型或整体)和一个学生(这是你想在生产中使用的轻量级模型),然后你在目标任务上训练老师,并让学生尝试模仿老师。

数据:
我们将使用在 Kaggle 数据集https://www.kaggle.com/mondejar/mitbih-database上处于预处理状态的麻省理工学院-BIH 数据集。该数据集包含与心律失常异常相关的五类个体心跳。

教师模型:
教师模型是 1D CNN,其具有卷积层,每个卷积层具有 64 个滤波器和两个完全连接的层。总共有17221 个可训练参数。

教师模型
学生模型:
学生模型的结构与教师模型相同,但卷积层更小。总共有3909 个可训练参数,因此比教师模型小 4 倍。

目标函数:
我们使用应用于独热标签的分类交叉熵来训练教师模型。当应用知识提炼时,使用 Kullback Leibler 散度和由教师模型作为目标预测的软标签上的 MAE 损失之间的混合来训练学生模型。
Kullback Leibler 散度测量两个概率分布之间的差异,因此这里的目标是使学生预测的分布{在班级上}尽可能接近教师。
结果:
在没有使用任何知识提炼的情况下,微型模型获得了 F1 分数 0.67 +- 0.02 ,在使用知识提炼后,微型模型的性能被提升到 0.78 +- 0.02 。当使用知识提炼时,我们能够使用相同的架构获得 F1 分数方面的 11 个绩效点。
结果概述:
- F1 教师模型: 0.82 +- 0.006
- F1 微型模式+知识提炼: 0.78 +- 0.02
- F1 微型模式从零开始: 0.67 +- 0.02
结论:
在这篇文章中,我们能够实现一个简单的知识蒸馏训练方案,该方案能够使用完全相同的架构将一个非常小的模型的性能从 0.67 F1 提升到 0.78 F1。例如,当拥有尽可能小且性能良好的模型对于部署非常重要时,这可能非常有用。当使用这种方法时,有很多需要探索的地方,比如使用合奏作为老师,或者老师和学生之间的大小差异如何影响知识提炼的质量。这将在以后的文章中完成😃。
参考资料:
代码:
https://github.com/CVxTz/knowledge_distillation
使用 Google Colab、Google Data Studio 和 Google Sheets 构建预测性商业智能
基于免费 Google 服务的预测性 BI 解决方案的实验结果

图片作者:Rostyslav Neskorozhenyi
我们许多人习惯于认为商业智能是大公司使用的东西,是用昂贵且通常难以学习的工具创建的(尽管也有令人愉快的例外,如元数据库和超集)。在我的文章中,我想展示几乎每个人都可以使用商业智能的力量,甚至可以通过普遍可用和免费的在线工具为其添加一些预测分析,如谷歌 Colab 和谷歌数据工作室。不需要部署数据库。所有用于分析和可视化的数据,我们将存储在谷歌表。
我们将在 Google Colab 中实现一个机器学习模型,根据产品的销售历史,我们将能够预测未来几个月的销售情况,并在 Google Data Studio 中可视化我们的预测。
我们将使用包含产品列表信息和每种产品 12 个月的销售历史的数据集。
该模型将分析每个月的销售历史和产品功能的变化,因此任何变化都会动态地影响模型预测。这将使我们能够迅速评估某些决定的后果,并采取最佳发展战略。
加载数据
我们认为,我们在 Google Colab 中的所有操作。首先,我们将使用 kaggle 模块下载所需的数据集。你可以通过这个链接阅读更多关于模块和如何获得 Kaggle API 令牌的细节。
!pip install kaggle
由于我们正在使用 Google Colab,我们将连接到 Google Drive 来复制 Kaggle 凭据。
from google.colab import drive
drive.mount(‘/content/drive/’)
用保存的凭证设置一个工作目录(在我们的例子中,该目录称为“Colab 笔记本”)。
import os
os.chdir(“/content/drive/My Drive/Colab Notebooks”)
复制 Kaggle API 的凭据。
import os
os.chdir(“/content/drive/My Drive/Colab Notebooks”)
下载数据集。
!kaggle competitions download -c online-sales
将数据集加载到内存中,并用零替换空值。
import pandas as pd
import numpy as np
from matplotlib import pyplot as pltdf = pd.read_csv(“TrainingDataset.csv”)
df = df.replace(np.nan, 0, regex=True)
现在我们可以预览数据集了。

图片作者:Rostyslav Neskorozhenyi
我们将把数据集分成训练部分(我们将在其上训练我们的模型)和测试部分(我们将在其上测试我们的模型的正确性)。
from sklearn.model_selection import train_test_splitdf_train, df_test = train_test_split(df, test_size=0.2)
print(df_train.shape)
print(df_test.shape)
探索性数据分析
让我们将数据可视化。我们将展示 10 个随机产品的价格变化动态。
import randomindexes = random.sample(range(len(df)), 10)
df_plot = pd.DataFrame()for i in indexes:
df_plot[“product_”+str(i)] = df.iloc[i, 0:12]df_plot.plot();

图片作者:Rostyslav Neskorozhenyi
正如我们所看到的,在大多数情况下,全年的销售额都在下降。
准备数据
我们需要以一种特殊的方式准备数据,以便加载到我们的模型中。我们将建立一个模型,根据以前的值预测未来一个月的结果。对于每个月,模型将分析产品功能和有关上个月结果的信息。
首先,我们将分开产品功能和每月结果的信息。
y_train_real = df_train.iloc[:, 0:12].values
print(y_train_real.shape)y_test_real = df_test.iloc[:, 0:12].values
print(y_test_real.shape)x_train_real = df_train.iloc[:, 12:].values
x_test_real = df_test.iloc[:, 12:].values
print(x_train_real.shape)
print(x_test_real.shape)
在一个范围内缩放值以获得更好的预测。
from sklearn.preprocessing import MinMaxScaler#scale datasets
x_scaler = MinMaxScaler()
x_scaler = x_scaler.fit(x_train_real)
x_train = x_scaler.transform(x_train_real)
x_test = x_scaler.transform(x_test_real)y_scaler = MinMaxScaler()
y_scaler = y_scaler.fit(y_train_real)
y_train = y_scaler.transform(y_train_real)
y_test = y_scaler.transform(y_test_real)
现在让我们转到这个过程中最重要的一步:将价格历史转换成多维时间序列。对于每个产品,我们将创建 1-12 个时间步的时间序列,其中包含有关产品功能和以前时间步结果的信息。我们不知道第一个时间步长的先前结果,所以我们只取零。
在这里,我们为训练和测试数据创建列表,每个列表将包含 12 个三维 numpy 数组。每个数组的第二维将代表时间步长,并逐渐增加 1。
x_train_series = []
x_test_series = []for k in range(len(y_train[0])):
x_train_series.append(np.zeros((x_train.shape[0], k+1, x_train.shape[1]+1)))for k in range(len(y_test[0])):
x_test_series.append(np.zeros((x_test.shape[0], k+1, x_test.shape[1]+1)))
向每个时间步长添加有关产品功能和先前时间步长结果的信息。现在,我们对每个时间步长使用相同的产品功能,但是该模型允许跟踪每个时间步长上的功能变化,以做出更准确的预测。
for k in range(len(y_train[0])):
for i in range(len(x_train)):
for j in range(k + 1):
shifted_index = j - 1
if shifted_index < 0:
x_train_series[k][i, j] = np.append(x_train[i], 0)
else:
x_train_series[k][i, j] = np.append(x_train[i], y_train[i, shifted_index])
测试数据的相同时间步长转换。
for k in range(len(y_test[0])):
for i in range(len(x_test)):
for j in range(k + 1):
shifted_index = j - 1
if shifted_index < 0:
x_test_series[k][i, j] = np.append(x_test[i], 0)
else:
x_test_series[k][i, j] = np.append(x_test[i], y_test[i, shifted_index])
制作 12 个列表,列出每个时间、每个产品的结果信息。
y_train_series = []
y_test_series = []for k in range(len(y_train[0])):
y_train_series.append(np.zeros((len(y_train), 1)))
y_test_series.append(np.zeros((len(y_test), 1)))
for k in range(len(y_train[0])):
y_train_series[k] = y_train[:, k].reshape(-1, 1)
y_test_series[k] = y_test[:, k].reshape(-1, 1)
构建 LSTM 神经网络
我们将使用长短期记忆(LSTM)网络的递归神经网络(RNN)。你可以在这里阅读更多关于这些类型的神经网络:
http://colah.github.io/posts/2015-08-Understanding-LSTMs/
我们使用 Keras 框架进行深度学习。我们的模型仅由一个具有 256 个单元的 LSTM 层、一个具有 128 个单元的密集层和具有一个神经元的密集连接输出层组成。我们还添加了一个脱层,以避免过度拟合。模型保持简单和快速,仍然能够做出有用的预测。
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from keras.layers import Dropoutmodel = Sequential()
model.add(LSTM(256, input_shape=(None, x_train.shape[1]+1)))
model.add(Dropout(0.5))
model.add(Dense(128, activation = "relu"))
model.add(Dense(1))
model.summary()

model.compile(loss='mse', optimizer='rmsprop')
训练我们的模型:
for i in range(len(x_train_series)):
print(i)
model.fit(x_train_series[i], y_train_series[i], epochs=10, validation_split=0.2)
评估模型,预测几个月后的结果。
for i in range(len(x_test_series)):
accr = model.evaluate(x_test_series[i], y_test_series[i])
print("Predicting outcome after {} months. MSE:".format(i), accr)

结果预测函数
我们将使用我们的模型创建一个递归函数,该函数将在几个月内获取有关产品特性和结果历史的信息。因此,这个函数可以预测未来几个月的结果。
def predictor(features, history, future):
'''
features: list of product features
history: list with outcome per month
future: int, number of months to predict outcome
'''
if future == 0:
return history
p_serie = np.zeros((1, len(history), len(features)+1))
for j in range(len(history)):
shifted_index = j - 1
if shifted_index < 0:
p_serie[0, j] = np.append(features, 0)
else:
p_serie[0, j] = np.append(features, history[shifted_index])
prediction = model.predict(p_serie)
history.append(prediction[0][0])
future -= 1
return predictor(features, history, future)
我们将在随机产品 n 上测试我们的功能。我们将创建两个列表。首先是前 m 个月的成果历史,其次是产品特性
import randomn = random.choice(range(len(x_test)-1))
m = 6
future = 6features = x_test[n].tolist()
history = y_test[n, 0:m].tolist()
绘制预测结果与实际数据的对比图
prediction = predictor(features, history, future)plt.plot(y_scaler.inverse_transform([prediction])[0])
plt.plot(y_scaler.inverse_transform([y_test[n, :m+future]])[0])
plt.title('Predicted and real outcome')
plt.legend(['predicted', 'real'], loc='upper left')
axes = plt.gca()plt.show()

图片作者:Rostyslav Neskorozhenyi
正如我们所看到的,它相当准确地显示了销售变化的总体趋势。对于一个相对简单的模型来说,这是一个不错的结果。
在 Google Data Studio 中显示预测
现在,当我们有了我们的预测数据,我们可以在谷歌的商业智能解决方案谷歌数据工作室中显示它。这个工具的一个优点是可以免费用来制作自定义报表和仪表盘。
Google Data Studio 可以连接多个数据源进行报告。Google Sheets 作为数据源很适合我们的目的。我们将把我们的预测保存为 Google Sheet,Google Data Studio 将在 dashbord 上显示其中的数据。因此,我们可以很容易地整合谷歌实验室和数据工作室。
我不会详细解释谷歌数据工作室的功能。你可以在 https://developers.google.com/datastudio/的官方文件中了解到
我们将随机抽取三个产品,保存每个产品的预测和结果历史。为了将我们的数据保存到谷歌电子表格中,我们将使用 gspread 库。
我们将需要一个客户端密钥写在谷歌电子表格。这里介绍如何得到钥匙https://gspread.readthedocs.io/en/latest/oauth2.html。
!pip install — upgrade oauth2client gspread
连接到 Google Sheets。
import gspread
from oauth2client.service_account import ServiceAccountCredentialsscope = ['[https://spreadsheets.google.com/feeds'](https://spreadsheets.google.com/feeds'),
'[https://www.googleapis.com/auth/drive'](https://www.googleapis.com/auth/drive')]credentials = ServiceAccountCredentials.from_json_keyfile_name('spreadkey.json', scope)gc = gspread.authorize(credentials)
列出三种随机产品的真实和预测结果历史。出于测试目的,我们使用来自测试数据集的数据,但在实际情况下,您可以在 Google Sheets 中插入产品功能的任何变化,从 Google Sheets 加载数据并做出预测。
real_data = []
predicted_data = []for i in range(3):
n = random.choice(range(len(x_test)-1))
m = 6
future = 6
features = x_test[n].tolist()
history = y_test[n, 0:m].tolist() prediction = predictor(features, history, future) predicted_data.append(y_scaler.inverse_transform([prediction])[0])
real_data.append(y_scaler.inverse_transform([y_test[n, :m+future]])[0])
打开谷歌工作表保存真实和预测的数据。我们有两个工作表:“真实”代表真实数据,“预测”代表预测数据。
ws = gc.open('TrainingDataset2')ws_predicted = ws.worksheet("predicted")
ws_real = ws.worksheet("real")
把我们真实的和预测的数据写到 Google Sheets。我们将从第二行开始写,保留第一行作为列名(Product1、Product2、Product3)。
for j in range(len(real_data)):
for i in range(len(real_data[0])):
ws_predicted.update_cell(i+2, j+1, float(predicted_data[j][i]))
ws_real.update_cell(i+2, j+1, float(real_data[j][i]))
for i in range(len(real_data[0])):
# add index column
ws_predicted.update_cell(i+2, len(real_data)+1, i)
ws_real.update_cell(i+2, len(real_data)+1, i)
在 Google Sheets 查看我们的数据
ws_real.get_all_records()[6:11]

由于我们已经有了充满真实和预测结果的 Google Sheets,现在我们可以将 Google Sheets 作为 Google Data Studio 中的数据源进行连接。
在 Google Data Studio 中,创建新的仪表板并为其创建数据源。你会在资源列表中找到谷歌工作表。将您的 Google 工作表添加为数据源。
基于“预测的”和“真实的”工作表中的数据,我们可以做出显示结果变化的图表。
就是这样!现在你有人工智能驱动的仪表板,显示对未来结果的预测!

图片作者:Rostyslav Neskorozhenyi
结论
这篇文章的主要思想是,甚至带有一些人工智能特征的商业智能比我们想象的更容易获得。您可以创建高级分析,将建议的图表嵌入到您的分析报告中,并对当前情况和不久的将来有所了解。所有的变化,你想检查可以迅速插入谷歌表,预测的后果将在谷歌 Colab 计算,并显示在谷歌数据工作室。
你可以通过这个链接找到所有描述代码的 Google Colab 笔记本。
Power BI 中的 Build PRO 切片器窗格
借助定制的交互式切片器窗格,为您的 Power BI report 用户带来全新体验

玛丽安娜·普罗恩卡在 Unsplash 上拍摄的照片
我最喜欢 Power BI 的一点是——书签。对于不熟悉的人来说,书签是 Power BI 中最喜欢和使用最多的功能之一。
基本上,书签做什么,它捕捉报告的当前状态,所以你可以通过按钮、图像、形状等在你的行动中使用它作为参考。简单地说,这将使您有可能为您的报告创建一个类似应用程序的体验,并使其看起来具有交互性。
当空间成为问题时…
实际上有许多可以应用书签的用例,但是我在这里将把重点放在一个特定的问题上:我要说这是一个常见的问题,并且我向您保证,在报表设计过程中,您迟早会遇到这个问题。
因此,我们创建了漂亮的小功率 BI 报告,一切看起来都很好,我们在页面上有 3-4 个切片器,到目前为止,一切都很好。但是,有一天,我们的用户希望有一个额外的切片器,比如说,品牌类别。没问题,我会把现有的切片机做得更小,并为新的确保一个空间。然后,一两个月后,我们的用户想要多一个切片机,而不是再过一两个月,多一个,等等。我想你明白了…
那么,当我们无法在报告页面上容纳所有请求的切片器时,我们该怎么办呢?第一种选择是告诉我们的用户选择对他们来说最重要的,然后丢弃其他的……开个玩笑,当然你不应该这么做:)。
我们可以创建一个单独的报告页面,仅包含切片器。或者…我们可以创建一个切片器窗格,它将包含现有报告页面上的所有切片器…我们将能够根据用户的选择显示或隐藏该切片器窗格。
作为一个奖励,我们将为我们的用户提供一个选项,一键重置所有的切片器!
从头开始构建
下面是我的报告画布开始时的样子:

我要做的第一件事是打开视图选项卡下的书签窗格和选择窗格,这样我就可以完全控制报表中不同对象的操作。

如你所见,我们到目前为止还没有创建任何书签,但很快我们就会创建。
您可以注意到报告画布上唯一“奇怪”的项目是左上角的过滤器图标。该图标将用于打开我们将要构建的切片器窗格。
下一步是为报告创建所有必要的切片器。我已经创建了 8 个不同的切片机,根据用户的要求。如果您需要在报告中显示所有选中的切片器,请参考这篇文章。

最后,我将添加一个漂亮的矩形形状,它将作为我所有切片器的窗格,以及关闭切片器窗格的图标。

现在我们在报告页面上有了所有的元素,所以下一步是定义书签中特定项目的可见性,并定义在书签中导航的动作。
因为我们已经在画布上拥有了所有的元素,所以让我们首先创建一个书签,它将捕获页面的当前状态:

我点击添加,并命名为我的书签切片窗格展开。最重要的是取消数据选项(点击三个点打开此菜单),这样我们可以确保当用户在书签之间切换时切片器不会重置。
现在,让我们设置过滤器图标的 Action 属性,这样我们就可以指定我们希望它做什么:

通过这样做,我们指示图标导航到由切片器窗格扩展书签捕获的报告状态。
现在,让我们设置切片器窗格折叠时的状态。首先,我将隐藏选择中与切片器窗格相关的所有项目:

我现在可以创建一个名为“切片器窗格折叠”的新书签,使用与上一步相同的规则:

关于选择面板,我有一个重要的意见:通过上下拖动元素,您定义了报表页面上可见性的顺序!这意味着,如果用作切片器窗格的矩形形状在选择窗格中的切片器上方,并且该矩形不透明,它将覆盖我们的切片器,它们将不可见。因此,请确保在这里定义了正确的元素顺序。
一旦我按住 CTRL 键单击我们的过滤器图标,看看会发生什么:

我们的切片器面板在那里!我可以在我的切片器中选择我想要的任何值,它们将被传播到“后面”的视觉效果中。这里要配置的最后一件事是为关闭切片器窗格的图标定义一个动作:

现在,让我们看看它在现实中是如何工作的:

太棒了,不是吗?
额外提示—只需一次点击即可重置所有过滤器!
现在,让我们的用户更加开心的最后一点…当有人在 8 个不同的切片器中选择 8 个不同的值来返回默认选择时,这将是非常麻烦的。人们必须一个接一个地点击切片器并清除选择。
所以,让我们来帮助我们的用户吧!首先,我将在新创建的切片器窗格中放置一个空白按钮。我已经格式化了按钮,使其看起来更好,并且“告诉”我们的用户它是关于什么的——我认为“全部重置”在这里是不言自明的。
现在,让我们创建另一个书签,我们称之为切片器窗格重置。应用与前面相同的步骤,但不要取消选中数据选项!这将捕获页面的当前状态(包括切片器中的所有选择),因此一旦我们通过书签导航到该状态,它还将“传输”捕获的数据状态(在我们的示例中,它是所有切片器都重置为默认状态的状态):

让我们再一次检查一切是否如预期的那样工作:

绝对完美!
结论
正如您所看到的,我们在报告中使用书签,将过滤体验提升到了一个全新的水平。你的用户会喜欢你的——你提供了他们想要的所有切片器,但你也节省了报告的空间,以容纳更多的视觉效果,或给现有的一些空间。
成为会员,阅读 Medium 上的每一个故事!
订阅此处获取更多有见地的数据文章。
用 PyCaret 构建:部署在 Google 云平台上
实用教程
将机器学习模型部署到谷歌云平台

由作者创建
在这个故事中,我开发了一个关于在谷歌云平台上部署一个用pycaret训练的模型的工作教程。本教程可以用来部署任何机器学习模型,稍加修改。
我们将学习如何将使用pycaret训练的模型部署到 Google 云平台。正如你可能知道的,pycaret已经支持在 AWS 上部署训练好的模型,但目前还不支持 GCP 或 Azure。我遵循了库中用于在 AWS 上部署模型的类似代码实践,并为 GCP 部署添加了必要的实用程序。
PyCaret 是 Python 中的一个开源、低代码机器学习库,它允许您在选择的笔记本环境中在几秒钟内从准备数据到部署模型。
PyCaret 是公民数据科学家的 autoML 框架,在其官方文档中使用。PyCaret 相对来说是一个新的库,几个月前发布供公众使用,目前仍在积极开发中。在浏览了一些源代码后,我意识到当前的公开版本缺乏对将经过训练/最终确定的模型部署到 Google 云平台的支持。但是,它只支持在 Amazon web services 上部署。
考虑到 GCP 作为云服务的广泛使用,我尝试添加了一个教程,使用 PyCaret 的方式在 google cloud 上部署训练好的模型。
对于本教程,我们将使用回归教程(REG101) —初级初学者进行模型训练。
正在安装 PyCaret
!pip install pycaret
安装 Gdrive
我们需要安装 google drive 来在 colab 环境中读/写数据。下面是最简单的安装方法。您将被要求输入访问过程生成的令牌。这里是关于安装 gdrive 的文章的链接
在本教程中,我们将在 Google drive 上本地保存模型。
from google.colab import drive
drive.mount('/content/drive')Drive already mounted at /content/drive; to attempt to forcibly remount, call drive.mount("/content/drive", force_remount=True).
让我们创建一个目录来本地保存模型。
# Create directory on google drive to save models locally. You can use temp paths.
import os
model_dir = '/content/drive/My Drive/gcp_deploy_model/'
os.makedirs(model_dir, exist_ok=True)
获取数据
您可以从这里找到的原始源下载数据,并使用 pandas (了解如何使用) 加载数据,或者您可以使用 PyCaret 的数据存储库使用get_data()函数加载数据(这将需要互联网连接)。
from pycaret.datasets import get_data
dataset = get_data('diamond')

#check the shape of data
dataset.shape(6000, 8)data = dataset.sample(frac=0.9, random_state=786).reset_index(drop=True)
data_unseen = dataset.drop(data.index).reset_index(drop=True)
print('Data for Modeling: ' + str(data.shape))
print('Unseen Data For Predictions: ' + str(data_unseen.shape))Data for Modeling: (5400, 8)
Unseen Data For Predictions: (600, 8)
在 PyCaret 中设置环境
让我们使用 PyCaret 的设置模块准备一个建模管道。
from pycaret.regression import *exp_reg101 = setup(data = data, target = 'Price', session_id=123)Setup Succesfully Completed!

创建一个轻型 GBM 模型
对于本教程,我们使用 PyCaret 中实现的许多选项中的轻量级 GBM 对数据进行建模。您可以选择任何您喜欢的模型,但这不是本教程的重点。
lightgbm = create_model('lightgbm')

调谐光梯度增强机
让我们来训练这个模型,用 PyCaret 的术语来说也叫做调整模型。
tuned_lightgbm = tune_model('lightgbm')

残差图
下图显示了模型的残差
plot_model(tuned_lightgbm)

让我们画出预测误差与目标值的关系图。
plot_model(tuned_lightgbm, plot = 'error')

特征重要性图
特征重要性是一个非常有用的图,可以看到模型中每个特征的贡献。
plot_model(tuned_lightgbm, plot='feature')

分析模型性能的另一种方法是使用evaluate_model()函数,该函数显示给定模型的所有可用图的用户界面。它在内部使用plot_model()功能。
evaluate_model(tuned_lightgbm)interactive(children=(ToggleButtons(description='Plot Type:', icons=('',), options=(('Hyperparameters', 'param…
根据测试/保留样本进行预测
predict_model(tuned_lightgbm);

最终确定用于部署的模型
final_lightgbm = finalize_model(tuned_lightgbm)#Final Light Gradient Boosting Machine parameters for deployment
print(final_lightgbm)LGBMRegressor(boosting_type='gbdt', class_weight=None, colsample_bytree=1.0,
importance_type='split', learning_rate=0.4, max_depth=10,
min_child_samples=20, min_child_weight=0.001, min_split_gain=0.9,
n_estimators=90, n_jobs=-1, num_leaves=10, objective=None,
random_state=123, reg_alpha=0.9, reg_lambda=0.2, silent=True,
subsample=1.0, subsample_for_bin=200000, subsample_freq=0)predict_model(final_lightgbm)
****
根据看不见的数据预测
unseen_predictions = predict_model(final_lightgbm, data=data_unseen)
unseen_predictions.head()

Label列被添加到data_unseen集合中。标签是使用final_lightgbm模型的预测值。如果您想对预测进行四舍五入,您可以在predict_model()中使用round参数。
在本地保存模型
让我们首先在本地保存模型
model_dir
model_name = 'Final_lightgbm_model''/content/drive/My Drive/gcp_deploy_model/'# Saving model to google drive
save_model(final_lightgbm, model_dir + model_name)Transformation Pipeline and Model Succesfully Saved
加载保存的模型
为了在将来的某一天在相同或不同的环境中加载已保存的模型,我们将使用 PyCaret 的load_model()函数,然后轻松地将已保存的模型应用于新的未知数据进行预测。
saved_final_lightgbm = load_model(model_dir + model_name)Transformation Pipeline and Model Sucessfully Loaded
一旦模型被加载到环境中,您可以使用相同的predict_model()函数简单地使用它来预测任何新数据。下面我们应用了加载模型来预测我们在上一节中使用的相同的data_unseen。
new_prediction = predict_model(saved_final_lightgbm, data=data_unseen)new_prediction.head()

注意unseen_predictions和new_prediction的结果是相同的。
在谷歌云平台上部署训练好的模型
一旦我们有了训练好的模型,下一个任务就是部署它来为客户服务。有各种部署选项可用,但在这一节中,我将重点放在部署在谷歌云人工智能平台上。我尝试使用类似于pycaret库中的方法在 AWS 上部署。
先决条件
在 google cloud 上部署机器学习模型的先决条件是
- 熟悉谷歌云项目
- 对存储桶和 it gsutil 命令行工具有基本的了解
- 基本了解 gcloud 命令行工具与 Google Cloud 的交互
- 使用 PyCaret 的最终训练模型
from google.colab import auth
auth.authenticate_user()
定义 google cloud project,target bucket,设置 cloud_project 环境变量。创建一个谷歌云项目,如果之前没有创建的话。请遵循上述指南获取更多信息。
# GCP project name, Change the name based on your own GCP project.
CLOUD_PROJECT = 'gcpessentials-rz' # GCP project name
bucket_name = 'pycaret-reg101-rz' # bucket name for storage of your model
BUCKET = 'gs://' + CLOUD_PROJECT + '-{}'.format(bucket_name)
# Set the gcloud consol to $CLOUD_PROJECT Environment Variable for your Desired Project)
!gcloud config set project $CLOUD_PROJECTUpdated property [core/project].
我们定义了一些实用函数来创建 google 云存储桶,将 blob 上传到存储桶,并从存储桶下载 blob。
代码取自谷歌官方文档,并根据我们的要求稍作修改。
from google.cloud import storage
def create_bucket(project_name, bucket_name):
"""Creates a new bucket."""
# bucket_name = "your-new-bucket-name"
storage_client = storage.Client(project_name)
buckets = storage_client.list_buckets()
if bucket_name not in buckets:
bucket = storage_client.create_bucket(bucket_name)
print("Bucket {} created".format(bucket.name))
else:
raise FileExistsError('{} already exists'.format(bucket_name))
def upload_blob(project_name, bucket_name, source_file_name, destination_blob_name):
"""Uploads a file to the bucket."""
# bucket_name = "your-bucket-name"
# source_file_name = "local/path/to/file"
# destination_blob_name = "storage-object-name"
storage_client = storage.Client(project_name)
bucket = storage_client.bucket(bucket_name)
blob = bucket.blob(destination_blob_name)
blob.upload_from_filename(source_file_name)
print(
"File {} uploaded to {}.".format(
source_file_name, destination_blob_name
)
)
def download_blob(project_name, bucket_name, source_blob_name, destination_file_name):
"""Downloads a blob from the bucket."""
# bucket_name = "your-bucket-name"
# source_blob_name = "storage-object-name"
# destination_file_name = "local/path/to/file"
storage_client = storage.Client(project_name)
bucket = storage_client.bucket(bucket_name)
blob = bucket.blob(source_blob_name)
if destination_file_name is not None:
blob.download_to_filename(destination_file_name)
print(
"Blob {} downloaded to {}.".format(
source_blob_name, destination_file_name
)
)
return blob
将模型保存到 GCP 存储桶
使用上面的实用程序,使用下面的代码将模型上传到 GCP 存储桶。
# Create Bucket
create_bucket(CLOUD_PROJECT, bucket_name)Bucket pycaret-reg101-rz created
将模型上传到 google 云存储桶
# Save Model Local/google drive and upload to GCP
model_name_gcp = 'lightgbm-reg101-gcp'
save_model(final_lightgbm, model_name= model_dir + model_name_gcp, verbose=False)
model_src = model_dir + model_name_gcp +'.pkl'
model_dst = str(model_name)+'.pkl'upload_blob(CLOUD_PROJECT, bucket_name, model_src, model_dst)File /content/drive/My Drive/gcp_deploy_model/lightgbm-reg101-gcp.pkl uploaded to Final_lightgbm_model.pkl.
从 GCP 下载预测模型
一旦你的模型上传到 GCP,你可以随时下载来进行预测。我遵循一个简单的流程,首先在本地或 google drive 中下载模型,然后使用load_model函数,可以生成预测。
outfile_name = model_dir + 'lightgbm-reg101-gcp-downloaded'
model_gcp_src = str(model_name)+'.pkl'
model_downloaded = download_blob(CLOUD_PROJECT, bucket_name, model_gcp_src, outfile_name + '.pkl')Blob Final_lightgbm_model.pkl downloaded to /content/drive/My Drive/gcp_deploy_model/lightgbm-reg101-gcp-downloaded.pkl.os.listdir(model_dir)['Final_lightgbm_model.pkl',
'lightgbm-reg101-gcp.pkl',
'lightgbm-reg101-gcp-downloaded.pkl']
使用最近从 GCP 下载的模型进行预测。
# Loading the model for predictions
gcp_final_lightgbm = load_model(outfile_name)Transformation Pipeline and Model Sucessfully Loaded# Predictions from deployed model
new_prediction_gcp = predict_model(gcp_final_lightgbm, data=data_unseen)new_prediction_gcp.head()

谷歌 Colab 笔记本
按照下面的谷歌合作笔记本来复制和实践这个指南。
结论
在本教程中,我们学习了如何在使用pycaret库训练时将模型部署到 GCP。
主要目标是使用[pycaret](https://github.com/pycaret/pycaret)的内置实用程序从 GCP 部署和加载模型。以下是一些亮点
- 安装 google drive 以保存模型
- 用
pycaret训练回归模型 - 保存并加载经过训练/最终确定的模型 google drive
- 将经过培训/最终确定的模型部署到 GCP 存储桶
- 使用 GCP 部署的模型来执行预测
使用 Streamlit 构建快速美观的应用程序
在几个小时内轻松构建一个交互式应用

卢克·切瑟在 Unsplash 上的照片
每一个数据都讲述了一个故事。通过视觉表现比查看成千上万的记录更容易理解它们。数据科学家经常利用条形图、折线图、面积曲线等图表向他们的利益相关者传达这个故事。在处理数据时,Python 和 R 一直是首选语言。有多个库,如 Matplotlib、Seaborn、pyVis 等,通过它们可以在 Jupyter 笔记本或独立应用程序中使用 Bokeh、Flask 等创建可视化效果。
在本文中,我将尝试向您介绍 Streamlit 并熟悉它。在本文结束时,您将能够根据您的数据创建一个交互式应用程序。让我们从 Kaggle 获取一个公开的数据集。最终,我们将能够创建一个这样的应用程序。

演示应用程序(作者提供的 Gif)
上面的 gif 其实是演示 app 的一段屏幕记录。Streamlit 为您提供了一个简单的选项来录制音频应用程序,以防您需要演示。如果你计划向观众展示它,这是非常有用的。

(图片由作者提供)
设置简化 it
在我们开始构建应用程序之前,让我们设置一下 streamlit。我在用 Ubuntu 机器。对于所有操作系统来说,命令几乎都是一样的。
python3 -m pip 安装细流
如果您遇到这样的错误,这是一个很常见的错误:
AttributeError:模块' google.protobuf.descriptor '没有属性' _internal_create_key'
修复方法是升级 protobuf
python3 -m pip 安装—升级 protobuf
让我们构建我们的应用程序
设计
在我们开始编码之前,应该花一些时间来创建一个粗略的布局。我的做法是把它画在一张纸上——图表应该放在哪里,下拉框应该放在哪里?图表会连接到按钮吗?…等等
如果你没有纸和笔,draw.io 是绘制设计/流程图/UML 图等的替代方法。这是我在一张纸上画的。

应用布局(图片由作者提供)
密码
既然我们已经记住了设计,让我们开始添加标题,然后添加一些分析描述。如果增加应用程序的吸引力,您可能希望添加一个图像。
代码非常简单直观。要加载图像,只需读取图像并调用 streamlit.image 方法。你也可以写出与 Github 非常相似的降价。要添加描述,我们只需调用带有 python 对象作为参数的 write 方法。它可以是字符串或熊猫数据框。
在上面的代码中,我们正在读取数据集并显示值的一瞥。就代码而言,它非常简单。你可以称之为取样熊猫数据框。这是 streamlit 的魔法部分,也称为魔法命令。当您编写变量名时,streamlit 会隐式地将它写出到您的应用程序中,就像您使用 write 方法一样。我们将利用这个应用程序中的一些神奇的命令来创建图表和交互式选项。
启动应用程序— streamlit 运行 app.py 。你会得到一个这样的应用程序:

数据概述(图片由作者提供)
看过数据后,我们想创建一些双变量可视化。这些也应该是交互的,以便人们可以选择不同的值并分析趋势。例如,我想显示各种平台的跨年度销售额。为了使它具有交互性,我们添加一个下拉菜单,最终用户可以在其中选择值。
在上面的代码中,我们创建了一个下拉列表和两个图表(折线图和堆积条形图)。要在 streamlit 中创建下拉菜单,非常简单——只需调用 Magic 命令 st.selectbox
platform_name = st.selectbox('选择一个平台',options= df)。Platform.unique()
现在,我们如何确保在下拉选项中选择的值反映在图形上呢?嗯,那也很容易。您做出的任何选择都会被分配到 platform_name 变量中。在这个例子中,我们使用 altair 库来创建图表。参考第 6 行。要在应用程序中嵌入图表,只需调用
圣牛郎星图表(基本图表)
圣牛郎星图表(堆叠条形图)
还有魔法!以下是您在应用程序中获得的内容

(图片由作者提供)
我在 API 中发现了一个有趣的功能。如果你想在应用程序中分享代码片段,它只是 streamlit 中的一行代码。在你调用 st.echo 之后写你的代码
上面的代码用于为上面的堆积条形图创建数据框。

这是代码在应用程序中的呈现方式(图片由作者提供)
侧砂坝
如果你希望你的应用程序有多个部分,你肯定可以这样做。

(图片由作者提供)
analysis = st.sidebar.selectbox('选择一个选项',['图像分类','数据分析&可视化')
if analysis== '数据分析&可视化':
代码渲染 app 第 1 部分
else:
渲染 app 第 2 部分
建立了一个令人敬畏的基于深度学习的图像分类模型,想要快速建立一个演示吗?
基于计算机视觉的模型已经在工业应用中得到应用,如基于人脸识别的生物特征认证;检测栽培中是否有害虫等。
数据科学家花大量时间处理数据,然后建立模型。构建一个演示来展示和构建一个一样重要。Streamlit 也让这项工作变得更容易。比方说,我构建了一个基于 keras 的模型来识别数字(0–9)。
只需遵循以下简单的 5 个步骤,你就能打造出一款应用
- 添加标题、页眉和描述与第一个应用程序非常相似。
- 为了对图像进行分类,我们需要上传图像——我们需要一个文件上传小部件。
- 只需调用 st.file_uploader ,将支持的文件类型作为参数(第 5 行)。
- 加载 keras 模型
- 检查按钮是否按下— 如果**ST . button(‘按钮名称’)。这一行创建按钮,并处理按钮被点击的事件。
- 显示一些进度条,以防模型需要一些时间

完整代码可以在这个 Github repo 上找到。
我认为这篇文章可以帮助你开始使用 Streamlit。他们已经有很好的文档可以参考。如果你有任何疑问,请发表在评论区。
使用 Elasticsearch 构建闪亮的仪表板
使用带有弹性搜索功能的闪亮仪表板,让数据变得生动

卡伦·艾姆斯利在 Unsplash 上的照片
在企业中,由于拥有大量的数据,可能需要处理多个数据源。当试图构建一个仪表板来展示商业想法时,通常需要集成来自 NoSQL 数据库、关系数据库和搜索引擎的数据。因此,像 Kibana 或 Google Data Studio 这样的仪表板并不是合适的选择,因为多数据源的灵活性有限。于是人们需要一个同样简单明了替代方案。对于这种情况,我推荐闪亮的仪表板来完成任务,因为它满足了要求:灵活、直截了当和美观。然而,在构建仪表板时,连接 Amazon Elasticsearch 服务有一个直接的实现障碍,这促使我写这篇文章。
本文展示了如何将 Elasticsearch 数据集成到一个闪亮的仪表板中。使用的编程语言主要是 R,用 Python 进行后端连接。同时,对于数据可视化部分,在 R 中用 3 个不同的绘图包绘制图形,分别是: ggplot2 、 plotly 和 wordcloud2 。
文章的内容:
- Elasticsearch 连接(与亚马逊 Elasticsearch 服务
- 使用 r 的数据操作。
- 展示工具闪亮的仪表板无需太多的样式定制即可将数据带入生活。
使用的环境:
- r 版本 3.4.4
- Python 3.7.4
- Ubuntu 18.04
Elasticsearch 是企业中流行的搜索引擎。一般来说,在进行汇总统计或及时定位特定批次的大量数据时,我建议将其添加到数据基础设施中。对于设置,一个方便的方法是使用 Amazon Elasticsearch 服务,因为它只需要处理一些高级参数,如碎片数量。此外,还提供了全面的文档和示例代码,当公司已经在 AWS 中构建了基础设施时,没有理由不使用它。亚马逊提供了样本代码,这是有据可查的,但支持语言不包含 R。虽然 R 中有各种用于 Elasticsearch 连接的包,但将其与亚马逊 Web 服务版本 4 认证(AWS4Auth)集成的方法并不直接。要构建仪表板,最关键的部分是克服这个实施障碍。

连接 Amazon Elasticsearch 服务和 Python 后端
首先,我们需要定位 Python 路径。我建议用两种方法来寻找它:
- 在 Python 环境中显示
import sys
# Python search for libraries at the ordering of the path
print(sys.path[0])
2.在命令行中显示,并激活所选的 Python 环境
which python
这两种方法都可以定位 Python 可执行文件的系统路径。
一旦知道了 python 路径,我们就可以开始连接了。我们将在 R 中使用 reticulate 包,它为 Python 和 R 之间的互操作性提供了一套全面的工具。详细内容可以在这里找到并且我推荐你阅读这个很棒的备忘单!
这个简单的方法管用!为了避免卡住,同时学习 R 和 Python 总是一个好主意。

照片由 Mirko Blicke 在 Unsplash 上拍摄
示范
因为我们目前没有托管的 Elasticsearch 实例。出于演示目的,让我们在本地机器上创建一些样本数据。
使用本地机器中的样本数据设置 Elasticsearch 的步骤:
- 下载并遵循 Elasticsearch 的说明。
- 下载并遵循基巴纳的指示。
- 主持 Elasticsearch 和 Kibana。
- 将样本飞行数据加载到基巴纳。Kibana 托管在 http://localhost:5601/ 上。

从 Kibana 加载样本数据。(图片由作者提供)
5.连接到 Elasticsearch
elasticsearch <- import("elasticsearch")host <- "localhost:9200"es <- elasticsearch$Elasticsearch(hosts = host)
由于没有使用 AWS4Auth,因此有多种连接方式。你也可以使用 R only 方法。
6.安装闪亮仪表板的必要组件,包括闪亮仪表板和闪亮仪表板。
使用 R 操作数据并构建闪亮仪表板
连接后,我们现在就可以开始在仪表板中编写功能了。首先让我们从结构开始:
├── global.R
├── server.R
└── ui.R
为了更好地组织代码,我将文件分成了以上 3 个部分。
global.R
顾名思义,这个文件存储了在应用程序启动之前运行一次的全局变量和函数。因此,我包含了 Elasticsearch 连接和查询。
全局中的连接和查询。R
server.R
一旦 dashboard 应用程序启动,它就会处理后端任务。例如,文件中应包含关于如何渲染图以及何时重新运行查询的逻辑。
使用Elasticsearch . search从 elastic search 得到的响应数据是字典格式的,并根据转换成命名列表。为了便于绘图,最好将所有响应数据转换为 R 数据帧格式,我们有两种选择:**
- 转换 r 中的数据。
- 用 Python 转换数据,转换熊猫。r 中的数据帧至数据帧。
在演示中,我们将使用 r。考虑到命名列表响应数据的复杂性,更有效地编写合适的数据转换函数的方法是使用 str 不断观察对象的结构。

响应子集数据的示例结构
在 R 控制台中经过多轮反复试验后,我们提出了两个函数来转换来自单个和两个聚集查询的数据。
现在我们为图表绘制准备数据框。首先,我们创建数据框架,并使用 Plotly R 绘制航班数量的饼图。
函数来渲染一个 plotly 图形
以下形式的转换后的数据帧。

航班数量的转换数据框架
Plotly 是一个流行的图表可视化工具,它允许用户创建具有交互性选项的交互性可视化。使用 Plotly 制作的图形支持放大和缩小以及悬停文本等功能。然而,与 ggplot 相比,在 Plotly 中渲染图表在显示大量数据时会非常慢。
然后我们创建数据框架,并使用 ggplot 绘制航班延误时间序列数据的堆积条形图。我们将在控制面板中制作一个时间滑块,供用户选择图表的时间范围,因此我们必须按选定的时间输入进行过滤。
以下形式的转换后的数据帧。

航班延误的转换数据帧
ggplot 允许用户快速可视化趋势,并在层中添加定制。如果需要更具交互性的图表,您可以通过代码ggplotly(p)将您的图形转换为 Plotly 。
最后,我们使用 wordcloud2 为天气数据创建数据框架和单词云。此外,我们将在仪表板中制作一个滑块,供用户调整所需的 wordcloud 大小。
以下形式的转换后的数据帧。

天气的转换数据帧
用 wordcloud2 制作的单词云自动计算单词的大小和位置,当鼠标悬停时,它支持显示原始值。因此,用户可以获得数据的概览,以及针对特定的词进行数据洞察。

ui.R
它处理应用程序的前端外观。闪亮的部件和风格的代码应该放在这里。基本上所有想要的仪表板外观都应该在这里。交互式仪表板的基本要素是小部件的使用。有很多资源可以用来创建闪亮的小工具,比如这里的。一旦你有了一个想法,你就可以简单地搜索合适的小部件并把它放到ui.R文件中。除此之外,一些闪亮的仪表板元素可以在找到。只要确保每次添加新的小部件时都处理了数据逻辑。
作为演示的一个例子,对于我们的 word cloud 框,我们创建一个 sliderInput 来控制它的整体大小。
关于 UI 的更多细节,欢迎您阅读我的源代码。
最后,让我们在 R 控制台中托管闪亮的应用程序:
**runApp(host="0.0.0.0", port=1234)**
访问 http://localhost:1234/ 可以查看演示仪表盘。

本次演示中制作的仪表板。(图片由作者提供)
结论
在本文中,我们已经完成了创建一个闪亮的仪表板的基本步骤,将数据带入生活。特别是,我们有
- 使用 Python 后端连接 Elasticsearch 并将数据转换为 R 命名列表。
- 用 r 创建多个数据转换函数。
- 利用 Plotly、ggplot 和 wordcloud2 包进行绘图。
感谢阅读!希望这篇文章对你有用。源代码贴在我的 GitHub 库里。请随时给我留言,告诉我你对这篇文章的看法。如果你有更方便的方法,请告诉我:)
领英:
https://www.linkedin.com/in/andy-k-1b1a44103/
利用朴素贝叶斯和随机森林建立垃圾短信分类模型
如果你对数据科学感兴趣,并且正在寻找入门项目,那么垃圾短信分类项目是你应该着手的项目之一!在本教程中,我们将一步一步地从导入库到完整的模型预测,然后测量模型的准确性。

Dhaval 的图片(在 iPad 上绘制)
关于垃圾短信分类
一个好的文本分类器是这样一种分类器,它能在合理的时间范围内以可接受的准确度有效地对大量文本文档进行分类,并提供人类可读的分类规则以进行可能的微调。如果分类器的训练也很快,这可能在一些应用领域中成为分类器的良好资产。已经设计了许多用于自动文本分类的技术和算法。
文本分类任务可以被定义为基于在训练阶段在分类系统中获得的知识将类别标签分配给新文档。在训练阶段,给我们一组附有类别标签的文档,并使用学习方法构建一个分类系统。分类是数据挖掘和机器学习领域的一项重要任务,然而,文本分类中的大多数学习方法都来自于机器学习研究。
使用 Python 和 Pandas 构建垃圾短信分类
对于这个项目,我会使用谷歌 Colab,但你也可以使用 python 笔记本来达到同样的目的。
导入库
首先,我们将导入所需的库,如 pandas、matplotlib、numpy、sklearn
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import scipy as sp
from google.colab import drive
from sklearn import feature_extraction, model_selection, naive_bayes, metrics, svm
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import precision_recall_fscore_support as score
%matplotlib inline
*drive.mount*('/content/drive')
注意:如果您没有使用 Google Colab,可以删除代码片段的最后一行。最后一行是为了在 Google Colab 上安装我的 Google Drive,这样我就可以使用我的 Drive 中的数据集。
导入数据集
我会上传我的 GitHub repo 中的数据集,可以在这里找到。
下载数据集后,我们将使用 pandas 的 read_csv 函数导入它。
dataset = pd.read_csv(*"/content/drive/My Drive/SMS_Spam_Classification/spam.csv",* encoding='latin-1')
注意:请使用您自己的数据集路径。
现在我们已经导入了数据集,让我们看看是否使用 head()函数导入了格式不正确的数据集。
dataset.head()

从上面的数据集片段中,我看到了我们不需要的列名!因此,现在的任务是清理和重新格式化数据,以便我们使用它来构建我们的模型。
数据清理&探索
现在我们必须删除未命名的列。为此,我们将使用 drop 函数。
*#removing unnamed columns*
dataset = dataset.drop('Unnamed: 2', 1)
dataset = dataset.drop('Unnamed: 3', 1)
dataset = dataset.drop('Unnamed: 4', 1)
现在,下一个任务是将列 v1 和 v2 分别重命名为标签和消息!
dataset = dataset.rename(columns = {'v1':'label','v2':'message'})
现在,另外(这是一个可选的步骤,但是做一些数据探索总是好的:P)
dataset.groupby('label').describe()

接下来,我们想知道在我们的数据集中有多少邮件是垃圾邮件。为此:
count_Class=pd.value_counts(dataset["label"], sort= True)
count_Class.plot(kind = 'bar',color = ["green","red"])
plt.title('Bar Plot')
plt.show();
解释:这里我们设置 sort = True,使用熊猫的 value_counts 方法。这段代码将为垃圾邮件类和非垃圾邮件类和非垃圾邮件类分别制作一个绿色和红色的条形图。
您可能会得到类似如下的输出:

我们看到我们有很多垃圾邮件,而垃圾邮件却很少。在本教程中,我们将继续使用这个数据集,但不增加它(没有过采样/欠采样)。
实现用于垃圾短信分类的朴素贝叶斯
首先,让我将垃圾邮件和非垃圾邮件分别编码为 1 和 0。
*# Classifying spam and not spam msgs as 1 and 0*
dataset["label"]=dataset["label"].map({'spam':1,'ham':0})
X_train, X_test, y_train, y_test = model_selection.train_test_split(X, dataset['label'], test_size=0.70, random_state=42)
现在,上面代码片段的第二行使用 sklearn 库 splot 方法将数据分成训练和测试数据集。这里我提到了测试数据的大小是整个数据集的 70%。(您可以在这里根据您的意愿进行更改)
奖励: DONT 知道数据集的拆分及其好处吗? 阅读我的这篇文章,我在这里解释了所有 !
现在我将使用多项式朴素贝叶斯算法!
list_alpha = np.arange(1/100000, 20, 0.11)
score_train = np.zeros(len(list_alpha))
score_test = np.zeros(len(list_alpha))
recall_test = np.zeros(len(list_alpha))
precision_test= np.zeros(len(list_alpha))
count = 0
**for** alpha **in** list_alpha:
bayes = naive_bayes.MultinomialNB(alpha=alpha)
bayes.fit(X_train, y_train)
score_train[count] = bayes.score(X_train, y_train)
score_test[count]= bayes.score(X_test, y_test)
recall_test[count] = metrics.recall_score(y_test, bayes.predict(X_test))
precision_test[count] = metrics.precision_score(y_test, bayes.predict(X_test))
count = count + 1
正如您所看到的,我还加入了一个回忆测试和精度测试,以便更准确地评估我的模型的性能。
现在,对于不同的α值,我会制作一个表格来查看各种度量,如训练准确度、测试准确度、测试召回率、测试精确度。
matrix = np.matrix(np.c_[list_alpha, score_train, score_test, recall_test, precision_test])
models = pd.DataFrame(data = matrix, columns =
['alpha', 'Train Accuracy', 'Test Accuracy', 'Test Recall', 'Test Precision'])
models.head(n=10)

现在我们必须看到测试精度的最佳指标,因为我在这里更关心它。请注意,我们并不总是必须使用精度来评估我们的模型。它总是取决于您的用例!
best_index = models['Test Precision'].idxmax()
models.iloc[best_index, :]**OUTPUT: -**alpha 10.670010
Train Accuracy 0.977259
Test Accuracy 0.962574
Test Recall 0.720307
Test Precision 1.000000
实现随机森林
我将使用 RandomForestClassifier 函数,n_estimators 为 100(您可以根据自己的意愿更改它以获得最佳结果)
rf = RandomForestClassifier(n_estimators=100,max_depth=**None**,n_jobs=-1)
rf_model = rf.fit(X_train,y_train)
在上面的代码片段中,上次我用 X_train 和 y_train 拟合我的模型。
现在,让我们看看预测。我会使用预测功能和计算精度,召回,f 分数,以及准确性措施。
y_pred=rf_model.predict(X_test)
precision,recall,fscore,support =score(y_test,y_pred,pos_label=1, average ='binary')
print('Precision : **{}** / Recall : **{}** / fscore : **{}** / Accuracy: **{}**'.format(round(precision,3),round(recall,3),round(fscore,3),round((y_pred==y_test).sum()/len(y_test),3)))
车型评价
Precision : 0.995 / Recall : 0.726 / fscore : 0.839 / Accuracy: 0.963
因此,我们看到,我们的模型的准确性约为 96 %,我认为这相当不错。它的精度值也接近 1,这也是一个不错的值。
在我的下一篇文章中,我将使用 NLP 和神经网络,并解释我们如何才能得到一个更准确的模型!
如果你喜欢这个教程,请分享给你的朋友或在社交媒体上!
想聊聊数据科学吗?在 LinkedIn 上 Ping 我!
使用 SQLAlchemy 和 AWS RDS 为您的投资组合项目构建坚实的基础
借助 SQL Alchemy 和 AWS RDS,您可以将数据发送到云中,并在舒适的 Jupyter 中利用 SQL。

法比奥在 Unsplash 上拍摄的照片
通常情况下,项目所需的数据存储在一些关系数据库中……如果它目前以 csv 文件的形式四处传播,那么您也应该将它存储在安全的地方。最简单的方法当然是 SQL。
好消息是,如果您不喜欢使用 MySql 或其他关系数据库管理系统(RDBMS ),由于 SQLAlchemy,您仍然可以在舒适的 Jupyter 上完成大部分工作!
从 AWS 云服务入手比你想象的要容易!
AWS、Azure 或 Google Cloud 等云服务通常是部署模型的最简单方式,这使得它们成为申请数据科学职位时所需的技能。哪怕只有其中一种的基本经验,也会让您在数据科学之旅中有一个良好的开端。
嗯……你已经完成了几门 Coursera 课程,参加了 Kaggle 比赛,掌握了 Scikit-Learn 但是云服务听起来像是很复杂,自己很难掌握的东西?你大错特错了…与理解机器学习的基础相比,这是小菜一碟。通过这一点额外的工作,你真的可以提高你创建 E2E 项目的技能。
在本文中,我旨在向您展示如何轻松地开始使用 AWS 环境,并使用它来创建您的私有 RDS。我选择 AWS,因为我相信它是最好的学习材料之一,并且易于使用。在小规模学习项目方面,它也有不错的定价——你几乎可以免费获得所有东西。然而,在选择服务时要小心——我建议在任何变化后的几天内检查账单,以确保你在月底不会被收取太多费用。
在以后的文章中,我还将关注 AWS 的其他方面,比如 EC2 与 Docker 的结合,用于模型的稳定部署。由于数据不是数据科学中的第一个词,我决定建立一个稳定的数据基础将在未来节省您的时间和精力。
1.建立自己的 MySql 数据库
如果你已经专业地处理数据,你可能熟悉你公司的关系数据库。然而,我相信至少整个数据管道的基本知识是有用的,包括建立一个数据库。
另一方面,数据科学需要不断学习,参与私人项目是这一旅程的重要组成部分。出于这个原因,我建议你建立你的私人数据库。
我自己花了将近两年的时间,基于本地或 GitHub 上存储的 csv 和 json 输入构建自己的项目组合,相信我,过一段时间后,所有的输入和输出文件都变得一团糟,我真希望早点创建自己的私有 DB。
在 AWS RDS 上建立一个数据库需要大约 10 分钟,并且不需要任何经验:你需要做的就是遵循 AWS 本身的这份出色的入门材料——他们做得如此之好,以至于我自己都不会试图写它,因为它不可能更清楚了。按照下面的说明设置数据库,直到第 1 步结束-我们将直接从 Python 继续第 2 步:
在本教程中,您将学习如何创建一个运行 MySQL 数据库的环境(我们称这个环境为…
aws.amazon.com](https://aws.amazon.com/getting-started/hands-on/create-mysql-db/)
请记住选择免费层,记下所选密码(如果丢失,将无法找回),并将 Publicly Accessible 设置为 Yes —(您需要扩展附加连接配置)。要记住的另一个重要部分是在步骤 e 中设置数据库名称——忽略这一点会使以后的工作更加困难。一旦你准备好了,我们可以在舒适的 Jupyter 笔记本上做剩下的工作。
2.使用 SQL Alchemy 连接到 AWS RDS
恭喜你!您已经创建了自己的基于私有云的关系数据库。现在让我们用 SQL-Alchemy 将我们的 Jupyter 笔记本连接到数据库。文章这一部分的代码和数据可以从 GitHub 获得。
首先,我们需要定义 4 个关键参数,它们允许 SQLAlchemy 连接到 AWS RDS。
host="sqlalchemytutorial.*****.eu-central1.rds.amazonaws.com"
port=3306
dbname="TUTORIAL"
user="admin"
password="Baloney1" #now they make you add numbers...
- 前两个参数可以在连接性和安全性详细信息中找到,一旦进入 DB 实例就会出现这些信息

关于数据库实例的关键信息
- dbname 是您在创建数据库期间定义的名称(或者您将来可能要使用的任何其他模式名称)

- 用户和口令已由您在设置数据库时的身份证明设置过程中定义

一旦我们完成了排序,我们需要做的就是用这个简单的查询建立一个连接
database_connection = sqlalchemy.create_engine('mysql+mysqlconnector://{0}:{1}@{2}/{3}'
.format(user, password,host, dbname)).connect()
现在我们已经连接好了,准备向我们的数据库写入一些数据!
3.将数据从 csv 文件写入数据库
目前,我们的数据库是空的,我们需要填充它。出于本教程的目的,我将使用从 Right move 删除的伦敦租金数据的一个小样本:如果你对这个话题感兴趣,你可以在我的文章中阅读更多关于伦敦租金列表的漂亮汤的网络抓取初学者指南。
#Reading data from csv file
data = pd.read_csv(r"[https://raw.githubusercontent.com/Jan-Majewski/Medium_articles/master/02_AWS_RDS_with_SQLAlchemy/London_property_data.csv](https://raw.githubusercontent.com/Jan-Majewski/Medium_articles/master/02_AWS_RDS_with_SQLAlchemy/London_property_data.csv)")data.head()

目前,所有数据都存储在一个堆栈中,但这不是很容易扩展,让我们将它分成 3 个表,以利用 SQL 的优势。我们将能够根据“id”键加入数据。值得确保键列具有 int 类型,因为在 floats 上连接比较慢,并且可能由于舍入误差而导致困难。
property_features=['id','bedrooms', 'bathrooms']
location_features=['id','latitude','longitude','City', 'Country']
price_features=['id', 'MonthlyPrice','download_time']table_properties=data[property_features]
table_locations=data[location_features]
table_prices=data[price_features]table_price.head()

将我们的数据拆分到单独的表中有一个很大的优势,我们可以节省存储空间——在这种情况下,我们可以很有信心,一旦我们有了关于物业位置及其特征的数据,它就不太可能改变。然而,价格可能会经常变化,这就是为什么我只在 table_price 中包含 download _ time 我们可以追加更新的价格,而不必将我们已经拥有的位置和属性数据追加到其他表中。
既然我们已经准备好了数据,我们可以将它写入我们的数据库。我们不需要担心游标、数据类型等等,我们可以只使用 pd.to_sql。
table_property.to_sql(con=database_connection, name="PROPERTIES", if_exists='replace',chunksize=100, index=False)table_location.to_sql(con=database_connection, name="LOCATIONS", if_exists='replace',chunksize=100, index=False)table_prices.to_sql(con=database_connection, name="PRICES", if_exists='replace',chunksize=100, index=False)
我选择 chunksize 为 100 来批量写入数据,但是如果容量不大,您也可以一次写入所有数据。
在这里,我们已经填充了数据库中的前 3 个表:属性、位置和价格。
4.使用 SQL 查询数据
测试 data foundation 的最后一步是查询保存的数据,这样我们就不需要再次使用 csv 文件。让我们编写一个简单的查询,其中我们连接“id”上的所有表并执行它。
sql_query='''
SELECT * FROM PRICES a
JOIN LOCATIONS b
ON a.id=b.id
JOIN PROPERTIES c
ON a.id=c.id
'''property_data=pd.read_sql(sql_query,con=database_connection)
property_data.head()

我们设法检索并连接存储在数据库中的财产数据。这个数据集非常简单,存储在关系数据库中没有什么优势,但是对于频繁更新的更大、更复杂的数据集,它有一个巨大的优势,您可以使用与这里演示的完全相同的方法。
5.创建新模式
为了使您的数据库可伸缩,您可能需要不止一个模式,它很像数据库中的一个文件夹。您也可以从 Python 中添加它。但是,您需要安装 sqlalchemy_utils 库。您需要做的就是使用新模式的名称创建另一个连接。然后测试模式是否已经存在,如果不存在,则创建它—类似于在本地工作时检查文件夹并在需要时创建它。
dbname_2='TUTORIAL_ADVANCED'
database_connection_2 = 'mysql+mysqlconnector://{0}:{1}@{2}/{3}'.format(user, password,host, dbname_2)if not database_exists(database_connection_2):
create_database(database_connection_2)
摘要
在这篇简短的文章中,我旨在展示如何快速开始使用 AWS RDS 并为您的项目构建稳定的数据基础,同时通过使用 SQL Alchemy 将所有主要步骤都保留在笔记本中。
我希望这种方法能够帮助您构建可扩展的数据科学项目,并避免存储在几十个不同文件中的数据出现混乱。
这篇文章是我计划在 AWS 上写的一系列文章中的第一篇,所以如果你对这个话题感兴趣,请关注我的简介,这样你就不会错过了!
感谢您的宝贵时间!希望你喜欢这篇文章。
用 Kiba 在 Ruby 中构建世界上最简单的 ETL(提取、转换、加载)管道
数据预处理
通过构建管道修改 CSV 中的文本来学习 ETL

您多久遍历一次数据库表中的所有记录,修改每条记录,然后重新保存一次?
对我来说,很多。
这种模式被称为 ETL (提取、转换、加载)。
我在网络应用、分析平台和机器学习管道中看到了这一点。
你可以自己开发,但是有很多包可以让 ETL 的编写变得干净、模块化和可测试。
我们将使用 Kiba 在 Ruby 中浏览一个例子。
什么是 ETL?
ETL 代表“提取、转换、加载”,但除非你来自数据挖掘背景,否则这个名字会误导人。
更好的名称可能是“加载、修改、保存”。
提取 =从一个源加载数据(例如:数据库、CSV、XML、JSON、…)
转换 =修改/增加每个数据点(例如:添加地理位置数据、修改标点符号、计算一些东西等等)
加载 =存储更新(即:数据库、CSV、数据仓库……)
我们的目标
我们将:
- 将电话号码的 CSV 作为输入
- 删除非数字字符和不是 10 位数的电话号码
- 保存到另一个 CSV
代码
我们将把它打包到一个小型的 ruby 项目中。
创建我们的目录
$ mkdir kiba-etl && cd kiba-etl/
添加源 CSV
用touch phone.csv创建一个 CSV 文件并粘贴到下面。
id,number
1,123.456.7891
2,222
3,303-030-3030
4,444-444-4444
5,900-000-00001
6,#1000000000
7,#9898989898
8,800-000-00000
9,999.999.9999
10,1.1.1.1.1.1.1.1.1.1
11,(112)233-4455
12,(121)212-0000
在真实情况下,你可以使用 Twilio 这样的服务来检测它们是否是真实的电话号码。
创建 Gemfile
运行touch Gemfile并将以下内容添加到文件中。
source '[https://rubygems.org'](https://rubygems.org')gem 'kiba'
gem 'rake', '~> 11.2', '>= 11.2.2'
用bundle install安装这些包。
创建用于提取的类
创建一个文件来存储我们的 ETL 类。我们称之为common.rb。
写我们在common.rb的第一堂课。我们可以给这个类取任何名字,但是我选择了SourceCSV。
require 'csv'class SourceCSV
def initialize(filename:)
[@filename](http://twitter.com/filename) = filename
end # Iterates over each line in the CSV so we can pass them one at a
# time to transform in the next step
def each
csv = CSV.open([@filename](http://twitter.com/filename), headers:true) csv.each do |row|
yield(row.to_hash)
end csv.close
end
end
创建一个耙式文件
我们将使用耙子任务来启动 Kiba 作业。
创建一个名为Rakefile(没有扩展名)的文件,并添加以下内容。我们稍后会添加更多的逻辑。
require 'kiba'
require_relative 'common'task :kiba_run do
puts "The job is running..."
Kiba.run(
Kiba.parse do
##############################################################
source SourceCSV, filename: 'numbers.csv'
##############################################################
end
)
puts "...The job is finished"
end
注意,我们的 rake 任务被命名为kiba_run。让我们从控制台运行我们的任务。
$ rake kiba_run
输出应该是:
The job is running...
...The job is finished
如果我们看到这一点,到目前为止一切正常。
为加载创建一个类
现在我们将创建一个在数据被修改后保存数据的类。显然我们还没有添加任何修改逻辑。
在common.rb中,添加。
class DestinationCSV
def initialize(filename:)
[@csv](http://twitter.com/csv) = CSV.open(filename, 'w')
[@headers_written](http://twitter.com/headers_written) = false
end def write(row)
if !@headers_written
# Add headers on the first row
# after which, don't add headers
[@headers_written](http://twitter.com/headers_written) = true
[@csv](http://twitter.com/csv) << row.keys
end
[@csv](http://twitter.com/csv) << row.values
end def close
[@csv](http://twitter.com/csv).close
end
end
这将我们加载的数据存储到一个新的 CSV 中。或者,您可以将这些数据转储到像 postgres 这样的数据库中。
将加载步骤添加到 rake 文件。
...
##############################################################
source SourceCSV, filename: 'numbers.csv' destination DestinationCSV, filename: 'numbers-cleaned.csv'
##############################################################
...
用rake kiba_run再试一次。
现在应该有一个名为numbers-cleaned.csv的新文件,看起来和numbers.csv一模一样。
恭喜你!您已经完成了 ETL 中的“E”和“L”步骤。
为转换创建类
现在是有趣的部分。我们将创建两个与 transform 相关的类,每个类做不同的事情。
第一个从我们的数字中删除标点符号,并计算字符数。将此类添加到common.rb。
class TransformClean
def initialize(field:)
[@field](http://twitter.com/field) = field
end def process(row)
number = row[[@field](http://twitter.com/field)] # remove non-numeric characters
row[:number_cleaned] = number.tr('^0-9', '') # count number of characters
row[:digit_count] = row[:number_cleaned].length row
end
end
并更新Rakefile。
...
#################################################################
source SourceCSV, filename: 'numbers.csv' transform TransformClean, field: 'number' destination DestinationCSV, filename: 'numbers-cleaned.csv'
#################################################################
第二个删除所有不是 10 位数的数字。将第二个转换类添加到common.rb。
class TransformDropFake
def initialize(field:)
[@field](http://twitter.com/field) = field
enddef process(row)
number = row[[@field](http://twitter.com/field)]
row[:digit_count] == 10 ? row :nil
end
end
更新我们的耙子任务。
...
##################################################################
source SourceCSV, filename: 'numbers.csv' transform TransformClean, field: 'number'
transform TransformDropFake, field: 'number' destination DestinationCSV, filename: 'numbers-cleaned.csv'
##################################################################
...
现在再次运行我们的 rake 任务,看看输出的文件。应该是这样的。
id,number,number_cleaned,digit_count
1,123.456.7891,1234567891,10
3,303-030-3030,3030303030,10
4,444-444-4444,4444444444,10
6,#1000000000,1000000000,10
7,#9898989898,9898989898,10
9,999.999.9999,9999999999,10
10,1.1.1.1.1.1.1.1.1.1,1111111111,10
11,(112)233-4455,1122334455,10
12,(121)212-0000,1212120000,10
厉害!
如果我们把输出的 CSV 打印出来,看起来会像这样。试试:cat numbers-cleaned.csv | column -t -s, | less -S。
id number number_cleaned digit_count
1 123.456.7891 1234567891 10
3 303-030-3030 3030303030 10
4 444-444-4444 4444444444 10
6 #1000000000 1000000000 10
7 #9898989898 9898989898 10
9 999.999.9999 9999999999 10
10 1.1.1.1.1.1.1.1.1.1 1111111111 10
11 (112)233-4455 1122334455 10
12 (121)212-0000 1212120000 10
我们已经在 CSV 上实现了 ETL!
结论
这个 youtube 视频 和这个 博文 都有助于搞清楚这一点。
如果你把 ETL 模式放在心里,你会惊讶于使用它的频率。
但是 Python 里那么多 ETL 包(即:Airflow,Luigi,Bonobo,…),为什么会在 Ruby 里用 Kiba 呢?
您的 web 应用程序是 Ruby on Rails,您的团队中没有 Python 专家,或者您只是想要一个简单的 ETL 解决方案。
我说,在生产环境中,只要有可能,就使用你所知道的,并最小化复杂性。
构建、训练和部署一个包含 102 种花卉类型的真实世界花卉分类器
借助 TensorFlow 2.3、Amazon SageMaker Python SDK 2.5.x 和定制 SageMaker 培训和服务 Docker 容器

Lotus Flower taken at Summer Palace (颐和园), Beijing China in 2008. © Juv Chan. All rights reserved.
简介
我喜欢花。上面的荷花是我最喜欢的花卉照片之一,是我 2008 年参观北京颐和园时拍的。由于我是一名开发人员,并且喜欢学习和从事人工智能和云项目,我决定写这篇博客来分享我与 TensorFlow、Amazon SageMaker 和 Docker 一起构建真实世界花卉分类器的项目。
这篇文章展示了一步一步的指南:
- 使用现成的 花数据集 从 TensorFlow 数据集 。
- 使用 转移学习 从来自tensor flow Hub的预训练模型中提取特征。
- 使用 tf.data API 为分割成训练、验证和测试数据集的数据集构建输入管道。
- 使用 tf.keras API 建立、训练和评估模型。
- 使用回调定义提前停止阈值进行模型训练。
- 准备训练脚本以 SavedModel 格式训练并导出模型,用于部署tensor flow和Amazon SageMaker Python SDK。
- 准备推理代码和配置以运行 TensorFlow 服务模型服务器 为模型服务。
- 用亚马逊 SageMaker Python SDK 和中的 SageMaker TensorFlow 训练工具包 构建自定义Docker 容器 用于训练和服务 TensorFlow 模型。****
公众可通过以下网址获得该项目:
**** [## juv chan/亚马逊-sage maker-tensor flow-自定义-容器
这个项目展示了一步一步的指导如何建立一个现实世界的花卉分类器的 102 种花卉类型使用…
github.com](https://github.com/juvchan/amazon-sagemaker-tensorflow-custom-containers/)
设置
以下是用于开发和测试项目的系统、硬件、软件和 Python 包的列表。
- LTS
- 12 年 3 月 19 日
- Python 3.8.5
- 康达 4.8.4
- 英伟达 GeForce RTX 2070
- NVIDIA 容器运行时库 1.20
- NVIDIA CUDA 工具包 10.1
- sagemaker 2.5.3
- sagemaker-tensor flow-培训 20.1.2
- 张量流-gpu 2.3.0
- 张量流数据集 3.2.1
- 张量流-集线器 0.9.0
- 张量流-模型-服务器 2.3.0
- 木星实验室 2.2.6
- 枕头 7.2.0
- matplotlib 3.3.1
花卉数据集
TensorFlow Datasets (TFDS)是一个公共数据集的集合,可用于 TensorFlow、 JAX 和其他机器学习框架。所有 TFDS 数据集都以 tf.data.Datasets 的形式公开,易于用于高性能的输入管道。
迄今为止,TFDS 共有 195 个现成可用的数据集。TFDS 有 2 个花卉数据集:Oxford _ flowers 102, tf_flowers
使用Oxford _ flowers 102数据集是因为它具有更大的数据集大小和更大数量的花类别。
ds_name = 'oxford_flowers102'
splits = ['test', 'validation', 'train']
ds, info = tfds.load(ds_name, split = splits, with_info=True)
(train_examples, validation_examples, test_examples) = dsprint(f"Number of flower types {info.features['label'].num_classes}")
print(f"Number of training examples: {tf.data.experimental.cardinality(train_examples)}")
print(f"Number of validation examples: {tf.data.experimental.cardinality(validation_examples)}")
print(f"Number of test examples: {tf.data.experimental.cardinality(test_examples)}\n")
print('Flower types full list:')
print(info.features['label'].names)
tfds.show_examples(train_examples, info, rows=2, cols=8)

oxford_flowers 数据集摘要和示例
创建 SageMaker TensorFlow 培训脚本
Amazon SageMaker 允许用户使用训练脚本或推理代码,就像在 SageMaker 外部运行定制的训练或推理算法一样。其中一个区别是,亚马逊 SageMaker 使用的训练脚本可以利用 SageMaker 容器中的环境变量,例如 SageMaker 容器中的 SM_MODEL_DIR ,SM _ NUM _ GPU,SM _ NUM _ CPU。
Amazon SageMaker 在运行脚本、训练算法或部署模型时总是使用 Docker 容器。亚马逊 SageMaker 为其内置算法提供了容器,并为一些最常见的机器学习框架提供了预构建的 Docker 映像。您还可以创建自己的容器映像来管理 Amazon SageMaker 提供的容器无法解决的更高级的用例。
自定义培训脚本如下所示:
使用 TensorFlow Hub 进行迁移学习(TF-Hub)
tensor flow Hub是一个可重用的预训练机器学习模型库,用于不同问题领域的迁移学习。对于这个花分类问题,我们基于不同的图像模型架构和来自 TF-Hub 的数据集评估预训练的图像特征向量,如下用于在 oxford_flowers102 数据集上的迁移学习。
在最终的训练脚本中, Inception V3(非自然主义者)特征向量预训练模型用于该问题的迁移学习,因为它与上面的其他模型(在 5 个时期内约 95%的测试准确性,无需微调)相比表现最佳。该模型使用 Inception V3 架构,并在来自https://www.inaturalist.org/的超过 5000种不同动植物的inauturalist(iNat)2017数据集上进行训练。相比之下, ImageNet 2012 数据集只有 1000 个类,其中的花类型非常少。
具有张量流服务的服务花分类器
TensorFlow Serving 是一个灵活、高性能的机器学习模型服务系统,专为生产环境而设计。它是部署生产机器学习(ML)管道的端到端平台tensor flow Extended(TFX)的一部分。 TensorFlow 服务模型服务器二进制 有两种变体:tensor flow-model-server和tensor flow-model-server-universal。 TensorFlow 服务模型服务器支持gRPC API和RESTful API。
在推理代码中,tensor flow-model-server用于通过 RESTful APIs 为模型提供服务,从这里将模型导出到 SageMaker 容器中。它是一个完全优化的服务器,使用一些特定于平台的编译器优化,应该是用户的首选。推理代码如下所示:
为 SageMaker 训练和推理构建定制的 Docker 映像和容器
Amazon SageMaker 利用 Docker 容器来运行所有的训练作业和推理端点。亚马逊 SageMaker 提供了支持机器学习框架的预建 Docker 容器,如 SageMaker Scikit-learn 容器 、 SageMaker XGBoost 容器 、 SageMaker SparkML 服务容器 、 深度学习容器 (TensorFlow、PyTorch、MXNet 和 Chainer)以及 SageMaker RL(强化这些预先构建的 SageMaker 容器应该足以用于通用机器学习训练和推理场景。
有一些场景是预构建的 SageMaker 容器无法支持的,例如
- 使用不支持的机器学习框架版本
- 使用预构建的 SageMaker 容器中没有的第三方包、库、运行时或依赖项
- 使用定制的机器学习算法
Amazon SageMaker 支持用户为上述高级场景提供的定制 Docker 图像和容器。用户可以使用任何编程语言、框架或包来构建自己的 Docker 映像和容器,这些映像和容器是为亚马逊 SageMaker 的机器学习场景量身定制的。
在这个花卉分类场景中,自定义 Docker 图像和容器用于训练和推理,因为预构建的 SageMaker TensorFlow 容器没有训练所需的包,即 tensorflow_hub 和 tensorflow_datasets 。下面是用于构建自定义 Docker 映像的Docker 文件。
下面的 Docker 命令用于构建自定义 Docker 映像,该映像用于本项目的培训和 SageMaker 托管。
docker build ./container/ -t sagemaker-custom-tensorflow-container-gpu:1.0
在 Docker 映像成功构建之后,使用下面的 Docker 命令来验证新映像是否按预期列出。
docker images

本地模式下的 SageMaker 培训
SageMaker Python SDK 支持 本地模式 ,允许用户创建估算器、训练模型并将其部署到他们的本地环境中。这对于任何想要在运行到云中之前,在本地实例上使用 SageMaker Python SDK 在 Jupyter 笔记本中原型化、构建、开发和测试他或她的机器学习项目的人来说,都是非常有用和具有成本效益的。
亚马逊 SageMaker 本地模式支持本地 CPU 实例(单实例和多实例)和本地 GPU 实例(单实例)。它还允许用户通过更改 SageMaker Estimator 对象的 instance_type 参数,在本地和云实例(即 Amazon EC2 实例)之间无缝切换(注意:该参数在 SageMaker Python SDK 1.x 中以前称为 train_instance_type )。其他一切都一样。
在这种情况下,如果可用,默认使用本地 GPU 实例,否则回退到本地 CPU 实例。注意输出路径设置为本地当前目录(文件://)。)将训练好的模型工件输出到本地当前目录,而不是上传到亚马逊 S3。 image_uri 被设置为本地定制的 Docker 映像,该映像是在本地构建的,因此 SageMaker 不会从基于框架和版本的预构建的 Docker 映像中获取。您可以参考最新的sage maker tensor flow Estimator和sage maker Estimator BaseAPI 文档了解全部细节。
此外,通过设置 SageMaker 估计器对象的超参数,可以将超参数传递给训练脚本。可以根据训练脚本中使用的超参数来设置的超参数。在这种情况下,它们是*【epochs】【batch _ size】【learning _ rate】*。

在自定义 TensorFlow 容器中完成 SageMaker 培训作业
SageMaker 本地端点部署和模型服务
SageMaker 培训作业完成后,运行该作业的 Docker 容器将退出。当训练成功完成后,通过调用 SageMaker 估计器对象的 deploy 方法,并将 instance_type 设置为 local instance type(即 local_gpu 或 local ,可以将训练好的模型部署到 local SageMaker 端点。
将启动一个新的 Docker 容器来运行定制推理代码(即 serve 程序),该程序运行 TensorFlow Serving ModelServer 来为模型提供实时推理服务。ModelServer 将在 RESTful APIs 模式下提供服务,并期待 JSON 格式的请求和响应数据。当本地 SageMaker 端点部署成功时,用户可以向端点发出预测请求,并实时获得预测响应。
tf_local_predictor = tf_local_estimator.deploy(initial_instance_count=1,
instance_type=instance_type)

在自定义 TensorFlow 服务容器上运行的 SageMaker 推理端点

SageMaker TensorFlow 服务容器正在运行,训练容器已退出
利用花图像的外部来源预测花的类型
为了使用准确度度量来评估这种花分类模型的性能,使用了来自独立于 oxford_flowers102 数据集的外部源的不同花图像。这些测试图片的主要来源是提供高质量免费图片的网站,如【unsplash.com】以及自拍照片。****







总结
最终的花卉分类模型根据一组来自外部来源的不同类型的真实世界花卉图像进行评估,以测试它对看不见的数据的概括程度。因此,该模型能够正确地分类所有看不见的花图像。模型大小约为 80 MB ,对于生产中的边缘部署来说,这可以认为是相当紧凑和高效的。总之,该模型似乎能够在给定的一小组不可见数据上表现良好,并且对于生产边缘或 web 部署来说相当紧凑。
提议的改进
由于时间和资源的限制,此处的解决方案可能无法提供最佳实践或最佳设计和实施。这里有一些想法,对任何有兴趣改进当前解决方案的人都有用。
- 应用,即随机(但真实)的变换,如旋转、翻转、裁剪、亮度和对比度等。以增加其规模和多样性。
- 使用 Keras 预处理图层 。 Keras 提供预处理层,如图像预处理层和图像数据增强预处理层,它们可以作为 Keras SavedModel 的一部分进行组合和导出。因此,模型可以接受原始图像作为输入。****
- 将 TensorFlow 模型(SavedModel 格式)转换为tensor flow Lite模型(。tflite),用于移动和物联网设备上的边缘部署和优化。
- 优化 TensorFlow 服务签名(SavedModel 中的 SignatureDefs )以最小化预测输出数据结构和有效载荷大小。当前模型预测输出返回所有 102 种花类型的预测类别和分数。
- 使用TensorFlow Profiler工具跟踪、分析和优化 tensor flow 模型的性能。
- 使用 英特尔发布的 OpenVINO toolkit 在英特尔硬件如 CPU、iGPU、VPU 或 FPGA 上进行模型优化和高性能推理。
- 优化 Docker 图像尺寸。
- 为 TensorFlow 培训脚本添加单元测试。
- 为 docker 文件添加单元测试。
后续步骤
在机器学习工作流已经在本地环境中测试为预期工作后,下一步是将这个工作流完全迁移到带有 亚马逊 SageMaker 笔记本实例 的 AWS 云。在下一个指南中,我将演示如何调整这个 Jupyter notebook 以在 SageMaker Notebook 实例上运行,以及如何将自定义 Docker 映像推送到【Amazon Elastic Container Registry(ECR),以便整个工作流完全在 AWS 中托管和管理。
清理
最佳做法始终是在最后清理过时的资源或会话,以回收计算、内存和存储资源,如果在云或分布式环境中清理,还可以节省成本。对于这个场景,本地 SageMaker 推理端点以及 SageMaker 容器被删除,如下所示。
**tf_local_predictor.delete_endpoint()**

删除 SageMaker 推理端点并停止 TensorFlow 服务容器
**docker container ls -a**

SageMaker 培训和服务容器均处于退出状态
**docker rm $(docker ps -a -q)
docker container ls -a**

所有容器都被移除****
使用 Kubeflow Pipelines SDK 和 Argo 工作流在 Kubernetes 上构建您的数据管道
运行 K8 本地数据管道
良好数据管道的重要性

在构建你的机器学习管道的元素上花了多少精力?参考“机器学习系统中隐藏的技术债务”——斯卡利等人。
对于那些没有看过上图的人,我强烈推荐阅读论文“机器学习系统中隐藏的技术债务”。它涵盖了构建机器学习系统的最佳实践。本文中有一节是关于 ML 系统反模式和管道丛林的:
管道丛林。作为胶水代码的特例,管道丛林经常出现在数据准备中。随着新信号的识别和新信息源的增加,这些可以有机地发展。如果不小心的话,以 ML 友好格式准备数据的结果系统可能会变成一个由抓取、连接和采样步骤组成的丛林,通常还会有中间文件输出。管理这些管道、检测错误和从故障中恢复都是困难和昂贵的。
如何避开管道丛林
使用工作流引擎。
有许多工作流引擎可以帮助管道编排和构建 ETL。我不会深入讨论每个框架的利弊,因为那将需要一个完全不同的博客帖子,实际上,我不认为有一个明确的赢家。
这篇博文的目的是向你展示如何使用 Kubeflow Pipelines SDK 来运行 Argo 工作流。

为什么选择 Argo 工作流?
简单的答案是,它是云原生的,这意味着如果您已经有一个 Kubernetes 集群在运行, Argo 被实现为 Kubernetes CRD 并允许您在集群上原生运行管道。有了 Argo,每个任务都在一个 pod 中执行,你可以像一个 DAG 一样轻松地执行多个任务。它包含许多重要的特性,如在任务间传递工件、参数化、调度和更多。
如何运行 Argo 工作流?
运行 Argo 工作流的方法是使用 YAML 配置文件。
下面是一个运行简单的“hello world”任务的示例,该任务运行 python docker 图像并打印“hello world”。
apiVersion: argoproj.io/v1alpha1
kind: Workflow # new type of k8s spec
metadata:
generateName: hello-world- # name of the workflow spec
namespace: default
spec:
entrypoint: hello-world-template # invoke the template
templates:
- name: hello-world-template # name of the template
container:
image: python:latest
command: ["python","-c"]
args: ["print('hello world')"]
Argo 工作流引擎的用户界面具有以下功能:
- 监控和运行 Argo 工作流
- 查看容器日志、环境变量、任务参数和输出
- 查看和运行 cron 工作流

Argo 工作流用户界面
那么我们为什么需要 Kubeflow Pipelines SDK 呢?
YAML 有它的局限性,特别是当你想运行有许多任务的管道和进行快速迭代的时候。出于这个原因,目前正在构建各种 Argo SDKs,这些 SDK 将使您能够以编程方式在 Python 中定义 Argo 工作流,并将您的代码转换为 Argo YAML 规范。
最成熟的 SDK 之一是在 Kubeflow 项目下构建的。Kubeflow 是一个开放的、社区驱动的项目,使得在 Kubernetes 上部署和管理 ML 栈变得容易。包括谷歌、思科、IBM、微软、红帽、亚马逊网络服务和阿里巴巴在内的公司都在生产中使用它。它有一个松散耦合的微服务架构。
其中一个服务是 Kubeflow Pipelines (KFP),这是一个基于 Docker 容器构建和部署可移植、可扩展的机器学习(ML)工作流的平台。它有一个用户界面,用于管理和跟踪实验、作业和运行。
阿尔戈工作流和 KFP 之间有细微的区别。Argo 是 KFP 背后的工作流引擎,而 KFP 主要用于与 ML 相关的应用。
与 Argo 不同,ML 相关的用法一直是 Kubeflow 管道的唯一焦点;它不是针对其他数据处理任务的。
ML 相关用法在哪里开始和结束?我发现 Argo 对于像数据摄取和一般数据处理管道这样的任务来说更自然,这些任务并不意味着以运行 ML 实验来结束。
由于 Argo 是 KFP 背后的工作流引擎,我们可以使用 KFP python SDK 来定义 python 中的 Argo 工作流。 KFP SDK 提供了一组 Python 包,您可以使用它们来指定和运行您的工作流。这些管道将按照阿尔戈 YAML 规范进行编译。只需用pip install kfp安装包即可使用。
工作流程示例
在下面的例子中,我将向您展示如何用 KFP python SDK 编写一个简单的管道。管道将接收一个参数,运行 for-each 循环,并在任务之间传输数据(大多数数据处理管道的一般构造块)。它是使用 KFP python SDK 编写的,将被编译成阿尔戈 YAML 配置。
import kfp@kfp.components.func_to_container_op
def print_func(param: int):
print(str(param))@kfp.components.func_to_container_op
def list_func(param: int) -> list:
return list(range(param))@kfp.dsl.pipeline(name='pipeline')
def pipeline(param: int):
list_func_op = list_func(param)
with kfp.dsl.ParallelFor(list_func_op.output) as param:
print_func(param)if __name__ == '__main__':
workflow_dict = kfp.compiler.Compiler()._create_workflow(pipeline)
workflow_dict['metadata']['namespace'] = "default"
del workflow_dict['spec']['serviceAccountName']
kfp.compiler.Compiler._write_workflow(workflow_dict, 'pipe.yaml')
让我们解释一下脚本的不同部分
@kfp.components.func_to_container_op
def print_func(param: int):
print(str(param))@kfp.components.func_to_container_op
def list_func(param: int) -> list:
return list(range(param))
用@func_to_container_op decorator 包装 python 函数(任务)会将函数转换成任务组件并返回一个任务(ContainerOp)工厂。该任务将在 Docker 容器内部运行(默认图像是tensor flow/tensor flow:1 . 13 . 2-py3)。也可以改变基本图像。
@kfp.dsl.pipeline(name='pipeline')
def pipeline(param: int):
list_func_op = list_func(param)
with kfp.dsl.ParallelFor(list_func_op.output) as param:
print_func(param)
用一个@dsl.pipeline装饰器包装你的函数会将函数转换成一个管道组件,它描述了任务组件如何相互交互。任务之间有许多不同的交互方式(Dag、loops、conditions 等)。
在上面的例子中,管道接收一个参数,该参数将指定要运行的子任务的数量。*list_func_op* 是一个运行*list_func*的容器组件,对于*list_func* 返回的列表中的每一项,KFP 将启动另一个运行*print_func* 的容器,并将相关列表项作为参数。每个任务将在 Kubernetes pods 上并行运行。
眼尖的读者可能会问:“不同的任务之间是如何传输数据的?”。要做到这一点,你需要为 Argo(例如 S3 或 GCS)配置一个工件库 。您还可以使用kfp.dsl.ArtifactLocation.为每个管道配置不同的工件存储库。在我们的例子中,KFP 通过用 JSON 序列化程序包装我们的函数来保存和加载数据,JSON 序列化程序将数据保存到工件存储中。
最终线路将编译管道并输出阿尔戈 YAML。
workflow_dict = kfp.compiler.Compiler()._create_workflow(pipeline)# The following lines are needed to adapt kfp to argo yaml
workflow_dict['metadata']['namespace'] = "default"
del workflow_dict['spec']['serviceAccountName']# Save yaml output
kfp.compiler.Compiler._write_workflow(workflow_dict, 'pipe.yaml')
一旦你得到了 YAML,你就可以使用 Argo 命令行界面运行它:
argo submit --watch pipe.yaml -p param=**5**
最后,这是它在 Argo UI 中的样子:

您可以在以下要点中查看完整的管道脚本,包括工件配置:
如果你喜欢这篇文章,请随时在推特上关注我
使用 PyCaret 在 Power BI 中构建第一个异常检测器
在 Power BI 中实现异常检测的分步指南

Power BI 中的异常检测仪表板
在我们的上一篇文章中,使用 PyCaret 在 Power BI 中进行机器学习,我们展示了一个关于如何将 PyCaret 集成到 Power BI 中的分步教程,从而允许分析师和数据科学家在没有任何额外许可成本的情况下,将机器学习层添加到他们的仪表板和报告中。
在这篇文章中,我们将深入探讨并使用 PyCaret 在 Power BI 中实现一个异常检测器。如果你以前没有听说过 PyCaret,请阅读这个公告以了解更多信息。
本教程的学习目标
- 什么是异常检测?异常检测的类型?
- 在 Power BI 中训练和实现一个无监督的异常检测器。
- 在仪表板中分析结果和可视化信息。
- 如何在电力 BI 生产中部署异常检测器?
开始之前
如果您以前使用过 Python,很可能您的计算机上已经安装了 Anaconda 发行版。如果没有,点击这里下载 Python 3.7 或更高版本的 Anaconda 发行版。

https://www.anaconda.com/products/individual
设置环境
在我们开始在 Power BI 中使用 PyCaret 的机器学习功能之前,我们必须创建一个虚拟环境并安装 pycaret。这是一个三步走的过程:
✅ 步骤 1——创建一个 anaconda 环境
从开始菜单打开 Anaconda 提示符并执行以下代码:
conda create --name **myenv** python=3.7
✅ 第二步—安装 PyCaret
在 Anaconda 提示符下执行以下代码:
pip install pycaret
安装可能需要 15-20 分钟。如果您在安装时遇到问题,请查看我们的 GitHub 页面,了解已知问题和解决方案。
✅t24】第三步——在 Power BI 中设置 Python 目录
创建的虚拟环境必须与 Power BI 链接。这可以使用 Power BI Desktop 中的全局设置来完成(文件→选项→全局→ Python 脚本)。默认情况下,Anaconda 环境安装在以下位置:
C:\Users\ 用户名\ AppData \ Local \ Continuum \ anaconda 3 \ envs \ myenv

文件→选项→全局→ Python 脚本
什么是异常检测?
异常检测是机器学习中的一种技术,用于识别罕见项目、事件或观察值,这些观察值通过与大多数数据显著不同而引起怀疑。
通常,异常项目会转化为某种问题,如银行欺诈、结构缺陷、医疗问题或错误。有三种方法可以实现异常检测器:
(a)受监督:当数据集具有标识哪些交易是异常的,哪些是正常的标签时使用。(这类似于监督分类问题)。
(b)半监督:半监督异常检测背后的思想是仅在正常数据上训练模型(没有任何异常)。当训练好的模型随后用于看不见的数据点时,它可以预测新的数据点是否正常(基于训练好的模型中数据的分布)。
(c)无监督:顾名思义,无监督意味着没有标签,因此没有训练和测试数据集。在无监督学习中,在完整的数据集上训练模型,并假设大多数实例是正常的。同时寻找似乎最不适合其余部分的实例。有几种无监督的异常检测算法,如隔离森林或单类支持向量机。每种方法都有自己识别数据集中异常的方法。
本教程是关于在 Power BI 中使用名为 PyCaret 的 Python 库实现无监督异常检测的。对这些算法背后的具体细节和数学的讨论超出了本教程的范围。

Goldstein M,Uchida S (2016)多元数据的无监督异常检测算法的比较评估。巴勒斯坦解放组织
设置业务环境
许多公司向员工发放公司信用卡(也称为采购卡或 采购卡)以有效管理运营采购。通常情况下,员工可以通过电子方式提交报销申请。收集的数据通常是交易性的,可能包括交易日期、供应商名称、费用类型、商家和金额。
在本教程中,我们将使用美国特拉华州教育部 2014 年至 2019 年的州雇员信用卡交易。这些数据可以在他们的开放数据平台上在线获得。

https://data . Delaware . gov/Government-and-Finance/信用卡消费商户/8pzf-ge27
免责声明: 本教程演示了在 Power BI 中使用 PyCaret 构建一个异常检测器。在本教程中构建的示例仪表板并不反映实际的异常情况,也不是为了识别异常情况。
👉我们开始吧
现在,您已经设置了 Anaconda 环境,安装了 PyCaret,了解了异常检测的基础知识,并且有了本教程的业务上下文,让我们开始吧。
1.检索数据
第一步是将数据集导入 Power BI Desktop。您可以使用 web 连接器加载数据。(Power BI 桌面→获取数据→来自 Web)。

Power BI 桌面→获取数据→其他→ Web
链接到 csv 文件:https://raw . githubusercontent . com/py caret/py caret/master/datasets/Delaware _ anomaly . CSV
2.模特培训
为了在 Power BI 中训练异常检测器,我们必须在 Power Query Editor 中执行 Python 脚本(Power Query Editor→Transform→Run Python script)。将以下代码作为 Python 脚本运行:
from **pycaret.anomaly** import *
dataset = **get_outliers**(dataset, ignore_features=['DEPT_NAME', 'MERCHANT', 'TRANS_DT'])

超级查询编辑器(转换→运行 python 脚本)
我们忽略了数据集中的一些列,将它们传递到 ignore_features 参数下。可能有许多原因导致您不想使用某些列来训练机器学习算法。
PyCaret 允许您隐藏而不是删除数据集中不需要的列,因为您可能需要这些列用于以后的分析。例如,在这种情况下,我们不想使用事务日期来训练算法,因此我们在 ignore_features 下传递它。
PyCaret 中有超过 10 种现成的异常检测算法。

默认情况下,PyCaret 用 5%的分数训练一个 K 最近邻异常检测器(即表中总行数的 5%将被标记为异常值)。默认值可以很容易地更改:
- 要更改分数值,您可以使用 get_outliers( ) 函数中的 分数 参数。
- 要更改模型类型,请使用 get_outliers() 中的 模型 参数。
参见用于训练分数为 0.1 的隔离森林检测器的示例代码:
from **pycaret.anomaly** import *
dataset = **get_outliers**(dataset, model = 'iforest', fraction = 0.1, ignore_features=['DEPT_NAME', 'MERCHANT', 'TRANS_DT'])
输出:

异常检测结果(执行 Python 代码后)

最终输出(点击表格后)
两个新列附加到原始表。标签(1 =异常值,0 =内部值)和分数(具有高分数的数据点被归类为异常值)。应用查询以查看 Power BI 数据集中的结果。

Power BI Desktop 中的结果(应用查询后)
3.仪表盘
一旦您在 Power BI 中有了异常值标签,以下是如何在 dashboard 中可视化它的示例:

仪表板的摘要页面

仪表板的详细信息页面
你可以从我们的 GitHub 下载 PBIX 文件和数据集。
👉在生产中实施异常检测
上面展示的是在 Power BI 中实现异常检测的一种简单方法。然而,重要的是要注意,每当 Power BI 数据集被刷新时,上面所示的方法训练异常检测器。这可能是一个问题,原因有二:
- 当用新数据重新训练模型时,异常标签可能会改变(以前被标记为异常值的一些事务可能不再被认为是异常值)
- 你不想每天花几个小时的时间重新训练模型。
在 Power BI 中实现异常检测的另一种方法是将预先训练好的模型传递给 Power BI 进行标记,而不是在 Power BI 本身中训练模型。
事前培训模型
你可以使用任何集成开发环境(IDE)或笔记本来训练机器学习模型。在此示例中,我们使用 Visual Studio 代码来训练异常检测模型。

Visual Studio 代码中的模型定型
然后将训练好的模型保存为 pickle 文件,并导入到 Power Query 中以生成异常标签(1 或 0)。

异常检测管道保存为文件
如果您想了解有关使用 PyCaret 在 Jupyter 笔记本中实施异常检测的更多信息,请观看这个 2 分钟的视频教程:
https://www.youtube.com/channel/UCxA1YTYJ9BEeo50lxyI_B3g
使用预先训练的模型
以 Python 脚本的形式执行以下代码,从预训练的模型中生成标签。
from **pycaret.anomaly** import *
dataset = **predict_model**('c:/.../anomaly_deployment_13052020, data = dataset)

超级查询编辑器(转换→运行 python 脚本)
它的输出将和我们上面看到的一样。但是,不同之处在于,当您使用预训练模型时,标签是在使用相同模型的新数据集上生成的,而不是在每次刷新 Power BI 数据集时重新训练模型。

最终输出(点击表格后)
使其在 Power BI 服务上工作
一旦你上传了。pbix 文件到 Power BI 服务,还需要几个步骤来实现机器学习管道到数据管道的无缝集成。其中包括:
- 为数据集启用计划刷新—要使用 Python 脚本为包含您的数据集的工作簿启用计划刷新,请参见配置计划刷新,其中还包括关于个人网关的信息。
- 安装个人网关 —你需要一个个人网关安装在文件所在的机器上,并且安装了 PythonPower BI 服务必须能够访问 Python 环境。您可以获得关于如何安装和配置个人网关的更多信息。
如果您有兴趣了解有关异常检测的更多信息,请查看我们的笔记本教程。
PyCaret 1.0.1 来了!
我们收到了来自社区的大力支持和反馈。我们正在积极改进 PyCaret,并准备我们的下一个版本。 PyCaret 1.0.1 会更大更好。如果您想分享您的反馈并帮助我们进一步改进,您可以在网站上填写此表格或者在我们的 GitHub 或 LinkedIn 页面上发表评论。
关注我们的 LinkedIn 并订阅我们的 Youtube 频道,了解更多关于 PyCaret 的信息。
重要链接
用户指南/文档
GitHub 资源库 安装 PyCaret
笔记本教程
贡献于 PyCaret
想了解某个特定模块?
从第一个版本 1.0.0 开始,PyCaret 有以下模块可供使用。点击下面的链接,查看 Python 中的文档和工作示例。
另请参见:
笔记本中的 PyCaret 入门教程:
你愿意投稿吗?
PyCaret 是一个开源项目。欢迎每个人都来投稿。如果您愿意投稿,请随意处理未决问题。dev-1.0.1 分支上的单元测试接受拉请求。
如果你喜欢 PyCaret,请给我们 GitHub 回购的⭐️。
中:https://medium.com/@moez_62905/
领英:【https://www.linkedin.com/in/profile-moez/
推特:【https://twitter.com/moezpycaretorg1
建立你的第一个 CNN
一种构建卷积神经网络的更好方法

定义
卷积神经网络(CNN)是一种深度神经网络,在图像识别和分类中是有效的。它们接受图像作为输入,通过内核从中提取特征,并预测所需的输出。在 CNN 中,数据的预处理是最少的,并且它们可以自学识别来自不同图像的重要特征。对象检测、对象识别、面部识别、自动驾驶等领域的几乎所有先进网络。以某种方式利用 CNN。
介绍
网上有很多关于从头开始构建 CNN 的教程。尽管它们中的大多数确实提供了高精度,但是它们忽略了内存和参数的大量使用。当谈到在行业中部署模型时,构建网络不仅要达到目标精度,还要优化内存消耗。在本文中,我们将学习如何为物体识别构建一个优化的 CNN。
为了保持正确的期望值,让我们设定一个目标:
目标:上的MNIST 数据集
1。达到 99.4 %的验证准确率
2。模型的总参数数应小于 15k
3。最大历元数= 20
为了实现这个目标,我们将把我们的行动计划分成 4 个迭代。首先,我们将重点构建一个达到目标精度的模型。然后,我们将大幅降低参数,同时保持架构。这种参数的减少会导致精度的下降。为了弥补这一下降,我们将优化模型以满足我们的目标。
为了确保我们的模型在每次迭代中都是一致的,让我们添加一个条件,将每次迭代之间的修改限制为三次。
在我们开始设计网络之前,有几个术语我们应该熟悉——
核心
核是随机分配的权重矩阵,其在图像上被遍历和卷积。一个内核从图像中提取单个特征。
频道
卷积层的输出可以视为一组通道。
例如,1 个灰度图像(NxN) →与 64 个核的卷积(3x3) → 64 个通道((N-2)x(N-2))
感受野
感受野是感觉周围的一个区域,在这个区域内刺激可以影响感觉细胞的电活动。在 CNN 中,这是由通道/内核的单个细胞感知的图像部分。
CNN 的模型结构是通过将焦点保持在感受野上来设计的。通常,网络末端的模型的感受野与对象的大小相似。
卷积块
包含多个卷积层(3x3)的块。在每个后续层中,通常增加内核/文件的数量,以确保从图像中提取所有重要特征。
每个卷积层都有一个激活函数(最好是 ReLU,因为它对参数要求很低,这使得反向传播很容易校正权重),它给网络增加了非线性。
过渡块
该块具有逐点(1x1) 卷积以减少通道数量,以及最大池层以减少空间维度或通道大小。这个块的关键作用是过滤掉不相关的特征,限制参数的数量。
现在让我们开始设计网络
目标 1:普通网络
布局架构时首先要考虑的是感受域。在模型的末尾,感受野应该等于物体的大小。完整的架构是围绕这个概念设计的。添加成对的卷积块和过渡块以获得所需的感受野。
注意:过渡块有一个池层,这会导致信息丢失。在网络的末端,信道的大小很小,信息很重要。因此,避免了朝向网络末端的过渡块。
在最后一个卷积块之后,我们使输出变平,并使用 softmax 激活来提供类似概率的分布。
在这个特定的问题中,第一个过渡块在网络中添加得更快,因为背景主要是白色的,不包含太多信息,并且大部分信息位于中心。所以在网络早期使用第一个 maxPool 比较方便。
参数个数:1595316
最佳精度:99.93%(train) Colab 笔记本
目标 2:减少参数
我们的目标是在少于 15k 的参数中实现 99.40%的精度。在本节中,主要重点是减少每个卷积中内核/文件的数量,以便总参数小于 15k,而不会对精度造成太大影响(这将在后面的步骤中通过优化技术来恢复)。
对以前型号的更新:
1。减少 3×3 卷积层中的滤镜
2。减少 1x1 卷积层中的滤波器
即使大幅减少所有层中的参数,总参数仍然超过 15k。
3。恰好在第一过渡块和输出层的中间添加部分过渡块。该部分过渡块将仅包括 1x1 卷积,但不包括最大池。
第三步确保只有重要的功能在网络中继续进行,并避免因最大池而可能发生的信息丢失。
参数个数:12490
最佳精度:99.71%(train) Colab 笔记本
目标 3:优化
由于我们已经丢弃了一大块参数,我们需要采用一些优化技术来确保我们的模型不会损害准确性。
对以前型号的更新:
1。添加批量规范化图层。
这有助于标准化数据,并限制网络稍后的规模变化。这固定了层输入的均值和方差,有助于更快的收敛和改进梯度流。
2。选择合适的学习速率
选择最适合网络的 LR(基于实验)
3 .一个验证检查点
精度与历元图并没有严格递增。精度不断波动,因此不能依赖最后一个历元来给出最佳结果。因此,添加了一个验证检查点,用于在每个时期后计算验证数据的准确性。
参数个数:12874
最佳精度:99.28% (val),99.74%(train) Colab 笔记本
目标 4:过度拟合和进一步优化
请注意,训练和验证准确性之间的差距随着随后的时代而扩大。这说明模型过拟合。为了解决这个问题,我们将在每个 3x3 卷积后添加一个丢弃层。
对以前型号的更新:
1。Add Dropout
Dropout 随机跳过一些连接,强制网络学习其他参数。
2。增加一个 LR 调度器
一旦精度饱和,就需要降低学习率,这样模型才能收敛到更优的最小值,最终导致精度提高。
3。增加批量
大批量有助于更快地训练模型。
注意:批量不能过大。这可能导致损失函数陷入次优局部最小值。
参数个数:12874
最佳精度:99.36% (train),99.41% (val),第 19 历元 Colab 笔记本
超出我们的目标
我们已经实现了我们的目标。现在,让我们通过进一步减少每层中的内核数量,在不影响精度的情况下,尝试将我们的模型参数减少到 8k 以下。
参数个数:7602
最佳精度:98.93% (train),99.44% (val),第 22 历元 Colab 笔记本
进一步地
- 在稍微硬一点的数据集上实施这种方法,例如 CIFAR10、CIFAR100
- 使用图像增强:最有效的方法之一规范你的网络
- 添加跳过连接:这有助于模型拓宽其感受野范围,学习不同大小的对象。
- 使用循环 LR 加快收敛速度
参考资料:
- MNIST:勒村、扬恩;科琳娜·科尔特斯;克里斯托弗 J.C 伯吉斯。“MNIST 手写数字数据库,Yann LeCun,Corinna Cortes 和 Chris Burges”。检索于 2013 年 8 月 17 日
- 斯利瓦斯塔瓦,尼蒂什&辛顿,杰弗里&克里热夫斯基,亚历克斯&苏茨基弗,伊利亚&萨拉胡季诺夫,鲁斯兰。(2014).退出:防止神经网络过度拟合的简单方法。机器学习研究杂志。15.1929–1958.
在 GCP 建立你的第一个数据仓库
构建数据仓库的步骤是什么?你应该使用什么云技术?如何利用气流来协调你的管道?

这个项目的架构
作为一名数据专业人员,气流已经成为我的工具集的重要组成部分。在我之前的帖子之后,很多人联系我,询问如何开始学习气流。和许多其他事情一样,我相信开始学习一件事情的最好方法是通过实践。
在这个项目中,我们将在谷歌云平台上建立一个数据仓库,帮助回答常见的业务问题,并为仪表盘提供动力。您将直接体验如何构建 DAG 来实现常见的数据工程任务:从数据源提取数据,加载到数据接收器,转换数据并为业务消费建模。
如果你不知道什么是气流或者需要帮助来设置它,看看我以前的帖子。
气流已经存在了一段时间,但最近它获得了很大的牵引力。那么什么是气流呢?你如何使用…
towardsdatascience.com](/getting-started-with-airflow-locally-and-remotely-d068df7fcb4)
为什么选择谷歌云平台?
简短的回答是 BigQuery。虽然市场上有许多数据仓库解决方案,或者作为云提供商的解决方案,或者作为内部部署,但我对 BigQuery 的体验是最愉快的。
费用
首先,定价模式简单明了,无论规模大小都可以承受。您不需要为一个永不停机的实例(向您眨眼、红移)付费,而是每月每 TB 存储花费 20 美元,每次查询时每 TB 扫描花费 5 美元。
假设您的数据集大小为 200GB,这对于结构化数据集来说相当大。你每月只需支付 2 美元的仓储费。就查询成本而言,您也不会花费太多,因为 BigQuery 是一个列数据库,这意味着每次查询时,引擎不会扫描整个表,而是只扫描您选择的列,这取决于您构建数据仓库的方式,这是一个显著的成本节约。粗略估计,您一个月将扫描所有数据大约 50 次,这相当于扫描 10TB,花费您 50 美元。
因此,对于一个规模合理的结构化数据仓库,每月只需 52 美元,相比之下,最便宜的始终在线红移实例每月需要 146 美元。如果最低层的红移不能满足您的需求,那么无论您是否大量使用您的数据仓库,您每月都要支付大约 2,774 美元。对我来说,BigQuery 的按需定价更可取。
易用性
这更多的是个人意见,而不是确凿的事实,但我认为 GCP 比 AWS 更方便用户。在 GCP,从浏览器中维护权限或查询数据等操作通常更加用户友好。此外,BigQuery 会自动进行许多优化,在后台为您加速查询。
商业目标
在着手进行任何数据仓库项目之前,您应该有一个明确定义的、您试图解决的业务问题。对于这个项目,我选择了美国政府提供的 I94 移民数据,以及几个补充数据集。
假设你是美国移民局的数据工程师。你的老板找到你,说目前分析移民模式的方法是手工的,耗时且容易出错。他希望您提出一个解决方案,使分析过程更加简单、快速和可扩展。
该数据仓库将帮助美国官员分析移民模式,以了解是什么因素驱使人们迁移。
数据集
您可以为这个项目选择任何免费的数据源,并遵循。你可以在 Kaggle 或者谷歌数据集搜索上找到很多有用的数据集。以下是这个项目中使用的数据集。
- I94 移民数据:该数据来自美国国家旅游和贸易办公室。
- I94 数据字典:字典伴随着 I94 移民数据
- 世界温度数据:该数据集来自 Kaggle 。
- 美国城市人口统计数据:该数据来自 OpenSoft。你可以在这里阅读更多信息。
- 机场代码表:这是一个简单的机场代码和相应城市的表格。这里来自这里来自。
数据建模
根据原始数据,我们的下一步是为数据仓库设计一个数据模型。数据模型应该与业务目标和您试图回答的问题紧密联系在一起。
我根据星型模式原理设计了以下模型,其中包含一个事实表和七个维度表。

我们数据仓库的数据模型
F_IMMIGRATION_DATA:包含入境信息,如到达日期、离开日期、签证类型、性别、原籍国等。D_TIME:包含日期列的维度D_PORT:包含端口标识和端口名称D_AIRPORT:包含州内的机场D_STATE:包含状态标识和状态名称D_COUNTRY:包含国家标识和国家名称D_WEATHER:包含一个州的平均天气D_CITY_DEMO:包含一个城市的人口统计信息
体系结构

这个项目的架构
我们将跳过从不同数据库中提取数据的步骤,并假设我们在 Google 云存储(GCS)中拥有这个项目的所有数据。
GCS 将作为存储所有原始文件的数据源。然后,数据将被加载到 BigQuery 上的临时表中。ETL 过程将从这些临时表中获取数据,并创建数据仓库表。
Airflow 实例部署在 Google 计算引擎上或本地,以协调我们管道的执行。
以下是使用这些技术的理由:
- 谷歌云存储:充当我们的数据源,纵向可扩展。
- Google Big Query:充当数据仓库、数据集市和 ETL 过程的数据库引擎。BigQuery 是一种无服务器的解决方案,可以高效地处理 Pb 级数据集。
- Apache Airflow:通过发出 CLI 命令将数据加载到 BigQuery 或 SQL 查询中以执行 ETL 过程,从而协调工作流。Airflow 本身不需要处理任何数据,因此允许我们的管道进行扩展。
建立基础设施
要运行这个项目,你应该有一个 GCP 帐户。您可以免费创建一个新的 Google 帐户,并获得 300 美元的点数。与免费学分和免费层,你应该通过这个项目,无需支付任何费用。你可以参考我以前的文章这里在谷歌计算引擎实例上设置气流,并在这里运行我的代码来轻松地为项目创建必要的云资源。
否则,您可以使用 GCP 用户界面创建 GCS bucket、BigQuery 数据集和 BigQuery 表。
- 创建一个关于 GCP 的项目
- 通过添加信用卡启用计费(您有价值 300 美元的免费点数)
- 导航到 IAM 并创建一个服务帐户
- 授予帐户项目所有者。这对于本项目来说很方便,但不建议用于生产系统。你应该把钥匙放在安全的地方。
您可以通过运行以下命令将数据复制到存储桶中:
gsutil cp -r gs://cloud-data-lake-gcp/ gs://{your_bucket_name}
查看我的 GitHub repo 了解更多信息。
数据管道

数据管道
随着所有的设计和设置的方式,我们可以开始与这个项目的实际管道。下面用的代码可以参考我的 GitHub repo。
该项目在谷歌云平台上创建了一个数据湖,主要侧重于建立一个数据仓库和数据…
github.com](https://github.com/tuanchris/cloud-data-lake)
一个DummyOperator start_pipeline 启动流水线,随后是四个加载操作。这些操作将数据从 GCS bucket 加载到 BigQuery 表中。immigration_data被加载为parquet文件,而其他的被格式化为csv。在装载到 BigQuery 后,有检查行的操作。
接下来,管道从 I94 数据字典加载三个主数据对象。然后创建F_IMMIGRATION_DATA表,并检查以确保没有重复。还创建了其他维度表,管道也完成了。
导入气流库
定义新 dag 的第一件事是从 Airflow 导入所需的库。我们应该从 Airflow 导入 DAG,以及您希望使用的任何操作符。您可以阅读 Airflow 文档,了解操作员的工作内容和使用方法。
不同的操作符可以有相同的参数,每次使用操作符时定义所有相同的参数是重复的。这就是为什么您应该定义一个默认的 set 参数,它将被传递给所有的任务。
定义 DAG
接下来要做的是定义一个 DAG。您应该给它一个唯一的名称、开始日期和 schedule_interval。您还可以将上面定义的默认参数传递到 DAG。
可以使用 Airflow 变量传入变量,而不是像我下面这样在 DAG 定义代码中定义。经验法则是,对于经常变化的变量,使用气流变量。否则,您可以不使用标准的 Python 变量。请记住,您不应该定义大量的气流变量;否则,您可能会使气流的元数据数据库过载。
从 GCS 定义加载任务
对于我们的四个数据集,我们将使用GoogleCloudStorageToBigQueryOperator将数据从 GCS 加载到 BigQuery。您可以阅读 Airflow 文档,了解更多关于如何将变量传递给操作符的信息。
在我们的例子中,我们加载 CSV 格式的尺寸文件和 parquet 格式的immigration数据。请注意,对于 CSV 文件,您应该提供一个模式来确保以预期的格式加载数据。对于 parquet 格式,您不需要这样做,因为 parquet 文件已经附带了一个模式。
定义数据检查
在我们将数据加载到 BigQuer 之后,我们应该检查我们之前的任务是否按预期运行。我们可以通过检查表中的行数来验证是否有行存在。根据您的业务需求,您可以在这里实现更复杂的数据质量检查。
创建事实和维度表
在临时数据集中加载并检查了临时数据后,我使用 BigQueryOperator 执行 SQL 查询来转换和加载事实表和 dim 表。
注意,我在查询中传递参数,而不是数据集和表。这使得在开发和生产环境之间切换变得更加容易。查看我在 GitHub repo 中的 SQL 查询,找出我在转换中使用了什么逻辑。
定义任务相关性
最后,我们必须定义任务依赖性,即哪些任务相互依赖。您可以使用>>或<<操作符来实现。您也可以使用列表对多个任务进行分组。
结果
在所有这些步骤之后,您将有一个数据仓库呈现给您的老板。

我们的数据仓库
让我们运行一下我们的数据仓库。让我们看看哪些州的移民人数最多。在我们的数据集中,佛罗里达的移民人数最多,其次是纽约和加利福尼亚。

谁要移民到美国,他们的性别是什么?

打扫
请记住关闭 Airflow 实例/删除未使用的资源,以避免不必要的费用。
摘要
在本文中,我使用 Airflow 作为编排器,完成了在 GCP 设计和部署数据仓库的许多步骤。如您所见,这是一个漫长而复杂的过程,因此我无法在一篇文章中涵盖所有内容。
我希望你能更好地理解数据工程师是做什么的,并能运用这些知识。
快乐学习!
在 DialogFlow 上构建您的第一个 ML 集成聊天机器人!

丹尼尔·科尔派在 Unsplash 上拍摄的照片
您在 Google 的 DialogFlow 上的第一个机器学习集成聊天机器人只需 4 个步骤!
任何机器学习模型都是无用的,除非你把它应用到现实生活中。在 Jupyter 笔记本上运行模型,吹嘘 99.99%的准确率,都于事无补。你需要把它做成一个端到端的应用程序,把它呈现给外界。聊天机器人是一种有趣又简单的方式。
构建聊天机器人从未如此简单。谷歌的 DialogFlow 是一个显而易见的选择,因为它非常简单,快速和免费!在继续之前,先自己试用一下这个应用程序这里!
流动
现在您已经尝试过了,接下来要构建完整的应用程序,我们将讨论以下步骤:
- 你的机器学习模型(这里是 Iris)
- 获取用户输入的对话流聊天机器人
- 部署在任何公共主机上的 Flask 应用程序,用于呈现请求和响应
- 聊天机器人对 flask api 进行的 webhook 调用,用于发送数据和获取结果
- 集成 DialogFlow 和 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨
我们将一个接一个地检查每个步骤。让我们先来看看我们的完整应用程序的架构会是什么样子:

建筑
发生了什么事?
因此,用户可以访问 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨 聊天机器人,我们将建立在 DialogFlow 上,稍后与 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨 集成。对话开始,聊天机器人提示用户输入数据,这些数据是花的尺寸(花瓣长度、花瓣宽度、萼片长度和萼片宽度)。一旦聊天机器人接收到最后一个输入,它将触发对 flask API 的 webhook 调用,该 API 将部署在公共主机上。这个 flask API 由我们的应用程序组成,它将检索 4 个数据点,并将其与我们的机器学习模型相匹配,然后将预测回复给聊天机器人。你可以在我的 Github 找到完整的代码。
现在让我们来看一下每一步!
构建组件
ML 模型
首先,让我们建立一个基本的最大似然模型,该模型采用虹膜尺寸并预测虹膜类型。这里没有火箭科学。只是一个非常基本的模型,它能以相当高的精度呈现结果。下面是快速实现这一点的基本代码。
#Load data
iris = load_iris()
X = iris.data
y = iris.target
#Train test split
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state = 42, test_size = 0.25)
#Define and fit to the model
clf = RandomForestClassifier(n_estimators=10)
clf.fit(X_train, y_train)
predicted = clf.predict(X_test)
print(accuracy_score(predicted, y_test))
print(clf.predict(X_test))
#Save the model as Pickle
import pickle
with open(r'rf.pkl','wb') as model_pkl:
pickle.dump(clf, model_pkl, protocol=2)
我们只需加载数据,并使其适合随机森林分类器。不需要清理数据,因为数据集已经非常小了。我不会为了避免复杂性而在这里进行任何优化,因为我们的主要目标不是模型的准确性,而是完整的应用程序。然后只需 pickle 这个模型,之后这个模型、‘RF . pkl’、就会被加载到我们的 flask 应用中。
对话流聊天机器人
现在让我们直接进入 DialogFlow 来制作我们的聊天机器人。您也可以使用其他 API 和框架来构建聊天机器人,但 Google 的 DialogFlow 是一个显而易见的选择,因为它简单、免费且构建速度极快!前往 DialogFlow ,用你的谷歌账户登录。然后点击“创建代理”来创建您的聊天机器人。

创建代理
接下来,我们需要创建一个向用户请求数据并进行 webhook 调用的意图。让我们首先编辑默认的欢迎意图,让它要求用户回答“是”或“否”。

现在,只要用户键入“Yes”,DialogFlow 就会调用另一个 intent,要求用户输入并将数据点存储在“Entities”中。这里我们处理简单的随机数,所以我们不需要创建自定义实体。DialogFlow 有默认的实体来处理这样的数据。因此,我们需要为这个意图创建一个“Yes-follow-Intent ”,因为该意图将在用户的肯定回复之后被调用。

点击“添加跟进意向”>“是”。如果您愿意,可以将此意图重命名为其他名称。我将把它重命名为“IrisData”。现在我们需要添加实体,这些实体将保存从用户那里收到的数据。我们将在这里为所有 4 个输入使用默认的 @sys.number 实体。为用户需要的 4 个数据点设置 4 个不同的参数——花瓣长度、花瓣宽度、萼片长度、萼片宽度。确保添加提示,并要求用户单独输入。

添加参数

添加提示
用一些输入来训练模型,以便它知道会发生什么。您现在可以在右侧面板测试聊天机器人,检查它是否相应地运行。
完成后,您需要通过“为此目的启用 webhook 调用”来启用履行。通过这样做,这个特定的意图将对我们部署在公共主机 Heroku 上的应用程序进行 webhook 调用。我们现在需要构建 flask 应用程序,并将其部署在 Heroku 上,然后将 URL 放在左侧的“Fulfillment”选项卡中。
Heroku 上的 Flask 应用程序
我们现在需要构建我们的 flask 应用程序,它从我们的 chatbot 获取 webhook 调用,检索数据,然后适应 ML 模型(rf.pkl ),并将履行文本和预测一起返回给 DialogFlow。下面是代码:
# Importing necessary libraries
import numpy as np
from flask import Flask, request, make_response
import json
import pickle
from flask_cors import cross_origin
# Declaring the flask app
app = Flask(__name__)
#Loading the model from pickle file
model = pickle.load(open('rf.pkl', 'rb'))
# geting and sending response to dialogflow
@app.route('/webhook', methods=['POST'])
@cross_origin()
def webhook():
req = request.get_json(silent=True, force=True)
res = processRequest(req)
res = json.dumps(res, indent=4)
r = make_response(res)
r.headers['Content-Type'] = 'application/json'
return r
一旦完成,我们需要处理来自 DialogFlow 的 JSON 格式的实现请求来检索数据。履行请求看起来像这样:

API 请求格式
所以我们需要进入' query result ' > > ' parameters ' > > ' number ',' number1 ',' number2 ',' number4 '。一旦检索到,我们将把这些数据点转储到一个数组中,并将其应用到我们的模型中,从而得到预测。
# processing the request from dialogflow
def processRequest(req):
result = req.get("queryResult")
#Fetching the data points
parameters = result.get("parameters")
Petal_length=parameters.get("number")
Petal_width = parameters.get("number1")
Sepal_length=parameters.get("number2")
Sepal_width=parameters.get("number3")
int_features = [Petal_length,Petal_width,Sepal_length,Sepal_width]
#Dumping the data into an array
final_features = [np.array(int_features)]
#Getting the intent which has fullfilment enabled
intent = result.get("intent").get('displayName')
#Fitting out model with the data points
if (intent=='IrisData'):
prediction = model.predict(final_features)
output = round(prediction[0], 2)
if(output==0):
flowr = 'Setosa'
if(output==1):
flowr = 'Versicolour'
if(output==2):
flowr = 'Virginica'
#Returning back the fullfilment text back to DialogFlow
fulfillmentText= "The Iris type seems to be.. {} !".format(flowr)
#log.write_log(sessionID, "Bot Says: "+fulfillmentText)
return {
"fulfillmentText": fulfillmentText
}
if __name__ == '__main__':
app.run()
一旦完成,我们只需要在公共主机上部署代码。我再次选择了 Heroku,它简单、免费、超级快捷!你只需要添加以下文件到你的新 Github 库:flask 应用程序,模型 pickle 文件,一个 Procfile(这是非常重要的,帮助 Heroku 定位 flask 应用程序),和一个需求文本文件,告诉 Heroku 要正确运行应用程序需要预装哪些库和版本。
只需在 Github 上创建一个存储库,然后访问 Heroku。创建一个“新应用”,并在那里“连接”你的 Github 库。一旦连接,只需点击部署按钮,你就大功告成了!

将 Github repo 连接到 Heroku 应用程序
Webhook 调用
现在进入最后一步。我们现在需要将部署的应用程序连接到我们的聊天机器人。只需输入部署您的应用程序的 URL,并在其中添加“/webhook”即可。记住上面的 flask 代码,应用程序被路由到“/webhook”。只需转到 DialogFlow 左侧面板的“履行”选项卡,启用“网页挂钩”并添加<your_app>/网页挂钩即可。</your_app>

在 DialogFlow 上启用 Webhook
我们完了。(不要忘记点击保存按钮!)您可以在右侧面板上通过发起聊天来测试 webhook 请求/响应是否工作正常。您应该得到带有预测的实现响应。
与电报集成
到了最后一步。这里没什么要做的,因为将 web 应用程序与 DialogFlow 集成非常容易。我们首先需要去电报那里生成一个虚拟机器人,并生成它的令牌。搜索“机器人父亲”并点击“新机器人”。它会问你机器人的名字。根据需要输入任何名称。然后它会提示您输入用户名。
在你完成之后,你的机器人的一个令牌和一个链接将会在这里生成。只需复制令牌并转到左边的 DialogFlow“集成”面板。在那里启用 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨,粘贴您刚刚生成的令牌,然后单击 start。就是这样!现在只需进入电报机器人链接,并尝试应用程序!
使用 Python 和 Newscatcher 构建您的第一条新闻数据管道
新闻捕手
Newscatcher python 包可以让你从 3000 多个主要的在线新闻网站自动收集最新的新闻数据。

当我写这篇文章时,许多人不得不在家工作,有些人在此期间有很多空闲时间。你可以利用这段时间建立你的投资组合,提高你的技能或者开始一个副业。
Newscatcher 包使得新闻文章数据的收集和标准化变得容易,而不需要任何外部依赖。它是在我们开发名为 Newscatcher API 的主要数据即服务产品时构建的。我们是开发者优先的团队,因此,我们尽可能开源,以便编码人员可以免费部分复制我们已经完成的工作。
使用我们的包的方法很简单,你传递网站 URL 作为输入,获取最新的文章作为输出。对于每篇文章,您都有一个 标题、完整的 URL、简短的描述、发表日期、作者 和一些更多的变量。
快速启动
你需要 Python 3.7 以上版本
通过 PyPI 安装软件包:
pip install newscatcher
从包中导入 新闻捕捉器 类:
from newscatcher import Newscatcher
例如,我们想看看nytimes.com的最后一篇文章是什么
你必须传递 URL 的基本形式——没有www.,既没有https://,也没有在 URL 末尾的/。
news_source = Newscatcher(‘nytimes.com’)last_news_list = news_source.news
news _ source . news是 feedparser 的列表。FeedParserDict 。 Feedparser 是一个规范 RSS 提要的 Python 包。在我的另一篇中型文章中,我更详细地解释了什么是 RSS 以及如何使用 feedparser 处理它:
[## 使用 Python 通过 RSS/Atom 提要收集新闻文章
或者如何停止依赖数据提供商
towardsdatascience.com](/collecting-news-articles-through-rss-atom-feeds-using-python-7d9a65b06f70)
需要知道的一件重要事情是每个 RSS/Atom 提要可能有自己的一组属性。尽管 feedparser 在结构化方面做得很好,但是不同的新闻发布者的文章属性可能会有所不同。
对于 nytimes.com 的,物品属性列表如下:
article = last_news_list[0]
article.keys()dict_keys(['title', 'title_detail', 'links', 'link', 'id', 'guidislink', 'summary', 'summary_detail', 'published', 'published_parsed', 'tags', 'media_content', 'media_credit', 'credit'])
在上面的代码中,我们获取名为 last_news_list 的列表中的第一篇文章,并检查它的键(每篇文章都是一个字典)。
当我们浏览主要属性时:
print(article.title)Coronavirus Live Updates: New York City Braces for a Deluge of Patients; Costs of Containment Growprint(article.summary)Soldiers in Spain found nursing home patients abandoned. Officials warned that New York was experiencing a virus “attack rate” of five times that elsewhere in the United States. Washington edged closer to a $2 trillion relief package.print(article.link)[https://www.nytimes.com/2020/03/24/world/coronavirus-updates-maps.html](https://www.nytimes.com/2020/03/24/world/coronavirus-updates-maps.html)print(article.published)Tue, 24 Mar 2020 10:35:54 +0000
最有可能的是,你会在所有新闻出版商的文章数据中找到上述所有属性。
目前,最大的新闻出版商都在 Newscatcher 上。因此,你可以建立一个端到端的数据项目。此外,您还可以做许多不同的事情,例如:
- 收集新闻文章并将其保存到某种数据库的管道(带重复数据删除)
- +添加一个 NLP 层(例如,命名实体识别)
- +跟踪某个特定的主题
- +刮一篇文章的全文
- +可视化汇总数据
我建议在使用 newscatcher 包时使用以下包/技术:
- Elasticsearch 存储和查询数据
- Newscaper3k python 包自动抓取文章全文
- NLP 的空间
给那些想提高投资组合的人一个小提示。能够向招聘人员展示你有能力做一个端到端的项目会让你的简历脱颖而出。然而,你的工作的商业价值也很重要。因此,试着做一些服务于任何真实案例商业价值的东西。祝你好运。
阅读媒介上 Artem 的作品。固执己见的数据专家。newscatcherapi.com 和 politwire.com 的联合创始人…
medium.com](https://medium.com/@kotartemiy)
如果你想支持我们的团队,你可以通过注册 Newscatcher API 的封闭测试版来帮助我们。我们的 API 允许你搜索过去发布的最相关的新闻。
构建您的第一个随机森林分类器
预测病人的心脏病

图片由来自 Pixabay 的 Gordon Johnson 提供
在本文中,我将指导您使用 scikit-learn 库中的随机森林构建一个简单的分类器。
我们将从从 Kaggle 下载数据集开始,之后,我们将做一些基本的数据清洗,最后,我们将拟合模型并评估它。同时,我们还将创建一个用于评估的基线模型。
这篇文章适合希望了解机器学习项目的基本工作流程并构建他们的第一个分类器的初级数据科学家。
下载并加载数据集
我们将使用这个链接从 Kaggle 下载心脏病数据集。
该数据集包括近 300 名患有或未患有心脏疾病的患者。这就是我们将要预测的。
为此,我们将使用十三种不同的功能:
- 年龄
- 性
- 胸痛类型(4 个值)
- 静息血压
- 血清胆固醇(毫克/分升)
- 空腹血糖> 120 毫克/分升
- 静息心电图结果(值 0,1,2)
- 达到最大心率
- 运动诱发的心绞痛
- oldpeak =运动相对于休息诱发的 ST 段压低
- 运动 ST 段峰值的斜率
- 荧光透视着色的主要血管数量(0-3)
- thal: 3 =正常;6 =修复缺陷;7 =可逆缺陷
现在花点时间熟悉一下这些描述,这样您就能理解每一列代表什么。
下载完数据集并将其放入 Jupyter 笔记本文件所在的文件夹后,您可以使用以下命令加载数据集。
import pandas as pd
df = pd.read_csv('data.csv')
df.head()

这是您将使用的数据框的头部。
数据清理
你发现上面数据框中的问号了吗?看起来这个数据集的作者用它们来表示空值。让我们用真正的 Nones 来代替它们。
df.replace({'?': None}, inplace=True)
现在我们已经完成了,我们可以检查我们的数据集中有多少空值。我们可以用 info()函数来实现。
df.info()

我们可以看到第 10、11 和 12 列有很多空值。Ca’和‘thal’实际上几乎是空的,‘slope’只有 104 个条目。缺少的值太多,无法填写,所以让我们删除它们。
df.drop(columns=['slope', 'thal', 'ca'], inplace=True)
其余的列没有或很少缺少值。为了简单起见,我建议删除那些有它们的条目。我们不应该丢失太多数据。
df.dropna(inplace=True)
我们可以从 info()函数的结果中读取的另一个信息是,大多数列都是对象,即使它们看起来有数值。
我怀疑这是由初始数据集中的问号引起的。现在我们已经删除了它们,我们应该能够将对象更改为数值。
为了做到这一点,我们将对整个数据帧使用 pd.to_numeric()函数。对象值应该变成数字,它不应该影响已经编号的值。
df = df.apply(pd.to_numeric)
df.info()

如你所见,我们现在只剩下浮点数和整数。info()函数还确认删除了列'Ca ',' thal '和[T2 ',' slope '。
此外,具有空值的行被删除,因此,我们有一个包含 261 个数值变量的数据集。
在我们继续之前,我们还需要做一件事。我注意到最后一列‘num’的名称中有一些尾随空格(肉眼看不出来),所以让我们来看看列名列表。
df.columns

您应该在最后一列‘num’中看到尾随空格。让我们通过应用 strip()函数来移除它们。
df.columns = [column.strip() for column in df.columns]

搞定了。
探索性数据分析
我们来做一些基本的数据分析。我们将首先使用直方图来观察变量的分布。
import matplotlib.pyplot as plt
plt.figure(figsize=(10,10))
df.hist()
plt.tight_layout()

我们能立即注意到的是,有些变量不是连续的。实际上,只有五个特征是连续的:''年龄',' chol ',' oldpeak ',' thalach ',' trestbps' ,而其他的都是分类变量。
因为我们想在探索中区别对待他们,我们应该把他们分成两组。
continous_features = ['age', 'chol', 'oldpeak', 'thalach', 'trestbps'] non_continous_features = list(set(df.columns) - set(continous_features + ['num']))
完成后,您可以通过在 Jupyter 笔记本单元格中键入变量名来检查它们的值。
continous_features

non_continous_features

现在,我们将检查连续特征在目标变量中有何不同。我们将通过散点图来实现这一点。
import seaborn as sns
df.num = df.num.map({0: 'no', 1: 'yes'})
sns.pairplot(df[continous_features + ['num']], hue='num')

请注意,我们必须将‘num’*变量设为字符串,以便将其用作色调参数。我们是这样做的,将 0 映射为“否”,表示健康的患者,将 1 映射为“是”,表示患有心脏病的患者。
如果你看散点图和 kde,你会发现心脏病患者和健康患者相比有地区模式。
为了探究分类变量,我们将通过使用 describe()函数来查看它们可以取的不同值。
df[non_continous_features].applymap(str).describe()

我们可以看到' exang ',' fbs' 和 'sex' 是二进制的(它们只取两个不同的值)。而‘CP’和‘reste ceg’分别取四个和三个不同的值。
最后两个是数据集作者编码的有序分类变量。我不确定我们是否应该这样对待它们,或者将它们改为伪编码。这将需要进一步的调查,我们可以在未来改变方法。现在,我们将让它们保持有序。
最后但同样重要的是,我们将探索目标变量。
df.num.value_counts()

我们有 163 名健康患者和 98 名有心脏问题的患者。不是理想的平衡数据集,但对我们的目的来说应该没问题。
创建基线模型
在快速的探索性数据分析之后,我们准备好构建一个初始分类器。我们首先将数据集分为特征和目标变量。
X = df.drop(columns='num')
y = df.num.map({'no': 0, 'yes': 1})
*注意,我必须反转创建 seaborn 图时应用的映射,因此,在创建 y 变量时需要 map()函数。
我们还使用了数据集的所有功能,通过查看我们的快速 EDA,它们似乎都是相关的。
现在,我们将使用 train_test_split()函数将 X 和 y 变量进一步划分为它们的训练和测试对应变量。
from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1) X_train.shape, X_test.shape, y_train.shape, y_test.shape

作为上述操作的结果,我们现在应该有四个不同的变量:X_train,X_test,y_train,y_test,它们的尺寸打印在上面。
现在我们将使用 DummyClassifier 构建一个基线。
from sklearn.dummy import DummyClassifier
from sklearn.metrics import accuracy_score
dc = DummyClassifier(strategy='most_frequent')
dc.fit(X,y) dc_preds = dc.predict(X)
accuracy_score(y, dc_preds)

如你所见,基线分类器在训练集上给了我们 62%的准确率。我们基线的策略是预测最频繁的类。
看看能不能用随机森林打败它。
随机森林分类器
下面的代码设置了一个随机森林分类器,并使用交叉验证来查看它在不同折叠上的表现。
from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection
import cross_val_score rfc = RandomForestClassifier(n_estimators=100, random_state=1)
cross_val_score(rfc, X, y, cv=5)

如您所见,这些精度通常比我们的虚拟基线高得多。只有最后一次折叠的准确度较低。看起来这最后一个折叠有很难识别的例子。
然而,如果我们取这五个的平均值,我们会得到大约 74%的准确率,这远远高于 62%的基线。
通常,这是一个我们希望使用 GridSearchCV 等工具进一步调整模型参数的阶段,但这不是本教程的一部分。
现在让我们看看模型在测试集上的表现如何。如果你注意到了,我们到目前为止还没有对测试做任何事情。它一直被搁置到现在。
评估模型
我们将从准确性方面检查模型性能开始。
首先,我们将使用整个训练数据来拟合模型,然后我们将在测试部分上调用 accuracy_score()函数。
rfc.fit(X_train, y_train)
accuracy_score(rfc.predict(X_test), y_test)

我们的测试准确率达到了 75%。类似于我们在 74%的训练集上的平均交叉验证准确度计算。
让我们看看虚拟分类器在测试集上的表现如何。
accuracy_score(dc.predict(X_test), y_test)

基线分类器的准确度约为 51%。这实际上比我们的随机森林模型的准确性差得多。
然而,在评估分类器时,我们不应该只看准确性。让我们看看随机森林和基线模型的混淆矩阵。
我们将从使用 scikit-learn 函数计算随机森林的混淆矩阵开始。
from sklearn.metrics import plot_confusion_matrix
plot_confusion_matrix(rfc, X_test, y_test)

事实上,我们做得一点也不差。我们只有五个假阳性,还有八个假阴性。此外,我们预测 26 个有心脏问题的人中有 18 个会有心脏病。
不是很好,但也没那么糟。请注意,我们甚至没有调整模型!
让我们将这个混淆矩阵与为基线模型计算的混淆矩阵进行比较。
from sklearn.metrics import plot_confusion_matrix
plot_confusion_matrix(dc, X_test, y_test)

仔细看看上面的图表。你能看到我们总是预测标签 0 吗?这意味着我们预测所有患者都是健康的!
没错,我们已经设置了虚拟分类器来预测多数类。请注意,对于我们的目的来说,这将是一个可怕的模型,因为我们不会发现任何有心脏问题的患者。
兰登森林做得好多了!实际上,在测试的 26 人中,我们发现了 18 人有心脏问题。
总结
在这篇文章中,你已经学习了如何使用随机森林构建一个基本的分类器。
这是对在数据集上构建模型时使用的主要技术的概述,没有涉及太多的细节。
这是有意的,所以这篇文章不会太长,并且可以作为想要构建他们的第一个分类器的人的起点。
快乐学习!
最初发表于 about datablog . com:2020 年 8 月 13 日打造你的第一个随机森林分类器,。
PS:我正在 Medium 和aboutdatablog.com上写文章,深入浅出地解释基本的数据科学概念。你可以订阅我的 邮件列表 在我每次写新文章的时候得到通知。如果你还不是中等会员,你可以在这里加入。
下面还有一些你可能喜欢的帖子
* [## 作为一名有抱负的数据科学家,你应该关注的中型作家
我最喜欢的 10 个数据科学博主,让你的学习之旅更轻松。
towardsdatascience.com](/medium-writers-you-should-follow-as-an-aspiring-data-scientist-13d5a7e6c5dc) [## 熊猫概况和探索性数据分析的第一行代码!
了解如何为自动 EDA 安装和使用 pandas profiling
towardsdatascience.com](/pandas-profiling-and-exploratory-data-analysis-with-line-one-of-code-423111991e58) [## Jupyter 笔记本自动完成
数据科学家的最佳生产力工具,如果您还没有使用它,您应该使用它…
towardsdatascience.com](/jupyter-notebook-autocompletion-f291008c66c) [## 9 大 Jupyter 笔记本扩展
改进笔记本电脑功能,提高您的工作效率
towardsdatascience.com](/top-9-jupyter-notebook-extensions-7a5d30269bc8)*


浙公网安备 33010602011771号