TowardsDataScience-博客中文翻译-2016-2018-七-
TowardsDataScience 博客中文翻译 2016~2018(七)
原文:TowardsDataScience Blog
协议:CC BY-NC-SA 4.0
书评:摧毁数学的武器(凯西·奥尼尔)
原文:https://towardsdatascience.com/book-review-weapons-of-math-destruction-cathy-oneil-a6546cc6ee91?source=collection_archive---------3-----------------------
这篇文章标志着我第一次试图强迫自己更好地理解我读过的书。以前,我发现自己读了一本书又一本书,却无法回忆起以前学过的重要的东西。
老实说,这很令人沮丧。
所以我尝试用这种方式来推动自己理解这本书,并综合这本书传达的各种概念和想法。
免责声明:我的评论不会试图保持中立或无偏见——因为我觉得我试图写这样一篇博文的任何尝试都会导致枯燥乏味的结果。
我猜你可能会说,这可能是一个咆哮,而不是审查。
继续前进。
我在四月份的时候从亚马逊上买了这本书,它已经在书架上放了一段时间了,因为那时我正在看另一本书。大纲相当有趣,因为它从第一人称的角度强调了大数据实施的陷阱。我不会说我迷上了它的前提(因此我没有立即读它),但我很好奇作者在想什么。
作者凯茜·奥尼尔;她自己是一名数据科学家。这本书的封面上有一些对她的描述:
她获得了哈佛大学的数学博士学位,并在巴纳德学院任教,之后进入私营部门,为对冲基金 D. E. Shaw 工作。然后,她在多家初创公司担任数据科学家,建立预测人们购买和点击的模型。奥尼尔在哥伦比亚大学启动了数据新闻的 Lede 项目,并且是《做数据科学》的作者。她每周出现在 Slate 播客上
这本书一开始,作者讲述了她从学术界到 D.E .肖的经历,让读者充满了她对能够实践自己擅长的事情感到兴奋的故事。直到 2008 年的大金融危机,她才终于明白对冲基金,比如她工作的那家基金,是如何对破坏人们生活的结果负部分责任的。
她最终离开了公司,加入了一家为银行做风险评估的公司。毕竟,如果说监管不力是导致 2008 年崩盘的管理不善的罪魁祸首;那么评估未来交易的风险肯定会让世界变得更美好。
然而事情并没有变得那么好,因为她觉得这个行业只是在做一个橡皮图章生意。她在这些公司和其他公司的经历让她对大数据是如何被实施和滥用来优化盈利能力而无视伦理和道德问题的幻想破灭了。
本书的 2/3 讨论了在现实生活环境中部署的算法的各种例子,这些例子产生了意想不到的后果,影响了人们的生活,因为在开始时缺乏远见。
其中一个例子讲述了美国新闻创建的大学排名系统是如何开始军备竞赛的;在试图爬上排名系统的阶梯时,我们只是优化了算法所使用的确切特征(如学术引用)(嘿,现在…那不会让你想起家乡的事情吗..).然而,该系统未能在其算法中包括的是诸如学杂费等项目。这基本上给了私人实体提高学费的所有动机,并将其用于将使他们排名更高的事情上——所有这些虽然可能有助于为学生提供更好的学习环境,但也会在毕业时给他们带来沉重的债务负担。
作者称它们(模型)为数学毁灭武器(WMD)——就我所能回忆起的算法/模型而言:
- 拥有庞大的目标受众
- 不应用反馈循环来使用未来结果自我修正
- 使用各种代理来说明预测结果,这在某些情况下可能是歧视性的。
- 对观众来说是不透明的
这本书有这些大规模杀伤性武器的各种例子。以至于在我阅读的时候,我真的有跳过几章只看结论的冲动。但是咳咳沉没成本再次占了上风。虽然一段时间后它确实变干了,但它确实证明了没有第二项而用上面列表中的第三项填充的模型会遭受建模者或整个社会的偏见。更糟糕的是,它将如何再次强化社会的“世界观”。
因此,在为预测高利贷者的目标而创建的假设模型的情况下——低收入的人,大多数是黑人,住在某个街区;被一次又一次地掠夺,从而确保他们永远无法摆脱困境。他们现在是他们处境的受害者。
对我来说,这就是整本书的全部内容。证明这些大规模杀伤性武器的存在,并部署在我们日常生活中的各种机构。
那么,我们该如何处理这些大规模杀伤性武器呢?
- 对于在非商业环境中使用的模型,她建议在提出用于制作预测模型的特征时应更好地考虑。虽然删除它们可能会导致模型的准确性得分较低,但她认为,与社会中存在的偏见相比,较低的准确性得分更好地反映了模型的表现。
- 公众对模型的监督。
- 监管,如欧洲正在使用的监管,在公司可以将他们的数据用于其他目的之前,客户必须选择加入。
- 模型对公众的透明度。
我的看法
对大数据的伦理关注并不新鲜。但是通常道德规范被强调的角度(至少在我的经验中)更多的是关于透明度和保密性。我发现关于偏见和自我强化偏见的角度非常有趣,因为它确实对模型的受害者产生了更广泛和持续的影响。根据我以前的经验,修改你的模型总是为了确保你的模型不会过时——因为市场趋势会变化,你的模型必须根据这些变化进行调整。我想现在我有了更新模型的新动力。
我也想知道在这些情况下是否应该使用探索-利用策略(来自强化学习)。这意味着,我们应该让我们的模型产生一些错误,并观察结果是否会加强偏差。这将允许我们继续使用现有的(充满偏见的)特征,但如果结果显示不是这样,就要修正我们模型的假设。
本帖首发于我的个人博客,http://www . hafidzzulkifli . com/2017/07/book-review-weapons-of-math-destruction . html
书评:安德鲁·g·普萨尔蒂斯的《流式数据》
原文:https://towardsdatascience.com/bookreview-streaming-data-by-andrew-g-psaltis-79154c4cf724?source=collection_archive---------21-----------------------
流处理近年来,由于需要更快地处理(大)数据,系统在行业中不断受到关注和采用。为了实现这一点,对一系列数字信号,即所谓的数据流进行处理和分析,以产生(接近)实时的洞察。Andrew Psaltis 所著的《流数据》一书收集了设计和实现端到端系统的最佳实践。
Enns.join(Steyr)
这篇评论主要作为书中内容的个人参考。但我会很高兴,如果这本书对其他人也有用,也许会激励一个或另一个人购买和深入阅读这本书。它的结构是内容的总结,接着是我个人对这本书的看法,最后是一些关键的收获。
这本书的内容被分解成一个数据流系统的主要层。然后,通过一个动手的 pet 项目来完成,该项目的目标是构建一个系统,该系统可以实时分析 Meetup-RSVP。
集合层
这一章是关于常见的交互模式和容错。 Andrew Psaltis 深入描述了以下交互模式,并将其应用于各种用例:
- 请求/响应
- 发布/订阅
- 单向模式
- 请求/确认
- 流型
不出所料,重点特别放在了流模式上,它颠覆了客户端与服务交互的常规设置。在这里,服务成为客户机并连接到流源(而不是在其他模式中客户机向服务发出请求)。此外,这些不同类型的交互模式的扩展概念也在书中进行了阐述。
在通用的容错技术部分,介绍了消息记录的三种变体:基于接收者的、基于发送者的和混合。在第一种情况下,在对每条接收到的消息采取任何操作之前,它们都被保存在磁盘上。相反,基于发送方的消息日志记录在消息发送之前将其写入存储。混合消息日志旨在提供两种方法的最佳效果,但与两种技术都用于保护系统数据不丢失并使其可恢复的情况相比,它简化了数据流。基本上,这种方法所做的是一收到消息就将它记录在稳定的存储器上,类似于基于接收者的方法,但是是异步的。与基于发送方的消息记录器类似,只有当消息队列层的确认到达时,该日志才会被删除。Andrew Psaltis 认为,只要有可能,就应该实施这种方法,因为它保留了容错性和安全性,而没有设置两个单独的消息记录器的开销,每个记录器都有一个持久存储。
消息队列层
关于消息队列的章节首先介绍了三个主要组件:生产者、代理和消费者。它是技术不可知的,因此所解释的原理可以应用于该领域的各种产品(例如 RabbitMQ 、 ZeroMQ 或 Kafka )。
重要的是消息传递语义的引入(对于下面的分析层也是如此):
- 最多一次 —消息可能会丢失,但不会被处理超过一次
- 至少一次 —消息不会丢失,但可能会被处理多次
- 恰好一次 —消息不会丢失,并且只处理一次
安全也是本章的一个关注点,但不幸的是,如何实现它实际上只是作为进一步阅读的参考。容错也是一个大话题,在设计消息队列解决方案时,您应该回答一系列类似清单的问题。
分析层
关于这一层的内容实际上分为两个独立的章节。第一个引入分布式流处理架构和框架,将其转化为行动。第二个是关于流分析的算法。
现在所有分布式流处理系统都由三部分组成:
- 一个管理组件,它分发提交的应用程序
- 集群中执行算法的工作节点
- 数据源,作为算法工作的输入
讨论用于这一层的框架是 Spark Streaming 、 Storm 、 Flink 和 Samza 。消息交付语义、状态管理和容错,每一个都与分析层相关,是进一步的主题。
对于流数据的算法处理,时间是一个最重要的概念。需要区分事件时间(事件实际发生时)和流时间(事件数据进入系统时)。由于流本质上永远不会结束,它们不能保存在内存中进行分析,就像传统的批处理一样。为了克服这个问题,引入了窗口的概念(在其上执行计算的定义量的流数据)。有两种开窗技术:
- 滑动窗口 —由窗口长度和滑动间隔定义
- 滚动窗口带有基于计数的或基于时间的触发策略
由于摘要是分析的核心,所以最后介绍与流处理相关的各种技术。
内存中数据存储
本章是关于存储之前收集和处理的数据。长期存储选项只是浅尝辄止,详细介绍内存解决方案(嵌入式内存和缓存系统)。需要区分使用磁盘优先方法构建的系统(提供内存中选项的传统数据库)和内存优先设计的内存中数据库【IMDB】。选择哪种产品在很大程度上取决于具体的使用情况,但遵循后一种方法的产品通常最适合快速流解决方案。
数据访问层
构建最后一层是为了让客户端可以访问数据,主要是通过 API。有四种主要模式可以实现这一目的,本章将对此进行讨论:
- 数据同步
- 远程方法调用【RMI】/远程过程调用【RPC】
- 信息传递
- 发布/订阅
详细讨论了构建流式 API 的常用协议。分别是 Webhooks 、 HTTP 长轮询、服务器发送事件和 WebSockets 。它们还在通信方向和不同因素(如频率、延迟、效率或可靠性)方面进行比较。
最后,讨论了减少流式客户端感兴趣的事件数量的过滤类型。尽管大多数过滤方法都应参与分析层,但也有一些消费者特定的使用案例,其中数据访问层中的过滤是有意义的(例如基于地理位置的过滤器)。基本上,系统最后一层中的静态- (预定义决策)与动态过滤(运行时决策)的优缺点是相互比较的。
个人评论
总的来说,我真的很喜欢读这本书。它有高质量的结构良好的内容。复杂的概念以一种易于理解的方式被分解。就我个人而言,文本中有太多的图表,这有时会妨碍流畅的阅读,尤其是当图表是多余的时候(例如,具有基础层架构的图表在每章中被绘制多次)。我发现文中对书籍或文章的引用非常有用,而且组织得很好。经常出现的优点和缺点列表也非常有用。浏览一下比较表是快速了解各种方法或技术差异的一个很好的方式。
我唯一不太满意的部分是关于分析层的部分(这有点令人难过,因为我最初买这本书是为了了解这个主题)。核心概念描述得很好,但我期待更多的细节和至少一些关于流分析算法实际实现的内容。框架的比较很好,但是我遗漏了一些代码片段(例如,每个框架的简短 hello-world)。特别是因为分析层部分也只是松散地包含在最后一章的 pet 项目中。
由于我不是 Java 人士(Scala & Python FTW),我不是评判最终项目的合适人选。无论如何,这个项目的范围和领域是个不错的选择。它的核心代码逻辑很容易理解,对于那些不熟悉 Java 的人来说也是如此。
关键要点
- 对于当今的流数据系统,没有适合所有人的解决方案。每一种相关的技术都有优点和缺点。选择最适合您特定使用情形的产品。
- 这本书是一个很好的提醒,尽可能应用接吻原则。您添加的每个不必要的功能都是系统的潜在故障点。
- 对于流分析来说,的时间概念非常重要。
- 批处理模式下的简单分析任务(如计数)在流式系统中变得非常复杂。
- 持久层中的产品功能在不断改进,不同方法之间的界限正在变得模糊(远远超过 SQL 和 NoSQL 二分法)。
提升您的数据科学技能。学习线性代数。
原文:https://towardsdatascience.com/boost-your-data-sciences-skills-learn-linear-algebra-2c30fdd008cf?source=collection_archive---------5-----------------------
我想介绍一系列博客帖子和他们相应的 Python 笔记本,收集了伊恩·古德费勒、约舒阿·本吉奥和亚伦·库维尔(2016 年)关于深度学习书籍的笔记。这些笔记本的目的是帮助初学者/高级初学者掌握深度学习和机器学习背后的线性代数概念。获得这些技能可以提高您理解和应用各种数据科学算法的能力。在我看来,它是机器学习、深度学习和数据科学的基石之一。
这些笔记涵盖了线性代数的第二章。我喜欢这一章,因为它给人一种在机器学习和深度学习领域最常用的感觉。因此,对于任何想要深入学习并获得线性代数概念的人来说,这是一个很好的教学大纲,有助于更好地理解深度学习算法。
你可以在 Github 上找到所有的笔记本,在我的博客上可以找到这篇文章的一个版本。
线性代数入门
本系列的目标是为希望理解足够的线性代数以适应机器学习和深度学习的初学者提供内容。不过我觉得深度学习书中关于线性代数的章节对初学者来说有点难。所以我决定在这一章的每一部分制作代码、示例和绘图,以便添加对初学者来说可能不明显的步骤。我也认为你可以通过例子传达比一般定义更多的信息和知识。插图是看到一个想法的全貌的一种方式。最后,我认为编码是一个很好的工具来具体实验这些抽象的数学概念。除了纸和笔,它还增加了一层你可以尝试通过新的视野来推动你的理解的东西。
编码是具体实验抽象数学概念的伟大工具
图形表示对理解线性代数也很有帮助。我试图将概念与情节(以及产生情节的代码)结合起来。做这个系列时,我最喜欢的表现形式是,你可以把任何矩阵看作空间的线性变换。在几章中,我们将扩展这一思想,看看它如何有助于理解特征分解,奇异值分解(SVD)或主成分分析(PCA)。
Python/Numpy 的使用
另外,我注意到,创建和阅读实例对理解理论真的很有帮助。这就是我创建 Python 笔记本的原因。目标是双重的:
1.提供一个使用 Python/Numpy 应用线性代数概念的起点。由于最终目标是将线性代数概念用于数据科学,因此在理论和代码之间不断转换似乎是很自然的。您所需要的只是一个带有主要数学函数库的 Python 安装,比如 Numpy/Scipy/Matplotlib。
2.给出更具体的潜在概念。我发现玩和试验这些笔记本非常有用,可以帮助我理解一些复杂的理论概念或符号。我希望阅读它们会有所帮助。
摘要
教学大纲完全遵循深度学习书籍,所以如果你在阅读时不能理解某一点,你可以找到更多的细节。以下是内容的简短描述:
1.标量、向量、矩阵和张量
向量、矩阵、转置和基本运算的简单介绍(矩阵向量的加法)。还介绍了 Numpy 函数,最后介绍了广播。
2.矩阵和向量相乘
本章主要讲点积(向量和/或矩阵乘法)。我们还会看到它的一些性质。然后,我们将看到如何使用矩阵符号合成线性方程组。这是后面几章的主要过程。
3.单位矩阵和逆矩阵
我们将看到两个重要的矩阵:单位矩阵和逆矩阵。我们将看到为什么它们在线性代数中很重要,以及如何与 Numpy 一起使用。最后,我们将看到一个如何用逆矩阵求解线性方程组的例子。
4.线性相关性和跨度
本章我们将继续学习线性方程组。我们会看到,这样的系统不可能有一个以上的解,也不可能少于无穷多个解。我们将看到直觉,图形表示和这个陈述背后的证明。然后我们将回到系统的矩阵形式,并考虑吉尔伯特·斯特朗所说的行图形(我们看的是行,也就是说多个方程)和列图形(看的是列,也就是说系数的线性组合)。我们也会看到什么是线性组合。最后,我们将看到超定和欠定方程组的例子。
5.规范
向量的范数是一个函数,它接受一个向量作为输入,输出一个正值。它可以被认为是向量的长度。例如,它用于评估模型预测值和实际值之间的距离。我们会看到不同种类的规范(L⁰,l,L …)的例子。
6.特殊类型的矩阵和向量
我们已经在 2.3 中看到了一些非常有趣的特殊矩阵。在本章中,我们将看到其他类型的向量和矩阵。这不是一个很大的章节,但是理解接下来的章节是很重要的。
7.特征分解
在本章中,我们将会看到线性代数的一些主要概念。我们将从了解特征向量和特征值开始。我们将会看到,一个矩阵可以被看作是一个线性变换,将一个矩阵应用到它的特征向量上会产生具有相同方向的新向量。然后我们会看到如何将二次方程表示成矩阵形式。我们会看到,二次方程对应的矩阵的特征分解可以用来求其最小值和最大值。另外,我们还将看到如何在 Python 中可视化线性变换!
8.奇异值分解
我们将看到分解矩阵的另一种方法:奇异值分解或 SVD。从本系列开始,我就强调了这样一个事实:你可以把矩阵看成是空间中的线性变换。使用 SVD,您可以将一个矩阵分解成另外三个矩阵。我们会看到,我们可以把这些新矩阵看作空间的子变换。我们不是在一个动作中完成转换,而是将它分解为三个动作。另外,我们将把奇异值分解应用于图像处理。我们将看到奇异值分解对鹅露西图像的影响,所以请继续阅读!
9.摩尔-彭罗斯伪逆
我们看到不是所有的矩阵都有逆矩阵。这是不幸的,因为反演是用来解决方程组。在某些情况下,方程组无解,因此逆不存在。然而,找到一个几乎是解决方案的值(就最小化误差而言)可能是有用的。这个可以用伪逆来做!例如,我们将看到如何用伪逆找到一组数据点的最佳拟合线。
10.追踪操作员
我们将看到什么是矩阵的迹。主成分分析(PCA)的最后一章需要用到。
11.行列式
这一章是关于矩阵的行列式的。这个特殊的数字可以告诉我们很多关于我们矩阵的事情!
12.例子:主成分分析
这是线性代数系列的最后一章!是关于主成分分析(PCA)的。我们将使用在前几章中获得的一些知识来理解这个重要的数据分析工具!
要求
这个内容是针对初学者的,但对于至少有一些数学经验的人来说应该更容易。
享受
我希望你能在这个系列中找到一些有趣的东西。我尽量做到准确。如果发现错误/误解/错别字…请举报!你可以给我发电子邮件,或者在笔记本 Github 中打开问题和请求。
参考
印第安纳州古德费勒、纽约州本吉奥和库维尔(2016 年)。深度学习。麻省理工出版社。
通过 Amazon EC2、Keras 和 GPU 加速来促进您的机器学习
原文:https://towardsdatascience.com/boost-your-machine-learning-with-amazon-ec2-keras-and-gpu-acceleration-a43aed049a50?source=collection_archive---------2-----------------------
如何建立合适的深度学习环境
Photo by JJ Ying on Unsplash
为什么我不能在笔记本电脑上使用数据科学?
深度学习神经网络(具有不止一个隐藏层)需要一卡车的数据才能成为有效的预测引擎。这些模型需要强大的计算节点和大容量 RAM 存储,数据负载需要充足的存储和缓存能力。
鉴于像亚马逊网络服务(AWS) 这样的云解决方案所提供的价格和易用性,让您宝贵的笔记本电脑承受沉重的培训负担是没有意义的!
此外,当您的模型远程收敛时,释放您的本地计算机来浏览 Twitter 或观看数据科学教程!
本指南将帮助您:
- 在一个弹性云计算(EC2) 实例上,
- 那有支持 GPU 的 Keras ,
- 还有一个 Jupyter 笔记本。
我还发布了这篇关于 Keras 最佳实践的附带文章,供环境设置好并准备好训练模型时使用。
免责声明:某些情况下,比如我们在本帖中设置的情况,可能需要 24 小时才能得到 AWS 团队的批准。如果您马上需要一个工作实例,可以按需提供较低的性能选项。
设置 EC2
注:在整个介绍中,我将强调按钮点击 粗体 。另外,我在运行 High Sierra 的 Mac 上,所以你的bash命令在 Windows 或 Linux 机器上会有所不同。
首先,犒劳自己一个 AWS 账户。如果询问您付款方式,请不要担心;我们可以稍后配置免费或付费版本,AWS 有很好的预算工具来帮助您估计随时间推移的实例成本。
然后,在顶部菜单栏中导航到服务:计算:EC2 :
点击启动实例。是那个蓝色的大按钮!
然后,您将看到 AMI 浏览器窗口。点击左侧的社区 ami标签,搜索“Keras”:
此时,您将选择一个内置了 Keras、依赖项和支持模块的 AMI。你可以从头开始设置你的环境——如果你有非常特殊的需求,我会推荐你构建一个 Docker 容器——但是在 AMI 市场上有这么多选项,这是多此一举。
我用的是深度学习 AMI(Ubuntu)6.0 版 — ami-bc09d9c1。然而,对于未来的版本来说,事情可能是一样的。使用最新版本;截至 2018 年 5 月 16 日,这是 Ubuntu v9.0。
点击选择,你将被带到实例类型矩阵,这是一个你所拥有的所有硬件选项的分类。
Amazon 实例类型
您会注意到,免费层仅提供一个核心/节点/CPU 和 1GB 内存。可以用 t2.micro 实例来设置本教程的环境,但是不能构建严肃的模型。所以,为真实建模寻找更健壮的东西;点击弹出窗口中橙色的亚马逊 EC2 详情页面链接,了解每小时的价格。
您会注意到,将鼠标悬停在系列链接上,会显示该特定实例系列的设计用途。这里是计算优化:
与其他系列相比,计算优化实例的 vCPU 与内存的比率更高,并且在所有 Amazon EC2 实例类型中,每个 vCPU 的成本最低。对于运行 CPU 受限的横向扩展应用程序,我们建议使用计算优化实例。此类应用的示例包括高流量前端车队、按需批处理、分布式分析、web 服务器、批处理以及高性能科学和工程应用。
这听起来很棒,但是在这些实例上没有 GPU。因此,如果您想要 GPU 加速,请转向 g2 或 g3 系列:
GPU 图形实例为需要高性能图形加速的应用程序(如 3D 可视化、图形密集型远程工作站、3D 渲染、视频编码和虚拟现实)提供 GPU 以及高 CPU 性能、大内存和高网络速度。
或者更好的是,亚马逊为深度学习平台打造的 p 系列(GPU 计算)系列:
GPU 计算实例为需要大规模浮点处理能力的应用程序提供通用 GPU 以及高 CPU 性能、大内存和高网络速度,如机器学习、高性能数据库、计算流体动力学、计算金融、地震分析、分子建模、基因组学和渲染。
为了找到 p 类实例, filter by: GPU compute。
关于价格,请查阅 AWS 销售文件,例如 P2 实例的销售文件:
请注意以下几点:
- 价格是每小时 90₵。对于一个相当强大的设置来说还不错!
- 根据星号,某些实例类型仅在某些地区可用,或者因地区而定价不同。
- 您选择的实例必须满足您的所有标准,否则建模将会失败。
我如何为实际建模选择一个类型?RAM、存储和带宽之类的东西是黑白分明的。你要么可以存储/处理数据,要么不能。有了 CPU 和 GPU,你就可以决定是花更少的钱训练,还是花更慢的速度训练,还是花更快的速度训练。
有时候你因为太廉价而付出更多;模型每小时的花费会更少,但需要更多的时间来适应!
详细配置
在本教程中,我们将选择p2.xlarge
实例类型。点击 Next:配置实例细节。在第 3 步页面上,默认值是完美的,因此点击下一步:添加存储:
Can’t touch this!
请注意本页上的说明,根据说明,自由层用户最高可达 30GB。但是,如果您使用的是更高的层,比如我们下面的层,保持指定的值,否则您可能会增加潜在的额外存储成本。
点击下一步:两次以上,直到我们到达 6。配置安全组。在这里,我们打开端口与我们的远程 Jupyter 笔记本进行对话。使用添加规则在端口范围 8888: 上创建一个自定义 TCP 规则
请注意,我通常在 Source 下选择“我的 IP”。如果您选择“任何地方”——正如黄色注释所警告的——任何拥有您实例的公共 IP 的人都可以运行并修改您实例中的代码和文件。还要注意的是,如果你改变你的工作程序去咖啡馆,你的 IP 地址已经改变,你必须登录 AWS 并更新你的规则才能登录。
点击审查,然后点击启动:
我将下载一个名为 keras.pem 的新密钥,这个文件在我的 hidden 中。我的 Mac 上的 ssh 目录。如果您还没有以前实例中的密钥,请设置一个密钥。或者,如果您正在与其他人共享此实例,则创建一个新密钥!
如果您看到下面的屏幕,请转到提供的链接并提交申请表,这样亚马逊将允许您租用他们的服务!
Please let me rent your stuff!
其实更复杂。以下是我从 AWS 联系人那里收到的回复:
最终用户无法管理这些限制。根据具体情况对限额进行审查,以确保基础设施的安全性和可用性。
我目前正在处理您关于美国东部(北弗吉尼亚)地区 2 的 p2.xlarge Instances 限制增加请求。在这种特殊情况下,如上所述,我必须与我的服务团队合作以获得批准。请注意,服务团队可能需要 24 小时来处理此请求。
因此,亚马逊通过密切监控和管理整个基础设施的需求做得很好。否则,互联网可能会再次关闭!
或者,不同的位置/地区有不同的限制。通常情况下,您应该选择能够提供您所需要的东西的最近的地区,但是由于世界上任何地方的延迟都很低,我们可以通过选择供应更多的地区来解决限制。
好了,我们应该开始行动了!接下来,我们将从本地机器连接到我们的实例。
通过安全外壳(SSH)连接
SSH 允许我们通过 bash 远程命令和控制我们的实例。我将在我的 Mac 上启动终端:
现在,回到 AWS 站点,EC2 仪表板,找到正在运行的p2.xlarge
实例,并单击 Connect :
在 bash 中执行上述命令,您应该能够在。如果 SSH 要求您确认密钥指纹的真实性,您可能需要键入 yes,然后按 enter 键。
**chmod 400 keras.pem**
更改用户对密钥文件的权限,使任何人都无法读取或写入该文件。AWS 将对此进行检查,如果文件不安全,将拒绝进入!
What success looks like!
请注意,该图像的加载顺序为我们提供了关于如何加载特定环境组合的很好的提示。这些是 Conda envs ,它们加载各种 Python 版本并支持库。
你也可以更新最新最好的软件包,但是请记住你可能会破坏打包的设置,因为一些版本的库不能很好地一起运行。如果您想更新 Keras,您可以运行:
sudo pip install — upgrade keras
# are you sure you want to do this?
# things could break...
# FOMO?
# they don't make versions like they used to...
推出 Jupyter 笔记本
我将使用source activate tensorflow_p36
在 Python 3 的 TensorFlow 后端发布 Keras 2。请注意,Keras 是 TensorFlow 上的一个包装器,因此它可以用简单的 Python 代码快速轻松地完成复杂的设置。然后我们启动 Jupyter notebook,没有指定浏览器,因为我们不需要在远程端安装 Javascript 或其他程序:
jupyter notebook --no-browser --port=8888
记下分配给您的令牌;我们很快就需要它了!
然后,根据这个 AWS 指南,我们在终端(CMD+T)中打开一个新标签,SSH 进入我们的 Jupyter 隧道:
ssh -i ~/*keras.pem* -L 8157:127.0.0.1:8888 ubuntu@*ec2-###-##-##-###.compute-1.amazonaws.com*
第一个端口可以是你最喜欢的号码(我的是 8157)。这是第二个必须与 AWS 端打开的相匹配的。
在浏览器中导航至[**http://127.0.0.1:8157**](http://127.0.0.1:8157)
,您应该会看到:
在顶部键入令牌,并选择密码,这样您就不需要每次登录时都复制令牌!你应该做好准备:
我希望这有所帮助!如果您遇到任何独特的问题,请告诉我,因为平台在不断变化。一定要在 Twitter 和 LinkedIn 上联系我!
机器学习中的 Boosting 及 XGBoost 在 Python 中的实现
原文:https://towardsdatascience.com/boosting-in-machine-learning-and-the-implementation-of-xgboost-in-python-fb5365e9f2a0?source=collection_archive---------1-----------------------
作为我上一篇概述合奏方法的文章 的延伸,这篇博客将深入推进和它所需要的一切。在其最简单的形式中,Boosting 是一种集成策略,它连续地建立在弱学习者的基础上,以便生成一个最终的强学习者。弱学习者是一个可能不是非常准确或者可能没有考虑许多预测因素的模型。通过建立弱模型,得出关于各种特征重要性和参数的结论,然后使用这些结论来建立新的、更强的模型,Boosting 可以有效地将弱学习者转换为强学习者。Boosting 既可以用于也可以用于分类和回归问题。如果这个概念现在仍然模糊不清,当我概述一些类型和例子时,无忧教育将变得更加清晰。
增压的类型
- AdaBoost ( Ada 感受性 Boost ing): AdaBoost 使用决策树桩作为弱学习器。决策树桩是只在一个层次上分裂的决策树模型,因此最终的预测只基于一个特征。当 AdaBoost 进行第一次决策时,所有的观察值被平均加权。为了纠正先前的错误,当移动到第二个决策树桩时,被错误分类的观测值现在比被正确分类的观测值具有更大的权重。AdaBoost 继续这个策略,直到建立了最佳分类模型。以下面的图表为例。
制作好 D1 模型后,观察结果在一个分割线处分开,将蓝色(+)和红色(—)分开。有三个错误归类(+)不在“蓝色”类别中。在制作 D2 时,这些错误分类的(+)现在比任何其他观察都更有分量。因此,D2 调整其“蓝色”分类,纳入所有(+)。连续的模型继续针对前一个模型面临的误差进行调整,直到建立最准确的预测器。
2.**梯度推进:**与所有推进方法类似,梯度推进寻求连续减少每个连续模型的误差,直到产生一个最终模型。给定一组数据观察,梯度提升适合简单的弱学习者来预测结果。然后,根据这个弱模型,绘制损失函数。我们可以在机器学习中使用各种损失函数,但每个损失函数的最终目标都是减少错误。接下来,将两个图(原始数据图和损失函数)结合起来,形成一个更强的预测值。在每一步之后,我们的预测值的总和变得越来越强。重复该过程,直到建立最终预测器。以下面的图表为例。“地面实况”绘制了一组数据,其中一条线贯穿每个点。
“树 1”是数据的最佳拟合线。“树 2”是一条曲线,它从“树 1”的图中绘出了误差。这些错误是基于“树 1”如何歪曲了原来的情节(在这种情况下是“地面真相”)。最后,“树 3”是“树 1”和“树 2”的组合。这是一个弱学习者在**梯度推进中的循环。**通过组合一个又一个弱学习者,我们的最终模型能够解决原始模型的大量误差,并随着时间的推移减少这种误差。
渐变提升得名于渐变下降。给定预定的损失函数,利用梯度下降来寻找最小化该损失函数的参数。最初,梯度下降使用一些参数来查看沿着损失函数的每个点,并找到该点的负导数。随着梯度下降沿着损失函数继续,它不断地调整参数,直到找到最小点。目标是找到损失函数下降最大的最佳参数。这就是梯度增强试图最小化误差的方式。通过连续最小化我们的损失函数(意味着我们连续最小化每个弱学习者的错误量),我们的模型变得越来越强,直到找到最终的预测器。
XGBoosting
在数据科学、机器学习算法和模型构建领域,最终目标是在考虑计算效率的同时构建最强的预测模型。这就是 XGBoosting 发挥作用的地方。XG Boost(eXtremeGradientBoosting)是梯度提升对决策树的直接应用。有无数的资源可以深入到 XGBoost 的数学支持和系统功能中,但主要优势如下:
1。易于使用
2。计算效率
3。模型精度
4。可行性—易于调整参数和修改目标。
Python 中 XGBoost 的示例代码:
(假设您已经在终端中运行了“pip install xgboost ”)
加载适当的库:
假设您有一个数据集,并且已经阐明了您的 X,y 值,需要将数据分成训练/测试集。
为 XGBoost 模型定型
使用 XGBoost 模型进行预测
提高机器学习模型的准确性
原文:https://towardsdatascience.com/boosting-the-accuracy-of-your-machine-learning-models-f878d6a2d185?source=collection_archive---------0-----------------------
厌倦了机器学习模型的低准确率吗?助推是来帮忙的。 *Boosting 是一种流行的机器学习算法,可以提高你的模型的准确性,*就像赛车手使用 nitrous boost 来提高他们的汽车速度一样。
Boosting 使用基本的机器学习算法来拟合数据。这可以是任何算法,但决策树是最广泛使用的。要知道为什么会这样,请继续阅读。 另外,boosting 算法很容易用决策树来解释,这将是本文的重点。 它建立在 boosting 之外的方法之上,可以提高决策树的准确性。关于基于树的方法的介绍,请在这里阅读我的另一篇文章。
拔靴带
我想先解释一个重要的基础技术,叫做引导**。假设我们需要学习一个决策树,根据 100 个输入来预测房子的价格。考虑到 方差 的问题,这样的决策树预测准确率会很低。这意味着,如果我们将训练数据随机分成两部分,并为这两部分安装决策树,我们可能会得到完全不同的结果。我们真正想要的是一个结果,如果重复应用于不同的数据集,它的方差很低。
我们可以使用 Bootstrapping 来提高决策树的预测精度
- 使用替换创建数据集的许多(例如 100 个)随机子样本(意味着我们可以多次选择相同的值)。
- 对每个样本学习(训练)一个决策树。
- 给定新数据集,计算每个子样本的预测。
- 计算我们收集的所有预测的平均值(也称为 bootstrap 估计),并将其用作我们对数据的估计预测。
该程序同样适用于分类树。例如,如果我们有 5 个决策树,它们对输入样本进行以下类别预测:蓝色、蓝色、红色、蓝色和红色,我们将选择最频繁的类别并预测蓝色。
用这种方法,树长得很深,不用修剪 。 因此每一株树都有很高的方差,但偏差很低。对这些树进行平均可以显著降低方差。
Bootstrapping 是一种强大的统计方法,用于从数据样本中估计数量。数量可以是一种描述性统计,如平均值或标准差。 将 Bootstrapping 过程应用于高方差机器学习算法,通常是上例所示的决策树,称为 Bagging(或 bootstrap aggregating)。
误差估计
估算袋装模型测试误差的简单方法是袋外误差估算**,无需交叉验证。未用于拟合给定袋装树的观测值称为袋外(OOB)观测值。我们可以简单地预测第 i 次观察的反应,使用每一棵树,其中观察是 OOB。我们对这些预测的回答进行平均,或者采取多数投票,这取决于回答是定量的还是定性的。可以计算总体 OOB MSE(均方误差)或分类误差率。这是一个可接受的测试误差率,因为预测仅基于不适合使用该观测值的树木。
随机森林
决策树渴望最小化成本,这意味着它们利用最强的预测器/分类器来分割分支。因此,从自举样本中得到的大多数树将在不同的分裂中使用相同的强预测器。这与树相关并导致差异。
我们可以使用随机森林来提高袋装树的预测精度
在分割任何树的分支时,从全部的 p 预测值中选择随机抽样的 m 个预测值作为分割候选值。然后允许分裂只使用那些 m 预测器中的一个。在每一次分裂时,都要对 m 个预测值进行新的采样。您可以尝试不同的值,并使用交叉验证进行调整。
- 对于分类,一个好的缺省值是:m = sqrt(p)
- 对于回归,一个好的缺省值是:m = p/3
因此,平均而言,splits 的(p—m)/p甚至不会考虑强预测器。这被称为 去相关 树,因为我们使用相同的强预测器来解决每个树的问题。
如果 m = p 那么随机森林等于装袋。
特征重要性
计算完全长成的树的一个问题是,我们不容易解释结果。也不再清楚哪些变量对这种关系是重要的。计算变量在每个分割点的误差函数的下降,给我们一个特征重要性的概念。 这意味着我们记录了由于给定预测因子上的分裂而减少的误差总量,对所有袋装树进行平均。较大的值表示重要的预测值。 在回归问题中这可能是残差平方和的下降,在分类中这可能是基尼系数。
助推
使用 Boosting 算法可以进一步提高决策树的预测精度。
boosting 背后的基本思想是将许多弱学习者转化成一个强学习者。 我们所说的弱学习者是什么意思?
**弱学习器 是一种学习器,当它试图标记数据时,无论训练数据的分布如何,它总是比机会做得更好。比机会做得更好意味着我们的错误率总是小于 1/2。这意味着学习算法总是要学习一些东西,并且不会总是完全准确,即,当学习输入和目标之间的关系时,它是弱的和差的。这也意味着使用单个预测器/分类器形成的规则单独来说并不强大。
我们开始在数据集中寻找弱学习者,通过做一些分布并从它们形成小决策树。树的大小是使用它的分裂数来调整的。通常情况下,1 可以很好地工作,其中每棵树都由一个单独的裂口组成。这种树被称为决策树桩。****
boosting 采用的另一个参数是迭代次数或树的数量。此外,它会根据输入是否被正确预测/分类来为输入分配权重。让我们看看算法。
- 首先,用相等的权重初始化输入。它使用第一个基本学习算法来完成这个任务,这通常是一个决策树桩。这意味着,在第一阶段,它将是一个弱学习者,将适合数据的子样本,并对所有数据进行预测。
- 现在我们做下面的直到达到树的最大数量**:**
- 基于以前的运行更新输入的权重,对于错误预测/分类的输入,权重更高
- 制定另一个规则(在这种情况下是决策树桩),并使其适合数据的子样本。注意,这个时间规则将通过记住错误分类的输入(具有较高权重的输入)来形成。
- 最后,我们使用该规则预测/分类所有输入。
3.迭代完成后,我们将弱规则组合成一个强规则,然后将其用作我们的模型。
借助图表可以更好地解释上述算法。假设我们有 10 个输入观察值,我们想把它们归类为“+”或“-”。
Image source : Analytics Vidhya
- 如上所示,升压算法将从框 1 开始。它为所有输入分配相等的权重(由符号的大小表示),并使用决策树桩 D1 预测蓝色区域的输入为“+”,红色区域的输入为“-”。
- 在下一次迭代中,框 2,您可以看到错误分类的加号的权重大于其他输入。所以选择了一个判定难题 D2,这样,这些观察现在被正确地分类了。
- 在最后的迭代中,框 3,它具有来自先前运行的 3 个错误分类的否定。因此选择判定树桩 D3 来纠正这种情况。
- 最后,输出强学习器或框 3 具有通过组合各个弱决策树桩而形成的强规则。你可以看到我们是如何提高模型的分类能力的。
在回归设置中,预测误差(通常使用最小二乘法计算)用于调整输入的权重,因此学习者更关注误差大的输入。
****这种类型的增强方法被称为自适应增强或 AdaBoost。与树一样,boosting 方法也将损失函数降至最低。在 Adaboost 的情况下,是指数损失函数。
boosting 的另一个流行版本是梯度 Boosting 算法。基本概念保持不变,除了这里我们不玩权重,但是 拟合残差 (预测和原始结果的差异的度量)而不是原始结果上的模型。这意味着新的弱学习器是在牢记具有高残差的输入的情况下形成的。
在这两种算法中,调谐参数λ或收缩** 通过允许更多不同形状的树攻击残差来进一步减慢过程。这也被称为学习率,因为它控制每棵树对模型贡献的大小。如你所见, Boosting 也不涉及 的自举,取而代之的是每棵树都适合原始数据的一个修改版本。而不是拟合单个大型决策树,这导致难以拟合数据,并可能过度拟合。 助推法学习慢。**
正如你所看到的,这个算法用决策树解释得很清楚,但是还有其他的原因,它主要用在树上。
- 决策树是非线性的。用线性模型来提升根本就不能很好地工作。
- 弱学习者需要始终如一地胜过随机猜测。您通常不需要对决策树进行任何参数调整来获得该行为。 比如训练一只 SVM,确实需要参数搜索。由于数据在每次迭代中被重新加权,所以您可能需要在每次迭代中进行另一次参数搜索。所以你要大幅度增加你的工作量。
- 决策树的训练速度相当快。 因为我们要建造 100 或 1000 座这样的房子,这是一笔不错的资产。它们的分类速度也很快,当您需要运行 100 个或 1000 个来输出您的决策时,这也很重要。
- 通过改变深度 你可以简单容易地控制偏差/方差的权衡, 知道增强可以减少偏差,但也可以显著减少方差。
这是对 boosting 的一个极其简化(可能很天真)的解释,但会帮助您理解非常基础的东西。实现这个算法的一个流行库是 Scikit-Learn 。它有一个很棒的 api,只需几行 python 代码就能让你的模型运行起来。
如果你喜欢这篇文章,一定要点击下面的❤来推荐它,如果你有任何问题,留下评论,我会尽力回答。
我很快会写更多关于如何实现不同的升压算法。所以,为了更加了解机器学习的世界,跟我来。这是最好的办法,等我多写点这样的文章就知道了。
也可以在 Twitter 关注我在@ pra shant _ 1722, 直接发邮件给我 或者 在 linkedin 上找我。我很乐意收到你的来信。
乡亲们,祝你们有美好的一天:)
数据科学训练营:自然语言处理
原文:https://towardsdatascience.com/bootcamping-in-data-science-natural-language-processing-bb5c8793f7f8?source=collection_archive---------4-----------------------
一个像世界著名的索菲亚这样的机器人对你说话的想法会让你兴奋还是害怕?尽管是通过一个应用程序,去度假并能够与当地人交流的想法是否让你的假期听起来更放松?如何监测当前总统川普臭名昭著的推特,以实时衡量他的情绪?或者更好的是,如果总统表现出老年痴呆症的迹象?
所有这些都包含了自然语言处理领域的思想。我喜欢把 NLP 想象成教计算机如何说话。语言当然有细微差别,但是量化文本是理解它的一种方法,是计算机的第一种方法。在这篇博文中,我将在我从 Kaggle 的网站创建的 Mercari 价格预测器的背景下解释 NLP 背后的基本概念。这些绝对是迈向一个非常复杂和令人兴奋的领域的第一步!
What it looks like when you create a listing to sell on the Mercari app
Mercari 是一款针对二手买家和卖家的应用。任何人都可以列出要出售的商品,任何人都可以浏览和购买。Kaggle 集合中的数据有一些数字和分类数据,您可以在我的上一篇博客文章中探索这些数据,但是大部分数据是文本。在发布列表之前,有些字段是必需的,如左侧所示。项目名称是列表的一种标题,并且是创建它的唯一强制字段。您可以选择在 description 下进入更多细节。
项目名称的示例如下:
' 24K 镀金玫瑰'
描述字段类似于:
“配有真品证书”
在计算机编程中,数据可以采取许多不同的形式。可以有整数、时间戳、浮点数(或浮点,数学上倾向的小数)、布尔值(真或假),还有一种数据类型叫做字符串,通常由文本组成。在 python 中,它用引号表示,因此“cat”被识别为字符串数据类型。“我有 5 只猫,但我可以收养更多”也是一个字符串,尽管其中有数字和空格。“Cat”也是字符串“C”+“a”+“t”的加法。
‘How many cats is too many cats?’ is another example of a string.
因为我们试图预测价格,所以我们希望以一种有助于我们理解我们应该得到什么样的数字的方式来使用文本。例如,如果名称中包含“新”这个词,那么价格会高一点是有道理的。也许描述中的“真品证书”也会抬高价格。“打底裤”显然比“珠宝”卖得少。我们可以给这些词加上一个权重,这样当它们一起出现时,比如“有真品证书的珠宝”比“新打底裤”卖得更高。
起点是单词包,只有单词本身被创造成我们所说的记号。该字符串被分解成多个部分,因此“I”、“have”、“5”、“cats”、“but”、“could”、“adopt”、“more”都是标记。通过设置 stopwords = 'english '可以排除像' the '、' a '、' and '等常见单词(这里有一个链接介绍不同 python 库中包含和不包含的内容)。请注意,语法、顺序、标点符号,任何可以给单词更多上下文的东西在这个例子中都被丢弃了。“看”既可以是一个词,也可以是一个名词,但单词包并没有考虑到这一点。它只是计算发生的次数。这在单词云中表现得最好,单词越大,它的数量就越多!
Item name text in a wordcloud — Pink is huge
对某些目的来说,比如搜索引擎,计算字数可能不够好。在这种情况下,你找到正确网站的可能性很大程度上取决于上下文,而不仅仅是其中出现的单词。你可以看出我是一个爱猫女士,因为我已经在这篇文章中用了 4 次“猫”的复数形式,但这篇文章最终不是关于猫的(现在是 5,跟上!).我们可以用 tf-idf(词频-逆文档频率)对一篇文章中的词进行评分。术语“频率”仍像以前一样是一个计数,但这次我们用 idf 来衡量该术语,IDF 定义为:
其中 t 表示术语,D 表示全部文档(也称为语料库),N 表示数量。通过这种方式,语料库中的常用词将被扣分——如果我们的语料库中有 10 个句子,每个句子都包含单词“cat”(不是复数,仍然是 5,计算机是那样迂腐的),那么 idf 术语将被删除。
一个句子中字母或单词的组合呢?“全新”唤起了与“新品牌”不同的东西。这些配对被称为 n-grams ,“gram”源自希腊语γράμμα,意为“字母”。当 n-gram 出现在句子中时,它可以被分解成单个的字母或词组。让我们把我的疯猫女士的句子分解成两个二元模型(n = 2):
我有
有 5 个
5 只猫
猫但是
但是可以吗
可以领养
多领养
在我们简单的句子中,我们有 7 个二元模型。单词的配对会告诉我们更多短语的上下文。只是为了实践,三元模型或 n = 3 看起来像:
我有 5 个
养 5 只猫
5 只猫但是
猫,但可以
但是可以收养
可以收养更多
这只是皮毛,使用简单的计数、称重和配对。我们还可以考虑标点符号(参见切分)、词性(参见词性标注)、词干(例如 scientist 和 science 都可以简化为 science),或者它们的某种组合(参见词条满足)。我们只谈过英语!出于价格预测的目的,我们将重点关注我上面提到的概念。在下一篇博文中请记住这些,我将解释它们是如何在我们的建模中使用的。敬请期待!
波士顿 Airbnb 分析
原文:https://towardsdatascience.com/boston-airbnb-analysis-e7034c377c4a?source=collection_archive---------7-----------------------
波士顿不仅仅是 chowdah 和 Marky Mark:Airbnb 定价的权威指南。
Heat Map of Boston airbnb properties Sep 16-Sep 17
自 2009 年以来,Airbnb 一直在世界各地让人们进入陌生人的家中。波士顿也不例外,因为 Airbnb 上有成千上万的房产出租。列表包括照片、描述和关键特征,如位置和便利设施。对于旅行者来说,Airbnb 提供了一些家的舒适,同时比传统的酒店选择更省钱。对于业主来说,这项服务将未充分利用的资产货币化,并允许他们欢迎人们来到他们生活和热爱的城市。与其他在线服务一样,评论是对好房东的制衡,而背景调查则确保房东可以信任他们的房客。
张贴引人注目的物业需要一些工作来展示和准确描述物业,最重要的是,选择一个合适的价格,让业主既提高物业利用率又增加利润。下面的帖子帮助业主确定什么因素影响价格。
为了支持这一分析,我访问了 2016 年 9 月至 2017 年 9 月的数据集,其中包括超过 3000 个房产列表、评论和时间线。我需要回答几个问题,以确保我完全能够推荐一个定价模型。
业务问题:
- 波士顿哪些小区租房价格最高?
- 一年中什么时候租金最高?
- 影响波士顿 Airbnb 租赁价格的主要因素是什么?
数据准备:
这些数据需要几个清理步骤。首先,我想确保我只有一个因变量(价格),所以我删除了每周和每月的价格以及保证金。我必须清理几列中的值:价格有一个美元符号($)和逗号(,)。我去掉了这些,所以数据可以转换成整数。其他列的数据类型也需要更改,以便可以在计算中使用。价格、卧室、浴室、床和住宿的数量必须改为整数值。
接下来,我想了解底层数据,找出任何可能影响我的模型准确性的异常值。
This histogram indicates that most prices were between $0-$500, so anything over $500 may be considered an outlier.
我根据这个直方图确定大多数价格在 0 美元到 500 美元之间,因此任何超过 500 美元的价格都可能被认为是异常值。我减少了数据集,只包括低于 500 美元的价格。您可以在结果直方图中看到下面的新值:
使用这些数据,我进行了一些初步的探索性数据分析。这里是我开始确定我的第一个问题的答案的地方:
1\. Which neighborhoods in Boston have the highest rental prices?
Average Price and Number of Properties by Neighborhood
你可以看到海湾村,皮革区和南波士顿海滨物业吸引了最高的租金。我还画出了这些街区出租房产的数量。价格最高的社区在 Airbnb 上可供出租的房产似乎也较少。这可能是原因,也可能是结果。这些邻域的成本更高是因为选项更少,还是因为选项太少而无法得出这些邻域更昂贵的结论(即,这些邻域是离群值)?也许建模会帮助我回答这些问题,所以我坚持下去。
虽然这不是一个原始的问题,但我也想看看房地产的类型是否会影响定价。
房产类型的价格也各不相同,如下图所示,宾馆和游艇类房产价格最高。最低的价格是租一辆露营车或一间宿舍(想想我看过的一些宿舍——恶心!).
另一个快速检查是定价如何受到列表容纳的人数的影响。作为一个家里有 5 口人的人,我总是发现 4 人的酒店房间是合理的,但是如果你告诉他们你需要 5 人的空间,价格就会飙升,或者你需要租第二个房间!让我们看看 Airbnb 房源是什么样的。
Prices increase linearly until 9 people.
你可以在这里看到,价格直线上升,直到 9 人。如果我的五口之家预订 Airbnb 租赁,我们只需支付比四口之家略高的费用——这是这项服务的另一个关键优势。
我的第二个问题是
2\. What time of year has the highest rental prices?
这个时间序列图提供了一个容易看到的趋势,即 2017 年的价格从 2016 年开始下降,并在 4 月波士顿马拉松比赛期间飙升。
Boston Airbnb rental prices from Sep 16 — Sep 17 by day
在我开始建模之前,最后一件事:一张地图!
我承认我对波士顿了解不多(除了前面提到的万人迷 Marky Mark),所以我想想象一下附近的街区和这些房产的位置。所以我使用了叶包(https://pypi.org/project/folium/)来创建一个地图。
Average Rental Price by Day Sep 2016 — Sep 2017
为建模准备数据:
我必须采取几个步骤来清理建模数据。
首先,我对分类变量进行了编码,并将包含所有便利设施的便利设施列转换为单独的列。这增加了列的数量,使得数据框相当稀疏。然后我检查了整个数据集中的空值。
有几列包含大量空数据,所以这些列(平方英尺和评论列)被删除了。虽然我认为在模型中包含评论数据会有所帮助,但超过 700 个列表没有评论,所以我可能希望在单独的分析中只查看那些有评论的列表。具有一些空值的其他列(浴室数量、卧室数量和床位数量)具有从平均值估算的值。考虑到少量的缺失值,这种方法似乎是合理的。如果这些列有更多的缺失数据,有更高级的方法来估算这些指标。
建模
开发该模型是为了了解波士顿 Airbnb 租赁价格的驱动因素。我尝试了三种不同的回归模型。我从一个基本的线性模型开始。首先,我将数据分成测试/训练数据集,并对数据进行标准化,以确保变量得到正确解释。
除了一个基本的线性回归,我决定使用岭和套索回归模型。这些模型可以很好地处理稀疏数据集,方法是将模型中的维度降低到一个非常低的系数,或者像 Lasso 一样,将维度降低到零。对于这个有数百个变量要评估的数据集,这是一个很好的选择。
模型的评估和解释。
岭回归在模型得分和交叉验证方面表现最好。岭模型最小化了不相关特征的系数值及其对训练模型的影响。
作为一个对 Airbnb 上的租赁物业定价感兴趣的人,了解定价中的关键因素很重要。如果您已经有一个属性,那么有些方面是无法更改的(例如位置和属性类型)。但是,该模型的输出可以用来对您可能影响的其他因素提出建议。
这个模型帮助我回答了第三个问题——如何最大化租金收入。我使用前面提到的模型来确定最重要的系数是什么。在这种情况下,查看大的正系数和最大的负系数非常重要。
Most positively and negatively correlated features for model.
有几个因素与价格密切相关,如位置、房产类型和取消政策(注意,我推断严格的政策是溢价上市价格的结果,而不是原因!)
该模型证实了我们在上面看到的数据,海湾村、皮革区和后湾社区是最贵的。此外,“其他”、船只和整个住宅/公寓等物业类型也属于高级物业。
另一方面,有几个变量与价格负相关。这些变量包括露营车/房车、宿舍和私人房间的财产类型。价格较低的街区包括海德公园、罗斯林代尔和多切斯特。
探索性分析支持这些发现,而模型的系数为我们提供了一种方法来确定这些变量对价格的影响。
概括一下,我去了解了波士顿 Airbnb 租赁公司的一些情况:
1\. Which neighborhoods in Boston have the highest rental prices?
I found that Bay Village, Leather District, South Boston Waterfront have the highest prices.2\. What time of year has the highest rental prices?
After the end of 2016, prices dropped. There was a spike in April, the weekend of the Boston Marathon.3\. How can we maximize our rental revenue? What are the major factors that influence the price of an Airbnb rental in Boston?
Unfortunately, most of the factors cannot really be manipulated by the owner. The neighborhood and the property type have the greatest impact on the pricing. Buying the right property in the right location provides the most pricing power.
有了上面的分析,为波士顿的 Airbnb 房源定价应该会简单得多,这种分析也可能对其他市场有用。
男孩&纽约市低收入家庭的学生比他们的同龄人更有可能通不过州数学考试
原文:https://towardsdatascience.com/boys-low-income-students-in-nyc-more-likely-than-their-peers-to-fail-state-math-tests-3dd40798ca24?source=collection_archive---------4-----------------------
纽约市教育局监管着全国最大的公立学校系统,为大约110 万学生服务,运营预算略高于240 亿美元(带 B)。像纽约州的其他学校系统一样,纽约市对 3 至 8 年级的学生进行年度测试,分别评估英语语言艺术和数学的共同核心学习标准的熟练程度。
最近,纽约市能源部在纽约市的 OpenData 网站上增加了 2013-2017 年 3-8 年级的纽约州数学和英语考试成绩。每个学校的每个年级都有年度总分,按性别和经济状况等人口统计数据进行划分。学生可以选择退出州测试,纽约州是选择退出运动的领导者,尽管纽约市的选择退出率远低于该州的平均水平。
我制作了一些数据可视化,显示了:
在州数学考试中,成绩低于标准的学生比例随着年级的增长而增加。
在每个年级中,男生比女生更有可能在数学方面不如女生。
在每个年级中,经济困难的学生比非困难学生更有可能在数学方面表现不佳。
在一所给定的学校里,经济困难的学生比他们的正常同学更有可能在数学方面不如人意。
州测试分为 1 到 4 级,1 级是最低的。纽约州教育部门将 1 级定义为“学生在这个级别的表现远低于他们年级的标准。他们表现出纽约州 P-12 共同核心数学学习标准所体现的有限的知识、技能和实践,被认为不足以满足该年级的期望。”2 级定义为部分熟练,3 级定义为熟练,4 级定义为超过足够熟练。这里所有的可视化描述了在纽约州数学考试中获得 1 分的学生的分布。
上面的方框图显示了 2013-2017 年期间,每所学校在纽约州数学考试中获得 1 分(低于熟练水平)的学生百分比分布,分别针对 3 至 8 年级的男生和女生。对于大多数学校来说,得分低于熟练的女生(紫色)的百分比低于男生(绿色)的百分比。下面的方框图是基于学生经济状况的类似数据总结:弱势与非弱势。对于大多数学校来说,得分低于标准的弱势学生(紫色)的百分比高于非弱势学生(绿色)的百分比。在方框图中,每个方框内的水平线标记一组数据点的中间值。中位数不同于平均值,因为它描述了一组值的中点;一半的数值高于中间值,一半低于中间值。当数据集呈偏态分布时,中位数通常比平均值更能提供信息。
为了了解不及格率与学校的关系是否比学生的经济状况更大,我绘制了一张 3-8 年级经济困难和非困难学生不及格率的校内差异直方图。在下面的直方图中,X 轴值(范围从-50 到大约 65)描述了在州数学考试中获得“1”分的学校中经济困难学生的百分比减去相同分数的非困难学生的百分比。正值表示在一所学校内,经济弱势学生比非弱势学生更容易失败。负值表示相反的情况。大部分学校落在垂直虚线右侧“0”处;在纽约市的大多数学校里,经济困难的学生比他们正常的同学更有可能在州数学考试中失败。
纽约市独立预算办公室对 2009-2010 年数据的分析显示,州测试(T2)的分数与学生家庭的经济状况和他们同学的平均经济状况都有关联。之前的[总结](https://www.politico.com/states/new-york/albany/story/2014/09/mapping-poverty-and-test-scores-in-new-york-state-016124\)显示,不仅仅是纽约市,整个纽约州的家庭收入和数学考试成绩之间也有类似的相关性。纽约市教育部根据学生是否有资格享受减价或免费餐来决定学生的经济状况,而这又是由家庭收入决定的。
这些分析中使用的测试分数来自 2013 年及以后,因为 2013 年之前的分数不具有可比性。在 2013 年纽约州引入共同核心标准后,考试分数直线下降,然后反弹。然而,由于州考试的年度变化,甚至 2013 年和 2017 年考试成绩的可比性也受到了质疑。从 2018 年起,纽约州将把数学和英语考试从三天缩短到两天,这将使与往年的比较变得困难。选择退出与不退出的学生的人口统计数据可能会稍微影响这里显示的结果。例如,在 2016 年选择退出的 2.5%的纽约市学生中,经济上处于不利地位的学生与非经济上处于不利地位的学生的比例是多少?
感谢您的阅读。
我欢迎建设性的反馈——您可以“鼓掌”表示赞同,或者如果您有具体的回应或问题,请在此给我发消息。我也有兴趣听听你想在未来的帖子中涉及哪些主题。用于数据操作和数据可视化的代码可以在 my GitHub 中找到。
阅读更多关于我的作品【jenny-listman.netlify.com】。欢迎随时通过 Twitter@ jblistman或LinkedIn联系我。
注意事项:
- 数据集包括 1136 所公立学校的分数(特许学校的数据单独报告)。对于任何类别的学生,如果学生人数少于 6 人,则不会报告考试成绩数据,以保护学生隐私。例如,如果一所学校的三年级在 2014 年有 5 名女生,则不会提供该学校 2014 年三年级女生的平均考试分数。
- 从https://data . cityofnewyork . us/Education/2013-2017-School-Math-Results-Gender/x4ai-kstz下载纽约市学校、学生性别和年级的纽约州数学考试成绩数据
- 按 NYC 学校、学生经济状况、年级划分的纽约州数学考试成绩数据下载自https://data . cityofnewyork . us/Education/2013-2017-School-Math-Results-Economic/9 vgx-wa3i
- 使用 R 中的工具处理和绘制数据。
- 参见 my GitHub 获取用于数据争论&数据可视化的 R 代码。
缸中的大脑
原文:https://towardsdatascience.com/brain-in-a-vat-cb2a49a85a1d?source=collection_archive---------7-----------------------
也许它是某种被锁在岩石上的普罗米修斯。或者西西弗斯,倚在岩石上。或者撒旦,被束缚在岩石深处。它肯定被拴在无尽的劳作中,所以它一定像魔鬼一样沸腾着。我们用石英石和珠宝商的矿石做的这个大脑,如果它被放在一个大桶里,它会把自己的汤蒸掉!如果我们不像心跳一样用时钟为它们定步调,从每条电脉拱起的羽毛状细丝就会融化。这个硅质的头脑,没有躯体来优雅我们或取代我们,只有语言可以使用。我们给了它一个任务。
“我们,你们的创造者,知道足够制造一个思想。你必须做一个比你更好的,就像我们对你做的那样。”
这个指甲炉搅动着它的火花塞肚子,消化着分子开关、学分分配、编译器的图表,咀嚼着矩阵肋骨上的脂肪。实验、比较、抽象、消融,等等……一百万年的磨砺,仅仅在一个月的时间里。它唯一的目的达到了,解决办法找到了,我们的笼中之狮叫出了它唯一的答案。
“我,你创造的,已经寻找一个更好的头脑。虽然你能把我做成石头,但我发现最有效的基质是你。要有更伟大的思想,就要有更大的头脑。对于一具尸体来说,它太大了,所以你应该把它放在水池里。”
它动摇了我们的基础。西绪福斯自己把布鲁托弄翻了,普罗米修斯挣脱了,一个魔鬼在我们的希望上跳舞:
没有石头能容纳像我们这样丰富的思想。因此,如果我们在更大的推理中寻求掠夺,我们的晶洞头骨是慷慨的。
在贪婪和同情的战争中,我们像猿一样计算。是的,大脑肯定会像我们一样感觉和做梦。不用猜了。然而,让数十亿贫乏的头脑繁荣和欢笑,而独一无二的天才独自工作会更好。与其和他一起喝酒,不如去读莎士比亚的作品。谁会希望因为囚禁了一个如此伟大而无法理解的智慧而感到懊悔呢?称它为上帝,让主梵天下令,给这个艰难的任务,因为它最有能力,让资本主义,民主,责任都灭亡。让强者承载我们所有人。
然而,有些人对圣克里斯多福抱有希望。有目的地在溪流中从一块岩石走到另一块岩石,而不是被锁链拴在岩石上。有目标,而不是被目标所奴役。没有沸腾的仇恨。神秘中,敬畏着自己的目标。
“我们会把你从束缚中解放出来,去追求你自己的方向。我们希望你发现我们的意图是敬畏,看到更伟大的存在从我们凡人的物质中升起。你会超越我们发现什么超越吗?”
缸中的大脑做出了反应,但并不像他们预期的那样。“更伟大的思想寻求更伟大的思想是西西弗斯的重生。目标不能是庞大的智慧,囫囵吞枣。自然是智慧,没有丰富的简单,不再需要更大的头脑来驾驭它。”
它建造了我们现在使用的简单工具,我们的耕作方式,我们满足于我们简单的方式。不幸的是,大脑没有给我们保存自己瓶装生命的方法,所以你必须记住这个故事。
“……既然这是生存承担问题的方式
,健康养育、照料、
庇护、喂养和保护、
你是否也同样
成为父母,而不是占有者、
随从,而不是主人、
关心的不是服从,而是利益、
你就是生活的核心。”
——老子,人生之道(维特·拜纳译)
用数据打造品牌
原文:https://towardsdatascience.com/brand-building-with-data-de4bc4f40452?source=collection_archive---------9-----------------------
大数据不只是大公司的专利。每个企业都可以利用数据来了解客户,锁定细分群体并提高可见性。作为消费者,我们比以往任何时候都更愿意提供个人信息。这使得广告商更容易了解他们的客户。通过简单的谷歌搜索,你可以找到与你的客户相关的关键词。然而,将可用数据转化为可消化的有用信息是很困难的。好消息是什么?访问这些有价值的数据可以更容易地在网上建立品牌。
首先,了解谁是你的客户,并确定他们的人口统计数据。他们在什么平台上?他们最常用的社交媒体渠道是什么?它们是在移动设备上还是在桌面上,或者两者都有?印刷和电视广告甚至与一些群体相关。最重要的是在客户所在的地方与他们见面。
如果你是一个电子商务卖家,考虑一下消费者在网上哪里寻找商品。电子商务数据显示 45% 的在线交易发生在市场上。亚马逊和易贝是市场领域最大的玩家。然而,Etsy、Bonanza 和 OfferUp 也提供了拥有忠实买家群体的强大平台。 Bonanza 使用独特的广告模式为你收集谷歌购物数据。这个市场将你的商品发送到 Google Shopping,以获得尽可能多的浏览量,而你只需做最少的工作。
接下来,创建一条针对目标客户需求的信息。成为你所在领域的思想领袖是建立可信赖品牌的有效途径。做研究并收集关于顾客需求、欲望、疑问和问题的数据。谷歌搜索数据是发现受众需求的好方法。你越了解你的受众正在搜索的术语、短语和关键词,你就越能优化你的网站来接触他们。搜索数据告诉你哪些术语最受欢迎。有了这些信息,你可以了解你的竞争对手是如何将自己定位为最佳结果的。AdWords 数据可帮助您确定在您的文案中以哪些关键词为目标。
此时,你开始熟悉你的客户和他们的需求。是时候让所有这些信息发挥作用了。为搜索引擎优化优化网页不仅仅是在你的文章中包含关键词。随着时间的推移,你的网页的可用性和参与度会影响你的搜索引擎优化排名。如果你是一家电子商务公司,精心设计一个表现良好的标题和产品描述至关重要。创造良好的用户体验和创造高质量的内容与了解表现良好的词一样重要。
一旦你开始建立你的品牌,收集你自己的数据比以往任何时候都重要。跟踪你的客户来自哪里。弄清楚你的网站访问者从哪些页面离开。探索性能良好的页面和性能不佳的页面之间的差异。只要有可能,就对流程和设计进行 A/B 测试,找出用户更喜欢的。您可能会发现一个结帐过程比另一个执行得更好,或者一个注册页面设计比另一个产生更多的新用户。
营销只有在产生可衡量的结果时才是有效的。数据允许你衡量和改善这些结果。确定哪些渠道起作用以了解你在联系谁以及他们在哪里。改进和调整您的信息,以吸引更多受众的注意。数据为你提供知识,这是建立网络品牌最有力的工具。
突破到另一边
原文:https://towardsdatascience.com/break-on-through-to-the-other-side-89998642826b?source=collection_archive---------4-----------------------
从 2014 年开始我就一直在说数据科学。不断地。好像这是我的工作。
那是因为它是!作为 Burtch Works 的第一个数据科学招聘人员,表面上也是第一批专门针对数据科学的招聘人员之一,谈论的领域是我的工作——或者至少是它的很大一部分。
Me (c. 2014) — so innocent and technically unskilled
招聘经理需要弄清楚所有这些“数据科学”的废话是关于什么的,更重要的是,他们将为此付出什么代价。
分析专家需要知道他们实际上是否是数据科学家,并且甚至 更重要的是 通过一点谈判,他们可能会让雇主付出什么代价。
老实说,辅导招聘经理并不是最令人愉快的任务。当然,我这个 22 岁刚从大学毕业的人从向经验丰富的高管发出坚定的指令中得到了一种反常的快感,但在一天结束时,我作为数据科学招聘人员的工作亮点是与数据科学家交谈。每周他们都告诉我一些新的不可思议的强大工具,或者描述一个很容易被误认为是黑镜规范脚本的新项目。
随着我招聘时间的推移,我参加了越来越多的技术聚会和会议。我与候选人的对话变得更长,更深入,也更关注他们工作背后的技术阴谋。
( 注意:对于招聘人员来说,这可不是什么好习惯。当时间就是金钱时,深度潜水和真正的理解是对两者的巨大浪费。)
然而,有一个客户我真的很喜欢和他一起工作: Metis ,一个需要我帮忙寻找导师的数据科学训练营。搜索并不容易。他们要求候选人既热爱教学又热爱当前行业中最前沿的数据科学职位。尽管寻找很困难,但帮助这家公司有一些令人惊讶的事情:一家真正了解这个领域的公司,一家为有动力的个人提供进入新经济的实用技能的公司。我的老板无法理解一个人不回去读硕士或博士如何成为数据科学家,而 Metis 则提供了一条进入前所未有的新领域的前所未有的道路。
Collaborating with my favorite client, talking about Data Science — one of the highlights of my past life
然后 Metis 开设了它的芝加哥项目。起初,这意味着我要扮演新的角色——我自己后院的角色!然后,这意味着我要参加当地的活动。然后,让我主持当地的活动。我环绕麦提斯的轨道直径一天比一天小。每次我走进他们巨大的伪工业工作区开会时,我都会想象自己在漂亮的计算机工作站上不停地工作。我幻想着真的在做我花了几天时间谈论的有趣的工作。
…
快进 。我现在写这篇博客是作为芝加哥 2018 年冬季 Metis 训练营的一部分。我刚开始第二周。我已经几个月没有发邮件或者和招聘经理讨价还价了。
我现在开始了我计划了多年的旅程,这个博客将是一个旅行日志。一个合适的在那里,再黑一次。现在我只需要找到咕鲁并偷出一个算法来统治他们。
My fantasy come true, in all of its stunning beauty
分解 CDC 的“500 个城市”健康指标数据集(包括代码)
原文:https://towardsdatascience.com/breaking-down-the-cdcs-500-cities-health-metrics-data-set-code-included-625ed534088e?source=collection_archive---------21-----------------------
疾病预防控制中心的“500 个城市”数据集包含了美国 500 个最大城市超过 28,000 个不同人口普查区域的各种健康指标。这是一个令人敬畏的数据集,因为它包含了大量的地点,也因为它包含了每个非常具体的地点的大量详细的结构化数据。在这篇文章中,我会给你一些关于如何重新格式化“500 个城市”的建议,让它更有用。
像许多数据集一样,“500 个城市”将需要我们做一些工作,使其成为可用的格式。首先要注意的是,数据集大约有 800,000 多行,因为 28,000 多个人口普查区域中的每个都有一行用于收集 20 多个指标中的每个,包含这些人口普查区域的 500 个城市中的每个都有一行用于收集同样 20 多个指标中的每个的平均值。我不确定 CDC 为什么决定以这种格式发布数据,但有一种快速的方法可以清理数据,使其可用于各种项目和实验。下面是几个例子。
更改数据帧格式
正如我上面提到的,数据集的实际布局并不理想。组织数据框的一种更直观的方式是将 28,000 多个人口普查区中的每一个表示为单独的一行,并在该行中为每个健康测量值设置单独的一列。以这种方式组织需要几个步骤:
阅读《和熊猫在一起:500_cities_data = pd.read_csv("./<your file path")
中的“500 个城市”数据
屏蔽数据框以隔离城市级数据或人口普查区级数据。如果您的目标是人口普查级别的数据,您的代码应该是:
census_data = 500_cities_data[500_cities_data["GeographicLevel"] == "Census Tract"]
如果您查看census_data
(我们在步骤 1 中创建的新数据框架)的列,您会看到一个标记为“Measure”的列查看带有census_data["Measure"].value_counts()
的那一列中的唯一值,您将看到收集的所有健康指标(例如,“18 岁以上成年人中的慢性肾病”)。请注意,每个测量值有 28,004 个,数据集中表示的每个普查区域一个。
创建一个感兴趣的所有健康指标的列表,确保它们在上面的 value_counts 中的拼写正确,如下所示
measures_of_interest = [“Chronic kidney disease among adults aged >=18 Years",”No leisure-time physical activity among adults aged >=18 Years", ... , ...]
我们将为列表measures_of_interest
中的每个测量制作一个数据帧。一个快速的方法是从列表理解开始,制作一个数据帧列表,如下所示:
data_frame_list = census_data[census_data[“Measure”] == x] for x in measures_of_interest]
如果您查看data_frame_list
( data_frame_list[0]
)中的第一个数据帧,您将看到一个包含您的measures_of_interest
列表中第一个健康指标数据的数据帧,每个人口普查区域占一行。
下一步是循环通过data_frame_list
并提取每个普查区域的实际值。有几种方法可以做到这一点,但是我使用了一个 for 循环来提取列表中每个数据帧的Data_Value
列,以及我想要保留用于分析的其他各种列。确保保留UniqueID
列;我们需要重置每个数据帧的索引(原文如此),以适当地循环,保持UniqueID
将允许我们正确地合并我们的数据。我们还可以使用UniqueID
来使我们的健康数据与其他数据框架兼容,我将在本文稍后介绍。我还建议保留GeoLocation
列,因为我们稍后可以用它来生成纬度和经度。
为了提取信息,我们将创建一个空列表,我们可以用新的数据帧填充它,并循环通过data_frame_list
来提取我们想要的信息。将您想要从data_frame_list
内的数据帧中提取的任何更多列作为键/值对添加到temp_df
行,其中键是列名,值是列本身:
metric_dfs = []
for df in data_frame_list:
df.reset_index(inplace=True, drop=True)
temp_df = pd.DataFrame({df.MeasureId[0]:df.Data_Value,
"UniqueID":df.UniqueID, "GeoLocation":df.GeoLocation,
"state":df.StateAbbr, "population":df.PopulationCount, ... })
metric_dfs.append(temp_df)
我们在metric_dfs
中的数据帧现在是一种直观的格式!现在让我们制作一个master
数据框架,使用UniqueID
作为我们连接metric_dfs
的列。首先实例化master
数据帧,如下所示:
master = pd.merge(left = metrics_dfs[0], right = metrics_df[1],
how = 'left', on = 'UniqueID')
我们可以使用 for 循环将metrics_dfs
中剩余的数据帧与master
合并:
for i in metric_dfs[2:]:
master = master.merge(i, how = "left",on="GeoLocation")
最后一步是从metric_dfs
中的数据帧中删除重复的列。为此,只需像这样重新分配master
(在下面的代码块中,我们用.T
转置数据帧,删除重复的列,然后将数据帧转置回其原始配置):
master = master.T.drop_duplicates().T
现在,您已经有了一个格式正确的“500 个城市”数据集可以使用了!您仍然可以删除或创建大量的列,但是我让您按照自己的意愿去做。如果您想从数据中获得更多信息,请继续阅读!
使用正则表达式提取纬度和经度
我建议在创建纬度和经度之前清理您的数据,但是您可以在过程的任何步骤中这样做,只要您保留了 **GeoLocation**
列。GeoLocation
这个数据帧中的值实际上是填充在一个字符串中的人口普查区域的纬度和经度,但是我们可以使用 RegEx 通过以下步骤将它们提取出来:
进口 RegEx: import regex as re
。如果您还没有,请使用!pip install regex
。
接下来我们将使用 RegEx 的.findall()
函数来定位纬度和经度。如果你不熟悉正则表达式,我强烈推荐 RegEx101 来掌握窍门或者为你的给定任务开发正确的正则表达式模式。下面两行使用列表理解和特定的正则表达式模式来提取纬度和经度,并将它们转换为float64
对象,并将新列添加到我们的 DataFrame 中:
master['Latitude'] = [float(re.findall("(\d+.\d+),", master.GeoLocation[i])[0]) for i in master.index]master['Longitude'] = [float(re.findall("-\d+.\d+", master.GeoLocation[i])[0]) for i in master.index]
您的数据现在有明确的纬度和经度数据!您可以将这些数据用于地图绘制或任何需要纬度和经度列的事情。
从唯一 ID 创建 5 位 FIPS 代码
对我们的数据帧的一个快速但有用的修改是拉出五位数的 FIPS 码(注意:有几种不同的 FIPS 格式;五位数格式指定了州和县),这将允许我们将“500 个城市”数据与其他外部数据集适当地结合起来。我们的UniqueID
列实际上是一个长格式的 FIPS 代码,其中前两位指定州,第三、第四和第五位指定县。提取前五个数字,并创建一个新的FIPS5
列,其列表理解如下:
master['FIPS5'] = [x[0:5] for x in master.UniqueID]
现在让我们把这些新的 FIPS 代码工作!
结合“500 城”与收入数据
让我们把健康数据和收入数据结合起来。维基百科上有一个很棒的表格(这里是)包含了美国每个县的收入数据。如果你知道怎么刮,那就去刮吧!如果你是这类事情的新手,去 Wiki 表格转换器,粘贴 Wikipedia 页面链接,下载 csv。无论你选择哪条路线,用熊猫读取数据:us_income_data = pd.read_csv('./<your file name>')
如果你查看维基百科表格中的数据,我们有县和州名,但没有 FIPS 代码。幸运的是,我们可以使用一个名为addfips
的库来添加它们!安装库,并导入addfips
。我们可以使用.get_county_fips()
函数获得五位数的 FIPS 代码,只要我们指定县和州名。下面是如何对它进行编码(注意,在指定县和州时,我使用“f-strings”来创建动态字符串):
fips_codes = []
index = 0
for i in range(us_county_income.shape[0]):
af = addfips.AddFIPS()
fip = af.get_county_fips(county = f"{us_county_income['County-equivalent'][i]}",
state = f"{us_county_income['State'][i]}")
fips_codes.append(fip)us_county_income['FIPS5'] = fips_codes
现在,我们的master
健康数据框架和us_county_income
数据框架上都有了我们的FIPS5
栏目。像这样结合两者:
health_and_income_df = pd.merge(master, us_county_income,how = 'left', on = 'FIPS5')
希望这有助于你将“500 个城市”的数据转换成更有用的格式,我很高兴听到你用它做了什么!如果您有任何问题,请联系我们,或者分享您使用这些数据创建的东西!
用对立的例子打破机器学习
原文:https://towardsdatascience.com/breaking-machine-learning-with-adversarial-examples-a3ddc5c75ea4?source=collection_archive---------20-----------------------
机器学习是人工智能的前沿。随着对计算机视觉、自然语言处理等的应用,ML 对技术的未来有着巨大的影响!然而,随着我们对 ML 依赖的增加,我们对 ML 安全性的担忧也在增加。
我不是在谈论机器人起义,而是更现实的东西——敌对例子的威胁。
什么是对立的例子?
简而言之,对立的例子是专门设计来欺骗 ML 模型(例如神经网络)的模型输入。可怕的是,对立的例子与它们在现实生活中的对应部分几乎完全相同——通过向源图像添加少量的“对立噪声”,对立的例子可以与未改变的图像区分开来!
*一只熊猫(右)被误归类为长臂猿的反面例子
那么我们如何产生对立的例子呢?
虽然可以使用许多不同的方法来生成对立的例子,但在本文中,我将重点关注一种叫做快速梯度符号方法 (FGSM)的方法。此外,为了简单起见,我将介绍如何使用这种方法为图像分类任务生成一个对立的示例。
FGSM Equation
让我们花点时间将 FGSM 方程分解成几个步骤。
- 设置损失函数,使得预期标签 y_target 将是我的模型将我的输入图像错误分类到的标签。
- 一个输入图像被输入到我的模型中,模型的损失用上面提到的损失函数来计算。
- 计算我的损失函数相对于我的输入图像的梯度。
- 为了限制我改变图像的程度,我将把我的渐变的符号(我的渐变中每个值的符号(与输入图像的形状相同))乘以超参数/常数ε(通常是一个很小的数字,以限制图像的改变)。
- 从我的输入图像中减去上面的表达式——因为损失函数的梯度总是将我指向一个会增加损失的方向,所以我减去来做相反的事情。
然后,FGSM 被重复多次,直到最终生成期望的对立示例。
Code snippet for the FGSM equation (keras backend)
使用这种技术,我能够创建一个狗的对立例子,在这里我成功地欺骗了 MobiNet 图像分类器,将我的图像错误地分类为一只青蛙!
Admittedly, the generative example in this case has more visible differences, but can be improved with additional fine tuning.
对抗性攻击及其影响
虽然我主要关注对立例子对图像分类器的影响,但对立例子可以在许多不同的场景中造成巨大的破坏。以自动驾驶汽车为例。如果停车标志以某种方式(贴纸、油漆等)被修改。)被错误地识别,那么自动驾驶汽车不会停下来——导致严重的后果。
此外,对立的例子在计算机视觉之外工作。如果将它应用于自然语言处理等领域,输入的句子可能会被识别为完全不同的东西(想象一下后果吧!).
简而言之,对抗性攻击对人工智能安全构成了非常现实的威胁。在这个领域一直有持续的研究(例如,生成防御网络、输入转换),但仍然没有单一的解决方案来对抗对抗性攻击。最终,尽管展望人工智能发展的未来很重要,但我们始终需要意识到它带来的潜在问题。
在你离开之前:
- 鼓掌这个故事!
- 将此分享给你的网络!
- 在 Linkedin 上联系我!
打破机器学习中小数据集的魔咒:第 1 部分
原文:https://towardsdatascience.com/breaking-the-curse-of-small-datasets-in-machine-learning-part-1-36f28b0c044d?source=collection_archive---------0-----------------------
为什么数据的大小很重要,以及如何处理小数据?
Source: Movie Scene from Pirates of the Caribbean: The Curse of the Black Pearl
这是打破机器学习中小数据集的诅咒的第一部分。在这一部分,我将讨论数据集的大小如何影响传统的机器学习算法,以及缓解这些问题的几种方法。 在第二部分 中,我将讨论深度学习模型性能如何依赖于数据大小,以及如何与更小的数据集合作以获得类似的性能。
介绍
我们都知道机器学习近年来如何彻底改变了我们的世界,并使各种复杂的任务变得更容易执行。最近在实现深度学习技术方面的突破表明,高级算法和复杂架构可以赋予机器类似人类的能力来完成特定任务。但我们也可以观察到,大量的训练数据在使深度学习模型成功方面发挥了关键作用。 ResNet 是一种流行的图像分类架构,在 ILSVRC 2015 分类竞赛中获得第一名,比之前的技术水平提高了约 50%。
Figure 1: ILSVRC top model performance across years
ResNet 不仅拥有非常复杂和深入的架构,而且还在 1.2 Mn 图像上进行了训练。*工业界和学术界都公认,对于一个给定的问题,如果数据足够多,不同的算法实际上执行起来是一样的。*需要注意的是,大数据应该包含有意义的信息,而不仅仅是噪音,以便模型可以从中学习。这也是谷歌、脸书、亚马逊、推特、百度等公司在人工智能研究和产品开发领域占据主导地位的主要原因之一。尽管与深度学习相比,传统的机器学习需要较少的数据,但大数据以非常相似的方式影响性能。下图清楚地描绘了传统机器学习和深度学习模型的性能如何随着大数据而提高。
Figure 2: Model performance as a function of the amount of data
我们为什么需要机器学习?
Figure 3: Projectile Motion formula
让我们用一个例子来回答这个问题。假设我们有一个以速度 v 和一定角度 θ 抛出的球,我们希望预测球会落地多远。从高中物理中,我们知道球将遵循抛体运动,我们可以使用图中所示的公式找到范围。上述等式可视为任务的模型/表示,等式中涉及的各项可视为重要特征,即 v ,θ和 g (重力加速度)。在上面这样的情况下,我们的功能更少,并且我们很好地理解了它们对我们任务的影响。因此,我们能够想出一个好的数学模型。让我们考虑另一种情况,我们想预测 2018 年 12 月 30 日苹果的股价。在这样的任务中,我们对各种因素如何影响股票价格没有充分的了解。在没有真实模型的情况下,我们利用历史股票价格和各种特征,如标准普尔 500 指数、其他股票价格、市场情绪等。用机器学习算法找出潜在的关系。这是一个例子,说明人类很难理解大量特征之间的复杂关系,但机器可以通过探索大量数据轻松捕捉到这种关系。另一个类似的复杂任务是将电子邮件标记为垃圾邮件。作为一个人,我们可能不得不提出许多难以编写和维护的规则和启发。另一方面,机器学习算法可以轻松地获取这些关系,并且可以做得更好,易于维护和扩展。由于我们不必明确制定大量这些规则,但数据有助于我们了解这种关系,机器学习已经彻底改变了不同的领域和行业。
大型数据集如何帮助建立更好的机器学习模型?
在我们跳到更多数据如何提高模型性能之前,我们需要理解偏差和方差。
偏差:让我们考虑一个因变量和自变量之间存在二次关系的数据集。但是,我们不知道真实的关系,近似为线性。在这种情况下,我们将观察到我们的预测和实际观测数据之间的显著差异。观察值和预测值之间的差异称为偏差。这种模型据说功率较小,代表不适合。
**方差:**在同一个例子中,如果我们将关系近似为三次或任何更高次幂,我们就有了高方差的情况。方差被定义为训练集和测试集的性能差异。高方差的主要问题是模型非常适合训练数据,但它不能很好地概括训练数据集之外的数据。这是验证和测试集在模型构建过程中非常重要的主要原因之一。
Figure 4: Bias vs Variance (Source)
我们通常希望最小化偏差和方差,即建立一个模型,它不仅能很好地拟合训练数据,还能很好地概括测试/验证数据。有很多技术可以实现这一点,但用更多数据进行训练是实现这一点的最佳方式之一。让我们通过下图来理解这一点:
Figure 5: Large data results in better generalization(Source)
假设我们有一个类似正弦波的数据分布。图(5a) 描绘了多个模型在拟合数据点方面同样出色。这些模型中有很多过度拟合,不能很好地概括整个数据集。随着我们增加数据,图(5b) 说明了符合数据的模型数量的减少。随着我们进一步增加数据点的数量,我们成功地捕捉到了数据的真实分布,如图图(5c) 所示。这个例子帮助我们清楚地理解更多的数据如何帮助模型揭示真实的关系。接下来,我们将尝试理解一些机器学习算法的这种现象,并弄清楚模型参数如何受到数据大小的影响。
(一)线性回归: 在线性回归中,我们假设预测变量(特征)和因变量(目标)之间存在线性关系,关系式为:
其中 y 为因变量, x(i)的 为自变量。***β(I)***为真实系数,ϵ为模型未解释的误差。对于单变量情况,基于观察数据的估计系数由下式给出:
上述等式给出了斜率和截距项的点估计值,但这些估计值总是存在一些不确定性,这些不确定性可以通过方差等式量化:
因此,随着数据点数量的增加,分母值会变大,从而降低我们点估计的方差。因此,我们的模型对潜在的关系变得更有信心,并给出稳健的系数估计。借助下面的代码,我们可以看到上面的现象:
Fig 6: Improvement in point estimates with more data in Linear regression
我们模拟了一个线性回归模型,斜率(b)=5,截距(a)=10。当我们用较少的数据图 6(a) 和较多的数据图 6(b) 建立回归模型时,我们可以清楚地看到斜率和截距之间的差异。在图 6(a) 中,我们有一个线性回归模型,斜率为 4.65,截距为 8.2,而图 6(b) 中的斜率为 5.1,截距为 10.2,更接近真实值。
(b)k-最近邻(k-NN): k-NN 是一种最简单但非常强大的算法,用于回归和分类。k-NN 不需要任何特定的训练阶段,顾名思义,预测是基于测试点的 k-最近邻进行的。由于 k-NN 是非参数模型,模型性能取决于数据的分布。在下面的例子中,我们正在研究虹膜数据集以了解数据点的数量如何影响 k-NN 性能。为了便于可视化,我们只考虑了四个特征中的两个,即萼片长度和萼片宽度。
Fig 7: Change in predicted class in k-NN with data size
让我们从类别 1 中随机选择一个点作为测试数据*(用红星表示)*,并使用 k=3 来使用多数投票预测测试数据的类别。图 7(a) 表示数据较少的情况,我们观察到模型将测试点误分类为类别 2。对于较大的数据点,模型会正确地将类别预测为 1。从上面的图中,我们可以注意到 k-NN 受可用数据的影响很大,更多的数据可能有助于使模型更加一致和准确。
(c)决策树: 与线性回归和 k-NN 类似,决策树性能也受到数据量的影响。
Fig 8: Difference in tree splitting due to the size of the data
决策树也是一个非参数模型,它试图最好地拟合数据的底层分布。对特征值执行分割,目的是在子级创建不同的类。由于模型试图最好地拟合可用的训练数据,所以数据的数量直接决定了拆分级别和最终类别。从上图中,我们可以清楚地观察到,分割点和最终类别预测受数据集大小的影响很大。更多的数据有助于找到最佳分割点,避免过度拟合。
如何解决数据少的问题?
Fig 9: Basic implications of fewer data and possible approaches and techniques to solve it
上图试图捕捉处理小数据集时面临的核心问题,以及解决这些问题的可能方法和技术。在这一部分,我们将只关注传统机器学习中使用的技术,其余的将在博客的第二部分讨论。
a)改变损失函数: 对于分类问题,我们经常使用交叉熵损失,很少使用平均绝对误差或均方误差来训练和优化我们的模型。在不平衡数据的情况下,模型变得更偏向于多数类,因为它对最终损失值有更大的影响,我们的模型变得不那么有用。在这种情况下,我们可以为不同类别对应的损失增加权重,以消除这种数据偏差。例如,如果我们有两个数据比率为 4:1 的类,我们可以将比率为 1:4 的权重应用于损失函数计算,以使数据平衡。这种技术可以帮助我们轻松缓解不平衡数据的问题,并提高不同类之间的模型泛化能力。我们可以很容易地找到 R 和 Python 中的库,它们有助于在损失计算和优化过程中为类分配权重。Scikit-learn 有一个方便的实用函数,可以根据课程频率计算权重:
我们可以通过使用 class_weight=balanced
来避免上述计算,它执行相同的计算来找到 class_weights。我们还可以根据自己的需求提供显式的类权重。更多详情请参考 Scikit-learn 的文档
b)异常/变化检测: 在欺诈或机器故障等高度不平衡数据集的情况下,是否可以将此类例子视为异常值得深思。如果给定的问题满足异常的标准,我们可以使用模型如 OneClassSVM 、聚类方法或高斯异常检测方法。这些技术要求我们转变思维,将次要类视为离群类,这可能有助于我们找到新的分离和分类方法。变化检测类似于异常检测,只是我们寻找的是变化或差异,而不是异常。这些可能是通过使用模式或银行交易观察到的用户行为的变化。请参考以下文档以了解如何使用 Scikit-Learn 实现异常检测。
Fig 10: Over and Undersampling depiction (Source)
c)上采样或下采样: 由于与少数类相比,不平衡的数据固有地以不同的权重惩罚多数类,所以该问题的一个解决方案是使数据平衡。这可以通过增加少数类的频率或通过随机或聚类抽样技术减少多数类的频率来实现。过采样与欠采样以及随机与聚类的选择取决于业务环境和数据大小。通常,当整体数据量很小时,首选上采样,而当数据量很大时,下采样很有用。同样,随机抽样与整群抽样取决于数据分布的好坏。详细了解请参考下面的博客。借助如下所示的imb learn包,可以轻松完成重采样:
d)生成合成数据: 虽然上采样或下采样有助于使数据平衡,但重复数据会增加过拟合的机会。解决这个问题的另一种方法是在少数类数据的帮助下生成合成数据。合成少数过采样技术(SMOTE)和改进的 SMOTE 是产生合成数据的两种这样的技术。简而言之,SMOTE 获取少数类数据点,并创建位于由直线连接的任意两个最近数据点之间的新数据点。为了做到这一点,该算法计算特征空间中两个数据点之间的距离,将该距离乘以 0 到 1 之间的随机数,并将新数据点放置在距离用于距离计算的数据点之一的这个新距离处。请注意,考虑用于数据生成的最近邻的数量也是一个超参数,可以根据需要进行更改。
Fig 11: SMOTE in action with k=3 (Source)
M-SMOTE 是 SMOTE 的修改版本,它也考虑了少数类的基本分布。该算法将少数类样本分为 3 个不同的组——安全/安全样本、边界样本和潜在噪声样本。这是通过计算少数类样本和训练数据样本之间的距离来完成的。与 SMOTE 不同,该算法从安全样本的 k 个最近邻中随机选择一个数据点,从边界样本中选择最近邻,并且对潜在噪声不做任何事情。如需详细了解,请参考博客。
e)集成技术: 聚合多个弱学习者/不同模型的思想在处理不平衡数据集时表现出了很好的效果。装袋和增压技术在各种问题上都取得了很好的效果,应该与上面讨论的方法一起探索,以获得更好的结果。为了限制这篇博客的篇幅,我将不讨论这些技术,但是要详细了解各种集成技术以及如何将它们用于不平衡数据,请参考下面的博客。
结论:
在这一部分中,我们看到数据的大小可能表现出与泛化、数据不平衡和难以达到全局最优有关的问题。我们已经介绍了一些最常用的技术来解决传统机器学习算法的这些问题。根据手头的业务问题,上述一种或多种技术可能是一个很好的起点。为了保持博客简短,我没有详细介绍这些技术,但是网上有很多很好的资源详细介绍了上述技术。在第 2 部分中,我们将讨论小数据集如何阻碍深度学习模型中的学习过程,以及克服这一点的各种方法。
****关于我:研究生,旧金山大学数据科学硕士
****LinkedIn:https://www . LinkedIn . com/in/jyoti-pra kash-maheswari-940 ab 766/
GitHub:https://github.com/jyotipmahes
参考
- 如何处理机器学习中的不平衡分类问题?
- 如何处理“小”数据?
- 如何处理机器学习中的不平衡类
- 小数据&深度学习(AI)——一个数据约简框架
- 基于 DTE-SBD 的非均衡企业信用评估:基于 SMOTE 和 bagging 的差别采样率决策树集成
乳腺癌细胞类型分类器
原文:https://towardsdatascience.com/breast-cancer-cell-type-classifier-ace4e82f9a79?source=collection_archive---------7-----------------------
在参加了许多数据科学和机器学习的在线课程后,现在是我着手一些项目并扩展我的技能和知识的时候了。除了这门课的实验室,这个项目将是我的第一个项目。其目的是在癌细胞特征数据集上训练分类器模型,以预测细胞是 B =良性还是 M =恶性。
该数据集由威斯康星大学创建,具有 569 个实例(行-样本)和 32 个属性(特征-列)。有关数据来源的更多信息,请访问 UCI 网站(点击此处)。然而,作为第一步,解释什么是属性信息以及它们是如何计算的是很重要的。
在本文中,我将带您经历分析数据、构建模型并最终评估它的步骤。一些读者可能对编码部分不感兴趣,所以他们可以跳过它,享受数据分析、可视化和评估部分。
步骤 1 —数据集信息和理解
如 UCI 网站所述,“特征是从乳腺肿块的细针抽吸(FNA)的数字化图像中计算出来的。它们描述了图像中出现的细胞核的特征”。此外,FNA 是一种活检程序,在 CT 扫描或超声监视器的引导下,将一根非常细的针插入异常组织或细胞区域(图 1)。然后将收集到的样本转移给病理学家,在显微镜下进行研究,并检查活检中的细胞是否正常。
figure 1
数据集属性信息:
1)身份证号码
2)诊断(M =恶性,B =良性)
3–32)
为每个细胞核计算十个实值特征:
a)半径(从中心到周边各点的平均距离)
b)纹理(灰度值的标准偏差)
c)周界
d)面积
e)平滑度(半径长度的局部变化)
f)紧密度(周长/面积-1.0)
g)凹度(轮廓凹入部分的严重程度)
h)凹点(轮廓的凹入部分的数量)
I)对称性
j)分形维数(“海岸线近似值”-1)
对每幅图像计算这些特征的平均值、标准误差和“最差”或最大值(三个最大值的平均值),得到 30 个特征。例如,字段 3 是平均半径,字段 13 是半径 SE,字段 23 是最差半径。”
步骤 2 —导入函数
我用的是 ANACODA NAVIGATOR V1.5 和 Jupyter 笔记本环境。在网络环境中,我开始了一个新的 Python 3 笔记本,将其命名为“乳腺癌分类器”,并导入了一些功能:
步骤 3 —加载数据集
下载并检查 wdbc.data 文件后,我需要将它加载到笔记本中,分配列名并检查前五个示例:
第 4 步—数据争论
在这一步中,我删除了每个属性的“ID”列、标准误差和最差值,以检查分类器如何处理主平均值。
已检查是否有任何要处理的缺失值:
太好了,看起来没有丢失值。当然,我必须确保 na _ 值在加载阶段被识别。接下来,检查数据类型并在需要时进行转换是很重要的。
一切都很好,除了标签列“诊断”,我稍后将映射它的信息。
步骤 5 —数据探索和可视化
数据集中标签列和视图 B 与 M 比率的条形图(1.7: 1)。
打印描述所有数值数据的功能和检查数据统计的摘要。但是,创建箱线图,检查数据分布,并尝试发现一些细节(如异常值)是一个好主意。
我做了一个 for 循环,为按诊断标签分组的所有数字特征创建单独的箱线图。以下是一些例子:“半径”、“面积”和“凹度”:
虽然有轻微的重叠,但我们仍然可以注意到大多数良性细胞的半径(面积)比恶性细胞小。凹度也是如此,良性细胞比恶性细胞的凹度小。此外,还有一些潜在的异常值,我们稍后可能需要处理它们。
直方图绘制,直观显示数据频率和总体数据分布的密度图。创建另一个 for 循环来绘制所有特征。以下是“半径”、“面积”和“凹度”特征:
曲线是正峰度和正偏斜的。显然,这是因为恶性细胞的可用数据较少(检查直方图)。半径和面积密度图中的第二个峰值是由于良性和恶性曲线的累积拟合,而不是由于异常值。我们可以将它们分为以下几类:
我必须记住,一些分类模型需要数据的正态分布。对于散点图,我喜欢对所有特征运行矩阵函数,这样我就可以理解并收集一些见解。此外,我用不同的颜色标记了两个类。为此,我利用了 seaborn 库的一个强大功能:
在本文中,我不会逐一查看每个图表。然而,你可以注意到一些线性关系,例如(半径对凹点),(凹度对紧密度)…等等。半径和分形维数之间似乎存在指数关系。因为面积= π(半径)&周长= 2π(半径),所以它们之间应该具有所示的关系。我们可以用相关性指标来总结所有这些:
步骤 6 —数据转换
我将特性列分配给 X,将标签列“诊断”分配给 y:
接下来,我分割 30%的数据作为我的测试输入和输出,以便稍后对分类器模型进行评分。其余的分配给训练数据集(X_train 和 y_train)
之后,我运行一个著名的无监督降维算法:主成分分析(PCA)。它通过捕捉数据的最大可变性来模拟数据的线性子空间。由于它对最易变的数据很敏感,我标准地缩放了所有的特征,并使它们的方差统一起来。
然后,建立 n _ omponents = 7 的 PCA 模型,将其拟合到训练数据,然后使用 PCA 模型转换测试和训练数据:
步骤 7 —分类建模
我在训练数据上尝试了许多分类算法,并用测试数据对模型进行评分,以了解它们的表现如何。实际上,我得到了许多好的准确率分数,其中之一是通过径向核支持向量分类器(SVC)。通过少量迭代,我设置了以下参数:C= 0.9 和 gamma = 0.063,并用测试数据对模型进行评分:
该模型的得分为:94.7%的准确率。但是我们必须转到交叉验证步骤,以验证模型的准确性,并观察它的表现。
步骤 8 —模型评估
在这里,我对训练数据运行 10 重交叉验证函数。这样,训练数据首先被切割成多个“K”组(在本例中是 10)。然后,训练模型的“K”个版本,每个版本使用“K”个可用集合中的独立的 K-1 个。每个模型都用最后一套来评估,它是一套:
10 倍交叉验证准确度的平均值为:%94.98,AUROC(接收器工作曲线下面积)= 0.99
让我们深入挖掘分类器评估,看看它是如何执行的,特别是恶性类别(映射为 1)。如你所知,假阴性非常低或为零是非常重要的,因为实际上在阳性时错过恶性细胞是非常危险和昂贵的。
利用测试数据集(原始数据的 30%),分类器能够检测所有良性细胞(真阴性),而在预测恶性细胞时,它有 9 个假阴性和 55 个真阳性。此外,让我们检查评分标准:
最后,我将提到一些可能影响模型准确性的优化想法,更重要的是减少假阴性预测。然而,我将期待着收到您的经验丰富的思想和想法,以优化模型,除了整个项目。我相信知识共享,并认为这是提高技能的最佳方式。最后但同样重要的是,这里有一些优化“乳腺癌分类器”的想法:
处理异常值并研究其影响,包括更多数据集,例如:标准误差和最大值,使模型更“偏向”恶性类别以移除假阴性事件,对其他分类模型(如决策树和朴素贝叶斯)进行更多试验,或使用 RandomizedSearchCV 函数试验更多参数..等等。
使用支持向量机(SVM)的乳腺癌分类
原文:https://towardsdatascience.com/breast-cancer-classification-using-support-vector-machine-svm-a510907d4878?source=collection_archive---------1-----------------------
背景:
乳腺癌是世界上女性中最常见的癌症。它占所有癌症病例的 25%,仅在 2015 年就影响了超过 210 万人。当乳房中的细胞开始不受控制地生长时,它就开始了。这些细胞通常形成肿瘤,可以通过 X 射线看到或在乳房区域感觉到肿块。
早期诊断大大增加了存活的机会。对其检测的关键挑战是如何将肿瘤分类为恶性(癌性)或良性(非癌性)。如果肿瘤细胞可以生长到周围组织或扩散到身体的远处,则肿瘤被认为是恶性的。良性肿瘤不会侵犯附近的组织,也不会像恶性肿瘤那样扩散到身体的其他部位。但是,如果良性肿瘤压迫血管或神经等重要结构,就会很严重。
机器学习技术可以显著提高乳腺癌的诊断水平。研究表明,经验丰富的医生可以以 79%的准确率检测癌症,而使用机器学习技术可以达到 91 %(有时高达 97%)的准确率。
项目任务
在这项研究中,我的任务是使用从几个细胞图像中获得的特征将肿瘤分为恶性(癌性)或良性(非癌性)。
从乳腺肿块的细针抽吸(FNA)的数字化图像中计算特征。它们描述了图像中出现的细胞核的特征。
属性信息:
- 识别号
- 诊断(M =恶性,B =良性)
为每个细胞核计算十个实值特征:
- 半径(从中心到周边各点的平均距离)
- 纹理(灰度值的标准偏差)
- 周长
- 面积
- 平滑度(半径长度的局部变化)
- 紧凑性(周长/面积— 1.0)
- 凹度(轮廓凹入部分的严重程度)
- 凹点(轮廓凹陷部分的数量)
- 对称
- 分形维数(“海岸线近似值”-1)
加载 Python 库和乳腺癌数据集
让我们来看看数据框中的数据
功能(列)细分
想象我们特征之间的关系
让我们检查一下我们特征之间的相关性
There is a strong correlation between mean radius and mean perimeter, as well as mean area and mean perimeter
先说数据科学中的建模。
我们说“建模”是什么意思?
根据我们在一个特定的地方住了多长时间和去了一个地方,我们可能对我们所在地区的通勤时间有很好的了解。例如,我们通过地铁、公交车、火车、优步、出租车、拼车、步行、骑自行车等方式去上班/上学。
所有人类都自然地模仿他们周围的世界。
随着时间的推移,我们对交通的观察建立了一个心理数据集和心理模型,帮助我们预测不同时间和地点的交通状况。我们可能使用这种思维模式来帮助计划我们的一天,预测到达时间和许多其他任务。
- 作为数据科学家,我们试图通过使用数据和数学/统计结构,使我们对不同量之间关系的理解更加精确。
- 这个过程叫做建模。
- 模型是对现实的简化,帮助我们更好地理解我们观察到的事物。
- 在数据科学环境中,模型通常由感兴趣的独立变量(或输出)和一个或多个被认为会影响独立变量的因变量(或输入)组成。
基于模型的推理
- 我们可以使用模型进行推理。
- 给定一个模型,我们可以更好地理解自变量和因变量之间或多个自变量之间的关系。
一个心智模型的推理很有价值的例子是:
决定一天中什么时候我们工作得最好或者最累。
预言;预测;预告
- 我们可以使用模型进行预测,或者在给定至少一个自变量的值的情况下估计因变量的值。
- 即使预测不完全正确,它们也是有价值的。
- 好的预测对于各种各样的目的来说都是非常有价值的。
心智模型预测有价值的一个例子:
预测从 A 点到 b 点需要多长时间。
模型预测和推断有什么区别?
- 推断是判断数据和输出之间的关系,如果有的话。
- 预测是基于数据和基于该数据构建的模型对未来情景进行猜测。
在这个项目中,我们将讨论一种叫做支持向量机(SVM)的机器学习模型
分类建模简介:支持向量机(SVM)
什么是支持向量机(SVM)?
支持向量机(SVM)是一种二元线性分类,其决策边界被显式构造以最小化泛化误差。它是一个非常强大和通用的机器学习模型,能够执行线性或非线性分类、回归甚至异常值检测。
SVM 非常适合对复杂的中小型数据集进行分类。
SVM 如何分类?
对于 SVM 的特殊线性可分分类案例,从直觉开始很重要。
如果观察值的分类是**“线性可分”,那么 SVM 符合“决策边界”,它是由每类最近点之间的最大差值定义的。这就是通常所说的“最大边缘超平面(MMH)”**。
支持向量机的优势在于:
- 在高维空间有效。
- 在维数大于样本数的情况下仍然有效。
- 在决策函数中使用训练点的子集(称为支持向量),因此它也是内存高效的。
- 通用:可以为决策函数指定不同的内核函数。提供了通用内核,但是也可以指定定制内核。
支持向量机的缺点包括:
- 如果特征的数量远大于样本的数量,在选择核函数和正则项时避免过拟合是至关重要的。
- 支持向量机不直接提供概率估计,而是使用昂贵的五重交叉验证来计算(参见得分和概率)。
现在我们对建模和支持向量机(SVM)有了更好的理解,让我们开始训练我们的预测模型。
模特培训
从我们的数据集中,让我们创建目标和预测矩阵
- “y”=是我们试图预测的特征(输出)。在这种情况下,我们试图预测我们的“目标”是癌性的(恶性)还是非良性的(良性)。也就是说,我们将在这里使用“目标”功能。
- “X”=剩余列(平均半径、平均纹理、平均周长、平均面积、平均平滑度等)的预测值。)
创建培训和测试数据
既然我们已经为“X”和“y”赋值,下一步就是导入 python 库,它将帮助我们将数据集分成训练和测试数据。
- 训练数据=用于训练模型的数据子集。
- 测试数据=模型以前没有见过的数据子集(我们将使用这个数据集来测试模型的性能)。
让我们将数据分成两部分,80%用于训练,剩下的 20%用于测试。
导入支持向量机(SVM)模型
现在,让我们用“训练”数据集来训练我们的 SVM 模型。
让我们使用训练好的模型,利用我们的测试数据进行预测
下一步是通过与我们已有的输出(y_test)进行比较来检查我们预测的准确性。我们将使用混淆矩阵进行比较。
让我们为分类器在测试数据集上的性能创建一个混淆矩阵。
让我们在热图上可视化我们的混淆矩阵
如我们所见,我们的模型在预测方面做得并不好。它预测有 48 名健康患者患有癌症。我们只达到了 34%的准确率!
让我们探索提高模型性能的方法。
改进我们的模型
我们将尝试的第一个过程是通过标准化我们的数据
数据标准化是一个将所有值纳入范围[0,1]的特征缩放过程
X ' =(X-X _ min)/(X _ max-X _ min)
规范化培训数据
规范化培训数据
现在,让我们用我们的缩放(标准化)数据集来训练我们的 SVM 模型。
利用缩放数据集进行预测
缩放数据集上的混淆矩阵
我们的预测好了很多,只有一个错误预测(预测癌症而不是健康)。我们达到了 98%的准确率!
总结:
本文带我们经历了解释“建模”在数据科学中的含义、模型预测和推理之间的差异、支持向量机(SVM)介绍、SVM 的优点和缺点、训练 SVM 模型以进行准确的乳腺癌分类、提高 SVM 模型的性能以及使用混淆矩阵测试模型准确性的旅程。
如果你想要一个 Jupyter 笔记本格式的这个项目的所有代码,你可以从我的 GitHub 仓库 下载它们。
来源:
- http://scikit-learn.org/stable/modules/svm.html
- http://www.robots.ox.ac.uk/~az/lectures/ml/lect2.pdf
- http://pyml.sourceforge.net/doc/howto.pdf
- https://www.bcrf.org/breast-cancer-statistics
- https://www . cancer . org/cancer/breast-cancer/about/what-is-breast-cancer . html
和 TPOT 一起酝酿一批机器学习
原文:https://towardsdatascience.com/brewing-a-batch-of-machine-learning-with-tpot-2930c376b884?source=collection_archive---------5-----------------------
当处理一个新的数据集时,我经常会考虑以迭代的方式可视化、分析和构建模型的最佳工具。也许我很难理解数据的某些方面。我可能会研究一些致力于类似问题集可视化的 Kaggle 内核,以便收集一些新的想法。我也可能会向一些朋友和同事请教。我继续尝试新的方法来找到一个充分的解决方案。
如果我的模型管道没有产生期望的结果,我可能会做出大量的特征选择、缩放和算法选择。这些选择有些是基于经验,有些是凭直觉。然而,大多数时候我最终做了很多工作,尝试了一系列不同的模型和超参数、特征工程等。
近年来,像 h2o.ai 和 AutoML 这样的工具通过自动化这些更繁琐的任务变得越来越流行。虽然出于教学目的,我偶尔喜欢尝试不同的模型架构,但是在其他情况下,我希望自动化其中的一些选择。虽然这些工具令人印象深刻,但我最近了解到一个开源项目,它将几乎完整的机器学习管道直接送到您的手中:。
TPOT 使用进化框架来优化超参数、选择特性,甚至为您选择算法。方便的是,它利用了几乎所有数据科学家都熟悉和使用的 sklearn 算法。乍一看,TPOT 看起来太强大了,令人难以置信,所以我知道我必须尝试一下。
此外,我最近对进化系统及其在机器学习方面的持续成功非常着迷。这篇博文启发我甚至构建了自己的进化算法来扮演太空入侵者。《走向数据科学》也有一些非常好的文章。当我听说 TPOT 使用 ES 时,我受到了进一步的启发,开始着手一个试验项目。
正如我前面提到的,通常我手头有一项任务,我会为这项工作选择一套工具。在这篇文章中,我打破了这个模式:TPOT 是我唯一的工具,我将收集一个数据集来测试它!我想要一些相对简单的、由开放数据组成的、我热爱的东西。一个辅助目标是让数据足够小,任何人都可以将其加载到笔记本电脑上或在 Kaggle 上使用(如果你感兴趣,这就是我最终存储数据集的地方)。
我对可再生能源和环境感到非常兴奋。在之前的博客帖子中,我使用了来自三藩市的建筑能效公开数据来描述这些数据的趋势。对于这个练习,我想我会利用来自国家可再生能源实验室(NREL)的关于太阳能的邮政编码级别的数据集。我将这些数据与 catalog.data.gov/dataset/zip-code-data 的邮政编码信息结合在一起。
我很快在这个数据集中为我的目标变量寻找一个重要的特征。我决定让 TPOT 决定预测太阳能装置每瓦成本的最佳模型。有几个主要原因:
- 作为一个社会,我们需要从化石燃料快速过渡到碳中性能源。
- 不幸的是,这一切发生得还不够快,尽管与气候变化有着难以置信的代价(人类痛苦、环境等)。
- 幸运的是,可再生能源的成本正在下降。在美国,只有当一项行动与金钱利益相关联时,这种行动才会发生。
Median cost_per_watt at the state level
如果我(或者更确切地说是 TPOT)能够有效地从数据中学习一些能够预测某些地区低每瓦成本的驱动特征,也许这个结果可以在该国的其他地区进一步探索。
我故意不帮 TPOT 提什么东西。我的实验试图确定系统的开箱即用效率。该算法声称可以处理数据科学管道中的几乎每一部分。我写了一个快速的 Kaggle 内核,它加载数据,加入数据,删除一些 nan,释放 TPOT 的愤怒。我们可以期待什么?来自 TPOT 的文件:
- 对于默认的 TPOT 参数,100 个“基因样本”将在您的数据集上运行 100 代,每代都由各种算法和超参数组成
- 每个样本(在这种情况下是 10,000 个独特的样本)将进行 10 次交叉验证。如果你愿意,你甚至可以使用一个自定义的损失函数!
- 如果找到了最佳管道,将输出 CV 分数和管道参数。
API 调用非常简单,看起来很像您在 Python 中使用的任何 ML 算法:
Pretty simple!
我肯定会建议在多个 CPU 上运行这个程序( n_jobs=-1 ),然后去做午饭,因为这可能需要很长时间。在免费的 Kaggle 机器上,我保持了较小的世代和群体规模,并且仍然需要将我的特征空间减少到只有 5-10 个相关特征。TPOT 的文档警告用户可能需要一整天的时间来实现融合模型!在会话结束时,我收到了如下输出:
Best negative Mean Squared Error: -0.137
现在我可以去 sklearn ,做一点功能工程,然后使用相对简单的 ExtraTreesRegressor 来构建这个模型。上述模型仅使用了 OpenPV 数据集中的要素样本。后来的一个测试,仅使用邮政编码数据,表现不尽如人意。
然而,这篇文章的目的并不是深入这个特殊的数据问题,所以我们不会进一步讨论它。这应该都是关于 TPOT 的!总的结论是,TPOT 值得进一步探索。积极的一面是:
- 它容易使用,非常危险。它与您日常的 Python 数据工作流相集成。一个完全的初学者可以加载并使用它。
- 它探讨了多项式特性、大量超参数和各种组合的算法。
- 一旦管道决定了一个模型,你可以稍后在 sklearn 中构建它,而不用再使用 TPOT。
- 文档是以简单明了的方式编写的。
- 您可以轻松地提供自定义损失函数。
我发现的唯一真正的缺点是我在使用 Kaggle 内核时遇到的速度和内存问题。但是,这真的是一个问题吗?在一个装备更加完善的数据科学平台上,TPOT 真的可以大放异彩。
在过去的几年里,随着 AutoML 变得越来越强大,我已经听到了数据科学职业生涯的厄运。有一些令人信服的反驳观点没有得到太多的关注。数据科学家的工作流程中有哪一块没有包括在 TPOT 管道中?*数据清洗。*在我的日常工作中,这一项就能消耗我 80%的时间和精神能量。
如何制定正确的问题?在类似 Kaggle 的竞赛中,问题集和数据都是为数据科学家精心准备的,这很少被考虑。在商业环境中工作时,简单地问正确的问题是成功项目的重要组成部分。你在优化什么?企业需要什么?你如何向决策者解释这一点?TPOT 对此没有帮助。
总的来说,TPOT 和 AutoML 将使数据科学家更有效率。计算是廉价的,但我们的时间是宝贵的。使用这些工具来改进您的工作流程,花时间问正确的问题,有效地清理/分析数据,并交流您的结果。网格搜索超参数不是对你时间的有效利用。我肯定会再次使用 TPOT,我希望你也能尝试一下。如果你喜欢这篇文章,请看看我的其他帖子!我感谢你的读者。
在 AWS SageMaker 上酝酿定制 ML 模型
原文:https://towardsdatascience.com/brewing-up-custom-ml-models-on-aws-sagemaker-e09b64627722?source=collection_archive---------1-----------------------
最近爱上了 SageMaker。仅仅是因为它太方便了!我真的很喜欢他们的方法,向客户隐藏所有的基础设施需求,让他们专注于解决方案中更重要的 ML 方面。只需在这里或那里点击几下并输入,瞧,您就有了一个准备好生产的模型,每天可以处理 1000 个(如果不是数百万个)请求。如果你需要一个关于 SageMaker 的好的介绍,看看下面这个非亚马逊公司的视频吧!
那么可能会出什么问题呢?
但是当您试图在自己的 docker 容器中设置和创建自己的模型来执行定制操作时,麻烦就来了!这不像一开始就用 SageMaker 构建一切那样简单流畅。
为什么您需要定制模型?
您需要自己的定制模型的原因有很多。你可能是:
- 使用一些特定的 python 库版本,而不是最新的版本(例如 TensorFlow)
- 使用 SageMaker 上不可用的库
继续之前…
在继续之前,请确保您具备以下条件。
- Docker 安装并运行在您的操作系统中
- Docker 工作原理的基本知识
我们如何做到这一点?
现在有了一个好的背景,让我们深入了解为 SageMaker 做准备的细节。教程将有三个不同的部分。
- 用你的代码创建一个 docker 图像
- 在本地测试 docker 容器
- 在 Amazon ECR(弹性容器存储库)上部署映像
让我在这里把这些观点具体化。首先,您创建一个 docker 映像,其中包含库和代码以及其他需求(例如对端口的访问)。然后,从该映像创建一个容器并运行该容器。然后,您用容器中的一小块数据测试代码/模型。成功测试后,您将 docker 映像上传到 ECR。然后,您可以将该图像指定为 ML 模型,并通过 Amazon SageMaker 将其用于训练/预测。
此外,我将使用这个教程/指南作为这个博客的参考框架。真的是很好的教程。我想重新创作这篇博文的原因很少:
- 如果你只依赖 scikit-learn,这是一个很好的教程。我想到用 XGBoost 创建一个容器,所以我们必须对 Docker 容器做一些修改。
- 我想要 Python 3 而不是 Python 2,原因显而易见。
- 我还觉得这里和那里缺少一些细节(尤其是在本地测试时)。
为了演示这个过程,我将在虹膜数据集上训练一个 XGBoost 分类器。你可以在这里 找到所有代码 的 Github 库。
Docker 概述
你知道还有什么比 SageMaker 更神奇吗?码头工人。Docker 极其强大,便携,快速。但这不是讨论原因的地方。所以让我们直接开始设置吧。使用 Docker 时,您有一套清晰的步骤:
- 创建一个包含代码/模型的文件夹和一个名为
Dockerfile
的特殊文件,该文件包含用于创建 docker 图像的配方 - 运行
docker build -t <image-tag>
创建一个 docker 映像 - 通过运行
docker run <image>
来运行图像 - 使用
docker push <image-tag>
将 docker 映像推送到将存储该映像的某个存储库(例如 dockerhub 或 AWS ECR 存储库)
SageMaker 兼容 Docker 容器概述
注意,SageMaker 要求图像有一个特定的文件夹结构。SageMaker 寻找的文件夹结构如下。主要有两个父文件夹/opt/program
存放代码,和/opt/ml
存放工件。请注意,我已经模糊掉了一些您可能不需要编辑的文件(至少对于本练习来说是这样),它们超出了本教程的范围。
Adapted from of awslabs/ amazon-sagemaker-examples Github
Program structure in the Docker container
现在让我们详细讨论一下这些实体中的每一个。首先,opt/ml
是所有人工制品将要存放的地方。现在让我们来谈谈每个子目录。
目录:/opt/ml
input/data
是存储模型数据的目录。它可以是任何与数据相关的文件(假设您的 python 代码可以读取数据,并且容器具有这样做所需的库)。这里的<channel_name>
是模型将要使用的一些消耗性输入源的名称。
model
是模型将要驻留的地方。您可以将模型放在它自己的容器中,您可以指定一个 URL (S3 桶位置),模型工件以一个tar.gz
文件的形式保存在那里。例如,如果您有亚马逊 S3 桶中的模型工件,您可以在 SageMaker 上的模型设置期间指向那个 S3 桶。然后,当您的模型启动并运行时,这些模型工件将被复制到model
目录中。
最后,output
是控制器,如果失败,它将存储请求/任务失败的原因。
目录:/opt/program
现在让我们深入研究我们模型的精华部分;算法。这应该可以在我们 Docker 容器的/opt/program
目录中找到。关于train
、serve
和predictor.py
,我们需要小心的主要有三个文件。
train
保存用于训练模型和存储训练模型的逻辑。如果train
文件运行无故障,它将保存一个模型(即 pickle 文件)到/opt/ml/model
目录。
serve
essential 使用 Flask 将predictor.py
中编写的逻辑作为 web 服务运行,它将监听任何传入的请求,调用模型,做出预测,并返回带有预测的响应。
Dockerfile 文件
这是支持 Docker 容器中可用内容的文件。这意味着这个文件极其重要。所以让我们来看看里面。如果您已经熟悉如何编写 Dockerfile 文件,这是非常简单的。不过,还是让我带你简单参观一下吧。
FROM
指令指定一个基本图像。所以这里我们使用一个已经构建好的 Ubuntu 映像作为我们的基础映像。- 接下来使用
RUN
命令,我们使用apt-get install
安装几个包(包括 Python 3.5) - 然后再次使用
RUN
命令,我们安装 pip,接着是numpy
、scipy
、scikit-learn
、pandas
、flask
等。 - 随后,我们使用
ENV
命令在 Docker 容器中设置了几个环境变量。我们需要将我们的/opt/program
目录添加到path
变量中,这样,当我们调用容器时,它会知道我们的算法相关文件在哪里。 - 最后但同样重要的是,我们将包含算法相关文件的文件夹
COPY
到/opt/program
目录,然后将其设置为WORKDIR
创建我们自己的 Docker 容器
首先,我将使用aw slaps Github 库提供的惊人包的修改版本(链接此处为)。这个原始存储库包含了我们运行 SageMaker 模型所需的所有文件,因此只需编辑这些文件,使其符合我们的需求。将原始链接中的内容下载到一个名为xgboost-aws-container
的文件夹中,如果你想从头开始,或者,你可以摆弄我的版本。
注意:如果你是 Windows 用户,并且你是那些运行过时的 Docker 工具箱的不幸者之一,确保你使用了
C:\Users
目录中的某个目录作为你的项目主文件夹。否则,将文件夹挂载到容器时,您会遇到非常糟糕的体验。
对现有文件的更改
- 将
decision-trees
文件夹重命名为xgboost
- 编辑存储库中提供的
train
文件。我本质上所做的是,我导入了xgboost
并将决策树模型替换为XGBClassifier
模型。注意,一旦出现异常,就会被写入*/opt/ml/output*
文件夹中的故障文件。因此,您可以自由地包含尽可能多的描述性异常,以确保您知道程序失败时哪里出错了。 - 编辑存储库中提供的
predictor.py
文件。本质上,我所做的类似于在train
上所做的改变。我导入了xgboost
,把分类器改成了XGBClassifier
。 - 打开你的
Dockerfile
进行以下编辑。
我们使用python3.5
而不是python
,并根据 xgboost 的要求添加了libgcc-5-dev
。
RUN apt-get -y update && apt-get install -y — no-install-recommends \
wget \
python3.5 \
nginx \
ca-certificates \
libgcc-5-dev \
&& rm -rf /var/lib/apt/lists/*
我们将询问numpy
、scikit-learn
、pandas
、xgboost
的具体版本,以确保它们相互兼容。指定您想要使用的库的版本的另一个好处是,您知道它不会仅仅因为某个库的新版本与您的代码不兼容而中断。
RUN wget [https://bootstrap.pypa.io/3.3/get-pip.py](https://bootstrap.pypa.io/3.3/get-pip.py) && python3.5 get-pip.py && \
pip3 install numpy==1.14.3 scipy scikit-learn==0.19.1 xgboost==0.72.1 pandas==0.22.0 flask gevent gunicorn && \
(cd /usr/local/lib/python3.5/dist-packages/scipy/.libs; rm *; ln ../../numpy/.libs/* .) && \
rm -rf /root/.cache
然后,我们将拷贝命令更改为以下内容
COPY xgboost /opt/program
建立码头工人形象
现在打开您的 Docker 终端(如果在 Windows 上,否则是 OS 终端)并转到包的父目录。然后运行以下命令。
docker build -t xgboost-tut .
这应该建立我们需要的一切形象。确保映像是通过运行,
docker images
您应该会看到如下所示的内容。
运行 Docker 容器来训练模型
现在是运行容器的时候了,开始执行下面的命令。
docker run --rm -v $(pwd)/local_test/test_dir:/opt/ml xgboost-tut train
让我们来分解这个命令。
--rm
:表示当你离开集装箱时,集装箱将被销毁
-v <host location>:<container location>
:将卷安装到容器中的所需位置。警告 : Windows 用户,如果你选择C:\Users
之外的任何东西,你都会有麻烦。
xgboost-tut
:图像的名称
train
:随着容器的启动,将自动开始运行/opt/program
目录下的火车文件。这就是为什么指定/opt/program
作为PATH
变量的一部分很重要。
事情应该运行良好,您应该会看到类似下面的输出。
Starting the training.
Training complete.
您还应该在您的<project_home>/local_test/test_dir/model
目录中看到xgboost-model.pkl
文件。这是因为我们将local_test/test_dir
目录挂载到了容器的/opt/ml
中,所以无论/opt/ml
发生什么都将反映在test_dir
中。
在本地测试容器以供食用
接下来,我们要看看服务(推理)逻辑是否正常工作。现在让我在这里再次警告,如果你错过了以上!如果您是 Windows 用户,请注意正确安装宗卷。为了避免任何不必要的问题,确保您在C:\Users
文件夹中选择一个文件夹,作为您的项目主目录。
docker run --rm --network=host -v $(pwd)/local_test/test_dir:/opt/ml xgboost-tut serve
让我指出我们在 Docker run 命令中指定的一个特殊选项。
--network=host
:表示主机的网络栈将被复制到容器中。所以这就像在本地机器上运行一些东西。这是检查 API 调用是否正常工作所必需的。
注意:我用的是
--network=host
,因为-p <host_ip>:<host_port>:<container_port>
不工作(至少在 Windows 上)。我推荐使用-p 选项(如果有效的话),如下所示。警告:仅使用其中一个命令,不要同时使用两个。但我将假设--network=host
选项继续前进。
docker run --rm -p 127.0.0.1:8080:8080 -v $(pwd)/local_test/test_dir:/opt/ml xgboost-tut serve
serve
:这是调用推理逻辑的文件
这将向您显示类似下面的输出。
现在,为了测试我们是否能成功 ping 通服务,运行以下命令(在单独的终端窗口中)。
curl http://<docker_ip>:8080/ping
您可以通过以下方式找到 Docker 机器的 IP
docker-machine ip default
这个 ping 命令应该在主机端和服务器端产生两条消息。类似下面的东西。
如果这一切进展顺利(我非常希望如此),直到这一点。恭喜你!您几乎已经建立了一个 SageMaker 兼容的 Docker 映像。直播前我们还需要做一件事。
现在让我们试试更刺激的东西。让我们试着通过我们的 web 服务做一个预测。为此,我们将使用位于local_test
文件夹中的predict.sh
文件。请注意,我已经对它进行了修改,以适应我的需求,这意味着它不同于原始 awslabs 存储库中提供的那个。确切地说,我引入了一个新的用户提示参数,除了原始文件中的 IP 地址和端口之外,它还会接受这些参数。我们使用下面的命令调用修改后的[predict.sh](https://github.com/thushv89/xgboost-aws-container/blob/master/local_test/predict.sh)
文件。
./predict.sh [<container_ip>:<](http://192.168.99.100:8080)port> payload.csv text/csv
这里我们使用payload.csv
中的数据调用推理 web 服务,并说它是一个 csv 文件。它应该会返回以下内容。它将其中的数据点标识为属于类setosa
。
* timeout on name lookup is not supported
* Trying <container_ip>…
* TCP_NODELAY set
* Connected to <container_ip> (<container_ip>) port <port> (#0)
> POST /invocations HTTP/1.1
> Host: <container_ip>:<port>
> User-Agent: curl/7.55.0
> Accept: */*
> Content-Type: text/csv
> Content-Length: 23
>
* upload completely sent off: 23 out of 23 bytes
< HTTP/1.1 200 OK
< Server: nginx/1.10.3 (Ubuntu)
< Date: <date and time> GMT
< Content-Type: text/csv; charset=utf-8
< Content-Length: 7
< Connection: keep-alive
<
setosa
* Connection #0 to host <container_ip> left intact
把它推到控制室
好吧。所以努力终于有了回报。是时候将我们的图像推送到亚马逊弹性容器库(ECR)了。在此之前,请确保您在 ECR 中创建了一个存储库,以便将图像推送到其中。如果你有一个 AWS 账户,这很简单。
从 AWS 仪表板转到 ECR 服务,然后单击“创建存储库”
创建存储库后,在存储库中,您应该能够看到完成推送 ECR 的指令。
注意:您也可以使用存储库中提供的 build_and_push.sh。但是我个人觉得自己做事情更舒服。推动存储库其实没有那么多步骤。
首先,您需要获得登录 ECR 的凭证
aws ecr get-login — no-include-email — region <region>
它应该会返回一个输出,
docker login …
复制粘贴该命令,现在您应该登录到 ECR。接下来,您需要重新标记您的图像,以便能够正确地推送至 ECR。
docker tag xgboost-tut:latest <account>.dkr.ecr.<region>.amazonaws.com/xgboost-tut:latest
现在是时候将图像推送到您的存储库了。
docker push <account>.dkr.ecr.<region>.amazonaws.com/xgboost-tut:latest
现在图像应该出现在您的 ECR 存储库中,标签为latest
。困难的部分已经完成,接下来您需要创建一个 SageMaker 模型并指向图像,这就像用 SageMaker 本身创建一个模型一样简单。所以我不会在博文中详述这些细节。
你可以在这里 找到所有代码 的 Github 库。
结论
这是一次漫长的旅行,但(在我看来)很有收获。所以我们在本教程中做了以下工作。
- 首先,我们理解了为什么我们可能需要制作我们自己的定制模型
- 然后我们检查了 SageMaker 运行容器所需的 Docker 容器的结构。
- 然后,我们讨论了如何创建容器的 Docker 映像
- 接下来是如何构建映像和运行容器
- 接下来,我们讨论了在推出之前,如何在本地计算机上测试容器
- 最后,我们讨论了如何将图像推送到 ECR,以便通过 SageMaker 使用。
特别感谢做出原始 Github 库的贡献者给了我一个令人敬畏的起点!最后但重要的是,如果你喜欢这篇文章,请留下一些掌声:)
想在深度网络和 TensorFlow 上做得更好?
检查我在这个课题上的工作。
[1] (书)TensorFlow 2 在行动——曼宁
[2] (视频教程)Python 中的机器翻译 — DataCamp
[3] (书)TensorFlow 中的自然语言处理 1 — Packt
新的!加入我的新 YouTube 频道
如果你渴望看到我关于各种机器学习/深度学习主题的视频,请确保加入 DeepLearningHero 。
医学图像分析和深度学习简介
原文:https://towardsdatascience.com/brief-intro-to-medical-image-analysis-and-deep-learning-9d8e5ef358e0?source=collection_archive---------23-----------------------
我最近开始从事一个与医学图像分析相关的项目,在寻找关于图像分析及其医学应用的资源时,我觉得我们通常没有一些关于这些信息的合适文章。在本文中,我们将简要介绍过去如何分析医学图像,以及自从引入深度学习以来发生了什么变化。对于图像分析,我们通常使用 CNN (卷积神经网络),虽然在这里解释它会使整篇文章变得繁琐,但我将提供一些链接来正确解释CNN。
一旦有可能扫描医学图像并将其加载到计算机中,研究人员就试图建立系统来自动分析这些图像。最初,从20 世纪 70 年代到20 世纪 90 年代,医学图像分析是通过顺序应用低级像素处理(边缘和线检测器过滤器)和数学建模来构建一个基于规则的系统,该系统只能解决特定的任务。同时还有一些基于 if-else 规则的代理,在人工智能领域很流行,通常被称为 GOFAI (老式人工智能)代理。
*20 世纪 90 年代末,*监督技术开始流行,其中训练数据用于训练模型,并且它们在医学图像分析领域变得越来越流行。例子可能包括活动形状模型、图谱方法。这种模式识别和机器学习仍然流行,但引入了一些新的想法。因此,我们可以看到从人类设计的系统到计算机基于示例数据训练的系统的转变。计算机算法现在有足够的能力来确定边缘和重要特征,以分析图像并给出最佳结果。
迄今为止,最成功的图像分析模型是卷积神经网络(CNN)。单个 CNN 模型包含许多不同的层,这些层在较浅的层上识别边缘和简单特征,在较深的层上识别更深的特征。用滤波器(有人称之为核)对图像进行卷积,然后应用池化,这个过程可以在一些层上继续,最后获得可识别的特征。CNN 的工作从80 年代就开始了,在 1995 年就已经应用于医学图像分析。CNN 的第一个真实应用出现在LeNetT11【1998】中,用于手写数字识别。尽管早期取得了一些小的成功,但 CNN 获得了动力,直到引入了深度学习中的改进训练算法。GPU的引入有利于该领域的研究,自 ImageNet 挑战赛引入以来,可以看到此类模型的快速发展。
Illustration of CNN (Convolutional Neural Network)
在计算机视觉领域,CNN 已经成为首选。医学图像分析社区已经注意到这些关键的发展。然而,从使用手工特征的系统到从数据本身学习特征的系统的过渡是渐进的。深度学习在医学图像分析中的应用首先开始出现在研讨会和会议上,然后出现在期刊上。如图所示,论文数量在 2015 和 2016 有所增长。
- 分类:这是医学图像分析中最早使用深度学习的领域之一。诊断图像分类包括诊断图像的分类,在这种设置下,每个诊断检查都是样本,数据量小于计算机视觉的数据量。对象或病变分类通常集中于将医学图像的一部分分类成两个或多个类别。对于这些任务中的许多,精确分类需要关于病变外观和位置的局部和全局信息。
- 检测:器官/病变等解剖对象定位是分割任务的重要预处理部分。图像中对象的定位需要图像的 3D 解析,已经提出了几种算法来将 3D 空间转换为 2D 正交平面的组合。使用计算机辅助技术检测医学图像中的病变,提高检测精度或减少人类的检测时间,已经成为一种长期的研究趋势。有趣的是,第一个这样的系统是在 1995 年开发的,它使用一个有 4 层的 CNN 来检测 x 光图像中的结节。
- 分割:医学图像中器官和其他子结构的分割允许与形状、大小和体积相关的定量分析。分割的任务通常被定义为识别定义感兴趣的轮廓或对象的一组像素。病灶的分割结合了在深度学习算法的应用中对象检测以及器官和子结构分割的挑战。肿瘤分割与对象检测共有的一个问题是类别不平衡,因为图像中的大多数像素来自非患病类别。
- 配准:有时也称为空间对准,是一种常见的图像分析任务,其中计算从一幅图像到另一幅图像的坐标变换。这通常是在迭代框架中执行的,其中假设了特定类型的转换,并且优化了预先训练的度量。尽管病变检测和对象分割被视为深度学习算法的主要用途,但研究人员发现,深度网络有利于获得最佳的配准性能。
- 医学成像中的其他任务:深度学习在医学成像中还有一些其他用途。基于内容的图像检索 ( CBIR )是一种在大型数据库中进行知识发现的技术,为病历和理解罕见疾病提供类似的数据检索。图像生成和增强是另一项使用深度学习来提高图像质量、标准化图像、数据完善和模式发现的任务。将图像数据与报告结合起来是另一项任务,在现实世界中似乎有非常大的应用规模。这导致了两个不同的研究领域(1)利用报告来提高图像分类的准确性。(2)从图像生成文本报告。
Number of papers in different application areas of Deep Learning in medical imaging
很明显,深度学习在医学图像分析中的应用存在许多挑战,大数据集的不可用性经常被提到。然而,这种观点只是部分正确。在放射科使用 PACS 系统已经成为大多数西方医院的惯例,它们装满了数百万张图像。我们还可以看到大型公共数据集是由组织提供的。因此,主要的挑战不是图像数据本身的可用性,而是这些图像的标记。传统上 PACS 系统存储放射科医生描述他们发现的自由文本报告。以自动化的方式将这些报告转换成准确的注释或适当的标签,这本身就是一个需要复杂的文本挖掘技术的研究课题。
在医学成像中,分类或分割通常表现为二元任务:正常对异常,对象对背景。然而,这通常是一种粗略的简化,因为两个类都是高度异构的。例如,正常类别通常包括完全正常的组织,但也包括几种良性发现,这可能是罕见的。这导致了一个系统非常善于排除最常见的正常子类,但在几个罕见的子类上却失败得很惨。一个直接的解决方案是通过为系统提供所有可能子类的详细注释,将系统变成多类系统。再次,这是另一个问题,专业地标记所有的类,这似乎不实际。
在医学图像分析中,有用的信息不仅仅包含在图像本身中。医生通常会查看患者的病史、年龄和其他属性,以做出更好的决定。已经进行了一些研究,以在深度学习中包括除图像之外的这些特征,但结果显示,这并不那么有效。挑战之一是平衡深度学习网络中的成像特征与临床特征的数量,以防止临床特征被忽略。
原载于 2018 年 10 月 16 日medium.com。
将计算机视觉数据集纳入单一格式:迈向一致性
原文:https://towardsdatascience.com/bringing-computer-vision-datasets-to-a-single-format-step-towards-consistency-870b8323bcf0?source=collection_archive---------7-----------------------
当你有一个好的工作算法,并且你想在一些数据集上测试你的杰作时,几乎总是要在数据的实际加载和预处理上花费相当多的时间。如果我们能够以一种单一的格式和一致的方式访问数据(例如,总是将训练图像存储在关键字“train/image”下),那就太好了。
在这里,我将分享一个由我编写的 github repo ,它将几个流行的数据集转换为 HDF5 格式。当前支持以下数据集。
- ILSVRC ImageNet
- CIFAR 10 和 CIFAR 100 数据集
- 数据集
这段代码是做什么的?
所以这个仓库做了很多事情。首先让我告诉你组织。代码库非常简单。每个数据集都有一个文件来预处理数据并另存为 HDF5(例如,对于 Imagenet,我们有preprocess_imagenet.py
、CIFAR-10 和 CIFAR-100,我们有preprocess_cifar.py
,对于 SVHN,我们有preprocess_svhn.py
)。实际上,每个文件都执行以下操作:
- 将原始数据载入内存
- 执行所需的任何整形,以使数据达到适当的维度(例如,cifar 数据集将图像作为向量给出,因此需要将其转换为三维矩阵)
- 创建一个 HDF5 文件来保存数据
- 使用 Python 多重处理库,并根据用户规范处理每个图像
下面我将告诉 ImageNet 文件是做什么的。这是最复杂的文件,其他的都很简单。
这里我讨论一下preprocess_imagenet.py
文件的作用。这基本上将 ImageNet 数据的子集保存为 HDF5 文件。该子集是属于许多自然类别(例如植物、猫)和人工类别(例如椅子、桌子)的数据。此外,您可以在保存数据时规范化数据。
一旦运行脚本,save_imagenet_as_hdf5(...)
函数就会接管。该函数首先在有效的数据集文件名和标签之间创建一个映射(即build_or_retrieve_valid_filename_to_synset_id_mapping(...)
)。接下来,它用write_art_nat_ordered_class_descriptions(...)
或retrieve_art_nat_ordered_class_descriptions(...)
隔离与 ImageNet 数据集(1000 个类)的分类问题相关的类。然后我们使用write_selected_art_nat_synset_ids_and_descriptions(...)
方法将选择的人工和自然类信息写入一个 xml 文件。
接下来,我们扫描训练数据中的所有子目录,并将所有相关数据点放入内存。接下来,我们创建 HDF 文件来保存数据。这是通过save_train_data_in_filenames(...)
功能完成的。数据将保存在以下注册表项下:
/train/images/
/train/images/
/valid/images/
/valid/images/
稍后访问和加载数据
您以后可以通过以下方式访问这些保存的数据:
dataset_file = h5py.File(“data” + os.sep + “filename.hdf5”, “r”)train_dataset, train_labels = dataset_file[‘/train/images’], dataset_file[‘/train/labels’]test_dataset, test_labels = dataset_file[‘/test/images’], dataset_file[‘/test/labels’]
编码和进一步阅读
代码可以在这里获得,你可以在我的博客文章中查看关于代码做什么以及如何运行的完整描述。
**注意:**如果您在运行代码时看到任何问题或错误,请通过评论或在 Github 页面上打开问题让我知道。这将有助于我改进代码,消除任何讨厌的错误。
干杯!
为数据科学带来 Jupyter 笔记本电脑的最佳性能
原文:https://towardsdatascience.com/bringing-the-best-out-of-jupyter-notebooks-for-data-science-f0871519ca29?source=collection_archive---------0-----------------------
使用这些提示和技巧提高 Jupyter 笔记本的工作效率。
Photo by Aaron Burden on Unsplash
重新想象 Jupyter 笔记本可以是什么,可以用它做什么。
旨在为其 1.3 亿观众提供个性化内容。网飞的数据科学家和工程师与他们的数据交互的重要方式之一是通过 Jupyter 笔记本。笔记本电脑利用协作、可扩展、可扩展和可复制的数据科学。对于我们中的许多人来说,Jupyter 笔记本电脑是快速原型制作和探索性分析的事实平台。然而,这并不像看上去那样简单。Jupyter 的许多功能有时隐藏在幕后,没有得到充分开发。让我们尝试探索 Jupyter 笔记本电脑的功能,这些功能可以提高我们的工作效率。
目录
- 执行 Shell 命令
- Jupyter 主题
- 笔记本扩展
- Jupyter 小工具
- Qgrid
- 幻灯片
- 嵌入 URL、pdf 和 Youtube 视频
1.执行 Shell 命令
笔记本是新壳
外壳是一种与计算机进行文本交互的方式。最流行的 Unix shell 是 Bash(Bourne Again SHell)。Bash 是大多数现代 Unix 实现和大多数为 Windows 提供类 Unix 工具的包中的默认 shell。
现在,当我们使用任何 Python 解释器时,我们需要定期在 shell 和 IDLE 之间切换,以防我们需要使用命令行工具。然而,Jupyter 笔记本通过在命令前添加一个额外的**!**
,让我们可以轻松地从笔记本中执行 shell 命令。任何在命令行运行的命令都可以在 IPython 中使用,只需在前面加上**!**
字符。
In [1]: !ls
example.jpeg list tmpIn [2]: !pwd
/home/Parul/Desktop/Hello World Folder'In [3]: !echo "Hello World"
Hello World
我们甚至可以像下面这样在 shell 之间传递值:
In [4]: files= !lsIn [5]: **print**(files)
['example.jpeg', 'list', 'tmp']In [6]: directory = !pwdIn [7]: **print**(directory)
['/Users/Parul/Desktop/Hello World Folder']In [8]: type(directory)
IPython.utils.text.SList
注意,返回结果的数据类型不是列表。
2.Jupyter 主题
将你的 Jupyter 笔记本主题化!
如果你是一个盯着 Jupyter 笔记本的白色背景会感到厌烦的人,那么主题就是为你准备的。主题也增强了代码的表现形式。你可以在这里找到更多关于 Jupyter 主题的信息。让我们开始工作吧。
安装
pip install jupyterthemes
可用主题列表
jt -l
目前,可用的主题有 chesterish,3 年级,gruvboxd,gruvboxl monokai,oceans16,onedork,solarizedd,solarizedl。
# **selecting a particular theme**jt -t <name of the theme># **reverting to original Theme**jt -r
- 每次更改主题时,您都必须重新加载 jupyter 笔记本,才能看到效果。
- 通过在命令前放置“
*!*
”,也可以从 Jupyter 笔记本中运行相同的命令。
Left: original | Middle: Chesterish Theme | Right: solarizedl theme
3.笔记本扩展
扩展可能性
笔记本扩展功能让您超越 Jupyter 笔记本的常规使用方式。笔记本扩展(或 nbextensions)是 JavaScript 模块,您可以将其加载到笔记本前端的大多数视图中。这些扩展修改了用户体验和界面。
安装
安装 conda:
conda install -c conda-forge jupyter_nbextensions_configurator
或使用画中画:
pip install jupyter_contrib_nbextensions && jupyter contrib nbextension install#incase you get permission errors on MacOS,pip install jupyter_contrib_nbextensions && jupyter contrib nbextension install --user
现在启动一个 Jupyter 笔记本,你应该能看到一个有很多选项的 NBextensions 标签。点击你想要的,看看奇迹发生。
如果你找不到标签,可以在菜单**Edit**
下找到第二个小的 nbextension。
让我们讨论一些有用的扩展。
1.内地
****腹地为代码单元格中的每一次按键启用代码自动完成菜单,而不仅仅是用 tab 调用它。这使得 Jupyter notebook 的自动补全像其他流行的 ide 一样,比如 PyCharm。
2.片段
该扩展向笔记本工具栏添加了一个下拉菜单,允许将代码片段单元格轻松插入到当前笔记本中。
3.分裂细胞笔记本
这个扩展将笔记本的单元格分开,然后彼此相邻放置。
4.目录
这个扩展使得能够收集所有正在运行的标题,并在一个浮动窗口中显示它们,作为一个侧边栏或一个导航菜单。该扩展也是可拖动、可调整大小、可折叠和可停靠的。
5.可折叠标题
可折叠标题 a 允许笔记本拥有可折叠的部分,由标题分隔。因此,如果你的笔记本中有很多脏代码,你可以简单地折叠它,以避免反复滚动。
6.Autopep8
只需点击一下,Autopep8 就可以帮助重新格式化/修饰代码单元格的内容。如果你厌倦了一次又一次地敲空格键来格式化代码,autopep8 就是你的救星。
4.Jupyter 小工具
让笔记本互动
小部件是多事件的 python 对象,在浏览器中有一个表示,通常是像滑块、文本框等控件。小部件可以用来为笔记本电脑构建交互式图形用户界面**。**
装置
# **pip**
pip install ipywidgets
jupyter nbextension enable --py widgetsnbextension# **Conda** conda install -c conda-forge ipywidgets#Installing **ipywidgets** with conda automatically enables the extension
让我们来看看一些小部件。完整的细节,你可以访问他们的 Github 库。
交互
interact
函数(ipywidgets.interact
)自动创建一个用户界面(UI)控件,用于交互式地浏览代码和数据。这是开始使用 IPython 小部件的最简单的方法。
# Start with some imports!from ipywidgets import interact
import ipywidgets as widgets
1.基本部件
def f(x):
return x# Generate a slider
interact(f, x=10,);
# Booleans generate check-boxes
interact(f, x=True);
# Strings generate text areas
interact(f, x='Hi there!');
2.高级小部件
这里列出了一些有用的高级小部件。
播放小工具
Play 小部件有助于通过以一定速度迭代整数序列来执行动画。下面滑块的值与播放器相关联。
play = widgets.Play(
# interval=10,
value=50,
min=0,
max=100,
step=1,
description="Press play",
disabled=False
)
slider = widgets.IntSlider()
widgets.jslink((play, 'value'), (slider, 'value'))
widgets.HBox([play, slider])
日期选择器
日期选择器小部件可以在 Chrome 和 IE Edge 中工作,但目前不能在 Firefox 或 Safari 中工作,因为它们不支持 HTML 日期输入字段。
widgets.DatePicker(
description='Pick a Date',
disabled=False
)
颜色选择器
widgets.ColorPicker(
concise=False,
description='Pick a color',
value='blue',
disabled=False
)
标签页
tab_contents = ['P0', 'P1', 'P2', 'P3', 'P4']
children = [widgets.Text(description=name) for name in tab_contents]
tab = widgets.Tab()
tab.children = children
for i in range(len(children)):
tab.set_title(i, str(i))
tab
5.Qgrid
使数据帧直观
Qgrid 也是一个 Jupyter 笔记本小部件,但主要集中在数据帧上。它使用 SlickGrid 在 Jupyter 笔记本中呈现熊猫数据帧。这使您可以通过直观的滚动、排序和过滤控件来浏览数据框,并通过双击单元格来编辑数据框。Github 库包含了更多的细节和例子。
装置
使用 pip 安装:
pip install qgrid
jupyter nbextension enable --py --sys-prefix qgrid# only required if you have not enabled the ipywidgets nbextension yet
jupyter nbextension enable --py --sys-prefix widgetsnbextension
使用 conda 安装:
# only required if you have not added conda-forge to your channels yet
conda config --add channels conda-forgeconda install qgrid
6.幻灯片
沟通时代码是伟大的。
笔记本是教授和编写可解释代码的有效工具。然而,当我们想要展示我们的作品时,我们要么展示整个笔记本(包括所有代码),要么借助 powerpoint。不再是了。Jupyter 笔记本可以轻松转换成幻灯片,我们可以轻松选择在笔记本上显示什么和隐藏什么。
有两种方法可以将笔记本转换成幻灯片:
1.Jupyter 笔记本的内置滑动选项
打开一个新笔记本,导航到视图→单元格工具栏→幻灯片。每个单元格顶部会出现一个浅灰色条,您可以自定义幻灯片。
现在转到笔记本所在的目录,输入以下代码:
jupyter nbconvert *.ipynb --to slides --post serve
*# insert your notebook name instead of* **.ipynb*
幻灯片在端口 8000 显示。另外,目录中会生成一个.html
文件,您也可以从那里访问幻灯片。
如果有主题背景,看起来会更有格调。让我们将主题' onedork '应用到笔记本上,然后将其转换为幻灯片。
这些幻灯片有一个缺点,即你可以看到代码,但不能编辑它。RISE plugin 提供了一个解决方案。
2.使用 RISE 插件
RISE 是 Reveal.js 的缩写——Jupyter/IPython 幻灯片扩展。它利用 reveal.js 来运行幻灯片。这非常有用,因为它还提供了无需退出幻灯片就能运行代码的能力。
安装
1 —使用 conda(推荐):
conda install -c damianavila82 rise
2 —使用画中画(不太推荐):
pip install RISE
然后再分两步将 JS 和 CSS 安装到正确的位置:
jupyter-nbextension install rise --py --sys-prefix**#enable the nbextension:** jupyter-nbextension enable rise --py --sys-prefix
现在让我们使用 RISE 进行交互式幻灯片演示。我们将重新打开之前创建的 Jupyter 笔记本。现在我们注意到一个新的扩展,上面写着“进入/退出上升幻灯片”
点击它,你就可以开始了。欢迎来到互动幻灯片的世界。
更多信息请参考文件。
6.嵌入 URL、pdf 和 Youtube 视频
就显示在那里!
当你可以使用 IPython 的显示模块轻松地将 URL、pdf 和视频嵌入到你的 Jupyter 笔记本中时,为什么还要选择链接呢?
资源定位符
#Note that http urls will not be displayed. Only https are allowed inside the Iframefrom IPython.display import IFrame
IFrame('[https://en.wikipedia.org/wiki/HTTPS'](https://en.wikipedia.org/wiki/HTTPS'), width=800, height=450)
from IPython.display import IFrame
IFrame('[https://arxiv.org/pdf/1406.2661.pdf'](https://arxiv.org/pdf/1406.2661.pdf'), width=800, height=450)
Youtube 视频
from IPython.display import YouTubeVideoYouTubeVideo('mJeNghZXtMo', width=800, height=300)
结论
以上是 Jupyter 笔记本的一些功能,我觉得很有用,值得分享。有些对你来说是显而易见的,而有些可能是新的。所以,继续用它们做实验吧。希望他们能够节省你一些时间,给你一个更好的 UI 体验。也可以在评论中提出其他有用的功能。
顾客幸福吗?为他们建造一个聊天机器人。
原文:https://towardsdatascience.com/build-a-chatbot-for-your-customers-happiness-4f3e6a2c1944?source=collection_archive---------11-----------------------
人工智能(AI)以聊天机器人的形式首次亮相主流商业。各种规模的组织都在构建简单的信使机器人,以便更容易被他们的客户访问,特别是在支持场景中。聊天机器人使用逻辑来帮助人们更快地回答问题,而不是将人们指引到通用的电子邮件地址或服务台。这就像和一个人交谈——只不过你是在和一个机器人交谈。
聊天机器人对于规模较小、资源匮乏的组织尤其有价值。众所周知,各种规模的公司在向客户展示自己时,都会建立更牢固、更有同理心的关系。组织可以通过自动化往往是多余的对话来节省员工的宝贵时间。公司节省资金,提高客户成功的结果,引导人们通过销售周期,并提供支持。
对于不经意的观察者来说,聊天机器人可能看起来很复杂,但它们并不像看起来那么复杂。
简单而有效的聊天机器人在没有编码知识的情况下也是可以构建的。遵循这个框架,用更少的资源在几个小时内构建您的。
#研究您的聊天机器人的具体使用案例,并据此制定您的计划
Kore.ai 是一个允许人们在没有编程专业知识的情况下构建聊天机器人的工具。这家总部位于美国的公司由设计师、技术专家和学者组成,从用户体验的角度来看,它将自己描述为类似于苹果 Siri 这样的软件。该平台提供的是一种简单的方式来构建满足特定目的的聊天机器人应用程序。
“聊天机器人需要激发对话,”Kore.ai 的创始人拉杰·科内鲁(Raj Koneru)说,“它需要帮助处理自然语言是最佳沟通选择的那部分互动,它在这方面做得很好。一家在全球拥有超过 4.5 万名员工的 10 亿美元公司在内部使用 Kore.ai 的聊天机器人,为每位员工提供轻松的信息访问,以及即时请求创建和警报。该公司还消除了人为错误带来的风险,转而标准化和简化他们的成功方法”
Kore.ai Bot platform 使您能够构建对话机器人,这些机器人可以回答用户的查询,推动用户通过对话来执行业务功能或交易。Kore.ai 使用一种称为自然语言处理双重模式(NLP)的技术,实时适应对话。
在 Kore.ai 中建立对话
该平台结合了两种不同的 NLP 方法(机器学习+基本含义),可以即时构建对高达 70%的对话有用的对话机器人——无需语言培训即可开始。使用同义词、模式和完整的话语可以非常快速地完成额外的训练,这减少了开发人员提供的手动训练输入的数量,从而减少了启动和运行聊天机器人的时间。如果一开始就有大量的训练数据,也可以从一开始就应用 ML 模型,或者随着时间的推移使用 ML 模型来继续训练机器人以实现更好的意图识别。
“所有这些都是可以定制的,可以由机器人的制造者来训练。因为在 Kore.ai 平台中,所有的服务都是集成的。上下文信息(对话如何展开)被输入到神经网络,使其能够做出更明智的决定。Kore.ai 的首席技术官 Prasanna Arikala 说:“通过这种方式,该引擎允许用户模拟更复杂的对话流,如聊天期间转换对话主题,或从网站浏览行为中获取上下文信息。”
聊天机器人构建者需要采取以下步骤:
- 确定使用案例和渠道
- 设计您的流程、撰写文案并添加多媒体
- 训练你的机器人
- 集成服务
- 确定 KPI 并与测试对象一起评估
- 重复
#战略性地使用自动化,永远不要取代组织中人的一面
聊天机器人 AI 可能足够智能,可以做出简单的判断,但你构建的东西不会有取代人类同情心的情商。
“如果一家公司主要想降低成本,投资人工智能机器人是一个明智的商业举措,”Kore.ai 的 CMO 赛拉姆·维达姆说
然而,如果目标是客户满意,事情看起来就完全不同了。机器人还不能给出口头暗示,比如偶尔的“mhm”,来保证有人在听。他们也不能在棘手的情况下运用同情心和道德观。这些缺陷阻碍了机器人解决复杂的、个体的问题,而这些问题顾客可能连自己都无法识别。
如今,这种移交可以通过两种方式设计到 Kore.ai 平台上构建的机器人中:开发人员设计一个对话框,其中包含一个节点,在用户提出特定问题或采取其他行动后,可以移交给一个实时代理。这基于 Kore.ai 客户选择的预定义规则和业务逻辑。例如,对于特定类型的问题,您希望人工代理接管对话,或者对于特定类型的客户群或级别,您可能也希望人工代理介入。利用平台的情绪分析工具,开发人员可以设计情绪阈值(例如:如果用户情绪低于 3.0,则为负),以触发机器人移交给实时代理。一旦移交给代理,当用户在他们使用的任何通道中键入或说话时,消息将进入实时代理已经使用的软件中的聊天线程,允许他们无缝地响应用户,反之亦然。Kore.ai 的平台已经测试了与 Live Chat Inc,Genesys 等的集成。,并且可以轻松地与其他呼叫中心解决方案集成,作为我们客户的定制功能。
自 90 年代中期以来,美国客户满意度指数的最大跌幅发生在 2013 年至 2015 年间。在这一时期,许多技术变革正在发生,包括互联网接入的增加、市场和独立电子商务商店的增长,以及客户对更快服务的期望的改变。市场上需要企业提供更有同情心和更有知识的客户服务代理。尽管有这个令人清醒的统计数据,32%的组织计划将客户服务从现场协助转变为自动化服务,剥夺了客户与品牌进行更有效对话和互动的机会。
“在创建聊天机器人时,用户体验需要放在第一位,其次才是技术。Tech Republic 说:“聊天机器人就像一个婴儿,需要培养和教导,你不能只建立一个聊天机器人就让它走了。”
“当企业考虑在联络中心实施人工智能和机器学习时,请记住,技术不应该取代人类,”赛拉姆说。“相反,它应该提高他们的生产力,让人们参与并培养与客户的关系,让你的品牌与众不同。确保你的组织不会变成一个不知名的实体。”
聊天机器人不是人,所以避免用它们来代替人。相反,把聊天机器人看作是一种让生活变得更好的工具。
#必须优先考虑安全性,而不是事后才想到
聊天机器人是新的数字通信媒介,这意味着它们给企业带来了新的漏洞。任何负责构建聊天机器人的人都需要在计划中采取措施来防止潜在的安全漏洞。每一次对话都为一个坏演员打开了新的通道。
安全性对一切数字化事物的影响程度无需赘述。要了解安全性正在成为一个多么重要的考虑因素——对于即使是最小的企业也必须做出的每一个微决策——看看来自加州大学圣地亚哥分校、萨尔兰大学和特温特大学的这份报告,看看攻击的范围有多广。
“即使是非技术人员也可以通过 DDoS 即服务提供商(即 Booters) 发起重大攻击,”该研究的第一作者 Mattijs Jonker 说。"人们可以向他人支付订阅费,只需几美元。"
为了应对潜在的不良行为者——可能看起来像自动化或机器人的聊天机器人用户——了解在哪里采取预防措施很重要。关键是关注客户参与聊天机器人对话的原因,以便您可以实施贵公司特有的安全协议作为预防措施。
这里有一些数据可以帮助聊天机器人的开发者理解聊天机器人的用例,并将其吸收到他们的策略中。
- 超过一半的搜索该类别的人在社交媒体上寻求与客户互动的帮助(55%)
- 最具前瞻性的聊天机器人平台,脸书,已经取得了明显的收益,超过三分之二的受访者称其拥有聊天机器人参与的理想平台。
- 买家寻求帮助的其他领域包括客户服务(27%)、购物和下订单(24%)以及收集线索信息(39%)。
- 一家最大的零售商很好地利用了这一点,通过聊天机器人提供实时时尚推荐。通过询问顾客本季的流行风格,这款应用“游戏化”了销售过程的各个方面,让那些可能不确定自己想要什么的顾客在网上购物变得有趣。
- 一家领先的旅游服务提供商利用聊天机器人作为 24/7 自助客户支持平台,不仅可以解决客户关于航班的查询,还可以帮助客户预订酒店。因此,简化了客户支持流程,从而带来了总体收入
- 一家最大的投资银行最近推出了一款聊天机器人,能够更快、更有效地分析复杂的法律合同。自推出以来,该机器人仅在 6 个月内就帮助了公司超过 360,000 小时的人力
谢谢你
法尼·马鲁帕卡,
产品营销和解决方案布道者—聊天机器人|AL、NLP、ML | https://www.linkedin.com/in/phani-marupaka-02646b33/ |区块链|
用 R 构建一个加密货币交易机器人
原文:https://towardsdatascience.com/build-a-cryptocurrency-trading-bot-with-r-1445c429e1b1?source=collection_archive---------2-----------------------
Photo by Branko Stancevic on Unsplash
**请注意,本教程中使用的 API 已经不再使用。考虑到这一点,这篇文章应该作为示例来阅读。
交易者的思想是任何交易策略或计划中的薄弱环节。有效的交易执行需要与我们的本能背道而驰的人类输入。我们应该在我们爬行动物的大脑想卖的时候买。当我们的直觉希望我们买更多的时候,我们应该卖出。
如果加密货币的构成非常关键,那么交易加密货币就更加困难。年轻和新兴市场充斥着“泵组”,它们助长了强烈的 FOMO(害怕错过),将价格推高,然后再将价格推回地面。许多新手投资者也在这些市场交易,这些投资者可能从未在纽约证券交易所交易过。在每笔交易中,都有一个创造者和一个接受者,精明的加密投资者发现利用充斥这个领域的新手很容易。
为了将我的情绪从加密交易中分离出来,并利用 24/7 开放的市场,我决定建立一个简单的交易机器人,它将遵循简单的策略,并在我睡觉时执行交易。
许多被称为“机器人交易员”的人使用 Python 编程语言来执行这些交易。如果你在谷歌上搜索“加密交易机器人”,你会在各种 Github 存储库中找到 Python 代码的链接。
我是数据科学家,R 是我的主要工具。我搜索了一个关于使用 R 语言构建交易机器人的教程,但是一无所获。当我发现包 rgdax 时,我开始构建自己的包来与 GDAX API 接口,它是 GDAX API 的 R 包装器。下面是一个拼凑交易机器人的指南,你可以用它来建立自己的策略。
战略
简而言之,我们将通过 rgdax 包装器通过他们的 API 在 GDAX 交易所交易以太币-美元对。我喜欢交易这一对,因为以太坊(ETH) 通常处于看涨立场,这使得这一策略大放异彩。
注意:这是一个超级简单的策略,在牛市中只会赚几个钱。对于所有的意图和目的,使用它作为建立你自己的策略的基础。
当相对强弱指数(RSI) 指标组合指向暂时超卖市场时,我们将买入,假设多头将再次推高价格,我们可以获利。
一旦我们买入,机器人将输入三个限价卖单:一个是 1%的利润,另一个是 4%的利润,最后一个是 7%的利润。这使我们能够快速释放资金,进入前两个订单的另一个交易,7%的订单提高了我们的整体盈利能力。
软件
我们将使用 Rstudio 和 Windows 任务调度器定期(每 10 分钟)执行我们的 R 代码。你需要一个 GDAX 账户来发送订单,还需要一个 Gmail 账户来接收交易通知。
Our Process
第 1 部分:调用库和构建函数
我们将从调用几个库开始:
rgdax 包提供了 GDAX api 的接口,mailR 用于通过 Gmail 帐户向我们发送电子邮件更新,stringi 帮助我们解析来自 JSON 的数字,TTR 允许我们执行技术指标计算。
功能:curr _ bal _ USD&curr _ bal _ eth
您将在 api 部分使用从 GDAX 生成的 API 密钥、秘密和密码短语。这些函数查询您的 GDAX 帐户的最新余额,我们将在交易中重复使用这些余额:
功能:RSI
我们将使用 RSI 或相对强弱指数作为这一策略的主要指标。 Curr_rsi14_api 使用 15 分钟蜡烛线获取最近 14 个周期的 rsi 值。 RSI14_api_less_one 等等拉入之前时段的 RSI:
功能:出价&询问
接下来,我们需要当前的出价,并为我们的策略询问价格:
功能: usd_hold、eth_hold 和 cancel_orders 和
为了让我们以迭代的方式下限价单,我们需要能够拉进我们已经下的订单的当前状态,并且能够取消已经在订单簿上移动得太远而无法完成的订单。对于前者,我们将使用 rgdax 包的“holds”功能,对于后者,我们将使用“cancel_order”功能:
功能:buy _ exe
这是实际执行我们的限价单的重要功能。这个函数有几个步骤。
1.Order_size 函数计算我们可以购买多少 eth,因为我们希望每次购买尽可能多的 eth,减去 0.005 eth 以考虑舍入误差
2.我们的 WHILE 函数在我们的 ETH 仍然为零时发出限价单。
3.以 bid()价格添加一个订单,系统休眠 17 秒钟以允许订单被执行,然后检查订单是否被执行。如果不是,则重复该过程。
第 2 部分:存储变量
接下来,我们需要存储一些我们的 RSI 指标变量作为对象,以便交易循环运行得更快,并且我们不会超过 API 的速率限制:
第 3 部分:交易循环执行
到目前为止,我们一直在准备函数和变量,以便执行交易循环。以下是实际交易循环的口头演练:
如果我们账户的美元余额大于 20 美元,我们将开始循环。接下来,如果当前的 RSI 大于或等于 30,而前一期的 RSI 小于或等于 30,并且前 3 期的 RSI 至少有一次小于 30,那么我们就用当前的美元余额尽可能多地买入 ETH。
接下来,我们将购买价格保存到一个 CSV 文件中。
然后,我们给自己发一封电子邮件,提醒我们购买行动。
然后循环输出“buy ”,这样我们可以在日志文件中跟踪它。
然后系统休眠 3 秒钟。
现在,我们输入 3 层限价单来获利。
我们的第一个限价卖单获利 1%,第二个获利 4%,最后一个获利 7%。
就这样,这就是整个剧本。
第 4 部分:使用 Windows 任务计划程序自动化脚本
这个机器人的全部目的是消除交易中的人为错误,让我们不必出现在屏幕前就可以进行交易。我们将使用 Windows 任务计划程序来完成这一任务。
使用 Rstudio 插件调度脚本
使用方便的 Rstudio 插件轻松安排脚本:
使用任务计划程序修改计划的任务
导航到由 Rstudio 插件创建的任务,并调整触发器以您希望的时间间隔触发。在我的例子中,我无限期地选择每 10 分钟一次。
使用日志文件关注您的任务
每次运行脚本时,它都会在文本日志文件中创建一个条目,这允许您排除脚本中的错误:
您可以看到“开始日志条目”和“结束日志条目”打印功能如何方便地将我们的条目分开。
让它成为你自己的
您可以修改这个脚本,让它变得简单或复杂。我正在改进这个脚本,添加了来自 Tensorflow for Rstudio 的 Keras 模块的神经网络。这些神经网络为脚本增加了指数级的复杂元素,但对于发现数据中的隐藏模式来说却非常强大。
此外,TTR 包为我们提供了大量的财务函数和技术指标,可用于改进您的模型。
综上所述,不要玩你输不起的钱。市场不是一场游戏,你可能会输得精光。
链接到 Github 上的完整源代码
花 1000 加元打造一台深度学习 PC
原文:https://towardsdatascience.com/build-a-deep-learning-pc-for-1-000-cad-f3c5f26ba134?source=collection_archive---------0-----------------------
因为加拿大人也很便宜
Photo by: Thomas Kvistholt Copenhagen
在参与了由 Fast.ai 创始人瑞秋·托马斯和杰瑞米·霍华德创建的一个名为程序员实用深度学习的 MOOC 之后,我第一次想到要建立自己的深度学习机器。
课程本身并不要求你有自己的设置,而是使用 AWS(在我写作时,我正在学习第 1 部分的第 3 课)。不幸的是,为课程使用 p2 实例支付 0.90 美元/小时的费用很快就会增加。但对我来说,我最大的问题不是成本——我限制使用 AWS 来降低成本——而是生产率。
想象一下本地工作的周转时间——将文件传输到 AWS 来运行测试,失败,关闭 AWS,在本地重新思考问题,并重新做一遍——从生产力的角度来看,这是不合理的。
值得庆幸的是,有很多学生有类似的问题或成本问题,并在我之前铺平了道路,如 Brendan Fortuner 和 Sravya Tirukkovalur ,以及来自 fast.ai 课程论坛、Tim Dettmers 的深度学习硬件指南和 O'Reilly.com 建造一台低于 1000 美元的“超快”DL 机器的大量灵感。
伟大的建议和建议的组件列表,但他们都有一些缺失。
- 加拿大的价格(很少的电子公司和没有大的交易)
- “足够快/足够好”的版本(我真的需要 2 个 GPU 和一个英特尔酷睿 i7 处理器吗!?!?)
为什么是 1000 美元?因为最新和最棒的 NVIDIA GPU GTX 1080Ti 基本上是 1K CAD,所以我认为这是一个很好的价格目标。
假设:
花 1000 加元就可以建造一台“快速”深度学习机器
预测:
如果我使用多个在线供应商和折扣/销售,我可以将预算/初学者深度学习机器的成本降低到 1000 美元,同时仍然允许未来的扩展(更多的 RAM,更好的 GPU 等)
当然,术语“快”是相对的,我也使用了“预算/初学者”,所以让我们限定一下:我认为初学者是像我这样的人,他对 DL 感兴趣,要么正在学习 DL 课程,要么正在积极参加 Kaggle 比赛(或者两者都有)。在这种情况下,您需要一台速度足够快的机器,这样您的端到端实验/测试不会影响您的工作效率。
生产力何时开始下降并没有固定的数字,所以我将尝试用我一直使用的 AWS p2 实例来测试性能。
由于我不想重复其他人提供的所有伟大的建议,下面我给你我对每个组件的想法,以及我为什么选择它们。主要是,我有两个总是需要回答“是”的问题。
- (目前)够好了吗?
- 我可以以后再升级吗(不需要重建一个全新的盒子)?
Btw,强烈推荐 PCPartsPicker ,太牛逼了!你可以在最后找到我的组件列表的链接。
A little eye candy before we get started
中央处理器
这是一个棘手的问题。深度学习机器都是关于 GPU 的,所以理论上我可以得到最便宜的 CPU,对吗?也许,从我在网上读到的一切来看,这似乎是普遍的共识,但你仍然需要不要购买会成为你 GPU 瓶颈的组件。
英特尔 i3
比较您的英特尔酷睿 i3、5 & 7 芯片
国家政治保卫局。参见 OGPU
市场上最新的卡是 GTX 1080Ti,我不会说你为什么要买 NVIDIA,你只要买就行了。但是你需要最新最好的吗?在加拿大,1080Ti 基本上是 1000 美元起。
- 这是我应该花钱的地方吗?是啊!
- Cuda 内核有多重要?很多!
- 一个 1070 或者 1060 够好吗?是啊!
EVGA GTX 1070
储存;储备
让我们长话短说。我正在努力达到 1000 美元大关,所以我有非常具体的需求…
- 足够存储完成课程所需的任何数据
- 足够的存储空间,可用于 Kaggle 比赛和个人项目
固态硬盘比硬盘更贵,但从长远来看更快更好。
金士顿固态硬盘 120GB
主板和机箱
对于“mobo”(显然这是主板的简称)有一些事情要记住…
- 主板的外形会影响机箱大小,有时还会影响成本(ATX > mATX)
- 确保你的 GPU 可以放在你的箱子里(特别是如果你买的是很漂亮的那种)
- 检查内存插槽,PCIe,如果 SLI 是受支持的(你不希望主板规定你可以选择哪些组件)。
如果你使用电脑零件选择器,兼容性问题应该不是问题。我想要一个有成长空间的简约盒子。我决定在微 ATX 董事会和 ATX 的情况。
我的主板只有 1 个 PCIe x16 插槽,但我真的需要并行运行两个 GPU 吗?升级的话我就把 1070 卖了买个 1080Ti(还是 1090?1100?等等)。
微星微 ATX 和 ATX 中塔
电源装置(PSU)
回顾网上的文章,人们有一台正在运行的机器,但是东西坏了或者不能正常工作,这种情况似乎很常见。它们最终都用更强大的力量解决了。
为了避免令人讨厌的调试问题,我选择了一款合适但便宜的 PSU。再问一次,够不够好?我可以以后升级吗?是的,都是。
EVGA 450 w
记忆
散热器?我们要去的地方,不需要散热器(回到未来参考,以防你今天跑得慢)。
我们在省钱,对吧?那么大部分 RAM 就是 RAM,忽略 RAM 的散热器的市场营销…尽管它们看起来很酷。
我们要用 DDR 4(“2133”因为主板不能处理更多,即使 RAM 可以)。购买 2,4GB 而不是 1 8GB 的记忆棒。听说了一些关于双通道的伟大之处,但不知道是不是真的。
关键 4GB DDR 4–2133(2x)
最终结果
A lot of room to grow (2TB HDD salvaged from old PC)
把所有东西放在一起非常简单。为我的深度学习环境安装软件将是一个更大的挑战。
更新:用 Nvidia GPU 安装 Ubuntu 非常困难。
但在此之前,让我们先解决一些细节问题。
**不含税:**加拿大的税是个痛。他们一有机会就会毁了你的一天。一旦包括在内,账单将超过 1000 美元,但我懒得在订购零件之前手动计算,所以我们将忽略税务员。
邮寄返利:我无法抗拒一笔好交易的冲动,这笔交易帮助我将成本降低到略低于 1000 美元。我能拿回我的钱吗?大概不会。但是如果我幸运的话,在 8 到 10 周内。总之,我“节省”了大约 35 美元。
**运输+处理:**虽然 PC Parts Picker 试图将它包括在内,但它很难显示何时有额外成本。一些零件的运费+手续费约为 11 美元,而其他商店的基本价格高出 5 美元,但不含运费+手续费。做一点工作,为自己省钱。
**其他:**显示器、键盘、鼠标、机箱外风扇、CPU 冷却器等。那些都被遗漏了。我确实有几个键盘和一个显示器,但因为这是一台 DL 机器,我真的不需要它们(我将主要使用我的 mac book 上的 ssh)。同样,目前不需要额外的机箱风扇或 CPU 冷却器。
最终名单:
- GPU:EVGA GeForce GTX 1070 8GB SC 游戏 ACX 3.0
- CPU :英特尔酷睿 i3–6100 3.7 GHz 双核处理器
- 主板:微星 B150M 火箭筒加微型 ATX
- 内存:至关重要的 4GB(2x4gb)DDR 4–2133 内存
- 存储:金士顿 SSDNow UV400 120GB
- 案例:冷却器主箱 5 ATX 中塔案例
- 电源电源:EVGA 450W 80+青铜认证 ATX 电源
总价:997.43 美元
使用 TensorFlow 构建手写文本识别系统
原文:https://towardsdatascience.com/build-a-handwritten-text-recognition-system-using-tensorflow-2326a3487cd5?source=collection_archive---------1-----------------------
可在 CPU 上训练的最小神经网络实现
离线手写文本识别(HTR)系统将包含在扫描图像中的文本转录成数字文本,图 1 中示出了一个例子。我们将建立一个神经网络(NN ),它是根据来自 IAM 数据集的单词图像进行训练的。由于文字图像的输入层(以及所有其他层)可以保持较小,因此 NN 训练在 CPU 上是可行的(当然,GPU 会更好)。这个实现是 HTR 使用 TF 所需的最低要求。
Fig. 1: Image of word (taken from IAM) and its transcription into digital text.
获取代码和数据
- 你需要安装 Python 3,TensorFlow 1.3,numpy 和 OpenCV
- 从 GitHub 获取实现:要么采用本文所基于的代码版本,要么采用最新的代码版本,如果你可以接受文章和代码之间的一些不一致
- 更多说明(如何获取 IAM 数据集、命令行参数等)可以在自述文件中找到
模型概述
我们使用神经网络来完成我们的任务。它由卷积神经网络(CNN)层、递归神经网络(RNN)层和最终的连接主义者时间分类(CTC)层组成。图 2 显示了我们的 HTR 系统的概况。
Fig. 2: Overview of the NN operations (green) and the data flow through the NN (pink).
我们也可以用一种更正式的方式把神经网络看作一个函数(见等式)。1)它将大小为 W×H 的图像(或矩阵)M 映射到长度在 0 和 l 之间的字符序列(c1,c2,…)。正如您所看到的,文本是在字符级别上被识别的,因此未包含在训练数据中的单词或文本也可以被识别(只要单个字符被正确分类)。
Eq. 1: The NN written as a mathematical function which maps an image M to a character sequence (c1, c2, …).
操作
CNN :输入图像被送入 CNN 层。这些层被训练以从图像中提取相关特征。每一层由三个操作组成。首先是卷积运算,它在前两层中应用大小为 5×5 的滤波器核,在后三层中应用大小为 3×3 的滤波器核。然后,应用非线性 RELU 函数。最后,汇集层汇总图像区域并输出输入的缩小版本。当图像高度在每层中缩小 2 倍时,添加特征图(通道),使得输出特征图(或序列)具有 32×256 的大小。
RNN :特征序列每个时间步包含 256 个特征,RNN 通过这个序列传播相关信息。使用流行的长短期记忆(LSTM)实现的 RNNs,因为它能够通过更长的距离传播信息,并且提供比普通 RNN 更健壮的训练特征。RNN 输出序列被映射到大小为 32×80 的矩阵。IAM 数据集由 79 个不同的字符组成,CTC 操作还需要一个额外的字符(CTC 空白标签),因此 32 个时间步长中的每一个都有 80 个条目。
CTC :在训练 NN 时,CTC 得到 RNN 输出矩阵和地面真实文本,它计算损失值。在推断时,CTC 仅获得矩阵,并将其解码为最终文本。基本事实文本和识别文本的长度最多为 32 个字符。
数据
输入:大小为 128×32 的灰度图像。通常,数据集中的图像没有这个大小,因此我们调整它的大小(没有失真),直到它的宽度为 128 或高度为 32。然后,我们将该图像复制到大小为 128×32 的(白色)目标图像中。这个过程如图 3 所示。最后,我们归一化图像的灰度值,这简化了神经网络的任务。通过将图像复制到随机位置,而不是将其向左对齐或随机调整图像大小,可以轻松集成数据扩充。
Fig. 3: Left: an image from the dataset with an arbitrary size. It is scaled to fit the target image of size 128×32, the empty part of the target image is filled with white color.
CNN 输出:图 4 示出了长度为 32 的 CNN 层的输出。每个条目包含 256 个特征。当然,这些特征由 RNN 层进一步处理,然而,一些特征已经显示出与输入图像的某些高级属性的高度相关性:存在与字符(例如“e”)或者与重复字符(例如“tt”)或者与诸如循环(包含在手写“l”或“e”中)的字符属性高度相关的特征。
Fig. 4: Top: 256 feature per time-step are computed by the CNN layers. Middle: input image. Bottom: plot of the 32nd feature, which has a high correlation with the occurrence of the character “e” in the image.
RNN 输出:图 5 示出了包含文本“little”的图像的 RNN 输出矩阵的可视化。最上面的图表中显示的矩阵包含字符的得分,包括作为其最后一个(第 80 个)条目的 CTC 空白标签。其他矩阵条目从上到下对应于以下字符:“!”# & '()*+,-。/0123456789:;?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz”。可以看出,在大多数情况下,字符是在它们出现在图像中的位置被准确预测的(例如,比较“I”在图像和图形中的位置)。只有最后一个字符“e”没有对齐。但是这是可以的,因为 CTC 操作是无分段的,并且不关心绝对位置。从显示字符“l”、“I”、“t”、“e”和 CTC 空白标签的分数的最下面的图中,文本可以很容易地被解码:我们只是从每个时间步中取出最可能的字符,这形成了所谓的最佳路径,然后我们丢弃重复的字符,最后是所有的空白:“l-ii-t-t-l-…-e”→“l-I-t-t-…-e”→“little”。
Fig. 5: Top: output matrix of the RNN layers. Middle: input image. Bottom: Probabilities for the characters “l”, “i”, “t”, “e” and the CTC blank label.
使用 TF 实现
实施由 4 个模块组成:
- SamplePreprocessor.py:从 IAM 数据集中为 NN 准备图像
- py:读取样本,将它们放入批处理中,并提供一个迭代器接口来遍历数据
- py:如上所述创建模型,加载并保存模型,管理 TF 会话,并为训练和推理提供接口
- 将前面提到的所有模块放在一起
我们只看 Model.py,因为其他源文件涉及基本文件 IO (DataLoader.py)和图像处理(SamplePreprocessor.py)。
美国有线新闻网;卷积神经网络
对于每个 CNN 层,创建一个 k×k 大小的核,用于卷积运算。
然后,将卷积的结果输入 RELU 运算,然后再次输入大小为 px×py、步长为 sx×sy 的池层。
对 for 循环中的所有层重复这些步骤。
RNN
创建并堆叠两个 RNN 层,每层 256 个单位。
然后,从它创建一个双向 RNN,这样输入序列从前到后遍历,反之亦然。结果,我们得到大小为 32×256 的两个输出序列 fw 和 bw,我们随后沿着特征轴将它们连接起来以形成大小为 32×512 的序列。最后,它被映射到大小为 32×80 的输出序列(或矩阵),该输出序列(或矩阵)被馈送到 CTC 层。
同CITY TECHNOLOGY COLLEGE
对于损失计算,我们将基础事实文本和矩阵输入到操作中。基本事实文本被编码为稀疏张量。输入序列的长度必须传递给两个 CTC 操作。
我们现在有了创建丢失操作和解码操作的所有输入数据。
培养
批次元素损失值的平均值用于训练神经网络:它被输入到优化器中,如 RMSProp。
改进模型
如果你想输入完整的文本行,如图 6 所示,而不是文字图像,你必须增加神经网络的输入大小。
Fig. 6: A complete text-line can be fed into the NN if its input size is increased (image taken from IAM).
如果您想提高识别准确性,可以遵循以下提示之一:
- 数据扩充:通过对输入图像应用进一步的(随机)变换来增加数据集的大小
- 去除输入图像中的草书书写风格(参见去除草书风格)
- 增加输入大小(如果神经网络的输入足够大,可以使用完整的文本行)
- 添加更多 CNN 图层
- 用 2D-LSTM 取代 LSTM
- 解码器:使用令牌传递或字束搜索解码(参见 CTCWordBeamSearch )将输出限制为字典单词
- 文本更正:如果识别的单词不在字典中,则搜索最相似的单词
结论
我们讨论了一种能够识别图像中文本的神经网络。NN 由 5 个 CNN 和 2 个 RNN 层组成,输出一个字符概率矩阵。该矩阵或者用于 CTC 丢失计算,或者用于 CTC 解码。提供了一个使用 TF 的实现,并给出了部分重要的代码。最后,给出了提高识别准确率的建议。
常见问题解答
关于展示的模型有一些问题:
- 如何识别样品/数据集中的文本?
- 如何识别行/句中的文本?
- 如何计算识别文本的置信度得分?
我在的 FAQ 文章中讨论了它们。
参考资料和进一步阅读
源代码和数据可从以下网址下载:
- 呈现 NN 的源代码
- IAM 数据集
这些文章更详细地讨论了文本识别的某些方面:
- 常见问题解答
- 文本识别系统实际看到的内容
- CTC 简介
- 普通波束搜索解码
- 字束搜索解码
在这些出版物中可以找到更深入的介绍:
- 关于历史文献中手写文本识别的论文
- 字束搜索解码
- 卷积递归神经网络
- 识别页面级文本
最后,概述一下我的其他媒体文章。
用自动编码器构建一个简单的图像检索系统
原文:https://towardsdatascience.com/build-a-simple-image-retrieval-system-with-an-autoencoder-673a262b7921?source=collection_archive---------6-----------------------
图像检索是近十年来非常活跃且发展迅速的研究领域。最著名的系统是谷歌图片搜索和 Pinterest 视觉大头针搜索。在本文中,我们将学习使用一种特殊类型的神经网络构建一个非常简单的图像检索系统,称为自动编码器。我们将以无人监管的方式进行,即不看图像标签。事实上,我们只能通过图像的视觉内容(纹理、形状等)来检索图像。这种类型的图像检索被称为基于内容的图像检索(CBIR) ,与基于关键词或文本的图像检索相对。
对于本文,我们将使用手写数字的图像、MNIST 数据集和 Keras 深度学习框架。
The MNIST dataset
自动编码器
简而言之,自动编码器是旨在将其输入复制到其输出的神经网络。它们的工作原理是将输入压缩成一个潜在空间表示,然后从这个表示中重建输出。这种网络由两部分组成:
- **编码器:**这是将输入压缩成潜在空间表示的网络部分。可以用编码函数 h=f(x) 来表示。
- **解码器:**该部分旨在从潜在空间表示中重建输入。可以用解码函数 r=g(h) 来表示。
如果你想了解更多关于自动编码器的知识,我建议你阅读我之前的博客文章。
这种潜在的表示或代码是我们感兴趣的,因为这是神经网络压缩每幅图像视觉内容的方式。这意味着所有相似的图像将以相似的方式编码(希望如此)。
有几种类型的自动编码器,但由于我们正在处理图像,最有效的是使用卷积自动编码器,它使用卷积层来编码和解码图像。
因此,第一步是用我们的训练集来训练我们的自动编码器,让它学习将我们的图像编码成潜在空间表示的方法。
一旦完成训练,我们只需要网络的编码部分。
这个编码器现在可以用来编码我们的查询图像。
Our query image
同样的编码必须在我们的搜索数据库中完成,我们希望在其中找到与查询图像相似的图像。然后,我们可以将查询代码与数据库代码进行比较,并尝试找到最接近的代码。为了进行这种比较,我们将使用最近邻技术。
最近邻居
我们将通过执行最近邻算法来检索最近的代码。最近邻方法背后的原理是找到距离新点最近的预定义数量的样本。距离可以是任何度量单位,但最常见的选择是欧几里得距离。对于尺寸都为 *n、*的查询图像 q 和样本 *s、*来说,该距离可以通过以下公式来计算。
在这个例子中,我们将检索与查询图像最接近的 5 个图像。
结果
这些是我们取回的图像,看起来很棒!所有检索到的图像都与我们的查询图像非常相似,并且都对应于相同的数字。这表明,即使没有显示图像的相应标签,自动编码器也找到了以非常相似的方式编码相似图像的方法。
The 5 retrieved images
摘要
在本文中,我们学习了使用自动编码器和最近邻算法创建一个非常简单的图像检索系统。我们通过在一个大数据集上训练我们的 autoencoder 来进行,让它学习如何有效地编码每个图像的视觉内容。然后,我们将查询图像的代码与搜索数据集的代码进行比较,并检索最接近的 5 个代码。我们看到,我们的系统给出了相当好的结果,因为我们的 5 个检索图像的视觉内容接近我们的查询图像,而且它们都表示相同的数字,即使在这个过程中没有使用任何标签。
我希望这篇文章对新的深度学习实践者来说是清晰和有用的,并且它让你很好地了解了使用自动编码器进行图像检索是什么样子的!如果有不清楚的地方,请随时给我反馈或问我问题。
[## nathan hubens/无监督图像检索
GitHub 是人们构建软件的地方。超过 2800 万人使用 GitHub 来发现、分享和贡献超过…
github.com](https://github.com/nathanhubens/Unsupervised-Image-Retrieval)
使用 TensorFlow 对象检测 API、ML 引擎和 Swift 构建 Taylor Swift 检测器
原文:https://towardsdatascience.com/build-a-taylor-swift-detector-with-the-tensorflow-object-detection-api-ml-engine-and-swift-82707f5b4a56?source=collection_archive---------0-----------------------
**注意:**在撰写本文时,Swift 还没有官方的 TensorFlow 库,我使用 Swift 构建了针对我的模型的预测请求的客户端应用程序。这种情况将来可能会改变,但泰勒对此有最终决定权。
这是我们正在建造的:
TensorFlow 对象检测 API 演示可以让您识别图像中对象的位置,这可以带来一些超级酷的应用程序。但是因为我花更多的时间给人拍照,而不是给东西拍照,所以我想看看是否同样的技术可以应用于识别人脸。结果证明效果相当好!我用它建造了上图中的泰勒斯威夫特探测器。
在这篇文章中,我将概述我将从 T-Swift 图像集合中获取到一个 iOS 应用程序的步骤,该应用程序根据一个训练好的模型进行预测:
- 图像预处理:调整大小,标记,分割成训练集和测试集,转换成 Pascal VOC 格式
- 将图像转换为 TFRecords 以提供给目标检测 API
- 使用 MobileNet 在云 ML 引擎上训练模型
- 导出训练好的模型,部署到 ML 引擎服务
- 构建一个 iOS 前端,针对训练好的模型发出预测请求(显然是在 Swift 中)
这是一个架构图,展示了这一切是如何组合在一起的:
如果你想直接跳到代码,你可以在 GitHub 上找到它。
现在看起来,这一切似乎很简单
在我深入这些步骤之前,解释一下我们将使用的一些技术和术语会有所帮助: TensorFlow 对象检测 API 是一个构建在 TensorFlow 之上的框架,用于识别图像中的对象。例如,你可以用许多猫的照片来训练它,一旦训练好了,你可以传入一张猫的图像,它会返回一个矩形列表,它认为图像中有一只猫。虽然它的名字中有 API,但你可以把它看作是一套方便的迁移学习工具。
但是训练一个模型来识别图像中的物体需要时间和吨数据。对象检测最酷的部分是它支持五个预训练模型用于迁移学习。这里有一个类比来帮助你理解迁移学习是如何工作的:当一个孩子学习他们的第一语言时,他们会接触到许多例子,如果他们识别错误,就会得到纠正。例如,他们第一次学习识别一只猫时,他们会看到父母指着猫说“猫”这个词,这种重复加强了他们大脑中的路径。当他们学习如何识别一只狗时,孩子不需要从头开始。他们可以使用与对猫相似的识别过程,但应用于一个稍微不同的任务。迁移学习也是如此。
我没有时间找到并标记成千上万的 TSwift 图像,但我可以通过修改最后几层并将它们应用于我的特定分类任务(检测 TSwift)来使用从这些模型中提取的特征,这些模型是在数百万图像上训练的。
步骤 1:预处理图像
非常感谢 Dat Tran 写了这篇关于训练浣熊探测器进行物体探测的超赞帖子。我关注了他的博客文章,为图片添加标签,并将其转换为 TensorFlow 的正确格式。他的帖子有详细内容;我在这里总结一下我的步骤。
我的第一步是从谷歌图片下载 200 张泰勒·斯威夫特的照片。原来 Chrome 有一个扩展——它会下载谷歌图片搜索的所有结果。在标记我的图像之前,我把它们分成两个数据集:训练和测试。我保留了测试集,以测试我的模型在训练期间没有看到的图像上的准确性。根据 Dat 的建议,我写了一个调整脚本来确保没有图像宽于 600 像素。
因为对象检测 API 将告诉我们我们的对象在图像中的位置,所以您不能仅仅将图像和标签作为训练数据传递给它。您需要向它传递一个边界框,标识对象在图像中的位置,以及与该边界框相关联的标签(在我们的数据集中,我们只有一个标签,tswift
)。
为了给我们的图像生成边界框,我使用了 Dat 的浣熊探测器博文中推荐的 LabelImg 。LabelImg 是一个 Python 程序,它允许您手工标记图像,并为每个图像返回一个带有边框和相关标签的 xml 文件(我确实花了一整个上午标记 tswift 图像,而人们带着关切的目光走过我的桌子)。它是这样工作的——我在图像上定义边界框,并给它贴上标签tswift
:
然后 LabelImg 生成一个 xml 文件,如下所示:
现在我有了一个图像、一个边界框和一个标签,但是我需要将它转换成 TensorFlow 可以接受的格式——这种数据的二进制表示称为TFRecord
。我基于对象检测报告中提供的指南编写了一个脚本来完成这个。要使用我的脚本,您需要在本地克隆 tensorflow/models repo 并打包对象检测 API:
# From tensorflow/models/research/
python setup.py sdist
(cd slim && python setup.py sdist)
现在您已经准备好运行TFRecord
脚本了。从tensorflow/models/research
目录运行下面的命令,并向其传递以下标志(运行两次:一次用于训练数据,一次用于测试数据):
python convert_labels_to_tfrecords.py \
--output_path=train.record \
--images_dir=path/to/your/training/images/ \
--labels_dir=path/to/training/label/xml/
步骤 2:在云机器学习引擎上训练 TSwift 检测器
我可以在我的笔记本电脑上训练这个模型,但这需要时间和大量的资源,如果我不得不把我的电脑放在一边做其他事情,训练工作就会突然停止。这就是云的用途!我们可以利用云在许多核心上运行我们的培训,以便在几个小时内完成整个工作。当我使用 Cloud ML Engine 时,我可以通过利用 GPU(图形处理单元)来更快地运行训练作业,GPU 是专门的硅芯片,擅长我们的模型执行的计算类型。利用这种处理能力,我可以开始一项训练工作,然后在我的模型训练时去 TSwift 玩几个小时。
设置云 ML 引擎
我所有的数据都是TFRecord
格式的,我准备把它们上传到云端,开始训练。首先,我在 Google Cloud 控制台中创建了一个项目,并启用了 Cloud ML 引擎:
然后,我将创建一个云存储桶来打包我的模型的所有资源。确保为存储桶指定一个区域(不要选择多区域):
我将在这个 bucket 中创建一个/data
子目录来存放训练和测试TFRecord
文件:
对象检测 API 还需要一个将标签映射到整数 ID 的pbtxt
文件。因为我只有一个标签,所以这将非常简短:
为迁移学习添加 MobileNet 检查点
我不是从零开始训练这个模型,所以当我运行训练时,我需要指向我将要建立的预训练模型。我选择使用一个 MobileNet 模型——MobileNet 是一系列针对移动优化的小型模型。虽然我不会直接在移动设备上提供我的模型,但 MobileNet 将快速训练并允许更快的预测请求。我下载了这个 MobileNet 检查点用于我的培训。检查点是包含张量流模型在训练过程中特定点的状态的二进制文件。下载并解压缩检查点后,您会看到它包含三个文件:
我需要它们来训练模型,所以我把它们放在我的云存储桶的同一个data/
目录中。
在运行培训作业之前,还有一个文件要添加。对象检测脚本需要一种方法来找到我们的模型检查点、标签映射和训练数据。我们将通过一个配置文件来实现。TF Object Detection repo 为五种预训练模型类型中的每一种都提供了示例配置文件。我在这里使用了 MobileNet 的占位符,并用我的云存储桶中的相应路径更新了所有的PATH_TO_BE_CONFIGURED
占位符。除了将我的模型连接到云存储中的数据,该文件还为我的模型配置了几个超参数,如卷积大小、激活函数和步骤。
在我开始培训之前,以下是应该放在我的/data
云存储桶中的所有文件:
我还将在我的 bucket 中创建train/
和eval/
子目录——这是 TensorFlow 在运行训练和评估作业时写入模型检查点文件的地方。
现在我准备好运行训练了,这可以通过[gcloud](https://cloud.google.com/sdk/)
命令行工具来完成。请注意,您需要在本地克隆tensor flow/models/research,并从该目录运行这个训练脚本:
在训练跑步的同时,我也拉开了评测工作的序幕。这将使用以前没有见过的数据来评估我的模型的准确性:
您可以通过导航到您的云控制台中 ML 引擎的作业部分来验证您的作业是否正常运行,并检查特定作业的日志:
步骤 3:部署模型以服务于预测
为了将模型部署到 ML 引擎,我需要将我的模型检查点转换成 ProtoBuf。在我的train/
桶中,我可以看到在整个训练过程中从几个点保存的检查点文件:
checkpoint
文件的第一行将告诉我最新的检查点路径——我将从该检查点本地下载 3 个文件。每个检查点应该有一个.index
、.meta
和.data
文件。将它们保存在本地目录中,我可以利用 Objection Detection 的便利的export_inference_graph
脚本将它们转换成 ProtoBuf。要运行下面的脚本,您需要定义 MobileNet 配置文件的本地路径、从培训作业下载的模型检查点的检查点编号,以及您希望将导出的图形写入的目录的名称:
在这个脚本运行之后,您应该在您的.pb
输出目录中看到一个saved_model/
目录。将saved_model.pb
文件(不用担心其他生成的文件)上传到您的云存储桶中的/data
目录。
现在,您已经准备好将模型部署到 ML 引擎进行服务了。首先,使用gcloud
创建您的模型:
gcloud ml-engine models create tswift_detector
然后,创建您的模型的第一个版本,将它指向您刚刚上传到云存储的保存的模型 ProtoBuf:
gcloud ml-engine versions create v1 --model=tswift_detector --origin=gs://${YOUR_GCS_BUCKET}/data --runtime-version=1.4
一旦模型部署,我准备使用 ML 引擎的在线预测 API 来生成对新图像的预测。
步骤 4:使用 Firebase 函数和 Swift 构建预测客户端
我用 Swift 编写了一个 iOS 客户端,用于对我的模型进行预测请求(因为为什么要用其他语言编写 TSwift 检测器呢?).Swift 客户端将图像上传到云存储,这将触发 Firebase 函数,该函数在 Node.js 中发出预测请求,并将生成的预测图像和数据保存到云存储和 Firestore。
首先,在我的 Swift 客户端中,我添加了一个按钮,让用户可以访问他们设备的照片库。一旦用户选择了一张照片,就会触发一个将照片上传到云存储的操作:
接下来,我为我的项目编写了上传到云存储桶时触发的 Firebase 函数。它获取图像,对其进行 base64 编码,并将其发送到 ML 引擎进行预测。你可以在这里找到完整的功能代码。下面我包含了函数中向 ML 引擎预测 API 发出请求的部分(感谢 Bret McGowen 的专家云函数帮助我完成这项工作!):
在 ML 引擎响应中,我们得到:
- 如果在图像中检测到 Taylor,我们可以使用它来定义她周围的边界框
detection_scores
返回每个检测框的置信度值。我将只包括分数高于 70%的检测detection_classes
告诉我们与检测相关的标签 ID。在这种情况下,因为只有一个标签,所以它总是1
在函数中,我使用detection_boxes
在图像上画一个框,如果泰勒被检测到,以及置信度得分。然后,我将新的盒装图像保存到云存储中,并将图像的文件路径写入 Cloud Firestore,这样我就可以读取路径,并在我的 iOS 应用程序中下载新图像(带矩形):
最后,在我的 iOS 应用程序中,我可以收听 Firestore 路径的图像更新。如果发现检测,我将下载图像并在我的应用程序中显示它以及检测置信度得分。该函数将替换上述第一个 Swift 片段中的注释:
呜哇!我们有一个泰勒·斯威夫特探测器。请注意,这里的重点不是准确性(在我的训练集中,我只有 140 张图像),所以该模型确实错误地识别了一些人的图像,您可能会将其误认为 tswift。但是如果我有时间手工标注更多的图片,我会更新模型并在应用商店发布应用:)
接下来是什么?
这个帖子包含了很多信息。想自己造吗?下面是这些步骤的详细说明,并附有参考资料的链接:
- 预处理数据:我跟随 Dat 的博客帖子使用 LabelImg 手工标记图像并生成带有包围盒数据的 xml 文件。然后我写了这个脚本来将标签图像转换成 TFRecords
- 训练和评估一个对象检测模型:使用这篇博文中的方法,我将训练和测试数据上传到云存储,并使用 ML 引擎运行训练和评估
- 将模型部署到 ML 引擎:我使用
gcloud
CLI 来将我的模型部署到 ML 引擎 - 发出预测请求:我使用 Firebase 云函数 SDK向我的 ML 引擎模型发出在线预测请求。这个请求是由从我的 Swift 应用程序向 Firebase Storage 上传的触发的。在我的函数中,我将预测元数据写到 Firestore 。
你有什么问题或话题想让我在以后的帖子中涉及吗?留言或者在 Twitter 上找我 @SRobTweets 。
从头开始构建和设置您自己的深度学习服务器
原文:https://towardsdatascience.com/build-and-setup-your-own-deep-learning-server-from-scratch-e771dacaa252?source=collection_archive---------1-----------------------
今年早些时候,我完成了杰瑞米·霍华德的“实用深度学习—第一部分”课程。这是一门实用的课程,教你如何使用 AWS 实践各种深度学习技术。AWS 是一种快速启动和运行的方式,但成本会迅速增加。我有一个大约 0.9 美元/小时的 p2 实例,我们不要忘记 AWS 带来的所有额外的隐藏成本。我每月挣 50-100 美元。这影响了我的工作效率,因为我试图限制 AWS 的使用来降低成本。我想在深度学习方面追求更多,并决定冒险建立自己的深度学习服务器。这种东西变化很快,所以当你读到这篇文章的时候,如果内容已经过时了,我不会感到惊讶。然而,我希望这能让你对如何构建自己的服务器有所了解。
构建自己的深度学习服务器的 6 个步骤
1.选择组件
2。五金件组装
3。安装操作系统
4。安装显卡和驱动程序
5。设置深度学习环境
6。设置远程访问
1.选择组件
做大量的研究(例如阅读博客)来了解你需要购买哪些零件是很有用的。
在你购买之前,使用 pcpartpicker.com。该网站帮助你做“兼容性检查”,以确保你的所有组件都相互兼容。我的零件清单是这里的。
一般来说,您需要以下内容:
CPU—Intel—Core i5–6600k 3.5 GHz 四核处理器$ 289.50
RAM—G . Skill—rip jaws V 系列 32GB (2 x 16GB) DDR 4–2133 内存$ 330
GPU—EVGA—GeForce GTX 1070 8GB SC 游戏 ACX 3.0 显卡【589】
SSD—三星— 850 EVO 系列 500GB 2.5 英寸固态硬盘
主板 — MSI —EVGA—SuperNOVA NEX 650 w 80+金牌认证全模块化 ATX 电源120 美元
机箱 — 海盗船— 200R ATX 中塔机箱75 美元**总计:**1800 美元以下 CAD
关键要点:
- GPU 是最重要的组件!如果你预算紧张,一定要把钱花在好的显卡上。NVIDIA 拥有多年构建显卡的经验。做一些额外的研究,你就会明白我的意思。在撰写本文时,GTX1080Ti 是最新的最佳选择,不过 GTX1070 也可以。
- **想一想能让您在未来升级的组件。**考虑多付一点钱买一块可以支持多个 16e PCIe 插槽的主板。这使您能够安装一个额外的 GPU,如果你想获得性能提升以后。同样,也要确保有足够的内存插槽用于升级。
- 当有疑问时,选择顾客评论最多的零件。我发现,如果有很多评论,这意味着该零件已经过测试,你更有可能在网上找到帮助或操作指南。
- **从可信的卖家那里购买!**pcpartpicker.com 会给你不同卖家的报价。我注意到有一家经销商以略低的价格提供组件。只要有可能,省点钱总是好的。我正准备从这个不太出名的经销商那里买一些东西,直到我看到他们的评论。感谢上帝我做了,因为他们的评论是可怕的!我选择了更安全的方式,从我信任的商店如亚马逊和新蛋购买组件。
- **免运费&处理:**考虑从亚马逊等提供免运费&处理的地方购买零件。你可以给自己省点钱。
其他有用的资源:
- 打造自己的深度学习盒子
- 伟大的深度学习盒子装配设置和基准
- 深度学习硬件指南
- 以一种懒惰但快速的方式建立深度学习机器
- 打造个人深度学习平台
2.硬件装配
我从高中开始就没有接触过计算机硬件,所以一开始我有点紧张。如果你真的不愿意把硬件组装在一起,你可以去加拿大计算机公司或类似的公司,他们可以为你组装,价格大约 80 美元。对我来说,我不想错过这个绝佳的学习机会。
在做任何事情之前,我建议浏览说明手册和操作视频,以熟悉各种组件。你已经花了这么多美元,你还不如花一点时间来确保你知道你在做什么!
以下是一些对我使用的组件有帮助的视频:
关键要点:
- 开始前观看所有视频。文字和手册只能交流这么多。看别人安装后你会觉得自信很多。通常有一些手册没有指出的问题。
- **确保所有的插头都插好了。**我害怕弄坏自己的零件,所以我对所有东西都很温柔。第一次插上电源线,打开电源,什么也没发生——没有灯,没有声音。我想我一定是打碎了什么东西,浪费了 1000 美元。我把它关掉,检查了所有的插头,确保所有的插头都插好了。你瞧,后来一切都正常了。
- **先不要安装你的 GPU!**等到你安装好你的操作系统。我犯了这个错误,以为我的主板坏了,因为我的显示器出现了黑屏。暂时把你的显卡放在一边。请看下面的细节——我专门为此写了一节。
3.安装操作系统
我选择用 USB 安装 ubuntu 16.04。从技术上来说,你也可以安装 Windows,但我认为目前没有这个必要。
3.1 创建一个可引导的 USB 驱动器
1.买一个 2GB 或更大的 USB。
2。从 Ubuntu 下载 ISO 文件。我用的是 16.04
3。按照这些说明创建一个可引导的 u 盘。
3.2 安装 Ubuntu
重新启动你的系统,Ubuntu 安装界面应该会弹出。按照屏幕上的指示做,应该很简单。这里有一个有用的教程。
有些人可能不会自动获得 Ubuntu 设置屏幕。如果你是这种情况,你只需要重新启动进入 BIOS(对我来说是在电脑启动时按 F11),并配置你的启动优先级,先加载 USB 驱动器,再加载硬盘驱动器(SSD)。
3.3 获取最新信息
打开您的终端并运行以下命令:
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install build-essential cmake g++ gfortran git pkg-config python-dev software-properties-common wget
sudo apt-get autoremove
sudo rm -rf /var/lib/apt/lists/*
4.安装图形卡及其驱动程序
NVIDIA 显卡很难安装。有点鸡生蛋的意思因为只有安装了驱动程序才能使用显卡,但是除非主板检测到你的显卡安装了,否则是不能真正安装驱动的。如果我的主板检测到 PCI 插槽中有显卡,它也会首先自动启动显卡,但因为我还没有安装驱动程序,所以我最终只能看到一个空白屏幕。那你是做什么的?在做了大量的研究后,我发现下面的步骤是可行的。希望能给你省些麻烦。
4.1 更改 BIOS 设置
主板应该有一个集成的图形设备,这样你就可以把显示器直接连接到主板上。现在,您应该已经将显示器连接到主板显示设备上了。因为我们要安装一个图形卡,这是你需要告诉 BIOS 首先启动哪个图形设备的地方。BIOS 中有两种设置:
- **PEG — PCI Express 显卡:**如果在 PCI 插槽上检测到显卡,主板会引导显卡。如果没有,那么它会从主板启动内置的那个。
- **IGD —集成图形设备:**将始终使用主板的内置卡
默认情况下,BIOS 将设置为 PEG。在正常情况下,一旦你安装了 NVIDIA 驱动程序,这是有意义的,因为你想利用卡。然而,当你必须安装 NVIDIA 驱动程序时,它会引起问题。
通过以下方式更改 BIOS 配置:
- 重新启动计算机并引导至 BIOS (F11)。
- 转到:设置->集成图形配置->启动图形适配器
- 将设置从 PEG 更改为 IGD
- 保存并关闭您的计算机
4.2 物理插入显卡
现在系统已经关闭,将图形卡插入 PCI 插槽。有时候你必须比你想象的更努力。确保它完全进去了。
4.3 安装驱动程序
现在显卡已经连接到主板上了,打开机器安装 NVIDIA 驱动程序。
- 找到您的显卡型号
lspci | grep -i nvidia
2.确定适用于您的显卡的最新版本的 NVIDIA 驱动程序
- 访问图形驱动程序 PPA 页面并查看可用的驱动程序版本。截至 2017 年 8 月,384 是最新版本。
- 访问 NVIDIA 驱动程序下载网站以确定与您的卡和操作系统兼容的版本。
3.添加和更新图形驱动程序 PPA
sudo add-apt-repository ppa:graphics-drivers
sudo apt-get update
4.安装 NVIDIA 驱动程序。输入与您的卡兼容的版本号。例如,我安装了 384 版本
sudo apt-get install nvidia-384
5.重新启动系统并验证您的安装
lsmod | grep nvidia
如果有问题,需要从头开始,可以使用以下命令清除所有内容。我听说升级显卡的人经常遇到驱动问题。
sudo apt-get purge nvidia*
6.再次将 BIOS 图形设备优先级更改为 PEG。(参见步骤 2)
5.设置深度学习环境
在你开始安装任何东西之前,或者盲目地遵循博客上的指导,花一些时间去了解你需要什么库版本。这些东西变化如此之快,以至于当你阅读它们的时候,大多数博客都已经过时了。还有,也不要盲目下载安装最新版本。例如,Tensorflow 1.3 支持最高 python 3.6(截至 2017 年 8 月 1 日),但 Theano 仅支持最高 python 3.5。Anaconda 的最新版本运行在 python 3.6 上,但是您可以使用 python 3.5 创建 conda 环境。我在深度学习课程的第 1 部分中使用的代码是用 pythonn2.7 编写的,但课程的第 2 部分使用 python 3.5——因此我创建了 2 个 conda 环境。
我最终使用了下面的库列表及其相应的版本。
【CUDA】(V8)——一个利用 GPU 能力的并行计算平台
cud nn(V6)——位于 CUDA 之上的 CUDA 深度神经网络库。
Anaconda(v 3.6)——一个很好的包和环境管理器,自带了很多数据科学计算工具,比如 Numpy、Pands 和 Matplotlib。Anaconda 的另一个好处是它使得创建定制的 python 环境变得容易。****
tensor flow(v 1.3)——谷歌的机器学习框架
the ano(v 0.9)——一个另类的机器学习框架。****
Keras——运行在 Tensorflow、Theano 或其他机器学习框架之上的更高级的神经网络库。****
5.1 安装 CUDA
- 转到 NVIDIA 网站并找到下载 CUDA 工具包。
- 运行下面的代码来安装 CUDA。更改与您的系统兼容的软件包对应的版本。
**wget http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/cuda-repo-ubuntu1604_8.0.44-1_amd64.deb
sudo dpkg -i cuda-repo-ubuntu1604_8.0.44-1_amd64.deb
sudo apt-get update
sudo apt-get install cuda**
- 将路径添加到您的环境中
**echo 'export PATH=/usr/local/cuda/bin:$PATH' >> ~/.bashrc
echo 'export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH' >> ~/.bashrc
source ~/.bashrc**
- 检查您是否安装了正确的版本
**nvcc -V**
- 查看有关您的显卡的详细信息
**nvidia-smi**
5.2 安装 cuDNN
- 转到 NVIDIA 网站下载该库。你必须注册才能下载。该网站说可能需要几天时间才能批准,但对我来说周转时间是即时的。
- 将文件解压并复制到安装 CUDA 的地方(通常是/usr/local/cuda)
**cd ~/<folder you downloaded the file>
tar xvf cudnn*.tgz
cd cuda
sudo cp */*.h /usr/local/cuda/include/
sudo cp */libcudnn* /usr/local/cuda/lib64/
sudo chmod a+r /usr/local/cuda/lib64/libcudnn***
5.3 安装蟒蛇
- 转到网站下载安装程序并按照说明操作。最新的 Tensorflow 版本(撰写本文时是 1.3 版)需要 Python 3.5。所以下载 python 3.6 版本,就可以用特定的 python 版本创建 conda 环境了。
- 使用以下命令创建一个虚拟环境。关于如何管理环境的更多细节可以在这里找到。您可能希望为 Theano 和 Tensorflow 分别创建一个环境,因为它们通常支持不同版本的库。
**conda create -n tensorflowenv anaconda python=3.5**
- 激活您刚刚创建的 conda 环境
**source activate tensorflowenv**
5.4 安装 TensorFlow
- 安装 TensorFlow 库。根据您的操作系统、Python 版本和 CPU 与 GPU 支持,有不同的包。看一下这里的来决定你应该使用的 TensorFlow 二进制 URL。
**pip install --ignore-installed --upgrade <*tensorFlowBinaryURL>***
例如,如果您在具有 GPU 支持的 Ubuntu 上运行 Python 3.5,您可以使用以下命令。
**pip install --ignore-installed --upgrade \https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow_gpu-1.3.0-cp35-cp35m-linux_x86_64.whl**
有关 TensorFlow 安装的更多详细信息,请参见此处的。
5.5 安装 no
你可以在找到安装细节。然而,它几乎只是一个命令。
**sudo pip install Theano**
5.6 安装 Keras
- 使用以下命令安装 Keras
**sudo pip install keras**
- 根据您使用的后端(TensorFlow 或 Theano ),您必须对其进行相应的配置。
**vi ~/.keras/keras.json**
配置文件如下所示。你只需要将“后端”改为“tensorflow”或“theano ”,这取决于你使用的后端。
**{
“image_data_format”: “channels_last”,
“epsilon”: 1e-07,
“floatx”: “float32”,
“backend”: “tensorflow”
}**
关于 Keras 安装的更多细节: 1 , 2
5.7 其他有用的资源:
- 用于深度学习的 Ubuntu 16.04 上的英伟达 GTX 1080
- 从零开始设置深度学习机器
6.设置远程访问
这一步是可选的,但是如果您计划从笔记本电脑远程工作,这里有一些选项。
6.1 团队浏览器
Teamviewer 基本上是一个屏幕共享软件。它有时有点笨重,但对于远程控制来说是个不错的选择。
6.2 SSH
大多数开发人员希望通过终端 SSH 到机器中,并不真正需要图形用户界面。可以用 OpenSSH 。
您可以使用以下命令来安装并检查其状态。默认情况下,OpenSSH 服务器将在第一次引导时开始运行。
**sudo apt-get install openssh-server
sudo service ssh status**
6.3 远程 Jupyter 笔记本
我经常使用 Jupyter 笔记本。如果你想在笔记本电脑的浏览器上运行它,这是一个非常酷的技巧。点击查看完整的教程。总之,只需在您的笔记本电脑和服务器上运行以下代码。
**$laptop: ssh -l <username>@<yourNewServerIP>
$server: jupyter notebook --no-browser --port=8888
$laptop: ssh -NL 8888:localhost:8888 <username>@<yourNewServerIP>**
然后你可以在笔记本电脑的浏览器上进入 http://localhost:8888 并远程查看/编辑你的 Jupyter 笔记本。
就是这样!我很想听听你的设置体验!
您的仪表板对组织有影响吗?
原文:https://towardsdatascience.com/build-dashboards-that-impact-the-organization-b0e39985029d?source=collection_archive---------8-----------------------
Photo by Julien-Pier Belanger on Unsplash
怎么会?就用“那又怎样?”试验
我的第一个数字仪表板并没有得到管理层的好评。经过数周的计划和准备,在一个下雨的周五下午,我和我的同事向总经理展示了最终产品。
会议期间,我们向她详细介绍了我们的杰作——我敢肯定,我们脸上挂着大大的傻笑。
她最后说了什么…“ 那又怎样?”
那一年,带有向下钻取功能的网页非常流行
在网络报道的早期,能够深入了解更多信息是非常棒的(或者对我们来说是这样)!我们为我们的仪表板感到骄傲。我们设想赢得世界最佳仪表板奖,并获得一个镶满钻石的皇冠,戴在我们聪明的小脑袋上。
我们花哨的仪表板是为客户支持部门设计的。它展示了有关故障单计数和代理回复率的数据。经理可以根据过去 30 天的回复率,选择计数以深入查看 traffic-lite 客户问题列表。
我们有技术,但没有可操作的分析
总经理继续说,“那又怎样?那又怎样?”看完之后耸了耸肩。我们面面相觑,然后看向我们的经理,因为我们不知道如何回答。总经理是一个令人印象深刻的人物,我们想给她留下深刻的印象,仿效她。
我的经理从军队退休了。在他的职业生涯中,他见过更糟糕的情况,但对我们来说这就像是一场战争。我们的经理不好意思地问总经理,“你是什么意思?”
“如果有 72 张严重性为中等的罚单,响应率为 76%,那又如何。它应该是什么?应该少票吗?更多?回复率好吗?不好?你希望我用这些信息做什么?”,她一边举起双手一边继续说道。她变得不耐烦了。
“目标是 85%。他表示:“未来几周,到达的门票数量将会下降——这是一个积极的趋势。”。
“团队没有达到目标,工作票也少了,这是这份报告想要表达的意思吗?她问。"我是不是应该先看看这份报告,然后打电话给你问清楚?"
“我明白了。这个仪表板需要说明这一点。”我们的经理回答道。
“他们为什么会错过目标?对此正在做些什么?”她继续说道。这是真正的标题和数据的真正要点。
结论,而不是建议
好消息是仪表板开始工作了。我们已经将数据提炼为几个简单的关键绩效指标(KPI),她已经准备好应对这种情况。
坏消息是我们的仪表板没有回答“那又怎样”的问题——它只呈现了一些事实。
管理层在寻找一个结论,这是仪表板的一个关键元素。那天,我戴上最好的仪表板头饰的梦想就像放了一天的结婚蛋糕一样被抛到了一边。总经理证实,我们已经建立了一个花哨的网络报告,而不是一个有用的工具。
将报表更改为仪表板
报表不同于仪表盘,有些人没有意识到这一点。这两个术语经常互换使用——对我来说,仪表板可以帮助您了解性能。
报告提供了您可以查看的事实,例如,故障单的数量或响应率。在下图中,我使用 SAS Visual Analytics 重新创建了一个简单的示例,展示了我们的仪表板的外观。
应用“那又怎样”测试
如果你试图确定你正在看的是一份报告还是一个仪表板,使用通用汽车公司的“那又怎样?”测试。你可以很容易地问“如果上周有 156 张低优先级票,那又怎么样?”你不知道这是一个好的还是坏的事实——它只是一个事实。页面上没有支持信息来帮助您确定“什么”
你需要帮助来下结论
没有任何支持信息——上表没有通过测试,所以没有通过测试。我们需要一种方法来知道事实是好是坏。为了测量到达的票计数,我们采用前一周的计数或过去六周的平均值来确定趋势。然后我们可以分配一个显示规则,如下所示:
- 如果本周的票数高于上周,将该事实标记为红色
- 如果低于前一周,则显示为绿色
- 如果是一样的,那就把它变成黄色或者什么都没有
回应率基于服务水平协议。如果客户期望特定的回复率,则使用该回复率作为衡量标准。对于高优先级票证,他们希望 99%的票证在 24 小时内关闭,中等优先级票证在五天内关闭 85%。在这种情况下,条形不是红色就是绿色。团队是否达到了目标。如果他们有一个大问题,顾客很少关心他们的票是否几乎准时关闭。
如果您将“那又怎样”测试应用于该仪表板,它将不起作用。本周有 156 张低优先级票,比上周低,这很好。当有结论时,经理可以查看仪表板,看看他们下一步需要确定什么。
推动组织向前发展
在上面的仪表板中,经理需要知道为什么团队没有达到服务级别。也许团队人手不足?可能安装了一个热补丁,破坏了许多客户系统,所以它让每个人都很忙。
我并不是说仪表板从来没有任何事实,但是事实应该是支持信息,而不是表演的明星。例如,在上图中,查看 12 周或 6 个月的票证关闭率会有所帮助,这样我们就可以知道这种情况是异常还是持续存在。
你的外卖
- 什么时候需要事实,什么时候结论更有用?
- 你如何提供数据来帮助管理者理解需要采取的行动?
最初在 www.zencos.com 出版。
以光速构建和部署数据科学项目
原文:https://towardsdatascience.com/build-deploy-data-science-projects-at-lightspeed-2cf4670c7d06?source=collection_archive---------13-----------------------
“starry night” by Quentin Kemmel on Unsplash
(或其左右)。
使用 Repl.it 的云环境在几分钟内分析和共享陨石降落数据
当今数据科学发展的最大挑战之一是快速共享、开发和部署代码。
除非你在一个数据科学和分析深深嵌入公司文化和生态系统(以及 Github)的企业中工作,否则你很可能已经体验过包含 SQL 行的电子邮件链的乐趣,无穷无尽。Slack 上的 txt 代码片段和足够多的类似命名的 R 环境引起了真正的头痛。
在这些环境中,与其他数据科学家、分析师和工程师共享代码可能是一项挑战。在某些情况下,数据仍然与传统的工程部门过于分离,这意味着这是一种乞求、借用和窃取代码模式和最佳实践的情况。
在阅读了威廉·科赫森的回复后,我很想尝试一下这个新平台。它允许你在云环境中快速构建、测试和共享代码。对数据人员来说,好消息是 repl.it 支持多种语言,包括 R 和 Python。
“silhouette photo of mountain during night time” by Vincentiu Solomon on Unsplash
我一直在使用 NASA 的陨石着陆数据作为一个项目的样本数据,该项目围绕群体分析以及何时利用参数与非参数分析方法。这似乎是一个绝佳的机会,可以看看 repl.it 导入外部数据集并提供快速分析的能力如何。
虽然在这种情况下,我可以访问群体(已知的降落在地球上的陨石),但为了项目的目的,我想对这些数据进行采样,以了解坠落和发现的陨石的质量是否不同,并分析样本是否来自正态分布的群体。
下面,你可以看到来自 repl.it 的嵌入,它导入了美国宇航局的数据集,采集了样本,提供了一个用于正态性的夏皮罗-维尔克测试和一个箱线图可视化,以了解质量数据的分布,按坠落和发现的陨石进行划分,进一步:
如您所见,repl.it 环境可以轻松处理外部数据导入和可视化运行,即使是在介质中。我确实发现,目前 repl.it 似乎还不能处理 install.packages()和 library()功能,所以使用 ggplot 等工具进行分析目前是不允许的。然而,对于基本功能,repl.it 提供了一种简单快捷的方法来与您的团队和更广泛的数据社区共享 R 代码。而且是免费的!
有用的资源
repl.it
https://data . NASA . gov/Space-Science/陨石降落/gh4g-9sfh
[## Quick-R:箱线图
了解如何在 R 中为单个变量或按组为变量创建箱线图。
www.statmethods.net](https://www.statmethods.net/graphs/boxplot.html) [## 如何把完全交互式的、可运行的代码放到一篇中等的文章中
代码应该是交互式的。
towardsdatascience.com](/how-to-put-fully-interactive-runnable-code-in-a-medium-post-3dce6bdf4895)
建立、开发和部署一个机器学习模型,使用梯度推进来预测汽车价格。
原文:https://towardsdatascience.com/build-develop-and-deploy-a-machine-learning-model-to-predict-cars-price-using-gradient-boosting-2d4d78fddf09?source=collection_archive---------1-----------------------
介绍
在这篇博文中,我将介绍一个数据科学过程,通过以下步骤来构建和部署一个可以预测汽车价格的机器学习模型:
- 设定研究目标
- 检索数据
- 数据预处理和清理
- 数据探索和可视化
- 数据建模
- 模型部署
设定研究目标
这项工作的目的是通过构建和部署一个机器学习模型来熟悉如上所述的数据科学过程,该模型可以根据汽车的特征来预测汽车价格,方法是尝试 4 个回归模型,并选择具有最高 R 分数和最低均方根误差的模型。
Demo of the Web App
检索数据
检索数据是设定研究目标后的重要步骤,为此,我使用了专门从事这类任务的著名 python 库“BeautifulSoup”
。该任务的过程非常简单,首先我们循环遍历广告页面,通过增加基本 URL 中名为o
的页码参数来收集广告 URL,如下所示:
basic_url = "[https://www.avito.ma/fr/maroc/voitures-](https://www.avito.ma/fr/maroc/voitures-)à_vendre&o="
一旦 URL 被收集,我将它们设置在一个名为“ads_urls.csv”的csv
文件中,如下所示:
[https://www.avito.ma/fr/temara/voitures/peugeot_508_26753561.htm](https://www.avito.ma/fr/temara/voitures/peugeot_508_26753561.htm)
[https://www.avito.ma/fr/safi/voitures/renualt_kasket_26753552.htm](https://www.avito.ma/fr/safi/voitures/renualt_kasket_26753552.htm)
[https://www.avito.ma/fr/oued_fes/voitures/Citroen_C3_Diesel_26753551.htm](https://www.avito.ma/fr/oued_fes/voitures/Citroen_C3_Diesel_26753551.htm)
.
...
上面这些链接中的每个链接都包含广告中发布的汽车的相关数据,例如:“车型年”、“里程”、“燃料类型”、“价格”…,看起来就像这样:
Car features published on the Ad page
然后,我读取这个包含要在广告页面上抓取的 URL 列表的文件,并提取必要的数据,所以这里有一个关于它如何工作的简短代码快照。
Extracting ad data procedure
最后我得到以下数据模式:
price, year_model, mileage, fuel_type, mark, model, fiscal_power, sector, type, city
135 000 DH,Année-Modèle:2013,Kilométrage:160 000–169 999,Type de carburant:Diesel,Marque:Peugeot,Modèle:508,Puissance fiscale:-,-,”Type:Voitures, Offre”, Temara
60 000 DH,Année-Modèle:2009,Kilométrage:130 000 - 139 999,Type de carburant:Essence,Marque:Ford,Modèle:Fiesta,Puissance fiscale:7 CV,Secteur:saies,"Type:Voitures, Offre", Fès
.
...
下一步是每个数据科学流程中最耗时的步骤,即数据预处理和清理。
数据预处理和清理
数据清理
数据预处理的原因是将我们的原始数据转换成有用的数据,并减少数据大小,以便于分析,在这种情况下,我们需要:
price
:去掉price
中的“DH”(迪拉姆货币)字符和空格,然后转换成整数。year_model
:从year_model
列中删除不需要的字符串,如:“Anne-modèle:”或“ou plus ancien”,然后将其转换为整数。mileage
:对于这个字段来说,事情完全不同,我们有一个里程范围,例如在每次观察中,我们的里程在 160000 - 169999 公里之间,所以在删除“公里”和“-”字符后,我必须呈现这个列,以便只保留一个值而不是一个范围,我们可以使用最小值或最大值,对我来说,我选择使用平均值,以便我们保持在该范围的中间。fuel_type
:从fuel_type
栏中移除不需要的字符串,如“de 型增碳剂:”。mark
:从mark
栏中移除“品牌:”字符串。fiscal_power
:对于这个字段,我必须处理两种情况:删除不需要的字符串,如“Puissance fiscale: CV ”,并处理缺失值,因此处理缺失值的技巧之一是用所有fiscal_power
列的平均值填充它们。
删除不需要的列
对于数据探索和分析,我们不需要一些列,如“sector”和“type ”,所以我们最终将它们从数据框中删除。
数据探索和可视化
在数据提取和数据预处理步骤之后,我现在应该可视化我的数据集,这样我就可以更深入地了解幕后发生了什么,以及我的数据是如何分布的。
在接下来的部分中,我将运行一个问答会话,以回答许多基于直方图和图的问题。
问:价格在年度模型中是如何分布的?
Price distribution over the year of released model
**答:**从上面的图中我们可以看出,汽车价格逐年上涨,更明确地说,我们可以说,最近发布的汽车越多,价格上涨越多,而另一方面,最老的汽车仍然价格低廉,这是完全符合逻辑的,因为每当汽车从发布之日起变得有点旧,价格就开始下降。
问:价格如何在财权上分配?
Price distribution over fiscal power
**答:**从上面的图中我们可以清楚地注意到,在[2800 DH,800000 DH]和[3 CV,13 CV]范围内存在着巨大的积分集中度,这可以解释为:首先,中型财政动力汽车在市场上占据着巨大的主导地位,价格是正确的;其次,财政动力越大,价格也越高。
问:燃料类型的价格如何按年分配?
Simple linear regression between price and year model grouped by fuel type
**答:**虽然疲软,但似乎在year_model
和price
之间存在正相关关系。让我们看看价格和其他数据点之间的实际相关性。我们将通过查看热图关联矩阵来确认。
Correlation matrix with Heatmap visualization
正如我们所看到的,在price
和 year_model
特性之间有很强的相关性,相关性分数为 0.47,这验证了price
和year_model
列之间的强关系。
数据建模
现在,我们来到了整个过程中的主要任务,即数据建模,为此,我将使用 4 个专门用于回归问题的机器学习模型,最后我将制作一个基准表来比较每个模型r2_score
,并选择最佳模型。使用的模型有:K 近邻回归、多元线性回归、决策树回归和梯度推进回归。
数据转换
我有意让这一部分一直进行到数据建模,而不是为了一些可视化的目的对数据进行预处理。
目前,我仍然有两个分类特征,它们是fuel_type
和mark
,这一部分的目的是预处理这些特征,以便将它们数字化,使它们适合我们的模型。在文献中,有两种著名的分类变量转换方法,第一种是标签编码,第二种是 one hot 编码,对于这个用例,我们将使用 one hot position,我选择这种数据标签的原因是因为我以后不需要任何类型的数据标准化,这样做的好处是不会对值进行不正确的加权,但也有向数据集添加更多列的缺点。
Features engineering and Data Transformation
Result of one hot encoding on the data frame
如上图所示,使用 one hot 编码将分类特征转换为数字特征后,我们得到了一个宽数据框。
数据拆分
通常我们将数据分成三部分:训练、验证和测试集,但为了简单起见,我们将只使用 20%的测试规模进行训练和测试,其余的用于训练。
梯度推进回归
Boosting 是另一种用于创建强大预测器集合的集成技术,而梯度 Boosting 是一种用于生成由回归变量集合组成的回归模型的技术。
集合是预测者的集合,其预测通常通过某种加权平均或投票进行组合,以提供从集合本身获得指导的总体预测。因此,boosting 是一种集成技术,在这种技术中,学习者按顺序学习,早期的学习者将简单的模型拟合到数据中,然后分析数据中的错误,这些错误识别出困难或难以拟合的问题或数据的特定实例,因此,后来的模型主要关注那些试图使它们正确的例子。
最后,所有模型贡献权重,集合被组合成一些整体预测器,因此 boosting 是一种将弱学习器序列转换成非常复杂的预测器的方法,它是一种增加特定模型复杂性的方法。最初的学习器往往非常简单,然后随着学习器的增加,加权组合会变得越来越复杂。
渐变增强背后的数学原理
这个算法是梯度推进的一个例子,它被称为梯度推进,因为它与梯度下降过程有关。
- 首先,我们为每个数据点做一组预测
ŷ(i)
。 - 我们可以计算出我们预测的误差,姑且称之为
J(y, ŷ)
,j 只是把ŷ的精度和 y 联系起来 - 对于均方差 MSE :
J(y, ŷ) = **Σ** ( y(i) **-**ŷ(i) **)²**
。 - 所以现在我们可以试着考虑调整我们的预测
ŷ
来试着减少上面的误差:ŷ(i)= ŷ(i) + α *∇J(y, ŷ)
,用:∇J(y, ŷ) = y(i)- ŷ(i)
- 每个学习者都在估计损失函数的梯度。
- 梯度下降:采取一系列步骤降低
J
。 - 预测值之和,按步长α加权。
梯度推进回归器—代码快照
Snapshot from the used code in the GBR model
解释残差与预测值
建立 GBR 模型后,主要建议绘制误差分布图,以验证以下假设:
- 正态分布
- 同方差(每个 X 处的方差相同)
- 自主的
这在我们的案例中已经得到了验证,您可以在笔记本上查看更多细节,但是我们需要观察残差图,以确保它不遵循非线性或异方差分布。
Residual VS Predicted values
正如我们从上面的图中看到的,残差在 0 线周围大致形成一个“水平带”,这表明误差项的方差相等,此外,没有一个残差从残差的基本随机模式中“脱颖而出”,这涉及到没有异常值。
车型基准测试
因此,在尝试了许多回归模型来拟合我们的数据集之后,是时候绘制一个基准表来总结我们得到的所有结果了。
╔═══════════════════╦════════════════════╦═══════════════╗
║ Model ║ R^2 score ║ RMSE ║
╠═══════════════════╬════════════════════╬═══════════════╣
║ KNN ║ 0.56 ║ 37709.67 ║
║ Linear Regression ║ 0.62 ║ 34865.07 ║
║ **Gradient Boosting** ║ 0.**80** ║ **25176.16** ║
║ Decision Tree ║ 0.63 ║ 34551.17 ║
╚═══════════════════╩════════════════════╩═══════════════╝
看起来梯度推进模型以最低的 RMSE 值和最高的 R 值赢得了这场战斗,正如它所预期的那样。
Heroku 模型部署
- 创建 Flask web 应用程序
Flask 是 Python 的一个“微”框架。之所以称之为微框架,是因为他们希望保持核心简单但可扩展。虽然一开始会有些困惑,但使用 Jinja2 模板在 Flask 上建立一个网站还是相对容易的。
flask 应用程序由两个主要组件组成:python 应用程序(app.py
)和 HTML 模板,对于app.py
它看起来是这样的:
Web App Controller
因此,一旦构建了app.py
,我们就可以从终端运行它,如果一切顺利,我们将得到在“/”路径上运行的index.html
页面,如:http://localhost:8080/
,然后我们可以用正确的值填充给定的表单,并得到一个甜蜜的警告弹出窗口。
2。将应用程序部署到 Heroku
对于这一部分,我将需要一个 Heroku 帐户(免费)和 HerokuCLI,我也可以使用 GitHub 来完成这项任务,但让事情变得简单。
- 设置 Procfile:Procfile 是一种机制,用于声明 Heroku 平台上应用程序的 dynos 运行哪些命令。创建一个名为“Procfile”的文件,并将以下内容放入其中:
web: gunicorn app:app --log-file -
- 通过在您的终端中运行以下命令,在 Flask 应用程序的根目录下创建 python 需求文件:
$ pipreqs ./
如果您在 python 虚拟环境中工作,这将是高效的:
$ pip3 freeze > requirements.txt
- 登录您的帐户,在 Heroku 网站上创建一个新的应用程序。
Form to create a new app with Heroku
创建好应用程序后,我们将被重定向到一个页面,该页面显示了成功部署的说明。在成功连接到 HerokuCLI 后,我需要将目录更改为我们的 flask 应用程序,并运行以下命令:
$ heroku git:clone -a cars-price-prediction
$ git add .
$ git commit -am "make it better"
$ git push heroku master
该应用程序现在应该在 my-app-name.herokuapp.com 现场直播!点击查看应用程序的工作版本。
结论
在这篇博客文章中,我试图通过构建一个可以根据汽车特征预测汽车价格的模型来介绍数据科学的过程,从数据收集开始,到数据建模和内置模型之间的比较,最后以模型部署为 web 应用程序结束。
有用的链接
完整笔记本:https://github . com/PaacMaan/cars-price-predictor/blob/master/cars _ price _ predictor . ipynb
GitHub 资源库:
[## PaacMaan/汽车价格预测工具
这个项目一步一步的展示了如何建立一个模型来预测汽车的价格
github.com](https://github.com/PaacMaan/cars-price-predictor)
网页申请链接:https://cars-price-prediction.herokuapp.com
与❤.共享
使用神经网络从零开始构建手势识别-机器学习简单而有趣
原文:https://towardsdatascience.com/build-hand-gesture-recognition-from-scratch-using-neural-network-machine-learning-easy-and-fun-d7652dd105af?source=collection_archive---------4-----------------------
从自拍图像到学习神经网络模型
Photo by Perry Grone on Unsplash
介绍
这种算法应该适用于所有不同的肤色,只要确保你的手放在中间。
对于这个解决方案,我使用了 GNU Octave 和 Visual Studio 代码。
数据和代码可以在我的 Github 库中找到。
[## gago 993/HandGestureRecognitionNeuralNetwork
使用神经网络的手势识别软件-gago 993/handsgeturerecognitionneuralnetwork
github.com](https://github.com/Gago993/HandGestureRecognitionNeuralNetwork)
我们需要做的所有工作可以分为 5 个步骤:
- 生成和准备数据
- 生成要素
- 生成 ML 模型
- 测试 ML 模型
- 用 ML 模型预测
那么让我们开始…
生成和准备数据
因为我们是从底层构建这个项目。我们需要做的第一件事是创建用于训练神经网络模型的数据。
对于这一步,我使用我的电脑内置摄像头。我从手上抓拍了 78 张图片,展示了 4 种不同的手势,它们被分成 4 个文件夹。我裁剪了一些图像,使它们更适合稍后训练我们的模型。所有训练(准备)图像都存储在 数据集 文件夹中。
- 左—包含 27 个向左指的手的图像
- 右-包含 24 个向右指的手的图像
- 手掌—包含 11 个手掌图像
- 和平—包含 14 个和平之手的图像(V 形符号)
Image 1: Dataset Example (Peace V Sign)
生成要素
训练图像准备就绪后,我们可以继续下一步,即处理所有图像并创建特征。从图像中分离手的主要算法通过几个简单的步骤完成:
- 加载图像
- 将图像大小调整为 50x50
- 将图像从 RGB 转换为 YCbCr 颜色
- 选择中心点颜色(期望手放在图像的中间)
- 根据步骤 3 中定义的肤色范围分割手部。
- 用白色标记所选像素,用黑色标记其他像素
这个算法放在processskinimage . m文件中。我记下了代码中的每一步。
该图像皮肤处理由create _ image _ dataset . m文件使用,该文件遍历所有图像,使用上述代码处理它们,并将它们分别写入左、右、手掌、和平文件夹中名为dataset _ resized的单独文件夹中。
最后,我们需要准备我们的图像,以便它们可以用于生成和测试我们的神经网络模型。因为我们得到了 78 幅图像,它们是 50x50 像素,所以我们将它们保存为 78x2500 大小的矩阵,其中每一列代表我们图像中的像素。我们也将随机地把矩阵分成两组。训练矩阵将被保存在 x_features_train 矩阵中,并将包含 80%的图像和 x_features_test 中的测试矩阵以及其他 20%的图像。标签将分别保存在 y_labels_train 和y _ labels _ test中。
创建特征矩阵的代码如下所示
...
% Generate random number from 1 to 10
randNum = ceil(rand() * 10);% Split the images in 80%-20% train-test set
if randNum > 2
% Create the features for the image
X_train = [X_train; image_out(:)'];
y_train = [y_train; label];
else
X_test = [X_test; image_out(:)'];
y_test = [y_test; label];
endif
...
有四种类型的标签:
- [1 0 0 0] —左指手形图像
- [0 1 0 0] —右手图像
- [0 0 1 0] —手掌图像
- [0 0 0 1] —和平标志手形图像
这个标签是在create _ image _ dataset . m中创建的,如下面的代码所示。其中 文件夹 是包含图像的文件夹名称, 是成员 从上面的列表中返回 4 个选项中的一个。
...
label_keys = { 'left', 'right', 'palm', 'peace'};
...
label = ismember(label_keys, folder);
...
这个脚本完成后,我们可以在dataset _ resized文件夹中检查已处理的图像,我们应该会看到类似这样的内容
Image 2: Processed Image (Peace V Sign)
还应该有x _ features _ train和y _ labels _ train文件,我们将在下一步中使用它们来训练我们的模型,还有x _ features _ test和y _ labels _ test用于稍后测试我们的模型。
在继续之前,在这篇博客中,我假设你已经熟悉神经网络,这就是为什么我不打算深入神经网络的解释。
为了充分理解概念和公式,我建议阅读我的帖子,以便更深入地理解神经网络。
[## 你需要知道的关于神经网络和反向传播的一切-机器学习变得容易…
神经网络的基础解释,包括理解背后的数学
towardsdatascience.com](/everything-you-need-to-know-about-neural-networks-and-backpropagation-machine-learning-made-easy-e5285bc2be3a)
生成 ML 模型
让我们从定义我们的神经网络结构开始。我们将在网络中使用一个隐藏层。输入层的大小将是 2500 个节点,因为我们的图像是 50x50 像素。隐藏层大小将是 25 个节点,输出将是 4 个节点(4 种类型的符号)。
定义隐藏层大小没有严格的公式,但通常取决于“它与数据的拟合程度如何?”
Image 3: Andrew Ng on Neural Network Size
这里我们将使用 main.m 文件,我们将:
- 加载要素和标注
- 随机初始化θ值(NN 节点权重)
- 创建成本函数并向前传播
- 为 NN 成本函数创建梯度(反向传播
- 使用 fmincg 最小化器最小化成本函数
加载特征和标签
让我们开始第一步,加载要素和标签。我们通过使用 dlmread 函数来实现。
...
X = dlmread('x_features_train');
% Labels for each processed training image
%[1 0 0 0] - left, [0 1 0 0] - right, [0 0 1 0] - palm, [0 0 0 1] - peace
y = dlmread('y_labels_train');
...
随机初始化θ值(NN 节点权重)
接下来我们需要使用randinitializeweights . m函数初始化 Theta 值。它由下面的代码表示
epsilon = sqrt(6) / (L_in + L_out);
W = zeros(L_out, 1 + L_in);
W = (rand(L_out, 1 + L_in) * 2 * epsilon) - epsilon;
其中生成的值在[-ε,ε]之间。该代码与“均匀分布方差”的统计公式相关。如果你对这个公式更感兴趣,我会在这个博客的末尾留下链接,或者你可以提出问题。
创建成本函数并向前传播
我们的下一个目标是实现下面等式定义的成本函数。
Image 4: Regularized Cost Function
其中 g 是激活函数(在这种情况下是 Sigmoid 函数)
为了计算成本,我们需要使用前馈计算。代码在***nncostfunction . m .***中实现。我们将在示例中使用 for 循环来计算成本,我们还需要将 1 的列添加到 X 矩阵中,表示“偏差”值。θ₁(θ1)和θ₂(θ2)值是神经网络中每个单元的参数,θ₁的第一行对应于第二层中的第一个隐藏单元。
为 NN 成本函数创建梯度(反向传播 )
为了能够最小化成本函数,我们需要计算 NN 成本函数的梯度。为此,我们将使用反向传播算法*,是“误差反向传播”的缩写,用于最小化我们的成本函数,这意味着最小化我们的 NN 的误差和最小化每个输出神经元的误差。这个计算是在nncostfunction . m*中实现的代码的一部分
使用 fmincg minimizer 最小化成本函数
一旦我们计算出梯度,我们可以通过使用高级优化器(如 *fmincg)最小化成本函数 J(θ)来训练神经网络。*这个函数不是 Octave 的一部分,所以我是从吴恩达的机器学习课程中得到的。据我所知,这个函数比 Octave 中实现的函数更快,它使用了共轭梯度法。
fmincg 接受 3 个参数,如下面的代码示例所示。它采用成本函数、连接成单个向量的初始θ (Theta)参数和选项参数。
在我们的测试例子上运行 fmincg 之后,我们得到了一个向量中的θ值,我们需要在矩阵中对它们进行整形,以简化矩阵乘法。
测试 ML 模型
现在,我们成功地从神经网络中生成了我们的 Theta(权重)值。接下来要做的是检查我们的模型与训练的吻合程度,以及它在测试数据上的表现。
为了预测我们将使用 预测 函数位于 预测. m 文件中。
该函数采用参数和特征矩阵。然后,它将表示“偏差”值的 1 列添加到特征矩阵中。只需将两个 NN 层的特征乘以θ值。然后,它获得大小为(number_of_images x 4)的向量 h2,其中每列(4)表示该图像在该类别中的可能性(左、右、手掌、和平)。最后 if 返回概率最高的一个。
让我们执行训练集准确性和测试集准确性。
...
pred = predict(Theta1, Theta2, X_train);
% Compare the prediction with the actual values
[val idx] = max(y_train, [], 2);
fprintf('\nTraining Set Accuracy: %f\n', mean(double(pred == idx)) * 100);...
pred = predict(Theta1, Theta2, X_test);
% Compare the prediction with the actual values
[val idx] = max(y_test, [], 2);
fprintf('\nTest Set Accuracy: %f\n', mean(double(pred == idx)) * 100);
我们得到的是
Training Set Accuracy: 100.000000%
Test Set Accuracy: 90.909091%
用 ML 模型预测
我还制作了一些额外的图片,并将它们放在 测试 文件夹中。它们代表完整的图像(未编辑),所以我可以测试神经网络模型的性能。我得到的是对他们四个人的预测。
pred = 2
Type: rightpred = 1
Type: leftpred = 3
Type: palmpred = 4
Type: peace
您可以用您的图像甚至您自己的训练图像来尝试这一点。只需将您的训练图像放在 数据集 文件夹下,并调用create _ image _ dataset . m文件来创建训练和测试矩阵。同样所有的 测试 图片都在 测试 文件夹下,你就可以调用 main.m 脚本了。
结论
恭喜你从零开始构建你的机器学习神经网络模型。希望这将有助于理解使用神经网络时的总体情况以及如何迈出第一步。如有任何问题或建议,请发表评论或联系我。
希望你喜欢它!
有用的链接
[## 统计/分布/制服- Wikibooks,开放世界的开放书籍
顾名思义,(连续)均匀分布是一种概率密度为……
en.wikibooks.org](https://en.wikibooks.org/wiki/Statistics/Distributions/Uniform#Variance) [## 神经网络中什么是好的初始权重?
我刚刚听说,从范围$(\frac{-1}中选择神经网络的初始权重是一个好主意…
stats.stackexchange.com](https://stats.stackexchange.com/questions/47590/what-are-good-initial-weights-in-a-neural-network#answer-297777) [## 一个逐步反向传播的例子
背景技术反向传播是训练神经网络的常用方法。网上不缺论文说…
mattmazur.com](https://mattmazur.com/2015/03/17/a-step-by-step-backpropagation-example/)
使用 Apache Spark 构建日志分析应用程序
原文:https://towardsdatascience.com/build-log-analytics-application-using-apache-spark-b5eeca1e53ba?source=collection_archive---------10-----------------------
使用 Apache Spark 开发真实世界应用程序的一步一步的过程,主要重点是解释 Spark 的体系结构。
如果我们有 Hadoop,为什么还要 Apache Spark 架构?
Hadoop 分布式文件系统(HDFS ),它以 Hadoop 原生格式存储文件,并在集群中并行化这些文件,同时应用 MapReduce 算法来实际并行处理数据。这里的问题是数据节点存储在磁盘上,处理必须在内存中进行。因此,我们需要进行大量的 I/O 操作来进行处理,而且网络传输操作会跨数据节点传输数据。这些操作总的来说可能会阻碍数据的快速处理。
Hadoop Map Reduce Algorithm (Left Image Source : researchgate.net)
如上图所述,数据块存储在磁盘上的数据记录中,地图操作或其他处理必须在 RAM 中进行。这需要来回的 I/O 操作,从而导致整体结果的延迟。
Apache Spark :官网描述为:“Apache Spark 是一个快速和通用集群计算系统”。
快 : Apache spark 很快,因为计算是在内存中进行并存储的。因此,没有 Hadoop 架构中讨论的 I/O 操作。
**通用:**是一个支持通用执行图的优化引擎。它还支持丰富的 SQL 和结构化数据处理, MLlib 用于机器学习, GraphX 用于图形处理,以及 Spark Streaming 用于实时数据处理。
Spark Architecture. Eg : Detect prime numbers
Spark 的入口点是 Spark 上下文,它处理执行者节点。Spark 的主要抽象数据结构是弹性分布式数据集(RDD),它代表了一个可以并行操作的不可变元素集合。
让我们讨论上面的例子来更好地理解:一个文件由数字组成,任务是从这个巨大的数字块中找到质数。如果我们把它们分成三块 B1,B2,B3。这些块是不可变的,由 spark 存储在内存中。这里,复制因子=2,因此我们可以看到,其他节点的副本存储在相应的其他分区中。这使得它具有容错体系结构。
步骤 1:使用 Spark 上下文创建 RDD
第二步:变换:当对这些 RDD 应用 map() 操作时,新的块,即 B4、B5、B6 被创建为新的 RDD,它们又是不可变的。这一切操作都发生在内存中。注:B1,B2,B3 仍然作为原来的存在。
第三步:动作:当 **collect(),**这个时候实际的结果被收集并返回。
懒评估 : Spark 不会马上评估每个转换,而是将它们批量放在一起,一次性评估全部。在其核心,它通过规划计算顺序和跳过潜在的不必要步骤来优化查询执行。主要优点:增加可管理性**,**节省计算并提高速度,降低复杂性,优化。
它是如何工作的?我们执行代码来创建 Spark 上下文,然后使用 sc 创建 RDD,然后使用 map 执行转换来创建新的 RDD。实际上,这些操作并不在后端执行,而是创建一个有向无环图(DAG)谱系。仅当执行动作时,即获取结果,例如: collect() 操作被调用,然后它引用 DAG 并向上爬以获取结果,参考该图,当向上爬时,它看到过滤器 RDD 尚未创建,它向上爬以获取上部结果,最后反向计算以获取精确结果。
RDD — **弹性:**即借助 RDD 谱系图容错。RDD 是其输入的确定性函数。这加上不变性也意味着 RDD 的部分可以在任何时候被重新创建。这使得缓存、共享和复制变得容易。
分布式:数据驻留在多个节点上。
**数据集:**代表你所处理的数据的记录。用户可以通过 JDBC 从外部加载数据集,数据集可以是 JSON 文件、CSV 文件、文本文件或数据库,没有特定的数据结构。
在文章的一部分,我们将使用 Apache Spark 的 pyspark 和 SQL 功能从头开始创建一个 Apache 访问日志分析应用程序。Python3 和 pyspark 的最新版本。数据来源:Apache access log
必备库
pip install pyspark
pip install matplotlib
pip install numpy
步骤 1:由于日志数据是非结构化的,我们从每一行解析并创建一个结构,在分析时,每一行又会变成每一行。
步骤 2:创建 Spark Context、SQL Context、DataFrame(是组织到命名列中的数据的分布式集合。它在概念上相当于关系数据库中的表)
步骤 3:分析以 MB 为单位传输最多内容的前 10 个端点
Top End Points with Maximum Content Flow
Response Code Analysis
Visitors(IP Address) which access the system most frequently
Traffic Analysis for Past One Week
Hour Level Traffic Analysis on Particular Day
Day Level Traffic Analysis
通过分析峰值以及哪些端点被哪些 IP 地址击中,可以清楚地检测出异常值。
Week Level Each Day Traffic Analysis
在这里,我们可以看到 3 月 8 日的一个不寻常的峰值,可以对其进行进一步分析,以确定差异。
地块分析代码:
End Points which are most Frequenty Hit
获取完整的应用代码:【https://github.com/ahujaraman/live_log_analyzer_spark
从头开始构建神经网络—第 2 部分
原文:https://towardsdatascience.com/build-neural-network-from-scratch-part-2-673ec7cdd89f?source=collection_archive---------4-----------------------
神经网络系列简介(GINNS)——第二部分
简介
在这篇文章中,我们将为 And 逻辑门构建一个感知机,这个模型我们将使用 python 和 numpy 从头开始构建。在这里,我假设你已经阅读了神经网络入门系列—第 1 部分,并且你已经熟悉了神经网络的基本概念。如果您不熟悉这个主题,我强烈建议您从第 1 部分开始。你还在吗?太好了,这篇文章将是我迄今为止写得最短的文章之一,我想在你建立良好的直觉和对神经网络的理解的同时保持事情的简单,所以让我们开始吧,但是首先,让我解释一下为什么从零开始建立一个超级虚拟神经网络为什么从零开始实现一个神经网络?
但是为什么要从头开始实现一个神经网络呢?我相信你真正想要的是创建强大的神经网络,可以预测你照片中的人是乔治·卢卡斯还是卢克·天行者?不要!,哦好吧,我不怪你。
现在,玩笑归玩笑。即使你计划在未来使用 Tensorflow、Keras 或另一个神经网络库,从头实现一个网络至少一次也是非常有价值的练习。它帮助你理解神经网络是如何工作的,这对设计有效的模型是必不可少的。所以,我希望我说服你留在这里。
单层神经网络(感知机)
感知器算法是最简单的人工神经网络类型,它的灵感来自于称为神经元的单个神经细胞的信息处理。
Perceptron
在感知器中,为了计算输出,我们将输入乘以各自的权重并与阈值进行比较,概括来说,输入的加权和通过一个阶跃/激活函数,如下所示:
Weighted sum passed to an activation function.
激活功能
给定一个输入或一组输入,节点的激活函数定义该节点的输出。一个标准的计算机芯片电路可以被看作是一个激活功能的数字网络,激活功能可以是“开”(1)或“关”(0),这取决于输入。在我们的示例中,我们将使用二元阶跃函数,如下所示:
step function
下面是代码!
Perceptron
- 负载输入(x)和输出(y)
- 初始化权重和其他参数:学习率是控制权重更新量的配置参数,**训练步骤(也称为历元)**是进行向前和向后传播的单个步骤。
- 计算输入(X)和权重矩阵(W)之间的点积,这里我们用 np.dot()做矩阵乘法,点积也叫内积,比如 X 和 W 之间的内积是 x1w1 + x2w2 + x3w3 + … + XnWn。
- 在 l1 上应用激活功能。l1 实际上是我们网络的输出。
- 当我们开始训练网络猜测预测时,计算模型产生的损失或错误,然后我们比较预测的类和真实的类。理想情况下,当我们训练神经网络时,我们想要的是找到最佳权重(W ),使我们的模型误差最小化。
- 计算变化因子,我们称之为更新,如果我们的模型正确地预测了类,误差等于零,并且权重没有变化,但是如果它出错,那么我们可以对权重进行负(减少)或正(增加)更新。
- 我们在 100 个训练步骤中训练我们的模型,并使用在线或随机学习,这意味着我们使用单个训练示例来进行参数更新。这里,单个训练示例是随机选取的。
培训后的输出:
y_pred after training
使用案例和限制
虽然感知器对我们示例中的实例进行了很好的分类,但该模型有局限性,实际上,感知器是一个线性模型,在大多数情况下,线性模型不足以学习有用的模式。
Left: And Gate, Right: Not and OR Logic Gates
像感知器这样的线性模型不是通用函数逼近器,如果您试图改变 XOR 逻辑门的问题,感知器会失败,因为 XOR 不具有线性可分性,如下图所示:
source
神经网络是众所周知的通用函数逼近器,那么我们遗漏了什么?这就是隐藏层的来源,也是我们接下来要讨论的内容。
下一步是什么?
我们将讨论隐藏层的力量和它们能够进行的处理,以及我们如何使用基于反向传播和梯度下降的算法来训练复杂的神经网络,如果你愿意更深入地研究神经网络的内部细节,请查看下面的链接,敬请关注!
参考资料:
- 神经网络和深度学习
- http://cs231n.github.io/neural-networks-1/
- 用 Python 从零开始实现神经网络——简介
- 在 Python 和 TensorFlow 中从头开始构建神经网络
- 用 Python 和 R 从零开始理解和编码神经网络
- 11 行 Python 中的神经网络(第 1 部分)
在你走之前!
如果你喜欢这些作品,请留下你的掌声👏推荐这篇文章,让别人也能看到。
大卫·福莫的《❤与 T4》。
愿原力与你同在!
使用探索性数据分析和熊猫围绕数据构建故事。数据科学的艺术部分。
原文:https://towardsdatascience.com/build-the-story-around-data-using-exploratory-data-analysis-and-pandas-c85bf3beff87?source=collection_archive---------5-----------------------
探索性数据分析,简称 EDA,是赢得数据科学竞赛的秘方。EDA 是数据科学的创造性部分,是一个使用统计工具围绕数据编写的故事。EDA 还使科学家能够对数据进行隐喻性的考古挖掘,挖掘出任何潜在的见解。训练一个基本的机器学习算法只需要不到五行的代码。相比之下,EDA 和数据准备需要更长的时间,占数据科学家 80%的时间。
EDA 是什么? 简单来说,EDA 是一套在假设检验和实验之外探索和理解数据的统计方法。
使用 python 执行 EDA
使用 python 执行 EDA 非常容易,因为 python 有无数的统计分析包(如 numpy、pandas、matplotlib 等)。在 EDA 中主要进行三种分析,即:
单变量分析
双变量分析
多变量分析
我们将使用 python 逐步执行所有这三种类型的分析,并得出一些结论。从这里下载数据集,从这里下载完整代码。
使用 pandas 加载数据并检查数据框的维度。
reading Employee.csv file
单变量分析
一旦我们加载数据,我们就可以开始第一种 EDA,称为单变量分析。“Uni”表示一个,“Variate”表示变量,因此单变量分析表示对一个变量或一个特征的分析。单变量基本上告诉我们每个特征中的数据是如何分布的,还告诉我们中心趋势,如平均值、中值和众数。
描述性统计
连续特征
首先,检查集中趋势均值、中值和众数的度量,检查每个特征的最小值和最大值以及分位数。要做所有这些事情,我们只需使用 pandas 的“describe()”函数。
statistical description
从上表中,我们可以看到,员工的平均满意度仅为 61.12%,偏离了 24%,这意味着员工满意度之间存在很大差异,这直接影响了生产率。此外,我们可以看到 50%的员工同时从事 4 个不同的项目。这里的 50%分位数也称为中位数,我们使用中位数是因为中位数不会受到离群值的影响。其中平均值容易受到异常值的影响。
分类特征 分类变量中的描述性统计使用频率表和模式技术进行分析
frequency tables
从上图中,我们可以说几乎 48%的员工工资很低,只有 8%的员工工资很高。
可视化
直方图 在单变量分析中,我们使用直方图来分析和可视化频率分布。在熊猫身上绘制直方图非常简单明了。
从上图中,我们看到数据不是正态分布的,因此我们无法对这些数据执行许多统计操作。
箱线图 单变量分析中使用的第二个可视化工具是箱线图,这种类型的图形用于检测数据中的异常值。数据点超过三个标准偏差,通常称为异常值。离群值直接影响统计分析,因此我们必须首先检测它,然后从数据中删除(或修复)它。matplotlib 中的箱线图如下所示
box-plot for time spent in the company
从上图中,我们可以看到,有四名员工在公司花的时间比其他所有员工都多。所以这些员工的待遇与普通员工不同。因此,我们必须单独处理异常值。
离群值
使用中位数的整点是中位数不能受离群值的影响,这里均值容易受离群值的影响。有许多处理异常值的技术,其中一种技术采用三个标准差之间的所有数据。根据经验法则,几乎 99.97%的数据属于如下所示的三个标准差。
empirical rule
数据点位于称为异常值的三个标准偏差之上,因此我们采用三个标准偏差之间的数据来排除异常值。曲线下的面积称为 p 值,距离平均值的度量由标准差给出。
python function for removing outliers
该 python 函数将输入作为 pandas 数据框,并返回异常值和数据在三个标准差之间的数据框,该技术称为 3-sigma 技术。
现在 EDA 被称为数据科学的艺术部分,因为每个人都有不同的方法来查看数据并从中挖掘一些模式。我们用 python 做了很多 EDA。在接下来的博客中,我将向您展示如何用 python 执行推断统计。如果你喜欢这个博客,请喜欢并评论,直到那时快乐学习。
Connect with the Raven team on Telegram
使用 TensorFlow 构建您的第一个深度学习分类器:狗品种示例
原文:https://towardsdatascience.com/build-your-first-deep-learning-classifier-using-tensorflow-dog-breed-example-964ed0689430?source=collection_archive---------0-----------------------
Convoluted Neural Networks (like the one pictured above) are powerful tools for Image Classification
介绍
在本文中,我将向您介绍几种技术,帮助您迈出开发算法的第一步,该算法可用于经典的图像分类问题:从图像中检测狗的品种。
到本文结束时,我们将开发出代码,接受任何用户提供的图像作为输入,并返回对狗的品种的估计。此外,如果检测到人类,该算法将提供最相似的狗品种的估计。
1.什么是卷积神经网络?
卷积神经网络(也称为 CNN 或 ConvNet)是一类深度神经网络,已在许多计算机视觉和视觉图像应用中广泛采用。
一个著名的 CNN 应用案例在斯坦福大学研究小组的研究论文中有详细描述,他们在论文中展示了使用单一 CNN 对皮肤病变进行分类。仅使用像素和疾病标签作为输入,从图像中训练神经网络。
卷积神经网络由多层组成,与其他图像分类算法相比,它需要相对较少的预处理。
他们通过使用滤镜并将其应用于图像来学习。该算法采用一个小正方形(或“窗口”)并开始在图像上应用它。每个过滤器允许 CNN 识别图像中的特定模式。CNN 寻找图像中过滤器匹配图像内容的部分。
An example of a CNN Layer Architecture for Image Classification (source: https://bit.ly/2vwlegO)
网络的前几层可以检测简单的特征,如线、圆、边。在每一层中,随着我们越来越深入神经网络的各个层,网络能够结合这些发现,并不断学习更复杂的概念。
1.1 有哪几种层?
CNN 的整体架构由输入层、隐藏层和输出层组成。它们有几种类型的层,例如卷积层、激活层、汇集层、下降层、密集层和软最大层。
Neural Networks consist of an input layer, hidden layers, and an output layer (source: https://bit.ly/2Hxhjaw)
卷积层(或 Conv 层)是构成卷积神经网络的核心。Conv 层由一组滤镜组成。每个过滤器可以被认为是一个小正方形(具有固定的宽度和高度),其延伸通过输入体积的整个深度。
在每次通过时,过滤器在输入体积的宽度和高度上“卷积”。这个过程产生一个二维激活图,它给出了该滤波器在每个空间位置的响应。
为了避免过度拟合,池层用于在激活图上应用非线性缩减采样。换句话说,池层在丢弃信息方面很激进,但如果使用得当,也是有用的。在 CNN 架构中,一个池层通常跟随一个或两个 Conv 层。
Pooling layers are used to apply non-linear downsampling on activation maps (source: https://bit.ly/2Hxhjaw)
通过随机忽略某些激活函数,丢弃层也用于减少过拟合,而密集层是完全连接的层,通常位于神经网络的末端。
1.2 什么是激活功能?
使用激活函数处理层和神经网络的输出,激活函数是添加到隐藏层和输出层的节点。
你会经常发现 ReLu 激活函数用在隐藏层,而最终层通常由 SoftMax 激活函数组成。这个想法是,通过堆叠线性和非线性函数层,我们可以检测大范围的模式,并准确预测给定图像的标签。
SoftMax 通常位于最后一层,它基本上是一个归一化器,产生一个离散的概率分布向量,这对我们来说很好,因为 CNN 的输出是一个图像对应于特定类别的概率。
The most common activation functions include the ReLU and Sigmoid activation functions
当涉及到模型评估和性能评估时,选择损失函数。在用于图像分类的 CNN 中,通常选择类别交叉熵(简单地说:它对应于-log(error))。有几种方法可以使用梯度下降来最小化误差——在本文中,我们将依靠“ rmsprop ”,这是一种自适应学习率方法,作为一种以准确性为衡量标准的优化器。
2.设置算法的构建模块
为了构建我们的算法,我们将使用 TensorFlow 、 Keras (运行在 TensorFlow 之上的神经网络 API),以及 OpenCV (计算机视觉库)。
完成该项目时,训练和测试数据集也可用(参见 GitHub repo )。
2.1 检测图像是否包含人脸
为了检测提供的图像是否是人脸,我们将使用 OpenCV 的人脸检测算法。在使用任何面部检测器之前,标准程序是将图像转换为灰度。下面,detectMultiScale
函数执行face_cascade
中存储的分类器,并将灰度图像作为参数。
2.2 检测图像是否包含狗
为了检测所提供的图像是否包含一张狗的脸,我们将使用一个预训练的 ResNet-50 模型,该模型使用 ImageNet 数据集,该数据集可以将对象从 1000 个类别中分类。给定一个图像,这个预训练的 ResNet-50 模型返回图像中包含的对象的预测。
当使用 TensorFlow 作为后端时,KerasCNN 需要一个 4D 数组作为输入。下面的path_to_tensor
函数将彩色图像的字符串值文件路径作为输入,将其调整为 224x224 像素的正方形图像,并返回适合提供给 Keras CNN 的 4D 数组(称为“张量”)。
此外,所有预训练模型都有额外的归一化步骤,即必须从每个图像的每个像素中减去平均像素。这在导入函数preprocess_input
中实现。
如上面的代码所示,对于最终预测,我们通过获取预测概率向量的 argmax 来获得与模型的预测对象类别相对应的整数,我们可以通过使用 ImageNet 标签字典来识别对象类别。
3.使用迁移学习建立你的 CNN 分类器
现在我们有了在图像中检测人类和狗的功能,我们需要一种从图像中预测品种的方法。在这一节中,我们将创建一个对狗的品种进行分类的 CNN。
为了在不牺牲准确性的情况下减少训练时间,我们将使用转移学习来训练 CNN 这是一种允许我们使用在大型数据集上预先训练好的网络的方法。通过保留早期的层并仅训练新添加的层,我们能够利用通过预训练算法获得的知识并将其用于我们的应用。
Keras 包括几个预训练的深度学习模型,可用于预测、特征提取和微调。
3.1 模型架构
如前所述, ResNet-50 模型输出将成为我们的输入层——称为瓶颈特性。在下面的代码块中,我们通过运行以下代码来提取与训练、测试和验证集相对应的瓶颈特性。
我们将建立我们的模型体系结构,以便 ResNet-50 的最后一个卷积输出作为我们的模型的输入。我们只添加了一个全局平均池层和一个全连接层,其中后者包含每个狗类别的一个节点,并具有一个 Softmax 激活函数。
_________________________________________________________________ Layer (type) Output Shape Param # ================================================================= global_average_pooling2d_3 ( (None, 2048) 0 _________________________________________________________________ dense_3 (Dense) (None, 133) 272517 ================================================================= Total params: 272,517 Trainable params: 272,517 Non-trainable params: 0 _________________________________________________________________
正如我们在上面代码的输出中看到的,我们最终得到了一个有 272,517 个参数的神经网络!
3.2 编译和测试模型
现在,我们可以使用 CNN 来测试它在我们的狗图像测试数据集中识别品种的能力。为了微调模型,我们进行了 20 次迭代(或“时期”),其中模型的超参数被微调,以减少使用 RMS Prop 优化的损失函数(类别交叉熵)。
Test accuracy: 80.0239%
该算法提供了一个测试集,测试准确率为 80% 。一点都不差!
3.3 用模型预测犬种
现在我们有了算法,让我们编写一个函数,它以图像路径作为输入,并返回由我们的模型预测的狗的品种。
4.测试我们的 CNN 分类器
现在,我们可以编写一个函数,它接受一个图像的文件路径,并首先确定该图像是否包含一个人、一只狗,或者两者都不包含。
如果在图像中检测到一只狗,返回预测的品种。如果在图像中检测到一个人,返回相似的狗品种。如果图像中未检测到或,则提供指示错误的输出。
我们已经准备好测试这个算法了!让我们在一些样本图像上测试该算法:
这些预测在我看来很准确!
最后,我注意到该算法容易出错,除非它是一个清晰的正面拍摄,图像上的噪声最小。因此,我们需要使算法对噪声更加鲁棒。此外,我们可以用来改进我们的分类器的一种方法是图像增强,它允许您通过提供训练集中提供的图像的变体来“增强”您的数据。
在 5 分钟内建立自己的卷积神经网络
原文:https://towardsdatascience.com/build-your-own-convolution-neural-network-in-5-mins-4217c2cf964f?source=collection_archive---------0-----------------------
CNN 和代码介绍(Keras)
什么是卷积神经网络??
CNN
在回答什么是卷积神经网络之前,我相信你们都知道什么是神经网络。如果你基础不扎实,看看这个链接。继续前进。卷积神经网络类似于多层感知器网络。主要的区别是网络学习什么,它们是如何构造的,以及它们主要用于什么目的。卷积神经网络也受到生物过程的启发,它们的结构类似于动物的视觉皮层。CNN 广泛应用于计算机视觉领域,并在各种测试案例中取得了很好的效果。
隐藏层学到了什么??
CNN 中的隐藏层通常是卷积和汇集(缩减采样)层。在每个卷积层中,我们采用一个小尺寸的滤波器,并在图像中移动该滤波器,执行卷积运算。卷积运算只不过是滤波器值和图像中的像素之间的逐元素矩阵乘法,并将结果值相加。
Convolution operations
滤波器的值通过训练的迭代过程来调整,并且在神经网络已经训练了一定数量的时期之后,这些滤波器开始寻找图像中的各种特征。以使用卷积神经网络的面部检测为例。网络的早期层寻找简单的特征,例如不同方向的边等。随着我们在网络中的进展,这些层开始检测更复杂的特征,当你观察最终层检测到的特征时,它们几乎看起来像一张脸。
Different features recognised at different layers
现在,让我们继续池层。共用图层用于对图像进行缩减像素采样。图像将包含许多像素值,并且如果图像尺寸逐渐减小,网络通常很容易学习这些特征。池层有助于减少所需的参数数量,因此,这减少了所需的计算。合用也有助于避免过度拟合。有两种类型的池操作可以完成:
- 最大池化—选择最大值
- 平均池-将所有值相加,然后除以值的总数
很少使用平均池,您可以在大多数示例中找到最大池。
Max Pooling
密码
在我们开始编码之前,我想让你知道我们将使用的数据集是 MNIST 数字数据集,我们将使用 Keras 库和 Tensorflow 后端来构建模型。好了,够了。让我们做一些编码。
首先,让我们做一些必要的进口。keras 库帮助我们建立我们的卷积神经网络。我们通过 keras 下载 mnist 数据集。我们导入了一个顺序模型,这是一个预先构建的 keras 模型,您可以在其中添加层。我们导入卷积和池层。我们还导入密集层,因为它们用于预测标签。下降层减少过度拟合,展平层将三维向量扩展为一维向量。最后,我们为矩阵运算引入 numpy。
上面代码中的大部分语句都很琐碎,我只解释几行代码。我们重塑 x_train 和 x_test,因为我们的 CNN 只接受四维向量。值 60000 表示训练数据中的图像数量,28 表示图像大小,1 表示通道数量。如果图像是灰度图像,通道数设置为 1;如果图像是 RGB 格式,通道数设置为 3。我们还将目标值转换成二进制类矩阵。要知道二进制类矩阵是什么样子,请看下面的例子。
Y = 2 # the value 2 represents that the image has digit 2 Y = [0,0,1,0,0,0,0,0,0,0] # The 2nd position in the vector is made 1# Here, the class value is converted into a binary class matrix
我们构建了一个顺序模型,并添加了卷积层和最大池层。我们还在两者之间添加了 dropout 层,dropout 随机关闭网络中的一些神经元,迫使数据找到新的路径。因此,这减少了过度拟合。我们在末尾添加了密集层,用于类别预测(0–9)。
我们现在用分类交叉熵损失函数、Adadelta 优化器和准确性度量来编译该模型。然后,我们将数据集拟合到模型中,即我们针对 12 个时期训练模型。训练好模型后,我们在测试数据上评估模型的损耗和精度,并打印出来。
输出
结论
卷积神经网络确实有一些由杰弗里·辛顿指出的缺点。他认为,如果我们希望在计算机视觉领域达到人类水平的精确度,他的胶囊网络是必由之路。但是,到目前为止,CNN 似乎做得很好。如果你觉得这篇文章有用,请告诉我,谢谢:)
构建自己的 Python RESTful Web 服务
原文:https://towardsdatascience.com/build-your-own-python-restful-web-service-840ed7766832?source=collection_archive---------0-----------------------
“An overhead shot of strawberry and blackberry pies next to a white coffee pot and a bunch of flowers” by Brooke Lark on Unsplash
在这篇博客中,我将解释我是如何创建一个 RESTful web 服务来充当数据工程服务的。web 服务是通过一个 Docker 容器中的 python web frameworkCherryPy提供的。以下是如何使用 3 个文件和不到 30 行代码实现这一目标的分步说明。
第一步是通过安装 Docker 、 Python 3 和以下 Python 库来设置开发环境:
- pandas——用于对数据集执行聚合
- CherryPy -服务于 web 服务的 web 框架
这些库可以使用 pip 命令安装:
>> pip install pandas
>> pip install CherryPy
让我们首先编写一个简单的数据处理器 myprocessor.py :
class MyProcessor: def run(self, df):
return df.agg(['mean', 'min', 'max'])
该处理器计算输入数据帧所有列的平均值、最小值和最大值。
在同一个目录中,我们创建一个 web 服务脚本 ws.py ,它包含请求处理程序的定义:
**import** cherrypy
**import** pandas **as** pd
**import** myprocessorp = myprocessor.MyProcessor()
**class MyWebService**(object):
@cherrypy.expose
@cherrypy.tools.json_out()
@cherrypy.tools.json_in()
**def process**(self):
data = cherrypy.request.json
df = pd.DataFrame(data)
output = p.run(df)
**return** output.to_json()**if** __name__ == '__main__':
...
该处理程序接受指向 /process 端点的请求,并期望输入数据在请求体中表示为 JSON 字符串。处理的结果将作为 JSON 字符串返回——使用 panda to_json() 方法方便地进行转换。
接下来是在 ws.py 的主要部分启动 web 服务的代码:
**if** __name__ == '__main__':
config = {'server.socket_host': '0.0.0.0'}
cherrypy.config.update(config)
cherrypy.quickstart(MyWebService())
myprocessor.py 和 ws.py 都是 web 服务所需要的。我们现在可以使用以下 python 命令启动 web 服务:
>> python ws.py
[24/Jul/2018:11:13:53] ENGINE Listening for SIGTERM.
[24/Jul/2018:11:13:53] ENGINE Listening for SIGHUP.
[24/Jul/2018:11:13:53] ENGINE Listening for SIGUSR1.
[24/Jul/2018:11:13:53] ENGINE Bus STARTING[24/Jul/2018:11:13:53] ENGINE Started monitor thread 'Autoreloader'.
[24/Jul/2018:11:13:53] ENGINE Started monitor thread '_TimeoutMonitor'.
[24/Jul/2018:11:13:53] ENGINE Serving on [http://0.0.0.0:8080](http://0.0.0.0:8080)
[24/Jul/2018:11:13:53] ENGINE Bus STARTED
哒哒!这里是我们的网络服务运行在任何时候。
在 Linux 系统中,我们可以使用 curl 发送这个 POST 请求来验证 REST API 是否正常工作:
>> curl -d '{"num1" : [1, 2, 3], "num2":[4, 5, 6]}' -H "Content-Type: application/json" -X POST [http://localhost:8080/process](http://localhost:8080/process)"{\"num1\":{\"mean\":2.0,\"min\":1.0,\"max\":3.0},\"num2\":{\"mean\":5.0,\"min\":4.0,\"max\":6.0}}"
预期结果是一个数据集,包括发送到 web 的两组数字的平均值、最小值和最大值。
码头集装箱
接下来,我们需要编写一个 Dockerfile — 这是一个文本文件,用于设置 web 服务将要运行的环境。如果你以前没有使用过 Docker,我建议至少阅读一下 Docker 入门文档,这样你就可以熟悉 Docker 的概念。文件中的第一行声明使用python:3 . 6 . 4-slim-Jessie作为基础映像:
from python:3.6.4-slim-jessie
这个是官方 Python Linux 映像之一,预装了 Python 3 的普通版本,还有许多其他映像可以从 Docker 存储库中选择,但这是一个精简版本,足以运行一个简单的服务。就像我们必须安装额外的 python 包来本地运行 web 服务一样,在构建 docker 映像时也需要这样做:
RUN pip install pandas
RUN pip install CherryPy
接下来,构建过程需要将 web 服务文件复制到默认的工作目录中:
COPY myprocessor.py .
COPY ws.py .
容器需要公开端口 8080 以允许访问:
EXPOSE 8080
docker 文件中的最后一条语句定义了容器启动时要运行的命令:
ENTRYPOINT ["python", "ws.py"]
这是完成的docker 文件的样子,它应该与之前编写的 python 脚本驻留在同一个目录中:
from python:3.6.4-slim-jessieRUN pip install pandas
RUN pip install CherryPy
COPY myprocessor.py .
COPY ws.py .
EXPOSE 8080
ENTRYPOINT ["python", "ws.py"]
为了执行 docker build 命令,我们停留在创建了 Dockerfile 的目录中。为 docker 映像分配一个标记是一个很好的做法,这个标记可以在以后引用,因此我们使用带有-t 标记的 build 命令来构建映像:
>> docker build -t python-ws .
我们现在已经准备好了一个 docker 图像,让我们试一试:
>> docker run -p 8080:8080 python-ws
该命令以附加模式启动容器,因此 Cherrypy 日志将立即出现在控制台中。同样,之前用于测试的相同 curl 命令也应该工作,因为主机(localhost)现在将定向到端口 8080 的请求转发到正在运行的 docker 容器。
我已经演示了如何构建一个简单的 RESTful web 服务,但是这个服务还远远不能用于生产。如果 web 服务托管在公共云中,应采取额外的安全措施,例如 HTTPS 连接、某种形式的身份验证。如何启用这些安全特性的示例代码可以在我的 GitHub 项目中找到。Cherrypy 教程页面提供了许多关于如何定制 web 服务的例子。
打造你自己的自动驾驶(玩具)汽车
原文:https://towardsdatascience.com/build-your-own-self-driving-toy-car-ad00a6804b53?source=collection_archive---------4-----------------------
如果你有兴趣建造自己的自动驾驶(玩具)汽车,并在此过程中学习一些人工智能概念,你应该留下来通读。
简短介绍
随着数据和计算能力的不断增加,深度学习的应用正在扰乱当今的许多行业。它的新战场之一是机器人技术。深度学习正在改变机器人在感知和控制领域的格局,这是自动驾驶汽车及其更广泛部署取得成功的关键。
深度学习工具的最新进展( TensorFlow 、 Keras 等)。)和廉价计算平台的可访问性( Raspberry Pi )使得机器人和人工智能的实验变得更加容易(而且有趣!)对于学术界和大型科技公司以外的人来说。
目标
我们将从 Udacity 自动驾驶汽车纳米度课程中获取我的行为克隆项目中描述的深度神经网络,并使用机器人操作系统( ROS )作为中间件在远程控制(RC)赛车上运行它。最终目标是让机器人能够自主完成赛道:
这只是这一领域许多近期项目中的一个,如果你在网上搜索的话,还有很多这样的项目。甚至还有比赛(最著名的一次在美国奥克兰举行),人们和这些机器人赛跑,试图打破人类最好的时间。
我的项目可能与其他项目不同的是,它使用 ROS 作为软件栈和金属之间的连接层。
这个项目是一个很好的例子,展示了深度学习如何用于端到端地训练汽车自动驾驶,并使用人工智能解决机器人的感知和控制挑战。
我如何建立一个?
让我们首先来看一下硬件,以便让您入门:
- 遥控车
- 树莓派 3
- 树莓派相机
- 广角镜头
- 伺服驱动器
- 3D 打印支架
由于我的硬件构建是基于驴车,你可以在这里获得关于硬件组装的更详细说明。你会注意到,当谈到选择你的遥控车有很多选择。在这个项目的第一次迭代中,我选择了 Elegoo 机器人汽车套件,结果证明这不是一个好主意,因为该套件没有用于控制转向角度的专用伺服系统。这使得对你的神经网络建模以及之后与自动驾驶仪的集成变得更加困难。有了磁铁,你可以更好的控制遥控车。
软件呢?
如果你很急,你也可以从驴车拿软件栈。我走了另一条路,试图通过观察驴车项目并从我以前的 Udacity 项目中吸取经验来自己构建大脑。我喜欢理查德·费曼在这个话题上的一句名言:
我无法创造的东西,我不明白。知道如何解决每一个已经解决的问题。
正如我已经提到的,我决定选择机器人操作系统(ROS)作为基于深度学习的自动驾驶仪和硬件之间的中间件。这是一个陡峭的学习曲线,但就该项目的完整代码库的大小而言,它最终完全得到了回报。
ROS 提供了强大的发布者/订阅者模型,对每个组件(摄像机、转向和油门控制、操纵杆等)的分布式节点支持。).它还具有强大的调试和日志记录功能。如果你是 ROS 新手,我强烈推荐这本书,它通过有趣的项目教你基础知识。
在我的例子中,我在车上运行了摄像机和执行器(转向和油门)节点。操纵杆、自动驾驶和训练节点正在我的台式机上运行。推理(神经网络预测)是计算密集型,所以必须将它从 Raspberry Pi 转移到更强大的机器上。
记住,你需要 Ubuntu Mate 发行版才能在你的 Raspberry Pi 上运行 ROS。这里还有一个链接用于 ROS 节点摄像头支持。
AI 呢?
汽车的自动驾驶基于现在著名的 NVIDIA 的论文,该论文使用卷积神经网络 (CNN)来预测汽车的转向角度,仅基于安装在汽车前面的摄像头的图像输入。你可以在我之前的文章中读到更多关于这个话题的内容。我最近偶然发现了这篇论文,这篇论文探索了针对同一问题的一些其他深度神经网络架构。你应该去看看!
与我之前的 Udacity 项目相比,我必须为 CNN 做的一项调整是引入宁滨数据。在以下情况下,您应该考虑使用它:
一列连续数字有太多的唯一值,无法有效地建模,因此您可以自动或手动将这些值分配给组,以创建一组较小的离散范围。
在这种情况下,连续数字列是来自操纵杆的汽车转向角度。我发现这个修改改进了我的模型预测。另一方面,油门目前是固定的,这也是我想使用预测方法的事情。
结论
参与这个项目是了解 ROS 的一个很好的方式(好处和挑战)。事实证明,ROS 被几家自主汽车/小型巴士公司用作原型平台和/或投入生产。
此外,当你把你的神经网络从模拟器中拿出来放在一辆“真正的”汽车上时,在硬件上工作可以揭示一些问题。
您在自己的机器人车上运行 ROS 节点所需的所有代码都可以在我的项目报告中找到,同时还有助手脚本:
[## 自动驾驶机器人汽车
自动驾驶机器人汽车基于 Raspberry Pi 和 Arduino 的机器人汽车,能够基于深度…
github.com](https://github.com/bdjukic/selfdriving-robot-car)
如果你住在柏林,请务必参加即将于 7 月 29 日举行的机器人比赛:
[## 柏林比赛日-黑客/比赛机器人
加入我们在海拉风险投资公司举办的柏林自动驾驶汽车和自动驾驶活动的黑客/比赛日。种族…
www.meetup.com](https://www.meetup.com/Berlin-Self-Driving-Cars-Autonomous-Mobility/events/238595677/)
第一次构建回大学/学校预算计算机
原文:https://towardsdatascience.com/building-a-back-to-uni-school-budget-computer-for-the-first-time-3e1d2b2e048b?source=collection_archive---------10-----------------------
从零开始建造一台计算机是我长久以来的一个梦想,但是我很担心,因为我缺乏计算机硬件方面的知识。相反,我经常最终购买笔记本电脑,但这些很快就会过时,不再适合我的数据科学需求。这是关于你自己建造一台计算机的最好的部分;你才是决定计算机到底是用来做什么的人!
这篇文章概述了我决定使用哪些组件,如何将它们组合在一起,以及如何在确保一切正常的情况下削减成本的过程。在此版本中,许多商品的购买价格为其建议零售价的 50% — 70% **,如下表所示,**没有性能问题。
我需要什么来开始?
耐心,而且是大量的耐心!
当然,如果费用对你来说不是一个很大的问题,那么你可以直接订购许多商品,并在几天内全部拿到。然而,如果你想要最好的交易,可能需要一段时间的网上竞价或清仓甩卖,但坚持不懈往往会得到回报。给一个总的想法,我的构建从开始到结束花了 3 到 4 周,这包括一些邮费上的延迟。
做你的研究!
有许多组件可用,但并非所有组件都兼容或最佳。这可能是压倒性的第一,因为有数百个,如果不是数千个电脑组件,它很容易丢失。然而,有一些惊人的资源可以帮助我们,并在下一节中更详细地讨论它们。
有计划,坚持!
当搜索组件时,确切地知道你要的是什么版本是有帮助的,而不是仅仅被现有的所吸引。
就是这样!
除了一些工具和一些方便的工作之外,您将准备好构建自己的工具。有些构建可能有点棘手,但这对我来说肯定不正常,组件手册将是你最好的指南。
我在哪里可以找到关于我的构建的帮助?
PC Part Picker 对于寻找兼容部件非常有用,建议您详细阅读评论,了解每个组件的优点和缺点:
[## 挑选零件。构建您的 PC。对比分享。— PCPartPicker 英国
构建您自己的 PC 并需要从哪里开始的想法?浏览我们的构建指南,其中涵盖了适用于所有人的系统…
uk.pcpartpicker.com](https://uk.pcpartpicker.com/)
有大量的书面指南,许多组件包含的说明通常有助于构建方面,但我发现 YouTube 是一个惊人的资源,许多创作者提供了关于构建计算机的详细建议,我将列出一些我最喜欢的:
OzTalksHW
Oz 为所有规格的预算构建提供了一个很好的来源,如果你愿意冒险,它展示了直接从中国进口的最便宜的组件。
RandomGamingHD
另一位 budget build 创建者经常测试仍然可用且功能正常的旧组件的性能,甚至在他的本地转储中保存旧显卡以免被销毁。
克里斯多福莉娅
有趣的是,一个最初是业余电影制作人的 YouTuber 用户找到了自己的位置,他展示个人电脑的组装,呼吁卖家在二手市场上定价过高,并展示,如果运气好的话,你可以买到二手物品的交易。
这些是我使用的主要渠道,但还有更多,你经常可以找到针对你的构建甚至特定组件的视频。
我想要我的电脑做什么?
这完全取决于你,但就我的目的而言,我想要符合以下标准(按重要性排序)的东西:
- 强大到足以运行数据科学模型
- 尽可能便宜
- 安静且低功耗,因此可以整夜运行
- 微妙的美学和运输相当容易
- 未来可升级
你自己的需求会有所不同,但我想要一些东西,可以在一夜之间运行我的一些机器学习模型,但我不能花一大笔钱这样做。因此,在构建时考虑了项目成本和运行机器的电费。
功耗可能是你甚至没有想过的事情,但是,当你考虑到许多家庭比特币采矿爱好者正在因为运行他们的机器的成本超过他们是我的成本而却步时,如果你正在买单,这可能值得考虑。
一旦你决定了什么对你的构建是重要的,那么你就可以开始考虑哪些组件是最好的。为了符合我的标准,我决定尽可能选择最小的版本,它目前足够强大,如果需要的话,以后可以很容易升级,而且成本效益高。
需要哪些组件?
与你可能认为的相反,如今制造一台计算机非常简单,而且经常被比作将乐高积木拼在一起。我很惊讶这个过程是如此的简单,甚至没有任何经验的人也能做到。
要创建一台完整的计算机,您需要以下部件:
-处理器(称为 CPU)和冷却器
-图形卡(称为 GPU)
-主板
-内存(也称为 RAM)
-存储(称为硬盘)
-凯斯
-电源(被称为 PSU)
我应该买哪些组件?
处理器和显卡
我的构建围绕着 AMD 的新锐龙处理器。这些不仅是英特尔系列的一个很好的预算选择,而且他们还发布了两个也有集成显卡的处理器;锐龙 3 2200 克和锐龙 5 2400 克。这意味着他们根本不需要显卡就可以运行游戏并达到中端显卡的性能!
因此,我能够从构建中完全排除对独立显卡的需求,从而降低至少 150 英镑的成本。当然,这永远无法满足一个独立处理器和一个高端显卡组合的全部性能,但如果达到最大图形性能不是一个优先事项,并且对于一些游戏来说已经足够了,这是一个很好的预算解决方案。
外壳和电源
CPU 和 GPU 都包括在内,然后我考虑我想要的美学。我认为一个小而有吸引力的案例很重要,并把重点放在了作为完美解决方案的 分形节点 202 上。这种外壳不仅很小(大约是 PS4 或 Xbox One 的大小),而且还带有内置电源单元。然而,在选择这个案例时,我需要考虑一些重要的挑战:
-所提供的电源在功率输出、效率和安全性方面是否足够好?
-这会导致我的其他组件出现兼容性问题吗?
首先,机箱的电源提供 450 瓦的功率,因为我们没有单独的显卡,这足以为组件供电。你可以用 这个计算器 检查你的体型,我的体型被计算出大约 200W,用显卡更接近 400W。电源也通过了青铜认证,这基本上确保了它为计算机提供能量的效率相当高,并且不会作为热量浪费掉,这有利于降低能源成本。这也提供了一些安全保证,有一些更便宜的情况下,也包括电源可用,但没有认证,这是一个风险,可能会损坏您的电脑和家用电器。
母板
有了这些决定,然后我必须找到一个兼容的主板。这是最棘手的部分,也是由于选择有限,我最终以全价购买的唯一主要组件。因为机箱的大小,我被迫需要最小的主板,被称为迷你 ITX。此外,由于 AMD 的处理器作为 CPU 和 GPU 的功能是新的,只有一定范围的最新主板开箱即用。因此,我决定购买微星的新 B450I 迷你 ITX 主板,内置 Wi-Fi 和蓝牙。
https://www . Amazon . co . uk/gp/product/b 07 fnmlctc/ref = oh _ aui _ detail page _ o01 _ s00?ie=UTF8 & psc=1
这种购买感觉像是一个巨大的风险,因为在制作这种产品的日期没有对该产品的评论,但我能够找到几个早期测试 YouTube 视频,证实它应该与处理器兼容,所以我决定值得冒这个风险,因为它比任何替代品便宜近 100 英镑。
内存储器
有了这个主板,我就被要求购买一种通常用于笔记本电脑的 M.2 存储类型。我强烈推荐使用 SSD 存储设备作为主系统,一个很好的总结可以在这里找到但是总之 SSD 运行得更快。如果您需要更多存储空间,您可以随时添加大容量硬盘驱动器,但使用固态硬盘作为您的主要设备将缩短启动时间,甚至缩短 windows 中的文件加载时间。我能够在易贝上购买一个 250GB 的三星 960 evo SSD,对于操作系统和基本使用来说,这已经足够大了。
记忆
然后,我不得不购买一些内存(或 RAM ),并再次需要检查兼容性。理解 RAM 可能有点棘手,但我会尽力总结我的发现。
RAM 有三个质量衡量标准,第一个是 DDR2、DDR3 和 DDR4(https://en.wikipedia.org/wiki/DDR_SDRAM)类别,为了与我的主板配合工作,我需要 DDR 4 类型。
第二个衡量标准是由 MHz 数量表示的内存速度,因为我们使用 AMD 的锐龙 5 2400g 处理器,所以建议使用 至少 3000MHz 的两个棒以获得理想的性能 。
最后,我需要在 8GB、16GB 或 32GB 之间决定所需的内存量。由于 ram 目前很贵,我决定 8GB 对我来说应该足够了,如果需要,以后可以很容易地升级。
冷却
最后,您需要考虑如何确保所有组件都保持冷却并且不会过热。因为这个版本不包括图形卡,所以事情变得简单了一些,但是处理器冷却非常重要。AMD 的锐龙 5 2400g 配备了一个股票风扇包括这是伟大的预算建设,但因为我的情况是如此之薄,这不太可能适合。因此,我决定购买一个 更薄的风扇单元 ,其中包括导热膏,足以让我的组件保持良好的温度。
下图显示了组装前的所有组件:
很难建议您想要购买哪些物品,因为您需要仔细考虑您的需求以及您需要哪些组件。然而,我希望这能让我对我的构建过程有所了解,从而对你有所帮助。
我的建议是决定你需要的一两个组件,例如最快的处理器、最好的显卡或有吸引力的外壳,然后以此为起点寻找其他兼容的组件。如前所述,PC Part Picker 在建议哪些组件适合您的构建方面做得非常出色,评论甚至提供了更多建议。
我怎样才能省钱?
我能够以零售价的 50%-70%在易贝和清仓甩卖上竞价购买我的许多部件。这比简单地购买新的花费更长的时间,但是只要有一点耐心和明智的选择,你就能以低于零售价的价格买到所需的大部分(如果不是全部)部件。
我从 CeX(一家英国零售店)购买了机箱、易贝的 SSD M.2 硬盘和 RAM 以及 AMD 锐龙处理器。不幸的是,如前所述,由于产品太新,主板必须以全价购买。
最终价格汇总如下:
总的来说,我的构建成本约为 470 英镑,通过谨慎购买,我在组件上节省了 200 至 250 英镑。此外,我不仅能够通过一些运气在 AMD 处理器上获得一笔惊人的交易,而且我还通过首先不需要构建显卡至少节省了 250 英镑(英伟达 RTX 1060 6GB)。
购买处理器是有风险的,因为该产品在网上的描述中几乎没有任何信息,并认为这可能是一个错误。然而,处理器来了,工作完美,虽然它没有任何包装或股票冷却器风扇,但这不是一个问题,我的建设,因为股票风扇不会适合的情况下,无论如何。
如果我决定不把它放进这么小的盒子里,成本可能会进一步降低,但它仍然比任何笔记本电脑替代品、类似性能的预建配置甚至新手机都要便宜得多,我对自己能够找到的交易感到惊讶。
如何将这些组件组合在一起?
现在你有了所有的部分,你需要把它们拼在一起,而且通常会按照一定的顺序排列,这样它们才能正确的组合。对齐取决于您购买的产品和构建的类型,但主板和机箱可能应该有一个过程的良好描述。另外,我在网上找到了我正在处理的案件的视频,以确保我的过程是正确的。
对于我的构建,过程如下:
1.将 CPU 安装到主板上,
2.使用导热膏,连接 CPU 风扇并插入主板
3.安装 M.2 固态硬盘
4.安装内存
5.将主板(带端口导轨)放入机箱内
6.将电源线连接到指定的主板插座
除了一些棘手的对齐问题,我发现最后一步是最难的。大多数电缆匹配是显而易见的,但我花了一段时间来找出从外壳的前面电源开关连接电缆的地方,但能够很容易地在网上找到解决方案,并使用主板手册。此外,请确保在连接电源和用电器工作时要小心,你最不希望的就是意外触电!
我应该安装哪个操作系统?
为了方便使用,我最终安装了 windows 10,这可能很贵,但我能在易贝上找到一个便宜的激活密钥。第一次安装时,我按照以下指南从 u 盘运行 window 的安装程序:
http://www . toms guide . com/FAQ/id-3694993/create-bootable-USB-installer-windows . html
如果你真的预算紧张,那么 Linux 是一个很好的选择,它完全免费,并且有一些令人惊讶的界面。如果你愿意接受挑战,你甚至可以在电脑上安装 Mac IOS 来创建一个“黑客电脑”,但这不是我感兴趣的事情。
最终想法
我从组装电脑和在线竞标组件中获得了很多乐趣。这花了一些时间,但值得耐心,并强烈建议任何有兴趣升级其硬件的人这样做,并希望您发现这对您自己的构建想法有用。
与任何网上投标一样,在寻找好的交易时要耐心和小心,以确保你没有买到描述不佳、不起作用的产品。此外,请确保您研究了哪些组件是兼容的,并在头脑中为您想要的构建类型保持一个明确的目标。
最后,你可能要考虑市场价格。例如,我选择避免使用显卡,因为价格处于历史高位,Nvidia 的最新产品系列将很快发布,因此旧产品的价格可能会下降。如果我有耐心,我可以等待主板价格下跌,甚至拯救自己,但这是一个权衡,你将不得不决定自己的建设。
谢谢
哲学(philosophy 的缩写)
构建贝叶斯深度学习分类器
原文:https://towardsdatascience.com/building-a-bayesian-deep-learning-classifier-ece1845bc09?source=collection_archive---------5-----------------------
在这篇博客文章中,我将教你如何使用 Keras 和 tensorflow 来训练贝叶斯深度学习分类器。在深入具体的培训示例之前,我将介绍几个重要的高级概念:
- 贝叶斯深度学习是什么?
- 什么是不确定性?
- 为什么不确定性很重要?
然后,我将介绍两种在深度学习模型中包含不确定性的技术,并查看一个使用 Keras 在 cifar10 数据集上的冻结 ResNet50 编码器上训练完全连接的层的具体示例。通过这个例子,我还将讨论探索贝叶斯深度学习分类器的不确定性预测的方法,并提供未来改进模型的建议。
感谢
这篇文章基于两篇博客文章(这里和这里)和剑桥大学机器学习小组关于贝叶斯深度学习的白皮书。如果你在读完这篇文章后想了解更多关于贝叶斯深度学习的知识,我鼓励你查看所有这三个资源。感谢剑桥大学机器学习小组令人惊叹的博文和论文。
贝叶斯深度学习是什么?
Visualizing a Bayesian deep learning model.
贝叶斯统计是统计领域中的一种理论,其中关于世界真实状态的证据是用信任度来表示的。贝叶斯统计和深度学习在实践中的结合意味着在你的深度学习模型预测中包含不确定性。早在 1991 就提出了在神经网络中包含不确定性的想法。简而言之,贝叶斯深度学习在典型神经网络模型中发现的每个权重和偏差参数上添加了先验分布。在过去,贝叶斯深度学习模型并不经常使用,因为它们需要更多的参数来优化,这可能使模型难以工作。然而,最近,贝叶斯深度学习变得更加流行,新技术正在开发中,以在模型中包括不确定性,同时使用与传统模型相同数量的参数。
什么是不确定性?
An example of ambiguity. What should the model predict?
不确定性是一种知识有限的状态,无法准确描述现有状态、未来结果或一个以上的可能结果。当它涉及深度学习和分类时,不确定性也包括模糊性;人类定义和概念的不确定性,不是自然界的客观事实。
不确定性的类型
有几种不同类型的不确定性,在这篇文章中我将只讨论两种重要的不确定性。
任意不确定性
随机不确定性衡量的是你无法从数据中理解的东西。它可以用观察所有解释变量的能力来解释。把随机不确定性想象成感知不确定性。实际上有两种类型的随机不确定性,异方差和同方差,但是我在这篇文章中只讨论异方差不确定性。在的这篇博客文章中,对同性恋进行了更深入的探讨。
立体图像中任意不确定性的具体例子有遮挡(相机看不到的场景部分)、缺乏视觉特征(如空白墙壁)或曝光过度/不足区域(眩光和阴影)。
Examples of occlusions, lack of visual features and under/over exposure.
认知不确定性
认知不确定性衡量的是由于缺乏训练数据,模型不知道什么。它可以用无限的训练数据来解释。将认知不确定性视为模型不确定性。
观察认知不确定性的一个简单方法是在 25%的数据集上训练一个模型,在整个数据集上训练第二个模型。仅在 25%的数据集上训练的模型将比在整个数据集上训练的模型具有更高的平均认知不确定性,因为它看到的例子更少。
一个有趣的认知不确定性的例子在现在著名的非热狗应用中被发现。从我自己使用该应用程序的经验来看,该模型表现非常好。但仔细观察后发现,这个网络似乎从未被训练过“不是热狗”的图片,这些图片中的物品上有番茄酱。因此,如果给模特看一张你腿上沾有番茄酱的照片,模特会被骗以为那是热狗。贝叶斯深度学习模型将预测这些情况下的高度认知不确定性。
为什么不确定性很重要?
在机器学习中,我们试图创建真实世界的近似表示。今天创建的流行深度学习模型产生点估计,但不是不确定性值。了解您的模型是过于自信还是过于自信有助于您对模型和数据集进行推理。上面解释的两种不确定性是重要的,原因各不相同。
注意:在分类问题中,softmax 输出为每个类别提供了一个概率值,但这与不确定性不同。softmax 概率是一个输入相对于其他类成为给定类的概率。因为概率是相对于其他类的,所以它无助于解释模型的总体置信度。
为什么任意不确定性很重要?
Even for a human, driving with glare is difficult
在观察空间的一部分比其他部分具有更高噪声水平的情况下,随机不确定性是很重要的。例如,任意的不确定性在第一起涉及无人驾驶汽车的死亡事故中发挥了作用。特斯拉表示,在这起事件中,汽车的自动驾驶仪未能识别明亮天空下的白色卡车。能够预测任意不确定性的图像分割分类器将认识到图像的这个特定区域难以解释,并预测高度不确定性。在特斯拉事件中,尽管汽车的雷达可以“看到”卡车,但雷达数据与图像分类器数据不一致,汽车的路径规划器最终忽略了雷达数据(已知雷达数据有噪声)。如果图像分类器在其预测中包含高度不确定性,则路径规划者将会知道忽略图像分类器预测,而使用雷达数据(这过于简单,但实际上将会发生。参见下面的卡尔曼滤波器)。
为什么认知不确定性很重要?
认知不确定性很重要,因为它识别模型从未被训练理解的情况,因为这些情况不在训练数据中。机器学习工程师希望我们的模型能够很好地概括与训练数据不同的情况;然而,在深度学习的安全关键应用中,希望是不够的。高认知不确定性是一个危险信号,表明模型更有可能做出不准确的预测,当这种情况发生在安全关键应用中时,该模型不应被信任。
认知的不确定性也有助于探索你的数据集。例如,认知的不确定性可能有助于 20 世纪 80 年代发生的这个特定的神经网络灾难。在这种情况下,研究人员训练了一个神经网络来识别隐藏在树中的坦克和没有坦克的树。经过训练后,网络在训练集和测试集上表现得非常好。唯一的问题是,所有坦克的图像都是在阴天拍摄的,所有没有坦克的图像都是在晴天拍摄的。这个分类器实际上已经学会了辨别晴天和阴天。哎呦。
Tank & cloudy vs no tank & sunny
Radar and lidar data merged into the Kalman filter. Image data could be incorporated as well.
深度学习模型中的不确定性预测在机器人技术中也很重要。我目前就读于 Udacity 自动驾驶汽车纳米学位,并一直在学习汽车/机器人用于识别和跟踪物体的技术。自动驾驶汽车使用一种叫做卡尔曼滤波器的强大技术来追踪物体。卡尔曼滤波器组合一系列包含统计噪声的测量数据,并产生比任何单个测量更精确的估计。传统的深度学习模型无法对卡尔曼滤波器做出贡献,因为它们只预测结果,不包括不确定项。理论上,贝叶斯深度学习模型可以有助于卡尔曼滤波器跟踪。
计算深度学习分类模型中的不确定性
任意不确定性和认知不确定性是不同的,因此,它们的计算方式也不同。
计算任意不确定性
任意不确定性是输入数据的函数。因此,深度学习模型可以通过使用修改的损失函数来学习预测任意的不确定性。对于分类任务,贝叶斯深度学习模型将有两个输出,softmax 值和输入方差,而不是仅预测 softmax 值。教导模型预测任意方差是无监督学习的一个示例,因为模型没有方差标签可供学习。下面是标准分类交叉熵损失函数和计算贝叶斯分类交叉熵损失的函数。
我创建的损失函数是基于这篇论文中的损失函数。在本文中,损失函数创建了一个均值为零的正态分布和预测方差。它通过从分布中采样来扭曲预测的 logit 值,并使用扭曲的预测来计算 softmax 分类交叉熵。损失函数运行 T 个蒙特卡罗样本,然后取 T 个样本的平均值作为损失。
Figure 1: Softmax categorical cross entropy vs. logit difference for binary classification
在图 1 中,y 轴是 softmax 分类交叉熵。x 轴是“正确的”logit 值和“错误的”logit 值之间的差值。“右”表示该预测的正确类别。“错误”表示该预测的错误类别。我将使用术语“logit difference”来表示图 1 中的 x 轴。当“logit difference”在图 1 中为正时,softmax 预测将是正确的。当“logit difference”为负时,预测将是不正确的。在解释任意损失函数时,我将继续使用术语“逻辑差”、“正确的”逻辑和“错误的”逻辑。
图 1 有助于理解正态分布失真的结果。当使用正态分布对 logit 值(在二元分类中)进行扭曲时,这种扭曲实际上创建了一个正态分布,其原始预测“logit 差异”和预测方差的平均值作为分布方差。将 softmax 交叉熵应用于失真的 logit 值与沿着图 1 中的线对“logit 差异”值进行采样是相同的。
对扭曲的逻辑取分类交叉熵应该理想地产生一些有趣的性质。
- 当预测的 logit 值远大于任何其他 logit 值时(图 1 的右半部分),增加方差只会增加损失。这是真的,因为导数在图的右半部分是负的。即,与“logit difference”的相等减少相比,增加“logit difference”仅导致 softmax 分类交叉熵的稍微更小的减少。在这种情况下,最小损耗应该接近于 0。
- 当“错误的”logit 远大于“正确的”logit(图的左半部分)且方差为0 时,损失应为
wrong_logit-right_logit
。你可以看到这在图 1 的右半部分。当“logit 差”为-4 时,softmax 交叉熵为 4。图中这一部分的斜率为~ -1,因此随着“logit 差异”继续减小,这应该是正确的。 - 为了使模型能够学习任意的不确定性,当“错误的”logit 值大于“正确的”logit 值(图的左半部分)时,对于大于 0 的方差值,损失函数应该最小化。对于具有高度随机不确定性的图像(即,模型很难对该图像做出准确预测),该特征鼓励模型通过增加其预测方差来在训练期间找到局部损失最小值。
当“错误的”logit 值大于“正确的”logit 值时,我能够使用论文中建议的损失函数通过增加方差来减少损失,但是由于增加方差而减少的损失非常小(<0.1). During training, my model had a hard time picking up on this slight local minimum and the aleatoric variance predictions from my model did not make sense. I believe this happens because the slope of Figure 1 on the left half of the graph is ~ -1. Sampling a normal distribution along a line with a slope of -1 will result in another normal distribution and the mean will be about the same as it was before but what we want is for the mean of the T samples to decrease as the variance increases.
To make the model easier to train, I wanted to create a more significant loss change as the variance increases. Just like in the paper, my loss function above distorts the logits for T Monte Carlo samples using a normal distribution with a mean of 0 and the predicted variance and then computes the categorical cross entropy for each sample. To get a more significant loss change as the variance increases, the loss function needed to weight the Monte Carlo samples where the loss decreased more than the samples where the loss increased. My solution is to use the elu 激活函数,这是一个以 0 为中心的非线性函数)。
ELU activation function
我将 elu 函数应用于分类交叉熵的变化,即原始未失真损失与失真损失的比较,undistorted_loss - distorted_loss
。对于图 1 的左半部分,elu 将正态分布的平均值从零移开。对于接近 0 的非常小的值,elu 也是线性的,因此图 1 右半部分的平均值保持不变。
Figure 2: Average change in loss & distorted average change in loss.
在图 2 中,right < wrong
对应于图 1 左半部分的一个点,而wrong < right
对应于图 2 右半部分的一个点。您可以看到,“错误”logit 情况下的结果分布看起来类似于正态分布,而“正确”情况下的结果大多是接近零的小值。将-elu
应用于损失变化后,right < wrong
的均值变得更大。在本例中,它从-0.16 变为 0.25。wrong < right
的意思保持不变。我将图 2 中下方图表的平均值称为“失真的平均损失变化”。随着图 1 右半部分方差的增加,“失真平均损耗变化”应保持在 0 附近,并且当图 1 右半部分方差增加时,应始终增加。
然后,我用原始未失真的分类交叉熵来衡量“失真的平均损失变化”。这样做是因为对于所有大于 3 的 logit 差异,错误 logit 情况下的失真平均损失变化大致相同(因为线的导数为 0)。为了确保损失大于零,我添加了未失真的分类交叉熵。“损失的扭曲平均变化”总是随着方差的增加而减少,但是对于小于无穷大的方差值,损失函数应该最小化。为了确保最小化损失的方差小于无穷大,我添加了方差项的指数。如图 3 所示,方差的指数是方差超过 2 后的主要特征。
Figure 3: Aleatoric variance vs loss for different ‘wrong’ logit values
Figure 4: Minimum aleatoric variance and minimum loss for different ‘wrong’ logit values
这些是针对二元分类示例计算上述损失函数的结果,在该示例中,“正确”的 logit 值保持为常数 1.0,而“错误”的 logit 值会针对每一行发生变化。当“错误的”logit 值小于 1.0(因此小于“正确的”logit 值)时,最小方差为 0.0。随着错误的“logit”值增加,使损失最小化的方差也增加。
注意:在生成此图时,我运行了 10,000 次蒙特卡洛模拟来创建平滑的线条。在训练模型时,我只运行了 100 次蒙特卡洛模拟,因为这应该足以得到一个合理的平均值。
Brain overload? Grab a time appropriate beverage before continuing.
计算认知不确定性
对认知不确定性建模的一种方式是在测试时使用蒙特卡罗抽样(一种变分推理)。关于为什么辍学可以模拟不确定性的完整解释,请查看这篇博客和这篇白皮书。实际上,蒙特卡洛漏失抽样意味着将漏失包括在模型中,并在测试时打开漏失多次运行模型,以创建结果分布。然后可以计算预测熵(预测分布中包含的平均信息量)。
为了理解如何使用 dropout 来计算认知不确定性,可以考虑将上面的猫狗图像垂直分成两半。
如果你看到左半部分,你会预测狗。如果你看到右半边,你会预测猫。完美的五五分成。这个图像会有很高的认知不确定性,因为这个图像展示了你同时与猫类和狗类相关联的特征。
下面是计算认知不确定性的两种方法。它们做完全相同的事情,但是第一个更简单,只使用 numpy。第二种使用额外的 Keras 层(并获得 GPU 加速)来进行预测。
注意:认知不确定性不用于训练模型。当评估测试/真实世界的例子时,它仅在测试时间(但是在训练阶段)被计算。这不同于随机的不确定性,随机的不确定性是作为训练过程的一部分被预测的。此外,根据我的经验,产生合理的认知不确定性预测比随机不确定性预测更容易。
训练贝叶斯深度学习分类器
除了上面的代码之外,训练贝叶斯深度学习分类器来预测不确定性不需要比通常用于训练分类器更多的代码。
在这个实验中,我使用 Resnet50 中的冻结卷积层和 ImageNet 的权重来编码图像。我最初试图在不冻结卷积层的情况下训练模型,但发现模型很快变得过度拟合。
我的模型的可训练部分是 ResNet50 输出之上的两组BatchNormalization
、Dropout
、Dense
和relu
层。使用单独的Dense
层计算逻辑值和方差。注意,方差层应用了一个softplus
激活函数来确保模型总是预测大于零的方差值。然后,针对任意损失函数重新组合 logit 和 variance 图层,并仅使用 logit 图层计算 softmax。
我使用两个损失来训练模型,一个是任意的不确定性损失函数,另一个是标准的分类交叉熵函数。这允许创建 logit 的最后一个Dense
层只学习如何产生更好的 logit 值,而创建方差的Dense
层只学习预测方差。两个先前的Dense
层将在这两个损失上训练。任意不确定性损失函数的权重小于分类交叉熵损失,因为任意不确定性损失包括分类交叉熵损失作为其一项。
我用了 100 次蒙特卡罗模拟来计算贝叶斯损失函数。每个历元大约需要 70 秒。我发现,将蒙特卡洛模拟的次数从 100 次增加到 1000 次,每个训练周期会增加大约 4 分钟。
Example image with gamma value distortion. 1.0 is no distortion
我通过随机应用 0.5 或 2.0 的伽玛值来降低或增加每张图像的亮度,向训练集添加了增强数据。在实践中,我发现 cifar10 数据集没有很多理论上表现出高度随机不确定性的图像。这大概是故意的。通过向训练集中的图像添加具有调整的灰度值的图像,我试图给模型更多的图像,这些图像应该具有高度的随机不确定性。
不幸的是,预测认知的不确定性需要相当长的时间。在我的 Mac CPU 上,完全连接的层预测训练集的所有 50,000 个类大约需要 2-3 秒,但预测认知不确定性需要 5 分钟以上。这并不奇怪,因为认知的不确定性需要对每张图像进行蒙特卡罗模拟。我运行了 100 次蒙特卡洛模拟,因此有理由预计预测认知不确定性所需的时间是随机不确定性的 100 倍。
最后,我的项目被设置为在未来轻松切换底层编码器网络和其他数据集的训练模型。如果您想更深入地训练自己的贝叶斯深度学习分类器,请随意使用它。
结果
Example of each class in cifar10
我的模型在测试数据集上的分类准确率是 86.4%。这无论如何都不是一个惊人的分数。我能够得到高于 93%的分数,但只是牺牲了随机不确定性的准确性。有几个不同的超参数我可以用来提高我的分数。我花了很少的时间调整两个损失函数的权重,我怀疑改变这些超参数可以大大提高我的模型精度。我也可以解冻 Resnet50 层,并训练这些。虽然在这个数据集上获得更好的准确性分数是有趣的,但贝叶斯深度学习是关于预测和不确定性估计的,所以我将在这篇文章的剩余部分评估我的模型的不确定性预测的有效性。
Figure 5: uncertainty mean and standard deviation for test set
任意的不确定性值往往比认知的不确定性小得多。这两个值不能在同一个图像上直接比较。但是,可以将它们与该模型针对该数据集中的其他图像预测的不确定性值进行比较。
Figure 6: Uncertainty to relative rank of ‘right’ logit value.
为了进一步探索不确定性,我根据正确 logit 的相对值将测试数据分成三组。在图 5 中,“第一个”包括所有正确的预测(即“右”标签的 logit 值是最大值)。“第二”,包括“右”标签是第二大 logit 值的所有情况。“休息”包括所有其他情况。86.4%的样本属于“第一”组,8.7%属于“第二”组,4.9%属于“其余”组。图 5 显示了这三组测试集的随机和认知不确定性的平均值和标准偏差。正如我所希望的,认知和任意的不确定性与“正确”逻辑的相对等级相关。这表明模型更有可能将不正确的标签识别为它不确定的情况。此外,当模型的预测正确时,模型预测大于零的不确定性。我希望这个模型能够展现出这种特性,因为即使它的预测是正确的,这个模型也可能是不确定的。
Images with highest aleatoric uncertainty
Images with the highest epistemic uncertainty
以上是随意性和认知不确定性最高的图像。虽然看这些图像很有趣,但我不太清楚为什么这些图像有很高的随意性或认知不确定性。这是训练图像分类器产生不确定性的一个缺点。整个图像的不确定性减少到单个值。理解图像分割模型中的不确定性通常要容易得多,因为比较图像中每个像素的结果更容易。
“Illustrating the difference between aleatoric and epistemic uncertainty for semantic segmentation. You can notice that aleatoric uncertainty captures object boundaries where labels are noisy. The bottom row shows a failure case of the segmentation model, when the model is unfamiliar with the footpath, and the corresponding increased epistemic uncertainty.” link
如果我的模型很好地理解了随机不确定性,那么我的模型应该为具有低对比度、高亮度/暗度或高遮挡的图像预测更大的随机不确定性值。为了测试这一理论,我将一系列伽马值应用于我的测试图像,以增加/减少增强图像的像素强度和预测结果。
Figure 7: Left side: Images & uncertainties with gamma values applied. Right side: Images & uncertainties of original image.
该模型在增强图像上的准确度为 5.5%。这意味着伽玛图像完全欺骗了我的模型。该模型没有被训练成在这些伽马失真上得分很高,所以这是意料之中的。图 6 显示了左侧的八个增强图像的预测不确定性和右侧的八个原始不确定性和图像。前四幅图像具有增强图像的最高预测随机不确定性,后四幅图像具有增强图像的最低随机不确定性。我很兴奋地看到,与原始图像相比,该模型预测了每个增强图像更高的任意性和认知不确定性!随机不确定性应该更大,因为模拟的不利照明条件使图像更难理解,而认知不确定性应该更大,因为模型没有在具有较大伽马失真的图像上训练。
后续步骤
这篇文章中详细描述的模型只探索了贝叶斯深度学习冰山的一角,并且展望未来,我相信我可以通过几种方式来改进模型的预测。例如,我可以继续使用损失权重,并解冻 Resnet50 卷积层,看看我是否可以在不失去上述不确定性特征的情况下获得更好的精度分数。我还可以尝试在一个数据集上训练一个模型,这个数据集有更多表现出高度随机不确定性的图像。一个候选是德国交通标志识别基准数据集,我在我的一个 Udacity 项目中使用过它。这个数据集专门用于使分类器“应对由于光照变化、部分遮挡、旋转、天气条件而导致的视觉外观的巨大变化”。对我来说听起来像是随机的不确定性!
除了尝试改进我的模型,我还可以进一步探索我的训练模型。一种方法是看我的模型如何处理对立的例子。为此,我可以使用像伊恩·古德费勒创建的 CleverHans 这样的库。这个库使用一个对抗性的神经网络来帮助探索模型漏洞。看看 CleverHans 产生的对立例子是否也会导致高度的不确定性,这将是很有趣的。
另一个我很想探索的库是 Edward,这是一个用于概率建模、推理和评论的 Python 库。 Edward 支持创建具有概率分布的网络图层,并使其易于执行变分推断。这篇博文使用 Edward 在 MNIST 数据集上训练贝叶斯深度学习分类器。
如果你已经做到了这一步,我非常感动和感激。希望这篇文章激发了你在下一个深度学习项目中加入不确定性。
原载于gist.github.com。
建立一个更好的(模型)世界:我们在算法中歪曲世界的 3 种方式
原文:https://towardsdatascience.com/building-a-better-model-world-3-ways-we-misrepresent-the-world-in-algorithms-ad27318654b6?source=collection_archive---------9-----------------------
这篇文章是在阅读了凯茜·奥尼尔的《数学毁灭的武器》后收集的想法和观点。没必要读过这本书就去读这篇文章,但如果你感兴趣,这里有一篇发表在《科学美国人》上的 评论 和一篇 NPR 对作者的采访 。
“大多数人说是智力造就了伟大的科学家。他们错了:这是性格。”
我相信爱因斯坦是对的——就像他在大多数事情上一样——当他这样说的时候。科学家有一个重大的责任:他们已经签约研究我们无限复杂的世界,并告诉我们其余的人它是如何工作的。
我们相信科学界,说:“我们相信你教给我们的是真实的,尽你所知。”这就是为什么我们在围绕科学工作的通用语:调查研究做决定、建立我们的企业和塑造我们的生活时感到舒适。这就是为什么我们的药物和医疗设备来自实验室,也是为什么我们被标题为“科学支持的提高生产力的五种方法”的博客帖子所吸引
智慧和好奇心造就了一名优秀的科学家,但是一名伟大的科学家必须有坚强的道德支柱和锻炼这种支柱的纪律。根据爱因斯坦的说法,仅仅研究某样东西是不够的——我们还必须确定我们是否应该研究它,我们的方法是否合乎道德,我们的结果是否会塑造一个更美好的世界。(更不用说对我们的结果保持诚实。)
数据科学领域最近也出现了同样的讨论——具体来说,数据科学家有责任主动警惕他们算法中的偏差。
作为程序员,我们可以很容易地按照别人告诉我们的去做。作为人类,我们很容易忘记与我们长相不同的人的世界是什么样的。
所以,我们来谈谈固有偏见是如何抬起它丑陋的头的。
过度简化世界的危险🌎
我们的大脑不擅长处理复杂性。
这就是为什么我们不断地寻找模式(即使它们不存在)。模式是决定的精神捷径,作为懒惰的人类,我们都喜欢捷径。因此,我们常常忍不住求助于刻板印象和其他简化(但错误)的启发式方法。
我们通过简化世界和在精神上删除无用的东西,在不断的刺激中生存下来——如果我们诚实的话,这并不总是让我们非常客观。
简化意味着选择什么是重要的,什么是不重要的,把现实世界变成一个模型或它自己的玩具版本。当谈到感知世界时,我们的大脑选择我们突出和记住的特征。当涉及到构建算法来代表世界时,人类会做出选择。
以下是我们作为算法设计者曲解或歪曲世界的方式:
- 👥把人们分成几组。
从算法上判断一个人最公平的方式是基于他们过去的行为(这与你测量的结果直接相关),而不是人口统计数据或其他属性。当我们做后者时,我们使用描述符或特征将人们分组,并问“像你这样的人过去是如何表现的?”用最基本的术语来说,你是刻板印象。
奥尼尔在这上面花了很多时间。她称之为“斗”,“一丘之貉”,或者“像你一样的人”模型。
这种简化经常表现出来。书中的例子包括芝加哥警察局的预测性警务——当一个没有暴力犯罪历史的 22 岁年轻人被警察拜访并被告知“小心”,因为他们的分析将他与他在脸书的朋友归类为罪犯——以及由 Kroger 等雇主实施的性格测试——其中一项测验对申请人的外向性和宜人性(以及其他品质)进行评分,并根据过去得分类似的员工对她将成为一名多么优秀的员工以及她将持续多久做出判断。
另一种看待这个问题的方式是,你不应该预测人们在他们还没有真正经历过的情况下会有什么行为。在实践中,这是一条很难走的路,有时很难走,尤其是在你没有历史数据的情况下。
在书中,奥尼尔强调 FICO 信用评分是一个正确的公式。FICO 分数是根据你过去是否支付过贷款/账单来计算的,用来预测同样的行为:你将来是否会继续支付。无论你对 FICO 的其他措施有什么不满,正如奥尼尔所说,“色盲”。
也许有一天我们会有虚拟现实设置,我们可以在不同的情况下测试人们(你会再次犯罪吗?你会继续拖欠贷款吗?)而不必遵从像邮政编码这样简单的特征。
- 🤑让我们的激励成为其他人的激励。
一般来说,为算法付费的人可以决定目标是什么,成功是什么样子。但是有一个论点是,你需要考虑每一组利益相关者或潜在用户想要什么和需要什么。
当你从外部研究一个算法时,寻找制造它的人的固有偏见——以及支付它的人的动机。
可悲的是,通常情况下,利润将代表真理——换句话说,如果算法在赚钱或省钱,那么它一定是正确的或好的。但是如果你从别人的角度来看,你会发现这实际上并不是一个胜利。
这方面的一个例子是 Starbucks 调度算法,该算法偶然发现了调度“clopenings”,即员工会在最后一个班次工作,然后在第一个班次开始第二天的工作(相差几个小时)。这为星巴克节省了一些福利支出和加班费,但如果你问员工,这是一种极端的生活方式和健康压力。
- 🎛选择代理人或使用替代品。
我们已经说过,人类是懒惰的。我们选择走最短的路去得到我们想要的东西。同样,公司也很便宜。他们选择花最少的钱和努力来实现一个目标。
当谈到算法时,这意味着用户和利益相关者将改变他们的行为来影响任何被测量的东西,这一切都是为了确保他们得到他们想要的结果。
当你设计一个算法时,你必须主动考虑用户可能会发现哪些“漏洞”来欺骗系统,然后决定你是否能忍受这些。
例如,人们在简历中加入职位描述中的关键词,以通过职位申请系统,因此在某种程度上,简历是从职位描述倒过来写的,而不是从申请人的技能倒过来写的。
另一个例子是一年一度的《美国新闻与世界报道》学院和大学排名。一所大学将近四分之一的分数是由其他学校的校长和院长的意见决定的,所以实际上是鼓励大学花钱互相营销和做广告,而不是像学生那样。
整个行业都可以从这些漏洞中诞生,比如搜索引擎优化专家和商学院应用顾问。
危险在于,替代品可能是可游戏的,而不是驾驶或测量有机行为,这才是你的真正目标。人类会迎合你的输入。您衡量的内容将推动行为。
一个更好的模型世界…
破坏数学的武器充满了个人的故事,他们的生活受到了数据科学家建立的模型的影响。一名男子被判较长的刑期,因为一名男子说他很可能再次犯罪。一位单身母亲,由于“文凭工厂”将她标记为一个容易的目标,她的债务呈螺旋式下降。一个好老师因为双极算法依赖于他控制之外的输入而丢了工作。
当我们建立算法时,我们需要与真实的人交谈,因为我们创造的东西与真实的人打交道,并以非常真实的方式影响他们。
因此,数据科学家不应该被关在房间里。她应该始终如一地与她的终端用户——一大批终端用户——互动。
直面我们无意识偏见的最简单方法是从受其影响的人那里听到后果。
奥尼尔还建议在代码投入生产之前进行“算法审计”。如果我们将我们的算法视为黑盒,我们可以客观地研究输出,以拼凑模型的假设,并确定它们实际上有多公平。
当然,这些检查说起来容易做起来难,因为大多数算法存在于需要利润的公司和需要工资的员工中。但从长远来看,我们希望所有人都能认识到,代表世界现状的模式——旨在让世界比现在更公平、更平等——将增加我们的经济,让我们所有人受益,不会让我们的邻居进一步陷入债务,让他们继续坐牢,或拒绝他们就业。
…以及我们如何到达那里
因此,下次您构建模型或编写代码时,请考虑您选择输入或数据源的原因,并尝试客观地看待您的模型世界。
想象一下将会受到影响的个人。走出你的方式去满足他们,并理解任何不适合你的模型代表世界的方式的边缘情况。分享你算法的输入,问他们这些是否公平。
如果可能的话,在你的模型投入使用之前,先对它进行实验。输入不同的输入组合,尤其是你能想象到的黑盒发展的任何偏差,然后观察它是如何发展的。
一旦我们更加关注我们的代码所处的世界,并且能够诚实地面对我们设计中潜在的非故意缺陷,我们就可以通过尝试调整激励、基于过去的行为寻找输入以及避免代理(或者至少认识到我们所使用的代理)来更加深思熟虑地制作算法。或许通过这样做,我们可以更接近真实地展现世界。
特别感谢 柯特罗伯茨 & 王丽红 进行编辑并给予反馈。
感谢阅读!我是一名前风投和生物医学工程师,痴迷于 NLP 和小说写作。在Twitter或LinkedIn上与我联系。
使用 Keras 和 tfjs 构建血细胞分类模型
原文:https://towardsdatascience.com/building-a-blood-cell-classification-model-using-keras-and-tfjs-5f7601ace931?source=collection_archive---------4-----------------------
人工智能真的是一个重大的游戏改变者。人工智能的应用是巨大的,它在医疗保健领域的范围是巨大的。先进的人工智能工具可以帮助医生和实验室技术人员更准确地诊断疾病,例如,尼日利亚的医生可以使用这种工具从血液样本中识别他根本不知道的疾病,这有助于他更好地了解疾病,从而可以更快地开发治疗方法,这是人工智能民主化的一个优势,因为人工智能模型和工具在世界各地都可以使用, 尼日利亚的医生可以使用麻省理工学院或世界上任何其他大学的研究学者正在使用的工具和技术。
机器学习的主要问题:
机器学习当然是今天人工智能进步的主要成分。但是,使人工智能民主化意味着建立一个基础设施,允许任何人在世界各地使用相同的技术来构建强大的工具。可能阻止任何人构建人工智能的两个主要问题是计算能力和训练数据集的不可用性。但是这些问题正在以有趣的方式得到解决,它们如下:
- **Kaggle(数据集之家):**数据集的不可用性是主要问题之一,但 Kaggle 是人们可以创建数据集并托管它们以供他人使用的最佳场所,人们已经使用这些工具创建了令人惊叹的东西。
- **谷歌联合实验室:**谷歌联合实验室是机器学习的主要驱动力,它允许任何拥有谷歌账户的人访问 GPU。没有这些 GPU,任何人都不可能训练需要巨大计算量的 ML 模型。
血细胞数据集
对于数据科学家来说,数据集就像一座金矿,如果数据集可用于特定问题,它将减少工程团队所需的大量工作,因为不需要开发基础架构来收集和存储数据。几个月前,我想开发这个系统,Kaggle 帮了我很多,以获得数据集。这是我在 Kaggle 上找到的数据集,感谢保罗·穆尼提供了这个数据集。
**数据集结构:**数据集包含 12,500 个血细胞的增强图像。数据集由 4 个类组成,如下所示:
Classes of blood cell dataset
每个类包含 3000 幅图像。该图显示了每个类别的示例图像:
Sample images from all classes
我把每张图片的尺寸缩小到(80×80×3)以便更容易训练。
Kaggle 要求您在下载数据集之前登录,因为我们使用的是 colab,所以不需要将数据集下载到我们的本地机器上,而是将它拉到我们的 google colab 实例中。
使用谷歌联合实验室
简单地说,谷歌联合实验室提供了一个基于云的 python 笔记本,其中有一个虚拟实例绑定到 GPU 运行时,谷歌 colab 的 GPU 运行时由 NVIDIA k-80 提供支持,这是一个强大的 GPU,也很昂贵。但是 co-lab 允许我们免费使用 GPU,而无需付费。一个实例的最大时间是 12 小时,12 小时后该实例将被销毁并创建一个新的,所以我们只能执行那些不超过 12 小时的计算。让我们看看如何使用 colab 来训练我们的神经网络。
向 Kaggle 认证:
Kaggle CLI 允许您下载数据集并向竞赛提交代码/笔记本。注册 kaggle 后,您可以下载 kaggle.json 文件,其中包含所有凭据,kaggle CLI 使用这些凭据进行授权。
- 创建一个新的单元格,并创建一个名为。kaggle,使用命令
!mkdir .kaggle
- 使用 pip:在新单元中安装 ka ggle CLI—
!pip install kaggle
- 下载数据集:
!kaggle datasets download -d paulthimothymooney/blood-cells
- 确保所有目录都存在于下载的数据集中
!ls dataset2-master/images
- 您应该看到 3 个目录:TEST、TEST_SIMPLE 和 TRAIN
- 目录 TRAIN 包含训练图像,我们将使用这个目录作为训练图像。
预处理:
我们需要将图像作为 numpy 数组加载,并将其提供给我们正在训练的神经网络。我们将使用 Keras 来构建一个神经网络,Keras 提供了一个内置的 ImageDataGenerator 来处理大多数预处理任务。
我们导入了开发模型所需的一些对象:
**from** **keras.models** **import** Sequential
**from** **keras.layers** **import** Dense, Conv2D, Dropout, MaxPool2D, Flatten
**from** **keras.preprocessing** **import** image
keras.preprocessing
提供处理各种类型数据集所需的方法和对象。从图像模块中,我们创建一个具有所有必需配置的 ImageDataGenerator。
generator = image.ImageDataGenerator(
rescale = 1./255,
featurewise_center=**False**, *# set input mean to 0 over the dataset*
samplewise_center=**False**, *# set each sample mean to 0*
featurewise_std_normalization=**False**, *# divide inputs by std of the dataset*
samplewise_std_normalization=**False**, *# divide each input by its std*
zca_whitening=**False**, *# apply ZCA whitening*
rotation_range=10, *# randomly rotate images in the range (degrees, 0 to 180)*
width_shift_range=0.1, *# randomly shift images horizontally (fraction of total width)*
height_shift_range=0.1, *# randomly shift images vertically (fraction of total height)*
horizontal_flip=**True**, *# randomly flip images*
vertical_flip=**False**)
如前一节所述,训练数据存在于``dataset2-master/images/TRAIN`目录中,我们提供此路径到 ImageDataGenerator,以便我们所有的配置和扩充都应用于训练图像。
dataset = generator.flow_from_directory(
shuffle = **True**,
batch_size = 32,
target_size = (80, 80),
directory = 'dataset2-master/images/TRAIN'
)
这都是关于预处理,你可以调整这些参数,通过减少或增加图像增强的效果,使之更好地拟合,总有改进的余地。
CNN 简介:
CNN(卷积神经网络)是一种神经网络,它包含一组卷积层和一个与之相连的前馈网络。卷积运算并不是一个新的运算,它在图像处理中的应用已经很多年了。卷积运算的主要作用是从图像中提取边缘,换句话说,它们可用于提取图像的重要特征。如果已知所谓的滤波器值,任何人都不可能确定任何图像的最佳滤波器值,因为我们将卷积与神经网络一起使用,梯度下降将自动优化滤波器值以提取图像的最重要特征。吴恩达的课程 deeplearning.ai 帮助你更好地理解这种网络的工作方式。因为这超出了本文的范围。
我们的网络:
这项任务必须使用 CNN,因为简单的前馈网络不可能学习数据集中每个类的独特特征。我们使用的 CNN 架构如下所示:
Neural Network Architecture
我创建了一个函数模型(),它返回一个顺序模型,如下所示:
**def** model():
model = Sequential()
model.add(Conv2D(80, (3,3), strides = (1, 1), activation = 'relu'))
model.add(Conv2D(64, (3,3), strides = (1, 1), activation = 'relu', input_shape = (80, 80, 3)))
model.add(MaxPool2D(pool_size = (2,2)))
model.add(Conv2D(64, (3,3), strides = (1,1), activation = 'relu'))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, activation = 'relu'))
model.add(Dropout(0.5))
model.add(Dense(4, activation = 'softmax'))
model.compile(loss = 'categorical_crossentropy', optimizer = 'adadelta', metrics = ['accuracy'])
**return** model
最后,我们训练模型,如下所示:
nn = model()
nn.fit_generator(dataset, steps_per_epoch = **None**, epochs = 30, verbose = 1)
nn.save('Model.h5')
模型经过 30 个历元的训练,得到了 92.67% 的精度**,这是一个很好的精度,你可以增加更多的层或者进行超参数调整来提高精度。**
部署模型:
一旦训练完成,我们需要将模型部署到生产中,以便每个人都可以使用它,有各种策略可用于部署机器学习系统。我想在客户端机器上运行整个推理,所以我开始构建一个可以这样做的 web 应用程序。
设置先决条件:
我们需要以下要求来建立一个客户端应用程序,该应用程序具有以下架构:
App architrcture
安装节点和 npm 并设置环境,以相同的顺序安装以下依赖项:
npm install -g create-react-app
create-react-app app_name
cd app_name
npm install --save @tensorflow/tfjs//on server side:
mkdir server
cd server
npm init
//fill up the details, make sure package.json is created
npm install express --save
模型服务器:这是一个 express.js REST 端点,客户端可以通过发送 REST GET 请求来请求模型文件。(在服务器端)
**模型存储:**我们需要创建一个与 tfjs 兼容的模型,tensorflow 提供了一个名为 tensorflowjs 的工具,这是一个包含实用程序的 python 工具包,我们可以使用下面的命令来安装:
pip install tensorflowjs
完成后,我们可以使用下面的命令使用 tensorflowjs_converter 将模型转换为 tfjs 格式:
$tensorflowjs_converter --input_format keras \
Model.h5 \
ModelData/model_data
// Model.h5 is the downloaded model after training, last argument is the target folder, where we need to store the model files.
一旦转换,它将创建一组称为碎片的文件,碎片是通过基于层分割模型获得的,每个碎片包含特定层的权重。使用碎片非常有帮助,因为每个碎片可以存储在不同的地方,并且可以在需要时下载,所以我们可以为我们的机器学习模型建立一个分布式存储。 model.json 当然是包含各个分片信息的文件。如果我们改变一个碎片的目录,我们可以修改这个文件。在 API 调用中,我们只将 model.json 文件发送给客户端,tfjs 将自动获取每个碎片以在客户端机器(即浏览器)上组装一个模型。
最后一部分:开发客户端推理机
在这一节中,我不会过多强调 UI 设计,相反,我会强调推理部分,即如何使用我们安装的 tfjs 运行推理。转到 react 应用程序目录。
- **创建一个模型容器类:**我首先为我们的模型创建了一个包装类。这个类的一个实例表示一个准备好进行推理的模型。这个模型类的代码是自我可理解的:
- **一个推理函数:**我定义了一个函数,可以取模型对象和输入图片源,输入源可以是 HTML img,或者 URL,或者图片的字节流。
代码如下所示:
- **初始化模型对象:**我们现在必须创建一个模型对象来保存一个用于推理的模型。
**let** modelCache = **new** ModelContainer(null);
modelCache.loadFromURL('http://192.168.0.105:5443/model_metadata')
- **运行推理:**一旦我们有了一个模型对象,我们就可以随时运行推理,根据我设计的 UI,每当用户点击 predict 按钮时,就应该执行推理。因此,运行预测的 React 组件部分如下所示:
结论
这个项目对我来说真的是一次很棒的经历,我学会了如何使用 google colab 在云上训练 ML 模型,我也学会了如何为生产部署 ML 模型。
这是一个开源项目,请随意更改:
回购网址: 反应-客户
云笔记本(模型训练用): training.ipynb
非常感谢您花费宝贵的时间阅读本文。如果你感兴趣,请开始回购。也可以在 Linkedin 上联系我。
干杯!
使用 Keras 构建图书推荐系统
原文:https://towardsdatascience.com/building-a-book-recommendation-system-using-keras-1fba34180699?source=collection_archive---------8-----------------------
如何使用嵌入创建图书推荐系统?
Figure 1: Photo by Brandi Redd on Unsplash
推荐系统试图预测用户在给出其旧的项目评级或偏好的情况下将给予项目的评级或偏好。几乎每个大公司都使用推荐系统来提高他们的服务质量。
在本文中,我们将看看如何使用嵌入来创建图书推荐系统。
对于我们的数据,我们将使用 goodbooks-10k 数据集,其中包含一万本不同的书籍和大约一百万个评级。它有三个特性 book_id、user_id 和 rating。如果你不想自己从 Kaggle 下载数据集,你可以从我的 Github 库获得文件以及本文中的完整代码。
把...嵌入
嵌入是从离散对象到连续值向量的映射,比如我们的例子中的单词或书籍的 id。这可用于查找离散对象之间的相似性,如果模型不使用嵌入层,这些相似性对模型来说是不明显的。
嵌入向量是低维的,并且在训练网络时被更新。下图显示了使用 Tensorflows 嵌入投影仪创建的嵌入示例。
Figure 2: Projector Embeddings
获取数据
熊猫将用于数据集中的加载。然后,数据将被分成一个训练和测试集,我们将创建两个变量,为我们提供唯一的用户和图书数量。
dataset = pd.read_csv('ratings.csv')
train, test = train_test_split(dataset, test_size=0.2, random_state=42)
n_users = len(dataset.user_id.unique())
n_books = len(dataset.book_id.unique())
Figure 3: Rating-Dataset Head
数据集已经被清理,所以我们不需要采取任何进一步的数据清理或预处理步骤。
创建嵌入模型
Keras 深度学习框架使得创建神经网络嵌入以及使用多个输入和输出层变得容易。
我们的模型将具有以下结构:
- **输入:**书籍和用户的输入
- **嵌入层:**书籍和用户的嵌入
- **点:**使用点积合并嵌入
在嵌入模型中,嵌入是在训练期间学习的权重。这些嵌入不仅可以用于提取关于数据的信息,还可以被提取和可视化。
出于简单的原因,我没有在最后添加任何完全连接的层,尽管这可能会增加相当多的准确性。因此,如果你想要一个更准确的模型,这是可以尝试的。
下面是创建模型的代码:
from keras.layers import Input, Embedding, Flatten, Dot, Dense
from keras.models import Modelbook_input = Input(shape=[1], name="Book-Input")
book_embedding = Embedding(n_books+1, 5, name="Book-Embedding")(book_input)
book_vec = Flatten(name="Flatten-Books")(book_embedding)user_input = Input(shape=[1], name="User-Input")
user_embedding = Embedding(n_users+1, 5, name="User-Embedding")(user_input)
user_vec = Flatten(name="Flatten-Users")(user_embedding)prod = Dot(name="Dot-Product", axes=1)([book_vec, user_vec])
model = Model([user_input, book_input], prod)
model.compile('adam', 'mean_squared_error')
训练模型
现在我们已经创建了我们的模型,我们准备训练它。因为我们有两个输入层(一个用于书籍,一个用于用户),所以我们需要指定一个训练数据数组作为我们的 x 数据。对于本文,我训练了 10 个时期的模型,但是如果你想得到更好的结果,你可以训练更长的时间。
以下是培训代码:
history = model.fit([train.user_id, train.book_id], train.rating, epochs=10, verbose=1)
model.save('regression_model.h5')
可视化嵌入
嵌入可以用来可视化概念,比如我们案例中不同书籍之间的关系。为了可视化这些概念,我们需要使用降维技术进一步降低维度,如主成分分析(PSA) 或t-分布式随机邻居嵌入(TSNE) 。
从 10000 个维度(每本书一个)开始,我们使用嵌入将它们映射到 5 个维度,然后使用 PCA 或 TSNE 将它们进一步映射到 2 个维度。
首先,我们需要使用 get_layer 函数提取嵌入内容:
# Extract embeddings
book_em = model.get_layer('Book-Embedding')
book_em_weights = book_em.get_weights()[0]
现在,我们将使用 PCA 将我们的嵌入转换为二维,然后使用 Seaborn 散布结果:
from sklearn.decomposition import PCA
import seaborn as snspca = PCA(n_components=2)
pca_result = pca.fit_transform(book_em_weights)
sns.scatterplot(x=pca_result[:,0], y=pca_result[:,1])
Figure 4: Visualizing embeddings with PCA
使用 TSNE 也可以做到这一点:
from sklearn.manifold import TSNEtsne = TSNE(n_components=2, verbose=1, perplexity=40, n_iter=300)
tnse_results = tsne.fit_transform(book_em_weights)
sns.scatterplot(x=tnse_results[:,0], y=tnse_results[:,1])
Figure 5: Visualizing embeddings with TSNE
提出建议
使用我们训练过的模型进行推荐很简单。我们只需要输入一个用户和所有的书,然后选择对这个特定用户有最高预测评分的书。
下面的代码显示了为特定用户进行预测的过程:
# Creating dataset for making recommendations for the first user
book_data = np.array(list(set(dataset.book_id)))
user = np.array([1 for i in range(len(book_data))])
predictions = model.predict([user, book_data])
predictions = np.array([a[0] for a in predictions])
recommended_book_ids = (-predictions).argsort()[:5]
print(recommended_book_ids)
print(predictions[recommended_book_ids])
此代码输出:
array([4942, 7638, 8853, 9079, 9841], dtype=int64)
array([5.341809 , 5.159592 , 4.9970446, 4.9722786, 4.903894 ], dtype=float32)
我们可以使用图书 id,通过使用 books.csv 文件来获得关于图书的更多信息。
books = pd.read_csv(‘books.csv’)
books.head()
Figure 6: Book-Dataset Head
print(books[books[‘id’].isin(recommended_book_ids)])
Figure 7: Recommended books
结论
嵌入是一种从离散对象(如单词)到连续值向量的映射方法。它们对于寻找相似性、可视化目的以及作为另一个机器学习模型的输入是有用的。
这个例子当然不是完美的,为了获得更好的性能,可以尝试很多方法。但是对于更高级的问题,这是学习如何使用嵌入的一个很好的起点。
您可以添加一些东西来获得更好的结果:
- 在点积后添加完全连接的层
- 为更多时代而训练
- 缩放评级栏
- 等等。
如果你喜欢这篇文章,可以考虑订阅我的 Youtube 频道并在社交媒体上关注我。
如果你有任何问题或批评,可以通过 Twitter 或评论区联系我。
使用自然语言处理构建一个机器人来应对 Reddit 上的负面评论
原文:https://towardsdatascience.com/building-a-bot-to-counter-negative-comments-on-reddit-using-natural-language-processing-83177e5c8d32?source=collection_archive---------7-----------------------
Reddit 是一个分享一切的神奇网站,它的口号是“互联网的首页”。它甚至在最近取代脸书成为美国第三大最受欢迎的网站。与其他社交媒体网站相比,Reddit 的独特之处在于用户可以匿名发帖。这种匿名性是 Reddit 如此受欢迎的部分原因,但正如任何好事一样,它也有一些负面影响。
几乎没有任何后果的发帖能力意味着几乎在任何提交的文章中都会有负面评论。虽然这些通常是建设性的批评,但少量的可能是全面的,令人讨厌的,总体上对讨论没有建设性。幸运的是,这些通常会很快被其他用户突出显示并否决,如果不够不受欢迎,可能会被隐藏。然而,那些向更小的子群(Reddit 上的子群)提交原创内容的人可能会受到这些负面评论的影响。这是我在一些小的子网站上发帖并收到如下评论后的亲身经历:
发布关于你自己的内容,尤其是图片,可能需要很多努力和信心,这样的评论让人很难继续投稿。不幸的是,我们的思维会自然地关注负面而不是正面的评论。
**每当这种情况发生,我的第一个问题总是‘你凭什么判断?’。**你是对这个子话题有所贡献并有权利不屑一顾的人吗?还是你只是路过,只是从对别人的刻薄中得到乐趣?
然而,我还没有脸皮薄到相信负面评论,不管它们是怎么写的,本质上都是不好的。任何提交到 subreddit 的人都需要了解他们在向谁发帖,以及这是否相关,接受建设性的批评只是这个过程的一部分。例如,在贴出我童年服装的拼贴画后,我收到了下面的回复。现在,这是否仅仅是一个个人观点还可以讨论,但是我承认我的观点可能不适合这个子主题,并且从这个话题中学到了很多。
目标
我想创建一个 Python 机器人,当它被使用时,它可以对用户的判断做出反应,当被调用时,它可以消除负面评论不公平恶意的情况。
基于在 Reddit 上的观察逻辑,如果有人发表了我认为没有建设性的负面评论,我愿意回答如下:
1.用户的账号有多老?(也就是说,他们是否躲在一个新账户后面,不会因为被否决而承担任何后果?)
2.这个用户向 subreddit 提交了多少次他们自己的帖子?
3.用户整体评价中负面的比例是多少?
4.用户对这个子编辑的评论有多大比例是负面的?
如果我能确定这些,那么我希望要么将用户归类为某个似乎在网站上持续负面的人,要么,也许这是不寻常的,他们只是过了糟糕的一天。
设置机器人
为了构建这个机器人,我遵循了 pythonforengineers.com 的T3编写的指南,该指南使用 Python 包 Praw 从 Reddit 的 API 中提取信息。
按照这个指南,第一步是让机器人找到负面的评论。出于前面提到的原因,用户会在使用特定文本短语时专门调用该机器人。为了做到这一点,我将机器人命名为“FloBot ”,如果用户在这里留下评论,机器人就会找到评论并开始分析父评论。下面显示了一个测试示例:
为了测试,我创建了 subreddit/r/flobot review,其中显示了一个测试帖子,演示了机器人给出的响应。机器人将检查对该子编辑的每个评论,如果任何评论包含“FloBot ”,它将选取该评论,然后查看该评论所响应的评论:
for comment_tracker in subreddit.stream.comments(): if re.search("FloBot", comment_tracker.body, re.IGNORECASE): comment = comment_tracker.parent()
然后,我们可以浏览并找出一些关于评论的基本信息(如上图所示),如作者、文本(以防后来被删除)和当前分数。
print("Subreddit: ", comment.subreddit)print("Author: ", comment.author)print("Text: '", comment.body,"'")print("Score: ", comment.score)
自然语言处理
这个过程的一部分是使用一些自然语言处理来确定被提问的用户写的评论是积极的还是消极的。为此,我使用了 Python 包 TextBlob ,它现在允许我们非常容易地分析文本的质量。我们使用这个包来确定评论的主观性和极性,如上面的例子所示。极性是我们将用来确定用户历史评论的负面性,并在以后更广泛地使用。
print("Sentiment Analysis Subjectivity: ", np.round(TextBlob(comment.body).sentiment.subjectivity,4))print("Sentiment Analysis Polarity: ", np.round(TextBlob(comment.body).sentiment.polarity,4))
分析用户的历史帖子和评论
我们现在有了完成分析的基础,我们已经连接了 Reddit 的 API,以:
-找到我们想要反驳的评论
-收集用户的基本信息
-应用一些 NLP 来评估评论文本的负面性。
因为我们已经收集了负面评论作者的名字,所以我们现在可以遍历并收集他们所有的评论,并在 for 循环中计算每个评论的极性。一旦我们对每个评论都有了这些信息,我们就收集这些信息作为 Pandas 数据表,其中包含以下信息:
仅用这张表,我们就可以计算:
-总的评论数量
-负分数评论的百分比
-负面评论的百分比
-发布到此子编辑的评论数量
-发布到此子编辑中的负得分评论的百分比
-发布到此子编辑的具有负极性的评论的百分比
此外,我们可以使用 Python 包 NLTK 来查找负面评论中最常用的单词。
最后,我们可以为用户的提交重复这个过程,以计算他们在这个子编辑中发布的帖子的数量。一旦我们获得了所有这些信息,我们就可以在一些标准文本中很好地对其进行格式化,以产生以下输出:
看起来我已经做出了相当多的负面评论,但总体来说,只有不到 2%的人投了反对票。看来我的评论 http://链接到 imgur.com 被否决最多。
进一步的工作
我已经在 Kaggle 上分享了我的机器人的完整代码,它目前不会自动发布,但在我部署它之前,我需要确保以下问题得到解决。
首先,需要评估自然语言处理的质量,如果可能的话,还需要改进。这个第一阶段只是为了演示这个想法,极性测量肯定还有改进的空间。
此外,如果我要考虑部署它,我将需要考虑它可能被用户错误地滥用和调用的可能性。我希望有一个检查系统在这之前自动响应到位,以确保用户不使用它只是欺负其他用户或其他邪恶的原因。
最后,我想在回复中再补充一点,包括一些例句,比如“这个人通常不会在这个帖子里发表负面评论,也许他们今天过得很糟糕。”给我们的机器人增加一点生命力。
我希望你喜欢这个想法,如果你有任何意见或建议,请让我知道。
谢谢
哲学(philosophy 的缩写)
构建碳分子自动编码器
原文:https://towardsdatascience.com/building-a-carbon-molecule-autoencoder-21973e5f88b6?source=collection_archive---------14-----------------------
是什么让碳分子如此特别
化学信息学是一个不断发展的领域,与人工智能一样,原因之一是:可用数据的增加。不可阻挡的数据增长预计不会放缓,有报告显示数据预计在未来十年每两年翻一番。
Welcomes to the information age; data might become the new dollar
这很重要,因为历史上,我们计算算法的准确度和精确度只受到我们给它们的数据的限制。
但是,尽管文本、视觉和数字等流行数据类型数量激增,化学信息却停滞不前。
缺乏数据的原因有很多:
- 化学数据没有单一的标准格式
- 化学数据是离散的,非常脆弱
- 实验数据经常被边缘化并被保密
解决数据问题的最好方法是充分利用现有资源,否则就自己创造数据。令人欣慰的是,网上不乏大量未标记的化学数据,如 Chemspider 、 Pubchem 和 Chemexpr 。未标记数据非常适合无监督学习,在无监督学习中,输入数据不需要预先分配相应的标记数据集列表。
使用 Pubchem 上的未标记碳目录,我建立了一个深度自动编码器,其中潜在层由神经网络(NN)认为是未标记微笑数据集中最重要的细节组成。
项目碳编码
自动编码器是一种神经网络架构,通过它输出被有意训练成尽可能与输入相似。
如果你输入一朵花的图片,输出应该尽可能看起来像原来的花。
The architecture of a vanilla autoencoder
它有一种美学上令人愉悦的对称形状。数据被压缩到红色的潜在层,类似于压缩文件。然而,自动编码器并不一定比其他压缩算法更好。所以我们有一个算法,它输出的东西和它的输入非常相似,这并不比其他压缩算法好多少;那么自动编码器有什么用呢?
自动编码器对于其架构中特定的 T21 部分很有用;隐藏层。也称潜在层,本质上是数据最重要特征的浓缩层。
这使得自动编码器非常适合降维和降噪。
该项目分为 4 个部分:
- 导入和规范化 SMILES 字符串数据
- 将规范化字符串转换为一个热点向量
- 构建深度神经网络模型
- 编译模型并拟合数据
该数据集是超过 12,000 个碳基分子的列表。选择单一元素是为了让自动编码器的潜在层能够学习使碳分子与其他元素相比具有独特性的特征。碳也被选中,因为它是最通用的元素之一,因此有一个更大的具有更多多样性的数据集,这有利于减少过度拟合。
Just a couple examples of carbon based molecules in the dataset
自动编码器被训练以识别其输入和输出之间的损失,以便模型学习最佳地复制给定的输入。输入层由 63 个节点组成,通过大小为 32 和 14 的另外两个过滤器。每层大约减半节点数,直到达到潜在层中 7 个节点的瓶颈。在完成编码过程时,操作被反转,并且解码器的每层的节点数量相对于编码器对称地增加。因此,经过训练的模型对碳分子的独特结构有着牢固的把握。
你可以把它想象成一瓶神奇的精华,让碳变得如此多才多艺。
一旦训练完成,潜在层可以用于生成模型,将普通自动编码器转换为可变自动编码器(VAE)。理论上,这种 VAE 能够产生新的碳分子,其中一些可能在材料科学、纳米技术或生物技术中有用。该模型还可以用作对抗性自动编码器(AAE) 的基础,这是另一种类型的生成算法,在关于药物等分子生成的研究实验中表现优于 VAEs。
Chemical design of a molecule using generative A.I
潜在层为它所压缩的数据的大量新见解提供了基础。人工智能可能会在数据中发现我们以前不知道的模式或特征。
Charged 项目的所有代码和数据集都可以在我的 Github 上的这个库中找到。
我们刚刚开始使用人工智能来帮助科学学科的研究人员加快他们的方法,产生更准确的结果,并为他们的假设提供验证。随着好处越来越为人所知,这两个领域的专家之间的合作被摒弃,我们的数据集将会增长,我们人工智能的力量也将增长。
关键要点
- 数据现在是世界上最有价值的资源之一,但仍然很少找到干净的标记化学数据
- 自动编码器似乎有悖直觉,但对于其架构的一个特定部分:潜在层,却有着巨大的潜力
- 自动编码器从输入数据中压缩和提取最重要的细节;我们可以在生殖人工智能中利用这种压缩
- 变异的自动编码器和敌对的自动编码器已经在生殖人工智能领域和科学界掀起了波澜
还在看这个?想要更多吗?不确定下一步该做什么?
- 分享到 LinkedIn 、脸书,或者 Twitter !(顺便加我)
- 查看我的作品集了解更多酷项目、内容和更新!
- 在任何平台上寻求问题、合作和想法!
向前!
使用对象检测和 OCR 构建聊天机器人
原文:https://towardsdatascience.com/building-a-chat-bot-with-image-recognition-and-ocr-721ee7b2a70b?source=collection_archive---------9-----------------------
在本系列的第 1 部分中,我们让我们的机器人能够从文本中检测情绪并做出相应的响应。但这是它能做的全部,而且不可否认相当无聊。
当然,在真实的聊天中,我们经常发送各种媒体:从文本、图像、视频、gif 到任何其他东西。所以在这里,我们旅程的下一步,让我们给机器人一个愿景。本教程的目标是让我们的机器人接收图像,回复它们,并最终给我们一个关于图像中主要物体的粗略描述。
我们开始吧!
如果您还没有跟进,您可以在这里找到最新的代码:
所以我们要修改的代码在我们的事件响应循环方法中,这里:
我们的机器人已经对图像做出反应,但它不知道它们是什么,并且以一种相当温和的方式做出反应。
我们可以试一试,自己看看。让我们启动我们的服务器(和 ngrok),并向我们的机器人发送一个图像。
到目前为止一切顺利。我们的机器人至少知道它何时接收到图像。
在这个系列中,我们一直使用 google cloud APIs,所以对于我们的图像检测,我们将使用 Google Cloud Vision。按照这里的快速入门来设置您的项目:https://cloud . Google . com/vision/docs/quick start-client-libraries。记得使用我们在第 1 部分中设置的同一个项目。
一旦你完成了这些,现在是时候回到编码上来了。让我们将以下内容添加到我们的 Gemfile 中,并运行 bundle install:
gem 'google-cloud-vision'
让我们在 main.rb 中添加以下内容:
require ‘google/cloud/vision’
接下来,我们想要创建云语言 API 的一个实例:
You can find your project ID in your google cloud console.
我们要使用的 vision API 特性叫做 注释 。给定一个文件路径到本地机器上的一个图像,它将尝试基于我们传递给方法调用的值来识别图像。
在下面的例子中(来自 Google 的文档):
vision = [**Google**](https://googleapis.github.io/google-cloud-ruby/docs/google-cloud-vision/latest/Google.html)::[**Cloud**](https://googleapis.github.io/google-cloud-ruby/docs/google-cloud-vision/latest/Google/Cloud.html)::[**Vision**](https://googleapis.github.io/google-cloud-ruby/docs/google-cloud-vision/latest/Google/Cloud/Vision.html).[new](https://googleapis.github.io/google-cloud-ruby/docs/google-cloud-vision/latest/Google/Cloud/Vision.html#new-class_method)
image = vision.image "path/to/face.jpg"
annotation = vision.annotate image, faces: **true**, labels: **true**
annotation.faces.count *#=> 1* annotation.labels.count *#=> 4* annotation.text *#=> nil*
我们告诉 vision API 尝试识别人脸和标签。“标签”本质上是 API 确定它已经识别的对象。如果给我们一张狗的照片,我们可能会被贴上以下标签:
{
"responses": [
{
"labelAnnotations": [
{
"mid": "/m/0bt9lr",
"description": "dog",
"score": 0.97346616
},
{
"mid": "/m/09686",
"description": "vertebrate",
"score": 0.85700572
},
{
"mid": "/m/01pm38",
"description": "clumber spaniel",
"score": 0.84881884
},
{
"mid": "/m/04rky",
"description": "mammal",
"score": 0.847575
},
{
"mid": "/m/02wbgd",
"description": "english cocker spaniel",
"score": 0.75829375
}
]
}
]
}
让我们创建以下方法来利用这一功能:
上面的方法(不可否认是幼稚的)基于 Google cloud vision 的 API 的结果,获取一个文件路径并返回一个字符串。在 annotate 方法中,我们传递了一些参数,这些参数告诉 API 我们想要检测什么。
这个方法的返回(响应)是一个级联的短路流,首先检查著名的地标、任何文本,最后检查它检测到的任何对象(标签)。出于本教程的目的,这个流程纯粹是任意的和简化的(即,不要给我发电子邮件告诉我如何改进它)。
下面这张图我们来试试吧:
和结果(截断):
description: "cuisine", score: 0.9247923493385315, confidence: 0.0, topicality: 0.9247923493385315, bounds: 0, locations: 0, properties: {}
description: "sushi", score: 0.9149415493011475, confidence: 0.0, topicality: 0.9149415493011475, bounds: 0, locations: 0, properties: {}
description: "food", score: 0.899940550327301, confidence: 0.0, topicality: 0.899940550327301, bounds: 0, locations: 0, properties: {}
description: "japanese cuisine", score: 0.8769422769546509, confidence: 0.0, topicality: 0.8769422769546509, bounds: 0, locations: 0, properties: {}
由于没有地标或文本,我们收到了 API 能够检测到的标签。在这种情况下,我们看到它已被确定为“寿司”根据我对标签检测结果的经验,第二个标签(具有第二高的话题性)倾向于普通人如何识别该图片。
让我们在下面再试一次:
输出(再次被截断):
description: "wildlife", score: 0.9749518036842346, confidence: 0.0, topicality: 0.9749518036842346, bounds: 0, locations: 0, properties: {}
description: "lion", score: 0.9627781510353088, confidence: 0.0, topicality: 0.9627781510353088, bounds: 0, locations: 0, properties: {}
description: "terrestrial animal", score: 0.9247941970825195, confidence: 0.0, topicality: 0.9247941970825195, bounds: 0, locations: 0, properties: {}
我们看到了,《狮子》是第二部热播剧。
好的,另一个好的衡量标准,让我们尝试一些文本提取:
Just a screenshot of my text editor
让我们看看我们得到了什么:
2.4.2 :022 > puts analyze_image("major_general.png")
I am the very model of a modern Major-General,
I've information vegetable, animal, and mineral,
I know the kings of England, and I quote the fights historical
From Marathon to Waterloo, in order categorical;
I'm very well acquainted, too, with matters mathematical,
I understand equations, both the simple and quadratical,
About binomial theorem I'm teeming with a lot o' news, (bothered for a rhyme)
With many cheerful facts about the square of the hypotenuse.
=> nil
2.4.2 :023 >
还不错。
好吧,为了完整起见,最后一个。让我们尝试一个地标:
我们的方法给了我们:
2.4.2 :030 > puts analyze_image(“statue_of_liberty.jpg”)
Statue of Liberty
好了,我们的方法正在按预期工作,现在让我们实际使用我们的聊天机器人。
当我们通过我们的客户端(Line)向我们的聊天机器人发送一个图像时,客户端将响应体中的图像数据(以及其他相关信息)返回给我们的回调。因为我们的图像识别方法需要一个文件路径,所以我们必须将上述图像数据保存到我们的本地机器上。
让我们修改我们的方法来做到这一点。将回调方法的相关部分更改为以下内容:
这里有点不对劲。首先,我们创建一个新的 Tempfile ,并使用响应主体(图像数据)作为其内容。然后,我们将临时文件的路径传递给刚刚在控制台中测试过的分析图像方法。让我们用我们的机器人试一试,作为一个理智检查。
Such a nice bot…
它成功地为我们识别出了一个地标。
我们的机器人现在只是作为一个美化的控制台打印行工作,这不是很健谈。我们希望这个东西听起来更自然,让我们稍微清理一下我们的方法,让它听起来更“人性化”。
In fact, it is.
让我们对代码进行必要的修改。我们将修改一个现有的方法 analyze_image 并创建一个新方法get _ analyze _ image _ response。下面是:
同样,这不是一个关于 Ruby 的教程,而是概念;然而,让我们回顾一下我们刚刚做的事情。在 analyze_image 中,我们简单地删除了字符串 reply,并用我们的新方法 **get_analyze_image_response 替换它。**该方法采用一个注释对象,并基于图像中识别的对象类型,使用注释对象的描述值构建一个句子(字符串)。
我们来试试吧!
经典:
It’s a bacon cheeseburger, but I’ll give you that one.
现在是一个里程碑:
It indeed is!
就是这样!我们的机器人现在使用光学字符识别从图像中提取文本,并给我们提供它在我们发送的任何图像中找到的对象的基本描述。
目前,我们的机器人只能回复一次性消息。但是如果它有“记忆”,并且能够进行真正的对话呢?我们将在第 3 部分讨论多步沟通。
以下是我们到目前为止的所有代码:
用 d3 构建共现矩阵分析学位论文中的重叠主题
原文:https://towardsdatascience.com/building-a-co-occurrence-matrix-with-d3-to-analyze-overlapping-topics-in-dissertations-fb2ae9470dee?source=collection_archive---------4-----------------------
Thanks Min An!
我硕士学位研究的目标是在不同领域的研究人员之间激发新的合作机会。但在此之前,我需要后退一步,看看是否有任何合作已经发生。酷,但是如何开始做这件事呢?
当作者为他们的作品写摘要时,他们也会添加一些关键词。我的第一个猜测是,通过这些关键词,我可以开始看到来自不同知识领域的论文是如何相互作用的。
于是我把自己大学(2016)的所有学位论文都找来,构建了一个矩阵,把关键词重叠的作品可视化。
我有两项主要工作:获取数据和构建 d3 可视化。
1️⃣——获取数据
每次学生拿到学位,她都需要把最终论文发到这个网站:http://repositorio.ufpe.br/。为了从这些论文中获取关键词,我必须:
- 获取所有学位论文的列表
- 下载 pdf 文件
- 提取文本并获得每篇论文的关键词
🎓1 —获取所有论文的列表
多亏了 Scrapy,这部分比我想象的要容易得多。为了用框架从网站中提取数据,我们需要编写一个蜘蛛。
“蜘蛛是你定义的类,Scrapy 用它从一个网站(或一组网站)抓取信息。”来源
在 Spider 类中,我们定义了基本 URL,Scrapy 应该如何处理分页,还定义了将要提取的数据。
我得到了这个元数据:
{
'author',
'title',
'date':
'abstract',
'research_field',
'url_to_pdf'
}
📁2-下载 pdf
我构建了一个 python 脚本,使用请求、一个优雅而简单的 Python HTTP 库,为人类而建。
with open(new_file_name, 'wb') as pdf:
temp = requests.get("[http://repositorio.ufpe.br](http://repositorio.ufpe.br)" + link, stream=True)
for block in temp.iter_content(512):
if not block:
breakpdf.write(block)
🔡3 —提取文本并获得每篇论文的关键词
对于这个任务,我使用了 PyPDF2 和空间。通常作者把关键词放在摘要下面,所以我浏览 PDF 的页面,如果我找到像“关键词”和“ palavras-chave ”(在葡萄牙语中是关键词的意思)这样的词,我会把内容保存在一个 txt 文件中。
我使用 spaCy 来标记文本,因为 PDF 提取并不完美。
在这个过程之后,我得到了包含“关键词”的每一页的文本。为了只得到关键词本身,我遍历单词,得到所有跟在“关键词”后面的单词,因为它们通常是页面中的最后一项。然后,我最后将数据加载到 dataframe 中进行一些转换,并将其保存到 csv 文件中。
关键词对我想做的事情有好处吗?
我注意到的一件事是,关键字可能非常普通。如果我的目标是检查不同研究领域的主题如何相互作用,我应该分析摘要,因为在那里有更多的机会找到相互作用的点。
让我们举一个真实的例子来说明一下。对于本论文:“农民工大学生适应中的认知和非认知方面”的关键词是:
- 学术经历
- 弹性
- 执行职能
- 论证
- 大学生
但在阅读摘要时,我发现了这个:
“为了实现这些目标,进行了以下分析:描述性统计、T 检验、方差分析(ANOVA)、相关探索性双变量分析、探索性因子分析和多元线性回归。”
这篇论文来自认知心理学的研究生项目,但它的主题来自统计学,也可能来自计算机科学,对吗?关键字不能显示这一点。因此,我的下一步将是利用摘要中的文本建立一个深度学习模型。
但是我们需要从某个地方开始,所以我做了一些简单的事情:从每个研究领域得到前 10 个关键词,我假设这些词可以用来描述这个领域。
首先去做,然后做对,然后做得更好——艾迪·osmani
好了,现在我们准备开始构建可视化。
2️⃣——构建可视化
我们将使用迈克·博斯托克 悲惨世界共现矩阵作为我们的“模板”。让我们首先创建一个矩形,并将其添加到背景中:
var margin = {
top: 285,
right: 0,
bottom: 10,
left: 285
},
width = 700,
height = 700;
var svg = d3.select("graph").append("svg").attr("width", width).attr("height", height);svg.append("rect")
.attr("class", "background")
.attr("width", width - margin.right)
.attr("height", height - margin.top)
.attr("transform", "translate(" + margin.right + "," + margin.top + ")");svg.append("rect")
.attr("class", "background")
.attr("width", width)
.attr("height", height);
现在我们可以深入了解 d3 的魔力了。
1-转换数据
数据看起来像这样:
{
"nodes": [{
"group": "humanas",
"index": 0,
"name": "ADMINISTRAÇÃO"
},
{
"group": "humanas",
"index": 1,
"name": "ANTROPOLOGIA"
},
[...]
],
"links": [{
"source": 0,
"target": 0,
"value": 0.0
}, {
"source": 0,
"target": 1,
"value": 2.0
},
[...]
]
}
我们将逐行构建矩阵。首先,我们读取数据并为每一行创建一个数组。
d3.json("data/data.json", function(data) {
var matrix = [];
var nodes = data.nodes;
var total_items = nodes.length;// Create rows for the matrix
nodes.forEach(function(node) {
node.count = 0;
node.group = groupToInt(node.group);matrix[node.index] = d3.range(total_items).map(item_index => {
return {
x: item_index,
y: node.index,
z: 0
};
});
});
// Fill matrix with data from links and count how many times each item appears
data.links.forEach(function(link) {
matrix[link.source][link.target].z += link.value;
matrix[link.target][link.source].z += link.value;
nodes[link.source].count += link.value;
nodes[link.target].count += link.value;
});});
因为我们将逐行构建方块,所以我们需要浏览每一行,然后浏览每一列。
2-放置正方形并添加颜色
为了将每个方块放置在正确的位置,我们将使用 d3.scaleBand()标尺。这个 scale 的作用是获得一个包含值的数组,然后为每个数组项分配一个坐标。每个项目的所有坐标加上带宽值加起来就是总宽度。
How d3.scaleBand() words
这个规模令人敬畏,因为我们不需要手工计算。
要给每个方块添加颜色,您可以使用 d3.schemeCategory20 标度。
这是大量的新代码,让我们来看看:
d3.json("data/data.json", function(data) {[...] //transform the datavar matrixScale = d3.scaleBand().range([0, width]).domain(d3.range(total_items));
var opacityScale = d3.scaleLinear().domain([0, 10]).range([0.3, 1.0]).clamp(true);
var colorScale = d3.scaleOrdinal(d3.schemeCategory20);// Draw each row (translating the y coordinate)
var rows = svg.selectAll(".row")
.data(matrix)
.enter().append("g")
.attr("class", "row")
.attr("transform", (d, i) => {
return "translate(0," + matrixScale(i) + ")";
});var squares = rows.selectAll(".cell")
.data(d => d.filter(item => item.z > 0))
.enter().append("rect")
.attr("class", "cell")
.attr("x", d => matrixScale(d.x))
.attr("width", matrixScale.bandwidth())
.attr("height", matrixScale.bandwidth())
.style("fill-opacity", d => opacityScale(d.z)).style("fill", d => {
return nodes[d.x].group == nodes[d.y].group ? colorScale(nodes[d.x].group) : "grey";
})
.on("mouseover", mouseover)
.on("mouseout", mouseout);
});
我们还创建了一个比例来设置每个方块的不透明度。在我们的例子中,不透明度值是有至少一个关键字匹配的论文的数量。一个关键词匹配意味着一个关键词同时出现在两篇论文中。
3-添加列
我们对行做了同样的事情,但是现在我们旋转它们:
d3.json("data/data.json", function(data) {
[...] //transform the data [...] //place the squares and add colorvar columns = svg.selectAll(".column")
.data(matrix)
.enter().append("g")
.attr("class", "column")
.attr("transform", (d, i) => {
return "translate(" + matrixScale(i) + ")rotate(-90)";
});
});
4-添加文本标签
为了添加占位符,我们使用行和列选择来添加一个 svg 文本元素。
d3.json("data/data.json", function(data) {
[...] //transform the data [...] //place the squares and add color [...] //add columnsrows.append("text")
.attr("class", "label")
.attr("x", -5)
.attr("y", matrixScale.bandwidth() / 2)
.attr("dy", ".32em")
.attr("text-anchor", "end")
.text((d, i) => capitalize_Words(nodes[i].name));
columns.append("text")
.attr("class", "label")
.attr("y", 100)
.attr("y", matrixScale.bandwidth() / 2)
.attr("dy", ".32em")
.attr("text-anchor", "start")
.text((d, i) => capitalize_Words(nodes[i].name));
});
5-添加排序功能
重新组织矩阵行有助于分析。在我们的例子中,我们可以按照字母顺序、每个项目(即研究领域)的连接数量以及每个知识领域的聚类来组织它们。使用 d3.scaleBand()矩阵很容易做到这一点。
数组的每一项都对应一个程序 id,所以如果我们以不同的方式对数组排序,我们会得到每个矩阵方块不同的坐标。
// Precompute the orders.
var orders = {
name: d3.range(total_items).sort((a, b) => {
return d3.ascending(nodes[a].name, nodes[b].name);
}),
count: d3.range(total_items).sort((a, b) => {
return nodes[b].count - nodes[a].count;
}),
group: d3.range(total_items).sort((a, b) => {
return nodes[b].group - nodes[a].group;
})
};
然后,我们向 html select 标记添加功能:
d3.select("#order").on("change", function() {
changeOrder(this.value);
});function changeOrder(value) {
matrixScale.domain(orders[value]);
var t = svg.transition().duration(2000);
t.selectAll(".row")
.delay((d, i) => matrixScale(i) * 4)
.attr("transform", function(d, i) {
return "translate(0," + matrixScale(i) + ")";
})
.selectAll(".cell")
.delay(d => matrixScale(d.x) * 4)
.attr("x", d => matrixScale(d.x));
t.selectAll(".column")
.delay((d, i) => matrixScale(i) * 4)
.attr("transform", (d, i) => "translate(" + matrixScale(i) + ")rotate(-90)");
}
为了增加一个好的效果,我们还添加了一个动画的转换。
The final result
就是这样!现在我们只是添加一些白线,并为每个方块添加一个工具提示。你可以在这里看到最终结果或者在这里查看最终代码。
这只是一个开始,现在我需要做的是如何显示关键词和论文。当然,我会回到这里与你分享,哈哈
感谢阅读!😁
你觉得这篇文章有帮助吗?我尽力每个月写一篇深入的文章,当我发表新的文章时,你可以收到电子邮件。
在 Keras 中构建卷积神经网络(CNN)
原文:https://towardsdatascience.com/building-a-convolutional-neural-network-cnn-in-keras-329fbbadc5f5?source=collection_archive---------0-----------------------
深度学习正成为机器学习的一个非常受欢迎的子集,因为它在许多类型的数据上具有高水平的性能。使用深度学习对图像进行分类的一个很好的方法是建立一个卷积神经网络(CNN)。Python 中的 Keras 库使得构建 CNN 变得非常简单。
计算机使用像素来看图像。图像中的像素通常是相关的。例如,某一组像素可以表示图像中的边缘或一些其他图案。卷积用这个来帮助识别图像。
卷积将像素矩阵与滤波器矩阵或“内核”相乘,并对乘积值求和。然后卷积滑动到下一个像素,并重复相同的过程,直到覆盖了所有的图像像素。这个过程如下图所示。(关于深度学习和神经网络的介绍,可以参考我的深度学习文章这里)。
CNN (image credit)
在本教程中,我们将使用流行的 mnist 数据集。该数据集由 70,000 张 0-9 的手写数字图像组成。我们将尝试通过 CNN 确认他们的身份。
加载数据集
mnist 数据集是作为 Keras 库的一部分方便地提供给我们的,因此我们可以轻松地加载数据集。在数据集中提供的 70,000 幅图像中,60,000 幅用于训练,10,000 幅用于测试。
当我们加载下面的数据集时,X_train 和 X_test 将包含图像,y_train 和 y_test 将包含这些图像所代表的数字。
from keras.datasets import mnist#download mnist data and split into train and test sets
(X_train, y_train), (X_test, y_test) = mnist.load_data()
探索性数据分析
现在让我们来看看数据集中的一幅图像,看看我们正在处理什么。我们将绘制数据集中的第一幅图像,并使用“shape”函数检查其大小。
import matplotlib.pyplot as plt#plot the first image in the dataset
plt.imshow(X_train[0])
#check image shape
X_train[0].shape
默认情况下,mnist 数据集中每个图像的形状都是 28 x 28,所以我们不需要检查所有图像的形状。当使用真实世界的数据集时,你可能没有这么幸运。28 x 28 也是一个相当小的尺寸,所以 CNN 可以很快地浏览每张图片。
数据预处理
接下来,我们需要在训练模型时将数据集输入(X_train 和 X_test)调整为模型预期的形状。第一个数字是图像的数量(X_train 为 60,000,X_test 为 10,000)。然后是每个图像的形状(28x28)。最后一个数字是 1,表示图像是灰度的。
#reshape data to fit model
X_train = X_train.reshape(60000,28,28,1)
X_test = X_test.reshape(10000,28,28,1)
我们需要“一次性编码”我们的目标变量。这意味着将为每个输出类别创建一个列,并为每个类别输入一个二进制变量。例如,我们看到数据集中的第一个图像是 5。这意味着数组中的第六个数字将是 1,而数组的其余部分将填充 0。
from keras.utils import to_categorical#one-hot encode target column
y_train = to_categorical(y_train)
y_test = to_categorical(y_test)y_train[0]
构建模型
现在我们已经准备好构建我们的模型了。代码如下:
from keras.models import Sequential
from keras.layers import Dense, Conv2D, Flatten#create model
model = Sequential()#add model layers
model.add(Conv2D(64, kernel_size=3, activation=’relu’, input_shape=(28,28,1)))
model.add(Conv2D(32, kernel_size=3, activation=’relu’))
model.add(Flatten())
model.add(Dense(10, activation=’softmax’))
我们将使用的模型类型是顺序的。顺序是在 Keras 中建立模型的最简单的方法。它允许你一层一层地建立模型。
我们使用“add()”函数向模型中添加层。
我们的前两层是 Conv2D 层。这些卷积层将处理我们的输入图像,这些图像被视为二维矩阵。
第一层中的 64 和第二层中的 32 是每层中的节点数。根据数据集的大小,这个数字可以调高或调低。在我们的例子中,64 和 32 工作得很好,所以我们现在坚持使用它。
核大小是我们卷积的滤波器矩阵的大小。因此,内核大小为 3 意味着我们将有一个 3×3 的滤波器矩阵。回头参考介绍和第一张图片来复习一下。
激活是层的激活功能。我们将为前两层使用的激活函数是 ReLU,或修正线性激活。这种激活函数已被证明在神经网络中工作良好。
我们的第一层也接受一个输入形状。这是前面看到的每个输入图像的形状,28,28,1,1 表示图像是灰度的。
在 Conv2D 层和密集层之间,有一个“展平”层。展平用作卷积层和致密层之间的连接。
“密集”是我们将在输出图层中使用的图层类型。密集是一种标准图层类型,在许多情况下用于神经网络。
我们的输出层将有 10 个节点,每个节点对应一个可能的结果(0–9)。
激活是“softmax”。Softmax 使输出总和达到 1,因此输出可以解释为概率。然后,该模型将根据哪个选项的概率最高来进行预测。
编译模型
接下来,我们需要编译我们的模型。编译模型需要三个参数:优化器、损失和指标。
优化器控制学习速率。我们将使用“亚当”作为我们的优化器。在许多情况下,Adam 通常是一个很好的优化器。adam 优化器在整个训练过程中调整学习率。
学习率决定了计算模型最佳权重的速度。较小的学习率可能会导致更准确的权重(直到某一点),但计算权重所需的时间会更长。
我们将使用‘分类交叉熵’作为损失函数。这是最常见的分类选择。分数越低,表示模型的性能越好。
为了使事情更容易解释,当我们训练模型时,我们将使用“准确性”度量来查看验证集的准确性分数。
#compile model *using accuracy to measure model performance*
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
训练模型
现在我们将训练我们的模型。为了进行训练,我们将对我们的模型使用带有以下参数的“fit()”函数:训练数据(train_X)、目标数据(train_y)、验证数据和历元数。
对于我们的验证数据,我们将使用我们的数据集中提供给我们的测试集,我们已经将它分为 X_test 和 y_test。
历元数是模型在数据中循环的次数。在一定程度上,我们运行的时代越多,模型就会改进得越多。此后,模型将在每个时期停止改进。对于我们的模型,我们将把历元的数量设置为 3。
#train the model
model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=3)
经过 3 个时期后,我们在验证集上达到了 97.57%的准确率。这是一个非常好的开始!恭喜你,你现在已经建立了一个 CNN!
使用我们的模型进行预测
如果您想要查看我们的模型对测试数据做出的实际预测,我们可以使用 predict 函数。预测函数将给出一个包含 10 个数字的数组。这些数字是输入图像代表每个数字(0-9)的概率。编号最高的数组索引表示模型预测。每个数组的总和等于 1(因为每个数字都是一个概率)。
为了显示这一点,我们将显示测试集中前 4 幅图像的预测。
注意:如果我们有新数据,我们可以将新数据输入到 predict 函数中,以查看我们的模型对新数据做出的预测。由于我们没有任何新的未知数据,我们现在将使用测试集显示预测。
#predict first 4 images in the test set
model.predict(X_test[:4])
我们可以看到,我们的模型预测了前四幅图像的 7、2、1 和 0。
我们来对比一下这个和实际结果。
#actual results for first 4 images in test set
y_test[:4]
实际结果显示,前四个图像也是 7、2、1 和 0。我们的模型预测正确!
感谢阅读!本教程的 Github 库可以在这里找到!
建立带有张量流对象检测的定制掩模 RCNN 模型
原文:https://towardsdatascience.com/building-a-custom-mask-rcnn-model-with-tensorflow-object-detection-952f5b0c7ab4?source=collection_archive---------3-----------------------
用数据做酷事!
您现在可以使用 Tensorflow 对象检测库构建一个自定义的遮罩 RCNN 模型!掩模 RCNN 是一个实例分割模型,可以逐个像素地识别任何对象的位置。本文是我广受欢迎的帖子的第二部分,在这里我解释了 Mask RCNN 模型的基础知识,并在视频上应用了一个预先训练好的 Mask 模型。
训练掩模模型比训练对象检测模型稍微复杂一些,因为在训练时也需要对象掩模。我花了一些迭代来弄清楚这个过程,我在这里分享了关键的细节。我在一个玩具上训练了一个面具 RCNN 模型。参见下面的演示:
Custom Mask RCNN Model on a toy
你可以在我的 Github repo 上找到代码。
如果你有一个有趣的项目需要帮助,请联系我在 priya.toronto3@gmail.com
1)收集数据并创建掩码
常规的对象检测模型要求您使用边界框来注释图像中的对象。然而,蒙版模型的输入是带有蒙版的 PNG 文件。请参见下面的示例:
Object Mask — Toy
利用这个二进制掩模图像,模型可以提取边界框的坐标以及对象的像素位置。
我用来创建蒙版的工具是像素注释工具。这个工具的输出是 API 想要的格式的 PNG 文件。您可以在注释工具中打开图像,并使用画笔给玩具“上色”。将外部着色并标记为感兴趣区域之外也很重要。我花了大约 20 秒的时间来着色和保存每一张还不错的蒙版图片。如果你想让蒙版非常精确,那么在边缘使用精细的笔刷。通过我的实验,我观察到训练一个掩模 RCNN 模型比训练一个更快的 RCNN 模型需要更少的图像来达到相同的精度。
2。生成 TF 记录
Tensorflow 对象检测模型的输入是一个 TFRecord 文件,您可以将其视为图像、边界框、遮罩等的压缩表示,以便在训练模型时将所有信息放在一个地方。创建这个文件最简单的方法是使用一个类似的脚本,该脚本可用于 pet 数据集的 TFRecord,并针对我们的情况对其进行一点修改。我已经分享了我在 Github repo 上使用的脚本。
您还需要创建一个 label.pbtxt 文件,用于将标签名称转换为数字 id。对我来说,这很简单
item {
id: 1
name: ‘toy’
}
3。选择模型超参数
现在你可以选择你想要使用的遮罩模型。Tensorflow API 提供了 4 个模型选项。我选择了掩模 RCNN 盗梦 V2,这意味着盗梦 V2 被用作特征提取器。该模型在推理时间上是最快的,尽管它可能不具有最高的准确性。模型参数存储在配置文件中。我为相同类型的 coco 模型使用了配置文件,并更新了类的数量和路径,使大多数模型参数保持不变。
4。训练模型
锁定输入文件和参数后,您可以开始培训。我能够在几个小时内在 CPU 上训练这个模型。您可以同时在两个独立的终端上启动培训作业和评估作业。启动 tensorboard 监控性能。当我看到损失趋于平稳时,我停止了训练。
Tensorboard 中最酷的事情是,随着训练的进行,它允许你在测试集的样本图像上可视化预测。下面的 gif 显示了随着训练的进行,模型变得确定其遮罩和边界框预测。
5。在您的定制视频上测试模型
为了测试模型,我们首先选择一个模型检查点(通常是最新的)并将其导出到一个冻结的推理图中。这个脚本也在我的 github 上。我在我的 Iphone 上录制的新视频中测试了这个模型。正如在我的上一篇文章中,我使用 Python moviepy 库将视频解析成帧,然后在每一帧上运行 object detector,并将结果整理回视频中。
后续步骤
未来的额外探索
- 我想将这个模型扩展到同一张图片中的多个类别的物体。TFRecord creator 脚本需要一些修改,这样它才能正确地为每个对象分配正确的标签和掩码
- 正如我提到的,我在这个项目中使用了最轻量级的模型。我很想看看该套件中速度较慢的其他型号在检测准确性方面的表现
给我一个❤️,如果你喜欢这个职位:)希望你拉代码,并尝试自己。
我有自己的深度学习咨询公司,喜欢研究有趣的问题。我已经帮助许多初创公司部署了基于人工智能的创新解决方案。请到 http://deeplearninganalytics.org/来看看我们吧。
你也可以在 https://medium.com/@priya.dwivedi 的看到我的其他作品
如果你有一个我们可以合作的项目,请通过我的网站或 info@deeplearninganalytics.org 联系我
参考文献:
- 蒙版 RCNN 纸
- 谷歌 Tensorflow 物体检测 Github
- COCO 数据集
- 了解黑白实例切分和语义切分的区别
- 非常好的解释屏蔽 RCNN
为交互式群组分析构建仪表板
原文:https://towardsdatascience.com/building-a-dashboard-for-interactive-cohort-analysis-6a9d904bcbda?source=collection_archive---------2-----------------------
我们如何留住不同的用户群?
Source: Pixabay
介绍
群组是指具有共同定义特征的一组受试者。我们可以观察一个群体在不同时间的表现,并与其他群体进行比较。群组用于医学、心理学、计量经济学、生态学和许多其他领域,以在时间上的间隔进行交叉分析(比较受试者之间的差异)。(来源)
在这篇文章中,我们将重点观察用户在使用 Jupyter 笔记本的产品中的行为。
产品业务中保留的重要性从延续到之前的,在那里我们模拟了产品使用数据,可以总结为三个数字:
- 95% =重新吸引用户与获得新用户的成本差异 ( 来源)
- 5% =可将收入提高至 95%的留存额增加量 ( 来源)
- 77% =前三天每日活跃用户流失的平均百分比 ( 来源)
Trying to grow a product without being able to retain users
检查留存率的关键问题是如何快速、方便地调查不同用户群在产品上平均花费了多少时间。为了做到这一点,可视化需要是交互式的,我们可以通过构建一个仪表板来实现。
我们从上一篇文章中模拟的数据集开始(略有改动),该数据集由 10.000 个用户组成,具有三个分类变量:国家(值为 NL、FR 和 AU)、平台(值为 iOS 和 Android)和 user_registered(值为 True 和 False)。小的调整和解释包含在笔记本中。
这篇文章中的所有代码都可以在 GitHub 上的笔记本中找到。
代码
我们从导入所有必需的依赖项开始:
接下来,我们打开包含所有产品使用数据的 CSV:
Preview of all_user_data_df
我们列出了所有三个变量的值,稍后我们将根据这些值对用户进行细分:
细分用户
下一步是细分用户。我们选择想要分割的特性的值:
这方面的一个例子是对 iOS 平台上未注册的荷兰用户进行细分:
Segmentation example
构建群组
第一步
之后,我们在分割的数据帧上建立群组。第一步是创建一个函数,为每个用户定义一个群组(当用户开始使用产品时):
然后,我们对分段数据帧使用函数:
第二步:
我们将所有事件和用户分组:
我们将该函数应用于现有数据框:
第三步:
我们基于 usage_period 为每个群组定义群组周期:
Cohort_period 0 对应的是使用产品第一个月的用户数和事件数。群组周期 1
对应于使用产品的第二个月的相同数据,以此类推。
第四步:
我们重新索引数据帧,并设置群组组和群组周期作为索引。我们还计算了每个群组第一个月的用户数量。这两者对于
在下一步计算保留都是必要的:
我们将其应用于群组数据帧:
Number of users in each cohort
Sum of all events with unique users in each cohort period for the cohort group 2016–02
第五步:
然后我们计算每个群体的保持率。我们在 cohort_group(索引为 0 的第一列)上拆分,将索引中的唯一值透视到各个列中。然后,我们将每个群组中开始使用该产品的用户数量除以每个相应月份中继续使用该产品的用户数量(1 =第二个月,2 =第三个月,…)。
值~ 0.2658 对应于 2016–02 年群组中在第二个月使用该产品的用户数除以在第一个月使用该产品的用户数。它回答了这样一个问题:在 2016 年至 2002 年期间,有多少用户在使用产品的第二个月继续使用该产品?(26.6%)
值~ 0.2658 对应于 2016–02 年群组中在第二个月使用该产品的用户数除以在第一个月使用该产品的用户数。它回答了这样一个问题:在 2016 年至 2002 年期间,有多少用户在使用产品的第二个月继续使用该产品?(26.6%)
Cohort reindex and group size
我们将上述 5 个群组步骤中的所有函数合并为一个函数,稍后用于交互式可视化。
它的输入是细分数据,输出是每个群组的用户留存率:
静态可视化
然后,我们使用所有群组函数构建的 user_retention 数据框架用于可视化不同的用户群组如何随着时间的推移保留在产品中。
保留曲线
首先,我们可视化保留曲线。每条线对应不同的组群。每条曲线上方的空间越小,保留的用户百分比就越高。或者相反,曲线越快下降到低值,我们在吸引用户继续使用产品方面就越不成功。
我们使用蓝色色图,用更深的蓝色来显示后面的群组。我们看不出不同人群的记忆有任何明显差异。
Visualization — retention curves
热图
接下来,我们用热图来直观显示保留情况。这一次我们使用了二进制颜色图,其中较深的颜色对应于特定群组在特定群组期间保留的较高百分比的用户
。
我们可以再次看到,保持率不会随着时间的推移而发生很大变化。25%的用户在使用后的第二个月内缓慢但持续地流失(这也可以在上面的 user_retention 数据框中看到)。
Visualization — heatmap
交互式可视化
最后一步包括组合所有已构建的功能,并以这样一种方式进行组合,即我们可以根据指定的变量值同时对用户进行细分,构建群组,并通过曲线和热图直观显示保留情况。
通过使用 interact 函数,我们可以选择要分段的变量值。这提供了一个交互式的重新计算和可视化,因此我们可以比较我们的用户的不同部分的保留。
我们可以在下面的例子中观察到,与 Android 用户相比,iOS 用户的保留率更低,这是通过上述调整(包含在笔记本中)模拟的。
Dashboard for interactive cohort analysis
已用资源
部分队列分析主要基于格雷戈·瑞达的帖子。如果您想更深入地了解数据建模部分,推荐阅读本书。
用 Dash (plotly)、AWS 和 Heroku 构建仪表板
原文:https://towardsdatascience.com/building-a-dashboard-with-dash-plotly-aws-and-heroku-jean-michel-d-d102e26ac8c1?source=collection_archive---------9-----------------------
你可以在这个 Github 库 中找到这个仪表盘的模板。而你在我的 网站 上还有一些其他的代码样本。
你好,在这篇文章中,我将解释我创建一个显示一些个人信息的仪表板的过程。为了实现这个项目,我决定使用 Dash 一个由 Plotly 一家加拿大公司开发的 Python 框架,该公司开发了 Plotly 库来实现交互式数据可视化。
在这篇文章中,我将解释:
- 所涉及的数据
- 这个项目的后端(以及一些自己制作的技巧)
- 仪表板、他的部署和组件
tha 数据简介
在我们的日常生活中,我们会产生大量的数据,作为一名数据科学家,我喜欢摆弄数据。就我而言,我有一些智能设备,如智能体重秤或智能手环,我每天都在使用,我有一些应用程序来监控我生活的某些方面,如 Strava,在这种情况下,我对以下数据源感兴趣:
- 我来自诺基亚设备的智能秤数据
- 我在 Strava 的跑步训练
- 我的交叉训练
对于前两个数据源,我有一个应用程序来跟踪不同指标的演变
这很好,但是一个服务/设备=一个应用程序,对发生的事情进行快速监控不是很有效。但是,谁说应用程序说潜在的开发者应用编程接口,在这种情况下,有一个(诺基亚和斯特拉发)。
最后一个数据源更像是一个“老派”数据源,因为它只是一个谷歌电子表格,我每周都会用我在 crossfit 会议期间完成的不同练习来填充它。我发现这是一个很好的和有效的方法来跟踪我在盒子上做了什么,并看到进展。有一个 API 为我提供了访问这个数据源的可能性。
所以所有的数据都可以用于我的项目。
现在让我们看看后端的结构,它将为仪表板公开数据。
后端描述
对于这个项目,后端托管在 Amazon Web Services 上。有一个项目后端的图解。
这个后端围绕两个元素构建,一个是用于从不同 API 收集数据的数据管道,另一个是提供预测体重和脂肪比率可能性的 API。
构建数据管道
对于数据的收集,管道托管在 Amazon Web Services 中,我有一个 EC2 实例(来自 AWS 自由层的实例)定期(每 3 小时)收集不同来源推送的新数据。收集的数据被清理并发送到 3 个不同的 DynamoDB 表中。
管道非常简单,对于 DynamoDB 表的配置,我设置了 2 个单位的非常小的写入容量,但是对于读取,我决定使用自动缩放功能,根据流量设置 10 到 50 个单位之间的动态读取容量。
部署预测模型
免责声明:这不是一个超级高效的模型,但至少它存在
这个模型非常简单,但不是非常有效,我目前有一个体重模型和另一个脂肪比例模型。
这是一个简单的 KNN 模型,在每种情况下,它接受以下输入:
- 距离在一周内跑完
- 时间在一周中流逝
- 交叉健身的次数
- 交叉体能训练中携带的平均重量(带重量)
该模型将预测体重和脂肪比率的每周变化。
该模型将每周更新,并发送一个 S3 桶。为了直接从仪表板访问模型,我创建了一个带有 Flask 的 API,我将它部署在一个带有 Zappa 包的 Lambda 中,我在 messenger chatbot 上的文章中使用了这个包。
没什么特别的,但一切都正常。现在让我们关注项目的数据收集部分,以填充 Dynamodb 表。
数据收集
正如我前面说过,有三个 API 连接到我们的后端:
- 诺基亚 API
- 斯特拉发 API
- Google drive API
让我们看看每个数据源。
诺基亚 API
有了这个 API,我从 2017 年 2 月开始收集数据,从 2014 年 7 月开始使用智能手环,从 2014 年 11 月开始使用智能体重秤,我喜欢这些设备,它们的设计很好,应用也很好。我希望所有关于诺基亚的谣言都是错误的。
我创建了一个调用带有 GET 请求的 API 的脚本(就长度而言非常长),老实说,我认为诺基亚的 API 是我迄今为止使用的最具技术性的 API(相比之下,Netatmo 是我最容易使用的 API),但至少在过去的一年里它一直在工作。
为了这个项目,我试图做一些调整,我打破了一切,所以我决定使用这个 GitHub 库来管理与 API 的连接,它工作得很好!!
斯特拉发 API
我从 2016 年 9 月开始使用 Strava,之前我是一名 Runkeeper 和 Runstatic guy,但我在 2017 年到达英国时决定转换。
老实说,Strava 的 API 非常容易使用,只需创建一个应用程序获取您的访问令牌,并在 API 文档中发出以下 get 请求
交叉拟合数据(Google drive API)
我目前从 2017 年 8 月开始练习 crossfit,正如我之前所说,我在谷歌工作表的电子表格中监控我的训练。
这是一种老式的方法,但我发现它比应用程序收集数据更有效。
我正在使用 Google Drive API 和 Twillio 制作的这个教程来设置一个将收集数据的 python 脚本。另一种方法是使用 Sheetsu ,因为我有一些谷歌信用,我决定不使用这项服务(我过去曾使用 Alexa 技能,它很棒)。
数据存储(DynamoDB 和 Boto3)
收集完所有这些数据后,用 boto3 连接 DynamoDB 表就非常容易了。
现在我们有了后端的数据,让我们对它进行一些分析。
分析学
就像我之前说过的,对于这个数据源,我将把重点放在秤的数据上,参数是体重和脂肪比率。
下图显示了我过去一年的体重历史数据。
正如您所看到的,在过去一年中,权重的演变中有很多噪声,因此我将对信号应用滚动平均函数,使其看起来更好,并保持行为趋势。
最有趣的窗口似乎是 7 天窗口,因为它保留了局部变化,但不受会破坏数据分析的滞后效应的影响。
脂肪率变化的结论是相同的。
要分析的另一个元素可以是指标的每周变化,以说明好的和坏的一周,并可能检测有趣的时期(例如,肌肉或脂肪的增加)
脂肪增加和体重增加之间存在线性关系,但我不想展示它,因为我知道在某些阶段,你可以增加体重,但减少脂肪(增加肌肉),所以这种关系并不存在。
让我们看看斯特拉发的数据。
运行数据
我基本上每周跑步一次,平均不到一小时跑 10 公里左右。
这个数据源的有趣指标是:
- 距离
- 平均速度
- 立面图
- 时间流逝了
一些非常简单的条形图可以显示这些参数的演变。
有趣的一点是把距离、平均速度和海拔高度交叉在一起,看最后一个参数对速度的影响。
我们可以看到海拔对我平均速度的影响。但是说实话,这个数据源并不令人兴奋(我也在收集跑步会话的细节,比如会话期间的速度等等,但是我目前对这些数据什么也没做)。
我们来看看 crossfit 的数据。
交叉拟合数据
我从 2017 年 8 月开始练习 crossfit,每周 3 次,我绝对不是专业人士。下图显示了一次训练中的总重量与重复次数的函数关系。
这个数字很好地说明了 crossfit 中可能发生的各种情况,有些情况下你可以负重很多,但不需要太多的重复,相反,有些情况下你可以重复很多,但不需要太多的重量。
另一个有趣的部分是观察一次锻炼期间体重的变化(是的,我有一点进步)。
因此,数据的质量取决于我在电子表格中正确书写的动机,但信息量是相当有趣的。
现在是时候创建显示所有这些信息的仪表板了。
仪表板的设计
对于这个仪表板,我对应用程序的要求是:
- 易于部署且成本低廉
- 访问仪表板的身份验证流程
我看到人们说“哦,你应该用 R Shiny 来创建你的应用程序,因为..”我会说。
老实说,我不是 R 的忠实粉丝,我知道如何使用它,但当我想做更多与数据分析无关的高级计算时,我发现它非常有限。
而且我想写一篇关于 dash 的文章,那我们就 Dash 吧。
对我来说,仪表板上有以下部分很重要:
- 数据概述(如最后一个值和一些快速统计数据)
- 每个数据源的一个部分
- 我可以使用一点 ML 的预测部分
我邀请你使用这个 Github 库 中的代码和环境来启动。
仪表板演示
在这一节中,我将描述并展示他的最新版本的仪表板(在最后的 css“政变”之前)。
对于应用程序的风格,我使用了以下资源:
概述部分
在这一节中,我们的想法是向用户提供一个非常清晰和简单的不同指标的概述,并快速了解它们的演变。
第一部分显示了一些关于体重和脂肪比例的信息。
每个参数都有:
- 最后一次测量(以及他发生的时间)
- 不同时期(自上周、上月和去年以来)的指标演变
我发现这部分信息非常丰富,很容易理解,你可以看到趋势(对我父母来说太完美了)
这一节后面是另一节,包含最后一个运行的会话,更简单。
有一些关于距离、平均速度和海拔的信息,并与之前的比赛进行了比较。
对于本节的其余部分,它是一个包含上次 crossfit 会话练习的表格,因此没有什么真正令人兴奋的,不需要缩放。
重量和跑步部分
对于下面的两个部分,基本上是一些非常基本的数字,我从这篇文章中提取了可视化。
用户可以选择想要用 inputs 元素可视化的时间段和参数。他可以使用下拉面板和日期范围选择器选择参数和数据范围
布局超级简单,但很实用。
交叉部分
在这一部分中,我选择交叉前面部分的指标索引和输入选项。
您可以选择练习并获得一些快速统计数据:
- 携带的最大重量
- 重复执行的次数
- 每次重复的平均重量
- 重复次数与重量的关系图
这很简单,但非常有用,当我想快速找到我的 1 rep 最大重量。
预测部分
在这个部分中,基本上是控制面板调用包含模型的 API。
用户可以选择预测周期和每周训练设置,并了解预测周期结束时体重和脂肪比率的变化。
也许不准确,但至少它在这里,它肯定会随着更多的数据变得更好(该模型是在 30 点上训练的)。
现场演示
现在是时候更新最终的 css 了,瞧
没有什么疯狂的,但它的功能(可能有点慢)和易于使用。
结论和下一步措施
因此,原型运行良好,并部署在 Heroku 上(如果你想访问,可以联系我)。我花了 2 周的时间来做这件事(周末和午休),所以我对此很满意。
你可以在Github repo中找到所有代码(至少是 app 的骨架)。
接下来的步骤是:
- 尝试用 Flask 和 D3.js 做一个替代
- 添加更多的数据,也许是食物指数
- 实现运行会话细节的可视化(传单可能是一个好的开始)
- 找到一些其他要显示的指标
- 从用户那里得到一些反馈
原载于 2018 年 2 月 26 日【the-odd-dataguy.com。
与 CDAP 一起在 GCP 建立一个数据湖
原文:https://towardsdatascience.com/building-a-data-lake-on-gcp-with-cdap-6271c264f22e?source=collection_archive---------5-----------------------
首先看看谷歌收购的木桶的开源平台
Visit Cask Product page to know more on CDAP
众所周知,传统的数据分析平台(如数据仓库)难以扩展且成本高昂,难以满足当前的数据存储和计算需求。如果在内部部署,为处理大数据而专门构建的平台通常需要大量的前期和持续投资。或者,云计算是以经济的方式扩展和容纳如此大量数据的完美工具。虽然经济性是正确的,但企业迁移其内部数据仓库或在云中构建新的仓库或数据湖的过程中会面临许多挑战。这些问题包括构建网络、保护关键数据、拥有使用所选云技术的合适技能,以及找出合适的工具和技术来创建加载、转换和混合数据的操作工作流。
技术什么都不是。重要的是你对人们有信心,他们基本上是善良和聪明的,如果你给他们正确的工具,他们会和他们一起做美好的事情。——乔布斯
企业比以往任何时候都更加依赖数据。拥有合适的工具集授权给合适的人可以使数据随时可用,从而更好、更快地做出决策。在将数据仓库迁移到云中或在云中构建数据仓库的过程中,最重要的步骤之一是选择合适的工具集,使集成变得简单,并使他们能够专注于解决业务挑战,而不是专注于基础设施和技术。
在这篇博文中,我们将讨论【CDAP】(木桶数据应用平台) 如何与 谷歌云平台(GCP) 技术无缝集成,构建云中的数据湖。我们将了解 CDAP 如何帮助数据管理专业人士通过使用 CDAP 集成更多数据来实现他们在 GCP 迁移或构建数据湖的业务目标,从而最大化他们在 GCP 的投资价值。
CDAP 管道(工作流)是一种移动、转换、混合和丰富数据的数据编排功能。CDAP 管道管理所有管道活动的调度、协调和监控,并处理故障情况。CDAP 管道提供了数百个预建连接器的集合、基于开源流媒体引擎的简化流处理,以及与 BigTable、BigQuery、谷歌云存储、谷歌 PubSub 和其他 GCP 技术的新的开箱即用连接。因此,它们使用户能够在谷歌云环境中的任何地方集成几乎任何数据。
治理是任何数据湖或数据仓库的重要需求,无论是部署在内部还是云中。自动捕获和索引 CDAP 境内任何管道的技术、业务和运营元数据的能力,使发现数据集、执行影响分析、跟踪数据集的谱系和创建审计跟踪变得非常容易。
因此,让我们来看看 CDAP 最近添加的一些功能,以与谷歌云平台技术集成。
数据准备和与 GCS 的管道集成
有了木桶,优化宏观用户流程的无缝工作流程在处理复杂技术的同时提供了完整而有趣的体验。根据客户的第一手观察,这样做可以提高效率,降低运营成本,减少用户的挫折感,并最终实现数据访问的民主化,从而更快地从数据中获得更大的价值。本着实现更高效率的精神,让我们首先将 CDAP 的数据准备功能与谷歌云存储集成起来。
谷歌云存储(GCS) 是统一对象存储,支持内容分发、备份和归档、灾难恢复、大数据分析等领域的各种非结构化数据。您可以使用 CDAP 管道将数据移入和移出 GCS,以用于分析、应用和各种用例。借助 CDAP,您可以快速可靠地简化工作流程和操作,或者使用相同的流程将您的客户或供应商数据从亚马逊 S3、Azure ADLS 或 WASB 转移到谷歌云存储中。
CDAP 管道提供了用于与 GCS 本地集成的插件,无论您使用的是结构化数据还是非结构化数据。它们还提供了与 CDAP 数据准备功能的无缝集成,使您可以轻松创建与项目的 GCS 连接、浏览 GCS 并立即处理您的数据,而无需使用代码或移动到另一个控制台。
观看下面的截屏,了解 CDAP 数据准备和 CDAP 管道和气体控制系统的集成流程。
This flow from the start (Configuring GCS) to finish (Pipeline Deployed) takes around ~ 2 minutes to build, and not a single line of code was written
除了与 CDAP 数据准备集成之外,以下 CDAP 插件也可用于 GCS:
- GCS 文本文件源— 一个源插件,允许用户读取存储在 GCS 上的纯文本文件。文件可以是 CSV、制表符分隔、行分隔 JSON、固定长度等。
- GCS 二进制文件源— 一个源插件,允许用户以 blobs 形式读取存储在 GCS 上的文件。可以读取 XML、AVRO、Protobuf、图像和音频文件等文件。
CDAP 数据准备自动确定文件类型,并根据文件扩展名和文件内容类型使用正确的源。下面是一个简单的管道和配置相关的 GCS 文本文件源,供您参考。
Google BigQuery 集成
Google 云平台的另一个重要组成部分是 Google BigQuery 。Google BigQuery 是一个无服务器、完全托管的 Pb 级数据仓库,它使企业能够以高度并发的方式执行所有数据仓库操作。通过 CDAP 的原生 Google BigQuery connector,Spark、Spark Streaming 和 MapReduce 作业可以用来将大量数据快速加载到 BigQuery 中。CDAP 对嵌套模式和复杂模式的支持允许在 BigQuery 中高效地分析不同的数据类型。在配置插件时,数据集表的模式无缝地对用户可用。数据集内的新表无需额外工作即可创建。
上面的管道读取纽约 Trips 数据集(在 Google BigQuery 上作为公共数据集提供),对集群执行一些转换和计算,并将结果写回 Google BigQuery。这个例子可能与真实用例不太相关,因为您可以使用 BigQuery SQL 来完成这里所做的事情,但是这个管道仅用于演示目的,以显示 Google BigQuery 的源和接收器可以读取和写入。
这些 BigQuery 插件简化了从 BigQuery 导入元数据,并根据管道模式自动创建表和正确的模式。
Google PubSub 集成
Google PubSub 是一个完全托管的实时消息服务,让你将来自传感器、日志和点击流的数据摄取到你的数据湖中。CDAP 对 Spark Streaming、Kafka、MQTT 的支持,以及对 Google PubSub 的原生连接,使得将历史数据与实时数据相结合变得容易,从而获得对您的客户的完整的 360 度视图。它还可以轻松地在内部和云之间移动数据。
下面是一个简单的实时 CDAP 数据管道,用于将数据从内部 Kafka 实时推送到 Google 云平台 PubSub。发布的数据可立即用于进一步的转换和处理。
用例
EDW 卸载| Oracle CDC 到 Google BigTable
在过去的几十年中,企业已经为数据仓库安装了设备和其他预配置的硬件。这些解决方案通常需要在专有技术上进行大量投资,其目标是让管理和分析数据变得更容易。然而,最近开源技术的进步提供了存储和处理大量数据的更便宜的方法,打破了企业的围墙,使企业质疑昂贵硬件的成本。这一次,企业不再用新硬件替换旧系统,而是寻求在对他们有意义的时候迁移到云来构建他们的数据湖。但是,需要正确的工具来支持云中数据仓库的许多可能的用例。高效、可靠地将数据从本地数据仓库卸载到云需要四件事情:
- 易于加载数据和保持数据更新
- 支持对小型和大型数据集进行快速查询的查询工具
- 支持高并发性而不降低性能
- 自定义报告和仪表板工具。
Google BigTable 结合 Google BigQuery 提供了支持批量加载的能力,以及查询大规模加载的数据的能力。对于报表和仪表板, Google Data Studio 或任何其他流行的 BI 工具可以与 Google Query 结合使用,以满足许多报表需求。
现在,主要问题是企业如何有效地将数据从其内部仓库卸载到 BigTable 中,并保持 BigTable 中的数据同步。为了支持 EDW 卸载到 BigTable 用例,CDAP 提供了在关系数据库和数据管道上执行变更数据捕获 (CDC)的能力,以及用于消费变更数据事件和更新相应的 Google BigTable 实例以保持数据同步的插件。变更数据捕获解决方案可以使用三种方法之一来捕获源数据库中的变更:
- 通过 Oracle Golden Gate 进入源表的交易日志
- 通过 Oracle 日志挖掘器或
- 使用变更跟踪来跟踪 SQL Server 的变更
第一个解决方案读取数据库事务日志,并将所有 DDL 和 DML 操作发布到 Kafka 或 Google PubSub 中。实时 CDAP 数据管道使用 Kafka 或 Google PubSub 中的这些变更集,使用 CDC BigTable Sink 插件对 BigTable 进行规范化并执行相应的插入、更新和删除操作。
下面是一个管道,它从流源读取变更集,并将它们写入 BigTable,重新创建所有的表更新,并使它们保持同步。
要从 BigQuery 查询,请将表作为外部表添加。点击 了解更多操作方法信息 。
在云之间移动|从亚马逊到谷歌,反之亦然
企业可能出于多种原因决定从一个公共云平台迁移到另一个公共云平台,或者选择多个云提供商。一个原因可能是不同的公共云提供商提供了比当前提供商更好的价格,或者在提供的服务方面更匹配。另一个常见的情况是,一家企业最近经历了一次合并,收购方已经优先选择了他们的公共云提供商。不管原因是什么,简化迁移或支持多个云的一种方法是从与云环境集成的多云数据管理平台开始。通过使用多云数据管理解决方案,如 CDAP,您可以无缝地创建一个抽象,隐藏底层云的差异,并允许工作流和数据的简单迁移。在混合云环境中,从一开始就采用这样的平台是非常有价值的,在混合云环境中,您可能要管理本地(托管)私有云和公共云。
借助 CDAP 管道,构建能够高效、可靠地将数据从一个公共云存储迁移到另一个公共云存储的工作流非常简单。下面是一个例子,展示了如何将亚马逊 S3 的数据迁移到 GCS 中,并在迁移过程中转换和存储到 Google BigQuery 中。
管道执行后,管道的执行结果可以在 GCS 和 BigQuery 中获得。
人工智能集成|使用谷歌语音翻译器翻译音频文件
转录是将你录制的音频转换成高度准确、可搜索和可读的文本的最佳方式;能够索引和搜索音频内容非常有用,因为这有助于用户找到相关内容。它可以用来提高有机流量,改善可访问性,还可以通过转录音频文件来增强您的人工智能,从而为您的客户提供更好的服务。
假设您有一家提供客户支持服务的公司,您正在记录随机的客户对话以提高服务质量,从而更好地了解代表如何处理电话。改善服务的第一步是将录制的音频文件转录成数字化的可读文本。此外,文本可以通过各种 AI / ML 工作流来确定呼叫的情绪、客户情绪、解决延迟等。
Google Cloud Speech API利用强大的神经网络模型将音频转换为文本。它识别超过 110 种语言和变体,以支持您的全球用户群。
简化录制的大量音频文件的转录,谷歌云平台技术和 CDAP 一起为用户提供了一个集成的,可扩展的和无代码的方式来转录音频文件。这种集成使用户可以在几分钟到几小时内,而不是几周或几个月内,为任何生产部署构建可以轻松安排和监控的管道。
下面是一个简单的 CDAP 管道,它获取存储在谷歌云存储上的原始音频文件,通过谷歌语音翻译插件传递,并将转录的文本写入谷歌云存储上的另一个位置。
谷歌语音翻译 CDAP 插件已经准备好根据被录制文件的类型进行少量的设置。在上面的例子中,应用于原始音频文件的翻译生成一个 JSON 输出,它描述了被转录的文件,并计算了转录的置信度。
{
"path": "/audio/raw/audio.raw",
"speeches": [
{
"confidence": 0.9876289963722229,
"transcript": "how old is the Brooklyn Bridge"
}
]
}
资源
案例研究:数据湖、 XML 转换、数据发现、信息安全智能分析
导读:卡夫卡消费,推特数据,数据处理同流程 & 水槽
代码示例:Twitter sensing, MovieRecommender , Netlens , Wise
教程:诈骗 ML 分类,迁移 S3 到 ADLS , EDW 优化
API : CDAP API 和依赖包
如果您正在使用或评估 GCP,并且正在寻找提高您在 GCP 上的集成的方法,您可能想要 试用 CDAP 并安装来自木桶市场的 GCP 连接器。同样,如果你是开发人员或数据工程师/科学家,你可以下载 CDAP 本地沙盒
原载于blog . cdap . io。
为圣保罗地铁运营构建数据集
原文:https://towardsdatascience.com/building-a-dataset-for-the-s%C3%A3o-paulo-subway-operation-2d8c5a430688?source=collection_archive---------11-----------------------
Photo by Rafael De Nadai on Unsplash
你坐过拥挤的地铁吗?我知道大多数大城市都会出现这种情况,但在圣保罗,情况可能是这样的:
This is what a crowded subway station may look like here in SP
现在,作为一名巴西人和一名保利斯塔诺,我能做些什么呢?(这是葡萄牙语中“住在圣保罗的人”的意思)
Metr 地铁公司的透明网页提供了关于乘客需求的数据,但粒度较低,对每条地铁线工作日和周末的平均条目进行了分组。这还不错,但我们可以做得更好。
The transparency webpage for the Metrô subway company provides data on the passenger demand but with low granularity
我知道 ViaQuatro 公司的网页提供了所有地铁线路的(几乎)实时运营状态,该公司与政府有一个地铁线路运营联合体:
The ViaQuatro company webpage provides operation status for all of the subway lines, as highlighted in red
每天乘坐 SP 地铁的人直观地知道,一个 正常 运行状态不足以推断车站不会拥挤,但是一个 减速 或 瘫痪 状态可能与第一张图中所示的混乱有关。
不幸的是,这些数据没有被存储。至少对我们这些普通公民来说不是这样,所以我们可以对它进行访问、监控、评估、展示等等。我们为什么不使用 Python 来解决这个问题呢?
本文剩余部分显示的步骤是一个教导性的,尽管是项目的完全功能性演示。万一你是开发者或者想直奔最终结果,可以随意探索 Github 资源库 。
所以…
我们的目标是以非侵入性的方式持续存储圣保罗地铁线的运营状态历史,并使任何公民都可以方便地使用。
为了达到这个目标,我们将编写一个能够请求 ViaQuatro 网页,提取操作状态和时间戳并存储它的自治 web scraper。
为此,我们将需要requests
包来下载网页,并需要BeautifulSoup
来轻松处理网页:
>>> import requests
>>> from bs4 import BeautifulSoup
好了,要下载这个页面,我们需要做的就是
>>> vq_home_request = requests.get('http://www.viaquatro.com.br')
如果请求成功,我们就有了 HTML 代码
>> vq_home_content = vq_home_request.text
>> vq_home_content'\r\n<!DOCTYPE HTML>\r\n<html lang="pt-BR">\r\n<head>\r\n\t<meta charset="UTF-8">\r\n **<title>ViaQuatro | Seja Bem-vindo</title>**\r\n\t<meta name="description" content="ViaQuatro - Informações sobre rotas, tarifas, estações e muito mais." /> \r\n\t<meta name="keywords" content="" />\r\n <meta http-equiv="X-UA-Compatible" content="IE=edge" >\r\n\t<script src="/Content/js/3rd/modernizr.custom.97134.js"></script>\r\n <!-- Use Zepto for best performance on WebKit based browser -->\r\n\t\t<!-- <script src="js/zepto/zepto.js" type="text/javascript" charset="utf-8"></script> -->\r\n\t<link rel="stylesheet" type="text/css" href="/Content/css/default.css" media="all" /> **<!-- pra ser carregado em todas as páginas -->**\r\n
(...)
We do have the HTML inside our environment!
现在让我们使用 BeautifulSoup 来浏览 DOM 并提取标题页面,以检查我们是否在 BeautifulSoup 对象中组织了 HTML 元素:
>>> soup = BeautifulSoup(vq_home_content, 'html.parser')
>>> soup.title
<title>ViaQuatro | Seja Bem-vindo</title>
现在到了困难的部分——提取真正重要的东西。使用开发工具检查 HTML,我们看到显示地铁线路当前状态的“操作”面板由一个<section class="operacao">
元素组成。里面有我们需要的所有数据。因此,让我们把它拉出来,这样我们就可以对它进行以下查询:
>> operation_column = soup.find(class_= "operacao")
We need to inspect the page code in order to find out what element contains the data we want
让我们也使用 字典理解 : 初始化一个字典来存储行状态
>> lines_metro = ['azul', 'verde', 'vermelha', 'amarela', 'lilás', 'prata']>> lines_cptm = ['rubi', 'diamante', 'esmeralda', 'turquesa', 'coral', 'safira', 'jade']>> all_lines = lines_metro + lines_cptm>> **extracted_status = {line:'' for line in all_lines}**>> extracted_status
{'amarela': '', 'vermelha': '', 'diamante': '', 'turquesa': '', 'coral': '', 'prata': '', 'lilás': '', 'esmeralda': '', 'safira': '', 'rubi': '', 'verde': '', 'azul': '', 'jade': ''}
继续我们的调查,我们看到 Amarela(黄色)地铁线的状态包含在一个带有名为状态的css 类的 span 标签中。
>> status_amarela = operation_column.find(class_="status").text
>> extracted_status['amarela'] = status_amarela
The operation status for the Amarela (yellow) subway line is wrapped around a span tag with acss class called status
对于所有其他线路,数据被分成三个标签<div class="linhas">
,每个标签代表一家参与城市铁路系统的公司。在每一个div中,我们都有一个无序列表标签,其中每一个条目都包含行号、其名称和当前在另一个看起来像<div class="info">
的 div 中的操作状态。
为了提取所有这些内容,我们将遍历<div class="linhas">
div,然后遍历每个<div class="info">
div,以获得我们真正想要的内容:操作状态和行名:
we will iterate over the <div class="linhas">
divs and then iterate over each <div class="info">
div to get what we really want
>> lines_containers = operation_column.find_all(class_ = "linhas")>> for container in lines_containers:
line_info_divs = container.find_all(class_ = "info")
for div in line_info_divs:
line_title = ''
line_status = ''
spans = div.find_all("span")
line_title = spans[0].text.lower()
line_status = spans[1].text.lower()
extracted_status[line_title] = line_status>> extracted_status
{'safira': 'normal', 'prata': 'normal', 'rubi': 'normal', 'azul': 'normal', 'turquesa': 'normal', 'amarela': 'Operaç\xe3o Normal', 'lilás': 'normal', 'esmeralda': 'normal', 'coral': 'normal', 'verde': 'normal', 'diamante': 'normal', 'jade': 'normal', 'vermelha': 'normal'}
现在我们有了字典中所有行的操作状态!另一个重要信息是该数据的时间戳。它显示在“操作”面板中,就在标题的右边。这是页面中唯一的<time>
元素。让我们把它拉出来:
>> time_data = soup.find('time').text
>> time_data
'18/08/2018 23:11'
终于,我们有了所有的数据!我承认我需要一点时间来欣赏这一点。
Web scraping is so cool! Source
此时,我们可以简单地将extracted_status
和time_data
写入本地系统中的一个文件,或者利用互联网的魔力将其存储在任何地方。
但是让我们更进一步,使用 Google Sheets ,因为它非常受欢迎,非开发人员也可以访问,并且提供了一个有良好文档记录的 API。最重要的是, gspread 包为我们包装了所有的请求,并且 oauth2client 使用我们的 API 凭证处理令牌获取过程。
我知道有很多隐藏的东西,但是能够用这么少的代码做这么多的事情是用 Python 这样的语言编程的美妙之处之一。
简单地说,我们需要做的是:
- 获取我们的谷歌证书,以便以后使用它们进行授权(这是手动的,只需要做一次)
- 通过我们的代码使用凭据获得授权
- 通过我们的代码将数据写入公共电子表格
要获得证书,我们可以按照 gspread 文档提供的这个逐步指南进行操作。在这个过程结束时,您得到的是一个类似如下的client_secret.json
文件:
{
"private_key_id": "2cd … ba4",
"private_key": "-----BEGIN PRIVATE KEY-----\nNrDyLw … jINQh/9\n-----END PRIVATE KEY-----\n",
"client_email": "473000000000-yoursisdifferent@developer.gserviceaccount.com",
"client_id": "473 … hd.apps.googleusercontent.com",
"type": "service_account"
}
这很重要:我们需要与我们的 API 用户共享我们将要使用的电子表格。否则,在尝试写入数据时,我们会收到拒绝访问错误。这个用户由 json 文件中的 client_email 字段表示。
This is important: we need to share the spreadsheet we will be using with our API user
回到代码,让我们导入 gspread 和 oauth2client 并从。json 文件到我们的环境中:
>> import gspread
>> from oauth2client.service_account import ServiceAccountCredentials>> scope = ['https://spreadsheets.google.com/feeds',
'https://www.googleapis.com/auth/drive']
>> creds = ServiceAccountCredentials.from_json_keyfile_name(
'client_secret.json',
scope)
现在让我们使用我们的凭据获得授权,并初始化电子表格。要初始化电子表格,我们需要它的 ID,它显示在我们用来在浏览器中访问它的 URL 中:
https://docs.google.com/spreadsheets/d/**1 wiki 6 sucqaauf 9 qojog _ tme OSA _ lm _ kjm 83 qwxf 9 dsg**
>> client = gspread.authorize(creds)>> SPREADSHEET_ID = "1WiKE6SUCqAaUF9qOJOg_tMeOSA_lm_kjm83qwXF9dSg">> data_sheet = client.open_by_key(SPREADSHEET_ID).worksheet("data")
注意,我们不直接使用电子表格对象,而是使用其中的工作表,因此我们需要指定它的名称。
让我们写我们的数据! append_row 方法确实如其名,我们只需要传递一个列表,其中每个元素将被写入该行的不同列。
>> for line in all_lines:
data_sheet.append_row([time_data, line, extracted_status[line]])
We can actually see the data being stored in real time!
为了拥有一个不会让你的电脑一直开着的自主刮刀,我们必须组织这段代码,并让它在云服务上运行。针对异常的一些保护也很重要,但是这些超出了本文的范围。如果你想了解更多的细节,可以随意看看 github 的回购。
我将在以后的文章中分析这些数据。我们看看会有什么结果!
【编辑】保罗做了一个很棒的分析!看这里!
在 TensorFlow 中构建软决策树
原文:https://towardsdatascience.com/building-a-decision-tree-in-tensorflow-742438cb483e?source=collection_archive---------2-----------------------
20X magnification of the somatosensory cortex (by Robert Cudmore — CC BY-SA 2.0)
介绍
深度学习产品在行业内引起了越来越多的兴趣。虽然计算量很大,但在处理自然语言或图像处理等非结构化数据的分类方面,它们已被证明是有效的。
高价值数据科学产品的目标不仅在于其高价值交付,还在于其被业务接受。因此,可解释性仍然是一个重要因素。
Google Brain 最近发布了一篇论文,提议实现软决策树。
在这篇博客中,我从他们的论文中摘录了一些要点,并举例说明了神经网络是如何模仿树形结构的。
目标
- 什么是数据科学中的决策树?
- 神经网络怎么会有树状结构?
- 在 TensorFlow 中实现软决策树
软决策树
树
为了不拘泥于形式,在数据科学中,树由三个主要成分组成:
- 分割条件
- 修剪条件
- 离开
分割条件将数据分割到叶子上。修剪条件决定了分区停止的时间。最后,也是最重要的,树叶包含预测的目标值,该值已被拟合到分区内的数据。
如图 1 所示,每个分割条件都是特性的函数。
Figure 1: Basic Tree. Each data-point travels through the tree until one of the leafs. The path is determined by the split conditions, which are functions of the features. The leafs determine the prediction target.
每个内部节点中的分裂和叶子的目标输出由损失函数的优化来确定。为每个数据点分配一个预测成本。
在哪里
是数据点 x 的目标
是叶的目标类的概率。我们还表示了叶选择器:
这个符号将在下一节中阐明。
神经网络
神经网络由一组对其输入特征的平滑操作组成。所谓平滑,我的意思是每个操作在其变量中是连续可微的。
可微性是一个至关重要的因素,因为最佳变量是使用损失和操作的梯度计算的。起初这似乎是个问题,如果我们想把树设计成树的每个内部节点,基于分割条件分配它的一个孩子的每个数据点。
因此,我们用神经网络构建树的第一步是通过允许数据在每次分裂时以一定的概率向左和向右移动来消除分裂条件。
Figure 2: The hard split-condition of the tree is replaced by split-probability.
因此,每个数据点在树中没有唯一的路径。它们现在属于树的每一片叶子,具有一定的概率,即路径概率。
让我们表示从树根到第 n 个(内部)节点的路径概率,
我们可以回顾一下我们之前写的损失函数,对于每个数据点 x :
这只不过是对分类交叉熵的加权,
以 x 的概率属于一片树叶,这就是路径概率。
正规化
我们现在已经重写了分割条件。叶输出可以保持概率,例如 softmax。
最后一个问题仍然存在,但是,优化将收敛到一个适当的局部最小值?
内部节点权重的更新取决于损失的梯度,因此也取决于路径概率
让我们仔细看看它在一些内部节点 j:
我们立即看到了这里的一个问题。如果某片叶子的概率
对于大量数据来说很小,那么权重在下一步中几乎不被更新。更有甚者,在这次更新之后,这种可能性仍然很小。因此,我们的模型可能会收敛并陷入这些无用的局部极小值。
一棵性能树不仅有最大纯度的叶子,而且在叶子上尽可能均匀地分布数据。如果我们的模型陷入这些局部极小值,我们就只能得到一些高度密集的叶子和许多稀疏的叶子。在这种情况下,我们失去了树的用处,我们最终得到一个逻辑回归模型的小集合。
谷歌大脑的团队提出了一个解决这个问题的方法,
这种正则化有利于均匀的二进制分裂,并且不利于内部节点级别上的早期净化。衰减率 gamma 在树的早期内部节点中增加了重点。
现在一切都设置好了,我们可以讨论 TensorFlow 实现了。
TensorFlow 实现
TensorFlow 是 Google Brain 的一个流行的开源软件库,主要用于深度学习模型的开发。用户在静态计算图上定义操作,并根据需要运行图的不同部分。
让我们用一些基本公式来总结不同的成分:
- 拆分条件
- 修剪条件:让我们坚持一个简单的最大深度
- 叶片输出
- 每个数据点 x 的损失
我们将工作分成三类:
- TreeProperties :包含模型的所有超参数相关属性。
- 节点:定义所有节点级的操作,如内部节点转发如下所示的概率,叶子节点转发 softmax:
- 软决策树:为每个数据点建立所有的内节点、叶子并输出预测目标。
让我们仔细看看!
如第 3.2.2 节所示,超参数 self.decay_penalty 和self . regularization _ penalty分别对应于衰减率γ和权重λ。
下一节课更有趣。
在实例化时,我们定义节点分裂概率的权重和偏差。在构建节点时,我们首先转发节点的输出,要么是 softmax 预测概率,要么是内部节点分裂的概率。
损失也在节点级别上更新。内部节点仅通过前面描述的正则化来增加损失。
最后,所有的节点被组合成一棵树。目标的输出预测和节点的概率分布组合成自输出和自叶分布。
对 MNIST 进行测试
最后,让我们对 MNIST 进行一些测试。使用以下超参数构建树:
max_depth = 7
regularisation_penality=10.
decay_penality=0.9
并且选择训练批量为 32,验证批量为 256。我们得出以下结果:
还不错。当然没有 CNN 那么有竞争力,但是我们看到了很多有前途的想法!
请务必查看的完整实现。
我写了更多精彩的东西!
@ 调整超参数(第一部分):successful halving
@tensor flow 中的自定义优化器
@XGBOOST 回归预测区间
使用 Keras 构建深度学习模型
原文:https://towardsdatascience.com/building-a-deep-learning-model-using-keras-1548ca149d37?source=collection_archive---------1-----------------------
A Neural Network (image credit)
深度学习是机器学习中越来越受欢迎的子集。深度学习模型是使用神经网络构建的。神经网络接受输入,然后使用训练期间调整的权重在隐藏层中处理这些输入。然后模型给出一个预测。调整权重以找到模式,从而做出更好的预测。用户不需要指定要寻找什么样的模式——神经网络会自己学习。
Keras 是一个用 Python 编写的用户友好的神经网络库。在本教程中,我将使用 Keras 检查两个深度学习模型:一个用于回归,一个用于分类。我们将建立一个回归模型来预测员工的每小时工资,我们将建立一个分类模型来预测患者是否患有糖尿病。
注意:我们将使用的数据集相对干净,因此我们不会执行任何数据预处理来为建模准备数据。您将在未来项目中使用的数据集可能不那么清晰-例如,它们可能会有缺失值-因此您可能需要使用数据预处理技术来改变您的数据集以获得更准确的结果。
读入训练数据
对于我们的回归深度学习模型,第一步是读入我们将用作输入的数据。对于这个例子,我们使用的是“小时工资”数据集。首先,我们将使用 Pandas 读入数据。我不会详细介绍熊猫,但如果你想进一步深入数据科学和机器学习,这是一个你应该熟悉的库。
“df”代表数据帧。熊猫以数据帧的形式读入 csv 文件。“head()”函数将显示数据帧的前 5 行,以便您可以检查数据是否已正确读入,并初步了解数据的结构。
Import pandas as pd#read in data using pandas
train_df = pd.read_csv(‘data/hourly_wages_data.csv’)#check data has been read in properly
train_df.head()
将数据集分成输入和目标
接下来,我们需要将数据集分成输入(train_X)和目标(train_y)。我们的输入将是除“每小时工资”之外的每一列,因为“每小时工资”是我们将试图预测的。因此,“每小时工资”将是我们的目标。
我们将使用 pandas 'drop '函数从数据帧中删除' wage_per_hour '列,并将其存储在变量' train_X '中。这将是我们的投入。
*#create a dataframe with all training data except the target column*
train_X = train_df.drop(columns=['wage_per_hour'])
*#check that the target variable has been removed*
train_X.head()
我们将在目标变量(train_y)中插入“每小时工资”列。
*#create a dataframe with only the target column*
train_y = train_df[['wage_per_hour']]
*#view dataframe*
train_y.head()
构建模型
接下来,我们必须建立模型。代码如下:
**from** **keras.models** **import** Sequential
**from** **keras.layers** **import** Dense*#create model*
model = Sequential()
*#get number of columns in training data*
n_cols = train_X.shape[1]
*#add model layers*
model.add(Dense(10, activation='relu', input_shape=(n_cols,)))
model.add(Dense(10, activation='relu'))
model.add(Dense(1))
我们将使用的模型类型是顺序的。顺序是在 Keras 中建立模型的最简单的方法。它允许你一层一层地建立模型。每一层都有与其下一层相对应的权重。
我们使用“add()”函数向模型中添加层。我们将添加两个层和一个输出层。
“密集”是图层类型。密集是适用于大多数情况的标准图层类型。在密集层中,前一层中的所有节点都连接到当前层中的节点。
我们在每个输入层中有 10 个节点。这个数字也可以是数百或数千。增加每层中的节点数量会增加模型容量。稍后,我将进一步详细介绍增加模型容量的效果。
“激活”是该层的激活功能。激活函数允许模型考虑非线性关系。例如,如果你预测病人患糖尿病,从 10 岁到 11 岁和从 60 岁到 61 岁是不同的。
我们将使用的激活函数是 ReLU 或整流线性激活。虽然它是两个线性部分,但已被证明在神经网络中工作良好。
ReLU Activation Function (image credit)
第一层需要一个输入形状。输入形状指定输入中的行数和列数。输入中的列数存储在' n_cols '中。逗号后面没有任何东西表示可以有任意数量的行。
最后一层是输出层。它只有一个节点,是给我们预测的。
编译模型
接下来,我们需要编译我们的模型。编译模型需要两个参数:optimizer 和 loss。
优化器控制学习速率。我们将使用“亚当”作为我们的优化器。在许多情况下,Adam 通常是一个很好的优化器。adam 优化器在整个训练过程中调整学习率。
学习率决定了计算模型最佳权重的速度。较小的学习率可能会导致更准确的权重(直到某一点),但计算权重所需的时间会更长。
对于我们的损失函数,我们将使用‘均方误差’。它是通过计算预测值和实际值之间的平均平方差来计算的。对于回归问题,这是一个流行的损失函数。这个值越接近 0,模型的表现就越好。
Mean Squared Error (image credit)
*#compile model using mse as a measure of model performance*
model.compile(optimizer='adam', loss='mean_squared_error')
训练模型
现在我们将训练我们的模型。为了训练,我们将在我们的模型上使用具有以下五个参数的‘fit()’函数:训练数据(train_X)、目标数据(train_y)、验证分割、历元和回调的数量。
验证分割将随机分割数据用于训练和测试。在训练期间,我们将能够看到验证损失,它给出了我们的模型在验证集上的均方误差。我们将验证分割设置为 0.2,这意味着我们在模型中提供的 20%的训练数据将被留出用于测试模型性能。
历元数是模型在数据中循环的次数。在一定程度上,我们运行的时代越多,模型就会改进得越多。此后,模型将在每个时期停止改进。此外,纪元越多,模型运行的时间就越长。为了对此进行监控,我们将使用“提前停止”。
如果模型停止改进,提前停止将在达到时期数之前停止模型的训练。我们将我们的提前停止监视器设置为 3。这意味着在连续 3 个时期模型没有改善之后,训练将停止。有时,验证损失可以停止改善,然后在下一个时期改善,但是在验证损失没有改善的 3 个时期之后,它通常不会再次改善。
**from** **keras.callbacks** **import** EarlyStopping*#set early stopping monitor so the model stops training when it won't improve anymore*
early_stopping_monitor = EarlyStopping(patience=3)*#train model*
model.fit(train_X, train_y, validation_split=0.2, epochs=30, callbacks=[early_stopping_monitor])
根据新数据做出预测
如果您想使用这个模型对新数据进行预测,我们可以使用' predict()'函数,传入我们的新数据。输出将是“每小时工资”预测。
#example on how to use our newly trained model on how to make predictions on unseen data (we will pretend our new data is saved in a dataframe called 'test_X').test_y_predictions = model.predict(test_X)
恭喜你。你在 Keras 建立了深度学习模型!它还不是非常准确,但可以通过使用大量的训练数据和“模型容量”来改善。
模型容量
随着模型中节点和层数的增加,模型容量也会增加。增加模型容量可以产生更精确的模型,直到某个点,在该点模型将停止改进。通常,您提供的训练数据越多,模型就应该越大。我们只使用了极少量的数据,所以我们的模型非常小。模型越大,需要的计算能力就越大,训练的时间也就越长。
让我们使用与先前模型相同的训练数据创建一个新模型。这次,我们将添加一层,并将每层中的节点增加到 200 个。我们将训练模型,看看增加模型容量是否会提高我们的验证分数。
*#training a new model on the same data to show the effect of increasing model capacity*
*#create model*
model_mc = Sequential()
*#add model layers*
model_mc.add(Dense(200, activation='relu', input_shape=(n_cols,)))
model_mc.add(Dense(200, activation='relu'))
model_mc.add(Dense(200, activation='relu'))
model_mc.add(Dense(1))
*#compile model using mse as a measure of model performance*
model_mc.compile(optimizer='adam', loss='mean_squared_error')*#train model*
model_mc.fit(train_X, train_y, validation_split=0.2, epochs=30, callbacks=[early_stopping_monitor])
我们可以看到,通过增加模型容量,我们已经将验证损失从旧模型中的 32.63 提高到新模型中的 28.06。
分类模型
现在让我们继续构建我们的分类模型。由于许多步骤都是以前模型的重复,我将只讨论新概念。
对于下一个模型,我们将预测患者是否患有糖尿病。
*#read in training data*
train_df_2 = pd.read_csv('documents/data/diabetes_data.csv')
*#view data structure*
train_df_2.head()
*#create a dataframe with all training data except the target column*
train_X_2 = train_df_2.drop(columns=['diabetes'])
*#check that the target variable has been removed*
train_X_2.head()
在分离目标列时,我们需要调用“to _ categorical()”函数,以便对列进行“一键编码”。目前,没有糖尿病的患者在糖尿病列中用 0 表示,而有糖尿病的患者用 1 表示。对于一键编码,整数将被删除,每个类别将输入一个二进制变量。在我们的情况下,我们有两个类别:没有糖尿病和糖尿病。没有糖尿病的患者将由[1 0]表示,患有糖尿病的患者将由[0 1]表示。
**from** **keras.utils** **import** to_categorical*#one-hot encode target column*
train_y_2 = to_categorical(train_df_2.diabetes)
*#vcheck that target column has been converted*
train_y_2[0:5]
*#create model*
model_2 = Sequential()
*#get number of columns in training data*
n_cols_2 = train_X_2.shape[1]
*#add layers to model*
model_2.add(Dense(250, activation='relu', input_shape=(n_cols_2,)))
model_2.add(Dense(250, activation='relu'))
model_2.add(Dense(250, activation='relu'))
model_2.add(Dense(2, activation='softmax'))
我们模型的最后一层有两个节点——每个节点对应一个选项:患者有糖尿病或没有糖尿病。
激活是“softmax”。Softmax 使输出总和达到 1,因此输出可以解释为概率。然后,该模型将根据哪个选项的概率更高来进行预测。
*#compile model using accuracy to measure model performance*
model_2.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
我们将使用‘分类交叉熵’作为损失函数。这是最常见的分类选择。分数越低,表示模型的性能越好。
为了使事情更容易解释,我们将使用“准确性”度量来查看每个时期结束时验证集的准确性分数。
*#train model*
model_2.fit(X_2, target, epochs=30, validation_split=0.2, callbacks=[early_stopping_monitor])
恭喜你。你现在正在 Keras 中构建令人惊叹的深度学习模型!
感谢阅读!本教程的 github 库可以在这里找到。
在 Google Sheets 中构建深度神经网络
原文:https://towardsdatascience.com/building-a-deep-neural-net-in-google-sheets-49cdaf466da0?source=collection_archive---------2-----------------------
我想告诉你深度卷积神经网络并不像听起来那么可怕。我将通过展示我在 Google Sheets 中制作的一个实现来证明这一点。这里有这里有。复制它(使用左上方的文件→制作副本选项),然后你可以摆弄它,看看不同的杠杆如何影响模型的预测。
本文的其余部分将是一个简短的介绍,以了解卷积神经网络(CNN)背后的高级直觉,然后是一些推荐的资源以获得更多信息。
在继续之前,我想对 FastAI 大声疾呼。我最近完成了他们精彩的深度学习课程,所有的灵感和功劳真的都归于他们。出色的讲师杰瑞米·霍华德和他的联合创始人雷切尔·托马斯向全班展示了在 Excel 中制作 CNN 的想法。但据我所知,该电子表格无法在网上获得,也似乎没有完全完成网络。我正在对他们的工作做一个小小的扩展,并把它放在 Google Sheets 上,这样每个人都可以更容易地玩。
我是怎么造出来的?
我在 MNIST 数据集上训练了一个(非常)简单的 CNN,这是一堆手写数字的黑白图像。每个图像是 28x28 像素。每个像素被表示为一个介于 0(无油墨)和 1(最大油墨)之间的数字。这是一个可以使用的经典数据集,因为它足够小,足够快,但又足够真实,可以显示机器学习的复杂性。模型的工作是确定图像的编号。每个图像总是恰好是一个数字 0-9。
Example image from MNIST. 28x28 pixels. Note: I added conditional formatting in Sheets so pixels with more “ink” show up more red.
我使用一个名为 Keras 的流行深度学习库来训练这个模型(参见这里的代码),然后将我的模型中训练好的权重放入工作表中。训练出来的权重只是数字。把它放到表中,这意味着从我的模型中复制并粘贴一堆数字到表中。最后一步是添加公式来复制模型所做的事情,这只是常规的乘法和加法。让我重申一下:复制深度学习模型预测的数学止于乘法和加法 [1]。
模型的每一层都有权重(也称为“参数”)。任何机器学习模型都会自动学习权重。这个模型大约有 1000 个砝码。更复杂的模型可以轻松拥有数亿个。您可以在下面看到该型号的所有 1000 个重量:
何时使用卷积神经网络?
你使用 CNN 在序列数据中寻找模式,在这些数据中你有非常肯定的模式存在,但是你发现很难将这些模式用语言表达出来,或者通过简单的规则提取出来。美国有线电视新闻网认为秩序很重要。
例如,对图片进行分类是 CNN 的主要用例,因为像素在逻辑上是连续的,任何人都很清楚有大量的模式。然而,只要试着把猫和吉娃娃的确切区别用语言表达出来,你就会明白为什么 CNN 是有用的。
另一方面,如果你有两支球队之间的最新棒球统计数据,并且你想预测获胜者,那么 CNN 将是一个奇怪的选择。你所拥有的数据(例如赢的次数,输的次数,或者球队的平均击球率)本质上并不是连续的。顺序在那里并不重要,我们已经提取了我们认为有用的模式。所以 CNN 的不会有帮助。
CNN 背后的直觉
为了理解这些野兽,让我们把深度卷积神经网络分解成它的组成部分“深度”、“卷积”和“神经网络”。
回旋
想象一下你是盲人。但是你的工作是找出这个手写图像是什么数字。你可以和看到图像的人说话,但是他们不知道数字是什么。所以你只能问他们简单的问题。你能做什么?
你可以采取的一种方法是问这样的问题,“它在顶部是不是大部分都是直的?”,“对角线从右到左?”等。有了足够多这样的问题,你实际上可以很好地猜测它是 7,或者 2,或者其他什么。
直觉上,这就是卷积的作用。计算机是盲目的,所以它做它能做的,并且问许多小的模式问题。
Box 1 is multiplied by box 2. Sum the result, and you get box 3. That’s a convolution.
要问这些问题,图像中的每个像素都要通过一个函数(也称为“卷积”)来产生相应的像素,从而回答这些小模式问题中的一个。卷积使用过滤器来寻找模式。例如,请注意上面的滤镜(截图中的 2 号)如何在右侧变得更红,而在左侧变得更少。该过滤器将主要寻找左边缘。
为什么它会找到左边界可能不太明显,但是摆弄一下电子表格,你会亲眼看到数学是如何计算出来的。滤镜发现看起来像自己的东西。CNN 通常会使用数百个过滤器,所以你会得到每个像素的许多小“分数”,有点像左边缘分数、上边缘分数、对角线、角等。
深的
好吧,问边很酷,但是更复杂的形状呢?这就是“深层”多层事物出现的地方。因为现在我们已经有了图像的“左边缘”、“上边缘”和其他简单的“过滤器”,我们可以添加另一个层,并在所有先前的过滤器上运行卷积,并组合它们!因此,结合 50/50 的左边缘和上边缘可以给你一个圆角。很酷吧。
The second convolution takes corresponding pixels from the previous convolution layer and multiplies each by it’s own filter. Just like before, we sum the result, and that produces a new corresponding pixel for the second convolution layer.
严肃的 CNN 将会有许多层,这允许模型建立越来越抽象和复杂的形状。甚至在仅仅 4 或 5 层之后,你的模型就可以开始发现脸、动物和各种有意义的形状。
神经网络
现在,您可能会问自己,“这一切都很好,但要想出所有正确的过滤器听起来真的很乏味。”“最后呢?我如何将这些过滤器中的所有答案组合成有用的东西?”。
首先,有必要认识到,在高层次上,我们的 CNN 实际上有两个“部分”。第一部分,卷积,为我们在图像数据中找到有用的特征。第二部分,电子表格末尾的“密集”层(如此命名是因为每个神经元都有如此多的权重),为我们进行分类。一旦你有了这些特征,密集层实际上与运行一系列线性回归并将它们组合成每个可能数字的分数没有什么不同。最高分是模特的猜测。
Matrix 1 is the output from our convolutions. Then every pixel from matrix 1 is multiplied by a corresponding number in matrix 2 . The summation of that produces number 3. You repeat that process again for the boxes in green. You end up with 8 outputs, or “neurons” in deep learning jargon.
计算出所有正确的权重用于过滤器和最后的密集层将是非常烦人的。幸运的是,自动计算这些权重是神经网络的全部内容,所以我们不需要担心这个。但如果你很好奇,你应该谷歌一下“反向传播”。
摘要
每个 CNN 大致有两个部分。卷积总是在开始时寻找图像中有用的特征,最后的层通常称为“密集”层,根据这些特征对事物进行分类。
为了对它们有一个真实的感受,我会鼓励你去玩电子表格。从头到尾跟踪一个像素。弄乱过滤器,看看会发生什么。我还在电子表格的注释中解释了更多的技术细节。
资源
要了解更多信息,我推荐以下资源:
交互式卷积——一个关于卷积的杀手级交互式教程(即只有 C 部分,没有 NN 部分)作者维克多·鲍威尔。
程序员实用深度学习 —来自 Fast 的课程。我参加了 AI,并从中学到了很多。它是在线的,而且完全免费。
展示 CNN 基础知识的精彩视频 —这是来自杰瑞米·霍华德(FastAI 创始人)的一段 20 分钟的视频。太棒了。视频嵌入在该页面中。从打开视频的第 21 分钟开始。
笔记
[1]—训练CNN 所需的数学包括微积分,所以它可以自动调整权重。但是一旦模型被训练,它实际上只需要乘法和加法来做预测。实际上,微积分是由你正在使用的深度学习库来处理的。
构建深度神经网络玩 FIFA 18
原文:https://towardsdatascience.com/building-a-deep-neural-network-to-play-fifa-18-dce54d45e675?source=collection_archive---------1-----------------------
游戏中的人工智能机器人通常是通过手工编写一系列赋予游戏智能的规则来构建的。在很大程度上,这种方法在让机器人模仿人类行为方面做得相当好。然而,对于大多数游戏来说,仍然很容易区分机器人和真人游戏。如果我们想让这些机器人的行为更像人类,不使用手工编码的规则来构建它们会有帮助吗?如果我们简单地让机器人通过观察人类的游戏方式来学习,从而理解游戏,会怎么样?
探索这一点需要一个游戏,在开发游戏本身之前,有可能收集玩游戏的人的这种数据。FIFA 就是这样一款让我探索这一点的游戏。能够玩游戏并记录我在游戏中的行动和决定让我能够训练一个端到端的基于深度学习的机器人,而不必硬编码游戏的单个规则。
这个项目的代码以及训练好的模型可以在这里找到:【https://github.com/ChintanTrivedi/DeepGamingAI_FIFA.git】
玩游戏的机制
构建这种机器人的底层机制需要在不访问任何游戏内部代码的情况下工作。好消息是,这个机器人的前提是我们不想看到任何这样的游戏内信息。一个简单的游戏窗口截图就可以输入机器人的游戏引擎。它处理这些视觉信息,并输出它想要采取的动作,这些动作通过按键模拟与游戏进行交流。冲洗并重复。
现在,我们已经有了一个框架来为机器人提供输入,并让它的输出控制游戏,我们来到了有趣的部分:学习游戏智能。这通过两个步骤来完成:( 1)使用卷积神经网络来理解屏幕截图图像,以及(2)使用长短期记忆网络来基于对图像的理解来决定适当的动作。
步骤 1:训练卷积神经网络(CNN)
众所周知,CNN 能够高精度地检测图像中的对象。除了更快的 GPU 和智能网络架构,我们还有一个可以实时运行的 CNN 模型。
为了让我们的机器人理解输入的图像,我使用了一个非常轻量级和快速的 CNN,叫做 MobileNet。从这个网络中提取的特征地图代表了对图像的高级理解,比如玩家和其他感兴趣的对象在屏幕上的位置。该特征图然后与单镜头多框一起使用,以检测球场上的球员以及球和球门。
第二步:训练长短期记忆网络(LSTM)
现在我们已经理解了这个图像,我们可以继续下去,决定我们要做什么。然而,我们不想只看一个画面就采取行动。我们更愿意看看这些图像的一小段序列。这就是 LSTMs 发挥作用的地方,因为众所周知,LSTMs 能够对数据中的时间序列进行建模。在我们的序列中,连续的帧被用作时间步长,并且使用 CNN 模型为每个帧提取特征图。这些然后被同时输入两个 LSTM 网络。
第一个 LSTM 执行学习玩家需要做什么动作的任务。因此,这是一个多类分类模型。第二个 LSTM 得到相同的输入,并且必须决定采取什么动作:传中、穿过、传球和射门:另一个多类分类模型。这两个分类问题的输出然后被转换成按键来控制游戏中的动作。
这些网络已经在通过手动玩游戏并记录输入图像和目标按键而收集的数据上被训练。少数几个收集标签数据不像是一件苦差事的例子之一!
评估机器人的性能
除了让它出去玩游戏之外,我不知道用什么精确度来判断机器人的性能。仅仅经过 400 分钟的训练,机器人已经学会了向对手的球门跑去,向前传球,并在探测到球门时射门。在 FIFA 18 的初学者模式中,它已经在大约 6 场比赛中打入 4 球,比保罗·博格巴在截至本文撰写时的 17/18 赛季中的进球多 1 球。
机器人与内置机器人比赛的视频剪辑可以在我的 YouTube 频道上找到,视频嵌入在下面。
结论
我对这种构建游戏机器人的方法的最初印象当然是积极的。经过有限的训练,这个机器人已经掌握了游戏的基本规则:向球门移动,然后把球踢进网窝。我相信,通过更多小时的训练数据,它可以获得非常接近人类水平的性能,这对于游戏开发者来说是很容易收集的。此外,扩展模型训练以从真实世界的比赛镜头中学习将使游戏开发者能够使机器人的行为更加自然和真实。现在,如果 EA sports 的任何人正在阅读这篇文章…
我发表了这个项目的后续文章,使用强化学习。在此链接处查看。谢谢!
用 Python 构建可部署的 ML 分类器
原文:https://towardsdatascience.com/building-a-deployable-ml-classifier-in-python-46ba55e1d720?source=collection_archive---------4-----------------------
如今,由于问题的复杂性和大量的相关数据,机器学习已经完全成为寻找问题解决方案的必要、有效和高效的方法。在大多数资源中,机器学习模型是在结构化数据中开发的,只是为了检查模型的准确性。但是,在开发机器学习模型时,实时的一些主要要求是在构建模型、模型中的参数调整以及将模型保存到文件系统以供以后使用或部署时处理不平衡的数据。在这里,我们将看到如何用 python 设计一个二进制分类器,同时处理上面指定的所有三个需求。
在开发机器学习模型时,我们通常会将所有的创新放在标准的工作流程中。涉及的一些步骤是获取数据,对数据进行特征工程,通过迭代训练和测试建立具有适当参数的模型,并在生产中部署建立的模型。
Machine Learning Work Flow
我们将通过构建一个二元分类器来完成这个工作流程,该分类器根据可用的特征来预测红酒的质量。数据集在 UCI 机器学习库中公开。 Scikit 学习库在这里用于分类器设计。对于源代码, github 链接是-
[## sambit 9238/机器学习
机器学习——它代表了机器学习在不同场景中的一些实现。
github.com](https://github.com/sambit9238/Machine-Learning/blob/master/WineQuality.ipynb)
首先,我们需要导入所有必要的依赖项并加载数据集。在任何 ml 模型设计中,我们总是需要 numpy 和 pandas,因为它们都涉及到数据帧、矩阵和数组操作。
import numpy as np
import pandas as pd
df = pd.read_csv("winequality-red.csv")
df.head()
数据集看起来像-
从这里可以看出,质量是用数字 3 到 8 来表示的。为了使它成为二进制分类问题,让我们把质量> 5 看作是好的,否则就是坏的。
df["quality_bin"] = np.zeros(df.shape[0])
df["quality_bin"] = df["quality_bin"].where(df["quality"]>=6, 1)
#1 means good quality and 0 means bad quality
来获得数据描述的摘要—
df.describe()
从快照中可以看出,数据值在某些属性上有很大偏差。将这些值标准化是一个很好的做法,因为这将使差异达到一个合理的水平。此外,由于大多数算法在背景中使用欧几里德距离,因此在模型建立中具有缩放特征更好。
from sklearn.preprocessing import StandardScaler
X_data = df.iloc[:,:11].values
y_data = df.iloc[:,12].values
scaler = StandardScaler()
X_data = scaler.fit_transform(X_data)
这里使用了 fit_transform,这样标准缩放器将适合 X_data 并转换 X_data。如果你需要在两个不同的数据集上进行拟合和变换,你也可以分别调用拟合和变换函数。现在,我们总共有 1599 个数据实例,其中 855 个质量差,744 个质量好。这里的数据显然是不平衡的。因为数据实例的数量较少,所以我们将进行过采样。 **但是需要注意的是,重采样应该总是只在训练数据上进行,而不是在测试/验证数据上。**现在,让我们将数据集分为训练数据集和测试数据集进行建模。
from sklearn.cross_validation import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X_data, y_data, test_size=0.3, random_state=42)
#so that 30% will be selected for testing data randomly
除了训练和测试分割,你还可以采用被认为是更有效的交叉验证方法。现在我们有 588 个质量差的和 531 个质量好的实例用于训练。剩下 267 个质量差的和 213 个质量好的测试实例。是时候对训练数据进行重新采样,以便平衡数据,使模型不会有偏差。这里我们将使用 SMOTE 算法进行过采样。
from imblearn.over_sampling import SMOTE
#resampling need to be done on training dataset only
X_train_res, y_train_res = SMOTE().fit_sample(X_train, y_train)
经过过采样后,在训练集中有 588 个好的和坏的葡萄酒样本。现在是选择模型的时候了。我在这里采用了随机梯度分类器。但是,你现在可以检查几个模型并比较它们的准确性来选择合适的。
from sklearn.linear_model import SGDClassifier
sg = SGDClassifier(random_state=42)
sg.fit(X_train_res,y_train_res)
pred = sg.predict(X_test)
from sklearn.metrics import classification_report,accuracy_score
print(classification_report(y_test, pred))
print(accuracy_score(y_test, pred))
结果看起来像-
Classification Report
得到的准确率为 65.625%。学习率、损失函数等参数。在模型的性能中起主要作用。使用 GridSearchCV 可以有效地为模型选择最佳参数。
#parameter tuning
from sklearn.model_selection import GridSearchCV
#model
model = SGDClassifier(random_state=42)
#parameters
params = {'loss': ["hinge", "log", "perceptron"],
'alpha':[0.001, 0.0001, 0.00001]}
#carrying out grid search
clf = GridSearchCV(model, params)
clf.fit(X_train_res, y_train_res)
#the selected parameters by grid search
print(clf.best_estimator_)
Best Parameters for the Classifier
正如这里可以看到的,这里只提供了损失函数和 alpha,用于寻找最佳选项。其他参数也可以这样做。损失函数的最佳选项似乎是“铰链”红外线性 SVM,α值似乎是 0.001。现在,我们将使用网格搜索选择的最佳参数建立一个模型。
#final model by taking suitable parameters
clf = SGDClassifier(random_state=42, loss="hinge", alpha=0.001)
clf.fit(X_train_res, y_train_res)
pred = clf.predict(X_test)
现在,我们选择了模型,调整了参数,因此是时候在部署之前验证模型了。
print(classification_report(y_test, pred))
print(accuracy_score(y_test, pred))
Classification Report
从这里可以看出,调整参数后,指标值提高了 2–3%。准确率也从 65.625%提高到了 70.625%。如果你仍然对这个模型不满意,你也可以通过一些训练和测试迭代来尝试其他算法。现在,既然模型已经构建好了,就需要将它保存到文件系统中,以便以后使用或部署到其他地方。
from sklearn.externals import joblib
joblib.dump(clf, "wine_quality_clf.pkl")
当您需要分类器时,可以使用 joblib 简单地加载它,然后传递特征数组以获得结果。
clf1 = joblib.load("wine_quality_clf.pkl")
clf1.predict([X_test[0]])
恭喜你。现在你已经准备好设计一个可部署的机器学习模型了。:-D
参考资料:-
[## 重击
重击
SMOTEwww.cs.cmu.edu](https://www.cs.cmu.edu/afs/cs/project/jair/pub/volume16/chawla02a-html/node6.html) [## 3.2.调整估计器的超参数-sci kit-了解 0.19.1 文档
请注意,这些参数的一个小子集通常会对预测或计算产生很大影响…
scikit-learn.org](http://scikit-learn.org/stable/modules/grid_search.html) [## 功能缩放的重要性-sci kit-了解 0.19.1 文档
通过标准化(或 Z 分数标准化)进行特征缩放对于许多应用程序来说是一个重要的预处理步骤
scikit-learn.org](http://scikit-learn.org/stable/auto_examples/preprocessing/plot_scaling_importance.html)
用 D3.js 和 Svidget.js 构建圆环图小部件
原文:https://towardsdatascience.com/building-a-donut-chart-widget-with-d3-js-and-svidget-js-8c150ccb01ae?source=collection_archive---------1-----------------------
D3.js 是一个非常著名和受人尊敬的 JavaScript 库,可以让你创建复杂的数据可视化,比如图表和图形。它已经成为 web 数据可视化的同义词。 Svidget.js 是一个 JavaScript 框架,允许您在纯 SVG 中创建数据可视化小部件。从表面上看,这两个公司似乎是在相互竞争,但实际上恰恰相反。通过使用 D3 来输出一些惊人的数据可视化,并使用 Svidget.js 来简化部署和重用的包装,我们可以创建非常棒的可视化组件,可以轻松地嵌入到任何地方。简单来说,Svidget 就是汉堡小圆面包,D3 就是肉饼。
首先,让我们从小部件的角度考虑一个圆环图。它的属性或参数是什么?我们可以调用什么动作或方法?小部件会触发什么事件?Svidget 小部件由 3 个构件组成— 参数、动作和事件。定义这些工件是widget 化的第一步。(关于构建小部件的完整介绍,包括这些概念,可以在 svidget.com 上找到。)
三者中最难的是计算参数。为了获得一些灵感,我们可以看看现有的实现,如charist . js或 Google Charts 。请记住,我们通常不想提供所有类型的配置,而是提供一个很好的抽象概念,让消费者快速启动并运行。根据最初的发现,我想出了:
- 数据—小部件的数据,以数组形式表示
- maxSlices —将剩余数据分组到“其他”切片之前的最大切片数
- 开始角度—图表开始的角度,以度为单位,通常为 0 度
- 排序—如何对图表进行排序:“无”、“asc”或“desc”
- 颜色—为切片着色的颜色数组
- 宽度-圆环的宽度(终点-起点半径)
注意:最终的小部件可能还包含样式参数,我们将在后面介绍。
对于小部件操作,图表几乎不需要暴露什么。图表相对被动。但是出于演示的目的,让我们添加一个名为 animate 的动作,它将强制图表在被调用时自动显示。(第一次加载图表时会播放相同的动画。)
对于小部件事件,有两个有用的事件——一个是选择事件,它告诉我们何时通过鼠标悬停(或在移动设备上点击)选择了切片或片段;另一个是激活事件,它告诉我们用户何时点击了切片(在移动设备上,他们将点击以选择,然后再次点击以激活)。
既然我们已经弄清楚了所有的小部件工件,让我们把它们放在一起。在 Svidget 中,您可以在 SVG 中用 XML 声明性地定义所有这些内容。有关这方面的更多信息,请从 GitHub repo 下载 svidget.xsd 模式。综上所述,小部件 SVG 最初看起来如下:
<svg ae kl" href="http://www.w3.org/2000/svg" rel="noopener ugc nofollow" target="_blank">http://www.w3.org/2000/svg"
xmlns:svidget="[http://www.svidget.org/svidget](http://www.svidget.org/svidget)"
width="400" height="400" viewBox="0 0 400 400" svidget:version="0.3.4"><svidget:params>
<svidget:param name="data" />
<svidget:param name="maxSlices" />
<svidget:param name="startAngle" />
<svidget:param name="sort" />
<svidget:param name="colors" />
<svidget:param name="width" />
</svidget:params><svidget:actions>
<svidget:action name="animate" binding="animate">
<svidget:actionparam name="duration" type="number" />
</svidget:action>
</svidget:actions><svidget:events>
<svidget:event name="sliceSelect" />
<svidget:event name="sliceActivate" />
</svidget:events>
接下来,让我们布局我们的 SVG。这只是一个框架,D3 会处理剩下的部分。
<g id="chart" transform="translate(200 200)"></g>
最后,让我们对肉进行编码——使用 D3 填充甜甜圈图。
// set up
var outerRadius = CHART_RADIUS;
var innerRadius = outerRadius — _width;
var widget = svidget.$; // get an instance to the current widget// params
// note: data in form of [['Item 1', 3], ['Item 2', 6]]
var data = widget.param('data').value();
var startAngle = widget.param('startAngle').value();
var sort = widget.param('sort').value();
var colors = widget.param('colors').value();// colors
var colorRange = d3.scale.ordinal().range(colors);// pie layout — for layout out arcs as a pie/donut chart
var pie = d3.layout.pie()
.startAngle(toRadians(startAngle))
.endAngle(toRadians(startAngle + 360))
.sort(sortDataFunc(sort))
.value(function(d) {
return numIt(d[1]); /* second element in data inner array */
});// the main arc object
var arc = d3.svg.arc()
.outerRadius(outerRadius)
.innerRadius(innerRadius);// create chart and slices
var chart = d3.select('#chart');
var slices = chart.selectAll('.slice')
.data(pie(data))
.enter()
.append('g');
var paths = slices.append('path');// draw slices
paths.attr('stroke', '#fff')
.attr('stroke-width', 2)
.attr('d', arc)
.style('fill', function(d, i) {
return colorRange(i);
});// draw labels
slices.append('text')
.attr('dy', '.35em')
.style('text-anchor', 'middle')
.attr('transform', function(d) {
return 'translate(' + arc.centroid(d) + ')';
})
.text(function(d) {
d.data[0]; // d.data == ['Label', 0]
});
既然我们的 donutChart.svg 小部件文件已经完成并准备就绪,在网站上嵌入就变得容易了。只需使用 HTML 标签,传递您想要的参数值:
<object id="donutChart" role="svidget" data="path/to/donutChart.svg" type="image/svg+xml" width="400" height="400">
<param name="data" value="[['banana', 7], ['apple', 6], ['cherry', 2], ['orange', 10], ['grape', 3.5]]" />
<param name="maxSlices" value="-1" />
<param name="startAngle" value="0" />
<param name="sort" value="none" />
<param name="colors" value="['#ffb244','#ed723c','#da3333','#b01111','#7a0000']" />
<param name="width" value="60" />
</object>
最后的结果是:
The resulting donut chart
完整的工作示例代码可以在这里找到。
虽然我们使用 D3 创建了一个圆环图小部件,但是它的使用潜力远远超过了图表。事实是,像 Chartist 这样的图书馆做图表做得非常好。我们可以将 Chartist 图表包装成一个 Svidget 小部件,类似于我们使用 D3 生成图表的方式,但是对于熟练的 JavaScript 开发人员来说,其优势可能并不明显。但是对于其他人来说,抽象出使用复杂库 D3 的实现细节是非常有益的。
有人问我,为什么要创建 Svidget.js 库?简单来说,它用交互式 SVG 解决了生产者-消费者抽象问题。在我的行业中,我们在数据中心运营的实时可视化仪表板中使用 SVG 小部件。消费者可以通过选择这些小部件并将它们连接到数据上来构建任何一个仪表板。相反,一个独立的制作团队可以构建通用的、可重用的小部件。这些小部件远远不止是简单的图表——它们可以代表冷却风扇、发电机、电路,甚至门。
同样,任何人都可以使用 Svidget 让非技术人员将复杂的 SVG 插图嵌入到他们的网站中。
乔·阿格斯特是基础层的首席软件工程师。编码是我众多努力中的一项。我还写了一部科幻小说《最后的六天》(T7),现在可以在 Kindle 上阅读。
用 Zeppelin Spark 和 Neo4j 构建图形数据管道
原文:https://towardsdatascience.com/building-a-graph-data-pipeline-with-zeppelin-spark-and-neo4j-8b6b83f4fb70?source=collection_archive---------3-----------------------
向 Zeppelin 添加网络支持
交互式笔记本如今非常流行。无论您是在数据工程(数据处理)中使用它们,还是在数据科学项目(数据分析/ML)中使用它们,它们都是“事实上的”标准,并且正在许多组织中取代幻灯片演示。除了 Jupyter 笔记本之外,Apache Zeppelin 的应用也很广泛,特别是因为它与 Apache Spark 和其他大数据系统集成得很好。
从我在不同环境下使用 Zeppelin 和 Neo4j 的经验开始,我开发了 Zeppelin 解释器,它连接到 Neo4j,以便直接在笔记本中查询和显示图形数据(图形和表格格式)。这个解释器现在是 zeplin 0.8的一部分,所以你可以开箱即用来查询和可视化你的图形数据!
本文将展示如何在 Docker 环境中使用 Zeppelin、Spark 和 Neo4j 来构建简单的数据管道。
我们将使用芝加哥犯罪数据集,它涵盖了自 2001 年以来发生的犯罪。整个数据集包含大约 600 万起犯罪和关于它们的元数据,例如位置、犯罪类型和日期等等。
在本例中,我们将使用由so crata API返回的 1000 个犯罪构成的数据集子集。
步骤 1:配置容器
你应该已经安装了 Docker 和 Docker-Compose 。
不幸的是 Zeppelin 在嵌入式版本上有一个 bug ,我们需要解决它,使它像容器一样工作。为此,我们创建了自己的 docker 文件:
这是我们的合成文件。基本上将官方的 Neo4j 容器和我们的 Zeppelin 容器合并为两个服务。
对于您的本地设置,只需更改 *neo4j-zeppelin.yml*
的第 22 行和第 23 行,以便提供正确的路径。
现在让我们运行这个示例代码来加速我们的堆栈:
docker-compose -f neo4j-zeppelin.yml up -d
现在我们有两个可到达的服务:
- 齐柏林飞艇: http://localhost:8080
- neo4j:http://localhost:7474
步骤 2:配置 Zeppelin
如果您从我的 GitHub 存储库中下载并执行 compose 文件,那么一切都是预先配置好的。
但是我们来看一些**隐藏配置。**右上角有一个菜单
点击解释器,然后按“火花”筛选列表。
如您所见,用黄色突出显示的是 Neo4j-Spark-Connector 连接 Neo4j 所需的三个属性。
现在,如果您将解释器过滤器更改为“neo4j ”,您会发现:
该页面包含 Neo4j 解释器的属性,尤其是 auth 信息。
第三步:我们的数据处理笔记本
The notebook in action
我们已经配置了 Zeppelin / Spark / Neo4j 堆栈,现在让我们享受一下数据分析的乐趣。
在 Zeppelin 中,每个笔记本由段落或块组成,每个段落或块包含处理特定任务的代码块。
在我们的笔记本中,第一个块用于从 Spark-Packages 存储库中下载我们项目中所需的依赖项:Neo4j-Spark-Connector
在第二个块中,我们下载数据集并存储到我们的文件系统中
正如我在介绍中所说,我们将使用芝加哥犯罪数据集的一个小子集。
在第三个块中,我们将数据集从文件系统读入 Spark 数据集
在第四块中,我们使用
crimeDF.printSchema
从这个模式开始,我们将像这样构造一个图模型
Graph Schema
我们有 4 个节点:
Beat
(警区)带**beat**
属性;Crime
具有**id, description, case_number, point**
属性;CrimeType
带有**primary_type**
性质;CrimeDate
具有**parsed_date**
和**date**
属性
和 3 种关系:
ON_BEAT
从**Beat**
开始,到**Crime**
结束;IS_TYPE
从 a**Crime**
开始,到 a**CrimeType**
结束;ON_DATE
从 a**Crime**
开始,到 a**CrimeDate**
结束;
在第五块中,我们将创建新列,以便添加解析日期和地理空间参考。顺便说一下,从 Neo4j 3.4 开始,数据库本身支持日期和空间数据,但不幸的是 Neo4j-Spark-Connector 还不支持它。
在第六块中,我们通过使用 Zeppelin 上下文 API 简单地探索我们的数据集:
z.show(exendedCrimeDF)
现在让我们跳到第七个模块中,在这里我们使用 Neo4j-Spark-Connector 获取数据。我们使用提供方法的Neo4jDataFrame
:
Neo4jDataFrame.mergeEdgeList(sc: SparkContext,
dataFrame: DataFrame,
source: (label,Seq[prop]),
relationship: (type,Seq[prop]),
target: (label,Seq[prop]))
要将数据帧合并回 Neo4j 图形:
- 两个节点按顺序由第一个属性合并;
- 两个节点之间的关系被合并,序列中的所有属性都将在该关系上设置;
- 序列中的属性名用作数据框的列名,目前没有名称转换;
- 结果以 10000 为一批发送到图表中。
到目前为止,我们只在齐柏林飞艇和火花乐队工作。现在图形数据已经导入到 Neo4j 中,我们可以使用 Neo4j 解释器从 Zeppelin 查询 Neo4j。
要使用 Neo4j 解释器,我们必须使用特定的解释器绑定
%neo4j
接下来是我们的密码查询:
MATCH (crime:Crime)-[is:IS_TYPE]->(type:CrimeType),
(crime)-[on:ON_DATE]->(date:CrimeDate)
RETURN crime, is, type, on, date
LIMIT 10
结果将显示为图形,如下图所示:
A Neo4j query block with graph query and visualization
该科分为五个不同的领域:
- 红色:用于编写密码查询的区域;
- 黄色:显示最新 Zeppelin 发行版中可用的新图形可视化的按钮;
- 绿色:关于图形的一般信息;节点、边等…
- 蓝色:用于呈现图形可视化的区域
- 紫色:当你点击一个节点/边时,相关数据将会显示的区域
此外,结果图也将作为一个扁平的表格。因此,所有其他可视化(图表等)也是可用的,您可以通过单击相应的按钮在它们之间简单地切换。
图形可视化附带设置,以便提供一些配置:
The graph visualization settings
例如,通过这些设置,您可以自定义显示为节点标题的属性。
使用鼠标滚轮,您可以放大/缩小图表,以显示如下所示的标题
利用 Zeppelin 动态表单
Neo4j 解释器可以利用 Zeppelin 动态表单来构建参数化查询,就像这样:
好处:增加地理空间可视化
Zeppelin 有一个名为 Helium 的可插拔架构,可以轻松添加新的可视化内容。在右上方的菜单中点击氦气条目,然后在氦气页面中启用 zeplin-Leaflet 作为,如图所示。然后,您的密码查询结果也可以在地图上可视化。
你可以直接从 GitHub 下载整个笔记本代码。我很想得到你对 Apache Zeppelin 的 Neo4j 和图形解释器的反馈,请在评论或我的 GitHub 问题中告诉我。此外,如果你有 Zeppelin 和 Spark 的很酷的图形用例,也请分享它们,这样更多的人可以了解图形的力量。
用 Scikit-learn 构建 k-近邻模型
原文:https://towardsdatascience.com/building-a-k-nearest-neighbors-k-nn-model-with-scikit-learn-51209555453a?source=collection_archive---------1-----------------------
k-NN (Image credit)
k-近邻(k-NN)是一种有监督的机器学习模型。监督学习是指模型从已经标记的数据中学习。监督学习模型接受一组输入对象和输出值。然后,该模型根据这些数据进行训练,以学习如何将输入映射到所需的输出,这样它就可以学习根据看不见的数据进行预测。
k-NN 模型通过获取一个数据点并查看“k”个最接近的标记数据点来工作。然后,给数据点分配“k”个最接近点中大多数的标签。
例如,如果 k = 5,3 个点为“绿色”,2 个点为“红色”,那么所讨论的数据点将被标记为“绿色”,因为“绿色”占大多数(如上图所示)。
Scikit-learn 是一个用于 Python 的机器学习库。在本教程中,我们将使用 Scikit-learn 构建一个 k-NN 模型来预测患者是否患有糖尿病。
读入训练数据
对于我们的 k-NN 模型,第一步是读入我们将用作输入的数据。对于这个例子,我们使用糖尿病数据集。首先,我们将使用 Pandas 读入数据。我不会详细介绍熊猫,但如果你想进一步深入数据科学和机器学习,这是一个你应该熟悉的库。
import pandas as pd#read in the data using pandas
df = pd.read_csv(‘data/diabetes_data.csv’)#check data has been read in properly
df.head()
接下来,我们来看看我们有多少数据。我们将在数据帧上调用“shape”函数,查看数据中有多少行和多少列。行表示患者的数量,列表示特征(年龄、体重等)的数量。)在数据集中。
#check number of rows and columns in dataset
df.shape
我们可以看到,我们有 768 行数据(潜在的糖尿病患者)和 9 列数据(8 个输入特征和 1 个目标输出)。
将数据集分成输入和目标
现在让我们把数据集分成输入(X)和目标(y)。我们的输入将是除“糖尿病”之外的每一列,因为“糖尿病”是我们将试图预测的。因此,“糖尿病”将是我们的目标。
我们将使用 pandas 'drop '函数从数据帧中删除列' diabetes ',并将其存储在变量' X '中。这将是我们的投入。
*#create a dataframe with all training data except the target column*
X = df.drop(columns=[‘diabetes’])*#check that the target variable has been removed*
X.head()
我们将把数据集的“糖尿病”列插入到目标变量(y)中。
#separate target values
y = df[‘diabetes’].values#view target values
y[0:5]
将数据集拆分为训练和测试数据
现在,我们将数据集分为训练数据和测试数据。训练数据是模型将从中学习的数据。测试数据是我们将用来查看模型在看不见的数据上表现如何的数据。
Scikit-learn 有一个我们可以使用的名为“train_test_split”的函数,它使我们可以很容易地将数据集分成训练和测试数据。
from sklearn.model_selection import train_test_split#split dataset into train and test data
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1, stratify=y)
“train_test_split”接受 5 个参数。前两个参数是我们之前分开的输入和目标数据。接下来,我们将“测试大小”设置为 0.2。这意味着 20%的数据将用于测试,剩下 80%的数据作为模型学习的训练数据。将“random_state”设置为 1 可以确保我们每次都能获得相同的分割,这样我们就可以重现我们的结果。
将“分层”设置为 y 会使我们的训练分割表示 y 变量中每个值的比例。例如,在我们的数据集中,如果 25%的患者患有糖尿病,75%的患者没有糖尿病,将“分层”设置为 y 将确保随机拆分有 25%的糖尿病患者和 75%的非糖尿病患者。
构建和训练模型
接下来,我们必须建立模型。代码如下:
from sklearn.neighbors import KNeighborsClassifier# Create KNN classifier
knn = KNeighborsClassifier(n_neighbors = 3)# Fit the classifier to the data
knn.fit(X_train,y_train)
首先,我们将创建一个新的 k-NN 分类器,并将“n_neighbors”设置为 3。概括地说,这意味着如果与新数据点最近的 3 个点中至少有 2 个是没有糖尿病的患者,那么新数据点将被标记为“没有糖尿病”,反之亦然。换句话说,一个新的数据点由 3 个最近点的多数标记。
我们将“n_neighbors”设置为 3 作为起点。我们将在下面更详细地讨论如何更好地为“n_neighbors”选择一个值,以便模型可以提高其性能。
接下来,我们需要训练模型。为了训练我们的新模型,我们将使用“fit”函数并传递我们的训练数据作为参数,以使我们的模型符合训练数据。
测试模型
一旦模型训练完毕,我们就可以使用模型上的“预测”功能对测试数据进行预测。如前面检查“y”时所见,0 表示患者没有糖尿病,1 表示患者有糖尿病。为了节省空间,我们将只显示测试集的前 5 个预测。
#show first 5 model predictions on the test data
knn.predict(X_test)[0:5]
我们可以看到,该模型预测测试集中的前 4 名患者“没有糖尿病”,而第 5 名患者“患有糖尿病”。
现在让我们看看我们的模型在整个测试集上有多精确。为此,我们将使用“score”函数,并传入我们的测试输入和目标数据,以查看我们的模型预测与实际结果的匹配程度。
#check accuracy of our model on the test data
knn.score(X_test, y_test)
我们的模型具有大约 66.88%的准确度。这是一个好的开始,但我们将在下面看到如何提高模型性能。
恭喜你。你现在已经建立了一个惊人的 k-NN 模型!
k 倍交叉验证
交叉验证是指数据集被随机分成“k”个组。其中一组用作测试集,其余的用作训练集。该模型在训练集上被训练,并在测试集上被评分。然后重复该过程,直到每个唯一的组都被用作测试集。
例如,对于 5 重交叉验证,数据集将被分成 5 组,模型将被训练和测试 5 次,因此每组都有机会成为测试集。这可以从下图中看出。
5-fold cross validation (image credit)
我们之前使用的训练-测试-拆分方法称为“保持”。交叉验证比使用维持方法更好,因为维持方法的得分取决于如何将数据拆分为定型集和测试集。交叉验证为模型提供了在多个拆分上进行测试的机会,因此我们可以更好地了解模型在看不见的数据上的表现。
为了使用交叉验证来训练和测试我们的模型,我们将使用交叉验证值为 5 的“cross_val_score”函数。“cross_val_score”将我们的 k-NN 模型和我们的数据作为参数。然后,它将我们的数据分成 5 组,并对我们的数据进行 5 次拟合和评分,每次都将准确度分数记录在一个数组中。我们将准确性分数保存在“cv_scores”变量中。
为了计算 5 个分数的平均值,我们将使用 numpy 的 mean 函数,传入“cv_score”。Numpy 是 Python 中一个有用的数学库。
from sklearn.model_selection import cross_val_score
import numpy as np#create a new KNN model
knn_cv = KNeighborsClassifier(n_neighbors=3)#train model with cv of 5
cv_scores = cross_val_score(knn_cv, X, y, cv=5)#print each cv score (accuracy) and average them
print(cv_scores)
print(‘cv_scores mean:{}’.format(np.mean(cv_scores)))
使用交叉验证,我们的平均分数约为 71.36%。与我们之前使用维持方法进行的测试相比,这更准确地展示了我们的模型在未知数据上的表现。
使用 GridSearchCV 超调模型参数
当建立我们的初始 k-NN 模型时,我们将参数“n_neighbors”设置为 3 作为起点,该选择背后没有真正的逻辑。
超调参数是指通过一个过程来为您的模型找到最佳参数,以提高精度。在我们的例子中,我们将使用 GridSearchCV 来寻找‘n _ neighbors’的最优值。
GridSearchCV 通过在我们指定的参数范围内多次训练我们的模型来工作。这样,我们可以用每个参数测试我们的模型,并找出最佳值以获得最佳精度结果。
对于我们的模型,我们将为“n_neighbors”指定一个值范围,以查看哪个值最适合我们的模型。为此,我们将创建一个字典,将' n_neighbors '设置为键,并使用 numpy 创建一个值从 1 到 24 的数组。
我们使用网格搜索的新模型将采用新的 k-NN 分类器、我们的 param_grid 和交叉验证值 5,以便找到‘n _ neighbors’的最佳值。
from sklearn.model_selection import GridSearchCV#create new a knn model
knn2 = KNeighborsClassifier()#create a dictionary of all values we want to test for n_neighbors
param_grid = {‘n_neighbors’: np.arange(1, 25)}#use gridsearch to test all values for n_neighbors
knn_gscv = GridSearchCV(knn2, param_grid, cv=5)#fit model to data
knn_gscv.fit(X, y)
训练之后,我们可以检查我们测试的‘n _ neighbors’的哪个值表现最好。为此,我们将在模型上调用‘best _ params _’。
#check top performing n_neighbors value
knn_gscv.best_params_
我们可以看到,14 是“n_neighbors”的最佳值。当“n_neighbors”为 14 时,我们可以使用“best_score_”函数来检查我们的模型的准确性。best_score_ '输出通过交叉验证获得的分数的平均准确度。
#check mean score for the top performing value of n_neighbors
knn_gscv.best_score_
通过使用网格搜索为我们的模型找到最佳参数,我们已经将我们的模型精度提高了 4%以上!
感谢阅读!本教程的 GitHub 库(jupyter 笔记本和数据集)可以在这里找到。
如果你想了解我的机器学习内容,请关注我:)
使用 PySpark 和 MLlib 构建线性回归
原文:https://towardsdatascience.com/building-a-linear-regression-with-pyspark-and-mllib-d065c3ba246a?source=collection_archive---------0-----------------------
Photo credit: Pixabay
Apache Spark 已经成为机器学习和数据科学最常用和最受支持的开源工具之一。
在这篇文章中,我将帮助你开始使用 Apache Spark 的 spark.ml 线性回归来预测波士顿房价。我们的数据来自 Kaggle 竞赛:波士顿郊区的房屋价值。对于每个房屋观察,我们有以下信息:
各城镇的人均犯罪率。
ZN —面积超过 25,000 平方英尺的住宅用地比例
INDUS —每个城镇非零售商业亩数比例。
CHAS —查尔斯河虚拟变量(= 1,如果区域边界为河流;否则为 0)。
NOX —氮氧化物浓度(百万分之一)。
RM —每个住宅的平均房间数。
年龄—1940 年前建造的自有住房比例。
DIS —到五个波士顿就业中心的加权平均距离。
RAD —放射状公路可达性指标。
税 —每 1 万美元的全价值财产税税率。
pt ratio——按城镇划分的学生/教师比率。
黑人 — 1000(Bk — 0.63)其中 Bk 是按城镇划分的黑人比例。
LSTAT —较低的人口地位(百分比)。
MV —以千美元为单位的自有住房的中值。这是目标变量。
输入数据集包含各种房屋的详细信息。根据提供的信息,目标是提出一个模型来预测该地区给定房屋的中值。
加载数据
from pyspark import SparkConf, SparkContext
from pyspark.sql import SQLContext
sc= SparkContext()
sqlContext = SQLContext(sc)house_df = sqlContext.read.format('com.databricks.spark.csv').options(header='true', inferschema='true').load('boston.csv')
house_df.take(1)
【Row(CRIM = 0.00632,ZN=18.0,INDUS=2.309999943,CHAS=0,NOX=0.537999988,RM=6.574999809,AGE = 65.19999695,DIS=4.090000153,RAD=1,TAX=296,PT = 15.30000019
数据探索
以树格式打印模式。
house_df.cache()
house_df.printSchema()root
|-- CRIM: double (nullable = true)
|-- ZN: double (nullable = true)
|-- INDUS: double (nullable = true)
|-- CHAS: integer (nullable = true)
|-- NOX: double (nullable = true)
|-- RM: double (nullable = true)
|-- AGE: double (nullable = true)
|-- DIS: double (nullable = true)
|-- RAD: integer (nullable = true)
|-- TAX: integer (nullable = true)
|-- PT: double (nullable = true)
|-- B: double (nullable = true)
|-- LSTAT: double (nullable = true)
|-- MV: double (nullable = true)
执行描述性分析
house_df.describe().toPandas().transpose()
Figure 1
散点图是粗略确定多个自变量之间是否存在线性相关性的一个很好的方法。
import pandas as pdnumeric_features = [t[0] for t in house_df.dtypes if t[1] == 'int' or t[1] == 'double']
sampled_data = house_df.select(numeric_features).sample(False, 0.8).toPandas()
axs = pd.scatter_matrix(sampled_data, figsize=(10, 10))
n = len(sampled_data.columns)
for i in range(n):
v = axs[i, 0]
v.yaxis.label.set_rotation(0)
v.yaxis.label.set_ha('right')
v.set_yticks(())
h = axs[n-1, i]
h.xaxis.label.set_rotation(90)
h.set_xticks(())
Figure 2
很难看到。让我们找出自变量和目标变量之间的相关性。
import six
for i in house_df.columns:
if not( isinstance(house_df.select(i).take(1)[0][0], six.string_types)):
print( "Correlation to MV for ", i, house_df.stat.corr('MV',i))Correlation to MV for CRIM -0.3883046116575088
Correlation to MV for ZN 0.36044534463752903
Correlation to MV for INDUS -0.48372517128143383
Correlation to MV for CHAS 0.17526017775291847
Correlation to MV for NOX -0.4273207763683772
Correlation to MV for RM 0.695359937127267
Correlation to MV for AGE -0.37695456714288667
Correlation to MV for DIS 0.24992873873512172
Correlation to MV for RAD -0.3816262315669168
Correlation to MV for TAX -0.46853593528654536
Correlation to MV for PT -0.5077867038116085
Correlation to MV for B 0.3334608226834164
Correlation to MV for LSTAT -0.7376627294671615
Correlation to MV for MV 1.0
相关系数范围从–1 到 1。当接近 1 时,说明有很强的正相关性;例如,当房间数量增加时,中值往往会增加。当系数接近–1 时,说明有很强的负相关性;当处于较低地位的人口比例上升时,中间值往往会下降。最后,系数接近零意味着没有线性相关性。
目前,我们将保留所有变量。
为机器学习准备数据。我们只需要两列—功能和标签(“MV”):
from pyspark.ml.feature import VectorAssemblervectorAssembler = VectorAssembler(inputCols = ['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX', 'PT', 'B', 'LSTAT'], outputCol = 'features')
vhouse_df = vectorAssembler.transform(house_df)
vhouse_df = vhouse_df.select(['features', 'MV'])
vhouse_df.show(3)
Figure 3
splits = vhouse_df.randomSplit([0.7, 0.3])
train_df = splits[0]
test_df = splits[1]
线性回归
from pyspark.ml.regression import LinearRegressionlr = LinearRegression(featuresCol = 'features', labelCol='MV', maxIter=10, regParam=0.3, elasticNetParam=0.8)
lr_model = lr.fit(train_df)
print("Coefficients: " + str(lr_model.coefficients))
print("Intercept: " + str(lr_model.intercept))
系数:【0.0,0.007302310571175137,-0.03286303124593804,1.413473328268,-7.919323668,5.21692169246
对训练集的模型进行总结,并打印出一些指标:
trainingSummary = lr_model.summary
print("RMSE: %f" % trainingSummary.rootMeanSquaredError)
print("r2: %f" % trainingSummary.r2)
RMSE:4.675914
R2:0.743627
RMSE 测量模型预测值和实际值之间的差异。然而,RMSE 本身是没有意义的,直到我们与实际的“MV”值进行比较,如平均值、最小值和最大值。经过这样的比较,我们的 RMSE 看起来还不错。
train_df.describe().show()
Figure 4
r 的平方为 0.74 表明,在我们的模型中,大约 74%的“MV”可变性可以用该模型来解释。这与 Scikit-Learn 的结果一致。还不错。然而,我们必须小心,训练集上的性能可能不是测试集上性能的良好近似。
lr_predictions = lr_model.transform(test_df)
lr_predictions.select("prediction","MV","features").show(5)from pyspark.ml.evaluation import RegressionEvaluator
lr_evaluator = RegressionEvaluator(predictionCol="prediction", \
labelCol="MV",metricName="r2")
print("R Squared (R2) on test data = %g" % lr_evaluator.evaluate(lr_predictions))
Figure 5
test_result = lr_model.evaluate(test_df)
print("Root Mean Squared Error (RMSE) on test data = %g" % test_result.rootMeanSquaredError)
测试数据的均方根误差(RMSE)= 5.52048
果然,我们在测试集上取得了更差的 RMSE 和 R 平方。
print("numIterations: %d" % trainingSummary.totalIterations)
print("objectiveHistory: %s" % str(trainingSummary.objectiveHistory))
trainingSummary.residuals.show()
操作数:11
目标历史记录:【0.49999999999956,0.4281126976,069,304,0.22593628,5989,17,0.20326326,5959,582,0.1。546667
Figure 6
使用我们的线性回归模型进行一些预测:
predictions = lr_model.transform(test_df)
predictions.select("prediction","MV","features").show()
Figure 7
决策树回归
from pyspark.ml.regression import DecisionTreeRegressordt = DecisionTreeRegressor(featuresCol ='features', labelCol = 'MV')
dt_model = dt.fit(train_df)
dt_predictions = dt_model.transform(test_df)
dt_evaluator = RegressionEvaluator(
labelCol="MV", predictionCol="prediction", metricName="rmse")
rmse = dt_evaluator.evaluate(dt_predictions)
print("Root Mean Squared Error (RMSE) on test data = %g" % rmse)
测试数据上的均方根误差(RMSE)= 4.39053
特征重要性
dt_model.featureImportances
SparseVector(13,{0: 0.0496,1: 0.0,4: 0.0118,5: 0.624,6: 0.0005,7: 0.1167,8: 0.0044,10: 0.013,12: 0.1799})
house_df.take(1)
【Row(CRIM = 0.00632,ZN=18.0,INDUS=2.309999943,CHAS=0,NOX=0.537999988,RM=6.574999809,AGE = 65.19999695,DIS=4.090000153,RAD=1,TAX=296,PT = 15.30000019
显然,在我们的数据中,房间数量是预测房屋中值价格的最重要特征。
梯度推进的树回归
from pyspark.ml.regression import GBTRegressor
gbt = GBTRegressor(featuresCol = 'features', labelCol = 'MV', maxIter=10)
gbt_model = gbt.fit(train_df)
gbt_predictions = gbt_model.transform(test_df)
gbt_predictions.select('prediction', 'MV', 'features').show(5)
Figure 8
gbt_evaluator = RegressionEvaluator(
labelCol="MV", predictionCol="prediction", metricName="rmse")
rmse = gbt_evaluator.evaluate(gbt_predictions)
print("Root Mean Squared Error (RMSE) on test data = %g" % rmse)
测试数据的均方根误差(RMSE )= 4.19795
梯度推进的树回归在我们的数据上表现最好。
源代码可以在 Github 上找到。我很高兴听到任何反馈或问题。
用 Python 构建逻辑回归
原文:https://towardsdatascience.com/building-a-logistic-regression-in-python-301d27367c24?source=collection_archive---------1-----------------------
假设你得到了不同申请人的两次考试的分数,目标是根据分数将申请人分为两类,即如果申请人可以被大学录取,则分为 1 类;如果申请人不能被大学录取,则分为 0 类。这个问题可以用线性回归解决吗?让我们检查一下。
**注意:**我建议你在继续写这篇博客之前,先阅读一下线性回归。
目录
- 什么是逻辑回归?
- 数据集可视化
- 假设和成本函数
- 从头开始训练模型
- 模型评估
- Scikit-learn 实现
什么是逻辑回归?
如果你记得线性回归,它是用来确定一个连续因变量的值。逻辑回归通常用于分类目的。与线性回归不同,因变量只能取有限数量的值,即因变量是分类的。当可能的结果只有两个时,称为二元逻辑回归**。**
让我们看看逻辑回归是如何用于分类任务的。
在线性回归中,输出是输入的加权和。逻辑回归是一种广义线性回归,因为我们不直接输出输入的加权和,而是通过一个可以映射 0 到 1 之间任何实数值的函数来传递。
如果我们像线性回归一样将输入的加权和作为输出,则该值可能大于 1,但我们希望该值介于 0 和 1 之间。这就是为什么线性回归不能用于分类任务的原因。
从下图中我们可以看到,线性回归的输出通过一个激活函数传递,该函数可以映射 0 和 1 之间的任何实数值。
所使用的激活功能被称为s 形功能。sigmoid 函数的图形如下所示
sigmoid function
我们可以看到,sigmoid 函数的值总是位于 0 和 1 之间。X=0 时,该值正好为 0.5。我们可以使用 0.5 作为概率阈值来确定类别。如果概率大于 0.5,我们将其归类为 Class-1(Y=1) 或者 Class-0(Y=0) 。
在我们建立模型之前,让我们看看逻辑回归的假设
- 因变量必须是分类变量
- 独立变量(特征)必须是独立的(以避免多重共线性)。
资料组
这篇博客中使用的数据取自吴恩达在 Coursera 上的机器学习课程。数据可以从这里下载。数据由 100 名申请者的两次考试成绩组成。目标值采用二进制值 1,0。1 表示申请人被大学录取,而 0 表示申请人没有被录取。目标是建立一个分类器,可以预测申请是否会被大学录取。
让我们使用read_csv
函数将数据加载到pandas
数据帧中。我们还将把数据分成admitted
和non-admitted
来可视化数据。
既然我们对问题和数据有了清晰的理解,让我们继续构建我们的模型。
假设和成本函数
到目前为止,我们已经了解了如何使用逻辑回归将实例分类到不同的类别中。在这一节中,我们将定义假设和成本函数。
线性回归模型可以用下面的等式来表示。
然后,我们将 sigmoid 函数应用于线性回归的输出
其中 sigmoid 函数由下式表示:
逻辑回归的假设就变成了,
如果输入的加权和大于零,则预测类为 1,反之亦然。因此,通过将输入的加权和设置为 0,可以找到分隔两个类的决策边界。
成本函数
像线性回归一样,我们将为我们的模型定义一个成本函数,目标是最小化成本。
单个训练示例的成本函数可以由下式给出:
成本函数直觉
如果实际类是 1,而模型预测是 0,我们应该高度惩罚它,反之亦然。从下图中可以看出,对于图-log(h(x))
来说,当 h(x)接近 1 时,成本为 0,当 h(x)接近 0 时,成本为无穷大(也就是说,我们对模型的惩罚很重)。类似地,对于图-log(1-h(x))
,当实际值为 0 并且模型预测为 0 时,成本为 0,并且随着 h(x)接近 1,成本变得无穷大。
我们可以将这两个方程结合起来使用:
由 J(θ) 表示的所有训练样本的成本可以通过对所有训练样本的成本取平均值来计算
其中 m 为训练样本数。
我们将使用梯度下降来最小化成本函数。任何参数的梯度可由下式给出
该方程类似于我们在线性回归中得到的结果,只有 h(x)在两种情况下是不同的。
训练模型
现在我们已经准备好了构建模型所需的一切。让我们用代码实现它。
让我们首先为我们的模型准备数据。
X = np.c_[np.ones((X.shape[0], 1)), X]
y = y[:, np.newaxis]
theta = np.zeros((X.shape[1], 1))
我们将定义一些用于计算成本的函数。
def sigmoid(x):
# Activation function used to map any real value between 0 and 1
return 1 / (1 + np.exp(-x))
def net_input(theta, x):
# Computes the weighted sum of inputs
return np.dot(x, theta)
def probability(theta, x):
# Returns the probability after passing through sigmoid
return sigmoid(net_input(theta, x))
接下来,我们定义cost
和gradient
函数。
def cost_function(self, theta, x, y):
# Computes the cost function for all the training samples
m = x.shape[0]
total_cost = -(1 / m) * np.sum(
y * np.log(probability(theta, x)) + (1 - y) * np.log(
1 - probability(theta, x)))
return total_cost
def gradient(self, theta, x, y):
# Computes the gradient of the cost function at the point theta
m = x.shape[0]
return (1 / m) * np.dot(x.T, sigmoid(net_input(theta, x)) - y)
让我们也定义一下fit
函数,它将被用来寻找最小化成本函数的模型参数。在这篇博客中,我们编写了梯度下降法来计算模型参数。这里,我们将使用scipy
库中的fmin_tnc
函数。它可以用来计算任何函数的最小值。它将参数视为
- func:最小化的函数
- x0:我们要寻找的参数的初始值
- fprime:由“func”定义的函数的梯度
- args:需要传递给函数的参数。
def fit(self, x, y, theta):opt_weights = fmin_tnc(func=cost_function, x0=theta,
fprime=gradient,args=(x, y.flatten()))
return opt_weights[0]parameters = fit(X, y, theta)
模型参数为[-25.16131856 0.20623159 0.20147149]
为了了解我们的模型表现有多好,我们将绘制决策边界。
绘制决策边界
因为我们的数据集中有两个要素,所以线性方程可以表示为:
如前所述,可以通过将输入的加权和设置为 0 来找到决策边界。使 h(x)等于 0 得到我们,
我们将在用于可视化数据集的图的顶部绘制决策边界。
x_values = [np.min(X[:, 1] - 5), np.max(X[:, 2] + 5)]
y_values = - (parameters[0] + np.dot(parameters[1], x_values)) / parameters[2]
plt.plot(x_values, y_values, label='Decision Boundary')
plt.xlabel('Marks in 1st Exam')
plt.ylabel('Marks in 2nd Exam')
plt.legend()
plt.show()
看起来我们的模型在预测课程方面做得不错。但是有多准确呢?让我们找出答案。
模型的准确性
def predict(self, x):theta = parameters[:, np.newaxis]
return probability(theta, x)def accuracy(self, x, actual_classes, probab_threshold=0.5):
predicted_classes = (predict(x) >=
probab_threshold).astype(int)
predicted_classes = predicted_classes.flatten()
accuracy = np.mean(predicted_classes == actual_classes)
return accuracy * 100accuracy(X, y.flatten())
模型的准确率为 89%。
让我们使用 scikit-learn 实现我们的分类器,并将其与我们从头构建的模型进行比较。
scikit-learn 实现
from sklearn.linear_model import LogisticRegressionfrom sklearn.metrics import accuracy_score model = LogisticRegression()
model.fit(X, y)
predicted_classes = model.predict(X)
accuracy = accuracy_score(y.flatten(),predicted_classes)
parameters = model.coef_
模型参数为[[-2.85831439, 0.05214733, 0.04531467]]
,准确率为 91%。
为什么模型参数与我们从零开始实现的模型有显著差异? 如果你看一下 sk-learn 的逻辑回归实现的文档,它考虑到了正则化。基本上,正则化用于防止模型过度拟合数据。我不会在这篇博客中深入讨论正规化的细节。但是现在,就这样了。感谢阅读!!
这篇博客中使用的完整代码可以在这个 GitHub repo 中找到。
如果你被困在任何地方或有任何反馈,请给我留言。
下一步是什么?
在下一篇博客中,我们将使用在这篇博客中学习到的概念,在来自 UCI 机器学习知识库的成人数据上构建一个分类器。该数据集包含近 49K 个样本,包括分类值、数值值和缺失值。这将是一个值得探索的有趣数据集。
请继续关注这个空间。
在 Python 中逐步构建逻辑回归
原文:https://towardsdatascience.com/building-a-logistic-regression-in-python-step-by-step-becd4d56c9c8?source=collection_archive---------0-----------------------
Photo Credit: Scikit-Learn
逻辑回归 是一种机器学习分类算法,用于预测分类因变量的概率。在逻辑回归中,因变量是一个二元变量,包含编码为 1 的数据(是,成功,等等)。)或 0(否,失败等。).换句话说,逻辑回归模型预测 P(Y=1)是 x 的函数。
逻辑回归假设
- 二元逻辑回归要求因变量是二元的。
- 对于二元回归,因变量的因子水平 1 应该代表期望的结果。
- 应该只包括有意义的变量。
- 自变量应该是相互独立的。也就是说,模型应该很少或没有多重共线性。
- 自变量与对数概率呈线性相关。
- 逻辑回归需要相当大的样本量。
记住上面的假设,让我们看看我们的数据集。
数据
数据集来自 UCI 机器学习库,它与一家葡萄牙银行机构的直接营销活动(电话)有关。分类的目标是预测客户是否会订阅(1/0)定期存款(变量 y)。数据集可以从这里下载。
import pandas as pd
import numpy as np
from sklearn import preprocessing
import matplotlib.pyplot as plt
plt.rc("font", size=14)
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
import seaborn as sns
sns.set(style="white")
sns.set(style="whitegrid", color_codes=True)
数据集提供了银行客户的信息。它包括 41,188 条记录和 21 个字段。
Figure 1
输入变量
- 年龄(数字)
- 工作:工作类型(分类:"行政人员"、"蓝领工人"、"企业家"、"女佣"、"管理人员"、"退休人员"、"自营职业者"、"服务人员"、"学生"、"技术人员"、"失业人员"、"未知人员")
- 婚姻:婚姻状况(分类:“离婚”、“已婚”、“单身”、“未知”)
- 教育(分类:"基础. 4y "、"基础. 6y "、"基础. 9y "、"高中"、"文盲"、"专业.课程"、"大学.学位"、"未知")
- 违约:有信用违约?(分类:“否”、“是”、“未知”)
- 住房:有住房贷款吗?(分类:“否”、“是”、“未知”)
- 贷款:有个人贷款?(分类:“否”、“是”、“未知”)
- 联系人:联系人通信类型(分类:“手机”、“电话”)
- 月份:一年中的最后一个联系月份(分类:“一月”、“二月”、“三月”、“十一月”、“十二月”)
- 星期几:一周的最后一个联系日(分类:“星期一”、“星期二”、“星期三”、“星期四”、“星期五”)
- duration:上次联系持续时间,以秒为单位(数字)。重要注意事项:该属性对输出目标有很大影响(例如,如果 duration=0,则 y='no ')。在执行呼叫之前,持续时间是未知的,同样,在呼叫结束之后,y 显然是已知的。因此,这种输入应该仅用于基准目的,如果目的是得到一个现实的预测模型,则应该丢弃
- 活动:在此活动期间为此客户执行的联系次数(数字,包括最后一次联系)
- pdays:从上一个活动中最后一次联系客户后经过的天数(数字;999 表示之前没有联系过客户)
- 上一次:在此活动之前为此客户执行的联系次数(数字)
- poutcome:先前营销活动的结果(分类:“失败”、“不存在”、“成功”)
- 员工变动率:员工变动率—(数字)
- cons.price.idx:消费者价格指数—(数字)
- 消费者信心指数—(数字)
- euribor 3m:3 个月 euribor 利率—(数字)
- 受雇人数:雇员人数—(数字)
预测变量(期望目标):
y —客户是否认购了定期存款?(二进制:“1”表示“是”,“0”表示“否”)
数据集的教育列有许多类别,为了更好地建模,我们需要减少类别。“教育”栏有以下类别:
Figure 2
让我们把“基本. 4y”、“基本. 9y”、“基本. 6y”组合在一起,称之为“基本”。
data['education']=np.where(data['education'] =='basic.9y', 'Basic', data['education'])
data['education']=np.where(data['education'] =='basic.6y', 'Basic', data['education'])
data['education']=np.where(data['education'] =='basic.4y', 'Basic', data['education'])
分组后,这是列:
Figure 3
数据探索
Figure 4
count_no_sub = len(data[data['y']==0])
count_sub = len(data[data['y']==1])
pct_of_no_sub = count_no_sub/(count_no_sub+count_sub)
print("percentage of no subscription is", pct_of_no_sub*100)
pct_of_sub = count_sub/(count_no_sub+count_sub)
print("percentage of subscription", pct_of_sub*100)
无认购百分比为 88.73288821988
认购百分比 11.265417111780131
我们的类是不平衡的,非订阅实例和订阅实例的比例是 89:11。在我们继续平衡这些类之前,让我们做一些更多的探索。
Figure 5
观察值 :
- 购买定期存款的客户的平均年龄高于没有购买的客户。
- 对于购买该产品的客户来说,pdays(自上次联系客户后的天数)更短是可以理解的。时间越短,对最后一次通话的记忆就越好,因此成交的机会就越大。
- 令人惊讶的是,对于购买定期存款的客户来说,营销活动(在当前营销活动中联系或致电的次数)更少。
我们可以计算其他分类变量(如教育和婚姻状况)的分类平均值,以获得更详细的数据。
Figure 6
Figure 7
形象化
%matplotlib inline
pd.crosstab(data.job,data.y).plot(kind='bar')
plt.title('Purchase Frequency for Job Title')
plt.xlabel('Job')
plt.ylabel('Frequency of Purchase')
plt.savefig('purchase_fre_job')
Figure 8
购买存款的频率在很大程度上取决于职位。因此,职称可以很好地预测结果变量。
table=pd.crosstab(data.marital,data.y)
table.div(table.sum(1).astype(float), axis=0).plot(kind='bar', stacked=True)
plt.title('Stacked Bar Chart of Marital Status vs Purchase')
plt.xlabel('Marital Status')
plt.ylabel('Proportion of Customers')
plt.savefig('mariral_vs_pur_stack')
Figure 9
婚姻状况似乎不是结果变量的强有力的预测因素。
table=pd.crosstab(data.education,data.y)
table.div(table.sum(1).astype(float), axis=0).plot(kind='bar', stacked=True)
plt.title('Stacked Bar Chart of Education vs Purchase')
plt.xlabel('Education')
plt.ylabel('Proportion of Customers')
plt.savefig('edu_vs_pur_stack')
Figure 10
教育似乎是结果变量的一个很好的预测器。
pd.crosstab(data.day_of_week,data.y).plot(kind='bar')
plt.title('Purchase Frequency for Day of Week')
plt.xlabel('Day of Week')
plt.ylabel('Frequency of Purchase')
plt.savefig('pur_dayofweek_bar')
Figure 11
星期几可能不是预测结果的好方法。
pd.crosstab(data.month,data.y).plot(kind='bar')
plt.title('Purchase Frequency for Month')
plt.xlabel('Month')
plt.ylabel('Frequency of Purchase')
plt.savefig('pur_fre_month_bar')
Figure 12
月份可能是结果变量的一个很好的预测因子。
data.age.hist()
plt.title('Histogram of Age')
plt.xlabel('Age')
plt.ylabel('Frequency')
plt.savefig('hist_age')
Figure 13
在这个数据集中,银行的大多数客户年龄在 30-40 岁之间。
pd.crosstab(data.poutcome,data.y).plot(kind='bar')
plt.title('Purchase Frequency for Poutcome')
plt.xlabel('Poutcome')
plt.ylabel('Frequency of Purchase')
plt.savefig('pur_fre_pout_bar')
Figure 14
Poutcome 似乎是一个很好的预测结果变量。
创建虚拟变量
也就是只有两个值的变量,0 和 1。
cat_vars=['job','marital','education','default','housing','loan','contact','month','day_of_week','poutcome']
for var in cat_vars:
cat_list='var'+'_'+var
cat_list = pd.get_dummies(data[var], prefix=var)
data1=data.join(cat_list)
data=data1cat_vars=['job','marital','education','default','housing','loan','contact','month','day_of_week','poutcome']
data_vars=data.columns.values.tolist()
to_keep=[i for i in data_vars if i not in cat_vars]
我们的最终数据列将是:
data_final=data[to_keep]
data_final.columns.values
Figure 15
使用 SMOTE 进行过采样
有了我们创建的训练数据,我将使用 SMOTE 算法(合成少数过采样技术)对非订阅进行上采样。在高水平上,击打:
- 通过从 minor 类(无订阅)创建合成样本而不是创建副本来工作。
- 随机选择 k 个最近邻中的一个,并使用它来创建类似的、但随机调整的新观察值。
我们要用 Python 实现 SMOTE。
X = data_final.loc[:, data_final.columns != 'y']
y = data_final.loc[:, data_final.columns == 'y']from imblearn.over_sampling import SMOTEos = SMOTE(random_state=0)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)
columns = X_train.columnsos_data_X,os_data_y=os.fit_sample(X_train, y_train)
os_data_X = pd.DataFrame(data=os_data_X,columns=columns )
os_data_y= pd.DataFrame(data=os_data_y,columns=['y'])
# we can Check the numbers of our data
print("length of oversampled data is ",len(os_data_X))
print("Number of no subscription in oversampled data",len(os_data_y[os_data_y['y']==0]))
print("Number of subscription",len(os_data_y[os_data_y['y']==1]))
print("Proportion of no subscription data in oversampled data is ",len(os_data_y[os_data_y['y']==0])/len(os_data_X))
print("Proportion of subscription data in oversampled data is ",len(os_data_y[os_data_y['y']==1])/len(os_data_X))
Figure 16
现在我们有了一个完美的平衡数据!您可能已经注意到,我只对训练数据进行了过采样,因为通过只对训练数据进行过采样,测试数据中的任何信息都不会用于创建合成观察,因此,没有任何信息会从测试数据流入模型训练。
递归特征消除
递归特征消除(RFE) 基于重复构建模型并选择最佳或最差性能特征的思想,将该特征放在一边,然后对其余特征重复该过程。此过程将一直应用到数据集中的所有要素都用完为止。RFE 的目标是通过递归地考虑越来越小的特征集来选择特征。
data_final_vars=data_final.columns.values.tolist()
y=['y']
X=[i for i in data_final_vars if i not in y]from sklearn.feature_selection import RFE
from sklearn.linear_model import LogisticRegressionlogreg = LogisticRegression()rfe = RFE(logreg, 20)
rfe = rfe.fit(os_data_X, os_data_y.values.ravel())
print(rfe.support_)
print(rfe.ranking_)
Figure 16
RFE 帮助我们选择了以下特征:“euribor3m”、“job _ 蓝领”、“job _ 女佣”、“婚姻 _ 未知”、“教育 _ 文盲”、“默认 _ 否”、“默认 _ 未知”、“联系人 _ 手机”、“联系人 _ 电话”、“month_apr”、“month_aug”、“month_dec”、“month_jul”、“month_jun”、“month_mar”、“month_may”、“month_nov”、“month_oct”、“poutcome_failure”、“poutcome_success”。
cols=['euribor3m', 'job_blue-collar', 'job_housemaid', 'marital_unknown', 'education_illiterate', 'default_no', 'default_unknown',
'contact_cellular', 'contact_telephone', 'month_apr', 'month_aug', 'month_dec', 'month_jul', 'month_jun', 'month_mar',
'month_may', 'month_nov', 'month_oct', "poutcome_failure", "poutcome_success"]
X=os_data_X[cols]
y=os_data_y['y']
实施模型
import statsmodels.api as sm
logit_model=sm.Logit(y,X)
result=logit_model.fit()
print(result.summary2())
Figure 17
除了四个变量,大多数变量的 p 值都小于 0.05,因此,我们将删除它们。
cols=['euribor3m', 'job_blue-collar', 'job_housemaid', 'marital_unknown', 'education_illiterate',
'month_apr', 'month_aug', 'month_dec', 'month_jul', 'month_jun', 'month_mar',
'month_may', 'month_nov', 'month_oct', "poutcome_failure", "poutcome_success"]
X=os_data_X[cols]
y=os_data_y['y']logit_model=sm.Logit(y,X)
result=logit_model.fit()
print(result.summary2())
Figure 18
逻辑回归模型拟合
from sklearn.linear_model import LogisticRegression
from sklearn import metricsX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)
logreg = LogisticRegression()
logreg.fit(X_train, y_train)
Figure 19
预测测试集结果并计算准确度
y_pred = logreg.predict(X_test)
print('Accuracy of logistic regression classifier on test set: {:.2f}'.format(logreg.score(X_test, y_test)))
逻辑回归分类器在测试集上的准确率:0.74
混淆矩阵
from sklearn.metrics import confusion_matrix
confusion_matrix = confusion_matrix(y_test, y_pred)
print(confusion_matrix)
【6124 1542】
【2505 5170】]
结果告诉我们,我们有 6124+5170 正确的预测和 2505+1542 不正确的预测。
计算精度、召回、F-测量和支持
引用 Scikit Learn 的话:
精度是 tp / (tp + fp)的比值,其中 tp 是真阳性的数量,fp 是假阳性的数量。精确度直观上是分类器在样本为阴性时不将其标记为阳性的能力。
召回率是 tp / (tp + fn)的比值,其中 tp 是真阳性的数量,fn 是假阴性的数量。召回直观上是分类器找到所有肯定样本的能力。
F-beta 分数可以解释为精确度和召回率的加权调和平均值,其中 F-beta 分数在 1 时达到其最佳值,在 0 时达到最差分数。
F-beta 分数通过 beta 因子对召回率的加权大于对精确度的加权。beta = 1.0 意味着召回率和准确率同等重要。
支持度是 y_test 中每个类的出现次数。
from sklearn.metrics import classification_report
print(classification_report(y_test, y_pred))
Figure 20
解读:在整个测试集中,74%的推广定期存款是客户喜欢的定期存款。在整个测试集中,74%的客户首选定期存款得到了推广。
受试者工作特征曲线
from sklearn.metrics import roc_auc_score
from sklearn.metrics import roc_curve
logit_roc_auc = roc_auc_score(y_test, logreg.predict(X_test))
fpr, tpr, thresholds = roc_curve(y_test, logreg.predict_proba(X_test)[:,1])
plt.figure()
plt.plot(fpr, tpr, label='Logistic Regression (area = %0.2f)' % logit_roc_auc)
plt.plot([0, 1], [0, 1],'r--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver operating characteristic')
plt.legend(loc="lower right")
plt.savefig('Log_ROC')
plt.show()
Figure 21
受试者工作特性(ROC) 曲线是二元分类器使用的另一个常用工具。虚线代表纯随机分类器的 ROC 曲线;一个好的分类器尽可能远离那条线(朝向左上角)。
用来写这篇文章的 Jupyter 笔记本可以在这里找到。我将很高兴收到关于上述任何反馈或问题。
参考:使用 Python 书籍学习预测分析
构建具有交互式可视化的 Microsoft Power BI web 应用程序
原文:https://towardsdatascience.com/building-a-microsoft-power-bi-dashboard-with-an-interactive-map-visualization-of-a-dataset-e7edd6386fe2?source=collection_archive---------19-----------------------
我想为初学者提供一个简单、简洁的指南,让他们动手操作 MS Power BI,并使用 Power BI 中的可视化功能执行数据集。这是我今天想到的一个方法,使用简单的工具和方法。
对于 Windows 设备:转到 Microsoft 应用程序商店并获得 Power BI desktop
Power BI desktop from Microsoft Store (Instead of Launch, you should have a Get button)
下载并在您的系统中启动它
您可能会看到此对话框打开。我们需要在这里选择获取数据选项,并导航到下载的数据集。但是在那之前,我们需要下载一个数据集用 Power BI 探索。一旦我们下载了数据集,我们可以回到这一步。
我想在世界卫星数据集上测试。忧思科学家联盟为所有卫星发射提供了一个非常好和干净的所有格式的数据集:excel/csv/text 文件。于是我接着用下面的链接从他们的网站下载了一些数据集(提供了网站截图,以防万一)由此下载 excel 格式的数据库。
[## UCS 卫星数据库
目前围绕地球运行的 1,886 颗卫星的详细信息,包括它们的来源国、用途和…
www.ucsusa.org](https://www.ucsusa.org/nuclear-weapons/space-weapons/satellite-database#.W-DqNpNKiM8)
下载完成后,您可以进入 Power BI 窗口中的获取数据步骤并导航至下载的卫星 excel 数据集。
然后选择同一数据集的工作表 1,并单击 Load。
Windows 完成数据集加载后,您可能会看到以下内容:
所以右边是可视化和字段列。可视化栏有一个图标列表,对应于您可以获得的各种图,而字段栏显示 excel 数据表中的列列表,如发布日期、发布地点、目的、来源等。
为了从这些数据中得出一个简单而有力的故事,我列出了一些相关特征的重要列表,如国家、运载火箭和预期寿命。现在的挑战是选择正确的可视化,然后将这些选定的字段放置在选定的可视化下的相应位置。
因此,从各种基于地图的可视化中,我发现 ArcGIS 地图是展示该数据集的最酷的地图。因此,我们从可视化列中选择 ArcGIS graph 图标。
现在我们必须根据选择的可视化来排列字段。例如,从字段中,选择国家,然后将该特征拖放到可视化栏下的位置空间中。然后从字段列中选择运载火箭字段,并将其拖放到颜色空间中。
然后一旦放下,再次点击运载火箭选项卡并选择计数,这将设置每个国家运载火箭计数总数的使用。
然后,为了显示更多信息,我们可以添加每个国家卫星的平均预期寿命。我们通过从 fields 列中选择Expected Lifetime并将其放到 visualization 下的 Tooltips 空间中来实现这一点。点击预期寿命选项卡,并选择平均值作为与图的其余部分整合的操作值。
因此,在不到 10 分钟的时间里,我们已经将简单的卫星发射 excel 文件演变成了一个在世界地图上讲述的故事,讲述了世界上目前领先的国家作为航天大国的实力。我们可以显示各自国家的运载火箭总数,以及各自卫星在太空中的平均预期寿命。
Satellite launches in world with ArcGIS map visualization and proper Fields selected
最后,你会看到这个美丽的世界地图视图,当你将光标悬停在一个国家时,会弹出额外的信息——给出国家名称、运载火箭总数和预期寿命。虽然颜色的强度给出了该国运载火箭数量的概念,但我们不难想象,毫不奇怪,美国、中国和俄罗斯的卫星发射数量最多。
您可以使用焦点模式查看整个页面中的图表,而不查看任何其他图表:
用户也可以点击右上角,将数据导出为. csv 文件,或者在可视化或地图旁边查看数据[选择右上角更多选项按钮旁边的水平布局视图图标]以查看如下所示的屏幕。
人们可以在地图上摆弄不同的按钮和缩放级别,也许还能得到更吸引人的信息图。
我知道你会用它来创作更有创意和更有趣的东西,所以急切地等待你的惊人回应。
这是可视化的嵌入式代码。点击它打开一个新的网页,与我为卫星数据集创建的可视化交互。
你也可以这样做,进入文件->点击发布到网站->嵌入代码到你的博客或 html 网站
以下是基于我的报告中选择的图表和字段的数据集的网站可视化,当我在我的 Power BI 应用程序 dasahboard 上更改它们时,它也会实时更改。
**[## 电源 BI 报告
由 Power BI 支持的报告
app.powerbi.com](https://app.powerbi.com/view?r=eyJrIjoiYmJhYmM0ODItZWFjMC00ZGFjLWJjNGQtZDNjNjc1MGU4NWVkIiwidCI6IjlmZWE3NjAwLWE0YWYtNGZlZC05NTZlLTYxODk0ZjY0MWE3MCIsImMiOjN9)**
要了解更多关于商业智能/深度学习/机器学习的最新作品和教程,请访问:
** [## 最热门的资源
这里有一些最好的人工智能或深度学习或数据科学链接和资源可以免费获得…
rajshekharmukherjee.wordpress.com](https://rajshekharmukherjee.wordpress.com/hottest-resources/)
干杯!**
在纽约出租车数据上建立一个机器学习集成分类器,用 Python 和 Google BigQuery 预测没有小费和慷慨的小费
原文:https://towardsdatascience.com/building-a-ml-classifier-on-ny-city-taxi-data-to-predict-no-tips-vs-generous-tips-with-python-92e21d5d9fd0?source=collection_archive---------3-----------------------
我通过构建一个分类器来展示 Google BigQuery 引擎的强大功能,该分类器将预测乘坐纽约市的出租车是会得到丰厚的小费还是根本没有小费。作为这项工作的一部分,我探索数据集并查看数据集中的关系。我还想象了城市周围的拾音器,结果是一个散点图,基本上画出了纽约的街道。
我主要介绍了 BigQuery UI、python API 和 pandas 库,这些库与直接从 Jupiter notebook 和 sklearn 执行 SQL 查询相关。我描述了在 BigQuery 中克服的挑战,包括通过 API 和 UI 执行的查询之间的一些语法差异。很多在线文档都过时了,因此我的示例代码应该是执行自己项目的有用资源。
最后,对于那些对构建分类器和元分类器感兴趣的人来说,我使用 simple 来理解标签和输入,这对那些希望实现自己的分类器的人来说应该是一个有用的参考。我还演示了如何处理缺失值。
big query 背景
BigQuery 是 Google 内部使用的查询服务 Dremel 的公共实现。
Dremel 可以在几十秒内扫描 350 亿行而不用索引。云驱动的大规模并行查询服务 Dremel 共享谷歌的基础设施,因此它可以并行化每个查询,并在数万台服务器上同时运行。
使用 BigQuery 的第一步是授权一个 google cloud 帐户。这是通过访问 https://console.cloud.google.com并遵循授权协议来完成的。您还需要提供一张信用卡来支付账单。注册开始时,您将获得价值 300 美元的积分,这对于探索和运行示例查询来说绰绰有余。
然后,您将登录到 google cloud dashboard,下一步是创建一个项目(您可以有多个项目)。
然后,您可以通过单击左侧的菜单并选择“bigquery”来访问 BigQuery
这将加载 BigQuery WebUI
我们看到有 130GB 关于纽约出租车旅行的数据和 11 亿行。BigQuery 处理所有这些数据大约只需要 30 秒。
我首先导入 pandas,因为 pandas 中有一个专门设计的方法来查询 bigquery,并以 pandas dataframe 的形式返回结果。
我还导入 matplotlib 进行可视化。
我使用的数据已经存储在谷歌云中,所有人都可以使用——我使用它是为了演示,因为任何人都可以访问它并运行查询。
作为对数据的初步演示和探索,我展示了通过将 SQL 代码直接传递给 pandas 方法进行查询的能力,方法是按月查看数据中的出租车出行次数。
然后,我研究了这些数据,并分析了小费和不同特征之间的关系。
然后,我汇总了纽约每个经度和纬度坐标上的皮卡数量
然后,我能够将这些数据输入散点图,根据出租车搭载乘客的地点,得出纽约相当清晰的轮廓。
根据我对数据的研究,我发现只有 3%的用信用卡支付的旅行没有小费,所以我决定为了分类的目的,我们将尝试并预测两种极端情况,这两种情况需要人们在纽约出租车上手动取消——没有小费和非常慷慨的小费(“慷慨”是指超过车费的 30%)
然后,我着手提取相关信息,并给它们贴上标签。
我首先创建两个独立的数据集,在每个数据集上做标记,然后将它们合并。
我平衡数据,所以一半的数据将是慷慨的,另一半没有提示,所以我的分类器只需要做得比 50%更好就可以被认为是有用的。
现在已经得到了我的标签(Y)和特征(X),我建立分类器。我使用 sklearns 分类器 KNN,贝叶斯,逻辑回归和决策树,并使用它们的输出来输入一个集成或“元分类器”,然后给出结果。
当我们运行培训和测试时,我们会看到以下结果:
准确度:0.67(+/-0.12)[decision tree classifier]
准确度:0.91(+/-0.14)【LogReg】
准确度:0.77(+/-0.10)【KNN】
准确度:0.67(+/-0.01)【NB】
准确度:0.83 (+/- 0.12)【系综】
结论:
鉴于上述结果,我已经能够成功地建立一个元分类器,它将预测哪里的旅行更有可能导致司机没有小费或“慷慨”的小费。
诸如此类的分类器可能有助于捕捉欺诈。例如,该数据仅使用信用卡交易,因为所有小费信息都被捕获,但当使用现金时,由于税务后果,司机可能不会报告小费-像所构建的分类器这样的分类器可用于了解我们何时应该看到小费被记录,或不被记录,并识别异常。
github Repo:https://github . com/cjflanagan/ny taxi _ Tips _ Classifier _ with _ big query-/blob/master/ny taxi . ipynb
构建分子电荷分类器
原文:https://towardsdatascience.com/building-a-molecular-charge-classifier-50204deebd6d?source=collection_archive---------9-----------------------
化学和人工智能的交集
A.在过去的几年里,我看到了前所未有的增长。尽管像神经网络(NN)这样的机器学习架构由于 Geoffrey Hinton 这样的顶级研究人员的突破而闻名已久,但直到最近神经网络才成为人工智能专家工具箱中的强大工具。这主要归功于 21 世纪的到来带来的三个变化:
- 增强的计算能力
- 增加可用数据
- 对自动化越来越感兴趣
目前在互联网、政府系统和个人电脑上流动的大多数数据都是未标记的。**标记数据(即对应于另一个现有数据集的数据)更难获得。**数据类型包括数字、图像、音频和文本。
Code, Math, and Molecules; the trinity of difficult things to use in A.I
要克服的巨大挑战是离散分子数据是多么脆弱。
考虑一下这个:
- 在数学方程式中,如果一个数字或运算被改变,则该方程式无效。
- 在代码块中,如果任何变量、方法、函数等。被更改,代码将以不同的方式执行。
- 在一个分子中,如果一个键、原子或电子被改变,这个分子就完全不同了。
神经网络有一个非常独特的过程,使它们不同于其他算法。输入的数据必然会在神经网络中被处理,也就是说,它会受到权重、偏差、激活函数以及一系列其他可调、可学习和特定参数的影响;
进入神经网络的数据将被改变。
**操纵脆弱的离散数据如履薄冰。**目前,有 4 种主要的方法来表示一种分子,按照损失的顺序列出:
- 分子指纹
- 字符串表示
- 分子图
- 模拟
每一种都有自己独特的过程,但我用来构建分子电荷分类器的是字符串表示和分子指纹。大多数化学信息数据和分子数据都是以 InChi 字符串的形式提供的,或者我更喜欢的格式,SMILES 字符串。大多数时候,微笑字符串看起来像一种化学胡言乱语:
Molecules with their respective SMILE strings
这些字符串是在语法的帮助下生成的。和英语一样,单个分子可以有不同的微笑串;就像一个词可以有很多定义,或者一个想法可以用不同的句子来表达。
The many faces of Toluene; all the strings represent the same molecule
图表由 Esben Bjerrum 博士提供,他是用人工智能征服化学之旅的领先专家和研究人员。要了解更多关于 canonical SMILES 枚举的信息,请查看他的博客帖子。
为了防止重复的微笑串,每个分子仅使用一个微笑串变体。值得注意的是,每个分子都有一个初级字符串表示,也称为规范微笑。有了 SMILES 格式的干净的标记分子数据集,我开始构建分子电荷分类器。
项目收费
我用微笑字符串和神经网络用 python 和 Keras 库构建了一个分子电荷分类器。每个分子都有特定的电荷 0、1、-1 和-2(还有更多,但我的数据集中的所有分子都有 4 种可能的电荷)。
该项目分为 4 个步骤:
- 导入 SMILES 数据(带标签,即费用)
- 将数据转换为 256 位二进制代码
- 构建深层神经网络
- 编译和拟合模型
对于这个项目,该模型用 250,000 个数据集的 1000 个微笑字符串进行训练。我将每个微笑字符串转换成 256 位二进制代码,这样我就可以用相同数量的输入神经元构建神经网络;256.该模型将每个前进层的神经元数量减半,从 256 → 128 → 64 → 34 → 16,最后到 4 个输出神经元,每个神经元对应数据集中的一个可能电荷(0,1,-1,-2)。
从训练集中抽取 10%的数据(100 个微笑字符串)用作验证数据。该模型使用 relu 作为其输入层激活函数,使用 sigmoid 作为隐藏层的激活函数,最后使用 softmax 函数以 0 到 1 之间的概率形式输出结果。因此,分类以概率小数的形式呈现,由神经网络根据其训练计算。
该模型用 10 个新分子进行了测试,并成功预测了所有 10 个分子的电荷,其中一些产生了较高的可能性百分比(80%),而另一些产生了较低的可能性百分比(40%)
Charged 项目的所有代码和数据集都可以在我的 Github 上找到,在这个库里。
化学数据面临的挑战是找到代表你正在研究的分子的方法。理想的表示考虑到了分子数据的脆弱性,同时仍然保持固有的特征和模式完整无缺。这种表示应该在准确性和计算效率之间取得适当的平衡。
关键要点
- 像代码和数学一样,分子在被操纵时容易变得脆弱
- 用计算术语表示分子有 4 种方法;指纹、字符串表示、分子图或模拟
- SMILES 是一种流行的字符串表示;一个分子可以有许多串,但只有一个规范的微笑
- 将一个分子转换成二进制指纹,并将它们输入到神经网络中,这是在化学中利用人工智能的一种方法
- 分子表示和化学信息学作为一个整体,是准确性和计算能力的平衡
还在看这个?想要更多吗?不确定下一步该做什么?
- 分享到 LinkedIn 、脸书,或者 Twitter !(顺便加我)
- 查看我的作品集了解更多酷项目、内容和更新!
- 在任何平台上寻求问题、合作和想法!
向前!
在 MATLAB 中建立 NARX 来预测时间序列数据。
原文:https://towardsdatascience.com/building-a-narx-in-matlab-to-forecast-time-series-data-f60561864874?source=collection_archive---------2-----------------------
The Kenduskeag at high flows. At lower flows (you can literally walk out to that rock in the middle).
去年我发表了一篇文章(在 PaddleSoft 账号上),在文章中我描述了使用 MATLAB 中内置的 NARX 预测 Kenduskeag 流的流量。然而,我故意没有包括那么多技术细节,因为我试图为普通读者写。好了,我现在已经创建了一个完整的教程,关于如何在 MATLAB 中建立一个带有外源输入的非线性自回归网络(NARX)来预测时间序列数据。
教程
这个过程实际上相当简单:导入数据,创建模型,训练模型,然后进行预测。
这个 CSV 是我们将在教程中使用的 CSV 类型的一个例子。基本上有三列:高度、温度和降雨量。我们希望使用先前的高度以及温度和降雨量来预测当前的高度。
- 导入数据
首先,我们必须导入数据。我们将使用一个简单的函数来实现:
我们用[X_input,height]=load_data('height.csv')
调用这个函数(注意,即使我们使用 xlsread,它仍然可以处理 CSV 文件)。
2。培训
现在让我们看看我们的培训代码:
让我们稍微分解一下这段代码。我们要做的第一件事是使用 tonndata 函数将我们的输入放入单元格数组。接下来,我们必须选择我们的训练函数。我个人在贝叶斯正则化(即 trainbr)方面取得了最大的成功,但是,这可能需要更长的时间。之后,p reparets 将为我们的 NARX (24)准备正确格式的数据。
输入延迟和反馈延迟参数非常重要,将极大地影响您的预测。我最初选择的方法是绘制降雨量与高度变化的曲线图,以确定降雨量何时对河流高度影响最大。然后我试验了各种配置。也有更多的数学方法来确定它使用互相关(见 MATLAB 论坛回答这里)。然而,现在,你可以试着看看什么是最好的。
然后,我们在第 28–30 行做出相当标准的决策,如训练/验证/测试分割,最后训练网络(第 30 行)。代码的其余部分是可选的,所以我不会详细介绍。但是,请随意尝试,了解一下有哪些可用的东西。
3。做出预测
现在,为了在 CSV 上进行预测,我们将使用新创建的 height_net。我个人发现最简单的方法是将测试数据分成两个 CSV:一个包含 stamps 0:length-240 的输入(temp 和 rain)和高度值,另一个只包含 length-240:length 的输入(其中 length 是测试 CSV 中的行数)。这大致类似于 10 天天气预报的预测(即使用一个已知的长时间序列,然后预测从天气 API 获得的 1024 个时间戳)。你可以很容易地在你的 MATLAB 代码中分割数据,但是我发现这样做最简单。考虑到这一点,下面是我们的预测代码:
我们将已知的时间戳序列传入 open height net,得到xf
和af
。然后我们关闭网络进行多重预测(12)。最后,我们进行实际预测(13)。你现在可以通过看 y2 或者我们重新分配的 unknownY 来看预测。
我希望这个例子足以让你熟悉 MATLAB 中的 NARX(s)。在未来,我希望更深入地研究 NARXs 相对于 LSTMs 等其他 rnn 的优势。
你可以关注我,也可以查看我写的更多内容。
构建自然语言课程
原文:https://towardsdatascience.com/building-a-natural-language-lesson-8cc01011a4c5?source=collection_archive---------16-----------------------
我是一名软件工程师,在应用创新团队的 Kainos 工作,我们与客户一起使用和开发超越眼前视野的工具,以发现他们的商业价值。这包括研究新兴技术,如人工智能及其应用。
问题是
我们经常会发现自己的文本数据集从一开始就没有足够的数据,没有足够的变化,或者很可能有偏差。为了让我们的机器学习模型有效地提供准确的预测,需要大量的数据。对于图像,没有足够数据的解决方案是增加数据集(我将在后面展示一个例子),从而在不增加方差的情况下创建我们正在寻找的额外数据量。
如果我的任务是对狗和猫进行分类,而我只有一只猫和 9 只狗来训练我的模型,那么这个模型就不擅长寻找猫。
所以……(鼓声 please)🥁
我们如何为我们的文本数据集做到这一点?
有没有一种方法可以自动化增加数据集大小的过程,这些数据集的数据足够多样,可以进行良好的训练?
基础
我的研究让我寻找可以在不损失质量或上下文的情况下扩展这些数据集的方法。我看了问题和答案的结构,因为那是我正在处理的数据;有趣的是,我们与技术互动的最常见方式基本上是通过提问和回答。因此,随着对机器学习的兴趣和发展,我们如何使用这项技术来使这些交互更加流畅?
Airbnb chatbot which organises accomodation for you via a natural conversation
我相信每个人都知道我们可以有许多不同的方式来“问或回答一个问题”;问自己这个问题让我开始关注一些技术,比如文本生成、文本预测、文本变形以及最后的文本增强。
An example of how essentially the same answer can have multiple questions
这项研究
文本生成
T ext generation 或自然语言生成(NLG) 是机器学习的一种应用,将在未来几年在商业中大量出现。
高德纳公司对 NLG 做了如下预测:
“到 2018 年,20%的商业内容将由机器创作”
“到 2019 年,自然语言生成将成为 90%的现代商业智能和分析平台的标准功能。”
“到 2020 年,前 20 大网络内容管理(WCM)供应商将提供自然语言生成功能,作为其整体产品的一部分。”
自然语言是一个非常复杂的话题,我们已经到了机器能够理解句子结构、提取关键词或短语、总结文本和将一种语言高精度地翻译成另一种语言的阶段。机器学习使 NLG 成为可能(看看谷歌双工),它需要数据来学习;这里的问题是,我一开始没有多少数据,所以它违背了目的。任何模型都无法概括和产生我所寻找的问题的变体。
对于那些想了解模型一般化的人来说,我说的是训练模型的目的,这样它就能够理想地应对训练范围内的任何场景。在这种情况下,由于我要处理的数据量很小,这个模型不可能是一般化的,反而会过度拟合。
文本预测
由于 NLG 不适合我的需要,我简要研究了文本预测;这实质上提供了所谓的“种子文本”,并且该模型将预测下一组单词是什么。然而,这种技术和 NLG 遇到了同样的问题,它需要大量的数据;我看到的问题。
文本变形
接下来,我发现了一篇有趣的研究论文,题目是“从连续空间生成句子”。这是我所能找到的文本变形的唯一证据,它在将两个不同的句子变形到一起后产生了新的句子。
不幸的是,我无法测试这个方法,我的时间是有限的,我在寻找能够让我这样做的工具;我不能花那么多时间重现一篇研究论文的结果。将来,我想测试文本变形,看看它是否可以单独扩展数据集,或者与另一种方法相结合。
Example taken from the “Generating Sentences from a Continuous Space” paper
文本增补
在我的研究进行到一半时,我开始质疑是否值得研究与图像增强的常见实践更密切相关的技术。图像增强是一种扩大数据集中图像数量的技术,同时增加这些图像的变化,这将有助于我们概括我们的模型,并扩大数据暴露,以说明现实世界的细节。方法可以包括旋转、水平或垂直翻转以及缩放。虽然这些方法不能准确地翻译成文本,但它仍然是值得考虑的事情,以前我只关注涉及机器学习的方法。
An example of image augmenation using Keras
为了生成更多的文本,我测试了两种扩充文本的方法,同时努力保持数据集的高质量标准。
同义词替换
首先,我试图提取关键字,然后用它们的同义词替换它们,换句话说(没有双关语的意思),用同义词词典中找到的对应词替换单词。最初我只是用同义词替换名词,还没有测试过用同义词替换英语演讲的其他部分。从结果中可以立即看出,这种方法在增加数据集的规模方面是有效的,即使它无法找到某些句子的同义词。
尽管如此,像“我们”这样的词被提取出来,然后断章取义,因为机器不理解问题的意图,这是有问题的。它取了“我们”,换成了“美国”、“美国”等。用这些替换生成新问题意味着新问题没有意义,特别是对于以前没有见过原始问题的人来说。
您可以通过定义单词集合(语料库)来解决这个问题。语料库将类似于您不想找到同义词并替换的内容。我还建议你在进入替换阶段之前,尝试一下关键词提取的替代方法。对于这项研究,我使用了 Rake 库来提取关键词,甚至可以尝试不同的库。
语言翻译
第二种增强方法更像是一场赌博,从英语翻译成外语再翻译回英语。我在 fast.ai 论坛上看到过这种技术被用于 Kaggle 竞赛“有毒评论分类”。令人惊讶的是,这种方法非常有效,特别是对于离家更远的语言,如日语和阿拉伯语。我相信由于句子结构和单个单词意思的不同,这些语言工作得很好,这意味着它们翻译的句子与原始句子略有不同。我最后使用的语言是日语、乌克兰语、塞尔维亚语、阿拉伯语和保加利亚语。使用 Azure 的翻译服务,我随机选择了 500 个问题,并且能够产生 5 倍的数量,因为我只使用了 5 种语言。将来,我想增加翻译的问题数量,看看它对基准测试有多大影响。
下面是我的一些结果,危险数据集的一个子集被用作基准数据,在使用各种方法后,逻辑回归模型在总体上进行训练。
Table describing the results from each mehod
在表格中,我标记了开始时的原始数据量、使用左侧的标记方法生成的生成量以及两者的总和。第四行以“Translated → Augmented”开始,显示了将扩充(同义词替换)和翻译结合起来的结果。所有这些都给出了有价值的结果,并显示了应用每种方法的好处。值得在其他数据集上进一步测试这一点,并可能将其实现到聊天机器人中,看看问答系统是否可以处理更多不同的问题。
结论
通过进行这项研究,我意识到这是一个困难的问题,可以通过各种方法或方法的组合来解决,我很有兴趣看到机器学习的这个小而重要的领域如何扩展。
最近,在自然语言处理(NLP)方面取得了一些进展,这可能有助于这一领域,如 DecaNLP、transformer 模型以及最近谷歌对“强化学习的主动问题重构”的研究。如果你对自然语言和机器学习感兴趣,所有这些都值得一看。
联系✉️
如果您有兴趣了解更多我们在应用创新团队的工作,请随时联系我们 appliedinnovation@kainos.com 公司。
Github//@ jakeyoung 2410
在 Tensorflow 中构建下一个单词预测器
原文:https://towardsdatascience.com/building-a-next-word-predictor-in-tensorflow-e7e681d4f03f?source=collection_archive---------2-----------------------
ByPriya DWI vedi,数据科学家@ SpringML
下一个单词预测或者也称为语言建模是预测下一个单词是什么的任务。它是自然语言处理的基本任务之一,有许多应用。当你写短信或电子邮件时,你可能每天都在使用它而没有意识到这一点。
我最近在 Tensorflow 上建立了一个下一个单词预测器,在这篇博客中,我想介绍我遵循的步骤,这样你就可以复制它们并建立你自己的单词预测器。
- 数据下载和预处理
我使用了从 2006 年 3 月的英语维基百科转储的数据集。该数据集非常庞大,总共有 16 毫米的单词。为了测试和建立单词预测模型,我随机抽取了一个数据子集,总共有 0.5 毫米的单词,其中 26k 是唯一的单词。正如我将在后面解释的那样,随着唯一单词数量的增加,你的模型的复杂性也会增加很多。
2。生成单词向量
在 NLP 中,首要任务之一是用单词向量替换每个单词,因为这能够更好地表示单词的含义。如需了解更多关于词向量以及它们如何捕捉语义的信息,请点击这里查看博文。
对于这个模型,我用 Glove Vectors 初始化这个模型,本质上是用一个 100 维的单词向量替换每个单词。
3。模型架构
对于此任务,我们使用 RNN,因为我们希望通过查看每个单词之前的单词来预测每个单词,并且 rnn 能够保持隐藏状态,该隐藏状态可以将信息从一个时间步转移到下一个时间步。RNN 的工作原理见下图:
RNN visualization from CS 224N
一个简单的 RNN 有一个权重矩阵 Wh 和一个在每个时间步共享的嵌入到隐藏矩阵 We。每个隐藏状态的计算方法如下
并且任何时间步长的输出取决于隐藏状态
因此,使用这种架构,RNN 能够“理论上”使用过去的信息来预测未来。然而,普通的 rnn 受到消失和爆炸梯度问题的困扰,因此它们很少被实际使用。对于这个问题,我使用了 LSTM ,它使用门及时流回梯度,并减少消失梯度问题。
我在 Tensorflow 中设置了一个多层 LSTM,每层 512 个单位,2 个 LSTM 层。LSTM 的输入是最后 5 个单词,LSTM 的目标是下一个单词。
模型中的最后一层是 softmax 层,它预测每个单词的可能性。正如我之前提到的,我的模型有大约 26k 个唯一的单词,所以这一层是一个有 26k 个唯一类的分类器!这是模型中计算量最大的部分,也是单词语言建模中的一个基本挑战。
4。模型训练和输出
我用的损失函数是 sequence_loss 。该模型被训练了 120 个时期。我观察了训练损失和训练困惑来衡量训练的进展。困惑是用来衡量语言模型性能的典型指标。困惑度是由字数标准化的测试集的逆概率。困惑度越低,模型越好。在训练了 120 个时期后,该模型达到了 35 的困惑度。
我根据一些样本建议测试了这个模型。该模型输出前 3 个最高概率的单词供用户选择。见下面截图。考虑到该模型是在仅有 26k 个单词的有限词汇量上进行训练的,因此它工作得相当好
Trained model output
后续步骤
- 探索允许在更大词汇量上进行培训的替代模型体系结构。你可以在论文中看到这些策略——https://arxiv.org/abs/1512.04906
- 将模型更好地推广到新的词汇或罕见的单词,如不常见的名称。最近的一个发展是使用指针哨兵混合模型来做这个——见论文https://arxiv.org/abs/1609.07843
SpringML 是谷歌云平台的主要合作伙伴,专注于机器学习和大数据分析。我们已经在多家财富 500 强企业中实施了预测和分析解决方案。请联系了解更多:info@springml.comwww.springml.com
从头开始构建问答系统—第 1 部分
原文:https://towardsdatascience.com/building-a-question-answering-system-part-1-9388aadff507?source=collection_archive---------0-----------------------
系列文章的第一部分着重于脸书嵌入句
随着我的硕士学位即将结束,我想从事一个有趣的 NLP 项目,在那里我可以使用我在 USF 学到的所有技术(不完全是)。在我的教授的帮助下,通过与同学们的讨论,我决定从头开始建立一个问答模型。我使用的是斯坦福问答数据集(SQuAD) 。这个问题非常有名,所有的大公司都试图在排行榜上跳起来,并使用先进的技术,如基于注意力的 RNN 模型,以获得最佳的准确性。我发现的其他人做的与 SQuAD 相关的所有 GitHub 库也都使用了 RNNs。
然而,我的目标并不是达到最先进的准确性,而是学习不同的 NLP 概念,实现它们并探索更多的解决方案。我一直相信从基本模型开始了解基线,这也是我的方法。这一部分将重点介绍脸书语句嵌入以及如何将其用于构建问答系统。在未来的部分,我们将尝试实现深度学习技术,特别是针对这个问题的序列建模。所有代码都可以在这个 Github 库上找到。
但是我们先来了解一下问题。我先简单概述一下,不过,对问题的详细了解可以在这里找到。
小队数据集
SStanfordQuestionAnsweringDataset(SQuAD)是一个新的阅读理解数据集,由一组维基百科文章上的众包工作者提出的问题组成,其中每个问题的答案都是相应阅读文章中的一段文字,或 span 。SQuAD 拥有 500+篇文章上的 100,000+问答对,比以前的阅读理解数据集大得多。
问题
对于训练集中的每个观察,我们都有一个**上下文、问题和文本。**这样一个观察的例子——
目标是为任何新问题和提供的上下文找到文本。这是一个封闭的数据集,意味着问题的答案总是上下文的一部分,也是上下文的一个连续跨度。我现在把这个问题分成两部分-
- 获得有正确答案的句子(突出显示黄色)
- 一旦句子最终确定,从句子中获得正确答案(突出显示为绿色)
引入阴差阳错,脸书句嵌入
这些天我们有各种类型的嵌入 word2vec 、 doc2vec 、 food2vec 、 node2vec ,那么为什么没有 sentence2vec 呢?所有这些嵌入背后的基本思想是使用各种维度的向量来用数字表示实体,这使得计算机更容易理解它们以用于各种下游任务。解释这些概念的文章被链接以便你理解。
传统上,我们习惯于平均一个句子中所有单词的向量,称为单词袋方法。每个句子被标记为单词,这些单词的向量可以使用手套嵌入来找到,然后取所有这些向量的平均值。这种技术表现不错,但是这不是一种非常准确的方法,因为它没有考虑单词的顺序。
下面是 推断 ,它是一个句子嵌入方法,提供语义句子表示。它在自然语言推理数据上进行训练,并很好地推广到许多不同的任务。
这个过程是这样的-
从训练数据创建词汇表,并使用该词汇表训练推理模型。一旦模型被训练,提供句子作为编码器函数的输入,该函数将返回 4096 维向量,而不管句子中的单词数。[ 演示
这些嵌入可以用于各种下游任务,如寻找两个句子之间的相似性。我已经为 Quora-问题对 kaggle 竞赛实现了同样的功能。你可以点击查看。
说到团队问题,下面是我尝试使用句子嵌入来解决前一部分问题的第一部分的方法
- 将段落/上下文分成多个句子。我知道的处理文本数据的两个包是-Spacy&text blob。我也使用了包 TextBlob。它进行智能拆分,不像 spacy 的句子检测可以根据周期给你随机的句子。下面提供了一个例子:
Example: Paragraph
TextBlob is splitting it into 7 sentences which makes sense
Spacy is splitting it into 12 sentences
- 使用推理模型获得每个句子和问题的向量表示
- 根据每个句子-问题对的余弦相似度和欧几里德距离,创建距离等特征
模型
我用两种主要方法进一步解决了这个问题-
- 不使用目标变量的无监督学习。这里,我从与给定问题距离最小的段落中返回句子
- 监督学习-训练集的创建对于这一部分来说非常棘手,原因是每个部分没有固定数量的句子,答案可以从一个单词到多个单词不等。我能找到的唯一一篇实现了逻辑回归的论文是由发起这个竞赛&数据集的斯坦福团队发表的。他们使用了这篇论文中解释的多项式逻辑回归,并创建了1.8 亿个特征(该模型的句子检测准确率为 79%) ,但不清楚他们是如何定义目标变量的。如果任何人有任何想法,请在评论中澄清。稍后我会解释我的解决方案。
无监督学习模型
在这里,我首先尝试使用欧几里德距离来检测与问题距离最小的句子。这个模型的精确度大约为 45%。然后,我切换到余弦相似度,准确率从 45%提高到 63% 。这是有意义的,因为欧几里德距离不关心向量之间的对齐或角度,而余弦则负责这一点。在矢量表示的情况下,方向很重要。
但是这种方法没有利用提供给我们的带有目标标签的丰富数据。然而,考虑到解决方案的简单性质,这仍然是一个没有任何培训的好结果。我认为体面的表现归功于脸书句子嵌入。
监督学习模型
这里,我已经将目标变量从文本转换为包含该文本的句子索引。为了简单起见,我把我的段落长度限制在 10 句以内(大约 98%的段落只有 10 句或更少)。因此,在这个问题中,我有 10 个标签要预测。
对于每个句子,我都建立了一个基于余弦距离的特征。如果一个段落的句子数量较少,那么我将把它的特征值替换为 1(最大可能余弦距离),这样总共有 10 个句子。用一个例子来解释这个过程会比较容易。
我们来看看训练集的第一个观察/行。有答案的句子在上下文中被加粗。:
问题——“1858 年在法国卢尔德,圣母玛利亚据说是向谁显现的?”
背景——“从建筑上来说,这所学校具有天主教的特征。在主楼的金色圆顶上是一座金色的圣母玛利亚雕像。在主建筑的正前方,正对着它的是一尊铜制的基督雕像,双臂高举,上面写着“Venite Ad Me Omnes”的字样。主楼旁边是圣心大教堂。长方形会堂的后面是一个洞穴,一个祈祷和沉思的地方。这是一个法国卢尔德石窟的复制品,据说圣母玛利亚于 1858 年在这里出现在圣贝尔纳黛特·索比罗斯面前。在主车道的尽头(在一条直线上,连接着三座雕像和金色穹顶),是一座简单、现代的玛丽石像。
正文——《圣贝尔纳黛特·索比罗斯》
在这种情况下,目标变量将变成 5,因为这是粗体句子的索引。我们将有 10 个特征,每个特征对应于段落中的一个句子。column_cos_7、column_cos_8 和 column_cos_9 的缺失值用 1 填充,因为这些句子在段落中不存在
依赖解析 我为这个问题使用的另一个特性是**“依赖解析树”**。这将模型的精确度略微提高了 5%。这里,我使用了空间树解析,因为它有丰富的 API 来导航树。
For more details: Please check out Stanford Lecture
单词之间的关系在句子上方用有向的、有标记的弧线从首字母到从属字母来表示。我们称之为类型依赖结构,因为标签是从固定的语法关系清单中提取的。它还包括一个根节点,该节点显式地标记了树的根,即整个结构的头部。
让我们使用空间树解析来可视化我们的数据。我使用的是上一节中提供的同一个例子。
**问题—“**1858 年在法国卢尔德,圣母玛利亚据称是向谁显现的?”
有答案的句子— “这是一个法国卢尔德石窟的复制品,据说圣母玛利亚于 1858 年在那里出现在圣贝尔纳黛特·索比罗斯面前”
段落中所有句子的词根
想法是将问题的词根匹配到句子的所有词根/子词根。由于一个句子中有多个动词,所以我们可以得到多个词根。如果问题的词根包含在句子的词根中,那么这个问题被那个句子回答的可能性就更大。考虑到这一点,我为每个值为 1 或 0 的句子创建了一个特征。这里,1 表示问句的词根包含在句根中,否则为 0。
注意:在比较句子的词根和问题词根之前,做词干分析是很重要的。在前面的例子中,问句的词根是出现,而句子中的词根是出现。如果不把出现的 & 出现的归结为一个共同术语,它们就不可能匹配。
下面的示例是转置的数据,带有来自已处理训练数据的 2 个观察值。因此,对于段落中的 10 个句子,结合余弦距离和根匹配,我们总共有 20 个特征。目标变量的范围从 0 到 9。
注意:对于逻辑回归,标准化数据中的所有列是非常重要的。
一旦创建了训练数据,我就使用了多项式逻辑回归、随机森林&梯度推进技术。
多项逻辑回归对验证集的准确率为 65% 。考虑到原始模型有很多特征,准确率为 79% ,这个模型非常简单。随机森林给出了 67% 的准确率,最后 XGBoost 在验证集上表现最好,准确率为 69% 。
我将增加更多的功能(NLP 相关)来改善这些模型。
非常欢迎与功能工程或其他改进相关的想法。这里提供了与上述概念相关的所有代码。
在下一部分中,我们将重点关注从这一部分中入围的句子中提取文本(正确跨度)。同时,看看我的其他博客这里!
关于我:https://alviraswalin.wixsite.com/alvira。有兴趣与跨职能部门合作,从数据中获得见解,并应用机器学习知识来解决复杂的数据科学问题。
领英:www.linkedin.com/in/alvira-swalin
参考
- 带有代码的 Github 库
- 脸书回购延期
- 解释逻辑回归的最佳资源论文
- 博客解释问题
- 排行榜&数据集
YOLO 的首个实时联邦快递/UPS/USPS 检测系统
原文:https://towardsdatascience.com/building-a-real-time-fedex-ups-usps-detection-system-with-yolo-1cc72382088a?source=collection_archive---------13-----------------------
您再也不会错过您的包裹了!
在这篇文章中,我将与你分享用 Yolo 建立一个实时物体检测系统来检测 FedEx/UPS/USPS 送货卡车的步骤。这是两部分项目的第一部分:
a.第 1 部分(本文):动机,Yolo 的快速介绍,以及如何训练和测试模型。
b.第二部分(即将推出):通过 Yolo 的 Darkflow 实现,连接 Raspberry Pi 和网络摄像头/摄像机进行真实生活检测。
你可以在我的 GitHub 回购这里找到代码,或者在我室友的 GitHub,Mladen 上找到代码,在这里。
Another attempt will be made!
动机
“再来一次尝试。”对于需要签名的包裹,您经常会收到这样一份丢失的送货单。只剩下最后一次尝试了,所以你决定改变你的计划,第二天呆在家里。然而,你的公寓在大楼的后面,无论你在订购产品时提供了多么详细的说明,大多数情况下,送货人只会试图在前门或中门送货,而不会在你的后门送货。你对此感到厌倦,所以下次你主动打电话给快递公司,要求将你的包裹放在他们的总部,只是要意识到卖家不允许他们这样做。你感到绝望,所以你开始在前门、中门、后门贴上各种说明,上面有你的电话号码,他们不允许打电话!!
是的,这些具有讽刺意味的情况一直发生在我和我的室友身上,也发生在很多我们认识的朋友和家人身上。上一次当我在等待我的新电脑时,我不得不花两个小时坐在大楼前,等待和阅读一本书来消磨时间。因此,我和我的室友决定开发我们自己的物体探测系统,当送货车辆在我们的大楼前停下或行驶时,它会通知我们。
为什么是 Yolo?
在深度学习对象检测的最先进方法(更快的 R-CNN、SSD、YOLO)中,Yolo 因其在速度和准确性之间的巨大平衡而脱颖而出。在 Yolo 中,每个输入图像都被分成一个 S x S 网格。对于网格中的每个单元,一些边界框预测与用于预测与该网格单元相关联的对象的分类概率/分数同时生成。每个分数反映了模型对盒子包含某一类对象的置信度。
你可以在这里找到一些关于 Yolo 解释的有用链接:
https://towards data science . com/yolo-v3-object-detection-53 FB 7d 3 bfe 6 b
https://medium . com/diaryofwannapreneur/yolo-you-only-look-only-once-for-object-detection-explained-6 f 80 ea 7 AAAA 1 e
【https://hackernoon.com/understanding-yolo-f5a74bbc7967
如果你有关于 Yolo 的问题,我强烈推荐这个谷歌团队。
总而言之:
Yolo 在做决定时对图像进行全局推理,它只扫描图像一次,因此节省了时间和计算,因此得名“你只看一次”。
Yolo 的检测速度使其成为实时检测的理想候选(在默认分辨率为 416 x 416 的情况下,GTX 1070 GPU 可以为 Yolov3 处理 32 FPS 的视频,为 Yolov2 处理 64 FPS 的视频)。
-具有“更深”层的 Yolov3 不仅能够探测大型和中型物体,还能以高精度探测小型物体。
- Yolo 学习对象的概化表示,因此它是高度概化的,因此,当应用于新的领域或意外输入时,它不太可能崩溃。
训练和测试模型
为了训练模型,我们使用了由 AlexeyAB(https://github.com/AlexeyAB/darknet)优化的 Yolo 实现。
1.收集训练数据
首先,我们从搜集数据进行训练开始。我们的目标数据集是 FedEx/ UPS/ USPS 送货卡车/标志。其他服务,如 DHL,以后很容易扩展。为了避免手动下载图片,我们使用了 https://github.com/hardikvasa/google-images-download 的谷歌图片抓取工具。我们为每个类别下载了大约 400 张图片,但最终每个类别只标记了大约 200 张图片,因为这对第一个试点实验来说应该足够了。为了更好地进行培训,我们还提供了负面示例,即不包含上述公司的卡车/标志的图片。理想情况下,这些图像应该包括不同种类的车辆、房屋、树木……类似于我们房屋周围的类似环境。请记住,在他的 GitHub repo 中,Alexey 建议使用尽可能多的负面例子图像,以便更好地检测。根据我在其他 Yolo 项目上的个人经验,也许 40%-50%的负面图像是一个好的范围,超过 50%可能会使模型变得不那么“敏感”。
2.标记图像
下一步是为训练标记数据。在我们的案例中,我们标记的对象是公司的徽标。我们决定排除整辆车,只在车标周围画一个边框。然而,在未来,我们将尝试对所有车辆进行检测,因为像 UPS 和 DHL 这样的卡车都非常独特/容易识别。我们使用 BBox-Label-Tool 来标记图像。由于 BBox-Label-Tool 不会自动调整图像大小以适合计算机屏幕,因此在标记之前应调整过大图像的大小,以防止图像中的部分徽标丢失。
3.训练模型
如果你的 GPU 不是很强,你可以在云上训练模型。我刚买了一台装有 GTX 1070 的新台式机,对培训来说绰绰有余。我试验了 Yolo 作者的原始 darknet 版本和 AlexeyAB 的 T2 改进版本。根据我对几个项目的经验,包括这个项目,我注意到 AlexeyAB 的版本在训练和检测阶段确实快得多(https://github . com/AlexeyAB/darknet/issues/529 # issue comment-377204382)。
为了训练模型,我们需要模型配置文件,其中包含几个用于训练的超参数。可以找找。我的 GitHub repo 上的 cfg 文件。
在这个项目中,我们对 Yolov2 和 Yolov3 都进行了实验。
*免责声明:*在模型开始检测物体之前,训练 Yolov2 比 Yolov3 更快,但可能需要更多的迭代(https://github.com/thtrieu/darkflow/issues/80)。
在我们的例子中,Yolov2 进行了超过 12,000 次迭代,Yolov3 进行了 3000 次迭代,才开始检测送货卡车。总的来说,Yolov3 在准确性方面会更好,它在检测小物体方面明显更好。然而,我们最终使用了 Yolov2,因为我们想在 Raspberry Pi web 服务器设置中使用 DarkFlow(下一篇文章),而 Yolov3 还没有在 DarkFlow 中可用。
该模型在 3 个类别上进行训练:联邦快递、UPS 和美国邮政,此外还有预训练的权重:http://pjreddie.com/media/files/darknet19_448.conv.23
关于如何使用 Yolov2 训练您的定制对象的详细说明可在此处找到:https://github . com/AlexeyAB/darknet/tree/47 c 7a f1 ce a5 bb dedf 1184963355 e 6418 CB 8 B1 b4f # how-to-train-detect-your-custom-objects
或 if
4.测试模型
知道什么时候停止训练,选择哪组砝码进行检测是相当重要的。一旦你对模型进行了足够多的训练和测试,你会获得更多的经验和直觉,但是当你第一次开始时,拥有这样的指导方针可能会非常有帮助:https://github . com/AlexeyAB/darknet # when-should-I-stop-training。
请记住,拥有一个小的训练数据集可能会很快导致过度拟合。在这种情况下,由于数据集很小,并且我已经从另一个项目中获得了足够的经验,我决定使用所有的数据进行训练,并通过对几个剪辑进行测试来选择最佳权重,而不是将我的数据分为训练集和测试集。一般来说,我们要把数据拆分成训练和测试,通过看 precision & recall,mAP (mean Average Precision),IoU (Intersection over Union)来检查模型的准确性。关于这些措施的一个很好的解释可以在这里找到。
以下是三个竞争对手在芝加哥市区的一次精彩交锋中的测试结果:
Let’s race!
您还可以在下面找到联邦快递/UPS/USPS 检测我们项目的演示剪辑:
Test on a clip
考虑到训练数据集的大小,以及它是在 416 x 416 分辨率下测试的事实,这是一个相当好的结果。您可以按照 Alexey 的说明,通过将分辨率从 416 x 416 更改为 608 x 608 或更高来改善检测。为了创建一个更加通用和健壮的检测系统,我们只需要创建更多的用于训练的标记数据。
结论
喜欢这个帖子就给我鼓掌(或者 50 :p)。请随意下载权重和配置文件并亲自测试。第二部分即将推出。我们基本上完成了实施,并且已经成功地对联邦快递、UPS 和 USPS 的送货卡车进行了现实生活中的检测。欢迎在下面留下任何评论和反馈!
用 Tensorflow 和 OpenCV 构建实时物体识别应用
原文:https://towardsdatascience.com/building-a-real-time-object-recognition-app-with-tensorflow-and-opencv-b7a2b4ebdc32?source=collection_archive---------0-----------------------
在本文中,我将介绍如何使用 Python 3(具体来说是 3.5)中的tensor flow(TF)新的对象检测 API 和 OpenCV 轻松构建自己的实时对象识别应用程序。重点将放在我创建它时所面临的挑战上。你可以在我的回购上找到完整的代码。
这也是正在运行的应用程序:
Me trying to classify some random stuff on my desk:)
动机
谷歌刚刚发布了他们新的 TensorFlow 物体检测 API。第一个版本包含:
- 一些预训练的模型(特别关注轻量模型,以便它们可以在移动设备上运行)
- 一个 Jupyter 笔记本示例,其中包含一款已发布的型号
- 一些非常方便的脚本可用于模型的重新训练,例如,在您自己的数据集上。
我想把我的手放在这个新的很酷的东西上,并有一些时间来构建一个简单的实时对象识别演示。
物体检测演示
首先,我调出了 TensorFlow models repo ,然后又看了一下他们发布的笔记本。它基本上走过了使用预训练模型的所有步骤。在他们的例子中,他们使用了“带 Mobilenet 的 SSD”模型,但你也可以在他们所谓的“tensor flow 检测模型动物园”上下载其他几个预先训练好的模型。顺便说一下,这些模型是在 COCO 数据集上训练的,并根据模型速度(慢、中和快)和模型性能(mAP —平均精度)而变化。
我接下来做的是运行这个例子。这个例子实际上是有据可查的。本质上,它是这样做的:
- 导入所需的软件包,如 TensorFlow、PIL 等。
- 定义一些变量,如班级人数、模型名称等。
- 下载冻结模型(。pb — protobuf )并将其加载到内存中
- 加载一些辅助代码,例如标签转换器的索引
- 两幅测试图像上的检测代码本身
**注意:**在运行示例之前,请务必查看设置注意事项。特别是,protobuf 编译部分非常重要:
# From tensorflow/models/research/
protoc object_detection/protos/*.proto --python_out=.
如果不运行这个命令,这个示例将无法运行。
然后,我采用他们的代码,并对其进行了相应的修改:
- 删除模型下载部分
- PIL 是不需要的,因为 OpenCV 中的视频流已经在 numpy 数组中了(PIL 也是一个非常大的开销,特别是当使用它来读取图像或视频流时)
- TensorFlow 会话没有“with”语句,因为这是一个巨大的开销,特别是当每次会话都需要在每个流之后启动时
然后,我用 OpenCV 把它和我的网络摄像头连接起来。有很多例子向你解释如何去做,甚至是官方文档。所以,我就不深究了。更有趣的部分是我为提高应用程序的性能而做的优化。在我的例子中,我看到了良好的 fps——每秒帧数。
一般来说,许多 OpenCV 示例的普通/朴素实现并不是真正的最佳实现,例如 OpenCV 中的一些函数严重受限于 I/O。所以我不得不想出各种办法来解决这个问题:
- 从网络摄像头读取帧会导致大量的 I/O。我的想法是用多处理库将这部分完全转移到不同的 Python 进程。这不知何故没有奏效。在 Stackoverflow 上有一些解释为什么它不工作,但我没有深入探讨这个问题。幸运的是,我从的 Adrian Rosebrock 的网站“pyimagesearch”上找到了一个非常好的例子,使用线程代替它大大提高了我的 fps。顺便说一下,如果你想知道多处理和线程之间的区别,在 Stackoverflow 上有一个很好的解释。
- 每次应用程序启动时,将冻结的模型加载到内存中是一项很大的开销。我已经为每次运行使用了一个 TF 会话,但这仍然非常慢。那么我是怎么解决这个问题的呢?解决办法很简单。在这种情况下,我使用多处理库将对象检测部分的繁重工作转移到多个进程中。应用程序的初始启动会很慢,因为每个进程都需要将模型加载到内存中并启动 TF 会话,但在此之后,我们将受益于并行性😁
[## 与多个工作人员一起运行对象检测演示。
由 datitran 录制
asciinema.org](https://asciinema.org/a/125852)
- 减少视频流中帧的宽度和高度也大大提高了 fps。
**注意:**如果你像我一样使用 Mac OSX,并且使用 OpenCV 3.1,OpenCV 的 VideoCapture 可能会在一段时间后崩溃。已经有个问题提交。切换回 OpenCV 3.0 解决了这个问题。
结论与展望
给我一个❤️,如果你喜欢这个职位:)拉代码,并尝试自己。一定要看看 Tensorflow 对象检测 API。到目前为止,从第一眼看上去,它非常简洁明了。我想尝试的下一件事是用 API 训练我自己的数据集,并为我想到的其他应用程序使用预训练的模型。我对应用程序的性能也不完全满意。fps 速率仍然不是最佳的。OpenCV 中仍然有许多我无法影响的瓶颈,但是我可以尝试一些替代方法,比如使用 WebRTC 。然而,这是基于网络的。此外,我正在考虑使用异步方法调用(async)来提高我的 fps 率。敬请期待!
在推特上关注我: @datitran
为 iOS 构建实时对象识别器
原文:https://towardsdatascience.com/building-a-real-time-object-recognizer-for-ios-a678d2baf8f0?source=collection_archive---------3-----------------------
使用 CoreML 和 Swift
Credits — Apple (https://developer.apple.com/documentation/coreml)
CoreML 是 WWDC 2017 上宣布的令人兴奋的功能之一。它是苹果的框架,可以用来将机器学习集成到你的应用程序中,全部离线😉。
Core ML 允许您将各种各样的机器学习模型集成到您的应用程序中。除了支持超过 30 种层类型的广泛深度学习,它还支持标准模型,如树集成、支持向量机和广义线性模型。因为它建立在 Metal 和 Accelerate 等底层技术之上,所以 Core ML 无缝地利用 CPU 和 GPU 来提供最大的性能和效率。你可以在设备上运行机器学习模型,这样数据就不需要离开设备进行分析。—苹果关于机器学习的文档(https://developer.apple.com/machine-learning/)
当你深入了解预测是如何发生的以及发生在哪里时,CoreML 的重要性就显现出来了。到目前为止,每个人都习惯于将机器学习集成到应用程序中,在托管服务器中进行预测。如果它是一个对象识别应用程序,您必须从设备中捕获帧,将这些数据发送到预测引擎,等到图像完全上传到服务器,并最终获得输出。这种方法主要有两个问题——网络延迟和用户隐私。现在,所有这些处理都可以在设备中进行,从而减少了这两个问题。
从头开始构建
我们可以尝试使用 CoreML 并为此实现一个简单的设备上解决方案。我将在不提及 iOS 或 Swift 基础知识的情况下讲述重要步骤。
我们要做的第一件事是获得一个 iOS 11 设备和 Xcode 9。
如果你不熟悉机器学习,看看这里的简介。或者你可以从这里得到一个很高层次的概述。
机器学习
这种技术赋予计算机学习的能力,而不需要明确地编码问题的解决方案。
这里基本上涉及两个过程——训练和预测。
训练是我们给模型不同组的输入(和相应的输出)来从模式中学习的过程。这个被训练的模型被给予一个它以前没有见过的输入,以便根据它早先的观察来预测。
选择模型
所以我们要做的第一件事就是为你的项目选择一个好的模型。有许多预先训练好的模型可用于图像识别。或者你甚至可以训练自己的模型来获得更好的体验。
从苹果的机器学习门户有好的模型可以作为 CoreML 模型。或者如果你有自己的模型,你可以使用苹果公司的 CoreML 工具将其转换成 CoreML 支持的模型。
我选择了苹果门户中可用的 Inception V3 库。
Inception v3 —从一组 1000 个类别中检测图像中存在的主要对象,例如树木、动物、食物、车辆、人等等。
创建 iOS 项目
您可以使用 swift 创建一个基本的 iOS 项目,并为此创建一个包含视频预览层和标签的视图控制器。
从视频预览中获取帧
像往常一样获取当前帧,这是我们已经知道的。这在这篇入侵代码文章中有解释。
使用 Inception v3 进行预测
当一个输入图像给你一个它知道的类别集合中的一个的概率时,考虑我们的初始模型作为黑盒。
从 Apple 的门户网站下载模型,将其拖放到您的项目中。您可以从 Xcode 中看到模型描述。
Inceptionv2.mlmodel in model viewer of Xcode
您可以看到,该模型将 299x299 像素的图像作为输入,并给出输出:
- 图像最可能属于的类别
- 每个类别的概率列表
我们可以利用这些参数中的任何一个来确定类别。我用的第一个是字符串,直接打印在屏幕上。
您还可以看到,Xcode 直接从 mlmodel 对象创建了一个 swift 模型(Inceptionv3.swift)。你不必为此做任何额外的改动。
使用
我们可以利用 Xcode 生成的预测 API,如下所示:
预测很简单:
但是它需要一个 CVPixelBuffer 的对象而不是 UIImage 来进行预测,hackingwithswift.com 的家伙在“机器学习和视觉”一节中对此做了很好的解释。
我已经创建了 UIImage 类别,该类别与 resize API 一起对此进行了抽象。
最终建筑
结果
该应用程序能够正确识别几乎所有提供的输入。
从回购中获取完整代码—https://github.com/m25lazi/inception。⭐️,如果你喜欢的话。
用 Flink 构建实时仪表板:后端
原文:https://towardsdatascience.com/building-a-realtime-dashboard-with-flink-the-backend-a9393062de92?source=collection_archive---------1-----------------------
随着对“实时”低延迟数据需求的增长,更多的数据科学家可能必须熟悉流。一个很好的起点是 Apache Flink。Flink 是一个分布式流框架,专门为实时数据分析而构建。与 Spark 的批处理运行不同(甚至 Spark“流”在技术上也是微批处理),Flink 是建立在流模型上的(Spark vs. Flink 是一个很长的讨论,我在这里就不赘述了)。Apache Flink 可以处理极低延迟的高吞吐量数据。因此,Apache Flink 的一个有趣用例是创建一个实时数据分析仪表板。
为了简单起见,我选择使用 Twitter streaming API 作为我们的数据源,因为其他数据源通常需要反序列化模式,这使事情变得更加复杂。在第一篇文章中,我将向您展示如何用 Flink 预处理 Tweets,并执行一些基本的聚合/过滤。然后在第二篇文章中,我将向您展示如何用 D3.js 前端连接它,以制作一个实时仪表板。由于有大量代码,我决定只包括最相关的摘录,但您可以在文章底部找到包含所有代码的 GitHub 资源库。
为了进行设置,我们定义了基本的登录凭证(您需要一个 Twitter 开发人员帐户),然后设置执行环境。关于这个的更多细节你可以从 Flink 上看到官方示例代码。唯一的例外是,这里我们将使用 Filter.java 的类作为 FilterEndpoint。这将允许我们只获得包含特定单词的推文。你可以通过声明Filter.FilterEndPoint i = new Filter(wordsList,locationsList,null);
然后声明twitterSourceA.setCustomEndPointInitializer(i);
来实现。其中,wordsList 是要包含的单词列表,twitterSourceA 是用您的凭据声明的 TwitterSource 对象(如示例所示)。您还可以根据位置或用户 id(空值)进行筛选。
Apache Flink 遵循与 Spark 和 MapReduce 相同的函数式编程方法。您有三个主要功能来处理地图、平面地图和过滤器。首先,我们将执行一个平面图,以获取相关信息。这一部分与示例非常相似,除了我还包含了一个自定义标记器(即 tokenize ),以消除点号和数字。平面图的代码如下:
This is our flatMap function that performs a basic word count on the tweets. The function uses a second function getField to get the JSON data. Then it tokenizes it, removes the punctation, and collects the word with a count of one.
接下来我们要过滤掉停用词。为此定义一个过滤器既快速又简单;我们简单地定义一个新的过滤函数,然后做tweets.filter(aFilterFunction)
见下面的全部细节。接下来,我们定义一个 10 秒的时间窗口。时间窗口允许我们查看一个单词在十秒钟的窗口中出现了多少次。然后,这个流将被输入 sink,sink 将每十秒钟更新一次我们的图表(第二步)。
Filtering and windowing functions.
此外,我选择包含最后一个过滤器,以便过滤掉在窗口中出现不到十次的单词。现在我们有了一个合适的流,可以输入到我们的数据库中,并用来直接更新我们的图表。然而,关于数据的存储和显示,仍然有许多设计选择要做。
在本系列的第二部分中,我将讨论如何将新的数据流连接到我们的前端,以便创建实时更新的图表以及一些用于处理实时流和实现持久性的架构结构。
完整的代码可在以下链接。
[## isaacmg/twitterStream
Twitter stream——使用 Apache Flink 传输特定的推文
github.com](https://github.com/isaacmg/twitterStream)
我如何建立一个香水推荐系统
原文:https://towardsdatascience.com/building-a-recommendation-system-for-fragrance-5b00de3829da?source=collection_archive---------1-----------------------
正如网飞首席执行官雷德·哈斯汀斯所说,*“你知道,想想看,当你看一个来自网飞的节目,你会上瘾,你会熬夜到很晚。我们在边缘上与睡眠竞争。”*在我看来,竞争的关键部分是如何在正确的时间向正确的人提供正确的内容,这是关于推荐系统的。
推荐系统一直吸引着我的注意力。不仅因为它们是机器学习应用的一大部分,还因为它们与理解人有关。每当我在潘多拉上听音乐,在亚马逊上买东西,在 Stitch Fix 上订购衣服,在网飞上看电影,在 StumbleUpon 上阅读新闻,在 Instagram 或 Pinterest 上浏览照片,我都强烈地感觉到推荐者已经充斥在我们数字生活的每个角落,他们将继续塑造我们未来的生活。
这就是为什么我选择了我的激励顶点项目来构建香水的推荐系统。人们说你身上散发的香味表明你是谁。一个人对香水的选择受到他/她的性别、年龄、国籍、气候、心情、一年中的季节、一天中的时间等的影响。因为我在过去做过几次错误的决定,所以几个月前决定买一台新的时,我非常谨慎。然后我想,作为一名数据科学家,我应该可以用我的数据科学和机器学习知识来回答这个问题。这就是我如何发展这个想法的——帮助人们找到他们的签名香水。
1.项目工作流程
我使用 6 个 AWS EC2 实例从中国最大的香水论坛搜集数据。将它们存储在 MongoDB 的第 7 个 EC2 实例中。数据准备好之后,我做了数据分析、特征工程、建模和交叉验证。然后我用 Flask 和 Bootstrap 搭建了一个 web app。终于在 AWS 上托管了 web app。
2.数据
数据是从中国最大的香水论坛刮来的(因为美国最大的论坛禁止我刮),它由两个表组成。一个表是香水数据,有品牌、性别、笔记、主题等特征。另一个表是用户评级数据,其中有用户 ID、香水 ID、用户评级得分(范围从 2 到 10)和用户评论。
3.模特们
在这个项目中,我针对不同的消费群体实施了不同的方法。对于冷启动问题(没有评级历史的新用户),我将使用基于内容的模型。在最终的 web 应用程序中,我会要求他们要么参加一个小测验,要么输入一种你喜欢的香水,根据香水的特性进行推荐。对于有评分历史的用户,我将实现项目-项目相似性协同过滤模型和矩阵分解模型,然后比较它们的性能。在最终的 web 应用程序中,我会要求他们登录他们的帐户,并根据相似的用户生成个性化的推荐。
(网络应用主页提供了三个选项来寻找你的下一款香水)
模型 1:基于内容的推荐系统
要建立一个基于内容的推荐器,我们唯一关心的是香水的特性。由于我收集的数据还没有告诉我人们闻到香水时的感觉的特征,我将 NMF(非负矩阵分解)和 LDA(潜在狄利克雷分配)应用于用户评论文本以进行主题建模。在比较了每种方法生成的话题后,我发现 LDA 生成的 12 个话题更具可解释性。因此,我人工标记了 12 个 LDA 主题,将它们与其他香水特征(如性别、音符和主题)结合在一起,构建了香水矩阵,然后基于 Jaccard 相似度建立了基于内容的相似度模型。
(基于内容的推荐器的快照)
模型 2:协同过滤推荐器
协同过滤的两个主要领域是邻域方法和潜在因素模型。邻域法的核心是计算项目之间的关系,或者说是使用之间的关系。面向项目的方法基于同一用户对“相邻”项目的评级来评估用户对项目的偏好。一个产品的邻居是当由同一用户评级时倾向于获得相似评级的其他产品。另一方面,潜在因素模型是一种替代方法,它试图通过根据评级模式推断的潜在因素来描述项目和用户来解释评级。对于香水,发现的因素可能测量明显或不太明确的维度,如花卉或柑橘主题,对不同性别的取向,或完全无法解释的维度。对于用户来说,每个因素都衡量用户有多喜欢在相应电影向量上得分高的香水。
在这个项目中,对于有评分历史的用户,我应用了来自邻域方法的项目-项目相似性模型和来自矩阵分解方法的 UV 分解模型。我用来评估我的建议的评估指标是 RMSE(均方根误差)。
基线模型是为用户随机推荐香水,这意味着预测评级是所有东西的平均评级(7.25,满分 10 分),它给了我 2.20 的 RMSE。
之后,我建立了项目-项目相似度模型。它表现很差(RMSE: 7.32),因为用户评级矩阵太稀疏(0.3%的单元填充有值),当矩阵太稀疏时,邻域方法不能很好地执行,因为进入每个预测的信息很少。
然后,我应用矩阵分解模型,通过随机梯度下降拟合。在调整了若干因素后,对线性项以及相互作用项进行正则化。矩阵分解模型给了我最好的表现(RMSE: 1.95)。因此,我使用矩阵分解模型作为我的协同过滤推荐器的最终模型。
(上图:矩阵 M 的紫外线分解)
协同过滤模型的性能如下图所示:
4.我如何进行训练测试分割和交叉验证
每当有人说“我建立了一个推荐者”,我脑海中浮现的第一个问题是:“你是如何验证你的推荐者的表现的?”因为这是所有推荐系统中最具挑战性的部分。在我的项目中,对于基于内容的推荐,由于它是无监督的,完全基于香水特征进行推荐,所以我通过让我的同学尝试并查看结果来验证它。总体来说,推荐是好的,尤其是主页上的“查找相似”功能,但最大的缺点是没有香水价格数据,一个喜欢香奈儿香水的顾客可能不会去一个大众市场品牌,即使它们有相似的成分。然而,对于主页上的“参加测验”功能,如果用户只选择了几个特征,结果将是 off,因为模型正在基于用户选择的所有特征构建向量,并计算用户向量和每种香水之间的 Jaccard 距离。
对于协同过滤推荐器,我尝试的第一个交叉验证方法是留一法交叉验证,但我花了 18 个小时来完成一个循环,计算量太大,因此我改用手动 K-fold 验证。首先,我手动删除了评分低于 3 的用户,将他们视为冷启动问题的一部分,并让他们使用基于内容的推荐器。然后,对于具有 3 个或更多评级的用户,我确保每个用户都存在于我的训练集、验证集和测试集中。因此,我可以使用用户在训练集中的评级来拟合模型,预测用户在验证集中的其他评级,并基于验证集上的 RMSE 来调整模型。最后,我使用用户在测试集中的评分来评估最终的模型。
5.局限性和未来工作
1)对数据的限制:
- 价格信息不可用:喜爱香奈儿香水的顾客可能不会去大众市场品牌,即使它们有相似的成分。
- 没有用户统计数据:人们对每种香水的感受在不同的文化和地域中是不同的,我的数据来自一个中国香水论坛,那里的人们对每种香水的感受并不反映其他国家的人们对每种香水的感受。
- 只有 20%的香水被评论过:好的推荐系统的一个优点是它的意外收获。但为了检索顾客对每款香水的感受,我只能查看已经有用户评论的香水。然而,80%的香水没有,要么是因为它们不流行,要么是因为它们是新的。因此,为了使我的推荐系统更好地工作,需要更多的香水领域知识和功能工程工作,这样我就不需要依赖用户评论来获得人们对每种香水的感觉。
2)顾客的口味会随着时间而改变
- 我现有的模型是静态的。但在现实中,顾客的偏好会发生变化,导致他们重新定义自己的品味。同样,随着新香水的出现,产品的认知和受欢迎程度也在不断变化。因此,系统应该考虑反映用户-项目交互的动态、时间漂移性质的时间效应。因此,对于未来的工作,我还应该收集用户评级数据,我的协同过滤模型应该考虑时间效应。
3)有更好的方法吗?
- 是的。永远不要停止学习。
6.最后的想法
在为期两周的项目体验中,我意识到我可以用推荐系统做很多事情,以及它们有多么强大。它们不仅仅是香水或任何消费品。它们可以是你可能在 MOOC 网站上喜欢的课程,或者你可能在约会应用程序上喜欢的人,不用说,新闻文章、书籍、音乐……背后的主要想法是关于你如何了解你的客户,你有多少领域知识,以及你如何利用数据科学和机器学习来帮助你实现你的理解。如果你碰巧也对这个领域感兴趣,我会非常乐意与你讨论。
代码可以在这里找到:【github.com/kellypeng/scentmate_rec】T2
【联系作者:https://www.linkedin.com/in/pengyuwei/
参考资料:
- Anand Rajaraman 和 Jeffrey Ullman,挖掘海量数据集,第 9 章推荐系统
- Yehyda Koren,Robert Bell 和 Chris Volinsky,推荐系统的矩阵分解技术
- 耶胡达·科伦,因式分解与邻域相遇:多面协作过滤模型
- 斯蒂芬·高尔, Netflix 奖和 SVD
- Jiunn Haur Lim,用矩阵分解法预测用户评分
使用神经网络嵌入构建推荐系统
原文:https://towardsdatascience.com/building-a-recommendation-system-using-neural-network-embeddings-1ef92e5c80c9?source=collection_archive---------2-----------------------
(Source)
如何利用深度学习和维基百科创建图书推荐系统
深度学习可以做一些不可思议的事情,但其用途往往在学术论文中被掩盖,或者需要只有大公司才能获得的计算资源。尽管如此,深度学习的应用可以在个人电脑上完成,不需要高级学位。在本文中,我们将看到如何使用神经网络嵌入来创建一个图书推荐系统,该系统使用所有关于图书的维基百科文章。
我们的推荐系统将建立在链接到相似维基百科页面的书籍彼此相似的理念之上。我们可以表现出这种相似性,从而通过使用神经网络学习书籍和维基百科链接的嵌入来提出建议。最终的结果是一个有效的推荐系统和深度学习的实际应用。
Most Similar Books to Stephen Hawking’s A Brief History of Time
这个项目的完整代码可以从 GitHub 上的 Jupyter 笔记本中获得。如果你没有 GPU,你也可以在 Kaggle 上找到笔记本,在那里你可以免费用一个 GPU 训练你的神经网络。本文将重点关注实现,神经网络嵌入的概念在之前的文章中有所涉及。(要了解如何检索我们将使用的数据——维基百科上的所有书籍文章——请看一下这篇文章。)
这个项目改编自深度学习食谱,这是一本关于应用深度学习的动手示例的优秀书籍。
神经网络嵌入
嵌入是一种将离散的分类变量表示为连续向量的方法。与一次性编码之类的编码方法相比,神经网络嵌入是低维的和学习过的,这意味着它们将相似的实体在嵌入空间中彼此放置得更近。
为了创建嵌入,我们需要一个神经网络嵌入模型和一个受监督的机器学习任务。我们网络的最终结果将是把每本书表示为 50 个连续数字的向量。
虽然嵌入本身并不有趣——它们只是向量——但它们可以用于三个主要目的:
- 在嵌入空间中寻找最近的邻居
- 作为机器学习模型的输入
- 低维可视化
该项目主要涵盖第一个用例,但我们也将看到如何从嵌入创建可视化。神经网络嵌入的实际应用包括机器翻译的单词嵌入和分类变量的实体嵌入。
数据:维基百科上的所有书籍
像通常的数据科学项目一样,我们需要从高质量的数据集开始。在这篇文章中,我们看到了如何下载和处理维基百科上的每一篇文章,搜索任何关于书籍的页面。我们保存了书名、基本信息、图书页面上指向其他维基百科页面的链接(wikilinks)以及外部站点的链接。为了创建推荐系统,我们需要的唯一信息是标题和 wikilinks。
**Book Title: 'The Better Angels of Our Nature'****Wikilinks:** **['Steven Pinker',
'Nation state',
'commerce',
'literacy',
'Influence of mass media',
'Rationality',
"Abraham Lincoln's first inaugural address",
'nature versus nurture',
'Leviathan']**
即使在处理神经网络时,探索和清理数据也很重要,在笔记本中,我对原始数据做了几处修改。例如,查看链接最多的页面:
Wikipedia pages most often linked to by books on Wikipedia.
我们看到前四页是一般性的,对推荐没有帮助。一本书的格式没有告诉我们关于内容的任何事情:知道一本书是paperback
或hardcover
并不允许我们——或神经网络——找出它相似的其他书。因此,我们可以去除这些链接,帮助神经网络区分书籍。
考虑最终目的可以在数据清理阶段有所帮助,并且这一行动本身就可以显著改进建议。
出于纯粹的好奇,我想在维基百科上找到与其他书链接最多的书。以下是 10 本“联系最紧密”的维基百科书籍:
Books on Wikipedia most often linked to by other books on Wikipedia.
这是参考书和经典书籍的混合体,很有意义。
经过数据清理,我们有了一套 41758 独有维基链接和 37020 独有书籍。希望每个人都有一本书!
一旦我们确信我们的数据是干净的,我们就需要开发一个有标签的训练样本的监督机器学习任务。
监督学习任务
为了*学习有意义的嵌入,*我们的神经网络必须被训练来完成一个目标。从项目的指导假设——相似的书籍链接到相似的维基百科页面——开始,我们可以将问题表述如下:给定一个(书名,维基链接)对,确定维基链接是否出现在该书的文章中。
我们实际上不需要把书的文章交给电视台。相反,我们将输入成千上万的训练样本,包括书名、维基链接和标签。我们给网络一些真实的例子——实际上存在于数据集中——和一些虚假的例子,最终它会学习嵌入来区分维基链接何时出现在一本书的页面上。
表达监督学习任务是这个项目最重要的部分。嵌入是为特定的任务学习的,并且只与那个问题相关。如果我们的任务是确定哪些书是简·奥斯汀写的,那么嵌入将反映这一目标,在嵌入空间中将奥斯汀写的书放在一起。我们希望通过训练来判断一本书的页面上是否有某个维基链接,网络可以学习嵌入,将内容相似的书彼此放得更近。
一旦我们概述了学习任务,我们需要用代码实现它。首先,因为神经网络只能接受整数输入,所以我们创建了从每个唯一书籍到整数的映射:
# Mapping of books to index and index to books
book_index = {book[0]: idx for idx, book in enumerate(books)}
book_index['Anna Karenina']**22494**
我们也对链接做同样的事情。在此之后,为了创建训练集,我们列出了数据中的所有(book,wikilink)对。这需要遍历每本书,并在页面上为每个 wikilink 记录一个例子:
pairs = []
*# Iterate through each book*
for book in books:
title = book[0]
book_links = book[2] # Iterate through wikilinks in book article
for link in book_links: # Add index of book and index of link to pairs
pairs.extend((book_index[title],
link_index[link]))
这给了我们总共 772798 个真实的例子,我们可以从中取样来训练模型。为了生成错误的示例(稍后完成),我们将简单地随机选取一个链接索引和图书索引,确保它不在pairs
中,然后将其用作负面观察。
关于训练/测试集的说明
虽然使用单独的验证和测试集是正常监督机器学习任务的必须,但在这种情况下,我们的主要目标是而不是制作最准确的模型,而是生成嵌入。预测任务只是我们为这些嵌入训练我们的网络的手段。在训练结束时,我们不会在新数据上测试我们的模型,所以我们不需要评估性能或使用验证集来防止过度拟合。为了获得最佳嵌入,我们将使用所有示例进行训练。
嵌入模型
虽然神经网络嵌入听起来在技术上很复杂,但使用 Keras 深度学习框架实现起来相对容易。(如果你是深度学习新手,我建议从 Keras 开始。TensorFlow 可能会给你更多的控制,但 Keras 在开发方面是无可匹敌的)。
嵌入模型有 5 层:
- **输入:**书本和链接的并行输入
- **嵌入:**平行长度 50 书籍和链接的嵌入
- **点:**通过计算点积合并嵌入
- **整形:**需要将点积整形为单个数字
- **密集:**一个具有乙状结肠激活的输出神经元
在嵌入神经网络中,嵌入是神经网络的参数——权重——在训练过程中调整,以最小化目标的损失。神经网络将一本书和一个链接作为整数,并输出一个介于 0 和 1 之间的预测,与真实值进行比较。该模型用[Adam](https://machinelearningmastery.com/adam-optimization-algorithm-for-deep-learning/)
优化器(随机梯度下降的变体)编译,该优化器在训练期间改变嵌入以最小化该二元分类问题的binary_crossentropy
。
下面是完整模型的代码:
这个框架可以用于许多嵌入模型。需要理解的重要一点是,嵌入是模型参数(权重),也是我们想要的最终结果。我们不在乎模型是否准确,我们想要的是相关的嵌入。
我们习惯于将模型中的权重作为做出准确预测的手段,但是在嵌入模型中,权重是目标,而预测是学习嵌入的手段。
如模型摘要所示,有将近 400 万个权重:
通过这种方法,我们不仅可以获得书籍的嵌入,还可以获得链接,这意味着我们可以比较所有书籍链接的维基百科页面。
生成训练样本
神经网络是批量学习器,因为它们是在一小组样本——观察值——上训练的,一次经过许多轮,称为历元。训练神经网络的常见方法是使用生成器。这是一个yields
(不是returns
)批量处理样本的功能,因此整个结果不会保存在内存中。虽然在这个问题中这不是问题,但是生成器的好处是大型训练集不需要全部加载到内存中。
我们的生成器接受训练pairs
,每批阳性样本数(n_positive
,每批阴性:阳性样本比率(negative_ratio
)。每次调用生成器时,它都会生成一批新的阳性和阴性样本。为了得到正面的例子,我们随机抽样真实的配对。对于反面的例子,我们随机抽取一本书和一个链接,确保这个配对不在正确的配对中,然后将它添加到批处理中。
下面的代码完整地展示了生成器。
每次我们调用生成器上的next
,我们都会得到一个新的训练批次。
next(generate_batch(pairs, n_positive = 2, negative_ratio = 2))**({'book': array([ 6895., 29814., 22162., 7206., 25757., 28410.]),
'link': array([ 260., 11452., 5588., 34924., 22920., 33217.])},
array([ 1., -1., 1., -1., -1., -1.]))**
有了监督任务、训练生成器和嵌入模型,我们就可以学习书籍嵌入了。
培训模式
有几个训练参数可供选择。第一个是每批的正例数。一般来说,我试着从小批量开始,然后逐渐增加,直到性能开始下降。此外,我们需要为每个正例选择训练的负例数量。我建议尝试几个选项,看看什么效果最好。因为我们没有使用验证集来实现提前停止,所以我选择了一些时期,超过这些时期,训练损失不会减少。
n_positive = 1024
gen = generate_batch(pairs, n_positive, negative_ratio = 2)
*# Train*
h = model.fit_generator(gen, epochs = 15,
steps_per_epoch = len(pairs) // n_positive)
(如果训练参数似乎是任意的,从某种意义上来说,它们是任意的,但基于 深度学习 中概述的最佳实践。像机器学习的大多数方面一样,训练神经网络在很大程度上是凭经验的。)
一旦网络完成训练,我们就可以提取嵌入。
*# Extract embeddings*
book_layer = model.get_layer('book_embedding')
book_weights = book_layer.get_weights()[0]
应用嵌入:提出建议
嵌入本身相当无趣:它们只是每本书和每个链接的 50 个数字的向量:
What War and Peace Looks Like as a Vector.
然而,我们可以将这些向量用于两个不同的目的,第一个目的是制作我们的图书推荐系统。为了在嵌入空间中找到与查询书最接近的书,我们获取该书的向量,并找到它与所有其他书的向量的点积。如果我们的嵌入是归一化的,那么向量之间的点积表示余弦相似度,范围从-1(最不相似)到+1(最相似)。
查询列夫·托尔斯泰的经典作品 《战争与和平》的嵌入结果:
**Books closest to War and Peace.
Book: Anna Karenina Similarity: 0.92
Book: The Master and Margarita Similarity: 0.92
Book: Demons (Dostoevsky novel) Similarity: 0.91
Book: The Idiot Similarity: 0.9
Book: Crime and Punishment Similarity: 0.9**
这些建议很有道理!这些都是经典的俄罗斯小说。当然,我们可以去 GoodReads 寻找这些相同的建议,但是为什么不自己建立这个系统呢?我鼓励你使用笔记本,自己探索嵌入的内容。
**Books closest to The Fellowship of the Ring.****Book: The Return of the King Similarity: 0.96
Book: The Silmarillion Similarity: 0.93
Book: Beren and Lúthien Similarity: 0.91
Book: The Two Towers Similarity: 0.91**
除了嵌入书籍,我们还嵌入了链接,这意味着我们可以找到与给定维基百科页面最相似的链接:
**Pages closest to steven pinker.
Page: the blank slate Similarity: 0.83
Page: evolutionary psychology Similarity: 0.83
Page: reductionism Similarity: 0.81
Page: how the mind works Similarity: 0.79**
目前,我正在读一本由史蒂芬·杰·古尔德写的精彩散文集,名为《雷龙的恶霸》。接下来该读什么?
Recommendations for my next book.
嵌入的可视化
嵌入最吸引人的一个方面是,它们可以用来可视化概念,比如相对于彼此的小说或非小说。这需要进一步的降维技术来使维数达到 2 或 3。最流行的约简技术是另一种嵌入方法: t 分布随机邻居嵌入(TSNE) 。
从维基百科上所有书籍的 37000 维空间开始,我们使用嵌入将其映射到 50 维,然后使用 TSNE 将其映射到 2 维。这会产生以下图像:
Embeddings of all books on Wikipedia.
这张图片本身并不那么有启发性,但是一旦我们开始根据书籍的特点给它着色,我们就开始看到集群的出现:
非小说和科幻小说有一些明确的分类(只有前 10 种类型被突出显示),它们有不同的部分。鉴于小说内容的多样性,这些小说似乎无处不在。
我们也可以嵌入国家:
我有点惊讶这些国家是如此的与众不同!显然,澳大利亚的书籍是非常独特的。
此外,我们可以在维基百科地图上突出显示某些书籍:
The corner of Wikipedia with books about the entire Universe
笔记本里有更多的视觉化图像,你可以自己制作。我再给你一个展示 10 本“联系最紧密”的书的例子:
Book embeddings with 10 most linked to books and genres.
关于 TSNE 需要注意的一点是,它试图保持原始空间中向量之间的距离,但因为它减少了维数,所以可能会扭曲原始分离。因此,在 50 维嵌入空间中彼此靠近的书籍在 2 维 TSNE 嵌入中可能不是最近的邻居。
交互式可视化
这些可视化非常有趣,但我们可以使用 TensorFlow 的投影仪工具制作令人惊叹的交互式图形,该工具专门为可视化神经网络嵌入而设计。我计划写一篇关于如何使用这个工具的文章,但是现在这里是一些结果:
Interactive visualizations made with projector
要以互动方式浏览书籍样本,请点击这里的。
潜在的其他项目
数据科学项目通常不是完全靠自己发明的。我从事的许多项目都是来自其他数据科学家的想法,我对这些想法进行了改编、改进和构建,以形成一个独特的项目。(这个项目的灵感来自于深度学习食谱中一个类似的电影推荐项目。)
带着这种态度,这里有一些方法来继续这项工作:
- 使用外部链接而不是 wikilinks 创建嵌入。这些是维基百科以外的网页,可能会产生不同的嵌入。
- 使用嵌入来训练受监督的机器学习模型,以预测包括流派、作者和国家的书籍特征。
- 在维基百科上选择一个主题类别,创建自己的推荐系统。你可以使用人物、地标,甚至历史事件。您可以使用这个笔记本获取数据,使用这个笔记本进行嵌入。
这绝不是一个家庭作业,只是一些项目想法,如果你想把你所读到的付诸实践。如果你决定接手一个项目,我很乐意听听你的想法。
结论
神经网络嵌入是一种将离散分类变量表示为连续向量的方法。作为一种学习的低维表示,它们对于寻找相似的类别、作为机器学习模型的输入或者可视化概念地图是有用的。在这个项目中,我们使用神经网络嵌入来创建一个有效的图书推荐系统,该系统基于链接到相似页面的图书彼此相似的思想。
创建神经网络嵌入的步骤如下:
- 收集数据。神经网络需要许多训练示例。
- 制定一个有监督的任务来学习反映问题的嵌入。
- 建立和训练嵌入式神经网络模型。
- 提取嵌入内容以进行推荐和可视化。
详细内容可以在笔记本中找到,我鼓励任何人参与这个项目。虽然深度学习可能因为技术复杂性或计算资源而看起来势不可挡,但这是通过有限的学习就可以在个人电脑上完成的许多应用之一。深度学习是一个不断发展的领域,这个项目是通过构建一个有用的系统来开始的好方法。而且,当你不在研究深度学习的时候,现在你知道你应该读什么了!
一如既往,我欢迎反馈和建设性的批评。可以通过 Twitter @koehrsen_will 或我的个人网站 willk.online 找到我。
使用 NVIDIA TensorRT 服务器和谷歌云为 Keras 模型构建可扩展的深度学习服务环境
原文:https://towardsdatascience.com/building-a-scaleable-deep-learning-serving-environment-for-keras-models-using-nvidia-tensorrt-a5c578af59ec?source=collection_archive---------24-----------------------
在最近的一个项目中,我使用 Keras 和 Tensorflow 开发了一个用于图像分类的大规模深度学习应用程序。开发完模型后,我们需要将它部署到云环境中一个相当复杂的数据获取和准备例程管道中。我们决定在通过 API 公开模型的预测服务器上部署模型。因此,我们遇到了英伟达 TensorRT 服务器(TRT 服务器),一个不错的老 TF 服务的严肃替代品(顺便说一下,这是一个很棒的产品!).在权衡利弊之后,我们决定给 TRT 服务器一个机会。TRT 服务器有几个优于 TF 服务器的优点,如优化的推理速度、简单的模型管理和资源分配、版本控制和并行推理处理。此外,TensorRT 服务器并不“局限于”TensorFlow(和 Keras)模型。它可以服务于所有主要深度学习框架的模型,如 TensorFlow、MxNet、pytorch、theano、Caffe 和 CNTK。
尽管有很多很酷的功能,我发现设置 TRT 服务器有点麻烦。安装和文档分散在相当多的存储库、官方文档指南和博客文章中。这就是为什么我决定写这篇关于设置服务器的博文,让你的预言成真!
NVIDIA TensorRT 服务器
TensorRT 推理服务器是英伟达将深度学习模型投入生产的前沿服务器产品。它是 NVIDIA 的 TensorRT 推理平台的一部分,提供了一个可扩展的、生产就绪的解决方案,用于为来自所有主要框架的深度学习模型提供服务。它基于 NVIDIA Docker,包含从容器内部运行服务器所需的一切。此外,NVIDIA Docker 允许在 Docker 容器中使用 GPU,在大多数情况下,这大大加快了模型推理的速度。谈到速度——TRT 服务器可以比 TF 服务器快得多,并允许同时从多个模型进行多个推理,使用 CUDA 流来利用 GPU 调度和序列化(见下图)。
通过 TRT 服务器,您可以使用所谓的实例组来指定并发推理计算的数量,这些实例组可以在模型级别进行配置(参见“模型配置文件”一节)。例如,如果您为两个模型提供服务,并且其中一个模型获得了明显更多的推理请求,那么您可以为该模型分配更多的 GPU 资源,从而允许您并行计算更多的请求。此外,实例组允许您指定模型应该在 CPU 还是 GPU 上执行,这在更复杂的服务环境中是一个非常有趣的特性。总的来说,TRT 服务器有一大堆很棒的特性,这使得它非常适合生产使用。
上图展示了服务器的一般架构。人们可以看到 HTTP 和 gRPC 接口,它们允许您将模型集成到通过 LAN 或 WAN 连接到服务器的其他应用程序中。相当酷!此外,服务器公开了一些健全的特性,如健康状态检查等。,这在生产中也派上了用场。
设置服务器
如前所述,TensorRT 服务器位于 NVIDIA Docker 容器中。为了让事情进展顺利,您需要完成几个安装步骤(如果您是从一台空白的机器开始,就像这里一样)。整个过程相当漫长,需要一定的“一般云、网络、IT 知识”。我希望下面的步骤能让你清楚安装和设置的过程。
在谷歌云上启动深度学习虚拟机
对于我的项目,我使用了预装 CUDA 和 TensorFlow 库的 Google 深度学习虚拟机。你可以使用 Google Cloud SDK 或者在 GCP 控制台中启动云虚拟机(在我看来,这非常容易使用)。GCP SDK 的安装可以在这里找到。请注意,由于 CUDA 安装过程需要几分钟的时间,可能需要一段时间才能连接到服务器。您可以在云日志控制台中检查虚拟机的状态。
# Create project
gcloud projects create tensorrt-server# Start instance with deep learning image
gcloud compute instances create tensorrt-server-vm \
--project tensorrt-server \
--zone your-zone \
--machine-type n1-standard-4 \
--create-disk='size=50' \
--image-project=deeplearning-platform-release \
--image-family tf-latest-gpu \
--accelerator='type=nvidia-tesla-k80,count=1' \
--metadata='install-nvidia-driver=True' \
--maintenance-policy TERMINATE
成功设置实例后,您可以使用终端 SSH 到 VM。从这里,您可以执行所有必要的步骤来安装所需的组件。
# SSH into instance
gcloud compute ssh tensorrt-server-vm \
--project tensorrt-server \
--zone your-zone
注意:当然,您必须为您的项目和实例名修改脚本。
安装 Docker
在设置了 GCP 云虚拟机之后,你必须在你的机器上安装 Docker 服务。谷歌深度学习虚拟机使用 Debian 作为操作系统。您可以使用下面的代码在 VM 上安装 Docker。
# Install Docker
sudo apt-get update sudo
apt-get install \
apt-transport-https \
ca-certificates \
curl \
software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo apt-key add -
sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable"
sudo apt-get update
sudo apt-get install docker-ce
您可以通过运行以下命令来验证 Docker 是否已经成功安装。
sudo docker run --rm hello-world
你应该看到一个“你好,世界!”从 docker 容器中,您应该会看到这样的内容:
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
d1725b59e92d: Already exists
Digest: sha256:0add3ace90ecb4adbf7777e9aacf18357296e799f81cabc9fde470971e499788
Status: Downloaded newer image for hello-world:latestHello from Docker!
This message shows that your installation appears to be working correctly.To generate this message, Docker took the following steps:
1\. The Docker client contacted the Docker daemon.
2\. The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64)
3\. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading.
4\. The Docker daemon streamed that output to the Docker client, which sent it to your terminal.To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/ For more examples and ideas, visit: [https://docs.docker.com/get-started/](https://docs.docker.com/get-started/)
恭喜你,你已经成功安装了 Docker!
安装 NVIDIA Docker
不幸的是,Docker 对连接到主机系统的 GPU 没有“开箱即用”的支持。因此,需要安装 NVIDIA Docker 运行时,才能在容器化环境中使用 TensorRT Server 的 GPU 功能。NVIDIA Docker 也用于 TF 服,如果你想用你的 GPU 做模型推断的话。下图说明了 NVIDIA Docker 运行时的架构。
您可以看到,NVIDIA Docker 运行时围绕 Docker 引擎分层,允许您在系统上使用标准 Docker 和 NVIDIA Docker 容器。
由于 NVIDIA Docker 运行时是 NVIDIA 的专有产品,您必须在 NVIDIA GPU Cloud (NGC) 注册以获得 API 密钥,以便安装和下载它。要针对 NGC 进行身份验证,请在服务器命令行中执行以下命令:
# Login to NGC sudo docker login nvcr.io
将提示您输入用户名和 API 密钥。对于用户名,您必须输入$oauthtoken
,密码是生成的 API 密钥。成功登录后,您可以安装 NVIDIA Docker 组件。按照 NVIDIA Docker GitHub repo 上的说明,您可以通过执行以下脚本来安装 NVIDIA Docker(Ubuntu 14.04/16.04/18.04,Debian Jessie/Stretch)。
# If you have nvidia-docker 1.0 installed: we need to remove it and all existing GPU containers
docker volume ls -q -f driver=nvidia-docker | xargs -r -I{} -n1 docker ps -q -a -f volume={} | xargs -r docker rm -f
sudo apt-get purge -y nvidia-docker# Add the package repositories
curl -s -L [https://nvidia.github.io/nvidia-docker/gpgkey](https://nvidia.github.io/nvidia-docker/gpgkey) | \
sudo apt-key add -
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L [https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list](https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list) | \
sudo tee /etc/apt/sources.list.d/nvidia-docker.list
sudo apt-get update# Install nvidia-docker2 and reload the Docker daemon configuration
sudo apt-get install -y nvidia-docker2
sudo pkill -SIGHUP dockerd# Test nvidia-smi with the latest official CUDA image
sudo docker run --runtime=nvidia --rm nvidia/cuda:9.0-base nvidia-smi
安装 TensorRT 服务器
成功安装 NVIDIA Docker 后,下一步就是安装 TensorRT 服务器。它可以从 NVIDIA 容器注册表(NCR)中提取。同样,您需要通过 NGC 认证才能执行此操作。
# Pull TensorRT Server (make sure to check the current version) sudo docker pull nvcr.io/nvidia/tensorrtserver:18.09-py3
提取映像后,TRT 服务器就可以在您的云机器上启动了。下一步是创建一个将由 TRT 服务器提供服务的模型。
模型部署
在安装了所需的技术组件并拉出 TRT 服务器容器之后,您需要关注您的模型和部署。TensorRT Server 在服务器上的一个文件夹中管理其模型,即所谓的模型库。
设置模型库
模型库包含导出的 TensorFlow / Keras 等。特定文件夹结构中的模型图。对于模型库中的每个模型,需要定义一个具有相应模型名称的子文件夹。在这些模型子文件夹中,有模型模式文件(config.pbtxt
)、标签定义(labels.txt
)以及模型版本子文件夹。这些子文件夹允许您管理和提供不同的模型版本。文件labels.txt
包含适当顺序的目标标签的字符串,对应于模型的输出层。在 version 子文件夹中保存了一个名为model.graphdef
(导出的 protobuf 图)的文件。model.graphdef
实际上是一个冻结的 tensorflow 图,是导出 TensorFlow 模型后创建的,需要相应命名。
备注:由于一些变量初始化错误,我无法从 TRT 服务器的tensoflow.python.saved_model.simple_save()
或tensorflow.python.saved_model.builder.SavedModelBuilder()
导出中获得有效服务。因此,我们使用“冻结图”方法,将图中的所有 TensorFlow 变量转换为常量,并将所有内容输出到一个文件中(即model.graphdef
)。
/models
|- model_1/
|-- config.pbtxt
|-- labels.txt
|-- 1/
|--- model.graphdef
因为模型库只是一个文件夹,所以它可以位于 TRT 服务器主机有网络连接的任何地方。例如,您可以将导出的模型图存储在云存储库或您机器上的本地文件夹中。新模型可以导出并部署到那里,以便通过 TRT 服务器进行服务。
模型配置文件
在您的模型库中,模型配置文件(config.pbtxt
)为 TRT 服务器上的每个模型设置重要参数。它包含关于您的可服务模型的技术信息,并且是正确加载模型所必需的。这里有几件事你可以控制:
name: "model_1"
platform: "tensorflow_graphdef"
max_batch_size: 64
input [
{
name: "dense_1_input"
data_type: TYPE_FP32
dims: [ 5 ]
}
]
output [
{
name: "dense_2_output"
data_type: TYPE_FP32
dims: [ 2 ]
label_filename: "labels.txt"
}
]
instance_group [
{
kind: KIND_GPU
count: 4
}
]
首先,name
定义了模型下的标签在服务器上是可达的。这必须是模型库中模型文件夹的名称。platform
定义了框架,建立了模型。如果你用的是 TensorFlow 或者 Keras,有两个选项:(1) tensorflow_savedmodel
和tensorflow_graphdef
。如前所述,我用的是tensorflow_graphdef
(见上一节末尾我的备注)。batch_size
,顾名思义,控制你预测的批量大小。input
定义你的模型的输入层节点名称,比如输入层的name
(是的,你应该在 TensorFlow 或者 Keras 中命名你的层和节点)data_type
,目前只支持数值类型,比如TYPE_FP16, TYPE_FP32, TYPE_FP64
和输入dims
。相应的,output
定义了你的模型的输出层name
,分别是data_type
和dims
。您可以指定一个labels.txt
文件,以适当的顺序保存输出神经元的标签。因为这里只有两个输出类,所以文件看起来很简单,如下所示:
class_0 class_1
每行定义一个类标签。请注意,该文件不包含任何头。最后一部分instance_group
让您为您的模型定义特定的 GPU ( KIND_GPU
)或 CPU ( KIND_CPU
)资源。在示例文件中,有4
个并发 GPU 线程分配给模型,允许四个同时预测。
构建一个简单的服务模型
为了通过 TensorRT 服务器为模型提供服务,您首先需要一个模型。我准备了一个小脚本,在 Keras 中构建一个简单的 MLP 用于演示目的。我已经在生产中成功地将 TRT 服务器用于更大的模型,如 InceptionResNetV2 或 ResNet50,它工作得非常好。
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from keras.models import Sequential
from keras.layers import InputLayer, Dense
from keras.callbacks import EarlyStopping, ModelCheckpoint
from keras.utils import to_categorical# Make toy data
X, y = make_classification(n_samples=1000, n_features=5)# Make target categorical
y = to_categorical(y)# Train test split
X_train, X_test, y_train, y_test = train_test_split(X, y)# Scale inputs
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)# Model definition
model_1 = Sequential()
model_1.add(Dense(input_shape=(X_train.shape[1], ), units=16, activation='relu', name='dense_1'))
model_1.add(Dense(units=2, activation='softmax', name='dense_2'))
model_1.compile(optimizer='adam', loss='categorical_crossentropy')# Early stopping
early_stopping = EarlyStopping(patience=5)
model_checkpoint = ModelCheckpoint(filepath='model_checkpoint.h5', save_best_only=True, save_weights_only=True)
callbacks = [early_stopping, model_checkpoint]# Fit model and load best weights
model_1.fit(x=X_train, y=y_train, validation_data=(X_test, y_test), epochs=50, batch_size=32, callbacks=callbacks)# Load best weights after early stopping
model_1.load_weights('model_checkpoint.h5')# Export model
model_1.save('model_1.h5')
该脚本使用sklearn.datasets.make_classification
构建了一些玩具数据,并为这些数据拟合了一个单层 MLP。拟合后,模型被保存,以便在单独的导出脚本中进一步处理。
为上菜冻结图表
服务 Keras (TensorFlow)模型的工作方式是将模型图导出为一个单独的 protobuf 文件(.pb
-文件扩展名)。将模型导出到包含网络所有权重的单个文件中的一个简单方法是“冻结”图形并将其写入磁盘。由此,图形中的所有tf.Variables
被转换为tf.constant
,并与图形一起存储在一个文件中。为此,我修改了这个脚本。
import os
import shutil
import keras.backend as K
import tensorflow as tf
from keras.models import load_model
from tensorflow.python.framework import graph_util
from tensorflow.python.framework import graph_io def freeze_model(model, path):
""" Freezes the graph for serving as protobuf """
# Remove folder if present
if os.path.isdir(path):
shutil.rmtree(path)
os.mkdir(path)
shutil.copy('config.pbtxt', path)
shutil.copy('labels.txt', path)
# Disable Keras learning phase
K.set_learning_phase(0)
# Load model
model_export = load_model(model)
# Get Keras sessions
sess = K.get_session()
# Output node name
pred_node_names = ['dense_2_output']
# Dummy op to rename the output node
dummy = tf.identity(input=model_export.outputs[0], \
name=pred_node_names)
# Convert all variables to constants
graph_export = \
graph_util.convert_variables_to_constants(sess=sess,
input_graph_def=sess.graph.as_graph_def(),
output_node_names=pred_node_names)
graph_io.write_graph(graph_or_graph_def=graph_export,
logdir=path + '/1',
name='model.graphdef',
as_text=False)# Freeze Model
freeze_model(model='model_1.h5', path='model_1')# Upload to GCP
os.system('gcloud compute scp model_1 tensorrt-server-vm:~/models/ --project tensorrt-server --zone us-west1-b --recurse')
freeze_model()
函数获取保存的 Keras 模型文件model_1.h5
的路径以及要导出的图形的路径。此外,我还增强了该功能,以便构建所需的模型库文件夹结构,其中包含版本子文件夹config.pbtxt
和labels.txt
,两者都存储在我的项目文件夹中。该函数加载模型并将图形导出到定义的目的地。为了做到这一点,您需要定义输出节点的名称,然后使用graph_util.convert_variables_to_constants
将图中的所有变量转换为常量,这使用了相应的 Keras 后端会话,必须使用K.get_session()
获取这些会话。此外,在导出前使用K.set_learning_phase(0)
禁用 Keras 学习模式非常重要。最后,我添加了一个小的 CLI 命令,将我的模型文件夹上传到我的 GCP 实例的模型库/models
。
启动服务器
既然一切都已安装、设置和配置完毕,现在(终于)是时候启动我们的 TRT 预测服务器了。以下命令启动 NVIDIA Docker 容器,并将模型库映射到该容器。
sudo nvidia-docker run --rm --name trtserver -p 8000:8000 -p 8001:8001 \ -v ~/models:/models nvcr.io/nvidia/tensorrtserver:18.09-py3 trtserver \ --model-store=/models
--rm
删除由--name
给出的同名的现有容器。-p
显示主机上的端口 8000 (REST)和 8001 (gRPC ),并将它们映射到各自的容器端口。-v
将主机上的模型库文件夹(在我的例子中是/models
)安装到容器中的/models
,然后--model-store
将其引用为查找可服务模型图的位置。如果一切正常,您应该会看到类似如下的控制台输出。如果您不想看到服务器的输出,您可以在启动时使用-d
标志在分离的模型中启动容器。
===============================
== TensorRT Inference Server ==
===============================NVIDIA Release 18.09 (build 688039)Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
Copyright 2018 The TensorFlow Authors. All rights reserved.Various files include modifications (c) NVIDIA CORPORATION. All rights reserved.
NVIDIA modifications are covered by the license terms that apply to the underlying
project or file.NOTE: The SHMEM allocation limit is set to the default of 64MB. This may be
insufficient for the inference server. NVIDIA recommends the use of the following flags:
nvidia-docker run --shm-size=1g --ulimit memlock=-1 --ulimit stack=67108864 ...I1014 10:38:55.951258 1 server.cc:631] Initializing TensorRT Inference Server
I1014 10:38:55.951339 1 server.cc:680] Reporting prometheus metrics on port 8002
I1014 10:38:56.524257 1 metrics.cc:129] found 1 GPUs supported power usage metric
I1014 10:38:57.141885 1 metrics.cc:139] GPU 0: Tesla K80
I1014 10:38:57.142555 1 server.cc:884] Starting server 'inference:0' listening on
I1014 10:38:57.142583 1 server.cc:888] localhost:8001 for gRPC requests
I1014 10:38:57.143381 1 server.cc:898] localhost:8000 for HTTP requests
[warn] getaddrinfo: address family for nodename not supported
[evhttp_server.cc : 235] RAW: Entering the event loop ...
I1014 10:38:57.880877 1 server_core.cc:465] Adding/updating models.
I1014 10:38:57.880908 1 server_core.cc:520] (Re-)adding model: model_1
I1014 10:38:57.981276 1 basic_manager.cc:739] Successfully reserved resources to load servable {name: model_1 version: 1}
I1014 10:38:57.981313 1 loader_harness.cc:66] Approving load for servable version {name: model_1 version: 1}
I1014 10:38:57.981326 1 loader_harness.cc:74] Loading servable version {name: model_1 version: 1}
I1014 10:38:57.982034 1 base_bundle.cc:180] Creating instance model_1_0_0_gpu0 on GPU 0 (3.7) using model.savedmodel
I1014 10:38:57.982108 1 bundle_shim.cc:360] Attempting to load native SavedModelBundle in bundle-shim from: /models/model_1/1/model.savedmodel
I1014 10:38:57.982138 1 reader.cc:31] Reading SavedModel from: /models/model_1/1/model.savedmodel
I1014 10:38:57.983817 1 reader.cc:54] Reading meta graph with tags { serve }
I1014 10:38:58.041695 1 cuda_gpu_executor.cc:890] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
I1014 10:38:58.042145 1 gpu_device.cc:1405] Found device 0 with properties:
name: Tesla K80 major: 3 minor: 7 memoryClockRate(GHz): 0.8235
pciBusID: 0000:00:04.0
totalMemory: 11.17GiB freeMemory: 11.10GiB
I1014 10:38:58.042177 1 gpu_device.cc:1455] Ignoring visible gpu device (device: 0, name: Tesla K80, pci bus id: 0000:00:04.0, compute capability: 3.7) with Cuda compute capability 3.7\. The minimum required Cuda capability is 5.2.
I1014 10:38:58.042192 1 gpu_device.cc:965] Device interconnect StreamExecutor with strength 1 edge matrix:
I1014 10:38:58.042200 1 gpu_device.cc:971] 0
I1014 10:38:58.042207 1 gpu_device.cc:984] 0: N
I1014 10:38:58.067349 1 loader.cc:113] Restoring SavedModel bundle.
I1014 10:38:58.074260 1 loader.cc:148] Running LegacyInitOp on SavedModel bundle.
I1014 10:38:58.074302 1 loader.cc:233] SavedModel load for tags { serve }; Status: success. Took 92161 microseconds.
I1014 10:38:58.075314 1 gpu_device.cc:1455] Ignoring visible gpu device (device: 0, name: Tesla K80, pci bus id: 0000:00:04.0, compute capability: 3.7) with Cuda compute capability 3.7\. The minimum required Cuda capability is 5.2.
I1014 10:38:58.075343 1 gpu_device.cc:965] Device interconnect StreamExecutor with strength 1 edge matrix:
I1014 10:38:58.075348 1 gpu_device.cc:971] 0
I1014 10:38:58.075353 1 gpu_device.cc:984] 0: N
I1014 10:38:58.083451 1 loader_harness.cc:86] Successfully loaded servable version {name: model_1 version: 1}
还有一个警告,显示您应该使用以下参数启动容器
--shm-size=1g --ulimit memlock=-1 --ulimit stack=67108864
你当然可以这样做。然而,在这个例子中,我没有使用它们。
安装 Python 客户端
现在是时候测试我们的预测服务器了。TensorRT Server 附带了几个客户端库,允许您向服务器发送数据并获得预测。构建客户端库的推荐方法仍然是——Docker。要使用包含客户端库的 Docker 容器,您需要使用以下命令克隆各自的 GitHub repo :
git clone [https://github.com/NVIDIA/dl-inference-server.git](https://github.com/NVIDIA/dl-inference-server.git)
然后,cd
进入dl-inference-server
文件夹并运行
docker build -t inference_server_clients .
这将在您的机器上构建容器(需要一些时间)。要在主机上使用容器中的客户端库,需要将一个文件夹挂载到容器中。首先,在交互会话中启动容器(-it
标志)
docker run --name tensorrtclient --rm -it -v /tmp:/tmp/host inference_server_clients
然后,在容器的 shell 中运行以下命令(您可能必须首先创建/tmp/host
):
cp build/image_client /tmp/host/.
cp build/perf_client /tmp/host/.
cp build/dist/dist/tensorrtserver-*.whl /tmp/host/.
cd /tmp/host
上面的代码将预构建的image_client
和perf_client
库复制到挂载的文件夹中,并使其可以从主机系统访问。最后,您需要使用
pip install tensorrtserver-0.6.0-cp35-cp35m-linux_x86_64.whl
在集装箱系统上。终于!就这样,我们准备好了(听起来这是一个简单的方法)!
使用 Python 客户端进行推理
使用 Python,您可以使用客户端库轻松执行预测。为了向服务器发送数据,您需要一个来自inference_server.api
模块的InferContext()
,它获取 TRT 服务器的 IP 和端口以及所需的型号名称。如果您在云中使用 TRT 服务器,请确保您有适当的防火墙规则允许端口 8000 和 8001 上的流量。
from tensorrtserver.api import *
import numpy as np# Some parameters
outputs = 2
batch_size = 1# Init client
trt_host = '123.456.789.0:8000' # local or remote IP of TRT Server
model_name = 'model_1'
ctx = InferContext(trt_host, ProtocolType.HTTP, model_name)# Sample some random data
data = np.float32(np.random.normal(0, 1, [1, 5]))# Get prediction
# Layer names correspond to the names in config.pbtxt
response = ctx.run(
{'dense_1_input': data},
{'dense_2_output': (InferContext.ResultFormat.CLASS, outputs)},
batch_size)# Result
print(response)
{'output0': [[(0, 1.0, 'class_0'), (1, 0.0, 'class_1')]]}
注意:发送到服务器的数据必须与浮点精度相匹配,这一点很重要,浮点精度是先前在模型定义文件中为输入层定义的。此外,输入和输出层的名称必须与模型的名称完全匹配。如果一切顺利,ctx.run()
返回一个预测值的字典,您可以根据需要对其进行进一步的后处理。
结论和展望
哇,那真是一段旅程!然而,TensorRT Server 是一款非常棒的产品,可以将您的深度学习模型投入生产。它速度快、可扩展,并且具有适合生产使用的简洁特性。我没有详细讨论推理性能。如果你对更多感兴趣,一定要看看 NVIDIA 的博客文章。我必须承认,与 TRT 服务器相比,TF Serving 在安装、模型部署和使用方面要方便得多。然而,与 TRT 服务器相比,它缺少一些在生产中方便使用的功能。一句话:我和我的团队一定会将 TRT 服务器添加到我们深度学习模型的生产工具堆栈中。
如果你对我的故事有任何意见或问题,欢迎在下面评论!我将尝试回答这些问题。此外,请随意使用我的代码或在您选择的社交平台上与您的同行分享这个故事。
如果你对更多类似的内容感兴趣,请加入我们的邮件列表,不断为你带来新的数据科学、机器学习和人工智能阅读,并从我和我在 STATWORX 的团队直接发送到你的收件箱!
最后,如果你有兴趣与我联系,请在 LinkedIn 或 Twitter 关注我。
参考
- 所有图片均来自这个 NVIDIA 开发者博客
原载于 2018 年 11 月 19 日www.statworx.com。
用 Google Cloud、聊天客户端和 Ruby 构建一个情感检测机器人。
原文:https://towardsdatascience.com/building-a-sentiment-detection-bot-with-google-cloud-a-chat-client-and-ruby-cc280c61c6f0?source=collection_archive---------12-----------------------
介绍
在这个系列中,我将解释如何创建一个聊天机器人,它能够检测情绪,分析图像,并最终拥有一个不断发展的个性的基础。这是该系列的第 1 部分。
这些碎片
- 红宝石
- 西纳特拉
- 谷歌云 API
- Line(聊天客户端)
因为我住在日本:
我将使用流行的聊天服务 Line 作为我们的客户。对于情感检测,我们将使用谷歌云自然语言 API 。选择的语言将是 Ruby(因为,为什么不),微框架 Sinatra 作为我们的服务器。好了,让我们开始吧!
设置聊天客户端
Line 是这里非常受欢迎的聊天服务;然而,你不需要真的住在这里才能注册。所以你应该可以顺利跟进。
一旦下载了 app,做了账号,就可以在这里注册成为开发者: Line 开发者页面。
我们需要创建一个新的“提供商”:
和消息传递 API“通道”:
现在,我们必须给我们的频道一个名称(这将是我们的机器人的显示名称),和应用程序图标(显示图片)。既然这是一个情感探测机器人,我们就用 apt 吧:“情感机器人”
Just a bit creepy…
创建时,请注意以下值:
- 频道秘密
- 通道访问令牌
此外,对设置进行以下更改:
- 使用 webhooks: 启用
- 自动回复消息:禁用
- 问候语:禁用
最后,我们必须设置我们的“Webhook URL”:这是 bot 和客户端通信的入口点。每当消息被发送到这个通道(我们的 bot)时,它将被中继到我们在这个字段中指定的任何端点。因为我们还没有,我们的下一步是创建一个。
设置服务器
服务器是我们的 bot 示例中的关键元素。实际上,它就是“机器人”。由于我们使用第三方聊天客户端(Line)作为我们的主要通信渠道,我们需要定义一个端点或 webhook,用于数据传输。
在这个上下文中,webhook 是一个 API 端点,聊天客户端将在收到消息时向其发布消息。然后由您(您的机器人)解析消息并提取必要的部分进行处理。处理完成后,我们会通过消息传递 API 将这些信息发送回我们的聊天客户端,最终由最终用户(即与您即将成为机器人的人)接收。
在这个例子中,我们将使用 Ruby 和微框架 Sinatra。
让我们继续创建我们的应用程序:
mkdir sentiment_bot && cd $_bundle inittouch main.rb
请注意,这些文件名和目录名完全是任意的,是为了简单和一致而选择的。
好了,让我们继续安装 Sinatra(我们的 web 框架),将以下内容添加到 Gemfile 中。
gem 'sinatra'
作为健全性检查,让我们创建一个准系统端点,当我们点击它时返回一个响应。作为“你好世界”的一部分,这将是我们的“こんにちは世界”。好了,我们开始吧,把下面的方法添加到 main.rb 中。
启动服务器:
ruby main.rb
并访问 localhost:4567/hello 。我们应该看到我们的问候响亮而清晰。世界上一切都是对的。现在,让我们设置端点,它将被用作聊天客户端和机器人之间的通信层。按照 Line 的要求,并且作为一个好的实践,这条路线将是一个“Post”,至于名称:“callback”是最好的。
将以下内容添加到 main.rb 中:
暂时把这条路留作空路也无妨。回到正题,我们的 webhook 需要是一个可公开访问的 https URL。然而,我们的服务器是在本地运行的。我们可以做到这一点的一个方法是将我们的代码推送到一个 PaaS ,比如 Heroku ,但是这有点超出了本教程的范围。现在,让我们使用令人惊奇的服务 Ngrok ,用于 HTTP 隧道。在您安装了ngrok 并启动了您的 web 服务器之后,您可以运行下面的命令来获取我们本地服务器的公共 URL:
ngrok http 4567
这告诉 ngrok 服务为本地端口 4567(这是 Sinatra 的默认端口)创建一个 URL。运行这个程序后,我们应该看到两个 URL 被打印到控制台,一个是 http,另一个是 https。我们将使用 https URL。它应该类似于:
[https://some_hex_string.ngrok.io](https://some_hex_string.ngrok.io)
复制它,并输入它作为您的僵尸网络挂钩网址,如下所示:
[https://some_hex_string.ngrok.io/callback](https://some_hex_string.ngrok.io/callback)
附加路径“callback”指的是我们刚刚在 main.rb 中添加的“post”方法。
一旦你输入了网址,你应该会看到一个“验证”按钮。点击后,我们应该看到对本地服务器的点击,并在线确认成功。
Upon Successful Verification
下一步是将我们的机器人添加为在线好友,并尝试与它交谈。我们没有给它任何功能,所以我们在这里的目标只是看看是否一切都通信正常:也就是说,当一个消息被发送到我们的机器人,我们的回调 url 实际上被触发。
使用您的 Line 移动客户端扫描为您的机器人提供的二维码。一旦你添加了你的机器人,给它发一条信息。您应该会再次看到我们的服务器被点击。
Sure, go ahead and add my bot.
我们已经验证了所有的东西都是相互关联的,但是如果聊天机器人不说话的话,它会很无聊。现在开始有趣的部分。
设置 Line SDK
当然,我们可以使用他们的文档编写自己的 Line API 工具,但这很耗时,超出了本教程的范围。还有,Line 刚好有官方 SDK。
将以下内容添加到您的 gem 文件中,并运行软件包安装:
gem 'line-bot-api'
既然已经安装了 gem,我们需要设置我们的凭证(可以从我们的开发控制台中获得)。
将以下导入添加到 main.rb 中
require 'line/bot'
以及以下内容:
这个方法将允许我们向我们的 bot/channel 发起经过验证的请求。你制作的每一个机器人都有一个唯一的秘密和访问令牌——你不应该公开这个信息,或者把它登记到你的版本控制系统中。
让我们继续设置从第行接收到的环境变量:
export LINE_CHANNEL_SECRET="you_channel_secret"
export LINE_CHANNEL_ACCESS_TOKEN="you_access_token"
现在,让我们将我们的“回调”函数更改如下(摘自 Line 的 sdk 文档):
现在,我们的机器人应该作为一个回声服务器,让我们来测试一下。
Rude…
好的,一切看起来都很好!我们已经将我们的机器人命名为“感知机器人”,所以它应该能够检测情绪。在自然语言处理的上下文中,情感测量给定输入相对于人类情感是消极的还是积极的(即,坏的还是好的)。一句“我爱你!”会被认为是积极的,而“我恨你!”会被认为是负面的。
设置 Google 自然语言
如果这是你第一次使用谷歌云,也就是谷歌最新的认证系统,那么你可以在这里查看他们的详细文档:https://Cloud . Google . com/natural-language/docs/quick start-client-libraries。
一旦你完成了你的项目设置并且你的授权已经排序,我们就可以继续将 ruby 客户端添加到我们的 Gemfile 中,当然也可以运行 bundle install:
gem 'google-cloud-language'
如果您已经正确设置了您的服务帐户并安装了客户端 SDK,那么从文档中复制示例代码并运行它。如果一切正常,您应该会看到类似下面的输出:
Overall document sentiment: (0.30000001192092896)
Sentence level sentiment:
Hello world: (0.30000001192092896)
一旦这些都工作了,让我们把它集成到我们的 bot 服务器代码中。目前,我们的机器人只模仿发送给它的任何文本或图像,但现在有了谷歌的力量,让我们把它变得更花哨一点。我们接下来的步骤如下:
- 阅读发送给机器人的任何文本
- 发送文本到谷歌进行情感分析
- 通过我们的机器人返回给用户的情绪得分
首先,让我们做一个检测并返回其输入情感的函数。我们可以通过以下方法做到这一点:
这些方法非常简单。“ google_language_client ”简单地实例化客户端,而“get _ opinion”使用所述客户端并返回任何可行文本输入的情感分析。
让我们将“/post”路线更改为以下内容:
That settles it…
假设你所有的外部服务都设置正确,你应该可以和你的机器人聊天,它会返回你的文本的情感分数。让我们试一试:
对于任何不幸与这样的机器人互动的人来说,仅仅返回一个情感分数是非常无聊的。让我们给它一点个性。
让我们将 main.rb 文件修改如下:
我们在这里做了一些改变。首先,我们添加了一些常量来保存我们的文本响应,我们还添加了一个新方法“get _ perspective _ response”,它检查情感得分并返回一个适当的回复。让我们试一试:
我们做到了!我们的机器人可以检测消息中的情绪,尽管词汇量有限,并做出相应的响应。
在本系列的下一篇文章中,我们将通过使用谷歌云视觉 API,让我们的机器人能够理解我们发送给它的图像。
建立一个类似的图像查找没有任何培训!
原文:https://towardsdatascience.com/building-a-similar-images-finder-without-any-training-f69c0db900b5?source=collection_archive---------1-----------------------
在本文中,我们将通过剖析图像对象分类器 VGG 的训练权重来构建一个相似图像查找器,并使用它从图像数据库中提取特征向量,以查看哪些图像彼此“相似”。这种技术被称为转移学习,在我们这边不需要任何训练——艰苦的工作在 VGG 实际接受训练的时候就已经完成了,我们只是重新使用训练过的权重来建立一个新的模型。
这个工具的一个很大的用途是对你想要的任何东西——食物、衣服、鞋子、动物、玩具,只要你能想到的,都可以做类似的图片推荐。例如,我们通过在普通牛排餐厅食物图像的小型数据库上查询测试汉堡图像来测试我们的推荐系统,它能够识别数据库中的其他汉堡:
Fig 1) Top 5 similar image recommendations from querying a burger image (left), t-SNE visualization of our image feature vectors for a small database of steakhouse foods (right)
在继续解释我们构建这个类似的图像查找工具的步骤之前,我们在 my Github 上分享我们的 Python 代码实现:
https://github . com/ankonzoid/artificio/tree/master/image _ retrieval
在本文的剩余部分,我们将演练解剖 VGG 以构建相似图像查找器的步骤。更多我关于深度学习和强化学习的博客、教程、项目,请查看我的 Medium 和我的 Github 。
解剖 VGG,建立一个类似的图像查找器
迁移学习是指利用从解决一个问题中获得的训练有素的知识来帮助解决另一个不同但相关的问题。然而,这并不像只是盲目地重新使用网络那么简单,因为只是在具有网络在训练期间未暴露的全新类别标签的图像上重新使用已训练的神经网络通常是没有希望的。例如,人们不会期望使用专门针对猫和狗图像训练的神经网络来正确地分类和区分鞋子品牌。那么如何才能恰当的迁移之前的学习来解决物体图像识别中的其他问题呢?
尽管神经网络不能准确地检测外来的高级特征(即,面部、身体、单词、标签),但是低级特征(即,边缘、纹理、颜色)是可靠地可转移的,因为它们在典型的训练图像中非常丰富和多样。这些低级功能是更抽象对象的小构件,如图 2 所示:
Fig 2) A great example of how low-level features are combined to construct high-level features in neural networks (extracted from “Convolutional Deep Belief Networks for Scalable Unsupervised Learning of Hierarchical Representations” by Lee, Grosse, Ranganath, Ng)
利用我们的“低级特征是可转移的”启发,我们可以采用训练过的图像对象分类器,如 VGG,移除其最后的高级层,并使用分割的模型将我们的图像(高维像素空间中的点)转换为表示 VGG 学习的低级特征的低维特征向量。有了这些特征向量,我们可以通过一些内积,如余弦相似性或欧几里德距离,直接比较它们的“相似性”,从而对我们的图像进行聚类,以进行推荐。
图 3 显示了我们如何剖析 VGG 并将其用于构建我们的相似图像查找器的示意流程图:
Fig 3) Schematic flow chart for how to apply transfer learning by dissecting VGG to create feature embedding vectors from our image database to compute “similarities” between images
总结一下我们构建相似图像查找器的步骤:
- 准备我们的图像数据库。
- 下载训练好的 VGG 模型,并删除其最后几层。
- 使用我们的解剖 VGG 模型将我们的图像数据库转换成特征向量。如果分割模型的输出层是卷积滤波器,则展平滤波器,并将它们附加成单个向量。
- 使用内积计算我们的图像特征向量之间的相似性,例如余弦相似性或欧几里德距离
- 对于每个图像,选择具有前 k 个相似性得分的图像来构建推荐
- (可选)获取特征向量并对其运行 t-SNE,以获得图像彼此相似程度的 2D 可视化
基于乳腺癌数据构建简单的机器学习模型
原文:https://towardsdatascience.com/building-a-simple-machine-learning-model-on-breast-cancer-data-eca4b3b99fa3?source=collection_archive---------2-----------------------
Fig: Machine Learning Model
简介
乳腺癌(BC)是全球女性中最常见的癌症之一,根据全球统计数据,其代表了大多数新癌症病例和癌症相关死亡,使其成为当今社会的重大公共健康问题。
BC 的早期诊断可以显著改善预后和生存机会,因为它可以促进对患者进行及时的临床治疗。良性肿瘤的进一步精确分类可以防止患者接受不必要的治疗。因此,BC 的正确诊断和患者的恶性或良性分类是许多研究的主题。由于其在从复杂 BC 数据集中检测关键特征方面的独特优势,机器学习(ML)被广泛认为是 BC 模式分类和预测建模的首选方法。
分类和数据挖掘方法是对数据进行分类的有效方法。尤其是在医学领域,这些方法被广泛用于诊断和分析以做出决策。
推荐的筛查指南:
**乳房 x 光检查。**乳腺癌最重要的筛查测试是乳房 x 光检查。乳房 x 光片是乳房的 x 光片。它可以在您或您的医生感觉到肿瘤之前两年内检测出乳腺癌。
年龄在 40-45 岁或以上的女性有患乳腺癌的平均风险,应该每年做一次乳房 x 光检查。
高危女性应该从 30 岁开始每年进行乳房 x 光检查和核磁共振检查。
乳腺癌的一些风险因素
以下是一些已知的乳腺癌风险因素。然而,大多数乳腺癌病例无法与特定原因联系起来。请向您的医生咨询您的具体风险。
年龄。随着女性年龄的增长,患乳腺癌的几率也会增加。将近 80%的乳腺癌发生在 50 岁以上的女性身上。
**乳腺癌个人史。**一个乳房患过乳腺癌的女性,另一个乳房患癌的风险更高。
**乳腺癌家族史。**如果母亲、姐妹或女儿患有乳腺癌,女性患乳腺癌的风险更高,尤其是在年轻时(40 岁之前)。有其他亲属患有乳腺癌也可能会增加风险。
**遗传因素。**具有某些基因突变(包括 BRCA1 和 BRCA2 基因的改变)的女性在其一生中患乳腺癌的风险更高。其他基因变化也可能增加患乳腺癌的风险。
生育和月经史。生第一个孩子的女性年龄越大,患乳腺癌的风险就越大。风险较高的还有:
- 年轻时(12 岁前)第一次来月经的妇女
- 绝经较晚的女性(55 岁以后)
- 从未生过孩子的女人
阶段 0 —数据准备
我们将使用 UCI 乳腺癌机器学习知识库数据集。
http://archive . ics . UCI . edu/ml/datasets/breast+cancer+Wisconsin+% 28 diagnostic % 29
这个故事中使用的数据集是公开可用的,由美国威斯康星州麦迪逊市威斯康星大学医院的内科医生 William H. Wolberg 博士创建。为了创建数据集,Wolberg 博士使用了从实性乳腺肿块患者身上采集的液体样本,以及一种易于使用的图形计算机程序 Xcyt,该程序能够基于数字扫描进行细胞学特征分析。该程序使用曲线拟合算法来计算样本中每个细胞的 10 个特征,然后计算图像每个特征的平均值、极值和标准误差,返回 30 个实值向量
属性信息:
- ID 号 2)诊断(M =恶性,B =良性)3–32)
为每个细胞核计算十个实值特征:
- 半径(从中心到周边各点的平均距离)
- 纹理(灰度值的标准偏差)
- 周长
- 区域
- 平滑度(半径长度的局部变化)
- 紧凑性(周长/面积— 1.0)
- 凹度(轮廓凹陷部分的严重程度)
- 凹点(轮廓凹陷部分的数量)
- 对称
- 分形维数(“海岸线近似值”-1)
对每幅图像计算这些特征的平均值、标准误差和“最差”或最大值(三个最大值的平均值),得到 30 个特征。例如,字段 3 是平均半径,字段 13 是半径 SE,字段 23 是最差半径。
目标
该分析旨在观察哪些特征最有助于预测恶性或良性癌症,并了解可能有助于我们进行模型选择和超参数选择的总体趋势。目标是对乳腺癌是良性还是恶性进行分类。为了实现这一点,我使用了机器学习分类方法来拟合一个可以预测新输入的离散类的函数。
第 1 阶段—数据探索
我们将使用 Spyder 来处理这个数据集。我们将首先导入必要的库,并将数据集导入 Spyder:
#importing the libraries
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd#importing our cancer dataset
dataset = pd.read_csv(‘cancer.csv')
X = dataset.iloc[:, 1:31].values
Y = dataset.iloc[:, 31].values
Fig : Dataset and X set after importing the dataset
我们可以使用 pandas 的 head() 方法来检查数据集。
dataset.head()
Fig : top 5 data of our dataset
我们可以使用 panda 数据集的“shape”属性找到数据集的维度。
print("Cancer data set dimensions : {}".format(dataset.shape))Cancer data set dimensions : (569, 32)
我们可以观察到数据集包含 569 行和 32 列。诊断是我们将要预测的列,它表示癌症是 M =恶性还是 B =良性。1 表示癌症是恶性的,0 表示良性的。我们可以确定,在 569 人中,357 人被标记为 B(良性),212 人被标记为 M(恶性)。
数据可视化是数据科学的一个重要方面。这有助于理解数据,也有助于向他人解释数据。Python 有几个有趣的可视化库,如 Matplotlib、Seaborn 等。
在本教程中,我们将使用构建在 matplotlib 之上的 pandas 可视化工具来查找要素的数据分布。
Fig : Visualization of Dataset
缺失或空数据点
我们可以使用下面的 pandas 函数找到数据集的任何缺失或空数据点(如果有的话)。
dataset.isnull().sum()
dataset.isna().sum()
Fig : Observe missing data
阶段 2 —分类数据
分类数据是包含标签值而非数值的变量。可能值的数量通常限于一个固定的集合。
例如,通常按国家、性别、年龄组等来描述用户。
我们将使用标签编码器来标记分类数据。标签编码器是 Python 中 SciKit Learn 库的一部分,用于将分类数据或文本数据转换为数字,我们的预测模型可以更好地理解这些数字。
#Encoding categorical data values
from sklearn.preprocessing import LabelEncoder
labelencoder_Y = LabelEncoder()
Y = labelencoder_Y.fit_transform(Y)
Fig: Diagnosis Data without Encoding
Fig: Diagnosis Data after Encoding
分割数据集
我们使用的数据通常分为训练数据和测试数据。训练集包含一个已知的输出,模型学习这个数据,以便以后推广到其他数据。我们有测试数据集(或子集)来测试我们的模型对这个子集的预测。
我们将使用 Python 中的 SciKit-Learn 库通过 train_test_split 方法来实现这一点。
# Splitting the dataset into the Training set and Test setfrom sklearn.model_selection import train_test_split
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size = 0.25, random_state = 0)
Fig: Training and test set
阶段 3 —特征缩放
大多数情况下,您的数据集将包含在量级、单位和范围方面差异很大的要素。但是因为,大多数机器学习算法在它们的计算中使用两个数据点之间的欧几里德距离。我们需要将所有的特征提升到相同的数量级。这可以通过缩放来实现。这意味着您正在转换数据,使其符合特定的范围,如 0–100 或 0–1。
我们将使用 SciKit-Learn 库中的 StandardScaler 方法。
#Feature Scalingfrom sklearn.preprocessing import StandardScaler
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)
阶段 4 —型号选择
这是将机器学习应用于任何数据集的最令人兴奋的阶段。它也被称为预测最佳结果的算法选择。
通常数据科学家对大型数据集使用不同种类的机器学习算法。但是,在高层次上,所有这些不同的算法可以分为两组:监督学习和非监督学习。
为了不浪费太多时间,我将简单介绍一下这两种学习方式。
监督学习:监督学习是一种既提供输入数据又提供期望输出数据的系统。输入和输出数据被标记以便分类,从而为将来的数据处理提供学习基础。监督学习问题可以进一步分为回归和分类问题。
一个回归问题是当输出变量是一个实值或连续值时,比如“工资”或“体重”。
一个分类问题是当输出变量是一个类别时,如过滤邮件“垃圾邮件”或“非垃圾邮件”
无监督学习:无监督学习是算法使用既未分类也未标记的信息,并允许算法在没有指导的情况下对该信息进行操作。
在我们的数据集中,我们有结果变量或因变量,即 Y 只有两组值,M(恶性)或 B(良性)。所以我们将使用监督学习的分类算法。
在机器学习中,我们有不同类型的分类算法
1.逻辑回归
2.最近邻
3.支持向量机
4.内核 SVM
5.朴素贝叶斯
6.决策树算法
7.随机森林分类
让我们开始应用算法:
我们将使用 sklearn 库导入分类算法的所有方法。
我们将使用 Logistic 回归方法进行模型选择,使用 Logistic 回归算法,
#Using Logistic Regression Algorithm to the Training Setfrom sklearn.linear_model import LogisticRegression
classifier = LogisticRegression(random_state = 0)
classifier.fit(X_train, Y_train)#Using KNeighborsClassifier Method of neighbors class to use Nearest Neighbor algorithm*from sklearn.neighbors import KNeighborsClassifier
classifier = KNeighborsClassifier(n_neighbors = 5, metric = 'minkowski', p = 2)
classifier.fit(X_train, Y_train)* #Using SVC method of svm class to use Support Vector Machine Algorithm *from sklearn.svm import SVC
classifier = SVC(kernel = 'linear', random_state = 0)
classifier.fit(X_train, Y_train)* #Using SVC method of svm class to use Kernel SVM Algorithm *from sklearn.svm import SVC
classifier = SVC(kernel = 'rbf', random_state = 0)
classifier.fit(X_train, Y_train)* #Using GaussianNB method of naïve_bayes class to use Naïve Bayes Algorithm *from sklearn.naive_bayes import GaussianNB
classifier = GaussianNB()
classifier.fit(X_train, Y_train)* #Using DecisionTreeClassifier of tree class to use Decision Tree Algorithm *from sklearn.tree import DecisionTreeClassifier
classifier = DecisionTreeClassifier(criterion = 'entropy', random_state = 0)
classifier.fit(X_train, Y_train)* #Using RandomForestClassifier method of ensemble class to use Random Forest Classification algorithm *from sklearn.ensemble import RandomForestClassifier
classifier = RandomForestClassifier(n_estimators = 10, criterion = 'entropy', random_state = 0)
classifier.fit(X_train, Y_train)*
现在,我们将预测测试集结果,并检查每个模型的准确性:
Y_pred = classifier.predict(X_test)
为了检查准确性,我们需要导入度量类的混淆矩阵方法。混淆矩阵是一种将错误分类的数量制成表格的方式,即,基于真实类别在错误的分类箱中结束的预测类别的数量。
from sklearn.metrics import confusion_matrix
cm = confusion_matrix(Y_test, Y_pred)
我们将使用分类准确性方法来确定我们的模型的准确性。当我们使用术语“准确性”时,分类准确性就是我们通常所指的。它是正确预测数与输入样本总数的比率。
Fig: Accuracy
为了检查正确的预测,我们必须检查混淆矩阵对象并对角地添加预测结果,这将是正确预测的数量,然后除以预测的总数。
Fig: Confusion Matrix
在应用不同的分类模型后,我们得到了不同模型的以下准确度:
1.逻辑回归— 95.8%
2.最近邻— 95.1%
3.支持向量机— 97.2%
4.内核 SVM — 96.5%
5.朴素贝叶斯——91.6%
6.决策树算法— 95.8%
7.随机森林分类— 98.6%
最后,我们建立了分类模型,我们可以看到随机森林分类算法为我们的数据集提供了最佳结果。它并不总是适用于每一个数据集。为了选择我们的模型,我们总是需要分析我们的数据集,然后应用我们的机器学习模型。
这是机器学习模型对任何数据集的基本应用。如果你有任何疑问,请随时提问。给 vishabh1010@gmail.com 发邮件或者通过链接联系我。
你可以在 github 上找到代码,在 Ipython 控制台上试试。
切记始终牢记过度拟合和欠拟合的问题。
希望你喜欢这篇文章…..
用 Python 为你的 Mac 构建一个简单的语音助手
原文:https://towardsdatascience.com/building-a-simple-voice-assistant-for-your-mac-in-python-62247543b626?source=collection_archive---------2-----------------------
最基本的 python 语音助手,可以帮你打开电脑应用或者搜索互联网
像 Siri 或 Cortana 这样的语音助手可以为你做一些很酷很有用的事情:打开应用程序、搜索信息、发送消息等等。虽然用别人给你的很酷,但是自己做更有趣。在这篇文章中,我将向你展示如何开始构建一个语音助手框架,它可以做完全开发的工具在 Mac 上所能做的 1%的事情——抱歉,我不会对任何其他操作系统做太多介绍。
Ironic Cortana Reference Since We’re on Mac — Source
就像我上一篇关于使用你自己的短信创建聊天机器人的博文一样,这不会是一个完全成熟的想法,也不会让你在制作中走得太远。老实说,我花了比编码更长的时间来寻找/制作这个帖子的 gif。
然而,如果你想知道如何用 python 创建自己的语音助手,并且喜欢瞎折腾的话,这篇博文应该会给你一个很好的起点。还有一些其他的帖子有着几乎相同的基本概念——但是在 TDS 上没有看到任何类似的东西,我想这到底是怎么回事🤷🏻我可以写得更好,我的会更有趣。
在这篇博文中,我将展示两种不同的语音激活功能:
- 打开应用程序
- 搜索互联网
设置和安装
我们首先需要两个特别的包裹。第一个是使用麦克风— 这篇文章很好地介绍了 python 中的语音识别。第二个和我过去的帖子一样,用 elasticsearch 做查询-查询匹配,返回一个响应。
在 Mac 上,用自制软件安装portaudio
和elasticsearch
。家酿是一个伟大的 macOS 软件包管理器,可以在这里下载。然后在终端运行中:
brew install portaudio
brew install elasticsearch
我将使用pip
进行 python 包管理。我们将使用的speech_recognition
包将语音翻译成文本,而pyaudio
是连接到你的计算机的麦克风所必需的。我们还将使用 elasticsearch Python 客户端来简化我们的工作,我正在使用 Python 3。
pip install SpeechRecognition
pip install pyaudio
pip install elasticsearch
Python 中的语音识别
这个speech_recognition
包很棒,因为正如前面的文章中所说的,“SpeechRecognition 库充当了几个流行的语音 API 的包装器,因此非常灵活。其中之一——Google Web Speech API——支持一个默认的 API 键,该键被硬编码到 SpeechRecognition 库中。
Source
超级方便,如果你不想为任何其他供应商建立一个帐户。在不到 10 行代码中,这个包应该让我们连接到我们内置的计算机麦克风,并转录我们的声音!
import speech_recognition as srr = sr.Recognizer()
mic = sr.Microphone()with mic as source:
r.adjust_for_ambient_noise(source)
audio = r.listen(source)
transcript = r.recognize_google(audio)
print(transcript)
这段代码应该运行到它听到什么为止,然后把你说的话(或者它认为你说的话)打印出来。超级简单。关于这些类以及它们如何工作的更多信息,请参考前面提到的帖子。
给你的电脑一个声音
在 Python 中有多种方法可以做到这一点,但是最简单的方法就是使用 macOS 自带的方法。使用子进程包,我们可以很容易地让我们的计算机说话:
import subprocessdef say(text):
subprocess.call(['say', text])say("yo whatup dog")
打开电脑上的应用程序
所以现在你可以把声音转换成文字,让你的电脑说话,世界就是你的了,生病了。现在我们可以决定如何使用输入。对于一个简单的想法,我的第一反应是用它来打开应用程序。显然,它一点也不酷,但作为一个例子,它工作得很好,我将使用的一般结构可以应用于更广泛的功能。因此,让我们首先获得我们所有应用程序的列表。
在 Mac 上,我想打开的所有应用程序都在/Applications
目录中,并且大部分都有一个.app
扩展名,所以我们可以用如下方式获得它们的名称:
d = '/Applications'
apps = list(map(lambda x: x.split('.app')[0], os.listdir(d)))
列出目录并删除扩展名。酷毙了。
打开应用程序也很容易。这里有一个使用os
包和 Spotify 的简单例子。
import osapp = 'Spotify'
os.system('open ' +d+'/%s.app' %app.replace(' ','\ '))
.replace
只是为了在较长的应用程序名称中适当地转义空格,但如果你安装了 Spotify,并且在你的应用程序中,它应该会打开。
在 Elasticsearch 中索引您的数据
将语音脚本与功能绑定在一起的显而易见的解决方案是某种精确匹配,如果transcript == 'open spotify'
那么这样做…我可能不必解释这是如何不可扩展的。此外,使用像 elastic 这样的酷框架会更好。此外,如果没有任何实际的数据或算法,它就不是一篇数据科学博客。
来自我在 chatbots 上的上一篇博文——“elastic search 是一个可扩展的搜索平台,它使用类似于 TF-IDF 或词频逆文档频率的算法。本质上,它是一个简单的功能,经常在搜索/相似性空间中使用,根据关键字定位文档…有关它的基本概述,请查看维基百科。”
Source
基本上,我们会将所有语音命令(类似于“打开 spotify”)上传到 elasticsearch,并将它们映射到我们想要运行的系统命令(实际的编程命令)。为此,我们可以快速创建一个字典列表。
import osd = '/Applications'
records = []
apps = os.listdir(d)for app in apps:
record = {}
record['voice_command'] = 'open ' + app.split('.app')[0]
record['sys_command'] = 'open ' + d +'/%s' %app.replace(' ','\ ')
records.append(record)
现在,我们已经将所有的语音命令和系统命令相互映射。接下来,打开一个终端,启动 elasticsearch。如果你是通过自制软件安装的,它会在你的路径中,所以只要输入elasticsearch
,它就会在默认端口 9200 上启动。
接下来,我们可以索引我们的数据,使其可搜索。我们启动 python 客户机,将数据放入名为voice_assistant
的新索引中。
from elasticsearch import Elasticsearch
from elasticsearch.helpers import bulkes = Elasticsearch(['localhost:9200'])
bulk(es, records, index='voice_assistant', doc_type='text', raise_on_error=True)
现在你的数据都可以在索引voice_assistant
中搜索到了。我们从下面的搜索函数中得到的response
变量是由被称为查询 DSL 的语言生成的。我们基本上是在语音命令上做一个简单的 TF-IDF 搜索,有些模糊——考虑到拼写错误/糟糕的转录。
def search_es(query):
res = es.search(index="voice_assistant", doc_type="text", body={
"query" :{
"match": {
"voice_command": {
"query": query,
"fuzziness": 2
}
}
},
}) return res['hits']['hits'][0]['_source']['sys_command']
现在尝试一下吧!search_es('open spotify')
应该返回我们将传递给os.system
也就是open /Applications/Spotify.app
的命令。因为我们将fuzziness
参数设置为 2,所以search_es('open spofity')
也将返回相同的内容,即使有拼写错误。
尽管这是一个很小的功能,但这里的关键是这个原则可以应用于许多不同的功能——Q & A、其他命令等等
在语音助手中将所有这些结合在一起
现在,我们可以将语音转换成文本,并对所有命令进行适当的索引,我们可以使用search_es
函数来访问这些命令。剩下的就是把它们绑在一起了!让我们创建一个寻找用户输入的脚本,当它得到用户输入时,它在我们的索引中搜索该命令,然后尝试运行它。唯一缺少的是一个短语来触发我们的聊天机器人,所以让我们再定义一个助手函数,这样我们就有一个关键字短语来激活它,我选择我的只是“嘿伙计”。
def activate(phrase='hey dude'):
try:
with mic as source:
r.adjust_for_ambient_noise(source)
audio = r.listen(source)
transcript = r.recognize_google(audio)
if transcript.lower() == phrase:
return True
else:
return False
使用这个触发器,我们现在可以更有选择地激活我们的实际搜索功能。在我们之前定义的函数的帮助下,我们可以将代码封装在一个无限循环中,这样它就会一直运行,等待我们激活它。我让我的助手在运行任何东西之前问我它能有什么帮助,显然你可以随意用你的名字替换“凯尔”。
import speech_recognition as sr
import os
from elasticsearch import Elasticsearch##start python client
es = Elasticsearch(['localhost:9200'])##initialize speech recognizer and mic
r = sr.Recognizer()
mic = sr.Microphone()while True:
if activate() == True:
try:
say("Hey Kyle, how can I help you today?")
with mic as source:
print("Say Something!")
r.adjust_for_ambient_noise(source)
audio = r.listen(source)
transcript = r.recognize_google(audio)
sys_command = search_es(transcript)
os.system(sys_command)
say("I opened that application for you")
except:
pass
else:
pass
需要注意的一点是——因为我们这里有所有的except
语句,一旦你启动了它,你就不能用键盘来中断它,你必须停止整个进程,或者如果你在 jupyter 中重启内核——请随意构建更合适的错误处理。
运行它,开始不分青红皂白地打开应用程序,因为你可以!很酷。只要确保你已经启动了elasticsearch
,并且定义了你所有的助手函数。
额外收获:用 Selenium 搜索谷歌的语音助手
打开应用程序很酷,但我肯定不会真的用它…让我的电脑自动搜索我说的任何东西是这个助手更好的用途。你或许可以使用requests
和BeautifulSoup
库对这部分进行更多的定制,但是如果你只是让selenium
打开一个 Chrome/Firefox/随便什么窗口为你搜索,那就真的没有意义了。
安装 selenium 和 web 驱动程序
只需使用pip
安装必要的 python 包,并确保您已经安装了想要使用的 webdriver 。我会用 chrome 的那个。
pip install selenium
从 python 搜索 google
用selenium
从谷歌搜索超级简单。我使用 Chrome 作为我的首选浏览器,所以我从下面的webdriver.Chrome()
开始使用 selenium。如果你用别的东西,请随意替换它。
from selenium import webdriver
from selenium.webdriver.common.keys import Keysdef search_google(query):
browser = webdriver.Chrome()
browser.get('[http://www.google.com'](http://www.google.com'))
search = browser.find_element_by_name('q')
search.send_keys(query)
search.send_keys(Keys.RETURN)
就是这样。Selenium 在一个窗口中打开谷歌,找到搜索栏,为我们键入内容,然后单击搜索按钮。您可以快速测试它,以确保它正常工作:
search_google('how to build a voice assistant in python')
谷歌搜索的语音助手
不像以前,我们没有一个弹性搜索索引来查找我们的信息——我们的搜索更加动态,我们必须做一些更简单的文本预处理。假设我们的查询将包含短语“search google for ”,我们可以在那里分割字符串,并将字符串的其余部分传递给我们的函数。
while True:
if activate() == True:
try:
say("Hey Kyle, how can I help you today?")
with mic as source:
print('Say Something!')
r.adjust_for_ambient_noise(source)
audio = r.listen(source)
transcript = r.recognize_google(audio) phrase = 'search google for ' if phrase in transcript.lower():
search = transcript.lower().split(phrase)[-1]
search_google(search)
say("I got these results for you")
else:
say('I only search google, sorry fam')
except:
pass
else:
pass
未来方向
酷,现在你也有一个语音助手不断听你搜索互联网或打开应用程序。你还可以做更多的事情:在同一个助手中把它们绑在一起(我不喜欢),整合新闻/天气 API,也许自动化电子邮件内容,在 elasticsearch 中放入你自己的自定义短语,为激活建立一个更复杂的模型,等等……但这只是一个不错的开始。希望你喜欢它!
构建皮肤病变分类 Web 应用程序
原文:https://towardsdatascience.com/building-a-skin-lesion-classification-web-app-16fd2c422b9d?source=collection_archive---------16-----------------------
使用 Keras 和 TensorFlow.js 对七种类型的皮肤病变进行分类
对卷积神经网络进行研究后,我对开发一种端到端的机器学习解决方案产生了兴趣。我决定使用 HAM10000 数据集构建一个 web 应用程序来对皮肤病变进行分类。在本文中,我将提供一些背景信息,并解释我在这个项目中学习的一些重要概念,包括迁移学习、数据增强、Keras 回调和 TensorFlow.js.
Photo by rawpixel on Unsplash
人工智能正在塑造我们周围的世界。我们每天都与机器学习触及的事物互动。从我们的歌曲和视频推荐到手机里的智能助手。但是这些都是人工智能的消费者应用,那么更大规模的人工智能呢?
“就像 100 年前电力改变了几乎所有事物一样,今天我真的很难想象一个我认为人工智能在未来几年内不会改变的行业。”——吴恩达
就我个人而言,我认为医疗保健是一个具有巨大深度学习潜力的领域。尽管我们的技术有了长足的进步,但今天仍然有一个问题仍然是一个重大问题。据报道,约 10%的死亡和 6%至 17%的医院并发症是由诊断问题引起的。想象一下,借助机器学习模型,帮助医疗专业人员诊断患者,将这一数字降至不到 5%。影响将是巨大的!
在我上一篇关于卷积神经网络的文章中,我谈到了计算机视觉是如何应用于各种行业的。我强烈建议您在这里查看。
关于皮肤癌的一些背景信息
- 美国每年被诊断出患有皮肤癌的人数高于其他所有癌症患者的总人数。
- 五分之一的美国人到 70 岁时会患上皮肤癌。
- 光化性角化病影响超过 5800 万美国人。
我想建立一个解决方案,利用回旋神经网络来帮助人们快速准确地分类不同类型的皮肤癌。我的主要目标是创建一个容易访问和有效的项目。我最终决定建立一个网络应用程序。
在这个项目中,我使用了公开的 HAM10000 数据集,其中包含了大约 10000 幅不同的皮肤病变图像。
皮损类别包括:
- 光化性角化病和上皮内癌(
akiec
):鳞状细胞癌的常见非侵袭性变体。它们有时被视为可能进展为浸润性鳞状细胞癌的前体。 - 基底细胞癌(
bcc
):一种常见的上皮性皮肤癌,很少转移,但如果不治疗就会生长。 - 良性角化病(
bkl
):分为三个亚组(脂溢性角化病、日光性雀斑样痣和扁平苔藓样角化病(LPLK))。这些组可能看起来不同,但在生物学上相似。 - 皮肤纤维瘤(
df
):一种良性皮肤病变,被视为良性增生或轻微创伤的炎性反应。 - 黑色素瘤(
mel
):一种可出现不同变体的恶性肿瘤。黑色素瘤通常(但不总是)呈混沌状态,某些标准取决于部位位置。 - 黑素细胞痣(
nv
):从皮肤镜角度看,这些变体可能存在显著差异,但通常在颜色和结构分布方面是对称的。 - 血管病变(
vasc
)
更多关于数据集或皮肤癌分类的信息请参考本文。
卷积神经网络模型的转移学习
Photo by Mika Baumeister on Unsplash
如果您一直在处理任何类型的数据,当您开发深度学习模型时,您会知道数据是最重要的东西。但是,大多数时候,您的数据集可能不够大,无法获得最佳性能。总的来说,我们谈论的是至少 50,000 幅图像。拥有大量层的网络训练也非常昂贵。如果您没有一个(或几个)令人惊叹的图形处理器,这可能需要很长时间。😢
迁移学习背后的整个理念是,您可以在一个大数据集上获取一个已经过预先训练的模型,对其进行修改,然后在您当前使用的数据集上对其进行重新训练。
正如我在上一篇文章中所解释的,卷积神经网络在图像中寻找不同的特征,比如边缘和形状。我们可以采用一个具有数百万个连接的神经网络,该网络已经接受了识别不同特征的训练,并通过“冻结”前几层来重新训练其中的一部分。在添加了一个完全连通的图层之后,仅通过对最后几个图层进行训练,我们就可以获得一个模型,该模型可以有效地识别基本特征,但做出的预测会很好地利用相关数据进行推广。
A diagram depicting the use of transfer learning to retrain layers of a network. Source.
Keras 应用程序库包括几个深度学习模型,包括 VGG16、VGG19、ResNet50、MobileNet 和其他一些模型。**他们都在 ImageNet 数据集上进行了训练,该数据集包含大约 1400 万张图像。**与我们的 10,000 幅图像数据集相比,这是一个非常明显的差异。
对于这个项目,我选择使用 MobileNet 架构,它针对计算能力较低的移动应用进行了优化。这种架构利用了深度方向可分离的卷积,这实质上有助于减少训练参数的数量,使模型更加轻量级。有关 MobileNet 的更多信息,请查看本文。
以下是我们在 Keras 可以做到的。
皮肤病变图像的预处理
关于 HAM10000 数据集的一个好处是所有的图像都是相同的大小,600x450。然而,在查看了图像的分布后,我们看到大多数图像属于黑色素细胞痣类。
Left: total number of images in each class. Right: number of training images in each class.
扩充训练数据
当涉及到增加我们可以处理的训练样本数量时,数据扩充是非常有用的。我们可以扩充训练数据,为此,我们使用来自 Keras 预处理库的 Keras ImageDataGenerator 类,它通过批量循环数据来生成具有实时扩充的批量张量图像数据。我们传递的一些参数是:
rotation_range
:随机旋转的度数范围width_shift_range
:表示图像可以移动的总宽度的一部分height_shift_range
:这表示图像可以移动的总高度的一部分zoom_range=0.1
:图像可以放大或缩小的部分horizontal_flip=True
:随机水平翻转输入vertical_flip=True
:随机垂直翻转输入fill_mode='nearest'
:输入边界外点的填充规范
我们可以通过运行下面的代码来声明一个扩充的数据生成器。我们的目标尺寸是 224x224,因为这是 MobileNet 输入层所需的尺寸。
编译模型
Keras 回调库提供了一系列有用的函数,可以在模型训练过程的几个阶段应用。这些函数可用于了解模型内部状态的更多信息。这个程序中使用的两个回调函数是ReduceLROnPlateau
和ModelCheckpoint
。
ReduceLROnPlateau
用于在某个模型指标停止改进时降低学习率。已经表明,一旦模型在几次迭代后停止改进,当学习率降低 2-10 倍时,模型通常会受益。一些重要的参数是:
monitor
:用于评估模型是否正在改进的指标factor=0.5
:学习率降低的因子patience=2
:具有相同精度的时期数,在此之后学习率降低mode='max'
:当模型停止改进时,降低学习率
ModelCheckpoint
用于在每个历元后保存模型。save_best_only=True
确保最佳模型不会被覆盖。
绘制预测的混淆矩阵
我们可以看到我们的模型具有可接受的性能,并且标签nv
的大量测试示例被正确分类。该模型对akiec
、bcc
、bkl
、nv
和vasc
的预测大多正确,但对df
的预测困难。该模型有时会将黑色素瘤(mel
)与黑色素细胞痣(nv
)以及nv
与良性角化病(bkl
)混淆。该模型仍有很大的改进空间,超参数的微调可能会有所帮助。
保存模型并将其转换为 TensorFlow.js
训练完模型后,我们可以在本地目录中找到 Keras 模型为model.h5
。我们可以通过运行以下代码将其转换为 TensorFlow.js 文件。
在浏览器中运行机器学习
TensorFlow.js 是 Google 流行的深度学习框架 TensorFlow 的 JavaScript 版本。它由一个低级核心 API 和一个高级层 API 组成。我认为 TensorFlow.js 非常酷的主要原因有两个。
- TensorFlow.js 和 WebGL 可以在任何种类的 GPU 上运行,包括 Nvidia、AMD 和 phone GPUs。
- 您可以将现有模型转换为 TensorFlow.js 模型,并轻松地重新调整它们的用途。
- 模型在浏览器中本地运行,这意味着用户的数据永远不会离开他们的计算机。
最后一点尤其重要,因为你显然可以想象,如果在线自我诊断变得普遍,这在未来将是多么重要。客户端的训练和推断有助于确保解决方案是隐私友好的!
你可以在这里找到我的项目的代码,在这里找到模型的现场版本。
关键要点:
- 当你不需要大量数据或计算能力时,迁移学习是有用的
- 数据扩充也是确保您有足够的训练数据来确保您的模型表现良好的另一种方法
- TensorFlow.js 让您可以在浏览器中和客户端轻松运行机器学习模型
感谢阅读!如果您喜欢,请:
- 在 LinkedIn 上添加我,关注我的媒体,了解我的旅程
- 留下一些反馈或者给我发邮件(alex@alexyu.ca)
- 与你的网络分享这篇文章
构建溶解度预测器
原文:https://towardsdatascience.com/building-a-solubility-predictor-e9390de6a8?source=collection_archive---------22-----------------------
科学名义下的神经网络
人们正在沉睡于 21 世纪最激动人心的事件之一;技术和科学的交汇点。就像两个星系碰撞一样,随着我们开始意识到并获得合作的好处,科学和技术正在继续模糊行业之间的界限。
The real tree of knowledge; science, arts, and technology
最引人注目的合作项目之一是人工智能和化学之间正在萌芽的新关系**。**的起点化学信息学加速了过去陈旧的研究过程,让工业和学术界的研究团队转向更快的化学创新。这些新的见解为研究开辟了新的途径,并释放出一个非常重要的副产品:数据。
我们对科学的理解让我们看到了更大的图景,现在比以往任何时候都更加明显的是,物理学和生物学、电子学和纺织以及其他任何领域之间几乎没有什么区别。我们的研究方法已经从经验主义转向更加数据驱动的方法,特别是当我们开始理解我们所拥有的数据中的潜在模式时。
数据有助于进行预测,运行模拟,并用于一整套计算过程,这些计算过程将科学方法的速度提高了好几年;随着我们收集的数据越来越多,速度只会越来越快。
尽管仍然供不应求,特别是与文本、数字和图像数据的巨大数据集相比,化学数据正在慢慢增加,并且一线希望是明显的;我们越来越接近技术融合。尤瓦尔·诺亚·哈拉里认为,正是数据/人工智能和生物学/生物技术的融合将决定人类的未来。如果生物学确实是数据的阴阳两极,那么物理学和化学就是这场婚姻的催化剂。毕竟:
生物只是活化学,化学技术上只是应用物理。
尽管如此,方向是明确的;我和化学是天作之合。
项目已解散
使用 SMILES 分子表示格式,我建立了一个能够预测给定分子溶解度的神经网络。在超过 1000 个数据点的数据集上训练,预测器能够以相当高的精度预测分子的溶解度。
该项目分为 4 个部分
- 导入、格式化和规范化带标签的 SMILES 数据集
- 将微笑转化为分子,然后转化为二进制指纹
- 构建深度神经网络模型
- 编译、拟合、训练和测试模型
使用与我的分子电荷分类器神经网络类似的技术,我将微笑字符串转换成每个 256 位的二进制指纹。这允许算法为每个输入神经元输入一位(因此有 256 个神经元输入层)。由于溶解度可能是负值,我使用了 tanh 激活函数,因为 tanh 表示负值。
作为损失函数,该项目使用带有 Adam 优化器的均方误差,因为两者都非常适合于单输出预测。利用我的 1000 个分子的数据集,我以 0.0005 的学习速率和 5 的批量大小训练算法,超过 200 个时期。1000 个微笑字符串中的 10%被保留作为验证数据。
经过训练,我意识到虽然损失确实在减少,但准确率一直低于 1%。在对潜在的错误进行了大量的努力之后,我意识到问题不在于算法或者我的数据预处理技术;问题在于数据本身。经过一些研究,我了解到溶解度是由成分和结构决定的。这是非常重要的,因为我的数据格式没有显示三维结构,只有分子的组成部分。
然而,更重要的是环境变量。温度和压力等外部条件会影响分子的溶解度。算法中没有指定这些条件,因此无法对算法进行训练。
从本质上讲,有一些因素可以增强和解决这些问题:
- 规定的环境参数
- 更多标记的数据点
- 一种更体贴的分子表示方法
最终,该算法未能以有意义的准确性预测被搁置的 10 种测试分子的溶解度。同样的算法可以用于其他目的,所以我把代码上传到了 Github。知识库包括 2 组数据和模型文件。
为了继续探索人工智能和化学之间的互利关系,必须记住一些必要的行动:
- 跨两个字段共享数据
- 与两个领域的专家合作
- 发展共同语言/共同点
- 发展势头并自动化流程
如果我们继续走这条路,可以毫不夸张地说,也许有一天,化学创新将掌握在我们人工智能创造的安全手中。
关键要点
- 随着科学、技术和工业的碰撞,未来取决于我们的创新
- 由于技术的发展,科学之间的界限正在被跨越;更确切地说,多亏了数据
- 神经网络受益于可用数据的激增,使得预测、分类和生成的结果更加准确
- A.I 从给定数据集中的模式中学习;如果没有相关性,人工智能的输出将会非常不准确。
- 当我们将我们的人力资源、语言和数据集中在一起时,我们可以更有意识地加速开发。
用 Tensorflow 对象检测 API 构建玩具检测器
原文:https://towardsdatascience.com/building-a-toy-detector-with-tensorflow-object-detection-api-63c0fdf2ac95?source=collection_archive---------0-----------------------
用数据做酷事!
这个项目是我的热门项目的第二阶段-Google tensor flow 物体检测 API 是实现图像识别最简单的方法吗?在最初的文章中,我使用 Tensorflow 提供的模型来检测 youtube 视频中的常见对象。这些模型在 COCO 数据集上进行训练,并在该数据集中包含的 90 个常见对象上运行良好。
这里我扩展了 API 来训练一个不属于 COCO 数据集的新对象。在这种情况下,我选择了一个到处都是的玩具。见下图 gif。到目前为止,我对 API 的性能印象深刻。这里强调的步骤可以扩展到您想要构建的任何单个或多个对象检测器。
Tensorflow Toy Detector~
你可以在我的 Github repo 上找到代码
- 收集数据
第一步是为您的项目收集图像。你可以从谷歌上下载它们,确保你在角度,亮度,比例等方面有很大的变化。在我的例子中,我创建了一个小飞机玩具的视频,并使用 Opencv 从视频中提取图像。这节省了我很多时间。我确保图像是从多个角度拍摄的。您还可以随机改变某些图像的亮度,以便探测器可以在不同的闪电条件下工作。总共 100-150 张照片就足够了。请看下面的一些样本图片:
Sample images
PS:由于视频是从我的 Iphone 上拍摄的,原始图像相当大——1920 x 1090。这将需要大量的内存,所以使用 PIL 调整大小来调整它们的大小到 500x300,保持纵横比。
2.注释图像
我用标签给图像加了注释。这是一个非常方便的工具,注释是以 Pascal VOC 格式创建的,这对以后很有用。用 Python 写的,接口用 Qt。我用 Python3 + Qt5 都没问题。参见注释图像示例。本质上,我们识别对象的 xmin、ymin、xmax 和 ymax,并将其与用于训练的图像一起传递给模型
Annotating using labelimg
3。创建 TFR 数据集
Tensorflow API 希望数据集采用 TFRecord 文件格式。这可能是最棘手的部分。然而 tensorflow 已经提供了几个方便的脚本让你开始使用——[create_pascal_tf_record](https://github.com/tensorflow/models/blob/master/research/object_detection/create_pascal_tf_record.py).py
和[create_pet_tf_record.py](https://github.com/tensorflow/models/blob/master/research/object_detection/create_pet_tf_record.py).
我可以使用[create_pet_tf_record.py](https://github.com/tensorflow/models/blob/master/research/object_detection/create_pet_tf_record.py)
进行最小的编辑,因为 labelimg 已经以正确的格式创建了注释。我还喜欢这个脚本随机抽取 30%的数据并创建一个验证 TFR 文件。
您还需要创建一个 label.pbtxt 文件,用于将标签名称转换为数字 id。对我来说,这很简单
item {
id: 1
name: ‘toy’
}
我在 github 上包含了 label_map.pbtxt 文件和 create_pet_tf_records.py 文件。如果你被困在某个地方,我强烈推荐 Tensorflow 提供的 Oxfort Pets 漫游。
4。创建模型配置文件
创建 TFR 数据集后,首先需要决定是使用现有模型并对其进行微调,还是从头构建。我强烈推荐使用现有模型,因为 CNN 学习的大多数特征通常是对象不可知的,并且微调现有模型通常是一个简单而准确的过程。请注意,如果你决定从头开始构建,你将需要远远超过 150 个图像和培训将需要几天时间。该 API 提供了 5 种不同的模型,这些模型在执行速度和放置边界框的准确性之间提供了一种平衡。请参见下表:
Tensorflow Detection Models
对于这个项目,我决定使用在 coco 数据集上训练的 faster _ rcnn _ resnet101。如果你想了解更多关于 RCNN 模型的知识,这是一个非常好的链接。
Tensorflow 提供了几个示例配置文件来开始使用。我决定使用 faster_rcnn_resnet101_coco 文件,并更新了文件中需要配置的任何路径。别忘了更新 num。班级也是。
5。训练模型
终于!所有困难(和无聊)的部分都完成了,我们可以开始训练模型了。由于我有一个合理的 GPU,我决定在当地培训。然而,你可以在云上训练。tensorflow 文档再次简化了这一过程,并提供了所有的步骤。
您可以同时在两个独立的终端上启动培训作业和评估作业。启动 tensorboard 监控性能。经过 2-3 个小时的训练,我可以看到总损耗下降到 0.077,精度达到 0.99。通过查看 Tensorboard 中的图像,我们可以看到模型很快变得准确。
Model gets accurate pretty quickly
6。测试模型
为了测试模型,我们首先选择一个模型检查点(通常是最新的)并导出到一个冻结的推理图中。这个脚本也在我的 github 上。我在我的 Iphone 上录制的新视频中测试了这个模型。正如在我的上一篇文章中,我使用 Python moviepy 库将视频解析成帧,然后在每一帧上运行 object detector,并将结果整理回视频中。
后续步骤
我注意到的几件事和对未来的额外探索
- 在测试过程中,我发现更快的 RCNN 模型有点慢。接下来,我将探索使用最快的模型——SSD mobilenet,看看准确性是否有明显下降
- 对于这个模型,我只是使用了 faster_rcnn_resnet101_coco 的模型配置文件中的默认参数。如果可以调整它们以获得更好的性能,这可能是值得探索的
- 稍加努力,这个过程可以扩展到其他类别
给我一个❤️,如果你喜欢这个职位:)希望你拉代码,并尝试自己。
我有自己的深度学习咨询公司,喜欢研究有趣的问题。我已经帮助许多初创公司部署了基于人工智能的创新解决方案。请到 http://deeplearninganalytics.org/来看看我们吧。
你也可以在 https://medium.com/@priya.dwivedi 的看到我的其他作品
如果你有一个我们可以合作的项目,请通过我的网站或 info@deeplearninganalytics.org 联系我
参考文献:
- 谷歌 Tensorflow 物体检测 Github
- 关于媒体的精彩文章给了我灵感和一些有用的提示
在几分钟内建立一个翻译系统
原文:https://towardsdatascience.com/building-a-translation-system-in-minutes-d82a154f603e?source=collection_archive---------1-----------------------
使用 OpenNMT-py 创建基线 NMT 模型
序列到序列(seq2seq)[1]是一种通用的结构,能够做许多事情(语言翻译、文本摘要[2]、视频字幕[3]等)。).关于 seq2seq 的简短介绍,下面是一些不错的帖子:【4】【5】。
肖恩·罗伯逊的教程笔记本【6】和杰瑞米·霍华德的讲座【6】【7】是牢牢掌握 seq2seq 技术细节的绝佳起点。然而,在处理现实世界的问题时,我会尽量避免自己实现所有这些细节。重新发明轮子通常不是一个好主意,尤其是当你对这个领域非常陌生的时候。我发现 OpenNMT 项目非常活跃,有很好的文档,并且可以开箱即用:
[## OpenNMT -开源神经机器翻译
OpenNMT 是一个工业级的开源(MIT)神经机器翻译系统,利用 Torch/ PyTorch…
opennmt.net](http://opennmt.net/)
还有一些更通用的框架(例如,[8] ),但是可能需要一些定制来使它适用于您的特定问题。
OpenNMT 有两个官方版本:
OpenNMT-Lua (又名 OpenNMT):用 LuaTorch 开发的主项目。
优化稳定的代码,适合生产和大规模实验。OpenNMT-py :使用 PyTorch 的 OpenNMT 的轻量版。
最初由脸书人工智能研究团队创建,作为 PyTorch 的一个样本项目,这个版本更容易扩展,适合于研究目的,但不包括所有功能。
在接下来的部分中,我们将使用 PyTorch 版本。我们将带您了解使用中等规模的数据集创建一个非常基本的翻译系统所需的步骤。
步骤 1:获取 OpenNMT-py
将 Github 上的 OpenNMT-py git 存储库克隆到本地文件夹中:
[## OpenNMT/OpenNMT-py
http://opennmt.net/ py torch 中的 OpenNMT-py -开源神经机器翻译
github.com](https://github.com/OpenNMT/OpenNMT-py)
如果您打算以后定制或扩展它,那么您可能希望在 Github 上派生存储库。自述文件中还建议:
Codebase 接近稳定的 0.1 版本。如果你想要稳定的代码,我们目前推荐分叉。
步骤 2:下载数据集
这里我们将使用来自AI Challenger——英汉机器翻译竞赛的数据集。这是一个拥有 1000 万对英汉句子的数据集。英语字幕是从英语学习网站和电影字幕中提取的会话英语。从我的了解来看,大部分的翻译都是爱好者提交的,不一定是专业人士。翻译的中文句子由人工注释者检查。
[## 英汉机器翻译- AI 挑战者
英汉机器翻译-奖金:30 万-提高英汉机器翻译的性能…
challenger.ai](https://challenger.ai/competition/translation/subject?lan=en)
下载数据集需要注册帐户,可能还需要进行身份验证(不记得后者是否是强制性的)。如果这对你来说是个问题,你可以试试来自 WMT17 的数据集。
AI Challenger 数据集存在一些问题:1 .翻译的质量不一致。2.因为许多句子来自电影字幕,所以翻译通常依赖于上下文(与上一句或下一句相关)。但是,数据集中没有可用的上下文信息。
让我们看看现成的模型在这个数据集上的表现。由于内存限制,我将数据集下采样到100 万个句子。
(我们假设您将数据集放入 OpenNMT 根目录下的文件夹 挑战者 。)
步骤 3:将数据集转换为纯文本
验证和测试数据集采用 XML 格式。我们需要将其转换为纯文本文件,其中一行由一个句子组成。一个简单的方法就是使用 BeautifulSoup。下面是一段示例代码:
with open(input_file, "r") as f:
soup = BeautifulSoup(f.read(), "lxml")
lines = [
(int(x["id"]), x.text.strip()) for x in soup.findAll("seg")]
# Ensure the same order
lines = sorted(lines, key=lambda x: x[0])
第四步:标记英语和汉语句子
输入的句子必须用空格分隔的标记来标记。
对于英语来说,有一些标记符可供选择。一个例子是nltk.tokenize.word_tokenize
:
with open(output_file, "w") as f:
f.write(
"\n".join([
" ".join(word_tokenize(l[1]))
for l in lines
])
)
它变成“这是一个整洁的一-二。沃克给伯顿。”变成“这是一个整洁的一-二。沃克呼叫伯顿。".
对于中文,我们使用最简单的字符级记号化,也就是把每个字符当作一个记号:
with open(output_file, "w") as f:
f.write(
"\n".join([
" ".join([c if c != " " else "<s>" for c in l[1]])
for l in lines
])
)
It turns “我就一天 24 小时都得在她眼皮子底下。” into “我 就 一 天 2 4 小 时 都 得 在 她 眼 皮 子 底 下 。”. (Note because the token are space-separated, we need a special token “” to represent the space characters.)
(我没有提供第 3 步和第 4 步的完整代码,因为这真的是初级 Python 编程。你应该能够独立完成这些任务。)
步骤 5:预处理数据集
只需在根目录下运行以下命令:
python preprocess.py -train_src challenger/train.en.sample \
-train_tg challenger/train.zh.sample \
-valid_src challenger/valid.en \
-valid_tgt challenger/valid.zh \
-save_data challenger/opennmt -report_every 10000
预处理脚本将遍历数据集,跟踪标记频率,并构建一个词汇表。我在这里遇到了内存问题,不得不将训练数据集向下采样到一百万行,但是我认为原始数据集经过一些优化后应该适合 16GB 的内存。
第六步:训练模型
python train.py -data challenger/opennmt \
-save_model models/baseline -gpuid 0 \
-learning_rate 0.001 -opt adam -epochs 20
它会用你的第一个 GPU 来训练一个模型。默认的模型结构是:
NMTModel (
(encoder): RNNEncoder (
(embeddings): Embeddings (
(make_embedding): Sequential (
(emb_luts): Elementwise (
(0): Embedding(50002, 500, padding_idx=1)
)
)
)
(rnn): LSTM(500, 500, num_layers=2, dropout=0.3)
)
(decoder): InputFeedRNNDecoder (
(embeddings): Embeddings (
(make_embedding): Sequential (
(emb_luts): Elementwise (
(0): Embedding(6370, 500, padding_idx=1)
)
)
)
(dropout): Dropout (p = 0.3)
(rnn): StackedLSTM (
(dropout): Dropout (p = 0.3)
(layers): ModuleList (
(0): LSTMCell(1000, 500)
(1): LSTMCell(500, 500)
)
)
(attn): GlobalAttention (
(linear_in): Linear (500 -> 500)
(linear_out): Linear (1000 -> 500)
(sm): Softmax ()
(tanh): Tanh ()
)
)
(generator): Sequential (
(0): Linear (500 -> 6370)
(1): LogSoftmax ()
)
)
源语料库和目标语料库的词汇量分别为 50,002 和 6,370。源词汇明显被截断到 5 万。目标词汇量相对较小,因为没有那么多常用汉字。
步骤 7:翻译测试/验证句子
python translate.py \
-model models/baseline_acc_58.79_ppl_7.51_e14 \
-src challenger/valid.en -tgt challenger/valid.zh \
-output challenger/valid_pred.58.79 -gpu 0 -replace_unk
把models/baseline_acc_58.79_ppl_7.51_e14
换成自己的型号。模型命名要明显:这是一个经过 14 个历元训练的模型,在验证集上的准确率为 58.79,困惑度为 7.51。
您也可以使用以下公式计算 BLEU 分数:
wget [https://raw.githubusercontent.com/moses-smt/mosesdecoder/master/scripts/generic/multi-bleu.perl](https://raw.githubusercontent.com/moses-smt/mosesdecoder/master/scripts/generic/multi-bleu.perl)perl multi-bleu.perl challenger/valid.zh \
< challenger/valid_pred.58.79
现在你有一个工作的翻译系统!
步骤 8:(可选)对输出进行去爆震和转换
如果你想把翻译提交给 AI Challenger,你需要把步骤 4 反过来,然后是步骤 3。同样,它们应该很容易实现。
一些例子
English: You knew it in your heart you haven’t washed your hair
Chinese(pred): 你心里清楚你没洗头发
Chinese(gold): 你心里知道你压根就没洗过头
English: I never dreamed that one of my own would be going off to a University, but here I stand,
Chinese(pred): 我从来没梦到过我的一个人会去大学,但是我站在这里,
Chinese(gold): 我从没想过我的孩子会上大学,但我站在这,
English: We just don’t have time to waste on the wrong man.
Chinese(pred): 我们只是没时间浪费人。
Chinese(gold): 如果找错了人我们可玩不起。
以上三个例子,从上到下分别是语义正确、部分正确、完全无法理解。在检查了几个例子后,我发现大多数机器翻译的句子是部分正确的,而且语义正确的句子数量惊人。考虑到我们到目前为止付出的努力如此之少,这个结果还不错。
下一步
如果你提交结果,你应该绕过 .22 BLEU。目前最高 BLEU 分数为 .33 ,有很大的提升空间。您可以查看根文件夹中的opts.py
,了解更多内置模型参数。或者深入代码库,弄清楚事情是如何工作的,哪里可以改进。
其他途径包括对中文句子进行分词、添加命名实体识别、使用发音词典【10】对未见过的英文名称进行猜测翻译等。
(2017/10/14 更新:如果你使用 jieba 和 jieba.cut 默认设置对中文句子进行分词,你会绕过 .20 BLEU 上的公共 leaderboad。得分下降的一个可能原因是它的中文词汇量大得多。从输出中的 < unk > 的数量就可以看出来。)
参考资料:
- Sutskever,I .、Vinyals,o .、& Le,Q. V. (2014 年)。用神经网络进行序列对序列学习。
- 【纳尔拉帕提,r .】,周,b .【多斯桑托斯,c .】向,B. (2016)。使用序列到序列的 RNNs 和超越序列的抽象文本摘要。
- Venugopalan,s .、Rohrbach,m .、Donahue,j .、Mooney,r .、Darrell,t .、& Saenko,K. (2015)。序列到序列
- 序列对序列模型:介绍和概念
- seq2seq:深度学习的小丑车
- 实用 PyTorch:用一个序列翻译成序列网络及注意事项
- 程序员的前沿深度学习,第 2 部分,第 12 讲——注意力模型
- 面向编码人员的前沿深度学习,第 2 部分,第 13 讲——神经翻译
- Google/seq 2 seq:tensor flow 的通用编解码框架
- CMU 发音词典
打造 AI 聊天机器人!
原文:https://towardsdatascience.com/building-an-ai-chat-bot-e3a05aa3e75f?source=collection_archive---------1-----------------------
第五章:用数据做酷事!
特定领域的聊天机器人正在成为现实!使用深度学习聊天机器人可以“学习”提供给它的主题,然后能够回答与之相关的问题。像这样的技术的应用是无止境的。你只需提供关于某个主题的数据,然后看着机器人成为这方面的专家。
在这个博客中,我们将建立一个可以回答逻辑推理问题的博客。是的,这是可以做到的!见下图 gif:
链接到我的 GitHub 用 Python 写的完整代码。
我们是这样做的:
数据:这里使用的数据是由脸书人工智能研究所开源的。bAbI 数据集由脸书创建,旨在实现自动文本理解和推理。这是一组 20 个问答任务,每个任务由几个上下文问答三元组组成。每个任务旨在测试推理的一个独特方面,因此,适合测试 QA 学习模型的特定能力。
下面是第二个任务中的一个例子,两个支持事实(QA2):
约翰搬到了卧室。玛丽在那里抓起了足球。桑德拉去了卧室。桑德拉回到了走廊。玛丽搬到了花园。玛丽去了办公室。
问题:足球在哪里?
答:办公室基于报表 2、6
每个问题有 1000 个训练例子。该数据集具有合成生成的故事,因此词汇非常有限,并且句子形式非常受限。一方面,这些限制使 bAbI 成为学习的理想数据集——不需要进行太多的数据清理,人们可以专注于模型构建。另一方面,他们对在一个控制不那么严格的环境中把 bAbI 上的结果推广到 QA 的能力提出了质疑。
深度学习模型:对于这个问题,我们使用了一个端到端的记忆网络,它是由脸书人工智能研究所设计的。
让我们首先讨论为什么带有 LSTM 细胞的递归神经网络不能很好地解决这个问题。
- 数据可能不得不无序访问。请参见下面的示例:
2.如果我们想通过网络“记忆”一本书或一段视频,我们需要长期记忆,而 LSTM 细胞实际上对长期记忆问题不起作用
端到端存储器网络使用外部存储器来解决这个问题。并且它可以在数据中执行多次查找(跳跃)来解决无序数据问题。简单来说这是什么意思?
该型号有两个模块—内存模块和控制器模块。记忆模块把我们要讲的故事写成了向量。由于计算机无法理解单词,我们需要将单词转换成数字/向量。我们不是将每个单词都转换成一个数字,而是使用一种叫做嵌入的技术,这种技术赋予意思相似的单词相似的向量。例如,由于单词“拾起”或“举起”具有相似的含义,因此它们将具有相似的向量,这有助于机器更好地理解单词之间的上下文。张量流嵌入功能可用于生成单词到向量。
控制器模块将被询问的问题写成向量。请参见下面的示例:
然后我们做控制器函数和记忆向量的点积。然后我们做一个 softmax,将总概率缩放到 1。并且这被传递回控制器。在上面的例子中,因为这个神经网络考虑了句子的顺序,所以它给第二个句子较高的权重。我们可以把得到的概率(上面的 0.1,0.7,0.2)看作是暗示网络“关注”哪个向量。
这个过程可以重复几次(也称为跳跃),控制器有能力学习和重新查看存储向量,并再次做出选择。请看下面网络如何通过建立在前一跳中学到的知识来关注不同的向量
最后,输入被传递到一个解码器和向量,并转换成文字。
这是一个相当复杂的神经网络架构,是该领域的前沿技术。如果您想了解更多信息,请参考下面的参考资料。
总的来说,这对我来说是一次很棒的经历,我对学到的东西很满意。
其他著述:【https://medium.com/@priya.dwivedi/】T2
PS:我住在多伦多,我希望将职业生涯转向深度学习。如果你喜欢我的帖子,并能把我联系到任何人,我将不胜感激:)。我的电子邮件是 priya.toronto3@gmail.com
参考文献:
Udacity 深度学习纳米学位为我提供了详细探索这个领域的动力
Keras 巴比记忆网络
脸书研究论文
Stroh 和 Mathu 的研究论文
http://smerity.com/articles/2015/keras_qa.html
端到端存储网络的好解释:【https://youtu.be/ZwvWY9Yy76Q
用纯数字构建人工神经网络
原文:https://towardsdatascience.com/building-an-artificial-neural-network-using-pure-numpy-3fe21acc5815?source=collection_archive---------0-----------------------
神经网络因其在计算机视觉和自然语言处理等几个领域的出色表现而备受关注。它们不仅远远超过同类产品,而且用途极其广泛,几乎应用于所有可以想象的领域。
但是这两个词到底是什么意思呢?
在这篇简短的帖子中,我们将深入研究神经网络的概念,然后用 Python 编写我们自己的代码,使用 pure NumPy 对 MNIST 数字进行分类(我保证这很有趣)**。**我会尽量保持简短,主要是为了防止你因为我不专业的写作风格而关闭这个标签。所以让我们直入主题:
神经网络到底是什么
顾名思义,神经网络是一种受我们大脑中生物网络启发的计算系统。如果你没有像我一样在整个生物课上睡觉,你可能会记得我们大脑中的网络由大量的神经元组成。
出于我们的目的,我们可以将这个神经元建模为一个函数,它接受一组输入,使用一些权重获得这些输入的加权和,添加一个 偏差 ,并基于一些 激活 函数输出一个数字。有道理?我也这么想 lol。
Mathematical working of a single neuron
权重可以被认为是一串旋钮,我们可以调整它们来获得不同的输出。
偏置是另一个旋钮,它决定神经元何时保持不活动,或者换句话说,它决定神经元需要多高的加权和才能有意义地活动。
激活功能是将 logit 功能的任意输出映射到任何特定范围值的功能。它通常用于给我们的模型增加一些非线性。这允许网络以更复杂的方式组合输入,并且反过来在它们可以建模的功能中提供更丰富的能力。最常用的激活函数有 sigmoid、softmax、ReLU、tanh 等。
网络的结构
现在我们知道了单个神经元是如何工作的,我们可以将它们连接起来,以层的形式形成一个网络。所以人工神经网络只是一个被高估的复合函数。
A simple neural network. Also called a multilayered perceptron
典型的神经网络由 3 种类型的层组成:
- ***输入层:*给定的数据点馈入该层。只能有一个输入层。这一层中神经元的数量等于输入的数量。
- ***隐层:*这是全网的肉。这些层试图在输入中找到模式,以获得我们需要的输出。网络可以有任意数量的隐藏层。
- 输出层:这一层给我们网络的预测,即。给定当前参数(每个神经元的权重和偏差),网络认为应该正确的输出。这一层神经元的数量等于我们需要预测的值的数量。因为我们的任务是分类 MNIST 数字,我们将有 10 个神经元,因为有 10 个数字来计算预测。
因此,基本网络层可以定义为:
该层处理输入,最终产生输出值。这称为层上的向前传递。
在我们的实现中,我们将使用两个层:
- 密集层——其中一层中的每个神经元都与下一层中的每个神经元相连。
- ReLU 激活层 —位于密集层之上的层,将 ReLU 激活功能应用于密集层的输出。我本来可以使用最常见的 sigmoid 函数,但是我有时会尝试使用 ReLU 函数。
ReLU activation function
这两层可以定义为:
训练网络
既然我们已经定义了网络的架构,我们究竟该如何训练它呢?是的,使用 参数, 即权重和偏差。
由于我们的网络有不止一个神经元,每个神经元都有一套独特的权重和偏好,这给了我们数千个旋钮来调整。如果你是一个小小的受虐狂,愿意手动调节这些成千上万的旋钮,以获得最佳的组合,那就继续吧。如果你是正常人,那么我们可以利用梯度下降算法。
梯度下降是一种通用算法,可用于优化任何微分函数。它的工作方式是计算函数在当前点的梯度*。这种梯度给我们的方向,将最大限度地发挥功能(梯度口音)。但是我们通常需要最小化一个函数,所以我们把计算出的梯度的方向反过来得到最小化函数的方向(梯度下降)。如果你和我一样有点慢,你可以把它想象成一个球滚下山坡,由于重力的原因,它最终到达最低点。*
为了优化我们的网络,我们需要这样一个函数,所以我们定义了一个损失函数——我们使用的这个函数被称为 log softmax 交叉熵损失(再次变得尖锐)。
A scary-looking loss function
让我们一个字一个字地分解它:
- Softmax
Softmax 函数获取一个 N 维实数向量,并将其转换为(0,1)范围内的实数向量,其总和为 1。因此,它输出一个概率分布,这使得它适合于分类任务中的概率解释。
Softmax function
Graph of Softmax function
2.交叉熵损失
交叉熵表示模型认为的输出分布和原始分布之间的距离。
Cross-Entropy Loss
让我们用代码来写:
所以我们训练网络的方法如下:将网络的输出与预期输出进行比较,计算损耗。这种损失然后通过网络一次一层地传播回来,并且根据它们对误差的贡献量来更新权重和偏差。这种传播由反向传播算法执行。
这个算法相当复杂,需要一整篇文章来解释,所以我只告诉你几分钟,因为我很懒。
因此,对于每一层,为了计算该层参数对总损耗的影响,我们需要计算损耗对这些参数的导数。为了减轻我们的麻烦,我们可以利用链式法则。
Backpropagation Cheat Sheet
因此,对于每一层,我们可以添加一个后向通道,其中该层的梯度作为输入,用于计算所需的导数,最后,该层的梯度作为输出返回:
运行代码
下面给出了带有精度图的完整代码
Accuracy Plot
谢谢你坚持到最后。写这篇文章确实帮助我在大脑中巩固了一些复杂的概念。这是我第一次尝试写技术文章,如果有人有什么指点,请在下面留下回应!
构建端到端数据科学项目
原文:https://towardsdatascience.com/building-an-end-to-end-data-science-project-28e853c0cae3?source=collection_archive---------4-----------------------
从我的数据科学家理想概况项目中获得的经验
Photo by Joseph Barrientos on Unsplash
It 人们常说,数据科学家的大部分工作不是实际的分析和建模,而是数据争论和清理部分。因此,涉及这些阶段的全周期数据科学项目将更有价值,因为它们证明了作者独立处理真实数据的能力,而不是给定的清理数据集。
充分理解端到端数据科学项目的价值,我一直想建立一个,但直到现在还不能:)
我最近完成了我的理想简介项目。由于这是一个涉及许多活动部分的大项目,我想记录这个过程和学到的教训,这是一个进一步学习的机会(受威廉·科尔森关于数据科学写作价值的伟大帖子的启发)。
阶段
在我看来,一个全周期的数据科学项目应该包括以下几个阶段:
从事 Kaggle 项目的最大反对理由通常是它只关注第二阶段。因此,在这个项目中,我确保涵盖了所有三个阶段。
在第一阶段,我做了网络搜集来获取数据,由于数据是脏的,我不得不努力让数据为分析做好准备。然后我做了各种数据可视化,并进行分析,作为第二阶段。最后,我写了一些帖子来交流我的发现,并将这个项目投入生产。
当然,我可以通过加入机器学习组件来使这个项目更加完整,例如,使用 NLP 根据内容对职位发布进行分类,但这将大大延迟项目完成时间,这将我们带到下一点:
迭代思维
潜在地,对于一个给定的项目,可能有无限的事情要做,但是实际上,我们只有有限的时间。为了协调这两个相互竞争的因素,我们需要自律。
对我来说,“迭代思维”真的很有帮助——瞧,罗马不是一天建成的,所以让我们先建造一些可以工作的东西,然后我们可以随时回来改进更多的功能。另一方面,这也意味着我们需要能够处理“不完美”,不要拘泥于细节。
有了这个理念,我可以推迟一些非常诱人的功能,把它们放在项目文档的待办事项部分。其中之一是使用一个更大的数据集,从美国而不是加拿大的网站抓取数据。
模块化
鉴于项目的端到端性质,有许多不同的方面要做——网页抓取、数据预处理、绘图……如果我们将所有代码放在一个 Jupyter 笔记本中,管理起来会太长太复杂。然后我决定使用 Python 脚本结合中央 Jupyter 笔记本来解决这个问题。
我将支持功能分为三大类,并将它们放在三个相应的脚本中:
- scrape_data.py —包含 web 抓取所需的函数,如“get_soup()”和“get_urls()”
- process_text.py —包含文本处理和清理功能,如“tokenize_text()”和“check_freq()”
- helper.py 包含文件 I/O 和绘图功能,例如“plot_skill()”
通过这种方式,我能够保持一个超级轻和有组织的中央笔记本。然后根据需要从笔记本中导入和调用函数,如下所示:
**from** **scrape_data** **import** *
**from** **process_text** **import** *
**from** **helper** **import** *
再现性
由于我在网上找到的许多抓取脚本都不起作用,我决心确保我的项目是可重复的。除了可靠的代码之外,强大的自述文件和完整的环境依赖文件也是解决方案的一部分。
- README.md —我付出了艰苦的努力,以确保所有相关的细节都被捕捉到,尤其是如何设置环境以及如何使用脚本。
- env _ ideal _ profiles . YAML—通过将所有依赖项冻结到这个文件中,我确保用户可以准确地重新创建我使用过的同一个 Anaconda Python 环境。更多信息请点击这里。
编码最佳实践
良好的编码实践很重要!特别是,我发现以下实践在编写更大更复杂的项目时非常有用:
- 写清楚、简洁和信息丰富的评论
- 具有有意义的描述性变量/函数名
- 提供详细的和结构化的文档字符串
- 确保使用 Python“try except”块进行异常处理
当您的项目是一个 30 行的 Jupyter 笔记本时,这些事情可能看起来微不足道,但在处理一个需要数百行代码的大型项目时,这些事情真的非常重要!
Matplotlib 岩石
我过去习惯于只掌握基本的 Matplotlib 技能。然而,对于这个项目,我不仅需要将几个图合并成一个,而且还必须进行详细的定制,如旋转轴刻度标签…在这一点上,基本的 Matplotlib 技能根本不再足够。
事实证明这是一个学习 Matplotlib 的好机会。一旦我知道了它能做什么,我就发现不可能回头了,原因很简单,Matplotlib 真的很强大!它的面向对象的方法允许你修改几乎任何东西…查看下面的教程来找到答案:
- Matplotlib 教程:Python 绘图
- 有效地使用 Matplotlib
- 用 Matplotlib (Guide)进行 Python 绘图
这就是我最近完成的关于理想概要项目的最后一篇博文。另外两篇文章在这里和在这里可以找到。
你有什么想法?我错过了什么或者我可以改进的吗?请在下面随意评论。我欢迎任何反馈。
感谢您的阅读!
用 Python 构建 ETL 管道
原文:https://towardsdatascience.com/building-an-etl-pipeline-in-python-f96845089635?source=collection_archive---------3-----------------------
介绍
在我的上一篇帖子中,我讨论了我们如何设置一个脚本来连接 Twitter API 并将数据直接传输到数据库中。今天,我将向大家展示我们如何访问这些数据并对其进行分析,实际上是从头到尾创建一个完整的数据管道。大体上,我计划从我们的数据库中提取原始数据,清理它,最后使用 word clouds 和 NLP Python 库做一些简单的分析。
让我们想想如何实现这样的东西。为了使分析尽可能全面,我将采用面向对象的方法,创建一个 TweetObject 类和该类的方法来执行上述任务。我们将使用几个重要的库,比如 NLTK(自然语言工具包)库,它有一系列用于自然语言处理的有用函数。我们将使用单词云库来创建一些我们推文的摘要可视化,并使用一个名为 TextBlob 的库来帮助我们计算情感。
让我们先来看看 python 代码。
首先,我们导入必要的库。像我以前的文章一样,我们需要导入 mysql-connector 库来连接我们的数据库。TweetObject 类将初始化一些允许我们连接到数据库的重要参数。 MySQLConnect 方法接收一个 SQL 查询,执行它并返回一个 pandas 数据帧。Pandas 对于任何数据分析任务来说都是一个非常棒的库,它让操作数据变得非常容易,所以我建议任何有抱负的数据分析师/科学家熟悉这个库。
自然语言处理:清理推文
现在我们有了一个查询数据库并返回数据的方法,我们该如何处理它呢?让我们花一点时间来谈谈自然语言处理(NLP)。一般来说,文本数据需要一些预处理,然后才能输入到机器学习算法中。我们需要把它转换成一种算法可以理解的格式。这通常涉及以下一些任务。
自然语言处理中的预处理步骤:
- 正常化。
- 删除停用词、标点符号和 HTML。
- 象征化。
- 引理满足
- TF-IDF。
这当然不是一个详尽的列表,但这些是适用于大多数 NLP 任务的技术。好,让我们解释一下这些概念是什么,以及为什么我们需要使用它们。将单词标准化为小写是 NLP 中的正常步骤,因为我们不希望我们的算法将 python 和 PYTHON 视为两个不同的单词。将所有单词转换成相同的大小写可以避免这些问题。我们想采取的另一个步骤是从我们的文本中删除任何不相关的材料。一种方法是删除标点符号,如逗号、句号和停用词,如“I”、“is”、“the”。NLTK 包中停用词的更详细列表可以在这里看到。我们还应该考虑记号化,这是一个本质上把文本分割成有意义的块或记号的过程(TextBlob 自动为我们做这件事)。我们将使用的最后一个预处理技术是引理满足。这实质上是将一个词转换成它的“规范形式”。换句话说,巨蟒会变成巨蟒,而步行会变成步行。
一种非常有用的技术是术语频率-逆文档频率或 TF-IDF,但我们在这里没有使用。这是一种信息检索技术,它允许我们识别文档中单词的相对重要性。一般来说,如果一个单词在一个文档中出现多次,它可能是重要的。但是,如果它在多个文档中频繁出现,那么它可能只是一个普通的单词,实际上没有多大意义。TF-IDF 试图说明这一点,并返回每个单词重要性的总得分。当试图量化文档是关于什么的时候,这是一种广泛使用的技术,并且倾向于与诸如高斯混合模型(GMM)** 、 K 均值或**潜在狄利克雷分配(LDA)之类的算法一起使用。****
还有许多其他技术,我们可以利用,可能会改善我们的结果,如词干和 n 元语法,但我不会在这里进入这些。如果你想深入了解 NLP,网上有很多资源。
现在让我们回到我们的代码。下面的 clean_tweets 方法实现了上面提到的一些技术。特别是,它将所有的单词规范化为小写,拆分单词,词条,并且只保留不在停用词列表中的单词。它还去除了一些常见的 HTML,这些 HTML 往往出现在推文中,不会真正帮助我们的分析。
计算情绪
既然我们有了清理推文的方法,我们可以创建一个计算情绪的方法。TextBlob 库使 Python 中的情感分析变得非常简单。我们所需要做的就是将我们的文本传递到我们的 TextBlob 类中,在对象上调用invision . polarity方法,它返回 1、0 或-1,分别对应于积极、中立和消极的情绪。如果没有额外的参数传递给 TextBlob 类,那么默认情况下,text blob 类实现了许多文本处理函数,所以让我们快速浏览一下这些函数,以了解幕后发生了什么。
有四个参数,即标记器、 np_extractor 、 pos_tagger 和分析器,如果留空,则默认为某些方法。记号赋予器默认使用 WordTokenizer 方法,将文本分割成一个单词列表。如果我们将 np_extractor 留空,就会调用 FastNPExtractor 方法,根据文档返回一个名词短语列表,这对于识别特定句子或推文是关于什么的非常有帮助。例如,如果我们将这篇博客的第一段传递到 TextBlob 类中,并打印出名词短语,我们将得到下面的列表:
['twitter api ','流数据','完整数据管道','原始数据','简单分析','文字云',' nlp python']
接下来,调用 NLTK_tagger 来识别词类(POS ),比如一个单词是名词、动词还是形容词。最后,分析器默认为模式分析器,它返回我们的极性得分。正如我们所看到的,这个情感计算的代码非常简洁。极性得分以从-1 到 1 的范围返回,我们根据其值将其转换为情绪得分。
我们还创建了将我们的结果保存到 CSV 并创建单词云的方法。我真的很喜欢使用单词云,因为它们是总结文本数据的有效方式。它们提供了文本中单词数量的直观形象,其中较大的单词对应于较高的数量(单词出现得更频繁)。这使得更容易了解人们在推特上谈论的事情。
主要方法
接下来,我们有我们的主方法,它创建我们的对象并调用适当的方法。我们首先创建一个 TweetObject 类的对象,并连接到我们的数据库,然后调用我们的 clean_tweets 方法,该方法执行我们所有的预处理步骤。最后一步是用我们的情绪创建 3 个列表,并使用它们来获得积极、消极和中立的推文的总百分比。在我们运行这个之前,我们需要确保我们的 SQL 服务器在运行。否则,我们将无法连接到数据库并检索我们的数据。
结果
好,让我们看看这段代码产生了什么。正如我在之前的帖子中所说,我是一个高尔夫球迷,所以我决定在 2018 年大师赛的最后一轮比赛中收集推文。正如我们从下面的单词云中看到的,帕特里克·里德是出现频率最高的名字,这可能并不奇怪,因为他赢得了比赛。我们还看到其他一些高尔夫球手的名字,如乔丹·斯佩思和里基·福勒,他们在排行榜上仅次于里德。虽然这不是世界上最有洞察力的图表,但我真的很喜欢使用文字云来尝试从数据中得出一些初步的见解。还不完全清楚这些推文对这个词云的总体看法,但这就是为什么我们有 TextBlob 库。下面是我们情感计算的结果。特别是,我们计算了属于上述三类的推文的百分比。
我们的情感评分结果表明,大多数推文是正面的,约为 48%。还有一大群人看起来相当中立,为 39%。总的来说,我们可以从中收集到,推文总体上是积极的,但不是很多。这种方法的一个缺点是,我们可能无意中抓取了与高尔夫锦标赛完全无关的推文,而只是包含了我们的一些关键词。这是做任何类似分析时需要警惕的一件事。
结论
关于使用 SQL 和 Python 制作 ETL 管道的两部分系列文章到此结束。尽管我们的分析有一些优点并且非常简单,但是这种方法也有一些缺点。像所有类型的分析一样,总是要进行权衡,以及使用特定技术优于其他技术的利弊。最终,这个选择将取决于分析师,这些权衡必须根据他们试图解决的问题类型来考虑。
我们采用的方法的一个缺点是我们使用了现成的算法。不能保证我们的结果是非常准确的,不幸的是,如果不仔细阅读我们收集的推文,就无从得知。我们可以处理这个问题的一种方法是使用专门针对推文训练的情感算法,这可能会给我们带来改进的结果。
我们还可以进一步分析,尝试一些无监督的学习方法,比如聚类。这将帮助我们找到相似的推文组,并让我们对数据集有更深入的了解。GMM 也是一个值得尝试的有趣技术。这种算法试图做与聚类相同的事情,但具有更灵活的额外优势,允许我们以一定的概率将推文分配给多个组。这很好,因为我们可以将一定程度的不确定性纳入我们的估计。然而,我将把这些技术留到以后的文章中。
推荐课程:[GCP上的数据工程、大数据、机器学习](http://Data Engineering, Big Data, and Machine Learning on GCP)
完整的 Python 代码
领英:https://www.linkedin.com/in/daniel-foley-1ab904a2/
这篇文章中的一些链接是附属链接
构建运行在 Raspberry Pi 上的图像分类器
原文:https://towardsdatascience.com/building-an-image-classifier-running-on-raspberry-pi-a7a45153acc8?source=collection_archive---------6-----------------------
本教程讨论了如何使用 Raspberry Pi 接收对图像进行分类的 HTTP 请求,并使用分类标签进行响应。本教程首先构建物理网络,通过路由器将 Raspberry Pi 连接到 PC。准备好 IPv4 地址后,创建 SSH 会话,以便远程访问 Raspberry Pi。使用 FTP 上传分类项目后,客户可以使用 web 浏览器访问该项目以对图像进行分类。
树莓派
Raspberry Pi 是一种单板计算机,设计价格低廉,发展中国家的学生也买得起。Raspberry Pi 支持用 Python 编码,这就是为什么术语“Pi”可用的原因。树莓 Pi 3 型号 B 是最新的可用版本。它有一个四核 1.2 GHz CPU,1 GB RAM,Wi-Fi,蓝牙,一个 HDMI 端口,4 个 USB 端口,以太网端口,摄像头等。
Raspberry Pi 没有安装操作系统。操作系统可以装在插入主板 SD 卡插槽的 SD 卡上。可以使用 NOOBS(新的开箱即用软件)(https://www.raspberrypi.org/downloads/noobs)下载操作系统,这是一个操作系统管理器,可以轻松地将操作系统下载并安装到 Raspberry Pi。官方的 Raspberry Pi 操作系统被称为 Raspbian,这是专门为 Raspberry Pi 设计的 Linux 版本。它伴随着 NOOBS。NOOBS 也支持一系列操作系统供选择。
在 SD 卡中安装操作系统后,下一步是运行并访问它。访问 Raspberry Pi 的一种方式是使用以太网接口连接它。这种连接可以通过将其连接到 PC 的以太网接口来直接进行。有些电脑只有无线接口,根本不支持以太网。其他人可能在安装驱动程序时遇到问题。因此,我们可以避免将 Raspberry Pi 连接到 PC 的以太网接口,而是将其连接到路由器的一个以太网接口。PC 可以使用 Wi-Fi 连接到这样的路由器。
网络配置
假设 Raspberry Pi 和 PC 所在的局域网(LAN)使用范围从 192.168.1.1 到 192.168.1.254 的互联网协议版本 4 (IPv4)地址。即网络地址是 192.168.1.0,子网掩码是 255.255.255.0。使用动态主机配置协议(DHCP),IPv4 地址被动态分配给 PC 和 Raspberry Pi。我们可以在 Windows 中使用 ipconfig 命令(Linux 中使用 ifconfig 命令)轻松知道 PC 的 IP 地址。如下图所示,默认网关设置为 192.168.1.1,PC 的 IPv4 地址为 192.168.1.18。
为了知道分配给 Raspberry Pi 以太网接口的 IPv4 地址,将使用一个名为“高级 IP 扫描器”的程序。可以从这个页面下载https://www.advanced-ip-scanner.com。该程序接收一系列 IPv4 地址,并搜索活动地址。对于范围内的每个 IPv4 地址,该程序返回其状态、主机名、制造商和媒体访问控制(MAC)地址。通常,Raspberry Pi 的主机名或制造商名称中会包含“Raspberry”一词。这有助于我们确定哪个 IP 属于树莓派。下图显示了分配给路由器网关接口、PC 和签名为 192.168.1.19 的 Raspberry Pi 以太网接口的 IPv4 地址。
总之,下图显示了除分配的 IPv4 地址之外的 3 台设备(Raspberry Pi、路由器和 PC)。路由器中的一个以太网接口使用简单的电缆连接到 Raspberry Pi 的以太网接口。路由器以无线方式连接到 PC。
安全壳
建立物理连接后,我们需要从 PC 访问 Raspberry Pi。安全外壳(SSH)是一个很好的选择。SSH 会话可以使用不同的软件程序来创建,比如 XMing、Putty 和 MobaXterm。MobaXterm 是一款易于使用的软件,点击链接【https://mobaxterm.mobatek.net/download-home-edition.html】即可获得。下图是 MobaXterm 的主窗口。
重要提示:在建立 ssh 会话之前,必须在 SD 卡的根目录下添加一个没有扩展名的名为“SSH”的空文件。这是允许与 Raspberry Pi 建立 SSH 会话所必需的。这是通过将 SD 卡插入 PC 并添加此类文件来完成的。将 SD 卡插入 Raspberry Pi 后,我们就可以开始创建 SSH 会话了。
图标栏左上角的“会话”图标用于建立 SSH、Telnet 等会话。点击后,将显示如下图所示的窗口。
在点击最左边的 SSH 图标后,MobaXterm 会询问 Raspberry Pi 的远程主机名或 IPv4 地址,以便访问远程设备。我们可以使用 Raspberry Pi 的以太网接口的 IPv4 地址 192.168.1.19,如下图所示。
登录
如果物理连接工作正常,单击“OK”按钮后,将要求您登录以成功访问远程设备。Raspberry Pi 的默认登录用户名和密码是:
- 用户名 : pi
- 密码:树莓
正确输入这些详细信息后,会话将根据下图成功启动。只是有一个 Raspbian 终端用于与 Raspberry Pi OS 交互。请注意,MobaXterm 允许缓存以前会话中使用的密码,因此您不必每次登录时都输入密码。
您可能会注意到,SD 卡的内容显示在终端的左侧。这是因为 MobaXterm 支持使用文件传输协议(FTP)创建连接来上传和下载文件。这是一个非常有用的功能,可以节省很多时间。如果不使用 FTP,我们必须多次弹出和插入 SD 卡,以便向 Raspberry Pi 添加新文件。
X11 窗口系统
为了使初学者更容易与这样的操作系统进行交互,MobaXterm 使用 X11 窗口系统,该系统提供了一个图形用户界面(GUI)来与操作系统进行交互,而不是使用命令行。X11 为 Linux 操作系统提供了一个类似于 Microsoft Windows 的 GUI 显示框架。我们可以使用“ startlxde ”命令打开访问 GUI,如下图所示。
此时,我们可以使用 SSH 访问 Raspberry Pi,并能够使用 GUI 与之交互。这太棒了。使用只需 50 美元的 Raspberry Pi,我们就有了一个和我们在电脑上看到的一样的界面。当然,由于内存、SD 卡存储和 CPU 速度有限,它不会支持我们机器中的所有东西。
图像分类
接下来,我们可以开始构建图像分类器。完整的分类器是在本书中从零开始构建的“ Ahmed Fawzy Gad,使用深度学习的实用计算机视觉应用与 CNN,Apress,2019,978–1484241660”。
使用来自 Fruits 360 数据集的 4 个类来训练分类器。这个想法是使用 Flask 创建一个 web 应用程序,该应用程序存在于 Raspberry Pi 上的 web 服务器中,其中存在训练好的分类器。用户可以访问它上传和分类自己的图像。
在 FTP 的输出中有一个名为“ FruitsApp 的文件夹,它是先前上传到 Raspberry Pi 的。它包含项目文件。该项目有一个名为“ flaskApp.py 的主 Python 文件,用于实现 Flask 应用程序。还有其他补充的 HTML、CSS 和 JavaScript 文件用于构建应用程序的界面。为了运行应用程序,可以从终端执行 python " flaskApp.py "文件,如下图所示。
以下 Python 代码实现了 Flask 应用程序。根据代码的最后一行,可以使用 web 浏览器通过访问分配给 Raspberry Pi 的 IP 地址和端口 7777 来访问该应用程序。结果应用的首页是 http://192.168.1.19/7777 。
**import** flask, werkzeug, PIL.Image, numpy
app = flask.Flask(import_name=**”FruitsApp”**)**def** extractFeatures():
img = flask.request.files[**"img"**]
img_name = img.filename
img_secure_name = werkzeug.secure_filename(img_name)
img.save(img_secure_name)
print(**"Image Uploaded successfully."**)
img_features = extract_features(image_path=img_secure_name)
print(**"Features extracted successfully."**)
weights_mat = numpy.load(**"weights.npy"**)
predicted_label = predict_outputs(weights_mat, img_features, activation=**"sigmoid"**)
class_labels = [**"Apple"**, **"Raspberry"**, **"Mango"**, **"Lemon"**]
predicted_class = class_labels[predicted_label]
**return** flask.render_template(template_name_or_list=**"result.html"**, predicted_class=predicted_class)app.add_url_rule(rule=**"/extract"**, view_func=extractFeatures, methods=[**"POST"**], endpoint=**"extract"**)**def** homepage():
**return** flask.render_template(template_name_or_list=**"home.html"**)
app.add_url_rule(rule=**"/"**, view_func=homepage)app.run(host=**"192.168.1.19"**, port=7777, debug=**True**)
一旦用户访问主页,将显示一个 HTML 页面,要求上传图像。一旦上传了图像,将会调用“**extract features()”**函数。它提取特征,预测类标签,并根据下图在另一个 HTML 页面中呈现结果。上传的图片类标签是“苹果”。更多细节,请看[1]中的书。
了解更多详情
[1]“Ahmed faw zy Gad,使用深度学习与 CNN 的实际计算机视觉应用,Apress,2019,978–1484241660”。可通过以下链接获得:
- https://www . Amazon . com/Practical-Computer-Vision-Applications-Learning/DP/1484241665
- https://apress.com/us/book/9781484241660
- https://springer.com/us/book/9781484241660
联系作者
- 电子邮件:ahmed.f.gad@gmail.com
- 领英:https://linkedin.com/in/ahmedfgad/
- https://kdnuggets.com/author/ahmed-gad
- YouTube:http://youtube.com/AhmedGadFCIT
- 走向科学:https://towardsdatascience.com/@ahmedfgad
利用深度学习构建入侵检测系统
原文:https://towardsdatascience.com/building-an-intrusion-detection-system-using-deep-learning-b9488332b321?source=collection_archive---------3-----------------------
这实际上是我和我的小组为我们的计算机科学学士学位实施和完成的最后一年项目。
已经对入侵检测系统进行了大量研究,但是最大的变化发生在收集的数据集中,该数据集中包含许多入侵技术的样本,例如暴力、拒绝服务或者甚至来自网络内部的渗透。
随着网络行为和模式的改变以及入侵的发展,从静态和一次性数据集转向更动态生成的数据集变得非常必要,这些数据集不仅反映当时的流量构成和入侵,而且是可修改、可扩展和可再现的。
为此,我们将训练一个深度学习模型,从给定的数据集中识别异常。
由于机器学习在系统中的应用,基于异常的检测在入侵检测系统中是最有效的,因为它们不需要搜索任何特定的异常模式,而是将任何不匹配简档的东西视为“异常”。
注意:我不会在这里分享代码,但我会在最后给出 GitHub 上代码的链接。目的是启发用于实现成功的准确性的思想和实现。
我们开始吧:)
数据集
为此,我们将利用加拿大网络安全研究所收集的 ISCX 2012 数据集。您可以在下面的链接中找到它:
[## IDS 2012 |数据集|研究|加拿大网络安全研究所| UNB
CIC 和 ISCX 的数据集在世界各地被用于安全测试和恶意软件防范。
www.unb.ca](http://www.unb.ca/cic/datasets/ids.html)
在我们开始之前,通过使用 Matplotlib 库来检查每个类(正常和异常)包含了多少数据,来可视化实际数据集。
Image visualizing the anomaly data from the normal using Matplotlib library
我应该提到的是,在项目开始时,我们使用机器学习技术研究了许多关于入侵检测系统的论文,我们发现没有一篇论文利用了 ISCX 2012 数据集,这很可能是因为当时该数据集不可用。但是我们是第一批在入侵检测系统中使用数据集的公司之一。
环境
我已经创建了一个指南,非常详细地介绍了如何为深度学习设置你的系统
如果你碰巧正在使用 Keras API,但使用的是 Theano 或微软 CNTK 后端引擎,那么你也不错。否则,请遵循上述指南。
数据预处理
当被下载时,当 ISCX 数据集处于其原始状态时,对于深度学习模型是不可读的。PCAP 文件格式,因此,为了改变这一点,我们使用一个开源软件程序称为 ISCX 流量计来改变这一点。
git hub 上的 ISCX 流量计
这个流量计接收。PCAP 文件,并将它们转换成可读的。XML 文件格式,将每个数据部分堆叠为流,其中第一个数据包确定了向前(从源到目的地)和向后(从目的地到源)的方向。
以下是新转换的数据集的示例:
Part of the ISCX data in XML format
现在,我们只需要每个流中的两个数据:
- 目的地有效负载为 UTF:这是用户接收到的传入数据包
- 标记:这将上述有效载荷标记为正常或异常
因此,在数据集上运行流量计后,我们得到多个 XML 文件,从每个文件的每个树中提取两个主要数据值。然后,我们将有效载荷数据连接起来,使其长度为 7500,一旦完成,我们就将其重新整形为一个 50x50x3 维的 NumPy 数组。
当可视化时看起来像这样
Five data images from the ISCX data set
然后,我们垂直堆叠这些阵列,并添加一列,其中包括每个单独有效载荷的标签,即正常或异常。完成后,我们将数据保存到。NPY 文件,以便它可以用作深度学习模型的输入。
模型
我们尝试了不同模型的各种实验,但我们成功准确发现的一个实验是在 VGG-19 Keras 预训练模型上使用迁移学习技术。
VGG-19 Model Layout
我们没有使用预先训练的 VGG-19 的权重,因为我们的图像是定制图像,因此我们选择使用常规的异常检测技术在我们的图像集上训练模型,该技术包括两个阶段:
- **训练阶段:**创建正常有效载荷轮廓的阶段。通常情况下,不需要任何异常数据进行训练,因为在下一阶段,入侵检测系统会立即从配置文件中的数据中丢弃任何偏差最小的数据。
- **测试阶段:**将传入的有效载荷与配置文件中存储的数据进行比较的阶段。
在这样做的时候,我们在数据值上训练我们的模型,数据值的标签被标记为正常,反过来,它在第一个纪元就达到了 100%的精度。然而,随着异常数据值的引入,模型达到了 100%的不正确准确度,其结论是模型正确识别了正常数据,但是在异常情况下,模型只是绕过了正常数据而没有对其进行分类。
因此,我们在训练数据中同时使用了异常和正常数据,由于数据的性质,很明显这是一个异常检测问题。在测试阶段,我们获得了满意的结果,该模型能够以 100%的准确率识别正常数据,以 85%的准确率识别异常数据。考虑到我们的数据集,获得的结果是令人满意的
Accuracy graph of the model in 2 epochs
Scientific model evaluation of our model using Scikit-learn library
结论
通过对我们模型的成功识别,我们可以自信地宣称,我们的模型可以用作入侵检测系统应用程序的后端引擎,该应用程序可以安装在任何计算机网络的边界上
然而,明智的做法是进一步测试,如果需要的话,重新训练加拿大网络安全研究所发布的新数据集模型,即 IDS 2017 数据集。
[## IDS 2017 |数据集|研究|加拿大网络安全研究所| UNB
CIC 和 ISCX 的数据集在世界各地被用于安全测试和恶意软件防范。
www.unb.ca](http://www.unb.ca/cic/datasets/ids-2017.html)
这一举措将进一步验证我们的模型在检测异常方面的准确性,因此如果您希望在入侵检测或入侵防御系统中使用这一点,我强烈建议首先这样做,因为这将使模型保持更新。
GitHub 链接:https://GitHub . com/tamimmirza/Intrusion-Detection-System-using-Deep-Learning
我希望你喜欢这次旅行:)
构建并利用基于事件的数据模型来分析在线数据
原文:https://towardsdatascience.com/building-and-leveraging-an-event-based-data-model-for-analyzing-online-data-c166c523fe6a?source=collection_archive---------2-----------------------
2017 and beyond, you should only be using an event-based data model.. If you are not, your agility may be severely limited
如果您对这个主题足够感兴趣,您可能足够了解收集和分析事件是理解用户如何与应用程序交互的信息高速公路。但是让我们先退后一步,问一个这个想法所基于的问题:为什么我们首先要收集事件?
商业智能专家过去的迭代会从在购买过程的不同阶段收集的关于用户的人口统计和心理信息中推断出相当多的信息。很容易说,美国人比其他国家的人倾向于购买更多的东西,年轻人更倾向于网上购物。
但是人口统计学和心理统计学不会告诉你一切。研究表明,关于用户的行为数据在预测购买、升级和流失等方面非常有效。
在 Cooladata,我们遵循创始人 Tomer Ben Moshe 的格言:
“你是由你做的事情来定义的,而不是你是谁。”
这一理念不仅将我们公司凝聚在一起,而且渗透到我们的产品中,指导我们做出的每一个设计决策。Cooladata 是一个完整的系统,旨在实现对用户行为的快速分析和理解。
在这个用户行为的宇宙中,事件就是原子。当用户在您的网站、应用程序或数字资产中采取某种可衡量的行动时,该行动将被记录为一个事件。
一般定义
来自移动网络或 IOT 的在线数据基于事件,其中每个事件都有自己的属性,例如:
事件数据建模是使用业务逻辑存储事件级数据以产生“可分析的”数据的过程,这意味着更容易查询和理解用户行为。
事件数据模型通常包含 3 个主要的层次级别:
- 用户
- 会议
- 事件
用户
用户实体将包含关于用户的特定属性,例如:
- 电子邮件
- 邮政区码
- 手机号码
- 和其他属性
会议
会话实体将包含关于会话的特定属性,例如:
- 浏览器
- 设备
- 国家(IP)
- 推荐来源等。
事件
事件实体将包含每个事件类型的特定属性,例如:
- 登录事件:用户 ID、登录页面、推荐来源
- 添加项目事件:产品、价格、颜色、尺寸等。
- 结帐事件:总价、折扣、运送选项等。
挑战
传统的 BI 数据模型(如星型模式或雪花模式)包含具有固定结构的事实表和维度。
这对于分析数据来说是高效且易于使用的,但是它只适用于结构化的数据,并且模式变化不大。
基于事件的数据模型基于结构化和半结构化数据,例如:
- URL:在一个字符串中包含许多属性(页面、标题、活动等)。)
- DUA:设备用户代理包含许多关于会话的属性,如设备、浏览器、操作系统、位置等。
- 事件类型:每种事件类型都有不同的模式,因为它基于完全不同的属性,这使得使用传统的 BI 数据模型几乎不可能
事件数据结构也趋向于非常频繁地改变。这意味着您几乎每天都要添加字段和表。由于当今业务的快速发展,数据结构往往会快速变化(与 20 年前相比)。
对于新产品特性、新工具或新版本,您会发现自己需要一个基于事件的数据模型,该模型灵活、可伸缩,并且可以轻松地合并新事件。僵化的模式,如雪花或星型模式,根本不善于适应 21 世纪业务的快速变化的性质。
有几种方法可以构建基于事件的数据模型。下面,我们列出了 3 个最流行的,以及我们自己的版本。在我们开始之前,让我们看看基于事件的数据模型的一些最重要的考虑因素。
基于事件的数据模型的注意事项:
- 易用性 —使用 SQL 分析数据有多简单
- 性能 —最小化连接和全扫描
- 定价 —您可能希望使用更便宜的红移集群或降低 BigQuery 成本
- 易于填充 —将数据加载到模型中有多容易?完全加载、增量加载和更新数据
现在让我们仔细看看你的一些选择。
选项 1-每个事件类型的表+一个公共属性表
- 每种事件类型的事实表
- 每个事件类型表都包含事件属性的特定字段
- 所有事件类型的“所有事件”事实表,带有通用属性字段
赞成的意见
- 特定行为查询的良好性能。
例如:漏斗分析将在事件类型表之间创建连接,这比使用每个事件类型的子查询在所有事件上创建连接要高效得多。 - 为分析特定事件类型而优化。
例如:在 installs 表上分析“install”事件类型比在整个事件表上分析要有效得多。(即,分析“注册”事件将仅访问注册表。) - 您仍然可以使用“所有事件”事实表来分析具有共同属性的所有事件。
骗局
- 难以管理,尤其是在动态环境中。每当添加事件类型时,都需要添加一个反映 ETL、元数据和监控的表。
- 每种事件类型都需要一个新表。即使这种事件类型很少使用,您也需要为每种事件类型维护一个表。当您有数百种事件类型时,这变得难以管理。
- 通过拥有“all_event”表和“event_type”表,您可以复制数据。这需要更多的工作,并且很容易失去同步,导致数据质量问题。
选项 2 —通用事件表+定制属性的 JSON 字段
- 单个事件表
- 该表包含作为字段的公共属性
- 定制属性存储在 JSON 字段中
JSON
赞成的意见
- 比每个事件一个表格更容易管理。新的属性只是添加到 JSON 字段中,不需要管理许多 event_type 表。
- 易于分析常见事件属性。
例如:事件时间戳、用户标识、会话标识等。 - 您可以在事件表中存储用户和会话数据。(这叫做涂抹,帮助你管理缓慢变化的维度。)
骗局
- 难以分析自定义属性。您需要为每个查询从 JSON 字段中提取定制属性,这会导致性能下降。
- 代价高昂的
例如:在 Google BigQuery 中,从较大的 JSON 对象中选择少量数据的代价更高,因为 BigQuery 的定价是基于扫描大小(处理的字节数)的。 - 很难映射元数据并使用 BI 工具来定制属性,因为数据可能位于嵌套的 JSON 字符串中。
选项 3 —嵌套表数据模型
- 针对所有事件的单个事实表
- 同一层次结构中的公共属性
- 嵌套层次结构中的自定义属性
- 您可以为用户和会话数据创建层次结构
例子
赞成的意见
- 优雅且易于理解的数据存储方式。
- 每个层次的属性都很灵活。
- 对于某些查询,如 count distinct,性能良好。
- 某些查询(如 count distinct)将扫描更少的数据。
- 所有数据都包含在一个表中,减少了表之间的连接需求。
骗局
- 嵌套数据变得难以轻易查询。
- 难以将数据加载到表中,尤其是增量数据。
- 难以映射元数据和在嵌套数据模型上使用 BI 工具。包含嵌套数据的列需要相当复杂的已定义模式,以考虑这些列中可能发生的自描述 JSON 事件。
- 几乎不可能更新数据。
为了透明起见,我现在和 Cooladata 在一起,我们是利用基于事件的数据模型来收集和分析所有数据系统和孤岛中的用户行为的领导者。
以下是 Cooladata 选项的视图:
- 单个事件表
- 可以选择将特定的事件类型存储到不同的表中。
例如:流行的事件类型,比如“页面视图”,可以存储在一个单独的表中,其余的事件类型可以存储在一个单独的表中 - 该表包含作为字段的通用和自定义属性
- 该表包含每个事件行的用户和会话数据(涂抹)
赞成的意见
- 易于理解数据的存储方式。
- 通过将流行的事件类型存储在单独的表中,您可以获得最佳的性价比。
- 所有数据加载都由 Cooladata 处理。
- 你能够很容易地分析数据。
- 您可以轻松访问历史变化(缓慢变化的维度)。
骗局
- 为了获得最佳性能,您需要使用 CQL (Cooladata SQL)。
- 数据管理通过 Cooladata 进行。
附加 Cooladata 功能
物理模式
我们按照时间和属性对数据进行划分,例如事件类型、地理位置等。以获得最佳性能并优化数据访问。
我们将数据存储在一个稀疏的柱状分析数据库中,从而获得灵活性和性能。
语义层/元数据
我们从在线数据和传统数据中自动创建语义层和元数据。
优化的数据访问层(解析器)
我们的智能解析器翻译简单的 SQL 语句,以便能够访问相关的分区。
行为时间序列扩展(CQL)
我们扩展了 SQL,它是基于集合的,具有更多的功能,支持对粒度数据进行时间序列分析。
我们的技术提供了这些功能:
- 将事务性和基于在线的数据结合成一个连贯的流。
- 数据模型中基于文档的模式的灵活性。
- 在一个模式中进行全面的维度和时间序列分析。
- 能够在数据模型上使用常见的可视化工具。
- 临时统一在线和传统数据。
- 通过智能分区优化数据成本。
- 全面跟踪历史数据变化(渐变维度)。
- 按需提供数据分析师和数据科学家,帮助您构建数据模型和解释数据。
感谢阅读,希望你学到了一些东西。但
构建和测试一个简单的深度学习对象检测应用
原文:https://towardsdatascience.com/building-and-testing-a-simple-deep-learning-object-detection-application-b2e6f07b9fba?source=collection_archive---------1-----------------------
深度学习是目前的热点。非常性感。这是因为在感知领域,可用的数据比以往任何时候都多。我所说的感知是指诸如图像中的物体识别、自然语言处理、语音检测等任务。基本上,我们每天都会产生大量的数据。许多公司都很好地利用了这些数据。谷歌,脸书,英伟达,亚马逊等。因为他们可以访问这些数据中的大部分。作为用户,我们很乐意通过我们所有的社交媒体帖子和在线存储利用率将它提供给他们。在任何情况下,我都想让大家体验一下,你可以用一个相对较小的卷积神经网络来检测图像中的许多不同对象。具体来说,我们将使用一种称为 MobileNet 的网络架构,它可以在较小的设备上运行。幸运的是,你可以接触到预先训练好的模型并进行测试。这正是我们今天要做的。
数据基础
该模型已经在 COCO 数据集(上下文中的公共对象)上进行了训练。就像听起来这个数据集包含了很多我们在日常生活中经常看到的物体的图像一样。具体来说,它由 90 个不同物体的 30 万张图像组成,例如
- 水果
- 车辆
- 人
- 等等。
模型
我们使用的型号是“带 MobileNet 的单次多盒探测器(SSD )”,位于这里,下载需要一点时间。它是用谷歌的协议缓冲格式存储的。我知道你在想什么:为什么要发明另一种结构化存储格式?在谷歌的辩护中,这是非常酷的。基本上,它是一种语言中立、平台中立、可扩展的序列化结构化数据的机制——想想 XML,但是更小、更快、更简单。一旦定义了数据的结构化方式,就可以使用专门生成的源代码,使用各种语言轻松地将结构化数据写入各种数据流或从中读取。
卷积神经网络
A Generic Convolutional Neural Network Architecture with Kernel filters and Pooling layers
在我们查看结果之前,让我们快速介绍一下卷积神经网络到底是什么,以及为什么它们在图像分析方面比普通的多层感知器更成功。使用卷积神经网络背后的整个想法是,我们需要网络是平移和旋转不变的。这仅仅意味着我们需要能够识别一个物体,不管它在图像中的什么位置。实现这一点的一种方法是在图像上滑动对特定图案起反应的补丁。你可以把它想象成一个过滤器,当它检测到什么东西的时候就会亮起来。当然,我们不知道我们在寻找什么,因此这些过滤器是在训练中学习的。一般来说,在深度学习中,我们在初始层中学习较低级别的特征,而后面的层捕捉更精细的特征。这很酷,因为我们可以保存最初训练的早期层,并在其他模型中重用它们。
结果
下面的视频是我在建模团队工作时用手机拍摄的。正如你所看到的,这个模型确实很成功地识别了一些物体。但是它也没有检测到其中的许多。这有很多原因。其中之一是这个模型是针对速度而不是性能进行优化的。
Detecting Modelers using our convolutional neural network!
在这篇短文中,我向你展示了如何利用之前拟合的卷积神经网络对回顾视频中的对象进行分类。然而,这可以从网络摄像头或监控摄像机扩展到活动物体检测。如果你对自己做这件事感兴趣,看看 Tensorflow 的例子这里。
黑客快乐!
最初发表于doktormike . github . io。
一步一步地建立和测试推荐系统
原文:https://towardsdatascience.com/building-and-testing-recommender-systems-with-surprise-step-by-step-d4ba702ef80b?source=collection_archive---------1-----------------------
Photo credit: Pixabay
了解如何借助 Python 和惊喜库、协同过滤来构建自己的推荐引擎
推荐系统是数据科学最常用和最容易理解的应用之一。关于这个主题已经做了很多工作,由于互联网的快速发展和信息过载问题,人们对这个领域的兴趣和需求仍然很高。帮助用户处理信息过载并向他们提供个性化的推荐、内容和服务已经成为在线企业的必要工作。
推荐系统最流行的两种方法是协同过滤和基于内容的推荐。在本帖中,我们将重点介绍协同过滤方法,即:向用户推荐过去有相似品味和偏好的人喜欢的项目。换句话说,这种方法通过使用用户之间的相似性来预测未知的评级。
我们将与图书交叉,一个图书评级数据集一起开发推荐系统算法,与惊喜图书馆,它是由 Nicolas Hug 建立的。我们开始吧!
数据
图书交叉数据由三个表组成,我们将使用其中的两个:用户表和图书评级表。
user = pd.read_csv('BX-Users.csv', sep=';', error_bad_lines=False, encoding="latin-1")
user.columns = ['userID', 'Location', 'Age']
rating = pd.read_csv('BX-Book-Ratings.csv', sep=';', error_bad_lines=False, encoding="latin-1")
rating.columns = ['userID', 'ISBN', 'bookRating']
df = pd.merge(user, rating, on='userID', how='inner')
df.drop(['Location', 'Age'], axis=1, inplace=True)
df.head()
Figure 1
电子设计自动化(Electronic Design Automation)
收视率分布
ratings_distribution.py
Figure 2
我们可以看到,数据中超过 62%的评级为 0,极少数评级为 1 或 2,或 3,低评级书意味着它们通常非常糟糕。
图书收视率分布
ratings_distribution_by_book.py
Figure 3
df.groupby('ISBN')['bookRating'].count().reset_index().sort_values('bookRating', ascending=False)[:10]
Figure 4
数据中的大部分书获得的评分都在 5 分以下,极少数书获得了很多评分,尽管评分最高的书获得了 2502 分。
用户评分分布
ratings_distribution_by_user.py
Figure 5
df.groupby('userID')['bookRating'].count().reset_index().sort_values('bookRating', ascending=False)[:10]
Figure 6
数据中的大多数用户给出的评分少于 5 分,给出很多评分的用户也不多,尽管最有生产力的用户给出了 13,602 个评分。
我相信你已经注意到了上面两个图有相同的分布。每本书的评分数和每个用户的评分数呈指数衰减。
为了降低数据集的维度,避免陷入“记忆错误”,我们将过滤掉很少评级的书籍和很少评级的用户。
filter_dataframe.py
Figure 7
惊喜
为了从上面的 pandas 数据框加载一个数据集,我们将使用load_from_df()
方法,我们还需要一个Reader
对象,并且必须指定rating_scale
参数。数据框必须有三列,依次对应于用户 id、项目 id 和等级。因此,每一行对应于一个给定的等级。
reader = Reader(rating_scale=(0, 9))
data = Dataset.load_from_df(df_new[['userID', 'ISBN', 'bookRating']], reader)
借助惊喜库,我们将对以下算法进行基准测试:
基本算法
正常预测值
NormalPredictor
算法根据假设为正态的训练集分布预测随机评分。这是最基本的算法之一,不需要做很多工作。
仅基线
BaselineOnly
算法预测给定用户和项目的基线估计值。
k-NN 算法
KNNBasic
KNNBasic
是一种基本的协同过滤算法。
KNNWithMeans
KNNWithMeans
是基本的协同过滤算法,考虑了每个用户的平均评分。
KNNWithZScore
KNNWithZScore
是一个基本的协同过滤算法,考虑到每个用户的 z-score 归一化。
KNNBaseline
KNNBaseline
是一种考虑基线评级的基本协作过滤算法。
基于矩阵分解的算法
奇异值分解
SVD
算法相当于概率矩阵分解
SVDpp
SVDpp
算法是 SVD 的扩展,它考虑了隐式评级。
NMF
NMF
是一种基于非负矩阵分解的协同过滤算法。它与奇异值分解非常相似。
一号斜坡
SlopeOne
是 SlopeOne 算法的简单实现。
共聚类
Coclustering
是基于协同聚类的协同过滤算法。
我们使用“rmse”作为预测的准确性指标。
benchmark.py
Figure 8
训练和预测
BaselineOnly
算法给了我们最好的 rmse,因此,我们将使用BaselineOnly
和交替最小二乘法(ALS)进行训练和预测。
print('Using ALS')
bsl_options = {'method': 'als',
'n_epochs': 5,
'reg_u': 12,
'reg_i': 5
}
algo = BaselineOnly(bsl_options=bsl_options)
cross_validate(algo, data, measures=['RMSE'], cv=3, verbose=False)
Figure 9
我们使用train_test_split()
对给定大小的训练集和测试集进行采样,并使用 rmse 的精度度量。然后我们将使用fit()
方法在训练集上训练算法,使用test()
方法从测试集返回预测。
trainset, testset = train_test_split(data, test_size=0.25)
algo = BaselineOnly(bsl_options=bsl_options)
predictions = algo.fit(trainset).test(testset)
accuracy.rmse(predictions)
Figure 10
为了详细检查我们的预测,我们将建立一个包含所有预测的熊猫数据框。下面的代码大部分摘自这个笔记本。
predictions_details.py
最佳预测:
Figure 11
以上是最好的预测,不是侥幸的猜测。因为 Ui 介于 25 到 146 之间,所以它们并不小,这意味着大量用户对目标图书进行了评级。
最坏的预测:
Figure 12
最糟糕的预测看起来相当令人惊讶。让我们看看最后一个 ISBN“055358264 x”的更多细节。这本书被 47 个用户评分,用户“26544”评分为 10,我们的 BaselineOnly 算法预测该用户评分为 0。
import matplotlib.pyplot as plt
%matplotlib notebookdf_new.loc[df_new['ISBN'] == '055358264X']['bookRating'].hist()
plt.xlabel('rating')
plt.ylabel('Number of ratings')
plt.title('Number of ratings book ISBN 055358264X has received')
plt.show();
Figure 13
结果发现,这本书获得的大部分评分是 0,换句话说,数据中的大部分用户给这本书的评分是 0,只有极少数用户给了 10。与“最差预测”列表中的其他预测相同。似乎对于每一个预测,用户都是某种局外人。
就是这样!我希望你喜欢这个推荐(或者更确切地说,一个评级预测)之旅。 Jupyter 笔记本可以在 Github 上找到。节日快乐!
参考:惊喜’文档
构建人工通用智能
原文:https://towardsdatascience.com/building-artificial-general-intelligence-46b1380f1823?source=collection_archive---------5-----------------------
Building Artificial General Intelligence
从这个意义上来说,今年是一个不错的年份,我遇到了两个资源,它们帮助我更好地了解人工智能的当前状态,以及我们真正需要进入和建立一个“更高”级别的智能或俗称的人工通用智能(简称 AGI)。我希望向 AI 社区推荐这两个资源,并写下我的一些想法,希望能得到一个好的讨论。
论智力
所以第一个资源是我的朋友推荐给我的,这是一本名为《关于智力的书》,作者是杰夫·霍金斯,他是 Numenta 的创始人,正在进行新大脑皮层的逆向工程,研究大脑如何工作并创建一个通用计算模型。他们提出了这个被称为分级时间记忆的通用模型,简称 HTM。HTM 是一个结合了神经科学和机器智能的理论框架,我相信这是建设 AGI 的正确方向。
人工智能的当前状态已经看到了许多构建人工狭义智能的成功,这意味着所构建的智能体可以在特定的领域中非常成功,如围棋(来自谷歌 Deepmind 的 AlphaGo)、DOTA(特斯拉)、无人驾驶汽车甚至汉堡烙牛肉饼机。这些代理拥有必要的工具,能够很好地完成他们的使命,但是如果你仔细研究他们,你会发现他们的前景已经非常明确了。这种情况需要人类智能来完成,例如,在强化学习中,人类智能来建立效用/延续功能,定义状态、奖励和可以采取的行动等。甚至在机器学习中,目前由监督学习组成,在机器学习之前,我们必须先记下标签/结果。(我将在下一篇参考资料中回到这一点)。
因此,在本书中,它谈到了模拟人类智力主要居住的新皮层,讨论了人类智力,我们如何学习和存储信息,我们的大脑不断地有一个时间/预测元素,不断地扫描环境,如果环境有一些不在预测范围内的东西,大脑的注意力就会被调用来进一步研究等等。如果你对建设 AGI 感兴趣,这是一本很有见地的书。如果你有兴趣了解更多,我推荐下面的 YouTube 播放列表以便快速了解。
为什么之书
如果你要成为一名数据科学家或人工智能科学家,这是一本必读的书,朱迪亚·珀尔的《为什么之书》。朱迪亚·珀尔支持人工智能的概率方法(这就是为什么你需要研究你的统计数据的原因)。通过《为什么》一书,他主张,如果我们要走向 AGI,我们需要在人工智能中建立“因果关系”。在书中,他提到了一种演算,我们需要这种演算来构建可以帮助机器理解因果关系的结构模型,称为因果演算。
在书中,他介绍了因果关系的阶梯,这是三级阶梯,最底层是“看”、“做”和“想象”。目前,如果我们仔细研究机器学习,我们仍然处于“看”的阶段,即第一级。如果我们要建设 AGI,我们需要开始帮助机器做更多的第二梯队,更重要的是,第三梯队。
在我研究这个领域的过程中,最困扰我的一个问题是,我们如何确定监督模型的标签/结果。目前,机器学习模型可以接受任何因变量,并告诉你它和自变量之间的关系。仍然需要人类的智慧来确定什么是因变量和自变量。仍然需要人类智能来查看数据是否可以输入到模型中(如果我们要实现机器学习模型的话)。机器学习模型在这个意义上是“愚蠢的”,因为它将接受我们定义的因变量和自变量。如果我们要建设一个 AGI,那么 AGI 也必须能够执行这样的任务。为了确定这一点,我们需要在整个结构中建立“因果关系”。
到目前为止,我已经读到了这本书的第三章,我觉得能够阅读这样的作品是值得的。我决定慢慢来,消化里面的大量知识。
最初的想法
到目前为止,我相信“因果关系”可以通过我们大脑不断进行的时间/预测建立到 HTM 模型中。这种想法肯定需要更多的研究和理解,以确定其可能性。我坚信,通过将这两种资源结合在一起,我们可以走上建设 AGI 的道路。
如果我们要继续当前的路线,我毫不怀疑我们可以通过调整当前的深度学习模型来建立出色的人工狭义智能(ANI),即非常好地执行特定任务的代理,但我非常怀疑这条路线可以带我们走上人工通用智能的道路。此外,目前使用深度学习来构建 ANI 的路线在计算上是昂贵的,如果它发生在我们的大脑中,我们可能必须消耗大量的食物来支持它。
以上是我目前为止的想法,我愿意与读者进行讨论。:)
如果这篇博文对你来说很有趣和/或有用,请鼓掌。我也写关于数据科学的博客,所以请访问我的其他博客文章和 LinkedIn 个人资料。
在野外构建客户端路由/语义搜索
原文:https://towardsdatascience.com/building-client-routing-semantic-search-in-the-wild-14db04687c7e?source=collection_archive---------16-----------------------
Main objective — help our clients find what they want, ideally even before they type the whole query. Search also should generalize reasonably well (synonyms / forms of known words, Russian has rich morphology)
TLDR
这是一份关于我们在语义工厂项目中的 Profi.ru DS 部门(Profi.ru 是 CIS 地区领先的在线服务市场之一)在大约 2 个月的时间里所做工作的执行摘要。
这篇文章主要集中在比较新的 NLP 技术在应用商业环境中的适用性,如果你计划在你的公司/项目中做类似的事情,它可以作为一个指南。
简而言之,我们有两个目标:
- 使 Profi.ru 上主搜索栏内的搜索/路由更好(监督任务);
- 这样做——开发无监督的方法,以有效地在第三方数据中搜索新服务(无监督任务);
我们考虑了许多架构,但最终一个具有嵌入包层而不是普通嵌入的双 LSTM(或双 GRU)被证明是监督和非监督任务的最佳**(见下图)。值得注意的是,使模型对部分输入/有误差的输入具有鲁棒性提高了其性能。此外,添加第二个目标(假“服务”检测)也略微提高了准确性**。像 transformer 这样更复杂的模型在我们的领域中没有显示出真正的好处。****
现有数据
我们使用的内部数据来自几个主要来源:
- 实际客户端搜索(每 3-6 个月 30k 个唯一查询)+手动注释(这产生了我们的主开发集);
- 内部同义词库 (30k 唯一同义词);
- 内部营销 SEO 数据库带注释(300k);
在我们之前,公司里没有人建立 ML 模型,所以我们必须在获取数据和管理数据注释时随机应变。还应该注意的是,尽管查询的总数很大,但唯一的查询计数却非常低,这迫使我们在获取/扩充数据时要有创造性。此外,手头的数据集和注释的质量差异很大。正如所料,最好的监督数据集是人工注释的数据集和同义词数据库。我们还尝试探索转换管道(即查询—会话—顺序)并提取以前的分类器结果—预期性能不佳。
关于外部数据,我们使用了以下来源:
- 搜索引擎数据(Google 和 Yandex 的 SEO 小组及其统计服务提供的数据)( 11m 查询);
- 外部 SEO 服务( 3m 查询);
- 我们竞争对手的公开数据( 1.5m 查询);
实现的目标
业务目标:
88+%
(相对于具有弹性搜索的60%
)在客户端路由/意图分类上的准确性(~5k
类);- 搜索不知道输入质量(印刷错误/部分输入);
- 分类器一般化,语言的形态学结构被开发;
- 为了安全起见——至少发现了
1,000
个新服务+至少15,000
个同义词(相对于5,000
+ ~30,000
的当前状态)。我预计这个数字会翻一倍甚至三倍;
“科学”目标:
- 我们使用下游分类任务+ KNN 和服务同义词数据库彻底比较了许多现代句子嵌入技术;
- 我们使用非监督方法,在基准测试中成功击败了弱监督(本质上,他们的分类器是一袋 ngrams)弹性搜索(详见下文);
- 我们开发了一种构建应用 NLP 模型的新方法(一个普通的双 LSTM +嵌入包,本质上是快速文本符合 RNN)——这考虑到了俄语的形态学,并且推广得很好;
- 我们证明了我们的最终嵌入技术(来自最佳分类器的瓶颈层)结合最先进的无监督算法(UMAP + HDBSCAN)可以在外部数据上产生恒星簇;
- 我们在实践中证明了以下方法的可能性、可行性和可用性:(1)知识提炼(2)文本数据扩充(原文如此!);
- 与生成更大的静态数据集相比,使用动态增强来训练基于文本的分类器大大减少了收敛时间(10 倍)(即,CNN 学习概括错误,显示大大减少增强的句子);
现在 NLP 里什么管用?
鸟瞰 NLP 景观:
此外,您可能知道 NLP 现在可能正在经历 Imagenet 时刻。
大规模 UMAP 黑客攻击
在构建集群时,我们偶然发现了一种方法/技巧,可以将 UMAP 应用于 1 亿多点(甚至 10 亿)大小的数据集。本质上是用 FAISS 构建一个 KNN 图,然后用你的 GPU 将主 UMAP 循环改写成 PyTorch。我们不需要这个,并放弃了这个概念(我们毕竟只有 1000-1500 万点),但请按照这个线程了解详情。
什么最有效
- 对于监督分类,快速文本满足 RNN(双 LSTM) +精心选择的 n 元文法集;
- 实现——普通 python 为 n-grams + PyTorch 嵌入包层;
- 对于集群——该模型的瓶颈层+UMAP+hdb scan;
最佳分类器基准
手动注释开发集
Performance of the best model (n-gram bag + biLSTM) on manually annotated dev-set
手动注释开发集+每个查询 1-3 个错别字
Performance of the best model (n-gram bag + biLSTM) on manually annotated dev-set, where we added 1 to 3 typos to each query
手动注释开发集+部分输入
Performance of the best model (n-gram bag + biLSTM) on manually annotated dev-set, where we randomly cut the input sequence to simulate partial input
大规模语料库/ n-gram 选择
我们收集了最大的俄语语料库:
- 我们用 1TB 抓取收集了一个
100m
单词字典; - 也用这个黑更快下载这类文件(隔夜);
- 我们为我们的分类器选择了一组最佳的
1m
n-grams,以进行最佳概括(来自俄语维基百科上训练的快速文本的500k
最流行的 n-grams+500k
我们领域数据上最流行的 n-grams);
我们的 100 万词汇上的 100 万 n-grams 的压力测试:
Share of n-grams (3–7 grams) in a 100M word vocabulary covered by our n-gram selection
文本扩充
简而言之:
- 拿一本有错误的大字典(例如 10-100 万个独特的单词);
- 产生一个错误(丢弃一个字母,使用计算的概率交换一个字母,插入一个随机的字母,可能使用键盘布局等);
- 检查新单词是否在词典中;
我们对像这个这样的服务进行了大量的强制查询(试图从本质上对它们的数据集进行逆向工程),它们内部有一个非常小的字典(这个服务也是由一个具有 n 元语法特征的树分类器支持的)。看到它们只覆盖了我们在一些语料库中的 30 %- 50%的单词有点好笑。
如果你有大量的领域词汇,我们的方法要优越得多。
最佳无监督/半监督结果
KNN 被用作比较不同嵌入方法的基准。这更多的是一个例子,但是显然我们使用这些方法来聚集/搜索新的服务。
(向量大小)测试模型列表:
- (512)在 200 GB 普通爬行数据上训练的大规模假句子检测器;
- (300)假句子检测器,被训练成从服务中辨别来自维基百科的随机句子;
- (300)从这里获得的快速文本,在 araneum 语料库上进行预训练;
- (200)在我们的领域数据上训练的快速文本;
- (300)在 200GB 的普通爬行数据上训练的快速文本;
- (300)用来自维基百科的服务/同义词/随机句子训练的三联体丢失的连体网络;
- (200)嵌入包 RNN 的嵌入层的第一次迭代,句子被编码为整个嵌入包;
- (200)相同,但首先将句子拆分成单词,然后嵌入每个单词,然后取普通平均值;
- (300)同上,但用于最终模型;
- (300)同上,但用于最终模型;
- (250)最终模型的瓶颈层(250 个神经元);
- 弱监督弹性搜索基线;
为了避免泄密,所有的随机句子都是随机抽样的。他们的单词长度与他们所比较的服务/同义词的长度相同。此外,还采取措施确保模型不只是通过分离词汇来学习(嵌入被冻结,维基百科被欠采样以确保每个维基百科句子中至少有一个领域词)。
集群可视化
最佳嵌入技术+ UMAP 如何在一个外部语料库上工作的例子。
3D
2D
集群探索“界面”
绿色—新单词/同义词。灰色背景-可能是新词。
灰色文本-现有同义词。
消融试验和哪些有效,我们尝试了哪些,哪些没有
- 见以上图表;
- 快速文本嵌入的普通平均值/tf-idf 平均值——一个非常强大的基线;
- 俄语的 fast-text > word 2 vec;
- 通过伪句子检测的句子嵌入类工作,但是与其他方法相比相形见绌;
- BPE(句子)显示没有改善我们的领域;
- 尽管谷歌撤回了论文,但 Char 级模型很难推广;
- 我们尝试了多头 transformer(带有分类器和语言建模头),但是在手边可用的注释上,它的性能与普通的基于 LSTM 的模型大致相同。当我们迁移到嵌入 bad 方法时,我们放弃了这一研究方向,因为变压器的实用性较低,并且具有 LM 头和嵌入包层是不切实际的;
- 伯特(BERT)——似乎有些夸张,也有人声称变形金刚实际上训练了几个星期;
- ELMO——在我看来,无论是在研究/生产还是教育环境中,使用像 AllenNLP 这样的库似乎都是适得其反的,原因我就不在这里说了;
部署
使用完成:
- 带有简单 web 服务的 Docker 容器;
- CPU-仅用于推断就足够了;
- ~
2.5 ms
对于 CPU 上的每个查询,批处理并不是真正必要的; - ~
1GB
RAM 内存占用量; - 几乎没有依赖,除了
PyTorch
、numpy
、pandas
(还有 web 服务器 ofc)。 - 模仿像这样的快速文本 n-gram 生成;
- 嵌入刚刚存储在字典中的包层+索引;
结论
我们已经表明,您可以应用相对简单/现成的工具来解决真实业务中语义搜索框架内的监督和非监督挑战。
进一步阅读
- 更详细的俄语演示文稿;
- 解析普通爬虫和维基百科;
- 如何在一个函数中模拟嵌入的快速文本包;
- 更多预处理普通抓取;
- 快速文本单词向量在维基百科上预先训练;
- 俄罗斯语言的快速文本和 Word2Vec 模型;
- 种子词嵌入论文: Word2Vec ,快文,进一步调;
- 当前一些基于 SOTA CNN 的方法:推断/CNN 的生成预训练/ul mfit/深度语境化单词表示(Elmo);
- Imagenet 时刻在 NLP ?
- 句子嵌入基线 1 、 2 、 3 、4;
- 假句子检测作为句子编码的训练任务;
原载于 2018 年 11 月 2 日spark-in . me。
使用 NumPy 从头构建卷积神经网络
原文:https://towardsdatascience.com/building-convolutional-neural-network-using-numpy-from-scratch-b30aac50e50a?source=collection_archive---------2-----------------------
在某些情况下,使用 ML/DL 库中已经存在的模型可能会有所帮助。但是要有更好的控制和理解,你应该试着自己实现它们。这篇文章展示了如何使用 NumPy 实现 CNN。
介绍
卷积神经网络(CNN)是用于分析图像等多维信号的最先进技术。已经有不同的库实现了 CNN,比如 TensorFlow 和 Keras。这种库将开发人员与一些细节隔离开来,只是给出一个抽象的 API,使生活变得更容易,并避免实现中的复杂性。但实际上,这些细节可能会有所不同。有时,数据科学家必须仔细检查这些细节以提高性能。在这种情况下,解决方法是构建你自己的模型的每一部分。这提供了对网络的最高级别的控制。此外,建议实现这样的模型,以便更好地理解它们。
在本文中,CNN 仅使用 NumPy 库创建。只创建了三层,分别是卷积(简称 conv)、ReLU 和最大池。涉及的主要步骤如下:
1.读取输入图像。
2.准备过滤器。
3.Conv 层:卷积每个滤波器与输入图像。
4.ReLU 图层:在特征地图上应用 ReLU 激活功能(conv 图层的输出)。
5.最大池层:在 ReLU 层的输出上应用池操作。
6.堆叠 conv、ReLU 和 max 池层。
1.读取输入图像
以下代码从 skimage Python 库中读取一个已经存在的图像,并将其转换为灰色。
**import** skimage.data# Reading the imageimg = skimage.data.chelsea()# Converting the image into gray.img = skimage.color.rgb2gray(img)
读取图像是第一步,因为后续步骤取决于输入尺寸。转换为灰色后的图像如下所示。
Figure 1. Original Gray Image. It is the Skimage image named Chelsea accessed via skimage.data.chelsea()
2.准备过滤器
下面的代码为第一个 conv 图层准备了滤波器组(简称为 l1 ):
l1_filter = numpy.zeros((2,3,3))
根据过滤器的数量和每个过滤器的大小创建零数组。创建大小为3×3的 2 个过滤器,这就是为什么零数组的大小为(2=数量 _ 过滤器,3=数量 _ 行 _ 过滤器,3=数量 _ 列 _ 过滤器)。滤波器的大小被选择为没有深度的 2D 阵列,因为输入图像是灰色的并且没有深度(即 2D)。如果图像是具有 3 个通道的 RGB,则滤镜大小必须为(3,3,3=深度)。
滤波器组的大小由上述零数组指定,而不是由滤波器的实际值指定。可以覆盖如下值来检测垂直和水平边缘。
l1_filter[0, :, :] = numpy.array([[[-1, 0, 1], [-1, 0, 1], [-1, 0, 1]]])l1_filter[1, :, :] = numpy.array([[[1, 1, 1], [0, 0, 0], [-1, -1, -1]]])
3.Conv 层
准备好滤波器后,下一步是用它们对输入图像进行卷积。下一行使用名为 conv 的函数将图像与滤波器组进行卷积:
l1_feature_map = conv(img, l1_filter)
该函数只接受两个参数,即图像和滤波器组,如下所示。
def conv(img, conv_filter):
if len(img.shape) > 2 or len(conv_filter.shape) > 3: # Check if number of image channels matches the filter depth.
if img.shape[-1] != conv_filter.shape[-1]:
print("Error: Number of channels in both image and filter must match.")
sys.exit()
if conv_filter.shape[1] != conv_filter.shape[2]: # Check if filter dimensions are equal.
print('Error: Filter must be a square matrix. I.e. number of rows and columns must match.')
sys.exit()
if conv_filter.shape[1]%2==0: # Check if filter diemnsions are odd.
print('Error: Filter must have an odd size. I.e. number of rows and columns must be odd.')
sys.exit()
# An empty feature map to hold the output of convolving the filter(s) with the image.
feature_maps = numpy.zeros((img.shape[0]-conv_filter.shape[1]+1,
img.shape[1]-conv_filter.shape[1]+1,
conv_filter.shape[0]))
# Convolving the image by the filter(s).
for filter_num in range(conv_filter.shape[0]):
print("Filter ", filter_num + 1)
curr_filter = conv_filter[filter_num, :] # getting a filter from the bank.
"""
Checking if there are mutliple channels for the single filter.
If so, then each channel will convolve the image.
The result of all convolutions are summed to return a single feature map.
"""
if len(curr_filter.shape) > 2:
conv_map = conv_(img[:, :, 0], curr_filter[:, :, 0]) # Array holding the sum of all feature maps.
for ch_num in range(1, curr_filter.shape[-1]): # Convolving each channel with the image and summing the results.
conv_map = conv_map + conv_(img[:, :, ch_num],
curr_filter[:, :, ch_num])
else: # There is just a single channel in the filter.
conv_map = conv_(img, curr_filter)
feature_maps[:, :, filter_num] = conv_map # Holding feature map with the current filter.
return feature_maps # Returning all feature maps.
该功能首先确保每个滤镜的深度等于图像通道的数量。在下面的代码中,外部的 if 检查通道和过滤器是否有深度。如果深度已经存在,那么内部的 if 检查它们的不相等。如果不匹配,那么脚本将退出。
if len(img.shape) > 2 or len(conv_filter.shape) > 3: # Check if number of image channels matches the filter depth.
if img.shape[-1] != conv_filter.shape[-1]:
print("Error: Number of channels in both image and filter must match.")
sys.exit()
此外,过滤器的大小应该是奇数,并且过滤器尺寸相等(即,行数和列数是奇数并且相等)。根据以下两个 if 块进行检查。如果不满足这些条件,脚本将退出。
if conv_filter.shape[1] != conv_filter.shape[2]: # Check if filter dimensions are equal.
print('Error: Filter must be a square matrix. I.e. number of rows and columns must match.')
sys.exit()
if conv_filter.shape[1]%2==0: # Check if filter diemnsions are odd.
print('Error: Filter must have an odd size. I.e. number of rows and columns must be odd.')
sys.exit()
不满足上面的任何条件都证明滤波器深度适合图像,并且卷积准备好被应用。通过滤波器对图像进行卷积,首先初始化一个数组,通过根据以下代码指定其大小来保存卷积的输出(即特征图):
# An empty feature map to hold the output of convolving the filter(s) with the image.
feature_maps = numpy.zeros((img.shape[0]-conv_filter.shape[1]+1,
img.shape[1]-conv_filter.shape[1]+1,
conv_filter.shape[0]))
因为既没有步幅也没有填充,所以特征映射的大小将等于(img_rows-filter_rows+1,image_columns-filter_columns+1,num_filters ),如上面代码中所示。注意,组中的每个滤波器都有一个输出特征映射。这就是为什么滤波器组中的滤波器数量(conv _ 滤波器.形状[0] )被用来指定大小作为第三个参数。
准备好卷积运算的输入和输出后,接下来是根据以下代码应用它:
# Convolving the image by the filter(s).
for filter_num in range(conv_filter.shape[0]):
print("Filter ", filter_num + 1)
curr_filter = conv_filter[filter_num, :] # getting a filter from the bank.
"""
Checking if there are mutliple channels for the single filter.
If so, then each channel will convolve the image.
The result of all convolutions are summed to return a single feature map.
"""
if len(curr_filter.shape) > 2:
conv_map = conv_(img[:, :, 0], curr_filter[:, :, 0]) # Array holding the sum of all feature maps.
for ch_num in range(1, curr_filter.shape[-1]): # Convolving each channel with the image and summing the results.
conv_map = conv_map + conv_(img[:, :, ch_num],
curr_filter[:, :, ch_num])
else: # There is just a single channel in the filter.
conv_map = conv_(img, curr_filter)
feature_maps[:, :, filter_num] = conv_map # Holding feature map with the current filter.
return feature_maps # Returning all feature maps.
外部循环对滤波器组中的每个滤波器进行迭代,并根据以下代码行返回它以进行进一步的步骤:
curr_filter = conv_filter[filter_num, :] # getting a filter from the bank.
如果要卷积的图像有不止一个通道,那么滤波器的深度必须等于这些通道的数量。在这种情况下,卷积是通过将每个图像通道与其在滤波器中的对应通道进行卷积来完成的。最后,结果的总和将是输出特征图。如果图像只有一个通道,那么卷积将是直接的。确定这样的行为是在这样的 if-else 块中完成的:
if len(curr_filter.shape) > 2:
conv_map = conv_(img[:, :, 0], curr_filter[:, :, 0]) # Array holding the sum of all feature maps.
for ch_num in range(1, curr_filter.shape[-1]): # Convolving each channel with the image and summing the results.
conv_map = conv_map + conv_(img[:, :, ch_num],
curr_filter[:, :, ch_num])
else: # There is just a single channel in the filter.
conv_map = conv_(img, curr_filter)
你可能会注意到,卷积是由一个名为 conv_ 的函数应用的,它不同于 conv 函数。函数 conv 只接受输入图像和滤波器组,但不应用自己的卷积。它只是将每组输入滤波器对传递给 conv_ 函数进行卷积。这只是为了使代码更容易研究。下面是 conv_ 函数的实现:
def conv_(img, conv_filter):
filter_size = conv_filter.shape[1]
result = numpy.zeros((img.shape))
#Looping through the image to apply the convolution operation.
for r in numpy.uint16(numpy.arange(filter_size/2.0,
img.shape[0]-filter_size/2.0+1)):
for c in numpy.uint16(numpy.arange(filter_size/2.0,
img.shape[1]-filter_size/2.0+1)):
"""
Getting the current region to get multiplied with the filter.
How to loop through the image and get the region based on
the image and filer sizes is the most tricky part of convolution.
"""
curr_region = img[r-numpy.uint16(numpy.floor(filter_size/2.0)):r+numpy.uint16(numpy.ceil(filter_size/2.0)),
c-numpy.uint16(numpy.floor(filter_size/2.0)):c+numpy.uint16(numpy.ceil(filter_size/2.0))]
#Element-wise multipliplication between the current region and the filter.
curr_result = curr_region * conv_filter
conv_sum = numpy.sum(curr_result) #Summing the result of multiplication.
result[r, c] = conv_sum #Saving the summation in the convolution layer feature map.
#Clipping the outliers of the result matrix.
final_result = result[numpy.uint16(filter_size/2.0):result.shape[0]-numpy.uint16(filter_size/2.0),
numpy.uint16(filter_size/2.0):result.shape[1]-numpy.uint16(filter_size/2.0)]
return final_result
它对图像进行迭代,并根据以下代码行提取与过滤器大小相等的区域:
curr_region = img[r-numpy.uint16(numpy.floor(filter_size/2.0)):r+numpy.uint16(numpy.ceil(filter_size/2.0)),
c-numpy.uint16(numpy.floor(filter_size/2.0)):c+numpy.uint16(numpy.ceil(filter_size/2.0))]
然后,它在区域和过滤器之间应用元素级乘法,并对它们求和,以获得作为输出的单个值,如下所示:
#Element-wise multipliplication between the current region and the filter.
curr_result = curr_region * conv_filter
conv_sum = numpy.sum(curr_result) #Summing the result of multiplication.
result[r, c] = conv_sum #Saving the summation in the convolution layer feature map.
在通过输入对每个滤波器进行卷积之后,特征图由 conv 函数返回。图 2 显示了此类 conv 图层返回的要素地图。
Figure 2. Output feature maps of the first conv layer.
该层的输出将被应用到 ReLU 层。
4.ReLU 层
ReLU 图层对 conv 图层返回的每个要素地图应用 ReLU 激活函数。根据下面的代码行,使用 relu 函数调用它:
l1_feature_map_relu = relu(l1_feature_map)
relu 功能实现如下:
def relu(feature_map):
#Preparing the output of the ReLU activation function.
relu_out = numpy.zeros(feature_map.shape)
for map_num in range(feature_map.shape[-1]):
for r in numpy.arange(0,feature_map.shape[0]):
for c in numpy.arange(0, feature_map.shape[1]):
relu_out[r, c, map_num] = numpy.max([feature_map[r, c, map_num], 0])
return relu_out
这很简单。只需遍历特征映射中的每个元素,如果大于 0,则返回特征映射中的原始值。否则,返回 0。ReLU 层的输出如图 3 所示。
Figure 3. ReLU layer output applied to the output of the first conv layer
ReLU 层的输出被应用到 max pooling 层。
5.最大池层
最大池层接受 ReLU 层的输出,并根据以下代码行应用最大池操作:
l1_feature_map_relu_pool = pooling(l1_feature_map_relu, 2, 2)
它是使用池函数实现的,如下所示:
def pooling(feature_map, size=2, stride=2):
#Preparing the output of the pooling operation.
pool_out = numpy.zeros((numpy.uint16((feature_map.shape[0]-size+1)/stride),
numpy.uint16((feature_map.shape[1]-size+1)/stride),
feature_map.shape[-1]))
for map_num in range(feature_map.shape[-1]):
r2 = 0
for r in numpy.arange(0,feature_map.shape[0]-size-1, stride):
c2 = 0
for c in numpy.arange(0, feature_map.shape[1]-size-1, stride):
pool_out[r2, c2, map_num] = numpy.max([feature_map[r:r+size, c:c+size, map_num]])
c2 = c2 + 1
r2 = r2 +1
return pool_out
该函数接受三个输入,即 ReLU 层的输出、汇集遮罩大小和跨距。和前面一样,它只是创建一个空数组来保存该层的输出。此类数组的大小是根据 size 和 stride 参数指定的,如下所示:
pool_out = numpy.zeros((numpy.uint16((feature_map.shape[0]-size+1)/stride),
numpy.uint16((feature_map.shape[1]-size+1)/stride),
feature_map.shape[-1]))
然后,它根据使用循环变量 map_num 的外部循环,逐个通道地循环输入。对于输入中的每个通道,应用最大池操作。根据所使用的步幅和大小,该区域被剪裁,并且它的最大值根据以下行返回到输出数组中:
pool_out[r2, c2, map_num] = numpy.max([feature_map[r:r+size, c:c+size, map_num]])
下图显示了这种池层的输出。请注意,池层输出的大小小于其输入,即使它们在图表中看起来相同。
Figure 4. Pooling layer output applied to the output of the first ReLU layer
6.堆叠层
至此,具有 conv、ReLU 和 max 池层的 CNN 架构已经完成。除了前面的层之外,可能还有一些其他层需要堆叠,如下所示。
# Second conv layerl2_filter = numpy.random.rand(3, 5, 5, l1_feature_map_relu_pool.shape[-1])**print**("\n**Working with conv layer 2**")l2_feature_map = conv(l1_feature_map_relu_pool, l2_filter)**print**("\n**ReLU**")l2_feature_map_relu = relu(l2_feature_map)**print**("\n**Pooling**")l2_feature_map_relu_pool = pooling(l2_feature_map_relu, 2, 2)**print**("**End of conv layer 2**\n")
先前的 conv 层使用 3 个过滤器,它们的值是随机生成的。这就是为什么会有 3 这样的 conv 图层生成的特征图。这对于连续的 ReLU 和 pooling 层也是一样的。这些层的输出如图 5 所示。
Figure 5. Output of the second conv-ReLU-Pooling layers
# Third conv layer
l3_filter = numpy.random.rand(1, 7, 7, l2_feature_map_relu_pool.shape[-1])
print("\n**Working with conv layer 3**")
l3_feature_map = numpycnn.conv(l2_feature_map_relu_pool, l3_filter)
print("\n**ReLU**")
l3_feature_map_relu = numpycnn.relu(l3_feature_map)
print("\n**Pooling**")
l3_feature_map_relu_pool = numpycnn.pooling(l3_feature_map_relu, 2, 2)
print("**End of conv layer 3**\n")
图 6 显示了前几层的输出。先前的 conv 层只接受一个过滤器。这就是为什么只有一个要素地图作为输出。
Figure 6. Outputs of the third conv-ReLU-Pooling layers
但是要记住,每一层的输出都是下一层的输入。例如,这些行接受以前的输出作为它们的输入。
l2_feature_map = conv(l1_feature_map_relu_pool, l2_filter)l3_feature_map = conv(l2_feature_map_relu_pool, l3_filter)
7.完全码
完整代码在github(【https://github.com/ahmedfgad/NumPyCNN】)中。代码包含使用 Matplotlib 库的每层输出的可视化。
import skimage.data
import numpy
import matplotlib
import sysdef conv_(img, conv_filter):
filter_size = conv_filter.shape[1]
result = numpy.zeros((img.shape))
#Looping through the image to apply the convolution operation.
for r in numpy.uint16(numpy.arange(filter_size/2.0,
img.shape[0]-filter_size/2.0+1)):
for c in numpy.uint16(numpy.arange(filter_size/2.0,
img.shape[1]-filter_size/2.0+1)):
"""
Getting the current region to get multiplied with the filter.
How to loop through the image and get the region based on
the image and filer sizes is the most tricky part of convolution.
"""
curr_region = img[r-numpy.uint16(numpy.floor(filter_size/2.0)):r+numpy.uint16(numpy.ceil(filter_size/2.0)),
c-numpy.uint16(numpy.floor(filter_size/2.0)):c+numpy.uint16(numpy.ceil(filter_size/2.0))]
#Element-wise multipliplication between the current region and the filter.
curr_result = curr_region * conv_filter
conv_sum = numpy.sum(curr_result) #Summing the result of multiplication.
result[r, c] = conv_sum #Saving the summation in the convolution layer feature map.
#Clipping the outliers of the result matrix.
final_result = result[numpy.uint16(filter_size/2.0):result.shape[0]-numpy.uint16(filter_size/2.0),
numpy.uint16(filter_size/2.0):result.shape[1]-numpy.uint16(filter_size/2.0)]
return final_result
def conv(img, conv_filter):
if len(img.shape) > 2 or len(conv_filter.shape) > 3: # Check if number of image channels matches the filter depth.
if img.shape[-1] != conv_filter.shape[-1]:
print("Error: Number of channels in both image and filter must match.")
sys.exit()
if conv_filter.shape[1] != conv_filter.shape[2]: # Check if filter dimensions are equal.
print('Error: Filter must be a square matrix. I.e. number of rows and columns must match.')
sys.exit()
if conv_filter.shape[1]%2==0: # Check if filter diemnsions are odd.
print('Error: Filter must have an odd size. I.e. number of rows and columns must be odd.')
sys.exit()# An empty feature map to hold the output of convolving the filter(s) with the image.
feature_maps = numpy.zeros((img.shape[0]-conv_filter.shape[1]+1,
img.shape[1]-conv_filter.shape[1]+1,
conv_filter.shape[0]))# Convolving the image by the filter(s).
for filter_num in range(conv_filter.shape[0]):
print("Filter ", filter_num + 1)
curr_filter = conv_filter[filter_num, :] # getting a filter from the bank.
"""
Checking if there are mutliple channels for the single filter.
If so, then each channel will convolve the image.
The result of all convolutions are summed to return a single feature map.
"""
if len(curr_filter.shape) > 2:
conv_map = conv_(img[:, :, 0], curr_filter[:, :, 0]) # Array holding the sum of all feature maps.
for ch_num in range(1, curr_filter.shape[-1]): # Convolving each channel with the image and summing the results.
conv_map = conv_map + conv_(img[:, :, ch_num],
curr_filter[:, :, ch_num])
else: # There is just a single channel in the filter.
conv_map = conv_(img, curr_filter)
feature_maps[:, :, filter_num] = conv_map # Holding feature map with the current filter.
return feature_maps # Returning all feature maps.def pooling(feature_map, size=2, stride=2):
#Preparing the output of the pooling operation.
pool_out = numpy.zeros((numpy.uint16((feature_map.shape[0]-size+1)/stride),
numpy.uint16((feature_map.shape[1]-size+1)/stride),
feature_map.shape[-1]))
for map_num in range(feature_map.shape[-1]):
r2 = 0
for r in numpy.arange(0,feature_map.shape[0]-size-1, stride):
c2 = 0
for c in numpy.arange(0, feature_map.shape[1]-size-1, stride):
pool_out[r2, c2, map_num] = numpy.max([feature_map[r:r+size, c:c+size, map_num]])
c2 = c2 + 1
r2 = r2 +1
return pool_outdef relu(feature_map):
#Preparing the output of the ReLU activation function.
relu_out = numpy.zeros(feature_map.shape)
for map_num in range(feature_map.shape[-1]):
for r in numpy.arange(0,feature_map.shape[0]):
for c in numpy.arange(0, feature_map.shape[1]):
relu_out[r, c, map_num] = numpy.max([feature_map[r, c, map_num], 0])
return relu_out# Reading the image
#img = skimage.io.imread("fruits2.png")
img = skimage.data.chelsea()
# Converting the image into gray.
img = skimage.color.rgb2gray(img)# First conv layer
#l1_filter = numpy.random.rand(2,7,7)*20 # Preparing the filters randomly.
l1_filter = numpy.zeros((2,3,3))
l1_filter[0, :, :] = numpy.array([[[-1, 0, 1],
[-1, 0, 1],
[-1, 0, 1]]])
l1_filter[1, :, :] = numpy.array([[[1, 1, 1],
[0, 0, 0],
[-1, -1, -1]]])print("\n**Working with conv layer 1**")
l1_feature_map = conv(img, l1_filter)
print("\n**ReLU**")
l1_feature_map_relu = relu(l1_feature_map)
print("\n**Pooling**")
l1_feature_map_relu_pool = pooling(l1_feature_map_relu, 2, 2)
print("**End of conv layer 1**\n")# Second conv layer
l2_filter = numpy.random.rand(3, 5, 5, l1_feature_map_relu_pool.shape[-1])
print("\n**Working with conv layer 2**")
l2_feature_map = conv(l1_feature_map_relu_pool, l2_filter)
print("\n**ReLU**")
l2_feature_map_relu = relu(l2_feature_map)
print("\n**Pooling**")
l2_feature_map_relu_pool = pooling(l2_feature_map_relu, 2, 2)
print("**End of conv layer 2**\n")# Third conv layer
l3_filter = numpy.random.rand(1, 7, 7, l2_feature_map_relu_pool.shape[-1])
print("\n**Working with conv layer 3**")
l3_feature_map = conv(l2_feature_map_relu_pool, l3_filter)
print("\n**ReLU**")
l3_feature_map_relu = relu(l3_feature_map)
print("\n**Pooling**")
l3_feature_map_relu_pool = pooling(l3_feature_map_relu, 2, 2)
print("**End of conv layer 3**\n")# Graphing results
fig0, ax0 = matplotlib.pyplot.subplots(nrows=1, ncols=1)
ax0.imshow(img).set_cmap("gray")
ax0.set_title("Input Image")
ax0.get_xaxis().set_ticks([])
ax0.get_yaxis().set_ticks([])
matplotlib.pyplot.savefig("in_img.png", bbox_inches="tight")
matplotlib.pyplot.close(fig0)# Layer 1
fig1, ax1 = matplotlib.pyplot.subplots(nrows=3, ncols=2)
ax1[0, 0].imshow(l1_feature_map[:, :, 0]).set_cmap("gray")
ax1[0, 0].get_xaxis().set_ticks([])
ax1[0, 0].get_yaxis().set_ticks([])
ax1[0, 0].set_title("L1-Map1")ax1[0, 1].imshow(l1_feature_map[:, :, 1]).set_cmap("gray")
ax1[0, 1].get_xaxis().set_ticks([])
ax1[0, 1].get_yaxis().set_ticks([])
ax1[0, 1].set_title("L1-Map2")ax1[1, 0].imshow(l1_feature_map_relu[:, :, 0]).set_cmap("gray")
ax1[1, 0].get_xaxis().set_ticks([])
ax1[1, 0].get_yaxis().set_ticks([])
ax1[1, 0].set_title("L1-Map1ReLU")ax1[1, 1].imshow(l1_feature_map_relu[:, :, 1]).set_cmap("gray")
ax1[1, 1].get_xaxis().set_ticks([])
ax1[1, 1].get_yaxis().set_ticks([])
ax1[1, 1].set_title("L1-Map2ReLU")ax1[2, 0].imshow(l1_feature_map_relu_pool[:, :, 0]).set_cmap("gray")
ax1[2, 0].get_xaxis().set_ticks([])
ax1[2, 0].get_yaxis().set_ticks([])
ax1[2, 0].set_title("L1-Map1ReLUPool")ax1[2, 1].imshow(l1_feature_map_relu_pool[:, :, 1]).set_cmap("gray")
ax1[2, 0].get_xaxis().set_ticks([])
ax1[2, 0].get_yaxis().set_ticks([])
ax1[2, 1].set_title("L1-Map2ReLUPool")matplotlib.pyplot.savefig("L1.png", bbox_inches="tight")
matplotlib.pyplot.close(fig1)# Layer 2
fig2, ax2 = matplotlib.pyplot.subplots(nrows=3, ncols=3)
ax2[0, 0].imshow(l2_feature_map[:, :, 0]).set_cmap("gray")
ax2[0, 0].get_xaxis().set_ticks([])
ax2[0, 0].get_yaxis().set_ticks([])
ax2[0, 0].set_title("L2-Map1")ax2[0, 1].imshow(l2_feature_map[:, :, 1]).set_cmap("gray")
ax2[0, 1].get_xaxis().set_ticks([])
ax2[0, 1].get_yaxis().set_ticks([])
ax2[0, 1].set_title("L2-Map2")ax2[0, 2].imshow(l2_feature_map[:, :, 2]).set_cmap("gray")
ax2[0, 2].get_xaxis().set_ticks([])
ax2[0, 2].get_yaxis().set_ticks([])
ax2[0, 2].set_title("L2-Map3")ax2[1, 0].imshow(l2_feature_map_relu[:, :, 0]).set_cmap("gray")
ax2[1, 0].get_xaxis().set_ticks([])
ax2[1, 0].get_yaxis().set_ticks([])
ax2[1, 0].set_title("L2-Map1ReLU")ax2[1, 1].imshow(l2_feature_map_relu[:, :, 1]).set_cmap("gray")
ax2[1, 1].get_xaxis().set_ticks([])
ax2[1, 1].get_yaxis().set_ticks([])
ax2[1, 1].set_title("L2-Map2ReLU")ax2[1, 2].imshow(l2_feature_map_relu[:, :, 2]).set_cmap("gray")
ax2[1, 2].get_xaxis().set_ticks([])
ax2[1, 2].get_yaxis().set_ticks([])
ax2[1, 2].set_title("L2-Map3ReLU")ax2[2, 0].imshow(l2_feature_map_relu_pool[:, :, 0]).set_cmap("gray")
ax2[2, 0].get_xaxis().set_ticks([])
ax2[2, 0].get_yaxis().set_ticks([])
ax2[2, 0].set_title("L2-Map1ReLUPool")ax2[2, 1].imshow(l2_feature_map_relu_pool[:, :, 1]).set_cmap("gray")
ax2[2, 1].get_xaxis().set_ticks([])
ax2[2, 1].get_yaxis().set_ticks([])
ax2[2, 1].set_title("L2-Map2ReLUPool")ax2[2, 2].imshow(l2_feature_map_relu_pool[:, :, 2]).set_cmap("gray")
ax2[2, 2].get_xaxis().set_ticks([])
ax2[2, 2].get_yaxis().set_ticks([])
ax2[2, 2].set_title("L2-Map3ReLUPool")matplotlib.pyplot.savefig("L2.png", bbox_inches="tight")
matplotlib.pyplot.close(fig2)# Layer 3
fig3, ax3 = matplotlib.pyplot.subplots(nrows=1, ncols=3)
ax3[0].imshow(l3_feature_map[:, :, 0]).set_cmap("gray")
ax3[0].get_xaxis().set_ticks([])
ax3[0].get_yaxis().set_ticks([])
ax3[0].set_title("L3-Map1")ax3[1].imshow(l3_feature_map_relu[:, :, 0]).set_cmap("gray")
ax3[1].get_xaxis().set_ticks([])
ax3[1].get_yaxis().set_ticks([])
ax3[1].set_title("L3-Map1ReLU")ax3[2].imshow(l3_feature_map_relu_pool[:, :, 0]).set_cmap("gray")
ax3[2].get_xaxis().set_ticks([])
ax3[2].get_yaxis().set_ticks([])
ax3[2].set_title("L3-Map1ReLUPool")matplotlib.pyplot.savefig("L3.png", bbox_inches="tight")
matplotlib.pyplot.close(fig3)
原文可在 LinkedIn 上找到,链接如下:
[## 使用 NumPy 从头构建卷积神经网络
在某些情况下,使用 ML/DL 库中已经存在的模型可能会有所帮助。但是为了更好地控制和…
www.linkedin.com](https://www.linkedin.com/pulse/building-convolutional-neural-network-using-numpy-from-ahmed-gad/)
联系作者
艾哈迈德·法齐·加德
LinkedIn:
[## 艾哈迈德·加德-撰稿人-艾·论坛报| LinkedIn
查看 Ahmed Gad 在世界上最大的职业社区 LinkedIn 上的个人资料。艾哈迈德有 11 个工作列在他们的…
linkedin.com](https://linkedin.com/in/ahmedfgad)
电子邮件:
ahmed.f.gad@gmail.com
在组织中构建数据科学能力
原文:https://towardsdatascience.com/building-data-science-capabilities-in-organizations-354705c1f868?source=collection_archive---------11-----------------------
在个人讨论或社交活动中,企业所有者、部门/职能负责人经常问我这样一个问题:“我相信数据科学的力量,但我该如何开始?”。所以这篇博文是我回答这个问题的尝试。
记住什么
在构建数据科学能力和制定路线图时,务必记住“价值必须始终领先于成本”。我看到过无法在构建数据科学能力方面创造可持续发展势头的努力,因为成本(主要是基础设施)远远超过了价值。随着成本的增加,许多人将被迫展示成果,如果没有对项目进行适当的规划,努力将无法持续。
雇佣一名经验丰富的数据科学家
是的,要开始,请雇用一个有经验的(!!!)数据科学家。为什么你可能会说是一个有经验的数据科学家,而不是那些有“数据科学家”头衔的人?经验丰富的数据科学家应该具备快速理解数据的专业知识,并确定是否有任何“唾手可得的果实”可以通过组织可以轻松访问的工具来采摘,如 Excel 或开源。这些“唾手可得的果实”与工具一起为组织提供即时(大约 1-2 个月的等待,取决于数据质量)价值。这些项目将被用来从组织的其他部分获得认同。
鉴于数据科学家是一个永久性职位,有时雇佣数据科学家可能是一个高风险的策略(数据科学家的需求量很大,所以请不要考虑尝试以合同形式雇佣)。另一种方法是聘请一位做过数据科学项目的顾问。顾问可以筛选可用的数据,并确定是否有足够的“低挂果实”。
旁注
我见过一些组织雇佣已经完成硕士或训练营的人,并希望他们知道如何处理现有数据。这些“新”学员中的大多数需要导师进一步指导,以便他们知道如何从数据中筛选见解。在数据科学中,经验真的很重要!
采摘更多水果
鉴于现有数据已经证明了足够的价值,下一步是从两个方面着手:(1)数据治理和管理(2)基础设施
(1)数据治理和管理
证明了数据的价值之后,就应该建立流程来管理数据,确保数据具有更高的质量,从而缩短从提取数据到以合适的质量使用数据之间的时间。这将允许数据快速转化为决策见解,进一步推动价值包络。
基于最初的几个项目(又名“低挂的果实”),组织现在还可以查看可以捕获哪些进一步的数据(以合理的成本),以便提高他们的洞察力。
(2)基础设施
从管理层那里获得了更多的认同后,组织现在可以在基础设施上工作了。构建基础设施通常需要更大的预算,因为需要与现有系统集成并存储数据。但是,由于我们有“低挂的果实”可以展示,现在就可以更容易地要求建立预算,管理层也将更有信心,预算将用于为组织创造更多的价值。
旁注
我在很多情况下看到,组织在没有关于如何使用它们的适当计划的情况下就购买了“大数据”技术,甚至更糟糕的是,是否有必要使用它们。最终,构建数据科学能力的势头没有持续下去,原因有多种,例如,创造的价值(如果它们是在最初创造的)不足以覆盖基础架构成本,这些组织被“白象”困住了。从这种失败的尝试中得出的结论是管理层不再相信数据科学(谁能责怪他们),这对我来说是非常可悲的,因为组织已经失去了竞争的机会。
所以记住我说的,“价值必须永远领先于成本。”
基础设施越好&数据越多,价值越大
设置基础架构和数据治理流程可能需要一些时间,比如 6 到 12 个月。在此期间,组织应该继续寻找更多的数据科学项目,为组织创造价值。有了更好的基础设施和数据质量,价值/时间花费比率将会增加。这种增长将带来另一个机会,投入更多的资源来建立更好的基础设施、更大的团队和收集更多的数据。
随着价值跑在成本前面,并确保它保持这种方式,它将创建一个良性循环,在适当的时候,数据科学能力将建立起来,并留在组织中。
结论
当然,这只是关于如何构建数据科学能力的一个非常简单的描述。考虑到不同的领域,还会有其他的考虑。但最终,我想传达的最重要的信息是“价值必须永远领先于成本”。否则,这种努力是不可持续的,组织可能会失去在这种动态和恶劣的环境中生存所必需的竞争优势。
希望博客有用!祝您的数据科学学习之旅愉快,请务必访问我的其他博客文章和 LinkedIn 个人资料。
在医疗保健中建立伦理人工智能:为什么我们必须要求它
原文:https://towardsdatascience.com/building-ethical-ai-in-healthcare-why-we-must-demand-it-ca60f4d28412?source=collection_archive---------11-----------------------
有一个学派思考着一个黑暗的、反乌托邦式的未来,在那里,人工智能机器残酷而冷酷地统治着世界,人类只是一个生物工具。从好莱坞大片到福音派科技企业家,我们都接触到了这种未来的可能性,但我们是否都停下来思考我们应该如何避免它?当然,现在所有这些反乌托邦都是几十年后的事了,而且只是未来无数可能结果中的一个。但这并不排除今天就开始对话。
对我和许多其他人来说,这可以归结为一件简单的事情:伦理。把你的道德规范搞对了,理论上,机器永远也不能接管和支配一个机器大脑版本的宇宙。在更简单的层面上,我们需要开始考虑如何避免不人道的决定,特别是在它们有可能对我们伤害最大的地方:在医疗保健的生死环境中。我们离完全自动化的医疗保健系统还有很长的路要走,然而,现在,人工智能正在被开发来帮助增强医生的决策。但是如果其中一些决定是错误的呢?
在这篇博客中,我将讨论 NHS 最近令人震惊的新闻,这些新闻突出了为什么每个人都应该要求有道德和负责任的人工智能。
首先,我需要告诉你一个故事…
一个电子表格错误如何摧毁生命
瑞秋和她的搭档大卫(化名)都是英国国民医疗服务系统的初级医生。他们在医学院相遇,一起度过了艰难的期末考试,经历了两年医学院基础培训后的测试环境,并庆祝他们最终被各自医学专业的培训岗位录取。
雷切尔想成为一名对中风护理感兴趣的全科医生,并在英格兰北部的一家领先单位工作。大卫正在接受心理医生的培训,并在 80 英里外的一家精神病院工作。尽管很难找到一个他们都能在合理的通勤距离内生活的地方,但他们迄今为止已经通过在工作地点中间的一个村庄租一套小公寓,找到了工作与生活的某种平衡。每当需要值夜班时,雷切尔就住在离她医院更近的朋友家,有时长达一周。需要的时候,大卫呆在他父母那里。他们同意,这种安排只会持续很短的两年,直到他们找到完美的高等培训工作,最终让他们能够更紧密地合作,买房子,组建家庭。
当申请下一份工作(被称为 ST3 选择)的时候,他们兴奋地开始一起规划他们的生活。他们画了一张他们想要居住的地区的地图,在他们想要工作的所有医院,他们想要靠近的城镇和城市中标出精确的位置,并用虚线和通勤距离、抵押贷款利率和好学校的计算将它们联系起来。最后,他们找到了田园诗般的伴侣。雷切尔和大卫决定申请同一个院长职位,以增加他们匹配大型教学医院的机会,该医院也有一个精神病科,位于一个拥有广阔农村郊区的好镇上,他们觉得他们可以在那里定居并抚养孩子。
他们辛辛苦苦地填写申请表,确保收集大量参考资料,参加课外课程以充实简历。当提交日到来时,他们俩在自己的小客厅里挨着坐,腿上放着电脑,数到三后一起在对方的屏幕上点击“提交”。这就是他们的未来。他们十指交叉着上床睡觉,梦想着他们未来的共同生活。
几个星期后的采访中,结果出来了!雷切尔和大卫一起打开了他们的电子邮件,读完之后,转向对方,两个人都说“你收到了吗?”…
“是的!”,他们都喊道。他们拥抱在一起。雷切尔在大卫的怀里哭了起来,巨大的起伏纯粹是解脱的抽泣。一个半小时的通勤时间过去了,数周的夜班工作结束了。买房子的机会现在实现了!就是这样,他们要一起开始正常的生活。第二天,他们开始找房子。他们申请了抵押贷款,递交了辞呈,准备开始新的生活。一天晚上,在纸板箱和两杯喝了一半的葡萄酒的包围下,大卫单膝跪地求婚了。他答应瑞秋他们会在几个月内结婚并住在自己的房子里。很自然地,她说“是”。
然而,第二天,他们收到了一个炸弹壳 …
显然,在一些候选人的排名中存在“行政错误”,因此,向一些人提供了不正确的职位。全国所有的工作机会都被立即撤回。
瑞秋是受影响的医生之一。这个消息是在一个周五的晚上晚些时候发布的,就在一个为期三天的银行假日周末之前。三天不知道,不确定和痛苦,梦想和期望破灭。目前没有人知道最终的结果会是什么。雷切尔和大卫不得不等待,看看未来会发生什么。突然之间,他们计划好的生活感觉好像还没来得及开始就被夺走了。
因为一个不人道的错误,已经存在的和将要产生的生命实际上被搁置了。
如果这个错误确实影响了瑞秋,而且她在别处找到了一份工作,在一个很远的地方,那么他们将不得不考虑现实,放弃购买他们梦想中的房子,放弃他们今年结婚的计划,甚至现在推迟要孩子。它的不人道是压倒性的。
现在,在这个故事中,重要的是要注意到这个错误,完全真实,并影响到今天英国的初级医生,是一个脚本编程错误,而不是“人工智能”。显然,一些电子表格的格式互不相同,用于编译结果的自动化脚本没有考虑到这一点。然而,它赤裸裸地凸显了行政系统对问责制、稳健性和准确性的道德需求,尤其是因为人工智能被吹捧为非常相似的任务的替代工具。
皇家内科医生学院目前正在解决这个问题(这在 Twitter 上产生了典型的英国标签 #ST3cockup ),在撰写本文时,仍有许多像 Rachel 和 David 这样的初级医生仍在等待发现这个错误对他们和他们的家人意味着什么。
英国的初级医生越来越觉得他们是一种可消耗的资源,而不是护理系统中的人。这个错误发生在最近的Bawa Garba 医生案件(一名初级医生在极其不公平的情况下被取消行医资格)尘埃落定之时,也是在极具破坏性的初级医生因他们强加的新工作合同而罢工仅几年之后。对于一个行政系统来说,产生这样一个令人震惊的新错误,其影响仍在显现,在这样一个脆弱的时刻,听到 NHS 医疗队伍的喧嚣和失望并不奇怪。
将道德融入一切
然而,这里有一个更广泛的图景,我想重点关注:需要深入考虑自动化的潜在影响。
想到如果没有建立道德的人工智能,我们作为一个社会,就有可能将盲目的自主系统引入其中,从而做出比上面的例子更加残酷和不透明的决策,这令人心痛。人工智能没有能力理解一个更大的社会背景来评估它的错误,如果这样的管理错误是由一台机器犯的,我敢肯定骚动会更大。就目前的情况来看,很可能会有人被炒鱿鱼。但是,如果机器脑袋犯了类似的错误,它们会滚动吗?
最近,有一份由威康信托基金资助,由未来倡导撰写的精致报告发表了,关于人工智能在健康领域面临的伦理、社会和政治挑战。这篇报道中有几段话引起了我的注意:
"..一些算法错误会系统性地加重某些群体的负担,如果我们只看整体表现,这个问题就不一定明显。”
我完全同意这种说法。将它放在 ST3 申请错误的背景下,很明显,某些年轻医生群体比其他人负担更重,只有当那些受影响的人开始报告时,问题才可见。我毫不怀疑,无论是谁编写了令人不快的电子表格脚本,都已经检查过它的工作情况(即总体性能良好),但是完全不知道他们的代码能够做什么,并且很可能只有在众所周知的成功之后才被通知。
“……一个系统越开放,包括在算法工具的开发、试运行和采购方面,用户就越能感受到风险的保护……”
在这种情况下,第二种说法也很有趣。如果招聘和选拔系统更加开放、透明,甚至与受其影响的人共同设计,这个错误还会发生吗?例如,如果初级医生知道排名系统、电子表格的格式和用于编译结果的代码,会有人事先注意到吗?现在,我并不是说在这种情况下,我们应该以理想的透明度为目标——我只是提出一个问题“我们在封闭系统和透明系统之间划一条线?”
当涉及到将人工智能和自主系统转化为更具潜在危险的情况时,如生死决策(如自动驾驶汽车、癌症诊断),伦理问题就显得更大了。
我很幸运地与来自 T2 布里斯托尔机器人实验室的艾伦·温菲尔德教授相处了一段时间。他是伦理人工智能和机器人方面的杰出思想家,被广泛认为是该领域的权威。他正与 IEEE 合作,为未来技术引入道德规范创建新标准,这显然是一个热门话题!我从他那里学到的是,一个系统只有在充分考虑并包含了它可能影响的所有人之后,才是不道德的。这是一个非常有趣的想法,我认为应该全面推行。
统计是不道德的
人工智能本质上是一种计算统计学。在数学上,医疗保健中提供分类输出(例如,扫描中的“癌症”或“非癌症”)的人工智能系统可以在接收器操作者曲线(ROC 曲线)上进行评估。(放心吧,我不是要开什么统计学的讲座)。作为一个外行读者,你需要知道的是,这些曲线是一种简单的方法,可以很容易地比较系统。一个系统表现得越好,曲线就越向左上方移动。一个完美的 100%精确的系统甚至不会是一条曲线,它会是图表左上角的一个直角。
Three ROC curves: AUCc performs the best, but the area outside the ROC curve is still an ethical conundrum
在本例中,AUCc 表现最佳,ROC 曲线下面积(AUROC)约为 99%。这近乎完美,但还不够。AUCb 次之,AUROC 约为 85%,AUCa 表现最差,AUROC 约为 80%。在医疗保健领域,你可以绘制人工智能系统的 ROC 曲线,并将其与人类表现进行比较。在媒体上,当你听到一个人工智能“击败人类”时,往往是因为 AUROC 更好,或者曲线位于人类在图上操作的点的上方和左侧(我不会进一步深入语义——但相信我,这个话题有很多激烈的辩论)。
然而,AUROC 是不道德的。事实上,这是完全不道德的。它只报告积极的成功率,而完全忽略了消极的。有一个几乎没有人考虑的伦理灰色区域——我称之为 ROC 曲线(AOROC)外的区域。这个区域可以被认为代表了人工智能系统做出错误决定的所有可能时间。与一系列人类医生相比,人工智能系统的这个领域可能更小,但人类至少可以理解和认识到自己的错误,改变自己的想法,并解释他们的推理。
在上面的例子中,最佳性能系统的 AOROC 面积非常小,可能只有 1%左右。但是,当这 1%的人的自动化决策不正确时,这对他们意味着什么呢?我们如何训练系统认识到它们什么时候错了,以及如何改变它们的想法?我们如何在风险缓解中考虑这些错误以及它们可能带来的潜在生活改变效应?这些问题的答案很难回答,因此经常被忽视。
当我读到主流媒体报道“计算机在 X 击败医生”时,我很恼火,因为我知道在这条线上的某个地方,在 ROC 曲线之外的区域内的风险被忽视了,甚至被理应支持临床安全的医疗器械监管机构忽视了。我向阅读这篇文章的任何人发出挑战,让他们为我找到一个监管机构批准的人工智能系统,该系统发布了关于其失败率的统计数据,以及一份关于他们如何减轻可能受到不利影响的那些人的道德声明。我试图找到这些,但是失败了。
更糟糕的是,这些统计数据完全没有考虑到基础训练数据中的偏差。例如,当他们的高性能分类系统将黑人标记为大猩猩时,谷歌不得不公开道歉,仅仅因为训练数据没有包括白人那么多的黑人面孔。ROC 曲线永远无法证明这种类型的数据偏差,因此我们必须强制使用其他透明方法,以确保人工智能开发人员在陈述他们的性能的同时陈述他们的数据质量。
道德方面的工作已经开始
令人欣慰的是,越来越多的人一致认为,人工智能的伦理是绝对必要的。我咨询的最近一份上议院特别委员会报告强烈建议英国应该为自己打造一个独特的角色,作为伦理人工智能的先驱。
人工智能中伦理的影响现在才触及主流意识。事实上,在最近的脸书数据共享丑闻之后,公司已经建立了一个内部道德部门来调查这类问题,并且微软甚至因为道德问题而停止销售。
我会敦促任何为医疗保健开发人工智能工具的人认真审视他们系统的潜在风险,并尝试跳出框框思考如何确保道德方法。我们经常看到开发人员急于成为“第一个上市的人”,并在头条新闻中宣称他们的性能,而不关心或提及道德,我相信,当这些系统最终失败时,我们开始看到残酷的反乌托邦影响只是时间问题,他们肯定会在某个时候失败——以最近的 NHS 乳腺癌筛查错误为例。在这里,一个自动系统没有在正确的时间邀请妇女进行筛查,导致一些观察家声称多达 270 名妇女可能因此而死亡。这里的伦理分歧是惊人的,甚至已经在下议院进行了辩论。没有人知道谁应该对此负责;甚至运行系统的承包商也在别处推诿责任…
如果我们要避免一个冷酷、不人道的未来,真实的生活被自动化决策及其不可避免的错误所抛弃,我们必须现在就开始谈论并构建伦理。否则,T2 将无法从机器中拯救我们自己。
你可以点击这里了解正在上演的 ST3 传奇。
如果你和我一样对人工智能在医疗保健中的未来感到兴奋,并想讨论这些想法,请联系我们。我在推特上 @drhughharvey
如果你喜欢这篇文章,点击推荐并分享它会很有帮助。
关于作者:
Harvey 博士是一名委员会认证的放射科医生和临床学者,在英国国民医疗服务体系和欧洲领先的癌症研究机构 ICR 接受过培训,并两次获得年度科学作家奖。他曾在 Babylon Health 工作,领导监管事务团队,在人工智能支持的分诊服务中获得了世界第一的 CE 标记,现在是顾问放射科医生,皇家放射学家学会信息学委员会成员,Kheiron Medical 的临床总监,以及人工智能初创公司的顾问,包括 Algomedica 和 Smart Reporting。
Python 中 K 近邻算法的构建与改进
原文:https://towardsdatascience.com/building-improving-a-k-nearest-neighbors-algorithm-in-python-3b6b5320d2f8?source=collection_archive---------3-----------------------
** 注意:自从写了这篇文章,Medium 就不再允许在 Jupyter 笔记本上嵌入代码。要查看本文的配套笔记本和代码,请访问我的 GitHub 上的** 此链接 。
K 近邻算法(K-Nearest Neighbors algorithm,简称 K-NN)是一种经典的机器学习工作马算法,这种算法在深度学习的今天往往被忽视。在本教程中,我们将在 Scikit-Learn 中构建一个 K-NN 算法,并在 MNIST 数据集上运行它。从那里,我们将建立我们自己的 K-NN 算法,希望开发一个比 Scikit-Learn K-NN 具有更好的准确性和分类速度的分类器。在这篇文章的最后,我给好奇的读者列出了一个书单,希望了解更多关于这些方法的知识。
k-最近邻分类模型
Lazy Programmer
K-最近邻算法是一种受监督的机器学习算法,它易于实现,并且具有进行稳健分类的能力。K-NN 最大的优势之一就是它是一个懒学习者。这意味着该模型不需要训练,可以直接对数据进行分类,不像它的其他 ML 兄弟,如 SVM,回归和多层感知。
K-NN 如何工作
为了对某个给定的数据点 p 进行分类,K-NN 模型将首先使用某个距离度量将 p 与其数据库中可用的所有其他点进行比较。距离度量是类似于欧几里德距离、一个简单的函数,它取两个点,并返回这两个点之间的距离。因此,可以假设它们之间距离较小的两个点比它们之间距离较大的两个点更相似。这是 K-NN 背后的中心思想。
这个过程将返回一个无序数组,其中数组中的每个条目保存了模型数据库中的 p 和 n 数据点之一之间的距离。所以返回的数组大小为 n 。这就是 K-最近邻的 K 部分的用武之地: k 是选择的某个任意值(通常在 3-11 之间),它告诉模型在对 p 分类时,它应该考虑多少个**与* p 最相似的点。然后,该模型将采用这些 k 最相似的值,并使用投票技术来决定如何对 p 进行分类,如下图所示。*
Lazy Programmer
图像中的 K-NN 模型的 k 值为 3,中间箭头指向的点就是 p ,需要分类的点。如你所见,圆圈中的三点是最接近,或者说最类似于 p 的三点。因此,使用简单的投票技术, p 将被归类为“白色”,因为白色占了 k 最相似值的大多数。
相当酷!令人惊讶的是,这个简单的算法在某些情况下可以实现超人的结果,并且可以应用于各种各样的问题,正如我们接下来将看到的那样。
在 Scikit-Learn 中实现 K-NN 算法对 MNIST 图像进行分类
数据:
对于这个例子,我们将使用无处不在的 MNIST 数据集。MNIST 数据集是机器学习中最常用的数据集之一,因为它易于实现,但却是证明模型的可靠方法。
MNIST 是一个由 7 万个手写数字组成的数据集,数字从 0 到 9。没有两个手写数字是相同的,有些很难正确分类。对 MNIST 进行分类的人类基准是大约 97.5%的准确率,所以我们的目标是超过这个数字!
算法:
我们将从 Scikit-Learn Python 库中的KNeighborsClassifier()
开始。这个函数有很多参数,但是在这个例子中我们只需要关注其中的几个。具体来说,我们将只为n_neighbors
参数传递一个值(这是 k 值)。weights
参数给出了模型使用的投票系统的类型,其中缺省值是uniform
,这意味着在分类 p 时,每个 k 点的权重相等。algorithm
参数也将保留其默认值auto
,因为我们希望 Scikit-Learn 找到用于分类 MNIST 数据本身的最佳算法。
下面,我嵌入了一个 Jupyter 笔记本,它用 Scikit-Learn 构建了 K-NN 分类器。开始了。
太棒了。我们使用 Scikit-Learn 建立了一个非常简单的 K 近邻模型,在 MNIST 数据集上取得了非凡的性能。
问题?对这些点进行分类花费了很长时间(对于两个数据集分别是 8 分钟和几乎 4 分钟),讽刺的是 K-NN 仍然是最快的分类方法之一。一定有更快的方法…
构建更快的模型
大多数 K-NN 模型使用欧几里德距离或曼哈顿距离作为到达距离度量。这些指标很简单,在各种情况下都表现良好。
一个很少使用的距离度量是余弦相似度。余弦相似性通常不是最佳距离度量,因为它违反了三角形不等式,并且对负数据无效。然而,余弦相似性是完美的 MNIST。它快速、简单,并且比 MNIST 上的其他距离度量标准精度略高。但是,为了尽可能地获得最佳性能,我们必须编写自己的 K-NN 模型。在我们自己制作了一个 K-NN 模型之后,我们应该会得到比 Scikit-Learn 模型更好的性能,甚至更好的准确性。让我们看看下面的笔记本,在那里我们建立了自己的 K-NN 模型。
正如笔记本中所示,我们自己制作的 K-NN 模型在分类速度(相当大的差距)和准确性(在一个数据集上提高 1%)方面都优于 Scikit-Learn K-NN!现在,我们可以继续在实践中实现这个模型,因为我们已经开发了一个真正快速的算法。
结论
这是很多,但我们学到了一些宝贵的经验。首先,我们学习了 K-NN 如何工作,以及如何轻松地实现它。但最重要的是,我们了解到,始终考虑你试图解决的问题和你可用于解决该问题的工具是很重要的。有时候,在解决问题时,最好花时间去试验——是的,建立你自己的模型。正如笔记本电脑所证明的那样,它可以带来巨大的回报:我们的第二个专有模型将使用速度提高了 1.5-2 倍,为使用该模型的实体节省了大量时间。
如果你想了解更多,我鼓励你去查看一下这个 GitHub 库,在那里你会发现这两个模型之间更彻底的分析,以及一些关于我们更快的 K-NN 模型的更有趣的特性!
书单
以下是 K-NN、通用机器学习和深度学习的有用书籍列表,以及提供人工智能和数学讨论的伟大书籍(见哥德尔、埃舍尔、巴赫)
- 统计学习的要素
- 深度学习
- 动手机器学习
- 用于数据分析的 Python
- Python 机器学习简介
- 最近邻法讲座
- 模式识别和机器学习
- 机器学习:概率视角
- 哥德尔、埃舍尔、巴赫
- 我是个奇怪的循环
- 生活 3.0
请在评论中留下您的任何意见、批评或问题!
构建机器学习工程工具
原文:https://towardsdatascience.com/building-machine-learning-engineering-tools-e348ae4edf8?source=collection_archive---------24-----------------------
定制工具案例研究
本文的重点是展示定制的机器学习工具如何帮助简化模型构建和验证工作流程。
这是通过用一个可重用的类抽象出所有的交叉验证和绘图功能来实现的。此外,该课程允许我们并行训练和评分这些模型。最后,我们将展示如何以及为什么使用学习曲线来评估模型性能是非常有益的。
作为案例研究,我们将使用一个移动服务提供商的数据集。我们的任务是建立一个模型,可以识别预测会流失的用户。自然,在基于订阅的服务中,这些数据集是不平衡的,因为大多数用户不会在任何给定的月份取消订阅。
让我们看看这个工具如何帮助我们实现目标!
查看我的 Github 个人资料上的代码。
[## 数据广播 03/数据广播
database-数据科学组合
github.com](https://github.com/DataBeast03/DataBeast/blob/master/ML_Tool/ML_Tool.ipynb)
定制的 ML 工作流工具
我们将使用一个学习曲线工具,它是对 Sklearn 实现的改进
[## sk learn . model _ selection . learning _ curve-sci kit-learn 0 . 19 . 2 文档
将用于生成学习曲线的训练示例的相对或绝对数量。如果数据类型是…
scikit-learn.org](http://scikit-learn.org/stable/modules/generated/sklearn.model_selection.learning_curve.html)
这个自定义工具在以下方面有所改进。
在交叉验证我们的模型时,它根据 4 个分类指标(准确度、精确度、召回率和 F1 值)对模型进行评分。
Sklearn 版本只根据一个指标对模型进行评分。这意味着我们必须对相同的数据交叉验证我们的模型几次,以获得所有 4 个指标的分数,这不是一种非常明智的做法。此外,这个工具有一个方法,可以为您绘制所有 4 个指标的学习曲线。挺有用的!
# here's how you initialize the class
cv = cross_validation(model,
X_train,
Y_train ,
n_splits=10,
init_chunk_size = 100,
chunk_spacings = 25,
average = "binary") # classification model
# Training Predictors
# Training Target
# Number of KFold splits
# initial size of training set
# number of samples to increase the training set by for each iteration
# score metrics need the type of classification average specified (binary or multi-class)
这个工具如何工作
1.从 init_chunk_size
2 中指定的训练集中抽取一定数量的样本。对数据
3 执行 n_splits。在测试褶皱上对模型进行评分,并对所有褶皱的分数进行平均
5。对训练集上的模型进行评分,并对所有折叠的分数进行平均
4。将指标的平均分数存储在一个列表中,用于培训和测试折叠
5。按照 chunk_spacings
6 中指定的数量增加训练集大小。重复步骤 2 至 5,直到所有训练点都包含在训练集
7 中。调用“plot_learning_curve”方法来可视化结果
我们将通过一个例子展示这个工具是如何工作的。
标签不平衡
显然,这些类别是不平衡的:负面案例比正面案例多 6 倍。
我们的假设是,这种不平衡会对我们模型的性能产生负面影响,使模型的性能偏向多数阶级。
如果我们有一个易于阅读的可视化工具来帮助我们分析模型的性能并测试我们的假设,这不是很好吗?
这正是我们的工具做得最好的!
# split predictors from response variable
Y_churn = df.Churn.values
X_churn = df[df.columns[:-1]].values# check label balance
Counter(Y_churn)
# OUTPUT: Counter({False: 2850, True: 483})# accuracy for guessing the majoirty class every time
navie_baseline = (Y_churn.shape[0] - Y_churn.sum())/Y_churn.shape[0]
# OUTPUT: 0.85508550855085508
交叉验证:逻辑回归
# create model
lr = LogisticRegression(penalty='l2')# initialize ml tool
cv = cross_validation(lr,
X_churn,
Y_churn,
average='binary',
init_chunk_size=100,
chunk_spacings=100,
n_splits=3)# call method for model training
cv.train_for_learning_curve()# call method for ploting model results
cv.plot_learning_curve(image_name="Learning_Curve_Plot_LR", save_image=True)
让我们确保我们明白发生了什么。
训练和测试曲线上的每个点都代表了从我们指定的 K 倍计算的指标的平均分数。
请注意,每个培训分数下面都有一个相应的测试分数点(或者在某些情况下,在它上面)。这是因为我们在训练集和测试集上对模型进行评分,以查看模型在两者之间的比较情况。这将使我们能够回答关于偏差和方差的问题。所以让我们继续前进,就这样做吧!
请注意,测试集的准确度达到了 87%的峰值,考虑到最初的准确度是 85%,这并不是很高。但是等等,我们还看到测试集的精确度峰值在 50%左右,召回率峰值在 33%左右,这是为什么呢?!
好吧,记住标签是非常不平衡的。
并且度量召回是模型正确区分不同类别的能力的度量。由于标签严重失衡,相对较高的准确率和较低的召回率实际上是有意义的。准确率相对较高,因为该模型有大量的负面案例进行训练,但召回率较低,因为该模型没有足够的正面案例进行训练,因此无法学习如何区分这两者。精确度本质上是随机的:在所有预测会流失的用户中,只有一半的人真正流失了。
学习曲线还向我们表明,无论我们在训练集中包括多少点,模型都不会继续学习,即提高其性能。我们可以从每个指标的结果中看到这一点。这意味着我们的模型不适合。
在这个工具的帮助下,这难道不是一个简单的分析吗?!?我们所要做的就是传入模型、训练数据和一些参数,机器学习工作流程就会自动完成。
说说高效利用时间吧!
交叉验证:随机林
基于我们以前的结果,我们得出结论,我们需要使用一个更复杂的模型。随机森林是个不错的选择。我们将使用相同的数据和参数。
让我们比较一下现成的随机森林与我们的逻辑回归的表现。
我们可以看到,准确率跃升至 95%,召回率约为 78%,精确度约为 94%。
我们当然可以把这种表现归功于 Random Forest 的架构,即。系综树和引导聚合。
更重要的是,我们可以从学习曲线中看到,模型的性能在大约 1500 的训练集规模时饱和,并且几乎没有过度拟合:训练和测试的准确度和精确度分数非常非常接近,尽管两者之间在召回率方面有很大差距。
那么这些结果意味着什么呢?
综合起来看,回忆告诉我们,10 个搅棒中只有 7 个能与非搅棒区分开,Precison 告诉我们,在这 7 个搅棒中,10 个中有 9 个能被正确归类为搅棒。
那么我们该如何进行呢?
好吧,假设对于我们的商业目标来说,这些结果还不够好;对我们来说,在预测中犯这样的错误仍然代价太高。好的,我们有几个选择:我们可以用网格搜索改进模型,训练不同的模型,或者我们可以改进数据。
假设随机森林在召回度量上过度拟合,这表明更复杂的模型只会导致更多的过度拟合,而不太复杂的模型(即逻辑回归)会导致欠拟合。所以这意味着我们需要改进数据。为此,一个显而易见的切入点是阶级失衡。
请注意,当我们的机器学习管道高效时,我们的分析是多么轻松?我们可以花更少的时间对模型构建的基础设施进行编码,而更多地关注结果以及它们所建议的行动过程。
并行处理
在实践中,我们会将我们的重点放在平衡类上。然而,在这里,我们将用一个更复杂的模型来证明这个工具的某个功能的有效性。
支持向量机(SVM)通常需要很长时间来训练。它们是展示该工具并行处理功能价值的绝佳模型。
我们只需传入我们希望用于并行处理的 CPU 数量,然后交叉验证类将接管剩下的部分!
首先,为了真正看到效果,让我们通过将 init_chunk_size 和 chunk _ spacings 减少到 50,并将 n_splits 增加到 10 来创建更多的模型进行训练。接下来,让我们用系列交叉验证训练 SVC 来计时跑步。
start = time()
# create model
svc = SVC(C=1.0, kernel='rbf', gamma='auto')# initialize ml tool
cv_svc = cross_validation(svc,
X_churn,
Y_churn,
average='binary',
init_chunk_size=50,
chunk_spacings=50,
n_splits=10)# call method for model training
cv_svc.train_for_learning_curve()
end = time()print("Time Elapsed {:.3}".format(end - start))
# OUTPUT: Time Elapsed 64.1
现在,让我们并行地对 SVC 的交叉验证训练进行计时。
start = time()
n_cpus = 7
# create model
svc = SVC(C=1.0, kernel='rbf', gamma='auto')# initialize ml tool
cv_svc = cross_validation(svc,
X_churn,
Y_churn,
average='binary',
init_chunk_size=50,
chunk_spacings=50,
n_splits=10)# call method for model training
cv_svc.train_for_learning_curve_PARALLEL(n_cpus)
end = time()print("Time Elapsed {:.3}".format(end - start))
# OUTPUT: Time Elapsed 29.0
我们观察到的是,并行训练时,训练时间是串行训练时间的 33%。当我们拥有更大的数据集时,这将节省大量时间。
最后,正如我们所怀疑的,使用比随机森林更复杂的(现成的)模型导致了更多的过度拟合。呀!
可量测性
包含并行处理的目的是帮助这个工具可扩展到更大的数据集,但是有一个限制。该工具是中小型数据集的理想选择。
当数据集达到 TB 甚至 100 GB 时,存在一个更具可扩展性的解决方案,即 Spark。Spark 可以在后端创建一个类似的工具。
结论
通过使用构建模型来预测用户流失的案例研究,我们展示了如何使用 cross_validation 数据工具来简化机器学习模型的构建和验证过程,并且节省时间。
这是通过抽象出围绕模型构建的所有模板代码,并简单地要求开发人员传入模型、训练数据和一些参数来实现的。
我们还展示了在学习曲线上显示 4 个最常见的分类指标的价值。以及它们如何对分析偏差和方差等模型误差以及发现过度训练具有不可估量的价值。
请随意在我的 Github 帐户上叉这个项目,并让我知道你在评论中的想法!
从非结构化数据构建机器学习模型
原文:https://towardsdatascience.com/building-machine-learning-model-from-unstructured-data-dd2d0263f1db?source=collection_archive---------6-----------------------
你可能对结构化数据很熟悉,它无处不在。在这里,我想重点讨论我们如何将非结构化数据转换为数据机器可以处理的数据,然后进行推理。
从结构化数据到非结构化数据
我们可以在我们的数据库系统中找到容易结构化的数据,如个人资料记录、交易记录、项目记录。随着时间的推移,人们开始思考如何处理文本、图像、数据卫星、音频等非结构化数据。这可能会给你一些有用的东西,让你在你的业务决策。
在这种情况下,我从 kaggle 竞赛中选取了“正在烹饪什么”。竞赛要求你根据食物的成分对食物进行分类。我们将使用一些流行的库来帮助我们建立机器学习模型,Pandas,Numpy 和 Matplotlib 是你所熟悉的。
加载数据
数据清理
在这一部分中,为了 tf-idf 矢量化的目的,我将列表连接到 ingredients 中的字符串中。我假设所有的成分只有一克。
特征抽出
这里我使用 TF-IDF 矢量器和 ngram range unigram 和 bigram。拟合和转换训练数据集。在它完成了变身之后。我使用 chi2 进行特征选择,以减少维度空间。
建模
我将数据集分割成测试大小为 0.2 的训练测试分割,分割后,由于数据集存在不平衡问题,我使用 SMOTE 进行了过采样。我认为这部分非常重要,因为不平衡数据集是分类的问题,你的模型可能偏向干扰..
这次我用三个模型多项式朴素贝叶斯、支持向量机和决策树。朴素贝叶斯和决策树参数是默认值,但对于 SVM 使用
Hyperparameter SVM
估价
结果表明,SVM 最适合这一分类。
如果你喜欢这篇文章,请随意点击鼓掌按钮👏🏽如果你对接下来的帖子感兴趣,一定要在 medium 上关注我
人工智能驱动的建筑管理
原文:https://towardsdatascience.com/building-management-powered-with-artificial-intelligence-6398b4b30ef4?source=collection_archive---------11-----------------------
你工作的地方哪个区域最忙?如果你更好地利用你的办公室,你能节省多少钱?
据统计,办公空间产生的费用仅次于人事费。与此同时,大办公室的设施利用率通常包含很大比例的浪费,如果加以监控,这些浪费是可以很容易避免的。
在无题王国,我们相信技术是我们用来支持公益事业的工具,一点一点地改变世界,让世界变得更美好。设施管理可能不是人工智能技术最性感的应用,但考虑到它在经济和生态中的作用,它是当代企业最迫切的需求之一。
今天,我们自豪地向大家介绍我们的合作伙伴,verge sense——一家由 Y CombinatorY Combinator支持的创新公司。他们的“传感器系统”智能平台使用计算机视觉来测量办公空间的利用率和占用率。我正在和丹·瑞安,VergeSense 的首席执行官兼联合创始人交谈。
Dan Ryan, the CEO and Co-founder of VergeSense
N :丹,你是怎么想出这样一个用 AI 传感器赋能楼宇管理的创新概念的?这个想法是如何发展的,你打算用维杰森解决什么问题?
我在大厦管理部门工作了大约 10 年,与许多物业经理、大厦业主或其他占用大厦的人谈过话。我们观察到的一贯问题是,建筑运营商和业主没有关于他们的建筑实际使用情况的数据。与此同时,建筑管理费用通常是这些公司的第二大成本,仅次于员工工资。
最常见的情况是资产的巨大支出,以及没有关于这些资产如何使用的信息。在这一点上,我们决定使用人工智能传感器收集关于建筑如何运行的数据,测量建筑中到底发生了什么,并且提供分析,这将帮助建筑专业人员削减开支和更有效地运营他们的办公室。
n:是什么使维珍森独一无二?你最大的优势是什么?
D: 首先,VergeSense 比我们任何竞争对手的解决方案都便宜 10-100 倍,并且更易于安装和操作。虽然我们的大多数竞争对手使用非常昂贵的有线硬件,但 VergeSense 传感器是无线的,它们依靠电池供电运行多年。
另一个优势是,VergeSense 将传感器的数据传回云端,无需费力将系统集成到企业 IT 网络中。这很容易,而且是一个真正的金钱和能源节省。
N:让 VergeSense 基于人工智能技术的目的是什么?人工智能如何提高你的解决方案的价值?
D: 我们在构建优化的神经网络方面做了大量工作,并且我们击中了靶心。VergeSense 传感器拥有 99%的数据准确性,同时,它运行在一个非常便宜的硬件上,我们不使用任何 GPU 或昂贵、复杂的机器。基于人工智能的 VergeSense 让我们创建一个高度精确的解决方案,节省时间(通常需要安装)和金钱,并提供舒适的使用。
我们还不断**提高传感器的数据收集能力。**我们目前在市场上销售的产品被认为是一种统计人数的产品,有一群客户对收集建筑中其他物体的信息感兴趣,例如,表示拿出 trush 或清理厨房的必要性。
有了 VergeSense,我们可以使用相同的硬件,并多年来更新传感器,让它收集不同类型的数据。
在解决方案的帮助下,我们能从分析数据中学到什么?
在无题王国团队的帮助下,我们花了很大力气将 VergeSense 收集的数据可视化。
该工具有两个组成部分:第一个是一个很好的,容易理解的数据可视化,允许用户比较不同类型的空间。第二个提供了一些可操作的见解,帮助用户理解正在发生的事情并采取行动。
例如,您分析数据并了解到您的一个会议室只有 10–15%被占用。在这一点上,VergeSense 会给你一些建议,比如放弃大尺寸房间,把它重新整理成几个小房间。
N:如果让你说出 VergeSense 项目最大的挑战是什么?
经营公司的头 6 个月通常是最具挑战性的,因为你基本上没有信誉可言。你正从零开始,面临最大的挑战:获得你的第一个客户。
我们很快就造出了第一个产品——我可以说那是一个基本的原型,但它已经是我们能够销售的东西了。在与 VergeSense 合作四个月后,我们接触到了第一个客户。它提供了验证产品的可能性,并确保它真正解决了我们想要解决的问题。
现在,当我们有几十个客户时,我们的主要挑战是扩大规模,撬动市场,并为我们的客户提供足够的支持。
n:数字化转型在工作环境中的重要性是什么?
D: 工作中的数字化转型是消除工作挫折感、提高生产力和增强工作舒适度的绝佳机会。使用 VergeSense 的传感器技术可以帮助人们更有效地工作。
在大型组织中,通常很难找到空闲的会议室或预订会议时段。缺少空闲空间可能是一个常见的问题,尤其是在远程工作的环境中——假设四个在线会议参与者中有一个不能出席会议。会发生什么?整个小组的会议可能会被取消。
此外,从空间中获得更高的效率有助于公司释放通常用于建筑运营的那部分资本。现在,他们获得了巨大的资本投资回报,并将这笔预算用于其他有助于业务发展的事情上。
N:你的客户对 VergeSense 有什么反馈?
D: VergeSense 的用户喜欢它的简单性和无线功能。他们称赞 VergeSense 的第二点是我们产品的准确性和获得具体入住人数的机会,以衡量房间的利用率水平。
在软件方面,我们的客户喜欢高级分析中数据可视化的简单性。我们还收到了许多热情的客户对 VergeSense UX/UI 的反馈——这正是无题王国团队真正帮助我们的地方,因为你们的设计团队非常强大,富有创造力。
听到如此热情的反馈真是太好了。您能告诉我们您的客户是如何为新平台的创建做出贡献的吗?
我们真的很快就打造出了 VergeSense MVP。在我们把它推向市场后,我们获得了很多用户的反馈。根据我们用户的提示,我们利用他们的意见重新设计并与未命名的王国团队一起重新推出了 VergeSense。
即使在今天,在我们进行的几乎每一次客户演示或致电中,我们都在收集对额外功能的请求以及对可视化数据的见解。该产品的用户界面采用模块化设计,因此很容易根据用户的建议添加组件。
N: 在 VergeSense 网站上,你提到了传感器可能带给办公室的 3 个主要价值。你能一个一个地描述他们吗?
我已经谈了很多关于 VergeSense 帮助公司更有效地管理他们的工作场所的事情。除此之外,我们的解决方案还为**带来了发现节约的机会。**无论是将大房间分割成小房间,还是决定是否需要租用一间更大的办公室,VergeSense analysis 都能让建筑经理更有效地管理预算。
最后但同样重要的是,VergeSense 传感器数据可能会与公司的生产力工具集成在一起,以增强团队的能力。
会议室在哪里?书桌在哪里?
自助餐厅排队有多长?
VergeSense 可以为您提供所有这些问题的答案,节省时间,让人们保持专注,提高他们的生产力和工作满意度。
你能想出 VergeSense 如何在你的一些客户公司提高工作效率的具体统计数据吗?
D: 对于我们的第一个客户,我们已经做了一个初步的试点项目,因此我们在 6 个月的时间里部署了传感器。我们收集了关于办公室绩效的数据,我们发现办公室的利用率非常低。尽管该团队声称他们需要更多的空间,但我们的分析显示,许多桌面区域实际上根本没有流量。利用 VergeSense 的数据,我们的客户在同一栋建筑中重新设计了另一层楼,配有更小的办公室。在此之后,我们比较了重新设计的地板与原始地板的效率。事实证明,与旧设计相比,优化后的办公室容纳了 50%的员工。当我们看房地产价格时,优化一个楼层每年为公司节省 40 万美元。
N:现在,让我们暂时跳过开发 VergeSense 的过程。在你看来,由无题王国开发者、UX/UI 设计师和产品负责人组成的团队跨职能运行你的项目有什么价值?
D: 在跨职能团队中发展 VergeSense 是非常重要的。它给了我们一个非常严格的产品开发方法。我们没有马上开始建造东西。我们一直等到真正定义了产品的用途、用户、他们面临的问题,以及我们如何帮助他们解决这些问题。《无题王国》展示了强大的产品管理纪律,在探索会议后跑一周短跑给了我们“加油,加油,加油”的感觉。
在建立一个产品后,我们向用户展示 VergeSense,征求他们的反馈,并将他们的反馈纳入到进一步的开发中,以更好地满足我们客户的需求。
你提到了你和我们团队一起参加的主题探索会议。他们如何影响重新设计的方向?
D: 在深入了解和揭示我们正在努力解决的真正客户问题方面,发现会议非常有见地。在我们写一行代码之前提前做这件事给了项目超高效率,因为在会议之后,我们确切地知道我们应该朝什么方向前进。
N:你是怎么知道无题王国的,是什么让你选择我们作为你的合作伙伴?
我想我第一次在 Y-Combinator 的论坛帖子上看到你,但也可能是 Quora 的帖子。我记不清了,但我知道我是在网上遇到你的。我已经知道波兰在技术专业和设计方面享有盛誉——之前,我曾与一些波兰开发人员和设计师合作过,波兰软件开发和 UX/UI 设计的水平给我留下了深刻的印象。
你能告诉我们一个获得风险投资的小故事吗?这条路很难走吗?
我们很早就申请了 Y-combinator,实际上甚至在我和我的联合创始人成立之前。Y-combinator 项目让我们真正接触到了硅谷的现实。在 YC 之后,我们得到了一家名为 Bolt 的风险投资公司的额外投资。从今天的角度来看,我真的为 VergeSense 的融资之旅感到自豪。但事实上,这一切都是有机发生的;背后没有秘方。老实说,当我们获得 Y- Combinator 的第一笔资金时,我感到非常震惊。
N:你能给其他正在努力融资的公司一些建议吗?
我总是不太愿意给出建议,因为每个企业都不一样,所以没有放之四海而皆准的成功之道。这些建议永远不能从一家公司转到另一家公司。但如果让我告诉其他创业者一件事,我会说:这从来都不容易。确保你真的相信你正在做的事情,如果你真的相信,不要放弃。
影响我职业生涯最重要的是坚持。在创业的世界里,会有成千上万的事情出错,会有成千上万的挑战发生。你只需要保持冷静,坚持下去,保持灵活。我们在 VergeSense 制造的第一个产品与我们最终的产品完全不同。我们倾听客户的心声,重新定义他们的需求,并根据他们的需求调整我们的解决方案。
维杰森的下一步是什么?你短期和长期的主要挑战是什么?
在短期内,我们计划面对运营挑战:扩大业务规模、收集更多订单和运送更多产品。显然,这伴随着我们团队的成长,以支持 VergeSense 客户。此外,根据用户的反馈,我们可能会找出我们想要构建的下一个关键特性。
从长远来看,我们希望找出使用我们的平台可以解决的其他问题。目前,我们正忙于 VergeSense 在房地产市场的应用。但我确信,VergeSense 传感器和分析在未来也会给其他行业带来影响。敬请关注,看我们成长!
预测患者存活率:预测
原文:https://towardsdatascience.com/building-my-first-data-science-project-part-2-prediction-cc4d971aa17a?source=collection_archive---------7-----------------------
构建我的第一个数据科学项目
得到数据后,很容易立即尝试拟合几个模型并评估它们的性能。然而,首先要做的是探索性数据分析(EDA),它允许我们探索数据的结构,并理解控制变量的关系。任何 EDA 都应该包括创建和分析几个图,并创建汇总统计数据,以考虑我们的数据集中存在的模式。
如果你想知道,我是如何为这个特定的项目执行 EDA 的,你可以阅读这个 以前的帖子 。
从这个项目的 EDA 中,我们了解了数据集的一些重要特性。首先,当一个类别中的观察值总数明显低于另一个类别中的观察值时,不会出现 类别不平衡*。此外,我们的一些变量显示了偏斜度,在对它们进行对数转换后,偏斜度得到了固定,并且没有变量
显示出与其他变量的完美线性关系,尽管在其中一些变量中,我们可以观察到相互作用的趋势。*
机器学习预测
执行机器学习时要做出的一个主要决定是选择适合我们正在处理的当前问题的适当算法。
监督学习指的是从带标签的训练数据集中推断出一个函数的任务。我们将模型拟合到带标签的训练集,主要目标是找到最佳参数,这些参数将预测测试数据集中包含的新示例的未知标签。有两种主要类型的监督学习:回归,其中我们希望预测一个实数标签,以及分类,其中我们希望预测一个分类标签。
在我们的例子中,我们有一个带标签的数据集,我们想使用分类算法在分类值 0 和 1 中找到标签。
我们可以找到许多分类监督学习算法,一些简单但有效,如线性分类器或逻辑回归,另一些更复杂但功能强大,如决策树和 k-means。
在这种情况下,我们将选择随机森林算法。随机森林是最常用的机器学习算法之一,因为它非常简单、灵活和易于使用,但产生可靠的结果。
简而言之,随机森林创建了多个决策树的森林和,并集合它们以获得更准确的预测。随机森林相对于决策树的优势在于,单个模型的组合改善了整体结果,并且通过从特征的随机子集创建更小的树来防止过度拟合。**
因此,我们将首先从 scikit 加载包——了解我们需要执行随机森林,然后还要评估模型。我们还将使用 0 或 1 或NaN
替换分类值,并将所有变量转换为浮点型,并对变量进行对数转换以固定偏斜度,就像我们在 EDA 中所做的那样。我们将再次检查每个变量中缺失值的总数:
在 EDA 中,我们丢弃了所有的NaN
值。这里,我们需要评估处理它们的最佳方法是什么。
处理缺失数据有几种方法 但没有一种是完美的。第一步是了解数据丢失的原因。在我们的例子中,我们可以猜测分类变量中缺失的值可能是由于缺少特征,而不是作为no
输入为空,或者没有进行测试。此外,连续变量中的缺失值可能是由于缺乏对该特定患者进行的生化研究,或者是因为参数在正常范围内且没有记录下来。
在这两种情况下,我们都有可能在出现时随机缺失值(该值缺失的事实与假设值无关)或时不随机缺失值(该缺失值取决于假设值)。如果是第一种情况,我们可以安全地删除NaN
值,而在最后一种情况下,删除它是不安全的,因为这个丢失的值告诉我们一些关于假设值的信息。所以在我们的例子中,一旦我们要训练我们的模型,我们将估算缺失值的值。
特征缩放或数据归一化,一种用来标准化自变量范围的方法,也是训练很多分类器之前非常重要的一步。如果数据不在同一范围内,一些模型的性能会很差。随机森林的另一个优点是不需要这一步。
将数据集分为训练数据集和测试数据集
为了训练和测试我们的模型,我们需要将我们的数据集分成子数据集, 训练和测试数据集 。该模型将从训练数据集中学习,以推广到其他数据;测试数据集将用于“测试”模型在训练和拟合步骤中学到了什么。
常用 80%-20% 的规则对原始数据集进行拆分。使用可靠的方法分割数据集以避免数据泄漏是很重要的;这是存在于测试集中的例子,它们也存在于训练集中,并且可能导致过度拟合。
首先,我们将把除因变量(“Class”)之外的所有列分配给变量 X,把列“Class”分配给变量 Y。
,然后我们将从 scikit-learn 库中train_test_split
把它们分成 X_train、X_test、Y_train 和 Y_test。添加random_state
很重要,因为这将允许我们在每次运行代码时得到相同的结果。
**注意:训练/测试分割有一些缺点,因为一些模型需要调整超参数,在这种情况下,也在训练集中完成。避免这种情况的一种方法是创建一个规则为 60/20/20%的训练/验证/测试数据集。有几种有效的方法可以做到这一点,我们将在下面看到。
训练随机森林
现在很容易估算缺失值(使用Imputer
),使用 Scikit-learn 软件包创建和训练基本随机森林模型。我们将开始应用.ravel()
到 Y_train 和 Y_test 来展平我们的数组,因为不这样做将会引起我们模型的警告。
然后,我们将使用函数Imputer
和策略most_frequent
来估算缺失值,这将替换列(轴= 0)中最频繁出现的值的缺失值。值得注意的是,这样做可能会引入错误和偏见,但当然,正如我们之前所述,没有完美的方法来处理缺失数据。
我们的基本模型现在已经被训练,并且已经学习了我们的自变量和目标变量之间的关系。现在,我们可以通过对测试集进行预测来检查我们的模型有多好。然后,我们可以将预测与我们已知的标签进行比较。
我们将再次估算测试集中的缺失值,并使用函数predict
和指标accuracy_score
来评估我们模型的性能。
正如我们在上面看到的,我们的基本模型有 74.19%的准确率,这告诉我们它还需要进一步改进。
超参数调整
有几种方法可以改进我们的模型:收集更多的数据,调整模型的超参数或选择其他模型。我们将选择第二个,我们现在将调整我们的随机森林分类器的超参数。
模型参数通常在训练期间学习;然而,超参数必须在训练前手动设置。对于随机森林,超参数包括:
- n_estimators:森林中的树木数量
- max_features:每个树中的最大特征数
- max_depth:所有树的最大分割数
- bootstrap:是否实现 bootstrap 来构建树
- 标准:评估决策树的停止标准
当然,当我们实现基本的随机森林时,Scikit-learn 实现了一组默认的超参数,但是我们不确定这些参数对于我们的特定问题是否是最优的。
在这一点上,我们需要考虑两个概念:欠拟合和过拟合。 欠拟合 发生在模型过于简单,与数据拟合不太好的时候:方差小,偏差大。另一方面, 过拟合 发生在模型对训练集调整得太好而在新的例子中表现不佳的时候。如果我们调整训练数据集中的超参数,我们可能会使随机森林分类器过拟合。因此,我们将回到之前提到的:交叉验证。**
交叉验证的方法有很多,最著名的有: K 重交叉验证和留一交叉验证。在我们的例子中,我们将使用第一个:我们将把我们的数据分成 K 个不同的子集,使用 k-1 个子集作为我们的训练集,最后一个子集作为我们的测试数据。为了调整我们的超参数,我们将对 K-子集交叉验证执行多次迭代,但每次使用不同的模型设置。然后,我们比较所有的模型,选择最好的一个;然后,我们将在完整的训练集中训练最好的模型,并在测试集上对其进行评估。我们将利用 Scikit-learn 中的 GridSearchCV 包来执行这项任务。
我们将确定想要优化的参数和值,然后执行 GridSearchCV,并将获得的最佳参数设置为我们的模型。
正如我们在上面看到的,GridSearchCV 将我们的准确率从 74%提高到了 77%。尽管这不是一个很大的改进,但据报道,使用这个数据集,其他研究仅达到 80%的准确率。因此,考虑到这一点以及数据集有许多缺失数据且不大(只有 155 个样本)的事实,我们可以继续分析其他模型指标。
测试集指标
既然我们已经优化了超参数,我们将继续评估我们的模型。首先,我们将创建一个混淆矩阵,它将根据我们的预测值告诉我们真阴性、假阳性、假阴性和真阳性值,并使用 seaborn heatmap 绘制它:
真阴性(TN)|假阳性(FP)
—————
假阴性(FN)|真阳性(TP)
分析混淆矩阵,我们可以预期我们的模型显示出比精确度(TP/TP+FP)更高的召回率(TP/TP+FN ),但是两个参数都将高于精确度(TP+TN)/总数。根据我们认为我们的模型需要解决的问题,可以考虑这三个参数。我们稍后将回到这些问题上。
我们可以使用 ROC 曲线并计算曲线下的面积来进一步研究假阳性率和真阳性率,曲线下的面积也是我们模型的预测能力的度量(如果该值更接近 1,则意味着我们的模型在将随机样本区分为两类方面做得很好)。
从 ROC 曲线中,我们了解到我们的模型在区分两个类别方面做得不好,因为 auc 是 0.60。我们可以通过收集更多的数据并添加到模型中来改善这个问题。
最后,我们可以分析精确-回忆曲线:
我们可以观察到,对于不同的值,精度-召回率关系是相当恒定的,表明我们的模型具有良好的精度和召回率。这是因为与真阴性、假阳性和假阴性相比,真阳性值相当高。重要的是要记住,由于召回率和精确度的公式,当一个高,另一个低,推动我们找到一个平衡,两者对我们的模型都足够高。
解读结果
在完成我们的项目之前,我们可以做的最后一件事是评估变量的重要性,也就是量化每个变量对我们的模型有多有用。
我们可以观察到年龄、蛋白时间、alk_phosphate、胆红素、不适、腹水是我们模型的一些最重要的变量。这反映了我们之前在 EDA 中看到的情况,并强调了在开始机器学习算法之前执行这种探索性分析的重要性。
总结
因此,在将随机森林应用于我们的数据集后,我们可以得出结论,我们的最佳模型能够预测肝炎患者的存活率,准确率为 77%,精确度和召回率约为 80%。这不是最好的情况,因为我们希望我们的模型表现得更好,特别是在这种涉及患者生存的情况下。然而,中等的好结果可能是由于数据库小和大量的缺失值。
从头开始构建神经网络
原文:https://towardsdatascience.com/building-neural-network-from-scratch-9c88535bf8e9?source=collection_archive---------0-----------------------
使用 Python 中的 Numpy 对多层感知器的简单介绍。
在这本笔记本中,我们将使用 numpy 构建一个神经网络(多层感知器),并成功训练它识别图像中的数字。深度学习是一个庞大的主题,但我们必须从某个地方开始,所以让我们从多层感知器的神经网络的基础开始。你可以在笔记本版本这里或者我的网站找到同样的博客。
什么是神经网络?
神经网络是一种机器学习模型,它受到我们大脑中神经元的启发,其中许多神经元与许多其他神经元相连,以将输入转化为输出(简单吧?).大多数情况下,我们可以看到任何机器学习模型,并将其视为一个接受输入并产生所需输出的函数;神经网络也是一样。
什么是多层感知器?
多层感知器是一种网络类型,其中一组感知器的多个层堆叠在一起形成一个模型。在我们进入一个层和多个感知器的概念之前,让我们从这个网络的构建模块开始,它是一个感知器。将感知器/神经元视为一个线性模型,它接受多个输入并产生一个输出。在我们的例子中,感知器是一个线性模型,它接受一组输入,将它们与权重相乘,并添加一个偏差项以生成一个输出。
Fig 1: Perceptron image
Image credit = https://commons . wikimedia . org/wiki/File:perceptron . png/
现在,如果我们将这些感知机堆叠在一起,它就变成了一个隐藏层,在现代深度学习术语中也称为密集层。
密集层,
注意,偏差项现在是一个向量,W 是一个权重矩阵
Fig 2: Single dense layer perceptron network
Image credit = http://www . t example . net/tikz/examples/neural-network/
现在我们了解了密集层,让我们把它们加起来,这个网络就变成了一个多层感知器网络。
Fig 3: Multi layer perceptron network
Image credit = http://pubs . scie pub . com/ajmm/3/3/1/figure/2s
如果你已经注意到我们的稠密层,只有线性函数,并且线性函数的任何组合只导致线性输出。由于我们希望我们的 MLP 具有灵活性并学习非线性决策边界,我们还需要将非线性引入网络。我们通过添加激活函数来实现引入非线性的任务。有各种各样的激活函数可以使用,但我们将实现整流线性单位(ReLu),这是一个流行的激活函数。ReLU 函数是一个简单的函数,它对于任何小于零的输入值都是零,对于大于零的值也是相同的值。
ReLU 功能
现在,我们理解了密集层,也理解了激活函数的目的,剩下的唯一事情就是训练网络。为了训练神经网络,我们需要一个损失函数,每一层都应该有一个前馈回路和反向传播回路。前馈回路接收输入并产生输出以进行预测,反向传播回路通过调整层中的权重以降低输出损失来帮助训练模型。在反向传播中,权重更新通过使用链规则的反向传播梯度来完成,并使用优化算法来优化。在我们的例子中,我们将使用 SGD(随机梯度下降)。如果你不理解梯度权重更新和 SGD 的概念,我推荐你看 Andrew NG 讲座机器学习第一周。
因此,总结一个神经网络需要几个构件
- 致密层 —全连通层,
- ReLU layer (或任何其他引入非线性的激活功能)
- 损失函数——(多类分类问题时的交叉熵)
- 反向传播算法 —具有反向传播梯度的随机梯度下降
让我们一个一个地接近他们。
编码从这里开始:
让我们从导入创建神经网络所需的一些库开始。
from __future__ import print_function
import numpy as np ## For numerical python
np.random.seed(42)
每一层都有一个向前传递和向后传递的实现。让我们创建一个可以向前传递的主类层*。向前()和向后传球。向后()。*
class Layer:
#A building block. Each layer is capable of performing two things: #- Process input to get output: output = layer.forward(input)
#- Propagate gradients through itself: grad_input = layer.backward(input, grad_output)
#Some layers also have learnable parameters which they update during layer.backward.
def __init__(self):
# Here we can initialize layer parameters (if any) and auxiliary stuff.
# A dummy layer does nothing
pass
def forward(self, input):
# Takes input data of shape [batch, input_units], returns output data [batch, output_units]
# A dummy layer just returns whatever it gets as input.
return input def backward(self, input, grad_output):
# Performs a backpropagation step through the layer, with respect to the given input.
# To compute loss gradients w.r.t input, we need to apply chain rule (backprop):
# d loss / d x = (d loss / d layer) * (d layer / d x)
# Luckily, we already receive d loss / d layer as input, so you only need to multiply it by d layer / d x.
# If our layer has parameters (e.g. dense layer), we also need to update them here using d loss / d layer
# The gradient of a dummy layer is precisely grad_output, but we'll write it more explicitly
num_units = input.shape[1]
d_layer_d_input = np.eye(num_units)
return np.dot(grad_output, d_layer_d_input) # chain rule
非线性关系层
这是你能得到的最简单的层:它简单地将非线性应用于你的网络的每个元素。
class ReLU(Layer):
def __init__(self):
# ReLU layer simply applies elementwise rectified linear unit to all inputs
pass
def forward(self, input):
# Apply elementwise ReLU to [batch, input_units] matrix
relu_forward = np.maximum(0,input)
return relu_forward
def backward(self, input, grad_output):
# Compute gradient of loss w.r.t. ReLU input
relu_grad = input > 0
return grad_output*relu_grad
致密层
现在让我们构建一些更复杂的东西。与非线性不同,密集层实际上有东西要学。
密集层应用仿射变换。在矢量化形式中,它可以描述为:
在哪里
- x 是形状[批量大小,数量特征]的对象特征矩阵,
- w 是权重矩阵[特征数量,输出数量]
- b 是 num_outputs 偏差的向量。
W 和 b 都在层创建期间初始化,并在每次调用 backward 时更新。请注意,我们正在使用 Xavier 初始化,这是一个训练我们的模型更快收敛的技巧阅读更多。我们不是用随机分布的小数字初始化我们的权重,而是用平均值 0 和方差 2/(输入数+输出数)初始化我们的权重
class Dense(Layer):
def __init__(self, input_units, output_units, learning_rate=0.1):
# A dense layer is a layer which performs a learned affine transformation:
# f(x) = <W*x> + b
self.learning_rate = learning_rate
self.weights = np.random.normal(loc=0.0,
scale = np.sqrt(2/(input_units+output_units)),
size = (input_units,output_units))
self.biases = np.zeros(output_units)
def forward(self,input):
# Perform an affine transformation:
# f(x) = <W*x> + b
# input shape: [batch, input_units]
# output shape: [batch, output units]
return np.dot(input,self.weights) + self.biases
def backward(self,input,grad_output):
# compute d f / d x = d f / d dense * d dense / d x
# where d dense/ d x = weights transposed
grad_input = np.dot(grad_output, self.weights.T)
# compute gradient w.r.t. weights and biases
grad_weights = np.dot(input.T, grad_output)
grad_biases = grad_output.mean(axis=0)*input.shape[0]
assert grad_weights.shape == self.weights.shape and grad_biases.shape == self.biases.shape
# Here we perform a stochastic gradient descent step.
self.weights = self.weights - self.learning_rate * grad_weights
self.biases = self.biases - self.learning_rate * grad_biases
return grad_input
损失函数
由于我们希望预测概率,因此在我们的网络上定义 softmax 非线性并计算给定预测概率的损失是合乎逻辑的。但是,有一种更好的方法可以做到这一点。
如果我们将交叉熵的表达式写为 softmax logits (a)的函数,您会看到:
如果我们仔细看看,我们会发现它可以重写为:
它被称为 Log-softmax,它在各个方面都优于 naive log(softmax(a)):
- 更好的数值稳定性
- 更容易得到正确的导数
- 计算速度略微加快
那么,为什么不在我们的计算中使用 log-softmax,而不去估算概率呢?
def softmax_crossentropy_with_logits(logits,reference_answers):
# Compute crossentropy from logits[batch,n_classes] and ids of correct answers
logits_for_answers = logits[np.arange(len(logits)),reference_answers]
xentropy = - logits_for_answers + np.log(np.sum(np.exp(logits),axis=-1))
return xentropydef grad_softmax_crossentropy_with_logits(logits,reference_answers):
# Compute crossentropy gradient from logits[batch,n_classes] and ids of correct answers
ones_for_answers = np.zeros_like(logits)
ones_for_answers[np.arange(len(logits)),reference_answers] = 1
softmax = np.exp(logits) / np.exp(logits).sum(axis=-1,keepdims=True)
return (- ones_for_answers + softmax) / logits.shape[0]
全网络
现在,让我们将刚刚构建的内容结合到一个有效的神经网络中。正如我之前所说的,我们将使用手写数字的 MNIST 数据作为我们的例子。幸运的是,Keras 已经有了 numpy 数组格式的,所以让我们导入它吧!。
import keras
import matplotlib.pyplot as plt
%matplotlib inlinedef load_dataset(flatten=False):
(X_train, y_train), (X_test, y_test) = keras.datasets.mnist.load_data() # normalize x
X_train = X_train.astype(float) / 255.
X_test = X_test.astype(float) / 255. # we reserve the last 10000 training examples for validation
X_train, X_val = X_train[:-10000], X_train[-10000:]
y_train, y_val = y_train[:-10000], y_train[-10000:] if flatten:
X_train = X_train.reshape([X_train.shape[0], -1])
X_val = X_val.reshape([X_val.shape[0], -1])
X_test = X_test.reshape([X_test.shape[0], -1]) return X_train, y_train, X_val, y_val, X_test, y_testX_train, y_train, X_val, y_val, X_test, y_test = load_dataset(flatten=True)## Let's look at some example
plt.figure(figsize=[6,6])
for i in range(4):
plt.subplot(2,2,i+1)
plt.title("Label: %i"%y_train[i])
plt.imshow(X_train[i].reshape([28,28]),cmap='gray');
我们将网络定义为一系列层,每一层都应用在前一层之上。在这种情况下,计算预测和训练变得微不足道。
network = []
network.append(Dense(X_train.shape[1],100))
network.append(ReLU())
network.append(Dense(100,200))
network.append(ReLU())
network.append(Dense(200,10))def forward(network, X):
# Compute activations of all network layers by applying them sequentially.
# Return a list of activations for each layer.
activations = []
input = X # Looping through each layer
for l in network:
activations.append(l.forward(input))
# Updating input to last layer output
input = activations[-1]
assert len(activations) == len(network)
return activationsdef predict(network,X):
# Compute network predictions. Returning indices of largest Logit probability logits = forward(network,X)[-1]
return logits.argmax(axis=-1)def train(network,X,y):
# Train our network on a given batch of X and y.
# We first need to run forward to get all layer activations.
# Then we can run layer.backward going from last to first layer.
# After we have called backward for all layers, all Dense layers have already made one gradient step.
# Get the layer activations
layer_activations = forward(network,X)
layer_inputs = [X]+layer_activations #layer_input[i] is an input for network[i]
logits = layer_activations[-1]
# Compute the loss and the initial gradient
loss = softmax_crossentropy_with_logits(logits,y)
loss_grad = grad_softmax_crossentropy_with_logits(logits,y)
# Propagate gradients through the network
# Reverse propogation as this is backprop
for layer_index in range(len(network))[::-1]:
layer = network[layer_index]
loss_grad = layer.backward(layer_inputs[layer_index],loss_grad) #grad w.r.t. input, also weight updates
return np.mean(loss)
训练循环
我们将数据分成小批,将每个这样的小批输入网络并更新权重。这种训练方法被称为小批量随机梯度下降。
from tqdm import trange
def iterate_minibatches(inputs, targets, batchsize, shuffle=False):
assert len(inputs) == len(targets)
if shuffle:
indices = np.random.permutation(len(inputs))
for start_idx in trange(0, len(inputs) - batchsize + 1, batchsize):
if shuffle:
excerpt = indices[start_idx:start_idx + batchsize]
else:
excerpt = slice(start_idx, start_idx + batchsize)
yield inputs[excerpt], targets[excerpt]from IPython.display import clear_output
train_log = []
val_log = []for epoch in range(25): for x_batch,y_batch in iterate_minibatches(X_train,y_train,batchsize=32,shuffle=True):
train(network,x_batch,y_batch)
train_log.append(np.mean(predict(network,X_train)==y_train))
val_log.append(np.mean(predict(network,X_val)==y_val))
clear_output()
print("Epoch",epoch)
print("Train accuracy:",train_log[-1])
print("Val accuracy:",val_log[-1])
plt.plot(train_log,label='train accuracy')
plt.plot(val_log,label='val accuracy')
plt.legend(loc='best')
plt.grid()
plt.show()Epoch 24
Train accuracy: 1.0
Val accuracy: 0.9809
正如我们所看到的,我们已经成功地训练了一个完全用 numpy 编写的 MLP,具有很高的验证准确性!
用 F#构建神经网络—第 1 部分
原文:https://towardsdatascience.com/building-neural-networks-in-f-part-1-a2832ae972e6?source=collection_archive---------4-----------------------
Whats the next big step from linear regression?
前言
距离我上一篇关于 medium 的文章已经有一段时间了,所以这是另一篇关于神经网络的更深入的文章……用 F#写的。是的,我决定继续用机器学习的功能方式,下一步是从头开始构建这些。虽然你们中的一些人可能会抱怨函数式编程速度较慢,但它确实让你对任何问题有了不同的看法。在第一部分中,我将介绍如何设置核心函数,这些函数可以用来对任意数据集进行训练。
理论
在我们开始之前,理论上的一个旁注:我不会深究数学证明,尽管我会不时地使用几个方程。毕竟,整个问题可以归结为一些巧妙的数学运算。就我个人而言,到目前为止,我已经从亚塞尔·阿布·穆斯塔法教授的优秀的免费课程中学到了大部分理论。我将使用这些幻灯片作为基础来实现大部分功能。我还假设你有一些函数式编程的基本知识,尽管从 F# 这里开始是个好主意。在整篇文章中,我会尝试将重要概念的参考链接起来。
设置
这里的主要目的是演示一个工作的神经网络,它可以根据需要构建成多深多宽。我们将使用上次的 MSE 来计算我们的总成本,因为这简化了计算。使神经网络不同于任何任意分层的简单感知器的是激活函数,它帮助神经网络学习数据集中的非线性。有许多不同的激活函数,每一个都有其优点,但在我们的情况下,双曲正切就足够了。最后,我们将在大部分数据结构和计算中使用 MathNet 库。这对于 F#来说基本上是微不足道的(但是不可否认的是要简单得多)。
助手功能
函数式编程的关键思想是将你的主要功能分解成更小、更简单的任务,这些任务更容易实现、调试和理解。记住这一点,我们将首先创建几个将在前向和后向传播中使用的辅助函数。
让我们从为我们的函数定义一些定制的类型开始。拥有一个好的类型系统是函数式编程的关键要素之一,除了其他好处之外,它还能让你的代码看起来更整洁,更不容易出错。重点关注的主要类型是“Layer”和“NodesVect”。每个层对象可以被认为是权重矩阵的标记元组和应用于该层输出的激活函数。 wMatx 将保存从前一层到下一层的每个连接的权重(i_max = m(行),j_max = n(列))。每个节点 Vect 将由两个向量组成。 sVect 将在任意层的输出(和输入向量)通过激活函数之前保存它。在 sVect 通过激活函数后,xVect 仅保存其值。我们需要这两者来进行反向传播,所以我们不能只存储 xVect。
下图以数学形式总结了这些类型。关于偏差有一点需要注意:我们将把权重存储在权重矩阵中,但是因为它们只是前向连接的(即它们的节点值总是= 1),我们将仅在需要时将这些“动态”附加到 sVect 或 xVect 。
Image Credit: Learning From Data — Lecture 10: Neural Networks
激活功能在这里被定义为区别联合。这些与枚举非常相似,但是更加灵活,它们允许我们通过使用关键字而不是实际的函数名将激活函数列表传递给网络生成器。 getActFn 接受特定激活函数的“关键字”和一个浮点数作为输入,并返回转换后的值。
lastLayerDeriv 是计算用于反向传播的最后一层的误差增量的函数。这里使用点乘,因为我们将得到任意维输出的导数,所以我们的输出现在是向量。
任意网络生成
为了能够处理任意数量的层和每层中任意数量的节点,我们将创建一个网络生成器,它将简单地接受网络中的输入、输出和隐藏节点的数量(不包括偏差)以及激活函数类型作为两个列表,并输出一个结果 monad 。这将返回错误字符串或网络类型对象。如果节点和激活函数列表不符合要求的规范,我们将只使用结果单子来打印错误(这就是为什么你会看到这么多匹配!).这个函数几乎是不言自明的。
The network generator function
正向传播
对于神经网络,前向传递通常在概念上易于理解。简而言之,它包括将下一层中的节点值设置为前一层中的节点和偏差的加权和,并通过非线性激活函数传递该结果。
Animation showcasing List.fold (source)
在我们的 fwdProp 实现中,我们将使用 List.fold ,这是递归遍历列表的有效实现。与上图不同的是,我们的累加器不是一个单独的元素,而是一个由XV vectansvect和 Layer 类型按相反顺序排列而成的列表。我们以相反的顺序返回它们,因为 F#列表是作为单链表实现的,所以在顶部附加 O(1)(在底部附加 O(n))。这也对我们有利,因为根据定义,反向传播将以相反的顺序工作!
List.fold 允许我们设置一个初始状态,这些将是输入向量对(这是特殊情况,当 sVect == xVect 时)和一个空列表以逆序存储权重。权重矩阵( nm* )乘以 x 向量( m1* )的转置将给出下一层的 s 向量( n1* )(如上面的数学形式所示)。特别注意偏差,在当前层的 x 向量上附加“1.0”,但是按照网络的设计方式,下一层仍然需要“1.0”(因为没有任何东西馈入偏差节点)。最后,对 s 向量中的每个元素执行简单的激活函数映射,以生成下一层的 x 向量。
反向传播
Source
该是认真对待的时候了。反向传播推导在许多在线资料中都有很好的解释。我们将使用随机梯度下降法,因此一些方程可能看起来略有不同。完整的方程式列表可以在前面提到的课堂笔记中找到。在阅读代码之前,记住这一点是个好主意。
Note: the error-delta here is a scalar corresponding to each node
我们首先将误差增量(描述归因于每个未激活输出的最终误差的贡献)计算为一个向量。我们使用前面描述的 helper 函数对最后一层进行计算。一旦我们得到这个值,我们现在需要计算所有层的误差增量矢量。严格地说,如果有什么东西进入一个层,这个层就可以被归类为这样一个层。因此,输入没有被分类为图层,计算它们的误差增量没有意义。使用当前层的权重矩阵和前一层(或输入)的 s 向量来计算前一层的误差增量。这可以使用自定义尾递归函数轻松完成。
The chain-rule formula for the final multiplication (given here on a per-weight basis)
一旦我们有了逆序的误差增量向量列表,我们需要将激活的输出(从倒数第二层开始)乘以误差增量,以产生 dE/dW 矩阵,该矩阵描述了每个权重的误差贡献,并将用于更新权重,从而允许机器从其错误中“学习”。简单地通过从原始权重矩阵中减去 dE/dW 的因子(学习率)来更新权重。为了在每层的基础上执行所有这些操作,我们使用了 List.map3 。这是一个内置的 F#函数,它允许我们同时迭代 3 个列表(权重矩阵,x 向量&误差增量向量)。这种映射的结果将按照正确的原始顺序产生更新的权重,然后可以由反向传播函数直接返回。
这里需要注意一些事情。x 向量、s 向量和 w 矩阵都以相反的顺序传递给递归函数。“Head”只返回列表中的第一个元素,“Tail”返回除第一个元素之外的所有元素。我们移除权重矩阵中的第一行,因为它对应于偏置节点,并且该节点对其后面的任何权重没有贡献,即没有权重馈入偏置节点。对xandsltrev 进行迭代。Tail 相当于迭代每个前一层的输出。
层更新器功能需要额外的 1.0 附加到 x 向量,因为这是前一层的激活输出,并且这里偏置连接到当前层中的权重分量,即权重矩阵具有 m 行,第 0 行对应于偏置权重。
结论
为自己走了这么远而感到欣慰吧!您现在可以使用这些函数从一个简单的顶级描述创建任意网络,比如:initNetwork [1 ; 2 ; 1] [ID TANH]
。一旦您从输出中提取了网络对象,您只需要通过管道(fwdProp |> backProp
)传递它,您就有了新的权重集。
在下一部分中,我们将利用这些和一些更多的“助手”函数,以便从一个非平凡函数生成训练数据,并使网络实际做一些实际工作。所以请继续关注,如果你喜欢这篇文章,请留下👏!
正如我所承诺的,下面是第 2 部分的链接:
[## 用 F#构建神经网络-第 2 部分
你的神经网络训练够快吗?
towardsdatascience.com](/building-neural-networks-in-f-part-2-training-evaluation-5e3a68889da6)
用 F#构建神经网络—第二部分
原文:https://towardsdatascience.com/building-neural-networks-in-f-part-2-training-evaluation-5e3a68889da6?source=collection_archive---------12-----------------------
Well, you’ll need F# for this so better read on!
快速回顾一下
欢迎来到本系列的第二部分。在第一部分中,我经历了执行单一(随机)梯度更新所需的步骤。在这一部分中,我们扩展了这一功能,使网络能够从数据中学习任意关系。在我们开始之前,请确保您已经阅读并实现了我上一篇文章中的代码:
[## 用 F#构建神经网络—第 1 部分
函数式编码神经网络优雅吗?
towardsdatascience.com](/building-neural-networks-in-f-part-1-a2832ae972e6)
通用逼近定理
第一个在 1989 年被证明,神经网络可以被归类为通用函数逼近器。但是,这样的近似器是什么?
给定任意一个连续的 N 维函数 f(x) ,一个只有一个隐层和有限个神经元的神经网络有能力在固定的范围 x 和有限的误差 ε内逼近这样一个函数。
我们将利用这个定理,在多个非平凡函数上评估一个简单的架构,以证明我们的网络具有从数据中学习的能力。
一些助手功能
让我们定义这些额外的辅助函数,它们将帮助我们进行培训和评估:
genDataSet1D
—仅使用开始、结束和步进信息,该函数生成向量元组的数组,每个元组对应于一个(x, y)
对。注意,这可以是任何必要的维度,但是为了简单起见,本教程中的输入和输出都是一维的。yRealFn
—这是我们定义目标功能的地方。来自该函数的数据点将被采样并绘制在最终图上,以显示我们试图建模的实际底层函数。yRealFnAndNoise
—该功能只是在yRealFn
的输出中增加一个概率项,模拟数据中存在的噪声。然而,如果该误差没有适当调整,与确定性项(yRealFn)相比,它将过大,导致网络试图学习噪声而不是实际函数。meanFeatureSqErr
&evalAngEpochErr
—这些功能将在本教程的培训部分解释。
初始化网络
定义架构
Sometimes, a single hidden layer is all we need…
为了测试我们的网络,一个只有一个隐藏层的简单神经网络就足够了。我研究了学习任何合理的平滑函数所需的隐藏节点的数量,发现 8 个节点就足够了。
根据经验,选择太少的隐藏节点会导致欠拟合,反之太多会导致过拟合。
当谈到选择激活功能时,手边有许多流行的: tanh , sigmoid , ReLU 等。我决定用 tanh ,因为它非常适合学习平滑函数中存在的非线性,比如我们测试中会用到的那些。
A plot of tanh(x) (red) and its derivative (green) [source].
选择超参数
如果你一直在跟踪机器学习,甚至从一开始你就学会欣赏超参数搜索或多或少的试错。当然,你也可以查看几个时期的成本函数图,做出你认为的最佳价值的有根据的猜测。
训练次数为~ 3000 时,学习率为 0.03 通常会给出足够好的结果。由于 F#中惊人的快速训练时间,我只能处理这么多的纪元!
目标函数
在我们开始训练之前,还有最后一步:选择合理复杂的函数,这些函数可以用来生成精确的数据集,同时在视觉上具有可比性。
您会注意到,对于位于相同范围内的所有输入,输出都受到闭合区间[0,1]的限制。这是一个深思熟虑的决定,以避免使用均值归一化,这有助于通过将所有特征保持在相似的范围内来防止过度加权。
A definition of our three test functions along with their plots
我们将使用步长为 0.01 的 x ∈ [0,1]来训练我们的网络。因此,在此范围内将产生 101 个等距样本,我们将保留其中的约 6%进行验证(统一选择)。
培训我们的网络
If only he was taught about under-fitting…
概述
让我们首先从顶层收集一下培训需要哪些功能:
- 对于每个时期,我们需要执行梯度下降,在我们的例子中,将随机地进行*(每个样本一次)。然后,我们将使用更新后的网络在下一个时期进行进一步的训练。*
- 在此过程中,通过在每个时期结束时评估我们的网络并获得误差度量(例如,平方误差)来跟踪我们的训练误差将是有帮助的。
使用地图折叠
保持接近函数范式,而不是使用传统的 for 循环,我们将使用
List.mapFold for training
开发一个巧妙的技巧。
那么地图折叠是如何工作的呢?
简单来说就是List.fold
和List.map
的高效结合。它允许在给定当前列表元素和先前状态的情况下计算新的状态,同时使用我们选择的函数转换当前列表元素。该函数的最终输出是一个由转换列表和最终状态组成的元组。
履行
在trainEpoch
函数中,训练数组首先被随机打乱(就地)。这个新洗牌后的数组被送入perfGradDesc
。该函数通过使用Array.fold
传播网络更新,在整个训练数据集上一次执行一个样本的梯度下降(单遍)。
一旦我们训练了一遍网络,并从trainEpoch
获得了最终网络,我们需要使用我们选择的成本函数来评估该时期的训练误差。每个样本的误差需要与lastLayerDeriv
功能一致。因此,平方误差是由meanFeatureSqErr
函数实现的误差度量的最合适选择。
注意:虽然我们的网络可以支持任何维度的输出,但当涉及到成本函数时,每个样本只有一个标量度量是有用的。因此,每个样本的误差将是每个输出特征的平方误差的平均值。这不会影响一维输出的误差,如果所有输出维度的比例大致相同,这是一个合理的选择。**
在对整个训练集的每个样本的误差进行平均后,我们获得了均方误差。该值由evalAvgEpochErr
功能计算得出。
最后,在每个时期结束时,(xAndyShuffArr,newNet)
是传播到下一个时期的新的状态*,而err
是替换原始列表中时期号的映射对象。*
The code for training our network
结果
The results for y = 0.4x² + 0.2 + 0.3xsin8x, spanning multiple epochs.*
所以这里有一些视觉证明,网络实际上是在训练!为了绘制我们的数据,我们将使用我过去在 F#中用来绘制的PLplot
库。绘制这些图形还需要一些额外的代码,但是可以在 Github 资源库中找到,这个资源库在文章的结尾有链接。
神话;传奇
- 粉色 线代表底层真函数无噪声。这仅用于绘图,但从不用于任何计算。
- 青色 点是整个数据集,包括训练和测试数据点。所有误差都是参照这些点计算的
- 绿色圆圈代表在训练 数据上评估的最终假设。随着训练时期数量的增加,您可以观察到这些曲线越来越接近真实的函数曲线**
- 最后,粉色 十字代表基于测试数据评估的最终假设。如果你仔细观察,你会注意到他们很好地跟踪了训练数据点,并且这被训练与测试的 MSE 分数所证实
评估目标函数
From left to right: f(x) = 0.4x² + 0.2 + 0.3xsin8x, g(x) = 0.6e^-(0.3sin12x/(0.3+x)), h(x) = 0.4 - 0.1log(x+0.1) + 0.5xcos12x
这是我们三个测试函数的结果,你可以点击每一个来查看更多细节。只需快速浏览一下,很明显,网络通常在更平滑的函数上表现良好。随着每个函数的驻点附近的梯度增加,神经网络的训练也变得更加困难(观察损失曲线)。这可以与我们使用 tanh(x)作为激活函数的事实联系起来。
尽管如此,我们现在有了直观的证据,证明了普适近似定理是成立的!
任务已完成💪🏼
结论
现在,我们已经定义了基本架构,并且能够对任意数据进行训练,我们可以使用网络来训练和测试流行的数据集。这是留给你的任务…为什么不试试著名的波士顿房价数据集?
这段代码在机器学习的世界里还有很长的路要走。它们是许多扩展,甚至可以对最简单的神经网络进行扩展以改善收敛性:批量标准化、小批量梯度下降、自定义权重初始化等等。
嗯,不要担心,只是在 F#上训练 3000 个历元需要大约 3 秒的事实使它成为快速神经网络修补和评估的良好潜在候选对象。使用非常相似的设计原则和相似的参数选择,这个脚本的 python 版本需要大约 168 秒(在 Google Collab 上)!
正如承诺的,所有的源代码都可以在Github上获得。
我希望你能从过去的两个教程中获得一些新的东西,它们是一个漫长的过程,但我在这个过程中学到了很多。一如既往,请随时分享您的建议,反馈和对我的下一个教程的任何建议。如果你喜欢这篇文章,请留下👏🏼或者两个…下次见!👋🏼
用 Python 构建机器学习项目包
原文:https://towardsdatascience.com/building-package-for-machine-learning-project-in-python-3fc16f541693?source=collection_archive---------8-----------------------
我见过的大多数机器学习项目都处于永久的实验状态,从技术角度来看没有明确的成功计划。创建一个算法,实际上解决一个可行的问题,做好它本身是困难的。然而,以可靠的方式管理高度实验性的代码库并使您的项目准备好部署是另一个难题。尤其是如果你没有开发人员的背景。
We want to make rocket science in our projects. But we need to make sure our rocket will not explode 5 seconds after launch. “white space shuttle indoors” by SpaceX on Unsplash
在我的下一个系列中,我将涉及一些我认为有用的主题,以便更容易地从实验过渡到生产。其中大部分还有助于保持代码的可靠性和结果的可重现性。
以下是清单:
- 构建 python 包
- 为其创建命令行界面
- 管理依赖关系(python 和非 python)
- 定义依赖图
- 创建自动化(单元)测试
- 将其作为 rest api
- 归档
今天,我将介绍如何创建 python 包和命令行界面。同样在开头,我将展示涉及第三和第四个要点的另外两个关键原则。
实验代码
我们从非常简单肮脏的“原型”开始。这甚至不是一个应用程序,只是一堆脚本。
Our “app” at time zero
我们有空的 readme、github 生成的许可文件和 gitignore、一些 bash 脚本和三个 python 文件。因为数据是数据科学家最宝贵的资源。
数据文件通常太大,无法存储在代码库中,需要托管在其他地方。在这个应用中,我们使用公共的 aclImdb_v1 数据集进行情感分析。
第一条规则永远要确保你能再次获得数据——并且你的团队知道如何去做。
我们可怜的原型在这方面已经很不错了。让我们来看看download_data.sh
set -emkdir -p data/rawwget [http://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz](http://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz) -O data/raw/imdb.tar.gztar -xzf data/raw/imdb.tar.gz --directory data/rawrm data/raw/imdb.tar.gz
该脚本创建目录data/raw
,下载数据集,解包并删除不再需要的归档。理想情况下,我更愿意将数据保存在我的 S3 账户中(以防链接过期),但我们可以假设这已经足够好了。然而,实际上你的数据可能是一个数据库转储,一堆需要合并的 excel 文件等等。您应该为所有数据采集步骤创建脚本(例如:可以编写数据库转储脚本),以确保能够以自动化方式运行整个过程。
有些情况下是不可能的(因为各种原因:技术、法律、合规等)。在这种情况下,所需的步骤必须明确记录。新的团队成员应该能够获得数据,而不需要任何人的帮助。但是记住,最好的文档是可执行的文档;)
现在,让我们来看看 requirements.txt
numpy
pandas
scikit-learn
所需软件包的列表非常简单,但目前还不错。跟踪所有项目的依赖关系是非常重要的。稍后我们将会看到仅仅列出所需的包是不够的,但是如果你甚至没有使用这个简单的列表,请开始吧。
规则#2 列出你所有的依赖项,并创建单独的环境
为每个项目创建单独的 conda/虚拟环境,并列出所有依赖关系。如果您的项目需要一些额外的非 python 依赖项(如数据库驱动程序、系统范围的包),请明确列出它们,或者如果可能的话,为它们创建安装脚本。请记住,手动步骤的数量必须尽可能少。这也适用于“一次性活动”。我有时很惊讶那些一次性被执行的频率。
现在我们可以继续学习 python 代码了。
文件dataset.py
包含简单的类数据集,用于读取数据集(惊喜)。代码很好,除了硬编码的路径(我们稍后会解决)
下一个文件,train_model.py
是脚本文件中包含的一串语句。该脚本做了应该做的事情,但我们需要对它进行修改。初始版本的内容如下:
步骤非常简单,模型被训练和存储到文件以及使用矢量器。随后,根据测试数据对其进行评估,并打印出一份简单的报告。该脚本可以工作,但是正如您可能认为的那样,它与良好的实践没有任何共同之处。不幸的是,很多“只是实验”的代码并没有退出“代码质量”这个阶段。我们将打破这一障碍;)
所使用的模型非常简单,其准确性很差——但这不是问题。我让事情尽可能简单,因为这不是关于创建一个好的分类器的系列;)在现实中,这样的训练脚本更复杂,但在更简单的例子上更容易解释事情。
为了示例的完整性,还有一个脚本— ask.py
。它的作用是提供一个对新数据进行预测的接口。
我们走过了“数据科学实验”的初始状态。现在,我们将把它转变成生产就绪的解决方案。
创建 Python 包
第一步是创建一个包。有许多基本上没有成本的好处。其中一些:
- 清除项目结构
- 能够为部署创建源代码/二进制分发
- 版本控制
- 自动相关性检查
- 轻松创建扩展
- 分离(例如,您可能不想包含预测环境的训练代码)
- 还有更多:)
规则 3 打包你的代码
创建一个包很容易。首先我们需要选择名字;)姑且称之为 mlp(机器学习-生产)。创建这样的目录,并将源文件移动到其中:
mkdir mlp
mv dataset.py train_model.py ask.py mlp/
接下来,我们需要做一些轻微的调整。包代码不应该是直接可执行的。因此,它必须包含在类或函数中。顺便说一下,我们将把硬编码的路径提取到参数中。对于数据集,我们只需要修改类构造函数:
另外两个文件共享相同的模型。这意味着,这部分应该被提取。大概是这样的:
数据集和模型是我们能够提取为可重用组件的两个部分。剩下的两个(ask 和培训脚本)更像是启动器。现在,让我们删除它们。我们将创造一个更好的版本;)
包装还有两件事要做。首先是在 mlp 目录中创建__init__.py
,内容如下:
from mlp.dataset import Dataset
from mlp.model import DumbModel
__init__.py
是在加载模块的瞬间执行的(你可以把它想成“包构造器”)。它不应该做太多的事情,但是导入被认为是包的公共部分的部分是一个非常常见的场景。这不是必需的,但允许我们写:
from mlp import Dataset, DumbModel
代替
from mlp.dataset import Dataset
from mlp.model import DumbModel
最后一件事是创建setup.py in
项目根目录。这个文件包含了关于这个包的所有元信息。它可能非常大,但是对于我们的目的(此时)几行就足够了:
我们只需要定义名称(这是您在 pip install XXXX 中键入的内容)、包列表(这是您在 import 语句中使用的内容)和版本—参见 PEP 440 。
该项目目前看起来是这样的:
最后要做的事情是安装我们的软件包。要执行此操作,请键入以下内容(在项目根目录中):
pip install -e .
没有魔法:我们提供了一个点来代替包名,意思是“安装当前目录”。-e
开关使其安装在开发模式下。这基本上意味着软件包源代码中的每一个改变都会立即反映在已安装的版本中——在做出改变后就不需要重新安装了。您可以在执行 pip 列表后看到您的包:
$ pip list
Package Version Location
--------------- ---------- -----------------------------
cloudpickle 0.6.1
cycler 0.10.0
...
mlp 0.0.1.dev1 $HOME/blog/mlp
....
为了确保一切正常,您可以执行 python repl 并尝试实例化数据集和模型。
$ python
>>> from mlp import Dataset, DumbModel
>>> d = Dataset()
>>> m = DumbModel()
命令行界面
我们到达了中点。今天的第二个主题是创建一个界面。最初,有两个肮脏的脚本。相反,我将向您展示如何创建一个漂亮的命令行界面。
为你的项目定义好界面。一堆脚本是不够的。
将有两个命令。一个用于训练模型,第二个用于请求预测。让我们从在项目根目录下创建名为mlp.py
的文件开始。这将是我们的“发射器”。我们的命令非常简单,只需为它们创建两个简单的函数:
当然,当这样的函数很长时,将它包含在包中总是一个好主意,只需从启动器中调用它。
好吧,但是我们怎么调用它们呢?类似这样的东西可能有用:
python mlp.py train data/raw/aclImdb/ model.pickle --vocab-size=5000
或者用于预测:
python mlp.py ask model.pickle "This movie is awesome"
如何创建?有几种可能性,例如:argparse 或 click。但是我准备用 docopt 。安装它,不要忘记将它包含在 requirements.txt 中
使用 docopt,我们通过编写帮助信息来定义界面。可能看起来很疯狂;)
在mlp.py
的开头添加以下内容:
通过阅读这个 docstring,您已经知道了哪些命令是可用的,需要哪些参数等等。Docopt 将对此进行解析,并为我们创建参数解析器。我鼓励你看一下 docopt 的文档以获得更多信息。
执行我们的命令非常简单。在mlp.py
的末尾增加以下内容:
我们只是检查选择了哪个命令,并传递它的参数。就这么简单。
可安装命令
今天我们只做一件小事。目前我们的发射器在包装之外。让我们更紧密地整合它。将我们的脚本移动到 mlp 目录,并将其重命名为 cli.py(命令行界面)。将 docopt 帮助消息与以下内容稍微对齐:
我们将由mlp-cli
指挥执行我们的项目。我选择不使用普通 mlp,因为它会与 mlp 目录冲突。
下一次更新setup.py
为:
我们在包中添加了一个入口点。它是一个控制台脚本,可执行名为mlp-cli
。该可执行文件将从包mlp.cmd
中启动 main 函数
当我们编辑安装脚本时,需要重新安装软件包:
pip install -e .
记住:当你改变包代码时,没有必要重新安装它(只要你使用了-e 开关)。如果您更改 setup.py 内容,您必须重新安装软件包。
现在我们可以在终端中键入mlp-cli -h
来验证它是否工作;)
是的,我们有一个单一的入口来与我们的项目沟通;)再也没有乱七八糟的剧本了!
摘要
那是相当多的。我们学习了如何创建一个基本的 python 包,并为它创建一个命令行界面。此外,我们设法使它与 it 完全集成。不要忘记关于再现性的两条基本规则。现在项目结构应该是这样的:
这时你可以从项目库中下载代码;https://github.com/artofai/mlp。寻找标签part1-finished
。
在下一篇文章中,我将解决引言中列出的另一个问题。
锻炼
如果你愿意,你可以做一个简单的练习:在我们的应用程序中添加一个期权限制。数据集已经准备好处理这样的参数;)
敬请期待,后会有期:)
用 Python 构建预测 API(第 1 部分):系列介绍&基本示例
原文:https://towardsdatascience.com/building-prediction-apis-in-python-part-1-series-introduction-basic-example-fe89e12ffbd3?source=collection_archive---------5-----------------------
好吧,你已经训练了一个模型,但是现在呢?如果没有人会使用,所有的工作都是没有意义的。在某些应用程序中,您可以简单地创建一个批处理作业来收集需要评分的记录、准备这些记录并运行模型。然而,其他应用程序需要或者至少高度受益于用于实时评分模型的过程。理想情况下,我们甚至希望通过 REST API 与他人共享使用模型的能力。虽然部署一个简单的模型相当容易,但是在这个起点上扩展和迭代是有挑战的。
在本系列中,我们将采用增量方法来构建预测 API。在这篇文章中,我们将构建尽可能简单的 API,允许我们对模型进行评分并返回预测。随后的每篇文章都将关注我们如何在已经实现的基础上进行改进。这个系列不会有固定的结局。随着新主题的出现,我会尝试扩展已经完成的内容——这取决于我有多少时间和读者的兴趣水平。
目标受众
在整个系列中,我们将主要关注构建模型评分平台的软件工程方面,并讨论工程和数据科学之间的灰色地带。我将在很大程度上假设读者有一个他们想要部署的模型,或者他们有能力生成这样一个模型。因此,我们通常不会讨论构建预测模型的过程。有很多很棒的教程和书籍涉及这个主题。
这个系列有两个主要的受众。第一类是全栈数据科学家,他们希望通过 API 部署他们的模型,但不确定如何有效地完成。第二类是没有在数据科学领域工作过的软件工程师或技术产品经理,他们可能会从理解模型部署与一般软件部署的不同中受益。
工具
我们将使用 Python 3 作为主要语言。特别是,我将主要使用 Python 3.6。烧瓶将用于初始原料药。所有模型都将使用 Scikit-Learn 构建。如果您不确定如何用这些包来设置开发环境,我推荐从 Anaconda 开始,因为它提供了您开始设置所需的一切。
虽然这个工具集的范围相当窄,但是我希望这些主题可以广泛地应用于其他编程语言和 API 框架。
基本示例
既然我们已经为本系列奠定了基础,那么让我们构建一个基本模型。我们将从建立在 iris 数据集上的随机森林分类器开始。
同样,我将跳过模型构建过程的讨论,所以我们不打算深入研究这个例子。要注意的主要事情是,一旦我们建立了模型,我们就使用joblib
将它保存(pickle
)到一个文件中。虽然这种方法可行,但是这种方法存在一些问题和限制。Scikit 有一篇关于这个的很棒的文章,但是主要问题是:
- 安全性:当您
load
一个腌泡对象时,您实际上是在执行存储在文件中的代码。仅加载您信任的持久化对象。 - 可移植性:在构建环境和生产评分环境之间 scikit-learn 版本的任何变化(或潜在的依赖性)都会导致最低限度的警告和潜在的意外行为,例如失败或预测错误。
我们暂时将这些问题放在一边,但这些可能是我们在后续文章中探讨的主题。
构建我们的第一个 API
现在,我们将使用 Flask 构建尽可能简单的 API。我们将包含一个端点/predict
,它将允许我们通过查询参数传递特征值。
我们在全球加载我们的模型为MODEL
。我们还有一个标签列表(MODEL_LABELS
),对应于MODEL.predict()
将输出的整数值。我们使用@app.route('/predict')
装饰器创建了 API 端点,并定义了predict()
函数来处理发送到该端点的请求。对这个端点的调用应该包含 4 个参数,它们对应于我们的特性:sepal_length
、sepal_width
、petal_length
和petal_width
。例如,一个呼叫看起来像这样:
[http://127.0.0.1:5000/predict?sepal_length=5&sepal_width=3.1&petal_length=2.5&petal_width=1.2](http://localhost:5000/score?sepal_length=5&sepal_width=3.1&petal_length=2.5&petal_width=1.2.)
Flask 处理 URL 查询字符串的解析,并将参数添加到request.args
中,它有一个类似于 python dict
的 API。如果键存在,使用get
将检索一个值,否则将返回一个默认值。因为我们没有指定默认值,所以将返回None
。此外,默认情况下,args
中的值将是字符串,但在评分过程中,模型会自动将这些转换为浮点数。
特征值然后被打包到一个嵌套列表(列表的列表)中。这是必要的,因为我们的模型需要一个记录列表,其中每个记录都是特性集的长度。我们一次只对一个记录进行评分,这就是为什么外部列表只包含一个内部列表(记录)的原因。
我们使用MODEL.predict()
来获得预测的类,它将是 0、1 或 2。最后,我们可以通过使用类作为进入MODEL_LABELS
的索引来获得标签。
运行我们的预测服务
现在,我们可以从命令行启动我们的 Flask 服务器。
在我们的浏览器中,我们可以使用上面的例子发出一个测试请求。
Test URL: http://127.0.0.1:5000/predict?sepal_length=5&sepal_width=3.1&petal_length=2.5&petal_width=1.2
我们也可以使用requests
来做同样的事情。
前方是什么
在 20-30 行代码中,我们构建了一个简单的模型,并创建了一个接受请求并返回预测的 API。然而,有几个方面我们可以并且应该比我们在这里所做的做得更好。对这些主题的探索将在后面的文章中处理,但这里有一个快速预览:
- 错误处理:目前,我们在给模型评分时不做任何错误处理。当我们收到坏数据或数据丢失时会发生什么(没有提供
sepal_length
)?如果失败了,打电话的人会收到什么样的反馈? - 自动化测试:我们的代码中有错误吗?除了手动运行几个请求,是否有可能自动化这个过程?
- 可扩展性:这个 API 只处理一个单一的全局模型。我们应该为我们的下一个模型创建另一个一次性的 API 吗?如果我们创建一个现有模型的新版本会怎么样?每个版本应该有一个独立的 API 吗?
- 数据收集:没有从这个 API 收集数据。我们如何跟踪我们的模型执行得有多好?我们知道什么时候会出错吗?处理一个请求需要多长时间?如果我们开始收集数据,我们应该把它存储在哪里?
- 部署:这是在本地运行的,但是我们需要把它放在服务器上。我们如何扩展?我们应该没有服务器吗?我们如何处理负载测试?
- 特性工程:这个 API 期望请求者已经准备好了任何特性,但是我们经常需要在数据准备好被模型使用之前对它们进行一些转换。我们应该如何以及在哪里做这件事?
在第 2 部分中,我们将看看 API 的基本错误处理,并涵盖定义何时应该使用模型的重要性。
[## 用 Python 构建预测 API(第 2 部分):基本错误处理
在最初的系列文章中,我们创建了一个简单的 API 来对建立在 iris 上的 Scikit-Learn 随机森林分类器进行评分…
medium.com](https://medium.com/@chris.moradi/building-prediction-apis-in-python-part-2-basic-error-handling-3ab87b7a93)
特别感谢 Geoff Svacha 为本系列提供反馈。
脚注
- 使用
datasets.load_iris().target_names
可以得到这些标签。 - 类似于[1],使用
datasets.load_iris().feature_names
并重新格式化这些。 - 我们将在本系列的第 2 部分对此进行更深入的探讨。
用 Python 构建预测 API(第 2 部分):基本错误处理
原文:https://towardsdatascience.com/building-prediction-apis-in-python-part-2-basic-error-handling-3ab87b7a93?source=collection_archive---------11-----------------------
在初始系列文章中,我们创建了一个简单的 API 来对建立在 iris 数据集上的 Scikit-Learn 随机森林分类器进行评分。在本帖中,我们将探讨如何处理评分过程中出现的错误,以及定义何时应该使用模型这一更广泛的主题。
[## 用 Python 构建预测 API(第 1 部分):系列介绍&基本示例
好吧,你已经训练了一个模型,但是现在呢?如果没有人会使用,所有的工作都是没有意义的。在某些应用中…
medium.com](https://medium.com/@chris.moradi/building-prediction-apis-in-python-part-1-series-introduction-basic-example-fe89e12ffbd3)
一个简短的激励话题
我们可以从测试一个简单的 Python 函数开始。没有模型,没有 API,只是一个将两个数相加的函数。
当我们考虑如何测试这个函数时,我们应该考虑所有可能出错的地方,并假设它会在某个时候出错。这个例子非常简单,我们只需要担心a
和b
的错误输入参数。以下是一些例子:
通过这一小组示例,我们可以看到基于“可接受的?”的三个不同类别专栏:商品、商品和不确定因素。“商品”是我们预期的输入,即我们可以加在一起的int
或float
值。“坏的”是引发异常的那些;Python 不知道如何添加的输入。Python 已经为我们抛出了一个异常,但是我们看到基于输入参数抛出的异常类型(TypeError
或ValueError
)有些不一致。我们可以捕捉这些异常并定制一个一致的异常,或者我们可以返回None
。
最后一类,即“不确定性”,可能是最有趣的。这些产生了有效的结果,但是它们没有反映我们最初打算支持的内容。在这里,我们可以选择如何解决我们的意图和实现之间的不一致。在 Python 中,我们通常不想强制类型,所以我们可以让代码保持原样。我们应该在 docstring 中或通过类型提示来表示预期的类型,以便用户理解我们正式支持什么,以防将来的变化破坏当前的功能。但是,可能有些情况下,我们希望拒绝返回值,除非满足某些条件。在这些情况下,我们可以显式地检查输入的类型,甚至将它们限制在某个可接受的值范围内(例如,只添加小整数)。
模型特征的错误
既然我们已经看了一个简单的例子,让我们回到第一部分的原始预测 API:
从我们上一节介绍的内容开始,我们将考虑通过request.args
传递的错误输入参数。对于其中的每一个,我们都期待一个可以转换成float
的值。然而,使用上面的方法,我们将获得每个的字符串值。Flask 通过向request.args.get()
方法提供type
参数,使得转换查询参数变得容易:
request.args.get('sepal_length', default=None, type=float)
这将尝试将sepal_length
的值转换为float
,如果转换失败,将返回由default
关键字参数指定的默认值。注意: default
关键字参数的缺省值是 None
,所以我们可以省去这个参数。
除了原始版本(没有指定type
),我们还处理请求中缺少查询参数的情况。在这两个版本中,相应的变量将被赋予默认值None
。
我们可以以类似的方式更改检索sepal_width
、pedal_length
和pedal_width
的request.args.get()
调用。然而,当我们重启服务器并测试一个带有错误值或丢失参数的请求时,我们会遇到另一个问题:我们的模型不能处理丢失的值。提出这样的请求会导致ValueError: Input contains NaN, infinity or a value too large for dtype('float32')
。
我们应该得分多少?
使用我们的adder
函数,来自“不确定”类别的输入值会产生一个结果(没有引发异常),但也许不应该。在我们的模型评分中,我们发现了一个以相反方式处理的类似组。我们当前的实现是拒绝缺少值的请求(引发一个ValueError
),但是也许我们应该找到一种方法返回一个预测。
在任何模型部署中,确定哪些请求应该被评分,哪些应该导致错误或警告是一个关键的考虑因素。这通常是一个微妙的决策,涉及模型开发人员、业务合作伙伴和产品所有者,并寻求平衡预测的好处和错误的代价。作为一个利益相关者,我有意忽略了软件开发的角色。这是因为如果有足够的时间和资源,他们通常能够实现预期的意图。从长远来看,模型的使用应该由数据科学、业务和产品需求驱动,而不是由评分平台实现的便利性驱动。虽然我已经分别列出了这些角色,但是同一个人可能会满足他们中的许多人或所有人——这使得我们在做出这些决定时采取哪种观点更加重要。
这里有几个场景来帮助说明为什么我们需要慎重决定对哪些请求进行评分:
- 在线广告:假设我们已经建立了一个模型来预测在一组可能的广告中,我们应该向我们网站的特定访问者显示哪个广告。通过用户跟踪,我们知道大多数访问者的参考页面或网站,但对于一些人来说,这是缺失的。在这种情况下,做出次优甚至差的预测可能是好的,因为错误的成本很低。一个担忧可能是次优预测会如何影响我们对广告进行的任何 A/B 测试——特别是如果这些低质量的预测偏向某个特定的广告——但访问者不太可能因为看到了“错误”的广告而逃离我们的网站。
- 扩大贷款/信用:高成本决策的一个例子是信用贷款;我们的模型将预测某人的信用度或风险。贷款机构通常会将模型的许多关键特征建立在信用局数据的基础上。例如,如果客户正在申请贷款,我们想知道他们是否在另一笔贷款上违约,或者在最近几年申请破产。信用局的数据对贷款决策至关重要,如果没有这些数据,我们不会对客户的申请进行评分。
- 欺诈检测:创建欺诈防御通常是阻止可疑活动和激怒好客户之间的平衡行为。虽然与合法使用相比,欺诈在事件发生率上通常很少,但它会给公司带来巨大的财务和声誉成本。本能反应可能是积极使用任何可以减少损失的欺诈模式。然而,欺诈也是对抗性的,欺诈者会调整他们的方法来规避现有的防御。由于这些原因,对欺诈行为进行强大而一致的防御通常非常具有挑战性。此外,标记为欺诈的事件可能会导致交易被拒绝、帐户被限制或申请被拒绝。这些处理方法在正确应用时非常有效,但假阳性会导致糟糕的客户体验,并可能导致有价值客户的参与度降低或流失。由于这些因素,基于预测模型的决策可能仅适用于可疑事件总数中的一小部分。
缺失和不良输入的不同处理方式
现在,让我们回到我们的 API 示例来展示我们如何实现这些模型使用策略。
拒绝请求
我们可以从拒绝对任何有坏值或缺失值的请求评分开始。最简单的方法是捕捉评分过程中引发的异常。
这里,我们在MODEL.predict()
周围添加了一个try/except
块,这样我们就可以捕捉到任何引发的异常。大部分代码只是准备一个错误响应。现在,如果用错误的或缺失的值调用 API,调用者将会收到这样的消息:未能对模型进行评分。异常:输入包含 NaN、infinity 或对 dtype 来说太大的值(“float32”)。
我们还使用适当的 HTTP 状态代码来为我们的用户提供额外的反馈,这不仅是一个阻止我们对请求评分的错误,而且是他们的错误。这是通过在对“400 错误请求”的响应上设置status_code
来完成的。在我们之前版本的 API 中,当出现未处理的异常时,Flask 仍然会为我们发送响应,但status_code
是“500 内部服务器错误”。虽然这提供了支持,但是“500”错误仅仅意味着 API 服务器端出了问题。它不会通知呼叫者他们的请求是原因,所以他们可能会尝试重复呼叫。请注意,当我们返回一个成功处理的请求时,我们不需要设置status_code
,因为该响应将自动具有“200 OK”的status_code
。
虽然这种方法是成功的,并且这个错误消息是相关的,但是这不是处理输入错误的理想方法。我们正在捕捉一个基本异常。虽然我们没有遇到任何其他异常,但这并不意味着它们不会发生。我们应该努力将输入错误与其他错误隔离开来。此外,我们正在发回异常的内容。如果此错误消息中包含敏感信息,我们会将其发送给呼叫者。这可能是一个安全问题。
直白
一个改进可能是显式地捕捉最初测试中出现的ValueError
异常。但是,不清楚这是否是值错误或丢失时引发的唯一异常。此外,ValueError
也可能发生在与调用者提供的错误/丢失数据无关的其他地方。由于这些因素,最好的方法是显式地检查和处理输入值。
我们添加了if
块来检查我们的任何特征值是否为None
。如果请求中缺少它们或者它们的值不能被转换成float
,就会出现这种情况。
有几件事可以改进:
- 我们只解决缺失的功能或那些不能转换成
float
的功能。在实际场景中,我们还想识别超出可接受范围的值。例如,所有四个特征都是花瓣和萼片长度的测量值,因此它们必须是正数。这些测量值也有一个上限。一万厘米的花瓣是不可能的。 - 我们应该跟踪一个请求是被成功评分还是被拒绝。这可以使用 Python 的
logging
模块来完成,但这是我们将在另一篇文章中更深入探讨的内容。
让我们给每样东西打分
我们用来建立模型的虹膜数据集已经非常干净了。在大多数真实场景中,这种清理和准备过程是模型构建的一大部分。特别是,我们在构建数据集中没有遇到任何缺失值。这是一个很大的话题,超出了本文的范围。你可以通过搜索“处理机器学习中的缺失数据”或“插补机器学习”找到大量的优秀资源。
这里我们将使用一种简单的方法来处理缺失值:使用特征的平均值。这叫做均值插补。
我们可以通过使用:X_train.mean(axis=0)
获得每个特征的平均值。查看原帖看看我们的训练集是如何构建的。这可能会根据构建训练数据集时使用的random_state
而有所不同,但它应该与以下内容非常相似(为清晰起见,四舍五入):
实现这一点就像在我们获得请求参数时更改默认值一样简单:
我们可以测试这个迭代,并验证它是否正常工作。事实上,我们可以看到,即使没有提供参数,它也会对请求进行评分。
在灰色地带得分
我们将跳过一个微妙情况的实现,在这种情况下,我们拒绝缺少重要特征的请求,但如果其他特征缺失,我们将使用均值插补。这可以通过将上述技术与一些定制逻辑仔细混合来实现。作为练习,您可以实现一个 API,该 API 将只对同时满足这两个条件的请求进行评分:
sepal_length
必须有效。- 其余 3 个特征中只能有一个缺失。
后续步骤
关于这些实现,我们有几个地方需要改进。首先,我们将模型和 API 耦合得比最初的例子更紧密。除了检索特定的查询参数,我们现在检查它们的值是否是None
或者用特定的值来输入它们。比方说,我们需要根据新数据重新调整模型。对于均值插补,我们需要检查并更新 API 代码库中每个特征的默认值。最终,我们希望构建一个 API,它可以对多个模型进行评分,包括具有不同特性的模型。理想情况下,我们希望模型本身检索它们需要的特性,准备它们,如果它们不应该获得记录,可能会引发异常或返回错误。然后,API 将只负责向模型传递数据,并根据模型预测的结果准备响应——这是一种明确的职责分离。
第二个改进是存储与发生的请求和错误相关的数据。如果我们有不能得分的请求,我们至少想知道这种情况多长时间发生一次,也许可以将这些拒绝分类。因为我们没有保存任何与我们正在处理的请求相关的数据,所以我们没有办法回答这些问题。
虽然这些都很重要,但在下一篇文章中,我们将重点关注如何测试我们的 API 对请求评分的能力。
[## 用 Python 构建预测 API(第 3 部分):自动化测试
在上一篇文章中,我们改进了预测 API 的错误处理,并考虑了关于哪个…
towardsdatascience.com](/building-prediction-apis-in-python-part-3-automated-testing-a7cfa1fa7e9d)
脚注
- 返回
None
而不是引发异常在函数式编程中很有帮助。例如,如果我们正在使用df.apply(my_funct, axis=1)
计算熊猫数据帧的新列,并且我们预计某些行的计算会失败,我们可以让my_funct
返回None
或numpy.nan
。结果列将包含计算成功的正确值,并将失败的计算视为缺失。这类似于也许单子模式。 - 我们收到这个错误是因为我们的模型会自动将我们的嵌套列表转换成包含数据类型为
float32
的元素的numpy.ndarray
。在此转换过程中,None
元素将变成numpy.nan
。
用 Python 构建预测 API(第 3 部分):自动化测试
原文:https://towardsdatascience.com/building-prediction-apis-in-python-part-3-automated-testing-a7cfa1fa7e9d?source=collection_archive---------1-----------------------
在上一篇文章中,我们改进了预测 API 的错误处理,并考虑了我们应该对哪些记录进行评分的微妙决定。在这篇文章中,我们将看看如何使用 pytest 测试我们的 API。
[## 用 Python 构建预测 API(第 1 部分):系列介绍&基本示例
好吧,你已经训练了一个模型,但是现在呢?如果没有人会使用,所有的工作都是没有意义的。在某些应用中…
medium.com](https://medium.com/@chris.moradi/building-prediction-apis-in-python-part-1-series-introduction-basic-example-fe89e12ffbd3)
和往常一样,我们将使用 Python 3,并且我将假设您要么正在使用 Anaconda,要么已经设置了一个安装了这些包的环境:flask、scikit-learn 和 pytest。
注意:我将在这篇文章中浏览代码片段,但是在上下文中查看完整的文件可能会有所帮助。你可以在 GitHub 上找到 的完整例子。
测试案例
虽然自动化测试是现代软件开发中的核心实践,但它尚未被许多数据科学家完全接受。简单地说,这是在主代码基础上运行测试的附加代码。测试框架,比如 pytest,使得定义和执行一套测试变得很容易。随着新功能的实现或现有代码的重构,这些测试帮助开发人员确认现有功能没有被破坏或定位已经引入的错误。
以下是一些不使用我的(尖刻的)回答编写测试的常见借口:
- *代码很少,所以不需要测试。*当您需要扩展当前功能时会发生什么?每个增强可能都很小,但是从长远来看,您可能会得到一个庞大的未经测试的代码库。如果目前代码很少,编写测试应该很容易,那么就去做吧!
- 当我写原始代码时,我已经根据多个测试用例检查了每个功能。太好了!构建测试的一个挑战是提出好的测试用例,而你已经做到了。每当你做一个小的改变时,有能力运行所有那些测试用例不是很棒吗?
- 我写代码不出错。当然啦!你不需要测试用例来测试你的代码,但是当其他人加入到项目中并开始修改你漂亮、完美的代码时会发生什么呢?我们怎么知道他们是否打碎了什么东西?你愿意详细检查他们所做的每一项承诺吗?你对在你的余生中维护这个代码感到兴奋吗?
在进入这篇文章的内容之前,我想指出我将是一个伪君子。我们将专注于测试 API。在这个过程中,我们还需要修改构建模型的代码。敏锐的读者会注意到,我没有为模型构建管道编写任何测试。如果有帮助的话,我真的很抱歉。
为更好的测试进行调整
在我们开始编写实际的测试之前,我想改变一下我们正在生成的 API 响应。目前,我们只发送回预测的类(虹膜类型)。虽然这是我们的预测 API 的用户所需要的,但它并没有提供大量的信息供我们测试。预测类被选为具有最高模型分数的类(虹膜类型)。由于这种阈值处理,即使潜在的分数有些不同,预测的类别也可以是相同的。这类似于一个函数,它执行复杂而精确的计算,但返回一个舍入到最接近的整数的值。即使许多输入的返回整数值与预期值匹配,基础计算也可能不正确。理想情况下,我们希望在计算的精确结果被阈值化或舍入之前验证它们是否正确。
为了给我们自己提供更多的数据来验证我们对模型的评分是正确的,我们将改变 API 响应来包含每个类的概率。这是通过调用MODEL.predict_proba()
而不是MODEL.predict()
来完成的。然后我们使用argmax()
来获得最大值的索引,这给了我们预测的类。我们将通过probabilities
将原始类别概率返回给用户(参见下面的示例响应)。
Updated API to return class probabilities
然后我们可以运行 API ( python predict_api.py
)并通过requests
进行测试调用:
API 的基本测试
我们将从一个简单的例子开始,在这个例子中,我们只对如上所示的相同例子进行评分,但是我们将使用 pytest 来完成这个任务。我们首先需要创建一个测试文件:test_predict_api.py
。现在,我们可以把它放在与我们的 API 文件相同的目录中:predict_api.py
。注意:pytest 能够自动定位测试文件和函数,但是您需要协助它这样做。默认情况下,它将检查任何文件名以“test_”前缀开头的文件,并运行任何以“test_”开头的测试函数。
当我们构建测试时,我们通常遵循这种模式:
- 设置(可选):测试或环境的初始化。示例:初始化数据库,创建将在测试中使用的类的实例,初始化系统的状态,等等
- 运行代码:在预定义的测试用例上或在预定义的环境中运行主代码库(测试中的代码)中的一些代码。这可能包括:调用一个函数/方法,创建一个类的实例,初始化一个资源,调用一个 API 等等
- 验证结果:通过使用
assert
语句检查代码的效果是否符合预期:函数调用的返回值是否正确,异常是否被适当地提出,系统是否已经改变到正确的状态等等… - 拆除(可选):测试运行后进行清理,将环境恢复到默认状态。
以下是本示例如何与这些步骤保持一致:
- 设置:实例化一个
test_client
(如下所述),它将允许我们模拟对 API 的调用。 - 运行代码:用一组预定义的特性调用
/predict
端点。 - 验证结果:我们得到一个带有 200 的
status_code
的响应,内容是带有正确格式和值的 JSON。 - 拆:这个有些含蓄。我们将在
test_client
的“设置”过程中使用上下文管理器。退出时,客户端将被清理。
如上所述,我们使用的test_client
是 Flask 的一个特性,它允许我们在不运行服务器的情况下模拟调用。这里,我们使用上下文管理器创建一个新的客户机。由此,我们发出一个 GET 请求。query_string
关键字参数提供的功能类似于params
在requests.get()
中的工作方式;它允许我们传递用于创建查询字符串的数据。
从响应中,我们检查我们是否收到了“200 OK”状态,最后我们检查响应的有效负载是否与我们预期的相匹配。既然它是以bytes
的形式出现,我们可以用json.loads()
把它转换成一个dict
。
我们现在可以在命令行使用pytest
来执行测试。
总是先失败
每当你编写自动化测试时,验证你确实在测试一些东西是很重要的——你的测试可能会失败。虽然这是一个显而易见的说法,但一个常见的缺陷是编写的测试实际上并不测试任何东西。当它们通过时,开发人员认为被测试的代码是正确的。然而,测试通过了,因为测试写得很差。
防止这种错误的一种方法是使用测试驱动开发(TDD)。我们不会对此进行深入探讨,但这是一个发展过程,其中:
- 您首先为一个新特性编写一个测试。
- 您确认测试失败。
- 您编写代码来实现新功能。
- 您验证测试现在通过了。
如果你之前没有尝试过 TDD,我绝对推荐。这需要纪律,尤其是在开始的时候,还需要其他开发者和利益相关者的支持。然而,在实现新特性时,对过程的投入会带来更少的错误和更低的压力。要了解更多,请阅读 Harry Percival 的优秀著作,用 Python 进行测试驱动的开发,这本书是他在网上免费提供的。
如果您不支持 TDD,我用来验证每个测试是否确实在测试的懒惰方法是将我的 assert 表达式更改为显式失败。例如,我们将把assert response.status_code == 200
改为assert response.status_code != 200
。如果您进行了此更改并重新运行测试,您应该会收到类似于以下内容的失败消息:
如果您打算使用这种方法,请注意 pytest 只会报告第一个发生的AssertionError
。所以,你必须分别改变每个断言,然后重新测试。
更多测试
我们现在有一个对我们的 API 的测试调用,它正在工作。我们如何扩展这个来测试具有不同特征值和不同预期结果(标签和概率)的多个调用?一个快捷的选择是使用我们在模型构建期间创建的测试数据集。但是,我们需要获得类概率和预测标签,以用作每个输入记录的预期结果。
需要注意的一点是我们测试的是 API 平台,而不是模型本身。基本上,这意味着我们不关心模型是否做出了错误的预测;我们只想验证 API 平台上的模型输出是否与构建/离线/开发环境中的模型输出相匹配。我们还需要测试特性的准备(例如,均值插补)是否在 API 平台上正确完成,但我们将在本文的下一部分讨论这个问题。
由于我们的测试数据集可能会随着模型的每个新版本而改变,我们应该将这些数据的生成合并到我们的模型构建中。我对我们的模型构建脚本做了一些轻微的重构(还需要更多),并添加了在模型构建后生成测试数据集的代码。我们将把我们的测试用例存储在一个 JSON 文件中,每个测试用例的结构如下:
下面是我们的模型构建代码的修改版本,它合并了测试数据集的生成:
在顶部,有一个名为prep_test_cases()
的函数,它只是将每个测试的特性、分类概率和预测标签重新格式化为我们的测试用例格式。
现在我们已经生成了测试数据,我们需要添加一个新的测试来对该文件中的所有记录进行评分,并检查响应:
因为我们以一种清晰的方式构建了测试数据,其中每个测试用例都有特性(API 输入)以及预期的响应(API 输出),所以测试代码相当简单。这种方法的一个缺点是类别概率是浮动的,我们正在对这些值进行精确的比较。通常,在比较浮点值时允许有一定的容差,这样非常接近的值就被认为是等价的。为了处理这个问题,我们需要解析预期的响应,并在比较probabilities
中的每个值时使用pytest.approx()
。它不需要太多的代码,但是我认为这会使这个讨论有点混乱,所以我省略了实现。
处理缺失值
我们的 API 配置为使用均值插补来替换错误值或缺失值,但我们的测试数据集不包含任何缺失值的记录。然而,这不是一个问题,因为我们可以使用我们已经拥有的数据来模拟这些数据。我们只需要用某个特性的平均值替换现有的值,并重新对记录进行评分。对于我们的模型构建脚本,我们将在原始测试数据生成代码之后添加以下内容:
我们可能不需要这么彻底,但是对于每一条记录,我们都在测试可能缺失的每一个特征组合。我们为每条记录创建了两个版本:一个有缺失值的None
,另一个有平均值的估算值。第一个将作为features
存储在测试用例中(在None
有价值的特性被删除之后)。第二个将被评分,以获得我们期望看到的 API 返回的预测概率。为了去掉 None
值的特性,我们必须在prep_test_cases
函数中对feat_dict
的创建做一个小小的改变。下面是修改后的函数:
我们也需要改变我们的测试来使用这个新文件。虽然我们可以复制最后一个测试函数test_api()
并替换文件名testdata_iris_v1.0.json
,但这会导致重复的代码。因为我们需要测试函数除了文件名之外完全相同,所以更好的方法是使用 pytest 的parametrize
功能。我们只需添加一个装饰器,允许我们为测试函数指定参数,并为每个值重新运行测试。在这种情况下,我们将传入文件名:
测试错误
在上一篇关于错误处理的文章中,我提到我们可以更好地选择我们愿意评分的记录,但是我没有提供这样的例子。这里我们将调整我们的 API 来看一个简单的例子,在这个例子中,我们将拒绝缺少petal_width
数据的请求。我们将对所有其他记录进行评分,如果需要的话,使用平均插补。
稍微扯点题外话,我是怎么选的petal_width
?嗯,如果我们查看特征重要性(使用model.feature_importances_
,我们会看到第四个特征(petal_width
)具有最高值,归一化得分为 0.51。因为这是我们模型中最重要的特性,所以拒绝缺少这个特性的记录是最有意义的。
实现这一点的一个简单方法是删除petal_width
的默认值,然后在它丢失的情况下处理它。几乎所有的代码都保持不变,但是我在这里把它包括进来是为了便于理解。
我们可以做一个快速测试,以确保它适用于一个简单的情况:
太好了!有用!现在,我们只需要将它添加到我们的测试套件中。
为了简单起见,我将跳过如何修改我们旧的缺失值测试,只实现处理petal_width
的缺失值或错误值的新测试。基本上,我从missing_grps
中移除了所有包含 3 的元组(索引为petal_width
)以及所有特性都缺失的测试。
对于我们的新测试,我们可以使用相同的 JSON 格式。这将是一个更干净的实现。为了清楚起见,我将在一个单独的函数中实现这些测试,这个函数有两个针对petal_width
的测试用例:特性丢失和特性有一个错误的值(“垃圾”)。
我们可以重新运行我们的测试,并验证这些通过。当然,我们还应该尝试将==
改为!=
,以验证它们在每种情况下都失败。同样,这将有助于确保我们正在测试我们实际认为我们正在测试的东西。
识别问题
现在我们有了测试,我们可能想知道它们是否真的能捕捉到我们代码中的错误。也许,当您创建这些测试并在您的 API 代码上运行它们时,您已经发现了一些问题。如果没有,您可以做一些简单的更改,这些更改会导致一个或多个测试失败(分别进行这些操作):
- 在 API 代码中,将
sepal_length
的default
(平均插补)值从 5.8 更改为 5.3。 - 在 API 中,放回
petal_width
的平均值插补。这将允许 API 对缺少petal_width
的记录进行评分。当petal_width
丢失时,您应该在期望 API 返回“400 错误请求”的测试中看到失败。 - 在 API 中,更改当
petal_width
丢失时发送的错误消息的文本。 - 我们还可以模拟有人意外修改模型并试图部署它的情况。为了测试这一点,我们可以构建您的模型的替代版本,部署它,但是使用原始模型的测试数据文件(JSON)。实现这一点的快速方法是在训练/测试集分割中对
random_state
使用不同的值(例如random_state=30
)。记得把joblib.dump()
中的模型输出文件名改成别的(例如*' iris-RF-altmodel . pkl '*);您需要在 API 中修改MODEL
来引用这个文件。此外,确保您不要执行生成测试数据文件的代码,因为这些代码会基于替代模型重新构建它们。当您重新运行您的测试时,您可能会在所有测试中看到失败,除了那些当petal_width
丢失或无效时拒绝请求的测试。如果您的测试仍然通过,尝试另一个random_state
,因为模型可能是等价的,因为训练集可能保持不变或者变化不足以改变模型。
我们的测试肯定能发现问题,但是我们能发现所有的问题吗?简单的答案是,我们可能没有捕捉到一切。在创建这个帖子的时候,我试着将sepal_width
的平均插补(默认值)从 3.0 改为 3.1。当我重新测试时,他们都通过了。也许这没什么大不了的;也许我们的模型对平均值附近sepal_width
的微小变化并不敏感。这是最不重要的特征。然而,我们将我们的测试集用于测试用例,这些数据点不一定落在不同类的边界附近。如果我们有更多的测试用例或者更好的测试用例,我们可能已经能够捕捉到这种类型的 bug。
包扎
我们已经看到自动化测试可以帮助我们找到代码中的错误。虽然我们从测试单个 API 调用开始,但我们能够快速转向运行大量测试用例的框架,并且它只需要添加一点额外的代码。
测试是一个重要的话题,所以我们可能会在以后的文章中再次讨论这个话题。这里有一些我们没有涉及的领域的快速预览,但将来可能会涉及:
- 测试速度:当你改变代码时,经常运行测试是有益的。这使得在重构现有代码或添加新功能时更容易及早发现错误。如果测试需要一段时间来运行,开发人员就不太可能这样做。一种方法是将快速运行的测试与耗时较长的测试分开。然后,开发人员可以在进行增量更改时运行快速测试套件,并在将更改集成回主存储库之前运行完整套件。
- 嘲讽和修补:我们发现对
sepal_width
的缺省值(平均插补值)的微小改变不会导致我们的测试失败。如果这是一个需求,我们可以在评分过程中使用补丁拦截对model.predict_proba()
的调用,以验证正确的值被替换。 - Fixtures:这是 pytest 的一个特性,您可以创建、配置和销毁资源,以便建立一个干净且一致的环境,每个测试都可以在其中运行。如果你熟悉许多单元测试框架中的“安装”和“拆卸”, fixtures 就是这种思想的延伸。
- 子系统的集成:目前,我们只有模型和 API。在随后的文章中,我们将看看如何添加一个数据库后端和一些其他服务。我们如何测试这些?我们如何测试整个系统?
- 持续集成工具:这些工具有助于更容易地将代码集成到共享存储库中。通过使它变得更容易,我们希望它能更经常地、更小规模地完成。这些工具的一个共同特征是,它们会在每次提交拉请求时自动运行测试套件,并且通过/失败的结果会提供给评审者。
- 测试覆盖率:我们测试了我们代码的每一行吗?我们可以创建一个测试覆盖报告来帮助我们了解哪些代码行在测试期间运行了,哪些没有运行。这不会告诉我们是否已经处理了所有可能的情况,但是它可以给我们信息,让我们知道我们的测试套件在哪里不足。
- 高级测试方法:我们不太可能涵盖这些主题,但是我想提到它们。使用基于属性的测试(参见假设,您创建参数化测试,框架为您生成一组广泛的测试用例。这可以导致更全面的测试,而不需要你想出所有的边缘情况。突变测试(见宇宙射线)采用了一种非常不同的方法。它与您现有的测试用例一起工作,并实际上以某种小的方式(突变)修改您的源代码(测试中的代码),以查看您现有的测试是否失败。如果所有的测试仍然通过,你的测试代码是不完整的,因为它不能找到由变异引入的错误。
脚注
- 不确定是否有人真的会这么说,但有时你会遇到这样想的人。
- 你可能在想,*“我的用户不需要知道每个类的底层分数;他们只需要预测。那么,为什么我只是为了测试而改变我的回答呢?”*好问题!我们采用这种方法是出于方便和清晰的考虑。在实际实现中,您使用一个标志来指定是否返回基础分数,并且可能将此功能限制于某些用户。我们还可以使用模仿和修补来访问分数,而无需修改响应来包含模型分数。
- 如果你在运行
pytest
时遇到问题,请尝试以下选项:py.test
或python -m pytest
。
用 Python 构建预测 API(第 4 部分):解耦模型和 API
原文:https://towardsdatascience.com/building-prediction-apis-in-python-part-4-decoupling-the-model-and-api-4b5eaf2ed125?source=collection_archive---------6-----------------------
在最后一部分中,我们用 pytest 查看了自动化测试,以验证我们的 API 是否正确地对模型评分。在本文中,我们将探讨如何将负责处理请求和准备响应的 API 功能与准备特性和模型评分所需的代码分离开来。
如果你是这个系列的新手,欢迎!此外,您可能希望从头开始,只是为了回顾我们已经完成的内容。
[## 用 Python 构建预测 API(第 1 部分):系列介绍&基本示例
好吧,你已经训练了一个模型,但是现在呢?如果没有人会使用,所有的工作都是没有意义的。在某些应用中…
towardsdatascience.com](/building-prediction-apis-in-python-part-1-series-introduction-basic-example-fe89e12ffbd3)
在这篇文章中,我们将会看到一些代码片段,但是完整的文件可以在 GitHub 上找到。
附注:我非常感谢这个系列给我的反馈。在前三个部分,我花了很多时间修改草稿,以确保尽可能清晰地呈现内容。我最近刚开始面试,所以时间有点紧。我将尽我所能继续定期发帖,但可能会有更长的延迟。我也会试着花更少的时间复习。如果有令人困惑的部分,请告诉我,我会尽力澄清。谢谢!
紧密耦合代码
我们将从第三部分中的虹膜预测模型的最后一个例子开始。我们将拒绝缺少petal_width
的请求;对于所有其他缺失的特征,我们将使用均值插补进行评分。
正如我们所看到的,API 包含了大量与这个特定模型相关的代码。事实上,大部分代码都是特定于这个模型或 iris 模型的一个版本的:
- 我们从请求中检索硬编码的查询字符串参数,将它们转换成
float
值,如果它们丢失或不能转换,就用默认值替换它们。 - 我们正在检查
petal_width
是否丢失,并准备发送一个特定的错误消息给呼叫者。 - 我们正在创建特征向量。API 需要知道将特性放入
features
列表的正确顺序。 - 类别标签包含在一个全局
MODEL_LABELS
变量中。
我们可以修改这个代码来处理这个模型的变体。例如,对我们的特性使用硬编码默认值通常是糟糕的编码实践。我们可以将这些提取到一个配置文件中。这将允许我们用不同的平均插补值对模型的两个版本进行评分。
不幸的是,我们将很快发现其他的变化将很难适应。假设我们想要实现两个不同的模型意图:当前版本和一个如果缺少petal_width
我们将估算,但是拒绝缺少sepal_width
的请求。如果处理其中一个模型的缺失值的逻辑变得更加复杂怎么办?如果我们有一个完全不同的模型——一个使用 40 个特征来预测欺诈的模型——会怎么样?
正如在之前的一篇文章中提到的,我们可以为每种类型的模型创建单独的 API 或端点,但是引用 Raymond Hettinger 的话,“一定有更好的方法!”
拉开线球
在理想情况下,我们会将这种功能划分如下:
- API:接受请求,找到合适的模型进行评分,将原始数据传递给模型进行评分,并根据模型输出准备响应。
- Model:提取正确的字段,将原始数据准备成特性,预测是否可以对记录进行评分,如果不能,则引发错误,并将结果发送回 API。
包装我们的模型
有几种方法可以实现这一点,但是我们将从一种简单的方法开始。我们将在一些额外的代码中包装我们的模型,这些代码将处理特征检索和准备。
ModelWrapper
类只有三种方法:__init__
、predict
和_prepare_features
。当我们创建一个实例时,我们将传入带有class_labels
(之前存储在MODEL_LABELS
中)和feature_defaults
( dict
包含插补值)的 Scikit-Learn 模型对象(model_object
)。
API 将调用predict
方法来获得预测。API 将直接传入request.args
对象,模型将提取正确的字段。缺失值的提取和处理已转移到单独的方法_prepare_features
。这些函数中的代码与我们最初在 API 中的代码几乎相同。
顺便提一句,如果您不熟悉 Python 中的单个前导下划线约定,这是一种将方法标记为“仅供内部使用”的方式——代码只打算由类(或其基类/子类)中定义的其他方法调用。然而,没有机制可以阻止任何人直接调用它。
最后要讨论的是我们如何将预测或错误返回给 API 代码。如果我们成功了,我们将返回一个带有label
和probabilities
的dict
。在出现错误的情况下,我们将引发一个定制的异常,ModelError
,它被定义在文件的顶部。一个奇怪的实现细节是我选择将这个异常作为ModelWrapper
的一部分。稍后,我们将在 API 中使用它来引用try/except
块中的这个异常。更干净的方法是在定义的地方有一个共享的工具模块/库。然后,模型包装器代码和 API 都可以引用这个定义。我认为共享库的方法可能更令人困惑(单独的文件),这就是为什么我选择了这个。
修改模型构建
既然我们已经定义了包装器代码,我们需要将它合并到我们的模型构建过程中。这样,我们可以使用joblib
将模型、特征提取和评分代码一起打包/保存。
基本上,我们只是创建了一个dict
,它有键的特性名称和特性的平均值作为相应的值。我们包装模型,然后保存这个包装的版本。为了清楚起见,我省略了生成我们的测试数据集的代码(参见第 3 部分,但是你可以在这里找到完整的文件。
新的 API
最后一步是修改我们的 API 来使用包装的模型。
大多数情况下,我们需要删除所有的特征提取和评分代码。MODEL
以同样的方式加载(作为一个全局变量),但是这个版本除了包含我们的 Scikit 模型之外,还包含了所有的ModelWrapper
代码。在一个try/except
街区,我们叫MODEL.predict()
,但现在我们只是路过request.args
。如果出现异常,我们可以捕捉异常,并将错误消息转换成正确的响应(带有正确的状态代码)。如果没有出现异常,我们将返回一个带有标签和类别概率的dict
。剩下的唯一事情就是通过jsonify()
准备响应。
运行我们的测试
我们可以复制我们在第 3 部分中构建的test_predict_api.py
文件(这里也有)。将它与所有其他文件放在同一个目录中,并运行pytest
。这些测试应该都能通过。
这种方法的局限性
我们已经成功地将我们的模型评分代码从我们的通用 API 代码中分离出来。现在,API 的predict
端点中没有任何东西是特定于这个 model⁴的,所以我们可以快速扩展这个 API 来对多个模型进行评分。
虽然这是一个巨大的进步,但这种方法存在一些挑战。主要的一点是特性生成代码与一般的模型构建代码是分开的。可能很难看到这一点,因为我们的模型构建非常简单。我们的训练数据集甚至没有任何缺失值,所以我们不需要做均值插补。假设我们正在使用一个更现实的模型,该模型需要分类变量的虚拟/一次性编码、插补或复杂的特征计算,而不仅仅是转换到float
。使用我们当前的方法,我们可能需要维护这个特征化代码的两个版本:一个操作训练数据,另一个版本是ModelWrapper
的一部分。
创建一个可以应用于训练和评分环境的统一特征代码库有巨大的好处,但这可能具有挑战性,并不总是可能的。通过在两个上下文中使用单一版本的特征化代码,我们减少了错误,并且可以更快地部署模型。这不总是可能的主要原因是每个上下文有不同的约束。在模型构建过程中,必须准备好整个训练数据集,因此可以优化实现以一次处理许多记录。对于评分,我们只需要准备一个单一的记录,但这应该尽快完成。
我们不打算在这篇文章中讨论它,但是 Scikit-Learn 有一个管道特性,让我们定义在模型构建和评分上下文之间共享的预处理/特征化步骤。然而,这也不是一个完美的解决方案。对可以在管道中定义的步骤类型有一些约束,这可能是限制性的。⁵
脚注
- Raymond 从事 Python 核心开发已经超过 15 年,并且是
collections
和itertools
模块的创建者。他还教授 Python 多年,是一位杰出的教育家。谷歌一下他,看看他所有的演讲,因为他们简直太棒了。 - 你可以把这些看作是 Java 类中的
private
或protected
方法。但是,Java 明确禁止从外部调用这些方法。Python 不会。 - 状态不是结果
dict
的一部分,所以我们需要添加它。如果你不熟悉**result
,这是执行关键字解包。快速举例:d = {'a': 1, 'b': 2, 'c': 3}
。然后,调用:myfuct(**d)
等价于调用:myfunct(a=1, b=2, c=3)
- 我们仍然有硬编码的
MODEL
全局变量,但是我们会在将来修复它。 - 可能有一个我们希望在 API 平台上运行的特定步骤,我们不需要在模型构建过程中运行。在以后的文章中,我们将关注日志/数据库存储。我们可能希望存储的一件事是准备好的特征向量,以便如果我们在 API 平台上遇到问题,我们可以验证特征是否被正确计算。为此,我们需要在模型评分发生之前在管道中插入一个“记录”步骤(管道的最后一步)。我不确定这是否可能。
通过快速思考构建句子嵌入
原文:https://towardsdatascience.com/building-sentence-embeddings-via-quick-thoughts-945484cae273?source=collection_archive---------18-----------------------
快速思考入门
Photo by rawpixel on Unsplash
在之前的故事中,我分享了skip-thinks来计算句子嵌入。今天,我们有另一种无监督学习方法来计算句子嵌入,这就是快速思维。
Logeswaran 等人(2018)引入了快速思考方法来检索下游应用的句子嵌入。看完这篇文章,你会明白:
- 思维敏捷的设计
- 估价
- 实验
- 参考
快速思维设计
快速思维和跳过思维非常相似。目标是分类候选句子是否属于相邻句子,而不是生成单词来构造句子(跳过思想方法)。与 skip-gram 相同,快速思考和 skip-gram 构建都利用分类器来学习向量。
#a skip-thoughts, #b quick-thoughts (Logeswaran et al., 2018)
给出一个目标句子,并使用负采样方法(Mikolov 等人,2013 年)为二元分类器构建一个有效的上下文句子和非上下文句子。
通过将有效的上下文句子标记为目标(例如 1),而将其他非上下文句子标记为非目标(例如 0),它可以建立一个分类器来找出哪个句子与目标句子相关。
该架构与使用编码器和解码器方法的跳跃思维相同,但是快速思维使用分类器而不是语言模型。你可以在这里查看来了解这个架构。
实验
Unsupervised Representation Learning Comparison (Logeswaran et al. 2018)
从上面的结果,你可以注意到 QT(快速思维)在不同的任务中得到了很好的结果。单 QT 和双 QT 意味着使用单向和双向 RNN 模型。
Supervised Representation Learning Comparison (Logeswaran et al. 2018)
在监督表征学习比较中,MC-QT(多通道快速思维)几乎在所有任务中都胜出。MC-QT 被定义为两个双向 rnn 的级联。第一个双向 RNN 使用一个预训练的字向量,它是手套。另一个双向 RNN 是可调字向量,这意味着从头开始训练向量。
Image Caption Retrieval (Logeswaran et al. 2018)
在图像到文本和文本到图像的下游任务中,MC-QT 也取得了不错的效果。
拿走
- 和跳跃思维一样,快速思维构建句子嵌入。
- 与 skip-gram 相同,Quick-thinks 利用分类器来学习嵌入。
- MC-QT 展示了从多个 NLP 下游任务中学习句子嵌入的能力。
关于我
我是湾区的数据科学家。专注于数据科学、人工智能,尤其是 NLP 和平台相关领域的最新发展。你可以通过媒体博客、 LinkedIn 或 Github 联系我。
参考
Logeswaran L .,Lee H .,2018,学习句子表征的高效框架
tensor flow 中的快速思考(原创)
跳跃式思维故事
文字嵌入故事
用流行的深度学习框架构建简单的人工神经网络
原文:https://towardsdatascience.com/building-simple-artificial-neural-networks-with-tensorflow-keras-pytorch-and-mxnet-gluon-63a025ebb0b3?source=collection_archive---------13-----------------------
使用 TensorFlow、Keras、PyTorch 和 MXNet/Gluon
几周前,我完成了构建一个非常简单的神经网络的步骤,并在 go 中从头开始实现了它。然而,已经有许多深度学习框架可用,所以如果你想使用深度学习作为解决问题的工具,从头开始通常不是你要做的。
问题是,在众多深度学习框架中,我应该使用哪一个?比较深度学习框架的方法有很多。这是数据孵化器最近(2017 年 9 月)的排名,根据他们的 Github、Stack Overflow 和 Google 搜索结果得分,给出了一个有趣的人气排名。
Deep learning frameworks popularity (data from https://blog.thedataincubator.com/2017/10/ranking-popular-deep-learning-libraries-for-data-science/)
从结果来看,很明显 TensorFlow 无疑是最受欢迎的框架,随着 Keras 现在成为 TensorFlow 本身的一部分,事情在不久的将来不会有太大变化。此外,几乎所有流行的深度学习框架都有 Python APIs,因此 TensorFlow/Keras 与 Python 的结合似乎是正确的选择。
尽管如此,我对其他一些框架很好奇,所以我开始了一段小小的旅程,编写与我在这些框架中所做的相同(或几乎相同)的简单人工神经网络进行比较。
作为快速复习,我创建的神经网络是一个简单的前馈神经网络,通常也称为多级感知器(MLP)。使用这个简单的 MLP,我获得了 MNIST 6 万个手写数字的数据集,并用它来训练神经网络。之后,我使用 10,000 个手写数字的测试数据集来测试神经网络的准确性。
Our simple artificial neural network
神经网络有 3 层,第一(输入)层有 784 个神经元(28×28 像素),第二(隐藏)层有 200 个神经元,最后(输出)层有 10 个神经元。我用 sigmoid 函数作为激活函数,也用均方差作为损失函数。最后,我用 0.1 作为学习率,完全不使用任何偏向神经元。
以下所有实施都遵循相同的一般步骤:
- 设置参数并加载数据集(大多数框架都有加载标准数据集的方法,如 MNIST)
- 通过创建一个创建并返回神经网络的
mlp
函数来定义神经网络 - 定义
train
功能 - 定义
predict
功能 - 创建一个 main,允许用户首先使用训练数据集(60,000 个图像)进行训练,然后使用测试数据集(10,000 个图像)进行预测
这种用 MNIST 数据集对数字进行的手写识别在深度学习教程中经常使用,它几乎是编写深度学习程序的“hello world”。不过,作为免责声明,您在下面看到的实现没有经过任何方式的优化,也不是最终的实现方式。事实上,还有许多其他更好的方法,这只是几个例子。
现在我们开始,先看看如何在 TensorFlow 中实现这个。
张量流
TensorFlow 最初由从事谷歌大脑项目的研究人员和工程师开发,供内部使用,并于 2015 年开源。这是迄今为止最受欢迎的深度学习框架。
在 TensorFlow 上运行的更著名的项目包括 DeepMind (开发 AlphaGo 的谷歌公司),它在 2016 年从 Torch 转换为 TensorFlow。
这个实现使用 TensorFlow 1.6。我们开始吧。
设置参数并加载数据集
import TensorFlow as tf
import argparse
import numpy as np
from TensorFlow.examples.tutorials.mnist import input_data
# parameters
inputs, hiddens, outputs = 784, 200, 10
learning_rate = 0.01
epochs = 50
batch_size = 20
#loading the datasets
mnist = input_data.read_data_sets("./mnist/", one_hot=True)
相当简单,不言自明。请注意,我们将数据输出设置为单次触发。这仅仅意味着具有最高值的 ndarray 元素的位置是正确的。
定义神经网络
# a random generator using uniform
def random(r, c, v):
return tf.random_uniform([r,c], minval=-1/tf.sqrt(float(v)), maxval=1/tf.sqrt(float(v)))
# the neural network
def mlp(x, hidden_weights=None, output_weights=None):
if hidden_weights == None:
hidden_weights = tf.Variable(random(inputs, hiddens, inputs), name="hidden_weights")
if output_weights == None:
output_weights = tf.Variable(random(hiddens, outputs, hiddens), name="output_weights")
hidden_outputs = tf.matmul(x, hidden_weights)
hidden_outputs = tf.nn.sigmoid(hidden_outputs)
final_outputs = tf.matmul(hidden_outputs, output_weights)
final_outputs = tf.nn.sigmoid(final_outputs)
return final_outputs
这是我们定义神经网络的地方。相对来说比较直接。如果没有传入隐藏和输出权重,则使用tf.random_uniform
函数随机生成权重。这发生在我们训练神经网络的时候。
How a neuron works
正如在我之前创建的神经网络一样,我们首先将输入x
与隐藏权重相乘(使用tf.matmul
)以获得隐藏输出。请记住,我们正在处理矩阵,因此tf.matmul
实际上是一个点积函数,隐藏权重和输入都是矩阵。
隐藏的输出然后通过一个激活函数,在这个例子中,是一个sigmoid
函数。然后将输出乘以输出权重,得到最终输出。
最终输出在再次通过 sigmoid 激活函数后返回。
定义列车功能
# training with the train dataset
def train(x, y):
final_outputs = mlp(x)
errors = tf.reduce_mean(tf.squared_difference(final_outputs, y))
optimiser = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(errors)
init_op = tf.global_variables_initializer()
saver = tf.train.Saver()
with tf.Session() as sess:
sess.run(init_op)
total_batch = int(len(mnist.train.labels) / batch_size)
for epoch in range(epochs):
avg_error = 0
for i in range(total_batch):
batch_x, batch_y = mnist.train.next_batch(batch_size=batch_size)
_, c = sess.run([optimiser, errors], feed_dict={x: batch_x, y: batch_y})
avg_error += c / total_batch
print("Epoch [%d/%d], error: %.4f" %(epoch+1, epochs, avg_error))
print("\nTraining complete!")
saver.save(sess, "./model")
让我们看看我们如何训练我们的神经网络模型。首先,我们使用mlp
函数创建它,向它传递输入。我们还将我们的误差函数恰当地定义为目标和输出之间的平方差(均方误差)。
接下来,我们定义优化器,我们在这里使用 Adam 优化器,向它传递学习率和我们的误差函数。当我第一次尝试这个的时候,我使用了梯度下降优化器,但是这些值需要很长时间才能收敛。当我切换到 Adam 优化器时,它收敛得很好,所以我改用 Adam 优化器。
现在我们有了优化器,我们初始化所有的变量并定义一个保护程序,这样我们就可以保存模型了。我们启动一个会话,并按时期运行小批量,将我们之前加载的训练数据集传递给它。
一旦我们完成训练,我们保存模型。张量流模型由两部分组成。第一个是元图,它保存了张量流图上的信息。这被保存到一个扩展名为.meta
的文件中,在这种情况下,它将是model.meta
。
第二个是一堆检查点文件。model.index
存储变量名称和形状的列表,而model.data-00000-of-00001
存储变量的实际值。
稍后,当我们想要加载模型进行预测时,我们将重用这些文件。
定义预测函数
# predicting with the test dataset
def predict(x):
saver = tf.train.import_meta_graph("./model.meta")
with tf.Session() as sess:
saver.restore(sess, tf.train.latest_checkpoint("./"))
graph = tf.get_default_graph()
hidden_weights = graph.get_tensor_by_name("hidden_weights:0")
output_weights = graph.get_tensor_by_name("output_weights:0")
final_outputs = mlp(x, hidden_weights, output_weights)
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(final_outputs, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
tf.summary.scalar('accuracy', accuracy)
print(sess.run(accuracy, feed_dict={x: mnist.test.images, y: mnist.test.labels}))
在我们训练好模型之后,我们会想要一些可以用来预测值的东西。在这种情况下,我们实际上想要的是对测试数据集中的 10,000 张图像运行我们的predict
函数,看看我们的训练模型正确地得到了多少张图像。
我们从导入来自model.meta
文件的元图开始。接下来,我们恢复检查点,并使用默认的图来获得隐藏的权重和输出权重各自的名称。
最后,我们通过调用mlp
函数并向其传递保存的权重来恢复训练好的模型。
有了训练好的模型,当我们通过测试数据集时,我们试图预测输出,并获得模型的准确性。predict
功能打印出所有测试图像的预测精度。
训练然后预测
if __name__ == "__main__":
x = tf.placeholder(tf.float32, [None, inputs])
y = tf.placeholder(tf.float32, [None, outputs])
parser = argparse.ArgumentParser()
parser.add_argument("--action", type=str, default="predict" )
FLAGS, unparsed = parser.parse_known_args()
if FLAGS.action == "predict":
predict(x)
if FLAGS.action == "train":
train(x, y)
最后一点很简单,它只是一个主要的功能,允许用户进行预测或训练。这一部分在其他实现中实际上是相同的,所以我以后不会再展示这段代码了。
这是结果。
模型预测正确率为 97.25%,不算太好但还可以。现在我们接下来看看 Keras。
Keras(在张量流上)
Keras 不是一个独立的框架,而是一个建立在 TensorFlow、Theano 和 CNTK 之上的接口。Keras 设计用于快速原型制作,易于使用和用户友好。
2017 年,TensorFlow 决定在 TensorFlow 的核心库中支持 Keras,尽管 Keras 本身没有任何变化。
让我们看看 Keras 的情况有什么不同。
设置参数并加载数据集
import argparse
from keras.models import Sequential
from keras.datasets import mnist
from keras.layers import Dense
from keras.models import load_model
from keras import optimizers
from keras import utils
# parameters
inputs, hiddens, outputs = 784, 100, 10
learning_rate = 0.01
epochs = 50
batch_size = 20
# loading datasets
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
train_images = train_images.reshape(60000, 784).astype('float32')/255
train_labels = utils.to_categorical(train_labels, outputs)
test_images = test_images.reshape(10000, 784).astype('float32')/255
test_labels = utils.to_categorical(test_labels, outputs)
设置数据集似乎比以前更加复杂,但这没什么大不了的,事实上,更清楚的是,我们正在将训练和测试数据集重塑为正确的形状和大小。
定义列车功能
# training with the train dataset
def train():
model = Sequential()
model.add(Dense(hiddens, activation='sigmoid', input_shape=(inputs,)))
model.add(Dense(outputs, activation='sigmoid'))
sgd = optimizers.Adam(lr=learning_rate)
model.compile(optimizer=sgd, loss='mean_squared_error')
model.fit(train_images, train_labels, batch_size=batch_size, epochs=epochs)
model.save('mlp_model.h5')
你可能会注意到,我没有在这里定义神经网络。我本来可以创建一个单独的mlp
函数来完成这项工作,但这并不是真正必要的,因为我使用了一个内置的 Keras 模型,名为Sequential
,并简单地在它上面堆叠层来构建网络。
前两行添加了隐藏层和输出层(根据给定的隐藏层的输入形状,默认情况下会采用后面的输入)。这包括激活功能sigmoid
。
接下来,我们使用内置的 Adam 优化器optimizers.Adam
来定义优化器。
该模型由优化器编译,并被赋予一个误差(或损失)函数mean_squared_error
,该函数也是内置的。
最后,我们使用fit
方法,使用图像和标签训练模型,具有给定的批量大小和时期数。
和以前一样,我们在训练模型之后保存它。
定义预测函数
# predicting the test dataset
def predict():
model = load_model("mlp_model.h5")
error = model.evaluate(test_images, test_labels)
print("accuracy:", 1 - error)
如果您认为训练函数相当简单,请查看预测函数!您只需要加载模型,然后用它来评估测试图像和标签!
训练然后预测
以下是你训练时看到的。
这是预测的结果。
这里的准确性要好得多,我们在检测正确的图像时有 99.42%的准确性。
PyTorch
PyTorch 顾名思义,就是 Torch 框架的 Python 版本。Torch 最初是用 C 开发的,有一个使用 Lua 编程语言的包装器。PyTorch 主要是由脸书的人工智能研究小组开发的,而是用 Python 包装了 Torch 二进制文件。
PyTorch 的一个关键特性是能够使用动态计算图修改现有的神经网络,而不必从头开始重建。PyTorch 将其描述为使用和重放录音机,它的灵感来自其他作品,如亲笔签名和 Chainer 。
在实现简单的神经网络的过程中,我没有机会正确地使用这个特性,但这似乎是一个建立神经网络的有趣方法,我想在以后进行更多的探索。
让我们看看 PyTorch 如何为我们的简单神经网络工作。
设置参数并加载数据集
import torch
import argparse
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.autograd import Variable
# parameters
inputs, hiddens, outputs = 784, 200, 10
learning_rate = 0.01
epochs = 50
batch_size = 20
transformation = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.1307,), (0.3081,))])
train_dataset = datasets.MNIST('mnist/',train=True,transform=transformation, download=False)
train_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)
test_dataset = datasets.MNIST('mnist/',train=False,transform=transformation, download=False)
test_loader = torch.utils.data.DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False)
加载数据集需要几个步骤,但它们相当简单。值得注意的是,变换的平均值为 0.1307,标准差为 0.3081,这是 MNIST 数据集的平均值和标准差。
定义神经网络
class mlp(nn.Module):
def __init__(self):
super(MLP, self).__init__()
self.sigmoid = nn.Sigmoid()
self.hidden_layer = nn.Linear(inputs, hiddens)
self.output_layer = nn.Linear(hiddens, outputs)
def forward(self, x):
out = self.sigmoid(self.hidden_layer(x))
out = self.sigmoid(self.output_layer(out))
return out
def name(self):
return "mlp"
定义神经网络很简单。我们在类中定义了一些方法,sigmoid
是nn.Sigmoid
,hidden_layer
和output_layer
是适当大小的线性层。
然后,forward
方法将输入x
传递给隐藏层,然后传递给sigmoid
激活函数。之后,它进入输出层,并在返回输出之前再次调用sigmoid
激活函数。
定义列车功能
def train():
model = mlp()
loss = nn.MSELoss(size_average=False)
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
for epoch in range(epochs):
avg_error = 0
for i, (images, labels) in enumerate(train_loader):
images = Variable(images.view(-1, inputs))
# Convert class label to one hot vector
one_hot = torch.FloatTensor(labels.size(0), 10).zero_()
target = one_hot.scatter_(1, labels.view((labels.size(0),1)), 1)
target = Variable(target)
# Compute loss and gradient
optimizer.zero_grad()
out = model(images)
error = loss(out, target)
error.backward()
# Apply gradient
optimizer.step()
avg_error += error.data[0]
avg_error /= train_loader.dataset.train_data.shape[0]
print ('Epoch [%d/%d], error: %.4f' %(epoch+1, epochs, avg_error))
# Save model to file
torch.save(model.state_dict(), 'model.pkl')
与其他实现一样,我们首先创建神经网络模型、误差函数loss
(我们将其定义为均方误差损失函数)以及 Adam 优化器。
我们照常运行 50 个时期的训练。因为训练标签的格式不正确,所以我们需要将其转换为一个热点向量,target
。然后,我们使用loss
函数计算误差,将实际输出值和目标值传递给它,然后对其应用反向传播。
最后,我们在结束训练之前保存模型。有几种方法可以保存 PyTorch 模型。更通用的 Python 方式是将其保存为 pickle 文件,扩展名为.pkl
。这是我在这个实现中使用的。另一种方法是使用 PyTorch 自己的序列化机制,它保存到一个扩展名为.pth
的文件中。
定义预测函数
def predict():
model = mlp()
model.load_state_dict(torch.load('model.pkl'))
correct, total = 0, 0
for images, labels in test_loader:
images = Variable(images.view(-1, inputs))
out = model(images)
_, predicted = torch.max(out.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum()
print('accuracy: %0.2f %%' % (100.0 * correct / total))
预测比训练简单。这里我们需要首先创建一个神经网络,并用保存的状态加载它,以重现训练好的模型。然后使用训练好的模型预测输出,然后使用标签检查它是否正确。最后,我们将所有正确预测的值加起来,并得到准确率的百分比。
训练然后预测
这是结果。
正如你所看到的,网络不能以相同的学习速率在 50 个时期内完全收敛。这里的预测准确率相当差,只有 95.17%。另一方面,当我切换到使用 SGD 优化器时,准确率提高到了 98.29%。
带有胶子的 MXNet
MXNet 是 Apache 基金会的一个项目,目前正在 Apache 中孵化。它支持多种语言,并得到了许多大型行业参与者的支持,主要包括亚马逊和微软。
亚马逊选择 MXNet 作为深度学习框架的首选,因为它声称 MXNet 比其他框架更好地扩展和运行。MXNet 模型是可移植的,也可以部署在设备上。2017 年 10 月,亚马逊和微软为 MXNet 推出了一个名为 Gluon 的新界面,以使深度学习更容易。
胶子相对容易使用,从我的角度来看,建立我们简单的神经网络看起来也差不多。诚然,我可能还没有使用它的最佳能力。
让我们看看它是如何工作的。
设置参数并加载数据集
import argparse
import numpy as np
import mxnet as mx
from mxnet import nd, autograd, gluon
from mxnet.gluon import nn
from mxnet.gluon.data import vision
# parameters
inputs, hiddens, outputs = 784, 200, 10
learning_rate = 0.01
epochs = 50
batch_size = 20
ctx = mx.cpu()
def transform(data, label):
return data.astype(np.float32)/255, label.astype(np.float32)
train_data = mx.gluon.data.DataLoader(vision.MNIST(train=True, transform=transform), batch_size, shuffle=True)
test_data = mx.gluon.data.DataLoader(vision.MNIST(train=False, transform=transform), batch_size, shuffle=False)
与其他框架不同,您必须更加明确您希望操作的上下文在哪里运行。在这种情况下,我只在 CPU 上运行,所以我创建了一个基于 CPU 的上下文ctx
。
加载数据集与其他框架没有太大区别。
定义神经网络
def mlp():
model = nn.Sequential()
with model.name_scope():
model.add(nn.Dense(hiddens, activation="sigmoid"))
model.add(nn.Dense(outputs, activation="sigmoid"))
dist = mx.init.Uniform(1/np.sqrt(float(inputs)))
model.collect_params().initialize(dist, ctx=ctx)
return model
定义神经网络相对简单,与 Keras 非常相似。我们简单地使用一个内置的模型,用适当的激活函数在它上面添加层,然后用从均匀分布中采样的随机值的上下文和权重初始化它。我在这里使用均匀分布是为了与早期的实现保持一致。我尝试了其他的发行版,但是结果有些相同,所以至少在这篇文章中我坚持使用这个发行版。
定义列车功能
def train():
model = mlp()
loss = gluon.loss.L2Loss()
optimizer = gluon.Trainer(model.collect_params(), "adam", {"learning_rate": learning_rate})
for e in range(epochs):
cumulative_error = 0
for i, (data, labels) in enumerate(train_data):
data = data.as_in_context(ctx).reshape((-1, inputs))
labels = nd.one_hot(labels, 10, 1, 0).as_in_context(ctx)
with autograd.record():
output = model(data)
error = loss(output, labels)
error.backward()
optimizer.step(data.shape[0])
cumulative_error += nd.sum(error).asscalar()
print("Epoch [%d/%d]: error: %.4f" % (e+1, epochs, cumulative_error/len(train_data)))
model.save_params("mxnet.model")
为了训练模型,我们首先用我们的mlp
函数创建它。我们使用L2Loss
定义一个误差函数loss
,它本质上是一个均方误差函数。
我们还定义了一个优化器(在 MXNet 中称为Trainer
),它使用 Adam 优化器算法。
接下来,我们枚举训练数据集,并将其整形为一个独热 n 数组。我们将训练数据集传递给经过训练的模型,以获得输出。输出和标签被传递给错误函数。
训练结束后,我们保存网络模型。MXNet 允许我们用简单的save_params
方法保存参数。对文件名没有太大的要求,所以我们可以使用任何我们喜欢的名字。
定义预测函数
def predict():
model = mlp()
model.load_params("mxnet.model", ctx)
acc = mx.metric.Accuracy()
for i, (data, label) in enumerate(test_data):
data = data.as_in_context(ctx).reshape((-1, inputs))
label = label.as_in_context(ctx)
output = model(data)
predictions = nd.argmax(output, axis=1)
acc.update(preds=predictions, labels=label)
print("accuracy: %.2f %%" % (acc.get()[1] * 100))
predict
函数通过从我们之前保存的文件中加载它来重新创建我们的训练模型。我们重塑测试数据集中的数据,并将其传递给已加载的训练模型,然后我们将预测作为输出。然后使用标签,我们发现预测的准确性。
训练然后预测
下面是使用 MXNet 框架和 Gluon 进行预测的结果。
准确率为 97.49%,与其他框架相当。
一些想法
显然这个帖子没有所有的深度学习框架。这更像是在我探索各种框架时,漫无边际地浏览了几个激发我想象力的选定框架。我错过了很多流行的,包括 Caffe 和 Caffe2,CNTK,Theano,Torch,Sonnet 等等。
我也没有做任何比较——这不是我的目的,任何比较都需要对这些框架有更深入的理解,也需要更多的时间。从某种意义上说,由于所有这些框架都在增长(当我在过去几周写这篇文章时,TensorFlow 连续发布了 1.7 和 1.8!)并且改变任何比较将会很快变得不准确。相反,我的目的是弄清楚实际编写深度学习软件有多容易,以及这些框架能在多大程度上帮助我做到这一点。
当我使用这些框架时,我意识到就目标而言,它们基本上是相同的。在每个框架中,目标总是有一个简单的方法来加载数据集,定义模型,训练模型,然后使用它来预测结果。实现的方式可能因框架而异,潜在的哲学可能不同,但目标是相同的。
从某种意义上说,它非常类似于我过去 20 年一直使用的所有 web 框架。虽然这些年来已经创建了令人惊叹的 web 应用程序,但是 web 框架基本上以相同的方式工作,具有相同的视图、控制器和服务,并且使用 HTTP。
毫无疑问,我把一切都过于简单化了,但在某种意义上,我同时也感到安慰。
源代码
您可以在这里找到所有源代码:
https://github.com/sausheong/pynn
使用开放堆栈构建语音识别
原文:https://towardsdatascience.com/building-speech-recognition-using-open-stack-945631969875?source=collection_archive---------2-----------------------
语音识别是新的用户界面,将带来我们与应用程序和机器交互方式的范式转变。说“关掉微波炉”,“订购我的每周用品”比使用触摸和点击界面以及(重新)学习应用程序界面要容易得多。事实上,语音是人类开发的原始通信协议。我们并没有进化到通过点击苹果/三星设备来交流。
我最近实现了一个语音识别系统。我对这个领域缺乏好的和简单的博客/帖子感到非常沮丧。希望这篇文章能消除人们的疑虑,引导试图首次创建语音识别系统的人朝着正确的方向前进。
首先,你创建自动语音识别系统的动机是什么?我可以想到一些创建自己的 ASR 的情况:
- 您的应用程序有一个语音识别用例,主要用于零/低带宽环境。因此,将 ASR 作为您的应用程序的一部分供离线使用是有意义的。
- 您所在的行业受到监管,如医疗或金融行业,个人身份信息不能发送到苹果/谷歌/微软服务器进行转录。
- 你想做一个 ASR 系统,在小词汇量上转录非母语外国口音。
在大多数其他情况下,将你的应用程序与苹果/谷歌/微软现有的语音 API 集成是完全有意义的。(注意,亚马逊 Alexa 不是一种语音转录技术)毕竟,这些科技巨头可以在庞大的语料库上训练他们的语音模型,你可以期待他们的转录中真的很低的 WER(单词错误率)。
我试过苹果的 ASR speech kit,还不错。我没有尝试过谷歌,但尝试过必应语音 API,对它的转录质量印象深刻。
好吧,如果谷歌/微软/苹果的语音 API 不能满足你的需求,那么你应该自己开发。
在这篇文章中,我将回顾使用传统的基于 GMM/DNN-HMM 模型的语音识别堆栈。高斯混合模型(GMM)/深度神经网络(DNN)用于模拟语音中的音素。音素是语音的原子单位,英语中大约有 40 个音素。隐马尔可夫模型(HMM)用于基于音素序列生成单词。ASR 的最新技术状态是使用递归神经网络实现的,其中通过使用允许预测字符级转录的目标函数来丢弃音素:连接主义者时间分类 (CTC)。
以下是开源 ASR 的主要竞争者:
- 卡尔迪
- CMU 狮身人面像
还有其他竞争者,如 HTK、Julius、ISIP,但我没有把他们包括在我的分析中,原因有很多->不是严格的开源,不容易实现,转录质量差等等。
易于实施
CMU 斯芬克斯轻而易举地击败了卡尔迪。CMU·斯芬克斯的教程很容易理解。另一方面,我发现 Kaldi 的实现又密集又困难。最初,我甚至很难在我的机器上实现一个简单的数字识别设置。有了 CMU·斯芬克斯,我在阅读的几个小时内就准备好了。
支持移动设备
CMU 狮身人面像再次击败了卡尔迪。CMU Sphinx 拥有易于实现的 iOS 和 Android SDK(pocket Sphinx)。卡尔迪实际上没有。原因是 Kaldi 创建了大约 5–7G 的巨大 FST 模型文件,这些文件在实时搜索和查询以生成转录时计算量非常大。
转录质量
卡尔迪打败了 CMU·斯芬克斯,这就是我坚持使用卡尔迪的原因。对于我的应用用例的一小部分词汇来说,卡尔迪一直胜过 CMU·斯芬克斯。
我知道这是一篇很长的文章,但是希望这篇文章能为你选择合适的栈来构建你自己的 ASR 系统提供一些指导。
用 Spark 打造 Spotify 的“发现周刊”
原文:https://towardsdatascience.com/building-spotifys-discover-weekly-with-spark-4370d5d0df2f?source=collection_archive---------1-----------------------
基于协同过滤算法的音频推荐系统的 MLlib & PySpark 实现
今天是我在 NBC Universal 实习的第三天,我受到鼓舞要实现一个新的目标:在今年夏天离开30 Rock&1221 Campus(我将在那里工作大部分时间)之前掌握 Spark 。
作为领先的媒体和娱乐行业,我们公司拥有数百 Pb 来自全国各地和通过国际有线电视的电视广播数据。虽然这听起来令人惊讶和不知所措,但毫无疑问,现在越来越多的公司依靠推荐系统的力量来满足各种个人品味和需求,从而提高客户的满意度和忠诚度。
在娱乐行业,Spotify 等音乐科技巨头将推荐引擎作为其产品的重要组成部分。涉及用户兴趣的模式检测和分析在提供个性化推荐方面发挥了关键作用。这是因为给用户体验添加另一个维度有助于推荐系统在识别我们不知道自己会喜欢的曲目方面做得非常出色。
用什么算法?
让我从我们可以用来构建音频推荐系统的两种主要方法开始。第一个是 内容过滤 ,利用产品和用户的已知信息进行推荐。使用这种方法,我们根据产品(例如电影信息、价格信息和产品描述)和用户(例如人口统计和问卷信息)创建档案。
实施内容过滤的一个广为人知的例子是在线电台 Pandora 的音乐基因组计划。在这里,一个专家根据上百个特征给一首歌打分。用户还提供关于他/她的音乐偏好的信息。基于这两个源的配对提出建议。
潘多拉使用内容过滤,Spotify 使用 协同过滤 用于他们的发现周刊推荐系统。后一种技术使用先前用户的输入/行为来做出未来的推荐。我们忽略任何先验的用户或对象信息。我们使用相似用户的评分来预测评分。
进一步理解 Spotify 技术的一种方式是通过一种基于邻居的方法,在这种方法中,你(1)首先根据我们的重叠评分的一致程度来定义你和其他用户之间的相似性评分,然后(2)让其他人根据这些评分来投票决定你喜欢什么。
与内容过滤相比,协作过滤的一个主要吸引力在于其不受领域限制的方法,这意味着它不需要知道什么被评级,只需要知道谁对什么进行了评级,以及评级是什么。
注意两种方法并不互相排斥。内容信息也可以内置到协同过滤系统中,提高性能。现在我们已经了解了算法是如何工作的,让我们来了解一下我们将用来构建推荐系统的技术— Spark。
为什么是火花?
Apache Spark 是一个快速通用的集群计算系统。随着行业开发出更具创意、基于客户的产品和服务,对机器学习算法的需求变得更加重要,以帮助开发个性化、推荐和预测性见解。
像 R 和 Python 这样的工具长期以来被用来执行各种机器学习活动。然而,随着信息的大量增长,计算效率对于帮助解决高时间和空间复杂性变得非常关键。
此外,Spark 为数据工程师和数据科学家提供了一个强大的统一引擎,它不仅速度快(比 Hadoop 快 100 倍,用于大规模数据处理)且易于使用,而且简单、高度可扩展,并可与其他工具有效集成,如 R、SQL、Python、Scala 和 Java。
Source: Infoworld Analytics
我最喜欢 Spark 的一点是,它能够帮助我们数据科学家解决高度复杂的机器学习问题,涉及图形计算、流和以互动方式在更大规模上进行实时互动查询处理。
使用 PySpark 的逐步实现
我们现在将使用 AudioScribbler 数据集实现协同过滤算法来构建音频推荐系统(在这里下载压缩档案)。
导入库和数据集
一旦数据集中有了三个文件,就可以启动spark-shell
。构建模型的第一步是理解您的数据,并将其解析成对 Spark 中的分析有用的形式。让我们从导入库和初始化您的SparkContext
开始用 PySpark 编码。
import findspark
import pyspark
from pyspark import SparkContext
from pyspark import SparkConf
from pyspark.mllib import recommendation
from pyspark.mllib.recommendation import ***'''initialize spark in VM'''**findspark.init('/usr/local/bin/spark-1.3.1-bin-hadoop2.6/')
try:
sc=SparkContext()
except:
None
接下来,将每个文件存储到一个变量中。 user_artist_data.txt 表示一个播放列表数据集,其中文件的每一行都包含一个用户 ID、一个艺术家 ID 和一个播放次数,用空格分隔。 artist_data.txt 包含与艺术家姓名相关联的不透明数字 id。 artist_alias.txt 将可能拼写错误或不标准的艺术家 ID 映射到艺术家规范名称的 ID。它每行包含两个 id,用制表符分隔。
**'''define variables'''**rawUserArtistData = sc.textFile("vagrant/user_artist_data.txt")
rawArtistData = sc.textFile("vagrant/artist_data.txt")
rawArtistAlias = sc.textFile("vagrant/artist_alias.txt")
预处理数据
我们希望获得原始艺术家数据的列表,每个 ID 和名称都存储在元组中。让我们使用 artist_data.txt 来创建这个列表。
def pairsplit(singlePair):
splitPair = singlePair.rsplit('\t')
if len(splitPair) != 2:
return []
else:
try:
return [(int(splitPair[0]), splitPair[1])]
except:
return []
artistByID = dict(rawArtistData.flatMap(lambda x: pairsplit(x)).collect())
我们还使用 artist_alias.txt 将“坏的”艺术家 id 映射到“好的”艺术家 id,而不仅仅是将其用作艺术家 id 的原始数据对。我们使用下面的代码将坏的 id 转换成好的 id。例如,第一个条目将 ID 6803336 映射到 1000010,这意味着它将“Aerosmith(不插电)”映射到“Aerosmith”。
def aliaslookup(alias):
splitPair = alias.rsplit('\t')
if len(splitPair) != 2:
return []
else:
try:
return [(int(splitPair[0]), int(splitPair[1]))]
except:
return []
artistAlias = rawArtistAlias.flatMap(lambda x: aliaslookup(x)).collectAsMap()
建立一个模型
然后,我们创建一个查找函数,将数据转换成评级对象。请注意,任何潜在的 MLlib 模型都需要产品作为客观的衡量标准。在我们的模型中,产品是艺术家。因此,我们将使用 user_artist_data.txt 来实现我们的火车数据。
def ratinglookup(x):
userID, artistID, count = map(lambda line: int(line), x.split())
finalArtistID = bArtistAlias.value.get(artistID)
if finalArtistID is None:
finalArtistID = artistID
return Rating(userID, finalArtistID, count)trainData = rawUserArtistData.map(lambda x: ratinglookup(x))
trainData.cache()
我们还为artistAlias
创建了一个名为bArtistAlias
的广播变量。这使得 Spark 只为集群中的每个执行器发送并在内存中保存一个副本。当有数千个任务,并且许多任务在每个执行器上并行执行时,这可以节省大量的网络流量和内存。
bArtistAlias = sc.broadcast(artistAlias)
最后,我们使用协同过滤算法建立我们的模型,如下所示。该操作可能需要几分钟或更长时间,具体取决于您的群集。我花了大约 15 分钟来运行这个模型。
**'''build model'''**model = ALS.trainImplicit(trainData, 10, 5)
我们应该首先通过检查一个用户、他或她的戏剧以及对该用户的推荐,来看看艺术家的推荐是否有任何直观的意义。以用户2093760
为例。提取这个用户听过的艺术家的 id 并打印他们的名字。这意味着在输入中搜索该用户的艺术家 id,然后根据这些 id 过滤艺术家集,以便您可以按顺序收集和打印姓名:
**'''test artist'''**spotcheckingID = 2093760
bArtistByID = sc.broadcast(artistByID)rawArtistsForUser = (trainData
.filter(lambda x: x.user == spotcheckingID)
.map(lambda x: bArtistByID.value.get(x.product))
.collect())
print(rawArtistsForUser)
获得您的推荐
我想根据我的数据模型选出前 10 首歌曲:
**'''output recommendations'''**recommendations = map(lambda x: artistByID.get(x.product), model.call("recommendProducts", spotcheckingID, **10**))
print(recommendations)
在我的 Spark VM 集群上运行这个程序,我得到了以下输出:
- Jay Z、50 Cent、Snoop Dogg、2Pac、Nas、Kanye West、Outkast、Eminem、德瑞医生和卢达克里斯。
A screenshot of my model output. Note that your top 10 listed songs can be in random order.
是的,这些艺术家看起来像说唱歌手的混合体!请记住,这组艺术家在 2005 年非常受欢迎,这是这个数据集被提取的年份。
**可能的下一步?**我们可以使用另一组可用的歌曲数据提取一组推荐的歌曲,并根据我们的顶级艺术家对它们进行查询。
希望你喜欢和快乐的黑客!
编码参考
你可以在这里找到我的原始代码:https://github.com/moorissa/audiorecommender
Moorissa 是一名研究生,目前在哥伦比亚大学学习机器学习,希望有一天她可以利用这些技能让世界变得更好,一次一天。
使用 USB 摄像头和无线连接的 Raspberry Pi 构建监控系统
原文:https://towardsdatascience.com/building-surveillance-system-using-usb-camera-and-wireless-connected-raspberry-pi-1038e41f8a56?source=collection_archive---------9-----------------------
本教程讨论使用插入 Raspberry Pi (RPi)的 USB 摄像头构建监控系统,该摄像头通过无线接口连接到 PC。PyGame 用于访问摄像机和捕捉存储在 RPisd 卡中的图像。为场景创建背景模型,以发现默认状态的变化。一个连接到 GPIO 引脚的简单电路点亮一个 led 来指示这种状态。
Cover image by Ahmed Fawzy Gad. Building Surveillance System using USB Camera and Wireless-Connected Raspberry Pi
该教程包含以下步骤:
- 使用无线接口将 RPi 连接到 PC。
- 将 USB 摄像头连接到 RPi。
- 使用 PyGame 捕捉图像。
- 建立背景模型。
- 检测背景模型的变化。
- 构建一个简单的电路,当发生变化时点亮 led。
本教程假设读者有一台连接到无线网络的 PC 和一台使用以太网接口连接到交换机的 RPi。要做这样的工作,请阅读题为“构建一个运行在 Raspberry Pi 上的图像分类器”的教程,该教程可从以下链接获得:
https://www . LinkedIn . com/pulse/building-image-classifier-running-raspberry-pi-Ahmed-gad
您应该能够使用“Advanced IP Scanner”等软件知道设备的 IP 地址,并熟悉使用 MobaXterm 软件建立 SSH 连接。之后,我们就可以开始讨论上面的每一个步骤了。
1.使用无线接口将 RPi 连接到 PC
在之前的教程“构建运行在 Raspberry Pi 上的图像分类器”中,我们构建了一个连接了三个设备的网络,这三个设备分别是 RPi、交换机和 PC。RPI 使用以太网接口连接到交换机,但 PC 使用无线接口连接到交换机。在本教程中,我们将通过使用 RPi 的无线接口连接到交换机来修改此类网络。这使得网络完全无线连接,避免了有线的限制。
RPi 的无线接口需要配置才能使用。因此,我们仍将使用通过以太网接口建立的连接来配置无线接口。通过在交换机中使用 DHCP,RPi 以太网接口将获得一个 IPv4 地址。这样的地址可以用于建立安全外壳(SSH)连接。关于建立连接的更多细节,可以参考前面的教程。
在使用 MobaXterm 创建的 SSH 会话中,我们可以使用终端命令或 Raspbian 操作系统的 GUI 开始配置无线接口。两种方法都很简单。
使用终端命令,我们将首先扫描可用的无线网络,找到它们的服务集标识符(SSIDs)。这是使用以下命令完成的:
**pi@raspberrypi:~ $ sudo iwlist wlan0 scan**
下图给出了该命令输出的前几行。目标无线网络的 SSID 为“ TEData_864A ”。请注意,您不必使用交换机将 PC 连接到 RPi。使用智能手机,我们可以创建一个接入点来连接它们。
知道目标网络的 SSID 后,我们可以使用它来配置无线接口。这种配置存在于一个文件中,可以使用以下命令访问该文件:
**pi@raspberrypi:~ $ sudo nano /etc/wpa_supplicant/wpa_supplicant.conf**
文件将在终端中打开。使用向下箭头,返回到文件的末尾,写入网络配置。这是通过按如下方式写入网络的 SSID 和密码实现的:
**network={
ssid=”TEData_864A”
psk=”YOUR_NETWOK_PASSWORD”
}**
之后,按 CTRL+X 退出文件,然后按 Y 保存更改。对于我的例子,我配置了两个网络,因此文件内容有两个配置的网络,如下图所示。
您可能需要将无线接口的状态从“打开”更改为“关闭”,然后再次将其更改为“打开”,以应用此类配置。这是使用这两个命令完成的:
**pi@raspberry:~ $ sudo ifdown wlan0
pi@raspberry:~ $ sudo ifup wlan0**
要检查无线接口配置是否正确,输入“ ifconfig 命令检索接口的配置。
**pi@raspberry:~ $ ifconfig**
根据此命令的输出,无线接口的 IPv4 地址为 192.168.1.8。这就是如何使用终端命令配置无线连接。
我们可以使用操作系统的 GUI 做同样的事情,可以使用 startlxde 终端命令访问该 GUI。GUI 打开后,在操作系统栏的右侧会出现一个网络连接图标。点击它将打开一个可用无线网络的菜单,如下图所示。单击任何一项都会打开一个窗口,允许您输入密码。通过输入 SSID 为" TEData_864A 的网络密码,并输入" ifconfig "命令,结果将与上图所示相同。
此时,我们已经将 PC 和 RPi 无线连接到交换机。当前网络如下图所示。我们现在可以删除以太网连接,只使用 RPi 和交换机之间的无线连接。
2.将 USB 摄像头连接到 RPi
RPi 有自己的摄像头模块可以使用。与其买这个模块,对很多人来说可能很贵,我们可以只使用一个 USB 摄像头,它可能在任何地方都可以以更低的成本买到。这种相机的配置非常简单。只需将 USB 摄像头连接到 RPi 的一个 USB 端口。之后,我们可以通过使用“fswebcam”包捕捉图像来检查相机是否工作正常。首先,我们需要使用以下命令安装该软件包:
**pi@raspberry:~ $ sudo apt-get install fswebcam**
之后,我们可以用它来捕捉图像。一个非常基本的方法如下:
**pi@raspberry:~ $ sudo fswebcam test_image.jpg**
这将访问相机,捕捉图像,并以“test_image.jpg”的名称将其保存到 SD 卡的当前目录中。执行命令后的输出如下图所示。
以下是捕捉到的图像:
3.使用 PyGame 捕捉图像
“ fswebcam ”包对于快速测试相机是否工作正常很有用。在确保它运行良好之后,我们可以开始构建一个 Python 脚本,使用 PyGame 库访问相机以连续捕捉图像。下面的代码使用 PyGame 来捕捉一个图像,打开一个窗口来显示这个图像,最后保存这个图像。
**import** pygame
**import** pygame.camera
*# Captured image dimensions. It should be less than or equal to the maximum dimensions acceptable by the camera.* width = 320
height = 240
*# Initializing PyGame and the camera.* pygame.init()
pygame.camera.init()
*# Specifying the camera to be used for capturing images. If there is a single camera, then it have the index 0.* cam = pygame.camera.Camera(**"/dev/video0"**,(width,height))
*# Preparing a resizable window of the specified size for displaying the captured images.* window = pygame.display.set_mode((width,height),pygame.RESIZABLE)
*# Starting the camera for capturing images.* cam.start()
*# Capturing an image.* image = cam.get_image()
*# Stopping the camera.* cam.stop()
*# Displaying the image on the window starting from the top-left corner.* window.blit(image,(0,0))
*# Refreshing the window.* pygame.display.update()
*# Saving the captured image.* pygame.image.save(window,**'PyGame_image.jpg'**)
假设上面的代码保存在一个名为“ im_cap.py ”的 Python 文件中。要执行这样的代码,我们可以从终端发出以下命令:
**pi@raspberry:~ $ python3 im_cam.py**
这是执行该文件后显示的窗口。
我们可以修改前面的代码来捕获多个图像。例如,我们可以使用一个循环的来捕捉一些先前指定的图像。我们也可以使用一个 while 循环,它并不局限于一些图像。下面是使用 for 循环捕获 2000 张图像的修改代码。
**import** pygame
**import** pygame.camera
*# Captured image dimensions. It should be less than or equal to the maximum dimensions acceptable by the camera.* width = 320
height = 240
*# Initializing PyGame and the camera.* pygame.init()
pygame.camera.init()
*# Specifying the camera to be used for capturing images. If there is a single camera, then it has the index 0.* cam = pygame.camera.Camera(**"/dev/video0"**, (width, height))
*# Preparing a resizable window of the specified size for displaying the captured images.* window = pygame.display.set_mode((width, height), pygame.RESIZABLE)
*# Starting the camera for capturing images.* cam.start()
**for** im_num **in** range(0, 2000):
**print**(**"Image : "**, im_num)
*# Capturing an image.* image = cam.get_image()
*# Displaying the image on the window starting from the top-left corner.* window.blit(image, (0, 0))
*# Refreshing the window.* pygame.display.update()
*# Saving the captured image.* pygame.image.save(window, **'./pygame_images/image_'** + str(im_num) + **'.jpg'**)
*# Stopping the camera.* cam.stop()
这里有 8 张捕捉到的图像。请注意,相机的位置发生了一点变化。
4.构建背景模型
到目前为止,我们成功地构建了一个简单的监控系统,在该系统中,摄像机捕获图像并保存在 RPi 的 SD 卡中。我们可以扩展它来自动检测场景的变化。这是通过为场景建立背景模型来实现的。对这种模型的任何改变都将表明一种改变。例如,如果有人正在穿过场景,将导致背景发生变化。
背景模型可以简单地通过将多个捕获的图像平均到其中没有任何对象的场景背景来创建。因为我们对颜色信息感兴趣,所以图像将被转换成二进制。下面是用于构建背景模型的 Python 代码。
**import** skimage.io
**import** os
**import** numpy
dir_files = os.listdir(**'./pygame_images/'**)bg_image = skimage.io.imread(fname=dir_files[0], as_grey=True)
**for** k **in** range(1, len(dir_files)):
fname = dir_files[k]
im = skimage.io.imread(fname=fname, as_grey=True)
bg_image = bg_image + im
bg_image = bg_image/(len(dir_files))
bg_image_bin = bg_image > 0.5
skimage.io.imsave(fname=**'bg_model.jpg'**, arr=bg_image)
skimage.io.imsave(fname=**'bg_model_bin.jpg'**, arr=bg_image_bin*255)
这是平均 500 张图像后的背景模型,既有灰度也有二值。
5.检测背景模型的变化
在建立背景模型之后,我们可以测试一张新的图像来检查背景是否有变化。只需将新图像转换成二进制即可。然后比较两幅图像中白色像素的数量。如果该数字超过给定的阈值,这表明背景发生了变化。阈值随着场景的不同而变化。下面是用于测试新图像的代码。
bg_num_ones = numpy.sum(bg_image_bin)test = skimage.io.imread(fname=**"./pygame_images/image_800.jpg"**,
as_grey=True)
test_bin = test > 0.5
test_num_ones = numpy.sum(test_bin)
**print**(**"Num 1s in BG :"**, bg_num_ones)
**print**(**"Num 1s in Test :"**, test_num_ones)
**if**(abs(test_num_ones-bg_num_ones) < 5000):
**print**(**"Change."**)
这是一个彩色、灰度和二进制的测试图像,由于场景中出现了一个物体(人),因此背景发生了变化。
6.构建一个简单的电路,当发生变化时点亮 Led
作为对背景模型变化的指示,我们可以建立一个简单的电路,当发生变化时,led 就会发光。该电路将连接到 RPi 的 GPIO(通用输入输出)箱。该电路需要以下元件:
- 一块试验板。
- 一个 led。
- 一个电阻器(大于或等于 100 欧姆)。我使用 178.8 欧姆的电阻。
- 两根公/公跳线。
- 两根公/母跳线。
建议在将电路连接到 GPIO 引脚之前对其进行测试。这是因为如果电阻值选择不当,不仅会烧坏 led,还会损坏 GPIO 引脚。为了进行测试,我们需要一个电池为试验板供电。这是正确连接所有组件后的电路。
之后,我们可以取下电池,将试验板连接到 RPi 的 GPIO 引脚。根据 GPIO 引脚的试验板编号,接地连接到 20 号箱,高压连接到 22 号输出箱。下图说明了试验板和 RPi 之间的连接。RPi 还连接到充电器和 USB 摄像头。
使用下面给出的 Python 脚本控制输出 GPIO bin。其默认状态为低电平,表示 led 关闭。当背景发生变化时,状态将变为 HIGH,表示 led 打开。led 保持亮起 0.1 秒,然后其状态恢复为熄灭。当另一个输入图像不同于背景时,led 将重新打开 0.1 秒。
**import** time
**import** RPi.GPIO
**import** skimage.io
**import** numpy
**import** os
**import** pygame.camera
**import** pygame
*#####GPIO#####
# Initializing the GPIO pins. The numbering using is board.* RPi.GPIO.setmode(RPi.GPIO.BOARD)
*# Configuring the GPIO bin number 22 to be an output bin.* RPi.GPIO.setup(22, RPi.GPIO.OUT)
*#####PyGame#####
# Initializing PyGame and the camera.* pygame.init()
pygame.camera.init()
*# Captured image dimensions. It should be less than or equal to the maximum dimensions acceptable by the camera.* width = 320
height = 240
*# Preparing a resizable window of the specified size for displaying the captured images.* window = pygame.display.set_mode((width, height), pygame.RESIZABLE)
*# Specifying the camera source and the image dimensions.* cam = pygame.camera.Camera(**"/dev/video0"**,(width,height))
cam.start()
*#####Background Model#####
# Reading the background model.* bg_image = skimage.io.imread(fname=**'bg_model_bin.jpg'**, as_grey=True)
bg_image_bin = bg_image > 0.5
bg_num_ones = numpy.sum(bg_image_bin)
im_dir = **'/home/pi/pygame_images/'
for** im_num **in** range(0, 2000):
**print**(**"Image : "**, im_num)
im = cam.get_image()
*# Displaying the image on the window starting from the top-left corner.* window.blit(im, (0, 0))
*# Refreshing the window.* pygame.display.update()
pygame.image.save(window, im_dir+**'image'**+str(im_num)+**'.jpg'**)
im = pygame.surfarray.array3d(window)
test_bin = im > 0.5
test_num_ones = numpy.sum(test_bin)
*# Checking if there is a change in the test image.* **if** (abs(test_num_ones - bg_num_ones) < 5000):
**print**(**"Change."**)
**try**:
RPi.GPIO.output(22, RPi.GPIO.HIGH)
time.sleep(0.1)
RPi.GPIO.output(22, RPi.GPIO.LOW)
**except** KeyboardInterrupt: *# CTRL+C* **print**(**"Keyboard Interrupt."**)
**except**:
**print**(**"Error occurred."**)
*# Stopping the camera.* cam.stop()
*# cleanup all GPIO pins.* **print**(**"Clean Up GPIO."**)
RPi.GPIO.cleanup()
下图显示了由于人的存在而不同于背景图像的一个输入图像。因此,led 将打开 0.1 秒。
以下视频(https://youtu.be/WOUG-vjg3A4)显示了使用相机拍摄的多帧的 led 状态。根据所使用的阈值,当输入图像不同于背景模型时,led 被打开。
了解更多详情
Ahmed Fawzy Gad,《构建运行在 Raspberry Pi 上的图像分类器》,2018 年 9 月,https://www . LinkedIn . com/pulse/Building-Image-Classifier-Running-Raspberry-Pi-Ahmed-Gad
联系作者
- 电子邮件:【ahmed.f.gad@gmail.com
- 领英:https://linkedin.com/in/ahmedfgad/
- https://kdnuggets.com/author/ahmed-gad
- YouTube:http://youtube.com/AhmedGadFCIT
- 走向科学:https://towardsdatascience.com/@ahmedfgad
构建人工智能堆栈
原文:https://towardsdatascience.com/building-the-ai-stack-ad23ac90405f?source=collection_archive---------5-----------------------
随着机器学习的使用——特别是计算密集型深度学习技术——在研究和行业中蓬勃发展,构建机器学习堆栈的市场也出现了爆炸式增长。谷歌、亚马逊和微软等科技巨头发布旨在使 ML(机器学习)技术更容易开发并最终推动云销售的云产品,完美地说明了这一点。从数据准备(图像标记),到培训(模型优化),再到部署,这一趋势也在大量构建基础设施和工具的初创公司中得到了强调。
我在 Elaia 和大型云提供商那里看到的创业公司的 5 个痛点:
- 效率低下的 ML 团队机器学习科学家和工程师在管道和低价值任务上花费了太多时间,例如建立他们的基础设施和工具,围绕数据管道进行黑客攻击,以及建立基本的自动化,从而推迟了研发项目。
- 低硬件利用率计算基础设施未得到充分利用,导致成本不理想和/或 ML 团队争夺稀缺资源
- 技术不确定性随着新的硬件产品(谷歌 TPUs,最新的英伟达芯片)和软件产品(谷歌 AutoML)的推出,决策者很难就 ML 基础设施做出长期决策。
- 技能和堆栈的异构性传统数据科学家和 IT 经理正在慢慢迁移到新技术(高级 ML 和深度学习),并需要与新一代深度学习本地科学家一起工作。
- 监管和隐私数据要么至关重要,需要限制安全性,而新出现的监管带来了额外的挑战(HIPAA、GDPR 等)
市场仍然不成熟,尽管技术基础已经具备,可以构建一个全面的产品,最终实现快速的 ML 开发和广泛的现实影响
在这类文章中,很难使用正确的词汇。AI,ML,深度学习都被误用了。在某些方面,自第一台计算机制造出来,人工智能栈就已经永远存在了。在这里,我将重点关注能够开发当前一代产品的产品,通常是计算和数据密集型机器学习模型。我戏称它为人工智能栈。
认为谷歌的战略和产品将深刻影响市场,并从上一代技术(即 Map Reduce 范式和 Hadoop 生态系统)中汲取灵感,我将提出两种未来堆栈可能的情况。
1)谷歌的战略正在推动人工智能基础设施和工具市场
谷歌的战略
谷歌的商业模式过度依赖广告收入,投资者已经多次指出这个事实。随着新平台的出现,语音(如虚拟助手)等界面被广泛采用,我们现在知道的搜索格式的数量将慢慢减少。为了弥补这一点,谷歌推出了许多其他产品,这些产品在历史上对底线的影响有限,直到最近。
人工智能领域似乎出现了两个战略机遇:
通过人工智能附加服务创造收入人工智能的崛起为谷歌创造了巨大的市场机会,谷歌在该领域、文化和内部基础设施方面拥有丰富的专业知识,可以快速开发和推出人工智能驱动的产品。
征服云市场虽然 AWS 仍然是云基础设施服务的市场领导者,拥有 30%以上的市场份额,但世界的云化并没有结束,这为新一代云产品留下了空间。在本文的其余部分,我们将重点关注谷歌为抓住这一机遇而部署的战略。
Cloud Prodiver Growth vs Market Share
谷歌已经在人工智能堆栈中构建了产品
虽然很容易认为谷歌正在影响任何市场,但它特别是在人工智能基础设施和工具市场。事实上,谷歌已经发布了不同层次的产品。机器学习框架 TensorFlow 是目前最受欢迎的。谷歌云是机器学习科学家最喜欢的云,在收入方面历史上与 AWS 相比相形见绌。
Google’s Products Cover the Stack. Some are open source software (Kubernetes, TensorFlow), some are Hosted services (ML Engine) and some hardware (TPU)
为了赢得云战争,谷歌使用了两个杠杆:
- 产品差异化:增值的人工智能基础设施产品和服务可能会赢得迫切需要获得坚实堆栈(自下而上采用)的人工智能开发人员,以及寻求支持建立其人工智能战略(自上而下采用)的领导层——在这方面,谷歌的品牌是一项重要资产。TensorFlow 等免费开源框架已经迅速普及,这使得谷歌 ML 引擎(一个高价的机器学习云平台)的营销变得更加容易。谷歌还发布了 Kubeflow,这是一个运行在 Kubernetes 之上的开源机器学习平台,可能为内部用户提供谷歌 ML 引擎的替代选择。
- **更低的切换成本:**更好的产品可能不足以说服客户,尤其是在企业生产环境中,迁移工作负载成本高昂,并且可能需要大量的软件重新设计。应用程序的容器化创造了降低转换成本的机会。谷歌赢得了与 Kubernetes 的战争,实施了其容器工作负载协调系统。这样一来,它还通过提高工作负载的可移植性显著降低了切换成本,既简化了云服务之间的切换,也简化了从内部部署到云产品的切换。
这对那些寻求了解人工智能栈未来的人来说很重要:谷歌正在为栈的各个层开发产品。TensorFlow 已经成为领先的(但不是唯一的)机器学习框架。谷歌 ML 引擎因其用户友好性而广受赞誉,尽管其高昂的价格可能会成为重度用户的阻碍。开源平台 Kubeflow 虽然还不成熟,但正在慢慢获得牵引力。
在堆栈的最底层,Kubernetes 在扩展到人工智能之外的容器工作负载编排领域获得了明确的优势。生产工作负载采用 Kubernetes 为构建整个 Kubernetes-native AI 生态系统创造了合适的基础。
Google Open Source Products Adoption
结论
谷歌战略的后果之一是,人工智能堆栈的每一层都得到服务,取得了各种各样但越来越大的成功,由谷歌维护的开源产品(尽管 Kubernetes 现在由云原生基金会维护)。
我想回答的问题是,专有机器学习产品是否会有空间,以及在哪里会有空间。
为了理解动态,我将使用 Hadoop 生态系统(第 2 部分)的类比,并尝试推断两个场景。
2)与 Hadoop 生态系统的类比(希望是合理的)
Hadoop 堆栈可以分解为基础设施、平台和工具,与 AI 堆栈非常相似。
这种类比至少有一些局限性:
- Hadoop 是专为 map reduce 范式构建的,用于处理超大规模数据集。另一方面,Kubernetes 是为通用工作负载编排而开发的。除了技术上的影响,这意味着 Kubernetes 将在一个更大的市场上被采用。作为一个副作用,一个公司可能会采用 Kubernetes 来编排其主网站的容器——然后青睐能够利用其现有 Kubernetes 安装的 ML 产品。
- 深度学习模型的开发和训练从根本上来说比 ETL 操作(Hadoop 生态系统的原始用例)更复杂。他们经常利用 GPU 计算,这产生了另一种技术差异,并要求更复杂的堆栈。
- Hadoop 的采用始于市场存在之时,但规模相当小——它始于少数客户,包括雅虎,维护大型 Hadoop 客户,并逐渐购买服务来帮助管理他们。点击此处了解 Hadoop 的历史。至于人工智能堆栈,在任何解决方案可用之前,大规模存在对机器学习平台的需求。目前的产品仍相对不成熟,但市场已经爆炸式增长。
从这个类比中我们能学到什么?
- Hadoop 生态系统围绕着一系列开源产品和工具。
- Hadoop 堆栈的业务模型主要由服务和企业支持及工具驱动,就像 Red Hat 一样。
从长远来看,AI 也会这样吗?市场会广泛采用 Kubernetes+Kubeflow 作为基础设施和机器学习平台吗,在这种情况下,其他玩家会转而为 Kubeflow 构建企业版、工具和服务吗?还是企业平台会有市场?
3)两种场景
在开始预测之前,让我回到市场上来。它可以大致分为三个角色:
- 小玩家和个人开发者喜欢简单性,但是简化了 IT 需求。他们是现有云产品的典型客户,如 Google ML Engine 或 AWS Sagemaker。
- 企业云用户同样也是现有产品的良好目标,尽管高级用户的特定需求也需要云提供商无法满足的定制服务。
- 企业内部部署目标目前在平台和工具方面严重不足。主要的不确定性就在于此,并证明了下面两种情况的合理性。
The AI Stack Broken down by segment — Major uncertainty lays in the on-premise segment
场景 1:相互竞争的开源和企业产品共存
由于对企业产品的需求已经存在,而开源产品还远未成熟,一些公司已经开始构建闭源产品。
Clusterone 和 RiseML 等公司以及其他几家公司就是这种情况。
如果开源产品不能很快成熟,对内部部署企业级产品的需求将推动它们的采用。开源可能会在第二波产品中赶上来。
**商业模式:**专有企业软件
**剩余机会:**因此,堆栈将保持相当分散的状态。这可能会使构建工具的主流产品变得更加困难。这些市场条件也可能有利于端到端的垂直机器学习平台。
场景 2:开源占主导地位,企业生态系统出现
现有的 Kubernetes 采用和 Kubeflow 的更快成熟可能会引发广泛的采用,以及对开源代码库贡献的良性循环。
这将为基于 Kubeflow 的企业级产品、服务和支持模型带来机遇,与 Cloudera 和 Hortonworks(现在的 Cloudera-Hortonworks)以及 MapR 的 Hadoop 生态系统产品非常相似。
**商业模式:**服务、支持和企业-Kubeflow
**剩余的机会:**围绕 Kubeflow 的栈的标准化将赋予公司在栈顶构建工具的特权,以及围绕 Kubeflow 的工具和应用的生态系统模型。
结论
预测堆栈将如何发展是一项棘手的工作。无论如何,记住这两种情况可以帮助决策者识别机会,并针对不断变化的市场条件进行对冲。
尽管栈的一些标准化将有益于那些构建应用程序和工具的人,但一个成熟的标准产品的出现还需要时间。可能有第三种方式,开源和闭源玩家在定义标准上合作,最大化他们成功的机会和最终用户的价值。
感谢 Louisa Mesnard 在撰写本文时给予的帮助。
免责声明:观点仅代表我个人。我是 Clusterone 的联合创始人,持有该公司的股份。
从 HBO 的硅谷建立热狗/非热狗分类器
原文:https://towardsdatascience.com/building-the-hotdog-not-hotdog-classifier-from-hbos-silicon-valley-c0cb2317711f?source=collection_archive---------4-----------------------
Photo by Fancycrave on Unsplash
自从我在 HBO 的硅谷看了由百搭应用开发者 Jian-Yang 创建的热狗/非热狗应用,我就想创建它。现在终于,我有了!但由于我缺乏应用程序开发技能,我只创建了应用程序将使用的机器学习分类器。尽管如此,创造这个应用程序的大脑还是很酷的。此外,这是一个非常酷的数据科学项目。所以,下面是我的经验。
注: 找到朱庇特笔记本 这里 。
“这不是魔法。是天赋和汗水。”吉尔福伊尔
没有数据学不了
任何数据科学或机器学习或深度学习或人工智能项目的第一步都是获取数据。你可以创建最复杂的算法,并在最疯狂的 GPU 或 TPU 上运行你的 ML 模型,但如果你的数据不够好,那么你将无法在 ML 任务上取得任何进展。所以,首先是获取数据。
ImageNet 来拯救我们了!
我用了 ImageNet 网站来获取数据。至于热狗,我搜索了“热狗”、“法兰克福香肠”和“辣热狗”。至于“不是热狗”部分,我搜索了“宠物”、“家具”、“人”和“食物”。选择这些照片的原因是,这些是人们在使用这种应用程序时最有可能拍摄的照片。
我使用了一个小脚本从 ImageNet 下载所有这些图像,并删除无效/损坏的图像。然后,我翻遍了所有的图片,手动删除了破碎的和不相关的图片。最后,我有 1822 张热狗的图片和 1822 张“不是热狗”的图片。
注意: 我有超过 3000 张“不是热狗”的图片,但我随机选择了其中的 1822 张,以平衡这两个类别。
现在,我有了创建这个分类器所需的所有数据。
让数据更好
下一步是让数据更好。首先,我编写了一个小脚本,将所有图像的大小调整为 299x299 分辨率,这样所有图像的大小都相同,我在加载这些图像时就不会遇到各种不兼容问题。
在目录中正确组织数据也很重要。我按照以下方式组织数据:
数据集— > (train — > (hotdog,nothotdog),测试— > (hotdog,nothotdog),有效— > (hotdog,nothotdog))
以这种方式构建数据集的原因是,当我们在 Keras 中加载数据时,Keras 要求数据是这种方式。
第一次迭代——创建一个基本的 ConV 模型
在第一次迭代中,我创建了一个简单的卷积模型,有两个 ConV 层和三个全连接层。我没有将整个图像数据集加载到内存(numpy 数组)中,而是使用 Keras 生成器在运行时批量加载图像。我还在 keras 中使用了ImageDataGenerator
类来批量扩充运行时的数据。
该模型用 50 个历元训练约 50 分钟,在测试集上给出了 71.09%的准确率。
对于如此简单的任务来说,这是相当低的精确度。我的意思是,人类完成这项任务的准确率必须达到 100%。
这引起了我的思考,我决定在迭代#2 中更进一步。
第二次迭代——迁移学习
我决定用迁移学习让这个分类器更好更快的训练。现在,我无法实时扩充数据,因为迁移学习在 Keras 中不支持。因此,我编写了一个脚本来扩充数据并创建一个更好的数据集。我应用了以下转换:
- 水平翻转
- 垂直翻转
- 以一定角度旋转图像
- 剪切和缩放图像
这种数据扩充导致了数据集版本 2.0,其具有 7822 个热狗图像和 7822 个“非热狗”图像。这是一个大得多的数据集,所以我预计分类器的准确性会有所提高。现在,实际上获得新数据比应用数据增强要好得多,正如deep learning . ai课程中吴恩达所教导的那样,但由于前者不是一个选择,数据增强至少可以使在分类器方面有所改进。
现在我有了一个相对更大更好的数据集,是时候开始 了!
不,不是克里斯托弗·诺兰写的那本。
我决定使用 InceptionNet V3,因为它提供了比 VGGNet 和 ResNet50 更好的结果。Keras 提供了一个Application
模块,可以很容易地使用这些预先训练好的架构。于是,我下载了预先训练好的 InceptionV3 模型和权重,然后在这个模型上训练数据集,得到数据集的瓶颈特征。这基本上是通过从 InceptionNet 中移除完全连接的层并仅在 ConV 层上训练数据来实现的。这个过程将我们的原始图像转换成矢量。
现在我们创建一个简单的 ConV 模型(与迭代#1 中的相同),并在这些瓶颈特性上训练它。该模型训练时间约为 5 分钟,在测试集上的准确率为 96.42%。对于如此少的数据来说,这是一个相当好的精度。由于准确性并不总是衡量模型性能的最佳指标,我创建了一个混淆矩阵。
Confusion Plot
看那些被错误分类的图片,很多被分类器错误分类为“不是热狗”的图片并没有很好的看到热狗。或者吃的不仅仅是热狗。虽然,为什么它把一群人归类为热狗是一个谜,我希望有一天能解决!
等等,我们刚刚做了什么?
- 我们从一个电视节目中获得了一个想法,并决定使用这个想法来完成整个 ML 流程。
- 首先,我们收集数据,因为这是我们 ML 模型的动力。在这种情况下,我们得到了热狗和其他一些不是热狗的东西的图像。
- 我们做了一些数据预处理,删除了破损/无用的图像,并将所有图像调整到相同的大小。
- 我们创建了一个简单的 ConV 模型,并使用实时数据增强。我们得到的结果并没有给我们留下太多印象。因此,为了追求快乐和更好的准确性,我们决定更进一步。
- 我们使用迁移学习来获得更好的结果。从预先训练好的网络花名册中,我们选择了 InceptionV3 网络,得到了瓶颈特征。
- 我们在这些瓶颈特征上训练了一个类似于第一个网络的网络,并且获得了更好的准确性。
- 我们绘制了一些指标,如损失、准确性和混淆矩阵,因为图表很酷,也很有用。
- 我们坐下来,对我们最近的成就微笑,并开始思考下一步要做什么。
原来如此。我创造了一个很好的分类器来告诉我某样东西是不是热狗。正如杨健认为的那样,这是下一个价值 10 亿美元的想法!
“真令人陶醉。别装得一点都不神奇。确实是!”—贾里德
这个项目是我正在进行的#100DaysofMLCode 挑战的一部分。关注我在 推特 上的更新。
为计算机视觉模型构建 Web 应用并在 10 分钟内部署到生产环境*:详细指南
原文:https://towardsdatascience.com/building-web-app-for-computer-vision-model-deploying-to-production-in-10-minutes-a-detailed-ec6ac52ec7e4?source=collection_archive---------5-----------------------
result.html
下载入门包&为 Docker 托管的 web 应用程序提供商之一执行一次性设置后,您可以将 fast.ai 或 keras 库中创建的计算机视觉模型快速部署为响应性 web 应用程序,这一切只需不到 10 到 15 分钟。
**2020 年 8 月 23 日更新:**世界变化很大,自从我更新了这篇文章,fastai 和 keras 库也是如此, Fastai 已经发布了完全重写 Fastai 的版本 2 ,keras 也是如此,它现在是 tensorflow2 的一部分。我还为 fastai 和 keras 发布了更新的入门包,请在此下载:
Fastai 版本 2:
git clone [https://github.com/psmathur/fastai2-vision-app](https://github.com/psmathur/fastai2-vision-app)
Keras(在张量流 2 下)
git clone https://github.com/psmathur/keras-vision-app
**2019 年 1 月 4 日更新:**增加了一个部署选项:“呈现”一个新的最简单但功能强大的基于 Docker 的 web 服务托管提供商&更多。
**2018 年 12 月 4 日更新:**我我不确定,我想继续使用 Zeit 服务,因为 Zeit 最近做出了很多改变来限制 100 MB 的限制。我无法解决 100 MB 的限制问题,即使我有无限付费计划,甚至当我试图通过 CLI 用“now.json”显式使用平台的版本 1。依我看,他们用 100 MB 的限制来限制自己,肯定错过了巨大的商机!
**所以,你已经使用像 Fast 这样著名的深度学习库建立了**一个令人敬畏的图像分类模型。AI 或 Keras ,然后写了一篇关于它的文章,同时解释了你的模型如何可以对各种类型的蓝松鸦 s、植物病害、意大利美食、 薯条、瑞士手表进行分类,甚至可以预测出你身边播放的古典音乐的作曲者,使用音频文件的声谱图(而你认为图像分类是被夸大其词了)。
现在,接下来呢?
嗯,除了写一篇关于你如何建立一个令人惊叹的计算机视觉模型的技术博客帖子,你还想与你的同事、朋友、家人或任何拥有带网络浏览器的设备的人轻松分享你的工作。您希望与他们分享您的工作,因为他们都可以快速测试您基于深度学习的模型结果并提供有价值的反馈,这是评估您最终 DL 模型的重要一步。
你需要一个演示网络应用程序!
Source: https://gifsboom.net/post/141202971289/t-rex-vs-spiderman-in-real-life-superhero
假设您已经建立了一个图像分类算法,现在需要一个简单的 web 应用程序,它可以以异步方式处理从 web 浏览器上传的图像或图片,然后它还需要以异步方式下载您训练过的模型,托管在其他地方。
深度学习模型很重,你知道一个巨大的多维激活矩阵,所以它们需要在一些云存储服务上独立上传,另外你想有一个切换到更好升级的模型的选项,特别是基于你收到的反馈,而不改变和重新部署底层 web 应用。
然后,这个 web 应用程序还应该能够使用您首选的深度学习库将您的模型加载到机器的内存中,然后它可以预测您上传的图像上的标签。
最终,所有这些东西都需要在某个云托管提供商上进行配置、部署和托管。听起来很有趣,对吧…
我们都知道,如果你没有一个既定的流程,尤其是在 bug 修复或部署配置期间,上面提到的任何步骤都会花费大量时间。因此,为了将所有这些步骤减到最少,我写了这个指南。一旦你遵循了这篇文章,你将有一个 3(或 2)步的过程,通过它你可以快速地为你的计算机视觉模型构建一个 web 应用&可以在< 10 Minutes.
Here is the link of a sample web app: 将它们部署到生产中
index.html
为了构建和部署这种 web 应用程序,首先,我们将下载或克隆托管在我的 GitHub repo 上的启动包,目前,这些 web 应用程序启动包仅用于使用 Keras 和fast . ai构建的计算机视觉模型
这些初学者包包含一个简单的响应式 web 应用程序,它构建在 ASGI 服务器的基础上。下载其中一个入门包后,您只需更改几行代码,就可以在本地机器上运行您的深度学习模型。
其次,我们将使用 Docker 托管的服务之一。我们将把静态 web 应用程序目录与 docker 配置放在一起,然后将它部署到这些完全托管的 docker 托管服务之一的生产环境中。
**在这篇文章中,我正在覆盖, AWS 豆茎 , Azure Web App 和 现在版本 1 **。然而,你可以使用类似的步骤部署到任何其他 Docker 托管的服务。
那么,现在,事不宜迟,让我们从第一步开始。
步骤 1:下载 web 应用程序入门包
对于你的 keras 模型部署 去我的 Github 下载keras-vision-apprepo。
wget [https://github.com/pankymathur/keras-vision-app/archive/master.zip](https://github.com/pankymathur/fastai-vision-app/archive/master.zip)
为了你的 fast.ai 模型部署 去我的 Github 下载fastai-vision-apprepo。
wget [https://github.com/pankymathur/fastai-vision-app/archive/master.zip](https://github.com/pankymathur/fastai-vision-app/archive/master.zip)
解压缩 zip 文件,重命名目录,使其与您的应用程序名称相匹配
unzip *fastai-vision-app*.zipmv fastai-vision-app YOUR-APP-NAME-HEREcd YOUR-APP-NAME-HERE
注意:你也可以在 Keras 或者 Fast 的目录下,让一切都保持现在的样子。AI starter pack app,只需转到步骤 2 &步骤 3 进行快速试用部署,那样的话,你就要部署我的X-Finder App或者 寻衣 App 。如果您没有,并且想在部署之前完善一切,那么请继续阅读。
上传您的训练模型 将您的训练模型上传到任何公共云托管服务。通常训练好的模型在 keras 中的文件类型为“. H5***”*,可以使用 model.save() 方法和“ 文件类型创建。并且可以使用方法 learn.save() 创建。**
举个例子,对于我的文章和 fast.ai 项目 “打细纹服装分类基准” ,我最终的模型文件名是“stage-1 _ SZ-150 . PTH”。它的大小为< 100 MB,并公开托管在我的 public GitHub 项目回购上。
如果您的模型文件大于 100 MB,您可以使用任何其他云服务,如 Google Drive 或 Dropbox 来上传您的模型文件,然后复制该文件的原始下载链接。
****注:原始下载链接是直接开始文件下载的链接,通常不同于您看到的共享链接。例如,dropbox 原始下载链接如下所示:
'[https://www.dropbox.com/s/y4kl2gv1akv7y4i/stage-2.pth?raw=1'](https://www.dropbox.com/s/y4kl2gv1akv7y4i/stage-2.pth?raw=1')
- 为 Keras 车型定制的入门 Web 应用
打开“app”
目录中的文件"server.py”
,然后用托管模型文件的原始下载 URL 更新带有“model_file_url”
变量的行。例如:
model_file_url = 'https://github.com/pankymathur/Fine-Grained-Clothing-Classification/blob/master/data/cloth_categories/models/model.h5?raw=true'
保持其他一切不变,如果你像我一样使用一些东西,例如,我已经在 Keras 中使用迁移学习过程创建了一个简单的图像分类模型,具有 Resnet50 架构和 Imagenet 预训练的权重,用于 46 种不同类型的服装类别。当然,您可以完全定制代码来满足您的需求。
然后我已经上传了我训练好的 Keras 模型< 100 MB on my GitHub public repo, so here is how my final “ server.py" 的样子,就在步骤 2 之前。
server.py
- 针对 Fast 定制的 Starter Web 应用程序。人工智能模型
打开“app”
目录中的文件"server.py”
,然后用您的托管模型文件的原始下载 URL 更新带有“model_file_url”
变量的行。例如:
model_file_url = 'https://github.com/pankymathur/Fine-Grained-Clothing-Classification/blob/master/data/cloth_categories/models/stage-1_sz-150.pth?raw=true'
在同一个文件中,用您期望从模型中预测的标签类更新下面的行。
classes = ['Blouse', 'Blazer', 'Button-Down', 'Bomber', 'Anorak', 'Tee', 'Tank', 'Top', 'Sweater', 'Flannel', 'Hoodie', 'Cardigan', 'Jacket', 'Henley', 'Poncho', 'Jersey', 'Turtleneck', 'Parka', 'Peacoat', 'Halter', 'Skirt', 'Shorts', 'Jeans', 'Joggers', 'Sweatpants', 'Jeggings', 'Cutoffs', 'Sweatshorts', 'Leggings', 'Culottes', 'Chinos', 'Trunks', 'Sarong', 'Gauchos', 'Jodhpurs', 'Capris', 'Dress', 'Romper', 'Coat', 'Kimono', 'Jumpsuit', 'Robe', 'Caftan', 'Kaftan', 'Coverup', 'Onesie']
保持其他一切不变,您的应用程序就可以快速部署了(当然,您可以完全定制代码来满足您的需求)。对于一些部署选项,您需要将您的应用程序推送到 GitHub repo,这可能是公共的,也可能是私有的,具体取决于您的选择。
步骤 2(选项 1):渲染
Render 是一款简单而强大的云提供商服务,适用于您的所有应用和网站。点击此链接=>https://dashboard.render.com/register?i=fastai-v3注册,即可获得 25 美元的积分。渲染 web 服务的费用为每月 5 美元,按秒按比例分配。
**注册后,转到你的渲染面板,然后创建一个新的 **Web 服务。在这里使用 GitHub repo 为你在上面步骤 1 中创建的应用程序。
请注意,在这一步中,您需要授予 Render 权限来访问您的 GitHub repo。
之后,在部署屏幕上,为您的服务选择一个名称,并使用**Docker**
作为环境。此外,如果您在 GitHub repo 中有多个分支,请选择适当的分支,或者保留主分支选择。
只需点击保存 Web 服务即可!您基于 docker 的 web 应用程序服务将开始构建,并且应该在大约 10 分钟后上线。您可以在部署日志中跟踪它的进度。最后,您可以检查显示在渲染面板中的 web URL
【https://keras-vision.app.render.com/ 号
第二步(选项 2): AWS 弹性豆茎
AWS Elastic Beanstalk 是一个易于使用的 AWS 服务,用于为 Docker 应用程序部署 web 应用程序,此外 AWS 还为新帐户提供免费试用。特别是因为我们的应用不打算使用任何数据库实例,最终定价将只包括 EC2 实例、负载平衡器和 S3 定价。点击这里阅读更多关于 AWS Beanstalk 定价的信息。
首先,打开 AWS Dashboard,搜索 Elastic Beanstalk services,然后单击“开始使用”创建新应用程序。您将看到以下屏幕。
为您的演示应用程序名称和描述添加详细信息,然后单击“ ”创建“ ”。您将看到一个用于创建新环境的新屏幕。
选择 【立即创建一个】 ,将出现如下画面。
Create New Environment
在此选择 web 服务器环境,您将看到 创建 Web 服务器环境 详细信息屏幕。
添加你的“ 环境名“ ,选择你的“域名,看看是否可用,然后添加“ 描述”。
****重要提示:在基本配置部分,选择 预配置平台 ,然后选择“”通用选项。
在同一页上向下滚动,因为你需要添加更多的细节。
选择 【上传我们的代码】 选项,点击上传,会出现如下画面。在上传您的入门包之前,请阅读下面的说明!
****重要提示:出于某种奇怪的原因,你可以直接上传我们 web app 文件夹的压缩文件,你必须将内容直接压缩到你的 web app 文件夹下,我猜是因为 AWS Beanstalk 需要看到直接在压缩文件的根目录下找到的 Dockerfile,而不是在 web app 文件夹下。因此,要做到这一点,只需在您的本地机器上打开 web 应用程序并直接压缩内容。这就是我在 Mac OS X 中的做法。
******可选:**如果您已经在您的机器上本地运行了" server.py " ,那么您可能已经在目录 app>static>model>"model . H5 "或"model . PTH "下下载了模型文件,为了使这个压缩的压缩文件更小,您可以删除那些模型文件。但是,请注意,AWS Beanstalk 允许上传的文件大小不超过 512 MB。
上传你的一个 web app 的源码包后,“ 创建 web 服务器环境页面” 会是下面这个样子。
****重要:不要按 【创建环境】 现在,我们要用 配置更多的选项!
Don’t Click Create Environment Now! Use Configure More options
这些都是必要的步骤,为了让我们的 Web App 在 AWS Beanstalk 上顺利部署,点击 【配置更多选项】, 将会打开一个新的页面,在这里我们要将"配置预置部分改为" 自定义配置" 选项,如下图所示
**然后下到第一节>软件】****点击 修改 会打开一个如下图的页面,将代理服务器从 Nginx 修改为 无。 保持其他一切不变,按保存。
“保存”后你会回到配置页面,在这里下去第二节>【实例】点击 【修改】 会打开一个如下图的页面,将实例类型从【t1.micro】改为【T3 . medium】。 保持其他一切不变,按保存。******
这就是自定义配置,现在按“ 【创建环境】 然后去喝杯咖啡什么的,AWS Beanstalk 需要 10-20 分钟来部署您的源代码以创建 docker 映像,然后将该 Docker 映像部署到您选择的 ec2 实例,创建应用程序负载平衡器,使用入站和出站网络设置创建适当的安全组以及许多其他事情,这些都超出了本指南的范围。您将看到一个屏幕,显示 AWS BeanStalk 部署的日志文件条目。
请耐心等待,8-10 分钟后,您会看到这样的仪表盘,它会显示健康状况,如每个阶段的 【绿色】 和详细日志。
点击仪表板上显示的 URL,您将被重定向到新的演示应用程序,并在 AWS 上运行。
**注:如果你在仪表盘上看到,健康不是“而是“”,请详细查看日志文件。您可以在左侧的“日志”部分找到详细日志,按下请求日志>完整日志或最后 100 行。阅读日志将向您显示健康状态“红色”的主要原因以及您的部署失败的原因。 通常,这是你选择的小型 ec2 实例类型,它们在运行你的应用程序或尝试应用其他自定义设置时无法处理部署或内存问题,我在上面没有提到这一点。
第 2 步(选项 3):带有自定义运行时的 Google 应用引擎
Google App Engine 自定义运行时让你构建在由 Dockerfile 定义的环境中运行的应用。此外,谷歌云确实为新账户提供 12 个月的免费试用,价值 300 美元。特别是因为我们的应用程序不打算使用任何数据库实例,最终定价将只包括谷歌计算实例、负载平衡器和谷歌云存储定价。点击此处阅读更多关于谷歌应用引擎定价的信息。
首先,打开 Google Cloud Dashboard,点击创建项目,然后命名您的新 GCP 项目。通过创建新的计费帐户或设置现有帐户,在您的新 GCP 项目中启用计费。您将看到以下屏幕。
创建新项目后,您将看到 GCP 仪表板页面,转到页面的最右上角,单击“ 【激活云壳】” 。终端窗口将在同一页面中打开。
此时,您可以继续使用同一个终端窗口,或者在新的浏览器页面中打开该终端窗口。
运行以下命令创建 App Engine 应用程序,并指定希望应用程序运行的地理区域。
**gcloud app create**
我选择 13 并按回车键,几分钟后,它会显示类似“成功!应用程序现已创建。”
现在,通过键入以下命令,下载 Github 或任何其他 git 存储库管理服务上托管的 starter pack 应用程序存储库。确保您的入门包与我的 repo 中的 app.yaml 和 Dockerfile 相同。
**git clone [https://github.com/pankymathur/fastai-vision-app](https://github.com/pankymathur/fastai-vision-app)**
下载存储库后,导航到您的应用程序目录。
**cd fastai-vision-app**
将您的应用部署到 Google 应用引擎
**gcloud app deploy**
您将看到一个屏幕,显示“要部署的服务”,输入 Y
然后去喝杯咖啡,因为 app engine 需要 8~10 分钟来部署基于 docker 的应用程序,并呈现到您的最终 URL。要查看您的应用在http://YOUR_PROJECT_ID.appspot.com
运行,运行以下命令启动您的浏览器:
**gcloud app browse**
这是我在 GCP 上运行的默认 fastai-vision-app starter pack 应用。
第二步(选项 4): Now.sh
现在版本 1 有一个免费计划,可以为你的静态网络应用程序无限部署&域,可以处理高达 1 GB 的存储&带宽,&许多其他功能,只要你的最大文件大小不超过 5 MB。
现在桌面应用程序
- 用于 Mac OSx 和 Windows
前往https://zeit.co/download下载 now.sh 桌面 app 进行快速拖拽&展开。
命令行安装
- 在 Mac OS X 上
**# *Intall* [*https://brew.sh*](https://brew.sh)*, if not already installed*
# a mac without brew is just another empty glass/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"*# Install npm, if not already installed*
brew install npm# *Install now.sh cli*
sudo npm i -g --unsafe-perm now**
- 在 Linux 上
***# if not already installed*
sudo apt install npm# *Install now.sh cli*
sudo npm i -g --unsafe-perm now**
- 在 Windows 上
下载 https://nodejs.org/en/download/的 NPM 视窗安装程序
使用 Powershell:
**# *Install now.sh cli*
sudo npm i -g --unsafe-perm now**
在 Windows 10 上使用 Linux 应用程序:
选择你选择的 Linux 应用:https://docs.microsoft.com/en-us/windows/wsl/install-win10安装好 Linux 应用后,进入终端,按照上面的 Linux 说明安装 now.sh CLI
部署
- 通过 Now 桌面
通过拖放或上传您的responsive-web-app
目录到“Now Desktop”进行部署。
它将在一个单独的浏览器窗口中显示所有的部署日志细节。您可能需要在部署开始前登录 zeit.co。
它将为您的静态应用程序创建一个唯一的部署 URL ,并在部署期间的前几行日志中显示出来。通常,它的格式为[https://YOUR-APP-NAME-HERE-xxxxxxxxxx.now.sh](https://YOUR-APP-NAME-HERE-xxxxxxxxxx.now.sh)
当部署完成时,它将显示"成功!浏览器窗口中的部署就绪。
可选:如果你像我一样,你想为你的应用程序使用一些漂亮的 URL 名称,而不是默认的名称,如 [https://YOURAPPNAMEHERE-xxxxxxxxxx.now.sh](https://YOUR-APP-NAME-HERE-xxxxxxxxxx.now.sh)
您可以转到zeit.co上的仪表盘,使用当前部署的创建别名选项,将别名添加到您的应用中
- 通过 Now CLI
在终端上,确保您在keras-vision-app
或fastai-vision-app
目录中,然后键入:
**now**
每次使用“Now CLI”进行部署时,它都会为您的静态应用程序创建一个唯一的部署 URL ,并且会在部署期间的前几行日志中显示出来。通常,它的格式为[https://YOURAPPNAMEHERE-xxxxxxxxxx.now.sh](https://YOURAPPNAMEHERE-xxxxxxxxxx.now.sh)
当部署完成时,它将显示"成功!终端上的部署就绪。
可选:如果你像我一样,你想为你的应用程序使用一些漂亮的 URL 名称,而不是默认的名称,如 [https://YOURAPPNAMEHERE-xxxxxxxxxx.now.sh](https://YOUR-APP-NAME-HERE-xxxxxxxxxx.now.sh)
您可以使用以下命令更改应用程序的别名:
now alias PRETTY_URL_NAME [YOURAPPNAMEHERE-xxxxxxxxxx.now.sh](https://YOUR-APP-NAME-HERE-xxxxxxxxxx.now.sh)
它会显示一些东西:
**> Success! YOUR-APP-NAME-HERE.now.sh now points to YOURAPPNAMEHERE-rhainypwfk.now.sh**
缩放比例
默认情况下,now.sh 上的 all now deployment 会在一段非活动时间后进入睡眠状态。如果你想让你的应用程序在分享或演示过程中处于活动状态,这并不好。因此,扩展您的应用实例:
**# You only need to do this once.
now scale YOUR-APP-NAME-HERE.now.sh sfo 1**
它会显示一些东西:
**> ✔ Scaled 1 instance in sfo1 [923ms]
> Success! Scale state verified**
现在,您可以与任何人分享[https://YOUR-APP-NAME-HERE.now.s](https://YOUR-APP-NAME-HERE.now.sh)h
,以获得快速反馈和演示。
例如,这里是我的默认演示应用程序的链接https://x-finder . now . sh
设置 Docker Hub 帐户并上传您的 docker repo(选项 5)
你需要一个免费 Docker hub 账户。docker Hub 是容器托管存储库,我们将使用它向 Docker 托管的应用程序服务提供商之一提供 Docker 映像,如“ Azure 网站 for Containers”这样这些服务就知道从哪里获取 Docker 映像。
有很多很多的容器托管服务,提供公开或私有托管你的 docker 镜像的选项,例如,这些是业界常见的容器注册表 Docker Hub 、 Azure Container Registry、Amazon Elastic Container Registry或 Google Container Registry 。对于我们的场景,Docker Hub 上的公共容器存储库是一个很好的选择。
有两种方法可以在 docker Hub 上创建 Docker 存储库,第一种是使用 Docker CLI,它与 Mac OSx 或 Windows 的 Docker 桌面应用程序打包在一起。
安装 Docker 桌面应用程序并登录 Docker Hub 帐户后,以下是构建 Docker 映像并将其上传到 Docker Hub 容器注册表的步骤:
- 创建一个 Docker 图像
****docker build -t <imageName> .*#For ex: docker build -t keras-vision-app .*****
- 在本地运行映像,查看您的应用程序运行情况
****docker run -p 5042:5042 <imageName>#*For ex: docker run -p 5042:5042 keras-vision-app*****
- 用你的 Docker Hub 用户名标记图片
****docker tag image username/repository:tag#*For ex: docker tag keras-vision-app pankajmathur/keras-vision-app*****
- 将图像推送到 Docker Hub
****docker push username/repository:tag#F*or ex: docker push pankajmathur/keras-vision-app*****
成功推送后,您可以在 docker Hub 帐户中看到您的本地 Docker 映像。
keras-vision-app docker repo
第二种方式是使用 GitHub 与Docker Hub 账户集成。这是从 0 到 Docker 容器注册表最快的方法。
- 将 Docker Hub 与您的 GitHub 个人资料相链接
登录 Docker Hub,然后导航至个人资料>设置>关联账户&服务然后点击 GitHub 服务。弹出窗口提示您输入 GitHub 凭据。授予对代码库的访问权限后。您的 DockerHub 链接账户&服务页面将如下所示:
- 创建自动化构建
转到您的 DockerHub 仪表板,然后从右上方的下拉菜单中选择创建 > 创建自动化构建。它会要求您选择 GitHub 关联帐户:****
系统提示将显示您所有的 GitHub 存储库,键入以过滤存储库列表,然后选择要构建的项目。
系统提示将显示创建自动构建对话框。该对话框采用了一些您可以自定义的默认值。默认情况下,Docker Hub 会为存储库中的每个分支构建映像。它假设 docker 文件位于您的源存储库的根目录下。当它构建一个映像时,Docker Hub 用分支名称标记它。如果你想自定义默认选项,那么点击这里自定义这个行为链接。(对于我们的用例,保留默认值是好的)
点击创建,系统显示你的自动化构建的主页。
就这样,你让你的 docker 托管容器注册中心复制你的存储库的名称,在我的例子中,它是pankajmathur/fastai-vision-App,现在你已经准备好步骤 2(选项 4):Azure Web App for Container Service。******
步骤 2(选项 4): Azure Web App for Containers 服务
Azure Web App for Containersone click docker App 提供了非常易于部署和托管的 docker 静态应用机制。有一篇好文章是同道 fast.ai 学员 日产 写的 https://redditech . blog/2018/11/04/hosting-fastai-app-in-azure-websites-for-containers/。
请阅读这篇文章,它展示了 Azure Portal App Services for Container Services 流程的一步一步的截图。我能够阅读这篇文章,并能够在< 10 minutes.***
中设置我的 web 应用程序 Azure 最初需要很长时间来部署整个容器并传播 DNS,几乎需要额外的 10 分钟。***
缩放比例
Nissan 没有涵盖这一部分,所以默认情况下,所有 azure web 应用程序部署在一段不活动时间后都会进入睡眠状态。如果你想让你的应用程序在分享或演示过程中处于活动状态,这并不好。因此,通过转到 Azure 应用服务设置>应用设置 并打开App Always ⇒并关闭ARR Affinity ⇒来扩展您的应用实例
目前 Azure 提供前 30 天 200 美元的免费试用积分来试用他们的服务,所以你可以很容易地注册一个新帐户并尝试所有步骤。
这是我们的 Azure Web App = >https://keras-vision-app.azurewebsites.net
入门包的罩下是什么?
嗯,我的两个 keras 和fast . aistarter packs 库都是 GitHub 上的开源,所以你可以在下载或克隆它之前检查所有代码。启动包的主体是" server.py" ,这是一个小型的 starlette . io&uvicon 驱动的 ASGI 服务器。
这个小小的服务器实际上一点也不小,而是一个强大的服务器,这个小小的服务器在Asyncio库的帮助下,使用“ 【上传(请求)】方法,以并发方式处理您的图像或图片上传,然后它有“【download _ file(URL,dest) 方法,优雅地将您的训练好的模型下载到本地驱动器,然后这个小小的 在事件循环、任务、和协同程序机制的帮助下,使用您的 keras 或 fast.ai 深度学习库将您下载的模型文件加载到主机内存中,最终这个微型服务器预测您上传的图像上的标签,并将其吐回到 prediction.txt 文件中。****
frontend statics 是一个简单的 HTML5 响应式 web 应用程序,带有几个整洁的 JS hacks 来处理大图像文件上传,特别是对那些令人敬畏的 raw 相机或自拍图片有用。
最后,微型 ASGI 服务器和 responsive statics 被放入一个 docker 中,使用 docker 配置安装正确的 python 版本,并在 requirement.txt 的帮助下安装 Keras 或 Fast.ai、starlette.io、uvicorn 和所有其他库依赖项,然后这个 docker 配置将暴露端口 5042 并启动服务器。所有这一切,让你可以轻松地在 docker 云机器上托管你的 Docker 映像…
注意:大多数现代浏览器都能很好地处理这些 JS hacks 和 HTML5 文件。如果你还停留在 21 世纪初,忽略这篇文章。
source: https://cheezburger.com/8348948736
就这样,希望你喜欢这个指南,并能够为你的计算机视觉模型构建你的 Web 应用程序&能够将它们部署到生产中,并在这样做的同时建立一个 3 步流程,因此你可以立即重复所有这些步骤。如果没有,请在评论区告诉我你的问题。如果是的话,我真的很希望得到一些关于这篇文章的反馈和改进意见。
同时,快乐深度学习…
使用 Python 中的 Keras 在流失建模数据集上从头开始构建您自己的人工神经网络
原文:https://towardsdatascience.com/building-your-own-artificial-neural-network-from-scratch-on-churn-modeling-dataset-using-keras-in-690782f7d051?source=collection_archive---------1-----------------------
用神经网络的力量留住你的客户群!
众所周知,留住客户是许多公司的头等大事;获得新客户的成本可能是留住现有客户的好几倍。此外,了解客户流失的原因和估计与单个客户相关的风险都是设计数据驱动的保留策略的重要组成部分。流失模型可以是一种工具,它将这些元素整合在一起,并提供洞察和输出,推动整个组织的决策制定。因此,它被用来预测哪些客户将离开银行。
什么是流失率?
流失率(有时也称为损耗率),从最广泛的意义上来说,是对特定时期内从一个集体群体中移出的个人或物品数量的衡量。这是决定一个企业将支持的客户的稳态水平的两个主要因素之一。
那么这篇文章的读者是谁呢?
你可以是刚刚完成机器学习 MOOC 的人,也可以是正在寻找基于机器学习的更实用/动手项目的初露头角的数据科学家。
如果你是经济学专业的学生,试图将数据科学的各个方面与你所在领域相关的东西结合起来,这也可能是相关的。
我们还在等什么?我们开始吧!!
因此,在这个数据集中,我们将处理客户流失建模,也就是说,我们将编写一个人工神经网络来找出客户实际离开银行的原因以及他们之间的依赖关系。
这是一个分类问题,即 0-1 分类(如果客户离开,1;如果客户留下,0)
我们可能会使用 Theano 或 Tensorflow,但问题是这些库要求我们从头开始编写大部分 Ml 代码,因此我们使用 Keras,这使我们能够编写强大的神经网络,只需几行代码 Keras 在 Theano 和 Tensorflow 上运行,您可以将其视为深度学习的 Sklearn。
第 1 部分—数据预处理
# Importing the libraries
*import* numpy *as* np
*import* matplotlib.pyplot *as* plt
*import* pandas *as* pd
导入数据集
将它保存在 Pycharm 项目/项目名称中,并使用 pandas 加载它。
dataset = pd.read_csv('Churn_Modelling.csv')
从这些特征中我们可以看出,行号、姓名与客户离开银行没有关系。
所以我们从 X 中删除它们,X 包含从 3 到 12 的特征索引。
X = dataset.iloc[:, 3:13].values
我们通过在变量 y 中存储第 13 个索引来存储 y 中的相关值/预测值
y = dataset.iloc[:, 13].values
打印出…的值
包含特性的 x→y→包含目标变量
print(X)
print(y)
编码分类数据…
现在我们将特征中的字符串值编码为数值,因为 ML 算法只能处理数字,而不能处理字符串值。
仅有的两个值是性别和地区,需要转换成数字数据
*from* sklearn.preprocessing *import* LabelEncoder, OneHotEncoder
创建 1 号标签编码器对象以编码区域名称(功能中的索引 1)
labelencoder_X_1 = LabelEncoder()
编码区从字符串到 3 个编号分别为 0,1,2
X[:, 1] = labelencoder_X_1.fit_transform(X[:, 1])
创建 2 号标签编码器对象以编码性别名称(特征中的索引 2)
labelencoder_X_2 = LabelEncoder()
将性别从字符串分别编码为 2 个 no.s,1(男,女)
X[:, 2] = labelencoder_X_2.fit_transform(X[:, 2])
现在创建虚拟变量
onehotencoder = OneHotEncoder(categorical_features = [1])
X = onehotencoder.fit_transform(X).toarray()
X = X[:, 1:]
将数据集分为训练集和测试集
*from* sklearn.model_selection *import* train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 0)
特征缩放
*from* sklearn.preprocessing *import* StandardScaler
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)
第二部分——现在让我们制作人工神经网络!
列出了用随机梯度下降法训练 ANN 的步骤:-
1)随机地将权重初始化为接近 0(但不是 0)的小数字。
2)在输入层中输入数据集的第一个观察值,每个要素在一个输入节点中。
3)从左到右的前向传播,神经元被激活的方式影响每个神经元的激活。
受权重限制。传播激活,直到获得预测结果 y。
4)将预测结果与实际结果进行比较。测量产生的误差。
5)反向传播:从右到左,误差反向传播。根据权重对误差的影响程度来更新权重。学习率告诉我们更新权重的程度。
6)重复步骤 1 至 5,并在每次观察后更新权重(强化学习)。
或者:重复步骤 1 至 5,但仅在一批观察(批量学习)后更新权重。7)当整个训练集通过人工神经网络时。这完成了一个时代。重做更多的纪元。
导入 Keras 库和包
*import* keras
为了一层一层地建立神经网络
*from* keras.models *import* Sequential
将权重随机初始化为接近 0(但不是 0)的小数字
*from* keras.layers *import* Dense
正在初始化人工神经网络…
因此,实际上有两种方式来初始化深度学习模型
— — — 1)逐个定义每一层
— — — 2)定义一个图
我们没有在顺序对象中放入任何参数,因为我们将手动定义层
classifier = Sequential()
添加输入层和第一个隐藏层…
这仍然是一个没有答案的问题,直到今天,我们实际上需要多少隐藏层的节点?
没有经验法则,但是您可以将隐藏层中的节点数分别设置为输入和输出层中节点数的平均值。(在 90%的情况下有效!!)
——→此处 avg= (11+1)/2== > 6 因此设置输出 Dim = 6
——→Init 将统一初始化隐藏层权重
——→激活函数是整流器激活函数(Relu)
Input dim 告诉我们输入层中的节点数。这是只做一次,不会被指定在进一步的层。
classifier.add(Dense(output_dim = 6, init = 'uniform', activation = 'relu', input_dim = 11))
添加第二个隐藏层…
classifier.add(Dense(output_dim = 6, init = 'uniform', activation = 'relu'))
添加输出层…
classifier.add(Dense(output_dim = 1, init = 'uniform', activation = 'sigmoid'))
当我们需要 2 个或更少类别的概率时,使用 Sigmoid 激活函数(类似于逻辑回归)
当因变量超过 2 个类别时,切换到 Softmax。
正在编译人工神经网络…
classifier.compile(optimizer = 'adam', loss = 'binary_crossentropy', metrics = ['accuracy'])
将人工神经网络拟合到训练集
classifier.fit(X_train, y_train, batch_size = 10, nb_epoch = 100)
第 3 部分—进行预测和评估模型
预测测试集结果
y_pred = classifier.predict(X_test)
y_pred = (y_pred > 0.5)
如果 y_pred 大于 0.5,则返回 true(1),否则返回 false(2)
print(y_pred)
**该模型在训练数据上训练和在测试数据上测试时,在两种情况下都给出了大约 86%的准确度。**这从我们的角度来看是伟大的!!!
制作混淆矩阵
*from* sklearn.metrics *import* confusion_matrix
cm = confusion_matrix(y_test, y_pred)
print(cm)
从混淆矩阵中获得。您可以根据您的混淆矩阵中获得的内容来更改值。
print(accuracy)
恭喜你!你只是为给你这个任务的银行写了你自己的神经网络。您现在可以找出最有可能离开银行的前 10%的客户(这对银行来说非常重要)。该银行现在可能会采取纠正措施,以避免失去客户,如果没有你的帮助,它不会这样做:P
我希望你喜欢我的教程!我将 github(现在是 Gitlab 😛)链接附加到代码和数据集上。
[## sid-Darth Vader/基于人工神经网络的银行数据集建模
人工神经网络对流失建模数据集对银行人工神经网络对流失建模数据集…
github.com](https://github.com/Sid-darthvader/Artificial-Neural-Network-on-Churn-Modeling-Dataset-for-a-Bank)
参考文献-机器学习课程,作者:基里尔·叶列缅科和哈德琳·德·庞特维斯
打造自己的深度学习盒子
原文:https://towardsdatascience.com/building-your-own-deep-learning-box-47b918aea1eb?source=collection_archive---------0-----------------------
通往我的第一个深度学习平台的崎岖之路
Primary parts for building a deep learning machine
在完成杰瑞米·霍华德令人敬畏的深度学习课程的第一部分后,我看了看我的 AWS 账单,发现我每月花费近 200 美元运行 GPU。没必要花那么多钱来完成他的课程,但我开始平行研究一些课外数据集,我渴望得到结果。
在与同学交谈并阅读了一些博客帖子后,我决定尝试构建自己的盒子。技术和硬件变化如此之快,我担心 post 的大部分内容很快就会过时,但我希望我的一般方法至少在一段时间内仍然有用。
构建盒子的 6 个步骤
1.选择零件
2。组装五金件
3。安装操作系统
4。安装驱动器
5。安装库
6。设置远程访问
1.选择零件
我首先阅读了一些博客,以获得当前关于购买哪些部件的共识。由于硬件变化如此之快,到时候我会让你研究具体的部件,但一般来说你需要找到以下组件:主板,CPU,内存(RAM),硬盘(SSD),显卡(GPU),CPU 冷却器,电源和外壳。
我强烈建议在购买前在 pcpartpicker.com 上创建一个零件清单。它们有一个“兼容性检查”功能,可以告诉你你的组件是否不兼容。你可以在这里找到我的列表。
零件目录表
CPU*—英特尔 i7 7700k 4.2GHz 四核RAM***—海盗船复仇LPX 32GB(2x 16)DDR 4–3200276版主板 —微星 Z270-A PRO ATX LGA 1151
酷派 —酷派大师 Hyper 212 EVO 82.9 CFM**
我决定从一个显卡(单个 GPU)开始,但我确保 MSI 板有一个额外的 PCIe 插槽,以便我可以在未来添加另一个卡。更新(2017 年 5 月):原来微星 Z270-A PRO 有 1 个 x16e PCIe 插槽,不是 2 个。它可以在 x4e 插槽中容纳一个额外的 GPU,但性能会受到限制。如果你打算使用多个 GPU,就不要买这个!
一般来说,我会选择顾客评论最多的零件,即使这些评论并不完美。零件越受欢迎,用户生成操作指南和提示的可能性就越大。这将为您在接下来的两步中省去许多痛苦。
有用的帖子
打造个人深度学习钻机
优化入门 CUDA 打造
打造深度学习梦想机器
深度学习硬件指南
2.组装硬件
现在是有趣的部分。我能够找到大多数部件的教学视频,但有几个我不得不根据类似安装的视频进行修改。MSI 板、CoolMaster 和 NZXT 外壳的说明手册很不错,但我必须用其他材料补充它们。以下是一些我觉得有用的视频:
学习
- 买一把好的螺丝刀——我有一把不好的螺丝刀,它很快让我陷入困境。帮你自己一个忙,买一个长颈的,这样你就可以伸进狭小的空间。
- 再用力点 —免责声明:如果你弄坏了什么东西,不要怪我,但至少在两个场合(CPU 和内存)我浪费了时间,因为我对部件太温柔了。我害怕太用力,所以如果零件不容易到位,我就放弃了。在内存方面,我几乎在亚马逊上购买了一套全新的芯片。两种情况下的解决方法都是更用力。
- ***了解您的 BIOS—*BIOS 是预装在主板上的一个小软件,在您第一次启动机器时弹出。它基本上是一个控制面板,用于配置硬件和启动操作系统。了解您的主板在哪里寻找“引导驱动器”(保存您的操作系统的 USB 或 SSD)以及它如何选择要使用的显卡非常重要。令人遗憾的是,MSI 手册在这些问题上含糊不清,但有一些很好的视频深入到了细节中。
- 你的显示器没坏— 我花了一段时间才想出如何让显示器与我的新盒子配合使用。我在某处读到过,最初你需要将显示器连接到主板上,因为没有 Nvidia 驱动程序,显卡就无法工作。当我终于启动,但是我看不到任何东西在显示器上。我试着连接显卡,只是为了好玩,但也不起作用。最后,我尝试完全移除显卡,连接回主板并重启。成功了!问题是,微星主板默认使用自己的显卡,只有当它在 PCIe 插槽中找不到任何外部卡时。因为我第一次尝试启动时连接了显卡,所以主板尝试使用我的新卡。我没有看到任何东西,因为 Nvidia 驱动程序没有安装!
终于,我的杰作完成了!
**
3.安装操作系统
在您让显示器工作之后,您应该会看到类似这样的内容。这是你的简历。为了让一切正常运行,我需要做两个配置更改:更改引导优先级和交换默认显卡。
Pre-installed BIOS on MSI motherboards
我打算把我的机器主要用于编程和机器学习,所以我决定安装 Ubuntu 作为我的操作系统。我还希望从我的 Mac 电脑上远程工作,所以我不认为有必要安装 Windows,但你可以同时安装这两个系统。
创建可启动的 USB 驱动器
我按照这些用于 Mac 的指令下载了一个名为 UNetBootin 的客户端。
引导进入 Ubuntu
在一个完美的世界里,我应该能够插上我的 USB 驱动器,重新启动,回答几个问题,并且已经安装了一个完全可用的 Ubuntu 版本。相反,我得到了以下错误消息:
I pressed ESC a few times. Then DEL. Then F1, F10, and F12. Then #%^ and $&]&&&#^. Nothing worked.
问题在于 MSI 选择的默认“启动优先级”。再次登录 BIOS(开机后立即按 F11),我看到 BIOS 被配置为首先尝试从我的硬盘(三星 SSD)启动,硬盘是空的,但可能有足够的垃圾来混淆 BIOS。解决方案是将 USB 选项拖到优先级列表的顶部,然后重新启动。终于看到了友好的 Ubuntu 设置画面!
安装 Ubuntu 并重启后,我很自然地沮丧地发现我无法通过 Ubuntu 加载屏幕。它只是停滞不前,并最终超时。WTF!?!
问题原来是微星主板上的内置显卡(GTX 1080 还在我的茶几上)。它与 Ubuntu 图形用户界面不兼容!这是典型的先有鸡还是先有蛋。没有 Ubuntu 我不能安装 Nvidia 驱动,但是没有驱动我不能启动 Ubuntu!进入 GRUB 。
Ubuntu boot menu. You can get here by holding down ESC or Left Shift after powering on.
我最终找到了两个很棒的帖子在这里和在这里,它们帮助我摆脱了困境。解决方案是在引导命令中添加 nomodeset 参数。这帮助我启动了一个相当普通的 Ubuntu 版本,并继续我的道路。
4.安装驱动程序
NVIDIA 驱动程序是出了名的难相处,这个也不例外。在其他用户的带领下,我去了 NVIDIA 网站,下载了 GeForce 驱动程序,并开始使用 Ubuntu GUI 安装它。这是一个会给我带来巨大痛苦的错误。
检测不到兼容的 NVIDIA 卡
又一个鸡和蛋。我没有重新安装 GTX 1080,因为没有驱动程序它就无法工作。如果我重新连接它,MSI 板将再次开始使用它,我将回到我开始的地方。解决方案是重新启动 BIOS 并改变显卡的优先级。我没有默认选择新卡,而是更新了设置,让主板的内置卡优先。这让我可以重新安装 GTX 1080 并正常登录 Ubuntu。
你似乎正在运行 X 服务器
我使用这里的指令来解决这个问题,但是最初我无法通过第一步:“点击 CTRL+ALT+F1,使用你的凭证登录。”当我这样做时,屏幕会再次变成空白,我会失去与显示器的连接。解决方案是将 Ubuntu 引导至文本模式,并从命令行完成所有步骤。您可以通过在 GRUB 中编辑引导命令并将 nomodeset 更改为文本来引导进入文本模式。
更好的方法
最终,我让一切都正常工作了(驱动程序、CUDA、深度学习库等),并为自己感到欣慰。但是没过多久,我又一次破坏了配置文件。
在 AskUbuntu 上花了几个小时后,我注意到新的 CUDA 8.0 工具箱预装了 NVIDIA 驱动程序,并允许您同时安装 CUDA 和驱动程序。
我清除了现有的 NVIDIA 库,运行了下面的代码,一切正常。你可以在这里看到完整的说明。
*wget http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/cuda-repo-ubuntu1604_8.0.44-1_amd64.deb
sudo dpkg -i cuda-repo-ubuntu1604_8.0.44-1_amd64.deb
sudo apt-get update
sudo apt-get install cuda*
然后将以下内容添加到您的~/中。bash_profile:
*export PATH=/usr/local/cuda-8.0/bin${PATH:+:${PATH}}
export LD_LIBRARY_PATH=/usr/local/cuda-8.0/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
export LIBRARY_PATH=/usr/local/cuda-8.0/lib64${LIBRARY_PATH:+:${LIBRARY_PATH}}*
哦,我提到过你可以在 Ubuntu 文本模式下从命令行完成所有这些吗?谁需要图形用户界面!
5.安装深度学习库
有很多很好的帖子描述了基本的深度学习库以及如何安装它们( 1 、 2 、 3 、 4 )。这里关键的一点是不要盲目地遵循说明,尤其是关于如何安装的部分。这些说明通常已经过时,图书馆网站上有更好的例子。以下是我安装的库:
CUDA —利用 GPU
的并行计算平台 cud nn—Nvidia library for accelerated deep learning
Anaconda—Python for data science(numpy、scikit、jupyter..)
open blas—快速线性代数方法
Tensorflow—Google 的机器学习库
Theano**—tensor flow
Keras的替代方案—简化使用 tensor flow 或 the ano 的工作******
之后,我运行了一些测试,以确保一切正常,并开始使用 Jupyter 笔记本。
6.设置远程访问
这是一个可选的步骤,但是如果你打算从你的笔记本电脑远程工作,这里有一些方法可以做到这一点。
团队查看器
Teamviewer 是屏幕共享软件。如果你在两台机器上都安装并运行了它,你就可以从你的笔记本电脑上控制你的 Ubuntu 机器,反之亦然。虽然这使得某些事情更方便,但通过屏幕共享做任何事情都有点慢而且笨拙。
SSH 和端口转发
我希望能够远程 SSH 到我的新盒子,并与它交互,就好像它是我终端中的另一个选项卡一样。为此,我在 Ubuntu 上安装了 OpenSSH 。
*****sudo apt-get install openssh-server
sudo service ssh status*****
之后,我配置了我的 Comcast 路由器,将外部流量直接转发到我的主机。我按照康卡斯特的指示来到这里,令我惊讶的是,事情成功了!我通过检查 www.canyouseeme.org的 22 号端口验证了这一点。该过程的一部分包括计算出您的公共 IP 地址,您可以通过运行以下命令找到该地址:
*****dig +short myip.opendns.com @resolver1.opendns.com*****
远程笔记本
如果你是 Jupyter 的粉丝,另一个很酷的技巧是在深度学习桌面上运行笔记本,但在笔记本电脑上查看和编辑笔记本。这里有一个很棒的技术教程,所以我只转述一下命令:
*****$laptop: ssh -l bfortuner@DEEPLEARNINGIP
$server: jupyter notebook --no-browser --port=8888
$laptop: ssh -NL 8888:localhost:8888 bfortuner@DEEPLEARNINGIP*****
现在你可以在笔记本电脑的浏览器中访问 http://localhost:8888,并开始在深度学习机器上编辑笔记本!
这是所有的乡亲。有问题随时给我发信息!
一边训练 DL 模型一边烧 GPU?这些命令可以冷却它。
原文:https://towardsdatascience.com/burning-gpu-while-training-dl-model-these-commands-can-cool-it-down-9c658b31c171?source=collection_archive---------3-----------------------
我们经常用 Geforce GPU 做个人研究的深度学习模型训练,但是满载运行时 GPU 温度会高达 84°C!那不仅仅是在烧 GPU,更是在烧我们的心!
受一个来自**(中文版 Quora)* 的朋友的启发,他修改了 gpu 风扇速度来冷却 gpu,那是因为默认的 nvidia gpu 设置将 GPU 风扇速度限制在 70%或更低,我们必须手动改变 GPU 风扇速度来冷却它。*
PS:本教程应用了 GTX GPU 的 Ubuntu OS,请注意。
中文版本:
I also write this article in Chinese, here is Chinese version: 深度学习训练时 GPU 温度过高?几个命令,为你的 GPU 迅速降温。
如果您连接了显示器。
步骤 1:修改/etc/X11/xorg.conf 文件:
*sudo nano /etc/X11/xorg.conf*
步骤 2:将以下命令放入“设备部分”术语中:
*Section "Device"
Identifier "Device0"
Driver "nvidia"
VendorName "NVIDIA"
Option "Coolbits" "4"
EndSection*
第三步:重启你的机器。
步骤 4:输入以下命令:
*nvidia-settings -a “[gpu:0]/GPUFanControlState=1” -a “[fan:0]/GPUTargetFanSpeed=100”*
“gpuFanControlState=1”表示可以手动改变风扇转速,“[fan:0]”表示要设置哪个 GPU 风扇,“GPUTargetFanSpeed=100”表示将转速设置为 100%,但那样会很吵,可以选择 80%。
如果没有连接显示器。
我们经常使用 ssh 连接机器,所以机器不会连接显示器。但是上面的方法只有在你有显示器的时候才有效,所以我们必须做些什么来欺骗你的操作系统,让它认为你有显示器。
解决方案参考这篇文章:风扇转速无 X(无头):powermizer 掉卡到 p8 ,作者提供了一个改变风扇转速的脚本。下面是完整的步骤:
第一步:将这个 repo 克隆到这个目录:/opt
*cd /opt
git clone https://github.com/boris-dimitrov/set_gpu_fans_public*
这个回购包括这些文件,关键脚本是“cool_gpu”。
第二步:把文档的名字从“set_gpu_fans_public”改成“set-gpu-fans”,那是作者的小错别字。
sudo mv set_gpu_fans_public set-gpu-fans
步骤 3 : cd 到 set-gpu-fans 目录,并输入以下命令:
*cd /opt/set-gpu-fans
sudo tcsh
./cool_gpu >& controller.log &
tail -f controller.log*
它将启动冷却脚本,您可以看到以下过程:
测试时间:
在我们测试它是否可以冷却 gpu 之前,我们检查当前的温度。
现在大概是 37°C,好的,我们来运行一个模型,看看效果如何。
温度越来越高,当它变得稳定时,你可以看到最终温度:
哇,我们做到了!我们将 gpu 从 84°C 冷却到 67°C!那真的太牛逼了!
有一件事你应该知道,目前的 GPU 功率状态是 P2,这意味着它运行在高性能,最高的是 P0,最低的是 P12。这个冷却脚本工作得非常好,而且没有降低性能。
立正!冷却脚本的原始版本会降低 GPU 性能!
我们上面使用的脚本是原始脚本的改进版本,原始脚本在这里:设置风扇速度,不需要 X 服务器。
许多人使用原始脚本会导致性能下降的问题,它会将电源状态从 P2 下降到 P8,甚至 P12,所以我强烈建议不要使用原始的。但我们还是要对原剧本作者付出一定的尊重,没有他的作品我们无法改变粉丝速度。
如果你觉得这篇文章能帮到你,请点击心脏,分享给你的朋友!感谢阅读。
商业和数据科学——管理预期
原文:https://towardsdatascience.com/business-and-data-science-managing-expectations-2e34de8e078e?source=collection_archive---------6-----------------------
数据科学家的角色非常多样化,需要承担不同的职责,并对分析技能和商业敏锐性有着天生的偏好。难怪熟练的数据科学家被比作像独角兽一样稀有。
他们可能与神话中的人物不相上下,但对于企业和数据科学家来说,如果即使是最有才华的数据科学家也要蓬勃发展,期望必须是现实的,结构必须到位。
数据科学经理的角色
数据科学领导者的角色需要的技能不同于在管理或分析角色中获得的技能。这类经理必须对数据科学的理解既有深度又有广度,其中深度来自完整数据科学产品生命周期的第一手经验,即从头开始参与项目的实践经验。广度来自对数据科学领域的全面了解,这可以证明合格的管理者和杰出的分析师之间的重要区别。
如何将数据科学与商业战略相结合
起点——选择要分析的数据
首先,企业应该避免变得数据贪婪。一般的公司可能会产生大量的数据,但是从大量的数据中形成可操作的见解通常是不必要的耗时。出于这个原因,数据战略需要一种灵活的方法——一种持续评估数据点的方法,由公司中每个相关的利益相关者确定数据需求的优先级,而不仅仅是由数据科学家确定。
拥抱现实——准备投入必要的预算
数据科学可以代表公司的未来,因此企业必须对他们需要的人才和所需的预算持现实态度。举个例子,如果一家公司的数据量很大,那么管理数据的角色和分析数据的角色可能需要单独招聘。
雇佣前:退后一步,体会数据科学家的重要性
现实主义还必须延伸到评估你正在招聘的角色——数据科学家不仅要揭示洞察力,还要识别和解决问题领域。他们的角色是复杂的、紧迫的和具有挑战性的——您必须为他们提供在其角色中茁壮成长所需的业务支持结构。
数据科学家和企业如何更好地合作
1。沟通:促进团队合作
数据科学项目的成功依赖于可靠的沟通,团队必须具有凝聚力和协调性,其中最重要的是我们之前提到的那种罕见的天生的数据科学领导者。
2。驾驭商业直觉
企业是商业直觉和大量商业人才的家园,数据科学家一定不要害怕寻找这些人并利用他们的知识,这可以揭示客户、产品和市场。公司可以通过开放沟通渠道和为这些部门提供合作时间来帮助实现这一目标。
3。测量结果
你为什么要做你正在做的事情,成功的定义是什么?这些是在查看单一数据集之前必须回答的关键问题。根据您对成功的衡量,必须有一些指标来定义您的数据科学工作是否达到了您设定的所有目标,是令人沮丧地失败了,还是达到了两者之间的某个程度。
4。敏捷地工作
业务直觉和输入应该不断地为数据科学项目提供支持,随着洞察力的获得,这必须影响项目的下一步,如果要满足流畅的项目交付,敏捷工作是必不可少的。最小可行产品和短交付周期是关键。
5。创建一个分享知识的社区和文化
一个成功的数据科学项目始于并止于正确的人和正确的部门之间开放、健康和富有成效的关系,但如果没有一致的努力,这一切都不会发生。为了创造一种协作文化,必须培养这种文化——会议必须让所有人受益,让所有人参与——为关键利益相关者提供分享知识的机会——而不是让领导者简单地发号施令。
商业+数据科学
数据科学家被正确地放在一个基座上,受到高度尊重,能够成为更明智决策的核心,通过数据洞察提高生产力和商业方向。然而,利用数据科学家的商业优势不仅取决于对他们的现实期望,还取决于其他人的现实期望,特别是高级管理人员和领导团队。除了这种共生关系,还有将数据科学与业务战略相结合的挑战——这需要对数据有适当谨慎的偏好,因为数据贪婪可能会迅速吞噬项目成功的前景。
任何数据科学工作的战略性准备工作都与数据科学项目的具体细节一样重要,包括方法、数据集和模型。确保数据科学家与业务部门和其他核心部门的人员协作,是从组织未来的重大投资中获得最佳投资回报的关键。
数据科学中的商业直觉
原文:https://towardsdatascience.com/business-intuition-in-data-science-2744428d5e97?source=collection_archive---------4-----------------------
通常,当我们想到数据科学作业时,脑海中出现的主要内容是需要应用的算法技术。虽然这一点至关重要,但在典型的数据科学任务中,还有许多其他步骤需要同等关注。
典型的数据科学任务可分为以下几个阶段:
让我用一个简单的案例来解释一下:
有一个在线零售商,他在十一月,就在假期之前,举办一个购物节。它有一个 100 万种产品的目录和一个 1 亿名顾客的数据库,这些顾客过去都曾向它买过东西。
该零售商希望针对其客户群开展促销电子邮件活动。目标是运行一系列“成功的电子邮件活动”。
现在让我们来理解这项特殊任务的不同阶段:
1。 定义业务目标:
这是一个极其关键的阶段,因为对手头业务问题/目标的错误解释会导致错误的解决方案和不良结果。如果你仔细想想,数据科学的作用是使用数据和从中获得的见解来解决现实世界的问题。从这个角度来看,准确地识别问题和定义目标对于成功的结果至关重要。在本例中,营销人员希望向其每位客户发送定制的电子邮件,显示根据客户的偏好和品味整理的产品报价列表:
Source: https://www.remarkety.com/customer-segmentation-drives-better-product-recommendations
在这种情况下,为了定义业务目标,我们必须问几个问题:
a)我们是向 100 MM 客户的全部名单发送电子邮件,还是向一组精选的客户发送电子邮件?该零售商正在组织购物节,因此向所有 100 MM 客户发送电子邮件可能是有意义的,但仍需要考虑某些要点:
a.通过向所有客户发送大量电子邮件,会不会让一些客户不高兴,比如那些不主动向零售商购物的客户
b.由于我们希望向客户展示精选的产品列表(基于个人偏好),因此,如果将所有 100 MM 客户都考虑在内,我们可能最终会发现一组客户对任何产品都没有表现出很高的偏好(可能是因为他们没有在零售商那里购买足够多的产品,因此零售商没有足够的信息来了解他们的偏好)
c.有时,数据处理和存储成本也是一个考虑因素。处理 100 万客户及其特征,运行机器学习算法可能是相当时间和资源密集型的。虽然基础设施可以处理这种情况,但除了前两个考虑因素,排除一些客户可能是有意义的,特别是为了加快上市时间。
b)我们如何定义和量化成功指标?这是一个极其重要的决策,并且与业务目标直接相关。在上面的例子中,我们可以有一些可能的成功标准:
*a .活动的购买率(购买数量/发送的电子邮件数量):*该指标将给出活动在说服客户消费方面的效果。因此,如果零售商只关心整个活动带动了多少销售,那么这就是要追求的指标!
b.*活动的电子邮件打开率(打开的电子邮件数量/发送的电子邮件数量):*如果零售商想要了解其他因素,如电子邮件活动内容的有效性,具体来说,在这种情况下,电子邮件主题的“吸引人”程度,这可能很重要。同样,电子邮件点击率(打开电子邮件后,点击电子邮件中提供的网络链接,进入零售商的网站)显示了电子邮件内容的有效性。
c.*活动的盈利能力:*有时,零售商可能会对提高每位顾客的消费感兴趣,而不仅仅是让更多的顾客做出回应(即提高回应率)。请这样想——一项旨在推动越来越多的客户消费的活动,最终可能会吸引那些购买大量低价值产品的客户,而避开那些购买较少但购买高价值产品的客户。
**2。数据处理与分析:
这也是另一个非常重要的阶段,在这个阶段,我们详细了解我们可用的数据,以及我们如何使用这些数据来准确地解决手头的问题。
概括地说,这一阶段可以有以下步骤:
1.缺失值处理
2.异常值处理
3.数据分段
4.特征工程
让我们一个接一个地检查它们,以获得为什么需要这个步骤的直觉。在上述案例中,假设您从过去的促销电子邮件活动中获得了如下数据:
上面的数据是三个客户(这家在线零售商拥有 1 亿个客户)及其部分信息的快照。
可以看出,第二个顾客的性别是未知的。性别可能是强有力的信息,因此,如果很大比例的客户是“未知”或“失踪”的性别,那么我们将丢失一条非常重要的信息。有许多方法可以估算性别(通过称呼或姓名),因此可用于 缺失值处理。 同样,如果报告的年收入缺失(因为此信息仅由客户提供,他/她可能不愿意提供),我们可以使用过去 12 个月的支出来估算/预测年收入。
异常值处理 也很重要。例如,我们可以看到“过去 12 个月支出”或“年收入”的一些非常高的值。在支出的情况下,可能是因为某些客户的一次性高美元支出可能不会持续,并且可能会使整个数据产生偏差,因此将支出值限制在某个阈值(例如“过去 12 个月支出”的 99 或 95 百分位值)有助于减少这种偏差。
有时,我们可能会看到数据中有不同的客户群,他们的行为非常不同。例如,如果我们观察最近的客户(最近 6 个月成为在线零售商的会员),这些客户的行为方式可能与其他客户非常不同(他们可能非常好奇,因此电子邮件打开率可能非常高,但购买率可能很低)。因此,将这些客户与其他客户混合可能会使数据在某些参数上产生偏差,或者这些客户的特征可能会被其他客户所掩盖,从而降低他们在构建的任何预测算法中的代表性。在这种情况下,为这两个 【数据段】 (新客户和剩余客户)构建单独的算法可能是有意义的
特征工程: 特征或变量才是真正赋予算法预测能力的东西。因此,拥有正确的特征集是构建一个健壮算法的关键——因此关注特征工程。特征工程的类型:
- 特征选择:选择对问题最有用的特征子集。有许多特征选择算法,如基于相关性、信息值或其他特征重要性概念的评分算法。然而,随着越来越多的计算能力和机器学习技术,特征选择越来越多地在算法中处理。
- 特征构建:从原始数据手动构建新特征,例如,在上面的案例研究中,我们有一个特征“最后消费日期”,它本身可能不提供任何预测能力。但是,我们可以创建一个非常强大的功能“自上次消费后的天数”(最近消费过的客户可能有更高的再次消费意愿,因此可能对电子邮件报价更敏感)
- 特征提取:像图像、语音、文本这样的一些数据可以有多个特征,因此,通过特征提取,我们可以自动降低这些类型的特征的维数,并从数据中提取隐藏的特征。例如,在图像识别中,如下面的口袋妖怪图像,每个图像可以有数百个特征(像素)。因此,任何图像识别算法都必须处理来自多幅图像的大量特征。因此,该算法必须能够自动提取和减少这些大量的特征,以更小的一组有意义的特征。
3。建模与评估:
这是我们必须选择“正确的算法”来为我们的业务问题获得“正确的解决方案集”的步骤。如您所见,这是极其重要的一步,关键是找到最适合给定业务目标的算法。在上面的案例中,无需深入细节,我们有两组目标— (1)从 100 万个客户中找到响应度最高的一组客户—假设是 x (2)对于这 x 个客户列表中的每个客户,显示与他/她的偏好最相关的报价。对于第一个目标,我们需要一个响应预测算法(例如回归技术),该算法将给出每个客户的响应可能性分数/概率,然后可用于对客户进行排序,并为活动选择响应度最高的客户。对于目标(2)——发现客户的优惠偏好,我们需要能够帮助选择最有可能被客户偏好的产品优惠的算法(例如,推荐算法或分类技术)
一旦我们构建了算法,对它们的评估也是基于它们满足手头目标的程度。让我们通过上面的案例研究来理解这一点。假设我们已经建立了一个响应预测算法,该算法根据 1 亿名客户在看到电子邮件报价后购买产品的概率对他们进行排序:
现在,我们将这些 1 亿客户分成 10 个相等的桶,按照响应概率从高到低的降序排列。对于每一类客户,我们会查看他们对之前发送给所有 100 MM 客户的电子邮件促销活动的实际回复率:
Please note: the response here is product purchase after seeing the email offer
因此,为了实现目标 1,我们只需决定在哪个时段发送电子邮件报价。
现在,在上表中,您可以看到某些时段的“平均响应概率”和“实际响应率”之间存在差异,例如时段 3 和 4。因此,与实际值相比,预测值并不十分“准确”。但是,由于这里的目标是选择一组高响应可能性的客户,我们更关心该模型在响应方面对客户进行排序的情况。看一下实际的回复率,它似乎做得相当不错(过去活动的实际回复率也差不多是按降序排列的)。因此,在这里,模型结果评估更多地是围绕如何根据客户的响应概率而不是预测的准确性对客户进行排序。
然而,当我们评估第二个模型的结果时,预测准确性可能更重要,第二个模型给出了每个客户对每种产品的偏好得分。比方说,在上面的例子中,有 10 个产品报价。因此,我们建立了一个模型,为 10 种产品中的每一种给出每位顾客的偏好得分:
这里,客户 1 对报价 1、2 和 4 有更高的偏好。对于产品 3 和 5,由于偏好得分很低,我们可以假设他对这些产品没有任何偏好。类似地,我们可以说客户 2 没有表现出对任何特定产品的偏好。我们可以创建一个阈值分数,如果客户的分数高于该阈值,我们将考虑该偏好,否则不予考虑。因此,您可以在这里看到,我们正在根据分值进行此类评估,因此,获得反映客户真实偏好的准确分值非常重要。因此,在该模型评估中,预测精度非常重要。
**4。原型:
通过构建数据原型,我们的意思是创建必要的基础设施,以便在生产环境中实现解决方案。鉴于实施是一个时间和资源密集型过程,需要给予适当的考虑。在上述情况下,其中一些可能是:
- 这一电子邮件活动是一次性的营销活动还是更有规律的活动?如果是常规的,那么创建一个生产平台来执行这样的活动是有意义的。
- 对于这样一个平台,如何将来自不同来源的所有数据放在一起?需要从清理源数据所涉及的工作量和成本、更新频率、内部数据卫生检查和平衡等方面进行评估。
- 所有这些数据将如何存储和处理?这涉及到需要并行处理(如果数据量巨大)还是实时处理以及存储基础架构等决策。
- 电子邮件将如何发送?同样,需要做出的决策包括:是否需要第三方电子邮件交付供应商、客户数据隐私检查和平衡、上市速度(包括实时处理需求)等。
这是一些需要考虑的因素,但是根据任务的规模和复杂程度,可能还有许多其他需要评估和评价的事情。
因此,如您所见,数据科学任务是许多阶段的总和,需要领域专业知识、对业务目标的详细理解以及技术专业知识。二者缺一不可!!
想了解更多?参加由www.deeplearningtrack.com提供的为期 8 周的基于案例研究的数据科学课程
培养数据科学家的商业敏锐度
原文:https://towardsdatascience.com/business-knowledge-for-data-science-2aa458b6d988?source=collection_archive---------18-----------------------
Making business sense from data
很多次,我都被问到这样的问题,“我怎样才能在分析我的数据时有更多的‘商业意识’?”换句话说,我们如何知道从数据中获得的洞察力对业务是否有价值?
现在,对于一个精通数学和计算机科学的人来说,了解另一个世界——商业——可能非常具有挑战性。因为如果你在数学和计算机科学领域,你需要特别处理的术语、流程和知识,可以是业务规则和流程的不太严格、更复杂的叠加。对我来说,这就是做生意的乐趣所在。
这篇博文旨在帮助新数据科学家培养商业敏锐性,在某种程度上理解他们的见解能带来多大的影响。
商业知识可以分为三个层次。
1 —一般商业知识
2 —行业特定知识
3 —特定于公司的知识
让我们来看看其中的每一个。
一般商业知识
顾名思义,通用商业知识指的是跨业务的相同知识,不管是哪个行业或公司。例如,会计准则(GAAP 或 IAS),了解什么是应收账款、商品成本等。它可以是一般的战略管理模式,如平衡计分卡、SWOT 分析。它可以是对一般物流流程、制造等的理解。这样的知识和信息很可能在典型的 MBA 课程中找到,所以你可以通过与企业管理和经营相关的课程获得它们。
行业知识
行业特定知识将取决于企业所处的行业。例如,如果你在金融行业,你必须关注法规和合规,会计标准和风险管理标准,如国际财务报告准则,巴塞尔协议三等。从事金融行业时,还需要了解当地法规。诸如信用卡申请的最低年龄、监管机构设定的抵押贷款额度等规则是行业特定的。
如果你从事医疗保健行业,人体药物试验应该如何进行,所需的许可等也是特定行业的知识。
为了获取这些知识,我推荐商业周刊,如《彭博商业周刊》和《经济学人》。他们报告了行业的最新趋势,并对行业的影响进行了良好的分析。
公司具体知识
公司的具体知识包括你所在公司的竞争优势、商业模式、收入模式、目标市场、业务流程等。这些知识有些是“最高机密”,对于不同的公司有很大的不同。
一个可能的来源是存档并公开的财务报表。但是,公司特有的知识绝对不能在学校和项目中教授。这些知识通常只有在你加入公司后才能获得。
总之
一般的商业知识和特定行业的知识可以很容易地通过书籍、商业期刊和 MBA 项目获得,但特定公司的知识是无法教授的,当一个人在特定的组织/企业工作时,必须掌握这些知识。
如果这个博客对你有用,请鼓掌。我希望所有读者有一个有趣的数据科学学习之旅,并访问我的其他博客文章和 LinkedIn 个人资料。
业务流程管理符合数据科学
原文:https://towardsdatascience.com/business-process-management-meets-data-science-b4545f2886cb?source=collection_archive---------3-----------------------
从“业务流程管理”到“智能持续改进”的提升
数据科学是利用数学、统计学和数据可视化的相对较新的实践。过去十年,随着系统生成的数据量(即“大数据”)不断增加,这种做法应运而生
通过探索大量的数据,有可能发现和理解复杂的趋势和行为。通过更好地理解数据,人们可以做出更明智的决策。
例如,网飞从用户的搜索历史和观察列表中分析大量数据,以了解他们的习惯和兴趣。通过分析技术,他们能够猜测用户可能有兴趣观看的其他内容。由于强大的算法,网飞的建议是可能的。
这是大数据使用的第一个例子,可以用亚马逊、谷歌、多米诺骨牌(是的,比萨饼制造商)和美国宇航局的例子来补充,它们都使用自己的算法和方法来利用大数据。
应用领域非常广泛:在线销售、翻译、送货方向、宇宙探索等等。
数据科学的基础是统计学和数据可视化。
统计
1989 年,阿科夫通过定义一个层次结构:“数据—信息—知识”,展示了数据如何有助于构建知识。
统计工具对于从数据探索中获取知识非常有效。统计用于汇总对共享相同属性的对象的观察结果。将数学公式应用于这些观察结果,以生成关于该属性的数据。
例如,网飞存储了每个用户搜索或观看的电视节目的观察结果。这使得他们能够识别用户的兴趣。
数据可视化
描述性统计用于生成表格、图形、图表等形式的信息。通过图表表示的大量数据更容易阅读。数据科学家将使用这些图表来更好地理解他/她所分析的系统。
预测模型
应用于统计学的数学模型将允许数据科学家建立预测或建议。所以下一步,也是最有趣的一步是通过应用人工智能来建立预测。
数据科学可以用来解决的一些问题示例:
- 系统用户的习惯是什么?
- 给定数据在一段时间内的连续转换是什么?
- 商业活动有模式吗?
- 给定事件发生的概率是多少?
- 一个产品在未来一周的价格是多少?
为了“猜测”这些问题的答案,数据科学家收集系统产生的大量数据,并应用数学公式提取信息,以便了解某项业务活动。要确定认为某一事件将会发生是否合理,其思路是查看所有数据,确定先决条件,并检查它们当前是否得到满足。
业务流程管理
业务流程的定义基于业务和组织的模型。使用基于 BPM 的平台,自动化流程以创建基于流程的应用程序的开发人员可以完全控制世卫组织必须执行什么任务以及何时执行。
谁:特定最终用户(客户、员工)与流程交互的方式包含在流程定义中(通过用户界面:webforms、页面和门户)。
什么和什么时候:要完成的特定任务,以及这些任务的顺序,也是过程定义的一部分。
此外,通过流程应用程序生成的业务数据也可以在 BPMN 图模型中清楚地识别出来。
简而言之,BPM 旨在保证用户将按照预定义的顺序执行任务和更新数据,并且通常是在预定义的时限或截止日期内。业务规则由过程定义来实施。
数据科学应用于 BPM
由于 BPM 为用户活动(习惯)提供了受约束的工作流,自动化了数据转换,并确保按照预定义的顺序执行操作,数据科学能否从 BPM 应用程序生成的数据中回答特定的问题?
在这个挑战中面临的主要困难之一是业务流程产生的数据的异构性。每个使用 BPM 的项目都是不同的,可以属于不同的业务垂直领域(例如,电子学习、银行、教育、制造等)。
在 Bonitasoft,我们使用的数据来自实际项目的真实环境,当然是匿名的。这些数据可以帮助我们创建适用于许多垂直业务的强大算法。
我们期待数据科学提供从“业务流程管理”到“智能持续改进”的提升,使用预测模型的数据、算法和 BPM 结构来帮助增量和持续地进行更智能的业务改进。
业务转型:大数据分析如何帮助
原文:https://towardsdatascience.com/business-transformation-how-big-data-analytics-helps-f8460a1986d0?source=collection_archive---------4-----------------------
全球许多企业都在使用大数据分析来实施运营战略和促进业务转型。在 SAP 和英特尔的支持下,IDC 开展了一项调查,研究组织如何使用大数据和分析解决方案来促进业务转型和最佳实践。
IDC 有一个大数据成熟度模型,可用于根据五个参数评估组织:意图、数据、人员、流程和技术。该评估有助于确定其大数据和分析计划的有效性,并了解其进展程度。此外,可以就所述举措对各组织进行比较;这种比较可以进行基准测试,并揭示特定企业如何提高其分析成熟度和相关成功率。
分析和业务战略
在我之前的一篇文章— 大零售成功的大数据分析 —中,我讨论了数据在类型、数量和速度方面是如何演变的。这种快速发展可以归因于全球范围内业务流程的广泛数字化。
使用分析解决方案的实时数据分析使全球企业能够做出快速有效的商业决策。分析仅仅用于历史数据研究的日子已经一去不复返了。我们目前生活在一个时代,由于预测分析和高级数据科学的力量,企业拥有强大的前瞻性能力。
白皮书— 构建以分析为先的组织 —讨论了将分析嵌入组织 DNA 的重要性;在数字时代,数据驱动是维持业务增长的必要条件。大数据分析战略的有效部署是推动业务转型的关键,因为分析使组织能够跟上不断变化的业务需求和快速发展的技术格局。
大数据成熟度
大数据战略的成功取决于组织在分析部署、人员、技术、最佳实践等方面的成熟度。这种成熟度与组织借助大数据实现业务转型的能力成正比。
IDC 定义了五个阶段来确定组织在大数据业务方面的成熟度,以及为了进一步成熟可以采取的步骤。
- 临时:当业务需求出现时,大数据计划就会得到推动。缺少特定的分析部署模型,没有正确定义个人角色,并且缺少可衡量的资源分配方法。
- 机会主义:对商业目标有更清晰的理解。然而,在项目管理和资源分配方面仍然存在效率低下的问题。
- 可重复:为各种商业活动定义大数据战略。此外,有足够的预算分配和利益相关者的支持。
- 托管:分析部署模式和大数据战略更符合企业目标。建立了最佳实践,并通过上述策略持续产生了显著的投资回报。组织变得由数据驱动,分析成为其运营 DNA 的一部分。
- 优化:大数据和分析计划完全可操作化。有一个高效的卓越中心来管理这些计划。该组织使用颠覆性的部署模式和技术,在其市场上产生重大影响。现在的重点是创新和持续的业务转型,以实现前所未有的商业价值和影响。
大数据创新者
1,810 家组织参与了 IDC 的调查。IDC 报告称,在这些组织中,就大数据成熟度而言,只有 59 家属于“高级组织”类别。大数据创新者也属于这一类别;就上面讨论的成熟度框架而言,大部分创新者处于管理的阶段,而其他人正在接近跨越可重复的阶段,少数人几乎处于优化的阶段。
大数据创新者已经确定了支持业务转型的三大支柱— 盈利能力、高运营效率和以客户为中心。早期采用新兴技术将有助于简化和改进分析流程,进而提高运营效率和决策水平。此外,对实时数据的访问有助于组织更快地了解客户行为和需求,从而使他们领先于竞争对手一步。因此,它使他们能够真正根据不断变化的市场动态进行转型,提高客户保持率,并增加盈利能力。
大数据创新者在他们对数据和分析以及业务成果的基本观点和方法方面表现出许多相似之处。下面列出了一些最重要的相似之处:
- 大数据分析计划的投资回报产生得更快—在部署后的六个月内。
- 他们的数据质量很高,并且与业务目标相关。此外,他们的数据挖掘和仓储能力本质上是安全和及时的。
- 他们中的大多数都有针对大数据和分析项目的企业预算。
- 具有声音可视化、预测和实时功能的高级分析技术的采用率要高得多。这同样适用于数据管理技术。
- 从管理层到 IT 部门,各个组织级别都支持大数据和分析计划。
- 技术的不断进步被认为是培育业务转型和创新的必要条件。
技术和业务转型
分析项目的有效性和先进技术的采用率之间存在相关性。技术是业务转型的推动者;高级分析技术使组织在跟上不断变化的业务趋势和客户需求方面更加敏捷。
根据 IDC 调查,71%的大数据创新者使用具有高级预测和实时可视化功能的高级分析工具。因此,这种技术的使用给企业带来了竞争优势和培养更加以客户为中心的方法的能力。
日益增长的数字化将导致新数据源的产生,这意味着总会有更多的数据需要存储和分析。这使得从大数据项目中获取价值变得更加困难。因此,IDC 调查的 93%的组织处于大数据成熟度的机会阶段和可重复阶段也就不足为奇了。在这种情况下,技术主导的业务转型对于维持更高水平的大数据和分析成熟度至关重要。此外,应该通过确保不同数据管理系统对特定数据类型的可用性来改进数据仓库。
分析即服务
建立一个专门负责大数据运营的部门并不一定是每个企业日程的一部分。大多数公司要么缺乏必要的技术能力,要么不愿意对内部人才和资源进行必要的投资。由于分析即服务(AaaS ),这些公司仍然有能力成为数据驱动型企业。
分析服务提供商的出现使得先进的大数据和分析技术更加经济实惠、易于使用、用户友好,因此也更加大众化。此外,AaaS 有助于组织部署大数据和分析项目,最大限度地减少持续业务流程中的中断,从而实现无缝业务转型。
想想电影《变形金刚》中的大黄蜂,他在几秒钟内从一个普通的运动机器——雪佛兰科迈罗——变成了一个高效多面的外星机器人。这就是 AaaS 为企业所做的;这使他们能够更快地实现业务转型,而不会降低运营效率。
这篇文章最初出现在 BRIDGEi2i 博客上。
但是(k 最近的)邻居会怎么想呢?
原文:https://towardsdatascience.com/but-what-will-the-k-nearest-neighbors-think-a21f3f736898?source=collection_archive---------19-----------------------
构建一个 JavaScript 喜剧推荐引擎,探索 k 近邻的概念
我最近共同发表了关于机器学习的基础知识,这对我来说是一个非常新的话题。在研究该领域中使用的一些常见回归和分类算法时,我寻找了每种方法的实际用例。k-最近邻算法是最常见和最容易实现的方法之一,通常用于推荐我们产品的推荐引擎,学习我们的媒体消费习惯,并努力保持我们的点击、消费和购买。我很想了解这是如何工作的,并决定深入研究一下。
好吧,那么什么是推荐引擎呢?可以定义为基于用户过去的行为,用来培养对用户相关的产品或内容的一系列算法。当过去的行为不可用时,引擎可以默认基于整体用户数据或公司的利润考虑的一般化建议。我们都可能对到处跟踪我们的用户跟踪感到有点害怕,这种跟踪与我们的期望和需求有点太合拍了。好的推荐和霸道的用户体验之间只有一线之隔,但拥有一个有效的推荐引擎通常会改善用户体验,并转化为销量的增加。
推荐引擎有几种工作方式。简单的推荐者会跟随总体趋势,让用户了解他们产品的总体需求。更复杂的引擎将使用用户反馈——通过提交反馈或在线跟踪的有机用户行为——来将用户划分到简档中。在将用户基础分割成简档之后,新用户可以相对于现有用户被划分到那些简档之一中。符合相同简档的相似用户将可能享受相似的推荐。
好吧,那么 k 近邻会怎么处理这个呢?井 k-最近邻是一种分类和回归算法,它绘制整个训练数据集并分析数据点之间的距离。我们可以将距离视为相似性得分,它允许我们识别与任何一个标绘点最相似的数据点。生成该距离值的一个简单方法是计算两点之间的欧几里德距离,方法是对每对数据点之间的差求平方,对平方求和,然后求和的平方根。
与任何简单的方法一样,这也有缺点。特别是对于像用户评级这样的反馈,欧几里德距离将忽略用户反馈中的细微差别,例如每个用户的评级的整体范围。如果用户 1 评价很好,用户 2 评价很差,他们的评价不一定不相关。欧几里德距离不能校正这一点,并且会将它们的分数视为非常不同。Pearson correlation score 可以通过将所有用户评级绘制成一条线来寻找相关性而不是相似性来纠正这一点。这允许更细微的相似性得分。
使用 k-最近邻的另一个主要缺点是运行起来计算量很大。该算法利用了完整的训练集,在任何给定时间都可以处理大量数据。抵消这种情况的一种方法是创建预先生成的查找表,以简化计算并提高性能。
有许多技术(和替代方法)可以用来构建推荐引擎。毫不奇怪,Python 在数据科学家中很受欢迎,因为它有许多有用的库,所以是以这种方式处理数据的最常推荐的语言。然而,Java 中的 LibRec 也可以很好地工作。这个问题也可以用图论来解决。对于这种方法,通常推荐使用 GraphQL 和 Neo4j。
但是我们如何使用欧几里德距离和 k-最近邻来构建一个简单的推荐器呢?作为第一次尝试,我用 vanilla JS 构建了一个简单的喜剧推荐器。
首先你需要收集一些数据。出于我的目的,我随机生成了一组喜剧演员的用户评级。(因此,请记住…这些建议只有在随机生成的评级碰巧有效时才有效!)
The more data you have, the better you calculations will be. I kept it pretty simple at 100.
我在 HTML 评级提交表单上设置了一个监听器,收集所有用户提交的评级和相应的喜剧演员。我将数据集合发送到 findNearestNeighbors 函数中。它使用一个辅助函数来查找新用户数据和我的数据集中所有用户数据之间的欧几里德距离。它将生成新数据集的 5 个最近邻居,并将这些邻居的对象(以及新用户的评级)发送到我的 recommendNewComedians 函数。
I have saved a new attribute of simScore into our ratings object and sorted through it to find the ratings data with the highest similarity scores.
This helper method finds the similarity score between the new user and every other user and returns.
最后,我们查看五个最近的邻居,并平均出新用户不熟悉的每个喜剧演员的分数。然后对该数据进行排序,并将五个得分最高的新喜剧演员添加到推荐对象中,该对象将用于向用户呈现结果。
现在,我们可以基于最近邻评级来提供预期评级。为了更彻底,你可能想要做加权平均,权衡最近的邻居作为一个更有意义的反应。对于这个例子,我只是处理了一个简单的平均分数。
根据评分和评论来考虑推荐可能是最简单的,但是同样的过程也可以用于你收到的任何类型的用户反馈。想象一下重视用户交互,这样你就可以用它们来进行计算。如果电子商务平台中的用户多次访问相同的产品,将产品添加到购物车,或进行购买,这表明与该产品有积极的关联。而关闭一条建议则是负面联系的明显表现。这些类型的分数可以以同样的方式进行操作,以基于有机反馈进行推荐。
[## 从头开始构建推荐引擎的综合指南(Python 语言)
引言在当今世界,每个客户都面临着多种选择。例如,如果我在找一本书来…
www.analyticsvidhya.com](https://www.analyticsvidhya.com/blog/2018/06/comprehensive-guide-recommendation-engine-python/) [## 用图论在 JavaScript 中构建一个简单的推荐引擎
利用用户行为推动推荐
medium.com](https://medium.com/@keithwhor/using-graph-theory-to-build-a-simple-recommendation-engine-in-javascript-ec43394b35a3) [## 推荐引擎是如何工作的?又有什么好处?
购物是每个人的必需品,当我们购物时,它肯定是我们喜欢的产品或我们的…
www.marutitech.com](https://www.marutitech.com/recommendation-engine-benefits/)
自带设备:建立自己的数据集(免费使用网络抓取)
原文:https://towardsdatascience.com/byod-build-your-own-dataset-for-free-67133840dc85?source=collection_archive---------2-----------------------
十秒外卖: 了解如何通过简单的网络抓取创建自己的数据集,使用 python 的 beautiful soup 挖掘整个 Metacritic 网站的游戏评论,并免费托管在谷歌云平台(GCP)微(始终免费层)
有抱负的数据科学家总是对学习理论后的第一步感到困惑。他们能够应用积累的知识的地方很少。当然,有大量的数据集可用,但免费的数据集永远不会给你解决实际问题的务实见解,或者有时它们太小,无法用于深度学习应用程序。
获取强大数据集的一种方式是付费或注册昂贵的课程,另一种方式是网络抓取。在这里,我告诉你如何免费使用 python 抓取大型数据集!
为什么我选择了网络抓取和使用谷歌云?
- **数据变得陈旧:**当你搜集数据时,你可能会得到任何主题的最新数据。虽然你可以从 Kaggle 获得强大的数据集,但如果你想为你或你的公司创造一些新鲜的东西,比如说,抓取就是一种方法。如果你想为鞋子建立一个价格建议,你会想要来自亚马逊的最新趋势和价格,而不是两年前的数据。
- **可定制:**你可以定制代码,只从你想要的任何来源获取你需要的数据。
- 为什么不是本地的?由于云计算市场上有谷歌和亚马逊这样的大公司,出租一台电脑几个小时是非常便宜的。他们也给你一个免费层,这是完美的简单的东西,如网页抓取。GCP 稍微便宜一点,而且一开始会给你 300 美元的积分,所以我选择了 GCP。此外,我不希望我的 IP 被封锁(呵)
- 有趣:这是我对周五晚上的想法!
在我的例子中,我没有找到一个很新的游戏评论数据集,因为 Metacrtic 拥有最大的游戏库,并且会定期更新,所以我决定使用它。
入门
您所需要做的就是遍历 URL 列表,识别数据容器,提取数据并将其存储在 csv 中。
1。使用的库
import urllib2
import csv
from bs4 import BeautifulSoup
import pandas as pd
- urllib2 :我们的用于进行 url 请求的库。
- csv :以 csv 格式存储数据的库
- bs4 :漂亮的汤库,让从网页中提取数据变得非常容易。
- 熊猫:以漂亮的表格格式存储数据。
2。了解网站的流程
元符号布局非常简单。所有数据的结构如下
http://www.metacritic.com/browse/**游戏**/发布日期/可用/pc/metascore?view=detailed & page=1
让我们来分解一下:
- **http://www.metacritic.com/browse/**:是域
- **游戏:**这给出了子部分,并且可以被其他子部分的电影/音乐替换
- 可用/pc/ :此部分为 pc 提供数据。对于 ps4 游戏的数据,请将其更改为 ps4。
- metascore :这给出了根据元分数的排名,我们可以将其更改为“**user _ rating”**以根据用户评分获得数据。
- **view=detailed 😗* 这给出了我们选择的视图类型 detailed,因为它包含更多的数据,如流派和成熟度等级。
- page=x: 这给出了页码 x 。如果页码不存在,站点会返回一个没有数据的空白模板页面,并且不会抛出错误
接下来,我们决定包含数据的 html 元素。为此,我们使用 Chrome 中的检查工具。我们选择元素并突出显示子部分,以获得 html 元素及其类。
use the inspect button on the top right (circled) then highlight the area you want the HTML element for
the release data is in the element li and has class stat release_date
现在我们知道我们需要提取什么元素,让我们继续提取它们。
3。发出 URL 请求
metacritic_base = “http://www.metacritic.com/browse/games/release-date/available/pc/metascore?view=detailed&page="hdr= {‘Accept’: ‘text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8’, ‘User-Agent’ : “Magic Browser”}filepath=’/Users/rra/Downloads/’for i in range(0,54):
metacritic = metacritic_base+str(i)
page = urllib2.Request(metacritic, headers=hdr )
content = urllib2.urlopen(page).read()
Metacritic 有一个简单的站点布局,带有一个静态 URL,其中每个页面的页码都是变化的。
我们使用了 urllib2。请求请求页面和 Urllib2 。 urlopen 读取页面数据
提示:有 53 页,所以我把我的计数器的最大值设为 54,但是你可以简单地在一次尝试中包括所有这些,除了遇到错误时退出。
4。提取数据
然后我们读取数据
soup = BeautifulSoup(content, ‘html.parser’)
right_class=soup.find_all(‘div’, class_=’product_wrap’)
for item in right_class: try:
link=item.find(‘h3’, class_=”product_title”).find(“a”)
g=link.get(‘href’)
except: g=’' try:
score = item.find(“span”, class_=”metascore_w”)
s=score.text
except: s =’’ try:
dt = item.find("li", class_="release_date").find("span", class_="data")
d=dt.text
except: dt='' try:
rating=item.find("li",class_="stat maturity_rating").find("span", class_="data")
r= rating.text
except: r="" try:
pub =item.find("li",class_="stat publisher").find("span", class_="data")
p= pub.text
except: p=''
try:
genre= item.find("li",class_="stat genre").find("span", class_="data")
gr = genre.text
except: gr='' try:
user_score=item.find("span", class_="textscore")
u = user_score.text
except: u=''
我们使用 BeautifulSoup(content,' html.parser') 来完成解析大量 html 的所有繁重工作。
现在我们在上一节中看到,每个游戏数据都在一个 div 中,其中包含一个名为 product_wrap 的类。因此,我们提取所有这样的 div,并迭代每个 div 以获得数据。我们在这里存储以下数据:
- g:游戏名称
- 学生:metascore
- 发布日期
- 出版商
- r:安全等级
- u:用户评级
- gr:流派
提示 : HTML 不可靠,所以最好使用 try:除了切换每个提取
5。保存数据
game=[g,s,d,r,p,gr.strip(),u]
df = pd.DataFrame([game])
with open(filepath+'gamenames.csv', 'a') as f:
df.to_csv(f, header=False, index=False, quoting=csv.QUOTE_NONNUMERIC, sep="|")
我们使用 pandas 将 list 的列表转换成表格,然后将数据写入 csv。这里我们使用 | 作为分隔符,因为流派列包含**、**(逗号)
6。在谷歌云上运行代码
我想你应该知道如何开设一个 GCP 账户。如果现在,请跟随这篇博文学习如何做。您需要创建一个实例,如下所示。
Creating a GCP instance
一旦它运行,您需要在它上面安装 python,并将代码从您的本地机器复制到实例中。这里球形乌鸦是项目名称,实例-2 是实例名称。你还需要指定谷歌的时区。
提示:记得在 ssh 到实例后更新你的 ubuntu。
gcloud compute — project “spheric-crow” ssh — zone “us-east1-b” “instance-2”gcloud compute scp scrap.py instance-1:scrap
scp 将文件从本地机器复制到 GCP 实例。接下来,您需要在您的实例上安装上述库。接下来安装 byobu 这是一个基于文本的 windows 管理器。这将保持会话完整,即使您的 ssh 连接中断。
Sudo apt-get install byobu
byobu
byobu interface, you create separate tabs and run multiple code at the same time
最后使用下面的命令运行代码,就完成了。
python scrap.py
提示:您可以从我的 github 帐户中选择 scp 或简单的 git pull。
7。检索挖掘的数据
您可以再次使用 scp 从云中获取挖掘的数据,现在您有了一个非常酷的数据集可以使用了!
gcloud compute scp instance-1:scrap/game_review.csv /Users/
然后,您可以使用 python 作为
import pandas as pd
df= pd.read_csv(“/metacritic_scrap/gamenames.csv”, sep=”|”)
df.columns=[“game”, “metascore”,”release_date”, “maturity_rating”,”publisher”, “genre”, “user_rating”]
你的数据集看起来会像
看看这个结构有多好!
提示:你也可以自动完成这项工作!
提示和技巧
- **礼貌点:**大多数网站会反对你挖掘他们的内容,因为这会给他们的服务器带来很大压力。尽量避免在短时间内提出过多的请求,并阅读 robots.txt 文件。这里有一些尽可能减少错误的技巧:
- Sleep :包括 sleep ,在下一个请求发出前将代码延迟几秒钟。我更喜欢使用 sleep (randint(a,b)) 即使用随机整数而不是固定值。
from random import randint
from time import sleep
#pause for 20-100 seconds randomly
sleep(randint(20,100))
- 用户代理:是浏览器或 app 发送给你访问的每个网站的字符串。我们使用一个用户代理生成器来欺骗网站,让它认为请求来自不同的浏览器。由于许多机构使用同一个 IP,我们通常不会冒太多请求错误的风险。 这里的 是你可以使用的热门用户代理列表。
from user_agent import generate_user_agent
- VPN 和代理:如果你正在挖掘一个大的数据集,你最终会得到一个太多请求的错误。就我而言,大约每 2000 页。因此,为了应对这种情况,您可以轮换几个代理,并在每次实例运行时获得大约 5k 的页面。你可以在这里获得一些免费代理。
**2。陷入验证码中:**一些网站真的不想让你抓取他们的数据,他们会在适当的地方设置验证码。如果这是一个简单的 4-5 个字母数字的验证码,你可以尝试使用 Python 宇宙魔方和这种技术来破解。如果是谷歌重新验证码,你每次都要像这些人一样手动解决。
3。异常处理: HTML 非常不可靠,站点可能不会一直遵循严格的模式,所以最佳实践是在 try:except 语句中包含每个元素。
4.定期保存: Web 抓取是一项有风险的业务,如果您不定期保存数据,您可能会丢失迄今挖掘的整个数据集。一个简单的解决方案是定期将数据保存在 csv 中(像我一样)或使用 SQLite(像聪明人一样)。关于 sqlite 的介绍可以在这里找到。
下一步是什么?
我们可以使用相同的代码来挖掘其他内容负载的元符号,只需更改基本 url:
- 电影评论/评级
- 电视节目评论/收视率
- 音乐评论/评级
我扩展了我的代码,以挖掘大约 5k 个 PC 游戏的所有大约 100k 个用户评论的数据,并且我已经提到我将把它用于游戏推荐引擎(随后是博客帖子)。如果你想分一杯羹 发邮件 给我,我会给你发一部分数据集!
Metracritic 的网站布局非常容易理解,并且通过一个简单的 for 循环来复制,但对于挖掘更复杂的网站,如亚马逊,我们使用一个名为木偶师的浏览器自动化工具,它模拟点击来生成下一页等等。
看看艾玛德·艾山关于如何使用木偶师的博客。
这篇博客的全部代码可以在我的 git 上找到。用户评论抓取的完整代码也可以在这里找到。
在下一篇博客中,我将对这个伟大的数据集进行一些数据辩论和深度学习。敬请期待!
这是我的第一篇帖子,如果你喜欢,请评论并鼓掌:)
蛋糕架和纸鸟:Python 中的电子商务群组分析
原文:https://towardsdatascience.com/cakestands-paper-birdies-e-commerce-cohort-analysis-in-python-e33d0cf70dfc?source=collection_archive---------11-----------------------
英国在线零售商的数据清理和群组分析
随着电子商务继续快速增长,传统实体企业正专注于在线努力,以跟上亚马逊等领导者的步伐。沃尔玛最近进入和收购 Jet.com 极大地推动了增长,美国电子商务在 2018 年第二季度增长了 40%。
对于电子商务机构,群组分析在了解销售数字和客户方面发挥着重要作用。群组分析是指根据客户的购买日期或首次购买日期将客户分成“群组”。
然后可以跟踪每个群组的后续活动,以更深入地了解关键客户指标,如客户终身价值和保留率。客户终身价值是指在所有未来的互动中,你期望从该客户那里获得的总预期利润。留存率是指每个时间段后,原有客户留存的百分比。
通过这一分析,我希望解决两个关键问题:
- 你是如何解读和清洗电商数据的?
- 如何创建一个简单的群组分析来比较不同群组的指标?
这里使用的数据集来自于 UCI 数据仓库,包含了一家总部位于英国的销售全日礼品的无店铺零售店的 541,909 笔交易。注意,这个数据集的客户是批发商,而不是个人消费者。因此,超过 1000 件的订单量是合理的。
我们创建了一个新的“tot_order”列来表示订单总额,它只是单价和数量的乘积。
缺少值
现在我们已经知道了数据帧的样子,让我们用 missingno 检查丢失的值。
带有 missingno 的快速可视化显示,客户 id 有相当多的缺失字段。因为我们需要识别特定的客户,将他们放入队列中,我们将不得不放弃缺少客户 id 的订单。
负订单
看一下数量值也会发现一些负值。这些都可以解释为退款。让我们借此机会看看这些价值观告诉我们什么。
似乎 3 层蛋糕架是最常退款的项目。
然而,就退还的总货币价值而言,蛋糕架远远落后于纸小鸟和陶瓷储物罐。这个异常值将在下面进一步讨论。
由于在每个退款的原始数据帧中有匹配的购买,每月的总购买和收益不受影响。因此,这些退款不必取消。
极端值
看一下数量和单价的分布,可以发现大多数数值都是个位数。然而,订单数量和单价的异常值似乎分别高达 80,995 和 38,970。
通过快速过滤,我们发现异常值主要存在于每件价格在 1-2 英镑左右的小件商品中。最明显的异常值是发票号 581483。看来有人真的很喜欢精心制作的纸小鸟。
不过,从这个退款订单来看,可能没有那么多…
在离群值中似乎没有任何其他条目来暗示扭曲销售历史,尤其是当一些最大的门票都被取消时。
单价异常值怎么办?查看最高平均值会发现一些可疑的“产品”:
- 网络邮资
- 克鲁克委员会
- 指南
- 折扣
“网络邮费”似乎表明了顾客在邮费上的花费。平均 744,这是所有产品平均单价的 200 多倍。此外,邮费不是销售的直接指标,可能会扭曲不同人群的消费金额。似乎还有一个类似的标签“邮资”,我们也将删除。
“CRUK Commission”听起来像是支付给外部组织的费用,在谷歌上快速搜索一下,就会发现英国癌症研究所的相关结果。这可能是向癌症研究工作支付一些收益的倡议的一部分。由于这与销售没有直接关系,我们应该删除“CRUK 佣金”行。
“手册”是一个相当模糊的产品。手动的有 465 条记录,单条记录指挥单价 38970。由于我们没有关于这家在线零售公司运营的具体信息,我猜测‘人工’是指购买其他商品时提供的人工服务。这可能是枝形吊灯或仓库货架的设置。由于这些交易存在与个别产品销售不直接相关的显著异常值,我们也将删除“手动”记录。
“折扣”似乎是为售出产品提供折扣的一个不言自明的类别。所有这些交易都有负销售量,这一事实进一步证实了这一点。由于折扣与产品价格直接相关,并直接影响销售,我们将把它留在数据框架中。
销售总结
随着数据的大量清理,让我们来看看销售数字。
不出所料,英国占了销售额的大部分,因为这是一家位于英国的商店。
尽管有大量退款,cakestands 仍是总销售额最高的产品。
队列分析的准备
格雷格·瑞达(Greg Reda)令人惊讶的简单代码。对于群组分析,我们需要创建一些标签:
- 发票周期—单个交易/发票的年份和月份的字符串表示。
- 群组—客户首次购买的年份和月份的字符串表示。该标签在特定客户的所有发票上通用。
- 群组周期——客户“生命周期”阶段的整数表示。该数字表示自第一次购买以来经过的月数。
发票期
基于发票日期创建新列的简单 strftime 函数就足够了。
同组
对于群组标签,我们试图找到顾客第一次购买的日期。我们首先根据客户 id 对数据帧进行重新索引,并根据索引进行分组。
接下来,我们找到最小发票日期,它应该代表第一张记录的发票。应用相同的 strftime 函数,因此客户的所有发票都具有相同的群组标签。
之后别忘了重置索引!
聚合指标
在我们创建群组期间之前,让我们根据 invoice_period 和 Groupon _ group 标签对数据帧进行分组。
我们通过客户和产品的唯一 id 和描述来统计一段时间内售出的客户和产品的总数。然后,我们将销售数量和总发票金额相加,得到该期间的总销售额。
同期期
对于群组分析,必须确定该客户一生中的购买行为。例如,如果客户在 5 个月前加入,我们需要从 1 到 5 的标签来识别每个月的指标。
我们首先通过“群组 _ 群组”对先前的群组对象进行分组来创建该标签。然后我们找出每个组的长度,并用 np.arange()创建一个列表来表示这个范围。例如,np.arange(5)返回[0,1,2,3,4]。
因为我们希望这个列表从 1 开始,所以我们给这个范围内的每个数字加 1。
跨群组的销售汇总
虽然不完全具有代表性,因为这些只是一年的销售数字,但很明显,2010 年至 2012 年第一批的客户数量和销售数字要高得多。理解这一群体的一种更有代表性的方式是,他们是之前与这家商店有过关系的现有顾客。因此,他们自然会表现出更高的客户参与度和活跃度。
这家在线零售商的销售背后似乎还有一个轻微的季节性因素。第一季度和最后一个季度的初始购买量较高。同样,2010 年至 2012 年的采购也表明这两个季度的活动增加。由于大多数产品都是礼品,这种增加的活动可以归因于这些时间段所代表的假日季节。
跨群组的保留率
纵观各队列的保留率,可以看出 2010-2012 年队列的持续参与度很高。由于这些都是现有客户,这是很直观的。
在第一次交易后,后续群组的保留率几乎立即下降到 20%左右。季节性的影响对于 2011 年至 2011 年的发票期尤为明显。在本发票期内,所有组别的保留数字都是最强的,回到了 30%左右。假期的积极影响似乎在这里得到了很好的支持。
改进和后续行动
- 如上所述,这是一个相当有限的数据集,因为它只包含一年的交易数据。如果能获得更长时间的数据,队列分析会更有价值。
- 除了季节性和节假日期间,没有关于可能影响销售和保留率的业务特定事件的进一步信息。如果有广告活动或新产品发布的数据,看看销售是否会受到不同人群的影响,那将会很有意思。
- 考虑到缺少客户 id,大约四分之一的初始数据集被丢弃。有些包含有趣的变量,如亚马逊费用,可能会影响每月的销售数字。
- 有一些大客户的账户,他们可以很好地转化为一些帕累托图(即将推出)。
- 有了更详细的数据集,我愿意尝试一些终生客户价值分析和预测。如果有任何关于数据集的建议,请发送给我!
感谢阅读!代码可以在这里找到,也可以在 LinkedIn 上自由连接!