处理熊猫丢失数据的一般准则
图片由 Willi Heidelbach 来自 Pixabay
缺失值在现实生活的数据集中很常见。需要正确处理它们,以便进一步处理和正确解释数据。
作为一名成瘾科学家,我的研究包括从临床试验的社区参与者那里收集数据。一些参与者可能会跳过临床访视,因此数据可能会在整个访视中丢失。有时,参与者可以跳过某个问卷的一些问题,导致部分数据缺失。参与者在需要整数值的地方输入不相关的自由文本的情况也时有发生。由于这些不同的原因,临床数据中缺失值是很常见的。
因此,处理缺失值是处理临床数据的常规任务,这也适用于许多其他真实数据。在本文中,通过一个假设的例子,我将向您展示我们应该如何处理 Pandas 中丢失的数据 Pandas 是我最喜欢的数据处理 Python 包之一。出于本教程的目的,我在 GitHub 上创建了一个假想的数据集。当然,实际的临床数据或其他现实生活中的数据可能更混乱,因此也更复杂,但同样的原则也适用。
第一步。了解您的数据
**基本原理:**了解数据大小和数据类型的有效性(例如,预期的数据类型和范围)。
第一步是理解你正在处理的数据。例如,假设我们的数据是对调查的回答的集合,包括下面左面板中显示的四个问题。在右边的面板中,我们将数据作为熊猫的数据框导入,并快速查看数据框。我们知道数据帧有 20 行和 5 列,subject_id 是整数,而其余的字符串。
当然,在实际的数据处理中,我通常会运行一些分类变量的频率表和数值变量的单变量分析,以更深入地了解我们的数据。这些超出了本文的范围,我们可以在以后的单独文章中讨论它们。
假设调查数据
第二步。记录数据
理由:我们需要检查我们所有的数据是否有效。为了方便起见,我们将重新编码我们的数据。但是,如果某些值无效,我们将把它们重新编码为缺失。
对于这四个问题,我们希望 q1-q4 的回答遵循下面的验证规则。为了方便起见,我还列出了我们将为现有列重新编码的数据类型。
数据验证规则
因为我们确切地知道数据应该是什么样子,所以我们可以开发详细的验证规则,并在验证和重新编码过程中将这些规则应用到每一列。
下面的代码向您展示了我们将如何做。为清楚起见,这四列(即 q1-q4)中的每一列都单独重新编码。请注意,我们现在仍然希望保留旧的列,这样我们可以将它们与重新编码的列进行比较,以确保数据被正确地重新编码。
数据记录
第三步。检查丢失的数据
基本原理:在我们对缺失数据做任何事情之前,我们需要找出我们有多少缺失数据。
一旦我们完成了数据记录,我们就可以检查我们的数据集中有多少缺失的数据。因为我们现在只对重新编码的列感兴趣,所以我们可以简单地删除旧列,只检查新列的数据缺失。我们注意到的另一件事是,每条记录对于一个主题是唯一的,因此我们可以在删除旧列后使用 subject_id 作为索引创建一个新的数据框。
检查数据缺失
如上图所示,我们可以使用isnull()
来评估每个单元格是否缺失(True
)或不缺失(False
)。由于真值被评估为 1,当我们使用sum()
函数时,可以显示每一列缺失值的数量。为了找出总的缺失数,我们只需运行df_r.isnull().sum().sum()
,在我们的例子中,我们有 21 个缺失值。
与这个主题相关的是另一个方法isna()
,它做的事情和isnull()
一样。如果要检查非缺失数据,可以使用notna()
或notnull()
方法。
第四步。处理缺失值
**基本原理:**需要显式处理缺失值,以避免数据集的错误解释。
缺失数据的处理方式由几个因素决定,例如缺失的性质(例如,随机缺失或非随机缺失)和潜在的预期措施—生物、心理或物理。换句话说,缺失是在数据的大背景下逐案处理的。本节将向您展示一些处理缺失数据的常用方法。
删除缺失值的数据记录
第一种方法是删除缺少值的数据记录。下面的代码片段向您展示了我们如何使用dropna()
方法来删除丢失数据的行。当然,我们可以在列上做类似的操作,但是我们通常不这么做,因为列在大多数时候是研究兴趣的变量。下面使用的每种方法都有其预期应用的简要描述。
删除缺少值的记录
使用dropna()
方法的几个要点:
thresh
参数指定了指定轴的每个系列应该具有的非缺失值的最小数量。- 您可以使用
'any’
和‘all’
作为how
参数,这将删除丢失部分或全部值的记录。 - 您可以删除指定轴、行或列上的缺失值。
- 除非方法调用指定了
inplace=True
,否则dropna()
方法不会改变原始数据帧。
用缺失值填充数据记录
另一种方法是用一些值来填充缺失的值。为此,我们可以使用fillna()
方法。与dropna()
方法类似,您可以在两个轴上使用fillna()
。下面的代码片段提供了一些常见的用例。
用缺失值填充记录
使用fillna()
方法的几个要点:
limit
参数指定要填充的最大记录数。当设置了method
参数时,该限制适用于上一个和下一个可用有效值之间的间隔,当未设置该参数时,该限制适用于列。- 您可以使用
'ffill'
和'bfill'
作为method
参数,它们分别使用最后一个或下一个有效值来填补空白。 - 您可以填充指定轴、行或列上缺少的值。
- 除非方法调用指定了
inplace=True
,否则fillna()
方法不会改变原始数据帧。
外卖
处理缺失值并不像某些人想象的那么简单。一些研究人员经常忽略的部分实际上是我们数据处理的最早步骤——从内容角度理解我们数据的含义。例如,对于我自己作为一名成瘾科学家,我总是检查我的数据集对应哪些问题,基于这些问题,我可以正确处理缺失的数据。
因此,我不能再强调这一点,但最大的收获是在彻底理解数据内容含义的情况下处理数据。
数据科学和分析领域的通才与专家
在数据科学和分析社区,专家比通才更受青睐,这就是现实。我们固有地认为,更加专业化是保证在某个职位或业务成果上取得成功的必由之路。可惜没那么简单。虽然专家们在再造他们擅长的工作方面表现出色,但有时他们很难在规则没有很好定义的未知领域航行。具有讽刺意味的是,许多商业角色,尤其是小而灵活的公司中的角色,恰恰需要这样一种技能——处理模糊性、不确定性和缺乏明确规则的能力。多面手的闪光点就在于模糊性——他们兴趣广泛,可能从事过许多不同类型的工作和行业。但是,虽然他们的职业道路在纸面上看起来似乎很混乱,但事实上,它提供了大量可以用来解决问题的经验——这是数据科学和分析的面包和黄油。
让目标成为目标
参加过数据科学会议吗?我去过几个,我在每个地方观察到的重复模式是过度强调案例研究、解决方案和供应商,它们解决的问题只适用于前 5%的精英企业。这种模式反映在关于数据科学和数据工程实践的文献和思想领导中,并随后渗透到构建数据团队的几乎每一个组织策略中(以及此后的每一个工作列表)。不幸的是,我称之为“专家”的工作模型(这不是数据科学领域独有的,尽管可能更明显)虽然有时在超大型企业中有效或强制要求,但通常无法解决其他所有人(其他 95%的公司)的数据项目的底层需求,即向最终用户提供价值/行动/选择,或者换句话说,将一组技术交付成果与解决客户需求的解决方案联系起来(内部业务用户或面向外部的客户,同样的原则适用)。
数据驱动的解决方案开发周期
在上图中,我展示了我认为数据科学和分析团队开发业务解决方案的普遍适用周期。每个虚线框代表实现构建完整解决方案的最终目标所需的不同技能。在“专家”模式中,组织将雇佣一个人或一组人来完成每个发展阶段的任务。
“专家”工作模式
在大型组织中(前 5%)——这种可以起作用——通常大型公司有资源为开发的每个阶段有效地雇用超级专家,以及雇用和/或安排监督整个过程的领导层。注意我对 *can、*的强调。通常,交付解决方案所涉及的团队、部门和个人的数量会给过程带来不必要的复杂性和官僚主义,这可能会停止或完全搁置项目。在“专家”模型中,由于缺乏跨职能领域的知识或经验,不必要的复杂性也可能被无意地引入。一个很好的例子是业务部门和数据科学团队之间经常出现的脱节,因为它涉及到业务目标和建模响应变量。有时,数据科学团队花费数周时间构建一个旨在预测特定目标变量的模型,却发现该目标与业务实际试图实现的结果不匹配。
在较小的公司(其他 95%的业务),“专家”模式很少奏效。
在较小的组织中,雇佣专家的需要使得开发周期的重要部分暴露出来。
雇用专家来满足每一个独特需求的常见方法导致那些预算庞大的非大型企业在开发周期中缺少开发元素。为了解决这一问题,许多组织创建了不合理的职位列表,以寻找一直难以捉摸的数据科学“独角兽”。数据科学界的每个人都知道这种现象,并一直对此感到羞耻,但当你真正思考公司为什么这样做时,这完全有道理。任何地方的人力资源组织都采用专家招聘模式来填补几乎任何职位——这就是我们做事的方式。常识告诉我们,专业化等同于成功。当完成一个成功的数据科学项目需要如此多的组成部分,而预算有限时,人力资源团队会寻找能够填补每个空缺的候选人。众所周知,这种类型的候选人少之又少,而且很可能已经找到了加入团队的方法,或者已经在精英企业的简历中名列前茅。因此,公司最终会聘用一名专家,这位专家在其特定领域具有非凡的才华和丰富的经验,并期望他们神奇地将自己的技能扩展到与其超级专业无关的许多其他挑战上——结果往往很差(Epstein,Range,第 212 页)。这与候选人之前的成就无关,也与他或她的能力和资历无关。人力资源组织——以及许多招聘经理——不知道任何其他方法。他们生活的规则是过分强调经验的深度胜过所有其他因素。这种关注通常与被雇佣的数据角色的实际期望结果不匹配。当我们需要找到一个拥有某个领域最专业技能的候选人时,我们忽略了目标——解决独特的业务问题。将目标作为目标——如果你需要某人花 100%的时间为零售业务做时间序列预测或倾向建模,那么你可以雇佣一个在整个职业生涯中都在高水平做这些事情的人(即重现他们之前已经完成的业绩)。然而,在一家小公司,很少有人会把他们的每一秒钟都花在做一件单一的任务上,不可避免地,这个人会被要求扩展他们的高度专业化,以解决跨几个领域的挑战,这就是“专家”模式的不足之处。
多面手
这里有一个激进的想法:我建议 80%的情况下,你应该雇佣多面手而不是专家。这并不是说多面手比专家更好,只是根据我的个人经验,在我工作过的许多公司中,多面手通常对我遇到的大约 80%的案例更有用。什么是通才?我将它定义为在广泛的技能组合和专业领域具有经验的人,并且在一个或多个领域具有足够的(最低要求的)深度来履行工作的基本职能。从某种程度上来说,通才牺牲了职业生涯的深度,因为他们跨越了几个不同的角色、部门或工作类型,甚至可能超出了数据科学和分析的范畴,但作为回报,他们创造了一种独特的技能组合,使他们能够在工作中建立专家很难做到的联系。这种技能组合对于解决没有直接解决方案的实际问题特别有用。
“通才”模式
我将称之为“通才”模型,它并没有不必要的强调专业化,而是寻求将被雇佣的问题的性质与每个候选人的独特经历恰当地联系起来。因此,如果所寻求的结果是一套非常明确的规则,目标是重新创造一个非常具体的输出,候选人已经证明他/她已经掌握(像外科医生或职业高尔夫球手),那么你就要找专家。然而,如果这份工作的性质更加开放,新的方法不断被创造,新的规则不断被起草(“现实世界”的复杂性增加),那么你就要寻找多面手。
例如,你想在你的公司做“人工智能和机器学习”?太好了!不幸的是,你可能甚至没有资格讨论人工智能。首先,你需要有人可以帮助创建数据架构、管道和系统,这样你就有了可以开始查看的数据集。然后你可以开始思考简单的“如果-那么”场景,这些场景最终会导致“人工智能”从能为一个项目打下基础的多面手开始,然后,很可能是更久以后,雇佣能在业务需要时(且仅在业务需要时)增加单个组件深度的专家。
您是否希望为您的营销计划提供自动化仪表板、报告和统计数据?太好了!首先,你需要一个可以大规模支持你的项目的营销数据库架构。你可能需要一个有实际营销经验的人,但是他也有足够的技术知识来构建一个数据架构来支持你的目标。不要雇佣一个谷歌分析专家并期望他们建立一个程序,他们期望有数据来处理——而你没有。那么你的候选人就会很沮丧,你也得不到你想要的。这就是拥抱丰富经验的美妙之处,而不是将其视为负面因素(很多人都这么认为)——员工和候选人最终会更快乐、更有成就感,同时企业也会得到它想要的结果和成果。
在“多面手”模型中,你通过拥抱模糊性和“现实生活”的复杂性,而不是期望你的超级专家只是处理它,来定位个人和团队的成功。这在敏捷的组织中尤其重要,在这种组织中,变化经常发生,新的“东西”必须在运行中构建——在有很大程度的结构并且不需要变化的情况下就不那么重要了。
改变你的视角
虽然“多面手”的想法看起来很激进,但我在这篇文章中列出的一切都是有研究支持的,其中大部分已经在大卫·爱泼斯坦的书 Range 中揭示出来(阅读!).与普遍的看法相反,让一大群“专家”去解决问题并不是解决问题的最佳方式——最佳和最具创新性的解决问题的方法来自于拥有来自多个领域的广泛知识的个人。横向联系的经验,再加上足够的技术知识,是创建新的解决方案的最佳组合,这些解决方案可以解决真实的、实际的业务问题。
外卖:
- 与普遍的看法相反,跨许多领域的广泛经验并不会让你成为众所周知的“万金油”,相反,会提高你建立别人看不到的联系的能力,并提出别人想不到的解决方案。
- 在适当的情况下,超级专家非常重要,非常有价值。需要高技术重复表现的工作适合超级专家,对多面手来说可能不是个好选择。让目标成为目标,按照“通才”模式招聘。
- 大公司雇佣专家可能比小公司受益更多。这是因为大型企业已经扩大了他们的业务,以至于他们经常有多个个人在业务的极其有限的部分工作。也就是说,如果公司的目标是创造新的东西,或者以一种新的方式将系统结合在一起,多面手可能更适合。
- 如果你正在开始——不要决定成为多面手或专家——弄清楚你个人擅长什么,然后打造你自己独特的道路。如果你喜欢深入研究一两个主题,或者想成为某个主题的专家,你可能会喜欢成为专家,应该寻找能迎合你难以置信的专注技术能力的工作。如果你兴趣广泛,或者很快就厌倦了,那么你可能是个多面手。掌握足够的技术,以满足技术面试的最低要求,但又足够宽泛,以构建解决方案(例如,从头构建一个商业智能程序,或创建一个端到端的机器学习管道,或构建一个从多个来源获取数据的网络应用)。此外,如果你是一个多面手,花时间获取知识和技能,补充你的分析专业(有点像“辅修专业”)。商业、金融、营销、设计和产品是分析专家的几个重要倍增因素。
有问题吗?你可以给我发电子邮件,地址是 cwarren@stitcher.tech,或者在 Linkedin 上关注我,地址是 https://www.linkedin.com/in/cameronwarren/
广义最小二乘法(GLS):与 OLS 和 WLS 的关系
通过数学推导和直觉
背景和动机
对于任何从事统计学或机器学习研究的人来说,普通最小二乘(OLS)线性回归是第一个也是最“简单”的方法之一。但是,有一组数学限制,在这些限制下,OLS 估计量是最佳线性无偏估计量(BLUE),即具有最小采样方差的无偏估计量。 ( )关于 OLS、蓝色和高斯-马尔科夫定理的更全面的概述,请参见我以前关于这个主题的文章 )
如果 OLS 是蓝色的数学假设不成立呢?下一个“飞跃”是广义最小二乘(GLS) ,其中的 OLS 实际上是一个特例。这篇文章是对 GLS 的介绍,包括以下主题:
- 回顾 OLS 估计量及其为蓝色所需的条件
- 广义最小二乘法的数学设置(GLS)
- 恢复 GLS 估计量
- GLS 估计量无偏的证明
- 恢复 GLS 估计量的方差
- 浅谈加权最小二乘(WLS)的关系
请注意,在本文中,我是从频率主义范式(与贝叶斯范式相反)出发的,主要是为了方便起见。所以,让我们开始吧:
1.OLS 估计量及其为蓝色的条件评述
让我们先快速回顾一下 OLS 估计量
作者图片
作者图片
关于 OLS 估计量的更多信息和它的无偏性的证明,请参见我以前关于这个主题的文章。
2.广义最小二乘法的数学设置(GLS)
作者图片
3.恢复 GLS 估计量
作者图片
4.GLS 估计量无偏的证明
作者图片
5.恢复 GLS 估计量的方差
作者图片
6.浅谈加权最小二乘(WLS)的关系
作者图片
总结、最终想法和后续步骤
广义最小二乘(GLS)是一个大话题。这篇文章是一个简短的介绍,旨在从数学上为 GLS“设置场景”。还有更多的内容需要介绍,包括(但不限于):
- 对 WLS 更深入的探究
- 指定协方差矩阵 V 的方法和途径
- 可行广义最小二乘的主题
- 与迭代加权最小二乘法(IRLS)的关系
我计划在以后的文章中深入讨论这些主题。
希望以上有见地。正如我在以前的一些文章中提到的,我认为没有足够的人花时间去做这些类型的练习。对我来说,这种基于理论的洞察力让我在实践中更容易使用方法。我个人的目标是鼓励该领域的其他人采取类似的方法。我打算在未来写一些基础作品,所以请随时在【LinkedIn】和 上与我联系,并在 Medium 上关注我的更新!
广义线性模型
它们是什么?我们为什么需要它们?
广义线性模型(GLMs)诞生于将各种各样的回归模型纳入一个保护伞之下的愿望,这些模型涵盖了从用于实值数据的经典线性回归模型到基于计数的数据模型(如 Logit、Probit 和 Poisson)再到生存分析模型的范围。
GLM 伞下的模特
GLMs 为您提供了一种通用的方法,使用一个通用的过程来指定和训练以下类别的模型:
- 经典线性回归(CLR)模型,俗称实值(和潜在负值)数据集的线性回归模型。
- 方差分析模型。
- 计数比率模型。例如预测获胜几率、机器故障概率等的模型。这类模型的一些例子是 Logit 模型(用于逻辑回归)、概率单位和有序概率单位模型,以及非常强大的二项式回归模型。
- 用于解释(和预测)事件计数的模型。例如,用于预测超市、购物中心、急诊室的客流量的模型。这类模型的例子有泊松和负二项式回归模型,以及栅栏模型。
- 预测零件、机器(和人类)下次故障时间的模型。估算生物(和非生物)寿命的模型。
当上述看似不同的回归模型中的每一个都以广义线性模型的格式表达时(我们将很快解释这种格式是什么),它给建模者带来了为所有这样的模型应用公共训练技术的巨大好处。
对于广义线性模型,人们使用一种通用的训练技术来训练一组不同的回归模型。
此外,GLMs 允许建模者以线性和加法方式 表达回归变量(又称为协变量、又称为影响变量、又称为解释变量) X 和响应变量(又称为因变量) y 、之间的关系,即使基础关系可能既不是线性的也不是加法的。
广义线性模型让您以线性、相加的方式表达协变量 X 和响应 y 之间的关系。
与经典线性回归模型的关系
说到线性和可加性,线性回归模型是一种简单而强大的模型,可成功用于建模线性、可加性关系,如下所示:
回归变量 x_1,x_2,x_3,…x_p 是加性相关的(图片由作者
CLR 模型通常是“首选模型”:在为自己的问题选择复杂模型之前,应该仔细比较复杂模型。
CLR 模型具有明显的优势:
在满足某些条件的情况下,它们有一个简洁的“封闭形式”解,这意味着,它们可以通过简单地求解线性代数方程来拟合,即根据数据进行训练。
解释训练模型的系数也很容易。例如,如果训练的 CLR 模型由以下等式表示:
拟合的线性回归模型(图片由作者提供)
从这个等式中可以清楚地看出这个模型已经发现了什么:露营者人数每增加一个单位,捕获的鱼的数量就会增加 75%左右,而露营小组的儿童人数每增加一个单位,该小组捕获的鱼的数量就会减少相同的数量!此外,在捕捉到任何鱼之前,需要一个至少 3 人的野营小组(=roundup(2.49))。
但是经典的线性回归模型也有一些严格的要求,即:
- **加性关系:**经典线性模型假设回归变量之间应该存在加性关系。
乘法和加法关系(图片由作者提供)
- **同方差数据:**经典线性模型假设数据应该具有恒定方差,即数据应该是同方差的。在现实生活中,数据往往是而不是同质的。方差不是常数,有时它是平均值的函数。例如,方差随着平均值的增加而增加。这在货币数据集中很常见。
同方差和异方差数据(图片由作者提供)
- **正态分布误差:**经典线性模型假设回归误差(也称为残差)正态分布,均值为零。这个条件在现实生活中也很难满足。
- **不相关变量:**最后,假设回归变量之间不相关,最好是相互独立的。
因此,如果您的数据集是非线性的、异方差的并且残差不是正态分布的,这在现实世界的数据集中是常见的情况,那么需要对***【y】和【X】***进行适当的变换,以便使关系呈线性,同时稳定方差并使误差正常化。
平方根和对数变换通常用于实现这些效果,如下所示:
对数将乘法关系转换为加法关系(图片由作者提供)
不幸的是,没有一种可用的变换能同时达到所有三种效果,即使关系线性、使异方差最小化和使误差分布正常化。
转换方法还有另一个大问题,如下所示:
回想一下 y 是一个随机变量,它遵循某种概率分布。所以对于数据集中任何给定的 x 值的组合,现实世界很可能呈现给你几个 y 的随机值,而这些可能值中只有一部分会出现在你的训练样本中。在现实世界中, y 的这些值将围绕 y 的条件均值随机分布,给定x 的具体值,y 的条件均值由E(y|x)表示这种情况可以说明如下:**
条件期望 E( y|x) 如红点所示(图片由作者)
在变量转换方法中,我们做了一个不切实际的假设,即在使用 log()、sqrt() 等进行转换后, y 的每个单个值,即上面图中的每个蓝点。,最终会和 X 成线性关系。这显然是过高的期望。
似乎更现实的是,**【y】的条件均值(又名期望),即E(y|X,)经过适当的变换,应该与 X 成线性关系。
换句话说:
条件期望的对数,表示为协变量的线性组合(图片由作者提供)
广义线性模型做出了上述至关重要的假设,即转换后的条件期望 y 是回归变量 X 的线性组合。
该转换函数被称为 GLM 的链接函数,并由 g(.)
我们举例说明 g() 的动作如下:
广义线性模型的链接函数(图片由作者提供)
因此,GLMs 不是为每个转换 y 的每个单个值,而是只为每个 x 转换 y 的条件期望。所以不需要假设 y 的每一个单值都可以表示为回归变量的线性组合。**
在广义线性模型中,将因变量 y 的转换条件期望表示为回归变量 X 的线性组合。
**链接功能 *g(。)*可以采取多种形式,我们根据什么形式得到不同的回归模型 g(。)不紧不慢。下面是一些流行的形式和它们导致的相应回归模型:
线性回归模型
**在线性模型中, g(。)是下面的 身份 功能:
线性回归模型使用的身份函数(图片由作者)
逻辑回归模型(通常是二项式回归模型)
**在逻辑回归模型中, g(。)是下面的 Logit 功能:
逻辑回归模型使用的 Logit(对数优势)函数(图片由作者提供)
泊松回归模型
泊松回归模型使用以下函数:
泊松回归模型使用的对数函数(图片由作者提供)
**g 还有很多其他的变体(。)如泊松-伽马混合导致负二项式回归模型和正态分布的累积分布函数的逆,从而导致 probit 模型。
如何处理数据中的异方差?
最后,让我们看看 GLMs 如何处理异方差数据,即方差不恒定的数据,以及 GLMs 如何处理潜在的非正态残差。
glm 通过假设方差是均值的某个函数 V( ) ,或者更准确地说是条件均值|X = X来说明非恒定方差的可能性。
在上面提到的每个模型中,我们假设一个合适的方差函数V(|X=X)。
在广义线性模型中,将数据中的方差表示为平均值 的合适函数。
在线性回归模型中,我们假设 V( ) =某常数 ,即方差为常数。为什么?因为线性模型假设 y 是正态分布,一个正态分布有一个恒定的方差。
****Related Post:** [Robust Linear Regression Models for Nonlinear, Heteroscedastic data](/robust-linear-regression-models-for-nonlinear-heteroscedastic-data-14b1a87c1952)**
在 Logistic 和二项式回归模型 s 中,我们假设, V( ) = — /n 为一个数据集大小为 n 的样本,为一个 Logit 所要求分布的 y 值。**
****Related Post:** [The Binomial Regression Model: Everything you need to know](/the-binomial-regression-model-everything-you-need-to-know-5216f1a483d3)**
在泊松回归模型中,我们假设 V( ) =。 这是因为,泊松回归模型假设y 具有泊松分布,在泊松分布中,方差=均值。
****Related Post:** [An Illustrated Guide to the Poisson Regression Model](/an-illustrated-guide-to-the-poisson-regression-model-50cccba15958)**
在负二项回归模型中,我们假设V()=+α****,其中 α 是一个分散参数,它允许我们处理过度分散或分散不足的数据。***
****Related Post:** [Negative Binomial Regression Model: A Step by Step Guide](/negative-binomial-regression-f99031bb25b4)**
…其他型号也是如此。
在 GLMs 中,可以证明模型对残差的分布形式不敏感。简而言之,模型不关心模型的误差是正态分布还是以任何其他方式分布,只要您假设的均值-方差关系实际上满足您的数据。
广义线性模型不关心残差是否正态分布,只要数据满足指定的均值-方差关系。
这使得 GLMs 成为许多真实世界数据集的实际选择,这些数据集是非线性和异方差的,并且我们不能假设模型的误差总是正态分布的。
最后,提醒一句:与经典的线性回归模型类似,GLMs 也假设回归变量彼此不相关。因此,GLMs 不能用于建模通常包含大量自相关观测值的时间序列数据。
广义线性模型不应用于模拟自相关时间序列数据。
摘要
广义线性模型将各种不同的回归模型(如经典线性模型、各种数据计数模型和生存模型)汇集在一个估计伞下。
以下是关于 GLMs 需要记住的一些事情的概要:
- GLMs 巧妙地避开了经典线性模型的几个强要求,如效应的可加性、数据的同方差性和残差的正态性。
- GLMs 在 GLM 家族的所有模型上强加了一个通用的函数形式,它由一个链接函数g(|X=X)组成,允许您将因变量的转换条件均值表示为回归变量的线性组合。**
- GLMs 需要指定合适的方差函数V(|X=X),用于将数据中的条件方差表示为条件均值的函数。什么形式 V(。)取值取决于数据集中因变量 y 的概率分布。
- glm 并不关心误差项的分布形式,因此对于许多真实世界的数据集来说,glm 是一个实用的选择。
- GLMs 确实假设回归变量 X 是不相关的,从而使得 GLMs 不适于对自相关时间序列数据建模。
快乐造型!
感谢阅读!我写关于数据科学的主题,重点是回归和时间序列分析和预测。
如果你喜欢这篇文章,请关注我的Sachin Date获取回归和时间序列分析方面的技巧、操作方法和编程建议。
R 中的广义对图
用关联矩阵可视化您的数据
Artur Tumasjan 在 Unsplash 上拍摄的照片
您的创新想法可能来自对您的数据的详细探索。大多数情况下,数据将包含连续变量和分类变量。你需要从中找到可以解释的模式。如果它可以在一个图表中有条理地显示出来,并且您可以用简单而简短的代码行来实现它,那会怎么样?
为什么是 R?
R 是统计计算 R 基金会支持的统计计算和图形开源编程语言。使用其广泛使用的集成开发环境- RStudio 既易学又舒适。
安装软件包
首先,我们需要用下面的代码安装所需的包。
**install.packages("tidyverse")
install.packages("GGally")
install.packages("ISLR")**
**‘tidy verse’包用于数据争论&数据可视化。广泛使用的‘gg plot 2’封装在‘tidy verse’中。 GGally 通过在【gg plot 2】中增加几个函数,降低了将几何对象与转换数据结合的复杂性。在本练习中,我们将使用大西洋中部工资数据 a,其中包含美国大西洋中部地区 3000 名男性工人的工资数据。“ISLR”**加载此数据集需要包。
加载包
这些包需要安装一次,但是每次运行脚本时,你都需要用**library**
函数加载这些包。
**library(tidyverse)
library(GGally)
library(ISLR)**
浏览数据集
我们将使用**data**
函数加载数据集,并使用**glimpse**
和**head**
函数探索数据集。
**data(Wage)****glimpse(Wage)
head(Wage)**
作者图片
作者图片
让我们只选择**【年龄】【学历】【工作阶级】* & *【工资】几列来进行我们的工作。
***Wage2 <- Wage %>%
subset(select = c("age", "education", "jobclass", "wage"))****glimpse(Wage2)
head(Wage2)***
作者图片
我们可以看到“年龄”和“工资”变量(列)是连续的(<int>, <dbl>
),“教育程度”&,“工作阶层”变量(列)是分类的(<fact>
)。
不同的绘图选项
我们这个练习的目的是看看“工资”是如何随着“年龄”、“教育程度”和“工作阶层”而变化的。让我们用 ggplot2 包的**ggplot**
&各自的 geom 功能尝试不同的绘图选项。
散点图
***# P1
ggplot(Wage2) +
geom_point(aes(x = age, y = wage,
color = education), size = 4) +
labs(x = 'AGE', y = "WAGE") +
ggtitle("wage ~ age, education ") +** **theme_bw() +
theme(axis.text.x = element_text(face = 'bold', size = 10),
axis.text.y = element_text(face = 'bold', size = 10))****# P2
ggplot(Wage2) +
geom_point(aes(x = age, y = wage,
color = jobclass), size = 4) +
labs(x = 'AGE', y = "WAGE") +
ggtitle("wage ~ age, jobclass ") +** **theme_bw() +
theme(axis.text.x = element_text(face = 'bold', size = 10),
axis.text.y = element_text(face = 'bold', size = 10))***
作者图片
作者图片
直方图
***# P3
ggplot(Wage2) +
geom_histogram(aes(x = wage,
fill = education), color = 'lightblue') +
labs(x = 'WAGE') +
ggtitle("wage ~ education ") +
theme_bw() +
theme(axis.text.x = element_text(face = 'bold', size = 10),
axis.text.y = element_text(face = 'bold', size = 10))****# P4
ggplot(Wage2) +
geom_histogram(aes(x = wage,
fill = jobclass), color = 'lightblue') +
labs(x = 'WAGE') +
ggtitle("wage ~ jobclass ") +
theme_bw() +
theme(axis.text.x = element_text(face = 'bold', size = 10),
axis.text.y = element_text(face = 'bold', size = 10))***
作者图片
作者图片
密度图
***# P5
ggplot(Wage2) +
geom_density(aes(x = wage,
fill = education)) +
labs(x = 'WAGE') +
ggtitle("wage ~ education ") +
theme_bw() +
theme(axis.text.x = element_text(face = 'bold', size = 10),
axis.text.y = element_text(face = 'bold', size = 10))****# P6
ggplot(Wage2) +
geom_density(aes(x = wage,
fill = jobclass)) +
labs(x = 'WAGE') +
ggtitle("wage ~ jobclass ") +
theme_bw() +
theme(axis.text.x = element_text(face = 'bold', size = 10),
axis.text.y = element_text(face = 'bold', size = 10))***
作者图片
作者图片
条形剧情
***# P7
ggplot(Wage2) +
geom_bar(aes(x = education,
fill = jobclass)) +
labs(x = 'WAGE') +
ggtitle("wage ~ education ") +
theme_bw() +
theme(axis.text.x = element_text(face = 'bold', size = 10),
axis.text.y = element_text(face = 'bold', size = 10))****# P8
ggplot(Wage2) +
geom_bar(aes(x = jobclass,
fill = education)) +
labs(x = 'WAGE') +
ggtitle("wage ~ jobclass ") +
theme_bw() +
theme(axis.text.x = element_text(face = 'bold', size = 10),
axis.text.y = element_text(face = 'bold', size = 10))***
作者图片
作者图片
方框图
***# P9
ggplot(Wage2) +
geom_boxplot(aes(x = education, y = wage,
fill = education)) +
labs(x = 'EDUCATION') +
ggtitle("wage ~ education ") +
theme_bw() +
theme(axis.text.x = element_text(face = 'bold', size = 10),
axis.text.y = element_text(face = 'bold', size = 10))****# P10
ggplot(Wage2) +
geom_boxplot(aes(x = jobclass, y = wage,
fill = jobclass)) +
labs(x = 'JOBCLASS') +
ggtitle("wage ~ jobclass ") +
theme_bw() +
theme(axis.text.x = element_text(face = 'bold', size = 10),
axis.text.y = element_text(face = 'bold', size = 10))****# P11
ggplot(Wage2) +
geom_boxplot(aes(x = jobclass, y = wage,
fill = education)) +
labs(x = 'JOBCLASS') +
ggtitle("wage ~ jobclass, education ") +
theme_bw() +
theme(axis.text.x = element_text(face = 'bold', size = 10),
axis.text.y = element_text(face = 'bold', size = 10))***
作者图片
作者图片
作者图片
****关联矩阵同【GGally】**的【ggpairs】
到目前为止,我们已经检查了不同的绘图选项-散点图,直方图,密度图,条形图和箱线图,以找到相对分布。现在该看 R 中的 广义对情节了。
我们已经加载了【GGally】包。函数**ggpairs**
会变魔术,把这些情节都带到一个页面里!
***# P12
ggpairs(Wage2) + theme_bw()***
作者图片
颜色特色由【教育】**
***# P13
ggpairs(Wage2, aes(color = education)) + theme_bw()***
作者图片
**颜色特征由【job class】**表示
***# P14
ggpairs(Wage2, aes(color = jobclass)) + theme_bw()***
作者图片
希望这篇实践文章对您有用。我建议你在自己的领域数据中应用这些容易编码的图,并为你的业务创新得出有意义和有趣的见解。
祝您的数据之旅顺利……
约书亚·厄尔在 Unsplash 上拍摄的照片
* [## Ahmed Yahya Khaled-EPMO 经理-企业战略- Robi Axiata 有限公司| LinkedIn
打破数据、战略、规划和执行之间的孤岛!这个简介是一个技术和人工智能专业人士目前…
www.linkedin.com](https://www.linkedin.com/in/aykhaled/)*
真实世界数据集的广义泊松回归
Phil Dolby 的照片来自 PxHere 下 CC BY 2.0
以及用 Python 进行广义泊松回归的分步指南
常规泊松回归模型通常是基于计数的数据集的首选模型。泊松回归模型的主要假设是计数的方差与其平均值相同,即数据是等分布的。不幸的是,现实世界的数据很少是等分布的,这促使统计学家使用其他模型进行计算,例如:
- 负二项式(NB)回归模型以及,
- 广义泊松回归模型
这两个模型都而不是做出关于数据集的方差=均值假设。这使得它们成为基于计数的数据建模的更好的实用选择。在之前的一篇文章中,我详细介绍了 NB 模型。在本文中,我们将介绍广义泊松回归模型。
文章的布局
我们将在本文中讨论以下主题:
- 什么是基于计数的数据集?
- 什么是等分散、分散不足、分散过度?我们将讨论泊松模型对于分散不足和分散过度的数据集的局限性。
- 领事的广义泊松回归(GP-1) 模型和 法莫耶的限制广义泊松回归(GP-2) 模型介绍。
- 一个基于 Python 的教程,用于构建和训练 GP-1 和 GP-2 模型,并将它们的性能与标准泊松回归模型进行比较。
什么是基于计数的数据?
基于计数的数据集是因变量 y 代表某个事件发生的次数的数据集。以下是一些例子:
- 每月发现的系外行星数量。
- 历年太阳黑子的数量。
- 每小时走进急诊室的人数。
在上述每一个数据集中,因变量 y 代表观察到的计数,而 X 的选择,解释变量的矩阵,即被认为解释 y 中的方差的一组变量,主要(可悲地)留给了统计建模者的判断。
等分散、欠分散、过分散和泊松模型的局限性
可以从尝试将相关计数变量建模为泊松过程开始。不幸的是,在许多真实世界的数据集中,泊松过程无法令人满意地解释观察计数的可变性。这主要是由于泊松回归模型对数据的方差=均值假设。换句话说,泊松模型错误地假设计数是等分布的。
泊松模型无法摆脱这一假设,因为该模型基于因变量是一个服从泊松概率分布的随机变量的假设,可以证明泊松分布的随机变量的方差等于其均值。
下面的公式表示了泊松分布随机变量的概率分布函数(也称为 P 概率MasF函数)。可以看出:
方差(X) =均值(X) = λ ,单位时间内发生的事件数。
假设每单位时间发生λ个事件,看到 k 个事件的概率(图片由作者提供)
下面是一些有趣的概率分布图,由上述公式针对不同的λ值生成:
不同λ值下看到 k 个事件的概率(图片由作者提供)
顺便提一下,在回归建模中,谈论无条件方差和无条件均值是不常见的。相反,人们更喜欢将方差称为 ,条件是解释变量 X 呈现某个特定值X _ I用于第 I 次观察 。
条件方差可以表示为方差(y|X = X _ I)。条件均值同上。
如前所述,现实世界的数据集很多都不是等分散的,所以 y 的条件方差不等于 y 的条件均值。其中一些的方差大于平均值,这种现象被称为过度分散,而在其他情况下,方差小于平均值,也称为分散不足。
总的来说:
当您的因变量 y 的方差大于您的模型假设的方差时,那么从您的模型的角度来看,您的数据集是过度分散的。
当您的因变量 y 的方差小于您的模型假设的方差时,那么从您的模型的角度来看,您的数据集是欠分散的。
过度(或不足)分散的影响是您的模型将无法充分解释观察到的计数的可变性。相应地,它的预测质量会很差。
解决这个问题的一个常见方法是假设方差是平均值的一般函数,即:
方差=f(均值)
常用的一种形式为 f(。) 如下:
一个常用的方差函数(图片由作者提供)
其中 p=0,1,2…
α 被称为离差参数,它代表由一些未知变量集合引入的**【y】的额外可变性,这些变量集合导致y 的总体方差不同于您的回归模型预期的方差。
注意,当 α=0 时,方差=均值你就得到了标准泊松回归模型。
当 α > 0 时,我们考虑两种有趣的情况,即当 *p=1 和 p=2 时。*在这两种情况下,我们得到了所谓的负二项(NB)回归模型**。**
在 NB 回归模型中,我们假设观察计数 y 是一个事件率为 λ 和 λ 本身是一个伽玛分布随机变量。
负二项式回归模型(通常称为泊松-伽马混合模型)被证明是许多真实世界计数数据集的优秀模型。我在下面的文章中对此做了更详细的介绍:
**[**Negative Binomial Regression: A Step by Step Guide**](/negative-binomial-regression-f99031bb25b4)**
还有许多其他方法可用于推广泊松回归模型,以将其扩展到过度分散和分散不足的数据。在本文中,我们将讨论两个这样的模型。
领事的广义泊松回归模型
1989 年,Prem C. Consul 在他的著作《广义泊松分布:性质和应用》,中提出了一种修正泊松分布的概率分布的方法,使其能够处理过分散和欠分散的数据。这个模型后来被称为 GP-1(广义泊松-1)模型。GP-1 模型假设因变量 y 是具有以下概率分布的随机变量:**
GP-1 模型的概率分布、方差和均值函数(图片由作者提供)
如果在上面的等式中设置分散参数 α 为 0,GP-1 的 PMF、均值和方差基本上减少到标准泊松分布。
法莫耶的限制性广义泊松分布
1993 年,Felix Famoye 引入了他所谓的受限广义泊松回归模型,作为一种将标准泊松模型的范围扩展到处理过度分散和分散不足数据集的方法。这个模型被称为 GP-2(广义泊松-2)模型。
GP-2 模型假设因变量 y 是具有以下概率分布的随机变量:
GP-2 模型的概率分布、方差和均值函数(图片由作者提供)
如前所述,当分散参数 α 被设置为 0 时,GP-2 的 PMF、均值和方差函数基本上减少到标准泊松分布的那些。
色散参数α使用以下公式估算:
计算α的公式(图片由作者提供)
在 statsmodels 库中, α 为您估算,作为 GP-1 和 GP-2 模型的模型拟合过程的一部分。
GP-1 和 GP-2 在 Python 和 Statsmodels 中的实现
statsmodels 库包含通过statsmodels.discrete.discrete_model.GeneralizedPoisson
类实现的 GP-1 和 GP-2 模型。
在本节中,我们将展示如何使用 GP-1 和 GP-2 对以下真实世界的计数数据集进行建模。
真实世界的计数数据集
下表包含了骑自行车穿过纽约市各种桥梁的人数。从 2017 年 4 月 1 日到 2017 年 10 月 31 日每天测量计数。
来源:东河大桥的自行车数量(纽约开放数据)(图片由作者提供)
这里是到原始数据集的链接。
我们将集中分析每天穿过布鲁克林大桥的骑自行车的人数。这是布鲁克林大桥上自行车数量的时间顺序图:
每天骑自行车的人在布鲁克林大桥上计数(背景来源:从曼哈顿岛看到的布鲁克林大桥
我们的回归目标
我们回归的目标是预测任意一天穿过布鲁克林大桥的骑自行车的人数。
我们的回归策略
我们将使用数据集中的一组回归变量,即日、星期几(从日期中得出)、月(从日期中得出)、高温、低温和降水量,来“解释”布鲁克林大桥上观测到的计数的变化。
观察到的自行车数量的回归矩阵和向量(图片由作者提供)
我们回归模型的训练算法会将观察到的计数 y 拟合到回归矩阵 X 。
一旦模型被训练,我们将在一个模型在训练期间根本没有见过的持续测试数据集上测试它的性能。
回归策略—循序渐进
- 我们将首先在这个数据集上训练标准泊松回归模型。标准泊松模型也将作为测试广义泊松模型有效性的“控制”模型。
- 如果数据集中的方差与平均值大致相同,那么除了检查泊松模型的拟合优度之外,就没什么可做的了。
- 如果方差大于或小于泊松均值,那么我们将在数据集上依次训练 GP-1 和 GP-2 模型,并将它们的性能与泊松模型进行比较。
我们将从导入所有需要的包开始。
**import pandas as pd
from patsy import dmatrices
import numpy as np
import statsmodels.api as sm
import matplotlib.pyplot as plt**
为计数数据集创建一个熊猫数据框架。这里是数据集的链接。
**df = pd.read_csv('nyc_bb_bicyclist_counts.csv', header=0, infer_datetime_format=True, parse_dates=[0], index_col=[0])**
我们将在 X 矩阵中添加一些派生的回归变量。
**ds = df.index.to_series()
df['MONTH'] = ds.dt.month
df['DAY_OF_WEEK'] = ds.dt.dayofweek
df['DAY'] = ds.dt.day**
让我们打印出数据集的前几行,看看它是什么样子:
**print(df.head(10))**
(图片由作者提供)
让我们创建训练和测试数据集。
**mask = np.random.rand(len(df)) < 0.8
df_train = df[mask]
df_test = df[~mask]
print('Training data set length='+str(len(df_train)))
print('Testing data set length='+str(len(df_test)))**
在 Patsy 符号中设置回归表达式。我们告诉 patsy,BB_COUNT 是我们的因变量 y ,它取决于回归变量 X : DAY、DAY_OF_WEEK、MONTH、HIGH_T、LOW_T 和 PRECIP。
**expr = 'BB_COUNT ~ DAY + DAY_OF_WEEK + MONTH + HIGH_T + LOW_T + PRECIP'**
让我们使用 Patsy 为训练和测试数据集绘制出 X 和 y 矩阵:
**y_train, X_train = dmatrices(expr, df_train, return_type='dataframe')y_test, X_test = dmatrices(expr, df_test, return_type='dataframe')**
使用 statsmodels GLM 类,对定型数据集定型泊松回归模型。
**poisson_training_results = sm.GLM(y_train, X_train, family=sm.families.Poisson()).fit()**
打印培训总结。
**print(poisson_training_results.summary())**
这会打印出以下内容:
泊松回归模型的训练总结(图片由作者提供)
我突出显示了输出中的重要部分。
我们可以看到,所有回归系数(回归术语中称为 β 向量)在 95%的置信水平下具有统计显著性,因为它们的 p 值为< 0.05。
稍后将使用最大对数似然值(-11872)来比较模型与 GP-1 和 GP-2 模型的性能。
让我们打印出数据集的方差和均值:
**print('variance='+str(df['BB_COUNT'].var()))print('mean='+str(df['BB_COUNT'].mean()))**
这会打印出以下内容:
**variance=730530.6601948135mean=2680.042056074766**
方差显然比平均值大得多。数据非常分散,泊松模型的主要假设不成立。
因此,我们接下来将构建和训练 GP-1 和 GP-2 模型,看看它们的表现是否会更好。
Statsmodels 让您用 3 行代码就可以做到这一点!
建立 Consul 的广义毒物回归模型,称为 GP-1:
**gen_poisson_gp1 = sm.GeneralizedPoisson(y_train, X_train, **p=1**)**
拟合(训练)模型:
**gen_poisson_gp1_results = gen_poisson_gp1.fit()**
打印结果:
**print(gen_poisson_gp1_results.summary())**
这会打印出以下内容(我在输出中突出显示了一些有趣的区域):
GP-1 模型的训练结果(图片由作者提供)
请注意,除了日变量的系数,所有其他回归系数在 95%的置信水平下具有统计显著性,即它们的 p 值> 0.05。回想一下,在泊松模型中,发现所有回归系数在 95%的置信水平下具有统计显著性。
GP-1 模型的拟合优度
GP-1 模型的最大似然估计为-1350.6,大于零模型的最大似然估计-1475.9。零模型是简单的仅截距模型,即穿过 y 截距的水平线。但是这种差异在统计学上有意义吗?似然比(LR)检验的 p 值显示为 3.12e-51,这是一个非常小的数字。因此,是的,GP-1 模型确实比简单的仅截取模型在数据建模方面做得更好。
但是 GP-1 比常规泊松模型做得更好吗?
回想一下,常规泊松模型的最大似然估计是-11872。与 GP-1 的 MLE-1350.6 相比。显然,GP-1 产生了更好的拟合优度(它有更大的最大似然估计)。如果我们愿意,我们可以使用两个似然估计值进行 LR 检验,并使用卡方检验评估显著性。在这种情况下,这是不必要的,因为 GP-1 的最大似然比常规泊松模型的大得多。
预言;预测;预告
让我们使用 GP-1 预测骑自行车的人数,使用模型在训练期间没有看到的测试数据集:
**gen_poisson_gp1_predictions = gen_poisson_gp1_results.predict(X_test)**
gen_poisson_gp1_predictions 是一个 pandas 系列对象,它包含 X_test 矩阵中每一行的预计骑自行车的人数。记住 y_test 包含实际观察到的计数。
让我们绘制预测和实际计数,以直观地评估预测的质量:
**predicted_counts=gen_poisson_gp1_predictions
actual_counts = y_test[**'BB_COUNT'**]fig = plt.figure()fig.suptitle(**'Predicted versus actual bicyclist counts on the Brooklyn bridge'**)predicted, = plt.plot(X_test.index, predicted_counts, **'go-'**, label=**'Predicted counts'**)actual, = plt.plot(X_test.index, actual_counts, **'ro-'**, label=**'Actual counts'**)plt.legend(handles=[predicted, actual])plt.show()**
我们得到了预测的和实际的骑自行车的人数的图表:
GP-1 模型中预测的和实际的骑自行车的人数对比图(图片由作者提供)
正如你所看到的,除了一些计数,GP-1 模型在预测骑自行车的人数方面做得相当好。
如果需要,我们可以通过比较 GP-1 预测的均方根误差(RMSE)与常规泊松模型对相同测试数据集的预测,来比较 GP-1 与常规泊松模型的预测质量。我将把它作为一个练习。
最后,让我们也尝试一下法莫耶的受限广义泊松回归模型**,称为 GP-2:**
我们将使用同样的 3 步方法来构建和训练模型。注意参数 p=2:
***#Build Famoye's Restricted Generalized Poison regression model, know as GP-2* gen_poisson_gp2 = sm.GeneralizedPoisson(y_train, X_train, **p=2**)
*#Fit the model* gen_poisson_gp2_results = gen_poisson_gp2.fit()
*#print the results* print(gen_poisson_gp2_results.summary())**
我们看到以下培训输出:
GP-2 模型的训练输出(图片由作者提供)
分析和比较 GP-2 的拟合优度和预测质量的方法与 GP-1 相同。但是请注意,在这种情况下,模型的训练算法无法收敛。因此,我们将不再研究这个模型,而是更倾向于使用 GP-1 而不是标准的泊松模型来对骑自行车的人计数数据进行建模。
源代码
以下是完整的源代码:
这里是本文中使用的数据集的链接。
摘要
- 标准泊松模型假设基于计数的数据的方差与平均值相同。这个假设经常被过度分散或分散不足的真实世界数据集所违背。
- 因此,我们需要对基于计数的数据使用其他模型,如负二项式模型或广义泊松回归模型,它们不假设数据是等分散的。这种模型假设方差是均值的函数。
- Consul 的广义泊松回归模型(称为 GP-1)和 Famoye 的受限广义泊松回归模型(GP-2)就是两个这样的 GP 模型,它们可用于对基于真实世界计数的数据集进行建模。
- Python 库 Statsmodels 恰好对构建和训练 GP-1 和 GP-2 模型提供了出色的支持。
感谢阅读!我撰写关于数据科学的主题,重点是时间序列分析和预测。
如果你喜欢这篇文章,请关注我的Sachin Date获取关于时间序列分析和预测主题的提示、操作方法和编程建议。
用气流概括数据加载过程
构建数据仓库:基本架构原则
数据加载过程不应该写两遍,它们应该是通用的
我们使用 Airflow 作为我们的数据管道编排器,以便轻松地编排和监控数据流程。特别是,我们一直致力于 数据加载过程 以便使它们更容易*。*这些流程允许我们从不同的来源提取数据,并将它们集成到我们的数据湖中——在本例中是 AWS S3。
在我们体验气流的早期,我们会为应该集成到数据湖中的每个数据源创建一个 DAG。然而,过了一段时间,我们最终会得到许多重复的代码。基本上,创建用于提取数据的 Dag 的源代码对于它们中的每一个都是相同的。它们之间唯一的区别是数据库连接和将数据增量装载到数据湖的查询。
重复代码的问题是,当必须引入更改时,它们必须在执行数据加载的每个 Dag 中传播,这既耗时又容易出错。
我们决定通过推广我们为数据加载过程创建 Dag 的方式来解决这个问题。为此,我们构建了一个框架,在这个框架中,为编排数据加载过程创建这样的 Dag 更加容易。因此,在这篇文章中,我们想与你分享框架是如何构建的,以及它如何帮助我们简化数据加载过程。
我们如何解决它?
我们构建了一个旨在简化数据加载的框架。特别是,编写一个配置文件更容易。基于这样一个文件,框架动态生成 DAG ,允许从目标源增量提取数据并上传到 AWS S3。
该框架包括三个逻辑层次:配置文件、 DAG 工厂和加载器:
- 配置文件是 YAML 文件,其中提供了目标源的配置。这种配置可以包括 DAG 配置参数、数据库凭证、表规范、数据类型等等。这样,集成一个新的源代码就像编写一个简单的配置文件一样简单。
- DAG 工厂 基于一种我们称之为 DAG 工厂的模式。它们允许封装逻辑动态创建 Dag。 DAG 工厂模式包括 DAG 接口和工厂。 DAG 接口的功能是读取配置文件并将配置参数传递给适当的工厂,因此工厂可以创建 DAG 工作流,允许从目标源提取数据。我们集成了许多工厂,例如数据库引擎类型*,例如*,我们集成了来自 MySQL 和 MongoDB 引擎的数据。所以,在这一点上,我们只实现了 MySQL 工厂和 MongoDB 工厂。
- 一个 加载器 是一个 docker 映像,它实现了我们所说的加载器模式。基本上,加载器模式基于在数据加载过程中实现功能数据工程方法的。因此,给定一组参数,加载器能够从目标源提取数据并上传到 AWS S3。加载器是确定性的和幂等的,因此它们每次运行时都会产生相同的结果。
你可以在下一张图中找到我们的框架的逻辑结构的图示。
框架逻辑结构
配置文件
接下来,给出一个名为“ databasename ”的 MySQL 数据库的配置文件示例。在配置文件中,指定了一些配置,如 DAG 名称、默认参数、计划、数据库连接和表及其列数据类型。因此,它们可用于动态生成 DAG。
DAG 接口
在 DAG 界面中,读取配置文件信息。然后,根据数据库引擎类型,通过调用适当的工厂方法来创建 DAG 工作流。此外,必要的参数被传递给工厂,以便创建适当的 DAG 工作流。
因此,基于上面指定的配置文件,t
工厂
一个工厂允许动态生成一个 DAG 工作流,允许提取和加载给定目标源的数据。特别是,DAG 工作流将具有与配置文件中指定的表一样多的任务。任务基于通过使用 气流对接操作符 运行适当的加载器对接映像。为此,配置文件中提供的参数应该作为环境变量传递给 docker 映像。
请记住,该框架旨在执行每日增量加载。所以,它就是为此而设计的。为了支持其他用例,应该引入一些更改。
我们在下一段代码中展示了 MySQL 工厂。
最后,这是由 *MySQL 工厂生成的 DAG 工作流的样子。*记住每个任务都是一个运行 MySQL loader 的 airflow docker 操作员。
装货设备
一个加载器是一个 docker 镜像,允许从一个特定的数据库引擎提取数据并上传到我们的数据湖——AWS S3。
在下一段代码中,出现了 MySQL 加载器**。我们试图遵循 Maxime Beauchemin 在这篇文章中提出的功能数据工程方法。相应地,加载器被设计成上下文无关的;它们使用覆盖方法,并且它们的结果是不可变暂存区的一部分。这使得它们易于复制。
结论
我们构建这个框架是基于这样一个信念,即数据加载过程不应该写两次,它们应该是通用的。
我们的解决方案深受功能数据工程范例的影响,该范例由 Maxime Beauchemin 在这篇文章中提出。事实上,你可以在这篇帖子中找到更多关于这种范式如何塑造了装载机的设计方式的信息。
希望这些信息对你有用!
感谢您的阅读!😃
如果你想随时更新我的作品, 请加入我的 简讯 ! 我会努力为你提供信息和资源,让你成为更好的数据从业者!
使用 Python 的 Matplotlib 生成等值线图
制作等高线图的简易教程
我相信你以前见过等高线图。至少在天气数据上是这样。它被大量用于展示气象或地理数据。但它也用来表示密度、亮度和电势。它在数据分析和机器学习中被大量使用。它显示了一个响应变量与两个预测变量的关系。
它给出了一个二维视图,其中具有相同响应的所有点由一条线连接。那条线是轮廓线。
等高线图的三个主要元素:
- x 轴和 y 轴显示预测值
- 等高线来表示相同的响应值
- 提供一系列响应值的彩色条带
下面是如何绘制等高线图
首先导入必要的包。
import numpy as np
import matplotlib.pyplot as plt
import pylab
让我们生成一些 x 和 y 值
xp = np.arange(-8, 10, 2)
yp = np.arange(-8, 10, 2)
你大概可以想象‘XP’和‘yp’是什么样子。不过,还是看看吧。
xp
输出:
array([-8, -6, -4, -2, 0, 2, 4, 6, 8])
输入:
yp
输出:
array([-8, -6, -4, -2, 0, 2, 4, 6, 8])
x 和 y 的长度都是 9。
这个信息很重要,因为我们需要用这个数生成 z。
首先,初始化一个 9 x 9 形状的随机 z 点
zp = np.ndarray((9,9))
zp
输出:
array([[1.20117830e-311, 1.20117830e-311, 1.20120150e-311,
1.20120150e-311, 1.20120150e-311, 1.20120150e-311,
1.20118338e-311, 1.20119781e-311, 1.20120151e-311],
[1.20120150e-311, 1.20120151e-311, 1.20117830e-311,
1.20117830e-311, 1.20118045e-311, 1.20120150e-311,
1.20119863e-311, 1.20119863e-311, 1.20117830e-311],
[1.20119864e-311, 1.20118316e-311, 1.20117850e-311,
1.20117830e-311, 1.20118500e-311, 1.20118500e-311,
1.20118490e-311, 1.20118488e-311, 1.20118316e-311],
[1.20118500e-311, 1.20118493e-311, 1.20118493e-311,
1.20118493e-311, 1.20118493e-311, 1.20118339e-311,
1.20117862e-311, 1.20117835e-311, 1.20118337e-311],
[1.20118339e-311, 1.20118338e-311, 1.20118347e-311,
1.20118348e-311, 1.20118339e-311, 1.20118348e-311,
1.20118316e-311, 1.20118338e-311, 1.20118348e-311],
[1.20118339e-311, 1.20118348e-311, 1.20118347e-311,
1.20118348e-311, 1.20118348e-311, 1.20118348e-311,
1.20118339e-311, 1.20118339e-311, 1.20118333e-311],
[1.20118348e-311, 1.20118348e-311, 1.20118348e-311,
1.20117830e-311, 1.20117830e-311, 1.20117853e-311,
1.20117830e-311, 1.20117830e-311, 1.20117830e-311],
[1.20117830e-311, 1.20117830e-311, 1.20117830e-311,
1.20117830e-311, 1.20117830e-311, 1.20117830e-311,
1.20117830e-311, 1.20117830e-311, 1.20117830e-311],
[1.20117830e-311, 1.20117830e-311, 1.20117830e-311,
1.20117830e-311, 1.20117830e-311, 1.20117830e-311,
1.20117830e-311, 1.20117830e-311, 0.00000000e+000]])
现在,我将用自己选择的公式替换这些随机值。你可以使用你想要的或者你需要的公式。
for x in range(0, len(xp)):
for y in range(0, len(yp)):
zp[x][y] = xp[x]**2 + yp[y]**2
zp
输出:
array([[128., 100., 80., 68., 64., 68., 80., 100., 128.],
[100., 72., 52., 40., 36., 40., 52., 72., 100.],
[ 80., 52., 32., 20., 16., 20., 32., 52., 80.],
[ 68., 40., 20., 8., 4., 8., 20., 40., 68.],
[ 64., 36., 16., 4., 0., 4., 16., 36., 64.],
[ 68., 40., 20., 8., 4., 8., 20., 40., 68.],
[ 80., 52., 32., 20., 16., 20., 32., 52., 80.],
[100., 72., 52., 40., 36., 40., 52., 72., 100.],
[128., 100., 80., 68., 64., 68., 80., 100., 128.]])
因此,我们已经准备好了 x、y 和 z 数据。下面是如何做等高线图。
plt.figure(figsize=(7, 5))
plt.title('Contour Plot')
contours = plt.contour(xp, yp, zp)
plt.clabel(contours, inline=1, fontsize=12)
plt.show()
马鞍面等高线图
我将用一个稍微不同的 z 值公式来完成完全相同的过程。所以这次我就不一步步解释了:
xp = np.arange(-3, 4)
yp = np.arange(-3, 4)zp =np.ndarray((7,7))for x in range(0, len(xp)):
for y in range(0, len(yp)):
zp[x][y] = xp[x]*xp[x] - yp[y]*yp[y]plt.figure(figsize=(8, 6))
plt.title('Contour plot for saddle surface - Hyperbolic paraboloid')
contours = plt.contour(xp, yp, zp)
plt.clabel(contours, inline=1, fontsize=12)
plt.show()
密度图
这是一张密度图。因此,我将制作一个不同的数据集,其中数据点更接近。这是 x 和 y。
x = np.linspace(0, 5, 60)
y = np.linspace(0, 5, 48)
x 和 y 都是一样的。数据看起来是这样的:
array([0\. , 0.08474576, 0.16949153, 0.25423729, 0.33898305,
0.42372881, 0.50847458, 0.59322034, 0.6779661 , 0.76271186,
0.84745763, 0.93220339, 1.01694915, 1.10169492, 1.18644068,
1.27118644, 1.3559322 , 1.44067797, 1.52542373, 1.61016949,
1.69491525, 1.77966102, 1.86440678, 1.94915254, 2.03389831,
2.11864407, 2.20338983, 2.28813559, 2.37288136, 2.45762712,
2.54237288, 2.62711864, 2.71186441, 2.79661017, 2.88135593,
2.96610169, 3.05084746, 3.13559322, 3.22033898, 3.30508475,
3.38983051, 3.47457627, 3.55932203, 3.6440678 , 3.72881356,
3.81355932, 3.89830508, 3.98305085, 4.06779661, 4.15254237,
4.23728814, 4.3220339 , 4.40677966, 4.49152542, 4.57627119,
4.66101695, 4.74576271, 4.83050847, 4.91525424, 5\. ])
和之前一样,我需要一个 z 的函数。这是我选择的函数,
def fn(x, y):
return np.sin(x)**5 + np.cos(y+17)**8
现在,该准备 X、Y 和 Z 数据了。我将简单地在 x 和 y 上使用 np.meshgrid 函数,它从一维数组构建二维网格。
X, Y = np.meshgrid(x, y)
Z = fn(X, Y)
数据准备好了。这是最简单的黑白密度等值线图。
plt.contour(X, Y, Z, colors = 'black')
让我们添加一个色彩映射表,并指定我们希望在该范围内绘制 15 条等距线。
plt.figure(figsize=(8, 6))
contours = plt.contour(X, Y, Z, 15, cmap = 'RdGy')
plt.clabel(contours, inline=True, fontsize=12)
matplotlib 中还有一个函数是 contourf。现在,看一个 contourf 的例子。
plt.figure(figsize=(14, 10))
plt.contourf(X, Y, Z, 20, cmap = 'RdGy')
plt.colorbar()
“imshow”的一个例子:
plt.figure(figsize=(14, 10))
plt.imshow(Z, extent=[0,6,0,6], origin='upper', cmap='RdGy')
plt.colorbar()
我们甚至可以把黑白等高线图放在这个 imshow 上面。
plt.figure(figsize=(14, 10))
contours = plt.contour(X, Y, Z, 15, colors='black')
plt.clabel(contours, inline=True, fontsize=12)plt.imshow(Z, extent=[0,6,0,6], origin='upper', cmap='RdGy', alpha=0.5)
plt.colorbar()
我喜欢!你呢?
结论
如果你以前从未画过等高线图,我希望你现在能在必要的时候画出来。它提供了大量的信息,而且看起来也不错!如果您是机器学习建模者,请使用等值线图来可视化不同类别中的范围或数据中的异常。
更多阅读:
完整的可视化课程
towardsdatascience.com](/your-everyday-cheatsheet-for-pythons-matplotlib-c03345ca390d) [## Numpy 完全指南
日常工作中需要的所有数字方法
towardsdatascience.com](/a-complete-guide-to-numpy-fb9235fb3e9d) [## 练习数据科学技能和制作优秀投资组合所需的所有数据集
一些有趣的数据集提升你的技能和投资组合
towardsdatascience.com](/all-the-datasets-you-need-to-practice-data-science-skills-and-make-a-great-portfolio-857a348883b5) [## 逻辑回归模型拟合和寻找相关性,P 值,Z 值,置信度…
静态模型拟合和提取的结果从拟合模型使用 Python 的 Statsmodels 库与…
towardsdatascience.com](/logistic-regression-model-fitting-and-finding-the-correlation-p-value-z-score-confidence-8330fb86db19) [## 学习使用 Python 的 Scikit_learn 库通过项目开发 KNN 分类器
适合机器学习新手
towardsdatascience.com](/clear-understanding-of-a-knn-classifier-with-a-project-for-the-beginners-865f56aaf58f) [## 无限免费虚拟主机和域名
非常适合投资组合、开博客或创业
towardsdatascience.com](/unlimited-free-hosting-and-domain-5998e14f7bfe)
使用 Pylustrator 生成易于复制的科学图形
Python 科学绘图
使用基于 GUI 的程序生成可重复的 Python 绘图脚本
几个月前,我写了一篇关于用 Python 生成科学出版物图的文章。最近,我发现了这个名为 Pylustrator 的令人难以置信的新包,它大大简化了制作多面板图形的过程,而无需摆弄轴的大小。该软件包还会为您生成 Python 代码,因此您可以重现并与他人分享您的数据。在这篇文章中,我将做一些你可以用pylustrator
做的事情的基本演示——希望它对你的剧情制作有用!
安装
您可以使用以下命令使用pip
安装pylustrator
:
pip install pylustrator
生成地块
首先,我们将把matplotlib
、numpy
(创建一些虚拟日期)和pylustrator
导入到我们的脚本中:
**# Import packages** import matplotlib.pyplot as plt
import numpy as np
import pylustrator
我将使用我们在上一篇文章中开发的科学的matplotlib
样式文件作为起点,这样我们就不必重复地改变字体、刻度大小等属性。在pylustrator
中:
**# Use scientific plot style** plt.style.use('scientific')
现在,我们可以创建我们的图形——因为我们将在pylustrator
中完成大部分操作,我们只需要创建最基本的图形,而不考虑格式。首先,让我们创建一些虚拟数据:
**# Create dummy data**
x = np.linspace(0, 4*np.pi, 200)
y1 = np.sin(x)
y2 = np.cos(x)
在我们开始创建图之前,我们将调用pylustrator
函数:
**# Start pylustrator**
pylustrator.start()
现在让我们开始创建我们的基本图形。回想一下,当我们调用add_subplot(rows, cols, index)
时,三个参数如下:
rows
—我们的多点图中的行数
cols
—我们的多点图中的列数
index
—子情节的索引,从左上角开始,向右下方蜿蜒
**# Create panelled figure**
fig = plt.figure()
ax1 = fig.add_subplot(311)
ax2 = fig.add_subplot(312)
ax3 = fig.add_subplot(313)**# Plot data
# Subplot 1**
ax1.plot(x, y1, label='y1')
ax1.plot(x, y2, label='y2')
ax1.legend()**# Subplot 2**
ax2.plot(x, y1)**# Subplot 3**
ax3.plot(x, y2)
现在,我们最后必须在脚本末尾添加一个plt.show()
来显示我们的情节,这样我们就完成了代码的编写!
**# Show plot** plt.show()
运行 Pylustrator
因为我们已经添加了一行pylustrator.start()
,我们可以继续运行我们的脚本文件:
python <your_filename>.py
然后,您应该会看到弹出以下屏幕:
调整大小/重新排列图形
我们可以很容易地改变我们的情节安排,通过点击每个支线剧情,调整我们需要的大小,并四处拖动:
编辑刻度间隔
还有一些菜单可以调整我们的图的刻度间隔:
编辑图例
我们可以单击图例,切换一些选项,并像处理我们的图一样移动它:
添加文本注释
当创建面板图时,您需要用数字或字母标记每个子图,以便在文本中引用它。这也很简单!
救国新图
完成编辑后,我们可以通过使用Ctrl/Cmd + S
并关闭pylustrator
GUI 窗口来保存我们的图形。您会注意到代码将被添加到您原来的.py
文件中。
现在,我们可以从脚本中删除pylustrator.start()
命令,然后直接运行我们的文件来查看我们编辑过的图形!
酷!你现在可以分发这个.py
文件,而不需要pylustrator
,任何人都应该能够重现你的形象!
结论
我们仅仅触及了pylustrator
的一些特性,但是它看起来是一个不可思议的工具,可以为你的出版物/文章编辑你的 Python 图形。本文中的plot.py
文件可以在这个 Github 资源库中获得。
感谢您的阅读!我感谢任何反馈,你可以在 Twitter 上找到我,并在 LinkedIn 上与我联系,了解更多更新和文章。
参考文献
格勒姆河(2020 年)。py literator:用于出版的可复制图形的代码生成。开放源码软件杂志,5(51),1989 年。
使用 Python 生成虚假的唐纳德·特朗普推文
马尔可夫模型和 RNN 文本生成的比较
萨拉·库菲在 Unsplash 上拍摄的照片
让我们使用机器学习来生成模仿唐纳德·特朗普的语言和风格的虚假推文!许多介绍性的机器学习教程都专注于分类任务,如 MNIST,所以我希望你喜欢这篇关于生成模型的文章。
我们将首先使用一种相对简单的方法来完成这项任务,称为马尔可夫模型,我们将从头开始编写代码(我使用的唯一的库是 NumPy)。然后,我们将看一看更高级的递归神经网络实现。我的希望是,首先通过马尔可夫模型的简单例子,可以更容易理解 RNN 模型是如何工作的。
数据
特朗普推特档案包含唐纳德·特朗普的 3 万多条推文。访问网站以 CSV 或 JSON 文件的形式下载给定日期范围内的推文。有一个选项可以下载每条推文的元数据(赞数、转发数、时间戳等)。),但是现在,我们只需要原始文本。
特朗普的所有 30,000 多条推文都可以立即搜索到
www.trumptwitterarchive.com](http://www.trumptwitterarchive.com/archive)
方法 1: N 元马尔可夫模型
背景
Markov 模型查看文本中的 n-gram(n 个字符的子字符串),并计算每个 n-gram 出现在训练文本中时各种字母跟随它的频率。这是一种相当简单的语言表达方式,它很容易编程,在我上大学的时候,用 Java 做这件事是《CS 导论》中的一个作业。
为了更深入地理解这是如何工作的,假设我们的训练文本由一个随机的英语大样本组成,使用的 n 元语法大小为 3。马尔可夫模型一旦建立,就应该存储一个字典,其中的关键字是 n-gram(文本中出现的所有 3 个字符的子字符串),值是从字符到频率的映射(给定字符跟随给定 n-gram 的次数)。例如,如果为模型提供了 n 元单词“mac”,那么模型将知道下一个字母是“h”(像“machine”或“machete”这样的单词)的概率高于下一个字母是“z”(我想不出任何包含“macz”的单词)的概率。另一方面,给定 n-gram“piz”,模型应该给下一个字母是“z”(像“pizza”和“pizzeria”这样的词)比下一个字母是“h”更高的概率。
该模型本质上是一个将 n 字符序列映射到字符频率字典的字典。给定频率后,我们就可以归一化来寻找概率。
在语言语料库上对此进行训练会将训练数据的特征结合到模型中。如果你对它进行莎士比亚方面的训练,它将学会莎士比亚的词汇、表达和典型的莎士比亚戏剧的格式。如果你在 Twitter 数据集上训练它,你会看到标签、Twitter 句柄、URL 等。
n 元语法的大小越大,输出的文本就越“真实”。n 的值很小,就像一个人在到达末尾时忘记了他们是如何开始一个句子的。同时,具有大的 n 值将使模型更有可能从原始文本中再现精确的单词和短语,而不是产生新的句子。
加载数据
让我们直接进入马尔可夫模型的代码(完整的代码可以在这里找到)。首先,我们读入并稍微预处理特朗普的推文。我们通过将所有推文连接在一起并去掉换行符来创建一个庞大的字符串。我们将保留大写,因为这在 tweet 的上下文中通常是有意义的。
f = open("trump_tweets_all.txt")
text = " ".join(f.readlines())
text = " ".join(text.split())
text = text.encode("ascii", errors="ignore").decode()
text.replace("&", "&")
f.close()
构建模型
接下来,我们必须定义 MarkovModel 类。它的构造函数将接受 n-gram 大小n
和训练文本。然后,我们在文本中移动大小为n
的滑动窗口,并构建一个字典,其中每个 n 元语法都映射到它自己的字典,该字典包含从字符到计数的映射。当我们滑动窗口时,我们获取紧跟在当前 n-gram 后面的字符,并更新对应于给定 n-gram 字典中该字符的计数。你在 n-gram ‘mac ‘后面看到一个’ h ‘的次数越多,在’ mac’ n-gram 的字典中’ h '的计数就越高。口头上解释这个有点混乱,那就用视觉形式试试吧。
上图说明了如何根据训练文本构建模型。在这个例子中,n-gram 的大小是 3(绿色字符的数量)。每个 n-gram 的字符计数字典根据下面的字符(用红色突出显示)进行更新。下图解释了我们试图创建的数据结构。当然,在通读了整个训练文本之后,这将是一部巨大的字典!
{
"The": {" ": 1, ...},
"he ": {"U": 1, ...},
"e U": {"n": 1, ...},
" Un": {"i": 1, ...},
...
}
马尔可夫模型有一个get_next_char()
方法,它采用一个 n-gram,并根据它在构造器阶段学习到的概率分布选择下一个字符。当然,我们不希望这个方法总是为同一个 n-gram 返回同一个字符,所以必须有一点随机性,但是它应该遵循从文本中学习到的权重。NumPy 函数numpy.random.choice()
在这里是个大帮手。
为了生成更长的字符串,我们反复调用get_next_char()
方法。每当方法返回一个字符时,我们从 n-gram 中截取第一个字符并追加返回的字符。
def get_n_chars(self, length, ngram):
*"""Returns a generated sequence of specified length,
using the given n-gram as a starting seed."""* s = []
for i in range(length):
nextchar = self.get_next_char(ngram)
ngram = ngram[1:]+nextchar
s.append(nextchar)
return ''.join(s)
结果
下面是模型输出的一些例子(我提供了第一个n
字符,其余的由它填充)。
n=13,start string = “Hillary Clint”
希拉里·克林顿一直在如此努力地工作,而且受了如此严重的伤。我们继续生产以下地面以上高度的产品@ NHC _ 大西洋:随着墨西哥湾沿岸危险条件的到来。请一定要投票给奥巴马。他不需要任何帮助——但是我正在给各种慈善机构捐款。
n=7,start string = “希拉里”
希拉里举了整整一个小时,这非常重要。明天中午。我会更好。今晚两分钟后加入我在加州的民主党)不要存在腐败!DJT 仍然没有证据表明天然气是为 TT 提供帮助的——但我们正在对如此小的马尔科鲁伯进行一项运动调查
观察
很酷地看到,这个模型能够识别所有没有以任何方式硬编码到系统中的语言特征。它只是查看 n-grams 后字符的统计分布,然而它能够正确拼写单词(大多数情况下),使用标点符号和大写字母,有时甚至创建伪语法句子。
这种方法的一个缺点是,特别是对于小的训练文本,这种方法可能导致从源文本复制长串内容,而不是创建新的组合。理想情况下,我们希望模型能够提取拼写和语法等语言特征,但产生新的单词字符串,而不是简单地重复训练数据的长块(即一次几个单词)。Markov 模型的另一个缺点是,我们提供给 generate 方法的起始字符串必须是在训练文本中找到的 n-gram。如果你喂它一个它从未见过的 n-gram,那么它就不知道如何处理。下一节将介绍一个更高级的文本生成模型。
完整的代码和数据:https://github.com/thomashikaru/faketrumptweets
方法 2:递归神经网络
背景
递归神经网络因其能够解决复杂的机器学习问题而受到广泛关注。RNNs 从根本上不同于其他类型的神经网络,如简单的前馈网络或卷积神经网络,因为网络的当前状态被“记住”并作为下一个时间步骤的输入。参见下面的文章,了解一些有趣的背景和例子。
递归神经网络(rnn)有一些神奇的东西。我仍然记得当我训练我的第一个循环…
karpathy.github.io](http://karpathy.github.io/2015/05/21/rnn-effectiveness/)
准备培训示例
我们需要做的第一件事是确定词汇表——训练文本中的独特字符集。如果您包括大写字母、小写字母、数字、空白和特殊字符,这将带给我们大约 90 个独特的字符。然后,文本必须从字符串转换为数字列表,数字和字符之间存在一对一的映射。字符串"abcba"
可能会变成类似于[1, 2, 3, 2, 1]
的东西。
每个训练示例将由一个输入序列和一个目标序列组成,每个序列都有 n 个字母。目标序列就是去掉第一个字符并添加下一个字符的输入序列。如果原始文本包含序列"Donald"
,那么我们可以形成一个输入-目标对("Donal", "onald")
。看到许多这样的字符对将允许模型学习什么字符通常遵循序列"Donal"
,并且希望任何其他序列。
我使用 Tensorflow 和 Keras 创建了 RNN,遵循了 Tensorflow 网站的教程中使用的结构。网络由以下几层组成:单词嵌入层、GRU 层和全连接(“密集”)层。
模型概述。
把…嵌入
嵌入层将输入的字符序列转化为数值,并嵌入到一个高维向量空间中。因此,每个字符首先被映射到一个整数(词汇表中的索引),然后每个整数被映射到一个向量(在我的代码中,是一个 64 维的向量)。
我们为什么要这样做?字符嵌入很重要,因为它创建了比仅使用索引更有意义的输入数字表示。说字母“a”对应于数字 1,字母“z”对应于数字 26 是完全武断的。理想情况下,出现在相似上下文中的字符应该有相似的向量。嵌入层允许模型在训练期间学习词汇字符的良好矢量表示。
苏军总参谋部情报总局
GRU 是基本 RNN 体系结构的一种变体,已经非常有效地应用于许多自然语言任务。在这里和这里可以看到关于 RNNs、LSTMs 和 GRUs 的精彩文章,它们很好地解释了它们是如何工作的以及为什么工作。
培养
为了训练这个模型,我们需要为我们的模型附加一个优化器和损失函数。损失函数计算预测输出和正确目标序列之间的分类交叉熵损失,如我们之前制作的训练样本中所定义的。请注意,模型的输出是词汇表中每个字符的概率序列(嗯,技术上是对数概率)。损失函数应该奖励将高对数几率分配给正确字符的模型,惩罚将高对数几率分配给错误字符的模型。
def loss(labels, logits):
return tf.keras.losses.sparse_categorical_crossentropy(labels, logits, from_logits=True)
完成后,我们可以建立一个检查点目录,并开始培训!我用笔记本电脑的 CPU 和 Google Colab 上提供的免费 GPU 进行了实验。GPU 的训练速度快了大约 10 倍。Tensorflow 教程建议训练大约 30 个周期,以获得不错的结果。
发生
一旦模型被训练,我们使用与马尔可夫模型相似的过程来生成虚假推文。像以前一样,我们需要提供一个开始字符串,尽管它可以是任意长度,不一定是训练文本中存在的子字符串。该模型被反复评估,每次生成一个新的字符。然后,这个新字符作为输入被输入到模型中,模型仍然“记住”它在上一步中看到的文本。最后,我们打印所有生成字符的连接。
def generate_text(model, start_string):
num_generate = 280
input_eval = [char_to_index[s] for s in start_string]
input_eval = tf.expand_dims(input_eval, 0)
text_generated = []
model.reset_states() for i in range(num_generate):
predictions = model(input_eval)
predictions = tf.squeeze(predictions, 0)
predicted_id = tf.random.categorical(predictions, num_samples=1)[-1, 0].numpy()
input_eval = tf.expand_dims([predicted_id], 0)
text_generated.append(index_to_char[predicted_id]) return start_string + ''.join(text_generated)
结果
以下是 RNN 的一些示例输出(我提供了起始字符串,它填充了其余部分):
开始弦乐:“美”
美国已经达成了一个代理,谁做了一个非常大的交易改变了男人&这将…纽约必须知道这本书,但它是关于他的。因为他们会找到任何抗议声明。关闭新的,我们给所有参与给我们带来新书十亿美元扔出一个骄傲的坏。伤心!
开始字符串:“希拉里·克林顿”
希拉里·克林顿在 CNBCNBC 的 today-RESSUDEMINT
上离开了夜晚,我们必须测试 200 亿美元将会建造的凯尔索的经济效益。
俄罗斯最愚蠢的愤怒和资助。
@ bassuckstmannieseal&@ dn some 1 z @ CNN 找链接人肯定是川普国际早安美国】http://t.co/AhYnMlbaement
观察
考虑到 RNN 比马尔可夫模型复杂得多,结果似乎并不令人印象深刻。然而,重要的是要记住,rnn 通常是在数百兆字节的数据上训练的,远远超过这个训练集中的大约 3 万条特朗普推文。此外,通过调整超参数或将多个 RNN 图层添加到模型中,您可能会获得更好的结果。您可以试验不同的序列长度值、嵌入维数或 gru 数。
RNNs 的一个缺点是训练速度很慢。出于许多实际目的,GPU 对于实现合理的训练时间是必要的,即使这样也需要一些耐心。考虑使用 Google Colab,其中包括对 GPU 的有限免费访问,来试验 RNNs。你可以在云端训练,让你的机器不会过热!
完整的代码和数据:https://github.com/thomashikaru/faketrumptweets
结论
如果你想自己学习这些话题,我建议你找一个像这样的迷你项目,你可以真正地投入其中并享受其中。这将有助于你保持动力,你将从自己的项目实践中学到比被动阅读或观看教程更多的东西。
在更严格的设置中,我们可能希望使用某种度量来评估我们的生成器,但这实际上是相当具有挑战性的。评估文本输出的质量比评估分类器复杂得多,在分类器中,您只需要将预测与标签进行比较。这篇伟大的文章讨论了一些用于评估 NLP 中文本输出的指标。
感谢阅读!欢迎留下您的反馈,祝您学习顺利!
参考资料:
[1] Andrej Karpathy,递归神经网络的不合理有效性 (2015)。
[2] Tensorflow,文本生成与 RNN (2020)。
[3]普林斯顿大学计算机科学系,自然语言的马尔可夫模型 e (2020)。
[4] M. Phi,LSTM 和 GRU 的图解指南:一步一步的解释 (2018),中等。
[5] M. Phi,循环神经网络图解指南 (2018),中。
通过深度学习为您最喜欢的类型生成新鲜的电影故事
微调 GPT 新协议,根据类型生成故事
在发现时间旅行后,地球居民现在生活在由政府控制的未来派城市中,为期十年。政府计划向该市派遣两个精英科学家小组,以便调查这些机器的起源并发现“上帝”的存在。
为你喜欢的类型创作故事不是很有趣吗?这就是我们今天要做的。我们将学习如何构建一个基于流派创建故事的故事生成器,就像上面创建科幻故事的生成器一样(在上面的故事中,用户提供的输入是粗体的)。
你也可以把这篇文章作为开发你自己的文本生成器的起点。例如,您可以生成科技、科学和政治等主题的标题。或者生成你喜欢的艺术家的歌词。
为什么是故事生成?
作为一个狂热的电影和电视剧迷,我喜欢故事生成器的想法,它可以根据类型、输入提示甚至标题生成故事。在了解了 GPT 2 号之后,我想把这个想法变成现实。这就是我建造这个模型的原因。
预期用途:寻找乐趣并测试融合讲故事的想法,我们可以通过混合我们的创造力(通过提供提示)和模型的创造力(通过使用提示生成故事的其余部分)来生成故事。
预告片时间:测试故事生成器!
Alex Litvin 在 Unsplash 上拍摄的照片
在深入构建生成器之前,让我们先尝试一下故事生成。在这个 Huggingface 链接 查看我的故事生成器或者运行这个 Colab 笔记本中的单元格来生成故事。模型输入格式的形式如下:
< BOS > <流派>可选提示……
例如发现时间旅行后,
所属类型所属:超级英雄、科幻、动作、剧情、恐怖、惊悚
模型将使用这个提示生成它的故事。还有一种更直观的方式来生成故事:一个使用我的模型 的 网络应用(记住这个应用的生成比hugging face link慢)。
现在你已经完成了对模型的实验,让我们来探索这个想法:我们正在一个包含不同流派电影情节的数据集上微调 OpenAI GPT-2 模型。本演练遵循三幕结构:
- 第一幕:什么是新 GPT 协议?
- 第二幕:微调时间……
- 第三幕:生成时间!
第一幕:什么是 GPT-2?
马特·波波维奇在 Unsplash 上的照片
如果你熟悉 GPT 2 的关键思想,你可以快进到下一幕。否则,请快速复习下面的 GPT 新协议。
最近,我们看到了文本生成模型 GPT-3 背后的巨大宣传,以及它在使用零触发学习生成代码等任务中令人眼花缭乱的表现。GPT 2 号是 GPT 3 号的前身。
等等,为什么我们用 GPT 2 号而不是 GPT 3 号?嗯,还在测试阶段。还有…
正如其炒作一样,GPT-3 的尺寸也是 硕大 ( 传言要求350 GB RAM)。虽然体积仍然庞大,但 GPT-2 占用的空间少得多(最大的变体占用 6GB 磁盘空间 )。它甚至有不同的尺寸和。所以,我们可以在很多设备上使用它(包括iphone)。
如果你在寻找 GPT-2 的详细概述,你可以直接从马嘴那里得到。
但是,如果你只是想快速总结一下 GPT 2 号,这里有一个经过提炼的纲要:
- GPT-2 是一个文本生成** 语言模型 使用一个解码器专用变压器(一个变压器架构的变体)。如果这看起来像是胡言乱语,只需知道 Transformer 是用于 NLP 模型的最先进的架构。**
- 它被预先训练(具有 40GB 的文本数据 ),任务是预测作为输入的前一文本在每个时间步长的下一个单词(更正式地说,令牌)。
第二幕:微调时间…
照片由 Kushagra Kevat 在 Unsplash 上拍摄
我们可以在选定的数据集上微调(进一步训练)像 GPT-2 这样的预训练模型,以适应该数据集的性能。为了微调和使用 GPT-2 预训练模型,我们将使用 拥抱脸/变形金刚 库。它为我们做了所有繁重的工作。
出于这个想法,我通过清理、转换和组合 Kaggle 维基百科电影情节数据集 以及从维基百科搜集的超级英雄漫画情节来创建数据集文件。
培训文件有 3 万多个故事。文件中的每一行都是这种格式的故事:
<博斯> <流派>故事到此为止……
类型:超级英雄、科幻、恐怖、动作、剧情、惊悚
要为另一项任务创建自己的数据集,如基于主题生成研究论文摘要,每个示例的格式可以如下所示:
< BOS > <科目>摘要此处……
科目:物理、化学、计算机科学等。
我推荐你在 Google Colab 上训练模型(设置运行时为 GPU )。用于微调的 colab 笔记本的链接我们的型号是这里的。您可以创建此 笔记本 的副本,并为您自己的数据集进行修改。****
这里有6 _ genre _ clean _ training _ data . txt(训练文件)和6 _ genre _ eval _ data . txt(评估文件),你需要在运行代码之前上传到你的 Colab 笔记本的环境中。****
在这篇文章中,我将介绍 Colab 笔记本中的一些核心代码。
**!pip install transformers torch**
上面,我们正在安装核心库。我们需要变形金刚库来加载预先训练好的 GPT-2 检查点并对其进行微调。我们需要手电筒,因为它是用来训练的。
注意:我从这个变形金刚示例文件中取出代码,并对其进行了修改。
在上面的代码片段中,我们指定了模型的参数(模型参数)、数据参数(数据训练参数)和训练参数(训练参数)。让我们快速浏览一下这些参数的关键论点。要正确检查所有参数,查看这里的。
ModelArguments
- 型号名称或路径:用于指定型号名称或其路径。然后,模型被下载到我们的缓存目录中。查看此处的所有可用型号。这里,我们将模型名称或路径指定为 gpt2 。我们还有其他选项,如 gpt2-medium 或 gpt2-xl。
- model_type :我们指定想要一个 gpt2 模型。这与上面的参数不同,因为,我们只指定型号类型,不指定名称(名称指 gpt2-xl、gpt2-medium 等。).
数据训练参数
- train_data_file :我们提供培训文件。
- eval_data_file :我们提供一个数据文件来评估模型(使用困惑)。困惑衡量我们的语言模型从 eval_data_file 生成文本的可能性。困惑度越低越好。
- 逐行:设置为 true,因为我们文件中的每一行都是一个新的故事。
- block_size : 将每个训练示例缩短为最多只有 block_size 个令牌。
训练参数
下面, n 是指这些参数的值。
- output_dir :微调后的最终模型检查点保存在哪里。
- do_train,do_eval :设置为 true,因为我们正在训练和评估。
- logging_steps :每经过 n 个优化步骤,记录模型的损耗。
- per _ device _ train _ batch _ size:每个训练优化步骤涉及 n 个训练样本。
- num_train_epochs :训练数据集的完整遍数。
- save_steps :在每个 n 优化步骤后保存中间检查点(如果 Colab 在几个小时后保持断开,建议使用)。
- save_total_limit :任意点存储的中间检查点数。
现在,是时候加载模型、它的配置和标记器了。
正在加载模型、标记器和配置
类 AutoConfig 、 AutoTokenizer 、 GPT2LMHeadModel 根据 model_name 加载各自的配置( GPT2Config )、标记器( GPT2Tokenizer )和模型( GPT2LMHeadModel )。
GPT2Tokenizer 对象对文本进行标记(将文本转换成标记列表)并将这些标记编码成数字。注意,令牌可以是单词,甚至是子单词(GPT-2 使用字节对编码来创建令牌)。下面是一个标记化的例子(没有编码)。
在此之后,我们必须将代币编码成数字,因为计算机只处理数字。
我们有 GPT2Config 对象用于根据型号名称加载 GPT-2 型号的配置。
最后,我们有GPT 2 lmheadmodel对象,它根据模型名和 GPT2Config 加载模型。
有些人可能想知道:到底什么是" LMHeadModel ?简单地说,对于文本生成,我们需要一个语言模型(一个为词汇中的标记分配概率分布的模型)。GPT2LMHeadModel 是一个语言模型(它为词汇表中的每个标记分配分数)。所以,我们可以用这个模型来生成文本。
下一个主要步骤是添加特殊的令牌来将模型与我们的数据集成在一起。
数据集有一些特殊的标记,我们需要向模型指定这些标记是什么。我们可以传入一个 special_tokens_dict ,它可以有一些类似“bos_token”的键。要查看哪些键是允许的,请访问此链接。
- bos_token (" < BOS >")是出现在每个故事开头的令牌。
- EOS _ token(“”)是出现在每个故事结尾的 token。
- PAD _ token(“”)是指将较短的输出填充为固定长度的填充令牌。
然而,我们有一些额外的特殊记号(在本例中是我们的流派记号)在我们的 special_tokens_dict 中没有它们自己的键。这些额外令牌可以作为列表放在一个集合密钥“附加 _ 特殊 _ 令牌”下。
如果您正在使用自己的数据集,请用自己的类别替换流派标记。
我们已经为训练做好了准备,所以让我们创建训练者对象。
训练器对象可用于训练和评估我们的模型。
为了创建教练对象,我们指定了模型、数据集以及训练参数(如上所示)。 data_collator 参数用于批量训练和评估示例。
然后,我们调用训练者的训练方法,并在训练后将模型保存到我们的输出目录中。是时候放松一下,让机器训练模型了。
训练完模型后,将模型检查点文件夹从 Colab 下载到您的计算机上。你可以将其部署为 Huggingface 社区模型 ,开发一个 web app ,甚至可以使用该模型开发一个 手机 app 。
第三幕:世代时间!
埃里克·维特索在 Unsplash 上的照片
激动人心的部分来了!如果你渴望创作故事,请在你的 Colab 笔记本中运行下面的单元格!
这里,我们使用了TextGenerationPipeline对象,它简化了我们模型的文本生成,因为它抽象了输入预处理和输出后处理步骤。
**text_generator = TextGenerationPipeline(model=model, tokenizer=tokenizer)**
text_generator 是 TextGenerationPipeline 类的一个对象。我们如何将这个对象作为一个函数来使用?这个类有一个 call method ,允许它的对象像函数一样工作(当使用对象作为函数时调用这个方法)。这里,我们像使用函数一样使用这个对象,通过提供 input_prompt 来生成文本。这就是全部了。
我们还没有解释一些文本生成参数,比如 top_p。如果你想了解这些参数,请跟在片尾字幕后面。
尾声和片尾字幕
概括地说,我们采用了各种类型的电影情节数据集,并将其馈送给 GPT2LMHeadModel 来微调我们的模型,以生成特定类型的故事。使用这些想法,您还可以创建其他数据集来基于这些数据集生成文本。
要测试我的电影故事生成器,请单击此处的(或使用 web app 此处的 )。********
非常感谢 Huggingface 团队 提供的变形金刚库和详细的例子,以及 Raymond Cheng 撰写的这篇 文章 帮助我创建了我的模型。
可选:探索文本生成参数
首先,让我们了解一下 GPT2LMHeadModel 的输出是什么:
当预测下一个标记时,该模型为其词汇表中所有可能的标记生成逻辑。为了简化起见,可以将这些逻辑看作每个标记的分数。具有较高分数(logits)的记号意味着它们有较高的概率成为合适的下一个记号。然后,我们对所有令牌的 logits 应用 softmax 操作。我们现在得到每个令牌的 softmax 分数,该分数在 0 和 1 之间。所有令牌的 softmax 分数总和为 1。这些 softmax 分数可以被认为是在给定一些先前文本的情况下,某个标记成为合适的下一个标记的概率(尽管它们不是)。
以下是参数的基本大纲:
- max_length [int]:指定要生成的令牌的最大数量。
- do _ sample【bool】:指定是否使用采样(比如 top_p 或者使用贪婪搜索)。贪婪搜索是在每个时间步选择最可能的单词(不推荐,因为文本会重复)。
- repetition _ penalty【float】:指定对重复的惩罚。增加重复 _ 惩罚参数以减少重复。****
- 温度【浮动】:用于增加或减少对高逻辑令牌的依赖。增加温度值会减少只有少数令牌具有非常高的 softmax 分数的机会。
- top _ p【float】:指定仅考虑概率(形式上,softmax)得分之和不超过 top_p 值的令牌
- top_k【int】:告诉我们在生成文本时只考虑 top _ k 个标记(按它们的 softmax 分数排序)。
仅此而已。
从现有空间数据生成十六进制地图只需不到 3 个步骤
空间可视化——结合使用 Turf 和 Hextile JavaScript 库来生成十六进制地图
看过许多文章后,我注意到许多人试图为他们当前的空间数据集生成十六进制地图,要么是为了美观(例如仪表板可视化),要么是为了最大限度地减少重叠几何特征造成的空间失真。嗯,我有好消息告诉这些人,因为我最近发现结合使用两个 JavaScript 库可以让用户立即呈现所需的输出,消除了在 Tableau 中添加任何额外计算字段的麻烦。为了方便用户和将来的使用,这个新功能已经被部署到我在 https://tableau-data-utility.onrender.com/的网络应用上。因此,下面是数据转换和结果可视化的快速预览:
图片作者| ( 左)美国各州多边形地图| ( 右)美国各州十六进制地图
上图不涉及 Tableau 中的任何计算。方法是简单地将 GeoJSON 格式的文件预处理成另一个 GeoJSON 文件,该文件渲染六边形而不是多边形。
只需导航至https://tableau-data-utility.onrender.com/并将您的空间数据输入 web 应用程序:
作者图片| US_States.geojson 文件已成功上传至浏览器工具
按作者分类的图像|如果您的空间数据集采用其他格式,如 SHP 或 KML,则在同一页面上还有一个实用工具可用于将您的空间数据输出为所需的 GeoJSON 格式
图片作者|最后,上传 GeoJSON 数据后,选择可用的形状选项-正方形、菱形、六边形和反六边形|继续调整宽度(以米为单位),然后选择“导出 GeoJSON 十六进制地图输出”
作为参考,US_States.geojson 的文件可以在我的 GitHub 上找到,带有上述参数的输出文件—倒六边形+宽度(500,000m)也可以在我的 GitHub 上找到。只需保存文件,并在 Tableau 或 Leafletjs(无论你喜欢哪个 GeoJSON 平台)中渲染它,这就是你得到十六进制地图可视化所要做的一切!
基本上,浏览器工具使用库 Turf 和 Hextile 在后端完成所有繁重的工作,生成十六进制格式的数据。需要注意的是,要确定没有映射到地图任何特定部分的六边形:
按作者分类的图像|空值是指未映射到原始空间文件任何部分的六边形
图片作者|因此,隐藏空值以最大限度地减少生成的地图中的冗余六边形是明智的做法|通常,空值的出现是因为计算出的六边形的质心都不在原始空间数据的任何多边形内
请访问https://tableau-data-utility.onrender.com/随意尝试其他国家省或州的其他数据集——请注意,目前 web 应用程序的标题上有几个选项卡:
作者图片|选择“空间数据到十六进制地图”以访问正确的工具
请随意使用其他 Tableau 数据实用工具——我发布的另一个教程中的网络图到 CSV,以及本教程中的空间数据到 CSV。
希望这有助于简化和减少 Tableau 数据处理中的麻烦!
感谢您的阅读。
获得李思欣·崔和其他作家在媒体上的所有帖子!😃您的会员费直接…
geek-cc.medium.com](https://geek-cc.medium.com/membership)
用 Python 生成有意义的词云
辅导的
从文本中提取有意义的单词并在 python 中创建单词云艺术的方法。
布莱恩·迪金森的插图
你肯定见过一个字云。一般来说,这是一张充满单词的照片,其大小取决于单词在你想要分析的文本中出现的频率。我对此并不知情,但很明显,有人(不确定)对文字云有强烈的反对和支持。我读到过他们是糟糕的、蹩脚的,把他们等同于现代的饼状图,甚至把他们比作新的乌鱼。哎哟。一条鲻鱼?走吧。
布莱恩·迪金森插图
我也看过一些改善 word 云的方法和有用的时候去使用它们。不管你属于哪个阵营,我发现在演示中利用引人注目的图形或视觉效果,可以吸引你的观众,促使他们做出反应,可以开始对话,可以产生影响,并为更详细的分析打开大门。视觉上引人注目的文字云艺术可以吸引读者。也就是说,我不会深入研究单词云的利弊,你可以查看上面的链接。
我们将使用几种不同的方法从文本中提取一些有意义的单词。然后,我们将使用 Python 库 WordCloud、pandas 和 NumPy 生成一些单词云。
WordCloud 是 Python 中的单词云生成器。您可以通过以下命令之一安装 WordCloud。
pip install wordcloud conda install -c conda-forge wordcloud
在这里查看安装细节,在这里可以通读 WordCloud 文档。
数据
我们将使用的数据是 2020 年总统大选的民主党初选辩论。你可以在这里通过 Kaggle 找到完整的数据集。数据已经被清理和过滤。Github repo 包含了清洁步骤。
1|导入库和数据
在创建词云之前,文本停用词应该专门更新到文本的领域。例如,如果我们正在为一家航空公司完成来自客户推文的词云,我们可能会得到像“飞机”、“飞行”、“旅行”这样的词,它们可能对您正在完成的任何分析都没有任何意义。
在这个数据集中,包含了额外的停用词,因为它们在文本中出现了很多,但对分析没有贡献。例如,像’参议员’、众议员’、人民’、事实这样的词都是许多候选人在句子中使用的词,如*‘我同意参议员桑德斯……'或’事实是……’、‘美国人民想要…’*并不一定有助于词义的词为词云。
2.1|方法 1 —使用 WordCloud 处理 创建文字云最简单快捷的方法就是简单地使用 word cloud 处理文字。
文本需要在一个长字符串中,以便 WordCloud 对其进行处理。我们将数据过滤到“ biden ”,创建一个他的回答列表,并连接该列表以创建一个长的文本字符串。然后我们创建单词云对象,使用 generate() 方法,并传递我们的文本字符串。最后,我们使用 plt.imshow 来显示图像。
我们来看看文档中的参数:
停用词 :该参数取一组将从词云中剔除的字符串(词)。我们在这里使用了更新的停用词列表。
背景 _ 颜色 :设置背景颜色,默认为黑色
结果…看起来有点像胡言乱语,看起来没有太多信息。单词’ re ‘、表示’、 make ‘、表示似乎是出现频率最高的单词。这些在乔·拜登的信息中似乎并不太重要,而像’成本’、医疗保险’和’世界’这样的词在背景中。一种选择是继续更新停用词。这个过程的一个挑战是知道何时停止。什么时候你知道你有足够多的单词而不用去掉有用的单词?我并不是对这种方法不屑一顾,我以前用过。
我们可以使用 process_text() 和 words_ 方法分别显示文本中的字数和相对数。
# output
[('re', 148), ('make', 117), ('ve', 106), ('said', 95), ('able', 88)]
[('re', 1.0), ('make', 0.7905405405405406), ('ve', 0.7162162162162162), ('said', 0.6418918918918919), ('able', 0.5945945945945946)]
你可以瞥一眼其他候选词,你会注意到类似的结果,无意义的词出现在列表的较高位置。让我们调整一些额外的 WordCloud 参数来改善显示的单词。
***min _ word _ length:***是一个词必须包含的最小字母数
搭配 _threshold: 是一个催款似然得分。文本中的二元模型必须达到大于此参数的分数,才能算作二元模型。默认值设置为 30。
我们将添加最小单词长度 4 和 collocation _ threshold 3 来包含更多二元模型。最后,也许是最重要的,我将使用一组不同的停用词。原始设置是从 WordCloud 导入的。我将导入并使用 SpaCy 库中提供的停用词,并用我自己的停用词更新列表。没有真正的理由使用 SpaCy 的列表,除了我在过去使用过它,并取得了良好的效果。您可以使用许多不同的停用词库。
左:原始词云|右:更新的停用词和参数
我们看到了相当大的进步!我们得到了一些不同的词,包括像“唐纳德·特朗普”、“巴拉克·奥巴马”、“公共选择”和“中产阶级”这样的词。更多的调整/更新停用词可能会改善这一点。
2.2|方法 2——利用词频 前一种方法使用一串文本。如果不一定能接触到全文或者想直接使用词频怎么办?一个替代 generate() 方法的 WordCloud 是*generate _ from _ frequency()*方法,它将获取一个单词及其频率的字典,并根据计数创建一个单词云。让我们试一试。
我们仍然有全文,所以我们将利用 CountVectorizer 来创建一个字数矩阵。如果你已经有一本计数字典或者一袋单词矩阵,你可以跳过这一步。
单词包数据框的片段
现在我们只需要提取这个数据帧中的一行,创建一个字典,并将其放入 WordCloud 对象中。
左图:使用词云的旧词云|右图:使用词频的新词云
新的词云看起来和以前的版本有些相似。有相似的顶频词,也有一些区别。当使用generate _ from _ frequency方法时,它会忽略一些参数,包括搭配和停用词参数。CountVectorizer 处理文本,包括停用词和词汇化。如果我们想对单词做额外的调整,需要在将它们放入 WordCloud 对象之前完成。我们可以看到’唐纳德’被词条化为’唐’,在这个版本中没有二元模型。
从 frequencies 创建单词云的另一个选项是利用 collections Counter 对象来创建一个字典,您可以在 word cloud 中使用它。这需要对文本进行预处理,包括对单词进行标记,然后使用 counter 对象对每个单词进行计数。如果您需要整个文本,那么使用 WordCloud 对象来完成这个任务会更容易。
2.3|方法 3—对数比值比 从最后两个词云中,我们得到了包含这些候选人所说内容的相当好的词组。如果你查看来自多个候选人的热门单词,你会发现相似的单词开始出现在所有人的面前——但是特定于某个人的单词或短语呢?例如,如果你看过这些辩论,你可能会注意到艾米·克洛布查尔提到*“领先的民主党人”,拜登喜欢数他的分数(“第一”,“第二”)…*)相当经常。我们可以看到某个候选人提到的重要单词或短语,但其他人没有。
回到我们为飞机公司分析客户推文的例子。我们可能希望捕捉客户提及的细分市场。与其他旅客相比,我们的商务旅客是怎么想的?许多词可能是相同的,如’座位’和’体验’,但它们可能与同样提到’座位’和’体验’的紧急旅行者有不同的想法和优先顺序。区分这些词有助于更好地了解这些不同的客户群。
简而言之,我们希望看到某个候选人(比如说皮特·布蒂吉格)的哪些词相对于所有其他候选人来说最常见。我们会对每个候选人都这样做。
为此,我们将使用为每个单词计算的对数比值比的度量,如下所示:
加法平滑用于避免被零除
我们使用单词包数据帧,并使用上面的计算转换每一行。结果是一个数据框,显示了特定候选人说出的每个单词的对数概率。
转换后的单词包数据帧与对数比值比的片段
我们试图找出每个候选人最独特的词。以下是四个候选人的前 10 个单词,你能把它们和正确的候选人匹配起来吗?
从左至右:皮特·布蒂吉格、卡玛拉·哈里斯、伊丽莎白·沃伦、伯尼·桑德斯
按照上面通过词频生成词云的相同步骤,我们现在可以创建一个新的词云。
这个方法的伟大之处在于 n 元文法是用这个方法生成的。我们看到了拜登关于*重塑美国灵魂的信息,以及他提到的针对女性的暴力法案。*还有其他方法可以使用,比如加权对数优势比& tf-idf。
那么我们用哪个文本呢?前提是用文字创造出令人惊叹的视觉对比分析。我将两者结合起来,给出一个候选人常用词和常用词的一般概念。
2.4|组合词典 我们有两种不同的词典/词频(方法 1 & 3),我们可以单独使用或组合使用它们来创建一个无所不包的词云。合并后,我们将再做一个调整。你会注意到一个单词可能会有不同的拼写。像保健和保健。我们将把这些加在一起,以便更好地表达这个词。
这可能看起来有点疯狂。这段代码将第二个字典中最常用单词的频率设置为第一个字典中最常用单词的频率。
我们现在合并字典,将“healthcare”和“health care”合并成一个关键字,以便更好地表示。下面显示了前 5 个条目和词云。
[('number number', 56),
('argued', 44),
('special forces', 41),
('single solitary', 41),
('restore soul', 40)]
很好,我们看到了候选人频繁使用的两个世界的融合,以及候选人独有的常用词。我们有我们的文本接下来将创建我们的自定义单词云。
3 |准备照片 这一步不是用 python 完成的。你需要找到一个图像来使用。有很多免费的图片收藏网站可以选择,比如:Unsplash、Pixabay、Pexels 和 T10。
一旦你找到一张照片,它需要被转换成黑色&白色。照片的黑色部分将是文字显示的地方,白色区域将显示为白色。你可以在 Photoshop 等照片编辑软件中完成这一点,也可以在网上用免费的照片编辑软件如 Pixlr 来完成。我用这两种方法很容易地将背景从图片的主体中分离出来。有些照片比其他照片需要多一点时间。
左图由量具 Skidmore CC BY-SA 2.0 提供
专业提示:在创建照片时,确保背景确实是白色的,而不是透明的。透明像素值将被导入为 0 或黑色,不会给你一个蒙版图像。
3 |导入照片并创建单词云 有多种方法可以给你的单词云中的单词上色。我将详细介绍两个,您可以在 Github repo 中看到第三个。第一个是利用彩色地图。
好了,让我们来看一下这段代码。第一行导入您的黑白图像,第二行在创建图像时调整任何细微的颜色差异。我让 Adobe Illustrator 给我一个介于 240 和< 255 之间的更大范围的“白色”像素值,创建一个无法工作的图像。所以这条线把所有大于 3 的像素值都变成白色,剩下的都是原来的值。然后,我们用一些新参数创建 WordCloud 对象。
font_path :这是一个你想为单词使用的字体的路径。您可以将此路径指向操作系统的字体文件夹。(即。c:\ Windows \ Fonts \ font . TFF)
contour _ color:图像轮廓的颜色
max _ words:图像中使用的最大字数
mask :您的图像矩阵
color map:用于文字的颜色图
乔·拜登的单词云和蓝色地图
看起来棒极了!虽然浅色很难辨认。我们可以改变背景或选择不同的颜色或色彩映射表。另一个选择是选择我们想要使用的颜色图中较暗的部分。我们将添加两行,从 matplotlib 导入一个色图作为颜色矩阵,然后选择矩阵中较暗的部分。
用自定义颜色创建的左侧图像。用 matplotlib 色彩映射表创建的右图
你可以看到成品看起来相当不错。右边的图像是上面代码中颜色较深的图像。我也用它来创建标题图像。左边的图像是自定义颜色。你可以在 Github repo 中找到这个词云的代码。您可以使用 to_file() 方法保存图像,并传递一个保存文件的位置。wordcloud.to_file(“path_to\\wordcloud_image.png”)
3.1 |创建一个图像着色的文字云 另一个选择是使用照片本身的颜色给文字着色。你需要像以前一样准备照片,但是只去掉背景,留下你希望文字覆盖的图像部分。
左图由量具滑轨莫尔 CC BY-SA 2.0 提供
我们再次创建遮罩(不改变任何值)。对 WordCloud 的参数做了一些改动。为了增加可读性,对字体和背景的大小和颜色做了一些改变。
ImageColorGenerator用于为文字云创建颜色,而 recolor() 方法用于改变文字的颜色。
艾米·克洛布查尔的词汇云
我们探索了几种不同的方法,利用不同的停用词从全文和词频中提取一些有意义的文本。我们还研究了利用对数比值比从部分文本中寻找常用词。我们还使用不同的遮罩、字体和颜色绘制了几种类型的单词云。希望这能帮助你为项目创造一些有用的视觉效果。
点击这里查看 Github 库,上面所有例子的代码都在这里。
如果你对学习和实现其他 NLP 技术以从文本中提取见解感到好奇,请查看 Neptune.ai 的这篇博客文章,它涵盖了超过 7 种其他 NLP 技术,包括情感分析和词性标注。
如果这有帮助,让我知道!我很想听听你对词云的想法,看看你的一些成果。
两分钟内生成尼克·凯夫的歌词
在这篇文章中,我们将使用 GPT-2 语言模型来开发一个简单的歌曲歌词生成器,以尼克·凯夫为例,他是我最喜欢的艺术家之一。
GPT-2
GPT-2 是一个大型的基于转换器的语言模型,有 15 亿个参数。它的训练有一个简单的目标:给定某个文本中所有的前一个单词,预测下一个单词。由 800 万个网页组成的数据集的多样性,导致这个简单的目标包含跨不同领域的许多任务的自然发生的演示。有关详细信息,请访问open ai 出版物。让我们集中精力练习吧!
解析歌词
首先,我们需要使用众所周知的BeautifulSoup
库解析来自尼克·凯夫 官方网页的歌词。
解析尼克·凯夫的歌曲
运行上面的代码后,我们在songs.txt
文件中保存了来自 20 张专辑的 201 首歌曲。
火车模型
构建标记器
使用[aitextgen](https://github.com/minimaxir/aitextgen)
库在下载的歌曲上训练一个自定义标记器。这将保存两个文件:aitextgen-vocab.json
和aitextgen-merges.txt
,它们是重新构建分词器所需要的。
列车 GPT-2 变压器模型
使用创建的 tokenizer 启动 aitextgen
创建 TokenDatasets,构建用于训练的数据集,以适当的大小处理它们。
训练时间到了!
生成歌曲
从“我们淹死了”开始生成 3 个段落,并将它们保存到文件中。您可以修改max_length
和temperature
参数。温度是随机性相关的超参数。当其值较小时(如 0,2),GPT-2 模型更有信心,但也更保守。当温度是一个大值(例如 1)时,GPT-2 模型产生更多的差异,也产生更多的错误。在我看来,当你想生成一件艺术品时,第二种选择要好得多;).
下面你可以看到样本结果。看起来挺有前途的,尤其是考虑到需要多少编码量:)。
感谢阅读!
利用深度学习生成新颖的艺术作品
深度学习与艺术:神经类型转移
神经类型转移的一个例子
1.问题陈述
在这篇文章中,我将继续使用深度学习以另一幅图像的风格创作图像(曾经希望你能像毕加索或梵高一样画画吗?).这就是所谓的神经风格转移!这是一种在莱昂·A·加蒂斯的论文中概述的技术,一种艺术风格的神经算法,这是一本很棒的读物,你绝对应该去看看。
但是,什么是神经风格转移呢?
神经风格转移是一种优化技术,用于拍摄三幅图像,一幅内容图像,一幅风格参考图像(如著名画家的艺术作品),以及您想要设计风格的输入图像——并将它们混合在一起,以便输入图像被转换为看起来像内容图像,但以风格图像的风格“绘制”,从而桥接深度学习和艺术的轨道!
例如,让我们来看看这只海龟和葛饰北斋的神奈川外的巨浪:
绿海龟图片——P . Lindgren【CC By-SA 3.0(https://creative Commons . org/licenses/By-SA/3.0)】%5D),来自维基共享资源。
https://en.wikipedia.org/wiki/The_Great_Wave_off_Kanagawa
现在,如果 Hokusai 决定用这种风格来画这只海龟,会是什么样子呢?类似这样的?
这是魔法还是只是深度学习?幸运的是,这不涉及任何巫术:风格转移是一种有趣的技术,展示了神经网络的能力和内部表示。
神经风格转移的原理是定义两个距离函数,一个描述两幅图像的内容如何不同的𝐿𝑐𝑜𝑛𝑡𝑒𝑛𝑡,另一个描述两幅图像在风格方面的差异的𝐿𝑠𝑡𝑦𝑙𝑒.然后,给定三个图像,期望的样式图像、期望的内容图像和输入图像(用内容图像初始化),我们尝试变换输入图像,以最小化内容图像的内容距离和样式图像的样式距离。总之,我们将获取基本输入图像、我们想要匹配的内容图像和我们想要匹配的样式图像。我们将通过反向传播最小化内容和样式距离(损失)来转换基本输入图像,创建一个匹配内容图像的内容和样式图像的样式的图像。
在本文中,我们将生成一幅巴黎卢浮宫博物馆的图像(内容图像 C),混合了印象派运动领袖克洛德·莫内的一幅画(风格图像 S)。
2.迁移学习
神经风格转移(NST)使用先前训练的卷积网络,并在此基础上构建。使用在不同任务上训练的网络并将其应用于新任务的想法被称为迁移学习。
根据NST 的原始论文,我将使用 VGG 网络。具体来说, VGG-19 ,19 层版本的 VGG 网络。该模型已经在非常大的 ImageNet 数据库上被训练,因此已经学会识别各种低级特征(在较浅的层)和高级特征(在较深的层)。
下面的代码从 VGG 模型中加载参数(更多信息请参考 Github repo):
pp = pprint.PrettyPrinter(indent=4)
model = load_vgg_model(“pretrained-model/imagenet-vgg-verydeep-19.mat”)
pp.pprint(model)
模型存储在 python 字典中。python 字典包含每个图层的键-值对,其中“键”是该图层的变量名,“值”是该图层的张量。
3.神经类型转移
我们将分三步构建神经类型转移(NST)算法:
- 构建内容成本函数 J_content (C,G)。
- 构建风格成本函数 J_style (S,G)。
- 放在一起得到 J(G) = α * J_content (C,G) + β * J_style (S,G)。
神经风格转移算法的总成本函数
3.1 计算内容成本
在我们运行的例子中,内容图像 C 将是巴黎卢浮宫博物馆的图片(缩放到 400 x 300)
content_image = scipy.misc.imread(“images/louvre.jpg”)
imshow(content_image);
内容图片©显示了卢浮宫博物馆的金字塔,周围环绕着古老的巴黎建筑,背景是晴朗的天空和几朵云。
3.1.1 将生成的图像 G 的内容与图像 C 进行匹配
如前所述,ConvNet 的较浅层倾向于检测较低级别的特征,如边缘和简单纹理;更深的层倾向于检测更高级的特征,例如更复杂的纹理以及对象类别。
我们希望生成的图像 G 具有与输入图像 C 相似的内容。假设你已经选择了一些层的激活来代表图像的内容。实际上,如果你在网络的中间选择一个图层,你会得到最令人满意的视觉效果——既不太浅也不太深。
注意:在你完成了这篇文章的例子之后,你可以自由地尝试不同的层,看看结果如何变化。
首先,我们将图像 C 设置为预训练的 VGG 网络的输入,并运行前向传播。让一个 ᶜ 成为你选择的层中的隐藏层激活。这将是一个 nH × nW × nC 张量。
使用图像 G 重复此过程—将 G 设置为输入,并运行正向传播。让一个 ᴳ 被相应的隐藏层激活。
然后我们将定义内容成本函数为:
内容成本函数
这里, nH 、 *nW、*和 nC 分别是您选择的隐藏层的高度、宽度和通道数。这些术语出现在成本中的规范化术语中。
为了清楚起见,请注意, ᶜ 和 ᴳ 是对应于隐藏层激活的 3D 体积。为了计算成本 J_content (C,G),也可以方便地将这些 3D 体积展开成 2D 矩阵,如下所示。
将激活层的 3D 体积展开成 2D 矩阵。
从技术上来说,计算 J_content 并不需要这个展开步骤,但是当您稍后需要执行类似的操作来计算样式成本 J_style 时,这将是一个很好的实践。
实现
***compute_content_cost()***
函数使用 TensorFlow 计算内容成本。
实现该功能的 3 个步骤是:
- 从
a_G
中检索尺寸。 - 展开
a_C
和a_G
,如上图所示。 - 计算内容成本。
总之,内容成本采用神经网络的隐藏层激活,并测量 a ᶜ 和 a ᴳ 有多不同。当我们稍后最小化内容成本时,这将有助于确保 G 拥有与 C 相似的内容。
3.2 计算风格成本
对于我们的运行示例,我们将使用以下样式图像:
由印象派运动的领袖克洛德·莫内以 印象派 的风格作画。
风格矩阵
样式矩阵也被称为 Gram 矩阵。线性代数中,一组向量(v₁,…,v n )的格拉姆矩阵 g 是点积矩阵,其项为 G ij = vᵢᵀ vⱼ= np.dot(vᵢ,vⱼ)
换句话说,G ij 比较 vᵢ和 vⱼ.有多相似如果它们非常相似,你会期望它们有一个大的点积,因此 G ij 会很大。
请注意,这里使用的变量名中有一个不幸的冲突。我们遵循文献中使用的通用术语。 G 用于表示样式矩阵(或克矩阵); G 也表示生成的图像。对于这个例子,我们将用Ggram来指代 Gram 矩阵,用 G 来表示生成的图像。
在神经风格传递(NST)中,您可以通过将“展开的”过滤器矩阵与其转置相乘来计算风格矩阵:
GG测量两个滤波器之间的相关性:
结果是一个维数矩阵( nC,nC ),其中 nC 是滤波器(通道)的数量。值Ggram(I,j) 测量滤波器 i 的激活与滤波器 j 的激活有多相似。
克 克也衡量图案或纹理的流行程度:
对角线元素Ggram(I,i) 测量过滤器 i 的“活动”程度。例如,假设过滤器 i 正在检测图像中的垂直纹理。然后Ggram(I,i) 度量图像整体上垂直纹理有多常见。如果Ggram(I,i) 大,这意味着图像有很多垂直纹理。
实现
风格成本
目标是最小化样式图像 S 的 gram 矩阵和生成的图像 g 的 Gram 矩阵之间的距离。
现在,我们只使用一个单独的隐藏层一个 ˡ.该层的相应样式成本定义为:
款式成本
实施
**compute_layer_style_cost()**
实现该功能的 3 个步骤是:
- 从隐藏层激活中检索尺寸
a_G
。 - 将隐藏层激活
a_S
和a_G
展开成 2D 矩阵,如上图所示。 - 用我们之前写的函数计算图像 S 和 G 的样式矩阵。
- 计算风格成本。
样式重量
到目前为止,我们只从一层捕捉到了风格。如果我们从几个不同的层“合并”风格成本,我们会得到更好的结果。每一层将被赋予权重( λˡ ) ),以反映每一层对风格的贡献。默认情况下,我们会给每个层相同的权重,权重加起来是 1。完成这个例子后,可以随意试验不同的权重,看看它如何改变生成的图像 G 。
您可以组合不同图层的样式成本,如下所示:
其中 λˡ 的值在STYLE_LAYERS
中给出。
STYLE_LAYERS = [
(‘conv1_1’, 0.2),
(‘conv2_1’, 0.2),
(‘conv3_1’, 0.2),
(‘conv4_1’, 0.2),
(‘conv5_1’, 0.2)]
实现
**compute_style_cost()**
该函数多次调用compute_layer_style_cost(...)
函数,并使用STYLE_LAYERS
中的值对结果进行加权。
对的描述**compute_style_cost**
对于每一层:
- 选择当前层的激活(输出张量)。
- 从当前图层中获取样式图像 S 的样式。
- 从当前图层获取生成的图像 G 的样式。
- 计算当前层的样式成本
- 将加权风格成本加到总风格成本上( J_style )
完成循环后:
- 返还整体风格成本。
注意:在上面 for 循环的内循环中,a_G
是一个张量,还没有求值。当我们在下面的 model_nn()中运行张量流图时,它将在每次迭代中被评估和更新。
总之,图像的风格可以使用隐藏层激活的 Gram 矩阵来表示。通过组合来自多个不同层的这种表示,我们甚至可以获得更好的结果。这与内容表示形成对比,在内容表示中通常只使用一个隐藏层就足够了。此外,最小化样式成本会导致图像 G 跟随图像 S 的样式。
3.3 定义优化的总成本
最后,让我们创建一个最小化样式和内容成本的成本函数。公式是:
NST 的总成本函数
实现
总成本是内容成本 J_content (C,G)和样式成本 J_style (S,G)的线性组合。
α 和 β 是控制内容和风格之间相对权重的超参数。
4.解决最优化问题
最后,让我们把所有的东西放在一起实现神经风格转移!
以下是该程序必须要做的事情:
- 创建交互式会话
- 加载内容图像
- 加载样式图像
- 随机初始化要生成的图像
- 加载 VGG19 型号
- 构建张量流图:
- 通过 VGG19 模型运行内容映像,并计算内容成本
- 通过 VGG19 模型运行样式图像,并计算样式成本
- 计算总成本
- 定义优化器和学习率
7.初始化张量流图并运行它进行大量迭代,在每一步更新生成的图像。
让我们详细介绍一下各个步骤。
互动会议
我们之前已经实现了总成本 J(G) 。我们现在将设置 TensorFlow 来针对 G 进行优化。
为此,我们的程序必须重置图形并使用一个“交互会话”。与常规会话不同,“交互式会话”将自己安装为默认会话来构建图表。这允许我们运行变量,而不需要经常引用会话对象(调用sess.run()
),这简化了代码。
# Reset the graph
tf.reset_default_graph()# Start interactive session
sess = tf.InteractiveSession()
内容图像
让我们加载、重塑和规范化我们的内容图像(卢浮宫博物馆图片):
content_image = scipy.misc.imread(“images/w_hotel.jpg”)
content_image = reshape_and_normalize_image(content_image)
风格图像
让我们载入、重塑并正常化我们的风格形象(克洛德·莫内的画):
style_image = scipy.misc.imread(“images/starry_night.jpg”)
style_image = reshape_and_normalize_image(style_image)
生成的图像与内容图像相关
现在,我们将生成的图像初始化为从content_image
创建的噪声图像。
生成的图像与内容图像略有关联。通过将生成的图像的像素初始化为主要是噪声但与内容图像稍微相关,这将有助于生成的图像的内容更快速地匹配内容图像的内容。
请随意在nst_utils.py
中查看 Github 回购中的generate_noise_image(...)
细节。
generated_image = generate_noise_image(content_image)
imshow(generated_image[0]);
生成 _ 噪声 _ 图像(内容 _ 图像)
加载预训练的 VGG19 模型
接下来,如前所述,我们将加载 VGG19 模型。
model = load_vgg_model(“pretrained-model/imagenet-vgg-verydeep-19.mat”)
内容成本
为了让程序计算内容成本,我们现在将指定a_C
和a_G
为适当的隐藏层激活。我们将使用层conv4_2
来计算内容成本。下面的代码执行以下操作:
- 将内容图像指定为 VGG 模型的输入。
- 设置
a_C
为张量,激活conv4_2
层的隐藏层。 - 将
a_G
设置为激活同一层隐藏层的张量。 - 使用
a_C
和a_G
计算内容成本。
注:此时,a_G
是张量,还没有求值。当我们运行下面model_nn()
中的张量流图时,将在每次迭代中对其进行评估和更新。
# Assign the content image to be the input of the VGG model.
sess.run(model[‘input’].assign(content_image))# Select the output tensor of layer conv4_2
out = model[‘conv4_2’]# Set a_C to be the hidden layer activation from the layer we have selected
a_C = sess.run(out)# Set a_G to be the hidden layer activation from same layer. Here, a_G references model[‘conv4_2’]
# and isn’t evaluated yet. Later in the code, we’ll assign the image G as the model input, so that
# when we run the session, this will be the activations drawn from the appropriate layer, with G as input.
a_G = out# Compute the content cost
J_content = compute_content_cost(a_C, a_G)
风格成本
# Assign the input of the model to be the “style” image
sess.run(model[‘input’].assign(style_image))# Compute the style cost
J_style = compute_style_cost(model, STYLE_LAYERS)
总成本
现在我们有了内容成本 ( J_content) 和样式成本 ( J_style ),通过调用total_cost()
计算总成本 J。
J = total_cost(J_content, J_style, alpha=10, beta=40)
【计算机】优化程序
这里,我使用 Adam 优化器来最小化总成本J
。
# define optimizer
optimizer = tf.train.AdamOptimizer(2.0)# define train_step
train_step = optimizer.minimize(J)
实施
***model_nn()***
函数初始化张量流图的变量,将输入图像(初始生成的图像)分配给作为 VGG19 模型的输入,运行张量(它是在该函数上面的代码中创建的)大量步骤。
运行以下代码片段来生成艺术图像。每 20 次迭代应该花费大约 3 分钟的 CPU 时间,但是在大约 140 次迭代之后,您开始观察到有吸引力的结果。神经类型转移通常使用 GPU 来训练。
model_nn(sess, generated_image)
你完了!运行此程序后,您应该会看到下图右侧所示的内容:
以下是其他几个例子:
- 具有梵高风格(星夜)的波斯波利斯(伊朗)古城的美丽遗迹
- Pasargadae 的居鲁士大帝墓,采用来自伊斯法罕的陶瓷 Kashi 风格。
- 具有抽象蓝色流体绘画风格的湍流的科学研究。
6.结论
你现在能够使用神经风格转移来生成艺术图像。神经风格转移是一种算法,即给定一个内容图像 C 和一个风格图像 S ,可以生成一个艺术图像。
它使用基于预训练的 ConvNet 的表示(隐藏层激活)。使用一个隐藏层的激活来计算内容成本函数;一层的样式成本函数使用该层激活的 Gram 矩阵来计算。使用几个隐藏层获得整体风格成本函数。
最后,优化总成本函数导致合成新图像。
7.引用和参考文献
Github 回购:https://github.com/TheClub4/artwork-neural-style-transfer
特别感谢deep learning . ai。图片由 deeplearning.ai 提供。
神经风格转移算法源于 Gatys 等人(2015 年)。Harish Narayanan 和 Github 用户“log0”也有可读性很高的文章,我们从中获得了灵感。在该实现中使用的预训练网络是 VGG 网络,这是由于 Simonyan 和 Zisserman (2015)。预训练的权重来自 MathConvNet 团队的工作。
- 利昂·a·加蒂斯、亚历山大·s·埃克、马蒂亚斯·贝赫(2015 年)。艺术风格的神经算法
- 用于艺术风格转移的卷积神经网络。
- Log0, TensorFlow 实现的“一种艺术风格的神经算法”。
- 卡伦·西蒙扬和安德鲁·齐泽曼(2015)。用于大规模图像识别的极深度卷积网络
- MatConvNet。