TowardsDataScience-博客中文翻译-2016-2018-一百零一-

61 阅读1小时+

TowardsDataScience 博客中文翻译 2016~2018(一百零一)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

电子商务:如何利用统计数据增加销售额?

原文:towardsdatascience.com/ecommerce-h…

Photo by Bench Accounting on Unsplash

销售分析中的回归分析和聚类案例。

在前一部分,我们看了一下电子商务商店的表现。我们从虚荣 KPI(会话)和相当好的业务 KPI(交易)的组合开始。它有着相当有趣的关系。

Number of sessions (horizontal axis, blurred) by number of transactions (vertical axis)

如何弄清楚数据的意义并理解其中的关系?在前一部分,我们探讨了相关性,这导致了更多的问题。下一步将涉及两种统计方法的使用:回归分析和聚类。

预测销售额—回归分析 在统计建模中,回归分析是估计变量之间关系的统计过程。这正是我们正在寻找的。

我们将使用 Python 和 stat 模型库构建一个模型,根据会话数预测事务数。

模型的结果可以表示为一条直线(线性回归)。

Predicting number of transactions based on number of sessions

我们的模型面临两个直接挑战。逻辑上讲不通。它无法解释没有会话或会话数量非常少的情况。如果会话等于零,模型预测有四个事务(截距值为 3.99)。 2。 R 平方值为 0.232 。我们的模型只解释了*23%*的数据可变性。这使得 77%的数据无法解释,从商业角度来看这是不可接受的。

让我们尝试调整我们的模型,以适应会话数量较少的情况。我们将强制截距等于零(零会话意味着零事务):

新模型在逻辑上更有意义,但*明显更差。*它只解释了 13%的数据可变性,令人失望。我们总是可以尝试通过使用不同的回归分析方法来改进 r 平方参数,如套索梯度下降而不是最小二乘法),但这超出了本文的范围。我们将探索另一种有趣的方法。

了解受众——聚类分析 聚类分析或聚类是对一组对象进行分组的任务,使得同一组(称为聚类)中的对象彼此之间比其他组(聚类)中的对象更相似(在某种意义上)。

为什么这对电子商务很重要?没有一般的用户或客户。相反,我们可以试着区分有一些共同点的不同群体(集群)。

我们通过将数据集分成几个不同的组来说明聚类的概念:

Examples of clusters

我们可以使用像 SPSS 或 BigML 这样的统计软件包来处理数据。

在下面的例子中,我们采用了两个变量:会话数和事务数。集群的数量被设置为四个。每个圆圈代表一个集群,大小代表其中的实例数量。

Diagram showing distance between clusters — level of similarity.

在这个简化的示例中,我们已经完成了四个集群。虽然它不会提供丰富的见解,但它将有助于理解集群的概念。

以上四个聚类可能比回归分析更能解释我们的受众。例如,聚类 2(非常高的事务数)是由回归分析没有捕捉到的异常值组成的。

每个集群由多个参数描述:实例(观察)的数量、事务和会话的中心点。集群中的所有实例都与他的中心点相关。直方图中显示了距该点的距离。

从聚类分析中获得洞察力。现实生活场景。

拥有行业知识会有所帮助。良好实践将要求在分析中包含更多相关数据。我们应该从哪里开始?我们可能要考虑以下变量: ——客户获取方式(付费、电子邮件、社交等)。), -交易明细(如产品类别)

Adding more variables may brings better insights

聚类分析是一种很好的平衡行为。我们的目标是更好地了解电子商务受众,同时我们试图保持集群数量较低,并确保它们具有商业意义。

下一个问题:我们能根据过去的业绩预测未来的销售吗?

回到第 1 部分——揭开虚荣心 KPI 的神秘面纱

糟糕的地址每年给印度造成 100-140 亿美元的损失

原文:towardsdatascience.com/economic-im…

对于新兴经济体来说,无组织、结构不良的寻址系统是主要的经济负担。我们估计,糟糕的地址每年给印度造成 100-140 亿美元的损失,约占 GDP 的 0.5%。

本文大图最初出现在麻省理工学院的(【MITs】)新兴世界博客

在地球上的 70 亿居民中,大约有 40 亿[1]没有合适的地址,无法在地图上以合理的精度定位他们的房屋、财产或企业。举例来说,考虑我们的一个作者在两个不同大陆的两个地址:

Figure 1: Every place needs an address. Crowded Old Delhi seen from the Jama Masjid. Photo Credit — Erik Torner

  • 在美国:【名称】,7116 Via Correto Dr,Austin,TX 78749:该地址的位置很容易找到,任何导航系统都可以在白天或晚上将您带到家门口;或好或坏的天气!这是一个结构化地址的例子。
  • 在印度:【姓名】,蒂拉学院,PO Agartala 学院,Agartala 799004:谷歌地图将这个地址解析为大约 76 平方公里的区域。公里。在阿加尔塔拉城。这个地址是非结构化的。
  • 在上面的地址上添加一个地标,“蒂拉学院靠近蒂拉学院湖,..”将答案缩小到大约 3 平方公里。公里。到达目的地后,根据对居住者、房子或位置了解的详细程度,如果不是深夜或下雨,还需要 15-45 分钟。此外,基于地标的寻址是不常见的、不完整的并且也是不一致的。

Figure 2: Most addresses in the developed world resolves within a narrow area, where those in India can resolve anywhere from town to a locality to (rarely) at a house level

这些不仅仅是造成不便的一次性体验。无法为每个地址提供准确的位置,在许多方面影响了居民的生活。它抑制了当地行业的发展,如沙龙、面包店或小吃摊。它降低了便利设施的可用性,如创建银行账户和交付货物和服务(如电子商务),并延误了消防队和救护车等紧急服务。

对工业的经济影响

案例研究 1:物流和运输

如前一个示例所示,无法在合理的准确度内定位地址会影响运输商按时交付货物的能力。考虑一下电子商务行业,或者任何一个把商品送到一个地址的行业。在没有适当的地理编码的情况下,印度的大多数公司通过 PIN 码(PIN 代表“邮政索引号”)对包裹或货物进行“分类”,因为 PIN 码是在印度大多数书面地址中出现的唯一数字位置描述。

虽然按密码对交货和设施(存储交货和退货的货物)进行分类听起来是一个逻辑上可行的解决方案,但它有两个主要的实际问题:

  • 在印度,大约 30–40%[2]的 pin 码书写不正确,导致货件发送路线错误,需要人工干预才能发送到正确的 pin 码
  • 一个密码的平均面积约为 179 平方英尺。公里。约有 135,000 个家庭和 100,000 多个商业、教育机构、政府建筑等。对超过 25 万个地址的可交付内容进行排序,其中只有 30%的地址是结构化的,这带来了许多挑战。

我们将选择物流和运输行业中的一个领域来详细说明这些挑战。考虑一个电子商务,它正在以 30 CAGR【3】的速度增长,受收入、消费和数字化【4】增长的驱动,并且在可预见的未来预计将继续如此。印度消费者希望产品免费送货上门,这给电子商务公司带来了独特的负担,这在世界上大多数地方是看不到的。

当一个电子商务网站的产品在网上订购时,商品从卖家或仓库被取走,并被送到加工厂,在那里被分拣到目的地城市,这一过程被称为“第一英里操作”。然后在始发地和目的地城市之间进行长途运输。在“最后一英里操作”中,商品被送到配送中心,从那里被送到购物者的家里。图 3 展示了这个过程。

Figure 3: The “last mile cost” in India is ~30% of the total cost of delivery

在西方国家,结构化地址导致相对准确的地理编码,因此最后一英里的成本约为总成本的 10–12%[5]。在印度,同样的费用约占配送总成本的 30%;尽管印度的劳动力成本很低。额外的成本来自于司机在定位一个地址时所花费的更长的时间——多次停下来给收件人打电话或向路上的人问路,以及为寻找正确的位置而额外驾驶。

图 4。说明了向无法在内部消除歧义的地址发送邮件所面临的挑战。在缺少所需地址的经度的情况下,基于密码对地址进行分类,并且对一个密码的所有包裹进行分类、存储并从一个(或者有时是两个或更多个)递送中心进行递送。位于橙色 pin 位置的典型的基于 pin 码的分拣中心可以有 4-20 公里的递送“范围”(半径)。在缺乏对基于地址的负载分布的理解的情况下,这种中心的位置往往是不平衡的。例如,在这种情况下,一名送货骑车人行驶了大约 22 公里,而另一名骑车人行驶了大约 104 公里,几乎是第一名骑车人行驶距离的 5 倍。这些问题严重阻碍了这些中心提高生产率和降低成本的举措。

Figure 4: The difference between a pincode-based sorting and local-address-based sorting. In this picture, the light orange area shows a typical pincode boundary. In this delivery center productivity can vary widely as optimal route planning becomes complex, as depicted by two delivery bikers’ routes

另一方面,如果地址可以在家庭一级消除歧义,那么每个地方都可以有一个小的递送中心。在这种情况下,配送中心的平均“行程”会下降到 1-3 公里。在图 4 中,这种小型交付中心的位置用红色大头针表示,它们覆盖的区域用黄色表示。这使得能够进行基于地址的分拣的较小中心的生产率显著提高。

此外,地址地理编码的粒度更大,也使我们能够执行路线优化,并为快递员提供系统驱动的路线。我们以 Delhivery 为例,它是印度领先的电子商务公司物流供应商之一。

在 Delhivery,根据地址的类型/复杂性和地区的大小/形状,从基于密码的分拣转换到基于地区的分拣,将最后一英里操作的生产率提高了 40–60%。

Table 1: An address-based sorting can result in a 40–60% better productivity

这种最后一英里的高成本不成比例地影响了公司的底线。在表 2 中的一个简单分析中,我们证明了一个更好的地理编码可以将最后一英里的成本降低 40%,完全在当前技术的范围内,可以提高电子商务公司的盈利能力。

Table 2: Illustration: An improvement in the last mile cost can swing the profitability of an e-commerce business

即使对于印度的一个小行业,如电子商务交付,估计每年有 50 亿卢比(约 7 . 75 亿美元)的业务(截至 2017 年),更好的寻址方案每年可以节省约 65 亿卢比(约 1 亿美元)的成本。

对于物流和运输行业,同一框架可用于不同类型的货物和服务运输。即使在城市间运输的情况下,第一英里(例如,从客户或配送中心提货)或最后一英里(送货到户或企业)的交付都会受到无法解析地址的严重影响。

案例研究 2:贷款和金融服务

印度是一个信用匮乏的国家,有 6.42 亿人(高达 53%)被排除在正规金融产品之外,如贷款、保险和其他形式的信贷和金融服务。这对经济的影响是巨大的。麦肯锡估计,到 2025 年,印度数字金融服务的回报可以达到 7000 亿美元,并且可以额外创造 2100 万个工作岗位。

缺乏信用的原因有很多:缺乏可验证的身份(类似于美国的社会安全号码),在一个主要由现金驱动的经济中缺乏正式收入的证明,以及消除一个人的位置(无论是家庭还是工作场所)的复杂性。

因此,在过去两年中,在金融科技公司(fintech)的大型风险投资的资助下,100 多家初创公司开始提供连接借款人和贷款人的服务。

图 5 显示了这类服务之一承诺的典型流程。这个过程相当简单。一旦用户在线或通过应用程序申请并选择产品,他们通常会被要求提供 5-8 套文件,包括身份证明、地址、年龄和收入、教育资格、就业证明文件和银行对账单。

Figure 5: Typical loan generation process promised by one of India’s many digital loan or financing start-ups

信使从借书人那里取走这些文件。然后,这些文件(主要是纸质文件)经过扫描和代码转换,使用光学字符识别(OCR)保存在数据库中,并与借款人在贷款申请中提供的信息进行比较。

这一过程对大约 60%—70%的借款人非常有效,尤其是在大城市。根据我们对领先公司的调查,我们估计大约 70%的文档被认为是“匹配的”,并进入贷款处理的下一步,例如贷款资格分析、贷款批准等。,尽管只有一定比例的申请人有资格获得贷款。

然而,对于大约 30%的申请,申请人在申请中提供的地址与文件不符。要理解为什么,请考虑图 6 中同一栋房子的以下地址。

Figure 6: Same address written in multiple formats in different documents

替换为:对于同一地址:a)门牌号写为“TH-146B”、“146”、“146 单元”。b)该社区被称为"普尔瓦公园岭"和"普尔瓦公园岭",也简称为" PPR "。c)道路名称以两种方式拼写为“Goshala Road”和“Ghosala Road ”,其中一种完全省略。d)该地区被称为“哥鲁达查帕利亚”和“哥鲁达查帕利亚”。

换句话说,仅仅四个不同来源的官方地址验证文档就可以产生超过 50 种组合。因此,文件中提供的地址经常不匹配也就不足为奇了。由于这些信息的处理发生在一个集中的设施中,那里的人们不会知道“普尔瓦公园岭”和“PPR”是同一个社区。

对于 30%不匹配的文档,下面的过程开始,如图 7 所示。

Figure 7: 30% of the applicants whose addresses do not match directly are either asked for additional documentations or have their addresses manually verified, adding to the time and cost for the service providers

这导致贷款审批延迟,最好的情况下会延迟 5 天,有时甚至会延迟几周或几个月。这既影响了借款人,他可能急需用钱;而贷款人必须承担他在贷款最终处理之前本可以赚取的利息损失以及额外验证的成本。

Table 3: Bad addresses delay verification and approval resulting in the loss of interest to moneylenders

此外,居住地或企业是贷款风险评估过程中的一个关键因素,无法消除这一点在风险模型中表现出来,从而提高了利率,进而提高了贷款的总成本。

泛印度经济影响

我们对排名前三的行业——物流、制造业(包括消费品)和应急服务进行了类似的分析,得出了印度的成本估算。使用这种方法,我们的估计表明,不良地址每年花费印度 100-140 亿美元,约占 GDP 的 0.5%;参见表 4。

Table 4: The economic cost of bad addresses in India

还要注意的是,表 4 中的数字反映了不良地址的成本,但不包括拥有更好地址的额外好处,如生产率和收入的提高,这将导致企业和 GDP 的进一步增长等。

结论

容易被发现的地址对于像印度这样快速发展的经济体来说非常重要。地址不仅仅是一种便利,它对于推动自我强化的经济循环,进而改善下一个 10 亿印度人的生活和收入至关重要。消费者为了自己的方便而独立地识别和采用地址,而企业使用技术或第三方服务将这些地址解析成地理编码,以降低的成本交付产品和服务。

我们的案例研究分析表明,缺乏良好的寻址系统每年给印度造成至少 100-140 亿美元的损失,相当于其年度国内生产总值的 0.5%。随着印度经济在经济产出以及各种新业务和服务方面的持续增长,由于缺乏适当的寻址系统而导致的成本将显著增加。因此,印度需要考虑一种全新的方法来实现寻址系统的现代化,以提高效率。

参考

[1]40 亿人没有地址。机器学习可以改变这种情况

[2]样本来自 Delhivery 的 1000 万个地址的数据库

[3]摩根士丹利押注数字预测 6 万亿美元经济,Sensex 在 1,30000https://www . Bloomberg quint . com/markets/2017/09/28/mor gan-Stanley-Bets-On-Digital-To-Forecast-6 万亿美元经济-sensex-at-130000

[4]摩根士丹利报告《印度的数字未来》【www.morganstanley.com/ideas/digit…

[5]与亚马逊、联邦快递和史泰博电子商务的多个利益相关方的私人谈话

[6]数字金融如何促进新兴经济体的增长(2016 年 9 月)https://www . McKinsey . com/global-themes/employment-and-growth/How-digital-finance-can-boost-growth-in-emerging-economies

关于作者:

Santa nu Bhattacharya 博士是 Airtel 的首席数据科学家,Airtel 是全球最大的电信公司之一,拥有 4.5 亿多用户。他是一位连续创业家,曾在脸书 a 引领新兴市场手机,他是美国国家航空航天局戈达德太空飞行中心的前物理学家,也是麻省理工学院媒体实验室的合作者

Sai Sri Sathya 是麻省理工学院媒体实验室 REDX 和 Camera Culture Group 的合作研究员,之前在脸书的连通性实验室工作,专注于新兴世界的创新。他是一家致力于在边缘实现人工智能民主化的秘密模式初创公司的创始人

Kabir rusto gi 博士领导着印度最大的电子商务物流公司 Delhivery 的数据科学团队。他是一位已经出版的作者,之前是英国格林威治大学运筹学的高级讲师。

Ramesh Raskar 教授是麻省理工学院媒体实验室的副教授,领导麻省理工学院新兴世界项目,该项目旨在利用全球数字平台解决重大社会问题。

编辑命运

原文:towardsdatascience.com/editing-fat…

在世界将继续见证的所有技术进步中,就造福人类而言,很少能超过生命科学领域的突破:生物技术、流行病学和医学,仅举几例。与这些领域相关的行业,如医疗设备和药品,在未来几十年将继续经历巨大的变化。这一切都归功于允许模拟新药对身体的影响、加速化学化合物验证测试、甚至人类基因编辑的创新。

最近,通过对遗传密码具有重复出现的 DNA 序列的微生物和细菌的研究,为遗传学领域历史上最伟大的革命之一奠定了基础。这些重复被来自病毒的遗传物质片段打断,这些片段在被研究的有机体生命的某个时刻试图攻击原始细胞。这些片段作为细胞防御系统的“记忆”工作,因为它们存储了“侵略者”的身份。这种间断重复的配置被称为聚集的规则间隔的短回文重复(CRISPR,读作“crisper”)。当与一组被称为“Cas”的酶结合时,重复之间的“空间”中的遗传物质——即入侵病毒的遗传物质——可以用来引导酶,以便切除病毒并将其中和。

重大的革命在于科学家通过这种方法获得了在所需位置精确切割任何 DNA 序列的能力——并用新的预定义序列替换提取的序列。也就是说,可以更有效地研究由各种基因组变化引起的复杂疾病,最终可以在造成任何伤害之前解决许多遗传问题。多亏了这种新技术,以前科学上从未有过的程序变得触手可及。根据 Grand View Research 2017 年 3 月的一份报告,到 2025 年,基因组编辑市场估计将超过 80 亿美元。

在 2015 年 7 月为《新英格兰医学杂志》发表的一篇文章中,哈佛医学院和麻省理工学院的教员埃里克·s·兰德博士警告说,“编写”新的遗传密码(特别是在人类胚胎中)存在伦理风险。他还强调了一旦完全掌握这项技术,可以从这项技术中获得的好处。Lander 博士提到了一些例子,如与艾滋病相关的 HIV 病毒,它不会影响缺失 CCR5 基因的人。理论上,“删除”这种基因可以赋予特定生物体免疫力。血友病也可以通过编辑血液干细胞来解决,就像使视网膜细胞中的特定基因失活很可能防止某些类型的遗传性失明一样。

但是改变自然强加的生物现实的方法并不局限于 CRISPR 技术。通过采用三种现代项目发展趋势——创客运动(在这种运动中,企业家社区不是获得现成的设备,而是从现有的设备中创建自己的工具),开放架构(通过这种方式,信息可以在社区中自由共享)和开放设计(允许世界不同地区的人工作和修改特定的项目)—医生、工程师、设计师、家庭和患者通过 e-NABLE 网络参与创建假肢的过程。使用相对容易获得的设备和 3D 打印机渲染最终结果,可以为各种身体部位——手、下巴、腿——生产定制的假肢。下次我们将讨论这个话题:三维打印技术对行业和消费者的影响。到时候见。

对企业进行人工智能教育

原文:towardsdatascience.com/educating-t…

采用人工智能的最大障碍是缺乏知识。企业公司和其他生态系统参与者需要学习什么?

很容易说,人工智能(AI)承诺的每个行业的变革都被夸大了。人工智能的嗡嗡声从过多的商业文章延伸到消费者意识。在科技科学领域的杰出人物甚至表达了对其快速扩散的担忧。

公司无视炒作,后果自负。机器学习和其他应用的人工智能解决方案确实对各行各业的企业产生了变革性的影响,早期采用者比那些只是涉猎的人看到了更多的价值。2017 年麦肯锡全球研究所的一项研究发现,公司对人工智能越熟悉,他们在业务中看到的机会就越多。考虑新的收入来源,而不仅仅是更多部门的成本节约。

那么,是什么阻碍了许多公司的发展呢?有几个因素,但更广泛采用的两个最大障碍是访问知识

在技术采用曲线的早期阶段,访问问题是常见的——干净、全面的解决方案仍然稀缺和昂贵,并且很少有供应商有跟踪记录。这一挑战现在正受到初创公司和老牌公司的机会主义者的猛烈攻击。有些在增加价值,但许多没有。你可以在各种细分评论厂商列表中观看他们的潮起潮落。

但是,光有渠道是不够的。从人工智能中实现价值最大化需要一种不同的思考问题和数据的方式。为了利用即将出现的新工具,需要应对几个挑战,而大企业无法独自克服这些挑战。

革命意味着快速变化

有些人会争辩说,我们以前也遇到过这种情况。第三次工业革命带来了无处不在的廉价计算,这是一场自 20 世纪 80 年代以来几乎没有减弱的重大技术驱动的剧变。行业已经采用和适应;有赢家也有输家。为什么当前的进步不是一种自然的进展,而是一些新的东西?

首先,数字时代的变化速度非常快。研究人员几乎一致认为,未来十年,世界数据至少每两年翻一倍。随着存储变得越来越便宜,各种设备越来越互联,产生数据来填充存储,增长率可能会加快。

数据的膨胀给各种规模和各种行业的企业带来了压力,造成了做某事的紧迫性。事实证明,做某件事很难,有几个原因。

首先,我们有前面介绍的访问问题。许多可供企业用来从数据中获得洞察力的人工智能工具仍处于研究阶段。一个典型的商业用户可以利用的人工智能应用是针对非常狭窄的用例,尽管如此,仍然可能是复杂和昂贵的。增加灵活性意味着建立一个团队,从头开始开发自己的应用程序。

但这导致了另一个问题:培训赶不上需求,人工智能专业知识的人才库很浅。虽然关于今天是否真的缺乏数据科学家的辩论,但这种辩论通常不会扩展到产品经理、运营团队和商业策略师的需求,他们知道如何以及何时应该利用人工智能来为自己服务。这整个生态系统的商业职能谁是人工智能意识是其成功应用的关键,而这种集体意识是很难实现的。

即使一家公司能够组建自己的跨职能人工智能团队,留住他们也可能是一场斗争。尤其是在拥有新生数字能力的组织中,拥抱人工智能所必需的文化和流程转型可能会来得很慢。也许数据丢失了,或者必要的数据规程丢失了。有时组织认为他们需要人工智能,但实际上只需要数据分析。或者,人工智能可能被视为对其他人工作的威胁,给办公室政治增加了一个新的困难层面。对于人工智能团队来说,这些情况会导致幻灭或沮丧,并最终导致减员。

工业界需要重返校园

对于希望利用人工智能的组织来说,让公司获得最新的工具和技术并不是银弹。相反,我们需要给人们提供他们需要的信息,以做出正确的决定,即人工智能可以在哪里帮助他们,以及如何在这个新的商业环境中进行批判性思考。知识是关键。

然而,大公司无法独自应对这一挑战。有几个不同的小组需要共同努力,以提高商业生态系统中的人工智能意识水平,每个小组都需要不同类型的知识。让我们来看看这些小组在努力建立对成功概念的理解时应该问自己的一些问题。

企业需要重新思考他们的商业模式

虽然他们可以自己创新,但在食物链的顶端,最大的组织往往是新技术的消费者。他们受益最大的是了解全局,以及推动其行业或部门职能的决策和方向的基本细节。因此,企业团队需要能够回答几个关键问题:

  • 人工智能有哪些类型,它们最适合用来做什么?
  • 我们需要哪些数据来支持每一种人工智能技术,我们从哪里获得这些数据?
  • 我们如何准备自己的数据供 AI 使用?
  • 我们的重点应该是降低成本,还是人工智能提供了一个新的收入机会?
  • 我们应该雇佣内部数据科学团队,还是可以通过第三方黑盒解决方案来满足我们的需求?

最后一个问题与传统的“制造还是购买”的困境不太一样。相反,它更多的是关于知识应该生活在哪里。您是依靠第三方来告诉您如何最大限度地发挥企业数据的价值,还是应该始终在组织内部获取这些信息?这就引出了最后一个问题,哪些公司今天应该开始考虑:

  • 我们的数据到底值多少钱?

能够回答这些问题的公司将成为当前工业革命的赢家。要找到答案,大企业需要在内部建立并保持对这些主题、其对行业的具体影响以及对客户的影响的广泛跨职能理解。

创业公司和科技公司需要重新思考产品策略

初创公司和更小、更灵活的科技公司通常是生态系统的创新者和新技术供应商。虽然他们通常更有条件(文化和人才方面,如果不是财政方面的话)来应对加速发展新技术所必需的 R&D,但他们也有自己的问题需要回答。例如,在考虑新产品时:

  • 我们如何通过将人工智能添加到我们今天生产的产品中来创造独特的价值主张?
  • 我们有哪些独特的数据或算法可以驱动人工智能——无论人工智能是我们的还是别人的?
  • 对于一个可能被人工智能颠覆的行业或流程,我们有什么独特的见解?
  • 产品经理如何将数据和人工智能融入产品战略和设计流程?

最后一个问题暗示了产品公司需要经历的必要的流程转型。如上所述,有许多初创的人工智能公司正在涌现,为行业提供解决方案。但是我们仍然处于人工智能产品开发的狂野西部时代,对于产品经理来说,还没有一种标准的方法来将数据和人工智能思维融入他们的设计中。

产品经理已经在营销、设计和技术的交叉领域工作,这个角色需要战略以及深入的分析思维、相当的沟通能力和足够的机智。要求他们也承担数据建模和机器学习算法是不是太过分了?

为了避免在产品经理的角色上倾倒太多额外的责任,我们将需要形成组织结构和过程,将人工智能的快速扩张所产生的新设计需求纳入其中。虽然他们已经有很多事情要做,但是产品经理需要在这些主题上进行自我教育,并成为转型工作的先锋。

学生和应届毕业生需要保持开阔的视野

第三组生态系统贡献者是刚刚进入劳动力市场的人。尽管 IBM 和谷歌等公司的人工智能项目赢得了公关,但人工智能领域的许多创新仍发生在学术机构中。因此,数据科学专业的毕业生离奇迹发生的地方很近,需求量很大。但是他们还没有完成他们的教育。

当这些人开始他们的商业生涯时,他们也应该问自己一些问题,例如:

  • 我如何了解各种各样可能的人工智能解决方案,并避免陷入一个封闭的生态系统?

无论是在学术界还是在商界,在最喜欢的技术和供应商之外扩展知识都是困难的。来自微软和亚马逊等供应商的大型人工智能平台作为一站式商店很有吸引力,但它们可能很昂贵,可能不总是提供最好的数据或技术,而且供应商锁定往往阻止用户从其他地方寻找解决方案。在求职时,你的优势不仅在于保持中立,还在于拥有广泛的技术平台经验。

  • 有哪些人工智能应用于不同问题的例子,使用了哪些数据?

结合最近的数据科学培训,了解人工智能如何应用于行业解决方案也将非常有用。如上所述,企业仍然在努力理解不仅是基本技术,而且如何应用它。因此,理论和实践知识的结合将成为热门商品。此外,准备好回答以下问题会让你受到欢迎,真的:

  • 我可以做些什么来帮助我的同事了解在哪里以及如何使用 AI?

最近花时间探索和学习人工智能的人可能最适合向他们的新同事介绍人工智能的用途和好处。

人工智能的民主化需要途径和知识

我们探讨了人工智能技术的快速发展及其影响,它带来的挑战,以及商业生态系统的不同部分如何需要自我教育来应对这些挑战。虽然获得技术的机会正在突飞猛进地增长,但为了最大限度地发挥该技术对工业的价值,教育是必要的。

因此,工业界现在需要建立制度知识,在此基础上可以建立下一波应用创新。如果没有对人工智能可以解决什么样的问题、什么样的算法可以最好地解决这些问题以及需要什么样的数据来支持这些模型的内在意识,商业世界将继续朝着承诺的未来自动化乌托邦奋斗。

没有快速的解决方案,技术的企业消费者无法独自解决问题。相反,需要一种关于人工智能及其应用的持续、系统的教育努力,在当前产业的不同领域以及新兴劳动力中积累知识。

鉴于少数大型平台垄断人工智能技术和数据的威胁,我们的新理解不要偏向特定供应商的角度,而是代表尽可能广泛的观点,这也很重要。

每个人都应该有平等的机会用人工智能创新,让世界变得更好。

Agorai 这样的公司正在努力扩大人工智能技术的使用范围,不仅为企业,也为中小型企业提供一流的工具和数据。Agorai 还将通过加速器项目为教育机构和初创公司提供打折的市场准入。

数据科学家的教育

原文:towardsdatascience.com/education-o…

最近,有人找我帮忙设计数据科学硕士学位课程。我欣然接受了这一邀请,因为我已经招募了几位数据科学家,并对他们的教育差距有强烈的看法。

数据科学是一个广泛的学科,数据科学家的工作描述各不相同。但是我要把它们分成两个不同的类别。第一类是算法专家。这些数据科学家设计和实现算法,开发用于机器学习和数据挖掘的软件库,设计和实现数据管道。这些人实现了 TensorFlow,python scikit-learn 库,实现了用于训练深度网络的分布式和并行算法。他们的工作头衔包括:应用研究科学家、机器学习工程师、数据工程师等。他们几乎都有硕士学位,有时是博士学位。

第二大类是应用数据科学家。这些科学家应用机器学习、统计学、数据挖掘、可视化的技术来获得洞察力,建立预测模型和进行实验。他们可能为实施产品推荐的电子商务公司工作,为实施内容个性化的媒体公司工作,为建立疾病爆发预测模型或评估政策影响的公共卫生组织工作。最近,机器学习在警务、招聘和教育等领域的应用激增。

这两类人需要不同的教育和不同的技能。然而,我认为大多数大学课程都是为了迎合算法学家,很少能提供应用数据科学家需要的培训。我所在的大学正试图填补这一空白。

应用数据科学家需要的教育是什么?首先是基础知识:对统计学和概率(尤其是统计推断、实验设计、概率分布)的扎实理解是必不可少的。其次,他们需要对机器学习和数据挖掘算法有扎实的理解。在他们的职业中,他们将使用已建立的库,并且很少探究它们的内部,但是他们应该对底层的假设以及每个算法的适当使用和限制有一个坚实的理解。他们应该能够在适当的时候定制损失函数。

标准数据科学课程中通常不会教授的课程。

我提倡开设一门“决策分析”的课程。决策分析是一门成熟的学科,大多在商学院教授。数据科学家将受益于它的概念和工具。决策分析是在不确定条件下制定决策的正式学科,提供了一种评估决策方案、结果和信息影响的方法。应用数据科学家可以很好地理解大多数 ML 模型是一个更大的决策过程或系统的组成部分。产品推荐系统是大型电子商务系统的组成部分,点击预测模型是广告投放系统的一部分,为求职者评分的模型是员工招聘和管理流程的一部分。决策分析框架将帮助数据科学家评估误报和漏报的影响,并权衡获取新数据的收益和成本。

“理解数据”课程包括对数据来源、探索性数据分析和数据可视化的全面理解。每个人都知道垃圾中的垃圾,但很少有人给予足够的重视。很少有数据科学家意识到大多数大数据集是有偏见的。建模者需要理解,机器学习的模型通常嵌入在人机系统中,并影响行为。由于这种影响,由行为产生的数据表现出偏差。还有许多其他方式,生成的数据可能有偏差,或者在其他方面不适合模型训练(我将在单独的帖子中讨论这一点)。理解数据的一个关键组成部分是探索性数据分析(EDA),这似乎是一门失传的艺术。

一门关于研究设计的课程将教会初露头角的数据科学家如何为研究构建适当的描述性和解释性问题,设计数据收集策略(如调查)以及设计和运行实验。他们将学习如何从研究中得出适当的结论。强大的研究技能与沟通和说服科学受众研究结果的能力密切相关。我告诉年轻的数据科学家,数据科学本质上是用数据讲故事。这些故事讲述了一个强有力的归纳论点与说明性的视觉效果。像所有优秀的沟通者一样,他们应该能够预见问题。

我没有提到计算技能,但这是已知的。一个数据科学家应该是一个强大的程序员,尤其是使用 Python。她还应该擅长处理各种类型的数据库,包括关系数据库和 NoSQL 数据库。

一个好的数据科学家应该致力于他们所关注的领域。研究公共卫生问题的数据科学家应该以公共卫生科学家的身份出现,而不是以机器学习工程师的身份出现。为电子商务构建预测模型的数据科学家应该致力于营销和电子商务。只有这样,她才知道问重要的问题,理解数据。

由于应用数据科学完全是关于*实践,*应用数据科学课程应该包括基于项目的培训。我的建议是每个学生在一个项目中被分配两个导师——一个是项目中要部署的技术的专家,另一个是项目领域的专家。此外,在计划的项目阶段,应该鼓励学生在介绍学科概念和方法的项目领域中选择适当的课程。

让我用一个故事来结束。最近,一个研究小组在一次关于人工智能、伦理和社会的会议上展示了他们关于犯罪是否与帮派有关的自动化分类的工作(http://www . science mag . org/news/2018/02/Artificial-Intelligence-can-identify-gang-crimes-and-ignite-ethical-firestorm)。他们使用了一种叫做“部分生成神经网络”的技术。研究人员认为,他们的模型可以比没有帮助的人类判断产生更快更好的结果。观众就数据和某人被误认为帮派成员会有什么影响等问题向演讲者进行了激烈的提问。演示者不确定。被这些问题逼得走投无路,他举起双手说:“我只是个工程师”!设计良好的数据科学课程应该设法防止毕业生做出这种反应。

特征标准化对线性支持向量机的影响

原文:towardsdatascience.com/effect-of-f…

因为支持向量机(SVM)优化是通过最小化决策向量 *w,*来实现的,所以最优超平面受输入特征规模的影响,因此建议在 SVM 模型训练之前对数据进行标准化(均值为 0,方差为 1)。在这篇文章中,我展示了标准化对双特征线性 SVM 的影响,以及一些(希望)对结果的实际解释。

我在这里使用的数据来自大学记分卡,这是一个免费的美国教育部数据来源,包含美国大学的各种统计数据。我使用了由 Kaggle 托管的版本的大学记分卡数据。

使用此数据源,我将训练一个 SVM 来根据(1)注册学生的平均 SAT 分数和(2)注册学生的平均家庭收入预测大学的州内学费是大于还是小于每年 2 万美元。这个模型有点做作和简单——我的主要目标不是成功地预测目标类本身,而是展示特性标准化对最终模型的影响。

在该数据集中,有 4166 所大学具有非空平均 SAT 分数和家庭收入数据。有相当多的大学在这些特征上具有空值,我在分析中排除了这些特征:

每年 2 万美元的州内学费介于该变量的第 50 和第 75 百分位之间——因此在这个目标阶层的两边都有相当数量的大学。

上面,我根据平均 SAT 分数和家庭收入绘制了大学学费。应该立即明确的是,这些数据不是线性可分的。在线性 SVM 中,没有超平面可以按照学费类别清晰地分割数据点——在模型选择的任何决策超平面中,总是会有大学位于“错误的一边”。sklearn SVM 实现将根据用户指定的超参数“C ”,搜索最佳超平面(和+1/-1 边缘超平面),该超参数确定边缘超平面“错误侧”上的数据点的惩罚程度。

对于每组特征(非标准化,然后标准化),我运行了 11 个线性 SVM 模型,C 系数为 5**-3,5**-2,…5**3。

很明显,这两种模型在运行时间上有很大的不同:

以下两个表格记录了每个拟合 SVM 的分类预测精度(字段“测量”)。顶部的结果集代表 60%的训练数据子集,而底部的结果集代表 40%的测试或维持数据子集。我还包括了每次运行的拟合决策向量 w 和标量 b 。所有模型的准确率都相似,但是 wb 的拟合值却大相径庭。

下面的 6 个图显示了各种罚系数 c 值的拟合 SVM 超平面和(+1,-1)余量。上面的三个图显示了非标准化特征的拟合超平面,而下面的三个图显示了标准化特征的拟合超平面。

不难看出,非标准化数据会产生对系数 c 高度敏感的决策超平面。前三个支持向量机中的每一个都会产生肉眼明显不同的决策超平面。标准化数据跨超参数产生更加一致的 SVM 超平面。底部图之间的差异在于,C 值越低,(+1,-1)边缘超平面的范围越宽。直观地,由于边缘超平面的“错误侧”上的数据点在低 C SVM 模型中受到的惩罚越少,因此模型逻辑具有更大的自由度来拟合远离决策超平面的边缘边界。

[## 达索特罗/SVM _ 学院 _ 学费. py

github.com](github.com/dasotelo/Py…)

有效的数据科学演示

原文:towardsdatascience.com/effective-d…

如果你是数据科学领域的新手,我想提供一些提示,告诉你如何从你在学术界的演示过渡到为行业创建有效的演示。

不幸的是,如果你的背景是数学、统计学或计算机科学,可能没人会让你准备好在工业界做一个令人敬畏的演讲。事实是,这需要练习。在学术界,我们共享 t-stats 和 p-values 的表格,并大量讨论数学公式。这基本上与你向非技术观众演示时想做的相反。

如果你的听众都是 STEM 博士,那就开始吧,但在很多情况下,我们需要调整我们思考展示技术材料的方式。

我可以没完没了地谈论这个话题,但这里我们将涉及:

  1. 谈论模型输出而不谈论模型
  2. 使用实际客户或输入描绘画面
  3. 花时间讲述这个故事

谈论模型输出而不谈论模型

某些型号确实很适合这种情况。逻辑回归,决策树,它们只是尖叫着被赋予生命。

您不希望将模型输出复制/粘贴到演示文稿中。您也不希望将输出格式化成一个漂亮的表格并粘贴到您的演示文稿中。你想讲述这个故事,而记录几率肯定不会为你的利益相关者讲述这个故事。

逻辑回归模型的第一步是对对数概率取指数,这样你至少可以用概率来处理。因为这个输出是乘法的,你可以说:

“在其他一切保持不变的情况下,我们预计[变量]每增加一个单位,平均会增加 x%。”

因此,我们不讨论模型的技术方面,而是讨论不同的驱动因素如何影响输出。然而,我们可以更进一步。

用真实客户来画图

喜欢用现实生活中的用例来展示模型是如何工作的。上面我们看到了一些类似于我在谈论我的季节性模型时所展示的东西。当然,我为这篇文章改了他的名字,但在演示文稿中,我会谈论这个人的业务,为什么是季节性的,展示明显的季节性模式,并让他们知道模型将这个人归类为季节性的。我不是在谈论傅立叶变换,我是在描述真实的人是如何被分类的,以及我们可能想如何向他们营销。像这样深入挖掘也有助于我更好地理解正在发生的事情。我们都知道,当我们深入挖掘时,我们会看到一些疯狂的行为模式。

提取特定的客户/用例也适用于其他类型的模型。你建立了一个保留模型?选择一对翻盘概率高的情侣,和一对翻盘概率低的情侣,聊聊那些人。

“这里的玛丽长期以来一直是我们的客户,但她最近参与度较低,没有做过 x、yz (模特司机),所以她取消订阅的概率很高,尽管任期较长的客户通常不太可能离开。”

花时间讲故事

如前所述,将这些东西放在一起需要一些额外的工作。另一个很好的例子是聚类分析。您可以为每个属性创建一张幻灯片,但是人们需要仔细阅读多张幻灯片才能弄清楚世卫组织分类 1 与分类 2 的真正区别,等等。您希望为您的消费者汇总所有这些信息。我不会为我的细分市场想出俗气的名字,它只是来自于领域:)。

这里值得注意的是,如果我不按集群汇总所有这些信息,我也无法从较高的层次上谈论谁实际上进入了这些不同的集群。对我来说,这将是一个很大的失误,因为最终,您的利益相关者希望了解这些集群的整体情况。

我提出的每一项分析都花时间思考,对于数据所能讲述的故事,合适的流程应该是什么。我可能需要额外的信息,如按地理划分的市场渗透率,(或任何东西,可能性是无限的)。我的模型中可能没有按地理位置划分的小企业数量,但用谷歌搜索一下,我就能找到。做一些额外的工作来计算市场渗透率,然后创建一个地图,并使用这些信息来进一步支持我的故事。或者,也许我知道市场渗透率并不支持我的故事,我需要做更多的分析,以了解正在发生的事情的真正核心。我们是侦探。我们不仅仅是在处理模型中的数据。我们试图探索任何可能提供有趣见解并有助于讲述故事的东西。此外,如果你正在做额外的工作,发现你的故事是无效的,你只是救了自己一些心痛。当你先陈述,然后意识到你的结论是错误的时候,情况会更糟。womp womp。

结束语

在开始构建模型之前,您要确保输出是可操作的,对吗?在演示结束时,你当然希望谈论如何使用你的模型并增加价值的后续步骤,无论是提出如何以你认为他们会响应的新方式与客户沟通的想法,减少保留,增加获得等。但是要说清楚。花点时间想出一些具体的例子来说明人们如何使用这些输出。

我还想提一下,学习创建优秀可视化的最佳实践将会给你极大的帮助。Kate Strachnyi 的两篇文章涉及了这个话题。你可以在这里找到那些文章,在这里找到

如果您创建了一个幻灯片,却找不到“那又怎样?”是幻灯片的一部分,它可能属于附录。当你在创作职业生涯的第一批幻灯片时,如果没有包含一张你花了很多时间的幻灯片,你可能会崩溃,但如果它没有增加一些有趣的东西,不幸的是,那张幻灯片属于附录。

我希望你在这篇文章中至少找到了一个技巧,可以应用到你的下一次演讲中。如果我能帮助一个人做一场精彩的演讲,那就值得了。

原载于 2018 年 9 月 10 日datamovesme.com

命名在数据科学代码中的作用

原文:towardsdatascience.com/effective-n…

即使有工具允许在不编码的情况下实践数据科学,它们也远远不够。数据科学家将编写和读取代码。阅读可读性差的代码是一种可怕的体验。这篇文章关注命名实体(例如变量、函数)的重要性,以及它如何容易地提高你的代码质量。

“会有代码”

“……我还预计特定领域语言的数量将继续增长。这将是一件好事。但它不会消除代码。”

罗伯特·c·马丁在他的书的第一页写道《干净的代码:敏捷软件技术手册》,第一章名为“将会有代码”。我们,数据科学家,编写和读取代码。即使有帮助工具,我们仍将编写和阅读代码。这是我们的核心实践之一。这就是我们如何分析数据、训练模型、预测结果等等。我坚信,对于一个数据科学家来说,代码是无法逃避的。

在某种程度上,我们仍然可以不用编码来实践数据科学。从早期到今天,有图形工具可以分析数据或练习机器学习。这种工具的一个例子是 WEKA 。WEKA 是一个带有图形用户界面的机器学习工具包。根据维基百科,它的发展始于 1993 年 * 。它允许用户在不编写一行代码的情况下进行机器学习实验等。那我为什么坚持说写代码和读代码是数据科学家的根本?因为会有自定义操作。

图形工具只有这么多操作。如果你不是每天都在做同样的事情,那么总有一天工具会失去你所需要的功能。这可以是一个分析,一个机器学习模型,或者一些其他的操作。您需要在某种程度上控制、定制和扩展您的操作。级别取决于任务、库或工具。由于许多问题需要新的或定制的方法,很快你就会超过那些图形工具。

我们很少单独工作。组织通常没有单一的数据科学家,而是有数据科学团队。即使事实并非如此,数据科学家也会与其他学科合作。这种协作需要良好的数据科学代码质量。

此外,如果你在为一家公司工作,你其他团队的同事会需要你的代码。为了将你的模型嵌入后端、前端或其他系统,你需要代码。一个不能部署或集成的模型对你的公司来说是没有用的。

如果你认同数据科学会有代码,那我们就来谈谈如何为数据科学写好代码。编写好的代码是一项艰巨的任务。有很好的文字解释为什么它是必要的和如何实现它。在这篇文章中,我的目标是关注其中的一点。这一点不需要培训或教育,但会显著提高您的代码质量。我将重点关注的是命名、,它将提高代码的可读性。

一个简单的技巧:重命名

阅读一段可读性差的代码是一种可怕的体验。让我们看看下面这个简单的例子:

import pandas as pddf = pd.DataFrame({"f1": [42, 12, 5, 8, 15, 65], 
                   "f2": [172, 155, 110, 120, 158, 168]})
df2 = df[df.f1 >= 18]
out = df2.f2.mean()
# out: 170.0

试着猜猜这段代码是做什么的。这段代码的作者知道每一行的目标,并且在她编写代码时知道整个代码的目标。然而,作为一个读者,你看到了一个你需要破译的代码片段。由于作者没有注意可读性,你将花费更多的时间和精力试图理解这段代码。此外,你将更容易犯错误。让我们仔细分析一下这个例子,看看它为什么不好:

  • 我知道进口熊猫作为 pd 现在是非常标准的。所有与熊猫打交道的数据科学家都会理解这种简写。这不是代码中最大的问题,但我相信这是可以改进的。除此之外,短(例如 2 个字符)变量名在自动补全中也很麻烦(例如 pd vs pdb)。
  • df = ...同样,可能是因为 pandas 教程,将数据帧命名为 df 是一种广泛应用的实践。但是它隐藏了上下文中的数据。那是什么样的数据?
  • "f1":... "f2":...这些是我们数据框的列。然而,它不提供信息。那些列有什么样的数据?为什么它们被列举为 1 和 2?列举是否有目的(比如某事物的第一和第二),或者没有?
  • df[df.f1 >= 18]这行中的 18 是什么意思?是某种神奇的数字吗?为什么我们要过滤大于或等于 18 的值,为什么我们要过滤 f1 列?
  • out = df2.f2.mean()到处都是同样的问题。f2 列的意义是什么?为什么我们要取其平均值?

现在让我用更易读的方式重写它,而不是解释它的目的。我将只是重命名变量,并保持代码的其余部分不变。

import pandasphysical_data = \
        pandas.DataFrame({"age": [42, 12, 5, 8, 15, 65], 
                          "height": [172, 155, 110, 120, 158, 168]})adult_physical_data = physical_data[physical_data.age >= 18]
mean_height_of_adults = adult_physical_data.height.mean()
# mean_height_of_adults: 170.0

仅仅通过重命名,你只需一瞥就能理解代码片段的目标和每行中的操作。我认为现在没有必要解释代码,因为它非常清楚。

数据= …,但是哪些数据呢?

我相信数据科学代码中的命名可能比一般的软件代码更难。我们有更少的适合对象设计的概念,更多的抽象实体和多样化的集合。这使得数据科学中的命名更加困难。例如,考虑使用包含许多列的表。例如,一个表具有关于作为人的客户(例如,姓名、年龄)、客户行为(例如,购买)、地理信息(例如,购买的地址)和时间信息(例如,购买的时间)的列。你会如何命名这张桌子?

您可以为该表取不同的名称,但有一些常见的不好的名称。例如,不要将其命名为dtdf。即使你会在 pandas 文档的每个地方看到 df,你也必须明白它们是不属于某个项目的简短示例代码。也不要把它命名为data。是的,它是数据,但你会将保存年龄的变量命名为“整数”吗?“数据”作为一个名称是非常模糊的。那是什么数据?它包含什么样的信息?

不要害怕使用长名字。较长的名称通常包含关于实体的更多信息。拥有更长的名字并不是一种负担。有许多不错的具有自动完成特性的 ide,比如 PyCharm ,所以你不必写全名。

编码的时候,想想下一个会阅读你代码的人。她能理解剧本的主要目标以及每一句台词是如何服务于这个目标的吗?更具体地说,命名:她会仅仅通过名字就迅速捕捉到那个实体的含义吗?

不要为糟糕的代码找借口

用更好的名字,不仅仅是为了你的队友,也不仅仅是为了你自己。你的队友和你自己都从这个习惯中受益。从你队友的角度来看,她会更容易更快地读懂你写的代码。从你个人的角度来看,你会写你的代码更容易,因为你将有更少的认知负荷去记忆你的实体的意义。因此,你的团队和组织将从这个习惯中受益。

首先,命名更好的习惯似乎很难养成。你可能不想把时间花在寻找更好的名字上。然而,这是一个有回报的习惯。即使你写的代码是一个原型,或者是一个小项目的一部分,你也应该实践它。在不知道的情况下,这样的代码可能会变成一个更大的项目。很多情况下,项目看起来很小,但是开发持续了很多年;设计为“一劳永逸”的项目最终对组织非常重要。这就是为什么即使是最短的代码也应该有好的命名。

如果你从来没有想过更好的命名,我希望在读完这篇文章后,你会尝试更好地命名你的实体,并看看它如何提高你的代码质量。

效率与清晰度

原文:towardsdatascience.com/efficiency-…

作为一名数据科学家,编写代码时要考虑的一个问题是如何最好地平衡效率和清晰度。(在这里,效率=代码执行的速度,清晰性=同样的代码组织得有多好,有多容易理解。)在这种情况下,量化效率比量化清晰更容易,但是查看两组代码并确定哪一组更有组织性是很简单的。(嗯,这在理论上是真的,这意味着在现实中可能一点也不真实。)

Giphy >> computer >> download funniest GIF near top of page

一方面,代码的目标几乎总是解决一些问题——那么为什么不尽可能地高效呢?如果我们能更快地解决一个问题,那就比解决得更慢更好…对吗?

小故事:几年前,我的男朋友飞往加州,试图阅读安伯托·艾柯的《福柯的钟摆》。通过机场时,美国运输安全管理局把他的书签抖了出来。他后来找到了自己的位置,读了 20 分钟,意识到自己已经读完了那一部分。(这本书显然难以置信的密集。)这种情况发生了两三次,直到他最终放弃完成这本书。

Me, in grad school.

这是积极的数据科学家/程序员/开发人员/任何做过项目的人的困境。你已经上床睡觉了——没有星巴克、Soylent 或你选择的燃料——第二天早上醒来时,你不知道你在代码中的什么位置,也不知道一部分如何与其他部分相适应。也许你正在与他人合作编写代码,因此愿意为了清晰而牺牲一些效率。作为数据科学爱好者,我们认识到一些实际的限制可能会干扰最巧妙和最快的解决方案。当然,我们可以(也应该!)在我们的代码中包含注释,但这并不意味着我们不能力求清晰…只要这种清晰不影响我们的效率!

“Fizzbuzz”问题,经常在技术面试中使用(包括我自己的一个!),这是一个很好的例子,说明用不同的方法处理不同优先级的问题可以得到相同的解决方案。

TL;博士——“T2”问题需要有人描述一种算法,对于 1 到 100 之间的每个整数:

  • 如果这个数能被 3 整除,打印“Fizz”
  • 如果数字能被 5 整除,打印“Buzz”
  • 如果数字能被 15 整除,打印“FizzBuzz”,或者
  • 如果数字不能被 3、5 或 15 整除,则打印数字本身。

期望的输出将类似于:

1, 2, “Fizz,” 4, “Buzz,” “Fizz,” 7, 8, "Fizz," ...

即使你以前没有见过这个问题,你们中的超逻辑者可能已经有了一个你将如何着手解决它的心理草图。创建一个取值为 1,2,…,99,100 的变量。对于每个值,检查它与 3、5 和 15 的整除性。认识到 3、5 和 15 会有一些重叠,我们要小心。在这一点上,我们可能最好把笔放在纸上(或手指放在键盘上)并尝试一下。

Click.

在我的 Python 访谈中,我在黑板上写下了以下内容:

for i in range(1,101):
    if i % 3 == 0:
        if i % 5 == 0:
            print 'Fizzbuzz'
        else:
            print 'Fizz'
    elif i % 5 == 0:
        print 'Buzz'
    else:
        print i

那时,一位面试官问我为什么要这样安排。这在我的思考中是最有意义的——我知道被 3 和 5 整除的数字会更棘手,所以我想在一开始就考虑被 15 整除的可能性。然而,退后一步,让写在白板上的面试神经稍微平静下来,它确实看起来很笨拙。我提到,这样可能会更有效率,因为我们运行的操作更少,但考虑到这些紧张因素,我不想强调这一点,以免我忽略了一些愚蠢的事情。

在面试官的要求下,我又做了一遍:

for i in range(1,101):
    if i % 3 == 0 & i % 5 == 0:
        print ‘Fizzbuzz’
    elif i % 3 == 0:
        print ‘Fizz’
    elif i % 5 == 0:
        print ‘Buzz’
    else:
        print i

这似乎更优雅。显然更清楚了。如果我试图教某人编码,或者如果我和一群都接触相同代码的人一起工作,这似乎是一个更好的解决方案。

Yup. Nerding out 24/7.

直到我回到家,我一直在回想哪个代码块会更有效率。当我回到家,我坐下来展示了运行我最初写的算法确实会更有效率。(对数字 1 到 1,000,000 运行这个程序,我的第一个代码将运行 33.39 秒,而第二个代码将运行 34.80 秒。这是因为第一个代码片段对于所有不能被 3 和 5 整除的数字只需要少一次运算。)

不幸的是,就像数据科学中的许多事情一样,效率和清晰之间几乎没有硬性的规则。说“如果许多人在同一代码上工作,你应该关注清晰性”或“如果你在‘大数据’上使用代码,那么效率可能更重要”是相当琐碎的。但是我对你的最佳实践感兴趣!

对编码人员来说,什么时候更重要?

对于非编码人员,格兰芬多即使读到这里也要加 100 分,但是你对日常环境中“效率与清晰”的概念有什么想法?

用 Scipy——有效边界解释最小风险的投资组合优化

原文:towardsdatascience.com/efficient-f…

Photo by Chris Liverani on Unsplash

(我的博客里也有这个帖子)

超越界限

给定 4 种资产的风险和回报如下,用这些资产构建的任何投资组合的风险回报可能是多少。人们可能认为所有可能的值都落在凸包内。但如果考虑资产之间的相关系数,超越债券是有可能的。也就是说,组合反向相关的资产可以构建一个风险较低的投资组合。更多细节可以在我的上一篇中找到。

为了证明投资组合的风险回报可以超越这个区域,我得到了 3000 个随机加权投资组合的样本,并绘制了它们的风险回报。

环境设置

遵循这个帖子中的步骤 1

计算并可视化资产回报和风险

这是教程,我们从 4 个不同的部门挑选了 4 只股票 BA(波音),C(花旗集团),AAL(美国航空集团),NFLX(网飞)进行分析。正如我的上一篇文章所说,风险是通过每日回报的标准差来衡量的。回报计算如下

**K * (expected return – expected risk free rate)**

k 是采样频率的平方根。这意味着如果我们用日收益率来衡量,K 就是 sqrt(250)(一年大概有 250 个交易日)。国债利率通常被用作无风险利率。在本教程中,我们将使用 0。

密码

散点图描绘单个资产的风险收益

**import** pandas_datareader.data **as** web
**import** pandas **as** pd
**import** matplotlib.pyplot **as** plt
**import** numpy **as** np
**from** scipy.optimize **import** minimize**def** get_risk(prices):
    **return** (prices / prices.shift(1) - 1).dropna().std().values **def** get_return(prices):**return** ((prices / prices.shift(1) - 1).dropna().mean() * np.sqrt(250)).valuessymbols = [**'BA'**, **'C'**, **'AAL'**, **'NFLX'**]
prices = pd.DataFrame(index=pd.date_range(start, end))
**for** symbol **in** symbols:
    portfolio = web.DataReader(name=symbol, data_source=**'quandl'**, start=start, end=end)
    close = portfolio[[**'AdjClose'**]]
    close = close.rename(columns={**'AdjClose'**: symbol})
    prices = prices.join(close)
    portfolio.to_csv(**"~/workspace/{}.csv"**.format(symbol))prices = prices.dropna()
risk_v = get_risk(prices)
return_v = get_return(prices)fig, ax = plt.subplots()
ax.scatter(x=risk_v, y=return_v, alpha=0.5)
ax.set(title=**'Return and Risk'**, xlabel=**'Risk'**, ylabel=**'Return'**)**for** i, symbol **in** enumerate(symbols):
    ax.annotate(symbol, (risk_v[i], return_v[i]))plt.show()

Return and risk for BA (Boeing), C (Citigroup), AAL (American Airlines Group), NFLX (Netflix)

构建随机权重的投资组合

**def** random_weights(n):
    weights = np.random.rand(n)
    **return** weights / sum(weights)**def** get_portfolio_risk(weights, normalized_prices):
    portfolio_val = (normalized_prices * weights).sum(axis=1)
    portfolio = pd.DataFrame(index=normalized_prices.index, data={**'portfolio'**: portfolio_val})
    **return** (portfolio / portfolio.shift(1) - 1).dropna().std().values[0]**def** get_portfolio_return(weights, normalized_prices):
    portfolio_val = (normalized_prices * weights).sum(axis=1)
    portfolio = pd.DataFrame(index=normalized_prices.index, data={**'portfolio'**: portfolio_val})
    ret = get_return(portfolio)
    **return** ret[0]risk_all = np.array([])
return_all = np.array([])*# for demo purpose, plot 3000 random portoflio* np.random.seed(0)
normalized_prices = prices / prices.ix[0, :]
**for** _ **in** range(0, 3000):
    weights = random_weights(len(symbols))
    portfolio_val = (normalized_prices * weights).sum(axis=1)
    portfolio = pd.DataFrame(index=prices.index, data={**'portfolio'**: portfolio_val})
    risk = get_risk(portfolio)
    ret = get_return(portfolio)
    risk_all = np.append(risk_all, risk)
    return_all = np.append(return_all, ret)
    p = get_portfolio_risk(weights=weights, normalized_prices=normalized_prices)fig, ax = plt.subplots()
ax.scatter(x=risk_all, y=return_all, alpha=0.5)
ax.set(title=**'Return and Risk'**, xlabel=**'Risk'**, ylabel=**'Return'**)**for** i, symbol **in** enumerate(symbols):
    ax.annotate(symbol, (risk_v[i], return_v[i]))
ax.scatter(x=risk_v, y=return_v, alpha=0.5, color=**'red'**)
ax.set(title=**'Return and Risk'**, xlabel=**'Risk'**, ylabel=**'Return'**)
ax.grid()
plt.show()

风险来自于不知道自己在做什么——沃伦·巴菲特

再来看风险和收益。我们确实看到区域外有蓝点。所以分散投资确实有助于降低风险。但是,我们如何找到最佳或有效的重量呢?

Return and risk of a portfolio of random weighted BA (Boeing), C (Citigroup), AAL (American Airlines Group), NFLX (Netflix) (3000 samples)

效率限界

来自维基百科,在现代投资组合理论中,有效边界(或投资组合边界)是一种投资组合,它占据了风险回报谱的‘有效’部分。

在这里,我们将使用 scipy 的优化器来获得不同目标回报的最佳权重。请注意,我们有界限来确保权重在范围[0,1]内,并且有约束来确保权重之和为 1,并且投资组合回报满足我们的目标回报。有了所有这些条件,scipy optimizer 就能够找到最佳分配。

*# optimizer* **def** optimize(prices, symbols, target_return=0.1):
    normalized_prices = prices / prices.ix[0, :]
    init_guess = np.ones(len(symbols)) * (1.0 / len(symbols))
    bounds = ((0.0, 1.0),) * len(symbols)
    weights = minimize(get_portfolio_risk, init_guess,
                       args=(normalized_prices,), method=**'SLSQP'**,
                       options={**'disp'**: **False**},
                       constraints=({**'type'**: **'eq'**, **'fun'**: **lambda** inputs: 1.0 - np.sum(inputs)},
                                    {**'type'**: **'eq'**, **'args'**: (normalized_prices,),
                                     **'fun'**: **lambda** inputs, normalized_prices:
                                     target_return - get_portfolio_return(weights=inputs,
                                                                          normalized_prices=normalized_prices)}),
                       bounds=bounds)
    **return** weights.xoptimal_risk_all = np.array([])
optimal_return_all = np.array([])
**for** target_return **in** np.arange(0.005, .0402, .0005):
    opt_w = optimize(prices=prices, symbols=symbols, target_return=target_return)
    optimal_risk_all = np.append(optimal_risk_all, get_portfolio_risk(opt_w, normalized_prices))
    optimal_return_all = np.append(optimal_return_all, get_portfolio_return(opt_w, normalized_prices))# plotting
fig, ax = plt.subplots()
*# random portfolio risk return* ax.scatter(x=risk_all, y=return_all, alpha=0.5)*# optimal portfolio risk return* **for** i, symbol **in** enumerate(symbols):
    ax.annotate(symbol, (risk_v[i], return_v[i]))
ax.plot(optimal_risk_all, optimal_return_all, **'-'**, color=**'green'**)*# symbol risk return* **for** i, symbol **in** enumerate(symbols):
    ax.annotate(symbol, (risk_v[i], return_v[i]))
ax.scatter(x=risk_v, y=return_v, color=**'red'**)ax.set(title=**'Efficient Frontier'**, xlabel=**'Risk'**, ylabel=**'Return'**)
ax.grid()
plt.savefig(**'return_risk_efficient_frontier.png'**, bbox_inches=**'tight'**)

绿线表示有效边界。现在我们知道了给定目标回报率的最佳配置。下一个问题,总体而言,最佳配置是什么?投资组合的表现可以用收益/风险比率(称为夏普比率)来评估。高夏普比率表明收益和风险的良好平衡。这种分配可以通过画一条与有效边界相切的资本分配线来找到。切点是产生最高夏普比率的分配。要了解更多,你可以看看这篇文章,关于如何用资本配置线(CAL)从有效边界找到最高夏普比率。

Efficient frontier — Return and risk of optimal asset-weights at different targeted returns

现在我们知道为什么多样化可以帮助你的投资。如果你想了解更多关于机器学习的知识,educative.io 网站上有一系列课程很有帮助。这些课程包括像基本的 ML,NLP,图像识别等主题。投资和编码快乐!

我的下一篇帖子——交易策略:用 Python TA-Lib 进行技术分析。

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

推荐阅读:

动手机器学习

用于数据分析的 Python:与 Pandas、NumPy 和 IPython 的数据角力

对冲基金真正在做什么

我的帖子:

我关于 FAANG 访谈的帖子

我的 YouTube 频道

我关于金融和科技的帖子

从 CRUD web 应用开发到语音助手中的 SDE——我正在进行的机器学习之旅

全栈开发教程:将 AWS Lambda 无服务器服务集成到 Angular SPA 中

全栈开发教程:用运行在 AWS Lambda 上的无服务器 REST API 提供交易数据

全栈开发教程:在 Angular SPA 上可视化交易数据(1)

强化学习:Q 学习简介

Python 中的高效前沿投资组合优化

原文:towardsdatascience.com/efficient-f…

Photo by Frank Busch on Unsplash

我个人对金融的兴趣让我在 Coursera 上了一门关于投资管理的在线课程。这是由日内瓦大学和瑞士联合银行合作的 5 门专业课程。它不是专门为金融建模,但更多的是对投资策略及其相关理论的一般性介绍。作为一个没有任何行业经验的人,该课程确实有助于了解大局。我目前正在专业的第三个课程上,我学到了一些非常有趣的东西,叫做“现代投资组合理论”

在我学习这门课程的时候,我认为这将是一个非常好的练习 Python 技能的材料。尽管这个课程没有提供任何关于如何实际实现它的技术细节,但通过一些挖掘,我发现了一些非常有用的博客帖子,我可以参考。

Bernard Brenyah 撰写的一系列媒体博客文章

布拉德福德·林奇的博客文章

基于我从课程中学到的东西,以及从上面的博客文章中,我试图用我自己的方式复制它,一路上不断调整。

*除了我将附上的简短代码块,你可以在这篇文章的末尾找到整个 Jupyter 笔记本的链接。

现代投资组合理论

一个好的投资组合不仅仅是一长串好的股票和债券。这是一个平衡的整体,为投资者提供了各种保护和机会。哈利·马科维茨

现代投资组合理论(MPT)是由哈里·马科维茨发展的投资理论,于 1952 年以“投资组合选择”的标题发表在《金融杂志》上。

Harry Markowitz is the 1990 Nobel Memorial Prize winner in Economic Sciences

有几个基本概念可以帮助你理解 MPT。如果你熟悉金融,你可能知道缩写“TANSTAAFL”代表什么。这是“天下没有免费的午餐”的著名缩写。这个概念也和‘风险收益权衡’密切相关。

风险越高,回报越高的可能性越大,风险越低,回报越小的可能性越大。MPT 假设投资者厌恶风险,这意味着给定两个预期回报相同的投资组合,投资者会选择风险较小的一个。因此,投资者只有在得到更高预期回报的补偿时,才会承担更大的风险。

另一个在 MPT 发挥作用的因素是“多元化”。现代投资组合理论认为,只看一只特定股票的预期风险和回报是不够的。通过投资一种以上的股票,投资者可以获得多样化的好处——其中最主要的是降低投资组合的风险。

你需要明白的是“投资组合的风险不等于投资组合中个股的平均/加权平均”。就回报而言,是的,它是单个股票回报的平均值/加权平均值,但这不是风险的情况。风险在于资产的波动性,如果你的投资组合中有不止一只股票,那么你必须考虑这些股票的走势如何相互关联。多样化的美妙之处在于,通过优化配置,你甚至可以获得比投资组合中风险最低的股票更低的风险。

我将在使用实际代码的同时尝试解释。首先,我们从导入一些我们需要的库开始。" Quandl "是一个金融平台,它也提供 Python 库。如果你之前没有安装过,当然首先需要在你的命令行“pip install quandl”中安装包,在使用之前,你还需要在 quandl 的网站上获取一个 API key。注册并获得 API 密钥是免费的,但有一些限制。作为登录的免费用户,您最多可以在 10 分钟内拨打 2,000 个电话(速度限制),每天可以拨打 50,000 个电话(音量限制)。

import pandas as pd  
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import quandl
import scipy.optimize as scoplt.style.use('fivethirtyeight')
np.random.seed(777)%matplotlib inline
%config InlineBackend.figure_format = 'retina'

为了运行下面的代码块,你需要自己的 API 密匙。这篇文章选择的股票是苹果,亚马逊,谷歌,脸书。下面的代码块将获得从 2016 年 1 月 1 日到 2017 年 12 月 31 日每只股票的每日调整收盘价(2 年的价格数据)。

quandl.ApiConfig.api_key = 'your_api_key_here'
stocks = ['AAPL','AMZN','GOOGL','FB']
data = quandl.get_table('WIKI/PRICES', ticker = stocks,
                        qopts = { 'columns': ['date', 'ticker', 'adj_close'] },
                        date = { 'gte': '2016-1-1', 'lte': '2017-12-31' }, paginate=True)
data.head()

data.info()

通过查看数据的 info(),似乎“date”列已经是 datetime 格式了。让我们稍微转换一下数据,使其更容易处理。

df = data.set_index('date')
table = df.pivot(columns='ticker')
# By specifying col[1] in below list comprehension
# You can select the stock names under multi-level column
table.columns = [col[1] for col in table.columns]
table.head()

现在看起来好多了。让我们先来看看每只股票的价格在给定的时间框架内是如何演变的。

plt.figure(figsize=(14, 7))
for c in table.columns.values:
    plt.plot(table.index, table[c], lw=3, alpha=0.8,label=c)
plt.legend(loc='upper left', fontsize=12)
plt.ylabel('price in $')

看起来,亚马逊和谷歌的股价相对比脸书和苹果要贵。但由于脸书和苹果被挤在底部,很难看到这两个移动。

另一种方法是绘制每日回报(与前一天相比的百分比变化)。通过绘制每日回报而不是实际价格,我们可以看到股票的波动性。

returns = table.pct_change()plt.figure(figsize=(14, 7))
for c in returns.columns.values:
    plt.plot(returns.index, returns[c], lw=3, alpha=0.8,label=c)
plt.legend(loc='upper right', fontsize=12)
plt.ylabel('daily returns')

亚马逊有两个明显的正面峰值和几个负面峰值。脸书有一个最高的正峰值。而且苹果也有一些尖峰从剧情中脱颖而出。从上面的剧情中,我们大致可以看出,亚马逊看起来是一只风险相当大的股票,而谷歌似乎是其中最稳定的一只。

随机投资组合生成

我们的投资组合中有 4 只股票。我们必须做出的一个决定是,我们应该如何将预算分配给投资组合中的每一只股票。如果我们的总预算是 1,那么我们可以决定每只股票的权重,这样权重的总和就是 1。权重的值将是我们分配给特定股票的预算部分。例如,如果亚马逊的权重为 0.5,这意味着我们将预算的 50%分配给亚马逊。

让我们定义一些函数来模拟投资组合中每只股票的随机权重,然后计算投资组合的总年回报率和年波动率。

“投资组合 _ 年化 _ 绩效”函数将计算回报率和波动性,并使其作为一个年化计算我考虑 252 作为一年中的交易天数。“random_portfolios”函数将生成随机权重分配给每只股票的投资组合,通过给出 num_portfolios 参数,您可以决定要生成多少个随机投资组合。

从上面的代码块中,我想指出两点。

投资组合标准差

第一个是“投资组合 _ 年化 _ 绩效”函数中投资组合波动率的计算。如果你查找“投资组合标准差公式”,你会遇到如下公式。

如果我们使用矩阵表示法,这个公式可以简化。我在文章开头提到的 Bernard Brenyah 已经在的一篇博客文章中清晰地解释了如何用矩阵计算来表达上述公式

通过上面的矩阵计算,我们得到了原公式中平方根里面的部分。现在,我们需要做的就是把它们放在平方根里面。与年化回报相同,我考虑了 252 个交易日(在这种情况下,是 252 的平方根)来计算投资组合的年化标准差。

夏普比率

我想指出的第二点是夏普比率。为了理解夏普比率,有必要理解更广泛的风险调整回报率概念。风险调整回报通过衡量产生回报所涉及的风险来细化投资回报,这通常用数字或评级来表示。可能有许多不同的方法来表达风险调整后的回报,夏普比率是其中之一。

夏普比率是由另一位诺贝尔经济学奖得主威廉夏普于 1966 年得出的。

Sharpe was one of the originators of the CAPM (Capital Asset Pricing Model)

这个比率描述了你持有高风险资产所承受的额外波动带来的超额回报。夏普比率可以用下面的公式表示。

对于夏普比率如何使用回报率的标准差作为分母,假设回报率的正态分布,有一些批评。然而,通常情况下,金融资产的回报往往偏离正态分布,并可能使夏普比率的解释产生误导。正是由于这个原因,有其他方法来调整或修改原始夏普比率。但这是一个更高级的话题,对于这篇文章,我将坚持传统的夏普比率。

现在让我们获取函数所需的参数值。通过在带有价格数据的数据框上调用 pct_change,可以很容易地获得每日回报。平均日收益,收益的协方差矩阵是计算投资组合收益和波动性所需要的。我们将生成 25,000 个随机投资组合。最后,无风险利率来自美国财政部。1.78%的利率是 2018 年初的 52 周国库券利率。这背后的基本原理是,历史价格数据是 2016~2017 年的,如果我假设我在 2018 年初实施这一分析,最新的国债利率是从 2018 年初开始的。我还选择了 52 周的国库券利率来匹配我计算的年化回报和风险。

returns = table.pct_change()
mean_returns = returns.mean()
cov_matrix = returns.cov()
num_portfolios = 25000
risk_free_rate = 0.0178

让我简单解释一下下面的函数在做什么。首先,它生成随机投资组合,并获得结果(投资组合回报、投资组合波动性、投资组合夏普比率)和相应结果的权重。然后,通过找到具有最高夏普比率的投资组合,它将最大夏普比率投资组合显示为红星符号。对最小波动率投资组合做类似的步骤,在图上显示为绿色星号。所有随机生成的投资组合也将根据夏普比率绘制彩色地图。越蓝,夏普比率越高。

对于这两个最优投资组合,它还将显示如何在投资组合中分配预算。

display_simulated_ef_with_random(mean_returns, cov_matrix, num_portfolios, risk_free_rate)

对于最小风险投资组合,我们可以看到超过一半的预算分配给了谷歌。如果你再看一下之前的每日回报图,你会发现谷歌是四只股票中波动性最小的,因此将很大一部分股票分配给谷歌以获得最小风险的投资组合具有直观的意义。

如果我们愿意为了更高的回报而承担更高的风险,那么能给我们带来最佳风险调整回报的股票就是夏普比率最大的股票。在这种情况下,我们将很大一部分配置给亚马逊和脸书,从之前的每日回报图来看,这两只股票波动很大。谷歌在最小风险投资组合中占了 50%以上,但分配给它的预算不到 1%。

效率限界

从随机模拟的投资组合图中,我们可以看到它在聚集的蓝点顶部形成了一条弧线。这条线叫做有效边界。为什么有效率?因为对于给定的目标回报,沿线的点会给你最低的风险。直线右侧的所有其他点会给你带来更高的风险和相同的回报。如果预期回报是一样的,当有一个风险更低的选择时,你为什么要冒额外的风险呢?

我们找到上述两种最优投资组合的方法是通过模拟许多可能的随机选择,并挑选出最佳选择(最小风险或最大风险调整回报)。我们也可以通过使用 Scipy 的优化函数来实现这一点。

如果您是 excel 的高级用户,您可能熟悉 Excel 中的“规划求解”功能。Scipy 的 optimize 函数在给定要优化的内容以及约束和界限时执行类似的任务。

下面的函数是为了得到最大的夏普比率投资组合。在 Scipy 的优化函数中,没有“最大化”,所以作为一个目标函数,你需要传递一些应该最小化的东西。这就是为什么第一个“负夏普比率”计算负夏普比率。现在我们可以用这个作为目标函数来最小化。在“max_sharpe_ratio”函数中,您首先定义参数(这不应包括您想要为优化而更改的变量,在本例中为“权重”)。起初,约束的构造对我来说有点难以理解,这是由于它的表述方式。

constraints = ({‘type’: ‘eq’, ‘fun’: lambda x: np.sum(x)1})

上面的约束是说 x 的和应该等于 1。你可以把“有趣”部分的结构想象成等号右边的“1”被移到了等号的左边。

np.sum(x) == 1 变成了 np.sum(x)-1

这意味着什么?它仅仅意味着所有权重的总和应该等于 1。您分配的总额不能超过预算的 100%。

“bounds”给出了分配随机权重的另一个限制,即任何权重都应该在 0 和 1 之间。你不能给一只股票负的预算分配,也不能给一只股票超过 100%的分配。

我们还可以定义一个计算最小波动率投资组合的优化函数。这一次我们真的最小化目标函数。我们想要最小化什么?我们希望通过尝试不同的权重来最小化波动性。“约束”和“界限”同上。

正如我在上面已经提到的,我们也可以画一条线来描述给定风险率的有效投资组合应该在哪里。这就是所谓的“有效前沿”。下面我定义其他函数来计算有效边界。第一个函数“efficient_return”计算给定目标回报的最有效投资组合,第二个函数“efficient_frontier”将采用一系列目标回报,并计算每个回报水平的有效投资组合。

让我们试着用所有随机生成的投资组合来绘制具有最大夏普比率和最小波动性的投资组合选择。但这一次,我们不是从随机生成的投资组合中挑选最优的,而是使用 Scipy 的“最小化”功能进行计算。下面的函数也会画出有效的边界线。

display_calculated_ef_with_random(mean_returns, cov_matrix, num_portfolios, risk_free_rate)

我们从随机生成的投资组合中挑选,得到了几乎相同的结果。略有不同的是,Scipy 的“优化”功能没有为谷歌的最大夏普比率投资组合分配任何预算,而我们从随机生成的样本中选择的一个为谷歌分配了 0.45%的预算。小数位有些不同,但大致相同。

我们可以在图上用每只股票的年收益和年风险的相应值来绘制每只股票,而不是绘制每个随机生成的投资组合。这样,我们可以看到并比较多样化是如何通过优化配置来降低风险的。

display_ef_with_selected(mean_returns, cov_matrix, risk_free_rate)

从上面的图可以看出,风险最小的股票是谷歌,在 0.18 左右。但通过投资组合优化,我们可以实现 0.16 的更低风险,同时仍能获得比谷歌更高的回报。如果我们愿意在类似谷歌的风险水平上承担稍微多一点的风险,我们可以通过投资组合优化获得 0.30 的更高回报。

考虑到金融领域的广度和深度,我可能只是触及了皮毛。但是我在编码和试图理解这个概念的过程中获得了乐趣。我每天都在学习。做完这个实现,我肯定比昨天的我更清楚。如果我继续学习,大约几年后,我会比今天的我知道得更多。如果您有任何意见或问题,请随时留下您的评论。任何反馈都将不胜感激。

感谢您的阅读。你可以从下面的链接找到 Jupyter 笔记本。

https://github . com/tthustlea/Efficient _ Frontier/blob/master/Efficient % 20 _ Frontier _ implementation . ipynb

TensorFlow 中的特征向量投影自动编码器

原文:towardsdatascience.com/eigen-vecto…

GIF from this website

最近我一直在玩特征值和向量以及投影。(通过点积)现在我想看看它们是如何被整合到神经网络中的。(自动编码器)。此外,请注意,我在这里使用的技术与执行主成分分析(PCA )时非常相似,但并不完全相同。(具体来说,我没有删除维度,也没有对特征值进行排序)。所以我不会叫它 PCA。在这篇文章中,我将比较不同的自动编码器,如…..

情况 a)改变潜在向量基的自动编码器 情况 b)改变潜在向量基并增加网络参数的自动编码器 情况 c)普通自动编码器 情况 d)改变潜在向量基的自动编码器(不同的激活函数) 情况 e)改变隐藏层基的自动编码器 情况 f)改变隐藏层基的自动编码器(2)

请注意,这个帖子只是为了自己表达创意。

网络架构/数据集

蓝色矩形 →卷积/全连接层 红色矩形 →转置卷积/全连接层

如上所述,我们的网络仅由 3 个卷积运算、2 个全连接层和 2 个用于上采样的转置卷积运算组成。对于下采样操作,我选择使用下采样操作。现在我将要使用的数据集是著名的 MNIST 数据集。

情况 a)自动编码器改变潜在向量的基础

红色部分 →自动编码器潜在向量的基础变化

由于我们要将维度从 28*28 降低到 3,因此我们实际上可以计算隐藏表示的协方差矩阵,并使用协方差矩阵的特征向量来投影原始数据。

左侧 GIF →生成的训练图像 右侧图像 →训练阶段的时间成本

网络在生成原始图像方面表现不佳,大多数图像都很模糊,甚至与原始图像不接近。现在让我们来看看编码向量的潜在空间。

如上所述,在改变基底之前,我们可以看到编码器实际上在将相似图像彼此聚类方面做得很好。

然而,在投影到本征向量后,我们可以看到,现在数据已经混合在一起,显然彼此不能完全分开。

情况 b)增加了网络参数 改变了潜在向量的基的自动编码器

现在,我添加了一个名为 network_effect 的参数,这是一个来自均匀分布的 3*3 矩阵。(范围 0–1)。这是因为我想让网络对投影空间有更多的控制。

左图 GIF →生成的训练图像 右图 →训练阶段的时间成本

与情况 a)相比,该网络做得还不错,然而,同样,大多数生成的图像是模糊的,不可识别的。

同样,当我们可视化编码的潜在空间时,我们观察到编码器在聚类相似图像方面做得很好。(投影前)

但是,在向量投影之后,每一类之间的编码空间实际上恶化了。

案例 c)普通自动编码器

被上面两个网络的性能所质疑,我想知道网络架构本身是否是问题所在。所以我训练了一个普通的自动编码器。

左侧 GIF →生成的训练图像 右侧图像 →训练阶段的时间成本

与其他网络相比,vanilla 在生成和分离潜在空间中的数据方面做得最好。

如上所述,每种颜色的数据点都很好地聚集在一起。

情况 d)自动编码器改变潜在向量的基础(不同的激活函数)

红色部分 → Tanh 激活功能

从以前的 GIF 中,我们可以观察到生成的潜在空间的范围是巨大的。(当我们要生成数据的时候,这不是一件好事。所以我想看看当我使用一个双曲正切函数而不是一个恒等函数时,事情会有什么变化。

左侧 GIF →生成的训练图像 右侧图像 →训练阶段的时间成本

不幸的是,生成的图像非常模糊,不是最好的。

如上所述,现在潜在空间在更近的范围内,但是数据点彼此之间的聚类很差。非常非常差。

然而,在投射之后,它产生了我所见过的最有趣的图案。我希望回到这件事上来,因为它太有趣了。

情况 e)隐藏层 基础改变的自动编码器

现在,我想看看当我在创建潜在空间的完全连接的层后面的层上执行投影时的效果。(如果我可怕的描述没有意义,请理解为我在不同的层上做了相同的操作。)

网络实际上在生成新图像方面做得很好,当我们观察潜在空间时,我们可以观察到类似的潜在空间,当我们与普通的自动编码器进行比较时。

实际上,我认为它比普通的自动编码器做得更好。

情况 f)自动编码器与隐藏层的基础变化(2)

前一个实验者的自然延伸是在不同的层上执行相同的操作。(在这里,我将在前面两层上执行它。)

尽管这个网络产生了最有趣的图像模式,但实验还是彻底失败了。

当我们看到潜在空间时,我们可以看到这些数据点是无法区分的。

互动码

对于 Google Colab,您需要一个 Google 帐户来查看代码,而且您不能在 Google Colab 中运行只读脚本,所以请在您的操场上创建一个副本。最后,我永远不会请求允许访问你在 Google Drive 上的文件,仅供参考。编码快乐!同样为了透明,我在 github 上上传了所有的训练日志。

要访问案例 a 的代码,请单击她的 e,要查看日志,请单击此处。 点击 h 查看案例 b 的代码,点击 l ogs 点击此处。 要访问案例 c 的代码,单击 re,要查看日志,单击此处。 点击此处访问 r 案例 d 的代码,点击此处查看日志。 访问案例 e 的代码点击此处,日志的点击此处。 点击此处查看案例 f 的代码,点击此处查看日志。

最后的话

这是一个非常有趣的实验,通常我认为自动编码器本身就是一种降维的方法。但是现在,我越来越想知道是否可以在网络中加入额外的技术。

如果发现任何错误,请发电子邮件到 jae.duk.seo@gmail.com 给我,如果你想看我所有写作的列表,请在这里查看我的网站。

同时,在我的 twitter 上关注我这里,访问我的网站,或者我的 Youtube 频道了解更多内容。我还实现了广残网,请点击这里查看博文 t。

参考

  1. 导入 tflearn 错误:属性错误:模块“熊猫”没有属性“计算”问题#766 tflearn/tflearn。(2018).GitHub。检索于 2018 年 7 月 11 日,来自github.com/tflearn/tfl…
  2. 适合 ML 初学者的 MNIST。(2018).张量流。检索于 2018 年 7 月 11 日,来自https://www . tensor flow . org/versions/r 1.0/get _ started/mnist/初学者
  3. 警告,T. (2018)。Tensorflow 导入 mnist 警告。堆栈溢出。检索于 2018 年 7 月 11 日,来自https://stack overflow . com/questions/49901806/tensor flow-importing-mnist-warnings
  4. TensorFlow,E. (2018)。张量流中的特征值问题。堆栈溢出。检索于 2018 年 7 月 11 日,来自https://stack overflow . com/questions/43697539/tensor flow 中的特征值问题
  5. 基本功能的领域和范围。(2018).Analyzemath.com。检索于 2018 年 7 月 11 日,来自http://www . analyze math . com/domain range/domain _ range _ functions . html
  6. tf.self _ 共轭 _eig | TensorFlow。(2018).张量流。检索于 2018 年 7 月 11 日,来自https://www . tensor flow . org/API _ docs/python/TF/self _ 共轭 _eig
  7. (2018).Users.stat.umn.edu。检索于 2018 年 7 月 11 日,来自users.stat.umn.edu/~helwig/not…
  8. tf.random_uniform | TensorFlow。(2018).张量流。检索于 2018 年 7 月 11 日,来自https://www . tensor flow . org/API _ docs/python/TF/random _ uniform
  9. tf.self _ 共轭 _eig | TensorFlow。(2018).张量流。检索于 2018 年 7 月 11 日,来自https://www . tensor flow . org/API _ docs/python/TF/self _ agreement _ EIG
  10. 实施主成分分析(PCA)。(2014).塞巴斯蒂安·拉什卡博士。检索于 2018 年 7 月 11 日,来自https://sebastianraschka . com/Articles/2014 _ PCA _ step _ by _ step . html # 4-计算-特征向量-及对应-特征值
  11. MNIST 手写数字数据库,Yann LeCun,Corinna Cortes 和 Chris Burges。(2018).Yann.lecun.com。检索于 2018 年 7 月 11 日,来自yann.lecun.com/exdb/mnist/

Eigenfaces:从鬼魂中找回人类

原文:towardsdatascience.com/eigenfaces-…

Figure #1: Casper the Friendly Ghost (source: vignette.wikia.nocookie.net/christmassp…)

用更少的拥有更多…简单!这种机器学习方法将帮助你只用一些线性代数基础知识就能在更小的空间里存储更多的信息。到那时,我们将从一些鬼影形状的混乱中恢复人脸。

你一定听说过,独立矢量以抽象的方式创造空间。现在,想象一下真实情况。所有的空间都是由向量构成的,这些空间里的东西也是如此。其中一些向量对某些事物的贡献比其他的更大。除了他们之外,其他人可能可以忽略不计,也许我们不需要知道这些,因为我们基本上不在乎,也不想带着他们的问题。这正是我在这篇文章中向你展示的特征脸。

Figure #2: not this space but also this space (source: img.purch.com/w/660/aHR0c…)

我们的主题是 PCA。它是一种广泛应用于各种学科的算法。在人脸上使用它使它更容易被人类理解,所以它是最受欢迎的应用之一。本征脸是一种用于人脸识别和检测的方法,通过确定人脸图像集合中人脸的方差,并使用这些方差以机器学习的方式对人脸进行编码和解码,而不需要完整的信息,从而降低了计算和空间复杂度。尽管它在 1991 年由 Turk 和 Pentland 首次使用,并且与今天的技术相比有局限性,但它的基本原理仍然对新的实践非常有益。

Figure #3: LFW (source: vis-www.cs.umass.edu/lfw/Six_Fac…)

在开始实现之前,我想向您简单介绍一下提到的基本概念。此外,你可以找到完整的脚本和数据集(一小部分LFW _ 裁剪)我用在这里

特征向量和特征值

我们都知道特征向量和特征值是如何工作的。也许不完全是,但是我们听说过,好像,很多次了。这里给我这种不断遗忘的少数人一个解释。

让我们有一个正方形一个矩阵。几乎所有的矢量在乘以 A 时都会改变方向,就像我们预期的那样。然而,某些向量 xAx 方向完全相同。你猜怎么着?这些是我们的特征向量。特殊的……即使方向相同, Axx 仍然可能是大小不同的两个矢量。这里有一个熟悉的等式。 Axx 。使这两者相等的是λ,我们的幅度均衡器标量,特征值。这将告诉我们,我们的特征向量在相乘后是如何变化的

从上面,你可以知道为什么它们在实践中有用。为了更深入的理解和欣赏,请阅读麻省理工学院的特征值和特征向量章节。

主成分分析

PCA 的主要目标是降维。它在可视化、特征提取、数据压缩等方面有许多应用。其背后的思想是将原始数据线性投影到较低维度的子空间上,提供投影数据的主分量(特征向量)最大方差和/或投影的最小失真误差。最终,两者导致相同的结果,即最佳重建公式。作为旁注,这个子空间叫做主子空间。

关于方差最大化和失真误差最小化的计算,可以去 ANU 关于 PCA 的讲义。此外,youtube 上另一个名为主成分分析-佐治亚理工学院-机器学习的视频帮助我更好地理解了这些概念。

履行

好吧!每个人都准备实施。首先,我们将导入所需的库。我想你们都知道它们是干什么用的。我将把重点放在算法的解释部分。如果您对代码有任何其他问题,请在下面回复。

然后,我们需要一个函数来以一种好看的方式可视化我们数据集中的图像。在这里。

让我们把它放到我们的数据集上 lfwcrop_grey.zip 。这里,由于计算的复杂性,我只取了前 1000 张脸,但这真的没关系。如果你想满座,那就去吧。我还将图像转换成 numpy 数组(形状为 1000,64,64)进行处理。

Figure #4: Left: The people that I thought it would be nice to viualise / Right: 16 Random Famous People that I don’t actually care from the dataset of 1000

右边的表是我将实际使用的表。我基本上可视化了 1000 个数据集中的前 16 个图像。左边的是一个数据集,当我不知道自己在做什么的时候,我从原来的数据集上收集的。然而,我注意到最好有更多的数据来更清楚地解释这些概念。

继续,下一步是定义 PCA。它的参数是图像的向量 X 和主成分的数量 n_pc。提醒一下,主成分定义了一个正交基,它可以提取原始数据中的最大方差。在我们的例子中,它的形状是(1000,4096),因为我们需要将图像转换成 PCA 的向量。然后,我们找到平均值,并将其从数据中减去,使其以原点为中心。之后,我们需要对中心数据进行奇异值分解,以找到那些被称为特征脸的主分量。

S matrix has the singular values along the diagonal while U and V are singular vectors

(SVD 很难得到,而且比那复杂得多。为了得到一个有用的例子,去麻省理工学院开放式课程视频。)

Figure #5: mean face

顺便说一下,这是数据集中所有 1000 张人脸的平均脸。我们试图找到使个人与其他人不同的特征。我希望减去每个人的平均脸和最大化方差现在更有意义。看那个。小心!有点吓人,不是吗?

接下来的步骤是操纵我们的图像成为向量,调用 PCA 函数并操纵我们的特征脸再次成为图像。

Figure #6: Bunch of ghost shaped images. Look at them in the eyes.

名为 n_components 的第一个参数决定了我们想要创建多少个特征面。这些是我们的主要组成部分,我们将从中恢复我们的数据,即人脸。除非小于 16,否则改变它不会改变这个表。然而,我可以保证只有 50 张图片是我们可以信任的,而不是一开始的 1000 张。(本征脸.形状= (50,64,64))

对于重建,我们将使用这些特征脸。正如你可能会说的,每张脸都是这些特征脸的加权组合。为了找到权重,我们应该点乘我们的中心数据和特征脸。然后,我们应该对特征脸进行加权,得到中心脸,然后再把它加到平均脸上。毕竟,我们已经准备好将恢复的人脸与原始人脸进行对比。

Figure #7: n_components=50

哇!不好看!但是,别忘了我们是从 1000 x 64 x 64 到 50 x 64 x 64 的。这样,我们保留的数据比以前少了 20 倍。尽管如此,我不会愚弄任何人。这些还不够好。很明显,我们仍然有一些重要的主要成分。让我们看看我们能做什么。我将尝试使用前 100 个组件。

Figure #8: n_components=100

越来越好,但仍然不够好。250…

Figure #9: n_components=250

这个对我来说完全令人满意。仅用我们所拥有的四分之一,我们就恢复了完全可辨别的面孔。这完全没有意义,但你可以使用 1000 个特征脸组件,并获得准确的原始结果。为了向你们展示这一点,我将运行一些计算和空间复杂度。

还在跑…坚持住…来了。

结果出来了。相当甜蜜!!!

Figure #10: n_components=1000

这篇文章实际上向你展示了用很少的数据就能获得足够好的信息,这是我们对机器学习最重要的期望之一。我希望你能看到这个应用之外的东西,并开始思考新的创新。我陈述了我在上面使用的参考文献。

再次希望你喜欢我的帖子。不要犹豫提出你的问题或给出任何类型的反馈。

干杯,

Nev

给我更多的内容和支持关注!

TwitterLinkedIn 上与我联系……

人工智能中的肘聚类

原文:towardsdatascience.com/elbow-clust…

聚类是将一堆未分类的东西(你的数据集)根据相似性分成几堆(即聚类)的过程。这是一个无人监督的过程(不需要训练的例子)。也许最常见的方法是使用 k-means(T1),我将介绍一种不同的方法,使用高斯混合模型(GMM)和一些其他的东西(T3)。

我们今天的例子是在一个数据集中分离两种类型的图片,在你的数据集中,你实际上没有一个标签或者一个分类器。正如我们将要看到的,只要看看结果,你就能明白它的工作原理。首先,我想说明这种方法并不总是有效,因此需要一些微调。

在你的人工智能项目的每个主要步骤中,你需要记住的第一件事是 用你的眼睛 看你的数据。我再怎么强调都不为过,如果你看不到 k 均值在做什么,它可能会愚蠢地出错

从我在关于图像数据集集合的文章中停止的地方继续,让我们使用 k-means 和 GMM 通过感知哈希来进行图像聚类。如果您只是想找到哪些图片与其他图片相似,在 imagehash 代码中有一个示例可以做到这一点。我们在这里尝试做的更多一些:我们想要将数据分成类别(即使我们不知道类别是什么)。在 GitHub 上有一个这种类型的库的例子,它只被许可用于学术用途。

不管我们选择什么样的库,我们都会立即遇到一个问题:我们最终想要多少个集群?这不是聚类库给你的。你需要决定,决定集群的数量应该基于一些逻辑。我们应该使用……肘法!

肘法对于一个简单的想法来说是一个奇怪的名字。不断添加集群,直到你看到收益递减,然后停止。对于 k-means,这意味着从 2 个均值开始,然后是 3 个均值,以此类推,直到 k。GMM 也是同样的想法。当我们在解释方差与聚类数的关系图中看到一个拐点时,我们后退并选择看到拐点的聚类数。在下图中,您可以看到前两个点是手臂,4 处的点是肘部,前臂是 5 到 8 处的点。

Graph of explained variance vs cluster count, where the red circle shows the elbow. (from wikipedia)

我知道:我们计算机人现在应该停止给东西命名。图灵机循环赛k-maps ,就是不停。

参见“ Python Machine Learning ”第 148 页上的图,了解数据集的一些组件如何比其他组件包含更多差异(PCA)。在早期停止期间,当决定何时停止训练时,肘方法同样有效,但是在这种情况下,数据通常更嘈杂。基本上,当看起来不值得努力时,我们就停下来。

为什么这个肘法的东西不太为人所知?嗯,我想这有点主观,所以那些想知道确切数字的人会感到奇怪。此外,当我们对事物进行聚类时,我们往往会想到一些聚类,这通常是出于愚蠢的原因,但这是事实。例如,我更喜欢有一些我小小的大脑理解的集群(例如,一个小数字),而不是数学告诉我真正需要的数字。此外,我也遇到过集群数量受到硬件限制等外部因素限制的情况。可能有 299,945 种交易模式类型,但如果我在 GPU 上的时间有限空间有限的神经网络只能在有用的时间内分析 2,048 种模式类型,那么我想我们会有 2,048 个聚类。在研究文献中有许多使用肘法的例子。在我们的例子中,我们会看到肘法并不是唯一的游戏。

让我们继续做我们来这里要做的事情:使用感知哈希用肘方法聚类图片!让我们对来自标准图像数据集的图像进行排序,看看我们最终得到了哪些子类型。这里的目标是对图像 进行排序,而不使用 使用基础事实标签来进行排序(即聚类)。我们要用 k-means 做的事情是无人监督的。它只是看着图片,把图片整理成一堆堆。使用带有标签的数据集的原因只是为了帮助在排序过程对数据集所做的事情之后进行可视化。实际上,你会用眼睛看每一组中的图片,并对它的作用有一个直观的感觉。

在我们今天的例子中,我们将使用 Caltech101 数据集的“Faces”和“airplanes”子文件夹。我们把这些图片像一副扑克牌一样混在一起,然后把它们堆成一大堆。现在想象这是一些图像抓取作业的输出。

对于上一篇文章中的叶数据集,我们最终得到的是 4102 行× 2 列,它确切地告诉我们每个图像的散列是什么。大约 20%的原始 5000+图像不会生成散列,通常是因为文件在抓取过程中不知何故被损坏。让我们更好地理解刚刚发生了什么…

Screenshot of the dataframe printing out after the hashing is completed.

我们需要解开这个鬼鬼祟祟的东西,我们称之为哈希。我们可以通过减去两个不同图像的哈希来计算图像之间的差异,但此时会出现一些奇怪的情况。尽管我们能够对这个散列值使用减法运算符,但它实际上并不做减法。通过简单地增加散列而不是减少来证明这一点,它将不会如此优雅地编译失败。那么,我们在输出端得到的这个哈希是什么呢?嗯,它是每张图片的布尔值字段。很明显,hash 字符串中的字符是十六进制的,所以打印一个元素可以揭示隐藏在这个漂亮字符串下面的 hash 的真实性质:它是一串二进制数。

The binary result of the hash is hiding inside the hex string….

那么,当我们“比较”散列时,减法运算到底在做什么呢?它执行 XOR 运算,并计算不相同的位数。换句话说,图像之间的“差异”被量化为两个图像的散列中的差异数量的计数。我们可以使用这个方便的小脚本来证明这一点…

运行该脚本时,我们会看到以下输出:

Counting the bits that didn’t match gives the same result as “subtracting” hashes.

所以,这是相当卑鄙的,但现在我们知道,散列之间的距离不是一个可排序的属性。它根据我们使用哪两张图像作为输入而变化。我们真正想说的是,我们计算海明距离。在 scipy land,这个指标在距离指标列表中排名第 8。

现在,进行聚类!我们的散列字符串中有 4 位十六进制字符,每个散列中有 16 个字符。这给了我们 64 个维度来比较图像。我们需要更新我们的 pandas 数据帧,以包括 64 个列(每个哈希特性一个)。

我们最终得到了我们想要的 64 个新列。

使用来自这篇文章的代码,我们可以获得完整图像数据集的一些漂亮的图表,包括解释方差的百分比。

This figure is for hashed generated by pHash. It shows the increase in explained variance as we add clusters.

我们在上图中看到,在大约 8 或 9 个集群时,我们开始失去动力。此外,由于模型无法解释大多数方差,因此它不是一个非常有用的预测器。

This figure is for hashed generated by the average hash. It shows the increase in explained variance as we add clusters.

类似于感知哈希图,我们在上图中看到,在大约 8 或 9 个集群时,我们开始失去动力。与上图中的感知哈希相比,这种方法可以解释更多的差异(顶行是 40%,而不是 14%)。在这个图中,我们还看到了一个更好的弯头。它仍然不是一个超级有用的预测工具,但比以前好了。

现在我们有了一些答案,这意味着什么呢?每一堆都聚集了哪些图像?嗯,只有在一些受限的情况下,集群才能很好地工作。让我们看看在文章开始时混合在一起的两种图像(飞机和面孔),看看聚类是否能够将这两种图像类型分开。让我们比较一下 GMM 解混和 k-means,看看对于这个问题哪个是更好的无监督“解混器”。

首先,这是 K-means 的代码:

结果看起来像这样:

Cluster 0 is red, and cluster 1 is green. In the chart above, we can see that counting up all of the images containing faces, 90.8% ended up in cluster 0. Similarly 62.6% of the images with faces in them ended up in cluster 0. This is not a nice outcome.

有 800 张飞机照片和 435 张人脸照片。

正如我们在上面的饼图中所看到的,在两个集群中,飞机和人脸没有很好的分离。我们可以选择两个集群,因为我们知道有两个东西可以分成两堆。这两个类的内容最终大部分集中在 0 类中。在 GMM,我们看到了一个不同的故事。

让我们先看看 GMM 的代码,然后看看结果。

现在是几个运行示例的结果:

所以这些结果要好得多。GMM 把这些文件分成一个文件夹,里面大部分是人脸,另一个文件夹里大部分是飞机。

我们可以通过运行几次 GMM 来挑选结果,以查看何时分割看起来不错(通过对结果图像数据集的视觉检查)。我们还可以标记数据的一些子集,使用上面的代码,我们只需查看饼状图就可以了解拆分是如何进行的。这种方法比成熟的图像分类器需要更少的数据。还有 50 种其他的方法可以做到这一点,但是把这个算作第 51 种方法。

克隆它!!

我已经为你提供了代码,希望这能帮助你更好地处理你收集的图片。在很多课程中,这变得非常混乱,但是我有一个建议。经常发生的情况是,在很多类中,垃圾图像和重复图像聚集在一起,帮助你删除垃圾图像。然后,您可以重新集群,看看会发生什么。K-means 有时会起作用,在这种情况下,GMM 稍微好一点。世事难料。基本上,尝试很多东西,你会马上知道它什么时候起作用。

因此,总之,感知哈希可以用来将图像压缩到一组二进制维度,k-means、GMM 或其他无监督的方法可以根据这些维度将图像分类。

如果你喜欢这篇关于用 k-means 和 elbow 方法对图像进行聚类的文章,看看我过去读过的一些文章,比如“如何给一个人工智能项目定价”和“如何雇佣一个人工智能顾问”除了与商业相关的文章,我还准备了一些关于寻求采用深度机器学习的公司所面临的其他问题的文章,如“没有云和 API 的机器学习

编码快乐!

-丹尼尔 丹尼尔@lemay.ai ←打个招呼。 LEMAY . AI 1(855)LEMAY-AI

您可能喜欢的其他文章:

数据科学家的薪酬要素

原文:towardsdatascience.com/elements-of…

到目前为止,我在大会经历中最喜欢的部分是网络抓取项目。虽然在我们将在数据科学沉浸式课程中涉及的更简单的任务中,web 抓取是我最感兴趣的。我甚至写过两篇关于编写一个简单的 scraper 的博文(这篇博文的灵感来自这个项目)。

该项目的目标是找出哪些特征或变量与高薪数据科学家职位最直接相关。为了收集数据,我们在 indeed.com 运行了一个 web scraper,从美国 40 多个城市的招聘信息中提取数据。然后对数据进行处理,以创建逻辑元素,最大限度地让我们确定何时一份工作的薪酬高于全国职业的中位数。该项目得出的结论是,除了更直接的“数据科学家”术语,对决策重要的其他特征是术语“定量”、“工程师”和“机器”。没有特定的技能或编程语言成为最重要的词汇,然而,亚利桑那州和俄勒冈州都登记为负面影响特征。

我的方法

这些数据是使用一个 web scraper 获得的,该 web scraper 针对术语“数据科学家”迭代了 350 多个页面,并针对 42 个美国城市重复了这一过程。对于 scraper 找到的每个职位发布,它都记录了职位名称、位置、公司名称和薪水。绝大多数帖子不包括工资数据,由于它们是这个项目的目标,我只能使用包括上述数据的条目。

然后,salary 列被转换为 float,如果提供了范围,则进行平均。基于月/周/日的工资数据被转换以匹配单位:美元/年。当工资浮动数据准备就绪时,我取数据的中间值,并将高于和低于该值的任何条目分别转换为二进制 1 和 0。当我们创建模型中使用的变量时,这个过程被重复。这背后的基本原理是因为我们正在尝试使用逻辑分类来解决这个问题,它适用于二元选择。

在使用上述过程为职位和位置(按州)中的几个关键词设置变量后,我利用了一个过程,该过程对职位的所有条目中的单词进行计数,并根据它们与成功结果(即正确预测)的相关程度对它们进行排序。这个项目选择的模型是 Random Forest,这是一个分类聚合器,将使用二进制数据进行位置和“单词排序”。

结果

当预测与我们在实验开始前生成的测试数据集进行比较时,该模型产生了 89%的准确率。在被认为对预测很重要的显著特征中,该模型确定,除了职位名称中“数据、科学家、研究、分析师”及其组合等显而易见的词之外,还有一些其他被认为很重要的词:定量、机器、高级和技术人员,顺序如下。根据该模型,排名前 15 位的唯一一个州是亚利桑那州,排在第 10 位。

当我使用 Scikit Learn 在逻辑回归模型上运行相同的变量时,使用与上述相同的标准,我最终得到了 84%的相似准确度分数。尽管重要性的度量并不等同于系数值的排名,但我能够看到我的随机森林模型识别的特征也是逻辑回归模型中更具影响力的变量:数量、工程师、高级、亚利桑那州,这些特征都与成功的预测有非常积极或消极的关系。

下面我提供了一个简短的表格,列出了来自随机森林模型的单词作为特征及其各自的重要性,以及来自逻辑回归模型的单词及其各自的系数:

  • 抱歉,尺寸有问题..

最后的想法…

总结从这项研究中得出的所有信息,当发布工作或寻找工作时,要注意你的用词会对薪水期望和潜在的谈判优势产生影响。在更大范围的求职中,进行像我这样的研究并不特别耗时,所以花点时间去调查市场。最坏的情况是,如果你获得了这些链接,你就有了一个很好的工作数据库和申请方法,让你的求职工作效率成倍提高。

带 TensorFlow hub 的 Keras 中的 Elmo 嵌入

原文:towardsdatascience.com/elmo-embedd…

新发布的 Tensorflow hub 提供了一个简单的接口,可以使用现有的机器学习模型进行迁移学习。然而,有时启动 Keras 并快速构建模型原型也是不错的。通过一些修复,很容易将 Tensorflow hub 模型与 Keras 集成在一起!

Allen NLP 开发的 ELMo 嵌入,是 Tensorflow Hub 上许多优秀的预训练模型之一。ELMo 嵌入从双向 LSTM 的内部状态中学习,并表示输入文本的上下文特征。在各种各样的自然语言处理任务中,它的表现都优于 GloVe 和 Word2Vec 嵌入。

A bidirectional LSTM is trained on a large text corpus, and the internal states are combined to calculate rich, context sensitive features of text.

这是我们在 Strong Analytics 的团队最近使用 Keras 中最先进的 ELMo 嵌入技术制作的一个 NLP 模型的原型。

首先,我们加载一些数据:

# Load all files from a directory in a DataFrame.
def load_directory_data(directory):
  data = {}
  data["sentence"] = []
  data["sentiment"] = []
  for file_path in os.listdir(directory):
    with tf.gfile.GFile(os.path.join(directory, file_path), "r") as f:
      data["sentence"].append(f.read())
      data["sentiment"].append(re.match("\d+_(\d+)\.txt", file_path).group(1))
  return pd.DataFrame.from_dict(data)

# Merge positive and negative examples, add a polarity column and shuffle.
def load_dataset(directory):
  pos_df = load_directory_data(os.path.join(directory, "pos"))
  neg_df = load_directory_data(os.path.join(directory, "neg"))
  pos_df["polarity"] = 1
  neg_df["polarity"] = 0
  return pd.concat([pos_df, neg_df]).sample(frac=1).reset_index(drop=True)

# Download and process the dataset files.
def download_and_load_datasets(force_download=False):
  dataset = tf.keras.utils.get_file(
      fname="aclImdb.tar.gz", 
      origin="http://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz", 
      extract=True)

  train_df = load_dataset(os.path.join(os.path.dirname(dataset), 
                                       "aclImdb", "train"))
  test_df = load_dataset(os.path.join(os.path.dirname(dataset), 
                                      "aclImdb", "test"))

  return train_df, test_df

# Reduce logging output.
tf.logging.set_verbosity(tf.logging.ERROR)

train_df, test_df = download_and_load_datasets()
train_df.head()

我们接下来处理我们的数据。注意,要使用字符串作为 Keras 模型的输入,我们需要创建一个 numpy 对象数组。我已经将这些数据限制为内存的前 150 个字(ELMo 嵌入是计算密集型的,所以使用 GPU!).

# Create datasets (Only take up to 150 words)
train_text = train_df['sentence'].tolist()
train_text = [' '.join(t.split()[0:150]) for t in train_text]
train_text = np.array(train_text, dtype=object)[:, np.newaxis]
train_label = train_df['polarity'].tolist()test_text = test_df['sentence'].tolist()
test_text = [' '.join(t.split()[0:150]) for t in test_text]
test_text = np.array(test_text, dtype=object)[:, np.newaxis]
test_label = test_df['polarity'].tolist()

要在 Keras 中实例化 Elmo 嵌入,我们首先必须创建一个自定义层,以确保嵌入权重是可训练的:

class ElmoEmbeddingLayer(Layer):
    def __init__(self, **kwargs):
        self.dimensions = 1024
        self.trainable = True
        super(ElmoEmbeddingLayer, self).__init__(**kwargs)def build(self, input_shape):
        self.elmo = hub.Module('[https://tfhub.dev/google/elmo/2'](https://tfhub.dev/google/elmo/2'), trainable=self.trainable, name="{}_module".format(self.name))self.trainable_weights += K.tf.trainable_variables(scope="^{}_module/.*".format(self.name))
        super(ElmoEmbeddingLayer, self).build(input_shape)def call(self, x, mask=None):
        result = self.elmo(K.squeeze(K.cast(x, tf.string), axis=1),
                      as_dict=True,
                      signature='default',
                      )['default']
        return resultdef compute_mask(self, inputs, mask=None):
        return K.not_equal(inputs, '--PAD--')def compute_output_shape(self, input_shape):
        return (input_shape[0], self.dimensions)

现在,我们可以使用 ElmoEmbeddingLayer 构建和训练我们的模型:

input_text = layers.Input(shape=(1,), dtype=tf.string)
embedding = ElmoEmbeddingLayer()(input_text)
dense = layers.Dense(256, activation='relu')(embedding)
pred = layers.Dense(1, activation='sigmoid')(dense)model = Model(inputs=[input_text], outputs=pred)model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
model.summary()model.fit(train_text, 
          train_label,
          validation_data=(test_text, test_label),
          epochs=5,
          batch_size=32)

就是这样!tensorflow hub 上有很多很棒的模型,一定要全部试用!

点击这里查看 IPython 笔记本:https://github . com/strong io/keras-Elmo/blob/master/Elmo % 20 keras . ipynb'

想和芝加哥的顶级数据科学家团队一起从事各种行业中具有挑战性的 NLP、机器学习和 AI 工作吗?我们正在招聘有才华的数据科学家和工程师!

strong.io 了解更多信息,并在 careers.strong.io 申请

ELMo 有助于进一步提高你的句子嵌入

原文:towardsdatascience.com/elmo-helps-…

by pixabay.com/en/universa…

在最后一个故事中,上下文化的单词向量 (CoVe)被引入,这是单词嵌入的增强版本。Peters 等人提出了深度语境化单词表征,旨在为不同语境下的自然语言处理任务提供更好的单词表征。他们称之为 ELMo(来自语言模型的嵌入)。

看完这篇帖子,你会明白:

  • 语言模型设计中的嵌入
  • 体系结构
  • 履行
  • 拿走

语言模型设计中的嵌入

Photo by Conor Luddy on Unsplash

ELMo 使用双向语言模型(biLM)来学习单词(例如,句法和语义)和语言上下文(即,对多义性建模)。在预训练之后,向量的内部状态可以被转移到下游的 NLP 任务。Peters 等人使用 6 个 NLP 任务来评估 biLM 的结果。

这些任务分别是问答文本蕴涵语义角色标注指代消解命名实体抽取情感分析。他们都取得了优异的成绩。

体系结构

与传统的单词嵌入不同,ELMo 针对不同的场景,为每个单词生成多个单词嵌入。较高层捕获单词嵌入的上下文相关方面,而较低层捕获语法的模型方面。在最简单的情况下,我们只使用 ELMo 的顶层(只有一层),同时我们也可以将所有层合并成一个矢量。

Peters et al. (2018)

我们可以连接 ELMo 向量和令牌嵌入(单词嵌入和/或字符嵌入)以形成如下新嵌入:

在实验中,Peters 等人使用 L=2 (2 个 biLSTM 层),其中 4096 个单元和 512 个输出维度用于上下文相关部分,而 2048 个字符 n-gram 构成过滤器和 512 个输出维度用于上下文不敏感部分,以构建上下文化的单词嵌入。

履行

原作者是 McCann 等人,他们用 python 3.6 通过 Pytorch 实现了 ELMo。有 Tensorflow,chainer 和 Keras 版本可供选择。我将使用 Keras 版本来演示我们如何将文本转换为矢量。对于其他人,您可以查看参考资料部分提到的 githubs。

下面的例子展示了我们如何使用 keras 来实现它。 Tensorflow Hub 是一个模型 Hub,存储了大量不同的模型。如果您只需要一个预训练的嵌入,您可以使用下面的代码从 Tensorflow Hub 中检索它并传输到 Keras。

可以从 Tensorflow Hub 预训练模型中选择 2 个嵌入层(总共有 5 层)。第一个“elmo”是其他 3 层的加权和。第二个是“默认”,它是所有层的固定均值轮询。你可以从这里找到更多信息。

在我的演示中,有 3 种方法可以使用 ELMo 预训练模型。它们是:

  1. 具有单词嵌入的 3 层的加权和
  2. 没有单词嵌入的 3 层的加权和
  3. 不含单词嵌入的固定均值池

1。具有单词嵌入的 3 层的加权和

# Input Layers
word_input_layer = Input(shape=(None, ), dtype='int32')
elmo_input_layer = Input(shape=(None, ), dtype=tf.string)# Output Layers
word_output_layer = Embedding(
    input_dim=vocab_size, output_dim=256)(word_input_layer)
elmo_output_layer = Lambda(
    elmo_embs.to_keras_layer, 
    output_shape=(None, 1024))(elmo_input_layer)
output_layer = Concatenate()(
    [word_output_layer, elmo_output_layer])
output_layer = BatchNormalization()(output_layer)
output_layer = LSTM(
    256, dropout=0.2, recurrent_dropout=0.2)(output_layer)
output_layer = Dense(4, activation='sigmoid')(output_layer)# Build Model
model = Model(
    inputs=[word_input_layer, elmo_input_layer], 
    outputs=output_layer)
model.compile(
    loss='sparse_categorical_crossentropy', 
    optimizer='adam', metrics=['accuracy'])
model.summary()
model.fit(
    [x_train_words, x_train_sentences], y_train,
#     validation_data=([x_test_words, x_test_sentences], y_test), 
    epochs=10, batch_size=32)

结果

Accuracy:77.10%
Average Precision: 0.78
Average Recall: 0.77
Average f1: 0.76

2。没有单词嵌入的 3 层的加权和

# Input Layers
elmo_input_layer = Input(shape=(None, ), dtype=tf.string)# Output Layers
output_layer = Lambda(
    elmo_embs.to_keras_layer, 
    output_shape=(None, 1024))(elmo_input_layer)
output_layer = BatchNormalization()(output_layer)
output_layer = LSTM(
    256, dropout=0.2, recurrent_dropout=0.2)(output_layer)
output_layer = Dense(4, activation='sigmoid')(output_layer)# Build Model
model = Model(
    inputs=elmo_input_layer, outputs=output_layer)
model.compile(
    loss='sparse_categorical_crossentropy', 
    optimizer='adam', metrics=['accuracy'])
model.summary()
model.fit(
    x_train_sentences, y_train,
#     validation_data=([x_test_words, x_test_sentences], y_test), 
    epochs=10, batch_size=32)

结果

Accuracy:76.83%
Average Precision: 0.78
Average Recall: 0.77
Average f1: 0.77

3。不含单词嵌入的固定均值池

# Input Layers
input_layer = Input(shape=(None,), dtype=tf.string)# Output Layers
output_layer = Lambda(
    elmo_embs.to_keras_layer, 
    output_shape=(1024,))(input_layer)
output_layer = Dense(
    256, activation='relu')(output_layer)
output_layer = Dense(4, activation='sigmoid')(output_layer)model = Model(inputs=[input_layer], outputs=output_layer)
model.compile(
    loss='sparse_categorical_crossentropy', 
    optimizer='adam', metrics=['accuracy'])
model.summary()
model.fit(
    x_train_sentences, y_train,
#     validation_data=([x_test_words, x_test_sentences], y_test), 
    epochs=10, batch_size=32)

结果

Accuracy:74.37%
Average Precision: 0.79
Average Recall: 0.74
Average f1: 0.75

拿走

要访问所有代码,您可以访问这个 github repo

  • CoVe 需要标签数据来获得上下文单词向量,而 ELMo 则采用无监督的方式。
  • CoVe 只使用最后一层,而 ELMo 使用多层来表示上下文单词。
  • 无法解决 OOV 问题。它建议使用零向量来表示未知单词。ELMO 可以处理 OOV 问题,因为它使用字符嵌入来构建单词嵌入。
  • ELMo 计算矢量很费时间。根据作者的建议,您可以离线预计算令牌,并在在线预测期间查找它,以减少时间开销。

关于我

我是湾区的数据科学家。专注于数据科学、人工智能,尤其是 NLP 和平台相关领域的最新发展。你可以通过媒体博客LinkedInGithub 联系我。

参考

彼得斯 M. E .、诺依曼 m .、乌耶 m .、加德纳 m .、克拉克 c ...深层语境化的词语表达。2018.arxiv.org/pdf/1802.05…

py torch 中的 ELMo(原创)

ELMo in Keras

ELMo in Tensorflow

ELMo in chainer

埃隆·马斯克和推特

原文:towardsdatascience.com/elon-musk-t…

Elon 与 Twitter“麝香”关系的频率和情感分析

Twitter 是一个强大的微博工具,从一开始就改变了人们的对话——不管是好是坏。有如此多的数据可用,因为它有数百万全球活跃用户来收集和利用。

特斯拉和 SpaceX 的首席执行官埃隆·马斯克(Elon Musk)因其最近的推文而成为争议的焦点。我想既然他是一个在世的名人,分析他在 Twitter 上的行为和声誉会很有趣。

我把我的项目分成几个部分:对马斯克的推文频率的分析,对马斯克推文的情感分析,对关于马斯克的推文的情感分析,以词云为产品。

我用 R 和 Twitter 的 API 做了我的项目。链接设置 API 这里

以下代码建立了 twitter 和 R Studios 之间的连接:

twitter_token<-create_token(app = "joysentiment1", api_key, api_secret, accessToken, accessTokenSecret, set_renv = TRUE)

之后我继续摘录了埃隆·马斯克的 5000 条推文。

em_tweets<-get_timeline("ElonMusk",n=5000)

第一部分:推文频率

我首先查看了埃隆·马斯克过去几年的推特习惯。他于 2009 年加入 Twitter,但只有他自 2016 年以来的推文可用。

Elon Musk’s 5000 Tweets Frequency

ggplot(data = em_tweets,
aes(x=em_tweets$month,group=factor(year(created_at)), color=factor(year(created_at)))) +
geom_line(stat="count") +
geom_point(stat="count") +
labs(x="Month", colour="Year",y="Number of tweets") +
theme_classic()

值得注意的是,埃隆·马斯克在 5 月和 6 月开始更频繁地发推特。他过去最令人难忘的一些推文可能包括宣布他为记者创建 Yelp 的想法。

Yelp for journalists…

我创建了另一个他在 12 个月内发推文频率的可视化,这也不奇怪,他在 5 月、6 月和 7 月在 Twitter 上最活跃。

Elon Musk’s Tweets Frequency over 12 months

ggplot(data = em_tweets, aes(x = em_tweets$month)) +
geom_bar(aes(fill = ..count..)) +
xlab("Month") + ylab("Number of tweets") +
theme_classic()

这引发了一个重要的问题:为什么马斯克比过去花更多的时间发推特?

第二部分:马斯克推文的情感分析

情感分析是针对特定情感/产品对词语进行量化和分类的过程。我在课堂上被介绍了这个概念,并且在阅读了这里的后变得更加感兴趣。

我对埃隆·马斯克的 5000 条推文进行了情绪分析,很想知道这种情绪在过去的一年里是如何变化的。我利用了“NRC”词典,它将单词归类为情绪,如“快乐”、“悲伤”等。

在我的第一次可视化中,我看到埃隆·马斯克的推文主要植根于积极、信任和期待的情绪。

Sentiment Analysis On Elon Musk’s Tweets

ggplot(data=primaryscores,aes(x=sentiment,y=Score))+
geom_bar(aes(fill=sentiment),stat = "identity")+
xlab("Sentiments")+ylab("Scores")+
ggtitle("Total sentiment based on scores")+
theme(legend.position="none")+
theme_minimal()

我还想看看他的情绪在 2018 年的过去几个月里有什么变化。

Sentiment Analysis on Elon Musk’s Tweets the past year

ggplot(data=monthly_sentiment,aes(x=month,y=value,group=sentiment))+
geom_line(aes(color=factor(sentiment)))+
geom_point(aes(color=factor(sentiment)))+
labs(x="Month", colour="Sentiment",y="Value")+
theme_minimal()

积极情绪在 4 月和 6 月间达到顶峰。但我们可以看到,愤怒、消极、期待和信任情绪也经历了类似的增长。鉴于他在 Twitter 上的多次公开争吵,这一发现是有道理的。

An example of a public dispute

埃隆经常以积极的态度在推特上谈论他的生活经历,特别是关于他的公司:特斯拉和 SpaceX。

An example of a positive tweet

我想涉及的另一个方面是他的词汇用法。最有效的方法是创建一个单词云,这是我在阅读了这个指南后意识到的。

这被证明是这项任务中最具挑战性的部分,因为我必须创建一个停用词列表,包括但不限于:just,like,way,also,其实。

停用词用于删除对分析没有价值的词。很难完全删除所有的停用词,因为这些词是他推文的主干。

Word cloud for Elon Musk’s tweets

wordcloud(em_text_corpus,min.freq=1,max.words=50,scale=c(2.5,1),colors=brewer.pal(8,"Accent"),random.color=T,random.order=F)

埃隆·马斯克(Elon Musk)使用他的 twitter 账户谈论他在无聊公司特斯拉(Tesla)和 SpaceX 的工作,这在这个词云中显而易见。他对自己公司的骄傲和对未来的乐观态度反映在他的推特上。

第三部分:关于埃隆马斯克 的推文情感分析

Twitter 的魅力在于能够加入其他人的对话。我利用这个功能来看看大多数用户是如何描绘埃隆·马斯克的。

为此,我做了另一项情感分析。我查看了我的 1000 条微博。

elon_raw<-searchTwitter("elon",lang="en",n=1000)

我进行了另一项情感分析,但这次是通过给每个词打分:正面词的分数大于 0,负面词的分数小于 0。关于伊隆的推文数量分布如下:

我通过实现我上面的技术创建了另一个单词云,来看看流行的单词是什么。

Word Cloud on tweets about Elon Musk

wordcloud(elon_text_corpus,min.freq=1,max.words=50,scale=c(2.5,1),colors=brewer.pal(8,"Accent"),random.color=T,random.order=F)

Twitter 用户似乎没有对埃隆·马斯克的积极情绪做出回应。大多数 Twitter 用户谈论他最近的追求、丑闻和个人生活,而不是他在公司的工作。俗话说,一枚硬币有两面。

Twitter 的有效性取决于用户本身。虽然有些人认为,如果不想伤害他的公司,埃隆·马斯克必须尽快改变他的推特习惯,但这种命运仍然不确定。很明显,尽管他发了积极的推文,但大多数人并不一定有同样的感觉。

这个项目很有趣,也很有挑战性。我会把扩展代码上传到我的 G itHub 上。如果你想了解更多关于它和我用于情感分析的代码,我在页面底部提供了一些参考。

最初,我在设置 API、创建停用词列表和实现代码时遇到了困难。我的发现有局限性,所以如果你愿意,请随时给我反馈。

总结一下,这是埃隆·马斯克最好的作品之一。

I guess he’s funny sometimes

重要包裹:

library(wordcloud)
library(httr)
library(rtweet)
library(twitteR)
library(plyr)
library(ggplot2)
library(devtools)
library(tm)
library(dplyr)
library(stringr)
library(tidytext)
library(lubridate)

参考:

为情感分析设置代码

https://www . slide share . net/ajayohri/Twitter-analysis-by-kaify-rais

示例项目

https://analyze core . com/2014/04/28/Twitter-情操-分析/

如何用机器学习算法设计垃圾邮件过滤系统

原文:towardsdatascience.com/email-spam-…

探索、绘制和可视化您的数据

作为软件开发人员,电子邮件是非常重要的沟通工具之一。为了进行有效的通信,垃圾邮件过滤是一个重要的功能。

那么垃圾邮件过滤系统实际上是如何工作的呢?我们能从零开始设计类似的东西吗?

概述

本文这两部分的主要目的是展示如何从头开始设计垃圾邮件过滤系统。

本文概述如下:

  1. 探索性数据分析
  2. 数据预处理
  3. 特征抽出
  4. 评分和指标
  5. 利用嵌入+神经网络进行改进(下)
  6. 最大似然算法与深度学习的比较(下)

我们开始吧!

探索性数据分析

探索性数据分析是数据科学中一个非常重要的过程。它帮助数据科学家理解手头的数据,并将其与业务上下文联系起来。

我将在可视化和分析我的数据中使用的开源工具是 Word Cloud。

Word Cloud 是一个用于表示文本数据的数据可视化工具。图像中文本的大小代表训练数据中单词的频率或重要性

在这一部分要采取的步骤:

  1. 获取电子邮件数据
  2. 探索和分析数据
  3. 使用文字云和条形图可视化培训数据

获取垃圾邮件数据

在我们开发任何有意义的算法之前,数据是必不可少的成分。知道从哪里获取数据可能是一个非常方便的工具,尤其是当你只是一个初学者的时候。

下面是几个著名的仓库,在那里你可以很容易地免费获得上千种数据集

  1. 加州大学欧文分校机器学习知识库
  2. Kaggle 数据集
  3. 自动气象站数据集

对于这个邮件垃圾数据集,是垃圾刺客分发的,可以点击这个链接去数据集。有几类数据,你可以阅读readme.html来获得更多关于这些数据的背景信息。

简而言之,这个存储库中存在两种类型的数据,即垃圾数据(非垃圾数据)和垃圾数据。此外,在垃圾邮件数据中,有简单和困难,这意味着有一些非垃圾邮件数据与垃圾邮件数据具有非常高的相似性。这可能会给我们的系统做出决定带来困难。

如果您使用的是 Linux 或 Mac,只需在终端中这样做, wget 只是一个命令,它可以帮助您下载给定 url 的文件:

wget [https://spamassassin.apache.org/old/publiccorpus/20030228_easy_ham.tar.bz2](https://spamassassin.apache.org/old/publiccorpus/20030228_easy_ham.tar.bz2)wget [https://spamassassin.apache.org/old/publiccorpus/20030228_easy_ham_2.tar.bz2](https://spamassassin.apache.org/old/publiccorpus/20030228_easy_ham_2.tar.bz2)wget [https://spamassassin.apache.org/old/publiccorpus/20030228_spam.tar.bz2](https://spamassassin.apache.org/old/publiccorpus/20030228_spam.tar.bz2)wget [https://spamassassin.apache.org/old/publiccorpus/20050311_spam_2.tar.bz2](https://spamassassin.apache.org/old/publiccorpus/20050311_spam_2.tar.bz2)wget [https://spamassassin.apache.org/old/publiccorpus/20030228_hard_ham.tar.bz2](https://spamassassin.apache.org/old/publiccorpus/20030228_hard_ham.tar.bz2)

让我们运行一些代码,看看所有这些电子邮件的内容!

探索和分析数据

让我们看一下邮件内容,对数据有一个基本的了解

火腿

这看起来像是给另一个人的普通邮件回复,这不难归类为一个火腿:

This is a bit of a messy solution but might be useful -

If you have an internal zip drive (not sure about external) and
you bios supports using a zip as floppy drive, you could 
use a bootable zip disk with all the relevant dos utils.

硬火腿(火腿电子邮件是棘手的)

硬火腿确实更难从垃圾数据中区分出来,因为它们包含一些关键词,如限时订单、特殊“返校”优惠,这使其非常可疑!

Hello Friends!

We hope you had a pleasant week. Last weeks trivia questions was:

What do these 3 films have in common: One Crazy Summer, Whispers in the =
Dark, Moby Dick?=20

Answer: Nantucket Island

Congratulations to our Winners:

Caitlin O. of New Bedford, Massachusetts

Brigid M. of Marblehead, Massachusetts Special "Back to School" Offer!

For a limited time order our "Back to School" Snack Basket and receive =
20% Off & FREE SHIPPING!

罐头猪肉

其中一个垃圾邮件训练数据看起来确实像垃圾邮件文件夹中的垃圾广告邮件:

IMPORTANT INFORMATION:

The new domain names are finally available to the general public at discount prices. Now you can register one of the exciting new .BIZ or .INFO domain names, as well as the original .COM and .NET names for just $14.95\. These brand new domain extensions were recently approved by ICANN and have the same rights as the original .COM and .NET domain names. The biggest benefit is of-course that the .BIZ and .INFO domain names are currently more available. i.e. it will be much easier to register an attractive and easy-to-remember domain name for the same price.  Visit: [http://www.affordable-domains.com](http://www.affordable-domains.com) today for more info. 

可视化

Wordcloud

Wordcloud 是一个非常有用的可视化工具,可以让你粗略估计出在你的数据中出现频率最高的单词。

Visualization for spam email

Visualization for non spam email

从这个图像中,您可以注意到垃圾邮件的一些有趣之处。他们中的许多人有大量的“垃圾”词,如:免费,金钱,产品等。在设计垃圾邮件检测系统时,有了这种意识可能有助于我们做出更好的决策。

需要注意的一点是,单词云只显示单词的频率,不一定显示单词的重要性。因此,在可视化数据之前,有必要进行一些数据清理,例如从数据中删除停用词、标点符号等。

N 元模型可视化

另一种可视化技术是利用条形图并显示出现频率最高的单词。N-gram 的意思是,当你计算单词的频率时,你把多少个单词作为一个单位来考虑。

在本文中,我展示了 1-gram 和 2-gram 的例子。你绝对可以尝试更大的 n-gram 模型。

Bar chart visualization of 1-gram model

Bar chart visualization of 2-gram model

列车试分裂

将您的数据集分为训练集测试集非常重要,这样您就可以在将模型部署到生产环境之前使用测试集来评估模型的性能。

在进行训练测试分割时,需要注意的一件重要事情是确保训练集和测试集之间的数据分布是相似的。

在这种情况下,这意味着垃圾邮件在训练集和测试集中的百分比应该相似。

Target Count For Train Data

Train Data Distribution

Target Count For Test Data

Test Data Distribution

训练数据和测试数据之间的分布非常相似,大约为 20–21%,所以我们可以开始处理我们的数据了!

数据预处理

文字清理

文本清理是机器学习中非常重要的一步,因为你的数据可能包含许多噪音和不需要的字符,如标点符号、空白、数字、超链接等。

人们通常使用的一些标准程序是:

  • 将所有字母转换为小写/大写
  • 移除数字
  • 删除标点符号
  • 删除空白
  • 删除超链接
  • 删除停用词,如 a、about、above、down、doing 等等
  • 词干
  • 单词词条化

对大多数人来说,这两种技术可能是陌生的,它们是单词词干单词词条化。这两种技术都试图将单词简化为最基本的形式,但采用的方法不同。

  • 词干提取—词干提取算法通过使用该语言中常见的前缀和后缀列表来删除单词的结尾或开头。英语单词词干的示例如下:

  • 单词词汇化——词汇化是利用特定语言的词典,并试图将单词转换回其基本形式。它会试着考虑动词的意思,然后 conv 把它还原成最合适的基本形式。

实现这两种算法可能很棘手,需要大量的思考和设计来处理不同的边缘情况。

幸运的是 NLTK 库已经提供了这两个算法的实现,所以我们可以从库中开箱即用!

导入库,开始设计一些函数,帮助我们理解这两个算法的基本工作原理。

# Just import them and use itfrom nltk.stem import PorterStemmer
from nltk.stem import WordNetLemmatizerstemmer = PorterStemmer()
lemmatizer = WordNetLemmatizer()dirty_text = "He studies in the house yesterday, unluckily, the fans breaks down"def word_stemmer(words):
    stem_words = [stemmer.stem(o) for o in words]
    return " ".join(stem_words)def word_lemmatizer(words):
   lemma_words = [lemmatizer.lemmatize(o) for o in words]
   return " ".join(lemma_words)

词干分析器的输出非常明显,一些词尾被砍掉了

clean_text = word_stemmer(dirty_text.split(" "))
clean_text#Output
'He studi in the hous yesterday, unluckily, the fan break down'

词汇化已转换为研究->研究,休息->休息

clean_text = word_lemmatizer(dirty_text.split(" "))
clean_text#Output
'I study in the house yesterday, unluckily, the fan break down'

特征抽出

我们的算法总是期望输入是整数/浮点数,所以我们需要在中间有一些特征提取层来将单词转换成整数/浮点数。

有几种方法可以做到这一点,今天我将向大家介绍:

  1. 计数矢量器
  2. tfidf 矢量器
  3. 单词嵌入

计数矢量器

首先,我们需要将所有训练数据输入到 CountVectorizer 中,CountVectorizer 将保存每个单词及其各自 id 的字典,该 id 将与整个训练集中该单词的字数相关。

比如像*‘我喜欢吃苹果,喝苹果汁’这样的句子*

from sklearn.feature_extraction.text import CountVectorizer# list of text documentstext = ["I like to eat apple and drink apple juice"]# create the transformvectorizer = CountVectorizer()# tokenize and build vocabvectorizer.fit(text)# summarizeprint(vectorizer.vocabulary_)# encode documentvector = vectorizer.transform(text)# summarize encoded vectorprint(vector.shape)print(type(vector))print(vector.toarray())# Output# The number follow by the word are the index of the word
{'like': 5, 'to': 6, 'eat': 3, 'apple': 1, 'and': 0, 'drink': 2, 'juice': 4}# The index relates to the position of the word count array below
# "I like to eat apple and drink apple juice" -> [1 2 1 1 1 1 1]# apple which has the index 1 correspond to the word count of 2 in the array

tfidf 矢量器

字数不错,但我们能做得更好吗?简单字数统计的一个问题是,像“the”、“and”这样的词会出现很多次,它们并没有真正增加太多有意义的信息。

另一个流行的选择是 TfidfVectorizer。除了计算每个单词(经常出现在多个文档或句子中的单词)的字数,矢量器还会尝试缩小它们的大小。

关于 CountVectorizer 和 TfidfVectorizer 的更多信息,请阅读这篇伟大的文章,这也是我获得大部分理解的地方。

字嵌入

网上有很多很棒的文章解释了单词嵌入的细节和生成它们的算法。所以在这里,我将跳过其中的大部分,试着给你一个大概的概念。

单词嵌入试图将单词转换成矢量化格式,该矢量表示该单词在高维空间中的位置。

对于具有相似含义的单词,这两个单词向量的余弦距离会更短,并且它们会彼此更接近。

事实上,这些单词是向量,所以你甚至可以对它们进行数学运算!这些操作的最终结果将是映射到单词的另一个向量。出乎意料的是,那些操作产生了一些惊人的结果!

例 1:国王-男人+女人=王后

示例 2:马德里-西班牙+法国=巴黎

例 3:步行-游泳+游泳=步行

简而言之,单词嵌入是单词的一种非常强大的表示,生成这种嵌入的一种众所周知的技术是 Word2Vec。

呼!将所有的句子转换成某种形式的向量后,就到了我们文章最精彩的部分→ 算法实现!

算法实现

tfidf 矢量器+朴素贝叶斯算法

我采用的第一种方法是使用 tfidf 矢量器作为特征提取工具,并使用朴素贝叶斯算法进行预测。朴素贝叶斯是一种简单的概率型传统机器学习算法。

即使在过去,它在解决垃圾邮件检测等问题时也非常流行。朴素贝叶斯的细节可以在这篇由 Devi Soni 撰写的文章中查阅,这篇文章简明清晰地解释了朴素贝叶斯算法的理论。

使用 sklearn 库提供的朴素贝叶斯库,让我们自己实现这个算法省去了很多麻烦。我们可以用几行代码轻松完成这项工作

from sklearn.naive_bayes import GaussianNBclf.fit(x_train_features.toarray(),y_train)# Output of the score is the accuracy of the prediction
# Accuracy: 0.995
clf.score(x_train_features.toarray(),y_train)# Accuracy: 0.932
clf.score(x_test_features.toarray(),y_test)

我们达到了 93.2%的准确率。但是准确性并不是评价算法性能的唯一指标。让我们尝试其他评分标准,这可能有助于我们彻底了解该模型的表现。

评分&指标

准确度的缺点

在评估数据科学模型的性能时,有时准确性可能不是最佳指标。

我们在现实生活中解决的一些问题可能有一个非常不平衡的类,使用准确性可能不会给我们足够的信心来理解算法的性能。

在我们试图解决的垃圾邮件问题中,垃圾邮件数据约占我们数据的 20%。如果我们的算法预测所有的电子邮件都是非垃圾邮件,它将达到 80%的准确率。

对于一些只有 1%正面数据的问题,预测所有样本都是负面的会给他们 99%的准确率,但我们都知道这种模型在现实生活中是没有用的。

精度&召回

查准率和查全率是人们评价类不平衡分类模型时常用的评价指标。

让我们试着理解 Precision & Recall 试图回答什么问题,

精度:实际上有多少比例的肯定识别是正确的?

回忆:实际阳性中有多少比例被正确识别?

所以, precision 是评估,当一个模型预测某件事是肯定的,这个模型有多精确。另一方面, recall 正在评估一个模型在寻找所有正样本方面做得如何。

精确率和召回率的数学等式分别是

TP:真阳性

FP:假阳性

TN:真阴性

FN:假阴性

混淆矩阵

混淆矩阵是理解像真阳性、假阳性、真阴性等结果的一个非常好的方法。

Sklearn 文档提供了一个示例代码,说明如何绘制好看的混淆矩阵来可视化您的结果。你可以在这里查看或者你可以在我在文章末尾分享的笔记本中找到代码。

Confusion Matrix of the result

Precision: 87.82%
Recall: 81.01%

该模型的召回率相当低,可能在发现垃圾邮件方面做得不够好。我们如何做得比这更好?

总结

在本文中,我向您展示了设计垃圾邮件检测算法所需的所有必要步骤。简单回顾一下:

  1. 探索和理解您的数据
  2. 将手头的数据可视化以获得更好的直觉——word cloud,N-gram 条形图
  3. 文本清理—单词斯特梅尔和单词词条化
  4. 特征提取—计数矢量器、Tfidf 矢量器、单词嵌入
  5. 算法—朴素贝叶斯
  6. 评分和指标——准确度、精确度、召回率

垃圾邮件检测算法设计演示的第一部分到此结束。

还有这篇文章的第 2 部分!我将展示如何通过使用单词嵌入和**深度学习模型来提高模型的准确度、精确度和召回率。**有兴趣的话在这里 阅读文章

你可以从 Github 克隆笔记本,或者直接从 Colab 运行。请在下面的评论区留下你的任何问题。

开始探索学习更多的数学知识

原文:towardsdatascience.com/embarking-o…

我是一名工作中的“数据科学家”,我把它放在引号中,因为这个术语的意思几乎是人们希望它表达的任何意思。我所知道的是,我处理大量数据,我建立模型,有时制作漂亮的图表(有时很难看)。哦,我经常使用 SQL。我还患有冒名顶替综合征,这可能是因为我对学习(和了解)数学上难以理解的新事物有着巨大的兴趣,我总是把它内化为一个存在主义问题:

为什么除了我每个人都在做如此前沿的 ML 研究?

不要误解我,我有很好的应用数学和统计学知识。很明显,因为如果没有创建回归模型和执行基本统计计算的能力,就很难成为“数据科学家”。但当我阅读一篇关于新的机器学习算法的论文时,我通常会直接跳到结果,并检查是否有“完成它的包”,因为我通常无法掌握方法部分给出的足够多的实质性细节,更不用说自己想出类似的东西了。我大概是低估了我的理解,但最终结果是一样的。我经常觉得自己错过了在谋生的道路上做得更好的机会。

我的问题的根源,正如我所诊断的,是我没有足够好的“纯粹”的数学背景。我看过《概率论》和《统计学》的书,但没有看过《概率论》和《统计学》,我现在理解这两本书差别很大。人们可以应用前者的方法,而不理解后者。但是要深入挖掘并能够设计出新的方法,在某种程度上需要理论知识。现在,我没有时间去获得第二个数学博士学位,但我的希望是,我可以通过勤奋的自学来填补我的数学教育中的一些漏洞。

在确定了核心问题后,我决定需要为自己建立一个课程来保持这个旅程的专注。为了做到这一点,我基本上是从我想去的地方往回走。翻阅“概率论”和“统计学理论”书籍时,我意识到的第一件事是,在某个时候,我会想要解决测量理论,这似乎是这些学科的核心组成部分:

数学分析中,集合上的度量是一种系统化的方法,用来给该集合的每个合适的子集分配一个数字,直观地解释为它的大小。从这个意义上说,度量是长度、面积和体积概念的概括。一个特别重要的例子是欧几里得空间上的勒贝格测度,它将欧几里得几何的常规长度面积体积分配给 n - 欧几里得空间 R n 的合适子集。例如,实数区间【0,1】的勒贝格测度就是它在这个词的日常意义上的长度——具体来说,就是 1。

所以,是的,很明显,在不知道什么是“数学分析”的情况下,我无法处理测量理论。相信我,我已经试着阅读测度论,但它就是不理解。所以我需要学习一些实分析,根据我的(元)研究,这似乎是大多数本科数学学位的一个非常基本的核心要求:

实分析(传统上,实变量函数的理论)是数学分析的一个分支,处理实变量的实数和实值函数。具体来说,是关于实函数序列解析性质,包括实数的收敛极限序列、实数的微积分、以及实值函数的连续性光滑性等相关性质。

显然,真正的分析就像我在类固醇上学的微积分。太棒了。对于数据科学家来说,还有其他一些潜在的有趣和有用的分析领域,尤其是向量空间和函数分析,这两个领域本质上是线性代数的理论基础。所以我决心从理论上从头开始学习线性代数(这在 ML 算法中是普遍存在的)。

作为一名“数据科学家”,我也写很多程序。再一次,因为我对事物非常好奇,我是一个喜欢学习编程语言和范例的普通人,只是为了好玩。好的一面是,我从这项练习中获得的知识往往会在我的日常工作中产生影响,并帮助我成为一名更好的程序员(至少,我喜欢告诉自己确实如此)。很长一段时间以来,我一直感兴趣的编程领域之一是函数式编程,并且在过去的一年左右的时间里尝试过(不是第一次!)拿起 Haskell ,一种近乎僧侣般的纯函数式编程语言。我提到 Haskell 的原因是,如果没有术语范畴理论的出现,你很难尝试学习这门语言:

范畴理论【1】数学结构及其概念形式化为对象箭头(也称为态射)的集合。一个类别有两个基本属性:能够组合箭头关联和每个对象存在一个标识箭头。范畴理论的语言已经被用于形式化其他高级抽象的概念,例如集合、

如果你认为这听起来很数学,那是因为它就是数学!我试着读了一些关于范畴理论的书,看了一些 YouTube 的讲座,但没有走得很远。这真的很抽象。但是最近我有了一个顿悟,那就是,正如我可能应该在进入度量理论之前处理实分析一样,为什么不在进入范畴理论之前学习抽象代数呢?

代数中,它是数学抽象代数(偶尔也叫近世代数)是对代数结构的研究。代数结构包括向量空间,以及代数。抽象代数这个术语是在 20 世纪早期创造的,目的是将这一研究领域与代数的其他部分区分开来。

代数结构及其相关的同态,形成数学范畴范畴理论是一种形式主义,允许以统一的方式来表达各种结构的相似属性和构造。

嘿,看,“群”,“环”,呀,呀。看来我的方向是对的。

所以我挑选了几本书开始我的旅程(大多基于亚马逊、Quora 和 StackExchange 上的好评),我的计划是不时地发布我的进展更新(甚至可能是我处理的一些具有挑战性的证明!),让我坚持下去。欢迎在评论中发表书籍建议。感谢阅读!

将机器学习模型嵌入 Web 应用程序(第 1 部分)

原文:towardsdatascience.com/embedding-m…

Source (Pixabay)

学习数据科学的最佳方式是实践,没有其他选择。在这篇文章中,我将反映我如何开发一个可以将电影评论分为正面或负面的机器学习模型,以及如何将该模型嵌入到 Python Flask web 应用程序中。最终目标是完成一个端到端的项目。我坚信,在这篇文章的结尾,你将具备将 ML 模型嵌入 web 应用程序的所有必要技能。我遇到了这种情况,打算写一本书,由 Sebastian Raschka 和 Vahid Mirjalili 编写的“Python 机器学习:用 Python、scikit-learn 和 TensorFlow 进行机器学习和深度学习,第二版”。我发现这本书对我的数据科学之旅是一个很好的投资,我鼓励你试用这本书。

请注意,我不打算详细讨论理论和概念。为了让这篇文章简单易懂,我将简单地提供解释,并分享链接,这样你就可以在时间允许的情况下阅读更多的概念和理论。我的建议是,从头到尾跟着这篇文章,在你阅读的第二阶段重新审视新概念。

现在系好安全带,这将是一次奇妙的:D 之旅

这篇文章有两个主要部分

  1. 开发电影评论分类器(这篇文章)
  2. 开发 Python Flask web 应用程序并集成电影评论分类器(即将发布!)

开发电影评论分类器

Source(Pixabay)

我在 Paperspace 建立了我的开发者环境,这是一个云基础设施提供商(可能有其他用途,但我只用作 PaaS ,它提供基于 GPU 的计算能力来开发机器学习和深度学习模型。我在我选择的位置创建了一个单独的项目文件夹“情感分析”。这是项目的根目录。

下载电影评论数据

首先,让我们开始下载所需的电影数据。我创建了一个单独的文件‘download _ data . ipynb’。这会将电影评论下载并提取到“数据”文件夹中。当您在“数据”文件夹中导航时,您将能够看到一个名为“acllmdb”的文件夹。在“acllmdb”文件夹中,有“train”和“test”文件夹。“train”和“test”文件夹都包含两个子文件夹,分别名为“pos”和“neg”,前者包含正面评价,后者包含负面评价(图[1])。

download_data.ipynb

Image[1]: Inside data folder

你会注意到这些在‘pos’和‘neg’文件夹中的评论是文本文件的形式。为了方便我们进行数据处理和操作,我们的下一步是创建一个 Python Pandas 数据框。

从文本文件创建熊猫数据框

pandas_data_frame_from_text.ipynb

上面的脚本创建了一个 Pandas 数据帧“df ”,其中包含来自“train”和“test”文件夹中“pos”和“neg”子目录的文本文件的电影评论(这一步大约需要 10-20 分钟,取决于您的 PC 的性能)。如果电影评论是正面的,我们将情感标记为“1”,如果是负面的,我们将情感标记为“0”。在我们的数据框架“df”中,我们有两列,“review”列,它包含文本字符串形式的评论,以及“perspective”列,它包含评论的情绪,根据情绪的积极和消极程度,该情绪为“1”或“0”。图像[2]包含数据帧“df”的前五行。

Image[2] : Movie reviews in Pandas data-frame

在图[2]中,我们只能看到正面的影评。原因是,当我们创建数据框架时,该函数以一种排序的方式安排评论。为了更好地进行有用的数据操作,我们需要随机化电影评论的顺序(即,我们应该以不均匀的无序方式看到‘0’和‘1’)。为此,我们可以利用 NumPy 库的内置函数“置换”和“随机”。

随机化数据帧并保存为 CSV 文件

randomize_data_and_create_csv.ipynb

Image[3]: Unsorted movie reviews

正如您在图[3]中看到的,现在我们有了一个随机数据框,并将数据保存到一个名为“ movie_data.csv ”的 csv 文件中。

清理文本数据

我们的数据框中的“审查”有文本。非常仔细地看这些文本是极其重要的。让我们继续,从上一步准备的数据框中可视化最后 999 个字符。

movie_reviews_last_999_chars.ipynb

Image[4]: Reviews consists of HTML mark-up

很明显,“评论”栏包含 HTML 标记。这些标记并没有给评论增加任何有用的洞察力。因此,作为文本清理过程的一部分,我们必须确保在使用这些评论来开发模型之前,删除这些不需要的标记。

虽然 HTML 标记不包含太多有用的语义,但标点符号可以表示 NLP 上下文中有用的附加信息。为了简单起见,我们将删除除表情符号之外的标点符号,例如:),因为这些表情符号对于语义分析肯定是有用的。我们将使用 Python 的正则表达式 ( regex )来执行这项任务。

这些评论都是大段文字。为了让我们分析评论,我们需要将这些评论分成单独的元素。这个过程在 NLP 上下文中被称为“”[2]。有多种技术可以对给定的文本字符串进行标记。最简单的方法就是在 Python 中的内置函数中使用 split() 。下面是使用 split()函数将一组字符串标记为单个元素的简单示例,如图[5]所示。

tokenize_text_to_individual_element.ipynb

Image[5]: Tokenize words from text

在图[5]中,你可以看到我们已经成功地将文本标记为它的单个元素。在结果输出中,我们可以看到单词“running”和“run”。在 NLP 中,有一种技术可以将单词转换成它们的词根形式。这种技巧叫做 词干【3】。波特·斯特梅尔在自然语言处理领域的研究者中很受欢迎。在下面的代码段中,你可以看到我们如何使用 NLTK 包的 PorterStemmer 来获得单词的根形式(图[6])。

porter_stemmer.ipynb

Image[6]: Tokenize words in their root form

在这个项目中,我们不打算看单词的词根形式。原因是,已经证明它不会给我们将要建立的模型带来显著的改进。为了这篇文章的完整性,我与你分享了这些信息。

数据清理和预处理步骤中的另一个重要概念是被称为“停止字移除”的概念。“停用词”是在各种形式的文本中经常出现的词,可能没有任何有用的信息。几个“停用词”是,……停用词去除使得我们的文本处理机制高效,因为它减少了我们需要分析的词的数量。Python NLTK 提供了一种有效的机制来从给定的文本语料库中移除“停用词”。你可以参考下面的代码片段和图片[7]来了解停用词移除的机制。

stop_words_removal.ipynb

Image[7]: Stop words removal results

注意 : 在上面的代码片段中,我们使用了在前面的代码片段中定义的‘tokenizer _ porter’函数。

如图[7]所示,打包的“停用词”去掉了最常出现的词,如“ a ”、“”。这将减少我们的“单词袋”的大小(这将在本文后面说明),从而使计算更有效。

至此,您已经了解了清理文本数据的许多重要步骤。

  • 移除不需要的 HTML 标记(通过正则表达式)
  • 标记化(通过 Python split() 方法)
  • 词干(如波特斯特梅尔)
  • 停止单词删除(通过 NLTK 停止单词)

制作电影评论分类器

有了这些背景知识,我们现在可以继续开发情感分类器。我们将把上述步骤(除了词干处理)应用到我们创建的 movie_data.csv 文件中。

有两种方法来开发分类器。一种是一次利用整个数据集,或者换句话说,一次读取整个 movie_data.csv 文件,创建训练和测试集并拟合模型。这种方法的缺点是,我们需要高性能的 PC/计算能力。尽管我在试用本教程时使用了 Paperspace ,但是用这种方法构建分类器花了我将近两个小时。这是一种非常麻烦的体验。因此,在这篇文章中,我将继续第二种方法。

当处理大量数据时,机器学习从业者使用在线学习算法。同样,在我们的例子中,我们也将使用一种在线学习算法,称为" 【核外学习】【5】。简单来说,这就是我们在给定时间使用数据集的一部分,并从这部分数据中创建模型。我们将用我们输入的每个新数据部分来更新模型。通过遵循这种方法,我们可以很容易地在合理的时间框架内构建我们的模型。此外,我们将定义一系列函数来执行以下操作:

  • stream_docs — read_csv(一次一个文档)
  • get_minibatch —通过附加文档创建较小尺寸的文档

最后利用以上两个函数创建分类器。你可以参考图[8]和下面提供的代码片段来获得更多关于分类器构建过程的理解。

Image[8]: Classifier creation steps using out-of-core-learning approach

movie_review_classifier.ipynb

这就是创建电影分类器所需的全部内容。也许这现在看起来有点复杂,所以让我带您看一下代码。必要时你可以参考图[8]。

根据图[8],我们的第一步是读取我们在最开始创建的 csv 文件。在上面的代码片段中,第 16 行读取 csv 文件。它一次读取一行(文档),然后将该文档传递给(第 53 行) get_minibatch() 函数以创建一个迷你文档。我们创建一个迷你文档,直到迷你文档的大小达到 1000(第 53 行)。一旦在 get_minibatch() 函数中创建了这个迷你批处理,它就返回这个迷你批处理以供进一步处理(从第 36 行到第 53 行)。我们使用这个小批处理并创建训练集变量 X_trainy_train

然后,这个 X_train 变量被传递下去,以创建单词包**(第 56 行)。因为我们使用的是核外学习方法,所以我们使用了 scikit-learn哈希矢量器。哈希矢量器负责创建单词包。在创建单词包时,它将对包含电影评论的***【X _ train】、*** 进行预处理,并在移除停用词(或对我们的文本语料库没有任何价值的频繁出现的词,如“ a ”、“likeis”等)的同时移除不必要的 HTML 标记。)(第 49 行和第 38–44 行)。**

我们用标记器函数初始化哈希矢量器**,并将特征数量设置为 221** 。此外,我们通过将SGD 分类器损失 参数设置为 日志 来重新初始化逻辑回归分类器。在 HashingVectorizer 中选择大量功能的原因是,在增加逻辑回归模型中系数数量的同时,减少导致哈希冲突的机会。**

使用 for 循环(第 52 行),我们迭代了 45 个小批量文档,其中每个小批量包含 1000 个文档。完成增量学习过程后,我们将使用 5000 个文档来评估我们模型的性能。下面我给出了关于测试集生成和准确性计算的代码片段。这几乎是不言自明的:)(你可以参考上面的详细解释来加深你的理解)。

test_set.ipynb

Image[9]

我们可以看到,我们的模型已经产生了 86.7%的准确率,这是相当不错的。到目前为止,我们已经完成了最重要的一步,下一步是保存这个模型供以后参考。否则,我们需要再次执行所有这些步骤来达到这一点。请保持您当前的 Python 会话打开

PS:我们的 csv 文件包含 50K 记录,我们使用 45K 作为训练集,5K 作为测试集。你可以使用熊猫的“信息”功能来查看我们 csv 中的记录数量。

每当我们关闭 Python 会话时,对我们来说训练我们的模型将是一项相当忙碌的任务。因此,我们将保存我们训练和构建的分类器。为此,我们使用 Python 内置的 pickle 模块,它允许我们序列化和反序列化 Python 对象以压缩字节代码。当我们想要对新样本进行分类时,我们可以直接重新加载这些对象。

serialize_deserialize_objects.py

在上面的代码段中,我们创建了一个名为' movieclassifier 和' pkl_objects 子目录的文件夹来保存序列化的 Python 对象。' dump 方法所做的是,它序列化经过训练的逻辑回归模型以及 NLTK 库中的'停用词集。我鼓励你阅读 Python pickle 文档【6】来了解更多关于这个包的信息(如果我要在这里解释,那将是:D 的另一篇博文)

我们的下一步是创建一个新的 Python 脚本,我们可以使用它将矢量器导入到现有的 Python 会话中。让我们继续在上一步创建的 movieclassifier 目录中创建一个新的 Python 脚本 vectorizer.py

vectorizer.py

现在,在这一点上,我们应该能够使用我们创建的 Python 序列化对象,即使是在一个新的 Python 会话中(培训的麻烦将不再存在!耶!!!).让我们继续测试。导航到“电影分类器”文件夹。停止您当前的 Python 会话。让我们启动一个新的 Python 会话,看看能否从硬盘加载我们的模型。手指交叉!!!

unpiclked_classifier.py

上面的代码段负责加载我们创建的矢量器和分解分类器。现在我们可以使用这些对象和预处理文档样本,并对它们的情感做出预测。例如,让我们试着检查“我爱这部电影”是属于积极的还是消极的。

Image[10]

厉害!看来我们的模型工作正常。我们有能力将这种机器学习模型与我们将要开发的 web 应用程序集成在一起。这是这个两部分系列的第一部分的结尾。

开发 Python Flask web 应用程序

这将是这篇文章的第二部分。我鼓励您熟悉 Python Flask web 应用程序开发。大量的 Python Flask 足够让你阅读这篇文章的第二部分。如果你是新手,可以查一下 Traversy MediaFlask Web App 开发系列。

非常感谢你有兴趣阅读这篇文章。请给这篇文章一点掌声,留下你的评论和反馈,我总是欣赏和欢迎你的观点。如果你觉得这篇文章有用,那就和你的朋友:D 分享吧

礼貌:我想对塞巴斯蒂安·拉什卡和瓦伊德·米尔贾利利表示极大的感谢。我从他们身上学到了很多,并且还在学习。我从来不认为书籍是学习编程的好资源,因为我非常依赖在线视频教程。现在我觉得,书籍也是学习编程的一种很好的方式,而出版一本书需要付出巨大的努力。你可以做重点,边学边做笔记。这是一个很大的加分点,所以花你喜欢的书的钱真的是一个很大的时间投资。

参考资料:

[1]https://www . Amazon . com/Python-Machine-Learning-scikit-learn-tensor flow/DP/1787125939 【2】https://NLP . Stanford . edu/IR-book/html/html edition/tokenization-1 . html 【3】https://NLP . Stanford . edu/IR-book/html/html edition/stemming