NBA 三分线的演变
在过去的几年里,我们已经看到各种统计数据向 NBA 观众展示了所有新的三分线记录,以及三分线现在的使用有多么不同。相比之下,87-88 赛季的领袖是丹尼·安吉,他投中了 148 个三分球。相比之下,17-18 赛季大约有 45 场比赛,克莱·汤普森以 154 个三分球领先 NBA。这篇文章介绍了球员如何提高三分线的优势。
自从 1980-81 赛季引入三分线以来,三分球的尝试和三分球的百分比稳步上升,而场均 2 分的投篮次数相对保持不变。
当我们看看 NBA 中最多产的投手时,我们可以看到大多数的条目,尤其是好的条目,都来自最近 15 年。脚注中描述了纪元组。
即便如此,有两个名字还是很突出
即使是在 NBA 中最多产的 3 分投手中,水花兄弟在制造和效率方面也远远超过其他人。右上角没有标签的点对应于雷·阿伦。
他们到底有多特别?他们在同一个队的时候,在高命中率的时候,保持了很高的 3 分命中率。唯一的遗憾是这个小矮子凯文·杜兰特加入了球队。
注意事项:
- 马克·杰克逊担任主教练的第一年是 2011-12 赛季。在那之后,斯蒂芬和克莱立即得到了拍摄的许可。
- 电子逆向拍卖分为以下几类:
- 80 年代:1980 年至 1989 年
- 区域联防之前:1990-2002
- 区域联防简介:2003-2010
- 现代:2011–2017
- 在 1994-95 和 1995-96 赛季,三分线被缩短,在这两年,史蒂夫·科尔和蒂姆·莱格勒的三分球命中率达到了 50%以上。
- 在第二个散点图中,限制是每个赛季至少打 1000 分钟和至少投中 120 个三分球。
进化中的人工智能助手:抬头
尼古拉斯·费克斯 2017 年 5 月 10 日
AI 助手只是噱头吗?它们只是给喜欢发号施令的懒惰少年用的吗(嘿 Siri…)?它们到底是什么,我们应该更加关注吗?
最近,并不以偏爱技术著称的沃伦巴菲特被问及人工智能的影响。他评论说,潜在的人工智能可能会导致他的保险公司 Geico 减少 10,000 个工作岗位,这是我们从未见过的。他还表示,人工智能可能“具有巨大的破坏性,但有利于提高经济效率”。
不可避免的是,人工智能助手最终将实现他所指的变化。
但是什么是人工智能助手呢?
这一切都是从伊莱扎开始的,伊莱扎是一个早期的自然语言处理计算机程序,它是在 1964 年用 LISP 计算机编程语言创建的。)在麻省理工学院人工智能实验室。ELIZA 的创建是为了通过使用模式匹配和单词替换来模拟对话,从而演示人机交流是多么肤浅,它给用户一种理解的错觉,但实际上它没有内置的上下文响应框架。
这就是和今天(以及明天)的 AI 助手的巨大区别。
鉴于以下情况:
自然语言处理模块,
知识库/本体,
推理引擎,
语音识别/文本到语音转换服务,
图像识别服务,以及
以及基于机器学习的个性化模块
所有这些都在强大的基于云的基础设施上实现,你就有了一个强大的人工智能助手“数字员工”。然后你可以教它提供客户支持、销售保险单、教学、股票交易建议、告诉你该买哪辆车等等。AI 助手用的越多,就会越好。不再有海外服务台外包。“机器人技术”的未来其实在于软件,而不在于硬件。
人工智能助手将重新定义搜索和广告
人工智能助手将彻底改变搜索和广告。谷歌将不得不把自己重塑为一个个性化的人工智能助手。谷歌助手已经开始了这一过程,但这是一个“备份”项目,将分散资源,而不是专注于应该是主要目标的危险。这同样适用于所有主要的搜索引擎。
AI 助手的意义
所以,AI 助手不仅仅是一个语音到文本的界面来搜索。它们是人工智能技术最重要的方面,并且正在快速发展。谷歌、微软、亚马逊、脸书、苹果和三星都在这方面投资,这绝非巧合。
(顺便提一下,我认为全球的电力公司都应该重新审视他们的电力供应备用计划!)
天空中的眼睛:作为大数据的卫星图像。
我们迫切需要卫星图像可能提供的更广阔的图景。
艺术和科学长期以来推动人类探索大小和规模的极限。这两个领域的进步都以这样或那样的方式受到人类对极大和极小事物的兴趣的影响。想想微积分、微生物学、硅藻、望远镜、纳米技术和许多其他科学领域的例子。圣彼得大教堂的壁画,莫扎特作品的非凡长度,甚至列奥纳多·达·芬奇的插图和绘画的规模都是艺术中突出的例子。大小和比例通常让人类着迷,因为它们的极端与我们的自然感知格格不入。在他的文章介绍中(我推荐你阅读)。散文作家凯文·西姆勒陈述如下:
没有显微镜、望远镜或计算机,不久前的人类几乎没有办法在与日常生活大不相同的尺度上体验现实。仰望天空,远眺海洋,或者穿越峡谷,让我们对一些额外的数量级有了更多的欣赏。更进一步需要想象力。
今天,由于技术和科学,我们有工具在改变思维的尺度上理解现实。我们现在可以在几代人之前无法想象的维度上思考时间和空间。
科学上一个奇特的飞跃是使用卫星图像作为现成的数据来源。除其他原因外,这种特殊性源于卫星图像的使用在大光谱和小光谱的两端:
漂浮在巨人的肩膀上,看得更远,看得更详细。
艾萨克·牛顿(Isaac Newton)的格言一直激励着我,即依靠以前的工作来推动我们的进步:
为了看得更远,我不得不站在巨人的肩膀上
很酷的故事艾萨克。但是,你看,遥感和卫星图像提供了一个不同的进步视角,其重要性不受学科边界的限制。
另一种观点
卫星图像作为大数据的本质可以从我们看待世界的范式转变中看出。想想我们是如何看待衡量经济进步的指标的。大多数人信任经济模型,即使这些模型的方法在不合适的地方也会被使用。但是有了遥感技术(包括使用卫星和无人机等),我们可以从我们的夜灯图像中获得关于我们经济状况的相当有见地的信息。
现在你可能想说“好吧,这太荒谬了,伙计,我们电气化房屋的照片告诉了我们什么关于我们的经济,难道我们不需要复杂的图表和方程来理解这些吗”?我个人不这么认为:
然而,对此更合理的回应可以在的《每个人都在说谎》一书中找到,塞斯·斯蒂芬斯-达维多维茨在书中写道:**
为什么夜灯可以很好地衡量 GDP?在世界上非常贫穷的地方,人们努力支付电费。因此,当经济状况不佳时,家庭和村庄会大幅减少夜间的采光量。
遥感卫星图像记录的夜间光线变化与全球许多发展中地区的经济波动相关,这种相关性显然暗示着因果关系。
卫星图像的使用也与环境建模和监测相关。像 NDVI、NDBI 和 NDWI 这样的归一化差异光谱指数提供了数据,分别为我们提供了直接植被、人工和开放水域环境状态的众多视角。
- 归一化植被指数差异与森林监测、确定作物水分胁迫、湿地健康、河流流域管理甚至干旱监测相关
- 另一方面,标准化的差异建造指数可以为城市化速度、城市规划提供信息,甚至允许我们将媒介传播疾病的扩散与居住模式的变化联系起来。
- 标准化的差异水指数能够提取或描绘开放水域的特征,并能告诉你你家后院的湖有多浑浊,只要它在地球轨道上可见。此外,当嵌入机器学习系统和其他统计方法时,可以预测与洪水相关的主要灾害。这样美国人就可以在飓风出生前给它们命名:
为什么是卫星图像?
想想大多数撒哈拉以南非洲居民依赖的行业:农业。除了监测和预测干旱,卫星图像还可以提供对农田缺水可能性的见解,基本上在灌溉对作物生产造成威胁之前就通知灌溉需求。这强调了遥感和卫星图像的特殊意义,以及在我们追求可持续发展的未来时,这些技术为我们带来的希望。
卫星图像作为多用途数据源脱颖而出的另一个原因是其领域独立性。卫星图像的使用跨越了工业界和学术界,为各种决策和研究方法提供了信息。此外,insights 卫星图像能够以多种方式提供超过许多已为相同目的发明的技术。
透视反转
传统数据源并没有过时或无用。它们得到了新数据源的很好补充,新数据源能够给予我们以前从未想象过的洞察力。我们从遥感和卫星图像中获得的环境的光谱和空间细节包含了大量的数据,等待从中获得最佳的洞察力。然而,大小并不是最重要的。正是与遥感和卫星图像有关的领域知识的多样性使其成为一个独特的数据来源。
坍缩成致密物质!
加入星云研究时事通讯,获取更多关于一次一项技术让世界变得更美好的文章。点击这里报名
RNN / LSTM 的陷落
我们爱上了循环神经网络(RNN)、长短期记忆(LSTM)及其所有变体。现在是放下它们的时候了!
2014 年,LSTM 和 RNN 起死回生。我们都读过科拉的博客和卡帕西的《RNN 颂》。但是我们都很年轻,没有经验。几年来,这是解决序列学习、序列翻译(seq2seq)的方法,这也导致了语音到文本理解的惊人结果,以及 Siri 、 Cortana 、谷歌语音助手、 Alexa 的提升。我们也不要忘记机器翻译,它产生了将文档翻译成不同语言的能力或神经机器翻译,而且还将图像翻译成文本,将文本翻译成图像,以及字幕视频,而且……好了,你明白了。
然后接下来的几年(2015–16)就来了 ResNet 和关注。人们可以更好地理解 LSTM 是一种聪明的旁路技术。还注意到 MLP 网络可以被受上下文向量影响的平均网络所取代。稍后将详细介绍。
只花了两年多的时间,但今天我们可以肯定地说:
“放下你的 RNN 和 LSTM,他们不好!”
但不要相信我们的话,也可以看到证据表明,基于注意力的网络越来越多地被谷歌、脸书、 Salesforce 等公司使用。所有这些公司已经取代了 RNN 和基于注意力模型的变体,这仅仅是个开始。RNN 在所有应用程序中都计算天数,因为它们比基于注意力的模型需要更多的资源来训练和运行。见这篇文章了解更多信息。
但是为什么呢?
记住,RNN 和 LSTM 以及衍生工具主要使用时间顺序处理。请参见下图中的水平箭头:
Sequential processing in RNN, from: http://colah.github.io/posts/2015-08-Understanding-LSTMs/
这个箭头表示长期信息在到达当前正在处理的单元之前必须依次通过所有单元。这意味着它很容易被乘以小数字< 0. This is the cause of 消失梯度而被破坏。
为了挽救局面,出现了 LSTM 模块,它今天可以被视为多个开关门,有点像 ResNet 它可以绕过单元,从而记住更长的时间步长。因此,LSTM 有办法消除一些渐变消失的问题。
Sequential processing in LSTM, from: http://colah.github.io/posts/2015-08-Understanding-LSTMs/
但不是全部,从上图可以看出。我们仍然有一个从旧的过去细胞到当前细胞的顺序路径。事实上,路径现在变得更加复杂,因为它有附加和遗忘分支。毫无疑问,LSTM、GRU 和衍生品能够学到很多长期信息!此处见结果;但是他们能记住 100 的序列,而不是 1000 或 10000 或更多。
RNN 的一个问题是它们对硬件不友好。让我解释一下:我们不需要很多资源来快速训练这些网络。此外,在云中运行这些模型需要大量资源,鉴于语音到文本的需求正在快速增长,云是不可扩展的。我们将需要在边缘处理,直接进入亚马逊回声!更多详细信息,请参见下面的注释。
你是做什么的?
此时(2018 年 9 月)我会认真考虑这个方法这里。这是一个基于 2D 卷积的神经网络,具有因果卷积,可以胜过 RNN/LSTM 和注意力模型,如转换器。
从 2017 年到上面的论文,变形金刚绝对是一个很好的建议。它在训练和参数数量上有很大的优势,正如我们在这里讨论的。
**或者:**如果要避免顺序处理,那么我们可以找到“向前看”或更好的“向后看”的单元,因为大多数时候我们处理实时因果数据,我们知道过去并希望影响未来的决策。举例来说,在翻译句子或分析录制的视频时就不是这样了,我们有所有的数据,可以花更多的时间进行推理。这种回顾/前瞻单元是神经注意力模块,我们之前在这里解释过。
为了解决这个问题,结合多个神经注意力模块,出现了“分级神经注意力编码器”,如下图所示:
Hierarchical neural attention encoder
查看过去的更好方法是使用注意力模块将所有过去的编码向量总结成上下文向量 Ct。
注意这里有一个注意力模块的层级,非常类似于神经网络的层级。这也类似于下面注 3 中报告的时间卷积网络(TCN) 。
在分层神经注意力编码器中,多层注意力可以查看最近过去的一小部分,比如说 100 个向量,而上面的层可以查看这些注意力模块中的 100 个,有效地整合了 100 x 100 个向量的信息。这将分级神经注意力编码器的能力扩展到 10,000 个过去向量。
这是回顾过去并影响未来的方法。
但更重要的是,看看将表示向量传播到网络输出所需的路径长度:在分层网络中,它与 log(N) 成比例,其中 N 是分层的层数。这与 RNN 需要做的 T 个步骤形成对比,其中 T 是要记忆的序列的最大长度,T > > N
如果你跳 3-4 次,比跳 100 次更容易记住序列!
这种架构类似于神经图灵机,但让神经网络决定通过注意力从内存中读出什么。这意味着实际的神经网络将决定哪些来自过去的向量对未来的决策是重要的。
但是存储到内存呢?上面的架构在内存中存储所有以前的表示,不像神经转动机器。这可能是相当低效的:想想存储视频中每一帧的表示——大多数情况下,表示向量不会逐帧改变,所以我们确实存储了太多相同的内容!我们能做的是添加另一个单元来防止相关数据被存储。例如通过不存储与先前存储的向量太相似的向量。但这真的是一个黑客,最好的办法是让应用程序来指导什么向量应该保存或不保存。这是当前研究的重点。请继续关注更多信息。
所以总之忘掉 RNN 和变种吧。利用注意力。你真正需要的是关注!
**告诉你的朋友!**我们非常惊讶地看到,如此多的公司仍在使用 RNN/LSTM 进行语音到文本的转换,许多公司都没有意识到这些网络是如此低效和不可扩展。请告诉他们这个帖子。
附加信息
关于训练 RNN/LSTM: RNN 和 LSTM 很难训练,因为它们需要内存带宽限制的计算,这是硬件设计者最糟糕的噩梦,并最终限制了神经网络解决方案的适用性。简而言之,LSTM 要求每个单元 4 个线性层(MLP 层)在每个序列时间步长运行。线性层需要大量的内存带宽来计算,事实上,它们不能经常使用许多计算单元,因为系统没有足够的内存带宽来提供计算单元。增加更多的计算单元很容易,但增加更多的内存带宽却很难(注意芯片上足够多的线,从处理器到内存的长电线,等等)。因此,RNN/LSTM 和变体不是硬件加速的良好匹配,我们在此处和此处的之前讨论过这个问题。一个解决方案将是在内存设备中进行计算,就像我们在 FWDNXT 上所做的那样。
笔记
注 1: 分层神经注意类似于 WaveNet 中的思路。但是我们使用分级注意模块,而不是卷积神经网络。另外:分级神经注意力也可以是双向的。
注 2: RNN 和 LSTM 是内存带宽受限问题(详见此)。处理单元需要的内存带宽与它们能够提供的操作数一样多,因此不可能充分利用它们!外部带宽永远不够,稍微改善这个问题的方法是使用高带宽的内部快速缓存。最好的方法是使用不需要从内存中来回移动大量参数的技术,或者可以重复用于每个传输字节的多次计算的技术(高算术强度)。
注 3 :这里有一篇比较 CNN 和 RNN 的论文。时间卷积网络(TCN)“在各种任务和数据集上优于 LSTMs 等典型递归网络,同时表现出更长的有效记忆”。
注 4 :与这个话题相关的是,我们对人类大脑如何学习和记忆序列知之甚少。“我们通常以较小的片段来学习和记忆较长的序列,例如一个电话号码 858 534 22 30 被记忆为四个片段。行为实验表明,人类和一些动物在各种各样的任务中采用了这种将认知或行为序列分解成组块的策略”——这些组块让我想起了较小序列上的小卷积或注意力网络,然后这些小卷积或注意力网络按层次串在一起,就像在分层神经注意力编码器和时间卷积网络(TCN)中一样。更多的研究让我觉得工作记忆类似于使用递归真实神经元网络的 RNN 网络,它们的容量很低。另一方面,大脑皮层和海马体都让我们能够记住很长的步骤序列(比如:5 天前我在机场把车停在哪里),这表明回忆长序列可能涉及更多的平行路径,其中注意力机制控制重要的块,并迫使序列中与最终目标或任务无关的部分跳跃。
注 5: 以上证据表明我们没有按顺序阅读,事实上我们是把字、词、句作为一个整体来解读的。一个基于注意力的或卷积的模块感知序列,并在我们的头脑中投射一个表征。如果我们按顺序处理这些信息,我们就不会误读了!我们会停下来注意不一致的地方!
注 6: 一篇最近的论文用 attention/transformer 进行无监督训练,在迁移学习中表现惊人。NLP 的 VGG?这项工作也是杰瑞米和塞巴斯蒂安的开创性工作的延伸,其中一个具有特别训练程序的 LSTM 能够在无人监督的情况下学习预测一系列文本中的下一个单词,然后也能够将这些知识转移到新的任务中。此处给出了 LSTM 和 Transformer(基于注意力)的有效性比较,并显示注意力通常是注意力获胜,并且“仅 LSTM
在一个数据集上优于 Transformer——MRPC。”
注 7 : 在这里你可以找到关于变压器架构和数据流的精彩解释!
关于作者
我在硬件和软件方面都有将近 20 年的神经网络经验(一个罕见的组合)。在这里看关于我:媒介、网页、学者、 LinkedIn 等等…
复杂世界中预测的谬误
“统计预测只在无菌的实验室条件下有效,这突然变得不像以前那样有用了。”——Gary King
我注意到基于“预测分析”、“预测”、“统计分析”和最新术语“近似预测”的火灾和 EMS 部署模型有上升趋势。最近,一份基于奥兰治县消防局(OCFA)的“覆盖标准”报告提出了一种部署模型,该模型基于夜间低水平的火灾减少了午夜时段的灭火单位。当我读到这些报告时,我想站起来大声说“事情不是这样的;这一切都不是这样的。”
首先,发生的频率不等于风险水平。换句话说,一个事件从未发生过,并不意味着它发生的概率很低。考虑被蛇咬伤的情况。我从未被响尾蛇咬过;因此,我的出现频率为零。但是被蛇咬的频率为零并不能说明被蛇咬的风险。如果我把手伸到有响尾蛇的岩石下,我被咬的风险非常高,不管发生的频率如何。但这正是《OCRA 覆盖标准》的作者在提出基于发生频率的部署模型时所使用的逻辑。
在试图解释所发生的事情时,研究历史统计数据会非常有用。但是仅仅识别统计数据中的趋势并不能自动转化为对未来的预测。统计是解释工具,不是预测工具。如果你试图将统计数据整合到预测模型中,你可能会发现自己溺死在平均只有 4 英尺深的湖里,或者在平均温度为 75 度的建筑物中被烧死。
在平均温度 75 度的建筑里被烧伤
想象一下,你带着两辆车来到一栋四层公寓楼的火警现场;布莱斯和皮埃尔都是世界著名的统计学家。当布莱斯和皮埃尔认出这个地址是他们研究了多年的一栋建筑时,他们的脸上露出了兴奋的表情,这栋建筑的每个房间都安装了远程传感器。他们立即在手机上打开一个应用程序,访问该建筑的统计数据。
火警面板显示四楼有火警。你的船员拿起装备,向楼梯走去。皮埃尔突然抗议道。根据这些数据,Pierre 声称你应该离开设备,乘电梯而不是爬楼梯。“我们有所有的数据”皮埃尔喊道。“大楼里的平均温度只有 75 度。我们已经监视这座建筑很多年了,根据统计趋势,我们有 99%的把握没有发生火灾。这栋建筑的火灾是一个 sigma 事件。”
你的船员无视皮埃尔,爬上楼梯。坚持不懈,皮埃尔跟着,继续用诸如相关性、中心极限定理、干扰和回归分析等术语来攻击你。
在四楼,当你打开通往烟雾弥漫的走廊的楼梯井的门时,皮埃尔发出了最后一次抗议;"发生火灾几乎是不可能的,我担心你对拉普拉斯定律缺乏了解。"就在掩饰之前,你大声回应;是的,先生,但是我担心你对墨菲定律缺乏了解
墨菲定律——“任何可能发生的事情都会发生”——奥古斯都·德·摩根,1866 年
墨菲定律的起源是不确定的,但它通过我们的文化的超越是对其真理的认可。虽然不是普遍适用的(你的车不会变成火鸡),墨菲定律的哲学与应急管理领域相关;在我们的理想世界中,我们期待最好的,但在现实世界中,我们做最坏的打算,准备大吃一惊。
理想主义者 vs 现实主义者
在理想世界中,事件以一种孤立的、可预测的模式发生;所有可能的变量都可以绘制出来,并与备选方案进行权衡,从而产生精确的预测。
然而,在现实世界中,事件并不是孤立的,模式是不稳定的,无数的变量相互作用,创造出难以想象的事件,就像生命本身一样。唯心主义和现实主义对立的世界观从一开始就困扰着概率领域。
概率的起源——赌博公元 1653 年
先验的,事前知道的
1653 年,年轻的法国学者布莱士·帕斯卡发表了《算术三角形论》,现在被称为帕斯卡三角形。帕斯卡发明了一种方法来预测游戏的结果,通过绘制出每一种可能的结果,并将其与备选结果进行比较。
例如,如果我问在六面骰子上掷出“3”的几率,帕斯卡的理论是我们如何计算几率为 1/6,因为“3”是六个同等可能性选项中的一个。如果我问在八面骰子上掷出“1”或“2”的几率,几率是八分之二。随着变量的增加,程序变得指数级复杂,但是过程仍然是相同的。
Pascal’s Triangle based on the roll of two ten sides dice
尽管很聪明, Pascal 方法是为在无菌和受控的环境中玩游戏而设计的。帕斯卡从未打算将他的工作应用于现实世界,正如我们将在他的个人生活中看到的那样,帕斯卡使用了一种完全不同的方法,我称之为“风险管理”。
弥合差距——从理想到现实
后验——基于过去的事件
帕斯卡之后大约一百年,皮埃尔·西蒙·拉普拉斯想在现实世界中做出预测,特别是天体的运动。由于缺乏帕斯卡在他的机会游戏中所享受的每个变量的确切知识,拉普拉斯用历史数据代替了游戏中的已知变量。换句话说,帕斯卡知道每个骰子的边数,而拉普拉斯方法通过观察多次滚动来猜测骰子的边数,或者更确切地说是出现的频率。但是拉普拉斯并没有预测在六面骰子上掷出“1”的几率;他在预测明天太阳升起的几率。拉普拉斯的工作演变成一个复杂的领域,需要根据数据的质量和大小来衡量对结果准确性的信心,而帕斯卡的预测非常准确,因为他在游戏开始前就知道所有的变量。拉普拉斯是学者中真正的巨人,推动了数学、统计学、物理学和天文学的发展。然而,他的方法可能会被错误应用和过度利用;站在巨人的背上伴随着悲惨坠落的风险。
墨菲定律 Vs 拉普拉斯
顺便说一下,拉普拉斯根据历史数据计算出明天太阳升起的几率为 99.999999……%,这是基于历史数据可以做出的最有把握的预测。然而,太阳的衰老保证了太阳没有升起的一天。按照墨菲定律,拉普拉斯的预测充其量是 99%准确,但总有一天会 100%错误。
比喻利用历史数据进行预测
想象一下,你正在驾驶一辆挡风玻璃被遮住的汽车,后视镜是你唯一的导航工具。后视镜提供了周围环境的线索,如道路的宽度、路肩的深度、地形的坡度和道路的模式。通过大量的努力和一点点直觉,你会适应你身后的画面,让你根据你注意到的趋势选择一个舒适的速度。一条简单的直路和宽阔的路肩可以让你加速,而一条复杂的弯道会让你减速。但是如果路况改变,你的速度永远不会超过你的恢复能力。
在你的旅途中,你会遇到一个被轻微烧伤的法国统计学家,皮埃尔。你的新乘客对保持汽车行驶所需的努力感到惊讶,并主动提供帮助。他确定了一个与道路方向“高度相关”的“描述性数据样本”,或者用外行人的话来说,他说只要看看道路上画的黄线就行了。
接受 Pierre 的建议,你把注意力集中在黄线上,这比测量整个环境要容易得多。你放松并享受旅程,感谢你的新朋友。
在匆忙去当地诊所检查烧伤的时候,Pierre 建议你开快点,因为他 99%的信心是当前的趋势会继续下去,误差很小。如果道路急转弯,仅仅基于预测的新速度超出了你的恢复能力。当汽车加速时,一种本能的恐惧爬上你的心头,皮埃尔令人眼花缭乱的数学超越了你的判断。
金融业从预测中学到了什么
一个预测模型,“风险价值”(VaR)被广泛认为是 2006 年金融危机的原因。简而言之,VaR 将金融公司的累积风险总结为一个基于概率的指标;创建一个优雅、精确的风险衡量标准,但这个标准存在严重缺陷。用对冲基金经理大卫·艾因霍恩(David Einhorn)的话来说,风险值“当它的使用在高管中造成一种虚假的安全感时,可能是灾难性的。”
A VaR chart showing a 95% probability the portfolio will stay above 42 mil.
风险值误导预测的可能性遭到了猛烈抨击,风险经理和学者纳西姆·塔勒布(Nassim Taleb)在国会作证,要求禁止金融机构使用风险值。事实上,出于直觉,塔勒布在 1997 年公开预测了过度杠杆化预测模型所造成的损害,声称 VaR“忽视了 2500 年的经验,而倾向于非交易者建立的未经测试的模型”,这些模型“给出了错误的信心”,因为“不可能估计罕见事件的风险。”
尽管有这些缺点, VaR 型预测模型已经投入使用。从 1972 年 RAND 报告“纽约市消防项目部署研究”开始,一个令人印象深刻的预测分析显示建议关闭消防站。“确信他们的统计训练胜过了经验丰富的消防官员的经验,”兰德花了几年时间建立计算机模型来预测火灾,并根据分析结果实施车站关闭。其结果是许多不受控制的火灾和超过 60 万人从烧毁的家园流离失所。FDNY 让令人眼花缭乱的数学超越了他们的判断。
A scientific study showing the result of cutting the NY fire department, including the spread of tuberculosis and HIV
预测就像电锯,很容易用,很难用好,而且总是很危险。
随着亚特兰大和辛辛那提等城市投入预测分析,纽约正在用 FireCast 进行另一次尝试,“一种将来自五个城市机构的数据组织成大约 60 个风险因素的算法,然后用于创建最容易发生火灾的建筑物列表。”根据脆弱性对建筑物进行排名似乎是合理的,但是一旦你开始预测一个复杂系统中的事件,挑战就出现了。
想想预测 2016 年世界职业棒球大赛第七场冠军的难度。相对而言,这是一个简单的问题;你只有 50 个参与者在有限的时间内玩一个规定的游戏。你的参与者都有大量来自相对无菌环境的描述性和预测性数据。然而这场比赛的结果直到比赛结束都不为人知。
将简单的棒球问题与预测一个拥有一百万居民的城市在无限时间框架内的复杂行为进行对比。我们用一个简单的系统将一个模型扩展到极限,并试图将它扩展到超乎想象的程度,以适应一个复杂的系统。
复杂系统对简单系统
概率有效,预测有效——在正确的领域,简单的系统。Cynefin 框架将简单系统定义为“已知的已知”。像棒球比赛一样,简单的系统是稳定的,具有可识别的、可重复的和可预测的因果关系,例如预测未来五年消防车的行驶里程。在简单的系统中,你研究历史,预测未来,并制定计划。
与复杂系统相反,复杂系统中的因果关系只能在事后才能察觉。由于大量的变量和影响,这些系统继承了不可预测性。这就是墨菲定律的由来。简单的系统容易剖析和理解,但复杂的系统“不受简化论者的影响,因为你的行动以不可预测的方式改变了情况。”在复杂的系统中,概率是有限的,预测造成了一种虚假的自信感,墨菲定律是正确的。
城市是复杂的系统。人类行为是一个复杂的系统。由人类行为引发的城市火灾极其复杂。对于那些声称用数学模型预测复杂系统未来,却不能自信地预测下一届超级碗冠军的人,要持非常怀疑的态度。
“所有的模型都是错误的;有些是有用的。”乔治·博克斯
概率是一种辉煌的方法论,最初是为毫无结果的机会游戏设计的,后来演变成一个令人眼花缭乱的数学领域。概率在适当的情况下起作用,但如果过度利用,可能会产生致命的结果。用作者查尔斯·惠兰的话说,“概率不会出错;使用概率的人会犯错。”金融业和消防服务已经被过度杠杆化的预测模型所吞噬。数学是惊人的,结果是优雅的,但如果应用于错误的领域,后果是灾难性的。不要让数学超越你的智慧。
尾声——帕斯卡的赌注
概率之父帕斯卡明白他的方法在现实生活中的局限性。当被要求就上帝的存在打赌时,帕斯卡没有考虑上帝存在的概率、赔率或证据。帕斯卡考虑了错误的后果,并选择了后果最小的选项。帕斯卡得出结论,接受上帝的存在和错误没有比选择更大的后果。但是否认上帝的存在和犯错会带来巨大的后果,包括在地狱里永世不得超生。
Pascals wager
概率之父帕斯卡声称,当一个理性的人在处理未知时,他们应该考虑后果,而不是几率。证据表明,帕斯卡理解墨菲定律,是一个真正风险管理者。
并且可以在推特上关注 @saylorssays
我们在公共安全领域面临的最大挑战之一是以可量化的方式阐明我们的价值。这个挑战是…
medium.com](https://medium.com/elitecommandtraining/quantifying-the-negative-the-true-value-of-the-fire-service-f1093e4bcfc2)
最后一幕——就像一个天真的贝叶斯专家!
对于 ML 初学者
从零开始展开朴素贝叶斯!Take-3🎬
你几乎是在掩盖朴素贝叶斯文本分类算法的所有方面。
以防你错过了之前的博文,你可以参考下面的链接
从零开始展开朴素贝叶斯 Take-1🎬 !一个简单明了的朴素贝叶斯解释,以便在开始编码之前清楚地了解这个算法是如何工作的
从零开始展开朴素贝叶斯!take-2🎬 :在转向 python 的 ML 工具包之前,在基本 python 中从头实现朴素贝叶斯只是为了巩固核心理解
目标受众是谁?🗣 🗣 🗣
就像我在以前的博客文章中提到的一样,这篇文章也是为 ML 初学者准备的——关注基本概念。
本教程的成果—NB 的实践 Scikit-learn 实施
使用 Python 的机器学习框架 Scikit-learn 实现 NB 的完整演练
定义路线图……🚵
里程碑# 1: 预处理训练数据集
里程碑# 2: 在预处理的训练数据集上训练 NB 模型
里程碑# 3: 使用训练好的 NB 模型 进行测试
里程碑# 4: 培训&使用 Scikit 测试-学习管道功能
让我们从 Scikit-learn 实现开始吧!
预处理训练数据集
一些进口货…
预处理函数与从头开始展开朴素贝叶斯中定义的相同!Take-2🎬
正在加载 20 个新闻组数据集
这与之前在从头开始展开朴素贝叶斯中使用的数据集相同!Take-2🎬
这是原始形式的训练数据集的样子……
让我们从训练数据集的预处理开始,包括
- 文本清理
- 创建我们的训练数据集的 BoW 表示(测试数据集也需要同样的表示)
文字清理
处理后的训练数据集如下所示
创建我们的训练数据集的 BoW 表示
count vectorizer 上的几行
计数矢量器的作用是什么?
接收文本语料库,建立其术语文档矩阵(即 BoW ),并将其返回每个单词被分配一个固定的唯一整数 id,该矩阵的每个单元的值代表单词计数——BoW
例如,X_train_counts[ i,j ] ( i 指的是一个文档,在我们的例子中,每个文档指定一个训练示例,j 指的是单词 w 在其各自的文档 I 中的索引)将返回单词 j 的计数
下面是 X_train_counts 矩阵的样子:
X_train_counts[0,12048]将检索整数 id = 12048、文档/示例 id 为 0 的 word 的字数
里程碑# 1 已实现👍
在预处理的训练数据集上训练 NB 模型
简单地在实例化一个 NB 对象后,我们调用拟合函数来训练一个 NB 模型。我们将简单地传递训练示例作为第一个参数&训练集标签作为第二个参数。
注意,X_train_counts(术语文档矩阵)作为训练示例而不是文本数据被传递
我们只用 3 行代码就完成了培训!
里程碑# 2 已实现👍 👍
使用经过训练的 NB 模型进行测试
在我们开始测试之前,我们将首先需要以与训练数据集相同的方式对其进行预处理
测试设置文本清理
创建测试数据集的 BoW 表示 为训练数据集实例化的相同 count_vect 对象将用于测试数据集。但是请记住,我们不是在测试集上调用 fit_transform,因为我们只想将测试数据转换为术语-文档矩阵,而 fit_transform 首先学习词汇词典,然后返回术语-文档矩阵。我们应该只学习训练数据集中的词汇
fit_transform : learns the vocabulary dictionary and returns term-document matrixtransform : transforms documents to document-term matrix
现在我们可以在测试数据集的转换版本上进行测试
我们将简单地调用为 NB 模型拟合/训练的 clf 对象上的预测函数
里程碑# 3 实现 👍 👍 👍
培训&使用 Scikit 测试-学习管道功能
管道创造奇迹!通过使用 sklearn 的管道功能,上述代码可以进一步减少到 3 行代码
我们只需通过指定管道动作来构建一个管道对象,一旦该管道对象用于训练,它将按照指定的顺序自动执行管道步骤。
在我们的例子中,因为我们首先需要为 BoW 构建一个 CountVectorizer,然后拟合/训练一个 NB 模型,所以以完全相同的方式,我们将在管道中指定这些操作。
请注意,现在当调用 fir 方法时,我们将传递原始文本数据,因为现在管道中的 count_vect 将自己将其转换为数字形式。因此,在这里传递文本数据很重要,否则会出现令人讨厌的错误。测试数据也是如此。不需要单独对其进行计数矢量化,但我们需要从清理的角度对测试数据进行预处理
最后一部分——测试
所有的培训和测试只需 3 行代码!
你做到了!
里程碑# 4 实现 👍 👍 👍 👍
你可以在 Jupyter 笔记本 这里 找到所有源代码
如果您有任何想法、意见或问题,欢迎在下面评论或联系📞与我一起上 LinkedIn
实验的第一个幽灵:要么有意义,要么是噪音
汤姆·奥利弗,科林·麦克法兰和利兹·埃德里
The first Ghost of Experimentation: It’s either significant or noise
👻这篇文章是探索导致追逐统计幽灵的实验从业者普遍误解的系列文章的一部分。
在进行了一项实验后,我们想了解观察到的任何差异是随机噪声,还是真实的。不幸的是,确认偏差表明我们倾向于以确认我们已经想到的方式来消化数据。
实验者很容易思考,如果实验没有达到预先设定的宣布信号而不是噪声的阈值,那么这些实验是否是“几乎显著的”或类似的短语。p 值是反直觉的,经常被曲解,所以让我们来探讨如何更彻底地对 p 值做出反应。
一个 p 值试图回答这个简单的问题:这个数据有多令人惊讶?或者更正式地说:给定零假设,找到观察到的(或更极端的)数据的概率是多少。p 值提供了一个条件概率,因为它假设零假设为真。
“从某种意义上来说,它(p 值)提供了防止被随机性愚弄的第一道防线,将信号与噪声分开”——Benjamini,2016 年
标准的显著性水平是 0.05。在这种情况下,如果 p 值小于 0.05,这意味着您观察到的数据只是偶然发生的条件概率(假设为空)小于 5%。因此,如果我们结束实验,观察到 p 值为 0.05,根据数据,我们可以有把握地说零假设是不正确的,并接受观察到的因果关系。
“但我的结果几乎意义重大”…
这可能会有问题;一个实验数据样本并不具有显著性——结果要么显著,要么不显著,否则无法定性。这是对 p 值如何工作的最大误解,或者更确切地说,是对它们如何分布的误解。
我们可以通过模拟抛硬币实验来证明这一点。如果我们模拟 100,000 次实验,其中我们将两个无偏的硬币翻转 100,000 次以创建我们的 A 组和 B 组,那么我们预计在大约 5%的时间(使用标准水平)中会看到两组之间的显著差异。下面的散点图显示了每个实验的一个点,如果 A 和 B 之间的差异显著,则每个点都是红色的,如果不显著,则是蓝色的:
因此,我们确实看到了显著性的预期模式,5.0%的实验显示了显著差异。更有趣的是,当我们观察 p 值在所有实验中的分布时。
请记住,硬币是无偏的,所以测试实验就像 A/A 实验一样,处理之间没有真正的区别:
我们看到的是,当数据中不存在真效应时(或者当零假设为真时),每个 p 值的概率是相等的。实验并不致力于显著性,在阈值之外比较 p 值的相对显著性是一个错误,会导致大量的假阳性。
p 值不应被视为显著,除非它在显著性水平内-当测试假设(拒绝空值)时,我们只能这样做,或者不这样做,所以找到显著性或声明不显著。如果我们没有达到预定的阿尔法水平,我们只能保持不确定。
丹尼尔·拉肯斯提供了一个简单的纠正你可以遵循,以避免长期以来经常出错。其中α是我们的显著性水平:
p <= alpha: Act as if the data is not noise.
p > alpha:保持不确定性或表现得好像数据是噪音一样。
👻更:追统计鬼。
与我们合作
我们在 Skyscanner 以不同的方式做事,我们正在全球办事处寻找更多的工程团队成员。看看我们的 Skyscanner 职位寻找更多空缺。
Team in action.
我做的第一个机器学习程序。
我做的第一个机器学习程序是 2011 年我上高中时提交的 NASA 陨石坑识别竞赛
下面是链接:Ideone.com
编写这段代码花了我几周时间和大量的研究。很有趣!我已经设法通过一个非常聪明的优化来调整算法性能。
它没有包含很多机器学习,主要是计算机视觉。然而,我已经成功地使用简单的逻辑回归调整了它的参数!:)我一直非常兴奋,我的提交获得了高分,这激励我将我的职业生涯奉献给这一领域。
它首先使用高斯滤波器对数据进行预处理,以消除可能误导进一步视觉算法的噪声。
下一步,我使用了一个 Sobel 算子。它将图像转换为黑白轮廓图像,其中黑色代表图片的相似部分,白色代表边缘——图像的两个一致部分相互接触的地方。
预处理后,核心组件基于霍夫变换——一种识别圆形等形状并将它们转换到概率空间的算法。
这个想法是扫描图像,寻找不同大小和形状的椭圆,这是环形山的特征。
最后,将启发式和线性模型相结合来产生结果。它已经使用单独的可执行文件进行了微调,以使用线性回归找到最佳参数。
转贴自 Quorahttps://www . Quora . com/What-is-the-first-the-machine-learning-program-you-made
足球德比——一个数据科学故事
因此,这是我今年夏天发表的一系列中型文章中的下一篇文章,在这篇文章中,我一直致力于培养我在数据科学方面的技能,以朝着数据科学家的职业生涯迈进。
处理足球数据是我长期以来一直想做的事情,这一次,我抓住机会,利用足球运动员位置的数据集,对不同的比赛顺序和比赛进行了分析,以得出一些关于比赛顺序或比赛本身的有趣见解。
Photo by Willian Justen de Vasconcellos on Unsplash
我从 STATS,从他们的网站https://www.stats.com/data-science/获得了这个数据集。您可以从他们的网站上填写足球数据的申请表,以便发送数据请求,之后他们会在向您提供数据集之前向您发送一份协议供您签署。
这个分析的 Jupyter 笔记本是这里的。
出发
所以总结一下我在这次分析中想要做的事情
- 想象足球比赛的顺序,
- 显示关于单个游戏序列序列统计数据,
- 想象比赛中球员在球场上的位置,
- 对数据集应用 KMeans 聚类,以获得关于数据的有趣见解
数据集结构
数据集包含来自实际足球比赛的多列比赛序列(“序列 _1”到“序列 _18”),其中记录了每个球员和球的位置
让我们根据上面的可用信息定义数据中的列:前 22 列是防守球员的 X,Y 位置,后 22 列是进攻球员的 X,Y 位置,最后 2 列是比赛中球的 X,Y 位置
TLDR;关于数据集的这些信息是随数据集一起提供的,如果您想了解关于数据集的详细信息,请阅读此信息
数据集中包括 7500 个序列的训练集和两个单独的测试序列集。Python 用户可以将训练数据(以 pickle 格式)加载到字典中,每个序列的键将是“ sequence_n ”,其中 n 是从 1 到 7500 的任意值。
每个序列包含一段对应于最近职业足球联赛的实际比赛的跟踪数据。每个序列的格式如下:
-每个序列是具有 46 列的矩阵(numpy 2D 阵列)。每一行包含 23 对(x,y)坐标,来自两个队的 22 名球员和频率为 10Hz 的球。
——前 22 列是 11 对(x,y)联防队员。接下来的 22 列是进攻球队的坐标(定义为连续控球的球队)。最后两列是球的坐标。
-攻击队和防守队的每组 22 列包括守门员的(x,y)对,随后是其他 10 名队友的 10 个连续的(x,y)对。身份和团队因序列而异。然而,在每个序列中,身份是一致的。因此,具体来说,在每个序列的 46 列中,我们知道前 2 列代表防守队守门员的坐标。列 2 到 22 包含 10 对连续的(x,y)其他防守队员。列 23 和 24 携带攻击队守门员的 x 和 y 坐标。列 25 到 44 包含 10 对连续的(x,y)其他进攻队员。列 45 和 46 携带球的 x 和 y 坐标。
-坐标通常属于沿 x 轴的[-52.5 米,+52.5 米]范围和沿 y 轴的[-34 米,+34 米]范围,间距的正中心为[0,0]。因此,例如,要将数据标准化到范围[-1,+1],可以简单地将 x 列除以 52.5,y 列除以 34(这将有效地重新缩放球场,大致相当于 105×70 米大小的足球场,从矩形框到正方形框)
-坐标也进行了调整,以便攻击队从左向右移动,这意味着防守队在右手边防守球门。
-总的来说,该数据集相当于大约 45 场比赛的比赛时间,其中删除了冗余和“死亡”情况。
采集和处理数据
为了开始这个分析,我将数据集导入 Jupyter 笔记本。数据在数据库里。pkl '格式,这对我来说是新的,但是快速的谷歌搜索显示了熊猫的 pd.read_pickle 功能。
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib import patches
import numpy as np
%matplotlib inlinedata = pd.read_pickle('football/test_data_1.pkl')
让我们根据上面的可用信息定义数据中的列:前 22 列是防守球员的 X,Y 位置,后 22 列是进攻球员的 X,Y 位置,最后 2 列是比赛中球的 X,Y 位置
columns = ['GKDef_X', 'GKDef_Y', 'Def1_X', 'Def1_Y','Def2_X', 'Def2_Y','Def3_X', 'Def3_Y','Def4_X', 'Def4_Y','Def5_X', 'Def5_Y', 'Def6_X', 'Def6_Y', 'Def7_X', 'Def7_Y','Def8_X', 'Def8_Y','Def9_X', 'Def9_Y','Def10_X', 'Def10_Y', 'GKAtt_X','GKAtt_Y','Att1_X','Att1_Y','Att2_X','Att2_Y','Att3_X','Att3_Y','Att4_X','Att4_Y','Att5_X','Att5_Y','Att6_X','Att6_Y','Att7_X','Att7_Y','Att8_X','Att8_Y','Att9_X','Att9_Y','Att10_X','Att10_Y','Ball_X','Ball_Y']
从这里开始,现在是时候创建一个熊猫数据框架来保存这些值了
test_sequence = 'sequence_1'
df = pd.DataFrame(data[test_sequence], columns = columns)
df.head(5)
Result from the code above, we can see now the data split into the respective columns in a DataFrame
想象足球场和球的运动
在分析的这一部分,我们将把上面的内容转换成球的位置的可视化。让我们使用上面设计的列将数据转换成数据帧,并显示测试序列的球的轨迹。这是序列中单个时间点的球位置代码。
# Obtaining the positions occupied by the ball
ball_pos = df[['Ball_X','Ball_Y']].values.tolist()
ball_pos[0]# Output = [-19.961977005004883, 3.843478202819824]
这里是构建球场的代码,这里我使用 matplotlib 来构建它,并使用了这篇文章中的代码。
# Plotting the ball along with the position of the ball
# Run with createPitch([]) to just display the pitch
def createPitch(ball_pos, defense_pos, attack_pos, size=0.2):
#Create figure
fig=plt.figure()
ax=fig.add_subplot(1,1,1)#Pitch Outline & Centre Line
plt.plot([-52.5,-52.5],[-35,35], color="black")
plt.plot([-52.5,52.5],[35,35], color="black")
plt.plot([52.5,52.5],[35,-35], color="black")
plt.plot([52.5,-52.5],[-35,-35], color="black")
plt.plot([0,0],[-35,35], color="black")
#Left Penalty Area
plt.plot([-39.5,-39.5],[16,-16],color="black")
plt.plot([-52.5,-39.5],[16,16],color="black")
plt.plot([-39.5,-52.5],[-16,-16],color="black")
#Right Penalty Area
plt.plot([39.5,39.5],[16,-16],color="black")
plt.plot([52.5,39.5],[16,16],color="black")
plt.plot([39.5,52.5],[-16,-16],color="black")
#Left 6-yard Box
plt.plot([-52.5,-47.5],[-10,-10],color="black")
plt.plot([-47.5,-47.5],[-10,10],color="black")
plt.plot([-52.5,-47.5],[10,10],color="black")
#Right 6-yard Box
plt.plot([52.5,47.5],[-10,-10],color="black")
plt.plot([47.5,47.5],[-10,10],color="black")
plt.plot([52.5,47.5],[10,10],color="black")
#Create Arc and add it to our plot
leftArc = patches.Arc((-45.5,0),height=18.3,width=18.3,angle=0,theta1=310,theta2=50,color="black")
rightArc = patches.Arc((45.5,0),height=18.3,width=18.3,angle=0,theta1=130,theta2=230,color="black")#Assign circles to variables - do not fill the centre circle!
centreCircle = plt.Circle((0,0),10,color="black",fill=False)
centreSpot = plt.Circle((0,0),0.8,color="black")
leftPenSpot = plt.Circle((-43.5,0),0.4, color="black")
rightPenSpot = plt.Circle((43.5,0),0.4, color="black")
#Draw Arcs
ax.add_patch(leftArc)
ax.add_patch(rightArc)#Draw the circles to our plot
ax.add_patch(centreCircle)
ax.add_patch(centreSpot)
ax.add_patch(leftPenSpot)
ax.add_patch(rightPenSpot)
# Plotting the ball
for pos in attack_pos:
locBall = plt.Circle((pos[0],pos[1]),size,color="red")
ax.add_patch(locBall)
for pos in defense_pos:
locBall = plt.Circle((pos[0],pos[1]),size,color="blue")
ax.add_patch(locBall)
for pos in ball_pos:
locBall = plt.Circle((pos[0],pos[1]),size,color="green")
ax.add_patch(locBall)
createPitch(ball_pos, [], [])
Result from the code above, position of the ball
想象整个游戏过程
在我们连接数据之前,我们必须做一些数据处理来转换每个序列中球员的位置。这一部分将会非常代码密集,但是最终结果是非常值得努力的。
positions = []
new_cols = columns + ['seq']
for seq in data:
for d_seq in data[seq]:
seq_list = d_seq.tolist()
seq_list.append(seq)
positions.append(seq_list)
df_data = pd.DataFrame(positions, columns = new_cols)df_data.seq = df_data.seq.apply(lambda x: int(x.strip('sequence_')))
sequences = list(set(df_data.seq))
grp = df_data.groupby('seq')
sequenced_data = []
for sequence in sequences:
sequenced_data.append(grp.get_group(sequence))
sequenced_data[0].head(5)
We just made a ‘seq’ column to store the entire dataset within this dataFrame and grouped by sequence
现在更多的争论是如何将每个球员的 X 和 Y 组合起来,并根据上面数据框中的值提供一个在球场上的位置。
def parse_data(data, seq):
df = data[seq]
defense = []
attack = []
ball = []
defense.append(df[['GKDef_X','GKDef_Y']].values.tolist())
defense.append(df[['Def1_X','Def1_Y']].values.tolist())
defense.append(df[['Def2_X','Def2_Y']].values.tolist())
defense.append(df[['Def3_X','Def3_Y']].values.tolist())
defense.append(df[['Def4_X','Def4_Y']].values.tolist())
defense.append(df[['Def5_X','Def5_Y']].values.tolist())
defense.append(df[['Def6_X','Def6_Y']].values.tolist())
defense.append(df[['Def7_X','Def7_Y']].values.tolist())
defense.append(df[['Def8_X','Def8_Y']].values.tolist())
defense.append(df[['Def9_X','Def9_Y']].values.tolist())
defense.append(df[['Def10_X','Def10_Y']].values.tolist())
attack.append(df[['GKAtt_X','GKAtt_Y']].values.tolist())
attack.append(df[['Att1_X','Att1_Y']].values.tolist())
attack.append(df[['Att2_X','Att2_Y']].values.tolist())
attack.append(df[['Att3_X','Att3_Y']].values.tolist())
attack.append(df[['Att4_X','Att4_Y']].values.tolist())
attack.append(df[['Att5_X','Att5_Y']].values.tolist())
attack.append(df[['Att6_X','Att6_Y']].values.tolist())
attack.append(df[['Att7_X','Att7_Y']].values.tolist())
attack.append(df[['Att8_X','Att8_Y']].values.tolist())
attack.append(df[['Att9_X','Att9_Y']].values.tolist())
attack.append(df[['Att10_X','Att10_Y']].values.tolist())
ball = df[['Ball_X','Ball_Y']].values.tolist()
def_list = []
att_list = []
for i in range (0,11):
def_list = def_list + defense[i]
att_list = att_list + attack[i]
return def_list, att_list, ball
现在到了关键时刻,想象防守球员和进攻球员的整个比赛过程。这里进攻队用红色表示,防守队用蓝色表示
list_defense, list_attack, list_ball = parse_data(sequenced_data,0)
createPitch(list_ball, list_defense, list_attack)
Visualizing a sequence of play, attacking team in red, defending team in blue
不错!以我从小看足球训练有素的眼光来看,这里我们想象一名后卫将球回传给守门员,长时间踢向前锋/中场,绿色虚线是传球。
单个游戏序列的统计
我在这里选择了另一个序列,因为在进攻和防守队伍的位置之间有更多的重叠。这看起来像一个通向目标的复杂的传球序列
The sequence we will be working with for the analysis
球员和球的关系
我构建了一个函数来找出球员与球之间的距离,并返回一个距离列表来绘制球员与球之间的关系。你可以在我的笔记本这里找到这部分分析的代码
A complex sequence of play leading to a shot visualized with the player’s distances from the ball plotted over the time of the sequence
我们可以看到进攻和防守队伍中的一些球员如何在同一时间出现上升/下降,因为他们经常对传球做出反应。
进攻统计—控球
从这部分分析来看,每支球队的控球统计是一个简单的步骤。每当球的位置非常接近球员的位置时,就说球在球员手中。该序列应该对进攻方而不是防守方有更多的机会,因为数据集是作为进攻序列构建的。
让我们来看看这部分的代码
player_ppa = []
player_ppd = []
for i in range(0,11):
player_df = pd.DataFrame(player_game_plot[i], columns = ['player', 'seq_num','def_ball','att_ball'])
# Adding values to each team ppa = attacking ppd = defending
player_ppa.append((player_df[player_df['att_ball'] < 2].seq_num.count()/len(player_game_plot[i]))*100)
player_ppd.append((player_df[player_df['def_ball'] < 2].seq_num.count()/len(player_game_plot[i]))*100)# create plot
fig, ax = plt.subplots()
index = np.arange(0,11)
bar_width = 0.4
opacity = 0.8
rects1 = plt.bar(index, player_ppa, bar_width,
alpha=opacity,
color='b',
label='Attacking')
rects2 = plt.bar(index + bar_width, player_ppd, bar_width,
alpha=opacity,
color='g',
label='Defending')plt.xlabel("Player on team")
plt.ylabel("Percentage with Posession")
plt.legend()
plt.show()
Possession stats for each player in sequence of play
这是一个普遍的趋势,看到攻击队保持球从防守队。我们在这里可以看到,6 名球员比攻击队中的其他人拥有更多的控球权,这表明这次攻击是 6 名球员参与的结果。6 名进攻球员强烈参与了这场比赛,另外 2 名进攻球员轻微参与了这场比赛。
进攻位置——距离球门的距离
现在让我们仔细看看在这个游戏序列中每个玩家离目标的距离。我将距离函数定义为(x0-y0) + (x1-y1)的平方根。
def dist(x, y):
return math.sqrt(math.pow((x[0] - y[0]),2) + math.pow((x[1] - y[1]),2))
在这里,我将计算进攻球员的位置,并找出他们距离球门的平均距离
def attackingPosition(attack):
att_players = np.array_split(attack, 11)
distance = []
# For each sequence time j
for j in range(len(att_players[0])):
# for each player on the attacking team k = 1 to 11
for k in range(11):
# Add the distances of the players on the attacking team to the goal
player_dist = min(dist([52.5,-4], att_players[k][j]),dist([52.5,4], att_players[k][j]))
distance.append((j,k,player_dist))
return distanceatt_positions = attackingPosition(list_att)
att_values = pd.DataFrame(att_positions, columns = ['time', 'player', 'dist'])
players = att_values.groupby(['player']).mean()
然后我试着想象球员离球门的距离,并在做的时候用颜色来取乐。
def plotDistanceFromGoal(player_distances):
ig, ax = plt.subplots()
index = np.arange(0,11)
bar_width = 0.6
opacity = 0.8dist = plt.bar(index, player_distances, bar_width,
alpha=opacity,
label='Attacking team')
# Some fun with colors
colors = ["#FF5733", "#FFFF33", "#33FF39", "#33FFE0", "#333FFF", "#DA33FF", "#FF3333", "#000000", "#0087FF", "#B2FF00", "#00FFC1"]
i = 0
for color in colors:
dist[i].set_color(color)
i+=1
plt.xlabel("Player on attacking team")
plt.ylabel("Distance from Goal")
plt.show()
plotDistanceFromGoal(players['dist'])
Distance from goal for each player on the attacking team
攻击性统计——是目标吗?
现在我们可以看的更重要的一件事是这个序列是否会导致一个目标。这非常简单,因为我可以使用 sequence 的最后一个值,看看它是否在门柱内。这是代码。
def isGoal(sequence):
seq = sequence[-1]
#print(seq)
if (((-39.5 < seq[0] < -52.5) or (39.5 < seq[0] < 52.5)) and ((-4 < seq[1] < 4))):
return True
else:
return False
isGoal(list_ball)# Output: False
**哦,原来这个序列并没有导致一个目标!**我在数据集中搜索了一个序列,找到了这个。
Visualizing a classic counterattack leading to a goal
哇,一个经典的反击导致进球。所以我们的功能似乎是在寻找目标。
防御分析—标记
现在让我们更仔细地看看比赛的防守方,这里我为防守队的每个球员定义了一个新的指标作为最近的进攻球员,以分析这些球员与进攻队的球员的距离有多近。这是一种特征提取的尝试。
现在让我们来看看防守球员盯防对手的能力有多强,这里我假设盯防的唯一标准是与进攻方最近球员的距离。有人指出,这种假设可能是不正确的,因为球员可能会试图阻止传球。但是在这个分析的范围内,我只考虑最近的进攻球员的距离。
分析的这一部分是为了看到同一防守队的不同球员在对攻击的反应上的相似之处。
在下面的函数中,我找到了序列中每个时间步进攻球员与防守球员之间的距离。
def closestPlayerDist(defense, attack):
def_players = np.array_split(defense, 11)
att_players = np.array_split(attack, 11)
distance = []
# For each sequence time j
for j in range(len(def_players[0])):
# for each player on the defensive team k
for k in range(11):
# Add the distances of the players on the attacking team to the list
player_dist = [dist(def_players[k][j], att_players[i][j]) for i in range(11)]
distance.append((j,k,player_dist))
return distancedistances = closestPlayerDist(list_def, list_att)
最近的进攻球员距离测量将显示:
- 拉开距离,防守队中的每个球员在多大程度上缩小了他们盯防的进攻者的空间
- 序列中每个时间步长的平均值将表明团队离拿到球有多近
- 并且序列中每个时间步长的中值将指示运动员的某些部分离球有多近
- 数据序列中每个时间步的变化显示了团队的“静态性”,即他们移动了多少来适应团队的进攻
def plotdist(distances):
distances_2 = [(distances[i][0], distances[i][1], distances[i][2][np.argmin(distances[i][2])]) for i in range(len(distances))]
x = [distances_2[i][0] for i in range(len(distances_2))]
y = [distances_2[i][2] for i in range(len(distances_2))]
plt.plot(x,y,'bo', alpha=0.2)
plt.ylabel('distance of closest attacking player')
plt.xlabel('time')
plotdist(distances)
Distance of closest attacking player for each player on the defending team
def plotmeans(distances):
distances_2 = [(distances[i][0], distances[i][1], distances[i][2][np.argmin(distances[i][2])]) for i in range(len(distances))]
values = pd.DataFrame(distances_2, columns = ['time', 'player', 'dist'])
means = values.groupby(['time']).mean()
medians = values.groupby(['time']).median()
fig, ax = plt.subplots()
x = [i for i in range(len(means))]
ax.plot(x,means.dist,'bo', alpha=0.5)
ax.plot(x,medians.dist,'ro', alpha=0.5)
ax.legend(['mean','median'])
plt.ylabel('mean and median distance of closest attacking player')
plt.xlabel('time')
plt.show()plotmeans(distances)
Mean and median of closest attacking player distance for the sequence of play
def plotvariance(distances):
distances_2 = [(distances[i][0], distances[i][1], distances[i][2][np.argmin(distances[i][2])]) for i in range(len(distances))]
values = pd.DataFrame(distances_2, columns = ['time', 'player', 'dist'])
variance = values.groupby(['time']).var()
fig, ax = plt.subplots()
x = [i for i in range(len(variance))]
ax.plot(x,variance.dist,'go', alpha=0.2)
ax.legend(['variance'])
plt.ylabel('variance of distance to closest attacking player')
plt.xlabel('time')
plt.show()plotvariance(distances)
The variance of closest attacking player distance for sequence of play
player column indicates defense, att_player indicates attack, time indicates percentage of time in sequence spent marking specific attacking player
现在让我们来看看防守方球员盯防对方球员的时间百分比。
这部分的代码
distances_3 = [(distances[i][0], distances[i][1], np.argmin(distances[i][2])) for i in range(len(distances))]marking = pd.DataFrame(distances_3, columns = ['time', 'player', 'att_player'])
marking = marking.groupby(['player','att_player']).count().sort_values(by='time', ascending=False)
marking.time = (marking.time/(len(distances)/11))*100
marking
以我训练有素的眼光来看,我们可以看到防守球员 2、5、10、6 和 1(守门员)靠近他们的进攻球员,但之后有一个急剧下降,这表明防守球员要么被进攻球员超过,要么作为一个团队进行区域防守。
我不认为统计上这是一个伟大的功能,否则。
在整个比赛中可视化球员在球场上的位置,
既然我们现在已经查看了一个单一的游戏序列并对其进行了分析,那么让我们将数据集作为一个整体来看。
球员位置热图
在这里,我们将构建一个玩家位置的热图,并显示每个玩家占据的位置
我首先构建了一个助手函数来解析数据并构建玩家位置的热图。接下来,我必须将这些值解析为整数,因为我使用的是 plt.pcolor,它必须在数据中包含整数值。52 和 35 是硬常数,以确保我的数据中没有任何负值。
def parse_sequence(values, data):
round_data = [(round(x[0]),round(x[1])) for x in data]
for r in round_data:
a = r[0] + 52
b = r[1] + 35
values[b,a] += 1
在这里,我获得了原始数据,并从数据中提取了球员位置的值,用球员的位置填充网格
values = np.zeros((71,107))
ball = np.zeros((71,107))
for i in range(len(sequenced_data)):
list_defense, list_attack, list_ball = parse_data(sequenced_data,i)
parse_sequence(values, list_defense)
parse_sequence(values, list_attack)
parse_sequence(ball, list_ball)
最后,在这个分析的第二个关键时刻,玩家位置的热图
def createGrid(values, title_str):
v = np.asarray(values)
plt.pcolor(v)
plt.title(title_str)
plt.legend()
plt.show()
createGrid(values, "Heatmap for player's position on pitch")
Look at this thing of beauty, heat map for positions of players for all the sequences of play
现在继续,我想看看比赛中的传球,以及整场比赛中球的位置热图。
createGrid(ball, "Heatmap for ball position on pitch")
Heat map for position of the ball throughout the entire game
k 均值聚类分析
显然,有了一组我可以聚集的点,我发布了 KMeans 是聚集这些数据的最简单的方法,以显示对数据的一些有趣的见解
我选择 KMeans 的原因
- KMeans 聚类用于对非结构化数据进行分类——非结构化数据具有两个特征,每个球员位置的 X 和 Y 坐标非常适合分析
- KMeans 通过查找数据的特征映射的质心来工作——我使用它来查找球员位置的 X,Y 坐标的质心,这为进攻和防守团队提供了对团队相对结构的洞察
- 在防守球员和进攻球员的位置上使用 KMeans 将揭示比赛中球场的自然位置
让我们来看一下代码,这是为了获得所有的数据,以馈入我们的 KMeans 分类器
from sklearn.cluster import KMeanslist_def = []
list_att = []
list_bll = []
for i in range(len(sequenced_data)):
list_defense, list_attack, list_ball = parse_data(sequenced_data,i)
list_def = list_def + list_defense
list_att = list_att + list_attack
list_bll = list_bll + list_ball
现在转到 KMeans 分类器和可视化代码。笔记本也可以在这里买到。
def plotKMeans(train, data, title_str, k=11):
# Number of clusters
kmeans = KMeans(n_clusters=k)
# Fitting the input data
kmeans = kmeans.fit(train)
# Getting the cluster labels
labels = kmeans.predict(data)
# Centroid values
centroids = kmeans.cluster_centers_
def xy(lst):
x = [l[0] for l in lst]
y = [l[1] for l in lst]
return x, y
x, y = xy(data)
fig, ax = plt.subplots()
if (title_str[0] == 'D'):
ax.scatter(x, y, marker='o', color='#ffff00', alpha=0.03)
else:
ax.scatter(x, y, marker='o', color='#00ffff', alpha=0.03)ax.scatter(centroids[:,0], y=centroids[:,1], marker='*', c='#050505', s=100)
plt.title(title_str)
plt.legend()
plt.show()
return centroids
k 表示防守和进攻队的质心
现在画出克曼质心和防御队的位置
def_average_pos = plotKMeans(list_def, list_def, "Defensive team average positions")
att_average_pos = plotKMeans(list_att, list_att, "Attacking team average positions")
These do indeed look like formations, but we’ll come to that in a second.
与球的关系
所以这一次,我试着看看球的位置会如何影响进攻和防守球队的 KMeans 集群,但似乎没有太大的影响
Not much of a difference eh?
最活跃的球场区域
现在让我们来看看球场的哪个部分是最受欢迎的,这是对比赛本质的一种洞察。在这里,我将整个数据集的聚类数设为 10,希望看到双方球员在球场上占据的 10 个质心。这是它的代码
plotKMeans(list_def+list_att, list_def+list_att, "Areas of the pitch with most activity", 10)
This resulted in this heat map showing 10 positions (KMeans centroids) on the pitch that players of both teams occupy
形成
现在,我们终于明白了,我们可以看到,使用 KMeans 对 11 个集群进行聚类,我们可以找到防守和进攻团队中每个球员的位置,从而形成一个阵型。现在我从防守队和进攻队的位置提取质心,并绘制它们,它们看起来就像一个编队。把这个放在足球场上,从这个分析的前面部分,把它放到真正的背景中。
My first try to plot the centroids of the attacking and defending team
不错!以我训练有素的眼光来看,我可以看到防守排成 3-3-3-1 阵型,而进攻排成 4-2-3-1 阵型,边后卫被推得更高,让我在球场上展示一下
The attack is red and defense is blue.
结束了
我们从球员在球场上的位置开始,分析了不同度量的比赛序列,球员如何相对于球移动,相对于对方球队移动,尝试构建一个特征,分析球场上占据的位置,尝试使用 KMeans 聚类对数据进行分类,并最终使用 KMeans 质心对阵型进行可视化
这是一个具有挑战性的数据集,但我们最终得出了一些有趣的结果。期待大家对这个笔记本的评价,多提建议。
堆栈溢出标签的频率
在本帖中,我们将了解一些关于标签的数据,这些标签在 Stack Overflow 上用来标记问题,它们的频率以及我们可以测量它们周围的内容。
Image from https://pixabay.com
对于那些堆栈溢出严重的用户来说,这可能是绝大多数做技术的人,让帖子有适当的标签对于浏览网站的巨大存档是至关重要的。在写这篇文章的时候(2018 年 1 月),Stack Overflow 包含了超过 1500 万个问题,有大约 54000 个独特的标签。这里的帮助页面旨在就如何最好地使用该功能提供一些指导,因为以最佳方式标记您的问题以便相关人员能够找到并回答它是非常重要的。标签是技术的名称,如编程语言、框架、软件或技术元素和组件,如编码技术或计算机科学一般主题。
历史的片断
根据维基百科页面的说法,堆栈溢出已经在 2008 年 9 月推出,现在已经相当成熟地成为编程的一站式资源。一年后,在 2009 年 9 月(仍然是根据维基百科),它的成功模式已经扩展到了一个普通的 Q &站点,这个站点被分成了许多主题的子站点(其中许多是科技之外的),栈交换。总而言之,这个网络已经存在了 8/9 年,所以我们都在准备庆祝它的 10 周年纪念日。从历史的角度来看,阅读这篇名为的文章非常有趣,这篇文章讲述了在 2009 年网络刚刚诞生时,StackExchange 的所有问题的答案。
Stack Overflow Wikipedia 页面还断言,截至 2014 年 12 月,根据分配给问题的标签类型,网站上讨论最多的前八个主题是:Java、JavaScript、C#、PHP、Android、jQuery、Python 和 HTML 。我们将看到这种情况是否以及如何改变!
获取一些数据
为了查询堆栈溢出 API,我们将使用 Python 包 StackAPI 。注意,API 允许每 24 小时 10000 个请求。
我们将获取 5000 个最频繁的标签(那些具有最高使用计数的标签),因为由于所述 API 限制,我们不能获取所有的标签:如果我们确实将请求拆分为在多天内获取,因为标签的使用计数随时间变化,我们将不会有一致的画面。不管怎样,5000 美元看起来足够看一些有趣的东西了。
所有遵循的方法和结果都记录在本报告中,还有一本 Jupyter 笔记本供感兴趣的人使用。对于图,请注意我们将使用 Matplotlib 的 XKCD 主题,并且我们试图再现堆栈溢出的颜色!
首先(这是 2018 年 1 月 11 日的数据),最常见的标签是什么?频率作为使用计数给出,即带有该标签的问题的数量。下图显示了按频率排列的前 20 个标签: Javascript 为王,出现次数超过 150 万次,然后我们看到许多其他熟悉的语言和操作系统。不是特别惊讶!
自 2014 年底以来,最常见的 8 个标签是 Java、JavaScript、C#、PHP、Android、jQuery、Python 和 HTML,有什么变化吗?嗯,谁是最频繁的 8 个没有改变,但假设句子是按照频率递减的顺序报告它们,似乎发生了一个转变:Java 当时比 Javascript 更受欢迎。这是时代的标志吗?
有趣的是, AngularJS 是唯一一个进入前 20 名的 Javascript 框架(它诞生于 2010 年,所以可能已经足够老了),而数组作为一种数据结构被讨论了很多。
总之,请注意,即使只有这么小的一组数据,频率也跨越了很大的区间,最后一个显示的 AngularJS 大约有 20 万个计数,与上面的 150 万个 Javascript 相比。让我们探索一下我们检索到的所有标签的频率是如何随着标签的等级(在按频率排序的列表中的位置)而下降的。下图准确地显示了这一点,并清楚地表明标签频率确实跨越了几个数量级。
事实上,频率的分布是幂律的,如果你符合频率与等级的趋势(Zipf 定律),你最终会得到,分布的内部体积,趋势为。这是否暗示了富人越来越富的现象?
Zipf 定律决定了一种语言中单词的趋势频率/排名;斜率为-1 的幂律趋势意味着第二个出现频率最高的单词是第一个的一半;第三种是三分之一的频率,以此类推。我们在标签的频率方面也看到了同样的情况。
在文本生成的优先附件(也称为“rich gets richer”)模型中,当您选择要使用的单词时,您会选择一个与其频率成比例的现有单词,以便更频繁的单词有更高的概率被重用,这将生成频率的幂律趋势。以我们的标签为例,我们推断我们所看到的东西可能有类似的机制,这可能取决于一系列的原因。
首先,Stack Overflow 中的 UI 根据你写的内容的主题,为你的文章推荐标签。最常见的标签将变得更丰富,因为努力的方向是填充现有的标签,如果它们合适的话,而不是创建一个几乎没有填充标签的分散网络。此外,一些语言和工具确实比其他语言和工具更受欢迎,所以这再次加强了它们标签的频率。这就是为什么 Javascript 在网站上如此受欢迎的原因。
越老越有钱?
我们还可以询问数据,无论如何,旧的也变得更富有,也就是说,时间上更老的标签是否吸引了更多的帖子。这似乎是一件合理的事情,随着时间的推移,现有标签上会有越来越多的帖子。就这么简单,但有多真实呢?
关于这一点,我们需要注意,API 的tags/
端点并不提供标签的创建日期,尽管标签的信息页面会提供。所以我们所做的是附加一个标签,该标签带有从该标签出现的第一个问题中提取的创建日期(查询search/
端点);请注意,由于问题总是可以编辑,包括重新标记,这可能意味着当新标签首次出现时,旧问题会看到其标签被修改。这就是为什么有些标签的创建日期比它们所代表的技术还要早(例如,AngularJS 出生于 2010 年,但他的标签是 2009 年的)。
下面的图显示了使用计数与其年龄的散点图(以天为单位,此数据是在 2018 年 1 月 11 日检索的,因此是到那时的天数)。它还显示使用计数的平均宁滨,仓位为 200 天。
值得注意的是,对于最老的标签,在最后一个容器中有相当大的跳跃。除了有点神经质的行为之外,正如预期的那样,旧标签变得越来越富有。但是最老的一个比其他的更富有,这意味着有一个峰值:你从倒数第二个箱子的大约 3000 到最后一个箱子的 15000!这表明,在网站生命的头 200 天里,涵盖绝大多数热门话题的标签已经被创建出来,并一直保持着巨大的吸引力。自诞生以来的大约一年时间里,Stack Overflow 已经见证了大多数当今仍然非常流行和有趣的主题。
标签可以有同义词。当一个问题被标记了某个现有事物的变体时,它会自动映射到母标签,因此使用计数会与我们检索到的母标签相对照。请注意,当您在 API 中查询与母标签同义的标签时,您将获得母标签的使用计数。
获得一定声誉的用户将标签折叠为现有标签的同义词,参见帮助页面。这个过程控制标签的增加,使它们保持有序。例如, javascript 的一些同义词是类似 javascript-dom 或 javascript-module 的东西;一些 python 是 python-shell 或 python-interpreter 。
每个标签的同义词数量分布如图所示,这也是一个非常不均衡的情况,只有少数标签有大量的同义词。
作为参考,拥有最多同义词(25 个)的标签是 css (比如 font-weight 、 dynamic-css 、 inline-block )。
现在,你认为有同义词的标签会得到更高的频率计数吗?这很直观地归因于这样一个事实,即带有同义词的标签是一种可以用多种风格表达的标签,可能是一种复合和广泛的技术,这意味着人们可能对它的不同部分感兴趣。我们运行了一个快速 t-test 来确定有同义词和没有同义词的标签的使用计数分布的均值是否显著不同,结果是它们实际上是不同的,所述均值分别位于 21500 和 3200:一般来说,有同义词的标签的受欢迎程度大约是没有同义词的标签的 7 倍。
关于时间趋势的一个注记
2017 年,Stack Overflow 推出了一个很棒的工具,向每个人展示他们生成的关于技术受欢迎程度的数据,它被称为 Stack Overflow Trends ,你可以阅读这篇由 D Robinson 撰写的关于它的博客文章。简而言之,这是一个用户界面,你可以及时查询你选择的一些标签的使用计数数据,因为栈溢出诞生了。我们为上面提到的 8 个最受欢迎的标签中的一些标签做了这个这个就是结果: c# 在 2009-2010 年达到了它的最好年龄,现在正在稳步下降; Javascript 和 Python 正在崛起,第一个出现并且一直是王者, Java 在最近几年缓慢衰落。
一句小小的警告
从表面上看,这些时间趋势结果背后的假设是,堆栈溢出是周围技术专家的代表性社区,问题被正确标记,数据没有偏差。举个极端的例子,标签的流行可能是因为缺乏相关工具的良好文档,而不一定是因为它在用户中有多流行和有趣:网站上的许多用户会突然出现在那里,以获得一些帮助来解决他们在其他地方找不到好参考的问题。
总而言之,这是一个很好的工具,可以看到技术世界是如何发展的!
原载于 2018 年 1 月 14 日martinapugliese . github . io。
深度学习的成果:卷积神经网络如何支持机器人收割和产量绘图
Delicious deep learning
准确高效的水果检测对于机器人收获和产量制图至关重要。
不管机器人的抓取系统有多复杂,它们只能抓取视觉系统能探测到的水果。此外,水果检测有助于生成产量图,跟踪作物生产的空间可变产量,并作为精准农业的决策工具。
许多因素使水果检测成为一项具有挑战性的任务:水果出现在不同照明的场景中,可能被其他物体遮挡,有时很难从背景中分辨出来。
理想的水果检测系统是准确的,可以在容易获得的数据集上进行训练,实时生成预测,适应不同类型的水果,并使用不同的模式(如彩色图像和红外图像)日夜工作。
在过去的几年里,深度学习方法在解决这些需求方面取得了长足的进步。这篇文章强调了水果检测中的一些挑战和最近的里程碑。
计算机视觉任务的第一个挑战是获取相机图像或视频帧形式的原始数据。在农业领域,经常通过使用无人机和机器人来收集数据。
水果检测可以表述为一个图像分割问题。为了使计算机视觉系统从可用的原始数据中学习,需要将作为水果一部分的像素与代表背景的像素区分开。
单独注释水果像素是劳动密集型的。幸运的是,深度学习系统不需要像素信息,而是可以从边界框注释中学习。
Sa 等人[5]报告称,标记一幅图像中的水果像素需要将近 100 秒,执行边界框注释需要大约 10 秒。换句话说,给定相同的资源,使用边界框将产生十倍大的注释数据集。
合成生成的数据集提供了人类注释的潜在替代方案。Rahnemoonfar 和 Sheppard [3]实验了一个相对简单的过程,包括用绿色和棕色的圆圈填充空白图像,模糊图像,并在随机位置绘制随机大小的圆圈。Barth 等人[2]使用一个复杂的过程,为 42 个不同的植物模型综合创建了 10,500 幅图像,这些模型具有随机的植物参数。
在许多情况下,深度视觉系统受益于迁移学习。现有的卷积神经网络(CNN)已经在数百万张图像上进行训练,并由领先的研究人员多年来进行优化,可以针对特定领域的任务进行微调,而不是从零开始每个项目。
特别是,许多针对水果检测问题的深度学习解决方案都是基于一个非常成功的对象检测网络,名为 Faster R-CNN[4]。这个神经网络分两步训练:第一步,使用由 120 万个例子组成的数据集 ImageNet 训练更快的 R-CNN 作为图像分类器。然后,使用另一个名为 PASCAL VOC 的数据集对网络进行微调,以进行对象检测。
快速 R-CNN 中的区域提议模块生成一组可能包含感兴趣对象的候选边界框。用作者的话说,这个模块告诉网络“往哪里看”。对于每个建议的盒子,区域分类步骤然后计算该盒子可能属于的类的概率分布。
存在的更快的 R-CNN 的变体在用于为网络的区域提议部分提取图像特征的卷积层的集合上不同。具有 13 个卷积层的 VGG-16 变体更深且计算更密集,而 ZF 变体更浅但更快。
在深度神经网络出现之前,计算机视觉模型中的特征是针对特定任务和收集数据的特定条件人工设计的。深度学习模型会自动学习这些特征,从而节省大量的开发时间。
Sa 等人关于 DeepFruits 系统的论文的发表[5]标志着水果检测的深度学习方法的发展中的一个重要里程碑。DeepFruits 建立在更快的 R-CNN 上,可以检测温室中拍摄的图像中的甜椒和岩瓜。该系统可以在几个小时内完成训练,在商用硬件上运行,每幅图像的检测时间约为 400 毫秒。
作者使用了更快的 R-CNN 的 VGG-16 变体,并表明第一层中的过滤器专门处理低级特征,例如与红色和绿色糖果纸相对应的红色和绿色。具有强激活的较高级别层中的区域通常对应于属于水果的图像区域。
当交集超过联合分数大于 0.4 时,包含水果的区域被认为被检测到。使用这个阈值,作者报告了甜椒检测任务的 F1 分数在 0.8 和 0.84 之间。性能最好的方法是使用一种称为“后期融合”的评分方法,将来自 RGB 和近红外图像的单独训练模型的建议结合起来
有趣的是,当更快的 R-CNN 组件在仅仅 20 张训练图像上进行微调时,DeepFruit 达到了令人尊敬的 0.8 的 F1 分数。应该注意的是,实验中使用的数据集非常小。每个分类器在大约 100 幅图像上进行训练,并在几十幅图像上进行测试。
自发表以来,许多新论文都建立在 DeepFruits 的基础上,以解决类似的更具挑战性的问题。
一个显著的例子是 Bargoti & Underwood 发表的关于果园水果检测的论文[1]。研究人员在白天使用机器人车辆捕捉三种水果类型的高分辨率整树图像:苹果、杏仁和芒果。该数据集总共包含 2000 多幅训练图像和近 500 幅测试图像。
作者强调,由于每个水果的高像素计数和每个图像的低水果计数,增加了难度。例如,杏树可以结 1,000-10,000 颗杏仁,而且个头比其他水果品种小。
DeepFruits 和 Bargoti & Underwood 论文中描述的系统都使用更快的 R-CNN,并将水果检测视为一组二元问题:为每种水果类型训练一个检测器。另一个共性是非最大抑制(NMS)的应用,这是一种用于处理重叠区域的程序。NMS 消除了与高置信度候选项强烈重叠的低置信度区域,如通过联合分数的交集所测量的。
Bargoti & Underwood 试验了不同的数据增强技术,发现通过翻转和缩放可用图像可以实现性能的最大提升。
VGG-16 需要 2.5 GB 的 GPU 内存来存储 25 万像素的图像。为了克服这个瓶颈,作者采用了一种他们称为“平铺式更快 R-CNN”的方法:使用在图像上滑动的适当大小的窗口进行检测。为了确保水果不会在图块之间分开,两个图块之间的重叠大于最大水果尺寸。然后,将 NMS 应用于所有图块的组合输出。
使用这种设置,更快的 R-CNN 的 VGG 变体优于更浅的 ZF 变体,并且苹果和芒果的 F1 得分超过 0.9。对于较小尺寸和经常出现的杏仁,水果检测结果据报道接近 0.78。有趣的是,对于只有五幅图像的苹果,检测性能达到 0.6,而对于训练图像的最后一倍,检测性能仅提高了 0.01。
最后,作者指出,更快的 R-CNN 的正确选择取决于手头的任务。例如,计算效率对于机器人收割来说比产量绘图更重要,产量绘图可以离线进行。
DeepFruits 和相关系统取得的有希望的结果标志着农业技术的令人兴奋的发展。让我们希望深度视觉系统将为普遍获得负担得起的、有营养的和美味的食物的目标做出重要贡献。
水果计数是一个更高级的任务,它建立在水果检测的基础上,并需要跟踪在以前的帧中已经看到的水果,这是一个可能在将来的文章中讨论的主题。
感谢您的阅读!如果你喜欢这篇文章,请点击“鼓掌”按钮,关注我并查看aisummary.com以获得更多关于令人兴奋的机器学习应用的信息。
参考
[1]s .巴尔戈蒂和 j .安德伍德,2017 年 5 月。果园深度水果检测。在机器人与自动化(ICRA),2017 IEEE 国际会议上(第 3626–3633 页)。IEEE。
[2]r . Barth,IJsselmuiden,j . Hemming,j .和 e . j . Van Henten,2018 年。农业语义分割的数据合成方法:辣椒数据集。农业中的计算机和电子, 144 ,第 284–296 页。
[3] Rahnemoonfar,m .和 Sheppard,c .,2017 年。深度计数:基于深度模拟学习的水果计数。传感器、 17 (4),第 905 页。
[4]任,s .,何,k .,吉希克,r .和孙,j .,2015 年。更快的 r-cnn:用区域建议网络实现实时目标检测。在神经信息处理系统的进展(第 91–99 页)。
[5] Sa,I .,Ge,z .,Dayoub,f .,Upcroft,b .,Perez,t .和麦克库尔,c .,2016 年。Deepfruits:一个使用深度神经网络的水果检测系统。传感器、 16 (8),第 1222 页。
概率的基本原理
如果你给一个结果的发生分配一个概率,那么你必须愿意接受另一方以正确的隐含赔率提供的赌注(这个结果不会发生)。
如果你不会有意投资于一家对冲基金,而该基金的经理因产生巨额回报而获得的报酬与破产时相同,或者与一家输钱不还的博彩公司打赌,或者相信一名不审查其消息来源的记者,那么当科学家的假设是错误的、分析是有缺陷的或发现是虚假的时,你为什么会相信那些几乎没有或根本没有损失的科学家的说法呢?
投资、博彩和新闻报道业务绝非完美,但至少它们有内在的机制来协调生产者(基金经理、博彩公司、记者)和消费者(投资者、赌徒、读者)的利益。基金经理、博彩公司和记者不得不拿自己的财富、声誉和信誉冒险,这样他们才有资金来管理,有账簿来保管,有读者来写作。医生、屠夫、厨师和(非工会)水管工也是如此。但是为什么不是科学家呢?
职业科学家不是根据客观建立的标准(例如,上述例子中的利润、荣誉和真相)进行评估,而是通过行为准则、同行评审和编辑委员会来约束自己,为自己提供大量的好处——工作保障、舒适的薪水、数百万美元的纳税人资助的拨款,甚至如果他们的一项发现成为主流,还有可能获得名誉和财富——而潜在的坏处大多限于特殊情况,如欺诈或不当行为。这种不对称加上学术界的“发表或灭亡”文化导致了一种反常的激励结构,在这种结构中,快速和肮脏的行为比仔细和正确的行为更受奖励,这反过来又导致了所谓的科学“T1”复制危机。
十多年前,约安尼迪斯在一篇名为为什么大多数发表的研究结果都是假的的文章中呼吁人们关注这一系统的负面影响。十多年后,有许多改革科学调查、评估和报告方式的提议摆在桌面上,并以此提高已发表研究的可靠性。但是,即使人们对改革有着广泛的兴趣,复制危机也没有什么消退的迹象,因为最近的一项努力只成功复制了发表在心理学文献中的 37%的结果。
这些问题将持续存在,直到科学,如投资、著作和新闻报道,实现一种内在机制,将科学家的职业成功与其结果的可靠性联系起来。我在这里认为,这比看起来容易实现得多,因为它只需要很少或不需要改变目前进行科学调查的方式,只需要对科学结论的报告方式进行微小的修改。关键的想法是使科学文献中报告的结论更科学,在某种意义上是可测试和可证伪的,而不仅仅是透明或合理的,如根据最佳实践的标题或最先进方法的清单进行评估。因此,我主张更加强调结果,而不是回避被认为是“以结果为导向”的科学报告方法的可察觉的缺陷,我特别指的是实际的结果,例如,验证或伪造发表的声明的明确标准,而不是报告的结果,例如,统计意义。
像注册报告 (RRs)等(善意的)提议所寻求的那样,仅仅监管方法是不够的。哪些方法是“合理的”将由目前决定结果是否“重要”的同一批编辑和裁判来确定,他们不改变最终目标(发表)或机制(同行评审),而是改变实现该目标的手段(即,通过应用“合理的方法”而不是报告“重要的结果”)。因此,虽然这样的实现可以改变特定的行为,例如,通过消除 P-hacking 和其他形式的面向结果的不当行为,但是它们将在没有任何保证消除由这些行为引起的复制问题的情况下这样做。
正确的科学结果对合理的科学方法的重要性凸显了科学更大的社会作用,这一作用被注册报告和类似的将重点从结果转移到方法的建议所淡化。哲学、历史和数学等纯学术学科的直接影响不会远远超出象牙塔,与之不同的是,发表在科学文献中的结果会对经济、社会、医学、商业、工业和公共政策产生直接影响。因此,虽然专注于方法可能是确保总体科学一致性的谨慎方法,但个体研究的正确性对消费者来说很重要,因为他们根据科学文献中的具体结论做出政策和商业决策。事实上,癌症研究、教育政策或经济学中的错误结论是使用“最先进”的方法获得的,并且得到了“专家”同行评审员的批准,这对于受基于这些有缺陷的报告的错误政策影响的癌症患者、特殊需要儿童或贫困公民来说,并不是一种安慰。因为不管一个科学家是故意造假,还是不知不觉地误用了统计方法,或者不幸地由于随机误差得出了错误的结论,最终结果都是一样的:同行评议的科学文献中报告的结论不太可靠,结果是任何依赖科学研究可靠性的人(也就是几乎所有人)的处境都更糟。这并不是说科学家在报告结论之前必须 100%确定结论,因为反复试验对科学进步至关重要,但是这些结论的消费者,包括科学家同事和普通大众,应该确信他们所阅读的内容很可能是正确的,这不仅仅是因为科学界保证这些方法的合理性或结论的合理性,而是因为主张这些主张的科学家有动力保持正确,并面临错误的后果。同样的基本原则让基金经理、博彩公司、记者、医生、屠夫、厨师和水管工(除了那些受工会保护的人)保持警觉,对科学家也是如此。
只要科学家(即发表论文)的主要目标与科学(即获得新知识和新见解)的目标不一致,科学文献的可靠性将更多地受到社会学因素而非科学因素的影响。为了协调消费者和科学生产者的利益,仅仅消除对某些不当行为的激励或奖励特定的最佳做法是不够的。持续生产不可靠的科学(有意或无意)必须成为科学事业不可持续的战略,反过来,持续生产可靠的科学必须成为成功的科学事业的最清晰的路径。换句话说,科学家居住的学术世界需要与他们的结论具有影响力的现实世界进行接触。
学术与现实
提高已发表科学的可靠性与调整学术科学和 T2 真正科学的目标是齐头并进的。真正的科学结论可以用现实来检验,而学术科学只能由其他学术来评价。因此,可测试性标志着学术科学和真实科学之间的界限,并绘制出提高科学文献可靠性的逻辑路径。因为指导科学期刊发表的同行评议决定主要是基于学术标准,所以一些学术科学在与现实对比时表现不佳就不足为奇了;参见,例如,心理学中的大规模复制研究。
区分学术和现实的关键一步在于更清楚地了解科学结论通常是如何通过统计方法及其伴随的概率进行评估的,以及这些概率如何提供一个有机的机制来评估科学主张,所有这些都不需要同行评审期刊、专家裁判或官僚监督。事实上,复制危机的一个主要因素是科学文献没有区分学术概率和真实概率,而这种区分对于理解概率在科学话语中的作用至关重要。
关键的一点是真实概率可以用一种理论概率无法测试的方式来测试。
学术概率是仅与现实世界有假设联系的理论计算。
学术概率是纸上谈兵的分析结果,例如当贝叶斯哲学家根据对赌博的假设倾向来解释概率时,或者当科学家假设糖尿病和某些假定的风险因素(例如,年龄、体重、饮食等)之间的关系时。)遵循多变量逻辑回归,或者当统计学家假设从临床试验计算的检验统计量遵循具有一定自由度的 t 分布时。最初,从这些分析中出现的概率是学术性的(如“没有实际意义,只有理论意义”),因为它们是通过指令(任意的程度或声明)而不是通过与现实世界的具体联系来实现其意义的。因为这些概率是理论上的,所以这些概率所支持的结论也是理论上的。
从学术分析中得出的结论,只有当它们所基于的假设性假设与现实联系起来时,才会变得真实。
真实概率由真实的东西支持,并且是关于真实的东西。
对于“由真实事物支持”的概率,它必须有一个有形的担保人,也就是说,一些东西必须作为抵押品,以确保概率的提供者(“概率者”)是善意的。对于一个“关于真实事物”的概率,关于概率的陈述必须是可判定的,因为必须有明确的标准来确定概率陈述的对象是否发生,是或不是真实的。
在这种理解下,股票期权定价中使用的概率是理论上的*,直到期权在这些概率的基础上被买卖*。一旦交易完成,这种可能性就可以通过交易的已实现利润或亏损来检验。同理,概率和概率的导数如 P 值、置信区间等。科学文献中报道的都是学术性的*,除非这些概率的准确性可以被检验*。(注意:尽管在任何给定的交易中实现亏损并不表明相关的概率计算是错误的(同样,在任何给定的交易中实现盈利也不表明相关的概率计算是正确的),但在一长串交易中的持续亏损(盈利)提供了一种客观的方法来评估这些计算中的系统误差(或稳健性)。)
概率的基本原理
理论概率和真实概率之间的区别产生了我所谓的概率基本原理 (FPP),它通过将理论概率与真实结果联系起来,建立了理论概率和真实概率之间的联系。FPP 是一个常识性的概念,几乎每个股票交易者、庄家和普通人都能直观地理解:
如果你给一个结果发生的概率赋值,那么你必须愿意接受另一方以正确的隐含赔率提供的赌注(这个结果不会发生)。
通过 FPP,当你声称’ A ‘的概率是 p 时,那么你就是在含蓄地为’ not- A '提供了 p/(1-p) 的赔率。如果我选择接受你的提议,那么如果发生 A 的话,你就赢了我赌的所有钱,如果发生 A 的话,我每赌一个 1-p 美元,我就赢了你的 p 美元。
根据 FPP,真实概率由三部分组成:
(I)概率陈述适用的可判定陈述 A 。
(II)风险限额,即根据 A 的概率评估,一个人愿意承担风险的最大金额。
(III)断言 A 变为真的概率 p 。
学术概率往往不能满足(I),几乎总是不能满足(II)。在当前的学术科学中,( II)中的接触限值被隐含地设置为 0,根据 FPP,这表示对概率评估没有信心,因此对其相关结论没有可信度。为了让科学结论更加可信,科学家们需要提高他们声明的可信度。科学家很可能被自己的分析所说服,并提供了有利于自己的令人信服的论据。但是,除非得到 FPP 的支持,否则这些话所支持的概率毫无意义。
从技术上讲,(III)中的概率 p 是 A 的“较低概率”,在某种意义上,它决定了赌注对**A的几率 p/(1-p) (注意,并没有假设 p 是“公平赌注”的价格,因为提供公平赌注将使概率者面临潜在的毁灭性财富波动,而没有任何潜在的长期收益。FPP 的目的是让概率变得有意义,而不是迫使科学家去赌博或让自己面临毁灭。)如果 p 是 A 概率的合法下界,那么与 A 打赌的隐含赔率 p/(1-p) 从长远来看将对概率者有利。然而,如果 p 过于乐观,隐含的赔率将为损失付出过高代价,导致概率者长期遭受经济损失,并提供反对初始概率评估的证据。
学术概率和复制危机
从本质上来说,复制危机是一种统计和概率危机,是由误用的统计方法、误解的概率和未经检查的不当行为共同造成的。通过将学术概率和它们声称支持的结论混淆为真实的东西,这场危机得以持续。FPP 提供了一种内置机制,迫使统计和概率方法的用户报告更有意义的概率(或者根本不报告概率),而不需要编辑、同行评审员或其他所谓的专家的验证。
要理解实施 FPP 将如何影响科学结论的报告和评估,首先考虑它在博彩业中扮演的角色。众所周知,除了职业优势玩家,赌场游戏对赌徒不利。(脚注:‘优势玩家’是赌胜算对自己有利的赌徒。也许优势游戏最著名的例子是 21 点中的算牌。最近,菲尔·艾维和张·孙茵在玩百家乐时利用一种名为边缘排序的技术赢得了超过 2000 万美元。在 Bob Dancer 和 Richard Munchkin 的“T4 优势赌博”播客中讨论了体育博彩、电动扑克、轮盘赌、掷骰子游戏和其他“无与伦比”的赌场游戏中的优势游戏的其他例子。)重要的是,这些知识来自常识,而不是来自对赌场游戏的正式统计分析(这种分析一般人不具备进行的条件)。显而易见,任何主要赌场提供的赔率都必须有利于赌场,原因很简单:(1)赌场愿意接受其规定赔率的任何赌注,以及(2)赌场是有利可图的业务。
关于特定赌场提供的特定赔率,有人可能会问,我怎么知道在澳大利亚皇冠墨尔本赌场的双骰赌桌上,7 的掷出频率低于 20%。我声称知道这一点,即使我从未参观过墨尔本皇冠,更不用说检查它的骰子,桌子或经销商来确认游戏(或多或少)是公平的。正如上文所强调的,我的知识不是基于理论上的 STAT 101 计算——在两个“公平骰子”的标准模型下,掷出 7 的概率是 16.7%——因为我没有办法评估该计算背后的假设。事实上,在墨尔本皇冠上掷出 7 的准确概率(即频率)可能是 16.7%,或者 18%,或者 14%。我不知道,也不在乎。不管实际频率是多少,我很确定它一定少于 20%。我知道这一点是因为墨尔本皇冠在 7 的一次下注中提供 4 比 1 的赔率(隐含概率为 1/(4+1)=0.20),而墨尔本皇冠仍在营业。不管真实频率是 16.7%,18%,还是 14%,只要低于 20%,赌场长期就赢了,赌徒就输了。
由于 FPP 内置的生存机制——陈述坏概率的赌场要么修改赔率,要么破产——以及对墨尔本皇冠赌场仍在生存(事实上,欣欣向荣)的观察,我可以合理地肯定,其赔率所隐含的概率界限是合法的,而无需了解墨尔本皇冠是如何确定其赔率的,甚至不知道掷骰子的规则。我知道这些都是因为赌场的概率是真实的:如果隐含的赔率太高,赌场就会破产;如果它们太低,那么赌场的顾客就会太少。
如果我们不需要内部信息来确定赌场的赔率给出了游戏结果的有效概率界限,为什么我们需要编辑、副主编和裁判来评估科学家用来计算 P 值、置信区间、贝叶斯因子和其他证据概率度量的方法的可靠性?就像赌场不会提供过于慷慨的赔率来吸引更多的客户(因为他们会很快破产),如果科学家甚至不试图公布被黑掉的或过于乐观的 P 值或其他概率,那不是很好吗,因为这样做会让他们退出科学行业。由于概率的基本原理,这是一个简单的想法和简单的实现。
复制和概率的基本原理
用科学术语来说,骰子的每一次滚动、轮盘的每一次旋转以及 21 点的每一手牌都是对赌场规定赔率的测试,因此也是对这些赔率所隐含的概率的测试。对赌场的每一次下注都是试图伪造赌场的隐含概率声明。赌场持续从这些游戏中获利,而赌徒持续输钱,这一事实可以(也应该)被解释为赔率设置正确的令人信服的证据。(脚注:这里的“正确”是指那些赔率所隐含的概率给出了真实发生概率(即频率)的有效下限。)
就像赌场赔率一样,如果科学结论也得到了真实概率的支持,那么对科学方法的官僚评估将变得没有必要。对给定发现的可靠性(即可复制性)过于乐观的概率会刺激复制尝试;过于保守的概率会低估给定结论的重要性和可靠性。因此,概率的基本原理提出了一种直接而客观的方法来报告结论,并通过在报告结论时列出以下条件来在科学文献中进行复制尝试。
复制协议 1 。描述复制尝试应遵循的协议。
复制标准 1 。说明方案结果被视为成功复制的标准。
复制概率 1 。说明该程序成功复制的可能性。
复制曝光 1 。根据上述 FPP 的第(II)项,陈述这些主张背后的科学家愿意为测试其结论而公开的金额,并将该金额交由第三方保管。
继续其他复制协议、标准和概率 2、3、4 等。如你所愿。
陈述的协议、标准和概率提供了根据 FPP 测试结果的具体基础。这反过来又通过迫使作者、他们的机构(如果有的话)、出版该作品的期刊(如果有的话)以及参与出版决定的任何编辑、副主编和审稿人用真实的东西来支持他们的主张,从而限制了所述的复制概率。(根据领域的不同,每项索赔的担保金可能是 500 美元、5,000 美元、50,000 美元或 500,000 美元。“游戏中的利益”的适当数量应该与开展研究的成本以及相关方从出版物中获得的收益大致成比例。关键是,这种担保应该足够大,以至于作者不愿意为了出版而损失金钱。因此,如果进行这项研究花费了 100 万美元(其中大部分或全部通常是纳税人的钱),那么再贴出 50 万美元来支持这项研究是合理的。如果研究成本只有 1K 美元,那么 500 美元应该足够了。实际上,由商定的第三方执行的复制尝试的至少部分成本应该由该抵押品支付。)
发表后,担保品在固定的审查期(比如 2 年)内被锁定,在此期间,其他科学家可以选择以所述复制概率暗示的赔率赌不复制。重要的是,复制尝试必须发生在怀疑者已经决定赌不复制并且已经把他/她的钱放在第三方托管之后。这种复制尝试应由可信、中立的第三方科学家团队进行,进行复制的费用全部或部分由最初的科学团队和发表声明的期刊资助。希望测试声称的复制概率的科学团队(怀疑论者)将在进行复制尝试时,将他们愿意承担风险的金额放在托管中。在这样做的时候,怀疑者同意原始作者的复制协议和标准中所述的条款,这将启动由商定的中立第三方进行的复制尝试。复制尝试的结果决定了提出主张的科学家(概率学家)和验证主张的科学家(怀疑论者)之间打赌的结果。(脚注:选择此类第三方的确切协议和确保结论的真实性是一个实际问题,与确保当前的同行审查过程得到适当管理的味道非常相似。我不在这里进一步讨论这个问题。)
这一过程会持续到预先指定的审查期限,或者直到托管资金用完。如果托管资金用完,那么作者要么提交更多的担保品,要么将结果存档,并清楚地记录复制尝试的结果以及作者的净资金损益。那些仍然袖手旁观他们的主张的作者可以贴出更多的托管资金来鼓励对他们的结果进行额外的测试,希望能够验证他们最初的发现。审查期结束后,无论结果如何,复制尝试的结果都将与以指定复制概率得出的最终收益/损失记录一起发布。需要注意的是,虽然整个复制过程中的财务收益/损失并不一定表明最初的主张是正确的/错误的,但它们可以被合理地解释为支持/反对最初主张的证据,并且这些证据应该记录在已发表的科学记录中。
在审查期间的任何时候,作者都可以自由地修改他们的概率(向上或向下),并且提供重复研究的几率也将相应地修改。例如,如果最初陈述的 80%的复制概率过于保守(例如,真实的复制概率应该是 90%),则可能很少尝试复制最初的声明,因为复制的几率是不利的。对此,作者可能希望将他们的复制概率增加到 85%,从原作者的角度来看,这有两个好处。首先,它加强了最初的主张——因为作者陈述的概率是真实的,在 FPP 支持的意义上,更高的复制概率使最初的主张更有力。第二,更高的复制概率为任何希望挑战结果的人提供了更好的价格(5.6 比 1,而不是 4 比 1),因此可以吸引更多试图复制/伪造原始结果的活动。反过来,成功的复制使得文章中的说法更加可信。如果作者对 90%真实概率的评估是正确的,从长远来看,这些复制尝试应该会产生额外的研究资金。此外,成功的复制尝试将使作者的发现更加可信。
或者,如果作者确定他们的初始概率过于乐观,他们可以向下调整他们的复制概率,比如从 80%到 70%。无论哪种方式,如果陈述的结论是可靠的,并且概率是校准好的,那么科学家、他们的大学以及好的和精确的科学背后的期刊将因为得出合理的结论而在经济上和学术上得到奖励。如果结论不可靠,那么这些科学家、支持他们的大学以及发表糟糕科学的期刊都将受到惩罚。
这会有什么结果呢?
上述过程利用统计方法的内置校正机制(通过 FPP)来提高基于统计和概率方法的科学主张的可靠性:作者不应陈述过于保守的概率,否则人们对他们的结论兴趣不大,也很少有人试图复制他们的发现;但他们也不应该陈述过于乐观的可能性,否则他们为复制尝试提供了太好的价格,从长远来看,这可能会花费他们的钱。这种经济损失的直接影响是剥夺了发表过于乐观的复制概率的研究人员的研究经费。此外,由于这些结果被记录在结果的最终出版版本中,失败的复制尝试也可能导致失败的索赔中涉及的研究人员的可信度的损失。相反,从复制过程中获得的资金将对最初主张背后的科学家的声誉和财务状况产生相反(积极)的影响。最重要的是,科学文献应该因此变得更准确、更完整。
规定的复制概率应该更加保守
假设它的骰子是公平的,赌场知道滚动 7 的真实赔率是 5 比 1(隐含概率为 16.7%),但它只提供 4 比 1(隐含概率为 20%)。根据上面的复制概率,赌场声称而不是掷出 7 的概率是 80%,尽管理论概率是 83.3%。一家赌场高估了概率,比如说 85%(隐含赔率为 5.6 比 1),结果会遭受财务损失。
以此类推,使用统计方法计算复制概率为 90%的科学家受到激励,在出版物中引用更保守的概率,比如 80%或 85%。这些低估的概率说明了由于模型假设、近似值和科学家无法控制的其他因素而产生的不确定性。科学家公布更高的数字来表达对结果的信心——学术上相当于虚张声势——当他们的虚张声势被叫停时,他们可能会失去作为抵押品的钱。这反过来会对他们所陈述的结论产生负面印象,并剥夺这些科学家未来研究的资源。然而,如果概率过于保守(比如说,25%而不是 80%),那么这一主张就太弱了,不足以引起对复制的足够兴趣,这反过来又削弱了所报道的发现的重要性。
文献中报道的概率会更有意义
即使忽略学术界和现实之间的分歧,目前出现在科学著作中的特定概率也经常被定性地解释。没有机会测试概率或模型假设(根据 FPP),90%或 95%的概率之间几乎没有概念上的差异。这两种可能性都很高,通常会被解释为支持某一主张的证据。但是当受 FPP 约束时,90% (9 比 1 的几率)和 95% (19 比 1 的几率)之间有很大的差异。如果真实概率介于两者之间,比如说 92.5%,那么 90%而不是 95%就是托管资金的正回报和负回报之间的差异,从而使报告的数字概率具有更精确的含义。
复制尝试增加
奖励科学家正确识别过于乐观的已发表的主张,为带头复制尝试提供了激励。除了更清楚地了解已发表的文献,呼吁复制有缺陷的主张的研究人员将获得额外的研究资金。与此形成对比的是,在当前的情况下,许多人哀叹复制尝试太少,因为没有复制其他科学家的成果的激励措施(财政或其他)。
对“正常科学”没有保护
由于目前由负责同行评审期刊的把关人评估科学成果的方式,有一种趋势,即与现状相反的发现会被压制。从学术概率到真实概率,进而从学术概率到真实科学的转变,将消除压制任何提交给科学文献发表的东西的需要。通过以隐含的赔率打赌反对复制,科学机构可以很容易地驳斥基于客观理由的蛮横和虚假的主张。如果当权派是正确的,那么不准确主张背后的科学家将遭受经济损失,而当权派则获得经济收益;反之,如果建立不正确。这样,违背科学范式的有争议的结果不需要像目前的规范那样从文献中过滤掉,而是可以以透明和客观的方式接受审查,当这些新结果被反驳时进一步加强主导范式,当有争议的结果经得起审查时加快进展。
投资更好的科学
一些批评家会叫嚣,科学不是赌博游戏,上述提议的经济激励会腐蚀科学。但是,虽然我在这里使用了打赌的语言进行说明,但该提议更好地被认为是一种投资于好的科学/科学家并从坏的科学/科学家那里撤资的机制,旨在提高已发表科学的整体质量和可靠性。这样的结果将明显改善,而不是破坏科学的现状。它现在的工作方式是,科学家报告固定的概率,并隐含地陈述概率,对传递坏概率、假概率、伪造概率或欺诈概率几乎没有影响。结果就是复制危机。
对于优秀的科学家、优秀的期刊、优秀的编辑和优秀的审稿人来说,这里的提案是对优秀科学的投资。更好的科学家将会得到更多的资源来做更多更好的科学研究。糟糕的科学家将受到损失资源的惩罚,因此他们必须做更少的科学研究,或者将他们的努力重新集中在质量而不是数量上。同样,雇佣优秀科学家的大学和持续发表可靠科学的期刊将获得奖励。那些支持坏科学家的坏科学的人将会受到惩罚。资助机构不应该让大学将数百万美元的纳税人资金作为“间接成本”从拨款中抽走,而应该强制要求这些间接成本的一部分或全部首先投资于在该拨款下进行的科学,作为托管的一部分。审查结束后,托管资金的任何份额都将作为间接成本归大学所有。如果托管资金丢失,那么大学就没有管理费用。间接成本反而流向了科学家所在的机构,他们正确地投资于试图证伪错误结论的努力。因此,资助研究的纳税人将获得更好的投资回报,因为他们的税款将根据结果自动分配给更谨慎、诚实的研究人员,而不是根据拨款小组、编辑委员会或匿名裁判的主观决定。
就激励而言:声望、任期、晋升和金钱的激励不是已经成为科学家行为的一个因素了吗?授予这些奖项的任意方式难道不是科学文献中猖獗的 P-hacking、欺诈和其他可疑研究行为的部分原因吗?事实上,这些社会学因素经常被认为是“以结果为导向”的态度的催化剂,这种态度滋生了复制危机,这里的建议试图纠正这种情况。即使有了 FPP,同样的激励也会存在,但 FPP 通过断言虚假的、粗心的或伪造的概率,使实现这些激励变得更加困难,从而提供了改进。
用真正的概率改革科学
Courtesy of http://lowres.jantoo.com/business-stat-statistician-lie-liar-statistic-01436756_low.jpg
当迪斯雷利提到“谎言、该死的谎言和统计数据”时,他指的是没有 FPP 的统计数据,或者是游戏中没有“T2”皮肤的概率。此处将科学文献中报告的概率与 FPP 合并的建议是一项提案,旨在通过赋予报告的概率真正的意义,从而赋予基于它们的结论真正的意义,来提高科学文献的可靠性,而不会对研究进行的方式施加任何额外的要求、管理工作或其他限制。科学家们将不再受到额外的限制,而是可以自由地进行他们认为合适的研究,而不需要为了取悦裁判或在某个期刊上发表而采用特定的方法。随着这种自由而来的是对报告结果的责任,因为当根据科学家规定的复制协议进行测试时,最终声明的复制概率将不得不依靠其自身的价值。这个系统的设计使得好科学家成功,坏科学家失败,文献中报道的结论总体上更可靠。
当以这种方式实现时,FPP 可以被认为是希波克拉底概率誓言,一个不将自己暴露在同样的下行风险中而不将他人暴露在统计方法的潜在危害中的誓言。那些不愿意承担与他们的方法相关的风险的人不应该用概率来评估他们的结果,就像那些不能忍受看到血的人不适合当医生,下巴虚弱的运动员不适合当拳击手一样。
技术说明:
- 在的早期版本中,我以“第一概率规则”的名义讨论了 FPP。
- 将概率解释为赌注的价格是德·费内蒂、萨维奇等人的“激进主观贝叶斯”(RSB)哲学的基础。作为一种哲学立场的 RSB 和作为一种实践原则的 FPP 之间的区别,就像学术和现实之间的区别一样。RSB 概率仅仅是假设的信任度,仅与博彩有学术联系,而真实概率是实际的博彩商数,通过陈述这些概率的真实结果(潜在的财务损失或收益)来实现。
- FPP 通过迫使概率的提供者充当任何希望测试概率评估的人的“房子”,赋予了概率陈述真正的意义。概率学家也可能希望陈述 A 的逆命题的概率(即 A 没有发生),写成- A 。
在这种情况下,对-A 的较低概率 p* 提供了对 A 下注的隐含赔率 p/(1-p*)* 。概率 p 和 p* 一起给出了 A 和 -A 的实际概率范围:
p ≤ P(A) ≤ 1-p*
p* ≤ P(-A) ≤ 1-p
如果这些不是适当的间隔,意味着 p+p > 1* ,那么概率者将自己暴露于确定的损失,因为我可以打赌 1-p 对 A 的赔率为 p/(1-p) 和 1-p* 对- A 对 p/(1-p*)* 。如果 A 发生,那么我赌 A 赢*(1-p)x(p/(1-p))= p*,赌- A 输 1-p* ,总收益为 p-(1-p)=p+p*-1 > 0* 。如果- A 发生,那么我对- A 的下注赢了*(1-p *)x(p */(1-p *))= p ,对 A 的下注输了 1-p ,总收益为 p-(1-p)=p+p-1 > 0
没有人谈论数据经济的根本问题
这是数据深度挖掘系列的第 1 部分,重点关注作为资产的数据、数据市场以及区块链技术如何让数据经济成为现实。
数据是新的石油
世界上最有价值的资源不再是石油,而是数据。在信息时代,数据推动增长和变革,提高生活质量,为更公平、更高效的社会铺平道路。
例如,在医疗保健领域,数据被用于预测流行病、预防疾病和改善治疗[ 福布斯、来源 ]。政府使用数据在最需要的地方实施项目,例如,通过了解应该在哪里建造新学校或开辟新的公交线路。事实上,从气候到人工智能,现代社会的几乎所有领域都将受到更好的数据访问的积极影响[ 世界经济论坛,来源 ]。
这也创造了围绕数据的重大经济机会。据估计,2016 年仅欧盟的数据经济价值就接近 3000 亿€,预计到 2020 年将翻一番以上,达到€的 7390 亿[ 欧盟委员会,来源。在全球范围内,据估计,更好地访问数据可以帮助释放至少 3-5 万亿美元的全球经济价值[ 麦肯锡 ],这相当于世界生产总值的 2-5%的增长!
数据很难交易
如果数据的价值显而易见,潜力如此巨大,为什么数据革命还没有发生?为什么我们仍然在等待承诺的数据驱动的创新和改变游戏规则的社会变革?
原因很简单。
- 大多数数据以未提炼(或非结构化)的形式存在,将其转换为结构化数据(软件中使用的格式)并不容易。
- 数据所有者使用不兼容的数据模型来构建他们的数据,这些数据保存在孤立的孤岛中,尽管经常受到其他人的追捧。
- 还没有人想出如何有效地定价和交换数据。
简而言之,没有标准或平台可以让数据交换像股票市场那样顺利进行——这很疯狂——因为数据将成为本世纪最有价值的资产。
因此,交易数据是乏味的。它通常如此昂贵、低效且法律上繁琐,以至于组织宁愿完全避免交易数据[Gartner;经济学家,来源。
这是没有人谈论的数据经济的基本问题:
除非我们为数据所有者和收集者创造必要的基础设施和激励机制,使他们的数据可供他人使用,否则我们无法释放数据经济的全部潜力。
创建一个开放的数据市场
从历史上看,连接供给和需求的最佳方式是开放市场。它们提供了基础设施,并通过允许各方自由买卖彼此的资源,为交易创造了激励。
数据的问题在于,为它创建一个开放的市场带来了一系列独特的挑战,因为它是一种无形的非竞争资产,不像今天几乎所有的商业交易。
也就是说,一旦数据被获取,它就可以与另一方免费共享,这在传统的基于稀缺性的资源定价方法中产生了矛盾——以及许多其他问题。
下一篇数据深度探讨文章将探讨新兴的开放数据市场、它们的实际应用,以及为什么区块链是实现开放数据交换所缺少的关键技术。 继续阅读 ➔
未来不再是过去的样子…
这句不朽的话来自约吉·贝拉,一位为纽约扬基队效力的美国棒球运动员。
显然他的意思是,“时代不同了。不一定更好或更坏。就是不一样。”
未来不确定。人类对不确定性有着强烈的厌恶。随着机器学习在各个领域的应用以及流程驱动任务自动化的增加,人们已经有了很多关于其对行业性质的影响的猜测。
“机器的三月让手闲下来”——纽约时报,1928 年
《经济学家》的一篇文章表明,美国 47%的工人从事着潜在自动化的高风险工作。在英国是 35%,日本是 49%。风险最大的行业包括运输和物流、办公支持、销售和服务——几乎所有行业都是如此!
作为一个乐观主义者,我真的等不及被裁员。我生活中自动化程度越高越好。你花在过程驱动的任务上的时间越少,效率就越高。它将释放资源来生产目前不存在的产品、服务和发明。
思考未来可能会发生什么令人不安,但如果最近的事态发展可以借鉴的话,这可能是相当具有革命性的。几周前,我看了杰夫·贝索斯的年度信,信中谈到了第一天和第二天的公司。有趣的是,看看第一天公司的创始人把他们的个人财富投资在哪里…
聚变能
聚变能 101:
- 你把氢的两种同位素融合在一起,就会产生氦
- 氢在海洋中大量存在,副产品氦是一种安全的气体
- 因为两个氢原子带正电,它们自然会互相排斥,所以你必须以很高的速度把它们扔向对方,这样核力会让它们结合,产生氦气
- 然后,气体必须被加热到 1.5 亿摄氏度,产生等离子体,并保持在磁场中
- 扔进几个微波和另外几个反应,你最终会得到类似太阳产生的能量
- 这一切都在这个 15 分钟的对话中解释
目前有两种方法。
国际热核实验反应堆(ITER)
- 目前正在进行的最大的科学项目
- 投资 200 亿美元在这个项目上,主要目的是在地球上创造一个人造太阳
- 如果成功,将与人类登月和 DNA 测序齐名
- 贝佐斯的探险为公司注入了一部分资本
- 该公司正在使用聚变技术以低成本创造大量的清洁能源
- 我发明了一种类似于巨型柴油发动机的机器,它使用大活塞来产生压缩和热量,除非它们从中获得聚变能
- 预计聚变能源将于 2040-2050 年可用
行星资源
投资者:拉里·佩奇(谷歌联合创始人)、理查德·布兰森、罗斯·佩罗
短游戏
目前正在开发的开采小行星的技术可以降低在太空通信、观察和操纵的成本,从而提高地球上的资源效率
漫长的游戏
开发技术,勘探和开采近地小行星的材料
新贸易路线:小行星将开启太阳系经济
- 自从登上月球,人类就被困在地球重力井的底部
- 这个想法是从太空获取燃料到达火星
- 火箭依靠小行星上丰富的氢和氧运行效率最高
下一次淘金热:开采小行星
- 我们已经在加拿大开采了丰富的矿体,其起源可以追溯到小行星撞击
- 从小行星上收获的铂族金属在小行星上的浓度要高得多
- 一颗 500 米宽的富含铂的小行星含有的铂是世界年产量的 174 倍,是已知铂族金属储量的 1.5 倍
我们以前见过类似的基础设施扩张。在工业革命期间,随着制造业从家庭转移到工厂,我们创建了主要的城市中心。原材料和资源来自遥远的地方来创造成品。运输系统随着铁路工业的出现而发展。适应处理这些新项目规模的通信、银行和金融机制。随着我们的基础设施扩展到太空,我们将看到类似的演变。我们将建造轨道城市和重型制造设备,由来自小行星的原材料供应。数百万人最终将在太空生活和工作。–James or sulak,行星资源公司
读心术
投资者:脸书和埃隆·马斯克
脸书正在研究一种非侵入性系统,它可以让你用脑电波一分钟打 100 个字。马克·扎克伯格相信这项技术“会让你只用大脑交流”。
Bob McDonald 与 Jack Gallant 博士就怪癖夸克进行了一次有趣的采访,讨论了我们目前在读心术方面的情况以及前所未有的进入大脑所产生的问题。
机器离读懂我们的思想有多近?
- 如果我们知道有人在想一只狗,那么我们就可以测量与想狗相关的活动模式
- 随着时间的推移,你可以建立一个字典,在可以测量的大脑活动模式和其他类型的想法之间进行转换
词典目前有多丰富?
- 如果一个人在看电影,你可以通过大脑活动大致了解他们在看什么
- 它会告诉你屏幕有多亮,颜色和阴影
- 但无法破译大部分细节
你能接触到我们不知道的想法吗?
- 可以获取的第一类信息是大脑中正在发生的想法
- 你可能破译的第二类是潜意识思想
- 第三类是潜在的长期记忆,它们被锁在大脑突触深处,此时无法进入
随着技术发展成为商业接口,最大的担忧是什么?
- 众所周知,人类不善于保护自己的隐私
- 最终,这项技术将能够解码任何活跃的大脑工作空间
- 它将打开先前私有的无意识和有意识的大脑空间
- 它将使你能够去到一个外国,让你的思想被解码,然后用当地的语言说出来
- 这将引发这样的问题:谁控制着这个设备,一旦它离开你的大脑,这些信息会发生什么
但是我们仍然没有那个悬浮滑板…
很快我们将拥有制造人造太阳、开采小行星和读心术的技术,但我们不能发明马蒂·小飞侠在《回到未来》中的悬浮滑板?未来听起来没有我最初想的那么令人兴奋…
人工智能的未来:重新定义我们如何想象
原文贴在 FICO 博客
展望未来 20 年,我认为我们将远远超越人工智能迄今带来的生产力提升。随着人工智能的出现,我们将看到我们个人生活以及整个社会的复兴。
卫生保健
今天,我们的设备能够监测我们走的步数、心跳速率以及汗水含量。所有这些丰富的信息使得一个由医生、工程师和分析师组成的团队能够监测我们的健康状况,并保持我们的最佳表现。同样,随着基因组测序和神经图谱方面的创新通过 FDA 试验,我们将很快看到个性化医疗领域的巨大飞跃。人工智能将帮助我们了解个体的生理需求,以便提出定制的处方,提高我们的整体健康标准。
认知能力
人们热衷于提高认知。谁不想更好地记住名字和面孔,更快地理解困难的抽象概念,更好地“发现联系”呢?谁会严重反对能够在更深层次上欣赏音乐呢?
最佳认知功能的价值是如此明显,以至于没有必要详细阐述这一点。今天,我们通过艺术、电影、音乐、博客和各种社交媒体应用来表达自己。在图像识别领域,AI 已经可以通过观察远远超过 RGB 的东西,比我们“看”得更好。虚拟现实让我们感觉自己仿佛被传送到了另一个世界。为了让我们更好地体验我们周围的世界,数据可视化和降维算法的新习惯用法一直在不断产生。
我们一直在努力增强我们的五感,以超越人类的极限。10 年后,这些创新加上物联网设备将成为我们的延伸,帮助我们更深刻地体验我们的周围环境。
情商
正如我们增强了我们的五种认知感官一样,我们也增强了表达自己和理解周围人的能力。
很多时候,我们甚至不知道自己想要什么。我们努力以一种特定的方式与周围的人联系,或者消费一种特定的产品,只是为了能感受到一种无法描述的独特情感。我们感受到的不仅仅是快乐、悲伤、愤怒、焦虑或恐惧。我们的情绪是上述所有因素的复杂组合。
随着神经绘图的创新,我们将更好地了解我们作为人类是谁,并更好地了解我们可以达到的无数种情绪状态。随着我们对脑电波进行无监督学习,并帮助找到提高情商的创新方法,我们复杂的情绪模式将得到更好的理解。这包括理解我们自己的情绪和对我们周围的人更加敏感。
或许我们可以解开从未体验过的新情绪。在合适的人手里,人工智能可以作为我们的延伸,帮助我们与生活中我们重视的人建立有意义的联系。
经验和想象力
人工智能对我们的经验和想象力的影响将来自更好的认知能力和情商的聚合。人工智能的最新创新可能会帮助我们解锁新的认知体验和情绪状态。
让我们想象一下,我们今天的体验模式是在空间 x 中呈现的。10 年后,让我们说,体验模式是在空间 Y 中呈现的。空间 Y 将比空间 x 大得多。这个 Y 的未来空间可能会接触到除了我们传统的快乐、悲伤和疯狂之外的新类型的情感。这个新的 Y 空间甚至可以让我们更准确地理解反映我们想要表达的抽象思想。
这个新的 Y 空间实际上可以打开一个新的可能性世界,它超出了我们目前的想象。未来的人们将以比我们今天更丰富的程度来思考、感受和体验这个世界。
沟通
10 年前,我们的大部分交流仅限于电话和电子邮件。今天,我们可以参加视频会议,虚拟现实和社交媒体上的各种应用程序。随着我们认知能力和情商的提高,我们可以通过分辨率更高、抽象程度更低的习语来表达自己。
我们已经有佛罗里达大学的学生实现了只用意念控制无人机。我们甚至可以使用振动游戏机,利用我们的触觉使马里奥赛车游戏更加逼真。10 年后,我们相互交流的方式将比今天更深入,更具表现力。如果我们有足够的希望,我们甚至可能瞥见*《星球大战》的全息图和《x 战警》*的心灵感应通信。
今天的虚拟现实只会限制我们的视觉和听觉。在未来,虚拟现实可能真的允许我们去闻、尝和触摸我们的虚拟环境。除了访问我们的 5 种感官,我们对某些情况的情绪反应可能会通过人工智能的力量进行微调和优化。这可能意味着分享我们的主要角色对超自然活动的恐惧,感受 T2 艾玛的心碎,或者对口袋妖怪的冒险感到兴奋。当我们探索智能虚拟现实控制台的戏剧艺术时,所有这些都是可能的。
信息安全
人工智能允许我们以更高速度挖掘更多的非结构化数据,以产生有价值的洞察力。然而,这些非常敏感的数据落入坏人之手的风险也会增加。
今天,网络安全是每个人心中的一个主要问题。事实上,2017 年是指纹被黑的一年。在人工智能的帮助下,信息技术将变得更加复杂,以保护我们生活中珍惜的东西。
这是人类的天性,想要超越我们的极限,变得更加强大。每个人都希望健康长寿,体验更生动,感受更深刻。技术只是实现这一目标的手段。
数据科学的未来
Copyright: Warakorn — Fotolia
影响数据科学未来的三个关键趋势,以及如何利用即将到来的机遇
那是晚上 8 点左右,我买了一些杂货,正开车回家。当我开车进入一个灯光昏暗的横截面时,我几乎没有注意到闪光,然后我感觉到了一个猛烈的冲击,当时另一名司机失去了对他的汽车的控制,撞上了我。幸运的是,损坏只发生在车辆上。接下来发生的事情,纯粹是未来的事情。
我没有提交车祸保险索赔的常规文件,而是拿出我的保险应用程序,选择了车祸菜单。然后,我被问了几个问题,并按照指示,其中包括采取了一些照片。当我完成时,应用程序通知我道路救援正在路上,事故已经被报告。
第二天,我接到保险公司的电话。他们告诉我,在审查了我的索赔数据、我车内摄像头的视频片段以及无数其他传感器的数据后,他们处理索赔的机器学习算法很快验证了我对事件的叙述。
他们正在向对方的保险公司索赔。此外,在接下来的几天内,我将能够在他们合作伙伴的汽车店里取车。
虽然这只是一个故事,但让这一切发生的技术,以及更多的东西,就在眼前。分析的应用和使用机器学习工具来释放数据价值(也称为数据科学)正在增长,我们才刚刚开始触及表面。
不断增长的数据量、改进的机器学习算法和更好的计算资源这三个相互交织的趋势正在以令人兴奋的方式塑造数据科学领域。本文将关注这些趋势的当前发展和未来,它们的影响以及如何准备。
数据爆炸
自我们的数字时代开始以来,我们目睹的数据指数增长预计不会很快放缓。事实上,我们可能只是看到了冰山一角。未来几年将会产生越来越多的数据洪流。新数据将作为我们数据科学模型的火箭燃料,产生更好的模型以及新的和创新的用例。
物联网的发展——IoT
一个明显的来源是物联网。目前,全球约有 70 亿台联网物联网设备,预计 7 年后这一数字将增至 215 亿台。不仅有更多的设备上线,而且随着硬件的改进,它们提供的数据类型将更加丰富和多样化。物联网数据的最大生成者预计是航空业、采矿业和汽车业。
社会化媒体
社交媒体是另一个巨大的数据来源。2012 年 5 月,我们每分钟向 YouTube 上传大约 72 小时的视频。五年后,这个数字飙升至每分钟 400 小时,相当于每天 65 年的视频。脸书是另一个巨大的数据生成器,截至 2017 年,每月用户超过 20 亿,每分钟产生超过 400 万个赞。
除了上述数据源,我们还有博客、娱乐、支付交易、监控数据、电信数据和金融数据。该列表绝非详尽无遗,随着数字化进程的推进,以及公司发现需要收集更多客户信息,数据来源将继续增长。
这种数据增长趋势的影响是不可低估的。我们可以访问的数据越多,不仅会提高我们机器学习模型的精确度和准确性,还会增加它们可以应用的可能领域,从而推动对数据科学的需求。
所有这些数据只是一种喂给机器的方式——真的!如果不是有越来越多的可用训练数据,我们的许多机器学习模型都不可能取得如此大的进步。这让我们看到了下一个关键趋势。机器学习算法效率的指数增长。
机器的崛起
机器学习算法,尤其是深度学习的子领域,在过去几年中发展迅速。此外,机器学习软件的开发也在紧张进行。这提高了算法的质量,使工具更容易使用,降低了有抱负的数据科学家的准入门槛。由于对机器学习工具的强烈依赖,该领域的进展直接影响数据科学的有用性和能力。
什么是机器学习?
我们可以将机器学习算法视为能够基于我们输入的数据产生某种输出的软件,最重要的是,这种软件使计算机能够在没有显式编程的情况下进行学习。
通常,这是通过向算法提供大量示例来实现的,它会从中学习。这与专家系统形成对比,在专家系统中,所有的逻辑都由程序员编码到算法中。在过去的 5-10 年里,机器学习中最令人兴奋的子领域之一是深度学习。
深度学习算法基本上只是许多接受数据的输入节点,然后这些数据被馈入其他节点,最后到达一个输出层。由于它们与大脑的工作方式相似,深度学习算法被称为神经网络。我们不会深入研究这些网络的细节,因为这超出了本文的范围,但可以说它们的发展是机器学习中一些重大突破的背后。
AlphaGo
深度学习成功的一个显著例子是 AlphaGo,这是一种有两个玩家的战略游戏,被认为比计算机更难学习,甚至比国际象棋更难。
2014 年,DeepMind 公司启动了研究项目 alpha Go——其使命是击败人类围棋选手。一年后,AlphaGo 击败了欧洲围棋冠军范辉,2016 年 3 月 AlphaGo 与世界上最好的棋手之一 Lee Sedol 对弈。AlphaGo 赢了 5 场比赛中的 4 场。该程序的更新版本被创造出来,AlphaGo Zero 在与它的前身 AlphaGo 的 100 场比赛中赢了 100 场——完全统治了任何人类对手。
机器视觉领域令人印象深刻的进步也是由深度学习推动的。在机器视觉领域,我们现在能够创造出比人类更好地对一些图片进行分类的算法。
我们也能够给出照片内容的摘要。用不了多久,这些算法就可以“观看”视频并学习其内容,这有可能颠覆几个行业。
我们可以使用常规搜索来搜索数百万小时的视频。可以通过直接查询闭路电视录像来进行监控。
在自然语言处理方面,我们也取得了巨大的进步。手写识别与人类水平的技能相当,情感分析在过去几年中有了很大的改进,我们总结书面文本的能力也有所提高。
这些例子中的许多都强调了机器学习算法与人类不相上下或者比人类更好的情况。在接下来的几年里,我们将继续开发超人机器。
算法和我们的主要区别在于它们的指数级改进率。没有迹象表明这种趋势会停止。相反,预计将呈指数级增长。
更好、更易于使用的算法将通过改善我们当前的模型来积极影响数据科学,并将使机器学习模型能够用于以前为人类保留的任务。能够在业务流程中使用和应用这些算法的公司,很可能会比竞争对手拥有强大的比较优势。
心不在焉
我们的计算能力随着我们的机器学习算法和不断增加的数据量而发展。我们正在创造越来越强大的计算机,能够存储越来越多的数据,并以前所未有的速度处理这些数据。
对于神经网络,我们已经从 CPU 转向 TPU,云服务提供商也在不断改进他们的服务——所有主要的参与者都提供机器学习即服务,MLaaS。
计算能力的提高和资源访问的简化是数据科学领域的强大推动力。
从 CPU 到 TPU
多年来,我们一直使用 CPU 来训练我们的神经网络。这花费了大量时间,并限制了我们可以建立的潜在模型。2007 年有了突破,GPU 最大的厂商 Nvidia 发布了 CUDA 编程平台。
这使得应用程序开发人员能够利用 GPU 的通用并行处理能力,几年后,GPU 开始彻底改变我们的神经网络。快进到 2017 年,谷歌发布了 TPU,或张量处理单元。这种设备在训练许多神经网络方面甚至比 GPU 更快,随着 GPU 在过去几年中不断改进,TPU 也可能会继续改进。
所有主要的云提供商现在都提供构建和部署机器学习模型的环境。他们的产品范围从基于 TensorFlow 项目的谷歌云机器学习引擎到微软 Azure 机器学习工作室及其 Cortana 智能画廊。随着这些产品的改进,使用机器学习工具所需的技能可能会减少,从而有助于降低使用数据科学的门槛。
数据科学码头工人
在开发方面,我们开始看到越来越多的项目使用 Docker 进行数据科学开发。Docker 是一款用于虚拟化计算环境的工具。将它用于数据科学使得扩展和部署机器算法变得更加容易。
首先,它很容易设置,因为您可以从 Docker 文件构建 Docker 映像,这些映像可以专门定制以满足您的机器学习项目的需求。此外,Docker 实例可以很容易地部署到云中,并按需运行。这使得数据科学可能比以前更加敏捷。
最后,终端设备也变得越来越智能和小巧。端点设备是指位于网络边缘的设备。例如电话或其他类型的物联网设备。2007 年发布的第一代 Iphone 拥有 412 MHz 的 CPU 和 128 MB 的内存。最新的 Iphone XS Max 现在拥有令人印象深刻的 6 核处理器,两个 2.5 GHz 的 Vortex 处理器和四个 1.59 GHz 的 Tempest 处理器,以及 4 GB 的 ram。
当然,芯片制造商正在取得的许多进步将会扩展到其他设备上,提高它们的性能,降低它们的成本。这一切都增加了我们可以从物联网设备中预期的数据量和数据类型,这些数据可能再次被用于推动数以千计的机器学习算法在云上运行。
那么这有什么关系呢?
在这一点上,你可能会问自己,为什么这是相关的?嗯,即使计算领域的趋势有一半以目前的速度继续发展,也仍然会对数据科学产生巨大的影响。制作模型、将它们部署到生产环境中以及将它们集成到业务流程中变得更加容易。
鉴于许多最近的发展和持续的趋势,我们可能刚刚开始触及数据科学为我们提供的皮毛。但是,我们应该如何为这些关键趋势做准备,我们可以做些什么来增加从中创造成功商业模式的机会呢?这就把我们带到了下一个话题。
如何为数据科学的未来做准备
公司可以也应该以多种方式为数据科学的未来做准备。其中包括创建一种使用机器学习模型及其输出的文化,标准化和数字化流程,尝试云基础架构解决方案,对数据科学项目采用敏捷方法,以及创建专门的数据科学部门。能够执行这些要点将增加在高度数字化的世界中取得成功的可能性。
数据科学部门
在之前的工作中,我是一家保险公司的数据科学家。他们做出的明智之举之一是创建一个跨公司垂直行业的分析部门。
这使得我们更容易在各种数据集上重用我们的技能和模型。这也是对公司其他人的一个信号,表明我们关注数据科学,这是一个优先考虑的问题。如果一家公司有一定的规模,创建一个专门的数据科学部门绝对是正确的举措。
标准化
流程的标准化也很重要。这将使这些流程更容易数字化,甚至在未来实现自动化。自动化是增长的关键驱动力,使其更容易扩展。一个额外的好处是,从自动化流程中收集的数据通常比从手动流程中收集的数据少得多,也不容易出错。由于数据科学模型的一个重要使能因素是获得良好的数据,这将有助于使模型变得更好。
采用数据科学
公司还应该有一种采用机器学习算法的文化,并将它们的输出用于商业决策。当然,这往往说起来容易做起来难,因为许多员工可能担心算法会让他们过时。
因此,重点关注员工如何利用他们现有的技能和算法来做出更高层次和战术性的商业决策至关重要,因为这种人机结合很可能是许多职业的未来。可能还需要几年时间,机器学习算法才能在开放的世界环境中独自导航并做出超人的决策,这意味着由于机器的崛起而导致的大规模失业在不久的将来不太可能发生。
总是实验
随着新数据从物联网来源生成,探索新数据集并了解如何使用它们来增强现有模型非常重要。有源源不断的新数据等待被发现。
也许将一个模糊数据集中的两个新变量包含到您的模型中会将潜在客户生成模型的精度提高 5%,但也可能不会。关键是要不断尝试,不要害怕失败。像所有其他的科学调查一样,失败的尝试比比皆是,胜利者是那些坚持尝试的人。
创造一个促进实验的环境,并尝试对现有的业务流程进行增量改进。这将使数据科学家更容易引入新模型,并将重点放在较小的改进上,这比更大的宏伟愿景风险小得多。请记住,数据科学仍然很像软件开发,项目越复杂,失败的可能性就越大。
尝试构建一个应用程序,您的客户或供应商可以使用它来与您的服务进行交互。这将使收集相关数据变得更加容易。建立激励机制,促进应用程序的使用,从而增加生成的数据量。同样重要的是,应用程序的 UX 要有吸引力,并促进使用。
我们可能需要走出舒适区,迎接数字黄金带来的机遇和挑战。随着数据量的持续增长,机器学习算法变得更智能,我们的计算能力提高,我们将需要适应。希望通过创建一个使用数据科学的强大环境,您的公司将为未来做好更充分的准备。
如果您喜欢这篇文章,并希望看到我的更多内容,或者希望使用我的服务,请随时通过 LinkedIn 联系我,地址是https://www.linkedin.com/in/hans-christian-ekne-1760a259/,或者访问我在https://ekneconsulting.com/的网页,查看我提供的一些服务。如有任何其他问题或意见,请发邮件至 hce@ekneconsulting.comT4。
感谢阅读!
数据可视化的未来
数据改变了我们对世界得出结论的方式,数据可视化帮助我们更好地理解数据。
数据可视化——正如我所观察到的——由于三大领域的发展而发生了变化。用流代替静态数据,改变上下文和更好的数据处理和设计工具。这将深刻改变数据可视化对我们未来生活的影响。
新上下文
潘多拉是希腊神话中众神创造的第一个人。作为一个概念,这很重要,因为潘多拉是我们渴望成为的人的隐喻。她是我们自己的代表,她是我们想要成为的样子。非常像在场的社交媒体中的数字化身。在脸书,我们不分享我们最糟糕的时刻或弱点,我们炫耀我们的成就,只上传我们最好的照片。我们创造更好的自我版本,比如数字潘多拉。
Data visualization of related topics and users on Twitter
我去谷歌和其他社交媒体平台下载了所有我能找到的关于我自己的个人数据。1.2GB 的下载数据之后,我可以自信地说,这是惊人的准确,但也有些不完整。虽然,这比我预期的要多。
将来这种情况会改变。目前,我们正以指数级的速度每年创建 28 万亿字节的数据,因此很容易预测,将会有更多关于我的数据,事实上是关于我们所有人的数据,从而创建一个关于我们是谁的更完整的图像。不仅如此,还包括我们在过去任何特定时间的身份和位置。有一天,我的数字化身可能没有潘多拉漂亮,但比我们任何人希望的都要准确。
不仅人的数据将更容易获得,而且任何东西的数据都可以获得,比如我们的汽车,当然还有我们的家。通过数据流互连的所有设备将帮助我们提高安全性,提高运营效率,并更好地了解消费者需求。
不断增长的数据雪崩
由于我们收集的数据量惊人,以及我们用来收集数据的传感器,基于流的 API 变得越来越普遍。
Data visualization for a conceptual car dashboard of the future
我们收集的数据中只有很小一部分应该放在数据库中。其中大部分是由发出事件的系统收集的,比如电动汽车的电池电量。这些数据以数据流的形式出现,并被高效地交付给那些可能想要使用它们的人。在传感器和消费者之间放置一个数据库将成为不必要的奢侈品。没有明确目的地囤积数据代价高昂。
使用数据流改变了我们对世界得出结论的方式。这意味着每一个新的数据点都会立即影响我们对世界的理解。
图表插入到实时数据流中。消息更快地传遍市场。阅读每篇文章所用的时间更少,而生成数据甚至新闻的自动化程度更高。
Data visualization of TensorFlow experiment called T-SNE by Google
你所需要交流的只是一种情绪,让一个算法来拾取你的故事并对其进行分类。例如,当马斯克在 Twitter 上宣布他正在考虑将特斯拉私有化时,市场的反应非常迅速。
然而,对于算法来说,从图表和动画视频等非结构化数据中获取情感几乎是不可能的。图表和动画总是为人类消费而创造的。
不再是了。彭博创造了一个名为散射行动的系统。它可以沿着一个轴读取每个像素,以揭示产生每个点的信息。
Data visualization reversed: From chart to data with Scatteract by Bloomberg
该系统使用光学字符识别(OCR)和深度学习技术从图表的图像中提取数字数据点,然后将结果转换为表格。这是有史以来第一次数据可视化被逆转。现在我们可以从视觉再回到数据,而不是从数据到视觉。
尽管 Scatteract 还很粗糙,但这些工具的改进只是时间问题,在未来,数据可视化对于算法来说将是完全清晰的。
塑造未来的工具
在谷歌、苹果和宝马的许多产品公告中,越来越多的数据将通过增强现实或投影覆盖在我们的物理环境中。这意味着不仅数据将更加可视化,而且我们周围的视觉现实也将转化为数据。
Data visualization of a new AR wind shield by Apple
到 2020 年,70%的新车将搭载某种形式的 AR 技术,就像这个苹果挡风玻璃。
智能城市交通管理,如“滴滴出行智能交通大脑”,将允许交通参与者和寻路软件做出更明智的决策。今年,中国城市安装了滴滴智能交通灯,节省了多达四分之一的等待时间。滴滴所有 4.5 亿移动用户的数据都是共享的。包括来自联网汽车和交通管理系统的数据,以创建最佳的交通流量图。
Data visualization of traffic by Didi Smart Transportation Brain
城市交通问题不仅仅是呈现一幅画面。智能交通系统可以预测未来几小时内哪里会发生交通堵塞。它可以预测出租车和公共交通的短缺,并可以重定向其他交通参与者,以最有效地处理即将到来的拥堵。
一个城市变得越聪明,它的数据就越需要被分析和“读取”。数据可视化可以轻松检测数据中的异常、模式和峰值。随着数据可用性的增加,用户对其有用性的期望也在增加。
如果像滴滴这样的新解决方案告诉我们关于新工具的任何事情,那就是人们将对数据的可用性、准确性、有用性以及未来如何可视化有更高的期望。很明显,新工具的趋势是向用户提供更多数据,而不是更少。它们将更容易使用,因此覆盖范围更广,正如我们看到的对 Tableau 和 Power BI 的兴趣越来越大。
Power BI compared to Tableau in Google Trends
在未来,专业人士将比以往任何时候都更需要像记者一样,根据数据做出决策。在“假新闻”时代,新闻故事越来越受到数据的破坏。一个很好的例子是“美国零售业的末日”。
Data visualization of America’s Retail apocalypse by Bloomberg
它描绘了一幅关于美国各地商店倒闭的清晰画面。不仅如此,光是数据就不会那么可怕了。红色和黑色的油漆,它的情感诉求被大量强调。商店的关闭给人以威胁的感觉。
为了对更广泛的受众产生更大的吸引力而呈现的数据,允许通过更多样化的解释进行更广泛的数据审查。
数据可视化不同于纯粹的理性分析,因为它旨在讲述一个故事,以产生情感反应。你可以有理性的证据就在你面前,但是如果你不能想象以前从未存在过的东西,就不可能刺激深远的行动。
算法可以预测,人类可以想象。数据可视化最能激发想象力。
未来的工具将允许更多的方式来分割数据。这一点很重要,因为工具非常有限,很容易陷入重视可衡量的东西的陷阱,而不是衡量有价值的东西。这将允许更准确地描绘我们周围的世界,避免潘多拉风格的虚假未来的烟雾和镜子。
以下是来自莫斯科 BigData 的演讲全文:
智能讲故事的未来
我们是讲故事的人。从古代到现代文明,我们在漫长的历史中一直在讲述故事。今天,我们仍然明白,对于任何人来说,故事是最好的交流方式。当我们讲述我们的故事时,我们将我们的想象力、创造力、批判性思维、意识、同理心和理解他人的能力结合起来,以影响、娱乐、激发和团结他人。
多年来,技术改变了我们讲述故事的方式。现代媒体和计算机技术的使用把我们的故事增强成一种几乎超现实的环境,就好像我们就在那里;我们今天的故事充满了动作、冒险、戏剧、悬疑和英雄。
随着我们继续拥抱适应性和认知学习等更新的技术,这种人工智能将如何塑造我们的故事?我们如何应用机器学习不仅增强我们的叙述,还提高我们与正确的人联系的能力?
在当今的现代世界,不是讲故事的问题,而是花时间讲故事的问题。作为一名生活在韩国的外国人,我遇到了一个常用词,不仅在商业中,而且在韩国生活中也是如此——빨리빨리(Pali Pali ),意思是快。我相信这个词同样适用于我们今天的生活。尽可能快地完成它,然后继续做下一件事,尽可能快地做这件事,一遍又一遍,这样似乎永远不会结束。
同样的方法也适用于商业。我们一直在寻找提高生产率的方法。我们的故事讲述现在已经转变为商业世界中的内容创作和信息传递,因为我们接触到我们的受众,说服他们使用我们的产品或解决方案。
那么 AI 如何帮助我们进行内容创作呢?我相信人工智能可以用来帮助增加所有业务线的内容创作叙事。随着组织共享更多信息,无论是关于行业、公司、人员、产品、解决方案还是趋势的信息,内容创作达到了前所未有的高度。公司创建这些内容是为了建立透明度和信任。但是,随着内容创作而来的是同样的挑战,即创作内容。各种营销报告表明,超过 60%的组织在尝试创建内容时不断面临挑战。这就是人工智能发挥作用的地方。如果您可以插入关键内容主题和信息,在几个小时内而不是几天甚至几周内生成叙述、构建故事并交付引人注目的内容,会怎么样?人工智能可以搜索关于该主题的互联网,监控社交媒体以了解趋势和看法,了解行业中广泛和具体的客户挑战,并强调通过关键产品优势或功能解决问题的可用解决方案。随着认知技术提高理解和学习的能力,它们也可以提高我们的生产力,以生成高质量的内容实施,使我们能够专注于业务的战略组成部分。
内容创作问题的另一面是,当我们创作所有这些内容时,许多人认为它们被浪费了,因为它们没有到达正确的受众,或者只是没有与我们的受众联系起来。直到最近,我们还没有合适的工具来了解谁真正对我们的内容感兴趣。我们进行了测试、调查和研究,但即使我们有这些信息,大部分时间也是过时的,太旧了,不能用于当前的使用。
大数据挖掘有助于改变这种心态。我们现在看到实时的大数据分析,为我们提供了更可靠的数据,但有时这仍然不足以了解谁从我们的内容创作中受益。这就是预测分析发挥作用的地方,它不仅使用实时数据来确定品牌认知、用户反馈和当前的关键见解,以正确定位我们面向正确受众的产品;而且使用认知学习来确定最有效的信息传递、媒介和内容信息传递的类型,以吸引他们的功能、情感和理性期望。在这种情况下,认知学习可以根据他们的行为、心理特征、个性、购买习惯和趋势,通过创建像故事一样触动他们的个性化信息,来确定接触他们的最佳方式。这些类型的故事讲述结果将与观众联系起来,并很容易影响他们对产品或解决方案的心态。
随着人工智能增强我们成为更好的故事讲述者的能力,这只是人工智能融入多种科学和商业应用的一个例子。我们与人工智能合作的能力将建立一个更美好的未来,以理解和解决从改善我们的日常生活到探索复杂情况的挑战,从而增强全人类的创新。
汽车工业技术的未来
就像手机现在能做的不仅仅是打电话,汽车能做的不仅仅是开车和停车。近年来,汽车行业与主要技术公司携手合作,以提供最先进、最安全和最舒适的汽车。汽车正在成为大型智能设备,具有先进的紧急制动能力、自动驾驶的地图技术、更好的燃油效率以及作为一种运输形式的汽车服务。
在安全方面,汽车正在改善司机和周围其他车辆的生活,减少从 A 点到 B 点的麻烦,并在整个过程中娱乐我们,这样的方式并不缺乏。在未来几年,汽车行业有望取得更大的进步,让我们离更加互联和数字化的环境更近一步。应用程序 Blinker 就是这样一项技术进步,它将控制权还给消费者,让他们可以在智能手机上购买、出售和融资汽车。
这里有四项最具突破性的技术,你可以期待在不久的将来出现在汽车行业。
1)更省油的游乐设施
特斯拉处于节能运动的前沿,发布了一系列电动和混合动力汽车,一次充电可以行驶数百英里。2016 年,全球售出了超过 200 万辆电动汽车,随着更多汽车制造商将电动汽车技术应用到他们的产品中,这一数字预计将在不久的将来上升。大众和通用汽车等公司最近向他们的车队推出了电动汽车,而沃尔沃表示,到 2019 年,他们生产的所有发动机都将配备电动马达。
电动汽车也变得越来越实惠,现代、起亚和丰田等公司推出了 3 万美元以下的混合动力汽车,这表明投资燃油效率可能很快会在全球范围内被广泛采用。预计到 2030 年,美国 20%至 25%的汽车销售将是电动汽车,而这一数字在中国预计将达到 35%。
2)预测车辆技术
随着预测能力在汽车中变得越来越普遍,个性化的驾驶体验,人工智能(AI)和机器学习(ML) 在汽车行业的未来具有重要作用。越来越多的制造商正在应用使用数据来自动设置车辆过程的算法,包括汽车的信息娱乐系统及其应用程序偏好。车辆正在成为物联网设备,可以连接到智能手机并接受语音命令,改变用户界面。
预测车辆技术也可以以汽车内传感器的形式使用,通知车主车辆是否需要机械师维修。根据您汽车的里程和状况,该技术将能够评估其性能,实时安排预约,并通知用户与因公司召回而发生故障的汽车相关的任何安全隐患。
3)自动驾驶技术
自动驾驶技术已经取得了很大进展,尽管一些公司已经在开放道路上测试他们的自动驾驶功能,但我们距离广泛采用这些汽车还有很长的路要走。许多汽车已经具备了驾驶辅助技术形式的半自动驾驶能力。其中包括自动制动传感器、高速公路车道传感器、监控盲点的地图技术、汽车前后的摄像头、自适应巡航控制和自动泊车功能。
谷歌最近发布了自动驾驶 pod Waymo,而 Local Motors 也发布了一款全自动驾驶汽车。福特希望到 2021 年能有自动驾驶汽车上路。
4)汽车即服务(CaaS)
汽车即服务(CaaS)是指即将推出的汽车租赁服务,它允许城市司机参与拼车服务。智能设备所有者可以通过一个应用程序叫一辆无人驾驶技术的汽车,该应用程序会根据他们的运输或送货需求来接他们。这项技术的伟大之处在于,不需要驾照就可以进入其中一辆车,充当无人驾驶优步。
IHS Automotive 预测,无人驾驶 CaaS 即将出现,预计将在 2025 年前推出。这种技术有助于降低移动服务成本,同时也为人类司机提供了更安全的替代方案。
底线…
科技行业的一些最伟大的头脑已经与汽车公司联手,以改善我们的车辆运行方式。随着越来越多的公司设计电动汽车,电动汽车技术的兴起有助于在不破产的情况下减少碳排放。
大数据和人工智能在车辆定制方面也发挥着重要作用,通知车主他们的车辆何时需要维护。此外,自动驾驶汽车的兴起和 CaaS 作为移动服务的潜力将极大地节省消费者,同时也增加了他们的安全性。
商业智能可视化的未来
BI 应用程序可视化的未来可能根本不是可视化。
大多数公司已经创建了复杂的商业智能系统,包括基于主题和角色的仪表板。理论上,这种可视化可以为公司的高管提供公司过去、现在和未来的快照。但高管们很少打开这些仪表盘。即使他们这样做,他们也很少能超越对更早时期的事后分析。
高管面临的挑战是知道要寻找什么。现代 BI 系统允许以不同的维度和粒度对数据进行切片和切块。所以,一个勤奋的主管应该着眼于所有可能的组合,以了解组织的真实情况。这项任务即使不是不可能完成,也是很困难的。
未来
未来将会不同。未来的主管不会看仪表板,而是希望将摘要推给她。第二,她不会通过切割来发现洞见,而是会向系统询问更多信息。这个未来的第一部分就快到了。 Tableau 和 PowerBI 已经在仪表盘上设置了人工智能驱动的警报。这些智能警报将被推送给高管。
分析是事情会发生巨大变化的地方。主管不会使用 BI 系统中可用的切片和切块选项。他们将使用自然语言与系统进行交流,并更深入地挖掘数据以确定根本原因。
这种趋势的一个很好的例子是麻省理工学院概率计算项目。
假设首席营销官(CMO)想要确定具有类似业绩的地区。这个问题可以用两种不同的方法来解决。第一个想法是使用 BI 工具和领域专家来定义“相似性”,然后创建一个派生的 KPI,称为相似性。然后,每个区域的相似性得分(相对于其他区域的 w.r.t)可以显示为热图,CMO 可以解释相似区域。
第二个想法是使用机器学习技术。在这种情况下,该问题将引发使用统计方法的区域分析。数据科学家可能会使用异常值检测、归一化和聚类等技术来得出表现类似的区域组。
在数据分析的概率编程世界中,许多这样的任务将自动完成。CMO 字面上问相似性问题,并使用一个 SQL 等价调用 BQL。并且背景中的概率程序对数据建模并使用模拟技术来识别相似的区域。麻省理工团队关于这个主题的一篇优秀论文可以在这里找到。
麻省理工学院的一个团队正在解决使用概率编程进行更智能搜索的问题。SalesForce 的爱因斯坦团队正在使用一种更直接的方法。在一年前的一篇论文中,描述了 SQL 序列——一种用于将自然语言问题翻译成相应 SQL 查询的深度神经网络。
A scheme to implement Seq2SQL (photo from — https://arxiv.org/pdf/1709.00103.pdf)
这些方法是未来事物的范例。想象一下这样一个世界,Alexa 告诉 CMO“公司的整体表现非常好。但一些地区比其他地区做得更好。”CMO 问 Alexa“哪些地区有类似的表现?”。Alexa 将这个句子转换成 BQL 或 SQL (MIT 或 Salesforce)。一旦查询被执行,Alexa 就会用自然语言回放结果。此时(之前不止一次),CMO 可能会要求将相关图表通过电子邮件发送给她的团队。
也许在未来,仪表板不是高管们获取信息的首选。
工作的未来是现在:人工智能帮助求职者找到、获得和保持梦想中的工作
刚从商学院毕业,劳拉就开始建立关系网,并在适当的时候附上一份简历。反过来,她接到了一家商务旅行社的电话,这家旅行社对她的才华非常感兴趣。劳拉接受了面试,她穿着一套新西装,手里拿着一份精心制作的相关简历,提前 30 分钟到场,准备给人留下最好的印象。
等了一个小时后,一名助理把她带进了首席执行官的办公室,在那里,她被反复训练她来自哪里,她的父母是否大学毕业,他们是否患有任何精神疾病,他们以什么为生(“只是为了确保她是专业人士”),她是否已婚或有孩子,以及她将如何吸引劳拉知道对商务旅行丝毫不感兴趣的潜在客户。在采访结束时,这位首席执行官尴尬地透露,他不关心自己即将退休后公司会发生什么。礼貌地感谢首席执行官后,劳拉离开了,希望公司里没有人会再打电话给她。遗憾的是,四个月后,她确实收到了回电。
是的,这是一个真实的故事。而且,不幸的是,这样的面试恐怖故事并不少见。
破碎的招聘流程意味着更多的求职时间
《财富》500 强人力资源高级副总裁兼《福布斯》人力资源撰稿人利兹·瑞恩向证实,“招聘流程已经破碎了 20 年,但其下放的步伐最近一直在加快。”
而且,即使找到了工作,糟糕的招聘过程也会转化成不太好的就业经历: 65% 的人在被聘用后的 3 个月内就开始寻找下一份工作。
好消息是,求职者现在有了一个准备为他们的利益而战的后起之秀:人工智能。
人工智能为求职者提供更好的长期成功
Ken Lazarus、Marlina Kinnersley、WorkFusion、Scout Exchange、Fortay.ai 和无数人工智能公司正在研究、构建和完善人工智能平台,求职者可以依靠这些平台来改善体验。他们的专业知识和解决方案揭示了人工智能在幕后工作的四种方式,以提供更顺畅、更成功的求职旅程。
- 人工智能帮助求职者找到适合他们技能的合适职位
在搜索空缺职位、研究公司、为职位准备简历、写求职信、建立关系网以及参加每个职位空缺的几次面试的过程中,求职往往是一项全职工作。尤其是当求职者没有过滤掉那些不太可能符合他们技能的职位的面试时。人工智能使寻找相关就业机会更加有效,因此也更加成功。
肯·拉扎勒斯,Scout Exchange 的首席执行官,一个为创业品牌和财富 10 强公司服务的人才匹配平台,解释了求职者如何依靠人工智能。他表示,优秀的招聘人员非常了解他们所在的行业,包括完成各自工作所需的技能,以及在主要雇主面前赢得观众所需的人脉。
“如果我在弗吉尼亚州,我想找一份为政府做国防研究和分析的工作,有专门从事这方面工作的招聘人员,获得这份工作的最佳方式是了解他们,”他说。
但是,并不是所有的招聘人员都同样擅长他们的工作。因此,他强调求职者与合适的招聘人员建立关系的重要性。他们可以使用人工智能驱动的侦察交换来衡量参与的招募者。为此,他鼓励求职者向招聘人员询问他们的平台评级。
Scout Exchange 生成一个由人工智能驱动的评级,反映每个招聘人员将候选人与工作匹配的成功程度。糟糕的评级提醒求职者,招聘人员不太可能向他们推荐值得他们付出努力和时间的工作。
- 人工智能帮助求职者找到完美的工作文化。
组织文化有无穷无尽的变化和怪癖。一个组织可能有随意的沟通规范,但等级森严,而另一个组织有正式的社会规范,但强调团队合作和扁平的组织结构。
同样,求职者对工作环境的偏好也各不相同。他们可能更喜欢创业文化、扁平化组织、强大的社交环境、团队环境,或者独立工作。
为了确保候选人保持参与和致力于他们所提供的工作,人才公司正在依靠人工智能来匹配求职者的组织文化偏好和与之一致的公司。虽然许多人才匹配平台是供雇主使用的,但 Fortay 为求职者提供了一个测试,他们可以通过这个测试来确定他们最有可能在什么样的公司文化中茁壮成长。
一旦完成一项测验,Fortay 的人工智能算法就会开始汇编相关公司的列表。求职者随后会在收件箱中收到一份公司列表,并配有一个按钮,一旦按下,就会引导他们申请这些公司的空缺职位。
- 人工智能确保招聘偏见不会制造障碍。
研究表明,即使我们无意,人类也会无意识地产生偏见。因此,招聘偏见会给求职者制造障碍。“如果我们假设人们有偏见…那么我们知道无论我们有什么数据集都会有偏见,因为数据集是基于过去发生的人类决策,”Ken Lazarus 解释说。
因此,他说,有经验的数据科学家编程算法,以消除招聘偏见,从而防止算法污染。好消息是,给定一个良好规模的数据集,当数据科学家依靠人工智能时,他们可以减少偏见的影响,以获得更好的未来工作。
例如,Ken 知道男性或女性招聘人员推荐与他们性别相匹配的求职者的几率要高 25%。因此,当一名男性招聘人员推荐四名男性候选人时,Scout Exchange 的数据科学家删除了其中一人,以消除结果中的偏见。然后,他们将这个公式编程到他们的人才匹配算法中,以防止偏见被纳入他们未来的预测中。
一旦被编程到人工智能驱动的算法中,这个公式就可以影响数百万次人才匹配活动。反过来,由于雇主收到的求职者名单不那么有偏见,求职者在他们的行业和主要雇主面前享有公平的代表权。
- 人工智能有助于将内部员工与发展机会相匹配。
到目前为止,我们已经了解了人工智能如何在幕后帮助求职者求职。但是,即使在候选人被雇用后,AI 仍继续工作,以确保他们保留来之不易的工作,并从中获得成功的职业生涯。
例如,人工智能驱动的智能人群解决方案允许品牌监控员工的表现,以确定员工可以发展新技能的领域。然后,它设计了专门的培训项目,这样员工就能在当前的岗位上取得成功,并有更多的晋升机会。
此外,它还会监控员工,找出他们的优势,然后将工作分配给那些绩效评分最高的人。这意味着人工智能在幕后工作,挑选出最符合可用内部职位的员工,然后将他们推荐给这些职位的经理,以做出晋升决定。
最终,诚实让人工智能能够在求职者旅程的各个阶段与他们同行。 劳拉痛苦地认识到接受每一次面试都可能是一个错误。不相关的技能组合、不一致的文化偏好、招聘偏见和不良的在职成功倾向会导致可怕的面试和更糟糕的工作经历。
但是,人工智能显然让求职者的旅程变得更容易。此外,还有更多好消息:从现在开始,情况只会越来越好。不断增长的数据集和持续的人工智能学习意味着像 WorkFusion,Fortay 和 Scout Exchange 这样的人工智能平台只会变得更加智能和高效。
肯·拉扎勒斯说,求职者利用人工智能现在和未来所能提供的一切的诀窍是诚实。确保简历准确符合工作表现和技能。这样做,你就输入了人工智能数据集,为所有求职者在就业旅程的所有阶段提供了更光明的未来。
强化学习的未来
第 2 部分:比较和应用
如果你还没有读过强化学习入门,先回去看看这里。那篇文章将为你提供强化学习的关键概念。然后你就可以充分比较不同类型的机器学习了。
将强化学习与其他机器学习类型进行比较
A high-level breakdown of the three major categories of machine learning
你可能听说过其他类型的机器学习,例如:监督学习,非监督学习等。理解强化学习(RL)与它们有何不同,是把握机器学习前景的好方法。
监督学习
最容易掌握的 ML 类型是监督学习。监督学习是带有人类标签的学习。图像分类是一种监督学习。你有一个算法,根据标记的图像,系统可以将图像分类为一只猫或一只狗。该算法通过观察训练集进行学习,然后可以正确推断未知图像的主题。
监督学习问题的另一个好例子是回归问题。在回归问题中,你需要一组参数,并基于这些参数估计一个真实的、连续的值。例如,你可以获取一所房子的信息(房间数量、面积、窗户数量等。)并输出一个价格。我们知道很多房子的价值,可以将这些标记的例子输入到算法中。然后,当你把一栋新房子提交给系统时,它可以自己给出一个好的价格估计。这些问题很容易被框定为监督学习问题。
无监督学习
Using unsupervised learning, we can find the underlying patterns in data
另一方面,我们有无监督学习:没有标签的学习。一个很好的例子是获取用户购买数据,并将您的客户按照相似的购买模式分组。你的算法进行分组,你可以向特定类别的人推荐产品。我们不告诉算法标签或类别名称是什么,我们只是简单地给它一堆数据,它就根据数据中的模式创建组。无监督学习也广泛用于可视化大量复杂数据。这使得人们更容易看到一幅图像中的所有信息。
强化学习
强化学习经常被描述为介于监督学习和非监督学习之间。有时间延迟标签(奖励),当算法学习在环境中交互时,它会得到这些标签。算法是基于学习问题的措辞来学习的。这正是强化学习擅长实时决策、视频游戏人工智能、机器人导航和其他复杂任务的原因。关键是让系统能够根据环境的当前状态,理解哪些决策是好的,哪些是坏的。
应用这些概念
在上一篇文章中,我们介绍了强化学习的基本概念。这里以一个具体例子的形式总结了我们到目前为止所涉及的内容:
想象一只老鼠在一个基本的迷宫里。鼠标将是我们的代理。首先,我们将检查代理需要的东西:
- 目标:老鼠的目标是获得最多的奶酪
- 动作:鼠标可以向四个主要方向移动
- 感官:老鼠可以观察到它所处的环境的状态(开始,什么都没有,小奶酪,两个小奶酪,大奶酪,死亡)。对于我们这个简单的例子,仅仅对环境的状态有一个简单的了解就足够了。
Our simple mouse agent exploring for cheese!
此外,让我们看看问题的子元素,看看它们如何符合标准:
- 策略:在任何给定的状态下,我们的鼠标会采取四个动作中的哪一个?
- 奖励信号:阳性(获得了一个奶酪;但是多大的奶酪呢?)、中立(未达到任何状态)或消极(死亡状态已结束我们的游戏)。
- 价值函数:这是我们的鼠标动态构建和维护的东西。它可以在一次迭代的过程中进行调整,也可以在迷宫中多次运行。
- 模型:如果我们让我们的老鼠知道它周围环境的大小,它就能在记忆中储存一个模型。我们可以将世界表示为一个 2D 网格(数组),当鼠标穿过并观察实际环境时,允许它在给定的网格方块中填入是积极的、消极的还是没有奖励
让我们剖析一个代理可能采用的基本贪婪策略:
策略之一是 Q 表策略。Q-table 代表“质量表”。这是一个动作和状态的表格,以及与它们相关的奖励。我们可以采用一个基本策略,当我们遇到一个状态时,选择能给我们的代理人最大回报的行动。当我们的代理不知道什么会给出最大的回报时,随机选择一个行动。
A basic Q-table where the rows are potential states and the columns are the actions our agent can take
一开始,我们老鼠的桌子是空的。它什么都不知道。例如,它随机选择策略,可能向右移动并得到少量奶酪。很好,我们的代理收到了奖励信号!该表得到相应的更新,我们的代理将继续选择行动,直到用尽所有的可能性或已经死亡。
Hurrah! Our mouse gets some cheese!
你可能已经看到一个问题出现了:当我们重新开始我们的迷宫时,我们的代理人总是倾向于向小奶酪移动,从不选择未知的替代品。这被称为探索与开发的权衡,但是我们一会儿会回到这个问题上来。
Updating our Q-table for the reward that we have received.
现在我们已经看到了这些组件是如何协同工作的,让我们深入了解一下我们希望解决的任何强化学习问题所需要的一些东西。
用任务组织强化学习
强化学习应用程序需要考虑的一个主要因素是任务的结构。这些通常分为两类:插曲式或连续式。
1.偶发性任务
情节任务有不同的开始和结束状态。我们可以保存这些“情节”,并对它们进行“离线”训练一个主要的例子就是我们上一篇文章中的马里奥关卡。
2.连续任务
连续的任务没有终点。这可能就像一个决策算法,预测某人何时应该在股市中买入或卖出股票。这总是随着许多环境因素而不断发展变化。没有明确的开始和停止状态可以让我们轻松地截取一集进行训练,因为害怕让我们的算法过于接近一小段时间。
股票市场总是在变化。将它分割成几段就是忽略了它如何演变的相关连续性
我们如何制定我们的代理人的目标和奖励是由我们期望完成的任务类型决定的,因为它可以改变我们学习的性质(我们将在接下来谈到这一点)。
何时学习
时间对于代理如何执行任务至关重要。也许代理应该在游戏的每一帧都学习,或者代理可以一集一集地学习。我们可以采用蒙特卡洛策略,在整个学习过程中循环,然后在每次迭代中变得更好、更聪明。这些选项有不同的权衡,可能可行也可能不可行,这取决于我们的代理试图完成的任务类型(连续任务可能永远不会使用蒙特卡罗策略,因为它需要循环一集进行训练,这对于连续任务来说甚至是不存在的!).
探索与开发
当代理探索一个环境时,很快就会遇到探索与利用的权衡。如果代理人很早就发现,如果它做了简单的事情,它将获得少量的奖励,它可能会一遍又一遍地继续做那个简单的事情,随着时间的推移积累少量的奖励。如果它探索未知,并试图发现新的情况,它可能会获得更大的回报。
用人类的话来说,这就像问这样一个问题:你会去你经常去的那家你知道会很好的餐馆吗?或者你会冒险进入未知的领域,去一个你以前从未尝试过的地方看看,那可能会非常棒。
If you ask me, the new place looks pretty fantastic
代理的策略是如何构建的,将决定它将学习利用什么样的动作,以及何时决定探索。早期探索可能会产生更高的长期回报,然而,过度关注探索可能会导致我们非常了解的状态下的次优行动。这导致你最终得到的奖励比我们本可以得到的要少。
在我看来,探索与开发的权衡仍然是一个悬而未决的问题,也是一个特别有趣的研究领域。
方法
这给我们带来了制作强化学习应用程序的另一个重要因素。是基于价值还是基于政策?
基于政策的方法
我们之前提到过,代理的策略是它如何根据环境的当前状态来决定采取什么行动。具有基于策略的学习方法的 RL 代理将尝试并学习具有决策结构的复杂策略,该决策结构允许它在任何给定情况下尝试并采取最佳行动。
基于价值的方法
另一方面,我们有基于价值的 RL 应用。价值函数是我们的 RL 算法将累积的长期回报的当前估计。如果我们有一个基于价值的代理,它将专注于基于该功能的优化。这包括专注于学习对长期回报越来越好的估计,以及采取贪婪的行动在任何给定时间最大化该功能。在很多方面,我们可以认为这是一个代理学习采取行动的隐含贪婪策略。
演员-评论家方法
基于值的算法和基于策略的算法之间的决定是决定强化学习算法看起来像什么的重要决定。这两条思路的交叉部分被称为演员-评论家方法。它的特点是跟踪估计的未来回报收入(我们的价值函数)以及学习新的、更复杂的政策,以使我们的代理在更长的时间范围内获得更大的回报。由于该算法现在同时优化两个函数,它很快变成一个更难的问题。
在演员-评论家领域有很多焦点,并且已经产生了许多很酷的算法。谷歌的异步优势演员-评论家(A3C)是一个很酷的演员-评论家算法的主要例子,已经显示了很多好的结果。
结论
在过去的两篇文章中,我们讨论了基本的术语以及一些围绕强化学习问题的更复杂的概念。希望有了这两个组件,你会觉得你已经很好地掌握了什么是强化学习,以及使用它编写算法的一些考虑因素。
现在,你可能对 RL 感到非常兴奋。您可能想知道如何在 RL 系统上开始工作。在下一篇文章中,我们将深入研究 RL 的优势,主要的开放性问题是什么,以及一些关于学习自己编写 RL 算法的资源!
原载于 2018 年 8 月 14 日recast . ai。
强化学习的未来——第一部分
想象一个世界,每个计算机系统都是根据你自己的个性定制的。它学习你如何交流和你希望如何被交流的细微差别。与计算机系统的交互变得比以往任何时候都更加直观,技术素养直线上升。在强化学习成为常态的未来,这些是你可以看到的潜在结果。
在这篇文章中,我们将分解强化学习,剖析一些组成强化学习系统的组件。
强化学习的高级概述
如果你以前从未听说过强化学习(RL ),不要着急!这个概念非常简单。在一个非常高的层次上,强化学习只是一个代理学习如何根据它从环境中收到的反馈信号与环境进行交互。这使得它不同于其他机器学习方法,在其他机器学习方法中,学习代理可能在训练期间看到正确的答案。在强化学习中,我们可以把我们的学习代理想象成获得一个等级或分数,让它知道自己的表现。
让我们用一个电子游戏来描述这个想法。假设我们有一个玩马里奥游戏的电脑程序。它学会控制角色,以变化的屏幕形式接收来自环境的反馈。基于我们算法的成功(或失败),它可以学习与环境互动,并通过使用它收到的反馈来改进。
To learn about the environment, we need to explore! The only way we can find out that Goombas are bad and power-ups are good is through trail-and-error and feedback.
强化学习试图模仿人类或其他智能生物与新环境互动的方式:试错法。它诞生于计算机科学、心理学、神经科学、数学等许多领域的研究成果。尽管今天在工业中很少见到 RL,但它的潜在影响是巨大的。
Reinforcement learning really is the culmination of many fields and has a rich history in optimization and behavioral psychology.
这种潜力就是我要为你揭示的。
马里奥游戏强化学习词汇
我们已经提到了 RL 玩视频游戏的经典例子。现在,让我们继续使用我们的马里奥例子,同时我们更深入地挖掘这个想法和围绕这个概念的词汇。
经纪人:马里奥
首先,我们有我们的代理人。我们的代理是我们的算法和程序。它是操作的大脑。它将与我们的环境相互作用。在这种情况下,我们的经纪人是马里奥,他将发号施令。
Our agent: Mario
环境:游戏级别
代理存在于环境范围内。环境就是我们玩的马里奥的水平。是屏幕上的敌人和积木组成了这个世界。时间在流逝,分数在上升(或者我们希望如此!).我们的代理人的目标是以一种获得回报的方式与环境互动。
Our environment: a simple level
动作:跳,蹲下,向前移动
什么是奖励,我们的代理如何获得奖励?我们的特工必须与环境互动。它可以通过从它可能采取的潜在动作列表中选择一个动作来做到这一点。也许我们的代理马里奥决定向上跳。或者向左或向右移动。也许他们有火球术,所以我们的代理人决定发射一个。关键是,这些行动中的每一个都将改变环境,并导致变化。我们的代理可以观察到这种变化,将其作为反馈信号,并从中学习。
The interface a human might use to execute actions that affect the environment
状态:马里奥+动作+环境=状态
我们的代理观察到的这些变化是环境状态的变化。我们的代理观察到的新状态可能会产生一个“奖励”信号。将代理采取的行动、状态的变化以及从状态变化中获得的潜在回报结合在一起,代理开始为他们正在探索的环境建立工作模型。
The state holds all the information about what’s going on in the environment from what we can observe. Things like where our character is, our current score, and enemies on the screen all play into what the state of our environment is currently.
奖励:点数+生存
如果代理人知道当它跳到并落在一个敌人身上时,它会得到一点提升,并且不会再被这个敌人杀死,这是一件值得学习的好事情!它还可能知道,如果马里奥掉进了一个洞里,游戏就结束了,以后就没有机会再得分或赢得关卡了。这些是代理可以随着时间学习的东西,它与环境的交互越多,它学习的就越多。
In Mario, a good way to measure reward might be the score!
这包含了对强化学习问题中所有主要组成部分的介绍。在这一部分要记住的重要的事情是代理人、环境、行动、状态和奖励,并尝试在你的头脑中有一个这些需要的工作定义。
如果你是一个视觉学习者,这张图片很好地将这些结合在一起。
All of the components coming together to make up how an agent learns from its environment!
它是如何工作的?
既然我们理解了一些基本词汇,我们可以应用它来学习代理如何操作。一个代理人如何决定采取行动来获得最大的回报?
我们需要分析理解两个主要的流:RL 代理需求及其子元素。
强化学习需求
RL 代理必须学会在充满不确定性的环境中决定什么是好的行动。反馈作为延时的奖励信号被接收,作为观察到的状态变化和可以从中计算出的奖励。代理人必须能够探索这种不确定性,并对给予奖励的原因进行推理。要做到这一点,代理需要有三个简单的东西:行动、目标和感觉。
行动
动作是代理在任何给定时刻可以对环境进行的操作列表。通过执行动作,代理影响其环境并改变其状态。如果不能做到这一点,一个主体就永远无法积极地影响国家,从其行动如何积极或消极地影响环境中获得任何可解释的回报,甚至无法学会在未来采取更好的行动。
A list of actions someone might take with an Atari controller.
目标
目标是我们定义奖励信号的方式。我们在电子游戏中会根据分数来奖励吗?完成一个级别?什么是好的和坏的行为?这些是我们在 RL 环境中定义目标时必须考虑的问题。这就是我们激励代理完成任务的方式。
A simple setup of a goal. How can one get from start to finish?
感觉
感官是智能体用来观察环境的东西。在视频游戏环境中,使用计算机视觉设置中的技术来观察屏幕上的对象以及当我们的代理采取行动时它们如何变化可能是有用的。也许我们用光学字符识别来观察一个点值。关键是,如果一个代理不能感知环境,他们就不能思考他们的行为如何影响环境。因此,我们需要感官来监控我们与之互动的环境。
强化学习系统的子元素
现在,我们可以过渡到 RL 系统的子元素:政策、奖励信号、价值函数和环境的最优模型。
该政策
保单是我们 RL 代理的核心。这是我们的代理在当前环境状态下的行为方式。这是我们的代理人将采取的行动。在生物学中,我们可能会将一项政策视为一个有机体如何根据它所接受的刺激做出反应。我们的代理观察环境的状态,策略是它已经学会要做的。好的政策会产生积极的结果。
Our policy will dictate what an agent will do given a state of the environment. We can see here a policy might be that given a certain tile, our agent moves in a certain direction.
奖励信号
奖励信号是我们衡量代理成功的标准。这是我们成功实现目标的量化指标。奖励信号可以是积极的,也可以是消极的,这样我们的代理人就可以衡量一个行为是好的、坏的还是中性的。这些可以是视频游戏中的分值,也可以是我们的特工是否还活着。关键是,我们的代理人接受这些奖励信号,衡量当前目标的执行情况,并根据这一反馈制定政策,以便进一步努力改变环境,使未来可能获得的奖励最大化。
We can think of this as the hidden reward mapping from the previous goal image. Only by exploring the environment the agent can learn that stepping on the goal tile yields a reward of 1!
价值函数
我们可以把奖励信号看作是一个行为好坏的直接指示器。然而,强化学习不仅仅是直接的积极或消极的结果。它是关于长期规划,以最大限度地成功完成一项任务。为了对这种长期性能进行建模,我们引入了一个叫做价值函数的概念。价值函数是对我们的代理取得长期成功的可能性的估计。这是很难估计和衡量的,但它是我们的 RL 问题的最关键的组成部分之一!在一个不确定的环境中,我们的代理将不断地修改他们对价值的估计,学习更好地制定政策和行动,以接管长序列的行动和状态。
A visualization of a value function being shaped by an agent. As it becomes more and more certain about its potential long term reward given its state, it can come up with solutions to this challenge.
环境的最佳模型
最后,我们的 RL 系统可以模拟环境。我说可能是因为不是所有的 RL 代理都会模拟一个环境。一些代理人只是通过试错来学习,通过良好的价值函数和策略组合来构建某种程度上隐含的环境模型。其他代理可以显式地创建环境的内部模型,允许代理基于它希望直接采取的行动来预测结果状态和奖励。这似乎是一个非常好的方法,但是在高度复杂的环境中,建立这样一个内部模型是非常困难的,所以代理通常不会选择这种策略。
As an agent explores an environment, they could build a 3D interpretation of the world around them to help them reason about the actions they might take in the future.
摘要
有了这些基本概念,我们可以开始看到这样的未来,计算机系统根据我们的行动和反应进行学习,专门针对我们的个性进行调整。在我们上面例子中的马里奥代理中,我们可以想象未来的计算机系统会像马里奥角色阅读环境一样阅读我们的动作和反应。它得到的回报信号越多,我们就越快乐,我们就能越快实现目标。很容易看出这种未来的结果是如何在我们的能力范围之内。
即将推出:第 2 部分和第 3 部分
所有这些综合起来给了我们一个增强系统如何执行和操作的基本概述。这篇高水平的初级读本将有助于我们的第 2 部分文章,其中我们讨论了强化学习与其他类型的机器学习的比较,以及我们在制定强化学习问题时考虑的一些因素,以及我们的第 3 部分文章,其中我们查看了强化学习领域的一些最新成就和开放的研究问题。
观看马里奥游戏!看看你是否能识别强化学习场景中需要的所有元素。
如果你喜欢读这篇文章,给我留言或者给我的 GoFundMe 捐款来帮助我继续我的 ML 研究!
原载于 2018 年 8 月 8 日recast . ai。
Fitbit 的游戏化
API 如何提供下一层次的培训
任何人都可以在精品店寻找时尚,在博物馆寻找历史。富有创造力的探险家在五金店寻找历史,在机场寻找时尚”——罗伯特·威德
项目灵感
你可能听说过这个词,也可能没有,但你很可能经历过。
Gamification
是游戏设计元素和游戏原则在非游戏环境中的应用。这个想法是,如果你使用游戏的元素,比如将规则和奖励链接到一个反馈系统中,你可以使(几乎)任何活动变得激励和有趣。
Gamification
是电子学习背后的概念。我记得在小学时,所有的学生都想在电脑课上玩俄勒冈小径 T21。我还记得另一个游戏,你必须在东西落地之前解决数学问题。好吧,也许这不是对gamification
最激动人心的介绍,但我仍然记得。
在我职业生涯的某个时候,我厌倦了使用nano
,决定尝试学习Vim
。
就在那时,我发现了两个非常有趣的gamification
的例子:
[Vim Adventures](https://vim-adventures.com/)
有点像Zelda
中的Gameboy
,你必须在环境中移动并解开谜语——除了用Vim
命令!你可以在这里看它在 Twitch 上播放。
[shortcutFoo](https://www.shortcutfoo.com/)
教你Vim
、Emacs
、Command Line
、Regex
、*等快捷键。*通过间歇训练,本质上是间隔重复。这有助于你更有效地记忆快捷方式。
今天,我喜欢在像 DuoLingo 和 DataCamp 这样的平台上进行电子教学。
我最近也开始参加一个 Kaggle 竞赛,“PUBG 完成位置预测”。Kaggle 是谷歌为数据科学爱好者开设的一个场所,他们可以使用机器学习来解决预测分析问题,以获得现金和影响力。类似象棋还有所谓的 Kaggle 特级大师。
探索
我们的实验室研究围产期对心理健康结果的早期逆境的生物嵌入的影响。我们将遗传学、表观遗传学和流行病学方法结合起来,以确定哪些孕妇的后代可能存在不良精神健康后果的潜在风险。
我的主管向我提出挑战;从 200 个 Fitbits 获取生物特征数据的可行性有多大?
所以我给自己买了一个 Fitbit Charge2 健身追踪器,然后去了健身房!
在某个时刻,我想我们都意识到这个项目将是一个大工程。也许R
并不真正打算从 API 服务中进行大规模实时数据管理。这对于静态文件或者静态端点来说是很棒的,但是如果你和多个参与者一起工作,像 Fitabase 这样的专用解决方案可能是最好的——或者他们是这么宣称的。
尽管如此,我还是想在R
尝试一些很酷的新事物,比如用blogdown
制作个人网站,用Rokemon
使用gganimate
,用httr
访问 fitbit API,以及用一些自定义 CSS/HTML 添加背景图片。有可能有更好的方法来缩短我的学习曲线吗——我认为没有。
以下是我对**R**
****gamification**
的网络学习尝试。**
我使用了[blogdown](https://bookdown.org/yihui/blogdown/)
包,允许我以 R Markdown 文档的形式写博客,将一切编织成一个漂亮整洁的静态网站,我可以在网上推送。这是一个学习 pandoc、Hugo、隐藏在服务器端代码下的 CSS/HTML 的好机会。我决定继续使用Hugo的学术主题,从 Fitbit API 中获取尽可能多的数据,对其进行清理,然后进行一些探索性的数据分析。在这个过程中,我生成了一些很酷的动画精灵,并使用视频游戏启发的可视化效果。
设置 Fitbit 开发人员帐户
Fitbit 使用OAuth 2.0Access令牌向 Fitbit API 发出 HTTP 请求。您需要设置一个帐户来使用 API,并在R
中包含您的令牌。我不会去阅读 FITBIT 开发帮助部分,而是让读者在这里找到更好更简洁的说明。
现在你有一个帐户,我们准备在R
做事情。
设置您的令牌:
# You Found A Secret Area!
token = "yourToken"
使用fitbitr
包
我以前从未提出过HTTP
请求,尽管这个过程在这里有正式记录,但它可能会让人不知所措。因此,我最初求助于使用一个名为fitbitr
的包来访问 R API。
不幸的是,这将限制我只能访问一些基本的用户信息、heart rate
和step count
数据。
获取基本用户信息
这个包中的第一个函数向Get Profile
资源 URL 发送一个GET
请求。
# Extracting Resources# Get userInfo
user_info <- fitbitr::getUserInfo(token)# Hailing a Chocobo!# What is my stride length in meters?
strideLengthWalking <- user_info$strideLengthWalking
我的步幅是 68.5。
步幅是从脚跟到脚跟测量的,它决定了你每走一步走多远。平均来说,男人走路的步幅是 2.5 英尺,也就是 30 英寸,而女人的平均步幅是 2.2 英尺,也就是 26.4 英寸,根据这个 报道 。
# Hitting 80 MPH# What is my running stride length
strideLengthRunning <- user_info$strideLengthRunning
我跑步的步幅是 105.5。
默认情况下,Fitbit 使用您的 *sex*
和 *height*
来测量您的步幅,这可能会不准确。
# Looking for the fourth chaos emerald # What is my average daily steps?
averageDailySteps <- user_info$averageDailySteps
我每天的平均步数是 14214 步。
考虑到每天推荐的步数是 10,000,我认为这是可以接受的。也就是说,总有改进的空间。
使用fitbitr
包获取心率和脚步
我要为一个非常初步的 EDA 获取一周的数据。
# Smashing buttonsdays <- c("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday")monday_heart <- getTimeSeries(token, type = "heart", activityDetail = "1min", date = "2018-08-20", startTime = "00:00", endTime = "23:59")
monday_heart %<>% mutate(date = "2018-08-20")
monday_steps <- getTimeSeries(token, type = "steps", activityDetail = "1min", date = "2018-08-20")
monday_steps %<>% mutate(date = "2018-08-20")
monday <- monday_heart %>% full_join(monday_steps)
monday %<>% mutate(week_date = "Monday")
monday %<>% mutate(day_of_week = "1")tuesday_heart <- getTimeSeries(token, type = "heart", activityDetail = "1min", date = "2018-08-21")
tuesday_heart %<>% mutate(date = "2018-08-21")
tuesday_steps <- getTimeSeries(token, type = "steps", activityDetail = "1min", date = "2018-08-21")
tuesday_steps %<>% mutate(date = "2018-08-21")
tuesday <- tuesday_heart %>% full_join(tuesday_steps)
tuesday %<>% mutate(week_date = "Tuesday")
tuesday %<>% mutate(day_of_week = "2")wednesday_heart <- getTimeSeries(token, type = "heart", activityDetail = "1min", date = "2018-08-22")
wednesday_heart %<>% mutate(date = "2018-08-22")
wednesday_steps <- getTimeSeries(token, type = "steps", activityDetail = "1min", date = "2018-08-22")
wednesday_steps %<>% mutate(date = "2018-08-22")
wednesday <- wednesday_heart %>% full_join(wednesday_steps)
wednesday %<>% mutate(week_date = "Wednesday")
wednesday %<>% mutate(day_of_week = "3")thursday_heart <- getTimeSeries(token, type = "heart", activityDetail = "1min", date = "2018-08-23")
thursday_heart %<>% mutate(date = "2018-08-23")
thursday_steps <- getTimeSeries(token, type = "steps", activityDetail = "1min", date = "2018-08-23")
thursday_steps %<>% mutate(date = "2018-08-23")
thursday <- thursday_heart %>% full_join(thursday_steps)
thursday %<>% mutate(week_date = "Thursday")
thursday %<>% mutate(day_of_week = "4")friday_heart <- getTimeSeries(token, type = "heart", activityDetail = "1min", date = "2018-08-24")
friday_heart %<>% mutate(date = "2018-08-24")
friday_steps <- getTimeSeries(token, type = "steps", activityDetail = "1min", date = "2018-08-24")
friday_steps %<>% mutate(date = "2018-08-24")
friday <- friday_heart %>% full_join(friday_steps)
friday %<>% mutate(week_date = "Friday")
friday %<>% mutate(day_of_week = "5")saturday_heart <- getTimeSeries(token, type = "heart", activityDetail = "1min", date = "2018-08-24")
saturday_heart %<>% mutate(date = "2018-08-24")
saturday_steps <- getTimeSeries(token, type = "steps", activityDetail = "1min", date = "2018-08-24")
saturday_steps %<>% mutate(date = "2018-08-24")
saturday <- saturday_heart %>% full_join(saturday_steps)
saturday %<>% mutate(week_date = "Saturday")
saturday %<>% mutate(day_of_week = "6")week <- monday %>% bind_rows(tuesday) %>% bind_rows(wednesday) %>% bind_rows(thursday) %>% bind_rows(friday) %>% bind_rows(saturday)
week$date <- as.Date(week$date)
汇总统计数据
# Opening pod bay doorsweek %>%
group_by(type) %>%
summarise(
total = sum(value),
minimum = min(value),
mean = mean(value),
median = median(value),
maximum = max(value),
max_time = max(time)
) %>%
knitr::kable(digits = 3) %>%
kable_styling(full_width = F)
探索性数据分析
因为这是一个关于gamification
的帖子,我决定用我的探索性数据可视化做一些有趣的事情。我想使用Rokemon
包,它允许我将ggplot2
(和ggplot2
扩展)的主题设置为Game Boy
和Game Boy Advance
主题!方便的时候,我会用cowplot
组合剧情。
我们来快速看一下heart rate
和step count
的关系和分布。
# Doing the thing...g <- week %>%
spread(type, value) %>%
rename(hear_rate = "heart rate") %>%
na.omit() %>%
ggplot(aes(steps, hear_rate)) + geom_point() + geom_smooth(method="lm", se=F, colour = "#DE7243") gb <- g + theme_gameboy()
gba <- g + theme_gba()plot_grid(gb, gba, labels = c("", ""), align = "h")
或者,我们可以通过ggExtra
包中的ggMarginal()
函数将边际密度图添加到散点图中,从而更好地查看数据。
每周趋势
让我们快速看一下连续变量的分布,以获得比平均值和中位数更好的想法。
# Loading..... Wait, what else were you expecting?annotations_steps <- data_frame(
x = c(45, 100, 165),
y = c(0.01, 0.01, 0.01),
label = c('walking pace', 'brisk walking pace', 'running pace'),
type = c('steps', 'steps', 'steps')
)g <- week %>%
ggplot(aes(value)) +
geom_density(fill = "#DE7243") +
geom_text(data = annotations_steps, aes(x = x, y = y, label = label), angle = -30, hjust = 1) +
facet_grid(.~type, scales = 'free_x') +
labs(title = 'Heart Rate and Steps-per-minute over two months',
subtitle = 'Data gathered from Fitbit Charge2')g + theme_gameboy()
g + theme_gba()
****
Heart rate
有点右偏,可能是睡眠和久坐工作的原因。同样,对于step count
你可以看到,当我滑板上班时,在brisk walking pace
下面只有一个小凸起。
锻炼模式
这个星期我没有健身,所以我想我至少应该在上班的路上看看。下图显示蓝色为heart rate/min
,橙色为steps/min
的编号。
# You are carrying too much to be able to runbetween_six_nine <- function(time) time > 7*60*60 & time < 10*60*60is_weekday <- function(day_of_week) day_of_week %in% 1:6week$week_date_f <- factor(week$week_date, levels=c("Monday","Tuesday","Wednesday", "Thursday", "Friday", "Saturday"))g <- week %>%
filter(between_six_nine(time) & is_weekday(day_of_week)) %>%
spread(type, value) %>%
ggplot(aes(x = time)) +
geom_bar(aes(y = steps), color = '#DE7243', alpha = 0.3, stat = 'identity') +
geom_line(aes(y = `heart rate`), color = '#E3F24D', size = 0.8) +
facet_grid(~week_date_f) +
scale_x_continuous(breaks=c(27000, 30000, 33000, 36000), labels=c("7am", "8am", "9am", "10am"))g + theme_gameboy()
g + theme_gba()
****
自从我每天早上滑滑板去上班后,我的活动整个星期都差不多一样。
最活跃时间
# 60% of the time, it loads ALL the timestep_counts <- week %>%
filter(type == 'steps') %>%
group_by(day_of_week) %>%
summarise(
type = last(type),
avg_num_steps = sprintf('avg num steps: %3.0f', sum(value)/52)
)g <- week %>%
ggplot(aes(x= value, y = fct_rev(factor(day_of_week)))) +
geom_density_ridges(scale = 2.5, fill = "#DE7243") +
geom_text(data = step_counts, nudge_y = 0.15, hjust = 0,
aes(x = 85, y = fct_rev(factor(day_of_week)), label = avg_num_steps)) +
scale_y_discrete(breaks=1:6, labels = c("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday")) +
facet_grid(.~type, scales = "free") +
labs(x = '', y = "Day of the Week") g + theme_gameboy()
g + theme_gba()
****
每分钟的步数分布相当稳定,因为我说过我没有锻炼;这可能反映了我拖着脚步去喝茶。
看起来周一是我心跳加速最多的一天,双峰高峰可能是我四处寻找出租物业的时候。
用httr
包直接访问 Fitbit API
最终,我找到了一个由 obrl-soil 撰写的优秀的教程,它向我介绍了httr
包,并给了我阅读 Fitbit DEV web API 参考所需的信心。现在我能够访问更多的数据来源。
有哪些数据可用?
Fitbit API 提供了哪些数据的简要概述:
# Your Boko Club is badly damaged# make a kable table for data you can access from Fitbit API
dt01 <- data.frame(Scope = c("activity",
"heartrate",
"location",
"nutrition",
"profile",
"settings",
"sleep",
"social",
"weight"),
Description = c("The activity scope includes activity data and exercise log related features, such as steps, distance, calories burned, and active minutes",
"The heartrate scope includes the continuous heart rate data and related analysis",
"The location scope includes the GPS and other location data",
"The nutrition scope includes calorie consumption and nutrition related features, such as food/water logging, goals, and plans",
"The profile scope is the basic user information",
"The settings scope includes user account and device settings, such as alarms",
"The sleep scope includes sleep logs and related sleep analysis",
"The social scope includes friend-related features, such as friend list, invitations, and leaderboard",
"The weight scope includes weight and related information, such as body mass index, body fat percentage, and goals")
)dt01 %>%
kable("html") %>%
kable_styling(full_width = F) %>%
column_spec(1, bold = T, border_right = T) %>%
column_spec(2, width = "30em", background = "#E3F24D")
测量单位是什么?
# Loading Cutscenes You Can't Skip# make a Kable table or measurement information
dt03 <- data.frame(unitType = c("duration",
"distance",
"elevation",
"height",
"weight",
"body measurements",
"liquids",
"blood glucose"),
unit = c("milliseconds",
"kilometers",
"meters",
"centimeters",
"kilograms",
"centimeters",
"milliliters",
"millimoles per liter"))
dt03 %>%
kable("html") %>%
kable_styling(full_width = F) %>%
column_spec(1, bold = T, border_right = T) %>%
column_spec(2, width = "30em", background = "#E3F24D")
定义一个将json
列表转换成数据帧的函数。
# Inserting last-minute subroutines into program...# json-as-list to dataframe (for simple cases without nesting!)
jsonlist_to_df <- function(data = NULL) {
purrr::transpose(data) %>%
purrr::map(., unlist) %>%
as_tibble(., stringsAsFactors = FALSE)
}
调查我的 10 公里跑
GET
请求检索我的 10km 跑步的每分钟心率数据。
# Preparing for the mini-bossget_workout <- function(date = NULL, start_time = NULL, end_time = NULL,
token = Sys.getenv('FITB_AUTH')) {
GET(url =
paste0('https://api.fitbit.com/1/user/-/activities/heart/date/',
date, '/1d/1min/time/', start_time, '/', end_time, '.json'),
add_headers(Authorization = paste0("Bearer ", token)))
}# Get the workout for my 10Km run
got_workout <- get_workout(date = '2018-10-21', start_time = '09:29', end_time = '10:24')workout <- content(got_workout)# summaryworkout[['activities-heart']][[1]][['heartRateZones']] <- jsonlist_to_df(workout[['activities-heart']][[1]][['heartRateZones']])# the dataset
workout[['activities-heart-intraday']][['dataset']] <- jsonlist_to_df(workout[['activities-heart-intraday']][['dataset']])# format the time
workout$`activities-heart-intraday`$dataset$time <- as.POSIXlt(workout$`activities-heart-intraday`$dataset$time, format = '%H:%M:%S')
lubridate::date(workout$`activities-heart-intraday`$dataset$time) <- '2018-10-21'# find time zone
# grep("Canada", OlsonNames(), value=TRUE)
lubridate::tz(workout$`activities-heart-intraday`$dataset$time) <- 'Canada/Eastern'
让我们来看看我的 10 公里跑的总结:
# Farming Hell Cowsworkout$`activities-heart`[[1]]$heartRateZones %>% kable() %>% kable_styling(full_width = F)
obrl-soil 使用的是MyZone Efforts Points
【MEPS】,它是以每分钟最大心率的百分比计算的。它衡量的是投入的努力——分数越多越好。另一个gamification
的例子。
# Looting a chestmeps_max <- function(age = NULL) { 207 - (0.7 * age) }
我的是 186。
现在,我们创建一个包含 4 个心率范围的表格,显示下限和上限,并使用上面的mutate()
函数计算我的最大心率(包含下限和上限)。
# Taking the hobbits to Isengardmy_MEPS <- tribble(~MEPS, ~hr_range, ~hr_lo, ~hr_hi,
1, '50-59%', 0.50, 0.59,
2, '60-69%', 0.60, 0.69,
3, '70-79%', 0.70, 0.79,
4, '>=80', 0.80, 1.00) %>%
mutate(my_hr_low = floor(meps_max(30) * hr_lo),
my_hr_hi = ceiling(meps_max(30) * hr_hi))
my_MEPS## # A tibble: 4 x 6
## MEPS hr_range hr_lo hr_hi my_hr_low my_hr_hi
## <dbl> <chr> <dbl> <dbl> <dbl> <dbl>
## 1 1 50-59% 0.5 0.59 93 110
## 2 2 60-69% 0.6 0.69 111 129
## 3 3 70-79% 0.7 0.79 130 147
## 4 4 >=80 0.8 1 148 186
有了现在定义的方程,让我们来计算我的总 MEPS:
# Checkpoint!mep <- mutate(workout$`activities-heart-intraday`$dataset,
meps = case_when(value >= 146 ~ 4,
value >= 128 ~ 3,
value >= 109 ~ 2,
value >= 91 ~ 1,
TRUE ~ 0)) %>%
summarise("Total MEPS" = sum(meps))
哇是 216!
我不知道这到底是什么意思,但显然在 42 分钟的锻炼中最大可能的 MEPS 是 168,因为我在 54:35 跑完了 10 公里,我想这很好?
我想在我的下一次 10 公里跑中坚持 50 分钟,但我不确定我是否应该争取更高的peak
心率分钟数——我想我需要对此进行研究。
一晚每分钟的睡眠数据
让我们检查一下我昨晚的睡眠模式。
# Resting at Campfireget_sleep <- function(startDate = NULL, endDate = NULL, token = Sys.getenv('FITB_AUTH')){
GET(url = paste0('https://api.fitbit.com/1.2/user/-/sleep/date/', startDate, "/", endDate, '.json'),
add_headers(Authorization = paste0("Bearer ", token)))
}# make sure that there is data for those days otherwise it tosses an errorgot_sleep <- get_sleep(startDate = "2018-08-21", endDate = "2018-08-22")
sleep <- content(got_sleep)dateRange <- seq(as.Date("2018-08-21"), as.Date("2018-08-22"), "days")sleep_pattern <- NULL
for(j in 1:length(dateRange)){
sleep[['sleep']][[j]][['levels']][['data']] <- jsonlist_to_df(sleep[['sleep']][[j]][['levels']][['data']])
tmp <- sleep$sleep[[j]]$levels$`data`
sleep_pattern <- bind_rows(sleep_pattern, tmp)
}
好了,现在数据管理完成了,让我们来看看我的睡眠模式。
# Now entering... The Twilight Zoneg <- sleep_pattern %>% group_by(level, seconds) %>%
summarise() %>%
summarise(seconds = sum(seconds)) %>%
mutate(percentage = seconds/sum(seconds)) %>%
ggplot(aes(x = "", y = percentage, fill = c("S", "A", "R"))) +
geom_bar(width = 1, stat = "identity") +
theme(axis.text.y = element_blank(),
axis.text.x = element_blank(), axis.line = element_blank(), plot.caption = element_text(size = 5), plot.title = element_blank()) +
labs(fill = "class", x = NULL, y = NULL, title = "Sleep stages", caption = "A = Awake; R = Restless; S = Asleep") +
coord_polar(theta = "y", start = 0) +
scale_fill_manual(values = c("#FF3F3F", "#2BD1FC", "#BA90A6"))g + theme_gameboy()
g + theme_gba()
****
饼图可能不是显示这些数据的最佳方式。让我们用一个箱线图来形象化这个分布。
# Entering Cheat Codes!g <- ggplot(sleep_pattern, aes(y=log10(seconds), x=level)) +
geom_boxplot(color="#031300", fill='#152403') +
labs(x = "", title = 'Sleep patterns over a month',
subtitle = 'Data gathered from Fitbit Charge2') +
theme(legend.position = "none") g + theme_gameboy()
g + theme_gba()
****
一个更好的可视化分布的方法是使用覆盖原始数据点的小提琴图。
# Neglecting Sleep... g <- ggplot(sleep_pattern, aes(y=log10(seconds), x=level)) +
geom_violin(color="#031300", fill='#152403') +
geom_point() +
labs(x = "", title = 'Sleep patterns over a month',
subtitle = 'Data gathered from Fitbit Charge2') +
theme(legend.position = "none")g + theme_gameboy()
g + theme_gba()
****
获取 3 个月的日常活动模式
您可以从 Fitbit 活动和练习日志中为不同的时间段执行 API 请求,但是因为我只有几个月的时间,所以我将使用3m
时间段。
我还需要剔除未来的任何一天,否则它们会在数字中显示为0
卡路里。做EDA
的时候最好使用Sys.Date()
功能而不是硬编码日期,做一个闪亮的 app,或者参数化一个 [RMarkdown](https://resources.rstudio.com/rstudio-connect-2/parameterized-r-markdown-reports-with-rstudio-connect-aron-atkins)
文件。这样你就可以探索不同的时间段,而不会出现任何问题。
我不记得我是什么时候开始戴 Fitbit 的,但我们可以通过下面的代码来解决这个问题:
# ULTIMATE IS READY!# Query how many days since you've had fitbit for
inception <- user_info$memberSince
我从 2018 年 8 月 20 日开始使用 Fitbit。
让我们收集 2018 年 9 月 20 日至 11 月 6 日的数据。
# Catching them all!### Calories
get_calories <- function(baseDate = NULL, period = NULL, token = Sys.getenv('FITB_AUTH')){
GET(url = paste0('https://api.fitbit.com/1/user/-/activities/calories/date/', baseDate, "/", period, '.json'),
add_headers(Authorization = paste0("Bearer ", token)))
}
got_calories <- get_calories(baseDate = "2018-11-20", period = "3m")
calories <- content(got_calories)
# turn into df
calories[['activities-calories']] <- jsonlist_to_df(calories[['activities-calories']])
# assign easy object and rename
calories <- calories[['activities-calories']]
colnames(calories) <- c("dateTime", "calories")### STEPS
get_steps <- function(baseDate = NULL, period = NULL, token = Sys.getenv('FITB_AUTH')){
GET(url = paste0('https://api.fitbit.com/1/user/-/activities/steps/date/', baseDate, "/", period, '.json'),
add_headers(Authorization = paste0("Bearer ", token)))
}
got_steps <- get_steps(baseDate = "2018-11-20", period = "3m")
steps <- content(got_steps)
# turn into df
steps[['activities-steps']] <- jsonlist_to_df(steps[['activities-steps']])
# assign easy object and rename
steps <- steps[['activities-steps']]
colnames(steps) <- c("dateTime", "steps")### DISTANCE
get_distance <- function(baseDate = NULL, period = NULL, token = Sys.getenv('FITB_AUTH')){
GET(url = paste0('https://api.fitbit.com/1/user/-/activities/distance/date/', baseDate, "/", period, '.json'),
add_headers(Authorization = paste0("Bearer ", token)))
}
got_distance <- get_distance(baseDate = "2018-11-20", period = "3m")
distance <- content(got_distance)
# turn into df
distance[['activities-distance']] <- jsonlist_to_df(distance[['activities-distance']])
# assign easy object and rename
distance <- distance[['activities-distance']]
colnames(distance) <- c("dateTime", "distance")### FLOORS
get_floors <- function(baseDate = NULL, period = NULL, token = Sys.getenv('FITB_AUTH')){
GET(url = paste0('https://api.fitbit.com/1/user/-/activities/floors/date/', baseDate, "/", period, '.json'),
add_headers(Authorization = paste0("Bearer ", token)))
}
got_floors <- get_floors(baseDate = "2018-11-20", period = "3m")
floors <- content(got_floors)
# turn into df
floors[['activities-floors']] <- jsonlist_to_df(floors[['activities-floors']])
# assign easy object and rename
floors <- floors[['activities-floors']]
colnames(floors) <- c("dateTime", "floors")### ELEVATION
get_elevation <- function(baseDate = NULL, period = NULL, token = Sys.getenv('FITB_AUTH')){
GET(url = paste0('https://api.fitbit.com/1/user/-/activities/elevation/date/', baseDate, "/", period, '.json'),
add_headers(Authorization = paste0("Bearer ", token)))
}
got_elevation <- get_elevation(baseDate = "2018-11-20", period = "3m")
elevation <- content(got_elevation)
# turn into df
elevation[['activities-elevation']] <- jsonlist_to_df(elevation[['activities-elevation']])
# assign easy object and rename
elevation <- elevation[['activities-elevation']]
colnames(elevation) <- c("dateTime", "elevation")### minutesSedentary
get_minutesSedentary <- function(baseDate = NULL, period = NULL, token = Sys.getenv('FITB_AUTH')){
GET(url = paste0('https://api.fitbit.com/1/user/-/activities/minutesSedentary/date/', baseDate, "/", period, '.json'),
add_headers(Authorization = paste0("Bearer ", token)))
}
got_minutesSedentary <- get_minutesSedentary(baseDate = "2018-11-20", period = "3m")
minutesSedentary <- content(got_minutesSedentary)
# turn into df
minutesSedentary[['activities-minutesSedentary']] <- jsonlist_to_df(minutesSedentary[['activities-minutesSedentary']])
# assign easy object and rename
minutesSedentary <- minutesSedentary[['activities-minutesSedentary']]
colnames(minutesSedentary) <- c("dateTime", "minutesSedentary")### minutesLightlyActive
get_minutesLightlyActive <- function(baseDate = NULL, period = NULL, token = Sys.getenv('FITB_AUTH')){
GET(url = paste0('https://api.fitbit.com/1/user/-/activities/minutesLightlyActive/date/', baseDate, "/", period, '.json'),
add_headers(Authorization = paste0("Bearer ", token)))
}
got_minutesLightlyActive <- get_minutesLightlyActive(baseDate = "2018-11-20", period = "3m")
minutesLightlyActive <- content(got_minutesLightlyActive)
# turn into df
minutesLightlyActive[['activities-minutesLightlyActive']] <- jsonlist_to_df(minutesLightlyActive[['activities-minutesLightlyActive']])
# assign easy object and rename
minutesLightlyActive <- minutesLightlyActive[['activities-minutesLightlyActive']]
colnames(minutesLightlyActive) <- c("dateTime", "minutesLightlyActive")### minutesFairlyActive
get_minutesFairlyActive <- function(baseDate = NULL, period = NULL, token = Sys.getenv('FITB_AUTH')){
GET(url = paste0('https://api.fitbit.com/1/user/-/activities/minutesFairlyActive/date/', baseDate, "/", period, '.json'),
add_headers(Authorization = paste0("Bearer ", token)))
}
got_minutesFairlyActive <- get_minutesFairlyActive(baseDate = "2018-11-20", period = "3m")
minutesFairlyActive <- content(got_minutesFairlyActive)
# turn into df
minutesFairlyActive[['activities-minutesFairlyActive']] <- jsonlist_to_df(minutesFairlyActive[['activities-minutesFairlyActive']])
# assign easy object and rename
minutesFairlyActive <- minutesFairlyActive[['activities-minutesFairlyActive']]
colnames(minutesFairlyActive) <- c("dateTime", "minutesFairlyActive")### minutesVeryActive
get_minutesVeryActive <- function(baseDate = NULL, period = NULL, token = Sys.getenv('FITB_AUTH')){
GET(url = paste0('https://api.fitbit.com/1/user/-/activities/minutesVeryActive/date/', baseDate, "/", period, '.json'),
add_headers(Authorization = paste0("Bearer ", token)))
}
got_minutesVeryActive <- get_minutesVeryActive(baseDate = "2018-11-20", period = "3m")
minutesVeryActive <- content(got_minutesVeryActive)
# turn into df
minutesVeryActive[['activities-minutesVeryActive']] <- jsonlist_to_df(minutesVeryActive[['activities-minutesVeryActive']])
# assign easy object and rename
minutesVeryActive <- minutesVeryActive[['activities-minutesVeryActive']]
colnames(minutesVeryActive) <- c("dateTime", "minutesVeryActive")### activityCalories
get_activityCalories <- function(baseDate = NULL, period = NULL, token = Sys.getenv('FITB_AUTH')){
GET(url = paste0('https://api.fitbit.com/1/user/-/activities/activityCalories/date/', baseDate, "/", period, '.json'),
add_headers(Authorization = paste0("Bearer ", token)))
}
got_activityCalories <- get_activityCalories(baseDate = "2018-11-20", period = "3m")
activityCalories <- content(got_activityCalories)
# turn into df
activityCalories[['activities-activityCalories']] <- jsonlist_to_df(activityCalories[['activities-activityCalories']])
# assign easy object and rename
activityCalories <- activityCalories[['activities-activityCalories']]
colnames(activityCalories) <- c("dateTime", "activityCalories")##### Join multiple dataframes with purrr::reduce and dplyr::left_join
activity_df <- list(calories, steps, distance, floors, elevation, activityCalories, minutesSedentary, minutesLightlyActive, minutesFairlyActive, minutesVeryActive) %>%
purrr::reduce(left_join, by = "dateTime")# Add the dateTime to this dataframe
activity_df$dateTime <- as.Date(activity_df$dateTime)names <- c(2:ncol(activity_df))
activity_df[,names] <- lapply(activity_df[,names], as.numeric)# trim off any days that haven't happened yet
activity_df %<>% filter(dateTime <= "2018-11-06")
获取最近的活动类型
# We're giving it all she's got!
get_frequentActivities <- function(baseDate = NULL, period = NULL, token = Sys.getenv('FITB_AUTH')){
GET(url = paste0('https://api.fitbit.com/1/user/-/activities/recent.json'),
add_headers(Authorization = paste0("Bearer ", token)))
}
got_frequentActivities <- get_frequentActivities(baseDate = "2018-11-20", period = "3m")
frequentActivities <- content(got_frequentActivities)# This is a list object let's look at how many frequent activities are logged
length(frequentActivities)
## [1] 5# Take a look at the object with str()
str(frequentActivities)## List of 5
## $ :List of 6
## ..$ activityId : int 2131
## ..$ calories : int 0
## ..$ description: chr ""
## ..$ distance : int 0
## ..$ duration : int 3038000
## ..$ name : chr "Weights"
## $ :List of 6
## ..$ activityId : int 90009
## ..$ calories : int 0
## ..$ description: chr "Running - 5 mph (12 min/mile)"
## ..$ distance : int 0
## ..$ duration : int 1767000
## ..$ name : chr "Run"
## $ :List of 6
## ..$ activityId : int 90013
## ..$ calories : int 0
## ..$ description: chr "Walking less than 2 mph, strolling very slowly"
## ..$ distance : int 0
## ..$ duration : int 2407000
## ..$ name : chr "Walk"
## $ :List of 6
## ..$ activityId : int 90001
## ..$ calories : int 0
## ..$ description: chr "Very Leisurely - Less than 10 mph"
## ..$ distance : int 0
## ..$ duration : int 4236000
## ..$ name : chr "Bike"
## $ :List of 6
## ..$ activityId : int 15000
## ..$ calories : int 0
## ..$ description: chr ""
## ..$ distance : int 0
## ..$ duration : int 1229000
## ..$ name : chr "Sport"
我从来不认为自己是达尔文或梭罗,但显然,就花费的时间而言,慢慢散步是我最喜欢的活动。
你可以看到我的 Fitbit 也记录了Weights
、Sports
和Biking
的时间,这可能是我手动记录我的活动时记录的。Fitbit 有可能会在我玩滑板的时候注册Biking
。
活动相关图
以前我总是使用corrplot
包来创建一个相关图;然而,它不能很好地与ggplot
配合,这意味着你不能轻易地添加Game Boy
主题。尽管如此,我还是给了它一个复古的调色板,做了一些小小的调整。
由于我从最初的gameboy
中想到了两种颜色,并且知道它们的hex
代码,我能够从这个网站中生成一个调色板。
# Aligning Covariance Matrices # drop dateTime
corr_df <- activity_df[,2:11]# Correlation matrix
corr <- cor(na.omit(corr_df))
corrplot(corr, type = "upper", bg = "#9BBB0E", tl.col = "#565656", col = c("#CADCA0", "#B9CD93", "#A8BE85", "#97AF78", "#86A06B", "#75915E", "#648350", "#537443", "#426536", "#315629", "#20471B", "#0F380E"))
在相关图中,每个圆圈的颜色表示相关性的大小,圆圈的大小表示相关性的显著性。
在搜索了一会儿ggplot2
扩展之后,我能够使用ggcorrplot
,这允许我再次使用gameboy
主题!
# Generating textures...ggcorrplot(corr, hc.order = TRUE,
type = "lower",
lab = TRUE,
lab_size = 2,
tl.cex = 8,
show.legend = FALSE,
colors = c( "#306230", "#306230", "#0F380F" ),
title="Correlogram",
ggtheme=theme_gameboy)
# Game Over. Loading previous save
ggcorrplot(corr, hc.order = TRUE,
type = "lower",
lab = TRUE,
lab_size = 2,
tl.cex = 8,
show.legend = FALSE,
colors = c( "#3B7AAD", "#56B1F7", "#1D3E5D" ),
title="Correlogram",
ggtheme=theme_gba)
探索活动
# Link saying "hyahhh!"
# Static
g <- activity_df %>%
ggplot(aes(x=dateTime, y=calories)) +
geom_line(colour = "black") +
geom_point(shape = 21, colour = "black", aes(fill = calories), size = 5, stroke = 1) +
xlab("") +
ylab("Calorie Expenditure")
g + theme_gameboy() + theme(legend.position = "none")
g + theme_gba() + theme(legend.position = "none")
****
# Panick! at the Discord...
# gganimate
g <- activity_df %>%
ggplot(aes(x=dateTime, y=calories)) +
geom_line(colour = "black") +
geom_point(shape = 21, colour = "black", aes(fill = calories), size = 5, stroke = 1) +
transition_time(dateTime) +
shadow_mark() +
ease_aes('linear') +
xlab("") +
ylab("Calorie Expenditure")
g + theme_gba() + theme(legend.position = "none")
距离是由你的步数和你估计的步幅(你输入的身高)决定的。
我还制作了Distance
、Steps
、Elevation
和Floors
的剧情,但是你必须查看这个页面才能看到它们。
结束语
尽管 Fitbit 为单个用户提供了一个很好的仪表板,但它是不可扩展的。通过直接访问数据,人们可以向 200 个甚至更多的人提问。如果有人愿意,他们甚至可以构建一个带有定制可视化效果的奇特Shiny
仪表盘。
如果您有任何问题或意见,您可以随时通过 LinkedIn 联系我。在那之前,下一篇文章再见!
# Wubba Lubba Dub Dub
# https://www.spriters-resource.com/game_boy_advance/kirbynim/sheet/15585/
sprite_sheet <- png::readPNG("kirby.png")
Nframes <- 11 # number of frames to extract
width <- 29 # width of a frame
sprite_frames <- list() # storage for the extracted frames
# Not equal sized frames in the sprite sheet. Need to compensate for each frame
offset <- c(0, -4, -6, -7, -10, -16, -22, -26, -28, -29, -30)
# Manually extract each frame
for (i in seq(Nframes)) {
sprite_frames[[i]] <- sprite_sheet[120:148, (width*(i-1)) + (1:width) + offset[i], 1:3]
}
# Function to convert a sprite frame to a data.frame
# and remove any background pixels i.e. #00DBFF
sprite_frame_to_df <- function(frame) {
plot_df <- data_frame(
fill = as.vector(as.raster(frame)),
x = rep(1:width, width),
y = rep(width:1, each=width)
) %>%
filter(fill != '#00DBFF')
}
sprite_dfs <- sprite_frames %>%
map(sprite_frame_to_df) %>%
imap(~mutate(.x, idx=.y))
fill_manual_values <- unique(sprite_dfs[[1]]$fill)
fill_manual_values <- setNames(fill_manual_values, fill_manual_values)
mega_df <- dplyr::bind_rows(sprite_dfs)
p <- ggplot(mega_df, aes(x, y, fill=fill)) +
geom_tile(width=0.9, height=0.9) +
coord_equal(xlim=c(1, width), ylim=c(1, width)) +
scale_fill_manual(values = fill_manual_values) +
theme_gba() +
xlab("") +
ylab("") +
theme(legend.position = 'none', axis.text=element_blank(), axis.ticks = element_blank())
panim <- p +
transition_manual(idx, seq_along(sprite_frames)) +
labs(title = "gganimate Kirby")
gganimate::animate(panim, fps=30, width=400, height=400)