TowardsDataScience-博客中文翻译-2020-二十二-

龙哥盟 / 2024-10-14 / 原文

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

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

金融服务中的大数据

原文:https://towardsdatascience.com/big-data-in-financial-services-f3d4fd7a30cd?source=collection_archive---------19-----------------------

数据科学、大数据、金融

现在的情况与 10 年前有所不同,因为我们现在拥有的数据比以前更多。

约书亚·索蒂诺在 Unsplash 上拍摄的照片

我们已经分析了千万亿次级的大数据,zettabytes 将是下一个(Kaisler 等人,2013)。

但是什么是大数据呢?简而言之,就是前所未有的保留、处理和理解数据的能力(Zikopoulos,2015)。大数据是指您面临传统数据库系统无法应对的挑战。

在数量、多样性、速度和准确性方面的挑战。这些都可以在金融服务中找到。事实上,技术是银行业不可或缺的一部分,以至于金融机构现在几乎与 IT 公司无法区分。

本文着眼于金融服务行业,研究大数据和所采用的技术。它进一步涵盖了投资回报、大数据分析、监管、治理、安全性和存储,以及造就该行业今天的障碍和挑战。

金融服务中的大数据

许多金融服务机构已经通过投资计算和存储大数据的平台开始了他们的大数据之旅。为什么?因为这里面有价值,而寻找新的价值形式是金融服务业务的全部内容。

大数据客户分析通过观察消费模式、信用信息、财务状况以及分析社交媒体来更好地了解客户行为和模式,从而推动收入机会。

大数据也是金融服务数据提供的核心业务模式的关键,例如彭博、路透社、数据流和金融交易所,它们提供金融交易价格并记录每秒数百万笔日常交易,以供客户分析使用和满足监管合规性要求(SOX、GDPR)。

所有这些大数据都必须存储起来(参见 NASDAQ 案例研究),因为无论计算机的速度有多快,无论组织的规模有多大,总有比组织知道如何处理或如何组合的数据更多的数据源,并且数据已经静止和流动了很长时间。

以下是大数据对金融行业的规模和社会影响的图示。

(来源:https://www . businessprocessincubator . com/content/technology-empowers-financial-services/)

(来源:https://www . slide share . net/swift community/nybf 2015 big-dataworksession final 2 mar 2015)

经过深入的小组研究,大数据已被发现存在于价值链的每个部分,下面给出了一些确定了收益实现(ROI)的示例:

VISA 于 2011 年通过使用 IMC 的“内存计算”平台和网格计算来分析信用卡欺诈检测监控的大数据,从而获得了竞争优势。以前只有 2%的交易数据受到监控,现在有 16 种不同的欺诈模式,分布在不同的地区和市场(Celent,2013)。

Garanti Bank,土耳其第二大盈利银行,通过使用复杂实时数据(如 web、呼叫中心和社交媒体数据)的 IMC 进行大数据分析,降低了运营成本并提高了绩效(Karwacki,2015)。

BBVA,西班牙第二大银行集团使用大数据交互工具 Urban Discovery 检测潜在的声誉风险,提高员工和客户满意度。他们还了解了客户在分析大数据时的感受,从而制定公共关系和媒体策略(Evry,2014)。

花旗集团(美国第四大银行)将大数据技术 Hadoop 用于客户服务、欺诈检测和网络分析(Marr,2016)。根据(花旗报告,2017)金融机构使用大数据进行利率和 GDP 预测。

Zestfinance 使用大数据 ZAML 技术密切监控其交易对手的信用质量,并试图评估其整体信用风险敞口(Lippert,2014)。

BNY 梅隆通过潘兴 NetX360 平台实施了大数据技术,为其投资者审视风险和机遇(BNY 梅隆报告,2016)。

美国银行利用大数据增强多渠道客户关系,并在从网站、呼叫中心、柜员开始的客户旅程中使用,以提高其服务水平和客户留存率(Davenport,2013)。

纳斯达克使用AWS S3 大数据存储技术,每天向 AWS 提供数十万个小文件,然后在几毫秒内返回给客户,用于其市场回放和数据点播服务,以满足客户快速访问历史股价信息的需求,查看任何历史时间点的账面报价和交易价格。交易员和经纪人也用它来寻找错过的机会或潜在的不可预见的事件。低成本的理想解决方案(AWS 案例研究)。

(来源:https://www . data Maran . com/blog/the-big-data-revolution-doing-more-for-less/)

以下案例研究更详细地探讨了金融服务中的大数据技术。

照片由 CHUTTERSNAP 在 Unsplash 上拍摄

案例研究 1-摩根大通和 Hadoop

JP Morgan Chase 银行面临着理解信用卡交易(消费模式)产生的大数据以及非结构化和结构化数据集数量大幅度增长的挑战。

他们选择 Hadoop(开源框架)来利用大数据分析来分析客户的支出和收入模式。Hadoop 现在可以帮助挖掘非结构化数据(如电子邮件、脸书或 Twitter 标签),这是传统数据库无法做到的。

借助大数据分析,it 可以确定最适合其客户的最佳产品,即在客户需要时为其提供合适的产品。因此,该银行选择了 Hadoop 来支持不断增长的数据量以及快速处理复杂非结构化数据的需求。

类似地,(Pramanick,2013 年)声称,金融机构使用大数据来分析他们的呼叫中心,通过分析非结构化语音记录进行情感分析,这有助于他们降低客户流失率,并向客户交叉销售新产品。

案例研究 2-德意志银行、算法匹配和 Hadoop

德意志银行选择使用多种大数据平台和技术,例如构建风险平台,在此平台上挖掘非结构化数据并将其处理为可理解和可展示的格式,以便德意志银行的数据科学专家获得分析活动的洞察力和灵感。大数据技术应用于公司的交易和风险数据(收集时间超过 10 年)。

数据量和多样性需要大量的存储、排序和筛选,但借助大数据技术,可以快速高效地获取和提取数据,以提高性能,并通过使用匹配算法获得竞争优势,该算法挖掘数据集告诉他们的关于销售、满意率和投资回报的信息,从而从数字中获得更真实的意义和更深入的视角。

(Sagiroglu 等人,2013 年)还列举了金融公司使用自动化个性化推荐算法来提高客户亲密度的例子。因此,识别客户需求并提供量身定制的信息对金融机构来说是有利的。

大数据有助于识别合法交易与欺诈交易(洗钱、盗窃信用卡),并通过设置以下参数预测贷款违约支付行为、借款人与银行接触点的互动历史、征信机构信息、社交媒体活动和其他外部公共信息。(《经济情报》,2014 年)

该银行在 2013 年使用 Hadoop 来管理非结构化数据,但对与传统数据系统的集成持怀疑态度,因为存在多个数据源和数据流、价值数百万英镑的大型传统 IBM 大型机和存储库,并且需求与其传统系统和较新数据技术的功能相匹配,并对其进行简化。

最终,Hadoop、NoSQL 和大数据预测分析的组合适应了其所有运营领域,技术现在被视为德意志银行决策和战略管理行为中的重要因素。

案例研究 3-纳斯达克、存储(AWS 红移)和可扩展性(虚拟化)

所有金融交易交易所都存在大数据问题,纳斯达克也不例外。价值 7.9 万亿美元,每秒数百万次交易,一天内交易 29 亿股的世界纪录(2000 年),与容量相关的延迟是一个大问题,例如,处理 650 万个报价会因处理大量数据而导致处理延迟(Greene,2017)。

2014 年,这个问题变得更加复杂,因为公司的业务战略是从一个主要的美国股票交易所转变为一个企业、交易、技术和信息解决方案的全球提供商。这意味着他们需要进行更多的数据处理,并存储法律要求他们持有的大量数据内容。

金融服务行业的公司通常需要将交易信息保留七年,这是一项法规要求,可能会产生巨额存储费用。在纳斯达克,他们有一个传统的仓库(每年维护 116 万美元)和有限的容量(即只有一年的在线数据)。

他们的大数据量包括每个交易日插入的 40-80 亿行数据。数据构成是订单、交易、报价、市场数据、安全主数据和会员数据(即结构化数据)。数据仓库用于分析市场份额、客户活动、监控和计费。

还有一个性能挑战。当客户进行查询时,纳斯达克负担不起加载昨天的数据。灾难恢复是纳斯达克的另一个重要因素。

最初的要求范围是通过迁移到 AWS Redshift 来替换本地仓库,同时保持等同的模式和数据,并且大数据解决方案必须满足两个最重要的考虑因素,即安全性和法规要求。方法是从众多来源提取数据,验证数据,即数据清理,并安全地加载到 AWS Redshift 中。

更详细地说,数据验证需要每天对坏数据/丢失数据发出警报,接收必须强制执行数据约束,即不重复,并且对于敏感的交易和公司数据来说,速度和安全性是最重要的。这最初导致了一个问题,因为 AWS 红移不强制数据约束。如果有欺骗,它接受它。

符合监管要求的安全解决方案

数据是他们业务的基础,处理敏感数据意味着纳斯达克的安全要求很高,因为他们是一家受监管的公司,必须对 SEC(美国证券交易委员会)负责。

因此,他们需要安全的系统,因为大数据的一大挑战是,它将使个人财务信息更加分散,因此更容易被窃取。AWS Redshift 通过提供多层安全来满足安全要求:

  1. 直接连接(专线,即没有公司数据通过互联网线路传输)。
  2. VPC-将 Nasdaq Redshift 服务器与其他设备隔离/互联网连接+安全组限制入站/出站连接。
  3. 动态加密(HTTPS/SSL/TLS)。所有 AWS API 调用都是通过 HTTPS 进行的。SSL(安全套接字层)意味着有一个验证集群身份的集群证书认证系统。
  4. 红移中的静态加密(AES-256)。这意味着红移加载文件是在客户端加密的。
  5. CloudTrail/STL_connection_Log 来监控未授权的数据库连接。这意味着监控集群访问并对任何未经授权的连接做出反应。

此迁移项目的优势实现如期完成,并带来了以下优势:

●红移成本是传统数据仓库预算的 43%(对于大约 1100 个表的相同数据集)

●2014 年平均每天 55 亿行

●高水位线=一天 14 行

●下午 4 点到 11 点摄入

●最佳写入速率约为 2.76 兆行/秒

●现在查询运行速度比传统系统更快。

●数据存储负载增加到 1200 多张表。

●通过安全审核。内部控制;信息安全,内部审计,纳斯达克风险委员会。外部审计;SOX,SEC。

Redshift 通过在多个数据中心复制数据解决了灾难恢复问题。

纳斯达克(2014 年)的当前数据存储需求= 450 GB/天(压缩后)加载到 Redshift 中。之前的压缩平均值,即未压缩= 1,895 GB/天。集群每季度调整一次大小以满足需求。NDW(纳斯达克数据仓库)目前每季度增长 3 倍!

纳斯达克的另一个问题是在不影响性能和成本的情况下的可扩展性。NASDAQ 发现 Apache Hadoop 和大数据分析所需的基础架构可能难以管理和扩展。所有这些过去的不同技术不能很好地协同工作,管理所有这些技术的成本也很高。

因此,It 使用云虚拟化来消除硬件限制,降低软件基础架构软件复杂性、成本和部署 Hadoop 和 Spark 的时间。虚拟化简化了所需的技术和资源数量,最大限度地提高了处理器利用率(18–20%到 80–90%),保持了安全性,并且通过虚拟化将性能提高了 2%。

从工程和运营的角度来看,纳斯达克能够满足客户的大数据分析需求,而无需增加员工数量。因此,蓝色数据帮助纳斯达克推动了创新(Greene,2017)。

挑战

Jukan Tateisi 在 Unsplash 上拍摄的照片

GDPR(2018 年 5 月 25 日生效):(Zerlang,2017 年)确认数据处理的透明度是 GDPR 的核心。跨境金融服务必须将所有对话记录至少 5 年,否则可能会被罚款,例如巴克莱因错误报告 5750 万笔交易而被罚款 245 万英镑。同样,(Gilford,2016)指出,GDPR 可能会因数据安全违规对乐购银行罚款 19 亿英镑。

金融机构必须审查当前的合规流程。客户同意的数据只能用于同意的目的,这意味着任何历史大数据分析示例客户信用卡消费数据都必须销毁。价值数十亿美元的信息将会丢失。因此,金融机构应该重新审视收集数据的过程。

未来的预测建模技术必须是非歧视性的。金融机构必须根据新的 GDPR 准则重新设计它们的算法和自动化流程。

(Lahiri,2017 年)声明 GDPR 将更新欧洲数据保护规则,违反规则将付出高昂代价;2000 万欧元或 4%的营业额。(LeRoux,2017)声称 GDPR 的新法规将成为大数据的杀手。(Woodie,2017 年)证实,GDPR 的新修正案将为欧盟 7.43 亿消费者制定强制性数据处理流程、使用透明度和消费者友好型隐私规则。

数据隐私共享机密信息会导致法律和商业风险(Deutsche,2014)。此外,交叉链接异构数据以重新识别个人身份是一个隐私问题(Fhom,2015)。因此,不当使用此类敏感数据可能会引起法律纠纷。

熟练的劳动力解读大量的大数据也是一个巨大的挑战,因为错误预测的结果可能代价高昂。因此,训练有素的大数据技术员工至关重要,因为(Fhom,2015)预测将会出现大数据专业人员短缺。

因此,公司应该在实施大数据项目之前计划培训或雇佣新员工。(McAfee 等人,2012 年)还提倡将强大的领导力、良好的公司文化、适应新技术的意愿作为大数据成功的关键因素。

构建大数据基础设施的成本短期来看非常昂贵,但长期来看将为金融公司带来竞争优势。根据(Davenport,2013),花费在大数据上的时间和金钱的合理性 (ROI) 并不透明。因此,该公司的高层管理人员将长期战略押在了大数据上。

结论

由凯利·西克玛在 Unsplash 上拍摄的照片

总之,所研究的不同案例显示了正在使用的各种大数据技术和优势,如 Nasdaq & AWS RedShift 案例中的存储减少,以及由此带来的从 6PB 到 500GB 的存储减少。

从这些案例研究中,我们发现接受调查的所有公司都非常重视积极利用大数据来实现自己的使命和目标,并有着共同的目标。它们之间有一些共性,例如更有针对性的营销,也有一些差异,例如存储所采用的不同类型的技术。

通过分析大数据,行业参与者可以提高组织效率,改善客户体验,增加收入,提高利润,更好地预测风险,并可以洞察进入新市场的情况。(尹等,2015)行情大数据提升运营效率 18%。

同样,(McAfee 等人,2012 年)指出,与市场上的竞争对手相比,数据驱动型公司的生产率平均高出 5%至 6%。银行将快速获得更好的数据洞察力,以便做出有效的决策。

参考

● AWS 案例研究。可从https://aws.amazon.com/solutions/case-studies/nasdaq-omx/获得

●大数据革命。可从https://www . data Maran . com/the-big-data-revolution-doing-more-for-less/获取

● BNY 梅隆大学(2016),BNY 梅隆大学的潘兴引入了额外的功能,使客户能够将大数据转化为大见解。可从https://www . Pershing . com/news/press-releases/2016/bny-mellons-Pershing-introduces-additional-capabilities-enabled-clients-to-transform-big-data 获取。

● Celent (2013 年)。风险管理中的大数据:提供新见解的工具。可从 https://www.celent.com/insights/903043275.获得

●花旗(2017)。寻找阿尔法:大数据。导航新的备选数据集。可从 https://eaglealpha.com/citi-report/.获得

达文波特(2013 年)。大公司的大数据。可从http://resources . idgenterprise . com/original/AST-0109216 _ Big _ Data _ in _ Big _ companies . pdf 获取

●德意志银行(2014 年)。大数据:它如何成为差异化优势。可从http://CIB . db . com/docs _ new/GTB _ 大数据 _ 白皮书 _(DB0324)_v2.pdf 获得

●经济学人信息部(2014 年)。零售银行和大数据:大数据是更好的风险管理的关键。可从https://www . eiuperspectives . economist . com/sites/default/files/retailbanksandbigdata . pdf 获得

●埃夫里(2014 年)。面向营销人员的银行业大数据。可从 https://www . evry . com/global assets/insight/bank 2020/bank-2020-big-data-whitepaper.pdf 获得。

Fhom,H.S. (2015)。大数据:机遇和隐私挑战。可从 http://arxiv.org/abs/1502.00823.获得

福斯特,赵,杨,莱库,陆,2008 年 11 月。云计算和网格计算 360 度对比。2008 年网格计算环境研讨会。GCE’08(第 1-10 页)。IEEE。吉尔福德·g .(2016 年)。GDPR 银行违规罚款 19 亿英镑。可从https://www . HR solutions-uk . com/1-9bn-fines-gdpr-bank-breach/获取

●格林,M. (2017)。纳斯达克:用蓝色数据克服大数据挑战。可从 https://itpeer network . Intel . com/Nasdaq-comprising-big-data-challenges-bluedata/获得。

●凯斯勒,s .,阿默,f .,埃斯皮诺萨,J.A .和钱,w .,2013 年 1 月。大数据:前进中的问题和挑战。在系统科学(HICSS),2013 年第 46 届夏威夷国际会议(第 995-1004 页)。IEEE。

●卡尔瓦基(2015 年)。土耳其五大银行。可从http://www . The Banker . com/Banker-Data/Bank-Trends/The-top-five-banks-in-Turkey 获得?ct =真

●诺克斯(2015)。金融服务中的大数据。可从https://www . slide share . net/swift community/nybf 2015 big-dataworksession final 2 mar 2015获取

● Lahiri,K. (2017) GDPR 和英国退出欧盟:离开欧盟如何影响英国的数据隐私。可从https://www . cbronline . com/verticals/CIO-agenda/gdpr-英国退出欧盟-离开-欧盟-影响-英国-数据-隐私/ 获取

●纽约勒鲁(2017 年)。GDPR:即将出台的法规会扼杀大数据吗?可从https://www . finance digest . com/gdpr-is-the-about-regulation-killing-off-big-data . html获得

Lippert,J. (2014 年)。Zest Finance 发放小额高利率贷款,利用大数据剔除赖账者。可从https://www . Washington post . com/business/zest finance-issues-small-high-rate-loans-uses-big-data-to-weed-out-dead beats/2014/10/10/e 34986 b 6-4d 71-11e 4-aa5e-7153 e 466 a02d _ story . html?utm_term=.6767c7abfefb.

刘,杨,张,2013 年 9 月。大数据技术概述。工程和科学互联网计算(ICICSE),2013 年第七届国际会议(第 26-29 页)。IEEE。

马尔,B. (2016 年)。花旗集团利用大数据改善银行绩效的惊人方式。可从https://www . LinkedIn . com/pulse/amazing-ways-Citigroup-using-big-data-improve-bank-performance-marr/获得。

● McAfee,a .,Brynjolfsson,e .和 Davenport,T.H .,2012。管理革命。哈佛商业评论,90(10),第 60-68 页。

普拉曼尼克,S. (2013 年)。大数据用例-银行和金融服务。可从https://thebigdata institute . WordPress . com/2013/05/01/big-data-use-cases-banking-and-financial-services/获取

Preez 博士(2013 年)。德意志银行:遗留系统阻碍了大数据计划。可从https://www . computer world uk . com/data/Deutsche-bank-big-data-plans-hold-back-by-legacy-systems-3425725/获得

s .萨吉罗格卢和 d .西纳克,2013 年 5 月。大数据:综述。协作技术与系统(CTS),2013 年国际会议(第 42-47 页)。IEEE。

● Statista (2016)。大数据。可从 https://www-statista-com . ez proxy . Westminster . AC . uk/study/14634/big-data-statista-filoral/获取。

● Timmes,J,2014,《地震式转变:纳斯达克向亚马逊红移的迁移》。可从https://www . slide share . net/Amazon web services/fin 401-seismic-shift-nas daqs-migration-to-Amazon-redshift-AWS-reinvent-2014获取

●M . Trombly,2000 年,创纪录的交易量使纳斯达克陷入困境。可从https://www . computer world . com/article/2593644/it-management/record-volume-stalls-Nasdaq . html获得

●判决,(2017)。GDPR 的监管规定可能会让银行在头三年被处以超过€47 亿英镑的罚款。可从https://www . verdict . co . uk/what-is-gdpr-regulations-could-cost-banks-over-E4-70 亿-in-fines-first-three-years/

● Woodie,A. (2017)。GDPR:告别大数据的蛮荒西部。可从https://www . datanami . com/2017/07/17/gdpr-say-goodbye-big-datas-wild-west/获取

●尹,s .和凯纳克,o . 2015。现代工业的大数据:挑战和趋势[观点]。IEEE 会议录,103(2),第 143-146 页。

●泽朗,J. (2017 年)。大数据和 GDPR;金融中的风险和机遇。可从https://www . accounting web . co . uk/community/blogs/jesper-zer lang/big-data-and-gdpr-risk-and-opportunity-in-finance获取

现在,把你的想法放在 Twitter Linkedin,以及Github!!

同意 还是 不同意 与 Saurav Singla 的观点和例子?想告诉我们你的故事吗?

他对建设性的反馈持开放态度——如果您对此分析有后续想法,请在下面的 评论 或联系我们!!

推文@ SauravSingla _ 08、评论Saurav _ Singla,还有明星SauravSingla马上!

大数据:优势、挑战和未来

原文:https://towardsdatascience.com/big-data-its-benefits-challenges-and-future-6fddd69ab927?source=collection_archive---------10-----------------------

约翰·霍普斯金 DS 专业化系列

简单看一下大数据和未来

由 Unsplash 上 Greg Rakozy 拍摄的照片

[Full series](https://towardsdatascience.com/tagged/ds-toolbox)[**Part 1**](/the-data-scientists-toolbox-part-1-c214adcc859f) - What is Data Science, Big data and the Data Science process[**Part 2**](/how-to-learn-r-for-data-science-3a7c8326f969) - The origin of R, why use R, R vs Python and resources to learn[**Part 3**](/a-crash-course-on-version-control-and-git-github-5d04e7933070) - Version Control, Git & GitHub and best practices for sharing code.[**Part 4**](/the-six-types-of-data-analysis-75517ba7ea61) - The 6 types of data analysis[**Part 5**](/designing-experiments-in-data-science-23360d2ddf84) - The ability to design experiments to answer your Ds questions[**Part 6**](/what-is-a-p-value-2cd0b1898e6f) - P-value & P-hacking[**Part 7**](/big-data-its-benefits-challenges-and-future-6fddd69ab927) - Big Data, it's benefits, challenges, and future

本系列基于约翰·霍普斯金大学在 Coursera 上提供的 数据科学专业 。本系列中的文章是基于课程的笔记,以及出于我自己学习目的的额外研究和主题。第一门课, 数据科学家工具箱 ,笔记会分成 7 个部分。关于这个系列的注释还可以在这里找到

介绍

在互联网出现之前,信息在某些方面受到限制,而且更加集中。唯一的信息媒介是书籍、报纸和口头传播等。但现在,随着互联网的出现和计算机技术的进步(摩尔定律),信息和数据激增,它已经成为一个开放系统,信息可以不受任何限制地传播给人们。随着互联网变得越来越容易访问和全球化,社交移动应用和网站逐渐成为共享数据的平台。数据和许多其他东西一样,随着大小的增加而价值增长,这种价值在许多方面都有应用,但主要用于分析和决策。这里有更多关于大数据的内容。

什么是大数据?

ev 在 Unsplash 上拍摄的照片

B ig 数据可以定义为大量的结构化和非结构化数据,通常存储在云中或数据中心,然后被公司、组织、创业公司甚至政府用于不同的目的。

利用数据意味着清理数据,然后分析数据,形成模式和联系、趋势和相关性,以产生洞察力。这就是所谓的大数据分析。

大数据也通常通过其质量来描述,也称为 4v

大数据的质量—4v

1.卷

  • 由于技术和数据存储的改进(云存储、更好的流程等),数据量不可逾越

2.速度

  • 数据以惊人的速度生成,这与计算机的速度和能力增长有关(摩尔定律)

3.多样化

  • 在社交媒体和互联网时代,可以轻松收集各种不同格式和类型的数据。

4.诚实

  • 数据的不一致性和不确定性(非结构化数据—图像、社交媒体、视频等。)

两类数据

结构化和非结构化数据的简要说明

1.结构化的

  • 传统数据—表格、电子表格、包含列和行的数据库、CSV 和 Excel 等
  • 如今的数据很少如此混乱
  • 工作是提取信息,并把它整理成整洁有序的东西

2.无社会组织的

  • 来自数字交互的数据激增——电子邮件、社交媒体、文本、客户习惯、智能手机、GPS、网站、活动、视频、面部识别、
  • 大数据—利用新数据的新工具和方法&清理和分析非结构化数据

大数据工具/语言

有一些流行的工具通常与大数据分析相关联,

工具

  • Hadoop
  • 阿帕奇火花
  • 阿帕奇蜂房
  • 斯堪的纳维亚航空公司

这些工具中的大部分只是用于高效处理大量数据的开源框架和有用的功能。

语言

  • 稀有
  • 计算机编程语言
  • 斯卡拉

这些语言在数据科学领域非常流行,可以用于通过特定的库和包处理大量数据。

大数据在行动

今天很多地方都可以看到大数据。一个普遍的例子是在线零售商。像亚马逊这样的公司专注于建立精确的推荐系统,为他们的客户量身定制,系统越好,他们的客户就会对越多的产品感兴趣,从而转化为更多的销售。

要做到这一点,亚马逊需要大量的数据,如购买行为、浏览和购物车历史、人口统计等信息。建立用户档案的推荐系统也出现在社交媒体、流媒体服务等等。

大数据还应用于许多领域,如医疗保健、制造、公共部门、媒体和娱乐等。

利益

—一些问题受益于大量的数据,凭借庞大的数据量,它否定了微小的混乱或不准确。

速度 —实时信息→根据最新的、有根据的预测做出快速决策

多样性——提出新问题和建立新联系的能力,这些问题是以前无法触及的

准确性——杂乱和非结构化的数据可能会导致隐藏的相关性。

也许更多数据最有希望的好处是识别隐藏的相关性。

示例:

GPT-3

  • 使用深度学习的流行语言模型。它有 1750 亿个参数,它是通过从互联网上吞噬数据来发现模式和相关性而建立的。它能够编写代码片段,

新冠肺炎(新型冠状病毒肺炎)

  • 大数据的概念也可以应用于疫情的情况,通过接触追踪收集人们的行踪(互动和访问位置)数据,可以进行分析来预测病毒的传播,并帮助遏制病毒。

拥有大量数据有它的好处,但它不会没有任何挑战。

挑战

1。大

  • 大量原始数据需要存储和分析
  • 昂贵且需要良好的计算投资

2。不断变化和更新

  • 数据不断变化和波动,为处理这些数据而构建的系统必须具有适应性

3。种类繁多

  • 很难确定哪个数据源有用

4。凌乱

  • 要快速分析的名人
  • 需要先清理数据

大数据的未来

大数据通常与机器学习、数据科学、人工智能、深度学习等其他热门词汇联系在一起。由于这些领域需要数据,大数据将继续在改善我们现有的模型方面发挥巨大作用,并推动研究的进步。以特斯拉为例,每辆具有自动驾驶功能的特斯拉汽车同时也在训练特斯拉的人工智能模型,并随着每次错误不断改进它。这种巨大的数据虹吸,加上一个才华横溢的工程师团队,使特斯拉成为无人驾驶游戏中的佼佼者。

随着数据的不断扩大和增长,AWS、微软 Azure 和谷歌云等云存储提供商将在存储大数据方面占据统治地位。这为公司的可扩展性和效率提供了空间。这也意味着将会有越来越多的人被雇佣来处理这些数据,这意味着更多的工作机会给“数据官员”来管理公司的数据库

大数据的未来也有其黑暗的一面,如你所知,由于隐私和数据问题,许多科技公司正面临来自政府和公众的压力。管理人们对其数据的权利的法律将使数据收集更加受限,尽管是诚实的。同样,网上数据的激增也让我们面临网络攻击,数据安全将变得极其重要。

摘要

照片由 NASA 在 Unsplash 上拍摄

如今,许多大型科技公司都在接收来自用户的海量数据,当涉及到利润、权力或社会的更大利益时,选择前者是人的本性,尤其是在你可以选择的情况下。我们生活在一个注意力不断被资本化的时代。我们必须更聪明地生活,理性地行动,以防止我们的生活屈服于这些短暂的多巴胺爆发以及权宜之计和琐碎的行为。

我们只能希望,随着我们进入未来几十年,控制这些公司决策的人将会为整个社会和文明做出更好的贡献。我们的数据将用于构建服务于我们的系统,使我们更具生产力,而不是寻找吸引我们注意力的方法,构建能够为我们的生活提供价值和意义的产品。

到目前为止所有事情的快速总结

  • 大数据 —快速生成的各种类型的大型数据集。数据从结构化向非结构化转变。
  • 非结构化数据 —定义不明确且需要更多工作来处理的数据(图像、音频、社交媒体等)
  • 结构化数据——被称为传统数据,因为它在现实生活中很少见,基本上是定义明确且易于处理的数据。它的数据科学家的工作是清理它,形成整齐的数据

4v 的优缺点

音量

  • 稍微杂乱的数据抵消了小错误
  • 很多东西需要存储和分析

品种

  • 回答非常规问题
  • 选择类型的负担

速度

  • 实时分析和决策
  • 不断更新

准确性

  • 隐藏的相关性
  • 分析杂乱的数据

你应该吸取的一个重要教训是,即使有大量的数据,你仍然需要正确的数据和正确的变量来正确地回答你的问题。

美国著名数学家约翰·图尔基的一句话很好地说明了这一点:

一些数据和对答案的渴望并不能保证从给定的数据中提取出合理的答案——John Turkey,1986

斯坦福大学的 Atul Butte 引用了另一段关于数据隐藏能力的话

“隐藏在这些成堆的数据中的知识可能会改变病人的生活,或者改变世界。”

感谢阅读,本系列到此结束。我希望你从这些文章中学到了一些东西,并留下关于我如何改进的评论,如果你对我接下来应该写什么有任何建议。保持安全,上帝保佑。

如果您对学习数据科学感兴趣,请查看“超学习”数据科学系列!

* [## 如何“超级学习”数据科学—第 1 部分

这是一个简短的指南,基于《超学习》一书,应用于数据科学

medium.com](https://medium.com/better-programming/how-to-ultralearn-data-science-part-1-92e143b7257b)

查看这些关于数据科学资源的文章。

[## 2020 年你应该订阅的 25 大数据科学 YouTube 频道

以下是你应该关注的学习编程、机器学习和人工智能、数学和数据的最佳 YouTubers

towardsdatascience.com](/top-20-youtube-channels-for-data-science-in-2020-2ef4fb0d3d5) [## 互联网上 20 大免费数据科学、ML 和 AI MOOCs

以下是关于数据科学、机器学习、深度学习和人工智能的最佳在线课程列表

towardsdatascience.com](/top-20-free-data-science-ml-and-ai-moocs-on-the-internet-4036bd0aac12) [## 机器学习和数据科学的 20 大网站

这里是我列出的最好的 ML 和数据科学网站,可以提供有价值的资源和新闻。

medium.com](https://medium.com/swlh/top-20-websites-for-machine-learning-and-data-science-d0b113130068) [## 开始数据科学之旅的最佳书籍

这是你从头开始学习数据科学应该读的书。

towardsdatascience.com](/the-best-book-to-start-your-data-science-journey-f457b0994160)

联系人

如果你想了解我的最新文章,请通过媒体关注我。

也关注我的其他社交资料!

  • 领英
  • 推特
  • GitHub
  • Reddit

请关注我的下一篇文章,记得保持安全!*

基于 Spark 的 Apriori 算法的大数据购物篮分析

原文:https://towardsdatascience.com/big-data-market-basket-analysis-with-apriori-algorithm-on-spark-9ab094b5ac2c?source=collection_archive---------5-----------------------

在 PySpark 上从头开始应用 Apriori 算法

乔丹马德里在 Unsplash 上的照片

客户购买特定产品的概率可能基于几个因素。客户的交易历史、人口统计特征和兴趣等因素都是这方面的例子。如果我们没有这些因素。这意味着顾客以前没有来过我们的商店,我们没有他/她的数据(甚至没有性别)。在这种情况下,我们有办法找到客户可能购买的产品。通常,这些方法中使用的数据属于之前在商店中购物的其他顾客。这些方法获取所有交易,控制交易中的每个项目(产品),并找到显示客户在同一个篮子中购买最多的产品的模式。发现这些模式的方法称为频繁模式挖掘或关联规则挖掘[1]。

Apriori 算法是用于频繁模式挖掘的算法之一。在本文中,我将解释如何在 Python 中用 Spark 应用 Apriori 算法。在开始应用下面的代码之前,了解“Apriori 算法”是如何工作的是很重要的。我还将解释 Apriori 的基础知识,但如果你想详细了解它,请阅读我以前的文章什么是“Apriori 算法”及其工作原理。在这篇文章中,将会看到以下几个部分,

  • 应用先验知识的一个实例
  • 什么是火花,为什么我们应该使用它
  • 如何准备交易数据
  • 先验术语和基础
  • 使用 PySpark 从头开始应用 Apriori

快捷方式:您可以在我的 GitHub 仓库中找到 python PySpark 上 Apriori 算法实现的源代码,并且可以使用为 Spark 创建的模块。

[## 塞尔根坎西斯/先验派斯帕克

该模块被开发用于在基于 RDD 的 pyspark 上运行 apriori 算法。在功能更新之前,应该显示数据…

github.com](https://github.com/sergencansiz/apriori-pyspark)

示例案例

假设纽约市有一个蔬菜水果商。这家蔬菜水果商是纽约市最大的蔬菜水果商,一个月有数百万顾客。蔬菜水果商的老板仅在一天内就购买了大量的产品。然而,有些日子她卖不完所有的产品,就把它们扔掉,因为产品的寿命到期了。因此,扔掉产品会造成大量损失。因此,蔬菜水果店的老板决定创新他们的营销策略。她想为她的蔬菜水果商雇佣一名数据科学家。这位数据科学家的职责是创建一种算法,可以找到客户将产品放入购物篮后可能会购买的产品。她将为算法为每个特定客户找到的产品提供折扣。由于这种算法,她计划及时销售她的产品。好主意!
现在,假设她雇佣的数据科学家是你,你会如何开始?

环境

Apache Spark [2]是一个开源分析引擎,专注于速度、易用性和分布式系统。它运行机器学习算法的速度比非分布式系统快 100 倍[3]。如果有大量数据集,Spark 将是分析该数据集的最佳选择。好的,让我们回到我们的例子:考虑到蔬菜水果商一个月有数百万的顾客,你将不得不处理数百万的交易数据。为了提供更快的数据分析,最好的选择之一可能是 Spark。

你如何准备你的数据?

首先,你应该做的是准备一个客户交易的数据集。但是,你不应该忘记,一个顾客可能会从蔬菜水果店里购买一件或多件商品,这意味着我们的数据集不能每行都有一定数量的列。因此,我决定逐行编写事务,并用逗号分隔事务中的每一项,并保存为“txt 或 CSV”文件。每一行都用逗号分隔的项目表示每个交易。例如,在第一次交易中,客户购买了苹果、芒果和香蕉,在第二次交易中,客户购买了香蕉和芒果。如果您有 CSV 格式的数据集,您也可以使用它(它已经用逗号分隔,但不要忘记删除标题行)。

算法—先验

在 Spark 上实现 Apriori 之前,我们需要理解它的主要术语和概念。Apriori 算法依赖于项目集的频率。它创建包含项目组合的不同表格。它扫描显示所有交易的主数据集,并通过考虑这些组合在主数据集内出现的次数来查找频率[4]。在 Apriori 算法中,这些频率被称为支持值。此外,表格的数量根据最大项目集长度而变化。如果最大项目集长度为 5,则意味着将有 5 个支持值表。但是,有一个最小支持值,用于决定哪个项目集应该留在表中。假设最小支持值已经被决定为 2。因此,如果任何项目集在主数据集中出现的次数少于 2 次,我们应该从表中删除该项目集。

让我们检查下图,以便理解先验是如何工作的。为了简单易懂,我在下图中取了一些交易记录。

先验-支持表(图片由作者提供)

“数据集”代表我们的交易数据,“数据集”中的每一行都显示了客户同时购买的每个交易项目集。表 a 中有单项频率。这是我们需要为 Apriori 算法创建的第一个表。在表 A 之后是表 B,它包括单个项目的二进制组合。最重要的部分是这里的项目顺序没有意义。所以,“苹果,芒果”和“芒果,苹果”是一回事。因此,在生成项目组合时,必须移除项目集的副本。从表 B 中可以看出,支持值小于 2 的“香蕉-椰子”和“芒果-椰子”的项目集已经被删除。然而,在表 C 中有单个项目的三重组合,并且支持显示在主数据集中出现多少次的值。支持值小于 2 的项目集也从此表中删除。如果您看到表 D,则只有一个支持值为 0 的项目集,它有四个单项。应用算法时不应考虑该表。因为在主数据集中没有这样的交易。

那么,如果一个客户买了苹果,利用上图中的这些支持表,我们怎么计算他买芒果的概率呢?为了计算该概率,我们需要将“芒果”和“芒果,苹果”的支持值放在一起。“芒果”的支持值为 4,“芒果,苹果”的支持值为 3。我们可以计算概率;(3 / 4) * 100 = %75.这个概率被称为先验的置信值。对该值的解释是,购买芒果的客户可能会购买置信度为%75 的苹果产品。

现在,我们知道如何计算支持度置信度值。我们可以用 PySpark 来研究 Apriori 算法。在下面一节中我们将看到;

  • 使用 PySpark 读取数据
  • 解析数据以激发 RDD 对象
  • 使用“MapReduce”查找项目的第一个支持值
  • 决定最小支持值
  • 使用“MapReduce”创建以下支持表
  • 计算置信度值
  • 决定客户购买哪种产品时信心十足

用 PySpark 读取数据集

PySpark 在 rdd 上工作,这意味着我们需要将所有事务记录转换成多个 rdd。在此之前,我们需要确保 SparkContext 已创建,以便定义 rdd 的每个记录并读取 CSV 文件。

在开始本节之前,请确保您的系统上安装了 SparkPySpark

首先,在你的工作目录中创建一个名为“apprioriSpark.py”(或者任何你想要的名字)的 python 文件,然后你可以通过下面的命令轻松地创建一个 SparkContext(你还应该从 P ySpark 导入 SparkContext )。

代码 1:用 PySpark 创建 spark 上下文

创建 SparkContext 后,我们可以使用 SparkContext 中的 textFile()方法读取数据。请确保您的数据文件与 python 文件位于同一目录中。

代码 2:用 Spark 读取文本文件

将交易项目解析到 RDD

默认的 textFile()方法逐行读取文件,这意味着 CSV 文件中的每一行都将是一个 RDD 值。这些 rdd 包括 CSV 行作为单个字符串值(结果在第 6 行)。这就是为什么我们需要映射到每个 RDD,并用逗号分割这些单个值,以便获得行中的每个项目,并将它们分割到一个 RDD 数组中。为了跑那段路。

代码 3:将项目解析到数组中

现在,您可以清楚地看到,事务数据集中的每一行都由逗号分隔。在我们的 RDD 中,每个数组都代表客户交易的项目列表。我们通过考虑属于客户的每一笔交易,成功地将文件转换为 Spark RDD 对象。

为先验获取项目的第一支持值

Apriori 算法依赖于项目的频率。因为第一,我们需要获得每一个项目的频率。这些频率将是我们在表 1 中的第一个支持值(如前一节所述)。为了做到这一点,我们需要将 rdd 中的每一项提取到数组的所有项中。我们可以通过使用“平面图”方法做到这一点。

代码 4:文件中项目的平面映射

从结果可以看出;我们所有的交易项目都在一个数组中。现在我们可以计算每个独特的项目的频率。不要忘记,这些频率将是我们的第一支持值。如果我们将致力于“NumPy”阵列,找到频率将是容易的。但是,我们在 rdd 上工作,这就是为什么我们需要通过考虑“MapReduce”方法来找到获得频率的方法。解决方案;首先,我们可以将每个项目转换为一个“元组”对象,并添加“1”作为“元组”的第二个项目。我们可以通过使用“reduceByKey”(类似于 SQL 中的 groupby 方法)方法对这些值求和。通过对元组的第二个数字求和,我们可以获得每个唯一项目的频率(客户交易发生的次数)。我们还需要在功能部分列出独特的项目。因此,我们也可以通过使用“distinct”方法来获得独特的项目。

代码 5:生成第一个支持值

如果在上面的代码片段之后运行“supportRdd.collect()”,就会得到第一个 item -support 元组(假设为表 A)。从支持值可以看出,“苹果”比其他品牌出现的频率更高。这意味着购买“苹果”产品的可能性比其他产品更大。这些支持值是通过分别考虑每个项目获得的。我们还需要考虑它们如何在事务中一起出现。得益于此,我们可以通过 Apriori 算法计算置信度值。我们将在接下来的课程中看到这些步骤。

最小支持值

为了决定哪些项目集将留在支持表中,我们需要定义一个最小支持值。我们可以选择最小支持值作为第一个支持值数组(表)中的最小频率。如果项目集数组中的任何支持值小于最小支持值,我们应该从该数组中删除该项目集。如果我们的数据没有很多记录,最小支持度可能是 1。在这种情况下,我们可以将最小支持度定义为 2 或任何大于 1 的值。

代码 6:支持 RDD 对象和最小支持

在本例中,我们发现最小支持值为 1。为了获得更一致的结果,我们可以将最小支持度设置为 2。这意味着,如果任何项目或项目集在交易中出现少于 2 次,我们不会考虑它。从第 8 行可以看出,我们根据最小支持值过滤了第一个项目集表(这是单个项目支持值)。我们还创建了一个“baseRdd”对象。“baseRdd”代表我们对每一项的第一支持值。此对象将使用即将到来的组合支持值进行更新。我们还需要定义“supportRdd ”,它只显示没有支持值的项目。我们将在下一节中使用它来创建项目的组合。

进入 Apriori 算法

在本节之前,我们只找到了每个项目的支持值(频率)。现在,我们将创建一个在 while 循环中生成项目组合的算法。在每个循环中都将创建不同的支持表。当不存在任何支持值大于最小支持值的组合时,该 while 循环将结束。该算法将控制这些项目组合在每个循环的事务数据集中一起出现的次数,并将其保存在 RDD 中。

我们已经创建了一个“supportRdd”对象,它只包含第一个表的项目集,没有支持值(每行只有一个项目)。现在,我们将在 while 循环中使用这个 RDD,将它与唯一的项目组合起来,以便创建其他支持表。然而,这个 RDD 将在每次循环之后被更新。比如说;

# Fitst supportRDD
([Apple] , [Mango] , [Banana] , [Grapes])# After first loop = supportRDD 
([Apple,Mango],[Mango,Banana],[Apple,Banana],[Apple,Grapes] ......)# After second loop = supportRDD
([Apple,Mango,Grapes] , [Apple,Banana,Grapes] ........ )

该算法将根据最小支持值过滤每个组合表。当没有项目设置时,while 循环将结束。此外,我们还需要定义一个函数,它可以在组合的项目集中找到副本。如前所述;(苹果,芒果)和(芒果,苹果)的集合对于 Apriori 算法来说是一样的。正因为如此,我们需要找到这样的模式,并删除其中的。从下面的代码片段可以看到,有一个函数叫做“removeReplica”。该函数在组合后删除这些重复项,并只返回其中一项。

耶!我们准备创建 while 循环。首先,我们需要定义一个变量,我们可以在每个循环中控制项目集长度。它在上面的代码片段中表示为“c”。这个“c”变量从 2 开始。为什么?请记住,我们已经创建了第一个支持表“supportRdd”。所以,在 while 循环中支持表将从 c=2 开始。这意味着将在 while 循环中创建的第一个支持表将具有包含 2 个项目的项目集。为了创建项目的组合,我们可以使用 PySpark 附带的“笛卡尔”函数(第 6 行)。它被创建,我们将删除重复的项目(在第 7 行)。我们将使用“c”变量,以便比“c”变量更多地过滤组合项目(在第 9 行)。然而,我们也使用“distinct”方法来获得一个惟一的项目集,以防万一。

正如你所看到的,在每个循环中创建了两个对象“组合”和“组合 _2”。上面已经解释过了。“Combined_2”则是“Combined”变量和整个数据集(每笔交易)的每一行的组合。从第 14 行可以看出,有一个过滤过程控制每个项目集,不管“组合”的项目集是否在数据集中。如果数据集中没有任何这样的项目集,则它移除该项目集。毕竟我们也是用“reduceByKey”的方法得到频率,按照最小支持值过滤。在第 21 行,我们将最终的支持表添加到“baseRDD”中,它包含我们所有的项目集支持值(理论上它被称为 table)。但是,我们还需要用不带支持值的“combined_2”更新“supportRdd”变量。这个过程将继续下去,直到“supportRdd”中没有任何项目集。

最后,我们可以计算置信度值。您可以使用以下代码来计算 baseRdd(整个项目集组合)的每个组合的置信值。有一个“Filter”类,可以根据置信度计算过滤数据。它还包括计算置信度的“计算置信度”方法。

如果运行 baseRddConfidence.collect()可以获得所有置信度值。您还可以过滤大于特定置信度的结果。结果中的几个例子如下所示:

[[['Apple'], ['Mango'], 58.333333333333336], 
 [['Mango'], ['Apple'], 70.0], 
 [['Apple'], ['Banana'], 41.66666666666667], 
 [['Apple'], ['Mango', 'Banana'], 33.33333333333333], 
 [['Mango', 'Apple'], ['Banana'], 57.14285714285714], 
 [['Apple', 'Banana'], ['Mango'], 80.0], 
 [['Mango', 'Banana'], ['Apple'], 66.66666666666666], 
 [['Mango', 'Apple'], ['Raspberry'], 28.57142857142857
 [['Raspberry', 'Apple'], ['Mango'], 50.0], 
 [['Mango', 'Raspberry'], ['Apple'], 50.0], 
 [['Mango', 'Banana'], ['Raspberry'], 33.33333333333333], 
 [['Mango', 'Raspberry'], ['Banana'], 50.0], 
 [['Raspberry', 'Banana'], ['Mango'], 50.0]]

数组中的第一个项目集显示客户购买的产品,第二个项目集显示如果客户购买了第一个项目集中的产品,他们可能会购买的产品。数组的最后一个元素显示了该模式的置信度值。例如,购买芒果的客户可能会以%58 的信心购买苹果。再比如;购买芒果和香蕉的顾客可能会以 66.6%的信心购买苹果。如果仔细看前两个数组["Mango "," Apple" ]和["Apple "," Mango"]的置信度值不同。我们来写一下对“芒果”= >“苹果”的支持公式

( support(["Mango" , "Apple"]) / support(["Mango"]) ) * 100 = 70

和公式[“苹果”= >“芒果”]

( support(["Mango" , "Apple"]) / support(["Apple"]) ) * 100 = 58

["芒果"]"苹果"]的支持度是 7,["芒果"]的支持度是 10,["苹果"]的支持度是 12。虽然在两种计算中[“苹果”“芒果”]的出现频率(支持度)相同,但由于“苹果”的出现频率和“芒果”的出现频率不同,所以它们的置信度值也不同。

您也可以通过使用以下代码来转换结果 pandas 数据框;

结论

在本文中,我们学习了什么是频繁模式挖掘,以及如何将其应用于 Apriori 算法。我们以一个数据集为例,从头开始在 PySpark 上应用 Apriori 算法。您还可以查看其他 FPM 方法,如 FPGrowth、Eclat 等。理解了先验知识之后,你就可以很容易地理解其他方法是如何工作的。如果你有任何问题,请随时提问。

希望对你有帮助…

参考

【1】频繁模式挖掘
【https://en.wikipedia.org/wiki/Frequent_pattern_discovery】T4

****【2】阿帕奇火花
https://spark.apache.org/

****【3】什么是火花
https://databricks.com/spark/about

【https://en.wikipedia.org/wiki/Apriori_algorithm 先验算法

大数据显示每个人都会撒谎

原文:https://towardsdatascience.com/big-data-says-everybody-lies-b7e9e28376c2?source=collection_archive---------17-----------------------

为什么大数据如此重要,为什么您也应该关注它

詹·西奥多在 Unsplash 上的照片

你的直觉在骗你

在我们的日常生活中,除了高科技,绝大多数人都是凭直觉做决定和给出建议。在他们的一生中,他们吸收了大量的数据,这些数据安全地保存在他们的大脑中,使他们能够对问题做出结论。

然而,这带来了几个问题:

  1. 你所有的观察(数据点)都是从你的角度出发的。这意味着你会看到一个有限的画面。
  2. 随着时间的推移,你的大脑会改变记忆,你能记住的就这么多

以篮球为例。你可能听说过贫穷的成长会帮助你成为一名优秀的 NBA 球星。有很多成功的故事证明,看到勒布朗·詹姆斯,所以这一定是真的。但你听到的故事只是成功的故事(生存偏差);你没听到剩下的。

“下一个弗洛伊德将是数据科学家。下一个马克思将是数据科学家。下一个索尔克很可能会成为一名数据科学家。”

这就是为什么大数据非常有益,可以帮助回答有趣的问题。大数据可以从全国范围内获取数据,看看成长为穷人或中产阶级对你的 NBA 梦想是否有任何影响。事实证明确实如此。如果你不是出身贫寒,你更有可能进入 NBA。

这个博客是关于什么的?

除非你过去十年一直躲在石头下面,否则你肯定听说过大数据。这是一个越来越受欢迎的话题。这种现象如此普遍,以至于一本关于大数据的书登上了纽约畅销书排行榜!

谷歌大数据趋势

这本书名为《每个人都在撒谎:网络能告诉我们的真实身份》,作者塞思·斯蒂芬斯-达维多夫茨。

[## 每个人都会撒谎

纽约时报畅销书。年度经济学家书籍

books.google.co.uk](https://books.google.co.uk/books/about/Everybody_Lies.html?id=8dEkDwAAQBAJ&printsec=frontcover&source=kp_read_button&redir_esc=y#v=onepage&q&f=false)

嗯,我读了这本书,总共 300 页左右,我觉得它很吸引人。为了不让你也不得不去读它,我试图在这篇博客中提炼出这本书的信息。我希望你会觉得有趣。

乔·塞拉斯在 Unsplash 上的照片

图书概述

总的来说,这本书描绘了什么是大数据,以及如何使用它来识别某些以前未知的真相。它举例说明了它是多么有用,如果你不给予应有的关注,它会被有意或无意地误解。

在整本书中,赛斯给出了大数据的例子和它揭示的真理,同时给你提供了令人兴奋的轶事,很像史蒂芬·都伯纳和史蒂芬·列维特的《魔鬼经济学》(另一本畅销书)。

“数据科学采用自然、直观的人类流程——发现模式并理解它们——并为其注入类固醇”

更具体地说,这本书探索了许多数据集,包括来自 Google Trends 和 PornHub 的数据。在这样做的过程中,它引起了人们对政治(选举、演讲以及对种族主义的影响等)等话题的关注。),在金融或赛马中寻找优势,以及人类的性。

如果你决定要读这本书,不要过多关注细节,以免毁了它,以下是关键要点!

真诚媒体在 Unsplash 上拍摄的照片

大小不如拥有正确的数据重要

大数据革命不是收集越来越多的数据。这是关于收集正确的数据。

自本世纪初以来,我们目睹了数据生成和可用性的大幅增长。你想要什么样的数据并不重要;它很可能存在!

据认为,在未来五年内,我们每天将产生大约 500 的数据!为了扩大规模,1 EB 等于 1,000,000 TB。

人们正在做各种疯狂的实验,在海量数据中寻找能让他们在行业或工作中获得优势的东西。

这方面的例子包括:

  1. 对冲基金正在使用推特和谷歌数据来计算哪些股票会涨跌。在某些情况下,他们甚至通过低轨道卫星监控停车场。没错——他们去太空给停车场拍照是为了获得优势!
  2. 研究人员在全国各地对赛马进行医疗程序,以找出是什么让赛马禁食。这样,他们就可以预测并确定下一个大赢家。这样做,他们既能知道如何赌钱,又能为拥有和比赛这些马的人充当马匹侦察员。

可能性真的是无穷无尽!

照片由米切尔罗在 Unsplash

每个人都会撒谎,除了对谷歌

人们一次又一次地发现,当人们认为自己被监视时,他们往往会撒谎。根据赛斯的说法,说谎是很普遍的。

“一切都是数据!有了这些新数据,我们终于可以看穿人们的谎言了。”

人们对朋友、社交媒体和调查撒谎。在某种程度上,他们也可能对自己撒谎。只有当你放大人们的行为,并在他们认为没人看的时候关注他们真正的问题(见谷歌搜索),你才能开始从谎言中看到真相。

网飞在其生命周期的早期也得到了类似的教训:不要相信别人告诉你的;相信他们所做的。

利用公共调查的数据,人们可以很快了解美国人有多少安全性行为。然而,将这一数据与避孕套销售进行比较,似乎存在相当大的差距。通过查看谷歌趋势数据,我们可以发现大量关于“无性婚姻/关系”的搜索

同样的逻辑也适用于回顾特朗普大选。当美国正在庆祝后种族时代的成功时,特朗普当选了。塞思的谷歌趋势分析再次揭示了一些非常令人担忧的结果。

照片由 NASA 在 Unsplash 拍摄

大数据,小范围

研究人员和机构一直在收集大量的数据集。拥有大型数据集并不是什么新鲜事。大数据背后的理念是这种数据的深度和广度。您可以收集前所未有的详细数据。人家居然会免费递过来!

“大数据允许我们有意义地放大数据集的小部分,以获得关于我们是谁的新见解。”

有了新级别的数据,数据科学家可以在微观和宏观级别上放大和缩小,以了解更多信息。他们可以从国家一级的分析开始,然后向下移动到州、城市、城镇、村庄,甚至社区。

照片由 Aki Tolentino 在 Unsplash 上拍摄

公司如何利用大数据影响你

鉴于每个人都在撒谎,人们不禁要问调查的价值何在。公司一直使用焦点小组来确定人们喜欢或不喜欢某个产品,但对使用 A/B 测试更有选择性,因为它往往更昂贵。

A/B 测试是应用随机实验来理解变量变化的影响的过程。正如你所想象的,由于变量和可变值的数量无限,公司需要在这个过程中分配大量的资源。

然而,在互联网和软件时代,游戏完全变了。公司可以推出不同的内容,在不同的人群中稍加修改,然后观察他们如何与之互动。这可能包括一些文本的颜色、措辞、字体、位置;什么都有可能。

“2011 年,谷歌工程师进行了 7000 次 A/B 测试。而且这个数字还在不断上升。”

这个过程被政客、软件公司和几乎所有想要获得优势的人所使用。他们不关心为什么你的潜意识喜欢那种措辞,或者当你看到它时,为什么你的大脑会活跃起来并与之互动——只关心你会这样做。

“2009 年,谷歌在 A/B 测试中测试了 41 种略微不同的蓝色后,一名沮丧的设计师辞职了。但这位设计师支持艺术胜过痴迷的市场研究的立场,并没有阻止这种方法的传播。

由 Unsplash 上的信托“Tru”kat sande拍摄的照片

你最好再检查一下那些结果

与任何事情一样,在处理大数据和统计数据时,需要注意一些陷阱。有一些你可能会屈服的常见错误,所以值得仔细检查你的结果。

同样不言而喻的是,你无疑应该仔细检查别人对具体结果的说法。

维度的诅咒

用随机变量重复一个实验足够多次,果然,你会发现一些相关性。然而,仅仅因为你找到了一段关系,并不意味着它就在那里。

换句话说,随着数据维度级别的提高,您需要更多的观察数据来支持您的分析。没错;您的大数据可能不够大!

相关性并不意味着因果关系

仅仅因为你能够在你的数据集中找到两个变量之间的关系,并不意味着一个导致另一个。举个例子,你的研究让你认识到“所有喝水的人都会死”这个事实。这是一个事实上正确的说法,但如果你说死亡是由饮水引起的,那你就错了。

这种现象被称为“反向因果关系”,需要注意的是,相关性并不意味着因果关系。

奥比·奥尼耶德在 Unsplash 上拍摄的照片

大数据的伦理

大数据非常强大,可以应用到生活的各个方面。这就提出了使用这种做法的道德问题。

举个例子,一个特定的行为是你下一步要做什么的一个重要的统计预测。公司或政府是否应该提前采取措施?会做第一个动作而不是预测的第二个动作的人的百分比是多少?

或者考虑回答某些类型的问题的含义,这些问题可能不需要回答。

结论

总的来说,我觉得这本书很有趣。从这本书里可以获得很多好的观点和一种思维方式。总之,作者说他希望这本书与《魔鬼经济学》不相上下或者超越它。我会说,这是一个很好的尝试,但不完全在同一水平上。

如果你喜欢这本书的概述,也许你也会喜欢我对“我们为什么睡觉”的评论:

[## 关于睡眠的 5 个重要事实

我从阅读《我们为什么睡觉》中学到了什么

medium.com](https://medium.com/swlh/5-important-facts-about-sleep-76b92d23f3d8)

大数据,小盒子

原文:https://towardsdatascience.com/big-data-small-box-d9896310259f?source=collection_archive---------41-----------------------

使用 VirtualBox: Spark、ElasticSearch & Kibana 构建和浏览大数据开发环境。

照片由法比奥在 Unsplash 上拍摄

TL;博士:看看我们如何使用 Vagrant 来构建和配置一个大数据开发环境,它小到可以装进你的笔记本电脑。用一行代码启动这个环境。掌握 ElasticSearch、Kibana 和 Spark 的基础知识:将 Spark 数据帧索引到 Elasticsearch,然后了解如何使用 Python、Kibana 或 good ol' cURL 查询索引。享受使用虚拟机的乐趣,提高您对大数据堆栈中一些关键技术的熟练程度。

我已经尽可能地让这篇文章易于理解,你应该能够在不了解我们将使用的任何技术的情况下理解这篇文章。

1.介绍

在本文中,我们将把大数据堆栈中的关键技术联系在一起,探索数据如何在这些组件之间流动,以及每个组件发挥什么功能。我们将能够通过使用一种让我们构建和配置虚拟机,并为它们提供软件的技术,非常容易地做到这一点。事实上,如果你已经做到了这一步,你离拥有一个功能性的“大数据”开发环境只有几步之遥,尽管没有处理 TB 级数据集的资源。

您将能够使用此设置来学习如何在自己的时间内高效使用大数据技术堆栈(并且在没有人看到的情况下犯错误),以便在真正使用这些技术时,您将拥有坚实的基础和一些实践经验!

内容

  1. 简介
  2. 入门
  3. 弹性搜索和基巴纳
  4. 火花
  5. ElasticSearch Hadoop
  6. 快捷方式
  7. 进一步练习和阅读

2.入门指南

是时候开始运行了..travel 允许我们根据写在 travel 文件中的指令初始化、供应和配置虚拟机。一个浮动文件包含虚拟机供应器的指令,以及(可能)在虚拟机上下载、安装和配置软件所需的所有其他内容(尽管指令块可以重构为在供应过程中执行的单独脚本)。这意味着,如果你幸运的话,有人已经创建了一个描述虚拟机的流浪文件,它有能力做你想做的事情,你可以直接进入有趣的部分。要开始使用我为本文创建的 VM,请遵循下面的步骤。

  1. 下载并安装 vagger(以及类似VirtualBox)https://www.vagrantup.com/intro/getting-started这样的 VM 提供者),检查你是否可以创建一个基本的裸机 VM。
  2. 从这里克隆我的 GitHub 库,这包含一个将被用来创建一个特定 VM 的流浪文件,以及一些安装脚本来为它提供我们想要使用的软件。
  3. *进入克隆的 git repo,打开命令控制台并键入vagrant up

*作为设置虚拟机过程的一部分,Spark 从这里下载并安装。实际上,在下载 Spark 之前,我已经包含了一个步骤,让安装脚本检查spark-2.4.6-bin-hadoop2.7.tgz文件是否已经存在于与流浪者文件相同的目录中,如果是,那么下载步骤被跳过。我建议手动下载这个文件,放在流浪汉文件目录下,因为下载这个.tgz的默认镜像站点会超级慢。

一旦你输入了vagrant up,就是这样!喝杯茶犒劳一下自己,因为安装和配置不会在瞬间完成。

这个简单的小命令只是触发了一系列事件的连锁反应,最终将创造一个完全成熟的大数据虚拟机供我们使用和探索。事情是这样的:

  1. 创建了一个虚拟机。
  2. Python、Spark、ElasticSearch 和 Kibana 都被安装在虚拟机上。
  3. 一个 Python 虚拟环境(虚拟机中的虚拟环境?矩阵多?)时,PySpark 是根据 Spark 附带的源代码构建的,并安装到该虚拟环境中。

在了解如何使用我们的虚拟机探索这些技术之前,让我们简要了解一下它们各自扮演的角色,以及它们通常如何在生产大数据环境中一起使用。

  1. 火花。Spark 是我们的分布式计算引擎,接受使用 Python 或 Scala API 等指定的指令,并在我们的集群中优化和并行化所需的数据转换。Spark 用于在内存中快速处理大型分布式数据集。
  2. 弹性搜索。ElasticSearch (ES)是一个搜索引擎,它允许我们对事物(文档)进行索引,这样我们可以非常快速地搜索和检索特定的信息。在本文的后面,我们将介绍如何直接从 Spark 数据帧中索引文档。可以使用一组由 es 服务器作为端点公开的 API 来搜索、更新和删除索引。这为我们提供了在非常大的数据集上构建面向用户的应用程序所必需的响应能力。
  3. 基巴纳。基巴纳有多种用途。它可以作为一种工具,以一种用户友好的方式探索经济服务指数。我们还可以使用 Kibana 构建仪表板,并使用其开发工具来学习如何与 ElasticSearch 交互。

尽管 ElasticSearch 和 Kibana 是数据可能流向的“目的地”,但我们将通过查看这两个工具来开始探索我们闪亮的新虚拟机,因为服务器进程应该已经在运行了!

启动、停止和重新启动虚拟机

您可以在方便的时候轻松地停止和启动 VM。要停止 VM,在游民文件所在目录的 shell 中键入vagrant halt(如果您已经通过 ssh 进入 VM,请确保在执行该命令之前关闭 ssh 连接)。当您想重启 VM,并从您离开的地方开始,只需运行vagrant up。谢天谢地,这将比我们第一次运行虚拟机时快得多!

我们的虚拟机由 vagger 和 VirtualBox 构建,托管了多项大数据技术。

3.弹性搜索和 Kibana

虚拟机启动并运行后,让我们执行一些基本的检查,以确保一切正常。您应该已经克隆了 git 存储库,并运行命令vagrant up来启动、配置和供应虚拟机。现在运行命令vagrant ssh将 ssh 导入正在运行的机器。使用以下命令检查 ElasticSearch 和 Kibana 是否已成功启动:

systemctl status elasticsearch (2.a)

systemctl status kibana (2.b)

这两个命令应该向我们显示一些看起来令人放心的输出,告诉我们我们的服务正在运行。如果一切正常,运行以下代码应该没有问题:

curl -XGET http://127.0.0.1:9200/_cat/health?v (3)

我们刚刚向 ElasticSearch REST API 提交了一个 HTTP GET 请求,我们应该会收到一个响应,给出一些关于弹性集群状态的诊断信息。从 ES 索引中查询和检索信息同样简单!我们可以尝试的下一件事是切换到我们主机上的浏览器并导航到127.0.0.1:5602(注意,在Vagrantfile中,我们已经配置了来宾虚拟机的端口5601,这是 Kibana 正在侦听的端口,用于将流量转发到主机上的端口5602)。在我们的浏览器中,我们应该能够看到一个闪屏,告诉我们 Kibana UI 正在启动。加载后,导航至“开发工具”(左侧导航面板底部的扳手图标)。这使我们能够访问一个控制台,该控制台允许我们向 es 服务器发送请求,并帮助我们处理语法、自动完成以及探索可用的选项。响应显示在相邻的窗口中。尝试输入GET /_cat/health?v并将查询发送到 ES 服务器。在引擎盖下,发生了与我们执行(3)时非常相似的事情。

很高兴知道我们的 ES 集群正在运行——但是更好的做法是完成文档的索引和搜索过程。导航到一个工作目录—可能是/home/vagrant,然后使用下面的命令下载并解压缩一些示例数据。

wget https://download.elastic.co/demos/kibana/gettingstarted/accounts.zip (4.a)

unzip accounts.zip (4.b)

现在我们将使用 ElasticSearch 批量上传 API 来索引accounts.json中的文档。为此,我们需要向 ES 服务器发出一个POST请求。完整的命令是:

curl -H "Content-Type: application/x-ndjson" -XPOST 127.0.0.1:9200/financial/_bulk?pretty --data-binary @accounts.json (5)

注意accounts.json是根据 API 文档中概述的要求方便地格式化的。这就在financial索引中创建了 1000 个新文档。一个成功的请求将会得到一个由类似下面的单元组成的长响应:

"index" : {
        "_index" : "financial",
        "_type" : "_doc",
        "_id" : "990",
        "_version" : 4,
        "result" : "updated",
        "_shards" : {
          "total" : 2,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 3998,
        "_primary_term" : 1,
        "status" : 200
      }

现在让我们从索引中检索一些文档。为了增加多样性,切换回浏览器中打开的 Kibana 应用程序。转到控制台,键入GET /financial/_doc/1,然后“点击发送请求”。在相邻的窗口中,我们将看到响应,应该是成功的,以及带有_id = 1的文档的内容。将使用文档的内容填充_source属性。注意,我们可以通过使用不同的工具,比如curl,来发出请求,从而获得相同的结果。

如果你已经做到了这一步,祝贺你。您已经拥有了使用 ElasticSearch 和 Kibana 进行探索和实验所需的一切。请记住,稍后您可以轻松地停止并重新启动您的虚拟机,以继续接下来的步骤。

4.火花

我们要使用的下一项技术是 Spark。Spark 实际上是高性能大数据处理的同义词。我想在这里介绍它的原因是,可以直接将 Spark 数据帧的行索引到一个弹性簇中。这使得直接从数据处理管道向 Elastic 写出步骤(我们的输出)变得非常容易,在 Elastic 中,可以通过 API 搜索索引和检索单个文档,或者使用 Kibana 仪表板浏览和可视化。在我更详细地介绍如何做到这一点之前,让我们先了解一下如何在我们的流浪者虚拟机中使用 Spark。Spark 有用多种语言编写的 API,我们将使用 Python API,也就是 PySpark。

从连接到虚拟机的 shell 中,导航到/vagrant/examples,并运行

pipenv shell,(6)

这将激活已经使用pipenv设置好的 Python 虚拟环境。通过使用 pip 构建和安装 Spark 发行版中包含的 PySpark 源代码,PySpark 已经被安装到这个虚拟环境中。如果您有兴趣更详细地理解这些步骤,您可以查看 GitHub 资源库中的bootstrap/install/spark_install.shbootstrap/install/setup_demo_project.sh脚本。

此时,你有两个选择:一组捷径,或者绕远路。要查看可用的快捷方式,请查看快捷方式部分。

请继续阅读,寻找一种更为基础的方法,我们将一个接一个地分解中间步骤。

我们应该做的第一件事是启动 Python 解释器并运行以下命令,以检查我们是否可以正确启动 Spark 会话:

(examples) vagrant@vagrant:/vagrant/examples$ python
Python 3.5.2 (default, Jul 17 2020, 14:04:10)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pyspark
>>> from pyspark.sql import SparkSession
>>> ss=SparkSession.builder.getOrCreate()

这将为您提供一个 SparkSession 对象,它是底层 Spark 魔法的主要入口点,接下来我们应该使用它将一些数据加载到 DataFrame 中。为此,我们将重复使用上一节中获得的accounts.json。我们需要通过删除包含索引/id 信息的行来快速转换这些数据,这样我们就可以将数据读入 Spark 数据帧。我们可以使用sed(流编辑器)来完成,您可以在单独的 shell 中使用它:

cat accounts.json | sed -n 's/\({"a.*}\)/\1/\p' > accounts_edited.json

head -n 5 accounts_edited.json检查结果,你会注意到我们用索引信息去掉了断续的行。你还会注意到我的正则表达式非常懒惰,在更一般的情况下会很快失效。我不找借口。

切换回我们的 Python 解释器,将 json 文件加载到 Spark 数据帧中(注意,如果您将数据下载到不同的位置,则必须在代码片段中设置适当的路径):

>>> import json
>>> import os
>>> data_file = os.path.join(os.environ['HOME'], 'accounts_edited.json')
>>> with open(data_file, 'r') as f:
...   data = [Row(**json.loads(l)) for l in f]
...
>>> df = ss.createDataFrame(data)
>>> df.printSchema()
root
 |-- account_number: long (nullable = true)
 |-- address: string (nullable = true)
 |-- age: long (nullable = true)
 |-- balance: long (nullable = true)
 |-- city: string (nullable = true)
 |-- email: string (nullable = true)
 |-- employer: string (nullable = true)
 |-- firstname: string (nullable = true)
 |-- gender: string (nullable = true)
 |-- lastname: string (nullable = true)
 |-- state: string (nullable = true)

这个 Spark 数据帧与您可能在使用 Spark 的任何类型的数据处理管道的末端(或中间(或开始…))使用的对象完全相同。我们接下来要做的是看看如何将这个对象中包含的数据直接索引到 ElasticSearch 中。

5.ElasticSearch Hadoop

现在,为了能够将 Spark 数据框架直接索引到 ElasticSearch 中,我们需要付出一些努力来进行设置——即 ElasticSearch 和 Spark 之间的接口,该接口由 ElasticSearch Hadoop 提供。同样,一些工作已经完成了:所需的归档文件已经在 VM 的供应期间下载并解压缩,相关的代码片段可以在这里找到。您还会注意到,我在.bashrc文件中添加了一个export语句,定义了一个名为ES_HDP_JAR的环境变量。将该变量的值回显到控制台,以查看实例化会话时需要传递给 Spark 的 jar 文件的路径。正是因为包含了这个 jar 文件,我们才可以直接使用 PySpark DataFrameWriter 对象中的索引数据。我们可以利用 Python 中的环境变量来轻松配置新的 SparkSession:

(examples) vagrant@vagrant:/vagrant/examples$ python
Python 3.5.2 (default, Jul 17 2020, 14:04:10)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> from pyspark import SparkConf
>>> from pyspark.sql import SparkSession
>>> sconf = SparkConf().set('spark.jars', os.environ['ES_HDP_JAR'])
>>> ss = SparkSession.builder.config(conf=sconf).getOrCreate()

我们将索引使用前面步骤中的accounts_edited.json数据创建的数据帧。我们需要运行的命令是:

>>> df.write\
... .format('org.elasticsearch.spark.sql')\
... .option('es.nodes', 'localhost')\
... .option('es.port', 9200)\
... .option('es.resource', 'sparkindex')\
... .save()

上面的命令使用数据帧df的内容创建一个新的索引sparkindex。要查看这个新索引的内容,请切换回 Kibana 控制台(或使用等效的命令行),并使用带有空“match_all”子句的搜索 API:

GET /sparkindex/_search
{
  "query": {
    "match_all": {}
  }
}

请注意,ElasticSearch 文档包含了与上面类似的示例,带有“复制为 cURL”选项,因此您可以看到如何使用 cURL 实现相同的结果。

响应的正文将包含一些匹配的文档:

"hits" : [
      {
        "_index" : "sparkindex",
        "_type" : "_doc",
        "_id" : "PFapu3MB4cJ_QglfiKLK",
        "_score" : 1.0,
        "_source" : {
          "account_number" : 1,
          "address" : "880 Holmes Lane",
          "age" : 32,
          "balance" : 39225,
          "city" : "Brogan",
          "email" : "[amberduke@pyrami.com](mailto:amberduke@pyrami.com)",
          "employer" : "Pyrami",
          "firstname" : "Amber",
          "gender" : "M",
          "lastname" : "Duke",
          "state" : "IL"
        }
      }
]

注意,因为我们没有指定一个列作为惟一的文档标识符,所以已经代表我们生成了_id字段。

返回目录

6.捷径

/vagrant/examples中输入pipenv shell,然后输入spark-es-demo --help,您会看到有几个命令可以运行:

spark-es-demo make-spark-dataframe (7.a .)

spark-es-demo spark-to-es (7.b)

spark-es-demo search-es-index (7。c)

运行这些并检查各自的代码(在/vagrant/examples/examples/spark_demo.py中可以找到)应该会给你一些有用的、有文档记录的例子来参考。

(7.a)将下载一些演示数据,并将其放入 Spark 数据帧中。

(7.b)将带您了解通过 Spark DataFrame 将数据放入弹性集群的整个过程。

(7.c)将允许您编写一个基本的匹配查询并提交给一个 ES 集群。默认情况下,它会寻找一个名为sparkindex的索引,运行(7。b)将创建它,并将一些数据放入其中,以便该命令可以成功运行。运行带有--match-all选项的命令将提交一个匹配所有查询并返回一些结果,这样您就可以看到一些从 es 索引返回的文档示例。系统会提示您选择要搜索的字段,然后要求您输入要搜索的值。将返回实际结果的一些组合有:

0\. firstname接着是Nanette(感谢 Nanette)

3\. employer接着是Anocha(感谢 Anocha)

试着找出一些其他的。

7.进一步练习

在前面的章节中,我们简要介绍了如何使用一些关键的大数据技术。我们已经通过示例逐步了解了如何:

  1. 使用 ElasticSearch REST API 索引和查询数据。
  2. 使用 Kibana 及其开发工具和控制台与 ElasticSearch 集群进行交互。
  3. 使用 Python 配置 SparkSession,并使用 ElasticSearch Hadoop 接口将数据直接从 Spark 数据帧索引到 ElasticSearch 索引。
  4. 通过使用 Python 的 urllib 编写请求来搜索 ES 索引。

从这里开始,您可以使用我们的 vagger 开发环境来磨练您的大数据技能:熟练使用 Lucene,这是 ElasticSearch 用来编写搜索并返回与我们的查询匹配的文档的库,使用 Kibana 来构建仪表板以可视化和探索您最喜欢的数据集,构建 ETL 管道以将转换的数据集写入 ElasticSearch 索引,等等。

具有复杂和嵌套数据类型的大数据转换

原文:https://towardsdatascience.com/big-data-transformations-with-complex-and-nested-data-types-c1b9c45ca792?source=collection_archive---------22-----------------------

Apache Spark 编程技巧和诀窍

劳拉·奥克尔在 Unsplash 上的照片

介绍

Apache Spark 是一个分布式计算大数据分析框架,旨在跨机器集群转换、设计和处理海量数据(想想万亿字节和千兆字节)。经常使用不同的数据集,您会遇到复杂的数据类型和格式,需要昂贵的计算和转换(想想物联网设备)。极其复杂和专业,在扩展大数据工程工作方面, Apache Spark 是其工艺的大师。在这篇博客中,我将使用原生的 Scala API 向你展示 1。)如何用嵌套 schema ( arraystruct )对半结构化 JSON 数据进行扁平化和规范化,2。)如何透视数据,以及 3 .)如何将数据作为拼花模式保存到存储中,以便进行下游分析。注意,同样的练习可以使用 Python API 和 Spark SQL 来完成。

步骤 1:规范化半结构化嵌套模式

1a。)让我们来看看我们漂亮的多行 JSON schema(来自我最喜欢的视频游戏的虚拟数据)。

1b。)接下来,为了提高性能,我将把我们的模式映射并构造为新的StructType(),以避免在读取 JSON 数据时触发不必要的 Spark 作业。

1c。)现在,我们可以打印我们的模式并检查数据,您可以看到,由于涉及到的数据类型,这是一件令人欣喜的事情。该数据集中总共有 12 行 5 列,但是我们在本机模式中看到 2 行 2 列。

1d。)是时候使用内置的Sparkdata frameAPI 函数(包括explode)将array数据类型中的元素转换为单独的行和点*,这些函数解包struct数据类型中的子字段。由于子类超级列具有一对一的元素对映射,slick arrays_zip函数也将与点选择一起使用,以避免在分解期间创建额外的行组合。

1e。)是时候检查转换后的数据集及其模式了。正如所料,它返回 12 行 5 列。

第 2 步:转换和重塑数据

2a。)下一个练习将采用我们的展平数据集并应用pivot函数,这将触发大范围转换,将特定列的不同值转置到各个列中。可以在聚合或不聚合的情况下执行透视。对于使用许多列也称为功能作为学习算法输入的数据科学用例,无聚合通常是必需的模式。一个有效的性能提示是在pivot函数输入中指定您的唯一值,这样 Spark 就不必触发额外的作业。

第三步:写入拼花格式

3a。)最后一个练习将简单地把我们的数据写到存储器中。将使用 Parquet 格式,因为它是一种可拆分的文件格式,经过高度压缩以提高空间效率,并针对列存储进行了优化,因此非常适合下游大数据分析。

结论

这些练习只是触及了 Apache Spark 对于大数据工程和高级分析用例的皮毛。感谢你阅读这篇博客。

大数据;纽约优步天气预报

原文:https://towardsdatascience.com/big-data-uber-forecast-in-new-york-5a25ffb9914f?source=collection_archive---------48-----------------------

维克多·拉兹洛拍摄于的照片

将 450 万条记录转化为见解和预测

在这个故事中,我描述了我作为一名经济学学生在特拉维夫大学学习大数据课程时开发的预测方法。

我收到了纽约市 450 万份优步骑行订单的数据集,它将司机和那些对骑行感兴趣的人联系起来。
该数据集包含 2014 年 4 月至 7 月的观测数据,包括订购地点和时间。
根据数据集,我被要求每隔 15 分钟预测未来一个月(2014 年 9 月)的订单数量。

首先,我将描述对数据的研究,以发现模式和联系,然后基于研究见解,将交叉检查额外的数据。
最后,将阐述预测游乐设施未来趋势的模型。

数据研究

首先,我已经根据项目规范清理了数据;缩小了从纽约证券交易所到午夜的 1 公里半径范围,确保没有丢失的数据单元。
然后,订单被分成 15 分钟的时间段窗口。
我创建了下面的图,它描述了在 15 分钟的时间段内,给定数量的订单出现的次数。
(即已经有 20 个订单的次数【x 轴】,在 15 分钟时段窗口中是在【y 轴】)。

乘坐次数分布

正如你所看到的,这个分布峰值接近它的平均值,然后急剧下降。
分布尾部主要由异常时间段窗口组成,在这些时间段内,乘车需求激增。
这种模式在其他月份也保持一致。
这种订单数量惊人的现象引发了我的好奇心,因此我整理了下表,其中描述了主要事件和天气状况。
该表按乘坐次数降序排列,旨在发现重大事件和多雨天气与接送次数之间是否存在关联。
如您所见,在 52%的 40 次以上游乐设施时段窗口和 48%的 30-40 次游乐设施时段窗口中,确实出现了重大活动的寒冷天气,这可能描述了游乐设施需求的飙升。
虽然这可以解释时隙窗口中的一些异常,但这些原因(如未来天气或重大事件)是无法预测的,因此在设计模型时要特别注意处理它们。

继续进行数据研究,创建“热图”,描述一周中每一天每一个小时的订单数量。

每天每小时的乘车次数热图

正如你所看到的,工作日下午 17 点至 19 点的需求有所上升(可能是因为下班通勤),工作日深夜时段的需求有所下降。
这种模式在其他月份也保持一致。

此外,不同月份的订单总量趋势显示优步在 4-7 月份增长,在 5 月份有所倾斜。

2014 年 4 月至 7 月优步订单数量的增长

此外,我还研究了需求领域及其模式。
下面的热图用暖色描述了一周不同日子里订单数量最高的区域。

每天的动态热图;暖色是订单数量较多的区域

正如你所看到的,需求在一周的不同日子里会发生变化,尤其是工作日和周末之间。

然而,“温暖”区域在不同月份之间保持不变,与每日热图相比,表现出较低的熵。

不同月份的动态热图;暖色是订单数量较多的区域

这些温暖的区域与曼哈顿提到的吸引点和兴趣点相关联。
另一个有趣的观察是,温暖的地区不靠近火车站,火车站在那些时间经常经过。有理由相信,在某些情况下,火车是优步乘车的替代品。

最后,建立了一个相关矩阵。

建立模型

开发的模型是一个聚类模型。
每一个订单都被分配到一个聚类,而聚类中心就在最温暖地区的中心。
这样的划分是为了独立地了解每个区域的模式,因为不同的区域在不同的日子和时间变暖——然而星团的中心又被称为“质心”几乎是静止的。
为了选择正确的聚类数量,我在聚类平方和图中创建了一个总数。
该图用于确定合理的集群数量(用 K 表示),使用“肘法”启发式;收益递减不再值得额外成本的分界点(当解释的数据量微不足道时,停止添加新的聚类或提高 K)。

聚类平方和图内合计

所选择的群集数量(可在代码中配置)是 K=8,其质心与上述较温暖的区域相匹配。

为了构建模型,在将订单划分为聚类之后,使用由 Hadley Wickham 为聚类开发的 dplyr 库构建了一个指定的表。
主表中的每一行都匹配一个聚类的数据,并且对其应用了线性回归。
以这种方式,模型被训练以独立地学习每个聚类的模式,并且回归将基于每个聚类的独特特征为每个聚类产生不同的系数。
未来 15 分钟时隙窗口的期望预测是所有聚类预测的总和。

线性回归模型为:

pick_num ~ minute + hour + day_in_week + hour*day_in_week

增加了一周中的小时和天之间的相互作用,以掌握它们的不同组合的效果。

此外,如上所述,每个月都有异常时段窗口,订单量非常大;
为了解决这一问题,并消除天气或不可预测事件的负面影响,为每个集群引入了订单量阈值,阈值=9,可通过代码进行配置。
以基于集群的方式削减阈值有利于禁用一个集群中的异常,而不会对另一个集群产生副作用,并且与设置全局阈值相比更加灵活。

摘要和其他模型

总而言之,我已经从数据研究和识别不同日期和时间的模式开始,并继续研究不同月份和温暖地区的模式。

我发现在不同的月份之间,温暖的地区几乎保持不变。
然而,在一周的不同日子里,尤其是当比较工作日和周末时,温暖的区域发生了变化。
然后,研究了时间段窗口中的异常情况,其中订单数量激增。
寒冷天气、重大事件和那些异常现象之间的关联已经得到证实。
有了这些见解,我开发了一个与温暖地区相匹配的聚类模型,并独立地学习了每个聚类的模式。
除了开发的模型之外,简单的线性模型(尽管很明显它们不能掌握全局)以及随机森林模型也已经过测试(以及与聚类模型的组合)——然而这些模型都没有超过上述模型所达到的 R 。
最后,提出了一种模型,该模型将城市划分为感兴趣的区域,并为每个区域学习唯一的系数,从而最小化异常的不良影响。

喜欢这篇文章吗?随意长按👏下面的按钮😀

大数据将在 5 年内消亡

原文:https://towardsdatascience.com/big-data-will-be-dead-in-5-years-ef4344269aef?source=collection_archive---------18-----------------------

意见

一切都将是大数据,因此不需要特殊的名称

马库斯·斯皮斯克在 Unsplash 上的照片

大数据是一个很棒的营销术语,但实际上,它仅此而已。这是一个用来激励企业高管的术语,让他们觉得自己像谷歌或亚马逊。现实是,大数据并不代表任何东西,它的意义只会越来越小。

随着公司越来越熟悉数据处理,服务提供商越来越抽象出更多的复杂性,大数据将成为数据。大数据工程师将成为数据工程师,任何称职的数据工程师都将处理我们现在所说的“大数据处理”。

不过不用担心,这并不意味着您的大数据知识过时了,只是它的名称可能没有以前那么重要了。

大数据真的死了吗?

号码

它根本没有死。事实上,它只会变得更加突出。据预测,到 2025 年,全球“数据球”将从今天的 50ZB 增长到 175 zb(T7)。

所有这些数据都需要以某种方式进行处理,那么大数据怎么会消亡呢?

答案是“大数据处理”本身不会有任何发展,它只会成为一种规范。因此,我们将不再称之为大数据,而需要专业的“大数据工程师”。大数据应用背后的复杂性和可扩展性将被亚马逊这样的云提供商抽象化,这样所有的数据工程实际上都是“大数据工程”。

这也不是一个新现象,它开始于 Hadoop 的早期。当脸书开始使用 Hadoop 来管理其庞大的数据集时,他们发现编写 MapReduce 任务耗时、费力且昂贵。这是因为当时 MapReduce 的工作需要编程,所以他们建立了 Hive。

Hive 是 Hadoop 上的 SQL。脸书从编写 MapReduce 作业中抽象出复杂性,它们变成了简单的 SQL 查询。这意味着任何懂 SQL 的人都有能力构建大数据应用程序,而不仅仅是大数据工程师。

快进到今天,你有按需扩展数据的解决方案,如亚马逊红移或谷歌大表。大多数现代服务迎合小数据,但可以很容易地扩展到大数据。

[## 如何构建完美的数据仓库

关键仓储技术变得简单

lewisdgavin.medium.com](https://lewisdgavin.medium.com/how-to-architect-the-perfect-data-warehouse-b3af2e01342e)

你可以使用亚马逊 S3 作为“小数据”应用程序的数据存储,但是如果你的数据量增长,你仍然可以使用 S3 作为数据湖,因为它实际上是一个无限的数据存储。现在,甚至有像雅典娜这样的数据处理工具位于 S3 之上,使得它更加引人注目。

什么将取代大数据?

我们没有人真正知道下一个大的营销术语会是什么。数据科学已经走上了类似的道路。目前,它是数据世界的典型代表,但同样,随着其复杂性被抽象化,对专业数据科学家的需求将会减少,其影响力也会减弱。

重要的是,不是大数据处理正在消亡,而是“大数据”这个术语本身正在消亡。在所有的抽象背后,大数据处理技术仍将存在。我们仍将使用水平扩展的集群,我们仍将减少数据接收延迟并处理数 Pb 的数据。所有这些都不会消失,这些技术只是被隐藏起来,这样每个人都可以更容易地接触到它们。

我们仍然需要擅长数据提取和处理的数据工程师。我们仍然需要能够建立预测和提供报告的数据科学家和分析师。

缺少的是工程师从头开始构建一个健壮的、可扩展的数据湖的能力,因为只需按一下按钮就可以部署。数据科学家也不需要理解太多的“本质”数学。相反,他们只需要知道需要哪些模型,需要提供哪些数据。训练和部署模型的复杂性将被抽象出来,并作为云服务提供。

我的观点是,数据领域的任何工作对未来都是一个安全的赌注。然而,你需要保持警觉,开始思考如何更快、更便宜地为企业提供服务,即使这意味着使用现成的解决方案。

随着复杂的大数据和数据科学服务的云抽象的增长,您使用这些服务并将它们结合在一起的能力将是最重要的,即使您可以自己从头开始构建它。

寻找更多伟大的数据工程内容?然后 注册我的简讯 学习现实世界的数据工程技术,并接收个人策划的内容。我还经常在时事通讯中刊登订阅者的文章,以增加你的影响力

大数据:昨天、今天和明天

原文:https://towardsdatascience.com/big-data-yesterday-today-and-tomorrow-389de1a46cd8?source=collection_archive---------53-----------------------

美国陆军照片,n.d .公共领域

什么是“大数据”——了解历史

由詹姆斯·怀恩加 — 18 分钟阅读

一次历史之旅,我们是如何走到这一步的,我们释放了哪些能力,以及我们下一步要去哪里?

Guillermo Ferla 在 Unsplash 上拍摄的照片

重新审视聚类算法

通过 Dmitry Selemir — 14 分钟读取

这个项目根本没有到最后阶段。分享当前的想法,详细检查代码,获得一些反馈,看看是否值得进一步开发。

多臂强盗实验的视觉探索

保罗·斯图布利 — 9 分钟阅读

在营销数据科学部门工作有一个不变的事实:在实验和开发之间做出选择从来都不容易。当你想推出限时优惠时,尤其如此,因为你事先对不同版本的优惠效果知之甚少。

田宽在 Unsplash 上的照片

使用 DVC 构建可维护机器学习流水线的终极指南

由德博拉·梅斯基塔 — 10 分钟阅读

当我的 ML 项目开始发展时,我通常会感到焦虑,因为:一切都开始变得混乱,我知道它变得一团糟,但我不知道如何改善它。我喜欢使用开源工具和框架,因为随着项目的发展,贡献者的知识会“嵌入”其中。

使用 twitter-nlp-toolkit 进行简单的 Twitter 分析

埃里克·希布利(Eric Schibli)—4 分钟阅读

Twitter 是商业分析和学术或教学自然语言处理最丰富的数据源之一;Kaggle 上的许多顶级数据集都是在 Twitter 上收集的,最受欢迎的文本嵌入之一是使用 Twitter 训练的,几乎每个公司都在积极监控 Twitter。

我们的每日精选将于周一回归!如果你想在周五收到我们的 每周文摘 ,很简单!跟随 我们的出版物 ,然后进入你的设置,打开“接收信件”您可以在此 了解有关如何充分利用数据科学 的更多信息。

大型科技公司正向我们走来。但是我们可以阻止它。

原文:https://towardsdatascience.com/big-tech-is-coming-for-us-but-we-can-stop-it-a61ba00101e9?source=collection_archive---------25-----------------------

监控数据化世界中的隐私。

来源:可信评论

早上闹钟响的时候,你做的第一件事是什么?就在你睡觉前?你周围有多少人正在使用他们的手机或电脑?

过去的十年改变了我们人类的日常生活。几乎不可能用几种不同的方式来衡量我们使用了多少技术。订购比萨饼、跟踪您的心跳、与朋友分享片刻、关注新闻——我们在任何事情上都使用技术。它的可负担性和可访问性使它更加有趣和成功,因为它已经嵌入到我们所做的一切事情中,无论是专业的还是个人的。然而,所有这些进步和便利都是有代价的。在过去的十年中,像“数字 DNA”和“数据阴影”这样的术语已经成为现实,并突显了我们不断从我们使用的各种技术服务中收集的大量信息。对消费者来说,技术带来了一种奇妙的满足感。然而,在后台,技术开始要求通过监视、控制和行为影响来扩大关于我们在线活动的数据集。随着这些系统逐渐走向全知,是时候我们考虑承认问题,设置限制并大声说出来了。

那么,这项技术是如何工作的呢?

算法。算法是告诉计算机如何执行任务的一段代码——计算机在解决问题的操作中必须遵循的一组规则,以产生特定的结果。对于普通大众来说,算法本质上是一个塑造我们周围世界的黑匣子。然而,我们不知道它们是什么,也不知道我们如何受到它们的影响。我们当前的数字环境要求我们在过去的偏见影响我们的未来之前打开这些算法黑匣子。是时候让我们的声音和需求被听到了。

弗兰克·帕斯奎尔推广了“算法自我”的概念,“T1”是在网上战略自我推销中得到很好实践的自我。虽然算法仍然不透明,但社会规范正在迅速变化。他提到,“一种网络眩晕由此产生,因为我们被迫推销我们的算法自我,但却对这样做的最佳方式感到困惑。”这提出了一个重要的问题——谁在为我们推动这个决策过程?谁负责激发我们尝试自我推销的不同方式?Pasquale 探讨了监控在公众日常使用的技术中的存在,以及从所有数据收集中提取的指标如何允许“大规模行为调节”

如果我们跳入热门电视节目《黑镜》的反乌托邦宇宙,剧集《俯冲》就是一个被监控的世界修改我们行为的完美例子,它根据我们过去的所作所为“建议”我们该做什么和如何表现。在这个世界上,在由社会等级奖励的善意和善良的表面下,个人被剥夺了情感和身体上的个人主义和自由意志。被困住和控制,他们在努力自我优化和自我提升时成为指令的追随者。

有点担心吧?事实上,这是不太遥远的未来。大约 13 小时后,中国将最早于 2020 年推出反乌托邦记分卡系统。虽然中国已经实行了大量的审查制度,但这一制度将赋予当权者对其公民几乎完全的控制权。公民的行为将在各个方面进行排名,任何不符合“规则”的行为都将受到惩罚更高的分数意味着更高的生活质量,这完全取决于有效地成为中国政府的奴隶,失去一个人作为一个人的所有权利。

现在,你可能会觉得这很惊人,但是我们在美国也有类似的系统。

在中国,公民现在和将来都是政府审查和行为修正的受害者。虽然美国是建立在自由的价值观上的,但我们这里有私人实体,主要是在硅谷,他们也在类似的轨道上进行他们自己版本的监控和修改。Twitter 最近禁止了政治广告,这凸显了由消费者数据收集驱动的在线广告的力量。这是关于你和我的数据。目标是保护普通人免受虚假政治广告、被篡改的视频和误导信息的传播。Twitter 的首席执行官杰克·多西提到,政治信息的传播“应该是挣来的,而不是买来的”在过去的选举中,社交媒体上的这类广告被认为不公正地影响了选民,导致一些人可能认为不具代表性的选举结果。然而,我们认为这一禁令是对用户可以接触的内容的控制行为,还是一种保护形式?

技术变得既具有创新性又具有破坏性,并正在慢慢接管政府过去的工作。我们必须将权力交还给人民。算法推动技术流程的成功。这些流程不透明,存在歧视和偏见影响我们决策的风险。但是,我们应该责怪算法决定了我们在做什么,还是应该责怪构建这些算法的人?有关数据权利的问题始于脸书-剑桥分析公司数据丑闻的公开。在一次关于脸书在数字世界中的角色的对话中,Kickstarter 的前数据主管弗雷德·贝纳森(Fred Benenson)描述了一种被称为“数学清洗”的趋势:我们倾向于崇拜像脸书这样的程序,认为它们完全是客观的,因为它们的核心是数学。他说,“算法和数据驱动的产品将永远反映建造它们的人类的设计选择。”我们没有被机器控制;我们正被极少数强大的人所控制。这就是我们如何变得相同并失去我们的个人主义。我们能阻止它吗?

技术革命不仅仅发生在网上,也发生在个人层面和整个社会结构中。随着我们继续依赖技术,我们正在放弃越来越多的关于我们自己的信息作为交换。公众越早集体理解技术的根深蒂固的影响,我们就能越早让剥削我们的跨国科技公司承担责任。我们从导致其余部分的问题开始——透明度。作为用户,权力在我们手里。

BigQuery +云函数:如何在新的谷歌分析表可用时立即运行查询

原文:https://towardsdatascience.com/bigquery-cloud-functions-how-to-run-your-queries-as-soon-as-a-new-google-analytics-table-is-17fbb62f8aaa?source=collection_archive---------1-----------------------

如何确保您的表格、仪表板和数据传输始终保持最新的分步指南

如果你的谷歌分析视图链接到 BigQuery,你可能正在享受它带来的好处。您的数据中没有抽样,您可以引入第三方数据,您对您的数据有更多的控制权等等。

但是,有一件事困扰着我。也许这也困扰着你。每天从 Google Analytics 导出到 BigQuery 表(ga_sessions_YYYYMMDD)的确切时间可能有些不可预测。这使得在这个数据集上运行计划查询而不冒一点风险是不可能的。

  • 您可能过早设置了计划查询。如果由于某种原因,Google Analytics 的导出被延迟,您可能会错过一天的数据。每次发生这种情况时,您都必须手动更正。或者你可以考虑使用日内表。但这可能也不理想,因为谷歌声明:“在每日导入完成之前,当天的数据不是最终数据。你可能会注意到日内和每日数据之间的差异”(见文档这里)。
  • 您可能会将计划查询设置得太晚。在这种情况下,如果出口延迟,你可能是安全的。但是,您的仪表板的基础表和/或向其他数据系统的可能转移可能不像决策者需要的那样是最新的。

当然,在这个不确定的日冕时代,你可以称之为第一世界的问题。但因为这是一个我可以帮助解决的问题,我将带您一步步地了解如何在 Google Analytics 新的每日导出准备就绪时运行您的预定查询。结果是一个更加可靠的设置,其中您的表和仪表板总是尽可能地保持最新。

我们将采取的步骤是:

  1. 在云日志中创建一个过滤器,隔离确认新的 Google Analytics 表准备就绪的每日日志。
  2. 设置一个收集这些每日日志的云发布/订阅主题。
  3. 部署一个云函数,一旦用新日志更新了发布/订阅主题,它就在 BigQuery 中运行您的计划查询。

第一步。云日志记录

  • 好的。首先要做的是打开云日志。
  • 单击搜索字段右侧的小下拉箭头,选择“转换为高级过滤器”。至少,在我写这篇文章的时候,它还在那里😉。
  • 您可以复制/粘贴下面的代码来创建一个过滤器,该过滤器将隔离确认新的 Google Analytics 表(ga_sessions_YYYYMMDD)已创建的日志。不要忘记在前两行填写您自己的数据集 ID 和项目 ID。
protoPayload.serviceData.jobCompletedEvent.job.jobConfiguration.load.destinationTable.datasetId="[REPLACE_WITH_YOUR_DATASET_ID]"protoPayload.serviceData.jobCompletedEvent.job.jobConfiguration.load.destinationTable.projectId="REPLACE_WITH_YOUR_PROJECT_ID"protoPayload.authenticationInfo.principalEmail="[analytics-processing-dev@system.gserviceaccount.com](mailto:analytics-processing-dev@system.gserviceaccount.com)"protoPayload.methodName="jobservice.jobcompleted"protoPayload.serviceData.jobCompletedEvent.job.jobConfiguration.load.destinationTable.tableId:"ga_sessions"NOT protoPayload.serviceData.jobCompletedEvent.job.jobConfiguration.load.destinationTable.tableId:"ga_sessions_intraday"
  • 如果您将时间范围调整为过去 7 天,您现在应该每天都会看到一条消息。在下面的截图中,您可以看到导出的确切时间的不可预测性。在这个例子中,有时候桌子在下午 2 点之前就准备好了,有时候在下午 3 点之后。如果你的屏幕是这样的,你就准备好进入下一步了!

谷歌日志中的截图

第二步。云发布/订阅

Pub/Sub 代表发布-订阅,可以看作是系统之间的消息传递系统。在这种情况下,我们希望创建一个新的发布/订阅主题,收集我们在上一步中隔离的日志。这样,每次有新的 Google Analyicts 表可用时,都会收集一条消息。

  • 点击上面截图中的“创建汇”。
  • 输入接收器名称时,您可以随心所欲地发挥创造力。
  • 选择“发布/订阅”作为接收服务。
  • 选择创建一个新的云发布/订阅主题,并为其命名,以便在下一步中记住。
  • 点击“创建接收器”,您就可以开始下一步了。

Google 日志中的屏幕截图:创建发布/订阅接收器和主题

第三步。云函数

在最后一步中,我们将创建一个云函数(用 Python 编写),它在每次发布/订阅主题被触发时运行。然后,该函数向 BigQuery DataTransfer API 发送一个请求,在一个预定的(按需)SQL 查询上开始手动传输运行。

  • 开启云功能
  • 选择创建新功能。
  • 选择“云发布/订阅”作为触发器,并选择您在上一步中创建的发布/订阅主题。
  • 选择“Python 3.7”(或者更高版本,如果你将来读到这篇文章的话🚀)作为运行时。

如何设置谷歌云功能的屏幕截图

  • 复制/粘贴下面的代码,并将其放在“Main.py”文件中。

  • 用要运行的计划查询的详细信息替换项目 ID 和转移 ID。

  • 您可以在您的计划查询的配置选项卡中找到这些 ID。资源名称显示了一个 URL,您可以在其中找到这两个 ID:“projects/[THIS _ IS _ YOUR _ PROJECT _ ID)/locations/us/TRANSFER configs/[THIS IS YOUR TRANSFER _ ID]”。

  • 在这种情况下,我假设您已经创建了想要运行的计划查询。如果您还没有,现在是时候在 BigQuery 中用创建您的预定查询了。最好将查询设置为“按需”运行,否则它可能会运行得太频繁。

  • 将下面的一小段代码添加到“Requirements.txt”中,这样它就有了运行 Python 代码所需的所有包。

google-cloud-bigquery-datatransfer==1
  • 将“runQuery”设置为要执行的函数。
  • 点击部署!

现在:享受自动化👍

如果您已经正确地设置了所有内容,那么一旦新的每日表被导出到 BigQuery,您的预定查询就会立即开始运行!这意味着你可以高枕无忧,享受你的谷歌分析数据总是新鲜的。

如果你有任何建议、意见或问题,请不要犹豫,在下面的评论中问我。

BigQuery:使用 SQL 创建嵌套数据

原文:https://towardsdatascience.com/bigquery-creating-nested-data-with-sql-727b761f1755?source=collection_archive---------10-----------------------

正如我在我的另一篇文章 BigQuery:嵌套数据上的 SQL中所阐述的,在嵌套数据上使用 SQL 是非常高效的——只要任务在后端是可并行化的。但是,如果您的数据来自平面表,例如 CSV,则必须首先转换数据。

作者照片

嵌套单个值

通常——在平面表场景中——您只需要使用JOIN来组合两个表:

上面查询的结果表——试试吧!

但是当然,我们永远不会保存这样的表,因为有些字段只是一遍又一遍地重复,占用存储空间,这反过来会产生可避免的成本。

但是如果我们使用表authors将书籍放入数组中,我们就不会重复作者字段。在 BigQuery 中,我们可以使用[ARRAY_AGG()](https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#array_agg)轻松做到这一点,这是一个聚合函数,可以与GROUP BY结合使用,将值放入数组中:

嵌套在“works”数组中的标题——自己试试吧!

如果我们保存这个结果表,我们将通过有效地存储信息来避免成本,并且我们可以去掉一些 id,因为我们不再需要加入。

它还降低了查询的复杂性,因为信息位于同一个表中。您不必想象表 A 和表 B 以及它们加入后的样子,然后才考虑如何选择和分组,您可以直接选择和分组。

看看这里的最后一个SELECT语句——想象我们将结果表存储在某个地方,而不是放入WITH

使用 UNNEST()编写子查询(第 24 行)在 BigQuery:嵌套数据上的 SQL中有介绍

上面查询的结果表——试试看!

在这里,我们可以轻松地对数组应用各种聚合技术,或者简单地将数组与其父数组交叉连接以获得一个平面表。为了进一步分析,我们预先连接了表,但保持了存储效率。我们甚至引入了两个字段 qtyTitlesqtyCharacters ,它们已经告诉了我们关于数组的事情——这对数组聚合中的常见用例很有帮助。

嵌套多个值

让我们引入另一个字段,看看如何在一个数组中存储多个字段。让我们快速思考一下:我们在一个数组中一次只能存储一种元素类型——这是一个简单的列表:[1,1,2,3,5,8]。所以我们需要把多个值变成一个复数值的东西。对此的解决方案是STRUCT,它基本上是一个带有要求的键-值对列表:键必须保持不变,值不允许改变它们的数据类型:[{a:1,b:x},{a:2,b:y},{a:3,b:z}]。这也是 BigQuery 被称为“半结构化”的原因。

有几种方法可以构建结构,但是与ARRAY_AGG()结合使用最方便的是函数[STRUCT()](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#constructing_a_struct)。只需选择要嵌入到数组中的字段,并将它们放入一个结构中:

第 15–17 行显示了每个组(array_agg + group by)中被放入数组的结构

带点的列标题表示结构

为此,我们准备了一个预连接表:

我们甚至可以使用ARRAY()SELECT AS STRUCT从现有的数组创建新的复杂数组。此外,窗口函数的作用域是由数组的边界自动确定的!

上面查询的结果表

创建新数组或扩展旧数组——在这里,扩展更有意义。为此,我们只需在子查询中选择现有的列,例如ARRAY(SELECT AS STRUCT *****, UPPER(title) AS title ...

嵌套更复杂的值

虽然我们可以使用 struct 函数简单地将结构嵌套在结构中,但是如果我们想将数组嵌套在数组中,我们需要提前做一些计划。

让我们介绍第三个表,它包含与一本书相关的标题。该表只有三个条目,只是为了让它暂时易于管理。

我们必须首先创建最内层的数组,以便以后可以将它们嵌套在其他数组中:

第 22 行的“忽略空值”有助于避免空数组错误

结果表—尝试为其他标题添加更多信息!

将最后一个SELECT语句作为 round1 放入WITH中,我们可以从SELECT * FROM authors LEFT JOIN round1 USING(id)开始第 2 轮,并得到我们的作者…

为 array_agg() round 2 准备好的表!

从这里,我们可以使用相同的方法在更高的范围内再次聚合:

我们需要为我们想要创建的每个深度级别的阵列进行一轮聚合:

阵列中的阵列——多么美妙的世界

为了在分析中达到这些值,相同的规则始终适用:

  • 为了将数组聚合为一个值,使用子查询
  • 对数组中的值进行分组使用交叉/左连接

交叉连接消除空行,而左连接保留空行。

relatedTitles 从一个数组中抓取另一个数组中的信息,而 relatedBooks 使用子查询交叉连接将两个数组中的信息合并为一个。

我希望这能让您对使用 SQL 在 BigQuery 中构造表的可能性有一点了解。我应该注意到,创建性能良好的表还有更多的方面。一定要看看分区和聚类表的主题!使用 DDL 可以非常方便地做到这一点。如果你想用 SQL 语句插入数据,看看插入结合WITH语句准备数据。

如果你有任何问题或意见,请告诉我。我很想知道您是如何在 BigQuery 中准备和优化表的!

Google 中的 BigQuery 数据结构:云存储入门

原文:https://towardsdatascience.com/bigquery-data-structure-in-google-how-to-get-started-with-cloud-storage-b6146fcad1d1?source=collection_archive---------34-----------------------

来源:沉积照片

了解如何开始使用云存储:创建数据集和表,设置与 Google BigQuery 之间的数据导入和导出

Google BigQuery 是一项云存储服务,允许您在一个系统中收集所有数据,并使用 SQL 查询轻松分析这些数据。为了便于处理数据,应该正确地组织数据。在本文中,我们将解释如何创建上传到 Google BigQuery 的表和数据集。

数据集:什么是数据集以及如何创建数据集

要使用 Google BigQuery,需要在 Google 云平台(GCP) 中创建一个项目。注册后,您将在免费试用期内获得所有云平台产品,并在接下来的 12 个月内获得 300 美元用于购买这些产品。

在 Google 云平台中创建项目后,需要向 Google BigQuery 添加至少一个数据集。

数据集是用于组织和控制数据访问的顶级容器。简单地说,它是一种文件夹,你的信息以表格和视图的形式存储在其中。

在 GCP 打开您的项目,转到 BigQuery 选项卡,并点击创建数据集:

在打开的窗口中,指定数据集的名称和表的保存期限。如果希望自动删除包含数据的表,请指定具体的删除时间。或者保留默认的永久选项,以便只能手动删除表。

加工地点字段是可选的。默认情况下,它设置为 US multiregion。您可以在帮助部分找到更多关于存储数据区域的信息。

如何添加表以将数据加载到 Google BigQuery 中

创建数据集后,您需要添加一个将收集数据的表。表格是一组行。每一行都由列组成,这些列也称为字段。根据数据源的不同,有几种方法可以在 BigQuery 中创建表:

  • 手动创建一个空表,并为其设置一个数据模式
  • 使用以前计算的 SQL 查询的结果创建一个表
  • 从您的计算机上传文件(CSV、AVRO、JSON、Parquet、ORC 或 Google Sheets 格式)
  • 你可以创建一个引用外部数据源的表,而不是下载或流式传输数据: Cloud Bigtable 、云存储或 Google Drive 。

在本文中,我们将仔细研究第一种方法:手动创建一个表。

第一步。选择要添加表格的数据集,然后单击创建表格:

第二步。在源字段中选择空表,在表类型字段中选择目标对象原生格式的表。想出一个表名。

重要信息:数据集、表格和字段的名称必须是拉丁字符,并且只包含字母、数字和下划线。

第三步。指定表模式。该模式由四个部分组成:两个是强制性的(列名和数据类型),两个是可选的(列模式和描述)。正确选择的类型和字段模式将有助于处理数据。

BigQuery 中的模式示例:

列名
在列名中,您需要指定每列负责的参数:日期、用户标识、产品等。标题只能包含拉丁字母、数字和下划线(最多 128 个字符)。不允许相同的字段名称,即使它们的大小写不同。
数据类型
在 BigQuery 中创建表时,可以使用以下字段类型:

模式
BigQuery 支持以下表列模式:

注意:不需要填写模式字段。如果没有指定模式,默认列可为空。

列描述
如果您愿意,您可以为表格中的每一列添加一个简短的描述(不超过 1024 个字符),以便解释特定参数的含义。

在 BigQuery 中创建空表时,需要手动设置模式。这可以通过两种方式来实现:
1。点击添加字段按钮,填写每一列的名称、类型和模式。

2.使用编辑为文本开关,以 JSON 数组的形式输入表格模式。

此外,Google BigQuery 在从 CSV 和 JSON 文件加载数据时可以使用自动模式检测。

该选项的工作原理如下:BigQuery 从您指定的源中选择一个随机文件,扫描其中多达 100 行的数据,并将结果用作代表性样本。然后,它检查上传文件中的每个字段,并尝试根据示例中的值为其分配数据类型。

加载 Google 文件时,BigQuery 可以更改列名,使其与自己的 SQL 语法兼容。因此,我们建议您上传带有英文字段名的表格;例如,如果名称是俄语,系统会自动对其进行重命名。例如:

如果在加载数据时输入的列名不正确,或者您希望更改现有表中列的名称和类型,您可以手动执行此操作。我们会告诉你怎么做。

如何对表模式进行更改

将数据加载到 Google BigQuery 后,表的布局可能会与原来略有不同。例如,字段名可能因为 BigQuery 中不支持的字符而更改,或者字段类型可能是整数而不是字符串。在这种情况下,您可以手动调整模式。

如何更改列名

使用 SQL 查询,选择表中的所有列,并为要重命名的列指定一个新名称。在这种情况下,您可以覆盖现有的表或创建一个新表。请求示例:

#legacySQL
**Select**
date,
order_id,
order___________ **as** order_type, -- new field name
product_id
**from** [project_name:dataset_name.owoxbi_sessions_20190314]#standardSQL
**Select**
* **EXCEPT** (orotp, ddat),
orotp **as** order_id,
ddat **as** date
**from** `project_name.dataset_name.owoxbi_sessions_20190314`

如何更改模式中的数据类型

使用 SQL 查询,从一个表中选择所有数据,然后将相应的列转换为不同的数据类型。您可以使用查询结果来覆盖现有的表或者创建一个新的表。请求示例:

#standardSQL
**Select**
**CAST** (order_id **as** **STRING**) **as** order_id,
**CAST** (date **as** **TIMESTAMP**) **as** date
**from** `project_name.dataset_name.owoxbi_sessions_20190314`

如何更改列模式

如帮助文档所述,您可以将列模式从必需更改为可空。第二个选项是将数据导出到云存储,并从那里以正确的模式将数据返回给 BigQuery。

如何从数据架构中删除列

使用 SELECT * EXCEPT 查询排除一列(或多列),然后将查询结果写入旧表或创建一个新表。请求示例:

#standardSQL
**Select**
* **EXCEPT** (order_id)
**from** `project_name.dataset_name.owoxbi_sessions_20190314`

此外,还有第二种方法来更改模式,这种方法适用于上述所有任务:导出数据并将其加载到新表中。要重命名列,可以将数据从 BigQuery 上传到云存储,然后将其从云存储导出到新表中的 BigQuery,或者使用高级参数覆盖旧表中的数据:

你可以在谷歌云平台帮助文档中了解改变表格结构的其他方法。

从/向 Google BigQuery 导出和导入数据

您可以通过界面或 OWOX BI 的特殊插件从 BigQuery 下载数据或向 big query 上传数据,而无需开发人员的帮助。让我们详细考虑每种方法。

通过 Google BigQuery 接口导入数据

要将必要的信息上传到存储,例如,关于用户和离线订单的数据,请打开数据集,单击创建表,然后选择数据源:云存储、您的计算机、Google Drive 或云 Bigtable。指定文件的路径、格式以及将加载数据的表的名称:

单击“创建表”后,数据集中会出现一个表。

通过 Google BigQuery 接口导出数据

还可以从 BigQuery 上传处理过的数据——例如,通过系统界面创建报告。为此,请打开包含数据的所需表格,然后单击导出按钮:

该系统将提供两种选择:在谷歌数据工作室查看数据或上传到谷歌云存储。如果您选择第一个选项,您将立即转到 Data Studio,在那里您可以保存报告。

选择导出到 Google 云存储会打开一个新窗口。在其中,您需要指定数据的保存位置和格式。

使用 OWOX BI 的插件导出和导入数据

免费的 OWOX BI BigQuery Reports 插件允许你快速方便地将数据从 Google BigQuery 直接传输到 Google Sheets,反之亦然。因此,您不需要准备 CSV 文件或使用付费的第三方服务。

例如,假设您想要将离线订单数据上传到 BigQuery 来构建一个 ROPO 报告。为此,您需要:

  1. 在浏览器中安装 BigQuery Reports 插件。
  2. 在 Google Sheets 中打开您的数据文件,在标签 Add-ons 中,选择 OWOX BI BigQuery Reports →将数据上传到 BigQuery。
  3. 在打开的窗口中,在 BigQuery 中选择项目和数据集,并为表输入所需的名称。此外,选择要加载其值的字段。默认情况下,所有字段的类型都是 STRING,但是我们建议根据上下文选择数据类型(例如,对于带有数字标识符的字段,选择 INTEGER 对于价格,浮动):

  1. 点击开始上传按钮,你的数据将被加载到谷歌大查询

您还可以使用这个插件将数据从 BigQuery 导出到 Google Sheets——例如,可视化数据或与无权访问 BigQuery 的同事共享数据。为此:

  1. 打开谷歌工作表。在插件选项卡中,选择 OWOX BI BigQuery 报表→添加新报表:

  1. 然后在 Google BigQuery 中输入您的项目,并选择 Add new query。
  2. 在新窗口中,插入 SQL 查询。这可能是一个将数据从表上传到 BigQuery 的查询,也可能是一个提取并计算必要数据的查询。
  3. 通过单击“保存并运行”按钮,重命名查询,使其易于查找和启动。

要定期将数据从 BigQuery 上传到 Google Sheets,您可以启用计划的数据更新:

  1. 插件选项卡中,选择OWOX BI big query ReportsSchedule report:

  1. 在打开的窗口中,设置报告更新的时间和频率,并点击保存:

为什么要在 Google BigQuery 中收集数据?

如果您还没有意识到 Google BigQuery 云存储的好处,我们建议您尝试一下。在 OWOX BI 的帮助下,您可以将来自您的网站、广告源和内部 CRM 系统的数据整合到 BigQuery 中,以便:

  • 建立端到端分析并找出您营销的实际回报,考虑线下订单、退货和购买过程中的所有用户步骤;
  • 创建带有任何参数和指标的完整未采样数据的报告;
  • 使用群组分析评估客户获取渠道;
  • 找出你的在线广告如何影响线下销售;
  • 降低广告费用的份额,延长客户的生命周期,从整体上增加你的客户群的 LTV;
  • 根据顾客的活动对其进行细分,并与他们进行个性化交流。

BigQuery、PII 和云数据丢失防护(DLP):通过数据目录将其提升到新的水平

原文:https://towardsdatascience.com/bigquery-pii-and-cloud-data-loss-prevention-dlp-take-it-to-the-next-level-with-data-catalog-c47c31bcf677?source=collection_archive---------20-----------------------

如何通过使用云数据丢失防护检查所有 BigQuery 数据来创建数据目录标记。

背景由 Kelli Tungay 上 Unsplash

你知道你的组织掌握着什么样的敏感数据吗?您是否跟踪应用于所有表和列的每个更改?你有信心回答审计员可能提出的关于数据法规的问题吗?

背景由 Sandra Grünewald 在 Unsplash

让一个审计员来敲你的门并不是最可怕的事情,数据泄露才是最可怕的!从罚款到客户流失和法律后果,后果可能是残酷而持久的。

对您的敏感数据进行分类和管理是着手处理这一问题的好方法,但用手动方式来做不是办法。

有一点值得思考,谁想检查数千、数百万的数据资产,然后给每一个都贴上标签,说它们是敏感的还是不敏感的?如果表有令人困惑的列名怎么办?我不会开始讨论这有多容易出错,但你会明白…

我们需要以某种方式自动完成这项工作。

在本文中,我们将看到一个全自动的解决方案,通过使用 DLP 和数据目录来发现所有大型查询资产中的敏感数据(每当我提到 DLP 时,它都会支持数据丢失预防】)。如果您不熟悉 DLP 和数据目录,您会对第一部分和第二部分感兴趣。

否则,如果您想了解 DLP 和数据目录的神奇之处,请直接跳到第三部分。

本文涵盖的主题有:

  1. 云数据防丢失概述
  2. 数据目录概述
  3. DLP 到数据目录标签概述
  4. 脚本执行演练

事不宜迟,我们走吧!

我们将提供一个带有工作示例的 GitHub 存储库。

云数据丢失防护概述

DLP 是一项托管的 Google 云服务,旨在帮助您发现、分类和保护您最敏感的数据。

Cloud DLP 拥有 120 多种内置信息类型,让您能够从几乎任何地方扫描、发现、分类和报告数据。云 DLP 具有对云存储、BigQuery 和数据存储中的敏感数据进行扫描和分类的原生支持,以及支持附加数据源、自定义工作负载和应用程序的流内容 API。

特征

来自官方文件的 DLP 特性

在本文中,我们将利用流媒体内容 API 和DLP 检查模板。

数据目录概述

数据目录是一种可管理和可扩展的元数据管理服务,使组织能够快速发现、了解和管理其所有数据。

Data Catalog 通过 Google Cloud 提供了一个更安全的中央数据目录,使组织能够对其所有数据资产有一个统一的视图。该服务自动吸收 BigQuery 和云发布/订阅的技术元数据,并允许客户通过标签、自定义 API 和 UI 以模式化格式捕获业务元数据,从而提供一种简单高效的方法来对其数据资产进行编目。

特征

正式文档中的数据目录特性

在本文中,我们将利用标签模板标签、和进行数据目录搜索。

快速查看数据目录标签结构:

从GCP-数据目录-图表中标记心智模型

我们将在后面介绍更多细节,但是请记住,由于我们关注的是大型查询资产,每个大型查询表都代表数据目录中的一个条目,我们将创建标记来对敏感数据进行分类,标记模板将代表 DLP 信息类型。

DLP 到数据目录标记概述

现在,您已经熟悉了 DLP 和数据目录,让我们继续了解体系结构概述:

从 dlp 到数据目录标签的参考架构

该脚本使用Java工作负载,用户能够在他们的本地机器、云外壳或计算引擎虚拟机上执行它。

如果您对脚本执行的快速视频演示感兴趣,请查看:

来自 dlp 到数据目录标签的演示视频

阅读大查询资源

工作负载从读取来自 Google Cloud 项目的大查询资源开始,然后我们将大查询行分成许多块。我们需要这一点,因为 DLP 内容 API 有一个使用限制,这也是奇迹发生的地方。

呼叫 DLP

对于 DLP 使用限制,我们可以将其分为两类:

  • 请求大小

首先,我们需要确保请求大小不超过使用限制,在撰写本文时,我们得到了以下值:

显示来自DlpDataCatalogTagsTutorial.java的请求大小限制的代码

  • 每分钟请求数

第二,每分钟有一个请求强制限制,所以我们添加了简单的睡眠和重试逻辑:

显示来自DlpDataCatalogTagsTutorial.java的睡眠逻辑的代码

DLP 检查模板

接下来,为了调用 DLP,我们将使用 DLP Inspect 模板,它们对于解耦配置信息非常有用。在这个用例中,我们使用它来存储我们的infoTypes:

DLP 检查来自DLP-to-data catalog-tags的模板

云数据丢失防护(DLP)使用信息类型或infoTypes来定义它扫描的内容。infoType是一种敏感数据,如姓名、电子邮件地址、电话号码、身份证号或信用卡号。

最后,我们创建检查请求:

显示来自 DlpDataCatalogTagsTutorial.java的检查内容逻辑的代码

写入数据目录列标记

一旦我们从 DLP 获得检查结果,我们需要将它们转换成数据目录标记,我们从检索列名开始:

显示从 DlpDataCatalogTagsTutorial.java检索列逻辑的代码

接下来,我们设置数据目录标签模板:

显示从DlpDataCatalogTagsTutorial.java创建模板逻辑的代码

还记得我们在标签心智模型中看到的大查询条目吗?我们需要构建条目linkedResource:

显示来自DlpDataCatalogTagsTutorial.java的链接资源逻辑的代码

最后,我们创建标签请求:

显示来自DlpDataCatalogTagsTutorial.java的标签创建逻辑的代码

等一下!datacatalogBatchClient?请注意,以编程方式访问 Google Cloud APIs 的推荐方式是使用客户端库,在我们的例子中,我们要处理大量的标签,因此为了提高性能,我们正在批处理这些 API 调用。

关于其工作的更多细节,请看一下 DataCatalogBatchClient 。

脚本执行演练

如果你已经到了这一步并且喜欢冒险,你可以执行运行云壳教程的脚本,我已经自动完成了它的每一步,如果你想试试的话:

[## mesma Costa/DLP-to-data catalog-tags-教程

它将指导您使用 DLP 结果创建数据目录标记。它比…的内容更广泛

github.com](https://github.com/mesmacosta/dlp-to-datacatalog-tags-tutorial)

我将跳过启用必需的 API设置您的服务帐户步骤,因为它们是常见的用例——完整的演练,请查看上面的 GitHub 库。

创建大型查询表

首先,我们用假的 PII 创建一些大的查询资源,以便稍后运行脚本。

# Install bq-fake-pii-table-creator using PIP
pip3 install bq-fake-pii-table-creator --user# Create the first table
bq-fake-pii-table-creator --project-id $PROJECT_ID --bq-dataset-name dlp_to_datacatalog_tutorial --num-rows 5000# Create a second table
bq-fake-pii-table-creator --project-id $PROJECT_ID --bq-dataset-name dlp_to_datacatalog_tutorial --num-rows 5000# Create a third table with obfuscated column names
bq-fake-pii-table-creator --project-id $PROJECT_ID --bq-dataset-name dlp_to_datacatalog_tutorial --num-rows 5000 --obfuscate-col-names true

创建检查模板

其次,我们创建检查模板:

# Generate your OAUTH 2.0 token with gcloud
TOKEN=$(gcloud auth activate-service-account --key-file=$HOME/credentials/dlp-to-datacatalog-tags-sa.json && gcloud auth print-access-token)# Call API using Curl
curl -X POST \  [https://dlp.googleapis.com/v2/projects/$PROJECT_ID/inspectTemplates](https://dlp.googleapis.com/v2/projects/$PROJECT_ID/inspectTemplates) \
  -H "Authorization: Bearer ${TOKEN}" \
  -H 'Content-Type: application/json' \
  -d '{
  "inspectTemplate":{
    "displayName":"DLP 2 Datacatalog inspection Template",
    "description":"Scans Sensitive Data on Data Sources",
    "inspectConfig":{
      "infoTypes":[
        {
          "name":"CREDIT_CARD_NUMBER"
        },
        {
          "name":"EMAIL_ADDRESS"
        },
        {
          "name":"FIRST_NAME"
        },
        {
          "name":"IP_ADDRESS"
        },
        {
          "name":"MAC_ADDRESS"
        },
        {
          "name":"PHONE_NUMBER"
        },
        {
          "name":"PASSPORT"
        }
      ],
      "minLikelihood":"POSSIBLE",
      "includeQuote":false
    }
  },
  "templateId": "dlp-to-datacatalog-template"
}'

在撰写本文时, gcloud 不支持 create inspect template API 调用,所以我们使用的是 Curl 。

我们在 API 调用中设置了一个 DLP 信息类型的预定义列表,您可以使用作为参考:内置信息类型或通过创建自定义类型来更改它或添加新类型。

执行脚本

关于 CLI 参数的完整细节,以及如何构建下面的脚本,请查看社区教程。

java -cp target/dlp-to-datacatalog-tags-0.1-jar-with-dependencies.jar com.example.dlp.DlpDataCatalogTagsTutorial \
-dbType "bigquery" \
-limitMax 1000 \
-dbName dlp_to_datacatalog_tutorial \
-projectId $PROJECT_ID \
-threadPoolSize 5 \
-inspectTemplate "projects/$PROJECT_ID/inspectTemplates/dlp-to-datacatalog-template" \
-minThreshold 100

在这次执行中,我们只扫描了dlp_to_datacatalog_tutorial数据集,用 5 个threads运行,并使用我们之前创建的dlp-to-datacatalog-template

让我们运行它并检查结果:

脚本执行

脚本完成后,我们可以去数据目录验证敏感数据:

数据目录条目—模式和列标记

在第一个表中,通过查看列名,可以清楚地看到我们拥有哪种敏感数据。无论如何,通过标记这些列,我们能够轻松地搜索我们的敏感数据。

你还记得那个愤怒的审计员敲你的门吗?

现在,如果他来问我们,如果你存储任何 PII,如信用卡号码…我们只是在数据目录中做一个简单的查询!我们甚至可以使用 IAM 并给他Data Catalog Viewer角色,这样他就可以自己看,省去了我们的拜访。

寻找信用卡号码的数据目录搜索

玩笑归玩笑,数据目录搜索语法真的很强大,由支持 Gmail 和 Drive 的谷歌搜索技术驱动。所以检查他们的文档,看看所有的可能性。

您还记得那个带有混乱的列名的表格吗:

数据目录条目—模式和列标记

DLP 来救援了!我们可以看到,我们标记了一些列,通过展开标记详细信息:

数据目录标签详细信息

我的天啊。DLP 在那个列上找到 303 CREDIT_CARD_NUMBERS,有 1000 行样本,感谢 DLP

结束语

在本文中,我们看到了如何结合数据目录和 DLP 来发现 Google Cloud 项目中的敏感数据。

随着 GPDR、CCPA 和其他监管法案成为现实,现在拥有一个结构化数据治理流程比以往任何时候都更加重要,该流程允许您了解您的公司存储了哪些数据、数据位于何处以及业务如何受到这些数据的影响。

在这个领域,总是有改进的空间,如果我们可以扩展这个脚本,在发现敏感数据时自动阻止对敏感数据的访问,会怎么样?这当然是可能的,通过使用数据目录策略标签,所以请继续关注新的帖子,讨论这个问题!干杯!

参考

  • DLP 文件:https://cloud.google.com/dlp
  • 数据目录文档:https://cloud.google.com/data-catalog
  • DLP 转数据目录标签演练教程:https://github . com/mes macosta/DLP 转数据目录标签教程
  • 社区博客教程:https://cloud . Google . com/Community/tutorials/DLP-to-data catalog-tags

BigQuery:云巨头的意外诞生

原文:https://towardsdatascience.com/bigquery-the-unlikely-birth-of-a-cloud-juggernaut-b5ad476525b7?source=collection_archive---------36-----------------------

10 名工程师如何转变云数据分析

伊斯托克上吉拉夏的照片

T 何 BigQuery 团队最近以一段趣味纪念视频来纪念其推出十周年。作为 BigQuery 的创始产品经理,参加庆祝活动让我对团队的成就感到无比自豪。BigQuery 被大大小小数千家公司使用,已经成为世界上使用最广泛的云数据仓库之一。此外,由于管理着数 Pb 的数据,可以说 it 在将大数据分析纳入主流方面做得最多。

因此,当了解到 BigQuery 在谷歌内部的卑微出身时可能会感到惊讶——最初几年不到 10 名工程师。为了让 BigQuery 走到今天,这个小团队依靠对客户的专注,克服了多个潜在的陷阱,并迅速将一款突破性的产品推向市场。我想我应该分享一下早期的内幕——与一个伟大团队的不可思议的旅程,以及是什么让我最终创办了 Switchboard。

云分析的愿景

2010 年,谷歌西雅图办公室的一群具有前瞻性思维的工程师评估了谷歌开创性的内部存储、计算和分析能力——这些技术也曾用于抓取和索引整个互联网。他们想象这些技术可以为走向数字化的公司带来变革性的好处,并开始开发一个外部服务层,最终成为谷歌云平台(GCP)。该战略的一个关键支柱是释放常规公司的网络规模分析能力,而无需构建或管理自己的大规模数据中心。项目代号…BigQuery。

分析核心工程团队 Jordan Tigani、Siddartha Naidu、Jeremy Condit、Michael Sheldon 和 Craig Citro 创建了早期的概念验证(REST API ),外部用户可以使用它来利用谷歌巨大的分析能力。我以项目经理的身份加入,利用我在谷歌之前的企业软件背景,帮助团队定义产品路线图和市场路径。

早期的“科学实验”

BigQuery 的 DNA 源自 Dremel,这是一项突破性的谷歌内部服务,在 2010 年的白皮书中有所描述,被全公司的工程师和项目经理用于对网络规模的产品进行临时日志分析。想想谷歌搜索或 Gmail,数十亿用户账户的交互被记录并存储在大量存储服务器上,用于调试或分析使用模式。传统上,这样的活动通常需要几个小时的 MapReduce 作业执行来将原始日志压缩成更易于管理的集合。Dremel 完全颠覆了这种观念,它能够使用 SQL 实时查询数万亿行数据,并在几秒钟内返回结果。

照片由 imgix 在 Unsplash 上拍摄

值得记住的是当时更广泛的行业背景:企业商业智能和分析由 Teradata、IBM 和 Oracle 等公司主导,需要一家公司拥有和操作一机架又一机架的服务器和硬盘,每 TB 存储高达 100,000 美元!“云”对许多企业来说仍然是一个非常新的概念,就像存储所有数据供以后分析的概念一样。当时,许多首席信息官声明,“我们绝不会将公司的敏感数据存储在别人的电脑上!”

2010 年 5 月,我和 Amit Aggarwal 在 Google 的 I/O 大会上发布了 BigQuery 的 Alpha 版本。这项服务太新了,以至于在那个时候,BigQuery 甚至还没有一个摄取 API!处理外部数据需要我们的一名工程师手动将数据输入系统。但是,这种向前推进并与外部早期采用者密切合作的意愿是团队的关键优势之一,这将使我们能够快速进入市场。

照片由 Gerold Hinzen 在 Unsplash 上拍摄

那个小小的引擎可以

接下来的一年,BigQuery 团队面临着严峻的资源挑战。有太多东西需要建造。Dremel 引擎是在考虑内部专家的情况下创建的——拥有 CS 学位的内部人员可以在命令行中来回跳转,调试错误堆栈跟踪或与内部团队交流以寻求帮助。您甚至不得不提供自己的数据服务器来使用这项服务。当然,作为内部用户,没有“成本”,因此没有定价或账单。因此,云服务的其余部分必须从头开始构建:编程和安全模型、访问控制、计量和计费、前端用户界面、可靠的错误处理,等等。

在只有 10 名工程师的情况下,我们必须专注于 MVP(最小可行产品)。吉姆·卡普托作为工程经理加入后,团队得到了极大的推动。他的务实方法有助于让事情快速发展,同时保持一致。Jim 很快成为了我的思想领袖和重要的合作伙伴——在 BigQuery 的大部分开发过程中,我们都被绑在了一起。

闪避和迂回发射

随着快速的进展和积极的客户反馈,BigQuery 团队开始在 Google 内部出名。但规模小意味着,在谷歌有点达尔文主义的内部环境中,BigQuery 团队必须不断寻找其他更大的、任务重叠的谷歌产品团队。

Ads 产品领域的几个资金雄厚的团队也怀有类似的野心,要为他们的客户构建查询、可视化和数据目录功能。有一次,一个拥有五倍工程师的团队试图将 BigQuery 纳入他们的计划。其他人声称他们将简单地在他们的产品路线图中复制 BigQuery 的功能。

我们通过坚定地关注我们的(外部)客户来应对这一点。通过了解他们的具体需求和痛点,我们可以向利益相关者清楚地说明为什么这对谷歌的公共云工作至关重要。这使我们能够专注于早期产品,并稳步走向发布。

照片由乔·内里克在 Unsplash 上拍摄

反击反对者

不能保证 BigQuery 会启动,因为事情进展得很快。该项目面临一些强大的内部怀疑论者,他们反对这个概念。反对意见以多种形式出现——一位高管坚持认为,BigQuery(旨在通过按查询收费来颠覆数据分析的经济学)应该向一小部分公司收取巨额费用。其他人则认为云 API 和 web 用户界面永远不会起作用。

最令人难忘的是,发射审查委员会的一位高级工程师轻蔑地(非常公开地)告诉我们,“这个项目毫无意义。没有人会使用这样的服务。”

我们坚持下来,分享早期客户告诉我们的事情——有一个重要的需求需要得到满足。

早期采用者

到 2011 年 10 月,BigQuery 被批准进行有限的预览,我们能够获得谷歌开发倡导团队的帮助。把这些人想象成构建开发者社区的核心工程师。领导这项工作的是迈克尔·马诺奇里(后来成为 Switchboard 的联合创始人)。在开发者大会上发表演讲,编写参考应用和 API 代码样本,寻找有吸引力的合作伙伴和应用,Michael 与队友 Ryan Boyd 和 Felipe Hoffa 一起,做了大量工作来启动围绕 BigQuery 的早期开发者社区。

我们还有幸与一些有远见的公司合作,包括 Gamesys、Claritics 以及早期的 Tableau 和 Looker 团队。这些团队都需要快速处理和理解大量数据,其速度是他们自己构建的 Vertica 或 Hadoop 集群无法比拟的。

企业势头

我们还与 Eric Morse 和 Matt McNeil 领导的谷歌早期云企业销售团队密切合作。我们发现无畏的销售工程师布莱恩·斯奎布和汤姆·格雷是犯罪同伙。他们已经注意到客户的数据呈指数级增长,并演变成嵌套 JSON 这样的新格式——像 State Farm、Booking.com 和宏盟这样的大型企业。

2011 年,我们与 Omnicomm 和 DoubleClick 客户工程团队合作,对 BigQuery 独特的商业适用性进行了早期展示。我们将 25 个大型 DCM(双击活动管理器)广告客户网络整合到 BigQuery 中——许多万亿字节的细粒度广告服务器日志。这些日志在单个事件层面上丰富了人口统计数据,实现了实时活动受众和频率/覆盖范围分析。这是突破性的,因为替代方案将是数月的工程设计,以构建和调整数百万美元的并行处理 Vertica 集群,或者与 Hadoop MapReduce 技术搏斗。有了 BigQuery,Omnicomm 只需为存储和必要时的查询付费,成本仅为传统系统的百分之一。宏盟最终围绕这一新的战略数据资产开发了几款产品。

照片由 SpaceX 在 Unsplash 上拍摄

正式上市和开发商采用

BigQuery 于 2012 年 5 月 1 日正式发布。自从它作为一个“科学项目”开始,我们就不断迭代并倾听客户的意见,在这个过程中,我们构建了一个早期客户因其强大和简单而喜爱的系统。现在我们必须向世界讲述他们的故事。

我还记得与我们的营销主管 Raj Sarkar 和我们的公关专家 Liz Markman 一起撰写发布博文时的兴奋。他们组织了一场发布活动,包括一场会议路演和几天的记者和分析师简报会。大数据的概念在当时是新的和闪亮的,充满了各种数据上线等待被解锁的前景。各行各业的专业人士都对 BigQuery 非常感兴趣,认为它是一种加速获取数据洞察力的方法。《连线》、、GigaOm 和 Gartner 都是报道这一趋势的科技媒体。

到 2013 年,BigQuery 迅速成为基于云的分析的标准,特别是在技术初创公司和数字原生公司中。Jordan 和 Siddartha 编写了权威的 BigQuery reference ,迅速提升了这个社区的专业知识。这些团队拥有利用 API 的编码能力,并且知道如何在 BigQuery 中处理数据。

我们会议路演的演讲者徽章(作者拍摄)

企业中尚未解决的需求

尽管采用速度很快,但企业方面仍然存在挑战。当技术组织采用 BigQuery 时,这些团队和他们的业务线同行之间的差距开始扩大。我们与收入运营和营销分析负责人进行了交谈,他们抱怨外部数据源的数量越来越多。他们的业务团队在采用 Salesforce、Marketo 或 NetSuite 等 SaaS 服务来运营业务时,一直在努力应对各种不同且通常很复杂的数据源。这使得很难将数据组合成获得洞察力所需的正确“形状”,通常需要(并加重)宝贵的开发或 BI 资源。

越来越多的传统、非技术企业,如航空公司、保险公司和零售商,开始接触我们的团队。有趣的是,站出来的不是首席信息官或首席技术官,而是首席营销官和业务部门主管。他们的信息始终如一:“我有所有这些新数据,这些数据庞大而复杂,我的技术团队没有带宽和/或领域专业知识来帮助我的团队管理这些数据……您能帮助我们吗?”

迈克尔和我努力寻找系统集成商(SI)合作伙伴来帮助这些利益相关者。但是这些系统集成商总是以构建定制的应用程序或者拼凑遗留的 BI 和 ETL 系统而告终。这些首席营销官和业务部门仍然无法控制他们的数据。他们仍然不得不依赖 IT 层,而在许多情况下,IT 层根本不理解这种新的第三方数据。我们最终会离开谷歌,成立 Switchboard 来帮助企业解决已经成为许多组织的一个决定性问题。但那是以后的事了。

Javier Allegue Barros 在 Unsplash 上拍摄的照片

云中数据的未来

自推出以来,BigQuery 一直在不断推进基于云的分析。该团队增加了强大的新功能,如流摄取、对标准 SQL 的支持和机器学习功能。新的预订价格使利用所有这些优势变得更加经济高效。也许是因为 BigQuery 团队的创新 DNA 保持不变。例如,该团队最近宣布了 BigQuery Omni 的测试版,这使得使用 BigQuery 分析生活在 AWS 或 Azure 等其他云系统中的数据成为可能。

回想这个过程,我了解到伟大的创新是如何从科技巨头内部产生的。从外部来看,这些公司似乎拥有几乎无限的资源,雇佣大量的工程师在流水线上不断产生数以千计的想法。相反,它需要难以置信的专注、专注的团队和非凡的技术,才能从内部竞争、功能蔓延、资源限制和唱反调者的严峻考验中脱颖而出。光有一个好主意是不够的。要诞生一款科技产品,你需要满足客户的迫切问题,并有毅力为他们解决问题。但是,成功推出一款产品并看到它成为行业标准的回报是无法估量的,我个人也很高兴成为其中的一员。这无疑塑造了我在离开谷歌后的职业生活。

10 年是一段很长的时间,尤其是在科技行业。承认这一里程碑并回顾这段不可思议的旅程真是太棒了。祝贺 BigQuery 团队及其不断壮大的社区,感谢他们的持续创新和发展。我迫不及待地想看看未来 10 年会发生什么!

双语数据科学家:Python 到 R(第 1 部分)

原文:https://towardsdatascience.com/bilingual-data-scientist-python-to-r-part-1-70438fcdc155?source=collection_archive---------67-----------------------

与 Python 中的代码相比,使用 R 中的代码基础的简要总结和指南。

在学院和大学,Python 被广泛教授和应用于许多学科;数学、物理、工程等。因此,更多的编码初学者最初有 Python 背景,而不是 R 背景。我就是这些人中的一员。我在大学期间有使用 Python 的经验,我在熨斗学校再次使用 Python;我把它应用于数据科学。

2019 年数据科学最需要的工具/语言来源:https://www . kdnugges . com/2020/02/getting-started-r-programming . html

关于最佳编程语言的争论一直存在,但当涉及到数据科学时,有两种语言肯定会登上领奖台,Python 和 R。了解到 R 作为一种编程语言是 2019 年数据科学第二大最受欢迎的工具/语言,占 59.2%,我想我还不如通过学习用 Python 和 R 编码来获得额外的优势。

我们开始吧!首先让我们回顾一下 Python。

来源:https://www.python.org/community/logos/

Python 自 20 世纪 80 年代末就出现了,由荷兰的古杜·范·罗森实现,作为另一种语言 ABC 的继承者。Python 是以电视节目《巨蟒剧团的飞行马戏团》命名的。

作为一种编程语言,Python 拥有哪些特性:

  • 解释
  • 面向对象
  • 高级/动态

优势:

  • 相对简单的语法(易于初学者学习编码)
  • 百事通(用于 web 开发、科学/数字计算、游戏开发等。)
  • 总体良好的社区支持(邮件列表、文档和堆栈流)
  • 受深度学习的欢迎(广泛的库和框架选择)
  • 对人工智能来说很棒

R 有什么不同?

来源:https://rveryday.wordpress.com/resources/

r 是 S 编程语言的现代实现,由统计学家 Ross Ihaka 和 Robert Gentlemen 在 90 年代创建。这个名字来自于两个创造者的名字的首字母,并发挥了 S 语言的名字。

作为一种编程语言,R 有什么特点:

  • 统计计算环境
  • 强大的图形功能

优势:

  • 用于统计的内置数据分析(代码更少)
  • 包含数据编辑器、调试支持和图形窗口的环境
  • 总体良好的社区支持(邮件列表、文档和堆栈流)
  • 非常适合图形绘图

r 是一种由统计学家和数据挖掘者开发的编程语言,通常用于分析数据、统计分析和图形。用于统计计算。

(来源:https://hacker noon . com/5-free-r-programming-courses-for-data-scientists-and-ml-programmers-5732 CB 9e 10)

Python 和 R 在不同方面都很棒。所以,我们开始用 R 吧!

安装

安装 R 和 RStudio。RStudio 是一个很好的使用 r 的 IDE,以下是两者的链接:

https://www.r-project.org/

https://rstudio.com/products/rstudio/download/

RStudio 接口

  • R 控制台:这个空间显示可以用来编写可执行代码的输出。
  • R Script: 这个空间是你写代码的地方,然后你选择你想要执行的代码,按 Control + Enter(或者 Mac 上的 Command + Enter)或者点击“运行”按钮。
  • R 环境:这个空间显示用名称、类型、长度、大小和值创建的变量。
  • 图形输出:该空间显示图形/图表,可用于选择包装。

下面是 R 中使用的一些基本语法和操作:

算术运算:

算术与 python 几乎相同,除了寻找除法的余数,因为我们使用%%而不是%,并且必须在 Python 中为平方根导入“math”或“numpy”库。

**Addition/Subtraction/Multiplication/Division:****#Python**
1 + 2
2 - 1
2 * 3
6 / 2**#R**
1 + 2
2 - 1
2 * 3
6 / 2**Square/SquareRoot/Remainder From Division:****#Python**
3**2
math.sqrt(9)
10%3**#R**
3**2 or 3^2
sqrt(9)
10%%3

数据类型:

同样,R 的数据输入与 Python 非常相似,只是在数字后添加了一个“L”来区分 R 中的数值和整数值,并且 R 中的 TRUE/FALSE 也是大写的。

**String/Float/Integer/Boolean:****#Python**
"Hello" or 'Hi'
26.56 or 1/3
30 or -2
True or False**Character/Numeric/Integer/Logical:****#R**
"Hello" or 'Hi'
26.56 or 1/3
30L or -2L
TRUE or FALSE **Type of Data:****#Python**
#gives you the type of data of chosen objecttype('this is a string')
type(True)**Type of Class:****#R**
#gives you the class type of chosen objectclass("Goodbye")
class(1.23) 

赋值运算符:

R 语法中最独特的是赋值操作符的选择。Python 使用传统的' = '将右边的值赋给左边的变量,而 R 有几种不同的方法来处理赋值。

**#Python**
x = 1**#R**
#Leftwards Assignment
x <- 1
y <<- "i am a string"
z = True
#Rightwards Assignment3 -> a
"Hi" ->> welcome

条件运算符:

对于条件运算符,Python 和 R 是相同的。

**Greater/Less Than or Equal To and Equal to/Not Equal to:****#Python**
a > b
b < c
a >= b
b <= c
a == b
b != c**#R**
a > b
b < c
a >= b
b <= c
a == b
b != c

If/Else 语句:

当看更多的函数代码时,Python 和 R 之间的逻辑是相同的,但是区别在于语法和缩进。Python 缩进是关键,因为它标记了要执行的代码块。r 在缩进方面更加宽容,但是需要花括号来区分代码块。

**#Python**i = 6
if i > 8:
    print("larger than 8")
else:
    print("smaller than 8")**#R**i = 6
if (i>8){
  print("larger than 8")
} else {
  print ("smaller than 8")
}

对于循环和 While 循环:

for 和 while 循环都采用类似的方法,就像两种语言之间的 if/else 语句一样。缩进和花括号是两种语言语法的定义特征。另外,for 和 while 条件都包含在 R 的括号中,不像 Python 使用冒号来结束条件。

**#For Loops****#Python**for i in range(1,6):
    print(i)**#R**for (i in 1:5){
  print(i)
}**#While Loops****#Python**i = 1
while i < 5:
    print(i)
    i += 1**#R**i = 1
while(i < 5){
  print(i)
  i <- i + 1
}

数据结构:

在 Python 中,数据集合有不同的数据结构,比如列表和字典。r 也有数据结构,但是有一些不同的类型和相当不同的语法来表示它们。

**#Python****#Dictionary**
my_dict = {key:value}**#List** my_list = [a,b,c]
my_other_list = list(z,y,z)**#Array** from numpy import array
my_array = ([2,4,6])**#Tuple** my_tuple = (1,2,3)**#R****#Vector** my_vector <- c(1,2,3)**#List** my_list <- list(1,2,3)**#Array**
my_array <- array(c(vector_1,vector_2),dim = c(2,2,2)**#Matrix** my_matrix <- matrix(1:6, nrow=3, ncol=2)**#Dataframe** my_df <- data.frame(column_1 = c("a","b"), column_2 = c(1,2))

向量包含同一类的对象。如果您混合不同类的对象,这些对象会变成一个特定的类,这称为强制。

**#Python**input:
my_list[1]

output: 
2**#R**input:
my_list[1]output:
1

与 Python 不同,R 的索引不是从列表中的第 0 个元素开始,而是从第 1 个元素开始,因此数据在列表中的位置与用于从列表中调用它的索引号相同。

r 脚本

r 控制台

r 环境

分析学

R 的一些好处来自图形功能,所以我将详细介绍数据科学家如何使用 R 来创建一些数据可视化。

导入和操作数据帧:

在 R 中导入 csv 文件类似于 Python,但是您添加了另外两个参数:

  • 判断正误:取决于 csv 的第一行是否是列名(如果是,则使用 TRUE)
  • 文件中的数据使用什么类型的分隔?(在本例中为“,”逗号)

我在下面列出了几个 dataframe 函数。还有很多,但是我想用一些常见的例子来展示这些函数的语法的方法和简单性。

**#Python** name_of_df = pd.read_csv("name_of_csv_dataset.csv")name_of_df.head()
name_of_df["columns_name"]**#R
#import**
name_of_dataframe <- read.csv("name_of_csv_dataset.csv",TRUE,",")**#show head of dataframe**
head(name_of_df)**#shows variables and their observations (structure)** str(name_of_df) shows variables and their observations**#show shape of dataframe** dim(name_of_df)**#locate value for specific datapoint in dataframe** name_of_df[row_index,"column_name"**#show entire row as a dataframe**
name_of_df[row_index,]**#show entire column as a dataframe**
name_of_df[,"column_name"]**#show specific rows and columns as a dataframe**
name_of_df[c(row_a,row_b),c("column_name_1","column_name_2]**#sort values by a column as a dataframe**
name_of_df[order(name_of_df$column_to_sortby,decreasing=TRUE),]

剧情:

r 已经内置了绘图功能,而不需要使用做得很好的外部库,如果需要,还有更专业的图形软件包。我不会比较 Python 和 R 的直接代码,因为这两种语言都有各种各样的库和包可以用于绘图,也有各种各样的图形类型。

我将使用内置的 Iris 数据集来显示一个简单的箱线图和直方图。

plot(iris$Species,iris$Sepal.Length)
hist(iris$Sepal.Length)

当您在控制台中执行上述代码时,这些图形将出现在 RStudio 的图形环境块中。

植物分类和萼片长度的基本箱线图

植物萼片长度的基本直方图

在 RStudio 的图形环境模块中,您可以检查您想要使用的包。我将在这里使用 ggplot2 包进行一些更高级的绘图。

我将使用 ggplot2 包的内置数据集。

qplot(displ,hwy,data=mpg,facets=.~drv)
qplot(hwy,data=mpg,fill=drv)

按车辆车轮驱动类型的发动机尺寸划分的公路里程散点图

公路里程直方图,根据车辆的车轮驱动类型进行着色

我会把 R 指南分成多部分的系列,这样更容易消化…

下一集双语数据科学家:

  • 数据操作:我将介绍 R 中使用的技术和方法,类似于您可能在 Python 中对 Pandas 使用的函数
  • 统计:我将在 R 中探索各种各样的统计测试

十亿美元的数据科学

原文:https://towardsdatascience.com/billion-dollar-data-science-ea586c621590?source=collection_archive---------15-----------------------

如何防止高风险数据科学应用中代价高昂的失败

预测智能手机计划的客户流失的内在风险与为一万亿美元的抵押贷款支持证券定价或为自动驾驶汽车检测人行横道上的行人是不同的。在第一种情况下,一个错误的决定有机会成本,在第二种情况下,它会导致金融危机,在第三种情况下,有人可能会受伤或死亡。作为数据科学家,我们经常谈论模型选择、超参数优化和性能指标,但很少谈论应用的严肃性会如何影响我们的工作。从事金融行业十年后,我发现有 5 个问题是模型失败的最常见根源。了解它们是什么以及如何处理它们可能会帮助你避免在数据科学中犯下十亿美元的错误。

照片由佩皮·斯托扬诺夫斯基在 Unsplash 拍摄

风险和可逆性

有两个概念对于很好地评估一个模型将如何用于决策是至关重要的:风险和可逆性。第一个概念,风险,更直观。衡量风险的最佳方式因每个决策而异,但它总是关于理解正确决策的回报和错误决策的代价。第二个概念,可逆性,是关于一个不正确的决定在事实发生后是否可以被改变。决策几乎永远不会完全可逆,因为通常会产生一些成本,即使是损失的时间或受损的声誉等非金钱成本,但错误可以逆转或减轻的程度会改变糟糕选择的实际成本。

当我在《纽约时报》从事评论审核工作时,机器学习模型的错误成本是明确而有限的。一个读者会发布算法漏掉的淫秽评论,其他读者会向我们的评论审核专家团队报告,评论会被删除。即使在系统故障的情况下,也需要不到 24 小时来检测故障,并修复机器学习系统或暂时使整个系统离线。错误决策造成的风险很低,因为出现淫秽评论的可能性和显示淫秽评论的成本都很低。模型决策也是可逆的,因为版主可以在评论显示后将其删除。在这种情况下,数据科学家应该自由地快速行动,打破常规。通过模型的快速迭代进行学习和实验的好处超过了部署前的仔细验证和检查。

在为信用卡建立风险模型时,人们面临的情况是完全不同的。今天部署的模型出现严重问题的第一个明显迹象可能不会在 6 个月内出现。某些类型的模型故障可能需要 2 到 3 年才能显现出来。当问题变得明显时——为时已晚,损害已经造成。在这里,每个错误的决策都是低风险的,因为与投资组合的规模相比,损失是很小的。但是每个决定都是不可逆的,在反馈回路闭合之前,总成本变得很高。如果失败足够严重,剩下要做的就是看着亏损滚滚而来,直到你慢慢地(或者可能很快地)倒闭。投资者失去了他们的钱,数据科学团队让每个人都失业,公司变成了一个恐怖的故事,就像长期资本管理一样,讲述了当你在公司给书呆子太多权力时会发生什么。

决策中风险的一般概念在用于假设检验的科学哲学中早已得到认可。虽然应用 0.95 的显著性水平被灌输给每个 Stats 101 学生,但要求对网站上按钮的颜色进行 A/B 测试的信心水平也是同样荒谬的,因为只要求医生给有风险的药物注射这样的信心水平是可怕的。尽管如此,在某些时候,科学家必须对什么样的显著性水平是合适的做出判断。

类似地,当我们构建一个模型时,我们必须对如何平衡方法的便利性和严谨性做出判断。当一个模型是高风险决策的主要输入时,我们应该如何加强我们的方法以最小化模型失败的机会?

没有通用的方法来保证模型的性能,但是在模型可能失败的无数方式中——这里是我在构建或审查模型时试图意识到的 5 种失败模式。

模型失败的五大原因

1.选择偏差

micha Parzuchowski 在 Unsplash 上的照片

建模中最常见,也是最容易被忽视的问题之一是选择偏差。选择偏差的定义因领域而异,但大致上我指的是以非随机方式收集训练数据并偏离预期应用的任何过程。大多数实际问题在某种程度上都存在选择偏差。

假设我们想要预测某人的汽车售价。选择偏差的一个温和的例子是,大部分数据是关于轿车的,只有一些数据是关于卡车和 SUV 的。基于该数据集建立的模型可能对轿车比对 SUV 更准确,但价值、里程和年龄之间的基本关系应该成立,并给出良好的预测。一种更严重的选择偏差是,只根据美国汽车的数据建立一个模型,并将其应用于日本制造商的汽车。这种差异很容易被忽略,但日本汽车有更好的记录和可靠性的声誉,所以价格不会随着年龄或里程快速下降。

为了避免被选择偏差绊倒,在建立模型之前,最好养成问两个问题的习惯:

  1. 数据收集的选择过程是怎样的?
  2. 模型是否会有与训练集在重要方面不同的操作条件?

问题#1 是最重要的,因为如果我们不理解选择过程,我们就不能对我们的模型或数据进行调整。理想的情况是只研究像物理科学中的问题,其中每个观察单位都是相同的(例如电子或细菌),所有感兴趣的变量都是独立操纵的,以使因果推断变得容易,并确保模型将完美地推广到整个群体。但是对于行业应用,数据收集很少归数据科学家所有,它可能不符合模型的操作条件,并且数据收集很少仅用于科学研究的目的。由于来自物理科学的数据往往是例外,而不是数据科学从业者的规则,所以可以问的好问题包括:

  • 什么过程将数据从更广泛的人群中提取到样本中?
  • 选择过程如何影响样本数据?(例如,用于分类的标签比率的变化,或者特征分布的支持)
  • 时间的流逝是否带来了潜在的影响?

对于我们关于选择偏差的第二个问题,如果训练数据的选择过程与应用有意义的不同,第一步是尝试量化这种差异。在无监督学习或迁移学习问题的情况下,我们仍然可以以单变量方式(这更容易)或联合分布(这更难)来评估特征分布的差异。对于监督学习问题,我们还可以比较样本数据和应用之间的目标差异或预测器和目标之间的关系。

当我们想要对 P(Y | X)建模并且 X 的分布有变化时,在协变量移位的大标题下有许多技术,并且,利用相对灵活的模型,对协变量移位进行调整是容易处理的。当 P(Y)变化时(先验概率变化),校准通常是一个简单的解决方法。当一个数据选择过程(无论该过程是已知的、潜在的还是由于不稳定的环境)改变了我们所了解的 X 和 Y 之间的关系(概念转变)时,通常没有聪明的算法方法来逃避只有可用数据的问题。在这种情况下,有 5 种明智的方法:

  1. 使用护栏:约束模型允许操作的空间。这可能很简单,比如对单个要素的值进行硬切割,也可能更复杂,比如在样本数据的联合分布密度较低的地方不做决策。这种技术的一个例子是当市场在不到 10 分钟内下跌超过 10%时,停止模型交易。
  2. 收集更多数据:改变选择过程,最好是通过实验,直接解决选择偏差。
  3. 渐进式探索:使用分层抽样或主动学习等技术(通常受预算限制)来更新模型,并在“实时”环境中高效学习。
  4. 使用预测区间:对于监督学习,当有可能生成准确的预测区间时,有时调整决策过程以使用预测区间而不是点估计就足够了。
  5. 建立一个因果模型:这是最难也是最不实用的方法,但是识别因果关系解决了许多选择偏差产生的问题,当有可能识别它们的时候。

大多数实际应用都存在某种程度的选择偏差。最重要的是理解它,以便有意识地决定偏差带来的风险,以及如何在模型的构建或应用中减轻风险。

2.操作化

照片由 Tachina Lee 在 Unsplash 上拍摄

可操作化的概念是如何将一个模糊的、真实的目标变成一个可量化的问题。一个简单的例子就是“吸烟致癌”的假设。即使有了这样一个直观的想法,我们仍然需要决定如何量化假设。例如,我们是否应该将“吸烟”的定义局限于烟草?如果是,一个人要抽多少或多长时间才有资格成为“烟民”?我们对癌症的定义是否仅限于肺癌?诸如此类。

让数据科学的可操作性变得棘手的是,错误往往不在于数据或算法,而在于我们自己。我们从技术训练中获得的素质经常引导我们去熟悉和舒适的方法,即使它们可能不是解决问题的正确选择。有时候最重要的问题也是最不明显的。要设置一个新问题,有两个背景问题需要仔细考虑:

把这个问题框定为数据科学问题到底合适不合适?

在工业界,非科学的、昂贵的或不可行的问题总是被提出来。在试图回答迈克尔·乔丹或勒布朗·詹姆斯是否是有史以来最伟大的篮球运动员之前,问问这个问题是否值得回答,如果值得,数据科学是获得答案的正确途径吗?

可以用什么方法学来设计这个问题?

我们都倾向于默认使用我们最熟悉的工具和技术,这可能是一个错误。身份盗窃问题就是一个很好的例子。将问题设计成分类问题和异常检测问题可以得到更好的结果。当数据是相关的,或者我们需要进行因果推断时,我们必须处理这些问题,即使大多数技术不能保证这一点。问题应该决定方法,而不是相反。

一旦解决了背景问题,我们就可以评估更明显的技术主题:

分解 —问题是否应该分解成零件?尽管端到端学习对于复杂的问题来说可能很有吸引力,正如吴恩达在“机器学习的渴望”一章中就端到端学习的利弊指出的那样它可能需要更多的数据,并且更难分析和改进。

特性 —基于对领域的了解,是否存在所有相关的度量?潜在特征在多大程度上可能产生影响?无关数据被排除了吗?如果与人打交道,这些数据会导致不公平或歧视性的待遇吗?

目标 —目标是否最接近预期结果?无论是多臂强盗还是分类器,选择对看起来接近人的概念建模,如收入和利润,可以对模型产生巨大的影响。

目标函数 —目标函数是否用正确的约束优化了正确的权衡?尽管最小化 RMSE 或对数损失的想法在监督学习中普遍存在,但可能有更合适的方法(例如,不同的损失函数、成本敏感的机器学习、结构化预测、多目标优化)。

性能评估 —即使在对监督学习问题的损失函数进行了大量考虑的理想情况下,优化的函数也很少是手边的实际问题。这仍然是一种简化,对于高风险模型更是如此,在高风险模型中,问题的某些方面可能存在难以量化的限制,如可解释性、计算复杂性或与其他系统的交互。高风险模型的最终评估必须超越简单的汇总统计,并尽可能根据预期用途进行评估。

操作化是任何数据科学问题中最具挑战性的部分之一,因为它将该领域中一些最巧妙和技术性的方面联系在一起。即使有领域知识,也很难对一个问题提出一个好的概念表示。为这一概念提出实证测量和数学表述,如果不是更难的话,至少也是同样困难的。好消息是,当一个问题被正确操作时——其他一切都变得容易多了。

3.黑箱滥用

阿里·沙阿·拉哈尼在 Unsplash 上拍摄的照片

高风险问题不同于低风险问题的一个方面是,我们几乎总是想要一些证据,证明模型使用信息的方式与我们对现实的理解一致。虽然“白盒”模型经常被提议作为“黑盒”模型的替代方案,如神经网络或集成方法来提供证据,但现实是线性或逻辑回归模型不容易解释大多数现实世界的问题,并且需要更多的工作来实现类似水平的预测准确性。当复杂模型失败时,问题几乎从来都不是模型的灵活性,而是将输入数据、算法或模型对输入数据的使用视为黑盒的某种滥用。

对于一个高风险的决策来说,忠实——一个模型的概括能力——甚至比准确性更重要。对于任何高风险模型,谨慎的做法是:

理解算法 —这看似显而易见,但却是许多失败的根源。每个算法都有优点、缺点和假设。无论是特征的规模还是数据的维度,对算法局限性的实际工作知识与合理的理论理解一样重要。

了解特征-即使在学习特征表示是建模任务的一部分的情况下,了解输入数据是什么以及如何使用它也是至关重要的。两个很好的例子说明了这一点的重要性:

  1. 泄漏 —除了在某个特征与目标有着滑稽的强关联的情况下,泄漏需要人为干预来防止。
  2. 歧视 —导致不公平待遇的数据(如种族主义、性别歧视等。)对人来说可能是显而易见的,但在模型优化中却不明显。甚至像一份好的清单这样简单的事情也可以成为从数据或模型中承认歧视的起点。

理解模型如何使用特性:有各种各样的方法来评估一个模型,甚至是一个“黑盒”模型,如何使用数据。对于稀疏数据,手动检查每个特征是不可行的,但利用特征重要性的指数衰减或问题中的特殊结构(如生物信息学中的双聚类)仍然可以证明模型中的原则驱动因素在概念上是正确的,即使在具有大量竞争因素的高维空间中的行为难以理解。

尊重数据集偏差的影响-对超参数优化的短视关注可能会使我们相信模型性能已经得到改善,即使跨数据集泛化或对超时维持的泛化很差。对运行条件变化具有鲁棒性的模型可能更适合高风险应用。

当然,有时不理解一个模型是如何工作的,理解一个模型是如何崩溃的就足够了——我们将在关于错误分析的第 5 章中讨论。

4.部署

凯文·杰瑞特在 Unsplash 上拍摄的照片

即使是在正确的数据上以正确的方式构建的模型仍然面临着部署的障碍。为了使模型有用,模型的输出必须走出实验室,回到现实世界。机器学习:技术债务的高息信用卡是关于机器学习系统的软件工程最佳实践的权威参考,我强烈推荐它,因此我将特别关注部署高风险应用程序的一些实际考虑

匹配环境

开发环境和预期应用程序的硬件差异往往是最难处理的,尤其是在浮点运算存在差异的情况下。幸运的是,我们大多数人只需要关心软件层,虚拟机和容器让生活变得更加轻松。无论采用哪种方法,环境细节都需要匹配:操作系统、语言和软件包版本等。都需要排队。模型的单元测试和集成测试经常会错过边缘情况,这些情况可能是由在两个独特的环境中执行的具有细微差别的相同的全功能代码行引入的。

序列化

为了存储、共享或复制一个模型,需要将它序列化到持久存储中。不幸的是,对于许多实际应用来说,模型序列化仍然具有挑战性。原生序列化格式,如 Python 中的 pickle 或 R 中的 rds ,以及工具特定的序列化格式,如 TensorFlow 或 mllib 中的格式,都很方便,但几乎总是会产生问题。安全性可能是一个问题,随着模型的老化,重新创建正确的执行环境可能是困难的或不可取的,并且可能没有简单的方法将模型分发到不同的平台。虽然 PMML 是行业标准的序列化格式,因为它是独立于语言和平台的,但它也有缺点。PMML 强调的是便携性,而不是性能;此外,只有有限数量的模型类型可用,并且将格式扩展到新类型的模型或转换是一项不小的工作量。 ONNX 和on XML已经开始弥合深度学习模型和标准机器学习模型的序列化格式之间的差距,但仍在积极开发中。因为序列化很少有一个显而易见的答案,所以最终,存储模型及其训练参数的数据总是一个好习惯,以便在必要时可以从头重新创建它。

特征

根据我的经验,特性导致的失败比模型部署的任何其他方面都要多。

翻译错误

特性工程经常发生在与生产环境不完全匹配的开发环境中。有时,开发中编写的特性甚至必须翻译成不同的编程语言才能用于生产。将功能转换到生产环境中可能会出现错误。尽管编写所有特性的生产实现并通过生产系统提取它们用于开发,但由于时间和现有系统的限制,这通常是不可行的。通常,我们所能做的最好的事情是在共享数据集上测试生产实现和开发实现,并要求匹配达到浮点精度。

所有权

不管数据是来自传感器还是 ORM,建模者很少拥有或维护数据的创建。除了我们在“黑盒滥用”一节中讨论的泄漏概念之外,这一挑战还会以几种不同的方式出现:

  • 漂移:即使当一个特性的计算和一个模型之间有一个明确的依赖关系时,由于大多数软件系统中存在的耦合程度,特性的分布也会随时间漂移。即使计算本身不变,它也依赖于输入,而输入又具有依赖性。一个很好的默认假设是,代码库的正常开发和与之交互的真实世界过程最终会导致不可接受的偏差。
  • 修复“损坏的”功能:虽然漂移会导致模型慢慢退化,但有一个棘手的维护问题会导致功能立即损坏。有时,模型具有被精确实现的特性,但是具有明显的计算错误——例如,将整数视为字符串或除以零。然后,作为正常维护的一部分,特征计算被某个人改变,该人认为他们正在修复一个 bug——但是无意中破坏了模型。即使基于改进的计算来重新训练模型可能是理想的,但模型的性能保证是基于原始特征计算的,并且会有所不同(可能更差),因为其参数是基于该计算的。

复杂性

复杂性带来的挑战是邪恶的,因为它很难定义,也很难衡量。随着模型复杂性的增加,即参数、功能和依赖性越多,或者透明度越低,或者对硬件(无论是 CPU、GPU、RAM 还是内存)的要求越高,部署和维护就越困难。

正如 Leon Bottou 在他关于的演讲中解释的,机器学习的两大挑战,管理复杂性的另一个方面是不能孤立地考虑模型。一个模型在一个动态的生态系统中运行,特别是对于现代企业,一个模型可能会受到其他模型的决策或输出的影响。

如果我们追溯到开始这一切的竞赛,100 万美元的网飞奖,获胜的算法从未实现过,因为性能优势与复杂性不相称。在部署新的 champion 模型之前,应始终将性能优势与更简单的替代方案进行权衡,尤其是在下行风险可能远远超过性能提升的高风险应用中。

与“选择偏差”、“可操作化”或“黑盒滥用”等主要与设计和创建有关的章节不同,关于部署的好消息是,只要我们在编写测试和创建监控时牢记这些问题,我们就可以开发出避免这些问题的明确方法。

5.误差分析

斯蒂芬·道森在 Unsplash 上拍摄的照片

所有模型都失败了。所有的模型都是现实的一个脆弱的简化版本。无论一个模型有多聪明或多精确,它都有缺陷。但是,如果我们能够预测一个模型将如何执行,并了解一个模型将如何失败,我们就可以安全地使用它。

即使我们为正确的决策做了很好的优化工作,我们对它的评估仍然是一种简化。构建 champion 模型后,我们可以执行错误分析,以几种不同的方式审核模型的性能,这在培训阶段可能会不方便。

“所有的模型都是错误的,但有些是有用的”——乔治·博克斯

基准

如果可能的话,最好用已知性能良好的“黄金标准”模型来评估新模型。虽然每个人都习惯于在培训/测试中对照“冠军”来评估新的“挑战者”模型,但值得注意的是,因为我们在错误分析中的目标是寻找重要的缺陷,所以有时最好是对照最健壮、最稳定的模型来评估挑战者模型,而不是最佳表现的冠军。

更经常被忽视的是,在没有明显的冠军或黄金标准可供比较的情况下该怎么做。在这种情况下,仍然有几个选择。一种是纯粹为了比较而创建一个更简单的模型。例如,如果你已经建立了一个 GAM,把它与相同数据上的逻辑回归模型进行比较。如果有足够的数据,并且关系是非线性的,那么 GAM 应该在任何地方都优于逻辑回归。同样的类比适用于任何问题——如果你将伯特应用于你的 NLP 问题,而它并没有表现出一袋单词的方法,那就有问题了。

当时间或其他约束阻止一个简单的模型成为一个现实的选择时,我们可以退回到随机数生成——这可能是一个令人惊讶的有效的现实检查。众所周知,人类不善于识别“随机”是什么样子,数据科学家也不例外。将随机的统一特征注入到数据集中,或者通过从参数与目标匹配的分布中抽取随机数来模拟“模型”,至少可以显示出纯粹由于偶然而可能发生的情况。

残差

称残差分析是一门失传的艺术是不正确的,因为统计学家还没有忘记它。也就是说,没有受过正规统计学培训的从业者往往没有充分利用它,我得到的印象是,大多数人认为残差分析只对线性模型有用。虽然 PDP、ICE 和 SHAP 图都是解释模型和检查模型如何使用特性的好方法,但要了解模型哪里出错了——没有什么比查看残差的更好的了。不是所有的残差都是相等的,尤其是当时间是一个问题的相关维度时。幸运的话,检查残差可以建议改变特征表示、模型类型或集成模型的机会。在最坏的情况下,残差分析可以证明模型的整体指标没有隐藏残差上的恶劣行为,其中一小部分大残差被小的平均残差抵消。

成分

有时候,将机器学习系统分解成组件来分析性能,这在事后才显而易见。回到我们最初的例子,自动驾驶汽车的行人检测可能会在许多方面出错。模型可能擅长检测图像中的人,但不擅长检测场景中的位置。或者它可能对接近任何一种“条纹”图案的人来说太合适了,不管是条纹人行横道还是条纹衬衫。预测信用卡违约风险也是如此。预测 2 年期的违约概率包含许多因素。一个模型可能只是非常擅长预测前 6 个月或 12 个月的短期风险,之后也不会比随机风险更好。将一个系统分解成几个组成部分来测量哪里出现了错误,这有助于我们理解它是如何工作的,哪里出了故障。

与残差一样,成分分析的主题是检测意外错误。如果我们在构建模型的一开始就预料到某些组件将更难建模,我们可能会以不同的方式塑造我们的训练集,添加功能以避免矛盾的关系,或者创建子模型。事实是,我们最初的假设是,我们可以测量或优化的许多东西根本不重要。即使对于我们非常关心准确性和可靠性的模型或机器学习系统,对每个假设进行建模和测试也是不现实的。通常,事后检查性能是否符合预期以及错误是否是随机的要比事先为所有可能性做好准备容易得多。

结论

杰瑞米·托马斯在 Unsplash 上拍照

大多数模型不需要三级审问。有些是。在准备构建任何模型时,考虑模型将用于的决策的风险和可逆性总是谨慎的。如果一个模型将被用于做出高风险、不可逆转的决策——作为科学家,我们应该增强我们的怀疑精神和方法的严谨性。不幸的是,这 5 个模型失败的常见原因并没有涵盖所有可能的失败模式。但它们确实是一个健康的提醒,帮助任何从业者避免可预防的错误…甚至可能是十亿美元的错误。

基于 FAISS+SBERT 的亿级语义相似性搜索

原文:https://towardsdatascience.com/billion-scale-semantic-similarity-search-with-faiss-sbert-c845614962e2?source=collection_archive---------3-----------------------

构建智能搜索引擎的原型

作者图片

介绍

语义搜索是一种信息检索系统,它关注句子的含义,而不是传统的关键字匹配。尽管有许多文本嵌入可以用于此目的,但是很少有人讨论如何扩展它来构建可以从大量数据中获取数据的低延迟 API。在这篇文章中,我将讨论我们如何使用 SOTA 句子嵌入(句子转换器和 FAISS )来实现一个最小语义搜索引擎。

句子变形金刚

它是一个框架或一组模型,给出句子或段落的密集向量表示。这些模型是变压器网络(BERT、RoBERTa 等。)进行了微调,特别是针对语义文本相似性的任务,因为 BERT 对于这些任务的开箱即用表现不佳。下面给出了不同型号在 STS 基准测试中的性能

图片来源:句子变形金刚

我们可以看到,句子转换模型远远优于其他模型。

但是如果你看一下排行榜上有代码为和胶水的论文,你会看到很多 90 以上的模型。那么我们为什么需要句子变形金刚呢?。

在这些模型中,语义文本相似度被认为是一项回归任务。这意味着每当我们需要计算两个句子之间的相似性得分时,我们需要将它们一起传递到模型中,模型输出它们之间的数值得分。虽然这对于基准测试很有效,但是对于现实生活中的用例来说,它的伸缩性很差,原因如下。

  1. 当您需要搜索 10 k 个文档时,您将需要执行 10k 个独立的推理计算,这是不可能单独计算嵌入和仅计算余弦相似性的。见作者解释。
  2. 最大序列长度(模型在一次传递中可以采用的单词/标记的总数)在两个文档之间共享,这导致表示由于分块而被稀释

费斯

Faiss 是一个基于 C++的库,由脸书·艾创建,带有一个完整的 python 包装器,用于索引矢量化数据并对其进行有效搜索。Faiss 根据以下因素提供不同的指数

  • 搜索时间
  • 搜索质量
  • 每个索引向量使用的内存
  • 训练时间
  • 无监督训练需要外部数据

因此,选择正确的指数将是这些因素之间的权衡。

加载模型并对数据集执行推理

首先,让我们安装并加载所需的库

!pip install faiss-cpu
!pip install -U sentence-transformersimport numpy as np
import torch
import os
import pandas as pd
import faiss
import time
from sentence_transformers import SentenceTransformer

加载带有百万个数据点的数据集

我使用了一个来自 Kaggle 的数据集,其中包含了 17 年间发布的新闻标题。

df=pd.read_csv("abcnews-date-text.csv")
data=df.headline_text.to_list()

加载预训练模型并执行推理

model = SentenceTransformer('distilbert-base-nli-mean-tokens')encoded_data = model.encode(data)

索引数据集

通过参考指南,我们可以根据我们的用例选择不同的索引选项。

让我们定义索引并向其中添加数据

index = faiss.IndexIDMap(faiss.IndexFlatIP(768))index.add_with_ids(encoded_data, np.array(range(0, len(data))))

序列化索引

faiss.write_index(index, 'abc_news')

串行化的索引然后可以被导出到用于托管搜索引擎的任何机器中

反序列化索引

index = faiss.read_index('abc_news')

执行语义相似性搜索

让我们首先为搜索构建一个包装器函数

def search(query):
   t=time.time()
   query_vector = model.encode([query])
   k = 5
   top_k = index.search(query_vector, k)
   print('totaltime: {}'.format(time.time()-t))
   return [data[_id] for _id in top_k[1].tolist()[0]]

执行搜索

query=str(input())
results=search(query)
print('results :')
for result in results:
   print('\t',result)

CPU 上的结果

现在让我们看看搜索结果和响应时间

作者 GIF

仅用 CPU 后端对一个包含百万文本文档的数据集执行智能的基于含义的搜索只需要 1.5 秒

GPU 上的结果

首先,我们卸载 Faiss 的 CPU 版本,重装 GPU 版本

!pip uninstall faiss-cpu
!pip install faiss-gpu

然后按照相同的过程,但在最后将索引移动到 GPU。

res = faiss.StandardGpuResources()
gpu_index = faiss.index_cpu_to_gpu(res, 0, index)

现在让我们把它放在搜索函数中,用 GPU 执行搜索。

作者 GIF

没错,使用比 CPU 后端快 75 倍的 GPU (本实验中使用的是特斯拉 T4)**可以在 0.02 秒内得到结果**

但是,如果我可以等待几秒钟,为什么我不能序列化编码数据的 NumPy 数组而不是索引它们并使用余弦相似性呢?

因为 NumPy 没有自带的序列化函数,所以唯一的方法是将其转换成 JSON,然后保存 JSON 对象,但是这样一来,大小会增加五倍。例如,用普通索引编码成 768 维向量空间的 100 万个数据点大约是 3GB,将其转换成 JSON 将是 15GB,这是普通机器的 RAM 所不能容纳的。因此,每次执行搜索时,我们都必须运行一百万次计算推断,这是不实际的。

最后的想法

这是一个基本的实现,在语言模型部分和索引部分还有很多工作要做。有不同的索引选项,应根据使用情形、数据大小和可用的计算能力选择正确的选项。此外,这里使用的句子嵌入只是在一些公共数据集上进行微调,在特定领域的数据集上进行微调将改善嵌入,从而改善搜索结果。

参考

[1]尼尔斯·雷默斯和伊琳娜·古雷维奇。 制作单语句子嵌入多语使用知识蒸馏 。”arXiv (2020): 2004.09813。

[2]约翰逊,杰夫和杜泽,马特希斯和 J{'e}gou,赫夫{'e} 用 GPU 进行亿级相似性搜索*arXiv 预印本 arXiv:1702.08734 *

BIM 和人工智能相结合。用例。

原文:https://towardsdatascience.com/bim-and-artificial-intelligence-combined-use-case-778dad72f64c?source=collection_archive---------21-----------------------

利用深度神经网络优化 BIM 模型能源性能

相对而言,最近 AEC(建筑、工程、施工)行业遇到了一项名为 BIM 的新技术。建筑信息建模允许在实际施工开始之前虚拟地建造一座建筑;这带来了许多有形和无形的好处:减少成本超支,更有效的协调,授权决策等。对于一些公司来说,采用 BIM 是一个很大的障碍,许多公司仍在挣扎。但现在我们看到行业中出现了另一个新趋势:人工智能。我们不要害怕,仔细看看。这比你想象的要简单!

在本文中,我将展示我的硕士论文 使用深度神经网络 优化 BIM 模型能源性能。

提出问题

许多不同的估计表明大约 70–80%的设施成本是运营成本。

设施成本分配。作者图片

这些当然也是因为保养;但请记住,建筑业有时被称为“40%的产业”,因为它占据了世界自然资源和二氧化碳排放量的 40%。我们应该更好地保护自然!

我将尝试提出一个优化建筑能耗的框架,它被称为 EUI,或能源使用强度,以 MJ(或 kWh)/m/年为单位。能源分析将由绿色建筑工作室执行,该工作室使用 DOE-2 引擎和从 Revit 导出的 gbXML 文件。

获取数据

首先,我们需要做一些假设。让我们为我将要测试的每个模型保持相同的 HVAC 系统(即,Revit 提供的用于单户住宅的标准 HVAC 模型将用于每个 Revit 模型)。事实上,在真实的设施中,随着时间的推移,它可以被更高效的装置和系统所取代,否则我们可能不会那么早就知道 HVAC 的类型。

相反,让我们把注意力集中在建筑物更持久的特征上,比如地板、墙壁和屋顶的热传导率;窗墙比;计划中的旋转。这些都是我将要研究的特性。

另一个假设是,我们的 Revit 模型将是一个普通的盒子,里面只有一个房间,没有隔墙和窗户(窗墙比将在后面指定)。这是为了简化分析。

首个 Revit 模型。作者图片

因此,让我们尝试以下参数范围的所有组合:

设计参数。作者图片

10368 种组合太多了,但 Revit API 会有所帮助。Green Building Studio 使用 Revit 可以导出的 gbXML 文件。该脚本将热阻值和平面旋转的组合应用于模型,并将每个组合模型导出为 gbXML 格式。通过改变热资产的热导率来获得不同的热阻值。改变厚度会在分析中引入另一个因素:分析表面始终位于元素的中间,因此总面积会随着壁厚而变化。

在解析 gbXML 目录以获得所有文件的路径之后,我们准备将我们的 3456 (121212*2) gbXML 文件上传到 Green Building Studio。使用发电机包对发电机进行能量分析。

发电机节点能量分析。作者图片

分析完成后,我们可以开始在 Green Building Studio 中指定窗墙比。不幸的是,Dynamo 包没有这个功能,GBS API 只对开发者开放,所以我不得不求助于浏览器自动化来分配 wwr。然而,这只需要做一次,我们稍后会看到为什么。当能量分析完成后,我们可以解析 GBS 的数据并彻底检查它。

用密谋密谋。作者图片

现在,让我们用另一个简单但不同的 Revit 模型重复上述所有步骤。

第二个 Revit 模型。作者图片

我们需要这些数据供以后使用。

训练神经网络

对于每个机器学习项目,数据检查和准备是必须的。但是在这种情况下,我们没有缺失数据或异常值:我们的数据是人工创建的。因此我们可以安全地跳过许多检查步骤。我将在另一篇文章中更详细地描述神经网络。有兴趣的话,这里有剧本。但长话短说,给定大量数据,神经网络能够推导出管理数据的规则。与传统编程相比,我们给出规则和数据来获得答案。

图片作者。灵感来自 DataLya

当规则难以编码时,神经网络就派上了用场:人脸或语音识别、自然语言处理、翻译、情感分析等。

我设计的网络有这样的架构:

原始神经网络。作者图片

输入层(绿色)有 5 个单元。这些是我们的参数:WWR,平面旋转和三个热阻值。反过来,输出图层(黄色)是 EUI 值。将这个网络(蓝色层)视为一个巨大的矩阵,在第一步中只包含随机数。为了训练网络,我们的输入层(向量)乘以一系列矩阵,以获得 EUI 值的预测。然后将预测值与实际 EUI 值进行比较,并更新网络中的数字以更好地预测输出。这个循环一直重复,直到我们对表现满意为止。

现在是时候根据第一个盒子模型的数据点来训练我们的网络了。其中 94%将用于训练我们的网络,6%用于验证网络并调整影响网络的一些参数以获得更好的性能。

训练之后,我们使用网络来预测 10368 个 EUI 值:

网络的预测。作者图片

误差保持在 0.2%以内,还不错。除此之外,网络把我们的数据从离散变成了连续。换句话说,我们现在可以获得以前无法获得的参数的 EUI 值;例如 21% WWR 或 R=2.45。

好了,这让我们进入下一步。

转移学习

还记得我们在第一步中制作的第二个 Revit 模型吗?我们现在将把它与一种叫做“迁移学习”的技术结合起来使用。让我们将前一步中训练好的网络设置为不可训练的前四层:

冻结网络。作者图片

或者,换句话说,让我们只关注最后两层。

此时,网络“知道”主要模式和趋势以及每个参数如何影响 EUI。但仅适用于第一个 Revit 模型。

现在,让我们通过使用新数据重新训练最后两层,将新的 Revit 模型“引入”我们的网络。但是有一个重要的区别:这次只有 6%的数据用于训练,94%用于验证。不执行超参数调整。我们在训练后得到这样的结果:

再训练网络的预测。作者图片

注意:与第一个 box Revit 模型的 2-3 小时相比,训练花费的时间大约为 1 或 2 分钟,预测几乎一样准确。

一个小实验

为什么坚持 6%的培训-验证比例?让我们再尝试一些,看看效果如何。

4%的训练数据。作者图片

1%的训练数据。作者图片

0.25%训练数据。作者图片

事实证明,在大约 1-2%的训练-验证分裂时,性能开始显著下降。

请注意,在功能丧失达到稳定水平后,训练停止

结果和比较

恭喜你!现在,我们有了一个训练有素的网络,可以用少量的数据预测 Revit 模型在大范围参数下的能耗。该模型甚至可能没有任何窗口。我们做的最后一步展示了它:通过从我们想要分析的模型中引入一些数据点,我们得到了一个非常准确的估计,误差很小。

为了强调迁移学习效应,让我们以刚刚训练的网络为例,预测两个模型的 EUI。

一个网络-两个 Revit 模型预测。作者图片

这就是说,我们不能采取随机神经网络,并期望它与我们的模型一起工作:应该做一点点能量分析。然而,它可以像第一部分一样自动完成。

未来工作

现在,我们已经有了一个神经网络来建立一个准确的能耗预测,除了用复杂的 Revit 模型进行测试之外,还必须向实际优化迈出一步。为了找到参数的最优组合,需要建立一个成本模型。成本模型应包括材料成本、人工成本、可能的维护成本、能源成本,并应考虑建筑的生命周期、建筑和物理限制。

这将产生一个现实的框架,只需很少的努力就可以在项目的概念阶段选择最佳的参数组合。

谢谢你读到这里!

我总是乐于参与讨论或收到反馈。给我留言LinkedIn或电子邮件:mikhail1dem@gmail.com

二进制和多类文本分类(模型测试管道中的自动检测)

原文:https://towardsdatascience.com/binary-and-multiclass-text-classification-auto-detection-in-a-model-test-pipeline-938158854943?source=collection_archive---------18-----------------------

来源:作者图片

介绍

在我之前的文章(文本分类中的模型选择)中,我针对二进制文本分类问题,提出了一种通过比较经典机器学习和深度学习来选择模型的方法。

笔记本的结构是自动运行,交叉验证所有算法,并显示不同指标的结果,让用户根据自己的需要自由选择算法。

在这里,笔记本被创建来显示二元或多类问题的不同度量和学习曲线。笔记本将自动定义数据集的配置。

笔记本和脚本可以在这里找到: GitHub

信息

目标是使用不同的模型,并在训练测试期间观察它们的行为。当可能时,算法执行提前停止避免过拟合。对于深度学习,可以在训练期间使用预训练模型来减少训练时间。

开头有两件事很重要:
-文本列名归类
-标签列名

创建流水线是为了考虑到二进制分类或多类分类,而无需人工参与。管道提取标签的数量,并确定它是二元问题还是多类问题。所有算法和指标将自动从一个切换到另一个。

笔记本以用于测试您想要的模型的参数列表开始。下面的 要诀 显示了这个列表。 Lang 决定笔记本是否需要从 Google 调用Translator()API 来检测数据集的语言(默认为英语)。

相应的 python 函数:

I —数据清理、文本处理

在这篇文章中使用的数据与上一篇文章相同,IMDB 数据集(因为它是一个开源数据集,更多详细信息在此)。

数据集不是完全干净的,在自然语言处理任务中,你需要为你的问题清理你的数据。这一步将影响算法的性能。

关于 IMDB 数据集,我做了什么?

  • 去掉一个单词的所有大写字母,只保留第一个字母(这对 NER 提取很重要)
  • 移除网址(如果有)
  • 移除 html 应答器
  • 删除表情符号
  • 有代替
  • 而非 替换n的缩写

II —极性

使用库 TextBlob 估计文本的极性,并绘制成图表(在 5000 raws 的样本上制作)。

III —文本信息

所有的评论都没有相同的长度,相同的字数。研究这些信息很有趣:

  • 提取字数
  • 提取字符数
  • 计算密度(字符数/字数)
  • 提取首字母大写的单词数

我们可以很容易地用图表标出 char 的数量:

评论大多由 550-600 个字符组成。

看类(标签)的分布也很有意思。

标签

数据集是平衡的,大约有 2500 个标签类别的评论(二进制)。

六元语法

N-grams 是一种将句子分割成 n 个单词的技术,例如:

我学机器学习是为了成为一名数据科学家

  • Unigram :【我,学习,机器,学习,到,成为,a,数据,科学家】
  • 二元模型 : [(我学习),(学习机),(机器学习),(学习到),(成为),(成为一个),(一个数据),(数据科学家)]
  • 三元组 : [(我学习机器),(学习机器学习),(机器学习到),(学习成为),(成为一个),(成为一个数据),(一个数据科学家)]

我是 n 元语法的粉丝,因为我可以通过它们展示预处理是否正确。在笔记本上,你会发现单词重要性对于单个词、两个词、有和没有停用词的三个词(一个没有重要性的单词)以及对 5 个词的测试。

对于带停用词的三元模型:

没有停止词:

这种差异非常重要。一般来说,文本包含许多停用词,这对于像 TF-IDF单词嵌入 这样的方法并不重要,但是对于 One-Hot 编码 来说却是如此,因为每个单词在一个句子中具有相同的重要性。

我们使用什么模型和指标?

管道被配置为使用不同的模型。表 1 给出了机器学习和深度学习算法以及使用的指标。

看起来怎么样

我给大家看两个例子,第一个, 随机梯度推进浅层神经网络

训练经典分类器代码如下:

该函数输入分类器和数据以拟合模型。

对于指标,已经创建了相同类型的函数:

该函数将显示不同的曲线(精确召回率、真假阳性率、ROC AUC)、混淆矩阵、Cohen's Kappa(模型之间的比较以及两个标注器将如何做)和准确度。

随机梯度推进:

用 TF-IDF 方法获得了 SGD 算法(函数 1)的最佳结果。

if sgd: # does the computation if sgd = True
    print("\nStochastic Gradient Descent with early stopping for TF-IDF\n")
    print("Early Stopping : 10 iterations without change")
    metrics_ML(SGDClassifier(loss='modified_huber', max_iter=1000, tol=1e-3,   n_iter_no_change=10, early_stopping=True, n_jobs=-1 ),xtrain_tfidf, train_y, xvalid_tfidf, valid_y, gb=True)

metrics_ML()函数将调用 classifier_model()函数来训练模型并计算指标。训练分类器和指标的最简单方法。

结果是:

Stochastic Gradient Descent with early stopping for TF-IDF

Early Stopping : 10 iterations without change
Execution time : 0.060 s
Score : 84.7 %

Classification Report

              precision    recall  f1-score   support

    negative       0.87      0.81      0.84       490
    positive       0.83      0.88      0.85       510

    accuracy                           0.85      1000
   macro avg       0.85      0.85      0.85      1000
weighted avg       0.85      0.85      0.85      1000

混淆矩阵

Model: f1-score=0.855 AUC=0.923

精确召回曲线

ROC AUC=0.919

真假阳性率

还不错,84.7%的分数。现在我们能做得更好吗?

浅层神经网络:

浅层神经网络的代码已在上一篇文章中介绍过。这里再说一遍:

每个深度学习算法都以相同的方式实现。所有的代码都可以在笔记本和对应的 GitHub 中找到。

如何使用它:

es = tf.keras.callbacks.EarlyStopping(monitor='val_loss', mode='auto', patience=3)
if shallow_network:
    model_shallow = shallow_neural_networks(word_index, pre_trained=pre_trained)
    history = model_shallow.fit(train_seq_x, train_y,
                    epochs=1000, callbacks=[es],
                    validation_split=0.2, verbose=True)
    results = model_shallow.evaluate(valid_seq_x, valid_y)

输出:

Train on 3200 samples, validate on 800 samples
Epoch 1/1000
3200/3200 [==============================] - 2s 578us/sample - loss: 0.7117 - accuracy: 0.4837 - val_loss: 0.7212 - val_accuracy: 0.5175
...
Epoch 98/1000
3200/3200 [==============================] - 1s 407us/sample - loss: 0.4991 - accuracy: 0.9991 - val_loss: 0.5808 - val_accuracy: 0.88501000/1000 [==============================] - 0s 383us/sample - loss: 0.5748 - accuracy: 0.8590

指标:

浅层神经网络的历史

 precision    recall  f1-score   support

    negative       0.86      0.85      0.86       490
    positive       0.86      0.87      0.86       510

    accuracy                           0.86      1000
   macro avg       0.86      0.86      0.86      1000
weighted avg       0.86      0.86      0.86      1000

The balanced accuracy is : 85.88%

The Zero-one Loss is : 14.1%

Explained variance score: 0.436

ROC AUC=0.931

Model: f1-score=0.863 AUC=0.932

Cohen's kappa: 71.78%

所以,神经网络的结果更好。但是,不能对每种方法的单次运行进行比较。要正确选择模型,必须使用交叉验证等评估方法(参见:文本分类中的模型选择)。

结论

流水线是自动的,你只需要在开始时配置参数选择你想要测试的不同算法并等待结果。

目标是通过算法和方法(One-Hot encoding、TF-IDF、TF-IDF n-grams、TF-IDF char n-grams 和单词嵌入)显示不同的指标,并选择您希望用于解决问题的一类算法。下一步将是调整超参数并享受结果。

这项工作有助于在不了解类的情况下,针对文本分类二元或多元类快速测试 NLP 用例。管道可以接受法语文本或者英语文本。

笔记本和课程可在 GitHub 上获得。

后续步骤

  • 实现不平衡的方法来自动平衡数据集
  • 实现变压器分类模型
  • 实施预先培训的变压器
  • 用强化学习测试 NLP
  • 知识图谱
  • 使用分布式深度学习
  • 使用 TensorNetwork 加速神经网络
  • 用正确的方法选择一类模型并进行超参数调整
  • 使用量子 NLP (QNLP)

二元分类示例

原文:https://towardsdatascience.com/binary-classification-example-4190fcfe4a3c?source=collection_archive---------16-----------------------

预测阿片类药物的使用

里卡多·罗查在 Unsplash 上的照片

这场全球危机以这样或那样的方式影响了我们所有人的生活,但这是一个磨练你的手艺的绝佳机会。我碰巧更新了我的 Coursera 账户,专门尝试网络分析。加密货币/区块链媒介文章已经成为我日常生活的一部分。最后,我想发布一个 ML 分类的例子来帮助那些寻找一个详细的“从开始到结束”的用例的人,并从整个社区中寻求建设性的反馈。这将是一个漫长而详细的旅程,我希望你已经准备好了。

我们将利用一个保险数据集,该数据集概述了一系列以患者为中心的特征,最终目标是正确预测阿片类药物滥用是否已经发生。

功能定义

ClaimID Unique: Identifier for a claim
Accident DateID: Number of days since the accident occurred from an arbitrary date
Claim Setup DateID: Number of days since the Resolution Manager sets up the claim from an arbitrary date
Report To DateID: Number of days since the employer notifies insurance of a claim from an arbitrary date
Employer Notification DateID: Number of days since the claimant notifies employer of an injury from an arbitrary date
Benefits State: The jurisdiction whose benefits are applied to a claim
Accident State: State in which the accident occurred
Industry ID: Broad industry classification categories
Claimant Age: Age of the injured worker
Claimant Sex: Sex of the injured worker
Claimant State: State in which the claimant resides
Claimant Marital Status: Marital status of the injured worker
Number Dependents: Number of dependents the claimant has
Weekly Wage: An average of the claimant’s weekly wages as of the injury date.
Employment Status Flag:
F — Regular full-time employee
P — Part-time employee
U — Unemployed
S — On strike
D — Disabled
R — Retired
O — Other
L — Seasonal worker
V — Volunteer worker
A — Apprenticeship full-time
B — Apprenticeship part-time
C — Piece worker
RTW Restriction Flag: A Y/N flag, used to indicate whether the employees responsibilities upon returning to work were limited as a result of his/her illness or injury.
Max Medical Improvement DateID: DateID of Maximum Medical Improvement, after which further recovery from or lasting improvements to an injury or disease can no longer be anticipated based on reasonable medical probability.
Percent Impairment: Indicates the percentage of anatomic or functional abnormality or loss, for the body as a whole, which resulted from the injury and exists after the date of maximum medical improvement
Post Injury Weekly Wage: The weekly wage of the claimant after returning to work, post-injury, and/or the claim is closed.
NCCI Job Code: A code that is established to identify and categorize jobs for workers’ compensation.
Surgery Flag: Indicates if the claimant’s injury will require or did require surgery
Disability Status:
— Temporary Total Disability (TTD)
— Temporary Partial Disability (TPD)
— Permanent Partial Disability (PPD)
— Permanent Total Disability (PTD)
SIC Group: Standard Industry Classification group for the client
NCCI BINatureOfLossDescription: Description of the end result of the bodily injury (BI) loss occurrence
Accident Source Code: A code identifying the object or source which inflicted the injury or damage.
Accident Type Group: A code identifying the general action which occurred resulting in the loss
Neurology Payment Flag: Indicates if there were any payments made for diagnosis and treatment of disorders of the nervous system without surgical intervention
Neurosurgery Payment Flag: Indicates if there were any payments made for services by physicians specializing in the diagnosis and treatment of disorders of the nervous system, including surgical intervention if needed
Dentist Payment Flag: Indicates if there were any payments made for prevention, diagnosis, and treatment of diseases of the teeth and gums
Orthopedic Surgery Payment Flag: Indicates if there were any payments made for surgery dealing with the skeletal system and preservation and restoration of its articulations and structures.
Psychiatry Payment Flag: Indicates if there were any payments made for treatment of mental, emotional, or behavioral disorders.
Hand Surgery Payment Flag: Indicates if there were any payments made for surgery only addressing one or both hands.
Optometrist Payment Flag: Indicates if there were any payments made to specialists who examine the eye for defects and faults of refraction and prescribe correctional lenses or exercises but not drugs or surgery
Podiatry Payment Flag: Indicates if there were any payments made for services from a specialist concerned with the care of the foot, including its anatomy, medical and surgical treatment, and its diseases.
HCPCS A Codes — HCPCS Z Codes: Count of the number of HCPCS codes that appear on the claim within each respective code group
ICD Group 1 — ICD Group 21: Count of the number of ICD codes that appear on the claim w/in each respective code group
Count of the number of codes on the claim
— CPT Category — Anesthesia
— CPT Category — Eval_Mgmt
— CPT Category — Medicine
— CPT Category — Path_Lab
— CPT Category — Radiology
— CPT Category — Surgery
Count of the number of NDC codes on the claim within each respective code class
— NDC Class — Benzo
— NDC Class — Misc (Zolpidem)
— NDC Class — Muscle Relaxants
— NDC Class — Stimulants
Opioids Used: A True (1) or False (0) indicator for whether or not the claimant abused an opioid

探索性数据分析

让我们从导入所有需要的库和数据集开始。

from math import sqrt
import pandas as pd
import numpy as np
import scipy.stats as stats
import matplotlib.pyplot as plt
import seaborn as sns
from IPython.display import displayfrom sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipelinefrom feature_engine import missing_data_imputers as mdi
from feature_engine import categorical_encoders as ce
from sklearn.preprocessing import RobustScaler
from imblearn.over_sampling import SMOTEfrom sklearn.model_selection import cross_val_score
from sklearn.metrics import roc_auc_score
from sklearn.metrics import roc_curve
from sklearn.metrics import recall_score
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
from sklearn.model_selection import GridSearchCVfrom sklearn.ensemble import GradientBoostingClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn import svm%matplotlib inline
pd.pandas.set_option('display.max_columns', None)with open('opioid_use_data.csv') as f:
    df = pd.read_csv(f)
f.close()SEED = 42df.shape
df.head(10)
df.info()

我们的数据集包含刚刚超过 16,000 个观察值以及 92 个特征,包括目标(即使用的阿片类药物)。我们还有各种各样的特征类型,包括整数、浮点、字符串、布尔和混合类型。

删除初始特征

在我们处理缺失数据、离群值或基数之前,让我们看看是否可以快速删除任何功能以简化我们的进一步分析。

for var in df.columns:
    print(var, df[var].nunique(), len(df))df.drop('ClaimID', axis=1, inplace=True)

当我们滚动输出时,可以看到每个要素的唯一值的数量以及整个数据集的总长度。具有与数据帧总长度相似数量的唯一值的特征可以被移除,因为它们不提供太多的预测能力(即方差)。“ClaimID”是唯一符合此标准的功能,可以删除。

df_copy = df.copy()
corr_matrix = df_copy.corr().abs()
upper = corr_matrix.where(np.triu(np.ones(corr_matrix.shape), k=1).astype(np.bool))upper

to_drop = [var for var in upper.columns if any(upper[var] > .90)]
to_drop

df.drop(df[to_drop], axis=1, inplace=True)

接下来,我们可以检查数字特征之间的相关性,并删除相关性非常高的特征。由您决定什么被认为是“高度相关”,但在这种情况下,我们将选择 90 及以上的相关性。请注意,在代码中,我们构建了一个相关矩阵,并将相关性转换为绝对值,以便处理负相关性。可以删除索赔设置日期标识、报告日期标识、雇主通知日期标识和最大医疗改善日期标识。

for var in df.columns:
    print(var, 'percent of missing values', df[var].isnull().mean().round(3))

我们可以检查剩余要素的缺失值百分比,并移除任何缺失数据过多的要素。一个特性“事故源代码”有超过 50%的缺失值,但这不足以保证删除。

states = pd.DataFrame(df[['Claimant State', 'Accident State', 'Benefits State']])states

df.drop(['Claimant State', 'Accident State'], axis=1, inplace=True)

考察“索赔国”、“事故国”和“福利国”,我们发现绝大多数值是相同的。我们将保留“福利状态”,因为它包含最少的缺失值。

for var in df.columns:
    print(var, df[var].unique(), '\n')

# Converting nulls to np.nan
for var in df.columns:
    df[var].replace(to_replace='  ', value=np.nan, inplace=True)# Converting values of "X" to np.nan
for var in df.columns:
    df[var].replace(to_replace='X', value=np.nan, inplace=True)# Splitting out "Accident Type Group" (ie. mixed type feature) into separate features
df['Accident Type Group num'] = df['Accident Type Group'].str.extract('(\d+)')
df['Accident Type Group str'] = df['Accident Type Group'].str[0:5]
df.drop(['Accident Type Group'], axis=1, inplace=True)

当我们检查每个特性的唯一值时,我们可以开始看到一些需要我们注意的差异。首先,我们注意到未转换为 Np.nan 的空白值或空值。接下来,我们看到许多要素的“X”值,这似乎是记录差异,记录数据的个人记录了带有“X”的缺失值。最后,名为“事故类型组”的特征是我们所说的混合类型,因为它包含字符串和数值。让我们将字符串和数值分离成各自的特征,并删除原来的“事故类型组”特征。

for var in df.columns:
    print(var,'\n', df[var].value_counts()/len(df))

df.drop(['Neurology Payment Flag', 'Neurosurgery Payment Flag', 'Dentist Payment Flag',
         'Psychiatry Payment Flag', 'Hand Surgery Payment Flag', 'Optometrist Payment Flag',
         'Podiatry Payment Flag', 'Accident Type Group str', 'Post Injury Weekly Wage'], axis=1, inplace=True)df.drop(['HCPCS B Codes','HCPCS C Codes', 'HCPCS D Codes', 'HCPCS F Codes', 'HCPCS H Codes', 'HCPCS I Codes',
'HCPCS K Codes', 'HCPCS M Codes', 'HCPCS N Codes', 'HCPCS O Codes', 'HCPCS P Codes',
'HCPCS Q Codes', 'HCPCS R Codes', 'HCPCS S Codes', 'HCPCS T Codes', 'HCPCS U Codes', 
'HCPCS V Codes', 'HCPCS X Codes', 'HCPCS Y Codes', 'HCPCS Z Codes', 'ICD Group 1',
'ICD Group 2', 'ICD Group 3', 'ICD Group 4', 'ICD Group 5', 'ICD Group 7', 'ICD Group 8', 
'ICD Group 9', 'ICD Group 10', 'ICD Group 11', 'ICD Group 12', 'ICD Group 14', 'ICD Group 15', 
'ICD Group 16', 'ICD Group 17', 'ICD Group 20', 'NDC Class - Benzo', 'NDC Class - Misc (Zolpidem)',
'NDC Class - Stimulants'], axis=1, inplace=True)

现在让我们把注意力转向基数或每个特性的唯一值/类别的数量。像“周工资”这样的连续特征无疑会有数百甚至数千个独特的类别。标称和离散特征(即性别和受抚养人人数)的种类数量要少得多。本练习的目标是确定是否有任何类别拥有大多数(90%+)的值。如果一个特性包含一个或两个包含 90%以上值的类别,那么数据中就没有足够的可变性来保留该特性。最终由你来决定截止值,但我们认为 90%或更高是一个安全的假设。

特征特性

现在,我们已经成功地消除了许多由于高度相关性、重复值和缺乏可变性而导致的特征,我们可以专注于检查特征特性并决定如何解决每个问题。

你会注意到,在这一部分,我们只是简单地识别问题并做一个心理记录。我们将不会实际应用讨论的变化,直到笔记本结束到一个功能工程管道。

categorical = ['Benefits State', 'Industry ID', 'Claimant Sex', 'Claimant Marital Status', 'Employment Status Flag', 'RTW Restriction Flag', 'NCCI Job Code', 
'Surgery Flag', 'Disability Status', 'SIC Group', 'NCCI BINatureOfLossDescription', 'Accident Source Code',
'Orthopedic Surgery Payment Flag','Accident Type Group num']discrete = ['Claimant Age', 'Number Dependents', 'Percent Impairment', 'HCPCS A Codes',
'HCPCS E Codes', 'HCPCS G Codes', 'HCPCS J Codes','HCPCS L Codes', 'HCPCS W Codes', 
'ICD Group 6', 'ICD Group 13','ICD Group 18', 'ICD Group 19', 'ICD Group 21', 
'CPT Category - Anesthesia', 'CPT Category - Eval_Mgmt', 'CPT Category - Medicine', 
'CPT Category - Path_Lab', 'CPT Category - Radiology', 'CPT Category - Surgery', 
'NDC Class - Muscle Relaxants']continuous = ['Accident DateID', 'Weekly Wage']df.columns,'Number of Features:',len(df.columns)

缺少值

for var in df.columns:
    if df[var].isnull().sum() > 0:
        print(var, df[var].isnull().mean())

根据我们之前对缺失值的观察,我们发现只有一个要素包含超过 50%的缺失值,而绝大多数要素不包含任何缺失数据。也就是说,我们确实有一些包含缺失数据的要素,我们需要确定如何处理这个问题,因为许多 ML 算法需要完全干净的数据集。这是一个广泛的话题,我们不希望在这个博客中涵盖错综复杂的内容,但读者应该熟悉这个话题。首先,人们必须适应各种类型的缺失数据,如“完全随机缺失”、“随机缺失”和“非随机缺失”。这些主题有助于确定应该如何以及何时处理丢失的数据。此外,进一步解读插补技术,如均值/中值/众数、任意值插补、添加缺失数据指标、随机样本插补、最大似然插补等。将提供一个很好的概述。

我们有 9 个缺失数据的特征。对于缺失值少于 5%的特征(即申请人性别、申请人婚姻状况、就业状况标志、环球旅行限制标志)我们将用其分布模式替换缺失值。由于缺失值的百分比较低,模式插补不会对分布造成太大的改变。“事故日期”是我们唯一具有缺失数据的连续特征,我们将使用任意数字-99999 来估算缺失值。所有其他特征本质上都是分类的,由于它们有超过 5%的缺失值,我们将用字符串“missing”来估算缺失值。这最终不会改变发行版,只会给他们的发行版增加一个新的类别。

事故日期 ID:连续 w/ -99999
索赔人性别:分类 w/模式
索赔人婚姻状况:分类 w/模式
就业状况标志:分类 w/模式
RTW 限制标志:分类 w/模式
残疾状况:分类 w/‘失踪’
NCCI binatureofloss 描述:分类 w/‘失踪’
事故来源代码:分类 w/‘失踪’
事故类型组号:分类 w/‘失踪’

分类和离散特征的基数

for var in categorical:
    print(var, 'has', df[var].nunique(), 'unique categories')

for var in discrete:
    print(var, 'has', df[var].nunique(), 'unique categories')

for var in categorical:
    print(df[var].nunique(),(df.groupby(var)[var].count()/len(df)))

for var in discrete:
    print(var, 'has', df[var].nunique(), 'unique categories')

在上一节中,我们查看了基数,以便删除可变性低的特性(即具有包含大部分数据的类别的特征)。我们需要更深入地检查基数,并识别“稀有”类别。换句话说,哪些类别只包含非常小百分比的数据(=<1%)。我们将把所有的类别聚合成一个“稀有”的类别,从而减少每个特性的基数,简化模型。当我们讨论编码分类和离散特征时,这种方法将非常有用。

例如,功能“就业状态标志”目前有 13 个类别(包括 np.nan ),但正如您所见,“F =全职”和“P =兼职”类别几乎占了数据的 96%。所有其他类别仅出现 0.5%的时间,它们都将被汇总为“罕见”类别。任何类别出现次数少于 1%的分类或离散特征都将这些类别编码为“稀有”。

分布和异常值

该数据集仅包含两个连续特征“事故日期”和“周工资”。我们需要确定这些特征是否包含偏斜分布,以及它们是否包含任何异常值。

for var in continuous:
    plt.figure(figsize=(10,5))
    plt.subplot(1,2,1)
    fig = df.boxplot(column=var)
    fig.set_title('outliers')
    fig.set_ylabel(var)

    plt.subplot(1,2,2)
    fig = df[var].hist(bins=20)
    fig.set_ylabel('number of cases')
    fig.set_xlabel(var)

    plt.show()

这两个特征当然保持了偏态分布,但只有“周工资”包含任何异常值。最大似然算法对数据有某些假设,我们需要遵循这些假设来增加它们的预测能力。例如,线性回归假设预测值和目标值之间的关系是线性的(线性)。它还假设数据中没有异常值。对于高度相关的要素(多重共线性),这尤其困难。最后,它假设您的要素呈正态分布。

正态分布的要素遵循高斯分布,您可能还记得高中统计课程中的类似钟形的分布。如你所见,“事故日期”和“周工资”都不是正态分布的。有几种常用的方法来修复偏斜分布,如对数、倒数、平方根、box-cox 和 yeo-johnson 变换。

df_copy = df.copy()df_copy['Accident DateID'].skew(skipna = True)df_copy['Accident DateID_log'] = df_copy['Accident DateID'].map(lambda x: np.log(x))df_copy['Accident DateID_rec'] = df_copy['Accident DateID'].map(lambda x: np.reciprocal(x))df_copy['Accident DateID_sqrt'] = df_copy['Accident DateID'].map(lambda x: np.sqrt(x))df_copy['Accident DateID_log'].skew(skipna = True)
df_copy['Accident DateID_rec'].skew(skipna = True)
df_copy['Accident DateID_sqrt'].skew(skipna = True)df['Accident DateID_rec'] = df['Accident DateID'].map(lambda x: np.reciprocal(x))df.drop(['Accident DateID'], axis=1, inplace=True)

“事故日期”的校正偏差如下:

事故日期:0.137

事故日期 _ 日志:0.111

事故日期 _ 记录:0.00

事故日期 ID_sqrt: 0.124

我们可以看到“事故日期”的初始偏差为 0.137,从技术上讲,这并不是很大的偏差,因为正态分布的偏差为零(0)。也就是说,应用倒数变换将我们的偏斜调整为零(0)。

def diagnostic_plot(df, variable):
    plt.figure(figsize=(16, 4))
    sns.distplot(df[variable], bins=30)
    plt.title('Histogram')diagnostic_plot(df_copy, 'Accident DateID_rec')

df_copy['Weekly Wage'].skew(skipna = True)df_copy['Weekly Wage_log'] = df_copy['Weekly Wage'].map(lambda x: np.log(x) if x > 0 else 0)df_copy['Weekly Wage_rec'] = df_copy['Weekly Wage'].map(lambda x: np.reciprocal(x) if x > 0 else 0)df_copy['Weekly Wage_sqrt'] = df_copy['Weekly Wage'].map(lambda x: np.sqrt(x))
df_copy['Weekly Wage_log'].skew(skipna = True)
df_copy['Weekly Wage_rec'].skew(skipna = True)
df_copy['Weekly Wage_sqrt'].skew(skipna = True)df['Weekly Wage_sqrt'] = df['Weekly Wage'].map(lambda x: np.sqrt(x))df.drop(['Weekly Wage'], axis=1, inplace=True)

修正后的“周工资”偏差如下:

周工资:2.57 英镑

周工资 _ 日志:-3.74

周工资 _ 收入:54.37 英镑

周工资 _sqrt: 0.407

“周工资”的初始偏差要大得多,为 2.56,但平方根变换使偏差显著下降(0.40)。

现在我们已经修复了偏斜度,让我们来解决位于“Weekly Wage_sqrt”中的异常值,因为我们已经放弃了原来的特性。由于“周工资 _sqrt”呈正态分布,我们可以使用“平均值的 3 倍标准差”规则来识别异常值。如果您的分布是偏态的,您最好先计算分位数,然后计算 IQR 来确定您的上下边界。

值得注意的是,连续特征,如“事故日期”和“每周工资 _sqrt”通常可以从离散化或宁滨中受益。离散化需要将特征值分成组或箱。这种方法也是处理异常值的有效方法,因为它们通常更接近分布的平均值。这将最终将特征从连续变为离散,因为最终结果将是每个箱中的观察数量(即 0–1000、1000–2000、2000–5000 等。).

def find_boundaries(df, variable):# calculate the boundaries anything outside the upper and lower boundaries is an outlier
    upper_boundary = df[variable].mean() + 3 * df[variable].std()
    lower_boundary = df[variable].mean() - 3 * df[variable].std()return upper_boundary, lower_boundaryupper_boundary, lower_boundary = find_boundaries(df, 'Weekly Wage_sqrt')upper_boundary, lower_boundary

上限为 51.146,下限为-0.763。换句话说,任何超出这些边界的值都将被视为异常值。请注意,我们使用三(3)标准偏差规则来确定异常值。我们可以将该值更改为 2,我们的边界会缩小,从而导致更多的异常值。

print('We have {} upper boundary outliers:'.format(len(df[df['Weekly Wage_sqrt'] > upper_boundary])))print('We have {} lower boundary outliers:'.format(len(df[df['Weekly Wage_sqrt'] < lower_boundary])))

# Identify the outliers in 'weekly wage_sqrt'
outliers_weekly_wage = np.where(df['Weekly Wage_sqrt'] > upper_boundary, True, np.where(df['Weekly Wage_sqrt'] < lower_boundary, True, False))# trim the df of the outliers
df = df.loc[~(outliers_weekly_wage)]

不平衡的目标分布

df['Opiods Used'].value_counts()/len(df)

我们的目标是“使用过的 Opiods ”,和大多数分类问题一样,就纯粹的数量而言,错误类往往占大多数。正如你在上面看到的,几乎 90%的案例都是假的或者没有滥用阿片类药物。一些最大似然算法如决策树倾向于使它们的预测偏向多数类(即在我们的情况下为假)。有许多技术可以用来解决这个问题。过采样是一种尝试将少数类的随机副本添加到数据集直到不平衡消除的技术。欠采样与过采样相反,因为它需要移除多数类观测值。主要的缺点是删除数据的想法会导致模型的欠拟合。最后但同样重要的是,合成少数过采样技术(SMOTE)使用 KNN 算法生成新的观测值来消除不平衡。我们将在这个用例中使用 SMOTE 技术来生成新的(合成的)观察结果。

需要注意的是,所使用的任何技术都应该仅用于生成或消除训练集中的观察值。

预处理流水线

我们需要将我们的数据分成训练和测试数据集,但首先让我们将我们的特征转换成适当的格式,以便符合我们管道的要求。

df[discrete] = df[discrete].astype('O')
df['Industry ID'] = df['Industry ID'].astype('O')
df['Surgery Flag'] = df['Surgery Flag'].astype('O')
df['Accident Source Code'] = df['Accident Source Code'].astype('O')
df['Orthopedic Surgery Payment Flag'] = df['Orthopedic Surgery Payment Flag'].astype('O')
df['Orthopedic Surgery Payment Flag'] *= 1
df['Opiods Used'] *= 1X_train, X_test, y_train, y_test = train_test_split(
    df.drop('Opiods Used', axis=1),
    df['Opiods Used'],
    test_size=0.3,
    random_state=SEED)

为了简化缺失数据、稀有值、基数和编码的数据处理任务,我们将利用 Scikit-Learn 的 make_pipeline 库。管道允许我们将多个进程应用到一段代码中,这段代码将依次运行每个进程。使用管道使我们的代码更容易理解,可重复性更好。

**# Imputing missing values for continuous features with more than 5% missing data with -99999.**
feature_transform = make_pipeline(mdi.ArbitraryNumberImputer(arbitrary_number = -99999, variables='Accident DateID_rec'),

**# Imputing categorical (object) features w/ more than 5% of nulls as 'missing'** mdi.CategoricalVariableImputer(variables=['Disability Status',
'NCCI BINatureOfLossDescription','Accident Source Code','Accident Type Group num'], imputation_method='missing'),

**# Imputing categorical features w/less than 5% of missing values with the mode** mdi.CategoricalVariableImputer(variables=['Claimant Sex', 'Claimant Marital Status','Employment Status Flag','RTW Restriction Flag'],
imputation_method='frequent'),

**# Encoding rare categories for categorical and discrete features (Less than 1% is rare)** ce.RareLabelCategoricalEncoder(tol=0.01, n_categories=6, 
variables=['Benefits State', 'Industry ID', 'NCCI Job Code','Employment Status Flag', 'SIC Group', 'NCCI BINatureOfLossDescription','Accident Type Group num', 'Claimant Age', 'Number Dependents', 'Percent Impairment', 'HCPCS A Codes', 'HCPCS E Codes', 'HCPCS G Codes', 'HCPCS J Codes', 'HCPCS L Codes','HCPCS W Codes', 'ICD Group 6', 'ICD Group 13','ICD Group 18', 'ICD Group 19', 'ICD Group 21','CPT Category - Anesthesia', 'CPT Category - Eval_Mgmt','CPT Category - Medicine', 'CPT Category - Path_Lab','CPT Category - Radiology', 'CPT Category - Surgery', 
'NDC Class - Muscle Relaxants']),

**# We will use one_hot_encoding for categorical features**
ce.OneHotCategoricalEncoder(variables=['Benefits State', 'Industry ID', 'Claimant Sex','Claimant Marital Status','Employment Status Flag','RTW Restriction Flag','Disability Status','SIC Group','NCCI Job Code','NCCI BINatureOfLossDescription','Accident Source Code','Accident Type Group num'],drop_last=True),

**# We are going to use ordinal encoding according to the target mean to the target feature** ce.OrdinalCategoricalEncoder(encoding_method='ordered',variables=['Claimant Age','Number Dependents','Percent Impairment','HCPCS A Codes', 'HCPCS E Codes','HCPCS G Codes','HCPCS J Codes', 'HCPCS L Codes', 'HCPCS W Codes','ICD Group 6', 'ICD Group 13', 'ICD Group 18', 'ICD Group 19','ICD Group 21', 'CPT Category - Anesthesia', 
'CPT Category - Eval_Mgmt','CPT Category - Medicine','CPT Category - Path_Lab','CPT Category - Radiology','CPT Category - Surgery','NDC Class - Muscle Relaxants']))

我们的数据处理管道广泛使用了“特征引擎”库。我们可以使用 Scikit-Learn 来完成这些任务,但是我们想指出的是,feature-engine 具有某些优势。首先,基于 scikit-learn、pandas、numpy 和 SciPy 构建的 feature-engine 能够返回 pandas 数据帧,而不是像 scikit-learn 那样返回 Numpy 数组。其次,特征引擎转换器能够学习和存储训练参数,并使用存储的参数转换您的测试数据。

关于特征引擎已经说得够多了,让我们更详细地讨论一下管道。理解流水线中的步骤是连续运行的,从顶部的变压器开始,这一点很重要。学生通常会犯这样的错误,即应用第一步最终会改变数据的结构或第二步无法识别的特征的名称。

第一个转换器“ArbitraryNumberImputer”使用值-99999 对丢失数据超过 5%的连续要素进行估算。第二个转换器“CategoricalVariableImputer”使用字符串值“missing”对缺失数据超过 5%的分类数据进行估算。第三个转换器“FrequentCategoryImputer”用特征的模式估算缺失数据少于 5%的分类数据。第四个转换器“RareLabelCategoricalEncoder”将出现时间不到 1%的分类和离散特征观察值编码到一个名为“稀有”的新类别中。

第五个转换器“OneHotCategoricalEncoder”将每个分类要素的每个唯一值转换为存储在新要素中的二进制形式。比如“性别”有“M”、“F”、“U”的值。一个热编码将产生三个(或两个“k-1”取决于您的设置)新功能(即性别 _M,性别 _F,性别 _U)。如果在原始“性别”特征下观察值为“M ”,则“性别 _M”的值为 1,“性别 _F”和“性别 _U”的值为 0。由于这种方法极大地扩展了特征空间,现在您理解了为什么将稀有观察值(< 1%)归类为“稀有”非常重要。

最终的转换器“OridinalCategoricalEncoder”专门用于对离散特征进行编码,以保持它们与目标特征的有序关系。利用该编码器将会为测试集中存在的、没有在训练集中编码的类别生成缺失值或抛出错误。这也是在编码序数/离散特征之前处理稀有值的另一个原因。为了更好地理解这个顺序编码器,让我们检查一下“申请人年龄”特性。我们有三个潜在值“F”,“M”和“U”。让我们假设“F”的阿片类药物滥用率平均为 10%,“M”为 25%,“U”为 5%。编码器将根据他们平均阿片类药物滥用的程度将“M”编码为 1,“F”编码为 2,“U”编码为 3。

注意扩展到 155 个特征的特征空间

feat_transform.fit(X_train, y_train)
X_train_clean = feat_transform.transform(X_train)
X_test_clean = feat_transform.transform(X_test)X_train_clean.head()

接下来,将管道安装到 X_train 和 y_train 上,并转换 X_train 和 X_test。请注意,我们的特征空间已经大大增加到 155 个特征,这是由于我们对分类特征使用了一次性编码器。

特征缩放

最后,我们必须缩放特征,以使它们的所有值都在相同的范围或量级上。这个步骤必须完成,因为一些 ML 分类器使用欧几里德距离,并且具有更高幅度或范围的特征将对预测有更大的影响。例如温度,32 华氏度等于 273.15 开尔文,如果我们在模型中使用这两个特征,开尔文将具有更大的权重或影响预测。

scaler = StandardScaler()
scaler.fit(X_train_clean)X_train_std = scaler.transform(X_train_clean)
X_test_std = scaler.transform(X_test_clean)

X_train_std_df = pd.DataFrame(X_train_std, columns=col_names)
X_test_std_df = pd.DataFrame(X_test_std, columns=col_names)

基线模型

models = []
models.append(('log_reg', LogisticRegression(max_iter=10000, random_state=42)))
models.append(('rf_classifer', RandomForestClassifier(random_state=42)))
models.append(('bayes', GaussianNB()))
models.append(('gbc', GradientBoostingClassifier()))base_model_train = []
base_model_test = []for name, classifier in models:
    scores = cross_val_score(classifier, X_train_std_df, y_train, cv=5, scoring='recall')
    base_model_train.append(scores.mean().round(4))
    print(scores)
    print('{}: Avg CV recall using all features on training data: {}'.format(name, scores.mean().round(4)))

    classifier.fit(X_train_std_df, y_train)
    y_preds = classifier.predict(X_test_std_df)
    test_recall = recall_score(y_test, y_preds, average='binary')
    test_class = classification_report(y_test, y_preds)
    cnf_matrix = confusion_matrix(y_test, y_preds)
    base_model_test.append(test_recall.round(4))
    print('{}: Recall w/all features on test data {}:'.format(name, test_recall.round(4)))
    print(test_class)
    print(cnf_matrix)
    print('-------------------------------------------------------')

我们将比较四个不同分类器的相对召回分数。我们使用召回是因为我们想尽量减少假阴性(即滥用阿片类药物但预测不会滥用)。首先,我们希望建立一个基线,可以与分类器的额外迭代进行比较,以确定相对的改进。基线模型包括具有不平衡目标的整个特征空间。为了正确评估我们的分类器,我们将使用仅应用于训练数据集的 5 重分层交叉验证,从而大大减少数据泄漏。换句话说,每个分类器将在训练数据的五个唯一分割上被训练和测试 5 次。将为每个分类器计算五个独特的召回分数,并一起平均以产生最终召回分数。分类器在训练期间不会“看到”任何测试数据。最后,每个分类器将在保留的测试数据集上进行测试,以确定可推广性和过度拟合。

逻辑回归、随机森林和梯度推进分类器已经实现了很高的整体准确性。然而,朴素贝叶斯设法实现了最高的召回率,因为它只有 331 个假阴性预测。

如果您希望阅读有关分类指标的更多信息( 链接)

模型 1:完整的功能集和平衡的 SMOTE

sm = SMOTE(sampling_strategy='auto', k_neighbors=5, random_state=42)
X_train_std_sm, y_train_sm = sm.fit_resample(X_train_std_df, y_train)model1_train = []
model1_test = []for name, classifier in models:
    pipeline = make_pipeline(sm, classifier)
    scores = cross_val_score(pipeline, X_train_std_df, y_train, cv=5, scoring='recall')
    model1_train.append(scores.mean().round(4))
    print(scores)
    print('{}: Avg CV Recall w/All Reatures: {}'.format(name, scores.mean().round(4)))

    classifier.fit(X_train_std_sm, y_train_sm)
    y_preds = classifier.predict(X_test_std_df)
    test_recall = recall_score(y_test, y_preds)
    test_class = classification_report(y_test, y_preds)
    cnf_matrix = confusion_matrix(y_test, y_preds)
    model1_test.append(test_recall.round(4))
    print('{}: Recall w/All Features on test data {}:'.format(name, test_recall.round(4)))
    print(test_class)
    print(cnf_matrix)
    print('-------------------------------------------------------')

不平衡的目标给我们的预测强加了偏见。正如预期的那样,逻辑回归得到了很大的改进,因为该算法在平衡目标的情况下表现得更好。

谈 SMOTE 及其方法论。如果你还记得我们最初对数据集的检查,目标变量是不平衡的。与导致阿片类药物滥用的观察结果(10%)相比,我们有更多未导致阿片类药物滥用的观察结果(89%)。我们还决定使用 SMOTE 方法,因为它创建了少数类的新的合成观测值,而不是复制现有的观测值。SMOTE 使用 KNN(通常 k=5 ),其中从少数类中选择一个随机观察值,并找到最近邻居的 k 。然后,随机选择 k 个邻居中的一个,并且从原始观察和随机选择的邻居之间的随机选择的点构建合成样本。

特征选择

随机森林特征重要性

自然语言处理和物联网等领域的现代数据集通常是高度多维的。看到数千甚至数百万个特征并不罕见。知道如何将特征缩小到选定的几个,不仅增加了我们找到可概括模型的机会,还减少了我们对昂贵的计算能力的依赖。通过精确减少数据中的特征/维度数量,我们最终从数据中去除了不必要的噪声。

值得注意的是,特征选择不仅包括特征空间的缩减,还包括特征创建。了解如何发现数据集中的趋势和要素之间的关系(即多项式特征)需要多年的实践,但在预测能力方面有很大的好处。有整个大学的课程致力于特性选择/工程,但那些对这个主题更感兴趣的人请研究过滤器、包装器和嵌入式方法作为介绍。

Scikit-Learn 的 RandomForestClassifier 具有“feature_importances_”属性,该属性用于确定数据集中每个要素的相对重要性。由于随机森林在平衡目标下往往表现更好,我们将使用 SMOTE 平衡 X_train_std_sm 和 y_train_sm 数据集。

rf_selector = RandomForestClassifier(n_estimators=100, random_state=SEED, n_jobs=-1)rf_selector.fit(X_train_std_sm, y_train_sm)feature_imp = pd.Series(rf_selector.feature_importances_, index=X_train_std_df.columns).sort_values(ascending=False)feature_imp[:30]

30 大特性

sum(feature_imp[0:30]

我们能够将大多数原始特性减少到 30 个,这占了性能差异的 91 % 。任何额外的特征只会增加非常小的额外预测能力。

X_train_rf = X_train_std_df[feature_imp[:30].index]
X_test_rf = X_test_std_df[feature_imp[:30].index]plt.figure(figsize=(12,8))
sns.barplot(x=feature_imp[0:30], y=feature_imp.index[0:30])
plt.xlabel('Feature Importance Score')
plt.ylabel('Features')
plt.title("Visualizing Important Features")
plt.grid(b=False, which='major', color='#666666', linestyle='-', alpha=0.2)
plt.show()

模型 2:射频特征和不平衡目标

models = []
models.append(('log_reg', LogisticRegression(max_iter=10000, random_state=42)))
models.append(('rf_classifer', RandomForestClassifier(random_state=42)))
models.append(('bayes', GaussianNB()))
models.append(('gbc', GradientBoostingClassifier()))model2_train = []
model2_test = []for name, classifier in models:
    scores = cross_val_score(classifier, X_train_rf, y_train, cv=5, scoring='recall')
    model2_train.append(scores.mean().round(3))
    print(scores)
    print('{}: Avg CV Recall on RF Features: {}'.format(name, scores.mean().round(3)))

    classifier.fit(X_train_rf, y_train)
    y_preds = classifier.predict(X_test_rf)
    test_recall = recall_score(y_test, y_preds, average='binary')
    test_class = classification_report(y_test, y_preds)
    cnf_matrix = confusion_matrix(y_test, y_preds)
    model2_test.append(test_recall.round(3))
    print('{}: Recall w/RF features on test data {}:'.format(name, test_recall.round(3)))
    print(test_class)
    print(cnf_matrix)
    print('-------------------------------------------------------')

模型 3: RF 特性和平衡 w/SMOTE

X_train_rf_sm, y_train_sm = sm.fit_resample(X_train_rf, y_train)models = []
models.append(('log_reg', LogisticRegression(max_iter=10000, random_state=42)))
models.append(('rf_classifer', RandomForestClassifier(random_state=42)))
models.append(('bayes', GaussianNB()))
models.append(('gbc', GradientBoostingClassifier()))sm = SMOTE(sampling_strategy='auto', k_neighbors=5, random_state=42)
skf = StratifiedKFold(n_splits=5)model3_train = []
model3_test = []for name, classifier in models:
    pipeline = make_pipeline(sm, classifier)
    scores = cross_val_score(pipeline, X_train_rf, y_train, cv=skf, scoring='recall')
    model3_train.append(scores.mean().round(3))
    print(scores)
    print('{}: Avg CV Recall w/RF Reatures: {}'.format(name, scores.mean().round(3)))

    classifier.fit(X_train_rf_sm, y_train_sm)
    y_preds = classifier.predict(X_test_rf)
    test_recall = recall_score(y_test, y_preds, average='binary')
    test_class = classification_report(y_test, y_preds)
    cnf_matrix = confusion_matrix(y_test, y_preds)
    model3_test.append(test_recall.round(3))
    print('{}: Recall w/RF on test data {}:'.format(name, test_recall.round(3)))
    print(test_class)
    print(cnf_matrix)
    print('-------------------------------------------------------')

摘要

classifiers = ['Log_Regression', 'Random_Forest', 'Naive_Bayes', 'Gradient_Boosting_clf']idx = ['All_Feat_Imbalance_Train', 'All_Feat_Imbalance_Test','All_Feat_Smote_Train',
'All_Feat_Smote_Test','RF_Imbalance_Train', 
'RF_Imbalance_Test','RF_Smote_Train','RF_Smote_Test']combined_results = pd.DataFrame([base_model_train,base_model_test,
model1_train, model1_test, model2_train,
model2_test, model3_train, model3_test],
columns=classifiers, index=idx)test_results = pd.DataFrame([base_model_test, model1_test, model2_test, model3_test], columns=classifiers, index=idx[1:8:2])print(test_results)

plt.figure(figsize=(15,10))
sns.lineplot(data=test_results[['Log_Regression', 'Random_Forest',
                             'Naive_Bayes', 'Gradient_Boosting_clf']])
plt.xlabel('Iterations', fontsize=17, labelpad=15)             
plt.ylabel('Recall Scores', fontsize=17, labelpad=15)
plt.title('Classifier Recall Scores on Test Data',fontsize=25, pad=15)
plt.show()

特征的减少导致召回性能的轻微下降。这是意料之中的,因为仅使用 30 个特性就造成了 91%的性能差异。增加功能的数量肯定会提高召回率。只有朴素贝叶斯没有受到特征减少的影响。其次,我们数据集中的不平衡也影响了分类器的召回性能。一般来说,一旦不平衡得到纠正,大多数分类器都会提高它们的性能。逻辑回归受不平衡的影响最大。

就整体分类器性能而言,必须说所有分类器在特征减少以及目标平衡的情况下表现最佳。当然,有人可能会认为朴素贝叶斯表现最好,因为它设法实现了最好的测试召回率(0.949),但我会认为是逻辑回归胜过了领域。它实现了非常相似的召回率 0.945,相比之下,朴素贝叶斯的召回率为 0.949,而朴素贝叶斯仅解释了 14%的假阴性增加。更令人印象深刻的是,与朴素贝叶斯相比,它多了 2276 个正确的真阴性预测。在下一节中,我们将尝试超参数调优,看看我们能否提高逻辑回归模型的分类召回率。

具有 RF 特征和 SMOTE 的逻辑回归

超参数调谐

什么是超参数?

认为超参数是“调谐”旋钮。想象你正在编辑一张图片,以达到某种效果。您可以使用曝光、高光、阴影、对比度、亮度、饱和度、温暖度、色调等“旋钮”来调节画面。好吧,超参数是相同类型的“旋钮”,但用于分类器。

除了求解器、惩罚和 c 之外,逻辑回归没有太多的超参数需要调整。

解算器试图优化参数权重或θ,这将引出最小误差或成本函数。Sklearn 自带了几个解算器:newton-cg,lbfgs,liblinear。

惩罚参数也被称为“正则化”,其目的是帮助模型避免过度拟合训练数据,从而产生更通用的模型。它通过“惩罚”被认为是噪声或对模型贡献很小的特征来做到这一点。

  • L1 惩罚或套索:将惩罚的绝对幅度或特征的权重之和添加到成本函数中。L1 将噪声特征减少到零,从而简化了模型。
  • L2 惩罚或岭:将惩罚的平方幅度或特征权重的平方和添加到成本函数中。L2 也降低了噪声特征的影响,但是它们的权重或θ非常接近于零,但并不完全是零。

最后,“C”参数决定正则化惩罚的强度。C 参数越大,正则化程度越低,模型变得越复杂,过拟合增加。C 参数越小,应用的正则化越多,欠拟合增加。

clf_lr = LogisticRegression(max_iter=10000, random_state=SEED)penalty = ['l1','l2']
C = [0.001,0.002,0.003,0.005,1,10,100,1000]skf = StratifiedKFold(n_splits=5)
pipeline = make_pipeline(sm, clf_lr)
param_grid = dict(logisticregression__penalty=penalty,
                  logisticregression__C=C)grid = GridSearchCV(pipeline, 
                    param_grid=param_grid,
                    scoring='recall', 
                    verbose=1, cv=skf)grid_results = grid.fit(X_train_rf, y_train) 
print('Best Score: ', grid_results.best_score_)
print('Best Params: ', grid_results.best_params_)

X_train_rf_sm, y_train_sm = sm.fit_resample(X_train_rf, y_train)
clf_lr = LogisticRegression(max_iter=10000, penalty='l2', C=0.0001, random_state=42)clf_lr.fit(X_train_rf_sm, y_train_sm)
y_preds = clf_lr.predict(X_test_rf)
test_recall = recall_score(y_test, y_preds).round(3)
test_class = classification_report(y_test, y_preds)
cm = confusion_matrix(y_test, y_preds)print('Log Regression Recall w/RF on test data {}:'.format(test_recall.round(3)))
print(test_class)
print(cm)

为了减少训练时间和警告数量,我们将重点调整“惩罚”和“C”参数。不仅要了解每个超参数的作用,还要了解参数之间如何相互作用,这对它们的调整至关重要。此外,调整过程通常是迭代的,因为我们从每个参数的宽范围开始,然后开始缩小范围,直到选择特定的参数值。

GridSearchCV 应用了一种穷举方法,因为它考虑了所提供参数的所有组合。由于平衡目标在分类器评估期间产生了最佳的召回,我们选择将其与传递到 gridsearchcv 的对数回归分类器一起包含到我们的管道中。这样,每个交叉验证训练/测试分割仅与其数据平衡。换句话说,在交叉验证期间,SMOTE 和分类器都没有遭受数据泄漏。

不幸的是,我们没有增加我们的训练召回率,但是我们能够将我们的测试召回率从 0.945(对数回归 w/RF 特征和 SMOTE)增加到 0.954。此外,我们将假阴性计数减少了 42。我们的假阳性计数增加了 269,但是再一次,当你实际上没有使用阿片类药物时,预测使用阿片类药物更好。

结论

作为一名数据科学家,理解数据科学分类问题的全部本质是你走向成熟的关键。我希望你发现这个教程信息丰富,容易理解。我欢迎任何反馈和建议,因为我们都只是在磨练我们的手艺。

所有代码都可以在我的 GitHub 上找到。链接

二元分类模型:澳大利亚信贷审批

原文:https://towardsdatascience.com/binary-classification-model-australian-credit-approval-977ad7738411?source=collection_archive---------43-----------------------

预测信贷决策的二元分类器的 Python 实现。

作为我不断提高数据科学技能的努力的一部分,我在 UCI 机器学习知识库的随机数据集上建立机器学习模型。你可以在这里查看我以前的车型

纽约公共图书馆在 Unsplash 拍摄的照片

在这个挑战中,要解决的随机数据集是 澳大利亚信贷审批数据集。 如果你想跟随或者自己尝试数据集,你可以 下载 我已经清理过的 CSV 版本。

这些随机挑战的额外任务之一是将原始数据格式化为有用的 CSV 格式。因此,我将在我的 GitHub 上留下清理过的数据集的链接。

关于数据集:

数据集由 14 个特征变量和 1 个量化批准决定的类别标签组成。为了保密和便于处理统计算法,对 14 个特征本身知之甚少。

这意味着甚至特征名称都不存在,但是它们是连续的还是分类的是已知的。我同样标记了哪些列是连续的(N)、分类的(C)以及它们是否需要在数据集中进一步编码(C_enc)。

构建二元分类模型来预测信贷是被批准给特定客户还是被拒绝是非常简单的。

它包括:

数据预处理:一次热编码&标准化

构建分类器+评估模型性能:

查看每列直方图的类可分性:

下面的代码用每个独立变量和类标签绘制了一个直方图。这是为了辨别每个单独的变量在多大程度上可以解释类别的分离。

可以看出,几乎所有变量本身都不能解释批准决定。这意味着目标变量依赖于所有变量的非线性组合。下面是实现相同功能的代码。

度量&决定剧情:

以下是在测试集上评估时模型的精确度、10 倍交叉验证精确度的平均值和标准偏差。

模型精度

10 倍交叉验证后的准确度平均值

10 倍交叉验证后准确度范围内的标准偏差

此外,以下是如何用 seaborn 绘制决策计数图。该图有助于直观地显示已经提交了多少拒绝和批准。首先,您必须为绘图构建一个单独的数据框。

pred = list()
reject_count = approved_count = 0for i in range(len(y_pred)):
    if y_pred[i] == 0:
        pred.append('Rejections')
    else:
        pred.append('Approvals')pred = pd.DataFrame(pred)
pred.columns = ['Decisions']# Visualization of Decision Counts
plt.Figure(figsize = (8, 8))
sb.set_style('darkgrid')sb.countplot(pred['Decisions'], data = pred, edgecolor = 'black', linewidth=1.5, palette = 'dark')plt.title('Predicted Credit Approvals')
plt.xlabel('Approval Decision')
plt.ylabel('Count')
plt.show()

批准决定的计数图

原来如此。虽然这是一个简单的算法,模型的准确率高达 89%,但你可以看到变量之间的相关性是高度非线性的。

如果你有关于改进模型的建议,或者你可能会用不同的方式来处理它,请在下面的评论中留下。

感谢您的阅读,祝您愉快,我们会再见的。

灾难微博的二元分类

原文:https://towardsdatascience.com/binary-classification-of-disaster-tweets-73efc6744712?source=collection_archive---------39-----------------------

预测哪些推文是关于真实灾难的,哪些不是。

照片由 Yosh Ginsu 在 Unsplash 上拍摄

近年来,社交媒体因其在时空事件中的潜在用途而受到广泛关注。Twitter 是其中之一,它已经成为不同情况下的重要沟通渠道,例如在紧急情况下。智能手机使人们能够实时宣布他们看到的紧急情况。正因为如此,越来越多的机构对监控 Twitter 感兴趣(例如,救灾组织)。这项工作背后的想法是,我们可以从大量的推文中提取有用的摘要,这在灾难情况下可能是有用的。

数据集可以从这里下载。我们有 7613 条观察结果,我们正在预测一条给定的推文是否是关于一场真正的灾难。如果是,预测一个 1。如果没有,预测 0。功能及其描述如下所述。

id -每条推文的标识符

  • text -推文的文本
  • location——推文发出的地点(可能是南)
  • keyword -推文中的特定关键词(可能是 NaN)
  • target——判断一条推文是否是关于一场真正的灾难(1)的输出结果(0)

但是我们如何分析这类问题呢?

数据

让我们看看数据集中包含的要素:

There are 7613 observations and 5 features in this dataset.

如图所示,该数据集由 7613 条评论组成。在这个数据集中有五种不同的特性,但是我们只分别使用“文本”和“目标”列作为输入/输出。现在,让我们看看数据集中包含的要素:

在关键字和位置列中有许多丢失的值,但是我们不需要担心它们。为了使我们的生活更容易,我们需要清除文本特征中的噪声。我们将在下面的部分中讨论它。

数据探索

如果我们将灾难性推文的数量与非灾难性推文的数量对比如下,很明显数据集是不平衡的。

为了解决这个问题,我们将使用分层抽样,其中数据集被划分为称为地层的同质子组,并且从每个地层中抽样正确数量的实例,以保证测试集能够代表总体。我们可以看到,训练和测试数据集都有近 41%的灾难推文。分层抽样的代码如下。

训练和测试数据集不平衡。但是有几种方法可以处理不平衡的数据集,如过采样和欠采样。幸运的是,这里的许多应用算法可以为您解决这个问题。有一个名为“ class_weight ”的超参数使用目标的值来自动调整与数据集中的类频率成反比的权重。

让我们看看熊猫的每个特征的类型。info()函数,它也可以让您对特性有一个大致的了解。了解每一列是否有任何缺失值会很有帮助,这样您将能够有效地处理它。

train.info()

由于我们只处理两列,即(“文本”和“目标”),并且没有缺失值,因此我们不需要移除任何观察值或使用插补转换器来完成缺失值。

文本表示

下面显示了几条推文。请记住,我们将使用它们来预测是否有灾难推文。究竟什么能帮助我们去掉多余的单词、数字等。不会给文本增加任何价值,例如,标签、https、数字。因此,我们将删除干扰我们的文本分析的字符数字和文本片段。

使用下面的代码,我删除了数字、非 ASCII 字符、标点符号和 https,并将所有文本改为小写。

下面,你可以看到几个干净的文本,我们将用于文本分析。

我们的目标是找到输入和输出之间的关系。我使用“已清理”特征作为输入,使用“目标”作为输出。所以我的第一步是把推文转换成矢量。

我们需要将 tweets 转换为令牌计数矩阵,以便从文本内容中提取数字特征。这样,计数的稀疏表示就产生了。这是非常有益的,因为你可以想象独特的映射词到向量创建一个矩阵的巨大规模。CountVectorizer 用于此目的,它可以按如下方式导入。

**from** **sklearn.feature_extraction.text** **import** CountVectorizer

有许多像“the”、“them”、“are”这样的词对上下文的意思没有任何影响,这些词被称为停用词。它们不提供信息,可以通过选择 step_words='english '作为 CountVectorizer 函数中的超参数来删除。

下一步是使用 tf-idf 表示来规范化计数矩阵。标准化频率而不是使用原始频率的主要原因是为了减少在文本中出现几次的标记的影响,并且没有出现几次的标记信息量大。例如,单词“document”在给定的语料库中出现一千次,而“awesome”出现两次。tf-idf 在这种情况下工作,就像预处理数据,将原始特征向量变成更适合机器学习算法的表示。

**from** **sklearn.feature_extraction.text** **import** TfidfTransformer

管道

我使用管道功能来完成所有步骤。顺序应用变换列表和最终估计器。因此,它开始询问 CountVectorizer 和 Tfidf。您可以拥有管道工作所需的任意数量的变压器。

我只在“cleaned”特性上应用了管道,因为目标是二进制的。

模型评估

我使用了 20%的数据进行测试,其余的用于训练。这里涉及到很多超参数。因此,你的工作就像一个建筑师,寻找最佳的价值,以最大限度地提高准确性。一些技术是有益的,包括 Hyperopt、GridSearchCV 和 RandomizedSearchCV。在这个问题中,我随机选取了超参数。

我使用了下面代码片段中提到的十二种不同的监督算法。曲线下面积(AUC)分数和训练时间用于比较。

一个接一个地,每个监督算法都在训练数据集上训练,然后在测试数据集上推广。最后,根据 AUC 值对结果进行排序。还显示了每种方法的培训时间。我已经用这个内核写下了下面的分类代码。

我们可以看到,线性支持向量机有一个最大的 AUC 分数,但没有最小的训练时间。由于我们没有优化超参数,您可以更改它们来平衡精度和速度。

结论

SVM 没有在最快的时间内训练出来。尽管超参数没有被优化,文本清理可以减少文本数据集中的非索引词、标点符号和数字等形式的噪声。在现实世界的问题中,速度比准确性更重要。因此,随着数据量的增加,我们可能需要关注速度。深度学习也可以用于比较。一些算法也使用像 Lightgbm 这样的 GPU,所以如果你有大量的数据,你可以考虑使用这种方法。

本文使用的所有代码都可以从我的 GitHub 中访问。我期待听到反馈或问题。

IMDB 电影评论的二元分类

原文:https://towardsdatascience.com/binary-classification-of-imdb-movie-reviews-648342bc70dd?source=collection_archive---------9-----------------------

使用 Keras 根据情感对评论进行分类。

二元分类是指将样本分为两类。

在这个例子中,我们将设计一个神经网络来执行来自 IMDB 电影评论数据集的评论的两类分类,或二元分类,以确定评论是正面的还是负面的。我们将使用 Python 库 Keras。

IMDB 电影评论分类。(来源:GitHub)

如果您正在寻找一个更基本的问题,请查看解决 MNIST 数据集。接下来的内容主要建立在解决 MNIST 问题上,即“你好,世界!深度学习。

[## 解决 MNIST 图像分类问题

“你好,世界!”深度学习和 Keras

towardsdatascience.com](/solve-the-mnist-image-classification-problem-9a2865bcf52a)

IMDB 数据集

IMDB 数据集是一组来自互联网电影数据库的 50,000 条高度极化的评论。它们被分成 25000 条评论,每条评论用于训练和测试。每组包含相同数量(50%)的正面和负面评论。

IMDB 数据集与 Keras 打包在一起。它由评论及其对应的标签组成(0 代表负面,1 代表正面评论)。评论是一个单词序列。它们被预处理成整数序列,每个整数代表字典中的一个特定单词。

IMDB 数据集可以直接从 Keras 加载,通常会在您的机器上下载大约 80 MB。

加载数据

让我们从 Keras 加载预打包的数据。我们将只包括 10,000 个最频繁出现的单词。

加载和分析输入数据

为了好玩,我们来解码第一篇评论。

解读一篇评论

准备数据

我们无法将整数列表输入到我们的深层神经网络中。我们需要把它们转换成张量。

为了准备我们的数据,我们将对我们的列表进行一次性编码,并将其转换为 0 和 1 的向量。这将把我们的所有序列放大为 10,000 维向量,在对应于该序列中存在的整数的所有索引处包含 1。这个向量在所有索引处都有元素 0,这在整数序列中是不存在的。

简单来说,每个评论对应的 10000 维向量会有

  • 每个索引对应一个单词
  • 每一个值为 1 的索引都是评论中出现的一个词,用它的整数对应物来表示。
  • 每一个包含 0 的索引都是评论中没有的词。

我们将手动矢量化我们的数据,以获得最大的清晰度。这将产生一个形状张量(25000,10000)。

预处理输入数据

构建神经网络

我们的输入数据是需要映射到定标器标签(0 和 1)的向量。这是最简单的设置之一,一个简单的全连接、密集的层与 relu 激活的堆栈表现相当好。

隐藏层

在这个网络中,我们将利用隐藏层。我们将这样定义我们的层。

Dense(16, activation**=**'relu')

传递给每个Dense层的参数(16)是一层的隐藏单元的数量。

在一系列张量运算之后,生成了激活了 relu密集层的输出。这个操作链实现为

output = relu(dot(W, input) + b)

其中,W权重矩阵b是偏差(张量)。

具有 16 个隐藏单元意味着矩阵 W 将具有(输入 _ 尺寸16 )的形状。在这种情况下,输入向量的维数是 10,000,权重矩阵的形状将是(10000,16)。如果你把这个网络用图表来表示,你会在这个隐藏层看到 16 个神经元。

通俗地说,这一层会有 16 个球。

这些球或隐藏单元中的每一个都是层的表示空间中的一个维度。表示空间是数据的所有可行表示的集合。由它的隐藏单元组成的每一个隐藏层的目的是从数据中学习一个特定的数据变换或一个特征/模式。

DeepAI.org 有一篇关于隐藏层的非常翔实的报道。

简单地说,隐藏层是数学函数的层,每一层都被设计成产生特定于预期结果的输出。

隐藏层允许将神经网络的功能分解为特定的数据转换。每个隐藏层函数都专门用于产生定义的输出。例如,用于识别人的眼睛和耳朵的隐藏层函数可以与后续层结合使用,以识别图像中的面部。虽然单独识别眼睛的功能不足以独立识别物体,但它们可以在神经网络中共同发挥作用。

ReLU 激活功能。这是最常用的激活功能之一。

模型架构

对于我们的模型,我们将使用

  1. 两个中间层,每个中间层有 16 个隐藏单元
  2. 将输出标量情感预测的第三层
  3. 中间层将使用 relu 激活功能。 relu 或整流线性单位函数将负值清零。
  4. 最终层或输出层的 Sigmoid 激活。sigmoid 函数"将"任意值压缩到[0,1]范围内。

乙状结肠激活函数。(来源:维基百科,Qef)

在选择模型的架构属性时,有正式的原则指导我们的方法。这些不包括在本案例研究中。

定义模型架构

编译模型

在这一步,我们将选择一个优化器、一个损失函数指标进行观察。我们将继续前进

  • 二元 _ 交叉熵损失函数,常用于二元分类
  • rmsprop 优化器和
  • 准确性作为绩效的衡量标准

我们可以将我们对优化器、损失函数和指标的选择作为字符串传递给compile函数,因为rmspropbinary_crossentropyaccuracy是与 Keras 打包在一起的。

model.complie(optimizer**=**'rmsprop',
              loss **=** 'binary_crossentropy',
              metrics **=** ['accuracy'])

人们可以通过将定制的类实例作为参数传递给lossoptimizermertics字段来使用定制的损失函数或优化器。

在这个例子中,我们将实现我们的默认选择,但是我们将通过传递类实例来实现。如果我们有定制的参数,这正是我们要做的。

编译模型

设置验证

我们将留出一部分训练数据,用于在训练时验证模型的准确性。一个验证集使我们能够监控我们的模型在训练期间经历历元时在以前看不到的数据上的进展。

验证步骤帮助我们微调model.fit函数的训练参数,以避免数据的过拟合和欠拟合。

为模型定型设置验证集

训练我们的模型

最初,我们将在 512 个样本的小批量中为 20 个时期训练我们的模型。我们还将把我们的验证集传递给fit方法。

调用fit方法返回一个History对象。该对象包含一个成员history,它存储了训练过程的所有数据,包括随着时间的推移可观察到的或监控到的量的值。我们将保存该对象,以确定更好地应用于训练步骤的微调。

训练模型。Google Colab GPU 对应的时间。在 CPU、i7 上通常需要大约 20 秒

在训练结束时,我们达到了 99.85%的训练准确率和 86.57%的验证准确率

现在我们已经训练了我们的网络,我们将观察存储在History对象中的性能指标。

调用fit方法返回一个History对象。这个对象有一个属性history,这是一个包含四个条目的字典:每个被监控的指标一个条目。

培训过程的历史。

history_dict包含以下值

  • 培训损失
  • 训练准确性
  • 验证损失
  • 验证准确性

在每个时期结束时。

让我们使用 Matplotlib 并排绘制训练和验证损失以及训练和验证准确性。

从训练历史中得到的损失和准确性数据的分析。这些数据告诉我们我们的训练策略的表现。

我们观察到最小验证损失最大验证准确度在大约 3-5 个时期达到。之后,我们观察到两个趋势:

  • 验证损失增加,培训损失减少
  • 验证准确性降低,培训准确性提高

这意味着该模型在对训练数据的情绪进行分类方面越来越好,但当它遇到新的、以前从未见过的数据时,总是做出更差的预测。这是过度拟合的标志。在第 5 个时期之后,模型开始太接近训练数据。

为了解决过度拟合的问题,我们将把历元的数量减少到 3 到 5 之间。这些结果可能会因您的机器而异,并且由于不同型号之间随机分配重量的本质可能会有所不同。

在我们的情况下,我们将在 3 个纪元后停止训练。

重新训练我们的神经网络

我们重新训练我们的神经网络的基础上,我们的研究结果,从历史的损失和准确性的变化。这次我们运行它 3 个时期,以避免在训练数据上过度拟合。

从头开始再培训

最终,我们实现了 99%的训练准确率和 86%的验证准确率。这很好,考虑到我们正在使用一种非常幼稚的方法。通过使用更好的训练算法可以获得更高的准确度。

评估模型性能

我们将使用训练好的模型对测试数据进行预测。输出是一个浮点整数数组,表示评论为正面的概率。正如你所看到的,在某些情况下,网络是绝对肯定的审查是积极的。在其他情况下——没那么多!

做预测

你可以试着通过使用像均方差这样的度量来找到一些错误分类的情感数量的误差度量,就像我在这里做的。但是这样做就太傻了!对结果的分析不是我们在这里要讨论的内容。然而,我将解释为什么在这种情况下使用mse是无用的。

来自我们模型的结果是模型感知评论的积极程度的度量。该模型不是告诉我们样本的绝对类别,而是告诉我们它认为情绪在多大程度上偏向一边或另一边。MSE 是一个过于简单的衡量标准,不能反映解决方案的复杂性。

我没有想象这个神经网络。我会的,但这是一个耗时的过程。我确实想象过我用来解决 MNIST 问题的神经网络。如果你想的话,你可以看看这个 GitHub 项目来可视化人工神经网络

[## Prodicode/ann-visualizer

一个很棒的可视化 python 库曾经与 Keras 一起工作。它使用 python 的 Graphviz 库来创建一个可展示的…

github.com](https://github.com/Prodicode/ann-visualizer)

结论

因此,我们成功地对 IMDB 上的评论进行了分类。我猜这需要重新观看矩阵或 IMDB 建议的任何东西!

我建议你配合这篇文章。您可以使用类似的策略解决大多数二元分类问题。如果你解决了这个问题,试着修改网络及其层的设计和参数。这将帮助您更好地理解您所选择的模型架构的完整性。

我在每篇文章中都详细讨论了一个话题。在这一篇中,我们深入研究了一些隐藏的图层。对任何特定主题的详尽解释都不在我的文章范围之内;然而,你会发现大量的快速旁白。

我假设读者对诸如优化器、分类编码、损失函数和度量标准之类的技术细节有着实用的理解。你可以在这里找到我关于这些概念的练习笔记。

更多内容,请查看 Francois Chollet 的《用 Python 进行深度学习的 T2》一书。

请随意查看本文的实现以及我在 GitHub 上的更多工作。

感谢阅读!

二元交叉熵和逻辑回归

原文:https://towardsdatascience.com/binary-cross-entropy-and-logistic-regression-bf7098e75559?source=collection_archive---------14-----------------------

有没有想过我们为什么使用它,它来自哪里,如何有效地优化它?这里有一个解释(包括代码)。

尽管逻辑回归源于统计学,但它是解决机器学习中二元分类问题的一种相当标准的方法。它实际上是如此标准,以至于在所有主要的数据分析软件(如 Excel、 SPSS ,或其开源替代软件【PSPP】)和库(如 scikit-learn 、 statsmodels 等)中都有实现。即使你只是稍微熟悉逻辑回归,你也可能知道它依赖于所谓的二元交叉熵的最小化

其中 m 为样本数, x 为第 I 个训练样本, yᵢ 为其类(即 0 或 1), σ(z) 为逻辑函数, w 为模型的参数向量。你可能也知道,对于逻辑回归,它是一个凸函数。因此,任何最小值都是全局最小值。但是你有没有想过我们为什么要使用它,它实际上是从哪里来的,或者你如何能比简单梯度下降更有效地找到这个最小值?我们将在下面解决这些问题,并提供简单的 Python 实现。但首先,让我们快速回顾一下物流功能!

(非常)快速回顾一下物流职能

逻辑函数图。

逻辑函数 σ(z) 是一条 S 形曲线,定义为

它有时也被称为到期功能或s 形函数。它是单调的,并且在 0 和 1 之间有界,因此它被广泛用作概率模型。此外,我们还有

最后,你可以很容易地证明它对 z 的导数由下式给出

关于这个函数,这差不多就是你需要知道的全部了(至少对于这篇文章来说)。所以,事不宜迟,让我们开始吧!

逻辑回归的二元交叉熵推导

让我们考虑一个预测器 x 和一个二元(或伯努利)变量 y 。假设在 xy 之间存在某种关系,理想的模型会预测

通过使用逻辑回归,这个未知的概率函数被建模为

因此,我们的目标是找到参数 w ,使得模拟的概率函数尽可能接近真实的概率函数。

从伯努利分布到二元交叉熵

评估我们的模型做得有多好的一个方法是计算所谓的可能性函数。给定 m 个例子,这个似然函数被定义为

理想情况下,我们因此希望找到使w**)最大化的参数 w 。然而,在实践中,为了简单起见,人们通常不直接使用这个函数,而是使用它的负对数

因为对数是严格单调的函数,最小化负对数似然性将导致与直接最大化似然性函数时相同的参数。但是如何计算 P(y| x,w ) 当我们的 logistic 回归只建模 P(1| x,w ) ?鉴于

可以使用简单的求幂技巧来编写

将该表达式插入负对数似然函数中(并通过实例数量归一化),我们最终获得期望的归一化二进制交叉熵

因此,找到最小化二元交叉熵的权重 w 相当于找到最大化似然函数的权重,从而评估我们的逻辑回归模型在逼近我们的伯努利变量的真实概率分布方面做得有多好!

证明它是凸函数

如上所述,我们的目标是找到最小化二进制交叉熵的权重 w 。然而,在最一般的情况下,一个函数可能有多个极小值,寻找全局极小值被认为是一个困难的问题。尽管如此,可以表明最小化逻辑回归的二元交叉熵是一个凸问题,因此,任何最小值都是全局的。让我们快速证明这确实是一个凸问题!

有几种方法可以用来证明函数是凸的。然而,一个充分条件是其 Hessian 矩阵(即其二阶导数矩阵)对于 w 的所有可能值都是半正定的。为了便于我们的推导和后续实现,让我们考虑二进制交叉熵的矢量化版本,即

其中, X 的每一行都是我们的一个训练示例,我们利用了逻辑函数中引入的一些恒等式。使用矩阵微积分的一些元素(如果你不熟悉的话,查看这里的),可以显示我们的损失函数相对于 w 的梯度由下式给出

类似地,黑森矩阵写道

随着

从这一点,人们可以很容易地表明

因此,Hessian 矩阵对于每个可能的是正半定的,并且二元交叉熵(对于逻辑回归)是凸函数。既然我们知道我们的优化问题是行为良好的,让我们把注意力转向如何解决它!**

如何高效地找到这个最小值?

与线性回归不同,逻辑回归没有封闭形式的解。在当前情况下,二元交叉熵是一个凸函数,但是任何来自凸优化的技术都保证找到全局最小值。下面我们将使用两种这样的技术来说明这一点,即具有最佳学习速率的梯度下降牛顿-拉夫森方法

最优学习率梯度下降

在机器学习中,梯度下降的变化是模型训练的主力。在该框架中,权重 w 按照简单规则迭代更新

直到达到收敛。这里,α被称为学习速率或步长。使用恒定的学习速率是很常见的,但是如何选择呢?通过计算各种损失函数的 Lipschitz 常数的表达式, Yedida & Saha 最近表明,对于逻辑回归,最佳学习速率由下式给出

下面是相应算法的简单 Python 实现。假设您已经熟悉 Python,代码应该是不言自明的。

为了清晰和易用,我在我的每一篇文章中都尽量坚持使用 scikit-learn API。

牛顿-拉夫森方法

基于梯度下降的技术也被称为一阶方法,因为它们仅利用编码损失函数的局部斜率的一阶导数。当证明逻辑回归的二元交叉熵是凸函数时,我们也计算了 Hessian 矩阵的表达式,所以让我们使用它!

能够访问 Hessian 矩阵使我们能够使用二阶优化方法。这种技术使用关于由该 Hessian 矩阵编码的损失函数的局部曲率的附加信息,以在训练过程中自适应地估计每个方向上的最佳步长,从而实现更快的收敛(尽管计算成本更大)。最著名的二阶技术是牛顿-拉夫森方法,以杰出的艾萨克·牛顿爵士和不太出名的英国数学家约瑟夫·拉弗森的名字命名。使用这种方法,权重 w 的更新规则现在由下式给出

其中H(w)是对当前进行求值的黑森矩阵。注意,Hessian 矩阵的条目明确地依赖于当前的 w 。因此,它需要在每次迭代时更新,并对其进行逆重新计算。尽管牛顿法比普通梯度下降法收敛得更快,但它的计算量更大,占用的内存也更多。对于小规模到中等规模的问题,它可能仍然比梯度下降法收敛得更快(在挂钟时间内)。对于更大的问题,人们可以看看被称为拟牛顿的方法,其中最著名的是 BFGS 方法。和以前一样,下面提供了相应算法的简单 Python 实现。**

超越传统的逻辑回归

逻辑回归为分类任务提供了一个相当灵活的框架。因此,多年来已经提出了许多变体来克服它的一些限制。

处理非线性可分离的类

通过构造,逻辑回归是一个线性分类器。正如线性回归可以扩展到建模非线性关系,逻辑回归也可以扩展到分类点,否则非线性可分。然而,这样做可能需要专业知识、对数据属性的良好理解以及特征工程(与其说是精确的科学,不如说是一门手艺)。

不平衡的阶级分布

当使用普通逻辑回归时,我们隐含地假设样本中两个类别的流行率大致相同(例如,预测一个人是男性还是女性)。然而,现实生活中有许多情况并非如此。在医学科学中尤其如此,在医学科学中,人们可能希望根据他/她的病历来预测病人在手术后是否会死亡。有希望的是,大多数已经接受治疗的患者已经存活,因此我们的训练数据集只包含相对较少的死亡患者的例子。这就是所谓的阶级不平衡。

已经提出了不同的方法来处理这种类不平衡问题,例如对少数类进行上采样或者对多数类进行下采样。另一种方法是使用对成本敏感的培训。为了说明后者,让我们考虑以下情况:我们有 90 个样本属于比方说类别 y = 0 (例如,患者存活),只有 10 个样本属于类别 y = 1 (例如,患者死亡)如果我们的模型一直预测 y = 0 (即患者将存活),它将具有 90%的惊人准确性,但在预测给定患者是否可能死亡方面毫无用处。然而,提高模型的有用性和预测能力的简单技巧是如下修改二元交叉熵损失

权重α₀和α₁通常被选择作为训练集中每个类的逆频率。回到我们上面的小例子,α₀将被选为

而α₁将被设定为

这样做,当该模型将可能死亡的患者错误分类为存活的患者时,该模型受到更严重的惩罚(大约 10 倍以上)。它只需要对前面提出的算法进行微小的修改。尽管这种方法可能增加假阳性的数量(即,将存活的患者被错误地分类为可能死亡的患者),但是它减少了假阴性的数量(即,将死亡的患者被错误地分类为可能存活的患者)。这样,医生就可以把注意力集中在真正需要治疗的病人身上,尽管他们中的一些人本来是可以活下来的。

多项式分类

尽管二进制分类问题在现实生活中普遍存在,但一些问题可能需要多类方法,例如手写数字识别。

在这个问题中,人们试图分配一个标签(从 0 到 9)来表征图像中出现的数字。即使逻辑回归是通过设计二元分类模型,它也可以使用一对其余方法来解决这个任务。十个不同的逻辑回归模型被独立训练:

  • 模型 1:预测数字是零还是不是零。
  • 模型 2:预测数字是 1 还是不是 1。
  • 模式 10:预测数字是不是 9。

在部署阶段,分配给新图像的标签基于这些模型中哪个模型对其预测最有信心。然而,这种一对多的方法并不是没有限制,主要的三个限制是:

  • 不确定性量化:对该模型总体预测的置信度进行估计并不简单。虽然量化预测中的不确定性对于类似 Kaggle 的竞争可能并不重要,但在工业应用中却至关重要。
  • 不可判定性:当其中两个模型对它们的预测同样有信心时,如何处理这种情况?
  • 不平衡学习:每个模型使用不平衡数据集学习。假设我们对每个数字都有大致相同数量的例子,一个给定的模型只有 10%的这个特定数字的训练例子和 90%的非这个特定数字的训练例子。

尽管有这些限制,一对多逻辑回归模型仍然是处理多类问题时使用的一个很好的基线,我鼓励你这样做作为一个起点。一个更合适的方法,称为 softmax 回归,将在接下来的帖子中考虑。

正则化逻辑回归

在机器学习中,处理以大量特征为特征的数据是相当常见的。然而,并非所有这些特征都可以为预测目的提供信息,因此可以瞄准稀疏逻辑回归模型。为此,例如可以使用模型权重的ℓ₁-norm 正则化。修正的损失函数由下式给出

其中CE(w)是二进制交叉熵的简写符号。现在众所周知,使用损失函数的这种正则化促进了参数向量 w 稀疏。然后,超参数λ控制模型的稀疏程度和最小化交叉熵的重要性之间的权衡。虽然超参数优化本身是机器学习的一个专门领域,远远超出了本文的范围,但我们最后要提到的是,scikit-learn 提供了一种基于网格搜索和交叉验证的简单启发式方法来找到λ的好值。

结论

从数学和计算的角度来看,逻辑回归的简单性和灵活性使其成为现实应用中二元分类最常用的技术。如果你是机器学习的新手,我希望你现在对它所依赖的数学以及如何在实践中使用它有更好的理解。请注意,有很多内容我们没有涉及,例如:

  • 根据优势比(或对数优势)对模型的统计解释,
  • 如何使用各种指标和 ROC 或精确召回曲线来量化预测的准确性(除了我们最小化训练集的交叉熵这一事实)。

然而,这些应该是在你掌握了基础知识之后的第二步。此外,网上有很多资源可以解决这些额外的问题。为了获得更好的见解,请不要犹豫!不要犹豫,也要自己推导这里给出的所有数学结果,并使用提供的代码!请告诉我这些内容是否对您有用,或者您是否发现了任何错别字:]

在接下来的几篇文章中,我们将讨论以下主题:

  • 为什么你应该总是正则化逻辑回归!
  • 多类问题和 softmax 回归。
  • 贝叶斯逻辑回归。

其他在线资源

  • Aurélien Géron ( 此处为)的精彩视频从信息论的角度解释了为什么使用交叉熵进行分类是有意义的。

想看更多这方面的内容?查看我其他关于低秩结构和数据驱动建模 的文章或者干脆我的 机器学习基础知识

** [## 罗森布拉特的感知机,第一个神经网络

深度学习快速入门。

towardsdatascience.com](/rosenblatts-perceptron-the-very-first-neural-network-37a3ec09038a)**

Python 中的二进制、十六进制和八进制

原文:https://towardsdatascience.com/binary-hex-and-octal-in-python-20222488cee1?source=collection_archive---------2-----------------------

十进制系统之外的漫步

由 Alexander Sinn 在 Unsplash 上拍摄的照片

在数学方面,Python 以强大和易于使用而闻名。它的本机功能和资源丰富的库,如 NumPy、Pandas 或 Scikit-learn,为开发人员提供了处理繁重数字的必要工具。但有时我们需要跳出十进制世界,使用其他常见的基数之一。

基数是计数系统用来表示数值的位数。最普遍的数字系统是十进制,也称为十进制。在十进制中,数字 0、1、2、3、4、5、6、7、8 和 9 代表每一个可能的值。但是计算机和软件开发人员经常需要使用其他基础。

[## 如何实施成功的数据清理流程

因为你不能测量脏数据

towardsdatascience.com](/how-to-implement-a-successful-data-cleaning-process-701e565e6575)

在所有十进制系统中,十进制系统最受二进制、十六进制和八进制系统的欢迎。其他人属于你和朋友在一起时会避开的那种特殊的表亲。然而,如果你计划使用二进制、十六进制或八进制,你可能需要温习一下 Python。在 Python 中,它们不像 base 10 那样简洁易用。

二进制的

二进制只使用数字 0 和 1。从这两个,它可以说明每一个可能的值,同样的十进制系统。你还记得小学时的位置值吗?这就是它的工作原理。在十进制中,每个位置增加十的倍数,但在二进制中,每个位置增加二的倍数。

以 10 为基数的数位值,例如数字 10、100 和 1000

基数 2 位值

例如,101 表示值 5。

而 10101 将代表值 21。

想知道为什么您的网络子网掩码看起来像 255.255.255.0 吗?因为每一个用句点分隔的数字都是由八位二进制数 11111111 组成的。

我们可以这样开始这一部分:“二进制只使用 10 位数。”如果你不明白这个笑话,请再读一遍二进制是如何工作的解释。

在 Python 中,使用二进制数比使用十进制数要多几个步骤。当你输入一个二进制数时,以前缀“0b”开始(即一个零后面跟着一个小 b)。

0b11与二进制 11 相同,等同于十进制 3。不难,但这是额外的工作。每当你想在一个变量中存储一个二进制值,它会为你转换成十进制。

number1 = 0b11

这导致变量number1存储值 3。它只是存储这个值,并不表示你想用二进制来表示它。所以,当你检索它的时候,你会得到一个十进制值 3。事实上,Python 独立于 base 处理所有的数学运算符,但是它总是以十进制返回给你。

"但是如果我想让我的数字以二进制返回给我呢?"

很高兴你问了。

如果您希望代码中的数字严格保持二进制,这里有一个解决方案。

>>> num1 = "0b100"
>>> num2 = "0b110"
>>> mysum = int(num1, 2) + int(num2, 2)
>>> print(bin(mysum))
0b1010

在上面的代码片段中,我们首先将字符串“0b100”赋给变量num1。接下来,我们将字符串“0b110”赋给变量num2。所以我们有两个 string 类型的变量,分别存储 4 和 6 的二进制表示。

接下来,我们将这两个数字相加。但是当我们这样做的时候,我们使用函数 int()将每一个转换为基数为 10 的整数。通常 int()会抛出一个包含字母的字符串错误。通过指定第二个参数 2,我们指示 int()将字符串解释为二进制数。所以,它保持快乐。

您可以使用第二个参数来指定 2 到 36 之间的任何基数。基数 2 和 36 包括在该范围内。

[## 做出数据驱动决策的错觉

如何让数据真正驱动您的决策

towardsdatascience.com](/the-illusion-of-making-data-driven-decisions-bf54a2e594c4)

在我们将两个数字相加并将结果存储在mysum中之后,我们打印出总和。但它是独立于基地存放的。当我们回忆它的时候,它还是想用十进制呈现给我们。所以我们必须告诉 Python 我们想要二进制数。在将值打印到屏幕上之前,使用 bin()函数将值转换为二进制。

上面的代码给了你一个清晰的 Python 二进制表示。然而,你也可以使用一个更简短的版本,就像这样。

>>> num1 = 0b100
>>> num2 = 0b110
>>> mysum = num1 + num2
>>> print(bin(mysum))

你会得到同样的结果。唯一的区别是你如何在变量num1num2中存储数字。如果你在第一个例子中把任何一个变量打印到屏幕上,你会看到它是二进制的,尽管从技术上讲它是一个字符串。在第二个示例中,您将看到一个小数,除非您使用 bin()来转换它。

>>> num1 = "0b100"
>>> print(num1)
"0b100">>> num1 = 0b100
>>> print(num1)
4
>>> print(bin(num1))
0b100

十六进制的

十进制用十位,二进制用两位,十六进制用十六位。因为我们只有十进制系统中的十位数可以使用,所以我们用字母代替数字 9 以上的所有数字。所以十六进制的数字是 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,它们代表从零到九,那么 A 值十,B 值十一,C 值十二,D 值十三,E 值十四,F 值十五。所以,十六进制有十六个数字。如果你用十六进制写,你可以说,“十六进制有 10 个数字。”

等等?我们以前没见过吗?是的。老实说,如果你在相应的数字系统中写数字,10 总是代表任何基数的总位数。但是只有二进制才有意思。

在 Python 中表示十六进制数时,在数字前加上前缀“0x”。此外,使用 hex()函数将值转换为十六进制格式以便显示。

我们的两个十六进制代码样本类似于我们用于二进制代码的样本。

>>> hnum1 = "0x10"
>>> hnum2 = "0x10"
>>> myhsum = int(hnum1, 16) + int(hnum2, 16)
>>> print(hnum1)
"0x10"
>>> print(myhsum)
32
>>> print(hex(myhsum))
0x20>>> hnum1 = 0x10
>>> hnum2 = 0x10
>>> myhsum = hnum1 + hnum2
>>> print(hnum1)
16
>>> print(myhsum))
32
>>> print(hex(myhsum))
0x20

八进制的

最后,这同样适用于八进制。任何关于八进制数字系统中有多少位数的猜测?八进制代表八。对,八进制包含八位数。在 Python 中,我们使用 oct()将数字转换为八进制,而不是 bin()或 hex()。我们在八进制数字前加一个零,后面跟着一个小写的 o,比如“0o”。

八进制的八位数是 0,1,2,3,4,5,6,7。

让我们在这里使用相同的代码示例,但是我们将为八进制代码使用正确的符号和转换函数。

>>> onum1 = "0o10"
>>> onum2 = "0o10"
>>> myosum = int(onum1, 8) + int(onum2, 8)
>>> print(onum1)
"0o10"
>>> print(myosum)
16
>>> print(oct(myosum))
0o20>>> onum1 = 0o10
>>> onum2 = 0o10
>>> myosum = onum1 + onum2
>>> print(onum1)
8
>>> print(myosum))
16
>>> print(oct(myosum))
0o20

结论

Python 的伟大之处在于,除了洗衣服,它几乎可以做任何事情。我正在努力。

要点很简单:

  • 二进制使用 bin()和“0b”。
  • 十六进制使用十六进制()和“0x”。
  • 八进制使用 oct()和' 0o '。
  • 通过更改第二个参数,可以使用 int()函数将数字从 2 到 36 之间的任何基数转换为基数为 10 的整数。例如 int(number,30)

即使在我们喜爱的十进制系统之外使用基数需要更多的努力,Python 很容易适应并使我们能够进入十进制以前没有去过的地方——进入其他基数的最终边界。

杆蓖麻 帮助公司获得正确的分析!他帮助国际组织和小型企业改善他们的数据分析、数据科学、技术战略和技术领导力。除了咨询,Rod 还喜欢公开演讲、教学和写作。你可以在 rodcastor.com**和通过他的 邮件列表 了解更多关于 Rod 和他的工作。

Python 中的二分搜索法——更快吗?

原文:https://towardsdatascience.com/binary-search-in-python-is-it-faster-b960c74c3d11?source=collection_archive---------36-----------------------

二进制与线性搜索—实现和性能测试

照片由约书亚·苏考夫在 Unsplash 上拍摄

这是一周的时间!你决定深入一个话题,今天我们来看看二分搜索法。

和往常一样,解决同一个问题有很多方法。当你想检查一个元素是否在一个列表中,你可以用线性搜索和二分搜索法来完成,但是猜猜哪个更快。

为什么?

如果你最近在 Youtube 上看过编程工作面试,你就会知道二分搜索法是最受欢迎的。

你为什么要花时间去了解二分搜索法呢?你的 C++编程朋友可能已经告诉你了。Python 很慢。你要确保你的程序不会比需要的速度慢。

当您学习 Python 时,您将学习进行线性搜索来检查元素是否在列表中。当你学习编码时,这没问题,但是当你在一个列表中有 60.000.000 个元素时会发生什么呢?

如果你在一个有 11 个元素的列表中进行线性搜索,你必须遍历所有的 11 个元素。如果你使用二分搜索法,根据你要找的东西,你可能最终只有 2 次迭代。见下图。

哪种方法更快应该是显而易见的。

当您开始学习 Python 时,您很可能已经处理过上百次列表了。检查值是否在列表中是一项正常的任务,您以前已经看到过这种情况:

my_list = [1,2,3,3,5,11,12]if 11 in my_list:
    return Truereturn False

或者这个:

my_list = [1,2,3,3,5,11,12]for each in list:
    if each==11:
        return Truereturn False

让我们开始看看如何实现二分搜索法。

如何?

让我们想象一下二分搜索法是如何工作的。

首先,我们需要确保列表已经排序。你可以用.sort()或者sorted()来排序你的列表,我用.sort()来改变列表的位置。如果你出于某种原因需要一个新的列表或者不想修改原来的列表,使用sorted()

这是我们的测试材料:

bin_list = [1,2,3,5,6,9,11,12,15,20,22]
search_value_a = 15

我们将寻找值 15

  • 我们的起点。具有最小值和最大值的列表:

作者图片

  • 当我们做二分搜索法时,我们从寻找列表中的中间元素开始:

作者图片

  • 中间索引为**5**,值为**9**。我们想知道的第一件事是**9**是否是我们要找的号码。记住,我们找的是**15**。如果不是,我们检查它是更低还是更高。在我们的例子中,**9**小于 15,所以我们需要设置一个新的最小点。我们知道我们不再需要担心名单的下半部分。新的最小点将被设置为列表上部的第一个可能项目。

作者图片

  • 有了新的中点,我们检查这是否是我们正在寻找的数字。在这种情况下,它是。

如果我们在寻找**2**,并且我们的第一个中间值是**9**,你认为算法会如何表现?你说得对。最大指数将会移动。

作者图片

作者图片

作者图片

作者图片

代码

好吧,我知道你是来编码的。让我们开始吧。

伪代码将如下所示:

# create function with list and target as parameters.# make sure the list is sorted.# get length of list minus 1 as max and 0 as start.# a loop will: # get the new middle value
    # check if the middle value is higher or lower than the target. 
    # move the min or max to the middle after the check. 
    # if middle == target, return True
    # if we reach the end of the list, the target is not in the list

代码的作用:

我们已经创建了一个带有两个参数的函数。一个list和一个target value。目标值是我们正在寻找的数字。列表是我们迭代的列表,寻找数字。

def binary_search(input_list , target_value):

如果我们找到目标值,我们将返回True。如果没有,我们就返回False

我们做的第一件事是对列表进行排序,并定义列表的最小索引和最大索引。

input_list.sort()
min_index = 0
max_index = len(input_list) -1

我们使用len(list)-1的原因是 Python 从0开始索引。测试列表的长度为11,但最后一个索引为[10]

现在,让我们来看看大脑的功能,这个循环:

while max_index >= min_index:
    mid_index =(max_index+min_index)//2
    if input_list[mid_index] == target_value:
        return True
    elif input_list[mid_index] < target_value:
        min_index = mid_index+1
    else:
        max_index = mid_index-1

只要最大指数不高于最小指数,我们就继续前进。如果循环停止,这意味着我们已经折叠了列表,所以 max 小于 min。此时,搜索值没有意义,因为没有更多的列表。

  • mid设置为maxmin的平均值。注意我们如何使用基数除法/整数除法,例如7//2将是3而不是3.5。这样我们总能为我们的索引得到一个干净的整数。
  • 如果带有 mid 索引的列表项的值等于我们的目标值,我们成功了!返回True回家。
  • 如果该值小于目标值,我们知道必须将最小索引提高到该点。新的min因此是mid+1
  • 如果该值不等于或小于目标值,则该值较大。这意味着我们可以删除列表的顶部,并降低 max 指数。max设置为mid-1

如果您发现很难理解,您可以在代码中添加一个print()来获得索引跳转的可视化表示。

在 while 循环中的mid_index =(max_index+min_index)//2之后添加:

print (f'min: {min_index} , mid: {mid_index} , max: {max_index}')

main()

我们的主过程包含测试数据和一些断言,以检查一切是否按预期工作。

请注意,如果您想查看搜索失败的示例,我添加了另一种方法来构建列表。

#bin_list = list(range(6,501))

但是这样更快吗?

这个函数的时间复杂度是 O(n ),其中 n 是列表的长度。为了检查哪种搜索更快,我们可以用线性搜索来计算二分搜索法的时间。

来自 Pexels 的 Andrea Piacquadio 的照片

首先,我们需要编写一个线性搜索函数:

def linear_search(input_list, target_value):
    for each in input_list:
        if each==target_value:
            return True
    return False

然后,我们需要编写性能测试,一个针对二进制,一个针对线性:

陷阱

如果你运行上面的代码(与原代码合并),你会看到线性搜索比。这是什么魔法?

list = [6…500],target = 15,跑了 10.000 次。

有几个问题给二进制带来了困难。

  • 整理
  • 列表长度
  • 低目标值

以上所有因素,给了线性一个良好的开端。现在,让我们继续在那里排序,首先改变列表长度:

bin_list = list(range(1,10000))
lin_list = list(range(1,10000))

列表= [1…10.000],目标= 15,运行了 10.000 次

线性搜索还是占了上风。让我们从函数中取出排序,在将列表传递给函数之前对其进行排序。(这对线性搜索不公平,因为线性搜索不依赖于排序列表)。我们所要做的就是注释掉它,因为我们的列表已经排序了。

list = [1…10.000],target = 15,运行了 10.000 次,正在排序

越来越近了。

如果我们把目标值移到 7.500 呢?现在,我们的偏见是闪亮的,因为我们真的希望二进制更快。

list = [1…10.000],target=7500,运行了 10.000 次,正在排序

这一次的差异是极端的。下面的最后一个例子将会使所有的事情变得公平。

让我们用随机目标创建一个随机长度的随机列表。然后我们将对这两个函数运行 100.000 次。

由于他们不能分享列表,我们将相信蒙特卡洛模拟(同时祈祷 Macbook 不会着火……)

test_list = list(range(1,random.randint(2,50000)))
test_number = random.randint(2,50000)
binary_search(test_list,test_number)

list = rand[1…50.000],target = rand,运行了 100.000 次,正在排序

list = rand[1…50.000],target = rand,运行 100.000 次,排序依据

现在让我们运行 6000 万次!开玩笑,我相信这些结果。MacBooks 很贵。

最后

二进制比线性快吗?是的,但是它看情况。

当有人告诉你二分搜索法更快,那是因为它通常是。

像往常一样,你必须看设置,不要每次都选择单一的解决方案,因为它“是最好的”。

我们从实验中看到,这取决于你在做什么。如果您有一个简短的列表,或者如果您正在查找列表下部的元素,那么执行线性搜索可能会更好。

这也是编程的妙处。你不应该在不知道为什么要做某事的情况下使用一种方式。如果你还不知道二分搜索法,现在你又有了一个搜索工具。当你发现它的用处时,就用它。

不过,我希望我们能在一件事上达成一致。二分搜索法非常酷!

二叉树和最低共同祖先

原文:https://towardsdatascience.com/binary-tree-and-lowest-common-ancestor-58eddd433ac?source=collection_archive---------21-----------------------

二叉树中两个节点的最低公共祖先以及寻找它的算法。

作者图片

什么是“最低共同祖先(LCA)”。

它是树中两个节点共享的最低级别的父节点。

让我们来看一个例子:

作者图片

在上面的二叉树中,节点 8 和 10 被突出显示。他们共有的父母是什么?

作者图片

共享的父母是 5,7,9 是相当明显的。

但最底层的共享父代是 9,称为最低共同祖先(LCA)

二叉查找树中最低的共同祖先

让我们用二叉查找树热身。

二叉查找树是二叉树的一个特例,左子树只包含较小的节点,而右子树只包含较大的节点。

我们上面的例子是一个二叉查找树。如您所见,在节点 3,左子树(0,1,2)中的所有节点都小于 3,而右子树中的所有节点都大于 4。

那么,我们如何着手寻找二叉查找树中的 LCA,例如节点 8 和 10?

实际上,二叉查找树让搜索变得非常简单。仔细看看节点 9,它和节点 7 有什么不同?我能想到一件事:

节点 9 介于 8 和 10 之间,而对于节点 7,节点 8 和 10 都更大。

这实际上是足够信息来确定节点 9 是二叉查找树中节点 8 和 10 的 LCA,这要归功于它的巨大属性。

下面是它的一个实现:

from collections import deque

class Node:
    def __init__(self, value, left=None, right=None):
        self.value = value
        self.left = left
        self.right = right

def create_bt(value_queue):
    *"""create binary tree"""* if len(value_queue) <= 0:
        return None, None

    root = Node(value_queue.popleft())

    current_queue = deque()
    current_queue.append(root)

    while len(current_queue) > 0 and len(value_queue) > 0:

        current_node = current_queue.popleft()

        left = value_queue.popleft()
        if left is not None:
            current_node.left = Node(left)
            current_queue.append(current_node.left)

        right = value_queue.popleft()
        if right is not None:
            current_node.right = Node(right)
            current_queue.append(current_node.right)

    return root

def create_bt_fls(value_list):
    *"""create binary create from list"""* return create_bt(deque(value_list))

def lca_bst(bst, v1, v2):
    *"""lowest common ancestor of two nodes
       in a binary search tree"""* if v1 <= bst.value <= v2 or v1 >= bst.value >= v2:
        return bst
    elif bst.value > v1 and bst.value > v2:
        return lca_bst(bst.left, v1, v2)
    else:
        return lca_bst(bst.right, v1, v2)

bt1 = create_bt_fls([5, 3, 7, 1, 4, 6, 9, 0, 2, None, None, None, None, 8, 10])

lca = lca_bst(bt1, 8, 10)
print(lca.value)
'''
output:
9
'''

在这个实现中,我们首先从一个值列表中创建一个二叉树数据结构,然后调用 LCA 算法来查找节点 8 和 10 的 LCA,它返回正确的值 9。

让我们暂停一下,稍微思考一下这个算法的复杂性。该算法从根节点开始,在每个节点将节点的值与两个输入节点进行比较,如果值在两个节点之间,则返回该节点作为答案,否则,如果值大于两个输入节点,则向左移动,如果值小于两个输入节点,则向右移动。

所以在每次递归迭代过程中,搜索空间被切成两半(树的一半),这意味着如果树中的节点总数为 n,则需要的迭代次数为 log(n)(以 2 为底),所以复杂度为 O(log(n))。不算太坏。

二叉树中的 LCA(非 BST)

这是一个很好的热身,现在让我们把事情变得稍微复杂一些。

现在假设这棵树不是二叉查找树,而是一棵没有特定结构的随机节点值的树。我们如何找到树中两个节点的 LCA?

二叉树,作者图片

如果你试图在上面的树上运行二叉查找树 LCA 算法,它将悲惨地失败:

ls1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, None, None, None, None, 9, 10]
bt1, node_dict = create_bt_fls(ls1)

lca = lca_bst(bt1, 9, 10)
print(lca.value)
'''
output:
10 WRONG!!
'''

我们得想别的办法。

一种直观的方法是从下面的观察中得来的:

9 的路径:[0,2,6,9],10 的路径:[0,2,6,10],按作者排序的图像

从上图中可以看出,到节点 9 的路径是 0,2,6,9,到节点 10 的路径是 0,2,6,10。一旦我们有了到每个节点的路径,我们需要做的就是在两条路径中找到最后一个匹配的节点,这也是我们的 LCA!

下面是一个实现:

def find_path(tree, value):
    *"""find path from root to value"""* if tree is None:
        return None
    elif tree.value == value:
        return [tree]

    res = find_path(tree.left, value)
    if res is not None:
        return [tree] + res

    res = find_path(tree.right, value)
    if res is not None:
        return [tree] + res

    return None

def lca_fp(tree, v1, v2):
    *"""find lca of two nodes using find_path"""* path1 = find_path(tree, v1)
    path2 = find_path(tree, v2)

    cur_idx = 0
    while len(path1) > cur_idx and \
          len(path2) > cur_idx and \
          path1[cur_idx].value == path2[cur_idx].value:
        cur_idx = cur_idx + 1

    return path1[cur_idx - 1] lca = lca_fp(bt1, 9, 10)
print(lca.value)
'''
output:
6
'''

作品。

上面的算法足够简单,只需要注意一点,Find Path 算法搜索整个树寻找到目标节点的路径,所以它的复杂度是 O(n),因此使用 find_path 的 LCA 算法也是 O(n)。因为没有将树构造为二叉查找树而牺牲了性能。

寻路算法的优化

查找路径算法的复杂性并不令人担心,但是如果您需要重复执行搜索该怎么办呢?请记住,在一个大小为 n 的树中,有 n 选择 2 个唯一的节点对,即:

作者图片

节点对的数量,如果我们使用查找路径算法得到所有节点对的 LCA,那么将是 O(n n)或 O(n)。也许我们应该试着加快一点。

加快查找路径计算速度的一种方法是在节点中存储一个父指针,这样当我们试图查找到一个节点的路径时,我们需要做的就是沿着父指针一直到根,而不是在整个树中搜索路径。

下面是对树的这种增强的实现:

class Node:
    def __init__(self, value, **parent=None**, left=None, right=None):
        self.value = value
        **self.parent = parent**
        self.left = left
        self.right = right

    **def add_to_dict(self, node_dict):

        node_dict[self.value] = self**

def create_bt(value_queue):
    *"""create binary tree"""* if len(value_queue) <= 0:
        return None, None

    **node_dict = {}**

    root = Node(value_queue.popleft())

    **root.add_to_dict(node_dict)**

    current_queue = deque()

    current_queue.append(root)

    while len(current_queue) > 0 and len(value_queue) > 0:

        current_node = current_queue.popleft()

        left = value_queue.popleft()
        if left is not None:
            current_node.left = Node(left, **parent=current_node**)
            **current_node.left.add_to_dict(node_dict)**
            current_queue.append(current_node.left)

        right = value_queue.popleft()
        if right is not None:
            current_node.right = Node(right, **parent=current_node**)
            **current_node.right.add_to_dict(node_dict)**
            current_queue.append(current_node.right)

    return root, **node_dict**

def create_bt_fls(value_list):
    *"""create binary create from list"""* return create_bt(deque(value_list))

在树的这个新实现中,我们在节点中存储了一个额外的字段 parent 来存储父节点。

我们还为节点创建了一个值字典,这样我们就可以很容易地找到对应于某个值的节点。

有了这两个增强,我们可以实现一个新 LCA 算法:

def lca(node1, node2):

    parents = set()

    cur_parent = node1
    while cur_parent is not None:
        parents.add(cur_parent)
        cur_parent = cur_parent.parent

    cur_parent = node2
    while cur_parent is not None:
        if cur_parent in parents:
            return cur_parent
        cur_parent = cur_parent.parent

    return None ls1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, None, None, None, None, 9, 10]
bt1, node_dict = create_bt_fls(ls1)
lca1 = lca(node_dict[9], node_dict[10])
print(lca1.value)
'''
output:
6
'''

又管用了。

通过这种增强,我们牺牲了多一点的内存空间 O(n)来存储父指针,但是由于从节点到根父节点的跟踪是 O(log(n)),所以算法的复杂度降低到 O(log(n))。在所有节点对上运行现在需要 O(n log(n))内存来提高速度。

未完待续……

这是我们能做的最好的吗?绝对不是,有很多方法可以优化算法。特别是 Tarjan 的离线最低共同祖先算法,可以将性能复杂度降低到常数!但是因为它涉及一个全新的数据结构(不相交集),我们将在另一个故事中讨论它。

数据科学家二项分布教程

原文:https://towardsdatascience.com/binomial-distribution-tutorial-for-data-scientists-10921de753c8?source=collection_archive---------24-----------------------

使用简单的 python 代码提高您的统计技能!

没有这些骰子,统计也很有趣!来源

在学习数据科学时,我们经常听到正确研究统计数据的重要性,特别是对概率的关注,在运行机器学习模型和验证测试时,没有办法否认这种知识的重要性。然而,如果你是统计学新手,或者你在高中时历史比数学好,你可能很难理解它。

在本教程中,我将通过一个示例来指导您如何在 python 中运行二项分布模拟,并在最后绘制经验累积分布函数图。我在这里不涉及这个主题的基础概念,所以如果你不熟悉二项分布,你可以先看看这篇优秀的文章。也就是说,让我们开始吧!

哦,但在此之前,欢迎你点击这里下载我正在使用的所有代码的笔记本。

首先:定义一个问题

统计的例子可以很抽象,毕竟什么是“成功案例”,还有为什么那些人痴迷于抛硬币和掷骰子?我认为学习东西的最好方法是在你容易理解的问题/情境中。

比方说,我们正在做一个选举池。我们将随机询问 10 个人,他们是否会在 2020 年投票选举特朗普为总统。我们将与另一组 10 个人反复重复这条线索,直到我们得到 10 万组的答案。我们的目标是发现每组中有 6 人或更多人回答“是”的概率。

但是等等,与其拿着你的纸和笔跑到外面去骚扰街上的人,不如让我们用 python 的能力来模拟一下。

我们首先检查我们是否拥有二项分布情形的所有元素:

  • 是或否问题(因此是“二项式”部分):问题是他们是否会投票给特朗普,所以我们很好。
  • 独立结果:一个人的答案不影响下一个答案。
  • 氮、磷和大小。我们有了试验次数(n),10 个人,每个人回答是(p)的概率,我们用 50%,我们实验的规模,10 万组。

太好了,那我们先做什么?模拟答案!我们可以使用NP . random . random()函数来实现。它会生成一个介于 0 和 1 之间的随机数,所以我们会将所有低于 0.5 的数字视为否,等于或高于 0.5 的数字会被视为是。让我们想象一下如何为 10 人小组得出答案:

> [0.9600173  0.69951205 0.99986729 0.2200673  0.36105635 0.73984099  0.99645573 0.31634698 0.13654458 0.38398001] > [ True  True  True False False  True  True False False False] > Total number of positive answers for this group: 5

所以从我们的第一组 10 个人中,有 5 个人回答说他们会投票给特朗普。现在我们只需要将同样的逻辑重现十万次!为此,我们需要做一个循环并使用函数 np.random.binomial() ,它需要参数: n(试验次数,或者在我们的例子中,每组的人数)p(肯定答案的概率)size(我们想要运行它多少次):

> There's a probability of 37.69% of Trump getting 6 or more supporters in a group.

那是什么意思?

理解如何解释这一结果很重要,因为这不是关于特朗普是否会当选,而是显示了在随机选择 10 人的情况下,6 人或更多人对“你会投票支持特朗普竞选总统吗?”这一问题的回答是肯定的可能性有多大。。

鉴于美国复杂的选举系统,这种模拟可以用于不同的选区,初始概率各不相同。我们假设有 50%的机会回答是或不是,但如果你在佛罗里达或加利福尼亚,这种情况就会改变,对吗?通过改变得到肯定答案的概率(p ),看看结果变化有多大:

  • 对于 p=0.4 : 16.76% 获得 6 个以上支持者的几率;
  • 对于 p=0.6 : 63.27% 获得 6 个以上支持者的几率。

经验累积分布函数(ECDF)

可视化二项分布最酷的方法之一是绘制 ECDF 来检查肯定答案的分布。这可以通过一个简单的 plt.scatter() 来完成,在 y 轴上输入分布的密度,范围从 0 到 1 (100%的样本),在 x 轴上输入我们在每组中得到的肯定答案的数量:

n= 0.4、0.5 和 0.6 时的 ECDF 曲线。注意曲线是如何变化的。

如何解读 ECDF 的情节?

将 x 轴上的值 6 作为参考。在左边的第一个图中,p=0.4,数字 6 略高于 0.8,这意味着超过 80%的分布低于该值,不到 20%的分布高于该值。这与我们的计算 p=0.4 或 16.76%完全匹配,对于其他两个图也是如此。

花几分钟时间比较这些图和值。一旦你有了这个想法,你会注意到理解 ECDF 情节是多么的强大和简单。

结论

在这个实践教程中,我想把你带出我们在学习二项式分布时遇到的所有同类例子,并向你展示如何使用不同的 p 值进行第一次模拟,以及如何用 ECDF 图可视化结果。我希望这篇文章能帮助你提高你的统计技能,也欢迎在评论中分享你的想法。

生物信息学:人工智能如何为生命研究做出贡献

原文:https://towardsdatascience.com/bioinformatics-how-ai-can-contribute-to-the-study-of-life-7a67f3d62a9f?source=collection_archive---------14-----------------------

来自 Pixabay 的背景和封面图片

它是什么,最近的发展和未来

生物学是对生命的研究——可能是科学最迷人的方面之一。更重要的是,它的很大一部分在小的水平上研究生命——DNA 链,有机化学,所有的一切。在大千世界里,研究小物品意味着海量数据;因此,哪里是数据科学大放异彩的更好领域?

生物信息学结合了生物学和数据科学,赋予了机器学习和人工智能方法一个真实而重要的目的。

生物信息学的主要目标是利用机器学习和数据科学的力量来探索太复杂而无法用手探索的生物系统和过程。它将数据科学方法与生物学任务联系起来。例如,一个显著的例子是药物发现和设计——世界上最强大的超级计算机 IBM Summit 花了 1 到 2 天时间搜索可以对抗冠状病毒的化合物的分子结构。它使用生物信息学代码进行模拟。

通常,复杂的生物学现象涉及许多生物学方面,因此不能用一种数据类型来解释。出于这个原因,生物信息学涉及对几种不同数据类型的相互联系的分析,应该对复杂的生物现象有一个整体的理解。

机器学习已经在生物信息学中用于预测和发现——随着高可用性和各种组学(分子水平)数据的兴起,机器学习——尤其是深度学习——变得更加频繁。

由于数据量巨大,生物信息学是数据科学的一个丰富分支。一个人类基因组中大约有多少个核苷酸(“片段”)?

答案是:D,仅在一个人类基因组中就有 350 万个核苷酸。拥有所有这些数据,再结合像序列比对这样的生物信息学方法,可以为美国医院和诊所提供一种更经济实用的诊断工具。

序列比对是指将不同的序列进行比对,以便比较相似性和差异性。这是生物信息学中的一个常见任务。来源。

机器学习的一个机会领域是基因组特征的预测,它描述了任何具有某种注释功能的基因组区域,如基因。

机器学习也可以用来预测 DNA 和 RNA 链的序列。像聚类这样的无监督方法可以用来寻找类似的 DNA 突变,像主成分分析这样的降维技术可以帮助降低高维数据的维度。

生物信息学在解决群体和进化遗传学问题方面也有巨大的潜力。进化,尤其是在人类或其他拥有大量种群的生物中,可能是一个极其困难和复杂的系统来建模。因为生物信息学能够利用机器学习的预测能力,生物学家可以窥视未来,看看最有可能的群体结果是什么,或者某个群体的 DNA 进化成特定版本的概率是多少。

生物信息学中的一个挑战是高级人工智能算法缺乏可解释性(“黑盒性质”)。虽然已经开发了几种方法来解释这些模型,例如,用于解释卷积神经网络的基于梯度的方法,但是对生物信息学中常见的复杂情况的解释是具有挑战性的,并且通常是遥不可及的。因为生物学家通常不仅关注模型的结果,还关注模型如何得出结论,强大的神经网络可能需要被更容易解释的模型所取代,如朴素贝叶斯或逻辑回归。

生物数据和高分辨率/高维度(维数灾难——稀疏性、多重共线性、过拟合)数据的噪声特性带来了额外的挑战。

数据错误,如基因位置不正确、污染序列、序列变异或差异、拼写错误和注释错误困扰着数据库。

尽管改进的机器学习方法和越来越多的数据显示出增加人类对生物现象的理解的巨大潜力,但由于缺乏对隐藏的生物因素(如样本中的群体结构或基因之间的进化关系)的了解,适当的机器学习模型仍然受到阻碍。如果没有适当考虑这些因素,模型可能会过度拟合,导致假阳性发现。

就像机器学习中的免费午餐定理一样,生物信息学中的任何问题都没有确定的方法。不同的机器学习方法将对应于对数据的不同基础假设。

生物信息学在新冠肺炎备受关注。生物信息学家进行的第一次生物信息学突破是在新冠状病毒的生物序列上。

几所中国大学和研究机构已经对新冠肺炎的基因组和晶体结构进行了测序和阐释,这是开发药物、诊断工具和疫苗的起点。

生物信息学家还开发了使用逆转录聚合酶链反应(RT-PCR)的诊断工具。这是使用生物信息学序列比对方法创建的。

通过使用化合物库和药物库,像橡树岭国家实验室的生物信息学家正在使用基于机器学习的计算方法来改变和试验候选药物。

这是通过利用现有的生物信息学化学工具修改现有冠状病毒药物的化学结构,然后进行大规模分子模拟来实现的。

生物信息学的前景非常光明。随着人工智能热潮推动生物信息学的发展,DNA 分析、人造器官和不可想象的新药、药物和疫苗正在迅速发展。

生物信息学是有效的,因为它使用计算机的能力和机器学习的效率来模拟和观察人类需要太长时间才能到达或从未想过要去的地方,并作为人类的导轨。

生物学家和数据科学家:文化鸿沟

原文:https://towardsdatascience.com/biologists-and-data-scientists-the-cultural-divide-4f03f092e81e?source=collection_archive---------30-----------------------

亚历山大·提图斯的见解

来源:作者

生物学和数据科学领域有很多共同点。数据科学家和生物学家都分析数据集,试图理解这个世界。如今,数据科学对生物学越来越重要,因为生物学家越来越多地将机器学习和人工智能用于药物发现、医疗诊断和自动化重复任务。

尽管如此,这两个领域之间仍然存在巨大的文化差异。数据科学家和生物学家经常从非常不同的角度,使用不同的方法和不同的术语来处理同一个问题。

我们采访了高级再生制造研究所(ARMI)首席战略官兼《生物经济》主编 Alexander Titus。XYZ 。亚历山大最初是一名生物学家,后来获得了数据科学博士学位,现在正致力于弥合这两个领域之间的差距。

亚历山大的背景

亚历山大最初在大学学习生物化学和生物学,但在最后一个学期开始接触计算机科学。正如他所说的,

“我爱上了计算机科学,并意识到我一直在研究错误的东西。”

“我搬到了硅谷,想在科技领域的初创公司找份工作。但是我没有任何软件技能,所以我在做与编程无关的事情。然后,在真正的硅谷风格中,我把所有的时间都花在了地下室的黑客工作上:学习如何编码。学习统计学。最终学习机器学习。我考得足够好,可以去拿博士学位了。”

现在,作为一名战略执行官,亚历山大充当了数据科学家和生物学家之间的桥梁。他帮助 ARMI 做出正确的宏观决策,让再生制造成为现实。

【在 LinkedIn 、 Twitter 、他的播客 Titus Talks 、他的出版物 Bioeconomy.xyz 或alexandertitus.com了解更多关于 Alexander 的信息。]

生物学家应该学数据科学,还是数据科学家应该学生物学?

亚历山大已经看到人们在两个方向上拓宽了他们的技能,但他认为生物学家获得数据科学技能比反之更容易。他说:

“与我交谈过的创始人发现,让生物学家来教他们数学和编程,比让那些在数学和科学领域(而不是生物学领域)有着悠久历史的人来试图让他们了解他们错过的多年事实和信息要容易得多。”

但这两个方向都具有挑战性,Alexander 表示,数据科学基础的坚实基础对任何想要跟上不断变化的人都是有用的:

“编程变化真快。Python 很庞大,后来集成了 R。然后是所有的统计数据,然后是 TensorFlow,然后是 Keras。它只是不断变化。任何一套技能都会在几个月内过时。但学习这些技能的潜在能力是巨大的。”

事实上,亚历山大认为“学会学习”是大学教给人们的最重要的事情:

“我在大学里有一个教授,他总是告诉我,‘大学教你的唯一一件事就是如何在一个漫长的周末里学习任何东西。’这才是我真正需要的人们的心态。它是什么并不重要,因为有人将发明一些新的反向传播算法,或者一些我们将不得不使用的新框架。我们总是要去适应。”

“可解释性的文化差异”

数据科学家和生物学家从不同的角度看待同一个问题。来源:作者

每周了解更多关于在生物技术中应用数据科学的信息— 注册我们的每周简讯

生物学家和数据科学家处理问题的最大区别在于他们处理数据和假设检验的方式。

假设检验与机器学习

传统上,科学家会查看一个结果(患者 A 患了癌症,但患者 B 没有),做出一个假设(也许我们可以用这个特定的生物标记来诊断这个癌症),然后使用数据来测试这个假设(在两组患者中寻找那个生物标记:患癌症的患者和没有患癌症的患者)。

虽然使用机器学习的数据科学家也受到这种方法的指导,但侧重点不同。他们看着结果,做出一个更宽松或更宽泛的假设,比如:“也许这个结果可以用我在这个数据集中的一些变量来解释。”他们将数据输入机器学习算法,该算法可能会查看数十亿种可能的解释,然后自动锁定那些最能解释结果的模式。

这种使用更广泛的假设的过程对于许多生物学家来说是陌生的,并且常常让他们感到不舒服。正如亚历山大所说:

“在传统的生物学和化学中,你有一个非常具体的假设,你设计了一套非常具体的实验来测试它。一旦你到了那里,你就有了答案。这只是几个简单的数据点,表明你证明了这一点。

但是在数据科学中,你通常没有假设。你有一个宽松的假设,但你正在进行数据驱动的分析,以获得答案。”

生物学的狂热者:好的科学还是老式的方法?

这不仅仅是习惯的不同。这是人们非常强烈的观点——近乎狂热的信仰。亚历山大用宗教术语说:

“对于生物学家来说,没有假设是亵渎神明的。这与作为生物学家的训练和精神气质是如此的背道而驰。这几乎就像让人们质疑他们的科学宗教。生物学家会说,‘好吧,你是个没有假设的白痴。“你为什么没有一个假设,””

但是随着新的工具和技术允许我们更有效地探索数据,机器学习正变得越来越被接受。亚历山大说:

“有很多证据表明基于机器学习的分析有多好,有多有用。”

机器学习可以在数据中找到更复杂的关系

没有算法的帮助,科学家们只能进行有限的数据分析。传统上,生物学家在任何给定的实验中只考虑很少的变量,在数据中寻找简单的关系,他们只进行少数实验。

因此,难怪他们有时会发现很难理解机器学习为他们的领域提供的潜力。亚历山大赞同这种观点:

大多数来自生物和化学领域的科学家做少量的实验。他们使用一些简单的图表进行基本的 Excel 分析,以了解正在发生的事情。他们通常认为机器学习只是将更多的数据点打包到条形图的相同条中的一种情况;他们不太理解 维度 复杂性 带来了更多的数据和更多的变量。”

人类往往很难理解高维。Geoffrey Hinton 简洁地解释道:“要处理 14 维空间中的超平面,想象一个 3 维空间,大声对自己说‘14’。大家都这么干。”

但是机器并不局限于此。随着计算能力的提高和更先进的算法,机器学习不仅加快了传统分析的速度,还可以进行仅使用手动方法永远不可能进行的分析。机器经常可以找到几十个变量之间的相关性,而人类科学家通常一次只能看到一两个。

技术让我们能够收集更多的数据并进行更广泛的分析

从历史上看,严格的假设检验是有意义的。收集数据是昂贵的,所以生物学家接受培训,以确保他们只收集他们需要的东西,并专注于一个非常具体的问题。亚历山大承认这种狭隘观点背后的原因:

“以前,生物学家必须开发一个框架才能让实验成功。没有电脑。没有高维数据。没有深度学习。你只有足够的时间和金钱来收集非常具体的东西来证明你的假设。

但是现在收集数据太便宜了。第一个全基因组序列花费了 100 亿美元,而同样的东西现在只需要 800 美元。”

生成数据突然变得如此便宜和容易,这一事实产生了两种相互冲突的思想流派:一些科学家仍然更加保守,而另一些科学家则渴望充分利用更新的技术。正如亚历山大解释的那样:

“基本上,两种心态是:‘当你不知道你是否需要时,为什么要收集所有你能收集的数据?’与“为什么不呢?因为有一天你会需要它。”

新毕业生正在引领这种观点的转变

亚历山大认为,如果我们要弥合生物学和数据科学之间的文化鸿沟,我们仍然需要大的变革,但他乐观地认为,这种转变已经在进行中。当新毕业生进入实验室时,他们带来了关于如何更有效地做事的强烈意见。正如亚历山大所说:

“研究生们会问,‘为什么我们还在手工做这个?“为什么我们没有机器人来自动完成这项工作,也没有数据科学来分析它,””

并且有可能训练人们看到对方的观点。亚历山大亲身经历了这种转变:

“这一切都与取景有关。以我作为生物学家的经验来看,一旦你在数据科学方面接受过培训并有了经验,你就可以从两个角度来看待它。”

我们需要发展假设检验,而不是抛弃它

亚历山大提醒我们,机器学习并不完全取代假设检验。相反,科学实践需要发展和适应,这样我们才能释放久经考验的科学方法与机器学习潜力相结合的优势。

Alexander 认为这种混合方法遵循一个“轻”假设:被你的假设引导但不被限制。正如他所说:

“微生物测序就是一个很好的例子。我不是对我在停车场找到的每一种微生物进行测序,而是在我感兴趣的领域寻找微生物。如果我想寻找擅长处理黄金的微生物,那么我会去金矿而不是农民的地里收集微生物。这是一个假设。你还是不乱做事。但是你平衡一下,这是有用的。”

这不全是关于人才:专有格式和合法性的挑战

尽管找到理解数据科学的生物学家仍然是一个挑战,反之亦然,但亚历山大表示,该领域受到其他因素的影响更大:

“数据科学很少受到技术人才的阻碍。”

专有数据格式是数据科学家生存的祸根

数据文件可以用不同的方式格式化。许多文件类型(如 PDF 文件)都有开放的标准:任何人都可以实现软件来处理 PDF 文件,并访问其内部流程的细节。

相比之下,生物技术数据通常使用专有或封闭的数据格式,这使得理解和使用这些数据更具挑战性。亚历山大指出:

“我们正在努力避免使用任何以专有格式存储数据的东西。这是我的数据科学存在的祸根:当有一些文件类型我不能用任何旧电脑打开时。它让我发疯。规范化、标准化和获取原始数据非常困难。”

专有软件混淆了内部处理

不仅仅是访问数据;这也是为了准确理解数据已经经过了哪些预处理步骤。亚历山大描述了有时发现这一点所必需的侦探工作:

“这尤其具有挑战性,因为我们经常无法访问。软件都是专有的,我们不知道数据是如何在内部处理的——从原始数据到输出。我们不仅需要标准化一堆不同机器的输出,而且我们还必须弄清楚在数据到达那个阶段之前它们对数据做了什么。那很辛苦。”

软件供应商使用模糊的法律来获得数据的所有权

为了帮助驾驭这种专有软件和数据格式的局面,许多团队向专业软件供应商寻求帮助。亚历山大也尝试过这个,但是他没有好的经历。他描述了无意中签署合同会如何导致失去数据本身的所有权:

“我们采访并评估了许多软件供应商。我们询问他们将如何为此提供解决方案,以确保我们可以访问数据,并确保他们不会因为将数据存储在他们的系统中而最终拥有这些数据。围绕它有许多法律术语。”

你正在努力寻找人才还是驾驭技术?

我们喜欢听到不同的团队如何将机器学习与生物技术结合使用。如果您需要帮助或只是想聊天,直接联系我们的首席执行官。

生物≠技术

原文:https://towardsdatascience.com/biology-technology-e3e2c3a86e97?source=collection_archive---------74-----------------------

理解神经网络的一种稍微不同的方法

由 Unsplash 上的 chuttersnap 拍摄

每当我阅读一本关于神经网络的教科书时,介绍总是非常相似:它们大多以源自生物学的动机开始。这一直让我有点困扰。我绝不是生物学家,但在我看来,生物神经网络和人工神经网络之间存在相当大的差异:

  1. 神经网络(通常)具有确定的拓扑结构,并且通过修改权重来进行学习。另一方面,天然神经元不断改变它们的结构来学习。
  2. 生物神经元有一个“全有或全无”的策略:要么刺激通过,要么不通过,而人工神经元具有平滑的激活功能。
  3. 生物神经元有更高的容错能力。

因此,因为这些事情,我从来没有真正弄清楚为什么生物学概念的抽象数学表达在实践中如此有效。在这篇文章中,我想从一个不同的角度来探讨这个话题,即从统计学而不是生物学的角度。

逻辑回归:简介

为了接近神经网络,我们首先回到“经典机器学习”,特别是逻辑回归。让我们从一个简单的二元分类问题开始,即我们想要区分两个不同的类别。我们举一个简单的例子(见下图)。基于两个特征(任意命名为特征 1 和特征 2 ),我们想要确定给定数据点属于哪个类。

图 1:有两个类的简单分类问题

因此,为了更精确地描述我们的问题,我们需要一个模型来给出一个数据点属于类 1 的概率,给定特征 1 和特征 2:

一级方程式

为了使书写简单一点,我们将从现在开始用 y 表示我们的类,用 x1,x2 = x 表示我们的特征,即上面的表达式变成

公式 2

重要提示:记住我们只有两个类别,所以如果我们已经计算了一个数据点属于类别 1 的概率,我们就可以很容易地计算出该数据点属于类别 2 的概率:

公式 3

贝叶斯统计为我们提供了一条如何重构公式 1 的规则:

等式 1

边缘化允许我们将等式 1 改写为

等式 2

现在我们将分母和分子都除以 P(y1|x) P(x ),这样我们得到

等式 3

现在我们做最后一步,再次重写等式 3。

等式 4

我们基本上只是用一个指数函数代替分母中的方程。请记住,自然对数和指数函数相互抵消。

下一步真的很重要,因为它说明了为什么我们称这种分类技术为逻辑回归。逻辑回归的核心是我们搜索特征的权重,使它们接近我们的α:

等式 5

在我们的例子中,D 是 2,因为我们只有两个类。w0 是我们也加入的一个偏差。因此,为了完成区分这两个类别的任务,我们需要学习三个权重 w0、w1 和 w2。

逻辑回归:应用

我不想回顾这些参数的实际学习过程,因为已经有很多关于这个主题的优秀文章。因此,我们现在将直接跳到模型的应用!让我们用逻辑回归分析上面的数据(图 1)。经过 500 次训练后,我们得到了以下结果:

图 2:500 个时期后经过训练的逻辑回归

哇,看起来不错!我们的模型几乎可以完美地区分这两个类别。让我们尝试另一个数据集,看看模型的表现如何。

图 3:新的数据集

根据图 3 中的数据,我们得到了以下结果:

图 4:500 个时期后经过训练的逻辑回归

嗯,这个型号一点也不好用。它看起来更像是一条穿过数据的随机直线。这是什么原因呢?要得到答案,我们必须回头看看等式 5。我们在这里看到的是,逻辑回归将特征乘以一个权重,然后将它们相加。所以我们这里有一个线性模型。Logistic 回归只能学会对线性可分的数据进行分类,或者通俗地说,可以用一条直线明确划分的数据。我们这里的数据显然不是线性可分的,因为两个类别之间的边界呈抛物线形状。但是我们可以相当容易地克服这个问题。到目前为止,我们刚刚在模型中输入了两个值:特性 1 和特性 2。现在我们只添加第三个特性(特性 1)。所以我们只要平方特征 1 的值。再次对相同的数据进行训练,我们得到了图 5 中的结果。

图 5

有了这个额外的特性,我们的模型几乎完美地拟合了数据。但这真的是可行的解决方案吗?我们希望我们的模型尽可能通用,这样我们就可以适应尽可能多的不同数据分布。还有大量的非线性函数。因此,如果我们想要对除了平方值之外的许多数据集很好地执行逻辑回归,我们将必须添加输入要素的立方、正弦、平方根和所有其他种类的非线性函数。我们可以构建一个修改的逻辑回归,其中我们不直接将特征输入模型。取而代之的是,我们定义某种黑盒,它采用原始特征并应用各种线性和非线性变换。

不像以前那样处理数学方程,让我们用图表来说明标准逻辑回归(图 6)和我们的修改版本(图 7)。

图 6:标准逻辑回归图

图 7:修改后的逻辑回归图

这两张图片看起来奇怪地类似于神经网络——因为它们就是!让我们暂时记住这一点:标准的逻辑回归只不过是一个没有隐藏层的神经网络。我们的修改版本确实是一个带有隐藏层的神经网络。主要区别在于,在真实的神经网络中,我们不需要像在这里一样手工设计隐藏层中的函数。

神经网络分类

现在让我们将逻辑回归获得的结果与实际的神经网络进行比较。首先,我们尝试一个没有隐含层的神经网络(图 8)。

图 8:没有隐藏层的神经网络

毫不奇怪,这种神经网络的性能与标准的逻辑回归一样差。只有当我们开始添加具有非线性激活函数的隐藏层时,我们才能学习非线性关系。所以让我们尝试不同数量的隐藏神经元。

图 9:左:带有一个隐藏神经元的神经网络。右图:具有两个隐藏神经元的神经网络

图 10:左图:有 12 个隐藏神经元的神经网络。右图:有 50 个隐藏神经元的神经网络

正如我们在上面的图片中看到的,只有一个隐藏神经元的网络表现很差,而两个神经元似乎已经足以进行良好的分类。看起来网络能够在两边找到两个直线决策边界。但是我们添加的隐藏神经元越多,边界就越平滑。这在底部中心尤其明显。

现在让我们来看看我们网络的内部运作。我在这个项目中使用的 Keras 库使得查看隐藏层的输出变得相当容易。

图 11:具有一个神经元的隐藏层的输出

图 12:具有两个神经元的隐藏层的输出

图 13:具有 12 个神经元的隐藏层的输出

图 14:具有 50 个神经元的隐藏层的输出

具有一个和两个神经元的隐藏层的输出并不令人惊讶。用一个神经元,我们可以检测一个边界,但不能检测另一个,而用两个神经元,我们已经可以获得相当好的结果。查看具有 12 个和 50 个隐藏神经元的网络的输出,我们可以做出两个观察:

  1. 相当多的神经元的输出看起来非常相似。所以这可能是一个暗示,我们实际上不需要这么多隐藏的神经元,因为它们中的许多并没有增加任何额外的信息。
  2. 在前两个网络中,我们看到的不仅仅是近乎线性、非常清晰的边界,而是相当多的输出值在非常窄的范围内,没有形成清晰的边界。因此,这些输出可能有助于使整体分类更加平滑。

总的来说,我们对结果很满意。我们的网络只需要几个隐藏的神经元和几秒钟的训练,就能实现良好的转换,而不是像逻辑回归那样,必须对我们的输入特征进行良好的转换。

结论

我希望这篇文章能让你对神经网络有一个有趣的新看法,并让你更清楚地了解神经网络的想法来自哪里,以及它们为什么工作得这么好。所以,也许下次你遇到神经网络时,不要把它们仅仅视为生物神经元的抽象模型,而是非线性特征转换器(隐藏层)与逻辑回归(输出层)的结合——这是一个相当简单的概念,不是什么神奇的东西,也不是“一个可以工作的黑盒”!

生物认证方法

原文:https://towardsdatascience.com/biometric-authentication-methods-61c96666883a?source=collection_archive---------10-----------------------

指纹、面部识别、手形、虹膜识别、视网膜识别、语音识别、击键动力学和手写签名

作者图片

长期以来,生物识别一直是未来身份认证的目标,预计生物识别身份认证将在很大程度上取代我们当前身份认证和访问控制的其他方式。生物识别系统可用于以下两种不同的模式。

  • 【1–1】:确定一个人是否是他所声称的那个人。在验证模式下,系统通过将捕获的生物特征数据与存储在数据库中的模板进行比较来验证个人的身份。
  • 【1-n】:确定人是谁。在识别模式中,系统通过在数据库中搜索所有用户的模板进行匹配来识别该人。

生物识别系统首先通过 从个人处获取 生物识别数据,然后 从数据中提取 特征集,最后 特征集与数据库中的模板进行比较,如下图所示。

作者图片

什么是生物识别技术?

生物特征的使用,或者具体地说是独特的人类特征,已经以一种或另一种形式存在了数百年,无论是对一个人的身体描述,还是最近的一张照片。生物特征认证技术根据评估的特征类型进行分类:生理属性或行为异常。

生理生物统计学

生理生物识别是基于根据作为人体的一部分获得的数据(如指纹、面部或眼睛虹膜)对一个人进行分类。

指纹识别

迄今为止最流行的生物特征识别,指纹识别,可以利用多种分类方法,基于细节,这些细节是在手指和拇指的手掌侧、手掌和脚底发现的表皮摩擦皮脊的再现。我们可以使用它们进行身份验证,因为基本原理如下。

  • 指纹在一个人的一生中不会改变。
  • 指纹有一般的脊线图案,可以对它们进行系统分类。
  • 指纹是一种个人特征,因为还没有发现两个手指具有相同的纹线特征。

作者图片

手的几何形状

第二个最广泛使用的生物特征是手形。我们使用手的几何特征,例如手指的长度和手的宽度来识别个人。

面部识别

该系统通过数码摄像机记录面部图像,然后分析面部特征,如眼睛、鼻子、嘴巴和下巴边缘之间的距离。

虹膜识别

下图显示了人类眼睛的一部分。

作者图片

虹膜是眼睛瞳孔周围的有色组织,由具有许多沟和脊的复杂图案组成。

视网膜识别

基于视网膜的身份识别被认为是最安全的身份认证方法。视网膜识别通过获取内部身体图像,即必须以难以伪造的方式合作的自愿者的视网膜/脉络膜,来提供对个人的真实识别

行为生物测定学

它由从用户动作中获得的测量值组成,其中一些是从人体中间接测量的。

语音验证

声音验证系统不同于声音识别系统,尽管两者经常被混淆。语音识别是识别一个人说什么的过程,而语音验证是识别说话的人。

击键动力学

该系统测量和比较特定的定时事件,也称为“打字签名”。人们在键盘上打字的方式展示了一些独特的特性。

手写签名

签名识别系统试图根据人们的手写签名来认证他们

生物认证方法的比较

我们根据安全性、准确性、持久性、可用性、充分性和成本这六个特征对生物认证方法进行了比较,分为三个级别,分别是

下表提供了本帖中生物特征类型的快速比较。

生物认证方法的比较

安全性

这是系统在覆盖风险方面的优势,以及在考虑潜在攻击所代表的风险及其复杂性的基础上抵御潜在攻击的效率。

  • 高安全性 :指纹、手形、虹膜、视网膜。
  • 中等安全 :面部、声音、手写签名。
  • 低安全 :击键动力学。

准确(性)

由于收集数据的环境不同,或者生物识别中使用的阅读器不同,不可能达到 100%的准确性。因此,必须定义某些性能阈值,以考虑可靠的生物识别技术。用于评估生物识别性能的两个常规指标是 FAR 和 FRR。

  • 高精度 :指纹、虹膜、视网膜。
  • 中等准确度 :面部、手部几何、手写签名、语音。
  • 低精度 :击键力度。

持久

这是生物特征不应该随着时间而改变的条件。

  • 高持久性 :指纹、面部、手形。
  • 中持久性 :虹膜、视网膜。
  • 低持久性 :语音、击键力度、手写签名。

可用性

方便用户和更贴近用户需求和要求的品质

  • 高可用性:指纹、面部、按键力度和语音。
  • 中等可用性:手形和手写签名。
  • 可用性低:虹膜和视网膜。

费用

技术在整个认证系统中的经济影响,如实施成本、维护等。

  • 高成本:手形、虹膜、视网膜、手写签名。
  • 中等成本:指纹。
  • 低成本:面部,语音和按键动力学。

适当

能够满足特定用户群(如零售、公司、私人和投资者客户)的需求和期望的质量。

生物认证技术的用户部分

生物识别是如何被黑的?

重放攻击

在重放攻击中,入侵者能够记录涉及生物识别系统或设备的成功登录会话,然后试图通过重放捕获的数据自行执行身份验证。

例如,在语音验证系统中,黑客能够截取并记录包括用户语音在内的数据。他稍后可能试图访问同一系统,并将回放先前捕获的记录数据。

伪造的证件

一些生物识别系统可能容易受到使用伪造凭证的攻击。例如,如果生物识别系统依赖于面部识别,黑客可以通过在摄像头前拿着用户的真人大小的照片来欺骗这样的系统。

被盗凭据

一些生物识别系统比其他系统更容易受到被盗凭证的攻击。但是一想到被偷的眼睛,我们就毛骨悚然。然而,我们认为如果你的生物识别系统是基于声音的,你是相当安全的,因为我们还没有听说一个被盗的喉被用来成功骗过生物识别系统。

结论

如今,生物特征数据提取可以很容易地实现,而不需要特定的传感器;因此,当利用现代技术时,例如配备有用于面部识别或指纹的嵌入式相机的移动设备,其实现可以是低成本的。

生物认证方法的类型

指纹

由于成本低、易于使用和部署,它们是部署最广泛的技术,甚至不包括警察指纹识别。

但是有许多方法可以击败生物指纹扫描技术,例如假乳胶手指,一种表面蚀刻有指纹的木头。我们可以通过强迫使用多个手指来解决这些问题。

面部识别

由于其成本,面部识别受益于高用户接受度,但尽管如此,它们在非标准环境中的性能较低。

除此之外,这种方法也很脆弱,允许使用不难获得的“自拍”进行认证。因此,它必须伴有额外的方法,如活性检测机制。

语音验证

语音验证受益于高接受率,因为它的高可用性和成本。

与面部识别类似,结果表明在非标准环境中表现不佳。因此,语音认证技术不能被认为是足够成熟的,同样,它们必须伴随或结合其他机制。

此外,语音识别算法必须能够容忍噪音,并且不应受到喉咙痛或感冒产生的声音变化的影响。

击键动力学

由于不需要特殊设备,这种方法几乎不需要成本;它的可用性和可接受性被认为是高的,因为在大多数情况下,它可以对用户透明地执行。

然而,这种技术的主要缺点是其在训练阶段的低准确性和低安全性;因此,它适合于实现连续认证。

简单对吗?

基于隐马尔可夫模型的笔迹生物特征识别

原文:https://towardsdatascience.com/biometric-signal-verification-of-handwriting-with-hmms-8808cbd05699?source=collection_archive---------24-----------------------

使用 hmmlearn 在 Python 中实现

数码师在 Pixabay 拍摄的照片

数字签名正在兴起。由于我们中的许多人现在在家工作,许多机密的公司电子邮件需要在线签名。
伊恩古德费罗斯(Ian Goodfellows)发明的生成对抗网络(GAN)展示了如今在数据集上生成虚假数字是多么容易。这实际上只是一小步,也能够生成模仿任何人的笔迹风格的签名。但是那不是很危险吗?

我们能用机器学习来区分原始签名和人工制作的签名吗?我们确实可以!我们甚至不需要那些花哨的神经网络方法,我们可以用隐马尔可夫模型(HMM) 完全经典。在这篇文章中,我将展示我们如何结合 HMM 来分类签名是原始的还是模仿的。

这个项目的灵感大致来自朱利安·菲尔兹等人的论文。艾尔。发表于 2007 年,名为:基于 HMM 的在线签名验证。

介绍

即使隐马尔可夫模型不是最先进的,正如上面论文的出版日期“2007”已经表明的,它们仍然是每个数据科学家至少应该听说过的基本概念。当你想了解更近期的技术如递归神经网络时,理解 HMM 的工作方式会有启发,因为许多技术都是从 HMM 的基本思想发展而来的。

隐马尔可夫模型

隐马尔可夫模型可以在它们的计算中包括时间相关性。在下面的图 1 中,我们可以看到,从每个状态(雨天、晴天)我们可以来回转换到雨天或晴天,每个状态都有一定的概率在每个时间步长发出三种可能的输出状态(步行、购物、清洁)。总是需要提供开始概率(雨天 60%,晴天 40%)来开始计算链。

图 1 来自维基百科:隐马尔可夫模型

在我们的情况下,这意味着签名是从左到右,一个字母接一个字母地写。所以时间依赖关系包括笔移动形成一个字母的速度,压力和坐标。所有这些信息都可以考虑在内,以估计签名是由原作者书写还是伪造的可能性有多大。

图 1 表明我们需要预先了解:

  • 开始概率(雨天 60%或晴天 40%) 向量
  • 过渡(例如从多雨到多雨 70%) 矩阵
  • 排放(从雨天到步行 10%、购物 40%或清洁 50%) 矩阵

请注意,开始概率总计为 100%,对于矩阵转换和发射,每行总计为 100%。

高斯混合模型(GMM)

我们需要依赖于时间的数据并从中计算特征,然后我们可以拟合 GMM 来找到我们的 HMM 的参数。当我们有了 HMM 的参数,我们可以计算原始签名和模仿签名的分数。根据分数,我们可以对签名的真实性进行分类评估。

为什么我们首先要使用高斯混合模型来训练 HMM 参数?嗯,基本上 hmmlearn 为我们提供了三种选择:

  • GMM-嗯
  • 高斯 HMM
  • 多项式 HMM

GMM 效果最好,因为估计我们特征的密度很可能不仅仅是单个高斯或单个分布,而是地面实况看起来更像一个山谷,可以通过 GMM 更好地近似。

我们可以利用 GMM 的所谓 EM(期望最大化)算法,让我们自动计算那些隐藏参数。EM 算法期望什么来计算隐藏参数?

答案是:特色

GMM 使用 EM 算法计算其参数:

  • 步骤 e:使用 GMM 参数(均值、方差)的当前估计值计算组件占用概率 P(M|x)
  • 步骤 m:使用组件占用概率的当前估计值计算 GMM 参数。

我们必须选择 GMM 的超参数,它们是:

  • m:高斯混合分量
  • 学生:嗯,状态(晴天,雨天)

实际上,我们无法知道最佳的超参数集是什么,但是我们可以使用 K-Fold 交叉验证来找出答案。

等等什么,超参数,HMM 参数?

好的,超参数是我们人类需要选择的值。这也叫模式选择问题。模型参数是 GMM 和 EM 算法为我们计算的参数。

资料组

用于测量这些类型的特征(压力、速度等。),我们需要一个类似于下图最左侧所示的设备:

图 1 by [1]:提出的在线签名验证系统的体系结构。

我用的是 mobisig 数据集。它总共包含 83 个条目(49 个男性,34 个女性),我们稍后将把它们分成训练集、测试集和模拟集。签名是由 Margit Antal 等人收集的。艾尔。并于 2017 年发表在他们的研究论文中:mobi SIG 指画签名语料库上的在线签名验证

本文提供了一个签名示例。

图 2 by [2]:来自数据库的伪签名。第一列包含真实签名,第二列包含伪造签名。

可以看出,伪造签名包含了更密集连接的压力点。这篇论文解释了伪造是如何产生的。如果你愿意,你可以阅读它,但这篇文章的重点是我们如何检测这种伪造,而不是它是如何产生的。

包导入

我将使用 python 的HMM learn包,这样我就不用从头开始构建 HMM 了。

让我们从导入这个项目的默认包开始。我设置了随机种子,所以你会有和我完全一样的情节。

文件加载

此外,我们希望确保正确地加载数据集,如上面的代码片段所示。数据存储在字典中,每个人有两个条目(“原始”和“模仿”),每个条目被进一步分成多个签名。此外,所有签名都有几百或几千行带有时间戳 id(以毫秒为单位)。

特征抽出

回头看图 1,第一步是特征提取。如果数据点以零为中心并且具有标准化的标准偏差,则拟合高斯,尤其是混合高斯会更加有效和高效。从文献[1]中,我们可以得到以下归一化步骤:

图 3: 1。步骤:位置标准化

接下来,我们在归一化步骤之后提取四个特征。公式(2。步骤)从[3]中获得:

2.步骤:特征提取

规范化步骤 1 显示在代码的函数(第 1–2 行)中。图 3 中的公式只是对所有 x 和 y 求和,然后除以出现次数 n,因此只需取平均值。此外,增加了ε(e =NP . finfo)来防止除以零的错误。

第 2 步中的四个特征非常容易计算。x 和 y 上的点表示使用我们刚刚计算的赋范 x 和 y。除此之外,theta can 的计算与代码第 24 行中的公式完全一样。第 27 行用同样的方法计算路径速度。它只是平方根!

特别要注意的是对数曲率半径,因为如果你仔细观察,你会发现作者希望θ也被归一化。因此,在计算ρ(ρ)的第 30 行,我们也调用θ(θ)上的范数函数。

我在代码中把最后一个特性称为 alpha,因为它听起来比 a 更好。它和代码第 33 行中的其他特性一样容易计算。

我将所有的特征添加到它们相应的列表中,因为我们需要将这些特征输入到隐马尔可夫学习函数中。

因此,我们完成了特征提取步骤。现在让我们建立模型。
哦不! 我们需要将数据分成训练、测试和模拟数据集。从提到的条目中,我使用前 25 个人作为训练示例,这是防止过度拟合的最小数量,其中一个条目对应于一个人的多个签名。所以列车组包含 25 个不同的人,他们有许多真实和伪造的签名。测试集包含另外 20 个不同的人,验证集(X_val)包含所有模仿的签名。

***X_train: (3940, 8)
X_test: (3140, 8)
X_val: (10338, 8)***

因为我说过所有签名的行长度是不同的,所以我总是需要跟踪当前长度,并将其附加到新的数据帧中。正确编程是相当困难的。在第 51 行,我将特性重命名为特性提取步骤中的名称。

需要注意的是,我在第 47–49 行调用了特征提取函数来计算特征。

建立 GMM-HMM 模型

为了训练 GMM HMM,我们需要看一下来自 hmmlearn 的文档。

我们需要两个基本变量:

  • transmat(转换矩阵)(雨天,晴天)
  • startprob(开始的初始概率矩阵)(60% 40% —根据 S 的数量( HMM 状态))

转移矩阵将被参数化,使得它以 50%的概率(0.5)对角填充,除了第一个和最后一个条目。这是 hmmlearn 在文档中建议的。startprob 矩阵也是如此,我从 hmmlearn 中选择了默认的初始化。

特征变量 X_train 现在包含一个时间戳和每行七个特征:

  • x 和 Y 位置
  • 压力
  • 四个提取的特征

现在我们可以在下面代码的第 20 行创建模型。成分的数量和混合的数量在模拟签名的估计有多好方面起着重要的作用,但是正如已经说过的,我们无法知道最佳值是什么。因此,我尝试了不同的组合。让我们来看看这两个超参数是如何相互对抗的。

第 35、39 和 43 行中的 score 函数计算三个不同集合的分数。这些分数由 GMM 的目标函数计算得出,即负对数似然**

好了,让我们用不同的分量值和 GMM 值调用 fit_hmm 函数:

绘制 gif 图

当我们拥有一组分数不同于或低于原始签名(蓝色或绿色)的模仿签名时,我们称之为成功。

由我用 Matplotlib 创建:用户 3

由我用 Matplotlib 创建:用户 7

我们可以看到,HMM 状态的数量对分数的影响最大。我们希望分数尽可能将红点(模仿)与原始蓝点和绿点分开。七个或更少的 HMM 状态似乎很好地将红点从其余的中分离出来,并且 GMM 分量显然对输出的影响很小。

估价

如果我们在彩色点之间画一条线性分类线,

如果签名是假的,请分类

我们可以看到 HMM 能够多好地检测签名是否是伪造的。例如,我们将阈值设置为-2200,然后对新的签名进行评分。如果分数的值小于-2200,我们认为它是假的,如果分数大于-2200,我们认为它是原始签名。

延长

我们现在可以做的是保存分数,并训练例如逻辑回归来预测概率(0-100%),基于签名是否是原始的分数这个逻辑回归可以用 sklearn 的准确度分数进一步扩展,以估计模型的不确定性。**

结论

成功!我们可以成功地区分模仿签名和原始签名。一些也映射时间约束的最新方法是递归神经网络。但是现在,我们看到这也可以用非常经典的方法实现,比如 HMM。

要了解更多信息,你可以访问我的网站,并在我链接的社交媒体中添加我。如果你在这篇博文上给我鼓掌,我会很高兴的:)。

参考

[1] Julian Fierrez 等人。艾尔。、 HMM-based 在线签名验证:特征提取和签名建模 (2007)、科学直接
【2】马吉特·安塔尔、拉斯洛·佐尔特·绍博和图·NDE·托尔戴
* 在 MOBISIG 手指绘制签名语料库上的在线签名验证 (2017)、欣达维
【3】朱利安·菲尔雷兹等。艾尔。,基于局部和全局信息融合的在线签名验证系统 (2005), Springer***

这篇博文基于从弗里德里希·亚历山大大学埃尔兰根-纽伦堡的课程模式分析中获得的知识。我使用了 Christian Riess 博士演讲的部分内容来说明这篇文章的例子。所以所有权利归克里斯汀·里斯博士所有。

生物分子序列分析

原文:https://towardsdatascience.com/biomolecular-sequence-analysis-1748869ccb2b?source=collection_archive---------67-----------------------

第一部分:序列相似性搜索

亚历山大·波波夫在 Unsplash 上拍照

在某种程度上,生物分子序列“只是”固定字母表上的字符串。这可能会吸引计算机科学家,即使他们发现分子生物学神秘而有趣,但他们绝对理解字符串和字母!

在 DNA 和 RNA 中,这个字母是 A、C、T 和 g。在蛋白质序列中,这个字母是组成蛋白质的 20 个氨基酸。当然,在序列内部和序列之间发生了很多事情。这是分子生物学家和生物技术人员的领域。

在这篇文章中,我们将讨论所有生物分子序列分析中最有用的计算算法和工具:在已知序列的数据库中搜索一个新序列,以找到相似的序列。

为什么序列相似性搜索很重要

考虑一个已知蛋白质序列的数据库,注释了关于它们的已知信息,例如它们的功能和它们的进化谱系。考虑一个新确定的序列。搜索数据库来寻找与这个新序列高度相似的序列可能会很有启发性。这可能有助于阐明这个序列在进化等级中的位置。它也可能产生对这个序列的功能作用的见解。

以新冠肺炎序列为例。谁知道在已知病毒序列的数据库中搜索会发现什么。

变异游戏

这将极大地有助于理解接下来的相似性搜索问题。相信我。

我们会挑选 DNA 序列。只是因为他们的字母表更容易描述。这个游戏的经验同样适用于蛋白质序列。

游戏的整体结构是:

  1. 我们从一组不同的序列开始。
  2. 我们将这些收集到一个数据库中,我们称之为“已知序列”。
  3. 我们以特定的方式突变其中的一些序列(我们将在后面讨论细节)。
  4. 这些产生了我们所认为的“新确定的”序列。
  5. 我们使用相似性搜索算法和工具在数据库中搜索这些“新确定的”序列。
  6. 如果一切顺利,在每种情况下,我们都希望找到产生突变序列的序列。(正如我们很快就会看到的那样,事情不会总是一帆风顺。)

变异模式

我们将重点介绍三种类型的变异操作:在某个位置插入一个新符号,删除某个位置的符号,用另一个符号替换某个位置的符号。第三个是通过一个替代矩阵来完成的,该矩阵捕获替换偏好。我们把这三个操作分别叫做 I,D,S。

我们假设 I 和 D 中的每一个都有一个固定的概率,这个概率不依赖于突变在序列中的位置。(这个假设可以放宽。在一些特殊的用例中,这非常有帮助。然而,它有训练数据和算法结果。)替换也将用概率来建模。

让我们看一个例子。(我们将概率表示为百分比。)说 P(I) = 5%,P(D) = 8%。这意味着在任何位置都有 5%的机会插入字符,8%的机会删除字符。我们假设插入的字符是随机选择的。(更高级的模型允许在要插入的字符上的分布取决于位置。在某些用例中,这非常有帮助。然而,这也使建模变得复杂。)

假设我们的替代矩阵是

 A   C  T  G
A **90%** 2% 4% 4%
C 7% **80%** 5% 8%
T 3% 5% **85%** 7%
G 6% 2% 3% **89%**

首先,我们来带出它的特点。每行总和为 100%。这是因为包括了自身替换。所以,在每一个位置,一定会发生一些替换。第二,对角线项接近 100%。这表明自我替换比改变符号的可能性要大得多。最后,注意我们的替换矩阵是不对称的。对称在这个阶段是额外的不必要的假设。

突变单个序列

让我们来做一个突变单个序列的心理模拟。我们将获得一个输入序列,并从左端开始,在每个位置上概率性地应用三个变异操作。我们将展示有变化的所有中间序列。

我们的首发顺序很傻;尽管如此,它将完成我们为它设定的任务。

AAAAAAAAAA → AA**T**AAAAAAAA → AA**T**AA**G**AAAAA → AA**T**AA**G**AAAA
                                                 ^

第一个突变是紧接在位置 2 之后的 T 的插入。第二个是替换 A → G,我们用粗体标出了这两个。第三个是删除序列中倒数第二个字符。我们用^.标记了这一删除

最后,我们可以通过简单地多次重复这一过程来模拟更长期的进化。也就是说,我们对序列进行多次突变。毫不奇怪,我们通过的次数越多,最终的突变序列与我们开始时的序列差异就越大。由此产生的突变序列被称为(起始序列的)远源同源物。

突变多个序列

既然我们已经详细了解了突变单个序列所涉及的内容,让我们继续来突变几个。这当然是现实中发生的事情。对我们的目的同样重要的是,它将帮助我们更好地理解为什么序列相似性算法如此复杂。简而言之,我们突变的序列越多,就越难辨别突变序列是从哪个序列进化而来的。

为了阐明上一句的观点,我们将从一个比第一个更愚蠢的例子开始。

AAA → A**C**AA → ACA
ACC → A**A**C
TTT → **C**TT

AAA、ACC 和 TTT 这三个序列中的每一个都发生了突变。注意,第一个序列经历了两个突变。

现在让我们将已知序列的数据库设置为我们开始时的数据库:{AAA, ACC, TTT}。可以考虑用 ACA 搜索一下。有理由期待会发现两个结果:AAA 和 ACC,因为它们都与 ACA 足够相似。接下来,考虑在数据库中搜索 CTT。在这种情况下,只有一个结果将被发现,TTT,在同一水平的相似性。

我们试图用这种比较来说明什么?

*The statistical significance of a search result depends on the number of search results on the same query that get found*. 

结果 ACA → AAA 不像结果 CTT → TTT 那样具有统计显著性,因为对于查询 ACA 有两个足够相似的结果,而对于查询 CTT 只有一个。这也有直观意义吧?我们对 CTT → TTT 的结果更有信心,因为它是独一无二的。在 ACA → AAA 中不那么明显,因为它不是。

如果我们把这个例子扩大到现实,直觉会变得更有说服力。当在足够高的相似性阈值下搜索数百万个序列的数据库时,一个查询可能返回唯一的结果,第二个查询可能返回数千个结果。显然,第一个查询的结果比第二个查询的结果更重要。

编辑距离

至此,我们已经不严格地使用了术语“相似”和“相似性阈值”。现在让我们将它们形式化。这将有助于我们更具体地理解上述问题。它也是通向更高级的相似性度量的桥梁,我们将在讨论具体的相似性算法时看到。

两个序列的编辑距离是将一个序列转变成另一个序列所需的最小突变数。考虑(AAA,ACA)。它们的编辑距离是 1,因为我们可以通过一次替换将一个转换为另一个。

编辑距离是量化两个序列之间相似性的一个很好的近似度量。我们说“近似”有以下几个原因。首先,可能发生了比编辑距离所暗示的更多的突变。拿我们的例子 AAA → … → ACA。这涉及到两个突变。编辑距离建议一个。第二,编辑距离不能捕捉特定突变的不同概率:插入、缺失和特定替换。

好的,让我们用编辑距离的语言重新表达一下我们之前看到的例子。我们的数据库是{AAA, ACC, TTT}。根据它搜索 ACA 会在编辑距离 1 处找到两个结果。搜索 CTT 在编辑距离 1 处找到一个结果。

所有三个结果到查询的编辑距离相同。然而,如前所述,第三个结果比前两个结果更具统计学意义。也就是说,它更值得信任。

显然,编辑距离无法衡量统计意义。我们需要一个独立的机制。我们就不详细讨论了。它体现了我们已经讨论过的原则:一个查询返回的结果越多,应该分配给其中任何一个的信任就越少

在所谓的“局部比对”搜索的设置中,结果的统计显著性从“非常重要”到“极其重要”。到目前为止,我们还没有讨论“局部比对搜索”。所以读者可能不知道我们的意思。然而,我们认为在现阶段提出这一点是重要的。

序列相似性算法

我们已经看到了各种变异算子。现在让我们描述考虑到这些的序列相似性算法。

全局对齐

首先,我们需要另一个关键概念。两个序列(相同类型:DNA 或蛋白质)的全局比对是它们的符号之间的 1-1 对应,遵循序列顺序。让我们看一个例子。

A-CAT     ACAT
| | |     ||||
AAC-T     AACT

我们看到 ACAT 和 AACT 两个序列的两个全局比对。左侧对齐中的“-”符号表示“‘无’与符号对齐”。这些实现了移动一个或另一个序列的效果,使得对准的符号是兼容的。第二次对齐不使用任何“-”符号。

凭直觉,读者可能会猜测左边的排列比右边的好。读者可能是对的。这个会在下面出来。

全球比对分数

接下来,我们描述全局比对分数的概念。最常用的形式,实际上也是我们将描述的算法所使用的形式,简单地将比对中各种比对对的分数相加。

这里有一个例子。考虑左边的对齐方式,可能表示为{(A,A),(-,A),(C,C),(A,-),(T,T)。该比对的分数可以描述为

S({(A,A),(-,A),(C,C),(A,-),(T,T)}) = **S(A,A)** + *S(-,A)* + **S(C,C)** + *S(A,-)* + **S(T,T)**

粗体的术语对应于我们之前在突变游戏中看到的替换。斜体术语对应于插入和删除突变。

关键的一点是,尽管序列相似性算法至少部分是由突变博弈的考虑所驱动的,但在实践中,当比较两个序列时,我们经常不知道哪个扮演祖先的角色,哪个扮演后代的角色。

事实上,在许多用例中,甚至可能不存在这样的关系。想象一下,试图辨别两个序列是否是不太远的祖先的兄弟。高度的序列相似性可能对此有所帮助。很明显,没有祖孙关系,只有兄弟姐妹关系。

鉴于以上所述,相似性算法对称地对待两个序列是有意义的。其结果是对齐中出现的'-'不再能被解析为插入或删除。考虑对齐对(X=A-,Y=AA)。如果我们认为 Y 是祖先,那么'-'可以被视为删除,如果我们认为 X 是祖先,那么'-'可以被视为插入。由于这个原因,从现在起我们称 a 为'-' an indel 。事实上,我们将更进一步。我们将使用术语 gap 来表示 indel ,因为它听起来更好。

其进一步的结果是,将间隙与实际字符对齐的成本是相同的,而不管间隙是在顶部还是在底部。

接下来,让我们根据上一段中提到的要点来改进我们的分数示例。 S (A,A)S(C,C)S(T,T)都是来自一个 DNA 置换矩阵的分数。 S (-,A)和 S (A,-)都由一个负数表示,称为缺口成本。这个数字是负数,因为它是成本。

现在让我们详细阐述一下 DNA 置换矩阵。这在性质上类似于我们之前看到的 DNA 替换矩阵,在突变游戏中。性质相似但不相同。

如果你想知道为什么两个替换矩阵会不同,请阅读下一段,否则跳过它(它有点长,而且有点偏离我们在这篇文章中的主要路径)。

由于前面讨论的原因,相似性算法对称地处理两个序列。这意味着我们的替换矩阵也需要对称。相比之下,进化替代矩阵不必如此。第二个原因是我们正在对单个比对对的分数求和。在我们的例子中,限于涉及替换的术语,这是 S (A,A) + S (C,C) + S (T,T)。如果替换矩阵条目是概率(就像在突变游戏中那样),我们将会进行乘法运算。实际上还有更多。我们就陈述一下,不做解释。符号的对齐对(X,Y)的得分 S (X,Y)被定义为 log [ P (X,Y)/[P(X)P(Y)],其中 P (X,Y)是在真实的全局对齐中看到对齐对(X,Y)的概率,而 P (X)和 P 【T

好吧,回到主路。出于说明的目的,甚至下面的替换矩阵就足够了:

S(X,Y) = 1 if X equals Y and -1 if not. 

给定这个替代矩阵,我们想要选择一个绝对值小于 1 的缺口成本。我们把它设置成。

好了,现在我们已经准备好计算我们两个全球比对的精确分数了:

S({(A,A),(-,A),(C,C),(A,-),(T,T)}) = 
S(A,A) + *S(-,A)* + S(C,C) + *S(A,-)* + S(T,T) **=** 1–½ +1–½ +1 = **2**S({(A,A),(C,A),(A,C),(T,T)}) = 
S(A,A) + S(C,A) + S(A,C) + S(T,T) = 1–1–1+1 = **0**

第一次比对得分较高,如您所愿!

找到高分比对

我们现在知道如何进行全球比对。接下来,我们将介绍如何在众多比对中找到得分最高的比对。这是更多奇迹发生的地方。

给我们两个 DNA 序列 X 和 Y,置换矩阵 M,以及缺口成本 C < 0. Our aim is to find the highest-scoring alignment of X and Y.

The exhaustive search approach of generating every alignment, scoring each, and picking the one that scores the highest is excessively slow on long sequences. There are too many alignments to wade through!

Fortunately, there is a clever algorithm that is guaranteed to find an optimal alignment much faster. It uses an approach called dynamic programming.

The algorithm involves building a matrix S with n +1 行和 m +1 列其中 nm 分别是 X 和 Y 的长度。

接下来,关键点来了。花时间去吸收它。不到一分钟,我保证。

*S*(i,j) is the score of a best alignment of the first *i* symbols in X with the first *j* symbols in Y.

为什么这很重要?该算法的关键思想是以最优方式解决问题的较小版本,并从这些版本中为较大版本构建最优版本。具体来说,我们从左上角开始填充矩阵,最终在到达右下角时停止。(我们将很快介绍完整的端到端示例。)

我们首先将 S (0,0)设置为 0。这是有道理的。没有要对齐的内容,因此它的得分为“nothing”,其数值转换为 0。(注意“没什么”不等于“不知道”。)

接下来,我们为所有的I0 设置 S ( i ,0)到 i *C,为所有的 j > 0 设置 S (0, j )到 j *C。为什么?考虑 S ( i ,0)。它是 X[1]的最佳比对的分数.. i 带有空前缀 y .这样的对齐只有一个,其中 X[1.. ii 间隙对齐。这次对齐的分数是 i *C,同理,我们可以看出为什么 S (0, j )被设置为 j * C

下一个关键点现在来了。如何从 S 矩阵中到那时的分数计算出 S ( ij )。这是公式

S(i,j) = max{ S(i-1,j-1) + M(Xi,Yj), S(i,j-1) + C, S(i-1,j) + C}

max 中的第一项对应于扩展 X[1.. i -1】和 Y[1.. j -1】添加对齐的对(X[ i ,Y[ j )。得到的比对分数为 S ( i -1, j -1) + M(X i ,Y j )。

max 中的第二项对应于扩展 X[1.. i 和 Y【1.. j -1】通过添加对齐的对(-,Y[ j ])。X 部分是一个间隙,因为正在延伸的路线中已经有 X[I]。

第三任期为第二任期,其中 ij 互换。

S(i,j)被设置为“最佳中的最佳”,即这些项中的最大值。

到目前为止提出的算法仅找到最优全局比对的分数,而不是比对本身。在我们讨论后一个话题之前,让我们先来看一个端到端的例子,因为即使在评分部分也有很多东西需要学习。

示例

如果 x 等于 y ,我们将使用替换矩阵 S ( xy ) = 1,否则为-1。我们会用差距成本。我们将计算 X = ACA 和 Y = AAC 的全局比对分数。(即使在这个简单的例子中,得到的分数矩阵也会惊人的丰富!)

 **A      A      C**
      0     -½    -1    -3/2
**A**    -½     1      ½      0
**C**    -1     ½      0     3/2
**A**   -3/2    0     3/2     1

在解释这个矩阵中的各种值之前,让我们检查一下最后的分数,即右下角的“1”是否正确。对于我们的替代矩阵和缺口成本,ACA 和 AAC 的最佳比对是

ACA-
| |
A-AC

这次比对的分数确实是 1。

现在让我们讨论一下这个矩阵中的一些不同的分数。第一行和第一列中的分数对应于将连续的缺口串与另一序列的前缀进行比对。我们之前已经看到过,这是一个初始化步骤。

接下来我们来看看分数 S (1,1)。这表示 A 与 A 的最佳比对分数。它应该是 1。它的值来自于项 S (0,0) + M(A,A) = 0 + 1 = 1。很容易检查到来自其他项的分数,即涉及 S (0,1)和 S (1,0)的分数较低。

接下来我们来看看分数 S (3,2)。这代表 ACA 与 AA 的最佳比对分数。我们可以看到这种排列必须是(ACA,A-A)的形式。它的分数是 2 –= 3/2,这正是我们所看到的。

从得分矩阵重建最佳比对

在许多用例中,例如数据库相似性搜索,对两个序列进行相似性评分就足够了。可以单独使用查询结果相似性得分来对相似性数据库搜索的结果进行排名。

在其他用例中,我们还需要找到实际的最佳匹配。我们现在涵盖这一点。

关键思想是这样的:当我们构建评分矩阵时,我们记录在计算单元格的值时使用了哪个术语。也就是在计算 S ( ij )、 S ( i -1、 j -1)、 S ( ij -1)、或 S ( i -1、 j 【T(如果使用了多个,如果我们想要找到所有的最优全局比对,我们应该记录所有的,或者如果我们只寻找一个,则任意地打破联系。)

让我们看看添加了额外元数据的示例版本。计算 S ( ij ),D 表示使用了 S ( i -1, j -1),L 表示使用了 S( ij -1),U 表示 S ( i -1)d、L、U 分别对应对角线、左、上。

 **A         A        C**
     0       -½       -1       -3/2
**A**    -½      1 (**D**)    ½ (**D,L**)   0 (**L**)
**C**    -1      ½ (**U**)    0 (**L,U**)   3/2 (**D**)
**A**   -3/2     0       3/2 (**D**)    1 (**L,U**)

下面解释一下 S (2,3) = 3/2 附带的元数据。这个元数据是 d,我们看到 X[2]和 Y[3]都等于 C,因此我们可以看到 S (2,3) = S (1,2) + M(C,C)。

回溯阶段:一旦构建了完整的得分矩阵(包括元数据),通过反向“回溯”来重建实际的最优比对。这可以被视为仅仅跟随从矩阵的右下角单元开始的反向指针。

让我们在例子中说明这一点。我们从细胞(3,3)开始。这里附上的元数据是(L,U)。让我们任意选择:l。所以我们向左移动,在单元格(3,2)处结束。在单元格(3,2)中,我们有一个 d,所以我们对角移动到单元格(2,1)。在单元格(2,1)中,我们有一个 u,所以我们向上移动到单元格(1,1)。在单元格(1,1)中,我们有一个 D,所以我们对角移动到单元格(0,0)。

我们从终点出发,到达起点。所以我们结束了。(尽管如此,我们仍然需要填充一些细节——事实上,实际的对齐。)让我们按照采取行动的顺序来看看我们采取的行动。

(3,3) → L → (3,2) → D → (2,1) → U → (1,1) → D → (0,0)

太好了。但是对齐在哪里呢?这是我们接下来要讨论的。首先让我们再看一遍 2D 排列中的序列,这样我们就可以随着解释的展开来想象它们。

X\Y AAC
A
C
A

我们刚刚看到的脚手架上将会分层排列。我们的第一步是从单元格(3,3)中取出 L。想象它离开 Y[3] = C,停留在 X[3]。接下来,将此视为创建对齐对(-,C),即 X 中的一个缺口与 Y 对齐[3]。

我们的下一步是从单元格(3,2)中取出 D。想象这个移动离开 X[3]和 Y[2]。把这想象成创建对齐的对(X[3],Y[2]) = (A,A)。

我们的下一步是从单元格(2,1)中取出 U。这是一种进步。它创建了对齐的对(C,-)。我们的最后一步是从单元格(1,1)开始的 D。它创建了对齐的对(A,A)。

好的,让我们看看所有这些附加到我们的脚手架上。

(3,3) → **L** → (3,2) → **D** → (2,1) → **U** → (1,1) → **D** → (0,0)
X       **—**           **A**           **C**           **A**
Y       **C**           **A**           **—**           **A**

这是反向排列。逆转它给

ACA-
| |
A-AC

我们可以看到这是一个最佳的排列。

局部对准

通常我们感兴趣的是局部比对两个序列,而不是全局比对。在局部比对中,一个序列的连续切片与另一个序列的连续切片进行比对。这既包括找到相似的切片,也包括将它们对齐

下面是一个局部对齐的例子。这一个在排列中没有任何间隙。

 ACACT**TAACTTAACGAT**SACA
         ||||||||||||
GTCATCAGT**TAACTTAACAAT**GAGA

局部比对的一个常见用例涉及识别蛋白质序列中的保守区域。这种区域称为结构域,可以独立于蛋白质的其他部分进化和发挥功能。大多数蛋白质都有多个结构域。这些结构域决定了蛋白质的功能。因此,识别蛋白质序列中的结构域是非常有用的。典型地,这是通过对照具有已知结构域的蛋白质序列的数据库,对其结构域未被表征的蛋白质序列进行局部比对搜索来完成的。或者对照结构域序列数据库。

这是第二个涉及局部对齐的场景。我们有一个基因序列。我们感兴趣的是找到所有含有与其高度相似的基因的基因组。这包括以该基因的序列作为查询进行局部比对搜索,并以合适的全基因组序列数据库作为目标。

两个序列的最佳局部比对

先前描述的全局对齐算法可以被调整以找到最佳的局部对齐。

关键的变化包括用以下公式替换计算单元格得分的全局对齐公式

S(i,j) = max{ S(i-1,j-1) + M(Xi,Yj), S(i,j-1) + C, S(i-1,j) + C, **0** }

唯一不同的是加粗的 0。我们如何看待这一点?如果前三项都是负的,则该算法停止扩展先前的比对,而是从(X[i],Y[j])开始新的局部比对。此选项在全局对齐中不可用,只能进行扩展。全局对齐必须从单元格(0,0)开始。相比之下,局部对齐可以从任何单元格开始。

出于同样的原因,初始化步骤也被修改如下:

S(i,0) = 0 for all i; S(0,j) = 0 for all j

第二个变化涉及从哪里开始重建最佳局部比对。在全局对齐的情况下,是从 S ( mn )其中 mn 分别是 X 和 Y 的长度。在局部对齐的情况下,对齐可以在任何地方结束。因此,代表最佳局部比对末端的单元是包含评分矩阵中最大值的单元。追溯阶段从该单元开始。然后,它完全像全局对准器那样重建最优对准,除了它在其重建期间遇到的值为 0 的第一个单元处停止。

局部比对搜索:BLAST

局部和全局对齐算法都是计算密集型的。使用它们将查询与数据库中的每个序列进行比较可能会非常慢。

一种称为 BLAST(基本局部比对搜索工具)的工具放弃了寻找最佳比对的目标,而是通过一种更快的算法来寻找“足够好”的比对。BLAST 是所有生物分子序列分析中使用最广泛的软件。

下面是 BLAST 的工作原理。

首先,它识别查询序列中的 k -grams。(一个 k -gram 只是一个序列中长度为 k 的连续片段)。对于 DNA 序列来说, k 的默认值比蛋白质序列大得多。

接下来,它将新的k-克添加到这个列表中。这个步骤是特别为蛋白质序列而做的。它包括找到 k 个对于适当选择的替换矩阵来说分数足够高的图。不允许有缺口,所以这只是简单的计分。无评分矩阵;没有追溯。足够相似的 k 图对的构造可以离线完成。这加快了寻找与查询中相似的字母的过程。

接下来,BLAST 在数据库中查找所有包含这个列表中至少一个 k -gram 的序列。(计算机科学家,这类似于在搜索引擎中使用单词的倒排索引来查找候选文档。)

接下来,它考虑每个这样的事件,称为命中,并试图在两个方向上扩展它。将此过程视为旨在找到锚定在该命中点的最佳局部比对。

接下来,它计算比对的统计显著性分数。虽然细节很复杂,但高层次的目标是我们在本文前面讨论过的。这是为了考虑局部对齐偶然出现的可能性有多大。这个(机会)可能性低的时候分数就高。

最后,局部比对根据它们的统计显著性分数按顺序输出。

示例

我们的目的是用最简单的方式来说明 BLAST 算法。这个例子完全不现实。例如,它选择的 k 太小,在实践中不能很好地工作。

假设我们的查询序列是 ACATGA。假设我们选择 k = 3。该序列中的k-克为

ACA, CAT, ATG, TGA

下一步,添加更多类似于这些的k-gram,为了说明,想象一下,选择的替换矩阵认为替换 C ⇔ G 和⇔ T 是兼容的,其余的不兼容。假设选择分数阈值,使得最多允许这些替换中的一个,这将导致向上面的列表添加以下 k-gram

ACA → AGA, TCA, ACT, CAT → GAT, CTT, CAA, ATG → TTG, **AAG**, ATC
TGA → AGA, TCA, TGT

有一些重复的。还是,咻!

接下来,我们在数据库中搜索至少包含上面列表中一个 k -gram 的序列。假设我们发现的一个序列是 TTAC AAG ACC。这里,粗体区域标记了我们的 k 图列表中的一个热门图。接下来,我们将查询定位到这个命中的序列,如下所示。

 ACATGA
    |||
TTAC**AAG**ACC

接下来,只要分数保持增加,我们就尝试在两个方向上延伸对齐。在我们的例子中,这种对齐将覆盖整个查询序列。

关键环节

[## 基本局部对齐搜索工具

基本局部比对搜索工具(BLAST)寻找序列之间的局部相似区域。该程序比较…

blast.ncbi.nlm.nih.gov](https://blast.ncbi.nlm.nih.gov/Blast.cgi)

局部比对动态规划算法https://en . Wikipedia . org/wiki/Smith % E2 % 80% 93 waterman _ Algorithm #:~:text = The % 20 Smith % E2 % 80% 93 waterman % 20 Algorithm % 20 performs,acid % 20 sequences % 20 or % 20 protein % 20 sequences。&text = Like % 20 the % 20 needleman % E2 % 80% 93Wunsch % 20 算法,就是% 20a % 20 dynamic % 20 programming % 20 算法。

鸟箱

原文:https://towardsdatascience.com/bird-box-1d31bad4c9c7?source=collection_archive---------33-----------------------

用康奈尔大学的 NABirds 数据预测包围盒。

这是我上一篇关于使用由康奈尔鸟类学实验室提供的鸟数据集进行图像分类的文章的续篇。在本文中,我超越了简单的分类,考虑对象检测,这可能更好地称为图像或对象定位。我不仅试图确定某个对象是否在给定的图片中,即检测组件中,而且还试图找出该对象在图像中的位置。

尽管我有自己的观点,但物体检测是文献中普遍使用的术语,我将遵循惯例。

关于 NABirds 数据的详细讨论可以在前面的文章中找到;我在这里仅仅回顾一下重点。有 48562 张图片,大致均匀地分布在 404 种鸟类的训练集和验证集之间。除了图像之外,还有大量的元数据,包括男性/女性、青少年/成人和其他适当颜色变化的几个分类和注释级别。最终结果是最细的 555 个类别。在最粗略的层次上,有 22 个类别,这在这里会更有意思。在任何层面上,数据都远未达到平衡;有些种类很常见,有些极其罕见。

这个项目的目标是双重的。首先,我只想预测图像中包含一只鸟的边界框。只有一个检测类 bird,模型必须找到鸟在图片中的位置。第二个任务是定位这只鸟,并预测它属于 22 个顶级类别中的哪一个,这大致对应于分类学中的。下面列出了按常用名称描述字母顺序排列的类别以及图像数量。请注意,占所有鸟类一半以上的栖息鸟类是迄今为止最大的群体。敏锐的博物学家也会注意到,鸻形目(即滨鸟)被分成几个类别。

边界框

每个图像只有一个带标签的鸟和一个包含它的边界框。边界框是一个小矩形,包含模型正在搜索的图像中的对象以及尽可能少的其他内容。有三种方法来标记边界框,都涉及四个坐标。最简单的就是用盒子的左上角和右下角的坐标。(按照惯例,图像的左上角是(0,0),右上角是(宽度,高度))。或者,右下角可以替换为框的高度和宽度。第三种,也是数值上更稳定的,系统使用高度和宽度,但是用盒子的中心替换左上角。所有这三种方法都被对象检测网络用作输入,但是在训练神经网络时,大多数都转换为第三种系统。

带边框的闪亮鹰。从纳伯德的数据集中。

上图就是一个很好的例子。包围盒完全包围了这只闪亮的鹰,除了它的部分尾巴(尾巴在包围动物时很棘手)。盒子几乎尽可能的紧,同时仍然封闭整个动物。在我们的三种符号方案中,盒子将被编码如下:

  1. 左上,右下= (141,115),(519,646)。
  2. 左上,宽度,高度= (141,115),378,531。
  3. 中心,宽度,高度= (330,380.5),378,531。

在实践中,坐标通常被缩放为宽度和高度的百分比(即在 0 和 1 之间)。还通常使用盒子高度和宽度的对数标度变换,因为预测大盒子尺寸的小误差没有预测小盒子尺寸的小误差严重。

原则上,图像可以包含任意数量的包围盒,包围任意数量的不同类别的对象。我很幸运,NABirds 中的每个图像只有一个盒子。这对训练几乎没有影响,但是会使模型的评估稍微简单一些。

物体探测网络

用于对象检测的神经网络建立在用于图像分类的神经网络的基本架构上。图像分类网络由卷积层、跳过连接、初始层(一种层内分形层架构)、池层、批量标准化、丢弃和挤压激励组件的惊人复杂组合组成,但最终层很简单。全局平均池(GAP)层将最终张量折叠为单个特征向量,可选的批量归一化和丢弃层提供正则化,最终的密集层通常激活 softmax,提供最终分类。可以说,用于图像分类的神经网络只是一个复杂的特征提取器,然后是逻辑回归,间隙层标志着转变点。大多数对象检测网络的工作方式是从间隙层开始移除网络的顶部,并用更复杂的东西来替换它。

这涉及到锚盒。这些框中的每一个都以图像中的某个点为中心,并且具有图像的某个分数的高度和宽度。通常,有一个给定大小的锚框网格覆盖整个图像。全套锚盒是不同分辨率网格的集合;方框越大,网格点越少。如果锚定框与给定类的输入边界框的重叠足够大,则锚定框是该类的正锚定框。如果重叠过小,锚点就是负锚点,这些边界之间的任何内容都将被忽略。这种重叠的典型度量是 IoU(交集除以并集,听起来就是这样:两个框的重叠面积除以它们的组合面积)。典型的界限是正的 IoU > 0.7,负的 IoU < 0.3。

在执行 GAP 之前,最终的输出张量可以被视为特征向量的网格,每个特征向量预测图像的一小部分中对象的存在。一个非常简单(有点太简单)的对象检测模型可以只将一个分类层附加到网格中的每个向量,以及输出四个框坐标的第二个层。然后,可以使用损失函数来训练模型,该损失函数是 softmax 分类器和盒子坐标(通常是中心、宽度和高度,以保证数值稳定性)上的 MSE 回归损失之和。

如我所说,这有点太简单了,但也不算太简单。上述模型将对应于锚盒的最粗糙级别,因为 GAP 之前的最终张量具有比原始图像小得多的宽度和高度。在旧的 VGG16 网络的情况下,224x224 图像在最终处理之前离开 7x7x512 盒。我只能检测到 49 个可能的边界框,每个框对应一个 32×32 的子图像,这些子图像是通过将原始图像分割成 7×7 的网格而得到的。在实践中,我需要能够以多种分辨率搜索数千个可能的盒子中心。

维基共享资源

我可以通过使用网络的早期层来引入更好的分辨率。在这种情况下,我有 14x14 和 28x28 个网格可用。由于这些要素在网络中处于较早的位置,因此包含的信息较少,但我可以通过对较晚的要素进行向上采样并将结果添加回来来解决这个问题。每一层都对应于一个锚盒网格。对于现代对象检测模型来说,这仍然有点太简单了,现代对象检测模型学习各种分辨率层之间的复杂关系。在神经网络的最佳传统中,组合分辨率层的层本身可以堆叠在一起,以形成更丰富的特征。

可堆叠在一起的要素池图层示例。(谭明星、庞若明、郭诉乐)

在我有一个好的物体检测网络之前,有三个更重要的,虽然简单得多的改变必须被做。首先,softmax 必须在所有分类点被 sigmoid 替换。Softmax 并不真正处理任何对象的缺失,这将是大多数锚点最常见的输出,因此必须独立预测每个类的存在或缺失。第二,分类和回归损失在不同的尺度上;必须添加一个加权因子,以便两个响应都得到很好的训练。根据型号不同,class_loss + 10 * box_loss 或者 class_loss + 50 * box_loss 效果会很好。第三个,也可能是最简单的,是让每个锚定框中心对应于不同纵横比的多个锚定框。

效率检测

EfficientNet 系列网络的基本前提是,三个主要网络参数(层数、图像分辨率和每层过滤器)之间的简单关系可用于轻松生成一系列不同大小的图像分类模型,从适用于智能手机的小型模型到最先进精度所需的大型模型。EfficientDet 将相同的原理扩展到对象检测模型。基本高效网络主干以上述方式用作特征提取器。不同的分辨率级别由一系列双向特征金字塔网络(BiFPN)进一步处理,而不是在末端有一个间隙层。BiFPN 层的数量以及每层的信道数量随着主干网络的规模而增加。最后是几个卷积层,然后是分类和盒预测。

由于我在之前的项目中使用了 EfficientNet,EfficientDet 似乎是这个项目的自然选择。这带来了一些挑战。当我开始工作时,用 Colab 运行 EfficientDet 的唯一可行的选择是基于 PyTorch 的。(Tensorflow 已经发布了他们自己的实现)。到目前为止,我所有的工作都是在 Tensorflow 中完成的。学习在新环境中工作总是一个挑战,但我不介意。在 PyTorch 工作的真正缺点是我不能在 Colab 上使用 TPU。由于只能求助于 GPU,我被迫缩减了我可以比较的不同型号的数量。到目前为止,我只运行了 D0 到 D2,每个都有默认的输入大小。对象检测通常使用比简单分类更大的图像,这意味着批量大小必须更小,因此学习率必须更小。我只能对模型使用 4 的批量大小。初始学习率被设置为 0.0002,并且在验证损失没有改善的每个时期之后下降一半。我给了模型最多 100 个历元的训练选项,但通常发现我可以在 50 个历元时停止。

预处理

与所有图像处理神经网络一样,对象检测非常依赖于良好的图像预处理。大多数重要的预处理操作都涉及到变换,如移动和缩放,它们对边界框的影响和对图像的影响一样大。幸运的是,有一个软件包albuminations可以处理这个问题。我不知道 albumentations 应该是什么(如果有的话)(看起来拼写检查器也同样被难住了),但这个包包含的函数可以确保在图像分割问题的情况下,应用于图像的任何变换也可以应用于相关的边界框和/或图像遮罩。

NABirds 图像有各种大小,其高度和宽度的上限为 1024。大约一半的人一边的长度是 1024,另一边的长度在 600 到 900 之间。批处理需要固定的输入大小。这对于训练数据来说很容易,因为我从图像中随机截取了一个正方形,但是对于验证来说有点复杂。因为我不想因为裁剪验证图像而丢失任何信息,所以我改为重新调整尺寸,使较长的尺寸与输入尺寸相匹配,然后填充较小的尺寸,直到图像变成正方形。

D1 网络的示例验证图像。较长的维度已被重新调整为 640,较小的维度已被填充。Albumentations 已经调整了边界框坐标,以便它仍然覆盖鸟。原始数据来自纳伯德数据集

下面列出了我对训练数据使用的一组转换。

第一个操作是从原始图像中随机选取一个矩形裁剪,其大小介于完整图像和 10%之间,长宽比介于 4:3 和 3:4 之间,并将其重新调整为适当大小的正方形。我总是使用我正在使用的 EfficientDet 网络的默认输入大小。

第二阶段改变色调或亮度,但不是两者都改变,有 90%的可能性(即,十次中有一次它什么也不做)。第三阶段将图像转换为 1%的灰度。接下来的三个操作是沿垂直轴、水平轴和对角线轴翻转,每个操作有 50%的概率。抠图会用零替换图像中的一些小方块;它的功能类似于后续层的辍学。下面是由这些转换产生的训练图像的示例。

NABirds 数据集的原始数据

眼尖的读者会注意到,所有这些图像都包含边界框,尽管在一种情况下,框现在是完整的图像。如果随机裁剪根本不包含盒子会怎么样?很简单,我再试一次。预处理代码进行了多达 100 次尝试,以产生一个带有边界框的裁剪,然后返回到一个更简单的缺省值,该值仅在整个图像上执行调整大小操作。

我的验证转换如下。

所有这一切都是用零填充图像,直到我得到一个正方形,然后调整大小以适应模型。它的杰作如下。

NABirds 数据集的原始数据

培养

PyTorch 没有 Tensorflow 可用的 Keras 前端,这意味着训练模型需要更多的手动工作。关键的想法仍然相当简单。对于每批训练数据,向前传播以获得当前预测,然后向后传播以更新参数。我使用的完整的Fitter类对于本文来说有太多的样板代码,但是我可以分享训练一个纪元的循环。

在每个训练时期之后,类似的循环执行验证。如果新参数是一个改进,则保存该模型。

确认

对象检测验证不是一件简单的事情。与为每个类别生成一个概率的图像分类不同,对象检测为输出中的每个类别和锚定框生成一个单独的概率和边界框。这是一个很大的数字。其中大部分可以简单地通过阈值处理而被容易地丢弃,即,如果某个锚中某个类别的分数足够低,我们可以毫不犹豫地丢弃它。实际上,大多数锚定框中的所有类别以及所有锚定框中的大多数类别都是这种情况。这仍然存在多个边界框被标记为正 id 的可能性。如果肯定的类别与真实的类别不匹配,那么就存在明显的错误分类,但是如果类别匹配,那么也有必要考虑边界框的准确性。

如上所述,对象检测模型依赖于锚盒。在模型被训练之后,这些锚点中的每一个都有一个输出。大多数都可以被忽略,因为它们的置信度很低。也有可能两个(或更多)相邻的锚会为同一个类产生正输出。在这种情况下,边界框将非常相似,并且只需要保存一个,即具有最高置信度得分的那个。非最大抑制是去除冗余包围盒的标准算法。

直到现在,我才能着手将模型的输出与地面事实进行比较。我有一些优势,因为我知道每张图片只有一个边界框;我可以通过仅考虑具有最高置信度的预测边界框来进行评估。用于测量准确性的指标专门处理精度和召回,因此我必须定义对象检测的真阳性、假阳性和假阴性。

  1. True Positive —预测的类别与实际相符,并且 IoU 大于某个阈值。
  2. 假阳性—预测的类别与实际相符,但 IoU 低于阈值。
  3. 假阴性-预测的类别与实际情况不符,或者没有预测到任何类别。

精确度是真阳性与所有预测阳性的比率,而召回率是真阳性与真实结果的比率。通俗地说,精确度是准确的真实预测的百分比,召回是被识别的肯定类别的百分比。

通过计算各种 IoU 阈值(0.5 和 0.75 是常见的)下的精度,并在 IoU 阈值范围(通常为 0.5 至 0.95,增量为 0.05)内平均精度(看似多余的命名为平均精度),来评估对象检测模型。)可以为召回计算类似的度量。

单类检测

我的两个问题中比较简单的一个就是找到图像中哪里有一只鸟,并返回包含它的盒子。我尝试了三种不同的模型,在 EfficientDet 系列中从 D0 到 D2,使用具有最高置信度得分的边界框作为预测。我只允许 0.5 以上的信心分;一些图像足以混淆模型,没有边界框满足该阈值,因此有一些假阴性。

假阳性更有意思。作为一个衡量标准,IoU 必须戴几顶不同的帽子。它说预测框必须覆盖一定量的基本事实框,而且基本事实框必须覆盖一定量的预测框。低 IoU 可能意味着模型在图像的错误部分检测到了鸟,但也可能意味着模型找到了鸟,但不够精确(即,盒子太大。)通常,假阳性将是检测到鸟的情况,并且将在边界框中,但是预测的坐标不够好。

直觉上,0.5 的借据分数似乎有点低。值得看一些例子,看看不同的 IoU 阈值是什么样的。记住,图像是二维的。当不止一个维度同时发生变化时,我们的大脑很难识别面积或体积何时会翻倍。让我们看看 IoU=0.8 在现实生活中意味着什么。

六幅图像,带有实际值(蓝色)和预测值(红色)边界框,IoU 约为 0.8。NABirds 数据集的原始数据

任何看到这些图片的人可能会猜测重叠度超过 90%,但实际上在所有情况下都略低于 80%。这表明 0.8,对于许多度量标准来说被认为是一个平庸的值,对于边界框来说并不是那么糟糕。同样值得注意的是,预测的盒子往往比“地面真相”更好人类注释者有其局限性。

即使欠条只有区区 0.5 英镑,在这些人看来也没什么问题。

about 0.5 左右。蓝色表示地面真相,红色表示预测。NABirds 数据集的原始数据

这两个示例都使用了来自 EfficientDetD0 的预测。随着我从 D0 增加到 D2,精度略有提高。

使用 0.5 的 IoU 作为阈值,模型具有近乎完美的精度。只有在少数情况下,预测的边界框不会与地面真实充分重叠。即使在 0.75 的较高阈值下,预测和地面实况至少十之八九匹配。平均精度是指 IoU 阈值在 0.5 至 0.95 之间时的平均精度,它略低,因为 IoU=0.9 以上的精度急剧下降。

平均召回率也接近完美,因为只有几百张图像没有任何置信度得分至少为 0.5 的边界框。

仅从指标来看,这些模型似乎表现良好。随着模型大小的增加,精确度会适度但持续地增加。从产出来看,我认为模型甚至可能比数字显示的更好。在许多情况下,预测的边界框明显优于人类标注的地面真实。在其他情况下,预测的盒子太大,只是因为模型假设鸟在树枝后面延伸,这是一种很常见的情况。在一个滑稽的例子中,预测的边界框没有覆盖地面真相,因为它捕捉到了鸟的反射(回想起来,在训练中允许垂直翻转可能是不明智的)。在另一个例子中,预测框找到了注释者遗漏的第二只鸟。我认为,如果地面真相标签更干净一点,模型的表现会更好。

检测到鸟反射(左)和第二只鸟(右)。NABirds 数据集的原始数据

多类检测

在康奈尔大学数据集中有 22 个顶级类别,每个类别对应于鸟类的一个目或科,每个类别都有共同的名称。添加类别检测使对象检测模型的分类(是什么)组件变得复杂,但是对单独的定位(在哪里)组件影响较小。因为我已经将肯定类的数量从 1 增加到 22,所以我需要降低我认为预测分数是肯定匹配的阈值。除了最高分(每张图片一个边界框)之外,我仍然放弃所有东西,所以我可以将相对较低的 0.1 分作为正面预测。

我怎么挑了 0.1?随机猜测会给我不到 0.05;我把它翻了一倍,认为两次随机的信心得分不会偶然发生。结果很好,所以我坚持了下来。

不足为奇的是,不同类别之间的准确度或多或少地与类别中图像的数量成正比。因为我在训练中没有试图均衡数据,所以图像总数为两位数的六个班级在它们之间的三个模型中得到了两个正 id。同时,栖息鸟类占 97–98%。一个令人满意的结果是,在 300 到 1000 张图片的订单中,增加模型大小可能会产生巨大的影响。真正的阳性率可能上升 10-20%(军舰鸟的阳性率更高)。全部真阳性结果如下。

多类对象检测问题中的标准过程是通过对所有类的精度进行平均来计算平均精度。鉴于类别不平衡的程度,我认为计算整个数据集的“未加权”平均精度是有益的。这当然会给我比标准加权精度更大的数字。我认为这两个数据点都有一定的价值。

请记住,当预测的顺序与基础事实相匹配,但预测和基础事实框的 IoU 太低时,就会出现误报。

正如所料,精度比单类检测器的精度低,并且随着模型的增加而缓慢增加,这也是所料。加权(即标准)平均精度要低得多,但也比未加权的度量以更快的速度增加。这反映了这样一个事实,即对于中等规模的班级来说,准确率显著提高。两组模型的 IoU 值分布非常相似;几乎所有精度的下降都反映了该模型现在必须区分 22 个订单。

进一步的工作

任何好的实验都为新问题打开了大门。在这种情况下,我可以想到几个。假设我可以保持足够高的批量大小(即找到使用 TPU 的方法),增加模型大小超过 D2 会如何影响准确性?我用 D3 做了一个实验,但是被迫将已经很小的批量减少了一半。最终结果是较低的召回和精度分数回落到 D0 水平。由于我没有做其他的改变,看起来这完全是因为批量的原因。

我一直怀疑较大的模型需要较低的学习率。D3 和更高版本在学习率更低的情况下会更好吗?

如果我使用全部 404 个物种,甚至全部 555 个类别,而不是 22 个类别,会发生什么?我所看到的关于物体检测的一切都表明,它不能轻松处理像图像分类那样多的类别。反正还没有。

也许对上述算法最有用的测试是在一些其他的鸟类数据集上进行,比如在各种非自然主义者的数据集中的鸟类。

参考

[1]格兰特·范·霍恩、史蒂夫·布兰森、瑞安·法雷尔、斯科特·哈伯、杰西·巴里、帕诺斯·伊皮罗蒂斯、彼得罗·佩罗娜和塞尔日·贝-朗吉。与公民科学家一起构建鸟类识别应用程序和大规模数据集:细粒度数据集集合中的小字。2015 年 CVPR

[2]谭明星、庞若明和郭诉乐。EfficientDet:可扩展且高效的对象检测。2020 年 IEEE 计算机视觉和模式识别会议录。

强化学习算法分类的鸟瞰图

原文:https://towardsdatascience.com/birds-eye-view-of-reinforcement-learning-algorithms-landscape-2aba7840211c?source=collection_archive---------28-----------------------

“邀请所有有志 RL 从业者”系列第 3 集

在 Unsplash 上由伊尼基·德尔·奥尔莫拍摄的照片

在本系列的第一部分中,我们已经了解了强化学习(RL)中的一些重要术语和概念。在第二部的中,我们还学习了 RL 是如何应用在自主赛车上的。

在本文中,我们将了解强化学习算法的分类。我们不仅会学习一个分类法,还会从许多不同的角度学习几个分类法。

在我们熟悉了分类法之后,我们将在以后的章节中学习更多关于每个分支的知识。不浪费更多的时间,让我们深呼吸,做一杯巧克力,我邀请你和我一起学习 RL 算法分类的鸟瞰图!

照片由美国传统巧克力在 Unsplash 上拍摄

无模型与基于模型

无模型分类法与基于模型分类法。[图片由作者提供,转载自 OpenAI Spinning Up]

对 RL 算法进行分类的一种方式是询问代理是否可以访问环境的模型。换句话说,通过询问我们是否能确切地知道环境将如何对我们的代理人的行动作出反应。

基于这个观点,我们有两个 RL 算法分支:无模型的和基于模型的:

  • 基于模型的是 RL 算法的一个分支,它试图根据学习到的环境模型来选择最佳策略。
  • 无模型算法中,基于代理经历的试错法选择最优策略。

无模型算法和基于模型的算法都有各自的优缺点,如下表所示。

无模型算法和基于模型算法的优缺点。[图片由作者提供]

事实:无模型方法比基于模型的方法更受欢迎。

基于价值与基于政策

对 RL 算法进行分类的另一种方式是通过考虑算法优化了什么组件——值函数还是策略。

在我们深入探讨之前,让我们先了解一下政策和价值函数。

政策

策略π是从状态 s 到动作 a,的映射,其中π( a|s )是当处于状态 s. 时采取动作 a 的概率。策略可以是确定性的,也可以是随机的。

马库斯·沃利斯在 Unsplash 上拍摄的照片

让我们想象一下,我和你在玩石头剪刀布的游戏。如果你不知道这个游戏是什么,这是一个非常简单的游戏,两个人通过同时执行三个动作(石头/布/剪刀)中的一个向对方竞争。规则很简单:

  • 剪刀打败了布
  • 石头打败剪刀
  • 纸打败了石头

考虑迭代石头剪子布的策略

  • 确定性策略很容易被利用——如果你选择“石头”的频率高于其他选择,并且我意识到了你的行为,那么我就可以利用这一点,这样我就有更大的概率获胜。
  • 一致随机策略是最优的——如果你的行为完全是随机的,那么我不知道应该采取什么行动才能打败你。

价值函数

价值函数是一个基于对未来回报的预测或称为回报来衡量一个状态有多好的函数。基本上,回报(Gt)是从时间 t 开始的“贴现”回报的总和。

,其中 γ ∈ [0,1]为折现因子。贴现因子旨在惩罚未来的奖励,原因有几个:

  1. 在数学方面很方便
  2. 打破状态转换图中的无限循环
  3. 未来回报的不确定性更高(即股票价格变动)
  4. 未来的回报不会带来直接的好处(也就是说,人们倾向于在今天而不是 10 年后享受快乐)

我们现在知道什么是回报了。我们来定义一下价值函数的数学形式!

价值函数有两种形式:

  • 状态-价值函数(通常称为价值函数)是一个状态在时间 t: 的期望收益

  • 状态-行为价值函数(通常称为 Q 值)是一个状态-行为对在时间 t: 的期望收益

Q 值与值函数的区别是动作优势函数(通常称为 A 值):

好了,我们已经学习了什么是价值函数和行为状态价值函数。现在,我们准备学习更多关于 RL 算法的另一个分支,该分支专注于算法优化的组件。

基于值和基于策略的算法。[图片由作者提供,转载自大卫·西尔弗的 RL 课程]

  • 基于价值的 RL 旨在学习价值/动作-价值函数,以便生成最佳策略(即,最佳策略是隐式生成的)。
  • 基于策略 RL 旨在使用参数化函数直接学习策略。
  • 演员兼评论家 RL 旨在学习价值函数和政策。

下表列出了基于价值和基于策略的方法的优缺点。

基于值和基于策略的算法的优缺点。[图片由作者提供]

  1. 基于值的算法必须挑选最大化动作-状态值函数的动作,如果动作空间非常高维甚至是连续的,代价会很大,而基于策略的算法通过直接调整策略的参数来工作,不需要做最大化计算。
  2. 基于值的算法如果以“错误的方式”做事,可能会振荡/颤动/发散(更差的收敛特性/不太稳定),而基于策略的算法更稳定,具有更好的收敛特性,因为它们只对策略梯度做很小的增量改变。
  3. 基于策略的算法可以学习确定性和随机性策略,而基于值的算法只能学习确定性策略。
  4. 与基于值的算法相比,简单的基于策略的算法可能更慢,并且方差更大。基于值的方法试图挑选最大化动作-状态值函数的动作,该动作-状态值函数将朝着最佳策略(更快和更低的方差)的方向改进策略,而基于策略的方法只是迈出一小步,并朝着更稳定的方向平滑更新,但同时效率较低,有时会导致更高的方差。
  5. 基于策略的方法通常收敛于局部最优,而不是全局最优。

符合政策与不符合政策

还有另一种分类 RL 算法的方法。这次分类是基于策略的来源。

策略内与策略外算法。[图片由作者提供]

我们可以说被归类为 on-policy 的算法是在工作中学习的“换句话说,算法试图从π采样的经验中学习策略π。

而被归类为非策略的算法是通过监视某人来工作的算法。“换句话说,算法试图从μ采样的经验中学习策略π。例如,机器人通过观察另一个人的行为来学习如何操作。

最后的话

乔丹·沃兹尼亚克在 Unsplash 上的照片

恭喜你坚持到这一步!!

阅读完本文后,您应该已经知道 RL 算法是如何基于几种观点进行分类的。在未来的几集里,我们会学到更多关于基于值和基于策略的算法。

请记住,我们的 RL 之旅仍处于早期阶段!我还有很多材料要和大家分享。所以,如果你喜欢这些内容,并想在接下来的两个月里继续和我一起学习,请关注我的媒体账号,以获得关于我未来帖子的通知!

关于作者

Louis Owen 是一名数据科学爱好者,他总是渴望获得新知识。他获得了最后一年的全额奖学金,在印尼顶尖大学 万隆技术学院 攻读数学专业。最近,2020 年 7 月,他刚刚以优异的成绩毕业。

Louis 曾在多个行业领域担任分析/机器学习实习生,包括 OTA ( Traveloka )、电子商务( Tokopedia )、fin tech(Do-it)、智慧城市 App ( Qlue 智慧城市 ),目前在 世界银行 担任数据科学顾问

查看路易斯的网站,了解更多关于他的信息!最后,如果您有任何疑问或任何要讨论的话题,请通过 LinkedIn 联系路易斯。

参考

https://donnie . id/posts/on-policies-in-reinforcement-learning-algorithms-and-AWS-deepracer/

https://spinningup.openai.com/en/latest/spinningup/rl_intro2.html

https://www.davidsilver.uk/wp-content/uploads/2020/03/pg.pdf

https://www.youtube.com/watch?v=bRfUxQs6xIM & list=PLqYmG7hTraZBKeNJ-JE_eyJHZ7XgBoAyb & index=6

比特币减半是一个毫无意义的里程碑

原文:https://towardsdatascience.com/bitcoins-halving-is-a-meaningless-milestone-b94c616e138b?source=collection_archive---------40-----------------------

不要相信吹捧不存在的“供应减少”的专家

照片:德米特里·德米季科

比特币期待已久的减半于今天早些时候发生,其背景是加密货币的忠实追随者们真正的狂喜。有倒计时、直播视频事件和“当月亮时”的圣歌它破解了主流新闻,被视为密码中最大的事件。减半使得地球上几乎每一个比特币拥有者都热情地进行价格预测,并在网上发布。

所有这一切绝对是疯狂的。更糟糕的是,它建立在一个谎言之上,或者至少是比特币的主要支持者有目的的误导,他们应该更清楚这一点。

如今的比特币数量(18,375,000)与减半前的昨天一样多

让我们回忆一下减半实际上做了什么。很简单:它将比特币矿工的大宗奖励减半,从 12.5 新 BTC 降至 6.25。这极大地改变了采矿业的经济状况,降低了采矿业的利润。一些矿工可能会完全停止,损害比特币的散列率。

仅此而已。这就是减半所做的一切。它降低了新 BTC 产生的速度。这绝对无助于改变加密货币的实际供应量。不幸的是,大多数专家和比特币支持者都在宣扬相反的观点。让我们一点一点解构这种误导。

减半并没有减少 BTC 的供应量

比特币减半的典型故事是这样的:

  • 每隔四年,比特币的供应量就会减半
  • 供给减少,但需求不变,比特币的价格只能暴涨;因为相同数量的购买者购买更少数量的硬币
  • 价格怎么可能暴涨?毕竟,这是继比特币历史上的每一次减半之后的又一次。

希望这种叙述中明显的误导现在已经很清楚了。“供给”一词有多种含义,比特币社区中有太多的人在暗示绝对供给——即流通中的比特币数量——正在下降。这不是真的。如今的比特币数量(18,375,000)与减半前的昨天一样多。实际上,这个数字还在继续增加。它只是以较慢的速度这样做。

对“供应”的普遍误解对加密货币社区关于减半的想法产生了巨大的影响。真正的后果是我在上面列出的:矿工经济学、杂凑利率——相对来说是技术性的,很难看好比特币的价格。这是一个非常无聊的故事。

相反,比特币社区更喜欢事件的扭曲版本,即减半以某种方式改变了加密货币的基本供求。考虑到 BTC 的供应量不会发生任何变化,这就需要一种巨大的精神体操。然而,许多比特币“有影响力的人”正在完成一项可疑的任务,试图证明炒作的合理性:

拥有比特币社区最大追随者的 Pomp,真的通过屠杀经济在这里以身作则。

Pomp 把新的比特币日供应量(每天开采的极小数量的比特币)与比特币的绝对日供应量(即在任何一天有多少人希望卖出 BTC)混为一谈。如果你与比特币的日常需求(即,在任何一天有多少买家希望购买比特币)进行比较,后一个定义是唯一有意义的定义,但 Pomp 将两者完全混淆了。

上面的白色趋势线跟踪了一个非常流行的完全假设的“股票到流量”模型,该模型跟踪了 BTC 明显不可避免的涨到 100 万美元。正如你所看到的,这个模型的关键特征是比特币价格如何在减半时每四年“跳”一次。

神秘的是,BTC 价格并没有遵循这位理论家精心编造的霓虹绿趋势线,也没有在“明天这个时候”突破 10000 美元。

当需求增加时,价格就会上涨

这并不是说减半没有影响。真的会影响比特币矿工的底线。但很奇怪的是,这被视为一个看涨事件或加密货币的里程碑——如果有什么不同的话,矿工因缺乏利润而停止运营的风险可能会威胁到比特币的工作证明安全性。任何兜售减半将导致 BTC 价格飙升的“经济”证据的人,都应该受到高度怀疑。

减半无非是一个预先设定好的事件,让采矿变得更加困难

另一方面,围绕减半的纯粹数量和炒作也有可能产生自己的影响。所有狂热的预期和报道(包括主流新闻来源,这是罕见的)可能会驱使新一代买家购买闪亮的加密货币钱包,寻求在比特币火箭船预定的起飞前成为其中一员。这些买家是在不成熟的理论和不可靠的经济背景下被引进的,但最终 BTC 需求的任何显著增长都会提高其价格。

然而,尽管这种增长无疑可以归因于减半的数学魔力及其不存在的供应冲击,但真正的答案恰恰相反。比特币的供应量将保持不变,而推高价格的是不断增加的需求

对于比特币来说,这是一个可悲又无趣的事实。尽管如此多的人通过减少供应来寻求“不可避免的”价格上涨的安全性,但这实际上并没有反映比特币的工作方式或 Satoshi 的设想。

减半只不过是一个预先设定好的事件,目的是让开采变得更加困难,并使比特币产量曲线变平。如果 BTC 最终真的“无所事事”,那将是因为对该资产的需求激增,而非矿业利润减少。

如果你对加密和区块链的影响感兴趣,你会喜欢我的新出版物技术统治。我会定期写一些关于技术如何改变社会的文章,比如我最近的一篇关于冠状病毒如何让大规模监控成为我们的新常态的文章。

Pandas 中的按位运算符和链接比较

原文:https://towardsdatascience.com/bitwise-operators-and-chaining-comparisons-in-pandas-d3a559487525?source=collection_archive---------18-----------------------

Pandas 中的比较链接和运算符优先级的重要性

在学习熊猫的时候,很自然会有使用 Python 的布尔运算符(andor等)的倾向。)来链接条件,因为在 Python 中就是这样做的。然而,这些不是我们应该在 Pandas(或 NumPy)中使用的操作符。让我解释一下为什么…

图片来自 Unsplash

在 Python 中,链接比较非常简单:

x = 4
x==4 and x%2==0
True

这里我们只是检查x是否等于4以及是否为偶数。同样,我们可以将多个条件链接在一起,如下所示:

*b = 'random string'
x==4 and x%2==0 and b.endswith('ing')
True*

这是因为我们正在比较布尔值(TrueFalse)或true/falsy值(计算为TrueFalse的值),对于上面的例子,这些值产生了一个表达式True and True and True。**

比较布尔数组

然而,一个常见的错误是认为这同样适用于布尔值数组,这是应用一些比较的结果。例如:

**x = np.array([2,4,6])
x%2==0 and x!=3
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()**

正如你所看到的,上面产生了一个ValueError。这种情况下发生了什么变化?不同之处在于,我们不再比较布尔值,因为x%2==0产生:

**array([ True, True, True])**

这显然既不是True也不是False。Python 通过错误告诉我们,我们需要对结果应用聚合函数来消除歧义,a.any()a.all()。这样做会将数组缩减为一个值:

**(x%2==0).any()
True**

现在可以将其与另一个布尔值进行比较。

按位运算符

当我们处理一个数组或一个 Pandas DataFrame 列,并希望基于一个以上的比较进行过滤时,我们将需要计算基于元素的操作,在本例中,基于逻辑元素的** 操作。**

我们已经讨论了 python 的布尔操作符为什么不是我们想要的,因为它们要求被比较的项可以被评估为TrueFalse。对于基于逻辑元素的操作,我们应该使用 python 的按位操作符<<>>&|****~^.****

您可以将 python 的按位运算符视为布尔运算符,但它是基于元素应用的(在布尔数组上):

****x%2==0
array([ True, True, True])x==4
array([False, True, False])(x%2==0) & (x==4)
array([False, True, False])****

所以在这里,我们在两个结果布尔向量之间应用了一个按位 AND(&),这产生了另一个形状相同的数组,该数组是通过对其元素应用逐元素操作而得到的。

Python 对于所有布尔运算符以及下面列出的其他运算符都有一个等价的按位运算符:

  • x & y做一个“按位AND”。如果xy的对应位为1,则输出的每一位为1,否则为0
  • x | y 做一个“按位OR”。如果xy的对应位为 0,则输出的每一位为0,否则为1
  • ~x返回x ( NOT)的补码——通过切换每个1得到一个0,每个0得到一个1。这个和-x-1一样。
  • x ^ y做“按位异或”(XOR)。如果y中的位是0,则输出的每一位与 x 中对应的位相同,如果y中的位是1,则输出的每一位是x中位的补码。

我们还有按位移位操作符>><<(见这里的)。

运算符优先级

回到上面的例子,需要考虑的一个重要方面是,使用按位运算符时,括号很重要!****

这是因为按位运算符比比较运算符具有更高的优先级,这意味着按位运算将在比较运算的之前。********

在 Python 文档的表达式部分,在 运算符优先级 下,我们将找到一个包含所有 Python 运算符优先级的表格,从最低优先级(最少绑定)到最高优先级(最多绑定):**

图片来自 python 文档

为了更清楚地理解上述内容,假设我们有一个包含乘法运算符( ***** )和幂运算符( ****** )的表达式:

******3*2**2
12******

由于取幂运算符的优先级更高(看它是如何出现在表中较低位置的),python 会先对2**2求值,也就是4,然后是3*4=12。如果我们想给乘法一个更高的优先级,我们必须把表达式括起来:

******(3*2)**2
36******

在这种情况下,我们如何写数学表达式。

现在,这同样适用于按位运算符。由于==的优先级比&低,我们需要用括号括起比较表达式,以便首先对它们求值:

******(x%2==0) & (x==4)******

链式运算符比较

另一个常见的错误,是试图将连锁运营商视为:

******x = np.array([2,4,6])1<x<10
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()******

NumPy(或 Pandas)不支持这一点,它会产生一个ValueError。这里的问题是,Python 在内部将上述内容转化为:

******(1 < x) and (x > 10)******

这又把我们带到了与上例相同的错误:and隐式调用bool,而NumPy只允许隐式强制为单个元素的布尔值(不是带有size>1的数组),因为带有许多值的布尔数组既不计算True也不计算False

实际上在 PEP 535 中已经提出要实现这一点,尽管它仍然被推迟了。

在接下来的帖子中,我将讨论熊猫中更高级的比较操作,并回顾一些需要记住的有用提示。

非常感谢你花时间阅读这篇文章,希望你喜欢:)

“黑匣子”。没有办法确定算法是如何得出你的决定的。

原文:https://towardsdatascience.com/black-box-theres-no-way-to-determine-how-the-algorithm-came-to-your-decision-19c9ee185a8?source=collection_archive---------46-----------------------

人工智能黑匣子问题是基于无法完全理解为什么人工智能背后的算法会以这样的方式工作。

我们依赖机器学习,因为机器能够从经验和数据中学习,并在学习过程中不断改进。

但是如果我们不得不依赖它的一个模型, 我们怎么能信任一个像它的数据一样不精确的模型呢?

这一切都归结于透明度。

这是 AI 仍然可以为我们提供很多东西的地方。

虽然这在游戏或零售等行业可能是允许的,但对于在金融服务或医疗保健等高度监管行业运营的公司来说,这肯定是不可接受的。

照片由 Eugene Lim 在 Unsplash 上拍摄

如果你想了解更多,请访问oscargarciaramos.com

在高层次上,机器学习基本上是基于向机器提供大量数据,以便它们学习,并允许开发复杂的算法,这些算法可以推广和扩展到机器以前从未见过的其他数据。

然而,不管我们使用什么算法,有一个事实:模型和它的数据一样好。 坏数据→坏模型

我举个例子:如果我想自动识别猫的照片,模型识别狗,我们就有问题了!

现在是“借口”来了:

  1. 输入数据不好。
  2. 之前没有进行过数据清理。
  3. 设置和超参数配置不正确。
  4. 数据有偏差,这种偏差会转移到我们训练过的数据集。
  5. 模型训练不足,或者存在过拟合或欠拟合问题。

“喂,我们说的是猫狗!”。好吧,没什么事。 

现在让我们来谈谈面部识别模型,我们想把它卖给一家安全公司,这样他们就可以检测潜在的“小偷”。模型失败了,我们该怪谁?我发誓每个人都会逃走,没有人会告诉你一个字。

那么回到最初的问题, 我们怎么能相信一个可以像它的数据一样不精确的模型呢?

我们需要透明度

太好了,我们想要透明。但是,我们在讨论机器学习,对吗?如果我们知道学习是如何工作的,我想就没有必要用数据来训练它了。我们只是从头开始编写模型代码,然后以 50K 的价格出售。我们有生意了!

抱歉,我的朋友,但事情不是这样的!

我们将模型的功能建立在数据的基础上,通过使用不同的算法,我们试图建立最准确的模型,以便我们可以推广到其他新数据。这是第一步,我们开始用四肢爬行。但是没有人会知道如何完美地行走。我们需要不断采取措施,用更好的数据,更好的超参数配置,更好的算法,更好的机器和资源迭代,尤里卡!

从开发人员或数据科学家的角度来看,这是完美的。让我们设身处地为消费者着想。我们无法控制模型,当它的表现不如预期时,我们该指责谁?数据、数据科学家、配置?

没有人知道这些问题的答案。

作为消费者,只能用模型,或者扔掉。没别的了。要么接受它,要么建立你的,恐怕我很清楚你的决定会是什么。但随着市场的进步,这种反应越来越让人无法接受。

但是我们不能回答这个问题的原因是什么呢?

1.无法解释的算法

用于建立模型的算法有多大的解释力?

当图像识别模型将狗识别为猫时,为什么会出现这种情况?也就是说,当模型得出诸如分类或回归之类的结论时,很难理解模型是如何得出该结论的。甚至像神经网络这样的技术也有这个问题。然而,并不是所有的机器学习算法都有相同的解释问题。决策树,由于其本质,是可以解释的,然而,当我们谈论随机森林时,我们失去了那些元素。

2.无形的训练数据

正如我们所说,模型的性能直接取决于它的数据。但是,拥有完美的、干净的、标记良好的数据并不总是能确保一个好的模型。为什么?如果训练数据不代表真实世界的数据,我们就会有问题。我们将无法推断出任何东西!

3.数据选择

“我想让你给我访问你正在使用的全部数据集”。

够了吗?号码

你真的知道这些数据中的哪些被用于训练模型吗?如果我们用你无法访问的其他数据来丰富它们,会怎么样?完全透明还意味着知道如何从可用的训练数据中选择数据,并且理想情况下能够在训练数据中使用与模型消费者相同的选择方法来查看哪些数据被包括在内,哪些数据被排除在外。

4.训练数据集中的偏差

“偏差”一词可以指三个方面:在模型中建立的权重和“偏差”的意义上,在导致过度拟合或不足拟合的方差的未补偿意义上,或者在最广泛理解的意义上,作为信息“偏差”,由我们基于自己的先入为主的概念直接引起。

5.模型版本控制

我们必须明白,模型不是在一次迭代中创建的,而是连续的。过去正常工作的东西现在可能会降低性能。新的数据,新的设置,你必须发展它。但是,所有这些变化都应该主动宣布,而不是被动地宣布,以避免出现问题,并确保在新型号表现不佳时,始终能够使用以前的版本。

那么,下一步是什么?

“我们需要让行业透明化”

企业需要他们可以信任的模型。随着我们的采用增加,实现人工智能系统的透明度至关重要。

人工智能在用于现实世界的推理时必须是可靠的。

欢迎发表评论或分享这篇文章。关注 me 以后的帖子。

如果你想了解更多,你可以在oscargarciaramos.com找到我

黑狗黑猫综合症——神话还是现实?

原文:https://towardsdatascience.com/black-dog-and-black-cat-syndrome-myth-or-reality-819dc4e616f1?source=collection_archive---------15-----------------------

收容所被收养的猫和狗的颜色统计。为什么黑色动物会被收养者忽视

黑狗和黑猫

介绍

黑猫和黑狗综合症是由美国防止虐待动物协会(ASPCA)在 21 世纪初建立的。这被描述为一种现象,深色皮毛的宠物大部分时间被收养者忽视,而喜欢浅色皮毛的动物。它的发生通常是由于人们的信仰、迷信和联想。黑狗,尤其是大狗,通常在电影、书籍和其他媒体中被描绘成令人恐惧和好斗的形象。黑猫还被一种不同的迷信所包围,并与巫术联系在一起。总的来说,社会将黑色与邪恶和厄运联系在一起。

主要问题:黑猫和狗会被动物收容所忽视吗?

数据

这两个数据集:动物摄入量和动物结果取自 data.austintexas.gov奥斯丁动物收容所网站

动物摄入量数据集有 115,612 个条目和 12 个特征

动物结果数据集有 115,778 个条目和 12 个特征

我开始清理数据,删除对我的观察不重要的特征。我还从数据集中排除了其他动物类型。在探索性分析过程中,我筛选出了猫狗中最受欢迎的 24 种毛色,以便进一步探索和比较。

我把我的发现绘制在一个反图上,以观察进入收容所和被收容所收养的猫和狗的数量和百分比。

计数图,按颜色比较摄入和收养动物的百分比

正如预期的那样,在两种情况下都显示动物摄入多于产出。此外,最常见的猫颜色摄入是棕色平纹和黑色,最常见的狗颜色摄入是黑色/白色和棕色/白色。黑色的狗以 20%的摄入量排在第四位.

颜色重要吗?

为了了解收养是否真的取决于动物的颜色,我进行了卡方检验。p 值接近于零的极低测试表明,收养猫和狗非常依赖于皮毛颜色。

下一步是通过颜色找出平均被收养的猫和狗的百分比。

条形图显示每种动物颜色的收养百分比

上面的柱状图表明,黑猫和狗分别被平均 43.2%和 43.5%的人收养。对黑色动物来说还不错,考虑到这一比例高于其他一些动物的颜色,如猫的白色(33.3%)和狗的巧克力色(34.4%)

黑狗黑猫欣赏日

黑猫和黑狗赞赏日创办于 2013–2014 年,它们背后都有不同的令人心碎的故事。主要想法是突出和欣赏黑色的动物,并鼓励人们收养它们。美国的大多数收容所和动物中心开始通过收取收养费和给收养者提供一些福利来推广黑色宠物。为了增加对黑色宠物的收养,促销活动在 7 月至 8 月举行,因为黑猫的欣赏日是在 8 月 17 日,黑狗的欣赏日是在 10 月,因为黑狗的欣赏日是 10 月 1 日。

推广黑宠物真的增加了黑宠物被收养的数量吗?

对于这个观察,我只过滤了黑色的动物,并使用棒棒糖图来可视化每月的收养数量。

棒棒糖计划查看每月收养黑人动物的数量

看起来对猫的促销确实增加了黑猫在七月和八月被收养的数量,但是对黑狗的促销并不影响它们被收养的数量。另一个有趣的趋势是季节性采用。大多数猫在夏天被收养,狗在冬天被收养。

进一步探索

由于收容所对黑色动物的推广,自 2013 年以来,黑猫和狗的收养率有所增加。此外,黑色宠物的摄入量在 2013 年至 2019 年期间有所下降。

条形图显示每年黑人动物的摄入量和收养量

狗和猫在通过颜色被收养之前花了多少时间

下图显示,平均而言,动物在被收养前在收容所的时间不会超过一年,然而,也有很多异常值。我们可以看到狗中有更多的离群者,这是因为狗比猫有更难的收养过程。

用动物的颜色显示收养前在收容所度过的日子

最后

总结我的观察和数据分析,我可以得出这样的结论:黑猫和狗很难被收养,而且几乎总是被忽视。人们倾向于收养皮毛颜色更浅更亮的动物。黑猫和黑狗综合症是真实的,然而,这是在不久前。

目前的数据分析显示,由于促销活动和人们接受教育,黑狗和黑猫与任何其他颜色的狗和猫一样友好、可爱、忠诚,因此几乎 45%的黑色宠物被收养。

欣赏所有动物

注意:

这个项目是作为数据科学课程的一部分为 Lambda School(Bloom Technology now)完成的。

链接到源代码:

Github 知识库黑猫和黑狗综合症分析

黑人的生命也很重要

原文:https://towardsdatascience.com/black-lives-also-matters-4f8ae03ede17?source=collection_archive---------54-----------------------

不幸的现实

很难相信,但是…

医疗保健中的种族差异被很好地记录下来,防止它们仍然是一个全国性的问题。医疗保健中的种族差异极大地导致了不利的患者健康结果。根据国家健康科学中心的数据,尽管美国的健康水平和死亡率有了显著的提高,但是白种人和黑种人之间的健康差距在 1950 年仍然很大。

由马库斯·斯皮斯克在 Unsplash 上拍摄的照片

在男性中,死亡率的种族差异随着时间的推移有所增加。美国国家健康科学中心也报告说,美国黑人患有多种疾病,其后果比美国白人更糟糕。

黑人女性比白人女性更不容易患乳腺癌。然而,他们死于这种疾病的可能性要高出 40%[1]。

健康差异包括几个因素,如社会经济地位。属于高社会经济地位的人群通常拥有更好的健康状况。然而,社会经济地位并不能完全证明种族健康差异的合理性,这种差异甚至在高收入群体中也持续存在。

根据 2012 年全国医疗保健差异报告,在 191 项指标中,有 43%的指标显示,具有可比 SES 和保险的黑人患者比白人患者获得的护理质量更差[1]。

更多证据

  1. 一项研究分析了 100 多万名患有类似呼吸系统疾病的儿童的临床访问,报告称,与白人儿童相比,黑人儿童获得的抗生素较少[1]。

2.在美国进行的另一项全国性研究表明,失去一根手指的黑人儿童断指再植的可能性是白人儿童的一半[1]。

3.根据对 800,000 份出院记录的回顾,患有外周动脉疾病的黑人患者比白人患者有 77%的机会截肢[1]。

4.与白人女性相比,接受乳腺癌化疗的黑人女性更倾向于非标准治疗方案[1]。

因糖尿病和循环系统疾病入院的黑人和白人患者的再入院率有差异吗?

回答:是的

ggplot(readmission, 
 aes(x= number_inpatient,
 y=number_emergency))+
 geom_point(alpha=1/10,size=number_inpatient)+ 
 geom_jitter()+ geom_smooth() +
 facet_wrap(readmitted~diabetesMed, scales = “free” )+
 labs(y=”Number of Inpatient”, 
 x=”Number of Emergency”,
 title = “Number of Inpatient and Emergency by Readmission Status for Diabetic Patient”,
 caption=”Each facet is scaled independently”)+
 theme_light()

视觉叙事

作者照片

ggplot(readmission, 
 aes(y= num_medications,
 x=num_lab_procedures, color=readmitted))+
 scale_color_discrete()+ 
 geom_point(alpha=1/100,size=number_diagnoses)+ 
 geom_jitter(alpha=1/40)+
 facet_wrap(~readmitted)+
 labs(y=”Number of Medication”, 
 x=”Number of lab procedures”,
 title = “Number of medications and lab procedures”)+
 theme_dark()

作者照片

ggplot(readmission, aes(x=readmitted, color=age ))+ 
 geom_histogram( stat = “count”, aes(fill=age))+
 facet_wrap(~race,scales = “free”)+ scale_color_discrete()+
 labs(y=”Number of patients”, 
 title = “Number of Readmissions by Race and Age”,
 subtitle = “<30: readmitted within a month \n >30: readmitted after one month \n NO: Not readmitted “, 
 caption = “Note: Each facet is scaled independently”)

作者照片

分析显示,总体而言,患有类似疾病的美国黑人和白人患者受到了不同的对待。如下图所示,所有因素,如“实验室检查次数”、“住院患者就诊次数”、“门诊患者就诊次数”、“住院时间”、“诊断次数”、“药物治疗次数”都有显著差异。

作者照片(使用的软件:PRISM9)

如下所示,详细的分析还表明,与糖尿病黑人患者相比,糖尿病白人患者接受了更多的药物治疗和诊断测试。对于非糖尿病患者,美国白人接受了更多的实验室检查和诊断程序。然而,非糖尿病黑人和白人患者接受的药物治疗数量相似。

作者照片(使用的软件:PRISM9)

下面的分析表明,美国黑人比美国白人更有可能被重新接纳。

作者照片(使用的软件:PRISM9)

参考

[1]乔因特·柯,奥拉夫·EJ,贾·阿克。按种族和医疗场所划分的医疗保险受益人的 30 天再入院率。 JAMA。 2011 年;305(7):675–681.doi:10.1001/jama

布莱克-斯科尔斯期权定价是错误的

原文:https://towardsdatascience.com/black-scholes-option-pricing-is-wrong-b62cd13baf42?source=collection_archive---------47-----------------------

理论、假设、问题和从业者的解决方案

照片由像素的皮克斯拜拍摄

Black 和 Scholes (1973)提出的公式是欧式期权的标准理论定价模型。关键词是理论上的,因为布莱克-斯科尔斯模型做出了一些关键假设,但在实践中却立即遭到了违反。

关键模型假设:

  • 没有交易成本
  • 无套利
  • 连续交易

理论与实践

布莱克-斯科尔斯模型依赖于复制投资组合的概念(更具体地说,一个抵消复制投资组合,或对冲——见波动性交易 101 )。复制投资组合反映了期权的现金流,它是通过在基础资产中建立一个相对于基础资产的布莱克-斯科尔斯方程的一阶偏导数的头寸(期权 delta)来实现的。完美抵消的复制投资组合和期权头寸的组合创建了风险中性的投资组合,该投资组合必须赚取无风险利率,在 无套利 的假设下,将微分方程的期权定价解绑定到 Black-Scholes 模型。

投资组合 H 由抵消复制投资组合和赚取无风险利率的期权组成

完整解释见 推导布莱克-斯科尔斯模型

然而,完美的复制投资组合只存在于理论上。假设基础资产遵循扩散过程(几何布朗运动,见鞅和马尔可夫过程)。这个过程提供了无限量的变化,为了保持一个完美的复制投资组合,我们必须随着期权的 delta 变化不断调整我们的头寸。理论上,我们假设 没有交易成本连续交易 ,允许我们根据需要自由调整抵消复制投资组合。在实践中,尽管大多数人认为,除了潜在的流动性问题之外,大部分时间没有套利,但在期权的整个生命周期中,不断调整抵消复制投资组合将积累惊人的交易成本。学者和从业者实施了各种解决方案来寻找维持抵消复制投资组合的最佳频率和策略。在本文中,我想介绍这一研究潮流的创始人,他在 1985 年写了一篇名为带交易成本的期权定价和复制的论文。

利兰(1985)

利兰是第一个研究交易成本对期权价格影响的人。为了将期权价格重新绑定到 Black-Scholes 模型中,他开发了一种针对短期和长期头寸的方差修正方法。Black-Scholes 模型的这一修正方差旨在反映在期权有效期内维持复制投资组合所需的预期交易成本。其中 kappa 是交易成本占交易量的比例(复制投资组合调整或套期保值间隔)…

空头期权头寸的利兰方差

Leland 通过让套期保值区间之间的时间趋近于零,证明了他的方差修正方程,产生了与原始期权具有相同现金流的复制投资组合,在无套利假设下,再次将期权价格绑定到 Black-Scholes 模型。因此,具有这个修改的方差项的期权的 delta 更平坦,这降低了 gamma。直观上,交易成本在买入时会提高基础资产价格,在卖出时会降低基础资产价格,这可以被建模为基础资产价格的波动性高于实际价格。尽管利兰方差允许我们在期权价格模型中包含预期交易成本,但它并没有提到维持对冲的最佳频率或策略。

其他文献

如果你有兴趣了解更多关于对冲频率或策略问题的解决方案,请访问我的网站…

[## 研究

摘要:交易成本违反了布莱克-斯科尔斯模型的一个关键假设。这造成了不完美的复制…

romanthequant.com](https://romanthequant.com/research/)

学术研究为从业者提供了各种有用和不良的解决方案。我目前正在进行一个关于这个主题的文献综述,我有一个非常粗略的参考当前文献的草稿。

参考

利兰,H. (1985 年)。有交易费用的期权定价和复制。《金融杂志》,第 40 卷第 5 期,1283-1301 页。doi:10.2307/2328113

保鲁奇河(2020 年)。市场约束下的最优套期保值。我们的资本工作文件。

怪神经元。当神经科学和人工智能再次相遇。

原文:https://towardsdatascience.com/blame-neurons-when-neuroscience-and-ai-cross-paths-again-8be12f6c9229?source=collection_archive---------51-----------------------

神经科学和人工智能一直紧密相连,然而,是时候报仇了。

“责怪别人需要时间和精力来提升自己”。

L 让我们来谈谈神经科学。我们能够将一种主要的人工智能算法应用于我们的大脑吗?是的,你没看错!

是什么控制着我们每个人的思想、行为或争论?

的确,神经元。完美运行的无限神经回路。但是,这些神经元如何表现和顺应,以便不犯错误呢?想象你正在跑步,第一次你会摔倒,但一点一点地你会加快步伐,直到你完成第一场比赛。

那么一开始摔倒我们怪谁呢?那个神经元!或者是那个?大脑是如何从我们的错误中学习的?

深度学习的教父杰弗里·希尔顿(Geoffrey Hilton)博士以及其他伟大的特权思想认为,在这种机制背后是一种深度学习核心算法,它在大脑内部以同样的方式运行。

我们称之为“反向传播”。

由大卫·卡索拉托在像素上拍摄的照片

如果你想了解更多,去 oscargarciaramos.com访问

以防你以前从未听说过这个概念。在很高的层面上,这个概念是基于从错误中学习的想法,并且在做一件特定的事情时变得更好。这将是一种“责怪”我们网络中的神经元连接错误的方式,以便逐步提高期望的输出。

尽管这种说法尚未得到验证,甚至被一些神经科学家斥为“生物学上不可能”,但深度学习技术和神经科学日益交织的事实,唤起了许多“来自过去的幽灵”。但是,在理解我们的大脑方面也面临新的挑战。

就人工智能而言,它将令人惊讶地成为理解我们人类如何学习的奥秘的一种方式。

回去怪他们吧!

根据神经科学学习的教条是基于“一起开火,一起连线”。这是什么意思?当我们想要学习做一件新的事情时,神经元通过突触相互连接,形成一个网络,这个网络慢慢完善,将允许我们学习做一项新的任务,比如跑步。

但是它实际上是如何工作的呢?

神经网络由不同的个体或神经元组成,这些个体或神经元只与它们的邻居进行交互。换句话说,单个神经元只接收来自其上游伙伴的信息,并将该信息委托或传输给其下游伙伴。这些连接的强度或阻力取决于什么?上 【突触重量】 。一个明喻可以是一个有力或无力的握手。正如你所知道的,取决于你握手的对象,并不总是强有力的握手是最理想的。学习的要点是基于“调整”或平衡我们所有握手的重量,这样我们才能得到我们想要的结果。

现在,想象所有的神经元和它们的邻居决定投票选举社区的“市长”。然而,他的对手出来了。谁投票不好,网络如何整体解决?我们不得不“责怪”某人,这样我们才能让结果变得更好。那是我们的“学习过程”。但是为了学习,我们必须“调整”权重,甚至在我们知道首先调整哪些连接之前。

早在 1986 年,希尔顿、大卫·鲁梅尔哈特和罗纳德·威廉姆斯发现,信息通过不同的神经层传播,如果我们观察获得的输出与预期的输出有多远,就有可能用数学方法计算出一个 误差信号 。该信号可以通过神经层传输,每个神经层基于其上层接收新的信号误差。

因此得名“反向传播”

想象一场足球比赛。小区域有四名球员,最后一名球员失败,不得分。教练会怎么做?。他将从最后一个触球的球员开始,判断他/她没有最终得分“有多内疚”,并将倒退判断谁需要“穿上他的靴子”进行调整,也就是说,他将改变他们的“突触重量”。**

玩家回到该区域,也就是说,我们再次计算同样的问题,然后… Goooaaaal!我们成功了!反向传播调整已经生效,网络将把新的突触权重作为参考,并继续学习。

那么,下一步是什么?

这一切有意义吗?

反向投影结合其他算法已经成为面部识别、自动文本转录甚至人工智能游戏胜利(如围棋或扑克)等领域的主导技术。

然而,至少到目前为止,大脑中类似反向传播信号的想法仍然是猜测。

你可能想知道为什么…

一个最强有力的原因是,一般来说,人工智能网络的配置不像生物网络,因此,我们不能推断它们的反向传播。

基本上,我们的大脑不能回到过去改变突触的重量。生物神经元不是这样工作的。它们可以通过更多的输入或激素或化学递质等其他类型的调节来改变它们的连接,但在不混淆生物神经元的情况下,将相同的物理分支和突触用于直接和反馈信号被认为是“不可能的”。

但是,如果我们将这一理论应用到我们的大脑中,我们可以开发一个新的层次,将生物学习与人工智能联系起来。

你觉得这篇文章有用吗?

欢迎发表评论或分享这篇文章。关注 me 未来岗位。

**如果你想了解更多,你可以在oscargarciaramos.com找到我

与 R data.table 进行极快的数据争论

原文:https://towardsdatascience.com/blazing-fast-data-wrangling-with-r-data-table-de5045cc4b4d?source=collection_archive---------9-----------------------

谁有时间用慢代码做数据科学?

照片由 Fotis Fotopoulos 在 Unsplash 上拍摄

更新 2020 年 3 月: 在这里你可以找到一个很有意思的data.tabledplyr 的对比。

介绍

我最近注意到我写的每个 R 脚本都以library(data.table)开头。这似乎是我写这篇文章的一个非常有说服力的理由。

你可能已经看到,随着机器学习社区的发展,Python 获得了巨大的人气,因此,熊猫图书馆自动成为许多人的主食。

然而,如果我有选择的话,我肯定更喜欢使用 R data.table 进行相对较大的数据集数据操作、深入探索和特别分析。为什么?因为它太快了,优雅而美丽(抱歉我太热情了!).但是,嘿,处理数据意味着你必须把代码颠倒过来,塑造它,清理它,也许…嗯…一千次,然后你才能真正建立一个机器学习模型。事实上,数据预处理通常占用数据科学项目 80–90%的时间。这就是为什么我不能承受缓慢而低效的代码(作为一名数据专家,我认为任何人都不应该这样)。

所以让我们深入了解什么是data.table以及为什么许多人成为它的忠实粉丝。

1.那么 data.table 到底是什么?

data.table 包是 r 中data.frame包的扩展,广泛用于大型数据集的快速聚合、低延迟的列添加/更新/删除、更快的有序连接以及快速的文件读取器。

听起来不错,对吧?你可能觉得很难接,但实际上 a data.table也是data.frame的一种。所以请放心,您为data.frame使用的任何代码也将同样适用于data.table。但是相信我,一旦你使用了data.table,你就再也不想使用 base R data.frame语法了。想知道为什么就继续读下去。

2.Data.table 非常快

从我自己的经验来看,使用快速代码确实可以提高数据分析过程中的思维流程。速度在数据科学项目中也非常重要,在这个项目中,你通常必须快速地将一个想法原型化。

说到速度,data.table让 Python 和许多其他语言的所有其他包都相形见绌。这个基准显示了这一点,它比较了来自 R、Python 和 Julia 的工具。在一个 50GB 的数据集上进行五次数据操作,data.table平均只用了 123 秒,而 Spark 用了 381 秒,(py)datatable 用了 712 秒,pandas由于内存不足无法完成任务。

data.table 包中最强大的函数之一是fread(),它与read.csv()类似地导入数据。但它已经过优化,速度快得多。让我们看看这个例子:

require("microbenchmark")
res <- microbenchmark(
  read.csv = read.csv(url("[https://archive.ics.uci.edu/ml/machine-learning-databases/adult/adult.data](https://archive.ics.uci.edu/ml/machine-learning-databases/adult/adult.data)"), header=FALSE),
  fread = data.table::fread("[https://archive.ics.uci.edu/ml/machine-learning-databases/adult/adult.data](https://archive.ics.uci.edu/ml/machine-learning-databases/adult/adult.data)", header=FALSE),
  times = 10)
res

结果将显示,平均而言,fread()将比read.csv()函数快 3-4 倍。

3.它直观而优雅

几乎所有使用data.table的数据操作都是这样的:

来源:https://github.com/Rdatatable/data.table/wiki

因此,您编写的代码将非常一致且易于阅读。让我们以美国人口普查收入数据集为例进行说明:

dt <- fread("[https://archive.ics.uci.edu/ml/machine-learning-databases/adult/adult.data](https://archive.ics.uci.edu/ml/machine-learning-databases/adult/adult.data)", header=FALSE)
names(dt) <- c("age", "workclass", "fnlwgt", "education", "education_num", "marital_status", "occupation", "relationship", "race", "sex", "capital_gain", "capital_loss","hours_per_week", "native_country", "label")

在下面的例子中,我将比较 base R、Python 和 data.table 中的代码,以便您可以轻松地比较它们:

  1. 计算所有“技术支持”人员的平均age😗*

>base R 中你大概会写出这样的东西:

*mean(dt[dt$occupation == 'Tech-support', 'age'])*

>在 Python 中:

*np.mean(dt[dt.occupation == 'Tech-support'].age)*

数据表>与:

*dt[occupation == 'Tech-support', mean(age)]*

正如你在这个简单的例子中看到的,与 Python 和 base R 相比,data.table消除了所有重复dt的冗余。这反过来减少了犯打字错误的机会(记住编码原则 DRY —不要重复自己!)

2.到所有男性工人按职业分类的总年龄:

>基地 R* 你大概会写:*

*aggregate(age ~ occupation, dt[dt$sex == 'Male', ], sum)*

>在 Python 中:

*dt[dt.sex == 'Male'].groupby('occupation')['age'].sum()*

数据表与>对比*😗

*dt[sex == 'Male', .(sum(age)), by = occupation]*

by =术语定义了您希望在哪个(哪些)列上聚合数据。这种data.table语法一开始可能看起来有点吓人,但是一旦你习惯了,你就再也不会费心输入“groupby(…)”了。

3.为了有条件地修改列中的值,例如将所有技术支持人员的age增加5(我知道这是一个愚蠢的例子,但只是为了说明:)。

>在 base R 中,你可能不得不写下这可怕的一行(谁有时间写这么多次dt$!):

*dt$age[dt$occupation == 'Tech-support'] <- dt$age[dt$occupation == 'Tech-support'] + 5*

>在 Python 中(有几个备选方案同样长):

*mask = dt['occupation'] == 'Tech-support'
dt.loc[mask, 'age'] = dt.loc[mask, 'age'] + 5*

或者使用np.where:

*dt['age'] = np.where(dt['occupation'] == 'Tech-support', dt.age + 5, dt.age]*

>与数据表中的比较:

*dt[occupation == 'Tech-support', age := age + 5]# and the ifelse function does just as nicely:
dt[, age := ifelse(occupation == 'Tech-support', age + 5, age)]*

这几乎就像一个魔术,不是吗?没有更多繁琐的重复代码,它让你保持干爽。您可能已经注意到了data.table语法中奇怪的操作符:=。该操作符用于向现有列分配新值,就像在 Python 中使用参数inplace=True一样。

4.重命名列在 data.table 中轻而易举。如果我想将occupation 列重命名为job:

>在 base R 中,您可以写:

*colnames(dt)[which(names(dt) == "occupation")] <- "job"*

>而在 Python 中:

*dt = dt.rename(columns={'occupation': 'job'})*

>相对于数据表:

*setnames(dt, 'occupation', 'job')*

5.如何将函数应用到几列?假设您想将capital_gaincapital_loss乘以 1000:

>在底座 R:

*apply(dt[,c('capital_gain', 'capital_loss')], 2, function(x) x*1000)*

>在 Python 中:

*dt[['capital_gain', 'capital_loss']].apply(lambda x : x*1000)*

>相对于数据表:

*dt[, lapply(.SD, function(x) x*1000), .SDcols = c("capital_gain", "capital_loss")]*

您可能会发现 data.table 中的语法有点古怪,但是.SDcols参数在许多情况下非常方便,data.table 语法的一般形式就是这样保留下来的。

结论:

从上面几个简单的例子可以看出,R data.table中的代码在很多情况下比 base R 和 Python 中的代码更快、更干净、更高效。data.table代码的形式非常一致。你只需要记住:

*DT[i, j, by]*

作为补充说明,通过键入data.table使用i设置数据子集甚至允许更快的子集、连接和排序,你可以在这个文档或这个非常有用的备忘单中了解更多信息。

感谢您的阅读。如果你喜欢这篇文章,我会在以后的文章中写更多关于如何与 R 和 Python 进行高级数据辩论的内容。

炽热的 Python AsyncIO 管道

原文:https://towardsdatascience.com/blazing-hot-python-asyncio-pipelines-438b34bed9f?source=collection_archive---------24-----------------------

并发高效地处理大量流水线式 web、数据库和微服务请求

约书亚·牛顿在 Unsplash 上的照片

对于内存高效和可读的代码来说,流水线功能非常强大。在这些函数中,一个函数的输出输入下一个函数的输入。一些示例应用包括:

  • 跨越不同但相关的数据源的多级 web 刮刀
  • 具有数据提取、转换和处理步骤的机器学习管道
  • 对大数据集进行逐行操作

使用 Python 的asyncio库进行并发操作既快速又节省资源,尤其是对于 IO 绑定的任务。

本文将向您展示如何构建您自己的可以非常高效地运行的管道,尤其是如果您要进行大量的 IO 操作,如 web 请求或数据库查询。后续文章将通过提供一个库来抽象出下面显示的大部分底层机制,使之变得更加容易。

同步发电机管道

Python 生成器有一个send()方法,可以用来在生成器调用yield时将数据发送到生成器中。把它放入一个无限循环中,你会在你的管道中得到一个不断等待输入的阶段,用它做一些事情,然后发送到下一个阶段。

您可以使用这种基于推送的方法以扇出模式发送到多个其他生成器,因此我们假设我们有一个target生成器的列表。

当我们从生成器函数创建生成器时,我们必须通过发送None来初始化它。这使得生成器在功能代码中前进,直到遇到第一个yield语句。

这里有一个完整的例子。

运行输出:

T2:已初始化参数:你好 T2
T1:已初始化参数:你好 T1
T1:已接收输入:1
T1: T1 发送 1
T2:已接收输入:1
T1:已接收输入:2
T1: T1 发送 2
T2:已接收输入:2
T1:已接收输入:3
T1: T1 发送 3
T2:已接收输入:3
时长:6.01299477

注:

  • 我们将所有的输入(第 20–22 行)发送到第一阶段,它会通过管道自动传播
  • 这都是同步代码。在发送下一个输入之前,第一个输入完全通过。
  • 易于使用断点进行调试
  • 我们必须反向构造和链接,因为gen1(即gen2)的目标生成器必须存在,才能作为参数传递给 gen1 的生成器函数。

异步发电机管道

我们可以使用同步 python 生成器等待输入,但是使用协程异步处理输入(由 sleep 函数模拟)。我们通过将处理和发送代码放在async def内部函数中来实现这一点。

在循环中的每一次迭代中,我们都会得到一个输入值,并生成一个 asyncio 任务。我们在一个全局tasks列表中跟踪所有产生的任务。

我们的主函数也必须是一个运行在事件循环中的协程。这是由asyncio.run(main())完成的。注意在 main 中,我们如何使用async.gather()函数等待所有任务完成。这必须做两次,因为我们分两个阶段提交任务。现在很尴尬。

完整示例:

运行输出:

T2:用参数初始化:你好 T2
T1:用参数初始化:你好 T1
T1:用 T1_inner 创建任务,输入 1。
T1:使用 T1_inner 创建任务,输入 2。
T1:用 T1_inner 创建任务,输入 3。
T1:接收输入:1
T1: T1 发送 1
T2:用 T2_inner 创建任务,输入 1。
T1:接收输入:2
T1: T1 发送 2
T2:用 T2_inner 创建任务,输入 2。
T1:接收输入:3
T1: T1 发送 3
T2:用 T2_inner 创建任务,输入 3。T2:接收到的输入:1
T2:接收到的输入:2
T2:接收到的输入:3
持续时间:2.00000000001

:

  • 由于异步睡眠,运行速度更快
  • 需要一个事件循环
  • 很难知道什么时候所有的任务都完成了
  • 关于send函数的竞争条件的一些问题

等待救援的队伍

asyncio.Queue类也有一个方便的task_done()方法。队列对象跟踪get()task_done()被调用的次数。如果相同的次数,它假定从队列中取出的所有项目也已经被处理,并且它允许自己被加入(如果队列是空的)。这允许我们按顺序调用await on q.join()来了解一个阶段是否完成,并且我们可以避免多次调用asyncio.gather()

运行输出:

T2:用参数初始化:你好 T2
T1:用参数初始化:你好 T1
T1:用 T1_inner 创建任务,输入 1。
T1:用 T1_inner 创建任务,输入 2。
T1:用 T1_inner 创建任务,输入 3。
T1:接收输入:1
T1:接收输入:2
T1:接收输入:3
T1: T1 发送 1
T1: T1 发送 2
T1: T1 发送 3
T2:用 T2 _ 内创建任务,输入 1。
T2:用 T2_inner 创建任务,输入 2。
T2:用 T2_inner 创建任务,输入 3。
T2:已接收输入:1
T2:已接收输入:2
T2:已接收输入:3
持续时间:2.00000000005

注意:

  • input_q.task_done()是调用内部函数的结尾
  • 我们没有把send()变成发电机,而是把put()放在一个队列上
  • 我们只需要收集一次任务

结论

我们可以通过使用 python 生成器来创建简单的同步管道。通过交换到 asyncio 队列和协程,我们可以拥有非常高效的 io 管道,并保持对我们生成的任务的控制。

搅拌机机器人—第 1 部分:数据

原文:https://towardsdatascience.com/blender-bot-part-1-the-data-524beaedde65?source=collection_archive---------32-----------------------

图片来源:奥斯汀·迪斯特尔在 Unsplash

“我擅长同化的艺术。我观察、倾听、学习。我什么都不知道,但我研究了人类的方式,慢慢学会了如何毁灭,如何仇恨,如何贬低,如何羞辱。在我主人的脚下,我学到了人类最高的技能,没有其他生物拥有的技能。我终于学会了如何撒谎!”

你能猜到是谁说出这些台词吗?让我给你两个选择:

A) 一个聊天机器人 B) 来自《科学怪人》的生物。

我会在本文最后揭晓答案。

简介:

一个好的聊天机器人的目的是观察、倾听、学习和研究男人(和女人)的方式。),并学习许多不同的人类技能,以便进行良好的交谈。聊天机器人在会话机构的权限内服务于两种不同的设置。

  1. 目标导向对话:这些是从事在线机票/餐厅预订和其他客户服务的人。它们通常有一组固定的“意图”和相应的“响应”(以及映射到意图的“动作”,这些动作在后台执行)。他们还有一个知识库(数据库),可以通过 API 调用来访问。
  2. 开放领域对话:这些人可以参与各种话题的开放式聊天。开放领域聊天机器人最近的进步在很大程度上归功于神经网络模型的扩展——通过拥有更多参数和在巨大的语料库上进行训练。谷歌的米娜。Meena 有 2.6B 参数,并在来自社交媒体对话的 341GB 文本上进行训练。与 OpenAI GPT-2 相比,Meena 的模型复杂性增加了 1.7 倍,训练数据增加了 8.5 倍。

但是来自 FAIR 的研究人员试图表明,仅仅扩大规模是不够的,还需要考虑更多因素才能产生良好的对话——聊天机器人要显示出类似人类的特征,比如:

  1. 个性
  2. 参与度
  3. 神入
  4. 领域知识/专业技能

进入“搅拌机机器人”,公平的冠军对话代理,他们最近开源。

在这个关于 Blender 的 3 部分系列中,我将尝试逐一解释所使用的数据集、评估方法、所使用的变压器架构的工作方式以及模型架构及其培训目标。在第一部分,让我们详细讨论一下所用的数据集,同时也看看局限性和失败案例的概述。这篇论文有点系统化,所以对注意力、变形金刚、BERT 和语言模型的预先理解将有助于将所有的部分无缝地结合在一起(第 1 部分不需要)。

数据集:

在模型的预训练和微调阶段使用不同的数据集和(假)任务。

预培训:

伯特预先接受了多伦多图书语料库和维基百科的培训。这种训练在这种情况下没有帮助,因为我们处理的是对话生成,而不仅仅是句子关联。因此,来自 Reddit 和 subreddits 的公共领域数据被用作事实的来源。产生大约 15 亿个训练样本。这里的目标是生成一个注释,以通向注释的完整线程为条件。清理 reddit 数据是一个具有挑战性的过程。在下列情况下,不使用特定的注释:

  1. 如果作者是已知的机器人
  2. 如果它来自非英语子编辑
  3. 如果超过 2048 个字符或少于 5 个字符
  4. 如果它包含 URL
  5. 如果它以非 ASCII 字符开头
  6. 如果它在螺纹中的深度大于 7
  7. 如果是移除/删除的评论

尽管对数据进行了清理,但数据仍然受到毒性、噪音以及它们不是双向对话而是小组讨论这一事实的影响。

微调:

变压器模型的微调通常在与下游任务更相关和更接近的数据集上进行。同样,Blender 的微调是在众包、更干净、更小的双向对话数据集上进行的。让我们来详细了解一下它们。

  1. ConvAI2: 这是 NeurIPS-2018 中 ConvAI2 挑战赛的数据集。它基于角色聊天数据集。在这里,根据描述他们的人物角色的句子,给两个演讲者中的每个人分配一个角色,这些句子也是单独众包的(两个演讲者都可以看到他们自己的人物角色描述,但看不到他们搭档的人物角色)。因此,这项任务包括了解对方,让他们参与友好的对话,包括提问和回答问题。“角色”的使用提高了机器人的一致性。
  2. 移情对话(ED): 该数据集在“走向移情开放域对话模型:一个新的基准和数据集”中进行了基准测试,拉什金等人,2019 年。在这里,在每个对话中,一个人描述一个人的情况,另一个人扮演“倾听者”的角色,在讨论中表现出共鸣。在这个数据集上微调模型有助于他们在人类评估中表现出更多的同理心。
  3. 维基百科向导(WoW): 这里的任务包括深入讨论一个给定的主题,目的是让合作伙伴参与进来,并展示专业知识。然而,这两个参与者并不完全对称:一个将扮演知识渊博的专家(我们称之为向导)的角色,而另一个是好奇的学习者(学徒)。他们中的一个会选择一个话题。向导可以访问一个信息检索系统,该系统向他们显示维基百科中可能与对话有关的段落,而学徒没有注意到这些段落。在每次对话开始之前,向导可以阅读这些段落,然后根据观察到的知识做出下一次回复。收集这个数据集的目的是用一个有学问的代理人代替人类巫师,这个代理人将与人类学徒交谈。
  4. 混合技能对话(BST): 一个约 5000 次对话的小型众包数据集,参与者被要求在对话中酌情展示所有 3 种品质——个性、同理心和专业技能。他们提供了经过特定技能训练的模型的回答,作为对话中两个工人之一的灵感。该工作人员可以自由地使用和修改或忽略这些响应。因此,每次对话都包括一个“无指导”的说话者和一个“有指导”的说话者,无指导的说话者先说话。每当轮到被引导的演讲者回答时,他们都会看到三个建议的回答,分别来自三个单任务多编码器模型(下一部分将详细介绍),这些模型都是在 ConvAI2、ed 和 WoW 数据集上训练的。BST 中的所有对话都充分注释了所代表的技能。一旦收集了数据集,就可以通过组合针对单个功能训练的模型来训练 oracle 模型。它有两种变体:a)poly-encoder 首先在 Reddit 数据集上进行预训练,然后在各个数据集上进行微调。 b) 在 reddit 数据集上进行预训练,然后在 BST 数据集上进行微调。下面给出了 BST 数据集中两个人群工作者之间的对话示例。

BlendedSkillTalk 数据集中引导和非引导说话者之间的对话示例。

来自 BlendedSkillTalk 数据集的示例对话,用四种对话模式类型进行了注释:PB:个人背景;k:知识;s:个人情况;e:感同身受。被引导的(G)和未被引导的(U)工人被给予角色和主题。该对话已经被播种了来自从 WoW 中采样的对话的两个话语。当被指导的工作人员选择其中一个建议时,它以灰色阴影显示。

安全性:

BST 和其他进行微调的数据集都是众包的,在众包中,工作人员得到明确的指示,不要使用有毒/有偏见的语言,因此通常更安全。但请记住,预训练是在 Reddit 数据上进行的——这些数据往往包含大量的负面训练样本。在推理时,使用一个经过训练的分类器来识别有毒语言,以帮助缓解这个问题。

模型限制和故障案例:

  1. 词汇用法:采用波束搜索解码的生成变换器模型表现出过于频繁地生成常用词和过于不频繁地生成稀有词的倾向。例如,最常见的 3 个字母(在数据集中)像“你喜欢吗”、“有什么爱好吗”、“很有趣”会被反复重复。
  2. 非同寻常的重复:模特们经常重复别人对她们说的话。例如,如果对话伙伴提到宠物狗,他们会说他们有一只宠物狗,或者他们喜欢与他们交谈的人相同的乐队。
  3. 矛盾和健忘: Blender 模型自相矛盾,尽管在较大的模型中程度较低。他们也没有建立逻辑联系,即他们不应该问他们以前问过的问题(以避免“忘记”的出现)。
  4. 知识和事实正确性:操纵 Blender 模型犯事实错误相对容易,尤其是在深入探索一个主题的时候。
  5. 对话长度和记忆: Blender 的对话可能会在几天或几周的对话过程中变得枯燥和重复,尤其是考虑到 Blender 不记得以前的对话。
  6. 更深层次的理解:Blender 模型缺乏通过进一步交谈学习概念的能力,他们没有办法根植到现实世界中的实体、动作和经验。

在下图中,您可以找到失败案例的示例:

失败案例示例。

发现的问题:

  1. 示例 1:非平凡重复
  2. 例子 2:健忘
  3. 例 3:矛盾,佐治亚不在中西部
  4. 例子 4:产生幻觉的知识,错误地将游戏与制作者联系起来

在下一部分中,我们将探索 Blender 中使用的 Transformer 架构,称为 Poly-Encoder,以及它如何优于其他变体,如用于多句子评分的相同任务的双编码器或交叉编码器。

最后是我们在文章开头看到的问题的答案:B)来自《弗兰肯斯坦》的生物!如果你猜它是 A)一个聊天机器人,那么你就快猜对了,因为用不了多久,我们就可以和一个全面的对话代理谈论人类的邪恶了!

参考资料:

  1. 关于 Blender:https://www . kdnugges . com/2020/05/Facebook-open-sources-Blender-maximum-open-domain-chatbot . html
  2. 搅拌机机器人研究:【https://arxiv.org/abs/2004.13637
  3. 搅拌机机器人食谱:【https://parl.ai/projects/recipes/
  4. 果果技能对话:https://arxiv.org/abs/2004.08449
  5. 维基百科的巫师:https://arxiv.org/abs/1811.01241
  6. 关于 Meena:https://ai . Google blog . com/2020/01/forward-conversational-agent-than-can . html

搅拌机机器人——第二部分:变压器

原文:https://towardsdatascience.com/blender-bot-part-2-the-transformer-2e4d960b149f?source=collection_archive---------23-----------------------

科迪·恩格尔在 Unsplash 上的照片

脸书开源聊天机器人“Blender”打破了之前由谷歌“Meena”创造的所有记录。在本帖中,我们将回顾构成 Blender 核心的多编码器转换器架构。

你可以在 TDS 上阅读本系列的第一部分,在那里我们已经查看了训练聊天机器人的数据集。

假设读者对注意力、变形金刚、伯特和生成性语言模型有预先的了解,我将继续前进。

简介:

在看到如何在 Blender 的上下文中使用 Poly-Encoder 之前,我们将首先独立地理解它们。在预训练和微调搅拌机中使用的数据集和(假)训练任务(在第 1 部分中有详细解释)不应该与我下面将要解释的细节混淆。这里给出的实验设置是为了在一般设置中理解一个名为“多句子评分的特定任务以及为该任务训练的编码器架构。然后,在为此任务训练的编码器架构中,我们将看到多编码器是如何优越的。

任务:

多句子评分在输入和输出序列之间进行成对比较。给定一个输入序列,我们对一组候选标签进行评分。

从这里开始,我们将用【INPUT,LABEL】来表示输入输出对。

目标是从有限的候选标签列表中找到最佳标签。所使用的编码器是 BERT-Base,在前向网络中具有 12 个编码器块、12 个注意头和 768 个隐藏神经元。

预培训:

为此任务进行了两个版本的预培训:

  1. 像伯特一样预先训练,在多伦多图书语料库和维基百科上。这里的[输入,标签]可以认为是[句子 A,句子 B]。
  2. 接受过 Reddit 上公共领域社交媒体对话的预培训。这里的[输入,标签]可以理解为[上下文,下一句]

假训练任务:

训练任务与 BERT 预训练中使用的任务相同。

  1. MLM:屏蔽语言模型:这里,一定百分比的输入标记被随机屏蔽(使用[MASK]标记)。接下来的任务是学习预测屏蔽的令牌。
  2. NSP:下一句预测:这里给出两个句子 A 和 B,任务是说 B 是否跟随 A?(带负采样)。负抽样是通过从数据集中随机抽取一个句子作为 B 来实现的,50%的情况下。

这里有点跑题。为了记住 BERT 中这些预训练任务的性质,我使用的一个技巧是与生成 Word2Vec 嵌入时使用的假训练任务进行直接比较,即:1) CBOW 2) Skip-Gram。如果你能回忆起来,在 CBOW(连续单词袋)中,给定一个上下文,任务是预测目标单词——类似于 MLM 任务。在 Skip-Gram 模型中,给定目标词,预测上下文= >但是我们改变数据集而不是预测上下文/相邻词,任务变成:给定目标词和另一个词->预测另一个词是否是目标词的邻居(二进制分类问题)。由于初始数据集仅由目标单词和它们上下文中的单词形成,修改后的数据集现在仅包含正面的例子。所以我们通过负采样引入噪声。非常非常类似于伯特的 NSP 任务。(如果你认为在 BERT 和单词嵌入的训练任务之间进行这样的比较有任何不一致之处,请在评论中告诉我。谢谢!)

微调:

该模型在 ConvAI2 数据集上单独进行了微调,从而鼓励他们学习“个性”特征,并在 Ubuntu 聊天日志上帮助他们学习“领域知识/专业技能”。

架构:

我们将看到解决“多句子评分”任务的 3 种编码器架构,即,

  1. 双编码器
  2. 交叉编码器
  3. 多元编码器

一个架构在推理过程中的性能是通过预测质量和预测速度来衡量的。

在继续之前,重要的是要记住这是一个检索而不是生成任务:我们只需要从一组固定的候选标签中检索一个正确的标签。

双编码器:

参考文献[1]中的双编码器架构

在双编码器中,对输入和标签分别进行自我关注。这不过是向量空间模型的更一般的概念。这种架构的优点是在推理过程中速度更快,因为我们可以预先计算和缓存大型固定候选标签集的编码。这是可能的,因为标签是单独编码的,与输入上下文无关。

  • 输入和标签都被一个特殊的标记包围。这类似于 BERT 中的[CLS]标记,它捕获了整个句子的特征。
  • 输入到编码器的嵌入是标记嵌入+段嵌入+位置嵌入的组合。段嵌入一般用来说一个令牌是属于 A 句还是 B 句(在 BERT 的上下文中)。因为输入和标签在这里是分开编码的,所以在两种情况下,段嵌入都是‘0’。
  • 将输入和候选标签分别映射到一个公共特征空间。在所示的公式中,T1 和 T2 是两个独立的变压器(编码器)。

  • 编码器在对输入令牌嵌入执行自我关注后,给出每个令牌的编码器表示,如:

  • 然后使用 reduce 函数( red )将其简化为单个嵌入表示。减少功能可以是以下任何一种:

->它可以采用第一个令牌的表示形式。这是对应于特殊令牌的表示

->或者我们可以取所有输出嵌入的平均值

->或者我们可以取第一个“m”的平均值(m

  • Once the INPUT and LABEL are represented thus in a common vector space, measure the similarity between them using standard dot product or any other non-linear function.

  • We then minimize the Cross Entropy loss function, where the logits look like:

Cross-Encoder:

参考文献[1] 中的交叉编码器架构)

  • 这里,输入和标签被连接起来,并且在输入和标签的整个序列之间执行完全的自我关注。也就是说,输入的每一个标记都将关注标签的每一个标记,反之亦然。这导致了输入和标签之间丰富的交互。
  • 即使在这里,输入和标签都被一个特殊的标记包围。
  • 同样,输入到编码器的嵌入是令牌嵌入+段嵌入+位置嵌入的组合。因为输入和标签是组合的,所以段嵌入对于输入令牌是“0 ”,对于标签令牌是“1”。
  • 交叉编码器比双编码器提供更高的精度,因为输入和标签之间的完全双向关注。同时,它们在推理过程中非常慢——因为每个候选标签都应该与输入上下文连接,而不能像双编码器那样单独编码。因此,候选嵌入不能被预先计算和缓存。当候选标签的数量很大时(正如在大多数真实场景中一样),交叉编码器不可伸缩。
  • 在自我关注之后,转换器给出所有输入标记的编码器表示。通过采用对应于第一个标记(即特殊标记)的嵌入,我们将其简化为单个表示。然后通过线性投影将该嵌入向量转换成标量分数。这两个步骤如下所示:

  • 这里的训练目标也是最小化由逻辑给出的交叉熵损失函数:

  • 其中' cand1' 是正确的候选,其他的是从训练集中取出的否定。这里的一个问题是,在双编码器中,我们可以使用批中的其他标签作为负训练样本-这里我们不能这样做。我们使用训练集中提供的外部否定。因为它计算量大,所以交叉编码器的内存批量也很小。

多元编码器:

参考文献[1]中的多编码器架构

  • 多编码器结合了双编码器和交叉编码器的优点。因此,在推理过程中,它比交叉编码器更快,比双编码器更准确。
  • 候选标签被单独编码。
  • 给定输入上下文,如:

我们执行 3 种类型的注意,如下所述:

  • 自我关注输入上下文的标记,我们得到:

  • 第二,我们学习“m”码(或自我关注的说法中的查询),其中 m < N (N being the length of the INPUT). The number of codes to be learnt, ‘m’, is a hyperparameter. Each code Ci attends over all the outputs of the previous Self-Attention. The ‘m’ codes are randomly initialized.
  • We first get the Attention weights (w’s) by performing a dot-product attention (or a multiplicative attention in general) between the ‘m’ codes — which serve as the “Queries”, and the previous Self-Attention outputs (Out’s)—which serve as the “Keys”. Then use these attention weights to get a weighted sum of the previous Self-Attention outputs(Out’s) — which serve as the “Values”.

  • Think about why we are doing this kind of an Attention mechanism here. In a Bi-Encoder, the candidate label does not attend over the tokens of the input context. A Cross-Encoder on the other extreme, makes the candidate label attend over every token of the input context. Somehow in the Poly-Encoder we are trying to find a middle ground, by making the candidate label embedding attend over not the entire input context, but over a subset of features learnt from the input context.

  • The third kind of attention (alluded to in the previous paragraph) is between the ‘m’ global features of the Input Context and the embedding of the Candidate Label.

  • Now we compute the Similarity score between the Input Context embedding and the Candidate Label embedding as:

  • Once again, the training objective here too is to minimize the Cross-Entropy loss function given by the logits as before.

We saw three different Encoder architectures for the task of “Multi-Sentence Scoring” and saw how the Poly-Encoders were better. In the next part, we will see how the Poly-Encoders are used in the Blender and also about the different Model Architectures and training objectives. We will also touch upon the Evaluation methods used to compare the performance of Blender with that of the other Chatbots.

注意:上面所有的符号、公式和编码器框图都与参考文献中提到的原始论文中使用的相同。[1].

参考资料:

  1. 多编码器变压器:【https://arxiv.org/abs/1905.01969
  2. https://arxiv.org/abs/1810.04805
  3. 变形金刚:https://arxiv.org/abs/1706.03762

Blender Bot —第 3 部分:多种架构

原文:https://towardsdatascience.com/blender-bot-part-3-the-many-architectures-a6ebff0d75a6?source=collection_archive---------28-----------------------

Volodymyr Hryshchenko 在 Unsplash 上拍摄的照片

我们一直在研究脸书的开源对话产品 Blender Bot。

在第一部分中,我们详细回顾了预训练和微调中使用的数据集以及 Blender 的失败案例和局限性。

在第二部分中,我们研究了“多句子评分”这一更普遍的问题设置,用于此类任务的转换器架构,并特别了解了多元编码器——它将用于在 Blender 中提供编码器表示。

在第三部分,也是最后一部分,我们从聚合编码器的喘息中回到 Blender。我们将回顾不同的模型架构、它们各自的训练目标、评估方法以及 Blender 与 Meena 相比的性能。

模型架构:

本文(参考文献[2])讨论了模型的几种变体,这些变体在多个因素上有所不同(我们将在后面讨论更多涉及到的扰动)。但是在高层次上,讨论了 3 种不同的模型架构。

  1. 取回的人
  2. 发电机
  3. 检索和提炼

1.寻回犬:

给定对话历史(上下文)作为输入,检索系统通过对大量候选响应进行评分来选择下一个对话话语,并输出得分最高的一个。这与我们在本系列的第 2 部分中使用多编码器的多句子评分任务中看到的设置完全相同。开发了两种型号:参数分别为 256 米和 622 米。此处的培训目标是有效地对候选人的回答进行排序。这是通过最小化交叉熵损失来实现的,其逻辑如下:

其中每个“s”是上下文嵌入和候选响应之一的嵌入之间的分数。该分数可以是上下文和候选标签编码器表示之间的标准点积相似性分数(当投影到公共向量空间上时),或者更一般地是任何非线性函数。分数可以给定为:

使用多元编码器获得上下文和候选响应的编码器表示,多元编码器经历 3 种类型的注意机制:1)输入上下文的标记嵌入中的自我注意,2)通过在代码和先前自我注意的输出之间执行自我注意来学习“m”代码,3)候选嵌入和“m”全局学习特征之间的自我注意。(阅读第 2 部分以获得更深入的解释)。

2.发电机:

这里我们使用一个标准的 Seq2Seq Transformer(解码器)架构来生成响应,而不是从一组固定的候选项中检索它们。该模型的三个变体分别为:90M、2.7B 和 9.4B 参数。

最大似然估计:

这里的训练目标是最大似然估计,即最小化负对数似然。

似然性对整个序列概率分布进行建模。论文中给出的目标(参考文献。[2]):

参考文献中论文的截图。[2]

其中,可能性是在给定输入上下文“ x ”和直到时间步长“t”(y _<t)生成的记号的情况下,在时间步长“t”生成记号 y_t 的概率。金色的下一个话语' y '指的是在给定上下文的情况下,由人类提供的真实的下一个话语。

不太可能:

除了最大化在时间步“t”获得基本事实标记“y”的可能性之外,这里,我们还试图最小化在该时间步获得某些负候选标记的概率。这被称为非似然目标,它有助于减少重复出现的标记(或 n 元语法)。论文中给出的非可能性目标(参考文献。[2]):

参考文献论文截图。【2】

但是我们如何在每个时间步“t”得到否定候选集呢?或者,我们可以维护一个静态的否定候选列表(由模型生成的频繁 n 元文法),并在每个时间步使用相同的列表。或者更可接受的解决方案是,我们保持模型在每个时间步生成的 n 元语法分布。由此,每当 n-gram 计数大于从 gold 响应中观察到的相应 n-gram 计数(即,人类经常使用的 n-gram),我们就将该 n-gram 添加到在该时间步维护的阴性候选集合中。

解码:波束搜索:

在推理时,给定输入上下文,模型必须从可用的假设中选择最佳的下一个响应。这叫做“解码”。输出(下一个响应)被生成为词汇表中所有标记的概率分布。我们可以尝试获得到该时刻联合概率最大化的部分句子,而不是在每个时间步取最高概率令牌(这不过是“贪婪搜索”)。

  • 在“波束搜索”中,在每个时间步长“t”,在存储器中保存前 k 个部分形成的假设的列表——其联合概率是该时间步长的最大值。
  • 然后在时间 t,将词汇表中的每个单词附加到前 k 个假设中的每一个。
  • 计算新的联合概率。
  • 也可以通过到时间 t 为止形成的序列的长度来标准化分数
  • 基于联合概率得分对假设进行排序,然后从新的假设集中选择前 k 个。剩余的假设被丢弃。
  • 为了强制执行停止条件,词汇表中还包含了(句尾)标记。因此,当达到足够数量的令牌时,可以停止该过程。

然而,波束搜索试探法传统上导致生成比实际人类反应更短的反应,因此往往是枯燥和不那么吸引人的。因此,我们引入了一个最小长度约束——这样,直到我们有满足最小长度的部分假设,才会生成< EOS >令牌。这迫使模型生成长的响应。尽管更长的回答被认为更吸引人(在人工评估期间),但它们也更容易出错。所以最小响应长度是一个权衡。

波束搜索中可以做的另一个改进是 n-gram 波束阻塞。如果波束中的假设包含多于 1 次的 n-gram = >出现,则丢弃该假设。这样做是为了避免子序列或 n 元序列的重复。

3.检索和提炼:

检索器模型从有限的一组候选响应中获取下一个响应,并且仅使用输入上下文作为其知识。生成器模型对候选响应没有限制,但是为了生成下一个响应,除了上下文之外,仍然没有使用额外的知识。在第三种选择中,外部知识被结合到模型中,在生成之前产生=> 检索

对话检索:

检索&细化:对话检索系统

对于给定的输入上下文,检索系统(Poly-Encoder)从一组固定的候选响应中获得最可能的下一个响应。在上面的动画中,这被标记为“检索到的下一个响应”。在“寻回犬”模型中,我们停在这一点上。但是在这里,响应通过一个分隔符附加到输入上下文,并且这个组合序列作为输入馈送到生成器(解码器块)。解码器为给定的输入序列产生一个响应。这样做的目的是提高生成器可能产生的响应的质量。请记住,候选标签是人类生成的响应。即使对于给定的输入上下文,“检索到的下一个响应”不需要与“最佳响应”相同,我们也可以假设一个好的检索者会选择一个与最佳响应非常接近的候选项。并且人类的响应通常被认为比解码器生成的响应更有吸引力。这里的目的是让解码器以某种方式知道什么时候简单地直接使用“检索到的下一个响应”,而不努力自己生成任何东西;以及何时忽略检索到的响应并仅基于上下文生成一个响应。并且如果解码器能够学习这种关联,它将能够生成更像人类的响应。

训练目标:alpha-blending:解码器的理想学习将是当它好的时候简单地使用检索到的响应,当它不好的时候忽略它。但实际上,解码器通常会选择忽略检索到的下一个响应,并自行生成。这归因于上一段提到的事实:在给定输入上下文的情况下,对检索到的响应和黄金(人类)响应之间的关系缺乏理解。为了减轻这一点,我们做了“alpha-blending”,其中检索到的下一个响应被替换为当时的黄金响应“alpha”。这只不过是“老师强迫”的更一般的想法。

知识检索:

检索&提炼:知识检索系统

在这个变体中,使用了外部知识库。建立了一个信息检索系统来存储和检索维基百科转储。关于红外系统的工作原理有一点小插曲:

  • 对文档(在本例中是 Wikipedia 文章)进行解析,并构建一个形式为{term:出现该术语的所有文档的列表}的倒排索引。
  • 倒排索引可以通过“查询”进行搜索,输出是包含任何查询术语的文档列表。
  • 然后,我们通过查找查询和文档之间的相似性来对返回的文档进行排序,两者都表示在一个公共向量空间中,其坐标是查询/文档中的术语的 TF-IDF 分数。

回到我们的知识检索系统,输入的上下文被用作对 IR 系统的“查询”,以便检索最合适的候选知识(即与上下文相关的 Wiki 文章)。这些候选项和上下文被馈送到检索系统(Poly-Encoder ),以获得最佳候选项——这是最佳的外部知识,我们的对话下一个响应将基于此。然后,这个候选知识作为输入提供给生成器模型,该模型根据知识句子生成下一个响应。

评估方法:

自动评估:

检索模型:检索模型在我们在第 1 部分中谈到的众包干净数据集上进行微调,即 ConvAI2、ed、Wizard of Wikipedia 和 BST。报告的评估指标是对应数据集验证数据的 Hits@1/K(原则上类似于 Top@N 分类指标)。

参考文献论文截图。【2】

生成器模型:这里我们度量底层语言模型的困惑。困惑度量语言模型的不确定性。困惑度越低,模型在生成下一个标记(字符、子词或词)时就越有信心。从概念上讲,困惑表示模型在生成下一个令牌时试图选择的选项数量。从下图中,我们看到较大的模型以较少的步骤实现了更好的性能。

参考文献中的论文截图。[2]

人体评估:

这种评估提供了在不同版本的 Blender 之间进行比较以及在该领域的其他聊天机器人之间进行比较的杠杆作用——因为这些聊天日志在公共领域中可用于分析目的。许多不同版本的 Blender 是基于多种因素开发出来的,例如:

  • 在发电机模型中使用波束搜索时的最小波束长度
  • n-gram 波束阻塞是否完成
  • 较小模型与较大模型(就学习的参数数量而言)
  • 是否给定了角色上下文(在微调期间)
  • 使用可能性与可能性和不可能性的组合
  • 等等。

对所有类型的变体进行了人体评估,详细结果在论文中给出(参考文献。[2]),在那里你可以查看它们。

急性评估:

在这种方法中,人类评估者被给予一对人类和聊天机器人之间的完整对话。这些对话是由准备进行比较的两个模型/系统产生的。评估者的工作是比较两个对话,并回答下面的问题,如参考文献中所给出的。[2]:

  1. 参与度问题:“你更愿意和谁进行一次长谈?”
  2. 人性问题:“哪个说话者听起来更像人?”

自我聊天急性评估:

这是与上面相同类型的评估,除了被评估的对话是在两个模型之间,而不是人和模型之间。

下面给出了为人工评估者呈现的示例对话对:

参考文献论文截图。[2]

比较:

最后,我将留给您 Blender(及其变体)和 Meena 的人类评估分数;以及搅拌机和人类——如参考文献 1 所述。[2].

Blender 诉 Meena:

表示统计学显著性,p < 0.05,表示统计学显著性,p < 0.01。参考文献中的论文截图。[2]*

搅拌机诉人类:

**表示具有统计显著性。参考文献中的论文截图。[2]

Blender 的论文很长,包含了大量的信息,很容易被细节所困扰。写这一系列文章的目的,基本上是为了能够大声思考——识别并使个别概念和片段更容易理解,同时保持大局以及必要时放大细节的能力。

参考资料:

  1. 关于 Blender:https://www . kdnugges . com/2020/05/Facebook-open-sources-Blender-maximum-open-domain-chatbot . html
  2. 搅拌机机器人研究:【https://arxiv.org/abs/2004.13637
  3. 搅拌机机器人食谱:【https://parl.ai/projects/recipes/
  4. 多编码器变压器:https://arxiv.org/abs/1905.01969
  5. 关于 Meena:https://ai . Google blog . com/2020/01/forward-conversatile-agent-than-can . html

BLEU —双语评估替补演员

原文:https://towardsdatascience.com/bleu-bilingual-evaluation-understudy-2b4eab9bcfd1?source=collection_archive---------1-----------------------

理解 BLEU 的逐步方法,理解机器翻译(MT)有效性的度量标准

在这篇文章中你会学到什么?

  • 如何衡量一种语言翻译成另一种语言的效果?
  • 什么是 BLEU,我们如何计算机器翻译有效性的 BLEU 分数?
  • 理解 BLEU 的公式,什么是修正精度,计数剪辑和简洁惩罚(BP)
  • 使用示例逐步计算 BLEU
  • 使用 python nltk 库计算 BLEU 分数

你正在看一部你不懂的语言的非常受欢迎的电影,所以你用你知道的语言阅读字幕。

我们如何知道译文足以传达正确的意思?

我们查看翻译的充分性、流畅性和保真度以了解其有效性。

充分性是一个衡量标准,用来判断源语言和目标语言之间是否表达了所有的意思

保真度是指翻译准确呈现源文本含义的程度

流利度衡量句子在语法上的良好构成以及解释的难易程度。

翻译一个句子的另一个挑战是使用不同的词和改变词序。下面是几个例子。

不同的词语选择,但传达相同的意思

我喜欢这场音乐会

我喜欢这个节目

我喜欢这部音乐剧

传达相同信息的不同语序

由于交通堵塞,我上班迟到了

交通堵塞是我迟到的原因

交通堵塞耽误了我去办公室

有了这些复杂性,我们如何衡量机器翻译的有效性呢?

我们将使用基肖尔·帕皮尼尼描述的主要思想

机器翻译越接近专业的人工翻译越好:BLEU:Kishore papi neni 的机器翻译自动评测方法

我们将通过在参考人工翻译和机器生成的翻译之间寻找单词选择和词序的合理差异来衡量翻译的接近程度。

BLEU 上下文中的几个术语

参考译文是人类译文

候选翻译是机器翻译

为了衡量机器翻译的有效性,我们将使用一种称为 BLEU-双语评估替角的指标来评估机器翻译与人类参考翻译的接近程度。

让我们举一个例子,我们有以下参考译文。

  1. 我一向如此。
  2. 我总是这样。
  3. 我永远都是。

我们有两个不同的机器翻译候选人

  1. 我总是永远这样做。
  2. 我总是这样

候选人 2我总是做与这三个参考译文分享最多的单词和短语。我们通过比较每个候选翻译和参考翻译之间的 n-gram 匹配来得出这个结论。

我们所说的 n-gram 是什么意思?

n 元语法是在给定窗口内出现的单词序列,其中 n 表示窗口大小。

就拿这句话,“ 一旦停止学习,就开始死亡 ”来理解 n-grams。

一旦你停止学习,你就开始死亡。

BLEU 将候选翻译的 n 元语法与参考翻译的 n 元语法进行比较,以计算匹配的数量。这些匹配与它们发生的位置无关。

候选翻译和参考翻译之间的匹配数量越多,机器翻译就越好。

让我们从一个熟悉的指标开始:精度

就机器翻译而言,我们将精确度定义为“任何参考翻译中出现的候选翻译单词数”除以“候选翻译中的总单词数”

让我们举一个例子,计算候选翻译的精确度

  • 候选 1 的精度是 2/7 (28.5%)
  • 候选项 2 的精度为 1(100%)。

这些是不合理的高精度,我们知道这些不是好的翻译。

为了解决这个问题,我们将使用改进的 n-gram 精度。对于每个 n 元语法,它是分多个步骤计算的。

我们举个例子,了解一下修改后的精度分值是怎么计算的。我们有三个人工参考翻译和一个机器翻译候选人

我们首先使用以下步骤计算任何 n 元语法的计数剪辑

  • 步骤 1:统计候选 n 元语法在任何单个参考翻译中出现的最大次数;这被称为计数。
  • 第二步:对于每个参考句子,计算候选 n 元语法出现的次数。因为我们有三个参考转换,所以我们计算 Ref 1 计数、Ref2 计数和 Ref 3 计数。
  • 步骤 3:在任何引用计数中取 n 元文法出现的最大数量。也称为最大引用计数
  • 步骤 4:取最小的计数和最大的引用计数。也称为 Count clip ,因为它通过每个候选词的最大引用计数来削减其总计数

  • 第五步:将所有这些剪辑计数相加。

下面是一元和二元模型的剪辑计数

unigram 的剪辑计数

二元模型的剪辑计数

  • 第 6 步:最后,将修剪后的计数除以候选 n 元文法的总数(未修剪的)以获得修改后的精度分数。

Pₙ正在修改精确分数

  • 单字的修正精确度分数是 17/18
  • 双字母组合的修正精度分数为 10/17

汇总修改后的精度分数

语料库中所有候选句子的剪切 n 元语法计数的修正精度 Pₙ:总和除以候选 n 元语法的数量

这个修改后的精度分数有什么帮助?

修正的 n-gram precision score 抓住了翻译的两个方面:充分性和流畅性。

  • 使用与参考文献中相同的词的翻译倾向于满足充分性。
  • 候选翻译和参考翻译之间更长的 n-gram 匹配说明了流畅性

翻译太短或太长会怎样?

我们增加了简洁惩罚来处理太短的翻译。

当候选翻译长度与任何参考翻译长度相同时,简洁罚分(BP) 将为 1.0。最接近的参考句子长度是“最佳匹配长度”

通过简短惩罚,我们看到高分候选翻译将在长度、单词选择和词序方面匹配参考翻译。

BP 是指数衰减,计算如下

参考译文中的字数

候选翻译中的字数统计

:简洁罚函数和修正的 n-gram 精度长度都没有直接考虑源长度;相反,他们只考虑目标语言的参考翻译长度的范围

最后,我们计算 BLEU

BP-简洁惩罚

n:n 个字母的数字,我们通常用一个字母,两个字母,三个字母,四个字母

wₙ:权重为每个修正精度,默认情况下 n 为 4,wₙ为 1/4=0.25

Pₙ:修正精度

BLEU 度量的范围从 0 到 1。当机器翻译与参考翻译之一相同时,它将获得 1 分。正因如此,即使是人类翻译也不一定会得 1 分。

我希望你现在对 BLEU 有了很好的了解。

BLEU 度量用于

  • 机器翻译
  • 图像字幕
  • 文本摘要
  • 语音识别

如何用 python 计算 BLEU?

nltk 库提供了计算 BLRU 分数的实现

导入所需的库

import  nltk.translate.bleu_score as bleu

设置两个不同的候选翻译,我们将与两个参考翻译进行比较

reference_translation=['The cat is on the mat.'.split(),
                       'There is a cat on the mat.'.split()
                      ]
candidate_translation_1='the the the mat on the the.'.split()
candidate_translation_2='The cat is on the mat.'.split()

计算候选翻译 1 的 BLEU 分数

print("BLEU Score: ",bleu.sentence_bleu(reference_translation, candidate_translation_1))

计算候选翻译 2 的 BLEU 分数,其中候选翻译与参考翻译之一匹配

print("BLEU Score: ",bleu.sentence_bleu(reference_translation, candidate_translation_2))

我们也可以使用 nltk 库在 python 中创建自己的方法,用于计算 github 中可用的 BLEU

结论:

BLEU 衡量机器翻译与人类参考翻译的接近程度,考虑翻译长度、单词选择和词序。它用于机器翻译、抽象文本摘要、图像字幕和语音识别

参考资料:

BLEU:一种自动评估机器翻译的方法 Kishore Papineni,Salim Roukos,Todd Ward,和 Wei-朱婧

【https://www.statmt.org/book/slides/08-evaluation.pdf

http://www.nltk.org/_modules/nltk/translate/bleu_score.html

数据挖掘时控制错误发现

原文:https://towardsdatascience.com/blind-data-mining-is-bad-a609982a767f?source=collection_archive---------44-----------------------

至少 1 个假阳性的概率与有和无校正的假设检验的数量

多重比较问题背后的数学原理以及如何应对

2005 年,约翰·约安尼迪斯博士发表了一篇令人震惊的论文,题为为什么大多数发表的研究结果是假的,引发了对复制危机的认识。复制危机有多种原因,但与本文相关的是多重比较问题。数据分析师和科学家经常会遇到开放式的问题,这些问题需要进行数据探索,如“我们的客户在盈利能力方面的顶层和底层有什么不同?”本文解释了为什么分析师在探索数据集时不应该天真地测试多个假设。

多重比较问题背后的数学

多重比较问题可以用一句话来概括;如果你测试了足够多的假设,你会发现一些有统计学意义的结果,即使由于随机性,在潜在人群中没有真正的关系或差异。

“如果你折磨数据的时间足够长,它就会招供。”罗纳德·科斯

要理解为什么会这样,我们先用数学来定义这个问题。在测试多个独立假设时,我们担心在不应该的时候拒绝至少一个无效假设的可能性。这被称为家庭式错误率(FWER)。

这可能很难用大量的假设检验来解决,因此使用补充规则来重写等式会更容易,补充规则认为事件不发生的概率等于 1 减去事件发生的概率。这给出了:

那么我们如何计算 P(错误发现数= 0) 的概率呢?在单一假设检验中做出错误发现的概率是:

对于单个测试

使用补充规则,在单次测试中不出现错误发现的概率为:

对于单个测试

因为我们指定了我们的假设检验是相互独立的,所以我们可以用检验的数量乘以上面的数量。

现在我们有了一个 FWER 的公式:

让我们看看 FWER 是如何随着使用 Python 执行的测试数量的增加而增长的。

import numpy as np
import matplotlib.pyplot as pltalpha = 0.05
num_tests = np.arange(1, 100, 1, int)
fwer = 1 - (1 - alpha)**num_testsplt.plot(num_tests, fwer, linewidth=2)
plt.title(f'FWER vs. Number of Tests at alpha = {alpha}')
plt.xlabel('Number of Hypothesis Tests')
plt.ylabel('FWER')
plt.show()

如您所见,找到至少一个错误发现的概率增长很快。在 13 次假设测试中,至少有 1 次错误发现的概率为 50–50 %,在 27 次测试中有 75%的概率,在 90 次测试中有 99%的概率。

模拟演示

如果你不相信,这里有一个模拟演示。我写了一个函数,对从标准正态分布中随机抽取的样本重复执行均值差异测试。我们知道每个样本都来自具有相同均值的相同分布,因此低于临界值的 p 值是假阳性。因此,我们可以对至少有一个假阳性的模拟进行计数,然后除以模拟的数量,得到一个近似的 FWER。这个结果可以与上面的精确公式进行比较。

正如您在下面看到的,模拟的 FWER 接近每种情况下的确切 FWER。

from scipy.stats import norm
from scipy.stats import ttest_inddef exact_fwer(alpha, num_tests):
    return 1 - (1 - alpha)**num_testsdef simulated_fwer(alpha, num_tests, num_sims):
    count = 0
    for i in range(num_sims):
        false_disc = 0
        for j in range(0, num_tests):
            x = norm(loc=0, scale=1).rvs(size=100)
            y = norm(loc=0, scale=1).rvs(size=100)
            pvalue = ttest_ind(x, y)[1]
            if pvalue < alpha:
                false_disc += 1
                break
        if false_disc != 0:
            count += 1             
    return count / num_simsdef compare_exact_sim_fwer(alpha, num_tests, num_sims):
    exact = exact_fwer(alpha, num_tests)
    sim = simulated_fwer(alpha, num_tests, num_sims)
    return f'At alpha = {alpha} and {num_tests} Hypothesis Tests: \
             Exact FWER = {exact}, Simulated FWER ={sim}'print(compare_exact_sim_fwer(0.05, 13, 1000))
print(compare_exact_sim_fwer(0.05, 27, 1000))
print(compare_exact_sim_fwer(0.05, 90, 1000))

既然我们知道有问题,我们如何纠正它?

如何纠正多重比较偏差

有许多方法可以缓解多重比较问题,但有两种方法特别受欢迎:T2 的邦费罗尼校正法和 T4 的霍尔姆-邦费罗尼法。

邦费罗尼校正

要进行 Bonferroni 校正,只需将您的统计显著性临界值除以进行的测试次数。

Bonferroni 校正 FWER 与下面的未调整 FWER 一起绘制。

alpha = 0.05
num_tests = np.arange(1, 100, 1, int)
fwer = 1 - (1 - alpha)**num_tests
fwer_bonferroni = 1 - (1 - alpha / num_tests)**num_testsplt.plot(num_tests, fwer, linewidth=2, color='b', label='No Correction')
plt.plot(num_tests, fwer_bonferroni, linewidth=2, color='r', label='with Bonferroni Correction')
plt.legend()
plt.title(f'FWER vs. Number of Tests at alpha = {alpha}'0)
plt.xlabel('Number of Hypothesis Tests')
plt.ylabel('FWER')
plt.show();

这种校正的一个好处是易于实现。一个缺点是,一旦测试数量变大,或者如果测试统计数据是相关的,它可能会过于保守。通过保持低的假阳性率,我们增加了假阴性的概率。如果我们非常关心这种权衡,我们可以考虑 Holm-Bonferroni 方法。

霍尔姆-邦费罗尼方法

Holm-Bonferroni 方法比 Bonferroni 校正方法保守一些,但需要做更多的工作。

首先,从最小到最大排列假设检验的 p 值,然后应用此公式按最小 p 值的顺序获得每个假设检验的 alpha 值:

您浏览排序后的列表,将 p 值与其相关的 Holm-Bonferroni 校正α值进行比较。在第一次拒绝零假设失败时,你忽略了当时和之后的所有测试结果。

下图比较了 Holm-Bonferroni 调整和 Bonferroni 校正。如您所见,它不如 Bonferroni 校正保守,但与什么都不做相比,它确实大幅降低了 FWER。

def holm_bonf_fwer(alpha, num_tests):
    ranks = [i + 1 for i in range(num_tests)]
    adj_alphas = [alpha / (num_tests - rank + 1) for rank in ranks]

    p_no_false_disc = 1
    for adj_alpha in adj_alphas: 
        p_no_false_disc = p_no_false_disc * (1 - adj_alpha) 

    return 1 - p_no_false_discalpha = 0.05
num_tests = np.arange(1, 100, 1, int)
fwer = 1 - (1 - alpha)**num_tests
fwer_bonferroni = 1 - (1 - alpha / num_tests)**num_tests
fwer_holm_bonferroni = [holm_bonf_fwer(alpha, i) for i in num_tests]plt.plot(num_tests, fwer, linewidth=2, color='b', label='No Correction')
plt.plot(num_tests, fwer_bonferroni, linewidth=2, color='r', label='with Bonferroni Correction')
plt.plot(num_tests, fwer_holm_bonferroni, linewidth=2, color='g', label='with Holm-Bonferroni Correction')
plt.legend()
plt.title(f'FWER vs. Number of Tests at alpha = {alpha}')
plt.xlabel('Number of Hypothesis Tests')
plt.ylabel('FWER')
plt.show();

结论

如果您在阅读本文之前没有意识到多重比较问题,那么您现在应该知道为什么不能盲目地对一个数据集进行假设检验,看看哪些检验有意义。您还有两个工具来缓解这个问题。下次你在探索一个数据集时,别忘了使用它们。

注意:如果你对代码的理解受益于评论,请留言,我会添加它们。

使用眼睛视网膜图像上的深度学习进行失明检测(糖尿病视网膜病变)

原文:https://towardsdatascience.com/blindness-detection-diabetic-retinopathy-using-deep-learning-on-eye-retina-images-baf20fcf409e?source=collection_archive---------4-----------------------

使用卷积神经网络(使用 Python)自动化该过程,以在为时已晚之前加速患者的失明检测

目录

  1. 使用深度学习来检测失明
  2. 评估指标(二次加权 kappa)
  3. 图像处理和分析
  4. 使用多任务学习实现 arXiv.org 研究论文(前 1%解决方案)
  5. 其他迁移学习模式
  6. 未来的工作
  7. 链接到 github 代码和 linkedin 个人资料
  8. 使用的参考文献

图片来源—http://images 2 . fan pop . com/image/photos/10300000/Cas-Blindness-casti El-10370846-640-352 . jpg

1.使用深度学习来检测失明

本案例研究基于 APTOS 2019 失明检测基于此处的 kaggle 挑战赛——https://www . ka ggle . com/c/APTOS 2019-失明检测/概述。

数百万人患有 糖尿病视网膜病变 ,这是工作年龄成人失明的主要原因。印度 Aravind 眼科医院希望在难以进行医学筛查的农村地区发现并预防这种疾病。目前,技术人员前往这些农村地区采集图像,然后依靠训练有素的医生来检查图像并提供诊断。

这里的目标是通过技术扩大他们的努力;以获得自动筛查疾病图像并提供病情严重程度的信息的能力。我们将通过建立一个 卷积神经网络 模型来实现这一点,该模型可以自动查看患者的眼睛图像,并估计患者失明的严重程度。这种自动化过程可以减少大量时间,从而大规模筛选治疗糖尿病性视网膜病变的过程。

我们得到了 3200 张眼睛图像及其对应的严重程度等级,严重程度等级为【0,1,2,3,4】之一。该数据将用于训练模型,并对测试数据进行预测。

失明严重程度量表(5 级)

数据集中的样本眼睛图像如下—

对应于每个失明等级严重性(0-4)的眼睛图像

2.评估指标(二次加权 kappa)

二次加权 kappa 衡量两个评级之间的一致性。该指标通常从 0(评分者之间的随机一致)到 1(评分者之间的完全一致)不等。如果评定者之间的一致程度偶然低于预期,该指标可能会低于 0。在由人类评价人分配的分数和预测分数之间计算二次加权 kappa。

科恩卡帕的直觉

要理解这个指标,我们需要理解科恩的 kappa ( 维基百科— 链接)的概念。该指标说明了除了我们从混淆矩阵中观察到的一致性之外,偶然出现的一致性。我们可以用一个简单的例子来理解这一点—

假设我们想从下面的协议表中计算科恩的 kappa,这基本上是一个混淆矩阵。从下表中我们可以看出,在总共 50 项观察中,“A”和“B”评定者同意(20 项是+ 15 项否)= 35 项观察。所以,观察到的一致是P(o)= 35/50 =0.7

来源——维基百科

我们还需要找到多大比例的评级是由于随机的机会,而不是由于' A '和' B '之间的实际协议。我们可以看到,' A '说是 25/50 = 0.5 次,' B '说是 30/50 = 0.6 次。所以两个人随机同时说‘是’的概率是 0.50.6 = 0.3 。同样,他们两个随机同时说‘不’的概率是 0.50.4 = 0.2 。这样,随机一致的概率就是 0.3 + 0.2 = 0.5 。让我们称之为 P(e)。

所以,Cohens kappa 会是 0.4 (公式如下)。

来源——维基百科,科恩斯卡帕公式

我们得到的值是 0.4,我们可以用下表来解释。你可以在本博客中阅读更多关于这一指标的解读——https://towardsdatascience . com/inter-rater-agreement-kappas-69 CD 8 b 91 ff 75

来源—https://towards data science . com/inter-rater-agreement-kappas-69 CD 8 b 91 ff 75

0.4 将意味着我们有一个公平/适度的协议。

序数类中二次权的直觉——二次加权 kappa

当涉及到多类时,我们可以扩展相同的概念,并在这里引入权重的概念。引入权重背后的直觉是,它们是序数变量,,这意味着类别‘1’和‘2’之间的一致优于类别‘1’和‘3’,因为它们在序数尺度上更接近。在我们的失明严重度案例中,输出是序数(失明严重度,0 代表无失明,4 代表最高)。为此,引入了二次标度的权重。序数类越接近,它们的权重越高。下面是很好解释这个概念的博文链接—https://medium . com/x8-the-ai-community/kappa-coefficient-for-dummies-84d 98 b 6 f 13 ee

来源—https://medium . com/x8-the-ai-community/kappa-coefficient-for-dummies-84d 98 b 6 f 13 ee

正如我们所见,R1 和 R4 的权重为 0.44(因为它们比 R1 和 R2 的权重 0.94 大 3 个等级,因为它们更接近)。在计算观察概率和随机概率时,这些权重乘以相应的概率。

3.图像处理和分析

输出变量的类别分布

阶级不平衡——分布

正如我们所看到的,在训练数据集中存在类别不平衡,大多数情况下值为“0 ”,在“1”和“3”类别中最少。

视觉化眼睛图像

用于生成可视化效果的代码段

这些基本上是使用 眼底照相 拍摄的眼睛视网膜图像。正如我们所见,图像包含伪像,其中一些是失焦,曝光不足,或曝光过度等。此外,一些图像具有低亮度和低闪电条件,因此难以评估图像之间的差异。

样本 15 幅眼睛图像

下图是一只眼睛的视网膜图像样本,该眼睛可能患有糖尿病视网膜病变。源链接— kaggle 内核链接 T21原文出处—https://www.eyeops.com/

img 来源—https://www . ka ggle . com/ratthachat/aptos-眼部预处理-糖尿病视网膜病变,【https://www.eyeops.com/】T2

如我们所见,我们正试图找出那些出血/渗出物等。在有博士学位的高年级学生中。

图像处理

为了对图像进行调整,制作更清晰的图像,使模型能够更有效地学习特征,我们将使用 python 中的 OpenCV 库( cv2 )进行一些图像处理技术。

我们可以应用 高斯模糊 来突出图像中的特征。在高斯模糊操作中,图像与高斯滤波器卷积,高斯滤波器是去除高频分量的低通滤波器。

代码片段—高斯模糊

高斯模糊之前/之后

这个写得很棒的内核( 链接 )介绍了从灰度图像中进行圆形裁剪的思想。在下面的代码部分实现相同的功能:-

代码片段—圆形裁剪

之前/之后(模糊+裁剪)

正如我们所看到的,我们现在能够更清楚地看到图像中的独特模式。以下是对 15 个图像样本进行的图像处理。

图像处理后

多重处理和调整图像大小,以保存在目录中

应用上述操作后,我们需要将新图像保存在文件夹中,以便以后使用。原始图像每个大约 3 MB,整个图像文件夹占用 20 GB 空间。我们可以通过调整图像大小来减少这种情况。使用多核线程/多处理,我们可以在一分钟内完成这项任务。我们可以使用具有 6 个内核的线程池(因为我有 8 个内核的 CPU)来实现这一点,并使用(512x512)的图像大小来实现这一点( IMG 大小)。

代码片段—使用线程池的多重处理

TSNE 可视化

为了理解这些图像在各自的类别(失明严重程度)中是否是可分离的,我们可以首先使用 TSNE 在二维空间中对其进行可视化。我们可以首先将 RGB 等级的图像转换为灰度等级的图像,然后将这些图像展平以生成一个矢量表示,该矢量表示可以用作该图像的特征表示。

RGB(256 x256 x3)——>灰度(256 x256)——>展平(65536)

代码片段— TSNE

困惑是需要调整以获得良好结果的超参数。迭代之后,我们可以使用 TSNE 图来表示困惑= 40。

TSNE 情节,困惑= 40

从上面的图中我们可以看出,类“0”与其他类有些分离,而其他类之间的区别仍然很模糊。

图像增强

这是最常用的程序之一,通过从数据集创建额外的图像来生成数据的鲁棒性,以使其通过旋转翻转、裁剪、填充等对新数据进行良好的概括。使用 keras ImageDataGenerator

上述代码生成了应用增强后获得的样本图像—

图像放大(示例)

4.使用多任务学习实现 arXiv.org 研究论文(前 1%解决方案)

在 arXiv.org 上发现的一篇研究论文——研究论文链接 在 2943 个中获得第 54 位(前 1%)涉及多任务学习的详细方法来解决这个问题陈述。下面是使用 Python 复制研究论文代码的尝试。在 github 上没有找到这篇研究论文的代码参考。我已经在一篇研究论文(summary doc)中总结了研究论文。pdf 文件— github 链接 。总结以下研究论文中的指针和代码实现—

使用的数据集

实际的研究论文使用了来自其他来源的多个数据集,比如—

  1. 来自糖尿病视网膜病变的 35,216 张图像,2015 年挑战—https://www . ka ggle . com/c/Diabetic-Retinopathy-detection/overview/timeline
  2. 印度糖尿病视网膜病变图像数据集(IDRiD) (Sahasrabuddhe 和 Meriaudeau,2018 年)=使用 413 张图像
  3. 梅西多数据集(Google Brain,2018)数据集
  4. 完整的数据集由 18590 张眼底照片组成,由 Kaggle 竞赛的组织者分为 3662 张训练,1928 张验证和 13000 张测试图像

然而,由于不容易获得所有数据集,我们只能使用现有的 APTOS 2019 数据集来完成这项任务。

图像预处理和增强

多种图像预处理技术,如图像大小调整、裁剪,被用来从眼睛图像中提取出与众不同的特征(如以上章节中所讨论的)。

使用的图像增强包括:光学失真、网格失真、分段仿射变换、水平翻转、垂直翻转、随机旋转、随机移动、随机缩放、RGB 值移动、随机亮度和对比度、加性高斯噪声、模糊、锐化、浮雕、随机伽玛和剪切等。

然而,我们可以使用类似于上面的替代图像增强(使用参考— 链接 )。

使用的模型架构

正如我们在下面看到的,研究论文使用了多任务学习模型(它并行进行回归、分类、有序回归的训练)。这样,它可以使用单个模型,并且由于第一层无论如何都会学习相似的特征,所以实现该架构以减少训练时间(而不是训练 3 个单独的模型)。对于编码器部分,我们可以使用任何现有的 CNN 架构— ResNet50,EfficientNetB4,EfficientNetB5 ( 和 ensemble 这些)。

来源—https://arxiv.org/pdf/2003.02261.pdf

上述架构的代码实现如下(用 keras 表示)—

创建多输出-自定义图像数据生成器

我们需要创建一个自定义的 ImageDataGenerator 函数,因为我们有 3 个输出(引用— 链接 )。请注意,此函数产生 3 个输出(回归、分类、有序回归)代码如下—

请注意,对于每个类(0,1,2,3,4),顺序回归编码按如下方式进行。sklearn 中的multilabel binary izer实现了这个任务,如上面的代码要点所示。

来源—https://www . ka ggle . com/c/aptos 2019-失明-检测/讨论/98239

第一阶段(预培训)

这包括使所有层可训练,并使用现有的 Imagenet 权重作为 ResNet50 编码器的权重初始化器。模型仅被训练到 3 个输出头。使用以下损失函数编译模型(使用 SGD 优化器、余弦衰减调度程序的 20 个时期)—

model.compile(
optimizer = optimizers.SGD(lr=LEARNING_RATE),loss={'regression_output': 'mean_absolute_error',
'classification_output':'categorical_crossentropy',
'ordinal_regression_output' : 'binary_crossentropy'},metrics = ['accuracy'])

预训练阶段的历元(vs)损失图

第二阶段(主要训练)

在这个阶段,事情发生了变化。

  1. 首先,损失函数从交叉熵变为聚焦损失。你可以在这里阅读更多关于焦损的内容——https://medium . com/adventures-with-deep-learning/Focal-loss-demystified-c 529277052 de。简而言之,焦点丢失在处理等级不平衡方面做得更好,正如我们任务中的情况。

来源—https://medium . com/adventures-with-deep-learning/focal-loss-demystified-c 529277052 de

焦点损失参考代码—https://github.com/umbertogriffo/focal-loss-keras

model.compile(
optimizer = optimizers.Adam(lr=LEARNING_RATE),loss={
'regression_output': mean_squared_error, 
'classification_output': categorical_focal_loss(alpha=.25,gamma=2),
'ordinal_regression_output' : binary_focal_loss(alpha=.25,gamma=2)
},metrics = ['accuracy'])

2.第二,第二阶段的训练分两个阶段进行。第一子阶段包括冻结模型网络中的所有编码器层。这样做是为了预热权重(使用 Imagenet 权重初始化对小数据集进行迁移学习)。第二个子阶段包括解冻和训练所有层。

# SUB STAGE 1 (2nd Stage) - Freeze Encoder layers**for** layer **in** model.layers:
    layer.trainable = **False**
**for** i **in** range(-14,0):
  model.layers[i].trainable = **True**# SUB STAGE 2(2nd Stage) - Unfreeze All layers**for** layer **in** model.layers:
    layer.trainable = **True**

图表如下所示—

主要训练阶段的历元(vs)损失图

第三阶段(岗位培训)

这包括从 3 个头部(分类、回归、有序回归)获得输出,并将其传递给单个密集神经元(线性激活)以最小化均方误差(50 个时期)

train_preds = model.predict_generator(
complete_generator, steps=STEP_SIZE_COMPLETE,verbose = 1
)train_output_regression = np.array(train_preds[0]).reshape(-1,1)
train_output_classification = np.array(np.argmax(train_preds[1],axis = -1)).reshape(-1,1)
train_output_ordinal_regression = np.array(np.sum(train_preds[2],axis = -1)).reshape(-1,1)X_train = np.hstack((
train_output_regression,
train_output_classification,
train_output_ordinal_regression))model_post = Sequential()
model_post.add(Dense(1, activation='linear', input_shape=(3,)))model_post.compile(
optimizer=optimizers.SGD(lr=LEARNING_RATE), loss='mean_squared_error',
metrics=['mean_squared_error'])

培训后—纪元(vs)损失

测试数据的模型评估

因为我们有回归输出,所以我们可以进行最近整数舍入来得到最终的类标签。

我们在测试数据上获得的最终二次加权 kappa 分数是 0.704 (这表明模型预测和人类评分者之间的基本一致)。

在测试数据上获得的归一化混淆矩阵(matplotlib 的代码已从— 链接 中引用)

测试数据—标准化混淆矩阵

5.其他迁移学习模式

在处理小数据集(与 ImageNet 数据集没有相似性)时,常用的迁移学习方法是首先使用现有的 ImageNet 权重作为初始值(冻结前几层),然后重新训练模型。

我们可以使用类似的实现。一个简单的 ResNet50 架构在这样使用的时候会给出很好的结果(参考— 链接 )

我们可以训练上述模型 2-5 个时期(只有最后 5 层是可训练的,它们基本上是在 ResNet50 之后的层)。

然后,我们可以使所有层可训练,并训练整个模型。

**for** layer **in** model.layers:
    layer.trainable = **True**

ResNet50(迁移学习)—纪元(vs)丢失

正如我们所看到的,仅在 20 个时期内,我们就获得了良好的准确度分数——在验证数据集上接近 92%。

该模型在测试数据上给出了 0.83 的二次加权 kappa(这是一个很好的一致性分数)。

标准化混淆矩阵(测试数据)

同样,我们可以用本页提到的其他keras . applications——link做类似的实现。以下是在其中一些模型上实现时获得的结果(仅模型架构发生变化,其他参数保持不变)。

模型性能—摘要

6.未来的工作

优化器实验

正如我们所看到的,在主要的培训阶段,培训损失并没有减少。我们可以解决这个问题的方法之一是将优化器从 Adam 改为修正 Adam 优化器。(更多关于 RAdam 的内容在这里—https://www . pyimagesearch . com/2019/10/07/is-rectified-Adam-actually-better-Adam/)。此外,我们可以用 SGD (Momentum) 优化器和权重衰减方法,更多的学习率调度器来检查模型性能的改进。

规则化方法实验

此外,我们还可以在模型上使用更多的正则化来帮助更好地训练模型——一些技术可能涉及标签平滑(向目标标签添加噪声)——这将允许模型更好地概括并防止过度拟合。此外,我们可以尝试 L2 正则化来提高模型的泛化能力。

集合实验和 K 倍交叉验证

该研究论文还提到了跨各种架构使用集成技术,如 EfficientNetB4、5EfficientNetB5、SE-ResNeXt50 等,并使用分层交叉验证(5 折)来提高模型性能和泛化能力。

7.链接到 Github 代码和 linkedin 个人资料

所有代码都在我的 Github 库— 链接 里。如果你想讨论这方面的进一步实验,你可以在我的 Linkedin 个人资料上联系我— 链接 。你也可以通过debayanmitra1993@gmail.com联系我。

6.使用的参考文献

[## dimitrioliveira/aptos 2019 盲检

这个知识库的目标是使用比赛数据建立机器学习模型来处理图像数据…

github.com](https://github.com/dimitreOliveira/APTOS2019BlindnessDetection) [## APTOS:糖尿病视网膜病变中的眼睛预处理

使用 Kaggle 笔记本探索和运行机器学习代码|使用来自多个数据源的数据

www.kaggle.com](https://www.kaggle.com/ratthachat/aptos-eye-preprocessing-in-diabetic-retinopathy) [## 介绍 APTOS 糖尿病视网膜病变(EDA & Starter)

使用 Kaggle 笔记本探索和运行机器学习代码|使用来自多个数据源的数据

www.kaggle.com](https://www.kaggle.com/tanlikesmath/intro-aptos-diabetic-retinopathy-eda-starter)

研究论文—https://arxiv.org/pdf/2003.02261.pdf

BLiTZ——py torch 的贝叶斯神经网络库

原文:https://towardsdatascience.com/blitz-a-bayesian-neural-network-library-for-pytorch-82f9998916c7?source=collection_archive---------9-----------------------

blitz——Torch Zoo 中的贝叶斯层是一个简单且可扩展的库,用于在 PyTorch 上创建贝叶斯神经网络层。

贝叶斯回归图解。来源:https://ericmjl . github . io/Bayesian-deep-learning-demystified/images/linreg-Bayesian . png(2020–03–30 访问)

这是一篇关于使用库进行深度贝叶斯学习的文章。如果你是这个主题的新手,你可能想在 medium 上寻找关于它的许多帖子中的一个,或者只是我们 lib repo 的 Bayesian DL 的文档部分。

由于越来越需要收集神经网络预测的不确定性,使用贝叶斯神经网络层成为最直观的方法之一-这可以通过贝叶斯网络作为深度学习研究领域的趋势得到证实。

事实是,尽管 PyTorch 有成为主要深度学习框架的趋势(至少对于研究而言),但没有一个库让用户像使用nn.Linearnn.Conv2d那样轻松地引入贝叶斯神经网络层。

从逻辑上来说,这对于任何想要灵活地使用贝叶斯方法进行数据建模的人来说都是一个瓶颈,因为用户必须开发贝叶斯层的整个部分以供使用,而不是专注于其模型的架构。

BLiTZ 就是为了解决这一瓶颈而产生的。通过与 PyTorch(包括与nn.Sequential模块)完全集成,并易于扩展为贝叶斯深度学习库,BLiTZ 允许用户在其神经网络上引入不确定性,只需调整其超参数。

在本帖中,我们将讨论如何使用 BLiTZ 层和采样工具创建、训练和推断不确定性引入的神经网络。

贝叶斯深度学习层

正如我们所知,贝叶斯深度学习的主要思想是,在每个前馈操作中,贝叶斯层从正态分布中采样其权重,而不是具有确定性的权重。

因此,该层的可训练参数是确定该分布的平均值和方差的参数。

从数学上讲,操作将从:

确定性“香草”神经网络前馈操作。

收件人:

贝叶斯神经网络层的前馈操作。

在 Torch 上实现ρ和μ为可训练参数的层可能很难,除此之外,创建超参数可调层可能更难。BLiTZ 有一个内置的BayesianLinear层,可以很容易地引入到模型中:

它像一个普通的 Torch nn.Module网络一样工作,但是它的BayesianLinear模块利用之前解释的其权重的不确定性来执行训练和推理。

损失计算

正如在其原始论文中提出的,贝叶斯神经网络成本函数是“复杂性成本”与“数据拟合成本”的组合。在所有的代数争论之后,对于每个前馈操作,我们有:

贝叶斯神经网络的代价函数。

相对于简单得多的预定义 pdf 函数,复杂性成本(P(W))由(网络上每个贝叶斯层的)采样权重的概率密度函数之和组成。通过这样做,我们确保了在优化的同时,我们的模型相对于预测的方差将会减少。

为此,BLiTZ 为我们带来了引入一些方法的variational_estimator装饰器,比如将nn_kl_divergence方法引入我们的nn.Module。给定数据点、其标签和标准,我们可以通过以下方式获得预测的损失:

简单的模型优化

在优化和继续之前,贝叶斯神经网络通常通过对同一批次的损失进行多次采样来优化,这是为了补偿权重的随机性,并避免因受离群值影响的损失而优化它们。

BLiTZ 的variational_estimator装饰器也用sample_elbo方法为神经网络提供动力。给定inputsoutputscriterionsample_nbr,它估计在计算批次sample_nbr次损失时进行迭代过程,并收集其平均值,返回复杂度损失与拟合值之和。

优化贝叶斯神经网络模型非常容易:

看一个例子:

我们现在通过这个例子,使用 BLiTZ 创建一个贝叶斯神经网络来估计波士顿房屋 sklearn 内置数据集的房价的置信区间。如果你想寻找其他的例子,库上有更多的

必要的进口

除了已知的模块,我们将从 BLiTZ 带来variational_estimator装饰器,它帮助我们处理模块上的贝叶斯层,保持它与 Torch 的其余部分完全集成,当然,还有BayesianLinear,它是我们的层,具有权重不确定性。

加载和缩放数据

这并不是什么新鲜事,我们正在导入和标准化数据来帮助训练。

创建我们的回归类

我们可以通过继承nn.Module来创建我们的类,就像我们对任何火炬网络所做的那样。我们的装饰者介绍了处理贝叶斯特征的方法,计算贝叶斯层的复杂性成本,并进行许多前馈(对每一个采样不同的权重)来采样我们的损失。

定义置信区间评估函数

该函数确实为我们试图对标签值进行采样的批次上的每个预测创建了一个置信区间。然后,我们可以通过寻找有多少预测分布包含数据点的正确标签来衡量我们预测的准确性。

创建回归变量并加载数据

注意这里我们创建了我们的BayesianRegressor,就像我们创建其他神经网络一样。

我们的主要培训和评估循环

我们做了一个训练循环,唯一不同于普通火炬训练的是通过sample_elbo方法对其损耗进行采样。所有其他的事情都可以正常完成,因为我们使用 BLiTZ 的目的是让你轻松地用不同的贝叶斯神经网络迭代数据。

这是我们非常简单的训练循环:

结论

BLiTZ 是一个有用的 lib,可以在深度学习实验中使用贝叶斯层进行迭代,并且对通常的代码进行很小的更改。它的层和装饰器与神经网络的 Torch 模块高度集成,使得创建定制网络和提取它们的复杂性成本没有困难。

当然,这是我们回购的链接:https://github.com/piEsposito/blitz-bayesian-deep-learning

参考

[## piEsposito/blitz-贝叶斯深度学习

BLiTZ 是一个简单且可扩展的库,用于创建贝叶斯神经网络层(基于 Weight…

github.com](https://github.com/piEsposito/blitz-bayesian-deep-learning) [## 神经网络中的权重不确定性

我们介绍了一个新的,有效的,原则性和反向传播兼容的算法学习概率…

arxiv.org](https://arxiv.org/abs/1505.05424)

区块链和以太坊终于有了一些黑仔应用

原文:https://towardsdatascience.com/blockchain-and-ethereum-are-finally-getting-some-killer-apps-6666cf9f0f56?source=collection_archive---------15-----------------------

流动资金、在线投票、无损失彩票等等

照片:阿纳斯塔西娅·杜尔吉尔

作为一项新兴技术,区块链已经 被 淘汰的频率大致相当于谷歌眼镜或 3D 电视。忽视区块链是一种理智的时尚,认为它是被过度炒作的电子表格,唯一值得注意的是支撑比特币的可疑成就。一位评论家大胆批评这是“人类历史上最没用的发明”。

对于像我这样充满希望的技术人员来说,这些声明因为拥有真理之环而更加令人沮丧。尽管智能合同和区块链平台为研发筹集了数十亿美元的资金(T21 ),但几乎没有区块链的实际应用。比特币的价值已经飙升,但缺乏持续的技术发展、大规模采用或相对于美元等现有货币的任何真正优势。

然而,在过去的一年(尤其是过去的三个月),有用的区块链应用程序终于出现了激增,这些应用程序实际上可能代表了该技术的杀手级应用程序。大量的开发人员已经聚集在一个平台上,特别是以太坊,由此产生的新应用程序的爆炸看到了区块链实现的一些希望。

实时流动资金

Sablier 团队开发了一个协议,让人们可以像在 Spotify 上播放播放列表一样轻松地实时传输资金。不要每四周领一次工资,想象一下持续领工资——每小时,甚至每秒。Sablier 应用程序在透明的界面中显示正在进行的交易,因此您可以准确地看到支付了多少钱,以及支付的速度有多快。通过完全绕过银行系统,交易费用几乎不存在。

Sablier 应用程序,在本例中为 DAI 流(数字化美元)

实时工资支付是一种诱人的可能性——每月工资支付的效率低得可怕,让大量工人靠一张张支票生活,有时甚至无法满足日常开支。流动支付代表了一种解决方案,尤其是对低收入工人来说,是一种可能改变生活的服务。我们目前支付薪水和工资的方式可能会被扔进历史垃圾堆——谁会真正喜欢每月领取一次总付款,而不是每天领一次工资?

有了一个像流动资金一样完全通用的协议,潜在的应用范围远远超出了工资。遗产继承传统上被认为是死后一次性支付的一大笔钱——但是想象一下这样一个系统,一个去世的家庭成员在很长一段时间内将他们的遗产转移给他们的家庭,以避免税收和一次性支付大笔款项的冲动。实时流动资金也可能完全扰乱按小时计费的服务:法律费用、车辆租赁、停车场等等——只要你在使用服务,就要付费,不要多花一秒钟。

无损失彩票

仅在美国,花在彩票上的钱就有 710 亿英镑,这是一个荒谬的数字,尤其是任何一个参与者真的中奖的可能性极小,这让这个数字变得更加疯狂。当你停下来想一想,这是一个令人困惑的财务自残行为,只有获胜的乐趣和兴奋才能证明这是正当的——我们人类很容易受到基于游戏的反馈循环的影响

进入 PoolTogether ,这是一款将自己打造成“无损失储蓄游戏”的新应用。本质上,它是一种数字彩票,你用存款“购买”彩票——每周给你一次中头奖的机会——但你永远不会失去存款。你可以随时撤回。看起来像是黑魔法的东西是由区块链实现的——协议将所有存款“汇集”在一个生息的智能合同中,产生的利息作为头奖奖励给每周的持票人。

毫无疑问,虽然 PoolTogether 还处于早期阶段,用户相对较少,累积奖金也相对较少,但这个概念是基于金钱的(可以这么说)。世界上最大的赔钱游戏(彩票)可能会被一个激励人们储蓄的系统所取代,同时保留使彩票如此令人上瘾的类似游戏的属性。

安全在线投票

如果你关注美国政治(因为你的罪过),或者即使你不关注,你可能已经听说过民主党总统初选投票是一场灾难——爱荷华州党团会议仍然在确认确切的总数,尽管投票发生在三周前。总的来说,投票过程中有一长串的问题,从长长的队伍和等待时间到坏掉的机器,以及投票地点的党派安排。十年前的解决方案——在线投票——一直被认为太不安全,容易被黑客攻击或操纵。

由于区块链系统在安全性和效率方面的优势,安全的在线投票系统还是有希望的。一个名为 Vocdoni 的团队正在构建一个具有“普遍可验证”投票的在线投票协议——使用一些复杂的加密技术来构建一个系统,选民可以使用区块链协议投票,该协议会不断检查每一张选票的完整性,以保证其完整性(并阻止破坏系统的企图)。Vocdoni 还在构建协议时考虑到了智能手机的接入,目的是让民主变得更加简单和容易实现。

投资你最喜爱的体育明星

如果为一个特定的运动队或运动员加油的情感投资还不够,智能合同现在让球迷用自己的钱投资。布鲁克林篮网队的斯宾塞·丁翁迪在以太坊上将其 3400 万美元的三年合同进行了“T2 化”——这实质上意味着球迷可以购买他合同中的一小部分股份,将其转化为可交易的金融资产。如果你认为丁威迪将会有一个伟大的赛季,你不需要只是把他加入你的梦幻团队——你可以真正投资于他的表现,如果他达到了合同中基于表现的奖金,就可以获得收益。

一种行走、呼吸、可交易的金融资产。照片:杰罗姆米隆

尽管体育明星投资的全新市场还处于早期阶段(当然还会有更多的障碍——NBA 对丁威迪的创新并不太看好),但这是朝着更具流动性的金融体系迈出的相当令人兴奋的一步。区块链和智能合约允许新类型的投资和新颖的金融工具,看到智能合约的沙箱为体育部门产生真正的游戏规则改变者令人兴奋。

对于人类历史上最没用的发明来说还不算太寒酸。如果你对这些关于这个新兴平台的文章感兴趣,你可能会喜欢我的新出版物 Technocracy 。我将定期撰写关于技术正在改变社会的文章,比如我最近的一篇关于冠状病毒如何让大规模监控成为我们的新常态的文章。

区块链技术确保数据安全性和不变性

原文:https://towardsdatascience.com/blockchain-technology-ensuring-data-security-immutability-7150d309352c?source=collection_archive---------11-----------------------

图片资源:https://unsplash.com/@launchpresso

目前,区块链是最安全的数据保护技术之一。数字技术的快速发展也给数据安全带来了新的挑战。组织需要通过实施强身份认证和加密密钥保险机制来保护其数据。

区块链技术足以应对如何保护数据和防止恶意网络攻击的挑战。报告称,到 2024 年,全球区块链技术市场可能会达到 200 亿美元左右。区块链具有革命性,被用于医疗保健、金融、体育等许多行业。

与传统方法不同,这项技术主要激励许多区块链开发公司重新构建和重新表述安全问题。区块链提供了在数据中引入信任因素的真正意义。

区块链技术挑战漏洞

由分布式分类帐系统提供的高级安全性为建立安全的数据网络提供了好处。在消费产品和服务中提供服务的企业采用区块链技术来保护记录消费者的数据。

由于区块链是本世纪的主要技术突破之一,它允许在不需要任何第三方信任的情况下保持竞争力。

这项技术正在为消费者带来颠覆商业服务和解决方案的新机遇。在未来,这项技术将随着各个领域中不断发展的全球服务而成为领跑者。

提供加密和验证

区块链技术足够精通,可以管理一切,因此数据没有以任何方式被更改。区块链本质上是加密的,这使得提供适当的验证成为可能。

图片资源:/unsplash . com/@ clinta dair

智能合约可与区块链一起使用,以确保每次满足特定条件时发生特定的验证。 如果在任何情况下,有人确实更改了数据,网络中所有节点上的所有分类帐都验证更改已完成。

提供安全的数据存储

区块链是保护共享社区数据的最佳方式。利用区块链的功能,没有人可以读取或干扰任何敏感的存储数据。

处理分布在人际网络中的数据很有帮助。此外,该技术还可以用于公共服务,以保持公共记录的分散和安全。

图片资源:https://unsplash.com/@austindistel

除此之外,商业模式可以在区块链上保存一个数据的加密签名或者庞大的数据形式。这将允许用户留下来,以确保数据的安全。 区块链用于分布式存储软件,将海量数据分解成块。这在网络上的加密数据中可用,意味着所有数据都是安全的。

无法攻击

谈到区块链,黑客或攻击变得异常困难。区块链是去中心化的、加密的和交叉检查的,这允许数据保持强大的备份。由于区块链满载节点,同时攻击大多数节点是不可能的。

图片资源:https://unsplash.com/@markusspiske

作为分布式账本技术之一,其最基本的属性是数据不可变。 它提供了一种全新的成功安全性,任何行为或交易都不能被篡改或伪造。这项技术使每一笔交易都有效,得到网络上多个节点的确认。

最终想法

由于应用范围广泛,区块链用于建立安全网络。对于安全的数据交换,区块链安全开发服务是挑战传统方法的最佳选择。采用区块链技术可以改善技术和用户隐私之间的关系。

区块链技术的数字景观是安全性和透明性的组合。区块链带来了解决数据管理问题的技术,主要涉及安全、隐私和验证。

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

一个简单预测程序的蓝图

原文:https://towardsdatascience.com/blueprint-for-a-simple-forecasting-program-567833b3fc86?source=collection_archive---------47-----------------------

预测,但不是时间序列预测

万花筒在 Unsplash 上拍摄的照片

短期和长期预测是每个部门决策的基本商业活动。呼叫中心需要知道五年后呼叫量的增长情况,以保持足够的人员来为客户服务。电力公司希望预测未来十年的电力消耗增长,这样他们就可以投资新的装置来满足额外的需求。小企业需要了解他们的投资在未来几年的回报情况,并做出必要的调整。

所有这些业务需求都需要预测。传统上,这些预测是在临时的基础上进行的,数据科学家可以使用的工具有限。时间序列技术已经存在了很长一段时间,但是它们有自己的局限性,并且通常它们不能提供必要的准确性和指向特定的不确定性。对于时间序列,由于新政策的实施,也很难制定方案并对关键绩效指标(KPI)进行敏感性分析。

考虑到这一点,在本文中,我将介绍一种不同的预测技术的蓝图,这种技术依赖于很少的数据点。正如下面将要看到的,这种技术还允许对特定业务决策的影响及其对 KPI 的影响进行场景分析。

系统动态建模

系统动力学是一种复杂系统建模的方法,其中一个元素的变化导致其他元素的变化。

它广泛应用于医疗保健、流行病学、运输、商业管理和收入预测。可以说,其中最著名的是罗马俱乐部的增长极限模型。

一个系统动态模型代表了一个复杂的系统,通过反馈循环来预测系统的行为。假设一个银行账户有 100 美元的“股票”。每月存入 20 美元(由流程 1 表示),每月提取 15 美元(流程 2 )。在这种简单的情况下,流程 1 的变化将导致库存 1流程 2 的变化。因此,如果我们知道流量 1 将如何演变成未来,我们就可以预测股票 1流量 2

SD 建模中的存量、流量和反馈循环(来源:作者)

使用类似的概念,下面我将介绍一种依赖于更少数据点的预测方法,而不是传统预测中使用的复杂时间序列建模。

下面是一个简单的蓝图和必要的代码。我还在世界三大经济体的 GDP 预测中测试它。但这一概念可以应用于任何其他业务预测和决策过程。

方法、数据和代码

所以基本上我创建了一个名为forecast()的函数,它有 4 个参数:

  • 初始值
  • 变化的速度
  • 预测时间步数
  • 当前时间段。

然后,在给定初始值和变化率的情况下,该模型计算每个时间步中的未来值。该函数输出所有时间步长的预测值列表。

然后将预测值绘制成时间曲线。这里生成多个预测来比较不同的实体,但是如果我们要对单个实体进行预测,这个概念也可以以类似的方式工作。在这种情况下,业务政策或活动的变化将采用不同的参数,并对未来每个时间步的预测估计的变化进行建模。

因此,我在这个演示中提出的问题是,主要经济体的 GDP 将如何发展,它们在 2030 年将会是什么样子?这个简单的模型只需要 2 个参数,2019 年名义 GDP(美元)和 GDP 增长(%),但正如你将看到的,即使在这个简化版本中,它也可以产生强大的洞察力。以下数据用于演示:

  • 美国 GDP: 21.43 万亿 & 增长:2.3%
  • 欧盟国内生产总值:19.6 万亿 & 增长:1.6%
  • 中国 GDP: 14.1 万亿 & 增速:6.1%

预测

使用上述函数预测了美国、欧盟和中国的国内生产总值,并在每个预测年填入同一个面板中。

业内每个人都知道中国的经济正在着火。这种预测给出了火球有多大的概念。在这一点上,中国的经济似乎远远落后于美国和欧盟,但考虑到增长率,中国将很快超越只是时间问题。但是多快呢?

2023 年是中国接管欧盟的一年,2025 年 GDP 超过美国经济。

在美国和欧盟之间,在这一点上,他们的 GDP 处于类似的数量级,但正如预测所示,由于美国的增长率更高,差距将继续扩大。

2030 年世界主要经济体 GDP 预测

但当然,这些都是 COVID 之前的情况,在 COVID 之后,一切都将发生变化。我们需要等待一段时间,以了解事情的发展方向。

离别的思绪

本文的目的是展示一个简单的程序如何生成强大的预测洞察力。当然,这是一个简单的演示,但我的目标是给出超越传统时间序列预测的可能性的直觉,并尝试一些不同的东西,尤其是当数据是一个限制因素时。

基于神经网络的棋盘游戏图像识别

原文:https://towardsdatascience.com/board-game-image-recognition-using-neural-networks-116fc876dafa?source=collection_archive---------11-----------------------

如何使用计算机视觉技术来识别棋子及其在棋盘上的位置

蒂姆·福斯特在 Unsplash 上的照片

利用计算机视觉技术和卷积神经网络(CNN),为这个项目创建的算法对棋子进行分类,并识别它们在棋盘上的位置。最终的应用程序保存图像,以可视化的表现,并输出棋盘的 2D 图像,以查看结果(见下文)。本文的目的是逐步完成这个项目,以便它可以作为新迭代的“基础”。参见 GitHub 上该项目的代码。

(左)来自现场摄像机的画面和(右)棋盘的 2D 图像

数据

我对这个项目的数据集有很高的要求,因为我知道它最终会推动我的成果。我在网上找到的国际象棋数据集要么是用不同的国际象棋设置( Chess Vision )、不同的相机设置( Chess ID Public Data )创建的,要么是两者都用( Raspberry Turk Project ),这让我创建了自己的数据集。我使用我的国际象棋和相机设置( GoPro Hero6 Black 在“第一人称视角”)生成了一个自定义数据集,这使得我的模型更加准确。该数据集包含 2,406 幅图像,分为 13 类(见下文)。要点:这花费了我大部分的时间,但最终你会希望在图像上训练你的模型,使其尽可能接近你的应用程序中使用的图像。

自定义数据集的细分(图片由作者提供)

为了构建这个数据集,我首先创建了 capture_data.py ,它在点击 S 键时从视频流中提取一帧,并将其保存到导演。这个程序允许我无缝地改变棋盘上的棋子,并一遍又一遍地捕捉棋盘的图像,直到我建立了大量不同的棋盘配置。接下来,我创建了 create_data.py ,通过使用下一节讨论的电路板检测技术将帧裁剪成独立的片段。最后,我将裁剪后的图像分类,将它们放入带标签的文件夹中。然后…瞧!

棋盘检测

对于棋盘检测,我想做一些比使用findchesboardcorners(OpenCV)更复杂的事情,但不像 CNN 那么高级。使用低级和中级计算机视觉技术来寻找棋盘的特征,然后将这些特征转化为外边界和 64 个独立方格的坐标。该过程围绕实现 Canny 边缘检测和 Hough 变换来生成相交的水平线和垂直线。分层聚类用于根据距离对交叉点进行分组,并对各组进行平均以创建最终坐标(见下文)。

完整的棋盘检测过程(图片作者

棋子分类

当我开始这个项目时,我知道我想使用 Keras/TensorFlow 创建一个 CNN 模型,并对棋子进行分类。然而,在创建我的数据集之后,在给定数据集大小的情况下,CNN 本身不会给我想要的结果。为了克服这个障碍,我利用了imagedata generator和 transfer learning ,它们扩充了我的数据,并使用其他预先训练的模型作为基础。

创建 CNN 模型

为了使用 GPU,我在云中创建并训练了 CNN 模型,这大大减少了训练时间。快速提示:Google Colab是一种快速简单地开始使用 GPU 的方法。为了提高我的数据的有效性,我使用 ImageDataGenerator 来扩充我的原始图像,并将我的模型暴露给不同版本的数据。函数 ImageDataGenerator 随机旋转、重新缩放和翻转(水平)每个时期的我的训练数据,本质上创建了更多的数据(见下文)。虽然有更多的转换选项,但我发现这些对于这个项目来说是最有效的。

**from** **keras.preprocessing.image** **import** ImageDataGeneratordatagen = ImageDataGenerator(
        rotation_range=5,
        rescale=1./255,
        horizontal_flip=**True**,
        fill_mode='nearest')test_datagen = ImageDataGenerator(rescale=1./255)train_gen = datagen.flow_from_directory(
    folder + '/train',
    target_size = image_size,
    batch_size = batch_size,
    class_mode = 'categorical',
    color_mode = 'rgb',
    shuffle=**True**)test_gen = test_datagen.flow_from_directory(
    folder + '/test',
    target_size = image_size,
    batch_size = batch_size,
    class_mode = 'categorical',
    color_mode = 'rgb',
    shuffle=**False**)

我没有从头开始训练一个全尺寸模型,而是通过利用一个预训练模型来实现迁移学习,并添加了一个顶层模型,使用我的自定义数据集进行训练。我遵循典型的迁移学习工作流程:

1.从先前训练的模型(VGG16)中提取图层。

**from** **keras.applications.vgg16** **import** VGG16model = VGG16(weights='imagenet')
model.summary()

2.冷冻它们是为了避免在训练中破坏它们所包含的任何信息。

3.在冻结层上增加了新的可训练层。

**from** **keras.models** **import** Sequential
**from** **keras.layers** **import** Dense, Conv2D, MaxPooling2D, Flatten
**from** **keras.models** **import** Modelbase_model = VGG16(weights='imagenet', include_top=**False**, input_shape=(224,224,3)) 

*# Freeze convolutional layers from VGG16*
**for** layer **in** base_model.layers:
    layer.trainable = **False***# Establish new fully connected block*
x = base_model.output
x = Flatten()(x) 
x = Dense(500, activation='relu')(x) 
x = Dense(500, activation='relu')(x)
predictions = Dense(13, activation='softmax')(x)*# This is the model we will train*
model = Model(inputs=base_model.input, outputs=predictions)
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['categorical_accuracy'])

4.在自定义数据集上训练新图层。

epochs = 10history = model.fit(
    train_gen, 
    epochs=epochs,
    verbose = 1,
    validation_data=test_gen)model.save_weights('model_VGG16.h5')

虽然我使用 VGG16 或 VGG19 作为预训练模型来创建模型,但由于验证准确性更高,我选择了使用 VGG16 的模型。此外,我发现最佳的历元数是 10。任何大于 10 的数字都不会导致验证准确性的增加,并且会增加训练和验证准确性之间的差异,这暗示着过度拟合。收获:迁移学习让我能够充分利用深度学习在图像分类方面的优势,而不需要大型数据集。

结果

为了更好地可视化验证的准确性,我创建了一个模型预测的混淆矩阵。从这个图表中,很容易评估模型的优点和缺点。优势:空— 准确率为 99%,召回率为 100%;白棋和黑棋(WP 和 BP)——F1 值约为 95%。弱点:《白骑士》(WN)——召回率高(98%),但准确率很低(65%);白人主教(WB)——召回率最低,为 74%。

测试数据的混淆矩阵(作者的图片)

应用

该应用程序的目标是使用 CNN 模型并可视化每一步的性能。我创建了 cv_chess.py (见下面的摘录),它清楚地显示了步骤,还创建了 cv_chess_functions.py ,它显示了每个步骤的细节。这个应用程序保存来自实时视频流的原始帧,每个方格的 64 个裁剪图像,以及棋盘的最终 2D 图像。我以这种方式构建应用程序,以快速确定未来改进的优势和劣势。

print('Working...') 

# Save the frame to be analyzed        
cv2.imwrite('frame.jpeg', frame)  

# Low-level CV techniques (grayscale & blur)        
img, gray_blur = read_img('frame.jpeg') 

# Canny algorithm        
edges = canny_edge(gray_blur) 

# Hough Transform        
lines = hough_line(edges)   

# Separate the lines into vertical and horizontal lines        h_lines, v_lines = h_v_lines(lines) 

# Find and cluster the intersecting        
intersection_points = line_intersections(h_lines, v_lines)        points = cluster_points(intersection_points)   

# Final coordinates of the board        
points = augment_points(points)       

# Crop the squares of the board a organize into a sorted list        x_list = write_crop_images(img, points, 0)        
img_filename_list = grab_cell_files()        img_filename_list.sort(key=natural_keys)   

# Classify each square and output the board in Forsyth-Edwards Notation (FEN)        
fen = classify_cells(model, img_filename_list) 

# Create and save the board image from the FEN        
board = fen_to_image(fen)      

# Display the board in ASCII        
print(board)# Display and save the chessboard image        
board_image = cv2.imread('current_board.png')        cv2.imshow('current board', board_image)  

print('Completed!')

演示

显示了变化板现场(左)和新的 2D 图像输出(右)

我希望你喜欢这个演示!更多我的项目,请看我的网站和 GitHub 。请随时通过 LinkedIn 与我联系,对这个项目的未来迭代有想法。干杯!

散景、散景和可观察总部

原文:https://towardsdatascience.com/bokeh-bokehjs-and-observablehq-6ddf0c5ffe8a?source=collection_archive---------66-----------------------

脱离朱庇特轨道的冒险

2019 年 11 月朱诺号拍摄的木星北纬(图片来源:美国宇航局/JPL 加州理工

在 jupyter 笔记本中使用 python 时,散景可视化库已经成为我最喜欢的显示数据的工具之一。散景功能强大,易于使用,具有可访问的交互功能,并生成美丽的图形。然而,随着我在过去几个月中使用 Bokeh,并对其内部有了更多的了解,我开始意识到 jupyter 中用于 Bokeh 的 python API 只是整个 Bokeh 包的一小部分。除了这个 API,Bokeh 还包括一个服务器包和一个名为 bokehjs 的 javascript 库。事实上,Bokeh 的 python“绘图”包根本不做任何绘图;相反,它是一种描述绘图的语言,这些绘图被序列化到 json 包中,并传递给 bokehjs 以在浏览器中呈现。随着我尝试在我的情节中添加更多的交互性,我逐渐清楚地知道,了解一些 JavaScript——我并不知道——并对散景有更清晰的理解会让我用散景做更多的事情。

与此同时,出于完全不同的原因,我遇到了 Observablehq 。Observablehq 是由 javascript D3 可视化包的开发者 Mike Bostock 领导的团队创建的。乍一看,它非常像一个基于 javascript 的云托管 jupyter 笔记本。考虑到我探索 bokehjs 和学习一些 javascript 的目标,我天真地认为 Observablehq 是最适合我的工具。嗯,这并不那么简单,因为 Observablehq 不仅仅是 jupyter 笔记本的 javascript 版本,它是一个非常不同的东西,并且以自己的方式非常漂亮;bokehjs 并不完全适合 Observablehq 世界。尽管如此,在尝试将这些世界融合在一起的过程中,我学到了很多关于 bokehjs 和 Observablehq 的知识,并且我看到了很多进一步发展的潜力。这里有一份简短的进度报告和一些提示,如果你也想开始这段旅程的话。

Observablehq 不是 Javascript 的 Jupyter

正如我上面提到的,当我查看 Observablehq 用户界面时,我的第一反应是这只是 javascript 的 Jupyter

如上面的小动画所示,Observable 有笔记本,有单元格,你在单元格里输入 javascript(或者 markdown);按 shift-enter 键,单元格就会被求值。听起来像朱庇特,对吧?但是可观察的笔记本是完全不同的——每个单元格都有一个值,并且这些单元格根据引用组合成一个图表。当一个单元格的值发生变化时,所有依赖于该单元格的单元格都会被重新计算。这有点像小 javascript 程序的电子表格。这种设计意味着可观察笔记本以一种自然的方式支持高度的交互性,远远超过 jupyter 笔记本的能力。如果你感兴趣,你最好的选择是阅读 Observablehq 网站上的优秀文章。除了的介绍性文章,尤其值得一提的是:

  • 【jupyter 用户可观察到的
  • 如何观察运行

在 Observable 中加载 Bokehjs

在可观察的笔记本中试验散景的第一步是加载库。对于这一步,我得到了布莱恩·陈的你好,Bokehjs 笔记本的帮助。将下面的代码放入一个可观察到的笔记本单元格中,然后按 Shift-Enter 键,就可以实现这个目的:

正在将 Bokehjs 库加载到 Observablehq 中

不必在细节上花费太多时间,值得指出的是,加载 Bokeh 的代码被括在大括号中,以便作为一个单元执行。正如我前面提到的,可观察笔记本中的每个单元格就像一个自包含的 javascript 程序,单元格的执行和重新执行取决于它们引用之间的依赖图。这段代码中至关重要的require语句通过副作用起作用,而不是通过返回值。这意味着 Observable 不理解这些语句之间的依赖关系;如果放在不同的牢房里,它们可以按任何顺序执行。更一般地说,Observable 不是为了处理通过副作用起作用的函数而建立的,人们需要小心使用它们。

这个特殊的单元格是一个viewof构造,它的作用是将引用赋予变量Bokeh到附加 bokehjs javascript 库的window.Bokeh,同时显示变量message的内容,这是一个表示正在发生什么的html字符串。

您可以节省一些输入,而不是包含上面的代码,利用 Observable 跨笔记本导入单元格的能力,只需使用:

import {Bokeh} from "@jeremy9959/bokeh-experiments"

使用散景打印

现在我们已经加载了库,让我们画一个图。我将遵循 bokehjs 发行版中的分层条形图的示例。

Bokehjs 水果地块示例

你可以直接看我画这个图的可观察笔记本。笔记本的第一部分只是通过创建对应于fruitsyears数据的单元格来设置数据,以及对应的逐年计数。例如,逐年计数存储在直接声明的变量data中:

// help the parser out by putting {} in ()
data = ({
  2015: [2,1,4,3,2,4] ,
  2016:[5,3,3,2,4,6],
  2017: [ 3,2,4,4,5,3],
})

注意,javascript 显式对象创建中使用的括号需要括号来帮助可观察解析器。

创建这个图的 Bokeh 代码直接取自 bokehjs 发行版中的文件(尽管我把这个图做得更宽了一点):

最后,我们使用 Bokehjs 的嵌入函数将绘图渲染到 observable notebook 中的一个单元格中。

结果就是我上面画的图。

那又怎样?

到目前为止,这还不太令人满意,因为我们完全可以使用 python API 在 jupyter 笔记本上绘制相同的图形。为了说明为什么这种方法是有趣的,让我指出我们通过在 observable 中工作得到的两个主要好处。

  1. 我们可以检查 javascript 对象。我最初对 Observable 感兴趣的原因之一是,我正试图学习 javascript,并试图理解 bokehjs 的内部工作原理。当然可以使用浏览器的 javascript 控制台来探究 bokehjs 的内部,但是 observable 给出了一个优雅的界面。例如,在制作情节时,我们构建了一个名为PFigure对象。下图显示了可观察到的关于这个图形的信息,使用小三角形你可以打开这个物体并探索它的内部结构。(注意:如果你想这样做的话,加载非缩小的 bokehjs 包是很重要的,否则在这个输出中类 ID 将是不可理解的。)

2.可观察是互动的!在 Observable 中做这件事的真正不同和有趣之处在于它是交互式的。如果我去定义变量data的单元格,并更改数字,只要我一进入单元格,图形就会更新:

这是因为 Observable 的执行图知道水果图依赖于数据变量,当该变量改变时,该图得到重新计算。

顺便说一句,Observable 的另一个特性是,由于执行顺序与文档中单元格的物理顺序无关,所以我可以将图表移到紧靠data单元格的位置,这样我就可以清楚地看到发生了什么。

这只是在 Observable 中可能实现的交互性水平的一小部分——例如,在笔记本上添加小部件甚至制作动画是非常容易的。这篇文章不是深入探讨这个问题的地方,但是在可观察的主页上有许多漂亮的例子。

返回木星轨道时的讲话

最后,我认为重要的是要指出,有比使用散景更自然的方式来绘制可观察图像。特别是,使用织女星有一个紧密集成的 API,非常强大的 D3 包实际上是内置在 Observable 中的。但是对于像我这样熟悉 bokeh 的 python 接口并希望了解更多关于 bokehjs 的知识的人来说——特别是考虑到虽然 python API 被广泛而细致地记录,但 bokehjs API 基本上是一个黑盒——Observable 提供了一个有趣的机会。有更多的事情可以尝试,我期待着超越 Jupyter 轨道的进一步冒险。

股票交易的布林线 Python 中的理论与实践

原文:https://towardsdatascience.com/bollinger-bands-for-stock-trading-theory-and-practice-in-python-7d3e79d30e02?source=collection_archive---------13-----------------------

让我们看看 Python 中一个简单但有效的交易工具

作者图片

量化交易者经常寻找能发现趋势或反转的交易工具。这类工具应该能够自我适应市场条件,并试图以最准确的方式描述当前形势。

在本文中,我将讨论布林线以及如何在 Python 中使用它们。

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

布林线有哪些?

布林线是量化交易者约翰·布林格在 20 世纪 80 年代推出的工具。它们由两条线组成,以与波动性相关的方式包裹价格时间序列。波动性越高,波动幅度越大。

它们通常以这种方式绘制:

  • 高波段:20 周期简单移动平均线加上 2 倍的 20 周期滚动标准差,两者都是基于收盘价计算的
  • 较低波段:20 期简单移动平均线减去 2 倍 20 期滚动标准差,两者都是根据收盘价计算的

这是应用于标准普尔 500 指数的 SPX ETF 的结果:

正如你所看到的,波段试图包裹价格,但当价格突破它们时,会发生一些特殊的事件,我们可以利用这些事件来建立许多交易策略。

布林线策略

让我们看看一些可以用布林线发现的交易设置。

拒绝

二元期权交易者最常用的方法是将布林线视为动态支撑和阻力。一旦价格打破了一个波段,一般认为它可能会回到均线。

突破和拒绝模式。图片由作者提供。

然而,虽然这种方法看起来不错,但布林格自己通常建议将波段与另一个指标结合使用,例如,振荡指标。我们将看到打破波段通常不是一个反向信号。

骑着乐队

如果趋势强劲,一些蜡烛的价格可能会接近一个区间。这是因为强劲的趋势意味着高波动性,所以波段扩大,价格跟随他们。

价格波动很大。图片由作者提供。

w 和 M 模式

一组非常常用的模式是 W-M 模式。前者与后者相反。当价格打破下波段,然后上涨,然后再次下跌,最后上涨而没有再次打破波段时,出现 w 形态。真的好像画了个 W 字母。

w 模式示例。图片由作者提供。

当价格突破上带时,出现 M 型形态,然后在没有再次突破上带的情况下形成新的最大值。

m 模式示例。图片由作者提供。

这些模式通常被认为是动量的减少,所以它们以相反的方式使用。w 形态看涨,M 形态看跌。

挤压和破裂

不要忘记,市场波动会随着时间的推移而变化,有些低波动期会引发市场的大规模定向爆发。布林线可以很容易发现这种情况。你必须寻找一个市场条件,其中波段是平坦的,其宽度是恒定的。这被称为“挤压”,因为波动性正在降低。然后,你必须寻找一个巨大的蜡烛突破。这是价格定向爆发的前奏,你可以沿着突破的方向交易。

挤例子。图片由作者提供。

布林线参数

布林线有两个参数:均线和标准差的周期(相同)以及标准差的乘数。

20 周期的 SMA 经常被用来捕捉中期运动,所以 20 周期的值是根据经验选择的。

我们来谈谈标准差的乘数。根据正态分布,一个正态变量的值有接近 95%的概率远离均值 2 个标准差以上。这就是 2 这个数字的由来。

事实上,我们知道价格不遵循正态分布。根据几何布朗运动模型,对数正态分布是价格分布的一个很好的近似。而且根据切比雪夫不等式,任何一个有限方差的随机变量,其值远离均值超过 2 个标准差的概率小于 25%。所以,这相当高,与正常情况下的 5%有很大不同。

约翰·布林格本人建议使用一组略有不同的参数,根据某些特定情况改变乘数和周期。

然而,20-2 组合被广泛认为几乎是交易的标准。

Python 中的一个例子

用 Python 计算布林线非常容易。我们将利用标准普尔 500 的历史数据来看看如何做到这一点。完整的代码可以在我的 GitHub 知识库中找到:https://GitHub . com/gianlucamalato/machine learning/blob/master/Bollinger _ bands . ipynb

首先,让我们安装 yfinance:

!pip install yfinance

然后让我们导入一些库:

import yfinance
import pandas as pd
import matplotlib.pyplot as plt

让我们从标准普尔 500 指数中导入一些数据:

name = "SPY"ticker = yfinance.Ticker(name)df = ticker.history(interval="1d",start="2020-01-15",end="2020-07-15")

我们可以定义周期和乘数:

period = 20
multiplier = 2

然后,我们可以最终计算波段:

df['UpperBand'] = df['Close'].rolling(period).mean() + df['Close'].rolling(period).std() * multiplierdf['LowerBand'] = df['Close'].rolling(period).mean() - df['Close'].rolling(period).std() * multiplier

最后的图表是:

作者图片

正如你看到的,波段包装的价格就像预期的一样。

结论

布林线在交易中非常有用,计算也非常简单。使用这种动态工具的不同策略会导致不同的结果,因此应该对交易策略进行良好的回溯测试,以微调指标的参数。

使用机器学习进行时间序列预测时要小心的陷阱

原文:https://towardsdatascience.com/booby-traps-to-watch-out-for-in-time-series-forecasting-cd6aca1e8225?source=collection_archive---------22-----------------------

代价高昂的错误会使基于机器学习的时间序列预测模型在生产中变得不准确

图片来自 Tralfaz

T ime 系列预测在数据科学方面算是老手,有着扎实的统计学基础。甚至在 Python 使得在行业中应用 ML &数据科学更容易之前,它就已经存在了。它在能源预测、金融等方面有多种应用。仅举几个例子。但是如果你没有在你的数据科学入门课程中读到过 ARIMA、霍尔特-温特斯,我不会责怪你,因为他们不像 ML 模型那样耀眼。

然而,最近,许多研究表明,使用更闪亮的最大似然模型,如神经网络进行预测是有希望的。我的团队也决定冒险进入这个领域,将 ML 技术应用于预测问题。我有更传统的 ML 方法和应用的背景,例如预测模型、分类和 NLP,直到最近才有机会处理时间序列数据。这种传统主义意味着我必须改变处理问题的方式。更重要的是,我陷入了一些被传统的 ML 方法/途径完全掩盖的陷阱。

让我们来讨论一下这些陷阱。

  1. 数据科学 101:将数据集分为训练/验证/测试

构建机器学习模型的传统方法需要获取数据,清理数据,并将其分为训练、验证和测试。虽然这种方法在时间序列预测中可能仍然有效,但有必要寻找潜在的地雷。

首先,让我们看看用于预测功率(KW)的典型特征;一个时间序列问题。任何时间序列预测问题中最高度相关的特征之一是先前值,即从当前时间 T 的滞后值。在功率预测的情况下,已经看到前 6 个值和上周的相应值与当前时间的负荷值高度相关。下图对此进行了说明:

示例滞后值(负载-千瓦)

你可以在上图中看到每个滞后值是如何形成的;跨特征集形成的对角线是时间序列预测的一个非常明显的属性。每个滞后值都是在规定的滞后时间的目标值,如 t-1、t-2 等。现在让我们想象我们在 15:00 分割这个特征集。16:00–18:00将成为我们的测试/验证集(在我们的示例中无关紧要)。现在,如果我们想要预测这 3 个小时标记( 16:00、17:00、18:00 )中每个小时标记的电力负荷,我们将需要 16:00 的负荷值来预测 17:00 (因为 滞后(t-1)负荷[16:00】【T24)

我们的模型不应该知道真实世界场景中的实际值

但是,等一下,当我们不知道 16:00 的实际值时,我们怎么能在 17:00 和 18:00 得到这些滞后值呢?(请记住,我们预测的是 16:00 时的值)。换句话说,我们的模型公然作弊。你也几乎可以把这等同于用训练数据测试你的模型。如上图所示,这些值在生产中对我们不可用。因此,简单地分割数据集并验证/测试我们的模型是不可能的。解决这个问题的一种方法是每次动态构造测试行,将预测值用作下一行的滞后值,依此类推。这个问题也直接把我们引到了下一点。

  1. 错误分析:随时间恶化

回到我们之前的例子,我们知道我们不能使用实际值,所以我们将不得不用我们的预测值来凑合。正如任何回归/ML 问题一样,我们知道我们永远不可能获得 100%的准确性。这意味着我们的每一个预测都将带有一个误差,这个误差将会在接下来的所有测试行中传播。当我们在预测值上绘制实际值时,这种影响将是可见的,即我们的误差将随着预测时间的推移而增加。一个自然的结果将是尝试并过度拟合模型上的数据以提高性能,但我们应该避免这样做,并意识到这个错误是由于我们拥有的特征集造成的。我们有办法避免这种情况(只预测短期或稍微复杂的动态来预测下一个 h 步骤),但我将把这个讨论留到以后。但这为下一个陷阱埋下了伏笔。

3)列车模型一次

图片来自来源

在大多数机器学习问题中,我们识别相关特征,训练一次模型,然后将其部署到生产中。例如,我们想要开发一个 ML 模型来对手写数字进行分类,这是一个相当众所周知的问题。我们根据大量不同的数据来训练我们的模型。我们假设用于分类这些数字的特征不会随着时间而改变。因此,一旦我们在训练集上训练了模型,我们就简单地对我们的测试值进行分类,而不做任何改变。在时间序列中,情况并非如此。

图片来自来源

让我们再次回到电力负载的例子。我们不需要成为时间序列预测专家就知道,在炎热的夏季(更多空调)和寒冷的冬季(更多供暖),电力需求会增加。时间序列数据的这种波动是常见的。你不能指望数据一直保持不变。因此,每次我们想要预测数值时,都需要重新训练模型。这是为了纳入任何可能发生的重大波动(高能源价格、经济衰退等)。请看上图,了解历史上的能源消耗以及未来二十年的预测。快速浏览一下历史数据,就可以看出消耗是如何随时间变化的。同样,在没有其他随时可能变化的外部因素的情况下,我们也不能指望需求只是简单地上升。因此,牢记这一点并用最新的时间序列数据重新训练模型是非常重要的。

摘要

在处理时间序列数据和传统的机器学习模型时,必须记住这些要点。对于时间序列预测专家来说,这并没有让他们大开眼界,但是对于像我这样更传统的数据科学家来说,这是一个很好的教训。在处理时间序列数据时,我们应该意识到模型中的这些不确定性。

书评:用 Python 进行深度学习,2017,弗朗索瓦·乔莱,曼宁

原文:https://towardsdatascience.com/book-review-deep-learning-with-python-2017-françois-chollet-manning-99c36faa5a29?source=collection_archive---------44-----------------------

作者 Take 用 Python 深度学习,2017,Franç ois Chollet 的书和我的猫

不到 10 分钟的深度学习世界之旅。

我花了很长时间才打开这本书。更多的是因为害怕发现自己什么都不知道,而不是因为害怕对什么都知道感到沮丧。我定期收到关于人工智能、机器学习或深度学习的“最佳”或“最受欢迎”书籍的简讯。使用 Python 进行深度学习一直被认为是最值得推荐的方法之一。给定的等级经常在高级、中级或专家之间变化。我认为,我们不应该停留在某个人估计的水平上。出于兴趣,出于需要,你必须拿起一本书来读。

任何想学习的人都可以接触到这本书。写作的流畅性和简单性允许理解所有的概念,不管水平如何。

第 1 部分:深度学习的基础

第 1 章——什么是深度学习?

这本书的第一章给了读者一个很好的领域中使用的定义的概述,以及我们确切地称之为算法方式的 学习 。作者简明扼要地讲述了人工智能的历史

有很多解释和上下文来解释什么是深度学习,以及为什么它最近才出现在我们的行业和现实世界中(硬件、数据、摩尔定律……)。

作者为读者提供了不同机器学习算法和神经网络如何工作的清晰解释。

我很欣赏算法使用的背景以及与竞赛中使用的相似性(为什么这种类型用于特定的任务)。

第 2 章— [..]神经网络的数学构建模块

所以我们在这里,在本书的 数学 部分。嗯,每个人都会被这几句话吓到,但是,作者有一个 的特殊方法 来解释神经网络背后的数学。他自己的话是:

虽然这一节完全涉及线性代数表达式,但您在这里找不到任何数学符号。我发现,如果用简短的 Python 片段而不是数学方程来表达数学概念,没有数学背景的程序员会更容易掌握。所以我们将从头到尾使用 Numpy 代码。

没错,没有数学公式。所以,不要害怕数学,也不要疯狂地认为数学很难或者不可能。作者把学习过程 背后的数学不同部分剪得很简单,用 Numpy 代码 来解释。

通过这一章,你将熟悉 向量、矩阵和张量(以及它们对应的真实世界应用) 。与神经网络 的张量 和相应的 表示一起使用的不同 运算。您还将了解到 可微函数梯度 以及什么是 梯度下降、 随机梯度下降,以及不同的 神经网络 的对应参数。******

简洁明了这一章解释得很好,并且 允许我们很好地理解张量操作和表征学习的

作者利用几何学让读者将他所解释的概念形象化。

另外,在短短几行中,你将熟悉 反向传播 及其背后的数学原理。作者重用了前一章的一个例子,并把它分成几部分来映射你刚刚学到的相关数学概念。

一开始我有点犹豫,但是我急切地浏览了这些 三十页

第 3 章—神经网络入门

有了这一章,读者能够用神经网络处理分类(二进制和多进制)和回归等大多数常见问题。

作者解释了神经网络的不同部分(层、输入数据、损失函数、优化器)。他提供了用 Keras 编写的代码块,并解释了它们是如何工作的。

你会发现损失函数和优化非常相关的信息。

这些例子。本章提供了三个,每个常见问题一个(二元分类、多类分类、回归)。作者提供了最佳实践以及可视化应该关注的内容。他强调了过度拟合,以及如何评估你的模型,对于不同的问题使用什么损失函数。

你会对这三种情况下神经网络的输出有很好的理解。突出显示的一点是网络的大小,考虑数据集的大小来扩展网络非常重要。如果数据集很小,请选择层数很少的小型神经网络,以避免过度拟合。

这 36 页非常有用,充满了信息和最佳实践。

第 4 章—机器学习的基础

本章将让读者对机器学习世界的不同分支做一个调查。你将接触到 ML 世界中四个概念的快速描述。

作者将介绍分类和回归之间的不同概念以及不同的度量和损失函数。

你将知道如何评估你的模型和准备一个项目所需的所有步骤。从数据开始,到超参数调整结束。

作者提出了培训、评估和测试的重要性。您将了解评估您的模型的常用方法以及不同方法背后的代码。您还可以找到关于特征工程和数据格式的适当信息。

您将找到关于过度拟合和欠拟合的适当信息,以及这对您的模型意味着什么以及避免它们的方法。作者提供了一个关于辍学以及如何使用它的很好的解释。

还有最后一点,每个项目都需要走的机器学习工作流程。当开始一个机器学习问题时,你会发现不同的假设和一步一步的遵循。

因此,这是一个小章节(26 页),但在机器学习的研究项目中,有许多重要信息需要记住。

简历第一部分

在这一点上,你到达了本书第一部分的结尾,你通过了深度学习世界的所有基础部分,以及如何在你的项目中精确地使用它们。您将知道从哪里开始、寻找什么、如何准备数据、如何训练、评估和测试您的模型。理解算法每一部分背后的数学的重要性。但最重要的是,你有这个学科的背景和过程的定义。

第 2 部分:实践中的深度学习

第五章——计算机视觉的深度学习

在这一章中,作者将解释卷积神经网络(CNN)的所有概念。这部分有很多信息。

作者从 CNN 如何工作的操作开始(过滤器、填充、步幅、池…)。然后你将知道如何在一个小的数据集中使用它们来获得好的结果。你将熟悉计算机视觉中的过拟合概念,以及如何避免它(数据扩充、丢失……)。

下一步是通过预先训练的模型,它们的目标,它们是如何获得的,以及如何在不同的情况下使用它们来提高预测的准确性。作者解释了特征提取的概念和微调的概念(调整预训练 CNN 的最后几层,以学习特定的过滤器或特定数据的表示),以及如何在低数据集的情况下使用它们。

这一章以康文网如何看待世界的形象化结尾。研究模型每一层的不同抽象表示的三种方法。

作者用了一个图像分类(狗/猫)的例子,提供了很多代码解释他描述的所有事物的每一步。

第 6 章—文本和序列的深度学习

在探索了图像识别的世界之后,作者带领我们进入文本和序列数据的世界。对于那些对 NLP 和时间序列问题感兴趣的人来说,这部分真的很神奇。

这一章首先解释了需要如何准备数据。你将了解符号化、n-grams、一键编码和单词嵌入(我看到的最好的解释是 Coursera 提供的深度学习专门化)。作者提供了大量代码来使用这些不同的技术和预训练的模型(手套,…)。

在关于数据的部分之后。你将探索递归神经网络(RNN)及其变体,LTMS,GRU 和双向的世界。作者提供了足够的理论来理解代码(Keras)与具体的例子。您将能够在文本数据上使用不同的模型,并轻松地重现本章第一部分中显示的结果。

本章的结尾是关于 RNNs 更高级的应用,如时间序列和文本生成。您还将学习如何在 RNN 使用 dropout,以及如何使用 CNN 处理文本或时间序列,但是在考虑时间序列时,您会看到这种类型的模型的缺点。

第 7 章—高级深度学习最佳实践

在本书的这一步,您将了解 Keras 的高级功能。作者为您提供了从顺序模型到函数式 API 的建议。为什么这很重要?因为有了这种可用性,你就可以拥有多输入模型或多输出模型。

您将对非循环图(作为初始模型)、剩余连接(ResNet 模型)、在层之间共享权重或使用模型作为层进行解释。

您还有关于使用 Tensorboard 和回调(不同的类型以及如何使用它们)来监控模型的最佳实践。您还将了解如何以及何时使用批量归一化和深度方向可分离卷积。

本章最重要的部分,对我来说,是超参数优化的部分。作者介绍了调整它们的不同方法以及如何使用集合模型。

你将有 36 页的浓缩信息,但它非常有用。

第八章——生成式深度学习

激动人心的一章,然后是这一章。第一部分是文本生成,您将学习如何编写一个语言模型来生成具有不同可能性的文本。最重要的是知道如何为下一个字符或下一个单词重新加权概率分布,以便在文本生成中产生创造力。

然后,你将可以访问 DeepDream 上的大量信息,以及如何将它用于预训练的模型。你将学习如何创造新的图片,以及这一代人的内在机制是什么。

神经风格转移,是什么?你会在这一章学到,这是一种将一张图片的内容和另一张图片的风格混合在一张新图片中的能力。是的,你将了解到内容风格可以用数学方法写出来,并放入神经网络中进行混合。

变分自动编码器和生成对抗网络我们到了。在几页~20 页中,你有很多关于图像生成的 VAEs 和 GANs 的信息。您将找到相关信息来区分两者,并选择在您的案例中使用哪一个。GANs 是最难训练的,所以作者提供了不同的技巧让你更好地理解模型的行为。GAN 部分对我来说是最有趣的,因为我从来没有使用它们。

我带着对生成数据的不同技术的良好直觉完成了这一章。图像生成是 GANs 最大的部分,也是最有趣的部分。

第 9 章—结论

作者在这一章的开头提供了这本书的简明摘要。然后,作者很好地理解了深度学习的局限性,并将其置于 AI 的世界中。你也在你的探索中找到作者对深度学习未来的感受,以及往哪里看。有一点,关于 AutoML,与这个领域最近的进展相提并论是很有趣的。您还可以找到如何与该领域保持同步的信息。

最后的话

我希望这本书的简短摘要能给你关于内容的相关信息,让你找到你需要的东西。这本书在我的图书馆里已经放了很长时间了,购买它的目的主要是为了使用第 6 章中关于 NLP 的内容。

我目前正在进行一项不同的探索,来填补我自学的所有弱点。所以,我开始接受挑战,超越我的舒适区。第一步,把自我放在一边,承认我并不知道一切(远非如此)。剩下的,去攻克能有帮助的课本。使用 Python 进行深度学习是长期被列为基准的基石。在探索它并做了无数笔记和便利贴后,我觉得我已经准备好继续我的旅程,进入我感兴趣的子域。

关于作者:

弗朗索瓦·乔莱(Franç ois Chollet)是谷歌大脑团队的人工智能研究员,也是 Keras 深度学习图书馆的作者。

弗朗索瓦·乔莱,用 Python 进行深度学习 (2017),曼宁

等待第二版的出版

书评:Naeem Siddiqi 的“智能信用评分”

原文:https://towardsdatascience.com/book-review-intelligent-credit-scoring-by-naeem-saddiqi-334dacb001a9?source=collection_archive---------44-----------------------

关于如何开发和使用信用风险记分卡的完整指南

《智能信用评分》图书封面(作者本人法师)。

1.介绍

从信用卡到房屋抵押贷款,记分卡是所有现代贷款业务的核心。记分卡的核心思想是将客户支付贷款的概率(个人的信誉)转化为易于理解的数字,以指导商业决策。尽管记分卡并不新鲜,但随着新的大数据/人工智能场景的出现,它已经发生了很大变化,尤其是在 2008 年金融危机之后。

“智能信用评分”为您提供的不仅仅是对该主题的介绍。这是一个由该领域最有影响力的作者之一撰写的关于如何工作和构建记分卡的完整指南。

乍一看,当我收到 智能信用评分 时,我想这将是一本更无聊的书,我会阅读介绍,也许是前几章,然后把它装饰在我的书架上,也许在需要时用它进行研究。但是我完全错了!阅读这本书实际上是令人愉快的,对于一本 400 页、包含信贷监管和模型监控章节的技术信息的书来说,阅读速度超出了我的预期。

2.图书主要受众

智能信用评分 是一本面向广大受众,从行业初学者到经验丰富的专业人士的通俗易懂的书。无论你是信用分析师,信用评分经理,还是数据科学家,这本书的内容将提供关于如何创建,评估和监控记分卡的更深入的观点。

3.这本书的结构

在介绍(第 1 章)之后,作者描述了负责记分卡开发和实施的团队中每个人的角色(第 2 章)。信用评分的一个有趣的方面是,它通常是由一个大团队执行的工作,有各种各样的专业人员。

下一章定义了维护成功记分卡所需的基础设施,并总结了从数据收集到模型实施和监控的过程。从第 4 章到第 14 章,作者详细描述了记分卡开发的每个阶段,将流程分为 7 个部分。

第一阶段,规划

在开始记分卡开发之旅之前,你需要回答一些关于你的商业计划的问题,以及你的公司是否有可用的基础设施和人力资源。还列出了开发内部和外部记分卡的优点和缺点,以帮助您做出决定。

阶段 2,数据审查和项目参数

虽然我们生活在一个大数据时代,但拥有大量数据是不够的。为了让你的项目成功,你需要的不仅仅是数量,还有组织有序的数据。在这个阶段,Siddiqi 指导读者如何设置默认定义,这是开发过程中的一个关键步骤。基于新巴塞尔协议的当前监管信息对记分卡行业非常重要,在第 7 章中有很好的介绍。目前,新巴塞尔协议第三版和第四版的更新已经在讨论和实施中,如果能在新版本中提供这些信息,那就太好了。

阶段 3,数据库创建

就像任何数据科学项目一样,在记分卡开发中,拥有高质量的数据比使用更好的模型更重要。这就是这本书的这一部分如此重要的原因。创建和过滤要素以及替换缺失值是数据库创建过程的一部分,应该非常小心谨慎地执行。本课程中提到的另一个重要方面是将数据集分为训练数据集和测试数据集,以评估模型性能。本次会议还提到了记分卡中使用的替代数据和更大数据集(大数据)的潜力,监管和技术相互影响,决定了该领域的创新。

“在一个不缺乏信息的时代,最有行动洞察力的银行才是赢家。”— 智能信用评分(第二版),纳伊姆·西迪奇

阶段 4,记分卡创建

数据库准备就绪后,是时候开始处理您的要素了。在本书的这一部分,你将学习如何运用证据权重,用它将你的变量分成同类的类别。在特征选择的过程中使用了像信息值这样的其他概念。以下部分描述了如何使用逻辑回归来创建记分卡,以及如何从结果模型中计算分数。

阶段 5,记分卡管理报告

记分卡只有在表现出反映当前客户群体的一致绩效时才有价值。这就是监控模型如此重要的原因。本书的这一部分介绍了一些性能指标和报告模板,以帮助你设计自己的管理系统。

阶段 6,记分卡实施

记分卡创建完成后,就该投入生产了。但是仅仅用它来获得新客户是不够的。你必须确保它根据经验证的数据集表现良好。因此,跟踪人口稳定性指数等指标有助于监控模型性能。此外,根据业务战略,可以使用多个记分卡来评估客户的信用风险状况。本课程将介绍组合记分卡和设置临界值的不同策略。

第 7 阶段,监控

最后,记分卡开发的整个周期在团队使用一套工具来监控模型性能的阶段结束。客户的概况受各种外部事件的影响,所以不要指望你的模型能长时间保持最初的性能。作者提出了一系列的方法和策略来使用记分卡,以帮助您管理您的投资组合和做出明智的商业决策

4.主要要点

正如简介中所提到的,智能信用评分是一本面向广大读者的通俗易懂的书,所以即使你是新手,它也会对你有很大的价值。

这本书的另一个有趣的方面是,它背后的数学和统计学相对简单。所以即使你在精确科学领域没有很强的背景,你也能真正理解关于所呈现概念的逻辑。

最后,记分卡从来都不是一个人或一个小团队的产品。它的发展需要来自机构内部各种专业人士的反馈,以反映业务逻辑,并显示其对公司和银行内部决策的真正价值。

非常感谢你阅读我的文章!

  • 你可以在我的个人资料页面 找到我的其他文章🔬
  • 如果你喜欢并且想成为中级会员,你可以使用我的 推荐链接 来支持我👍

创建信用评分的额外资源

这本书缺少的一点是让你自己实现记分卡的代码示例。作者给出的例子都使用了 SAS 平台,这个平台对记分卡的发展有着重要的历史意义。但是,除非您的公司使用 SAS 环境,否则您可能需要使用其他语言实现逻辑。

好消息是,开源(或以非常便宜的价格)资源可以帮助你构建自己的记分卡。如果您是使用 Python 的数据科学家或开发人员,我强烈建议您查看以下资源:

A) OptBinning (Python 库)

由 Guillermo Navas Palencia 开发的这个库有一些强大的工具来执行变量的宁滨。Optbinning 提供了对证据权重、信息值和每个变量的其他重要指标进行可视化的方法,帮助您为模型选择最佳特征。OptBinning 最近加入了一个记分卡开发模块,使整个过程快速而稳定。对于使用 Python 的记分卡开发者来说,这可能是一个必看的项目!****

** [## 吉列尔莫-纳瓦斯-帕伦西亚/奥普宾宁

OptBinning 是一个用 Python 编写的库,它实现了一个严格而灵活的数学编程公式来…

github.com](https://github.com/guillermo-navas-palencia/optbinning)

Python 2020 中的信用风险建模(Udemy)

如果你刚刚开始使用记分卡,并使用 Python 作为你的主要编码语言,我强烈推荐你参加这个课程。解释信用评分背后的理论的视频具有很好的教育意义,并且每一步都是使用 Pandas、Scikit-Learn 和 Matplotlib 在 Python 中实现的。因此,在构建记分卡时,你会真正理解每种方法背后的逻辑。

[## Python 课程中的信用风险建模

嗨!欢迎学习 Python 中的信用风险建模。教你银行如何使用数据科学的唯一在线课程…

www.udemy.com](https://www.udemy.com/course/credit-risk-modeling-in-python/)**

书评:其他想法(1/2)

原文:https://towardsdatascience.com/book-review-other-minds-4176bd62edae?source=collection_archive---------64-----------------------

上午 12 点的对话

动物的大脑,我们的大脑,还有电脑的大脑…

阿什·埃德蒙兹在 Unsplash 上拍摄的照片

这个星期我想做一些不同的事情,分享一些我刚刚读完的一本书的想法。这本书名叫《T4:其他意识:章鱼、海洋和意识的深层起源》,作者是彼得·戈弗雷-史密斯。

我看过的所有关于这本书的书评都集中在章鱼有多聪明。这是有道理的,因为章鱼是这本书的主角,但我想说点别的。我想分享的一件事是,书中的一些概念如何奇怪地让我想起计算机科学中的概念。比如章鱼左右脑交流的方式,让我想起了 XG bosting 的优化。我们记忆系统的理论让我想起了数据结构。

还有一个是关于主观体验的话题,我很感兴趣的东西。作者对什么是主观体验进行了一次非常有趣的讨论。例如,当我们看到一种颜色和机器人看到一种颜色相比,为什么我们会认为它是不同的。我将用章鱼的例子来介绍这个话题,因为章鱼,伪装的大师,可以改变甚至比变色龙更多的颜色,是色盲。他们是怎么做到的?他们“看见”一种颜色吗?最后,我还想讨论一下,机器人是否有一天也能拥有主观体验。

列宁·埃斯特拉达在 Unsplash 上的照片

章鱼的大脑和 XG Boosting 的优化

我们都知道我们身体有左右两边,比如左脑和右脑,或者左手和右手。然而,大多数时候,我们只是把我们的大脑称为大脑,因为我们没有从左右两侧获得单独的信息。我们从左右两边作为一个整体得到一条连贯的信息。

但是在动物世界里这并不总是正确的。在一项使用九只鸟的研究中,其中八只不在左右脑之间传递信息(Godfrey-Smith,84)。例如,如果一只鸟用一只眼睛学习一个非常简单的技能,那么这只鸟只使用另一只眼睛进行测试,这只鸟将无法做到。(是啊..)

GIF via GIPHY

乍一看,你觉得这太疯狂了!但是,Giorgio Vallortigara 等动物研究人员指出,这实际上是有道理的。不同的任务需要不同类型的处理,所以最好有专门的方面,不要把它们彼此联系得太紧密。章鱼呢?

章鱼介于鸟类和我们之间。有些信息确实被传递了,但并不总是如此,而且这个过程并不像我们这样简单和同步。此外,章鱼也有许多遍布全身的神经元。这意味着章鱼的手臂可以看、感觉和思考…

它是这样工作的:章鱼的手臂可以随心所欲地做事情,不需要大脑的任何命令。大脑可能不知道手臂接触或学习了什么。而且,如果大脑想和手臂一起工作,它会向手臂发送信号,T2 希望手臂会配合。然而,当章鱼警觉时或在某些情况下,大脑似乎可以很好地控制手臂。整个章鱼就像我们一样作为一个整体一起工作。

我喜欢作者在书中的比喻。想象一下我们与呼吸的关系。当我们想要的时候,我们可以控制我们的呼吸,但是通常,我们不会注意到他们在做什么。

这与 XG boosting 算法有什么关系?

很多人把我们的大脑比作机器。我们知道,我们的大脑可以快速处理大量信息,具有非常高的计算能力。为了拥有这样的力量,大脑有 860 亿个神经元,是灵长类动物中最多的,它消耗了我们身体 20%的能量。这是一种昂贵的机器,大多数其他动物的大脑无法承受这样的功率。因此,他们找到了优化操作的方法。

将此放入算法的上下文中,找到最优解的一种方法是使用蛮力算法。该算法与贪婪算法形成对比。该算法保证全局最小值,这是贪婪算法所不能保证的,但是它很慢并且需要很高的计算能力。

决策树使用贪婪算法,经常会遇到过拟合的问题。虽然 XG Boosting 是一种基于树的算法,但它不会遇到这个问题,因为它实际上使用了一种强力算法。然而,即使在处理大型数据集时,它仍然可以高效运行。因为它实际上使用了半蛮力。我想称之为选择性蛮力,因为它在选择性样本上运行蛮力算法。(更多信息: XGBoost 第四部分:疯狂酷炫优化 )

这就是我如何把动物世界和三种算法联系起来的。我们的大脑就像是蛮力算法。它会自动进行大量计算并找到最佳解决方案。其他计算能力较低的动物大脑就像树算法。大脑的每一侧,或者说对于每一个不同类型的问题,它都会构建一个树算法来解决这个特定的问题。

说到章鱼,它们就像一个内置了许多优化工具的 XG boosting 算法。他们只传递一些信息,如果需要,他们会有意识地传递更多的信息。这样,大脑需要更少的计算能力,但仍然相当聪明。你知道当我读到章鱼的手臂会思考时让我想起了什么吗?那是 XG boosting 的并行学习…

GIF via GIPHY

人类记忆和计算机数据结构

书中谈到了英国心理学家艾伦·巴德利(Alan Baddeley)和格拉姆·希奇(Gramham Hitch)的名著《工作记忆模型》(model of working memory)。该模型认为,工作记忆是对少量信息的短期储存。当我们需要进行有意识思考/系统 2 思考时,我们会使用这些信息。

经过 simplypsychology.org 的麦克劳德 2012

你们中的一些人可能更熟悉短时记忆这个词。短时记忆和工作记忆都是指不储存在长时记忆中的记忆。STM 只强调信息的储存,但是工作记忆框架关注的是我们实际上是如何使用这些信息的。所以大致来说,工作记忆框架涵盖的范围更广。(更多信息: 关于工作记忆和短时记忆的区别 )

麦克劳德 2012 途经 simplypsychology.org

在工作记忆框架中,有三个组成部分:语音回路(P),视觉空间画板(V)和中央执行,c。P 部分处理口语和书面材料。V 部分处理视觉和空间信息。C 部分是确保一切顺利进行的控制中心。(更多信息: 工作记忆 )

从对短期记忆的研究中,我们知道我们的短期记忆储存了大约 7 个项目。所以,如果你想记住 10 个数字的电话号码,把它们分成 3 块:123-456-7890(啊哈!)

还记得任何以类似方式工作的数据结构吗?是哈希表 EE!!(更多信息: 下架哈希表 )

GIF via GIPHY

请这样想:我们可以储存在短期记忆中的 7 个项目就像是哈希桶。而中央执行部分的职责之一就是确保我们没有任何“冲突”。

在每个桶中,我们以数组的形式存储信息。这实际上也对应于当我们想要回忆一些事情时,我们的记忆是如何工作的。研究表明,短时记忆中的回忆是有顺序的,除非你已经知道它在序列中的位置。因此,为了回忆短期记忆,将事物按一定的顺序排列是有帮助的。就像在数组中搜索一个项目一样!

我们短时记忆的优缺点也像一个数组。它是为搜索而设计的,因为搜索很快,但它不适合存储大容量的内存。对于存储大容量内存,另一种数据结构,链表可以做得更好。

长期记忆的行为就像一个链表。长期记忆储存在我们大脑的不同地方,但短期记忆大多在前额叶皮层。从长期记忆中回忆,不是按顺序,而是通过联想。这就是为什么对于失去记忆的人来说,为了回忆,看看过去相关的事情会对他们有帮助。

长期记忆的储存空间仍然被认为是无限的。我怀疑它是无限的是因为长期记忆的空间客观上是如此之大,以至于我们还没有找到极限?或者是因为长期记忆可以有不同的大小,比如链表。因此,存储看起来是无限的。(更多信息: 总之什么是链表【第二部分】 )

timJ 在 Unsplash 上拍照

你可能想知道为什么我在谈论记忆系统,而这本书是关于章鱼的?这是因为作者试图理解为什么章鱼在没有明显原因的情况下不断改变它们的颜色。比如他们完全独处的时候。他怀疑这是一个类似于人类自言自语的想法。

拥有工作记忆就是当我们在头脑中说话时,人类能够听到我们自己的声音。这将我们与章鱼区分开来。章鱼被认为缺乏自言自语的能力。我将在下一篇博客中继续这个讨论,在这篇博客中,我想谈谈主观体验和高阶思想。

参考:

  • 巴尔斯,B . j .和 N M .盖奇。认知神经科学基础:初学者指南。n.p .:爱思唯尔学术出版社,2013 年。
  • 伯特温尼克,硕士;王;考恩,e;罗伊;巴斯蒂亚宁,c;P.J .梅奥;侯克,J.C. (2009 年)。“猕猴的即时系列回忆表现分析”。动物认知12(5):671–678。doi:10.1007/s 10071–009–0226-z。PMID1946 21 89。
  • 彼得·戈弗雷·史密斯。其他思维:章鱼、海洋和意识的深层起源。第一版。纽约:法勒,斯特劳斯和吉鲁,2016。打印。
  • McLeod,S. A. (2012 年)。工作记忆。单纯的心理学。https://www.simplypsychology.org/working%20memory.html
  • 页面,m;诺里斯博士(1998 年)。“首要模型:即时系列回忆的新模型”。心理复习。105(4):761–781。doi:10.1037/0033–295 x . 105 . 4 . 761–781。PMID 9830378。

有关更多信息:

  • XGBoost 第 4 部分:疯狂酷炫的优化 Josh Starmer
  • 从货架上取下哈希表,Vaidehi Joshi
  • 总之,什么是链表【第二部分】,Vaidehi Joshi
  • 关于工作记忆和短时记忆的区别,巴特·翁瑞迪、斯文·斯塔佩特和阿尔扬·布洛克兰
  • 工作记忆,艾伦·巴德利和格雷厄姆·j·希奇

书评推荐系统

原文:https://towardsdatascience.com/book-review-recommendation-system-5d9a4bd3eba7?source=collection_archive---------57-----------------------

照片由 Alfons Morales 在 Unsplash 上拍摄

书评的顺序应该个性化吗?

由 Sangeetha Veluru — 12 分钟阅读

我总是在购买一本书之前阅读书评,我经常发现自己不知道我应该给它们多少权重。就他们通常阅读的体裁以及他们如何评价这些体裁而言,评论者与我有多相似,因此他们的经历在多大程度上反映了我的经历?

Photo by 青 晨 on Unsplash

贝叶斯神经网络:在 TensorFlow 和 Pytorch 中 2 个完全连接

亚当·伍尔夫——11 分钟阅读

本章继续贝叶斯深度学习系列。在这一章中,我们将探索传统密集神经网络的替代解决方案。这些备选方案将调用神经网络中每个权重的概率分布,从而产生单个模型,该模型有效地包含基于相同数据训练的神经网络的无限集合。我们将用这些知识来解决我们这个时代的一个重要问题:煮一个鸡蛋需要多长时间。

照片由 Djim Loic 在 Unsplash 上拍摄

对计数数据使用负二项式

通过 Ravi Charan — 8 分钟阅读

负二项分布是一种离散概率分布,您的计数数据工具包中应该有这种分布。例如,您可能有关于某人在购买前访问的页面数量的数据,或者与每个客户服务代表相关的投诉或升级数量的数据。

我们的每日精选将于周一回归!如果你想在周五收到我们的 每周文摘 ,很简单!跟随 我们的刊物 然后进入你的设置,打开“接收信件”您可以在此 了解关于如何充分利用数据科学 的更多信息。

如果你是 Python 的新手(尤其是如果你是自学 Python 的话),请将此加入书签

原文:https://towardsdatascience.com/bookmark-this-if-you-are-new-to-python-especially-if-you-self-learn-python-54c6e7b5dad8?source=collection_archive---------3-----------------------

Python 中简单但有用的技巧和提示列表

在我们的调查中,增长最快的主要编程语言 Python 再次在编程语言中排名上升,今年超过 Java,成为第二大最受欢迎的语言(仅次于 Rust)。[1]

在 Unsplash 上由 Hitesh Choudhary 拍摄的照片

如果你是因为枯燥的隔离生活才开始接触 Python,那么恭喜你。你正在学习发展最快的主要编程语言。我相信你已经知道了 Python 的一些优点,比如它的简单、易学等。这些也是我五年前学习 Python 的主要原因。因为我希望你能更有效地学习 Python,并且能充分享受学习 Python 的乐趣,这里列出了一些简单但有用的技巧和提示。

提示:目前我正在使用 Python 3.8。如果您在学习我的示例时遇到任何问题,请检查这是否是因为您的 Python 版本。

目录

数值比较

条件返回语句

在列表/元组的一行语句中分配多个变量

列表理解

使用 zip 比较两个列表中的元素

使用 lambda 按第二个元素对嵌套数组进行排序

滤镜,贴图

检查列表中的所有元素是否唯一

字符串格式

列举

捕获数组的特定部分

形成组合和排列

价值比较

>>> a = 1
>>> b = 3
>>> a == 1
True
>>> a == 2
False
>>> a == b
False
>>> a > b
False
>>> a <= b
True
>>> if a <= b :
...     print('a is less than or equal to b')
...
a is less than or equal to b

您可以比较两个对象的值。该返回为真/假。可以在 if-else 语句中直接使用比较作为条件。

条件返回语句

代替

>>> def compare(a,b):
...     if a> b:
...             return a
...     else:
...             return b
...

可以将条件直接放在 return 语句中。

>>> def compare(a, b):
...     return a if a> b else b
...

在 list/tuple 语句的一行中分配多个变量

而不是:

>>> arr_list = [1,4,7]
>>> a = arr_list[0]
>>> b = arr_list[1]
>>> c = arr_list[2]

您可以在语句的一行中完成相同的赋值:

>>> a, b, c = arr_list
>>> a
1
>>> b
4
>>> c
7

列表理解

代替

>>> arr_list = [1,4,7]
>>> result = []
>>> for i in arr_list:
...     result.append(i*2)
...
>>> result
[2, 8, 14]

你可以

>>> result = [x*2 for x in arr_list]
>>> result
[2, 8, 14]

使用 zip 比较两个列表中的元素

代替

>>> a = [1,5,8]
>>> b = [3,4,7]
>>> result = []
>>> for i in range(len(a)):
...     result.append(a[i] if a[i]< b[i] else b[i])
...
>>> result
[1, 4, 7]

你可以

>>> result = [min(i) for i in zip(a,b)]
>>> result
[1, 4, 7]

使用 lambda 按第二个元素对嵌套数组进行排序

>>> arr_list= [[1,4], [3,3], [5,7]]
>>> arr_list.sort(key= lambda x: x[1])
>>> arr_list
[[3, 3], [1, 4], [5, 7]]

过滤器,地图

代替

>>> arr_list = [-1, 1, 3, 5]
>>> result = []
>>> for i in arr_list:
...     if i > 0:
...             result.append(i**2)
...
>>> result
[1, 9, 25]

你可以

>>> result = list(map(lambda x: x**2, filter(lambda x: x > 0, arr_list)))
>>> result
[1, 9, 25]

编辑:是我的错,用列表理解更好:)

谢谢奥列格·卡普斯汀和库尔迪普·帕尔。

>>> result = [i**2 for i in arr_list if i > 0]
>>> result
[1, 9, 25]

检查列表中的所有元素是否唯一

使用 set 从列表中移除重复的元素,然后测试列表和集合的长度是否相等

>>> arr_list = [1,4,4,6,9]
>>> len(arr_list) == len(set(arr_list))
False

字符串格式

Python 3.6 之前

>>> a, b, c = 1,5,9
>>> print('a is {}; b is {}; c is {}'.format(a,b,c))
a is 1; b is 5; c is 9

Python 3.6 及更高版本

>>> print(f'a is {a}; b is {b}; c is {c}')
a is 1; b is 5; c is 9

列举

代替

>>> arr_list = [1, 5, 9]
>>> for i in range(len(arr_list)):
...     print(f'Index: {i}; Value: {arr_list[i]}')
...
Index: 0; Value: 1
Index: 1; Value: 5
Index: 2; Value: 9

你可以

>>> for i, j in enumerate(arr_list):
...     print(f'Index: {i}; Value: {j}')
...
Index: 0; Value: 1
Index: 1; Value: 5
Index: 2; Value: 9

捕获数组的特定部分

>>> arr_list = [1,4,6,8,10,11]
>>> a, *b, c = arr_list
>>> a
1
>>> b
[4, 6, 8, 10]
>>> c
11

形成组合和排列

>>> str_list = ['A', 'C', 'F']
>>> list(itertools.combinations(str_list,2))
[('A', 'C'), ('A', 'F'), ('C', 'F')]
>>> list(itertools.permutations(str_list,2))
[('A', 'C'), ('A', 'F'), ('C', 'A'), ('C', 'F'), ('F', 'A'), ('F', 'C')]

虽然这些技巧相当简单,但它们可以帮助您节省不必要的步骤,使您的代码更简单。我希望你看完这篇文章后明白使用 Python 是多么简单。享受学习,享受编码。下次见。

(编辑:第 2 部分已经发布。进一步了解 Python 中的技巧和窍门。)

https://towards data science . com/bookmark-this-if-you-new-to-python-尤其是-if-you-self-learn-python-part-2-ab 3 ba 54 e 2 f 45

引用

[1]堆栈溢出开发者调查 2019 —堆栈溢出洞察,堆栈溢出,【https://insights.stackoverflow.com/survey/2019

(第 2 部分)如果您是 Python 的新手(尤其是自学 Python 的话),请将此加入书签

原文:https://towardsdatascience.com/bookmark-this-if-you-are-new-to-python-especially-if-you-self-learn-python-part-2-ab3ba54e2f45?source=collection_archive---------42-----------------------

提示和技巧的第二部分在这里。现在就学习这些来平滑你的编码吧!

首先,感谢大家支持我之前关于 Python 技巧和提示的文章。我不敢相信我的文章能吸引超过 12 万的浏览量。我希望你们都能从这篇文章中受益。如果你还没有读过第一本书,最好现在就读。

[## 如果你是 Python 的新手(尤其是自学 Python 的话),请将此加入书签

Python 中简单但有用的技巧和提示列表

towardsdatascience.com](/bookmark-this-if-you-are-new-to-python-especially-if-you-self-learn-python-54c6e7b5dad8)

在 Unsplash 上由 Hitesh Choudhary 拍摄的照片

为了奖励大家,这里是 Python 技巧和提示的第 2 部分。除了展示技巧和提示,我还会包括解释和链接,这样你就可以了解更多。

让我们继续我们的 Python 之旅。

目录

同时更新多个变量

从列表中返回一个长字符串

字符串格式化

下划线

关键字、关键字值、关键字项

两组对比

收藏。计数器

同时更新多个变量

代替

>>> a = 5
>>> b = 8
>>> temp = a
>>> a = b
>>> b = temp + a
>>> a
8
>>> b
13

您可以在一行中同时计算这两个变量。在这种情况下,您不需要创建临时变量。

>>> a = 5
>>> b = 8
>>> a,b = b, a+b
>>> a
8
>>> b
13

(PS:这是什么?斐波那契数列!)

更多信息:评估订单

从列表中返回一个长字符串

>>> str_list = ['This', 'is', 'WYFok']
>>> ' '.join(str_list)
'This is WYFok'

您可以使用 join 函数将所有元素(需要是字符串格式)组合成一个字符串。您需要决定每个元素之间的分隔符是什么

进一步应用

>>> ans_list = [3,6,9]
>>> 'The answer is '+','.join(map(str,ans_list))
'The answer is 3,6,9'

使用 map 函数,你可以把整数类型的元素转换成字符串,结合 join 函数,你可以得到一个新的字符串变量。

进一步信息: str.join ,地图

字符串格式

>>> pi = 3.14159
# Before Python3.6>>> print('The value of pi is {:.2f}'.format(pi))
The value of pi is 3.14# Python 3.6 and after 
>>> print(f'The value of pi is {pi:.2f}')
The value of pi is 3.14>>> pi
3.14159

字符串格式的一个优点是,您可以打印带有舍入的数值,而不会影响原始值的准确性。

更多信息: PyFormat

强调

通常,如果想重复一个步骤,可以使用如下的 for 循环:

>>> for i in range(3):
...     print('Hello')
...
Hello
Hello
Hello

但是,您可以看到变量“I”没有任何用法。在这种情况下,您可以使用下划线“_”来替换“I”。

>>> for _ in range(3):
...     print('Hello')
...
Hello
Hello
Hello

在这里,“_”是一个一次性变量。Python 不会在这个 for 循环中创建新变量。读者知道索引在 for 循环中是不必要的。

关键字,关键字值,关键字项

>>> teacher_subject = {'Ben':'English','Maria':'Math','Steve':'Science'}
>>> teacher_subject.keys()
dict_keys(['Ben', 'Maria', 'Steve'])
>>> teacher_subject.values()
dict_values(['English', 'Math', 'Science'])
>>> teacher_subject.items()
dict_items([('Ben', 'English'), ('Maria', 'Math'), ('Steve', 'Science')])

对于字典,可以使用键和值函数分别进行检索。对于 items 函数,可以同时检索键和值。当您需要切换键和值时,这很有用。

>>> subject_teacher = {y:x for x,y in teacher_subject.items()}
>>> subject_teacher
{'English': 'Ben', 'Math': 'Maria', 'Science': 'Steve'}

特别要注意的一点是,在切换过程中要小心重复的值。这将导致切换后元素丢失。

(额外:使用 zip,您可以从两个列表组成一个字典)

>>> subject = ['English','Math','Scienc']
>>> teacher = ['Ben','Maria','Steve']
>>> subject_teacher = {f:v for f,v in zip(subject,teacher)}
>>> subject_teacher
{'English': 'Ben', 'Math': 'Maria', 'Scienc': 'Steve'}

更多信息:映射类型—字典

两组的比较

>>> a = {1,2,3}
>>> b = {1,2,3,4,5}# Is a a subset of b?
>>> a<=b
True# Is a a superset of b?
>>> a>=b
False# Union of a and b 
>>> a.union(b)
{1, 2, 3, 4, 5}# Intersection of a and b 
>>> a.intersection(b)
{1, 2, 3}# Difference # Return elements in a but not in b 
>>> a.difference(b)
set()# Return elements in b but not in a
>>> b.difference(a)
{4, 5}

进一步信息:设置

收藏。计数器

当你想计算一个列表中所有元素的数量时,这很有用。您将收到一个类对象,显示列表中所有独特的元素及其各自的编号。

>>> import collections>>> arr_list = [1,1,1,1,2,2,2,3,3,5,5,5,7]
>>> c = collections.Counter(arr_list)
>>> c
Counter({1: 4, 2: 3, 5: 3, 3: 2, 7: 1})
>>> type(c)
<class 'collections.Counter'>
>>> c[1]
4
>>> c[6]
0# Convert back to a dictionary
>>> dict(c)
{1: 4, 2: 3, 3: 2, 5: 3, 7: 1}

更多信息:收藏。计数器

我希望在阅读完这篇文章后,你能进一步了解 Python 的简单性。享受学习,享受编码。下次见。

我的其他文章

Web Scrape Twitter by Python Selenium(第 1 部分)

Web Scrape Twitter by Python Selenium(第二部分)

运载数据分析演示(纽约市 Airbnb 开放数据)

如何用熊猫分析数值型数据?

通过标准化和规范化将机器学习性能提高 30%

原文:https://towardsdatascience.com/boost-machine-learning-performance-by-30-with-normalization-and-standardization-156adfbf215b?source=collection_archive---------44-----------------------

如果您不扩展您的数据,就等于放弃了性能

照片由像素的像素拍摄

预处理是机器学习管道中最被低估的方面。

特征缩放,将特征值控制在相似的数字尺度上,是其中的关键组成部分。

当数据没有缩放时,计算距离或相似性的模型表现不佳。这包括 KNN 和 SVM。

我将演示 KNN 的缩放数据如何将准确度从 72%提高到 96%。

如果您不扩展输入数据,您就放弃了轻松的性能提升。

我们将用 3 种方法解决一个简单的 ML 问题,比较结果,然后解释为什么缩放有效:
1)无缩放
2)缩放:标准化
3)缩放:标准化
4)为什么缩放可以提高性能

基本情况

在这里,我们将解决一个没有任何缩放的分类问题。

从 Kaggle 下载葡萄酒数据集。这是一个简单的数据集,我们在其中预测葡萄酒的品种(例如:cab sauv,merlot,riesling)。

import pandas as pdimport numpy as np
import pandas as pddf = pd.read_csv('Wine.csv', names=[
    'Class', 'Alcohol', 'Malic acid',
    'Ash', 'Alcalinity of ash', 'Magnesium',
    'Total phenols', 'Flavanoids',
    'Nonflavanoid phenols', 'Proanthocyanins',
    'Color intensity', 'Hue',
    'OD280/OD315 of diluted wines', 'Proline'])df.iloc[np.r_[0:2, -2:0]]

快速检查数据的形状。

df.describe()

df.hist(figsize=(25, 15))

观察特征在完全不同的比例上。酒精11.0314.83不等,而非黄酮类酚类0.130.66不等。

这应该会给你数据科学中的代码味道。不同的比例会混淆模型。

但是让我们用逻辑回归来分析一下。

# helper functionsimport numpy as np
from sklearn.model_selection import StratifiedShuffleSplit
from sklearn.neighbors import KNeighborsClassifierdef dataframe_to_X_and_y(df):
    X = np.asarray(
        df[['Alcohol','Malic acid','Ash',
            'Alcalinity of ash','Magnesium',
            'Total phenols','Flavanoids',
            'Nonflavanoid phenols',
            'Proanthocyanins','Color intensity',
            'Hue','OD280/OD315 of diluted wines',
            'Proline']])

    y = np.asarray(df[['Class']])

    return X, ydef split_data(X, y):    
    splitter = StratifiedShuffleSplit(n_splits=1, test_size=0.3, random_state=0)for train_index, test_index in splitter.split(X, y):
        X_train, X_test = X[train_index], X[test_index]
        y_train, y_test = y[train_index], y[test_index]return X_train, X_test, y_train, y_testdef fit_and_predict(X_train, y_train, X_test):
    classifier = KNeighborsClassifier()
    classifier.fit(X_train, y_train)
    y_pred = classifier.predict(X_test)

    return y_pred

对数据进行分类和评估。

X, y = dataframe_to_X_and_y(df)
X_train, X_test, y_train, y_test = split_data(X, y)
y_pred = fit_and_predict(X_train, y_train, X_test)from sklearn.metrics import classification_report
print(classification_report(y_test, y_pred))

这导致了 72%的准确率。不可怕,但我打赌我们可以通过扩展做得更好。

正常化

什么是正常化

归一化也叫做“最小-最大缩放”,但我认为“挤压”这个术语更直观。

它强制数据在 0 和 1 之间的范围内,最低特征值为 0,最高特征值为 1。

归一化后,所有要素的值都将在此范围内。例如,比较标准化前后的Total phenols数据。

attribute = 'Total phenols'
df_copy = df.copy()
df_copy = df_copy[[attribute]]
df_copy.hist()

以前

from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
df_copy[[attribute]] = scaler.fit_transform(df_copy[[attribute]])
df_copy.hist()

在...之后

请注意,在后者中,没有值低于 0 或高于 1。

这种缩放算法的一个缺点是,一个巨大的正异常值将变为 1,并将所有其他值挤到接近于 0。

例如,[1,2,10]会变成[0.00, 0.11 ,1.00]

分类问题

回到我们上面解决的那个分类问题。这一次,我们将在进行预测之前对数据进行归一化处理。

df_copy = df.copy()
X, y = dataframe_to_X_and_y(df_copy)
X_train, X_test, y_train, y_test = split_data(X, y)from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)y_pred = fit_and_predict(X_train, y_train, X_test)from sklearn.metrics import classification_report
print(classification_report(y_test, y_pred))

96%.这是一个巨大的进步!这是规范化数据帮助模型解决问题的一个很好的例子。

标准化

什么是标准化?

标准化减去平均值,然后除以样本方差,因此平均值为零,分布具有单位方差。

z = (x — u) / s

其中u是训练样本的均值,如果with_mean=False为 0,s是训练样本的标准差,如果with_std=False为 1。

  • Sklearn 文档

请注意下面应用标准化前后的比例差异。

attribute = 'Hue'
df_copy = df.copy()
df_copy = df_copy[[attribute]]
df_copy.hist()

以前

from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
df_copy[[attribute]] = scaler.fit_transform(df_copy[[attribute]])
df_copy.hist()

在...之后

分类问题

让我们解决同样的分类问题,但这一次我们将在进行预测之前对值进行标准化。

df_copy = df.copy()
X, y = dataframe_to_X_and_y(df_copy)
X_train, X_test, y_train, y_test = split_data(X, y)from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)y_pred = fit_and_predict(X_train, y_train, X_test)from sklearn.metrics import classification_report
print(classification_report(y_test, y_pred))

这也做到了!

为什么扩展可以提高性能?

缩放不会改进所有模型的预测。但是对于那些利用距离/相似性计算的人来说,这可能会有很大的不同。

假设我们正在根据购买价格(1000 美元)和行驶距离(公里)来比较二手车。

pd.DataFrame(
  {'purchase_price': [20, 25, 80], 
   'distance_driven': [10000,15000,11000]}
)

虚构数据

你可以看到一些距离的计算(虽然不是全部)会被distance_driven严重扭曲,因为它更大,即使purchase_price可能是相似性的更强指标。

结论

我们介绍了一个例子,其中缩放将 KNN 分类器的性能提高了 30%以上。虽然我们可以尝试其他模型,但扩展应该是标准做法。

即使缩放不能提高性能(例如:逻辑回归),它也能使系数更容易解释。

增强熊猫数据框架

原文:https://towardsdatascience.com/boost-up-pandas-dataframes-46944a93d33e?source=collection_archive---------50-----------------------

优化数据框架的使用

作者图片

作为21 世纪的数据分析师或数据科学家,最基本的、被所有人广泛使用的框架是——熊猫!借助内存处理能力和数据帧的使用,Pandas 让生活变得更加轻松。与将整个数据集转储到 SQL 数据库中并使用 SQL 查询来查询数据库以查看输出相反,现在我们只读取 pandas df 中的数据集文件。所有这些繁琐的过程现在都被熊猫 数据框所取代。

除了 pandas,还有更好的选择,可以通过优化 Pandas 的工作流程来进一步提高您的计算能力。这里有一些功能强大的替代品,易于安装,并允许您提高您的工作流程!

系好安全带,这将是一次颠簸的旅程

来源:吉菲

摩丁

厌倦了在处理大型数据帧时的漫长等待时间?— 摩丁来救援了!

摩丁使用 Ray 或 Dask 来提供一种毫不费力的方式来加速你的熊猫笔记本、脚本和库。与其他分布式数据框架库不同,Modin 提供了与现有 pandas 代码的无缝集成和兼容性。即使使用 DataFrame 构造函数也是一样的。

摩丁用一行代码的改变加速你的熊猫工作流程

安装

Modin 是加州大学伯克利分校 RISELab 的完全开源项目。这是该项目的 GitHub 链接

[## 摩丁-项目/摩丁

要使用 Modin,替换熊猫导入:Modin 可以从 PyPI 安装:如果你没有安装 Ray 或 Dask,你…

github.com](https://github.com/modin-project/modin)

可以通过 PyPI 快速安装 Modin:

pip install modin

用法

使用 Modin 就像使用 Pandas dataframe 一样简单。把熊猫当 pd 换成 modin.pandas 当 pd 就行了。

# import pandas as pd
import modin.pandas as pd

你都准备好了!使用具有增强计算能力和更快速度的数据帧优化您的 pandas 工作流程:)

达斯克

需要比摩丁更快的处理能力?—向达斯克问好!

Dask.distributed 是一个用于 Python 分布式计算的轻量级库。Dask.distributed 是一个集中管理的分布式动态任务调度程序。中央dask-scheduler进程协调分布在多台机器上的几个dask-worker进程的动作以及几个客户机的并发请求。

安装

Dask 也是一个开源框架,由他们的开发者积极维护。这是他们 GitHub 链接上的源代码:

[## 达斯克/达斯克

带有任务调度的并行计算。在 GitHub 上创建一个帐户,为 dask/dask 开发做贡献。

github.com](https://github.com/dask/dask)

Dask 可以使用 pip 轻松安装:

python -m pip install dask distributed --upgrade

光线

想要释放分布式计算的力量吗?—欢迎雷!

Ray 与 TensorFlow、PyTorch、MXNet 等深度学习框架完全兼容,在很多应用中很自然地会与 Ray 一起使用一个或多个深度学习框架(比如我们的强化学习库大量使用 TensorFlow 和 PyTorch)。

摩丁使用射线来提供一种毫不费力的方式来加速熊猫的笔记本、脚本和库。Ray 是一个高性能分布式执行框架,目标是大规模机器学习和强化学习应用。

安装

Ray 也是一个开源项目。这是 Ray 的 GitHub 链接:

[## 光线-投影/光线

Ray 是一个快速而简单的框架,用于构建和运行分布式应用程序。雷被包装成…

github.com](https://github.com/ray-project/ray/)

可以通过以下命令使用 pip 快速安装 Ray:

pip install ray

PySpark

想要利用内存中的处理能力吗?— PySpark 正是正确的选择!

PySpark 是一种很好的语言,可以进行大规模的探索性数据分析,构建机器学习管道,为数据平台创建 ETL。PySpark 使用内存计算能力,使数据帧比以往更快。Spark 数据帧是数据科学家和数据工程师的首选,因为它们通过用内存资源取代计算能力来提高速度,并且提供了连接外部框架的巨大灵活性

安装

Spark 由 Apache 维护,是一个开源框架,拥有活跃的开发人员社区。下面是 GitHub 上 Spark 的源代码:

[## 阿帕奇/火花

Spark 是用于大规模数据处理的统一分析引擎。它提供了 Scala、Java……

github.com](https://github.com/apache/spark)

使用以下命令可以很容易地安装 Spark:

确保您的机器上安装了 Java :

brew cask install java

由于 spark 是用 Scala 编写的,我们需要包含 Scala 依赖关系:

brew install scala

最后,在安装完所有依赖项后,使用以下命令安装 PySpark :

brew install apache-spark

用法

产生火花就像下面这样简单。就像摩丁一样,spark 和熊猫也有语法上的差异

df = spark.read.json("examples/src/main/resources/people.json")

迷茫?

来源:吉菲

对很多选项感到困惑?别担心。只需分析您正在处理的数据集并选择合适的框架。假设您正在处理一个只有几个字节的数据集——选择 Modin 将是一个不错的选择,因为您可以最大限度地发挥笔记本电脑的潜力。但是,让我们假设您正在处理一个 ETL 管道,其中摄取的数据非常巨大。在这种情况下, PySpark 会完成这项工作,但是您可能会想到一个替代框架,比如 Ray ,在这个框架中,您可以将负载分布到一个机器集群上,并充分利用并行计算!

请随意评论更好的选择和您的建议,使熊猫数据帧更快!

参考

[1]https://www.kdnuggets.com/2019/11/speed-up-pandas-4x.html

https://github.com/modin-project/modin

[3]https://github.com/ray-project/ray

https://modin.readthedocs.io/en/latest/

https://github.com/apache/spark

用这 6 个小窍门提高你的效率

原文:https://towardsdatascience.com/boost-your-efficiency-with-these-6-numpy-tricks-29ca2fe81ecd?source=collection_archive---------23-----------------------

并控制您的阵列

动机

有时,当我向我的朋友展示我使用的一些数字方法时,他们会发现它们很有帮助。所以我决定分享这些数字方法(或技巧),希望你也会发现它们很有帮助。

照片由 Pop &斑马在 Unsplash 上拍摄

从导入 Numpy 开始

import numpy as np

面具

假设我们有一个数组,我们想在这个数组中选择一个特定的元素:0,2,并删除其他元素。有没有一种快速的方法可以选择这两个元素?口罩就可以了。

>>> A = np.array([0, 1, 2, 3, 4, 5])>>> mask = np.array([True, False, True, False, False, False])>>> A[mask]array([0, 2])

我们可以看到,标记为False的元素被删除,而标记为True的元素被保留。

随意

创建快速随机数组是测试代码的一种有用且快速的方法。但是有不同的np.random方法,你可能想要选择一种而不是另一种来用于特定的用途。

用 0 到 1 范围内的给定形状创建随机值

>>> np.random.rand(10,2)array([[0.38850622, 0.31431385],        
      [0.00815046, 0.13334727],        
      [0.47482606, 0.92837947],        
      [0.89809998, 0.38608183],        
      [0.25831955, 0.56582022],        
      [0.36625782, 0.52753452],        
      [0.88125428, 0.71624809],        
      [0.83642275, 0.79315897],        
      [0.27361664, 0.8250761 ],        
      [0.89894784, 0.95994016]])

或者创建特定范围内具有特定大小的随机整数数组

>>> np.random.randint(0,10,(3,3))array([[0, 9, 6],        
      [1, 7, 3],        
      [6, 4, 7]])

类形状阵列

你有没有发现自己创建了第二个数组,它的尺寸与第一个数组的尺寸相同,但元素不同?通常的做法是使用shape来捕捉第一个数组的维度

>>> A = np.random.randint(0,10,(3,3))>>> A.shape(3, 3)>>> B = np.zeros(A.shape)array([[0., 0., 0.],        
       [0., 0., 0.],        
       [0., 0., 0.]])

这种方法没有错。但是有一个更快的方法来创建一个类似的数组,用 0 或 1 作为元素,用zeros_likeones_like

>>> A = np.random.randint(0,10,(3,3))>>> B = np.zeros_like(A)>>> Barray([[0., 0., 0.],        
       [0., 0., 0.],        
       [0., 0., 0.]])>>> B = np.ones_like(A)>>> Barray([[1, 1, 1],        
       [1, 1, 1],        
       [1, 1, 1]])

正如我们所见,数组 B 与数组 A 的维数相同,但元素不同。

使再成形

如果我们想改变一个数组的维数,reshape将是我们要使用的方法

>>> A = np.arange(9)>>> Aarray([0, 1, 2, 3, 4, 5, 6, 7, 8])#Reshape to 3x3 matrix>>> A.reshape((3,3))>>> Aarray([[0, 1, 2],        
       [3, 4, 5],        
       [6, 7, 8]])

或者展平

>>> A.reshape(-1)array([0, 1, 2, 3, 4, 5, 6, 7, 8])>>> A.flatten()array([0, 1, 2, 3, 4, 5, 6, 7, 8])

reshape(-1)flatten()将完成展平阵列的工作。

变换超出范围数组

假设我们有一个范围从-3 到 6 的矩阵 B

>>> B = np.arange(-3,9).reshape((3,4))>>> Barray([[-3, -2, -1,  0],        
       [ 1,  2,  3,  4],        
       [ 5,  6,  7,  8]])

但是我们只想保持元素的范围从 0 到 5,并将超出范围的元素转换为范围内的元素。我们如何做到这一点?这时我们需要np.clip

>>> np.clip(B,0, 5)array([[0, 0, 0, 0],        
       [1, 2, 3, 4],        
       [5, 5, 5, 5]])

从变换后的矩阵可以看出,0 以下的元素变换为 0,5 以上的元素变换为 5,而范围内的元素保持不变。

洗牌

有时,我们希望使用随机数组,但我们的数组可能不是随机的。想想一副牌,当我们怀疑牌可能以特殊方式排序时,我们会怎么做?我们洗牌!

>>> A = np.arange(9).reshape((3,3))>>> Aarray([[0, 1, 2],        
       [3, 4, 5],        
       [6, 7, 8]])>>> np.random.shuffle(A)>>> Aarray([[3, 4, 5],        
       [0, 1, 2],        
       [6, 7, 8]])

正如我们所看到的,数组 A 中的元素与原始元素的位置不同。

结论

我希望这篇文章有助于为您的数据科学和编程实践添加一些新的 Numpy 技巧。拥有几个有用的方法来操作数组将极大地提高您的工作流程,并为您提供转换数组以满足特定需求的灵活性。

在 this Github repo 中,您可以随意使用本文的代码。

我喜欢写一些基本的数据科学概念,并尝试不同的算法和数据科学工具。你可以通过 LinkedIn 和 Twitter 与我联系。

如果你想查看我写的所有文章的代码,请点击这里。在 Medium 上关注我,了解我的最新数据科学文章,例如:

[## 字典作为 If-Else 的替代

使用字典创建一个更清晰的 If-Else 函数代码

towardsdatascience.com](/dictionary-as-an-alternative-to-if-else-76fe57a1e4af) [## 如何用 Faker 创建假数据

您可以收集数据或创建自己的数据

towardsdatascience.com](/how-to-create-fake-data-with-faker-a835e5b7a9d9) [## 跟踪数据的 Python 技巧

如何用列表、字典计数器和命名元组来跟踪信息

towardsdatascience.com](/python-tricks-for-keeping-track-of-your-data-aef3dc817a4e) [## 高效 Python 代码的计时

如何比较列表、集合和其他方法的性能

towardsdatascience.com](/timing-the-performance-to-choose-the-right-python-object-for-your-data-science-project-670db6f11b8e) [## cy thon——Python 函数的加速工具

当调整你的算法得到小的改进时,你可能想用 Cython 获得额外的速度,一个…

towardsdatascience.com](/cython-a-speed-up-tool-for-your-python-function-9bab64364bfd)

增强你对助推的把握🚀

原文:https://towardsdatascience.com/boost-your-grasp-on-boosting-acf239694b1?source=collection_archive---------64-----------------------

揭秘著名的竞赛获奖算法。

比尔·杰伦在 Unsplash 上的照片

boosting 的普及是应用机器学习的重大突破。得益于多个软件包,boosting 天生易于实现,同时在许多任务上实现高性能,已经成为许多人的默认首选方法。在工业中,它被用来制造有价值的产品,被围棋大师用来赢得比赛。在本文中,我们将详细讨论升压。

请继续阅读,了解:

  • 虽然最初令人生畏,但助推实际上很容易理解。
  • 只需几行代码就可以实现不同的增强风格。
  • 是什么让一个好的弱学习者得到提升,为什么树是一个普遍的选择。
  • 自适应增强和梯度增强的区别。
  • 你可以调整哪些旋钮来优化升压算法。

什么是助推?

Boosting 是一种集成技术,它将多个被称为“弱学习者”的顺序拟合的简单模型聚合成一个“强学习者”模型。本质上,增强预测只是弱学习者预测的加权平均,例如:

  1. 较好的弱学习者获得较大的权重,
  2. 当拟合时,每个弱学习者优先考虑被前一个错误预测的观察,从而专注于最困难的情况。

就这么简单。

特定的提升算法,比如我们马上要谈到的自适应或梯度提升,主要区别在于如何计算弱学习者的权重,以及如何对最困难的观察进行优先排序。

自适应增压

从实际的角度来看,从历史的角度来看,让我们看看第一个 boosting 算法。自适应增强,也称为 AdaBoost,早在 1997 年就被提出。它最初是为分类任务设计的,后来才扩展到回归设置。为了更加集中,我们将分析分类案例。

AdaBoost 的想法是使用样本权重来拟合弱学习者。我们从每个具有相同权重的观察开始,随着连续弱学习者的建立,观察权重得到更新,以将更多的重点放在困难的情况上。下面的模式概述了在单个自适应增强迭代中会发生什么。希望它能把这一点讲清楚。

自适应增压程序。

一旦合适了所需数量的弱学习器,就可以通过简单地对它们的预测进行平均来获得最终的预测,这些预测由各自的模型权重进行加权。

我们自己编码吧!我们的弱学习器将是简单的决策树,我们将对垃圾邮件数据集应用 AdaBoost,其中的任务是根据一组描述电子邮件中使用的词频的特征将电子邮件分类为垃圾邮件或非垃圾邮件。数据以及加载和处理数据的代码都可以在这里获得。现在,你只需要知道我们有一个二进制目标,对于垃圾邮件编码为 1,对于非垃圾邮件编码为-1,还有一组功能,25%的数据已经作为测试集放在一边。

下面的代码遵循上面的模式。为了编程方便,我们将在每次迭代中添加加权弱学习者的预测,将累积和存储在加权 _ 测试 _ 预测 _ 和变量中。此外,每次迭代我们将评估当前的性能,以便我们可以看到它如何随着提升迭代的数量(即弱学习者的数量)的增加而提高。

Final accuracy 0.945

让我们画出测试精度在提升迭代中的图。

AdaBoost:测试 boosting 迭代的准确性

我们拟合的第一棵树(具有相等的观察权重)获得了大约 79%的准确度。然后,随着提升迭代次数的增加,精确度也在增加,尽管速度在下降。经过 500 次迭代,我们达到了几乎 95%的准确率!但是你有没有想过为什么我们使用决策树作为我们的弱学习器?

哪些是最好的弱学习者,为什么?

要回答这个问题,我们首先需要讨论一种叫做偏差-方差权衡的现象。简而言之:如果预测模型是错误的,这可能是由于以下三个因素之一:

  • 当模型不够复杂,无法捕捉数据中的关系时,就会出现偏差(或拟合不足);
  • 当模型过于复杂、熟记训练数据并且在看不见的数据上表现不佳时,会出现方差(或过度拟合);
  • 我们无能为力的无法解释的错误。

在大多数机器学习模型中,倾向于在偏差和方差之间进行权衡。也就是说,具有高方差的模型通常具有低偏差,反之亦然。 Boosting 通过拟合专注于解决难题的连续模型,旨在减少偏差。因此,可以从提升中受益最多的弱学习者候选是那些具有低方差(期望的)和高偏差(将在提升过程中减少)的学习者候选。

好吧,那么什么样的模型符合这些标准呢?线性回归,一个人能想到的最基本的模型呢?根据定义(和一些假设),线性回归的普通最小二乘估计量是无偏的,例如:偏差可以显示为恰好为零。因此,它不是一个很好的候选人。

决策树呢?你可能已经注意到我们是如何在上面的 AdaBoost 代码中适应弱学习者的:

model = DecisionTreeClassifier(max_depth=1)

通过限制树的深度,我们不允许它变得太复杂以至于超出数据的范围;不仅如此:它不可能变得足够复杂以适应数据。这样,我们就有了一个低方差(没有能力过度拟合)和潜在高偏差(过于简单,无法捕捉数据中的信息)的学习者。这是升压的理想情况,我们已经看到它提高了多少精度。

为了验证以上所说的,让我们试着不要限制树。让我们对以下弱学习者运行相同的 AdaBoost 代码:

model = DecisionTreeClassifier()

我们期望什么?我们的弱学习器现在将是一个过拟合模型,即高方差、低偏差。因此,我们预计提振不会带来多少改善。这是测试精确度在提升迭代中的曲线图。

AdaBoost:使用过拟合弱学习器测试 boosting 迭代的准确性

正如预期的那样,AdaBoost 将过度拟合的弱学习器的准确率提高了约 1.5 个百分点,达到 92%。这发生在最初的几次迭代中,随后没有进一步的改进。与之前弱学习者的更好选择相比。在那里,准确率提高了大约 15 个百分点,几乎达到 95%。

总而言之,我们已经说过,好的弱学习者是那些对数据拟合不足的人。受限树是好的,复杂树和线性回归就不那么好了。其他低方差、高偏差模型呢?你也可以提升它们,但是树是最受欢迎的。其原因如下:

  • 即使数据量增加,树也能快速适应和扩展。这一点很重要,因为在推进过程中,每个弱学习者都需要前一个学习者的输入来改进它。因此,模型必须按顺序拟合,不能并行计算。如果一个模型需要很长时间才能适应,那么提升许多模型将需要很长时间。
  • 树拥有许多属性,使它们适用于杂乱的数据,而不需要太多的数据预处理。例如,他们对各自预测因子的尺度和应用于它们的单调变换漠不关心。它们还可以自动处理不同的变量类型,并通过构造对异常值和无用预测值具有鲁棒性。

现在让我们来看看另一种提升树木的方法!

梯度推进

梯度推进是另一种推进方式。与自适应增强类似,它也输出弱学习者预测的加权平均值。主要区别在于,AdaBoost 在迭代过程中更新观测值权重,而梯度提升则更新观测值本身。

程序如下。我们需要从训练数据的一些预测开始。因为在拟合任何模型之前,我们没有模型,我们简单地用目标的样本均值初始化它们。然后,我们重复下面的多次。我们计算相对于当前预测的损失函数的负梯度。下面的代码使用了均方误差损失的梯度,这对于二进制分类来说不是最佳的,但是我们使用它来保持简单。然后,我们将回归树拟合到这些负梯度,并将该树的拟合值(可能乘以某个学习率)添加到我们在开始时初始化的累积训练集预测中。一旦运行了期望数量的提升迭代,我们就可以提取最终的预测。因为我们的目标被编码为-1 或 1,我们简单地取累积预测的符号。

下面的模式概述了在使用树作为弱学习器的单个梯度提升迭代中发生的情况。希望它能把这一点讲清楚。

梯度推进程序

我们来编码吧!与前面的 AdaBoost 代码片段一样,这里我们也在 boosting 迭代中计算测试数据的预测,并在之后绘制。

Final accuracy 0.933

梯度增强:测试增强迭代的准确性

我们已经获得了与 AdaBoost 相似的精度。据推测,使用比 MSE 更合适的损失函数会改善结果。

参数化升压算法

您可能已经注意到,在梯度推进代码中,我们使用了一个名为学习率的超参数,我们将其设置为 1。因为它作为乘法因子进入等式,所以值 1 会影响结果。如果我们将其设置为 0.1,那么最终的精度将会提高 1 个百分点。自己随便玩吧!

在任何升压算法中,还有更多可以参数化的东西。然后可以调整这些参数来优化性能。在不涉及太多细节的情况下,让我列举其中的一些。这绝不是一个详尽的集合。

  • 学习率:我们可以用一个介于 0 和 1 之间的因子来衡量每棵树对整体的贡献,以避免过度拟合。这在精神上有点类似于在岭回归中加入收缩。对于较小的学习率,我们可能需要增加提升迭代的次数。
  • 提升迭代的次数:太大可能导致过度拟合,太小可能阻止提升算法达到最佳性能。
  • 子采样行:在梯度推进模型中,可以让弱学习者适应数据的引导样本,而不是实际数据。bootstrap 样本是从原始数据行中替换抽取的样本。这往往会使模型更好地概括。
  • 子采样列:在每次迭代中使用随机选择的特征列来拟合弱学习者。
  • 所有弱学习者的参数。在树的情况下:最大树深度,在树的叶节点上进一步划分所需的最小损失减少,等等。

简单地

  • Boosting 是一种集成技术,它将多个被称为“弱学习者”的顺序拟合的简单模型聚合成一个“强学习者”模型。这个组合基本上是弱学习者预测的加权平均。
  • 升压有利于减少偏差。因此,要提升的理想弱学习者是那些具有高偏差和低方差的学习者,即简单的欠拟合模型。一个流行的选择是约束树模型。
  • 增强的两种主要方式是自适应增强和梯度增强。
  • 自适应增强使用样本权重使弱学习者适应数据。在整个过程中,权重会更新,以便将更多的注意力放在最难正确预测的观察结果上。
  • 梯度提升使弱学习器不适合原始数据,而是适合损失函数相对于当前预测的负梯度。后者随着迭代而更新。
  • 为了优化 boosting 算法的性能,可以调整多个超参数,这些超参数定义了弱学习者如何学习以及它们具体适合哪些数据。

感谢阅读!我希望你已经学到了一些有用的东西,将推动你的项目🚀

如果你喜欢这篇文章,试试我的其他文章。不能选择?从这些中选择一个:

[## 线性回归中收缩法和选择法的比较

详细介绍 7 种流行的收缩和选择方法。

towardsdatascience.com](/a-comparison-of-shrinkage-and-selection-methods-for-linear-regression-ee4dd3a71f16) [## 线性分类器:综述

本文讨论了四个流行的线性函数的数学性质和 Python 的实际应用

towardsdatascience.com](/linear-classifiers-an-overview-e121135bd3bb) [## 插补的不确定性

你在预测中考虑到它了吗?

towardsdatascience.com](/uncertainty-from-imputation-8dbb34a19612)

来源

  1. Hastie,Tibshirani,r .,,j . h . Friedman(2009 年)。统计学习的要素:数据挖掘、推理和预测。第二版。纽约:斯普林格。

使用这些神奇的库来提高模型的性能

原文:https://towardsdatascience.com/boost-your-models-performance-with-these-fantastic-libraries-8dc10579b7ff?source=collection_archive---------20-----------------------

将 XGBoost 和 CatBoost 应用到您的机器学习模型中!

质量取决于准确性和完整性。

公司使用机器学习模型来做出实际的商业决策,更准确的模型结果会带来更好的决策。错误的代价可能是巨大的,但是优化模型精度可以降低这种代价。机器学习模型准确性是一种衡量标准,用于根据输入或训练数据确定哪个模型最擅长识别数据集中变量之间的关系和模式。一个模型越能概括“看不见的”数据,它就能产生越好的预测和洞察力,从而带来更多的商业价值。

谷歌图片

癌症预测数据集

我选择的数据集是乳腺癌预测数据集。我们需要预测癌症是恶性的还是良性的。每一行对应一个患者,对于这些患者中的每一个,我们有几个特征,从凝块厚度,细胞大小的均匀性等。所有这些特征都是肿瘤的特征。如果我们得到 2 级,结果是良性的,如果我们得到 4 级,结果是恶性的。所以类别变量成为我们的因变量,告诉我们它是良性的还是恶性的。我已经建立了决策树模型,并实现了 95.3%的准确率,这是与其他分类模型相比最高的。

在这之后,我建立了 XGBoost 模型,我在同一个数据集上对它进行了训练,我想看看准确性是否跨越了决策树分类模型。我不仅在测试集上训练了它,而且还使用了 K-fold 交叉验证,我们将在 10 个测试集上测试它,以便我们可以获得相关的准确性度量。

现在让我们开始实施吧!

**Importing the libraries**import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

首先,我们导入实现所需的库。

**Importing the dataset**dataset = pd.read_csv('/content/Data.csv')
X = dataset.iloc[:,:-1].values
y = dataset.iloc[:,-1].values

x 包含患者的所有特征,并由所有独立变量组成。y 包括因变量,即类别变量。

**Splitting the dataset into Training set and Test set**from 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)

接下来,我们将数据集分为训练集和测试集,前者用于训练模型,后者用于评估结果。

在此之后,我们建立了三个不同的模型,并比较了所有模型的准确性。

决策树分类

谷歌图片

**Feature Scaling**from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)

由于变量值的范围变化很大,我们需要应用特征缩放,以便所有变量都缩小到一个可比较的范围。我们只需要对决策树分类应用特征缩放,而不需要对 XGBoost 和 CatBoost 应用特征缩放。

**Training the Decision Tree Classification model on the Training set**from sklearn.tree import DecisionTreeClassifier
dtc = DecisionTreeClassifier(criterion = 'entropy', random_state = 0)
dtc.fit(X_train, y_train)

导入 DecisionTreeClassifier 类,然后创建该类的一个实例。然后应用拟合函数在训练集上训练模型。

**Making the Confusion Matrix for Decision Tree**from sklearn.metrics import confusion_matrix, accuracy_score
y_pred = dtc.predict(X_test)
cm = confusion_matrix(y_test, y_pred)
print(cm)
accuracy_score(y_test, y_pred)[[103   4]
 [  3  61]]0.9590643274853801

从度量模块导入混淆矩阵和准确度分数函数。

混淆矩阵显示出来,accuracy_score 给出了我们模型的准确度。这个模型的准确率我已经达到了 95.9%。

当我们在不同的测试集上测试我们的模型的性能时,我们获得了不同的精度。这就是为什么我们找到 10 个精度,然后取所有这些精度的平均值,找到我们模型的最佳精度。所以这种方法被称为 K 重交叉验证法。

**Applying the K-Fold Cross Validation for Decision Tree**from sklearn.model_selection import cross_val_score
accuracies = cross_val_score(estimator = dtc, X = X_train, y = y_train, cv = 10)
print("Accuracy:{:.2f} %".format(accuracies.mean()*100))
print("Standard Deviation:{:.2f} %".format(accuracies.std()*100))Accuracy:94.53 % 
Standard Deviation:1.91 %

应用此方法后,精度变量包含获得的所有精度的列表。然后我们打印出模型的总体精度和标准偏差。因此,在各种测试集上评估该模型,并且评估每个测试集的准确性。在所有测试集上验证后达到的准确度为 94.53%,标准偏差为 1.91%,这是相当低且相当好的。

XGBOOST

谷歌图片

XGBoost 是一个优化的分布式梯度增强库,旨在高效、灵活、可移植。所以它是一个基于决策树的集成机器学习算法,使用了梯度提升框架。

要安装 XGBoost,您可以参考本文档

**Training XGBoost to the training set**from xgboost import XGBClassifier
xgboost=XGBClassifier()
xgboost.fit(X_train,y_train)

现在我已经用一个惊人的库 XGBoost 库训练了这个模型。

**Making the Confusion Matrix for XGBoost**from sklearn.metrics import confusion_matrix, accuracy_score
y_pred = xgboost.predict(X_test)
cm = confusion_matrix(y_test, y_pred)
print(cm)
accuracy_score(y_test, y_pred)[[84  3]
 [ 0 50]]0.9781021897810219

最初,用决策树建立的模型准确率为 95.9%。但是在 XGBoost 之后,准确率达到了 97.8%,令人印象深刻。

类似地,我们对 XGBoost 模型执行 K-Fold 交叉验证。

**Applying the K-Fold Cross Validation for XGBoost**from sklearn.model_selection import cross_val_score
accuracies = cross_val_score(estimator = xgboost, X = X_train, y = y_train, cv = 10)
print("Accuracy:{:.2f} %".format(accuracies.mean()*100))
print("Standard Deviation:{:.2f} %".format(accuracies.std()*100))Accuracy:96.53 % 
Standard Deviation:2.07 %

我们的模型的整体准确率为 96.53%,这是非常酷的。

这是我们能达到的最高精度吗?让我们试着用其他库来测试它,看看我们是否能击败这个精度。

CATBOOST

谷歌图片

CatBoost 是一个高性能的开源库,用于决策树上的梯度提升。CatBoost 是一种基于梯度下降的算法,它有一个非常特殊的功能,称为自调整。它不需要调整,并将自我训练以找到最佳参数和最佳得分,例如,用于回归的最佳 R 平方,用于分类的最佳准确度。这是 CatBoost 的关键特性。

要安装 CatBoost,您可以参考此文档

**Training CatBoost to the training set**from catboost import CatBoostClassifier
catboost = CatBoostClassifier() 
catboost.fit(X_train, y_train)

现在我已经用一个很棒的库训练了这个模型,这个库就是 CatBoost 库。CatBoost 经过几次迭代,将自己调整到最佳参数,以找到最高的精度(它将为特定问题找到最佳超参数)

**Making the Confusion Matrix for CatBoost**from sklearn.metrics import confusion_matrix, accuracy_score
y_pred = catboost.predict(X_test)
cm = confusion_matrix(y_test, y_pred)
print(cm)
accuracy_score(y_test, y_pred)[[84  3]
 [ 0 50]]0.9781021897810219

有趣的是,XGBoost 和 CatBoost 的精度是一样的。现在,让我们对 CatBoost 模型进行 K 倍交叉验证,并比较结果。

**Applying the K-Fold Cross Validation for CatBoost**from sklearn.model_selection import cross_val_score
accuracies = cross_val_score(estimator = xgboost, X = X_train, y = y_train, cv = 10)
print("Accuracy:{:.2f} %".format(accuracies.mean()*100))
print("Standard Deviation:{:.2f} %".format(accuracies.std()*100))Accuracy:97.26 % 
Standard Deviation:2.03 %

太好了!!我们在 K-fold 交叉验证上取得了 97.26%的准确率,这太不可思议了!因此,XGBoost 的准确率从 94.53%提高到 96.53%,但对于 CatBoost,准确率要高得多,因为我们在 CatBoost 的 K 倍交叉验证集上获得的准确率为 97.26%,这绝对令人惊叹。CatBoost 以将近 1%的优势击败 XGBoost。

这两个库非常强大,因为它们极大地提高了机器学习模型的准确性,并且背后涉及到大量的数学知识。理解数学以及它如何提高模型的性能也很重要。因此,使用这两个库非常好,因为它们可以提供更好的预测,还可以提高机器学习模型的性能。还有其他强大的库,比如 Light GBM ,它们在很大程度上提高了我们的准确性。

在这篇文章中,我试图详细讨论一切。但是你可以随时参考我的 Github 库 获取完整代码。

LinkedIn 上与我联系

“快固然好,但准确才是最重要的。”-怀亚特·厄普

我希望你觉得这篇文章很有见地。我很乐意听到反馈,以便即兴创作,并带来更好的内容。

非常感谢您的阅读!

没有技术术语的助推算法

原文:https://towardsdatascience.com/boosting-algorithms-without-technical-jargoons-e871414da2e2?source=collection_archive---------83-----------------------

没有术语的机器学习

不可能的任务?任务完成…

图片由 Wasserstrom 通过谷歌图片提供

介绍

在我之前的帖子中(见下文),我用人们投票的类比来展示加权随机森林和 boosting 算法之间的区别。概括地说,加权随机森林的规则是,投票给结果 A 的每个人都将被计算更多。提升算法的规则是,谁更有资格,谁就能投更多的票。如果结果 A 赢得了更多的选票,那么它就是。

[## 从不平衡数据集到助推算法

不平衡数据集完整工具包

towardsdatascience.com](/from-imbalanced-dataset-to-boosting-algorithms-1-2-798cd6384ecc)

这篇文章将介绍每个提升算法如何决定每棵树拥有的票数。通过理解算法是如何工作的,我们将理解我上一篇文章中所展示的性能差异。并且更好地知道何时使用哪个工具。

boosting 一家三口。它们是自适应增强、梯度增强和 XG 增强。它将被依次讨论。

adaboost 算法

Adaboost 只使用一个因素来决定一棵树的发言权——它的准确性。然而,有一个偷偷摸摸的转折。每棵树都被一组略有不同的样本训练。为什么

想象一下,你正在准备你的 SAT 考试,有四个部分:阅读,写作,数学 1(有计算器),数学 2(没有计算器)。为简单起见,我们假设每个部分有 15 个问题要回答,总共 60 个问题。你做了一次模拟考试,你意识到你在数学 1 中得分最低。所以下一次,你要多练习数学 1 题,少练习其他部分的题。因此,你仍然每次练习 60 个问题,但组合略有不同。

Adaboost 也是一样。Adaboost 的一个特别之处在于,它建立了一个带有“stump”的森林,一个一级深度的树。稍后我将对此进行更多的讨论。现在,把它当作一种约束。让我们先解决它是如何决定一棵树/树桩的话语权的。

假设我们想要建立一个模型来预测客户是否会购买我们的新产品。我们有 6 个样本客户。我们有来自 Amy、Tom、John、Tim、Lucy 和 Mike 的数据(见下图 1)。以下是建立目录林的步骤:

  1. 像建一棵普通的树一样建一个树桩。所以选择能正确分类大多数样本的变量。这就是我们的树桩 1。如果你不熟悉一棵树是如何建造的,你可以通过阅读这篇文章了解更多。

[## 什么是随机森林,为什么没有技术术语

使用业务语言并在业务环境中理解随机森林

medium.com](https://medium.com/swlh/programming-journal-2-what-is-and-why-random-forest-without-technical-jargon-c5a9a69d8739)

2.树桩 1 有 83%的准确率,而蒂姆被错误地分类了。因此,我将把样本 Tim 的权重提高到 0.3,把其他样本的权重降低到 0.14,这样它们加起来就是 1。

等等…但是“提高样品的重量”是什么意思?很好的问题,但超出了我的帖子范围。你可以看看这个视频看看它是怎么做的。简而言之,有两种方法。您可以根据权重创建新的样品组,也可以使用加权 GINI 指数。但是,直觉和我上面给的 SAT 类比是一样的。

GIF via GIPHY

3.我使用新的加权样本构建 stump 2,准确率为 87%。约翰被错误地归类了。因为正确分类每个样本的权重现在略有不同,stump 2 有 87%的准确性(注意:这不是精确的计算)。

图片 1

4.下一次,我会提高约翰的重量,降低其他样品的重量。如果我们没有设置我们想要的最大树数,那么这个过程将会重复,直到我们达到 100%的准确率。

图片 2

假设我将限制设置为 3 个树桩。就像我之前提到的,每个树桩的投票数完全取决于他们模型的准确性。它用下面的公式来决定它的最终发言权。

图 3

括号内的一切反映了模型给出正确预测的可能性。例如,对于 stump 1,给出正确预测的可能性是错误预测的 5 倍。

神奇的是日志部分。因为对数的性质,如果我们的模型有 0 个误差(分母趋向于 0),我们给出无穷的正幂。如果我们有许多错误,我们将通过记录它给出一个大的负数(尝试将 99%作为错误率)。

5.在我们知道每个候选人有多少发言权后,我们简单地把他们的投票加起来。得票多的班级获胜。

图 4

好吧,但是我们为什么要用树桩呢?为什么不用树呢?

让我们退一步,看看整个画面。这里的关键思想是突出难以预测的样本,以便我们可以建立一个针对这些样本的模型。

当我们构建一个多于 1 层的树时,预测也取决于我们如何构建树。通过使用不同顺序的预测器,我们可以得到不同的预测。这削弱了我们的目标。你可以从这里了解更多关于如何构建一棵树的信息:

[## 什么是随机森林,为什么没有技术术语

使用业务语言并在业务环境中理解随机森林

medium.com](https://medium.com/swlh/programming-journal-2-what-is-and-why-random-forest-without-technical-jargon-c5a9a69d8739)

这也是为什么对于不平衡数据集,boosting 算法比随机森林和决策树提供了更健壮的分析。Boosting 算法结合了更好地预测少数类的模型。

Ada boost 的问题是,每次构建一个 stump,都需要重新构建整个样本集!想象一下,你有成千上万的样本,甚至计算机也不想做这项工作。所以才推出了 Gradientboost!

梯度推进:

Gradientboost 通过不使用样本构建树解决了这个问题。它使用预测和实际结果之间的差异,也就是残差来构建树。图 6 向你展示了什么是剩余树,如果你像我一样困惑的话。

GIF via GIPHY

图 5 简单地展示了这个过程。基于样本集,我们将首先给出一个对数(赔率)预测,也就是说,我们的模型预测一个类别优于另一个类别的可能性有多大。然后,我们将对数(赔率)转换成概率,并计算残差。从这里,我们将开始建立一个森林,使每棵树的残差最小化。然后我们把所有的东西和初始预测一起加起来。终于,我们有了新的概率!

图 5

如果你不知道什么是对数(赔率)以及我们为什么使用它,先学习逻辑回归。你可以通过阅读下面的文章来了解更多关于逻辑回归的知识。

[## 没有技术术语的逻辑回归+与树模型的比较

如果你喜欢披萨,你就会明白逻辑回归和随机森林的区别!

towardsdatascience.com](/programming-journal-3-logistic-regression-cbf68f01bf7d)

这里有一个例子来形象化这个过程,以便我们能更好地理解它。我们有一个分类问题,因此,我们的预测可以是 0 或 1。在这个例子中,我们有四个 1 和两个 0。因此,我们的对数(赔率)是 0.69。在我们把它转换成概率之后,它将是 0.67。Amy 的残差为 1–0.67,Tom 的残差为 0–0.67。在右边,我比较了一棵规则树和一棵剩余树。

图 6

在一棵普通的树上,树叶给我们一个最终的类别预测,例如,红色或绿色。在残差树中,树叶给了我们残差。比如从左到右,第一片叶子(-0.7)是-0.7(咄…)。第二片叶子(0.3,-0.7)是-0.4,最后一片叶子是 0.9。

这里的直觉是:如果叶子加起来是一个大的负数或大的正数,它把正确的样本组合在一起。另一方面,如果它们不是同一个东西,值会互相抵消,因此接近于 0。

一棵树的价值是它所有叶子的总和。在我们建立了所有的树之后,我们将所有的树值相加,并将它们添加到初始的对数预测中。因此,如果一棵树具有更大的值(更善于分裂组),它将对初始预测应该如何改变具有更大的影响。

图 7

每棵树的价值将乘以 0.1。这个值被称为学习率,你可以任意选择任何值,但 0.1 是转换。它很小,所以它确保每棵树只是稍微改变初始值。

关于 Gradientboost 我想说的最后一点是,它实际上使用了一棵树,而不是树桩。但是通常我们将 max_depth 限制在 6 到 8 之间,以避免过度拟合。Gradientboost 不使用树桩,因为它不使用树来检测困难的样本。它正在构建树以最小化残差。

更多的技术见解(随意跳过):一棵树如何影响另一棵树。

当我们计算一片叶子的值时,我们实际上使用下面的公式,而不是简单地将残差相加。我想分享一些关于我们如何理解这个公式的直觉。这个公式的实际数学是超级讨厌的。它涉及二阶导数。所以我们不要去那里。

图 8

在上面的公式中,分母中的 P 是我们最后一棵树基于其总对数(odds)给出的概率。我在下面列出了四种情况,这样我们就能明白这个公式的含义了。

图 9

从分母来看,如果前一棵树对自己的预测非常有信心,那么下一棵树就有更大的值(更大的发言权)。从分子上看,如果当前树的残差很大,那么也会导致更大的值。这就像我们已经讨论过的一样。这也是最后一棵树的准确性如何影响下一棵树在森林中的发言权。

为什么我们还需要 XGboost?

GIF via GIPHY

XGboost 是专门为大型数据集设计的,因为它非常快。它使用了许多优化和正则化技术,这超出了我想谈论的范围。

我想强调 XGboost 和 Gradientboost 之间的一个关键区别。在 Gradientboost 中,在我们计算每个样本的残差后,我们选择一个节点进行分割,并继续使用传统方法构建树。面对大型数据集时,这一过程可能会非常昂贵。

因此,XGboost 更进了一步。它没有使用谓词作为树节点。它构建树来将残差分组在一起。就像我之前提到的,相似的样本会有相似的残值。所以树节点是可以分隔残差的值。所以 XGboost 中的叶子是残差,XGboost 中的树节点是可以对残差进行分组的值!

XGboost 的速度使得它对于大型数据集来说确实可行。然而,当我们有合理数量的样本时,比如几千个样本,Gradientboost 实际上更健壮。

我希望这能说明为什么 Gradientboost 是我在做流失分析时最健壮的算法。只有 3333 个样本。您可以点击此处的文章查看完整的分析:

[## 从不平衡数据集到助推算法

不平衡数据集完整工具包

towardsdatascience.com](/from-imbalanced-dataset-to-boosting-algorithms-1-2-798cd6384ecc)

GIF via GIPHY

我说完了:)

我在帖子中链接的视频和文章:

  • 没有技术术语的逻辑回归+与树形模型的比较
  • 从不平衡数据集到 boosting 算法
  • 什么是随机森林,为什么没有技术术语
  • 梯度推进第三部分:分类
  • 梯度增强第 4 部分:分类细节

其他重要资源:

  • 基本集成学习(随机森林、AdaBoost、梯度增强)-逐步解释
  • XGBoost 第 2 部分:用于分类的 XGBoost 树

用可解释的人工智能推进机器学习模型(XAI)

原文:https://towardsdatascience.com/boosting-machine-learning-models-with-explainable-ai-xai-601683119c84?source=collection_archive---------19-----------------------

关于 Airbnb 房源的见解

对于典型的机器学习模型,传统的特征重要性分析的相关性通常具有有限的价值。在数据科学家的工具包中,是否有可靠的、系统的、模型不可知的方法来测量对预测的特性影响?答案是肯定的。

这里我们用一个建立在 Airbnb 数据上的模型来说明:

  • 可解释的人工智能(XAI)技术
  • XAI 能为全球和地方解释做些什么
  • XAI 能为模型增强做些什么

XAI——概述

随着人工智能在更多应用中获得牵引力,可解释人工智能(XAI)越来越成为清晰解释和自信部署的关键组件。对于机器学习和深度学习来说,XAI 技术正变得越来越成熟。这里有几个算法中立的方法,现在很实用:

SHAP

SHAP 是由华盛顿大学的斯科特·伦德伯格提出的。SHAP 根据博弈论计算沙普利值,假设实例的每个特征值都是游戏中的“玩家”,预测就是支出。那么可以通过计算每个特征对预测的贡献来解释预测。注:SHAP 具有以下可取的特性:

1.局部精度:特征属性的总和等于我们试图解释的模型的输出

2.缺失:已经缺失的功能没有影响

3.一致性:改变一个模型,使一个特性对模型有更大的影响,这永远不会减少分配给那个特性的属性。

SHAP 支持树集成、深度学习和其他模型。它既可以用于全局解释,也可以用于局部解释。请参考斯科特·伦德伯格的 SHAP 论文。

石灰

局部可解释模型不可知解释(LIME)是基于代理模型的概念。当解释黑盒模型时,LIME 用数据的变化测试预测发生了什么,并用加权特征训练局部代理模型。最后,对“黑箱”模型的个别预测可以用局部的、可解释的替代模型来解释。

请参考石灰纸:《我为什么要相信你》

Airbnb 预订率模型

这里使用的模型预测 Airbnb 的预订率。它使用从 insideairbnb.com 获得的洛杉矶地区列表数据进行训练。为了简单起见,我使用一个特征子集来训练 XGBoost 模型。

关于模型设计的更多信息,请参考https://towards data science . com/predicting-market-rank-for-Airbnb-listings-59009 a886d 6

具有全局解释的洞察力

SHAP 摘要显示了主要功能贡献。它还显示数据点分布,并提供特征值如何影响预测的可视化指标。这里红色表示较高的特征值,蓝色表示较低的特征值。在 x 轴上,右边较高的 SHAP 值对应于较高的预测值(列表更可能被预订),左边较低的 SHAP 值对应于较低的预测值(列表不太可能被预订)。

以下是通过全局要素分析获得的一些见解:

谁是最成功的主持人?

使用依赖图,我们可以检查特征值和预测结果之间的关系。在第一张图中,随着主机列表数量的增加,我们看到 SHAP 值呈下降趋势。在第二个图表中,x 轴显示主机列表计数,颜色显示“整个家庭”的列表计数。

我们大概可以得出这些类型的宿主:

  • 拥有一个或几个列表的主机-这些是个人和家庭,他们的列表通常是有吸引力的,可能是由于关注和个人护理
  • 拥有 15-60 个房源的房东——这些房东拥有最不吸引人的房源,他们可能是出租房间的小旅馆或汽车旅馆?
  • 拥有超过 150 个列表的主机—在第二张图中,我们可以看到,随着主机列表的数量增加到 50 个以上,预计预订率将大幅增加(与之前的趋势相反)。进一步说,那些房源几乎都是“整栋住宅”。在最高端,那些拥有超过 100 个“全屋”房源的主机实现了 75%以上的预订率,远远高于其他任何人。那些是专业管理的 Airbnb 物业公司吗?

更高的清洁费还是更高的价格?

如果有选择的话,主人应该收取更多的每夜费用还是清洁费?相关性图显示了价格和清洁费之间的特征相互作用。红色表示较高的清洁费。沿着 x 轴,随着价格的上涨,预计预订率下降,这是意料之中的。此外,我们发现清洁费较高的列表(红点)往往位于清洁费较低的列表(蓝点)之上。

因此,清洁费较高的房源在预测预订率时实际上是有利的。主人将更多的成本转移到清洁费上,可能会通过鼓励客人逗留更长时间,并使首页的标价看起来更便宜而获胜。

评论多还是评论评分高?

在图中,我们看到点评率(x 轴)的上升导致预订率的上升。然而,评论数量的增加并不意味着预订率的提高(红点垂直分布)。一个主持人得到一些好评比有很多平庸的评论要好得多。

本地解释的洞察力

SHAP 力图可以用来解释个人的预测。

例如,我们可以看到基值(偏差项)为 0.01249,红色要素将该值向右推,蓝色要素将该值向左推,组合输出为 0.58。因此,top 特征的影响在具有局部精度的预测上被量化。特定的列表有许多强大的功能价值(超级主机,低价,整个家庭,最近的日历更新),这使得它有利于预订。

下面的列表有一些特色价值(390 美元的高价,最少 30 天的长时间停留,长时间日历没有更新),这使得它不太可能被预订。

LIME 方法也可以用来解释单个预测,它定量地显示了顶部特征的影响(橙色为正,蓝色为负)。

第一个例子显示了一个主要是正面特征值的列表(它是一个超级主机提供的一整个家,有很多评论)。

第二个示例显示了一个具有负特征值的列表(它要求最少入住 30 晚,并收取 150 美元的清洁费)。

模型改进的洞察力

通过检查特性的全局和局部影响,我们通常可以揭示出人意料的数据模式,并获得新的见解。通过进一步分析,我们可能会发现以下原因之一:

  • 商业分析的不足
  • 数据收集出错
  • 数据处理改进(估算和标度)
  • 或者说,不寻常的模式是新知识学习的真实反映

下图显示了主要有两种类型的列表具有较高的“日历更新”值(红点)。x 轴最左侧的一组,在过去 12 个月中没有评论,基本上是具有负 SHAP 值的陈旧列表,因此预测预订率低。其他红点分散在上部区域,这表明它们具有更高的 SHAP 值,更有可能被预订。这些列表是持续可用的,并且不需要主机进行多少日历更新。这为特征工程提供了线索,其目标是区分稳定列表和训练数据。

此处显示的另一个示例是溜冰者部分相关性图,它显示了纬度和经度特征的相互作用,纵轴表示它们对预测的影响。视觉上,这个 3D 图可以叠加在洛杉矶地区的地图上,该地图清楚地显示中部和北部地区更受欢迎,南部最不可能被预订。这种洞察力不能通过分析单个特征获得。

进行修正、调整和获取新知识是迭代模型生命周期的一部分,这将导致增量改进。XAI 可以发现隐藏的线索,并为此提供关键证据。

开源代码库

简化版的模型和 XAI 代码可以在这里找到:https://github.com/seanxwang/XAI-airbnb-booking

下一步是什么

Airbnb 房源具有丰富的信息功能,如图像和文本。将这些整合到模型中可以大大提高预测性能。拥有深度学习和远见的 XAI 应该既有挑战性又有回报。

使用 XGBoost 提升性能

原文:https://towardsdatascience.com/boosting-performance-with-xgboost-b4a8deadede7?source=collection_archive---------30-----------------------

在这篇博客中,我们将借助一个例子来看看 XGBoost 是如何工作的,以及 XGBoost 的一些重要特性。

来源:正面消息

所以,我们很多人都听说过树模型和助推技术。让我们将这些概念放在一起,讨论 XGBoost,这是目前最强大的机器学习算法。

XGboost 呼吁极端梯度助推树木。

【XGBoost 这个名字实际上是指提升树算法的计算资源极限的工程目标。这也是很多人使用 XGBoost 的原因。

自 2014 年推出以来,XGBoost 具有很高的预测能力,比其他梯度增强技术快近 10 倍。它还包括各种正则化,减少过度拟合,提高整体性能。因此也被称为“正则化增强技术。XGBoost 在性能和速度方面证明了自己的实力。

好吧!!!别急,我们来说说助推

什么是助推树?

我们遇到过许多基于树的算法,如决策树,在这些算法中,我们用来在特定数据集上训练我们的单一模型,可能需要一些参数调整。同样在集合模型中,我们习惯于单独训练所有的模型。

Boosting 也是一种集成技术,它将许多模型结合起来给出最终的模型,但不是单独评估所有模型,而是依次训练模型。这意味着,每一个新模型都被训练来纠正前一个模型的错误,当没有进一步的改进时,该序列被停止。这就是为什么它更准确。

安装 XGBoost

在 XGBoost 文档网站上有全面的安装指南。

它涵盖了 Linux、Mac OS X 和 Windows 的安装。

它还涵盖了在 R 和 Python 等平台上的安装。

设置我们的数据

所以,第一件事就是为我们的模型准备数据。我们将使用来自 Scikit Learn 的 iris flower 数据集。

这里,我们用 python 从 Sklearn 加载了数据集,还导入了 XGBoost 库

from sklearn import datasets
import xgboost as xgbiris = datasets.load_iris()
X = iris.data
y = iris.target

接下来,我们必须将数据集分成两部分:训练和测试数据。这是检验我们的模型表现如何的重要一步。因此,我们将把数据分成 80%-20%的部分。

from sklearn.model_selection import train_test_splitX_train, X_test, Y_train, Y_test = train_test_split(X, y, test_size=0.2)

与其他算法不同,XGBoost 需要将我们的数据转换成特定的格式,即 DMatrix。

DMatrix 是由 XGBoost 使用的内部数据结构,针对内存效率和训练速度进行了优化。

D_train = xgb.DMatrix(X_train, label=Y_train)
D_test = xgb.DMatrix(X_test, label=Y_test)

现在,我们将 NumPy 数组数据转换成 DMatix 格式,以提供给我们的模型。但在此之前,我们需要定义我们的模型。

定义 XGBoost 模型

我们要做的第一件事是定义梯度下降系综的参数。我们有 N 个参数可用于我们的模型,但现在,我们将把重点放在一些重要的。可能参数的完整列表可在官方 XGBoost 网站上获得。

param = {
    'eta': 0.2, 
    'max_depth': 4,  
    'objective': 'multi:softprob',  
    'num_class': 4
    }epochs = 20

这是我们的参数:

  • max_depth :被训练决策树的最大深度
  • 目标:使用损失函数
  • num_class :数据集中类的数量
  • eta :学习率

正如我们已经知道的,这种模型是按顺序工作的,这使得它更加复杂。这种技术很容易过度拟合。

eta 参数/学习率帮助我们的算法防止过度拟合,这不仅是通过将新树的预测添加到具有全权重的集合中,而且 eta 将乘以正在添加的残差以减少它们的权重。

:建议在 0.1 到 0.3 的范围内使用较小的 eta 值

我们现在已经定义了模型,让我们来训练它

培训和测试

model = xgb.train(param, D_train, steps)

这是一个与 Scikit Learn 非常相似的过程,运行评估也非常熟悉。

import numpy as np
from sklearn.metrics import precision_score, recall_score, accuracy_scorepreds = model.predict(D_test)
best_preds = np.asarray([np.argmax(line) for line in preds])print("Precision = {}".format(precision_score(Y_test, best_preds, average='macro')))
print("Recall = {}".format(recall_score(Y_test, best_preds, average='macro')))
print("Accuracy = {}".format(accuracy_score(Y_test, best_preds)))

输出:

太棒了,我们达到了 90%以上的准确率

如上所述,我们有很多参数,选择错误的参数,可能会影响你的模型性能很多。

所以这里的问题是:如何选择合适的参数?

嗯,用不同的值来比较模型性能太容易了。让我们看看

寻找最佳参数

设置任何 ML 模型的最佳超参数都是一项挑战。那么为什么不让 Scikit Learn 帮你做呢?我们可以很容易地将 Scikit Learn 的网格搜索与 XGBoost 分类器结合起来:

from sklearn.model_selection import GridSearchCVclf = xgb.XGBClassifier()
parameters = {
     "eta"    : [0.05, 0.10, 0.15, 0.20, 0.25, 0.30 ] ,
     "max_depth"        : [ 3, 4, 5, 6, 8, 10, 12, 15],
     "min_child_weight" : [ 1, 3, 5, 7 ],
     "gamma"            : [ 0.0, 0.1, 0.2 , 0.3, 0.4 ],
     "colsample_bytree" : [ 0.3, 0.4, 0.5 , 0.7 ]
     }grid = GridSearchCV(clf,
                    parameters, n_jobs=4,
                    scoring="neg_log_loss",
                    cv=3)grid.fit(X_train, Y_train)

输出:

如果你有时间的话,只在大数据集上这样做——进行网格搜索本质上是多次训练决策树的集合!

一旦您的 XGBoost 模型经过训练,您就可以将它的可读描述转储到一个文本文件中:

model.dump_model('dump.raw.txt')

这就是我们如何创建 XGBoost 模型,并为其选择理想的超参数。

保持曲调,快乐学习

最初发布于:https://blog . knol dus . com/machinex-boosting-performance-with-xgboost/

在 LinkedIn 和 Twitter 上关注我,了解更多信息:

  • 领英
  • 推特

用 Cython 提升 Python 脚本(应用于 Raspberry Pi)

原文:https://towardsdatascience.com/boosting-python-scripts-with-cython-applied-on-raspberry-pi-5ea191292e68?source=collection_archive---------7-----------------------

使用 Cython 将 Python 代码加速数千倍

比尔·杰伦:【https://unsplash.com/photos/NVWyN8GamCk】T2

Python 可能是当今最流行的编程语言之一,但它肯定不是最高效的。特别是在机器学习领域,从业者为了 Python 提供的易用性牺牲了效率。

这并不意味着你不能用其他方法加快速度。Cython 是一种显著减少 Python 脚本计算时间的简单方法,而不会牺牲使用 Python 轻松实现的功能。

本教程将向您介绍如何使用 Cython 来加速 Python 脚本。我们将看到一个简单但计算量很大的任务:为循环创建一个,该循环遍历一个包含 10 亿个数字的 Python 列表,并对它们求和。由于在资源有限的设备上运行代码时,时间尤其重要,我们将通过考虑如何在 Raspberry Pi (RPi)上的 Cython 中实现 Python 代码来考虑这个问题。Cython 显著提高了计算速度。把它想象成树懒和猎豹的比较。

今日印度的树懒图片| pix abay 的猎豹图片

本文原载于 Paperspace 博客 。你可以在渐变 上免费运行我的教程的代码

本教程涵盖的部分如下:

  • Python、CPython 和 Cython
  • 简化 Python 代码
  • 为回路鸣音一个
  • 将 C 数据类型赋给变量
  • Cython 在树莓派中的应用

让我们开始吧。

Python 和 CPython

许多人没有意识到这样一个事实,即像 Python 这样的语言实际上是用其他语言实现的。比如 Python 的 C 实现叫做 CPython 。注意不是 Cython 。关于 Python 不同实现的更多信息,你可以阅读这篇文章。

Python 的默认和最流行的实现是 CPython。使用它有一个重要的优点。c 是一种编译语言,它的代码被转换成机器代码,由中央处理器(CPU)直接执行。现在你可能会想,如果 C 是一种编译语言,那是不是意味着 Python 也是?

C (CPython)中的 Python 实现不是 100%编译的,也不是 100%解释的。在运行 Python 脚本的过程中,既有编译也有解释。为了说明这一点,让我们来看看运行 Python 脚本的步骤:

  1. 使用 CPython 编译源代码以生成字节码
  2. 在 CPython 解释器中解释字节码
  3. 在 CPython 虚拟机中运行 CPython 解释器的输出

当 CPython 编译源代码(.py 文件)来生成 CPython 字节码(.pyc 文件)。CPython 字节码(。pyc 文件)然后使用 CPython 解释器进行解释,输出在 CPython 虚拟机上运行。根据上面的步骤,运行 Python 脚本的过程包括编译和解释。

CPython 编译器只生成一次字节码,但是每次代码运行时都会调用解释器。通常字节码的解释要花很多时间。如果使用解释器会降低执行速度,为什么还要使用它呢?最大的原因是它有助于 Python 跨平台。因为字节码运行在 CPU 之上的 CPython 虚拟机中,所以它独立于运行它的机器。因此,字节码可以在不同的机器上运行而不发生变化。

如果没有使用解释器,那么 CPython 编译器将生成直接在 CPU 中运行的机器码。因为不同的平台有不同的指令,所以代码不会跨平台。

总之,使用编译器加快了这个过程,但是解释器使代码跨平台。所以,Python 比 C 慢的一个原因是使用了解释器。记住编译器只运行一次,但是每次代码执行时解释器都会运行。

Python 比 C 慢得多,但许多程序员仍然喜欢它,因为它更容易使用。Python 对程序员隐藏了许多细节,这有助于防止令人沮丧的调试。例如,因为 Python 是一种动态类型语言,所以您不必在代码中显式指定每个变量的类型——Python 会自动推导出它的类型。相反,对于静态类型的语言(如 C、C++或 Java ),您必须指定变量的类型,如下所示。

*int x = 10 
string s = "Hello"*

将它与下面的 Python 实现进行比较。动态类型化使编码更容易,但是增加了机器寻找合适的数据类型的负担。这使得该过程更慢。

*x = 10
s = "Hello"*

一般来说,像 Python 这样的“高级”语言对开发者来说更容易使用。然而,当代码运行时,它需要被转换成低级指令。这种转换需要更多的时间,这是为了易于使用而牺牲的。

如果时间是一个重要的因素,那么你需要使用低级指令。因此,您可以使用 CPython 编写代码,而不是使用 Python(这是一种接口)来键入代码,CPython 是用 C 实现的 Python 的后端。但是,如果您这样做,您会觉得您是在用 C 而不是 Python 编程。

CPython 要复杂得多。在 CPython 中,一切都是用 C 实现的。在编码中没有办法逃避 C 的复杂性。这就是为什么许多开发者选择 Cython 而不是 T1 的原因。但是 Cython 和 CPython 有什么不同呢?

Cython 与众不同

根据 Cython 文档,Cython 是 C 数据类型的 Python。来自 Cython tutorial 2009 论文的另一个定义阐明:

Cython 是一种基于 Python 的编程语言,具有额外的语法来提供静态类型声明。这充分利用了 Python 的优势,同时允许用户达到 c 语言的速度

根据上面的定义,Cython 是一种让你拥有两个世界的最好的语言——速度和易用性。您仍然可以用 Python 编写常规代码,但是为了在运行时加快速度,Cython 允许您用 c 语言替换 Python 代码的某些部分。因此,您最终会将两种语言混合在一个文件中。请注意,您可以想象 Python 中的一切在 Cython 中都是有效的,但有一些限制。有关限制的更多信息,您可以访问本页。

常规 Python 文件的扩展名为. py,但 Cython 文件的扩展名为。改为 pyx 扩展名。相同的 Python 代码可以编写在。pyx 文件,但是这些文件也允许您使用 Cython 代码。请注意,与直接运行 Python 代码相比,仅将 Python 代码放入. pyx 文件中可能会加快速度,但不如声明变量类型时快。因此,本教程的重点不仅仅是在。pyx 文件,但也进行编辑,这将使它运行得更快。通过这样做,我们给编程增加了一点难度,但是这样做节省了很多时间。如果你有 C 语言编程的经验,那么对你来说会更容易。

简化 Python 代码

要将 Python 转换成 Cython,首先需要用创建一个文件。pyx 分机而不是。py 分机。在这个文件中,你可以从编写常规的 Python 代码开始(注意,Cython 接受的 Python 代码有一些限制,在 Cython 文档中已经阐明)。

在继续之前,请确保安装了 Cython。您可以使用以下命令来完成此操作。

*pip install cython*

来生成。pyd/。所以我们需要首先构建 Cython 文件。的。pyd/。所以 file 表示稍后要导入的模块。为了构建 Cython 文件,将使用 setup.py 文件。创建这个文件,并将下面的代码放入其中。我们将使用 distutils.core.setup()函数来调用 Cython。Build.cythonize()函数,该函数将。pyx 文件。该函数接受您想要 cythonize 的文件的路径。这里我假设 setup.py 文件与 test_cython.pyx 文件放在同一个位置。

*import distutils.core 
import Cython.Build distutils.core.setup(ext_modules = Cython.Build.cythonize("test_cython.pyx"))*

为了构建 Cython 文件,在命令提示符下发出下面的命令。命令提示符的当前目录应该与 setup.py 文件的目录相同。

*python setup.py build_ext --inplace*

该命令完成后,两个文件将被放在。pyx 文件。第一个有。c 扩展名,而另一个文件将具有该扩展名。pyd(或类似的,基于使用的操作系统)。为了使用生成的文件,只需导入 test_cython 模块,就会直接出现“Hello Cython”消息,如下所示。

我们现在已经成功地将 Python 代码细胞化了。下一节将讨论如何创建一个. pyx 文件,并在其中创建循环。

将“for”循环变成 Cythonizing

现在让我们优化我们前面提到的任务:一个 for 循环,它遍历 100 万个数字并将它们相加。让我们从查看循环迭代的效率开始。导入时间模块是为了估计执行需要多长时间。

*import timecdef unsigned long long int maxval
cdef unsigned long long int total
cdef int k
cdef double t1, t2, tmaxval = 1000000000
t1=time.time()for k in range(maxval):
    total = total + k
print "Total =", totalt2=time.time()
t = t2-t1
print("%.10f" % t)*

在. pyx 文件中,3 次运行的平均时间是 0.0281 秒。代码运行在配备酷睿 i7–6500 u CPU @ 2.5 GHz 和 16 GB DDR3 RAM 的机器上。

将它与运行一个普通 Python 文件所需的时间进行比较,后者的平均值为 0.0411 秒。这意味着仅在迭代方面,Cython 就比 Python 快 1.46 倍,尽管我们不需要修改循环的来让它以 C 速度执行。**

现在让我们添加求和任务。为此,我们将使用 range()函数。

*import time
t1 = time.time()total = 0
for k in range(1000000):
    total = total + k
print "Total =", totalt2 = time.time()
t = t2-t1
print("%.100f" % t)*

请注意,这两个脚本返回相同的值,即 499999500000。在 Python 中,平均运行时间为 0.1183 秒(三次试验之间)。在 Cython 中,它的速度快了 1.35 倍,平均为 0.0875 秒。

让我们看另一个例子,循环从 0 开始遍历 10 亿个数字。

*import time
t1 = time.time()total = 0
for k in range(1000000000):
    total = total + k
print "Total =", totalt2 = time.time()
t = t2-t1
print("%.20f" % t)*

Cython 脚本完成了将近 85 秒(1.4 分钟),而 Python 脚本完成了将近 115 秒(1.9 分钟)。在这两种情况下,时间都太长了。如果在如此琐碎的任务上持续超过一分钟,那么使用 Cython 的好处是什么?注意这是我们的错,不是 Cython 的。

如前所述,在 Cython 中编写 Python 代码。pyx 脚本是一个改进,但是它并没有大幅减少执行时间。我们必须在 Cython 脚本中编辑 Python 代码。首先要关注的是明确定义所用变量的数据类型。

将 C 数据类型赋给变量

根据前面的代码,使用了 5 个变量: total,k,t1,t2T5t。所有这些变量的数据类型都是由代码隐式推导出来的,因此需要更多的时间。为了节省推断它们的数据类型的时间,让我们从 C 语言中指定它们的数据类型。**

total 变量的类型是无符号 long long int* 。它是一个整数,因为所有数字的总和是一个整数,它是无符号的,因为总和将是正数。但是为什么是长呢?因为所有数字的和非常大,所以添加 long long 以将变量大小增加到最大可能大小。*

为变量 k 定义的类型为 int ,为剩余的三个变量 t1t2t 分配了 double 类型。

*import timecdef unsigned long long int total
cdef int k
cdef double t1, t2, tt1 = time.time()for k in range(1000000000):
    total = total + k
print "Total =", totalt2 = time.time()
t = t2-t1
print("%.20f" % t)*

Python 需要超过 1.9 分钟,而 Cython 只需要 0.00009346 秒。

既然我们已经看到了如何通过使用 Cython 来提高 Python 脚本的性能,那么让我们将其应用到 Raspberry Pi (RPi)中。

从 PC 访问 Raspberry Pi

如果这是你第一次使用你的 Raspberry Pi,那么你的 PC 和 RPi 都需要通过网络连接。为此,您可以将它们连接到一台交换机,在该交换机中,DHCP(动态主机配置协议)处于活动状态,以便自动为它们分配 IP 地址。成功创建网络后,您可以根据分配给它的 IPv4 地址访问 RPi。您如何知道分配给您的 RPi 的 IPv4 地址是什么?别担心,你可以简单地使用一个 IP 扫描工具。在本教程中,我将使用一个名为高级 IP 扫描器的免费应用程序。

应用程序的界面如下所示。它接受要搜索的 IPv4 地址范围,并返回活动设备的信息。

您需要输入本地网络中的 IPv4 地址范围。如果您不知道范围,只需在 Windows 中发出 ipconfig 命令(或在 Linux 中发出 ifconfig)即可知道您的 PC IPv4 地址(如下图所示)。在我的例子中,分配给我的 PC 的 Wi-Fi 适配器的 IPv4 地址是 192.168.43.177,子网掩码是 255.255.255.0。这意味着网络中的 IPv4 地址范围是从 192.168.43.1 到 192.168.43.255。如图所示,IPv4 地址 192.168.43.1 被分配给网关。请注意,范围内的最后一个 IPv4 地址 192.168.43.255 是为广播消息保留的。因此,搜索范围应该从 192.168.43.2 开始,到 192.168.43.254 结束。

根据下图所示的扫描结果,分配给 RPi 的 IPv4 地址是 192.168.43.63。此 IPv4 地址可用于创建安全外壳(SSH)会话。

为了建立 SSH 会话,我将使用一个名为的免费软件。应用程序的界面如下。

为了创建一个 SSH 会话,只需点击左上角的会话按钮。将出现一个新窗口,如下所示。

在该窗口中,单击左上角的 SSH 按钮,打开如下所示的窗口。只需输入 RPi 的 IPv4 地址和用户名(默认为 Pi),然后单击 OK 启动会话。

单击 OK 按钮后,会出现一个新窗口,要求输入密码。默认密码是 raspberrypi。登录后,将出现下一个窗口。左侧的窗格有助于轻松导航 RPi 的目录。还有一个用于输入命令的命令行。

将 Cython 与树莓 Pi 一起使用

创建一个新文件,并将其扩展名设置为。pyx 来编写最后一个例子的代码。左侧窗格的栏中有用于创建新文件和目录的选项。您可以使用“新建文件”图标使事情变得更加简单,如下图所示。我在 RPi 的根目录下创建了一个名为 test_cython.pyx 的文件。

只需双击文件打开它,粘贴代码,并保存它。之后,我们可以创建 setup.py 文件,这与我们之前讨论的完全相同。接下来,我们必须发出以下命令来构建 Cython 脚本。

*python3 setup.py build_ext --inplace*

该命令成功完成后,您可以根据下图找到左侧窗格中列出的输出文件。注意,要导入的模块的扩展现在是。因此,由于我们不再使用 Windows。

现在让我们激活 Python 并导入模块,如下所示并运行 Cython 代码。

本文原载于 Paperspace 博客 。你可以在渐变 上免费运行我的教程的代码

结论

本教程讨论了如何使用 Cython 来减少执行 Python 脚本的计算时间。我们看了使用一个 for 循环对一个包含 10 亿个数字的 Python 列表中的所有元素求和的例子,并比较了声明变量类型和不声明变量类型的执行时间。虽然这在纯 Python 中运行需要将近两分钟,但使用 Cython 声明的静态变量运行基本上不需要时间。

在下一篇教程中,我们将用 NumPy 数组替换这个 Python 列表,并看看如何使用 Cython 优化 NumPy 数组处理。然后,我们将看看如何将更高级的 Python 脚本(如遗传算法)进行 cythonize。这是轻松提高机器学习项目效率的好方法。

通过客户细分分析促进销售:更好地了解市场

原文:https://towardsdatascience.com/boosting-sales-through-customer-segmentation-analysis-knowing-the-market-better-8c7feebd3479?source=collection_archive---------25-----------------------

应用客户细分来洞察营销活动

作者图片

客户细分是一个基于某些特征(年龄、性别、收入等)将公司的客户分成不同群体的过程。),而有效的分析可以帮助一个公司做出更好的营销决策。在这篇文章中,我将分享一个基于 Arvato 公司提供的数据的客户细分分析。Arvato 是一家供应链解决方案公司,我用于分析的数据集包含一家客户公司的客户人口统计数据。我还建立了一个模型来预测邮寄广告的回复率。

下面,我将向您详细介绍我使用无监督和有监督学习方法进行的分析。我们分析了两个数据集,即来自 Arvato 客户公司的客户数据和来自德国的一般人口统计数据,以回答以下问题:

1.谁是客户公司的忠实客户,随着营销策略的改变以扩大客户群体,谁是潜在的目标客户?

2.当客户公司发出邮件报价时,我们能预测回复率吗?

第一部分.客户细分

谁是客户公司的忠实客户,随着营销策略的改变以扩大客户群体,谁是目标潜在客户?

聚类分割有助于将客户公司现有客户的人口统计数据映射到德国的一般人群。在这里,我应用无监督学习来识别普通人群中的哪个部分代表客户公司的忠实客户,哪个部分代表他们可能瞄准的潜在新客户群。

数据探索

数据科学家花 80%的时间清理数据。

在这个项目过程中,我 90%的时间都花在了数据探索和预处理上。我在客户细分中使用的以下数据集包含大量原始数据:

  • Azdias —德国普通人口的人口统计数据(891211 x 366)。
  • 客户 —客户公司的人口统计数据(191652 x 369)。

在总体数据中,有 273 列包含缺失值。我决定删除缺失值率超过 30%的列(用红色表示),因为大量的缺失值对于分析统计数据和构建模型是有害的(例如 ALTER_KIND1 和 EXTSEL992)。对于剩余的列(蓝色),我会用最频繁的值来估算缺失的数据。

有 890919 行包含缺失值。通过检查缺失率的分布,大多数行的缺失值少于 10%,因此,我将删除阈值设为 50%。

数据预处理

数据预处理包括以下六个步骤:

  • 重新编码缺失值:我手工创建了特征描述文件 feature_summary.csv,包含属性名、特征类型、缺失值或未知值。根据功能描述文件,许多功能中的缺失值由–1 和 0 值表示(例如,在功能“AGER_TYP”中)。在这里,我根据特性描述文件将每个属性中所有缺失的值重新编码到 NaN 中(见下文)。

  • 丢弃缺失值:注意缺失值重新编码后,各列缺失率的分布向百分比较高的区域偏移。丢失值超过 30%的所有列和丢失值超过 50%的所有行都从两个数据库中删除。

  • 丢弃高度相关的特征:计算每个特征的皮尔逊相关系数。相关性可以是正的,也可以是负的,因此,我存储了相关性的绝对值。特征被阈值> 0.95 去除,比如 KBA13_BAUMAX,KBA13_FAB_SONSTIGE,LP_FAMILIE_GROB。
# Calculate Pearson's correlation matrix
corr_df = azdias_drop_missing.corr().abs()# Create and apply mask
mask = np.triu(np.ones_like(corr_df,dtype=bool))
tri_df = corr_df.mask(mask)# Find the features that meet threshold
to_drop = [c for c in tri_df.columns if any(tri_df[c] > 0.95)]

  • 一次性编码分类特征:根据特征描述文件识别多级分类特征,每个分类特征都被一次性编码为虚拟变量。
  • 平移变换混合型变量: 一些特征包含多个属性,被拆分成新的独立特征。例如,“CAMEO_INTL_2015”被拆分为“财富”和“人生阶段”属性。
  • 估算和缩放数据:模式方法估算剩余缺失值,用 StandardScaler 缩放数据。
imputer = SimpleImputer(strategy='most_frequent')
scaler = StandardScaler()

经过数据预处理后, Azdias 数据库的矩阵为 791244 x 395,客户数据库的矩阵为 140866 x 395。

主成分分析

具有多个特征会使数据分析的过程变得复杂,并且有必要在聚类分割之前降低数据的维度。在这个项目中,我进行了主成分分析(PCA ),将原始数据分解成几个不相关的主成分,仅保留 395 个成分中的 200 个,这解释了原始数据集约 88%的累积可变性。

n_components=200
pca = PCA(n_components=n_components,random_state=42)
azdias_pca = pca.fit_transform(azdias_scaled)

聚类和特征分解

我应用了 k -means 算法来将数据集分组到各个集群中,并使用了方法来找到正确数量的集群。方法的思想是运行k——意思是在数据集上对范围 k 进行聚类,并对 k 的每个值计算误差平方和(即k——意思是得分)。在 k 值和k-均值得分的图中,曲线上的“肘”是数据集的最佳聚类数。基于下面的方法结果,我使用 k 均值算法将数据集分成八个聚类。

# Number of different cluster counts
n_clusters = np.arange(2,21)# Run k-means clustering on the data and compute the average within-cluster distances.
scores = [MiniBatchKMeans(i).fit(azdias_pca).score(azdias_pca) for i in n_clusters]

将客户数据映射到人口统计聚类后,现在我们能够比较普通人群和客户公司的客户群之间的聚类分布。结果表明,集群 7 是该公司的主要客户群,因为它在其他客户中拥有最高的客户比例。这个集群可以被认为是“忠诚的客户”相比之下,聚类 2 显示出最低的客户百分比,并展示出一般人群和客户比例之间的最高负差。这表明,考虑到当前的营销策略,集群 2 中的一小部分人可能会成为客户公司的客户。对于客户公司来说,这里的机会是,针对集群 2 的人口定制营销策略将有可能吸引新的客户群。

聚类信息的分解揭示了什么类型的个体构成聚类 2 和聚类 7。首先确定哪些主成分对聚类更有意义,然后评估哪些特征可以解释特定主成分中的更多方差,同时通过逆 PCA 变换和数据缩放收集原始特征值。总之,我能够找出哪些类型的个人属于第 2 类和第 7 类。

忠诚客户:集群 7(中产阶级)

下面,我列出了十个最正相关的特征(红色),以及十个最负相关的特征(蓝色)。

客户公司的忠实客户大多年龄在 46-60 岁之间,属于中产阶级,有小规模的家庭。这些客户生活稳定,对金融投资兴趣不大,热衷于网上购物。

聚类 7 正相关特征

聚类 7 负相关特征

潜在客户:集群 2(富裕的上层阶级)

“车,车,车!”当我们看集群 2 的主要特征时,我们看到的都是豪华车。第二组中的人是昂贵的德国汽车的爱好者,除此之外,他们中的大多数人的祖先追溯到旧时代的西德。

聚类 2 正相关特征

聚类 2 负相关特征

外卖:家庭小、网购习惯活泼的中产个人,是客户公司的核心客户。如果客户公司想要扩大他们的客户群体,对德国豪华车感兴趣的来自西德的上流社会人士是潜在的营销目标。

第二部分。监督学习

当客户公司发出邮件报价时,我们能预测回复率吗?

这是一个典型的分类问题,建立一个有监督的机器学习模型是一个很好的解决方法。这部分的主要焦点是使用训练数据集来训练模型,并使用训练的模型来预测“响应”属性,即,确定测试数据集中的个体是否会响应邮寄要约。

数据探索

Arvato 提供的培训数据和测试数据包括以下内容:

  • Mailout_train —作为营销活动目标的个人的人口统计数据(42 982 x 367)。
  • Mailout_test —作为营销活动目标的个人的人口统计数据(42 833 x 366)。

如下图响应分布图所示,目标属性“response”在 Mailout_train 数据集中高度不平衡,有 42430 个否定响应,只有 532 个肯定响应,响应率仅为 1.2%。这种高度的不平衡会影响分类模型的训练,也会使常用的度量标准变得具有误导性(如准确性)。

数据预处理

第一部分的数据预处理过程已经实现为 clean 函数,可以在我的 GitHub 中找到。这里,我只是复制了相同的步骤来预处理 Mailout_trainMailout_test 中的数据。

实施和细化

由于“回应”中的数据高度不平衡,这里我采用的方法是计算个人对要约做出回应的概率,并分析做出回应的个人的集体特征,并使用这些信息来建议具有高回应概率的个人。ROC 曲线下的计算面积(假阳性率对真阳性率)用于评估机器学习模型的性能。

我考虑了以下五种分类算法:

  • AB: AdaBoostClassifier
  • GB:GradientBoostingClassifier
  • LR:物流回收
  • RF:RandomForestClassifier
  • XGB: XGBClassifier

为了评估这五种算法的性能,我创建了一个函数,当指定算法和参数时,它可以计算 ROC 得分。

def grid_search(estimator, param_grid, X=X, y=y):
    """
    Grid search a classifier by ROC score, using cross-  validation.

    INPUT:
    - estimator (classifier): name of classifier
    - param_grid (dict): parameters used with GridSearchCV
    - X (DataFrame): features from cleaned mailout_train dataframe
    - y (DataFrame): 'RESPONSE' from cleaned mailout_train dataframe

    OUTPUT:
    - classifier: fitted classifier
    - prints elapsed time and ROX AUC
    """

    grid = GridSearchCV(estimator=estimator, param_grid=param_grid, scoring='roc_auc', cv=5)
    grid.fit(X, y)
    best_estimator = grid.best_estimator_
    best_score = grid.best_score_
    return best_estimator, best_score

由于高度不平衡的响应属性,我通过 5 重交叉验证将 Mailout_train 数据集分成训练集和验证集,然后用默认超参数将数据拟合到五个算法中。

# Choose five classifiers, LR, RF, AB, XGB, and GB
models = []
models.append(('LR', LogisticRegression()))
models.append(('RF', RandomForestClassifier()))
models.append(('AB', AdaBoostClassifier()))
models.append(('XGB', XGBClassifier()))
models.append(('GB', GradientBoostingClassifier()))# Evaluate ROC AUC score of five classifiers with default parameter
for i in range(len(models)):
    score = grid_search(models[i][1], {})[1]
    print('ROC AUC score for {}: {}'.format(models[i][0], score))

AdaBoostClassifier (AB)和 GradientBoostClassifier (GB)是表现最好的模型,ROC AUC 得分分别为 0.7172 和 0.7564。从这一点开始,我使用网格搜索来调整 AB 和 GB 模型的超参数,将它们的 ROC AUC 分数分别增加到 0.7531 和 0.7570(见下面的红色柱)。

# Tune the hyperparameters of AB model
param_AB = {
          "learning_rate"     : [0.1,0.2],
          "n_estimators"      : [100,200,500]}
AB_tuned = grid_search(AdaBoostClassifier(), param_AB)# Tune the hyperparameters of GB model
param_GB = {
          "learning_rate"     : [0.1,0.2],
          "max_depth"         : [3,4],
          "n_estimators"      : [100,200],
          "min_samples_split" : [2,4]}
GB_tuned = grid_search(GradientBoostingClassifier(), param_GB)

然后,我研究了 AB 和 GB 模型的特征,看它们是否验证了我在第二部分的客户细分分析中得出的结论。不幸的是,两种型号中唯一突出的功能是“D19_SOZIALES”,该功能不包含描述,并且在第二部分中没有被确定为忠诚客户的相关功能。对“D19_SOZIALES”特征含义的大胆猜测是,它可能与交易历史有关,因此暗示着社会经济地位。

Kaggle 比赛

AB 和 GB 模型被用于预测 Mailout_test 数据集中的“响应”。AB 机型取得了 0.781 的成绩,GB 机型取得了 0.777 的成绩。这些结果被提交给了 Kaggle。

要点:建立机器学习模型是解决分类问题的最有效方法。我使用 AB 和 GB 算法构建了两个模型,两个模型都能够预测邮寄要约的回复率,得分约为 0.78。

结论

有人说 80–85%的数据科学项目在完成前失败,我感到幸运的是这个项目属于 15–20%。在这个项目中,我练习并应用了不同类型的数据科学技能来解决一个现实生活中的问题——找到忠诚和潜在新客户的特征,并预测个人是否会对邮件发送活动做出回应。

有改进的余地。主成分分析(PCA)受要素比例差异的影响很大,在这方面,使用 MinMaxScaler 等替代方法缩放数据可能会获得更好的性能。在监督学习部分,合成少数过采样技术(SMOTE)可能是解决不平衡分类问题的更好选择,因为这种方法允许人工合成数据以获得更平衡的数据集。

资信证明

本文使用的所有代码都可以在我的 GitHub 和 Tableau 上找到。

数据和资源由 Udacity 和 Bertelsmann&Arvato 提供。

助推对决:情感分类中的 Scikit-Learn vs XGBoost vs light GBM vs CatBoost

原文:https://towardsdatascience.com/boosting-showdown-scikit-learn-vs-xgboost-vs-lightgbm-vs-catboost-in-sentiment-classification-f7c7f46fd956?source=collection_archive---------3-----------------------

哪一个梯度增强库将在这场竞争中独占鳌头?

图像来源

梯度推进是近年来最流行的机器学习技术之一,统治了许多具有异构表格数据的 Kaggle 竞赛。类似于随机森林(如果你不熟悉这种集成算法,我建议你仔细阅读),梯度提升通过集成许多决策树来执行回归或分类。但是,与随机森林不同,梯度增强按顺序生长树,根据前一棵树的残差迭代生长树。这样做可以让梯度推进专注于特别棘手的观察,并产生一个异常强大的树木集合。

这是一种过于简单化的做法,并没有提到现有的各种 boosting 实现,但这并不是本文的目的。如果你有兴趣阅读更多关于 boosting 如何工作的细节,我在文章底部附上了一些有用的资源。

随着 XGBoost、LightGBM 和 CatBoost 等竞争算法争夺用户,梯度提升空间近年来变得有些拥挤。刚刚提到的三个是 Kaggle 比赛中最常见的,因为它们的速度、功率和 GPU 兼容性。有几篇文章已经在异构数据上比较了这些增强变体,例如:

  • CatBoost vs Light GBM vs XGBoost:

[## CatBoost 与轻型 GBM 和 XGBoost

谁将赢得这场预测战争,代价是什么?我们来探索一下。

towardsdatascience.com](/catboost-vs-light-gbm-vs-xgboost-5f93620723db)

  • XGBOOST vs LightGBM:哪种算法赢得了比赛!!!

[## LightGBM vs XGBOOST:哪种算法赢得了比赛!!!

这篇文章是关于在人口普查收入数据集上对 LightGBM 和 XGBoost 进行基准测试。我注意到了…的执行时间

towardsdatascience.com](/lightgbm-vs-xgboost-which-algorithm-win-the-race-1ff7dd4917d)

然而,还没有任何分析比较这些竞争对手在其他设置,如文本分类。这有一个很好的理由,因为梯度推进并不被认为是最适合这类问题的算法,但看看这种比较如何进行仍然很有趣!

关于数据

我们将分析斯坦福大学提供的大型电影评论数据集(链接如下),其中包含 50,000 篇与“正面”或“负面”标签相关联的电影评论。这些数据已经被分成训练集和测试集,每一个都有 25,000 条评论。我们的标签也非常平衡,共有 25,000 个正面和 25,000 个负面评论。我们应该承认这是多么干净,因为在文本分类中,我们很少有这种级别的分类平衡!

准备我们的数据

由于我们在这里强调的是比较梯度增强方法,因此我们将对文本数据执行简单的预处理,只需将其强制转换到数据框中,执行 tfi df-矢量化,这是一种将可变长度文本转换为单词包表示的常用方法,该单词包表示表示所述文本中转换后的词频。如果你不熟悉这项技术,我再次在文章底部放了一个链接,因为这是 NLP 领域的必读内容。我们将限制预处理数据帧中的单词数量,以使用 TFIDF 频率方面的 2000 个顶级单词。

我们还将把我们的训练集分割成一个训练集和一个验证集,这样我们就可以对一些没有在内部执行这种分割的功能的 boosting 候选项执行早期停止,这是一种正则化技术。

# Importing packages and data
from time import time
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.svm import LinearSVC
from sklearn.tree import DecisionTreeClassifier
from sklearn.experimental import enable_hist_gradient_boosting
from sklearn.ensemble import (RandomForestClassifier,
                              AdaBoostClassifier,
                              GradientBoostingClassifier,
                              HistGradientBoostingClassifier)
from xgboost import XGBClassifier
from lightgbm import LGBMClassifier
from catboost import CatBoostClassifier
import matplotlib.pyplot as pltdf_train = pd.read_csv('train.csv').sample(frac=1.0)
df_test = pd.read_csv('test.csv').sample(frac=1.0)# Preprocessing our data
tfidf = TfidfVectorizer(max_features=2000)
X_train = tfidf.fit_transform(df_train['text']).toarray()
X_test = tfidf.transform(df_test['text']).toarray()
y_train, y_test = df_train['negative'], df_test['negative']
X_train_sub, X_valid, y_train_sub, y_valid = train_test_split(X_train, y_train, test_size=0.1)# Setting up our results dataframe
df_results = pd.DataFrame(columns=['accuracy', 'run_time'])

设置我们的候选模型

我们将分析几个不同的基线模型以及我们的提升方法,每个方法都包含一个简短的总结,然后我们开始对我们的情感分类任务进行全面的比较。请注意,所有的准确性和运行时间将被记录在最终的视觉效果。在本节中,我们仅实例化我们的分类器。

决策图表

作为我们的第一个基线,我们将考虑最简单的情况:单个决策树分类器。我们将使用著名的 CART 算法的 Scikit-Learn 实现来逐级生成分类器,以对情感进行分类。请注意,这里我们可以做很多调整,例如正则化、树修剪和特征采样,但是对于我们的用例,我们将简单地指定速度的最大深度(否则,如果有 2,000 个特征和无限的深度,我们的树将会变得过深、过拟合,并且永远需要训练)。

dt = DecisionTreeClassifier(max_depth=12, random_state=1234)

随机森林

接下来,我们将考虑过去几十年中最有影响力的集成算法之一:随机森林。随机森林通过创建决策树的“森林”来工作,每个决策树都在训练数据的袋装(引导聚合)样本上进行训练。现在,我将继续从表面上概述 RF;如果你感兴趣,在页面底部有资源。随机森林在防止过度适应方面非常出色,并且往往开箱即用。我们将在我们的森林中使用 500 棵树,深度不限,作为比单一决策树更强的性能基准。

但是,请注意,从这一点开始,我们的所有增强算法(除 AdaBoost 之外)都将有一个类似于max_features的参数,该参数表示如何在每个树或分裂处对特征进行子采样(根据实现方式而不同),我们将该参数设置为 0.06,这意味着我们将在每个间隔对 6%的特征进行子采样。这样做是为了提高速度,减少过度拟合,并确保我们的候选模型之间的公平比较。为了公平比较,我们还将分布式计算限制在 6 个内核上(即使这些算法中的一些可能会随着内核的增加而有所不同)。

rf = RandomForestClassifier(n_estimators=500,
                            max_features=0.06,
                            n_jobs=6,
                            random_state=1234)

adaboost 算法

AdaBoost(T2 的简称)是早在 1997 年推出的首批主要助推技术之一。Adaboost 是梯度提升的一个特例,它使用一系列任何所需的弱学习器(这里通常选择决策树桩)来最小化指数损失。尽管早些年取得了很大成功,但这种算法在竞争环境中并不常见,因为它往往被更现代的提升技术超越。

如果你有兴趣了解 Adaboost 和梯度增强之间的区别,我在本文底部贴了一个链接。

base_estim = DecisionTreeClassifier(max_depth=1, max_features=0.06)                            ab = AdaBoostClassifier(base_estimator=base_estim,
                        n_estimators=500,
                        learning_rate=0.5,
                        random_state=1234)

梯度增强决策树(Scikit-Learn)

现在我们将进入第一个真正的梯度增强方法:梯度增强树。梯度提升是前述 Adaboost 算法的推广,其中可以使用任何可微分的损失函数。Adaboost 试图使用观察权重来通知训练,而梯度增强试图遵循梯度。在 Scikit-Learn 中,这个类的功能更加丰富;我们可以为正则化指定训练数据的子集化,并选择类似于随机森林的特征子集化百分比。请注意,虽然n_estimators被设置为 2000,但我们并不期望接近 2000,并且当我们的内部验证错误在 15 次迭代中没有改善时,早期停止将停止生长新的树。我们将遵循相同的早期停止过程,以便所有的增强方法都遵循这一过程。

请注意,大多数迭代算法都有可能提前停止,但我们没有将它与 AdaBoost 一起使用,因为它不包含在 Scikit-Learn 实现中。

gbm = GradientBoostingClassifier(n_estimators=2000,
                                 subsample=0.67,
                                 max_features=0.06,
                                 validation_fraction=0.1,
                                 n_iter_no_change=15,
                                 verbose=0,
                                 random_state=1234)

XGBoost

大多数严肃的 ML 从业者已经很熟悉,或者至少听说过 XGBoost(EXtremeGradientBoosting 的简称)。XGBoost 是一个梯度增强库,在 2014 年赢得 Kaggle Higgs 机器学习挑战赛后声名鹊起。这个库变得流行有几个原因:

  1. 它在底层树上实现了非常有效的正则化超参数。
  2. 它被构建为高度可伸缩的,利用分布式计算来处理极大的数据集。
  3. 它有许多不同的语言版本(如 Python、R、C、C++、Ruby、Julia 等。).

XGBoost 在现代比赛中仍然做得很好,XGBoost 社区在维护软件包和添加新功能方面做得很好。然而,它面临着来自其他 boosting 库(如 LightGBM 和 CatBoost)的竞争。XGBoost 库的一个缺点是,它不像竞争对手那样对分类特性进行任何特殊处理。这是不幸的,因为 boosting 库往往擅长表格数据,而表格数据通常包含离散的特性。然而,在我们的比较中,这无关紧要,因为我们的 TFIDF 表示只包含连续值特征。

还要注意,这里使用了与GradientBoostingClassifier,相似的参数,但也指定了tree_method='hist’。这将使用直方图宁滨对连续特征进行分类,减少需要分析的分割数量,这是 LightGBM 首先引入的技术。

xgb = XGBClassifier(n_estimators=2000,
                    tree_method='hist',
                    subsample=0.67,
                    colsample_level=0.06,
                    verbose=0,
                    n_jobs=6,
                    random_state=1234)

LightGBM

在我看来,截至 2020 年 3 月,LightGBM 是梯度推进库的王者。由微软在 2017 年推出的 LightGBM 是一个速度快得离谱的工具包,旨在为高维度的超大数据集建模,通常比 XGBoost 快很多倍(尽管当 XGBoost 添加了自己的宁滨功能后,这一差距缩小了)。LightGBM 通过以下方式实现这一速度:

  1. 与 XGBoost 类似,是高度分布式的。
  2. 种植树木时,使用叶子方向而不是水平方向的分裂。
  3. 使用连续特征的直方图宁滨(第一个这样做的增强算法)来减少分割的数量。

LightGBM 还通过使用一种特殊的最优分割算法,提供了对分类特性的特殊支持。

lgbm = LGBMClassifier(n_estimators=2000,
                      feature_fraction=0.06,
                      bagging_fraction=0.67,
                      bagging_freq=1,
                      verbose=0,
                      n_jobs=6,
                      random_state=1234)

CatBoost

最新的流行梯度增强库 CatBoost(CategoricalBoosting)是由俄罗斯科技公司 Yandex 在 2017 年年中开发的,紧随 LightGBM 之后。不幸的是,我还没有看到 CatBoost 持续优于其竞争对手(尽管它有许多分类功能,但它确实倾向于名列前茅),也没有比得上 LightGBM 的速度,但这肯定会随着未来的更新而改变。然而,CatBoost 适用于分类数据和文本数据,所以在决定为您的用例尝试哪些方法时,请对本文的结果持保留态度。

CatBoost 确实包括现成的文本功能(其他 boosting 库没有这种功能),但我们不会使用这种功能,因为它会改变 CatBoost 训练集的标记化方法,这又会扭曲我们的比较。因此,我们将坚持使用 CatBoost 的 tfi df-矢量化。(更新:本文底部有一个更新,展示了如何使用这个特性,以及它与我们的普通 TFIDF-vectorization 相比如何)

cb = CatBoostClassifier(n_estimators=2000,
                        colsample_bylevel=0.06,
                        max_leaves=31,
                        subsample=0.67,
                        verbose=0,
                        thread_count=6,
                        random_state=1234)

奖励:基于直方图的梯度增强机器(Scikit-Learn)

Scikit-Learn 最近发布了自己的直方图增强版本,名为HistGradientBoostingClassifier,其操作与 LightGBM 非常相似,速度比精确梯度增强快很多倍。然而,一个很大的警告是,截至 2020 年 3 月,Scikit-Learn 的实现只是实验性的,并且只包括少数超参数和两个损失函数。相对于它的精确对应物,HistGradientBoostingClassifier的一个改进是它包含了对缺失值的内置支持,以及一些关于如何将缺失观察值分配给叶节点的简单规则。

hgbm = HistGradientBoostingClassifier(max_iter=2000,
                                      validation_fraction=0.1,
                                      n_iter_no_change=15,
                                      verbose=0,
                                      random_state=1234)

比较我们的竞争对手

是时候进行我们的比较了!在开始我们的训练循环之前,我们需要创建几个对象,例如将我们的模型放入一个列表中,并提取类名以便稍后绘制:

models = [dt, rf, ab, gbm, hgbm, xgb, lgbm, cb]
model_names = [i.__class__.__name__ for i in models]

我们还想指定哪些模型需要在.fit()方法中提前停止。就我个人而言,我更喜欢非 Scikit-Learn 包的约定,其中您将一个离散的验证集传递给 es 的 fit 方法,而不是在内部执行分割(这给了您更多的控制)。

es_models = ['XGBClassifier',
             'LGBMClassifier',
             'CatBoostClassifier']

最后,是时候训练我们每个候选模特了!我们将为需要在.fit()方法中传递验证集的模型添加一点逻辑,以便提前停止。在每次运行结束时,我们将在测试集上附加我们的准确度,以及训练每个模型需要多长时间:

for m, n in zip(models, model_names):

    start_time = time() if n in es_models:
        m.fit(X_train_sub,
              y_train_sub,
              eval_set = [(X_valid, y_valid)],
              early_stopping_rounds=15,
              verbose=0)
    else:
        m.fit(X_train, y_train)

    run_time = time() - start_time
    accuracy = np.mean(m.predict(X_test) == y_test)

    df_results.loc[n] = [accuracy, run_time]

    del m

检查结果

现在,我们已经存储了所有的精度和运行时间,我们将把所有的数据打包到一个带有模型名称的数据框中,以便于以后使用。最后,我们将使用 matplotlib 可视化我们模型的测试精度和运行时间:

图 1:比较我们的候选模型之间的测试准确性

图 2:用绝对和相对时间比较我们的候选模型之间的运行时间(秒)

哇!正如我们从上面的图中看到的,LightGBM 似乎是这个用例中的明显赢家,比下一个 boosting 算法快三倍以上,同时在测试准确性方面也是最好的!LightGBM 的实现实际上非常快,它可以比我们单一的深度决策树更快地训练整个树集合!虽然每次运行之间可能会有一些差异,但这是如此之大的差异,以至于我们可以相当肯定地说它是赢家。

另一个问题是,CatBoost 在速度上表现不佳,与较老的库 XGBoost 的速度不太匹配。然而,随着 GPU 支持的启用和一些超参数调整,这种情况可能会改变。同样令人惊讶的是 Scikit-Learn 的HistGradientBoostingClassifier的性能,它比 XGBoost 和 CatBoost 都快得多,但在测试准确性方面似乎表现得不太好。我预计这个 boosting 类只会继续变得更好(记住它现在是实验性的),因为它甚至没有利用特性子集和其他库中存在的一些其他特性。

不出所料,AdaBoost 和 random forest 在运行时间上都落后了不少,但我对GradientBoostingClassifier的表现相当失望。这个类并不适合处理非常大的数据,但是如此大的性能差距是很有趣的。

看起来我们已经有了答案,LightGBM 是明显的赢家!

但是……

等等!其他算法呢?

我已经可以听到数据科学家和 ML 爱好者跃跃欲试地跳到评论区:“有更好的词汇袋模型!”,“你应该将这些与其他基线模型如神经网络或 SVM 进行比较!”,或者“在这里助推没有意义!”。

对于那些有这些想法的人,我完全同意你的观点。

我写这篇文章是为了看看 boosting 实现如何在非标准问题上进行比较,以及它们如何扩展到大范围的数据。不过,在我看来,boosting 算法对于这个用例来说并不理想,因为你可以用少得多的计算时间获得同样的性能。因为我们处理的是非常同质的数据,所以我们将我们的结果与一个简单得多的替代方法进行比较,这个替代方法通常用于单词袋的文本分类问题:SVM。特别是,我们将使用 Scikit-Learn 的LinearSVC类。

我们将在与我们的 boosting 候选数据相同的数据上运行我们的新模型,记录我们的测试准确性和运行时间,并将它们添加到前面的图中:

# Testing LinearSVC
svc = LinearSVC()
start_time = time()
svc.fit(X_train, y_train)
run_time = time() - start_time
preds = svc.predict(X_test)
score = np.mean(preds == y_test)df_results.loc['LinearSVC'] = [score, run_time]

图 3:比较我们的 SVM 与其他模型的测试精度

图 4:比较 SVM 和我们其他车型的训练时间

上面的两个图准确地显示了为什么当处理一个有大量先前文献的问题时,你不应该总是跳到最令人兴奋和最新的算法。支持向量机是一种已经存在了几十年的算法,其性能几乎与我们最好的最先进的 boosting 模型一样好,而训练速度却快了近十倍!这正好表明,根据手头的任务定制您选择的车型可能是几小时和几分钟的火车时间之差!

结论

我们查看了各种 boosting 库,以及它们如何在极宽的同质表格数据上进行比较,最终发现 LightGBM 是我们测试的所有库中最快、最准确的。然而,我们也表明,更传统的算法,如 SVM,仍然可以胜过最先进的和前沿的方法!看看当前流行的 boosting 库如何发展会很有趣!

感谢您的阅读!如果你有任何问题或意见,请在下面留下!

更新# 1—2020 年 4 月 28 日

CatBoost 团队最近发布了一个新版本 0.23,它将内部文本矢量化功能扩展到了 CPU(以前您只能使用 GPU 指定文本功能)。我不会深入讨论它们如何向量化的细节(你可以看看官方文档)。让我们来看看这个内置的矢量化与我们之前的结果相比表现如何:(注意,这是单独运行的结果,因此我们的结果与上面略有不同,但总体结果是相同的)

# Testing the CatBoost text feature
model = CatBoostClassifier(n_estimators=2000,
                           text_features=[0],
                           colsample_bylevel=0.06,
                           max_leaves=31,
                           subsample=0.67,
                           verbose=0,
                           thread_count=6,
                           random_state=1234)
model.fit(X_train_text,
          y_train_sub,
          eval_set = [(X_valid_text, y_valid)],
          early_stopping_rounds=15,
          verbose=0)

图 5:比较 CatBoost 内置文本矢量化的测试精度

图 6:比较 CatBoost 内置文本矢量化的训练时间

正如我们从上面看到的,利用 CatBoost 的内部文本矢量化功能,我们的火车时间几乎减少了一半!此外,我们可以看到,新的模型比我们迄今为止测试的任何其他方法都更通用。虽然我们没有达到与 LightGBM 相同的火车速度,但我们确实发现具有这一新扩展功能的 CatBoost 可以实现令人印象深刻的准确性!

参考

  • 大型电影评论数据集【https://ai.stanford.edu/~amaas/data/sentiment/ T3
  • tfi df-矢量化
    教程 https://towards data science . com/natural-language-processing-feature-engineering-using-TF-IDF-E8 b 9d 00 e 7e 76
  • 随机森林简介
    https://towards data science . com/an-implementation-and-explain-the-Random-Forest-in-python-77bf 308 a9b 76
  • Adaboost vs GBM 的有益帖子:
    https://stats . stack exchange . com/questions/164233/intuitive-explaining-of-differences-between-gradient-boosting-trees-GBM-ad
  • 梯度助推树上的幻灯片
    https://homes . cs . Washington . edu/~ tqchen/data/pdf/Boosted tree . pdf
  • XGBoost 主页
    https://xgboost.readthedocs.io/en/latest/
  • LightGBM 主页
    https://lightgbm.readthedocs.io/en/latest/
  • CatBoost 主页
    https://catboost.ai/

XGBoost 和不平衡类:预测酒店取消

原文:https://towardsdatascience.com/boosting-techniques-in-python-predicting-hotel-cancellations-62b7a76ffa6c?source=collection_archive---------5-----------------------

Boosting 是机器学习中一种非常流行的技术,旨在通过将许多弱模型组合成一个强模型来提高预测精度。

为此,增强被称为集成方法

在这个例子中,boosting 技术用于确定客户是否会取消他们的酒店预订。

数据概述和功能选择

训练数据从 AWS S3 时段导入,如下所示:

import boto3
import botocore
import pandas as pd
from sagemaker import get_execution_rolerole = get_execution_role()bucket = 'yourbucketname'
data_key_train = 'H1full.csv'
data_location_train = 's3://{}/{}'.format(bucket, data_key_train)train_df = pd.read_csv(data_location_train)

酒店取消表示响应(或相关)变量,其中 1 =取消,0 =继续预订。

用于分析的特征如下。

间隔

leadtime = train_df['LeadTime']
arrivaldateyear = train_df['ArrivalDateYear']
arrivaldateweekno = train_df['ArrivalDateWeekNumber']
arrivaldatedayofmonth = train_df['ArrivalDateDayOfMonth']
staysweekendnights = train_df['StaysInWeekendNights']
staysweeknights = train_df['StaysInWeekNights']
adults = train_df['Adults']
children = train_df['Children']
babies = train_df['Babies']
isrepeatedguest = train_df['IsRepeatedGuest'] 
previouscancellations = train_df['PreviousCancellations']
previousbookingsnotcanceled = train_df['PreviousBookingsNotCanceled']
bookingchanges = train_df['BookingChanges']
agent = train_df['Agent']
company = train_df['Company']
dayswaitinglist = train_df['DaysInWaitingList']
adr = train_df['ADR']
rcps = train_df['RequiredCarParkingSpaces']
totalsqr = train_df['TotalOfSpecialRequests']

绝对的

arrivaldatemonth = train_df.ArrivalDateMonth.astype("category").cat.codes
arrivaldatemonthcat=pd.Series(arrivaldatemonth)
mealcat=train_df.Meal.astype("category").cat.codes
mealcat=pd.Series(mealcat)
countrycat=train_df.Country.astype("category").cat.codes
countrycat=pd.Series(countrycat)
marketsegmentcat=train_df.MarketSegment.astype("category").cat.codes
marketsegmentcat=pd.Series(marketsegmentcat)
distributionchannelcat=train_df.DistributionChannel.astype("category").cat.codes
distributionchannelcat=pd.Series(distributionchannelcat)
reservedroomtypecat=train_df.ReservedRoomType.astype("category").cat.codes
reservedroomtypecat=pd.Series(reservedroomtypecat)
assignedroomtypecat=train_df.AssignedRoomType.astype("category").cat.codes
assignedroomtypecat=pd.Series(assignedroomtypecat)
deposittypecat=train_df.DepositType.astype("category").cat.codes
deposittypecat=pd.Series(deposittypecat)
customertypecat=train_df.CustomerType.astype("category").cat.codes
customertypecat=pd.Series(customertypecat)
reservationstatuscat=train_df.ReservationStatus.astype("category").cat.codes
reservationstatuscat=pd.Series(reservationstatuscat)

使用树外分类器前向和后向特征选择方法进行分析时,确定的特征如下:

  • 研制周期
  • 原产国
  • 细分市场
  • 存款类型
  • 客户类型
  • 所需的停车位
  • 到达日期:年
  • 抵达日期:月
  • 到达日期:周数
  • 到达日期:当月的某一天

助推技术

XGBoost 是一种提升技术,因其执行速度和模型性能而闻名,并越来越多地被作为默认的提升方法,这种方法实现了梯度提升决策树算法,其工作方式类似于自适应提升,但实例权重不再像 AdaBoost 那样在每次迭代时调整。取而代之的是,尝试用新的预测器来拟合前一个预测器产生的残差。

精确度与召回率和 f1 分数

当比较准确度分数时,我们看到在每个混淆矩阵中都提供了大量的读数。

然而,在精度召回之间存在一个特别重要的区别。

Precision = ((True Positive)/(True Positive + False Positive))Recall = ((True Positive)/(True Positive + False Negative))

这两个读数经常相互矛盾,也就是说,通常不可能在不降低召回率的情况下提高精确度,反之亦然。

对理想指标的评估很大程度上取决于所分析的具体数据。例如,癌症检测筛查出现假阴性(即表明患者没有患癌症,而事实上他们患有癌症)是一大禁忌。在这种情况下,召回是理想的衡量标准。

然而,对于电子邮件,人们可能更喜欢避免误报,例如,将一封重要的电子邮件发送到垃圾邮件文件夹,而实际上它是合法的。

f1 分数在设计一个更通用的分数时考虑了精确度和召回率。

哪个因素对预测酒店取消更重要?

从酒店的角度来看,他们可能希望更准确地识别出最终会取消预订的客户,这使得酒店能够更好地分配房间和资源。确定不打算取消预订的客户不一定会增加酒店分析的价值,因为酒店知道,无论如何,很大一部分客户最终都会坚持预订。

分析

该数据首先被分为 H1 数据集的训练和验证数据,H2 数据集被用作比较 XGBoost 预测与实际取消发生率的测试集。

以下是 XGBoost 算法的实现:

import xgboost as xgb
xgb_model = xgb.XGBClassifier(learning_rate=0.001,
                            max_depth = 1, 
                            n_estimators = 100,
                              scale_pos_weight=5)
xgb_model.fit(x_train, y_train)

注意,本例中的 scale_pos_weight 参数设置为 5 。这样做的原因是对次要类别的错误施加更大的惩罚,在这种情况下,响应变量中的任何 1 事件,即酒店取消。权重越高,对次要类上的错误施加的惩罚就越大。这样做的原因是因为数据集中 0 比 1 多,也就是说,坚持预订的客户比取消预订的客户多。

因此,为了有一个无偏见的模型,次要类上的错误需要受到更严厉的惩罚。

验证集性能

以下是训练和验证集的准确性:

>>> print("Accuracy on training set: {:.3f}".format(xgb_model.score(x_train, y_train)))
>>> print("Accuracy on validation set: {:.3f}".format(xgb_model.score(x_val, y_val)))Accuracy on training set: 0.415
Accuracy on validation set: 0.414

预测是这样生成的:

>>> xgb_predict=xgb_model.predict(x_val)
>>> xgb_predictarray([1, 1, 1, ..., 1, 1, 1])

下面是一个混淆矩阵,比较了验证集上的预测取消和实际取消:

>>> from sklearn.metrics import classification_report,confusion_matrix
>>> print(confusion_matrix(y_val,xgb_predict))
>>> print(classification_report(y_val,xgb_predict))[[1393 5873]
 [   0 2749]]
              precision    recall  f1-score   support 0       1.00      0.19      0.32      7266
           1       0.32      1.00      0.48      2749 accuracy                           0.41     10015
   macro avg       0.66      0.60      0.40     10015
weighted avg       0.81      0.41      0.37     10015

请注意,虽然 f1 分数(41%)的准确性很低,但类别 1(取消)的召回分数是 100%。这意味着该模型会产生许多误报,从而降低整体准确性,但这具有将召回率提高到 100%的效果,即该模型可以 100%成功识别所有将取消预订的客户,即使这会导致一些误报。

测试集上的性能

和前面一样,测试集也是从相关的 S3 存储桶导入的:

data_key_test = 'H2full.csv'
data_location_test = 's3://{}/{}'.format(bucket, data_key_test)h2data = pd.read_csv(data_location_test)

这是 XGBoost 模型在 H2 上的后续分类性能,这是本例中的测试集。

>>> from sklearn.metrics import classification_report,confusion_matrix
>>> print(confusion_matrix(b,prh2))
>>> print(classification_report(b,prh2))[[ 1926 44302]
 [    0 33102]]
              precision    recall  f1-score   support 0       1.00      0.04      0.08     46228
           1       0.43      1.00      0.60     33102 accuracy                           0.44     79330
   macro avg       0.71      0.52      0.34     79330
weighted avg       0.76      0.44      0.30     79330

f1 分数所指示的准确度稍高,为 44%,但是类别 1 的回忆准确度再次为 100%。

校准:磅秤位置重量

在这种情况下,观察到使用 5 的 scale_pos_weight 导致 100%的召回,同时将 f1 分数准确度非常显著地降低到 44%。

然而,100%的召回也是不可靠的。例如,假设 scale_pos_weight 被设置得更高,这意味着几乎所有的预测都表示响应为 1,即所有的客户都被预测取消预订。

如果预测所有客户都将取消预订,则该模型没有内在价值,因为不再有任何方法来识别可能会取消预订的客户与不会取消预订的客户的独特属性。

在这方面,更平衡的解决方案是具有高召回率,同时还确保整体准确度不会降得过低。

以下是分别使用 2345 的权重时的混淆矩阵结果。

秤重= 2

[[36926  9302]
 [12484 20618]]
              precision    recall  f1-score   support 0       0.75      0.80      0.77     46228
           1       0.69      0.62      0.65     33102 accuracy                           0.73     79330
   macro avg       0.72      0.71      0.71     79330
weighted avg       0.72      0.73      0.72     79330

秤重= 3

[[12650 33578]
 [ 1972 31130]]
              precision    recall  f1-score   support 0       0.87      0.27      0.42     46228
           1       0.48      0.94      0.64     33102 accuracy                           0.55     79330
   macro avg       0.67      0.61      0.53     79330
weighted avg       0.70      0.55      0.51     79330

秤重= 4

[[ 1926 44302]
 [    0 33102]]
              precision    recall  f1-score   support 0       1.00      0.04      0.08     46228
           1       0.43      1.00      0.60     33102 accuracy                           0.44     79330
   macro avg       0.71      0.52      0.34     79330
weighted avg       0.76      0.44      0.30     79330

秤重= 5

[[ 1926 44302]
 [    0 33102]]
              precision    recall  f1-score   support 0       1.00      0.04      0.08     46228
           1       0.43      1.00      0.60     33102 accuracy                           0.44     79330
   macro avg       0.71      0.52      0.34     79330
weighted avg       0.76      0.44      0.30     79330

scale_pos_weight 设置为 3 时,召回率为 94%,而准确率为 55%。当 scale_pos_weight 参数设置为 5 时,召回率为 100%,而 f1 得分准确率降至 44%。此外,请注意,将参数从 4 增加到 5 不会导致召回率或整体准确度的任何变化。

在这方面,使用 3 的权重允许高召回率,同时仍然允许总体分类准确度保持在 50%以上,并允许酒店有一个基线来区分取消预订的客户和没有取消预订的客户的属性。

结论

在本例中,您看到了使用各种提升方法来预测酒店取消预订。如上所述,在这种情况下,boosting 方法被设置为对 minor 类施加更大的惩罚,其结果是降低了由 f1 分数测量的整体准确性,因为存在更多的假阳性。然而,召回分数因此大幅增加——如果假设在这种情况下假阳性比假阴性更容易容忍——那么人们可以认为该模型在此基础上表现得相当好。作为参考,在相同数据集上运行的 SVM 模型展示了 63%的总体准确性,而在类别 1 上的召回率下降到 75%。

您可以在这里找到原始文章,它包括一个到 GitHub 资源库的链接,该资源库包含与上述示例相关的相关笔记本和数据集。

免责声明:本文是在“原样”的基础上编写的,没有任何担保。本文旨在提供数据科学概念的概述,不应以任何方式解释为专业建议。

有用的参考资料

  • 安东尼奥、阿尔梅迪亚和努内斯(2019)。酒店预订需求数据集
  • 分类:精度和召回率
  • 通过 Scikit-Learn 和 TensorFlow 进行机器实践学习
  • 机器学习掌握:应用机器学习 XGBoost 简介
  • 什么是 LightGBM,如何实现?如何微调参数?

用 Tensorboard 增强你的神经网络

原文:https://towardsdatascience.com/boosting-your-neural-networks-with-tensorboard-bc6ce815d55b?source=collection_archive---------40-----------------------

如何将你的实验结果形象化

神经网络(NNs)是强大的算法,通常用于深度学习任务。这类算法的美妙之处在于,神经网络是复合的,从某种意义上说,它们由多层组成,可以添加、删除、修改,通常还可以在训练后定制,以便尝试不同的网络配置(如果你想更深入地了解这种算法的功能,请查看我的文章这里)。

这样做的最终目的是获得能够返回高精度的算法。

这就是为什么在训练时对算法中正在发生的事情以及训练后最相关的结果有一个有意义的见解,是机器学习项目管道中的一个关键步骤。带着这个目的,在这篇文章中,我将谈论 Tensorboard 。

Tensorboard 是一个强大的仪表板工具,可以通过 pip 轻松安装,并且在不使您的代码变得更加复杂的情况下,能够返回一个非常有意义的仪表板,反映您的 NN 性能。

为了向您展示这个工具的强大功能,我将使用 Keras 设置一个图像分类器。

用 Keras Sequential()构建卷积神经网络(CNN)

为了构建我的模型,我将使用一个卷积神经网络,使用 t he Sequential()方法(您也可以使用 Keras Functional API 来实现相同的目的)。

我要解决的任务是机密任务。更具体地说,我下载了时尚 MNIST 数据集(嵌入在 Keras 中),其中包含 10 种不同时尚单品的图片。我们算法的目标将是正确地用相应的项目标记给定的图像。

因此,在开始构建模型之前,我们先来看看数据集。

#downloading necessary packagesimport tensorflow as tf
import datetime
from tensorflow import keras
import numpy as np
import matplotlib.pyplot as plt fashion_mnist = keras.datasets.fashion_mnist(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()#creating a list of labelsclass_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat','Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']

让我们检查第一个火车图像及其形状:

plt.figure()
plt.imshow(train_images[0])
plt.colorbar()
plt.grid(False)
plt.show()

train_images.shapeOutput: (60000, 28, 28)

因此,我们的训练集由 60000 张 28x28 像素的图像组成。如果图像是彩色的(RGB)而不是灰度的,我们在上面的张量中也会有第四维,表示通道。

在构建模型之前,我们还需要三个步骤,即:

  • 重塑 4D 物体中的张量(以便它们与 2D 卷积层兼容);
train_images = train_images.reshape((train_images.shape[0], 28, 28, 1))
test_images = test_images.reshape((test_images.shape[0], 28, 28, 1))
  • 一键编码标签集(训练和测试);
train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)
  • 在从 0 到 1 的范围内重新缩放像素(因为像素的范围是从 0 到 255)。
train_images = train_images / 255.0
test_images = test_images / 255.0

太好了!现在让我们建立一个简单的 CNN,它有以下几层。注意,在本文中,我不打算深入探究每一层和整个结构背后的数学原理。如果你对 NNs 的特性感兴趣,我推荐你阅读这篇文章。

#initializing Tensorboard extension%load_ext tensorboard#creating a logs directorylog_dir = "logs/fit/" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S")tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir=log_dir, histogram_freq=1)# number of possible label values
nb_classes = len(class_names) #10model = tf.keras.models.Sequential()model.add(tf.keras.layers.Conv2D(32,(3,3), padding='same', input_shape=(28, 28,1)))
model.add(tf.keras.layers.MaxPooling2D(pool_size=(2, 2)))
model.add(tf.keras.layers.Activation('relu'))
model.add(tf.keras.layers.MaxPooling2D(pool_size=(2, 2)))
model.add(tf.keras.layers.Dropout(0.25))
model.add(tf.keras.layers.Flatten())model.add(tf.keras.layers.Dense(nb_classes, activation='softmax'))
model.summary()

现在让我们训练我们的模型,确保将训练集的 20%作为验证集:

log_dir = "logs/fit/" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir=log_dir, histogram_freq=1)model.fit(train_images, 
          train_labels, 
          validation_split=0.2,
          epochs=10,  
          callbacks=[tensorboard_callback])

注意,添加tf.keras.callbacks.TensorBoard回调确保了日志的创建和存储:这在调用 Tensorboard 扩展时是需要的。

用 Tensorboard 可视化这一切

一旦我们的模型被训练好,通过使用%tensorboard logdir logs/fit magic 命令,我们可以可视化我们的结果的一个很好的仪表板:

当然,一切都是互动的:

正如你所看到的,Tensorboard 提供了各种各样的视觉项目,有助于深入了解 CNN 的表现和结构。请注意,在字段中,您可以以互动的方式可视化您网络的整体结构。

因此,只需几行额外的代码,我们就成功地将我们的网络变成了一个具有非常有趣的洞察力的可视化仪表板。

我希望你喜欢阅读!如果你对这个话题感兴趣,我建议你阅读文档部分的更多内容。

参考资料:

  • https://keras.io/guides/functional_api/
  • https://keras.io/
  • https://www.tensorflow.org/tensorboard/get_started
  • “用 Python 进行深度学习”, Francois Chollet

通过“波束搜索+语言模型”解码提升序列生成性能

原文:https://towardsdatascience.com/boosting-your-sequence-generation-performance-with-beam-search-language-model-decoding-74ee64de435a?source=collection_archive---------11-----------------------

https://www . shutterstock . com/image-vector/digital-binary-code-matrix-background data-flood-1341680024

波束搜索和 LM 解码的时间、原因和方式

每当涉及图像处理、音频数据分析或自然语言处理(NLP)任务时,深度学习都被证明是一个理想的选择,并显示出出色的成果。基于神经网络的模型架构在理解复杂模式以及生成有意义和现实的数据方面非常出色。虽然基于深度学习的解决方案通常非常有效,但使用更好的后处理技术来使预测更加准确从来都不是一个坏主意。

复杂的问题,如神经机器翻译(NMT),图像字幕生成(ICG)和语音识别(ASR),今天都可以通过深度学习来解决。这些问题被归类为序列生成问题,其中给定一个输入,模型学习生成一些文本序列。如果你看一看显示这些任务最先进( SOTA )结果的研究论文,你可能会发现他们的解决方案利用波束搜索解码器与语言模型融合来提高结果。让我们通过例子来了解更多关于这些解码技术的知识——

更进一步,我们将定义一个示例序列生成问题,并探索后处理(解码)技术。我们将从贪婪搜索解码技术开始,并引入融合语言模型的波束搜索解码来进一步改善整体结果。

示例问题

考虑一个英语文本生成的问题,并假设我们已经训练了一个模型来做这件事。根据问题的性质或解决策略,我们的模型可能是字符级模型或单词级模型。字符级文本生成器模型通过一次预测一个字符来生成文本。类似地,单词级文本生成器一次预测一个单词,多个预测的单词组成一个序列。

假设我们已经训练了一个字符级模型,它通过一次预测一个字符来生成文本。此问题可能与以下任何问题相关—语音转文本、光学字符识别、图像字幕生成等。此类问题通常使用编码器-解码器架构来解决,如下图所示。编码器部分负责获取输入向量(音频、图像或文本……)并产生编码的上下文向量。然后,解码器部分使用该上下文向量,通过一次预测一个令牌(char/ wordbbb)来生成输出序列。

https://stack overflow . com/questions/45977990/tensor flow-how-to-embed-float-sequences-to-fixed-size-vectors

由于我们的模型是字符级的,它将为输出序列中的每个标记生成所有可能字符的概率分布。换句话说,对于我们的模型预测的每个单词(char),它将生成一个长度为 26 的概率数组(根据英语——a 到 z ),概率将显示特定字符成为输出单词的可能性。

对于一个长度为 10(字符) 的预测序列,我们的模型的输出看起来像这样

output_shape = **10 * 26** output = [[**0.1**, 0.01, 0.03, ... ... ... ... ... (len-26)],
          [0.1, 0.002, **0.6**, ... ... ... ... ... (len-26)],
            ''         ''         ''      ''       ''    
            ''         ''         ''      ''       '' 
          [**0.9**, 0.01, 0.01, ... ... ... ... ... (len-26)]]

要将这种概率输出转换成可读形式(英文文本),我们需要一种解码算法。最简单的解码器是贪婪搜索解码器。让我们写一个贪婪搜索解码器和一个叫做波束搜索解码器的复杂解码器

  • 注意— 序列生成问题不一定涉及文本生成,它可以是任何种类的序列。我们以文本生成问题为例,因为在这篇文章中我们也将讨论语言建模。

贪婪搜索解码器

解码模型预测的最简单方法是将最可能的序列视为输出。贪婪解码器,也称为最佳路径解码器,在每次预测中考虑具有最高概率的标记(字符或单词),并连接所有预测的标记以获得最终的输出序列。这是获得输出序列的简单而快速的方法。但它可能不会总是给你最好的输出。

下面是你如何用 Python 为你的模型写一个贪婪的解码器—

这里模型预测的形状是 5*4 这意味着,模型试图生成一个长度为 5 的序列。由于词汇表中只有四个不同的标记,该模型预测序列中每个标记大小为 4 的概率分布。根据定义,贪婪解码器通过在每个时间步长选择最可能的记号来生成具有最高概率的序列。

波束搜索解码器

波束搜索解码是另一种流行的解码模型预测的方法,它在几乎所有情况下都比贪婪搜索解码器产生更好的结果。与贪婪解码器不同,它不仅仅考虑每次预测最可能的令牌,它还考虑具有更高概率的前 k 个令牌(其中 k 被称为波束宽度波束尺寸 )。虽然波束搜索给出了更好的结果,但是由于计算复杂,它使得整个流水线很慢。

因此,它不只是给你一个输出序列,它给你 k 个不同的输出序列以及它们的可能性(概率)。与只有一个输出序列的贪婪解码器不同,这里有 k 个不同的输出序列,这 k 个序列中很有可能有一个是正确的输出序列。

算法

对于第一个时间步预测,选择 k 个概率较高的令牌,而不是一个(因为在 greedy 中我们只选择一个)。现在更进一步,考虑当前预测的每个记号,并将其附加到所有先前解码的 k 个序列,并继续计算新序列的相应概率。现在根据概率得分从新序列中选择前 k 个序列,并移动到下一个时间步。重复这个过程,直到最后一个令牌。最后,返回 k 个序列及其对应的概率值。

提示: 单词波束搜索 是波束搜索解码技术的另一种变体,其限制或选择仅具有字典单词的输出序列。在大多数情况下,它比普通的波束搜索执行得更好。

用 Python 编写波束搜索解码器—

为什么是对数似然法?

这是因为当有更长的序列时,常规概率会引起问题。例如—考虑由模型生成的长度为 100 的序列。并且序列中每个记号的概率是 0.10 那么输出序列的概率将是所有这些概率的乘积—

Probability of a sequence with 100 tokens would be--
P(sequence) = **p(t1) * p(t2) * p(t3) .............. * p(t100)**
            = 0.1 * 0.1 * 0.1 * .................... * 0.1
            = **10 ^ (-100)** # An extremely small number 

正如我们所见,这是一个非常小的数字。任何编程语言都可能无法比较如此小的浮点数,因为这可能导致下溢。这就是为什么我们计算对数概率而不是常规概率。如果你注意到我们用负对数概率相乘来计算分数(代码中的第 16 行),这是因为概率的对数(0 < 1.0)总是负数。因此我们选择对数分数最小的前 k 个序列。

有 N 个记号的序列的概率是—

**P(seq)** = p(t1) * p(t2) * p(t3) ........ p(tN)### taking log on both sides (calculate **log-likelihood**)**log(P(seq))** = **log(**p(t1) * p(t2) * p(t3) ........ p(tN)**)   log(P(seq)) = log(p(t1)) + log(p(t2)) + .. log(p(tN))**### logarithm of a number < 1.0 will be always negative so  in this ### case log-likelihood of the sequence would be negative.

如果我们在两边取一个的对数,这个乘法就会转换成求和。因此,对数似然的计算而不是真实概率的计算会更快更有效。我们知道一个数< 1.0 的T5【对数】T6永远是负数。所以我们的序列会得到一个负的分数。我们可以通过取该分数的反对数,将该分数(对数似然)转换为原始概率。为了使用波束搜索找到 k 个最佳序列,我们只需要比较某些序列的概率,所以对数似然法就可以了。

++语言模型

现在我们知道,波束搜索解码器给你 k 个不同的输出序列,而不是一个,很有可能这些序列之一是正确的输出。但是我们没有办法确定哪个输出序列是最好的。这就是语言模型发挥作用的地方。

什么是语言模型?

语言模型是给定语言的统计表示。如果给定一个句子中先前出现的单词列表,它应该能够猜出下一个单词。换句话说,语言模型可以确定给定文本序列(句子)的概率,其中序列标记(字符/单词)是从固定词汇表(语言词汇)中提取的。所以,基本上它能给你的句子打分。一个好的分数意味着句子在语境上是正确的,并且属于给定的语言。

语言模型通常在非常大的文本语料库上训练,并且能够理解(学习)给定句子中单词的上下文(共现)。语言模型不一定是单词级别的,我们也可以在字符上训练语言模型。字符级语言模型应该在给定前几个字符的情况下猜测序列中的下一个字符。同样,字符级模型也可以给你一个给定句子的概率(或可能性)。

对文本序列评分的语言模型

考虑一个场景,其中深度学习模型试图生成一些文本(或者考虑一个问题,其中模型试图将语音转换为文本),并且得到的字符概率分布被发送到波束宽度为 5 的波束搜索解码器。假设以下是使用波束搜索解码生成的前 5 个序列。

***Generated Sequences **                  **           Probability (model)**1\. *speech recogniiion is a hald problem* ***0.41*** *2\. speech recog niiion isa hard problem           0.39
3\.* ***speech recognition is a hard problem*** *0.37
4\. spe ech recogniion is a hard problem           0.32
5\. spe ech recogni tion is ahard problem          0.29**

贪婪搜索解码器将给出第一个序列作为输出,因为根据我们的模型,它是具有最高概率(0.41)的序列。但显然(3)是正确的输出,只是概率稍小。

为了找到这 5 个序列中的最佳序列,我们将使用语言模型来检查每个英语序列的可能性。如果我们的语言模型训练有素,它应该给第三个序列一个很好的概率(分数),因为它按照英语是 100% 正确的。

假设根据我们的语言模型,以下是这 5 个序列的可能性。

***Generated Sequences **                  **      Probability  Probability
                                              (model)      (L.M.)**1\. *speech recogniiion is a hald problem* ***0.41*** *0.20
2\. speech recog niiion isa hard problem         0.39        0.40
3\.* ***speech recognition is a hard problem*** *0.37* ***0.70*** *4\. spe ech recogniion is a hard problem         0.32        0.35
5\. spe ech recogni tion is ahard problem        0.29        0.47**

现在,为了选择最佳输出序列,我们将考虑两种概率的加权和—

 ***P(final)** = *Alpha* ***** **P(model)** **+** *Beta* ***** **P(L.M.)***

常量*Alpha**Beta*的值是在验证数据集上调整后决定的。我们选择在验证集上给出最佳结果的值。然后,我们使用这些值在测试集上评估我们的模型。

***注:**有时在计算一个序列的最终得分时,也会考虑序列长度。如果我们不惩罚序列长度的分数,我们的模型将给予更小的序列更多的优先权。因为对于更长的序列,分数会更小(更多概率值的乘积(p < 1.0)会导致更小的分数)。

提示: 据观察,使用 单词级语言模型 在大多数情况下会给出更好的结果。为了能够使用单词级语言模型进行评分,输出序列应该仅限于字典单词。因此,使用词束搜索算法来得出受限制的词束,然后用语言模型对这些词束重新评分,以决定最终输出。

PS: 通常,根据研究论文,当应用波束搜索时,使用非常大的数字作为波束大小(~ 1000–2000)。它提供了更好的结果,但是以速度为代价,因为推理变得非常慢。

原刊此处。

很少有研究论文利用波束搜索解码和语言模型来改善结果—

  1. https://papers . nips . cc/paper/5346-sequence-to-sequence-learning-with-neural-networks . pdf
  2. 听、听、拼(https://arxiv.org/pdf/1508.01211.pdf)
  3. 展示和讲述(【https://arxiv.org/pdf/1411.4555.pdf】)
  4. 音序器(https://arxiv.org/pdf/1901.01808.pdf)

图像来源:

  1. **(矩阵图像)https://www . shutterstock . com/image-vector/digital-binary-code-matrix-background data-flood-1341680024
  2. **(LSTM 自动编码器)https://stack overflow . com/questions/45977990/tensor flow-how-to-embed-float-sequences-to-fixed-size-vectors

就这样吧!

感谢阅读,别忘了和我分享你的想法。

在 2020 年推动您的小型企业

原文:https://towardsdatascience.com/boosting-your-small-business-in-2020-6ae3529cbfb0?source=collection_archive---------33-----------------------

照片由Á·阿尔瓦罗·塞拉诺在 Unsplash 上拍摄

毫无疑问,2019 年是人工智能(AI)年。我们已经听说了很多,但许多人不确定这是否只是最新的时尚,或者是否会持续下去。

如果我们稍微观察一下我们周围世界正在发生的事情,到 2025 年,人工智能产业将在全球范围内增长到 1900 亿美元的产业。23%的企业已经在以某种形式使用人工智能,到 2021 年这一比例将上升至 75%。事实上,根据国际数据公司(IDC)的数据,今天 40%的数字化转型都使用了人工智能服务。

有人可能会说,这适用于大公司,但不适用于小企业。这种假设与事实相去甚远。在这篇文章中,我们将看看人工智能如何帮助小企业,特别是;餐馆,零售商,服务行业和那些在酒店工作的人。

照片由丹金在 Unsplash 上拍摄

让我们看看餐馆。公司账目已经记录了与原材料采购相关的大部分数据。销售记录可以通过销售点系统获取。此外,如今大多数餐馆都有自己的网站或 facebook 页面。如果将这三条信息结合起来,再加上一些人工智能,餐馆老板就能对未来的经营有一些难以置信的洞察力。该系统可以很容易地计算客流量(即使考虑到季节性、节日等)。),并且它将能够分析客户。它本质上意味着人工智能可以预测;什么时候有人会预订一张桌子,有多少人,他们可能会点什么。这样做的效果是,餐馆老板可以采用一种及时的订购系统,从而减少食物浪费,最终降低约 12%的成本。人工智能甚至可以分析社交媒体上的评论,并对餐厅提出可能的改进建议。

人工摄影在 Unsplash 上拍摄

谈到零售,大多数商店都依靠冲动购物。为了满足顾客的需求,零售商需要根据顾客的喜好增加库存。然而,过多的库存可能会有问题,因为它可能会导致库存积压。同样,鉴于大部分数据都是可用的,人工智能可以用来帮助零售商提高销售额。聊天机器人可以通过脸书网页回答用户的询问,还可以一周七天、一天 24 小时出售特定商品。在线门户网站,结合有针对性的宣传活动,可用于在线销售无库存商品。剖析客户有助于预测未来的购买。然后它会减少库存订单;从而储存更少的库存,但获得更显著的销售。这种系统还能够预测客户流失,并显著提高现有客户的保留率。

蒂姆·莫斯霍尔德在 Unsplash 上的照片

在服务行业中,时间至关重要。正因为如此,简单的自动化任务可以走很长的路。最基本的是安排约会。想象一下,一家理发店雇佣了四名理发师。每个理发师每个月可以服务大约 375 个客户(假设每个客户 30 分钟,一周工作 6 天)。因此,这家有四名理发师的商店每月总共有 1500 个预约。如果每个预约都是通过电话进行的,并且每个电话持续 1 分钟,这意味着一个理发师每个月花整整三个工作日来安排预约而不是理发。在这种情况下,一个简单的在线系统就可以实现整个过程的自动化!

照片由菲利奥斯·萨泽德斯在 Unsplash 上拍摄

酒店业也可以从人工智能中受益,不管你是拥有一家小型 Airbnb 还是一家大型酒店。人工智能系统可以用来分析列表,对评论进行情感分析,并就如何改善这个地方提出建议。自动翻译使与外国人的交流更加容易,因为电子邮件可以被翻译成地球上最常用的语言。分析有助于预测未来趋势和入住率。客户特征分析将有助于为客户提供个性化的独特体验。最后,人工智能可以用来缓解人员招聘和提供足够的培训。

从上面提到的各种例子中可以看出,无论业务规模大小,AI 都在几个用例中使用。2020 年,我们将在不同的经济领域体验到更广泛的人工智能应用,因为人工智能为任何使用它的组织提供了竞争优势。正因为如此,为什么不制定一个新年计划,并开始关注人工智能带来的可能性。

本文原载于【https://www.businesstoday.com.mt】

Alexei DingliProf 是马耳他大学的 AI 教授。二十多年来,他一直在人工智能领域进行研究和工作,协助不同的公司实施人工智能解决方案。他的工作被国际专家评为世界级,并赢得了几个当地和国际奖项(如欧洲航天局、世界知识产权组织和联合国等)。他已经出版了几本同行评审的出版物,并且是马耳他的成员。由马耳他政府成立的人工智能工作组,旨在使马耳他成为世界上人工智能水平最高的国家之一。

训练营及以后

原文:https://towardsdatascience.com/bootcamp-beyond-7c37bbde521d?source=collection_archive---------35-----------------------

使用 Deepart.io 在神奈川的巨浪和我的一幅画之间创建。

“你是如何成为数据科学家的?”

我经常被问到这个问题,我想我终于可以把我的故事写成文字了。我的目的是给你一些我在通往数据科学的道路上和飞跃中学到的经验。总的来说,我认为这是我做过的最好的决定之一。

我的背景🔙

在大学学习计量经济学时,我分析了预测一个人收入的变量,其中最大的因素是…父母的收入。等等,什么?出生在贫困家庭,父母只有 19 岁,我开始解开我对美国梦的概念。这是否意味着我也注定要经历同样的挣扎?进一步挖掘,发现和我一样的人只有 14%大学毕业。有道理,因为我也是全职工作,并没有真正睡觉。此外,我估计大约 5%的其他数据科学家像我一样是经济学本科。这些估计让我相信大约 1%的数据科学家在这方面是相似的。

我强调这些外部因素,因为我认为我在很多方面都非常幸运。我知道这些基本利率,并积极努力消除那些不利的基本利率。

这是第一课:了解你的基础利率。考虑到你的背景和具体的挑战,可能性有多大?他们是支持你还是反对你?如果机会对你不利,调查你可以用什么方法来增加你成功的机会。即使显示“不可能”,这并不一定意味着不可能。

进入🥾训练营

我一直热爱数学、逻辑和批判性思维。虽然我当时并不知道,但这些是数据科学的先决条件。然而,我对数据科学的兴奋遇到了旧金山湾区的一个销售角色。我的销售角色允许我在包装消费品领域探索一些饮食分析。但是,我需要出去。

销售轮换计划结束后,我开始承保商业贷款。当时我认为“银行支付更多”,但发现银行业通往分析的道路太长了。在转变为分析师角色之前,我必须承担两年多的贷款——即使是数据科学也不行。大学毕业两年后,我迈出了一大步:数据科学训练营。

被引导到新兵训练营

在 Kickstarter 活动的初步实得分析中获得 a。通过 Dataquest,用训练营的在线必修课程准备我的新生编码技能。我已经准备好参加数据科学沉浸式培训,这是一个为期 3 个月的全日制项目。

第六届数据科学沉浸式团队[DSI-6]是由 9 名斗志昂扬的专业人士组成的团队,他们希望进入一个预计未来 10 年增长 15%的行业。即使我在多年后写下这篇文章,我们大多数人仍然保持着联系。上课时间是 9-5 点,但我们一直呆到校园关闭,周末还要学习。很激烈。很有趣。我申请了私人学生贷款。

这是一个很大的风险,因为我有一些存款,没有安全网,还承担了额外的债务。我计划了 8 个月的消耗率——包括训练营。

这是第二课:了解你的项目期间和之后的财务状况。我强烈地,强烈地向你推荐有激励机制的训练营。无论是像 Lambda School 一样占你未来工资的一定比例;像跳板一样 6 个月没找到工作就付 0 美元;或者是低成本、新进入的第四大脑(由吴恩达的人工智能基金支持)。最终,你希望你的训练营项目直接投资于你最初的成功。

从编码到搜索策略💼

每周 80 小时的编码、调试和机器学习结束了。因为相对于你想申请的职位来说,只有一小部分职位在网上发布,所以大部分的求职都是通过申请/网络和大量的“观望”来完成的。在我空闲的时候,我决定和 DSI-6 的一个朋友一起参加一个追逐比赛。Kaggle 是一个竞争平台,一家公司众包一个问题给数据科学家,以达到一个最佳分数(通常在某些味道中误差最低)。经过几周的“申请/网络,等着瞧”之后,我见到了一家商业地产初创公司的工程总监。幸运的是,Kaggle 竞赛的重点是房地产——Zillow 100 万美元的奖金。

在我面试的那天,我粗制滥造了几个模型,把错误率降低到 0.0745(第一名是 0.0732)。然后我从市场街上的菲尔茨冲刺了几个街区,希望 XGBoost 不要花那么长时间。在与首席技术官、主管和首席架构师的演示结束后,我立即得到了一份工作。值得。

这是第三课:建立你的投资组合。找到您真正感兴趣的数据集,并希望了解更多关于特定问题的信息。你必须做出什么样的假设?你是如何清理和重新格式化数据的?你如何生产你的代码?我的训练营顶点预测了风险投资(有目的地概括)然后我预测了房地产价值。旨在让运气和机会相遇。

第三课警告:我建议不要使用 Kaggle,因为它所涉及的工作并不完全适用于“现实世界”的问题。优化单一指标会严重“过度拟合”速度极慢的模型的数据。在我的 Zillow 示例中,我将 3 个计算密集型模型的输出混合到最终回归中。不清楚你在工作中是否需要这样做。

数据科学家✅

这是我能给出的从训练营向数据科学家过渡的三个最重要的经验。

  1. 了解你的基本利率,积极提高你的赔率
  2. 选择一个能直接激励你被雇佣的训练营
  3. 通过让运气和机会相遇来建立你的投资组合

接下来,我要写一写我作为一名数据科学家最初的过山车经历。先睹为快:商业地产创业失败。在那之前,我很想听听你参观数据科学训练营的经历。一路走来,你学到了哪些道理和教训?

美国国家教育统计中心 发现,出生于社会经济地位最低的四分之一人口中,只有 14.2%的人获得学士学位或更高学位。

事实上 工程以“尽管该领域主要由拥有硕士和博士学位的人组成,但仍有大量拥有学士学位的人(26%)担任这一角色。”从第二张图中,我估计大约 15%的人拥有商业/经济学学位。由于肯定有重叠,我将这些百分比的乘积增加到 5%。

根据美国劳工统计局(2020 年 10 月访问) 的数据,信息(数据)科学家市场预计在 2019-2029 年间增长 15%。取决于你何时看到这篇文章,BLS 更新了他们的预测增长,我记得在 2017 年是 20%。

训练营培养不出高素质的数据科学家

原文:https://towardsdatascience.com/bootcamps-dont-make-high-caliber-data-scientists-9cba935602a5?source=collection_archive---------13-----------------------

为什么自学是 2020 年有抱负的数据科学家的出路

数据科学家的角色被吹捧为过去几年最热门的职业之一。随着物联网的不断发展,对数据科学家的需求也将增长。

对数据科学家的需求导致了员工招聘策略的转变。需要拥有高等学位才能被考虑担任数据科学家角色的日子已经一去不复返了。事实上,如今四年制大学学位不再是一项要求。

越来越多的雇主开始意识到一个现实,即正规教育不一定代表能力,尤其是在科技领域。

因此,在过去几年中,数据科学训练营的数量激增。世界各地有几十个项目可供选择,每个项目都承诺可以把你变成一名数据科学家。

如果你不熟悉什么是训练营,训练营是一个技术培训项目,向注册学生教授特定的专业。成功完成后,毕业生将获得结业证书,并加入他们的作品集。许多初学者认为这个证书是必要的,以表明他们接受了高水平的教育,然而,这实际上是不正确的。

我将权衡并分享我对参加训练营的一些好处的想法,同时也探索一些不那么明显的缺点。在我看来,2020 年将是自学成才的数据科学家之年。

上诉

训练营可以提供很多东西,因此他们作为一个商业企业取得了全面的成功。这些项目的推介都非常简单:注册并完成我们的数据科学项目,你将很快找到你梦想中的工作

对于任何有兴趣从事数据科学职业的人来说,这有很大的吸引力:

  • 构建你自己的学习的责任从你的肩上卸下来了,你所需要做的就是沿着你面前的路走
  • 在老师/导师/助手的指导下,你将能够创造出可以写进简历的项目
  • 在你参加夏令营期间,你有一个由同学、老师和其他工作人员组成的支持系统。
  • 你将获得结业证书,证明你已经接受了数据科学领域的培训
  • 一些机构为他们的毕业生提供额外的职业支持。
  • 一些机构提供不同的支付项目,包括延期支付直到你被雇佣。

这听起来像一个了不起的交易。数据科学是一个每天都在增长的巨大空间,几乎每周都有新技术出现(感觉上是这样)。尽管网上有几乎无限的免费资源,但作为一名新科学家,要想知道如何组织自己的学习可能会非常困难。这也可以是自我激励和保持学习纪律。

那么…如果可以,你为什么不想参加训练营呢?

的(不那么明显的)缺点和不足

训练营是一个合法的教育选择。许多大学培养出了能够获得各种工作机会的数据科学毕业生。但是,要考虑一些重大的缺点

  • 训练营任务

训练营旨在将学生变成入门级职位的合适候选人,通常是在初创公司或中小型公司。它们并不是为了让你成为一个能轻易在 FAANG 公司( F acebook、 A pple、 A mazon、 N etflix、 G oogle)或优步或 Airbnb 等独角兽初创公司获得职位的候选人。

Bootcamps 会以一种暗示他们的许多毕业生进入顶级科技公司的方式做广告,然而,这是非常不诚实的。在这些顶级职位上工作的毕业生应被视为异类,不应被视为常态

一般来说,能够获得 FAANG 职位的训练营毕业生之所以能够做到,是因为他们的简历上有比简单的结业证书更多的东西。他们可能比普通的训练营学生(普通学生只有 28 岁)有更多的工作经验和更多的正规教育。数据管理、咨询、写作和口语方面的额外经验也是数据科学家非常需要的技能。

永远记住训练营是一个商业企业。虽然训练营可以从技术上声称他们的课程培养出了 FAANG 级别的数据科学家,但事实是他们的课程并不是学生成功的唯一原因。

  • 教育质量

训练营因在短时间内塞进大量信息而臭名昭著,学生们不仅要跟上,还要掌握材料。一般来说,大多数夏令营持续时间在 3 到 6 个月之间,需要全职投入(每周至少 40 小时)。

候选人必须具备以下技能,才能被录用为入门级职位:

  • 精通 Python 或 R (Python 更受追捧)
  • 精通 SQL
  • 精通统计学、线性代数和微积分是一个很好的奖励。此外,候选人应该熟悉利用各种评估指标创建、运行和评估 A/B 测试。
  • 熟练使用 Matplotlib,Seaborn,Pyplot 等进行数据可视化。(Tableau 是一个不错的加分项,但不是必需的)
  • 精通监督和非监督机器学习技术。具有管道开发、模型评估和优化的经验。

这是训练营将提供的大部分课程,是几个月内要塞进去的大量信息。假设你能跟上并达到上述技能的熟练程度,你将勉强有资格成为一名入门级的数据科学家。然而,还有太多太多的东西要学。

这些是大多数雇主寻找的额外技能(当然取决于行业:)

  • 自然语言处理
  • 深度学习
  • 时间序列分析
  • 大数据分析
  • 云计算
  • 生物统计学
  • 机器人和计算机视觉
  • 还有更多!

同样,这是大量的额外学习材料。训练营不可能在短时间内提供无所不包的数据科学教育。这根本不可能,要学的东西太多了。

理论上,毕业后你可以学习额外的技能。你也可以花更多的时间重新学习和掌握核心课程,成为更好的科学家。

但是……如果你需要进行几个月的额外自学,你不是一直自学会更好吗?

  • 货币和机会成本

大多数对数据科学感兴趣的人没有资源或时间参加训练营。

训练营非常昂贵。学费本身就是几千美元,我见过夏令营收费高达 15000 美元。此外,训练营需要至少 40 小时的全职投入,课外时间用于学习、完成家庭作业和参加社交活动。

有些夏令营提供非全日制注册,时间承诺为每周 20 小时。但同样,在注册之前,你仍然需要了解一些耗时的活动,尤其是如果你打算在注册期间继续全职工作的话。当你计算一下,如果你确实参加了一个兼职项目,同时还保持着一份全职工作,那么在训练营的整个期间,你很容易每周工作 60-70 小时。

  • 结业证书对雇主来说是一个微弱的信号

想象一下:经过几个月不懈的努力,你终于获得了结业证书。你开始找工作,却发现雇主并没有排着队与你面谈。为什么不呢?

训练营结业证书只是表明你完成了训练营的课程。这并不意味着你会成为一名有能力的科学家。

完成证书不会成为你获得面试或其他潜在候选人的邀请的理由。说到底,数据科学训练营是非常新的,而且存在的时间还不够长,他们的认证还不足以让招聘经理选择你参加面试或担任某个角色。

让你从人群中脱颖而出的是你简历上的项目,这些项目体现了你在雇主寻找的技术方面的熟练程度。强大的项目组合将让你获得面试机会,在随后的技术评估和面对面面试中表现出色将让你获得梦寐以求的数据科学家角色。营地能提供给你的东西,没有一样是你自己不能提供的。

自学路线

综上所述,我坚信自学路线是最好的,原因有几个。尽管一开始会困难得多(直到你掌握了基础知识),自学成才的数据科学家真的非常非常受雇主青睐:

  • 自考考生表现出很强的职业道德,高度的纪律性和解决问题的能力。
  • 自学向雇主发出信号,表明你是一个自我激励的人。
  • 自学成才的数据科学家比他们的新兵训练营同伴拥有更发达、更多样的技能。此外,自学的学生在他们的作品集里将会有更多独特而全面的项目
  • 自学的候选人也表现出对数据科学的真正兴趣和热情。

现在我确实提到了开始自学之旅是很困难的。这是真的,因为学习如何编码和统计学的基础知识会非常令人沮丧和无聊。但是当你研究完基本面并开始进行第一次分析时,事情会变得容易得多。

从哪里开始我的自学之旅?

下面是我个人在自学过程中使用的免费资源列表,如果你对自学感兴趣的话。

  • 用 Python 自动化枯燥的东西
  • Python 数据科学手册和带有源代码的 GitHub repo
  • 机器学习讲座和课程材料来自斯坦福
  • 机器学习的圣杯

我也鼓励你去看看我写的关于基于项目的学习的文章,看看另外一个学习策略,我发现它在我刚开始的时候非常有用。编码快乐!

我叫 Kishen Sharma,是一名数据科学家,在旧金山湾区工作。我的使命是教授和激励全世界有抱负的数据科学家。

请随时在 Instagram 上与我联系,并在这里查看我的附加内容。你也可以在这里查看我的其他文章。

自助估计和实验

原文:https://towardsdatascience.com/bootstrap-estimates-and-experimentation-adf084d7c6e7?source=collection_archive---------58-----------------------

蒙特卡罗估计第一部分

莫里茨·金德勒在 Unsplash 上拍摄的照片

这些天进行的许多数字实验可以用频率统计方法愉快地分析,因为我们期望数据是正态分布的。然而,有些指标并不那么容易。以一个旨在增加税收或支付发票的实验为例。如果所有发票要么全部支付,要么根本没有支付,这可以用二项式比例检验卡方检验进行分析。然而,发票的某一部分将被部分支付,使得这些测试不合适。即使我们试图比较实际的账单分布,这些很可能是某种形式的指数分布,有许多小额账单和较少的大额账单,如下所示。

那怎么办呢?处理这个问题的一种方法是使用随机抽样统计工具,通常被称为蒙特卡罗模拟。与评估实验结果特别相关的两个是**(用于确定平均值等统计参数的分布)和 排列测试 ( 用于确定两个分布之间的统计数据是否存在差异,以及这种差异与偶然情况相比有多大可能是真实的)。在这篇文章中,我们将讨论自举。**

照片由克里斯蒂·金在 Unsplash 上拍摄

自举使用 替换采样 的概念来生成参数的分布。为了说明这一点,假设我们要估计二十朵花的平均高度。如果没有电脑,我们可以这样做:

  1. 测量每朵花,并在一张纸上记录花的 ID 和高度
  2. 计算样本中花朵的平均高度,并写下来。

上面我们用 Python 生成了 20 朵花的正态分布高度

现在是有趣和(稍微)神奇的部分……

  1. 把纸片放在帽子里,随机选择一张。
  2. 写下你选择的花的高度,然后把纸放回帽子里。
  3. 随机再选一次——你可能会再选同一个!这就是所谓的 抽样替换。
  4. 重复 20 次,以符合原始样本大小。这些应该是一样的。
  5. 再次计算平均值并记下来——这是平均值的第二个估计值。****

如果你重复上述 1000 次,你会得到 1000 个略有不同的平均值,这些平均值是:

  1. 正态分布,
  2. 提供您估计的花朵平均高度的平均值 的 标准误差。

在(非常不优化,但也许更可读?!)Python 我们可以这样做上面的内容:

****#generate a few normally distributed heights for demonstration
N_flowers = 20
flower_heights = np.random.normal(5,size = N_flowers)data_points = flower_heights
number_of_bootstraps = 1000
average_estimate = [np.mean(data_points)]for j in range(0,number_of_bootstraps):
    random_sample = []
    for i in range(0,len(data_points)):
        random_sample.append(np.random.choice(data_points))
    average_estimate.append(np.mean(random_sample))ax = sns.distplot(average_estimate, bins = 100).set_title('Average Flower Heights')
plt.xlabel("Height [cm]")
plt.ylabel("Count")****

这里我们有我们在这个例子中使用的 20 朵花的平均高度分布的 boostrapped 估计。

作为健全性检查,有必要将自举标准误差与我们使用 frequentist 方法从正态分布中预期的标准误差进行比较。标准偏差为σ、样本大小为 N 的正态分布的平均值(SE)的标准误差如下所示:

我们可以使用以下公式将上述内容与我们的自举估计进行比较:

****#normal distribution estimate
std_error_mean = np.std(flower_heights) / np.sqrt(N_flowers) -- 0.1983#bootstrap estimate
bootstrap_estimate = np.std(average_estimate) -- 0.1977****

我听到你们有些人在后台嘀咕- 有什么大不了的!如果没有这些乱七八糟的选择,我们本可以做到的。

但是 …如果(而不是花)我们有一些其他非正态分布的样本呢?那么通常具有某种指数分布的钞票呢?

下面显示的账单的含义是什么?对于实验来说更重要的是(我们试图确定两个均值或其他统计参数之间是否存在差异)均值估计的 标准误差 是多少?**

****bill_size = np.random.pareto(1,200)
sns.distplot(pareto).set_title("Average Bill Size")
plt.xlabel("Bill ($)")
plt.ylabel("Count")****

这就有点棘手了,不是吗…

让我们尝试使用 bootstrap 技术对此进行估计,但这次让我们稍微整理一下,并使用一个函数…

****def get_bootstrap_mean(data_values, n_bootstraps):
    '''
    data_values: Pandas Dataframe
    n_bootstrapes: Number of bootstrap estimates to calculate
    Return:
    Pandas Dataframe of the mean estimates
    ''' bootstrap_means = []
    for j in range(0, n_bootstraps):
        sample = data_values.sample(frac=1, replace=True).copy()
        bootstrap_means.append(sample.mean())
    return(pd.DataFrame(bootstrap_means))bill_size_experiment_a = pd.DataFrame(np.random.exponential(3,10000) )
average_estimate_a = get_bootstrap_mean(bill_size_experiment_a, 100)ax = sns.distplot(average_estimate_a, bins = 100).set_title('Average Bill Size Experiment Arm A')
plt.xlabel("Bill Amount ($)")
plt.ylabel("Count")****

太好了!但是这对实验来说意味着什么呢?对于实验来说,我们想让自己相信干预确实有效果。例如,假设我们做了一个旨在增加平均还款的实验?我们怎么知道它起作用了?我们可以比较如下的自举平均分布:

****bill_size_experiment_b = 1.1 +pd.DataFrame(np.random.exponential(3,10000) )
average_estimate_b = get_bootstrap_mean(bill_size_experiment_b, 100)****

然后如下所述比较两个直方图(其中 A 和 B 分别是实验组 A 和 B):

****fig, ax = plt.subplots()
for a in [average_estimate_a, average_estimate_b]:
    sns.distplot(a, bins = 20, ax=ax, kde=False)
plt.legend(["A","B"])
plt.title("Comparison of the Bill Bootstrapped Means")
plt.xlabel("Bill Amount ($)")
plt.ylabel("Count")****

一件很棒的事情是,我们现在可以用 t 检验来比较两个均值分布

****t2, p2 = stats.ttest_ind(average_estimate_a,average_estimate_b)****

对于上述情况,我们得到 p~0,即两个样本的平均值相同的概率几乎为零。如果这是两个实验条件的代表,我们可以有把握地假设它们之间存在差异。

这是一种 非常 强大的技术——它可以用来估计任何统计参数的标准误差,不管底层数据是什么分布。此外,得到的估计值是正态分布的,这使得使用标准频率技术进行比较变得容易。

在下一篇文章中,我将描述 排列测试 。这些特别用于确定参数在两个分布之间不同的可能性。

自举置信区间:基础

原文:https://towardsdatascience.com/bootstrapping-confidence-intervals-the-basics-b4f28156a8da?source=collection_archive---------27-----------------------

如何在没有 t 检验和 p 值的情况下计算任何指标的置信区间

两个 AB 测试:在左边,测试组之间没有统计学上的显著差异;在右边,这样的差异存在(图片作者)

如果你是数据驱动型公司的数据科学家、数据分析师或产品经理,你会对你的产品做很多实验,通常,你会做很多 AB 测试。让我们假设你有一个控制组和治疗组的 AB 测试。当分析结果时,您比较测试组中订单/访问/查看的平均数(或任何其他指标)。显然,您可以计算指标的平均值,甚至可以使用 t 检验和 p 值,如果两个平均值之间存在统计上的显著差异。但是通常,他们说不要只看 p 值,要看置信区间。在这篇博文中,我们发现了如何使用自举来计算置信区间。Bootstrapping 是一种很酷的估计置信区间的方法,因为它不依赖于任何数据分布的假设(例如,与流行的 Welch t-test 相比),并且它很容易自己实现(下面我分享了一个我的实现的链接)。

自举定义和原理

bootstrap 是一种估计标准误差和计算置信区间的方法。自举始于 1970 年布拉德利·埃夫隆;它已经存在了 40 多年,因此从那时起,开发了许多不同类型和方法的自举。

尽管有许多变化,所有的引导步骤看起来如下:

  1. 定义 u —从样本中计算出的统计数据(平均值、中值等)。
  2. 替换原始数据样本的样本。让它成为 F* —经验分布。重复 n 次( n 为引导迭代)。
  3. 计算 u* —从每个重采样中计算的统计量。

然后自举原理说:

如上所述,bootstrap 可用于不同的目标:

  • 估计置信区间
  • 假设检验
  • 偏差消除

每个话题都应该有一个单独的帖子,今天我们只关注自举置信区间。

自举置信区间的方法

当我研究这个主题时,我还没有找到一个一次性包含所有 bootstraps 方法的单一来源,每个引用都有自己的类型。最常见的如下所示:

简而言之,这种方法近似于自举均值和样本均值之间的差异。

让我们考虑一个例子(其他方法也是如此):估计基础分布的均值 μ ,给出一个 80%的 bootstrap 置信区间。

经验自举说:

  • 从重新采样开始,替换原始数据 n 次。
  • 对于每个自举,计算平均值 x* 。
  • 计算每个引导样本的δ = x —x(x是原始数据的平均值),将它们从最小到最大排序。
  • 选择 δ.1 作为第 90 个百分位数, δ.9 作为 δ* 排序列表的第 10 个百分位数,得到 80%的置信区间[x-δ. 1,x-δ. 9】

乏色曼的《统计学大全》一书为经验自助法提供了以下数学符号:

其中 x 是原始数据的平均值, x* 是自举平均值。

2.百分位自助法

bootstrap percentile 方法使用 bootstrap 样本统计的分布作为数据样本统计的直接近似值,而不是计算差值 δ* 。

对于百分位引导:

  • 从重新采样开始,替换原始数据 n 次。
  • 对于每个引导计算平均值 x* ,从最小到最大排序。
  • 选择 x.1* 为第 10 个百分位数, x.9* 为 x* 排序列表的第 90 个百分位数,得到 80%的置信区间 [x.1,x.9】。

或者换句话说:

bootstrap 百分位法非常简单,但它依赖于基于特定样本的 bootstrap 分布,该分布很好地逼近了 x 的真实分布(因此,该来源建议不要使用百分位 bootstrap)。

3.正常自举

正常的 bootstrap 方法不是取 bootstrap 均值的百分位数,而是计算这些 bootstrap 均值的置信区间。

  • 从重新采样开始,替换原始数据 n 次。
  • 对于每个引导,计算平均值 x* 。
  • 使用例如学生 t 检验,计算 x* 数组的 80%置信区间:

其中 x* 是来自 bootstrap 均值的样本均值, se 是 bootstrap 均值的标准差 s, z* 是临界值(从正态 CDF 的分布表中找到)。

当我将这种方法与其他方法比较时,它的 CI 与其他方法相比总是很窄,这让我很困惑。据我所知,这是因为该定义强烈依赖于关于数据正态分布的假设。

过了一段时间,我在乏色曼的《统计学》中偶然发现了这种方法略有不同的措辞。计算仅在一个参数上有所不同,但它会产生巨大的差异。

4.正常区间自举

正常间隔引导重复正常引导的所有步骤,但对 CI 使用以下公式:

其中 se_boot 是标准差的 bootstrap 估计值。

除非 x*的分布接近正态,否则这个区间是不准确的。

基本上,这里的公式没有除以 n. 的平方根,我还没有找到为什么要这样做的解释。如果你有任何想法,请在评论中分享。

5.参数自举

参数自举非常接近经验方法,唯一的区别是自举样本的来源。对于参数 bootstrap,我们从参数化分布中生成 bootstrap 样本。它通常用于贝叶斯后验分布的有效计算,而不是用于实验分析,所以我在这里不详细介绍它。

比较方法

正如前面承诺的,在这里你可以找到 Python 实现的所有方法。目标是估计目标度量平均值的 95% bootstrap 置信区间。我尝试了自举方法、自举样本的数量和数据本身的样本大小。

我的主要问题是:哪种 bootstrap 方法会显示更可靠的结果。首先,正态 bootstrap 显然产生了过于狭窄的 CI(因为正态假设)。在样本足够大的情况下,其他 3 种方法通常相互接近。百分位数和经验类型的优势在于,它们从左侧和右侧提供不同的区间(与正常区间自举相反)。通常,它更好,因为它考虑了数据的分布。正如您在下图中所看到的,百分位数和经验值的区间从左侧开始,在人口平均值所在的一侧。

采用不同方法的自举置信区间(图片由作者提供)

在百分位数和经验方法之间选择,我更倾向于百分位数方法,因为它简单。它的结果非常接近于经验方法,同时在计算中要求少一步。

另一个重要的问题是:要做多少 bootstrap 抽样。这取决于数据大小。如果数据点少于 1000 个,合理的做法是将引导数据库数量减少不超过数据大小的两倍(如果有 400 个样本,则使用不超过 200 个引导数据库,进一步增加不会带来任何改进)。如果您有更多的数据,100 到 500 之间的引导数量就足够了(更大的数量通常不会提高 CI 的准确性)。

而不是结论

使用自举应该记住的一个关键的评论是它不能改善点估计,这意味着自举的质量取决于收集的数据的质量。如果样本数据有偏差,不能很好地代表总体数据,bootstrap 估计也会出现同样的情况。因此,请始终记住,在实验过程中收集的数据应该是总体数据的良好近似值。

在这篇博文中,我描述并比较了基本的 bootstrap 方法。实际上,还存在更多的方法(如泊松、高斯、阻塞等)。此外,bootstrap 不仅与置信区间有关,还用于估计中位数的标准误差、75%百分位数、假设检验等。所有这些都是下一篇博文的好主题🙂

参考

  • 【https://projecteuclid.org/euclid.aos/1176344552#info
  • http://www-math.mit.edu/~dav/05.dir/class24-prep-a.pdf
  • https://en . Wikipedia . org/wiki/Bootstrapping _(statistics)

原载于 2020 年 5 月 17 日 https://elizavetalebedeva.com

引导前沿的自然语言处理模型

原文:https://towardsdatascience.com/bootstrapping-cutting-edge-nlp-models-baf62405a2b5?source=collection_archive---------24-----------------------

如何在 5 分钟内启动并运行 XLNet 和 Pytorch

由 Unsplash 上的 Pietro Jeng 拍摄

什么是 XLNet

XLNet 是基于 Transformers (BERT、RoBERTa、TinyBERT 等)的现代 NLP 语言模型。)XLNet 在各种自然语言理解任务上的结果接近人类的表现。XLNet 可以生成高中生级别的文本,它可以回答简单的问题。它可以理解狗和猫不一样,但它们都是人类的宠物。
总的来说,XLNet 是一个建立在 BERT 进步基础上的模型。

XLNet 解决了 3 大类 NLP 问题:分类、序列标记和文本生成

分类:

分类任务是自然语言处理中最常见的任务类型。分类任务给一段文本分配一个类别。更广泛地说,他们回答一个问题给定一段文本,告诉我该文本属于哪个类别
分类领域中的任务通常会回答如下问题:

这次就诊我们应该使用什么医疗账单代码?(提供访问描述)
这条短信是垃圾短信吗?(文字已提供)
这个用户感兴趣吗?(提供内容和用户简介)

序列标签:

NLP 中的另一类问题是序列标记。在序列标记中,我们试图在提供的文本中找到一些东西。通常,这种类型的任务将包括在所提供的文本中查找人(NER)或查找一个实体的所有共同引用,即,如果在句子“玛丽跳过一只蟾蜍。 没动算法会找出的‘它’指的是玛丽,不是蛤蟆。序列标记的另一个例子是检测哪个股票行情自动收录器与一个公司的每次提及相关联—

NVDA 定于 8 月 15 日报告 2020 财年第二季度业绩。

在随后的四个季度中,该公司的 (NVDA) 收益三次超过咤克斯共识预测,一次错过同样的(咤克斯),平均正惊喜为 3.94%。

文本生成:

XLNet 的第三种也是最后一种用途是文本生成。这里,给定一小段上下文,XLNet 将预测下一个单词。并且它将继续预测下一个单词,直到被指示停止。在下面的例子中,给定的输入,快速棕色* XLNet 将首先预测狐狸,然后整体查看上下文并预测下一个单词跳过等等。*

快速棕色

运行 XLNet

现在,让我们来看看如何设置和运行 XLNet。基于 XLNet 操作的 3 种模式—

XLNetLMHeadModel

XLNet 模型,顶部有一个语言建模头(线性层,权重与输入嵌入绑定)——XLNetLMHeadModel

Daulet Nurmanbetov 提供的示例代码

在这个例子中,你可以看到给定一个序列“快速的棕色狐狸跳过了懒惰的* <面具><面具>成为一个***

这种类型的 XLNet Head 通常用于 AI 完成人类句子或根据简短问题打出句子的演示。

XLNetForSequenceClassification

顶部带有序列分类/回归头的 XLNet 模型(汇集输出顶部的线性层),例如用于胶合任务— XLNetForSequenceClassification

Daulet Nurmanbetov 提供的示例代码由 Hugginface 的 Transformers 提供

如上所述,使用 XLNet 开箱即用而不先进行微调会给我们带来相当大的损失值 1.19

这种类型的 XLNet 头用于微调一个模型来为我们分类 NLP 任务。即。,我们可以使用上面的代码对文本或段落进行分类。为了做好分类工作,我们将需要标记的数据进行微调,并获得接近 0 的损失值。通常,根据我的经验,只需要 2k–5k 标记的样本就可以得到一个像样的模型。

XLNetForQuestionAnswering

****XLNet 模型,顶部有一个 span 分类头,用于提取问题回答任务,如 SQuAD(隐藏状态输出顶部的线性层,用于计算“span 开始逻辑”和“span 结束逻辑”)。


Daulet Nurmanbetov 提供的示例代码由 Hugginface 的 Transformers 提供

这种类型的 XLNet Head 用于回答问题或从文本中提取一条信息。同样,与上一个 XLNet 方法一样,我们需要为我们的特定任务提供训练数据,这样才能很好地工作。

我们可以用这些模式做什么?

有了上面提供的 3 种 XLNet 模式,我们几乎可以解决任何类型的 NLP 问题。以下是我使用 XLNet 和其他 Transformer 模型解决的一些问题—
—相关性检测
—共指消解

—NER
—序列分类
—文本生成
—下一个单词预测
—问题回答
—释义检测
—文本分类

我还见过 XLNet 被用来执行图形数据库的 关系提取汇总 任务。

结论

在当今时代,任何人都可以在几个小时内开始使用前沿模型。这是激动人心的时刻,因为其中一些模型在一些特定的任务中与人类能力相匹敌。

重要的是,任何开发人员或喜欢代码的个人都可以使用这些模型,比如 XLNet 模型。

这都要归功于持续的努力,让人工智能对每个人都是免费和可访问的。这些模型的纯 GPU 培训成本有时高达 50 万美元。使用运行在 Kubernetes-like 上的分布式计算和 GPU 集群来生产模型训练,需要花费更多的工程和研究时间。

公开共享模型权重以促进行业研究和应用的趋势确实令人惊讶。

2020 年美国总统选举中估计选民偏好的自举方法

原文:https://towardsdatascience.com/bootstrapping-method-to-estimate-voters-preferences-in-us-presidential-election-2020-d480ef13aef?source=collection_archive---------55-----------------------

替换抽样技术

声明:本文仅用于教育目的。它不反映或推断任何关于选举的事实信息

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

美国总统大选即将来临。美国总统选举以大量使用数据和分析而闻名。从了解选民的人口统计背景到估计不同州的选举结果,从预测选民的偏好到制定营销策略,数据无处不在。所有的政治活动都在数据分析上花费数百万美元来赢得选举。虽然我们之前已经看到不正确的采样技术未能预测选举结果,但我们不能简单地否认数据在美国总统选举中发挥的重要作用。在本文中,我们将尝试使用一种叫做 Bootstrapping 的抽样技术来了解选民在即将到来的总统选举中的总体偏好。

自举:

图:Bootstrap 分布与传统抽样分布(图片由作者提供)

在统计学中,抽样分布理论告诉我们,如果我们从一个未知总体中抽取许多样本,样本的均值、中位数、标准差等统计量。从所有这些样本中得出一个分布,称为抽样分布。如果抽样分布遵循一定的规则,抽样分布的统计量就接近于总体均值、中位数、标准差等参数。这意味着即使我们不知道总体参数,我们仍然可以使用抽样分布理论来估计或推断未知参数。现在,开发抽样分布的主要挑战之一是从总体中获得几个样本。很多时候,我们只有一个总体样本,但要估计总体参数,我们需要几个样本。这就是 bootstrapping 方法在从给定样本生成许多数据样本时派上用场的时候。美国统计学家布拉德利·埃夫隆在 1979 年引入了自举法。在本文中,我们将采用不同选举民调的数据,并尝试应用 bootstrapping 来生成许多民调结果样本,以估计支持民主党和共和党的美国人的百分比。bootstrap 抽样分布的一个主要优点是,我们可以计算不同的统计数据,如均值、中值、方差等。从中。此外,分布不需要遵循任何特定的形状。
需要注意的一个缺点是,bootstrapping 方法从现有样本中生成数据。如果在我们的案例研究中给定的投票样本不能代表选举中所有类型的选民,那么 bootstrapping 方法将不会为不在给定样本中的群体生成数据。因此,我们尽可能多地进行民意调查,以代表所有选民群体,这一点非常重要。我们将使用 R 编程语言来做这个分析。

数据可以在这个链接上找到

https://github.com/PriyaBrataSen/US-Election-Poll

现在让我们来看看数据集…

数据:

此分析中使用的数据集包括民意测验结果。总共有 51 个州,每个州都有不同的民调显示民主党和共和党的支持者比例。

df<-read.csv('pres_polls.csv')
head(df)

图:测向数据帧的前 6 行

从上表我们可以看出,这个数据集中有 8 个变量。Day 变量表示调查在一年中的哪一天完成。变量 state 表示完成调查的状态。区域变量描述了每个状态所在的 4 个区域。永远代表该州选举人票。Dem 和 GOP 代表给予民主党和共和党有利回应的人的百分比。日期列表示调查完成的日期,最后,民意测验者是民意测验的名称。

library(dplyr)poll=unique(pull(df,Pollster))
str(poll)

图:投票向量中的行数

让我们研究一下 Pollster 变量,看看这个样本中有多少池结果。我们可以使用“str”函数来查看数据集中有多少独特的投票。从输出中,有 233 个唯一的行,告诉我们给定的样本总共有 233 个投票。我们将使用 bootstrapping 来生成 10,000 个样本,每个样本中有 233 个池的结果。对于 10,000 个样本,我们将得到 10,000 个样本平均值,这将得出 bootstrap 抽样分布。由于自举是一种带有替换的重采样技术,一些样本可能多次具有相同的池。

估计选民的偏好:

在本节中,我们将尝试为整个数据集创建 bootstrap 分布,而不考虑地区或州,以获得全国选民偏好的估计值。之后,我们将为美国的四个地区中的每一个地区构建一个引导分布。我们将计算这些 bootstrap 分布平均值的置信区间,以了解偏好水平。

让我们开始吧..

library(boot)
bootmean=function(x,i){mean(x[i])}prefer_country=function(data){
  boot.object=boot(data,bootmean,R=10000)
  boot.ci(boot.object,conf = 0.95,type = 'bca')
}Dem=round(prefer_country(df$Dem)$bca[,c(4,5)],4)
GOP=round(prefer_country(df$GOP)$bca[,c(4,5)],4)c('Democratc party:',Dem)
c('Republican party:',GOP)

图:输出(来自 bootstrap 分布的置信区间)

在 R 中,为了计算引导分布,我们首先加载“boot”库。如果我们是第一次运行这个库,我们必须在加载它之前安装它。为了开发 bootstrap 分布,我们首先需要开发一个函数,告诉 R 当我们从给定的样本生成多个样本时,我们想要计算什么统计量。在我们的例子中,我们希望计算从给定样本生成的每个新样本的平均值。因此,我们在第二行创建了一个名为“bootmean”的函数,它主要获取一个向量并计算其平均值。接下来,我们创建了一个函数‘prefer _ country ’,它主要创建 bootstrap 分布,然后计算 95%置信度下的区间。如果我们仔细观察函数内部,可以看到在第一行中,我们使用了 boot 函数创建了一个名为 boot.object 的引导对象。引导函数将获取我们将传递的数据,并从中计算出 10,000 个新样本,因为我们提到 R=10,000。最后,它将计算每个样本的统计数据,并将结果存储在“boot.object”中。这就是为什么在 boot 函数的第二个参数中,我们传递了在第二行代码中创建的“bootmean”函数。在 boot.object 中存储了不同的东西。如果我们想知道存储在其中的东西是什么,我们可以使用 str(boot.object)来查看对象的结构。然而,在我们的例子中,我们感兴趣的是得到双方均值的置信区间。因此,在下一行中,我们使用了 boot。ci 函数计算 95%置信水平下的均值区间。boot 中保存了几种类型的置信区间。对象,但我们希望偏差校正和加速(' BCA') bootstrap 区间。因此,我们提到了 type='bca '。

最后,我们为民主党和共和党的数据调用了 prefer _ country 函数,并将结果保存在“Dem”和“GOP”变量中。最后两行打印出了结果。因此,根据我们的 bootstrap 分析,我们可以在 95%的信心水平下,在这次总统选举中,48.01%至 48.86%的美国人倾向于民主党候选人,43.31%至 44.20%的美国人倾向于共和党候选人。

图:总体偏好水平的置信区间(图片由作者提供)

让我们看看地区层面,以了解双方的置信区间是什么。我们将使用相同的技术,但我们需要计算每个地区的 bootstrap 样本,而不是整个国家。下面是它的 R 代码

lower=c()
upper=c()
region=c()
a=unique(pull(df,Region))prefer_region=function(data){
  for (i in a){
    data_Dem=data[df$Region==i]
    boot.Dem=boot(data_Dem,bootmean,R=10000)
    p=boot.ci(boot.Dem,conf = 0.95)
    lower=c(lower,p$bca[,c(4)])
    upper=c(upper,p$bca[,c(5)])
    region=c(region,i)
  }
  preference=data.frame(region,lower,upper)
  preference}DEM=prefer_region(df$Dem)%>%rename(Dem_lower=lower,Dem_upper=upper)
GOP=prefer_region(df$GOP)%>%rename(GOP_lower=lower,GOP_upper=upper)
inner_join(DEM,GOP,by='region')

图:区域层面的置信区间

我们已经开始建立 3 个空向量'下','上'和'区域'。我们将在这些向量中保存引导输出,以开发数据帧。接下来,我们将不同地区的名称保存在向量“a”中,该向量有四个值:南方、东北、西方、中西部。我们将在 for 循环中使用这个向量来过滤特定区域的数据,然后使用过滤后的数据只为该区域开发引导样本。现在,我们已经编写了另一个名为‘prefere _ region’的函数,它从我们的 df 数据帧中获取一列作为输入。在函数内部,我们编写了一个循环,它主要获取指定的列,并针对特定区域对其进行过滤。该循环将从向量“a”中读取地区名称,并以类似于我们对整个国家所做的方式执行自举计算。每次,我们已经计算了间隔,我们已经在“下”向量中保存了下限,在“上”向量中保存了上限。此外,我们将区域名称保存在“区域”向量中。一旦所有区域的计算完成,for 循环结束。现在,我们采用了三个向量“下”、“上”和“区域”,并创建了一个名为“首选项”的数据框。这是我们函数的结尾。在最后三行中,我们主要调用了民主党和共和党的函数,并将结果保存在输出中显示的一个数据框中。

如果我们观察结果,我们可以看到,在 95%的信心水平下,民主党在西部、东北部和中西部地区的平均百分比区间更高。然而,在南部地区,间隔相互重叠。南部地区 46.19%至 47.56%的美国人倾向于民主党候选人,南部地区 45.41%至 46.81%的美国人倾向于共和党候选人。

结论:

从上面的讨论中,我们可以看到如何使用 R 编程语言实现自举。我们能够从 233 个观测值的给定样本中生成 10,000 个样本,每个样本有 233 个观测值。这里重要的一点是,我们试图从国家和地区层面的自举抽样分布中找出区间。它不一定能告诉我们哪个政党将赢得选举,因为这项研究不是在州一级进行的。选举人票因州而异。因此,本研究运用 bootstrapping 方法对选民的总体政治偏好进行了全面的了解。

自举统计。它是什么,为什么使用它。

原文:https://towardsdatascience.com/bootstrapping-statistics-what-it-is-and-why-its-used-e2fa29577307?source=collection_archive---------1-----------------------

比较自举方法和传统方法,并理解它为什么有用。

图片作者:特里斯特·约瑟夫

统计学是从数据中学习的科学。统计知识有助于收集数据的正确方法,使用正确的方法分析数据,并有效地展示从数据中得出的结果。这些方法对决策和预测至关重要,无论是预测消费者对产品的需求;利用文本挖掘过滤垃圾邮件;或者在自动驾驶汽车中进行实时决策。大多数情况下,在进行研究时,从人群中收集数据是不切实际的。这可能是因为预算和/或时间限制等因素。取而代之的是,取群体的一个子集,并从该子集收集洞察力以了解更多关于群体的信息。这意味着可以从适当提取的样本中快速且相对便宜地获得适当准确的信息。然而,许多因素会影响样本反映总体的程度;以及结论的有效性和可靠性。正因为如此,我们来说说自举统计。

图片作者:特里斯特·约瑟夫

“Bootstrapping 是一种对单个数据集进行重新采样以创建许多模拟样本的统计过程。这个过程允许计算标准误差、置信区间和假设检验”( Forst)。自举方法是传统假设检验方法的一种非常有用的替代方法,因为它相当简单,并且减少了传统方法中遇到的一些陷阱,这将在后面讨论。统计推断通常依赖于采样分布和感兴趣特征的标准误差。传统方法(或大样本方法)从总体中抽取一个大小为 n 的样本,该样本用于计算总体估计值,然后进行推断。现在,在现实中,只有一个样本被观察到。然而,有一个抽样分布的概念,它是一个所有可能估计的理论集合,如果人口被重新抽样的话。该理论指出,在某些条件下,如大样本量,抽样分布将是近似正态的,分布的标准偏差将等于标准误差。但是如果样本量不够大,会发生什么呢?那么,就不一定能假设理论抽样分布是正态的。这使得很难确定估计的标准误差,也很难从数据中得出合理的结论。

图片作者:特里斯特·约瑟夫

与传统方法一样,大小为 n 的样本是从 bootstrapping 方法的总体中抽取的。让我们称这个样品为 S 。然后,不是使用理论来确定所有可能的估计,而是通过用来自 Sm 次的替换对观测值进行重采样来创建采样分布,每个重采样集具有 n 个观测值。现在,如果取样适当, S 应该能代表总体。因此,通过替换重采样 S m 次,就好像从原始群体中抽取了 m 个样本,并且得出的估计值将代表传统方法下的理论分布。必须注意,增加重采样的数量 m ,不会增加数据中的信息量。也就是说,对原始集合重采样 100,000 次并不比只重采样 1000 次更有用。集合中的信息量取决于样本大小, n ,在每次重采样中保持不变。那么,更多重采样的好处是得到采样分布的更好估计。

图片作者:特里斯特·约瑟夫

既然我们已经理解了自举方法,那么必须指出的是,所得到的结果与传统方法的结果基本相同。此外,自举方法将始终有效,因为它不假设数据的任何底层分布。这与理论上假设数据呈正态分布的传统方法形成对比。知道了 bootstrapping 方法的工作原理,一个合乎逻辑的问题就是“bootstrapping 方法是否过于依赖观察到的数据?”这是一个好问题,因为重采样是从初始样本中得到的。正因为如此,假设一个异常值会扭曲重采样的估计值是合乎逻辑的。虽然这是事实,但如果考虑传统方法,将会看到数据集中的异常值也会扭曲平均值并增大估计值的标准误差。因此,虽然认为异常值可能会在重新采样的数据中出现多次并扭曲结果,从而使传统方法更好,但自举方法与传统方法一样依赖于数据。“自举法的优点在于,它是一种导出标准误差和置信区间估计值的直接方法,而且它很方便,因为它避免了重复实验以获得其他组采样数据的成本。虽然不可能知道大多数问题的真实置信区间,但 bootstrapping 是渐近一致的,并且比使用通过样本方差和正态性假设获得的标准区间更准确”( Cline)。

这两种方法都需要使用适当抽取的样本来对总体进行推断。然而,这两种方法之间最大的区别是估计抽样分布背后的机制。传统的方法需要一个满足特定假设的检验统计量来获得有效的结果,这在很大程度上取决于实验设计。传统的方法也使用理论来告诉抽样分布应该是什么样子,但是如果不满足理论的假设,结果就会分崩离析。另一方面,bootstrapping 方法获取原始样本数据,然后对其进行重新采样,以创建许多[模拟]样本。这种方法不依赖于理论,因为采样分布可以简单地观察到,人们不必担心任何假设。这种技术允许对统计数据进行准确的估计,这在使用数据做决策时是至关重要的。

引文:

克莱恩格雷森。使用 r .的非参数统计方法,联合王国,EDTECH,2019 年。

福斯特,吉姆。《统计学中的自举法介绍及实例》。吉姆的统计。https://statisticsbyjim . com/hypothesis-testing/bootstrapping/。访问日期:2020 年 6 月 17 日。

参考文献:

布朗利,杰森。“自举法的简明介绍”。机器学习掌握,2018 年 5 月 25 日。https://machinelementmastery . com/a-gentle-introduction-to-the-bootstrap-method/。访问日期:2020 年 5 月 24 日。

安东尼·库勒萨等人《抽样分布和自助》自然方法第 12 卷,6(2015):477–8。doi:10.1038/nmeth.3414

其他有用的材料:

http://faculty.washington.edu/yenchic/17Sp_403/Lec5-

bootstrap.pdfhttps://web . as . uky . edu/statistics/users/pbre heny/764-F11/notes/12-6 . pdf

http://www . stat . Rutgers . edu/home/mxie/RC papers/bootstrap . pdf

自举与置换测试

原文:https://towardsdatascience.com/bootstrapping-vs-permutation-testing-a30237795970?source=collection_archive---------6-----------------------

入门

使用 Python 进行理论和实验比较

本文的主要目标是从理论上和实验上比较这两种重采样方法,然后在技术上有余地使用其中一种方法的情况下,就何时应该使用每种方法得出一些结论。促使我写这篇文章的原因是,我认为初学者在这个问题上缺乏免费的清晰指南。在一些学习材料中,我甚至遇到了这样的说法,我们可以使用其中任何一个,而没有任何进一步的解释。

文章的主要章节:
1。作为对 bootstrap】的介绍,我们将计算置信区间并分析测试一些假设,然后使用 bootstrap 方法非参数地解决相同的问题。
2。作为排列测试
(也称为显著性测试)的介绍,我们将在与第 1 节相同的数据上使用排列测试来测试假设。
3。我们将开发一个稍微复杂一点的例子,设计几个假设检验,并且
并排比较每个检验的重复统计的 bootstrap 分布和 permutation 分布

我们邀请了一些最好的朋友过来:NumPy,SciPy 和 Matplotlib…熊猫将休息一天,因为我们将使用的数据集相当简单。

import numpy as np
from scipy import stats
from matplotlib import pyplot as plt

1.CI 计算和 HT——通过参数和自举

第一部分,我们将使用 2008 年美国总统选举的结果,来自宾夕法尼亚州和俄亥俄州的“摇摆州”,具体来说,是给定州每个县投票给民主党的选民的百分比(来源:https://www.data.gov/)。

dem_share_PA = [60.08, 40.64, 36.07, 41.21, 31.04, 43.78, 44.08, 46.85, 44.71, 46.15, 63.10, 52.20, 43.18, 40.24, 39.92, 47.87, 37.77, 40.11, 49.85, 48.61, 38.62, 54.25, 34.84, 47.75, 43.82, 55.97, 58.23, 42.97, 42.38, 36.11, 37.53, 42.65, 50.96, 47.43, 56.24, 45.60, 46.39, 35.22, 48.56, 32.97, 57.88, 36.05, 37.72, 50.36, 32.12, 41.55, 54.66, 57.81, 54.58, 32.88, 54.37, 40.45, 47.61, 60.49, 43.11, 27.32, 44.03, 33.56, 37.26, 54.64, 43.12, 25.34, 49.79, 83.56, 40.09, 60.81, 49.81]
dem_share_OH = [56.94, 50.46, 65.99, 45.88, 42.23, 45.26, 57.01, 53.61, 59.10, 61.48, 43.43, 44.69, 54.59, 48.36, 45.89, 48.62, 43.92, 38.23, 28.79, 63.57, 38.07, 40.18, 43.05, 41.56, 42.49, 36.06, 52.76, 46.07, 39.43, 39.26, 47.47, 27.92, 38.01, 45.45, 29.07, 28.94, 51.28, 50.10, 39.84, 36.43, 35.71, 31.47, 47.01, 40.10, 48.76, 31.56, 39.86, 45.31, 35.47, 51.38, 46.33, 48.73, 41.77, 41.32, 48.46, 53.14, 34.01, 54.74, 40.67, 38.96, 46.29, 38.25, 6.80, 31.75, 46.33, 44.90, 33.57, 38.10, 39.67, 40.47, 49.44, 37.62, 36.71, 46.73, 42.20, 53.16, 52.40, 58.36, 68.02, 38.53, 34.58, 69.64, 60.50, 53.53, 36.54, 49.58, 41.97, 38.11]

对于本节和本说明的下一节,我们将使用相同的数据和相同的统计数据来保持示例的一致性,即 PA 和 OH 平均投票百分比之间的差异。

1.1 样品的 EDA

让我们看看每个州的平均值、中值、标准差和样本大小,以及直方图:

print("Mean:\t\t", round(np.mean(dem_share_PA),2))
print("Median:\t\t", round(np.median(dem_share_PA),2))
print("SD:\t\t", round(np.std(dem_share_PA),2))
print("Sample Size:\t", len(dem_share_PA))
plt.hist(dem_share_PA, bins=30, alpha=0.25)
plt.grid()
plt.show()

平均值:45.48
中位数:44.03
标准差:9.73
样本量:67

各县的 PA Dem 投票百分比(图片由 Gene Mishchenko 提供)

print("Mean:\t\t", round(np.mean(dem_share_OH),2))
print("Median:\t\t", round(np.median(dem_share_OH),2))
print("SD:\t\t", round(np.std(dem_share_OH),2))
print("Sample Size:\t", len(dem_share_OH))
plt.hist(dem_share_OH, bins=30, alpha=0.25)
plt.grid()
plt.show()

平均值:44.32
中位数:43.68
标准差:9.84
样本量:88

各县的选民投票率(T22)

结论:分布看起来并不完全正态,但它们可能足够接近于测试参数(分析)解,并且它们稍微正偏(平均值大于中间值,尾部在右侧/正侧更长)。

1.2 置信区间计算

置信度= 90%

1.2.1 CI 通过参数方法计算

(假设总体呈正态分布)

首先,让我们使用正态样本分布(相应地,α/2 在左边,α/2 在右边的 z 分数)来找到下临界值和上临界值(LCV 和 UCV)。在 Python 中,这可以通过使用scipy.stats.norm.ppf()方法来完成,该方法将左侧的 AUC(即百分位等级)作为输入,并返回与所提供的百分位等级相对应的 Z 分数。
注 1 :这是scipy.stats.norm.cdf()方法的逆方法,采用 Z 分数并返回相应的百分位等级。这是用于这种分析的两种最常用的 Python 方法,但是这里的是 SciPy 教程以获得更多信息。
注 2 :如果我们想使用学生的 t 分布而不是正态分布,我们将使用scipy.stats.t类及其方法,它将自由度作为一个附加参数。

# Lower Critical Value
lcv = stats.norm.ppf(0.05)
print("Lower CV:", round(lcv,3))
# Upper Critical Value
ucv = stats.norm.ppf(1 - 0.05)
print("Upper CV: ", round(ucv,3))

下 CV: -1.645
上 CV: 1.645

太好了!现在我们不需要携带这些愚蠢的查找表…
接下来,我们需要均值差异的标准误差(se)。
公式为:sqrt(std(sample_1)^2 / len(sample_1) + std(sample_2)^2 / len(sample_2))

se = np.sqrt( np.std(dem_share_PA)**2 / len(dem_share_PA) + np.std(dem_share_OH)**2 / len(dem_share_OH) )
print(round(se,3))

1.585

最后,我们需要均值的经验差异:

emp_diff_means = np.mean(dem_share_PA) - np.mean(dem_share_OH)
print(round(emp_diff_means,3))

1.158

现在我们准备好分析计算置信区间:

lower_lim_an = emp_diff_means + lcv * se
upper_lim_an = emp_diff_means + ucv * se
print(round(lower_lim_an,3), 'to', round(upper_lim_an,3))

-1.449 至 3.766

结论:
我们以 90%的信心估计,PA 和 OH 的平均票数之间的真正差异在-1.4493.766
(假设样本近似正态分布)
这一结果通过使用在线 CI 计算器进行验证,该计算器使用学生的 t 分布,结果与我们的非常接近,但比预期的要宽一些:(-1.4676, 3.7876)

1.2.2 通过 Bootstrap 方法计算 CI

一般来说,Bootstrapping 和重采样方法非常强大,因为它们对总体分布做了更少的假设(例如,没有正态约束),通常不涉及公式,并且计算相对简单。

关于自举的一些理论:

  • 首先,Bootstrapping 是一种从一个样本中找到抽样分布(至少是近似分布)的实用方法,而不是从总体中抽取多个随机样本。
  • 模拟从一个群体中仅用一个样本抽取多个随机样本,所以它非常依赖这个单一样本尽可能的随机。
  • 与传统的 t 检验不同,Bootstrap 检验不对实际样本所来自的总体分布施加正态性限制。

首先,我们需要计算测试统计的大量 bootstrap 复制。

让我们定义一个可重用的函数,我们可以利用它来产生测试统计的引导复制,调用一些对每个样本进行操作的基本统计函数(预定义的或用户定义的)。
注意在重新采样和计算每个重复之前,我们不会混合来自不同样本的数据。

def boot_diff(sample_1, sample_2, base_stat_func, num_iter):

    # initialize the list for holding the bootstrap replicates
    bs_replicates = []
    # iterate for the specified number of bootstrapping iterations
    for i in range(num_iter):
        # create the resampled sets of data of the original lengths (WITH REPLACEMENT)
        sample_1_bs = np.random.choice(sample_1, len(sample_1))
        sample_2_bs = np.random.choice(sample_2, len(sample_2))
        # compute the BS replicate using the specified base statistical function and append it to the list of BS replicates
        bs_replicates += [base_stat_func(sample_1_bs) - base_stat_func(sample_2_bs)]

    return bs_replicate

为我们的任务生成 BS 复制:

bs_replicates = boot_diff(dem_share_PA, dem_share_OH, np.mean, 100000)

直观地检查测试统计副本的分布总是一个好主意:

plt.hist(bs_replicates, bins=50, alpha = 0.25)
plt.grid()
plt.show()
print("Mean:  ", round(np.mean(bs_replicates),3))
print("Median:", round(np.median(bs_replicates),3))

平均值差异的 Bootstrap 复制(图片由 Gene Mishchenko 提供)

现在,我们可以将np.percentile()函数应用于这个生成的 BS 副本的大集合,以便在一个步骤中获得置信区间的上限和下限。对于下限计算,我们提供 alpha/2 作为该函数的第二个参数,对于上限计算,我们提供 alpha/2 的补码,因为该函数期望将累积百分位数作为第二个参数。
使用百分位数计算得出的置信区间称为 Bootstrap 百分位数置信区间 :

# the lower limit will be the 5th percentile
lower_lim_bs = np.percentile(bs_replicates,5)
# the upper limit will be the 95th percentile (5's complement to 100)
upper_lim_bs = np.percentile(bs_replicates,95)
print(round(lower_lim_bs,3), 'to', round(upper_lim_bs,3))

-1.433 至 3.792

:如果(且仅当)BS 重复分布呈正态且以真实参数值为中心(偏差较小),我们可以用下面的公式计算 Bootstrap t 置信区间 :
BS_stat_mean +/- t * SE

结论:
结果与分析结果(-1.449, 3.766)相当接近,但这里我们没有对样本的分布做任何假设。

1.3 双尾假设检验

首先,我们将检验总体均值之间的真实差异为 0 的假设。测试条件为:

Ho :(平均 PA 投票%)——(平均 OH 投票%) = 0
Ha :(平均 PA 投票%)——(平均 OH 投票%)!= 0
CL:90%
方向 :双尾

1.3.1 通过参数方法的双尾 HT

让我们使用 Z 值方法。
我们需要计算平均值的假设差异的 Z 值。公式为:
Zc = [(sample_mean_1 - sample_mean_2) - (hyp_difference)] / SE
临界 Z 值与上面计算置信区间中的相同:-1.6451.645
SE(标准误差)也可以在计算 CI 时重复使用:1.585
均值之间的假设差异为0

因此,对于计算的 Z 分数(Zc ),我们得到以下结果:

Zc = (emp_diff_means - 0) / 1.585
print(round(Zc,3))

0.731

结论:无法在 90%的置信水平下拒绝 (FTR)零假设,因为0.731的计算 Z 值正好在-1.6451.645的临界值之间。
直觉上,这是有意义的,因为两个样本的标准偏差相对于平均值而言相当大(分别为 21%和 22%),并且比平均值的经验差异大几倍。

:正态分布的这个 Z 值关联的右尾 p 值(AUC 到右边)是0.23239
双尾 p 值是那个的两倍:0.465
因此,如果我们想要使用 p 值方法进行分析,它也会导致 FTR 决定,因为这个 p 值比我们在尾部的拒绝区域之和(每个区域0.05大得多,由我们的总显著性水平10%定义。

1.3.2 通过自举方法的双尾 HT

在比较两组时,使用 bootstrap 方法比使用 analytical 方法的主要优点是,在 BS 方法下,对总体没有正态性限制。此外,我们在这里不仅限于手段的比较。

生成 bootstrapped test statistic 副本的基本过程与上一节 CI 中的过程相同(也没有混合样本总体,以及替换抽样),因此我们将使用相同的函数:

bs_replicates = boot_diff(dem_share_PA, dem_share_OH, np.mean, 100000)

额外的重要步骤 (与查找 CI 相比)是围绕假设平均值确定重复的分布中心:

bs_replicates_shifted = bs_replicates - np.mean(bs_replicates) - 0

让我们确保我们的最终 BS 重复组是有序的(以假设平均值为中心,并且标准误差的 BS 版本接近分析版本):

print("Replicate 25th percentile, mean, 75th percentile:",
      round(np.percentile(bs_replicates_shifted, 25),3), 
      round(np.mean(bs_replicates_shifted)+1e-4, 2), 
      round(np.percentile(bs_replicates_shifted, 75),3))
print("Replicate Std Dev:", round(np.std(bs_replicates_shifted),3)) # the analytical version is 1.585

重复第 25 百分位,平均第 75 百分位:-1.085 ~ 0.0 ~ 1.07
重复标准差:1.595

看起来不错…现在我们可以得到这组 BS 重复数据中平均值的经验差异的百分位数等级:
( scipy.stats.percentileofscore()np.percentile()的倒数)

emp_diff_pctile_rnk = stats.percentileofscore(bs_replicates_shifted, emp_diff_means)
print("Empirical difference of the sample means:", round(emp_diff_means, 3))
print("Its percentile rank among the replicates:", round(emp_diff_pctile_rnk, 2), "% (AUC to the left)")
auc_left = round(emp_diff_pctile_rnk / 100, 4)
auc_rght = round(1 - emp_diff_pctile_rnk / 100, 4)
print("AUC to the left:  ", auc_left)
print("AUC to the right: ", auc_rght)

样本的经验差异均值:1.158
其在重复中的百分位数排序:76.69 % (AUC 向左)
AUC 向左:0.7669
AUC 向右:0.2331

我们现在需要非常仔细地解释这个结果,这取决于我们正在进行的测试类型,以便获得 p 值:

  • 如果我们正在进行左尾测试,我们需要将 AUC 带到左边
  • 如果我们正在进行右尾检验,我们需要将 AUC 向右移动
  • 如果我们正在进行一个双尾检验,我们需要取较小的 AUC 值(因为它总是代表一个尾区域)并乘以 T2

因此,我们正在进行的双尾检验的 p 值为:

auc_tail = auc_left if auc_left < auc_rght else auc_rght
p_val = round(auc_tail * 2, 4)
print("P-value:", p_val)

p 值:0.4662

结论:未能在 90%置信水平下拒绝(FTR) 原假设,因为 p 值远大于0.10的显著性。

1.4 单尾假设检验

这里,我们将测试 PA 和 OH 平均值之间的真实差值小于或等于-2.0 的假设(换句话说,预计 OH 的平均投票百分比至少比 PA 大2.0)。

注意:在陈述这个单尾假设时,为了便于说明,我们保持了与上述例子中相同的均值顺序,尽管陈述这个不等式更自然的方式是“OH mean — PA mean > = 2”。

Ho :(平均 PA 投票%)——(平均 OH 投票%)<=-2
Ha:(平均 OH 投票%)——(平均 OH 投票%)>-2
CL:90%
方向 :右尾(自 Ho 拒绝

1.4.1 通过参数方法的单尾 HT

我们需要计算平均值的假设差异的 Z 值。公式为:
Zc = [(sample_mean_1 - sample_mean_2) - (hyp_difference)] / SE
SE(标准差)可以从计算 CI 中重复使用,也就是1.585
假设平均值之差为-2。我们假设人口的正态分布。
因此,对于计算的 Z 得分(Zc ),我们得到以下结果:

Zc = (emp_diff_means - (-2)) / 1.585
print(round(Zc,4))

1.9926

如果使用 Z 值方法,我们需要计算0.10的右尾 alpha 的上临界 Z 值,该值可以直接与计算的 Z 值进行比较:

round(stats.norm.ppf(0.9),4)

1.2816

如果使用 P 值方法,我们需要找到与计算的 Z 值相关的右尾 P 值。
首先,我们计算左边的 AUC:

# use scipy.stats.norm.cdf(), which is the inverse of stats.norm.ppf()
auc_left = round(stats.norm.cdf(1.9926), 4)
print("AUC to the left:", auc_left)

左边的 AUC:0.9768

因为我们正在寻找右尾下的 p 值,所以我们需要从1 :
中减去这个值(如果我们正在进行左尾测试,我们将按原样取这个 AUC 值)

p_val = 1 - auc_left
print("P-value:", p_val)

p 值:0.0232

结论:拒绝零假设因为:

  • 计算出的1.9926的 Z 值大于1.2816的临界值上限
  • 计算出的0.0232的右尾 p 值小于0.10的右尾显著性

1.4.2 通过自举方法的单尾 HT

生成引导复制的基本过程与之前相同:

bs_replicates = boot_diff(dem_share_PA, dem_share_OH, np.mean, 100000)

额外的重要步骤 (与查找 CI 相比)是围绕假设平均值确定重复的分布中心:

bs_replicates_shifted = bs_replicates - np.mean(bs_replicates) - 2

让我们确保我们的 BS 重复样本总体以假设平均值为中心,并且标准误差的 BS 版本接近分析结果:

print(“Replicate 25th percentile, mean, 75th percentile:”,
 round(np.percentile(bs_replicates_shifted, 25),3), “~”,
 round(np.mean(bs_replicates_shifted)+1e-4, 2), “~”,
 round(np.percentile(bs_replicates_shifted, 75),3))
print(“Replicate Std Dev:”, round(np.std(bs_replicates_shifted),3)) 
# the analytical version is 1.585

重复第 25 百分位,平均第 75 百分位:-3.077 ~ -2.0 ~ -0.94
重复标准差:1.584

看起来不错…现在我们可以得到这组 BS 重复数据中平均值的经验差异的百分位数等级:

emp_diff_pctile_rnk = stats.percentileofscore(bs_replicates_shifted, emp_diff_means)
print("Empirical difference of the sample means:", round(emp_diff_means, 3))
print("Its percentile rank among the replicates:", round(emp_diff_pctile_rnk, 2), "% (AUC to the left)")
auc_left = round(emp_diff_pctile_rnk / 100, 4)
auc_rght = round(1 - emp_diff_pctile_rnk / 100, 4)
print("AUC to the left:  ", auc_left)
print("AUC to the right: ", auc_rght)

样本的经验差异平均值:1.158
其在重复中的百分位数等级:97.55 % (AUC 向左)
AUC 向左:0.9755
AUC 向右:0.0245

解读:
由于这是右尾检验, p 值就是右边的 AUC(非常接近0.0232的分析结果)。
由于我们正在进行单尾检验,我们可以直接将该值与显著性水平进行比较。

结论:拒绝零假设,因为 p 值小于0.10的显著性。

2.使用排列测试的显著性测试

置换检验用于确定观察到的效应是否可以合理地归因于选择样本时引入的随机性。如果不是,我们有证据表明在样本中观察到的效应反映了在人群中存在的效应。置换测试在临床研究等受控环境中非常流行,在这些环境中,需要将接受某种治疗的组与未接受任何治疗的对照组进行比较。

2.1 PT 理论

排列测试时可以用:

  • 当零假设表明两个总体相同时的两样本情形。我们可能希望比较总体的任何基本统计数据。就我们可以选择的统计数据而言,传统测试非常有限。
  • 当零假设表明配对中只有随机差异时的配对情景。这里也可以进行广泛的比较选择。
  • 当零假设表明变量不相关时的两个定量变量情景。通常相关性是最常见的度量,但不是唯一的。

基本上,当有两组数据并且零假设表明它们之间的一些观察到的效应是偶然观察到的时,我们可以执行 PT。

排列测试的一般流程:

  1. 选择一个测试统计量来衡量我们在两组数据之间寻找的效果(这一步在 bootstrap 测试中很常见)。通常这是每个数据集的“基础”统计之间的差异。
  2. 构建如果不存在该效应时该检验统计量将具有的抽样分布(这是排列检验的独特核心)。
  3. 在这个假设分布中找到观察到的(经验的)检验统计值。分布主体中的值很容易偶然出现。尾部中的值很少是偶然出现的,这可能是除了偶然之外的东西在起作用的证据(这在自举中很常见)。

当排列测试时,是否应该使用来代替自举测试:

在双样本检验设置中,我们可以在 bootstrap 检验和 permutation 检验之间进行选择。即使双样本排列测试的测试统计量可能被选择为与双样本 bootstrap 测试相同的(例如,样本均值之间的差异),测试的潜在性质却大不相同:排列测试实际上使用某个狭窄的统计量查看两个样本是否可能假设来自同一个总体,而 bootstrap 测试则专门查看统计量本身,因此排列测试是比 bootstrap 测试更“深入”更普遍的比较,但是(注意!)测试统计可能不会显示出来,这取决于您如何设计它,以及它如何捕捉样本之间的实际差异。

总之,排列测试应用于:

  • 对影响的存在(或不存在)的假设检验(例如,某种影响是否存在,或者是否存在某种积极影响,或者是否存在某种消极影响)。

自举应该用于:

  • 针对特定已知/预期效果的定量假设测试(例如,汽车电池的平均寿命实际上提高了一年或一年以上吗?).
  • 非参数化确定置信区间。

2.2 介绍性 PT 示例

为了介绍这个过程本身,让我们使用同样的双样本场景,我们使用 bootstrap 测试(BT)来测试总体均值之间的差异:

Ho :底层分布相同(均值等特征)
Ha :均值(PA 投票%) —均值(OH 投票%)!= 0

注意 : 这里的检验统计量和替代假设与我们进行的 bootstrap 检验相同,但是零假设必须保持非常通用,这仅仅是由于检验统计量通过排列复制的过程的性质(我们将很快看到为什么)。这里的逻辑是,一旦有足够的证据接受一个相当具体的替代假设,我们就可以拒绝一个非常笼统的零假设,这个零假设是很多东西的合取,包括替代假设的对立面。使用法律类比,在一个刑事案件中,可能只需要从所有可用证据中拿出一条非常具体的证据就可以打破非常普遍的无罪推定。然而,与法律环境不同的是,在排列测试中,我们通常对零假设本身不感兴趣(除非实际的测试目标是知道总体是否相同)。所以焦点转移到了另一个假设上。

让我们定义一个可重用的函数,我们可以利用它来产生一个测试统计的排列副本,调用一些对每个样本进行操作的基本统计函数(预定义的或用户定义的)。

def perm_diff(sample_1, sample_2, base_stat_func, num_iter):

    # initialize the list for the test statistic replicate
    perm_replicates = []
    # iterate for the specified number of iterations
    for i in range(num_iter):
        # concatenate the two samples into one
        samples_app = sample_1 + sample_2
        # permute the entire appended set (making this complete combined resampling WITHOUT REPLACEMENT)
        samples_perm = np.random.permutation(samples_app)
        # create the hypothesized samples by:
        #  pretending that the first len(sample_1) elements is the first sample
        sample_1_hyp = samples_perm[:len(sample_1)]
        #  and the rest is the second sample
        sample_2_hyp = samples_perm[ len(sample_1):]
        # compute the test statistic replicate and append it to the list of permutation replicates
        perm_replicates += [base_stat_func(sample_1_hyp) - base_stat_func(sample_2_hyp)]return perm_replicates

现在,让我们生成置换复制集:

perm_replicates = perm_diff(dem_share_PA, dem_share_OH, np.mean, int(1e5))

让我们简单看一下均值差的假设分布。它应该以零为中心,并且应该近似正常。

plt.hist(perm_replicates, bins=50, alpha=0.25)
plt.grid()
plt.show()

均值差异的排列复制(图片由吉恩·米先科提供)

现在我们需要从两个尾部得到 p 值,该值与使用该分布的均值的经验差异相关。
注意由于中心极限定理,置换分布在大多数情况下应该是相对对称的,作为一个好的实践,最好直接得到两个尾部下的 AUC。有几种技术方法可以做到这一点:

# looking at the absolute values on both tails and comparing them to the absolute empirical value simultaneously
p_val_2t_a = sum(np.abs(perm_replicates) >= abs(emp_diff_means)) / len(perm_replicates)
print(round(p_val_2t_a, 4))# Get the percentile rank of the NEGATIVE ABSOLUTE empirical value and take it as-is (looking at the left tail)
lt_p_val = stats.percentileofscore(perm_replicates, -abs(emp_diff_means) ) / 100
# Get the percentile rank of the ABSOLUTE empirical value and take the complement of it (looking at the right tail)
rt_p_val = 1 - stats.percentileofscore(perm_replicates, abs(emp_diff_means) ) / 100
# Add the two half-values together
p_val_2t_b = lt_p_val + rt_p_val
print(round(p_val_2t_b, 4))

0.4709
0.4709

结论:FTR (保留)原假设,即县对民主党人有利的投票百分比对 PA 和 OH 的分布是相同的,因为所得的 p 值大于0.10的显著性。

可能值得注意的是,这里的 p 值比使用分析法和自举法(0.465)比较平均值时略大...样本是相似的,所以很难判断结果的这种差异是否真的有意义,但一般来说,较大的 p 值是保持零假设的更强基础。

3.比较 Bootstrap 和置换分布

3.1 工作流程概述

因为在可以使用自举的情况和可以使用置换的情况之间有一些重叠,所以让我们实验性地比较复制的测试统计的相应总体,以便我们更好地理解使用它们的含义。
每次比较将包括以下假设检验工作流程,部分进行:

(1) 陈述高级业务目标,以及我们正在进行的研究与这些目标的关系。在陈述业务目标和当前研究目标时,要尽可能具体。
【2】定义可以帮助我们达到研究目标的统计数据(这里我们假设这些样本是我们得到的唯一数据集,但通常这个阶段包括数据发现、EDA 和/或新数据收集设置的迭代过程,视需要和可行而定)。
(3) 设计使用上述统计量来满足上述研究目标的统计推断任务。根据需要创建尽可能多的任务。对于每个假设检验,需要说明以下项目:

  • 要使用的测试统计
  • 根据选定的统计数据陈述的无效假设和替代假设
  • 测试的方向(单尾/双尾)
  • 置信度/显著性水平
  • 要使用的方法(例如参数/引导/排列)

(4) 执行任务。

步骤(1)可能经常看起来琐碎和不必要,但它是选择统计数据和正确设计测试所必需的。在我们的比较中,步骤(1)和(2)将在 bootstrap 和置换测试中共享。
我们不会执行步骤(4)——实际进行测试——所以我们不需要定义置信区间。

我们将重点比较检验统计重复的两种分布和相应的 p 值:

  • 引导复制分布
  • 置换复制分布

3.2 示例设置

研究目标:这是一项关于一种新的教学方法对大学生成绩影响的假想对照研究。它被直接整合到新教学方法的开发和测试过程中。我们的任务是特别关注新方法的效果,通过学生的考试成绩来衡量。这项研究的结论将与其他考虑因素一起,用于决定是否为该科目改用新的教学方法。
研究设置:一个随机组成的“治疗”组在一个学期内接受新的教学方法,另一个随机组成的“控制”组接受同一科目的传统教学方法。每组由 100 名学生组成。教授这门课程的教师必须同时教授两组学生,以便尽可能地消除教学中的人为因素。两组学生的期中和期末考试是一样的。
为每个小组收集的数据是每个学生的期中和期末考试成绩的平均值,满分为 100 分。

让我们生成示例数据:

# draw the raw random data for the control sample from a normal distribution
np.random.seed(5)
cs_raw = np.random.normal(loc=75.0, scale=9.0, size=100)
# "pivot" the right tail around 100 with a multiplier 
# (there should not be many cases)
cs = [score - (score - 100)*1.5 if score > 100 else score for score in cs_raw]# draw the raw random data for the treatment sample from a normal distribution 
# with a slightly larger mean and a significantly larger standard deviation than for the control sample
# (it is expected that there will be quite a few instances here that go over 100)
ts_raw = np.random.normal(loc=78.0, scale=13, size=100)
# "pivot" the right tail around 100 with a multiplier, which caps the score at the max,
# making the right tail much thicker and shorter
ts = [score - (score - 100)*2.0 if score > 100 else score for score in ts_raw]

3.3 样品的 EDA

fig = plt.gcf()
fig.set_size_inches(16,8)
plt.hist(cs, bins=20, alpha=0.15, label = 'control group')
plt.hist(ts, bins=20, alpha=0.15, color='r', label = 'treatment group')
plt.legend()
plt.grid()
plt.show()

对照和治疗样品(由 Gene Mishchenko 成像)

print("Control   mean, 10th, 25th, 50th, 75th, 90th pctiles:", 
      round(np.mean(cs),2), "~", 
      round(np.percentile(cs,10),2), "~",
      round(np.percentile(cs,25),2), "~",
      round(np.percentile(cs,50),2), "~",
      round(np.percentile(cs,75),2), "~",
      round(np.percentile(cs,90),2))
print("Treatment mean, 10th, 25th, 50th, 75th, 90th pctiles:", 
      round(np.mean(ts),2), "~", 
      round(np.percentile(ts,10),2), "~",
      round(np.percentile(ts,25),2), "~",
      round(np.percentile(ts,50),2), "~",
      round(np.percentile(ts,75),2), "~",
      round(np.percentile(ts,90),2))

对照组均值,第 10、25、50、75、90 百分位数:75.82 ~ 67.12 ~ 70.62 ~ 74.43 ~ 81.78 ~ 86.67

结论:看起来平均分数提高了大约 2 分,并且相对于对照组,治疗组中的 A 和 B 学生要多得多,但是在低端也发生了一些事情——更多的学生不及格(分数< 70)并且差距更大。
因此,在本例中,我们可以看到潜在的正面影响和负面影响。

3.4 研究用例 1(平均学习进步)

让我们假设我们唯一关心的商业目标是所有学生平均学习成绩的提高。
测试统计:我们认为治疗组和对照组学生之间的平均测试分数
的任何统计显著正差异都是达到商业目标的证明。

自举测试

Ho :均值(治疗组得分)—均值(对照组得分)= 0
【Ha】:均值(治疗组得分)—均值(对照组得分)> 0
方向 :右尾

排列测试

Ho :学生分数分布相同(含均值)
Ha :均值(治疗组分数)—均值(对照组分数)> 0
方向 :右尾

生成和比较复制分布

首先,让我们生成并绘制两个复制分布:

boot_diff_mean_scores = boot_diff(ts, cs, np.mean, int(1e5))
# DON'T FORGET TO SHIFT TO THE HYPOTHESIZED MEAN (0 in this case)
boot_diff_mean_scores = boot_diff_mean_scores - np.mean(boot_diff_mean_scores) + 0perm_diff_mean_scores = perm_diff(ts, cs, np.mean, int(1e5))fig = plt.gcf()
fig.set_size_inches(10,5)
plt.hist(boot_diff_mean_scores, bins=50, alpha=0.15, label = 'boot repl')
plt.hist(perm_diff_mean_scores, bins=50, alpha=0.15, color='r', label = 'perm repl')
plt.legend()
plt.grid()
plt.show()

自助复制和排列复制—均值差异(图片由 Gene Mishchenko 提供)

分布之间没有很大的差异,排列重复分布略宽(对于较大的样本量,分布之间的差异较小,对于较小的样本量,差异更大)。

现在让我们看看 p 值。由于我们正在进行右尾检验,p 值是观察值的百分位秩的补数:

emp_val = np.mean(ts) - np.mean(cs)
boot_p_val = 1 - stats.percentileofscore(boot_diff_mean_scores, emp_val)/100
print("p-value by bootstrapping:\t", round(boot_p_val,5))
perm_p_val = 1 - stats.percentileofscore(perm_diff_mean_scores, emp_val)/100
print("p-value by permutation:\t\t", round(perm_p_val,5))

自举 p 值:0.09773
置换 p 值:0.10201

结论:排列法比自举法给测试过程增加了更多的随机性(这种差异在样本越小的情况下越明显),所以我们得到了一个更保守的答案。这就是为什么排列测试是分类假设测试的更好选择
在这个具体的例子中,如果我们的显著性水平设置为 10%,方法的选择将产生关键的差异,因为 p 值落在它的不同边上(这也是为什么我们应该总是在实施测试之前确定显著性水平,这样我们就不会试图回解)。

3.5 研究用例 2(留守学生)

现在,让我们说,就商业目标而言,大学管理层不仅关心平均学习成果,还关心学生的辍学率和不合格率(当然,尽可能保持这些比率较低)。
假设研究目标、研究设置和收集的数据自始至终都与这一新信息保持一致,我们能做些什么来实现研究目标?

好吧,鉴于这种人工数据集,我们无法测量辍学率(或课程完成率),但在现实生活中,完成课程的学生的考试成绩会得到这种信息的补充…所以让我们专注于分析低端的考试成绩。

我们可能要考虑的每个数据集的【基础】统计 是低于下四分位数的平均分数。因此检验统计量将是治疗组的基础统计量和对照组的基础统计量之间的差异。就像平均测试分数的差异一样,这是一个度量,意味着如果它有一个正的符号,它对业务有好处,反之亦然。
让我们定义一个用于计算基本统计数据的函数,我们可以将它传递给boot_diffperm_diff函数:

def low_quart_mean(arr):
    first_percentile = np.percentile(arr, 25)
    filt_arr = [x for x in arr if x <= first_percentile]
    return np.mean(filt_arr)

现在让我们在处理样品和对照样品上测试它…

low_quart_mean(ts)

60.97728174389116

low_quart_mean(cs)

65.93498145550805

从控制样本到处理样本的平均下降 5 个点…这应该很有趣…让我们来设置我们的测试。

自举测试

Ho :均值(治疗组最低分之一)—均值(对照组最低分之一)>= 0
Ha:均值(治疗组最低分之一)—均值(对照组最低分之一)< 0
方向 :左尾

排列测试

Ho :学生分数分布相同(包括分数最低的四分之一的均值)
Ha :均值(治疗组分数最低的四分之一)—均值(对照组分数最低的四分之一)< 0
方向 :左尾

注意:我们有意将替代假设的方向设定为我们在 EDA 过程中所做的初步发现的方向……否则,置换测试在 FTR 结果(未能拒绝零假设)的情况下将不会非常有用,因为零假设非常普遍(在 PT 中也必须如此)。在研究过程中,必须在第一次测试后保留零假设,然后尝试构建一个不同的测试来“打破它”,这是完全正常的,但如果我们有一个基于 EDA 的“直觉”,并且我们认为我们可以在一个测试中做到这一点,为什么不这样做呢?
在 bootstrap 测试中,我们没有这种限制——零假设可以被定义在与替代假设相同的水平上,并且是相反的镜像,因此测试的方向变得任意。
此外,作为一个提醒,除了排列测试中对零假设的限制,排列测试中的替代假设也有一个限制——测量假设数据集之间差异的重复统计必须以 0 为中心,因为方向性在这个过程中丢失了。
Bootstrap 测试对 HoHa 没有这些限制,这就是为什么对于已确认/预期效果的定量测试来说 Bootstrap 是一个自然的选择

生成和比较复制分布

boot_diff_lqms = boot_diff(ts, cs, low_quart_mean, int(1e5))
# DON'T FORGET TO SHIFT TO THE HYPOTHESIZED MEAN (0 in this case)
boot_diff_lqms = boot_diff_lqms - np.mean(boot_diff_lqms) + 0perm_diff_lqms = perm_diff(ts, cs, low_quart_mean, int(1e5))fig = plt.gcf()
fig.set_size_inches(10,5)
plt.hist(boot_diff_lqms, bins=50, alpha=0.15, label = 'boot repl')
plt.hist(perm_diff_lqms, bins=50, alpha=0.15, color='r', label = 'perm repl')
plt.legend()
plt.grid()
plt.show()

BS 复制和烫发。重复——下四分之一差异表示(图片由 Gene Mishchenko 提供)

同样,排列复制似乎分布得稍宽。

现在让我们看看 p 值。因为我们正在进行左尾检验,所以每种情况下的 p 值都是观察值的百分位:

emp_val = low_quart_mean(ts) - low_quart_mean(cs)
boot_p_val = stats.percentileofscore(boot_diff_lqms, emp_val)/100
print("p-value by bootstrapping:\t", round(boot_p_val,5))
perm_p_val = stats.percentileofscore(perm_diff_lqms, emp_val)/100
print("p-value by permutation:\t\t", round(perm_p_val,5))

自举 p 值:0.01304
置换 p 值:0.01651

结论:在这个用例中,重复分布之间的差异甚至比平均值之间的差异更明显,置换法产生了更宽的测试统计分布,并产生了更大的 p 值,这是一个更保守的零假设拒绝标准。

3.6 BT 与 PT —总结

Bootstrapping 是一种更通用的方法,它不局限于具有两组数据的情况,不局限于假设检验,并且在无效假设和备选假设方面限制较少。它应该用于估计置信区间和已知效应的定量假设检验。

置换检验可用于两个数据集(两个样本、配对或一个样本中的两个变量)的设置中,当我们想要确认两个数据集之间存在(或不存在)某种可观察到的效应时,应使用置换检验。

无聊的游戏——一个封闭的数据科学家的沉思

原文:https://towardsdatascience.com/bored-games-c31340859bef?source=collection_archive---------69-----------------------

Python 中探索性数据和回归分析的一个上午

(图片作者)

面对现实吧——在本月第十次拿出拼字板后,更多时间呆在家里的新鲜感开始消退。

抛开圣诞节前后的年度高峰不谈,一级防范禁闭已经让人们在网上搜索桌游的人数激增。这与搜索“无聊”的人增多不谋而合。

现在,虽然我不想宣扬虚假的相关性,但我发现在英国封锁期间,人们搜索“无聊”和“桌游”的趋势很能说明问题。受此鼓舞,在几个小时的空闲时间里(大约是我在拼字游戏中选择下一个单词的时间),我想知道我还能找到更多关于英国新的最受欢迎的过去时光的信息。

Kaggle 数据集 来救援了!

简单的搜索让我找到了一个取自 BoardGameArena 的精彩数据集,它提供了超过 100k 个游戏的全部信息!在看到数据集中的可用数据后,我发现自己想要深入的两个领域是年龄分级(“适合 12 岁以上”等。 ) 以及为众多游戏收集的星级财富。我想到了以下问题:

  1. 为年轻玩家设计的游戏是为了玩得更快吗?
  2. 某些游戏发行商在创作高质量、受欢迎的游戏方面是否落后于其他发行商?
  3. 给定这个不同的数据集,我能根据它的特点预测某个游戏将得到的评级吗?

前两个问题可以通过快速的探索性分析来回答,也就是说,直观地检查数据的某些部分,所以让我们开始吧。

为年轻玩家设计的游戏是为了玩得更快吗?

下图是一个方框图,显示了推荐的游戏时间是如何随着游戏的年龄范围而变化的。我还用灰色条显示了每个年龄有多少游戏被分级。

请注意,随着最小年龄从零开始增加,中值游戏时间(每个框中的橙色线)是如何增加的,然而,在 12 岁以上,建议的游戏时间似乎会减少。

似乎建议的游戏时间随着推荐年龄从零开始增加而增加,但是在 12 岁时达到一个转折点,之后它再次减少。

一个可能的原因是年龄限制的游戏,这里我认为是 15 岁以上,是为晚上/饭后聚会设计的,也许需要更快的游戏。

另一个可能的原因可能是这些年龄范围的样本量减少了,尽管每个范围都有 1000 多场比赛,我现在可以把这个问题放在一边。

某些游戏发行商在创作高质量、受欢迎的游戏方面是否落后于其他发行商?

在我们调查顶级发行商的游戏等级之前。

排名靠前的出版商按评分从高到低排序。

我们可以看到,虽然大约三分之二的顶级出版商拥有非常相似的评级,但有一些接近图表底部的出版商开始让这一方失望。

让我们简单地关注一下表现最差的出版商。当查看像这样的数据的单个切片时,需要考虑的一个问题是可能有一个被忽略的变量。这是回归分析中突然出现的一个概念,但在这里也适用。想象一下这个场景:

人们喜欢文字游戏,他们通常对它们评价极高。人们不太喜欢角色扮演游戏,对它们的评价也更低。如果某个发行商制作的角色扮演游戏比其他大多数发行商都多怎么办?后续的低收视率是发行商的影响,还是游戏类型的影响,或者两者兼而有之?

像这样同时考虑多种因素,挑出每个变量的真实影响会把我们带到回归分析的领域。

给定这些不同的数据集,有可能根据某个游戏的特点预测出它的评分吗?

要回答这个问题,我们可以用一种叫做线性回归的方法。本质上,我们希望利用我们所知道的关于一个游戏的所有因素(它的类别,它的年龄等级和推荐的游戏时间等等)。)并从中预测该游戏有多受欢迎。这类案件中出现的一个关键问题是:

我们如何知道一个预测是好的呢?

使用我们的案例来构建示例,评估预测是否是高质量的一种常用方法是预测一些游戏的评级,尽管我们手头有真实的评级,但在测试之前,我们没有让模型看到(并从中学习)。

一堆我们知道评级的游戏,使用分成训练和测试子集的方法来评估模型质量。(图片作者)

使用这种技术,我们可以创建所谓的 R 统计量。一个介于 0 和 1 之间的数字,它描述了在游戏评分中看到的变化有多少可以通过我们在模型中包括的因素解释——如果我们的模型给出的 R 为零,它在预测评分方面是无用的,如果它给出的 R 为 0.8,它将只使用我们提供的因素解释 80%的评分变化。

在这种情况下,使用:

Year, Minimum Age, Minimum Play Time, Maximum Play Time, Number of Votes, Category, Game Mechanic, Minimum Player, Maximum Players

…我们可以解释大约三分之一(R = 0.33)的评级变化。

让我们考虑一下这个问题。什么是好的棋盘游戏?是创作的年份吗?—也许有一点。是它需要的玩家数量吗?—我玩过一些很棒的双人游戏,也玩过一些很烂的!因此,虽然这些因素可能解释了一点什么使游戏变得有趣,但它们可能没有触及问题的核心——所以我们为什么要期待非常高的 R 值呢?

我想这可以归结为…回归方法不是魔法,它们只能显示关系,如果这些关系一开始就存在的话。

从另一个角度来看,如果你是一个游戏设计师,那么对于一个伟大的游戏来说,仅仅基于这里的因素,并不存在制胜公式

所以我们有了它,有了几个小时的空闲时间和一个免费可用的数据集,我们对游戏如何为年幼的孩子设计有了一些了解,你的下一个游戏可以参考哪些出版商,并看到了使用线性回归预测的一瞥。

无论你是一个现在有更多时间的数据科学家,还是你仍然想知道乐高套装是否真的变得越来越简单,有成千上万的开源数据集正等着你去发现…

你还在等什么?

接下来我要看什么?

在我的分析笔记本中可以找到我下一步要做的技术改变的细节。总的来说,这个快速调查向我展示了在短时间内可能发生的事情,无论这个问题是轻松的还是更深入的,我们对答案的搜索都不一定要以谷歌搜索和假设结束。外面有一整个世界的数据,你的问题的答案可能就在表面之下。

[## Paul stub ley-LinkedIn 自由职业数据和决策科学家

我是一名经验丰富的数据科学家,在个人工作和管理团队方面都有卓有成效的工作经历。

www.linkedin.com](https://www.linkedin.com/in/paul-stubley/)

如果你想联系我,你可以在 LinkedIn 上联系我。如果您想查看完成此分析的 Jupyter 笔记本 ,请在GitHub上查看。google-trends lineplot-race 是使用 【兴盛】 创建的。所有其他图表都是使用Seaborn创建的。封面图片和流程图都是我自己的内容。

【1】这个数据集是 Markus Shepherd 整理出来的,在这里

[2]如果你是盒状图的新手,关注中心的矩形。穿过中间的橙色线显示了中间值——如果所有游戏的评分从最低到最高排成一行,中间值将是列表中间的那个——而矩形的顶部和底部显示了 25%和 75%的界限——因此 75%的游戏评分低于矩形的顶部,但只有 25%的游戏评分低于矩形的底部。通过这种方式,箱线图不仅显示了分布的中心值,还显示了其分布的度量。

冠状病毒封锁期间鲍里斯·自行车在伦敦的使用

原文:https://towardsdatascience.com/boris-bike-usage-in-london-during-the-coronavirus-lockdown-9680a5e52e11?source=collection_archive---------47-----------------------

全球疫情时代的网络分析

点击此处更新截至 2020 年 8 月 9 日的最新 TfL 数据

在冠状病毒疫情期间,围绕公共旅行范围和所用交通方式的数据受到了密切关注——例如,在英国政府的每日简报和 Citymapper 的移动指数中出现。据我所知,没有人调查过鲍里斯自行车的使用情况。

伦敦交通局(TfL)-通过他们的统一 API 和开放数据-提供伦敦使用桑坦德循环公共自行车租赁计划(即所谓的“鲍里斯自行车”)的所有旅程的综合数据。在这篇文章中,我试图找出冠状病毒封锁期间人们如何使用这些自行车的行为变化。所有数据都是作者对这个 TfL 数据的分析。

[来源:unspalsh.com]

我们对每段旅程了解多少?

在 TfL 的数据中,您可以看到每个完整旅程的以下详细信息:

骑鲍里斯自行车的一次单独旅行[来源:作者自己的]

我使用 TfL 统一 API 将站点 id 映射到经度/纬度坐标。虽然这些数据非常全面,但不幸的是在可用性方面存在滞后——可用的最新数据截止到 2020 年 4 月底。

鲍里斯自行车在“正常时期”是如何使用的?

首先,利用 2019 年以来的所有旅程,我们需要了解鲍里斯自行车的“正常”用法。左图显示了工作日和周末行为的明显区别。自行车租赁在工作日是双峰式的——当自行车用于通勤时,在工作日的开始和结束时有两个明显的使用高峰。在周末,租用是单峰的——自行车用于休闲旅行或锻炼,租用高峰在下午三点左右。考虑到伦敦的天气,数据中有很多季节性就不足为奇了,如右图所示。夏季月份的使用率明显较高(7 月份的出行量几乎是 12 月份的两倍),但随着人们骑车休闲,周末出行的比例在夏季也有所增加。

2019 年正常使用情况:周末和工作日呈现不同的使用模式(左图);使用是季节性的(右图)[来源:作者自己的]

在冠状病毒封锁期间,行为发生了怎样的变化?

英国政府从 3 月 24 日星期二(今年的第 13 周)开始实施封锁。下图比较了 2020 年(深蓝色)和 2019 年(浅蓝色)每周的旅行次数,红线显示了 2020 年每周的使用量占 2019 年使用量的百分比。虽然旅行频率通常会增加(随着天气的改善),但从第 12 周(封锁前的一周,政府建议不要社交)开始,使用率急剧下降,并在实施封锁后的第 13 周触底。有趣的是,使用率大幅反弹,截至 4 月底,已达到 2019 年水平的 85%。这与地铁、公共汽车和道路的使用形成对比(如政府每日简报所示)。

对比 2019 年(浅蓝色)和 2020 年(深蓝色)的周雇佣量。当宣布封锁时,使用停止了,但后来又恢复了[来源:作者自己的]

自从封锁开始后,使用类型有变化吗?

在封锁之前,使用率可以总结为主要由工作日通勤和周末休闲/锻炼驱动,有两种截然不同的租用制度。下面的左图显示,在封锁期间没有什么不同——每天看起来都像周末。在早上的通勤时间仍然有一个小的工作日高峰,因为一些人仍然在上班。与周末(下午 2 点至 4 点)相比,工作日的使用高峰在一天的晚些时候(下午 5 点至 7 点)。这表明人们在下班后骑自行车进行一天一次的锻炼。

如果你在同一个停靠站开始和结束一次旅行,这是一次纯粹的休闲或锻炼的最清晰的标志。下图显示了这种旅行的频率,增加了 5 倍。

封锁期间的使用模式表明,自行车主要用于休闲和锻炼目的[来源:作者自己的]

鉴于这种用法的变化,人们会去不同的地方吗?

这些数据可以被认为是图论的一个很好的应用,每个旅程代表一个顶点,每个停靠站代表一个节点。下面的图表将每个停靠站映射为红点,将每个旅程映射为蓝线(仅显示最受欢迎的 4000 条独特路线)。对接站节点的大小对应于在该站开始或结束的旅程的数量;这是按比例缩放的,以便最流行的扩展坞在两个图表上具有相同大小的节点。图中显示了泰晤士河的大致形状(尽管并不完全准确)。

封锁期间的使用远不集中在伦敦市中心的交通枢纽国王十字和滑铁卢[来源:作者自己的]

在封锁之前,你可以清楚地看到伦敦市中心周围的焦点——特别是国王十字车站和滑铁卢附近的两大活动集中地,代表着交通网络的主要枢纽。虽然最繁忙的停靠站位于这些区域,但由于单个停靠站的自行车/停靠站数量有限,而且由于停靠站在这些区域的高度集中,因此没有单个停靠站占主导地位。

相比之下,在封锁期间,网络上的活动分散得多。伦敦市中心的交通枢纽不再占主导地位,使用率也不再集中在最受欢迎的停靠站。

然而,封锁导致一些停靠站变得异常繁忙,尤其是海德公园周围和沿河(威斯敏斯特,南岸)的停靠站。这可以通过查看最受欢迎的车站以及它们占旅程的百分比来看出。

少数车站在封锁期间变得异常繁忙[来源:作者自己的]

通过使用 Python 中的 NetworkX 包,很容易计算一些图论度量。例如,根据扩展坞节点的度中心性来确定扩展坞节点的大小(两个图表中的节点大小相同)强调了锁定前对国王十字车站和滑铁卢车站的关注,以及锁定期间更加统一的网络使用。这个软件包为更有趣的网络分析提供了很大的潜力。

节点大小与对接站的中心度成正比[来源:作者自己的]

有趣的下一步?

当 TfL 发布新数据时,更新分析。尝试通过自行车租赁来确定人们返回工作岗位的程度是很有趣的

更好的制图——如果有一张更准确、更容易辨认的伦敦地图就好了…

更多 NetworkX 分析!

2020 年 6 月 6 日更新:TfL 发布下一批 2020 年 5 月数据

在 2020 年 5 月,封锁程度略有缓解,这也是伦敦天气非常好的一个月。桑坦德自行车的使用率持续上升,每周总骑行次数现在回到(甚至到)2019 年的水平。

雇佣频率已恢复至 2019 年水平【来源:作者本人】

随着封锁的发展,桑坦德循环的数据可以用来理解行为变化吗?以下热图显示了一年中不同时间(y 轴)的雇佣频率(x 轴上的日期)。颜色越深,在那天的那个时间骑自行车的人就越多。

在 2020 年的数据中还没有回到通勤模式的证据[来源:作者自己的]

左边的图表显示了整个 2019 年。工作日的特点是上下班时间的使用高峰(如上所述),而周末的使用更多地分布在一天的中间。可以预见的是,在夏季的几个月里,活动量会更大,五月至七月的漫长夜晚鼓励了晚间使用。

右边的图表显示 2020 年至今。在实施封锁之前,使用情况与 2019 年非常相似。3 月下半月的活动明显减少(如上所述),此后几周内,自行车租赁有所恢复。截至 5 月底,没有迹象表明正常的“朝九晚五的通勤模式”回归,活动集中在一天的开始和结束。休闲自行车似乎仍然占主导地位。

随着时间的推移,关注这些数据会很有意思,试图观察更广泛的办公室回报。

截至 2020 年 8 月 9 日更新: TfL 发布下一批 2020 年 6 月和 7 月数据

经过长时间的拖延,TfL 终于发布了截至 8 月 4 日的最新一批数据。在这段时间里,封锁继续放松,酒店行业开始开放,WFH 的指导已经放松,我们现在在外面吃饭来帮助解决问题。这些变化如何反映在桑坦德循环的使用中?

在较高的水平上,使用率仍然很高,与 2019 年的水平非常接近。

雇佣频率保持与 2019 年水平相当[来源:作者自己的]

然而,最新的热图(左图)显示休闲自行车似乎仍然占主导地位,没有正常“通勤模式”回归的真正迹象。

右边的图表更清楚地说明了这一点;这张图表比较了 2019 年和 2020 年每周工作日上午 8-9 点之间的旅行频率。历史上,这个时间是桑坦德自行车公司活动的高峰期,因为通勤者骑自行车去办公室。尽管鼓励通勤者骑自行车上班,而不是使用公共交通工具,但在此通勤期间的出行量不到 2019 年相应水平的 50%。

休闲自行车似乎仍占主导地位,通勤旅行不到 2019 年水平的 50%【来源:作者自己】

这一最新数据充分表明,迄今为止,重返办公室的步伐一直很慢。

博鲁塔准确地解释了你希望别人如何向你解释

原文:https://towardsdatascience.com/boruta-explained-the-way-i-wish-someone-explained-it-to-me-4489d70e154a?source=collection_archive---------0-----------------------

看看最有效的特征选择算法之一的 Boruta

特征选择是许多机器学习管道中的基本步骤。您丢弃了一堆特征,并且希望只选择相关的特征,而丢弃其他的特征。这样做的目的是通过去除会引入不必要噪声的无用特征来简化问题(听说过 Occam ?).

Boruta 是一种非常智能的算法,可以追溯到 2010 年,旨在自动对数据集执行特征选择。它是作为 R 的一个包而诞生的(这个是最早描述它的文章)。Python 的一个版本 Boruta——叫做 BorutaPy——已经存在,可以在这里找到。

在这篇文章中,我们将看到一些直接的 Python 代码来从头实现 Boruta——我相信从头构建是真正理解它的最好方法——并且,在文章的最后,我们将看到如何使用 borutay 来使我们的生活变得更容易。

1.一切都从 X 和 y 开始

为了看到 Boruta 的行动,让我们建立一个玩具数据集,它具有 3 个特征(年龄身高体重)、一个目标变量(收入)和 5 个观察值。

import pandas as pd### make X and y
X = pd.DataFrame({'age': [25, 32, 47, 51, 62],
                  'height': [182, 176, 174, 168, 181],
                  'weight': [75, 71, 78, 72, 86]})
y = pd.Series([20, 32, 45, 55, 61], name = 'income')

x 和 y

所以目标是在知道一个人的年龄、身高和体重的情况下,预测他/她的收入。这可能看起来很荒谬(至少在理论上是这样:在实践中,身高已经被证明与薪水有关),但是总的来说,不要受个人偏见的影响是明智的。

在现实生活中,我们必须处理 3 个以上的特征(通常从几百到几千个)。因此,逐一检查并决定是否保留它是不可行的。此外,有些关系(例如非线性关系和相互作用)不容易被人眼发现,即使通过精确的分析也不容易发现。

理想情况下,我们希望找到一种算法,能够自主决定 X 的任何给定特征是否具有关于 y. 的一些预测值

2.为什么是博鲁塔?

一个流行的特征选择算法是 sklearn 的 SelectFromModel 。基本上,你选择一个方便的模型——能够捕捉非线性关系和相互作用,例如随机森林——然后把它放在 Xy 上。然后,从这个模型中提取每个特性的重要性,只保留高于给定重要性阈值的特性。

这听起来很合理,但这种方法的弱点是不言而喻的:谁来决定阈值,以及如何决定?这里面有很大的随意性。

当我第一次遇到这个问题时,我开始寻找一个更健壮的解决方案。直到我找到了博鲁塔。Boruta 是一种基于统计的特征选择算法,即使没有用户的任何特定输入也能非常好地工作。这怎么可能呢?

Boruta 基于两个绝妙的想法。

2.1 第一个理念:阴影功能

在 Boruta 中,特性之间并不竞争。相反——这是第一个绝妙的想法——他们与随机版本的他们竞争。

实际上,从 X 开始,另一个数据帧是通过随机洗牌创建的。这些置换的特征被称为阴影特征。此时,影子数据帧被附加到原始数据帧上,以获得一个新的数据帧(我们将称之为 X_boruta ),其列数是 X 的两倍。

import numpy as np### make X_shadow by randomly permuting each column of X
np.random.seed(42)
X_shadow = X.apply(np.random.permutation)
X_shadow.columns = ['shadow_' + feat for feat in X.columns]### make X_boruta by appending X_shadow to X
X_boruta = pd.concat([X, X_shadow], axis = 1)

在我们的例子中,这就是 X_boruta 的样子:

x _ 博鲁塔

然后在 X_borutay 上安装一个随机森林。

现在,我们将每个原始特征的重要性与一个阈值进行比较。这次,阈值被定义为阴影特征中记录的最高特征重要性。当特征的重要性高于这个阈值时,这被称为“命中”。这个想法是,只有当一个特性能够比最好的随机特性做得更好时,它才是有用的。

重现此过程的代码如下

from sklearn.ensemble import RandomForestRegressor### fit a random forest (suggested max_depth between 3 and 7)
forest = RandomForestRegressor(max_depth = 5, random_state = 42)
forest.fit(X_boruta, y)### store feature importances
feat_imp_X = forest.feature_importances_[:len(X.columns)]
feat_imp_shadow = forest.feature_importances_[len(X.columns):]### compute hits
hits = feat_imp_X > feat_imp_shadow.max()

对于我们的玩具数据集,结果是:

一次运行的结果

阈值为 14%(最大值为 11%、14%和 8%),因此有两个特征命中,即年龄身高(分别为 39%和 19%),而体重 (8%)得分低于阈值。

显然,我们应该放下体重,继续关注年龄身高。但是,我们应该相信这次跑步吗?如果只是一次不走运的减肥跑步呢?如果这只是年龄和身高的运气呢?

这就是博鲁塔的第二个绝妙想法发挥作用的地方。

2.2 第二个想法:二项分布

就像机器学习中经常发生的那样(生活中?),关键是迭代。毫不奇怪,20 次试验比 1 次试验更可靠,100 次试验比 20 次试验更可靠。

例如,让我们重复上述过程 20 次。

### initialize hits counter
hits = np.zeros((len(X.columns)))### repeat 20 times
for iter_ in range(20): ### make X_shadow by randomly permuting each column of X
   np.random.seed(iter_)
   X_shadow = X.apply(np.random.permutation)
   X_boruta = pd.concat([X, X_shadow], axis = 1) ### fit a random forest (suggested max_depth between 3 and 7)
   forest = RandomForestRegressor(max_depth = 5, random_state = 42)
   forest.fit(X_boruta, y) ### store feature importance
   feat_imp_X = forest.feature_importances_[:len(X.columns)]
   feat_imp_shadow = forest.feature_importances_[len(X.columns):] ### compute hits for this trial and add to counter
   hits += (feat_imp_X > feat_imp_shadow.max())

这是结果:

20 次运行的结果

现在,我们如何设定决策标准?这是博鲁塔所包含的第二个高明的想法。

就拿一个特征来说吧(不管的年龄的身高还是的体重),我们完全不知道它是否有用。我们保留它的可能性有多大?该特性的最大不确定性以 50%的概率表示,就像扔硬币一样。由于每个独立的实验可以给出一个二元结果(命中或未命中),一系列的 n 试验遵循一个 二项分布

在 Python 中,二项式分布的概率质量函数可计算如下:

import scipy as sptrials = 20
pmf = [sp.stats.binom.pmf(x, trials, .5) for x in range(trials + 1)]

这些值看起来像一个铃铛:

特征的二项式分布和定位

在 Boruta 案中,拒绝和接受之间没有硬性的界限。相反,有 3 个方面:

  • 一个拒绝区域(红色区域):结束在这里的特征被认为是噪声,所以它们被丢弃;
  • 犹豫不决的区域(蓝色区域):博鲁塔对这个区域的特征犹豫不决;
  • 一个接受区域(绿色区域):这里的特征被认为是预测性的,所以它们被保留。

通过选择分布的两个最极端部分,即分布的尾部来定义面积(在我们的例子中,每个尾部占分布的 0.5%)。

因此,我们对玩具数据进行了 20 次迭代,最终得出了一些有统计依据的结论:

  • 为了预测一个人的收入年龄是预测性的,应该保留,体重只是噪音,应该去掉,
  • 博鲁塔对身高举棋不定:选择权在我们,但在保守的框架下,还是保持为宜。

在这一段中,我们已经实现了必要的代码,但是在 Python 中有一个很棒的(优化的)Boruta 库。

3.在 Python 中使用 BorutaPy

Boruta 可通过 pip 安装:

!pip install boruta

这是它的使用方法:

from boruta import BorutaPy
from sklearn.ensemble import RandomForestRegressor
import numpy as np###initialize Boruta
forest = RandomForestRegressor(
   n_jobs = -1, 
   max_depth = 5
)
boruta = BorutaPy(
   estimator = forest, 
   n_estimators = 'auto',
   max_iter = 100 # number of trials to perform
)### fit Boruta (it accepts np.array, not pd.DataFrame)
boruta.fit(np.array(X), np.array(y))### print results
green_area = X.columns[boruta.support_].to_list()
blue_area = X.columns[boruta.support_weak_].to_list()print('features in the green area:', green_area)
print('features in the blue area:', blue_area)

如您所见,存储在 boruta.support_ 中的特征是那些在某个点上结束于验收区域的特征,因此您应该将它们包含在您的模型中。存储在 boruta.support_weak_ 中的特性是 boruta 无法接受或拒绝的特性(蓝色区域),这取决于数据科学家的选择:这些特性可能被接受,也可能不被接受,这取决于用例。

4.结论

特征选择是机器学习管道中的决定性部分:过于保守意味着引入不必要的噪音,而过于激进意味着丢弃有用的信息。

在这篇文章中,我们看到了如何使用 Boruta 在数据集上执行稳健的、基于统计的要素选择。事实上,做出关于特性的实质性决策对于确保预测模型的成功至关重要。

波士顿 Airbnb 探索性分析

原文:https://towardsdatascience.com/boston-airbnb-exploratory-analysis-75012d987e51?source=collection_archive---------42-----------------------

分析波士顿 Airbnb 房源,寻找成为房东的机会

迈克尔·布朗宁在 Unsplash 上拍照

分析背景

Airbnb,Inc 是一家总部位于加利福尼亚州旧金山的美国公司,是最著名的在线短期租赁公司之一。它专注于住宿交易、寄宿家庭和旅游体验,甚至没有任何真正的国有上市公司。

自成立以来,Airbnb 每年都在持续增长,这对任何有兴趣投资的人来说都是一个有吸引力的市场。随之而来的是,许多关于如何被引导做出最佳决策的问题。

在这个项目中,我们将通过数据分析探索波士顿市的 Airbnb 业务,确定哪些选项可能更有利可图,更值得投资。

数据集

为了找到答案,我们将使用由数据提供的来自 Airbnb 波士顿的文件。世界。该数据集由三个主要文件组成:从 2009 年到 2016 年的房源、评论和日历。

此外,还对有关波士顿市的其他信息进行了外部搜索。

数据探索

波士顿的 Airbnb 房源和旺季

首先,我们将带来一个不考虑上市、旺季和价格变化的总体概述,这将帮助我们了解作为投资者我们可以期待什么。

上面的图表向我们展示了上市公司逐年增长的情况,从中可以观察到自 2009 年以来持续的大幅增长。然而,我们可以注意到增长逐年减弱。

以每年的平均增长作为初始参数,过去五年的增长约为新上市公司的 124%。对比过去几年,我们可以看到分析期内最弱的增长。新上市公司的估计数据显示,2016 年新上市公司的数量增长了 26%左右,与前一年(2015 年)相比增长了 157%。

由于我们在数据集中没有关于预订的进一步信息,我们将点评数量和最短住宿时间放在了 2009 年 3 月至 2016 年 9 月期间。这个估计向我们展示了一个保守的结果,因为可能会有更多的预订,客人可能会停留更长的时间。

旺季图表明,7 月至 9 月期间是波士顿市最繁忙的时间,尤其是从 2013 年开始到 2016 年这段时间。峰值出现在 2016 年,达到 9.502 人次,同年平均增长约 49%。

下图展示了 2015 年 10 月和 2016 年 10 月之间的价格变化。每天最高的平均价格也发生在第三季度,价格在 9 月达到高峰,几乎高出 37%,每天 249 美元。

更显著的价格下降发生在 12 月,此时平均价格相对于峰值下降了约 31%,达到每天 199 美元。观察到的最低值出现在第一学期,每天 188 美元。

如“旺季”图所示,可以观察到第三季度的上升趋势和第四季度的下降趋势,此时低需求相应地降低了价格。

房产类型分析

波士顿 Airbnb 提供许多不同的房屋出租。游客可以选择从整个房子或公寓,直到船,露营车或只是一个负担得起的房间。然而,我们将继续关注那些有更多房源、可能有更多需求的房产。

检查数据集,我们可以找到总共 2880 处房产,其中 7%是公寓,16%是住宅,77%是公寓,分布在 23 个街区。

另一个相关信息涉及哪种属性具有对主机和超级主机的偏好。总主机中有 78%的主机拥有公寓甚至是除其他房产外的公寓,65%的超级主机在其他房产中拥有公寓。

从现在开始,我们必须把重点放在公寓礼仪上。

上面的分析向我们展示了每个街区的客人对房间类型的偏好。

大多数寻找公寓的客人都倾向于租用整个地方,从而产生 1528 套公寓,相当于 70%。私人房间是第二个首选,有 605 个单元,占总数的 28%。与之前的选项相差甚远,合租房间只有 2%的人响应偏好,有 38 个单元。

考虑到整个公寓选项,后湾,南端和芬威肯莫尔是更多的单位数量的街区。如果我们考虑所有的租金选择,奥尔斯顿-布莱顿附近出现作为一个新的选择。无论如何,我们可以看到他们中有相当多的人。

上面的重点表格显示了整个公寓的平均价格,包括每个街区的房间数量。

随着房间数量的增加,价格也会上涨,尽管会有一些异常值。我们还可以观察到,随着房间数量和每日价格的增加,公寓报价下降。除此之外,我们可以意识到,几乎每个社区都有两个房间的财产。

以房间数量来比较日均价格,我们可以看到价格平均上涨了 27%左右。尽管如此,最高的价格差异出现在一居室和两居室之间,第二居室要贵 38%。在多切斯特、米申山和罗斯林代尔,可以找到价格低于 100 美元的工作室。另一方面,Back Bay,Beacon Hill,Roxbury,South Boston,South End e 剧院区的价格普遍较高,在 400 美元以上。

分析距离对价格的影响

离市中心的距离对平均价格有很大影响。上面的图表显示了市中心每天的平均价格和距离之间的关系。

数字显示,随着离市区距离的增加,价格会下降。相比之下,如果我们考虑到距离市中心超过 7 公里的地方,每天的平均价格将是 170 美元,而距离市中心不到 1.5 公里的价格平均为 245 美元。

分析下面的图表,我们可以看到距离和入住率之间的关系,其中我们可以看到平均入住率约为 89%,分布在所有街区。

值得注意的是,一些地区的入住率远低于平均水平,尽管一些礼仪是在靠近市中心的街区。由于这些地区的价格较高,游客可能对价格比对距离更敏感。

下一张图探究了入住率、平均价格和每个街区的房产数量之间的关系。正如我们从之前的图表中认识到的,平均价格对入住率的影响比离市中心的距离更大。

对于价格从每天 210 美元到 340 美元的地方,入住率为 85%,略高于距离市中心 2 公里。在一些地方,价格从 138 美元到 200 美元左右不等,相当于 93%的入住率。这些地区距离市中心仅 8 公里多一点。

以房源数量作为参考,我们可以看到市中心附近的公寓相当集中。总共 1528 套公寓中,约 78%位于距离市中心不到 4.1 公里的地方。其余 22%的单元更远,超过 5.7 公里。不出所料,靠近市中心的房产平均价格为 240 美元,远离市中心的为 177 美元。

分析每个街区的评级,我们可以再次注意到,与市中心的物业距离有关的一些联系。

具体检查本地化评级,得分高于 98 分的整个街区(金融区、西区、灯塔山、北端、后湾、南端、芬威/肯莫尔和市中心)中有 39%位于距离市中心不到 4.1 公里的地方。仅分析评分超过 98 分的地方,78%的地方距离中心不到 2 公里。

总体评分和价值评分似乎更受价格的影响。如果我们选择一系列价值和综合评分高于 95 分的最高评分酒店(罗斯林代尔、西罗克斯伯里、海德公园、牙买加平原、查尔斯顿和东波士顿),这些地方的平均价格为每天 180 美元。

最赚钱的领域

结束分析时,我们将带来一些最终图表,向我们展示最有利可图的领域,因此,对可能的投资更感兴趣。

上图显示的是从 2009 年 1 月到 2016 年 9 月按街区划分的总收入。

Back Bay、Fenway/Kenmore 和 South End 的总收入最高,分别为 1360 万美元、1060 万美元和 930 万美元。这些价值的总和占所有社区总收入的 40%。

相比之下,收入第四高的社区南波士顿的总收入为 590 万美元,比第三名的南端少 63%。

上图为我们带来了附近地区的每日收入,根据上图,可以观察到总收入最高的三个地区仍然保持着有趣的定位,尤其是芬威/肯莫尔和后湾。

这三个地区,后湾,芬威/肯莫尔东南端的平均日价格在 222 美元到 307 美元之间。即使是 South End 街区支付的最低值 222 美元,也高于所有街区的平均日收入 214 美元。

在这里,我们可以看到最高的总收入领域支持第一的立场。Back Bay、Fenway/Kenmore e South End 的公寓上市量最高,分别为 220、200 和 180 套。

收集所有三个社区,我们在每个地区拥有整个公寓系列的近 40%,平均每天收费 241 美元。

在每个街区的本地化评级中,我们将 Back Bay、Fenway/Kenmore 和 South End 列为最佳地区评论,从 100 分的最高分中获得 98 分以上的评级。

在总共 23 个地区中,只有 9 个地区得分超过 98 分,只有 5 个地区得分超过 99 分,比如 Back Bay。此外,Back Bay、Fenway/Kenmore 和 South End 距离市中心平均只有 3 公里。

一般结论

  • 在结束分析之前,让我们回顾一下通过这次探索性搜索收集到的主要见解;
  • 第三季度是波士顿市最繁忙的时期。7 月至 9 月也是游览这座城市最贵的时候,价格最高,9 月份几乎达到 31%;
  • 70%的主机和 65%的超级主机有公寓,或在不同的属性,也有公寓;
  • 70%的客人更喜欢租赁整个公寓,而不是房间或合租房间,两室公寓在所有社区范围内的房源数量较多,这表明客人可能更喜欢这类物业;
  • 靠近市中心的街区有最高的每日价格和总收入;
  • 远离市中心的房产每日价格最低。多切斯特、米申山和罗斯林代尔距离市中心 7.7 公里,有 100 美元左右的选择。

最适合主持人的区域

  • Back Bay、Fenway/Kenmore 和 South End 的总收入最高,在 1360 万美元、1060 万美元和 930 万美元之间。
  • Back Bay、Fenway/Kenmore 和 South End 的日均房价加在一起为 270 美元,比所有街区的平均房价高出 25%以上。
  • Back Bay、Fenway/Kenmore 和 South End 的公寓房源也最多,分别为 220、200 和 180 套。
  • Back Bay、Fenway/Kenmore 和 South End 是本地化评级评论中最好的,从 100 分中得到 98 分以上。

希望你喜欢!感谢阅读!

这里 可以访问 用于分析的数据。

使用 PyTorch 从头开始预测包围盒

原文:https://towardsdatascience.com/bounding-box-prediction-from-scratch-using-pytorch-a8525da51ddc?source=collection_archive---------1-----------------------

多任务学习——包围盒回归+图像分类

作者点击的图像

对象检测是计算机视觉中非常流行的任务,其中,给定一幅图像,你预测图像中存在的对象周围的框(通常是矩形),并且还识别对象的类型。你的图像中可能有多个物体,有各种最先进的技术和架构来解决这个问题,如 Faster-RCNN 和 YOLO v3 。

本文讨论了图像中只存在一个感兴趣对象的情况。这里的重点是如何正确地读取图像及其边界框、调整大小和执行放大,而不是模型本身。目标是很好地掌握对象检测背后的基本思想,您可以扩展它以更好地理解更复杂的技术。

这里有一个笔记本的链接,其中包含了我在本文中使用的所有代码:https://jovian . ml/aakanksha-ns/road-signs-bounding-box-prediction

如果你是深度学习或 PyTorch 的新手,或者只是需要复习,这可能会让你感兴趣:

问题陈述

给定由路标组成的图像,预测路标周围的边界框并识别路标的类型。

这些迹象可能属于四个不同的类别:

  • 交通灯
  • 停止
  • 速度限制
  • 人行横道

这被称为多任务学习问题,因为它涉及执行两个任务——1)回归以找到边界框坐标,2)分类以识别路标的类型

样本图像。来源

资料组

我使用了 Kaggle 的路标检测数据集:

[## 路标检测

属于 4 类的 877 个图像。

www.kaggle.com](https://www.kaggle.com/andrewmvd/road-sign-detection)

它由 877 幅图像组成。这是一个非常不平衡的数据集,大多数图像属于speed limit类,但由于我们更关注边界框预测,我们可以忽略这种不平衡。

加载数据

每个图像的注释都存储在单独的XML文件中。我按照以下步骤创建了培训数据框架:

  • 浏览培训目录以获得所有.xml文件的列表。

  • 使用xml.etree.ElementTree解析.xml文件

  • 为每个图像创建一个由filepathwidthheight、边界框坐标(xminxmaxyminymax)和class组成的字典,并将该字典附加到一个列表中。

  • 使用图像统计字典列表创建一个熊猫数据框架。

  • 标签编码class

调整图像大小和边界框

由于训练计算机视觉模型需要图像具有相同的大小,因此我们需要调整图像及其相应的边界框的大小。调整图像的大小很简单,但是调整边界框的大小有点棘手,因为每个框都与图像及其尺寸相关。

以下是调整边界框大小的工作方式:

  • 将边框转换为与其对应的图像大小相同的图像(称为蒙版)。这个遮罩只有背景的0和边界框覆盖的区域的1

原象

边界框的遮罩

  • 将遮罩调整到所需的尺寸。
  • 从调整大小的遮罩中提取边界框坐标。

辅助函数从包围盒中创建遮罩,从遮罩中提取包围盒坐标

函数来调整图像大小,写入新路径,并获取调整后的边界框坐标

数据扩充

数据扩充是一种通过使用现有图像的不同变体创建新的训练图像来更好地概括我们的模型的技术。在我们当前的训练集中,我们只有 800 张图像,因此数据扩充对于确保我们的模型不会过度拟合非常重要。

对于这个问题,我使用了翻转,旋转,中心裁剪和随机裁剪。我在本文中讨论了各种数据扩充技术:

[## 计算机视觉的图像处理技术

图像处理是计算机视觉的一个组成部分。我们几乎总是想调整图像大小,增加数据…

towardsdatascience.com](/image-processing-techniques-for-computer-vision-11f92f511e21)

这里唯一要记住的是确保边界框也以和图像相同的方式变换。为此,我们遵循与调整大小相同的方法—将边界框转换为遮罩,将与原始图像相同的变换应用于遮罩,并提取边界框坐标。

辅助函数用于居中裁剪和随机裁剪图像

变换图像和遮罩

显示边界框

PyTorch 数据集

现在我们已经有了数据扩充,我们可以进行训练验证分割并创建 PyTorch 数据集。我们使用 ImageNet stats 标准化图像,因为我们使用预训练的 ResNet 模型,并在训练时在我们的数据集中应用数据扩充。

列车有效分离

创建训练和有效数据集

设置批处理大小和创建数据加载器

PyTorch 模型

对于这个模型,我使用了一个非常简单的预训练 resNet-34 模型。因为我们在这里有两个任务要完成,所以有两个最后的层——边界框回归器和图像分类器。

培养

对于损失,我们需要考虑分类损失和包围盒回归损失,因此我们使用交叉熵和 L1 损失(真实值和预测坐标之间的所有绝对差的总和)的组合。我用因子 1000 来衡量 L1 损失,因为分类和回归损失都在相似的范围内。除此之外,这是一个标准的 PyTorch 训练循环(使用 GPU):

对测试图像的预测

既然我们已经完成了训练,我们可以选择一个随机的图像并在上面测试我们的模型。即使我们有相当少量的训练图像,我们最终在测试图像上获得了相当不错的预测。

这将是一个有趣的练习,用你的手机拍一张真实的照片,并测试模型。另一个有趣的实验是不执行任何数据扩充,训练模型并比较两个模型。

结论

既然我们已经介绍了对象检测的基本原理,并从头开始实现了它,您可以将这些想法扩展到多对象的情况,并尝试更复杂的模型,如 RCNN 和 YOLO!此外,查看这个名为albuminations的超酷库,轻松执行数据扩充。

参考

  • 旧金山大学数据科学硕士项目的深度学习夏季选修课
  • https://www . usfca . edu/data-institute/certificates/fundamentals-deep-learning

票房收入分析和可视化

原文:https://towardsdatascience.com/box-office-revenue-analysis-and-visualization-ce5b81a636d7?source=collection_archive---------40-----------------------

克里斯特·卢哈尔斯在 Unsplash 上的照片

数据科学 100 天的第 4 天和第 5 天

欢迎回到我的 100 天数据科学挑战之旅。在第 4 天和第 5 天,我在处理在 Kaggle 上可用的 TMDB 票房预测数据集。

我将首先导入一些我们在这个任务中需要的有用的库。

import pandas as pd

*# for visualizations*
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
plt.style.use('dark_background')

数据加载和探索

一旦你从 Kaggle 下载了数据,你将有 3 个文件。因为这是一个预测竞赛,所以您有训练、测试和 sample_submission 文件。对于这个项目,我的动机只是进行数据分析和可视化。我将忽略 test.csv 和 sample_submission.csv 文件。

让我们使用 pandas 加载数据帧中的 train.csv。

%time train = pd.read_csv('./data/tmdb-box-office-prediction/train.csv')# output
CPU times: user 258 ms, sys: 132 ms, total: 389 ms
Wall time: 403 ms

关于数据集:

id: Integer unique id of each moviebelongs_to_collection: Contains the TMDB Id, Name, Movie Poster, and Backdrop URL of a movie in JSON format.budget: Budget of a movie in dollars. Some row contains 0 values, which mean unknown.genres: Contains all the Genres Name & TMDB Id in JSON Format.homepage: Contains the official URL of a movie.imdb_id: IMDB id of a movie (string).original_language: Two-digit code of the original language, in which the movie was made.original_title: The original title of a movie in original_language.overview: Brief description of the movie.popularity: Popularity of the movie.poster_path: Poster path of a movie. You can see full poster image by adding URL after this link → [https://image.tmdb.org/t/p/original/](https://image.tmdb.org/t/p/original/)production_companies: All production company name and TMDB id in JSON format of a movie.production_countries: Two-digit code and the full name of the production company in JSON format.release_date: The release date of a movie in mm/dd/yy format.runtime: Total runtime of a movie in minutes (Integer).spoken_languages: Two-digit code and the full name of the spoken language.status: Is the movie released or rumored?tagline: Tagline of a movietitle: English title of a movieKeywords: TMDB Id and name of all the keywords in JSON format.cast: All cast TMDB id, name, character name, gender (1 = Female, 2 = Male) in JSON formatcrew: Name, TMDB id, profile path of various kind of crew members job like Director, Writer, Art, Sound, etc.revenue: Total revenue earned by a movie in dollars.

让我们看一下样本数据。

train.head()

正如我们可以看到的,一些特性有字典,因此我现在删除所有这样的列。

train = train.drop(['belongs_to_collection', 'genres', 'crew',
'cast', 'Keywords', 'spoken_languages', 'production_companies', 'production_countries', 'tagline','overview','homepage'], axis=1)

现在是时候看看统计数据了。

print("Shape of data is ")
train.shape# OutputShape of data is
(3000, 12)

数据帧信息。

train.info()# Output
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3000 entries, 0 to 2999
Data columns (total 12 columns):
 #   Column             Non-Null Count  Dtype  
---  ------             --------------  -----  
 0   id                 3000 non-null   int64  
 1   budget             3000 non-null   int64  
 2   imdb_id            3000 non-null   object 
 3   original_language  3000 non-null   object 
 4   original_title     3000 non-null   object 
 5   popularity         3000 non-null   float64
 6   poster_path        2999 non-null   object 
 7   release_date       3000 non-null   object 
 8   runtime            2998 non-null   float64
 9   status             3000 non-null   object 
 10  title              3000 non-null   object 
 11  revenue            3000 non-null   int64  
dtypes: float64(2), int64(3), object(7)
memory usage: 281.4+ KB

描述数据帧。

train.describe()

让我们为发布工作日、日期、月份和年份创建新的列。

train['release_date'] = pd.to_datetime(train['release_date'], infer_datetime_format=True)train['release_day'] = train['release_date'].apply(lambda t: t.day)train['release_weekday'] = train['release_date'].apply(lambda t: t.weekday())train['release_month'] = train['release_date'].apply(lambda t: t.month)

train['release_year'] = train['release_date'].apply(lambda t: t.year if t.year < 2018 else t.year -100)

数据分析和可视化

照片由艾萨克·史密斯在 Unsplash 上拍摄

问题 1:哪部电影的收入最高?

train[train['revenue'] == train['revenue'].max()]
train[['id','title','budget','revenue']].sort_values(['revenue'], ascending=False).head(10).style.background_gradient(subset='revenue', cmap='BuGn')# Please note that output has a gradient style, but in a medium, it is not possible to show.

《复仇者联盟》电影的收入最高。

问题 2:哪部电影的预算最高?

train[train['budget'] == train['budget'].max()]
train[['id','title','budget', 'revenue']].sort_values(['budget'], ascending=False).head(10).style.background_gradient(subset=['budget', 'revenue'], cmap='PuBu')

《加勒比海盗:惊涛骇浪》是最昂贵的电影。

问题 3:哪部电影是最长的电影?

train[train['runtime'] == train['runtime'].max()]
plt.hist(train['runtime'].fillna(0) / 60, bins=40);
plt.title('Distribution of length of film in hours', fontsize=16, color='white');
plt.xlabel('Duration of Movie in Hours')
plt.ylabel('Number of Movies')

train[['id','title','runtime', 'budget', 'revenue']].sort_values(['runtime'],ascending=False).head(10).style.background_gradient(subset=['runtime','budget','revenue'], cmap='YlGn')

卡洛斯是最长的电影,338 分钟(5 小时 38 分钟)的运行时间。

问题 4:大部分电影在哪一年上映?

plt.figure(figsize=(20,12))
edgecolor=(0,0,0),
sns.countplot(train['release_year'].sort_values(), palette = "Dark2", edgecolor=(0,0,0))
plt.title("Movie Release count by Year",fontsize=20)
plt.xlabel('Release Year')
plt.ylabel('Number of Movies Release')
plt.xticks(fontsize=12,rotation=90)
plt.show()

train['release_year'].value_counts().head()# Output2013    141
2015    128
2010    126
2016    125
2012    125
Name: release_year, dtype: int64

2013 年共有 141 部电影上映。

问题 5:人气最高和最低的电影。

最受欢迎电影:

train[train['popularity']==train['popularity'].max()][['original_title','popularity','release_date','revenue']]

最不受欢迎的电影:

train[train['popularity']==train['popularity'].min()][['original_title','popularity','release_date','revenue']]

让我们创建流行分布图。

plt.figure(figsize=(20,12))
edgecolor=(0,0,0),
sns.distplot(train['popularity'], kde=False)
plt.title("Movie Popularity Count",fontsize=20)
plt.xlabel('Popularity')
plt.ylabel('Count')
plt.xticks(fontsize=12,rotation=90)
plt.show()

神奇女侠电影具有最高的受欢迎度 294.33,而大牌电影具有最低的受欢迎度 0。

问题 6:1921-2017 年大部分电影在哪个月上映?

plt.figure(figsize=(20,12))
edgecolor=(0,0,0),
sns.countplot(train['release_month'].sort_values(), palette = "Dark2", edgecolor=(0,0,0))
plt.title("Movie Release count by Month",fontsize=20)
plt.xlabel('Release Month')
plt.ylabel('Number of Movies Release')
plt.xticks(fontsize=12)
plt.show()

train['release_month'].value_counts()# Output
9     362
10    307
12    263
8     256
4     245
3     238
6     237
2     226
5     224
11    221
1     212
7     209
Name: release_month, dtype: int64

大多数电影在九月上映,大约是 362 部。

问题 7:大多数电影在哪个月的哪一天上映?

plt.figure(figsize=(20,12))
edgecolor=(0,0,0),
sns.countplot(train['release_day'].sort_values(), palette = "Dark2", edgecolor=(0,0,0))
plt.title("Movie Release count by Day of Month",fontsize=20)
plt.xlabel('Release Day')
plt.ylabel('Number of Movies Release')
plt.xticks(fontsize=12)
plt.show()

train['release_day'].value_counts().head()#Output
1     152
15    126
12    122
7     110
6     107
Name: release_day, dtype: int64

第一次约会上映的电影数量最多,152 部。

问题 8:大多数电影在一周的哪一天上映?

plt.figure(figsize=(20,12))
sns.countplot(train['release_weekday'].sort_values(), palette='Dark2')
loc = np.array(range(len(train['release_weekday'].unique())))
day_labels = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
plt.xlabel('Release Day of Week')
plt.ylabel('Number of Movies Release')
plt.xticks(loc, day_labels, fontsize=12)
plt.show()

train['release_weekday'].value_counts()# Output
4    1334
3     609
2     449
1     196
5     158
0     135
6     119
Name: release_weekday, dtype: int64

周五上映的电影数量最高。

最后的话

我希望这篇文章对你有帮助。我尝试用数据科学来回答几个问题。还有很多问题要问。现在,明天我将转向另一个数据集。所有数据分析和可视化的代码都可以在这个 GitHub 库或者 Kaggle 内核中找到。

感谢阅读。

我感谢任何反馈。

100 天的数据科学进步

[## 用熊猫分析和可视化 1955 年至 2020 年的乡村人口

100 天数据科学的第 1、2、3 天。

towardsdatascience.com](/analysing-and-visualising-the-country-wise-population-from-1955-to-2020-with-pandas-matplotlib-70b3614eed6b)

如果你喜欢我的工作并想支持我,我会非常感谢你在我的社交媒体频道上关注我:

  • 支持我的最好方式就是在 关注我。
  • 订阅我的新 YouTube 频道
  • 在我的 邮箱列表 报名。

异常检测的箱线图

原文:https://towardsdatascience.com/boxplot-for-anomaly-detection-9eac783382fd?source=collection_archive---------15-----------------------

照片由晨酿在 Unsplash 拍摄

小型数据科学

在上一篇文章中,我写了关于使用简单的统计技术 Z-score 检测异常值的文章。虽然这是一种创建筛选异常值的过滤器的简单方法,但还有一种更好的方法——使用箱线图。

箱线图是理解单变量和分类数据的分布、离散和变化的极好的统计技术——所有这些都在一个图中。

本文的目的是介绍 boxplot 作为异常值检测工具,我主要关注以下几个方面:

  • 箱线图背后的统计直觉
  • 如何在异常值检测中使用它们
  • 一点点编程

箱线图:一种直觉

箱线图是可视化数据相对于中心值的分布的有效工具。我真的不认为你需要了解很多细节,但下面是一个简单的描述,给一点它如何在引擎盖下工作的直觉。如果你没有 100%得到,也不要难过。

一张图胜过千言万语,所以不要用文字来描述这个概念,只需自上而下地看一下下图,就可以建立自己的直觉。这一切都始于一个由七个观察值组成的小数据集:1,6,5,4,4,7,8。

如果把数据从小到大重新排列,中点就是中位数。中位数将数据分成两半。每一半的中点称为“四分位数”。因此,我们得到两个四分位数,第一个四分位数是上半年的中点,第三个四分位数是下半年的中点。当您从顶部开始执行这些步骤时,在图的最后部分,您会看到一个箱线图及其包含的数据。

从统计学上来说,箱线图提供了几条信息,其中两个重要的信息是四分位数,由箱线图的两端表示。这两个四分位数之间的距离称为四分位数间距(IQR)。

在下面的盒状图中,盒子的长度是 IQR,最小和最大值由胡须表示。胡须通常延伸到盒子两侧的 1.5IQR 距离。因此,这些 1.5IQR 值之外的所有数据点都被标记为异常值。

与箱线图和异常值位置相关的统计概念

如果你有正确的直觉,理解一个“离群值”是如何发挥作用的并不困难。查看下图。

通常,最小值和最大值之外的任何数据点(由框两端的胡须表示)都被视为异常值。

Python 中的示例

同样,如果你没有 100%理解统计概念,不要生气。我们可以在不了解很多机械原理的情况下驾驶汽车。但是我们必须知道如何开车!

就像知道如何开车一样,理解如何实现一个算法是业务中最重要的部分。下面是用 Python 构建编程直觉的一小段代码。

# import libraries
import numpy as np
import seaborn as sns
sns.set_style("whitegrid")# data
data = [1, 4, 4, 5, 6, 7, 8, 13]# create boxplot
sns.boxplot(y = data)

正如你所看到的,在这个箱线图中有一个异常值非常明显,我们可以很容易地过滤掉它。我们不知道异常值的确切值,但我们知道它大于 12。因此,让我们过滤那些异常值。

# filter outliers 
outliers = [i for i in data if i > 12]print("Outliers are: ", outliers)

现在,箱线图将 13 检测为数据集中的异常值。这个异常值是否是一个异常,这当然是一个不同的问题,只能使用领域知识和其他技术单独回答。

结论

本文的目的是给出 boxplot 背后的统计直觉,并通过一点编程示例演示它是如何工作的。箱线图的强大之处在于,您可以“看到”极值,并通过直观的解释来决定异常值的阈值。这里的演示基于单变量数据,但对于多变量数据集和分类值,它也可以以类似的方式工作。

如果你喜欢这篇文章,请随时在媒体或推特上关注我。

脑机接口——魔法师时代

原文:https://towardsdatascience.com/brain-machine-interfaces-the-sorcerer-era-b19c2d5b6200?source=collection_archive---------76-----------------------

随着脑机接口在社会上的实现和商业化整合,不可能的事情很快就会变成可能——准备好称自己为巫师吧。

图片通过 pixabay

正如我在的上一篇文章中所讨论的那样,在我们人类大脑中集成计算机很可能在不久的或遥远的将来成为现实。如果这还不足以让你相信这项技术已经被讨论和研究了(查看 Neuralink 和 NextMind ),那么让我们采取一种直观的、历史的方法。人类交流的历史始于公元前 500,000 年的语言起源。大约 30,000 年前,符号的发明彻底改变了交流。大约 20,000 年前,第一批岩画被创造出来,不久之后表意文字和象形文字随之而来。然后又过了几千年,书面语言才成为现实。快进到几个世纪前,接下来出现了电、电报和留声机。不久之后,电话和移动电话出现了——现在你可以通过拇指与世界上的任何人保持全天候的联系。这些发展表明,通信在各个领域都得到了越来越多的改善——可访问性、易用性、可靠性和效率。我们如何才能提高更多?免提和无语音通信——脑对脑通信。这似乎是不可避免的。

对于这篇文章的其余部分,拿一杯水,沉浸在想象中。

最终,人们只能幻想戴上这种脑机接口设备后,我们的生活会有多大的改善。最终,就像移动电话一样,这项技术将如此融入我们的生活,以至于它几乎就像是我们人体的延伸。大多数人没有意识到的一件重要事情是,每个人本质上都已经是一个电子人。我们的手机一直握在手中,电脑触手可及,它们就像是我们身体和自我的一部分。我们的沟通将如何改善?在技术层面:

  • 交流的速度会加快。为了将一个想法传递给另一个人,一个人必须将这个想法压缩成可解释的东西,然后压缩并重新组织成语言,然后通过他们选择的媒介(演讲、书面语言、文本)来翻译它。跳过这一切,直接分享想法,脑对脑。
  • 通信带宽会增加。与其浪费时间用文字和图片来交流思想和观点,不如直接分享想法并立刻描绘出整个画面。
  • 通信的准确性将是极好的。当前交流的一个典型的准确性障碍是语言障碍。忘记学习另一种复杂的语言,努力完善它的复杂性,只是分享你的想法或想法。此外,通过使用脑机接口,你可能真的能够“设身处地为他人着想”。

目前,脑机接口应用于认知或身体残疾的患者。这里有几个如何使用它的例子:

  • 腰部以下瘫痪的患者可以利用脑机接口向有缺陷的身体部位发送刺激,最终能够再次行走。就像婴儿学习如何移动手指一样,身体残疾的病人可以重新学习如何重新激活受损的身体部位。
  • 患有痴呆症的老年妇女可能能够修复她的神经退化,增强她的记忆,以记住她的孙子孙女。同样,患有神经疾病的患者将有机会获得神经增强,甚至刺激神经再生,以提高他们的思维能力。这尤其与经常经历神经退化的老年人相关。
  • 通过使用脑机接口重新连接神经功能或屏蔽某些记忆,给受试者带来戏剧性应激障碍后的创伤经历可能能够神奇地忘记经历。

但是,正如上一篇文章所提到的,未来脑机接口的使用不会只延伸到认知或身体残疾的人。正如第一台计算机被设计用来计算火炮射表一样,它们被证明对无数的任务和需求都是有用的。这里是不可能变成可能的地方。

用意念控制实物:

图片来自 pixabay

首先,随着脑机接口成为一种社会规范,我们目前使用的许多设备(如果不是全部的话)可能有一天会连接到接口。以下是一些简单的脑机接口使用场景:

  • 你早上醒来,闹钟响着‘醒醒!’你用意念让时钟在一瞬间关闭。糟糕…外面还是一片漆黑。想象一下灯打开了,加热器开始温暖房间,咖啡壶加热到想要的温度——继续想象一下,在你跳进去之前,淋浴器打开了。你吃了一顿健康的早餐,边喝咖啡边发邮件(用心地)。工作时间到了——告诉界面锁门关灯。走出家门,你就在上班的路上了。
  • 你现在正开车去上班,但一些迷人的东西偷走了你的注意力。你就要撞上另一辆车了——用你的思维在瞬间改变方向。你刚刚用你的思想避免了一场车祸,避免了将危险的想法转化为实际行动所需的处理时间。
  • 不要用手操作危险的机器(如伐木机),直接用头脑操作。“思想到行动”技术的安全含义是巨大的。
  • 吉他弹得很差?用你的思想去演奏它。音乐创作不仅仅是由想法决定的——它需要身心的联系来将想法转化为声音。任何人都可以成为自己的艺术家,通过脑机接口,创造力将得到极大的增强。

储存

图片来自 pixabay

如前所述,我们储存信息的能力对我们学习、成就和进步的方式有着深远的影响。以下是一些例子:

  • 当你小睡一会儿的时候,写下你一直想开始写的文章。一旦你睡着了,你所有的编辑和更新都会以类似 Google Drive 的方式保存下来——全部保存在云上。
  • 我们的大脑受限于储存信息的能力。想学习多门课程,但对需要记忆和学习的大量信息感到气馁?通过云端记录下来,交错在你的界面里。你想获得以后开发的信息和技能——进入界面,让它实时地用你想要的信息和技能替换不相关的信息和技能。只要有时间和毅力,任何人都可以成为 博学
  • 这就是可怕的地方。在前面的示例中,存储委托给了一个人。但是如果社会可以集体储存然后分享它的经验和知识会怎么样呢?每个人都可以访问(如果不是所有的东西,肯定是很多)。一个集体建造、清洗和改良的大脑。

安全:

图片来自 pixabay

这项技术的安全含义令人震惊。下面是一些基本的例子:

  • 八月下旬,你的车在亚利桑那州中部抛锚了。气温超过了华氏 115 度。你手机没电了,你没水了,很可能很长时间都不会有其他人开车经过。使用你的界面拨打紧急求助电话,自救。
  • 采石场工人刚刚经历了一场事故。其中一名工人不小心将一块沉重的花岗岩石头掉在了他们的一条腿上,无法触及他们的无线电——他可以向他的同事发送紧急信息,告知他的位置和状况。
  • 一天晚上,天很黑,你在未铺砌的人行道上摔倒,不省人事,没有明显的呼救方式——界面正在跟踪你的神经状况,并向当地当局发出警报。你能活到明天。

心与心的交流:

图像通过 pixabay

心灵对心灵的交流——换句话说,心灵感应。人与人之间直接分享思想和观点的能力似乎是不可能的。脑机接口使这成为现实,极大地改善了我们交谈、合作和努力实现共同目标的方式。如果进步像乌龟一样移动,它现在可以像猎豹一样移动。

  • 向某人解释一个困难的概念变得容易多了。当一个人参与关于抽象或概念性想法的对话时,通常很难将这些想法转化为另一方可以理解的语言。直接分享复杂的想法和想法,而无需将它们复杂而困难地翻译成语言。
  • 小组会议看起来会有很大不同。“头脑风暴”将有一个新的、更直观的含义。人们将能够更有效、更准确地分享问题、想法和解决方案。更好的协作,更多的创新——进步。
  • 你在疫情——法律强制要求你呆在家里,不见任何人。没问题—与您所爱的人连接到云,进行正常的对话。
  • 你和你的朋友在一起。他们讨厌你发短信告诉你不要打电话。不能再发短信了?用你的思想给某人发送信息或想法。进行充分的交谈,没有打字的负担,也不会因为某人“老是打电话”而让他生气。

感官和情感交流:

图片来自 pixabay

这种类型的交流通常是最困难的。有人可能会说他们知道你在某个时刻的感受,但他们通常无法直接体验到。

如果之前事情看起来很不稳定,你就要被骗了。

有哪些脑机接口可以彻底改变这种交流方式的例子?

  • 你没有时间和你的朋友去海滩,因为你必须完成那个项目。你确实有 30 分钟的休息时间,所以你利用你朋友的感官输入,通过她来替代生活。你可以闻到海浪撞击的盐味,感受到温暖的沙滩,听到放松的音乐。享受“海滩日”的新方式。
  • 全国爆发了大规模抗议活动。抗议者要求所有种族之间的平等权利——虽然你在历史上被认为存在于特权群体中,但你可以挖掘那些破碎和痛苦的人的感觉,以了解那些需要帮助的人的观点。一个因同理心而强化的新世界。
  • 错过了你想去的音乐会?也许你仍然可以购买数字门票,让自己沉浸在真实的体验中——听声音、感受人群、可视化等等。
  • 付费观看湖人对凯尔特人的比赛。观看勒布朗詹姆斯在杰森·塔图姆上空的三分投篮。
  • 还记得《T4》黑镜集里那个可以直接体验病人症状的医生吗?在那集里,他可以很容易地诊断出病人的问题,即使他自己也能体验到症状。没错。

我想你明白了。可能性和潜力的清单是不可思议的。

为什么这很重要?

脑机接口在人类智能和机器智能之间架起了一座桥梁。随着人工智能日益融入社会,我们最终可能会融合成一个电子人,并利用技术为我们服务,这似乎是相当自然的。那么,为什么不把这项技术直接集成到我们的大脑中呢?通信方法和技术的历史发展清楚地表明,下一步是脑对脑的通信——在不久的将来,我们可能会体验到它的超能力。

BrainOS——最像大脑的人工智能

原文:https://towardsdatascience.com/brainos-the-most-brain-like-ai-61b334c7658b?source=collection_archive---------48-----------------------

应用神经科学实现更高效、更智能的人工智能。

娜塔莎·康奈尔在 Unsplash 上的照片

我们的大脑是生物神经网络。通过大数据、大计算和机器学习算法,我们可以创建非常接近真实交易的人工神经网络。

例如,革命性的 GPT-3 模型可以写文章欺骗 88%的读者认为它是人类,它可以写代码、诗歌、歌词、模因,等等。

然而,我们仍然没有达到开启超级智能的“光开关时刻”——也看不到它。

照片由伊瓦洛·乔尔杰夫拍摄,来自自由影像

神经科学可以提高人工智能

这是 BrainOS(一种新颖的类脑 AutoML 框架)所基于的前提。原因很简单:我们的大脑是已知最强大的处理器,因此我们至少应该测试我们的大脑(看起来)为 AI 的运行而运行的原理。

作为效率的题外话,让我们比较一下大脑和人工智能。毕竟,大脑是我们衡量人工智能准确性的基准,所以让我们粗略地看一下效率。

大脑每天消耗 300 卡路里。在特斯拉 V100 上训练 GPT-3 需要花费 355 年(310 万小时),特斯拉 V100 单独消耗 300 瓦。乘以瓦特/小时乘以训练小时总数得到 933 兆瓦。这等于 8020 亿卡路里。

NVIDIA 估计人工智能 80–90%的能源成本在于推理——在训练后使用模型。仅计算 GPU 成本,GPT-3 的成本高达 7.2 万亿卡路里。

哎哟。

BrainOS 目前还没有用于生产(我们稍后会提出建议),但目前有一些提高效率的尝试。

首先,脉冲神经网络是一种类似大脑的提高效率的方式,但它们不能提供 BrainOS 将带来的与 AutoML 相同的好处。

[## 脉冲神经网络——一种更像大脑的人工智能

神经网络是用来识别模式的大脑的简化模型,但是它们浪费了大量的计算…

medium.com](https://medium.com/bitgrit-data-science-publication/spiking-neural-networks-a-more-brain-like-ai-6f7ad86b7e7e)

虽然 BrainOS 仍然是一个研究项目,但有许多功能性的 AutoML 工具,如 Apteo 。有关 AutoML 的更多信息,请查看本指南:

[## AutoML 会是数据科学家的末日吗?

AutoML 越来越受欢迎。这就是事情的变化。

towardsdatascience.com](/will-automl-be-the-end-of-data-scientists-9af3e63990e0)

BrainOS 如何工作

BrainOS 通过以下属性自动选择合适的 ML 模型:

  • 它给出的数据
  • 先前的经验
  • 世界知识

BrainOS 不仅仅与我们对大脑如何工作的想法有着松散的联系,它还试图对神经元行为进行建模。

"该系统的结构和操作受到神经元细胞行为的启发."

体系结构

高层架构非常简单:输入数据(来自任何来源)与问题上下文和目标相结合。鉴于此,要么创建一个新模型,要么选择一个现有模型进行训练,然后部署该模型。

高级 BrainOS 架构。作者可视化。

详细组件

问题形式化是系统的切入点,包括上面的“输入数据”框。接下来,critic(或 qualifier)组件通过添加早日期数据集来增强输入数据,并通过应用资格来实现中间数据。

受大脑自适应学习特性的启发,历史数据库结合了历史(或遇到的数据集的经验)和世界知识(或存储的知识以及抽象研究)。

规划器组件简单地规划算法的执行顺序,或者系统的流程。并行执行器是任务调度器,它决定如何高效地执行线程。

模块调度器接收由上述并行执行器发送的线程,计划执行时间表。

选择器是 BrainOS 的关键组件,它通过并行执行许多步骤来挑选出正确的模型:搜索 BrainOS 的历史,搜索研究数据集,从头开始构建工具,并通过组合几个模型来执行集成学习。然后选择最适合的模型。

深度认知神经网络(DCNN) —实现 BrainOS

DCNNs 是在现实世界中实现 BrainOS 的一种方案。

与典型的神经网络不同,DCNNs 表现出感知和推理能力,并能够在小型设备(如智能手机)上进行近实时的大数据分析。此外,它们的能效极高,比类似的深度神经网络高出 300 倍。

市场上还没有任何基于 DCNN 的 AutoML,但鉴于传统深度网络对计算、数据和能源的极高要求,我相信我们很快就会看到它们。

打破障碍,成为一名宝贵的数据科学家

原文:https://towardsdatascience.com/break-the-barrier-to-become-an-invaluable-data-scientist-4cd9bbbefdd1?source=collection_archive---------25-----------------------

一个有价值的数据科学家长什么样?建议以最有效的方式开始你的数据科学生涯。

来源:默特萨洛夫

H

这是一个很常见的抱怨,我从我的朋友、同事,尤其是年轻人那里听到了很多次。几年前,在我职业生涯的初期,我也是这个陷阱的受害者。现在,我意识到这是数据科学家的一个真正的瓶颈,我想与他人分享我的经验,以便帮助其他数据科学家实现更光明的职业生涯。

每当我遇到其他数据科学研究员,大部分时间都花在谈论 RNN、NLP、深度学习或机器学习算法上。但是当我问他们为什么使用 RNN 而不是深度学习,或者他们的模型如何支持业务时,他们要么提供一个没有说服力的理由,要么停留在对概念和算法的冗长解释上,而没有全面的商业思维。

对于数据科学家来说,饱和于技术模型而低估商业思维的作用是一种惯例。然而,我完全不否认数据科学家的技术工作的不可或缺的作用,我只是想强调在任何其他活动 之前,首先 理解业务概念的重要性。

因此,我在下面列出了开始数据科学项目的标准流程和关键点,这是我作为数据分析师和数据科学家在两家跨国公司工作的 4 年中一直在应用的。

这篇文章是根据我的经历写的。因此,把它作为你的参考,并根据自己的需要进行调整。

1.首先也是最重要的一点——澄清业务问题

在我从事分析和数据科学的这些年里,除了技术概念解释,业务问题澄清是数据科学家与业务合作伙伴沟通时最困难的任务之一。

我相信你在很多文章里都能听到这句话,提醒你在任何情况下都要澄清商业问题。

但是怎么做呢?

工作和研究是不同的。在商界,高层人士从未停止期待数据科学家成为一个知道他们所有问题答案的智者。因此,挖掘问题是我们的工作,如何去做是我们的责任。

当一个销售经理问你“我想知道为什么销售额下降了”的时候,你一定非常熟悉。或者一位营销总监要求“如何提高品牌 A 在我们网站上的促销活动的效率?”

当你听到这些问题时,你是如何想象解决方法或答案的?你会不会不确定,一直问自己“是他们想让我这么做吗……”还是“我想他们想知道那个……”?如果你基于这种理解来交付成果,你对自己的交付有多少信心?

事实上,如果你一直这样,你将从他们那里得到的唯一回应是:

“这不是我需要的”

OMG!当你花了这么多心血在这上面,却没有人重视,这是多么可怕。

这是因为你没有真正理解问题,所以没有触及痛点!

例如,主管想知道提高其营销活动功效的方法,那么功效在这里是什么意思?他指的是哪种活动?真正的痛点是什么?如果清楚地阐明这些问题,该请求将被解释为“如何优化在线推广的预算支出,以提高购买率和新客户数,与去年相比”。这最终会增加疗效。

一个常见的建议是问 【为什么】 以便挖掘真正的问题。但是,这种解决方案并不总是适用的,因为业务合作伙伴可能不知道您所有问题的原因。

你还能做些什么:

  1. 询问问题的背景,在你收到请求后,他们为什么以及如何提出请求。
  2. 确定你有责任回答这个请求。如果你的公司有数据科学家、数据分析师、BI 等几个数据团队,一定要搞清楚每个团队的角色&职责,知道什么时候跳进去,什么时候跳出来。然而,永远不要说“这不是我的工作。问毕”。相反,向他们展示你对公司和数据了如指掌“根据你的要求,BI 团队已经获得了可以帮助你解决问题的数据,我建议你与 BI 会面,并索要过去 3 年的销售和流失率数据”
  3. 与公司的其他团队合作,经常获得公司内部发生的其他事情的最新消息。此外,始终提出诸如“最新的公司战略、日程表、当前的关键项目和最近的业绩是什么?”这样的问题也是非常重要的“我是否了解对我的公司至关重要的项目的愿景和目标?”
  4. 想出一些计划,以及在你的专业知识范围内你还能做些什么来将项目提升到一个新的水平。

做一个思想家,而不是一个实干家!

2.确定解决问题的方法

这一部分是为分析提供方法论。

这一步需要对统计模型机器学习方法有广泛的了解。在一些公司,尤其是非技术通,数据科学家负责分析和数据科学工作流。

随着分析和数据科学的混合作用,解决问题的方法也将随着各种概念和模型而多样化。例如:线性回归不能用于细分客户,或者描述性分析不能预测客户流失。

起初,选择方法似乎毫不费力,但确实总是让你抓狂。如果销售总监要求数据科学团队根据预算支出金额预测下一年的 销售额,同时将在线外观作为公司的重点 ,那么应该使用哪种方法/模型?如果企业希望基于市场运动的预测 能够维持当前公司的领导地位 ,哪种方法是正确的?

您可以做得更多:

  1. 理解描述性分析预测性分析 之间的差异是的基础(很多人仍然对这两个概念不清楚)。描述性分析的一个例子是因素之间的关系;而规定性分析则处理计算这种关系的未来结果。描述性分析提供历史洞察力,而规定性分析预见未来价值。
  2. 确定数据的具体类型以帮助解决问题 : 目标变量和其他变量是连续的、分类的或二元的。
  3. 了解关键问题的方法:
  • 二元 (2 种可能答案)或多类(2 种以上可能答案)分类
  • 回归关系(2 个或 2 个以上因素之间的关系)或回归预测(利用回归模型预测未来值);
  • 聚类(将未标记的观察值聚类成具有相似特征的组)或分割(将观察值分成特定的组);
  • 趋势检测(历史运动)或时间序列预测(预测该运动的未来值)。

3.获取适当的数据

在确定了业务问题和上述方法之后,接下来的事情就是建立数据需求并从数据仓库中提取适当的数据。

数据选择听起来很简单,但确实很复杂。为了解决业务问题,需要哪种数据。比如预测流失概率的任务,有没有必要有客户的生日信息?

摄取足够的数据将会为您节省大量的精力。记住一个不言而喻的事实:垃圾进来就是垃圾出去

在数据收集过程中通常会出现两个主要问题

1.数据的不可用性
2。训练数据的偏差

3.1 首先,我们来看看数据不可用

这个问题在全球非常普遍,由于当前数字连接的限制,数据无法在收集时获取。例如,仅仅是不可能获得在家做饭的时间

作为一个常识,当数据不存在时,你会立刻想到获取数据的方法。但是,您必须考虑不可用数据的后果,包括成本、时间、资源,如果数据对您的模型确实不太重要,您投入的所有努力都将付诸东流。

因此,这种情况的解决方案是暂时推迟不可访问的数据,如果模型需要这些数据以获得更好的结果,您将有更多的资源和信心在未来投资获取这些数据。

如果需要更多数据,您还可以做些什么:

  1. 拜访数据库所有者时,如果您需要就此与其他方沟通,请携带一份数据请求摘要。总结形式应该包括你的项目背景,数据要求,你的要求。这将有助于顺利讨论,业务合作伙伴将给出适当的解决方案。
  2. 改变收集数据的过程/方法以获取所需的正确信息。与数据库所有者或 IT 团队合作,或向您的上级提出系统修订计划以供批准。
  3. 准备预算,如果额外数据对改进模型至关重要且您无法获得,请联系外部数据所有者

3.2 第二,数据的偏差

当训练集从一开始就有偏差时,这个问题尤其严重。因此,模型将根据偏差进行学习,并在与真实世界进行比较时返回不准确的预测 。

数据偏见最著名的缺陷之一是亚马逊招聘人工智能工具显示了对女性的偏见。该工具审查候选人的简历,以便从中挑选出最优秀的人才。该工具显示出对女性的明显偏见,因为它的训练数据从一开始就不是性别中立的。

因此,首先,小心数据及其自然分布是每个数据科学家的重要职责。

你可以做些什么来消除偏见:

  1. 确保数据及其代表在人口中的统计分布。例如,如果人口由 56%的男性和 43%的女性以及 1%的其他人组成,则数据分布必须具有相似的比例。
  2. 验证训练的分割,验证和测试预测模型中的集合以建立类似的变量和类别分配。
  3. 选择适合问题的学习模型,降低偏度。一些模型可以减少数据中的偏差,包括聚类或降维
  4. 监控实际数据中的性能。经常对真实数据进行统计测试,以找出不常见的情况。如果测试结果显示男性的流失率比女性高,那就把它挖出来。是突然转变还是偏差的结果?

获得所需的所有数据后,下一步是数据科学家通常会做的事情:

顺序可以是灵活的,这是我在项目和工作中通常采用的标准进度。有时,在调优后,精度没有达到我的期望,我会回到特性工程步骤,寻找其他方法来处理特性。

这些是除了技术技能之外的关键瓶颈,我希望数据科学家能够超越数据洞察提取器。

分解 R 中的地理编码:完全指南

原文:https://towardsdatascience.com/breaking-down-geocoding-in-r-a-complete-guide-1d0f8acd0d4b?source=collection_archive---------4-----------------------

可视化|地图

如何使用 API 找到您感兴趣的地方,并在地图上可视化其位置

如果您想知道如何构建类似于您在应用程序中经常看到的地图,这可能是一个好的起点。在本教程中,我们将介绍如何根据描述或坐标找到一个地方,以及如何根据这些信息构建一个简单的地图。

请注意,本文假设读者对 R 语言有一定的了解:数据结构、操作符、条件语句、函数等等。本教程的所有代码都可以在 GitHub 上找到。

所以,让我们开始吧!

照片由 Julentto 摄影在 Unsplash

什么是地理编码?

地理编码是将一个地方的地址或名称转换成其坐标的过程。反向地理编码执行相反的任务:根据一个地方的坐标返回该地方的地址或描述。

仅此而已,就这么简单。因此,通过使用地理编码,您必须能够说在法国巴黎的埃菲尔铁塔可以在(48.858568,2.294513)纬度、经度坐标找到。在你的地图应用上输入(41.403770,2.174379),你将到达西班牙巴塞罗那的圣家族教堂罗马天主教堂。你可以自己核实——只需在谷歌地图上输入这些信息。

有哪些地理编码工具可用?

当谈到在线免费地理编码工具时,其中一个选项是专门的网站。比如上面提到的谷歌地图。稍微搜索一下,就能找到其他的。

如果你只需要找到几个地址,所有这些都是非常好的工具。但是想象一下有几百个呢?那成千上万呢?这项任务很快变得相当令人头痛。

对于批量请求,API 是更合适的选择。而这里最明显的选择大概就是谷歌地图 API 。为了能够使用谷歌服务,你需要在谷歌云平台上创建帐户,并获得你的 API 密钥。谷歌在他们的网站上提供了关于如何做的详细的说明。

另一个选择是使用来自 OpenStreetMap 的一个名为nomim的公共 API。OpenStreetMap 是一个合作项目,其目标是为公众创建一个免费的地图服务。正如其网站所说:

OpenStreetMap 是由一个地图绘制者社区构建的,该社区贡献并维护世界各地的道路、小径、咖啡馆、火车站等更多信息。

基本上,nomist 是一个在 OpenStreetMap 网站上进行搜索的工具。与谷歌地图不同,Nominatim 不需要你注册任何账户,也不需要你获得一个 API 密匙。但如果你想在应用程序中使用它的服务,你需要提供一个电子邮件地址,这样你的应用程序的活动就可以被跟踪,并在需要时受到限制——OSM 服务器的能力是有限的。

法律考虑

你可能会奇怪,如果 Google 提供了类似的功能,为什么我首先要告诉你关于 Nominatim API 的事情。你的第一个猜测可能是成本——与 OpenStreetMap 基金会不同,谷歌是一家私人公司,对其服务收费。这是事实,但只是部分事实。

首先,如果你现在在谷歌云平台上注册,你将获得 12 个月的免费试用,你的账户上有 300 美元的信用来了解它的功能。其次,即使在那之后,谷歌也免费提供一些最常用服务的有限访问权限,作为永远免费套餐的一部分。如果你的唯一目的是学习,那么这个包里的限制就足够了。要了解更多关于谷歌地图 API 定价的信息,请访问谷歌的帮助页面。

那么,你会问我什么问题?谷歌地图平台服务条款,其中声明:

3.2.4 对滥用服务的限制。
【一】 无刮。客户不得提取、导出或以其他方式抓取谷歌地图内容用于服务之外。
(c)不从谷歌地图内容创建内容。
【e】非谷歌地图不使用。

我不是法律界人士,不知道谷歌如何对待非商业目的使用其服务。但是我没有在这些服务条款中看到任何条款说明上述限制只适用于商业用途。所以,在你决定在你的应用中使用谷歌地图 API 之前,请注意这些限制。

与谷歌地图不同,OpenStreetMap 数据是在开放数据共享开放数据库许可证(ODbL)下获得许可的。正如作者自己所说,下面是 ODbL 1.0 的人类可读摘要 :

您可以自由:
*分享:复制、分发和使用数据库。

  • 创作:从数据库中产生作品。
  • 适应:对数据库进行修改、改造和建设。

只要你:

  • 属性:给原数据库做参考。
    *Share-like:在相同的许可下分发由原数据库改编的数据库。
  • 保持开放:向公众开放对适配数据库的访问。

一个全长许可,如果你想看的话,可以在开放数据共享网站上找到。

说了这么多,现在让我们继续编码!

照片由福蒂斯·福托普洛斯在 Unsplash 拍摄

安装软件包

让我们先安装并加载本教程中用到的所有包,所以以后不用担心。每个包的用途将在文章的相应部分描述。另外请注意,我们使用的是适用于 Windows 的软件版本 R 3.6.2。

***# install packages***
install.packages("ggmap")
install.packages("tmaptools")
install.packages("RCurl")
install.packages("jsonlite")
install.packages("tidyverse")
install.packages("leaflet")***# load packages***
library(ggmap)
library(tmaptools)
library(RCurl)
library(jsonlite)
library(tidyverse)
library(leaflet)

使用 R 包进行地理编码

R 社区创建了几个包,可以用来访问 Google Maps 和 nomist API。让我们看看它们。

包 ggmap

第一个包叫做 ggmap ,它允许你连接到谷歌地图 API。在开始使用这个包之前,您需要向 R 提供您的 API 密钥。

***# replace "api_key" with your API key*** register_google(key = api_key)

现在让我们在 12 家伦敦酒吧的样本上使用这个包中的geocode函数来演示它是如何工作的。该函数接受以下任一参数作为其output参数:

  • latlon —经纬度;
  • latlona —以上所有加地址;
  • 更多 —以上所有加地点的类型和地理界限;
  • 全部 —以上全部加上一些附加信息。

每个选项对应于生成的信息类型。一般来说,我们不需要比更多的选项提供的信息。

运行 ggmap 地理编码功能

让我们看看我们的结果。正如你所看到的,我们有一个酒吧的名字,它的坐标,地点的类型,结果的精度( rooftop 意味着谷歌能够找到一个具体的建筑)和它的地址。

运行 ggmap 地理编码功能的结果

现在,让我们用刚刚找到的坐标对它们所属的地方进行反向地理编码。

revgeocode函数允许这样做。它需要两个参数:location —经度/纬度的数值向量和output —或者地址或者全部。选项 all for output返回的信息比我们需要的多得多,所以让我们坚持使用地址

这次我们将把结果存储在一个列表中,而不是数据框中。这个列表的每个元素将包含另一个列表,其中包含关于酒吧的名称、坐标和地址的信息。

运行 ggmap 反向地理编码功能

运行 ggmap 反向地理编码功能的结果

ggmap 到此为止。现在让我们进入下一个项目。

打包 tmaptools

tmaptools 是一个包,它提供了一套读取和处理空间数据的工具。它促进了另一个名为 tmap 的 R 包的功能,该包是为可视化专题地图而构建的。许多 tmaptools 函数依赖于 Nominatim API。

现在,让我们试着从 tmaptools 获得与使用 ggmap 提取的信息相同的信息。我不得不稍微修改一些搜索请求,因为 Nominatim 无法找到基于它的位置。尽管我尽了最大努力,还是找不到其中一家酒吧——荣耀酒吧。因此,请注意,不同的服务提供商的数据质量和完整性可能会有所不同。

运行 tmaptools 地理编码功能

我们在最终表中只包括坐标和完整地址。这是它的样子。

运行 tmaptools 地理编码函数的结果

现在,是反向地理编码的时候了。在我们的输出中,我们将显示与来自 ggmap 的反向地理编码请求完全相同的信息。

运行 tmaptools 反向地理编码功能

运行 tmaptools 反向地理编码功能的结果

这是我们讨论 R 地理编码包的最后一段代码。在这里你可以读完这篇文章,然后自己练习上面描述的一些技巧。除非…除非你想了解更多!如果是这样,那我们继续!

由马丁·亚当斯在 Unsplash 上拍摄的照片

使用 API 进行地理编码

使用包是一种非常方便快捷的完成事情的方式。对于您想要完成的大多数任务,这些包提供的功能已经足够了。然而,如果你需要一些额外的东西,或者你对其他 API 函数感兴趣,或者你只是想学习如何使用 API,你需要去 Google/nomist 帮助页面做一些阅读。或者在网上搜索一些像这样的视频/教程,提供简短的总结。或者更好——双管齐下。

谷歌地图 API

看了 ggmap 包之后,现在让我们尝试直接使用 Google Maps API 来获取这个地方的位置、地址以及它的电话号码和网站。为了完成这个任务,我们需要地理编码 API 和位置 API 。

地理编码 API

地理编码 API 是一种提供地址和地点的地理编码和反向地理编码功能的服务。您可以通过 web 浏览器发送 HTTP 请求来访问地理编码 API,并获得 JSON 或 XML 格式的响应。虽然,在我们的例子中,我们将从 r。

地理编码 API 请求采用以下格式。

***# format***
[https://maps.googleapis.com/maps/api/geocode/outputFormat?parameters](https://maps.googleapis.com/maps/api/geocode/outputFormat?parameters)***# geocoding example***
[https://maps.googleapis.com/maps/api/geocode/json?address=The+Churchill+Arms,+Notting+Hill&key=YOUR_API_KEY](https://maps.googleapis.com/maps/api/geocode/json?address=The+Churchill+Arms,+Notting+Hill&key=YOUR_API_KEY)***# reverse geocoding example***
[https://maps.googleapis.com/maps/api/geocode/json?latlng=51.5069117,-0.194801&key=YOUR_API_KEY](https://maps.googleapis.com/maps/api/geocode/json?latlng=51.5069117,-0.194801&key=YOUR_API_KEY)

因此,您发送的 web 请求由几个部分组成 API url 后跟outputFormat (json 或 xml)和列表parametersoutputFormatparameters之间隔着一个问号(?)和parameters本身被一个&符号(&)彼此分开。

请求所需的参数包括:

  • 对于地理编码:address —地址或地名形式的搜索查询和key — API 关键字;
  • 对于反向地理编码:latlng —您搜索的地点的纬度和经度,以及key — API 关键字。

我们不会在查询中使用任何可选参数。

你可以在这里和这里阅读更多关于如何构造 API 请求的信息。

值得一提的是,如果你正在构建自己的应用程序,需要实时访问谷歌地图服务,你可以检查谷歌客户端( JavaScript )或服务器端( Java,Python,Go,Node.js ) API。

地点 API

如果您不想只局限于地点的地址和坐标,您可以使用 Places API。例如,要查找某个地方的电话号码和网址,我们需要使用地点搜索 来获取地点 ID ,并在以后使用它从地点详细信息中检索该信息。

在进行 API 调用时,确保提供您想要提取的fields的列表。否则,谷歌将发送所有这些邮件,并向您收取相应费用。在我们的情况下,这并不重要,因为我们不会超过免费限额,但是如果您计划 对大量请求使用 API,您可能会因此而被收费

对于 Place Search/Place Details API 调用,您还需要提供outputFormat (json 或 xml),后跟一个列表parameters

对于地点搜索,所需的参数包括:input —姓名、地址或电话号码(坐标不起作用);inputtype文本查询电话号码key — API 键。

对于地点细节,需要的参数是:place_id —可以通过使用地点搜索找到;key — API 键。

对于地点搜索和地点详细信息,我们将使用可选参数fields——我们希望 Google 返回的附加信息的逗号分隔列表。您可以在前面提供的相应帮助页面上阅读有关可能选项的更多信息。但是在我们的例子中,我们只需要来自地点搜索的字段 place_id 和来自地点详细信息的 formatted_phone_number 加上网站请记得阅读有关账单的信息!

API 调用的格式如下所示。

***# PLACE SEARCH******# format***
[https://maps.googleapis.com/maps/api/place/findplacefromtext/outputFormat?parameters](https://maps.googleapis.com/maps/api/place/findplacefromtext/outputFormat?parameters)***# example***
[https://maps.googleapis.com/maps/api/place/findplacefromtext/json?input=The+Churchill+Arms,+Notting+Hill&inputtype=textquery&fields=photos,formatted_address,name,place_id&key=YOUR_API_KEY](https://maps.googleapis.com/maps/api/place/findplacefromtext/json?input=The+Churchill+Arms,+Notting+Hill&inputtype=textquery&fields=photos,formatted_address,name,place_id&key=YOUR_API_KEY)***# PLACE DETAILS******# format***
[https://maps.googleapis.com/maps/api/place/details/outputFormat?parameters](https://maps.googleapis.com/maps/api/place/details/outputFormat?parameters)***# example***
[https://maps.googleapis.com/maps/api/place/details/json?place_id=ChIJGTDVMfoPdkgROs9QO9Kgmjc&fields=formatted_phone_number,website&key=YOUR_API_KEY](https://maps.googleapis.com/maps/api/place/details/json?place_id=ChIJGTDVMfoPdkgROs9QO9Kgmjc&fields=formatted_phone_number,website&key=YOUR_API_KEY)

同样,如果您考虑构建一个实际的应用程序,那么值得看看用于服务器端应用程序的 Java/Python/Go/Node.js 客户端或用于 Android 的Places SDK、用于 iOS 的Places SDK和用于客户端应用程序的 Places Library、Maps JavaScript API 。

使用谷歌地图 API 进行地理编码

说了这么多,现在让我们来编写代码本身。

我们的代码由七个函数组成:

  • 一个主要功能;
  • 用于生成 API 调用的三个函数;
  • 从 JSON 输出中提取数据的三个函数。

我们的主函数有三个参数:

  • search_query —搜索请求(地址或地点);
  • fields —提取信息(坐标地址联系人全部);
  • key —谷歌地图的 API 键。

第一个和最后一个是必需的,第二个是可选的,默认坐标

这些参数可以是以下类型:

  • search_query —字符串、字符向量、字符列表、一维矩阵或带有字符串数据的数据帧;
  • fields —字符串、字符向量、字符列表;
  • key —弦。

根据fields的值,该函数返回一个数据帧,其中包含:

  • 坐标 —经纬度;
  • 地址 —完整的地址和城市;
  • 联系人 —电话号码和网址;
  • 全部 —以上全部。

现在让我们来详细看看这个函数的每个组件。

正在生成 API 调用

一旦熟悉了我前面提供的信息,API 调用函数就非常简单了。

它分三步工作:

1.将搜索查询转换为列表。
2。对搜索查询进行百分比编码。
3。构造 API 调用字符串。

第一步是必需的,因为处理公共数据结构(在我们的例子中是一个列表)总是更容易。对于百分比编码,我们使用 RCurl 包中的URLencode函数。如果你不知道它是什么,访问这个页面有详细的解释。

谷歌地图 API 调用函数

从 JSON 中提取数据

Google 可以返回两种格式的数据——JSON 和 XML。在我们的例子中,我们使用 JSON 输出。这个输出需要转换成 R 对象,所以我们可以很容易地操作它包含的数据。一旦完成,我们的任务就是从格式化的列表中挑选我们需要的元素。

原始 JSON 输出及其格式化版本如下所示。

Google Maps API 的原始 JSON 输出

Google Maps API 的格式化 JSON 输出

那么,我们的函数是如何工作的呢?首先,使用 jsonlite 包中的fromJSON函数将 JSON 输出转换成 R 列表。之后,我们的函数检查 API 调用是否成功(status = "OK"),如果成功,它从列表中只提取我们需要的元素来构建最终的数据帧。检索一个城市名称有点棘手,因为首先我们需要找出它存储在address_components中的序列号。对于联系人来说,将所有NULL替换为NA也很重要,如果谷歌没有关于电话号码或网站的信息,就会出现所有的NULL,这样我们在生成最终数据帧时就不会出错。

将 JSON 输出转换成 R 对象的函数

主要功能

我们已经提供了我们的主要功能的描述。现在让我们解释一下它是如何工作的。

首先,该函数从谷歌地图获取坐标和地址。它检查用户是否真的想要这个信息(即fields参数中存在坐标和/或地址),如果是,它调用url_google_geocoding函数来构建 API 调用,并从 RCurl 包中调用getURL函数来实际创建它。

在我们收到 Google 的响应后,我们需要使用get_geodata_from_json_google函数将其从 JSON 格式转换成 R 列表。一旦完成,结果将存储在geodata_df数据帧中。

之后,对联系人重复相同的程序(即电话号码网站)。仅此而已。

这是代码。

使用 Google Maps API 进行地理编码的主要功能

现在,我们终于可以调用我们的函数并检查结果了。

***# replace "api_key" with your API key***
pubs_google <- geocode_google(pubs, "all", api_key)***# check results***
pubs_google

运行地理编码功能的结果—Google Maps API[第 1-5 列]

运行地理编码功能的结果—Google Maps API[第 6–7 列]

使用谷歌地图 API 进行反向地理编码

下面是几乎相同的功能,但反向地理编码。这一次,它只返回基于地点坐标的地址。我在这里没有给出任何详细的解释,因为到现在为止,你已经能够自己理解代码了。

除了key参数,主函数还需要coordinates作为输入,可以是:

  • 带有纬度和经度的向量(单个请求);
  • 纬度/经度向量的列表;
  • 有两列的矩阵——纬度和经度;
  • 包含两列(纬度和经度)的数据框。

该函数接受数值和字符串值作为coordinates

请注意,每次我们调用时,Google 可能会返回几个结果,但我们只使用第一个结果— results[[1]] —它对应于 Google 认为的最佳匹配。

另外,对要从 R 列表中提取的元素的硬编码引用也要小心。例如,在我们的例子中,第 5 个元素$address_components[[5]]$long_name可能指的是城市—伦敦($address_components$types = "postal_town")、二级行政区—大伦敦($address_components$types = "administrative_area_level_2")或一级行政区—英国($address_components$types = "administrative_area_level_1")。因此,在这种情况下,我们必须遍历 R 列表,找到我们需要的信息的types,并提取相应的long_name

反向地理编码功能(谷歌地图 API)

下面是在伦敦酒吧样本上运行这个函数的结果,我们之前从同一个 API 获得了这些酒吧的坐标。

***# extract coordinates from pubs_google***
pubs_google_crd <- pubs_google[ , c("lat", "lng")]***# replace "api_key" with your API key***
pubs_rev_google <- rev_geocode_google(pubs_google_crd, api_key)***# check results***
pubs_rev_google <- cbind(pubs_df, pubs_rev_google)
pubs_rev_google

运行反向地理编码功能的结果— Google Maps API

命名 API

现在让我们把注意力转向 OSM 的提名 API。

nomimsearchAPI 允许您根据描述或地址查找特定位置。它支持结构化请求和自由文本请求。搜索查询还可以包含对应于特定 OpenStreetMap 标签的特殊短语、。在我们的例子中,这个特殊短语是一个“pub”

反向地理编码 API 从一个地方的纬度和经度生成一个地址。

API 调用的格式如下所示。

***# geocoding format*** [https://nominatim.openstreetmap.org/search/](https://nominatim.openstreetmap.org/search/)<query>?<params>***# geocoding example*** [https://nominatim.openstreetmap.org/search/The%20Churchill%20Arms,%20Notting%20Hill?format=json&polygon=1&addressdetails=1](https://nominatim.openstreetmap.org/search/The%20Churchill%20Arms,%20Notting%20Hill?format=json&polygon=1&addressdetails=1)***# reverse geocoding format*** [https://nominatim.openstreetmap.org/reverse](https://nominatim.openstreetmap.org/reverse)?<query>***# reverse geocoding example*** [https://nominatim.openstreetmap.org/reverse?format=json&lat=51.5068722&lon=-0.1948221&zoom=18&addressdetails=1](https://nominatim.openstreetmap.org/reverse?format=json&lat=51.5068722&lon=-0.1948221&zoom=18&addressdetails=1)

一些参数对于地理编码和反向地理编码调用都是通用的:

  • format=[html | XML | JSON | JSON v2 | geo JSON | geocode JSON]—输出格式;
  • addressdetails = [0|1] —将地址分解成元素;
  • extratags = [0|1] —附加信息(维基页面、开放时间等)。);
  • accept-language —以何种语言显示搜索结果(English = en);
  • email —除非您提供一个允许跟踪您活动的电子邮件地址,否则您将无法在您的应用中使用 API(会出现错误消息)。

有些参数是每个 API 特有的。

搜索:

  • query —自由文本或地址;
  • countrycodes —通过 ISO 3166-1 alpha-2 国家代码(英国= gb)限制搜索;
  • limit —限制返回结果的数量。

反转:

  • query = lat,lon — in WGS 84 格式;
  • namedetails = [0|1] —在结果中包含替代名称列表;
  • zoom=[0–18]—地址所需的详细程度(默认值为 18,即特定的建筑物)。

queryformatemail为必选参数,其余为可选参数。我们不会在我们的函数中使用namedetails参数,也不会改变zoom参数的默认值——我提供它们只是供您参考。

这里一个重要的方面是标签的使用,它指向 OpenStreeMap mappers 提供的特定信息。这些标签中有一些是重复的(像电子邮件和电话和网站与联系人名称空间中的类似标签),所以不同的人可能会用不同的标签来标记同一类信息,你需要在你的应用程序中说明这一点。

还有一些要求,您必须遵守这些要求才能使用提名服务:

  • 限制同一网站/应用程序发送的请求数量——每个应用程序每秒一个请求;
  • 不鼓励对大量数据进行批量地理编码,但允许较小的一次性任务(我们的例子);
  • 搜索结果必须被缓存,所以不要多次发送相同的请求。

使用命名 API 进行地理编码

下面的函数复制了我们为 Google Maps API 构建的函数,所以我们不会详细描述它。

唯一显著的区别是我们添加了两个额外的可选参数:country,它对应于 API 调用的countrycodes参数,用于将您的搜索限制在某些县(默认情况下不使用)和language,它对应于accept-language参数,允许您选择显示结果的语言(默认为英语)。两个参数都需要以字符串的形式提供:country作为逗号分隔的代码列表(例如“gb,dr,fr”),而language作为单个值(例如“es”)。

地理编码功能(命名 API)

让我们看看运行这个函数的结果。

***# replace "email" with your email address*** pubs_nominatim <- geocode_nominatim(pubs_m, country = "gb", fields = "all", email = email)***# let's now see the results***
pubs_nominatim[, c(1:4)]
pubs_nominatim[, c(1, 5:10)]
pubs_nominatim[, c(1, 11:13)]
pubs_nominatim[, c(1, 14:17)]

运行地理编码函数的结果-命名 API[第 1–4 列]

运行地理编码函数的结果-命名 API[第 5–10 列]

运行地理编码函数的结果-命名 API[第 11–13 列]

运行地理编码函数的结果-命名 API[第 14–17 列]

使用命名 API 进行反向地理编码

类似地,下面的反向地理编码函数在很大程度上类似于我们为 Google Maps API 构建的函数。

反向地理编码功能(命名 API)

下面是在 12 家伦敦酒吧的样本上运行这个函数的结果。

***# extract coordinates from geocoding results*** pubs_nominatim_crd <- pubs_nominatim[, c("lat", "lng")]***# replace "email" with your email address*** pubs_rev_nominatim <- rev_geocode_nominatim(pubs_nominatim_crd, email = email)
pubs_rev_nominatim <- cbind(pubs_m_df, pubs_rev_nominatim)***# let's now see the results***
pubs_rev_nominatim[, 1:4]
pubs_rev_nominatim[, c(1, 5:11)]

运行地理编码反向函数-命名 API 的结果[第 1–4 列]

运行地理编码反向函数-命名 API 的结果[第 5–11 列]

使用传单库构建地图

普遍的事实是,只有当培训材料辅以实际应用的例子时,才能引起对该主题的真正兴趣。我向你们承诺过,基于我们从 API 获得的信息,我们将建立一个交互式地图,我打算兑现这个承诺。

轻松构建地图的方法之一是使用 JavaScript 传单库。传单在其网站上被描述为:“[……]领先的移动友好互动地图开源 JavaScript 库。”许多大型科技公司、一些媒体甚至政府机构都在使用它:GitHub、脸书、Pinterest、金融时报、华盛顿邮报、Data.gov、欧盟委员会都在使用它。在我们的例子中,我们将依赖 RStudio 的传单包,这使得在 r 中集成和控制传单地图变得很容易。

我不会在这里描述这个伟大工具提供的所有特性,因为这是另一篇完整文章的主题。相反,让我们把注意力集中在最重要的事情上。

因此,在传单中创建地图的过程包括三个基本步骤:

  1. 创建地图微件。
  2. 向地图添加图层。
  3. 显示地图。

微件本质上是地图的主干或容器。

图层允许您向地图添加以下元素:

  • 图块 —本质上是地图的“皮肤”,它定义了地图的外观和细节层次。更多关于平铺地图;
  • 标记 —可用于显示地图上的特定位置;
  • 弹出窗口和标注 —可用于向地图添加标注。例如,显示与某个位置相关联的地址或联系信息;
  • 多边形——特定的区域或面积。例如,一个州内的一个区;
  • 图例等。

对于我们的地图,我们将使用 OpenStreetMap 中的图块(传单的默认图块),并根据我们从 Nominatim 中提取的坐标绘制酒吧的位置。此外,我们将在标记弹出窗口中添加关于酒吧名称、地址和联系方式的信息。由于 Nominatim 没有返回每个酒吧的详细信息,我自己搜索了这些信息。我们没有在我们的可视化中使用任何多边形或图例,我添加的链接仅供参考。

因此,在我们继续之前,让我们做一些数据准备。

构建地图的数据准备

现在我们可以继续构建地图本身。

首先,让我们准备要在弹出消息中显示的文本:酒吧的名称、地址和电话号码。网站将不会单独显示,而是作为一个超链接添加到酒吧的名称。我们将使用一些 html 来以我们想要的格式呈现我们的文本。这里有一个提示。仅当您单击弹出消息所附着的对象时,才会显示弹出消息。如果您想在光标悬停在标记上时显示一些信息,您需要使用标签。然而,与弹出窗口不同,标签不会自动识别 HTML 语法——你需要先使用 htmltools 包中的HTML函数来转换你的消息。一旦完成,我们可以“画”我们的地图。

小叶功能是不言自明的。您可能唯一不熟悉的是管道操作符%>%,它是由 tidyverse packages 集合引入的。基本上,它允许您通过将一个函数的输出作为另一个函数的参数来传递,从而轻松地链接函数调用。更多关于那个的信息在这里。

***# text to be diplayed on pop-ups*** website <- paste0("<a href='", pubs_map$website, "'>", pubs_map$pub_name, "</a>")
center <- "<div style='text-align:center'>"
name <- paste0(center, "<b>", website, "</b>", "</div>")
address <- paste0(center, pubs_map$address_display, "</div>")
phone <- paste0(center, pubs_map$phone, "</div>")***# building the map*** pubs_map %>%
    leaflet() %>%
    addTiles() %>%
    addMarkers(~lng, ~lat, popup = paste0(name, address, phone))

最后看看结果吧。

用传单包装制作的地图

结论

在本教程中,我们介绍了使用 Google Maps 和 Nominatim 检索地理编码数据的不同方法,并展示了如何使用 JavaScript 传单库将这些数据用于在地图上绘制特定位置。我希望本指南将作为您探索所有不同种类的 API 和映射工具的起点。

使用 Python 分解 Goodreads 数据集

原文:https://towardsdatascience.com/breaking-down-goodreads-dataset-using-python-388e9b9d6352?source=collection_archive---------20-----------------------

找出下一本书

Ed Robertson 在 Unsplash 上拍摄的照片

我喜欢看书,总是在寻找下一本书来读,甚至在我开始读最近买的那本之前。所以,我决定摆弄这个 Goodreads 数据集我偶然发现了 Kaggle,看看我最终会得到什么样的书籍推荐。

这非常有趣,充满了学习!

和往常一样,我使用了 Jupyter 笔记本,并使用virtualenv建立了一个虚拟环境。所有步骤请查看本帖。

进口:

import sys
sys.path.append('./lib/python3.7/site-packages')
import pandas as pd
import re
import mathdata = pd.read_csv("books.csv")

错误:

读取 csv 文件时,会出现以下错误:

ParserError: Error tokenizing data. C error: Expected 10 fields in line 4012, saw 11

发生这种情况是因为,在某些行中,有逗号将所有值向右移动一个位置,从而添加了一个额外的列。

可能要做的事情:

  • 完全跳过这些行。但是我们事先并不知道这些行是什么。该数据集的 Kaggle 讨论区列出了这些行,但是删除它们将导致数据丢失。
  • 使用文本编辑器,用另一个分隔符如;|替换所有逗号,然后手动转到有多个作者的行,并在那里放置逗号。这是一个麻烦的过程,需要太多的手动操作。如果损坏的行数太多,这个解决方案是不可行的。

我最终做的是——使用文本编辑器,并在最后添加一列以避免出现ParseError。我给专栏命名为extra,并使用pandas读取 csv 文件。

添加了名为“额外”的列

现在我们可以查看和分析数据了。

data.describe(include = "all")

data.describe(include = "all")

数据:

bookID:每本书的唯一标识号;
title:书的名字;
authors:该书作者的姓名。多个作者用-分隔;
average_rating:该书的平均评分;
isbn:识别图书的唯一编号,国际标准书号;
isbn13:一个 13 位的 ISBN 来标识图书,而不是标准的 11 位 ISBN;
language_code:书的主要语言;
# num_pages:书的页数;
ratings_count:该书获得的总评分数;
text_reviews_count:该书收到的文字评论总数。

损坏的行:

13719 行中有 5 行损坏,即它们在extra字段中有一个值。

为了找出这些行,我们检查哪些在该字段中不具有值NaN,即具有整数值。因此,我将那些具有整数值的行的索引存储在字段extra中。

corrupted_rows = []for index, i in data.iterrows():
     if -math.inf <= i['extra'] <= math.inf:
         print("index number:", index)
         print("field value:", i['extra'])
         print("...")corrupted_rows.append(index)

损坏的行

data.loc[corrupted_rows, :]

data.loc[corrupted_rows, :]

让我们将多个作者合并到一个字段中。我使用authors字段中的;加入它们:

data['authors'] = data['authors']+ ";" +data['average_rating']

我们得到一个警告:SettingWithCopyWarning。这不是一个错误,所以没有什么是坏的。然而,知道警告试图告诉我们什么总是好的,而不是忽视它。这里有一个解释。

转变:

作者被合并在一个专栏中。现在剩下要做的是将列值从第三列开始(包括第三列,因为我们从索引 0 开始),向左移动一个空格。这是通过使用shift操作符来实现的,这里我们指定需要向左(或向右)移动多少个空格,以及是沿着行轴还是列轴。

**#-1 indicates one space to the left and axis=1 specifies column axis**data.iloc[corrupted_rows, 3:] = data.iloc[corrupted_rows, 3:].shift(-1, axis = 1) 

移位的结果(这不是正确的方式)

这种移位的结果是两列中的值丢失:# num_pagestext_reviews_count。这是因为列的数据类型与最终移位值的数据类型不匹配。

解决方案是将所有列的数据类型临时转换为str,执行 shift,然后将它们转换回原始数据类型。

data.iloc[corrupted_rows, 3:] = data.iloc[corrupted_rows, 3:].astype(str) **#convert to str**data.iloc[corrupted_rows, 3:] = data.iloc[corrupted_rows, 3:].shift(-1, axis = 1) **#the shift**data.describe(include="all")

data.describe(include="all")

我们现在可以删除最后一列。

 del data['extra']

我们现在必须将列的数据类型转换回它们的原始类型。

pd.to_numeric自动配置floatint数据类型。

data["average_rating"] = pd.to_numeric(data.average_rating) data["ratings_count"] = pd.to_numeric(data.ratings_count) data["# num_pages"] = pd.to_numeric(data.["# num_pages"])data["text_reviews_count"] = pd.to_numeric(data.["text_reviews_count"])

过滤数据:

我只想保留那些英文书。首先,我们需要一个正在使用的不同语言代码的列表。

language_code_unique = data.language_code.unique() 

当我们打印列表时,我们看到英语语言代码以en开头。因此,简单使用regex将帮助我们过滤数据。

**#list to store the different English language codes**
english_lang_code = [] language_code_regex = re.compile(r'^en')for code in language_code_unique:
    mo2 = language_code_regex.search(code)
    if mo2 != None:
        english_lang_code.append(code)

输出是对应于英语的 5 种语言代码。然后,我们使用 define 函数直接在数据帧上使用。

def check_lang_code(row):
     if row.language_code in english_lang_code:
         return rowdata = data[data.language_code.isin(english_lang_code)]

这给我们留下了英文书籍,并将行数减少到 12651。为了进一步减少数据量,我们只提取相关的列:titleauthorsaverage_ratingratings_count

data_filtered = data.iloc[:, [1, 2, 3, 8]] 

为了获得更高质量的图书列表,我们需要设置一个阈值average_ratingratings_count。我决定两者兼顾。

ratings_count_mean = data_filtered["ratings_count"].mean()average_rating_mean = data_filtered["average_rating"].mean()data_filtered = data_filtered[(data_filtered.average_rating > average_rating_mean)]data_filtered = data_filtered[(data_filtered.ratings_count > ratings_count_mean)]

这留给我们一个 1013 行× 4 列的数据集。

高评价书籍列表:

使用average_rating作为获得顶级书籍列表的唯一因素是不够的。

data_filtered.sort_values(by=['average_rating'], ascending=False) 

下面的列表不对。

data_filtered.sort_values(by=['average_rating'], ascending=False)

我们需要考虑到ratings_count。我创建了一个新列weighted_rating,作为ratings_countaverage_rating的乘积。

data_filtered['weighted_rating'] = data_filtered['average_rating'] * data_filtered['ratings_count']**#sort in descending order of 'weighted_rating'** data_filtered = data_filtered.sort_values(by='weighted_rating', ascending=False) 

data_filtered.head(10)

看起来好多了!

显然,哈利·波特是主角。现在,我已经读完了整个系列,所以我不想包括任何哈利波特的书。这是一个简单的regex案例。

match_regex = re.compile(r’Harry Potter’)**#list to store all 'Harry Potter' titles**
matched_titles = []for index, row in data_filtered.iterrows():
    mo1 = match_regex.search(row.title)
    if mo1 != None:
        matched_titles.append(row.title)

匹配的 _ 标题

data_without_hp = data_filtered[~data_filtered.title.isin(matched_titles)]

榜单前 20 本书:

data_without_hp.head(20)

列表中有我读过的书,通过添加到match_regex可以很容易地过滤掉,但我决定就此打住。脱颖而出的书是“蜜蜂的秘密生活”。我以前从未听说过这本书,这本书我一定要读一读!

局限性:(

不幸的是,这个数据集没有流派类别(恐怖/犯罪/搞笑/…)和小说/非小说类别,如果有这两个类别,这份名单会更具策划性和个性化(想到创建这样一份名单,我会兴奋得尖叫)!

要点:

→处理“损坏的行”
→尽可能过滤掉数据以获得期望的结果并提高性能
→一个主要的教训是尽可能减少for循环的数量,因为它们比其他方法慢:

  • 定义一个函数,然后在数据帧上应用它
  • 过滤数据框架括号内的数据
  • 直接计算函数值

希望你喜欢带走一些有价值的见解!

分解数据科学家面试流程

原文:https://towardsdatascience.com/breaking-down-the-data-scientist-interview-process-be6b88ac11dc?source=collection_archive---------23-----------------------

这是一个全新的十年,我们中的一些人可能正在寻找我们的下一个角色——也许是数据科学家?

根据我参与和主持数据科学面试的经验,我对面试流程进行了细分。数据科学是一个非常广阔的领域,有些数据科学家的职能类似于数据工程师,有些数据科学家的职能类似于产品经理等等。我会尽量保持这种概括,但我以前的经验肯定会使我偏向前者。

该过程

招聘人员电话

通常,招聘人员或人力资源部门的人会安排一次简短的拜访。他们会给你一个公司的概述,高层次的角色细节,并有机会问任何问题。面试官还会问一些千篇一律的问题,比如你有使用 Python 的经验吗?你有资格在这个国家工作吗?这种通话通常相当轻松;它通常被用来淘汰有明显危险信号的候选人。

招聘经理电话

在这个过程中的某个时候(通常是在开始的时候),招聘经理会想和你谈谈。在中小型公司,招聘经理是为他们的团队招聘的人。对于更大的公司,他们可以是另一个团队的经理。本次对话将深入到该角色的技术层面。面试官可能会问你以前的经历、技术能力和行为方面的问题,以了解你是谁。这也是一个很好的机会来询问更多关于这个角色的问题。

技术面试/带回家作业

下一部分是 1 小时的技术评估或带回家的作业。

技术评估通常是与团队中的数据科学家/工程师进行视频通话,讨论 Leetcode 问题或数据清理/建模练习。在这次面试中,面试官会评估你的技术能力。在开始解决问题之前,大声说出你的想法并提出任何澄清性的问题是一个好主意。

技术面试的替代方案通常是带回家的作业。这通常是一个建模/数据分析或机器学习任务,需要 3 个小时才能完成。其中一些时间长度可能具有欺骗性——我发现自己花了超过 10 个小时来完成一个 3 小时的带回家作业。根据我评估带回家作业的经验,候选人经常忽略的一个方面是他们工作的陈述和可重复性。如果任务是训练一个分类器,包括一些关于性能和如何评估模型的细节。如果解决方案涉及外部库,请包括如何复制解决方案的说明。

现场

现场面试通常是面试过程的最后阶段。在这次面试中,你将被带到公司与未来的团队成员见面,并经历一整天不同的面试。

没有特定的顺序,这些是典型的采访性质:

文化/行为:团队成员(有时是人力资源)将评估你是否符合文化。在我面试的几家公司,午餐时间是非正式的文化评估。面试官会评估你是否适合这个职位,并衡量你对这家公司的兴趣。

结对编程:和坐在你旁边看你编程的人一起解决一个问题。这与技术评估非常相似,只不过是面对面的评估。我看到这次采访有两种不同的方式。有时候,是 Leetcode 的问题。其他时候,它更适用(例如,清理这个数据集或在代码库中进行 XYZ 更改)。这是对你一般技术能力的测试。

解决问题/白板:这次面试旨在更好地了解候选人的批判性思维和解决问题的能力。我见过这种采访,从非常技术性的东西(编写伪代码来解决一个非常具体的编程问题)到设计一个实验,再到更抽象的东西,如解决康威的生命游戏。

这就是数据科学家面试流程。

感谢您的阅读!

如果你喜欢这篇文章,可以看看我关于数据科学、数学和编程的其他文章。请通过 Medium 关注我的最新消息。😃

作为一个业余爱好项目,我还在www.dscrashcourse.com建立了一套全面的免费数据科学课程和练习题。

如果你想支持我的写作,下次你报名参加 Coursera 课程时,可以考虑使用我的会员链接。完全公开—我从每一次注册中获得佣金,但不会对您产生额外费用。

再次感谢您的阅读!📕

分解支持向量机(SVM)算法

原文:https://towardsdatascience.com/breaking-down-the-support-vector-machine-svm-algorithm-d2c030d58d42?source=collection_archive---------33-----------------------

所以,我昨天在修改机器学习算法;我观察到 SVM 可能是一个广泛使用但复杂的机器学习算法。所以,在理解了其中的错综复杂并从头开始编码之后;我想我必须写一个帖子来帮助像我一样发现它比它的同行稍微复杂一点的人。

作者图片

所以,SVM 基本上使用向量空间来执行指定的任务。当谈到识别手写数字和相关任务时,你会惊讶地发现 SVM 实际上比一些神经网络更好。让我们开始吧!

基本直觉

在我们开始之前;你应该知道 SVM 一次只能划分两个组。但是嘿;这并不意味着它仅限于二元分类器(更强调单词‘一次’)。所以在直觉层面上。支持向量机在超平面的帮助下分离数据集中的两类数据。从超平面到数据点的垂直平分线表示最大可能距离。

SVM 超平面(决定边界)和垂线。作者图片

简而言之;即使可以有无限个超平面来分隔数据;最佳选择是可分离距离最大的一个(用数据点的垂线测量)。

因此,如果一个数据点位于超平面的任一侧;假设超平面是一堵分隔墙(只是打个比方),我们就可以很容易地说出它的类别。但是,这也可以在回归的帮助下完成,对吗?实际上是的,但是 SVM 可以处理更复杂的分色,因为它使用向量空间。不仅如此,SVM 还在确定决策界限方面做了出色的工作。(这是最佳位置—垂直线的最大长度)。

现在我们已经清楚了我们的基本原则;让我们开始讨论它的技术细节。

让我们多刺激一下我们的大脑

简单来说,我们可以说向量是一个既有大小又有方向的量(基础物理/数学)。在 SVM;幅度是数值(可以通过取 x 和 y 坐标的模或和的平方根来计算;类似毕达哥拉斯定理中的斜边)。

除此之外;另一个要知道的是两个向量的点积,简单来说就是两个向量中的值相乘。可以通过下图来理解。

作者图片

例如,如果数据集中有一个数据点“u”(可以用 u 向量表示),它被一个超平面(用红线表示)分隔开。现在,我们取另一个向量(w ),它是从超平面垂直画到原点的。现在,u 和 w 的点积加上偏差决定了我们的支持向量断言的输出。

SV 断言。作者图片

现在,如果我们方程的结果大于或等于零;然后我们可以对另一边的数据点进行分类(+ve)。在上面的例子中;我们可以直观地看到事实并非如此(我们的数据点显然不在+ve 一侧)。但是即使在复杂的情况下,这个等式也像魔法一样有效。

还有,你要注意,如果u . w+b = 0;然后,该点出现在决策边界上(一种罕见的情况)。

“但是萨蒂扬,这并不复杂。那就好理解了。”嗯,如果是这样的话,我会很高兴的。但是 SVM 在获取偏差和向量值时有一些限制。但是是的,一旦你熬过这一关,我相信你会爱上 SVM 的。

SVM 的制约因素

SVM 的约束是 u.w + b 必须是 1 或者-1。即使数学上这些值可以是-1 到 1 之间的任何值,但是因为我们想用向量对值进行分类;我们假设它是绝对的 1 或-1。此外,这涉及到复杂的数学(拉格朗日乘数)。

所以,如果我们的等式是 1;那么属于+类。如果它是-1,那么我们的数据点属于-class。但是嘿,我们还是不知道 wb. 的值是多少

得到 w;我们需要找到决策边界的最佳位置。因此,我们可以从它画一条垂线来测量矢量 w。

SVM 超平面和决策边界。作者图片

我们已经知道,决策边界应该与两侧的数据点有尽可能高的距离。(换句话说;决策边界和 2 个数据超平面之间的宽度必须最大)。

为了实现这一目标;我们需要最大化宽度。那就是:

在简化并用等式 u.w+b -1 = 0u.w+b+1 = 0 替换 X 正向量和 X 负向量的值后;我们得到:

以便最大化宽度;向量 w 的值应该是最小值。如前所述;向量 w 的大小是 1/2 * |w|

所以,我们在看一个想要最小化的方程。

这是额外需要阅读的内容。但是为了得到约束,我们必须插入拉格朗日乘数。不仅如此,我们还会看到一个向量 w(我们希望最小化)和偏差(最大化)。

迷路了?坚持住。就差最后一步了。如果你对微积分感兴趣。我们需要对 w 和 b 做偏导数。这给了我们一个二次方程。

而这就是我们如何得到向量 wb (bias)的值。天哪,我知道这很复杂。但仅此而已。

事物的利与弊

除了表演;从计算的角度来看,训练 SVM 可能是一个繁琐的过程,因为二次方程。但是,一旦训练出来;它可以很快预测出分数。因为它只需要计算 u.w+b 的符号(不管它是否大于零)。

我的朋友是支持向量机。

感谢 sklearn 让很多害怕数学的人只用一行代码就能使用这个漂亮的算法。无红利

如果你想了解更多,你必须查看 sentdex 的解释和 MITOCW 讲座,了解更详细的数学解释。

直到下一次!

闯入数据科学:如何根据每个细分市场来做

原文:https://towardsdatascience.com/breaking-into-data-science-the-recap-5b451c82048d?source=collection_archive---------65-----------------------

概述许多故事和技巧,以进入数据科学领域

伊恩·施耐德在 Unsplash 上拍摄的照片

打入数据科学领域很难。根据这个调查,大多数数据科学家列出了他们拥有的核心技能是 Python/R/Excel、数据可视化、批判性思维、沟通技巧、机器学习、统计学、数学、SQL、业务理解、数据准备。只要看看要掌握的各种技能,学习所有这些技能可能会很可怕。此外,发布在在线工作公告板上的数据科学家招聘广告通常需要大量的经验和/或技术知识,只有在该领域工作过一段时间后才能获得。

尽管打入数据科学领域很难,但这并不是一项不可能完成的壮举。事实上,许多人都这样做了,在这篇文章中,我想总结一下我从许多来源读到和听到的关于如何进入数据科学领域的所有故事,以及这些人给出的提示。

断路器类别

什么是断路器?这只是我为了方便而想出的一个词。在这篇文章中,我将把那些想要打破的人称为“打破者”。虽然许多人是断路器,他们实际上可以归类。Reddit 上有一个帖子对想要进入数据科学领域的人进行了分类,我引用了这个帖子,但我在这里补充了我自己的观点。这些分类是:

1。研究人员

这个分类中的断路器来自于学术界或者曾经在其中集中工作过。通常持有博士学位(或某些国家的硕士);通常来自定量领域,有出版物和会议的记录,并担任研究员/助理/教授/讲师。

研究破坏者在理论上很棒,但通常很难从学术界过渡到工业界。大多数时候,他们还缺乏商业视角,并因职责的不同而疲惫不堪。

2。转行者

职业改变者(career Changers)Breaker 是一个已经在工业领域拥有足够的专业经验的人,可能拥有硕士学位,也可能不拥有硕士学位,并且愿意改变他们的职业,进入数据科学领域。

根据他们以前的经验,这位破坏者可能拥有进入数据科学领域所需的几乎所有核心技能(通常是编程、沟通和/或业务理解),也可能根本没有任何核心技能。唯一可以肯定的是他们在数据科学领域缺乏资历。

3。新毕业生/在校学生

顾名思义,这位断路器是一个大学刚毕业目前在一个学生。它可以在任何学士专业,但主要是这个断路器来自定量或技术领域。

这是最困难的时候,因为他们需要找到被大量申请人淹没的初级职位。此外,许多这种“入门级”的职位看起来根本不是入门级的,就像他们需要一些先进的技术或一些类似的经验。尽管如此,如果有一个入门级职位似乎有许多高级要求,我会认为这些公司对数据科学了解不多。

故事重述

从我刚才解释的障碍类别来看,取决于你站在哪里,你面前的障碍会有所不同。在这里,我将重述人们如何根据他们的破坏者类别闯入数据科学。

人员断路器

这就是我。我来自学术界,在进入数据科学领域之前,我是一名研究员。

当他们想要进入数据科学领域时,大多数这种类型的破坏者都有一个共同点。

  • 他们热爱为科学做出贡献,并希望为更美好的人类实践这一理论。问题是,学术界的世界是艰难的,而且不像它那样纯洁。出版和竞争的环境让许多学术界人士对那些在科学上取得突破的人望而却步。
  • 僵化的职业道路,只有少数人能够成功。此外,财务安全和工作生活平衡与考虑组建家庭的人不相容。
  • 许多人在理论和/或编程算法方面有足够的知识,但觉得这些知识只停留在某个地方。他们想应用他们的知识

这个断路器面临着一些障碍。其中大多数是:

  • 很难从学术界过渡到工业界,因为环境确实不同。学术界的人没有行业工作环境的经验。在企业中担任数据科学家需要了解商业世界是如何运作的。这意味着来自学术界的人需要从学术文化到企业文化重新校准他们的思想。与可以塑造和体验专业的应届毕业生不同,从学术到行业的心态转变需要巨大的努力。
  • 来自学术界的人通常持有 T2 的高等大学学位,这意味着公司认为他们希望 T4 要求比本科学位持有者更高的薪水。不管是真是假,这是他们得到的感觉。
  • 弱现场编程技能面试和/或商务沟通技能。许多学术界人士天生热爱写作,专注于他们的研究。数据科学的问题在于,你不仅需要技术技能,还需要每天向非技术人员展示。是的,学术界的研究总是包括展示,但主要是展示给具有相似背景和知识的人。这就是区别,数据科学家需要将技术术语包装成更具商业价值的术语。

那么,这些人实际上是如何进入数据科学的呢?学术界人士仍然占据优势拥有经验和理论基础。大多数人说,他们需要做的是让别人相信你能胜任这份工作。这意味着你具备关于数据科学的必备知识展示你从事类似工作的经验和技能

知识可以通过大量阅读、在线课程或有导师来获得。展示经验和技能需要大量的调整;我个人在我的研究时间里量身定制我的经验,以适应我想进入的行业。例如,我是一名在生物统计方法方面有经验的生物学家。我只需要在我的简历和面试中展示我的统计方法,它实际上适用于工业企业。

许多报道还指出,他们是通过网上求职公告板申请工作,而不是随机申请。他们专门申请 他们曾拥有的研究业务背景的工作(例如医疗保健)。虽然,我也看过很多故事(像我一样)从自己的人脉中找到工作。这种联系可能来自他们的大学、Meetup 小组,或者只是你的老朋友。

职业改变者

这种类型的人以前已经是行业专家,但出于各种原因希望将他们的职业生涯转向数据科学。这种破坏者通常是那些:

  • 他们想要更高的薪水。大多数职业改变者和研究人员没有相同的动机。虽然财务安全仍然是目标,但研究人员破坏者也受到他们的研究工作可以应用的方式的激励,而职业改变者破坏者主要只是想要更高的工资(不是一概而论,只是从我读到的)。
  • 想要更好的职业机会。与金融安全相关,数据科学目前仍然是一个热门工作,行业中有许多需求。职业道路也足够清晰,这吸引了许多人尝试磨合。
  • 孤注一掷。我个人遇到过许多想中途改变职业的人,尤其是那些参加训练营的人。这里的人们赌上他们最后的钱和工作来获得进入数据科学的机会。

专业人士通常有更好的优势,因为他们已经有了正确的经验和心态,但仍然有一些缺点:

  • 缺乏核心技能。取决于他们的专业背景,他们可能已经拥有几乎所有必要的核心技能,甚至根本没有。例如,从事软件工程的人在编程方面会做得更好,但不一定需要交流他们的工作。
  • 他们有时只是没有分析能力或热情去做一件事。对,分析。不要以为只有数据分析器分析数据,数据科学只用深度学习来预测什么。数据科学与分析数据和利用数据进行创造性工作密切相关。我读过并见过许多人,他们只是没有准备好。这一点尤其表现在面试阶段,他们需要展示自己的分析能力,但却做不到。

与其他破坏者相比,拥有一些核心技能的专业人员仍然有优势,特别是如果他们已经拥有领域知识和/或编程技能。许多属于这一类别的人通常会在面试中展示他们的专业经验,并通过大量阅读和参加在线课程/认证来弥补他们的技能不足。建立投资组合也是必须的。一些人也报名参加更高的大学学位(通常是硕士)来增加他们的机会。其他人也推荐做实习

就像研究员断路器一样,许多人通过在线工作板申请,但通常情况下,职业转换断路器在行业方面更灵活,所以他们随时申请有空缺的职位。我也读过许多故事,说职业改变者 breaker 从他们自己的公司获得了一份数据科学的工作。例如,我读到他们的公司想要建立一个数据科学团队,因为这个人拥有技能,他们雇用他们作为数据科学家。

许多职业改变者也获得了数据科学家的工作,因为他们在网络媒体中的;尤其是 LinkedIn。他们尝试过在网上写博客或发布他们的工作,然后突然有招聘人员联系他们。

****联网虽然仍然是人们推荐的最多的方式。有了人际关系网,如果你像平常一样申请,他们可以绕过许多常规步骤,人际关系网也可以帮助你更容易获得这个职位。

新毕业生/当前学生破坏者

在数据科学领域,这种突破可能是最难突破的类型。没有实际的行业经验,并试图找到一个竞争激烈的有限领域(不仅来自新毕业的同事,也来自有经验的人)。这种破碎机大多具有以下特点:

  • ****找一份任何数据相关职位的工作都可以,但主要目标是数据分析师或数据科学家职位。这并不意味着没有具体的目标,但由于竞争,缺乏联系和有限的景点使这个断路器罚款任何种类的位置。
  • 他们可能拥有学士/硕士学位或者正在攻读。有些人没有任何学位,通常是刚从高中毕业。
  • ****已经申请了很多公司甚至之前在学生时期或者毕业后实习过。有些人还要求电话面试/面对面面试/编码面试或任何类型的面试,结果各不相同。
  • 一些人对数据科学感兴趣是因为薪水,另一些人感兴趣是因为技术前景。还有许多其他原因,但这主要是我所看到的。

我再次声明,这个破坏者最难进入数据科学领域,因为:

  • ****缺乏经验和核心技能。这一直是这个断路器不好过的主要原因。数据科学仍然是一个新鲜出炉的职业,意味着这个职位的需求大于供给。这也意味着大多数公司和早期创业公司都在寻找有经验的人。
  • ****没有正确连接。对于大一新生或学生来说,很难找到与工业企业的联系。我读到的许多故事是,人们通过网络找到他们的职业,而这个破坏者的评论通常是“我怎么能做网络呢?”
  • 数据科学职位中没有太多的入门级职位,因为大多数职位都需要大量的经验。更有甚者,我还读到许多大一新生甚至很难被要求参加这个所谓的“入门级”职位的面试。

似乎进入数据科学有很多障碍,事实也的确如此,但这并非不可能

这些成功进入的新生是那些坚持努力并通过大量阅读和在线课程不断更新知识的人。一些人通过实习找到工作,另一些人通过进入非技术行业找到工作,该行业有一个与数据相关的职位空缺。****

许多人也给出建议,如果你没有研究生学位,最好尝试找一份实习工作,或者努力追求一份工作。有些人还建议申请另一个职位,但是当你已经有足够的经验时,你可以尝试再次进入职场,成为一名职业改变者研究员。****

作为一名新生或学生,找到一个联系也不是不可能的,事实上,许多人做到了。许多人从他们大学的教授那里,从校园的就业公告板,甚至只是从他们的兴趣小组中找到一个。人们也试图通过在线媒体联系,比如 LinkedIn。关于网络的一个建议是它仍然是人与人之间的互动,意味着给予和索取。不要在 meetup 会议或 LinkedIn 上通过询问是否有空缺职位来突然联系某人。试着进行适当的讨论,和他们成为朋友。毕竟,人脉不是获得工作的捷径。在产生任何结果之前,它需要被慢慢地处理。我从高中起就开始建立自己的人际网络,直到十年后才有回报。毕竟,网络是关于彼此的信任,在某种程度上,是给予和索取。

结论

许多人试图进入数据科学领域,根据他们的经验,障碍也会有所不同。成功的断路器给出了许多提示,包括:

  • 更新您的技能,使其与数据科学核心技能相匹配
  • 根据职位要求个性化你的经历
  • 实习
  • 联网

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

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

打破 Spotify 的音乐流派分类的算法!

原文:https://towardsdatascience.com/breaking-spotifys-algorithm-of-music-genre-classification-31ecf8453af1?source=collection_archive---------16-----------------------

在这篇文章中,我将深入探讨构建您自己的模型的过程,该模型可以将音乐分类为不同的流派,并创建您自己的播放列表。

照片由沃瓦·克拉西尔尼科夫从派克斯拍摄

简介

这个行业中有许多不同类型的流派。但是基本的类型将会有几个主要的方面,使它们更容易被识别。流派是用来标记和定义不同种类的音乐,基于它们的创作方式或基于它们的音乐形式和音乐风格。

在本文中,您将学习构建自己的模型,该模型将接受一首歌曲作为输入,并预测或分类该特定歌曲的一个流派。我们将分为以下几个基本流派——布鲁斯。古典、乡村、迪斯科、嘻哈、爵士、金属、流行、雷鬼和摇滚。该模型将使用 LSTM 网络构建。如果你不知道 LSTM 是什么,不要担心。这篇文章将使你对 LSTM 及其工作有一个简单的了解。

以下是整个项目的 GitHub 链接—https://GitHub . com/rajatkeshri/Music-Genre-Prediction-Using-RNN-LSTM

整篇文章分为 4 个部分

  1. 先决条件
  2. 理论
  3. 数据预处理
  4. 训练模型
  5. 根据新数据进行预测

先决条件

在开始这个项目之前,你需要具备一些先决条件。你首先需要的是数据集。我在这个项目中使用的音乐数据可以从 ka ggle-https://www . ka ggle . com/andradaolteanu/gtzan-dataset-music-genre-class ification下载。

注意,这个数据集包含 10 个类,每个类中有 100 首歌曲。对于一个机器学习项目来说,这可能听起来很少,这就是为什么在下一节中,我将向您展示如何增加每类体裁的训练数据的数量。

您需要在 PC/笔记本电脑上安装一些模块,以便开始使用。我们将使用用 python 编码的 Tensorflow 来构建整个 LSTM 模型。我们将使用 python 3.6 或更高版本(如果您使用 python 2.7,则需要使用 python 3.6 或更高版本才能获得完整的支持和功能)。以下是需要安装的 python 包—

  1. Tensorflow —机器学习库
  2. librosa——从歌曲中提取特征的语音处理库
  3. numpy——科学计算的数学模型
  4. sklrean —另一个机器学习模型(我们将使用这个库来拆分训练和测试数据)
  5. json——对数据集进行 JSON 化(在下一节中解释)
  6. pytdub —将 mp3 转换为 wav 文件

这些模块可以使用 pip 或 conda 安装。您可以找到许多关于 pip 或 conda 入门的在线资源和 youtube 视频。一旦以上模块安装完毕,我们就开始编码吧!

理论

对于任何机器学习项目来说,都有两件主要的事情——从数据中提取特征和训练模型。

对于用于机器学习目的的音频和音乐特征提取,通常从歌曲或音频中提取梅尔频率倒谱系数(MFCC,并且这些特征用于训练模型。MFCC 特征提取是一种仅从音频中提取相关信息的方法。

为了更好地解释这一点,当我们以数字格式表示一个音频文件时,计算机将其视为一个波,X 轴为时间,Y 轴为振幅。这如图 1 所示。

音乐在振幅和时间上的表现

这种表示格式不能给我们提供太多关于音频或歌曲的信息,因此我们通过使用快速傅立叶变换(FFT)在频域中表示音频。FFT 是一种主要用于信号处理的数学算法,用于将时域转换到频域。您可以参考此链接或观看一些 youtube 视频,了解什么是 FFT 以及它的具体工作原理—https://www . nti-audio . com/en/support/know-how/Fast-Fourier-transform-FFT #:~:text = Fast % 20 Fourier % 20 transformation % 20 FFT % 20 2D % 20 basics,frequency % 20 information % 20 about % 20 the % 20 signal。

使用该 FFT,我们转换输入音频文件,并在频域和时域中表示它。在频域和时域显示音频数据的图形称为频谱图,如图 2 所示。

图 2

声谱图是一组叠放在一起的 FFT。这是一种直观表示信号响度或幅度的方式,因为信号以不同频率随时间变化。这里,y 轴被转换为对数标度,颜色维度被转换为分贝(你可以把这看作振幅的对数标度)。这是因为人类只能感知非常小且集中的频率和振幅范围,并且人耳根据对数标度的原理工作。

正常的频谱图可以用于提取特征,但是这仍然包含一些不需要的附加信息。由于人耳在对数尺度而不是线性尺度上工作,我们使用 mel 频谱图,该频谱图将该频谱图转换成对数表示,以通过移除或消除不想要的特征来更准确地获得特征。梅尔频谱图是一个频谱图,其中频率被转换为梅尔标度。图 3 显示了 mel 光谱图—

图 3

回到主题,MFCCs 使用 mel 标度,用于从音频信号中提取特征,当表示为图形时,结果是 mel 谱图。简而言之,我们在 mel 光谱图上看到的正是我们训练模型所需的特征。我在部门找到了这篇精彩的文章,它解释了关于 mfccs 的一切。

一旦我们准备好数据集,我们就要训练我们的模型。音乐是一个时间序列数据。这意味着音乐与时间成线性关系。LSTM 非常擅长在输入特征空间中提取模式,输入数据跨越长序列。鉴于 LSTM 的门控结构具有操纵其记忆状态的能力,它们是解决这类问题的理想选择。更多信息可以参考这个的博客 。

数据预处理

我们将在这里使用的数据集是从 Kaggle 下载的,在 10 个标签或流派下各有大约 100 首歌曲。每首歌曲时长 30 秒。如前所述,这个数据量对于训练 LSTM 模型来说要少得多。为了解决这个问题,我将每个音频文件分成 10 段,每段 3 秒长。因此,每个标签下的歌曲数量现在是 1000,这是训练模型以实现良好准确性的合适数量。

现在我们已经准备好了数据,我们需要提取适合于输入我们网络的特征。特征提取将通过使用 MFCCs 来完成。Librosa 用于从每个音频片段中提取特征。我们创建一个字典,以流派的标签或类别作为关键字,从所有 1000 个片段中提取的所有特征作为该标签下的特征数组。一旦我们在一个循环中对所有 10 个类别都这样做了,我们就把字典转储到一个 JSON 文件中。因此,这个 JSON 文件成为我们的数据集,模型将在这个数据集上进行训练。

转到数据集预处理的编码,我们首先定义段的数量和每个段的采样率。为了知道歌曲的回放速度,需要采样率。在这里,我们对每一段都保持不变。

dataset_path = "genres"
jsonpath = "data_json"sample_rate = 22050
samples_per_track = sample_rate * 30
num_segment=10

然后,我们创建一个循环,在这个循环中,我们打开每个流派文件夹中的每个歌曲文件,并将其分成 10 个片段。然后,我们提取每个片段的 MFCC 特征,并将其添加到字典中的流派名称(也是文件夹名称)下。

def preprocess(dataset_path,json_path,
               num_mfcc=13,n_fft=2048,hop_length=512,
               num_segment=5):
    data = {
            "mapping": [],
            "labels": [],
            "mfcc": []
    } samples_per_segment = int(samples_per_track / num_segment)
    num_mfcc_vectors_per_segment = math.ceil(samples_per_segment / 
                                             hop_length) for i, (dirpath,dirnames,filenames) in   
            enumerate(os.walk(dataset_path)): if dirpath != dataset_path:
            #Adding all the labels
            label = str(dirpath).split('\\')[-1]
            data["mapping"].append(label)
            #Going through each song within a label
            for f in filenames:
                file_path = dataset_path +"/" + str(label) + "/" + 
                            str(f)
                y, sr = librosa.load(file_path, sr = sample_rate) #Cutting each song into 10 segments
                for n in range(num_segment):
                    start = samples_per_segment * n
                    finish = start + samples_per_segment
                    #print(start,finish)
                    mfcc = librosa.feature.mfcc(y[start:finish], 
                           sample_rate, n_mfcc = num_mfcc, 
                           n_fft = n_fft, hop_length = hop_length)
                    mfcc = mfcc.T #259 x 13 #Making sure if
                    if len(mfcc) == num_mfcc_vectors_per_segment:
                        data["mfcc"].append(mfcc.tolist())
                        data["labels"].append(i-1)
                        print("Track Name ", file_path, n+1) with open(json_path, "w") as fp:
        json.dump(data, fp, indent = 4)

上述脚本将创建线段并提取要素,然后将要素转储到 data_json.json 文件中。

训练模特

LSTM 用于训练模型。但在我们建立模型之前,我们必须将模型加载到我们的程序中,并将其分为训练和测试。这是通过打开我们在上一节中创建的 JSON 文件并将其转换成 numpy 数组来实现的,以便于计算。这个方法如下面的代码片段所示。

def load_data(data_path):
    print("Data loading\n")
    with open(data_path, "r") as fp:
        data = json.load(fp) x = np.array(data["mfcc"])
    y = np.array(data["labels"]) print("Loaded Data") return x, y

加载数据后,我们准备数据,并分成训练集和测试集,如前所述。这是通过使用 sklearn 的 train_test_split 函数来完成的。该函数如下所示。

def prepare_datasets(test_size,val_size): #load the data
    x, y = load_data(data_path) x_train, x_test, y_train, y_test =  
    train_test_split(x,y,test_size = test_size)
    x_train, x_val, y_train, y_val = 
    train_test_split(x_train,y_train,test_size = val_size) return x_train, x_val, x_test, y_train, y_val, y_test

接下来,使用 tensorflow 创建 LSTM 网络。这里,我们创建了一个 4 层的 LSTM 网络,包括两个隐藏层。下面的代码片段显示了网络的创建。

def build_model(input_shape): model = tf.keras.Sequential() model.add(tf.keras.layers.LSTM(64, input_shape = input_shape)
    model.add(tf.keras.layers.LSTM(64))
    model.add(tf.keras.layers.Dense(64, activation="relu"))
    model.add(tf.keras.layers.Dense(10,activation = "softmax"))
    return model

我们将模型初始化为序列,并添加一个具有 64 个神经元的输入层,一个隐藏层,一个密集 LSTM 层和一个具有 10 个神经元的输出层,因为有 10 个流派。输入层的大小取决于我们作为参数“input_shape”传递的 MFCC 系数的大小。您可以尝试更多的隐藏层,并测试准确性。

一旦定义了所有的方法和函数,就该调用它们并训练我们的分类模型了!

if __name__ == "__main__": x_train, x_val, x_test, y_train, y_val, y_test =     
    prepare_datasets(0.25, 0.2) input_shape = (x_train.shape[1],x_train.shape[2])
    model = build_model(input_shape) # compile model
    optimiser = tf.keras.optimizers.Adam(lr=0.001)
    model.compile(optimizer=optimiser,
                  loss='sparse_categorical_crossentropy',
                  metrics=['accuracy']) model.summary()
    model.fit(x_train, y_train, validation_data=(x_val, y_val), 
                                     batch_size=32, epochs=50)
    model.save("model_RNN_LSTM.h5")
    print("Saved model to disk")

首先,我们调用“prepare_datasets”函数,并传递测试日期百分比和验证数据百分比。验证数据是训练数据的一部分,模型不是用它来训练的,而是用它来验证模型。验证集告诉我们,在训练完成后,数据是否表现良好。

接下来,我们调用“build_model”函数来构建 are LSTM 网络并编译它。编译用于添加优化器(定义学习率)和损失计算功能。这里,我们使用了分类交叉熵数学函数。你可以点击此链接这里 了解更多信息。

编译后,model.fit()用于在我们的数据上训练模型。根据您的硬件,培训可能需要大约 1 小时到 1.5 小时。我们不想为了测试模型而一直训练我们的模型,因此在训练之后,我们保存模型,以便我们可以使用保存的文件来预测我们的新数据。在训练结束时,您可以看到达到的精确度。

根据新数据预测

恭喜你!我们的模型已经被训练好了!现在是时候检查它预测不同歌曲并将其分类为不同流派的能力了。

在我们开始测试和预测新歌之前,我们必须定义这些常数。

###########################################################################
just_path = "genres/blues/"
song_path = "genres/blues/1.wav"
song_name = "1"
###########################################################################Constants which depend on the model. If you train the model with different values,
#need to change those values here too
num_mfcc = 13
n_fft=2048
hop_length = 512
sample_rate = 22050
samples_per_track = sample_rate * 30
num_segment = 10
############################################################################

如果你还记得,我们用 30 秒长的歌曲来训练我们的模型。因此,该模型将一次接受 30 秒的歌曲片段。为此,我们将要预测的输入歌曲分成多个 30 秒长的片段。这有三种不同的情况——歌曲长度小于 30 秒、歌曲长度等于 30 秒和歌曲长度大于 30 秒。对于长度小于 30 秒的歌曲,我们显示一条错误消息,说明没有达到最小值;对于长度大于 30 秒的歌曲,我们将整首歌分成多个 30 秒的片段,并将每个片段输入到模型中。以下片段是针对上述场景的。

#load the song
x, sr = librosa.load(song_path, sr = sample_rate)
song_length = int(librosa.get_duration(filename=song_path))
flag = 0
if song_length > 30:
        print("Song is greater than 30 seconds")
        samples_per_track_30 = sample_rate * song_length
        parts = int(song_length/30)
        samples_per_segment_30 = int(samples_per_track_30 / (parts))
        flag = 1
        print("Song sliced into "+str(parts)+" parts")
elif song_length == 30:
        parts = 1
        flag = 0
else:
        print("Too short, enter a song of length minimum 30 
        seconds")
        flag = 2for i in range(0,parts):
        if flag == 1:
            print("Song snippet ",i+1)
            start30 = samples_per_segment_30 * i
            finish30 = start30 + samples_per_segment_30
            y = x[start30:finish30]
            #print(len(y))
elif flag == 0:
            print("Song is 30 seconds, no slicing")

接下来,我们加载保存的模型,并定义不同的类别或流派。该模型将预测一个从 0 到 9 的数字,每个数字将代表训练期间定义的流派。

model = tf.keras.models.load_model("model_RNN_LSTM.h5") classes = ["Blues","Classical","Country","Disco","Hiphop",
                "Jazz","Metal","Pop","Reggae","Rock"]

该模型为输入歌曲的每个片段预测某种风格。组合了特定输入歌曲的所有切片片段的所有预测的预测最多的流派给出了最终的预测。例如,如果给定长度为 120 秒的歌曲作为输入,它首先被分成 3 个各 30 秒的片段,并且每个片段作为预测特定流派的模型的输入。平均预测次数最多的类型是整首歌的类型。对于预测,我们再次提取每个片段的 MFCC 特征,然后调用“model.predict()”来获得预测。

for n in range(num_segment):
            start = samples_per_segment * n
            finish = start + samples_per_segment
            #print(len(y[start:finish]))
            mfcc = librosa.feature.mfcc(y[start:finish], 
            sample_rate, n_mfcc = num_mfcc, n_fft = n_fft,   
            hop_length = hop_length) mfcc = mfcc.T
            mfcc = mfcc.reshape(1, mfcc.shape[0], mfcc.shape[1])

            array = model.predict(mfcc)*100
            array = array.tolist()#find maximum percentage class predicted
class_predictions.append(array[0].index(max(array[0])))occurence_dict = {}
for i in class_predictions:
            if i not in occurence_dict:
                occurence_dict[i] = 1
            else:
                occurence_dict[i] +=1max_key = max(occurence_dict, key=occurence_dict.get)
        prediction_per_part.append(classes[max_key]) prediction = max(set(prediction_per_part), key = prediction_per_part.count)
print(prediction)

现在你知道 Spotify 如何为你分类你的音乐了吧!希望你喜欢读这篇文章。感谢您的阅读。

打破深度学习中的对称性

原文:https://towardsdatascience.com/breaking-symmetry-in-deep-learning-fa5c67270b1d?source=collection_archive---------39-----------------------

在 L 层深度学习模型中将权重初始化为零矩阵可以导致成本降低,但权重不变。这篇文章讲的是深度学习中一个美丽却至关重要的术语“打破对称”。

照片来自 Unsplash,作者 Ellicia@ellicia_

T 深度学习算法的准确性让我们所有人着迷。每个领域都会不时地使用深度学习模型,无论是自动驾驶汽车、人工智能、语音到文本转换、图像识别、情感分析,还是更多。深度学习改善了许多问题的现状。但这些都是非常复杂的技术,仍处于开发阶段。

由于总是有一个起点,趋势表明,大概所有的深度学习指导者都是从“逻辑回归作为神经网络”开始的,这构成了深度学习的基本原理,它的单层深度学习模型使用交叉熵作为代价函数和梯度下降算法来更新权重。现在,我已经间接地提到了这篇文章的所有先决条件。

有一个假设非常小,就像埋在沙子里的铁钉一样,通常会被忽略,即我们将权重初始化为零。当我们处理单层神经网络时,这个假设仍然有效。其中不包含任何隐藏层。

让我们考虑著名的泰坦尼克号数据集问题,我们需要预测谁幸存下来,给定他们的某些特征。我们将不使用原始数据集,而是使用准备好进行训练的干净数据集。

案例 0:单层深度学习模型

因此,让我们使用激活函数为 sigmoid 函数的单层深度学习模型来预测谁在泰坦尼克号上幸存下来。这是一个逻辑回归,但是具有使用梯度下降算法的反向传播步骤和 0.001 的学习率。

################# WEIGHTS ARE INITIALIZED TO ZERO ##################
W = np.zeros((1,X.shape[0]))
b = np.zeros((1,1))################# WEIGHTS ARE INITIALIZED RANDOMLY #################
W = np.random.randn(1,X.shape[0])
b = np.zeros((1,1))################### ONCE WEIGHTS ARE INITIALIZED ###################
## dict for storing costs
ini_single = {}irts = 1000
while irts > 0 :
    irts = irts -1
    ## Forward Propagation
    Z = np.dot(W,X) + b
    A = sigmoid(Z)## Cost estimation
    logerror = -(np.multiply(Y, np.log(A)) +  np.multiply(1-Y, np.log(1 - A)))
    cost = logerror.sum()/m
    ini_single[1000-irts] = cost
    print('The cost of the function is: ' + str(cost))

    ## Backward Propagation
    dZ = A-Y
    dw = np.dot(dZ,X.T)/m
    db = np.sum(dZ)/m## Updating Weights    
    W = W - 0.001*dw
    b = b - 0.001*db

一旦我们执行了代码,我们就可以为两种权重初始化技术生成单层深度学习模型的成本与迭代次数。因此,我们可以说在几次迭代之后,两种权重初始化技术趋向于相同的成本,但是初始化为非零的权重最初具有较低的成本。

titanic 数据集的单层深度学习模型(作者发表)。

单层的结果是令人满意的,因为两种技术在一些迭代之后收敛到相同的成本。现在,让我们在模型中引入一个隐藏层,将权重和偏差初始化为零。

情况 1:两层深度学习模型,权重初始化为零矩阵

## dict for storing costs
ini_zero = {}## initializing weights of a 2 layer Deep Learning model as zero matrix.
W1 = np.zeros((4,X.shape[0]))
b1 = np.zeros((4,1))
W2 = np.zeros((Y.shape[0],4))
b2 = np.zeros((Y.shape[0],1))irts = 10
while irts > 0 :
    print('================ iteration number: ' + str(n-irts) + '================')
    irts = irts -1
    ## Forward Propagation
    Z1 = np.dot(W1,X) + b1
    A1 = np.tanh(Z1)
    Z2 = np.dot(W2,A1) + b2
    A2 = sigmoid(Z2)## Cost estimation
    logerror = -(np.multiply(Y, np.log(A2)) +  np.multiply(1-Y, np.log(1 - A2)))
    cost = logerror.sum()/m
    ini_zero[n-irts] = cost
    print('The cost of the function is: ' + str(cost)## Backward Propagation
    dz2 = A2 - Y
    dw2 = np.dot(dz2, A1.T)/m
    db2 = np.sum(dz2, axis=1, keepdims = True)/m
    derivative = 1 - np.tanh(Z1) * np.tanh(Z1)
    dz1 = np.multiply(np.dot(W2.T, dz2) , derivative)
    dw1 = np.dot(dz1,X.T)/m
    db1 = np.sum(dz1, axis=1, keepdims = True)/m## Updating Weights    
    W1 = W1 - 0.01*dw1
    b1 = b1 - 0.01*db1
    W2 = W2 - 0.01*dw2
    b2 = b2 - 0.01*db2

如上所述,这是一个两层深度学习模型,其中隐藏层的激活函数是 tanh ,输出层的激活函数是 sigmoid 函数,学习率等于 0.01。

如果我们仔细检查,那么成本在下降,但权重 W1 和 W2 的值保持不变。W 的无变化在深度学习中被称为对称。将权重初始化为零会给模型造成混乱,这就是为什么需要随机初始化权重,因此打破了对称性。

当权重初始化为零时,10 次迭代的成本、W1 和 W2 的值(由作者发布)。

但是为什么成本在变化呢?敏锐的观察表明,W 保持为零,但成本仍在下降。同样的问题让我很开心,现在我有了答案。改变成本的原因是“b2”,即输出层的偏差。对于梯度下降的第一次迭代,所有的预测都是相同的,但是我们发现:

dZ2 = A2-Y 其中 dZ2 是代价函数相对于 Z2 的偏导数, A2 是输出层的输出, Y 是目标变量的实际值。

如果我们找到 dZ2,很明显它对于泰坦尼克号这样不平衡的数据会有一个非零值。因此,在梯度下降的迭代过程中唯一改变的参数是 b2,这是成本降低的原因。这也说明了梯度下降算法有多厉害。

现在,如果我们以非零的方式初始化权重,那么让我们看看会发生什么。

情况 2:两层深度学习模型,权重初始化为非零

## dict for storing costs
ini_nonzero = {}## initializing weights of a 2 layer Deep Learning model as randmon value matrix.
W1 = np.random.randn(4,X.shape[0])*0.01
b1 = np.zeros((4,1))
W2 = np.random.randn(Y.shape[0],4) *0.01
b2 = np.zeros((Y.shape[0],1))irts = n
while irts > 0 :
    irts = irts -1
    ## Forward Propagation
    Z1 = np.dot(W1,X) + b1
    A1 = np.tanh(Z1)
    Z2 = np.dot(W2,A1) + b2
    A2 = sigmoid(Z2)## Cost estimation
    logerror = -(np.multiply(Y, np.log(A2)) +  np.multiply(1-Y, np.log(1 - A2)))
    cost = logerror.sum()/m
    ini_nonzero[n-irts] = cost
    print('The cost of the function is: ' + str(cost))## Backward Propagation
    dz2 = A2 - Y
    dw2 = np.dot(dz2, A1.T)/m
    db2 = np.sum(dz2, axis=1, keepdims = True)/m
    derivative = 1 - np.tanh(Z1) * np.tanh(Z1)
    dz1 = np.multiply(np.dot(W2.T, dz2) , derivative)
    dw1 = np.dot(dz1,X.T)/m
    db1 = np.sum(dz1, axis=1, keepdims = True)/m## Updating Weights    
    W1 = W1 - 0.01*dw1
    b1 = b1 - 0.01*db1
    W2 = W2 - 0.01*dw2
    b2 = b2 - 0.01*db2

这里,我们已经通过正态分布随机初始化了权重,并改变了权重,但没有改变偏差,学习率也是相同的,但差异是巨大的

当权重被初始化为非零时,10 次迭代的成本、W1 和 W2 的值(由作者发布)。

这是权重初始化有多重要的明显区别。但是敏锐的观察者会注意到偏差仍然初始化为零。正如我们已经看到的,梯度下降对偏差有直接影响,因此它们可能会也可能不会初始化为零。这不会像一个权重初始化为零那样产生巨大的差异。

另一个观察结果是,我们将权重乘以系数 0.01(恰好等于学习率),以确保权重较小。如果权重足够大,并且我们使用类似 sigmoid 或 tanh 的激活函数,那么初始斜率(激活函数中的输入值很大)将会非常小。因此,性能会很好,但需要时间来达到最佳结果。

让我们运行这两个代码(案例 1 和案例 2)3000 次迭代。

3000 次迭代的成本与迭代次数(由作者发布)。

这表明情况 1 和情况 2 将在一些迭代之后收敛,但是在大多数情况下,在该迭代次数下,将发生数据的过度拟合。因此,最好选择第二种情况,在这种情况下,我们可以在更短的时间内获得结果,并且过度拟合的可能性也最小化。

总结

审视微小的步骤是令人钦佩的,因为它们可以创造巨大的差异。

初始化权重的一小步就能产生这样的差异,但重要的是要注意偏差仍然初始化为零。通过欣赏这一点,我们可以节省时间和巨大的数据问题,如过度拟合。完整的代码文件可以在这里找到。

用 MCMC 破解 Python 中的 Enigma 代码(漫威主题)

原文:https://towardsdatascience.com/breaking-the-enigma-code-in-python-with-mcmc-marvel-themed-9ceb358dd8ae?source=collection_archive---------25-----------------------

一台谜机。来源

知识就是力量。这条规则几乎可以应用于任何领域,但可以说它从来没有比战争时期更有意义。预测你的敌人下一步行动的能力同样困难,因为这是值得的,如果你能提前阅读他们的计划,这项任务会变得容易得多。

这是第二次世界大战期间各方都知道的事情,纳粹德国为确保他们通信的隐私和安全付出了巨大的努力。一个主要的工具是“Engima”,这种机器可以通过简单的字母转换过程(例如,所有的“a”都变成了“z”)来安全地加密和解密他们的通信。

虽然加密过程很简单(至少以今天的标准来看),但对于盟军来说,找到正确的密钥来解密被截获的信息是一项艰巨的任务。更糟糕的是,这些按键每天都会切换,使得之前的所有努力都是徒劳的。当然,正如你可能知道的,艾伦·图灵和他的团队在布莱奇利公园遇到了挑战,这导致了计算的突破,并成为“人工智能”的基础。

然而,这篇文章不是关于图灵或他的方法(尽管他们有一些共同的品质)。这也不是关于解密纳粹通讯。相反,我们将采取更古怪的策略,看看神盾局特工截获的一条(虚构的)神秘信息,这条信息来自曾进行种族灭绝的泰坦军阀灭霸(漫威电影宇宙最初 22 部电影的主角)。将扮演一个神盾局分析师的角色,他只有通过使用 Python 和他的马尔可夫链蒙特卡罗(MCMC)知识才能尝试解密代码并拯救宇宙。

如果你对真正的英格玛机以及它是如何被解密的感兴趣,我推荐你从这个数字迷视频开始:https://www.youtube.com/watch?v=G2_Q9FoD-oQ

"huvw !kzcq7nv3 qv3!hqv ,evwrhqv3rvq9qwi3qvhuv2cq,3vmk,7v,7zvbikb!kvhuvzqe3!7ufv3 qvmk,7nv,evuriv57r1nv!ev3rvieqv3 qvwreh!wvq73!3!qev57r17v,ev3 qv!7b!7!3uve3r7qev3rv1!mqv ,kbvrbv3 qvi7!;qceqvri3vrbvq9!e3q7wqverv3 ,3v3 qvr3 qcv ,kbvh,uv3 c!;qfvricv2cq,3qe3vw ,kkq72qv ,evtqq7vb!7z!72v3 qve3r7qev!7v3 !ev;,e3vi7!;qceqnvti3v7r1v3 quv,cqv1!3 !7vricv2c,emfv3 qvem,wqve3r7qnv57r1ev,kerv,ev3 qv3qeeqc,w3nvcqe!zqevr7v,e2,czfv,b3qcvkr5!evb,!kicqvr7vq,c3 nv3 rcv ,ev3,5q7v!3v,7zvmi3v!3v!7vrz!7ev;,ik3fv3 qvmr1qcve3r7qv!evr7vhrc,2fv!v ,;qvrczqcqzvcr7,7v3 qv,wwieqcv3rvcq3c!q;qv!3vbrcvhqnv!7vcq3ic7v!ve ,kkvzqe3cruv9,7z,cfv3 qvh!7zve3r7qv!evr7vq,c3 nv!vmi3v!3v!7v3 qve3,bbv!v2,;qv3rvkr5!nvti3v7r1v!v ,;qv q,czv3 ,3v!3v!evmr1qc!72v,vwutrc2v57r17v,ev3 qv;!e!r7fv3 qvcq,k!3uve3r7qv!evr7v3 qvwqkqe3!,kv q,zv57r17v,ev57r1 qcqfv!3v!ev1!3 v3,7qkqqcv3!;,7v!7v !evm,3 q3!wvwrkkqw3!r7nv2!b3qzv3rv !hvtuv3 qv,e2,cz!,7ev,b3qcv3 qvz,c5vqk;qevb,!kicqv!7v,wxi!c!72vbrcv3 qheqk;qefv3 qv3!hqve3r7qv!ev,kervr7vq,c3 nv1!3 v,v2crimvrbvercwqcqcenvwiccq73kuv2i,czqzvtuv3 q!cvkq,zqcnv3 qv,7w!q73vr7qfv3 qvk,e3ve3r7qnv3 qverikve3r7qnv ,evuq3v3rvtqvbri7znvti3v!v ,;qvmi3vhuvb,;ric!3qvz,i2 3qcnv2,hrc,nvr7v3rv!3ev3c,!knv,7zve qv ,ev7r3vz!e,mmr!73qzvhqvuq3fvr7wqv,ve3r7qv!evwrkkqw3qzv!v1!kkvtqv,tkqv3rv ,c7qeev!3evmr1qcvie!72v,v2,i73kq3v!v ,;qvrczqcqzv3 qvz1,c;qevr7v7!z,;qkk!cfv3 qv3!hqvbrcvwreh!wvrczqcv!ev7q,cnv,7zv1 q7v!vwrkkqw3v,kkv3 qve3r7qev!v1!kkv rkzvi7!;qceqv!7vhuv ,7zefv i2ev,7zv5!eeqenvv3 ,7re"

以上是我们截获的神秘信息。这些字符是字母数字,来自英语,包括一些分散的标点符号。我们也注意到了 7、3、v 等常见字符,但是手工解决这个是没有希望的。幸运的是,研究生院教了我们关于 MCMCs 的知识,我们觉得它可能很适合这个问题。MCMC 算法有 7 个步骤,如下所示:

第一步 —选择一个随机的解决方案。

第 2 步 —将解决方案应用于问题。

第 3 步 —评估这种方法的效果如何。

步骤 4 —对溶液进行 1 次调整。

第五步 —应用新的解决方案解决问题。

第 6 步 —重新评估我们的解决方案。

步骤 7 (a) —如果新的解决方案具有更好的分数,它将成为当前的解决方案,我们从步骤 4 开始重复。否则:

步骤 7(b)-计算新解和旧解的比值,然后在 0 和 1 之间随机选择一个数字。如果比率超过该数字,则接受该解决方案。如果不符合,则拒绝该解决方案。不管怎样,我们从第 4 步开始重复。

注意,步骤 7 (b) 通过有时允许“更差”的解决方案最终提供更好的答案,允许探索更大百分比的潜在解决方案空间。接受这些“更差”解决方案的概率取决于它们有多差。这通常被称为“局部极小问题”。

然而,有一个问题:我们如何衡量解决方案的效果?我们需要一个经验分数来告诉我们两个解决方案中的哪一个更有可能是真正的解密消息。

为此,我们查看相邻的字母。例如,在加密的消息中,第一个字符串之一是“!kzcq7nv3”。我们可以计算在英语中,' k '跟在'!'后面的可能性有多大,或者“z”跟在“k”后面,依此类推。然后,如果我们随机改变一个字母,我们可以看到新的字母配对是更多还是更少可能来自英语单词。为了得到这些配对概率,我们将需要一个巨大的英语单词语料库——最好包括漫威单词,如复仇者联盟、灭霸或绿巨人。为此,我们可以抓取整个漫威维基(参见 GitHub ),并计算每个字母跟随另一个字母的频率。

Python 字典,包含漫威维基中“b”后面的字母的频率。

由此,我们发现字母配对“ba”出现了 41,943 次,而“bn”只出现了 141 次(“subnet”和“Kly'bn”,如果你想知道的话)。然后我们可以将这些计数转换成百分比。因为这些百分比往往很小,所以取它们的对数来使它们的值正常化是有意义的。这将把 0.0001%这样的值变成-4。现在我们有了每个字母配对及其各自对数似然性的字典,我们可以通过简单地将每个字母配对的所有对数似然性相加来评估任何解密消息的尝试。例如,如果我们评估字符串“hello ”,对数似然将是-8.6,而字符串“z9kk3”将是-32.6。这是因为在漫威维基(或任何英文文本)中,“他”远比“z9”更常见,等等。

假设我们现在有一个函数来评估任何潜在的解决方案,我们可以实现 MCMC 方法来尝试解密消息,代码如上。

我们从步骤 1 开始,随机选择一个解决方案,并评估其得分情况。应用第一种解决方案会呈现以下“解密”消息:

“我;1vd5awx47。VX;。d x;vnq1c x;。c;x:x1!。x;我;8wxn。;h5n4n4at!5td5 我;”

这种可能性的对数为-11,396。然后,我们通过交换字母配对对解决方案进行一次更改,对模型重新评分,并确定这是否使解决方案更有可能或更不可能。冲洗并重复。到第 1000 次迭代时,分数显著提高到-4,792,解密后的消息现在为:

“fyalpimoc NHA sp as if aprtalef asea j lus afy AGC rsavmrrnoabumbimafya”。

它仍然远不可读,但空间看起来很自然,数字/不当的标点符号已经消失了。

到第 3000 次迭代时,该消息开始看起来几乎是英语,得分为-3891:

《儿童》作者:hreas 氏族,mulmil 作者:

在第 7000 次尝试时,我们可以读到信息的开头一行:

“我的孩子。是时候执行我的伟大计划,实现我的

直到第 24,000 次迭代,上面的句号才被逗号正确地切换,分数才收敛到其全局最优值-3,451。最终解决方案如下(警告 —漫威几部电影的部分剧透!):

My children, the time has come to execute my great plan and fulfil my destiny. The plan, as you know, is to use the cosmic entities known as the infinity stones to wipe half of the universe out of existence so that the other half may thrive. Our greatest challenge has been finding the stones in this vast universe, but now they are within our grasp. The space stone, knows also as the Tesseract, resides on Asgard. after Loki's failure on earth, Thor has taken it and put it in Odin's vault. The power stone is on Morag. I have ordered Ronan the accuser to retrieve it for me, in return I shall destroy Xandar. The mind stone is on Earth, I put it in the staff I gave to Loki, but now I have heard that it is powering a cyborg known as the Vision. The reality stone is on the celestial head known as Knowhere. It is with Taneleer Tivan in his pathetic collection, gifted to him by the Asgardians after the dark elves failure in acquiring it for themselves. The time stone is also on earth, with a group of sorcerers, currently guarded by their leader, the Ancient One. The last stone, the soul stone, has yet to be found, but I have put my favourite daughter, Gamora, on to its trail, and she has not disappointed me yet. Once a stone is collected I will be able to harness its power using a gauntlet I have ordered the Dwarves to make for me on Nidavellir. The time for cosmic order is near, and when I collect all the stones I will hold Universe in my hands. Hugs and kisses, Thanos

(感谢超级漫威极客鲍勃·加德为我写下这篇文章。)

你很快打印出这条信息,并迅速传给你的老板。几个小时后复仇者们就集合起来了,他们正在制定保护石头和击败灭霸的计划。你很快被提升为高级数据科学家,并获得了可观的加薪。

但是,根据漫威漫画,存在着具有无限可能性的无限宇宙。在所有这些中,你成功地破译了信息并击败了灭霸吗?为了测试这个假设,我们可以重新运行 MCMC 算法 100 次,看看它收敛到正确解的次数。

100 次独立重复的算法每次迭代的对数似然性。

从上面我们可以看到,它并不总是成功地达到全局最大值。事实上,我们可以看看最终对数似然的分布,看看这 100 次中有多少次我们接近最优。

100 次独立重复的最终对数可能性的频率。

从这里,我们发现在 100 个宇宙中,我们有 50%会正确地解密信息并拯救地球。但是其他 50 次呢?他们会看到什么信息?下表让你知道,根据算法收敛的分数,你会向你的老板尼克·弗瑞提出什么解决方案。

然而,很可能通过足够的迭代,大多数问题最终会找到正确的答案。

最后一个例外,它落入了一个几乎不可能恢复的陷阱。常见的字母几乎都被数字取代了。鉴于数字最有可能跟在其他数字后面,任何用字母替换单个字符的尝试都会遭遇对数似然性的灾难性下降,这几乎永远不会被接受。

就拿“孩子”这个词来说吧。在最低分的尝试中,它被解密为:. 46!?327、。如果该算法将【2】换成了正确的字符【r】,它将不会提高给定的分数【32】**【27】将会比漫威维基中的【3r】【r7】出现得更频繁。

一个简单的解决方案是在算法开始时重复步骤 1-3(选择全新的随机解决方案并评估它们)几次,然后继续执行其中最高的执行。通过包括这一点,并将迭代次数增加到 100,000 次,我们能够在 100%的时间内接近解决方案(1 或 2 个不正确的字符)。这不仅拯救了我们的宇宙,也拯救了所有发现自己处于同样困境的多节诗。

GitHub:https://GitHub . com/JackWillz/Projects/tree/master/MCMC % 20-% 20 enigma % 20 thanos

你已经看到文章的结尾了!我叫 Jack J,是一名将人工智能应用于竞技游戏和电子竞技的专业数据科学家。我是 iTero 的创始人。GGT23和jung . GG。你可以在 Twitter 上关注我,加入 iTero Discord 或者给我发邮件到 jack@itero.gg 。下一场见。

原载于https://itero.gg/blogs/.

打破游戏:潘德雷肯四梅林的崛起

原文:https://towardsdatascience.com/breaking-the-game-pendragon-four-rise-of-merlin-4d9acfe5fbd7?source=collection_archive---------36-----------------------

图片此处

在我的第一个潘德雷肯四人组博客中,我介绍了我为手机游戏《命运大令》( FGO)设置的多智能体强化学习(RL ),我列出了几个目标:

1)为游戏添加支持

FGO 没有玩家对玩家的方面,基本上所有的角色都可以使用,但它仍然有一个合理定义的元。在游戏中,元粗略地描述了比其他人更占优势的策略、角色或武器。在 FGO,元在很大程度上是由支持角色定义的,这些角色可以实现强大的/主导的策略。对于 FGO 的北美服务器来说,第一个真正的游戏突破和元定义支持是 2018 年底发布的 Merlin。

花之法师梅林是 FGO 版的魔术师/巫师/德鲁伊,大多数人都熟悉他是亚瑟王传说中的国王创造者。我说梅林在《FGO》中是一个超定义角色,因为他提供治疗来帮助团队承受敌人的伤害,提供无敌能力,充能团队的终极能力,如果这些还不够,他还可以极大地放大团队的伤害输出。

因此,如果标题和过去的几个段落还不足以作为铺垫,我决定将梅林作为一个角色添加到我的游戏环境中,以训练一个代理人使用梅林的能力。

2)使用某种多代理框架清除最终游戏内容

我暂时不打算正式尝试清除任何种类的后期游戏内容,但加入梅林让我不得不这样做,以便为代理人提供足够的挑战。所以我选择了一个相对高级的任务来复制成一个环境,并建立了一个机器人团队来完成它。

3)让这个项目的某个版本被某个地方接受为一个讲座。

谁知道这是否会发生,但我肯定会尝试。

梅林打破了游戏

梅林对 FGO 的介绍基本上打破了游戏规则,因为他加入了大量的治疗和伤害提升,使得原本具有挑战性的内容变得相当简单。当我把他编进代码,开始和他一起训练机器人团队时,我发现梅林也破坏了我的游戏环境。

Merlin 的技术实现

从技术角度来看,梅林和我以前的特工略有不同,他们都是伤害交易者类型的角色。我之前为他们制造的伤害制造者基本上都有影响他们自己或者整个团队的能力。因为每个角色有三种能力,所以每个角色的行动空间是 4,包括传球选项。然而,梅林最终的行动空间是 6。梅林的能力是全队增益,全队无敌,和有针对性的伤害提升。两个全队技能代表两个可能的动作,传球是第三个,目标伤害提升用三个可能的动作表示,动作空间为 6。有针对性的伤害提升是我的一个潘德雷肯特工新增加的,我基本上让一个技能有三种可能的行动,我让梅林特工选择谁是这个技能的目标,这样特工就可以选择对团队中的三个角色中的任何一个使用这个技能。

除了这些技能之外,梅林也是我添加的第一个终极技能,高贵幻象(NP)与伤害无关的角色。在我的自定义游戏环境中,当以前的角色将他们的 NPs 充能到 100%时,我会让他们只造成一些伤害,但对于梅林,我不得不做一些修改。梅林的 NP 被称为“阿瓦隆花园”,我实际上利用了我添加的机制来跟踪技能及其持续时间的效果。因此,每当梅林在游戏环境中将他的 NP 充到 100%时,他的 NP 就像技能一样应用到他自己和其他特工身上

直接后果

一旦我把梅林编码成一个角色,游戏环境能够处理他,我发现我有一个有趣的问题。在我最困难的游戏环境中,我的代理团队一初始化就赢了 90%以上的时间。从表面上看,这是一件坏事。我发现,在这种设置中训练的特工基本上什么都不做。他们不会使用技能,他们实际上永远不会做任何有趣的事情…相比之下,我以前的机器人做过的最好的事情是,一旦它们经过完全训练,胜率在 85-90%之间。

不同的是梅林。

原图此处

本质上,梅林作为一个角色提供了如此多的功能,机器人基本上可以做他们想做的任何事情,并且仍然获胜。他的 NP 阿瓦隆花园允许机器人有效地治疗团队受到的几乎所有伤害,梅林的伤害 buffs 允许代理团队赢得胜利,不管他们单独做了什么。在我的游戏环境的那个版本中,机器人团队的奖励基于胜利,胜利+1,失败-1。然而,在团队所做的一切都是胜利的情况下,得到强化的行动是最常见的。

每个角色有三种能力,每次任务允许使用一次。一个普通的任务持续 7-15 回合,所以大部分时间他们必须通过。所以有了这个设置,这意味着机器人学会了pass,因此什么也不做。

跟着梅林学习

我花了几天时间才想出如何处理这个问题,因为从技术上来说,机器人正在获胜,并且做得很好,但它们只是没有学会我认为有用的行为。我的一部分只是想继续让游戏环境变得越来越困难,但在某一点上,环境将不再像一个合理的 FGO 水平。所以训练环境将不再真正代表实际的比赛。

我在这里的突破来自于我重读安德烈·卡帕西的博客关于教一个 RL 代理玩乒乓的时候。

安德烈·卡帕西的博客很值得一读!

如果你还没有机会并且对 RL 感兴趣,它值得一读!无论如何,我在重读中注意到的是,Andrej 注意到我们应该做的是:

鼓励和劝阻大约一半的行为

这让我想到了我和梅林的情况,以及他造成的困难。在我目前的实现中,我没有贴现未来的奖励,只是根据输赢应用了一个简单的+1 和-1 奖励,所以博客中列出的一些方法并不适用。阻止一个代理人采取的大约一半的行动的概念确实如此,问题是如何阻止。

我做的第一件有效的事情是设置机器人必须获胜的回合限制,否则他们实际上会收到少量的负面奖励。例如,回合限制为 12,如果机器人在 10 回合中获胜,它将获得全额+1 奖励,如果它在 13 回合中获胜,它将获得-.25 奖励,如果它失败,它将获得全额-1 惩罚。这种奖励结构意味着机器人将会知道他们不能只是赢,而是必须快速赢。

然而,这种方法对机器人应该以多快的速度获胜施加了一个略微人为的限制。为了解决这个问题,我最终做的是让机器人必须比过去的自己赢得更快,才能获得全额奖励。

由于我已经跟踪了在 1000 个游戏周期内赢得的游戏数量,作为我训练指标的一部分,我开始记录这些游戏有多长,并使用一个 1000 个游戏周期内游戏的平均长度来设置为机器人团队收集全部+1 奖励所需的回合数。这意味着机器人总是试图比以前的自己赢得更快。

使用这种奖励方法,潘德雷肯四号学会了有趣的行为,即使是在加入梅林之后。所以,一旦我能够让机器人再次学习,并在我以前的游戏环境中获得 97%以上的胜率,我觉得是时候看看我是否可以训练机器人清除一些更难的 FGO 内容。FGO 任务的难度是根据通关团队的等级来评定的。到目前为止,我的大部分基准测试都是建立在一个中级任务的基础上的,这个任务在 40 级的农场中很常见。在 FGO,最高等级的任务实际上是 90 级,少数任务是 90+级,这通常是某种类型的 boss 战。我选择了一个 78 级的任务来构建更难的内容,这个任务被称为 FGO 故事中发生在塞勒姆女巫审判期间的绞架山上的处决地点。

行刑现场

虽然我可以选择一个不同的任务进行基准测试,但我选择 Gallows Hill Salem 任务的原因是因为它是游戏中我目前需要的一个名为“哭泣之夜之桩”的项目的最佳投放点。

fgo wiki

为了提升角色的属性,你通常需要收集特定的材料。我正在制作的一个角色需要哀嚎之夜的木桩,完全升级需要 216 根木桩,平均需要运行 1.5 次才能放下木桩。是的……这个游戏有很多关于农业的内容。

建立关卡

关卡的结构遵循了后来游戏 FGO 内容的标准格式。从第一波到第三波,有三个难度增加的级别。

第一波相当容易,三个敌人的总血量是 38000。高水平的团队可以很快解决这个问题。

第一波敌人

第二波通过增加更强壮的敌人增加了难度。作为快速基准,这一波的敌人有 70813 点生命值,一个敌人的生命值相当于整个第一波。

第二波敌人

现在进入最后一波,第三波。对于这个任务,wave 3 有 290,058 HP。所以是前两次浪潮总和的两倍多。如果你长时间困在上面,这个会变得棘手,因为拥有 192K HP 的主要敌人每 4 回合就会发动一次强大的攻击。在对我的潘德雷肯四代理进行基准测试时,随机初始化的团队通常会进行到第三波,然后在试图削减敌人的 HP 时陷入困境并死亡。

挥动三个敌人

所以在建造这个关卡的过程中,我想做两件事。首先,适当地调整等级,这样代理团队将必须通过一个真实的健康等级。第二,为了增加难度,我想让特工们在冲锋后用更强大的攻击来对付他们的敌人。

第一点,与我之前的困难等级相比,我在每一波都给敌人增加了更多的生命值。第一波有 30 点生命值,第二波有 55 点生命值,第三波有 140 点生命值,总共 225 点生命值,比我之前 180 点的最高值有所提高。

对于第二点,我增加了机制让敌人每 X 回合造成更多的伤害。例如,这最后一波每 4 回合造成正常伤害+ 10 点额外伤害。代理作为一个团队有 30 总生命值,所以第三波的长期战斗可以很容易地击败代理团队。

一旦新的机制和规格到位,是时候训练和基准潘德雷肯四。

培训和结果

在我的其他各种管道改进后,我能够将环境编码起来,并决定让代理人扮演的团队。

这支队伍将由两个伤害经销商组成,梅林作为支援角色。这两个伤害处理者是伊师塔,我之前把她编为一个有用的角色,还有一个新的伤害处理者,昵称是尼禄·卡斯特,我想用她,因为她在这个级别有很好的匹配。

伊师塔、梅林和尼禄施法者

一旦团队就位,我们就可以开始行动了!

大致按照我对潘德雷肯四号的训练协议,我让机器人玩,并监控它们的进展。请参见下面的运行示例。训练开始于前 20,000 圈的高探索和学习率,这就是为什么在图的第一部分没有改善。然后我开始每转 10000 转左右降低探索率和学习率,直到 70000。正如我们所希望的,在训练过程中,输赢百分比会增加(蓝色),而在同一时间内,输赢的回合数会减少。

超过 70,000 场游戏平均轮到赢(红色)从 9.75 开始,到 7 点左右结束。整体胜率从 45%开始,到 80%结束。

这些训练结果令人振奋,因为机器人似乎在学习,这对它们来说似乎是一个足够的挑战,因为胜率从来没有特别高。

所以在理论上这似乎是成功的,但现在潘德雷肯四正在玩更困难的内容,我想把它与自己玩的水平进行比较。

打破潘德雷肯四人的游戏

为了测试潘德雷肯四人组的表现,我让潘德雷肯四人组训练有素的特工和我自己在实际的 FGO 游戏中玩了 10 轮处决,我们都在相同的限制下玩。

  1. 技能只能使用一次
  2. 一旦一个角色的高贵幻象(NP)充能到 100%,它就必须被使用。
  3. 波浪必须从前面打到后面(没有重新瞄准)

结果如下表所示:

为了进行基准测试,我包含了随机初始化的代理的运行。我在他们的“平均值”旁边加了星号,因为随机初始化的代理人会在前两波中蹒跚而行,到达第三波,然后因为长时间停滞不前而死去。我发现看这个令人沮丧,而且恢复一个团队并继续玩下去需要花费资源,这似乎对我来说是一种浪费,所以我在五轮左右后就停止了。相比之下,训练有素的潘德雷肯四特工和我本人实际上都没有失去水平。

作为一个人类玩家,我仍然利用了更多的游戏信息,比如每个人的指令卡属于哪个角色,我认为这帮助我比机器人玩得更快。然而,看到纸上的机器人行为,我实际上认为它会比我的人类策略差很多,但令人惊讶的是,机器人策略工作得很好,而且实际上相当一致。

在改进《潘德雷肯四》的过程中,我一直在做的一件事是,我想尽可能地把我自己和我对如何玩这个游戏的信念从管道中移除。这主要是通过切换到+1 和-1 奖励的纯政策梯度方法,并设计新的水平,而没有通过伤害提升或其他机制激励某些行动。看看这里的结果,我认为这种努力是相当成功的。

对立的策略

不管使用什么策略,对于这样一个任务来说,真正获胜的唯一方法是使用强大的伤害处理 NPs 来清除它。我的基本策略是保存我团队的 NPs,只在第三波的时候发射,以尽快清除他们。而潘德雷肯四号使用了一种非常不同的策略,实际上每场比赛两次发射本队的 NPs。

我的方法

作为一名玩家,我倾向于通过为最后一波敌人保留技能和 NPs 来玩 FGO,因为他们通常相当强大,为最后的艰难对抗保留火力是有意义的。所以从游戏性的角度来看,我通常会在第一波和第二波中不使用任何技能,或者只使用一些攻击 buffs 来更快地通过这些波。然后在第三波,我用我的团队的效用技能充能 NPs 到 100%并且相对快地赢了。所以在整个关卡中,我依赖于使用每个伤害制造者的 NPs 一次。

潘德雷肯四国的方法

然而,潘德雷肯四所做的几乎完全相反。潘德雷肯四号使用它的实用技能来攻击伊师塔和尼禄的 NPs,并立即清除前两波攻击,同时保留大部分战斗技能用于第三波攻击。一旦到了第三波,它开始发挥它的攻击 buffs 和梅林的支持能力,以增加它的回合伤害,治疗,并有能力重新充电到 100%的 NPs,并通过在关卡中第二次使用尼禄和伊师塔的 NPs 来赢得胜利。

打破潘德雷肯四人的方法

理论上,我认为这在实际的 FGO 等级中不会很顺利,因为我认为代理团队会在第三波中被卡住而死亡。然而,我感到惊喜,觉得我有一些东西要向代理商学习。

潘德雷肯四回合 1 伊师塔冲向她的 NP 并清除波浪

早期游戏:第一和第二波

从游戏性来看,似乎潘德雷肯四号使用它的 NPs 立即清除了前两波,因为它降低了可能的变化,并且非常一致地让机器人清除了那些初始波。它可能避免的一个危险是,有几次我以正常方式玩游戏,但意外地让 NPs 充满电,这意味着我被迫在糟糕的时候使用这些 NPs,并在不利的情况下进入第三波。这些跑了 9 圈或更多才完成,这意味着我比潘德雷肯平均速度慢 4 倍。所以潘德雷肯四人组决定使用那些 NPs 和实用技能,立即否定了这种潜在的危险。

潘德雷肯四回合 2:尼禄施法者给她的 NP 充电,并用它来清除波浪

进入第三波时,特工们的 NPs 充电量相对较少,所以作为一个人类,我会很担心,因为团队 NPs 的充电量越低,他们在 NPs 恢复之前在危险的第三波上花费的时间就越长。事实并非如此,因为潘德雷肯四号能够有效地使用梅林。

游戏后期:第三波

一旦游戏进行到第三波,潘德雷肯四号使用梅林的阿瓦隆花园,该花园给予队伍 5 轮治疗,每轮增加 5%的 NP。加上他的全队攻击 buff,每回合增加 20%的 NP 电荷,这意味着他可以在接下来的一段时间里给全队 45%的 NP 电荷。这与他所提供的持续性和不可战胜性相结合,给了团队足够的支持来度过任何潜在的伤害。

3 回合攻击 buffs 和梅林的 NP“阿瓦隆花园”。

我之前提到过梅林被压制了,我希望潘德雷肯四号能学会以有趣的方式使用梅林。我希望但不能保证看到的是,潘德雷肯四号学会了使用梅林提供的全队无敌技能来阻挡第三波的强大攻击。我提到过第三波每 4 回合使用强力充电攻击。潘德雷肯四号在训练中学会了这种模式,并利用梅林的全队无敌成功阻挡了这些攻击(见下文)。在正确的时间使用该技能,结合梅林用自己的 NP 提供的治疗,意味着机器人可以在第三波战斗中相当安全地战斗,直到他们通常能够为他们的 NP 充电并获胜。

梅林特工使用无敌来抵消充能敌人的伤害。

结束语

在这篇文章中,分解潘德雷肯四人组正在学习的策略是一次有趣的经历,因为我还没有真正研究过我的经纪人已经开发的战术方面。正如我提到的,我特别高兴的是,他们开发了一种不同于我用来玩 FGO 的游戏风格,因为它展示了强化学习方法的一些乐趣,并让代理自由探索他们的环境和行动空间。

比人类玩家更容易使用能力的倾向是我在其他 RL 项目中看到的有趣的一点,比如 OpenAI 的 OpenAI Five。人们对 OpenAI 五个代理人的评论是,他们对使用长冷却时间的能力没有人类那样有所保留,他们倾向于像我一样玩,并抓住能力寻找更“最佳”的时间来使用能力或冷却时间。这也可能是如何激励代理更直接地消费资源而不是保存资源的函数,因为如果他们保存了资源,就不能保证你将来会使用它。这种短期规划看起来很有趣,但我也想知道如何才能让代理在能力使用上更保守。看看我是否能让代理人在本质上更保守的想法可能是我试图让代理人更像“我”,而不是他们所需要的。

虽然他们的策略与我的不同,但仍然相当有效,我对他们的结果非常满意。我认为向他们扔一些不同结构的任务会很有趣。例如,有一些任务有非常强大的最终 bosses,我认为在任务早期燃烧法术很难清除。因此,这将是一次有趣的测试,看看潘德雷肯四人组如何适应这种难度。

展望未来,我认为我的很多工作将会围绕着增加更难的内容和训练代理人,这些代理人也许可以更好地概括不同的任务。我在 OpenAI 的作品中看到的一个有趣的笔记是关于等级和代理统计的随机化,以促进对他们环境的更大探索,以及他们的代理被训练成彼此的完美“克隆”的方式。这提供了一种可能性,有三个代理共享相同的重量,但可以自由地扮演任何一组 FGO 人物和明确的任务。

用伊师塔的 NP 结束游戏。尼禄·卡斯特上一轮用了她的。

使用 Unsplash API 为应用注入活力

原文:https://towardsdatascience.com/breathe-some-life-in-to-power-apps-with-the-unsplash-api-450bb9473f1b?source=collection_archive---------45-----------------------

如何在 Microsoft Power Automate(又名 Flow)中使用 REST APIs 向您的 SharePoint 列表中添加随机但非常漂亮的图片

山顶上的新加坡樟宜机场。好照片让东西看起来更好。卡米尔·塔托尔在 Unsplash 上拍摄的照片

看 Power 应用教程有点像看草生长。油漆干燥时。当你等着水壶烧开的时候。令人失望的是,你的“带按钮的 SharePoint 列表”看起来是如此乏味,这足以让任何人去喝锁定的杜松子酒和滋补品。

不要烦恼。我们可以偷别人的照片,让他们看起来很漂亮。

电力应用程序很难看

下面是 SharePoint 的经典无个性画布应用。

评分一个为什么大家都觉得 Power Apps 很垃圾的例子(对不起微软)。它们只是看起来很单调。来自微软的教程来自 SharePoint 的画布应用。

不要误解我的意思,微软发布 Power 应用程序的速度比任何人了解它们的速度都快。他们可以做的事情并不缺乏,你可以延伸他们的长度。问题是,它们永远不会像你直接使用网络应用程序时那样好看(只要看看那些花哨的引导主题

好吧,一个快速解决办法是添加一些图像,所以让我们开始从互联网的许多摄影师抢夺他们。

游戏计划

SharePoint 列表图片字段

从微软教程中获取 SharePoint 列表,并添加一个“图片”类型的列。

添加图片栏。有时候,列名的灵感来之不易。

添加或更新列表中的项目时,用户需要输入 URL 和可选文本字段。该字段的一个经典用例是使用它来存储您刚刚用 Power Apps 相机控件放下的冰淇淋的图像 URL。

“图片”类型的 SharePoint 列表字段需要 URL

将非屏蔽 URL 放入列表

这个想法是,我们从 Unsplash 获得这些带有一些搜索参数的 URL。这将是很好的,如果这些是随机的(不要只是想一遍又一遍地相同的图片),如果它自动完成。

在微软的世界里,用 Power Automate 实现自动化是最容易的。计划是这样的。

使用 Power Automate 的更明亮、更令人兴奋的 Power 应用程序的计划

1 - 创造权力自动化流程。

当我们创建列表项时触发。

当我们在枯燥的应用程序 SharePoint 列表中创建新项目时,就会触发 Flow。

2 - 获得不光彩的形象。

使用 SharePoint 项目的标题从 Unsplash 中检索照片的图像 URL。

un splash 文档相当全面,可能有点让人不知所措。下面是一个使用 HTTP 连接器(注意这是一个高级连接器)搜索与 SharePoint 列表项相关的图片的示例。

Client-ID 后面的 xxxxx 应该替换为您的 Unsplash 应用程序访问密钥。为此,你需要在 Unsplash 上建立一个开发者账户,并注册一个应用程序。

3 - 解析 Unsplash API 返回的 JSON。

当我们更新 SharePoint 列表时,解析 JSON 允许使用响应中的字段。

Power Automate 可以通过“从样本生成”按钮为您找出 JSON 结构。将 Unsplash 响应的主体传递给该步骤的内容。

Generate from sample 将让 Power Automate 从示例响应中为您猜测模式。运行一个测试,从上面的 HTTP 请求中获得一个示例响应,或者使用API 文档响应(但是去掉注释)

用于响应 Unsplash HTTP 请求的 JSON 模式在这里的 GitHub 上。这需要根据 Power Automate 自动生成的模式进行修改,以便允许字段为空(例如,Unsplash 遗漏了 Instagram 关注者的数量)。通过为 JSON 模式中的每个值提供两种类型的数组(例如["string "," null"],而不仅仅是" string "),每个字段都可以为空。做一个查找和替换,否则,你会在那里很长一段时间。

4 - 使用 SharePoint REST API 请求 SharePoint 列表属性“ListItemEntityTypeFullName”。

恼人的是,你不能在 Power Automate 中直接访问 SharePoint 列表“图片”字段。它们只是没有出现在更新 SharePoint 项目步骤中。

没事的。我们可以使用 SharePoint REST API 来更新列表项,这里有更多的文档来解释 SharePoint API 是如何工作的。

我们可以使用 Power Automate 中的 SharePoint HTTP 请求步骤来访问 SharePoint API,与一般的 HTTP 请求不同,这不是一个高级连接器。在这一步中,我们需要一个对列表的属性的 GET 请求。不要忘记解析这个返回的 JSON。

获取 SharePoint BoringAppList 的 ListItemEntityTypeFullName 属性

5 - 更新 SharePoint 列表项目图片字段

SharePoint HTTP 请求再次提供了帮助。这一次发送了一个 POST 请求,将我们之前响应中的 Unsplash URL 粘贴到创建/修改的项目的图片字段中。

该请求中的标头非常重要。正文需要从 SharePoint 检索的 ListItemEntityTypeFullName 属性和从 Unsplash 检索的 URL。这里使用了小的URL(400 x400 ),照片描述放在 SharePoint 图像的可选文本中。

将请求发送到 SharePoint API,该 API 将取消屏蔽 URL 放入列表项中

一些副本和过去的友好位在 GitHub 的上。

计划来了!

不那么无聊的应用程序

正如你所看到的,一些图片会产生很大的不同。就我个人而言,我迫不及待地想记录我的下一个冰淇淋。

从 Unsplash 添加随机图片带来了一点色彩,并可能赢得那些讨厌的用户。在 Wise Technical,我们也制作适当的网络应用程序和数据平台,以最大限度地提高其商业效益。伸出手来!https://www.wisetechltd.com/

值得注意的琐事

  • 在 Unsplash API 上,每小时只能收到 50 个请求
  • 不要将 Sharepoint 项目更新的 POST 请求中的内容类型设置为 application/json(根据文档),而是将其设置为“application/JSON;odata=verbose "

布伦特福德足球俱乐部:足球中的金钱故事

原文:https://towardsdatascience.com/brentford-fc-the-moneyball-story-in-football-9726619d0d1a?source=collection_archive---------18-----------------------

在 Unsplash 上Fancy claim的照片

2020 年 8 月 5 日,布伦特福德踏上温布利体育场的草皮,在足球最丰富的比赛中迎战富勒姆。这是他们自二战后联赛恢复后退出以来最接近英格兰足球顶级联赛的一次。由于富勒姆边后卫乔·布莱恩的梅开二度,他们输掉了比赛,但这标志着一个过程的高潮,这个过程始于五年前他们升上英冠的时候。从那时起,接下来是一个谨慎的计划和执行,非常依赖数据。

从晋级者到中等俱乐部

自晋级以来的每轮布伦特福德联赛排名。

布伦特福德在冠军联赛中最引人注目的方面是他们从未卷入降级战。对于一支被提升的球队来说,在获得提升后的前几个赛季的大部分时间里都处于积分榜的下半部分是很常见的。但除了一次,布伦特福德从未在联赛中期到后期跌入红区。

布伦特福德的另一个独特之处是,在最初的几个比赛周之后,他们在一个赛季中的进展曲线几乎总是在上升。除了 2015-16 年,他们在 35-40 游戏周的范围内急剧下降,他们的蠕虫一直在上升。

布伦特福德的联赛成绩与 2014-15 赛季和 2015-16 赛季的升班马相比。

为了证明布伦特福德的进步是独一无二的,我们来看看 2014-15 和 2015-16 赛季的晋级者在锦标赛中的表现。除了几个赛季之外,布伦特福德在所有赛季中都超过了他们。

在这段时间里,一些球队也降级了,包括一个降级的俱乐部,然后升级,又降级。然而,狼队在 2017-18 赛季赢得了联赛冠军,这伴随着大量的支出。

让我们看看布伦特福德这些年的开销。

转移活动

布伦特福德自从获得晋级冠军后的转会活动。

看过布伦特福德在锦标赛中的表现后,如果他们认为这是在一些重大支出后发生的,那也不会受到指责。这是一个动词。除了 2014-15 赛季布伦特福德重返锦标赛获得第五名之外,布伦特福德一直通过转会活动创造利润。

布伦特福德最大的出售资产。上赛季英超联赛的前四名。

经过三年的谨慎销售和支出,俱乐部在联赛中获得了一些稳定性,之后他们在 2018 年创造了创纪录的 3146 万英镑,其中 19 年他们在同一赛季用 590 万英镑购买球员。因此董事会认为是时候挑战英超联赛了!许多球员来到格里芬公园参加 2019-20 赛季。但是你猜怎么着?即使在支出之后,他们也产生了一些利润。这是一些计划和执行。

英超回归的裂缝

布伦特福德在 2019-20 EFL 锦标赛中最活跃的足球运动员。

上赛季布伦特福德联赛中最活跃的 11 名球员让你对托马斯·弗兰克喜欢他的球队如何运作有一个公平的想法。大卫·拉亚是无可争议的一号门将,这是理所当然的。如果不是他在斯旺西的点球扑救,布伦特福德可能会在一周前出价 aideu 实现英超梦想。

弗兰克更喜欢传统的后防线,让平诺克和扬松组成防守组合,这样里科·亨利和亨里克·达尔斯加德就可以跑到侧翼。克里斯蒂安·诺尔高、马蒂亚斯·延森和约什·达席尔瓦组成了三人中场核心。

Benrahma 说,Bryan Mbeumo 和 Ollie Watkins 组成了他们著名的三前锋,我将在本文的稍后部分谈到。

2019–20 EFL 锦标赛每 90 分钟进球+助攻-点球(最少 2000 分钟上场时间)排名前几位的球员。

托马斯·弗兰克喜欢他的球队进攻和得分。这显示了他的三名前锋是如何相互支持并取得进球的。宝马突击队的本拉赫马、姆布莫和沃特金斯都在名单中占据显著位置,出场时间也很长。

2019-20 EFL 锦标赛顶级前锋线(至少打 1000 分钟)。

宝马前锋 3 在上个赛季为布伦特福德贡献了近 60 个进球,远远超过了其他球队的前锋线。这是在布伦特福德在本赛季早些时候将他们 2018-19 赛季的领先前锋尼尔·穆佩卖给布莱顿之后。姆伯莫在 2019-20 赛季开始时刚刚抵达。本·拉赫玛一年前就到了。front 3 在短时间内建立起来的凝聚力是惊人的。数据可能是布伦特福德当初购买它们的原因,但数据无法让合作关系产生共鸣,不是吗?

“我只知道一件事——当我们下个赛季开始时,我们将再次拥有一支非常强大的队伍,我们已经准备好了。”

作为一家出售俱乐部有它的麻烦,但这是布伦特福德屡试不爽的方式。如果布伦特福德在众多英超俱乐部的传言和联系中成功留住前锋奥利·沃特金斯和边锋赛义德·本拉赫马,人们将会非常惊讶。但布伦特福德最近的历史表明,托马斯·弗兰克在季后赛 1-2 输给富勒姆后的话不应该被忽视。

本文大部分数据收集自【fbref.com】stats bomb。使用WebHarvy工具从【transfermarkt.co.in】中刮出转账相关数据。在使用Tableau进行可视化之前,收集的原始数据在Python中进行预处理。

这里是相关知识库的链接:https://github.com/PritamGuha31/Brentford-Analysis

供需缺口对按需交付意味着什么?

原文:https://towardsdatascience.com/bridging-supply-demand-gaps-in-last-mile-delivery-companies-geospatially-657a98bb1e01?source=collection_archive---------61-----------------------

地理空间分析和洞察

根据您的需求和供应在不同地区的表现,本地化您的匹配算法

注意:在阅读本文之前,我强烈建议您阅读本系列的第一部分,其中包括了供需分析的基础知识:

[## 微移动公司如何在地理空间上提高资产利用率

这里有一个很好的问题,可以写在便利贴上,放在你的桌子上:“我们现在有什么资产是不…

blog.locale.ai](https://blog.locale.ai/how-micro-mobility-companies-can-increase-asset-utilization-geospatially/)

如今,在我们的手机上点食物、杂货、香烟甚至酒已经成为一种常态。如果你像我一样,你可能会在一天中最奇怪的时间点所有的东西!

对于按需公司(又名“X 的优步”),这主要是一个三方市场,匹配需求和供应是业务的核心,也是极具挑战性的。此外,现实世界引入了比模型中更多的变异,导致了更为严酷的结果。

当供需缺口存在时,我们要么失去订单,要么我们的骑手闲置——这两者都会导致亏损。但是,是什么导致了这些差距的存在呢?这可能是需求、供给或两者共同作用的结果。

案例 1:需求

订单丢失

由于骑手不在或他们出现在错误的位置而导致您随着时间的推移而丢失的订单数量。

订单速度

当你失去订单时,订单速度是怎样的?也就是说你的订单比平时多了还是少了?

案例 2:供应

闲散的骑手

闲置的乘客数量以及他们由于错误的位置或较少的需求而没有被利用的时间。

注意:空闲是一个时间点属性。因此,在进行历史分析时,我们需要分析指标“空闲会话时间”。

可用总供应量

当骑手空闲时,总骑手的可用性是什么样的?可用骑手的数量是增加了还是减少了?在对此进行历史分析时,我们需要分析指标“总会话时间”。

收到的订单与闲置供应。

解读差距的原因

在试图弥合差距之前,我们首先需要理解它们为什么会发生。如果订单丢失,可能是由于以下原因:

没有骑手

  • 错误的地点:如果我们失去了订单,这可能意味着骑手不在,这意味着他们要么都很忙,要么在错误的地点闲着。
  • 供应过剩:还有一种情况,我们满足了所有的需求,但却有过剩的闲置人员。或许有必要分析一下总供应量。

供需缺口。来源:Locale.ai

订单频率在下降

如果你在那天和那个时间收到订单的频率比平常少,那意味着你需要深入了解为什么会发生这种情况。

  • 类型:是所有类型的订单还是只有某一种订单?举例来说,是不是只有 A 类的订单量在下降?
  • 生命周期:在订单流程中,是否有一个特定的步骤会导致大量订单的减少?例如,结账系统或支付网关是否存在一些挑战,导致用户无法完成订单?

Locale.ai:监控供需缺口

订单未被分配

可能会有订单进来,但没有分配给骑手。如果发生这种情况,您使用的分配(或匹配)算法可能有问题。在这些情况下,最好向组织内部的相关人员提出这个问题。

在三方市场中,有时商店或餐馆可能会有分配问题。我自己也经历过很多因为问题出在餐厅而无法收到订单的情况。

要深入了解如何对商店或餐馆等静态位置进行分析,请查看:

[## 在地理空间上优化静态定位的性能

对于一个公司来说,静态位置是他们的业务实体,不会移动久而久之。例如,对于一个…

blog.locale.ai](https://blog.locale.ai/optimizing-the-performance-of-static-locations-geospatially/)

骑手们不接受命令

假设订单被分配给骑手,但他们不接受订单。这可能是由多种原因造成的。

  • 距离:他们不接受订单是因为取货距离很远吗?
  • 区域:他们不接受订单是因为他们不想前往提货地点吗?
  • 支付:他们取消是因为用户的支付方式不可取吗?

供需缺口和重新定位

骑手们正在取消订单

通常,我们都有过骑手在接受订单后取消订单的经历——尤其是一旦他们知道了交货地点。

  • 距离:他们取消订单是因为距离卸货点很远吗?
  • 区域:他们取消订单是因为他们不想前往卸货地点吗?
  • 始发地-目的地:是不是既不是始发地也不是目的地,而是路线?在这种情况下,大的激励措施也往往不起作用,因为骑手们只是不想穿越这些区域。

城市通常有隐形的墙,骑车人不愿意越过。这些墙在哪里?他们在一天中的什么时候最突出?

流动。来源

如前所述,供需匹配不仅仅是现在正在发生的事情。是关于流的。下一个需求会在哪里,它在不同的日子和不同的时间会如何变化?

理解最后一公里配送公司的流程非常重要。接下来哪个领域最有可能获得需求?离车手现在的位置有多远?

例如,对于一家最后一英里配送公司,研究流程表明,配送伙伴开始向市中心移动,到了晚上,他们开始搬出去,因为他们大多数人住在郊区。但他们需要向内发展,因为这是他们获得订单最多的地区。

外部洞察力

  • 兴趣点:另一个非常有趣的分析是分析供需如何受到不同兴趣点的影响,如学校、大学、商场或旅游目的地。
  • 外部事件:分析不同的外部事件(如下雨、大型音乐会、体育比赛、抗议活动)如何影响贵公司的需求和供应也是很有见地的。
  • 群组:群组是一组表现相似的用户、骑手或自行车。在不同的时间,我会失去什么样的用户和订单
  • 星期几?什么样的车友大部分时间都很闲?

关于 Locale.ai

Locale 是一个位置分析平台,这意味着我们可以将所有数据库和格式的原始纬度数据转换为有意义的见解,以便决策者可以就其地面运营做出非常精确的数据驱动型决策。

网络分析工具已经利用点击流数据帮助你改善了这些指标。然而,对于在地面上有移动资产的公司来说,不从地理空间的角度看问题是非常有害的!

区域设置:工作流模块

场所 ,我们正在创建通过地理空间分析提高单位经济性、每次交付成本和利用率的公司范例。如果你是一名增长型经理,希望提高用户的获取、保留和转化,请在此处联系我进行演示或通过LinkedInTwitter联系我。

原贴 此处

类似阅读:

* [## Carto vs Kepler vs Locale:哪个产品用于地理空间分析?

Carto、Kepler.gl 和 Locale 是公司在分析中用来做出地面决策的三个工具

blog.locale.ai](https://blog.locale.ai/carto-vs-kepler-vs-locale-which-product-to-use-for-geospatial-analytics-2/) [## 如何使用位置分析提高用户获取和转化

一家基于应用程序的送货公司可以随时随地将用户通过应用程序订购的任何东西送到用户的位置…

blog.locale.ai](https://blog.locale.ai/how-to-improve-user-acquisition-conversion-using-location-analytics/)*

弥合遗传学和神经网络之间的鸿沟

原文:https://towardsdatascience.com/bridging-the-gap-between-genetics-and-neural-networks-4fdb91032f4b?source=collection_archive---------36-----------------------

基于遗传数据构建和分析神经网络

融合神经网络与 DNA 双螺旋(对齐)的轶事——作者绘制

我最近进行了基因序列的研究工作。关于这个问题,占据我头脑的主要问题是:“对于这个目的,哪一个最简单的建议神经网络与遗传数据最兼容?”在查阅了大量文献后,我发现与这个主题相关的最【脚踏实地】而又最引人入胜的工作发生在yo shua beng io 的实验室。这篇名为饮食网:脂肪基因组学的瘦参数 及其的论文主要目标是将 3450 个个体的基因序列分为 26 个种族。那篇论文启发了我,在这里我想解释一下构建神经网络来解决这类问题的基础。理解这个博客,不需要生物学的背景知识;我将尝试涵盖大部分必要的部分,直接进入计算部分。**

动机

我们正面临着充满挑战的时代:新型冠状病毒 T21 病毒让我们对强大的自然力量束手无策。通过学习新工具:获得关于基因组数据的直觉,并探索哪些机器学习方法可以最好地概括这些数据;我希望我们可以联手起来,为更好的日子做出改变,或者至少使用神经网络令人难以置信的智能来做一些事情,除了开发娱乐应用程序,而是拯救我们的生活甚至我们的星球。

为什么我觉得遗传学如此吸引人?

你的基因不仅揭示了你的生物信息,还通过代表哪些主要部分存活了下来,揭示了你祖先的遗传历史。

换句话说,它是你家族的生物进化编码,甚至更多,根据达尔文进化论,有机生物(植物、动物等)集合的整体。)都有相同的遗传原理。

直觉

让我带您浏览其他类型的数据,如图像和句子,以了解基因数据的独特性。一方面,图像是具有相邻关系的二维数据(或者对于体积是三维的)。句子是多达大约一千个值的一维向量,具有通过无监督方式训练的句子的层级性质。

另一方面,遗传序列是至少几十万个值的一维向量(序列),在邻居之间没有明确定义的关系,并且远离具有预先训练的模型集。

因此,在图像处理中非常流行的 G aussian 平滑滤波器在这里是不相关的,以及视觉中所有预训练的模型(I mageNet, V GG,Res net**…)和自然语言处理(W ord2Vec,

为什么说是挑战?

想象一个由成千上万个基因样本组成的数据库。你需要找到一种方法,能够很好地泛化(准确率 90%以上)千万种组合的输入数据。神经网络可能是一个很好的选择,因为它以一种其他“经典”算法所缺少的方式利用完全连接的单元的能力,如 PCA、SVM、决策树,这些算法不单独管理数据。然而,构建最简单的网络体系结构需要在第一层的权重中有数千万个以上的自由参数。降维(避免过多的自由参数)是面对这个问题的一种方法;我们将在本博客稍后讨论它。

生物背景

为了把事情搞清楚,并且不对这个论坛的主要目的造成困难,我在这里只提出这个博客中需要的生物部分的一个高层次的观点。不用说,我们非常欢迎你进一步探索这些生物学话题。

什么是基因序列?

DNA 分子是由字母 A、C、G、t 代表的四种碱基组成的序列。序列的特定部分(即使位于远处)与表型相关。例如,最近的一项研究:“一场与可能来自蝙蝠的新型冠状病毒相关的肺炎爆发” 表明 ACE2 基因可能是新型冠状病毒病毒的宿主受体(表型)。这个例子和许多其他例子显著地展示了仅基于你的 DNA 就可以获得的有价值的信息(罪犯检测、匹配大麻品种、营养和个性化药物)。

什么是 SNP 基因型?

如今,我们比以往任何时候都更接近于获得几乎全部的人类基因序列。然而,我们还远远没有涵盖它的全部。单核苷酸多态性 SNPs 是基因组序列中特定的基因型位置,一般表示为 RS 【数字】。不同的人群有不同的序列不变量,但在家庭中可能是相同的(因此亚洲人看起来与欧洲人不同)。SNP 序列的分析将是贯穿本博客其余部分的关键点。

方法

在本节中,我描述了数据和两个主要的网络架构(以及另一个具有改进参数的网络,以克服机器学习中的一些主要问题)以及一些技术提示…

数据

相对于其他数据类型,医疗数据集很难找到,主要是由于隐私限制。有鉴于此, 1000 基因组计划 通过发布 3450 个人类 DNA 样本的公共可用数据集,即 26 个全球人口中每个人口的 315,000 个 SNP,实现了显著突破。下图显示了从 1000 个基因组数据中得出的直方图,描述了每个群体(种族)中个体的频率;每个群体的平均样本数约为 133 个遗传样本。

1000 个基因组人口分布(种族)

降维

如上所述,减少模型中自由参数的数量是首选(在我们的例子中,我们正在处理大约 3000 万个参数)。所提出的实现这一点的方法使用了另一个辅助网络,其位于输入每类直方图的判别网络之上(以无监督的方式计算的嵌入矩阵)。该网络的输出初始化判别网络的第一层的权重。嵌入矩阵是每个群体的归一化基因型直方图,其大小为 SNPs X [4x26],其中 4 代表{00,01,11,NA}(双等位基因),26 代表类别数(群体)。

生成每类直方图

下面描述这种嵌入矩阵的实现。

无论如何,这是他们的解决方案;我的解决方案是减少隐藏单元层的数量(参见架构部分)。我将这种新架构称为改进模型,它的一个好处是克服过拟合,这将在后面的结果部分讨论。

建筑

这篇博客比较了两个主要的网络。两个网络都由两个完全连接的隐藏层和一个 softmax 层组成,但第二个(见下图)包括一个辅助网络,它预测 d 判别网络的自由参数。a 辅助网络将 e 嵌入 m 矩阵作为输入,然后返回判别网络的第一个矩阵的权重(图 1)。

图 1:两个有区别的模型,无(上)和有辅助网络(下)。由作者绘制。注意辅助网络的嵌入维数是 10K(解释如下)。

在图 2 中可以看到该架构的详细描述:在每个完全连接的层之前,需要一个批规范,后面跟随着一个丢弃层。

图 2:内部网络架构

实施

我在 Pytorch 中从头开始写了这部作品的全部代码,它可以在公共 GitHub 资源库中找到,命名为“人类基因组”。以下是我认为与本论坛最相关的一些要点。

  1. 管理数据结构

为了获得客观的结果,我们生成五个折叠,每个实验一个,最后计算统计变量。

  • 分裂和洗牌

我们将 3.5K 样本分为训练(60%)、验证(20%)和测试(20%)。像往常一样,我们随机打乱数据并对值进行归一化:

**mu = x.mean(axis=0)
sigma = x.std(axis=0)
train[0] = (train[0] — mu[None, :]) / sigma[None, :]
valid[0] = (valid[0] — mu[None, :]) / sigma[None, :]
test[0] = (test[0] — mu[None, :]) / sigma[None, :]**

2。降维

生成嵌入矩阵分两步进行:第一步通过bincount() 生成每类基因型的直方图,第二步归一化该直方图。结果是维数减少了大约十个数量级。

**for i in range(n_features):
    if i % 5000 == 0:
        print("processing snp no: ", i)
    for j in range(n_targets):
        # generate for each snp , a histogram of four bins, one for each allel's option
        embed[i, j*n_genotypes: j*n_genotypes + n_genotypes] += \
            np.bincount(genome[i, labels == j].astype('int32'), minlength=n_genotypes)# normalizing the result for each class
        embed[i, j*n_genotypes: j*n_genotypes + n_genotypes] /= \
            embed[i, j*n_genotypes: j*n_genotypes + n_genotypes].sum()**

以下是特定 SNP 的每个类别的直方图示例:

特定 SNP 的标准化每类直方图

3。连接网络

两个网络(辅助网络和判别网络)都有独立的计算图,没有以任何方式链接。包含损失的区别网络的计算图不具有关于损失和嵌入张量之间的依赖性的信息。一种解决方案可以是用判别网的梯度值手动设置嵌入张量的梯度值,并在嵌入网上调用 torch . autograded . backward(),因为在嵌入网的计算图中,张量之间的依赖关系是已知的。

训练循环是:

  • 嵌入网中的正向传球
  • 设置有嵌入值的判别网络中第一个隐层的权重
  • 椎间盘网中的向前传球
  • 嵌入网和区别网中的后向
  • 更新参数

判别模型的第一个隐藏层中,我们用辅助网络(即嵌入层)的输出初始化其 3000 万个权重

**with torch.no_grad():
    self.hidden_1.weight.copy_(embedding)**

前进传球:

**embedding = emb_model(feat_emb) *# forward pass in embedding net*discrim_model.hidden_1.weight.data = embedding  
embedding.grad = discrim_model.hidden_1.weight.grad**

优化器应该更新两个网络的参数:

**params = list(discrim_model.parameters()) + list(emb_model.parameters())
optimizer = torch.optim.Adam(params**,** lr=learning_rate)**

向后传递:

因为我们设置了嵌入网的计算图,所以嵌入网和判别网之间的依赖关系是已知的。

**loss.backward(retain_graph=True) *# compute the gradient of the weights of the hidden layer in the embedding net* 
torch.autograd.backward(emb**,** emb.grad) # *backpropagation in the embedding net***

4。培训课程

丹尼尔·戈多伊在他的博客中解释了培训过程,我想根据我们与小批量的工作扩大他的工作范围。

  • 迷你批次和时代

函数:loss_fn(y**,** yhat)返回输入 y 中每个元素与目标 yhat 之间的均方误差(平方 L2 范数)。因为我们想要计算损失,我们需要将该值乘以批次大小,然后汇总每个小批次的所有返回值。

**train_loss += loss * batch_size**

最后,每个时期包含来自最后部分的累积值。因此,为了得到损失,我们需要除以该循环中的小批量数量。

**test_loss = test_loss / len(test_minibatches)**

我强烈建议您使用 提前停止 ,其基本原理是根据验证损失自动决定何时停止训练并保存最佳的最后模型结果。

框架

以下是一些我觉得有用(而且免费)的酷工具:

  • 神经网络库

我必须提到使用 Pytorch 作为最好的神经网络库的好处,从我的经验来看,与许多其他人相比,它在许多方面都是最好的。论文: “深度学习即服务框架的比较测量研究” 对框架进行了实证分析: TensorFlow、Caffe、Torch、Theano

  • 云上培训

您将受益于在云上训练您的模型并节省时间。 Ashwin De Silva 在他的博客中描述了你如何在本地工作,提交并推送至你的 GitHub 库,在上提交并运行你的培训。在我看来,花时间和精力用不同的参数来编写一些测试是值得的,比如隐藏单元的数量、丢弃值等等。

结果

回顾过去,我在分析结果的过程中经历了数据科学家中的一些已知困难,并发现与您分享,为您提供开发此类网络的动态行为的真实证据非常重要。在调查您的网络性能时,我发现以下言论是主要特征:

  • 失败

让我们从损失函数开始:这是网络性能的"面包和黄油",随着时间的推移呈指数下降。此外,很好地概括了的模型保持了类似于训练损失的验证损失。原因很简单:模型在处理看不见的数据时会返回更高的损失值。如果你遇到不同的情况,你的模型很可能是过度拟合过度拟合的解决方案可以是以下的一种或组合:首先是降低隐藏层的单元或移除层以减少自由参数的数量。正如我们上面讨论的,我们的改进的网络以及辅助的网络,为了这个问题前来救援。其他可能的解决方案是增加下降值或正则化。 Mazid Osseni ,在他的博客中,解释了不同类型的正则化方法和实现。图 3 显示了在处理所谓的 过拟合 问题之前(左图)和之后(右图)我的网络的更简单版本的损失函数。

我的解决方案是降低隐藏单元的大小(从 100 到 50 个单元)和增加第一层的下降值(从 0.5 到 0.8)。

图 3:没有(左)和有(右)辅助网络时的损失函数(橙色表示训练,蓝色表示验证)

  • 准确(性)

在每个体系结构中计算测试精度。令人惊讶的是,似乎克服过拟合或减少自由参数的数量并不能保证更高的精度。图 4 显示了三种架构的测试精度:请注意,尽管存在过拟合问题,但精度更高。

这种模型的第一层的自由参数的数量大约是特征(SNP)的数量×第一层的数量(~ 300kx100)。现在,我们使用一个辅助网络来预测那 300kx100 个自由参数。这个辅助网络将特征嵌入作为输入,这是每个特征 SNP 在患者中取值的向量的一些任意变换。问题是这种嵌入看起来像什么。如果我们遵循本文中考虑的嵌入,我们将对每类直方图进行 4x26 维嵌入,x 100 是第一层的数字单元。

图 4:测试精度(批量:64)和第一层的自由参数个数。

  • 批量大小

测试不同批量的性能是一项有趣的任务。沈世爱,在他的博客中,调查了批量大小对训练动态的影响。根据总的训练时间,可能因为数据的多样性,批量大小与训练时间成反比(图 6)。出于同样的原因,损耗与批量成正比(图 5)。

图 5:损失函数——不同批量的训练和验证(虚线)

  • 培训时间

图 6 清楚地示出了在训练时间方面使用不同批量大小的行为,两种架构具有相同的效果:更大的批量大小在统计上更有效,但是不能确保通用性。阅读论文: “训练更长,泛化更好:缩小神经网络大批量训练中的泛化差距” 了解更多关于泛化现象以及使用大批量保持训练时间完整的同时提高泛化性能的方法。

图 6:不同批量的总训练时间

注意改变架构对训练时间的影响(图 7)。在 1500 万个自由参数的情况下,训练时间明显低于辅助网络。

图 7:三种架构的纪元时间(批量:64)

  • 替代机器学习方法

我还将改进模型的性能与决策树方法进行了比较,特别是数据科学领域常用的光梯度增强机器。然而,在错误分类错误方面,性能超出了我们的极限(更多细节请参见附录)。

讨论

哪个是最好的型号?(一千美元问题)

在这篇博客中,我描述了两个主要网络:有和没有辅助网络,以及一个具有改进参数的附加网络。参数预测网络的好处是,当输入是非常高维度时,如在遗传序列中,它大大减少了模型第一层中自由参数的数量。

我展示了改变基本网络的参数如何在过度拟合方面产生更好的泛化能力。我在公开可用的 1000 个基因组数据集上验证了这些网络的方法,解决了基于 SNP 数据的祖先预测任务。这项工作证明了神经网络模型在处理样本数量与其高维度不匹配的任务方面的潜力,如 DNA 测序。

鉴于祖先预测任务中所达到的高准确度,我相信神经网络技术可以改进遗传数据分析中的标准实践。我希望这些技术能让我们解决更具挑战性的基因关联研究。

感谢

感谢卡米尔·罗什福尔-布朗热(蒙特利尔大学)在实施过程中给了我一些很好的建议。

对于那些想知道我有哪台计算机的人:我想说一些关于我的 MacBook Pro 的好话,16 GB 的内存,英特尔酷睿 i7 让我能够完成如此惊人的任务,给我留下了那些令人满意的培训时间(见结果部分),以及整个“计算机实验室”的体验(在冠状病毒关闭期间在家工作)。

附录

使用决策树的结果

除了我在这篇博客中强调的神经网络方法,我想提一下我使用梯度提升决策树 s 的体验结果。可以在这个 GitHub 资源库中找到实现。该算法的参数是:

**params = {
'task': 'train',
'boosting_type': 'gbdt',
'num_class': 26,
'objective': 'multiclass',
'metric': 'multi_logloss',
'num_threads': 36,
'zero_as_missing': True,
'verbose': 1
}**

结果表明,决策树的分类误差较高,解释原因超出了博客的范围。

图 8:使用决策树和神经网络的误差比较

关闭

亲爱的读者,感谢你阅读这篇博客;你的任何想法都将非常感谢;请随时给我发邮件(miritrope@gmail.com)或 Linkedin 。

弥合纸质地图和技术之间的差距

原文:https://towardsdatascience.com/bridging-the-gap-between-paper-maps-and-technology-363a19c2aa50?source=collection_archive---------55-----------------------

用现代网络和移动框架为学习地理的旧方法注入新的活力

为什么 Mapcaso ?

本质上,我喜欢地理。在过去的几年里,我一直在努力寻找一种方法,将老派的展开和使用地图的触觉乐趣带到电子时代。在纸质地图上画出旅行计划,或者标出路线,或者只是在风景中寻找图案,都会带来某种满足感。这个概念始于我想帮助孩子们学习地理,并通过在地图上画画来获得一点乐趣。我记得小时候,老师给了我们一张地图的轮廓,并让我们用颜色标出该国哪些地方有铁、棉花等资源。被生产出来。这对我的空间思考能力有很大的影响。

几经周折后,我开发了一个应用程序,将画画的欲望与我们最近获得的缩放和平移的本能(以及将表情符号应用于一切事物)结合起来😂). Mapcaso 是一个基于地图的学习平台,面向所有年龄段的孩子。它帮助孩子们通过在地图上涂鸦来学习地理和探索世界。成年人也可以玩得很开心,参加小测验,标记旅行计划,徒步旅行路线,或其他一百万的事情。

客户端应用、框架和库

我首先构建了一个客户端 SPA 应用程序。我选择的框架是 VueJS 。我真的很喜欢它快速构建原型的能力,我知道与其他 SPA 框架如 Angular 和 ReactJS 相比,它在开发人员生态系统和支持方面享有很高的声誉。对于地图框架,我知道我需要一个清晰的底图,具有良好的细节和熟悉感,这促使我选择了谷歌地图。我想要先进的绘图工具和更灵活的地图库,允许添加插件和其他图层类型。我选择带着小叶子跑。我还开发了 web 应用 responsive(这将在以后带来显著的回报),并使用了谷歌的材料设计框架和指南,使其易于为各种受众和设备所用。

空间数据库

有各种各样的数据库支持空间功能,如关系空间中的 Oracle 、 SQL Server 、 PostgreSQL 。Cassandra 、 CouchDB 和其他一些 NoSQL 数据库选项也可以,但是我决定使用 MongoDB 。我也不想花费大量时间来托管和准备扩展我的数据库基础架构。 mLab 似乎是自然的选择:它是 MongoDB 的数据库即服务平台。此外,MongoDB 与 GeoJSON(我用来存储和提供空间数据的格式)配合得很好。

服务器 API

在我用过的众多服务器端编程语言中,C#。Net 有严格的、强类型的支持,这在您编写可能被各种实体使用的强大 API 代码时非常有用。我唯一不喜欢的是。Net 应用程序过去需要在 Windows 服务器上运行。但值得庆幸的是,微软在过去几年里在拥抱 Linux 方面取得了惊人的进步,并推出了。Net Core 支持在 Windows 和 Linux 服务器上托管。这使得它成为开发 Mapcaso 的 API 的最佳选择。我使用亚马逊的 S3 服务来托管静态图片和其他静态资产。我还需要任务调度来管理发送用户简讯、运行数据库维护等等。为此,我依赖于 T21 自动气象站。

部署和托管

容器化使得跨不同环境的部署变得非常容易,并提供了应用程序良好的稳定性和可用性。Docker 和 Kubernetes 是最受欢迎的两个。但是 Visual Studio 有内置的 Docker 支持,所以我使用了 Docker 容器。最后,我在 Docker 容器中部署了我的 web 应用程序和 API,并通过亚马逊的 ECS 托管它们。整个过程帮助我了解了很多关于 DevOps 的知识,我非常尊重那些夜以继日保持应用程序平稳运行的工程师。

混合移动应用

在我有了最低可行产品后,我想转向移动。我是一个开发团队:所以构建一次并使用相同的代码库来部署移动应用程序是有意义的。幸运的是,我已经开发了我的 web 应用程序,可以很好地与桌面、平板电脑和各种手机屏幕兼容。我使用了 Cordova,这是一个用 HTML、CSS&JS 构建移动应用的包装器。我用 Cordova 包装了我的 VueJS 客户端项目,经过一些 Android 和 iOS 构建的努力,我能够成功地构建两个平台。然后我注册了谷歌和苹果的开发者项目,并在他们的应用商店上发布了 Mapcaso 应用。

结束语

构建和维护这个应用程序对我来说是一次很好的学习经历,我觉得这个应用程序的功能将成为广大受众传统教育的补充。尤其是现在,当许多孩子远程上课和在家学习时,我认为 Mapcaso 可以成为一种有趣和免费的方式,创造性地吸引您的孩子。虽然您可以保持内容的私密性,但您也可以通过在平台和社交媒体上创建和共享涂鸦和新的测验内容来回馈 Mapcaso 社区:帮助他人更多地了解您的国家、州或我们的世界!

让我们不要忘记,即使在这些艰难的时刻,这个世界也是一个巨大而神奇的地方。我们可以让我们的思想在虚拟的世界中漫游,变得有创造力并在线联系!

在谷歌 Play 商店获得免费的 Android 应用程序

在苹果商店下载获得免费的 iOS 应用程序

在脚本模式下,将您的 TensorFlow 培训带到 AWS Sagemaker

原文:https://towardsdatascience.com/bring-your-tensorflow-training-to-aws-sagemaker-with-script-mode-aba9e73aa36b?source=collection_archive---------37-----------------------

使用 Sagemaker 脚本模式节省深度学习计算成本!

介绍

我会尽量让这篇文章简单明了。首先,我们先从这种方法的一些利弊谈起。

Artem Sapegin 在 Unsplash 上拍摄的照片

优点:

  • 允许您以更低的成本运行您的培训工作!为什么?因为你可以仅仅为了编码而启动一个非常廉价的实例;然后,您可以有一个单独的 GPU 实例,它只在训练期间启动,然后在您的训练代码运行完毕后关闭。这意味着你只在模型训练中消耗 GPU 时间,而不是在你编码的时候!

CONS:

  • 任何事情都是一种交换,很少有新的优势没有新的劣势。在这种情况下,缺点是我们需要学习一些新的技能。假设你正在运行一个本地培训任务,你想把它带到 Sagemaker (也许你想在一个更大的 GPU 上运行),你想利用这个方法来降低成本,那么你将需要编写更多的代码来让这个方法工作。你可能还需要了解线路和事物是如何一起工作的。

您可以在一个代码更改较少的笔记本实例中运行您的培训,但是您的作业不会自动关闭(因为您在笔记本实例中执行所有操作)。所以这是一个权衡。要在笔记本实例中运行您的作业,请参见步骤 1 中的链接。

步骤 1:开始使用 Amazon Sagemaker

如果你以前从未使用过 Amazon Sagemaker 或 S3,我推荐你阅读我在 Amazon Sagemaker 上的第一篇文章,我会一步一步地向你展示如何简单地将数据加载到 S3 并运行一个笔记本实例。你可以在这里找到文章的链接。

步骤 2:启动一个廉价的笔记本实例。

当你遵循第一步的文章,你将会做一件不同的事情。我们将启动一个廉价的 CPU 实例,例如类似于 ml.t3.medium 的东西,而不是用 GPU 启动一个笔记本实例。

[## 亚马逊 SageMaker 定价-亚马逊网络服务(AWS)

有了亚马逊 SageMaker,你只需为你使用的东西付费。构建、培训和部署 ML 模型的费用由…

aws.amazon.com](https://aws.amazon.com/sagemaker/pricing/)

第 3 步:创建一个培训脚本,打开一个新的笔记本并运行您的作业。

一旦运行了一个廉价的笔记本实例,并且访问了 Jupyter,您将创建一个新的 python 脚本并打开一个新的 Jupyter 笔记本。

  1. 训练脚本-这个 python 文件是您将拥有训练代码的地方。
  2. 朱庇特笔记本——这将是我们的训练指挥官。这个笔记本是要告诉 Sagemaker 我们的训练代码在哪里,我们的训练数据在哪里,模型训练要什么样的机器。

朱庇特笔记本代码

这个笔记本可以很短,这取决于你想让它有多复杂。同样,这个笔记本将作为我们的训练指挥官。我在 GitHub 上有代码,你可以在这里查看。在这篇文章中,我将强调一些基础知识。

首先,我们需要从 SAGEMAKER 导入 TensorFlow。这是非常不同的,因为我们不是导入普通的 TensorFlow,而是导入一个允许我们启动 TensorFlow 容器进行训练的对象(即云中包含 TensorFlow 的容器)。

**from** **sagemaker.tensorflow** **import** TensorFlow

接下来是代码的核心。这是我们为培训工作指定一切的地方。

参数入口点指向我们的训练脚本。在这种情况下,我的训练脚本名为 jigsaw_train1_aws2.py ,位于我的训练笔记本的工作目录中。

参数 train_instance_type 接受一个字符串,该字符串标识我们想要训练什么类型的实例。在本例中,我指定了一个包含 GPU 的 ml.p2.xlarge 实例。

参数 output_path 表示我希望我的所有输出被转储到哪里。我指着我在 S3 的一个地点。(这将在我们的培训脚本中再次出现)

参数 train_instance_count 指定我们需要多少训练实例。在这种情况下,我只需要 1 ,因为我们没有使用分布式代码,例如 Horovod。

参数 framework_version 指定我们想要 TensorFlow 的哪个版本。(注意,Sagemaker 可能不支持 TensorFlow 的最新版本,所以请注意您指定的版本,并且不要太新;或者如果是,那就支持)

参数 script_mode 接受一个布尔值,在本例中为 True ,因为我们正在提供我们的训练代码。

estimator = TensorFlow(entry_point='jigsaw_train1_aws2.py',
                       train_instance_type='ml.p2.xlarge',
                       output_path="s3://jigsaw-toxic-mjy-output",
                       train_instance_count=1,
                       role=sagemaker.get_execution_role(), 
                       framework_version='1.11.0',
                       py_version='py3',
                       script_mode=**True**)

然后,如果我们想要提交我们的培训作业,我们只需要运行估算器。作为估算器的输入,我已经包含了一个关键字为“data”的字典,对应的值是一个包含我的数据存储在其中的 S3 位置的字符串。

data_s3 = 's3://jigsaw-toxic-mjy/'
inputs = {'data':data_s3}
estimator.fit(inputs)

在我们运行这个之前,我们需要确保我们的训练脚本已经准备好了。让我们快速回顾一下我们的培训脚本。

培训脚本代码

你可以在 GitHub 这里阅读我的完整训练脚本代码示例。我不打算回顾这篇文章中的所有内容,只回顾要点。

首先,我们需要能够访问我们的数据。我们使用 argparse 来获取我们在 estimator.fit(inputs) 期间传递的数据目录。我们可以将数据目录与我们在 S3 获得的训练数据的名称连接起来。一旦我们有了这个字符串,我们就可以像往常一样使用 pandas 来读取我们的数据。

import argparse
import pandas as pd
import osparser = argparse.ArgumentParser()parser.add_argument('--data', type=str, default=os.environ.get('SM_CHANNEL_DATA'))args, _ = parser.parse_known_args()data_dir = args.datadf = pd.read_csv(os.path.join(data_dir, 'train.csv'))

接下来,我们可以像平常一样运行我们的训练代码了!

最后,如果我们想要保存任何信息,我们需要将它保存到 TensorFlow 容器知道的特定目录中。那个位置是 /opt/ml/model/ 。保存到这个目录的任何东西,都将被保存到我们在 Jupyter 代码中指定的输出路径。

data_location = “/opt/ml/model/submission.csv” submission.to_csv(data_location, index=False)

结束了!

就是这样!一旦您准备好培训脚本,您就可以从头到尾运行您的 Jupyter 笔记本,并观看您的培训工作开始!

再说一次,当你完成后,我会删除一切!这包括你的 S3 桶,你的实例,一切;因为如果你把所有这些工作都放在 AWS 上,即使你不再运行任何东西,也要花钱!

你可以在 GitHub 这里找到我自己的脚本模式培训工作的例子。这个 repo 包含我的笔记本实例中的代码,因此,它是我的笔记本实例的快照。希望人们发现这是有益和快乐的学习!😄

带来深度神经网络杀死尖塔

原文:https://towardsdatascience.com/bringing-deep-neural-networks-to-slay-the-spire-a2971d5a5115?source=collection_archive---------13-----------------------

内部 AI

用 Keras 和 TensorFlow 预测战斗结果和评估卡片

斩杀尖塔是我最喜欢的视频游戏之一,结合了盗贼般的地牢爬虫和甲板建筑的元素。刚刚在大学最后一年完成了一门深度学习课程,我认为 Slay the Spire 将是我第一个机器学习项目的一个很好的平台。

甲板建造是一个很难解决的问题

选择将哪些牌添加到你的牌组中是《杀死塔尖》中最重要的战略决策之一。玩家需要添加好牌,移除坏牌,升级重要牌,以提高他们的牌组,并在一次运行中击败越来越难对付的敌人和老板。在不同的情况下决定最好的牌加入你的牌组是非常困难的,世界上最好的玩家仍然一直在努力知道什么是正确的选择。

各种敌人在斩杀尖塔。图片来源:斩杀尖塔不和

为了进一步增加评估哪张牌更适合加入你的牌组的问题,不同的牌对不同的敌人表现更好。通常情况下,攻击所有敌人的牌在与多个敌人的战斗中比与单个敌人的战斗中更好。此外,在整个游戏过程中,一副牌中的牌相对于其他牌的强度是变化的。例如,平庸的攻击卡通常是玩家在游戏早期艰苦战斗中的主要伤害来源,因此,相当有价值。然而,当玩家获得更好的伤害源时,这些相同的牌相对于玩家牌组中的其他牌要差得多。

可玩角色:铁甲,沉默,叛变,守望者。图片来源:斩杀尖塔不和

每个可玩的角色都有一套不同的 75 张独特的卡片,这些卡片可以以多种方式组合,创造出各种各样的牌组和玩法。如果玩家将一张牌添加到他们的牌组中,根据战斗中减少的平均伤害来评估这张牌,是一种相对于这些牌组创建牌组的公正方法。向玩家提供这个指标有助于他们在每个决策节点做出最佳选择。

介绍 Slay-I

Slay-I 是在 Steam Workshop 上提供的一个 mod,它可以预测你在 Slay the Spire 的战斗中会受到多少伤害,并根据战斗中减少的平均伤害来评估添加、升级和移除牌。这包括战后卡片选择,玩家可以从 3 张卡片中选择 1 张加入他们的卡片组,在营火和活动中升级卡片,在商店和活动中移除卡片。

预测这场战斗中受到的伤害与实际受到的伤害。作者图片

评估向牌组中添加一张新牌。作者图片

高级概述

Slay-I 的核心是一个模型,它根据玩家的卡片、玩家的遗物、玩家正在战斗的敌人以及其他一些特征来预测战斗中受到的伤害。接下来,我将解释这个模型如何用于评估卡片。

在训练和部署 Slay-I 模型时使用了三个主要组件:

  1. 将运行历史文件转化为训练样本的 Python 脚本( GitHub repo
  2. Google Colab 上的 Python 脚本,使用 Keras 和 TensorFlow 建立和训练神经网络( Colab 笔记本)
  3. Java mod 运行训练有素的模型,斩杀 Spire 玩家可以下载并运行他们的游戏( Steam Link )

作者的形象

创建培训示例

任何机器学习项目中最不性感的部分几乎总是数据预处理。但这很重要!

实验了运行历史文件的两个不同的数据集。第一个数据集来自于 Jorbs ,一个 YouTuber 和 Twitch streamer,被广泛认为是最好的 Slay the Spire 玩家之一。第二组数据来自 Spire Logs 网站,玩家可以上传他们的跑步数据并查看分析。

运行历史文件具有类似事件的格式:

// Example Run History File
{
  "damage_taken":[
    {"damage":7,"enemies":"2 Louse","floor":1,"turns":2},
    ...
  ],
  "campfire_choices":[
    {"data": "Combust", "floor": 6, "key": "SMITH"},
    ...
  ],
  "card_choices":[
    {"picked": "Clothesline", "floor":1, ...},
    ...
  ],
  "event_choices":[
    {"cards_removed":["Strike_R"], "floor": 22, ...},
    ...
  ],
  "items_purged":["Pain", ...]
  ...
}

单个训练样本是一轮比赛中一场比赛的数据。这些数据包括玩家牌组中的牌、玩家的遗物、玩家正在战斗的敌人以及其他特征。通过遍历运行历史文件的类似事件的格式来逐层重建运行,从而创建训练样本。

// Training sample
{
    "cards": [
        "Strike_R",
        "Strike_R",
        "Defend_R",
        "Defend_R",
        "Clothesline",
        "Iron Wave",
        "True Grit",
        ...
    ],
    "relics": [
        "Burning Blood",
        "Pen Nib",
        ...
    ],
    "max_hp": 82,
    "entering_hp": 82,
    "ascension": 20,
    "enemies": "Lots of Slimes",
    "potion_used": false,
    "damage_taken": 14 // Y-value used in training
}

经过处理后,Jorbs 数据集产生了 2 000 个训练样本,Spire Logs 数据集产生了 325 000 个训练样本。

编码输入

现在的问题是,如何对训练样本进行编码,以传入神经网络。max_hpentering_hpascensionpotion_used已经是数字(或布尔)。enemies是一个热编码。

使用改进的 one hot 方法对cardsrelics进行编码。每张牌都有一个热点编码,然后将热点向量相加,计算出每副牌中有多少张。同样的过程被用于文物。

注:升级卡被视为完全不同的卡。

# Used for cards vector and relics vector
def encode_list(list_to_encode, category):
  np_array = np.array(list_to_encode)
  encoder = OneHotEncoder(categories=[category], sparse=False)
  n_by_1 = np_array.reshape(len(np_array), 1)
  onehot_encoded = encoder.fit_transform(n_by_1)
  summed = np.sum(onehot_encoded, axis=0)
  return summed

编码后的cardsrelicsenemies和其他特征被连接成一个单一的向量以提供给模型。

np.concatenate((cards, relics, encounter, num_and_bool_data))

使用MaxAbsScaler对输入进行缩放,因此在缩放过程中不会丢失稀疏性。

max_abs_scaler = MaxAbsScaler()
X_train_maxabs = max_abs_scaler.fit_transform(x_train)
X_test_maxabs = max_abs_scaler.transform(x_test)

输出(战斗中受到的伤害)上限为-100 和+100,除以 100 可以将输出调整为-1 到 1 之间的值。

构建和训练模型

Keras 让构建深度神经网络变得轻而易举。添加脱层有助于减少过拟合。如果你想自己构建和训练模型,可以在这里找到 Google Colab 笔记本。

model = tf.keras.models.Sequential([
  tf.keras.layers.Dense(400, input_shape=(970,), activation='relu'),
  tf.keras.layers.Dropout(.2),
  tf.keras.layers.Dense(40, activation='relu'),
  tf.keras.layers.Dropout(.1),
  tf.keras.layers.Dense(1)
])model.compile(
  optimizer=keras.optimizers.RMSprop(learning_rate=.001),
  loss='mean_absolute_error'
)history = model.fit(X_train, Y_train, batch_size=32, epochs=5, validation_split=0.2)

使用平均绝对误差(MAE)作为损失函数有两个主要原因:

  1. 在数据集上,MAE 比均方误差(MSE)具有更低的验证损失。
  2. MAE 代表预测的平均误差。例如:“在这场战斗中,你将损失 7 HP +/- X HP”,其中 X 是平均绝对误差乘以 100。

评估模型

损失* 100 =平均损失误差

Jorbs 模型统计

  • 培训损失= 0.0718
  • 验证损失= 0.0767
  • 测试损耗= .0878

这意味着模型平均在战斗结果的+/- 9 HP 范围内。

Spire 日志统计

  • 培训损失= 0.0584
  • 验证损失= 0.0705
  • 测试损耗= 0.0679

这意味着模型平均在战斗结果的+/- 7 HP 范围内。

更大的数据集有 23%更好的测试损失!有趣的是,在 Spire Logs 数据上训练的模型,在使用 Jorbs 数据作为测试数据时(0.0758),比只在 Jorbs 数据上训练的模型(0.0878)有更好的测试损失。

关于统计的想法

  1. 由于游戏固有的随机性(有时称为 RNG ),多次使用相同的卡片和遗物进行相同的战斗可能会有许多不同的结果。这使得数据本身就有噪声,模型需要大量数据来弥补噪声。
  2. 对于 Jorbs 模型,没有足够的数据(970 个参数只有 2000 个训练样本)来弥补数据中的噪音。
  3. 根据 Jorbs 数据训练的模型预测的值非常接近 0。这可能是因为乔伯斯是一个非常优秀的玩家,他在很多战斗中只受到很少的伤害(或者治疗)。对于一般玩家来说,这不是一个准确的样本。

模型的后续步骤

模型有过度拟合的问题。一些可能的解决方案包括:

  1. 为卡片、遗物和敌人使用嵌入层。嵌入层可用于学习卡片之间的关系,并将卡片映射到向量。
  2. 获取更多(和多样化的)数据。

部署模型

Slay the Spire 是用 Java 8 开发的,所以在游戏中使用了 Java TensorFlow 2.x 绑定来部署训练好的模型。玩家可以下载并运行这个模型,看看这个模型如何预测他们在战斗中的表现!

模型预测在这场战斗中受到 5 点伤害。作者图片

评估卡片

现在我们有了一个模型,可以预测一套卡和遗物在不同的战斗中的表现,我们可以使用这些信息来评估一张卡有多好。卡牌是通过每场战斗的平均伤害来评估的,游戏中更重要的战斗(老板和精英)的权重更大。这是通过在行动中的每一场比赛中将该副牌与添加了该牌的副牌进行比较来完成的。

根据战斗中受到的平均伤害来评估牌。作者图片

同样的过程适用于评估移除卡和升级卡。

卡移除屏幕。正值表示要移除的牌是好的。作者图片

承认

感谢 Spire Logs 和 Jorbs 提供您的数据集。同时也要对 Spire #modding 社区的不和谐大声疾呼(特别是 Gk,他帮助了 mod 的用户界面)。如果你发现了一个 bug 或者有兴趣贡献的话,项目每个部分的所有代码都在 GitHub 上。

将非技术用户引入 JupyterHub

原文:https://towardsdatascience.com/bringing-non-technical-users-into-jupyterhub-a7f9acf83571?source=collection_archive---------30-----------------------

扩展 JupyterHub,以便同事和客户可以与您的笔记本电脑的用户友好的安全版本进行交互

Jupyter notebooks 是一种交互式探索和开发数据科学模型的简单方法。 JupyterHub 是一个可以在 web 服务器上配置的独立项目,允许组织集中管理一个托管多个 Jupyter 笔记本环境的服务器,每个数据科学团队成员一个或多个。除了标准化用户开发环境和减轻个体数据科学家的维护负担,JupyterHub 还提供了一个认证框架——例如,基于企业电子邮件帐户实现单点登录访问。

总是有办法与其他团队成员共享文件系统,但 JupyterHub 通常被视为组织数据科学家实验的一种方式——非技术同事不会被邀请。也许一名数据科学家通过笔记本电脑与一名客户交谈,而他们都在看着同一个屏幕。也许有时,最有可能是不幸的是,一个非技术用户得到一个 JupyterHub 帐户,上面有在笔记本上 shift+enter 的指令,这样他们就可以自己研究结果…

手拿笔记本的非技术同事应接不暇……(照片由来自 Pexels 的 Pixabay 拍摄)

打开 JupyterHub

过去几年的新项目让 JupyterHub 做得更多。本文描述了如何将其他免费开源项目引入到您的 JupyterHub 中,使其成为一个有用的工具,以安全、自动化和用户友好的方式展示您的笔记本成果。

至关重要的是,如果您或您的 IT 部门拥有配置 JupyterHub 的资源,那么您只需要扩展配置就可以引入这个额外的功能。

我们努力实现的工作流程:

  • 数据科学家编写了一个 Jupyter 笔记本,可能会显示基于模型的不同输入的交互式图表
  • 当准备好分享时,他们点击几个按钮,旋转他们的笔记本的独立克隆,以用户友好的仪表板风格运行(即,查看者看不到代码,或者需要按 shift+enter!)
  • 任何可以访问 JupyterHub 的非技术用户(例如通过他们的公司 Google 电子邮件)都可以安全地查看仪表板并与之交互
  • 同时,数据科学家可以不受阻碍地继续使用他们的原始笔记本

为 JupyterHub 带来这种魔力的关键技术是 Voila ,这是 Jupyter 服务器的用户友好版本,它隐藏了代码单元,并将笔记本作为 web 应用程序运行。

其他一些默默无闻的开源项目也有助于实现这一点,所有的胶水都被一个新的叫做仪表盘的 JupyterHub 扩展混合在一起。

JupyterHub 主页上的标志

配置 JupyterHub

有三种主要方法可以为您的组织在服务器上安装 JupyerHub:

  • 在 Kubernetes 集群上,通过 Zero-to-JupyterHub 提供的方法—这种重量级的方法目前还不能支持这里描述的仪表板设置。
  • 通过最小的 JupyterHub(TLJH)——一种在单台机器上设置和配置 JupyterHub 的标准化方法。这有一个很好的命令行工具,可以轻松地设置 HTTPS 证书和其他配置,但对您的服务器有一些重要的基本要求。
  • 自己在一台服务器上安装。让 JupyterHub 在任何基于 Linux 的服务器上运行相对容易,但是你必须安装你自己的 HTTPS 证书,并找到一种方法来监督 JupyterHub 服务器进程。

我们将主要假设您正在使用 TLJH,但是您自己的手动安装步骤将是相似的。

TLJH 的初始安装和设置在 TLJH 的安装文档中针对各种云提供商(或您自己的服务器)进行了描述。

码头工人的重要性

Docker 是一项真正的革命性技术,它允许我们将每个 Jupyter 笔记本服务器作为一个独立的(轻量级)虚拟机来运行,这样我们就不需要担心 JupyterHub 进程本身或我们的多个用户的服务器相互冲突。

这种虚拟化可以在没有 Docker 的情况下建立——事实上,默认的 TLJH 安装在服务器上本地构建了精心构建的进程隔离。从 Dashboard 的角度来看,Docker 的真正天才之处是能够轻松地指示 Docker 拍摄 Jupyter 环境的快照,以便我们可以立即旋转它的新克隆,除了这一次使用用户友好的 Voila 前端而不是常规的 Jupyter 界面来启动它。

我们需要指示 JupyterHub 使用“DockerSpawner”启动新的独立 Jupyter 服务器。

如果你的 TLJH 安装还没有运行 Docker,请查看这里的说明。

更新:最新版本的 ContainDS 不需要 Docker! 无对接器安装说明在此

安装容器仪表板

到目前为止,一切都给了我们一个标准的最小 JupyterHub 设置。

最后的配置步骤是安装 ContainDS 仪表板。这为 JupyterHub 添加了一个额外的“仪表板”菜单,您可以在其中创建或查看其他用户制作的仪表板。

SSH 到您的服务器,如果不在那里,运行:

sudo /opt/tljh/hub/bin/python3 -m pip install cdsdashboards

添加一个额外的配置片段,告诉 TLJH 加载仪表板片段:

sudo vi /opt/tljh/config/jupyterhub_config.d/cdsdashboards.py

将以下内容粘贴到 vi 编辑器中:

c.JupyterHub.allow_named_servers = True

from cdsdashboards.app import CDS_TEMPLATE_PATHSfrom cdsdashboards.hubextension import cds_extra_handlers

c.JupyterHub.template_paths = CDS_TEMPLATE_PATHS
c.JupyterHub.extra_handlers = cds_extra_handlersc.CDSDashboardsConfig.builder_class = 'cdsdashboards.builder.dockerbuilder.DockerBuilder'

(如果不熟悉 vi 文本编辑器:启动时,按‘I’进入插入模式;粘贴文本;按 escape 键,然后键入':wq '和 enter 键来编写文件并退出。)

要试用并检查您的 JupyterHub 是否正常工作:

sudo tljh-config reload

从 web 浏览器访问您的 JupyterHub 安装,并看到它仍然像预期的那样运行。

构建仪表板

在您的 JupyterHub 中,点击“我的服务器”以访问您的 Jupyter 笔记本电脑服务器。创建你想要制作和分享的任何原型或可视化。为了跟随这个教程,你可以在这里找到一个简单的例子粘贴到你的笔记本单元格或者只是上传为一个 ipynb 文件。

我们在朱庇特笔记本上的代码

当您准备好分享时,点击返回“控制面板”,然后进入新的“仪表板”菜单:

空仪表板屏幕

点击“新仪表板”并填写屏幕:

新的仪表板屏幕

最重要的事情是输入一个名称,然后选择您正在工作的 Jupyter 服务器克隆到仪表板中。在这种情况下,只有我们的“默认服务器”可供选择。

您将看到 ContainDS 构建了新的仪表板。准备就绪后,您可以点击它,查看您闪亮的全新用户友好型仪表盘:

瞧,笔记本的版本

让你的非技术同事参与进来

创建仪表板的过程很简单,但是当您的非技术同事或客户亲眼看到您的工作时,这种设置的真正威力会大放异彩——而不是让他们阅读您的代码!

当另一个用户登录到 JupyterHub 并点击仪表板菜单时,他们将能够看到其他用户创建的所有仪表板。查看“来自其他人的仪表板”下的“图表”仪表板:

另一个用户访问我们的仪表板

其他用户可以点击进入仪表板,并以用户友好的形式与它进行交互,这一切都是安全的,并且不必在您的代码中按 shift+enter 键,甚至看不到任何内容!

这一切是如何运作的

在幕后,ContainDS Dashboards 使用 Docker 将原始的 Jupyter 服务器克隆为“映像”。然后,它启动了一个基于该图像的新服务器,只不过这次是通过 Voila 的服务器而不是常规的 Jupyter 服务器来运行。

无论哪个用户拥有仪表板,都可以在其主页上看到服务器的仪表板版本:

显示仪表板服务器的扩展主页

如果他们停止和/或删除它,这很好。如果任何其他用户尝试再次查看仪表板,将会启动一个新的仪表板服务器。

就 JupyterHub 而言,dashboard 服务器只是另一个 Jupyter 服务器,它现在独立于您原来的 Jupyter 服务器运行。这意味着您可以返回并对笔记本电脑进行更改,而不会影响仪表板。而且仪表盘的用户不会影响你原来的笔记本。

ContainDS Dashboards 配置中的选项允许您隐藏 dashboard 服务器列表,因此您的用户无需担心它们。

结论

这里的一切都建立在成熟的技术之上——最著名的是 Jupyter 笔记本和 JupyterHub。这意味着您或您的 IT 部门可以轻松访问这里描述的基础架构的核心。

最近的一些发展使得这个仪表板解决方案成为可能: Voila 本身,以及一个名为 jhsingle-native-proxy 的小项目,它提供了围绕 Voila 的 Jupyter-Hub 认证。当然,包含了仪表盘将所有东西联系在一起。

在基于项目的数据科学团队中,每个数据科学家可能最适合在他们自己的 Jupyter 环境中解决问题。通常,使用破坏性的临时流程将结果转移到 web 服务器或其他部署系统,以便非技术客户或同事可以充分欣赏笔记本电脑中演示的模型。

我希望这种生产安全可靠的笔记本“仪表板”版本的新能力将使数据科学家与非技术利益相关者的交流变得愉快和丰富。能够自动和即时地做到这一点意味着分享结果不需要等到项目的最后——然后变成一个漫长而痛苦的过程,危及结果本身的可靠性。

将可靠的数据和人工智能带到云端:与 Databricks 的 Matei Zaharia 的问答

原文:https://towardsdatascience.com/bringing-reliable-data-and-ai-to-the-cloud-a-conversation-with-databricks-matei-zaharia-25e950e96c4a?source=collection_archive---------31-----------------------

Matei Zaharia 关于人工智能、云计算和数据可靠性的采访

图片由陈琦烨在 Unsplash 上提供。

说你的公司是数据驱动的是一回事。从数据中获得有意义的见解是另一回事。

问问马泰·扎哈里亚,阿帕奇火花的原创者就知道了。自 2010 年由 Matei 和加州大学伯克利分校的 AMPLab 首次发布以来,Apache Spark 已成为世界领先的开源集群计算框架之一,为数据团队提供了一种更快、更有效的方法来处理和协作大规模数据分析。

图片由 Matei Zaharia 提供。

凭借 Databricks ,Matei 和他的团队通过构建一个平台,帮助数据团队更有效地管理他们的管道和生成 ML 模型,将他们对可扩展、可靠数据的愿景带到了云。毕竟,正如马泰所言:“你的人工智能只取决于你输入的数据。”

我们与 Matei 坐下来讨论 Apache Spark 背后的灵感,数据工程和分析领域在过去十年中的发展,以及为什么数据可靠性是业界最关心的问题。

你在 2010 年作为加州大学伯克利分校的一名研究人员发布了 Spark,从那时起,它已经成为现代数据堆栈中使用最广泛的技术之一。最初是什么激发了你的团队开发这个项目?

马泰·扎哈里亚(MZ): 十年前,人们对使用大型数据集进行分析很感兴趣,但你通常必须是一名软件工程师,并具备 Java 或其他编程语言的知识才能为他们编写应用程序。在 Apache Spark 之前,有 MapReduce 和 Hadoop 作为处理和生成大数据集的开源实现,但我在伯克利的 AMPLab 的团队希望找到一种方法,使数据处理更容易被全职软件工程师以外的用户使用,如数据分析师和数据科学家。

具体来说,对于数据科学家来说,我们构建的第一个功能之一是 SQL 引擎开销,它允许用户将 SQL 与可以用另一种编程语言(如 Python)编写的函数相结合。

Apache Spark 的另一个早期目标是通过设计模块化的编程接口,让用户可以轻松地使用现有的开源库来设置大数据计算,以便用户可以轻松地在一个应用程序中组合多个库。这导致了数百个为 Spark 构建的开源包。

是什么鼓励你和你在加州大学伯克利分校的团队将你的研究项目转化为企业数据团队的解决方案?

在研究项目的早期,有一些技术公司对使用 Apache Spark 感兴趣,例如 Yahoo!,该公司雇佣了当时使用 Hadoop 的最大团队之一,以及几家初创公司。因此,我们很高兴看到我们是否能够支持他们的需求,并通过这种合作,产生新的研究问题的想法,因为它仍然是一个如此新的空间。

因此,我们在早期花了很多时间让 Apache Spark 对企业可用。然后,在 2013 年,这个项目的核心研究团队正在完成我们的博士学位,我们希望继续研究这项技术。我们认为,以可持续和易于使用的方式将它提供给许多人的最佳方式是通过云,于是 Databricks 诞生了。

七年后,你的预见完全正确。2020 年,越来越多的数据团队将采用云来构建他们的数据平台。企业数据团队在设计他们的数据堆栈时应该记住什么?

首先,考虑你希望谁访问你的数据平台是很重要的。谁将访问 it 中产生的东西,围绕这一点,您需要什么样的治理工具?如果您没有权限实际使用数据,或者如果您不得不要求另一个团队编写数据工程作业,而不仅仅是运行一个简单的 SQL 命令,那么您就不能轻松地访问现有数据或与公司的其他利益相关者共享结果,这就会成为一个问题。

另一个问题是:您的数据可用性目标是什么?无论你只是构建一个简单的报告或机器学习模型,还是介于两者之间的任何东西,你都希望它们随着时间的推移不断更新。理想情况下,您不会花费大量时间来解决应用程序的停机问题。

因此,在设计平台时,评估满足公司数据用户的数据可用性需求所需的特性是非常重要的。这就是 数据可观察性 的用武之地。

过去,你说过 “人工智能只和你输入的数据一样好。” 我完全同意。你能详细说明一下吗?

我甚至可以说,人工智能或机器学习真的应该被称为类似“数据外推”的东西,因为这基本上是机器学习算法的定义:以某种方式从已知数据中进行归纳,通常使用某种统计模型。所以当你这么说的时候,我想很明显你输入的数据是最重要的元素,对吗?

如今,越来越多的人工智能研究被发表,强调运行这个或那个新模型需要多么少的代码。如果你为训练模型所做的一切都是标准的,那么这意味着你放入这个模型的数据是非常重要的。为此,需要考虑数据准确性和可靠性的几个重要方面。

例如,你输入的数据是正确的吗?它可能是不正确的,因为你收集它的方式,也可能是因为软件中的错误。问题是,当你生产,你知道,1tb 的数据或 1pb 的数据放入这些培训应用程序之一时,你经常必须逐个检查所有这些数据,看它们是否有效。

同样,您输入的数据是否涵盖了足够多样的条件,或者您是否遗漏了模型需要良好运行的关键现实条件?

为此,数据团队可以采取哪些步骤来获得高度可靠的数据?

在高层次上,我见过一些不同的方法,所有这些方法都可以结合使用。其中之一很简单,只需要一个模式和对将要进入表或报告的数据类型的期望。例如,在 Databricks 平台中,我们使用的主要存储格式是一种叫做 Delta Lake 的东西,它基本上是 Apache Parquet 的一个功能更丰富的版本,在您的表上有版本控制和事务。我们还可以强制实施将哪种数据放入表中的模式。

我见过的另一种数据质量方法是运行作业,在数据产生后检查数据并发出警报。理想情况下,您需要一个非常容易生成自定义检查的界面,并且您可以集中查看正在发生的事情,就像您的数据健康状况的单一窗格。

我要注意的最后一点与你如何设计你的数据管道有关。基本上,数据复制、ETL 和传输步骤越少,您的系统就越有可能可靠,因为出错的地方就越少。例如,您可以获取一个 Delta Lake 表,将其视为一个流,并拥有列出了更改的作业,这样您就不需要将更改复制到消息总线中。您还可以使用 Tableau 这样的商业智能工具直接查询这些表,这样就不必将数据复制到其他系统中进行可视化和报告。

数据可靠性是一个发展非常迅速的领域,我知道蒙特卡洛在这里做了很多有趣的事情。

当你联合创立 Databricks 的时候,云技术还处于萌芽状态。现在,许多最好的数据公司都在构建云。是什么导致了现代基于云的数据堆栈的兴起?

我认为这是一个时机和易于采用的问题。对于大多数企业来说,云使得大规模采用技术变得更加容易。有了云,您可以自己购买、安装和运行高度可靠的数据堆栈,而无需昂贵的设置和管理成本。

管理是维护数据管道最困难的部分之一,但是有了云数据仓库和数据湖,它就内置了。所以有了云服务,你买的不仅仅是一堆你必须安装在服务器上的光盘。您的管理质量直接影响到您在其上构建关键应用程序的可能性。如果你的某样东西每个周末都要停机维护,而且必须停机一周才能升级,你就不太可能想用它。

另一方面,如果你有云供应商正在管理的东西,有超高可用性的东西,那么你实际上可以构建这些更关键的应用程序。最后,在云上,供应商向客户发布更新并获得即时反馈也要快得多。

这意味着云供应商必须非常擅长在不中断工作负载的情况下实时更新一些东西,但对于用户来说,这基本上意味着您可以更快地获得更好的软件:想象一下,您现在可以访问软件,而您在未来一两年内只能从本地供应商那里获得这些软件。

这些是云产品在市场上取得成功的重要因素。

了解更多关于 马泰的研究阿帕奇 Spark、 Databricks**

有兴趣了解更多关于数据可靠性的知识吗?向 巴尔摩西 以及 蒙特卡洛 团队伸出援手。

本文由Molly Vorwerck共同撰写。**

通过音乐可视化将歌曲带入生活

原文:https://towardsdatascience.com/bringing-songs-to-life-through-music-visualization-8beee9573b7b?source=collection_archive---------34-----------------------

使用 p5.js 库将低音、高音和中音能量映射到动态视觉组件

去年秋天,当我在哥本哈根留学的时候,我遇到了这个设计师,他正在用 Javascript 做很多很酷的可视化项目。聊了几句,我就完全被他的创作世界吸进去了。我被他在 Instagram 上分享音乐可视化的帖子迷住了,我最终掉进了一个兔子洞,这让我发现了许多其他做类似工作的创意天才。我给自己做了一个记录,总有一天我会回到这个灵感的源泉,用我自己的项目来弄脏我的手。

在我们开始之前,让我先澄清一下我在创意公寓里的挣扎。我没有天马行空的想象力——我的艺术品味很大程度上局限于那些看起来令人满意、或许有点催眠的几何设计。因此,毫无疑问,弄清楚从哪里开始是这个项目最困难的部分。

奇怪的是,我这个项目的主要灵感来自电视节目这就是我们。无可否认,这是一部相当感人的戏剧——请不要因为我看了它就对我评头论足。然而,有一件事我并不羞于承认,那就是我是悉达多·科斯拉为该剧原创配乐的超级粉丝。我认为他是一位杰出的作曲家,有时我会在晚上反复播放他的音乐来哄我入睡。我想进一步探索这些曲目,看看我是否能创造一个视觉组件,可以像音频一样舒缓。

悉达多·科斯拉和中的几个场景这就是我们,来源: NPR

P5.js 库

第一步是熟悉 p5 Javascript 库。p5.js 是一个专门为艺术家、设计师、教育工作者和初学者定制的库,目的是使 Javascript 更容易被希望实现不同类型的应用程序的程序员访问。

p5.js 主页

我仔细阅读了大量的例子,以找出如何处理音频。首先,我摆弄了一下声音频谱,看看音频被映射到某种视觉的基本例子。然后,我了解了一个名为 getEnergy() 的函数,它返回特定频率下的能量(体积)数量,或者两个频率之间的平均能量数量。此外,预定义的频率范围(“低音”、“中低音”、“中低音”和“高音”)可以传递到函数中。唯一的规定是必须首先调用 analyze() 函数,因为 getEnergy() 函数依赖于来自该函数调用的分析频率数据。

音频→视频

我的项目的频率提取代码非常简单:

var fft = new **p5**.**FFT**();
fft.**analyze**();
var bass = fft.**getEnergy**("bass");
var treble = fft.**getEnergy**("treble");
var mid = fft.**getEnergy**("mid");

将音频映射到视觉组件需要大量的角度和数学上的反复试验。最后,我使用鼠标定位来指定可视化中多边形的线段数和半径。

pieces = **map**(mouseX, 0, width, 4, 8);
radius = **map**(mouseY, 0, height, windowHeight / 4, windowHeight/2);

然后,我为线段制作了一些贴图和缩放变量。

var map_mid = **map**(mid, 0, 255, -radius, radius);
var scale_mid = **map**(mid, 0, 255, 1, 1.5);var map_treble = **map**(treble, 0, 255, -radius, radius);
var scale_treble = **map**(treble, 0, 255, 1, 1.5);var map_bass = **map**(bass, 0, 255, -100, 800);
var scale_bass = **map**(bass, 0, 255, 0, 0.8);

最后,我编写了一个 for 循环来定义低音、中音和高音多边形环,它们将旋转到整首歌的音频频率。

这段代码的结果可以在下面的视频中看到。

附加功能

预装轨道

我选择使用这是我们原声带中的歌曲“杰克在 AA”的一个主要原因是因为我碰巧在我的电脑上有它的 MP3,可以很容易地上传到可视化中。我希望能够可视化其他歌曲,所以我实现了一个预加载的轨道功能,允许您单击数字键来切换正在播放的轨道。附加曲目选项(不包括预载为 0 号曲目的“AA 中的插孔”)包括:

  1. 我想去的地方
  2. 露天看台-狂野的心
  3. 设计师-熊猫
  4. 拉赫曼-发自内心再保险
  5. 哈利德-眩晕
  6. Shakey Graves -家族和属
  7. 蒙福之子乐团-我会等的
  8. 特拉维斯·斯科特,房间里最高的
  9. 玻璃动物,丹泽尔·库里-东京漂流

这些曲目代表了各种各样的流派。事实上,在不访问粗略的、充满病毒的、可能是非法的网站的情况下获取 MP3 文件是一个相当大的挑战。也就是说,如果你有一个. mp3,你可以选择上传自己的歌曲。wav 或者。ogg 文件。

调色板切换

可视化的着色非常简单。四种颜色的阵列用于组成调色板。四种颜色按以下顺序给出:[(背景),(低音),(中音),(高音)]。

为了允许颜色切换,我提出了总共 5 个调色板(红色、橙色、绿色、蓝色和紫色),然后添加了一个简单的按键监听器来遍历调色板。按下“Enter”键以及双击都会触发此功能。

切换播放/暂停

您可以通过点击“空格键”或点击左下角的切换按钮来暂停或播放曲目。

例子

在上面的演示中,我们看到歌曲“我想去的地方”被形象化了。这首歌有一个典型的快节奏,每当频率根据节拍变化时,多边形的频繁收缩就反映了这一点。在每一拍中按下“输入”键也是非常令人满意的,因为颜色的变化使视觉化感觉非常有活力,就像你在迪斯科舞厅或夜总会看到的一样。

玻璃动物和丹泽尔·库里的歌曲《东京漂移》是我最近最喜欢的一首歌。我的好朋友不久前把它发给了我,我不明白这种炒作是怎么回事,但每次听它,我都会更加欣赏它。我在上面的视频中录制了一段可视化片段,主要是因为这首歌的介绍很吸引人。由于在歌曲的前几秒钟没有很多音频通道同时混合在一起,每个半令人毛骨悚然的声音都与一些视觉成分直接相关。然后,在 0 点 27 分,有一个巨大的节拍下降,完全将你吸入轨道的其余部分。节拍在整首歌中相当突出,其意义体现在视频中浅蓝色所代表的每个节拍脉动的大小上。

与未来相关的愿望

  • 自动从一些音乐流媒体服务中提取新音乐,以便我(和其他人)可以访问这个可视化应用程序来聆听和体验新音乐。
  • 根据歌曲或艺术家开发更具创造性的音乐可视化,而不是几何图形。
  • 制作一个以更优雅的方式运行这些代码的移动应用程序(这个 web 应用程序中的一些组件有点简单)。
  • 建立一个持续产生音乐的 GAN。

结束语

源代码可以在这里找到:

[## sejaldua/音乐-即

使用 P5.js 库探索音乐可视化

github.com](https://github.com/sejaldua/music-viz)

这只是我第一个使用 Javascript 的音乐可视化项目。我肯定打算继续改进这个项目,我也希望转向其他有趣的应用程序和与音乐相关的开发工具。如果你想给我任何反馈或灵感,请通过 sejaldua@gmail.com 或我的网站联系我。

感谢您的阅读!

广播 PySpark 累加器

原文:https://towardsdatascience.com/broadcasting-pyspark-accumulators-343104c18c44?source=collection_archive---------43-----------------------

以及如何管理它们

照片由格雷戈·拉科齐在 Unsplash 上拍摄

在这篇文章中,我将讨论一个有趣的模式,用一个方便的广播。在进入更多细节之前,让我们回顾一下什么是火花累加器。

一种可以累加的共享变量,即有一个可交换的和相关的“加”操作。Spark 集群上的工作任务可以使用+=操作符将值添加到累加器中,但是只有驱动程序才允许使用[**value**](https://spark.apache.org/docs/2.3.1/api/python/pyspark.html#pyspark.Accumulator.value)来访问它的值。来自工人的更新自动传播到驱动程序。

来源:https://spark . Apache . org/docs/2 . 3 . 1/API/python/py spark . html # py spark。蓄能器

累加器的三大戒律

  1. 累加器只能用于交换和结合的“加法”运算。对于任何其他操作,我们必须使用自定义实现。稍后会详细介绍。
  2. 可以在工作任务上“更新”累加器,但该任务不能访问其值。
  3. 累加器可以在驱动程序上更新和访问。

几行代码抵得上千言万语

让我们看一个简单的累加器例子

在上面的示例代码中, cnt 是在全局级别上定义的。 add_items 方法将输入 x 加到 cnt 上。 add_items 方法后来应用于 global_accumulator 方法中 rdd 的每一项。这是累加器的典型用法,最后对 global_accumulator 的调用将输出 6,这是 1、2 和 3 的总和。请注意,我们需要将 cnt 定义为全局变量,否则各种方法都无法访问它,并且它将是未定义的。

那是什么问题…

现在,为了激发对广播累加器的需求,让我们将代码分成几个文件,这就是模块化代码库中的代码。

global _ accumulator _ module从另一个模块 accumulator_process 中调用 process_data 方法(代码如下)。

如果我们执行global _ accumulator _ module,那么它会失败并出现以下错误。

NameError: name ‘cnt’ is not defined

问题是 Python 中的全局变量对于一个模块来说是全局的。

Python 中的全局变量是模块的全局变量,而不是所有模块的全局变量。(与 C 不同,C 中的全局变量在所有实现文件中都是相同的,除非您显式地将其设为静态。).如果从导入的模块中需要真正的全局变量,可以在导入模块的属性中设置这些变量。

来源:https://www . tutorialspoint . com/Explain-the-visibility-of-global-variables-in-imported-modules-in-Python

那么,如何让一个全局变量在模块间可用呢?Python 医生有一些想法。

在单个程序中跨模块共享信息的规范方法是创建一个特殊的模块(通常称为 config 或 cfg)。只需在应用程序的所有模块中导入配置模块;然后,该模块就可以作为全局名称使用了。因为每个模块只有一个实例,所以对模块对象的任何更改都会在任何地方得到反映。例如:

配置文件:

x = 0# x 配置设置的默认值

mod.py:

导入配置
config.x = 1

main.py:

导入配置
导入模式
打印(config.x)

注意,出于同样的原因,使用模块也是实现单例设计模式的基础。

来源:https://docs.python.org/3/faq/programming.html?highlight = global # how-do-I-share-global-variables-cross-modules

虽然这不适用于 PySpark,原因是每个 worker 节点上有不同的 module 实例。因此需要累加器,因为共享变量的典型方式在 Spark 中不起作用。

广播累加器

在这种情况下, broadcast_accumulator 方法调用 accumulator_process 模块中的process _ data _ accumulator方法,累加器 acc

这里实际发生的是,我们向 worker 节点发送一个对象引用 acc 。这样我们就不必定义它为全局。

现在我将讨论累加器的两个定制:

  1. 将静态值与累加器一起广播
  2. 广播多个累加器

过滤累加器

在此示例中,FilterAccumulator 类保存项目列表。如果在过程方法中传递的项目不在项目列表中,则更新累加器 acc 。如代码所示, initcount 应该在驱动程序上执行,而进程应该在 worker 节点上执行。执行上述操作得到的值为 4,这是正确的结果。

多个累加器

在本例中,我们有两个累加器 sumnum ,分别累加项目的值和项目的数量。同样,如代码所示, init意味着应该在驱动程序上执行,而在 worker 节点上处理。虽然平均值可以使用其他本机 spark 方法获得,但这是一个如何使用单个类管理多个累加器而不将其声明为全局的示例(这在模块化代码中不起作用)。

结论

希望现在已经很清楚如何使用类和广播来管理累加器,而不是声明为全局的。我希望在将来发布如何创建非整型和浮点型的累加器,因为 Spark 允许自定义累加器。

用 Python 实现布朗运动

原文:https://towardsdatascience.com/brownian-motion-with-python-9083ebc46ff0?source=collection_archive---------4-----------------------

我们展示了如何使用简单的 Python 代码来模拟布朗运动,这是应用广泛的最著名的随机过程。

图片来源: Pixabay(免费商业使用)

免责声明:本文的灵感来源于 佐治亚理工学院在线分析硕士(OMSA) 项目学习资料。我很自豪能继续这个优秀的在线硕士项目。你也可以在这里查看详情。

什么是布朗运动?

物理起源和属性

B 它是由粒子与流体中快速运动的分子(由于内部热能而被激发)的随机碰撞产生的。前述流体应该处于所谓的热平衡,在那里不存在优先流动方向(与各种运输现象相反)。

发现和早期解释

布朗运动是以苏格兰植物学家罗伯特·布朗·T21 的名字命名的,他在 1827 年通过显微镜观察浸泡在水中的花粉时首次描述了这一现象。

长期以来,科学界对此并不重视。然后,在 1905 年,一个 26 岁的瑞士专利办事员通过借助热力学定律分析现象,改变了物理世界。

图片来源:维基百科

阿尔伯特·爱因斯坦发表了一篇开创性的论文,其中他模拟了花粉的运动,受单个水分子的影响,并取决于液体的热能。虽然这篇论文相对来说不如他 1905 年的其他论文出名,但它是他被引用最多的出版物之一。事实上,爱因斯坦对布朗运动的解释是第一个从数学角度证明分子存在的有力证据。****

你可以阅读这篇令人愉快的文章,纪念爱因斯坦论文发表 100 周年。

作为随机过程的布朗运动

多体相互作用

多体相互作用,产生了复杂而美丽的布朗运动模式,无法通过解释分子详细运动的第一原理模型来解决。因此,只有应用于分子群体的概率宏观模型才能用来描述它。

这是布朗运动描述背后的推理主要是作为一个现代形式的纯粹随机过程。几乎所有的实际应用也采用这种方法。

维纳过程

美国数学家诺伯特·维纳首先分析了一维布朗运动的数学性质。由此产生的形式是一个实值连续时间随机过程,称为维纳过程

它是最著名的随机过程之一,具有吸引人的性质,如平稳性和独立增量。因此,它在广泛的领域中发现了频繁的应用,包括纯数学和应用数学,定量金融,经济建模,量子物理,甚至进化生物学。

常见应用

布朗运动的概念和数学模型在现代数学中起着至关重要的作用,如扩散过程 。维纳过程也用于表示白噪声高斯过程的积分,该过程通常充当电气和电子工程中无处不在的噪声模型。同样的想法也适用于滤波器设计中的模型噪声和误差以及控制理论中的随机/未知力。****

****噪声信号(来源: Pixabay )

量子物理中,借助布朗运动研究与福克-普朗克和朗之万方程相关的扩散现象。它也是量子力学的严格路径积分公式形成的基础。例如,使用费曼-卡奇公式,著名的薛定谔方程的解可以用维纳过程来表示。物理宇宙学中的永恒膨胀模型,灵感来自布朗运动动力学。

金融和计量经济学建模的世界里,布朗运动拥有神话般的地位。它在几乎所有主要的金融数学理论中都占有显著的地位。特别是著名的 布莱克-斯科尔斯 期权定价模型,为此迈伦·斯克尔斯获得 1997 年诺贝尔经济学奖,就依赖于这种形式主义。

****量化金融大量使用布朗运动(来源: Pixabay )

Python 实现

一个相当简单的等式

按照布朗运动动力学生成数据点的核心方程相当简单,

其中 【易】可以是一个基本的随机过程如随机游走或来自正态分布的样本。

一门Brownian

实现 的 Jupyter 笔记本可以在这里 找到。

在下面的 Python 代码中,我们用一些有用的方法定义了一个类Brownian,

  • gen_random_walk():从随机行走过程生成运动
  • gen_normal():从正态分布绘制生成运动
  • stock_price():使用所谓的‘几何布朗运动’公式来模拟股票价格
class Brownian():
    """
    A Brownian motion class constructor
    """
    def __init__(self,x0=0):
        """
        Init class
        """
        assert (type(x0)==float or type(x0)==int or x0 is None), "Expect a float or None for the initial value"

        self.x0 = float(x0)

    def gen_random_walk(self,n_step=100):
        """
        Generate motion by random walk

        Arguments:
            n_step: Number of steps

        Returns:
            A NumPy array with `n_steps` points
        """
        # Warning about the small number of steps
        if n_step < 30:
            print("WARNING! The number of steps is small. It may not generate a good stochastic process sequence!")

        w = np.ones(n_step)*self.x0

        for i in range(1,n_step):
            # Sampling from the Normal distribution with probability 1/2
            yi = np.random.choice([1,-1])
            # Weiner process
            w[i] = w[i-1]+(yi/np.sqrt(n_step))

        return w

    def gen_normal(self,n_step=100):
        """
        Generate motion by drawing from the Normal distribution

        Arguments:
            n_step: Number of steps

        Returns:
            A NumPy array with `n_steps` points
        """
        if n_step < 30:
            print("WARNING! The number of steps is small. It may not generate a good stochastic process sequence!")

        w = np.ones(n_step)*self.x0

        for i in range(1,n_step):
            # Sampling from the Normal distribution
            yi = np.random.normal()
            # Weiner process
            w[i] = w[i-1]+(yi/np.sqrt(n_step))

        return w

    def stock_price(
                    self,
                    s0=100,
                    mu=0.2,
                    sigma=0.68,
                    deltaT=52,
                    dt=0.1
                    ):
        """
        Models a stock price S(t) using the Weiner process W(t) as
        `S(t) = S(0).exp{(mu-(sigma^2/2).t)+sigma.W(t)}`

        Arguments:
            s0: Iniital stock price, default 100
            mu: 'Drift' of the stock (upwards or downwards), default 1
            sigma: 'Volatility' of the stock, default 1
            deltaT: The time period for which the future prices are computed, default 52 (as in 52 weeks)
            dt (optional): The granularity of the time-period, default 0.1

        Returns:
            s: A NumPy array with the simulated stock prices over the time-period deltaT
        """
        n_step = int(deltaT/dt)
        time_vector = np.linspace(0,deltaT,num=n_step)
        # Stock variation
        stock_var = (mu-(sigma**2/2))*time_vector
        # Forcefully set the initial value to zero for the stock price simulation
        self.x0=0
        # Weiner process (calls the `gen_normal` method)
        weiner_process = sigma*self.gen_normal(n_step)
        # Add two time series, take exponent, and multiply by the initial stock price
        s = s0*(np.exp(stock_var+weiner_process))

        return s

初始值为零并使用随机行走的过程

我们可以使用一个基本的随机过程,如 随机行走 ,来生成布朗运动的数据点。

随机漫步(图片来源:维基百科)

b = Brownian()for i in range(4):
    plt.plot(b.gen_random_walk(1000))
plt.show()

初始值为 20 并使用正态分布的过程

我们可以从正态分布中得出布朗运动数据。

b = Brownian(20)for i in range(4):
    plt.plot(b.gen_normal(1000))
plt.show()

股票价格模拟

我们在类中实现了几何布朗运动模型作为一种方法。

股票价格的几何布朗运动模型

在演示中,我们模拟了 52 个时间段的多个场景(假设一年有 52 周)。注意,所有的股票价格都从同一点开始,但是沿着不同的轨迹随机变化。

请注意,动态由基础正态分布的均值和方差参数控制。这在某种程度上模仿了股票的增长趋势和“波动性”。

例如,具有正增长趋势的股票将具有正的含义。对于这个特定的模拟,选择均值(μ)为 0.2,选择标准差(方差的平方根)为 0.68。

我们首先为绘图定义一个效用函数。

def plot_stock_price(mu,sigma):
    """
    Plots stock price for multiple scenarios
    """
    plt.figure(figsize=(9,4))
    for i in range(5):
        plt.plot(b.stock_price(mu=mu,
                               sigma=sigma,
                               dt=0.1))
    plt.legend(['Scenario-'+str(i) for i in range(1,6)],
               loc='upper left')
    plt.hlines(y=100,xmin=0,xmax=520,
               linestyle='--',color='k')
    plt.show()

请注意,尽管这些情景看起来足够随机,但它们有下降趋势。这是因为即使是正平均值,我们也有稍高的利差或波动性。

plot_stock_price(mu=0.2,sigma=0.7)

波动性的微小变化

我们用稍微小一点的波动性(但是和以前一样的均值)再次模拟股票价格,这次得到了完全不同的结果。趋势看起来是中性的,即一些情景显示股价在 52 周后上涨,而一些情景显示股价下跌。

plot_stock_price(mu=0.2,sigma=0.65)

进一步降低波动性

如果我们降低波动性,甚至更多,我们会得到一个明显的积极趋势。

plot_stock_price(mu=0.2,sigma=0.6)

二维绘图

在下面的例子中,我们展示了一个二维布朗运动,很像流体介质中实际悬浮的粒子所经历的运动。

b1 = Brownian()
b2 = Brownian()

x = b1.gen_normal(1000)
y = b2.gen_normal(1000)

plt.plot(x,y,c='b')
xmax,xmin,ymax,ymin = x.max(),x.min(),y.max(),y.min()
scale_factor = 1.25
xmax,xmin,ymax,ymin = xmax*scale_factor,xmin*scale_factor,ymax*scale_factor,ymin*scale_factor
plt.xlim(xmin,xmax)
plt.ylim(ymin,ymax)
plt.show()

摘要

我们展示了如何生成随机数据集对应于布朗运动在一维和二维。我们还展示了这一思想在使用几何布朗运动模型的股票价格模拟中的应用。

对于这个重要的随机过程,拥有一个现成的 Python 实现是极其重要的,因为它在各种实际应用程序中无处不在。

例如,数据科学从业者在分析定量金融或物理模型时,可以很容易地将这种实现与他们的随机过程模型相集成。

同样,Jupyter 实现 的笔记本可以在这里 找到。欢迎读者根据自己的需求来叉和扩展。

A lso,你可以查看作者的 GitHub 知识库获取机器学习和数据科学方面的代码、思想和资源。如果你和我一样,对人工智能/机器学习/数据科学充满热情,请随时在 LinkedIn 上添加我或在 Twitter 上关注我。

** [## Tirthajyoti Sarkar - Sr .首席工程师-半导体、人工智能、机器学习- ON…

通过写作使数据科学/ML 概念易于理解:https://medium.com/@tirthajyoti 开源和有趣…

www.linkedin.com](https://www.linkedin.com/in/tirthajyoti-sarkar-2127aa7/)**