自然语言处理中的迁移学习——语境词向量综述
监督目标任务的迁移学习研究综述。
本系列的篇第一篇讨论了 NLP 中的迁移学习,并发表了— 半监督序列学习 *。*我们看到了使用序列自动编码器的简单预训练步骤如何改善所有四个分类任务的结果。
在这篇文章中,我想简单介绍一下列表中的下两个出版物。语境化的单词表示是这两个出版物的焦点。研究人员试图产生通常被称为嵌入的单词表示,它知道句子中的上下文含义。生成单词嵌入的过程是两者的区别所在。CoVe 使用类似 机器翻译 的监督任务,而 ELMo 使用类似 语言建模的非监督任务。
- 在翻译中学习:语境化的词向量— CoVe
- 深层语境化的词汇表征——埃尔莫
让我们深入研究每一份研究出版物,并指出其相似之处和不同之处。
在翻译中学习:语境化的词向量
机器翻译数据可以是 NLP 中 ImageNet 的潜在等价物。(由于使用 ImageNet 在计算机视觉中进行迁移学习取得了巨大成功)。作者试图通过采用为机器翻译训练的注意序列到序列模型来证明这一假设。机器翻译序列到序列模型在上下文中对单词进行编码,并将其解码成另一种语言。这些模型通常包含一个基于 LSTM 的编码器。他们利用这个编码器来获得他们所谓的上下文向量。
a) Training an encoder b) Reusing it for a downstream task. Source: “Learned in Translation: Contextualized Word Vectors” by McCann et al. 2017
这个过程包括两个步骤。a)训练用于机器翻译的注意力序列到序列模型。b)将学习到的信息传递给下游任务。
英语到德语的翻译数据用于训练机器翻译模型。他们使用一个标准的两层双向 LSTM 网络作为编码器(MT-LSTM),用手套向量初始化,一个两层单向 LSTM 作为解码器。预训练编码器 MT-LSTM 的输出被视为上下文向量。
w 是输入单词的序列,而 GloVe(w) 是由 GloVe 模型产生的单词向量的序列。 CoVe(w) 是 MT-LSTM 产生的上下文向量序列。
作者检查了 CoVe 向量在一系列分类任务数据集上的优势,即情感分析、问题分类和蕴涵;还有问答。分类模型使用双注意分类网络[1],问题回答模型使用动态共注意网络[2]。这些网络的架构超出了本文的范围。
与目标任务被预定义的第一次审查不同,这里没有目标下游任务。目的是使向量适应任何下游任务。
GloVe(w)中的每个向量与其 CoVe(w)中的对应向量连接在一起
作者将这些连接的向量作为分类和问答网络的输入。这些向量在整个实验过程中保持固定(不像第一次审查,在第一次审查中,预先训练的权重在目标任务上进行微调)。
Validation results: Accuracy for classification tasks and F1 for SQuAD. Source: “Learned in Translation: Contextualized Word Vectors” by McCann et al. 2017
使用 CoVe 和手套的模型始终比仅使用手套的模型表现更好。附加字符 n-gram 嵌入可以进一步提高某些任务的性能。他们在 SST-5 和 SNLI 数据集上实现了新的最先进的性能(在当时)。从实验中得到的一个重要启示如下。机器翻译数据集越大,使用 CoVe 对下游目标任务的改进越好。这是从实验中得到的重要启示之一。因此,这种相关性可以证明他们的假设,即在 NLP 中使用机器翻译数据作为 ImageNet 的等价物。
Test performance results. Source: “Learned in Translation: Contextualized Word Vectors” by McCann et al. 2017
深层语境化的词汇表征
艾伦人工智能研究所的这项研究介绍了另一种深度上下文单词表示。目标是学习对句法、语义和多义性(一个单词存在许多可能的含义)建模的表示。研究人员在语言建模任务中训练了一个双向 LSTM 网络来导出向量。这些被称为 ELMo(来自语言模型的嵌入)。ELMo 向量是语言模型所有内部层的函数,因此比 CoVe 更深。
双向语言模型是前向语言模型和后向语言模型的组合。正向 LM 通过模拟记号 k 的概率来计算序列的概率,提供了 k-1 记号的历史。反向 LM 类似于正向 LM,以相反的顺序运行序列,预测提供未来上下文的前一个标记。biLM 的架构与[3]相当。它是在 1B 单词基准语料库[4]上训练的。
作者修正了预先训练的 biLM,并用它来计算任何下游任务的表示。在某些情况下,对下游任务数据的 biLM 进行微调可以提高性能。因此,他们对特定任务数据的一个时期的 biLM 进行微调,去除受监督的标签,并在此后的整个任务实验中固定权重(不像第一次审查,他们在任务实验中微调权重)。在大多数情况下,他们使用微调的 biLM。
*ELMo 是 biLM 中中间层表示的特定任务组合。*一个 L 层 biLM 计算一组 2L+1 表示,如下所示。
ELMo 计算 biLM 中所有层的特定任务加权组合,如下所示。
s^task 是 softmax 归一化权重,标量参数 γ 通过实验确定。最简单的情况,它可以像 CoVe 一样只选择最后一层。
预训练的单词嵌入与来自 biLM 的 ELMo 向量连接,作为输入传递给下游任务。
他们验证了 ELMo vectors 在各种 NLP 任务中的性能,并在每个任务上实现了新的艺术水平(在当时)。他们为每项任务使用不同的基线架构,并将 ELMo 向量添加到输入中。与强基础模型相比,它们实现了 6–20%的相对误差减少。结果如下所示。
Test set results on 6 benchmark NLP tasks. Source: “Deep contextualized word representations” by ME Peters et al. 2018
它们表明,与仅使用最后一层相比,所有层的表示的加权组合提高了整体性能。在有可能进行比较的任务中,ELMo 胜过 CoVe。有时,在下游任务模型的输出层包含 ELMo 可以提高性能。它还成功地消除了一个词在上下文中的歧义,实现了一词多义。请参见下面的示例。
Nearest neighbours to ‘play’ using GloVe and ELMo. Source: “Deep contextualized word representations” by ME Peters et al. 2018
实验表明,biLM 的不同层描述了一个词的不同种类的信息。第二层在词义消歧方面表现更好,而第一层在词性标注方面实现了更高的准确性。这样,包含所有的 biLM 层是至关重要的。
通过 ELMo 制图表达添加大型无监督数据集非常有利。该模型更快地收敛到更高的精度,并且需要更小的训练集。该模型提高了训练数据的利用率。它显著减少了达到性能水平所需的训练数据量。
因此,ELMo 使用来自语言模型的深层嵌入来捕获上下文中单词的语法和语义。
CoVe 和 ELMo 在计算上下文单词表示的方式上是相似的。一些相似之处—
- 尝试计算上下文单词向量。
- 使用大型语料库进行预训练。
- 使用预先训练的模型以单词表示的形式传递学习到的信息。
- 计算出的单词向量被用作下游特定任务网络的输入。
- 预训练的权重在任务训练期间是固定的。
一些主要的区别—
- CoVe 在预训练步骤中使用机器翻译编码器来生成单词表示,而 ELMo 使用语言模型。
- CoVe 在有监督的机器翻译数据集上训练,而 ELMo 在无监督的语言模型数据上训练。
- CoVe 将最后一层机器翻译 LSTM 的输出视为上下文向量,而 ELMo 是语言模型 LSTM 中所有层的加权组合。
- CoVe 向量在任务训练期间是固定的,而来自 biLM 模型的权重在为任务训练固定之前用任务特定的数据进行微调。
- CoVe 的研究人员为各种下游分类任务使用通用架构,而 ELMo 则针对每项任务使用强大的基线架构。
上下文词向量的第一次审查和这次审查之间的一个重要区别是,研究人员选择了一个通用数据集进行独立于任务的预训练。这可能被视为向 ImageNet 类数据集发展的下一步。
参考资料:
[1] 机器理解的双向注意流
[2] 视觉和文本问答的动态记忆网络
[3] 探索语言建模的极限
[4] 测量统计语言建模进展的十亿字基准
延伸阅读:
这是系列文章中的第二篇,在这篇文章中,我简要介绍了最近关于 NLP 中迁移学习的出版物。你可以在这里找到第一个帖子。非常感谢任何反馈/建议。欢迎在下面发表评论,或者在 Twitter 或 LinkedIn 上联系我。
Udacity 人工智能工程师纳米学位概述,第 2 期
在完成了人工智能纳米学位的第一个学期后,我报名参加了第二个学期,明确期望学习更多关于深度神经网络的知识,特别是关于卷积和递归神经网络的知识。此外,中途停止也不符合逻辑:-)
等待时间 1
我在截止日期前 3 周完成了第一学期,一直等到 Udacity 解锁了第二学期。我把那段时间用于学习其他东西和做小项目,但是我认为从时间的角度来看并不是很有效。如果 Udacity 在完成第一个学期后马上解锁下一个学期,我会非常感激。
我还询问了他们对相反情况的支持——是否有可能在两个学期之间休息更长时间,然后再开始另一个学期。答案是肯定的,而且没有任何惩罚。所以如果你不能连续完成两个学期,这应该不是问题。
第二学期。深度学习和应用
结构
术语 2 由两部分组成:
- 深度学习和应用,您可以从中了解 CNN、和 GAN 的更多详细信息
- 专注部分,你可以深入到你最感兴趣的领域。你在计算机视觉、自然语言处理和语音用户界面之间进行选择。今天你只能做一个浓度,这很遗憾,因为从我的角度来看,至少有两个浓度是绝对可行的。
卷积神经网络
应用深度学习技术的第一部分是关于卷积神经网络。这一部分的结构非常好,你会得到详细的解释,解答测验和课程中的小项目。材质肯定比用深度学习基础纳米度要高。最后一个项目是一个狗品种检测器,你可以使用迁移学习技术来达到合理的结果。
您使用 Keras 作为掌握项目的工具,因此避免了应用原始 TensorFlow 的麻烦,可以专注于理解 CNN 而不是学习工具。
这些材料对我来说刚刚好,解释以一种清晰而恰当的方式给出,提供的参考资料也非常有用。亚历克西斯·库克是一位非常好的导师,我很喜欢这部分。
读完这一节后,我有一个印象,我理解了 CNN 的背景和他们的应用。这个项目要求有点高,但我更喜欢做一些准备不足的代码,自己多做一些研究。
递归神经网络和 LSTM
第二部分是关于递归神经网络(香草和 LSTM)及其应用。结构类似于 CNN 的一个部分,有解释、参考、小测验和项目。
我必须说,从讲解质量的角度来看,这是整个课程中最好的部分,不可能做得更好了。在我开始之前,我对概念的理解有一些问题,而且 LSTM 建筑对我来说也不是 100%清楚。完成后,我会说,我抓住了这个想法很好。杰里米·瓦特非常擅长用简单的方式解释复杂的事情。
**但是!!!**一个情绪预测的最终项目,真的是一个笑话。几乎一切都准备好了,你只需要做很少的事情就可以通过。真的真的很令人失望。学习材料这么好,最终项目却这么差:-(
生成对抗网络
最后一部分是关于生成性对抗网络。它由普通解释、深度卷积神经网络和半监督学习组成。由于导师是 Ian Goodfellow,你可以期待一个高质量的解释,最后,你对 GANs 背后的概念有一个很好的理解。
不幸的是,我在深度学习基金会 Nanodegree 中学习的所有材料都已经存在。我很失望,因为我以为我会花钱买到新东西,而不是我已经学会的东西。反正我刷新了一下知识,去做了专注部分。
等待时间 2 和浓度
我比要求提前 2 周完成了所有项目,必须等到专注部分解锁。再次从时间的角度来看,这不是最佳的,我看不到任何理由,为什么下一部分不能马上解锁。
浓度选择
你可以深入解决计算机视觉、自然语言处理或语音用户界面任务。所有三个浓度都由 Udacity 导师和一个公司的人(Affectiva 的情况下是工程师或首席执行官)提供给你,帮助你准备这个部分。
计算机视觉集中是与 Affectiva 合作完成的,start 项目是关于使用他们的 T2 SDK 进行情感识别。自然语言处理(NLP)的重点是与 IBM 合作,启动项目是关于使用 IBM Watson 来解决 NLP 任务。语音用户界面的集中是与亚马逊的合作,启动项目是关于使用 Alexa 的技能来创建你自己的语音界面。所有的 start 项目大多是为了好玩,不做评估。
最初,我想选择计算机视觉,但在看了介绍后,我改变了主意,选择了语音用户界面。原因是(从我的角度来看)这三个项目中最好的一个,我在 Udacity 论坛上读到,capstone 项目要求最高。
语音用户界面集中
一开始,你用亚马逊 Alexa 开发一个语音界面。亚马逊 Alexa 能够识别语音,理解它并做出适当的反应。在该项目中,您创建了自己的技能的语音交互模型,该模型在 Amazon Alexa 上运行,并创建了 AWS Lambda 函数来处理请求。其实你学会用亚马逊生态系统来解决语音识别及其理解的任务。该项目不是关于深度学习,而是关于使用准备好的积木。反正挺有意思的,也不是很简单。
学完这一非常实用的部分后,你就可以开始研究语音识别的问题了。您将了解挑战、信号分析、数据准备、特征提取、语音学、语言模型、传统自动语音识别系统(带隐马尔可夫模型)以及语音识别中的深层神经网络。
材料的质量和提供的参考资料都很棒,这个项目要求很高,尽管我希望它不是那么准备充分。我不后悔我的选择,如果必须的话,我会再次选择。
结论
最重要的是——我觉得自己已经做好了从纯软件工程领域转向机器学习/人工智能领域的充分准备。我非常清楚,我缺乏解决现实世界问题的专业经验,所以第一步将是在软件工程和机器学习领域之间的某个地方工作,以从我们可以通过应用机器学习和深度学习技术解决的问题中获取更多信息。
Udacity 为你成为一名从业者做了很好的准备,但我不指望你有机会通过完成这门课程转变为纯粹的研究领域。我强烈建议首先完成深度学习基础——如果你是该领域的新手,它在人工智能工程师纳米学位期间会有很大帮助。另一方面,我只需要 4 个月,每周 10-15 个小时就可以完成课程,而不是广告上说的 6 个月。
我仍然不确定这项投资——两个纳米学位需要 2000 美元。但至少我去年学到了很多新东西,希望它能帮助我在目前的职业道路上,或者改变到一个新的领域。无论如何,我明白深度学习技术对于一个纯粹的软件工程师来说也是解决新问题所必须的:-)
你可以在我的 GitHub 上找到所有的项目——第一期以 aind- 开始,第二期以 aind2- 开始。
面向数据科学家的 Python(和非 Python)制图工具概述
通常,数据需要在地理基础上理解。因此,数据科学家应该熟悉他们可以使用的主要制图工具。
我以前做过相当多的地图绘制工作,但鉴于我目前在温尼伯市担任交通资产数据科学家这一职位的中心性质,我很快就清楚我需要对地理地图绘制前景进行仔细的调查。
有一系列令人眼花缭乱的选择。鉴于我的主要编程语言是 python,我将从该生态系统中的工具开始,然后我将转到可用于地理分析的其他软件工具。
Python 中的绘图工具
GeoPandas 是一个很棒的库,它使得用 Python 管理地理数据变得很容易。
在其核心,它本质上是 pandas (任何使用 python 的数据科学家都必须知道的库)。事实上,它实际上是建立在 pandas 之上的,具有像“GeoSeries”和“GeoDataFrame”这样的数据结构,这些数据结构用有用的地理数据处理功能扩展了等效的 pandas 数据结构。所以,你得到了熊猫的所有优点,加上地理上的优势。
GeoPandas 结合了几个现有的地理数据分析库的功能,每个库都值得熟悉。这包括 shapely 、 fiona ,以及通过 descartes 和 matplotlib 内置的地理测绘功能。
您可以像熊猫一样将空间数据读入 GeoPandas,GeoPandas 可以处理您期望的地理数据格式,如 GeoJSON 和 ESRI 形状文件。加载数据后,您可以轻松地更改投影、执行几何操作、地理聚合数据、使用空间连接合并数据以及执行地理编码(这依赖于地理编码包 geopy )。
底图是基于 matplotlib 构建的地理绘图库,matplotlib 是 python 绘图库的鼻祖。与 matplotlib 类似,底图非常强大和灵活,但代价是获取所需的地图有些耗时和繁琐。
另一个值得注意的问题是,底图最近在 2016 年接受了新的管理,并将被 Cartopy 取代(如下所述)。尽管底图将维持到 2020 年,但 Matplotlib 网站指出,现在所有的开发工作都集中在 Cartopy 上,用户应该转向 Cartopy。因此,如果您计划使用底图,请考虑使用……
Cartopy 提供了几何变换能力以及映射能力。与底图类似,Cartopy 向 matplotlib 公开了一个接口,用于在数据上创建地图。matplotlib 为您提供了强大的制图能力和灵活性,但缺点是相似的:与其他选项相比,创建一个漂亮的地图相对来说更复杂,需要更多的代码和修改才能得到您想要的东西。
Geoplotlib 是 Python 的另一个地理制图选项,似乎是一个高度灵活和强大的工具,允许静态地图创建、动画可视化和交互式地图。我从未使用过这个库,它看起来相对较新,但它可能是一个值得关注的未来。
gmplot 允许你使用“类似 matplotlib 的界面”在谷歌地图上轻松地绘制多边形、线和点。这使您可以快速轻松地绘制数据,并利用谷歌地图固有的交互性。可用的绘图包括带填充的多边形、落点、散点、网格线和热图。对于快速简单的交互式地图来说,这似乎是一个很好的选择。
Mapnik 是一个用 C++编写的工具包(带有 Python 绑定),用于制作严肃的地图应用程序。它的主要目标是在网络上开发这些地图应用。它似乎是一个重型工具,为你今天在网上看到的许多地图提供动力,包括 OpenStreetMap 和 MapBox 。
follow 让你可以利用流行的 leaflet.js 框架来创建交互式地图,而无需编写任何 JavaScript 代码。这是一个很棒的库,我在最近几个月经常使用(我用 leav 为我的温尼伯树数据博客文章生成了所有的可视化)。
Folium 允许您绘制点、线和多边形,生成 choropleth 地图和热图,创建地图层(用户可以自行启用或禁用),并为您的地理数据生成弹出工具提示(额外的好处是:这些工具提示支持 html,因此您可以真正地自定义它们,使它们看起来更好)。地图上使用的标记和线条也可以进行大量的定制。
总的来说,leav 在特性、可定制性和编程简易性之间取得了很好的平衡。
Plotly 是一家提供大型在线数据分析和可视化工具套件的公司。Plotly 的重点是提供一些框架,使得在 web 上呈现可视化更加容易。您用 Python(或 R)编写代码,与 plotly 库对话,可视化效果使用极其强大的 D3.js 库呈现。为了体验什么是可能的,请查看他们的网站,该网站展示了一系列制图的可能性。
除了图表和绘图工具之外,他们的网站上还有一大堆感兴趣的相关产品,值得一看。我特别感兴趣的一个是 Dash ,它允许您仅使用 Python(不需要 JavaScript 或 HTML)创建响应性数据驱动的 web 应用程序(主要为仪表板设计)。这是我一定会去看看的,可能会在不久的将来发表一篇“深入数据科学”的帖子。
Bokeh 是一个专门研究浏览器中呈现的交互式可视化的库。这包括的地理数据和地图。与 Dash 类似,也有可能使用 Bokeh 来创建交互式 web 应用程序,这些应用程序实时更新数据并响应用户输入(它通过“ Bokeh 服务器”来实现这一点)。
其他制图工具
很明显,在 python 生态系统之外还有大量的绘图工具。这里有一些你可能想看看的简要总结。请记住,这个列表中遗漏了大量的工具。这些只是我比较熟悉的一些工具。
开普勒是一个基于网络的应用程序,允许您探索地理数据。这是优步在 2018 年 5 月下旬发布的全新工具。你可以在网站上使用该软件——开普勒是一个客户端应用程序,没有服务器后端,所以所有数据甚至都驻留在你的本地机器/浏览器上。然而,它不仅仅是在开普勒网站上使用;您可以安装应用程序并在本地主机或服务器上运行它,您也可以将它嵌入到您现有的 web 应用程序中。
该程序有一些很棒的功能,拥有你在交互式地图应用程序中期望的大多数基本功能,加上一些非常棒的附加功能,如分割地图和回放。网站上展示的例子非常漂亮,软件也很容易使用(非程序员也可以使用)。
本用户指南提供了更多关于开普勒的信息,它能做什么,以及如何做。我非常期待为一些即将到来的项目检查它。
Mapbox 提供了一套与制图相关的工具,旨在帮助开发人员创建使用地图和空间分析的应用程序。它提供了一系列服务,从为您的网站创建精美的地图到帮助您构建地理处理应用程序。
这个概述提供了一个可行的好主意。Mapbox 提供了一组底图图层,允许您自定义地图、添加自己的数据以及构建 web 和移动应用程序。它还提供了使用地理编码、方向、空间分析和其他功能等工具来扩展 web 应用程序功能的选项。虽然 Mapbox 不是免费服务,但他们似乎有慷慨的免费 API 调用限制(见他们的定价这里)。
重型 GIS 应用
此处未包括但对从事制图的人来说非常重要的是成熟的 GIS 应用程序,如 ArcGIS 和 QGIS 。这些都是非常强大的工具,值得地理数据分析师了解。注意 ArcGIS 相当贵;然而,这是一个非常值得了解的行业标准。QGIS 也相当普遍地被使用,并且具有免费和开源的优势。
这篇文章中有什么明显的疏忽吗?请在下面的评论中告诉我或者给我发一封邮件。
本帖原载于我的个人网站。
要访问我共享的 Anki deck 和 Roam Research notes 知识库,以及关于间隔重复和提高学习效率的技巧和想法的定期更新, 加入“下载 Mark 的大脑”。
更多资源
Python 数据可视化库
必要的 Python 地理空间库
所以您想要使用 Python 制作地图
使用 Python 可视化地理数据
使用 Python 中的开源工具可视化地理空间数据 (YouTube)以及附带的GitHub Repo of notebook
底图
Mapnik
map Nik Wiki
map Nik——也许是迄今为止最好的 Python 地图平台
控制你的地图
叶子
Python 教程用叶子制作多层传单网络地图 (YouTube)
用 Python 制作互动地图(三部分)
用叶子制作互动犯罪地图
散景
Python:用 Python 库 Bokeh 绘制数据
用 Bokeh 绘制交互式地图
拥有自己的知识
是的,我想念你们所有人,真诚地为长期的中断道歉。在我的下一篇文章中,你会更好地理解。哇,我很受启发来写我对学习的想法,特别是在我如何开始我的人工智能专家之旅时出现的许多问题。我们可以开始了吗?
a quote by Adam Lupu — VP of learning, Andela
2012 年
我清楚地记得,当我在期末考试中被分配到最后一年的项目主管时,我发现她拥有人工智能的博士学位,我决心选择一个与她的领域相关的项目主题,因为我想在期末考试中获得 A。
在对一个人工智能课题做了大量研究后,我决定建立一个牙科专家系统。有点遗憾的是,因为我没有编程知识,所以我不能像那时一样自己构建这个项目。我也觉得编程是为聪明人准备的,我不属于那一类。
我把我的项目题目给了我的主管,她很喜欢,并同意我立即开始。虽然听起来很悲伤,但我不得不将项目的代码部分外包给其他人,因为我当时不知道如何编码。然而,我确实为我的文书工作做了很多关于编码平台的研究,还不得不去拜访了几次牙医,他在项目的领域知识/工程部分帮助了我。
我喜欢我的项目的各种研究部分,我确保我的文书工作是正确的,这最终使我在这里发表了我的第一篇论文:http://research . ijias . org/volume 8/number 2/ijias 14-451270 . pdf
顺便说一下,我得到了我一直想要的成绩 A 【T7:)
arranging the ailment based on symptoms selected
2013/2014 年
我在一所著名的私立大学担任 IT/系统技术员,我认为我当时的收入很不错,因为我可以负担得起三餐,一个住所和几分奢侈生活的乐趣,但在某一点上,我决定对我的职业生涯进行深思熟虑,我的老板当时给了我一些数据库管理书籍来阅读。我开始在数据库中获得一些基础,并自信地认为我会杀了它。有一天,他告诉我“即使你认为你擅长数据库,你也应该选择编程,因为很多程序员实际上知道你做的这些事情”。我对不得不学习编程感到很难过,因为我已经对数据库了如指掌。
与此同时,我正在看一部小说系列相关人物,我爱上了一台机器能够在恐怖主义行动发生之前预测它们的方式。这很神奇,同时也很吸引人,因为它让我更加热爱人工智能的世界。那时我知道人工智能将成为我职业目标的一部分。从 W3 schools 开始,我开始自学 PHP,并通过电子邮件将我的代码片段发送给我以前的一个同学,他已经在这个领域工作了。
my favorite character in the movie “root”
2015 年
我从以前的工作场所辞职,发现自己在安德拉。这是我真正开始学习的地方。随着时间的流逝,我知道我必须深思熟虑才能开始我的人工智能专家生涯。对我来说有趣的是,我开始编程是因为我对人工智能的兴趣,我通过快速聊天发现,人们通常在进入编程后爱上人工智能,但我的情况正好相反。
2016 年
我决定开始我的学习,从在发展中心广场大喊开始。我能够召集对人工智能/机器学习/数据科学感兴趣的人,我们从一个松散的小组开始。请注意,在这个时候,我不知道我应该或不应该学习什么,但重要的是组成这个小组的人的多样性——新手(像我一样),初学者,中级和专家。
在这个伟大的社区中,资源每天都被共享,我开始充分利用它们。我不介意示意整个小组就我不清楚的概念提问。哦,我想起了朴素贝叶斯算法是如何在我理解它之前给我出难题的。请注意,很难将自学与我的日常工作结合起来,但我仍然有意每天至少花 3 个小时进行机器学习。
the struggle was real
我很幸运,我的工作时间是从中午 12 点到晚上 8 点,所以我很好地利用了中午之前的几个小时来加速机器学习,尽可能避免分心。我坚持练习,经过 3 个月的自学,我参加了一个全球人工智能锦标赛,甚至对自己在排行榜上的位置感到震惊。我从未察觉
你可以在这里赶上我关于锦标赛的代码教程。我也开始参加 Kaggle 比赛,并很快向该领域的专家寻求建议。
2017
我决定发表另一篇关于人工智能相关主题的论文,这是我目前正在做的,我还决定开始为新手组织研讨会。在人工智能领域,我仍处于初级水平,但有一点我很有信心,那就是无论你认为自己对某个概念/领域的了解有多少,总会有一群观众。还有一句名言说“确定你完全理解某事的最好方法是当你能教别人并且他们也能理解的时候”。我也把它看作是确定我认为我知道的事情的一种方式。
作为一名 Udacity 机器学习纳米学位的学生,我目前正在完成我的最后一个项目。虽然对我来说这是一个忙碌的旅程,但我期待着写一个关于我所做的代码教程。哦,我还买了一些书来帮助我学习,相信我,它们不便宜,尤其是美元对奈拉的汇率。
don’t borrow…BUY
结论
许多人问我安德拉目前是否有人工智能的发展道路,诚实的回答是目前没有。然而,我们正在数据科学的轨道上工作,我相信人工智能很快就会出现。我确实告诉这类人*“他们拥有并应该努力磨练自己的学识”*。我喜欢下面这句话
学会掌控自己的学习,不要完全依赖别人来负责你如何学习,要深思熟虑你想学什么,并愿意接受每个行动带来的牺牲。导师的地位怎么强调都不为过,我必须承认,我的导师为我铺平了道路,这是因为我也渴望学习。
特别感谢 Farouq Oyebiyi、Allen Akinkunle、Yinka Makanjuola、Deolu Adeleye 和 Dotun Owoade。谢谢你总是回答我愚蠢的问题,同时让我的 AI 之旅压力更小:)
仅供参考——这是一篇我觉得相当实用有趣的相关文章——https://www . LinkedIn . com/pulse/learning-developers-stories-blessing-orazulume
面向购房者和少数族裔的 P2P 贷款
从熊猫看美国的 P2P 借贷格局
近年来,个人对个人(P2P)贷款的兴起极大地促进了以前得不到充分服务的人群获得融资的民主化。这类借款人有什么特点,P2P 贷款又有哪些不同类型?
Lending Club 发布特定时期发放贷款的季度数据。我将使用 2018 年 Q1 的最新贷款数据来查看最近一批借款人。可以理解的是,由于数据的新近性,还款信息仍然不完整。将来查看包含更多还款信息的旧数据集或 Lending Club 提供的拒绝贷款数据会很有意思。
看一下 dataframe 形状,可以发现 2018 年 Q1 有 107,868 笔贷款。有 145 列,有些列完全是空的。
一些空列(如 id 和 member_id)是可以理解的,因为它们是个人身份信息。许多变量也与详细的贷款信息有关。出于这种分析的目的,我们关注几个人口统计变量和基本贷款信息。关于变量的更多信息可在这里获得。
缺失数据和数据类型
看看变量的数据类型,它们目前都是非空对象。对于应该表示规模或顺序感的变量,数据应该相应地改变。
单个条目显示,空数据由空字符串对象、非类型对象或字符串“n/a”表示。通过用 NaN 替换它们并运行 missingno,我们看到‘EMP _ length’下有大量缺失的字段。
删除丢失数据的记录会产生 98,424 行,而不是对初始数据的大量稀释。
根据单个变量的性质,它们必须转换为以下数据类型,以便在任何后续分析中使用:
整数数据类型:
- loan_amnt(申请的贷款金额)
- funded_amnt(资助的贷款金额)
- term(贷款的支付次数)
- open_acc(开放的信用额度数)
- total_acc(已知信用额度总数)
- pub_rec(贬损公共记录数)
Float 数据类型:
- int_rate(贷款利率)
- dti(债务收入比)
有序类别数据类型:
-等级(贷款等级 A-G)
- emp_length(任职年限)
- annual_inc(年收入)
整型和浮点型转换相对标准,通过简单的正则表达式去掉了复杂的符号和空格。分类变量可能有点棘手。对于这个用例,我们需要有序的分类变量。
例如,贷款等级为 G 代表质量最低、风险最高的贷款。
使用“cat.codes”将每个条目转换为相应的升序整数。通过同样的过程,我们也可以将就业年限转换成序数变量,因为整个’ > 1 年’和’ 10 年以上’不能传达必要的信息。
由于年收入中有太多独特的价值,根据它们所属的价值带将它们分成不同的类别会更有用。在这种情况下,我使用 pd.qcut 为每个值范围分配一个 bin。
“qcut”会将物品分开,使每个箱子中的物品数量相等。请注意,还有另一个名为 pd.cut 的方法。cut 根据值将项目分配到箱中,而不考虑每个箱中的项目数量。
虽然我最初倾向于使用 cut 来获得收入范围的更好视角,但事实证明有多个异常值严重扭曲了数据。从每个箱子中的物品数量可以看出,使用“cut”提供了收入数据的平衡视图。
贷款类型或借款人的状态等变量保持不变,我们可以仔细查看每个变量的唯一值。
初步分析
那么我们第一眼看到的是什么呢?
令人难以置信的扭曲的债务收入比
Loan amount and interest rate distributions
贷款金额和利率的偏度和峰度偏离正态分布,但非常低。较低的偏斜度值表示两条尾巴的重量没有显著差异。这些值不会向某一特定方向倾斜。较低的峰度值表示两个尾部的组合权重较低,表示存在少量异常值。
有趣的是,贷款金额的峰值出现在 5000 美元的区间内。鉴于这种对整数的偏好,分步定价策略可能吗?
此外,在收益率低于 10%时,利率会出现一个明显的峰值。鉴于高收益公司债券徘徊在 7.5%左右,P2P 贷款必须以更高的利率来证明其风险状况,这似乎是有道理的。
债务与收入比率的分布明显偏斜,尾部非常重。考察个别异常案例,了解贷款是如何发放给这些高风险个人的,将会很有意思。
修罗和脚蹼
从贷款类型来看,有一些特别突出的与房屋相关的贷款类型。考虑到有借款人房屋所有权状况的信息,我创建了一个新的房屋特定贷款数据框架来寻找有趣的趋势。
乍看之下,绝大多数有抵押贷款的借款人都在申请房屋装修贷款,几乎相当于房主和租房者的 5X。他们也是为了买房而贷款最多的群体。
抵押贷款的房主真的喜欢重新粉刷房子和安装吊灯吗?一种解释可能是,这些住房改善不是为了自己,而是为了在转手之前增加房产价值。这些固定和翻转操作并不新鲜,在 Attom 有关于这种现象的深入报道。一个公开的跨州房屋转手活动数据集将有助于更深入地了解这种 P2P 贷款的借款人构成。
另一个有趣的发现是针对租房者的“搬迁”贷款。虽然这种贷款的数量对其他群体来说几乎可以忽略不计,但房屋租赁者由于其居住安排的短期性质,对这种贷款有更多的需求。
债务整合中的高额贷款集中
Quick tip: the use of jitter=True prevents overlapping points and provides more information around individual data points
在债务合并、信用卡再融资和房屋装修类别中,似乎集中了高于中值的高价值贷款。鉴于债务合并通常是指个人与高水平的无担保贷款或太多的信贷设施,高贷款额是有道理的。
从色调的分布来看,大额贷款的期限明显集中在 60 个月。这将可靠地符合借款人更愿意分期偿还大笔贷款的假设。
加州爱 P2P 贷款
贷款数量和 P2P 贷款总额的图表显示,加州对这种形式的信贷有着贪婪的胃口。它获得的 P2P 贷款比排名第二的德克萨斯州多 40%。这种巨大的差距有几种解释。
有报告显示,较富裕的州通常倾向于承担更多的债务。加州的债务收入比是各州中最高的,这在我们的数据中也很明显。
此外,加州是美国技术最娴熟的州之一,可能会更多地接触 P2P 贷款平台等替代融资解决方案。事实上,P2P 贷款总额最高的州包括两个现有的顶级金融科技生态系统(加利福尼亚州,纽约州)和两个增长最快的金融科技中心(德克萨斯州,佛罗里达州)。
是什么决定了跨州的 P2P 贷款使用情况?
鉴于各州 P2P 贷款数量的概况,为什么不更进一步呢?
《赫芬顿邮报》上有一篇关于美国房地产危机的很棒的文章,有一个有趣的观察,在租金和房价上涨的情况下,由于种族财富差距,非裔美国人倾向于非传统贷款。由于信用评分和收入水平较低等原因,他们更有可能被这些贷款来源拒绝。
几个问题突然出现在我的脑海里:
1。他们会转向其他替代融资来源吗?比如说,P2P 贷款来获得与房屋相关的贷款?
2。其他州特有的因素会影响住房贷款的数量吗?
搜集时间
我去了www.census.gov搜集了各州层面的数据,从人口统计到经济数据。
在 Google Chrome 的网络选项卡中,我发现人口普查表上呈现的大部分数据来自另一个网站,链接类似于此:https://www . census . gov/quick facts/fact/table/DC,US/PST045217?ajax=true#qf-headnote-c
此外,这些页面中的每一个都包含了到 csv 文件的另一个链接,这些数据看起来像这样:https://www.census.gov/quickfacts/fact/csv/dc,US/PST045217
不同州的链接之间的唯一区别似乎是链接中的州代码。假设我的数据集的‘addr _ state’列中有所有唯一的州代码,我编写了一个循环来为每个州创建到每个 csv 的不同链接。一旦所有的数据都被提取出来,一个数据框架就会被创建出来,其中只包含与种族、住房和收入相关的变量。
所有带有 NaN 的列都被删除,并根据索引中的州名添加了一个附加列’ addr_state’。这是为了能够根据州代码合并数据帧。
我还从 FRED 那里获得了 2016-2018 年各州房价指数的另一个数据集。利用这个数据集,我在一个新的数据框架中创建了一个新列,用于显示 2016 年至 2018 年房价指数的百分比变化。
鉴于这只是对与住房相关的贷款的观察,我们基于相关 P2P 贷款的贷款计数创建了一个新的数据框架。
通过将数据框架合并在一起,从三个不同的来源创建了所需变量的主数据框架。房屋相关贷款,房屋购买、改善和移动 P2P 贷款的集合,是模型的结果变量。
不同变量之间的相关性显示,住房单元和建筑许可与住房相关贷款的结果变量高度相关。
我特别想使用“总贷款”作为控制变量,因为它与房屋相关贷款数量的结果变量和住房单元的独立变量相关。
然而,总贷款和住房相关贷款之间存在内生变量偏差。有更多的住房相关贷款,因为有更多的贷款,还是有更多的贷款,因为有更多的住房相关贷款?除非对这两个变量之间的关系有更清楚的了解,否则将贷款总额作为控制变量是不合适的。
First regression with all variables, second regression with statistically significant variables from first regression
乍一看,从 0.985 的 R 平方值来看,住房相关贷款的大部分可变性可以用现有变量来解释。
尽管住房单元和建筑许可证的系数值低得令人难以置信,但只有住房单元的数量、中位租金和建筑许可证的数量具有统计意义。住房单元和建筑许可证数字都表明住房供应和更多的贷款将被用于抵押或改善住房。较高的租金价格可能表明需要 P2P 贷款来支付这种生活成本,尽管这种贷款可以归类在其他标题下,如“其他”或“债务合并”。
仅针对统计显著变量的第二次回归运行返回了类似的 0.971 的高 R 平方,但将住房单元作为唯一具有无穷小系数值的统计显著变量。
那么…这一切都是徒劳的?
不完全是。尽管数据和提出的问题不匹配,但这里有一些改进的要点和想法:
贷款用途的细分——当前与住房相关的贷款类型主要面向房主和购房者。《赫芬顿邮报》文章中提到的贷款是为接近贫困线的非裔美国人和少数族裔提供的。此类贷款可能反映了用于支付租金和其他直接生活费用的发薪日贷款,可以归类为“债务合并”和“其他”类。对贷款用途进行更细致的分析,可以更准确地反映非裔美国人使用替代融资的情况。
低 P2P 市场份额——这里看到的住房单元和许可证的微小系数可以归因于替代融资来源所占的抵押贷款市场的微小部分。P2P 贷款平台不太可能是住房供应的显著受益者。
缺乏可靠的种族代理人——各州的非裔美国人人口并不是该种族群体贷款的最佳代理人。从 P2P 或抵押贷款记录中获取更多关于个人贷款种族的个人贷款信息将会改进该模型。
包含更多特征变量——本文选择了贷款变量和状态变量的一个选定子集,尽管实际上,对变量组的仔细重新设计可能会产生其他有用的变量来改进模型。这种包含大量新变量的做法不可避免地导致了维数灾难,但那是另一天的争论。
缺乏替代融资意识的指标——意识指数或跨种族和州的替代贷款来源知识的其他替代物会极大地改善该模型,因为它会令人难以置信地描述贷款人如何考虑和使用这种新的融资资源。例如,拥有更多 STEM 毕业生或技术孵化器的州更有可能了解 P2P 贷款的可用性。
合并数据帧的不同方式——还有其他一些重塑和合并来自其他来源的数据的替代方式,这些方式会导致不同的模型。例如,一个热编码可以用来指示不同的状态。另一个例子是从逐个贷款的基础上构建模型,而不是像现在这样逐个州地构建模型。
时间序列分析——所运行的回归模型只是时间上的一个快照。如果能够收集过去 5 年每个财务季度的数据点,结果将更具代表性。
对现有的抵押贷款数据集进行逆向工程以进行竞赛——如果有外部抵押贷款数据集具有与贷款俱乐部数据集相似的特征变量,则可能创建一个预测模型来标记贷款俱乐部的贷款。虽然肯定不如实际标签准确,但考虑到数据隐私,这可能是下一个最佳选择。
感谢阅读,您可以在这里找到相关代码和其他试用型号!
带薪休假和科学的本质
灵活的工作安排不仅仅是一种好的人力资源做法。它们将我们的大脑暴露在混乱的真实世界模式中,这有助于我们在更人工的数据环境中找到模式。
The view from this week’s office.
我在北卡罗莱纳州海岸的海滨别墅里写下这篇文章。我刚刚花了一周时间和我的妻子和孩子在沙滩上玩耍,在内陆水道划独木舟,学习救助海龟,打迷你高尔夫。
这也是我两个月来最有成效的一周。
过去的两个月很好——我做了很多事情——但是我一直在思考一个特殊的分析问题。我把问题分为两类:神秘和困惑。有了一个拼图,你就知道你在试图构建什么,你只需要弄清楚所有的碎片是如何组合在一起的。对于一个谜,你并不真的知道你在寻找什么,所以你在弄明白它的时候会慢很多。这个星期,我的神秘变成了一个谜题,我已经把很多碎片拼在一起了。我是在周二到周四电话会议之间远程工作的时候这样做的,在周五早上我的孩子看《海绵宝宝》的时候也做了一点。
这不是那种“如果你能减压,你能清楚地看到事物”的交易。我的工作和提供这份工作的公司都允许大量减压。在这一周的时间里,通过做一些我平时不会做的事情,我的大脑需要处理一些平时不会思考的事情。其中一些东西被证明是有用的。
我一直强烈支持进步的人力资源实践,比如无限带薪休假和在家工作的政策。我支持这些政策,主要是基于这样一个原则:我被雇佣并获得报酬是为了交付成果,而不是每周在某个特定的房间里坐一段时间。如果我能实现我承诺的结果,我应该能够按照我觉得需要的方式安排我的生活(当然,前提是我这样做不会妨碍我的同事实现他们自己的结果,等等)。)当雇主愿意对我表现出这种信任时,这意味着很多,而且这通常会提高我的生活质量,因为我不必担心我可以离开办公室的天数。
并不是说我相信无限的 PTO 或远程工作毫无保留地好。我认为这两种方式都是最好的,当它们代表着一种不同于常规工作的变化时。当远程工作成为的例行公事时,它真的会让人精疲力竭,尤其是如果团队中的大多数人没有远程工作,因此没有养成适应远程工作人员的习惯或基础设施。我认为,当灵活的工作安排仍然是员工的例外而不是规则时,这表明了雇主的信任,对员工来说是非常健康和授权的。
所有上述推理对我来说仍然很重要,但在过去几天里,我开始将我的假期和在家工作的时间视为我成为一名优秀数据科学家的能力的非常重要的一部分:远离我的正常例程实际上有助于我更好地执行这些例程。我当然不是第一个这样看待事情的人。例如,看看数学家亨利·庞加莱如何描述他发现了被称为的自同构形式:
我离开了当时居住的卡昂,去参加一个由矿业学院组织的地质会议。旅途中发生的事情使我忘记了我的数学工作。当我们到达 Coutances 时,我们休息了一会儿去开车,当我把脚放在台阶上时,我有了一个想法,尽管我以前的想法似乎没有让我为此做好准备,那就是我使用的变换…与非欧几里得几何的那些是相同的。我没有核实,也没有时间去核实,因为我在休息时一坐下就又开始了谈话,但我立刻感到绝对肯定。当我回到卡昂时,我在闲暇时验证了结果,以满足我的良心。
然后我开始研究算术问题,没有任何明显的结果,没有怀疑它们可能与我以前的研究有一点联系。厌恶我想要的成功,我去了海边几天,想完全不同的事情。有一天,当我走在悬崖上时,这个想法出现在我面前,同样具有简洁、突然和立即确定的特点…
我本周发现的东西当然没有庞加莱的发现那么令人印象深刻,但它们对我很重要,而且我相信,对雇佣我的企业和雇佣我的客户也很重要。我没有在海边散步时想着我的工作——事实上,工作是我最想不到的事情,直到它突然不在了。
这个想法中的某些东西对我来说似乎很熟悉,这促使我寻找一篇我已经很久没有读过的文章:人类学家 Clifford Geertz 的文章。Geertz 在 70 年代因倡导一种新的、有趣的、有用的研究人类文化的方法而声名鹊起,今天人类学家对他的看法很矛盾,因为他的方法并没有像他早期的支持者宣传的那样新颖、有趣或有用。抛开批评者不谈,我很欣赏 Geertz 关于理解复杂和不透明系统的困难的观点(这或多或少是数据科学家的工作)。我从下面的摘录中省略了“文化”、“人类学”和类似的术语,因为我认为它适用于任何分析任务。
连贯性不能作为描述有效性的主要测试。系统必须有最低程度的一致性,否则我们不会称之为系统;通过观察,他们通常有更多。但是没有什么比偏执狂的妄想或骗子的故事更有条理了。我们的解释的力量不能像现在经常做的那样,依赖于它们的紧密程度,或者它们被争论的保证程度。我认为,没有什么比对形式秩序的无可挑剔的描述更能使分析失去信誉,因为没有人能完全相信它的真实存在。
如果解释是在构建对发生的事情的解读,那么将它与发生的事情——与特定的人在此时此地所说的话、他们所做的事、对他们所做的事——以及整个世界的庞大事务分离开来,就是将它与它的应用分离开来,使它变得空虚。对任何事物——一首诗、一个人、一段历史、一种仪式、一个机构、一个社会——的好的解释会把我们带进它所解释的事物的核心。当它没有做到这一点,而是把我们引向别的地方——引向对它自身的优雅、作者的聪明或欧几里得秩序之美的赞美——它可能有其内在的魅力;但这是手头任务所要求的以外的东西。
我以前说过(例如:这里的这里的和这里的这里的)数据科学家的工作和人种学家的工作非常相似,数据科学和人类学真的是齐头并进的。正如 Geertz 所说,一个民族志学者可以很容易地构建一个社会的模型,这个模型是优雅的,优美连贯的,完全脱离现实的。虽然数据科学家经常(尽管肯定不总是)有验证集,允许他们检查自己的工作,但总是有一种诱惑,那就是选择一个数学上优雅的解决方案,仅仅是因为其优雅的*。*
在过去的两个月里,我试图找到多种符合事实的优雅解决方案,但它们就是不行。本周,我想出了一个远非优雅的解决方案。它是如此不雅,我不得不做一些额外的工作,只是为了确保它将规模。但这很有效。起初我认为这有点难看,尤其是与我以前尝试过的方法相比。但我突然意识到,我试图用这种方法模拟的现实本身非常丑陋——它是来自多个来源的信号的大杂烩,每个信号都经过多个中介的过滤,并以不同的保真度进行报告。
在过去的几个月里,我花了太多的时间研究现实的模型,而不是真实的现实,以至于我的思想陷入了认为生活比实际更简单——更干净——的窠臼。这限制了我处理棘手问题的能力。这不仅仅是计算机工作者或数学工作者的问题。我认为这是科学家普遍面临的问题,因为模型是科学家的惯用伎俩。当模型成为我们的现实,我们停止做好科学。我们需要时间远离我们的模特。
对于无限 PTO 来说,这似乎是一个非常不切实际的论点,但对于普通的数据从业者来说——我认为我很普通——带薪休假和远程工作安排是延长暴露在混乱的现实世界中的唯一方式。数据从业者从灵活的工作安排中获得了不成比例的好处,因为我们试图理解的东西是真实的,但模型甚至代表真实东西的数据都必然是人工的。我们需要看到现实生活中的新模式,以保持我们在计算机上寻找新模式的优势。
使用加密货币进行配对交易
本文简要介绍了 pairs 交易,包括概念、基础数学、策略算法、交易机器人开发、回溯测试和转发测试评估,以及未来问题讨论。作为一个实际的例子,机器人将进行加密货币交易。
概念
Pairs trading 是一种市场中立的交易策略,在一对高度联动的资产中使用多头头寸和空头头寸。
该策略的利润来源于两种工具之间的价格变化差异,而不是两者的变动方向。所以,如果多头涨得比空头多,或者空头跌得比多头多,就可以实现盈利(完美的情况下,多头涨,空头跌,但那不是盈利的要求)。配对交易者有可能在各种市场条件下获利,包括市场上涨、下跌或横盘——以及波动性低或高的时期。
来源: Investopedia
协整与相关性
在定量交易中,我们通常使用非平稳的时间序列。通常,当两个资产一起移动时,人们认为两个资产的相关,但是这个术语在这个上下文中是不正确的。皮尔逊相关性仅适用于静态变量。正如我们所看到的,这个公式使用了期望值和标准偏差,但是这些值在非平稳过程中是随时间变化的。
Correlation formula
对于这些过程,我们可以定义为协整。协整是指几个非平稳时间序列的平稳线性组合。你可以在这个视频中找到简单的解释
这张图片显示了两个过程(X 和 Y),以及它们的传播。这是一个没有协整的相关性的例子。
Correlation with no cointegration
这个例子反之亦然(无相关性的协整)
Cointegration with no correlation
如何使用 Python 构建这些流程你可以在这里找到。
为了进入下一章,我们应该知道如何检测协整。
检验协整的三种主要方法是:
恩格尔-格兰杰两步法
如果 xt 和 yt 是非平稳且协整的,那么它们的线性组合一定是平稳的。换句话说:
*yt-βXT = ut,*其中 ut 为静态。
如果我们知道 ut ,我们就可以用类似迪基-富勒测试、菲利普-佩伦测试的东西来测试它的平稳性,然后就完成了。但是因为我们不知道 ut ,我们必须先估计这个,一般用普通最小二乘法,然后在估计的 ut 序列上运行我们的平稳性测试。
2.约翰森测试
Johansen 检验是一种允许多个协整关系的协整检验,与 Engle-Granger 方法不同,但该检验受渐近性质的影响,即大样本。如果样本量太小,那么结果将是不可靠的,应该使用自回归分布滞后(ARDL)。
3.菲利普斯-欧利亚斯协整检验
Peter C. B. Phillips 和 Sam Ouliaris (1990)表明,应用于估计协整残差的基于残差的单位根检验在非协整的零假设下不具有通常的 Dickey-Fuller 分布。由于零假设下的虚假回归现象,这些检验的分布具有渐近分布,这取决于(1)确定性趋势项的数量和(2)被检验协整的变量的数量。这些分布被称为菲利普斯-欧利阿里斯分布,临界值已被制成表格。在有限样本中,使用这些渐近临界值的一个更好的替代方法是从模拟中产生临界值。
来源:维基百科
让我们为这个问题编写一些分析代码。首先从 Bitfinex 下载几个加密货币的数据(2018–01–01 到 2018–05–31)。下一步是策划加密货币的表演。最后,对所有资产对进行协整检验。
加密货币的表现是
Performance of cryptocurrencies (from 2018–01–01 to 2018–05–31)
零假设是不存在协整关系,另一个假设是存在协整关系。如果 p 值很小,低于一个临界大小,那么我们可以拒绝没有协整关系的假设。
Cointegration test result
我们可以得出结论,其中一些对是协整的,可以选择下一步的研究。
交易策略
结对交易中没有单一的方法来计算差价并进行交易。一些方法使用线性回归和残差作为分布。我们将使用下一个算法。
算法策略包含以下步骤:
- 通过上述方法之一(如 Engle-Granger)识别协整对。应该定期执行此步骤,以获得将在接下来的步骤中使用的一对(或几对)。
- 通过长度 N 获取资产的价格历史。计算资产对中每项资产(如 A 和 B )的收益
3.计算退货之间的差额
4.计算 z 得分,z 得分是数据点平均值的标准偏差数。
这张图片展示了 z 分数
Standard normal distribution
5.选中输入职位规则:
如果该条件为真,则打开 A (50%资本)的多头头寸和 B (50%资本)的空头头寸
如果该条件为真,则打开 A 的空头头寸和 B 的多头头寸
6.检查平仓规则:
如果这一条件成立,平仓所有头寸
让我们用 Catalyst 框架来编码这个算法。我在我的上一篇文章中提供了 Catalyst 的快速介绍。你在那里找到的初始化、 handle_data 、 analyze 和 run_algorithm 函数的信息。
一个标准的方法是使用训练\测试分割,但是我们也有一个协整测试周期。这些时间段不应交叉。因此,我们有
协整检验期— 5 个月(从 2018 年 1 月 1 日到 2018 年 5 月 31 日)
回测期— 4 个月(从 2018 年 6 月 1 日至 2018 年 9 月 30 日)
转发期— 2 个月(从 2018 年 10 月 1 日至 2018 年 11 月 30 日)
首先要验证算法。让我们使用 XMR/USD 和 NEO/USD 对运行这个脚本,禁用佣金成本并关闭滑点模型。
XMR/USD and NEO/USD with no commission
正如我们所见,算法返回曲线相当不错。这看起来就像它应该如何工作(非常高的分拣率和回报是 4 个月 164%)。控制台输出性能:
总回报:1.645993234216582
索提诺系数:30 . 96620118
最大压降:-0.05125165292172551
回溯测试
让我们建立佣金成本和滑点模型
XMR/USD and NEO/USD with commission and slippage
业绩差,权益(红线)平滑递减。通常情况下,当一个策略产生了许多平均利润值较低的信号时,就会发生这种情况。控制台输出性能:
总回报:-0.9160713719222552
Sortino coef:-11.6499238
最大压降:-0.914893278444377
我们应该尽量减少交易信号的数量,而且交易的潜在利润应该很高。我建议增加 min_spread 的值,设为 0.035,就意味着 spread 要比往返交易成本高几倍。另外, z_signal_in 值应该更高,例如对于 99.99%的间隔。时间范围可以更改为更大的值(例如每小时),但分析周期将保持不变(3 天)。
XMR/USD and NEO/USD with updated params
这组参数实现了我们的目标。信号数量较低(黄色线代表使用的杠杆),算法在 4 个月内表现良好:
总回报:0.0946758967277288
Sortino coef:8.343300492
最大压降:-0.0281546269574607
促进
这一步更真实地展示了所开发的算法。让我们对样本外数据(过去 2 个月)运行策略。
XMR/USD and NEO/USD forwarding test
性能仍然很好,指标接近回溯测试值:
总回报:0.040754467244888515
Sortino coef:8.20447014148
最大压降:-0.010029904921808908
我们可以通过排序比值来比较结果。
该战略的权益图是
Equity of the algorithm
进一步的问题讨论
- 对不同的资产进行大量实验,以创建可靠的资产组合,并在它们之间调整资金管理。它将允许获得更重要的统计数据,因为事务的数量将会更大。
- 尝试交叉货币对以降低交易成本(例如,用 XMR/NEO 代替 XMR/USD 和 NEO/USD)。
- 为投资组合中的每一对调整以下步骤协整检验—回测—前推,以在生产模式中获得更可靠的性能。用于调整的参数:历史长度、p 值阈值和算法参数。
- 创建当共同运动属性被破坏时停止算法的规则。如果没有预见到这一点,结果可能是一场灾难。
结论
- 描述了方法,并创建了算法交易策略。
- 该算法在回溯测试和转发测试中都取得了积极的结果。展示了不同的性能指标和图表。
- 就如何改进这项研究提出了建议。
- 源代码可以在 github 上得到。
最诚挚的问候,
谢尔盖
使用 Biopython 的成对序列比对
使用 Python 生物信息学工具检查两个序列有多相似
两个序列有多相似?
想要回答这个问题,你需要对序列比对有一个基本的了解。正如我在的上一篇文章、序列比对中描述的,序列比对是一种排列 DNA、RNA 或蛋白质序列以识别相似区域的方法。被鉴定的相似性可能是序列之间的功能、结构或进化关系的结果。
在这篇文章中,我将带你完成两两序列比对。此外,我们将使用一个名为 Biopython 的很酷的 python 工具尝试一些编码。
Figure 1: Pairwise Sequence Alignment using Biopython
什么是成对序列比对?
成对序列比对是序列比对技术的一种形式,这里我们只比较 两个序列 。这个过程包括找到两个序列之间的最佳比对,根据它们的相似性(它们有多相似)或距离(它们有多不同)进行评分,然后评估这个评分的显著性。
Figure 2: Image Scource: http://compbio.pbworks.com/w/page/16252912/Pairwise%20Sequence%20Alignment
评分
在继续进行成对序列比对技术之前,让我们看一下评分过程。
序列比对的基础在于评分过程,在该过程中,根据两个序列彼此相似(或不同)的程度给它们打分。成对序列比对算法需要一个评分矩阵来记录分配的分数。评分矩阵为匹配分配一个正分,为不匹配分配一个罚分。
分配分数时考虑三个基本方面。他们是,
- 匹配值 —分配给匹配字符的值
- 不匹配值 —分配给不匹配字符的值
- 空位罚分 —分配给空位的值
下面给出的图 3 显示了如何识别两个序列之间的匹配、错配和缺口。
Figure 3: Match, mismatch and gap
两个序列的第一个字符是匹配的**,因为两个都是字母 A 。第一个序列的第二个字符是 C ,第二个序列的第二个字符是 T 。所以,是不匹配。**
在第二个序列的末尾引入一个空格以匹配 g。这个空格被称为间隙**。间隙是给定比对中单个序列中最大的连续空格。**
一般来说,缺口被表示为缺口罚函数**,该函数将缺口的成本作为其长度的函数(可能是非线性的)来测量。**
成对序列比对的类型
考虑给你两个序列如下。
***X = x1 … xi … xn******Y = y1 … yj … ym***
- 全局比对:该方法在 2 个序列的整个长度上寻找最佳比对。序列 X 和 Y 的最大相似度是多少?
- 局部比对:该方法在两个序列中寻找最相似的子序列。 X 的一个子序列和 Y 的一个子序列的最大相似度是多少?
全球对齐
在该方法中,我们考虑 2 个序列的整个长度,并尝试将它们匹配以获得最佳比对。将gap**(空格)插入到 X 和 Y 中,直到两个序列的长度相同,这样两个序列就匹配了。**
例如,考虑序列 X = ACGCTGAT 和 Y = CAGCTAT 。一种可能的全局对准是,
**AC-GCTGAT
| || ||
-CAGC-TAT**
并不是说我们已经包含了 间隙 以便字符串对齐。
如果我们设置一个评分方案为匹配分数= 1 ,错配分数= 0 ,空位罚分= 0 ,那么上述比对的总分数将为:
Score = nMatch x 1 + nMismatch x 0 + nGap x 0
= 6x1 + 1x0 + 2x0
= 6
Needleman-Wunsch 算法
使用动态编程获得全局比对的算法之一是 Needleman-Wunsch 算法 。该算法由 Needleman 和 Wunsch 于 1970 年发表,用于两个蛋白质序列的比对,这是动态编程首次应用于生物序列分析。Needleman-Wunsch 算法寻找两个序列之间的最佳得分全局比对。
局部对齐
在这种方法中,我们考虑 2 个序列中每一个的子序列,并试图匹配它们以获得最佳比对。
例如,将两个序列视为 X=GGT CTGAT G 和 Y=AAA CGAT C。粗体字符是要考虑的子序列。最佳的局部对准是,
**CTGAT** (in X)
**| |||
C-GAT** (in Y)
这里,引入一个 缺口 以匹配 2 个子序列。
如果我们设置一个评分方案为匹配分数= 1 ,错配分数= 0 ,空位罚分= 0 ,那么上述比对的总分数为:
Score = nMatch x 1 + nMismatch x 0 + nGap x 0
= 4x1 + 0x0 + 1x0
= 4
史密斯-沃特曼算法
使用动态编程在两个给定序列内获得局部比对的算法之一是 Smith-Waterman 算法 。 Smith 和 Waterman 在 1981 年发表了一个动态规划的应用来寻找最优的局部排列。该算法类似于 Needleman-Wunsch 算法,但与评分过程略有不同。
在本文中,我们不会深入讨论上述两种算法的细节。
练习时间到了
既然我们有了关于成对序列比对的基本概念和两个有用的算法,现在是时候尝试一些编码了。
biopython——用于计算分子生物学的 python 工具
Figure 4: Biopython (http://biopython.org)
在这篇文章中,我将向你介绍一套工具,我们将使用它来处理以后的生物数据。 Biopython 是一套用 python 编写的工具,可用于各种生物计算、模拟和分析。
你可以从 这里 下载并安装 Biopython。确保您已经安装了 Python 2.7、3.4、3.5 或 3.6 。你可以参考 Biopython 教程和食谱 来进一步了解我们能做什么以及如何使用这些工具。
****bio . pairwise 2-P使用动态编程进行空中序列比对
让我们试用一些编码来模拟使用 Biopython 的成对序列比对。我将成对使用 模块,该模块可以在 Bio 包中找到。该模块提供了比对函数来获得两个序列之间的全局和局部比对。
对齐函数的名称遵循惯例;
**<alignment type>XX**
其中 <对准类型> 是全局或局部并且 XX 是一个 2 字符代码,表示它所采用的参数。第一个字符表示匹配(和不匹配)的参数,第二个字符表示空位罚分的参数。
****匹配参数为:
CODE DESCRIPTION
x No parameters. Identical characters have score of 1, else 0.
m A match score is the score of identical chars, else mismatch
score.
d A dictionary returns the score of any pair of characters.
c A callback function returns scores.
****间隙惩罚参数为:
CODE DESCRIPTION
x No gap penalties.
s Same open and extend gap penalties for both sequences.
d The sequences have different open and extend gap penalties.
c A callback function returns the gap penalties.
让我们使用 Bio.pairwise2 模块尝试几个成对序列比对的例子。
示例 1
考虑下面给出的两个序列。我们想找出所有可能的具有最大相似性得分的全局比对**。**
**X = ACGGGT
Y = ACG**
下面给出了获得给定两个序列的全局比对的 python 代码。请注意我们是如何使用 Bio.pairwise2 模块及其功能的。
Code Snippet 1: Pairwise sequence alignment (global)
通过运行代码,我们可以得到所有可能的全局比对,如图 5 所示。
Figure 5: Pairwise sequence alignment (global) output
在这个例子中,注意匹配的字符被给予 1 分。没有因不匹配或差距而扣分。
示例 2
考虑前面例子中给出的两个序列。我们想要找出所有可能的具有最大相似性得分的局部比对**。**
下面给出了获得给定两个序列的局部比对的 python 代码。
Code Snippet 2: Pairwise sequence alignment (local)
通过运行代码,我们可以得到所有可能的局部比对,如图 6 所示。
Figure 6: Pairwise sequence alignment (local) output
在这个例子中,注意匹配的字符被给予 1 分。没有因不匹配或差距而扣分。
示例 3
在本例中,我们将更改评分方案,并为匹配、不匹配和差距赋值。我们将考虑和以前一样的两个序列。我们想找出所有可能的具有最大相似性得分的全局比对**。**
匹配字符得 2 分,每不匹配一个字符扣 1 分。开一个缺口扣 0.5 分,延伸一个缺口扣 0.1 分。
Code Snippet 3: Pairwise sequence alignment (global with custom scoring)
通过运行代码,我们可以得到所有可能的全局比对,如图 7 所示。
Figure 7: Pairwise sequence alignment (global with custom scoring) output
希望你喜欢读这篇文章,并学到一些有用和有趣的东西。
因为我对这个领域还很陌生,所以我想听听你的建议。😇
感谢阅读…😃
熊猫数据框架:轻量级介绍
Introduction to Pandas → The Pandas DataFrame by @DakshHub
Pandas 是一个开源的、BSD 许可的库,为 Python 编程语言提供了高性能、易于使用的数据结构和数据分析工具。
Pandas 提供的数据结构有两种不同的类型
- 熊猫数据帧&
- 熊猫系列
我们将在本帖中查看 熊猫数据帧 。
学习熊猫(包括官方文档)的总趋势是先进入熊猫系列,再进入熊猫数据框。然而,在使用熊猫很长时间后,我确信我们应该从熊猫数据框架开始。一旦我们熟悉了熊猫数据框架,熊猫系列背后的概念和基本原理就会变得清晰易懂。
什么是数据帧?
这是技术定义的样子
Pandas DataFrame 是一个带有潜在不同类型列的二维标签数据结构。
你应该这样理解它
Pandas DataFrame 只不过是一个通过 Python 编程语言在内存中表示的 excel 表格
所以, 熊猫数据框 类似于 excel 表格,看起来是这样的
A Panda DataFrame ( An In-Memory representation of Excel Sheet)
就像 excel 一样,Pandas data frame提供了各种功能来分析、更改和从给定的数据集中提取有价值的信息。
如何创建熊猫数据框架?
在现实世界中,通过从持久存储中加载数据集,包括但不限于 excel、csv 和 MySQL 数据库,将创建一个Panda data frame。
然而,为了帮助你更好地理解它,我将在这里使用 Python 数据结构(字典和列表)。
如上面的 excel 表格所示,如果我们将列名视为 【键】 ,并将该列下的项目列表视为 【值】 ,我们可以轻松地使用 python 字典来表示相同的
my_dict = {
'name' : ["a", "b", "c", "d", "e","f", "g"],
'age' : [20,27, 35, 55, 18, 21, 35],
'designation': ["VP", "CEO", "CFO", "VP", "VP", "CEO", "MD"]
}
我们可以从这个字典中创建一个 熊猫数据帧 作为
import Pandas as pddf = pd.DataFrame(my_dict)
生成的数据框架应该类似于我们在上面的 excel 表格中看到的
Result of -> df = pd.DataFrame(my_dict)
有可能这些列没有按照字典中定义的顺序排列,因为 python 将字典实现为 hash,并且不保证保留顺序。
行索引→
由于我们没有向数据帧提供任何行索引值,它会自动生成一个序列(0…6)作为行索引。
为了提供我们自己的行索引,我们需要将DataFrame(...)
函数中的index
参数作为
df = pd.DataFrame(my_dict, index=[1,2,3,4,5,6,7])
索引不需要一直是数字,我们也可以通过字符串作为索引。例如
df = pd.DataFrame(
my_dict,
index=["First", "Second", "Third", "Fourth", "Fifth", "Sixth", "Seventh"]
)
正如您可能已经猜到的那样,索引本质上是*,这意味着我们也可以使用 NumPy 数组 作为索引。*
*np_arr = np.array([10,20,30,40,50,60,70])
df = pd.DataFrame(my_dict, index=np_arr)*
熊猫数据框的列
与 python 列表或字典不同,就像NumPy*,data frame的一列将始终是同一类型。*
我们可以使用类似字典的语法或者使用 DataFrame .
添加列名来检查列的数据类型
*df['age'].dtype # Dict Like Syntaxdf.age.dtype # DataFrame.ColumnName
df.name.dtype # DataFrame.ColumnName*
如果我们想检查数据框内所有列的数据类型,我们将使用 数据框 的dtypes
函数作为**
**df.dtypes**
它将所有列的类型显示为
Displaying Types of all Columns
查看数据帧的数据
在任何时间点, 熊猫数据帧 将包含数百(如果不是数千)行数据。我们只能在任何时间点选择性地查看它们。
为了有选择地查看行,我们可以使用 head(…)和 tail(…) 函数,这些函数默认给出前五行或后五行(如果没有提供输入),否则从顶部或底部显示具体的行数
下面是它显示内容的方式
**df.head() # Displays 1st Five Rows**
df.head()
**df.tail() # Displays last Five Rows**
df.tail()
**df.head(2) # Displays 1st two Rows**
df.head(2)
**df.tail(7) # Displays last 7 Rows**
df.tail(7)
这都是关于数据的,但是,如果我们想看到行索引和列名呢? 熊猫数据框 提供了查看它们的特定功能
**df.index # For Row Indexesdf.columns # For Columns**
熊猫数据框架列助手函数
Pandas data frame提供了各种列助手函数,对于从列中提取有价值的信息非常有用。其中一些是
unique
→通过删除重复项来提供列中的唯一元素。例如
**df.designation.unique()**
mean
→提供该列中所有项目的平均值。例如
**df.age.mean()**
使用列作为行索引
大多数情况下,给定的数据集已经包含一个行索引。在那些情况下,我们不需要Pandas data frame来生成单独的行索引。
这不仅是一个冗余信息,而且占用了不必要的内存。
Pandas DataFrame 允许将任何现有列或一组列设置为行索引。下面是如何使用前面创建的 熊猫data frame的列(使用字典my_dict
**df = pd.DataFrame(my_dict)df.set_index("name")**
df.set_index(“name”)
**df.set_index("age")**
df.set_index(“age”)
我们可以通过传递一个列表将多个列设置为索引
**df.set_index(["name","age"])**
df.set_index([“name”,”age”])
在数据框架中加载选择的列
任何数据分析活动都需要数据清理,我们很可能会得出结论,从需要分析的数据集中排除一些列。
这不仅节省了内存,而且有助于分析感兴趣的数据
我们将使用相同的字典来加载Pandas DataFrame**,但是这次我们将指定将成为 data frame 一部分的列**
**df = pd.DataFrame(my_dict, columns=["name", "age"])**
df = pd.DataFrame(my_dict, columns=[“name”, “age”])
从数据帧中删除行和列
熊猫 DataFrame 提供了多种删除行和列的方式。选择一个而不是另一个并没有功能上的损失。你可以使用任何你觉得舒服的语法。
使用字典语法→要删除一列,我们就用 ***del***
作为
**del df['name']**
使用 ***Drop***
功能→允许我们删除列以及行
我们是删除行还是列由drop
函数中的第二个参数决定。
函数
drop(...)
中的第二个参数“1”表示删除“列”,而“0”表示删除“行”
**# Delete Column "age"df.drop('age',1)# Delete the Row with Index "3"df.drop(3,0)**
我们也可以通过在
drop(...)
函数中传递列表来删除多行和多列
**# Delete Columns "name" & "age"df.drop(['name','age'],1)# Delete Rows with index "2","3", & "4"df.drop([2,3,4],0)**
注意:行索引不是索引号,而是包含该值的行
从列表中创建熊猫数据帧
如果我们得到一个没有任何列的数据集呢?
嗯,Pandas DataFrame并不介意这一点,它通过为我们隐式添加行索引和列标题来生成 data frame。
例如,如果我们从下面的列表中创建一个数据帧
**my_list = [[1,2,3,4],
[5,6,7,8],
[9,10,11,12],
[13,14,15,16],
[17,18,19,20]]df = pd.DataFrame(my_list)**
它看起来会像这样
df = pd.DataFrame(my_list)
如果我们不想让Pandas data frame自动生成行索引和列名,我们可以将这些在DataFrame
函数中作为
**df = pd.DataFrame(
my_list,
index = ["1->", "2->", "3->", "4->", "5->"],
columns = ["A", "B", "C", "D"]
)**
这是它看起来的样子
df with Row and Column Provided
应该注意的是,我们也可以从 NumPy 数组创建 Pandas 数据帧,如下所示
**np_arr = np.array([[1,2,3,4],
[5,6,7,8],
[9,10,11,12],
[13,15,16,16],
[17,18,19,20]])df = pd.DataFrame(np_arr)**
数据帧上的数学运算
就像 Excel 表格一样, 熊猫数据框 在完整的 数据框 上轻松进行数学运算。
在一个单独的列中完成这些操作是可能的,这就是熊猫系列出现的原因。
我们将在下一篇文章中研究熊猫系列,让我们先看看数学运算是如何在完整的 数据帧 上工作的
乘法→我们可以将标量值为的数据帧与另一个数据帧 相乘
**df * df**
df * df
**df * 10**
df * 10 ( A Scalar Value)
加法/减法→与上面的乘法类似,一个数据帧可以与一个标量值或另一个数据帧 相加/相减
**df + 100**
df + 100
位运算→可以进行位运算(AND( &)、OR (|))等来完成数据帧
**df & 0**
df & 0
熊猫系列是什么?
除了熊猫数据框架的一列之外,什么也没有的系列。
每当我们要处理一个以上的系列时,我们就有数据框架。
二者择一地
熊猫数据框是熊猫系列的集合
我会在下一篇文章中谈论 熊猫系列
感谢阅读…!!!!
达克什
熊猫数据帧:使用 CSV 文件
Pandas DataFrame: Playing with CSV files
CSV 代表逗号分隔值,这是一种在持久性存储中表示和存储面向表格、列的数据的流行方式
Pandas DataFrames 通常用于表示内存中类似 Excel 的数据。在大多数情况下,我们很可能会从持久存储中加载数据,持久存储可以是数据库或 CSV 文件。
在这篇文章中,我们将会看到如何使用 Pandas DataFrame 加载、存储和播放 CSV 文件
概述熊猫数据框架
我已经写了一篇名为熊猫数据框架:轻量级介绍的详细文章。如果你对熊猫数据框架不满意,我强烈建议你在继续这篇文章之前先看看这篇文章。
简而言之,Pandas DataFrame 只不过是 excel 之类的数据在内存中的表示。举个例子,
Pandas DataFrame → Excel like Data in Memory
该数据也可以使用 Python 字典表示为
my_dict = { 'name' : ["a", "b", "c", "d", "e","f", "g"],
'age' : [20,27, 35, 55, 18, 21, 35],
'designation': ["VP", "CEO", "CFO", "VP", "VP", "CEO", "MD"]}
我们知道我们可以通过调用DataFrame(...)
函数从 python 字典中创建一个熊猫数据帧
df = pd.DataFrame(my_dict)
生成的数据帧应如下所示
Pandas DataFrame → From Python Dictionary
将数据帧保存到 CSV 文件中
一旦我们有了数据帧,我们可以将它保存在本地磁盘上的 CSV 文件中。让我们首先使用数据帧中当前存在的数据创建我们自己的 CSV 文件,我们可以使用 Pandas 数据帧的 APIto_csv(...)
以 CSV 格式存储该数据帧的数据
df.to_csv('csv_example')
现在我们有了 CSV 文件,它包含了上面数据帧中的数据。
正如我们可以将数据帧保存在 CSV 文件中一样,我们也可以从 CSV 文件中加载数据帧。
让我们继续加载 CSV 文件,并从中创建一个新的数据帧
df_csv = pd.read_csv('csv_example')
生成的数据帧(df_csv)应如下所示
df_csv
你注意到不寻常的事情了吗?
嗯,我们可以看到这个索引生成了两次,第一次是从 CSV 文件加载的,而第二次,也就是Unnamed
是熊猫在加载 CSV 文件时自动生成的。
这个问题可以通过确保 CSV 文件的写入不写索引来避免,因为DataFrame
无论如何都会生成。我们可以通过在to_csv(...)
函数中指定index = False
参数来做同样的事情
df.to_csv('csv_example', index=False)
现在,如果我们把文件读成
df_csv = pd.read_csv('csv_example')
生成的数据帧应如下所示
df_csv
现在,您可以看到输出类似于我们之前从 python 字典创建数据帧时的输出,这是我们所期望的。
玩弄列标题
正如我们已经看到的,第一行总是被认为是列标题,但是,通过在read_csv(...)
函数中指定一个名为header=<integer>
的参数,可以有多行作为列标题。
默认情况下,该值被指定为“0”,这意味着第一行将被视为标题。
df_csv = pd.read_csv('csv_example', header = 0)
结果输出将与上面相同。然而,它提供了很多机会来安排头球。例如,我们也可以将多行作为标题
df_csv = pd.read_csv('csv_example', header=[0,1,2])
生成的数据帧应如下所示
df_csv → with 3 rows as Header
正如我们在这里看到的,列 0、1 和 2 现在是标题。
也没有必要将第一行序列作为标题,我们可以跳过前几行,然后从特定的行开始查看表格
例如
df_csv = pd.read_csv('csv_example', header=5)
这里,产生的数据帧应该看起来像
df_csv → After skipping 5 rows
唯一的缺点是我们必须放弃标题行号之前的可用数据。它不能是结果数据帧的一部分。
即使在标题为多行的情况下,实际数据帧数据也只能从最后一个标题行之后的行开始。
df_csv = pd.read_csv('csv_example', header=[1,2,5])
产生的数据帧将从行“6”开始,看起来应该像这样
df_csv → Multiple Row Headers
自定义列名
尽管我们从带有列标题的 CSV 文件中读取数据,但我们仍然可以拥有自己的列名。我们可以通过在read_csv(...)
中添加一个名为names
的参数来达到同样的效果
df_csv = pd.read_csv('csv_example', names=['a', 'b', 'c'])
生成的数据帧应如下所示
df_csv → with our own column names
然而,即使我们成功地添加了自己的标题,顶行仍然显示一个不需要的标题。
这可以通过使用read_csv(…)
中的header
参数跳过描述标题的行来避免。在这种特殊情况下,我们知道第一行,即第 0 行是标题,所以我们可以跳过它
df_csv = pd.read_csv('csv_example', names=['a', 'b', 'c'], header=1)
df_csv → With Customised Header
现在,我们得到了我们想要的带有定制头的输出。
另一种方法是在将 CSV 文件写成
df.to_csv('csv_example', index=False, header = False)
阅读时,我们可以不跳过标题
df_csv = pd.read_csv('csv_example', names=['AGE', 'DESIGNATION', 'NAME'])
df_csv → With customised header
CSV 到(任何)分隔值
虽然逗号分隔的值是众所周知的,但是read_csv(...)
函数可以识别逗号以外的分隔符。
唯一的区别是,我们需要在函数中显式传递分隔符,而默认情况下使用逗号
让我们首先使用不同的分隔符创建一个 CSV 文件,即“:”(冒号)
df.to_csv('csv_example', index=False, sep=":")
这将创建一个文件,其中冒号(‘:’)而不是逗号(‘,’)将用作分隔符。我们可以这样阅读文件
df_csv = pd.read_csv('csv_example', sep=":")
生成的数据帧应如下所示
df_csv → with “:” as separator
设置行索引
默认情况下,Pandas DataFrame 会自动生成一个行索引,我们可以通过将任何列设置为索引来进行更改
df_csv.set_index('age')
下面是结果数据帧的样子
df_csv → Using ‘age’ as row index
以这种方式设置索引是一种后期操作。也就是说,我们已经有了一个带有预定义索引的数据框架,但是我们后来又改变了它。
我们可以在加载 CSV 文件时通过传递一个名为index_col
的参数来做到这一点,该参数将自动分配由index_col
描述的列作为行索引。
df_csv = pd.read_csv('csv_example', sep=":", index_col=1)
同样的输出应该看起来像
df_csv → with index_col = 1
我们甚至可以提供一个以上的index_col
作为索引来对待
df_csv = pd.read_csv('csv_example', sep=":", index_col=[0,2])
输出将会是这样的
df_csv → index_col = [0,2]
如果不需要所有的行…不要加载它们
大多数情况下,CSV 文件都相当大,加载时可能会遇到内存限制。有一个选项,只从它加载选定的几行。
您可以通过在read_csv(...)
中传递一个参数nrows
来指定要加载的行数
# Load Only 3 Rows
df_csv = pd.read_csv('csv_example', sep=":", nrows=3)
这是它看起来的样子
df_csv → Loading only 3 Rows
跳过 CSV 文件中的空行
默认情况下,
read_csv(...)
函数跳过空行,即在加载文件和构建数据帧时会忽略空行。
但是,如果您想要加载空行来进行一些显式的计算,比如对空记录进行计数,您应该将跳过的空行标记为False
df_csv = pd.read_csv('csv_example', skip_blank_lines=False, sep=":")
这就是这篇文章的全部内容
感谢阅读…!!!
达克什
熊猫系列:轻量级介绍
Pandas Series: A Lightweight Intro
Pandas 是一个开源的、BSD 许可的库,为 Python 编程语言提供了高性能、易于使用的数据结构和数据分析工具。
Pandas 提供的数据结构有两种不同的类型
- 熊猫数据帧&
- 熊猫系列
本帖我们就来看看 熊猫系列 。
注:为了更好地理解熊猫系列之前,我强烈推荐阅读我之前在 上的帖子
什么是系列?
从技术上来说,Pandas Series 是一个一维标签数组,能够保存任何数据类型。
通俗地说,熊猫系列不过是 excel 表中的一列。如下图所示,带有名称、年龄和职务的列代表一个系列
Pandas Series
因此,根据 Pandas 数据结构,一个系列代表内存中的一个单独的列,它或者是独立的,或者属于 Pandas 数据帧。
注意:一个系列可以有自己独立的存在,而不是数据帧的一部分。
如何打造系列?
Pandas 系列可以从 Python 列表或 NumPy 数组中创建。必须记住,与 Python 列表不同,一个系列将总是包含相同类型的数据。这使得 NumPy 数组成为创建熊猫系列的更好的候选对象
下面是我们如何使用以上两者来创建一个熊猫系列
series_list = pd.Series([1,2,3,4,5,6])
series_np = pd.Series(np.array([10,20,30,40,50,60]))
这是它们的样子
Result of → series_list = pd.Series([1,2,3,4,5,6])
Result of → series_np = pd.Series(np.array([10,20,30,40,50,60]))
正如在创建熊猫数据帧时一样,该系列也默认生成行索引号,这是一个从‘0’开始的递增数字序列
正如您可能已经猜到的,在创建一个系列时,有可能拥有我们自己的行索引值。我们只需要传递索引参数,这些参数接受相同类型的列表或 NumPy 数组。
以下示例使用了 NumPy 生成的序列
series_index = pd.Series(
np.array([10,20,30,40,50,60]),
index=np.arange(0,12,2)
)
Result of → series_index = pd.Series(np.array([10,20,30,40,50,60]), index=np.arange(0,12,2) )
下面的示例使用字符串作为行索引
series_index = pd.Series(
np.array([10,20,30,40,50,60]),
index=['a', 'b', 'c', 'd', 'e', 'f' ]
)
Result of → series_index = pd.Series(np.array([10,20,30,40,50,60]), index=[‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’ ] )
我们可以使用序列的行索引作为
series_index.index
它返回一个 NumPy 数组,而不管我们在创建序列时是传递了一个列表还是一个 NumPy 数组
从 python 字典创建熊猫系列
正如我们在创建 Pandas DataFrame 的过程中所看到的,从 python 字典创建 DataFrame 非常容易,因为键映射到列名,而值对应于列值列表。
那么在创作熊猫系列的时候是如何贴图的呢?
如果我们从 python 字典创建一个序列,那么键成为行索引,而值成为该行索引的值。
作为一个例子,让我们看看一个非常简单的只有一个键值对的字典会发生什么
t_dict = {'a' : 1, 'b': 2, 'c':3}# Creating a Series out of above dict
series_dict = pd.Series(t_dict)
这是输出的样子
Result of → Code block Above
如果字典中的值包含一个项目列表,情况不会改变。列表项仍然是单行索引的一部分,如下例所示
t_dict = {'a' : [1,2,3], 'b': [4,5], 'c':6, 'd': "Hello World"}# Creating a Series out of above dict
series_dict = pd.Series(t_dict)
Result of → series_dict = pd.Series(t_dict)
从熊猫数据帧中获取序列
虽然 Pandas Series 本身对于进行数据分析非常有用,并提供了许多有用的帮助函数,但是大多数时候,分析需求将迫使我们一起使用 DataFrame 和 Series。
让我们先创建一个熊猫数据帧,就像我们在这里创建的一样
my_dict = {
'name' : ["a", "b", "c", "d", "e"],
'age' : [10,20, 30, 40, 50],
'designation': ["CEO", "VP", "SVP", "AM", "DEV"]
}df = pd.DataFrame( my_dict,
index = [
"First -> ",
"Second -> ",
"Third -> ",
"Fourth -> ",
"Fifth -> "])
下面是结果数据帧的样子
Result of → DataFrame creation from dictionary
DataFrame 提供了两种访问列的方法,即使用字典语法df['column_name']
或df.column_name
。每次我们使用这些表示得到一个列,我们得到一个熊猫系列。
在上面的例子中,我们可以通过访问列来获得序列(即一个单独的列)
series_name = df.name
series_age = df.age
series_designation = df.designation
series_name
Series_age
series_designation
通过遍历数据帧的列来获取序列
如果我们不知道列的名称会怎么样?
Pandas DataFrame 是可迭代的,我们可以遍历各个列来获得序列
series_col = []
for col_name in df.columns:
series_col.append(df[col_name])
使用系列创建数据框(独立或组合)
熊猫数据帧只不过是一个系列(1+)的集合。我们可以通过使用单个系列或组合多个系列来生成数据帧
例如,让我们通过组合series_name
和series_age
生成一个数据帧
df_from_series = pd.DataFrame([series_name, series_age])
令您惊讶的是,生成的数据帧看起来应该是
df_from_series
是的,序列的行索引成为列,而列成为行索引值。你可以认为这类似于矩阵的转置。即使我们提供单个系列来创建数据帧,也是如此
df_from_series_single = pd.DataFrame([series_name])
df_from_series_single
然而,当我们从序列中移除列表/数组符号时,这种情况不会发生。例如
df_from_series_single = pd.DataFrame(series_name)
将导致序列列名和行索引的保留
df_from_series_single
注意:不幸的是,这仅限于一个系列,因为 DataFrame API 不接受一个以上的系列参数
用 Python 字典创建数据帧的行为
当我们将 python 字典作为数组传递来创建 DataFrame 时,也会观察到同样的行为。让我们看看我们之前创建的t_dict = {'a': 1, ‘b’: 2, ‘c’:3}
ds = pd.DataFrame([t_dict])
得到的数据帧应该看起来像这样
ds
其中键被表示为列,否则如果我们创建了一个序列,它们将被表示为行索引
我们甚至可以组合多个t_dict
来创建一个数据帧
ds = pd.DataFrame([t_dict, t_dict ], index=[1,2])
ds
系列助手功能
就像熊猫 DataFrame 一样,Series 也有多组帮助器函数用于数据分析。
请注意,Pandas DataFrame 的所有列助手功能都将适用于 Pandas 系列。一些例子是
#Getting the mean of a Series
series_age.mean()# Getting the size of the Series
series_age.size# Getting all unique items in a series
series_designation.unique()# Getting a python list out of a Series
series_name.tolist()
迭代序列
就像 python 中的许多其他数据结构一样,可以使用一个简单的 for 循环来迭代序列
for value in series_name:
print(value)
我们还可以迭代索引为
for row_index in series_name.keys():
print(row_index)
熊猫系列的基本用法就这些了。
感谢阅读…!!!
达克什
熊猫的提示和技巧
这篇文章包括一些有用的提示,告诉你如何使用 Pandas 对大型数据集进行有效的预处理和特征工程。
熊猫 Ufuncs 以及为什么它们比应用命令好得多
Pandas 有一个应用函数,可以让你对一列中的所有值应用任何函数。注意,应用比循环的 python 快一点点!这就是为什么最推荐使用 pandas builtufuncs对列应用预处理任务(如果有合适的 ufunc 可用于您的任务)。Ufuncs,是用 C 实现的特殊函数(基于 numpy 库),这也是它们高效的原因。我们将提到的有用的 ufuncs 有:。差异,。移位,。累计。累计,。str 命令(作用于字符串),。dt 命令(作用于日期)等等。****
示例数据集—夏季活动
我将用不同的人名、它们的夏季活动和它们相应的时间戳来演示熊猫的把戏。一个人可以在不同的时间戳中进行多个活动。
Randomly generated data with summer activities
假设我们的目标是预测,基于给定的数据集,谁是数据集中最有趣的人:)。
Fun Fun Fun!
1.字符串命令
对于字符串操作,最推荐使用 Pandas 字符串 命令(它们是ufunc)。****
例如,您可以使用 .str.split 和 expand=True 将包含一个人的全名的列拆分为包含名和姓的两列。
Name column before split
df[‘name’] = df.name.str.split(" ", expand=True)
Name column after split
此外,您可以使用 .str.replace 和合适的 regex 有效清洁任何管柱。
2.分组依据和值计数
Groupby 是一个非常强大的熊猫方法。您可以按一列分组,并使用 value_counts 对另一列的值进行计数。使用 groupby 和 value_counts 我们可以计算每个人做了多少活动。
df.groupby('name')['activity'].value_counts()
Group by person name and value counts for activities
这是多索引,pandas 数据框架中的一个有价值的技巧,它允许我们在数据框架中有几级索引层次。在这种情况下,人名是索引的第 0 层,而活动在第 1 层。
3。拆垛
我们还可以通过在上面的代码中应用 unstack 来为每个人的夏季活动计数创建特性。取消堆叠将行切换到列,以获取活动计数作为特征。通过执行 unstack ,我们将索引的最后一级转换为列。所有的活动值现在将成为数据帧的列,当一个人没有进行某项活动时,该功能将获得一个值。 Fillna 用 0 填充所有这些缺失的值(人员没有访问的活动)。
df.groupby('name')['activity'].value_counts().unstack().fillna(0)
Activity count in columns
3.groupby、diff、shift 和 loc +提高效率的绝佳技巧
了解个人活动之间的时差对于预测谁是最有趣的人来说是非常有趣的。一个人在聚会上混了多久?他/她在海滩逗留了多长时间?这可能对我们有用,取决于活动。
计算时差的最直接的方法是通过人名对分组,然后使用 diff 计算时间戳字段的时差()😗***
df = df.sort_values(by=['name','timestamp'])
df['time_diff'] = df.groupby('name')['timestamp'].diff()
Calculating the time difference between person activities to get the duration of each activity
如果你有很多数据,并且你想节省一些时间(根据你的数据大小,这可以快 10 倍左右),你可以跳过 groupby ,在对数据排序后只做 diff ,然后删除不相关的每个人的第一行。
df = df.sort_values(by=['name','timestamp'])
df['time_diff'] = df['timestamp'].diff()
df.loc[df.name != df.name.shift(), 'time_diff'] = None
BTW —有用的。Shift** 命令将所有列向下移动一个空格,这样我们就可以看到该列在哪一行发生了变化:df.name!=df.name.shift()。**
还有。loc** 命令是为特定索引设置列值的最推荐方法。**
要将 time_diff 更改为秒单位:
df['time_diff'] = df.time_diff.dt.total_seconds()
要获得每行的持续时间:
df[‘row_duration’] = df.time_diff.shift(-1)
Added duration per row
4.累计和累计
这是两个非常酷的 Ufuncs,可以帮助你做很多事情。累计计数创建累计计数。例如,我们可以通过按人名分组,然后应用累计,只对每个人进行第二项活动。这将只是按顺序对活动进行计数。然后,我们可以通过 do = = 1(或通过 do = = 2 的第三个活动)并在原始排序的数据帧上应用索引,为每个人仅获取第二个活动。
df = df.sort_values(by=['name','timestamp'])df2 = df[df.groupby(‘name’).cumcount()==1]
The second activity of each person
df = df.sort_values(by=[‘name’,’timestamp’])df2 = df[df.groupby(‘name’).cumcount()==2]
The third activity of each person
累计只是一个数值单元格的累计汇总。例如,您可以将一个人在每项活动中花费的钱添加为附加单元格,然后使用以下公式汇总一个人在一天中每个时间花费的钱:
df = df.sort_values(by=[‘name’,’timestamp’])df['money_spent_so_far'] = df.groupby(‘name’)['money_spent'].cumsum()
Money spent so far
5.用于测量活动持续时间的 groupby、max、min
在第 3 部分,我们想知道每个人在每项活动中花费了多少时间。但是我们忽略了有时我们会得到一个活动的多个记录,而这个活动实际上是相同活动的继续。因此,为了获得实际的活动持续时间,我们应该测量从第一个连续活动出现到最后一个活动出现的时间。为此,我们需要标记活动的变化,并用活动编号标记每一行。我们将使用来做这件事。换档命令和。我们之前看到的 cumsum** 命令。新活动是指活动发生变化或时,人员发生变化。**
df['activity_change'] = (df.activity!=df.activity.shift()) | (df.name!=df.name.shift())
然后,我们将通过对每个用户进行分组并应用 glorious 来计算每行的活动数量。累计值:
df['activity_num'] = df.groupby('name')['activity_change'].cumsum()
Add activity num for the activities which continues between rows
现在,我们可以按如下方式计算每个活动的持续时间:按名称和活动编号(以及活动—这并不真正改变分组,但我们需要它具有活动名称)分组,并计算每行活动持续时间的总和:
activity_duration = df.groupby(['name','activity_num','activity'])['activity_duration'].sum()
activity duration
这将返回某种 timedelta 类型的活动持续时间。您可以使用. dt.total_seconds 获得以秒为单位的会话活动持续时间:
activity_duration = activity_duration.dt.total_seconds()
然后,您可以使用如下命令计算每个人的最大/最小活动持续时间(或中位数或平均值):
activity_duration = activity_duration.reset_index().groupby('name').max()
Maximal activity duration per user
摘要
这是一个短期的熊猫旅行,使用了一个夏季活动的数据集。希望你已经学会并喜欢它。祝你的下一个熊猫项目好运,享受这个夏天!
熊猫变了——不仅仅是看上去那样
最近我一直在和熊猫一起工作。在做一个项目时,我遇到了一个我以前不知道的漂亮的函数,经过询问,似乎我不是唯一一个错过的人,所以让我们补救一下。
首先,让我们回顾一下基础知识。
拆分—应用—合并
这是一种常见的方法。我们希望根据某些标准将数据分组,然后将我们的逻辑应用于每个组,最后将数据组合回单个数据框中。让我们看看我们的数据。我们有两家不同公司的几名员工的年薪:
Well researched data, aka I made it up.
“应用”阶段的一个众所周知的函数是 aggregate(或 agg)。当你可以把那些讨厌的细胞压缩成一个的时候,为什么还要有它们呢?使用 aggregate,您可以对数据求和、求平均值或任何其他此类计算,如下所示:
mean_salary = df.groupby('Company')['Yearly Salary'].\
aggregate('mean').rename("Mean Salary").reset_index()
您甚至可以为每列指定不同的功能!
在任何情况下,结果都是组中的每一列都减少为一个数据单元格。现在,为了将它组合回我们的数据帧,我们需要使用 merge。
df1 = df.merge(mean_salary)
我们可以在“应用”阶段使用的另一个功能是(惊喜!)应用功能。它允许我们对数据框中的一列(或一行)应用任何我们想要的函数。它可以是 lambda 函数,也可以是我们在别处定义的函数。这一次,数据没有减少,而是对每个单元格分别进行操作:
df['Yearly Salary K'] = df['Yearly Salary'].apply(lambda x: x*1000)
当我遇到一个问题时,我已经愉快地使用这些功能有一段时间了。我有想要拆分、运行一些逻辑并重新组合的数据,但我不想减少数据或单独运行每一行。相反,我希望对每组中我的列的每个单元格进行一些计算,并返回一个考虑到整个组的结果。数据的大小需要保持不变。
长话短说——在与这个问题纠缠了一会儿之后,一个队友告诉我去查一下 aggregate 的一个不太出名的表亲 transform。答对了。
改变
让我们看看变换是如何工作的:
df.groupby('Company').transform('mean')
我们得到的不是减少结果,而是与原始数据大小相同的结果。这使得组合数据变得非常简单。让我们添加另一行来展示我们可以做些什么:
df['avg_company_salary'] = df.groupby('Company').transform('mean')
df['is_above_avg_salary'] = \
df['avg_company_salary'] < df['Yearly Salary']
正如我们之前所展示的,在这个具体的例子中,您可以使用 aggregate 和 merge 来完成相同的结果,但是关于 transform 很酷的一点是,您可以在一个步骤中完成它。
我希望您也会发现转换函数很有用,并且您很快就会有机会使用它!
©Hasbro
对 git 也感兴趣吗?阅读我的帖子 Git:升级来提升你的 Git 游戏。
计算生物学中机器学习的十个快速提示
Gif from here
所以今天,我不想做一些技术性的东西。我发现了这篇由大卫写的论文计算生物学中机器学习的十个快速技巧。因此,让我们深入研究生物学中机器学习的十个技巧吧!
提示 1:检查并合理安排你的输入数据集
因此,在第一部分,作者建议,拥有足够的数据来实际上使机器学习模型正常工作。以及一些其他方法,例如随机混洗给定的数据。最后,作者建议,如果你有足够的数据,去除一个离群值,当你没有足够的数据时,将离群值四舍五入到上限。
提示 2:将你的输入数据集分成三个独立的子集(训练集、验证集、测试集)
很标准的方法来分割数据集,分成三个不同的数据集。训练、验证和测试集。作者还说,不要试图用训练阶段的测试数据来欺骗自己,以达到更高的准确率。
提示 3:将你的生物学问题纳入正确的算法范畴
这一部分可以总结为一句话,根据你的数据,你必须选择使用监督学习或无监督学习方法。这是一个有趣的部分,但是我要补充的是,可能有一些问题可以通过生物学中的强化学习或半监督学习来解决。
技巧四:应该选择哪个算法开始?最简单的一个!
作者推荐使用 K-均值聚类的无监督学习方法,和 K-最近邻的监督学习问题。我也认为最简单的解决方案是最优雅的解决方案。
提示 5:处理不平衡数据问题
在这里,作者建议确保你的数据集是适当平衡的。如果不是这样,作者也给了我们一个非常简单的规则,可以抵消这种差异。也就是 50%平均法则。
例如,如果你的数据中有 90%的反面例子,10%的正面例子。
通过使用如上所示的 50%平均规则,您可以获得将多少数据放入您的模型的良好比率。
提示 6:优化每个超参数
再次总结,用你的数据集做很多实验,选择最佳的超参数。
提示 7:最小化过度装配
所以,提示的标题说明了一切,要意识到过度合身的问题,并尽量减少它。我的建议是,也要注意不合身。
提示 8:用马修斯相关系数(MCC)或精确召回曲线评估你的算法性能
作者建议使用不同的度量系统来正确评估你的算法。这些指标包括准确性、F1 分数、MCC、召回率、脱落率、精确度、ROC 曲线和精确度-召回率曲线。
提示 9:用开源代码和平台来编写你的软件
总结:使用 python、R、IBM Spss 等开源软件。
提示 10:向计算机科学专家或在线社区寻求反馈和帮助
在 Reddit 或任何行业专家领域(甚至在媒体上)询问你的算法在给定数据集上的表现如何。
最后的话
这篇文章对于机器学习社区的初学者来说是一个很好的概述。
如果发现任何错误,请发电子邮件到 jae.duk.seo@gmail.com 给我,如果你想看我所有写作的列表,请在这里查看我的网站。
同时,在我的 twitter 这里关注我,并访问我的网站,或我的 Youtube 频道了解更多内容。如果你感兴趣的话,我还做了解耦神经网络的比较。
参考
- 奇科博士(2017)。计算生物学中机器学习的十个快速技巧。生物数据挖掘,10(1)。doi:10.1186/s 13040–017–0155–3
论文复制:使用“MAML”和“爬行动物”进行深度元学习
Source: imgur
在这篇文章中,我复制了最近在元学习领域的两篇论文: MAML 和类似的爬行动物。这个复制的完整笔记本可以在这里找到。
这两篇论文的目标都是解决 K-shot 学习问题。在 K-shot 学习中,我们需要训练一个神经网络来基于非常少量的例子(通常在 10 个左右的数量级)进行归纳,而不是我们在 ImageNet 等数据集中看到的通常成千上万的例子。
然而,在为 K-shot 学习做准备时,你可以就许多类似的 K-shot 问题进行训练,以学习仅基于 K 个示例进行归纳的最佳方式。
这就是学学或元学。我们已经在我的文章“通过梯度下降学习学习”中看到了元学习,你可以在这里找到:
这篇文章是一系列深度学习论文复制文章的第一篇。
becominghuman.ai](https://becominghuman.ai/paper-repro-learning-to-learn-by-gradient-descent-by-gradient-descent-6e504cc1c0de)
爬行动物和 MAML 的元学习方法都是为神经网络提出一个初始化,这个初始化很容易推广到类似的任务。这与“通过梯度下降学习”不同,在“梯度下降学习”中,我们不是在学习初始化,而是在学习优化器。
迁移学习
这种方法非常类似于迁移学习,其中我们在比如说 ImageNet 上训练一个网络,后来证明,微调这个网络可以很容易地学习另一个数据少得多的图像数据集。事实上,迁移学习可以被视为元学习的一种形式。事实上,它可以用来从非常小的数据集学习,正如你在这里看到的。
这里的区别在于,最初的网络是以易于推广为明确目的进行训练的,而迁移学习只是“偶然”发生作用,因此可能不会最佳地发挥作用。
事实上,很容易找到迁移学习无法学习到好的初始化的例子。为此我们需要看一下 1D 正弦波回归问题。
在这个 K-shot 问题中,每个任务包括学习一个修改的正弦函数。具体来说,对于每个任务,底层函数的形式将是 y = a sin(x + b) ,随机选择 a 和 b ,我们的神经网络的目标是学习仅基于 10 (x,y)对找到给定的 x 的 y 。
让我们绘制几个正弦波任务示例:
3 random tasks
为了理解为什么这将是迁移学习的一个问题,让我们画出其中的 1000 个:
1,000 random tasks
至少可以说,看起来每个 x 值都有很多重叠…
由于跨多个任务的每个 x 有多个可能的值,如果我们训练单个神经网络同时处理多个任务,它的最佳选择将只是返回每个 x 跨所有任务的平均 y 值。
Average value for each x, with random task shown for scale
平均值基本上是 0,这意味着一个经过大量任务训练的神经网络在任何地方都会返回 0!不清楚这是否真的会有很大帮助,然而这个是在这种情况下的迁移学习方法…
让我们通过实际实现一个简单的模型来解决这些正弦波任务,并使用迁移学习来训练它,来看看它做得有多好。首先,模型本身:
你会注意到它是以一种奇怪的方式实现的(什么是“可修改模块”?什么是“梯度线性”?).这是因为我们稍后将使用 MAML 来训练它。关于这些类的细节,请查看笔记本,但是现在你可以假设它们类似于 nn。模和线性神经网络。
现在,让我们按顺序对它进行一系列不同的随机任务的训练:
下面是当我们试图将这个转移模型微调到一个特定随机任务时发生的情况:
Transfer learning on a specific random task
基本上,看起来我们的传递模型学习了一个常量函数,很难将它微调到更好的状态。甚至不清楚我们的迁移学习是否比随机初始化更好……的确不是!随着时间的推移,随机初始化最终会比微调我们的传输模型获得更好的损失。
Learning curve for transfer learning vs random initialization
MAML
我们现在来看 MAML,这是我们今天要看的两个算法中的第一个。
如前所述,我们试图找到一组权重,以便在类似的任务上运行梯度下降可以尽可能快地取得进展。MAML 通过运行梯度下降的一次迭代,然后根据一次迭代朝着真正的任务前进了多少来更新初始权重,非常严格地执行了这个*。更具体地说,它:*
- 创建初始化权重的副本
- 对副本上的随机任务运行梯度下降迭代
- 通过梯度下降的迭代反向传播在测试集合上的损失,并返回到初始权重,以便我们可以在它们更容易更新的方向上更新初始权重。
因此我们需要一个梯度的梯度,也就是这个过程中的二阶导数。幸运的是,这是 PyTorch 现在支持的东西,不幸的是,PyTorch 使更新模型的参数变得有点笨拙,我们仍然可以通过它们运行梯度下降(我们已经看到这是“通过梯度下降学习学习”),这解释了模型编写的奇怪方式。
因为我们将使用二阶导数,我们需要确保允许我们计算原始梯度的计算图保持不变,这就是为什么我们将create_graph=True
传递给.backward()
。
那么它是如何在特定的随机任务中发挥作用的呢?
Training on a random function using MAML
哇,那好多了,甚至在梯度下降一步后,正弦形状开始可见,10 步后,波的中心几乎完全正确。这是否反映在学习曲线上?是啊!
不幸的是,有点烦人的是,我们必须为此使用二阶导数…这迫使代码变得复杂,也使事情变得相当慢(根据论文,大约 33%,这与我们将在这里看到的相符)。
有没有不使用二阶导数的 MAML 近似值?当然啦!我们可以简单地假设,我们用于内部梯度下降的梯度只是凭空出现,因此只是改善初始参数,而不考虑这些二阶导数。让我们为 MAML 训练函数添加一个一阶参数来处理这个问题:
那么这个一阶近似有多好呢?事实证明,它几乎和原来的 MAML 一样好,而且确实快了大约 33%。
Learning curve of MAML vs MAML first order
爬行动物
MAML 的一阶近似告诉我们,一些有趣的事情正在发生:毕竟,梯度是如何产生的似乎应该与一个好的初始化相关,然而它显然不是那么多。
爬虫进一步发展了这个想法,告诉我们做以下事情:在一个给定的任务上对运行几次的 SGD 迭代,然后在 SGD 的 k 次迭代后,将你的初始化权重向你获得的权重方向移动一点。一个非常简单的算法,只需要几行伪代码:
当我第一次读到这里的时候,我很紧张:这不就和在每项任务中交替训练你的重量一样吗,就像在迁移学习中一样?这怎么可能行得通呢?
事实上,爬行动物的论文预见到了这种反应:
你可能会想“这不就和训练预期损失 Eτ [Lτ] 一样吗?”然后检查日期是否是 4 月 1 日。
碰巧的是,我在 4 月 2 日写这篇文章,所以这一切都是严肃的。这是怎么回事?
事实上,如果我们运行 SGD 进行单次迭代,我们会得到与上述迁移学习相同的东西,但我们没有,我们使用了几次迭代,因此我们每次更新的权重实际上间接取决于损失的二阶导数,类似于 MAML。
好吧,但是,为什么会这样呢?爬行动物为此提供了一个令人信服的直觉:对于每项任务,都有最优的权重。事实上,可能有许多组权重是最优的。这意味着,如果您承担几项任务,那么应该有一组权重,对于每项任务,这些权重与至少一组最佳权重之间的距离是最小的。这组权重是我们想要初始化我们的网络的地方,因为它可能是对任何任务来说达到最优所必需的最少工作的权重。这是爬行动物发现的一组砝码。
我们可以在下图中直观地看到这一点:两条黑线代表两个不同任务的最优权重集,而灰线代表初始化权重。爬虫试图使初始化权重越来越接近最佳权重彼此最接近的点。
现在让我们实现爬行动物,并将其与 MAML 进行比较:
它如何看待一个随机问题?漂亮:
Reptile performance on a random problem
学习曲线呢?
Learning curve of Reptile, MAML and MAML first-order
看起来爬虫确实用一个更简单和更快的算法实现了和 MAML 相似甚至更好的性能!
所有这些都适用于更多的问题,而不仅仅是这个正弦波的玩具例子。要了解更多细节,我真的建议你阅读报纸。在这一点上,你应该有足够的背景来理解他们相当容易。
未来真正有趣的是将这些方法不仅应用于 K-shot 学习问题,还应用于更大的问题:对于基于中等规模数据集(几百或几千个,而不是 K-shot 学习中常见的大约 10 个)的训练模型,迁移学习在图像分类领域非常成功。使用爬行动物训练 resnet 网络会产生比我们现有的模型更适合迁移学习的东西吗?