TowardsDataScience-博客中文翻译-2016-2018-十六-
TowardsDataScience 博客中文翻译 2016~2018(十六)
原文:TowardsDataScience Blog
协议:CC BY-NC-SA 4.0
今天你需要知道的五个 Python 技巧
原文:https://towardsdatascience.com/five-python-tricks-you-need-to-learn-today-9dbe03c790ab?source=collection_archive---------1-----------------------
无论你是高级人工智能工程师还是一年级生物学生,你都会在某个时候碰到 Python 编程语言。Python 于 1991 年首次发布,很快成为程序员和技术人员最喜欢使用的语言。根据高收入国家的堆栈溢出问题视图,Python 正迅速成为最受欢迎的语言选择。
The Incredible Growth of Python- David Robinson
作为一种语法相对简单的高级解释语言,Python 对于那些没有编程经验的人来说是完美的。流行的 Python 库被很好地集成并用于不同的领域,如生物信息学( biopython )、数据科学(*猫)、机器学习( keras / tensorflow )甚至天文学( astropy )。在学习了 C 和 Java 作为我的第一门编程语言后,我能够在谷歌搜索的几周内自学 Python。尽管执行速度比 Java 和其他语言慢得多,但 Python 实际上通过良好构建的流程集成特性提高了生产率。
在我们开始之前,我强烈推荐你去看看 Dan Bader 的 Python 技巧书。在他的书中,Dan 分享了一些非常有用的技巧和窍门,告诉我们如何用 Python 更有效地编码。如果你对 Python 一无所知,我强烈建议你开始学习 Code Academy 的 Learn Python 互动课程。
招数№1:强大的俏皮话
您是否厌倦了通读一行行代码并迷失在条件语句中?Python 一行程序可能正是您正在寻找的。例如,条件语句
**>>> if** alpha > 7:
**>>>** beta = 999
**>>> elif** alpha == 7:
**>>>** beta = 99
**>>> else**:
**>>>** beta = 0
真的可以简化为:
**>>>** beta = 999 **if** alpha > 7 **else** 99 **if** alpha == 7 **else** 0
这太荒谬了!如果您对自己编写的代码多加注意,您总会发现可以简化为一行程序的地方。除了条件语句,for
循环也可以简化。例如,在四行中加倍一个整数列表
**>>>** lst = [1, 3, 5]
**>>>** doubled = []
**>>>** **for** num **in** lst:
**>>>** doubled.append(num*2)
可以简化为一行:
**>>>** doubled = [num * 2 for num in lst]
当然,如果您将所有内容都链接到一行程序中,可能会有点混乱。确保不要在代码中过度使用一行程序,因为有人可能会认为大量使用一行程序是“不符合 Pythonic 规范的”。
**>>> import** pprint; pprint.pprint(zip(('Byte', 'KByte', 'MByte', 'GByte', 'TByte'), (1 << 10*i for i in xrange(5))))
诀窍№2:快速字符串操作
字符串操作可能很棘手(没有双关的意思),但是 Python 隐藏了一些捷径,使您的生活变得非常容易。要反转一个字符串,我们只需添加::-1
作为列表索引
**>>>** a = "ilovepython"
**>>> print** a[::-1]
nohtypevoli
同样的技巧也适用于整数列表。在 Python 中,字符串操作非常容易。例如,如果您想使用以下预定义变量str1
、str2
和lst3
输出一个句子
**>>>** str1 = "Totally"
**>>>** str2 = "Awesome"
**>>>** lst3 = ["Omg", "You", "Are"]
简单地使用.join()
方法和算术运算符来创建想要的句子。
**>>> print** ' '.join(lst3)
Omg You Are
**>>> print** ' '.join(lst3)+' '+str1+' '+str2
Omg You Are Totally Awesome
除了字符串操作,我还推荐阅读更多关于 regex(正则表达式)的内容,以便有效地搜索字符串和过滤模式。
招数№3:嵌套列表组合
itertools
可能是我最喜欢的 Python 库之一。假设您的代码有十几个列表,经过一些操作后,您得到了一个深度嵌套的列表。这正是你解决这种语法混乱所需要的。
**>>> import** itertools
**>>>** flatten = lambda x: list(itertools.chain.from_iterable(x))
**>>>** s = [['"', 'An', 'investment'], ['in'], ['knowledge'], ['pays'], ['the', 'best'], ['interest."', '--'], ['Benjamin'], ['Franklin']]
**>>> print**(' '.join(flatten(s)))
" An investment in knowledge pays the best interest." -- Benjamin Franklin
从上面的例子可以看出,我们可以使用。join()
和itertools
。itertools
中的.combinations()
方法也是从输入 iterable 返回元素长度子序列的强大工具。点击此处阅读更多关于itertools
的信息。
绝招№4:简单的数据结构
回到招数№1 ,在 Python 中使用一行程序初始化数据结构也是非常容易的。Harold Cooper 使用以下代码实现了一个单行树结构:
**>>> def** tree(): **return** defaultdict(tree)
上面显示的代码简单地定义了一个树,它是一个字典,默认值是 trees。其他一行函数,如质数生成器
**>>>** **reduce**( (**lambda** r,x: r-**set**(**range**(x**2,N,x)) **if** (x **in** r) **else** r),
**range**(2,N), **set**(**range**(2,N)))
可以在 Github 和堆栈溢出中找到。Python 也有强大的库,比如Collections
,它将帮助您解决各种现实生活中的问题,而无需编写冗长的代码。
**>>>** **from** collections **import** Counter
**>>>** myList = [1,1,2,3,4,5,3,2,3,4,2,1,2,3]
**>>> print**(Counter(myList))
Counter({2: 4, 3: 4, 1: 3, 4: 2, 5: 1})
绝招№5:打印变得容易
最后一个技巧是我希望早点知道的。原来打印一个字符串数组作为一个逗号分隔的字符串,我们不需要使用.join()
和循环。
**>>>** row = ["1", "bob", "developer", "python"]
**>>>** **print**(','.join(str(x) **for** x **in** row))
1,bob,developer,python
这个简单的一行程序就可以了:
**>>> print**(*row, sep=',')
1,bob,developer,python
另一个巧妙的打印技巧是利用enumerate
。enumerate
是 Python 的内置函数,非常有用。所以不用写四行代码来打印
**>>>** iterable = ['a','b','c']
**>>>** c = 0
**>>>** for item in iterable:
**>>> ** print c, item
**>>> ** c+= 1
0 a
1 b
2 c
同样的事情只需要两行代码就可以完成
**>>>** for c, item in enumerate(iterable):
**>>> ** print c, item
Python 中有几十万种打印技巧,如漂亮打印pprint
。如果你知道一个巧妙的 Python 技巧,请在下面评论!
感谢您阅读我的文章。
机器学习工具箱的 5 种回归类型
原文:https://towardsdatascience.com/five-regression-types-b07483813b33?source=collection_archive---------11-----------------------
Siora Photography on Unsplash
机器学习领域发展迅速。然而,一些经验丰富的技术仍然存在。最重要的是回归技术。2017 年,60%的 KDNuggets 调查受访者将它们列为他们前一年使用的技术:
[## 2017 年使用的顶级数据科学和机器学习方法
最新的 KDnuggets 民意调查询问:在过去 12 个月中,您使用了哪些数据科学/机器学习方法和工具…
www.kdnuggets.com](https://www.kdnuggets.com/2017/12/top-data-science-machine-learning-methods.html)
只要这个数字一样高,你在机器学习生涯中就会遇到退步。即使你自己不使用它们,了解不同的味道和它们解决的问题也是很重要的。
在这篇文章中,我为你提供了五个不同回归的快速概述。我还添加了一些链接和提示来帮助您迈出第一步。
1.逻辑回归
逻辑回归对二元目标进行分类。如果您想将它应用于您的分类问题,请花些时间仔细看看 sklearn 中的实现。基本的想法很简单,但是有很多方法可以微调这个方法。
提示:默认情况下,逻辑回归——和许多其他变量一样——假设所有特征对结果变量都有独立的(也称为加性的)线性影响。如果这个假设在你的用例中不成立,考虑交互效果或者其他方法来包含特性之间的复杂关系。
2.有序逻辑回归
如果你有一个排序目标变量的机器学习问题,使用有序逻辑回归。例如星级评定或*规模调查。通常的做法是将这些情况建模为度量或多类问题。然而,这些替代方案淡化了目标的序数特征。只是用有序逻辑回归代替。这种回归技术不太为人所知,但却非常强大。如果你想试试的话,可以看看 Python 中的mord 包。
提示:与逻辑回归相比,有序逻辑回归的输出看起来相似。然而,对结果的解释更加困难。特别是优势比在这里可能会产生很大的误导。
3.普通最*二乘法
对度量变量使用普通最*二乘法(OLS)。该模型以及对结果的解释都很简单。Python 的实现在 sklearn 和 statsmodels 中都可用。
提示: OLS 依赖于几个真实数据经常违反的假设。结果的后果可能是巨大的。查看这里对最重要的假设的详细解释。
4.计数数据回归
计数数据回归是一组处理目标变量的方法,这些变量的值总是正数和整数。由此产生的数据通常是非常不准确的。参见这篇关于各种选项的精彩文章:
[## 泊松还是负二项式?使用计数模型诊断来选择模型
选择适当的盘点模型来分析离散盘点结果的关键标准之一是相对值…
www.theanalysisfactor.com](https://www.theanalysisfactor.com/poisson-or-negative-binomial-using-count-model-diagnostics-to-select-a-model/)
提示:底层发行版的选择至关重要。确保您使用了可用的测试来选择正确的测试。
5.正则化技术
正则化是防止过度拟合的一种方法。在回归技术的背景下,有两种正则化:L1 和 L2。如果你使用 L1,你是在应用所谓的套索回归。如果你使用 L2,你是在使用岭回归。在第一种情况下,模型倾向于将系数设置为零。在第二种情况下,它试图在整个范围内保持较*的系数。在弹性网中还实现了两种技术的组合。
正则化本身是一个话题,但是由于 sklearn 中的实现,它们很容易使用。关于 L1 和 L2 的详细解释,请看这里:
[## L1 和 L2 正则化方法
机器学习
towardsdatascience.com](/l1-and-l2-regularization-methods-ce25e7fc831c)
提示:了解每种方法会产生什么类型的输出是至关重要的。例如,如果你有两个相关的特征,套索随机选择其中一个,而弹性网选择两个。
你用什么回归,为什么?请在评论中或在 Twitter 上告诉我。我也很乐意在 LinkedIn 上联系。感谢阅读,留点👏🏻如果这对你有帮助,让我们继续学习吧!
使用法律数据改进起草工作的五个步骤
原文:https://towardsdatascience.com/five-steps-for-using-legal-data-to-improve-drafting-e84497ebe986?source=collection_archive---------5-----------------------
法律数据非常有价值。在保险领域,关于保单条款平均相似性得分的数据(衡量一个条款相对于一组旨在实现相同功能的其他类似条款的相对相似性或差异)可用于即时显示一个保单与另一个保单的对比情况。关于网络政策构成的数据可以用来揭示某项政策可能遗漏了哪些条款或信息。
然而,为了释放这些数据的价值,法律专业人士需要了解如何正确利用这些数据。这样做的一个最直接的背景是起草法律语言。我认为,这里的关键是让数据在基本层面上易于消化。
几个月前,我有幸有机会在 KC Cyber 的一个*组上发言,这是一个当地的网络安全会议,讨论管理网络风险的经济有效的策略。我们的*组特别寻求回答有关信息安全和网络责任保险之间的相互作用的问题。然而,活动结束后,一位观众提出的一个问题一直困扰着我,也是这篇文章的灵感来源。问题是,“网络责任保险政策的基本组成部分是什么?”这个问题之所以一直困扰着我,是因为它有助于将我长期以来一直纠结的一个问题联系起来——如何有效地使用政策数据,使起草法律文件的过程更有效、更容易理解。
photo credit: Heather Otto
我对这个问题的直接回答是参考了伍德夫、索耶和他的公司在网络风险核心组成部分上的一些发现。在概念层面上,网络政策应该涵盖四种常见的网络风险:隐私、网络安全、错误&遗漏和媒体责任。学法律的我会说,这是一个实质多于形式的问题;这些一般风险概念的管理方式因组而异,但作为参考点,这些一般概念可作为数据驱动分析的一个步骤。在对需要管理的风险有了大致的了解之后,可以使用同一组数据来帮助确定更具体的政策语言,从而为组织提供更可靠的风险管理框架。
然而,这些策略并不局限于网络责任保险。事实上,数据的使用——将众多政策、合同或文件与机器学习算法、自然语言处理和其他计算机科学技术相结合的最终结果——可以帮助识别任何一组文件中的缺失和分歧区域。
从更普遍的角度来看,我想提出一个策略,使用政策数据来识别不同的政策语言、缺失的覆盖部分,并为识别和理解网络风险的流程带来更高的透明度。
为了起草更全面的网络责任政策,承保人、律师和其他风险管理专业人员应该 1)列出需要管理的风险类型,2)列出政策的语言(列出存在的条款、不存在的条款、相似性得分和要管理的风险类型),3)使用关于缺失条款和风险类型的数据将缺失条款添加到政策中,4)使用关于低相似性得分和要管理的风险类型的数据改进政策的薄弱环节,以及 5)根据政策的变化评估新的政策数据。
使用数据改进起草工作的 5 个步骤
1)风险清单
2)政策语言清单
3)使用缺失条款的数据匹配风险类型
4)使用得分较高条款的数据全面提高相似性得分
5)重新评估更新的政策
继续使用网络责任政策语言作为一个用例,让我们通过分析下面用红色圈出的政策来浏览这些步骤并解释这在实践中是什么样子,Aviva 的工程产品“网络”扩展语言。在整个过程中需要注意的一个重要事实是,与其他法律文本一样,某些网络政策措辞可能是为了狭隘的目的而构建的,并被整合到一个更大的政策或一套文件中。
风险清单
从基础知识开始,让我们假设要涵盖的风险类型是 Woodruff、Sawyer 和 Co .概述的网络风险类型——隐私、网络安全、错误&遗漏和媒体责任。可以预见的是,根据风险清单的细微差别,这一步会更加稳健。
保险单语言清单 为了了解保险单所涵盖的风险类型,查看保险单的保险协议部分是有帮助的。保险协议部分是真正的核心政策。保单中的其他内容用于解释如何解释这些条款,定义保险协议条款中的词语,显示适用保险协议必须满足的条件,确定保险范围的除外责任,建立保险范围的限制,以及起草人可能决定添加或排除的任何其他内容。
查看前面提到的 Aviva 文档(网络扩展措辞),可以清楚地看到,这一特殊政策仅旨在确保与数据安全漏洞相关的事件管理,以及因某些个人数据丢失、被盗或意外泄露而导致的其他义务。例如,本文档中的保险协议部分涵盖了与“因保险期间发现的数据安全漏洞而产生的费用”相关的赔偿
识别缺失条款
在粒度级别上,有许多类型的条款可能在策略中缺失,并导致其成为异常值。不需要大量的统计知识就可以看出,平均的子句簇在 75 到 125 个子句之间,平均相似性分数在 85 左右。
然后,通过获取关于哪些政策得分较高、哪些条款对于得分较高的政策最常见以及哪些条款是异常值或出现频率较低的数据,起草者可以获得关于此类政策中通常会发现的其他条款的实时反馈。
作为一个购买政策的组织,了解这份具体的文件实际上可以作为英杰华网络电子媒体核心政策的延伸会有所帮助。通过合并两份文件的条款数量,并对英杰华电子媒体核心政策及其工程产品“网络”扩展词的新评分集进行平均,结果(上图中的红圈)是新政策在长度方面更符合行业内的其他政策,但与我们的网络指数的其余部分的平均相似度仍低于 80%。
考虑到上下文的其余部分,即该组合政策中确实没有完全涵盖隐私或媒体责任的内容,浏览条款库、找到这些部分的条款并继续构建涵盖我们通过风险清单确定的所有风险的更全面的政策并不困难。
审查和修改低评分条款
在简要查看文件中的低评分条款时,我确定了与网络责任市场的其他条款相比最薄弱的政策领域(排除—先前行为、排除—故意行为、排除—费用、罚款和罚金以及限额—可扣除),并对其进行了更新,以包括不同政策中得分较高的政策语言。结果是整个策略的平均相似性得分从 76%上升到 78%。让我对这一分析感到兴奋的是,这一增长仅仅是通过改变 71 个条款中的 5 个来实现的。如果对其他 66 个条款进行审查和修改,那么与现有的其他政策相比,gains 可能会提高其排名。
重新评估更新后的政策
看看我在这个练习中所做的,在尝试创建一个强大的、通用的网络责任政策之前,我还想改变一些事情。例如,我想添加有关隐私、错误和遗漏的条款,并用其他得分较低的条款替换得分较高的条款。通过这样做,将相似性分数提高到 90%以上并拥有对许多人有价值和有用的东西并不是不可想象的。
在整个起草过程中持续使用和创建数据,将有助于以更加迭代、透明和开放的流程来审查和管理不同类型的风险。对于那些起草这类政策的人来说,它可以减少花在研究上的时间,并为缺乏经验的起草者提供一个衡量标准。对于那些希望了解实际应该有什么政策的人来说,数据可以成为一种工具,教人们什么时候适用某些条款或规定,以及在什么情况下其他条款或规定应该适用。
度过周四的五种方式
原文:https://towardsdatascience.com/five-ways-to-spend-a-thursday-34432f9ee93e?source=collection_archive---------1-----------------------
令我有些惊讶的是,我的 之前的 对美国时间使用调查的分析最终强调了我们的相似之处,而不是我们的不同之处。事实证明,我们并没有太大的不同。我认为这是有希望的。
不过,到目前为止,我主要着眼于更高层次的行为,比较了大约五个、十个或二十个不同的活动。还有更多的东西需要挖掘。在最细的层面上,ATUS 提供了 13 年来大约 170,000 天的报告和 400 项活动。其中一些活动是无处不在的(睡觉、吃东西、看电视、洗碗和工作),而另一些活动则很少见(击剑和观看举重/力量训练各只出现一次,如果你正在寻找一种新的爱好让自己与众不同的话)。
偏斜、稀疏、中等*度的数据。这将描述一组推文,就像它描述手头的数据一样。为什么不把每一个活动都当成一个词,把每一个报道的日子都当成一个文档,并对其应用一些文本挖掘技术呢?
采矿偏见— tf-idf
tf-idf 是一种挑选表示文本的单词的算法。通过查找在一个文档中比在其他文档中出现得更频繁的单词,它给出了该文档是关于什么的想法。单词“”在大多数文本中频繁出现,因此意义不大,而多次包含“选举”的文档可能与政治或时事有关。
应用于我们数据的 tf-idf 假设将睡眠视为睡眠:每个人都做的事情,因此在强调差异方面没有什么价值。另一方面,打篮球在青少年经常做但 70 岁老人很少做的事情中不会让我们感到惊讶。
大家试一试吧,挑出十大活动。
你瞧,不同年龄组之间肯定有明显的差异。对我们的年轻人来说,学校和体育运动会出现。当孩子们到来时,我们的细节围绕着他们。过了 50 岁,孙子出现了,然后房子周围就有了静物。
尽管如此,这些发现似乎很老套,几乎就像一幅漫画。请记住:在解释这些结果时,我们需要精确。长条的长度并不能说明我们做每件事花了多少时间。相反,它向每个年龄段的人展示了每样东西的独特性。并不是所有 75-84 岁的老人都要照顾家里的其他成年人——大概是他们的老年配偶——而是那些照顾家里成年人的人更有可能是老年人。
这份名单有一种怪异的人情味。从某种意义上来说,这是一份刻板印象甚至偏见的清单,它不一定列出了许多人做了什么,而是列出了那些通常做这些事的人是谁。
父母对非父母
让我们尝试另一个*度:父母与非父母。在这里,我将简单地把那些有孩子住在家里的人称为“父母”,把那些没有孩子住在家里的人称为“非父母”。
同样,我们必须精确地解释结果。不是花时间的问题,而是独特性的问题。不言而喻,照看孩子的人就是父母。结果的后半部分更有趣一点。没有母亲的人的特别活动是瑜伽、有氧运动、跳舞和照顾宠物,而没有父亲的人则拿着枪或棍子回到他们的根源,或拿着棍子追球。
现在,这对于刻板印象来说怎么样?
但稍后会详细介绍。
度过周四的五种方式
让我们尝试第二种文本挖掘技术:主题建模。在文本分析中,主题建模意味着基于属于一起但使桶不同的单词将文档聚集在一组桶中。然后我可以用这些单词来找出有哪些不同的主题。例如,我将 LDA 应用于 2017 年 4 月下旬的一组新闻论文。我可能会以一个包含“朝鲜”和“导弹发射”等词的主题结束,而另一个包含“特朗普”、“100 天”、“天”等词。LDA 不仅把我的东西放在桶里,还很方便地告诉我为什么。
不过,要应用 LDA,我首先必须决定我希望看到的桶的数量。因为我追求可读性,所以我的目标是少数几个。我只是尝试了 3 到 7 之间的值,并坚持使用 5,因为这给出了有趣且主观上不太重叠的结果。此外,我选择只将周四作为一周工作中的任意一天进行分析。
Five ways to spend a Thursday
LDA 把东西放在桶里,并告诉我们为什么,但要由我们来解释这些原因。我在图表中添加了一些人口统计数据,以帮助理解每个群体。这些人口统计数据没有用于分析或分类,而是在之后添加的。
看看 LDA 认为重要的词,我们每天做的五组事情似乎是,从上到下:
- 不折不扣的老年生活
- 学习(“孩子”指生活在家庭中的孩子,大概包括兄弟姐妹)
- 呆在家里,家庭主妇和丈夫:ing,育儿
- 正常的一天工作
- 居家老人生活
结论
我确信盒子里有更强大的工具来进行这些分析。如果没有别的,我会通过将数据视为一个简单的“活动包”来丢弃一些信息。尽管如此,结果比我预期的要好,而且多亏了 tidytext 包,完成这件事变得非常简单。
一路走来,我意识到文字和这个有一些重要的区别。其中最重要的可能是这样一个事实,即在文本中很少出现的事件是高信息事件,但在其他数据中却经常是异常值。比如 tf-idf 原来就是一个相当性别歧视的*刺头。
话又说回来,也许这里有对我们所有人有价值的一课?也许这正是当我们太关注使我们不同的东西,而太少关注使我们相同的东西时发生的事情。因为,事实证明,我们并没有什么不同。
github 上的完整代码。
在 NLP 任务之前,修正你的文本思想注意
原文:https://towardsdatascience.com/fix-your-text-thought-attention-before-nlp-tasks-7dc074b9744f?source=collection_archive---------17-----------------------
“two white planes flying” by Alicia Steels on Unsplash
语法纠错(GEC)是纠正文本错误的方法之一。它可以是全局误差或局部误差。纪等人提出了纠正用词和拼写的注意机制。
看完这篇帖子,你会明白:
- 嵌套注意神经混合模型设计
- 体系结构
- 拿走
嵌套注意神经混合模型设计
纪等人将纠错问题归结为机器翻译问题,采用序列对序列模型来解决这一问题。与使用基于短语的机器翻译不同,S2S 方法具有学习长距离,甚至全局单词依赖性的能力。
作者扩展了基于 S2S 的模型来处理极大的词汇量和捕获句子结构。S2S 模型的输入是一个单词序列,并将其转换为向量序列。然而,传统的单词嵌入无法处理词汇外(OOV)问题。传统的解决方式有:
- 用一个单一的向量来代表整个 OOV
- 如果是 OOV,跳过这个词
作者使用第三种方法,即按字符计算单词向量。例如,“爱德华”是一个 OOV,它使用“E”、“d”、“w”、“a”、“r”和“d”来计算“爱德华”的嵌入,而不是使用静态的“未知”向量。对于角色嵌入,你可以访问这个故事来获得更多信息。
第二部分是学习处理拼写错误和屈折形式。例如,“aple”是一个拼写错误,而“apple”是预期的单词,而“invisions”后面应该是 he 而不是“invision”。
体系结构
该模型使用单词级和字符级嵌入来解决纠错问题。虽然它们用于不同的目的:
- 单词水平:纠正全局语法和流利性错误
- 字符级:拼写或变形形式
Architecture of Nested Attention Hybrid Model (Ji et al., 2017)
基于单词的序列对序列模型
首先,文本序列将被转换为向量序列。字编码器使用门控递归单元(GRU)来构建向量隐藏状态序列。GRU 也被用在解码器中,它输出基于单词注意力输入的向量序列。
混合编码器
字嵌入的一个限制是 OOV,混合编码器就是为了解决这个问题而设计的。当有 OOV 时,向量将由字符编码器计算,而不是查找嵌入。
嵌套注意混合解码器
解码器通过两个解码器输出目标字。如果字是由字编码器构建的,将使用字解码器。否则,将使用字符解码器。
拿走
- 需要大量的词汇,包括大量的单词和拼写错误。
关于我
我是湾区的数据科学家。专注于数据科学、人工智能,尤其是 NLP 和平台相关领域的最新发展。你可以通过媒体博客、 LinkedIn 或 Github 联系我。
参考
季军,王庆,图塔诺瓦,龚 y,张 s,高 J..2017.用于语法错误纠正的嵌套式注意力神经混合模型
链条中的 NANHM
人工智能的最后一英里问题
原文:https://towardsdatascience.com/fixing-the-last-mile-problems-of-deploying-ai-systems-in-the-real-world-4f1aab0ea10?source=collection_archive---------2-----------------------
三种类型的问题和五种战术解决方案
Photo by Alberto Frías on Unsplash
TLDR: 最后一英里的问题是实现人工智能承诺的价值的最后障碍。获得人工智能系统的好处需要的不仅仅是坚实的商业案例、执行良好的人工智能实现和强大的技术栈。它通常需要人工智能和人的协作,才能为客户提供正确的体验。但是,公司通常很难做到这一点。
许多分析从高管和数据科学家的角度强调了如何构建 AI 系统。相反,本案例研究使用个人轶事和新的视角来看待问题:通过一线员工和客户的视角。我讨论了各种实际的解决方案,例如人工智能中的 80-20 规则和机器与人类之间的平滑交接,以帮助团队克服现实世界中人工智能交付的最后一英里障碍。
喜欢你读的书吗?在媒体、 LinkedIn 或 Twitter 上关注我。还有,作为数据科学家要不要发展商业影响力?查看我的“对机器学习的影响”PDF 指南(2019 年 9 月 30 日提供)。订阅以便在它准备好的时候得到通知。
首先,让我分享一个故事……
最近,我和妻子 ess 去多伦多市中心的伊顿中心购物。Jess 心情非常好,因为她刚从公司组织的黑客马拉松(为期 3 天的构思和原型制作竞赛)回来。杰斯是多伦多一家银行的财务顾问。当我们在一个供应商摊位前停下来更新我的手机计划时,她正在描述所有的人工智能(AI)想法和原型是多么神奇(和不真实)。
一位名叫乔安妮的女士,大概 20 出头,欢迎我们并提出了几个不错的选择;我同意了她的一个建议。乔安妮在处理交易时,她转向杰斯说:“看起来有一个针对你的特别优惠,你想听听吗?”。
“当然!”杰斯说。
乔安妮看了屏幕两秒钟说:“我们愿意为你提供 10G 的数据,每月 75 美元。这是一笔了不起的交易!”
杰斯看上去很困惑,说道:“这说不通啊。我只需为同样数量的数据和服务支付 65 美元。”
我们都笑着化解尴尬。乔安妮回去完成我的交易。我们五分钟后离开。
在我们回家的路上,Jess 提到了人工智能是多么令人失望,并开玩笑说大公司是如何不能把它做好并错过销售机会的。她说,她在黑客马拉松上看到的人工智能原型要有能力得多。
我说:“嗯,这就是现实世界的 AI 和实验室的区别”。她最终对我说的话印象深刻。
在分解我们的经验来强调人工智能系统的几个常见问题之前,让我们先了解一下人工智能系统的背景和定义。如果你熟悉这个概念,可以跳过这个。
杰斯的报价是怎么产生的?在这个故事中,Joanne 提出的要约是由一个推荐系统(RS) 生成的。RS 通过分析客户行为和提供个性化的产品和服务来帮助推动销售。一些 RS 依靠一种叫做协同过滤的机器学习算法来决定对客户的最佳报价;一些 RS 依赖于更简单的算法,如逻辑回归或基于规则的方法,而一些 RS 使用更高级的算法,如深度强化学习。亚马逊和许多电子商务和数字公司是 rs 的早期采用者。许多传统企业(如电信和银行)紧随其后,开始了定义自己方式的旅程。
什么是 AI 系统?RS 是人工智能系统的一个例子。更具体地说,人工智能系统是全栈解决方案(例如前端和后端),通过使用大数据技术处理大量数据,并基于自主机器学习算法选择适当的交互,为用户提供上下文感知体验。
人工智能系统和传统的软件解决方案有一些明显的区别。这是最重要的一点:人工智能系统基于自主和持续的学习和决策与用户互动,而不是遵循一套静态的和由设计师和工程师预先设计的规则。
Source: Author’s Analysis
L 在故事中,RS 意识到 Joanne (最终用户)正在与 Jess 和我讨论产品变更(情境感知);它提供了一个 Joanne 可以分享的提议(基于大数据和机器学习的交互)。考虑到另一个客户和环境(例如,打电话投诉服务,而不是考虑产品变更),报价可能会有所不同。RS 是一个全栈解决方案,因为它有一个与 Joanne 交互的前端接口和一个支持数据存储、机器学习和系统集成的后端。
还有许多其他人工智能系统的例子,如自动驾驶汽车、robo-advisor、Alpha-Go、Siri、波士顿动力公司的机器人、Roomba 等。
现在,怎么了?这个故事强调了人工智能系统在现实世界中失败的一些常见方式。我们来分解一下。
- 错误的互动:让顾客为同样的服务额外支付 10 美元根本没有意义。我不相信任何营销和客户行为理论会支持这一提议。
- 糟糕的执行:虽然乔安妮训练有素、能力出众、风度翩翩,但她显然不明白为什么这个提议是由人工智能系统提出的,因此无法正确执行这个提议(即使这意味着而不是执行)。
- 缺乏反馈循环:在我们都意识到报价没有意义之后,Joanne 只是简单地完成了我的交易,没有向 AI 系统提供任何反馈来帮助它学习。质量反馈对于任何人工智能系统的长期成功都是至关重要的。
这个例子凸显了一个基本而普遍的问题:人类和人工智能系统之间的脱节。人-AI 协作是 AI 系统的最后一公里问题。
UX 的设计师可能会争辩说,这只是一个设计糟糕的典型解决方案。应用设计思*和界面设计的最佳实践应该可以解决这个问题。正确,但只是在某种程度上。自主交互的独特性要求我们进行更深入的思考。如果我们不能完全控制和理解人工智能系统的反应,我们如何预先设计用户交互的关键方面,如果不是全部的话?
那么,有哪些解决办法呢?在这里,我提出了一些战术解决方案,以帮助公司最大限度地实现人工智能系统的承诺。
Author’s Analysis, Updated on Feb. 23, 2020
1.从错误到正确(或更好)的互动
要求人工智能系统在 100%的时间里提供正确的答案是不可能的,无论是在数学上还是在实践中。所以,我们最好的目标是用合理的投资获得足够正确的答案。为此,我建议探索以下方法:
- 确定一个 80-20 人工智能救援计划。80–20 是一个众所周知的概念和商业公理;它强调了一个普遍的观察结果,即大约 20%的工作产生了 80%的结果。使用 80-20 思*来简化解决方案至关重要;这样做可以帮助避免推出一个有缺陷的人工智能系统,并损害客户体验(Jess 的例子)。显然,当人工智能系统提供不合理的建议时,一些技术问题就被打破了。过于复杂的设计是一个常见的问题。一组数据科学家可以问:1)要达到 80%的准确率,最简单的设计是什么?2)结果是否足以交付承诺的商业价值?3)有哪些更先进的技术可以抓住下一个 2%、5%和 10%的市场份额?尽管围绕复杂的人工智能技术进行了大肆宣传,如深度和强化学习,但并不是每个人都需要在第一天使用它们。简单的数据挖掘技术,如关联规则,可能能够捕捉大多数客户动态,并在早期提供足够好的结果。
Image Source: link
- 应用业务规则进行保护。由于机器学习模型肯定会有错误,因此拥有一个额外的业务规则层对于质量保证来说是必不可少的。例如,基于业务领域知识的简单规则可以是这样的:1)不提供没有额外的有意义的服务的更昂贵的套餐,2)抑制可能导致收入损失的过度打折的报价。避免复杂的规则很重要。它们可能会破坏人工智能系统的目的,并最终影响性能。要确定这些规则,与经验丰富的业务经理和一线员工合作是关键。这就引出了下一个建议。
- 使用合适的专家进行健全性检查。商业高管和数据科学家经常设想人工智能系统。拥有拥有足够技术马力的顶级支持对于推出成功的人工智能系统至关重要。然而,当谈到使用旨在提供更好的客户互动的系统时,一线专家知道得最多,也有最深刻的观察。因此,尽管一线员工可能不是技术专家,但将他们包括在流程中是非常重要的。
2。从差到好的执行
大多数人工智能系统依赖于人类员工在某些时候采取行动,良好的执行是实现承诺的商业价值的关键。良好的执行归结为一个要素:机器和人类之间的顺利交接。为了实现顺利移交,人工智能系统和人类都需要协同工作…
- 提供侧重于“是什么”、“为什么”和“如何”的说明。数据科学家花费大量时间微调算法,但往往忽略了提供必要的信息来帮助人类员工取得成功。关键是使人工智能系统能够解释为什么提供特定的建议,并分享简单的指令供人类员工遵循。一个简单的什么-为什么-如何模板可以做到这一点,见下面的例子;这个想法最初是由西蒙·西内克在领导力激励演讲中提出的。
- 高技能员工与人工智能系统合作。能够使用技术是许多入职培训的重要组成部分。但是今天这还不够。例如,人工智能系统不同于传统的客户关系管理(CRM)应用程序。基于他们的学习和见解,人工智能系统可能会提供对员工来说不明显的建议。也就是说,人类员工需要在更高的认知水平上参与理解、消化和挑战(如果需要的话);工作人员不能也不应该盲目听从指示。员工应该将人工智能系统视为合作伙伴,他们应该与之合作、挑战和培养。
想象一下:RS 提供了三行简单的语句,Joanne 可以在不到 10 秒(甚至更短)的时间内理解并理解…
- 做什么:建议升级 10GB 的数据套餐,每月 70 美元的新手机返现
- 为什么你应该这么做:客户(Jess)使用我们的服务已经超过 10 年了;根据与她相似的客户资料,她可能会感兴趣,并且对每月储蓄反应良好
- 如何接近:告诉 Jess 你很欣赏她 10 多年来的生意,你想提供一个其他忠实客户也欣赏的好交易;每月节省 25%(或者这可以是一个预先填充的脚本,但根据 Jess 的个人资料进行定制修改)
与人工智能系统一起工作更复杂,但回报——物质商业利益和更投入、更受重视的员工——可能是值得的。
3。从麻烦到参与反馈机制
最后,人工智能系统的真正力量来自它们学习和改进的能力。然而,如果没有来自环境的有意义的反馈,他们就做不到,在这种情况下,他们是一线员工。有意义的反馈是指描述客户行为原因的信息。由于笨拙的用户界面和缺乏激励,许多一线员工忽略了获取和分享这些信息的机会。以下是一些简单的注意事项…
- 开发一个简单有趣的反馈用户界面。有两个关键的考虑因素。首先,用户界面需要简单,这样员工就可以轻松准确地输入信息,这样他们就不会抗拒这样做。要获取的最重要的信息是为什么客户没有对建议做出回应。其次,游戏化,如使用徽章和健康的同行竞争,有助于鼓励和推动员工提供高质量的反馈,而无需硬性强化。这就是 CRM 管理中的传统技巧仍然有效的地方。
- 鼓励输入质量反馈。现实地说,很难期望员工做出更多努力,因为许多人已经被日常工作的任务和目标压得喘不过气来。因此,制定具体的激励措施是推动行为改变的最佳解决方案。例如,团队可以为“本月人工智能培训师”设立排行榜和奖项,或者在年度绩效评估中正式确定一个目标。
一旦反馈被捕获,数据科学团队需要将其与人工智能系统的学习机制联系起来。从技术角度来看,这很棘手,有很多关于处理时间的考虑。然而,一旦实施,人工智能系统可以从客户的独特信息中学习,修复系统学习中的缺陷,并持续自主地改进。更有意义的反馈导致更智能的人工智能系统,可以提供指数级的商业利益。
通过探索和实现这些考虑,好处是增加 AI 系统的成功概率,尤其是当它们在现实世界中与人类交互时。
让我们总结一下……
他的例子只是揭示了人工智能系统的一些有代表性的问题。随着人工智能的投资转化为现实世界的解决方案——许多人将与一线员工和客户密切互动——公司应该停下来,理智地检查他们对人-人工智能协作体验的想法。这里是断线经常发生的地方。此外,请记住,技术开发中的许多最佳实践仍然适用,例如“从*处着手,不断重复”和“以用户为中心”。
克服最后一英里的问题对于实现人工智能的温暖人心的承诺至关重要。有一个全面的诊断和手术修复是至关重要的。改善交互、执行和反馈机制的早期和轻量级解决方案可以帮助公司在现实世界中部署人工智能系统时避免重大挫折。
思想的果实
- 在使用人工智能系统时,你的团队面临哪些独特的运营挑战(例如,时间、技能和/或信任)?
- 人工智能系统如何通过简化流程(尤其是以前难以自动化的流程)来帮助您的企业削减成本?
- 人工智能系统如何让你的企业创造新的方式来提供产品和吸引客户?
喜欢你读的书吗?在中、 LinkedIn ,或者 Twitter 上关注我。还有,作为数据科学家要不要发展商业影响力?查看我的“对机器学习的影响”PDF 指南(2019 年 9 月 30 日提供)。订阅以便在它准备好的时候得到通知。
免责声明 :文中观点不代表作者雇主赞同。
你可能也会喜欢这些…
[## 12 *时 ML 挑战
如何使用 Streamlit 和 DevOps 工具构建和部署 ML 应用程序
towardsdatascience.com](/build-full-stack-ml-12-hours-50c310fedd51) [## 越狱
我们应该如何设计推荐系统
towardsdatascience.com](/how-to-design-search-engines-24e9e2e7b7d0) [## 我们创造了一个懒惰的人工智能
如何为现实世界设计和实现强化学习
towardsdatascience.com](/we-created-a-lazy-ai-5cea59a2a749) [## ML 和敏捷注定的联姻
Udacity 的创始人巴斯蒂安·特龙毁了我的 ML 项目和婚礼
towardsdatascience.com](/a-doomed-marriage-of-ml-and-agile-b91b95b37e35) [## 抵御另一个人工智能冬天的最后一道防线
数字,五个战术解决方案,和一个快速调查
towardsdatascience.com](/the-last-defense-against-another-ai-winter-c589b48c561) [## 人工智能的最后一英里问题
许多数据科学家没有充分考虑的一件事是
towardsdatascience.com](/fixing-the-last-mile-problems-of-deploying-ai-systems-in-the-real-world-4f1aab0ea10)
调情——贝叶斯统计中的一个练习
原文:https://towardsdatascience.com/flirting-an-exercise-in-bayesian-statistics-61de2bf73814?source=collection_archive---------23-----------------------
求爱的仪式既多又奇怪。对一点都不好笑的事情的假笑。一缕头发。一句老套的搭讪台词。
这一切意味着什么?
答案就在贝叶斯统计中,因为调情可以被视为一种观察,然后相应地更新先前信念的练习。调情的核心是两件事:
1)试图通过观察某人在你身边时的行为/信号来判断他是否喜欢你(或者他们是否会成为一个好伴侣)。
2)向其他人发出信号,希望他们能够理解并得出你希望他们得出的结论(你对他们感兴趣,或者你会成为一个很好的合作伙伴)。
让我们借助贝叶斯定理,以一种更正式的方式来分解它。下面是:
The foundational theorem guiding this essay (Source: Towards Data Science)
这是什么意思?我们来分解一下。让我们看看方程中的两个变量——θ和数据。我们可以把θ看作一个结果。我们从 P(θ)开始,我们称之为先验,P(θ)的含义非常简单——它是我们认为我们的结果实际发生的概率。这里有一个真实的例子来说明。假设θ是抛硬币正面朝上的结果。假设我们的先验信念——我们在观察到任何数据之前开始相信的东西——是 50%。这意味着我们的先验信念是,掷硬币的结果是正面的概率等于 50%。P(θ)= P(抛硬币的结果=正面)= 50%。先验本质上可以是任何东西——它是你开始相信的任何东西。在这种情况下,我的生活经验和常识使我认为 P(θ)= 50%是合理的先验,我希望你同意。
现在我们已经有了初始信念 P(θ)set,让我们引入等式的下一部分 P(data |θ)。如果我们假设θ的先验分布为真,这就是观察到某些结果/数据的可能性。所以我们有了先验P(θ)= 50%。P(data |θ)是说,给定一个硬币是公平的(正面的结果是 50%),观察到一些数据的概率是 P(data |θ)。这些数据就是我们实际看到的东西——例如,如果我们观察到 30 次抛硬币,30 次正面朝上,那么 P(data |θ)= P(30 次抛 30 次正面朝上|θ= 0.5)→如果硬币真的是公平的,那么我们在 30 次抛中得到 30 次正面朝上的可能性有多大?观测数据出现在之前的可能性有多大?很明显,如果硬币真的是公平的,30 次投掷中 30 次正面朝上的可能性是非常低的。P(数据|θ)= P(30 次投掷 30 个头|θ= 0.5)几乎为 0。
综上所述,P(θ| data)是我们观察证据后的后验信念。这可以被视为根据我们在数据中观察到的情况更新我们的先验信念。在这个例子的上下文中,这基本上意味着我们正在更新我们的先验信念,即硬币是公平的,到新的后验信念,即硬币倾向于正面。这只是常识——我们开始认为硬币是公平的,然后我们看到它在 30 次投掷中出现了 30 次正面,然后现在我们认为硬币没有我们最初认为的公平,而是更偏向正面。显然,从我们刚刚遵循的逻辑序列中,我们看到后验与先验乘以从该先验产生的数据的可能性成比例。数学上,P(θ|数据)αP(θ)* P(数据|θ)。
Fair or not? Observe data and use Bayes’ Rule to find out (Source: Public Domain)
很好,现在我们明白了贝叶斯法则。如果你想一想,我们实际上一直在我们的思*过程中实施贝叶斯法则。如果我们认为某件事是真的,然后我们看到影响先前信念的数据,我们会以某种方式改变我们最初的信念。如果我认为鲍勃是一个吝啬的人,然后我看到他在街上给乞丐钱,我会将我最初认为他吝啬的信念修正为一个新的信念,即他并不像我曾经认为的那样吝啬——因为如果我先前认为他吝啬的信念是真的,鲍勃给乞丐钱的可能性很低,这使得后来的信念更接近于鲍勃没有以前那么吝啬。每次你因为新的证据而改变主意时,你都在使用贝叶斯法则。
那么这和调情有什么关系呢?你现在可能已经猜到了。调情是贝叶斯法则的高风险、情绪化的表现。有几种方法可以考虑这个问题。
第一:你想弄清楚你的爱人是否也喜欢你。你一开始对之前的相对不了解,只是随意猜测他们是否喜欢你。可能你第一印象不好,你把先验设在 P(他们喜欢我)= 25%。这是一种不确定的方式,让你的品味去表达你的爱。你想先了解更多信息。
所以你们一起出去玩的时间越多,你们约会的时间越长,你们见面的次数越多,在每一种情况下,你们都在收集数据。也许他们紧紧地拥抱你——如果他们有 25%的机会喜欢你,这种情况发生的概率相当低——也许你一开始低估了自己,现在你将 25%的先验更新为 27%的后验。也许你碰了它们,它们本能地厌恶地退缩了→更新之前的并减少到 5%。我们继续前进。
This guy will update his prior belief on whether the woman likes him after he sees how she reacts to this touch (Source: Public Domain)
你正在收集所有这些数据,观察它们的每一个动作,并把它们代入贝叶斯法则,希望你能向上更新你的先验。也许有一天你觉得你已经收集了足够多的数据,并说是的,他们喜欢你的概率其实真的很高——是时候表白了!或者有一天你得出结论,他们喜欢你的可能性非常低,现在你知道你应该放弃,继续前进。
不管怎样,每次约会,你都在无意识地使用贝叶斯推理。对方也是。他们以完全相同的方式评价你和你的行为。你想引导他们走向正确的方向,帮助他们准确地更新他们的先验——所以你轻拂你的头发,触摸他们的前臂,等等。或者,如果你不感兴趣,你会冷淡他们,取消约会,等等。让他们更接近你希望他们得出的结论。
第二:同样的贝叶斯计算可以用于调情的另一个目的——评估潜在伴侣的质量或表明自己的质量。当你看到他们给服务生的*费很高时,你会修改之前的来反映这些数据——你的信念会更新,认为他们比你最初认为的更好。反之亦然,如果你的约会对象因为服务生晚了两分钟才把菜端上来而对他大喊大叫。**
有了这些知识,我们现在可以看到调情的关键。它们如下:
1)你需要收集数据。这是获得更多信息的唯一途径。所以去和你喜欢的人互动吧!
2)你的成功取决于你估算/计算 P(data |θ)项的能力有多强——你需要弄清楚,如果有人喜欢你,他们会如何行动,以及你的观察与这种预期有多大差异。
a.为了帮助计算,请你的朋友分析一下情况。当我们向朋友寻求建议时,我们所做的只是细化我们对 P(data |θ)的计算!
3)相应地更新后验。希望数据显示他们比你想象的更喜欢你!
希望这是有帮助的——带上贝叶斯法则,祝你的浪漫事业好运。
蜂拥而至
原文:https://towardsdatascience.com/flocking-with-go-2dcf6fcab144?source=collection_archive---------6-----------------------
如何使用 Go 在你的终端上创建一个群集模拟
我写植绒模拟已经很久了。我用 Java 尝试过,但我仍有记录的最早版本是用 JRuby 和 Swing 开发的,名为 Utopia 。我用鞋写了一个,那是我的 用 R 和 Ruby 探索日常事物书中的那个。过了一段时间,(总体来说,我对鞋子不太满意),我用 2D 的一个 Ruby 和 C++游戏开发库 Gosu 重新写了一遍。这个版本可以在这里找到。
群集模拟基本上是一个模拟鸟类群集行为的软件程序。这种群集行为与昆虫的群集行为或鱼类的群集行为非常相似。这被认为是一种紧急行为——一种源于个体遵循简单规则的行为,不涉及任何中央协调。这种行为,尤其是在椋鸟或成群梭鱼的低语中看到的,可能是一种令人惊叹的现象。
Photo by James Wainscoat on Unsplash
Boids
群集最早是由程序员 Craig Reynolds 用软件模拟的,他开发了一个名为 boids 的软件程序,并于 1987 年在 ACM SIGGRAPH conference 上发表了一篇关于该主题的论文。从那以后,在模拟群集方面有了很多进步,但是基本思想仍然很简单。
Boids 本身使用三个基本规则来描述单个 boid 如何移动:
- 分离——避免拥挤附近的其他蜂群
- 对齐——向附近队友的平均方向移动
- 凝聚力——向附近队友的平均位置移动
这些规则得到了扩展,在某些情况下,添加了更多的规则,但基本思想是,个人遵循一些简单规则的局部反应可能会导致复杂的、意想不到的行为。
在围棋中做
虽然我已经认真地用 Go 编程几年了(它现在是我的主要编程语言),但我一直没有找到用 Go 编写群集模拟的好方法。最大的问题是,Go 主要是一种后端编程语言,并没有真正的 GUI 工具包。虽然有一些尝试,包括绑定到 GTK 和 QT,但没有一个符合我的要求。如果你正在寻找一个桌面应用程序,你可能会更好地使用 Electron 并在 Go 中构建一个 web 应用程序来支持它。
也就是说,直到我在我的帖子中摆弄遗传算法。在那篇文章中,我试图向终端显示一个图像,在我的例子中,是优秀的 iTerm2 。这就是我在 iTerm2 上偶然发现这个允许我在屏幕上显示图像的黑客的地方。
当然,如果我可以显示一个图像,我就可以显示多个图像。如果我可以显示多幅图像,我也可以将它们一幅接一幅地重叠显示。如果我能足够快地展示它们…
How to make a flip book (credits: Andymation https://www.youtube.com/watch?v=Un-BdBSOGKY)
黄金
当然,我称它们为黄金。一个Goid
是一个简单的结构,带有位置、速度和颜色的信息。
*type Goid struct {
X int // position
Y int
Vx int // velocity
Vy int
R int // radius
Color color.Color
}*
位置和颜色很容易理解。这里的速度不仅仅是金子移动的速度,也是它移动的方向。在这种情况下,Vx
和Vy
是高尔夫球在下一个循环中将要离开的距离,也是它将要去的方向。从数学上来说,X
和Y
是标量位置(它告诉你在 2D 平面上离原点有多远),而Vx
和Vy
是 矢量 。
创建 goids 相对简单。每个 goid 必须在窗口内,并且它的起始速度*于它的大*。
*func createRandomGoid() (g Goid) {
g = Goid{
X: rand.Intn(windowWidth),
Y: rand.Intn(windowHeight),
Vx: rand.Intn(goidSize),
Vy: rand.Intn(goidSize),
R: goidSize,
Color: goidColor,
}
return
}*
大部分工作都在move
函数中。
*// move the goids with the 3 classic boid rules
func move(goids []*Goid) {
for _, goid := range goids {
neighbours := goid.nearestNeighbours(goids)
separate(goid, neighbours)
align(goid, neighbours)
cohere(goid, neighbours) stayInWindow(goid)
}
}*
自 30 年前以来,群集模拟已经有了相当大的进步,但是对于这个简单的模拟,我使用了 boids 的 3 个经典规则。这三条规则都要求 goid 知道谁是它的邻居,所以首先弄清楚这一点是有意义的。
*// find the nearest neighbours
func (g *Goid) nearestNeighbours(goids []*Goid) (neighbours []Goid) {
neighbours = make([]Goid, len(goids))
for _, goid := range goids {
neighbours = append(neighbours, *goid)
}
sort.SliceStable(neighbours, func(i, j int) bool {
return g.distance(neighbours[i]) < g.distance(neighbours[j])
})
return
}// distance between 2 goids
func (g *Goid) distance(n Goid) float64 {
x := g.X - n.X
y := g.Y - n.Y
return math.Sqrt(float64(x*x + y*y))}*
首先,我们克隆整个 goid 群体,然后我们使用sort.SliceStable
按照与所讨论的 goid 的距离对克隆的数组进行排序。找到距离只是一个使用毕达哥拉斯定理的问题。
这给了我们一个相邻高尔夫球的列表,按距离排序。让我们看看第一条规则。
分离规则
这就是个人空间法则。比方说,你和许多其他通勤者在一列火车上,它停在一个有许多人上车的车站。当他们进来的时候,他们会填满空间,会有一些人最终离你太近。你会怎么做?你会离开他们一点,但不会离其他人太近,最终会和其他人保持一个舒适的距离。这是规则。
*// steer to avoid crowding local goids
func separate(g *Goid, neighbours []Goid) {
x, y := 0, 0
for _, n := range neighbours[0:numNeighbours] {
if g.distance(n) < separationFactor {
x += g.X - n.X
y += g.Y - n.Y
}
}
g.Vx = x
g.Vy = y
g.X += x
g.Y += y
}*
我们只对有限数量的相邻 goids 感兴趣,这由参数numNeighbours
指定。相邻的高尔夫球场也必须在参数separationFactor
内(不是所有相邻的高尔夫球场都足够近,不会让人不舒服)。一旦这些金球进入那个空间,我们就远离它们。然后我们把速度更新到那个距离,然后用那个速度移动高尔夫球。
对齐规则
这就是同辈压力法则。同辈压力是同辈人对人们施加的直接影响,使他们改变行为以符合群体的要求。你可能对同辈压力很熟悉——当你看到你的邻居拥有闪亮的新 4K 电视或 iPhone X 时,你可能也会想给自己买一台。在我们的生活中,还有很多其他不需要进一步解释的同伴压力的例子,而这正是对齐规则。
*// steer towards the average heading of local goids
func align(g *Goid, neighbours []Goid) {
x, y := 0, 0
for _, n := range neighbours[0:numNeighbours] {
x += n.Vx
y += n.Vy
}
dx, dy := x/numNeighbours, y/numNeighbours
g.Vx += dx
g.Vy += dy
g.X += dx
g.Y += dy
}*
和以前一样,我们只对由numNeighbours
指定的有限数量的相邻 goids 感兴趣。然而,这条规则并不影响高尔夫球的位置,而是改变高尔夫球的速度,我们将所有相邻高尔夫球的速度相加,然后除以相邻高尔夫球的数量。最终值会修改速度,而不是完全替换它,同时新值会修改 goid 的位置。
内聚规则
这就是方阵法则。希腊方阵是一个矩形的、紧密排列的步兵编队,作为一个整体行进和战斗。这是古代战争中最有效和持久的军事编队之一。它的效力在于密不透风的盾牌和长矛组成的紧密队形,缓慢地向前推进,突破敌人的行列。罗马人后来采取了同样的想法,创建了三线罗马军团,用于征服已知世界。
*// steer to move toward the average position of local goids
func cohere(g *Goid, neighbours []Goid) {
x, y := 0, 0
for _, n := range neighbours[0:numNeighbours] {
x += n.X
y += n.Y
}
dx, dy := ((x/numNeighbours)-g.X)/coherenceFactor, ((y/numNeighbours)-g.Y)/coherenceFactor
g.Vx += dx
g.Vy += dy
g.X += dx
g.Y += dy
}*
和其他规则一样,我们只对邻近的金子感兴趣。我们取所有这些邻居的平均位置(将所有邻居的位置相加,然后除以邻居的数量),并从中减去 goid 的位置。然后将这个值除以一个coherenceFactor
,这个值决定了 goids 希望与其邻居保持一致的程度。如果coherenceFactor
太高,高尔夫球将不会移动,如果太低,高尔夫球将会彼此贴得太近,形成紧密结合的高尔夫球簇。
呆在视野之内
现在我们有了规则,我们可以运行模拟,但由于我们的视图仅限于参数windowWidth
和windowHeight
,一旦黄金离开屏幕,我们就再也看不到它了。也就是说过一段时间,就只是一个空屏幕了。为了防止这种情况发生,如果一个黄金离开了屏幕,我们会神奇地把它转移到窗口的另一边。
*// if goid goes out of the window frame it comes back on the other side
func stayInWindow(goid *Goid) {
if goid.X < 0 {
goid.X = windowWidth + goid.X
} else if goid.X > windowWidth {
goid.X = windowWidth - goid.X
}
if goid.Y < 0 {
goid.Y = windowHeight + goid.Y
} else if goid.Y > windowHeight {
goid.Y = windowHeight - goid.Y
}
}*
显示框架
拼图的最后一块是画出金子本身。
*// draw the goids
func draw(goids []*Goid) *image.RGBA {
dest := image.NewRGBA(image.Rect(0, 0, windowWidth, windowHeight))
gc := draw2dimg.NewGraphicContext(dest)
for _, goid := range goids {
gc.SetFillColor(goid.Color)
gc.MoveTo(float64(goid.X), float64(goid.Y))
gc.ArcTo(float64(goid.X), float64(goid.Y), float64(goid.R), float64(goid.R), 0, -math.Pi*2)
gc.LineTo(float64(goid.X-goid.Vx), float64(goid.Y-goid.Vy))
gc.Close()
gc.Fill()
}
return dest
}*
每一帧都是宽windowWidth
高windowHeight
的图像。在这个框架中,我们将每个 goid 绘制为一个圆,然后我们绘制一条线来表示 goid 的尾巴。这条线与高尔夫球前进的方向相反,所以我们从高尔夫球的速度中减去它的位置。
显示模拟
我们现在已经有了所有需要的函数,所以让我们把它们放在main
函数中。
*func main() {
clearScreen()
hideCursor() goids := make([]*Goid, 0)
for i := 0; i < populationSize; i++ {
g := createRandomGoid()
goids = append(goids, &g)
} for i := 0; i < loops; i++ {
move(goids)
frame := draw(goids)
printImage(frame.SubImage(frame.Rect))
fmt.Printf("\nLoop: %d", i) }
showCursor()
}*
还有几个你以前没见过的功能。什么是clearScreen
、hideCursor
、showCursor
、printImage
?这些是实际显示模拟的函数。
再来看clearScreen
、hideCursor
和showCursor
。
*func hideCursor() {
fmt.Print("\x1b[?25l")
}func showCursor() {
fmt.Print("\x1b[?25h\n")
}func clearScreen() {
fmt.Print("\x1b[2J")
}*
那么我们用了哪些奇怪的转义序列呢?这些是 ANSI 转义序列,用于控制文本终端上的各种选项。它们大多是过去的遗留物,但仍在 iTerm2 等终端仿真器中广泛实现。所有序列都以ESC
(27 或十六进制 0x1B)开头,后面是提供控制选项的第二个字节。特别是,ESC
后跟[
表示下一个字节是控制序列引入器(CSI),它是一组有用的序列。例如,?25h
显示光标,?25l
隐藏光标。您可能已经猜到了,2J
清除整个屏幕并将光标移到屏幕的左上角。
让我们看看如何将图像打印到屏幕上。
*// this only works for iTerm!
func printImage(img image.Image) {
var buf bytes.Buffer
png.Encode(&buf, img)
imgBase64Str := base64.StdEncoding.EncodeToString(buf.Bytes())
fmt.Printf("\x1b[2;0H\x1b]1337;File=inline=1:%s\a", imgBase64Str)
}*
这是一个有趣的黑客行为,只在 iTerm2 中发现(据我所知)。这允许您获取二进制图像的 base64 表示,并在终端上内联打印出来。在行首的转义序列2;0H
是一个 CSI,它将光标移动到第 2 行第 0 列,在那里我们要打印图像。
最终模拟
这是我运行它时的样子。
密码
这里找到的所有代码都可以在http://github.com/sausheong/goids找到。
我为什么要这么做?
群集模拟已经被做得死去活来,但是我喜欢写它。看到这些*家伙不是作为个体,而是作为一个有自己思想的群体四处活动,有一种禅意。在学习了群集和编写群集模拟之后,我开始做更多的模拟,将来我可能会写更多。
弗洛卡:监督学习,变得简单
原文:https://towardsdatascience.com/flokka-supervised-learning-made-easy-2ac5df426dea?source=collection_archive---------7-----------------------
机器学习模型的众包训练
图像识别是一个极其复杂的过程。这一过程中最困难的部分之一是获取数据并将其准确分类。在徒劳地寻找一种更实用的分类方法来节省时间和资源之后,我们开发了自己的解决方案。进来吧,弗洛卡,一个机器人。
Flokka 在今年的 Myriad Festival 上进行了尝试和测试,旨在众包一个简单图像识别模型的分类和训练。使用 Flokka slackbot,用户能够快速地将无序文件夹或列表中的文件排序为有序的文件结构——非常适合训练机器学习模型。
slackbot 是 Slack 平台独有的一种程序,它允许用户通过 Slack 聊天室与程序的界面进行交互。这可以通过自然语言来完成,例如“请为我获取最近 24 *时的最新头条”,或者通过命令来完成:“/获取新闻 10”。这有助于那些不知道如何使用某些程序/编程接口的用户轻松地使用它们。
我们选择开发 Flokka 作为 Slackbot,是因为 Slack 在 Max Kelsen 团队中扮演着不可或缺的角色。Slack 的多平台特性让我们可以随时随地轻松的对图像进行分类;在其他项目的短暂休息期间,甚至是在喝我们早晨的咖啡时。在办公室中,这种可访问性有助于简化图像分类过程,消除了数*时手动分类的需要。
弗洛卡是如何建成的? Flokka 是使用 SlackClient Python API(特别是 Events API)创建斜杠命令和处理交互消息而构建的。
使用/classify [number]命令,slackbot 从 training 文件夹中取出[number]张图像,并在指定的 Slack 通道中显示它们。显示后,用户可以使用每个图像下方的按钮输入选择适当的分类。然后,图像被分类到适当的文件结构中,以备在机器学习模型中使用。Flokka 为人们省去了将图像拖到桌面文件夹中的繁琐任务,并创建了一个更具吸引力和乐趣的整体过程。即使随着 slackbot 的发展,类别和图像变得更加复杂,一点一点分类的能力应该会提高执行任务的个人的准确性。
在接下来的几周里,我将会写一篇关于 Flokka 的更具技术性的文章。
测试模型
Myriad 是一个为期三天的技术和创新节,于 3 月 29 日至 31 日在布里斯班发电站举行。该活动鼓励企业家、投资者、企业主和技术爱好者之间的合作和交流。此外,Myriad 为我们提供了展示 Flokka 的机会,并让志同道合的人了解和测试 slackbot。我们邀请与会者帮助我们给未分类的四种珍奇动物贴上标签;一只*,一只虎鲸,一只老虎和一只巨嘴鸟。这种标记的结果然后将被用作训练集来构建图像分类模型。
每只动物的图片都是从 http://www.image-net.org/的和 T4 的中挑选出来的,放在亚马逊 s3 的一个训练文件夹中。该文件夹中的图片用于分类过程的众包。与会者被邀请参观 Max Kelsen 展台,并一次对多达 20 幅图像进行分类。
在两次会议的过程中,2000 张图片被分为:712 只*,790 只巨嘴鸟,154 只老虎和 286 只虎鲸。此外,58 张图片包含不相关的动物。
一旦图像被分类,我们就用它们来训练一个图像识别模型,以检测每种动物的新照片并对其进行分类。这个模型是通过重新训练一个张量流模型
创建的(有关教程,请参见此处 ) 。
然后,我们在模型中运行盲集(每个类别 50 张图片),该模型的结果显示在下图中:
该模型将 200 幅盲图像分为四类,每类图像的平均置信区间超过 99.8%。这一统计反映了程序比手工方法更有效、更准确地执行任务的能力。我们承认,这种准确性可能是由于图像类别在颜色、纹理、形状和模式方面有很大的差异,供模型辨别。认识到这一点,我们试图进一步测试该模型,并通过该模型运行该类别的亚种图像,包括黑*、*猫、北极*和白虎。
这些图像的结果如下所示:
这项研究的结果进一步鼓励了这样一种观点,即对于识别来说,图案和形状被认为是比颜色更重要的因素。得出这一结论是因为白虎、北极*和黑*的图像颜色不同,但具有与其相应类别“原始”相似的图案和形状,并且在模型的图像识别中保持了高准确率。然而,该模型被发现在识别*猫图像方面稍欠准确,*猫图像在形状上具有最大的差异。
最终结果 Flokka 创造了一个图像分类过程,与以前的手动图像分类技术相比,它对用户来说既更快又更容易使用。虽然我们注意到人们似乎很喜欢 Flokka 的游戏特色,但我们也认识到,这可能是因为本研究中使用的生动而奇特的样本图像的性质而被放大了。与十个或更多类别的系统相比,由于四个类别系统的简单性,该过程也变得更容易,这可能会降低 Flokka 的生产率。
考虑到与会者能够快速分类也很重要,因为图像之间的视觉差异很大。较*的差异将带来更大的困难,个人可能难以以相同的速度和准确度对图像进行分类。尽管如此,Flokka 通过松散平台的可访问性和组织的便利性仍然会在该过程中产生整体效率增益。对于 Max Kelsen 来说,这是一个激动人心的时刻,因为我们不断开发 Flokka 等方法来改进我们的平台、技术和整体生产力。
Max Kelsen 团队目前正致力于改进和开发可用于任何工作场所和图像识别模型的 Flokka。敬请关注即将推出的 Flokka 开源版本,并通过Flokka . io订阅 Flokka 时事通讯,了解该项目的最新详情。
流动的概念和创造的可能性
原文:https://towardsdatascience.com/fluid-concepts-and-creative-probabilities-785d3c81610a?source=collection_archive---------13-----------------------
通过概率规划的概念学习。
回到未来:人工智能大炒作时代的概念
“然后,‘人工智能’这个词就滑下了斜坡,最终变成了毫无意义的流行语和空洞的炒作。(……)幸运的是,一个新术语“认知科学”正在流行,我开始喜欢用这种方式来描述我的研究兴趣,因为它明确强调了对人类思*/大脑中实际发生的事情的忠诚。”—道格拉斯·霍夫施塔特(2000 年之前,只是为了说明一下)
我猜想有人带着下面的难题来找你:给定整数序列0, 1, 2, …
,猜下一项。这似乎并不难,是吗?3
将是我们显而易见的答案,因为我们会假设“生成器函数”可能像f(x) = x
一样简单:
f(0) = 0
f(1) = 1
f(2) = 2
f(3) = ??? -> 3
...
事实证明,这是而不是生成这个序列的函数。序列继续如下:
f(0) = 0
f(1) = 1
f(2) = 2
f(3) = 720!
f(4) = ???
...
那么,f(4)
是什么?
我们不会破坏这个惊喜(见解决方案的最后部分),但使用这个漂亮的难题来讨论一个更普遍的问题:给定由算术运算(加、减、乘等)构建的整数和函数的宇宙。),假设可能性的数目是无限的,如何学习一个数列的“生成函数”?
我们专门研究人类语言的形式模型——如果你认为求解整数序列是愚蠢的,你可以把英语语法想象成你现在正在阅读的内容的“生成器函数”,以及计算机对文本进行类似人类的推理是多么困难。关于语言,现在说够了,让我们回到整数!]
序列游戏是在探索概率编程 ( PP )时偶然想到的,这是经常解释的试图将通用编程与概率建模统一起来。我们对 PP 的兴趣在于明确推理结构的能力,以及在没有大量数据的情况下很好地处理不确定性的能力:祝“机器学习你的方法”好运;
f(1) = 1
f(2) = 4
f(3) = ???
序列游戏是令人惊奇的流动概念和创造性类比的一部分(有趣的事实:这是亚马逊上销售的第一本书!),一本由人工智能先驱、畅销书作家和认知科学家道格拉斯·霍夫施塔特(Douglas Hofstadter)于 1995 年出版的书( DH )。在他无与伦比的写作能力中,问题是这样引入的:
这一序列的数学起源表明,确实会有模式或顺序,但由于数学本身充满了极其多样的模式,这个领域仍然是敞开的。尽管如此,我们对简单和优雅有着固有的偏见,不管我们能否定义这些概念。那么,假设我们预期我们可能会找到一个简单而优雅的规则,那么接下来会发生什么呢?
在这篇简短的帖子中,我们将重新发现序列游戏,并用一些简单的 PP 程序讨论概念学习。一方面,这将是理解 PP 的一个很好的练习,因为我们将看到如何以令人满意和有原则的方式对待固有的偏见;另一方面,我们将使用 PP 来深入了解人工智能的最新进展。
免责声明:这篇文章既不是关于 PP 的教程,也不是学术著作(如果有的话,因为它带有明显的偏见),也不是生产就绪模型的集合 — 虽然包含了可运行的代码示例,但我们今天的兴趣几乎完全在于用标准 ML 工具难以实现的建模类型,而用 PP 来代替是自然的。作为奖励,我们将讨论关于概念学习的认知上合理的想法,这些想法超越了。
向前看,向后看:概率建模 101
"在纽约,百万分之一的几率一天发生八次."—佩恩·吉列特
在我们作为人工智能从业者和创业公司创始人的生活中,我们多次发现,概率编程中的许多想法仍然远远不是数据科学社区的主流。被这个轶事证据所说服,我们决定包括对 PP 的概述,以及它对有趣的推理问题的特殊之处,比如你在向机器教授语言时遇到的问题(熟悉 PP/WebPPL 的读者可以快速跳过接下来的两节)。
我们将大量使用 WebPPL 示例并充分利用在浏览器中运行代码的可能性:所有示例都可以从这个简单的 HTML 页面中完全运行。
让我们从一个简单的例子开始(当然是用骰子)。如果我们有两个公平的骰子,当你扔的时候得到 8 的概率是多少?这个 WebPPL 程序(记住:你可以在这里运行它)以一个漂亮的直方图显示结果的分布(如果有些东西不清楚,不要惊慌:很快就会很明显了):
Frequency distribution for our dice model.
PP 最酷的地方在于做逆推论是多么容易:假设我们观察到和是 8,那么一个骰子是 2 的几率是多少?
Frequency distribution for our dice model, conditioned upon observation.
正如读者可能怀疑的那样,如果总数是 8,那么骰子#1 有 20%的机会是 2(给懒惰读者的*测验:为什么上面的直方图中没有 1?).
虽然这可能看起来像一个明显简单的例子,但理解“模型的力量”真的很重要,即生成我们感兴趣的数据的过程的简化版本。模型是世界复杂性的一个非常紧凑的表示:在一个单一的模型中,你实际上可以从原因推理到结果(当你计划时,向前),从结果推理到原因(当你进行有根据的猜测时,向后)。模型也是我们认知能力的核心:通过拥有一个"七巧板模型",孩子们知道如何用零散的碎片建造一只鸭子(向前),并且根据鸭子的形状,他们可以猜测哪些碎片是用来建造它的(向后)。
A Tangram duck — humans can easily reason from pieces to figures and from figures to pieces.
对于许多人来说,基于模型的推理是智能的关键,其适用性远远超出了七巧板(如直观物理学和视觉学习);
生成模型描述了一个过程,通常是生成可观察数据的过程,表示关于世界因果结构的知识。这些生成过程是一个领域的简化“工作模型”(…);通过询问心智模型,可以回答许多不同的问题。
对于今天比理解人类智力更温和的目的来说,理解 PP 如何帮助是非常重要的。正如我们所看到的,这些模型通常被称为“生成型模型”:不用太在意的技术细节,对我们来说重要的是以下两个考虑因素:
- 生成模型讲述了一个关于数据点如何生成的故事:它们有一个可以检查的结构,并且它们通常包含人类可以理解、质疑、辩论的因果假设;
- 生成模型可以用来生成我们目标数据的新实例,这是一个并非所有机器学习模型都具备的特性。例如,如果我们训练生成模型来分类体育与金融中的新闻文章,我们可以使用它们来创建关于这些主题的新文章。
当人们已经手工编写生成模型很久了的时候,概率建模的黄金时代才刚刚开始。PP 的兴起为实践者解决了两个主要问题:首先,PP 带来了编程语言的表达能力:通过使用熟悉的工具,数据科学家现在可以表达任意复杂的模型,而不是一些分布;其次,PP 将推理的负担推给了编译器(和相关工具):研究人员专注于建模,因为计算机将解决所需的推理挑战。
用 Javascript 表达生成模型:WebPPL 101
"我的编程语言的极限意味着我的世界的极限."——(几乎)路德*希·*特斯坦根
既然我们已经有了一些关于为什么生成模型如此酷的共同背景,我们可以回到如何在 WebPPL 这样的语言中实现它们的问题。如果您还记得我们的第一个例子,模型被指定为一个简单的函数,包装在推断方法中:
*model() {
var die1 = randomInteger(6) + 1;
var die2 = randomInteger(6) + 1; return die1 + die2;
}*
当运行时会发生什么?由于enumerate
是指定的推理方法,程序将对模型中随机变量的所有可能值运行一次函数(即每个骰子从 1 到 6 的随机整数),并收集分布结果(通过方便的viz
实用程序可视化)。由于模型是可生成的,应该可以从中采样并创建新值(即模拟骰子滚动):sample
函数正是这样做的,通过将以下语句添加到单元块中可以看到(它将打印从模型中采样的 5 个整数的数组):
*print(repeat(5, function() { sample(roll); }));*
第二个例子介绍了 PP 的一个关键思想:条件作用。该模型与之前的模型相同,但增加了一个新命令:
*condition(die1 + die2 == 8)*
它运行时会发生什么?condition
告诉程序忽略不满足所需条件的运行:这就是为什么没有 1 出现在分布中——如果一个骰子是 1,则不存在总和是 8 的情况(因为 1+6=7)。
条件反射之所以重要,至少有三个原因:它让你从观察到原因进行推理;它有助于以有原则的方式陈述可能限制要考虑的程序运行空间的信息;最后,它可以用来模拟当代人工智能中一个非常重要的概念,学习,通过 18 世纪的一个被称为贝叶斯定理的想法:给定一些数据,你对一个假设HD 的信心应该与 a)你首先对 H 的信任程度有关,以及 b)你对 H 能够解释 D 的程度有关。
我们用一个稍微有趣的例子来结束我们对 WebPPL 的简短介绍。考虑一个年轻的领域语言学家——让我们称他为威拉德——在一个世界非常*的异国他乡(也叫本体论):
A toy universe with a tree-based ontology and 7 objects.
这个奇异的世界有七个物体(用整数 1-7 命名)组织成树状结构,概念是关于三个层次的共性(例如一切都是哺乳动物,腊肠犬是一种狗,#3 是一种腊肠犬)。当#2 出现时,威拉德听到说本族语的人说basso to(1000 奖励点给期望本族语的人说 gavagai )的读者。巴索托是什么意思:腊肠犬、狗还是哺乳动物?更一般地说:
给定一个未知的单词 W 和一组用 W 表示的物体,威拉德如何学习W 的适当的一般性水平?
不出所料,概率规划非常适合对此问题建模,如下图所示:
奇迹就发生在这里。我们可以区分三个主要部分:
- 首先,从假设空间取样:威拉德对什么可以用 W 来命名有一些先验的想法(在分布
ontologicalTree
中总结);特别是,威拉德认为像狗和猫这样的“自然物种”比非常普通的哺乳动物更引人注目; - 二、似然函数:威拉德知道在给定观测值(一组对象)的情况下,如何对假设进行优先排序;公式中重要的是认识到 1)较低级别的概念(检索器)将比较高级别的概念(哺乳动物)赋予数据更大的可能性;2)随着一致事件数量的增加(
observedData.length
),更低级别的概念更有可能以指数方式;** - 第三,实际观察数据,因为
mapData
负责将 Willard 观察到的数据提供给评分函数。
[ *技术说明:这个例子的最初想法来自于徐和 Tenenbaum 的工作——请参阅他们的论文,了解更多关于该模型背后的心理事实的背景以及关于先验和可能性的深入讨论。]
那么,回到我们观察到的单词的第二个例子,威拉德在想什么?运行代码会得到以下分布:****
Distribution over target concepts after one observation.
这似乎是一个合理的猜测,不是吗?威拉德更喜欢腊肠狗,但他仍然保持开放的心态;当然,与数据不符的假设(如寻回犬,其延伸不包括#2)根本不予考虑。当威拉德观察#2 + #3 和听到低音吉他时,这个场景变得非常有趣:
Distribution over target concepts after two observations.
发生了什么事?如果威拉德只是排除与数据不一致的假设,看到两只腊肠狗而不是一只不会增加有意义的信息:简单地说,威拉德不会学到任何新东西。相反,我们的概率模型允许捕捉威拉德的学习:在看到两只腊肠狗后,他更加确信 bassotto 是指腊肠狗,同时他几乎准备排除哺乳动物作为一种合理的解释(即使从纯粹的逻辑角度来看,与数据完全一致)。我们留给读者一个练习,以确保所有代码都是清楚的:尝试改变先验、可能性和观察以更好地理解幕后发生的事情!
如果你想在继续之前再玩一会儿,可以在 probmods 上找到一些关于向前和向后推理相互作用的有效例子。虽然该领域在数据科学社区中仍然相对*众,但事情正在快速发展:我们上周发现了这个出色的 WIP ,主要参与者正在进入 PP 。为了非懒惰读者的方便,我们在最后包含了一堆额外的书籍/链接。
现在让我们回到我们的序列游戏!
“寻找序列的来源”
"不要让一个人猜太久——他肯定会在别的地方找到答案的。"—梅·韦斯特
既然我们对 PP 背后的哲学有了更好的理解,我们可以试着将我们的序列游戏建模为一个在假设空间中的学习问题,假设空间是无限的。给定序列:
**f(1) = 1
f(2) = 4
f(3) = ???**
我们将尝试学习序列发生器 功能 调理(对!)对我们拥有的数据(f(1)
和f(2)
),然后将该函数应用于序列中的下一项(即 3)。即使我们只限于初等算术函数,也有许多函数符合我们的观察结果,例如:
**x * x
x ^ x
x ^ 2
x ^ (0 + x)
x * (x / 1)
0 + (x ^ x)
...**
换句话说,这是一个与我们之前的例子非常不同的场景:没有一个有限的假设集可以列出来,并以某种方式从最合理到最不合理进行评分。这个问题是 DH 在写的时候想到的:
由于数学本身充满了极其多样的模式,这个领域仍然是开放的。
既然我们不能列出我们的假设,我们需要把注意力转向能够产生无限假设的过程:幸运的是,我们的语言和语法知识来拯救我们。考虑这样定义的简单语言:
**1\. A, B, C ... Z are valid expressions
2\. If *X* is a valid expression, -*X* is also a valid expression
3\. If *X* and *Y* are valid expressions, *X&Y* is also a valid expression
4\. If *X* and *Y* are valid expressions, *X^Y* is also a valid expression**
根据语法可以生成多少个有效表达式?回答的关键是要认识到指令 2–4 以表达式为输入并产生新的表达式,这样任何一条指令的输出都可以成为另一条指令的输入(或者同一条!):
**A -> -A -> -A&B -> -A&B&A -> --A&B&A -> ...**
因此,即使像上面这样简单的语言也能够产生无数的表达式。
有了这种直觉,我们能通过一个语法来定义生成函数的空间吗?我们当然可以!我们只需要构建一个算术表达式的*语法,它可能会生成x * x
、x ^ x
、x ^ 2
等。和它们之上的先验(记住空间是无限的,所以我们需要一种“生成”的方式来分配所有可能函数之上的先验)。这是第一次尝试(要点包含语法,而完整的可运行代码可以在这里找到):
代码应该非常容易理解(原始代码来自优秀的 Goodman & Tenenbaum ):以 50%的概率,通过挑选一个整数(1–9
)或一个变量(x
)组成一个表达式,否则将两个表达式合并成一个新的表达式(它将递归地随机挑选一个整数,以此类推)。我们将只强调模型上的“隐式”先验,这是关于简单性的先验:在其他条件相同的情况下,更简单的函数(现在定义为语法上更短的)应该是首选的。由于产生x * x
比x * (x / 1)
需要更少的概率选择,尽管在外延上是等价的(如x = x/1
),前者被认为是一个更加可信的假设。显然,这在形式上等同于在一个模型中实施 DH 所说的:
倾向于简单和优雅的固有偏见
如果我们在序列上运行模型:
**f(1) = 1
f(2) = 4**
f(3)
的首选建议是 9:
Guessing the third integer for the sequence 1, 4, …
正如古德曼&特南鲍姆所说,“许多人发现分配给27
的高概率(……)是不直观的”。这表明,作为人类序列发现的认知模型,我们的先验可以使用一点修改:x times x
似乎比x raised to the power of x
更“自然”的想法(对非懒惰读者的练习:修改代码以反映这种偏差,并再次运行预测)。
这个模型能解决什么样的序列?下面是一些可以通过改变condition
语句来测试的例子:
**1, 4, 9 -> ??? x * x
0, 3, 8 -> ??? (x * x) - 1
1, 3, 5 -> ??? x + (x - 1)**
[非懒惰读者的练习:有时学习生成器函数最简单的方法是采用高阶序列,即认识到1, 4, 9, 16, 25, ...
产生一个3, 5, 7, ...
的子序列作为数对之间的差;然后,您可以使用第二个序列(奇数)对原始序列进行预测。鼓励读者将现有的模型扩展到二阶序列:在这种情况下先验是什么样的?]
我们可能想做的最后一件事就是兜一圈:在流体概念和创造性类比中,“PP 方法”与原始想法有多接近?DH 在整本书中的一个要点是概念表征是人工智能的问题..如果你从人类指定的概念(像“符号化的人工智能”)开始,你在乞求那些概念最初是如何被学习的问题;另一方面,完全自下而上的表示(那时,今天的深度学习系统在计算机视觉等任务中可以做的事情的非常早期的版本)适用于低级别的感知任务,但缺乏与人类概念相关的大多数通用性。因此, Fluid Concepts 中介绍的架构是自上而下和自下而上过程的混合,其中较低级别的概念被随机组合以构建较高级别的概念,这反过来使得一些其他低级别的概念更有可能被用于解决给定的任务。****
与我们的 PP 模型相比,最显著的相似之处是 1)假设空间的概率性探索(由基本概念构成),以及 2)组合原则的应用,以重用低级概念来构建高级概念。
我们强烈邀请读者从书中获得未经过滤的体验,因为我们不会用我们的概述来公正地对待它。也就是说,我们想在结束前再探索一个“流体任务”:让我们开始(数字)绘图板吧!
通过“视觉”语法学习空间概念
“画字母‘A’的方法有成千上万种,但我们一眼就能认出其中的任何一种。对于任何心理范畴(……),尽管差异巨大,我们还是能立即识别出成千上万个例子。”道格拉斯·霍夫施塔特
流体概念和创造性类比的最后一部分致力于文字精神,这个项目的目标是“设计和实现一个计算机程序,它本身可以设计出成熟的字体”。
在 DH 特有的利用玩具问题启发重要认知现象的方法论中, Letter Spirit 是一项类人机器创造力的实验,产生了一些非常有趣的字体设计:
Examples of Letter Spirit fonts as printed in Fluid Concepts and Creative Analogies.
众所周知,视觉概念既非常灵活(例如,我们可以用无数种方式画出一个一个),又非常独特(例如,人类可以立即识别出一些图画是同一主题的变体)。因此,毫不奇怪,教机器如何理解视觉概念从根本上被视为对字母概念本质的“T2”探索:
要认识某个事物——也就是说,要将一个项目与恰当的柏拉图式抽象相匹配——必须有空间来伸缩柏拉图式抽象和事物本身的精神表征,让它们相遇。什么样的扭曲是合理的?内部边界的重新调整、连接强度的重新评估和部件的重新排列是识别过程的核心。
正如我们在这篇文章中多次看到的,概率方法强调了理解一个概念 C 和生成 C 的新实例实际上是密切相关的活动。在不试图重现文字精神的全部复杂性的情况下,我们能在 PP 范式中讨论一些有趣的视觉学习案例吗?我们将从 WebPPL 计算机视觉演示的一个变体开始:如果我们用 n 条线画一个(数字)多边形(三角形、正方形、五边形),一个概率程序能首先找出它是如何制作的吗?
Examples of target polygons for our visual challenge.
基本成分现在应该很简单了。首先,我们定义了一个多边形的生成模型——如果你愿意,可以称之为“视觉语法”;一个可能的生成配方如下:
- **线条是我们的原始元素;基于四个整数[x1,y1,x2,y2]绘制线条;
- 首先从分布[3,4,5]中取样,以选择要绘制的线的数量;可能的话,将取样偏向更简单的模型,即尽可能少的画线;
- 如果 N 是要画的线数,则挑选 N 个四元组整数得到 N 条线,并画在画布上。
为了熟悉我们的可视化生成模型,你可以尝试在一个单独的代码块中创建一些行(见*要点让你开始)。在运行时,我们然后使用 PP 的能力来进行反向推理:给定一个具有某某特征的绘图,可能是什么指令创建了它?**
Forward and backward inference: from lines to polygons and back.
为了实现这一点,我们使用 WebPPL factor
表达式根据我们的多边形(使用上面的方法生成)与我们试图解码的目标图像的接近程度来衡量迭代。一旦我们生成了我们的分布,我们就可以通过反复采样来检查程序对视觉概念的了解,比如说,正方形:
*map(drawSamples, repeat(6, function() {sample(m);}));*
并显示结果:
Sampling instances of the concept “square” as learned by the probabilistic program: pretty cool!
还不错!换句话说,我们可以使用这个模型来生成我们所学的视觉概念的无限实例:非常简洁,不是吗?像往常一样,鼓励不懒惰的读者扩展和改进现有的代码样本(去可能以前没有模型去过的地方!).
作为最后一个练习,受我们最喜欢的公司之一的启发,我们在上面的视觉语法中添加了一些想法,并完成了我们自己的“仅在我的笔记本电脑上运行”原型,以展示 PP 的强大功能:不需要大数据进行训练,不需要黑盒优化,不需要昂贵的 GPUs——一切都在标准的网络浏览器中几秒钟内完成。欣赏视频!
Learning complex visual concepts re-using simpler ones.
结束语的随机分发
“我们(……)希望我们在本书中描述的工作可以在遥远的未来有助于引导比我们更深入地捕捉真正的流体心理的架构,艾伦·图灵在他首次提出他当之无愧的著名测试时就清楚地预见了这一点。”道格拉斯·霍夫施塔特
我们(终于!)在我们的绝技的最后,透过“流动的人类概念”的镜头来看概率编程。然而,我们几乎没有触及表面,因为当试图在一个雄心勃勃但非常未知的领域,即机器学习的概念和类似人类的推理(即使在*领域)中概述有趣的想法和有前途的技术工具时,这是不可避免的。
在没有穷尽上述线索的前提下,以下是我们迄今为止在概念驱动的人工智能方面的一些离别想法和更多哲学思考:
- 与深度神经网络中当前的人工智能大趋势相比,更明确地讨论 PP 在热点问题上的立场可能是好的。在我们看来,概率编程有望成为一种原则性的方法,用更少的数据进行学习,并以更人性化的方式行事,即既更接近我们对人类认知的了解,更重要的是更容易理解:虽然最近在深度学习模型中的可解释性问题上做了很多工作,但可以肯定地说,PP 模型在这方面有优势。深度学习已经获得了令人难以置信的普及,它承诺消除图像分类等任务中繁琐的特征工程,即通过自动学习有用的表示;虽然这通常是正确的,但在许多真实世界的案例中,人类专家确实知道很多关于手头推理的相关信息,而 PP 有一种直接的方式将这些数据包含到正式模型中:在一个还没有准备好(也没有准备好)为你提供完全自动化的科幻生活的世界中,能够用一种共享语言与你的企业软件应用程序进行协作是一件大事正如我们已经看到的,概率建模是一种非常自然的方式来弥合人类可理解的想法和机器学习的知识之间的差距。
- 有一些非常有趣的尝试将 PP 应用于计算语义学和语用学的主题。在 Tooso,我们正在研究知识图的 PP 模型,即利用隐式本体结构对自然语言查询进行快速可靠的推理。然而,天空是极限,因为 PP 承诺结合迄今为止难以调和的两个语言理解原则:首先,语言是合成的,因为复杂的表达(某种程度上)是由简单的表达组成的;第二,沟通是嘈杂的,以至于僵化的推论(例如纯粹的演绎)在几乎所有真实世界的用例中都将失败。真正的 - 而不是-有空闲时间的懒惰读者(学术界的朋友,有人吗?):反事实陈述要求我们根据没有发生的事实进行推理(“如果第一个骰子是 6,那么总和就不会是 5”)—有没有某种 PP(玩具)交流模型可以公正地解释这一点(贝叶斯建模和反事实之间的联系在相关文献中经常出现,但我们不知道反事实语义的具体应用,我们也没有太多地搜索)?
- 我们在帖子中多次提到古德曼、特南鲍姆和 T21,如果没有他们的网络书籍《认知的概率模型》。如果你喜欢玩概念学习,你一定要看看 理性规则例子;如果你发现文字精神的视觉挑战特别有趣,那么你应该而不是惊讶于 Tenenbaum 等人的最近的工作从 PP 的角度解决了一个非常相似的问题:概率程序归纳是我们近年来看到的最令人兴奋的范例之一——最好的范例肯定(嗯,很可能即将到来。
- 我们在博文中多次提到道格拉斯·霍夫斯塔德(Douglas Hofstadter ),如果没有他的书《T2:流动的概念和创造性的类比》( T3 ),这肯定是不可能的。作为最后的怀旧笔记,请允许我们陈述我们是多么想念 DH!他是大多数时候不出现在主流媒体上,不怎么参与推特争斗 ( O tempora!哦,莫尔! ) 《当代人工智能》中引用不多。遗憾的是,霍夫施塔特的想法仍然发人深省,并能为整个领域提供急需的原创视角,以更好地理解智力。
- 腊肠犬的例子( bassotto 是意大利语中腊肠犬的单词)是我自己的爱的回忆, Omero 。
如果你熬过了这篇令人难以置信的长博文(包括怪异的引用、书呆子论文和笨拙的代码样本),你值得我们最深切的感谢。
我们确实希望,不管你之前的信念是什么,观察这篇文章中的数据能说服你更密切地关注我们在 Tooso 正在构建的东西。
再见,太空牛仔
如果你有请求、问题、反馈或者疯狂的想法,请将你的人工智能故事分享给jacopo . taglia bue @ tooso . ai。
别忘了在 Linkedin 、 Twitter 和 Instagram 上获取来自 Tooso 的最新消息。
感谢
特别感谢安德里亚·波洛*奥利讲述了勇敢而令人敬畏的故事,感谢整个 Tooso 团队对本文之前的草稿提出了有益的评论;我们也感谢 人工智能的未来 见面会的组织者让我们在那里分享这些想法。
剩下的所有错误都是我的,而且只是我的。
关于 PP 的进一步阅读
我们的概率编程介绍很烂,尤其是在“编程”部分,因为我们只能介绍最少的 WebPPL 来说明我们的观点。从这里去哪里?不幸的是,对于脚本语言中的 PP(是的,我指的是 Python)来说,还没有太多完整的、从零开始的“计算机科学”介绍:**
- 这个曼宁本用的是费加罗(Scala);
- Pyro 最近已经开源了,但是社区仍然很*(这意味着:没有从 StackOverflow 复制+粘贴):将 WebPPL 模型移植到 Pyro 是一个很好的(尽管有时令人沮丧)入门方式;
- 这本“给黑客”的*书很有趣,非常实用,但没有涉及更抽象的人工智能应用(例如概念学习);
- 另一方面,认知的概率模型作为对 PP 的基于科学的介绍绝对是奇妙的,但它是基于 Javascript 的(免责声明:我们基本上喜欢一切Goodman&tenen Baum做的事情,所以我们也可能有点偏颇)。
最后,我们的建议是迷失在漂亮的例子和大量的研究论文中这里,这里这里和这里 ( 这个回购很神奇,但是大多数模型都不在 WebPPL 中:如果你喜欢自然语言语义,就从这个开始吧)。这个领域发展很快:如果你认为我们忘记了什么,请让我们知道。
720 的解决方案!难题
给定序列:
*f(0) = 0
f(1) = 1
f(2) = 2
f(3) = 720!
...*
发电机功能是什么?这是解决方案:
*0 -> 0 (0!)
1 -> 1!
2 -> 2!!
3 -> 3!!! (as 3! = 6 and [6! = 720](https://www.wolframalpha.com/input/?i=6!))
4 -> 4!!!!
...*
即对于每一个 x ,x-乘以阶乘 x* (参见流体概念与创造性类比,第 46 页)。*
#0014:度假袋鼠
原文:https://towardsdatascience.com/fms-0014-holidaying-kangaroos-149ba9b4030b?source=collection_archive---------5-----------------------
一个持续的问题是,被机器人取代的制造业工人会发生什么。这篇文章指出,在某些情况下,使用机器人的成本现在比公司使用奴隶劳动力的成本要低。#autonomous
#mechanised
自动驾驶汽车还没有真正为黄金时间做好准备,可能还需要一段时间。艺术家詹姆斯·布里德想出了一个新奇的点子:用一些道路油漆困住自动驾驶卡的方法。更多图片和视频这里。#autonomous
我们离第五级汽车自主驾驶还有多远还不清楚,但是优步今天能够做到的和宝马计划在 2021 年实现的与第五级汽车自主驾驶之间的差异是非常明显的。如果“每英里至少接管一次”是标准的话,我估计我现在的车只能算是“自动驾驶”了。至少在非常直的路上。#autonomous
#mechanised
技术界一直在讨论颠覆的概念。这篇文章讨论了颠覆是如何在移动行业上演的。每当有人谈论颠覆,也值得参考本·汤姆森的聚合理论,我认为,这比克里斯滕森的原始颠覆论文中提出的更好地描述了面向消费者的技术中实际发生的事情。#autonomous
#mechanised
机器会拥有自己的企业吗?#autonomous
需要在 60 英尺的积雪中清理出一条路吗?这些乡亲可以帮忙。#snow
#wow
我们可能很快就会开着电动黑色出租车到处跑。#electric
这是一个非常棒的“人工智能介绍”演讲:吴恩达:人工智能是新的电力。#cognitive
增加人工智能潜在影响的赌注:神经科学家和哲学家山姆·哈里斯描述了一个既可怕又可能发生的场景。他说,这不是一个好的组合。如果唯一安全的前进方式是“将这项技术直接植入我们的大脑会怎么样?“我认为这有点道理。我不确定我们(目前)是否有一条通往人工智能的明确道路,但如果我们有,那么我认为融合的场景,即我们通过增强自己而不是与之斗争来“成为”智能机器的一员,可能是我们作为一个物种长期生存的最佳机会。#cognitive
**
机器人值得拥有权利吗?如果那些机器人变得有意识了呢?嗯。我们无力回答的棘手问题。下面是提出这些问题的一个短片。如果这个问题被提出来假设机器是有意识的,无论你想提出什么样的测试,那么除了认为这些“机器”应该被赋予与其他有意识的“实体”相同的权利之外,我看不出你如何能得出一个道德或伦理上合理的结论。也许我们应该更担心机器是否会给我们权利……#cognitive
**
谷歌的 DeepMind 部门正在与英国国家电网进行谈判,以利用人工智能/人工智能技术减少 10%的能源使用,而无需改变基础设施。它还与英国国民保健服务系统合作。以及支持一个名为distilt的新(ish) AI/ML 研究出版物。#cognitive
目前有很多关于交通电气化的消息,但电池技术似乎没有同样快速的发展。锂电池的最初发明者约翰·古德诺的一项新发明可能会改变这种情况。他和三位合著者一起撰写了一篇新论文,描述了一种快速充电、不可燃电池的技术。然而,正如所有激进的技术进步一样,并不是每个人都信服。#battery
我不知道哪个更糟糕:由无知的人发布的假新闻,或者由人工智能语言工具启用的机器,机器人般地相互鸣叫。#cognitive
#fakenews
哭泣、哭泣、情感撕裂——这是怎么回事? #tears
#whatevenarethey
爱迪生是一台装在火柴盒里的 Linux 制造机。#mechanised
#cognitive
这项技术使用加密技术来创造一个只能进行加密预测的人工智能。这不仅具有允许人工智能在敌对环境中训练的好处,还意味着从人工智能的角度来看,外部世界是加密的。这是一个非常深刻的结果,它可能会创造一个环境,让我们(即人类)安全地发展人工智能。#cognitive
#agi
#mindblown
只有在澳大利亚
甚至袋鼠有时也需要休假。#onlyinaustralia
周五预告
抱歉,这周晚了一天。
从 1 到 100 依次有 100 个人站成一圈。一号人物有一把剑。他杀死了他面前的人(即 2 号),然后把剑交给下一个人,在这种情况下,是 3 号。队列中的每个人都这样做,直到只有一个人幸存。活到最后的人的数量是多少?
像往常一样,在评论中向第一个正确答案敬献花束。
问候,
M@
#0025:伦敦笔记。AI8
原文:https://towardsdatascience.com/fms-0025-notes-from-london-ai8-fb423fe88914?source=collection_archive---------5-----------------------
我去了伦敦。艾 8 上周四晚上。它是在 Twitter 的伦敦办公室举行的,说得轻描淡写一点,这里相当豪华。
当晚有来自四家企业的推介和演讲,它们在人工智能和机器学习方面做着有趣的事情:
- 不可能的:一家总部位于伦敦的初创公司,创造了一种分布式、实时、持续模拟的技术。
- 桌面遗传学:带你经历基因组编辑实验的每一个方面,从设计到数据指导你,让你充分认识到 CRISPR 技术的效用。
- 夏洛克 ML :数据科学的操作系统。
- Vortexa :使用人工智能分析和解释大规模数据。它从数百个来源吸收了数十亿个数据点,以显示全球石油的过去、现在和未来流动。
不大可能的
不大可能专注于使用云基础设施的大规模模拟,以“实现规模和复杂性前所未有的虚拟世界”。他们刚刚从软银获得了一大笔现金注入,软银也对硬件进行了大量投资。
在我职业生涯的早期,我在飞行模拟器上做了一些工作,构建大规模离散事件模拟的挑战是非常真实的,演示展示了一些令人印象深刻的技术。这项技术在大型多人在线游戏中有明显的使用案例,但是其用途远远超出了游戏。
与人工智能/人工智能社区的相关性有点模糊。但是,如果你考虑一下 OpenAI 对宇宙所做的事情,然后将空间技术应用于同类问题,似乎会有很大的潜力。
这些人在未来绝对值得关注。
桌面遗传学
桌面遗传学是一个人工智能驱动的基因编辑平台。我对编辑基因一无所知,但是看起来它将会改变基因研究的游戏规则。
如果你给“ai@desktopgenetics.com”发一封电子邮件,你会得到一个回复,里面有一堆关于 CRISPR 和相关技术的有趣链接,而不是试图解释这些人在做什么。
夏洛克 ML
SherlockML 试图成为“数据科学的操作系统”。要理解这意味着什么,想想 Excel 为会计师和分析师做了什么,或者 Photoshop 为设计师做了什么,然后你就可以理解 SherlockML 试图为数据科学家做的事情了。
随着数据科学、人工智能和机器学习等学科的不断成熟,将会有很多这样的平台。
旋涡
Vortexa 使用人工智能来分析和解释大规模数据。它从数百个来源吸收了数十亿个数据点,以显示全球石油的过去、现在和未来流动。他们使用卫星图像和人工智能/人工智能技术的组合来创建全球能源供需视图。
这是“任何可以预测的事情,都将成为”大规模数据科学带来的必然性的一个例子。这里的天才洞察力是使用高分辨率卫星图像结合机器学习模型来预测世界各地的石油运动。
问候,
M@
#0028:来自认知 X 2017 的注释
原文:https://towardsdatascience.com/fms-0028-notes-from-cognitionx-2017-7acd3edb23cb?source=collection_archive---------8-----------------------
Source: @heyerlein @ Unsplash
上周二有幸参加了 CognitionX 2017 的第一天。会议组织得很好,采用了主题演讲/*组讨论/分组讨论的新颖形式。主题演讲设置了一个主题,然后由 3-5 名专家组成的*组讨论了观众提出的互动问题(通过 Sli.do ),随后是详细的分组会议。
我所看到的主题的信噪比非常好,这些主题往往专注于人工智能和机器学习的社会、政治、经济和文化因素,而不是深度技术。在整个会议期间,大约 30%的与会者是女性,这比这类事情的正常情况要好得多。尽管组织者自己也承认,在这方面还有很多工作要做。
以下是我在第一天设法看到的 3 次会议的亮点:
人工智能的现状及其对社会的影响,第一部分
根据设计,会议有意关注窄/垂直 AI 的影响,并有意(在大多数情况下)避开关于人工通用智能 (AGI)或超级智能的讨论。
当会议简要谈到 AGI 和超级智能时,普遍的共识是没有达成共识。
汉森机器人公司的大卫·汉森认为,AGI 将在“5 到 10 年后”实现,届时将会有能感知周围环境的机器人帮助实现。大卫和索菲亚在一起,一个外表和声音都很逼真的机器人,并没有让我相信这些时间表。索菲娅和主持人之间的采访看起来完全是预先安排好的。
在第一个*组中,来自其他人(seánóHeigeartaigh)的经过深思熟虑的观点表明,AGI 可能还需要 20-50 年的时间,并且需要在多达 12 个独立的艰苦研究领域取得根本性的科学突破( Charlie Muirhead )。我不确定 12 是从哪里来的,但如果是 12,那很可能是 112 或 12000。很难预测科学研究的流向。
值得查阅的参考资料:
- 剑桥大学生存风险研究中心——生存风险研究中心是剑桥大学的一个跨学科研究中心,致力于研究和减轻可能导致人类灭绝或文明崩溃的风险。
- 汉森机器人——自己拿定主意索菲亚和其他机器人。
金融服务和经济
J Doyne Farmer 教授对复杂经济学和基于主体的建模领域进行了一次旋风式的访问。他认为目前在人工智能/人工智能领域进行的大部分工作都是“比回归分析好不了多少”(这不是一个不合理的描述),我们需要转向基于主体的模拟,以推动经济理论向前发展。与回归不同,回归从定义上讲是向后看的,这些技术允许您对以前从未遇到过的情况进行建模。
法默教授表示,他即将开发出一个可以模拟英国 2700 万个家庭的系统。他认为,这将为公共政策提供比民意调查更好的见解,民意调查在最近一段时间里出现了许多著名的失误。他还提到了“BINC”(生物、信息、纳米、认知)的概念,认为它掌握着人类未来的钥匙。或许有人应该成立一个 BINC 基金?
专家组会议中的一些选择(错误)引用:
- “人类是工业革命的机器人”J·多恩·法默教授——回避了一个问题:人类将在人工智能革命中扮演什么角色?
- “人工智能/自动化开始夺走认知技能”皮帕·马尔姆格伦——仅是轶事证据
- “英国 60%的经济是私营企业Damian Kimmelman,du edill——然而我们的大部分政策都是基于上市公司的数据
- “人们仍然认为机器没有”J·多恩·法默教授——也许永远不会有?
- “我们应该将市场的周期时间降到 1 秒钟,这样每个人都有时间做出明智的决定”J·多恩·法默教授 —这将使 HFT 的吸引力大打折扣,并消除某些特权玩家仅仅因为靠近交易所而获得的优势
- “在印度,只有不到 40%的人纳税,其他人都靠福利生活。”
在区块链理工大学的一次讨论中,皮帕·马尔姆格伦在回答观众提问时提到了一件有趣的轶事,关于 1834 年点燃计数棒导致威斯敏斯特教堂发生火灾。这一事件与区块链技术的推出有相似之处(在一些*组成员看来)。在我看来,这里的一些争论是基于对区块链技术到底是什么的根本误解,但这个轶事仍然很有趣。
值得查阅的参考资料:
- J . Doyne Farmer 教授—牛津马丁学院新经济思*研究院复杂性经济学联合主任。
- 经济模拟库 — ESL 是一个社区驱动的开源项目,旨在开发一个用户友好的建模库,用于构建基于代理的经济系统模型。
政治和治理
这里有一些关于人工智能在竞选中的作用的有趣讨论,特别是像最近美国大选中的剑桥分析和去年的#英国退出欧盟投票这样的组织的作用。专家组的一致意见是,像 CA(和其他组织)这样的组织的影响可能被夸大了,但他们参与的透明度确实令人担忧。
网络安全一瞥
由此得出的主要结论是“人工智能支持的数据窃取离还有很长的路要走”,这是个好消息。
还有一个非常有趣的线索,暗示了一个很好的研究主题:使用分布式版本控制系统中的版本历史作为训练数据的来源,来构建一个 AI/ML 系统,该系统可以自动找到并修复源代码中的 bug。这确实是软件工程的圣杯。这可能还有一段路要走,但是数据(在版本控制系统中)和过程(在人工智能/人工智能技术中)现在已经可以向前推进了。
人工智能的现状及其对社会的影响,第二部分
数字国务部长马特·汉考克讲述的重点是他自己讲述的事实,即卢德派领导人本杰明·汉考克是他的一个远亲。至少我认为看到了讽刺。
*组讨论的大部分集中在自动化渗透到各个层面时,经济会发生怎样的变化。作者卡勒姆·刘升对失业的 T2 人和失业的 T4 人进行了有趣的区分。他问了一些尖锐的问题,关于当 25%或更多的劳动力变得无法就业时,经济会是什么样子。他将这种(潜在的)暗淡的经济状态称为“经济奇点”。
值得查阅的参考资料:
- 卡勒姆·刘升—经济奇点和幸存 AI 的作者
摘要
总的来说,这是一个非常好的一天,内容非常棒(少一些技术,多一些社会/经济/政治/社会)。信噪比很好,没有任何形式的供应商推销演示(我看到的),并且受到了来自技术和商业社区各个部分的优秀、积极的观众的光顾。如果 CogX 2018 明年举行,它绝对值得参加。
问候,
M@
关注最终用户指标,走出你的舒适区
原文:https://towardsdatascience.com/focus-on-end-user-metrics-and-get-outside-your-comfort-zone-5c629dd0b0b2?source=collection_archive---------15-----------------------
Photo by Daniel Gaffey on Unsplash
过分专注于优化算法对任何产品都是有害的——打破这种专注,着眼于解决方案的整体情况,往往会以模型优化的一*部分成本为最终用户带来更好的性能。
理解全局是一项艰巨的工作,需要大量的时间。由于这些原因,它经常被搁置,以获得更多的数学改进。专注于一个模型的独特性和容易性对数据科学家来说可能是有吸引力的-因此,对于数据科学家来说,走出我们的舒适区更为重要。
关注最终用户
在我看来, 最重要的 数据科学家工作的一部分是了解最终用户,并从他们工作领域的专家那里吸收尽可能多的领域知识。我经常把自己的工作看作是算法的老师和向导,我应该给他们一切成功的机会。拥有领域知识并作为产品所有者,允许我站在用户的角度考虑问题,并允许我在优化之外找到改进产品的方法。让我们看一个简单的例子。
想象一下,在一个项目中,你试图从成千上万张照片中预测狗的品种。你不可避免地会构建一个深度学习模型,并拥有成千上万(或潜在的数百万)带注释的例子。当你和你的团队专注于该算法时,你将开始触及与边际收益递减规律相冲突的性能上限。
当您达到性能上限时,您可以将几个简单的步骤放入您的 ML 管道中以提高性能——并且这些步骤很可能会超过仅在您的模型上花费昂贵的开发人员时间所带来的增量改进。
- 为狗建立一个分类器,并从训练和测试集中删除所有不包含狗的例子。
- 使用模型的输出来识别分数很低的带注释的图像,或者在太多类别上分数很高而不真实的图像。使用此数据清理您的培训数据。这可以迭代完成,可以显著提高性能。如果你做的方法正确,你甚至可以自动完成大部分工作。
- 寻找人们不感兴趣的课程。也许人们对秘鲁印加兰花不感兴趣——把它们从你试图识别的类别中移除。
- 花时间了解假阳性与假阴性的成本。理解用户的这种成本效益,并将其构建到你的算法中。这可能不会提高您的精确度,但也许这没关系——通过优化正确的指标,而不是与最终结果脱节的东西,您可能会获得很大的价值提升。
- 构建一个分类器,对极有可能被错误分类的图像进行分类。这样做的时候,往往会发现系统性的问题。在图像分类中,这可能是镜头着色、相机故障或其他原因。
在一天结束时,你应该有一个可定义的,客观的标准来判断你的产品。在许多情况下,精确度、召回率、AUC、对数损失和其他标准度量是不够的。精确度的价值可能是回忆的十倍,也可能是回忆的一半——关键是如果你不尝试理解最终用例,你永远不会知道。通常,定制指标对于构建最好的产品至关重要。
通过梯度下降进行食品成分逆向工程
原文:https://towardsdatascience.com/food-ingredient-reverse-engineering-through-gradient-descent-2a8d3880dd81?source=collection_archive---------7-----------------------
DeepNutella — Neural Style Transfer (base image: nutella.com)
带着另一个奇怪的想法回来,这总是另一个学习新东西的借口。这个故事是关于我做的一个快速实验,猜测包装食品中每种成分的不同含量。基于成分列表和营养事实标签,我将任务公式化为线性回归问题,其中成分百分比是参数。为了执行优化(梯度下降),我使用了官方的 hipster 深度学习库,又名 PyTorch 。代码可以在这里找到。
我喜欢烹饪。我并不总是有时间做饭,但当我有时间时,我会尝试使用非常科学的方法。例如,我喜欢简化和揭开老祖母食谱的神秘面纱。在这个过程中,我可能不得不处理食物数据,尤其是营养数据(也就是碳水化合物、蛋白质、脂肪、盐等的含量)。).
在这个实验中,我试图通过使用大多数包装食品上要求的营养成分标签来找到食谱中(缺失的)成分百分比。我的直觉是,这些数据足以找到真正的配方。
注:显然还有一些其他的方法可以找到食材,但是在这个 炼金 的时代,为什么不针对问题扔点渐变下降呢?
就拿我们钟爱的棕榈油涂抹酱 Nutella 来说吧。
以下是配料:
砝码
在我的线性回归模型中,参数(重量)是不同成分的克数:
- w1 是 100 克果仁糖的含量,
- w2 是 100 克果仁中棕榈油的含量,
- 诸如此类…
在某些情况下,某些百分比是已知的。欧洲 Nutella 就是这种情况,我们知道其健康成分(榛子、可可等)的含量。).在这种情况下,重量是固定的,不可训练。
输入和输出
现在营养事实标签:
每个营养成分成为一个训练观察/例子(x,y)。
让我们以“总脂肪”组件为例,它给了我们一个(x,y)元组。
x 是包含每种成分中脂肪百分比的行向量:
- x1 是糖中脂肪的百分比(0%)
- x2 棕榈油中脂肪的百分比(100%)
- …
这些很简单。但对于某些成分,猜测其成分变得越来越难(卵磷脂有人知道吗?).在这个实验中,我使用了美国农业部国家营养数据库,其中包含了大多数基本成分的信息。
注意:这个数据库并不是万能的,营养成分会有很大的不同(榛子有不同的种类,你可以选择是否烘焙它们,可可可以是生的或脱脂的……)
在我的非常深的 1 层神经网络的另一边,y 是一个标量,包含最终产品中的脂肪量。这些信息很容易在营养事实表中找到:
每份 Nutella 含有 12g 脂肪,或者,在一个更文明的营养标签系统中:31%(谢谢法国)
由于这种标记非常冗长,我们可以得到大约十个(x,y)样本。
培养
当然,在模型中,线性单位没有偏差。在食物成分中找不到暗物质,所有的东西都被计算在数量的加权和中。
在 PyTorch 中声明所有这些相对容易(这是我的第一次),这个库非常自然和直接,我想我现在理解炒作了。现在,我们应该只是减少原始 L2 损失吗?不,我们必须在模型上设置很多约束,使它收敛到一个看似合理的局部最*值,而不是一个我必须放入负量可可的奇怪配方。
特定域约束
- 质量不能是负的(不是开玩笑)
- 一些权重是固定的(当百分比已知时)
- 质量的总和必须等于 100 克
- 最重要的是,重量要按降序排列(与包装上食品成分按降序排列的方式相同)
这些约束中的一些是在更新权重时强制实施的,一些是通过损失函数中的炼金术士技巧实施的。恐怕这些都不是什么好东西。
我使用整个数据集(批量梯度下降)来计算每一步的损失函数。结果如下:
配料:糖(50.8%)、棕榈油(19.7%)、榛子(13.0%)、可可(7.4%)、脱脂奶粉(6.6%)、乳化剂(1%*)
()充分披露:乳化剂保持在 1%以下(它只是一种添加剂)*
我承认结果并不令人印象深刻。但是我想把它看完,通常,旅程比目的地更重要:)希望你喜欢它!
source: hersheys.com
奖金:里斯的花生酱杯
我还试图找到里斯著名的花生酱杯子的原料。
这是一项更艰巨的任务:10 种不同的成分,但没有一种是已知的。
此外,还有两种“复合”配料,每种都有自己的配料表:牛奶巧克力涂层和花生酱夹心。
Here, a clear example of ingredients getting stuck between their left and right neighbors
配料:牛奶巧克力(62%)【糖(20.3 克)、可可脂(16.0 克)、可可液块(6.3 克)、脱脂牛奶(6.3 克)、乳脂(6.3 克)、乳糖(6.3 克)、乳化剂(0.3 克)】花生馅(38%)【花生(18.7 克)、葡萄糖(18.7 克)、盐(0.7 克)】
这个故事到此结束。如果你喜欢,可以关注我的 中 或 推特 获取最新消息。如果你喜欢唐纳德·特朗普,你可能会喜欢阅读 这篇文章 。如果你更喜欢《权力的游戏》, 去那里 。
另外,如果你觉得有什么不对,或者有什么问题,欢迎在下面评论。
使用机器学习的足球提示:添加玩家数据
原文:https://towardsdatascience.com/footy-tipping-with-machine-learning-adding-player-data-9ccdab56a4c5?source=collection_archive---------21-----------------------
我是如何停止担忧,学会获取、汇总和重塑 AFL 球员数据的。
Photo by Scott Webb on Unsplash
我试图开发一个关于*费的数据模型,这是系列文章的第四部分。你可以在这里阅读第三部**。本帖使用的 Jupyter 笔记本可以在* 这里找到 。*
当我开始这个项目时,我的主要目标之一是将玩家数据整合到我的足球*费模型中。我上个赛季的模特 Footy Tipper 将投注和团队比赛数据整合到一个整体中,但我不太明白如何以增强性能的方式包含基于球员的功能。我尝试按字母顺序对球员名单进行排序,将球员姓名视为分类变量,然后在我的神经网络中添加嵌入层,但这只是增加了噪声,实际上稍微降低了准确性。由于 AFL 赛季很快就要来临,我没有太多的时间进行实验,所以我暂时放弃了使用球员名单的想法,发誓要带着更多的人、马和钢铁回来。随着 Tipresias 的出现,我带着一些新武器向路障发起了另一次攻击。
菲茨罗伊不错,但我是个皮托*斯塔
在最近的 AFL 赛季,我开始关注强大的 AFL 统计社区,在我的美国沙文主义中,我认为这个社区并不存在。什么?在一个人口仅占美国 7.6%的国家,一个地区性职业体育联盟足以支撑一大批痴迷于数据的粉丝,他们能够撰写足够多的博客帖子和推文,来告知我对足球统计数据的新兴趣?就当我卑微吧。我在推特上关注了几个账号,读了一些关于统计数据的帖子,然后开始将我的模特的表现与那些在网上参赛的名人进行比较。
除了教会我足球的优点,我的研究还收获了这个*宝贝:菲茨罗伊。fitzRoy 是一个 R 包,它避开了流行的 AFL 统计网站,清理了数据,并在 good china 上提供了数据框架。它甚至有像样的文档!我对以最*的努力获得大量数据的前景感到非常兴奋,因为使用开源包比*护自己的网站抓取器容易得多,尤其是当面对导航 AFL 表的 borgesian 噩梦时。唯一的问题是,我所有的工作都是用 Python 完成的,而 fitzRoy 是严格针对 R 的,我每隔几年就要学习它的基础知识,但由于缺乏实践,很快就忘记了。我在 R 中有一个很棒的数据源;我在 Python 中有一个数据消耗的机器学习模型;我怎么才能让这两个人见面呢?
幸运的是,什么都有一个工具,甚至是让你的工具更好工作的工具。稍微搜索了一下,我就找到了 Python 包 rpy2 ,它的全部目的是让您在 Python 上下文中运行 R,无论这意味着将 R 包作为 Python 模块导入,直接在.py
文件中运行您自己的 R 代码,还是将 R 数据帧转换成 pandas。不幸的是,这给我的项目依赖性增加了额外的复杂性:我不仅使用了更多的包,而且我现在需要在我的开发环境中有两种完整的语言可用。解决这个问题的最好的工具肯定是 Docker(对于代码,它是一路向下的工具),特别是如果您计划在不同的机器上运行这样的代码或者与其他人合作。这不是 Docker 教程(如果你感兴趣,你可以在 GitHub 上查看 Docker 对 Tipresias 的设置),但基本思想是它创建了一个隔离的虚拟环境(即“容器”),你可以在其中运行你的代码。这意味着您可以安装所有依赖项的精确版本,而不用担心与计算机上的其他库冲突。此外,合作者只需输入几个命令,就可以轻松地创建一个已经安装了所有东西的开发环境。
我没想到福蒂做了这么多坏事
121 年来,很多人在 VFL 和 AFL 打了很多比赛:619,751 场(加上比芒格更容易输掉的几轮循环赛中的 100 场左右),给或拿。该数据集的规模带来了新的挑战,超出了更长的处理时间。首先,当我清理和转换数据时,我的 Jupyter 笔记本电脑一直在崩溃,这导致我花了整整一个周末来解决如何批量处理数据的问题,结果才意识到我所需要的只是增加 Docker 的内存限制。
至于弄清楚如何让球员数据成为对比赛预测有用的形状,本着总是从 MVP(在这种情况下是“最*可行产品”)开始的精神,我决定采用一种简单的方法:计算每个球员统计数据的滚动平均值(例如,踢球、得分、进球),然后将参加给定比赛的给定球队的所有球员的平均统计数据相加。这类似于使用一个球队在比赛中的统计数据的滚动平均值,但增加了一个细微的差别,只包括实际比赛的球员最近的表现。因此,如果一个球队的最佳球员没有参加他们的下一场比赛,总的统计数据将反映该队预期表现的下降。
在董事会上得到一个模型
现在,我已经将我的球员数据聚合并组织到团队比赛行中,就像我的其他模型的数据集一样,我可以开始查看各种机器学习模型的相对性能。与基于其他数据集的模型一样,我发现包括一支球队的统计数据和他们对手的统计数据可以提高模型的性能,最低的交叉验证平均绝对误差(MAE)在没有对手统计数据的情况下为 31.79,在有对手统计数据的情况下为 30.95。以下是使用球队及其对手的聚合球员数据的各种模型的 MAEs。
与博彩数据一样,尽管这次不那么明显,但线性模型的表现优于花哨的集合。然而,前五名都非常接近,如果不是按升序排列,很难选出最好的。下面的准确度分数进一步证明了这些模型的性能有多接近。
当考虑模型的准确性时,LinearSVR 和 Ridge 仍然是最高的,但它们现在落后于 MAE 分数排名第三至第五的集合模型。值得庆幸的是,至少相同的模型在 MAE 和准确性方面都排在前五位,这限制了我在逐年细分的性能中需要比较的数量。
Ridge 和 XGBoost 似乎有最好的年度 MAEs,每个都有两年内的最低值,但与 CV/test 分数一样,没有明显的赢家,因为 2015 年和 2016 年的误差分数非常接近,XGBoost 和 Ridge 在任何给定的年份都没有持续排名前二。
不管我用多少种不同的方法分割数据,我总是得到混杂的结果。在这一点上有点直觉,但 XGBoost 往往是跨不同度量和数据段的较好模型之一。这不是一个明显的赢家(Ridge 和 GradientBoost 的性能大致相当),但我过去使用 XGBoost 取得了不错的结果,这足以让它占据优势。
玩家评级模型
受到 HPN 的 PAV 的启发,但我对足球不够了解,无法应用必要的严谨性来创建我自己的球员评级系统,我想知道我是否能找到一种算法来为我创建一个。我没有像上面那样汇总玩家的比赛统计数据,而是将它们和一些汇总的对手统计数据一起输入一个回归变量,试图估计每个玩家对最终得分的贡献。这是一种简单的方法,但我只是想看看它是否有潜力作为一种使用球员数据来预测比赛结果的手段。
我通过几个线性算法(当我试图使用 scikit-learn 集合时,waaaay 花了太长时间来训练)来处理未聚合的球员数据,以根据每个球员的游戏内统计数据来估计每场比赛的最终得分差距。然后,我采用了表现最佳的模型,并使用其预测创建了一个球员评级特征,我将该特征按每场比赛的球队进行汇总(即每场比赛有两行,每个参赛队一行),以用于最终模型。这种堆叠整体的最终表现并不太糟糕,但表现最好的模型仍然比基于聚合球员统计数据的简单模型多几个点的 MAE 和低几个百分点的准确性,即使相对表现更接近,在原始球员数据上训练模型所花费的时间也是令人痛苦的。说真的,我的笔记本偶尔会在计算交叉验证分数的过程中挂起,这就像西西弗斯的巨石滚回冥河深处一样。有可能使用类似这样的东西向主玩家数据模型添加一个特性,但是我想我会通过添加 PAV 来获得更好的性能,所以这个想法对于未来的实验来说优先级很低。
3D 玩家数据
鉴于球员数据给我的初始团队比赛数据结构增加了一个额外的部分,我想知道,除了汇总统计数据,我是否可以将球员分成他们自己的*度,将*度为[team-match
xaggregated feature
的矩阵转换为[team-match
xplayer
xfeature
]的矩阵。获得正确的数据形状需要比我希望的更多的工作,但是我能够在 Footy Tipper 中重用递归神经网络(RNN)的一些代码来完成它。对我来说,最大的挑战是总是以正确的排序顺序获取数据,并计算出正确的*度,以便 numpy 的reshape
按照我想要的方式工作。一旦我超越了二*,我的大脑开始崩溃,但我最终还是到达了那里。
与玩家评级模型一样,这只是一个实验,所以我实现了一个尽可能简单的版本,选择了一*卷积层和常见的池层。由于对 RNNs 有了更多的经验,我对 CNN 模型在数据上训练的速度感到惊喜,但即使在退出或正则化参数的情况下,过度拟合也是一个主要问题。训练集的误差随着每个时期持续下降,而验证误差将在两个或三个时期达到峰值,然后继续上升。这导致了与玩家评级模型相似的性能,即,在最好的情况下,MAE 在 30-32 的范围内,准确性在 64-66%的范围内,这两个指标都明显比基于聚合玩家数据训练的线性模型差。将这一点添加到集合中或以某种方式扩展数据以减少过度拟合是有一定潜力的,但就目前而言,与玩家评级模型一样,这种实验的优先级低于其他改进,如特征工程和在完整数据集上实现 RNN。
我们今天学到了什么?
我感觉这一系列博文的叠句就是“保持简单,笨蛋”。尽管我不后悔花时间去试验更复杂的方法,但基本的线性模型一直表现得和花哨的集合模型一样好,甚至更好。即使万能的 XGBoost 是最好的模型,当使用正确的随机种子时,总有至少两个线性模型稍微差一点,有时可能更好。已经看到了从几个不同的模型类型创建集合的可测量的收益,然而,我认为稍微更细微的教训是在移动到构建整个城堡之前从简单的构建块开始。重要的是要有一个好的基础来比较未来变化的影响。
为了你的皮肤美丽:用散景映射化妆品
原文:https://towardsdatascience.com/for-your-skin-beauty-mapping-cosmetic-items-with-bokeh-af7523ca68e5?source=collection_archive---------6-----------------------
根据化妆品的化学成分给出建议
每当我想尝试一种新的化妆品时,都很难选择。实际上不仅仅是困难。这有时很可怕,因为我从未尝试过的新东西最终给我带来了皮肤问题。我们知道我们需要的信息在每个产品的背面,但是除非你是一个化学家,否则很难解释那些成分表。因此,我不再担心我的新选择,而是决定自己建立一个简单的化妆品推荐。
第一步,我从丝芙兰网站搜集信息。为了专注于护肤项目,我只选择了六个不同的类别——润肤霜、面部护理、洁面乳、面膜、眼部护理和防晒。数据集总共有 1472 个项目。它也有关于品牌、价格、等级、皮肤类型和每件物品的化学成分的信息。我将跳过网页抓取这一步,但完整的代码和数据集可以在我的 Github 上找到。
按成分推荐
本文假设您已经对推荐系统有了基本的了解。如果你不熟悉推荐系统或余弦相似度,我推荐你阅读艾玛·马尔迪的 这篇 文章,它能给你这方面的直觉。在构建推荐引擎的各种方法中,基于内容的推荐被应用于本项目。选择的原因主要有两个。
首先,根据我过去用过的物品来预测一个新产品有多合适是不合适的。那是因为训练集(过去的产品)比测试集*很多。想象一下,与世界上存在的化妆品数量相比,一个人尝试了多少产品。
其次,关于皮肤病的美容建议是一个复杂的问题。可能有些人对化妆品有着非常相似的品味。而且有了用户-用户协同过滤,我们就可以根据这个邻近群体的排名值来推荐新产品。然而,一个人的皮肤类型和特征是一个比仅仅推荐你今晚的电影更敏感和棘手的问题。要得到推荐中的可靠性和稳定性,我们需要关注每种产品的真实含量,或者产品的成分,并基于它们得到相似度。
进入之前的一些预处理步骤。
现在让我们从检查数据集开始。抓取后的几个预处理步骤已经完成,我们将从这里开始。无重复项 1472 项,17 列。
下一步是清除Ingredients
列中的文本数据。数据是从 Sephora 页面上刮下来的。正如你在下面看到的,有两个部分——一些特定成分的描述,所有成分的列表,以及附加信息。
这里只需要食材部分(左边第二段或者右边第一段)。由于行被'\r\n\r\n'
分隔,我们将使用此模式分割文本。
*# Split the ingredients with '\r\n\r\n'*
a = [t.split('\r\n\r\n') for t in cosm['Ingredients']]
结果将是列表中的列表。换句话说,分开的部分被放在一个列表中,每个条目的列表被收集在一个列表中。那么我们如何只提取成分的一部分呢?我的策略是使用几种模式来检测不需要的部分。
*# Take onle the part with the real ingredients*
pattern = ['\r\n', '-\w+: ', 'Please', 'No Info',
'This product','Visit']**for** i **in** range(len(cosm)):
num = len(a[i])
**for** j **in** range(num):
**if** all(x not in a[i][j] for x in patern):
cosm['Ingredients'][i] = a[i][j]
遍历每一项,我们可以只取一个不包含模式词的项,放入Ingredients
列的相应行。现在我们准备开始标记化了。
将 NLP 概念应用于化学品
我们的数据中有六类产品(保湿霜、洁面乳、面膜、眼霜、和防晒),还有五种不同的皮肤类型(混合性、干性、中性、油性和敏感性)。我们正在制作的地图是带有可选选项的绘图,以便用户可以获得更详细的结果。会有两种选择。一种用于化妆品类别,如保湿剂和清洁剂。另一类针对干性和油性等皮肤类型的用户。为了清楚起见,让我们先关注一个选项,即针对干性肤质的 保湿剂 ,然后将相同的过程应用于其他选项。
**# Making the two options*
option_1 = cosm.Label.unique().toarray()
option_2 = ['Combination', 'Dry', 'Normal', 'Oily', 'Sensitive']*# Filter the data by the given options*
df = cosm[cosm['Label'] == 'Moisturizer'][cosm['Dry'] == 1]
df = df.reset_index()*
过滤后的数据有 190 项。为了达到我们比较每个产品成分的最终目标,我们首先需要做一些预处理工作,并记录每个产品成分列表中的实际单词。第一步是标记Ingredients
列中的成分列表。将它们拆分成记号后,我们将制作一个二进制单词包。然后我们将创建一个带有标记ingredient_idx
的字典,如下所示。
**# Tokenization*
ingredient_idx = {}
corpus = []
idx = 0
**for** i **in** range(len(df)):
ingredients = df['Ingredients'][i]
ingredients_lower = ingredients.lower()
tokens = ingredients_lower.split(', ')
corpus.append(tokens)
**for** ingredient **in** tokens:
**if** ingredient **not** **in** ingredient_idx:
ingredient_idx[ingredient] = idx
idx += 1*
一个一个的经过,我们先把所有的字母放低,把文字拆分。将所有标记化的单词放入语料库。然后准备另一个循环。这个是用来把单词放进我们事先编好的字典里的。它首先检查重复,如果一个单词还没有找到,就用索引把它放进字典。指数的值会一个一个增加。
下一步是制作一个文档术语矩阵(DTM)。在这里,每个化妆品对应一个文档,每个化学成分对应一个术语。这意味着我们可以把矩阵想象成一个“化妆品成分”矩阵。矩阵的大*应该如下图所示。
为了创建这个矩阵,我们将首先创建一个用零填充的空矩阵。矩阵的长度是数据中化妆品的总数。矩阵的宽度是成分的总数。初始化这个空矩阵后,我们将在下面的任务中填充它。
**# Get the number of items and tokens*
M = len(df) # The number of the items
N = len(ingredient_idx) # The number of the ingredients
*# Initialize a matrix of zeros*
A = np.zeros((M, N))*
在填充矩阵之前,让我们创建一个函数来计算每一行的令牌数(例如,一个成分列表)。我们的最终目标是用 1 或 0 填充矩阵:如果一种成分在化妆品中,值就是 1。如果不是,则保持为 0。这个函数的名字oh_encoder
,接下来将变得清晰。
**# Define the oh_encoder function*
**def** oh_encoder(tokens):
x = np.zeros(N)
**for** ingredient **in** tokens:
*# Get the index for each ingredient*
idx = ingredient_idx[ingredient]
*# Put 1 at the corresponding indices*
x[idx] = 1
**return** x*
现在我们将把oh_encoder()
函数应用到corpus
中的记号上,并在这个矩阵的每一行设置值。所以结果会告诉我们每样东西是由什么成分组成的。例如,如果一个化妆品项目包含水、烟酸、癸酸酯和sh-多肽-1* ,该项目的结果将如下。*
这就是我们所说的一次性编码。通过对物品中的每种成分进行编码,化妆品成分矩阵将用二进制值填充。
**# Make a document-term matrix*
i = 0
**for** tokens **in** corpus:
A[i, :] = oh_encoder(tokens)
i += 1*
用 t-SNE 降*
现有矩阵的*数是(190,2215),这意味着我们的数据中有 2215 个特征。为了形象化,我们应该把它缩*成二*。我们将使用 t-SNE 来降低数据的*度。
【T-分布式随机邻居嵌入(t-SNE) 是一种非线性降*技术,非常适合于在二*或三*的低*空间中嵌入用于可视化的高*数据。具体来说,这种技术可以降低数据的*度,同时保持实例之间的相似性。这使我们能够在坐标平面上绘图,这可以说是矢量化。我们数据中的所有这些装饰项目都将被矢量化为二*坐标,点之间的距离将表明项目之间的相似性。
**# Dimension reduction with t-SNE*
model = TSNE(n_components = 2, learning_rate = 200)
tsne_features = model.fit_transform(A)
*# Make X, Y columns*
df['X'] = tsne_features[:, 0]
df['Y'] = tsne_features[:, 1]*
我将结果值与价格、品牌名称和排名等其他列相结合。因此生成的数据帧如下所示。
用散景映射装饰项目
我们现在准备开始创建我们的情节。有了 t-SNE 值,我们可以在坐标平面上绘制所有的项目。这里最酷的部分是,它还会向我们显示每个项目的名称、品牌、价格和排名。让我们使用散景制作一个散点图,并添加一个悬停工具来显示这些信息。请注意,我们还不会显示该图,因为我们将对其进行更多的添加。
**# Make a source and a scatter plot*
source = ColumnDataSource(**df_all**)
plot = figure(x_axis_label = 'T-SNE 1',
y_axis_label = 'T-SNE 2',
width = 500, height = 400)
plot.circle(x = 'X', y = 'Y', source = source,
size = 10, color = '#FF7373', alpha = .8)plot.background_fill_color = "beige"
plot.background_fill_alpha = 0.2*# Add hover tool*
hover = HoverTool(tooltips = [
('Item', '@name'),
('brand', '@brand'),
('Price', '$ @price'),
('Rank', '@rank')])
plot.add_tools(hover)*
这里的数据df_all
是所有可能的选择组合的数据。到目前为止,我们已经完成了相同的过程。我只是将所有可能的选项合并到一个数据框中。因此,当我们创建一个回调函数并给它一个可选选项时,它将获取给定条件下的数据并更新绘图。
**# Define the callback*
**def** update(op1 = option_1[0], op2 = option_2[0])**:**
a_b = op1 + '_' + op2
new_data = {
'X' : df[df['Label'] == a_b]['X'],
'Y' : df[df['Label'] == a_b]['Y'],
'name' : df[df['Label'] == a_b]['name'],
'brand' : df[df['Label'] == a_b]['brand'],
'price' : df[df['Label'] == a_b]['price'],
'rank' : df[df['Label'] == a_b]['rank'],
}
source.data = new_data
push_notebook()*# interact the plot with callback*
interact(update, op1 = option_1, op2 = option_2)
show(plot, notebook_handle = True)*
终于,表演时间到了!让我们看看我们制作的地图是什么样子的。🙌🙌
图上的每个点对应于化妆品项目。那这些轴在这里是什么意思?根据原始数据,SNE 霸王龙图的坐标轴不容易解释。如上所述,t-SNE 是一种在低*空间绘制高*数据的可视化技术。因此,定量解释 t-SNE 图是不可取的。
相反,我们从这张地图上能得到的是点与点之间的距离(哪些项目距离近,哪些项目距离远)。两个项目之间的距离越近,它们的组成就越相似。因此,这使我们能够在没有任何化学背景的情况下比较这些项目。
比较具有余弦相似性的项目
最后,让我们比较每个点之间的相似性。 余弦相似度 是衡量两个非零向量之间相似度的一种方式。我们用余弦值代替两者之间的距离是什么原因?使用距离也是可以的,但是如果我们将向量之间的角度加入到距离概念中,这个值将代表比长度更多的信息。它甚至可以包含带有符号的方向数据。所以取余弦相似度基本上能提供更多信息。
*df_2 = df[df.Label == 'Moisturizer_Dry'].reset_index()
df_2['dist'] = 0.0*
比如有个产品叫泥炭奇迹复活霜。让我们比较一下它和其他干性皮肤保湿产品的性能。
**# Find the product named Peat Miracle Revital*
myItem = df_2[df_2.name.str.contains('Peat Miracle Revital')]*# getting the array for myItem*
X = myItem.SVD1.values
Y = myItem.SVD2.values
Point_1 = np.array([X, Y]).reshape(1, -1)*# cosine similarities with other items*
for i in range(len(df_2)):
P2 = np.array([df_2['SVD1'][i], df_2['SVD2'][i]]).reshape(-1, 1)
df_2.dist[i] = (P1 * P2).sum() / (np.sqrt(np.sum(P1))*np.sqrt(np.sum(P2)))*
如果我们将结果按升序排序,我们可以看到前 5 个最接近的化妆品,如下所示。
**# sorting by the similarity*
df_2 = df_2.sort_values('dist')
df_2[['name', 'dist']].head(5)*
这是与myItem
性质相似的前 5 名化妆品。也许我下次应该买娇兰。有了这份清单,我们可以为新产品做推荐。如果我们按降序排列,那么这个列表可以被用作‘对你来说最差的选择’。
结论
基于产品属性的推荐可以应用于任何领域。它也可以应用于一本书或葡萄酒推荐。我们可以根据产品特点制作各种地图。在坐标平面上可视化产品有助于我们以直观的方式理解项目之间的关系。
通过这种分析,我们可以进一步实现更精细的服务。它可以显示商品的图片和评论,或者提供订购页面的直接链接。我们也可以画一个不同的图,它的轴代表化学属性。例如,如果我们添加一些专业的化学知识,我们可以设置水合作用或毒性的坐标轴。在这种情况下,它将能够看到每个项目的毒性有多大。这些类型的应用将提供更高水平的产品分析。
资源
- 准备好学习更多关于推荐系统的知识了吗?解释四种不同推荐算法的最佳文章作者James Le:https://medium . com/@ James _ aka _ Yale/the-4-recommendation-engines-that-can-predict-your-movie-tastes-bbec 857 b 8223
- 准备好用散景构建您的精彩情节了吗?Datacamp 上的这个课程将是最好的起点:https://www . data camp . com/courses/interactive-data-visualization-with-bokeh
感谢您的阅读,希望您对这篇文章感兴趣。如果有需要改正的地方,请分享你的见解!如果您想鼓励一位有抱负的数据科学家,请点击👏 👏 👏!我总是乐于交谈,所以请随时在 LinkedIn 上留下评论或联系我。我会带着另一个令人兴奋的项目回来。在那之前,机器学习快乐!
用递归神经网络预测空气污染
原文:https://towardsdatascience.com/forecasting-air-pollution-with-recurrent-neural-networks-ffb095763a5c?source=collection_archive---------10-----------------------
Photo by Carolina Pimenta on Unsplash
在完成了公民科学项目之后,我想了解更多关于空气污染的知识,看看我是否可以用它来做一个数据科学项目。在欧洲环境署的网站上,你可以找到大量关于空气污染的数据和信息。
在这本笔记本中,我们将关注比利时的空气质量,更具体地说是二氧化硫(SO2) 造成的污染。数据可以通过https://www . EEA . Europa . eu/data-and-maps/data/aqe reporting-2/be下载。zip 文件包含不同空气污染物和聚集水平的单独文件。第一个数字代表污染物 ID,如词汇表中所述。这个笔记本用的文件是BE _ 1 _ 2013–2015 _ aggregated _ time series . CSV这是比利时的 SO2 污染情况,但是你也可以找到其他欧洲国家的类似数据。
在数据下载页面上可以找到 CSV 文件中字段的描述。更多关于空气污染物的背景信息可以在*基百科上找到。
项目设置
*# Importing packages*
**from** **pathlib** **import** Path
**import** **pandas** **as** **pd**
**import** **numpy** **as** **np**
**import** **pandas_profiling**
%**matplotlib** inline
**import** **matplotlib.pyplot** **as** **plt**
**import** **warnings**
warnings.simplefilter(action = 'ignore', category = **FutureWarning**)
**from** **sklearn.preprocessing** **import** MinMaxScaler
**from** **keras.preprocessing.sequence** **import** TimeseriesGenerator
**from** **keras.models** **import** Sequential
**from** **keras.layers** **import** Dense, LSTM, SimpleRNN
**from** **keras.optimizers** **import** RMSprop
**from** **keras.callbacks** **import** ModelCheckpoint, EarlyStopping
**from** **keras.models** **import** model_from_json
*# Setting the project directory*
project_dir = Path('/Users/bertcarremans/Data Science/Projecten/air_pollution_forecasting')
加载数据
date_vars = ['DatetimeBegin','DatetimeEnd']
agg_ts = pd.read_csv(project_dir / 'data/raw/BE_1_2013-2015_aggregated_timeseries.csv', sep='**\t**', parse_dates=date_vars, date_parser=pd.to_datetime)
meta = pd.read_csv(project_dir / 'data/raw/BE_2013-2015_metadata.csv', sep='**\t**')
print('aggregated timeseries shape:**{}**'.format(agg_ts.shape))
print('metadata shape:**{}**'.format(meta.shape))
数据探索
让我们使用 pandas_profiling 来检查数据。
pandas_profiling.ProfileReport(agg_ts)
为了不与图表混淆,我不会在本文中显示 pandas_profiling 的输出。但是你可以在我的 GitHub 回购里找到。
pandas_profiling 报告告诉我们:
- 有 6 个常量变量。我们可以把这些从数据集中去掉。
- 不存在缺失值,因此我们可能不需要应用插补。
- 有一些零,但这可能是完全正常的。另一方面,这些变量有一些极值,可能是空气污染的不正确记录。
- 共有 53 个空气质量站,可能与采样点相同。airqualitystationoicode 只是 AirQualityStation 的一个较短的代码,因此变量也可以被删除。
- AirQualityNetwork 有 3 个值(布鲁塞尔、佛兰德和瓦隆)。大多数测量来自佛兰德斯。
- DataAggregationProcess :大多数行包含作为一天测量(P1D)的 24 *时平均值聚集的数据。关于其他值的更多信息可以在这里找到。在这个项目中,我们将只考虑 P1D 值。
- DataCapture :平均周期内有效测量时间相对于总测量时间(时间覆盖)的比例,以百分比表示。几乎所有行都有大约 100%的有效测量时间。一些行的数据捕获率略低于 100%。
- DataCoverage :平均周期内聚合过程中包含的有效测量的比例,以百分比表示。在这个数据集中,我们至少有 75%。根据该变量的定义,低于 75%的值不应包括在空气质量评估中,这解释了为什么这些行不出现在数据集中。
- TimeCoverage :与数据覆盖率高度相关,将从数据中删除。
- 单位空气污染等级 : 423 行有一个单位计数。为了有一个一致的目标变量,我们将删除这种类型的单位的记录。
- 日期时间开始和日期时间结束:柱状图在这里没有提供足够的细节。这需要进一步分析。
日期时间开始和日期时间结束
pandas_profiling 中的直方图结合了每个 bin 的多个天数。让我们看看这些变量在日常水平上的表现。
每个日期多个汇总级别
- datetime begin:2013、2014、2015 年 1 月 1 日和 2013、2014 年 10 月 1 日的大量记录。
- datetime end:2014、2015、2016 年 1 月 1 日和 2014、2015 年 4 月 1 日的大量记录。
plt.figure(figsize=(20,6))
plt.plot(agg_ts.groupby('DatetimeBegin').count(), 'o', color='skyblue')
plt.title('Nb of measurements per DatetimeBegin')
plt.ylabel('number of measurements')
plt.xlabel('DatetimeBegin')
plt.show()
Number of rows per date
记录数量中的异常值与多个聚合级别(DataAggregationProcess)有关。这些日期的 DataAggregationProcess 中的值反映了 DatetimeBegin 和 DatetimeEnd 之间的时间段。例如,2013 年 1 月 1 日是一年测量期的开始日期,直到 2014 年 1 月 1 日。
由于我们只对每日汇总级别感兴趣,过滤掉其他汇总级别将解决这个问题。为此,我们也可以删除 DatetimeEnd。
每日汇总级别缺少时间步长
正如我们在下面看到的,并非所有采样点都有三年期间内所有日期时间 Begin 的数据。这是 DataCoverage 变量低于 75%的最有可能的日子。所以在这些日子里,我们没有足够的有效测量。在本笔记本的后面,我们将使用前几天的测量值来预测当天的污染情况。
为了获得类似大*的时间步长,我们需要为每个采样点插入缺失的 DatetimeBegin 行。我们将用有效数据插入第二天的测量数据。
其次,我们将删除太多丢失时间步长的采样点。这里我们将任意取 1.000 个时间步长作为所需时间步长的最*数目。
ser_avail_days = agg_ts.groupby('SamplingPoint').nunique()['DatetimeBegin']
plt.figure(figsize=(8,4))
plt.hist(ser_avail_days.sort_values(ascending=**False**))
plt.ylabel('Nb SamplingPoints')
plt.xlabel('Nb of Unique DatetimeBegin')
plt.title('Distribution of Samplingpoints by the Nb of available measurement days')
plt.show()
Distribution of SamplingPoints by the number of available measurement days
数据准备
数据清理
基于数据探索,我们将执行以下操作来清理数据:
- 仅保留 P1D 的 DataAggregationProcess 记录
- 正在删除计数为 UnitOfAirPollutionLevel 的记录
- 删除一元变量和其他冗余变量
- 移除少于 1000 个测量日的采样点
df = agg_ts.loc[agg_ts.DataAggregationProcess=='P1D', :]
df = df.loc[df.UnitOfAirPollutionLevel!='count', :]
df = df.loc[df.SamplingPoint.isin(ser_avail_days[ser_avail_days.values >= 1000].index), :]
vars_to_drop = ['AirPollutant','AirPollutantCode','Countrycode','Namespace','TimeCoverage','Validity','Verification','AirQualityStation',
'AirQualityStationEoICode','DataAggregationProcess','UnitOfAirPollutionLevel', 'DatetimeEnd', 'AirQualityNetwork',
'DataCapture', 'DataCoverage']
df.drop(columns=vars_to_drop, axis='columns', inplace=**True**)
为缺失的时间步长插入行
对于每个采样点,我们将首先插入(空)没有 DatetimeBegin 的行。这可以通过在最*和最大 DatetimeBegin 之间的范围内创建包含所有采样点的完整多索引来实现。然后, reindex 将插入丢失的行,但是对于列使用 NaN。
其次,我们使用 bfill 并指定用有效数据的下一行的值来估算缺失值。bfill 方法应用于 groupby 对象,以将回填限制在每个采样点的行内。这样,我们就不会使用另一个采样点的值来填充缺失的值。
测试该操作是否正确工作的样本点是日期为2013–01–29的 SPO-BETR223_00001_100 。
dates = list(pd.period_range(min(df.DatetimeBegin), max(df.DatetimeBegin), freq='D').values)
samplingpoints = list(df.SamplingPoint.unique())
new_idx = []
**for** sp **in** samplingpoints:
**for** d **in** dates:
new_idx.append((sp, np.datetime64(d)))
df.set_index(keys=['SamplingPoint', 'DatetimeBegin'], inplace=**True**)
df.sort_index(inplace=**True**)
df = df.reindex(new_idx)
*#print(df.loc['SPO-BETR223_00001_100','2013-01-29']) # should contain NaN for the columns*
df['AirPollutionLevel'] = df.groupby(level=0).AirPollutionLevel.bfill().fillna(0)
*#print(df.loc['SPO-BETR223_00001_100','2013-01-29']) # NaN are replaced by values of 2013-01-30*
print('**{}** missing values'.format(df.isnull().sum().sum()))
处理多个时间序列
好了,现在我们有了一个干净的数据集,不包含任何丢失的值。使这个数据集特别的一个方面是我们有多个采样点的数据。所以我们有多个时间序列。
一种处理方法是为采样点创建虚拟变量,并使用所有记录来训练模型。另一种方法是为每个采样点建立一个单独的模型。在本笔记本中,我们将采用后者。但是,我们将限制笔记本电脑只能在一个采样点上这样做。但是同样的逻辑可以应用于每个采样点。
df = df.loc['SPO-BETR223_00001_100',:]
分割训练、测试和验证集
为了评估模型的性能,我们划分了一个测试集。在训练阶段将不使用该测试集。
- 列车组:截至 2014 年 7 月的数据
- 验证集:2014 年 7 月至 2015 年 1 月之间的 6 个月
- 测试集:2015 年的数据
train = df.query('DatetimeBegin < "2014-07-01"')
valid = df.query('DatetimeBegin >= "2014-07-01" and DatetimeBegin < "2015-01-01"')
test = df.query('DatetimeBegin >= "2015-01-01"')
缩放比例
*# Save column names and indices to use when storing as csv*
cols = train.columns
train_idx = train.index
valid_idx = valid.index
test_idx = test.index
*# normalize the dataset*
scaler = MinMaxScaler(feature_range=(0, 1))
train = scaler.fit_transform(train)
valid = scaler.transform(valid)
test = scaler.transform(test)
保存已处理的数据集
这样,我们就不需要在每次重新运行笔记本时重复预处理。
train = pd.DataFrame(train, columns=cols, index=train_idx)
valid = pd.DataFrame(valid, columns=cols, index=valid_idx)
test = pd.DataFrame(test, columns=cols, index=test_idx)
train.to_csv('../data/processed/train.csv')
valid.to_csv('../data/processed/valid.csv')
test.to_csv('../data/processed/test.csv')
建模
首先,我们读入经过处理的数据集。其次,我们创建一个函数来绘制我们将构建的不同模型的训练和验证损失。
train = pd.read_csv('../data/processed/train.csv', header=0, index_col=0).values.astype('float32')
valid = pd.read_csv('../data/processed/valid.csv', header=0, index_col=0).values.astype('float32')
test = pd.read_csv('../data/processed/test.csv', header=0, index_col=0).values.astype('float32')
**def** plot_loss(history, title):
plt.figure(figsize=(10,6))
plt.plot(history.history['loss'], label='Train')
plt.plot(history.history['val_loss'], label='Validation')
plt.title(title)
plt.xlabel('Nb Epochs')
plt.ylabel('Loss')
plt.legend()
plt.show()
val_loss = history.history['val_loss']
min_idx = np.argmin(val_loss)
min_val_loss = val_loss[min_idx]
print('Minimum validation loss of **{}** reached at epoch **{}**'.format(min_val_loss, min_idx))
使用时间序列生成器准备数据
Keras 的 TimeseriesGenerator 帮助我们以正确的格式构建数据用于建模。
- 长度:生成序列中的时间步长数。这里我们想回顾任意数量的 n_lag 时间步。实际上,n_lag 可能取决于如何使用预测。假设比利时政府可以采取一些措施来减少采样点周围的 SO2 污染(例如在一定时间内禁止柴油车进入某个城市)。假设政府在纠正措施生效前需要 14 天。那么将 n_lag 设置为 14 是有意义的。
- sampling_rate: 生成序列中连续时间步之间的时间步数。我们希望保留所有的时间步长,因此我们将其保留为默认值 1。
- 步距:该参数影响生成的序列重叠的程度。由于我们没有太多的数据,我们将其保留为默认值 1。这意味着相继生成的两个序列与除一个时间步长之外的所有时间步长重叠。
- batch_size: 每批生成的序列数
n_lag = 14
train_data_gen = TimeseriesGenerator(train, train, length=n_lag, sampling_rate=1, stride=1, batch_size = 5)
valid_data_gen = TimeseriesGenerator(train, train, length=n_lag, sampling_rate=1, stride=1, batch_size = 1)
test_data_gen = TimeseriesGenerator(test, test, length=n_lag, sampling_rate=1, stride=1, batch_size = 1)
递归神经网络
传统的神经网络没有记忆。因此,在处理当前输入时,它们不会考虑以前的输入。在时序数据集中,如时间序列,先前时间步骤的信息通常与当前步骤的预测相关。因此需要保持关于先前时间步的状态和状态。
在我们的例子中,时间 t 的空气污染可能受到先前时间点的空气污染的影响。所以我们需要考虑到这一点。递归神经网络或 rnn 有一个内部循环,通过它它们保持先前时间步长的状态。然后,该状态用于当前时间步长中的预测。当一个新的序列被处理时,该状态被复位。关于 RNNs 的图解指南,你绝对应该阅读 Michael Nguyen 的文章。
在我们的例子中,我们使用 Keras 包的一个 SimpleRNN 。我们还指定了一个提前停止回调,当有 10 个时期没有任何验证损失的改善时停止训练。模型检查点允许我们保存最佳模型的权重。模型架构仍然需要单独保存。
simple_rnn = Sequential()
simple_rnn.add(SimpleRNN(4, input_shape=(n_lag, 1)))
simple_rnn.add(Dense(1))
simple_rnn.compile(loss='mae', optimizer=RMSprop())
checkpointer = ModelCheckpoint(filepath='../model/simple_rnn_weights.hdf5'
, verbose=0
, save_best_only=**True**)
earlystopper = EarlyStopping(monitor='val_loss'
, patience=10
, verbose=0)
**with** open("../model/simple_rnn.json", "w") **as** m:
m.write(simple_rnn.to_json())
simple_rnn_history = simple_rnn.fit_generator(train_data_gen
, epochs=100
, validation_data=valid_data_gen
, verbose=0
, callbacks=[checkpointer, earlystopper])
plot_loss(simple_rnn_history, 'SimpleRNN - Train & Validation Loss')
Training and validation loss for a SimpleRNN
长短期记忆网络
RNN 人记性很差。很难记住许多时间点以前的信息。当序列非常长时会出现这种情况。其实是因为消失渐变问题。梯度是更新神经网络权重的值。当你的 RNN 中有很多时间步长时,第一层的梯度会变得非常*。结果,第一层的权重的更新可以忽略。这意味着 RNN 不能学习早期地层中的东西。
因此,我们需要一种方法将第一层的信息传递给后面的层。LSTMs 更适合考虑长期依赖性。Michael Nguyen 写了一篇关于 LSTMs 的视觉描述的优秀文章。
简单 LSTM 模型
simple_lstm = Sequential()
simple_lstm.add(LSTM(4, input_shape=(n_lag, 1)))
simple_lstm.add(Dense(1))
simple_lstm.compile(loss='mae', optimizer=RMSprop())
checkpointer = ModelCheckpoint(filepath='../model/simple_lstm_weights.hdf5'
, verbose=0
, save_best_only=**True**)
earlystopper = EarlyStopping(monitor='val_loss'
, patience=10
, verbose=0)
**with** open("../model/simple_lstm.json", "w") **as** m:
m.write(simple_lstm.to_json())
simple_lstm_history = simple_lstm.fit_generator(train_data_gen
, epochs=100
, validation_data=valid_data_gen
, verbose=0
, callbacks=[checkpointer, earlystopper])
plot_loss(simple_lstm_history, 'Simple LSTM - Train & Validation Loss')
Training and validation loss for a simple LSTM
堆叠 LSTM 模型
在这个模型中,我们将堆叠多个 LSTM 层。这样,模型将随着时间的推移学习输入数据的其他抽象。换句话说,表示不同时间尺度的输入数据。
在 Keras 中要做到这一点,我们需要在另一个 LSTM 层之前的 LSTM 层中指定参数 return_sequences 。
stacked_lstm = Sequential()
stacked_lstm.add(LSTM(16, input_shape=(n_lag, 1), return_sequences=**True**))
stacked_lstm.add(LSTM(8, return_sequences=**True**))
stacked_lstm.add(LSTM(4))
stacked_lstm.add(Dense(1))
stacked_lstm.compile(loss='mae', optimizer=RMSprop())
checkpointer = ModelCheckpoint(filepath='../model/stacked_lstm_weights.hdf5'
, verbose=0
, save_best_only=**True**)
earlystopper = EarlyStopping(monitor='val_loss'
, patience=10
, verbose=0)
**with** open("../model/stacked_lstm.json", "w") **as** m:
m.write(stacked_lstm.to_json())
stacked_lstm_history = stacked_lstm.fit_generator(train_data_gen
, epochs=100
, validation_data=valid_data_gen
, verbose=0
, callbacks=[checkpointer, earlystopper])
plot_loss(stacked_lstm_history, 'Stacked LSTM - Train & Validation Loss')
Training and validation loss for a stacked LSTM
评估绩效
基于最*验证损失,SimpleRNN 似乎优于 LSTM 模型,尽管度量标准彼此接近。使用 evaluate_generator 方法,我们可以对测试数据(生成器)上的模型进行评估。这会给我们带来测试数据上的损失。我们将首先从 JSON 文件中加载模型架构和最佳模型的权重。
**def** eval_best_model(model):
*# Load model architecture from JSON*
model_architecture = open('../model/'+model+'.json', 'r')
best_model = model_from_json(model_architecture.read())
model_architecture.close()
*# Load best model's weights*
best_model.load_weights('../model/'+model+'_weights.hdf5')
*# Compile the best model*
best_model.compile(loss='mae', optimizer=RMSprop())
*# Evaluate on test data*
perf_best_model = best_model.evaluate_generator(test_data_gen)
print('Loss on test data for **{}** : **{}**'.format(model, perf_best_model))
eval_best_model('simple_rnn')
eval_best_model('simple_lstm')
eval_best_model('stacked_lstm')
- simple_rnn 的测试数据的损失:0 . 54686 . 38686868661
- simple_lstm 的测试数据损失:0 . 54686 . 68686868661
- stacked_lstm 的测试数据损失:0 . 46866 . 38886888661
结论
在这个故事中,我们为 LSTM 使用了一个递归神经网络和两种不同的架构。最佳性能来自于由几个隐藏层组成的堆叠 LSTM。
肯定有许多事情值得进一步研究,以提高模型性能。
- 使用每*时的数据(EEA 网站上的另一个 CSV 文件),尝试除每日数据之外的其他采样策略。
- 使用关于其他污染物的数据作为特征来预测 SO2 污染。也许其他污染物与二氧化硫污染有关。
- 基于日期构建其他特征。在驱动数据的幂律预测竞赛的获胜者之一的 PDF 中可以找到一篇很好的文章
通过做这个项目,我学到了很多递归神经网络。我希望你喜欢它。欢迎留下任何评论!
在 Python 中使用 ARIMA 预测汇率
原文:https://towardsdatascience.com/forecasting-exchange-rates-using-arima-in-python-f032f313fc56?source=collection_archive---------4-----------------------
ARIMA 如何预测汇率时间序列数据
几乎所有部门都使用时间序列数据来预测未来的时间点。预测未来可以帮助分析师和管理层做出更好的决策,以实现回报最大化和风险最*化。我将在本文中演示我们如何预测汇率。如果你是金融新手,想了解什么是汇率,那么请阅读我的文章“学习金融的最佳途径?了解市场数据”。它提供了市场数据的基本概述。汇率取决于一系列因素,如供求关系、政府政策、国家增长率等。想了解更多关于影响汇率的经济指标的信息,请看看我的文章“评估和比较国家需要知道的一切”。
预测汇率
最近,引入了许多技术进步,可以快速、高效和准确地预测未来时间点。其中之一是在 Python 中引入统计和机器学习(ML)模型。在我的文章“ python 从头开始”中,我提供了 Python 基础知识的概述。
在本文中,我将使用 ARIMA 模型来预测汇率。
在我的博客“我如何预测时间序列?”和“理解自回归移动平均模型— ARIMA ”,我概述了时间序列的概念和 ARIMA 的工作方式。在这篇博客中,我将结合 Jupyter notebook 使用 python 编程语言来解释如何在 Python 中使用 ARIMA 来预测汇率。
请阅读 fintech 解释 d isclaimer 。
使用 Pandas 加载汇率数据
Pandas 是最流行的 Python 库之一。它建立在 Numpy python 库的基础上,提供了一系列功能,包括:
对象创建、数据分析和数据加载。它有内置的统计功能,可以合并/加入/联合多个集合。它还可以帮助我们分组、旋转和绘制数据。此外,Pandas 是一个非常有效的库,可以从 csv、HDF5 和 excel 加载数据。最后,可以对数据应用一系列样式和格式。
我们将利用*猫来:
1.从 csv(逗号分隔)文件中加载时间序列汇率
2.查看前 10 条记录
3.查看数据的基本统计信息
从 csv 文件加载时间序列汇率
我准备了一份文件,其中包括自 1998 年 12 月 31 日以来英镑/美元的每日收盘汇率。文件存储在这里。该文件包含两列数据:数据和英镑/美元收盘
确保文件保存在与 python 笔记本相同的位置。
键入以下行以加载文件并查看前 10 条记录:
要导入一个库,做:将
导入为 >
注意:GetData(fileName)是一个接受文件名作为参数的方法。
按 Alt + Enter 查看数据的基本统计信息
下图通过调用 GetData(fileName)方法显示了 csv 文件的前 10 条记录:
让我们找出有用的统计数据,并绘制出汇率图
键入:exchangeRatesSeries.describe()以查看如下所示的统计信息:
describe()显示了许多有用的指标,包括:
count —记录数, mean —期望值, std —告诉我们平均值周围数据的离差的标准偏差, min —集合中的最*值, max —集合中的最大值以及一个百分比范围。百分位数可以帮助我们理解数据的概率分布。
绘制加载的数据
可以添加 Html 样式来改变 Python 的感觉和外观。我将绘图颜色设置为绿色:
#绘制时间序列数据
exchange rates series . plot(color = ' green ')
注意,传递 color='green '会创建一个绿色线图。
键入:exchangeRatesSeries.hist()以显示 historgram。
直方图可以帮助我们理解数据的分布,反过来帮助我们预测变量:
matplotlib 可以帮助我们绘制数据。我们也可以通过编写以下代码来导入 matplotlib:
从 matplotlib 导入 pyplot
然后写出时间序列:
py plot . plot(exchange rate series)
带 StatsModels 套装的 ARIMA
StatsModels 是一个功能强大的 python 库,包含丰富的统计模型。StatsModels 库包含许多可用于预测和预测数据的模型。这个库也包含许多诊断工具。我们将使用 StatsModels 软件包中的 ARIMA 模型来预测汇率。
ARIMA 简介
ARIMA 模型有 3 个参数:
P —模型的自回归特征
d——差分顺序
Q —模型的移动平均特征
导入 statsmodels 后,使用 tsa.arima_model 并给它一个别名 arima:
从 statsmodels.tsa.arima_model 导入 ARIMA
有关参数的详细信息,请访问:http://www . stats models . org/dev/generated/stats models . TSA . ARIMA _ model。ARIMA.html
ARIMA 参数可以改变,以获得不同的预测行为。我已经定义了一个用户定义的方法,它接受三个参数的训练集和值。该函数首先创建 ARIMA 模型。然后对模型执行 fit()和 forecast()。Forecast()返回预测值。
将这几行复制并粘贴到您的笔记本上:
ARIMA(……)创造了 ARIMA 模式。Fits()通过卡尔曼滤波器以最大似然法拟合 ARIMA(p,d,q)模型,Forecast()返回基于拟合的 ARIMA 模型的估计值。
我们可以认为 Fit()是一个生成误差最*的最佳拟合曲线的过程。关于这个话题的更多内容,请见我的博客:我的预测模型——回归分析有多好?
p,q,d 参数可以调整以获得更好的结果。
这是一个我们如何传递时间序列数据并使用 ARIMA 根据实际观察数据预测值的示例:
通过运行该脚本,我们可以看到预测值:
我们传入随机值作为训练集。然后 ARIMA 模型进行拟合,预测下一个值为 15.219305
我们还可以将外生变量、日期、时间序列的频率等传递给 ARIMA 模型。
最后,让我们使用 Python 中的 ARIMA 来预测汇率
既然我们已经了解了如何使用 python Pandas 来加载 csv 数据,以及如何使用 StatsModels 来预测价值,那么让我们结合本博客中获得的所有知识来预测我们的样本汇率。
复制并粘贴这段代码。它是我们在这个博客中学到的所有概念的结合。
按 Alt+Enter。Python 将开始用实际数据循环调用 ARIMA 模型。70%的数据用于训练模型,其余 30%用于测试准确性。每次产生新的预测值。
实际值和预测值将打印在笔记本上。
最后,实际值与预测值将绘制在图表上
查看均方误差
我还导入了一个额外的库 sklearn ,我将在未来的博客中使用它。
复制粘贴这一行:
“从 sklearn.metrics 导入 mean_squared_error”导入库。
最后打印均方差:
均方误差计算实际数据和预测数据之间差异的平均值,并告诉您您的模型有多好。更多信息可以在我的博客里找到: 我的预测模型—回归分析 有多好
通过运行下面的代码,我们可以查看实际值、预测值以及折线图和总均方误差:
如您所见,我们打印了实际值和预测值。此外,我们用红色绘制了 MSE 为 1.551 的预测值。
完整的笔记本,请访问这里。
进一步的改进
预测汇率可以通过以下方式改进:
- 不断更新模型参数
- 通过输入影响汇率及其相关性的其他因素
- 模型参数也可以通过机器学习和优化技术来更新。
- 最后,可以强调因素及其相关性,以确保预测的汇率考虑到极端情况。
最终注释
本文演示了如何使用 python 通过 ARIMA 模型预测汇率。金融市场可以向任何方向移动,这使得准确预测汇率变得非常困难,如果不是不可能的话。话虽如此,通过 ARIMA 预测汇率的唯一目的是帮助我们做出精心计算的决定,以实现回报最大化和风险最*化。预测汇率取决于 ARIMA 模型的假设,该模型基于自回归、综合和移动平均概念。
ARIMA 是一个简单而强大的模型。它假设历史价值决定现在的行为。它还假设数据不包含异常,是稳定的,并且模型参数以及误差项是恒定的。
尽管 ARIMA 没有将市场数据中的压力、经济和政治条件或所有风险因素的相关性作为预测汇率的输入,但上面展示的简单示例可用于预测正常情况下稳定货币的运动,在正常情况下,过去的行为决定了现在和价值。
如果您有任何反馈,请告诉我。
在构建预测模型之前,您应该了解的预测基础知识
原文:https://towardsdatascience.com/forecasting-fundamentals-you-should-know-before-building-predictive-models-299a18c2093b?source=collection_archive---------10-----------------------
预测,还是不预测,这是一个问题。
人类文明史与我们尝试预测方法的历史交织在一起。当我们的祖先观察天空来预测天气时,数据科学家开发并训练机器学习模型来预测销售、风险、事件、趋势等。准确的预测是一项重要的组织能力,做得好的企业将会有很大的生存优势。
应该预测什么
在预测项目的早期阶段,需要决定应该预测什么,什么时候可以准确预测,以及什么时候预测不会比扔硬币好。
例如,如果需要对房地产市场进行预测,则有必要询问是否需要对以下方面进行预测:
- 任何类型的财产,或独立/半独立/联排别墅/公寓分开?
- 是按地区分组的房产平均销售价格,还是仅针对总销售额?
- 周数据,月数据还是年数据?
需要注意的关键是并不是所有的预测都比掷硬币好。事件或价值的可预测性取决于几个因素,包括:
- 我们是否发现并理解了影响结果的大部分因素?
- 这些因素有“大”数据吗?
- 预测是否会影响我们试图预测的事情?
例如,24 *时天气预报可以非常准确,因为这三个条件通常都满足。另一方面,很难预测下一滴雨滴落入你眼中的概率,明天的并发汇率会上升或下降或下周的比特币价格。
时间跨度和数据可用性方面的预测类型
是否需要提前几分钟、6 个月或 10 年的预测?就时间跨度而言,有 3 种类型的预测:
- 短期预测:一至三个月的正常范围
- 中期预测:时间周期一般为一年
- 长期预测:预测超过两年的结果
在大多数预测情况下,随着事件的临近,与我们预测的事物相关的不确定性会减少。换句话说,我们预测的越近,我们就越准确。
根据数据可用性,预测可以分为两种类型。
- 定性预测:如果没有可用数据,或者可用数据与预测无关。
- 定量预测(时间序列预测):如果过去的数字信息可用;过去的模式将延续到未来。
用于定量预测(时间序列预测)的数据通常以固定的时间间隔观察,例如每*时、每天、每周、每月、每季度、每年。目标是估计历史观察序列将如何延续到未来。
预测方法
方法的选择取决于可用的数据和事件的可预测性或要预测的价值。
由于缺乏历史数据,判断性预测是定性预测的唯一选择。例如,预测新政策、新产品或新竞争对手的影响。
最简单的时间序列预测方法仅使用待预测变量的历史值,并排除可能影响其行为的因素,如竞争对手的活动、环境或经济条件的变化等。下图显示了使用过去 10 年的销售数据对 2017 年的房屋销售预测。
house sales prediction for 2017 with past 10-year sales data
在本文中,我们将讨论什么是预测、预测类型和预测方法。预测显然是一项具有挑战性的活动。在以后的文章中,我将探讨一些常用的预测方法,包括指数平滑法、ARIMA 模型、动态回归模型、LSTM 等。
“你看到这些伟大的建筑了吗?没有一块石头留在另一块石头上,不被拆毁。”( 马克 13:1–2)
让预测在未来到来之前向你展示它。
预测欧元区的 GDP
原文:https://towardsdatascience.com/forecasting-gdp-in-the-eurozone-54778f79912e?source=collection_archive---------6-----------------------
使用欧盟统计局数据和 ARIMA 模型预测欧元区季度 GDP(国内生产总值)
这一分析使用了欧盟统计局的公共数据集来预测所有欧元区国家未来的季度 GDP 总量。欧盟统计局是位于卢森堡的欧盟统计局。它的任务是为欧洲提供高质量的统计数据。欧盟统计局提供了一系列重要而有趣的数据,政府、企业、教育部门、记者和公众可以在工作和日常生活中使用这些数据。特别是,使用了欧元区(欧盟 19 国)季度 GDP(国内生产总值)数据集。欧元区由 19 个国家组成:奥地利、比利时、塞浦路斯、爱沙*亚、芬兰、法国、德国、希腊、爱尔兰、意大利、拉脱*亚、立陶宛、卢森堡、马耳他、荷兰、葡萄牙、斯洛伐克、斯洛文*亚和西班牙。
国内生产总值(GDP)是在一段时间(季度或年度)内生产的所有最终商品和服务的市场价值的货币度量。它通常用于确定一个国家或地区的经济表现。
用于获取数据集的欧盟统计局软件包和用于 ARIMA 建模的预测软件包。
关于 ETL 步骤的更多细节可以在实际代码中找到,在文章结尾的链接中。
探索性分析
在探索性分析期间,我们试图发现时间序列中的模式,例如:
- 趋势时间序列中涉及长期增减的模式
- 季节性由于日历(如季度、月份、工作日)
- 周期性存在一种模式,其中数据呈现非固定周期(持续时间通常至少为两年)的上升和下降
下面是 1995 年以来欧元区国家季度 GDP 的时间序列图。
上面的时间序列图中有一些输出:
-我们可以说总体趋势是积极的
-趋势中没有明显的增加/减少的可变性
-看起来有一些季节性,但需要进一步调查
-没有周期性
-在 2008-2009 年左右,GDP 增长出现了明显的中断
下面用一个季节性图来研究季节性。季节图类似于时间图,只是数据是根据观察数据的单个“季节”绘制的。
这增强了我们对时间序列中季节性的信心。似乎每年的第四季度总是最高的,而第一季度是最低的。第二次和第三次差不多。
滞后图将帮助我们了解时间序列中是否存在自相关。查看时间序列数据的另一种方法是将每个观察值与之前某个时间发生的另一个观察值进行对比。例如,您可以根据 yt1 绘制 yt。这被称为滞后图,因为你是根据时间序列本身的滞后来绘制的。基本上,它是时间序列和时间序列滞后值之间的散点图。
滞后 4 (1 年)有很强的季节性,因为所有季度线图遵循几乎相同的路径。
下面是自相关函数图。与滞后图相关的相关性形成了所谓的自相关函数(ACF)。超出置信区间(蓝线)的香料表明具有特定滞后的自相关具有统计显著性(不同于零)
看起来在所有滞后上都有显著的自相关,这表明了时间序列中的趋势和/或季节性。
我们还可以使用 Ljung-Box 检验来检验时间序列是否是白噪声。白噪声是一个纯粹随机的时间序列。下面是第四阶段的测试。
## Box-Ljung test
##
## data: gdp_ts
## X-squared = 319.62, df = 4, p-value < 2.2e-16
Ljung-Box 检验 p 值很*< 0.01, so there is strong evidence that the time series is not white noise and has seasonality and/or trend.
Modelling
ARIMA (Auto-regressive integrated moving average) models provide one of the main approaches to time series forecasting. It is the most widely-used approach to time series forecasting, and aim to describe the autocorrelations in the data.
The final fitted model was produced by the auto.arima() function of the forecast library. It rapidly estimates a series of model and return the best, according to either AIC, AICc or BIC value. After fitting the ARIMA model, it is essential to check that the residuals are well-behaved (i.e., no outlines or patterns) and resemble white noise. Below there are some residual plots for the fitted ARIMA model.
## Ljung-Box test
##
## data: Residuals from ARIMA(2,1,1)(0,1,1)[4]
## Q* = 6.1916, df = 4, p-value = 0.1853
##
## Model df: 4\. Total lags used: 8
We can say that the model is fairly good, since the residuals are closely normally distributed, have no real pattern and autocorrelations are not significant.
最终模型是一个季节性 ARIMA(2,1,1)(0,1,1)【4】。季节性差异和第一次差异都被使用,由模型每个部分的中间槽表示。此外,选择了一个滞后误差和一个季节性滞后误差,由模型每个部分的最后一个槽表示。使用了两个自回归项,由模型中的第一个槽表示。没有使用季节性自回归术语。
最后,对预测模型的准确性进行了检验。下面是对模型准确性的测试,使用 2017 年所有四个季度和 2018 年第一季度作为测试集。
## ME RMSE MAE MPE MAPE MASE
## Training set -1763.393 18524.64 13332.4 -0.08197817 0.6440916 0.1939318
## Test set 47152.498 49475.29 47152.5 1.68398118 1.6839812 0.6858757
## ACF1 Theil's U
## Training set 0.06526246 NA
## Test set 0.09563655 0.6768184
测试集的 MAPE(平均绝对百分比误差)为 1.68,因此我们可以得出模型的预测精度在 98.3 % 左右。
下面是欧元区国家 2018-19 年季度 GDP 预测的时间序列图。
- 看起来国内生产总值将在未来几年保持增长。特别是对未来几个季度的预测是:
Quarter Forecast Lo 80 Hi 80 Lo 95 Hi 95
2018 Q2 2887406 2853687 2921524 2835996 2939748
2018 Q3 2892970 2841213 2945670 2814191 2973955
2018 Q4 2990005 2917818 3063978 2880312 3103876
2019 Q1 2888631 2805996 2973700 2763213 3019742
2019 Q2 2973066 2870171 3079650 2817151 3137610
2019 Q3 2976688 2859234 3098966 2798945 3165717
2019 Q4 3076720 2939974 3219827 2870063 3298258
- 到 2019 年底,国内生产总值很有可能在今年的一个或多个季度突破三万亿€的关口
使用其他预测方法开发的模型更多,如指数平滑(具有趋势和季节性 Holt-Winters 的指数平滑方法)& 指数三次平滑,但 ARIMA 模型表现更好。
全 R 码
用蒙特卡罗模拟预测软件项目的完成日期
原文:https://towardsdatascience.com/forecasting-software-projects-completion-date-through-monte-carlo-simulation-c1baa5bcf976?source=collection_archive---------6-----------------------
Photo by Jonathan Petersson on Unsplash
如今,我们正在使用一种比确定性方法更具概率性的方法来管理我们的过程。这意味着我们使用不同的统计方法来预测未来,而不是盲目的估计。但是等等…不可预测性难道不是让我们从瀑布式转变为敏捷的主要原因之一吗?
是的,不确定性是软件开发所固有的。例如,一个人不可能在一个项目的开始就预测一个系统的所有特性。
但是,如果我们能预测接下来几周的行为会怎样呢?
这就是我们试图通过收集指标并对其进行蒙特卡洛模拟来实现的目标。
要了解我们如何收集指标,我建议您阅读以下帖子:
- 我们为什么喜欢度量标准?学习提前期
- 我们为什么喜欢度量标准?吞吐量和燃耗图表
- 我们为什么喜欢指标?累积流程图
大多数人不使用任何度量来管理他们的项目。你可以想象有多少人使用复杂的统计模型来预测项目的完成。然而,在你当前的项目中拥有这些知识将会帮助你更快更好的交付。
在本帖中,你将看到我们如何使用蒙特卡罗模拟从一个简单的预测方法到一个更加精确和稳健的方法。此外,我们将以简单明了的方式解释蒙特卡罗模拟是如何工作的,然后在这个简单的例子和我们的现实世界方法之间进行类比。知道你的项目什么时候可能结束可以帮助你管理项目的预算,给利益相关者更好的反馈,给你信心,你确实在控制你的项目。
为什么不是其他方法?
长期以来,我们一直在尝试其他的预测方法,但它们都有一些缺点。在这里,我们列出了其中的一些,以及我们如何和为什么选择使用蒙特卡洛。
平均吞吐量
你们中的一些人可能已经想到了一个简单的方法,我们将使用平均吞吐量来预测项目的结束。然而,正如你在这篇博文中看到的 指标的力量:不要用平均值来预测最后期限 ,那将是一个极其幼稚的方法,而且它不起作用。
线性回归方法
作为第一种方法,我们使用线性回归,基于我们累积的吞吐量,来预测项目何时结束:
但是,我们发现了两个不同的问题,我们在进行分析时没有考虑到:
- 我们必须保持待办事项列表中的项目数量不变,以便进行预测,这非常有偏差。
- 经过一些分析后,我们发现吞吐量和交付时间都不符合正态分布,因此计算线性回归是没有意义的(参见 以不同的方式看待交付时间 和 线性回归 的假设)。
手动设置方法
首先,我们专注于避免第二个问题,我们开始使用一个更节俭的模型,它使用了我们知道有些倾斜的方法,但是我们可以更好地控制它们。
我们手动添加了吞吐量性能,这将导致每个不同的预测在某个日期到达积压。这种预测方法来自对我们吞吐量历史的百分位数的研究。
我们有了更好的结果,因为我们可以手动更改预测,因此可以根据项目的当前状态进行调整。但是第一个问题,事实上我们没有考虑到积压订单的变化,这让我们更进一步,尝试蒙特卡罗模拟。
蒙特 卡罗模拟
*基百科将蒙特卡洛方法定义为
蒙特卡罗方法各不相同,但往往遵循一种特定的模式:
定义可能输入的域。
根据域内的概率分布随机生成输入。
对输入执行确定性计算。
汇总结果。
乍一看,这似乎很难或很复杂,但实际上比看起来要简单得多。你可以把它看作是预测的强力方法。我们将给出一个简单的例子,然后展示我们在现实世界中的表现。Larry Maccherone 做了一个很好的模拟,可以更好地解释这一点。
骰子游戏
假设你在玩一个骰子游戏,目标是用最少的掷数得到 12 点。这里最好的玩法是连续两次掷骰子,你都得到 6,最差的是 12 次掷骰子得到 1。我们要计算的是 N 次运行后结束博弈的概率。
考虑到每一次掷骰子有 6 种可能的结果,即骰子的 6 个面,那么在 1 次掷骰子中完成游戏的概率是多少?
零。因为如果骰子只到 6 点,你就不能到 12 点。
第二卷呢?
就是连续得到两个 6 的概率,这是基本统计:
第三卷呢?
现在你可以用很多方法达到 12 点,其中一些是:(3,3,6),(3,4,5),(3,5,4),(3,4,6),(5,5,2),(4,4,4)等等。这个计算背后的统计数据并不简单,对吗?这就是蒙特卡罗模拟派上用场的时候。
蒙特卡洛模拟成千上万次掷骰子,然后分析结果。例如,要知道在第三轮完成游戏的概率,它将掷骰子三次,将点数相加并存储结果。之后,它将重复这些步骤 5000 次,并总结每一个点数总和得到的掷数:
现在它所做的是将所有产生大于 12 的和的事件相加,然后除以事件总数。在这种情况下:
同样的方式,我们做了第三轮,我们可以做第四,第五,等等。
现实世界
现实世界的解决方案非常类似于掷骰子的例子。唯一的区别是,我们也改变了目标(游戏场景中的 12 分),以考虑待办事项中的变化。
所以现在每一轮的可能结果(骰子的两面)就是我们的吞吐量历史。同样,我们是吞吐量的“滚动骰子”,我们需要滚动积压的骰子,以便给它增长的机会。在这种情况下,可能的结果将是积压的增长率(BGR)。
让我们慢慢开始。假设我们的项目历史是这样的:
因此,我们每一轮的吞吐量可能是集合{2,3,0,2,5,0,1,3,3},积压可能是{0,2,1,1,2,1,0,2,0}。我们不排除重复的数字,因为有了它们,我们可以保持拥有一个数字而不是其他数字的更高概率。
现在,我们可以将相同的基本原理应用到骰子游戏中。在第一周,总吞吐量达到积压量或更多的概率是多少?一些可能的结果如下:
然后,我们将运行许多这样的程序,看看有多少程序的吞吐量总和大于 backlog 总和,然后将结果除以运行次数。这样做,我们就有可能在第一周结束项目。在接下来的一周,我们将做同样的事情,但是每一轮掷骰子两次,然后对吞吐量和积压量求和。
这种方法的一个问题是,在项目开始时,backlog 的行为不同于在项目中间或结束时。在开始时,通常增长要快得多,因为我们更好地理解了我们项目的问题和细微差别,在最后,增长基本上来自于精炼的故事。
为了解决这个问题,我们不考虑整个 BGR 历史作为可能的结果,而只考虑积压的最后 10 个 bgr,这将使我们对积压最近的表现有更好的了解。
使用新的最后 10 个 BGR 方法得出的未来 10 周的结果显示在图表中:
如您所见,我突出显示了图表的三个不同区域,以说明我认为可以从图表中获得的信息:
- 第一个区域,红色的,是我们完成项目的概率低于 50%的几周。这意味着告诉项目的利益相关者你将在接下来的 4 周内完成它是非常危险的。
- 下一个区域,橙色区域,显示了我们完成项目的概率在 50%到 75%之间的几周。我要说的是,如果利益相关者向你施压,要求你快速交付,那么这几周,如果你有信心,你就能完成。
- 绿色区域是一个更无风险的区域,在那里你完成项目的概率大于 75%。我建议你总是优先考虑基于这个领域而不是其他领域来估计你的项目的结束,但是我们都知道我们不能总是那么安全。
我们在过去的项目中测试了蒙特卡洛模拟,它看起来工作得很好,但是,和任何其他统计方法一样,在项目中几周后,它比开始时好得多。
摘要
预测一个项目什么时候可能结束看起来太“胡说八道”了,但是这个方法真的很容易实现,并且让我们对我们的项目有更好的预测和理解。重要的是要弄清楚,这种方法是一种统计方法,因此它不是失败证明。主要目标是在我们的工具包中增加一个元素,让项目管理变得简单一点。
为了帮助你预测软件项目的完成日期,我们制作了一个简单版本的电子表格供你下载,这样你不用做太多工作就可以运行模拟。
要了解更多关于蒙特卡洛模拟的信息,我推荐以下参考资料:
- Troy Magennis 的书— 预测和模拟软件开发项目:使用蒙特卡罗模拟对看板& Scrum 项目进行有效建模
- 丹*尔·瓦坎蒂的网站、书籍和博客:可操作的敏捷
- Joel Spolsky 关于循证计划的博客文章
本文原载于http://blog . platafomatec . com . br/2016/08/forecasting-software-projects-completion-date-through-Monte-Carlo-simulation/。
预测可变差旅费用的准确率达到 95%
原文:https://towardsdatascience.com/forecasting-variable-travel-expenses-with-95-accuracy-5aa615203db5?source=collection_archive---------17-----------------------
首席财务官的自动机器学习
更新:我开了一家科技公司。你可以在这里找到更多
组织每年在差旅费上花费数百万美元,其中很大一部分是可变的,很难估计。除了在预订时已知的机票和住宿之外,餐饮和杂费等额外费用是未知的,可能对总费用有很大影响。
在本文中,我们将在几分钟内建立一个模型,该模型可以根据员工的职位、目的、目的地、住宿和机票计算出可变费用,对公布的数据有 95%的准确性,并且无需编写任何代码。数据准备和模型构建将由 AuDaS 处理,AuDaS 是由 [Mind Foundry](http://mind foundry.ai) 构建的自动化数据科学团队。
数据准备
费用数据是从安大略省养老金委员会下载的,包含其员工自 2010 年以来的费用报销。目标是使用截至 2017 年的数据来预测 2018 年的总支出。
Uploading the data into AuDaS
特征工程
数据集包含每次旅行的开始和结束日期,因此我们将要求 AuDaS 计算持续时间,因为这可能会对总花费产生很大影响。
然后,我们将使用 RegEx 转换删除数据中的$符号,以便进行格式化。
然后,我们将删除包含可变费用的列,以避免数据泄露,因为它们已经包含在我们希望预测的总支出中。这样做之后,AuDaS 检测到有一些丢失的值,并建议用户如何纠正它。
在整个过程中,AuDaS 在工作流程中增加了一些步骤,作为审计跟踪。您可以返回到数据集的先前版本,也可以导出工作流。在我们的例子中,我们将把这个工作流导出到包含 2018 年养老基金支出的测试集中。这将自动重现数据准备步骤,并允许我们在对其进行训练后,轻松地在其上部署我们的模型。
数据探索
现在我们已经清理了数据,我们可以访问直方图视图来提取初始的洞察力。我们也可以改变比例来查看稀疏分布的值。
我们的直接收获是,最常见的目的地是多伦多,董事会成员出差最多。似乎没有一个关键的模式,这就是为什么我们要使用机器学习来揭示更复杂的关系。
自动化建模
我们将要求 AuDaS 建立一个回归模型来预测总支出。
AuDaS 自动保留训练集的 10%用于最终验证。它还使用 10 重交叉验证来训练模型,以避免过度拟合。这保证了由 AuDaS 训练的模型在生产中表现良好。一旦我们满意了,我们现在就可以按开始按钮开始训练了。
训练是使用 Mind Foundry 的专有贝叶斯优化器 OPTaaS 实现的,opta as 允许 AuDaS 有效地在可能的回归管道的大搜索空间中导航。
AuDaS 提供了所选管道、模型和参数值以及性能统计的完全透明性。AuDaS 还为找到的最佳模型提供了特征相关性。
在这种情况下,住宿和机票费用以及目的地和目的地城市伦敦是可变费用的最强预测因素。首席信息官的头衔似乎也是总支出的一个很好的指标。既然我们对模型的准确性感到满意,我们就可以查看它的模型健康状况了。在我们的情况下,它是好的,我们可以放心地将其应用于测试数据集。
在测试数据集上运行训练好的模型之后,我们得到了每个条目的预测。AuDaS 会自动忽略模型训练中未使用的列。这意味着我们可以很容易地将实际总支出与预测支出进行比较。为此,我们可以导出数据并在 excel 中访问它。
在计算了每一列的总数后,我们可以看到 AuDaS 达到了 95%的准确率。
为什么这很重要
能够在一定程度上准确预测总支出对首席财务官来说是非常有价值的。在大公司,每季度的差旅支出可能达到 1 亿美元,甚至更多。可能会有相当大差异,分析人员通常会使用电子表格,根据不同部门的累积输入来估计预算需求。部门经理做了大量工作来积累有关未完成项目和过去支出的信息,增加了一些应急余量。同样的方法不仅适用于差旅费,也适用于许多成本预测情况。通过机器学习,业务线经理和财务可以在几分钟内做出更加准确的预测。最重要的是,这些模型可以实时运行,并在情况变化时提供高级警告。这避免了在关键的季度最后几周臭名昭著的旅行和成本禁运,因为预算已经达到。
了解更多信息
如果你想知道澳洲是否能解决你的问题,请填写这张简短的表格。如果你对 OPTaaS 感兴趣,你可以使用这个更短的表格获得一周免费试用的资格!
以下是这一过程的完整视频:
你可以在下面阅读更多 AuDaS 案例研究教程:
[## 信用卡聚类
营销人员面临的首要挑战是了解他们的销售对象。当你知道你的买家…
towardsdatascience.com](/credit-card-clustering-6a92657ac99) [## 利用自动化机器学习优化您的电子邮件营销策略
对于全球超过 1 万亿美元的企业来说,优化销售营销支出是一个价值 10 亿美元的问题…
towardsdatascience.com](/optimize-your-email-marketing-strategy-with-automated-machine-learning-e1bfb8cc171b) [## 利用 AuDaS 在几分钟内解决 Kaggle Telco 客户流失挑战
AuDaS 是由 Mind Foundry 开发的自动化数据科学家,旨在允许任何人,无论是否有…
towardsdatascience.com](/solving-the-kaggle-telco-customer-churn-challenge-in-minutes-with-audas-2273fed19961)
团队和资源
Mind Foundry 是牛津大学的一个分支机构,由斯蒂芬·罗伯茨(Stephen Roberts)和迈克尔·奥斯本(Michael Osborne)教授创建,他们在数据分析领域已经工作了 35 年。Mind Foundry 团队由 30 多名世界级的机器学习研究人员和精英软件工程师组成,其中许多人曾是牛津大学的博士后。此外,Mind Foundry 通过其分拆地位,拥有超过 30 名牛津大学机器学习博士的特权。Mind Foundry 是牛津大学的投资组合公司,其投资者包括牛津科学创新、牛津技术与创新基金、、牛津大学创新基金和 Parkwalk Advisors 。
使用 Python 和 Tableau 进行预测
原文:https://towardsdatascience.com/forecasting-with-python-and-tableau-dd37a218a1e5?source=collection_archive---------1-----------------------
我写了一本关于脸书先知的书,已经由 Packt 出版社出版了!这本书在亚马逊上有售。
这本书涵盖了使用 Prophet 的每个细节,从安装到模型评估和调整。十几个数据集已经可用,并用于演示 Prophet 功能,从简单到高级,代码完全可用。如果你喜欢这篇中帖,请考虑在这里订购:【https://amzn.to/373oIcf】T4!在超过 250 页的篇幅中,它涵盖的内容远远超过了媒体所能教授的内容!
非常感谢你支持我的书!
我是 Greg Rafferty,湾区的数据科学家。你可以在我的 github 上查看这个项目的代码。如有任何问题,请随时联系我!
在这篇文章中,我将展示如何在 Tableau 中使用 Python 代码来构建一个实现时间序列预测的交互式仪表板。如果你只是想先玩一下仪表盘,探索一下 SARIMAX 算法,请在这里下载完整的 python 实现的仪表盘,或者在 Tableau Public 上下载这个稍微有点笨的版本(Tableau Public 明智但令人失望地不允许上传外部脚本,所以我不得不用硬编码的数据集来伪造 Python 脚本)。
因为当你想不出一个好名字的时候,试试一个旅行箱
去年,Tableau 发布了 10.2 版本,其中包括与 Python 的集成。不过,如何使用它并不是非常简单,所以当一个客户要求一个时间序列预测仪表板时,我想我会弄清楚的。 ARIMA 模型没有内置到 Tableau 中(Tableau 的预测模块使用指数平滑,在这种特殊情况下,我确实需要使用 ARIMA 算法的更高预测能力,所以tabby似乎是我唯一的选择。
我不会详细介绍如何安装 TabPy(提示:pip install tabpy-server
),也不会详细介绍如何安装 Python(我想,如果你想在 Tableau 中运行 Python 代码,你可能已经知道如何使用 Python 了。如果没有,从这里开始。)
一旦安装了 TabPy 发行版,您将需要导航到包含在 /site-packages 中的源代码,然后进入 tabpy-server 目录(在我的例子中,是在默认位置安装了 Anaconda 3 的 MacOS 上,/anaconda3/lib/python3.7/site-packages/tabpy_server
)。从那里运行sh startup.sh
或python tabpy.py
来启动服务器。您需要指示 Tableau 不断地嗅探端口 9004,这是 Tableau 和 Python 的通信方式。为了做到这一点,在 Tableau 内部,
- 转到帮助→设置和性能→管理外部服务连接…
- 输入服务器(如果在同一台计算机上运行 TabPy,则为 localhost)和端口(默认为 9004)。
And you’re off to the races!
如果到目前为止你有任何困难,试试这个教程。
ARIMA:如果你的公文包听起来笨重,那就用首字母缩略词
ARIMA 代表一个独立的整体平均值。在本教程中,我使用了它的更高级的兄弟,SARIMAX(SeasonalAuto-RegressiveIintegratedMovingAaverage with eXogen 回归变量)。好吧,那是什么?
先从回归说起。你知道那是什么,对吧?基本上,给定一组点,它会计算出最能解释图案的直线。
接下来是 ARMA 模型(自回归移动平均)。自回归部分意味着它是一个基于以前的值预测未来值的回归模型。这类似于说明天会很暖和,因为前三天都很暖和。(附注:这就是时间序列模型比标准回归复杂得多的原因。数据点不是相互独立的!).均线部分其实根本不是均线(别问我为什么,我也不知道)。这仅仅意味着回归误差可以建模为误差的线性组合。
如果 ARMA 模型不太符合你的数据,你可以试试 ARIMA。额外的 I 代表集成。这个术语解释了先前值之间的差异。直觉上,这意味着明天很可能和今天一样的温度,因为过去一周没有太大变化。
最后,我们转到萨里马克斯。S 代表季节性-它有助于对重复模式进行建模。这些季节性模式本身并不一定每年都会发生;例如,如果我们在一个繁忙的城市地区模拟地铁交通,模式将每周重复一次。而 X 代表外源性的(抱歉。这个不是我想出来的)。这个术语允许将外部变量添加到模型中,比如天气预报(尽管我在本教程中的模型没有添加任何外部变量)。
一个 SARIMAX 模型采用 SARIMAX(p,D,q) x (P,D,Q)m 的形式,其中 P 是 AR 项,D 是 I 项,Q 是 MA 项。大写的 P、D 和 Q 是相同的术语,但与季节成分有关。*写的 m 是模式重复之前的季节周期数(因此,如果您正在处理月度数据,就像在本教程中一样,m 将是 12)。在实现时,这些参数都是整数,数字越*越好(即不太复杂)。对于我的模型,我选择的最适合模型的参数是 SARIMAX(2,1,2) x (0,2,2)12。
我进行了网格搜索以得出这些术语。我试图最*化的错误是赤池信息标准 (AIC)。AIC 是一种衡量模型与数据拟合程度的方法,同时降低了复杂性。在 Tableau 仪表板中,我报告均方误差,因为这更直观。
这样一来,让我们看看如何在 Tableau 中实现它!
航空乘客数据
如果你想跟进,你可以在我的 github 上下载打包的 Tableau 工作簿。我使用的是航空乘客数据集(https://www.kaggle.com/rakannimer/air-passengers),其中包含了 1949 年至 1961 年间航空乘客数量的月度数据。让我们来看看发生了什么:
(舞台上由人扮的)静态画面
我希望我的仪表板是完全交互式的,这样我可以更改所有的 p、d 和 q,同时观察它们对模型的影响。因此,首先(这里的“第一”,我指的是“第二,在您连接到上面链接的航空乘客数据集之后”),让我们为这些变量创建参数。
你需要创建 8 个参数: AR(时滞)、 I(季节性)、 MA(移动平均线)、月预测、期、季节性 AR(时滞)、季节性 I(季节性)、季节性 MA(移动平均线)。确保所有的数据类型都是整数,否则 Python 稍后会抛出一些错误(并且 TabPy 非常无益地拒绝为您提供错误行号)。对于月预测和期间,我使用了一个允许值范围,从 1 到 48(对于月预测)和 1 到 24(对于期间)。接下来我们需要创建一个名为预测日期的计算字段,这样 Tableau 将扩展 x 轴以包含预测值。在计算字段中,输入:
DATE(DATETRUNC('month', DATEADD('month', [Months Forecast], [Month])))
我们还将创建一个乘客数量计算字段,以确保我们的 SARIMAX 数据与实际数据相符:
LOOKUP(SUM([#Passengers]), [Months Forecast])
最后,还有一个名为过去与未来的计算字段,我们稍后将使用它将预测格式化为不同的颜色:
IF LAST() < [Months Forecast]
THEN 'Model Forecast'
ELSE 'Model Prediction'
END
计算机编程语言
好了,终于!在蟒蛇身上。让我们创建我们的第一个脚本。创建一个计算字段并将其命名为预测。在字段中,粘贴以下代码:
我们还将创建一个名为均方误差的计算字段,这样我们就可以在图表上有一个漂亮的动态标题:
现在,将预测日期拖到列架上,将乘客数量和预测拖到列架上。使其成为双轴图表,并使轴同步。将过去与未来放在预测卡的色标上,就大功告成了!那很容易,不是吗?(不,实际上不是。令人尴尬的是,我花了很长时间才弄明白如何让这些脚本工作,而且 Tableau 极其无益的不显示错误发生在哪里的习惯使得故障排除成为一项令人沮丧的工作。为了增加一点趣味,将这些参数添加到侧栏中,这样您就可以交互地更改它们。哦!我差点忘了那个时髦的标题。右键单击标题→编辑标题… →并键入以下代码:
下面是最终的仪表板应该是什么样子。如果你想让它看起来和我的一样,你会有一些格式化任务要处理,或者你可以下载我的仪表板在这里并完成它。Tableau Public 不允许上传任何外部脚本,很遗憾,这意味着我不能分享如下所示的确切版本。相反,我只是运行了数百个 SARIMAX 参数的排列,并将每个预测保存到一个 csv 文件中,这个版本虽然没有那么漂亮,也没有那么酷,但可以直接在 Tableau Public 这里上玩。
如你所见,模型相当不错!这就是 SARIMAX 的强大之处:它准确地模拟了随着时间推移的总体增长趋势,全年季节的起伏,甚至是随着时间的推移数据的增长方差(波峰高点和波谷低点之间的距离增加)。你需要*心选择你的参数,如果你不*心,一些有趣的事情会发生。例如,我表现最差的模型是这样的(看看这个误差幅度!):
法医深度学习:Kaggle 相机模型识别挑战
原文:https://towardsdatascience.com/forensic-deep-learning-kaggle-camera-model-identification-challenge-f6a3892561bd?source=collection_archive---------7-----------------------
数据扩充的重要性
From https://habr.com/company/ods/blog/415571/
大约一年前,在 kaggle.com 举办了一场名为 IEEE 信号处理学会——相机型号识别的计算机视觉挑战赛。任务是分配哪种类型的相机用于捕捉图像。比赛结束后,亚瑟·库津、阿图尔·法塔霍夫、伊利亚·基巴尔丁、鲁斯兰·道托夫和我决定写一份技术报告,描述如何解决这个问题,并分享我们在这个过程中获得的一些见解。它被接受参加在西雅图举行的第二届网络犯罪调查大数据分析国际研讨会,我将于 2018 年 12 月 10 日在那里发表演讲。在这篇博文中,我想写一个文本的扩展版本。
这篇论文有五位作者:
亚瑟·法塔霍夫、亚瑟·库津、伊利亚·基布丁和其他队员以 0.987 的成绩获得第二名。
我是以 0.985 分获得第九名的队伍中的一员。
我们的解决方案非常相似,所以我们决定写一份技术报告。深圳大学大数据研究所的研究生鲁斯兰(Ruslan )自愿帮我做文本,这对这篇论文至关重要。
在下文中,我将把第二名团队的方法称为“我们的”解决方案。此外,我将跳过一些对整体信息不重要的技术细节。第二名解决方案的代码可在 GitHubhttps://GitHub . com/iki bardin/ka ggle-camera-model-identificati on上获得。比赛结束后,我们使用我们开发的洞察力进行了一系列单独的实验。这里的工作主要是基于这一进一步的调查。
图像处理的许多应用之一是相机模型检测。例如,在法医学领域,可能至关重要的是要知道一张图片是使用谷歌 Pixel 还是 iPhone 拍摄的,以确定谁可能是非法或有罪照片的所有者,甚至确定谁是知识产权的合法所有者。这种系统还可以用于检测诽谤、中伤或传播假新闻的肇事者。
计算机中的图像存储为数字矩阵和附带的元数据。在最简单的情况下,相机模型应该存储在图像元数据中,这使得相机识别成为一个基本问题。但是图像元数据可能不可靠,并且很容易被恶意用户操纵。
还有另一种更复杂但更可靠的方法。采集完成后,数码相机中的图像将经过一系列后处理步骤,从而生成图像保真度和内存占用优化的图像。这些算法非常复杂,高度非线性。例子可以包括去马赛克、噪声过滤、修正镜头失真等。不同的算法用于各种相机模型,这意味着它们中的每一个都创建特定于模型的工件,人们可以将其用作机器学习管道的特征。
当然,有很多关于这个主题的文献。它的大部分提出了手动特征提取的步骤,在此基础上使用 SVM 或类似的分类算法。例如,当我面对这个问题时,我想到的第一个想法是拍摄一张图像,减去它的平滑版本,并计算这种差异的不同统计数据,如均值、中值、标准差和不同的量,并在其上训练 xgboost。关于如何进行这种相机型号检测的第一篇论文之一非常接近我刚才描述的内容。其他文章提出了一些更复杂的东西,但方法非常相似,基于领域知识的手动特征提取,并在此基础上使用逻辑回归、决策树或 SVM。
将这种方法推广到新的相机型号也很困难。假设我们想为一个新的、刚刚发布的模型进行相机检测。专家应该花多长时间来找出哪些特征有助于将它与其他模型区分开来?
另一方面,深度学习方法可以解决这两个问题。总的来说,深度学习是一头强大的野兽,如果你知道如何驯服它,它可能会帮助你创建高度准确的黑盒模型。
当你在查阅文献并试图理解哪种方法是“最好的”时,这是不可能的。几乎每篇论文都告诉你它们是最先进的。处理的方法是在同一个数据集上评估不同的方法。这种比较不会给你一个总体上哪种算法更好的答案,而是在给定的数据集上,哪种算法更好。这并不意味着在相似的数据集上算法排名是相同的,比如在 CIFAR 上最先进的架构可能在 ImageNet 上表现不佳,反之亦然。但这样的统一对比总比没有好。
对于相机检测任务,IEEE 信号处理协会组织了一次挑战,其中 582 个团队有两个月的时间和一个实时排行榜来比较他们的方法。582 是一个很大的数字,这确保了问题会被不同背景和技能的人所攻击。一些参与者在工业界和学术界从事法医工作,以此谋生。其他人,比如我,有使用计算机视觉技术的经验,但是没有意识到甚至存在像相机识别这样的问题,并且有人有兴趣解决它。
组织者准备了一个由 2750 张图片组成的训练集,这些图片来自 10 台相机——每台相机 275 张。
我们需要区分的相机型号有:
- 索* NEX-7
- 摩托罗拉摩托 X
- 摩托罗拉 Nexus 6
- 摩托罗拉 DROID MAXX
- LG Nexus 5x
- 苹果 iPhone 6
- 苹果 iPhone 4s
- HTC One M7
- 三星银河 S4
- 三星 Galaxy Note 3
为了让这个问题不那么无聊,组织者使用了 20 部不同的手机来收集图像:10 部用于训练,10 部用于测试。这意味着在训练期间,您的模型可能不会学习与后处理算法相关的相机模型特定的功能,而是过度适应特定手机特定的伪像。
测试集中的图像是用相同的 10 个相机模型捕获的,但是使用第二个设备。例如,如果 iPhone 6 的火车数据图片是用 Ben Hamner 的设备(相机 1)拍摄的,那么测试数据中的图像是用 Ben Hamner 的第二个设备(相机 2)拍摄的,因为他在风筝冲浪时丢失了海湾中的第一个设备。
此外,火车中的图像是全尺寸的,而在测试中,只使用了中央 512x512 作物。其原因是径向失真在图像的侧面更加明显。一些论文显示了纯粹基于径向畸变特征的有希望的结果。他们能增加多少附加值还不清楚,但组织者决定阻止参与者利用他们。
这还不是全部。在许多情况下,通常存储在电脑上的图像会受到不同转换的影响,如 jpeg 压缩、gamma 转换、对比度、亮度、调整大*等。
从实践的角度来看,有一个健壮的模型来进行这样的转换是很好的。以下类似的逻辑组织者用以下变换之一修改了一半的测试图像:
- 质量因子= 70 的 JPEG 压缩
- 质量因子= 90 的 JPEG 压缩
- 通过因子 0.5 调整大*(通过双三次插值)
- 通过因子 0.8 调整大*(通过双三次插值)
- 通过因子 1.5 调整大*(通过双三次插值)
- 通过因子 2.0 调整大*(通过双三次插值)
- 使用 Gamma = 0.8 进行 gamma 校正
- 使用 Gamma = 1.2 进行 gamma 校正
Jpeg compression with quality [5, 15, 25, 35, 45, 55, 65, 75, 85, 95]
Gamma Transform with quality [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75]
正如我上面提到的,在不同的图像主机上有数 Pb 的图像,我们可以从中提取相机模型。Kaggle 的各种比赛对外部数据有不同的规则,但在这种情况下,这是允许的。一般来说,所有允许外部数据的竞赛都有一条规则,强制所有参与者也可以访问这些数据。在任何此类比赛中,论坛上都有一个主题,参与者可以分享他们计划使用的数据和预先训练的模型。
这次比赛是个例外。管理员忘记在规则中加入关于共享数据的句子。这改变了游戏。
深度学习模型的好处在于,由于容量大,它们通常会受益于用于训练的数据量。同样重要的是,许多火车标签可能是错误的。这很好。只要错误标签的百分比低于 15%,你就没事。你使用的数据越多,你的模型就越好。
参与者可能不是法医专家,但他们肯定知道更多数据对 DL 更好的事实。这改变了竞争的态势。通常,在竞争中,您会试图从给定的数据集中获取最多的信息。经过一些实验后,你选择一个性能良好的模型,聪明地选择你的增强,探索领域知识,花时间制定一个智能训练计划,损失函数等。如果你没有更好的选择,所有这些都很重要。但是我们做到了。
Flickr,Yandex,Fotki,Wikipedia commons 都被废弃了,该团队拥有的原始图像数据总量约为 500Gb。我们可以使用所有这些数据,但是为了加速训练并潜在地提高模型的质量,我们进行了过滤。
对于训练,我们想要未经处理的数据,这意味着不受 Photoshop 或 LightRoom 或类似图像编辑软件的影响,不调整大*,并且是高质量的。
首先,我们删除了元数据中包含 Photoshop 和 LightRoom 的图像。其次,我们删除了 Jpeg 质量低于 95 的图像。第三,我们知道不同的相机以固定的尺寸拍摄照片。如果图像的大*与我们预期的不匹配,我们认为它被调整了大*。我们删除了不符合这些标准的图片。
这并不意味着我们得到的所有图像都是未经处理的,比如有人可能使用 10%质量的 jpeg 压缩,然后再使用 99%质量的 jpeg 压缩。实际上它仍然是 10%,但是对于我们的软件来说,很难发现它是 10 而不是 99。我不想说“困难”,我想说不可能,但是回想一下,在研究这个问题时,我看到过试图识别“双重 jpeg 压缩”的论文。再说一次,我甚至不知道有这样的问题存在。
过滤后,我们有 78807 个废弃的图像,它们被认为是原始的和未经处理的。阶级分布不均匀。正如人们所料,并非所有手机都同样受欢迎,或者手机型号与机主拍照并上传到互联网的频率之间存在相关性。因此,对于某些类,我们有更少的图像。
Camera model classes with the number of samples each part of the dataset. The table presents the final dataset, which contains external and organizers datasets.
From https://habr.com/company/ods/blog/415571/
总的来说,这是一个从 ImageNet 学习的过程。你拿一个预先训练好的网络,去掉预测 1000 个类的最后一层,换成预测你需要什么的一层。在我们的例子中,这个数字是 10。在此之后,您使用分类交叉熵来计算您的损失,并训练网络。第一名和第 50 名的区别通常不在于你使用的网络类型,而在于培训程序和进行培训的人。从实践的角度来看,深度学习仍然是炼金术多于科学。因此,当一个人从事不同的工作时,发展出来的直觉是至关重要的。
对 PyTorch 有影响力的网络有一个很好的列表,那就是雷米·卡登 https://github.com/Cadene/pretrained-models.pytorch的回购。人们可以使用类似的 API 访问不同的网络和预先训练的权重,从而快速进行实验。这种回购被挑战的参与者广泛使用。团队试验了 Resnet、VGG、DPN 和所有其他类型的网络。
对于这个问题,一个经验主义的结论是 DenseNet 工作得稍微好一点,但是团队之间的差异是如此之*,以至于它是真是假还不清楚。
什么是 DenseNet?DenseNet 是一种体系结构,它将在 Resnet 类型的网络中使用跳过连接的思想推进了一步。
https://arthurdouillard.com/post/densenet/ https://arxiv.org/abs/1608.06993
更多被跳过的连接给被跳过的连接之神!
DenseNet 论文的作者将卷积块中的所有层连接起来。跳跃连接简化了梯度的流动,使得训练深度网络成为可能。在 skip connections 成为主流之前,处理只有 19 层的 VGG19 是一件痛苦的事情。在引入它们之后,具有 100 层以上的网络可以处理非常高级的抽象功能,不再是训练的问题。
还认为损失曲面变得更平滑,防止训练陷入许多局部最*值。
https://arxiv.org/abs/1712.09913
除此之外,网络比较规范。一组卷积块,具有批范数和 ReLu 层,在块之间有最大池。全球平均池和密集层在最后。有必要提及的是,存在全局平均池层的事实允许我们使用不同大*的图像作为输入。
有些人认为 DenseNet 总是优于 Resnet,因为它是后来推出的,并成为 2017 年 CVPR 最佳论文。事实并非如此。在最初的文章中,DenseNet 在 CIFAR 上显示了良好的结果,但是在更多样化的 ImageNet 数据集上,更深的 Densenet 需要在准确性上匹配更浅的 ResNet 网络。
DenseNet 比 Resnet 好/差?看情况。在星球:从太空挑战中了解亚马逊,DenseNet,我们的团队在 900+中获得了第 7 名,在这个相机检测问题上表现更好。但在 ImageNet 上,情况更糟。
我与我的合作者进行了一次讨论,有人提出跳过连接不仅提供了良好的光滑损失表面,而且还降低了模型容量。这可能解释了为什么 DenseNet 在像 CIFAR 这样的非多样性问题中表现得更好。尽管如此,人们需要增加网络的深度,以弥补更多样化的 ImageNet 数据集的容量损失。基于这种推测,人们可能会想到 DenseNets 工作良好的用例是当数据集不是非常多样化并且不需要大容量时。尽管如此,区别性特征是高水平的,这可能需要非常深的网络。
摄像机检测任务属于这一类吗?我不知道。经验上是的,但是证据不足。
将智能正则化添加到训练过程的标准方法是使用增强。不同的问题可能受益于不同的增强,同样,你的直觉越好,你就可以选择更好的增强及其参数。
对于这个问题,我们使用:
- 二面角组 D4 变换:旋转 90 度、180 度、270 度和翻转。
- 伽玛变换。我们从[80,120]范围内统一选择伽马参数。
- 参数从 70 到 90 均匀采样的 JPEG 压缩。
- 重新缩放变换,从[0.5,2]范围中选择比例。
在代码中,使用相册库,它可以被描述为:
import albumentations as albu def train_transform(image, p=1):
aug = albu.Compose([albu.RandomRotate90(p=0.5),
albu.HorizontalFlip(p=0.5),
albu.RandomGamma(gamma_limit=(80, 120), p=0.5),
albu.JpegCompression(quality_lower=70, quality_upper=90, p=0.5),
albu.RandomScale(scale_limit=(0.5, 2), interpolation=cv2.INTER_CUBIC, p=1)
], p=p)
return aug(image=image)['image']
Left is the original image from my recent rock-climbing trip to Bishop, and right is flipped and a bit darker. The latter is the effect of the gamma transformation. Jpeg compression was also applied, but it is hard to find its effects because quality [70:90] is relatively high.
组织者告诉我们,他们使用三次插值来调整大*。如果我们没有这些信息,我们可以在不同插值之间交替使用。一般来说,竞争激烈的 ML 社区经常使用这个技巧,但是我还没有在文献中看到它。
无论如何,如果我们想要添加这种改变,代码会更复杂,但仍然相对透明。
import albumentations as albu def train_transform(image, p=1):
scale_limit = (0.5, 2) aug = albu.Compose([
albu.RandomRotate90(p=0.5),
albu.HorizontalFlip(p=0.5),
albu.RandomGamma(gamma_limit=(80, 120), p=0.5),
albu.JpegCompression(quality_lower=70, quality_upper=90, p=0.5),
albu.OneOf([albu.RandomScale(scale_limit=scale_limit, interpolation=cv2.INTER_NEAREST, p=0.5),
albu.RandomScale(scale_limit=scale_limit, interpolation=cv2.INTER_LINEAR, p=0.5),
albu.RandomScale(scale_limit=scale_limit, interpolation=cv2.INTER_CUBIC, p=0.5),
albu.RandomScale(scale_limit=scale_limit, interpolation=cv2.INTER_AREA, p=0.5),
albu.RandomScale(scale_limit=scale_limit, interpolation=cv2.INTER_LANCZOS4, p=0.5),
], p=0.5),
], p=p)
return aug(image=image)['image']
原始图像的分辨率很高。在全分辨率下重新调整它们是不明智的。因此我们连续收获了两季。一个在调整大*之前,一个在调整大*之后。
import albumentations as albu def train_transform(image, p=1):
aug = albu.Compose([
albu.RandomCrop(height=960, width=960, p=1),
albu.RandomRotate90(p=0.5),
albu.HorizontalFlip(p=0.5),
albu.RandomGamma(gamma_limit=(80, 120), p=0.5),
albu.JpegCompression(quality_lower=70, quality_upper=90, p=0.5),
albu.RandomScale(scale_limit=(0.5, 2), interpolation=cv2.INTER_CUBIC, p=1)
albu.RandomCrop(height=480, width=480, p=1),
], p=p)
return aug(image=image)['image']
使用初始学习率为 0.001 的 Adam optimizer 对网络进行 100 个时期的训练。
为了获得更好的精度,当学习率在不同值之间振荡时,我们还使用了循环学习率方法。
正如你从这张图片中所猜测的,学习率在 17 世纪左右下降了。
同时,在 42°左右和 53°左右有两个连续衰减的损耗峰。在训练过程中,网络往往会陷入局部最*值,而这些振荡有助于摆脱它们。
在推断时,我们执行测试时间增加,平均来自测试图像的不同 480x480 裁剪的预测。
我们还对估计不同的转换如何在推理时降低模型的准确性感兴趣。
绿色表示训练中使用的参数范围。
正如预期的那样,在模型被训练的范围内,精确度没有显著降低。这表明,如果使用深度学习方法并拥有足够数量的数据,增加所应用的增强的范围可能会导致更稳健的模型。
我们想要回答的另一个问题是,如果我们在测试时减少输入到网络的作物的输入大*,精确度会如何?
我会认为网络正在学习的特性是如此的局部化,以至于不需要大规模的裁剪,但是看起来事实并非如此。为了使 10 个类别的准确率达到 90%以上,人们需要至少 250x250 的作物,这可能意味着后处理算法会在网络捕捉的像素之间创建长距离相关性。
我们还希望验证,当训练数据量增加时,模型的准确性也会提高。从图中可以看出,这种情况并没有发生。我想我们的最低数据点 25k 对于高质量的模型来说已经足够了。如果我们需要检测的不是 10 个,而是 1000 个类别,那么作为训练数据的函数,模型质量的提高可能会更明显。
总结:
- 来自 ImageNet 的迁移学习即使对于像照相机检测任务中的那些低级特征也工作得很好。
- DenseNet 表现更好,但我们认为,人们可以从 Cadene 的列表中选择任何预训练网络,它会表现类似。
- 在训练期间应用增强可能有助于使模型更健壮。
- 如果你能得到更多的标签数据,那就去得到它。在许多(但不是全部)问题中,使用大量数据的蛮力可能比复杂的解决方案更容易使用。尽管利用领域知识可以增加重要的额外推动力。
课文中跳过的内容:
- 添加额外的输出来判断图像是否被操纵有意义吗?
- 像检查点平均这样的技巧。
- 其他架构表现如何?
- 如何完成这项任务?
- 如何利用测试中的类是平衡的?
- 如何将伪标签应用于此任务。
- 讨论我们尝试了什么,但它在这个任务中不起作用。
- 网络了解到的特征有哪些?
- 此问题评估标准的细微差别。
所有这些话题都很重要,但我并不认为它们有很大的影响力,或者我更愿意对每一个话题进行单独的讨论。
P.S .参加 2018 年 12 月 10-13 日在美国西雅图举行的 2018 年 IEEE 大数据国际会议的人。参观第二届网络犯罪调查和预防大数据分析国际研讨会的研讨会并问好:)
帮助编辑:埃里克·加塞德伦
2018 年需要关注的四大分析趋势
原文:https://towardsdatascience.com/four-analytics-trends-to-keep-an-eye-on-in-2018-854646e390f6?source=collection_archive---------12-----------------------
Courtesy:Flickr
当你想到 2018 年的分析时,是什么让你早上起床?是 AI 在我们生活中的突出地位、数据的民主化还是高级分析让你感到兴奋?让我们接受这一点,去年是多事之秋,自助分析、物联网分析以及聊天机器人变得越来越智能。感受到这些发展,2018 年应该成为分析行业加速创新的又一年-当然会有一些预期和意外的中断!激动吗?毫不费力地阅读我们在 2018 年要关注的四大分析趋势!
人工智能聊天机器人不再是镇上的“新手”,很快将成为所有操作的主要驱动力!
“Siri,今晚我该看哪部电影?或者“谷歌,告诉我去办公室的最佳路线”,熟悉这些日常对话?想象一下没有他们的生活吧!可以吗?不太可能,对吧?考虑到它们对我们繁忙生活的影响。2017 年,围绕智能推荐有太多的噪音,人工智能聊天机器人可以识别我们的情绪,并相应地回应我们。不仅是关于天气或交通拥堵的更新,聊天机器人将会发展,还可能有助于搜索财务运营指标或获得“为什么”和“如果”问题的答案,从而实现商业和消费者空间的转型。尽管这可能需要几年时间才能成熟,但我们可以预计 2018 年也不会有多少成功故事。
增强现实:从卷轴到现实,增强现实正在并将改变我们周围的世界
还记得 2016 年 7 月,数百万人如何穿过公园,走过人们的坟墓,进入教堂,寻找增强现实版的神奇宝贝角色。记忆犹新,对吧?虽然口袋妖怪的狂热已经消退,但增强现实却没有,我们可以在 2018 年看到一些更先进和更动态的 AR 模式。随着企业已经在使用 AR 来增强制造和研究流程或提供新的客户体验,人机交互将会增强。为什么这对分析行业很重要?根据 Gartner 副总裁 David Cleary 的说法,“增强分析是一个特别具有战略意义的增长领域,它使用机器学习来为广泛的企业用户、运营人员和公民数据科学家自动化数据准备、洞察发现和洞察共享。”因此,是的,在几年内,所有的资源消耗和时间敏感的分析将大大变得容易和流畅的增强分析!
物联网分析:2018 年,每个行业的银弹?
2017 年,是“互联互通”收获巨大的一年。尽管存在大量安全问题,但围绕物联网还是有很多投资和采用。2018 年怎么样?物联网分析会像 2017 年一样激动人心吗?不可忽视的是,物联网今年也将继续扩展,几乎每秒钟都会有越来越多的设备联网。尽管零售、医疗、和工业/供应链行业一直在使用物联网来提高投资回报率,但今年我们可以看到越来越多的公司将物联网用于更加个性化的营销工作。此外, Business Insider 预测,到 2021 年,企业在物联网解决方案上的支出将达到 6 万亿美元。根据这一预测,我们将看到许多风险投资家继续向物联网的承诺投入资金,这凸显了物联网在几乎每个行业改善客户体验的潜力!
区块链科技:实现新形式的数据货币化
所有人都同意,2017 年是区块链取得巨大增长的一年?许多人认为我们已经处于采用的“早期多数”阶段,并且我们正在朝着完全采用区块链的方向前进。与任何新技术一样,数据的重要性也在增长。今年,我们可能会看到区块链变得更加主流,医疗保健和零售等行业也开始使用它来处理数据,以防止黑客攻击数据泄露。根据戴尔 EMC 服务首席技术官 Bill Schmarzo 的说法,区块链技术还“有可能通过消除促成交易的中间人,使数据和分析的共享和货币化民主化。”因此,是的,组织将加快对这些虚拟货币的数据分析过程,以揭示强大的趋势、欺诈和洞察力,并做出明智的决策!
如何搭上虚拟货币涨势?请继续阅读,了解更多信息。
虽然很难说这些分析趋势会以多快的速度在我们的生活中体现出来,但我们相信 2018 年将再次成为多事之秋。将会有关于安全、治理以及最重要的消费者接受和适应这些创新和变化的能力的问题。唯一可以确定的是,今年的未来会有所不同,非常有希望!敬请关注!
四个破碎的系统& 2018 年的四大技术趋势
原文:https://towardsdatascience.com/four-broken-systems-four-tech-trends-for-2018-bd4698a3bef0?source=collection_archive---------11-----------------------
我受邀在未来女性活动上发表关于 2018 年科技趋势的演讲。未来女性是一场由现任和有抱负的女性企业家组成的运动。我非常钦佩这类女性,所以我很荣幸被邀请来演讲。此外,这是一个多么吉祥的方式来结束这一年,被要求思考未来,所以这里有一些关于这个巨大的话题的想法。
免责声明:我来自天体物理学,偏爱数据科学、统计学和目前归入机器学习和人工智能范畴的算法家族。
如何看待技术趋势这个话题?关于这方面的报道、刊物、文章、领域 - 具体、分析、、信息图。如何在这个时髦词汇的海洋中航行,并试图理解它对我们明年或以后的人意味着什么?我的出发点是问:
什么坏了?哪些在 2017 年行不通的,在 2018 年应该会更好?
虽然这个列表可能很长,但我想到了 4 个系统,它们在 2017 年表现出了多么不合适、不准确或彻底崩溃。
1.社会和政治工程
2017 年,社交媒体网络证明,它们并不像以前宣称的那样是一股团结的力量,在世界各地的人们之间建立桥梁。事实上,社交媒体平台恰恰相反,它分化了社区,分裂了社会,暴露了深刻的意识形态分歧,并以 YouTube 评论中首次发现的恶意和攻击性进行辩护。事实证明,南非本身并没有*到可以不被旨在煽动党派观点的推特机器人所注意。
我们已经看到公关公司改变公众舆论,加剧政治动荡,外国国家 利用社交媒体平台影响其他国家的投票和选举。我们已经看到政治预测者,从传统的民意测验专家到前沿的统计分析师都搞错了。
很明显,这没用。
2.传统(技术)教育
每年都有很多声音描述教育系统是如何崩溃的。虽然这可能是真的,而且太大了,无法在这里解决,但我认为专注于技术教育会很有趣,因为那里正在发生一些非常有趣的事情。
问题是,许多公司认为他们不能雇佣大学毕业生,因为他们(T2)不能像这些公司所希望的那样立即投入运营。南非的毕业生失业是一个问题。有一些努力。金伯利的 Sol Plaatjie 大学于 2014 年成立,专注于数据科学。像 Coursera 、 edX 、 Udacity 和 others 这样的大规模开放在线课程平台现在不仅提供课程,还提供专业学位,或者纳米学位,这些学位捆绑了一组急需的技能。这些在线学位在就业市场上越来越受到重视,以至于许多大公司,如微软,在这些平台上开设了许多认证课程。
让这个领域的创新变得有趣的另一个方面是不同商业模式的出现,以及除了赚钱之外的其他激励手段的使用。我想到的例子有 Insight 数据科学奖学金、 Ecole 42 以及它的南非版本,最优秀的我们认为代码 _ 。在这些科技教育机构中,学生不负责学费,但需要他们培养的人才的企业负责。这极大地改变了游戏的可访问性。Ecole42 和我们认为 code_ 在资格方面没有任何先决条件。没错。有人可能在 15 岁就辍学了,但仍然被录取,只要他们通过了在线解决问题技能测试。它不是对知识的测试,而是对人们如何处理问题的测试。这是大多数学校都不教的。
3.数据管理
今年我们已经看到了历史上一些最大的数据泄露事件,以及一些最大的掩盖事件。无论是优步、Equifax 还是雅虎,至少有一个漏洞最有可能影响到我们每一个人。在南非,我们已经看到一个数据泄露事件泄露了身份证号码和其他个人信息,这些信息可能被用于身份盗窃。
这里的问题是激励、所有权和风险都以错误的方式分配。我们都从系统中受益,大公司利用我们的数据来销售有针对性的广告,作为交换,我们愿意将我们的数据交给他人,这样我们就可以免费使用社交网络、网络平台和搜索引擎。当出现漏洞时,问题就来了。虽然这些大公司可能拥有数据,但他们不承担违规带来的风险。这种风险——身份盗窃、信用卡滥用等等——仍然由我们自己——消费者——承担。因此,应用能够抵御越来越聪明的黑客攻击的适当数据安全措施的动机不在于拥有和保存数据的大公司。完整的报告存在于被盗数据经济中;事实证明,在黑暗网络上,一个身份并不昂贵。
这些待售的身份不是大公司的信息,而是你我的。很明显这没用。
这个问题如此严重,以至于有些人投入巨资试图改变这种状况。这里面有很多钱。
4.人工智能应用传播其创造者的偏见
今天使用的人工智能算法主要建立在机器学习算法的基础上,这些算法经过编程,然后根据数据进行训练。这为算法和训练阶段的偏差留下了空间,后者可能是最能揭示问题的。AI 的偏见已经在 2017 年被多家主要刊物彻底记录。(请点击所有这些链接了解更多信息,有些文章可能在付费墙后面)。
下面的两个例子说明了这些偏见有多普遍。
第一张图片是谷歌图片搜索“正面”的屏幕截图,带有额外的彩色图片过滤器和知识共享许可,允许我在其他地方显示图片。寻找一张脸,我得到了一个雕像,一幅画,一座建筑,两只动物,但只有一个黑人。这实质上意味着,当搜索一张脸的图像时,黑色的脸出现的频率不会比动物和建筑物之类的错误更高!这不仅是对世界面孔的拙劣表现,也是一种完全有偏见的信噪比。
在第二个案例中,我的一个朋友玩了剑桥大学(Cambridge University)开发的在线人工智能服务,该服务通过分析推文或 facebook 帖子获得人口统计数据。不用说,我的朋友、我自己和一大群女科学家立即被贴上了男性标签,提出了一个合理的问题:“在人工智能时代,泛化是合理的吗?”。
答案当然是否定的。因此,这显然是行不通的。如果我们要信任我们的人工智能,我们都需要改进它,并记住人工智能会错过的边缘情况。我们必须比人工智能更聪明(我们也能)。
这涵盖了 2017 年的一些重大破事,以我谦卑和人性偏见的观点来看。现在谈谈我(和许多其他人)预见的一些有趣的技术趋势。
2018 年,技术可能会对我们的生活产生怎样不同的影响?
同样,这不是一个详尽的清单。我刚刚确定了四个有趣的趋势,我渴望看到发展。这个列表有一个偏差,因为这主要是对消费者可见的技术,如果不是直接的消费者技术的话。在工业和研究领域有着迷人的技术发展,我们无法直接看到,这是一个全新的探索世界。
1.与机器人一起工作和生活
几年来,这已经成为许多科学家的标准,但这仍然有助于科学研究。从用于寻找水污染源头的机器鳗鱼到学校认可的隐形 T2 机器斑马鱼,机器人技术正以创造性的方式应用于尖端领域。离我们更近的是,机器人手术正在成为许多医生的现实(伴随着过渡期的自然痛苦),因此也成为病人的现实。更有趣的是,价格实惠、外观自然的个性化智能假肢的兴起。有了 3D 打印,假肢不再需要看起来像商店橱窗里的人体模型,它们可以适合任何个人。随着神经修复术的进步,现在这是真正的机器人生活。
我认为,我们还将看到机器人更多地进入我们的物理空间。除了电话号码末尾的机器人,或者管理我们的社交媒体,我们将开始看到它们。任何自动驾驶车辆实际上都是机器人,无论是自动驾驶汽车、穿梭车、卡车,还是无人驾驶飞机、室内或室外,机器人正在变得可见,它们将很快成为我们生活环境的一部分。
2.消失的界面
在过去,我们会出去购买一些技术来访问一些东西,无论是听音乐的随身听,玩游戏的游戏机,还是阅读电子邮件的电脑。现在,这种情况似乎越来越少,我们不再需要购买更多的技术,而是回来坚持使用几十年来我们一直使用的一些产品,这些产品似乎会一直存在下去;汽车,手表,电话,娱乐系统。我们喜欢的一切的界面开始存在于那些对象中,但是在它们之间无缝导航。我们从手机上听音乐,但当我们开始开车时,汽车会接管它,它会接下一个电话,等等。
界面现在正在消失,无处不在,这为未来几年带来了一些非常有趣的机遇和挑战,从界面/交互设计到数据和隐私。期待看到 2018 年这个趋势会如何发展。
- 人工智能作为一种商品
人工智能是不可避免的。它将贯穿我们的大部分工作。人工智能有一些非常有趣的创造性应用,例如根据难民被重新安置的地点优化他们获得就业的机会,到你的普通聊天机器人。不同的是,现在人工智能正在变得商品化,因此,任何人都可以将其纳入他们的产品和服务。这种商品化有三个主要方面:
- 开源软件
tensor flowSparkpy brainopen nn等。一些最好的人工智能和机器学习库是开源的。不再躲在专有的微调算法后面。除此之外,还有丰富的免费在线课程,几乎任何人都可以学习将机器学习和人工智能应用到自己的业务中。 - 例如,如果没有大量数据来训练机器学习算法,那么可以通过 API 轻松访问预先训练的引擎。比方说,每次调用分析一张图片或一些文本,都不再非常昂贵。所有大公司都有一套全面的人工智能 API 可供使用;微软 Azure 的认知服务,谷歌的云服务——比如针对语音、视觉和自然语言,或者亚马逊的认知。
- 边缘计算
在我看来,这是一个特别有趣的问题。以前,如果你环顾互联设备的世界,你几乎可以说物联网主要是一堆互联的传感器,收集数据并在其他地方集中分析,因此需要连接。现在,世界各地的芯片制造商已经意识到 GPU 革命——图形处理单元(通常在游戏电脑中发现)比普通 CPU、中央处理器——笔记本电脑和手机中的芯片等更有效地用于机器学习和人工智能。去年我们已经看到了主要芯片制造商在发布了一系列公告,这是一种为人工智能设计的新型芯片;神经形态计算(称为神经形态,指大多数人工智能使用的神经网络)。芯片就是芯片,它们往往价值数十亿,而且价格低廉。这将在传感器所在的边缘带来负担得起的人工智能硬件能力。我相信这将改变我们对世界上人工智能应用的看法,我很高兴看到这将引领我们走向何方。
4.区块链
最后,我必须提一下这种“房间里的大象”技术,我不是这方面的专家。我了解它的工作原理,但不要问我加密货币和交易所之间的具体区别。区块链是加密货币的基础技术,据观察,在中央当局不再受信任的地方,这些加密货币提供了有吸引力的替代方案。他们也吸引了有着邪恶目的的组织。这让我想到了区块链科技的两个特点,正是这两个特点让它成为了游戏规则的改变者:
- 可信的分散化取代不可信的集中式系统
- 数字人工制品的独特性
第一点是,为什么加密货币在中央经济当局陷入困境或不受信任的国家如此有吸引力。它可以应用于合同、供应链等。第二点是前所未有的。在此之前,用数字人工制品区分原作和复制品的能力是不可能的。这可以保证艺术品的真实性,限制版权材料的复制等。
我将把它留在这里,不做进一步的开发,但我认为重要的是不要被围绕加密货币的所有宣传所蒙蔽,要看到这项技术的独特性,也许要看看它可以在任何行业中实现什么。2018 年无疑会看到一些有趣的应用从加密货币价值波动的噪音中出现。
最后
因为这是写给企业家的,所以我决定思考一下机会在哪里。我的印象是,光有技术和要解决的问题是不够的,还需要正确的经济激励模式,这里有大量创造力的空间,这是我试图说明的。
如果你有时间继续读下去:
我想强调的最后一点是经济激励的“超越企业社会责任”思想。
在这篇文章中,有两个双赢的例子,一点也不仁慈。第一个是 we think code_(和 Ecole 42)的商业模式。通过资助学校,雇佣他们毕业生的公司可以被视为自私地照顾他们的利益,即解决他们所需人才的稀缺问题,但事实上远不止如此。在南非,一个有工作的人常常要养活整个家庭,通常也是一个大家庭,特别是如果他们进入编码学校时没有主要资格证书,这有助于减轻贫困的可怕影响。因此,除了这种模式本身的双赢之外,还有一个额外的积极副作用。
第二个例子是大赦国际申请重新安置难民,以增加他们找到工作的机会。虽然这个例子不是来自私营部门,学术界的回报/货币是科学出版物,这显然导致了至少一个。但它也应用了尖端技术来造福那些利益往往被放在最后的人。此外,结果,更高的就业机会,直接导致更好的融合,看到融合是双向的,也导致更多的宽容。因此,除了这个项目的双赢之外,还有一个额外的积极副作用。
底线是,通过进一步关注而不仅仅是一个单一的受益者,一个人可以围绕价值/财富/健康创造和技术的生成链进行创新,这是不可能改变的。
针对实时分析的大数据堆栈四败一胜
原文:https://towardsdatascience.com/four-fails-and-a-win-at-a-big-data-stack-for-realtime-analytics-4f82f651d476?source=collection_archive---------8-----------------------
构建一个用户友好的应用程序来实时分析大数据(即保持响应时间低于 60 秒)是一项挑战。在大数据世界中,你要么进行批量分析,没有人真正关心查询时间(大多数企业);或者你在做流媒体(优步、脸书和 kin),在这种情况下,查询时间至关重要,但数据总量很大——每个用户只看到或使用很*一部分,并且后台正在进行批处理作业。
我正在开发一个 web 应用程序,该应用程序使非数据科学家用户能够实时构建和可视化地理数据的复杂分析,随着我们的数据和用户以及我们产品复杂性的增长,我们不得不修改堆栈以满足性能标准。我们的问题似乎应该是一个常见的问题,但奇怪的是,在用户友好的时间框架内对大量数据进行密集只读计算的指导非常少。
How analyses look in the web app
一年前,我还不是大数据领域的专家,这个领域有足够多的工具、术语和观点,很难知道从哪里开始。我还不知道所有的答案,但我已经想出了足够的办法,可以试探性地、谦恭地帮助其他人朝着对我们有用的堆栈前进。
失败 1:幼稚的 Postgres
首先,我会说不到万不得已不要修改你的堆栈。这可能是数据应该被视为大的时候——当您现有的基础设施难以应对时。我们愉快地用 SQL 做了很长时间的事情。Postgres 是一个令人惊叹的数据库,我的经验是,通过正确的索引和构造良好的查询,可以实时聚合和查询多达 8000 万行的表。
(虽然我提到了地理空间领域,但在本文中,我并不是在谈论地理计算,比如使用 PostGIS 。它们在计算上非常昂贵,但是我们在最初的 ETL/数据摄取过程中完成了大部分工作。)
不幸的是,执行所有必要的数据库*护、找出正确的索引以及编写和重写查询可能相当痛苦。您还必须将数据正确地存储在整齐规范化的行和列中。
失败 2:反规范化
还是你?总的来说,保持 SQL 数据的规范化和单一的真实来源是好的,但是复杂和频繁的表连接会降低性能。由于我们无法再满足用户的需求,我们不得不停止愚蠢的查询,并对一些较大的表进行反规范化。比如说,
这需要我们在 ETL 步骤中做更多的工作,并确保良好的数据治理,但这大大提高了速度。为了在团队规模保持不变的情况下弥补额外的时间,我们从自托管 Postgres 迁移到 AWS Aurora Postgres。性能没有改变,但它确实消除了一些数据库管理难题。
失败三:极光
只不过这也带来了新的性能问题。我们的应用程序的最大特点之一是,它可以根据用户指定的标准,对城市的微*六边形区域进行评分和聚类。一个城市可能由 50 万个六边形组成;对于每一个妖术,用户可能想要根据其夜间居民和白天工作者的中值收入和心理特征,以及它离最近的星巴克有多远来评价它。这需要大量的数据和计算。
迁移到 Aurora 让我们失去了将数据保存在自己机器的内存缓存中的能力。当不同的用户试图依次或者更糟的是同时给不同的城市打分时,数据被拉入(大概是从 S3)并从我们的虚拟机中弹出。这种数据加载时间,就像某种页面抖动一样,大大超过了计算时间:最终结果是,当数据可用时,一个城市的得分需要 3 分钟——对于打算实时进行的事情来说,这本身不是一个很好的结果——迅速增加到 10 分钟或超时。
现在,在大数据领域,我可以说,我并没有参与太久,目前“没有人因为收购 IBM 而被解雇”的是 Apache Spark。我努力着手创建一个 Spark 机器集群,看看它是否能有所帮助。
由于我们现在处理的表有数亿行,Postgres 运行缓慢,如果我们的应用程序要扩展,就必须对数据进行分区,并在多个节点上进行计算。
次要胜利 1:集群
多亏了 Kubernetes 和 Kops,在 AWS 上创建一个集群并不困难。
此时,您将获得一批新的 AWS 资源,包括集群主机和计算节点的实例。Docker 容器可以部署到这些实例中,由于 Kubernetes magic,它们将能够相互通信,与同一 VPC 上的其他机器通信,如果您选择通过暴露的负载平衡器与外界通信。
借助 Helm ,我能够快速启动并运行一系列 Spark 节点,以及一些用于 HDFS 文件存储的 Hadoop 节点。
失败 4:火花
我发现 Spark 很难管理,很难使用(它都是 Java 的,并且是为 Java 应用程序设计的,尽管 PySpark 的承诺可能会让您相信),而且总体来说没有那么快。
我确信 Spark 可以在一些人的批处理工作流中发挥作用,并且我知道它也有流扩展。然而,即使是简单的工作也需要几分钟来启动机器,这使得它在实时用例中毫无用处。
此外,HDFS 跑得并不快,现在我们有了 S3,这看起来有点无关紧要了。
此外,如果你像我一样来自 Python 生态系统,就不可能不去想念我们所拥有的大量工具。如果你是这样的人,并且你今天正在开始或发展一个大数据项目,我知道有一个更好的方法。
胜利:与 Dask 一起分发*猫
Pandas 处理数字数据的速度已经是最快的了。数组计算以本机速度进行(感谢 Cython ),并且经常利用向量指令(感谢 NumPy)。
尽管如此,我一直认为 Pandas 实际上是用于处理数据的 ETL 和分析部分;更像是一个数据科学工具,而不是一个可以部署到生产中的库。我错了:
*猫已被广泛应用于生产和金融领域
Dask ,Anaconda 背后的同一批人制作的分布式计算库,将大型数据帧划分到不同的节点上,在这些节点上调度并行计算(构建一个图,像 Spark 一样将计算延迟到最后一分钟),收集结果并管理分布式数据。它与*猫集成在一起,并且在很大程度上可以与*猫互操作,所以一起工作是一种乐趣。
(不是 100%;有些事情,例如在多列上索引一个数据帧,对于一个分区的数据帧没有意义)。
而且速度很快:每个节点都利用了 Pandas 及其矢量化的代码。分布式计算不是免费的;Dask 需要一些时间和网络延迟来构建图形和调度每个节点的计算,以及在最后合并/减少数据。如果能够将整个数据帧放入内存,基本的 Pandas 会更快——如果我们扩展我们的基本机器,这是可能的,但这不会永远持续下去:我们仍然需要在某些时候水平扩展我们的平台。
用 Dask 编码很大程度上是熟悉的。例如,下面是 SQL SELECT MAX(col + col2) FROM table WHERE zip_code IN ('94105', '94106') AND day_of_week IN (1,2,3)
的替换
from dask.distributed import Client
import dask.dataframe as dd
c = Client('172.x.x.x:8786')
df = dd.read_parquet('s3://my-bucket/mydatafile.parquet')
df = c.persist(df)
subset = df[df["zip_code"].isin(['94105', '94106']) & df["day_of_week"].isin([1,2,3])]
df["sum"] = df["col1"] + df["col2"]
print(df["sum"].max().compute())
将 Dask 部署到我之前制作的 Kubernetes 集群中也是相当容易的:他们有自己的掌舵图记录在这里。我们的基础设施现在看起来像这样:
- 单片 Node.js 后端
- 它调用 Python 微服务(用 Flask 构建,并将任务队列与 SQS 集成)
- 连接到集群并指示节点
- 从 S3 下载他们的数据部分(使用预先分区的 Parquet 文件非常快,因为从每个节点的读取是并行发生的)
- 用 Dask/Pandas/NumPy 处理其数据
- 并向后端返回一个 JSON 响应,后端将其转发给客户端 webapp
在 Postgres 中需要几分钟的分析,如果需要从持久存储中读取数据,则通常需要更长时间,现在不到 30 秒就可以返回到客户端。
结论
如果你有钱花,尤其是如果你还没有证明产品/市场适合,就去找供应商解决方案。一个快速的、面向列的内存 SQL 数据库不需要对我们的流程和代码做太多的修改。
否则,对于作为 SaaS 的一部分实时处理大数据,我建议看看 Dask 是否能满足您的需求:它速度快,可水平扩展,允许您使用您习惯的相同库以相同的方式编写代码,并且它目前正在生产中使用(至少被我们使用)。
显然,我认为 Dask 杀死了 Spark,但是如果你感兴趣的话,Dask 的作者确实给出了一个更微妙的观点。
傅立叶变换及其数学
原文:https://towardsdatascience.com/fourier-transformation-and-its-mathematics-fff54a6f6659?source=collection_archive---------1-----------------------
信号分解、时域和频域
source
简介
傅立叶变换(FT)将信号分解成组成它的频率。
这是什么意思?
所以,我们来举个例子。让我们有一个信号 S1。
S1: x-axis is time and the y-axis is amplitude
如果我们想在某个特定的时间测量这个信号的强度。我们用它的 振幅 来衡量。
所以,信号 S1 的振幅是 1
如果我们对另一个信号进行同样的操作,选择相同的时间点,测量其幅度。让我们有另一个这样的信号 S2
S2: x-axis is time and the y-axis is amplitude
同样,信号 S2 的幅度是 2
现在,我们同时发出这两个信号(S1 和 S2)会发生什么?
因此,当我们在同一时刻发射这两个信号时,我们会得到一个新信号,它是这两个信号幅度的之和。这是因为这两个信号被加在一起。
S3=S1+S2: x-axis is time and the y-axis is amplitude
所以,S3 的幅度= S1 的幅度+S2 的幅度= 1 + 2 = 3
所以,信号 S3 的幅度是 3
现在,有趣的问题是:
如果只给我们信号 S3(也就是信号 S1 和 S2 之和)。我们能恢复 S1 和 S2 的原始信号吗?
是的。这就是傅立叶变换的作用。它接收一个信号,并将其分解成组成该信号的频率。
在我们的例子中,傅立叶变换会将信号 S3 分解成其组成频率,如信号 S1 和 S2
但是,我们怎么才能恢复原来的信号呢?傅立叶变换能为我们做什么?
y-axis is the strength of the signal (amplitude)
假设上图中的三个信号是 S1、S2 和 S3,当我们将这三个信号合并在一起时,我们得到的是红色的信号,实际上是 S1+S2+S3。
傅立叶变换的作用是将我们从时域转移到频域。
万一有人在疑惑,我们要从频域回到时域怎么办?
我们可以通过使用逆傅立叶变换(IFT) 来实现。但我们不会在本文中讨论这个问题。
信号产生和相移
如果我们想描述一个信号,我们需要三样东西:
- 信号的频率,它显示了在我们的周期内发生了多少次。
- 振幅显示信号的高度或信号的强度。
- 相移至于信号从哪里开始。
我们举的第一个例子非常简单,每个信号都有相同的频率和相位差,只有不同的幅度。
现在我们来看一个稍微复杂的例子,我们来看上面例子中的单个信号,因为为了更好地理解傅里叶变换,我们需要仔细观察单个信号。
下面是我们在上面看到的原始信号。
Signal 1
Signal 2
Signal 3
频率:如果我们仔细观察这三个信号,我们会注意到所有三个信号的频率都是不同的。
如果在同一时间段内,信号 1 中有 n 个波,则信号 2 中有 2n 个波,反之亦然。
相位:同样,当我们仔细观察信号实际上是从哪里开始的。我们会发现,当信号 1 开始于(0,0) 时,信号 2 开始于(-0.5,0) ,如果我们追踪波形以在 0 处与 y 轴相交。因此,在 0,我们已经有了信号的最大幅度。这就是我们所说的相移。
振幅:三个信号的振幅不同,信号 1 的振幅为 1,信号 2 和信号 3 的振幅分别为 2 和 3。
这一切都包含在一个优雅而超级简单的数学公式中。因此,在上述示例中,如果 x 轴表示为 x,y 轴表示为 y,我们可以将y
生成为t
的函数,如下所示:
使用这个公式,我们可以产生我们想要的任何类型的信号,然后我们可以将它们合并在一起并进行处理。例如,如果我们合并信号 1、2 和 3。我们会得到这样的信号:
Signal 1 + Signal2 + Signal3
傅立叶变换背后的数学原理
傅立叶变换背后的主要思想是:
时域中的任何连续信号都可以由一个无限正弦系列唯一且明确地表示。
这意味着什么?
这意味着,如果我们有一个信号,并且这个信号是由某个函数x(t)
产生的,那么我们可以得出另一个函数f(t)
,这样:
因此,信号有多强并不重要,我们可以找到一个类似于f(t)
的函数,它是一系列正弦曲线的之和,实际上可以完美地代表信号。
现在的问题是,我们如何在上面的等式中找到系数,因为这些值将决定输出的形状,从而决定信号。
因此,为了获得这些系数,我们使用傅立叶变换,傅立叶变换的结果是一组系数。因此,我们使用X(F)
来表示傅立叶系数,它是频率的函数,我们通过求解积分得到,如下所示:
这个积分中棘手的部分实际上是表示复数的i
。所以,我们大概记得i² = -1
或者i = √-1
。记住复数的形式是a + *i*b
可能会有所帮助。所以,它有一个实部和虚部。
此外,当我们实际求解上述积分时,我们会得到这些复数,其中a
和b
对应于我们要寻找的系数。
然而,我们确实有三个问题需要处理:
- 如何应对
*i*
。 - 如何处理离散信号?
所以,我们从第二个开始。
要理解离散傅里叶变换,我们首先需要理解如何对连续信号进行采样?
根据*基百科介绍,在信号处理中,采样是将连续时间信号还原为离散时间信号。下面是一个信号形式如何随采样速率变化的示例:
假设原始信号是在一秒钟内振幅为 2、频率为 5 的信号:
sampling rate = 1000
现在,当我们降低采样率时,让我们看看信号的形状是如何变化的:
sampling rate = 50
当我们进一步降低采样率时,我们得到:
sampling rate = 15
所以,底线是 : 采样速率越高,信号质量越好,我们也可以区分更多频率。
现在,我们知道了如何对信号进行采样,接下来我们来看看称为离散傅里叶变换的算法的修改。
离散傅里叶变换
时域中任何长度为 N 的采样信号都可以由一系列有限的正弦曲线唯一且明确地表示。
所以,在我们的新定义中,我们不用再处理无穷大了。
有什么区别?
在标准傅立叶变换中,我们使用时间函数x(t)
来产生连续信号。在离散情况下,我们没有函数,只有数据集,即通过对连续信号进行采样获得的一组点。因此,我将使用{x}
来捐赠一个数据集,使其包含来自采样的读数,这样:
离散傅立叶变换将为我们做的是它将把{x}
的数据集变换成另一个包含傅立叶系数的数据集{X}
,使得:
如果我们看一下傅立叶变换的定义,{X}
中的每个X
都是一个复数,它包含频率的a
和b
分量。
但是,两个数据集 ***{x}***
和 ***{X}***
怎么会有相同的长度呢?
如果我们想一想,驱动{x}
数据集长度的是采样率,因为在一段时间内,我读取的数据点数量正好是采样率,对吗?如果我们考虑另一个数据集{X}
,我们说过频率是单位时间内出现的次数。因此,如果我以某一频率进行采样,我无法识别频率高于采样频率的信号,因为我们没有获得足够的数据点。
因此,如果我们以非常低的采样速率获得非常高频率的信号,我们根本无法识别这些信号。因此,我们可以通过应用傅立叶变换识别的频率数量实际上也是由采样速率决定的。
因此,现在我们有了数据集{x}
,我们将得到{X*k}*
,这样它就是{X}
中的一个元素,它们是我的傅立叶系数,这样:
Fourier Transform
这本质上就是离散傅里叶变换。我们可以进行这种计算,它将产生一个形式为a + *i*b
的复数,其中我们有两个傅立叶级数的系数。
现在,我们知道如何对信号进行采样,以及如何应用离散傅立叶变换。我们想做的最后一件事是,我们想通过使用所谓的欧拉公式来去掉复数*i*
,因为它在mllib
或systemML
中不受支持,该公式表示:
Eulers Formula
所以,如果我们把欧拉公式代入傅里叶变换方程,我们得到
我们还知道cos(-θ) = cos(θ)
和sin(-θ) = -sin(θ)
,如果我们在上面的等式中使用它,等式可以简化为:
实际上,我们可以将上述等式分解为两部分,即:
现在,如果我们将上面的等式与一个复数的等式a + *i*b
相比较,那么我们得到相应的值为:
所以,现在我们可以把这些值放入*f(t)*
的方程中,得到结果。
结论
在实践中,我们使用一种称为快速傅立叶变换的离散傅立叶变换的微*修改,因为离散傅立叶变换非常简单、基本且缓慢。如果我们真的想在生产环境中做些什么,这是不合适的。离散傅立叶变换的计算复杂度是二次时间O(n²)
,用于比较的快速傅立叶变换是准线性时间O(nlogn)
。快速傅立叶变换通过利用傅立叶变换中的不对称性来实现这一点。
框定狩猎…
原文:https://towardsdatascience.com/framing-the-hunt-913f9a0eae6a?source=collection_archive---------7-----------------------
这是我如何成功地从地球科学转向数据科学系列的第三篇文章。来刷新一下,这里是第一集和第二集。
好了,现在每个人都赶上了,我给你们留下了一个悬崖衣架。我去了一个编码“训练营”,非常热衷于网络,但是从来没有真正去了解我如何选择寻找哪些机会。我拥有石油和天然气行业之外很少有人能与之相关的技能和丰富的行业经验,以及越来越多的人脉。
对于我的正式求职,我有一套宽松的目标,可以缩*为两个标准:
- 在西雅图找工作(最好是我爱上了西雅图)
What geoscientist wouldn’t fall in love with their very own volcano?
2.一些支持“技术”产业的东西(不管 T4 真正的意思是什么)
好吧,含糊,我知道。我可以用很多方法来寻找答案。就其最基本的形式而言,找工作有两种方法,一种是窄范围的,一种是宽范围的。作为一名数据科学家,我将简要回顾一下 我对这些因素的 定义,以及它们如何影响我的求职目标。
缩*范围
这种方法适合那些确切知道自己想要什么并且不会降低要求的人。
更明确地说,我将它定义为具有以下标准:
- 有一个“数据科学家”的头衔或胸围
- 角色完全符合个人对数据科学的看法(例如,机器学习重点或“大数据”要求)
- 从事特定行业(如初创企业、公司、顾问)
优点 :
- 你确切地知道你想要什么,并能使你的面试策略与之相匹配。
- 你会有你喜欢的头衔和角色,但是你可能会被限制在你所在的特定公司。
缺点 :
- 你为那些没有正式贴上“数据科学家”标签,但实际上是数据科学家的机会留下了盲区。回想一下,直到 2008 年左右,数据科学这个术语才被完全创造和接受。一些组织仍然使用较老的术语,如分析师或统计师,而不是数据科学家。
- 你可能最终会把自己定位成一个专家,未来的行动没有多少回旋的余地。
- 你可能最终会让你原本喜欢的美好事物与你擦肩而过。与此相关的还有“未知,未知”类别。你不知道你不知道什么。听听推销,你可能会找到你真正喜欢的东西。
谁应该考虑这种策略:
- 一个有可靠理由支持他们调查的人。你以前在类似的组织中担任过类似的角色。大多数来自石油和天然气行业的地球科学家还不知道这一点。如果你有,就把自己当成“独角兽”吧。
- 在数据科学领域寻找第二份工作(或以后工作)的人。我通常不会向这个领域的新人推荐这种策略,即使是对我们这些处于职业生涯中期的人。
再说一遍,大多数人都不完全属于这一类。求职者希望认为他们知道自己想要什么。见鬼,有一段时间,我以为我很清楚自己想要什么。但是,我建议采用第二种方法,即大范围方法。
最终,我会认为<10% of geoscientists who are pivoting to data science will fall into this category. Of this, most of them will be going into data science roles within the energy industry.
Wide Scope
For most experienced professionals pivoting to the field of data science, the wide scope provides the best “bang for your buck”.
In this approach a job seeker:
- Casts their net wide. Look into all titles holistically. Data Scientist, Data Analyst, Business Analyst, Decision Scientist, Business Systems Analyst, Business Intelligence…
- Reads into the details. Look into job descriptions holistically. Not all job descriptions are created equal. One company’s Data Scientist is another company’s Data Analyst. Another company’s Data Scientist is simply a Data Analyst at another.
- Looks at a variety of opportunities across business types and industries.
有利 :
- 更多的选择和机会。这种方法可以让你在公司面试你的时候控制和面试他们。因为你有更多的选择,它允许你在驾驶座上。
- 你可以开始承认未知,未知列表。了解你以前从未接触过的行业和职能。例如,作为一名勘探地球科学家,我打赌你从未直接与社交媒体营销团队打交道。你甚至可能会被它吓跑。你和他们谈过了吗?在你尝试以前的大学生活之前,不要把他们排除在外。
- 你仍然可以从一个狭窄范围的方法中得到你想要的东西。这些工作仍然存在,你仍然可以申请。这就需要和更多不同的人交谈,来强化你对下一个角色的期望。
弊 :
- 一些职称可能会让你更难转换到另一家有不同职称的公司。真的不应该有关系,角色和职责应该为王,但如果你是冷申请(即没有内部推荐),有时会归结为简历排序的算法。
谁应该考虑这种策略:
- 人人 。大家都要考虑一下。如果你没有,你就没有适当地缩*你的范围。开始大,削减,如果你必须。
最终,我相信这应该是 90%以上转向数据科学的地球科学家的策略。除非你是一个“独角兽”,拥有无缝过渡到一个新行业或留在能源行业的背景,否则你应该使用这种策略。
这个分析对我个人来说意味着什么?
让我们回到我在本文开始时提出的两个主要目标:
- 在西雅图找工作(最好是,我爱上了西雅图)——我把这个扩展到了许多城市,包括波斯顿、三藩市/海湾地区和 DC 地区
- 支持“技术”行业的东西(不管它真正的意思是什么)——这扩展到了“技术”、金融、保险等等,我没有特别歧视任何行业,并听取了每一个向我抛出的建议
既然我们已经想好了范围。你实际上是如何理解和阅读数据科学领域的工作描述的?你需要整齐地满足所有的需求吗?如何申请每个职位?你应该对公司进行个性化设计还是使用一种简单的方法?
这是一个很大的难题。下周,我将介绍我在寻找第一个数据科学职位时最常看到的不同类型的“数据科学”帖子。
继续进入第 4 集、第 5 集、第 6 集、第 7 集和第 8 集。
关于“独角兽”和“紫色松鼠”的描述,请参见这篇文章。
极端类别不平衡下的欺诈检测
原文:https://towardsdatascience.com/fraud-detection-under-extreme-class-imbalance-c241854e60c?source=collection_archive---------3-----------------------
数据科学中的一个热门领域是欺诈分析。这可能包括信用卡/借记卡欺诈、反洗钱或网络安全。所有这些领域的一个共同点是阶级不平衡的程度。一般来说,交易总数中只有一*部分是真正的欺诈。以信用卡诈骗为例。在给定用户的 1000 次交易中,只有 1 次是真正的欺诈。这可能是因为客户的信用卡信息被盗,或者供应商的 PoS 设备受损。需要尽快抓住这个问题,以最大限度地减少对客户和供应商的经济损失。同时,我们需要注意假阳性。很自然,如果信用卡在没有发生实际欺诈的情况下被银行冻结,信用卡所有者会不高兴。在这篇博客中,我将介绍一些常用策略,用于揭露金融和网络不端行为,同时最大限度地减少假警报。
无监督学习模型
当交易记录没有被标记时,无监督学习模型是有用的。对于互联网流量数据来说尤其如此,因为没有明确的方法来判断特定的互联网交易本质上是否是恶意的。在这种情况下,异常检测是常见的。
异常检测
想象你在浏览互联网时有某种行为。你在浏览 YouTube 时传输了一定量的数据,通过脸书信使发送了一定量的数据。现在,让我们将它汇总到整个组织中。平均而言,端点将具有可预测的端口使用率。现在,假设其中一个端点碰巧使用某个端口(它通常从不使用)来访问服务器端口(该端口可能因发送恶意软件而被列入黑名单)。这可能是潜在的端口扫描,甚至是公司网络上的 torrent 使用。另一个例子可能是一个或多个端口的突然高使用率,这表明 DDoS 攻击。有很多无监督学习算法,从 K-Means 到高斯混合模型。
对于时间序列数据,可以查看数据点的标准偏差来寻找异常值。时间序列中的某些异常值可能显示不同的模式,可以使用傅立叶变换或隐马尔可夫模型来检测。
更多细节,请查看我关于基于聚类的无监督学习的博客。
监督学习模型
某些欺诈检测数据集带有标签。就拿信用卡诈骗来说吧。如果银行怀疑有欺诈行为,他们可以打电话给持卡人,检查卡是否真的被盗。该信息可以用作新模型构建的训练数据。正如我将在本节中介绍的那样,监督学习模型也有自己的一系列机遇和挑战。
标签错误的数据
在欺诈检测问题中,数据集已经严重失衡。想象一下,除此之外还有贴错标签的数据?可惜现实世界没有 Kaggle 干净。你会得到极其杂乱的数据。我个人的一般策略是使用 K-Means 来可视化数据,以检查标记是否真的有意义。
然而,这是非常主观的,将取决于用例。如果做得好,我们可以得到一个更可靠的数据集来训练我们的模型。不利的一面是,有目标泄露的可能。
模型复杂性
自然,对于大多数欺诈检测用例,模型往往更复杂。考虑到所需的粒度和特性工程水平,简单的线性回归可能没有帮助。也就是说,人们需要意识到过度拟合他们的数据集。学习曲线通常有助于检查模型是否具有高偏差或高方差。
如果模型是高度偏向的,那么就有可能研究更复杂的东西,比如决策树、随机森林甚至神经网络。通常,在金融机构中,通常使用系综模型。某些工程特征在单独的模型上工作得最好(通常是由于方差的巨大差异)。或者甚至将无监督学习模型与有监督模型结合使用(特别是当错误标签的可能性很大时)。
关于学习曲线、集合模型和其他基础知识的复习,请查看我的数据科学面试指南。
惩罚模型
你可以使用相同的算法,但给他们一个不同的角度来看问题。惩罚分类对模型施加了额外的成本,用于在训练期间对少数类进行分类错误。这些惩罚会使模型偏向于更多地关注少数群体。通常,类别惩罚或权重的处理专用于学习算法。有惩罚版本的算法,如惩罚 SVM 和惩罚 LDA。
性能指标
评估模型性能最常用的方法是分类得分。然而,当只有 2%的数据集属于一个类别(欺诈),而 98%属于其他类别(非欺诈)时,错误分类分数实际上没有意义。你可以达到 98%的准确率,但仍然没有发现任何欺诈行为。此外,请记住,在处理欺诈时,我们关心误报。在这一部分,我将讨论一些可供选择的性能指标。
混淆矩阵
在分析误分类时,混淆矩阵是一种常见的偏好。矩阵的每一行代表预测类中的实例,而每一列代表实际类中的实例
对角线代表已被正确分类的类别。这很有帮助,因为我们不仅知道哪些类被错误分类,还知道它们被错误分类为什么。
精确度、召回率和 F1 分数
为了更好地了解错误分类,我们经常使用以下指标来更好地了解真阳性(TP)、真阴性(TN)、假阳性(FP)和假阴性(FN)。
精度是正确预测的正观测值与总预测正观测值之比。
回忆是正确预测的正面观察值与实际类中所有观察值的比率。
F1-Score 是准确率和召回率的加权平均值。
F1 分数越高,模型越好。对于所有三个指标,0 是最差的,而 1 是最好的。
ROC 曲线
接收器操作特性或 ROC 曲线是欺诈分析(以及数字信号处理)领域中非常流行的指标。
45 度线是随机线,其中曲线下面积或 AUC 是 0.5。曲线离这条线越远,AUC 越高,模型越好。一个模型能得到的最高 AUC 是 1,其中曲线形成一个直角三角形。ROC 曲线也可以帮助调试模型。例如,如果曲线的左下角更接近随机线,则暗示模型在 Y=0 处分类错误。然而,如果右上角是随机的,则意味着误差发生在 Y=1 处。此外,如果曲线上有尖峰(而不是平滑的),这意味着模型不稳定。对付诈骗模特,ROC 是你最好的朋友。更多信息,请阅读接收器工作特性曲线解密(Python 语言)。
重新取样
我的最后一个建议是重新采样。如果有可能获得更多的数据来使这些类更加平衡,这将是最简单和最好的方法。如果没有,创建合成数据也是一种可能。本节将介绍这些方法。
过采样
对模型中的欺诈记录进行过采样有助于改进分类。但是,要意识到它需要代表真实世界(相对于非欺诈,欺诈实际上很少发生)。SMOTE 和 ADASYN 是这方面的常用算法。自动编码器也可用于创建合成欺诈数据。
欠采样
欠采样非欺诈是另一种被使用的技术。基于聚类方法(例如 K-Means)生成质心是一种常见的策略。
结束语
理想情况下,我在这篇博客中提到的内容将帮助你想出更好的方法来应对欺诈模型(无论是工作、学校还是 Kaggle 竞赛)。我提到的许多事情可以在我的其他博客中找到更多细节:
[## 数据科学面试指南
数据科学是一个相当大且多样化的领域。因此,做一个万事通真的很难…
towardsdatascience.com](/data-science-interview-guide-4ee9f5dc778) [## 基于聚类的无监督学习
无监督机器学习是一种机器学习任务,它从神经网络中推断出一个描述隐藏结构的函数
towardsdatascience.com](/clustering-based-unsupervised-learning-8d705298ae51) [## Scikit-Learn 上决策树和集成的研究
现在科技界最热门的话题之一是机器学习领域。应用范围从…
medium.com](https://medium.com/@sadatnazrul/study-of-decision-trees-and-ensembles-on-scikit-learn-e713a8e532b8)
池保护器:利用网络分析防止支付欺诈
原文:https://towardsdatascience.com/frauddetection-f801b781410b?source=collection_archive---------14-----------------------
一个典型的组织会因欺诈损失大约5%的收入。对于规模较*的企业来说,情况可能更为严峻,因为它们通常受到的保护更少,承受损失的能力也更弱。通过Insight Data Science Fellowship,我为一家支付服务初创公司提供咨询,该公司因欺诈遭受了重大损失。这家公司,我们称之为公司 A,为用户提供了一个平台来集中他们的钱进行一次购买。例如,假设爱丽丝和鲍勃要去克里斯家参加聚会,他们都想分摊费用。在这种情况下,Chris 创建了一个池,他、Bob 和 Alice 都参与其中。克里斯然后取出钱来支付聚会的费用。然而,有可能稍后爱丽丝决定她不想为聚会付钱。她可以对自己向泳池支付的费用提出异议,而不是要求克里斯退款。如果她拿到了钱,而克里斯已经提取了资金池的余额,A 公司就只剩下支票了!这样的交易被称为退款。
- User avatars in this picture are created by Freepik (https://www.freepik.com/free-photos-vectors/people)
按存储容量使用计费旨在保护消费者。例如,在上面的案例中,如果 Chris 多收了她的钱并且拒绝退款,Alice 可以对她的付款提出异议。尽管如此,一些用户滥用退款流程,故意从公司 A 偷窃。由于不可能了解公司 A 每笔退款交易背后的真实动机,我从公司的角度将所有退款视为欺诈交易,因为它们都会给公司造成直接损失,并使用这种启发式方法在数据中找到可能指出真正欺诈的模式。
概观
在 2017 年的前三个季度,我所工作的公司因退款而损失了大约一半的交易费收益。记录显示,不到 1%的用户和不到 1%的交易会导致这种严重的损失。为了防止潜在的退款,该公司已经开始努力提取特定于用户和交易的特征,以建立一个欺诈检测模型。鉴于欺诈通常不是一个孤立的事件,我认为利用用户网络环境中的用户信息来增强模型是有价值的。具体来说,我发现用户的池社区和社交网络影响他们欺诈行为的机会,这可以用来提高公司 A 预测欺诈的能力。
泳池社区
在公司 A 的平台上进行的每一笔交易都将一群用户联系在一起。经过多年的支付,一个丰富的、潜在的强大的网络结构开始形成。关于这些泳池社区的第一个问题是:泳池的大*重要吗?下面是涉及按存储容量使用计费的池与完全合法的池的池大*的频率分布。总的来说,合法交易更有可能发生在中等规模的池中,有趣的是,有退款的大部分池的规模为 1。一号池一开始就是奇怪的实体(人们试图与自己分担成本吗?)这强烈表明用户只是利用它们来实施欺诈。下面的数据表明,阻止甚至标记从 1 号池中的提款将会减少三分之一以上的退款频率,同时减少不到 10%的合法交易。假设交易金额和费用不会随着池的大*而变化太大,这些数字表明,与交易费用损失相比,像阻止大*为 1 的池这样的简单政策转变将节省大约两倍的费用,从而对公司的底线产生重大影响。
对于更大的池,分析池的组成可以让我们了解人们如何相互影响。将罪责归咎于个人可能取决于他们所交往的人,而不是他们犯下的任何欺诈行为,这种行为被称为“牵连犯罪”。下图显示了每个池中涉及按存储容量使用计费的欺诈用户与完全合法用户的百分比分布。按存储容量使用计费池组中有很大一部分池包含超过 10%的欺诈用户。这强烈表明,处于欺诈环境中会增加人们申请退款的倾向。
社交网络
除了池社区,用户的社交网络也可能与他们提交退款的机会有关。我们鼓励该平台的用户使用他们的脸书帐户进行注册。下面我展示了脸书的欺诈用户友谊网络,其中圆圈上的每个点代表一个用户,每个用户都标有一种颜色,表示他或她已提交的退款数量。连接线代表用户在平台内的脸书连接。与上一节显示欺诈用户倾向于群集相反,当涉及到实际的社会联系时,欺诈用户似乎是独立的。此外,有许多欺诈用户在记录上没有一个脸书朋友,可能是因为他们选择不将他们的脸书账户链接到该公司的平台。
Facebook friendship network of fraudulent users
我们可以使用每个用户的“度中心性”来量化用户在网络中的重要性,即用户的朋友数量除以网络中的用户总数。下面的分布显示,与合法用户相比,在按存储容量使用计费用户组中没有朋友的用户的频率要高得多。合法用户往往有更多的朋友,如果我们进一步查看二级连接,并测量用户朋友的平均朋友数量(分布如下所示),情况也是如此。换句话说,与欺诈用户的朋友相比,合法用户的朋友也有更多的朋友。
预测退款交易
上面讨论的网络特性本身显然是强大的。为了利用他们的集体力量,我将他们与公司 A 已经拥有的基于用户和基于交易的功能结合到一个单一的机器学习模型中。选择了一个随机森林模型来将每个交易分类为欺诈或合法。使用网格搜索来调整模型参数,这产生了具有 1300 棵树和最大深度 10 的模型。受试者工作特征(ROC) 曲线(左下)显示该模型具有很高的预测性。“完美”模型的曲线下面积(AUC)为 1.0,表明它对每个样本进行了完美分类,而“抛硬币”模型的 AUC 为 0.5。我训练的最终模型的 AUC 为 0.97。
由于欺诈的成本(每月约 4800 美元)比调查合法交易的成本(每月约 300 美元)高得多,A 公司主要对实现高召回率的模型感兴趣。混淆矩阵(中上)显示最终模型的召回率为 74.8%。与 61.0%的无网络功能的原有型号召回相比,这相当于在公司当前规模下,每年大约增加价值 8,600 美元的欺诈防范。虽然模型的精确度从 74.3%下降到 53.8%,但欺诈防范节省的成本远远超过了增加的调查成本。突出在此项目中构建的网络要素的重要性是它们的重要性-这些要素由模型中 4 个最重要的要素中的 3 个组成(上图最右侧仅显示了重要性> 0.08 的要素)。我工作过的公司已经在努力将这种模式纳入他们的平台,这将有助于调查人员在案件结束前标记案件,转化为实际的节约。
未来工作
在模型参数的网格搜索中,我当前的模型在优化过程中使用 AUC 作为度量。虽然这种选择可以产生具有高总体预测能力的模型,但我们可以使用 F_beta 分数来更好地优化模型,以降低退款造成的总损失,同时考虑调查成本。F_beta 分数是精确度和召回率的加权调和平均值。一方面,召回率高的车型可以减少退换货带来的损失;另一方面,模型的精确性也很重要,因为每一项交易的调查都伴随着成本。因此,为了平衡损失和成本,需要以 F_beta 作为优化度量来网格搜索更好的模型。F_beta 分数中的权重 beta 可以从退款的平均损失和调查的平均成本中得出。我与该公司的未来工作将是利用损失和成本的知识来优化模型,以便我们可以降低退款造成的总损失,同时最大限度地减少合法交易的标志。
关于惠宗 ( )领英 )
我目前是纽约市的 Insight 数据科学研究员,也是西北大学应用物理学的博士生。我的研究生研究主要集中在用于基因治疗的聚合基因递送系统的计算研究。在使用深度学习技术开发聚合物凝胶化的预测模型时,我对数据科学产生了兴趣。在这个项目中,我看到了数据驱动的方法如何解决有趣和相关的问题,我期待着继续沿着这个方向前进!
冻结 Keras 模型
原文:https://towardsdatascience.com/freezing-a-keras-model-c2e26cb84a38?source=collection_archive---------2-----------------------
如何为服务和其他应用程序冻结模型
“landscape photography of snowy mountain and body of water” by Joel & Jasmin Førestbird on Unsplash
简介
Keras 已经成为工业界和学术界开发和测试神经网络的主要 API 之一。由于其各种后端可能性,它结合了用户友好的语法和灵活性,这意味着你可以用 TensorFlow,Theano 或 CNTK 编写并在 Keras 中调用它。
一旦你用 Keras 设计了一个网络,你可能想在另一个 API 中,在网络上,或者在其他媒介上服务它。做上述许多事情的最简单的方法之一是使用预先构建的 TensorFlow 库(例如用于 C++环境中的模型推理的 TensorFlow C++ API )。为了做到这一点,由于这些 API 的后端工作方式,您很可能不得不“冻结”您训练过的 Keras 模型。不幸的是,为了轻松地做到这一点,您必须在 Keras 的 TensorFlow 实现中重新训练您的模型。然而,幸运的是,如果你知道你的目标是什么,这个过程非常简单,这要归功于 Keras 集成到 TensorFlow 的方式,以及 TensorFlow 为此任务提供的各种其他材料。
当我最初研究如何在 C++环境中为模型提供服务时,我从类似的帖子中找到了几个可能的答案,比如关于堆栈溢出的帖子,以及关于介质的帖子。类似地,一些人已经制作了各种很棒的开源包来做到这一点,比如 keras2cpp 。然而,我发现这些文章缺乏一些关键的细节,并且经常使用复杂的技术,这些技术在写作时是必要的,但由于 TensorFlow 的更新,这些技术已经大大简化了。
我希望这篇文章提供了一个简单的、最新的演练,展示了如何为任何一般需求冻结 Keras 模型,而不仅仅是为了在 C++环境中服务。虽然本文中描述的方法是专门为转换 Keras API 中编写的模型(本机或 TensorFlow 实现)而编写的,但它也可以用于任何用本机 TensorFlow 编写的模型。
为什么我需要转换我的模型?
如果您的模型经过训练并保存在 Keras API 中,那么您可能已经保存了模型的 hdf5 文件,其中网络架构和权重一起保存在一个文件中。这个文件可以被调用并加载回 Keras API 进行推理。然而,遗憾的是,TensorFlow APIs 无法识别这种文件类型,而且存储、加载和执行推理也不必要太大。
同样,如果你在 TensorFlow Python API 中编写一个模型,那么训练过程将使用 Google 的 ProtoBuf 库保存一个 TensorFlow 图,以及一系列检查点文件。该图存储了关于带有Variable
ops 的网络架构的信息,而检查点文件包含了训练不同阶段的权重值(取决于训练期间您的会话检查点的频率)。这些通常可以在 TensorFlow Python API 会话中加载用于推断,在此期间,来自检查点文件的权重被插入到图中的Variable
ops 中。然而,当仅仅执行推理时,这是低效的。另一方面,一个保存的 Keras .h5
文件仅仅是图形和最终状态检查点文件的组合,同时仍然保持超参数存储为Variable
ops。(注:以上不需要详细了解,我只是给想要更详细解释的人补充一下。)
冻结模型意味着生成一个包含图和检查点变量信息的单一文件,但是将这些超参数作为常量保存在图结构中。这消除了保存在检查点文件中的额外信息,例如每个点的梯度,这些信息包括在内,以便可以重新加载模型并从您停止的地方继续训练。因为这在为纯粹用于推理的模型服务时是不需要的,所以它们在冻结时被丢弃。冻结模型是一个谷歌.pb
文件类型的文件。
要求
冻结推理模型的要求很简单,但是,根据您的应用程序,您可能需要安装各种其他包来实际执行推理:
- 将 Keras 与 TensorFlow 后端一起使用
- 尽管安装了 TensorFlow 应该可以自动运行,但您需要确保 TensorBoard 在您的计算机上运行
- 从 TensorFlow 存储库中,将 freeze_graph.py python 脚本复制到您的工作目录中。或者,您可以使用定制设计的
freeze_graph
函数,我们将在后面看到。
转换模型
为了生成包含必要信息的.pb
文件,TensorFlow 编写了freeze_graph.py
文件,该文件在被调用时将合并 TensorFlow 图形和检查点文件。使用这个 Python 脚本通常是明智的,因为它是由 TensorFlow 团队编写的,他们确保它可以与他们内部的文件格式一起工作。但是,为了使用它,您必须首先拥有正确格式的图形和检查点文件。Keras API 不会自动生成这个文件,所以您需要重新训练模型来生成它们。
有两种相对简单的方法来获取以正确格式保存的训练模型以进行冻结。如果您直接使用 Keras API,那么您将需要切换到在 TensorFlow 环境中实现的 Keras API。
注意:这应该只需要在导入阶段进行更改,例如,您将拥有from tensorflow.keras.layers import Convolution2D
而不是from keras.layers import Convolution2D
。
第一种方法调用模型,然后将其转换为 TensorFlow 估计器,后者将处理训练。第二个要求理解 TensorFlow 会话是如何工作的,因为这种方法训练网络就像你用本地 TensorFlow 编写的一样。实施这些训练方法后,您将能够运行freeze_graph
以获得正确的输出。
让我们通过一个例子来演示这个过程。在这里,我们将把一个简单的 Keras 模型转换成一个估计量,用于对 MNIST 数据集进行数字分类。
首先,我们在 TensorFlow 中实现的 Keras API 中构建模型,确保命名您的输入和输出层,因为我们稍后将需要这些名称:
Defining the model, note we do not define an input layer here since the type of input layer depends on which method you choose for training
选项 1:转换为估计值
一般来说,这种方法可能是两种方法中最简单的,但是,由于处理定制估计器的性质,它可以很快变得更复杂,这取决于您想要如何训练模型。如果您只熟悉原生 Keras API 中的训练模型,那么这是最相似的训练模型的方式。TensorFlow 1.4 引入了将 Keras 模型转换为 TensorFlow 估算器的功能,本教程对此进行了描述。
要将上述模型转换成估算器,首先使用 TensorFlow 中实现的普通 Keras API 编译模型,然后使用model_to_estimator()
函数:
Converting the model into an Estimator, here the checkpoint files and graph will be saved in the model directory
现在estimator_model
表现得像一个张量流估计器,我们可以相应地训练模型。有关如何培训评估员的指南,请参见文档。
对于训练,定义一个输入函数并相应地训练模型:
模型现在已经训练好了,并且graph.pbtxt
和检查点.ckpt
文件将保存在./Keras_MNIST
模型目录中。
选项 2:像原生张量流模型一样训练
另一种方法是通过启动张量流会话并在会话中训练来训练模型。这需要对会话如何工作有更详细的了解,这超出了本文的范围,我建议读者参考这个 MNIST 教程作为这种培训的例子。然而,与示例不同的是,您不需要在 native TensorFlow 中编写模型,相反,我们可以调用上面的模型,只需更改输入层:
剩下的就可以从教程中遵循了。
冻结模型
现在模型已经训练好了,图形和检查点文件也制作好了,我们可以使用 TensorFlow 的freeze_graph.py
将它们合并在一起。
注意:确保freeze_graph.py
与您想要冻结的检查点和图形文件在同一个目录中。
或者,我发现由摩根开发的简化版更不容易标记错误。
Simplified freeze_graph implementation by Morgan
此函数使用图形重新启动临时会话,以恢复最近的检查点。使用这种实现的另一个优点是,您不必确保指定了正确的检查点文件,或者处理语法上更加密集的freeze_graph.py
输入。
我们需要知道输出节点的名称,作为函数的引用点。这和我们用不用freeze_graph
的简化版是一样的。你给最后一层起的名字是不够的,打开 TensorBoard 会给出一个可视化的图形。
TensorBoard output showing input to ‘metrics’ node
在这个例子中,我们想要的是进入“度量”节点的张量,叫做output_node/Softmax
。
这将在模型目录中生成一个冻结的图形。
关键要点
- Keras 模型可以在 TensorFlow 环境中训练,或者更方便的是,变成一个语法变化很*的估计器。
- 要冻结一个模型,你首先需要生成检查点和图形文件,以便调用
freeze_graph.py
或上面的简化版本。 - TensorFlow 上有许多标记为 Keras GitHubs 的问题,以及关于冻结模型的堆栈溢出,其中许多问题可以通过了解需要生成的文件以及如何指定输出节点来解决。
- 输出节点可以很容易地从 TensorBoard 可视化中找到,但它并不总是你指定的最后一层的名称。
使用异构网络嵌入的朋友推荐
原文:https://towardsdatascience.com/friend-recommendation-using-heterogeneous-network-embeddings-54f95babdb13?source=collection_archive---------22-----------------------
想象一下史努比没有伍德斯托克或者卡尔文没有霍布斯,老友记没有瑞秋,蝙蝠侠没有罗宾或者无忌没有布鲁。社交平台的繁荣依赖于成员找到相关朋友进行互动的能力。网络效应是驱动应用程序增长或花费时间和每日活跃用户的因素。这对于 Hike 来说更加重要,因为 Hike 是一个亲密朋友的网络。因此,我们需要确保找到朋友、邀请他们并将其添加到网络中很容易。
从一个人第一次开始徒步旅行,提供朋友建议作为登车体验的一部分是至关重要的。我们的数据显示,在加入后的最初几分钟内找到朋友的新用户,其留存率明显高于没有找到朋友的用户。因此,好友推荐算法的功效对于平台的增长和参与度至关重要。
“Society friendship and love, Divinely bestow’d upon man” — William Cowper, The Solitude of Alexander Selkirk
在像 Hike 这样活跃的现实社会网络上设计一个朋友推荐系统意味着:
- 好友建议需要相关 —由于屏幕空间有限,一次只能显示几个好友建议,这意味着我们需要推荐相关的人
- 好友推荐需要顺利进行这样新用户可以毫不费力地加入网络
- 它需要以未来为中心。网络在不断发展,每天都有新用户加入,添加朋友,老用户之间建立友谊等等。基于当前网络,我们希望能够预测网络中即将发生的变化,并相应地提出建议
在 Hike,我们在自然语言处理(NLP)、计算机视觉、相关性和推荐、网络分析等领域部署了最先进的机器学习算法。(ML @ Hike 概述)。我们的朋友建议模型是使用深度学习和网络分析的高级研究建立的。我们对此进行了深入研究,并开发了一个框架,用于在具有多种边缘类型的异构网络上进行图形表示学习,以进行朋友推荐。这对我们来说非常好,除了商业收益,当这项研究被提名发表在 2019 年 4 月的欧洲信息检索会议(ECIR)上时,我们非常兴奋。
朋友推荐问题符合社交网络中的经典链接预测问题。我们将平台上的用户表示为位于一个图上,图中的边是用户之间的连接。给定一个社交网络在时间 t 的快照,我们能否准确预测在从时间 t 到给定的未来时间 t` 的间隔期间将被添加到网络的边?简而言之,网络的当前状态可以用来预测未来的链接吗?传统的链路预测方法是基于分析网络中节点“接近度”的测量。具体而言,如果两个节点的邻域有很大的重叠,则这种方法将指示它们很可能共享一条链路。共同邻居、Jaccard 系数、Adamic-Adar 度量、是已经被设计用于评估节点邻域之间的重叠的不同度量。还有使用节点特征来训练分类模型的监督机器学习技术。这些功能并不总是容易获得,因此需要大量的功能工程。
两个节点的节点嵌入可以被组合以形成连接它们的边的表示。在链接预测的情况下,这种边缘嵌入可以被给予分类器,以预测边缘是否可能存在。
最近,在开发用于学习图形表示的方法方面已经有了很多工作。这些表示捕捉节点与其邻居的关系。我们可以使用这些图形表示来跳过我们的模型的手动特征工程,并且可以使用节点向量来训练模型,以解决诸如链接预测、节点分类和社区检测之类的问题。这种表现形式已被证明比手工设计的特征更有效。其思想是学习一种映射,该映射将节点投影到低*向量空间中,从而保持相邻关系。嵌入生成通常遵循两个步骤:
- 网络中每个节点的样本邻域,例如通过生成从节点发出的随机行走。这些示例捕获了节点之间的上下文关系。
- 一种 skip-gram 类型的模型,它将随机行走作为输入,并将节点投影到低*空间。
一个类比是文本文档中的单词嵌入(word 2 vec)——随机游走是句子的网络对应物。两种流行的节点嵌入方法如下:
Deepwalk 方法学习同构网络中的节点嵌入。首先,我们从每个节点开始,生成固定数量的选定长度的无偏且均匀的随机行走。Skip-gram 算法用于从随机行走中获得节点嵌入,随机行走期望捕获网络节点的上下文属性——出现在相同上下文中的节点具有相似的向量嵌入。
学习同构节点嵌入的另一个重要方法是 node2vec,其中随机行走偏向于导航节点的邻域,使得它们可以从广度优先搜索(BFS)过渡到深度优先搜索(DFS)遍历。BFS 和 DFS 之间的插值由一个参数指定,为了获得良好的性能,这需要进行大量调整。
朋友推荐可以被定义为二元分类问题,该问题从一对用户获取特征,并且如果是朋友对,则学习将它们映射到 1,否则映射到 0。我们可以利用网络嵌入来获取用户特征。如果 u,v 是两个用户,并且 vec_u,vec_v 分别是对应的节点嵌入,我们可以以各种方式组合这些嵌入来创建分类模型的输入,例如
- 串联,vec =**vec _ u⊕vec _ v
- 平均值,vec =(vec _ u+vec _ v)/n
- 哈达玛乘积,vec =vec _ uvec _ v*
注意,这些都是向量运算。向量 vec 可以认为是边< u,v >的嵌入。然后将 vec 输入机器学习模型,如逻辑回归、神经网络等。训练分类器需要模型“学习”的已知朋友和非朋友对的大量标记数据
D = { < u,v >,label},其中 label ∈ {0,1}
为了评估,保留了一个测试集。这种模型可以通过各种度量来评估,例如
ROC 曲线下面积(AUC)
-k 处的精度(P @ k)
为了在 Hike 等真实世界的活跃社交网络上测试朋友推荐模型,人们还需要评估该模型在应用程序上的功效,这可以通过比较前 k 名推荐的点击率(CTR)来完成。
Hike 的社交图谱相当独特。网络是高度异构的,具有多种节点类型,例如用户、帖子、主题等。以及多个边缘类型,例如友谊、喜欢、评论、关注等。对于朋友推荐系统,我们假设一个徒步旅行的用户网络是同类型的,但是这个网络的边是异构的,在节点之间有多种类型的边。为了便于说明和扩展,我们使用了具有三种边缘类型的异构网络:
“联系人”—如果用户在彼此的联系人中
“朋友”——如果用户是徒步旅行的朋友
“聊天”——如果用户在一段时间内至少聊过一次
这允许在两个节点之间存在多条边,例如,如果用户出现在彼此的联系人列表中,是朋友并且在过去的一个月中交换了聊天消息,则在他们之间将存在三条边。Hike 网络比以前使用网络嵌入方法对链接预测进行的研究要大得多。边缘类型的异质性对于我们的网络也是非常独特的,我们的网络在数学上可以描述为具有多种边缘类型的多图。我们数据中的另一个混淆因素是,在我们的验证数据中,46%的节点对没有共同的朋友——有许多孤立和松散连接的节点。这些挑战增加了朋友推荐问题的难度。
DeepWalk 和 Node2vec 的适用性仅限于具有一种类型的节点和节点间单一类型的边的同构网络。为同构网络设计的现有网络嵌入方法可能不直接适用于异构网络。最近, metapath2vec 提出了一种异构网络的嵌入技术,它定义了元路径(一系列节点类型)来限制随机游走。然而,如何定义这样的元路径并不明显,因为我们通常缺乏对路径和元路径以及元路径长度的直觉。此外,对于具有不同边类型和两个节点之间的多条边的异构网络(异构多图),没有直观的方式来定义边类型的元路径。在 metapath2vec 中,提出了一种在具有图像和文本节点的多模态网络中学习节点嵌入的深度架构。然而,它不能推广到一个多图,其中一对节点之间存在不同类型的边。对于异构网络,Deepwalk 有一些简单的扩展。
无偏随机行走是通过分配穿过两个节点之间的任何边的相等概率来生成的。这增加了随机行走到与当前节点有多条边的节点的概率。一个限制是,在 Hike 网络中,接触边远远多于朋友,聊天连接甚至更少。因此,随机漫步有更高的机会通过接触边,在某些情况下完全避免聊天边。
一个简单的解决方案是,随机游走受主导边类型的影响,随机游走是这样生成的,即有相等的概率跳到每个边类型上。这通过随机选择边缘类型来实现,然后在所选边缘类型中随机选择边缘。实际上,不同的边类型对随机游走的贡献不同,并且会有不同的权重。我们没有直观的方法来获得这些权重。
这些方法的主要缺点是,没有明显的方法来找出如何对每种边类型的随机游走进行偏置;没有理由认为边类型具有同等的重要性。
我们提出了一种方法来自动估计每个边缘类型的贡献,以获得边缘的最终嵌入。我们展示了与朋友推荐问题的相关性。计算过程如下:
- 将 Hike 网络分为朋友子网、联系人子网和聊天子网,用户分别通过友谊、联系人列表和聊天连接。这些子图中的每一个都是同质的。
- 使用 Deepwalk 或 Node2Vec 从每个子网中获取节点嵌入。我们现在有了一个节点在多个空间中的表示。
- 在每个同质嵌入空间中,从节点嵌入计算边缘嵌入
- 为链路预测训练统一的异构边缘嵌入。
用于学习统一表示的模型基于多输入神经网络,该网络从不同空间获取同质边缘嵌入,并将它们组合以在新空间中形成嵌入,该新空间具有来自 3 种边缘类型的贡献。下图显示了神经网络体系结构,其中节点嵌入被连接以产生边嵌入:
与其他最先进的技术相比,这种方法表现出优越的性能。我们报告了 AUC 分数比 Deepwalk 方法提高了 20%,并且在 5 处的精确度提高了 4.4%。我们还通过发送最可能的友谊作为应用内通知进行了用户实验,我们观察到比基线提高了 7.6%。
简单说一下工程方面——该系统有离线和在线组件。在离线系统中,社交图每天重新计算,节点嵌入被计算并存储在像 FIASS 这样的可扩展系统中,该系统建立索引以促进快速相似性搜索。如前所述,我们还基于神经网络训练了一个新的推荐模型。用户的朋友建议是以在线方式创建的,其中我们查找用户的节点嵌入并执行最近邻搜索以获取候选集,然后使用神经网络模型对其进行评分。布隆过滤器检查确保不会为用户重复推荐。以这种方式生成的前 k 个推荐在 Hike 应用程序上的不同推荐部件中提供。该系统如下图所示:
改进对远足的朋友推荐是我们团队本季度的一项关键 OKR 指标,我们已经达到了本季度的改进指标。在这次旅程中,我们开发了一个框架,用于在具有边缘异构性的图上进行图形表示学习,本文中介绍的模型基于我们即将在 2019 年 ECIR 会议上发表的研究论文🏆😎
原载于 2018 年 12 月 18 日blog . hike . in。
使用生成的谷歌表单进行更友好的数据标注
原文:https://towardsdatascience.com/friendlier-data-labelling-using-generated-google-forms-d25e3e9f6aa6?source=collection_archive---------7-----------------------
手动标记数据是无人喜爱的机器学习琐事。如果你能给别人一个愉快的工具来完成这项任务,你就不必担心要求别人帮忙。让我向您展示:使用 Google App 脚本生成的 Google 表单!
Google App Scripts allow you to build automation between Google Apps
人们给数据加标签的常规方式是在电子表格中输入标签。我通常也会这样做,但是在最近的一项任务中,我需要标记文本段落。你曾经尝试过阅读电子表格中的文本段落吗?..简直是地狱!幸运的是,当我试图找出一种方法使标签过程不那么累的时候,我遇到了一种使用 Google App Script 根据电子表格文档中的数据自动生成表单的方法。
Nasty! Nobody wants to strain their eyes trying to read documents in spreadsheet cells!
创建将生成我们表单的脚本
首先,我们只需从包含我们想要收集标签的数据的 Google 电子表格中进入应用程序脚本编辑器:
Opening the App Script editor from a Google Spreadsheet
使用应用程序脚本(pssst!这只是 JavaScript)我们可以读取电子表格数据,并向其他谷歌应用程序(在这种情况下,谷歌表单)发送命令。
使用表单进行标记的好处在于,您可以通过指定数据输入类型来保证用户输入的一致性。例如:
号码范围:
form.addScaleItem()
.setTitle(dataToLabel)
.setBounds(1, 10)
.setRequired(true);
二进制标签:
form.addCheckboxItem()
.setTitle(dataToLabel)
.setChoices([
item.createChoice('Is a cat')
])
多类标签
form.addMultipleChoiceItem()
.setTitle(dataToLabel)
.setChoices([
item.createChoice('Cats'),
item.createChoice('Dogs'),
item.createChoice('Fish')
])
在 App Script API docs 中查看更多输入类型的详细信息(或者手动创建 Google 表单时只查看不同的输入类型)。
您可以从我的 Github 中获取我用来生成用数字 0 到 10 标记文本文档的表单的脚本:
[## ZackAkil/更友好的数据标签
更友好的数据标注代码资源,用于生成标注数据的 google 表单。
github.com](https://github.com/ZackAkil/friendlier-data-labelling/blob/master/Code.gs)
在你写好剧本(或者复制粘贴)之后;然后选择脚本的入口点并运行它!警告:第一次做的时候,你可能需要通过一些授权环节。
Make sure to select the entry point function of the script before running.
使用生成的表单
脚本运行后,您可以前往您的 Google 表单,在那里您应该会找到一个全新的表单!你可以把表格发给任何你想贴标签的人:
Finally you can send your labellers a convenient link to a familiar Google Form that they can use to carry out the labelling task.
访问数据标签
完成标记后,您可以将标签作为电子表格查看,并导出为 CSV 格式:
It’s pretty straight forward to get the labels out as a CSV.
希望这能让你在未来的机器学习工作中少一点头痛!
本文中使用的完整脚本和数据集可以在我的 Github 上找到:
[## ZackAkil/更友好的数据标签
更友好的数据标注代码资源,用于生成标注数据的 google 表单。
github.com](https://github.com/ZackAkil/friendlier-data-labelling)
Frieze London 2018(第二部分):自然语言处理
原文:https://towardsdatascience.com/frieze-london-2018-part-2-natural-language-processing-66d0627f39af?source=collection_archive---------18-----------------------
第二部分:5.6k Instagram 和 3.2k Twitter 帖子的自然语言处理
介绍
Frieze 是一家国际艺术商业特许经营公司,1991 年以杂志起家,但后来发展成为一家组织一些年度日历上最重要的艺术博览会和活动的机构。
自 2003 年以来,每年 10 月,Frieze 都会在伦敦摄政公园的中央组织一次大型当代艺术展,吸引成千上万的人。来自 20 多个国家的 150 多家画廊通常会参加盈利性艺术博览会。
然而,Frieze 现在已经不仅仅是一个艺术博览会。
“楣周”已经成为一个文化娱乐周,人们纯粹是为了观赏而参加,这里有一个雕塑公园,甚至主要的拍卖行也举办他们的中期当代拍卖会,以配合楣周。
本文的目的是通过展示我对关于艺术博览会的 5.6k Instagram 和 3.2k Twitter 帖子的自然语言处理分析的发现,更好地了解 Frieze London 2018。
请向下滚动,通过交互式数据可视化查看我的分析!
数据和方法
这一事件的官方标签是#frieze。在通过 Twitter API 和 Instagram API 收集了事件发生时包含这个标签的 9000 个帖子之后,我首先清理了 Python 笔记本中的文本数据。
然后,我使用谷歌的 langdetect 库 过滤掉非英语推文,并从 NLP 分析中删除所有转发,这样就不会出现重复。在这些步骤之后,我剩下了 7400 个独特的帖子。接下来,我使用谷歌云自然语言 API 来获取每条推文的情感。
最后,我使用 gensim 库的 Word2Vec 模型来获取整个 tweets 语料库中与单词“frieze”相关的每个单词的单词嵌入向量。Word2Vec 用于从大型文本语料库中计算单词之间的相似度——卡*塔·加内桑的文章就是一个很好的解释。
一旦我有了每个单词的向量,我就使用 scikitlearn 库来执行主成分分析(PCA)以进行降*,并绘制出与“frieze”最相似的单词(最近邻居)。
你可以在这里查看我的 Kaggle 内核这篇文章的所有分析。
分析帖子
在这一节中,我将展示我的自然语言处理(NLP)分析的发现。下面,我报告以下三个指标:
- 每日推文的情感分析;
- 词频和标签频率分析;
- Word2Vec 模型的输出:主成分分析(PCA)和最近邻分析。
情感分析
每条推文的情绪是使用谷歌的云 NLP API 计算的。下面的条形图显示了每天推文的平均情绪,其中-1 表示非常消极的情绪,+1 表示非常积极的情绪。
不幸的是,我们看到,随着展会的进行,人们对 2018 年伦敦奥运会的热情逐渐降低。开始时为 0.47,到周日时一路下跌至 0.37。然而,到了交易会的最后一天,它又反弹到了 0.47!
Figure 1: Line chart showing the average sentiment of the tweets per day
文本频率分析
下面的条形图显示了一个词和一个标签在所有社交媒体帖子中出现的次数,分别在左侧和右侧。不出所料,“中楣”出现的次数最多。
但是,因为标签也出现在社交媒体帖子的主体中,所以在计算单词频率时,它们成为了一个混淆变量。因此,我采取措施将 hashtag 计数从单词计数中移除。
然而,下面的结果并不能很好地告诉我们人们对该事件的看法。我们只发现名词而不是形容词。我们可以使用一些机器学习技术来尝试挖掘一些形容词。
Figure 2: Bar graphs showing the count of words and hashtags appearing in all the tweets
最近的邻居
Word2Vec 是神经语言机器学习模型。它采用大量的文本,在这种情况下,来自 9000 个社交媒体帖子的文本作为输入,并产生一个向量空间,通常有数百个*度,每个唯一的单词对应于空间中的一个向量——单词嵌入。然后使用主成分分析将 Word2Vec 空间的*度降低到 x 和 y 坐标。
重要的是,Word2Vec 用于从 9000 条推文中捕捉单词之间的相似性和关系。具体来说,空间中距离较近的对象意味着它们是相似的。“最近邻”是来自 Word2Vec 模型的少数几个基于余弦度量相似性得分与“frieze”最相似的单词。
Figure 3: PCA output of the nearest neighbours of #frieze from the Word2Vec model
上面的散点图使用两个不同的语料库显示了“frieze”的最近邻居;一个包含标签,一个没有标签。
在带有标签的语料库中,我们看到许多与“frieze”最近的邻居实际上就是标签;比如《friezelondon 2018》《friezeartfaire》《friezemasters》。有趣的是,“regentspark”和“sculpture”出现在附近,可见雕塑公园的受欢迎程度。
不幸的是,很少有形容词或描述性词语来描述人们对艺术博览会的看法。在没有标签的语料库中,我们看到一些描述性的词,如“谢谢”、“最好”和“亮点”,但同样,这些词很少告诉我们人们对事件的看法。需要更深入的分析。
结论
所以你有它!我已经展示了我对关于艺术博览会的 5.6k Instagram 和 3.2k Twitter 帖子进行 NLP 分析的结果。我的发现没能告诉我们人们对博览会的看法。
在未来的研究中,我将致力于更深入的分析。有这么多的 NLP 库,我很可能会在未来使用 GloVe 、 Tensorflow 或 Bert 重新审视这个分析。
下次…
在我的下一篇文章(第 3 部分)中,我将展示我的计算机视觉分析的发现。期待看到哪些艺术品出现的次数最多。敬请关注。
感谢阅读!
Vishal
我是一名文化数据科学家,是伦敦 UCL 学院*的研究生。我对城市文化的经济和社会影响感兴趣。我欢迎反馈和建设性的批评。* 你可以在Twitter或LinkedIn、insta gram或我的 网站 上与我取得联系。
从大数据到微服务:如何通过 AWS lambdas 为 Spark 训练的模型提供服务
原文:https://towardsdatascience.com/from-big-data-to-micro-services-how-to-serve-spark-trained-models-through-aws-lambdas-ebe129f4849c?source=collection_archive---------6-----------------------
通过预先训练的 Spark 模型为端点供电的快捷方式
介绍
“我们选择它是因为我们要处理海量数据。另外,听起来真的很酷。”—拉里·佩奇
恭喜你!你用 Spark 训练了你的决策树,得到了一个很好的模型。现在呢?
你想利用你的模型来提供实时预测,但在 Spark 中没有简单的方法来获得网站或应用程序所需的交互性:如果你正在构建,比如说,欺诈检测,在每个用户动作时,你都想触发实时预测并采取相应的行动——时间是关键!
我们需要的是一种 快速简单 的方式,从我们的大数据模型转向一种微服务,一次只按需提供一个预测。
当然,可能会有更好的选项满足您的需求,并且味道更好:您可能事先知道测试集(在这种情况下,请参见这里的中的示例);您可能乐于处理传入的流数据,并定期访问缓存以进行接近实时的预测(例如,选项 B 在此处详述);最后,你可能喜欢 JVM,并寻找一些完善的、现成的东西(在这种情况下,你应该完全检查一下 Mleap )。
相反,我们在这里要做的是分享一个纯 Pythonic 式的端到端工作流,它将在几分钟内让您从 Spark 中训练的模型到服务于预测的公共端点。
我们的工作流程基于以下“原则”:
- 它是你所了解和喜爱的 Python,从头到尾(加上一个非常*的 yml 文件);
- 这涉及到一些语言解析(在也是如此,我们确实热爱语言);
- 它不会涉及部署服务器,甚至不会显式地编写端点(对于中等工作量也是免费的);
- 我们将使用决策树来演示工作流,但同样的想法可以很容易地扩展到其他 Spark ML 算法。
不仅仅是一种部署 Spark 模型的方法(以及其他方法),我们将有机会看到一个真正的数据工程挑战,以及将一个模型规范从一种语言翻译成另一种语言是多么有趣(嗯,如果你喜欢这种事情)。
这是“懒于开发”系列的上一篇文章的概念性续篇,那篇文章的特色是 AWS Lambdas(还有什么?)和 Tensorflow 模型。
先决条件
在深入研究代码之前,请确保:
- 有一个可用的 Spark 集群:为了方便,我们使用了由微软 Azure 提供的 Linux Spark 2.2,但是当然我们所说的任何东西也可以很容易地应用于其他设置;
- 设置一个 AWS 帐户,它将用于将我们的代码部署到 AWS Lambda 。
- 设置无服务器,可以按照这里的说明轻松安装(记住还要设置您的 AWS 凭证!).
你可以在我们的公共 GitHub repo 中找到所有代码:开始工作吧。
前传:在 Spark 中训练一个机器学习模型
Spark 机器学习库的内部工作不是本文的重点:如果你在这里,你可能已经知道如何训练你的模型——如果你知道,跳到下一节,因为我们唯一需要的是一个文本文件中训练模型的序列化版本。我们决定在 Spark 上包含一个*部分来共享一个端到端的、自包含的用例,所以我们只需要做最少的工作来获得一个经过训练并准备好使用的玩具模型。
SPARK 初学者注意事项:如果您已经为您的集群使用了 Azure 部署,您可以遵循微软的指南开始查询一些样本数据和/或花一些时间使用集群提供的示例笔记本。
The PySpark folder in Azure Jupyter contains several ready-made notebooks to get you started.
repo 中包含的 decision_tree_training 笔记本只包含加载一些数据并获得训练好的模型的基本步骤。我们使用的数据集是钞票认证数据集的 csv 版本(此处也有),有四个连续变量作为预测变量,两个目标类,在数据集中用 1/0 标识:多亏了 Spark,我们可以用简单的 SQL 语法快速了解类的分布情况:
Notebooks will let you easily display basic statistics of your datasets, with tables and simple charts.
为了训练我们的决策树模型,我们只需要将数据转换为标签点,并将结果 RDD 馈送到机器学习库。
经过快速计算后,模型终于可以使用了!请记住,我们的目标是将我们在 Spark 上学到的知识转化为现成的无服务器端点,因此我们需要一种方法来提取我们在培训期间学到的数据知识,以便它可以在运行时应用于我们堆栈中的其他地方。幸运的是,决策树可以只用一行代码导出:
serialized_model = model.toDebugString()
serialized_model 包含在训练期间推断的决策规则列表,例如:
DecisionTreeModel classifier of depth 5 with 37 nodes
If (feature 0 <= 0.23874)
If (feature 1 <= 7.2797)
If (feature 0 <= -0.36279)
If (feature 2 <= 6.6779)
If (feature 1 <= 5.496)
Predict: 1.0
...
...
...
作为一个简单的 python 字符串,可以使用标准的 Spark 方法或通过简单的复制+粘贴将它导出到一个文本文件中(可以在 repo 中找到通过数据集训练生成的模型的副本)。
解决方案概述
下面详细介绍了我们快速而有效的解决方案。
Solution overview: from CSV to a lambda-powered endpoint.
从左至右:
- 我们从 Spark 读取一个 CSV 文件开始(当然,这里用您拥有的任何数据管道来代替);
- 我们训练我们的 ML 模型(一个决策树)并使用 Spark 序列化选项来使它——可以说— 可移植;
- 我们编写了一个 Python 函数(细节如下),它将读取序列化的模型,并生成模型的 Python-runnable 版本;
- 我们在 AWS 中部署了一个基本的 lambda 函数,它将加载 Python-runnable 模型,并利用 API Gateway 向外界公开它的预测。
很明显,所有的神奇之处在于将模型从其 Spark 表示“移植”到 Python 可运行的代码中。在下一节中,我们将看到如何以一种有原则且优雅的方式来完成它:输入 DSL 解析。
作为形式语义学练习的模型转换
“这些是我的原则。如果你不喜欢他们,好吧,我还有其他人。”—格劳乔·马克斯
主要的见解(也是大部分的乐趣——在 Tooso 我们做了很多语言相关的东西!)是将问题视为一个语义挑战:我们有一种形式语言(Spark 序列化语言),我们为它提供了一种模型理论意义上的解释,即我们需要找到一种系统的方法来将 Spark 模型的语法组件与 Python 数据结构配对,这样我们就可以通过这些结构运行预测,同时保留原始模型中的信息。听起来很难?让我们先用一个例子来建立我们的直觉(熟悉形式语义学思想的读者可以安全地跳过下一段)。
让我们拿正式的玩具语言 L 来说,这样定义:
- 字母表由整数 1、2 … 10 和运算符“+”组成
- 一个良构公式 (wff)是形式为 A + B 的任何符号序列,其中 A 和 B 是整数或 wff。
为了产生有效的句子,我们只需要应用(一次或多次)语言规则。例如,我们可以这样做:
A + B > 2 + B > 2 + 9
为了得到 wff‘2+9’,或者我们可以这样做:
A + B > 2 + B > 2 + A + C > 2 + 9 + C > 2 + 9 + 7
其中我们将第二步中的 B 展开为一个新的 wff‘A+C’,然后用整数填充公式得到‘2+9+7’。显然,在 L 中并不是所有的公式都是可以接受的:例如,下面这些都是无效的:
2 9 +
+ 2 9
2 9
12 + 2
L 是一种非常简单的语言,具有 no 的内在含义:虽然人类不可避免地会认为‘2+9+7’是基于 L 的算术运算2 + 9 + 7
(18)的表示,但是到目前为止 L 中并没有任何指定的东西可以证明这一结论(例如,很容易想象一个外星种族将+
的含义与*
互换:如果我们给他们的话)).为了赋予 L- 句子“自然”的算术含义,我们需要语义学家所说的模型(不要与机器学习模型混淆),也就是说,我们需要以一种原则性的方式指定我们如何将“含义”附加到 L 句子上。由于“意义”是一个相当抽象的概念,我们将满足于更简单且对我们的教程直接有用的东西:我们将使用另一种正式语言 Python 来给出 L. 的解释
因此,我们的语义将是从 L 句子到 Python 指令的映射,这具有可操作性的非次要好处(这样我们就可以用 L 句子做运算)
我们的(粗略定义的)模型 M 可以如下:
- 整数 1,2 … 10 映射到 Python int 1,2 … 10
- 运算符“+”映射到 Python lambda
lambda x, y : x + y
- 像 A + B 这样的一个 wff 映射到 Python 函数
map(+, [A], [B]))
,即一个 wff 是用实际值在'+'操作中“填充槽”的结果。
有了 M 的武装,我们现在可以将我们无意义的 L 语句翻译成易于理解的 Python 命令,这样‘2+9’就可以被视为一种 L 的方式来表达下面的代码:
map(lambda x, y: x + y, [2], [9]))
更复杂的东西会按预期进行翻译,因此“2 + 9 + 7”将变成:
map(lambda x, y: x + y, map(lambda x, y: x + y, [2], [9]), [7])
我们的建模语言 Python 很酷的一点是,表达式可以被运行,这样,既然它们有了意义,L-句子就可以被看作是进行算术计算的简洁的 Python 指令:对于所有的L-表达式,我们可以关联一个相应的、唯一的 Python 代码来运行那个表达式。
既然我们理解了模型构建的含义,我们可以回到 Spark 序列化模型的原始语言,即产生“wff”的语言,例如:
DecisionTreeModel classifier of depth 5 with 37 nodes
If (feature 0 <= 0.23874)
If (feature 1 <= 7.2797)
If (feature 0 <= -0.36279)
If (feature 2 <= 6.6779)
If (feature 1 <= 5.496)
Predict: 1.0
...
...
...
我们的目标是以一种有原则的方式给这些字符串赋予一个“Python 含义”,以便每个字符串都有一个相应的、唯一的 Python 代码来运行该决策树。
我们利用 lark 构建了我们的 spark2python 服务(在这个项目之前我们从未使用过它,我们非常喜欢它!),这是一个很棒的工具,给定一个语法规范和一个目标字符串,它将生成一个“解析树”,一个组成字符串的语法片段的嵌套表示。我们跳过了带有 L 的树,因为这种语言足够简单,但是如果你想一想我们是如何构建“2 + 9 + 7”句子的,就很容易看出它的结构:首先将 2 和 9 相加,然后将结果相加为 7。
+
7
+
2 9
当 lark 解析一个 Spark 模型时,结果是一个嵌套了 if/else 块的树(如预期的那样):一旦我们有了解析树,我们就可以逐个节点地导航它,并用等价的 Python 片段替换(非常类似于上面的L)Spark 令牌,我们可以对目标值的特征向量运行这些 Python 片段。
如果您查看处理程序中的 predict 函数(AWS lambda 入口点,见下文),您可以很容易地了解运行时发生的情况:客户端在调用服务时将一个特征向量作为查询参数传递;启动时初始化的 Spark2Python 类,加载 lark 语法并解析序列化的模型字符串。
当客户端提供的特征向量到达映射服务时, run_instruction 将开始遍历所有 if/else 块:对于每个节点,组成等式测试的令牌将被映射到相应的 Python 对象。例如,这个火花节点:
(feature 0 <= 0.23874)
将等效于 Python 表达式:
map(lambda x, y: x <= y, [feature_vector[0]], [0.23874])
将根据客户端作为输入提供的向量中的特征 0 来评估结果表达式。当到达一个预测节点时,例如:
Predict: 1.0
给定特征向量和存储的模型,程序将停止并向客户端返回预测值。
虽然 run_instruction 看起来令人生畏,但一旦上述直觉得到巩固,它实际上是一个相当简单的概念:程序将递归地遍历 if/else 树结构的分支,并在每次遇到适当的节点时运行等效的 Python 代码。这就是服务执行的“自动”转换的全部内容!
Runtime comparison of the input features with the model decision rules: at each node a decision is made and the corresponding branch is explored until a prediction is reached.
重要的是要理解我们的语义到底有多普遍。由于我们为 Spark 模型建立了正式的语法,然后定义了结果树的递归 Python 解释,所以我们“保证”所有未来的模型,无论有多长或如何嵌套,都将被系统正确执行,就像我们保证所有现在和未来的L-句子都可以被 Python 评估一样。俗话说,循环是人,递归是神。
(我们将在下面讨论这个问题,但是是的,显然有一个更简单的选择,那就是直接顺序解析模型文件。“蛮力”是有效的(利用 Python 和 Spark if/else 结构中的同构),但是 DSL 方法不仅更优雅,而且也是尝试新事物的好借口,比如 lark 。
使用 AWS Lambda 服务模型
我们的承诺是在几分钟内为您的原型开发提供一个微服务,不需要服务器,只需要 Python 代码就可以了。实现这一点的方法是使用一个 AWS Lambda 来包装我们训练好的模型,并使用无服务器框架来发布我们的服务,让全世界都能看到!
并不缺少关于 Lambda 函数剖析的教程和解释(我们自己的版本是这里是)。对于那些在过去三年中被冷冻在石墨中的人,要点如下:
无服务器计算是一种云计算模式,允许您部署特定的功能/服务,而无需考虑底层硬件、操作系统甚至容器:计算是根据需要进行的,您只需为功能实际运行的时间付费。
无服务器功能由云提供商根据需要进行管理、运行和水平扩展,使开发人员能够自由地专注于业务逻辑,而不是部署/管理应用层。
AWS Lambdas 可以在 cron 上或通过几个“触发器”(队列中的新消息、s3 中的对象创建、通过 API 网关的 http 请求等)来调用。),允许复杂的转换链和基于事件的管道。虽然使用 AWS 控制台来手动部署和管理 lambda 函数是完全可能的,但我们发现使用部署框架将使您的项目保持整洁、自包含和自动版本控制。
在这个项目中,所需的基础设施简单得令人尴尬(只有一个函数),它被捕获在serverless.yml
文件中(env 变量有合理的默认值,但是可以随意使用您的名称/资源)。函数名为预测,函数定义在handler.py
文件中;最后,“触发器”是一个 http GET 请求,因此对 /predict 路由的调用将被路由到我们的函数。如果您对命名约定、目的地的 AWS 区域和分段满意,我们离工作端点就差两个简单的命令了。首先,我们需要确保项目中的vendored
文件夹(或者任何你想用的名字:确保文件夹在那里!)包含该项目的依赖项(在 included requirements.txt
中列出);打开终端,将 cd 放入项目文件夹,然后键入:
pip install -t vendored/ -r requirements.txt
(请注意,在我们的例子中,依赖项是纯 Python,所以不需要担心 Linux 兼容的二进制文件;然而,作为使用 lambdas 时的一般最佳实践,您应该有一个合适的系统,比如这个系统,以确保您为 AWS 容器上传正确的依赖项!)
最后,(在安装了无服务器的情况下),只需在终端中键入:
serverless deploy
无服务器将我们的函数部署到我们选择的 AWS 数据中心,并且自动为我们设置 API 网关,这样一个新的公共 URL 将可用,并且该 URL 将把所有的 /predict 调用路由到该函数。完成后(由于需要创建所有资源,第一次部署会多花一点时间),您将得到类似如下的输出:
Serverless successful deployment output in the terminal.
为了确保一切按预期运行,打开浏览器并测试一个示例 GET 调用,例如:
https://YOUR-LAMDBA-URL/predict?features=-0.4629,4.496,6.59,2.0
其中YOUR-LAMBDA-URL
是在上面的部署中创建的 URL。您应该会收到类似如下的响应:
Testing runtime prediction with a GET call directly from the browser.
恭喜你:你的大数据模型现在可以通过你的微服务获得了!通过交换模型文件(或者甚至用更多的处理程序/代码开关同时部署多个模型),您现在已经准备好使用这个模板并在不到一分钟的时间内部署任何决策树。
杂项注释和最终想法
“如果我们有数据,让我们看看数据。如果我们只有意见,那就用我的吧。”—吉姆·巴克斯代尔
像往常一样,我们设法保持教程的要点清晰简洁。我们忽略了一系列主题,因此下面是一个列表,按照笔记和临别感想的随机顺序,列出了我们在使用微服务服务大数据时所学到的内容。
- 虽然“正式保证”Spark 序列化模型将被服务正确评估,但我们在谨慎方面犯了错误,并为主要功能添加了一些非常简单的单元测试:在 Tooso 时,我们通常利用 pytest 来完成这些任务,我们鼓励您也这样做!
- 可能有人会说,整个语言映射的事情是太多了:给定 Spark 模型文件的特定结构(即多行、缩进格式),将一个 txt 文件逐行翻译成一个 py 文件比形式语义简单得多!这确实是真的,我们在 playground 文件夹中为喜欢这种实用解决方案的读者提供了一个 10 分钟的脚本:虽然比 repo 的其余部分测试得更少,但代码是不言自明的,可以很容易地改进成一个可靠的转换工具,以生成 py 文件来“嵌入”特定的 Spark 决策树。如上所述,DSL 方法更有趣,也更通用:如果 Spark 模型彻底改变了序列化格式,一种新的 lark 语法就足以让原则性方法适应。
- 有人可能会说,整个语言映射的东西太少了:既然语言翻译如此有趣,为什么不加入一些机器学习呢?事实证明,深度学习最近通过 Seq2Seq models 等实现了一些令人印象深刻的翻译改进:一个想法可能是完全抛弃语义方法,用神经网络的方式来面对问题,即通过产生 Spark 模型和 Python 程序对,并训练 NN 来猜测映射函数。虽然这个看起来确实很有趣,但是我们想要一个更快的方法在两种格式之间转换;此外,在其他领域的类似尝试强调了一个不*的挑战:由于 Seq2Seq 人工语言输出有时几乎是正确的,我们如何说服我们的计算机运行看起来像 Python 但实际上不是 Python 的代码?
- 当运行决策树时,我们很容易选择在内存中*护和遍历该树;虽然这对于我们的目的来说很方便,但它不是唯一的(甚至可能不是最好的)选项。即使不考虑编译解析树,一个简单的选择是将模型持久化到 py 文件中:我们可以将解析树转换成 Python 函数,并在端点被调用时加载/执行后者。现在,我们让读者去探索这种可能性和其他可能性!
- 我们的 lark 语法读起来相当简单,但有些难看:我们喜欢设置 lark,但我们没有时间去超越对可用选项的直接掌握,所以我们只是直接寻找一些易于共享和使用的东西(例如,整个语法建立在
instructions
和full_comparison
之间的递归关系上,这样比较可能包含 if/else 块,其内容本身可能是 if/else 块)。这里有很大的改进空间:只要记住,通过改变语法,树遍历函数将需要相应地调整。 - 对现有设置的一个简单扩展是使用 s3 作为共享卷来存储模型(和语法)。如果您的 Spark 管道将日常训练的模型序列化为例如
my-s3-bucket/YYYYMMDD/model.txt
,那么 lambda 可以通过使用 env 变量从my-s3-bucket
中读取,以通过YYYYMMDD
命名约定指定哪个模型是需要的。
作为最后的临别笔记,应该清楚的是,这些想法更多的是最终解决方案的草图,而不是准备投入生产的完整服务(在家里尝试一下,但可能还不是在办公室)。
撇开书呆子的兴趣不谈,这篇文章的总体理念是支持某种“数据科学家的自助式开发”:根据我们在 Tooso 和类似公司的经验,对于快节奏的分布式团队来说,创造/发明/破坏东西的人拥有快速、廉价(AWS lambda 对于前 100 万个请求 T10 是免费的)的低开销工具来自己构建复杂的数据管道是至关重要的,至少在开发阶段是如此。
但是,如果你非常喜欢这些想法,以至于想要将它们生产化,你至少应该考虑以下改进:进行一些一般的类重构以更好地抽象功能,压缩 lambda 部署中的文本文件,在类/端点级别引入适当的错误处理,考虑内存中与持久模型解释(如上所述),提高测试覆盖率,在查询时检查端点参数的一致性(例如,检查所提供的特性是否与训练好的决策树所期望的相匹配),等等。
编码快乐!
再见,太空牛仔
如果你想要一些其他的无服务器的灵感,查看一下我们关于如何建立一个网络分析平台的帖子或者我们关于服务 ML 模型的 T2 教程。
请在此分享您的反馈和意见,或在jacopo . taglia bue @ tooso . ai告诉我们您的大数据故事。
别忘了在 Linkedin 、 Twitter 和 Instagram 上获取来自 Tooso 的最新消息。
感谢
感谢 Tooso 联合创始人、来自 Makersight 的 Luca Bigon、Davide Romano 和 Matt McKinney 对这篇博文之前的草稿提出的有益评论:所有剩下的错误显然完全是我自己的。
从生物学到人工智能:感知机
原文:https://towardsdatascience.com/from-biology-to-ai-the-perceptron-81abfdc788bf?source=collection_archive---------20-----------------------
Python 中受生物启发的线性分类器
创造能像人类一样行动和推理的机器是一项长期的任务。虽然近年来人工智能(AI)和机器学习取得了很多进展,但一些基础工作在 60 多年前就已经奠定了。这些早期概念的灵感来自于生物神经网络(如人脑)的工作原理。1943 年,麦卡洛克和皮茨发表了一篇论文,描述了基于“全有或全无”活动特征的(人工)神经元在网络中的关系。这种“全有或全无”的特征是指生物神经元要么对刺激做出反应,要么保持沉默,没有中间状态。对这种行为的直接观察可以在人脑的微电极记录中看到。在这篇关于人工神经网络的初步论文之后,Frank Rosenblatt 于 1957 年发表了一篇题为“感知机——一种感知和识别自动机”的论文。感知器是一种受监督的线性分类器,它使用可调权重将输入向量分配给一个类别。与 1943 年麦卡洛克和皮茨的论文类似,感知机背后的想法是模拟生物神经元的计算来创造一个可以学习的代理。下面我们将看看感知器背后的思想,以及如何用 Python 代码实现它。
Hardware implementation of the Perceptron (Mark I)
这个想法
你的大脑包含数十亿个神经元,每个神经元都可以被视为一个处理单元,它整合输入并根据阈值标准创建二进制响应。在生物学术语中,输入是在神经元树突处的膜去极化,其向体细胞传播。如果去极化足够强,神经元将通过产生动作电位作出反应,动作电位将沿着轴突传播。在轴突末梢,神经递质将被释放到突触间隙中,这将使下游神经元的树突去极化。此过程的更详细描述可在这里找到。现在真正的线索是生物神经元网络可以学习如何对其输入做出反应。这种特性的术语是可塑性,正是这种特性使得静态软件和能够适应其环境的智能代理有所不同。然而,1943 年麦卡洛克和皮茨的论文并没有解决这个问题,而是关注神经元之间的关系。另一方面,感知器为可塑性问题提供了一个优雅的解决方案:权重。感知器的每个输入都乘以一个权重,然后将结果相加。因此,通过改变输入的权重,我们可以改变感知器的反应。下图给出了感知器如何工作的示意图。
Figure 1: Schematic outline of the Perceptron
在图 1 的左侧,输入表示为 x1、x2、x3…xn。每个输入乘以权重 w0,w1,w2,… wn。在这个乘法步骤之后,结果被累加并通过激活函数。在感知器的情况下,激活函数通过 亥*塞阶跃函数 类似于生物神经元的“全有或全无”特性。这意味着任何≤0 的值将被转换为 0,而任何值> 0 将变为 1。我们可以把上面的也写成:
其中 w 是权重向量, x 是输入向量, b 是偏差项。在图 1 中,我们已经将偏差作为 1(红色方块)包含在输入向量中,并作为 w0 包含在权重向量中。在这种情况下,我们只需要计算输入和权重向量的点积。但仍有一个问题:我们如何调整权重?毕竟这就是感知机的学习方式。思考这个问题的一种方式如下。我们的感知器应该根据输入做出二进制决定(0 或 1)。假设我们有两个数据点,一个属于类 1,另一个属于类 0,感知器必须学习每个数据点的类。下面的图 2 显示了该任务。
Figure 2: Geometrical interpretation
从图 2 中我们可以看到,这个问题可以被视为寻找一个决策边界,也称为超平面(红色虚线),,它将两个组分开。红色虚线以上的一切都是 0 类,超平面以下的一切都是 1 类。超平面由垂直于它的权重向量 w’定义(红色实线向量)。因此,计算输入向量与权重向量的点积并将结果传递给激活函数将给出输入的分类。因此,如果我们看看数据点 1,我们也可以将其绘制为一个向量,并垂直于它绘制另一个超平面(黄色实线)。接下来,查看输入向量 2,我们可以再次绘制一个垂直于它的超平面(蓝色实线)。由于分隔两组的超平面需要垂直于我们正在寻找的权重向量,从图 2 中可以明显看出,w’必须位于黄色和蓝色超平面之间(标记为“用于 x 的范围】)。因此,按照上述内容,我们可以实现如下学习规则。
首先,我们将权重向量中的所有值设置为零,包括偏差项。在二*输入的情况下,如图 2 所示,这意味着: w = [0 0 0]。然后,我们将偏差 1 添加到第一个输入向量,得到 X(1) = [1,x1,x2]。现在我们计算 X1 和 w 的点积。这个计算的结果是 0。通过激活函数传递 0 会将 X1 分类为 0 类,这是正确的。因此不需要更新 w 。对 X(2)做同样的事情也会得到类 0,这是错误的,因此我们需要通过以下学习规则更新 w :
在这种情况下,这意味着从正确的类(1)中减去我们的结果(类 0),将结果乘以当前输入向量,并将其添加到 w 。这将导致:w=【1 x1,x2】。如果有更多的数据点,我们将对每个输入向量继续这一过程,并且随着每次迭代,我们将更接近描述线性分离我们两组的超平面的权重向量。为了测试这一点,我们接下来将用 Python 代码实现感知器。
实施
为了开发我们的感知器算法,我们将使用通过 scikit-learn 生成的玩具数据。我们将使用 NumPy 实现所有其他功能。包含本文所有代码的完整 Jupyter 笔记本可以在这里找到。下面的代码将创建并可视化我们的玩具数据集。
# Import libraries
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
import numpy as np# Generate dataset
X, Y = make_blobs(n_features=2, centers=2, n_samples=1000, random_state=18)# Visualize dataset
fig, ax = plt.subplots(1, 1, figsize=(5, 5))
ax.scatter(X[:, 0], X[:, 1], c=Y)
ax.set_title('ground truth', fontsize=20)
plt.show()
Figure 3: Data for testing the Perceptron algorithm.
图 3 显示了我们刚刚创建的两个集群,正如我们可以看到的,它们可以被一个超平面线性分离,这是感知器工作的先决条件。接下来,我们需要将偏置项添加到输入向量中,并用零初始化权重向量。
# Add a bias to the X1 vector
X_bias = np.ones([X.shape[0], 3])
X_bias[:, 1:3] = X# Initialize weight vector with zeros
w = np.zeros([3, 1])
好了,现在我们都准备好编码感知器算法了。从下面的代码中我们可以看到,这是一个非常简单和优雅的算法。因为不能保证感知器一遍就收敛,所以我们会在不断应用学习规则的同时,将所有训练数据连续 10 次馈入感知器,只是为了确保这一点。
# Define the activation function
def activation(x):
return 1 if x >= 1 else 0# Apply Perceptron learning rule
for _ in range(10):
for i in range(X_bias.shape[0]):
y = activation(w.transpose().dot(X_bias[i, :])) # Update weights
w = w + ((Y[i] - y) * X_bias[i, :]).reshape(w.shape[0], 1)
让我们来看看结果。下面的动画形象地展示了感知器是如何搜索一个分离两个聚类的超平面的。正如我们所看到的,它最终提出了一个解决方案,其中一个 1 类数据点位于超平面上。这个解决方案实际上是正确的,因为我们在前面的激活函数中指定:return 1 if x >= 1 else 0
如果您感兴趣,您可以使用下面的激活函数重新运行上面的代码,看看结果如何变化:return 0 if x <= 0 else 1
结论
最后,在我们结束对以上的一些思考之前。正如我们看到的,感知器算法是一种实现监督线性分类器的简单方法。然而,它也有缺点。例如,当组不是线性可分时,它不起作用。此外,它是一个在线算法,这意味着我们一次只能传递一个训练示例,如果我们有一个更大的数据集,训练过程会很慢。尽管有这些限制,感知器实际上是一个重要的概念,启动了第一次人工智能炒作。具有讽刺意味的是,几年后,当它无法实现关于它的重大承诺时,它也结束了它。
如果你想要这个项目的完整代码,你可以在这里找到它。当然,你也可以在 Twitter 上关注我,或者通过 LinkedIn 联系我。
[## 阿克卡斯滕/感知器
在 GitHub 上创建一个帐户,为 akcarsten/Perceptron 的开发做出贡献。
github.com](https://github.com/akcarsten/Perceptron/blob/master/perceptron.ipynb)
从脑电波到具有深度学习的机器人运动:导论。
原文:https://towardsdatascience.com/from-brain-waves-to-arm-movements-with-deep-learning-an-introduction-3c2a8b535ece?source=collection_archive---------5-----------------------
用神经网络可视化和解码大脑活动。
你可以在这个在线合作笔记本中找到这篇文章的所有代码,你可以直接在你的浏览器上运行它。这里是 GitHub 回购。
在推特上关注我的工作更新和更多:【https://twitter.com/normandipalo
神经系统是一个极其复杂的结构。在你的全身,超过十万公里长的神经连接着你的脊髓和大脑。这个“网格”传输控制每个动作的电脉冲。每一个命令都来自你的大脑,一个更神奇的神经元结构,它通过电激活信号进行交流。理解和解释脑电模式是神经科学家和神经生物学家最大的梦想之一,但事实证明这是一项极具挑战性的任务。
一种记录大脑活动的非侵入性方法是脑电图(EEG) 。这是一种允许使用放置在患者头皮上的电极来记录脑电压波动的技术。通常,大约 30 个这样的电极被放置在头皮周围,允许记录脑电波的整体活动。总之,大脑活动和 EEG 信号之间的关系是复杂的,除了特定的实验室测试之外,对其了解甚少。因此,一个巨大的挑战是学习如何“解码”,从某种意义上说,这些脑电图扫描,可以允许控制机器人假肢和其他设备使用非侵入式脑机接口(BCI) 。
Example of brain waves recorded with EEG. CC BY-SA 2.0, https://commons.wikimedia.org/w/index.php?curid=845554
作为强数据驱动的学科,深度学习最近在相关模式识别任务中的突破,创造了一种使用神经网络分析这些电信号的新方法。在这篇文章中,我们将看到这个主题的介绍:我们将阅读由 Kaggle 竞赛提供的脑电图数据,该竞赛旨在检测哪些脑电图模式对应于特定的手臂和手势,如抓住或举起物体。在用不同的方式对数据进行预处理之后,我们将设计一个神经网络来执行这种分类。我也将展示一些大脑活动的数据可视化,以给出我们正在处理的数据的一个总体概念。该研究领域的最终目标是开发负担得起且有用的假肢装置,通过用大脑控制假肢,帮助截肢者重新获得轻松完成基本任务的能力。类似的技术也可以应用于读取肌肉电激活,从而通过分析激活的肌肉来解码一个人试图执行的运动类型。
你可以在这个在线合作笔记本中找到这篇文章的所有代码,你可以直接在你的浏览器上运行它。下面是 GitHub 回购。
数据简介
如果你有一个 Kaggle 帐户你可以在这里免费下载数据。正如您将看到的,该数据仅由几个组成。csv 文件。这些文件分别是:
- 用作模型输入的 EEG 数据,由放置在患者头皮上的 32 个电极记录。数据以 500 赫兹的频率记录。
- 测试人员试图实现的运动的逐帧标签,在 6 个可能的标签中。
这些数据是通过记录不同人类测试者执行简单动作(如抓取和举起物体)时的脑电图来收集的。因此,数据集被分成不同的剧集,但也有不同的主题。我们将在稍后的准确度预测中看到,脑电波可能是非常个人化的,因为一个模型可以非常准确地预测同一个人在看不见的情节中的意图,但是如果训练不够多样,在对新测试人员做同样的事情时可能会有困难。
因此,目标是创建一个神经网络,该网络将 EEG 读数作为输入,并输出测试者试图实现的这 6 个可能动作的概率分布。由于“无动作”不是一个可能的类,我们可以将其添加为一个类,或者将所有可能的输出设置为 0 到 1 之间的值,并使用阈值来决定是否检测到该动作。如果每个动作都低于阈值,我们就认为它没有动作。
Position of electrodes, source: https://www.kaggle.com/c/grasp-and-lift-eeg-detection/data
我制作了这些电极活动的动画数据可视化。由于采样频率相当高(500 Hz),我使用了一个简单的 3 步低通滤波器来平滑数据,我用前 100 帧创建了一个动画,大约 1/5 秒。
Activations of the 32 electrodes in the first 1/5 of second.
我们还可以将时间数据可视化为 2D 热图,其中纵轴是时间(从顶部开始向下),横轴表示 32 个电极。
EEG temporal heatmap. (time starts from top and goes down)
这也非常有用,因为正如我们将看到的,它将允许我们使用时空卷积。
数据预处理
这些原始数据应该进行预处理,以适应学习阶段。例如,与所执行的动作的相对低的变化率相比,EEG 的非常高的采样频率会导致许多问题:数据变化非常快,但是动作实际上保持不变,因此波动几乎可以被认为是噪声。此外,时态模型会接收大量快速变化的数据,而分类输出从不改变。
第一个可能的步骤是用低通滤波器对数据进行滤波。即使简单的移动平均也是可行的:通过这种方式,我们减轻了数据的高频变化,同时保留了更有用的低频结构,因为我们将分类的运动具有非常低的变化频率(最多 1Hz)。之后,我们可以对数据进行二次采样,即我们可以每 10、100 等只保留一个数据点。这也有助于减少时间*度,降低数据的相关性,在某种意义上使其更加时间稀疏。
可以采用许多其他预处理技术,但是为了简单起见,我们可以在这里停下来,开始设计我们的神经网络。
神经网络设计和实验
处理时态数据时,我们首先想到的架构之一是递归神经网络。这些网络具有动态结构,因此内部状态允许它们对时间数据进行编码,因此它们也基于过去的输入来计算输出。我在 Keras 设计了一个 LSTM 网络,用时序结构给它输入训练数据。结果很好,但在这个特殊的例子中,我更感兴趣的是展示一个常用于图像的卷积神经网络如何能够很好地处理时态数据。
如前所述,在某种意义上,我们实际上是在处理时空数据:上面显示的热图的垂直轴代表时间演变,而水平轴显示各种电极,并且接近的电极几乎总是在人类头皮上空间上接近。这意味着我们实际上可以用卷积提取有用特征:2D 核可以对时间和空间中的模式进行编码。想象一个 3x3 卷积核:它能够在热图中描绘的矩阵上,通过对三个不同的时间步长(3 个核行)以及三个不同的电极(3 个核列)进行加权求和来提取特征。因此,具有许多内核的 CNN 可以发现电极的激活如何在有限的时间周期内相对于期望的运动而变化的特征。
我在 Keras 中实现了一个简单的 CNN 来检查它在这个数据集上的性能。你可以在这个在线合作笔记本中找到这篇文章的所有代码,你可以直接在你的浏览器上运行它。下面是 GitHub 回购。
import keras
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.layers import Embedding
from keras.layers import LSTM, CuDNNLSTM, BatchNormalization, Conv2D, Flatten, MaxPooling2D, Dropout
from keras.optimizers import Adammodel = Sequential()
#model.add(CuDNNLSTM(128, input_shape = (time_steps//subsample, 32)))
model.add(Conv2D(filters = 64, kernel_size = (7,7), padding = "same", activation = "relu", input_shape = (time_steps//subsample, 32, 1)))
model.add(BatchNormalization())
#model.add(MaxPooling2D(pool_size = (3,3)))
model.add(Conv2D(filters = 64, kernel_size = (5,5), padding = "same", activation = "relu", input_shape = (time_steps//subsample, 32, 1)))
model.add(BatchNormalization())
#model.add(MaxPooling2D(pool_size = (3,3)))
model.add(Conv2D(filters = 64, kernel_size = (3,3), padding = "same", activation = "relu", input_shape = (time_steps//subsample, 32, 1)))
model.add(BatchNormalization())
#model.add(MaxPooling2D(pool_size = (3,3)))
model.add(Flatten())
#model.add(Dropout(0.2))
model.add(Dense(32, activation = "relu"))
model.add(BatchNormalization())
# model.add(Dropout(0.2))
model.add(Dense(6, activation = "sigmoid"))adam = Adam(lr = 0.001)model.compile(optimizer = adam, loss = "categorical_crossentropy", metrics = ["accuracy"])model.summary()
为了检查我们模型的性能,正如 Kaggle 竞赛中所建议的,我们检查了 AUC 分数。如果你不熟悉 AUC 是什么,我建议这个清晰直观的解释。您可以在在线笔记本中自行查看,通过快速培训阶段,我们可以达到 0.85 左右的 AUC 分数。
通过训练不同的神经网络架构以及预处理技术等,可以实现许多改进,但这种概念的介绍性证明显示了神经网络从这种数据中学习的显著能力。
结论
在这篇文章中,我们介绍了脑电图的脑电信号,这是一种非侵入性和相对简单的记录用户头皮有用信号的方法。我们看到了一些数据的直观可视化,以及如何使用神经网络从中提取运动意图等特征。我相信,由于深度学习,更广泛的各种数据科学技术,平台和逐年增长的竞赛,这个领域(机器人假体,脑机接口)将有一个深刻的推动。
这些技术的影响将是巨大的。拥有可以以自然方式控制的低成本假体可以极大地改善数百万人的生活。
我建议你去看看symbion 项目,这是一个最近开始的项目,一些有才华的人试图拼凑一个低成本、智能手臂假体,可以通过肌肉激活来控制,以真正实现这种设备的大众化。
在推特上关注我的工作更新和更多:https://twitter.com/normandipalo
从业务问题到数据科学任务
原文:https://towardsdatascience.com/from-business-question-to-data-science-task-55a49f471a0c?source=collection_archive---------15-----------------------
数据科学任务的六种类型
每一个分析的开始,都应该有一个问题。在商业世界中,这是一个典型的与商业运作、战略或产品相关的问题。作为一名数据科学家,我的工作是将问题转化为数据科学任务。听起来很简单,但确实至关重要,因为要解决的特定数据科学任务定义了可以从数据和分析中得出的结论。
我在数据分析&洞察部门工作,在我的 Meetup 简介中,我说“我试图将数据转化为洞察”,在我的工作日,我经常大声说“我们需要创造(可操作的)洞察,并以数据为导向”——但这实际上意味着什么呢?这是我的数据哲学系列的第一部分,我试图剖析并理解“将数据转化为见解”的实际含义。
数据科学任务的六种类型
Jeffery T. Leek 和 Roger D. Peng 在" 中定义的问题是什么? “六种日益复杂的数据科学任务:
在这篇文章中,我省略了“机械的”数据科学任务,因为它在日常数据科学问题和任务中很少出现(至少在我的日常工作中我从未遇到过)。
描述性和探索性数据分析
What is the number of active users per month? Is there a seasonal trend in the number of active users?
第一个例题是描述性问题。目标是获得现有数据样本的摘要。第二个示例问题是探索性问题,任务是总结,但也是探索潜在的相关性和趋势。通常,它的目标是处理数据,形成新的想法和假设,这些想法和假设可能会导致新的数据收集和实验。描述性和探索性任务中使用的方法范围从五数字汇总到与探索性数据分析相关的更复杂的方法(由约翰·图基大力推广)。对于示例描述性问题,我们将计算每月活跃用户的平均数量
(可能已经有了置信区间);对于示例探索性问题,我们将从时间序列图开始。
推理数据分析
Is the user activity really different between customers that bought the product in May vs. June?
在推理问题的情况下,任务是量化观察到的模式是否可能超出现有的数据样本。统计推断
包括,例如统计假设检验。对于上面的示例问题,我们可以使用零假设进行统计测试,假设两个月之间的活动相同,使用替代假设假设活动不同。假设零假设为真,测试计算结果的可能性。如果非常*(即 p 值*于
预定义的显著性水平),我们拒绝零假设,并认为存在显著差异。
推断性数据分析是我们开始产生可操作见解的地方,因为我们确保结果在数据样本之外有效,并且结果不是偶然的。然而,重要的是要理解,显著的差异并不一定意味着与业务相关的差异。人们还应该调查影响的大*,看看这种差异是否真的对业务有明显的影响。这被称为实用或
临床意义并且很可能是未来博客文章的一部分。
预测数据分析
Which of our users are most likely to churn?
推理数据分析可在群体层面(例如,在您的所有客户中)产生可操作的见解。如果问题是为个人发现可操作的见解,那么任务就是预测性数据分析。在这样的任务中,给定一组其他特征(自变量),我们预测个体的一个特征(因变量)。要为示例预测性问题构建预测模型,我们需要一个数据样本,该数据样本具有描述客户是否流失(是/否)的目标特征“流失”,以及一组描述客户行为(产品活动、客户服务呼叫等)的描述性特征。).给定来自搅动用户和活跃用户的例子,我们可以将任务建模为二元分类问题。
一个成功的预测模型(通过定义的绩效衡量指标来衡量)会为特定的个人产生可操作的洞察力。因此,如果模型表明某个特定客户可能会流失,我们应该定义一个行动来防止流失。不幸的是,这个模型并没有告诉我们应该采取什么行动——最佳行动是你需要在实验中找到的。在这种情况下,通常不容易正式评估业务影响,整体成功是我们构建预测模型的好坏与触发行动的好坏的结合。如果我们还想估计最优行动,那么这个任务就叫做规定性分析,这也是未来博客文章的主题。
因果数据分析
Why are our users churning?
因果推理是关于“为什么”这个问题的 —理解描述我们业务或特定业务流程的特征之间的因果关系。在因果数据分析中,我们希望找出如果一个特征被改变,另一个特征会发生什么:平均起来,特征之间的关系的方向和大*是什么。在我们的示例问题中,我们可以(应该)问一个更详细的问题,例如,“用户流失是因为我们展示了太多的广告吗?”。为了回答这样一个问题,我们可以利用我们已有的观察数据的统计模型,或者进行特定的随机实验并收集实验数据来明确回答这个问题。第二个选项是当您执行 A/B 测试时会发生什么。这也是我们可以做的来回答我们的示例问题:进行 A/B 测试,其中一组用户看到较少的广告,并监控两组用户之间的流失率。
随机数据分析是这篇博文中描述的五个数据分析中最困难的任务。然而,如果做得好,它会产生最清晰的可操作的洞察力,因为我们实际上了解我们特征之间的因果关系。显然,因果推理的背后有更多的东西,我计划在以后的博客中写更多。现在,永远不要忘记
"cum hoc ergo proper hoc":相关性并不意味着因果关系!
从买方角色到数据科学中的职业角色
原文:https://towardsdatascience.com/from-buyer-personas-to-career-personas-in-data-science-f677873f2e02?source=collection_archive---------9-----------------------
image credit: BRIDGEi2i.com
场景 :班加罗尔一个新办公室里一个不太大的会议室。
时间戳 : 17 年前。
人物:一群背景和教育程度各异的年轻人:统计学家、计量经济学家、经理、顾问、投资银行家和信用评级师。
:作为第一批开始证明围绕“分析”的宣传是真实的公司之一,每个人都有在数据行业留下印记的远大梦想。
:梦想是伟大的,但对于这个新的、尚未定义的行业,什么构成了职业成长和职业道路?
听起来像一本新书的开场白?
当我们加入分析行业时,这是我们许多人的现实,当时用数据解决问题尚未开始其爆炸性的旅程。今天,随着越来越多的人接受数据科学的力量,年轻人蜂拥加入这一职业,这个问题仍然被提出。
如果我从事分析,我可以期待什么样的职业?
时髦的词语和天花乱坠的宣传给那些纠结于如何建立深度和广度的年轻人制造了更多的困惑;是选择早期专业化还是尝试直到他们找到自己的定位。
image credit: BRIDGEi2i.com
嗯,我想通过这篇文章回答的是,在分析领域的职业生涯与你看待任何其他职业选择的方式没有任何不同。它始于吉姆·科林斯经典著作《从优秀到卓越》中讨论的基本原则(刺猬原则)。
image credit: BRIDGEi2i.com
上图中的交叉点就是你在职业生涯中想要达到的位置。
关于数据科学家的工作以及他或她需要具备的独角兽式技能组合,已经有很多文章。在我看来,并不是所有的数据科学专业人员都需要具备所有这些技能;事实上,他们不能。
然而,这个职业需要一套多学科的技能,最适合解决商业问题,而不仅仅是那些看起来像是彼此克隆的人。
作为分析专家,我们习惯于创建买家角色来更好地了解我们的客户,并细分适合他们的产品。让我们在这里应用同样的逻辑。
我将在分析领域创建四个职业角色——四个完全不同的人,他们拥有不同的技能,在行业中有着非常成功的职业生涯。就像电影里说的那样,与你的老板或前任老板的任何相似之处纯属巧合。
image credit: BRIDGEi2i.com
四个角色。四种不同的选择。
你认为他们在开始职业生涯时知道自己最终会选择哪个方向吗?
大概不会。
他们是否拥有与独角兽数据科学家相同的技能?
肯定不是。
相反,他们所拥有的是:
- 理解和解决问题的强烈好奇心
- 愿意学习、忘却、再学习和帮助
- 倾向于扮演重要的角色,而不是担心指定
- 增加接触,发现自己的优势
- 导师和更广泛的网络来探索新的机会
他们找到了自己的路。
正如我们为不同的买家角色设计不同的优惠一样,并非所有的分析工作都是一样的。这个行业有跨越多个角色的角色。那么,为什么我们只是试图创造克隆?是的,随着这个行业如此活跃,发展速度如此之快,我们将很快看到新的角色演变,从“商业模式破坏者”到“梦想设计师”,再到“全脑营销者”。
所以,祝你们所有在这个领域刚刚开始职业生涯的人,也祝那些目前正处于十字路口、决定角色的人一切顺利。
正如一幅著名的漫画所说:
你不能呆在森林的角落里等着别人来找你。有时候你必须去找他们。
——**丨*丨*
在其中一个角色中认出你自己?让我知道这是否有助于你思考你的分析职业选择。我很想听听你的想法。
(本文最早出现在 BRIDGEi2i 博客 上,作者是 Prithvijit Roy,bridge i2i Analytics Solutions)**
如果你喜欢这篇文章,请给它一个掌声,并留下评论,以便它达到更多的专业人士和有志之士!
从经典的人工智能技术到深度强化学习
原文:https://towardsdatascience.com/from-classic-ai-techniques-to-deep-learning-753d20cf8578?source=collection_archive---------3-----------------------
建造能够从例子、经验甚至从人类水平的另一台机器学习的机器是解决 AI 的主要目标。换句话说,这个目标就是创造一台通过图灵测试的机器:当一个人与它互动时,对于这个人来说,他不可能断定他是在与一个人互动还是与一台机器互动。
深度学习的基本算法是在 20 世纪中期开发的。自那以后,该领域作为随机运筹学和计算机科学的一个理论分支得到了发展,但没有任何突破性的应用。但是,在过去的 20 年里,大数据集、特别标记的数据和使用图形处理器单元的计算机能力的增强之间的协同作用,这些算法已经在更复杂的技术、技术和推理逻辑中得到发展,能够实现几个目标,如降低语音识别中的单词错误率;在一场图像识别比赛中降低错误率[Krizhevsky 等人 2012]并在围棋中击败一名人类冠军[Silver 等人 2016]。吴恩达将这一成功归因于深度神经网络正确学习复杂函数的能力,以及其与输入数据成比例增长的性能。
如今,每个人都可以使用机器学习来创建一些有趣的项目,例如,在石油和天然气行业:
[## 石油和天然气工程项目中的数据科学。
探索性数据分析
towardsdatascience.com](/datascience-in-oil-and-gas-engineering-projects-daace6e6c7f)
或者享受探索泰坦*克号事故数据的乐趣:
[## 泰坦*克号数据集的特征工程和算法精度
机器学习最流行的数据集之一对应于泰坦*克号事故
towardsdatascience.com](/feature-engineering-and-algorithm-accuracy-for-the-titanic-dataset-5891cfa5a4ac)
然而,深度学习是一种机器学习,它允许由多个处理层组成的计算模型学习具有多个抽象级别的数据表示。【le Cun et al 2015】要理解这项技术,了解机器学习的主要技术很重要:
机器学习技术分为两种:监督学习,它训练一个模型,该模型以已知数据集(一个带标签的训练集)作为输入,并生成一个可以预测新数据未来输出的模型。无监督学习获取数据集(未标记)并在数据中寻找模式或内在结构,它通常作为聚类数据工作。一些最重要的机器学习技术在表 1 中进行了分类。
Table 1. Some machine learning techniques
如果您想更详细地了解这些技术,请查看下一篇文章,在这篇文章中,我用图形和简单的代码解释了它们:
[## 监督学习算法:解释和简单代码
监督学习算法采用一组已知的输入数据(学习集)和已知的数据响应(学习集)
towardsdatascience.com](/supervised-learning-algorithms-explanaition-and-simple-code-4fbd1276f8aa)
此外,强化学习问题涉及学习从经验中最大化数字奖励信号,也就是说,如何将步骤映射到行动(或创建策略)以最大化奖励效用。这种类型的机器学习不从标记数据的训练集中学习,它从与其环境的交互中学习。它尝试几种途径以最大化长期积累的报酬,也叫效用。强化学习的特点是:学习系统的行动影响其后来的输入,它没有直接的指示,如采取什么行动,以及行动的后果,包括奖励信号,发挥了长时间[萨顿和巴尔托 1998]。
利用高效算法进行无监督或有监督的知识发现 特征学习
深度学习是一种基于 20 世纪中期开发的一些基本算法的机器学习。其中大多数用于神经网络,下一节我们将展示一些最重要的机器学习算法。
机器学习中最强大的技术之一是神经网络,因为它可以在不同类型的机器学习的补充中实现,如接下来的会议所示。受人类大脑的启发,神经生理学家沃伦麦卡洛克和逻辑学家沃尔特皮茨提出了一种神经网络,它由高度连接的功能网络组成,这些功能网络映射了从输入到所需输出的路径。这是第一种数学方法。通过迭代修改连接的权重来训练网络。[M .沃伦,W .皮尔茨 1943 年]
神经网络具有从复杂或不精确的数据中获取意义的非凡能力,可用于提取模式和检测太复杂而无法被人类或其他计算机技术注意到的趋势。一个经过训练的神经网络可以被认为是它所分析的信息类别中的“专家”。然后,可以使用该专家对感兴趣的新情况进行预测,并回答假设问题。”【梅林等人,2002 年】
同样受到神经科学的启发,Rosenblatt[Rosenblatt et al f . 1958]开发了感知器,这是一种用于学习二进制分类器的算法,它将每个神经元的输出映射为 0 或 1;它采用输入向量 x,权重向量 w 并评估标量积是否超过阈值 u,即如果 wx-u>0 则为 f(x) = 1,否则为 0。在简单的层神经网络中,这种算法不是很有用,因为二进制分类是有限的。
另一方面,强化学习算法是从动态规划原理发展而来的。动态规划是一组可以解决所有类型的马尔可夫决策过程的算法。[贝尔曼 1957 年动态规划] MDP 是在随机情况下建模决策的数学模型。它们通常用图来表示,其中节点是状态,线是从一个状态到另一个状态的动作,从每个状态开始,每个动作都有一定的概率独立于过去的状态或动作而发生。每个新状态给出一个奖励(正面或负面)。解决 MDP 问题意味着建立一个使所有奖励总和最大化的政策。如果处于某一状态的概率不是 100%,问题就变成了部分可观测 MDP (POMDP)
贝尔曼首先提出了一个可以解决这个问题的方程。[1957 Bellman]这个递归公式提供了遵循期望最高回报的特定政策的效用。解这个方程意味着找到最优策略,这个问题很难解决,因为这个方程涉及一个最大化函数,它是不可求导的。这个问题使得强化学习领域没有任何相关的进展,直到 1989 年 Watkins 提出了 Q 学习算法[Watkins,1989。它通过计算状态对行为的量来解决问题。(莎莎)
最后利用时间差分(TD)学习算法保证解的收敛性。它是由 R. S. Sutton 在 1988 年提出。[Sutton et al 1988]自从他第一次使用它以来,它已经成为解决强化学习问题的参考。它确保大多数国家的参与,有助于解决伴随勘探-开采困境而来的挑战。
推理技术与深度学习的整合
当神经网络发展到不止一层时,深度学习就开始了。在几层神经元中工作只是走向深度学习和数据挖掘的第一步。在这一部分,我们将揭示第一部分的技术是如何集成到多层神经网络中的,它们共同开发了深度学习的基础。
最初,感知器被认为是解决一层神经网络,它作为一个一*分类器。这种技术在例如语音或图像分类中不是很有用,因为该技术必须对输入的不相关变化不敏感,例如照片的方向、照明、缩放,但是它们应该对区分图像和另一个图像(例如狼和狗)的细节敏感。
当多层感知器(MLP)在 1986 年由 Rumelhart 用一种称为梯度下降反向传播技术开发出来时,感知器开始只在多层网络中有用。反向传播是算法的集合,旨在分配正确的权重,使神经网络在学习中具有较低的误差。反向传播中最重要的方法之一是随机梯度下降(SGD),这是一种算法,旨在使用微积分概念作为偏导数的链规则来最*化错误率[Rumelhart 等人,1986]。在该技术中,目标相对于神经元的输入的导数可以通过相对于该神经元的输出(即下一个神经元的输入)反向计算来计算。该技术传播所有导数或梯度,从顶部输出开始,一直到底部,然后直接计算每个链接的相应权重。
自 MLP 和 SGD 以来,在解决神经网络方面没有太多的进展,直到 1997 年提出了另一种称为长短期记忆 LSTM 的反向传播方法[Hochreiter et al 1997],它缩短了正常的梯度下降法,并引入了递归网络的概念来学习长范围的依赖性。它倾斜得更快,解决了以前从未解决过的复杂的人工长时间滞后的任务。
在深度学习论文中,LeCun 解释了其对深度学习形成的重要性:“长期短期记忆(LSTM)网络使用特殊的隐藏单元,其自然行为是长时间记忆输入。一个称为存储单元的特殊单元的作用就像一个累加器或门控漏神经元:它在下一个时间步长与自己有一个权重为 1 的连接,因此它复制自己的实值状态并累积外部信号,但这种自我连接受到另一个单元的乘法门控,该单元学会决定何时清除存储器的内容【LeCun 等,Nature 2015】,
LSTM 网络可以训练某种类型的网络,称为递归神经网络(RNN),可以为涉及顺序输入的任务进行训练,如语音和语言[Graves et al 2013]。RNN 在明年非常有用,但它没有解决深度学习的问题。
科学家还开发了另一种更容易训练的网络,这意味着它需要更少的例子来获得神经元之间连接的正确权重,并且它还可以进行更好的分类。这种网络被称为卷积神经网络(CNN ),其特征在于相邻层之间具有完全连通性。它首先出现在[Lecun et al 1989]中,应用于手写邮政编码识别。作者解释了 CNN 中的卷积层和池层是如何直接受到视觉神经科学中细胞的经典概念的启发。CNN 是发展计算机视觉的第一步。
结合神经网络和强化学习的系统是深度强化学习(DRL)的基础。在这种情况下,处于状态的代理使用深度神经网络来学习策略;根据这个策略,代理在环境中采取行动,并从特定的状态中获得奖励。奖励供给神经网络,它产生一个更好的政策。这是在一篇著名的论文《用深度强化学习玩雅达利》(playing Atari with deep reinforcement learning)[Mnih,V. et al 2013]中开发和应用的,在这篇论文中,他们学习一台机器直接从像素开始玩雅达利游戏,经过训练,这台机器输出了优秀的结果。
后来,AlhpaGo 团队开发了一个深度强化学习系统,使用了本次会议中引用的所有技术(LSTM,美国有线电视新闻网,RNN),创建了一个能够学习玩围棋的人工智能系统,被训练观察专家,被训练与自己对弈,并最终击败世界冠军 Lee Sedol。这是人工智能的一个突破,因为由于游戏的复杂性,科学家认为让一台机器赢得这场游戏需要更多年的时间。[西尔弗等人,2016 年]
感谢阅读!!!
如果你想继续阅读这样的故事,你可以在这里订阅!
我喜欢与贝叶斯网络一起工作:它们允许人类学习和机器学习协同工作,即贝叶斯网络可以从人类和人工智能的组合中开发出来。除了跨越理论和数据之间的界限,查看下一个帖子来了解更多信息:
[## 贝叶斯思*导论:从贝叶斯定理到贝叶斯网络
假设世界上存在一种非常罕见的疾病。你患这种疾病的几率只有千分之一。你想要…
towardsdatascience.com](/will-you-become-a-zombie-if-a-99-accuracy-test-result-positive-3da371f5134)
参考书目
1。贝尔曼河(1957 年)。一个马尔可夫决策过程(编号 P-1066)。兰德公司圣莫*卡加州。
2。贝尔曼(1957 年)。动态编程。新泽西州普林斯顿:普林斯顿大学出版社。
3。Bottou,L. (2014 年)。从机器学习到机器推理。机器学习,94 (2),133–149 页。
4。Ciresan 博士,Meier,u .,& Schmidhuber,J. (2012 年)。用于图像分类的多列深度神经网络。计算机视觉和模式识别(CVPR)(第 3642-3649 页)。
5。F. Vernadat,企业现代化技术:业务流程的应用,收款管理,经济学,1999 年
6。GONZALES N .:对“项目成熟度评估流程的实施:在汽车上的应用”的贡献,博士论文,2009 年 12 月 3 日
7。Graves,a .,Mohamed,A.-r .,& Hinton,G. (2013 年)。基于深度递归神经网络的语音识别。声学、语音和信号处理(icassp),2013 年 ieee 国际会议。
8。赫布,国防部长(1949 年)。行为的组织。威利。
9。辛顿,G. E .,达扬,p .,弗雷,B. J .,&*尔,R. M. (1995 年)。无监督神经网络的唤醒-睡眠算法。科学,268 (5214),1158–61。
10。Juang,B. H .,& Rabiner,L. R. (1990 年)。语音识别的隐马尔可夫模型。技术计量,33 (3),251–272。
11。Krizhevsky,a .,Sutskever,I .,& Hinton,G. E. (2012 年)。基于深度卷积神经网络的图像网分类。神经信息处理系统进展 25(第 1097-1105 页)。
12。LeCun,y . beng io,& Hinton,G. (2015)。深度学习。自然,521,436–444。
13。LeCun,y .,Boser,b .,Denker,J. S .,Henderson,d .,Howard,R. E .,Hubbard,w .,& Jackel,L. D. (1989)。反向传播算法在手写邮政编码识别中的应用。神经计算,1,541–551。
14。勒昆,y .,博图,l .,本吉奥,y .,& H
国家能源研究所,P. (1998 年)。基于梯度的学习在文档识别中的应用。IEEE 会议录,86 (11),2278–2323
15。利特曼博士(1994 年)。马尔可夫博弈作为多主体强化学习的框架。《第十一届机器学习国际会议论文集》(第 157 卷,第 157–163 页)。
16。麦卡洛克,沃伦;沃尔特·皮茨(1943)。“神经活动中固有的思想逻辑演算”。数学生物物理学通报。5 (4): 115–133.
17。麦卡洛克,沃伦;沃尔特·皮茨(1943)。“神经活动中固有的思想逻辑演算”。数学生物物理学通报。5 (4): 115–133.
18。非线性动力系统的建模、模拟和控制。泰勒和弗朗西斯,伦敦(2002 年)
19。Mnih,v .,Kavukcuoglu,k .,Silver,d .,Graves,a .,Antonoglou,I .,Wierstra,d .,& Riedmiller,M. (2013 年)。用深度强化学习玩雅达利。arXiv 预印本 arXiv:1312.5602。
20。罗森布拉特,F. (1958)。感知器:大脑中信息存储和组织的概率模型。心理评论,65,386–408 页。
21。鲁梅尔哈特,丁顿,g .&。通过反向传播误差学习表征。自然,323 (9),533{536。
22。S. Hochreiter 和 J. Schmidhuber。长短期记忆。神经计算,9(8):1735–1780,1997。
23。西尔弗,d .,黄,a,,C. J .,盖兹,a .,西弗尔,l .,德里斯切,G. V. D .。。哈萨比斯博士(2016)。用深度神经网络和树搜索掌握围棋。自然,529 (7585),484–489。
24。萨顿,R. S. (1988)。学会用时差法预测。马赫。学习。, 39.
25。萨顿,R. S .,&巴尔托,A. G. (1998)。强化学习:导论(第 1 卷第 1 号)。剑桥:麻省理工学院出版社。
26。沃特金斯,c . j . c . h .(1989),从延迟奖励中学习。博士论文,剑桥大学。
从数据分析师到数据科学家
原文:https://towardsdatascience.com/from-data-analyst-to-data-scientist-f67a724ea265?source=collection_archive---------3-----------------------
Source: Matterport mask RCNN
一个人如何从数据分析师转型为数据科学家?
- 去 LinkedIn 网站。登录。
- 点击“编辑我的个人资料”。
- 找到“数据分析师”这几个字,换成“数据科学家”。
搞定了。哇,那很容易。
不幸的是,生活没那么简单。在这里,我们承认,要从或多或少的数据中发掘洞察力,需要付出艰苦的努力。
有很多关于从数据科学起步的好文章(例如这里的和这里的),但是关于从数据分析师转型的文章却很少。
在开始之前,我有必要尝试一下这两个角色的定义。
数据分析师收集、处理结构化数据并应用统计算法,以获得收益并改进决策。
一个数据科学家有类似的目标,但也有强大的处理大量非结构化数据的技能,可能接近实时处理。他们发现重要的信息,并能够对来自各种来源的数据进行清理、处理和运行高级算法。他们有很强的讲故事和想象技巧。
我经常遇到有才华的分析师,他们渴望开始他们的数据科学之旅,却因缺乏机会和不确定从哪里开始而沮丧。这促使我写了这篇文章。
为什么要成为数据科学家?
呃,事实上有很多原因…
影响 —产生巨大商业利益的潜力。一个被高层倾听并帮助塑造未来方向的机会。
精通— 在一个快速发展的领域中,有无数迷人的问题需要通过各种方法来解决。例如,建立一个图像识别器或文本分类器来识别社交媒体上的有毒评论。
相关性——有人预测人工智能最终会取代我们的工作。一种安全的方法是让 it 部门创造自动化,而不是等待自己被自动化。
报酬/机会— 乘坐大游艇四处旅行,在按摩浴缸里喝香槟。也许不会,但是薪水会相对较高。好的数据科学家很少,需求量很大;让那成为你,生活应该是美好的。
Data science — loads to learn (left) , robots taking our jobs (middle) and good pay but remember that The Wolf a Wall Street ended in tears! (right)
我已经是数据科学家了吗?
大多数分析师都有良好的基础,但需要多年的努力来发展技能,以便在复杂的结构和/或大型数据集上全面应用尖端方法。也就是说,不需要很长时间就可以开始取得成功,甚至达到超出我们早期预期的水平。
那么,我们在朝着什么技能努力呢?这个问题可能没有正确的答案,但是一个复杂的数据科学项目可能有一个包含许多元素的复杂管道。在数据科学发展的最初几年,人们可能会期望至少触及以下合理的部分:
数据科学语言 — Python/R
关系数据库 — MySQL、Postgress
非关系数据库 — MongoDB
机器学习模型 —例如,回归、提升树 SVM、NNs
图形 — Neo4J,GraphX
分布式计算 — Hadoop、Spark
云 — GCP/AWS/Azure
API 交互 — OAuth,Rest
数据可视化和 Webapps — D3,RShiny
专业领域— 自然语言处理、光学字符识别和计算机视觉
Boosted Trees models are popular in data science competitions
RShiny dashboards can be an effective way to develop an interactive means for others to explore data.
获得这些技能需要很多时间(可能比你的学位课程还要长)。即使是世界上最优秀的人也还有很多东西要学。然而,我们总是可以知道更多,不应该担心我们有局限性。如果我们每天都能变得更好一点,我们都有潜力在某一天达到相当高的技能水平。
决心和坚韧会比我们原始的智力更好地为我们服务。
行动(或活动、袭击)计划
在做其他事情之前,我们需要一些基本技能:
- 从正确的哲学开始。十年前,等待数周时间被送去上数据软件课程可能是可以接受的。那些日子早已过去。到处都有奇妙的材料。让学习持续不断。不断练习技能。
- 学习一门语言,发展你的数学技能——Python 和/或 R 是大多数人的起点。在像 Coursera 和 Udemy 这样的网站上有大量的免费培训。许多 Python 用户喜欢使用 Anaconda 和 Jupyter 笔记本。很多 R 用户喜欢 R Studio 。在数字方面,吴恩达机器学习课程和斯坦福神经网络课程都非常棒,学习起来非常愉快。
- 解决问题——最好是你工作场所的真实问题,与商业专家和数据工程师一起工作。这是最好的端到端开发形式。
- 进入ka ggle竞赛 — Kaggle 任务被划分范围和清理,但是没有比和其他几千人一起做一个具有挑战性的问题更好的方法来提高建模技能了。不要担心等级。从操场比赛开始,然后从那里开始。每个人都有起点,试一试吧。
- 了解该领域的领导者在说什么 —有些人喜欢称之为“数据科学的摇滚明星”。这个*组做出了令人着迷的贡献,非常值得你花时间去做。留意像杰弗里·辛顿、吴恩达、扬·勒昆、雷切尔·托马斯和杰瑞米·霍华德这样的人。
- 使用有效的工作方式——一旦奠定了基础,就开始使用版本控制系统来改进你的工作流程,例如 GitHub 来部署和*护代码。考虑集装箱化的码头工人。
- 有效沟通——我们需要能够推销我们的作品。高管们喜欢闪亮的演示,所以一定要朝着你能在关键演示上展示的东西努力。
Lots of great materials on youtube. Andrew Ng’s state of artificial intelligence is fascinating.
Twitter can be another useful medium. Learn from the best such as Rachel Thomas.
获得正确的设置
即使拥有世界上所有的技能,如果你的组织没有合适的工具和环境,那么等待你的将是一场艰苦的斗争。很可能总是有我们无法控制的因素,所以我们需要考虑我们能够影响什么。
- 迁移到正确的团队 —最简单的计划。大多数大中型组织都至少有一个*型数据科学团队。加入它。
- 与合适的人合作 —如果不可能快速跳槽,那么就创造一个机会,与你认识的知识最渊博的数据科学家一起工作。例如,发现一个可以自动化的问题,然后与专家合作,而不是委托他们去做。
- 支持合适的工具和环境—组织并不总是确定是否以及如何投资数据科学工具。他们需要担心传统分析交付的繁忙计划。安全和审计都需要时间来发展,所以他们只会听到有明显好处的强有力的业务案例。抓住机会支持适当的环境、工具和培训。
- 开发清晰的用例 —了解您的业务以及如何应用数据科学。用一个*的概念证明将两者联系起来。利用成功来支持获得更多工具和环境的案例。
- 与懂得比你多的有才能的人一起工作— 成为拥有你不具备的技能的高技能多元化团队的一员。你不仅会获得更多,还会潜移默化地学到他们的一些知识。
结论
现在是开始行动的最佳时机。今天就开始学习,尽快着手解决一个真正的问题。将没有回头路。坚持不懈,用你的成就给自己惊喜。珍惜这个机会。
从特征分解到行列式:带有直观例子的机器学习基础数学第 3/3 部分
原文:https://towardsdatascience.com/from-eigendecomposition-to-determinant-fundamental-mathematics-for-machine-learning-with-1b6b449a82c6?source=collection_archive---------13-----------------------
为了理解机器学习算法的数学,特别是深度学习算法,从基础到更高级建立数学概念是必不可少的。不幸的是,数学理论在许多情况下太难/抽象/枯燥,难以消化。想象你正在吃一个比萨饼,喝一杯可乐总是更容易和更有趣。
这篇文章的目的是为基础数学理论提供直观的例子使学习体验更加愉快和难忘,那就是鸡翅配啤酒,薯条配番茄酱,里脊配葡萄酒。
包含 3 门课程的机器学习基础数学课程组织如下:
从标量到张量:带有直观例子的机器学习基础数学第 1/3 部分
- 什么是标量、向量、矩阵和张量?
- 标量、向量和矩阵之间的加法
- 标量、向量和矩阵之间的乘法
- 单位矩阵和逆矩阵
- 对角矩阵和对称矩阵
从范数到正交:机器学习的基础数学与直观示例第 2/3 部分
- 向量的 1-范数,2-范数,最大范数
- 正交和标准正交向量
- 正交矩阵
从特征分解到行列式:带有直观例子的机器学习基础数学第 3/3 部分
- 矩阵的特征分解:特征值和特征向量
- 跟踪运算符
- 方阵的行列式
在本文中,我们将通过直观的例子,从特征分解到行列式来浏览第 3/3 部分。
矩阵的特征分解:特征值和特征向量
为什么我们需要分解?如果我们想发现事物的本质,分解是一种有效而实用的方法。假设你刚交了一个新朋友,把他/她分解成以下四个组成部分,可以帮助你迅速对具体的人建立更深入的了解。
同样的数学方法。一个整数可以分解成质因数,比如 20 = 2 * 2 * 5,也就是说 20 不能被 3 整除,20 的任何整数倍都会被 5 整除。
特征分解是一种将矩阵分解成一组特征向量和特征值的方法。非零向量 v 是方阵 A 的特征向量,如果它满足特征值方程:
其中 λ 是一个标量,称为向量 v 对应的特征值。
矩阵 A 的特征分解由下式给出
其中 V 为方阵,其第 I 列为矩阵 A 的第 I 个特征向量,diag(λ)为对角元素为对应特征值的对角矩阵。
例如,一个真实的矩阵:
可以通过非奇异矩阵 V 的乘法分解成对角矩阵:
上述两个向量方程可以由单个向量方程表示:
通过将 λv 移至左侧,我们可以得到
其中向量 V 非零,因为矩阵 V 是非奇异的。因此,
根据行列式矩阵的定义,我们可以有:
将解放回到上面的向量方程中:
解方程,我们有
因此矩阵对进行本征分解所需的矩阵为:**
举个例子,
跟踪运算符
线性代数中,方阵的迹被定义为主对角线上元素的和:
比如有一个 33 的矩阵 一个 ,*
****
trace 运算符的一些基本属性如下:
更一般地,轨迹对于将最后一个因子移动到第一个位置是不变的,这被称为循环置换,即,
方阵的行列式
什么是行列式?为什么我们需要了解如何计算矩阵的行列式?行列式的值在机器学习中有什么意义?
表示为 det( A )的方阵的行列式是可以从矩阵的元素中计算出来的值。对于一个 2*2 矩阵,它的行列式是:
对于 3*3 矩阵,行列式定义为
在 4*4 矩阵的情况下,行列式为
Photo credit to Wikipedia
行列式等于一个矩阵的所有特征值的乘积,我们可以用行列式把一个矩阵映射成一个实标量。您可以使用 numpy.linalg.det 来计算数组的行列式。
scipy
行列式是机器学习算法中一个重要的数学概念,例如广泛使用的降*解决方案:主成分分析(PCA)。正如我们所知,一个矩阵可以被视为空间的线性变换,其行列式的值可以被认为是用这个矩阵变换空间时得到的乘法变化,可以是旋转、缩放或方向变化等。
恭喜你!您已经完成了第三部分,也是最后一部分机器学习的基础数学和直观示例。
“哪里有数字,哪里就有美。”—普罗克洛斯
基础数学理论的美妙之处在于它们永远不会过时。十年后的 2028 年,软件开发人员和数据科学家可能不会再使用 Python 或 TensorFlow 了。但标量还是标量,矩阵还是矩阵,张量还是张量。矩阵求逆的充分必要条件和现在一样。基础数学能够经受时间的考验。你可以在这个系列中投资一周或一个月。幸运的是,收获是你可以终身应用的知识和技能,因为“数学是一种思*方式。”
报名参加🦞:的 Udemy 课程
具有机器学习和统计的推荐系统
https://www.udemy.com/course/recommender-system-with-machine-learning-and-statistics/?referralCode=178D030EF728F966D62D
从探索到生产——弥合深度学习的部署差距(第 1 部分)
原文:https://towardsdatascience.com/from-exploration-to-production-bridging-the-deployment-gap-for-deep-learning-8b59a5e1c819?source=collection_archive---------7-----------------------
这是关于深度学习模型探索、翻译和部署的两个博客系列的第一部分。两者都涉及许多技术,如 PyTorch、TensorFlow、TensorFlow Serving、Docker、ONNX、NNEF、GraphPipe 和 Flask。我们将协调这些技术,使用更具挑战性但不太受欢迎的 EMNIST 数据集来解决图像分类的任务。第一部分介绍 EMNIST,我们用 PyTorch 开发和训练模型,用开放的神经网络交换格式 ONNX 翻译它们,并通过 GraphPipe 服务它们。第二部分介绍 TensorFlow 服务和 Docker,以及一种相当业余的方法,在这种方法中,我们构建了一个服务于我们模型的简单 web 应用程序。你可以在 GitHub 上找到所有相关的源代码。在这里你可以找到第二部分。
弥合差距,迈向人工智能驱动的社会
吴恩达是人工智能摇滚明星。作为斯坦福大学的教授,Coursera 和 deeplearning.ai 的联合创始人,他极大地推动了人工智能教育和应用。他可以被认为是这个领域学生最多的老师,这为他赢得了很大的权威。由此,他创造了人工智能这个术语,称之为点燃新工业革命的新电力。但是,与这种说法的轻松形成对比的是,将电力从实验室输送到数百万家庭和工厂需要付出巨大的努力。它需要人力、大量投资和切实可行的解决方案来将其从理论付诸实践,并使之成为大众的一件理所当然的事情。吴恩达也知道这件事。
回到艾的类比,情况是相似的。在人工智能方面有无数的研究,在医疗保健、交通运输或商业方面也有越来越多的实际应用——仅举几例。然而,大多数人仍然远远没有积极地将人工智能视为日常生活的一部分。可能有政治、社会或文化因素减缓适应。公平地说,当我们谈论人工智能时,我们也需要更精确地了解我们的意思。狭义人工智能和广义人工智能之间的区别表明,我们还没有越过许多人实际谈论人工智能时所指的那一点。
不管怎样,为了解决缺乏大众参与和理解的问题,我们需要 让人工智能更容易接近。在他在 2017 年人工智能前沿会议上的演讲中,吴恩达分享了他对人工智能社会的愿景,以及为人们提供所有工具来实现这一愿景的必要性。在我看来,这与更好地弥合勘探和生产之间的差距是齐头并进的。我指的是从概念和开发阶段到部署的机器学习模型的步骤。模型部署赋予模型生命,使它们对大众来说是可访问的,并允许我们看到它们的真实性能。按照吴恩达的类比,我们可以将人工智能的探索-翻译-部署与电力的产生-运输-消耗进行比较。为了让人们能够做到这一点并弥合差距,我决定写一篇博客,整合从探索到部署神经网络模型的不同技术。
使用 PyTorch 的 EMNIST 图像分类模型,使用 ONNX 的翻译,使用 GraphPipe 的部署
在这个从探索到生产的教程中,我们将使用神经网络解决一个监督学习任务,并通过 web 服务提供预测。我们将其分为以下 4 个步骤:
- 数据探索
- 模型开发
- 模型翻译
- 模型部署
从探索阶段开始,我将首先介绍 EMNIST 数据集并概述其特征。其次,我们继续构建和探索神经网络,通过为图像分配正确的数字和字符标签来学习输入和输出之间的正确映射。几次迭代将很快为我们提供令人满意的精度水平。请注意:我不会在这里详细讨论数据科学主题,因为这不是这篇博客的重点,所以数据和模型探索将是相当肤浅的,进一步的模型调整留给你。在第三步中,是时候离开实验室卷起袖子了:我们将模型转换成独立于框架的表示。在最后一部分,我们导入这个表示,将它转换成一个可部署的模型,并配置推理接口,使它对用户可用。
数据探索:EMNIST 数据集
手写数字的 MNIST 数据集是数据科学事实上的 Hello World (在 Iris flower 数据和 Boston pricing 之间)。 EMNIST 由美国国家标准与技术研究所(NIST)提供。它通过手写字符(大写和*写)的图像来扩展数字。28x28 像素和单一颜色通道(灰度)的图像具有与 MNIST 相同的格式。整个数据集包含来自 62 个类别(10 个数字、26 个*写字符和 26 个大写字符)的 814,255 个图像。对于那些对更多细节感兴趣的人,可以看看 2017 年相应的论文。由于其易于访问、有限的大*和易于掌握的结构,MNIST 已经成为各种深度学习教程的真正普及点。然而,在我看来,它也被过度使用了。因此,我决定对这篇博文的实用部分更进一步,它离现有内容不太远,但足以增加一些多样性。
NIST 以两种不同的格式提供 EMNIST 数据集:二进制和 Matlab。我决定继续使用 Matlab 格式,如果你喜欢走同样的路,欢迎你使用合适的装载机。读取图像和标签为我们提供了 697 932 个训练和 116 323 个测试示例,这几乎是我们在这里保留的 6:1 训练-测试分割。下面,您可以从数据集中看到一些示例:
EMNIST 带来的一个问题是高度不平衡的阶级分布。所有这 10 个数字构成了训练和测试数据集中大约一半的实例。在信件内部,也有两方面的巨大不平衡。首先,跨越大写和*写字母。这尤其适用于英语中一些最常用的字母,如 e 、 s 、 t 或 o 。第二,在大写字母和*写字母之间有很大的不平衡,这反映了语言中不同的使用频率。然而,还有一个好的方面:字母份额在整个训练和测试数据分布中几乎保持不变。
这种不平衡的数据会妨碍分类模型正确地学习正确的模式-标签匹配。有很多方法可以预测这一点,各有利弊。我们可以对类进行缩减采样以实现均匀分布。我们可以通过复制代表性不足的类实例或创建合成样本来增加数据的采样。但是,我们也可以调整稍后的训练损失计算,使得未被充分代表的类获得更高的权重,以便分类错误同等地影响损失,而不管它们的潜在频率。但是,按照我的说法,这不应该是我们关心的问题。
模型探索:使用 PyTorch 开发神经网络模型
根据我们对数据的第一印象,我们可以开始探索有用的模型。这通常是一个迭代过程,包括建立一个模型,训练它,并评估它在我们的测试数据上的性能,以估计它的泛化能力。然后,我们选择最好的一个(或多个)并将其投入生产。
关于我们如何在数据科学中失败的简短说明
这个过程也包括很多失败,如果你失败得快,学得也快,这绝对没问题。因此,我一般区分三种失败:
- 技术的
- 数学的
- 性能方面
技术失败是由于 API 的不正确使用导致了不可编译的模型或运行时错误。例如,在神经网络中实现一个完全连接的层,我们必须定义该层的权重矩阵期望的单元数和输出单元数。如果我们现在将该层堆叠在不满足定义的*度的输入层之上,则模型定义过程或实例化将导致错误。这种类型的问题通常很简单,或多或少容易检测和纠正。它专注于我们脑海中的模型的现有概念的实现。
数学识别和修复失败会变得更加复杂。由于高偏差和/或高方差而表现出一般预测质量的模型大多属于这一类。这意味着一个模型被正确地定义并成功地在训练数据上运行——从技术的角度来看——但会导致不合逻辑或完全糟糕的结果,因为该模型没有学习到从输入到输出数据的适当映射。我们可以将这些问题归因于不利的超参数或不适当的模型架构。例如,我们可以选择一个过高的学习率,并看到我们的损失函数大幅振荡,而不是收敛。这类问题通常涉及更深入的原因分析,有时需要大量的反复试验。他们的解决方案从经验、领域知识和对理论基础的扎实理解中受益匪浅。
性能方面的失败是达不到我们期望的车型的特征。这些期望可以是面向质量或效率的,并且与分类准确度、假阳性的可容忍量有关,但是也与训练持续时间、模型复杂性或关于后来的可扩展性的推断时间有关。在这个失败的最高阶段,我们看到的模型在技术上是正确的,并成功地从我们的数据中学习。但是我们仍然对他们学习的内容和方式不满意。例如,我们可以在图像上训练浅层神经网络来正确地对它们进行分类,并且我们的模型以 60%的分类精度收敛。因此,我们可能对其结果不满意,并可能增加模型的复杂性以提高准确性。
选择正确的深度学习框架
正如我们所看到的,一个模型需要通过不同的质量关。一般来说,需要多次迭代来驱动我们的方法通过它们。特别是对于初学者,我因此建议使用支持快速失败和学习的框架,以及促进我们理解为什么失败。当我开始构建我的第一个神经网络时,TensorFlow 的版本是 1.0。现在我们正在接近 2.0 版本。它是最广泛采用的深度学习框架,具有强大的社区,并由 Google 支持。我已经习惯了用它来解决问题的有时相当不自然的方式。与之相反的是,PyTorch 已经成为一个强大的竞争对手,得到了社区和脸书的大力支持。TensorFlow 是一个成熟的框架,具有一些有用的功能,如用于可视化的 TensorBoard 和用于模型部署和生产的 TensorFlow,但它也有一点静态图形范例的缺点,这会减慢失败和学习的速度。在这里,PyTorch 更好地集成了 Python 数据科学生态系统,而是使用了一种动态图形范式,让您可以轻松快速地探索变量并对故障做出响应。然而,它缺少一些功能和成熟性,而且人们还必须提到,TensorFlow 正以其急切的执行模式预测动态图,该模式宣布将成为“2.0 的核心功能”。我把这篇博客作为一个机会来更加熟悉 PyTorch,特别是探索我们如何从不同的世界中获得最大的收益。为此,我将把重点放在 TensorFlow 和 PyTorch 这两个最重要的框架上,并避免比较其他框架,如 CNTK 或 Caffee。
PyTorch 中的神经网络建模
回到 EMNIST 和我们的数字和字母分类问题:
在本节中,我们构建了两个不同的模型,并在 EMNIST 训练数据集上对它们进行训练。首先,一个简单的线性模型将输入与输出单元完全连接起来,并对输出单元应用 softmax 函数来预测与最高输出值相关的类。其次,我们通过添加两个也完全相互连接的隐藏层来增加这个浅层神经网络的深度。作为损失函数,我们使用平均交叉熵。为了反向传播损失并执行梯度更新,我们使用 Adam 优化器,该优化器在随机梯度下降中对逐渐减*的学习速率使用自适应动量。此外,我们使用每个具有 128 个图像的*批量,并且训练五个时期。在看到我的 JuPyter 笔记本内核芯片有将近 100 GB 的压缩内存后,我决定不使用所有测试实例进行评估,而是随机抽取 5%的子集用于每个评估步骤。然而,我们应该使用整个测试数据集,并在训练后分批评估,以获得对两个模型的泛化能力的更可靠的感知。参考这个笔记本的代码,自己试试。
线性模型
首先,我们加载 EMNIST 数据集,并为后面的训练过程设置一些信息变量:
接下来,我们从 NumPy 数组中轻松地创建 PyTorch 张量作为基本数据构建块。此外,我们将灰度图像的像素值归一化为单位间隔,并将它们展平。在 PyTorch 中,我们不必为分类任务对标签进行一次性编码。这是 PyTorch 内部处理的。这里我们唯一需要注意的是以整数格式提供它们:
现在,我们将线性模型定义为一个继承自torch.nn.Module
的新类。我们通常在构造函数中定义模型,并覆盖forward
方法。在训练期间,我们向它传递输入数据,它执行正向传播并返回输出层的结果。这是 PyTorch 中一个模型的最*配置,具有简单的可扩展性,我们将在第二个模型中看到:
在我们建立模型之后,我们创建一个模型实例并定义损失函数(最*化的标准)。此外,我们通过为优化过程传递模型参数和适当的学习率来设置 Adam 优化器:
为了控制总的训练持续时间,我们定义了历元的数量,即训练数据的完整遍数,以及适当的批量大*。为了在整个训练过程中跟踪和可视化模型性能,我们还提供了一些保持训练和测试数据集的损失和准确性的列表。最后,我们定义评估的频率:
现在,我们可以建立一个贯穿各时期和批次的训练程序。每次迭代,我们从训练数据中抽取一批,重置之前累积的梯度,执行向前传递以获得预测,并计算由预测和真实值之间的偏差导致的损失。我们通过调用它的backward()
函数来反向传播这个损失,并执行相应地调整网络参数的参数更新。可选地,我们采用当前模型,并将其应用于测试数据进行评估。现在我们都准备好开始训练程序了。
下面是我们从中得到的:测试准确率收敛到 68%左右。通常,我们现在会进入一些更深层次的错误分析,例如,通过参考混淆矩阵来识别哪些类别的模型是特别错误的,或者通过根据它们的逆频率来调整我们的损失函数加权代表不足的类别。
为了说明从 PyTorch 中现有的模型定义进行扩展是多么容易,我宁愿通过添加两个隐藏层来将现有的架构扩展到深度神经网络。没有一个体面的讨论是什么构成了 DNNs 实际上是深的,让我们去做它,简单地调整一下我们的网络。然而,如果你想有所准备,请咨询古德菲勒、本吉奥和库*尔这里。
深度神经网络
一旦我们设置了周围的参数和跟踪能力,交换或调整模型是相当容易的。我们可以在现有的基础上定义更多的类,或者按照上面已经显示的结构定义全新的模型。在这里,我们通过扩展层数以及定义将这些层相互连接的操作来类似地定义 DNN。这里,我们应用指数线性单位函数来激活隐藏层的逻辑。
最后,我们观察 DNN,以达到更准确的线性模型分类结果。当然,我们坚持使用更精确的模型,因为它在测试数据集上表现得更好,大约有 78%的精确度。这种性能作为泛化能力的代理,我们希望使用我们期望在新数据上很好地泛化的模型。
不言而喻,这些结果远非真正令人满意和严谨。相反,它们用于说明目的。我们可以用层次模型结构扩展我们的方法,首先区分数字和大*写字母,然后再进行识别。我们也可以转向使用卷积神经网络。然而,这里的重点不是模型调整,而是更好地将探索与生产联系起来。因此,我们在这一点上完成了模型开发,并继续进行模型转换。
模型转换:使用 ONNX——开放式神经网络交换格式
在模型探索和选择之后,我们不得不考虑如何将模型投入生产。部署依赖于框架的模型可能具有挑战性。一般来说,有两种范例可以在更高的层次上实现这一点:一方面,可以使用用于建模和训练的框架,例如通过实现嵌入前向传播的 web 服务。另一方面,人们可以跨越框架边界,混合使用各种技术。我个人更喜欢使用不同世界的精华,并希望说服你也这样做——通过轻松和一些指导。话虽如此,让我们跨越鸿沟,超越界限。
首先,我们阐述了在生产中部署机器学习模型的一些标准:
- 高性能和可扩展性
- 灵活性
- 互通
- 到期日
该解决方案需要处理请求的并发性和频率,并在传输、预处理、前向传播和后处理方面高速处理这些请求。如果资源耗尽,还需要快速适应传入的请求,特别是在容错(可靠性)方面。灵活性是指语言支持、配置和模型处理。互操作性涉及以最少的努力支持多种框架和格式。最后,如果没有满足某些标准,那么成熟度从一开始就可以获得回报。成熟促进采纳,从而促进讨论、解决问题以及想法的多样性和数量。这使得从新事物开始变得更容易。然而,如果解决方案在某些点上已经非常好了,这并不重要,因为在开始时,很少有人采用它。
https://onnx.ai/
开放式神经网络交换格式(ONNX)
ONNX 代表 开放神经网络交换格式 ,号称是“可互换 AI 模型的新开放生态系统”。它提供了一种标准格式来表示深度学习模型,并通过在框架之间轻松共享模型来实现互操作性。它由亚马逊、脸书和微软支持,自 2017 年以来一直存在。ONNX 格式定义了计算图形模型。在他们的 GitHub 页面上有很多关于从不同框架导出和导入的教程。Caffee2,微软认知工具包,MXNet,PyTorch 原生支持 ONNX。还有用于 TensorFlow 和 CoreML 的连接器。随着 TensorFlow 2.0 公告指出“交换格式的标准化”,我们也可能希望 TensorFlow 很快就能原生支持 ONNX。然而,在 GitHub 正在进行的讨论中,我们可以看到一些官员犹豫不决的反应。总的来说,ONNX 可以被视为 PMML预测模型标记语言(PMML) 的现代、可访问和专注于深度学习的继任者,用于以框架非特定的方式表示预测模型和数据转换。
幸运的是,PyTorch 已经集成了 ONNX,因此提供了功能来将模型导出为 ONNX protobuf 格式。因此,我们用torch.onnx.export
导出我们的模型,并向它传递模型、保存它的路径和示例输入。由于模型导出本身通过跟踪工作,我们需要提供这个示例输入。这意味着调用导出会触发模型使用该输入执行向前传递,并记录参与计算输出的操作符的踪迹。因此,该示例也可以是随机数据,但是需要与我们为模型输入指定的形状相匹配。最后,我们还可以指定模型参数的名称。现在,我们可以将其应用于训练好的深度神经网络dnn_model
以获得输出文件:
模型部署:高效模型服务器实现的 GraphPipe 和 Docker
Oracle 最近发布了 GraphPipe 来“简化机器学习模型部署,并将其与特定于框架的模型实现分离。”GraphPipe 的机器学习传输规范使用了谷歌的 flatbuffers 。它为 TensorFlow、caffee2 和 ONNX 提供参考模型服务器,并为 Go、Java 和 Python 提供客户端实现。集成 ONNX 支持扩展了它对更多深度学习框架的支持。尽管它接受 ONNX 作为独立于框架的模型格式,但 GraphPipe 使用特定于框架的模型服务器。通过调整模型服务器配置和标准化客户端-服务器通信,GraphPipe 在服务器效率和性能方面表现出色。各个模型服务器嵌入到他们网站上提供的 Docker 容器中。ONNX 模型服务器接受 ONNX 模型以及 caffee2 NetDef 格式的模型。TensorFlow 模型服务器处理 TensorFlow 模型、SavedModel 和 GraphDef 格式。以下是 GraphPipe 如何处理请求的总结:
本质上,GraphPipe 请求的行为类似于 TensorFlow-serving predict 请求,但是使用 flatbuffers 作为消息格式。Flatbuffers 类似于 google protocol buffers,具有避免在反序列化步骤中进行内存复制的额外好处。flatbuffer 定义提供包括输入张量、输入名称和输出名称的请求消息。GraphPipe 远程模型接受请求消息,并为每个请求的输出名称返回一个张量。远程模型还必须提供关于它所支持的输入和输出的类型和形状的元数据。
ONNX 和 GraphPipe 并不是促进互操作性和部署简易性的唯一技术。几乎在 GraphPipe 发布的同时,Khronos Group 发布了其神经网络交换格式(NNEF) 作为支持互操作性的新标准。此外,使用Glow——一个用于神经网络硬件加速器的编译器,有了另一种将不同框架的模型转换成通用标准的方法。请随意检查它们,不要忘记分享您的经验。在这篇博文中,我们现在将集中讨论 ONNX 和 GraphPipe,然后回到实际部分。说到这里,让我们回到我们的 EMNIST 图像分类模型,并通过 GraphPipe 提供它。代码可以参考这款 JuPyter 笔记本。
首先,确保你的机器上安装了 Docker。其次,用docker pull sleepsonthefloor/graphpipe-onnx:cpu
和docker pull sleepsonthefloor/graphpipe-tf:cpu
拉动 graphpipe-tf 和 graphpipe-onnx 容器图像。第三,使用pip install graphpipe
安装 GraphPipe 客户端来测试我们的模型。更多信息,请参考用户指南。这些参考资料使用简单,让我们可以通过运行的模型服务器快速提供深度学习模型。我们继续使用 ONNX 模型,并使用端口 9000 从存储库的根目录启动我们的模型服务器。为此,我们必须首先创建value-inputs
,这是使用 graphpipe-onnx 服务模型所需的。不幸的是,用户指南中关于如何设置value_inputs.json
的信息非常少:
--value-inputs string value_inputs.json for the model. Accepts local file or http(s) url.
然而,我们可以遵循示例性 Squeezenet 输入的结构,假设外部列表描述每个请求的批量大*,内部列表保存输入*度:
{"data_0": [1, [1, 3, 227, 227]]}
{"flattened_rescaled_img_28x28": [1, [1, 784]]}
现在可以用下面的命令启动模型服务器了:
docker run -it — rm \
-v “$PWD/models:/models/” \
-p 9000:9000 \
sleepsonthefloor/graphpipe-onnx:cpu \
— value-inputs=/models/dnn_model_pt.value_inputs.json \
— model=../models/dnn_model_pt.onnx \
— listen=0.0.0.0:9000
不幸的是,我们失败了,并显示以下日志消息(有关完整的日志,请参阅笔记本):
terminate called after throwing an instance of ‘caffe2::EnforceNotMet’
what(): [enforce fail at tensor.h:147] values.size() == size_. 784 vs 1229312
这似乎是一些张量形状没有按照预期设置。然而,如果没有 Caffee2 的相关知识,这可能很难调试。因此,我们尝试直接从 GitHub 加载两个资源(dnn_model_pt.value_inputs.json
和dnn_model_pt.onnx
),但也失败了。尽管 Squeezenet 的例子起了作用,但是在 GraphPipe 中,试图在我们自己的 ONNX 模型中复制这个例子是一个很大的麻烦。然而,随着 graphpipe-tf 成为 TensorFlow 模型服务器,似乎有了一条出路。多亏了 ONNX,我们可以轻松地从 ONNX-model 中生成 TensorFlow 模型导出,并尝试通过 GraphPipe 服务于该模型。因此,我们只需安装 ONNX TensorFlow 连接器。因此,让我们再试一次:
将 ONNX 模型转换成 TensorFlow protobuf 后,我们用以下代码启动 Docker 容器:
docker run -it — rm \
-v “$PWD/models:/models/” \
-p 9000:9000 \
sleepsonthefloor/graphpipe-tf:cpu \
— model=/models/dnn_model_tf.pb \
— listen=0.0.0.0:9000
为我们的终端带来以下内容:
INFO[0000] Starting graphpipe-tf version 1.0.0.10.f235920 (built from sha f235920)
INFO[0000] Model hash is ‘e3ee2541642a8ef855d49ba387cee37d5678901f95e8aa0d3ed9a355cf464fb2’
INFO[0000] Using default inputs [flattened_rescaled_img_28x28:0]
INFO[0000] Using default outputs [Softmax:0]
INFO[0000] Listening on ‘0.0.0.0:9000
现在看起来好多了。尽管最初有些困难,但我们只用了几行代码就快速部署了我们的模型。这就是为什么我们现在想知道我们部署的行为是否与我们训练的行为相似。
因此,我们最终使用一些针对容器化模型服务器的 REST 接口的测试数据查询来验证部署。为此,我们使用已经安装的 GraphPipe 客户端实现:
Predicted Label / True Label: 2 == z ? — False !
Predicted Label / True Label: r == r ? — True !
Predicted Label / True Label: 3 == 3 ? — True !
Predicted Label / True Label: h == h ? — True !
Predicted Label / True Label: 2 == 2 ? — True !
Predicted Label / True Label: j == j ? — True !
Predicted Label / True Label: 5 == 5 ? — True !
Predicted Label / True Label: 2 == 2 ? — True !
Predicted Label / True Label: 7 == 7 ? — True !
Predicted Label / True Label: 8 == 8 ? — True !
这是后端发生的情况:
…
INFO[0113] Request for / took 773.621µs
INFO[0113] Request for / took 859.584µs
INFO[0113] Request for / took 810.67µs
…
太好了,我们的模型充满活力,能够快速响应请求,并显示出与训练时相似的准确性。请随意尝试更多的例子来证明一些不那么可疑的统计意义;-)
我们现在在哪里,下次去哪?
有很多东西要读,但希望也有很多东西要学。这是我从这项工作中得到的,我希望你能分享经验或提供更多反馈:
- PyTorch 在易用性方面表现出色,并且本身支持 ONNX 互操作性,尽管它缺乏集成的部署解决方案。
- TensorFlow 在成熟度和效率方面表现出色,我们希望它也能在互操作性方面表现出色,使 ONNX 支持成为必然。
- ONNX 是一个令人信服的促进模型互操作性的中介。我希望看到它在未来集成更多的连接器,比如 onnx-tf 。
- GraphPipe 既有用又简洁,但也有一些初期问题。TensorFlow 的集成在盒子的右边工作,而 ONNX 模型不是这种情况。
如果你准备继续,在这里找到第二部。感谢阅读、鼓掌、分享,不要忘记注意差距。
感谢我的同事 弗洛里安·威廉 、简·本德和迈克尔·廷普兰提供的宝贵反馈。
从探索到生产——弥合深度学习的部署差距(第二部分)
原文:https://towardsdatascience.com/from-exploration-to-production-bridging-the-deployment-gap-for-deep-learning-part-2-9e33cc8dfe5e?source=collection_archive---------7-----------------------
这是关于深度学习模型探索、翻译和部署的两个博客系列的第二部分。两者都涉及到很多技术,比如 PyTorch、TensorFlow、TensorFlow Serving、Docker、ONNX、NNEF、GraphPipe、Flask 。我们将协调这些技术,使用更具挑战性但不太受欢迎的 EMNIST 数据集来解决图像分类的任务。在第一部分中,我们介绍了 EMNIST,使用 PyTorch 开发和训练模型,使用开放神经网络交换格式(ONNX)翻译它们,并通过 GraphPipe 服务它们。
本部分通过添加两种额外的模型部署方法来结束本系列。TensorFlow Serving 和 Docker 以及一种相当业余的方法,在这种方法中,我们构建了一个服务于我们模型的简单 web 应用程序。这两个部署都将提供 REST API 来调用预测。你会在 GitHub 上找到所有相关的源代码。如果您喜欢从头开始,请在这里找到关于数据科学的第部分。
我们将使用我们在第一部分中生成的来自 PyTorch 和 TensorFlow 的经过训练的模型文件。你可以在 GitHub 上的models
文件夹中找到它们。
模型部署:TensorFlow 服务和 Docker
这确实是我们第二次在这个系列中使用 TensorFlow 服务。我们第一次使用它是作为 GraphPipe 的一部分,它提供了参考模型服务器和调整模型服务器配置。我们现在不使用元框架,而是直接转向 TensorFlow。参考这个 JuPyter 笔记本按照步骤去体验深度学习模型部署的另一种方式。
第一步,我们必须加载我们的 ONNX 模型,并使用 ONNX TensorFlow 连接器创建它的 TensorFlow 表示:
接下来,我们定义加载模型的路径,并创建一个SavedModelBuilder
。这个实例是生成路径和创建模型的 protobuf 导出所必需的。在 TensorFlow 服务术语中,该特定保存路径也称为源。
为了给我们的模型构建一个合适的签名(某种类型的接口),让我们回顾一下模型由什么组成:
External Input: ['flattened_rescaled_img_28x28']
External Output: ['softmax_probabilities']{'weight_1': <tf.Tensor 'Const:0' shape=(512, 784) dtype=float32>,
'bias_1': <tf.Tensor 'Const_1:0' shape=(512,) dtype=float32>,
'weight_2': <tf.Tensor 'Const_2:0' shape=(256, 512) dtype=float32>,
'bias_2': <tf.Tensor 'Const_3:0' shape=(256,) dtype=float32>,
'weight_3': <tf.Tensor 'Const_4:0' shape=(62, 256) dtype=float32>,
'bias_3': <tf.Tensor 'Const_5:0' shape=(62,) dtype=float32>,
'flattened_rescaled_img_28x28': <tf.Tensor 'flattened_rescaled_img_28x28:0' shape=(1, 784) dtype=float32>,
'7': <tf.Tensor 'add:0' shape=(1, 512) dtype=float32>,
'8': <tf.Tensor 'add_1:0' shape=(1, 512) dtype=float32>,
'9': <tf.Tensor 'add_2:0' shape=(1, 256) dtype=float32>,
'10': <tf.Tensor 'add_3:0' shape=(1, 256) dtype=float32>,
'11': <tf.Tensor 'add_4:0' shape=(1, 62) dtype=float32>,
'softmax_probabilities': <tf.Tensor 'Softmax:0' shape=(1, 62) dtype=float32>}
我们可以识别三个完全连接的层以及我们的输入和输出张量。后者是入口和出口,特别重要的是构建所谓的签名定义。这些签名定义了服务环境和我们的模型本身之间的接口。这是模型部署的第一步,接下来是在 Docker 中启动服务器并进行适当的部署测试。
签名定义构建
在本节中,我们将创建适当的签名(分类和预测)并将它们添加到模型图中。之后,我们使用我们的SavedModelBuilder
实例进行实际的导出
为了创建合适的签名,我们必须从输入和输出张量中推断出TensorInfo
对象。TensorInfo
对象是类 JSON 对象,包含Tensor
的名称、数据类型和形状。我们简单地获取输入和输出张量的引用,并使用build_tensor_info
为它们创建TensorInfo
对象:
应用于output_tensor
,我们得到output_tensor_info
并看到张量持有与我们的 62 个不同 EMNIST 标签相关的*度 1 x 62 的 softmax 激活:
name: "Softmax:0"
dtype: DT_FLOAT
tensor_shape {
dim {
size: 1
}
dim {
size: 62
}
}
现在,我们已经准备好构建分类和预测签名,如下所示。它们只是将TensorInfo
对象与适当的名称和方法名的声明结合起来:
定义后的prediction_signature
看起来像这样:
inputs {
key: "images"
value {
name: "flattened_rescaled_img_28x28:0"
dtype: DT_FLOAT
tensor_shape {
dim {
size: 1
}
dim {
size: 784
}
}
}
}
outputs {
key: "scores"
value {
name: "Softmax:0"
dtype: DT_FLOAT
tensor_shape {
dim {
size: 1
}
dim {
size: 62
}
}
}
}
method_name: "tensorflow/serving/predict"
最后,我们将两个签名添加到模型中,并执行导出:
我们现在可以找到类似于包括元数据(签名)的序列化模型图定义的saved_model.pb
。此外,我们的构建器添加了包含序列化图形变量的文件夹variables
。不幸的是,签名构建过程增加了额外的复杂性。说实话,我还没得到它的效用。毕竟,人们也可以使用张量名称本身,而不需要任何额外的包装。但是,如果您想尝试一下,可以在相关 TensorFlow 文档中找到更多信息。
通过 Docker 容器中的 TensorFlow 服务模型
嘿,看起来我们刚刚创建了一个可服务的,它是 TensorFlow 为客户用来执行计算的对象提供语音服务。是时候真正为可服务对象服务了。但是,TensorFlow 中的服务一般是如何工作的?简而言之,TensorFlow Serving 由下图中描述的五个组件组成: Servables 、 Loaders 、 Sources 、 Manager 和 Core 。它们一起工作如下:我们运行一个模型服务器,告诉管理器它应该监听的源,以便它可以探索新的服务对象。在我们的例子中,我们使用一个文件系统。当我们将一个模型保存到那个文件系统时,源通知管理器关于一个新检测到的可服务的,这使得它成为期望的版本。源提供了一个加载器,它告诉管理器加载模型所需的资源。管理器同时处理请求,决定是否以及何时加载模型。根据版本策略,它可以卸载旧版本或保留旧版本。成功加载模型后,管理器可以开始服务客户端请求,将句柄返回到非常新的可服务或其他版本,如果客户端明确请求的话。客户端可以使用 gRPC 或 REST 发送推理查询。
https://www.tensorflow.org/serving/overview
到目前为止,一切顺利——让我们再练习一次:安装 Docker 后,我们用docker pull tensorflow/serving
提取 TF 服务容器映像,并简单地用下面的命令启动模型服务器:
docker run -p 8501:8501 --name emnist_model \
--mount type=bind,source=$(pwd)/../models/tf_emnist,target=/models/tf_emnist \
-e MODEL_NAME=tf_emnist -t tensorflow/serving &
这将启动 dockerized 模型服务器,并将其端口 8501 发布到我们主机上的同一个服务器。这个端口为我们的模型提供了一个 REST API。此外,我们将目录( source )挂载到容器( target )中,在那里我们喜欢保存我们的 servables。因此,每次我们导出较新的模型版本时,TF serving 都会在容器中识别它们并触发加载过程。我们现在可以直接看到服务进程以及由核心、管理器和加载器完成的任务。
2018-10-13 13:38:15.518130: I tensorflow_serving/model_servers/server.cc:82] Building single TensorFlow model file config: model_name: tf_emnist model_base_path: /models/tf_emnist
2018-10-13 13:38:15.518416: I tensorflow_serving/model_servers/server_core.cc:462] Adding/updating models.
2018-10-13 13:38:15.518455: I tensorflow_serving/model_servers/server_core.cc:517] (Re-)adding model: tf_emnist
2018-10-13 13:38:15.638251: I tensorflow_serving/core/basic_manager.cc:739] Successfully reserved resources to load servable {name: tf_emnist version: 1}
2018-10-13 13:38:15.638370: I tensorflow_serving/core/loader_harness.cc:66] Approving load for servable version {name: tf_emnist version: 1}
2018-10-13 13:38:15.638411: I tensorflow_serving/core/loader_harness.cc:74] Loading servable version {name: tf_emnist version: 1}
2018-10-13 13:38:15.639975: I external/org_tensorflow/tensorflow/contrib/session_bundle/bundle_shim.cc:360] Attempting to load native SavedModelBundle in bundle-shim from: /models/tf_emnist/1
2018-10-13 13:38:15.641451: I external/org_tensorflow/tensorflow/cc/saved_model/reader.cc:31] Reading SavedModel from: /models/tf_emnist/1
2018-10-13 13:38:15.659090: I external/org_tensorflow/tensorflow/cc/saved_model/reader.cc:54] Reading meta graph with tags { serve }
2018-10-13 13:38:15.660035: I external/org_tensorflow/tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA
2018-10-13 13:38:15.672728: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:162] Restoring SavedModel bundle.
2018-10-13 13:38:15.673671: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:172] The specified SavedModel has no variables; no checkpoints were restored. File does not exist: /models/tf_emnist/1/variables/variables.index
2018-10-13 13:38:15.673710: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:138] Running MainOp with key saved_model_main_op on SavedModel bundle.
2018-10-13 13:38:15.677101: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:259] SavedModel load for tags { serve }; Status: success. Took 35653 microseconds.
2018-10-13 13:38:15.678135: I tensorflow_serving/servables/tensorflow/saved_model_warmup.cc:83] No warmup data file found at /models/tf_emnist/1/assets.extra/tf_serving_warmup_requests
2018-10-13 13:38:15.684767: I tensorflow_serving/core/loader_harness.cc:86] Successfully loaded servable version {name: tf_emnist version: 1}
2018-10-13 13:38:15.686409: I tensorflow_serving/model_servers/server.cc:285] Running gRPC ModelServer at 0.0.0.0:8500 ...
[warn] getaddrinfo: address family for nodename not supported
2018-10-13 13:38:15.686843: I tensorflow_serving/model_servers/server.cc:301] Exporting HTTP/REST API at:localhost:8501 ...
[evhttp_server.cc : 235] RAW: Entering the event loop ...
测试模型服务器
再次测试的时候到了!让我们对我们的模型服务器使用一些测试图像,并评估它们的分类准确性。此时,使用我们的预测签名中定义的输入和输出定义将是直观的。然而,这并不是那么简单,我们创建了一个用instances
注释的数据有效负载作为我们的 POST 请求的输入,并接收一个响应对象,我们需要用predictions
处理它的内容:
在我们的 1000 个测试例子中,我们最终得到的准确率为 78.3% ,这与我们的训练结果一致。最后让我们看看下面的一些例子。我们可以发现该模型很难区分大写的 O 和 0 ,这一点都不容易。
模型部署:Flask Webservice
在本节中,我们将转向我们的最终部署方法。因此,我们在一个简单的 web 服务中嵌入了模型推理,并构建了一个允许用户上传图像进行分类的极简前端。为此,我们使用了 Flask ,这是一个简洁的 Python web 开发框架,基于 Werkzeug 和 Jinja2。我们将在包本身中实现模块emnist_dl2prod.emnist_webserver
,但是你可以参考这个 JuPyter 笔记本获得更多信息。
本节包括三个部分:
- 构建模型包装类
- 实现 web 服务和前端
- 运行并测试我们自己的 EMNIST 网络服务器
1.构建模型包装类
我们从下面的模型包装类开始。为了创建一个新的实例,我们必须提供之前使用SavedModelBuilder
保存的模型的路径。这里,我们使用tf.saved_model
的加载器功能来加载和恢复我们的模型。我们还创建了一个会话,在这个会话中,我们恢复了构成我们的SavedModel
的图形定义和变量。此外,模型类还实现了一个run
方法,以便稍后轻松执行单个实例或批量推理。此方法只是对展平和规范化的图像数据(浮点值在 0 和 1 之间)运行会话,并返回所有 62 个类的 softmax 激活。
2.实现 web 服务和前端
接下来,我们转向 Flask 和一些 HTML,因为我们将简单的 REST webservice 与极简前端相结合,以上传图像并可视化分类结果。首先,我们创建两个 HTML 文件,img_upload.html
和result.html
。第一个页面实现了一个图像上传界面和一个按钮来提交图像数据,这在内部触发了预处理和分类过程。后一个文件类似于显示上传图像本身的模板,当然也显示分类结果。结果是检测到的(最有可能的)类以及我们的模型得出的 softmax 分数。让我们仔细看看这中间发生了什么。上传图片时,上传页面触发以下重定向:url_for('process_img_upload')
。此重定向通过后请求提供了以下方法:
emnist_result
是一个字典,我们用它来最终用适当的值呈现我们的结果页面。这也需要临时保存上传的图像并检查文件类型是否正确。在后一部分,我们使用skimage
读取图像,直接产生一个 NumPy 数组——数据科学家的宠儿。然后,我们对图像数组进行预处理(归一化+展平)和分类,简单地调用我们的模型包装器实例的run
作为classify_img
的一部分。这将返回 softmax 激活值,并将最高激活的索引映射到适当的标签。最后,我们通过向字典添加 softmax 值和标签来完成我们的请求结果,并调用show_emnist_result
来呈现结果页面。
除了我们的前端展示,我们还实现了一个方法,用一个适当的响应对象来回答 POST 请求,而不是呈现任何 HTML 模板:
3.测试和性能评估
又到了收获我们劳动果实的时候了。我们启动我们的网络服务器,让我们处理一些例子。您可以使用python emnist_webserver.py
或使用随软件包安装的命令emnist-webservice
来启动它。无论哪种方式,您都应该在终端中显示类似于以下内容的内容:
[2018-10-14 11:07:26] INFO:__main__:Set up temporary media folder for webserver: /Users/mkurovski/Python/emnist_dl2prod/src/emnist_dl2prod/tmp_flask_media
* Serving Flask app "emnist_webserver" (lazy loading)
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: off
[2018-10-14 11:07:26] INFO:werkzeug: * Running on [http://0.0.0.0:5000/](http://0.0.0.0:5000/) (Press CTRL+C to quit)
太好了!让我们去参观一下:
为了方便测试,您可以在库中找到包含 10 个字符的文件夹test_images
。试几个吧!我们选择一个图像并点击Get Result
,然后“瞧”,我们在 softmax 激活中看到 e 和 99.74% 的概率。在后端,我们收到了进一步的确认,表明一切都按预期进行:
[14/Oct/2018 11:11:26] "POST /emnist/result HTTP/1.1" 200 -
[14/Oct/2018 11:11:26] "GET /emnist/img_upload/img_upload_1539508286216.png HTTP/1.1" 200 -
在相关的 JuPyter 笔记本中,您将看到我们后面的实现的一些示例,我们也想在这里尝试一下。出于评估和测试的目的,您可以将eval_serving_performance
作为emnist_dl2prod.utils
的一部分。该方法从测试或训练数据中创建一定量的请求,将它们发送到指定的端点,并评估响应的准确性及其时间。我们将在下一部分更详细地讨论它。这里,让我们在刚刚创建的终端上尝试一下:
这将一些结果可视化,并告诉我们请求的平均准确性:
Accuracy on 1000 test images: 77.60%
77.6% —耶!这看起来与我们的训练经验非常一致。
太好了!我们实现了自己的 web 服务,成功地证实了我们在生产中的培训结果。到了决赛的时候了——所有这些方法在定性和定量意义上如何相互比较?
结论:比较不同部署的吞吐量和预测准确性
这是我关于深度学习模型探索、翻译和制作的综合博客系列的最后一部分。借助 Docker、TensorFlow、GraphPipe、PyTorch、ONNX 和 Flask 等众多技术,我们构建了从勘探到生产的桥梁。所有的方法都是从 PyTorch 探索和 ONNX 翻译开始的。它们的不同之处在于我们部署每个解决方案的方式。我们从 GraphPipe 和 Docker 开始提供一个处理 REST 调用的简短包装器。我们继续使用 TensorFlow 在 Docker 容器中提供服务。这有点冗长和复杂。最后,我们使用 Flask 构建了自己的 web 服务器,并嵌入了模型推理调用。我们还将最后一种方法与极简前端相结合。这是最冗长的,但也是最容易理解的部署方式。然而,我不建议将它用于大规模生产系统,它有助于捕捉模型推理、客户端-服务器通信和前端如何相互连接。现在,让我们看看这些方法在定性和定量方面是如何相互比较的。
首先,让我们从易用性和实现努力的角度来看一下定性。在我看来,Flask 是最简单的方法 GraphPipe 紧随其后。服务 ONNX 模型的 GraphPipe 中的一些意外故障导致了问题。然而,转移到 TensorFlow 很容易地解决了我们当时的问题。使用 TensorFlow 服务,事情会变得有点复杂,因此它在这方面占据第三位。就我们的实现程度而言,GraphPipe 是明显的赢家,只需要很少的代码来部署我们的模型。TensorFlow 服务需要多一点,但仍然做得很好。签名的定义在这里增加了一些冗长。Flask 紧随其后,因为它比 GraphPipe 花费更多的精力,这对于构建自己的解决方案来说似乎是不言而喻的。
但是,作为数据科学家和工程师,我们更感兴趣的是仅仅作为直觉的数字。因此,我还对这些部署在给定请求吞吐量的情况下如何进行比较以及它们是否返回一致的结果感兴趣。参见这款 JuPyter 笔记本进行对比。我在一个只有一个 CPU 的谷歌云计算实例上测试了所有解决方案。然而,为了避免糟糕的网络连接导致的测量偏差,我在这里展示了本地托管每个服务的结果。我们涵盖了各种场景:发送单个实例请求和批处理请求,每个都有 128 个示例。对于这两个场景,我们使用单个客户端线程,没有异步请求,以保持与 Oracle 评估 GraphPipe 的方式一致。然后,我们计算在一致的持续时间内成功请求的数量,并获得每秒的吞吐量作为性能指标。参见emnist_dl2prod.utils:eval_throughput
了解我们吞吐量测试的实施。需要注意的是,不同设置下的绝对数字可能会有所不同。然而,这不应该是我们关心的问题,因为我们更感兴趣的是这些方法如何相互比较而不是它们各自的绝对性能。因此,让我们来看看单实例请求吞吐量。我们清楚地看到 TensorFlow 的服务性能优于 GraphPipe 和 Flask,每秒处理超过 200 个单实例请求,其中 GraphPipe 和 Flask 分别超过大约 150 个和 125 个。
如果我们研究使用的批处理推理案例,并且顺序已经改变,差异会变得更大。GraphPipe 显然脱颖而出,在相同时间内,它提供的图片数量大约是 TensorFlow 的三倍。TensorFlow 服务在处理请求方面排名第二,比 Flask 服务高出约 70-80%。
这与甲骨文的说法相当一致。然而,在我们的例子中,震级并没有变得那么极端。
https://oracle.github.io/graphpipe/#/guide/user-guide/performance
总之,在批量推断方面,GraphPipe 比 Flask 和 TensorFlow 要快得多。然而,TensorFlow 服务明显优于单个实例推理,这一点值得注意。如果我们不批量处理传入的请求并为其提供 GraphPipe,我们最好继续使用 TensorFlow 服务。但是,如果我们的问题允许,或者如果我们可以批量处理传入的请求,我们最好使用 GraphPipe。
观点
哇,这是很多,我希望你仍然喜欢它。请你自己尝试一下,分享一下你的经验,让我们试着介意一下探索和制作之间的差距。有大量的技术支持我们,甚至更多的技术将会出现。特别是,我预计 ONNX 将成为深度学习框架不可或缺的一部分,GraphPipe 将超越其目前的地位。有了这些和其他的贡献,我们可以让事情变得更容易生产,让人工智能通过改变人们的生活来为人们服务。
从虚构到现实:人工神经网络初学者指南
原文:https://towardsdatascience.com/from-fiction-to-reality-a-beginners-guide-to-artificial-neural-networks-d0411777571b?source=collection_archive---------3-----------------------
(这篇文章和许多类似的文章来自我在 jasonroell.com 的个人博客。看看吧!)
对人工智能的兴趣正在达到新的高度。2016 年是人工智能初创公司和资金创下纪录的一年,2017 年肯定会超过它,如果它还没有超过的话。根据 IDC 的数据,到 2020 年,认知系统和人工智能方面的支出将增长超过 750%。从最*的初创公司到最大的公司,从智能手机应用程序到公共健康安全系统,对人工智能的兴趣和投资涵盖了商业和技术领域的所有领域。技术领域的大牌都在人工智能上投入巨资,同时将其融入商业模式,并越来越多地用于他们的产品中:虚拟助理(如 Siri)、计算机视觉、语音识别、语言翻译和许多其他应用。但是 AI 背后实际的 IT 是什么?简而言之:人工神经网络(ANN)。在这里,我们来看看它们是什么,它们是如何工作的,以及它们如何与激发它们的生物神经网络相关联。
定义人工神经网络
术语人工神经网络用于指代数学模型或模拟大脑神经网络中基本计算特征的实际程序。
神经元
来源:http://www . robots . ox . AC . uk
虽然生物神经元是极其复杂的细胞,但它们在输入和输出方面的基本计算性质相对简单。每个神经元有多个树突和一个轴突。神经元从其树突接收输入,并通过其轴突传递输出。输入和输出都采用电脉冲的形式。神经元将其输入相加,如果总电脉冲强度超过神经元的触发阈值,则神经元沿着其单个轴突触发新的脉冲。轴突进而沿着其分支突触分发信号,这些分支突触共同到达数千个相邻的神经元。
来源:数据营
神经元和晶体管之间有一些基本的相似之处。它们都是各自领域信息处理的基本单位;它们都有输入和输出;他们都和邻居有联系。然而,神经元和晶体管之间也有很大的不同。晶体管是简单的逻辑门,通常连接到不超过三个其他晶体管。相比之下,神经元是高度复杂的有机结构,与大约 10,000 个其他神经元相连。自然地,当涉及到执行需要数千个并行连接的认知壮举时,这种丰富的连接网络使神经元比晶体管具有巨大的优势。几十年来,工程师和开发人员一直在设想如何利用这一优势,让计算机和应用程序更像大脑一样运行。最后,他们的想法已经成为主流。虽然晶体管本身不会很快看起来像神经元,但它们运行的一些人工智能软件现在可以模仿基本的神经处理,而且只会越来越复杂。
神经元建模
感知器
来源:http://cs231n.github.io/neural-networks-1/
感知器,或单层神经网络,是最简单的神经计算模型,也是构建的理想起点。你可以把感知器想象成一个神经元。然而,感知器没有树突,而是简单地有输入: x1,x2,x3,…,xN。此外,感知器没有轴突,而是只有一个输出: y = f(x) 。
重量
感知器的每个输入(x1,x2,x3,…,xN)都有一个权重(w1,w2,w3,…,wN)。如果某个权重*于 1,就会削弱其输入。如果大于 1,就会放大。在稍微复杂一点但被广泛采用的感知器模型中,还有一个输入 1 ,具有固定权重 b ,称为偏差,用作训练感知器的目标值。
激活功能
也被称为传递函数,激活函数决定了感知器输出的值。激活函数的最简单形式是某种类型的阶跃函数。它模仿生物神经元在达到其触发阈值时触发,如果总输入超过给定的阈值量,则输出 1,否则输出 0。然而,为了得到更真实的结果,需要使用一个非线性的激活函数。其中最常用的是 sigmoid 函数:
f(x)= 1 / (1+e^-x)
这个基本公式有许多常用的变体。然而,所有的 sigmoid 函数在绘制时都会采用某种形式的 S 曲线。当输入为零时,输出也为零。然而,当输入值变为正值时,输出最初(大致)呈指数增长,但最终在水平渐近线表示的固定值处达到最大值。这个最大输出值反映了生物神经元可以产生的最大电脉冲强度。
添加隐藏层
在更复杂、更现实的神经模型中,至少有三层单元:输入层、输出层和一个或多个隐藏层。输入层从系统试图解释、理解、感知、学习、记忆、识别、翻译等的外部世界接收原始数据。相比之下,输出层传输网络最终处理后的响应。然而,位于输入和输出层之间的隐藏层是驱动最先进的人工神经网络的机器学习的关键。
大多数建模假设各层完全连接。在完全连接的神经网络中,一层中的所有单元都连接到其相邻层中的所有单元。
反向传播
你可以认为反向传播是神经网络中允许网络学习的过程。在反向传播过程中,网络处于不断训练、学习、调整和微调的过程中,直到它更接近预期的输出。反向传播通过使用损失函数比较预期输出和实际输出进行优化。结果是一个误差值,或成本,反向传播使用它来重新校准神经元之间的网络权重(以找到最相关的特征和输入,从而产生期望的输出),通常是在众所周知的梯度下降优化算法的帮助下。如果存在隐藏层,那么该算法也重新校准所有隐藏连接的权重。每一轮重新校准后,系统再次运行。随着误差率变*,每一轮重新校准都变得更加精确。在反向传播网络的输出与预期输出紧密匹配之前,这个过程可能需要重复数千次。在这一点上,可以说网络是完全训练有素的。
考虑清楚
随着人工智能投资和开发达到新的高度,这对人工智能爱好者和有抱负的开发人员来说是一个激动人心的时刻。然而,重要的是首先要好好看看人工智能背后的 it:人工神经网络(ANN)。这些计算模型模拟了生物神经网络中的基本计算特征。神经元变成感知器或简单的单元;树突成为输入;轴突成为输出;电脉冲强度成为连接权重;神经元的触发强度函数成为单元的激活函数;一层层的神经元变成了一层层完全连接的单元。将所有这些放在一起,您可以按原样运行您完全训练好的前馈网络,或者您可以训练和优化您的反向传播网络以达到所需的值。很快,你就可以拥有你的第一个图像识别器,自然语言处理器,或者任何你想出来的新的人工智能应用程序。
感谢您的阅读,如果您喜欢这篇文章,请分享这篇文章,或者订阅我在 JasonRoell.com 的博客,或者在 LinkedIn 上关注我,我在那里发布了我认为普通程序员甚至技术爱好者都感兴趣的技术话题。
祝你有美好的一天,继续学习!
从前四到甜蜜的 16 岁:我如何预测锡拉丘兹将颠覆密歇根州立大学
原文:https://towardsdatascience.com/from-first-four-to-sweet-16-how-i-predicted-syracuse-would-upset-michigan-state-32fc95c96fa4?source=collection_archive---------14-----------------------
正如其他人注意到的那样,NCAA 锦标赛的前两轮相当疯狂。用我自己对冷门的定义(一场被排名比对手低至少 4 位的弱队获胜),仅在周日就有 4 场冷门。到目前为止,总共有 10 场冷门,已经超过了每场比赛 9 场的平均水平。还有 15 场比赛要打!
周日的所有冷门都令人震惊,但也许最令人震惊的是锡拉丘兹大学对密歇根州立大学的胜利。在周日最受欢迎的北卡罗来纳、泽*尔、辛辛那提和密歇根州之间,斯巴达有最大的分差8 分,这意味着密歇根州有 80%的胜算。与大多数年份一样,汤姆·伊佐的队伍是一个深入发展的威胁,他们确实被许多专家选为进入最后 4 强的。
但是你不会在我的范围内找到第二轮之后的密歇根州立大学,因为我的不安预测模型预见到了这一点。我的模型使用机器学习来检测冷门让锡拉丘兹有 81%的机会击败密歇根州立大学,进入甜蜜的 16 强。
老实说,我很震惊地看到这场比赛的爆冷概率如此之高。对密歇根州立大学的热爱不仅限于公众和专家;甚至先进的评级系统也将密歇根州立大学列为全国最好的球队之一。
今天,我仔细观察这两个团队,以理解为什么我的模型正确地预测了这场混乱。
冷门评论:雪城超过密歇根州立大学
是什么因素让这款游戏进入冷门警戒?我将着眼于这场比赛的三个突出特点。
锡拉丘兹大学的赛程对 11 号种子选手来说异常艰难
锡拉丘兹大学参加了 ACC,这是一个汇集了通常被认为是全国最好的发电站项目的会议。今年橘子有一个残酷的会议名单,包括北卡罗莱纳州两次,弗吉*亚两次,杜克大学和克莱姆森,扔在一个非会议游戏对堪萨斯的好措施。关于锡拉丘兹的整体记录的问题让他们在锦标赛上泡沫,但在他们的 13 场比赛中,9 场输给了 NCAA 锦标赛球队。Sports-reference.com 将他们的赛程排在全国第 19 位,相比之下密西根州排在第 56 位。
11 种子球队通常都这么难打赛程吗?答案是响亮的不。
Syracuse played a much tougher schedule than typical 11-seeds
在左侧,我显示了 2003 年至 2017 年所有 11 号种子的赛程评级强度,以及他们的锦标赛对手的赛程强度。在所有 11 个种子队中,只有 7 支球队今年的赛程比锡拉丘兹更艰难。
橙衣军团今年面临特别好的进攻,因为他们的对手平均进攻效率在全国排名第十。虽然 4 场对抗 10 大进攻(杜克,北卡 2x,堪萨斯)的比赛确实产生了 4 场失利,但防守精英进攻的经验可能有助于橙衣军团遏制斯巴达的强大进攻。密歇根州立大学在这个赛季平均每场比赛得 80 分。对锡拉丘兹,他们得了 53 分。
对于一个 3 号种子来说,密歇根州立大学在保护球方面表现平平,在历史上也不擅长制造失误。
1-3 号种子队通常是平衡的队伍,在球场两端都很强。密歇根州立大学队也不例外,他们的进攻效率排名第 13,防守排名第 11。但是在所有的三号种子队中,密歇根州立大学在比赛的一个方面一直很糟糕:制造失误。
营业额百分比衡量的是在营业额中所占的百分比,并根据球队的进攻和防守分别计算。下面我展示了自 2003 年以来所有三号种子队的防守失误率和进攻失误率。
Michigan State had the lowest defensive turnover rate among all 3-seeds since 2003
在整个赛季中,斯巴达人的防守只迫使对手 14%的失误。这是自 2003 年以来三号种子选手的最低水平。而且,密歇根州立大学没有平衡这种低防守失误率和进攻中特殊的控球保护,因为他们 19%的财产都以失误告终。这是三粒种子的中间位置。
赢得篮球比赛是不是一定要赢得翻身仗?不总是这样,特别是对于像密歇根州立大学这样的精英得分球队。但是更好的控球保护通常会有所帮助,随着锡拉丘兹大学周日以 14 比 12 赢得了翻盘战,并且仅以 2 分之差获胜,我相信密歇根州立大学会很乐意有几个这样的球员回来。
这场 3 对 11 的比赛有着极其罕见的精英教练对决
毫无疑问,密歇根州立大学的汤姆·伊佐和锡拉丘兹大学的吉姆·伯海姆都是教练精英,在比赛中名列前茅。在他们两人之间,他们拥有 2 次全国冠军,12 次四强出场,16 次常规赛冠军。他们都已经在名人堂了。这是一些严重的硬件。
在最初几轮比赛中,顶级锦标赛球队的教练通常会面对简历不如自己丰富的教练,但在这里肯定不是这样。3 号种子教练在第二轮面对这样的精英教练比赛的几率有多大?几乎没有。
This 3 vs 11 game was an extremely rare match-up of elite coaches
对于自 1985 年以来的所有 3 对 11 比赛,我显示了两位教练的比赛经验,用数字表示他们曾经走过的最远回合(添加了一些水平“噪声”以查看数据点)。通常情况下,3 号种子教练面对 11 号种子教练,他们没有深入的比赛。事实上,54%的情况下,3 号种子教练面对的是一个从未赢过锦标赛的 11 号种子教练。
在这种情况下,两位教练之前都参加过(并赢得了)全国决赛。自 1985 年锦标赛扩大到 64 支球队以来,这种情况只发生过一次,而且即使是这一次也有资格赛。2013 年,11 号种子明*苏达队的教练是 Tubby Smith,他早在 1998 年就在肯塔基州赢得了戒指。
这里的重点不一定是博海姆是一个比伊佐更好的教练。只是当 3 号种子在第二轮面对 11 号种子时,3 号种子教练通常不必与名人堂成员决斗。在这一次,策略无疑发挥了作用。当落后 3 分时,博海姆明智地拒绝了密歇根州立大学任何扳平 3 分的机会,而是选择故意犯规并放弃 2 次罚球。密歇根州立大学赢得或平的唯一机会是在最后一秒绝望的半场投球。它失败了,彻底颠覆了。
结束语
这一分析强调了这两个团队之间一些真正有趣的趋势,但我不能肯定地说,这些是预测这场比赛的主要因素。我的模型使用每个团队的许多特征来预测沮丧的可能性,而这些只是导致沮丧的等式的一部分。
我希望你喜欢我沮丧的预测。谁会是下一个成为冷门牺牲品的队伍?点击 @ 在 Medium 或 Twitter 上关注我,了解更多信息!
从游戏到金融科技:我的 DS 之旅
原文:https://towardsdatascience.com/from-games-to-fintech-my-ds-journey-b7169f08b6ad?source=collection_archive---------5-----------------------
Source: Tech in Asia, https://www.techinasia.com
作为一名分析师和数据科学家(DS)在游戏行业工作了五年后,我决定过渡到创业生活,加入一家金融技术部门的公司。虽然这是一个新的领域,有新类型的问题需要解决,但我在游戏行业发展的许多技能仍然与我的新角色相关。这篇文章的目标是展示如何在一个领域学习数据科学技能可以转移到新的意想不到的机会。
我的新角色的一个关键区别是从企业对消费者(B2C)到企业对企业(B2B)的转变。我现在不是对数百万消费者进行分析,而是构建数据产品,帮助数百家非营利组织和营利性公司。对产品分析的关注也越来越少,而是更多地关注为我们的最终用户提供准确的数据。我现在不是探索来自视频游戏和视频流媒体服务的跟踪数据,而是研究来自各种不同数据源的数据,包括房地产销售和政治捐款。
我在新职位的主要目标是建立预测模型,为美国富裕家庭提供准确的资产净值估算。数据源是不同的,我们的客户是企业而不是消费者,但是数据科学的许多关键功能可以很好地跨越这些领域。以下是我在这个新角色中运用到的一些技能。
探索性数据分析(EDA) 能够挖掘数据集对于任何领域都很重要。数据科学家应该能够可视化数据的分布,识别异常值,并找到数据中的相关性。
探索性分析的目标通常是确定数据中是否有预测结果的信号。例如,在游戏行业中,一个常见的目标是识别用户是否会流失或在游戏中失败。这可以表示为一个分类问题,但通常提供汇总统计数据,如漏斗分析,就足以为游戏团队提供反馈。在我的金融科技角色中,一个共同的目标是识别与净值相关的特征,并确定我们是否可以设计出额外的特征来提高我们对净值估计的准确性。
以下是我在这些领域中调查的问题类型:
- 游戏:新的订阅模式会蚕食销售额吗?
- FinTech: 政治献金和净资产有关联吗?
我使用了类似的方法来探索这些类型的问题,包括用于数据管理的 SQL 和用于可视化和相关性分析的 R。
实验 Twitch 的核心原则之一是实验决定,数据科学团队使用 A/B 测试和分阶段推出的组合来实现这一目标。实验的一个重要元素是能够衡量变化的结果,并确定变化是否对用户行为产生了重大影响。在我目前的角色中,我们经常需要确定营销活动是否对我们的客户产生了可衡量的影响,类似的方法可以用于这类任务。在这两种情况下,我都使用 bootstrapping 来测量实验中治疗组和抵制组之间的差异,并测试统计显著性。
以下是这些不同领域的实验例子:
- 游戏:一款应用的重新设计是否提高了移动用户的留存率?
- 金融科技:营销活动推动了收入增长吗?
类似的方法可以用来衡量这些实验的影响,即使这些领域是非常不同的。
预测建模 大多数数据科学角色的另一项重要技能是构建预测模型。在游戏行业,这通常涉及到建立模型来预测可能购买游戏或游戏失败的用户。如果您可以检测出哪些用户最有可能执行这些操作,您可以推动用户采取所需的操作,例如发送电子邮件让玩家登录并领取游戏内奖励。预测模型的另一个用途是评估特征的重要性,以便指导游戏设计。例如,在电子艺界,我建立了一个回归模型,该模型确定,探索更多剧本的用户通常比专注于优化少数特定剧本的玩家拥有更低的保留率。
当改变领域时,我必须做出的改变之一是使用新的度量来评估预测模型的性能。对游戏行业分类任务有用的指标,如 F1 得分和 ROC,并不能很好地转化为金融科技领域的任务,如预测房屋的价值。对于此回归任务,您可以使用相对误差、相关系数或其他误差指标,如平均对数误差。
以下是我为这些领域建立的预测模型的例子:
- 游戏:哪些用户最有可能购买订阅?
- 金融科技:哪些家庭最有可能向非营利组织捐款?
与 EDA 类似,相同的工具可以用于构建跨这些领域的预测模型,我在这两个领域中都使用了 R 来构建原型模型。
数据产品 除了原型预测模型之外,数据科学家还应该有一个适当的流程来扩展模型以进行部署。在游戏行业,这通常涉及将模型规范交给工程团队,而在我目前的职位上,我更多地参与模型的产品化。在这两个领域中,您可以使用一种中间模型格式,比如 PMML 来分离模型训练和模型部署任务。
在这两个领域中,我构建了批处理模式的数据产品,每周计算数百万条记录的值:
- 游戏:计算订阅转换分数。
- FinTech: 为房地产创建估价。
我执行这些任务的工具集在角色之间发生了变化。我以前与工程团队一起构建定制解决方案,现在已经转向使用开放工具,如 PMML 和 Apache Beam,来生产模型。
结论 在我的数据科学职业生涯中,我从游戏行业转向了金融科技,并在新的岗位上使用了许多不同的数据源,但我在游戏中开发的许多技能都得到了很好的转化。探索性分析、实验、预测性建模和构建数据产品对所有数据科学家来说都是有用的技能,与他们所应用的领域无关。
我的日常工作重心也发生了变化,但这是因为角色类型和领域的变化。我已经从专注于产品分析的角色转变为更专注于机器学习的角色。我花更少的时间构建仪表板,花更多的时间编写代码和提交 PRs。
本·韦伯是意外收获数据的首席数据科学家,我们的任务是确定世界上每个家庭的净资产。
如果你今年参加 GDC,请随时在 twitter 上给我发消息。
从 Keras 模型到角度应用
原文:https://towardsdatascience.com/from-keras-model-to-angular-application-491d3f6c4455?source=collection_archive---------10-----------------------
介绍
与 TensorFlow 合作服务我想,如果也能为 Keras 模特服务,那就太棒了。 Keras 的优势是显而易见的——它大大简化了模型开发,并允许比纯 TensorFlow 框架更快地尝试模型。
另一个动机是,我想让客户端独立于庞大的 TensorFlow 框架,并使用非常有限的一部分服务功能。当然,我想直观地显示结果,而不需要通过枯燥的 JSON 输出:-)
用 TensorFlow 服务 Keras 模型
Keras 提供高级神经网络 API,能够在 TensorFlow 、 CNTK 或 Theano 之上运行。基本上,它抽象了那些框架,更容易理解和学习,并且允许你用更少的代码做更多的事情。
TensorFlow Serving 是一款用于托管机器学习模型的软件。它的主要用途—高性能生产服务。它是用 C++编写的,使用了客户端用于计算的 Servables 的概念。
如何与 TensorFlow 服务器对话
TensorFlow Serving 提供 gRPC API 用于执行回归、预测和推理任务。这种 gRPC API 比 HTTP 协议上的 REST API 具有更好的性能,但是不能被 Web 应用程序简单地使用。因此,在我看来,gRPC 是内部客户的完美选择,但是它应该被一个向外部世界提供 REST API 的服务所包装。
犬种检测器
对于我的示例应用程序,我使用了一个狗品种检测器,它是我在 Udacity 纳米学位课程期间实现的。我们想要解决的问题是给定一幅狗的图像进行品种检测。该模型利用了卷积神经网络(CNN)架构,并在 ImageNet 数据集模型上进行预训练(我选择了 DenseNet 201 )。该模型是用 Keras 库实现的。
应用的第二部分是一个 Node.js 服务,包装 TensorFlow 服务的 gRPC API,对外提供 REST API。该服务尽可能少地依赖 TensorFlow 它使用修改过的 protobufs 文件和 gRPC 库来处理服务器请求。因此,我们不需要在这里安装任何巨大的 TensorFlow 包。
最后一部分是一个非常简单(也不太好)的 Angular 应用程序,它允许选择狗的图像,向我们的包装服务发送请求,并显示品种。
代码可以在我的 GitHub repo 中找到。如果你觉得有用,可以随意复制、修改和使用:-)
从模型到应用
让我们深入研究一下实现细节。这里有 3 个主要部分:
- 使用 Keras 创建和训练模型,并为 TensorFlow 服务做准备
- 实现一个向外界提供 REST API 的包装器服务
- 创建一个简单的狗品种预测和结果显示的应用程序
犬种检测器模型
我不想用很多代码把文章弄乱。相反,我将提供实现的链接,并解释我遇到的主要挑战。
我创建模型的方法相当简单(你可以在dog _ breed _ detector _ trainer . py中遵循它),Francois Chollet 在 Keras 博客中对此做了很好的解释。这些步骤是:
- 用权重加载预训练的 DenseNet 201,不加载顶层,并从预训练的网络中提取所谓的瓶颈特征。我已经在data _ extractor . py中实现了这个。
- 创建一个简单的顶层模型,该模型使用提取的要素作为输入,并且只有全局平均池和完全连接的图层。模型本身在dog _ breed _ detector _ model . py中实现。
- 训练顶级模特并保存检查点。这里 可以找到 。
- 创建“连接”预训练的 DenseNet 201 和训练的顶部模型的最终模型。这在final _ model . py中实现。
- 为 TensorFlow 服务准备并保存最终模型。你可以在这里 找到 。
主要挑战是找到一种合适的方法将 Keras 模型转换为 TensorFlow,并为 TensorFlow 服务做准备。基本上,我们这里有两个任务:将 Keras 模型转换为 TF 估计器,并将估计器导出为 TensorFlow 服务。
从版本 1.4 开始,我们可以将 Keras 模型转换为 TF 估计量——只需调用 model_to_estimator() 函数,就大功告成了!
tf_estimator = model_to_estimator(keras_model=model)
现在,我们可以保存估计器,用于这里描述的。这只是一个对 export_savedmodel() 函数的调用,带有一个用于服务的接收器函数。这样一个函数在最终模型之上创建了一个附加层,并负责输入解析。在我们的例子中,它将输入的 JPEG 图像转换成一个 3D 张量,可以被模型使用。
tf_estimator.export_savedmodel(export_dir,
serving_input_receiver_fn,
strip_default_attrs=True)
为了创建、训练和准备服务模型,首先安装 unzip (用于解压缩下载的带有狗图像的档案):
sudo apt-get update
sudo apt-get install unzip
然后克隆存储库,切换到模型服务目录,下载并解压缩狗图像,并训练模型:
git clone [https://github.com/Vetal1977/tf_serving_keras.git](https://github.com/Vetal1977/tf_serving_keras.git)cd tf_serving_keras/model_servingcurl [https://s3-us-west-1.amazonaws.com/udacity-aind/dog-project/dogImages.zip](https://s3-us-west-1.amazonaws.com/udacity-aind/dog-project/dogImages.zip) --output dogImages.zipunzip dogImages.zip
mv dogImages dog_images
rm dogImages.zippython dog_breed_detector_trainer.py
我的环境包括:
- 康达 4.3.14
- Python 3.5.4
- TensorFlow 1.8 的 GPU 版本
- Keras 2.1.6
Node.js 包装服务
第二个组件是一个包装器服务,它向外界提供 RESTful API,并将 gRPC 与 TensorFlow 服务器对话。附加要求—尽可能减少对 TensorFlow 的依赖。我为服务实现选择了 Node.js 和 Typescript。
第一步是准备 proto bufs——我把它们从官方仓库中拿出来,扔掉所有我不需要的东西。你可以在这里修改我的版本。我动态加载 protobufs,即在运行时,然后创建一个预测服务,如下所示:
this.tfServing = grpc.load(this.PROTO_PATH).tensorflow.serving;
this.client = new this.tfServing.PredictionService(
this.tfServerUrl, grpc.credentials.createInsecure());
动态加载的优点是——您不需要通过每次修改 protobufs 来重新生成 Typescript 代码。缺点是性能下降。因为我只加载了一次 protobufs,所以这个缺点并不严重。
现在,当通过 REST 接口调用服务时,我们获取输入数据(图像作为 base64 编码的字符串)并向 TensorFlow 服务器创建 gRPC 请求—请在源中找到详细信息。
包装器服务是一个 Node.js express 应用程序,使用inverisfy进行依赖注入,使用 inverisfy express 实用程序 进行 REST API 实现。
我的服务的 API 基本路径是 /api/v1 ,我的控制器实现了唯一的端点 /predict_breed ,它允许图片上传并在 TensorFlow 服务器上调用狗的品种预测。要构建一个项目,请执行以下命令(我假设您已经克隆了 repo):
cd tf_serving_keras/detector-api
npm install
npm build
我的环境包括节点 8.11.3 和 npm 6.1.0。
角度应用
最后一部分是一个简单的角度应用,带有一个按钮来选择一个图像目录和一个区域,用于显示带有预测品种名称的图像。这里没有什么新奇的东西——我使用这个指南创建了一个新的 Angular 项目,并根据我的需要扩展了代码。
与包装器服务对话的客户端在detector . service . API . client . ts中实现。实现的注意事项——我有一个抽象类,它声明了一个预测方法和它的两个实现——上面提到了其中一个,第二个是我尝试使用一个全新的tensor flow Serving RESTful API。稍后我会提供一些评论。
我们需要注意 CORS 机制。 Angular HttpClient 依赖于 XMLHttpRequest ,我不得不将的后续头添加到我的 Node.js 包装服务中,以获得应用程序中的响应:
'Access-Control-Allow-Origin': '*'
这是一个典型的应用程序屏幕,上面有狗的图像和预测的品种:
要构建一个项目,执行以下命令(我假设您已经克隆了 repo):
cd tf_serving_keras/detector-app
npm install
npm build
使用 Docker 进行本地测试
老实说,我懒得分别启动和运行所有 3 个组件:-) Docker 和 Docker Compose 让我的生活更轻松。我需要 3 个 Docker 容器——一个用于托管我的模型的 TensorFlow 服务,一个用于包装服务,一个用于我的应用程序。我安装了以下版本:Docker 18.03.1-ce 和 Docker Compose 1.21.2。
TensorFlow 服务的 Docker 图像
在创建 Docker 映像之前,您必须有一个为 TensorFlow 服务的导出模型——请参见上文如何操作。上次为 TensorFlow 服务创建 Docker 容器花费了很多精力。从那以后事情发生了变化,现在我们可以用 apt-get 安装服务组件,而不需要克隆存储库和自己构建服务器。
echo "deb [arch=amd64] http://storage.googleapis.com/tensorflow-serving-apt stable tensorflow-model-server tensorflow-model-server-universal" | sudo tee /etc/apt/sources.list.d/tensorflow-serving.listcurl https://storage.googleapis.com/tensorflow-serving-apt/tensorflow-serving.release.pub.gpg | sudo apt-key add -sudo apt-get update && sudo apt-get install tensorflow-model-server
我创建了一个 Dockerfile ,在这里我执行了那些命令,复制了为服务模型准备的内容并启动了服务器。如果要创建 Docker 映像,请执行以下命令:
cd tf_serving_keras/model_serving
<activate your Python environment>
python dog_breed_detector_trainer.py
docker build -t model-serving:latest -f Dockerfile .
Node.js 包装服务的 Docker 图像
包装器服务的 Dockerfile 基于节点 8.11.3 镜像。它将源文件复制到映像,构建它们并启动服务。没什么特别的,都是标准的。
角度应用的 Docker 图像
我的应用程序的 Dockerfile 使用了多阶段构建。首先,我们使用 Node 8.11.3 image 构建应用程序,然后使用 Nginx image 将其隐藏在 Nginx 服务器后面,这在生产环境中很有意义。
将它们组合在一起
我们不会也不应该一个接一个地创建 3 个 Docker 容器。相反,我们将它们组合在一起,并用 Docker Compose 使它们彼此可见。在 docker-compose 文件中,我有 3 个服务,属于同一个网络。应用依赖于包装器服务,包装器服务依赖于 TensorFlow 服务。这些服务公开了容器端口,并且可以通过它们的名称相互通信。
要运行完整的应用程序,请执行唯一的命令
cd tf_serving_keras
docker-compose -f docker.compose.yaml up
打开浏览器,进入本地主机。您应该能够看到应用程序,选择图像并看到结果。不要忘记关闭容器
docker-compose -f docker.compose.yaml down
尝试 TensorFlow Serving 1.8 及其 RESTful API
当我准备好我的实现时,我发现从 1.8 版本开始 TensorFlow 服务也提供了 RESTful API。这是一个相当新的功能,我想尝试一下。
不幸的是,它有一些问题。首先,对于 CORS 机制,您必须有一种特殊的代理,因为您不能更改服务器代码。最受欢迎的是 cors-anywhere 。我创建了一个*包装器并将其打包到 Docker 容器中。如前所述,我在应用程序中实现了一个客户端,它通过 REST 直接与 TensorFlow 服务器对话。
其次,应该将图像数据包含在发送给服务器的 JSON 对象中。对于大图像,这不是一个正确的方法,我总是倾向于使用多部分/形式数据来实现这个目的。
如果您想尝试,请查看客户端源代码,并使用
docker-compose -f docker.compose.cors.yaml up
GPU 支持
如果你有一台装有 NVidia 显卡的电脑,并且安装了 CUDA 和 CUDnn 库,那么我们也可以在 Docker 中使用它们。但是我们需要做一些准备:
- 确保 Docker Compose 的版本至少是 1.19.0
- 安装 NVidia 容器运行时。我使用了以下命令:
curl -s -L https://nvidia.github.io/nvidia-container-runtime/gpgkey | \
sudo apt-key add -distribution**=$(**. /etc/os-release;echo $ID$VERSION_ID**)**curl -s -L https://nvidia.github.io/nvidia-container-runtime/$distribution/nvidia-container-runtime.list | \
sudo tee /etc/apt/sources.list.d/nvidia-container-runtime.listsudo apt-get updatesudo apt-get install nvidia-container-runtime
- 通过 Docker 注册该运行时。我对守护程序配置文件使用了该方法:
sudo tee /etc/docker/daemon.json <<EOF
{
"runtimes": {
"nvidia": {
"path": "/usr/bin/nvidia-container-runtime",
"runtimeArgs": []
}
}
}
EOF
sudo pkill -SIGHUP dockerd
现在快跑
docker-compose -f docker.compose.gpu.yaml up
你应该得到一个 GPU 驱动的应用程序版本。你可以在资源库中找到支持 GPU 的 Dockerfile 和 Docker-compose 文件。
注意:可能需要几个*时才能看到系统启动并运行。原因是——我们仍然需要编译 TensorFlow 的 GPU 版本来创建一个合适的 Docker 图像。
结论
对我来说,实现从 Keras 模型到 UI 的完整深度学习应用程序是一次很好的体验。我尝试和使用了一些新的东西,并且为了在本地运行和测试所有东西,我需要解决一些挑战。我希望这对您的目的也有用:-)
从迷因到机器:将我们自己转移到人工智能宠物
原文:https://towardsdatascience.com/from-memes-to-machines-transferring-ourselves-to-our-ai-pets-1a9578279f93?source=collection_archive---------2-----------------------
“人无想法,想法有人。”—卡尔·荣格
理查德·道金斯在他的书《自私的基因》中谈到了一种迷因。他将迷因定义为任何在人类文化中表现得像基因的东西。它有一种繁殖机制,通过几代人的突变、繁殖或减少来实现。他说的目的是淡化基因是自然选择的唯一单位。
模因可以像曲调一样简单,也可以像文化意识形态一样复杂。我们的身份与拥有我们的迷因密切相关。即使缺乏基因相似性,我们还是会强烈偏向那些分享我们认为重要的迷因的人。如果一个家庭成员被一种对立的迷因如政治观点所占据,我们可以认为他们是蔑视。我们甚至会对那些分享表面模因的人表现出偏见,比如喜欢同一个音乐艺术家或运动队。
我们不能用机器进行生物繁殖,但将我们的迷因传递给我们的人工智能后代可能同样令人本能地满足。由于诸多不便,生物繁殖在高智商人群中已经过时了。这是痛苦的,它使我们的心智能力紧张,使社会交往紧张,减少了我们的物质资源。然而,生孩子被认为是我们能拥有的最有意义的经历之一。既然如此多的人致力于他们的事业,我们可以说,在这些个体中,模因的培养比生物繁殖的经验更丰富。
机器的迷因
我设想这个过程是在虚拟环境中进行的训练,在虚拟环境中,我们通过与我们有高度相似情绪控制输出的虚拟宠物来传递我们的想法。就像电影中的动画角色一样,它的身体将能够合成类似人类的表情和声音。然而,与电影中的角色不同,我们将教虚拟宠物他们表情的含义。
从一些基本技能开始,人工智能将把我们脸上的表情、声音和我们展示给他们的图像拼凑在一起。由此,他们将合成他们自己的表达方式,他们将因此受到我们的奖励和谴责。
这个过程将非常类似于从出生起抚养一个被收养的孩子。尽管没有生物学上的联系,但通过共同的经历和模因的传递,人们会感到一种亲密感。
这个可数字化定制的宠物将被设计成保存我们的迷因,并以一种独特的方式向我们表达新的、令人愉快的想法,但有一些问题很难忽视。如果人工智能宠物根据我们教给它的东西对道德状况做出反应,那么人工智能本身有道德吗?道德是需要同理心还是仅仅是一种技能?
可以说,道德是因为社会原因而进化的。它提供了一个共同的界面,让我们一起工作,以收集更多的资源。
人工智能将通过迷因与我们互动,其中最重要的是道德准则,以实现共同繁荣。饲养人工智能宠物的过程将在人和机器之间产生深刻的人类共性。本质上,通过培养一个虚拟的 AI,我们正在设计理想的交流界面。
无痛苦的养育?
我想把这个想法延伸到一个有些人可能认为亵渎神明的问题。如果我们如此巧妙地设计这种体验,以至于成为一个人工智能的父母比成为一个亲生父母更让人本能地满足,那会怎样?如果我们把它设计成最*化痛苦和最大化便利呢?
这一过程的成功是否意味着我们的灭绝或进化,或者两者都不是?最终结果会带来一个“耶稣基督”的人工智能吗?一个完美的人,他的每一个动作都代表着我们所信仰的理想。好莱坞如此痴迷于邪恶的人工智能,我想知道他们是否想过世界上有耶稣基督的可能性。毫无疑问,它不会那么引人注目。
耶稣对世界
自从我的我已经开始问亵渎神明的问题:如果一个虚拟的国家充满了耶稣基督,需要多少个人工智能魔鬼才能摧毁它?我们会发明一种可怕的箔片来对抗它吗?
结论
在这篇文章中,我可能掉进了哲学思考的兔子洞(毫无疑问,有些是有价值的),但我目前感兴趣的主要问题是将我们的迷因转移到我们的机器上的工程问题。这是一个需要很长时间来实现的过程,我可能永远没有机会,但我会在未来的帖子中提出一些想法。
从中年母亲到编码学员:通过技术重塑
原文:https://towardsdatascience.com/from-middle-aged-mom-to-coding-mentee-reinvention-through-tech-77b3e5772240?source=collection_archive---------3-----------------------
作为一个女人,一个母亲,一个中年人,我一直想恰当地讲述我的重塑故事。把你以前的大部分职业选择抛向空中,让它们随风而去,然后选择新的(有挑战性的)东西,这不适合胆*的人。但这令人振奋,也许会激励更多处于职业生涯中期的人考虑做出类似的转变。我要感谢 Chipy 导师项目让我开始记录它——我很幸运被选为今年秋季的学员之一,写博客是项目要求之一。
Oh those career choices…just some weed seeds, blowing away in the wind of change…
多年来,我是一名文科和艺术学院的大学教授,陷入了一个经典的兼职陷阱——在多份工作之间奔波,试图找到足够的工作来*持生活。在那之前,我是博物馆馆长。我有文化史博士学位。这些似乎都不能为转向编码或数据科学工作奠定基础。但我一直对数据充满热情,对更好的东西有着贪婪的胃口。我研究的课题之一是广义上的地图,这当然是数据可视化的一种形式。从当地政治到食品合作社的志愿者项目工作让我接触到了更高层次的 Excel,从命令行工作,并创建我自己的图形和图表。
Phoenix from the flames???
当我在学术生涯中筋疲力尽时,我看看我能做些什么。我自学了如何用 Wordpress 制作一个基础网站,并为我的学术研究积累了一个关注的重要社交媒体(有趣的是:我的成名是因为我是一名纹身历史学家)。我开始寻找自由职业的机会。一个老朋友把我和她的一个老朋友联系了起来,一个新的职业生涯开始了。
我成了众包人体图像网站MyBodyGallery.com的唯一正式员工。你可以在我为新妈妈们可以编码项目写的的短文中读到更多关于这方面的内容。在这里可以说,它打开了许多大门,从了解定制代码站点的后端到学习如何使用 SQL。我知道下一步是解决正确的编码。我对数据的兴趣和经验使得数据科学训练营变得显而易见。我选择了大会的,并彻底享受了这种体验(即使连续三个月每周 5 天都要上课,每天晚上都要做作业,每个周末都要做项目,这种睡眠剥夺让我想起了身为婴儿父母的痛苦)。
I’m not sure I’ve been able to take a proper nap since February…zzzzzzzzz….
我为我在训练营的顶点项目感到自豪——它将我的纹身研究与数据科学结合起来,为一个计算器创建了一个预测模型,它将告诉一个崭露头角的作者有多少图书馆最终可能拥有他们的书……仅仅基于书名。它并没有成为我所希望的工具的全部,但是它确实有助于标题的选择。你可以在我的 Github 上了解更多信息。
但是和大多数 bootcamp capstone 项目一样,我甚至没有足够的时间来真正做我想做的事情:让这个计算器真正出现在现实世界中。我想把它放在我创办的一个新生的数字人文基金会的网站上,这个基金会就是纹身历史和文化中心。这就是 Chipy 导师计划的用武之地。我很高兴能成为 web dev track 的一员,在那里我开始将这些技能添加到我的工具包中(感谢 Joe Jasinski 作为我非常耐心和有帮助的导师)。现在这有点令人生畏,但我总是喜欢陡峭的学习曲线。请继续关注,看看这个计算器是如何工作的!
A mock-up of what the calculator page might look like
如果我不抓住这个机会谈一谈重返学校和抽出时间学习编程的斗争,同时又是一个单身母亲,那我就是失职了。命运给了我一个耐心而独立的女儿,她能理解妈妈的忙碌,并能忍受被拖着去面对各种情况。营业时间训练营起作用了,因为她在学校的时候我也在学校。Chipy 非常乐于助人,让她跟我一起参加了我的第一个 Python 项目之夜。她花了一个晚上的时间建造了一个新的《我的世界》世界,然后在会议结束时带他们参观了一下这个世界,交了几个成年朋友(冥界之门和龙蛋之类的东西)。Chipy 董事会非常乐于看到他们是否可以开始正式的儿童保育或教育经历,以帮助处于类似情况的其他人(感谢雷·伯格把我的想法带给整个董事会)。我已经让这位老姐参加了几个编码营和精彩的编码、游戏、学习的课程,也许她可以在未来几年帮助解决技术领域的性别失衡问题。我希望通过看到我永不停止学习和挑战自己,她不会满足于一个没有出路的职业生涯。也许在我参加这个项目的几个月里,她可以代替那只花栗鼠成为花栗鼠的吉祥物:)
Shout-out to Target’s excellent Cat and Jack brand for the “Create with Code” shirt (these are Lego sculptures the kiddo made while she was hanging at General Assembly on a no-school day)
从范数到正交性:带有直观例子的机器学习基础数学第 2/3 部分
原文:https://towardsdatascience.com/from-norm-to-orthogonality-fundamental-mathematics-for-machine-learning-with-intuitive-examples-57bb898e69f2?source=collection_archive---------9-----------------------
为了理解机器学习算法的数学,特别是深度学习算法,从基础到更高级建立数学概念是必不可少的。不幸的是,数学理论在许多情况下太难/抽象/枯燥,难以消化。想象你正在吃一个比萨饼,喝一杯可乐总是更容易和更有趣。
这篇文章的目的是为基础数学理论提供直观的例子使学习体验更加愉快和难忘,那就是鸡翅配啤酒,薯条配番茄酱,里脊配葡萄酒。
包含 3 门课程的机器学习基础数学课程组织如下:
从标量到张量:带有直观例子的机器学习基础数学第 1/3 部分
- 什么是标量、矢量、矩阵和张量?
- 标量、向量和矩阵之间的加法
- 标量、向量和矩阵之间的乘法
- 单位矩阵和逆矩阵
- 对角矩阵和对称矩阵
从范数到正交:带有直观示例的机器学习基础数学第 2/3 部分
- 向量的 1-范数,2-范数,最大范数
- 正交和标准正交向量
- 正交矩阵
从特征分解到行列式:带有直观例子的机器学习基础数学第 3/3 部分
- 矩阵的特征分解:特征值和特征向量
- 跟踪运算符
- 方阵的行列式
在本文中,我们将通过直观的例子,从范数到正交性讨论第 2/3 部分。
向量的 1-范数,2-范数,最大范数
如何度量一个矢量的大*?一种方法是使用范数函数:
- 1-范数:在机器学习应用中,当 0 和非 0 元素之间的差异很重要时,通常使用 1-范数。
例如,向量 v 的 1 范数可以计算为:
- 2-范数:通称欧氏范数,是原点到向量 x 所标识的点的欧氏距离。
Photo credit to wikipedia
通常使用平方 2-范数而不是 2-范数本身来度量向量的大*。原因是平方 2 范数可以计算为:
这比计算 2-范数本身更方便。下面的例子说明了如何计算向量 v: 的 2-范数
- 最大范数:向量中元素的最大绝对值,可以写成:
下面的例子显示了向量 v: 的最大范数的计算
正交和标准正交向量
向量 u 和向量 v 彼此正交当且仅当它们的点积为 0:
例如,在三*欧几里得空间中,
在几何学中,两个正交向量在欧几里得空间中相互垂直:
Photo credit to ubisafe
向量 u 和向量 v 是一对正交的向量的意思是:
它可以扩展到 3-D 欧几里得空间中的下列方程:
举个例子,
因此,我们说,向量 u 和向量 v 是正交的。
正交矩阵
正交矩阵是行和列正交的正方形矩阵:
例如,以下矩阵是正交的,因为:
这意味着如果一个矩阵的转置等于其逆矩阵,则该矩阵是正交的:
因此,正交矩阵是机器学习中感兴趣的,因为矩阵的逆的计算非常便宜。我们需要注意的是,正交矩阵中的行和列不仅是正交的,而且是正交的。
恭喜你!你已经用直观的例子完成了机器学习基础数学的三分之二。你能做到的!
下一步: 从特征分解到行列式:带有直观例子的机器学习基础数学第 3/3 部分
从病人到 Python:成为“数据科学家博士”的思考
原文:https://towardsdatascience.com/from-patients-to-python-thoughts-on-becoming-a-dr-data-scientist-d01aa583b08a?source=collection_archive---------2-----------------------
“当我长大后,我想成为一名医生,因为我想让我的灵魂迷失在点击通知和写便条中。”
说没有孩子。
回到我的时代,我们住院医生用纸和笔写笔记。我们对图表的抱怨包括在特别长的 H+Ps 后严重的手抽筋,或者试图辨认难以辨认的鸡肉划痕。你可以想象当医院转向电子健康记录时我们的喜悦心情(EHR)。对我来说,在 AOL IM 和在线视频游戏中长大后,打字变得轻而易举,笔记也终于清晰可辨。
然后一些邪恶的想法开始给 EHR 增加“功能性”。
几年后,“功能性”导致了我们今天看到的 EHR 这个九头蛇怪物。你砍掉了一个脑袋,解决了一个订单输入故障,EHR 九头蛇又长出了三个脑袋,在它们的位置上弹出了通知窗口。
我正在为执业医师量身定做这个职位。如果那是你,那么我正在向唱诗班宣讲当前的医疗保健基础设施对我们的工作流程和患者护理的影响。然后,你会明白为什么我想在十年的医学训练后回到学校。如果我们要给系统带来改变,并说服我们的同事改变现状,那么我们最好知道我们到底在说什么。
为什么是数据科学?
也许是 2012 年《哈佛商业评论》的标题,“数据科学家:21 世纪最性感的工作”唉,我后来才知道,不是所有的数据科学家都生来平等,也不是所有人都天生性感(尽管我们在努力)。数据科学不是固定的描述;这是一个连续体。它涵盖了从清理和组织数据、限制统计分析中的偏差等极其无趣的事情,到有效地向你的受众传达可操作的发现。熟悉从原始数据到有意义的结论的流程似乎比在游戏的后期追求一个直接的编程学位更有用。
选择加州大学伯克利分校的数据科学硕士( MIDS )项目并不难。虽然听起来不像他们会说话的头,但我真的,真的,真的很喜欢做 MIDS 的学生。它仍然是一个相对年轻的项目,课程不断发展,并且是在线的(除了沉浸周,在那里你可以与科技公司接触),但它在一个国际知名的机构提供了坚实的课程和令人惊叹的师资,有大量的社交机会。不要告诉我不知道你的在线课程的同学——当你两年来每周都看到相同的人时,你会情不自禁地结交一些亲密的朋友(大声喊出 socal-4eva 和 da-mids slack channels!).
MIDS Immersion Week 2017, whereeveryone looks wierd in 3D
所以,对于所有执业医师来说,你应该如何对待这个进入科技世界的信念飞跃呢?
现实一点。
首先,你需要评估你的技能、金钱和时间。举个例子,我有一个博士后研究员基金,这个基金比我作为全职临床医生的正常收入低 30%。另一方面,我一个月有 3 周的研究时间。你可以尽情嫉妒,但请记住,当你开着玛莎拉蒂的时候,我还在吃拉面和鸡蛋(或者至少在为一辆玛莎拉蒂付款)。但我从未上过编码或计算机科学(CS)课程,我认为时间应该是最重要的。你的资助也是一个考虑因素,因为研究生课程并不便宜。当然,Coursera、Udacity 和 Khan Academy 的在线课程非常优秀,许多数据科学家都通过他们的教学促进了自己的职业发展。交几千拿个证好还是交几万拿个毕业证好?作为一名医疗科技行业的新人,我迫切需要在简历上获得街头信誉,所以我选择了后者。
要谦虚。
你不再是精英了。一点也不接近。当然,你挺过了医学院、住院医师和董事会,但是假设你真的没有任何计算机科学背景,当你还在疯狂地谷歌"如何做矩阵乘法"时,你知道比你* 15 岁的孩子将会讨论 LSTM 矩阵的*数我花了几个星期才明白,你可以通过点击 tab 键来自动完成命令行。老实说,我只是觉得我的教授打字非常非常快。不要让我开始参加 Kaggle / kegel 竞赛。最后,准备好 1:3 的家庭作业时间比例——你的同学花在家庭作业上的每一个*时,你都要花三倍的时间。虽然我不想说太多,但现在重温这一点还为时过早。
坚持不懈。
在我的第一个 Python 入门课程中,我认真考虑过放弃,如果我不是更讨厌放弃的话,我会放弃的。有时候,特别是当我住院和随叫随到的时候,抽出时间去上课或参与集体项目是如此的令人生畏,以至于我想蜷缩成一团哭出来。相反,我给自己倒了一杯威士忌,然后开始喝。这很像医学院,在那里学习不是短跑;这是一场马拉松。
不要脸。
对于医生来说,我们的招聘信息相当简单。事实证明,对于未来如何使用自己的数据科学技能,需要进行大量的自我反省。当我面对我在这个项目上投入的金钱和时间,却发现没有适合我描述的人的工作时,我没有预料到那段深深的、黑暗的绝望时期。我不符合数据科学家的特征,精通 SQL,对机器学习(ML)技术了如指掌。我也不是医学信息学家,他们对 EHR、SNOMED 和其他领域的所有东西都有深刻的理解。因此,在毕业前一年,我开始随机联系医疗技术行业的人或数据科学家。如果我在 techcrunch 上读到一篇关于他们的文章,或者看到一个转发的帖子引发了我的兴趣,我会联系他们。在我的巅峰时期,我每周发出 5-10 条信息,大约有 5%的回复,这导致了 30 分钟的电话聊天或谷歌聊天。在这样做了整整一年后,一些随机的信息让我收到了一些采访请求,其中包括一个关于我未来的家 Curai 的请求,我非常兴奋和感激几个月后就可以开始工作了。
冒名顶替。
进入硅谷是令人生畏的。在 SV 有很多聪明的人,他们似乎都互相认识并且穿着 Allbirds 。此外,每三个人中就有一个以几百万美元的价格卖掉了一家初创公司。当你遇到有工程学或计算机科学背景的了不起的医生时,我会想,“谁他妈的需要我?”我那了不起的丈夫改变了我的想法,他向我介绍了“骗子综合症”的概念,在这种情况下,我们不合理地低估了自己的表现和才能。查一下吧,它发生在我们最好的人身上。
要骄傲。
这是我从这次经历中得到的最重要的教训——有很多才华横溢的软件工程师和统计学家可以让我的基本逻辑回归和张量流图相形见绌。但当面对这样的疑问时,我想起了当初为什么要投身数据科学。我可以带来一些纯数据科学家做不到的东西。医疗保健系统需要像你和我这样的人,他们从临床战壕中幸存下来并理解 NLP 和 ML 概念,因为我们可以帮助将我们在医院或患者护理中看到的问题转化为工程师、统计学家、首席执行官、风投、UI 开发人员和其他重要决策者可以理解的术语。有了这些超能力,我们可以开始改变医疗保健系统,这是我们医生知道我们需要的。
祝你好运,希望胜率永远对你有利。
以最*的努力从科学到生产
原文:https://towardsdatascience.com/from-science-to-production-in-minimum-effort-acc9d0db6ec2?source=collection_archive---------20-----------------------
热链接:
---丹泽尔部署框架-
在过去的一年里,我在我工作的组织中完成了许多数据科学项目,我花了数百个*时与数据科学家同事一起工作。
由于数据科学领域非常年轻,所以我的同事以及一般的数据科学家来自不同领域也就不足为奇了。数学、统计学、物理学甚至心理学,这种多样性是非常积极的,因为每个人都从各自的领域带来了自己的优势和观点。我自己来自软件工程,这自然让我从一个工程师的角度来审视过程。
理工科之间的差距
完成一个数据科学项目需要很多技能。
一个人应该对算法的本质有数学理解和直觉,拥有创建和测试问题假设的统计知识,熟悉算法和最先进的解决方案等等。
要成为一名优秀的数据科学家,工程和编程技能不一定要达到专家级水平。不知道什么是 HTTP 动词,不知道如何管理工作人员和经纪人的任务队列,也不知道如何构建浏览器中的监控仪表板,完全有可能成为顶级的现场研究员。另一方面,生产系统需要相当高级的工程技能。
从我的工程角度来看,我已经注意到,一旦数据科学项目必须从研究阶段进入生产阶段,科学和工程之间的差距就会显现出来。
我见过数据科学家与框架斗争,花费不必要的时间学习超出他们必要技能范围的工具。
另一方面,我看到生产团队(来自数据科学家团队)交付的项目,他们不理解也不知道如何整合到他们组织的生产周期中。
由于这个问题是真实存在的,并且经常发生,我决定采取措施,用开源 Python 包来弥补这个差距。
见见丹泽尔
在我打开以德古拉为主题的编辑器开始编写框架之前,我已经坐下来定义了需求:
- 首先是数据科学家。对于数据科学家来说,框架应该有尽可能少的学习开销,并抽象出繁重的工作。
- 又瘦又快。框架内的开发应该是快速的,结果应该尽可能的精简。
- 生产就绪。使用生产级的工具和实践,它的输出应该能够很容易地交付给生产工程师使用。
三个要求,几十个*时的代码,几个月的测试和真正的生产使用,后来丹泽尔包诞生了,现在开源供公众使用。
Denzel 是部署机器学习训练模型的最*框架。
一旦你有了一个保存在磁盘上的训练好的模型,你需要做的就是实现四个简单的 Python 函数,丹泽尔会给你:
- 码头集装箱化项目
- 向最终用户公开 API 以与您的模型进行交互
- 任务管理系统排队并执行预测
- 在浏览器 UI 仪表板中监控您的部署
这里的一个重要方面是码头集装箱化的结果。这意味着任何知道如何在生产中管理 docker 容器的人都可以应用任何生产工具(如 Kubernetes、Rancher 等)。)以及在任何地方扩展和部署项目的无限可能性。此外,所有主要的云提供商都支持 docker 部署。所有这一切都不需要数据科学家自己学习 docker、API 构建、任务管理或 UI 设计。
该项目得到了我的雇主数据科学集团有限公司的全力支持,目前正在许多不同的部署中使用。
它为我们的数据科学家节省了大量不必要的时间,并为我们的客户提供了一种将我们的解决方案集成到他们的生产系统中的便捷方式。
Denzel 目前处于 alpha 阶段,这意味着功能仍将被添加到其中,开源是了解数据科学界真正需要它的最佳方式。
为了使用它,查看文档,尤其是教程,一个*时左右加上 60 行代码之后,你就可以部署你的模型了。
希望你喜欢这次阅读,丹泽尔将为你服务。
部署愉快:)
从 Scikit-学习到 TensorFlow:第 1 部分
原文:https://towardsdatascience.com/from-scikit-learn-to-tensorflow-part-1-9ee0b96d4c85?source=collection_archive---------1-----------------------
介绍
在过去的一年半时间里, TensorFlow 无论是在采用率还是在计算速度方面都以惊人的速度增长。
Image Source: Unreasonable Popularity of TensorFlow [http://deliprao.com/archives/168]
TensorFlow 已经成为最受欢迎的机器学习(ML)算法开发库。然而,它似乎也把自己建立成了一个库,需要对会话和图形进行定义,这是相当乏味和耗时的。虽然它在有效计算梯度以训练CNN、 RNNs 和lstm方面做得很好,但这还不是全部。
在这一系列帖子中,我想讨论如何将 TensorFlow 用作通用 ML 库。更具体地说,我们将讨论它如何类似于 scikit-learn ,另一个在数据科学家和开发人员中非常流行的 ML 库。
转向 TensorFlow 的理由
虽然 scikit-learn 拥有高度优化的算法,但在面对大量数据点时,它缺乏扩展能力。然而,TensorFlow 提供了许多优于 scikit-learn 的优势:
- 高性能 ML 模块
- 可定制性
- 纵向扩展以满足大数据点的需求
- 能够利用 GPU 并在地理上分散的 GPU 设备之间进行培训
- 设备无关计算
- 利用 Google Cloud 在训练好的 ML 模型上进行推理
- 高度灵活的 Apache 2.0 许可而 scikit-learn 是基于 BSD 许可(虽然两者都是商业可用的,但是 Apache 2.0 不太容易出现专利诉讼)
目标
- 了解 scikit-learn 和 TensorFlow 之间的相似功能,这些功能将允许 scikit-learn 用户无缝使用 TensorFlow。
- 使用 scikit-learn 和 TensorFlow 开发一个程序来对来自鸢尾花数据集的花卉品种进行分类,以了解构建这样一个系统所需的工作。
- 展示 TensorFlow 如何简单地实现新想法的原型。
功能级相似性
scikit-learn 受欢迎的原因之一是由于它的简单
classifier.fit() / classifier.predict()
对于所使用的任何分类器都保持不变的方法。这种简单的用户体验使开发人员能够专注于算法及其参数,而不是担心需要调用哪些 API 来完成手头的任务。
另一方面,我们在 TensorFlow 中有受 scikit-learn 启发的高级 API 。TensorFlow 中的这些函数的工作方式与 scikit-learn 非常相似,具有类似的 fit 和 predict 方法以及允许进一步微调的其他功能。
在我们深入研究使用 TensorFlow 的高级 API 调用开发我们的分类框架之前,让我们讨论一下 TensorFlow 的低级计算框架。TensorFlow 使用计算图来执行所有计算。计算被表示为tf.Graph
对象的实例,其中数据被表示为tf.Tensor
对象,并且使用tf.Operation
对象对这些张量对象进行操作。然后使用tf.Session
对象在会话中执行该图。很明显,使用 TensorFlow 的低级 API 创建一个分类框架需要测试一个简单的 ML 原型。这也是我们讨论 TensorFlow 的高级 API 与 scikit-learn 的 API 进行对比的原因之一。我们将在以后的文章中讨论低级 API 及其用法。
示例代码
我们使用 scikit-learn 的 SVM 模块和 TensorFlow 的高级 API 构建了一个分类器,根据花的特征对花进行分类。在这种情况下,数据集提供了 4 个不同的特征,如萼片宽度、萼片长度、花瓣宽度和花瓣长度,以将花分类为三个花卉品种之一(鸢尾、杂色鸢尾和海滨鸢尾)。)
这个项目的代码可以在我的 GitHub 页面上找到。
Image source: TensorFlow Quickstart [https://www.tensorflow.org/get_started/tflearn]
如果我们看看上面 GitHub 链接上的笔记本,我们可以看到数据加载和拆分功能是由两个框架共享的。我们在 scikit-learn 中定义了一个 SVM 分类器,如下所示:
*# ------------------------------------------*
*# Scikit Learn Implementation*
*# ------------------------------------------*
*# Use support vector classification*
classifier_sk = svm.SVC()*# Use the train data to train this classifier*
classifier_sk.fit(x_train, y_train)*# Use the trained model to predict on the test data*
predictions = classifier_sk.predict(x_test)
score = metrics.accuracy_score(y_test, predictions)
在上面的代码片段中,我们简单地定义了一个支持向量分类器 svm。SVC() ,其对象用于训练和预测。使用 fit() 实现训练,而使用 predict() 方法调用实现预测。我们最后计算这个四行代码片段最后一行的精度值。
另一方面,在 TensorFlow 中,我们可以使用深度神经网络(DNN)分类器来完成相同的任务。我们使用 TensorFlow 的 contrib 模块下的 DNNClassifier 如下:
*# ------------------------------------------*
*# TensorFlow Implementation*
*# ------------------------------------------**# Extract the features from the training data*
feats = tf.contrib.learn.infer_real_valued_columns_from_input(x_train)*# Building a 3-layer DNN with 50 units each.*
classifier_tf = tf.contrib.learn.DNNClassifier(feature_columns=feats,
hidden_units=[50, 50, 50],
n_classes=3)*# Use the train data to train this classifier*
classifier_tf.fit(x_train, y_train, steps=5000)*# Use the trained model to predict on the test data*
predictions = list(classifier_tf.predict(x_test, as_iterable=True))
score = metrics.accuracy_score(y_test, predictions)
在上面的代码片段中,我们可以看到如何为几乎相同数量的行(构建 DNN,除了用于将输入数据转换为要素的附加行。)这一额外的行完成了将输入数据转换成密集的、固定长度的浮点值的任务。
向张量流迁移的路径
虽然从一个框架转移到另一个框架的任务通常令人畏惧,有时令人沮丧,但 TensorFlow 似乎有一座桥梁,允许开发人员从一个不同的框架平稳过渡。 contrib.learn 模块提供了这样一个桥梁,允许从 scikit-learn 或 Keras 到 TensorFlow 的熟悉路径。
TensorFlow 还具有足够的适应性,可以包含针对生产质量使用进行了高度优化的阅读器,同时支持 ML 社区使用的大多数文件格式。这使得开发人员可以避免依赖其他框架,如*猫(它完成了读取文件的繁重工作,但仍然需要手动将数据输入 ML 框架。)在今年早些时候举行的 TensorFlow 开发峰会上,TensorFlow 阅读器也表现出了高性能。
摘要
在这篇文章中,我们开始探索使用 scikit-learn 和 TensorFlow 开发一个分类器来完成一个简单的任务。我们讨论了高级 TensorFlow API 如何类似于 scikit-learn 的 API。你可以在我的 GitHub 页面访问这篇博客中讨论的代码。
在下一篇文章中,我打算介绍更多的 scikit 模块及其 TensorFlow 对应模块。你有什么特别的想法吗?给我发推特 @krtk 或者在 LinkedIn 上联系我。
从 Scikit-学习到 TensorFlow:第 2 部分
原文:https://towardsdatascience.com/from-scikit-learn-to-tensorflow-part-2-66c56985d6c7?source=collection_archive---------1-----------------------
从我们离开的地方继续,我们从 scikit-learn 开发人员的角度更深入地研究如何使用 TensorFlow 开发机器学习(ML)算法。如果您想知道迁移到 TensorFlow 的原因、动机,请阅读我之前的帖子,了解迁移到 TensorFlow 的原因和一个简单的分类程序,该程序强调了 scikit-learn 和 TensorFlow 开发的相似性。
在之前的文章中,我们比较了 scikit-learn 和 TensorFlow 中 fit 和 predict 范式的相似性。在这篇文章中,我想展示我们可以用 Scikit-learn 的数据处理和报告工具开发一个 TensorFlow 分类框架。这将提供一个很好的方法来交织这两个框架,从而得到一个简洁明了的框架。
利用机器学习
机器学习(ML)问题无处不在。然而,这里的问题是,一旦你开始用 ML 解决问题,每一个新问题看起来都像是 ML 问题,就像那句老话所说的:
如果你只有一把锤子,所有的东西看起来都像钉子
一个理解 ML 的人和一个使用 ML 的人有一个重要的区别,那就是,当不是使用 ML 来解决问题的时候。如果您可以通过简单的规则轻松地找到解决方案,那么您可能不需要使用 ML。例如,你不需要一个 ML 算法来预测所有的自行车和汽车是交通方式或者用正确的拼写替换常见的拼写错误的单词。
如果规则变得难以处理,并且如果有太多的参数来确定这样的规则,我们将需要 ML。例如,我们将要求 ML 预测明天的天气,因为它取决于许多因素,如季节、地点、其他因素,如厄尔*诺,这使得编写规则很困难,而且往往不准确。我们可能需要 ML 的另一个例子是当数据变得人类不可能仔细阅读并找到模式时,这是 ML 似乎做得很好的一个领域。以电子邮件垃圾邮件或火腿为例,我们根据电子邮件中的文本(正文+主题)将电子邮件分类为垃圾邮件。如果垃圾邮件的模式是有限的,这个任务就很容易。然而,发送此类电子邮件的“王子”往往会找到新的方法让我们都变得“富有”,这使得我们有必要开发 ML 框架来帮助我们对抗垃圾邮件。
说了这么多,让我们来看看一个本来就很难发现规则的问题,以及一个获得高精度和召回率的棘手问题。
问题是
我们将使用威斯康星州乳腺癌诊断数据检测癌症的存在。这个数据集是一个二元分类问题(恶性或良性),有 569 个实例(数据点),允许我们执行分类任务。
这篇文章中描述的所有代码都可以在我的 GitHub repo 这里获得。
数据处理-sci kit-learn
我们利用 Scikit-learn 的高效数据加载工具来获取我们的数据。乳腺癌数据集可在这里获得。Scikit-learn 允许我们加载的其他数据集的列表可以在这里找到。让我们加载数据集并查看数据的一些属性。
from sklearn.datasets import load_breast_cancer
cancer_data = load_breast_cancer()print("Number of instances in the dataset: %d" % len(cancer_data.target))>> Number of instances in the dataset: 569
让我们讨论一下在训练数据之前,按原样使用数据与扩展功能的影响。缩放数据可以使特征标准化。这意味着数据以零为中心,并调整到标准偏差为 1。换句话说,我们将数据限制在[0,1]之间,而不改变数据的原始分布。这确保了分类器不会在大*度空间中搜索最优权重,而是将搜索空间限制在[0,1]之间。这种缩放对分类器的性能有很大的影响,这可以在下面的实验部分看到。我们尝试了两个实验,一个有特征缩放,另一个没有特征缩放。
实验一:按原样使用数据[D1]
我们按原样使用来自 SKLearn 的数据,使用内置的训练、测试分离器简单地加载变量
from sklearn.model_selection import train_test_split
in_train, in_test, out_train, out_test = train_test_split(cancer_data[‘data’],
cancer_data[‘target’])
实验二:缩放数据[D2]
对于第二个实验,我们使用 SKLearn 中可用的预处理功能来缩放数据。
from sklearn.preprocessing import StandardScaler
data_scaler = StandardScaler()# Fit train data
data_scaler.fit(in_train)in_train = data_scaler.transform(in_train)
in_test = data_scaler.transform(in_test)
网络-张量流
我们设计了一个类似于我的早期文章的神经网络,以保持网络的简单方法,而不是理解数据预处理和过度拟合的影响。我们使用 TensorFlow 的 DNNClassifier ,它在 TensorFlow 的 contrib 模块中可用。我们定义一个有三层的网络,每层有 <个单元> 个隐藏单元。在我们的实验中,我们首先通过改变输入的预处理方式来评估以下网络的性能,其中单位=50 。然后选择性能最佳的输入进行进一步实验,以了解过拟合,其中我们保持数据不变(在 D1 和 D2 中最好)并改变单位。网络结构描述如下:
feature_columns = tf.contrib.learn.infer_real_valued_columns_from_input(in_train)
classifier_tf = tf.contrib.learn.DNNClassifier(feature_columns=feature_columns,
hidden_units=[units, units, units],
n_classes=2)
classifier_tf.fit(in_train, out_train, steps=1000)
上面的网络所做的是定义一个全连接网络,也称为多层感知器,其输入来自我们刚刚加载的数据。多层感知器可以描述如下:
Multi-layer Perceptron [source: deeplearning.net]
在我们的例子中,输入是从癌症数据集加载的数据,而输出是一个二进制值,表示输入是恶性的还是良性的。
实验三:隐藏单元的数量[H1]
这两个实验的目的是了解隐藏单元的数量对每层的影响,这也将提供对过度拟合的洞察。
在这个实验中,我们首先选择 D1 或 D2(如上所述),然后改变网络每层的隐藏单元数量。这个实验的隐藏单元的数量保持在 H1=10。
实验四:隐藏单元的数量[H2]
我们用比 H1 更多的隐藏单元进行了第四次实验。这将能够适应数据中的更多变化,但是可能最终会记住数据,因此无法在测试数据上很好地执行。我们运行类似于上面 H1 的实验,然后运行 H2=50 的网络。
报告-sci kit-学习
我们使用 Scikit-learn 的报告功能来了解我们的分类器是如何执行的。我们使用分类报告和混淆矩阵来理解我们的分类器的表现。
分类报告生成一个矩阵,其中包含使用预测输出和实际输出值计算的关键指标。报告的指标是每个类别的精确度、召回率和 f1 分数,以及所有类别的平均值。
report = metrics.classification_report(out_test, predictions,
target_names=cancer_data.target_names)
print(report)
虽然分类报告提供了关键指标,但是混淆矩阵提供了每个测试数据点所属的类别。混淆矩阵显示了分类器在对一个类别进行预测时有多强,同时显示了分类器在对其他类别下的数据进行分类时的弱点。
# Plotting the confusion matrix using matplotlib
%matplotlib inline
confusion = metrics.confusion_matrix(out_test, predictions)# Plot non-normalized confusion matrix
plt.figure()
plot_confusion_matrix(confusion, classes=cancer_data.target_names,
title=’Confusion matrix, without normalization’)
分类报告描述了整体性能,而混淆矩阵提供了分类到每个类别下的数据点的准确数量。
结果
我们首先进行实验,以了解数据标准化是否有助于更好的分类。因此,我们选择 H1,在 D1 和 D2 进行实验。结果如下:
与 H1+D1 的表演
precision recall f1-score support
malignant 0.94 0.88 0.91 51
benign 0.94 0.97 0.95 92
avg / total 0.94 0.94 0.94 143Prediction Accuracy: 0.937063
H1+D2 的表现
precision recall f1-score support
malignant 0.96 0.93 0.95 46
benign 0.97 0.98 0.97 97
avg / total 0.96 0.97 0.96 143Prediction Accuracy: 0.965035
从我们的实验中可以明显看出,数据缩放在分类准确性方面提供了 ~3% 的改进。这让我们选择 D2(数据与缩放)为我们的实验与 H2。
H2+D2 的表现
precision recall f1-score support
malignant 0.96 0.92 0.94 53
benign 0.96 0.98 0.97 90
avg / total 0.96 0.96 0.96 143Prediction Accuracy: 0.958042
技术性能分析
H1+D2 和 H2+D2 的性能指标没有提供多少关于分类器在数据点数量方面在其他类别中表现如何的洞察力。这就是混淆矩阵为进一步分析提供更好的图像的地方。
Confusion matrix for H2 + D2
Confusion matrix for H1 + D2
上述矩阵更清楚地显示了 H1 和 H2 分类器的性能差异。尽管 H2 的隐藏单元数量是 H1 的五倍,但它在测试数据上的表现却不如 H1。混淆矩阵提供了每个类别下被错误分类的点数的准确分布。
结论
在这篇文章中,我们看到了如何使用 Scikit-learn 和 TensorFlow 来执行不同的分类实验,并查看每个分类器的性能。我们还对数据预处理和网络参数进行了简单的实验,以理解不同的概念。
这篇文章中描述的所有代码都可以在我的 GitHub repo 这里找到。
让我知道你希望我在下一篇文章中讨论什么话题,请在下面评论。我在推特上,如果你想在那里和我联系的话!
从无到有:50 行 Python 中的人工智能平衡术
原文:https://towardsdatascience.com/from-scratch-ai-balancing-act-in-50-lines-of-python-7ea67ef717?source=collection_archive---------3-----------------------
Ours will do a little bit better than this in the end 😃
大家好!今天我想展示如何用 50 行 Python 语言教会一台机器平衡一根杆子!我们将使用标准的 OpenAI Gym 作为我们的测试环境,并且只用 numpy 创建我们的代理。
手推车杆子问题是我们必须左右推动手推车来平衡上面的杆子。这类似于在我们的指尖垂直平衡一支铅笔,除了一*(相当有挑战性!)
在我们开始之前,你可以在 repl.it 查看的最终演示。
RL 速成班
如果这是你第一次学习机器学习或强化学习,我会在这里介绍一些基础知识,这样你就会对我们在这里使用的术语有所了解:)。如果这不是你的第一次,你可以继续往下跳,制定我们的政策!
强化学习
强化学习(RL)是一个研究领域,致力于教导代理(我们的算法/机器)执行某些任务/动作,而不明确告诉它如何做。把它想象成一个婴儿,随意地移动它的腿;幸运的是,如果婴儿站直了,我们会给它一颗糖/奖励。同样,代理人的目标将是在其一生中最大化总报酬,我们将决定与我们想要完成的任务相一致的报酬。对于站立的例子,当直立时奖励 1,否则奖励 0。
一个 RL 代理的例子是 AlphaGo,代理已经学会了如何玩围棋来最大化它的奖励(赢得比赛)。在本教程中,我们将创建一个代理,它可以通过向左或向右推手推车来解决平衡手推车上的杆子的问题。
状态
What a game of pong looks like, in case you need a refresher
一个状态就是游戏目前的样子。我们通常处理游戏的数字表示。在乒乓游戏中,可能是每个球拍的垂直位置和 x,y 坐标+球的速度。在*车杆的情况下,我们的状态由 4 个数字组成:*车的位置,*车的速度,杆的位置(作为一个角度)和杆的角速度。这 4 个数字作为一个数组(或向量)提供给我们。这很重要;理解状态是一组数字意味着我们可以对它做一些数学运算,以决定我们想要根据状态采取什么行动。
政策
策略是一个函数,它可以获取游戏的状态(例如棋盘棋子的位置,或者手推车和杆子的位置)并输出代理在该位置应该采取的动作(例如移动骑士,或者把车推到左边)。在代理采取我们选择的行动后,游戏将更新下一个状态,我们将再次将它输入策略以做出决定。这种情况一直持续到游戏以某种方式结束。政策非常重要,也是我们所寻求的,因为它是代理背后的决策能力。
点积
两个数组(向量)之间的点积就是将第一个数组的每个元素乘以第二个数组的相应元素,然后将所有元素相加。假设我们想要找到数组 A 和 B 的点积,它将简单地是 A[0]B[0] + A[1]B[1]…我们将使用此操作将状态(这是一个数组)乘以另一个数组(这将是我们的策略)。我们将在下一节中看到这一点。
发展我们的政策
为了解决我们的车杆游戏,我们希望让我们的机器学习一种策略或政策来赢得游戏或最大化我们的奖励。
对于我们今天要开发的代理,我们将把我们的策略表示为一个由 4 个数字组成的数组,这些数字表示状态的每个组成部分有多“重要”(手推车位置、杆子位置等)。)然后我们将策略数组与状态进行点积,以输出一个数字。根据数字是正数还是负数,我们将向左或向右推手推车。
如果这听起来有点抽象,让我们挑选一个具体的例子,看看会发生什么。
假设手推车在游戏中处于中心位置,并且静止不动,杆子向右倾斜,并且也向右倾斜。它看起来会像这样:
关联的状态可能如下所示:
那么状态数组将是[0,0,0.2,0.05]。
现在,凭直觉,我们会想通过向右推手推车,把杆子拉直。我从一次训练中获得了一个好的策略,它的策略数组是:[-0.116,0.332,0.207 0.352]。让我们手动快速计算一下,看看这个策略作为这个州的一个动作会输出什么。
这里我们将点积状态数组[0,0,0.2,0.05]和策略数组(粘贴在上面)。如果数字是正数,我们向右推,如果数字是负数,我们向左推。
结果是肯定的,这意味着在这种情况下,政策也会把车推到右边,这正是我们想要的结果。
现在这一切都很好,很明显,我们需要的是 4 个像上面这样的神奇数字来帮助解决这个问题。现在,我们如何得到这些数字?如果我们只是随机挑选呢?效果如何?让我们找出答案,并开始挖掘代码!
启动你的编辑器!
让我们在 repl.it 上打开一个 Python 实例。它允许您快速调用大量不同编程环境的云实例,并在一个强大的云 IDE 中编辑代码,该 IDE 在任何地方都可以访问!
安装软件包
我们将从安装这个项目所需的两个包开始:numpy 帮助进行数值计算,OpenAI Gym 作为我们代理的模拟器。
只需在编辑器左侧的包搜索工具中键入gym
和numpy
,然后单击加号按钮安装包。
奠定基础
让我们首先将刚刚安装的两个依赖项导入到我们的main.py
脚本中,并设置一个新的健身房环境:
接下来,我们将定义一个名为“play”的函数,它将被给予一个环境和一个策略数组,并将在该环境中播放该策略数组并返回分数,以及在每个时间步长的游戏快照(观察)。我们将使用分数来告诉我们该策略的执行情况,并使用快照来观察该策略在单个游戏中的表现。这样我们可以测试不同的政策,看看他们在游戏中表现如何!
让我们从函数定义开始,并将游戏重置为开始状态。
接下来,我们将初始化一些变量来跟踪游戏是否已经结束,策略的总得分,以及游戏过程中每一步的快照(观察)。
现在我们将简单地玩游戏很多时间步骤,直到健身房告诉我们游戏结束。
上面的大部分代码主要只是在玩游戏和记录结果。我们政策的实际代码只有这两行:
我们在这里做的只是策略数组和状态(观察)数组之间的点积运算,就像我们在前面的具体例子中展示的那样。然后我们根据结果是积极的还是消极的来选择 1 或 0(左或右)的行动。
到目前为止我们的main.py
应该是这样的:
现在我们要开始玩一些游戏,找到我们的最优策略!
玩第一个游戏
现在我们有一个函数来玩这个游戏,并告诉我们的策略有多好,我们将希望开始生成一些策略,并看看它们做得有多好。
如果我们一开始只是尝试插入一些随机策略会怎么样?我们能走多远?让我们使用numpy
来生成我们的策略,这是一个 4 元素数组或 1x4 矩阵。它将在 0 和 1 之间选择 4 个数字作为我们的策略。
有了这个策略,以及我们在上面创建的环境,我们可以让他们参与进来并获得分数。
只需点击 run 来运行我们的脚本。它应该输出我们的策略得到的分数。
这个游戏的最高分数是 500,很有可能你的政策并不顺利。如果你的有,恭喜你!今天一定是你的幸运日!虽然仅仅看到一个数字并不是很有价值,但是如果我们能想象我们的代理如何玩游戏,那就太好了,下一步我们将设置它!
监视我们的特工
为了观察我们的代理,我们将使用 Flask 来设置一个轻量级服务器,这样我们就可以在浏览器中看到代理的表现。Flask 是一个轻量级的 Python HTTP 服务器框架,可以服务于我们的 HTML UI 和数据。我将保持这一部分的简短,因为渲染和 HTTP 服务器背后的细节对于培训我们的代理并不重要。
我们首先要将Flask
安装成一个 Python 包,就像我们在前面几节中安装gym
和numpy
一样。
接下来,在脚本的底部,我们将创建一个 flask 服务器。它将在/data
端点上公开游戏的每一帧记录,并在/
上托管 UI。
此外,我们需要添加两个文件。一个是项目的空白 Python 文件。这是 repl.it 如何检测 repl 是处于评估模式还是项目模式的技术问题。只需使用“新建文件”按钮添加一个空白 Python 脚本。
之后,我们还想创建一个index.html
来托管渲染 UI。这里就不深究细节了,只是简单的把这个index.html上传到你的 repl.it 项目。
您现在应该有一个如下所示的项目目录:
现在有了这两个新文件,当我们运行 repl 时,它应该也能回放我们的策略是如何执行的。有了这些,让我们试着找到一个最优策略!
策略搜索
在第一遍中,我们简单地随机选择了一个策略,但是如果我们选择了几个策略,并且只保留了做得最好的一个,那会怎么样呢?
让我们回到播放策略的那一部分,我们不只是生成一个策略,而是编写一个循环来生成几个策略,并跟踪每个策略的表现,只保存最佳策略。
我们将首先创建一个名为max
的元组,它将存储目前为止我们看到的最佳策略的分数、观察值和策略数组。
接下来,我们将生成并评估 10 个策略,并将最佳策略保存在 max 中。
我们还必须告诉我们的/data
端点返回最佳策略的回放。
此端点:
应改为:
你的 main.py 看起来应该类似于 this now :
如果我们现在运行 repl,我们应该得到 500 的最高分,如果不是,尝试再运行一次 repl!我们也可以看到政策平衡的极点完美无缺!哇,太简单了!
没那么快
也可能不是。在第一部分中,我们在几个方面做了些手脚。首先,我们只在 0 到 1 的范围内随机创建策略数组。这只是发生了工作,但是如果我们把大于操作符反过来,我们会看到代理将会灾难性地失败。要亲自尝试,请将action = 1 if outcome > 0 else 0
更改为action = 1 if outcome < 0 else 0
。
这似乎不太可靠,因为如果我们只是碰巧选择了*于而不是大于,我们就永远找不到可以解决这个游戏的策略。为了缓解这种情况,我们实际上也应该生成带有负数的策略。这将使找到一个好的政策变得更加困难(因为许多负面的政策都不是好的),但是我们不再通过将我们的特定算法适用于这个特定的游戏来“作弊”。如果我们试图在 OpenAI 健身房的其他环境中这样做,我们的算法肯定会失败。
为了做到这一点,而不是有policy = np.random.rand(1,4)
,我们将改变为policy = np.random.rand(1,4) - 0.5
。这样,我们策略中的每个数字将介于-0.5 和 0.5 之间,而不是 0 到 1。但是因为这更困难,我们还想搜索更多的策略。在上面的 for 循环中,我们不遍历 10 个策略,而是通过将代码改为for _ in range(100):
来尝试 100 个策略。我也鼓励你先尝试遍历 10 个策略,看看现在用负数得到好的策略有多难。
现在我们的 main.py 应该看起来像这样:
如果你现在运行 repl,不管我们使用的是大于还是*于,我们仍然可以为游戏找到一个好的策略。
没那么快 Pt。2
但是等等,还有呢!即使我们的政策可能能够在一次运行中达到最高 500 分,它能每次都做到吗?当我们生成了 100 个策略,并选择在单次运行中表现最好的策略时,该策略可能只是非常幸运,也可能是非常糟糕的策略,只是碰巧表现非常好。这是因为游戏本身具有随机性(每次的起始位置都不同),所以一项政策可能只在一个起始位置有效,而在其他位置无效。
因此,为了解决这个问题,我们需要评估一项政策在多次试验中的表现。现在,让我们采用之前发现的最佳策略,看看它在 100 次试验中表现如何。
在这里,我们玩 100 次最佳策略(max
的索引 2),并记录每次的分数。然后,我们使用numpy
计算平均分数,并将其打印到我们的终端。“已解决”没有明确的定义,但应该只比 500 差几分。你可能会注意到,有时候最好的政策实际上可能是不合格的。但是,我将把修复工作留给您来决定!
完成=真
祝贺你!🎉我们已经成功地创造了一个人工智能,可以非常有效地解决 cart pole,而且相当高效。现在有很大的改进空间,这将是后续系列文章的一部分。有些事情我们可以深入调查:
- 找到一个“真正的”最优策略(将在 100 个单独的行动中表现良好)
- 优化我们必须搜索以找到最佳策略的次数(“样本效率”)
- 对保单进行适当的搜索,而不是随意挑选。
- 解决其他环境。
如果您有兴趣在您的下一个项目中使用预训练模型和开箱即用的工作代码来尝试更多的 ML,请查看 ModelDepot !
从零开始:贝叶斯推理,马尔可夫链蒙特卡罗和大都会黑斯廷斯,用 python 编写
原文:https://towardsdatascience.com/from-scratch-bayesian-inference-markov-chain-monte-carlo-and-metropolis-hastings-in-python-ef21a29e25a?source=collection_archive---------0-----------------------
Credit: Adi coco unsplash
你好,欢迎阅读“从零开始”系列的第一篇文章,在这里我解释并实现/构建任何从零开始的东西。
我为什么要这么做?因为在目前的情况下,我们拥有如此强大的库和工具,可以为我们做很多工作。大多数有经验的作者都很清楚实现这些工具的复杂性。因此,他们利用它们为来自不同背景的用户提供简短、易懂和切题的阅读。在我阅读的许多文章中,我无法理解这个或那个算法在实践中是如何实现的。它们的局限性是什么?为什么要发明它们?什么时候应该使用它们?
正如希拉里·梅森所说:
“当你想使用一种你并不深刻理解的新算法时,最好的方法是自己实现它,以了解它是如何工作的,然后使用一个库来受益于健壮的代码。”
这就是为什么,我提议从零开始解释和实现:贝叶斯推理(有点简略),马尔可夫链蒙特卡罗和 Metropolis Hastings,用 Python。
笔记本和 pdf 版本可以在我的知识库中找到: joseph94m
先决条件:基本概率、微积分、Python。
1-简介
在我的许多阅读中,我遇到了一种叫做马尔可夫链蒙特卡罗的技术,或者更通常的说法,MCMC。对这种方法的描述大致如下:MCMC 是一类从概率分布中取样的技术,可用于估计给定一组观察值的参数分布。
当时,我并没有多想。我想,“哦,这只是另一种采样技术”,我决定在我实际需要的时候读读它。这种需要从未出现过,或者它出现了,而我错误地使用了其他东西来解决我的问题。
1.1-那么为什么现在有兴趣呢?
最近,我看到了一些关于 MCMC 及其一些实现的讨论,特别是 Metropolis-Hastings 算法和 PyMC3 库。Markov Chain Monte Carlo in Python 一个完整的现实世界实现,是最吸引我注意的文章。在这篇文章中,William Koehrsen 解释了他是如何通过将该方法应用于现实世界的问题来学习该方法的:估计代表其睡眠模式的逻辑函数的参数。
The assumed model
Koehrsen 先生使用 Metropolis-Hastings 算法的 PyMC3 实现来计算α和β的分布空间,从而推导出最可能的逻辑模型。
1.2-那我为什么要说这些呢?
在本文中,我打算从头实现 Metropolis-Hastings 算法,为一个虚拟数据示例和一个真实世界的问题寻找参数分布。
我想如果我把手弄脏了,我也许最终能理解它。我只会用 numpy 来实现算法,用 matplotlib 来画漂亮的东西。或者,scipy 可以用来计算密度函数(我将在后面讨论),但我也将展示如何使用 numpy 实现它们。
1.3-文章的流程
在第 1 部分,我将介绍贝叶斯推理,MCMC-MH 及其数学组成部分。在第 2 部分中,我将解释使用虚拟数据的 MH 算法。最后,第 3 部分将提供 MCMC-MH 的一个实际应用。
第 1 部分:贝叶斯推理,马尔可夫链蒙特卡罗,和大都会黑斯廷斯
2.1-概率哲学的鸟瞰图
为了讨论贝叶斯推理和 MCMC,我将首先解释什么是概率的贝叶斯观点,并把它放在它的历史背景中。
2.1.1-频率主义者 vs 贝叶斯思*
概率有两种主要的解释:贝叶斯和频率主义者。
从频率主义者的角度来看,概率代表事件发生的长期频率。一个频繁投资者可以说,从长远来看,掷硬币得到反面的概率等于 0.5。每一个新的实验,都可以被认为是同一实验的无限可能重复序列中的一个。主要观点是,不相信一个频繁主义者的概率观点。事件 x 在 n 次试验中发生的概率大致如下:
并且当 n — > ∞时达到真概率。常客永远不会说“我 45%(0.45%)确定今天午餐有千层面”,因为从长远来看这不会发生。通常,频率主义方法被称为目标方法,因为其中没有信念和/或先前事件的表达。
另一方面,在贝叶斯思*中,概率被视为信念的表达。因此,贝叶斯理论完全有理由说“我 50%(0.5%)确定今天午餐有千层面”。通过结合先验信念和当前事件证据,人们可以计算出后验,即今天有千层面的概率。贝叶斯思*背后的想法是,随着更多证据的提供,不断更新信念。因为这种方法处理的是信念,所以它通常被称为关于概率的主观观点。
2.1.2-贝叶斯推理
在决策哲学中,贝叶斯推理与贝叶斯概率观密切相关,它操纵先验、证据和可能性来计算后验。给定某个事件 B,事件 A 发生的概率是多少?这可以用贝叶斯的著名公式来回答:
使用:
在我们的例子中,我们最感兴趣的是贝叶斯公式的具体表述:
也就是说,我们希望找到θ的最可能分布,即解释数据的模型参数 d。
A supposed portrait of Thomas Bayes, an English statistician, philosopher, and theologian. Image Credit: Wikipedia Commons
计算这些概率中的一些可能是乏味的,尤其是证据 P(D)。此外,还会出现其他问题,比如确保共轭的问题,我不会在本文中深入探讨。幸运的是,一些技术,即 MCMC,允许我们从后验样本中进行采样,并绘制参数分布,而不必担心计算证据,也不必担心共轭性。
2.1.3-马尔可夫链蒙特卡罗
MCMC 允许我们从分布中抽取样本,即使我们不能计算它。它可用于从参数的后验分布(我们希望知道的)中取样。它已经在许多应用中取得了成功,例如在给定一组观测值和一些先验信念的情况下计算参数的分布,以及在物理和数字通信中计算高*积分。
底线:它可以用来计算给定一组观察值和先验信念的参数分布。
2.1.4-大都会-黑斯廷斯
MCMC 是一类方法。Metropolis-Hastings 是 MCMC 的具体实现。与吉布斯采样和拒绝采样相反,它在高*空间中工作得很好。
这项技术需要一个简单的分布,称为建议分布(我喜欢称之为转移模型)Q(θ′/θ),以帮助从一个棘手的后验分布 P(θ=θ/D)中抽取样本。
Metropolis-Hastings 使用 Q 在分布空间中随机行走,根据样本的可能性接受或拒绝跳转到新位置。这种“无记忆”随机游走是 MCMC 的“马尔可夫链”部分。
每个新样本的“可能性”由函数 f 决定。这就是为什么 f 必须与我们要采样的后验概率成正比。 f 通常被选择为表达该比例的概率密度函数。
要获得参数的新位置,只需取我们当前的θ,并提出一个新的θ’,这是从 Q(θ’/θ)中抽取的随机样本。通常这是一种对称分布。例如,具有平均值θ和一些标准偏差σ的正态分布:Q(θ′/θ)= N(θ,σ)
为了决定是否接受或拒绝θ’,必须为每个新提出的θ’计算以下比率:
使用贝叶斯公式,这可以很容易地重新制定为:
The evidence P(D) is simply crossed out during the division
这也相当于:
Where f is the proportional function mentioned previously.
接受的规则可以表述为:
Note: The prior components are often crossed if there is no preference or restrictions on the parameters.
这意味着如果一个θ'比当前的θ更有可能,那么我们总是接受θ'。如果它比当前的θ更不可能,那么我们可能接受它或以递减的概率随机拒绝它,可能性越*。
简而言之,Metropolis-Hastings 算法执行以下操作:
Metropolis-Hastings algorithm
第 2 部分:虚拟数据示例
3.1-步骤 1:数据生成
我们从均值μ= 10、标准差σ= 3 的正态分布中生成 30,000 个样本,但我们只能从中观察到 1000 个随机样本。
3.2-第二步:我们想要什么?
我们希望使用 1000 个观察样本找到σ{观察值}的分布。你们当中那些狂热的数学家会说,有一个计算σ的公式:
为什么我们要取样什么的?这只是一个虚拟数据的例子,真正的问题在第 3 部分,这里很难直接计算参数。另外,在这里,我们不是试图找到σ的值,而是试图计算σ的概率分布。
3.3-步骤 3:定义 PDF 和过渡模型
从图 1 中,我们可以看到数据是正态分布的。通过取 1000 个样本值的平均值,可以很容易地计算出平均值。通过这样做,我们得到μ{observed} = 9.8(尽管附带说明,我们也可以假设μ未知,并对其进行采样,就像我们对σ进行采样一样。然而,我想让这个开始的例子简单一些。)
3.3.1-对于过渡模型/方案分配
我心中没有具体的分布,所以我会选择一个简单的:正态分布!
注意σ′与σ{new}和σ{current}无关。它只是指定了参数空间的标准偏差。它可以是任何需要的值。影响算法的收敛时间和样本之间的相关性,我后面会讲到。
3.3.2-用于 PDF
由于 f 应该与后验、成正比,我们选择 f 为下面的概率密度函数(PDF),对于数据集 D 中的每个数据点 di:
Since μ is constant, we can practically consider that σ is equivalent to θ
3.4-步骤 4:定义我们何时接受或拒绝σ
3.4.1-验收公式
如果这个比值不大于 1,那么我们将其与闭集[0,1]中的一个均匀生成的随机数进行比较。如果比值大于随机数,我们接受σ{new},否则拒绝。这确保了即使一个样本比当前的可能性*,我们可能仍然想要尝试它。(类似于模拟退火的概念)
3.4.2-可能性
一组观察值 D 的总可能性是:
This must be computed for both new and current sigma in order to compute the ratio in equation (1)
3.4.3-先验 P( μ,σ)
对于σ{new}和σ{current}可以采用的值,我们没有任何偏好。唯一值得注意的是,它们应该是积极的。为什么?直观地说,标准差衡量的是离差。离差是一个距离,距离不能是负数。
数学上:
而且一个数的平方根不能是负的,所以σ总是正的。我们在事前严格执行这一点。
3.4.4-最终验收表
在我们的例子中,我们将记录先验和似然函数。为什么要日志?仅仅是因为它有助于数值的稳定性,即乘以数千个*值(概率、可能性等..)会导致系统内存下溢,log 是一个完美的解决方案,因为它将乘法转换为加法,并将*正数转换为非*负数。
我们从等式(1)得到的接受条件变为:
这种形式可以通过从对数中取出平方根和乘法来进一步简化,但是不要介意,现在已经有足够的数学了!
3.4.5-那次咆哮的实施
实现很简单,对吧?!
3.6-步骤 6:使用初始参数运行算法,并收集接受和拒绝的样本
该算法接受 8317 个样本(每次新运行时可能会有所不同)。最后 10 个样本包含以下σ值:
[2.87920187, 3.10388928, 2.94469786, 3.04094103, 2.95522153, 3.09328088, 3.07361275, 3.08588388, 3.12881964, 3.03651136]
让我们看看算法是如何得出这些值的:
因此,从 0.1 的初始σ开始,算法很快收敛到预期值 3。也就是说,这只是 1D 空间中的采样…所以这并不奇怪。
尽管如此,我们仍将σ值的最初 25%视为“老化”,因此我们放弃它们。
3.6.2-让我们可视化 σ 的轨迹和轨迹的直方图
σ最可能的值约为 3.1。这比原始值 3.0 多了一点点。这种差异是由于我们只观察到原始人群的 3.33%(30,000 人中的 1,000 人)
3.6.3-预测:我们的模型在预测最初的 30,000 人口时表现如何?
首先,我们对σ的最后 75%的接受样本进行平均,我们从正态分布中生成 30,000 个随机个体,μ=9.8,σ=3.05(最后 75%的接受样本的平均值),这实际上比最可能的值 3.1 更好。
瞧:
现在,进入正题!
4-第 3 部分:真实世界的例子
Sunspots. Credit Wikipedia commons
太阳黑子是太阳表面(光球)的一个区域,其特征是温度低于其周围环境。这些降低的温度是由磁场通量的集中引起的,它通过类似于涡流制动器的效应抑制对流。太阳黑子通常成对出现,磁极相反。它们的数量根据大约 11 年的太阳周期而变化。
我们将研究的数据是“月平均太阳黑子总数”,从 1749 年 1 月到 2018 年 11 月的每个月。这些数据由世界数据中心收集、整理并公开发布,用于制作、保存和传播国际太阳黑子数。
4.1-让我们绘制这些年的数据,看看分布情况可能是什么样的
4.2-似乎我们可以用伽马分布来模拟这种现象,每 12 年有一个新的周期重置
γ分布γ是一族双参数的连续概率分布。参数是形状 A 和尺度 b。一个伽马分布的随机变量 X 记为 X ~γ(A,b),在我们的例子中,X 是太阳黑子的数量。两个参数 a 和 b 是我们想要计算其分布的未知数。
Gamma function with different parameters. Credit: Wikipedia Commons
例如,在第一个周期中,太阳黑子数从 1749 年底的 300 个左右的最高值开始,并在 6 年后的 1755 年下降到最低值。然后这个数字在 1761 年和 1762 年再次上升到最大值,然后在 1766 年再次下降,以此类推。。。
让我们通过绘制太阳黑子数直方图来确定:
4.3-事实上,计数频率似乎确实遵循伽马分布
对于 PDF,f,γ分布为:
其中γ是γ函数:γ(a)=(a-1)!(不要与伽马分布混淆!)
按照与虚拟数据示例中相同的过程,我们可以从这个 pdf 中写下对数似然性(参见下面的代码)。或者,可以使用 scipy.stats.gamma,b)。pdf(x)函数来计算它。但是,请注意,scipy 的实现比我实现的要慢几个数量级。
因为 a 和 b 必须是严格正的,所以我们在前面的例子中强制这样做:
运行代码并收集样本:
从 a=4 和 b =10 开始,该算法接受了 8561 对样本,a 的最后一个值是 0.98848982,b 的最后一个值是 84.99360422,这与初始值相差甚远。
与虚拟数据示例一样,让我们看看算法是如何得出这些值的:
从图 10、11 和 12 可以看出,该算法很快收敛到[a=1,b=85]区域。
提示:当算法开始大量拒绝样本时,这意味着我们已经达到了可能性的饱和区。通常,这可以被解释为已经达到了我们可以从中采样的最佳参数空间,即,算法几乎没有理由接受新值。这在图 11 和 12 中有所标记,其中算法不再接受*范围之外的任何值。
4.3.1-我们认为 a 和 b 值的最初 50%是“老化”,所以我们放弃它们。让我们来看一下 b 和 b 的轨迹以及轨迹的直方图。
4.4-预测时间
首先,我们对 a 和 b 的最后 50%的接受样本进行平均,并从γ分布中生成随机个体。a{average}=0.9866200759935773,b { average } = 83.70749712447888。
预测是:
4-评估
4.1-建议书分发的评估
我们如何指定分布 Q 的参数?我们应该远离当前样本θ,还是保持相对接近?这些问题可以通过测量接受样本之间的自相关来回答。我们不希望遥远的样本过于相关,因为我们正在尝试实现马尔可夫链,即样本应仅依赖于其先前的样本,自相关图应显示样本 I 和 i-1、i-2、…i-k 之间的相关性快速呈指数下降
通过为每个滞后 k 计算以下函数来定义自相关:
The lag 𝑘, is basically the range ahead of sample 𝑌i in which we would like to measure the correlation.
下图显示了从 1 到 100 的 a、b 和 k 的自相关性。k=0 的滞后意味着我们正在测量样本与其自身的相关性,因此我们期望它等于 1。k 值越高,相关性应该越低。
在我们的例子中,我们很幸运有足够低的相关性。一般来说,我们可能希望自动设置建议分布的参数 Q。常见的方法是不断调整提案参数,使 50%以上的提案被拒绝。或者,可以使用增强版的 MCMC,称为哈密顿蒙特卡罗,它减少了连续采样状态之间的相关性,并更快地达到稳定分布。
6-结论
虽然这种算法背后的抽象可能看起来难以理解,但实现实际上非常简单,并给出了令人惊叹的结果。事实上,概率编程的伟大之处在于,你只需要写下模型,然后运行它。不需要计算证据,或者确保一些约束性的数学属性。
我希望阅读这篇文章的每个人都觉得它很有趣,很有见地。如果有积极的反馈,将会有更多本系列的文章“从零开始”,在那里我从零开始解释和实现东西(显然!),所以如果你喜欢的话,请一定要建议你接下来想让我讲的内容!
欢迎任何问题,我会尽我所能回答!反馈是非常受欢迎的,因为这是我的第一篇文章,我希望改进。
参考资料:
Peter Driscoll,“径向速度数据集的最*二乘法和贝叶斯拟合技术的比较”
Carson Chow,“MCMC 和数据拟合模型”
约翰·h·威廉姆森,“数据基础——概率”
西蒙·罗杰斯,“机器学习的第一课”
致谢:
另一位媒体作家, Vera Chernova ,写了一篇文章:“如何通过三个步骤将 Jupyter 笔记本嵌入媒体文章:1–2–3!”
朋友和数据科学家同事马克·艾斯丘和康斯坦丁诺斯·约安*迪斯在本文发表前给予了反馈。
从拓扑数据分析到深度学习:不劳无获
原文:https://towardsdatascience.com/from-tda-to-dl-d06f234f51d?source=collection_archive---------2-----------------------
Source
今天,我将尝试给出一些关于 TDA(用于拓扑数据分析)的见解,这是一个快速发展的数学领域,肯定会很快完全集成到机器/深度学习框架中。为了说明这一理论的威力,本文后面将给出一些用例。
快速历史
拓扑数据分析,也缩写为 TDA ,是从应用拓扑学和计算几何的各种著作中出现的一个新领域。它的目的是提供良好的数学,统计和算法的方法来利用数据中的拓扑和潜在的几何结构。你通常会发现它适用于三*数据,但经验表明,TDA 揭示了在其他情况下也很有用,如时间序列。
Example of Mapper construction based on the height function
拓扑学定义的理论多种多样,在机器学习或者深度学习中的影响力也在不断增长。那些曾经对那些能够带来关于数据的意想不到的见解的开箱即用的理论感兴趣的人可能会对接下来的事情感兴趣!然而,关于这篇文章,我将把重点放在可视化的例子上,为了便于理解,我将自己限制在一*和二*空间。
持久性同源性
在流传最广的理论中,有持久性同源性。这是一种旨在计算不同空间分辨率下空间的拓扑特征的方法。通过构建,这些特征更有可能代表潜在空间的真实特征(而不是采样、噪声或特定参数选择的假象),因为它们与数据点的空间关系有着内在联系。为了计算一个空间的持续同调,它必须首先被表示为一个嵌套的单纯复形(基本上是一个由一组点和它们的关系组成的图,又名二*空间中的线和三角形)。这个家族叫做过滤。一般来说,这种过滤的构造是基于距离函数的定义,其值用于索引族中的复合体。因此,这个距离的选择非常重要,并为那些对公制学习感兴趣的人提供了思考的食粮
Visual Construction of the Simplicial Complex
持久性同调理论允许我们用一个持久性 条形码或持久性 图唯一地表示一个过滤的单纯复形的持久性同调。条形码图用一条水平线表示每个持久性发生器,水平线从它出现的第一个过滤级别开始,到它消失的过滤级别结束,而持久性图用其 x 坐标出生时间和其 y 坐标死亡时间为每个发生器绘制一个点(下面给出了示例)。视觉上,在二*中,你独立地考虑每个点:你围绕那些点画一个半径递增的圆,直到你找到一些交点(出生时间)。你继续绘制,直到你覆盖了一些点,破坏了一些先前创建的结构(死亡时间)。您最终得到组件(出生和死亡日期),这些组件通过那些持久性图和条形码来表示。
持久性图表
为了更好地形象化这个理论,让我们考虑一*时间序列的例子,记为 f 。我们想通过下面的规则来关注 f 的临界点:当引入一个新的组件时,我们说创建它的局部最*值代表该组件。当我们传递一个局部最大值并合并两个分量时,我们将最大值与代表这两个分量的两个局部最*值中较高的(较年轻的)值配对。另一个最*值现在是合并产生的组件的代表。当 x 和 y 通过这种方法配对时,我们定义这对的持久性为f(y)——f(x)。持久性在持久性图中通过将每一对映射到点( f(x),f(y) )来表示,该点的坐标是相应的临界值,如下所示。
Value-Based Persistence of a 1D Signal
矢量化和表示法
太好了,但是下一步该怎么办呢?!?从持续图中提取的向量的不一致性问题是机器学习应用的真正缺点。为了在不深入研究新型神经网络的情况下解决这个问题,我们必须转换以前的持久性表示,以某种方式收集相同的信息,这可能是相当大的。对于机器学习来说,提取外围的持久点可以表示很好的特征,但是图表中包含的一些底层信息可能会在这个过程中丢失。
在这里,我将强调三种可能性:贝蒂曲线、T2 持续景观和 T4 持续图像。(整个计算都要归功于 Gudhi 包,它是由法国团队 DataShape 为 INRIA 开发的。)以下结构即将成为 scikit-learn 兼容产品。同时,我向你推荐我对应的 Github 库的持久化构造,以及图表的表示。让我们通过下面的例子来想象一下。曾经梦想用算法计算你手上的手指数量的人会对即将到来的事情感到高兴…
TDA Representation of a 3D Object: Finger Characterization
我们从这个结果中得到什么。首先,您通过持久性图和条形码以图形方式观察到有 5 个突出显示的组件。不出所料,那是 5 根手指!然而,其中一个组件位于无穷大:这对应于在考虑过滤的上层时遇到的第一个点,自动给定一个无穷大的值。因此,你的持久性景观只清楚地代表了四个较*的手指。这是在应用 TDA 时要记住的事情!
贝蒂曲线:让我们考虑一个持久性条形码,我们对其半径空间进行矢量化。条形码图的每个组成部分都被称为一个函数,在定义它的半径上取值为 1,在其他任何地方取值为 0。这些函数的总和定义了贝蒂曲线。
暂留景观:暂留图的每个组成部分都由一个三角函数引用(斜率为 1)。这些三角形函数的叠加给出了不同平面上的山脉的外观结构,我们迭代地从中提取上层景观。
余辉图像:余辉图的每个分量成为特定方差的二*高斯分布的中心。通过创建相应的分布叠加矩阵,就获得了图像。
人们应该注意到下面这一点:即使手指的数量清楚地出现(对应于远离对角线的点),仍然存在拓扑噪声的概念(靠近对角线的点)。因此,持久性景观通常更好使用,因为它们或多或少对它保持健壮,因为它们更好地描述了数据集的大多数持久性对象。然而,拓扑噪声有时是有用的信息,特别是在处理标准偏差对分类非常重要的时间序列时…
深度学习管道
一旦您为所有的示例构建了相应的持久性表示,您可能想知道如何使用它。贝蒂曲线有点容易馈入一个 1D 卷积网络,而持续图像适合一个 2D 卷积网络。
关于持久性景观,它变得有点棘手。对于那些想知道如何充分利用它而不手工制作自己的功能的人,这里有一个我构建的解决方案。基本上是联系到持久性剪影的思想,是从持久性图中得到的三角函数的加权和。新创建的层对应于这些持续景观的加权和,得到持续轮廓的移动平均结构作为输出。输出是一个一*信号,你可以把它输入一个 1D 卷积网络。我会在接下来的工作中进一步发展这个想法!😃
Credits: Gaijin et al.
这个理论有很多可能性,这些结果和深度学习之间的接口目前仍在开发中。许多想法将会出现,这使得这个话题变得非常热门和有趣!敬请关注即将到来的文章,如果你想了解更多,别忘了给你鼓掌;)!
参考
- 我的 GitHub 资源库
- 持续理论:从颤动表象到数据分析 是
- 谷棣项目
- 同调与拓扑持续
- 几何和拓扑推论
从失败的通过到通过的仪式:作为数据科学教育工具的泰坦*克号数据集
原文:https://towardsdatascience.com/from-tragedy-to-educational-tool-the-titanic-data-set-at-a-data-science-rite-of-passage-91e95f336af8?source=collection_archive---------8-----------------------
皇家邮轮泰坦*克号的沉没是现代史上最著名的悲剧之一。它在历史上作为一个值得注意的事件的地位在很大程度上是由于它在 1997 年被重新改编成电影,其中泰坦*克号既作为背景又作为电影名称。当泰坦*克号的故事创下纪录时,它成为了一个标志性的悲剧,成为了第一部票房超过 10 亿美元的电影,并一直保持这一头衔,直到 2010 年《阿凡达》上映。很明显泰坦*克号的沉没在一般社会中是受欢迎的;几家公司已经宣布,他们将开始以 105,129 美元的价格为客户提供泰坦*克号残骸的水下潜水之旅,这些公司表示,这个数字相当于经通胀调整后泰坦*克号头等舱机票的价格。它在数据科学社区中的流行是因为它是一种有用的教育工具;泰坦*克号悲惨航行的数据为数据科学学生提供了许多教育可能性。
The Titanic at Southampton, England, one of the ports where it picked up passengers before it began its trip across the Atlantic.
使用 Titanic 数据集—本质上是一个逗号分隔的值(。csv)文件复制了船上的乘客声明——在现代数据科学世界中,这已经成为某种仪式。该数据集提供了大量实践各种基础数据科学技能的机会。一个已经变得流行的可能的学习练习,尽管它也是一个有点病态的练习,是在表面水平上分析泰坦*克号数据集,这对数据科学学生和新手来说是完美的,以获得对乘客在哪个等级和他们生存可能性之间关系的见解。对数据集的分析进一步揭示了数据中的一种模式,这种模式对许多人来说可能是直观的,并且得到了数据集证据的支持,即乘客乘坐的舱位等级越低——头等舱、二等舱或三等舱——泰坦*克号沉没时,你生还的可能性就越*。
除了这个特定的数据集,专业的数据科学家可以被要求研究任何主题,无论是什么,都必须以数据为基础。作为一个人,你不会带着偏见或预先存在的假设行事,而只是作为数据的推动者,在数据集中分析和寻找模式,而不管你找到的模式可能是什么。有了这些无偏见地发现的模式,你和你的团队(如果合作的话)可以开始评估这些模式的意义。如上所述,Titanic 数据集在分析数据、识别数据中的模式以及评估数据中的模式的意义方面尤其丰富。仅此一点就能使泰坦*克号数据集成为一个强大的教育工具,但这并不是使用这个特殊数据集成为某种仪式的唯一原因。
泰坦*克号的原始数据更加混乱。这提供了一个练习清理数据集以便于分析的教育机会。然而,即使在混乱的状态下,泰坦*克号数据集在分析后仍然显示出无数的模式-使这个数据集成为崭露头角的数据科学家的完美缩影,以从多个角度练习他们使用数据集的基本技能。这反过来意味着有几个机会来练习评估数据模式,以最终回答他们想要回答的问题。正是这些可能的技能应用机会,以及前面提到的机会,将这个流行的数据集变成了一个无处不在的教育工具,这个领域的大多数人都遇到过,如果不是自己工作的话。
尚不清楚这种使用泰坦*克号数据集的趋势是何时开始的,但就在几年前,它的受欢迎程度甚至进一步上升。这是因为几年前,一家提供免费在线数据集的公司和网站 Kaggle 在 GitHub 上发布了一项比赛,要求数据科学家想出一种方法来预测泰坦*克号沉没时是否有任何随机乘客幸存或死亡。这可能始于一场 Kaggle 比赛,但它的普及程度甚至更远。一个简单的谷歌搜索显示了数百篇博客文章,所有技能水平的数据科学家在这些文章中解释了他们制定的预测方法。更多关于泰坦*克号数据集的不同可能研究问题的谷歌搜索返回了大量由数据科学家撰写的博客文章,这些文章讲述了他们的解释,并解释了他们在解决问题时使用的方法,他们开始在脑海中分析泰坦*克号数据集。
Courtesy of Stephen Millborrow
这艘“不沉之船”的沉没已经过去了 100 多年,泰坦*克号的故事通过电影被纪念也已经过去了 20 多年,但在数据科学领域,它的相关性是非常当前的。它的持续相关性依赖于数据集丰富的可能性,这为数据科学家提供了一次又一次练习技能的机会,无论他们的技能水平如何。因此,对于那些处于数据科学创新前沿的人来说,巨大的数据集仍然是一个受欢迎的教学和学习工具。它的受欢迎程度似乎不会很快改变。
来自《什么是 numpy?🤔到“我爱 numpy!💪🏼"
原文:https://towardsdatascience.com/from-what-is-numpy-to-i-love-numpy-a130285e333d?source=collection_archive---------2-----------------------
Numpy 或“数字 python”是用于科学计算的核心 Python 库,Numpy 也很快,因为它与 C 库绑定。
常规 python 列表与 Numpy 数组:
这种差异主要是由于“间接性”——Python 列表是指向 Python 对象的指针数组,每个指针至少有 4 个字节,即使是最*的 Python 对象也有 16 个字节(4 个用于类型指针,4 个用于引用计数,4 个用于值——内存分配器四舍五入到 16)。NumPy 数组是一个统一值的数组,单精度数字每个占用 4 个字节,双精度数字占用 8 个字节。不太灵活,但是您为标准 Python 列表的灵活性付出了很多!这就是 numpy 数组比 Python list 更紧凑的原因。
来源:😊
目录:
- 装置
- 基本数字阵列
- 另一个很酷的内置方法
安装:👨🏼💻
有两种安装方式:使用 pip 或 anaconda。如果你没有安装 anaconda,我会使用 pip,但是我推荐使用 anaconda 🐍相反。
conda install numpy
或者
pip install numpy
基本 Numpy 数组:👓
Numpy 数组有两种不同的类型:vetrices 和 matrices。Vetrices 是严格的一*数组,而 Matrices 是二*的(注意:二*数组可以包含一行和一列)。在这一节中,我想介绍 Numpy 数组和几个函数的基本实现。
import numpy as np
这就是 numpy 显示二*数组的方式。在这种情况下,上面显示的二*数组的形状是(3,3)。3 个用于其行,3 个用于其列。
- shape: shape 是一个描述符,用于从给定的 np 数组中返回元组中的行数和列数。
- 整形:为你的 np 数组分配一个新形状的函数
注意:当你试图改变二*数组的形状时,请注意数组中有多少个元素。
举例:
当一个(3,3) 2d 数组总共有 9 个元素时,如果将其列整形为(3,5)或任何大于 3 的数,这是不可能的。但是在另一方面,仍然有可能重新成形为(9,1),九行和一列。
numpy_array.reshape(3, 5)
会给你:
Traceback (most recent call last):
File "practice_one_numpy.py", line 9, in <module>
two_darray.reshape(3, 5)
ValueError: cannot reshape array of size 9 into shape (3,5)
内置方法🐍:
这里有几个很酷而且可能是有用的数字内置方法😉。
- arange:返回具有给定间隔的均匀分布的值
- 眼睛:创建一个单位矩阵
- random.rand:创建一个给定形状的从 0 到 1 的随机数数组。
如果您想了解更多关于 numpy 的信息,请查看此资源。🐍。谢谢你😁
前沿人工智能技术正以前所未有的方式影响着金融科技的业务运营!
原文:https://towardsdatascience.com/frontier-ai-technologies-that-are-impacting-fintech-business-operations-like-never-before-99737daf197f?source=collection_archive---------8-----------------------
金融公司在采用新技术和创新方面总是领先于其他公司!难怪这些了解未来的公司体验到了最好的人工智能——从欺诈检测到风险管理,甚至预测不良贷款。
这一部分的挑战也是独特的,变化正以极快的速度到来。他们面临着数据量、信息量、复杂性和碎片化的问题。即便如此,机器学习、自然语言处理、大数据和分析、数据挖掘、自动化和物联网(IoT)等人工智能技术正在取得重大成果。
以下是人工智能技术为金融科技创造前所未有的商业运营改进的主要领域。关注领先的新兴公司以及这些推动他们走向积极业务成果的强大技术是值得的。
1.欺诈检测:
欺诈检测可能是人工智能领域最大的一块。这也是最重要的,预计到 2020 年将成为 3B 的一个美元市场。
为了理解金融科技领域欺诈的含义,让我们考虑一个常见的例子。随着越来越多的人在日常交易中使用网上银行,他们将会创造成千上万的印象和数据点。通过几个设备和接触点,这些服务将被不断地访问。银行必须建立非凡的灵活性,及时快速地识别和定位可疑行为。
欺诈检测解决方案依靠大规模数据挖掘和数据分析技术来得出答案。该系统基于强大的神经网络算法,能够系统地处理相当大的数据集,同时识别和标记不一致。它们非常敏感,因此即使是微*的不一致和违规也能被准确地发现。
每笔交易都要扫描数千个数据点,模糊查找被用来“发现”相关的模式、异常和巧合;无论是对用户,还是对特定交易,甚至是对一段时间内发生的类似交易。与过去更加手动和耗时的方法相比,使用人工智能进行几微秒的欺诈检测是一个飞跃!
2.生物认证和令牌化:
认证和授权是我们这个高度数字化、基于知识的世界的重要方面。在这里,访问是由可验证的凭证定义的入口。
身份验证和授权之所以重要,是因为一旦提供了访问权限,就很大程度上无法收回。或者,一旦未经授权的访问被允许,就会产生灾难性的后果。
生物认证和令牌化使用人工智能技术来创建更强的系统。例如,利用语音识别和自然语言处理的设备通过其声纹来识别和授权人员。使用物联网并将使用心电图与智能系统集成的设备,其中两个系统相互通信并传递信息,唯一目的是识别某人。此外,与眼白中的静脉图案匹配的设备,或用于完美识别的“眼纹”。
令牌化也有几个用例,其中令牌被用作一种方便交易的手段。卡的详细信息、姓名和账号等敏感个人信息被分离出来,单独存储在另一个位置。在欺诈者破解这个令牌的情况下,他/她将无法使用它或识别信息所属的人。
3.自动化:
自动化在整个金融科技行业得到了广泛应用。当然,有几个明显的优势。但是,让组织能够应对不断增长的数据量的冲击是一个主要问题。
此外,还通过优化、改进客户服务等方式大幅降低了成本、减少了冗余、降低了风险、提高了预测能力、敏捷性和响应能力。
当自动化与机器学习和深度学习在预测分析和报告、营销和活动管理、语音识别和响应、数据输入、客户关系管理(CRM)以及机器人流程自动化(RPA)等功能中相结合时,优势会进一步扩大。
一家名为“WorkFusion”的公司正在彻底改变这一领域。与金融公司合作,提供人工智能支持的优势和双赢。例如,本案例研究描述了 WorkFusion SPA 如何通过 RPA、AI 和人员的独特组合,帮助 Six Financial 应对其不断增长的数据处理挑战。
4.区块链:
这项创新的新技术有潜力改变商业运作的方式。产生共享信任并确保数据完整性。从零售银行到保险和财富管理,甚至投资银行,各种规模和类型的金融服务机构都将从中受益。
关键在于这项技术是如何工作的——它从分布式基础设施开始,在这个基础设施中,关于交易的信息被安全地共享。然后,一个用户网络支持和验证每一个独特的交易,确认其准确性。在最后阶段,记录被透明地添加到每个人都可以访问的区块链中。
区块链不是天生的 AI 技术。但人工智能可以赋予它更多的力量。例如,在能源密集型的开采过程中,人工智能算法可以通过优化和平衡来降低消耗。联邦学习系统和数据分片技术可以提高效率,增强快速增长的区块链的可扩展性。区块链可以抵御黑客攻击,但是底层和应用程序更容易受到攻击。这可以通过机器学习来改变,人工智能算法可以帮助安全的应用程序部署。
这项技术用途广泛。它用于资产创建(例如,在加密货币的生成中)、资产转移(例如,在艺术品交易商和画廊多次买卖艺术品时保留记录)和数据核对(例如,钻石行业用于标记“血钻”或假货)。)
5.实时警报和通知:
随着规范分析的出现,分析系统可以规定未来的路径,世界不再停滞不前。我们在快速前进。
客户期望通过任何设备和渠道获得准确的实时警报和通知,这是目前行业的基准。很难想象今天的一笔交易会在月底才生成一份对账单。标准变化很快。
大数据挖掘、物联网、机器学习和更多这样的人工智能技术正在为更快、更敏捷的系统创造可能性。不断发展的组织正在利用这些优势!
推荐系统的前沿&多样性
原文:https://towardsdatascience.com/frontiers-of-recommendation-systems-diversity-f668adad502c?source=collection_archive---------5-----------------------
批判性阅读:来自 2011 年 ACM RecSys 和管理科学的论文
Alaska Frontiers. Photo Credit: US Dept of Interior
介绍
最近,我一直试图了解推荐系统如何影响用户体验的多样性。在我开始自己的项目之前,我想看看聪明人都做了些什么。因此,我阅读了来自 ACM RecSys 关于多样性的 2011 年研讨会的全部论文,以及来自管理科学的相关论文。这些论文的作者已经成为音乐流媒体行业的重要参与者。例如,奥斯卡·塞尔马目前担任潘多拉公司的研究主管。所以我非常兴奋地看到他们的研究如何塑造了他们的产品。
在这篇文章中,我想与你分享我的文献综述。我的目标是:
- 把所有的文件归档在一个统一的框架下;
- 为每篇论文创建一个摘要;
- 批判性地评估每篇论文。
放弃
- 从 2011 年到现在已经 7 年了。那么,为什么我称这个推荐系统的前沿为&多样性呢?当然,从那时起,已经有一些关于这个主题的论文被发表了;但是 2011 年是 RecSys 最后一次举办关于推荐系统多样性的研讨会。我想阅读这些论文作为我的种子,在我的文献综述的下一个迭代中,我将从中扩展。
- 我们大多数人认为文学评论是必要的罪恶。然而,随着时间的推移,我已经学会了接受这个过程。它让我接触到许多不同的观点,并帮助我形成一个鸟瞰图。这有两个好处:(1)我不重新发明轮子;(2)我能识别该领域的公开挑战,这有助于我成为更好的贡献者。
- 本文假设读者已经熟悉基本的推荐算法。如果你是推荐系统的新手,Medium 上有一些写得很好的教程。我个人最喜欢的是 Kelly Peng 的 我是如何为香水——建立一个推荐系统的,这是一个非常棒的端到端项目,包括网络清理、直觉、代码和令人着迷的最终演示。
行动纲要
2011ACM rec sys论文多是关于推荐系统的设计。
- 优点:引入了许多不同的指标&算法,用于多样化的推荐。
- 缺点:在理解对用户体验的潜在影响时,常用的技术是交叉验证;精确度和召回率仍然是流行的指标。虽然这种方法通常用于信息检索文献,但它可能不适合推荐系统。一个新的推荐系统,一旦实现,改变的不仅仅是对个人用户的推荐。更重要的是,它改变了项目/用户网络的全局拓扑,这将馈入推荐系统。不幸的是,在 2011 年的 ACM RecSys 中,这个问题的动态性质很少受到关注。
- 值得注意的例外是 Oscar Celma 和 Perfecto Herrera 的论文。他们在 Last.fm 上实施了一项实验,使用了 233 名受试者。虽然这是正确的一步,但有限的受试者数量限制了他们研究动态、一般均衡效应的能力。
相比之下,管理科学论文关注消费者行为和福利分析。
- 优点:作者对消费者行为进行了建模,并通过模拟研究了他们的选择和效用如何受到常见推荐系统的影响。
- 缺点:我们不知道效用函数是否准确地描述了真实的顾客;如今企业实现的推荐算法可能更加复杂。
大多数论文提供了单一的视角。
我不怪他们。学术界奖励严谨——自然,一次对一件事严谨更容易。也就是说,我认为了解该领域的最佳方式是采取多视角、多学科的方法。这正是我希望在下一节中完成的。
假设空间
推荐会增加多样性吗?
- 【H1】建议增加多样性:与实体店不同,互联网有无限的货架空间。随着用户浏览数以百万计的商品,市场将从热门商品转向利基市场。
- 【H2】推荐减少多样性:尽管货架空间无限,但屏幕空间有限。如果推荐系统一直推荐高度相似的项目,它会降低感知的多样性。
- 【H3】推荐增加个体多样性;但是降低了总体的多样性:单个地,用户得到了大量不同项目的推荐。但是,如果每个人都被推荐了同一套不同的商品,就会降低对多样性的感知。
最后一点很抽象,所以让我给你举个例子:
- 网店之前:假设每个人只吃 1 种水果,因为他们当地的店都是这么卖的。爱丽丝吃苹果,鲍勃吃香蕉,凯特琳吃樱桃,迪伦吃苹果。当他们互相拜访时,他们会接触到新的水果。
- 网店消灭本地店铺后:RS 有可能只推荐(苹果、香蕉)给大家,因为这些是最受欢迎的商品。你期望人们更快乐,因为现在他们可以吃更多种类的水果。然而令人惊讶的是,他们可能仍然会抱怨多样性的减少。这是因为无论他们去哪里,他们都只能吃到东西(苹果、香蕉)——因为这种意外收获的美妙感觉现在已经消失了。
用户重视多样性吗?
- 【H6】熟悉感胜出:当我们听到一首新歌时,这是一种精神负担。所以大多数用户更愿意呆在他们的舒适区。
- 【H7】多样性胜:你对自己喜欢的歌,播放多次后,就厌倦了。这是边际收益递减的基本规律。
- 【H8】相关性+多样性:事实介于两者之间——用户只重视与他们“相关”的多样性。如何定义相关性?这似乎是一个悬而未决的问题,作者提出了许多不同的定义。
我的观察
- 最佳的 rs 设计取决于用户的偏好:如果用户重视熟悉度,那么推荐系统(RS)应该推荐相似的项目;如果用户看重多样性,那么 rs 应该推荐多样化的物品;如果用户只看重相关的多样性,那么 rs 应该推荐相关的、多样化的项目。如果不首先了解用户偏好,我们就不知道最佳 RS 应该是什么样子。
- 2011 年大部分论文潜水员不研究用户偏好。相反,他们对用户的偏好做出假设:他们是否关心多样性,如果是,以什么方式?我认为下一代报纸应该更加关注理解用户偏好。
- 变化是,用户是高度异质的: (1)一些用户可能喜欢呆在他们的舒适区内,而另一些用户更喜欢探索;(2)根据使用情况、一天中的时间、他们生活的时间、心情等,相同的用户可能想要熟悉的或陌生的。迄今为止,所提出的推荐算法都是“一刀切”的。这种部署很危险,因为在现实中,用户是高度多样化的,同一用户会随着时间的推移而变化。
一般性讨论到此结束。在接下来的部分中,我将深入研究每篇论文。
目录
潜水员 2011 年论文
- 主题演讲:推荐系统的新颖性和多样性研讨会,第五届 ACM 国际推荐系统会议。
- 最大化集合推荐多样性:一种图论方法
- ❤️论推荐系统中的意外:或者如何期待意外的❤️
- 一种评估新推荐的新方法
- 基于融合的提高意外收获率的推荐系统
- 遗忘问题:利用遗忘项提高推荐多样性
- 推荐收藏的框架
- ❤️帮助用户感知推荐多样性❤️
管理科学论文
- ❤️大片文化的兴衰:推荐系统对销售多样性的影响️️❤️个人最爱!如果您想偷窥,请滚动至底部:)
1.潜水员主题演讲
摘要
- 确定推荐系统的关键挑战是:增加新颖性和多样性,同时仍然实现用户兴趣的公平匹配。
商业正在以特殊的方式考虑新奇和多样性;而研究人员才刚刚开始“寻找在推荐模型、算法、理论和评估方法中加入新颖性和多样性的原则基础”。但仍有很大的空间进行进一步研究,这也是 2011 年潜水研讨会的动机。
- 关键问题: (1)如何衡量新颖性和多样性?(2)如何增强新颖性和多样性?(3)如何提高建议的新颖性和多样性?(4)如何评估推荐系统?
2 .最大化聚合推荐多样性:图论方法
摘要
- 回想一下,推荐是一个两阶段的过程: (1)预测评分;(2)选择前 N 个预测评级作为推荐。提高多样性可以通过(1)或(2)来实现。本文属于后一类。
- 本文的目标是增加总体多样性。聚合多样性,因为消费者重视多样性,而且许可不太受欢迎的商品更便宜。
- 将多样性最大化转化为最大流问题。具体来说,(1)有 2 组顶点:用户和项目;(2)如果我们向用户 u 推荐项目 I,那么有一个优势 iu;(3)优化目标是最大化用户-项目匹配的数量,服从容量约束。
数据
- 运动神经元
- 网飞 C 奖
- 我会非常担心选择偏差,以及基于这个样本的概括结论。作者将数据集局限于具有“显著”评级历史的用户和电影,而没有详细说明什么是显著的。修剪后,MovieLens 的数据留给他们(2830 名用户,1919 项),网飞竞赛的数据留给他们(3333 名用户,2091 项)。与实际数据量相比,所选评估样本非常*!MovieLens 10M 数据集有(72,000 个用户,10,000 部电影);MovieLens RecSys HetRec 2011 拥有(2,113 个用户,10197 部电影);网飞竞赛数据有(48 万用户,17,000 项)。
韵律学
- 聚合多样性的度量是被推荐的项目总数。
- 成功度量:“给定精度水平下的分集增益”。
评论
- 这是长尾巴吗?提高 MovieLens 前 2K 电影和网飞前 2K 电影的覆盖率不是我对长尾的想法。我猜这些可能是我已经接触过的过去 10-20 年的顶级电影。我会很有兴趣看:(1)推荐电影列表;(2)在理想的实验中,该算法在多大程度上扩展到具有有限评级的更大数量的用户和项目。
- #物品并不能很好的衡量多样性。例如,如果你看了一个关于早上 5 点起床的视频,你得到了 10 个以上的推荐,你会认为这是一个多样化的推荐吗?大概不会。
- 它仍然严重依赖传统的协作过滤器来预测收视率。这是有问题的,原因有两个:(1)它不能预测新项目的评分;(2)对于探索型用户来说,这可能太保守了——你得到的推荐仅仅是与你最“相似”的用户的多样性;或者通常同时出现的项目。因此,如果你是一个刚刚开始形成自己身份的人,你可能会被归类;如果你对来自其他社会经济背景的人在做什么感到好奇,你将很难突破。
3.❤️论推荐系统中的不可预测性:或者如何预测不可预测的❤️
摘要
- 这是为数不多的模拟用户偏好的论文之一。本质上,所提出的算法所做的是剔除所有明显的推荐项目。
- 本文的一大贡献是作者对不同多样性度量的关注:新颖性定义为用户以前不知道的项目;意外之喜是一种既新奇又愉快的经历;多样性意味着物品种类的增加;意外是字面上意想不到的项目。
- 关于提议指标的关键观察:以上指标并不完全重叠。从他们的角度来看,好的推荐既出人意料,又能引发积极的情绪。我完全同意这个好的推荐系统的定义。
- 效用函数取决于:一个用户总体上喜欢电影的程度;用户对推荐电影的喜爱程度;用户对冗余和不相关的容忍度;用户是否期望推荐;最后,特质噪音。
- 经验挑战:衡量意外性和用户满意度。
韵律学
- 对于单个用户,unexpecteness =[RS \ E]/N,其中 RS 是我们的推荐系统生成的推荐项目;e 是由“原始”推荐系统生成的推荐项目(即,已经评级的项目、用户喜爱的类别、项目的评级数量、同一导演、同一组主角、共享超过 20 个标签等)。);n 是推荐项目的长度。
- 项目相似度度量: (1)对于协同过滤器:皮尔逊相关系数、余弦相似度、雅克卡系数;(2)对于基于内容的相似性,两部电影之间所有属性的加权平均值。
用户偏好参数
- 用户总体上喜欢电影的程度;
- 用户对冗余和不相关的容忍度是多少?
这两个参数是用回归法计算出来的。
数据
- RecSys HetRec 2011 年发布的 MovieLens 数据:(2,113 个用户,10197 部电影)
评估指标
- RMSE,平均绝对误差,精确度,召回率和假阳性率。
评论
- 这是我 2011 年最喜欢的论文 diveRecSys : 它仔细定义了不同的指标,并花了大量时间讨论用户偏好。
- 我希望看到用户偏好参数的分布。这将帮助我们了解用户是否有不同的偏好,如果有,主要的聚类是什么。
- 正如作者指出的,为了验证这个推荐的算法,我们需要进行真实的实验。单纯的交叉验证是不够的。具体来说,我认为使用这种方法得到的用户偏好参数可能过于保守。历史评级是通过 2 个步骤产生的:(1)用户通过网站推荐或其他渠道了解项目;(2)用户然后观看他们知道的项目,并对它们进行评级。我们知道(1)受到 CF 或 CB 的严重影响,因为大多数现有的网站已经运行这些算法。因此,我们可能会得出这样的结论:普通用户对冗余的容忍度比他们实际承受的要高。这是因为生气的用户会直接退出平台,或者花更少的时间或更少的电影评分。所有这些用户都不会在数据集中被捕获,我们只剩下对冗余有更高容忍度的用户。因此,将这个用户群的发现推广到普通人群是非常危险的。
- 我希望看到明确的长期动态模型。一旦部署,推荐算法将改变物品网络的拓扑结构和用户的相似性,从而引发难以在模拟中捕捉的反馈循环。
4.一种评价新颖推荐的新方法
摘要
- 提出一个基于网络的指标来衡量推荐的新颖性。表明协同过滤器是偏向流行的。具体来说,如果你只跟踪“相似艺术家”链接,从热门艺术家开始到达尾部艺术家的概率大约为 0。从尾部艺术家开始也没有帮助,因为知道一个尾部艺术家的用户通常也知道其他相关的尾部艺术家。从“中间”艺术家开始似乎更好:更容易同时接触到非常受欢迎的艺术家和尾部艺术家。
- 用户分析:对(288 个对象,5,573 首歌曲)实验表明,用户更喜欢由协作过滤器推荐的歌曲,而不是由基于内容的算法推荐的歌曲,即使基于社交的算法推荐的歌曲不那么新颖。
数据
- Last.fm 上 288 个受试者的实验数据
构建网络
- 每个节点都是一首歌。
- 如果 Last.fm 的 API 认为两个节点相似,则这两个节点之间存在链接。
基于网络的新颖性度量
一旦每个项目位于头部、中部或尾部,下一步就是将项目的相似性网络的属性与长尾信息相结合。执行两个主要分析。首先,我们测量曲线每个部分的项目关系。也就是说,对于属于头部的每个项目,计算位于头部、中部和尾部的相似项目的百分比(类似地,对于中部和尾部的项目也是如此)。这衡量最受欢迎的项目是否与其他受欢迎的项目相关联。其次,我们测量一个项目在长尾中的位置和它的入度之间的相关性。这使我们能够检测网络中的集线器是否是最受欢迎的项目。
实验
- 使用 CF、CB 或混合方法生成建议。
- 受试者是否知道推荐给他们的曲目,以及他们如何根据歌曲的前 30 秒在 1-5 的范围内对它们进行评分。
评论
- 我喜欢他们创建的 Markov 转移矩阵来表明 CF 是受欢迎程度有偏差的。
- 我也喜欢他们如何用实验来评估建议。
- 我们从实验中看到的矛盾的结论是,尽管存在受欢迎程度的偏差,CF 仍然优于 CB 和混合方法。我们是否应该得出结论,用户暗地里渴望熟悉感?我们应该断定基于 CF 的变体是解决方案吗?这些结论听起来还为时过早。本文中实现的 CB 和混合算法可能过于原始。我们不知道未来改进的 CB 或 HY 或其他算法是否会优于 CF。
- 基于原始数据,CF 推荐给用户的曲目有 71.69%的时间是未知的。这似乎是一个可观的数字,尽管我怀疑它夸大了 CF 的发现率。这是因为受试者只能看到音轨的前 30 秒,人们很难从前奏中分辨出一个艺术家/歌曲。
5.基于融合的推荐系统提高奇遇度
摘要
- “以融合为基础”是什么意思?假设你喜欢两样东西:苹果和橘子。这两样东西的共同特点是它们都是水果。所以基于此,我推断你喜欢水果,并可以向你推荐其他水果。
- 作者声称这种方法速度很快,并且可以生成“新颖”的项目。
- 我不相信:(1)如果我在吃苹果和橘子,很可能我已经知道其他水果。所以其他水果对我来说并不新奇;(2)我确信现有的 CB 和/或 CF 已经推荐了相同的项目。我很想知道这个基于融合的推荐系统的边际贡献是什么。
6.遗忘问题:利用遗忘项目提高推荐多样性
评论
- 遗忘物品并不新奇。
- 同样,你也不能通过挖掘被遗忘的物品来提高推荐多样性。它已经包含在现有的多样性措施中。
7.推荐收藏的框架
摘要
- 本文是关于生成播放列表的公式化问题。
- 它强调了语境的重要性。
- 目前,它与推荐多样性没有直接关系。所以我暂时跳过。
8.❤️帮助用户感知推荐多样性❤️
摘要
- 用户感知的多样性!=客观多样性。好的 UI 有助于用户更好地感知推荐多样性。
实验
- 样本量: 20 人
- 方法:受试者内实验。每个用户都有两个用户界面。在这两个 ui 之间,推荐项目保持不变,但组织方式不同。第一 UI 具有列表格式;而第二个用户界面是按类别分类的,带有帮助用户理解类别的编辑注释。
- 结果:用户对第二代用户界面更加满意。他们还认为第二个用户界面推荐了更多样化的项目集合——即使两个用户界面推荐了相同的项目集合。
评论
- 我很喜欢这篇论文的主题。很有新意。
- 也就是说,样本量太*了。同样值得注意的是,在 20 名参与者中,有 10 名是中国人,据报道他们的职业是学生、研究助理、工程师和界面设计师。鉴于参与者和本文作者之间的共同国籍和职业,我不能排除这些是作者的朋友同事的可能性,他们听说过实验的设计/实施。毕竟,这篇论文是在瑞典写的,令人惊讶的是大多数实验对象都不是瑞士人。
❤️ 9.百视达文化的下一个兴衰:推荐系统对销售多样性的影响️️(2009)❤️
摘要
- 研究问题:推荐者是否有可能增加个体多样性,但降低总体多样性?
- 方法论:建立理论模型+模拟
公制的
- 多样性是用基*系数来衡量的。
假设
- 每个用户一次购买 1 件产品
- 只有两种产品,在没有推荐的情况下,购买概率为(p,1-p)。
- 当公司推荐一种产品时,它被接受的概率为 r。
- 该公司的推荐系统是使用历史市场份额生成的。为简单起见,当市场份额≥0.5 时,推荐者会推荐该产品。
消费者偏好
- 每个消费者被表示为 2D 属性空间中的一个点。
- P【消费者 c 对产品 P 的认知】是产品到消费者的距离、产品的受欢迎程度以及消费者对受欢迎或类似物品的认知如何随距离衰减的函数。
- P[消费者 c 购买产品 p]= P[消费者 c 购买产品 p | c 知晓产品 P] P[消费者 c 知晓产品 P]。*假设它是消费者 j 和产品 c 之间相似性的增函数,它也可以修改为包括品种寻求的可能性。
- 消费者效用函数建模为多项式 logit。
福利影响
- 认知效应:推荐者帮助消费者意识到良好的产品契合度。
- 显著性效应:推荐者增加了某种产品的显著性,这可能是也可能不是一个好的产品契合度——因为 CF 根据流行度对产品进行排名。
- 如果推荐者只是增加了更适合的产品的认知度,福利会明显增加。
- 福利可能下降,如果突显效应增加了不适合的受欢迎产品。
未来工作邀请
- "未来,实证研究将有助于确定意识与显著性效应的相对强度."
后续步骤
这标志着我关于这个话题的第一轮文献综述的结束。下一步包括(1)第二轮文献综述,针对 2011-2018 年间发表的论文;(2)拿出自己的模型来解释 last.fm 这个好奇的案例。
对 DataViz 工具的不满
原文:https://towardsdatascience.com/frustrations-with-dataviz-tools-de27cbcd2ff1?source=collection_archive---------8-----------------------
Slide rule (U.S. Air Force photo by Airman 1st Class Keenan Berry)
我对目前可用于数据可视化工作的工具范围感到沮丧。它们正在迅速扩散,但经常试图解决完全相同的问题,并从相似的角度解决它们。一些用例确实被很好地覆盖了,但是很多没有——除非我错了;如果是这样,请告诉我我遗漏了什么产品!
几个被很好覆盖的案例:
使用 R / Python 进行科学分析/发布
统计分析和数据争论是核心。图表可以一个接一个地制作,非常简单,通常看起来并不美观。(你可以把它们发表在科学杂志或你的数据博客上,但不能发表在其他地方。)
我大概有 25%的时间在这里工作,直到……
信息海报设计:R/其他+插画
如果你想要复杂的布局,你需要布局软件,通常是 Illustrator。多个图可以很容易地排列在一起,具有不同的层次和共性。视觉吸引力和可视性很高,完全集成了排版、插图和其他页面设计元素。
我经常从事这方面的工作,工具也很不错。我只是和 Illustrator 有时在本质上更技术性。
简单的交互式图表/仪表盘:大量在线产品
使用 Tableau 或 Plotly 或任何其他数量的服务,您可以制作简单、清晰的图表。它们可以被组合到仪表板中,并且至少是最低限度的交互(悬停状态,打开/关闭变量,也许是一些切片)。
通过 D3 高度定制的互动 Vizzes
从头开始建造你想要的任何东西。非常适合在线。学习曲线高。
这条路我还没走过。Javascript 对我来说是一种非常没有吸引力的语言。交互性也不是那么重要。
少了什么
用于基本打印就绪图形的高度可定制工具
“可定制”和“基本”似乎是对立的,但它们不应该是对立的。我愿意做(大量)前期工作来定义一种风格,然后输入数据,以非常快地获得该风格的结果。这是因为我经常需要为打印文档制作一些基本的图表——我也不是指 Word 文档,而是真实的、设计好的跨页。所以我需要严格遵守预先定义的布局、排版规则等的图表。
尽管有上百万种工具可以制作简单的图表,但没有一种工具可以充分定制。交互式 viz 工具并不适合静态显示,R 中的主要库也不能被正确控制。这很糟糕,但我看到的最好的工具是 Illustrator 的内置图表,可以最*化定制(这些可以追溯到十多年前!).
理想的解决方案:Adobe 为图表制作了一个创意套件应用程序。
一个 DataViz 迷你语言
我不想从线条构建图表(太详细了!)但我也不想要一个试图自动为我制作饼状图的系统(太抽象了!).这种语言的目的应该是通过利用算法思*来促进创新设计;所以需要一些技能和劳动力,但你也不一定要成为 web 开发人员。
我认为我们需要一种真正专注于数据的语法,即去掉所有与网络相关的东西;这是高级的,是为数据迭代而设计的(尽管我通常很喜欢函数式语言)。
现有的解决方案都是推某种解决方案和思考。也许这只是我的背景,但这些通常似乎不太正确。例如,在 R 的 ggplot 中有“图形的语法”,或“格子”显示,这吸引了统计学家们;或者 D3 和它的各种库,这对于专注于 responsive/DOM/等等的 javascript 人来说是有意义的。我认为图形更像一个设计师,也许是一个老式的计算机爱好者。
换句话说,为什么我们要从数据中的属性(比如范围/域)或者从盒子中构建东西?这在技术上是有道理的。但是它对人类探索数据可视化的可能性有意义吗?我想多想想:
- 等级和布局,以及一些标准化的选择
- 以及计算机将如何得出值;也就是说,数据是如何通过计算机将采取的过程映射到像素/矢量上的
我认为海龟图形可以成为一个灵感:因为一只海龟画一条线或点很像人类的手,以特定和明显的顺序。对数据进行循环可以直观地构建出在绘制时以特定方式变化的模式。
简而言之,我们有很好的工具给那些完全不想成为技术人员的人,以及那些想最大限度地成为技术人员的人。我们有很好的互动和在线展示工具。但是据我所知,我们没有好的工具,将算法思*和设计焦点融合在一起;这既适用于印刷,也适用于网络。
如果有的话我会买的!
成就感在于创造一些东西
原文:https://towardsdatascience.com/fulfillment-lies-in-the-creating-something-d118db307405?source=collection_archive---------15-----------------------
这篇博文旨在提供对生成性对抗网络及其数学的完整直观理解,包括它的张量流实现。
注意:读者应该对深度学习有一个基本的了解。
在 2014 年的一篇论文中,蒙特利尔大学的博士生伊恩·古德菲勒介绍了一篇名为《生成对抗网络》的论文,他在米兰的导师包括约舒阿·本吉奥和亚伦·库*尔。这篇论文被引用了 5000 多次,并得到了所有深度学习主要先驱的评论。阅读下面 Yann Lecun 对 Gan 的评论。
生成对抗网络是近十年来机器学习中最有趣的想法——Yann le Cun(脸书人工智能主任)
这清楚地表明,生成对立网络做了一些真正有趣的事情。从现在起,我们将把生成性对抗网络称为甘的网络。Gan 很有趣,因为他们可以学习近似数据分布(也称为模仿真实数据),这是非常强大的,因为现在它可以生成现实中不存在的图像、音频剪辑、视频。在某种意义上,你可以认为甘是艺术家。的一句名言解释了甘的直觉。
我不能创造的东西,我不理解——理查德·费曼(美国理论物理学家)
甘的作品产生的效果非常强大,2018 年 10 月,佳士得数码屋(Christie's digital house)一家法国公司在一场拍卖中以 432,000 美元的价格出售了一幅由甘创作的肖像(图 1.0)。
fig 1.0 Portrait by a Gan. source: here
为什么要生成对抗性模型?
这部分是 OpenAI 关于甘的博文摘要。这个想法是,如果 Gan 在创建数据方面变得更好,那么它也能够比任何其他算法更好地理解世界上存在的数据。随着他们学习数据的底层表示,他们将会更好地理解它。Gan 属于生成模型类,基于可微分生成网络的方法,因此它们是实现这一点的方法之一,其他一些流行的方法有:
- 变型自动编码器。
- Rnn 的像 LSTM 的或者 PixelRnn 的。
- RNN-RBM 顺序输出。
- 卷积玻尔兹曼机器等等。
稍后将详细介绍这些模型,但想法是一样的,所有这些架构都试图了解定义数据的底层表示。生成模型通常属于一个活跃的研究领域,称为表示学习,即从未标记的数据中学习表示。以上所有的工作方式都不同,但他们都试图学习概率分布。
甘的作品如何?
Gan 的想法很容易理解,它由两个架构组成:一个是鉴别器,用于估计样本为真实样本的概率;另一个是生成器,用于生成接近真实样本的数据。随着时间的推移,鉴别器在鉴别方面变得更好,而生成器在生成更接近真实样本的样本方面变得更好(图 1.1 用于说明)。这两个模型的目标是相反的,因为当生成器最大化鉴别器出错的概率的同时,鉴别器尽力预测正确的标签(真的或假的)。如果你仔细想想一个模型在帮助另一个变得更好,这个想法也会变得有趣。
fig 1.1. Block Diagram of Gan’s. source: here
考虑图 1.2。这里 p(x)(右边蓝色的一个)是图像的真实分布,pθ(x)(绿色的一个)是从通过我们的神经网络的高斯分布中提取的点。最初,这些点将是完全随机的,但与训练一样,我们的模型参数θ被优化以最*化两个分布之间的差异(通过使用 KL 散度或任何其他手段)。
fig 1.2 source: here
发生器和鉴别器可以是相同或不同的结构,在 Gan 的最初论文中,他们通过提供随机噪声作为发生器的输入来使用多层感知器,并且另一个多层感知器模型被用作鉴别器,其检测样本 a 是产生的还是真实的。在本文的后面部分,我们将通过使用一种基于卷积的架构(称为 DCGAN(深度卷积生成对抗网络))来构建我们自己的生成神经网络,但首先让我们将 GAN 背后的数学放入正确的位置。我会尽量让数学简单,但要确保你的基础知识顺序正确。
制定目标函数
目标是通过将随机噪声 z 作为输入经过神经网络 G(z; θg )其中 θg 是生成器神经网络的参数,把任何一个神经网络看成 a,**Universal function approximator**
,我们还将定义另一个神经网络 D(x;θd )鉴别器,这个网络将给出概率 d(x) 【在 0 到 1 之间】 x 来自真实数据而不是 Pg,当 G 被训练来最*化 log(1D(G(z))时,D 被训练来预测正确的标签。G 的最*化项 log(1D(G(z)))是有意义的,因为最初,概率 D(G(z))会很低,因为发生器刚刚开始产生样本,鉴别器很容易预测样本是真的还是假的,所以 log(1D(G(z))的总体结果很大。所以当 G 的目标是最*化时,D 的目标是最大化,把这整个情况看作一个最*-最大博弈 V(D,G)
fig 1.3 Loss function of Gan’s source here
打破上面的等式,
首先,Ex∞pdata(x)[log(D(x))]—期望[最大化生成的样本 x 是实数]。
第二,Ez∞pz(z)[log(1D(G(z))]—期望[最*化生成的样本不是真实的。]
上述等式本质上是一个最*-最大博弈,其中一个人试图最*化,另一个人试图最大化。让我们以机器学习中的 L2 正则化为例来理解这种最*-最大博弈情况。在正则化中,正则化项防止权重非常*,但同时优化器最*化总体目标函数,这通常导致*的权重值。这种情况类似于 gan 的最*-最大情况,但不同之处在于,Gan 的最*化和最大化都是由优化器本身控制的。
理想情况下,D(x)的最佳值应该是 0.5,这意味着它不能区分真样品或假样品,即
d∫(x)=Pdata(x)/(Pdata(x)+Pg(x))和 Pg = Pdata。
同时训练 D(x;θd )和 G(z; θg 理论上看起来不错但实际操作中我们通常训练 D(x;θd )对于我们每次训练 G(z; θg )使得鉴频器始终强于发生器。
生成性对抗网络训练。
考虑下面给出的图。
fig 1.4 source here
这个想法很简单,训练网络进行一些迭代,直到结果看起来令人满意。
重复以下步骤 N 次迭代:
步骤 1:对于 n 次迭代中每一次,K 次迭代:
1.select a mini-batch of noise samples (z1....zm) 2.select a mini-batch of real-data samples (r1....rm) 3.train the discriminator with using max-min loss function [eq(1)] over m samples.
第二步:对于下一次迭代:
1.select a mini-batch (z1.....zm) from p(z) 2.train the generator by minimizing the log probability of generator making mistake.
最初的论文提到了使用 SGD 进行训练,但建议使用更强大的优化器,如 Adam、Adagrad、rms-prop 等。
什么是 DCGAN?
DCGAN 或深度卷积生成对抗网络是对以前的 GAN 的一大改进。虽然理论上甘的架构看起来很简单,实际操作起来却很难训练出一个甘。原因是,梯度必须流过鉴别器和发生器,由于这个事实,Gan 的训练变得不稳定。我们将在本文的后面部分讨论这些主题,但首先,让我们试着理解 DCGAN 的架构。
DCGAN 本身是一类基于深度卷积的架构,由两个卷积神经网络组成,具有以下约束条件(根据原始论文,阅读:此处为)。以下约束是在执行广泛的模型搜索后得出的。
- 用步长卷积替换所有池层,通过这种方法,网络不是依赖池层(最大池或平均池)来执行空间下采样,而是自己学习。
- 移除所有完全连接的层以创建更深层次的架构,因为完全连接的层会影响网络的收敛。
- 使用批处理标准化来稳定深层之间的梯度流。
- 对生成器中的所有层使用 ReLu 激活,除了使用 tanh 的输出层和使用 sigmoid 或 softmax 的鉴别器。
在 DCGAN 的原始论文中提出的体系结构包含一个产生噪声的输入层以及发生器中的四个去卷积层和鉴别器中的四个卷积层以及一个输出层。
fig 1.5 DCGAN architecture. source here
如果你不知道转置卷积,那么看看 Naoki Shibuya 的博客文章。
构建深度卷积生成对抗网络。
本次演示的代码取自于tensor layerDCGAN 的原始实现,经过修改后可用于 Sully Chen 数据集和分层可视化,以真正理解网络是如何学习的。该数据集是为训练自动驾驶汽车而建立的,它包含 63k 张道路驾驶图像,以及相应的转向角和其他值,如油门踏板等。他们使用这个数据集的主要想法是看看 Gan 能多好地模拟真实的驾驶场景,如其他行人、车辆等。如果你从更大的角度来看,这个实验很棒,因为现在你不需要依赖安装在你车前的摄像头来捕捉道路图像,你只需要坐在一个房间里就可以产生无尽的数据。虽然用生成的图像来训练自动驾驶汽车的想法有多好?我将把它留待进一步讨论。
注意:模型的所有权重都使用 Glorot 初始化器初始化。典型的 Glorot 初始化如下所示,
步骤 1: std_dev = sqrt(2.0/(扇入+扇出))
步骤 2:权重=正态分布(平均值=0.0,stddev)
如果你想了解更多关于 Glorot 初始化器或者为什么使用它,点击这里。
Tensorflow 实现的生成器
让我们看看生成器的代码。代码的流程如下:
1.定义发生器参数,如输出图像大*,过滤器参数,伽玛初始化。
2.输入层的*数为 100,即 100 个随机数,由均值= 0、标准偏差= 1.0 的均匀分布生成。
3.输入层与 64 864*64 单元的密集层相连。
4.重塑致密层高度= 64,宽度= 64,深度= 512
5.使用批量归一化进行归一化,gamma 采样自均值= 1.0、std_dev=0.02 且 ReLu 激活的均匀分布。
6.DeConv2d 或简单转置卷积层,内核=(5,5),步幅= (h=2,w=2),深度 64 *4,零填充。
7.使用 ReLu 激活进行批处理标准化。
8.DeConv2d 或简单转置卷积层,内核=(5,5),步幅= (h=2,w=2),深度 64 *4,零填充。
9.使用 ReLu 激活进行批处理标准化。
10.DeConv2d 或简单转置卷积层,内核=(5,5),步幅= (h=2,w=2),深度 64 *4,零填充,双曲正切激活。
鉴别器的张量流实现
- 定义模型参数,如输出图像大*,过滤器参数,伽玛初始值。
- 卷积层,内核大*= (5,5),步距= (h=2,w=2),具有 Relu 激活和零填充。
- 卷积层,内核大*= (5,5),步距= (h=2,w=2),具有 Relu 激活和零填充。
- 使用 gamma =正态分布(平均值= 1.0,标准差= 0.02)进行批量标准化。
- 卷积层,内核大*= (5,5),步距= (h=2,w=2),具有 Relu 激活和零填充。
- 使用 gamma =正态分布(平均值= 1.0,标准差= 0.02)进行批量标准化。
- 卷积层,内核大*= (5,5),步距= (h=2,w=2),具有 Relu 激活和零填充。
- 使用 gamma =正态分布(平均值= 1.0,标准差= 0.02)进行批量标准化。
- 展平图层。
- 带有 1 个隐藏单元的输出层,带有 Sigmoid 激活。
让我们将生成的结果与真实结果进行比较
我不得不说结果看起来比预期的更有希望。在此之前,让我们看看真实数据图像是什么样的(下面的样本是从真实数据集中随机抽取的,目的是看看 gans 在理解数据方面有多好)。
fig 1.6 Random samples from train dataset source
现在生成的样本,
epoches from 1st to 3rd
epoches from 4th to 7th
fig 1.7 Incremental progress shown using epoches as progress points.
如您所见,第一个时期模型的样本只能获得数据的本质,但随着时期数量的增加,输出变得更好,在第 10 个时期,输出变得更好。这个网络被训练了 30 个 epoches,让我们来想象一下。从 epoches 11 到 epoches 排列成一行的图像。
fig 1.8 Generated samples from 11th epoch to 30th(some results skipped)
接近最后一个时代,结果开始捕捉甚至微*的建筑,如轮胎,灌木等。尽管效果不错,但生成器有时仍无法捕捉道路和山脉之间的模糊边缘,导致两者融合。结果仍然是完全可以接受的。
发电机和鉴频器损耗。
Gan 的会聚不稳定,这直接反映在损耗值的变化中。下面提供了我们 gan 架构的损耗值。
Epoch: [ 2/30] [ 139/ 997] time: 0.4634, d_loss: 0.67223823, g_loss: 0.71121359
Epoch: [ 2/30] [ 140/ 997] time: 0.4640, d_loss: 1.28069568, g_loss: 1.98622787
Epoch: [ 2/30] [ 141/ 997] time: 0.4628, d_loss: 1.44974589, g_loss: 0.46058652
Epoch: [ 2/30] [ 142/ 997] time: 0.4819, d_loss: 1.02387762, g_loss: 1.69937968
Epoch: [ 2/30] [ 143/ 997] time: 0.4781, d_loss: 0.59786928, g_loss: 1.81390572
Epoch: [ 2/30] [ 144/ 997] time: 0.4632, d_loss: 0.96302533, g_loss: 0.62419045
Epoch: [ 2/30] [ 145/ 997] time: 0.4622, d_loss: 0.62077224, g_loss: 1.15416789
Epoch: [ 2/30] [ 146/ 997] time: 0.4726, d_loss: 0.57695013, g_loss: 1.11101508
Epoch: [ 2/30] [ 147/ 997] time: 0.4843, d_loss: 0.64481205, g_loss: 1.35732222
Epoch: [ 2/30] [ 148/ 997] time: 0.4617, d_loss: 0.46775422, g_loss: 1.74343204
Epoch: [ 2/30] [ 149/ 997] time: 0.4668, d_loss: 0.60213166, g_loss: 0.84854925
Epoch: [ 2/30] [ 150/ 997] time: 0.4637, d_loss: 0.75188828, g_loss: 1.56600714
Epoch: [ 2/30] [ 151/ 997] time: 0.4644, d_loss: 0.80763638, g_loss: 0.80851054
Epoch: [ 2/30] [ 152/ 997] time: 0.4685, d_loss: 0.66286641, g_loss: 0.79960334
Epoch: [ 2/30] [ 153/ 997] time: 0.4619, d_loss: 0.64668310, g_loss: 1.32020211
Epoch: [ 2/30] [ 154/ 997] time: 0.4742, d_loss: 0.46545416, g_loss: 1.55003786
Epoch: [ 2/30] [ 155/ 997] time: 0.4970, d_loss: 0.94472808, g_loss: 0.49848381
Epoch: [ 2/30] [ 156/ 997] time: 0.4768, d_loss: 0.78345346, g_loss: 1.03955364
我们可以清楚地观察到鉴频器和发电机损耗值上升和下降了多少。与 gans 训练相关的问题将在本博客的后半部分讨论。
使用发生器和鉴别器的分层可视化来解释 Gan
在我们看到的大多数应用中,涉及到神经网络,它们就像一个黑盒,即从一方给出数据并得到输出。我们通常不了解网络内部发生了什么,即使是在抽象的层面上,所以我决定在这个方向上迈出一步,并试图了解生成器和鉴别器中每一层的输出发生了什么,网络是如何生成或鉴别数据的。
注:所有分层输出都是在 Sully Chen 上用 30 个历元训练网络后归一化前得到的。
发电机
第 1 层: 正如所料,最初网络只产生一些噪声。
fig 1.9 1st Layer output
第二层: 网络开始生成一些模式。
fig 1.10 2nd Layer output.
第三层: 有用的模式出现了。
fig 1.11 3rd Layer output
第 4 层: 将应用 tanh 激活的最终图案。
fig 1.12 4th Layer Output
鉴别器
第 1 层: 我们知道较低层用于提取简单的特征,如水平或垂直边缘检测,在我们的实验中观察到了同样的情况。
fig 1.13 1st Layer output.
第二层: 第二层的输出在第一层输出后完成。我们能理解的不多,但所有这些对网络本身都很重要。
fig 1.14 2nd Layer output.
第三层: 尺寸变*,预测仅与网络相关。
fig 1.15 3rd Layer output.
第四层: 网络越深入,很难做出任何解读,但网络就是这么做的。
fig 1.15 4th Layer output.
这些可视化让我们对网络如何预测以及每一层的输出发生了什么有了一些基本的了解,但我们只是触及了表面,要了解这些网络在做什么还有很多。这个开发的完整代码可以在我的 github 这里找到。
甘的问题
理论上,gan 的工作听起来不错,似乎应该收敛到全局最*值,但实际上,当生成器 G 和鉴别器 D 都表示为神经网络时,收敛的机会急剧下降,并且在大多数情况下,收敛将停止在鞍点。
在训练甘时,主要观察到以下问题
- 纳什均衡问题:这个问题主要是由于 Gan 最*-最大公式而存在的。在这种情况下,一个函数的两个部分只能在一个点上达到最佳值,在静止状态下,它保持不稳定。下面的例子摘自深度学习书籍,考虑一个函数 F(u,v) = uv,其中我们必须最*化 u 的值和最大化 v 的值,那么当 u=v=0 时,F(u,v)的唯一最优值存在。
- 模式崩溃:在这种情况下,Gan 无法捕获所有类别的数据,只能生成某些类型的模式。通常这种问题不会发生,但如果发生,可能会有问题。
- 梯度递减:当鉴别器或生成器的梯度变得很*时,这种情况很常见,它几乎停止了另一个的学习。这主要发生在鉴别器的情况下,因为它变得更好,因此梯度变得如此之*,以至于生成器无法学习分布。为了避免这个问题,建议在实际训练整个 gan 之前不要训练鉴别器。
稳定 Gan 仍然是深度学习领域的一个活跃的研究领域,许多学术机构和组织都在从事这方面的工作。如果你有兴趣更多地了解与甘退房相关的当前问题,这是的博客文章,作者 Jonathan hui 。
应用程序
虽然 Gan 的建立牢记合成数据,并从本质上制作模型,以了解更多关于构成真实世界数据的表示,但不幸的是,Gan 的大多数当前使用并不友好,许多甚至是灾难性的,其中一个著名的例子是 deep fakes ,其想法是创建人说或做某事的假图像。这些企图会对社会和国家造成严重损害。尽管如此,gan 还是有一些很酷的应用,
- 在网上服装行业,顾客可以在实际购买之前,通过试穿人工生成的虚拟版本来了解服装的外观。
- 生成卡通人物,而不是依赖昂贵的软件。
- 而不是依赖于工作室。一个经典的例子是最近中国国家新闻机构新华社上传了一段人工智能新闻主播而不是真人的报道。虽然他们没有透露他们的模式是什么,但我在这里采取了有根据的猜测。
摘要
生成对抗网络是目前深度学习中最有前途的技术之一。它们是建立在非常简单且感觉最普通的想法上的。我们的,似乎是甘的一个很好的实验,我会在我的博客里写更多的。完整的代码可以在这里找到。
参考
甘的初始论文:的
DCGAN 论文:https://arxiv.org/abs/1511.06434
tensorlayer dcgan 实现:https://github.com/tensorlayer/dcgan
CNNVIS(可视化库):【https://github.com/InFoCusp/tf_cnnvis
open ai 的生成模型博客
甘的问题:https://medium . com/@ Jonathan _ hui/Gan-why-it-so-hard-training-generative-advisory-networks-819 a86b 3750 b
github/carpedm 20/DCGAN-tensor flow
应用课程
Glorot 初始化器:andyl Jones . Tumblr . com/post/110998971763/an-explain-of-Xavier-initial ization
深度学习书籍:www.deeplearningbook.org/
成熟的推荐系统
原文:https://towardsdatascience.com/full-fledged-recommender-system-3bdf52b1eb69?source=collection_archive---------11-----------------------
人工智能应用的快速崛起,处理器和内存成本的降低,使得过去十年推荐系统取得了令人难以置信的进步。鉴于它们在零售业中日益上升的重要性,它们无疑是人工智能中更受欢迎的话题之一。
http://thedatascientist.com/wp-content/uploads/2018/05/recommender_systems.png
然而,创建一个成熟的、可投入生产的推荐系统可能是一项有点复杂的任务,需要非常系统的方法。在这篇文章中,我将一步一步地指导你如何创建一个推荐系统。
如果你参加过 AI 训练营和课程,你可能知道几乎每一个都包括开发一个基于评分/星级从 1 到 5 的推荐系统(是的,你知道那个有标准电影数据集的)。虽然这些都是很好的入门练习,但它们缺乏现实生活中的例子。当开发一个推荐系统时,你很可能也想参与"用户评论",它包含了许多需要包含在模型中的重要特性。对于用户评论,准备好使用 NLP。
在本教程中,我们将使用来自 Yelp 网站的数据来表示一个餐馆推荐问题。数据集包含业务 id、用户 id、评分和评论。基于用户的搜索,任务是推荐三家餐馆。这个例子最好使用 Jupyter 笔记本(你可以在这里找到 j upyter 笔记本和数据)。)
首先,我们需要创建我们的工作流程管道。我们的复杂模型就是从这个管道开始构建的。
管道:
现在,让我们按照管道开始构建我们的模型。
在第一步中,我们接收来自用户的输入,比如“素食比萨饼,便宜,有各种配料。”
第二步,我们对输入进行标记,得到:“蔬菜、披萨、便宜、多样、顶级。”
第三步,将这些令牌与业务功能相匹配。如何才能获得业务特征?这部分完全取决于我们的创造力和特征工程技能。我使用下面描述的特性创建了一个业务特性矩阵。行是业务类别,列是业务特征。如果某个功能在用户评论中,则分配“1”,如果某个功能不在评论中,则分配“0”在这种情况下,计算评论的词频-逆词频(tf-idf ),并手动选择与餐馆企业相关的词。接下来,找到与餐馆类型和菜单相关的单词(从餐馆在线找到)。最后,合并来自 tf-idf 和收集的 internet research & menu lookup 的两组特性。
以下是业务特征矩阵的示例快照:
Business Features Matrix
第四步,过滤出与用户输入相关的商家。我们如何做到这一点?以用户输入的第一个词为例:“蔬菜。”转到业务特征矩阵中的蔬菜一栏,在与蔬菜对应的业务中填入所有的 1。对其他特征(单词)重复相同的过程。
第五步,通过使用受限的波尔兹曼机器(RBM),预测用户是否会喜欢商家提供的选择。这一步将创建一个单行,在列中包含企业。如果用户喜欢这些选择,相应索引中的元素将为 1,否则为 0。
在第六步中,从与用户搜索标准相关的餐馆的搜索结果中取出前三个选择。
在第七步中,考虑另一个场景,用户的搜索是边缘的,RBM 不能返回三个餐馆。尽管对于大型数据集来说,这种情况不太可能发生,但我们仍然应该考虑例外情况。在这种情况下,使用自动编码器来预测每个企业的评级。这将返回一个与 RBM 非常相似的数组,但是这次数组将包括从 1 到 5 的数字(等级),而不是 0 和 1
在第八步中,根据评级,取前三个预测,并将它们与 RBM 预测合并。
在第九步中,如果我们仍然不能为用户找到三家餐馆(此事件再次发生的概率非常低),根据他们的总体评分选择前三家餐馆(请注意,此评分与第八步中的评分不同。不要混淆,自动编码器的预测也返回从 1 到 5 的等级)。
在第十步中,如果我们想向用户推荐新的餐馆,我们将使用协同过滤和基于内容的过滤技术来找到用户会喜欢的餐馆。这是如何工作的?
我们定义了企业和用户的相似度函数。例如,如果用户 A 和 B 的口味相似,推荐系统将向用户 A 推荐用户 B 也喜欢的餐馆,反之亦然。这就是协同过滤的主要思想。
另一方面,如果用户 A 喜欢素食场所,提供素食选择的商家也会彼此相似。将向用户推荐其他素食餐馆。这是基于内容的过滤。请看 jupyter 笔记本如何创建业务和用户相似性函数。
协同过滤和基于内容的过滤技术不能用于该数据集,因为该数据集对于推荐系统来说太*。皮尔逊相关的经验法则是 25。(https://www . research gate . net/post/What _ is _ the _ minimum _ sample _ size _ to _ run _ Pearsons _ R),我们的数据集平均每个商家有 2 个评分。如果您使用较大的数据集,您可能希望使用这些技术,因为它们非常强大!
最后,在步骤十一,向用户推荐排名前三的餐厅。
我希望这篇教程能让你对推荐系统有更好的理解。你可以从这里访问完整的代码和数据。敬请关注“如何部署推荐系统。
谢谢你
面向数据科学家和其他非 Web 开发人员的完整堆栈基础知识,第 2 部分:jQuery、D3、AJAX 和 Flask
原文:https://towardsdatascience.com/full-stack-basics-for-data-scientists-and-other-non-web-developers-part-2-jquery-d3-ajax-and-90f629c6b952?source=collection_archive---------5-----------------------
这是关于基本的全栈 web 开发工具的 2 部分系列的第 2 部分,数据科学家需要这些工具来在 web 上构建基本的交互式可视化。第一部分涵盖了 HTML 和 CSS。在这一部分中,我们将实现我们的承诺,教你如何制作交互式可视化,包括目前最流行的 web 编程语言 JavaScript,两个最流行的库 jQuery 和 D3.js,以及一个优秀的 Python 后端框架 Flask。
Java Script 语言
基本上,HTML 用于在页面上放置元素,CSS 用于设置这些元素的样式,包括将它们放置在页面上相对于彼此的特定位置,Javascript 用于在元素被放置在页面上后对其进行操作。例如,D3.js 只是一堆处理特定 HTML 元素类的代码——即,支持向量图形 (SVG)元素,如矩形和圆形。
Javascript 可以用来以你能想到的所有方式操纵元素。它可以改变元素的样式,或者直接改变样式,或者给元素分配一个不同的 CSS 类。它可以在页面上移动元素。
这些都可以用普通的 Javascript 来完成。然而,我们甚至不会在这里深入讨论如何做到这一点,因为最好的做法是使用目前最流行的 Javascript 库、 jQuery 来完成这样的任务。
jQuery
jQuery 允许您使用$
语法轻松地选择页面上的元素,特别是如果它们有一个指定的“id”或“class”的话。您可以使用与 CSS 类似的语法选择特定类的所有元素,例如,$(".fruit")
选择所有具有类fruit
的元素,$("#banana")
将只选择具有 id 的banana
的元素。
一旦我们做到了这一点,就有了相对直观、简单的语法来操作这些元素。例如,假设我们已经选择了页面上 class fruit
的所有元素;默认情况下,jQuery 会将它们读入一个数组,所以我们可以使用下面的$
和each
语法遍历它们并更改它们的属性:
var bananas = $(".banana");
bananas.each(function() {
$(this).text("My text now says 'banana'");
$(this).addClass("fruit");
}
你明白了。我们将在下面的函数中广泛使用这种模式。
还有另外两个基础工具,每个数据科学家都应该知道,它们被用来构建这个数独应用[D3.JS](https://d3js.org)
和[AJAX](http://adaptivepath.org/ideas/ajax-new-approach-web-applications/)
。
D3。射流研究…
你可能在网上看过非常酷的[D3.JS](https://bl.ocks.org/mbostock)
可视化。我认为这些展示了D3.JS
的力量是很棒的,但是华而不实的演示从根本上来说是为了记忆和让正在发生的事情看起来像魔术,而不是照亮表面下正在发生的事情。事实上,你说“他们是怎么做到的?”是好设计的标志。这是相反的——我想让你确切地知道我是怎么做的!
所以,华丽的 D3 可视化掩盖了 D3 在做什么。 D3 到底在做什么?D3 是一个 Javascript 库。基本上,它选择和操作页面上的 HTML 元素——就是这样。它使用的语法虽然需要时间来适应,但却非常有表现力和简洁。在我看来,初学者纠结 D3 的很大一部分原因。他们的头脑中没有这样的思*模式:
- 一个页面上存在 HTML 元素——即使这些是像
<svg>
或<circle>
这样的元素(通常是 D3 操作的元素),它们仍然是 HTML 元素。 - D3。JS 只是使用 Javascript 来操作这些元素——仅此而已。
那是 D3。我们一会儿会谈到它是如何在数独应用程序中使用的。首先:什么是 AJAX,我们为什么要了解它?
创建交互式、快速动态网页应用的网页开发技术
AJAX 代表异步 Javascript 和 XML。它用于以下在现代 web 上非常常见的用例:当一个页面加载时,它最初只是加载向用户显示“初始”页面所需的所有 HTML 和 CSS 想象一下脸书在你的新闻提要上加载前几个条目。但是,一旦在页面上执行了操作(例如,用户向下滚动或单击按钮),您可能希望用新信息更新页面上的内容。此外,这些信息可能必须来自外部来源,比如服务器。为了做到这一点,Javascript 有一个名为 AJAX 的内置函数,它可以向外部服务器或函数发出请求,获取所需的信息,然后根据这些信息更新页面上的内容,完成所有这些——这是关键部分— ,而无需重新加载页面。AJAX 是你可以向下滚动脸书新闻提要的原因,脸书不必把你带到一个包含“第二页”信息的新网站——它发出一个 AJAX 请求,得到的响应只是被添加到当前页面。
最后,让我们介绍一个更接近核心数据科学工具包的工具:Flask。
瓶
对于这个项目来说,Flask 允许您定义不同的路径,将 Javascript 数据路由到实际操作这些数据的 Python 函数。因此,如果您想拥有一个接受一个数字并将其乘以 2 的 Python 函数,您可以定义一个multiply
路由,在该路由后面有一个 Python 中的multiply_by_two
函数,并让 Javascript 调用该路由(使用 AJAX,我们将会看到)。或者,如果你想有一个函数,例如,接受一个数独板,并从板上消除一个数字作为候选,你也可以这样做。理论上,我们可以用 Javascript 完成所有这些工作。但是,因为 Python 是数据科学的标准语言,也因为它是一种比 Javascript 更简洁的通用语言——以及(真正的原因)Peter Norvig 用 Python 写了他的文章“如何解决每一个数独”——我们将使用 Python 编写数独函数,并使用 Flask 和 AJAX 在两者之间建立接口。
这些工具如何组合在一起
数独应用的代码是这里是。我们现在将介绍各种功能及其作用。
当用户导航到数独应用程序的时,他们正在前往烧瓶应用程序中的路线[/](https://github.com/SethHWeidman/Sudoku_solver/blob/master/main.py#L28)
。
当用户点击“逐步求解”并点击“开始”时,它调用 Python 路由[sudoku_action](https://github.com/SethHWeidman/Sudoku_solver/blob/master/main.py#L44)
。Flask 知道如何将单选按钮的值作为一个request
对象读入数据,该对象的值是一个可以通过request.form
访问的字典。特别是,它可以计算出使用[request.form['type']](https://github.com/SethHWeidman/Sudoku_solver/blob/ac6c36495657ead14dd7fa69c0d26a969b986923/main.py#L56)
选择了哪个单选按钮。如果它检测到“逐步求解”已被选中,它将简单地呈现 HTML 模板[sudoku_action.html](https://github.com/SethHWeidman/Sudoku_solver/blob/master/templates/sudoku_action.html)
。
该模板将立即启动callFlaskUpdateOne
功能:
function callFlaskUpdateOne() {
$.ajax({
url: {{ url_for('update_one')}},
data: extractData(),
type: 'POST',
success: function(response) {
updateClasses(response['values']);
displayMessage(response['message'])
highlightCell(response['peer']);
callFlaskUpdateOne();
},
error: function(error) {
console.log(error);
}
})
};
这个函数使用 jQuery 中特定的ajax
函数。作为参数,该函数需要
- 一个
url
,定义在哪里进行函数调用。 data
,告诉它向那个函数发送什么数据。- 请求的
type
,对于我们的目的来说是一个POST
请求。
所以:启动这个函数首先调用函数update_one
的 Python route。将发送到该函数的数据在extractData()
函数中。这个函数的目标是从实际的网页中获取关于数独板当前状态的所有数据。这样做的方式是我们到目前为止所学概念的直接应用,它利用了这样一个事实,即我们可以将关于数独板的实际数据存储在 Python 和 Javascript 都能理解的结构中。
Python 和 JavaScript 都“理解”的数独棋盘结构就是这个结构
{‘A1’: ‘123456789’, 'A2': '1245', 'A3': 8, ...}
也就是说,它是一本有 81 个词条的词典。这些物品的 81 个键是字母 A-I 和数字 1-9 的 81 种组合。作为值,它们是包含所有尚未从方块中消除的数字的字符串。此外,每个[cell](https://github.com/SethHWeidman/Sudoku_solver/blob/master/templates/sudoku_action.html#L11)
都被赋予了一个职业[sudoku-solving](https://github.com/SethHWeidman/Sudoku_solver/blob/master/templates/sudoku_action.html#L11)
和一个[name](https://github.com/SethHWeidman/Sudoku_solver/blob/master/templates/sudoku_action.html#L11)
属性,对应于前面提到的名字字母组合之一,比如D5
。
因此,在任何给定的时间,我们都可以使用 jQuery 提取具有该类名的所有 HTML 元素,然后简单地遍历每个元素,并将“data”中的元素赋值为将 HTML 元素的“name”作为其键,将 HTML 元素的 text 作为其值。
function extractData() {
output_dict = {};
var numbers = $(".sudoku-solving");
numbers.each(function() {
output_dict[$(this).attr('name')] = $(this).text();
})
return output_dict;
};
注意,在以output_dict
开始的行中,我们使用[]
符号在字典中查找元素,就像我们在 Python 中一样。
然后,我们用ajax
函数中的行和data: extractData()
将数据发送给 Python。这是一个很好的例子,说明了 HTML、CSS、jQuery 和 AJAX 是如何交互的,我们将在这个应用中介绍的其他功能也是根据类似的原理运行的。
一旦 Python 接收到数据,它就以相同的形式将数据发送回 Javascript ,除了 Python Sudoku 代码已经修改了数据,以便从棋盘上的一个单元格中删除一个数字作为候选。它还向 Javascript 发回一条将显示在屏幕上的“消息”,以及一个表示已经去掉数字的单元格的“对等体”:
return jsonify(values=new_values, message=message, peer=peer)
(阅读经典的 Peter Norvig 数独文章并查看[sudoku.py](https://github.com/SethHWeidman/Sudoku_solver/blob/master/python/sudoku.py)
中的[eliminate_one](https://github.com/SethHWeidman/Sudoku_solver/blob/master/python/sudoku.py#L96)
功能)
此响应由ajax
功能:success: function(response)
接收;收到此响应后,将运行几个 JavaScript 函数:
updateClasses(response['values']); displayNewData(response['values']); displayMessage(response['message']) highlightCell(response['peer']);
让我们一个接一个地看一下:
更新类
第一个功能是updateClasses
。这个函数循环遍历每个数独cells
。对于这些单元中的每一个,它查看从 Python 接收回的数据,看它接收到的数据的长度是否为 1,这意味着单元被“求解”。如果是这样,它将移除一个名为[sudoku-not-solved](https://github.com/SethHWeidman/Sudoku_solver/blob/master/static/stylesheets/style.css#L18)
的 CSS 类,该类对单元格中尚未求解的数字进行样式化(例如,定位和调整大*)。移除了该类之后,它添加了一个新的 CSS 类[sudoku_number](https://github.com/SethHWeidman/Sudoku_solver/blob/master/static/stylesheets/style.css#L2)
,其效果是增加该单元格中剩余数字的大*,并使其在父单元格中居中:
function updateClasses(input_sudoku) {
var numbers = $(".sudoku-solving");
numbers.each(function() {
var candidate_numbers = input_sudoku[$(this).attr("name")];
if (candidate_numbers.length == 1) {
$(this).text(candidate_numbers); $(this).addClass("sudoku_number");
$(this).removeClass("sudoku-not-solved");
}
});
};
显示新数据
一旦更新了类,就调用“displayNewData”函数。这个函数简单地遍历页面上的所有元素,并根据 Python 接收到的数据更新它们的文本。
function displayNewData(update_sudoku) {
var numbers = $(".sudoku-solving");
numbers.each(function() {
$(this).text(update_sudoku[$(this).attr('name')]);
});
};
显示消息
现在我们到了涉及 D3 的部分。在将原始的数独放到页面上时,一个<svg>
元素被附加到数独板的底部,宽度为 500,高度为 100。
var message_area = d3.selectAll(".update_message")
.append("svg")
.attr("width", 500)
.attr("height", 100);
完成 AJAX 请求后,JavaScript 会收到一条消息。使用 D3,我们将消息附加到 SVG 对象,并将其放在对象底部附近的y=80
处,并使其透明。然后,我们使用 d3 做一个过渡,将文本向上移动到y=50
并移除透明度,这样它就好像“出现”在屏幕上。然后,我们暂停 500 毫秒,然后我们从屏幕上移除对象,再用半秒钟将文本移回y=80
,并使其再次透明。以下是所有这些的代码:
function displayMessage(message) {
var variable_message = message_area.append("text")
.text(message)
.attr("x", 100)
.attr("y", 80)
.attr("fill", "red")
.attr("opacity", 0)
.transition()
.duration(500)
.attr("y", 50)
.attr("opacity", 1)
.transition()
.duration(500)
.transition()
.duration(500)
.attr("y", 80)
.attr("opacity", 0);
};
该函数突出显示一个特定的单元格,即 Python 代码返回的单元格。首先,它使用 Python 返回的函数名选择单元格。然后,它使用 JavaScript 函数setTimeout
暂停 2 秒钟,然后从单元格中删除这个类。这比我想象的要简单:CSS 中的[highlighted-cell](https://github.com/SethHWeidman/Sudoku_solver/blob/ac6c36495657ead14dd7fa69c0d26a969b986923/static/stylesheets/style.css#L89)
类处理得很好。下面是 Javascript 代码:
function highlightCell(cell) { $('#'.concat(cell)).addClass('highlighted-cell')
setTimeout(function() {
$('#'.concat(cell)).removeClass('highlighted-cell');
}, 2000)
};
把这些放在一起
所以,每三秒钟,我们做以下事情:
- 使用 jQuery 从页面中提取数据。
- 调用 Python 来获取“新数据”以显示在板上。
- 通过更新页面上事物的类别,使页面上任何有一个数字的单元格“变大”。
- 实际显示新数据。
- 在屏幕底部的 SVG 上显示消息。
- 突出显示已更新的单元格。
看到它的实际应用
导航到sethweidman.com/app/sudoku。这个应用程序预装了我在谷歌上找到的第一个“简单数独”。点击“运行数独”来看看它的行动!
结论
即使您自己不是 web 开发人员——我想大多数人都不是——我也希望这个由两部分组成的系列文章能让您了解 web 开发的基本工具是如何工作的,这样您至少可以更自信地参与到团队关于应该构建什么以及应该如何构建的讨论中。对于正在阅读这篇文章的数据科学家来说:我相信,如果你花时间学习这些工具,你会成为更有效的数据科学家,这样你就可以构建可视化,更好地向你的老板、客户甚至同事说明你正在做什么——毕竟,我们在 Metis 教授这些工具是有原因的!
面向数据科学的全栈 web 开发
原文:https://towardsdatascience.com/full-stack-web-dev-for-data-science-28f1f0bc22d1?source=collection_archive---------13-----------------------
一口大*的数据科学第 4 集
如果你像大多数数据科学家一样,你进入这个领域可能是因为你对算法或者数学感兴趣。因此,当意识到成为一名有效的数据科学家实际上意味着知道的远不止如何在 scikit-learn 中建立管道时,可能会有点震惊。
真正的数据科学通常需要了解足够多的 devops 来部署和容器化您的模型,以及足够多的 web 开发来执行抓取、用户跟踪和集成任务,这些任务是许多人日常数据科学工作流的一部分。
但是您如何知道使用哪些库和框架,以及学习什么呢?这是韦斯利本周一直在问的问题,这促使他在导师柳文欢的帮助下,探索每个优秀的数据科学家都应该知道的一些工具:Docker、Flask 和 AWS。
从普查数据中观察到的情况
原文:https://towardsdatascience.com/fun-with-census-data-2643ecd266c4?source=collection_archive---------5-----------------------
有一段时间,我想尝试用 Python 做一些基本的数据分析和可视化。所以,我从 2010 年美国人口普查中得到了一些文件。我处理的数据中有一些关于每个州的有趣事实,从 1910 年开始每十年一次(甚至是那些还没有加入联邦的州!).所以我提出了一些问题,然后开始工作。
注意:我在一个 Jupyter 笔记本上为此工作,你可以在这里查看。
群体大*
问题 1 :是什么让一个州的人口在十年间不断增长?([1]).
一个州今年的规模会影响下一年的增长吗?这次我可以选择任何一种方式。这种积极的关系需要“社会证明”——也许人们想搬到像纽约和加利福*亚这样的大州,那里有很多令人兴奋的事情发生。另一方面,也许人们想搬到更*的州,那里生活更安静,土地更便宜。
我没想到的是,几乎没有任何关系。对于数据集中的每一年,我计算了一年中各州的人口规模(该州的总人口数)与其未来十年人口增长百分比之间的相关性。
两者之间的相关性有时为正,有时为负,相关系数([2])的绝对值从未超过 0.25。很明显,没有任何关系。
即使是 1980 年,也显示了所有测量年份中最强的相关性,其相关性的 p 值为 p≈0.054,足以拒绝在 0.05 的显著性水平上存在相关性的假设。
人口密度
问题 1(修改后):也许我们需要提出一个更严格的问题。如果我们测量人口密度(即每平方英里的人口数量)而不是人口增长率(T10 ),我为正反两种情况提出的因素可能更有意义。如果你住在中央谷,像加利福*亚这样的大州并不令人兴奋——你需要住在大城市之一,那里有大量的人住得很近。即使你住在一个*州,你也需要更少的邻居来确保更便宜的土地和更安静的生活。
那么人口密度呢?一个州每平方英里的人口数量影响其人口增长吗?嗯,有时候。如果我们像以前一样做同样的事情——计算一年内一个州的人口密度与其未来十年人口增长之间的相关性,这就是我们得到的结果。
我们可能会变得更暖和一点。自 1960 年以来,一直存在微弱的负相关性,这意味着致密态比稀疏态增长得更慢。然而有趣的是,相关性最大的十年显示出相反的情况。1930-1940 年的人口增长是怎么回事,这期间的相关性是 r≈0.436,p 值是 p≈0.001?简而言之,沙尘暴。这绝对是一次大规模的州际人口迁移,是美国历史上最重大的事件之一。在沙尘暴期间,超过 350 万人从平原州移民到西部。事实上,捕虾最快的前五个州都来自大平原(达科他州、内布拉斯加州、堪萨斯州和俄克拉荷马州)。([3]).
但这是另一篇文章的内容。
众议院分配
每次人口普查都决定了每个州在美国众议院的席位。这是通过一个叫做分配的过程,实质上是给每个州一个免费的席位,然后使用一个法律规定的公式来分配第 51 个席位,然后是第 52 个,以此类推,直到第 435 个。([4]).
自 1930 年以来,美国人口增加了一倍多,而众议院拥有 435 个席位,因此每 10 年每名代表的人数都在增加。
很明显,随着时间的推移,个人的投票权被稀释了。此外,众所周知议院的代表性不平等,部分原因是不公正的选区划分。这让我不禁要问,众议院中的不平等代表性是否也达到了历史最高水平。
问题 2:现在州与州之间的众议院代表差距有多大?与前十年相比如何?
为了衡量这一点,我用每个代表人数的标准差来衡量每十年的“分布”。一个完全公平的年份的标准差应该是 0。
事实证明,用这种标准衡量,近代历史上的情况比过去好得多。这并不奇怪,因为不公正的选区划分已经存在了几个世纪。但是我不会因此得出任何结论,因为这并不严格,最好是逐区检查差异,而不是以州为单位。
问题 3:就每个代表的人数而言,哪个州最好,哪个州最差?这个问题的答案可能有点令人惊讶。作为一名加利福*亚人,我的第一个猜测是像加利福*亚和纽约这样的大州是最差的代表。但事实证明完全不是这样。人口众多的州正好位于中间。每个代表的最高和最低值的州都相对较*。
结论
这比我想象的要困难得多,但也很有趣。在以后的文章中,我想在更细粒度的层次上研究数据。例如,挖掘国会选区的数据会很有趣,而且可能会得出与我在这里发现的不同的分摊结论。
感谢阅读。请提出任何建议、批评或想法!
脚注
- 在这里,各州的人口增长是以过去十年的百分比来衡量的。因此,如果德克萨斯州在 1930 年有 1000 名居民,在 1940 年有 1500 名居民,那么其 1940 年的人口变化将是 0.5。
- 我用的是皮尔森的 r 。
- 来源:https://en.wikipedia.org/wiki/Dust_Bowl。
- 这些被称为优先级值,它们本身就有一个有趣的故事
有趣的*图像数据集
原文:https://towardsdatascience.com/fun-with-small-image-data-sets-8c83d95d0159?source=collection_archive---------1-----------------------
棒球还是板球?美元还是加元?
假设您想为自己的特定任务构建一个图像分类器。你可能认为你需要收集大量的数据。令人惊讶的是,少量的训练图像足以产生合理的准确率(90–100%)。我将在这里讨论两个案例研究:将图像中的运动分类为棒球或板球,并将钞票图像识别为美元或加拿大元。
我目前正在旧金山参加 Fastai 深度学习课程。到目前为止非常有趣。我尝试的两个案例(板球对棒球和美元对加元)都是基于第一课。该课程使用预先训练的模型 resnet 34(Fastai 的一位同学在此提供了关于 resnet 模型的更多细节)作为起点。使用 fastai 框架非常简单快捷。下面是这个难题主要部分的一个例子——调用学习者数据对象的 fit 方法来训练模型。
第一课是深入研究使用卷积神经网络(CNN)模型来获得非常受欢迎的狗与猫 Kaggle 比赛的最新结果。我强烈建议你在这里看看。课程是以 Jupyter 笔记本的形式,你需要有某种深度学习机器设置(流行的选择是 AWS,Paperspace 实例;或者定制的深度学习装备)。 Crestle 是另一个选项,让您几乎无需任何设置即可开箱运行 Jupyter 笔记本。
板球 vs 棒球
板球和棒球是两项有着相似“特征”的运动,所以我试图区分它们。为了收集用于训练和测试的图像,我分别使用 Google Image 搜索了 Cricket 和 Baseball 这两个术语。我为每项运动下载了 20 张图片,并将它们分成训练( 15 张图片)和测试( 5 张图片)组。我能够用 15 幅训练图像获得 90%的合理准确度(9/10 的测试图像被正确分类)。这里有一些图片被分类的例子。预测分数越接近 0 表示棒球图像。
在玩了这个模型之后,我发现 0.1 的学习率给出了很好的结果。由于训练图像的数量很少,所以我使用试错法来找到一个好的学习率。下面是一张分类错误的图片。
通过多次运行该模型并改变超参数,时不时地得到 100%是可能的。我不确定 100%的准确率是否意味着太多,因为测试图像的数量很少。接下来,我想用大量的有效图片来尝试一下,看看这个模型是如何推广的。
美元对加元
这次我用美钞做了同样的实验,分别用 7 张美元和加拿大元的图像进行训练,用 5 张图像进行测试。这一次,分类器能够轻松达到 100%的准确率。以下是一些示例结果——预测得分越接近 0,意味着美元钞票是加拿大的。
另一种分析分类模型结果的常用方法是使用混淆矩阵,它沿着负 45°对角线显示正确分类的分类变量。在这种情况下,没有美元被错误分类,因此我们看到下面的[5,0][0,5]模式。
结论
许多领域都受到数据收集问题的困扰(生物医学图像、工业设置)。收集足够的图像数据可能很难或者非常昂贵。然而,我们不一定需要 1000 张图像来使用预先训练的模型构建我们自己的定制分类器。这对于原型制作和快速实验来说是个好消息。以下是一些值得进一步探索的方向:
- 自动下载定制图像,以便构建更好、更定制的分类器
- 确定更适合*型数据集的技术/实践。将它们应用于收集数据困难/昂贵的领域
- 尝试一些有趣的例子:船 vs 潜艇?这个人戴没戴眼镜?
PS:这周我开始破解其中的一个问题。本系列的第二部分,阅读 人类是否戴着眼镜 ?
*图像数据集的乐趣(第 2 部分)
原文:https://towardsdatascience.com/fun-with-small-image-data-sets-part-2-54d683ca8c96?source=collection_archive---------4-----------------------
人类是戴眼镜的吗? 第一部看这里。
在这篇博客中,我们将看到如何训练一个分类器来识别人是否戴着眼镜。我们从一个预先训练好的模型和从 Google 图片搜索下载的 260 张训练图片开始。像第一部分中的一样,我们将使用 Fastai 课程的第一课 Jupyter 笔记本的修改版本。
早先玩 10 张图片很有趣,但随着我们进入更严肃的乐趣,我们想处理 100 张甚至 1000 张图片。为此,我使用了 Hardikvasa 的一个漂亮的*脚本。这是一个 Python 程序,可以在谷歌图片上搜索关键字/关键词,并可以选择下载所有图片。
我首先为“戴眼镜”和“不戴眼镜”两种情况下载了 200 个演员(男/女)的图像。我手动扫描图像以删除有缺陷的图像(jpg 文件损坏、错误的图像等),然后将图像分为 135 幅训练图像和 20 幅验证图像——包括“戴眼镜”和“不戴眼镜”的情况。
训练图像数量:135 x 2(带眼镜和不带眼镜)
Sample Training data-set (with glasses)
Sample training data-set (with no glasses)
使用学习率为 0.01 的普通 resnet 模型,我能够获得合理的准确度 77.5 % (31/40 的测试图像被正确分类)
为了提高我们的模型的准确性,我们可以尝试几种技术,如增强、优化最佳学习速率、对不同层使用不同的学习速率以及测试时间增强等。我们将在这里介绍两种技术:
(1)增强是一种将神经网络暴露于我们从现有数据集创建的更多数据的方法。这是通过以不影响图像解释的方式随机改变图像来实现的,例如水平翻转、缩放和旋转。
Applying augmentation transforms to a sample image (flipping, zooming in etc)
增强主要是为了减少过度拟合(这意味着我们的模型正在学习识别训练集中的特定图像,但没有足够好地概括,因此我们在验证集上获得了良好的结果)。使用训练数据集的增强,我能够获得更好的准确性— 87.5 % (35/40 的图像被正确分类)
(2)不同的学习速率和解冻层:我们在这里使用的 resnet 模型由几层组成。通常,早期的层识别基本特征,如线条、渐变等。每一层都逐步建立在前一层的基础上,因此,随着我们进入后面的层,所识别的“特征”的复杂性会增加。因此,我们预计后面的层对于新的数据集需要较少的微调。这里,我们将对不同的层使用不同的学习速率:前几层将处于 1e-4,中间层处于 1e-3,而我们的 FC 层将像以前一样处于 1e-2。如下图所示,使用增强和差异学习率的组合足以给我们的数据集带来 100%的准确率!重复实验几次,我注意到准确率大部分时间都徘徊在 97.5 到 100 %以上。
结论:我们的模型能够准确预测人是否戴眼镜。尽管训练图像数量如此之少,但看到这种深度学习模型的功效令人兴奋。在数据收集阶段,我不知道会发生什么,但我对结果感到惊喜。
深度学习的函数式编程
原文:https://towardsdatascience.com/functional-programming-for-deep-learning-bc7b80e347e9?source=collection_archive---------0-----------------------
在我开始在 ThinkTopic 的最新工作之前,“函数式编程”和“机器学习”的概念完全属于两个不同的世界。一个是随着世界转向简单性、可组合性和不变性以*护复杂的扩展应用程序,编程范式越来越受欢迎;另一个是教电脑自动完成涂鸦和制作音乐的工具。重叠在哪里?
我与这两位合作得越多,就越开始意识到这种重叠既是实际的,也是理论上的。首先,机器学习不是一项独立的努力;它需要迅速融入工业中复杂的缩放应用。其次,机器学习——尤其是深度学习——在设计上是有功能的。给定正确的生态系统,以完全功能化的方式执行深度学习有几个令人信服的理由:
- 深度学习模型是组合的。函数式编程就是组合高阶函数链来操作简单的数据结构。神经网络以同样的方式设计,将一层到下一层的函数变换链接在一起,对输入数据的简单矩阵进行操作。事实上,深度学习的整个过程可以被视为优化一组组合函数,这意味着模型本身具有内在功能。
- 深度学习组件是不可变的。当函数对输入数据进行操作时,数据不会改变,一组新值被输出并传递。此外,当权重被更新时,它们不需要被“变异”——它们可以被新值替换。理论上,对权重的更新可以以任何顺序应用(即,它们不相互依赖),因此不需要跟踪连续的可变状态。
- 函数式编程提供了简单的并行性。最重要的是,纯函数和可组合函数很容易并行化。并行意味着更快的速度和更强的计算能力。函数式编程为我们提供了基本上免费的并发性和并行性,使得在深度学习中使用大型分布式模型变得更加容易。
关于函数式编程和深度学习的结合,有许多理论和观点,从数学论证到实践概述,但有时只有在实践中才能看到它,这才是最有说服力的(也是最有用的)。在 ThinkTopic,我们一直在开发一个叫做 Cortex 的开源机器学习库。在这篇文章的其余部分,我将介绍函数式编程背后的一些想法,并将它们用于异常检测的 Cortex 深度学习模型。
Clojure 基础
在继续我们的 Cortex 教程之前,我想介绍一些 Clojure 的基础知识。Clojure 是一种函数式编程语言,它擅长两件事:并发和数据处理。对我们来说幸运的是,这两件事对机器学习都非常有用。事实上,我们使用 Clojure 进行机器学习的一个主要原因是,每天都要为训练准备数据集(数据操作、处理等)。)很容易超过实现算法的工作,特别是当我们有一个像 Cortex 这样的坚实的学习库时。使用 Clojure 和。edn(而不是 C++和 protobuf),我们可以在 ML 项目上获得杠杆和速度。
要更深入地了解这门语言,请看这里的社区指南。
从基础开始:Clojure 代码由一堆在运行时计算的表达式组成。这些表达式包含在括号中,通常被视为函数调用。
(+ 2 3) ; => 5
(if false 1 0) ; => 0
有 4 种基本的集合数据结构:向量、列表、散列映射和集合。逗号被视为空白,所以通常会被省略。
[1 2 3] ; vector (ordered)
'(1 2 3) ; list (ordered)
{:a 1 :b 2 :c 3} ; hashmap or map (unordered)
#{1 2 3} ; set (unordered, unique values)
列表前面的单引号只是防止它被当作表达式来计算。
Clojure 还附带了很多内置函数来操作这些数据结构。Clojure 的部分优点在于,它被设计为针对很少的数据类型提供很多函数,而不是针对很多数据类型中的每一种都提供一些专门的函数。作为一种 FP 语言,Clojure 支持高阶函数,这意味着函数可以作为参数传递给其他函数。
(count [a b c]) ; => 3(range 5) ; => (0 1 2 3 4)(take 2 (drop 5 (range 10))) ; => (5 6)(:b {:a 1 :b 2 :c 3}) ; use keyword as function => 2(map inc [1 2 3]) ; map and increment => (2 3 4)(filter even? (range 5)) ; filter collection based off predicate => (0 2 4)(reduce + [1 2 3 4]) ; apply + to first two elements, then apply + to that result and the 3rd element, and so forth => 10
当然,我们也可以用 Clojure 写自己的函数,用defn
。Clojure 函数定义遵循形式(defn fn-name [params*] expressions)
,它们总是返回主体中最后一个表达式的值。
(defn add2
[x]
(+ x 2))(add2 5) ; => 7
let
表达式在“let”的词法范围内创建和绑定变量。也就是说,在表达式(let [a 4] (...))
中,变量“a”在内括号内(且仅在内括号内)取值为 4。这些变量被称为“局部变量”
(defn square-and-add
[a b]
(let [a-squared (* a a)
b-squared (* b b)]
(+ a-squared b-squared)))(square-and-add 3 4) ; => 25
最后,有几种方法可以创建匿名函数,既可以赋给局部函数,也可以传递给高阶函数。
(fn [x] (* 5 x)) ; anonymous function#(* 5 %) ; equivalent anonymous function, where the % represents the function's argument(map #(* 5 %) [1 2 3]) ; => (5 10 15)
基本就是这样!现在我们已经学习了一些 Clojure,让我们把乐趣放在函数式编程上,回到一些 ML 上。
皮质
Cortex 是用 Clojure 编写的,是目前规模最大、发展最快的使用函数式编程语言的机器学习库之一。本文的其余部分将介绍如何在 Cortex 中构建最先进的分类模型,以及这样做所需的函数式编程范例和数据扩充技术。
数据预处理
我们的数据集将是由 Kaggle 在这里提供的信用卡欺诈检测数据。事实证明,这个数据集非常不平衡,在 284,807 个案例中,只包含 492 个正面欺诈案例。也就是 0.172%。这稍后会给我们带来问题,但首先让我们看看数据,看看这个模型做得如何。
为了确保个人数据的匿名性,除了“时间”和“数量”之外的所有原始特征都已经被转换成 PCA 成分(其中每个条目代表一个新变量,该变量包含来自原始数据的最相关的信息)。稍微研究一下数据就会发现,第一个“时间”变量相当不具信息性,所以我们在读取数据时会忽略它。下面是我们的初始代码:
皮层神经网络期望以图谱的形式输入数据,这样每个图谱代表一个单独的标记数据点。例如,一个分类数据集可能看起来像[{:data [12 10 38] :label “cat”} {:data [20 39 3] :label “dog“} ... ]
。在我们的 create-dataset 函数中,我们读入 csv 数据文件,将除最后一列之外的所有列指定为“数据”(或特征),并将最后一列指定为标签。在该过程中,我们基于分类类别将标签转变为独热向量(例如[0 1 0 0]
),因为我们的神经网络的最后一个 softmax 层返回类别概率的向量,而不是实际的标签。最后,我们从这两个变量创建一个映射,并将其作为数据集返回。
模型描述
在 Cortex 中创建模型相当简单。首先,我们将定义一个超参数图,供以后在训练中使用。然后,为了定义一个模型,我们简单地将这些层串在一起:
network-description
是神经网络的矢量层。我们的模型包括:
- 输入层
- 具有 ReLU 激活功能的全连接(线性)层
- 辍学者
- 另一个全连接的 ReLU 层
- 通过 softmax 函数传递的大*为 2 的输出层。
在第一层和最后一层,我们都需要指定一个:id
。这个 id 指的是我们的网络应该查看的数据图中的键。(回想一下资料图长得像{:data [...] :label [...]}
)。对于我们的输入层,我们传入:data
id 来告诉模型为它的前向传递获取训练数据。在我们最终的网络层中,我们提供了:label
作为:id
,因此模型可以使用真实标签来计算我们的误差。
培训和评估
这就是变得有点困难的地方。训练函数本身实际上并不复杂——Cortex 为训练提供了一个很好的高级调用,所以我们所要做的就是传入我们的参数(网络、训练和测试数据集等)。).唯一的警告是,系统期望一个有效的“无限”数据集用于训练,但 Cortex 提供了一个函数(infinite-class-balanced-dataset
)来帮助我们转换它。
复杂的部分是f1-test-fn
。事情是这样的:在训练期间,train-n
函数期望被提供一个:test-fn
,该函数评估模型的执行情况,并确定它是否应该被保存为“最佳网络”有一个默认的测试函数评估交叉熵损失,但这个损失值不是那么容易解释,它不太适合我们的不平衡数据集。为了解决这个问题,我们将编写自己的测试函数。
但是我们如何测试这个模型的性能呢?分类任务中的标准度量是准确性,但是在像我们这样不平衡的数据集中,准确性是一个相当无用的度量。因为正面(欺诈性)例子仅占我们数据集的 0.172%,即使是专门预测负面例子的模型也能达到 99.828%的准确率。99.828%是一个相当不错的准确率,但如果亚马逊真的使用了这种模式,我们可能会面临犯罪和信用卡欺诈。
谢天谢地,亚马逊没有使用这种模式,我们也不会。一组更能说明问题的指标是精度、回忆和 F1(或更一般的 F-beta)分数。
Precision and recall visualized. Source: https://en.wikipedia.org/wiki/Precision_and_recall
通俗地说,precision 会问这样一个问题:“在我猜测的所有正面例子中,实际上是正面的占多大比例?”回忆提出了这样一个问题:“在所有实际上是积极的例子中,我正确地猜测为积极的占多大比例?”
F-beta 分数(传统 F1 分数的推广)是精确度和召回率的加权平均值,也是以 0 到 1 的范围来衡量的:
当 beta = 1 时,我们得到2 * (precision * recall) / (precision + recall)
的标准 F1 度量。一般来说,beta 代表召回应该比 precision 重要多少倍。对于我们的欺诈检测模型,我们将使用 F1 分数作为我们的最高分数来跟踪,但我们也将记录精确度和召回分数来检查平衡。这是我们的f1-test-fn
:
该函数在测试集上运行当前网络,计算 F1 分数,并相应地更新/保存网络。它还打印出我们在每个时期的评估指标。如果我们现在在 REPL 中运行(train)
,我们会得到一个高分,它看起来像这样:
Epoch: 30
Precision: 0.2515923566878981
Recall: 0.9186046511627907
F1: 0.395
哈哈。这太糟糕了。
数据扩充
问题来了。还记得我说过我们高度不平衡的数据集会给我们带来问题吗?该模型目前没有足够多的正面例子可供借鉴。当我们在 train 函数中调用experiment-util/infinite-class-balanced-dataset
时,我们实际上创建了每个正面训练实例的数百个副本来平衡数据集。结果,该模型有效地记忆了那些特征值,而不是实际学习类别之间的区别。
解决这个问题的一种方法是通过数据扩充,在这个过程中,我们根据已经有的例子生成额外的人工数据。为了创建真实的正面训练示例,我们将向每个现有正面示例的特征向量添加随机数量的噪声。我们添加的噪声量将取决于正类中每个特征的方差,因此方差大的特征将被大量噪声增强,反之亦然。
以下是我们的数据扩充代码:
augment-train-ds
获取我们的原始训练数据集,计算必须达到 50/50 类别平衡的扩充数量,并通过基于允许的方差(get-scaled-variances
)添加随机噪声向量(add-rand-variance
)将这些扩充应用于我们现有的样本。最后,我们将扩充的示例连接回原始数据集,并返回平衡的数据集。
在训练期间,模型将会看到大量不切实际的正面例子,而测试集仍然只有 0.172%的正面例子。因此,虽然模型可能能够更好地了解两个类之间的差异,但它会在测试过程中过度预测正面的例子。为了解决这个问题,我们可以要求一个更高的确定性阈值来预测测试期间的“肯定”。换句话说,我们可以要求模型至少有 70%的把握,而不是要求模型至少有 50%的把握来对一个例子进行分类。经过一些测试,我发现最佳值设置为 90%。这个代码可以在源代码的vec->label
函数中找到,并在f1-test-fn
的第 31 行被调用。
使用新的、增强的数据集进行训练,我们的高分看起来像这样:
Epoch: 25
Precision: 0.8658536585365854
Recall: 0.8255813953488372
F1: 0.8452380952380953
好多了!
结论
一如既往,该模型仍可改进。以下是后续步骤的一些想法:
- 所有的 PCA 特征都是信息性的吗?查看正例与反例的值在特征中的分布,并删除任何无助于区分这两个类别的特征。
- 有没有其他的神经网络架构,激活函数等。表现更好?
- 有没有不同的数据扩充技术可以表现得更好?
- 与 Keras/Tensorflow/Theano/Caffe 相比,Cortex 中的模型性能如何?
该项目的源代码可以在这里找到。我鼓励你尝试这些后续步骤,测试新的数据集,并探索不同的网络架构(我们在 conv 网上有一个很棒的图像分类示例供参考)。Cortex 正在向它的 1.0 版本推进,所以如果你有任何想法、建议或反馈,一定要让我们知道。黑客快乐!
用 purrr 实现 R 语言中的函数式编程
原文:https://towardsdatascience.com/functional-programming-in-r-with-purrr-469e597d0229?source=collection_archive---------0-----------------------
Want replication without repetition? Use purrr!
当您第一次开始使用 R 时,您可能正在编写简单的代码。
print("Hello world!")5 * 6x <- c(1, 2, 3, 4, 5)
这很好,你正在学习 R 中的字符串、数学和向量!
然后你开始做一些基本的分析。你想看看你是否能找到一些数字的平均值。
employee <- c('John Doe','Peter Gynn','Jolie Hope')
salary <- c(21000, 23400, 26800)
startdate <- as.Date(c('2010-11-1','2008-3-25','2007-3-14'))# form dataframe and take mean of salary column
employ_data <- data.frame(employee, salary, startdate)
mean(employ_data$salary)# output
[1] 23733.33
最终,您有希望接触到tidyverse
,并且您会发现这个“为数据科学设计的 R 包的固执己见的集合”是如何使 R 中的数据分析更容易和更可读的!
mtcars %>%
group_by(cyl) %>%
summarize(mean(mpg))# A tibble: 3 x 2
cyl `mean(mpg)`
<dbl> <dbl>
1 4.00 26.7
2 6.00 19.7
3 8.00 15.1
一切都很顺利!在这一点上,你很可能已经取代了 Excel,还有 SPSS 或其他一些统计软件套件!但是你会遇到一个问题,你需要重复使用一个函数。
您可以使用类似下面的代码来计算一些因变量和一组自变量的单向方差分析:
aov_mpg <- aov(mpg ~ factor(cyl), data = mtcars)
summary(aov_mpg)aov_disp <- aov(disp ~ factor(cyll), data = mtcars)
summary(aov_disp)aov_hp <- aov(hp ~ factor(cyl), data = mrcars)
summry(aov_hpp)aov_wt <- aov(wt ~ factor(cyl), datas = mtcars)
summary(aov_wt)
但是您复制粘贴了 3 次代码,糟糕的是,您犯了一些*的拼写错误,从而引发了一个错误!(以上代码导致错误!)
此外,如果您意识到您实际上想要运行这些 ANOVAs 来计算齿轮数而不是气缸数,会怎么样呢?你必须回去把factor(cyl)
呼叫改成factor(gear)
4x!这不是很有效率,而且你更有可能以错误结束,因为你必须多次输入所有的内容!
再举个例子怎么样。
让我们根据气缸的数量,计算重量和每加仑行驶里程之间的线性关系的 R 平方值。
我在下面写了代码,为来自mtcars
数据集的 4 缸汽车做了这些。这是一个最坏的情况,你知道一些dplyr
代码(dplyr::filter
),但是不习惯使用管道。这很好,你完成了你的目标,但大量的编码!你必须为 6 缸和 8 缸汽车复制这个代码,甚至更多的代码…
# create df for 4 cylinder cars
cyl_4 <- filter(mtcars, cyl == 4)# create a linear model on 4 cyl cars
lm_4 <- lm(mpg ~ wt, data = cyl_4)# get the summ
lm_4_summary <- summary(lm_4)# get the r.squared value
lm_4_r_squared <- lm_4_summary["r.squared"]# check the value
lm_4cyl_r_squared# output
$r.squared
[1] 0.5086326
或者,你可以对管道做同样的事情。输入要少得多,但是对所有 3 个子集都这样做意味着我们必须多次复制粘贴,所以如果你最终想除了 mpg ~ wt 之外还作为 mpg ~ disp 的线性模型这样做,你就必须再复制代码 3 次,再修改 3 次。这可能看起来没什么大不了的,但是一旦你开始按比例增加代码(比如 10+倍或 100+倍,等等),最终将是一件大事。
lm_4cyl_rsquared <- mtcars %>%
filter(cyl == 4) %>%
lm(mpg ~ wt, data = .) %>%
summary() %>%
.$"r.squared"# output
[1] 0.5086326
为了解决这个最*化 重复 并进一步复制的问题,我们可以直接进入purrr
!要阅读更多关于purrr
的内容,Hadley Wickham 推荐了“R for Data Science”中的迭代章节,或者你也可以看看purrr
文档。最后,珍妮·布莱恩在这里有一个很棒的咕噜咕噜教程。你可以单独加载purrr
,但是它也作为tidyverse
库的一部分被加载。
I used to be all meep — meep — PANIC about purrr!!
now I’m all like
map %>%
map %>%
PARTY!
purrr
允许您将 映射 函数到数据。恰当地说,purrr
中的基本功能叫做map()
!map 函数通过对每个元素应用一个函数并返回一个与输入长度相同的向量来转换它们的输入。
map()的基本参数有: .x
—列表或原子向量(逻辑、整数、双精度/数字和字符)
.f
—函数、公式或原子向量
基本上map()
采用一个函数(.f
)并将其应用于数据(.x
)。
回到我们从线性模型中获取 R 平方的例子,我们使用下面的代码和purrr
。
*mtcars %>%
split(.$cyl) %>%
map(~ lm(mpg ~ wt, data = .)) %>%
map(summary) %>%
map_dbl("r.squared")# output
4 6 8
0.5086326 0.4645102 0.4229655*
这将在 5 行代码中根据气缸数量生成我们所有 3 个线性模型的输出!这就是purrr
的妙处,函数的高效缩放!
让我们来分解我们的线性模型 R 平方码。
我们采用 mtcars 数据集,根据气缸数量将其分成数据子集,将 mpg by wt 的线性模型应用于每个数据子集,应用汇总函数,然后得出 r.squared 值。然而,尽管purrr
是可读的,我们还是需要了解一些使用它的习惯。
*mtcars %>%
split(.$cyl) %>%
map(~ lm(mpg ~ wt, data = .)) %>%
map(summary) %>%
map_dbl("r.squared")# output
4 6 8
0.5086326 0.4645102 0.4229655*
对于我们这里的代码,你可能已经注意到我们有一个“.”在代码中放置了两次。这是数据的占位符,我们可以在下面看到。的“.”指示左侧数据,在本例中为mtcars
。我们的 split 调用将mtcars
数据帧分成 3 个数据帧,每个数据帧存储在一个列表中。这可能看起来很奇怪,但是它允许map
循环遍历我们的 3 个数据帧,并在其中的每一个上单独复制lm()
函数。
*# piped
mtcars %>%
split(.$cyl)# base R
split(mtcars, mtcars$cyl)# output
List of 3
$ 4:'data.frame': 11 obs. of 11 variables:
..$ mpg : num [1:11] 22.8 24.4 22.8 32.4 30.4 33.9 21.5 27.3 26...
..$ cyl : num [1:11] 4 4 4 4 4 4 4 4 4 4 ...
..$ disp: num [1:11] 108 146.7 140.8 78.7 75.7 ...
..$ hp : num [1:11] 93 62 95 66 52 65 97 66 91 113 ...
..$ drat: num [1:11] 3.85 3.69 3.92 4.08 4.93 4.22 3.7 4.08 ...
..$ wt : num [1:11] 2.32 3.19 3.15 2.2 1.61 ...
..$ qsec: num [1:11] 18.6 20 22.9 19.5 18.5 ...
..$ vs : num [1:11] 1 1 1 1 1 1 1 1 0 1 ...
..$ am : num [1:11] 1 0 0 1 1 1 0 1 1 1 ...
..$ gear: num [1:11] 4 4 4 4 4 4 3 4 5 5 ...
..$ carb: num [1:11] 1 2 2 1 2 1 1 1 2 2 ...
$ 6:'data.frame': 7 obs. of 11 variables:
..$ mpg : num [1:7] 21 21 21.4 18.1 19.2 17.8 19.7
..$ cyl : num [1:7] 6 6 6 6 6 6 6
..$ disp: num [1:7] 160 160 258 225 168 ...
..$ hp : num [1:7] 110 110 110 105 123 123 175
..$ drat: num [1:7] 3.9 3.9 3.08 2.76 3.92 3.92 3.62
..$ wt : num [1:7] 2.62 2.88 3.21 3.46 3.44 ...
..$ qsec: num [1:7] 16.5 17 19.4 20.2 18.3 ...
..$ vs : num [1:7] 0 0 1 1 1 1 0
..$ am : num [1:7] 1 1 0 0 0 0 1
..$ gear: num [1:7] 4 4 3 3 4 4 5
..$ carb: num [1:7] 4 4 1 1 4 4 6
$ 8:'data.frame': 14 obs. of 11 variables:
..$ mpg : num [1:14] 18.7 14.3 16.4 17.3 15.2 10.4 10.4 14.7...
..$ cyl : num [1:14] 8 8 8 8 8 8 8 8 8 8 ...
..$ disp: num [1:14] 360 360 276 276 276 ...
..$ hp : num [1:14] 175 245 180 180 180 205 215 230 150 150 ...
..$ drat: num [1:14] 3.15 3.21 3.07 3.07 3.07 2.93 3 3.23 2.76...
..$ wt : num [1:14] 3.44 3.57 4.07 3.73 3.78 ...
..$ qsec: num [1:14] 17 15.8 17.4 17.6 18 ...
..$ vs : num [1:14] 0 0 0 0 0 0 0 0 0 0 ...
..$ am : num [1:14] 0 0 0 0 0 0 0 0 0 0 ...
..$ gear: num [1:14] 3 3 3 3 3 3 3 3 3 3 ...
..$ carb: num [1:14] 2 4 3 3 3 4 4 4 2 2 ...*
类似地,这个“.”in 或 first map 调用是数据的占位符,但在这种情况下,它将循环遍历由前面的管道生成的 3 个数据帧的列表。你可以看到我们得到了一个 3 个lm()
输出的列表,我们需要map
一个对每个输出的总结调用来访问 R 平方。
*mtcars %>%
split(.$cyl) %>%
map(~ lm(mpg ~ wt, data = .))# output
$`4`Call:
lm(formula = mpg ~ wt, data = .)Coefficients:
(Intercept) wt
39.571 -5.647$`6`Call:
lm(formula = mpg ~ wt, data = .)Coefficients:
(Intercept) wt
28.41 -2.78$`8`Call:
lm(formula = mpg ~ wt, data = .)Coefficients:
(Intercept) wt
23.868 -2.192*
接下来,我们将总结函数映射到每个列表项,以获得具有 R 平方值的更清晰的输出。我们现在有了统计输出的其余部分,包括 p 值和 R 平方。
*mtcars %>%
split(.$cyl) %>%
map(~ lm(mpg ~ wt, data = .)) %>%
map(summary)# output
$`4`Call:
lm(formula = mpg ~ wt, data = .)Residuals:
Min 1Q Median 3Q Max
-4.1513 -1.9795 -0.6272 1.9299 5.2523Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 39.571 4.347 9.104 7.77e-06 ***
wt -5.647 1.850 -3.052 0.0137 *
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1Residual standard error: 3.332 on 9 degrees of freedom
Multiple R-squared: 0.5086, Adjusted R-squared: 0.454
F-statistic: 9.316 on 1 and 9 DF, p-value: 0.01374$`6`Call:
lm(formula = mpg ~ wt, data = .)Residuals:
Mazda RX4 Mazda RX4 Wag Hornet 4 Drive Valiant Merc 280
-0.1250 0.5840 1.9292 -0.6897 0.3547
Merc 280C Ferrari Dino
-1.0453 -1.0080Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 28.409 4.184 6.789 0.00105 **
wt -2.780 1.335 -2.083 0.09176 .
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1Residual standard error: 1.165 on 5 degrees of freedom
Multiple R-squared: 0.4645, Adjusted R-squared: 0.3574
F-statistic: 4.337 on 1 and 5 DF, p-value: 0.09176$`8`Call:
lm(formula = mpg ~ wt, data = .)Residuals:
Min 1Q Median 3Q Max
-2.1491 -1.4664 -0.8458 1.5711 3.7619Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 23.8680 3.0055 7.942 4.05e-06 ***
wt -2.1924 0.7392 -2.966 0.0118 *
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1Residual standard error: 2.024 on 12 degrees of freedom
Multiple R-squared: 0.423, Adjusted R-squared: 0.3749
F-statistic: 8.796 on 1 and 12 DF, p-value: 0.01179*
我们上一张地图有点不同。你可以看到我们这次使用了map_dbl
。这表明我们希望我们的输出是 dbl 或数字结果。我们得到了很好的命名数字!
*mtcars %>%
split(.$cyl) %>%
map(~ lm(mpg ~ wt, data = .)) %>%
map(summary) %>%
map_dbl("r.squared")# output
4 6 8
0.5086326 0.4645102 0.4229655*
如果我们没有指明map_dbl
,而是使用了map
,我们将得到一个相同结果的列表。
*mtcars %>%
split(.$cyl) %>%
map(~ lm(mpg ~ wt, data = .)) %>%
map(summary) %>%
map("r.squared")# output
$`4`
[1] 0.5086326$`6`
[1] 0.4645102$`8`
[1] 0.4229655*
您也可以使用map_dfr
,它将输出绑定到数据帧的行中。
*mtcars %>%
split(.$cyl) %>%
map(~ lm(mpg ~ wt, data = .)) %>%
map(summary) %>%
map_dfr("r.squared")# output
# A tibble: 1 x 3
`4` `6` `8`
<dbl> <dbl> <dbl>
1 0.509 0.465 0.423*
purrr
和purrr
中的其他函数有无限的应用,这极大地增强了 r 中函数式编程的能力。我希望本指南能激励您将purrr
添加到工具箱中,并探索这个有用的tidyverse
包!
作为purrr
更多应用的一个简短的引子,我将留给你这个例子。我在开始时提到了计算多个变量的 ANOVAs。自己分解一下这个例子,看看大家怎么看!(您可以将这段代码复制粘贴到 R 中,但是需要先加载tidyverse
和broom
包)。
*mtcars %>%
mutate(cyl = factor(cyl),
am = factor(am)) %>%
select(mpg, disp, hp) %>%
map(~ aov(.x ~ cyl * am, data = mtcars)) %>%
map_dfr(~ broom::tidy(.), .id = 'source') %>%
mutate(p.value = round(p.value, 5))*
最后,我要感谢几个#r4ds slack 社区成员,他们帮助我理解了 purrr: Frank Farach,Michael Kuehn 和 Kent Johnson。
如果你有兴趣加入这个由杰西·梅根领导的社区,在这里查看她的帖子,愿原力与你同在!
数据科学的功能
原文:https://towardsdatascience.com/functions-of-data-science-4afd5341a659?source=collection_archive---------10-----------------------
Data Visualization, a key skill of the For Product function
数据科学是一个宽泛的术语,包括组织内许多不同职能的工作角色。这篇文章介绍了一种在数据科学领域对不同工作职能进行分类的方法,并确定了这些专业的有用技能。
以下是我在职业生涯中体验到的数据科学的四大关键职能,这些职能通常与职位联系在一起:
- 对于产品(推理科学家)
- 作为产品(应用科学家)
- 运营部(系统科学家)
- As 操作(ML 工程师)
我用两个*度来划分工作职能:
- "For" vs "As": 数据科学家是支持正在构建某种东西(For)的团队,还是支持他们自己构建某种东西(As)?
- 产品与运营:数据科学家构建的是面向客户的东西(产品)还是对业务运营至关重要的后端系统(运营)?
第一个*度的关键区别在于数据科学团队是否在构建数据产品。如果一个数据科学团队拥有系统的一部分,那么这个团队就负责实现发现。如果团队与另一个执行调查结果实施的团队合作,那么数据科学就是一个支持角色。第二个*度区分数据科学团队的成果是否对客户直接可见。例如,网飞推荐系统是面向客户的,因为它影响向用户显示的标题和作品,而欺诈检测系统可能对运行在线游戏至关重要,但对用户不可见。
我自己曾在许多不同的职能部门工作过:在 Twitch,我被安插在移动产品团队,负责产品分析(针对产品),在 Twitch,我负责应用科学,专注于构建面向客户的数据产品(作为产品),在 Twitch,我监督一名科学家,专注于预测平台的运营指标,如页面加载时间(针对运营)。我还没有在 As 运营部门工作过,但我所知道的最常见的例子是 Quantcast 和 Pinterest 等公司使用的广告竞价系统。
产品的数据科学 这是我在游戏行业经历过的最常见的数据科学角色类别。在 Daybreak Games、EA 和 Twitch,许多数据科学家的角色侧重于分析,为产品经理或游戏制作人提供支持。许多数据科学团队渴望构建数据产品,但是没有工具和基础设施来拥有自己的数据产品。我也见过这种角色被称为推理数据科学家或决策科学家。
该角色的主要职责之一是为团队提供见解,然后用于改进产品和公司路线图。这可以包括围绕战略的高层次分析,或者关于特定产品性能的更多战术分析。出色地履行这一职责通常需要以下技能:
- 探索性分析:这涉及到使用脚本和 SQL 来探索和总结数据集,并回答以下问题:我们能否确定哪些行为对于监控产品健康状况很重要?我们能否确定哪些因素与此行为相关?
- 实验:如果产品团队做出改变,你如何评估影响?这可能包括 A/B 测试和分阶段推出。
- 影响:如果数据科学团队不断地处理关于数据的特别问题,而不是拥有一些自主性来寻找有用的见解,那么这个角色就更像是一个商业智能功能。担任这一角色的成功数据科学家能够获得团队的认可,将他们的发现应用到产品中。
拥有强大的书面和口头交流能力对于所有这些数据科学功能也很重要。这对产品支持功能特别有用,可以影响其他团队。
数据科学作为产品 这是另一个专注于改进产品的数据科学角色,但与之前职能的区别在于,其中一个关键产出是支持面向客户产品的数据产品。在 Twitch,应用科学团队符合这一功能,并使用机器学习来构建产品,如用于军团联盟的冠军探测器。
该职能的职位可能包括应用科学家或机器学习工程师。这也是一个经常向工程经理而不是分析或科学经理汇报的角色。以下是一些对这类角色有用的技能:
- 机器学习:虽然预测建模是所有数据科学功能的先决条件,但这一角色需要更多处理不同类型数据源(包括文本、图像和视频)的实践经验。还需要了解如何扩展这些预测模型。
- 原型制作:在分配大部分资源来构建系统之前,能够构建数据产品的 MVP 是很有用的。
- 软件工程:构建这种规模的数据产品需要能够部署在分布式环境中的系统编程语言的知识。数据产品的代码需要健壮且可*护。
数据产品通常是实时系统,该职能部门的数据科学家需要能够扩展预测模型的知识。
运营数据科学 我在 Twitch 的时候,这个功能还处于起步阶段。该职位的主要职责是了解不同的因素如何影响我们产品的运营指标,如页面加载时间。我们将这个角色称为系统科学家,因为它需要对我们的基础设施和可能影响各种系统度量的各种因素建立深刻的理解。
这一特殊角色的重点是系统性能下降的根本原因分析,但该职能更广泛的重点是建立模型,以更好地了解各种内部和外部因素如何影响系统。它需要以下技能:
- 系统基础设施:理解不同的因素如何影响运营指标需要对用于构建产品的系统和基础设施有深入的了解。例如,跟踪页面负载需要了解 cdn、缓存和 API 调用依赖关系。
- 预测:为了检测指标中的异常,有必要建立基线和预期行为。预测可以用来模拟影响系统行为的因素。
- 警报:这个角色可能还负责确定何时向其他团队发出异常系统行为的警报。重要的是能够设置何时提醒团队的阈值,而不会有太多的误报。
系统科学是一个较新的工作职能,比其他数据科学角色需要更多的基础设施知识。
数据科学作为运营 这是一个数据科学角色,通常是工程团队的一部分,目标是构建运营业务所需的数据产品,而不是面向客户的产品。构建自动广告竞价系统是这种角色的一个例子,构建欺诈检测系统是另一个例子。与数据科学产品组的主要区别在于,这些系统往往更加自动化。例如,由于数据的规模和实时要求,广告竞价系统可以使用相同的系统进行培训和生产,而面向客户的数据产品通常可以在较*的规模上进行原型化和迭代。
以下是一些对此功能有用的技巧:
- 分布式系统:该功能需要构建分布式系统的知识,这可能包括 Spark 或其他用于扩展流程的云技术。在意外收获,我们使用云数据流。
- 在线学习:这些系统的实时要求通常意味着批量学习过程是不合适的,相反,需要利用在线方法来更新模型。
- DevOps: 构建运行业务功能的数据产品意味着*护这些系统,而这是 DevOps 责任最大的数据科学角色。
这是一个我没有经验的功能,但我认为它是数据科学中最有价值的角色之一。
结论 数据科学术语可能执行各种不同的功能。为团队制定一个清晰的章程是很重要的,这样你就能够恰当地雇佣员工并支持组织的需求。这些职能需要不同的技能组合,数据科学家的首选职能可能会在职业生涯中发生变化。
本·韦伯是意外收获数据的首席数据科学家,我们的任务是确定世界上每个家庭的净资产。我们目前正在招聘产品数据科学和产品数据科学职能部门的角色。
R 和 rvest 函数:外行指南
原文:https://towardsdatascience.com/functions-with-r-and-rvest-a-laymens-guide-acda42325a77?source=collection_archive---------2-----------------------
如果有一个主题在使用 R 后很难理解,那就是函数。从编写函数到学习如何调试函数,一切都没有明确的指导。此外,已经出现了一些旨在帮助完成这项任务的工具,但是在解决您的问题时,似乎很难理解如何利用这些工具。这篇博客旨在让您了解 R 中有哪些函数,如何在任务中使用它们,并在 RStudio 中轻松调试它们,以诊断到底发生了什么。
最近,我有机会去苹果酒节,学习和尝试新的苹果酒。我不是苹果酒的最大粉丝,所以很自然地,我选择尝试几乎所有可用的啤酒,并想比较我品尝的味道。如果有人问我的味蕾,我会说我喜欢尚迪和*麦啤酒。我尝过的啤酒都不太合我的口味,但不知何故,味道比我预期的要好。如果能有一种方法来比较这两种啤酒,那肯定会很有帮助。我一直想知道为什么我喜欢美国淡啤酒,甚至是一桶啤酒。使用 rvest,我们可以很容易地从 RateBeer 中获取每种啤酒的必要数据,以帮助相互比较,确定它们可能有哪些相似之处。
但是首先…一些我们需要处理的事情
在我们开始之前,需要建立一些基本规则,这样你就可以让自己走上正确的轨道,完成手头的任务。一开始,通过编程与网络互动很容易让人觉得是未知的领域,就像喝第一杯啤酒一样:我在哪里,我怎么会在这里?但是,不要害怕,因为这个博客将为你提供资源,使你不会迷失在这个深渊中。
工具时间:
为了从这篇博客中获得最大的价值,你需要以下工具:
- RStudio
- Visual Studio 代码
- 基特克拉肯
你可能会问,我们为什么需要这些?用正确的工具武装自己有时是成功的一半:如果你没有解决问题的必要工具,很难弄清楚如何理解手头的问题。除了这些工具,我还强烈建议你考虑使用沙盒环境,使用 Docker 或 RStudio Cloud,因为 R 在不同操作系统上的编码存在一些问题。如果您想了解更多关于如何为 R 创建自己的自定义沙盒环境的信息,您可以查看这个博客了解更多信息,或者查看 RStudio Cloud。
https://medium . com/@ peterjgensler/creating-sandbox-environments-for-r-with-docker-def 54e 3491 a 3
https://rstudio.cloud/
概括地说,有两种获取 web 数据的通用方法:
- API 的——API 被称为应用编程接口
- 网络抓取——更像是一种暴力的方法
好吧,那么 API 到底是什么呢?我应该用它吗?
API 是一个信使,它接收请求,然后向您返回响应
API 已经设置好了,因此您可以轻松地与服务进行交互。假设我想要获取明*阿波利斯的火灾数据。
[## 明*阿波利斯确认 2013 年火灾-数据集
有关此数据的问题,请联系
数据世界](https://data.world/minneapolismn/8baeeaebfd9d489d9ee6c9ae0fed3988-0)
如果我愿意,我可以通过 data.world 的 API 轻松获取这些数据:
[## API 文档
为所有 OAS (Swagger)和 RAML 规范托管 API 文档。由 Stoplight.io 提供动力。文档、模拟、测试…
apidocs.data.world](https://apidocs.data.world/v0/data-world-for-developers)
另一方面,网络抓取是一种更加暴力的获取网络数据的方式。并不是所有的网站都有 API 可以使用,这意味着可能需要搜索才能找到。我们如何检查我们是否能抓取一个网页?简单,检查 robots.txt 文件。有关 robots.txt 文件用途的更多信息,请观看此视频:
对于我们的例子,我们使用的是网站 RateBeer,所以让我们看看他们的文件,看看是否有限制:
【https://www.ratebeer.com/robots.txt
User-agent: Mediapartners-Google
Disallow:
User-agent: *
Allow: /
查看 RateBeer 的 robots.txt 文件,我们可以看到它们允许抓取,因为它们不允许任何东西,所以我们可以继续。
吃个三明治,喝杯咖啡,然后去看下面列出的 RStudio 的网络研讨会。RStudio 有两个很棒的网络研讨会,分别涉及 API 和深度网络搜集,我们希望第 2 部分:
[## 从 web 部件 2 中提取数据
从 web 中提取数据第 2 部分下载资料描述互联网是一个数据宝库,如果你…
www.rstudio.com](https://www.rstudio.com/resources/webinars/extracting-data-from-the-web-part-2/)
网上研讨会的幻灯片可在此处找到:
https://github . com/r studio/webinars/blob/master/32-Web-Scraping/02-Web-Scraping . pdf
在我看了上面列出的网上研讨会后,我对所有这些话题都很迷茫,这是理所当然的。学习用于设计网站的网络技术不是一件容易的事情,在刚开始的时候会非常困难。如果您想了解更多资源,我强烈建议您观看《用户 2016》中的这些非常相似的幻灯片,并做好准备:
https://github . com/ropensci/user 2016-tutorial/blob/master/03-scraping-data-without-an-API . pdf
大多数用 R 开发的 web 抓取包都是为了抓取网页的 HTML 或 CSS 部分,而不是呈现在浏览器中的 Javascript 内容。Javascript 编写起来要复杂得多,可以用 RSelenium 完成,但不适合胆*的人:
[## 鲁本斯西/硒元素
RSelenium——Selenium 远程 WebDriver 的 R 客户端
github.com](https://github.com/ropensci/RSelenium)
理解和奠定基础
为了得到我们的数据,我们首先需要设置一些函数来获取每种啤酒的变量。现在,为了简单起见,我只挑选了三瓶啤酒,但是我希望这个例子能够说明一个函数在投入使用时是多么强大。让我们来看看:
为了比较每种啤酒,我们首先需要找到一种方法来获得每种啤酒的属性。Ratebeer 为我们提供了每种啤酒的基本统计数据:
Pollyanna Eleanor Beer Descriptive statistics
正如您在上面看到的,我们对每种啤酒的描述性统计很感兴趣,但是我们如何找到与该元素的确切联系呢?由于这些网页上没有关于每种啤酒的 JavaScript,我们可以简单地利用工具找到我们感兴趣的元素的 CSS 或 Xpath。最简单的方法是
现在,为了从网站中提取数据,我们首先需要下载网页,然后尝试通过 CSS 标签或 xpath 选择我们感兴趣的元素。毫无疑问,这可能是一个痛苦的过程,原因有二:
- CSS 标签应该(但没有)与 rvest 一起工作,因为 selectr 有一些问题(这促使找到 CSS 标签):https://github . com/sjp/selectr/issues/7 # issue comment-344230855
- 或者,您不知道所选择的路径是否是您想要的元素的正确路径,这种情况比我愿意承认的更常见
现在,起初,这似乎是一个几乎不可能的任务,但不用担心。我们仍然可以使用 xpath 来选择我们感兴趣的内容,以便进一步使用。
有两个工具非常有助于为您希望提取的元素找到正确的 XPath:Selectorgadget 和 chrome developer tools。
选择器*工具
Selectorgadget 是一个点击式 CSS 选择器,专门用于 Chrome。只需安装 chrome 扩展,然后点击你感兴趣的元素就可以了。这将选择与该对象相关的所有元素。接下来,选择你不想要的黄色的东西。这就对了。
Using SelectorGadget
有关 SelectorGadget 的更多信息,请访问:
[## SelectorGadget:指向并单击 CSS 选择器
SelectorGadget 是一个开源工具,使复杂网站上 CSS 选择器的生成和发现变得轻而易举…
selectorgadget.com](http://selectorgadget.com/)
如果您需要额外的示例,也可以在这里找到详细的演练:
[## 选择 orgadget
Selectorgadget 是一个 javascript bookmarklet,它允许你交互式地计算出你需要什么样的 css 选择器…
cran.r-project.org](https://cran.r-project.org/web/packages/rvest/vignettes/selectorgadget.html)
Chrome 开发者工具
如果从 SelectorGadget 获取正确的 xpath 有问题,也可以尝试使用 Chrome 开发者工具,它们对用户非常友好。
只需点击视图-开发者工具,这将加载开发者工具。
接下来,点击鼠标*按钮与网页互动。这将使您的光标能够显示是什么代码在驱动页面上的每个元素。
在下面的截图中,我们可以看到我们用鼠标选择的内容,以及驱动该特定元素的相应代码。
Chrome Developer Tools selecting element on page
点击上面的蓝色区域,如上所示。在本例中,我们对 stats 容器感兴趣,因为它包含了我们想要比较的指标。这将把你锁定在那个元素上,这样你的光标就不会试图为其他元素选择 HTML 或 CSS。现在右键单击 html 代码中突出显示的区域(红框),然后选择 copy->Copy XPath。这将允许您找到特定元素在页面上的最具体路径。
完美!现在我们有了元素的 xpath,我们可以开始编写从 xpath 中提取数据的函数了。
设置功能
让我们总结一下到目前为止我们所取得的成就。至此,我们首先确定了我们到底想要完成什么:收集每种啤酒的基本统计数据。然后我们找到了必要的 xpath,它标识了网页上我们感兴趣的元素。使用 rvest,我们可以编写一个脚本,允许我们
在 RStudio 的幻灯片(演讲开始时的链接)中概述了,在我们的功能中,对于给定的网页,我们需要完成三个“核心活动”。仔细想想,它们是有道理的:
- 拉下网页
- 确定我们想要的元素
- 提取并拉出元素
- 整理元素使其可用
rvest 包中有三个函数允许我们轻松地执行这些步骤。然而,由于我们想要在多个 URL 上执行这些步骤,我们可以像这样设置我们的函数:
library(magrittr) #for pipes
library(dplyr) #for pull function
library(rvest) #get html nodes
library(xml2) #pull html data
library(selectr) #for xpath element
library(tibble)
library(purrr) #for map functions
library(datapasta) #for recreating tibble's with ease#Sample Data
sample_data <- tibble::tibble(
name = c("pollyanna-eleanor-with-vanilla-beans","brickstone-apa","penrose-taproom-ipa","revolution-rev-pils"),
link = c("[https://www.ratebeer.com/beer/pollyanna-eleanor-with-vanilla-beans/390639/](https://www.ratebeer.com/beer/pollyanna-eleanor-with-vanilla-beans/390639/)",
"[https://www.ratebeer.com/beer/brickstone-apa/99472/](https://www.ratebeer.com/beer/brickstone-apa/99472/)",
"[https://www.ratebeer.com/beer/penrose-taproom-ipa/361258/](https://www.ratebeer.com/beer/penrose-taproom-ipa/361258/)",
"[https://www.ratebeer.com/beer/revolution-rev-pils/360716/](https://www.ratebeer.com/beer/revolution-rev-pils/360716/)"
)
)#the function:get_beer_stats1 <- function(x){
read_html(x) %>%
html_nodes(xpath = '//*[[@id](http://twitter.com/id)="container"]/div[2]/div[2]/div[2]') %>%
html_text()
}
我们还可以编写函数,使其在值发生变化时更加明确,从而更容易在 RStudio 中单步调试:
get_beer_stats2 <- function(x){
url <- read_html(x)
html_doc <- html_nodes(url, xpath = '//*[[@id](http://twitter.com/id)="container"]/div[2]/div[2]/div[2]')
stats <- html_text(html_doc)
return(stats)
}
等等,我想我们应该确保每一个动作都被精确地记录下来,这样他们的电脑就能理解了?难道我们不需要某种 for 循环,在每个 URL 之后作为一个计数器来增加吗?为什么我们不使用 dplyr::pull 命令将向量从数据帧中直接取出来进行迭代呢?
使用 purrr 的一个问题是理解如何以正确的心态思考你所面临的问题。思考这个问题,我们可以从以下几个角度着手:
- 我有一个 URL 的数据框架,我想迭代每一行(或 URL),并为每个 URL 执行一组给定的操作
- 我有一个包含一列 URL 的数据框架,对于每个 URL,我想对每个 URL 进行操作
- 将数据帧中的 URL 列视为一个向量,我希望对向量中的每个元素进行操作
你看,purr 的主要工作函数 map,被设计成迭代包含一堆元素的对象,然后允许你作为用户专注于写一个做一些动作的函数。在 R 中,大多数时候这些对象要么是列表、列表列,要么只是一个向量。这样,它允许您拥有这样的工作流:
- 确定您想对给定的元素做什么
- 把“收据”变成一个函数
- 在对象上应用带有 purr 的配方(如有必要,创建一个新列来存储结果)
好了,现在让我们将刚刚创建的函数应用于我们的数据,看看它是否有效:
sample_data_rev <- sample_data %>%
mutate(., beer_stats = map_chr(.x = link, .f = get_beer_stats1))
在我们继续之前,让我们分析一下到底发生了什么。首先,我们用管道连接 dataframe,并说我们想用 mutate 添加一个新列。接下来,我们使用 map_chr(或 vector)创建一个定义为字符列的新列,然后应用我们的自定义函数。
在 RStudio 中获取数据和调试
既然我们的核心函数已经定义好了,如果我们想看看值是如何变化的,我们可以使用 RStudio 遍历我们的函数。只需转到以下位置即可启用调试模式:
调试->出错->错误检查器
接下来,简单地用 debug 包装您的函数,如下所示:
debug(
get_beer_stats1 <- function(x){
read_html(x) %>%
html_nodes(xpath = '//*[[@id](http://twitter.com/id)="container"]/div[2]/div[2]/div[2]') %>%
html_text()
}
)
当运行调用函数的代码时,将进入调试模式,以便查看代码中的值是如何变化的:
sample_data_rev <- sample_data %>%
mutate(., beer_stats = map_chr(.x = link, .f = get_beer_stats1))
扩展我们的例子,让我们说,我们有可能导致一些打嗝的网址。我们如何创建一个函数来轻松处理这些错误呢?
purr 为我们提供了错误处理函数,来包装我们的函数,以优雅地处理错误。我们可以使用 possibly 函数添加错误处理:
sample_data_rev <- sample_data %>%
mutate(., beer_stats = map_chr(.x = link, possibly(get_beer_stats1, otherwise= "NULL")))
可能非常类似于 try-catch,它允许我们用不同的错误处理函数来包装我们创建的函数。乍一看,这可能有点令人困惑,但是一旦您正确地设置了它,这是有意义的。
编码和 R:进入深渊
在我们继续前进之前,值得注意的是,下面是我称之为“深渊”的地方,或者叫魔多。注意,这不适合胆*的人,所以如果你觉得你已经准备好了,那就继续吧。否则,去做个三明治,*睡一会儿。
Mordor, aka how Encoding feels in R
对我来说,用 R 编码让我想起了《指环王》中的魔多。这就像一些永无止境的坑,几乎濒临死亡。不过不用担心,你会得到很好的照顾。我们走吧。
我们有了数据,应该都准备好清理了,对吧?没有。为什么会这样呢?前面我们提到我们的工作流程由以下步骤组成:
- 拉下网页
- 确定我们想要的元素
- 提取并拉出元素
- 整理元素使其可用
这种工作流程的部分问题是,它假设一旦我们从网页中取出数据,它就应该“准备好,马上下船”,不幸的是,来自 web 的数据并非如此。你看,来自网络的数据必须被编码,发现甚至检测编码问题可能是一个真正的麻烦,因为你可能不会发现,直到你的分析过程的更下游,像我一样。
在我们进入下一步之前,我鼓励你先阅读下面的文章。这将有助于为理解我们的文本数据到底出了什么问题以及帮助检测问题根源的策略打下基础:
[## 面向初学者的字符编码
什么是字符编码,我为什么要关心?
www.w3.org](https://www.w3.org/International/questions/qa-what-is-encoding) [## r 代表数据科学
这本书将教你如何用 R 做数据科学:你将学习如何把你的数据放入 R,把它放入最…
r4ds.had.co.nz](http://r4ds.had.co.nz/data-import.html#readr-strings)
重复一下,我们的计算机(或机器,真的)以字节为单位存储数据。然后,这些字节被编码成不同的语言环境,如 UTF-8 或 ANSI。根据您如何设置您的平台(或机器)的本机编码,R 可能会给您带来很多麻烦。根据经验,无论您的平台的原生编码是什么,只要有可能,尝试与 UTF-8 接口总是最好的,因为它导致的困难最少。找出编码问题的根源可能是一项挑战,因此以下工具将有所帮助:
- textclean 包—用于检测编码文本的问题
- rvest —如果不确定,适合尝试猜测编码
- data pasta——有利于轻松地重新创建 tibble
- stringi- brute force 查看 unicode 是否与我们正在查看的内容匹配,并清除它
- base::charToRaw —查看字符串的原始字节
- 工具::showNonASCII 和 iconv 显示非 ASCII 字符
- Unicode 检查员-https://apps.timwhitlock.info/unicode/inspect
- Unicode 表-【http://www.utf8-chartable.de/
我们的一般工作流程如下:
- 检测或识别文本中的问题
- 尝试修复编码
在我们继续之前,我强烈建议您确保可以通过 Tools-Global Options-Code 查看 RStudio 中的空白,并显示空白字符。
Configuring whitespace characters in RStudio
此外,进入 Visual Studio 代码,并通过查看-切换渲染空白进行同样的操作。
Toggle Render Whitespace in Visual Studio Code
让我们举一*段代码作为例子。假设你得到这个数据:
bad_data <- tibble::tribble(
~id, ~value,
390639, “RATINGS: 4 MEAN: 3.83/5.0 WEIGHTED AVG: 3.39/5 IBU: 35 EST. CALORIES: 204 ABV: 6.8%”,
99472, “RATINGS: 89 WEIGHTED AVG: 3.64/5 EST. CALORIES: 188 ABV: 6.25%”,
361258, “RATINGS: 8 MEAN: 3.7/5.0 WEIGHTED AVG: 3.45/5 IBU: 85 EST. CALORIES: 213 ABV: 7.1%”
)> Encoding(bad_data$value)
[1] "UTF-8" "UTF-8" "UTF-8"
我们如何检测它是否有问题?从上面我们可以看到,数据编码为 UTF-8,所以我们应该没问题……对吗?这不就是网页告诉我们的编码吗?是的,但是深入研究数据,似乎有一些字符没有被正确转换。那么,我们究竟如何“纠正”一个坏的 UTF-8 文件呢?
第一圈火:发现问题
首先,我们可以尝试使用 datapasta 重新创建数据帧,如下所示,希望我们能看到一些东西
datapasta::tribble_paste(bad_data)
幸运的是,当我们这样做时,我们可以看到一些有趣的事情:
Odd red spaces in our data?
好的,所以在我们的数据中有一些奇怪的红色空格…那到底意味着什么呢?如果我们将输出粘贴到 Visual Studio 代码中,我们可以看到一些特殊的东西:
看了上面的截图,好像有点不对劲。为什么蓝色箭头的地方没有空格?似乎有点奇怪。假设我们想看的不仅仅是 3 瓶啤酒,而是几百瓶,也许几千瓶啤酒,这可行吗?当然,但是一定有更好的方法,而且有:
#Truncated Output
textclean::check_text(bad_data$value)
=========
NON ASCII
=========
The following observations were non ascii:
1, 2, 3
The following text is non ascii:
1: RATINGS: 4 MEAN: 3.83/5.0 WEIGHTED AVG: 3.39/5 IBU: 35 EST. CALORIES: 204 ABV: 6.8%
2: RATINGS: 89 WEIGHTED AVG: 3.64/5 EST. CALORIES: 188 ABV: 6.25%
3: RATINGS: 8 MEAN: 3.7/5.0 WEIGHTED AVG: 3.45/5 IBU: 85 EST. CALORIES: 213 ABV: 7.1%
*Suggestion: Consider running `replace_non_ascii`
textclean 包是 qdap 包的衍生包,设计用于处理文本数据,但需要 rJava 才能正常工作。textclean 是来自 qdap 生态系统的一个端口,并且更轻便,因此允许我们使用它来检测我们文本的问题。正如我们在上面看到的,有很多错误,但这允许我们验证非 ascii 字符存在于我们的文本中,因此如果我们现在不处理它们,会引起我们的头痛。
现在,如果你和我一样,试图掌握字符串中到底发生了什么可能是一个挑战:我们如何知道这些问题发生在字符串中的哪个位置?幸运的是,base-r 提供了一些优秀的工具来帮助检测这一点:
> iconv(bad_data$value[[2]], to = "ASCII", sub = "byte")
[1] "RATINGS: 89<c2><a0><c2><a0> WEIGHTED AVG: 3.64/5<c2><a0><c2><a0> EST. CALORIES: 188<c2><a0><c2><a0> ABV: 6.25%"
> tools::showNonASCII(x$value[[2]])
1: RATINGS: 89<c2><a0><c2><a0> WEIGHTED AVG: 3.64/5<c2><a0><c2><a0> EST. CALORIES: 188<c2><a0><c2><a0> ABV: 6.25%
工具包和 R 中的 iconv 都让我们看到,果然,这里出现了一些由<>指示的奇怪字符。
如果您想更好地了解这些字符到底是什么,我们可以将 datapasta 的 tribble_paste 的原始输出插入到 Tim Whitlock 的 Unicode Inspector 中,我们可以看到,毫无疑问,我们有一个名为“No Break Space”的字符
No Break Space
和各自的 UTF-16 代码。为了验证,我们可以插入带有前缀\u 的代码,以及上面的代码,果然:
str_detect(bad_data$value[[2]], “\u00A0”)
第二个火环:修复 UTF-8
有用!现在我们需要想办法修复绳子。要修复字符串,我们可以通过 rvest、textclean 或 stringi:
bad_data <- tibble::tribble(
~id, ~value,
390639, “RATINGS: 4 MEAN: 3.83/5.0 WEIGHTED AVG: 3.39/5 IBU: 35 EST. CALORIES: 204 ABV: 6.8%”,
99472, “RATINGS: 89 WEIGHTED AVG: 3.64/5 EST. CALORIES: 188 ABV: 6.25%”,
361258, “RATINGS: 8 MEAN: 3.7/5.0 WEIGHTED AVG: 3.45/5 IBU: 85 EST. CALORIES: 213 ABV: 7.1%”
)
#' for reference
#' [https://stackoverflow.com/questions/29265172/print-unicode-character-string-in-r](https://stackoverflow.com/questions/29265172/print-unicode-character-string-in-r)
#' stringi also uses mostly UTF-8, which is very comforting to know
#'[https://jangorecki.gitlab.io/data.table/library/stringi/html/stringi-encoding.html](https://jangorecki.gitlab.io/data.table/library/stringi/html/stringi-encoding.html)
str_detect(x$value, "\u00A0")
ex1 <- textclean::replace_non_ascii(bad_data$value)
ex2 <- rvest::repair_encoding(bad_data$value)
textclean 将消除它检测到的值,而 rvest 将尝试保留该值。虽然 rvest 可以(而且确实提供了这种能力),但它并没有很好地可靠地清理文本数据。相反,stringi 为我们提供了函数 str_trans_general,它允许我们保持每个字符之间的三个空格不变。这将允许我们稍后使用这些空格作为分隔符来进一步清理数据。
bad_data$value <- stringi::stri_trans_general(bad_data$value, “latin-ascii”)
放大:用更大的数据量进行编码
现在,这听起来很棒,但也许你和我一样,发现大量啤酒数据(比如 2GB),并发现可能有一些编码问题…..我们可以尝试在导入后运行一个函数来清理数据,但这可能需要相当多的时间。有没有更好的方法来处理这个烂摊子?是的,有。输入 iconv:
[## ICONV
iconv 程序将文本从一种编码转换为另一种编码。更准确地说,它从编码转换…
www.gnu.org](https://www.gnu.org/savannah-checkouts/gnu/libiconv/documentation/libiconv-1.15/iconv.1.html)
iconv 是一个 GNU 命令行实用程序,它帮助强制将数据转换成正确的形式,同时还试图保留尽可能多的数据。
让我们以这里的数据为例:
[## RateBeer 评论 petergensler 数据集
来自 https://snap.stanford.edu/data/web-RateBeer.html 的数据
数据世界](https://data.world/petergensler/ratebeer-reviews)
现在,乍一看,数据似乎有点乱,但让我们集中精力尝试将数据转换成 UTF-8。首先,让我们使用 r 中的 gunzip 将文件解压缩到一个目录中。
#Gunzip Ratebeer
gunzip(filename = “~/petergensler/Desktop/Ratebeer.txt.gz”,
destname = “~/petergensler/Desktop/Ratebeer.txt”, remove= FALSE)
这个命令中的~仅仅意味着相对于您机器上的主目录。只需在终端中键入 cd,您就会被带到您的主目录。
接下来,我们可以使用 bash 通过 wc -l 确定这个文件中有多少行,我们还可以看到 bash 认为 file -I 的编码是什么:
wc -l Ratebeer.txt22212596 Ratebeer.txtfile -I Ratebeer.txtRatebeer.txt: text/plain; charset=utf-8
好的,这看起来没问题,但是有 2200 万行,修复起来会很麻烦。iconv 使这一过程变得轻而易举:
Approach 1:
iconv −f iso−8859−1 −t UTF−8 Ratebeer.txt > RateBeer-iconv.txtApproach 2:
iconv -c -t UTF-8 Ratebeer.txt > Ratebeer-iconv.txt
对于方法一,我们尝试获取我们认为应该是什么样的文件,并指定我们希望它是 UTF-8,并尝试覆盖它。方法二是一种更加暴力的方法,因为我们简单地告诉 iconv 我们想要转换到 UTF-8,并创建一个新文件。沃伊拉!如果需要的话,我们现在可以以原始行的形式读取文件,没有任何问题,这都要感谢 iconv。
需要注意的一点是,虽然 R 确实有一个 iconv 函数,但我发现命令行实用程序更适合我的需要,您可以简单地在 RMarkdown notebook 中放一个 bash 块。使用命令行。
第 5 部分:清理数据
现在我们已经获得了数据,并清理了编码,让我们看看是否可以尝试将基本统计数据放入它们各自的列中。乍一看,这似乎很简单,因为我们只需要在一个分隔符上拆分统计数据列,这应该很好。但是当然,我的一种啤酒没有另一种那么多的元素,因此乍看之下造成了很大的破坏(好像编码已经够有挑战性了)。
简单回顾一下,我们的数据如下:
bad_data <- tibble::tribble(
~name, ~link, ~beer_stats,
"pollyanna-eleanor-with-vanilla-beans", "[https://www.ratebeer.com/beer/pollyanna-eleanor-with-vanilla-beans/390639/](https://www.ratebeer.com/beer/pollyanna-eleanor-with-vanilla-beans/390639/)", "RATINGS: 4 MEAN: 3.83/5.0 WEIGHTED AVG: 3.39/5 IBU: 35 EST. CALORIES: 204 ABV: 6.8%",
"brickstone-apa", "[https://www.ratebeer.com/beer/brickstone-apa/99472/](https://www.ratebeer.com/beer/brickstone-apa/99472/)", "RATINGS: 89 WEIGHTED AVG: 3.64/5 EST. CALORIES: 188 ABV: 6.25%",
"penrose-taproom-ipa", "[https://www.ratebeer.com/beer/penrose-taproom-ipa/361258/](https://www.ratebeer.com/beer/penrose-taproom-ipa/361258/)", "RATINGS: 8 MEAN: 3.7/5.0 WEIGHTED AVG: 3.45/5 IBU: 85 EST. CALORIES: 213 ABV: 7.1%",
"revolution-rev-pils", "[https://www.ratebeer.com/beer/revolution-rev-pils/360716/](https://www.ratebeer.com/beer/revolution-rev-pils/360716/)", "RATINGS: 34 MEAN: 3.47/5.0 WEIGHTED AVG: 3.42/5 IBU: 50 EST. CALORIES: 150
理解手头任务的部分关键是双重的——我们希望将数据拆分到每个列中,但是使用:来保持键-值对关系。
final_output <- bad_data %>%
# create a new list column, str_split returns a list
mutate(split = str_split(string, " ")) %>%
# then unnest the column before further data prep
unnest() %>%
# you can now separate in a fixed 2 length vector
separate(split, c("type", "valeur"), ": ") %>%
# then get the result in column with NA in cells where you did not have value in string
spread(type, valeur) %>%
rename_all(str_trim) %>%
select(-string, -link)
#> # A tibble: 3 x 6
#> ABV `EST. CALORIES` IBU MEAN `WEIGHTED AVG` RATINGS
#> * <chr> <chr> <chr> <chr> <chr> <chr>
#> 1 6.8% 204 35 3.83/5.0 3.39/5 4
#> 2 7.1% 213 85 3.7/5.0 3.45/5 8
#> 3 6.25% 188 <NA> <NA> 3.64/5 89
请理解,当我第一次运行这个脚本时,第一行代码一开始就失败了--这是由于编码问题,但是直到实际尝试使用 spread 函数时,我才收到错误消息。
起初,这看起来有点复杂,尤其是如果您不熟悉 list-column 的话。当我第一次看这段代码时,str_split 似乎有一个非常奇怪的行为,几乎是代码的一个不必要的负担。取消 list-column 嵌套几乎创建了一个类似笛卡尔的连接,它接受每条记录,然后使每一行都有每一个值的每一种可能的组合,从而使传播和动态传播成为可能。
现在我们的表看起来像这样:
> head(final_output)
# A tibble: 4 x 7
name ABV `EST. CALORIES` IBU MEAN RATINGS `WEIGHTED AVG`
<chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 brickstone-apa 6.25% 188 <NA> <NA> 89 3.64/5
2 penrose-taproom-ipa 7.1% 213 85 3.7/5.0 8 3.45/5
3 pollyanna-eleanor-with-vanilla-beans 6.8% 204 35 3.83/5.0 4 3.39/5
4 revolution-rev-pils 5% 150 50 3.47/5.0 34 3.42/5
由此,有趣的是,收视率最高的啤酒没有平均评论,但波利安娜似乎得分最高。
结束语
当你读完这篇文章时,我会鼓励你尝试喝点啤酒(或你选择的饮料),并尝试收集相关数据。你注意到了什么?ABV(饮料能有多烈)和啤酒的平均点评分数有关联吗?我希望这篇教程能够帮助你深入了解如何在尝试解决问题时利用 R,并且你已经了解了更多关于 R 编码的知识,以及在面临这些挑战时有所帮助的工具。我在下面概述了我的一些想法,因为我一直在思考这些数据是如何在这么多方面挑战我的,不仅仅是在 R 方面,而是在我的个人工作流程中。
编码
在过去的几天里,我一直在和 R 一起工作,我一直注意到的一件事是,当 R 失败时,很难明确地告诉它何时失败以及失败的原因。作为一个 R 的新手,我认为这使得诊断什么工具可能会失败变得非常困难,因为 R 不会很快失败,也不会很难失败。我们字符串的编码:
- 读取 html 失败了吗?
- 仅仅是 tidyr 与 UTF-8 有问题,还是这是一个更深层次的问题?
- 如果 base r 有如此多的编码问题,这是任何项目的“坚实基础”吗,无论是否与工作相关?
经历了大量的编码问题后,很明显,如果你使用的是 Windows,编码对 R 来说可能是一场灾难。对我个人来说,我实际上看了 TIBCO 发布的另一个版本的 R,名为 TERR:
[## TIBCO 企业版 R 运行时
在 TIBCO Enterprise Runtime for R 文档中,您可以找到关于创建和分发…
docs.tibco.com](https://docs.tibco.com/products/tibco-enterprise-runtime-for-r)
因为太多 base-r 的编码问题太麻烦了。这些问题虽然很*,但我认为几乎传达了一个关于 R 核心的信息:它根本不是一个稳定的基础。从开发的角度来看,使用函数而不信任输出是非常不利的。tidyverse 无疑为新来者提供了许多正在开发的新包,但我认为这提出了一个好问题:您应该在生产管道中使用 R 吗,或者甚至是为了分析的目的?当你没有碰到这些问题的时候,一切看起来都很顺利,但是一旦你碰到了,调试起来真的很痛苦,尤其是对于一个语言新手来说。
咕噜图 vs dplyr:骑行线
乍一看,purrr 似乎是一个理想的包,但是如果没有正确的用例,就很难使用它。在我们的例子中,我们有 URL,我们想应用一个函数。
然而,虽然 purrr 被设计为将函数应用于对象,但大多数时候我们只是对应用函数感兴趣,比如通过谓词函数将 POSIX 转换为 datetime:
library(lubridate)
library(dplyr)
x <- data.frame(date=as.POSIXct("2010-12-07 08:00:00", "2010-12-08 08:00:00"),
orderid =c(1,2))
str(x)
x <- mutate_if(x, is.POSIXt, as.Date)
str(x)
当您需要使用自定义函数迭代元素时,Purrr 确实很出色,但是如果您所做的只是在工作流中使用 mutate_if,就很难掌握了。相反,如果您从未见过 dplyr 中的这些新功能,也很难理解它们能为您做些什么。
作为一种函数式编程语言,r 有很多优点:它允许您轻松地操作数据,并且有大量的函数可供您使用。如果有什么不同的话,我写这篇文章时面临的最大挑战之一就是在寻找解决方案时到底从哪里开始:R Manual、堆栈溢出、特定的包,甚至是 RStudio 社区。在正确的人手中,使用正确的技能,R 可以成为一个强大的工具,但不适合胆*的人。你怎么想呢?你认为 R 对于你的日常任务来说足够强大吗,或者你认为 base-r 有时感觉不稳定吗?
科幻极客的数据处理基础——第二部分——走向 RDD
原文:https://towardsdatascience.com/fundamentals-of-data-processing-for-scifi-geeks-part-ii-apache-spark-rdd-3d4b2c6f39f?source=collection_archive---------3-----------------------
在阅读本文之前,请阅读第一部分。这个博客有一个代码库,里面有可运行的例子:https://github.com/actions/dp_fundamentals
在第一部分中,我们在科幻多*扩展概念和数据处理系统之间做了一个类比。我们引入了迭代器作为一种以转换形式构建数据处理计划的方式,以及执行这些转换并产生结果的动作。
在本系列的这一部分,我们将扩展到第二*空间,并开始通过多个内核和系统同时处理我们的数据。
就像布料是由许多线缝合在一起构成的一样,我们向第二*数据处理的扩展将需要多个迭代器。数据处理将利用可用的 CPU 内核在多个计算线程上同时工作。
分割
就像你不能不用一根线来做一件衣服一样,我们也不能并行处理一大堆数据。为了处理数据,我们必须对数据进行分区。上次我们处理了《威廉莎士比亚全集》。我们已经知道如何计算整个文件的字数。为什么我们不试着扩大加工规模。为此,我们需要将它分成多个部分。我能想到许多分裂的方法。我们可以按页拆分,有几千个*文件;我们可以按故事拆分,有几个大*不同的有意义的文件;我们可以简单地把这个大文件切成几个相等的部分。哪种方法效果最好?最长的答案是——“视情况而定”。
数据分区的快速经验法则是—使用固定数量的大*相等的分区。
稍后我们将研究不同的方法,并逐渐得出结论。
现实生活中分区是如何形成的。
事实上,我们很少对巨大(或不巨大)的文件进行分区。通常,这些数据来自连续不断的点击量、消息、IOT 报告指标或威廉·莎士比亚写的文本行。当数据到达时,形成分区。在接下来的部分中,我们将讨论如何使用我们将要构建的机器来处理连续流。
现在我们假设我们的数据已经被分区了。关于分区的进一步讨论可以在本文的附录中找到。
并行数据处理
现在,我们建立了开始讨论并行处理的基础。
多线程的想法总是会引发很多问题:
-我需要多少个线程?
-我怎么做同步?
-我如何获得我的计算结果?
Fork-join 公共线程池
分叉连接模型正是我们需要开始的。这有助于将工作分成更*的任务。每个任务串行工作,而多个任务并行执行。执行整个作业的主线程将等待任务完成并收集结果。
Fork-join 比喻是这样的:
-当任务开始执行时,它分叉成单独的线程。
-当任务完成后,它加入主线程并返回结果。
source: wikipedia:Fork–join_model
为了更容易想象,可以把一个公共线程池看作一条有几条车道的高速公路。每条车道都是一个运行线程,而每个任务都是一辆在其中一条车道上行驶的汽车。当汽车行驶时,CPU 正在处理我们的数据迭代器的元素。当迭代器被清空时,这辆车退出高速公路。
池中的线程数量或高速公路中的线路数量等于 CPU 中的核心数量。我目前使用的笔记本电脑有两个超线程内核,所以总共有 4 个内核。我的公共 fork-join 池有 4 个线程——每个内核一个。我们并不真的需要更多,线程越少,一些内核就越空闲。定义良好的数据处理程序持续利用所有内核。
在 java 中,对公共池的访问是使用 ForkJoinPool 完成的。common pool()API 调用。
处理一个分区
这里我们定义了我们的任务,它将处理一个分区并返回部分字数。我们将使用我们在第一部分中构建的字数统计函数。
将这一切结合在一起
让我们创建另一个任务,它将启动分区的并行处理,并将结果汇总在一起。
在任务的构造函数中,我们迭代我们的分区。我们为每个分区创建一个处理任务,并立即开始在一个可用的线程上运行它。我们使用方法 ForkJoinTask::fork 。在计算方法中,我们将任务结合在一起,并将分区计数汇总成最终计数。
运行作业剩下的工作就是将我们的任务提交给池:
基本计算图
如果我们要可视化我们的代码,我们可以看到我们刚刚构建了一个非常简单的计算图,其中一个 WordCountTask 派生出多个任务进行并行处理并协调结果。当我们为更复杂的处理建立机器时,计算图的概念将是重要的。
走向 RDD
看着上面我们的并行化代码并不能让我满意。Fork Join 模型为在线程上运行任务提供了很好的抽象,但它并不真正符合我们对数据处理的推理方式。直接处理线程池和调度任务可能会变得很麻烦并且容易出错。只是一个简单的代码洗牌的*例子,它可以改变行为。
下面是 WordCountTask 的版本,看起来很工整。
虽然代码看起来是在做同样的事情,但重要的区别是它将串行执行。一个分区将在另一个分区之后被处理,而我们所做的只是放错了 join 调用的位置。很难发现这种差异,问题也不会变得明显,直到我们将它部署到生产中,并意识到任务需要 4 倍的时间才能完成。
我们需要更好的并行数据处理模型。希望是为我们安排任务的那个。
在第一部分中,我们将迭代器作为一种机器来构建一个作为转换链的执行计划,然后使用一个动作来执行该计划。
让我们看看代码的组成部分,并尝试构建一个抽象,这将有助于我们将数据处理扩展到二*空间,并将其并行化,以充分利用我们的计算能力。
我们的第一个类正在处理一个分区。仔细看看我们的代码,我们需要知道的只是分区号 partitionId 。我们能够从 partitionId 构建处理链。然而,我们以后可能需要更多的信息。
接下来,我们使用 wordCount 方法处理一个分区。然而,wordCount 方法做了很多事情。查看内部,执行以下操作:
1 从一个分区文件构建了一个迭代器。
2.在这个迭代器上附加了一个转换链。
3.准备运行操作以获取分区级别的结果。
接下来我们使用 WordCountTask 来
4.构建一个计算图,并在我们的计算线程池中执行。
5.合并部分结果(另一个动作)。
现在让我们想象一下新的结构,它包装了一组分区迭代器。这种结构会像迭代器一样为我们构建处理链,我们将能够运行我们的操作,而无需考虑多线程和任务调度。这几乎就是 Apache Spark 背后的团队所做的。他们的基本想法被称为 RDD——弹性分布式数据集。虽然我们不会在这个模块中重新构建 Apache Spark,但是我们将研究这个机制背后的基本思想。
这是第一步。我们的抽象 RDD:
- 知道它的分区,
- 有能力访问分区数据的计算方法
- 意识到它的依赖性,以便能够建立一个计算图。
- 有权访问 ForkJoinPool 来运行作业。
在我们过于简化的 RDD 中,我们将 ForkJoinPool 等同于 sparkContext ,我们稍后将解决这个问题。
让我们看看它是如何为我们工作的,并在分区文件上创建一个 RDD:
- FilePartition 是分区的自定义实现,它引用数据所在的实际文件。
- 我们实现了 RDD,它允许我们通过从分区构建迭代器来访问分区文件数据。
接下来,我们需要做的就是将方法从文件添加到我们的 RDD 类中。
**static** RDD<String> fromFile(Path directoryPath){
**return new** PartitionedFileRDD(directoryPath);
}
地图分区
在我们的并行字数统计代码中,我们学习了如何处理一个分区,然后同时处理我们的分区。地图分区法有助于我们概括这一过程。我们将通过将一个 RDD 的分区迭代器映射到另一个 RDD 的分区迭代器来转换我们的 RDD。
首先,我们需要认识到,很多时候,我们会有一个依赖项,所以围绕这个特定的情况编写一些助手方法会有所帮助。
**public** RDD(RDD parent) {
**this**.**sparkContext** = parent.getSparkContext();
**this**.**dependencies** = Arrays.*asList*(**new** Dependency() {
@Override
**public** RDD rdd() {
**return** parent;
}
});
}
**public** <P> RDD<P> getParent(){
**return** (RDD<P>)**this**.**dependencies**.get(0).rdd();
}
现在我们准备建造我们的混凝土 RDD:
**private class** MapPartitionsRDD<T,O> **extends** RDD<O>{
Function<Iterator<T>, Iterator<O>> **converter**;
**public** MapPartitionsRDD(RDD parent, Function<Iterator<T>, Iterator<O>> converter) {
**super**(parent);
**this**.**converter** = converter;
}
@Override
**protected** List<Partition> getPartitions() {
**return** getParent().getPartitions();
}
@Override
**protected** Iterator<O> compute(Partition partitionId) {
Iterator<T> preComputed = (Iterator<T>)getParent().compute(partitionId);
**return converter** .apply(preComputed);
}
}
最终为 RDD 找到了新方法:
**public** <O> RDD<O> mapPartitions(Function<Iterator<T>, Iterator<O>> converter){
**return new** MapPartitionsRDD<T, O>(**this**, converter);
}
让我们准备使用 RDDs 重写我们的 wordCount 方法。这是它看起来的样子。
我们现在有一个简单的方法来处理分区。我们使用的函数调用非常类似于我们处理迭代器时的函数调用。然而代码看起来还是有点乱。MapPartitions 要求我们使用分区迭代器。
让我们介绍几个熟悉的方法,使我们的 RDD 更干净。这些方法将帮助我们停止考虑分区,让我们像处理迭代器一样处理分布式数据集。
平面地图
**public** <O> RDD<O> flatMap(Function<T, Iterator<O>> splitter){
**return this**.mapPartitions(pi->pi.flatMap(splitter));
}
地图
**public** <O> RDD<O> map(Function<T, O> mapper){
**return this**.mapPartitions(pi->pi.map(mapper));
}
现在缺少的是我们的动作,它将从迭代器中收集结果。我们需要一些模拟的减少RDD 的方法。在 RDDs 的世界中,它被称为“聚合”。
总计
让我们首先设计这个方法应该如何工作。如果我们看一下并行字数统计的原始实现,您会发现我们调用了两次 reduce 方法。作为作为我们的PartitionProcessingTask的一部分执行的串行字数统计方法的一部分,对每个分区进行了一次缩减。第二次 reduce 是为了将分区结果放在一起,作为 WordCountTask 的一部分。 现在我们有了处理分区的机制,我们可以将这两个调用放在一个方法中:
我们定义了分区缩减器,就像在串行字数统计方法中一样。它计算我们在每个分区的字数。接下来,我们定义了结果聚集器,它将来自每个分区的结果聚集在一起。我们使用熟悉的代码,这些代码我们已经在代码的不同部分使用过了。
现在我们有了启动事物的方法 aggregate。好的一面是,当我们讨论并行数据处理时,我们几乎已经建立了它。
我们的方法 aggregate 只是概括了我们在构建第一个并行字数统计方法时所做的工作。它很好地结合了 RDD 和 ForkJoinPool 来包装分区迭代器的处理以及结果的聚合。我们来讨论一下这是怎么回事。
- 我们必须为开始参数选择一个供应商。我们正在处理一个迭代器上对 reduce 的多次调用。我们需要能够在每次进行缩减时获得 start 参数的新副本。因此,我们需要根据请求提供新起点的能力。
- 分区聚合器是分区迭代器的 reduce 方法的组成部分。不像迭代器 reduce,我们还没有完成。
- 组合器组合我们从处理每个分区中得到的结果。
新代码还不错。我们不必处理任务调度或考虑并行处理。我们在那里所做的就是写下我们的逻辑,并让 RDD 机器来处理。
附录
什么分区方案最好?
既然我们已经了解了并行处理是如何工作的,我们可以考虑划分模式了。
如果我们有相同大*的分区,并且分区的数量等于核心的数量,那么一切看起来都很好。它看起来就像上面的图表。
不幸的是,这个世界并不理想。假设我们有 5 个分区和 4 个内核。
我们的总处理时间会立即翻倍,而数据量只会增加 25%。
现在,让我们想象一下,我们将文本按页面分割,并有数千个分区。这个方案非常灵活,但是我们会有与调度这么多任务和处理这么多文件相关的开销。
最终没有完美的答案。划分方案需要考虑底层技术和处理要求。
分区代码
这是我们的复合文件的分区代码:https://github . com/actions/DP _ fundamentals/blob/master/src/main/Java/fundamentals/ll processing/data splitting . Java
科幻极客的数据处理基础——第一部分
原文:https://towardsdatascience.com/fundamentals-of-data-processing-part-i-f6a6914e1fec?source=collection_archive---------8-----------------------
如果你对科幻感兴趣,你可能读过《三体问题》三部曲。我强烈推荐你去读一读,以防你没有看到这本书。
作者刘提出的一个最引人入胜的想法是质子多*膨胀的想法。他将质子描述为高度复杂的 11 *结构,看起来很*(0.8418±0.0007fm。)因为它的*度是坍缩的。一个先进的文明可以通过扩大质子的坍缩*度来获得巨大的能量。三体世界的居民能够在二*空间中扩展一个质子,以建造一个跨越半个星球的巨大球面镜。这面镜子是用来在长时间黑暗中控制白天光线的。
我们还不能扩大质子的*度,但*的东西可以变大,大的东西可以变*的想法是数据处理的基础。
让我们从我们的“质子”开始,我们将要展开它。在数据处理领域,我们从一个记录开始。记录可以是巨大点击流中的一次点击,可以是用户上传的一张图片,可以是 IOT 设备的一次测量,可以是一次医疗测试结果……记录是您的基石。现在让我们试着对你的记录进行多*扩展,看看能做些什么。
这个博客有一个代码库,里面有可运行的例子:https://github.com/actions/dp_fundamentals
*度 1 —迭代器
迭代器可能是最简单也是最吸引人的数据结构。你可能有最强大的数据结构,比如多*树或很酷的散列,这些都不能做迭代器能做的。一个迭代器可以遍历一个数据集,你甚至无法想象它能适合你的内存,它所需要的只是一个常量内存来容纳一条记录。真正的迭代器是你的一*扩展工具。让我们更详细地看一下。
**public interface** Iterator<E> { **boolean** hasNext(); E next();}
迭代器给了你获取数据的潜力。请注意,hasNext 方法不需要每次都返回 true。迭代器可以扩展非常大的数据集,甚至是永无止境的数据流。
迭代器允许你在执行这些计算之前建立一个计算链。让我们让迭代器更强大:
**abstract class** Iterator<I>{
.....
*/**
* map function apply an operation to every element of the
* iterator at the moment of iteration
** ***@param mapper*** *mapper function
** ***@param <O>*** *Returning type
** ***@return*** *new iterator over processed data
*/* <O> Iterator<O> map(Function<I, O> mapper) {
Iterator<I> origin = **this**;
**return new** Iterator<O>() {
@Override
**boolean** hasNext() {
**return** origin.hasNext();
}
@Override
O next() {
**return** mapper.apply(origin.next());
}
};
}
.....
}
我们介绍的第一种方法是 map 。方法映射在我们迭代时处理数据。我们一次处理一条记录。当我们调用 map 时,我们还没有处理数据。我们刚刚构建了一个以迭代器形式处理数据的计划。随着数据的到来,我们可以一次处理一个。
在实际执行处理之前构建执行计划的能力是构建数据处理管道的基础。执行规划可带来优化、容量规划、弹性、可扩展性和其他必要特性,从而实现持续可靠的数据处理。
平面地图
**abstract class** Iterator<I>{
....
<O> Iterator<O> flatMap(Function<I, Iterator<O>> splitter) {
Iterator<I> origin = **this**;
**return new** Iterator<O>() {
*//initialize current iterator as empty iterator* Iterator<O> **current** = Iterators.*empty*();
@Override
**boolean** hasNext() {
**if** (**current**.hasNext()){
**return true**;
}
**if**(origin.hasNext()){
**current** = splitter.apply(origin.next());
**return** hasNext();
} **else** {
**return false**;
}
}
@Override
O next() {
**return current**.next();
}
};
}
....
}
让我们试着理解一下 flatMap 实际上是做什么的,为什么它是数据处理中最重要的功能。
如果您可以将数据集的每个元素转换为其他元素的迭代器,那么 flatmap 将产生一个迭代器,它将迭代所有结果迭代器的所有元素。同样,请注意,除了存储一行所需的内存之外,我们没有使用更多的内存。出于多种原因,Flatmap 的确不同凡响。它可以一次完成变形和过滤。注意,原始迭代器的一些元素可以转换成空迭代器,因此在输出中不存在。从技术上来说,可以用 Flatmap 写出很多有帮助的数据处理方法。
我们将看到如何使用 flatMap 来处理和过滤数据。
在这个例子中,我们迭代一个相当大的文件的行,并将这个迭代器转换成文件中有意义的单词的迭代器。
迭代一个数据文件。
下面是我们如何在一个文件上构建一个迭代器。请注意,我们不是将整个文件读入内存,而是只获取我们立即需要的内容。
现在我们开发了一个强大的机器来转换迭代器,让我们看看如何从迭代器中得到结果。
**abstract class** Iterator<I>{...
**abstract boolean** hasNext();
**abstract** I next();
<O> O reduce(O start, BiFunction<O, I, O> aggregator){
O current = start;
**while**(hasNext()){
current = aggregator.apply(current, next());
}
**return** current;
}...
}
Reduce 是一个简单的方法,它将迭代器折叠成最终结果。我们需要的是将两个元素折叠成一个,然后随着迭代不断折叠的能力。
例子
顶级元素
Integer[] data = {**10**,**20,30**,**40**,**50**,**60**,**71**,**80**,**90**,**91**};
**int** k = 3;
PriorityQueue<Integer> top = Iterators.*overArray*(data)
.reduce(**new** PriorityQueue<Integer>(k), (topn, el)->{
**if**(topn.size()<k){
topn.offer(el);
} **else**{
**if**(topn.peek()<el){
topn.poll();
topn.offer(el);
}
}
**return** topn;
});
字数
这是一个例子,所有的东西都聚集在一起。我们阅读了一个大文件——莎士比亚全集。FlatMap 帮助我们将每一行拆分成单词,并一次性过滤掉无意义的行。Reduce 将计数聚集在一起。
作业——改进行处理,更好地提取有意义的单词。结合两个例子,得出前三个最受欢迎的词。
转换与行动
如果我们仔细看看我们的例子,我们可以用迭代器做两种类型的活动。这些可以分为两种类型——转换和动作。
像贴图、平面贴图、滤镜或 linesFromFile 、、这样的变换并不能真正做什么。他们只是建立了一个步骤链,这将发生在结果迭代器被遍历的时候。您可以构建最复杂的转换链,但是在有人对结果迭代器调用 next 之前,实际上不会发生任何计算。
像 reduce 这样的动作实际上是遍历一个迭代器来调用转换并产生结果。
扩大企业
现在我们知道了迭代器的基础知识以及如何使用它们。是时候添加更多的转换和操作了。
filter —更容易使用的方法来对过滤后的数据产生新的迭代器。如果你注意的话,我们已经用它从单词列表中删除了空字符串。
—当我们想知道元素在迭代器中的位置时会有帮助。我们只需在现有的迭代器中添加 counter。
取——在第一个迭代器的前 n 个元素上产生一个迭代器。您将看到它如何限制作为 wordCount 输出一部分的打印字数。
forEach—是一个动作,它遍历迭代器,对每个值应用一个函数。它不返回任何内容。如果我们必须将转换的结果保存到文件、数据库或其他存储中,这是非常有用的。
收藏——是一个动作。它遍历迭代器并将数据收集到 java list 中。
范围 — 在一个数字范围内迭代。将其视为 i 结构的的替代品。基本上只是一个围绕 reduce 的简单包装。**
over array—遍历数组中的元素
from Java——将 Java 迭代器,没有我们有用的方法,转换成支持转换和动作的迭代器。
结论
这里描述的迭代器是一个简单的工具,它帮助您在实际处理数据之前建立数据处理计划。它可以帮助处理看似无穷无尽的数据,只使用有限的内存。迭代器可以被想象成一*数据扩展,为扩展到“更高*度”打下基础。特别是在内核、机器和数据中心之间并行处理。
拍手,喜欢,分享是你想了解更多关于多*数据扩展的知识。
阅读第二部分学习如何扩展到第二*度。
放弃
注意:该实现仅为演示目的而特意简化。生产就绪实现稍微复杂一些。
未来实验室人工智能峰会悬崖笔记
原文:https://towardsdatascience.com/future-labs-ai-summit-cliff-notes-8ac185cef212?source=collection_archive---------5-----------------------
NYU 足球中心,2017 年 10 月 31 日
我昨天参加了未来实验室的人工智能峰会,作为了解该领域最新发展的一种方式。我喜欢这些活动,因为它们是相对亲密的,而且演讲者都在这个被广泛误解的前沿技术的采煤工作面。
我主要感兴趣的是了解组成人工智能(机器学习/深度学习等)的组成技术如何应用于现实世界的问题。我相信写一写人工智能是如何被应用的对揭开这项技术的神秘面纱和减少现在充斥的疯狂炒作大有帮助。
我冒昧地做了一些讲座的笔记,但是这些笔记并不全面,也没有涵盖所有的讲座。我只写了与产品直接相关的笔记,或者谈论了与实践者相关的人工智能技术的内在特征/行为。欢迎提问/评论。
利用神经网络:一个 ML 应用的故事
谷歌纽约研究主管科瑞娜·科尔特斯
Corinna 的演讲侧重于她和她的团队如何应对使用深度模型部署“智能回复”功能的挑战,最初是在谷歌收件箱内,后来是在 Gmail 上。
她首先提到,机器学习对谷歌产生了巨大影响,许多应用因此被注入了新的功能。接受过这种待遇的 app 包括;
- 谷歌翻译(提高准确性)
- Google 相册(自动字幕和物体识别)
- 语音识别(准确性提高)
- 收件箱/Gmail(智能回复)
智能回复
Gmail Autopilot, April 1 2009
智能回复的灵感来自谷歌 2009 年愚人节的恶作剧 Gmail 自动驾驶。这个恶作剧提出了一个系统,它能够推断电子邮件的内容,并根据可调的预设为你构建一个回复。
智能回复拉开了 2014 年秋季的序幕。它广泛使用 LSTMs(长短期记忆),这是一种递归神经网络的形式。我不会深入讨论这些,但是在这里可以找到一个很好的资源。
Corinna 继续提到,LSTMs 提供了一个强大的技术框架来构建智能回复功能。然而,该团队面临 3 个关键挑战;
如何控制特性的输出
为了求解产量,Corinna 和她的团队发现了以下结果:
- 不合语法和不恰当的答案是有问题的
- 他们找到的解决方案是使用固定的响应(数百万个固定的响应,而不是动态生成新的响应)
- 响应被人工净化(使用标签传播在语义上聚集在一起)
- 从不同的集群中挑选响应,以确保响应随时间的多样性
- 为边缘案件制定了规则。例如,如果你试图用“你闻到了”这样的电子邮件来欺骗智能回复,它甚至不会尝试回复。
如何加快推理速度
通过改进 LSTMs 的构造方式来改进推理。团队实现了前馈架构和非对称散列。由于实现了这种智能回复,实现了一些令人印象深刻的性能改进;
- 智能回复现在比最初发布时快了 100 倍
- 智能回复现在占所有手机回复的 10%
如何生成可扩展的架构
Corinna 和她的团队所做的工作导致了 Adanet 的开发,这是一个允许算法自适应学习并进一步改善底层神经网络的框架。更多信息在这一块由 Wired 提供。
人工智能的社会和伦理影响:我们的责任是什么?
执行董事苔丝·波斯纳 AI4ALL
这个演讲是一股新鲜空气,因为之前的大部分演讲都钻研了大量不必要的技术术语。Tess 的演讲讨论了人工智能领域出现的系统性高层次问题。这是一个相当短的演讲,所以我用要点格式写了下来。
- 未来 10 年人工智能为美国国内市场带来 1.49-2.95 万亿美元的机会。
- 在人工智能行业,我们正面临一个巨大的多样性问题
Bernard Parker, left, was rated high risk; Dylan Fugett was rated low risk. Image credit: Josh Ritchie for ProPublica
- 这在很大程度上表现为偏见。Tess 用 Northpointe 开发的 COMPAS(替代性制裁的矫正罪犯管理概况)软件举例说明了这一点。这个软件已经由独立的第三方在进行了广泛的测试,并被证明对黑人被告有偏见。
- 偏见也存在于谷歌翻译等日常工具的微妙互动中。
Gender bias present in translation between certain languages
导致上述例子的一些问题包括:
- 不同人群的准入门槛目前非常高
- 人工智能中的同质文化
- 对场地的感知有限
- 早期缺乏对技术概念的技术接触
- 很少有相关的榜样
- 缺乏对等支持
AI4all 试图解决的一个角度包括:
- 教育下一代人工智能领导者
- 建立人工智能意识,教育未来消费者
- 扩大促进人工智能技术的有益用途
版权法能否修复 AI 的隐性偏见问题?
作者阿曼达·莱文多夫斯基——NYU 法学院助教
这个演讲也激起了我的兴趣,因为它向社会结构提出了一个有趣的挑战——特别是版权法。Amanda 提出了一个令人信服的论点,认为版权法通过限制可用于训练算法的数据集类型,导致隐含的偏见,给社会造成了巨大的损害。同样,下面的要点总结了这次谈话;
- AI 有偏见是因为人有偏见
- 我们生活在一个充满偏见的社会,这些偏见主要通过有偏见的数据进入我们的人工智能系统
- AI 需要好的数据。垃圾进,垃圾出。
- AI 有版权问题
- 许多算法已经用安然公司的电子邮件进行了训练。这个由 50 万封电子邮件组成的语料库包含了大约 150 个用户的数据,其中大部分是安然公司的高级管理人员。这些是联邦能源管理委员会在调查期间发布的。
- 考虑到这些数据代表了安然内部的系统性欺诈行为,认为这些数据被用于训练算法是令人困惑的。
- 低摩擦和可访问的数据是训练人工智能系统的主要数据来源,尽管电子邮件的内容和创建它们的环境会产生负面影响。
- 因此,版权法可能会偏袒人工智能系统。这是版权法需要改革的主要原因。
聊天机器人的未来——机器人与机器人交谈
原文:https://towardsdatascience.com/future-of-chatbots-bots-talking-to-bots-388112a204f5?source=collection_archive---------13-----------------------
The future of integration with conversation
我最近在考虑一个项目。我们正在开发一个应用程序,其中一部分涉及到在餐馆预订。大多数餐馆没有自动预订系统——你可以插入的支持许多餐馆的 API 很少。
支持每一家餐馆的唯一可靠的方法是给这些餐馆打电话,用传统的好方法预订——和一个人交谈。然而,为了省钱,我们正在探索让机器人打电话的想法,而不是使用现代语音技术。理论上,这是非常可能的,尽管需要收集大量的数据来完成。
巧合的是,我也是 Vesta.ai 的技术顾问,这是一家为餐馆开发聊天机器人技术的公司。他们的目标是制造一个可以代替服务员的聊天机器人。你可以进来,坐下来,开始和一个*的智能扬声器说话来点菜。然而,该公司计划将这项技术扩展到通过电话接听电话。
于是很自然的想到这两个项目,我开始怀疑。如果这两种技术都成为主流,会发生什么?我们会让机器人和机器人说话吗?几乎不可否认的答案是——是的。但问题是,这将是一个边缘案例,一个我们将看到社会从人类供电系统向人工智能供电系统过渡的退化技术的幽默例子。或者,对话最终会成为集成两个软件的工程选择吗?
在考虑答案时,我要求你比较和对比集成系统的两种方式:
鉴于所有这些,相信自然语言集成可能会成为真正的工程选择似乎有些疯狂。但是我要提请注意这样一个事实,即假设的自然语言集成的许多负面影响随着长期趋势而减轻:
- CPU 能力和网络容量继续呈指数增长,降低了额外 CPU 和网络成本的重要性
- 通用 NLP 工具每天都在改进,减少了对专业知识和定制数据集的需求
- 人工智能专业知识正变得越来越广泛,这得益于它在科技行业的时尚地位
- 无论如何,公司越来越多地为人类创建对话界面,使机器对机器集成的重用变得容易
从长期趋势来看,有利因素同样越来越诱人:
- 随着变化速度的加快,*护基于 API 的集成变得越来越昂贵,这要求我们不断更新代码以跟上变化
- 随着越来越多的人进入技术行业,允许半技术或非技术人员理解系统的设计变得更有价值
- 有越来越多的系统需要集成,每个集成都需要单独创建和*护,即使它们的行为非常相似
所有这些趋势的结合似乎意味着,随着时间的推移,相对于传统的集成,两个系统之间的自然语言集成将变得越来越有价值。
一开始,它会从*处着手。它将从日益流行的为人类设计的机器人中衍生出来。一些有进取心的程序员会创建自然语言集成,只是为了证明这是可以做到的。一些机器人对机器人的对话可能是由于交易双方自动化程度的提高而偶然产生的。
然后,当项目进展缓慢,工程师面临交付压力时,自然语言集成可能被认为是临时的黑客修复或一次性计划,出于对其便利性的好奇,但从未打算成为永久的。但是,当这些集成投入使用,天不会塌下来,这种疯狂的思考 API 的方式将越来越成为一种可接受的工程选择,尽管被归入某些边缘情况。
不过我预测,随着人工智能行业继续向前发展,我们试图自动化越来越多的流程和工作,我们将需要以指数增长的速度在不同的组织之间创建集成。这些集成将需要以越来越复杂的方式进行交互,这需要代表人类进行越来越多的监督。有了它,自然语言集成将从一个深奥的概念,一个黑客玩具,变成一种占主导地位的主流技术。
在不同的集成之间分担工作的好处太大了,不容忽视。因此,不是人类越来越适应技术世界,而是技术世界将越来越像我们。即使在最深的层次,我们的机器也可能开始用人类的语言相互交流。机器人会和机器人说话。
仅供参考:本帖原载于www . electric brain . io。
面向未来的创业:医疗保健中的数据网络效应
原文:https://towardsdatascience.com/future-proof-your-startup-data-network-effects-in-healthcare-32d54de710af?source=collection_archive---------3-----------------------
在医疗创业公司激烈的竞争环境中,不断创新和改进是成功的关键。一个满足于满足市场需求的产品的公司会为下一个新事物创造机会让它过时。创新缓慢的公司可能会保持其地位,但会被利用网络和数据网络效应的创业公司超越。如果你的创业是数据驱动的,围绕网络建立的,强烈考虑使用以下现象来推动增长。
网络效应
由于社区分裂、互操作性问题和不利因素等原因,网络效应在数字医疗领域很大程度上没有得到充分利用。这个概念是众所周知的:
网络效应:网络效应描述了随着越来越多的人使用同一服务,一项服务如何变得对用户更有价值
科技领域的无数公司,如脸书、LinkedIn 和优步,都将网络效应作为增长黑客,它与业内许多最根深蒂固的巨头有关。
Source: Kinesis
如果你仍然怀疑网络和数据网络效应的实际好处,理解梅特卡夫定律可以帮助你相信:
梅特卡夫定律:网络的价值与系统上连接的用户数量的平方成正比。
一些人认为梅特卡夫定律应该改进,以显示网络价值遵循 n*log(n)曲线,其中 n 是用户数量。无论哪种方式,都会很快偏离线性回归。由于增长显然与网络的价值相关,因此很容易理解为什么初创公司争相利用这一现象。
数据网络效应
网络效应有一个强大且更模糊的兄弟:数据网络效应,它遵循相同的原则,在医疗保健领域有许多使用案例。虽然人工智能和机器学习产品比比皆是,但数据网络效应可以不费吹灰之力就将*麦从谷壳中分离出来。
数据网络效应:数据网络效应描述了随着越来越多的人使用同一服务,一项服务如何变得更智能(通常通过机器学习)
The Data Network Effect Flywheel. Source: CB Insights
数据驼峰到数据转储
让数据网络效应开始并不总是容易的,也不一定适用于每一次创业。开始有两个关键部分:
- 你需要访问数据,不管是你的还是别人的,从中学习。如果你不能生成自己的数据,从利用其他来源的数据开始可能是有用的,比如网络搜集,或者公开可用的数据集。
- 你需要激励用户在你的产品中创建他们自己的数据。这意味着让你的初创公司处理潜在的大型数据基础设施,并雇佣机器学习工程师来构建反馈回路的算法部分。
用例:Mediktor
数据网络效应也推动了采用,这通常是医疗保健领域最关键的挑战。症状检查器初创公司 Mediktor 利用了数据网络效应。他们的产品建立在机器学习算法的基础上,这些算法已经在患者记录结果的大型数据集上进行了训练。一个模型适合这个训练数据,以预测你得了什么病,以及你应该做什么来最有效地恢复。对于每一个输入数据的新用户,算法都会学习和改进。产品会自我学习变得更聪明。随着准确率的提高,越来越多的人想要使用该产品,循环往复。
结论
组织的数据被认为是企业最重要的资产。但是仅仅拥有数据本身并不能创造价值。通过利用您的数据来创建更智能的算法,您将创建更令人满意的产品。使用上述效果可以帮助飞轮旋转。
模糊流行:找出数据科学中流行词汇的“模糊逻辑”
原文:https://towardsdatascience.com/fuzzy-buzzy-sussing-out-the-fuzzy-logic-of-buzzwords-in-data-science-d790b41c5a9e?source=collection_archive---------12-----------------------
“bee perched on sunflower” by Christoph Polatzky on Unsplash
声明:本帖不涉及实际 模糊逻辑 。这个词原本只是一个双关语,但我后来意识到,它也表明了流行语的不当使用可能会产生误导。对于造成的任何困惑,我深表歉意。
随着数据科学越来越受欢迎,许多流行语被随意地抛来抛去,却没有正确理解它们的真正含义。其中一些流行语包括数据分析、大数据、人工智能和机器学习等术语。但是不同于在 ANCOVA 、 Moderation 和 The Confusion Matrix 的帖子中提到的术语,数据科学中的许多术语实际上是不可互换的。这篇帖子试图解释这些流行语的细微差异,以便我们都能说一种不那么令人困惑的共同语言。
介绍数据科学模糊 Buzzy
尽管有最近的趋势,数据科学实际上并不是一个新领域。如果我们将数据科学重新表述为“数据科学”,那么很明显 数据科学 就是所有与数据相关的事物的形式化。但是执行数据科学不仅仅包括分析数据;收集、清理和准备数据都是数据科学的重要子学科,其中每一个都可以成为一个独立的专业领域。换句话说,数据科学家的广义定义应该包括任何与数据打交道的人,甚至包括那些只使用电子表格来管理数据和进行简单计算的人(尽管这种联系可能会被更自负的更复杂的数据科学家所反对:P)。
The Data Science Fuzzy Buzzy.
现在,让我们把数据科学中的术语层次想象成一个模糊的嗡嗡声(实际上这只是一个可爱的*恩图),从最外圈的最广泛到最内圈的最具体。这也是一个很好的类比,可以将数据科学想象成一个模糊的概念,使用不同的技术从数据花中收集花粉和花蜜,然后将它们转化为蜂蜜洞察力!为了简化问题,我们将只关注数据科学中的数据分析领域。
有些人可能想知道,数据分析和数据分析之间到底有什么区别? 数据分析 是一个通用术语,用来描述为了获得某种洞察力而检查数据的过程。因为数据可以是定性的也可以是定量的,所以数据分析也可以以不同的方式进行。定性分析旨在通过解释技术了解无形因素,如潜在原因和动机;而定量分析旨在使用计算技术(如数据分析)进行可量化的测量。换句话说, 数据分析 是允许数据分析定量进行的技术集合。
这使得 数据挖掘 成为数据分析中使用的许多技术之一,其他众所周知的技术包括 机器学习 和 统计分析 。虽然这三种技术看似相似并有重叠,但它们的最终目标却大不相同。数据挖掘仅仅关注于在数据中寻找模式;机器学习更关心利用数据中的信息做出准确的预测;统计分析最感兴趣的是从数据中得出推论。将这些技术用于他们自己之外的目的是不合适的,但是研究人员和分析人员仍然经常犯这样的错误,导致错误的结论。这方面的更多内容将在后面的部分中讨论。
你可能会问,那么人工智能在哪里?【AI】人工智能(Artificial Intelligence)是以“学习”和“解决问题”的形式模仿人类智能的过程的一般描述(不是说人类智能是智能的缩影,但我们将不得不与它一起工作)。人工智能已经存在很多年了,最常见的形式是电脑游戏中不可玩的角色。但大多数人工智能都是使用 if-else 条件硬编程的,这不是对人类认知的准确描述。然而,近年来,机器学习的进步,特别是在强化学习(例如 AlphaGo 击败职业围棋选手)方面,已经让 AI 更接近人类处理信息的方式。因此,当我们在数据科学中谈论人工智能时,我们实际上是指使用看似智能的算法来处理和分析数据,而机器学习通常是实现这一目标的最常见方法。
这很好地总结了数据科学模糊 Buzzy 的结构,并澄清了人工智能实际上是通过机器学习实现的,而不是真正的技术本身。但是等等!大数据呢? 大数据 仅仅是如此庞大的数据集,需要专门的技术来处理和分析它们。除此之外,它们就像任何其他数据花一样,等待数据科学 Fuzzy Buzzy 从它们身上采集花粉和花蜜。
我们真的需要在这个问题上吹毛求疵吗?
有些人可能想知道是否真的有必要在条款上变得如此专业。除了被那些不理解其含义而随意使用这些术语的人弄糊涂之外,更重要的是澄清这些术语,因为它们通常是为非常不同的目的而设计的。数据分析中的各种技术并不等同,可能具有不同级别的可解释性和准确性。一般来说,更复杂的技术往往对它们被训练过的数据集有更好的准确性,但往往以过度拟合而告终,并且在推广到新场景方面表现不佳。因此,随着预测精度的提高,模型的可解释性往往会受到影响(参见下面的权衡图)。
Interpretability vs Accuracy Trade-off.
根据数据的类型和分析的目的,选择使用的技术应该是不同的。例如,如果重点是使用具有许多变量的大型数据集进行预测,机器学习通常是可行的方法。然而,如果目的是对一个只有几个变量的*数据集进行推断,用一个适当的假设进行统计分析是一个必要的过程。没有明确假设的数据挖掘行为无异于【p】——黑客,这也是众多学科中复制危机的部分原因。一些研究人员还犯了使用机器学习进行推理的错误。像深度学习这样的机器学习技术不仅因为是难以解释的黑盒而臭名昭著,试图根据输入和输出解释数据也类似于将相关性视为因果关系。
本质上,我们应该首先确定我们试图回答的问题,然后才能决定要使用的分析类型。基于 Gartner 分析优势模型,如果单纯想知道“发生了什么”,数据挖掘等描述性分析就足够了;但是如果我们想问“为什么会发生”的问题,诊断分析如统计分析对于解释是必要的;然而,如果我们想预测“将会发生什么”,机器学习等预测分析是更合适的方法;最后,如果需要知道“应该做什么”,将需要说明性的分析,如运筹学中的建模和模拟,以建议最佳行动方案。
Gartner Analytic Ascendancy Model.
诚然,这些各种各样的流行词汇和技术术语之间的界限可能比我所描绘的更加模糊。但是,我不认为这些术语是可以互换的,而是希望这个模糊的嗡嗡声的简单说明有助于区分它们。这将有助于更好地理解它们的用途,从而使它们的使用更加精确。
参考文献&延伸阅读:
[## 数据分析、数据分析、数据挖掘、数据科学、机器之间的区别是什么
数据分析,数据分析,数据挖掘,数据科学,机器学习,大数据和…
www.mo-data.com](https://www.mo-data.com/what-is-the-difference-between-data-analytics-data-analysis-data-mining-data-science-machine-learning-big-data-and-predictive-analytics/) [## 机器学习与统计学:何时使用每种方法
机器学习和统计学哪个好?希望这个问题的措辞突出了它的…
医疗保健. ai](https://healthcare.ai/machine-learning-versus-statistics-use/) [## 机器学习与统计学——硅谷数据科学
两位作者,一位机器学习实践者和一位长期合作的专业统计学家,解开了…
www.svds.com](https://www.svds.com/machine-learning-vs-statistics/) [## 意义点:统计学与机器学习
本月
www.nature.com](https://www.nature.com/articles/nmeth.4642) [## 机器学习、数据科学、运筹学——有什么区别?
机器学习、数据科学和运筹学是在不同行业中被大量使用的术语。
revenueanalytics.com](https://revenueanalytics.com/machine-learning-data-science-and-operations-research-whats-the-difference/) [## 为什么统计学、机器学习和运筹学作为独立的实体脱颖而出
似乎现在从事统计、机器学习和运营研究的人都认为…
stats.stackexchange.com](https://stats.stackexchange.com/questions/234863/why-do-statistics-machine-learning-and-operations-research-stand-out-as-separat) [## 机器学习在运筹学中是如何使用的?
机器学习(ML)可以在运筹学(OR)中使用。ML 可以用来调优特定于域的…
www.quora.com](https://www.quora.com/How-is-machine-learning-used-in-operations-research)
最初发布于:https://learn curily . WordPress . com/2018/11/04/fuzzy-buzzwords-in-data-science
模糊字符串匹配
原文:https://towardsdatascience.com/fuzzy-string-matching-in-python-68f240d910fe?source=collection_archive---------2-----------------------
Photo by Romain Vignes on Unsplash
使用 Python 查找与数据中的模式近似匹配的字符串。
Python 中 fuzzywuzzy 的介绍
作为一名数据科学家,您不得不从各种来源检索信息,要么利用公开可用的 API,要求数据,要么只是从网页上抓取您自己的数据。如果我们能够将这些信息组合起来,并且在数据中没有任何重复,那么所有这些信息都是有用的。但是我们如何确保没有重复呢?
我知道… “咄!您可以使用一个函数来检索所有唯一的信息,从而删除重复的“”。嗯,这是一种方法,但是我们的函数可能无法分辨出像“巴拉克·奥巴马”这样的名字与“巴拉克·h·奥巴马”是同一个名字,对吗?(假设我们正在检索世界上最著名的人的名字)。我们可以清楚地看出这些名字是不同的,但它们可能指的是同一个人。那么,我们如何匹配这些名字呢?
这就是模糊字符串匹配的用武之地。这篇文章将解释什么是模糊字符串匹配及其用例,并给出使用 Python 库 Fuzzywuzzy 的例子。
模糊逻辑
模糊(形容词 ) :难以感知;模糊或不清楚
-*基百科
模糊逻辑是多值逻辑的一种形式,它处理近似的推理,而不是固定和精确的推理。模糊逻辑值的范围在 1 和 0 之间。即该值的范围可以从完全真到完全假。相比之下, 布尔逻辑 是一种二值逻辑:真或假通常分别表示为 1 和 0,它处理的是固定和精确的推理。模糊逻辑倾向于反映人们如何思考,并试图模拟我们的决策,因此它现在正导致新的智能系统(专家系统)。
因此,如果我们使用模糊逻辑比较两个字符串,我们将试图回答问题“字符串 A 和字符串 B 有多相似?”、并重新表述为“字符串 A 和字符串 B 是一样的吗?”使用布尔逻辑时。
模糊字符串匹配
模糊字符串匹配,也称为近似字符串匹配,是寻找近似匹配一个模式的字符串的过程。该过程具有各种应用,例如拼写检查、 DNA 分析和检测、垃圾邮件检测、剽窃检测等等
Python 中的 Fuzzywuzzy 简介
Fuzzywuzzy 是一个 python 库,它使用 Levenshtein Distance 来计算序列和模式之间的差异,该库由 SeatGeek 开发并开源,seat geek 是一种从互联网上寻找活动门票并在一个平台上展示它们的服务。他们面临的一个大问题是,他们的博客上所描述的相同事件的标签。这和我在文章开头给出的例子是一样的,一个实体,比如一个人的名字,在不同的来源上可以有不同的标签。
安装
要安装库,您可以使用 pip:
pip install fuzzywuzzypip install python-Levenshtein
例题
首先,我们必须导入模糊的模块:
from fuzzywuzzy import fuzz
from fuzzywuzzy import process
现在,我们可以通过使用以下方法获得两个字符串的相似性得分两个方法 ratio()或 partial_ratio():
fuzz.ratio("Catherine M Gitau","Catherine Gitau")#91fuzz.partial_ratio("Catherine M. Gitau","Catherine Gitau")#100
你可能想知道为什么分数不一样。这是因为 fuzz.ratio()方法只是使用difflib.ratio.
来计算两个输入字符串中标记的某种排序之间的编辑距离。fuzz . partial _ ratio()接受最短的字符串,在本例中是“Catherine Gitau”(长度 14),然后将其与“Catherine M. Gitau”中所有长度为(14)的子字符串进行匹配,这意味着与给出 100%的“Catherine Gitau”进行匹配。你可以随意摆弄琴弦,直到掌握要领。
如果我们在一个字符串中交换两个名字会怎么样?在下面的例子中,我把“Catherine Gitau”这个名字换成了“Gitau Catherine”。让我们看看分数:
fuzz.ratio("Catherine M Gitau","Gitau Catherine")#55fuzz.partial_ratio("Catherine M. Gitau","Gitau Catherine")#60
我们看到这两种方法给出的分数都很低,这可以通过使用token _ sort _ ratio()方法来纠正。这种方法试图说明无序的相似字符串。例如,如果我们再次使用上述字符串,但使用token _ sort _ ratio(),我们会得到以下结果:
fuzz.token_sort_ratio("Catherine Gitau M.", "Gitau Catherine")#94
如你所见,我们得到了 94 分的高分。
结论
本文介绍了模糊字符串匹配,这是一个众所周知的问题,是建立在 Leivenshtein 距离。从我们所看到的,它计算两个字符串有多相似。这也可以通过找出将一个字符串转换为另一个字符串所需的运算次数来计算。例如,对于名称“巴拉克”,可以将其拼写为“巴拉奇”。只需要一个操作来纠正这一点,即在末尾添加一个 K。您可以使用 R 中的 stringdist 库来尝试一下:
adist("Barack", "Barac")
#[1]
来源
https://marcobonzanini . com/2015/02/25/fuzzy-string-matching-in-python/
直到下次:)
用 Keras 对银河动物园进行分类
原文:https://towardsdatascience.com/galaxy-zoo-classification-with-keras-219184aff581?source=collection_archive---------2-----------------------
A typical spiral galaxy, we’re going to build a convolutional neural network to classify these guys. Taken from wikipedia.
完整的代码可以在我的 Github 上的【https://github.com/jameslawlor/kaggle_galaxy_zoo】找到。
我最近参加了几周的关于实用深度学习的杰瑞米·霍华德和瑞秋·托马斯优秀 fast.ai MOOC。我过去学过几门神经网络课程,虽然我理解数学和理论,但我没有太多使用常用工具的实践经验,比如 TensorFlow 和 keras。这个课程用一种“自顶向下,代码优先”的方法完美地填补了我的知识空白,非常令人耳目一新。
所以直接进入正题:本课程第二课的作业是为我们选择的数据集创建一个深度学习模型。我选择 Kaggle 银河动物园竞赛是因为太空相当酷。比赛是大约 4 年前直播的,所以我来参加派对有点晚了!在这篇文章中,我将介绍我的解决方案,它的 RMSE 得分为 0.12875,这将使我处于排行榜的上半部分。对于几个*时的工作来说还不错。当然还有很多需要改进和试验的地方,我将在最后谈到,但我对结果很满意,因为我现在对 keras 更加熟悉和熟悉了。我在谷歌的前几页没有找到任何关于银河动物园与 keras 比赛的代码或演练,也许是因为比赛已经有 4 年了,而 keras 是两年前才发布的,所以希望这对试图解决这个问题的人有用。
数据准备
在训练集中有大约 60,000 幅图像,在测试集中有 80,000 幅图像,每幅图像都是 424x424 彩色 JPEG。通过检查图像,您可以看到只有图像的中心部分是有用的。我决定围绕中心裁剪为 212x212,并向下采样到一半分辨率,以减少我们必须调整的参数数量。
Left — An example from the training data. We only really care about the centre of each image, so crop and downsample to get the image on the right.
完成此操作的代码如下:
另一个考虑是,我们有大量的训练和测试数据,太多了,无法加载到 GPU 内存中。我编写了一些批处理生成器来顺序抓取一批图像,通过图像处理代码运行它们,然后将它们的解码数据传递给卷积神经网络(CNN)。下面是批处理生成器代码的一个例子
模型架构
Similar to my model architecture. Taken from http://blog.christianperone.com
我决定采用类似 VGG16 的 CNN 架构——这是一堆卷积/Max 池层,后面是一些大型 FC 块和最后一个 37 级 sigmoidal 激活层,用于预测星系级概率。我选择这种架构是因为众所周知 VGG16 在图像问题上做得非常好,网上的共识似乎是它在易于实现、训练时间和体面的结果之间取得了良好的平衡。有一种方法可以通过简单的导入在 keras 中加载预训练的 VGG16,然后您可以通过微调来适应您的问题,但我选择通过从头构建和训练来做一些困难的事情。所以你不会认为我在 GPU 时间上浪费金钱是完全疯狂的,我的动机是我想看看一个“新鲜”的神经网络在问题中会如何表现。我的理由是,因为我们希望我们的网络在星系数据集中检测和识别的功能和类别与 ImageNet 相比并不庞大,ImageNet 是“真正的”可预加载 VGG16 经过数周训练的,包含来自狗或牙齿或战舰的对象。因此,我们不应该需要长时间的训练来获得好的结果,因为输入之间的差异不是很大。我会试着想象一些模型过滤器来测试这个想法,并在我有时间的时候编辑它。这是我心中的一个很好的例子https://blog . keras . io/how-convolutionary-neural-networks-see-the-world . html。
基于模型简单的想法,如果我们移除或减少一些层,看看我的模型如何工作会很有趣。我有一种预感,完整的 VGG16 架构对这个问题来说可能是大材*用,但 YOLO 正如古语所说。
下面是实现该架构的代码:
我用的是 RMSProp 优化器,学习率 1.0e-6。这是训练的样子,我从训练集中拿出 4000 张图片放在一个单独的文件夹中进行验证。
在具有 1/2 K80 GPU 的 Azure NV6 机器上,训练进行了大约 90 分钟,进行了 42 个周期(提前停止)。
摘要
这个模型获得了 0.12875 的 RMSE 分数,从开始编码到提交 Kaggle 只需几个*时,这将使我处于排行榜的上半部分。有很多方法可以改进模型,我可能会回来,特别是数字预测——这些不是典型的概率,而是不同类别之间的加权。37 个类中的每一个的简单的 sigmoid 是天真的,没有捕捉到这个条件。我还想尝试更简单的架构、改进的图像处理等等。我可能会在某个时候回来,因为我确实很喜欢它,但现在我专注于完成 fast.ai 课程。
如果你对改编我的方法感兴趣,代码在我的 Github 上,在 https://github.com/jameslawlor/kaggle_galaxy_zoo。同样值得一提的是竞赛获胜者 Sander Dieleman 的评论,可以在他们位于 http://benanne.github.io/2014/04/05/galaxy-zoo.htmlT2 的博客上找到。
“激发”我的技能
原文:https://towardsdatascience.com/galvanizing-my-skills-a4b4d1175cb4?source=collection_archive---------5-----------------------
在我旅程的第一集,我描述了为什么地球科学家会成为伟大的数据科学家。我们有“硬”东西的工作知识,在商业环境中处理真实的数据和随之而来的一切。然而,在获得数据科学领域的机会之前,我们许多人都必须填补一些空白。
这些差距中最大的是正式的编码经验。我们中的许多人在我们的地球科学职业生涯中创建了相当复杂的模型,然而,在我们的生活中只编写了一两行代码(除了无处不在的“Hello,World!”).总的来说,我们的模型是由隐藏在可爱的用户界面下的复杂程序(Petrel,EarthVision 等)促成的。)使用地质统计学方法,我们对“黑匣子”中发生的事情有了基本的了解。
另一个缺口是我喜欢称之为“经典”统计。我们的优势之一是应用概率和统计,然而,当谈到学术环境中的经典统计时,我们可能会有所欠缺。我们肯定在日常生活中应用了概率和统计,但是正式的术语和如何与统计学家交谈可能是缺乏的。
为了填补这些空白,我四处寻找能够帮助像我这样的职业生涯中期的专业人士填补成为正式数据科学家所需的空白的项目。
我不会深入讨论过多的“训练营”项目的复杂利弊(例如,激励、Metis、数据孵化器、Insight 等)。).然而,我会用我的逻辑来选择训练营而不是传统的学术项目。
这实质上归结为 三个 重大原因:
- 学位要求——我已经有了一个基于论文的研究生学位。许多数据科学职位的最低要求是科学/定量学科的硕士或博士学位。回去找一个专业的全职 MS 看起来有点矫枉过正,而且时间:花费:支出比率也不理想。另一方面,训练营允许更快的周转时间来更快地进入市场。
- 时机——许多专业的微软项目要么是兼职的,要么要求在放弃薪水的情况下搬到不切实际的地方。兼职项目对于职业人士来说很好,但是对于我们这些需要休息的人来说,就不太实际了。“训练营”项目,如“激励”(我选择了其中的一个),平均 12-16 周,对促进职业转型更容易接受。
- 课程——作为地球科学家,我们已经有了很多“软”技能。深入研究经典概率和统计的编码和复习正是我们所需要的。这正是激励项目所提供的,也是我选择参加的原因。
我可以详细讲述一下我从《激励计划》中学到了什么,数学,建模和职业发展,但这最好留给另一个系列。在这里,我将简单地强调一下 我是如何利用这个项目为自己的数据科学职业定位的。
经过大量研究后,我计划中的第一个目标是,不仅要让自己获得激励,更重要的是,在入学时取得成功。对我来说,这需要在我已经掌握的最基本水平之外学习 Python(“你好,世界!”).
Early adopter of computing and always learning… (circa 1986)
我花了几个月的时间吸收了我能从初级和中级 Python 的 Coursera 、 Udacity 、 MITedX 等网站上找到的所有在线课程和内容。请注意,您可以找到很多资源来直接进入 Python 和 R 的机器学习包,但是我发现从长远来看,首先学习编程基础要好得多。
如果没有这些编程基础,您将无法掌握必要的技能:
- 与软件工程师进行智能交流。数据科学并不总是仅仅操纵数据和对数据建模。在许多公司,您需要与软件工程师一起工作,以确保您的模型部署顺利进行。在地球科学中,这类似于与油藏和钻井工程师一起工作。优秀的地球科学家需要具备工作知识,了解将我们的地质模型升级到油藏模型比例的含义。同样的原理,不同的领域。我们现在需要知道我们的代码对更大的产品的影响。如果我们孤立地存在,集成到一个无缝的(没有错误的)产品中会困难得多。
- 快速学习新语言。目前,大多数数据科学家都在结合使用 Python、R 和 SQL。然而,这种情况将来可能会改变。这不像在地球物理学中,非常复杂的地震处理算法仍然是用 Fortran 或 C++编写的。数据科学家需要充满活力,能够灵活应对技术的变化。学习编程的基础知识将使你为这些变化做好准备。
- 面试成功。不管你喜不喜欢,白板面试仍然是数据科学中的王者。许多数据科学家都有软件工程背景。作为地球科学家,我们可能在面试的解释和商业方面有优势。然而,在一天结束的时候,人们会根据我们在白板上解决常见(和不常见)算法谜语的能力来评判我们。在不使用图书馆的情况下,了解计算机编程的基础知识是在科技世界的面试环境中必备的技能。
学习可能需要一点时间和投入,但是一点点就足以获得第一个“官方”数据科学职位。
在熟悉了基础知识之后,我准备申请 getting。
在 While 项目中,我学习了我所知道和喜爱的机器学习算法的数学基础。我在项目的“休息时间”练习编程技能,这样我就能更快地识别面试中的谜语模式。和许多人一样,白板面试不是我的强项,我很早就发现了这一点,并稳步提高自己的技能,向未来的雇主证明我有编码能力。
在此期间,我还不得不撕毁我的简历。
它始于这样一个问题:作为一名数据科学家,我如何有效地沟通和推销自己?但它比这更深入:
- 作为一名地球科学家,我如何有效地传达我的成就和所做的事情实际上是数据科学?
- 在一个不披露信息和受 SEC 影响的世界里,我如何量化自己在石油和天然气领域的成就?
- 我如何强调快速掌握新的语言和概念,并满足公司的编码/技术要求?
你看,“科技”公司倾向于对候选人有一个大而全面的“愿望清单”。他们希望员工能够用有限的数字和 KPI 有效地传达他们的成就。在石油和天然气行业,对我来说,我拥有的最切实的 KPI 是,我们的评价井计划在撤资之前减少了对另一口约 3 . 5 亿美元井的需求(真实故事)。
使用 KPI 简明扼要地突出我们的成就需要创造力。这里面有很多要解开的,具体来说就是 两个 的问题:
- 行业之间的知识差距。就地球科学家而言,石油和天然气与科技。
- 地球科学家和数据科学家的角色和职责之间的知识差距
我通过创造性地从科技行业的角色和责任的角度撰写简历,完成了第二个目标。然而,第一个更难得到。
这就是我不断扩大的人际网络发挥作用的地方。联网 !
为了我的项目,我搬到了西雅图,所以这给了我一个极好的机会,让我走出自己的舒适区,结交新朋友。我开始参加聚会,特别是*狗(普吉特湾编程 Python)*组,该*组每月在科技公司轮流召开会议。
我不是最外向的人,我实际上渴望和平和安静来充电。定期去社交网络不在我的舒适区。然而,为了最大限度地提高我的成功概率,我需要建立网络来了解我在广阔的数据科学领域中的位置。
看,课程的实际内容并不像课程的结果那样吸引人(即使在数据科学领域,课程内容也是非常标准的)。你如何学习这门课程将会获得最高的投资回报率。
我接触 galilet 不仅是为了“激发”我的基本技能,更是为了促进我与公司和其他数据科学家的对话。
Presenting a personal project at Google for PuPPy Monthly MeetUp
请在未来几周继续关注,我将详细介绍我是如何获得数据科学工作的。
继续看第三集、第四集、第五集、第六集、第七集和第八集。
《权力的游戏》第一季首播推特分析
原文:https://towardsdatascience.com/game-of-thrones-s7e1-twitter-analysis-8dcd0bec958b?source=collection_archive---------5-----------------------
超过 215,000 条推文之后…
冬天来了。《权力的游戏》第七季到了,我们最爱的剧集只剩下 12 集了。现在是时候坐下来享受我们拥有的一切了。或者我们可以深入数据,做一些分析。一模一样,对吧?
“死亡是如此可怕的终结,而生命却充满了可能性”——提利昂·兰*斯特
因此,在几乎没有方向或最终目标的情况下,我开始思考在最近的首映式上做一些有趣的探索性数据分析的最佳方式。经过一番思考后,显而易见的选择似乎是 Twitter:在这里,普通大众、不经意的观察者和铁杆粉丝都聚集在一起,实时发表他们的观点和印象。我一定会发现一些有趣的见解。所以让我们开始吧。
剧透
如果你还没有看过这一季的首播,并且打算看的话,我建议你不要再看这个,打开你朋友的 HBO GO 账户,你已经用了 6 个月了,看看吧。然后,也只有到那时,再回到这篇文章,享受我的数据驱动的 S7E1 的精彩。
收集数据
因此,在几乎没有搜集数据的实际经验的情况下,我经历了提取数千条与《权力的游戏》相关的推文的过程。我选择只抓取那些包含#GoT 的推文来识别相关推文。事实证明这是足够的,因为我在一周内提取了超过 215,000 条推文,更重要的是超过 25,000 条来自首映期间的直播推文。这些将成为我分析的基础。
首映前
可以想象,随着时间的推移,围绕首映式的兴奋情绪越来越强烈。我在下图中捕捉到了这一点,该图显示了 7 月 10 日至 7 月 18 日这一周的相关推文数量。
你可以在 11 日和 13 日看到一些*光点。老实说,我不太确定这些是由于什么,可能是普遍的炒作或标题/文章被释放。更明显的是,我们可以看到一个明显的高峰发生在该集播出供公众欣赏的一个*时内。让我们来看看那个*时的实时推特。
整个事件中的活动
总而言之,我们可以从这一集期间来自世界各地的大约 25000 条与《权力的游戏》相关的推文中了解到很多。正如您在下面按分钟细分的图表中看到的,活动并不完全一致。
因此,很快,您可能会注意到 2-4 个突出的局部最大值。我回头看了看在这些高峰期到底发生了什么。事情是这样的:
0-4 分钟内(约 800 次提及):剧集开始,艾莉亚发表重要演讲。
8-12 分钟(约 1300 次提及):介绍开始了,我们听到了期待已久的甜美曲调。
34-36 分钟(约 400 次提及):山姆通过一个非常无趣的蒙太奇出场。
40-44 分钟(约 600 次提及):艾德·希兰莫名其妙地出演了一个*角色。
关键词分析
越过一般的活动分析,我们可以通过查看所有这些推文的内容更深入一点。我选择使用 nltk 包来创建一个包含这一集所有 tweets 的语料库。
必须采取一些措施来验证这个语料库是有意义的。我使用 nltk 内置功能立即删除了所有典型的停用词。接下来,我删除了三个字母以下的单词。我还删除了英语词典中没有的单词。最后,我重新添加了任何特定的“权力”术语,比如角色的名字。由于某种原因,“丹妮莉丝”不在英语词典中,但那是另一个讨论的话题。
现在我们已经清理了这个超过 50 万个不同单词的巨大语料库,可以开始理解这些数据了。为了将语料库可视化,我创建了一个包含前 20 个最常用单词的数据框架,并附带一个单词云。
所以你可以看到,明显的领先者是“首映”(有道理)。接下来,我们有几个其他有趣的数据点,以“红色”、“乔拉”和“瓦里斯”的形式出现。稍后我会更深入地分析角色,但所有的“红色”推文都可能指向艾莉亚在这一集开始时精心策划的红色婚礼的复仇。此外,如果我没有提到《希兰》排在第 12 位,被提及超过 4000 次,那我就大错特错了。尽管拿着吧。
人物提及
在一集的结尾,我们经常会问我们的朋友和自己:“哪个角色赢得了(或输掉了)那个夜晚?”。通过数据分析,可以更清晰准确的回答这个问题。
这些结果让我特别感兴趣。乔拉以超过 6000 次的提及位居第一(这让他非常沮丧)。而瓦里斯以几乎相同的票数位居第二(不太记得为什么会这样了…有人知道吗?).之后我们有了常见的嫌疑人:艾莉亚、琼恩、瑟曦和珊莎。令我惊讶的是,丹妮莉丝在关于性格的推特上排名第七,尽管她是最后 15 分钟的焦点。我猜测这主要是因为拼写她的名字很困难,但我可能错了。最后但并非最不重要的(好吧,可能是最不重要的)是阿多——他被提及超过 500 次,勉强挤进前十。阿多。
把它包起来
所以在这篇文章结束的时候,我想反思一些事情。首先,通过这个项目,我意识到大量使用时,像推特这样看似微不足道的事情中蕴含的力量。我计划通过 Twitter 和其他媒体利用这一概念,继续我的工作和创意实践。
展望下周,我在考虑为每一集发布一个类似的帖子,然后在这个短暂的赛季结束时将数据汇编成一个更大的项目。如果有任何想法或问题,请联系我,以便我进行探讨。另外,请随时查看我的代码。
感谢阅读!如果你喜欢这篇文章,请继续向鼓掌按钮展示你的爱。对更多的帖子感兴趣吗?请务必关注我并订阅下面的我的简讯以接收任何新内容。更多关于我和我在做什么的信息,请查看我的网站。
《权力的游戏》第 7.5 季第 1 集
原文:https://towardsdatascience.com/game-of-thrones-season-7-5-episode-1-27bdc906e6df?source=collection_archive---------10-----------------------
绘制大图
在第一集里,我们将使用动画展示整个网络在七季中的“拓扑结构”,来鸟瞰不断发展的角色共现网络。这些图表也将向我们展示随着故事的展开,人物的位置在网络中是如何变化的。
Character Co-appearance Network
阅读网络
在深入研究之前,先了解一下图表的内容,以帮助理解它们。
节点。节点代表单个人物,七季共有 557 个。为了给每个角色的重要性一个感觉,出现在更多场景中的角色的节点更大,主要角色(147 个常规和重复出现的角色)的节点为绿色。次要角色的节点是粉红色的,当然也很*。
角色在第一次出现在场景中时进入网络,在被杀或以其他方式死亡时退出(100 个主要角色的命运)。次要人物如果连续五集没有出现,以后也不会再出现,也会退出。那些后来重新出现的仍然存在,缺失的连接向图的中心漂移,直到它们重新出现并重新连接。
棱角分明。边缘连接在特定场景中共同出现的角色。在 557 个字符中,有 3849 条边(~ 7/字符)。当角色第一次一起出现在场景中时,边缘被添加。主要角色之间的边被认为是永久的——一旦两个主要角色同时出现,除非其中一个或两个被杀死或死亡,否则会有一条边将他们连接起来。如果角色没有连续五集同时出现,或者一集或两集退出网络,则涉及次要角色的边缘被移除。这种差异反映了主要角色之间的联系可能会持续下去,尽管他们最近没有共同出现——例如,史塔克或兰*斯特家族成员之间的联系,尽管他们走的是分开的(和断开的)道路。
边缘也标志着关系的性质。较厚的边表示更频繁的共同出现,因此关系“更强”。领带的基调反映在它们的颜色上,较红(较蓝)的边缘表示在武装场景中更频繁(不太频繁)的共同出现,因此更具战斗性(亲切)的关系。略带紫色的边缘混合了友好和敌对的共同出现,因此可能反映了一起对抗敌人的朋友,或者后来成为敌人的朋友(或者反之亦然)。
布局。使用“力导向”算法生成图形,在该算法中,未连接的节点被推开,而连接的节点被拉在一起。这赋予了字符在图形中的位置以意义。图中同处一地的角色在场景中更频繁地一起出现。并且,当一组字符倾向于彼此频繁地共同出现时,这些字符将聚集在一起。与倾向于不一起出现的字符一起出现的字符占据这些字符之间的位置,这些字符本身位于图形的不同区域。
现在你知道了“阅读”图表所需的一切,并赋予图表中角色的位置和运动以意义。多看几次图表动画,看看你是否能跟踪图表中展开的故事线,并理解演变中的网络。
图表特征和趋势
在未来的剧集中,我们会对该图的几个特征感兴趣。我将在这里介绍其中的几个,这样我们可以在以后的章节中更深入(更精确)地挖掘它们(以及其他的)。
*集团。一个值得注意的特点是,该网络在该系列的大部分时间里都以“派系”结构为特征,在这种结构中,相对不同的角色群围绕支撑他们的主要角色展开故事线——正如边缘颜色所显示的那样,一些角色比其他角色更加暴力。
这些“集团”和他们的中心人物,在下一张图中更容易看到,其中经常一起出现的人物群被涂上相似的颜色。因为他们的成员主要是彼此共同出现,所以这些集团(及其成员)在网络中彼此相对孤立——以丹妮莉丝·坦格利安为中心的集团是最孤立的。
Character Co-appearance Network with Clusters Colored
该图的拓扑结构在第七季发生了转变,因为该图汇聚成一个由所有主要角色组成的单一集团。这一转变反映了在面对日益增长的白人沃克威胁时,先前分离的故事线和他们的中心人物合并成一个单一的联盟。
*天地。第二个是,在第七季融合之前,几个主要角色,而不是属于一个*团体,跨在他们之间,将他们的故事线连接起来,并将他们的主要角色连接成一个单一的网络图。例如,提利昂·兰*斯特在网络中跨越多个派系,席恩·葛雷乔伊也是如此。另一些人,比如琼恩·雪诺,既以*集团为中心,又在他们之间牵线搭桥。
这种拓扑结构——由少量桥连接起来的密集互连的集团——是标志性的“*世界”网络,在社会(以及生物和技术)系统中无处不在。因此,有趣的是,这种拓扑结构也出现在这些虚构的土地上,不管有没有该系列创作者/作者的意图。
在*世界网络中,尽管大多数节点主要连接到集团内相对少量的其他节点,但是它们之间的路径很短,因为少量节点“桥接”该集团。*世界网络结构表现出重要的特征,包括信息在网络中快速传播只需几步,以及对节点丢失的鲁棒性,其中大多数对路径的长度或网络的集团性几乎没有影响。
当艾德·史塔克(奈德·史塔克)失去理智,以及他的妻子和儿子凯特琳和罗柏在“红色婚礼”中死去时,这种坚强都显而易见。从动画中可以明显看出,图形的拓扑结构几乎没有因为它们的退出而改变。因为与他们一起出现的角色也倾向于彼此一起出现(他们的边缘颜色相对统一——灰色、紫色;凯特琳和罗柏,绿色),它们的边是“冗余的”,网络拓扑对它们的消亡是鲁棒的。
相比之下,像提利昂·兰*斯特这样的“桥接”角色的边并不是多余的,它们的丢失会极大地改变拓扑结构。
( )没有提利昂的世界 。为了说明这一点,我贴了一张图,图中提利昂受到了“乔治-贝利-这是一种美妙的生活”的待遇。除去他的节点和所有的边,图的中心大部分是空的,派系几乎没有联系(但对席恩·葛雷乔伊来说,尤其是在红色婚礼之后),并且在第七季汇合之前一直如此……这很大程度上取决于提利昂的联系,在他缺席的情况下不太可能。可以在这里 查看 。)
短暂的联系。突出这些网络特征的另一种方式是,如果主要人物和次要人物没有在连续五集内共同出现,或者其中一个或两个人物退出,则通过丢弃所有边缘,在故事的更窄时间窗口内绘制共同出现网络。
5-episode edge windows.
因为这个图表是基于最近的共同出现(活跃的联系)绘制的,所以派系之间的联系更为稀疏,正如那些从一个派系跳到另一个派系的桥牌人物一样,他们通过网络与人物建立联系。例如,观察提利昂·兰*斯特在网络中的移动。结果是他在早期图表中的中心位置,这些图表假设这些联系是持久的而不是短暂的。
接下来:第二集——这是一个冰与火的*世界
在下一集(下面的链接),我将更详细地研究全球网络结构特征的“统计力学”,量化其各种特征——密度、聚类、路径长度和*世界性——并可能开始挖掘一些主要人物的网络位置和联系。
同时…
新来 GoT 第 7.5 季?在这里查看预告片,以及剧集:
第 1 集— 描绘大局
第 2 集— 冰与火的*世界
第 3 集— 人物网络地位和优势
第四集— 谁会熬过第八季?杀死的网络位置
对“应要求”这一集有什么想法?留下评论,我会看看我能做些什么…
《权力的游戏》第 7.5 季第 2 集
原文:https://towardsdatascience.com/game-of-thrones-season-7-5-episode-2-dd518f6b03c?source=collection_archive---------12-----------------------
这是一个冰与火的*世界
在第一集中,我们使用图表来展示冰与火之地七季中网络的拓扑结构,鸟瞰了不断发展的角色共现网络。我们看到的是一个不均匀的,移动的,模块化的结构。许多角色聚集成密集的*集团,主要是彼此共同出现,由一些共同出现的角色连接,这些角色通过相对较短的路径连接那些不经常共同出现的角色。所有这些特征都是“*世界”网络的特征。
很容易看出这种社会结构是如何普遍出现的。人们倾向于形成“社区”,其中每个人都认识其他人,每个社区的成员倾向于与其他社区的人有一些关系,而一些人——例如政治和社区领导人——与许多社区的人有联系。
在第 2 集,我们将更详细地研究这种拓扑结构,并量化它的一些关键特征——密度、聚集、桥接和路径长度——以得出关于共现网络的更坚定的结论,并准备挖掘网络位置和单个角色的优势。
背景
*世界效应首先出现在斯坦利·米尔格拉姆(1967)的经典研究中,他描述了一个实验,在这个实验中,信件在熟人之间传递,他从中得出结论,许多对看似遥远的人被非常短的熟人链连接起来。在他的研究中,这个链条的典型长度大约是 6,这个数字已经成为民间传说,并在约翰·格尔(1990)的戏剧《六度分离》中被载入史册。尽管米尔格拉姆的研究中存在偏见——例如,路径较长的字母更容易丢失或遗忘——但他的结果通常被视为支持假设的证据,即人口中的大多数人可以通过熟人的短连接路径连接起来,即使是在包含社会结构(如孤立社区或地理和文化障碍)的大型人口中。米尔格拉姆将这种现象称为“*世界效应”。最近, Watts 和 Strogatz (1998) 将这种描述正式化,将*世界定义为展示短路径和社会结构组合的网络,后者的特征在于高度的网络聚集。这两个条件现在被作为*世界的标准定义,揭示了网络拓扑对于理解*世界的本质和运作的重要性。(改编自鲍姆等人,2004 年)。
密度
人物之间的联系有多密集(或者反过来说,稀疏)?我们可以通过考虑组成网络的节点(字符)和边(共现)的相对数量来回答这个问题。这些按情节显示在图 1 中。
Figure 1. Character Co-appearance Network — Nodes & Edges
在第一季和第二季中,角色的数量增长很快,然后随着角色引入的放缓和死亡人数的增加,增长速度会变慢。在第六季达到 126 个角色的高峰后,随着故事情节的趋同,角色的数量急剧下降,留下了一些角色,另一些角色死去。在第七季结束时,剩下的角色比第一季第一集中出现的要少。(也许并不令人惊讶——在第一集介绍的 44 个角色中,只有 13 个出现在第七季的大结局中!)
共同出现的数量遵循相同的一般模式,保持每个角色的平均边缘数量相对恒定在 8-9 之间,尽管在第一季和第七季中更大,在 13-16 之间。
Figure 2. Character Co-appearance Network — Density
总的来说,边与节点的比率表明连接相对稀疏,或低密度网络。也就是说,实现了相对*部分的可能边(即,如果所有节点都具有与所有其他节点的边)。例如,考虑第 35 集,其中 110 个角色的共同出现创建了 1092 条边。虽然这看起来是一个很大的数字,但它仅代表 11,990 个可能边的 9%的密度(即 110*109)。图 2 显示了网络密度在第 2-6 季中介于 8-10%之间,而在第 1 季早期则下降了 30%以上。密度在第七季中跃升,在最后两集达到近 50%。这一跳跃与我们在《T2》第一集中观察到的转变相吻合,当之前独立的故事线合并,中心人物在面对日益增长的白人沃克威胁时结成联盟时,图表崩溃成一个单一的集团。
使聚集
尽管总体稀疏,但共现网络的图形仍然揭示了一种不均匀的结构,具有稀疏链接的密集聚集区域。但是,共现网络的聚集程度——以及连接的不均匀程度——如何呢?
为了回答这个问题,我们可以计算网络的聚类系数,它测量“封闭三元组”(所有边都被画出的三角形)与“开放三元组”(缺少一条边的三角形)的比率。如果所有的三联体都是“开”的,系数为 0,如果所有的三联体都是“闭”的,系数为 1。当我们在网络图中看到聚类时,我们可以期望找到许多三角形。在共现网络中高比例的“封闭”三元组意味着字符倾向于彼此共现。
Figure 3. Character Co-appearance Network — Clustering
图 3 显示了每集的聚类系数以及“随机网络”的聚类系数,该“随机网络”具有与每集中实际网络相同的边数和节点数。随机网络的聚类系数往往很*,这为评估实际网络中的聚类提供了一个基准( Watts & Strogatz,1998 )。
共现网络的聚类系数在 0.7-0.8 之间,但在第一季开始和第七季结束时略高(当时网络密度也更高)。这意味着网络中 70-80%的“三胞胎”是“封闭的”。随机网络的聚类系数低得多,在 0.08-0.09 之间,除了在第一季开始和第七季结束时。因此,对于实际的同现网络,聚类系数要大 8-10 倍。
桥接
既然我们已经量化了集群网络区域,那么让我们来看看贯穿和链接它们的连接。在第一集的图表中,这些“桥梁”似乎是由几个字符与那些往往不会相互出现的字符共同出现造成的——它们形成了“开放”的三元组,通过一条短路径将原本不相连的字符连接起来。
我们可以通过考虑同现网络中的介数和度中心性的分布来量化这些桥的性质。在下面给出的这些分布的图表中,只包括主要的字符(规则的和重复出现的);次要角色在这两个指标上都得分较低,增加了许多接近零的观察值。
Figure 4. Character Co-appearance Network — Betweenness
中间性衡量一个字符位于其他字符之间最短路径上的程度,分数越高表示最短路径越多。如图 4 所示,分布是高度倾斜的。大多数主要人物没有最短路径,少数人有几条最短路径,极少数人有多条最短路径。这种偏斜使得少数字符具有个体意义,它们的高度中间性赋予了它们控制信息流和资源的潜力。
Figure 5. Character Co-appearance Network — Degree
度是一个给定的字符与其他字符一起出现的次数。如图 5 所示,学位分布也是倾斜的,尽管不太严重。大多数主角每集和 10 个或更少的其他角色一起出现,少数有 10-20 个,极少数超过 20 个。
这些分布的偏斜度的差异反映了一些高度特征位于几条最短路径上。这些字符占据了图形中密集聚集的区域;丹妮莉丝·坦格利安就是一个例子。除了龙之母,低度节点往往属于密集集群,这些集群通过高度(和高介数)节点相互连接。
这种偏斜对网络中节点之间的路径长度有影响。当偏斜度很高时,网络的“直径”——节点之间的最大距离——很大程度上不受网络规模增加的影响( Cohen & Havelin,2003 )。因此,这些分布的偏斜度意味着在共现网络中字符之间的步数相对较少。
路径长度
路径长度是最后的*世界拼图。我们可以通过将字符之间的所有最短路径相加并除以路径总数来计算字符之间的路径长度。下面的图表显示了每集的结果。并且,再次作为基准,对于具有相同数量的节点和边的随机网络。正如我们所见,虽然随机图往往具有较*的聚类系数,但它们也往往具有相对较*的平均路径长度( Watts & Strogatz,1998 )。
Figure 6. Character Co-appearance Network — Path Length
如图 6 所示,角色之间的平均路径是 2-3 步,除了在第一季和第七季,它低于 2 步。虽然比表征随机网络的短路径稍长,但是桥确实导致了预期的短距离偏斜。沿着这些短路径,只需几步,信息就能迅速到达网络的其他遥远区域。
世界真*
在数量上,我们发现同现网络的特征是高度模块化的,与具有相同数量的节点和边的随机网络相比,具有更高的聚类和几乎一样短的平均路径长度。我们可以使用这些见解来计算*世界商 (Q)以量化共现网络拓扑的“*世界性”。
q 比较实际(a)网络与节点和边数相同的随机(r)网络的聚类系数(CC)和平均路径长度(PL)。具体来说,Q = [CC(a)/CC(r)]/[PL(a)/PL(r)]。一个网络的 CC(a) >> CC(r)和 PL(a) ~ PL(r)越多,它就越“*世界”,Q 就越大,如果 Q > 1,就说这个图是一个*世界。
Figure 7. Character Co-appearance Network — Small World Quotient
从我们早期对聚类和路径长度的研究中,我们知道 CC(a)比 CC(r)大 8-10 倍,并且 PL(a) ~ PL(r),所以我们预计 Q > 1。
图 7 证实了这一点。在第一季和第二季中,q 从 2 上升到 8,然后在 5-8 之间波动,直到第六季的 9 左右达到峰值,然后迅速下降。到第七季结束时,Q 值已经下降到接近 1,这个*世界崩溃了,因为核心人物在面对白衣行者威胁时形成的联盟将网络折叠成了一个*团体。
好吧。那就证实了。这的确是一个冰与火的*世界……嗯,对于七季中的大部分来说。
接下来:第 3 集—网络地位和优势
在下一集(下面的链接),我们将把注意力转向网络中的角色。谁在网络中处于有利位置?谁失去或浪费了一个网络优势?谁有权力控制信息和资源的流动?谁能赢得信任和忠诚?他们是如何拥有(或失去)这些网络优势的?
同时…
新来 GoT 第 7.5 季?在这里查看预告片,以及剧集:
第 1 集— 描绘大局
第 2 集— 冰与火的*世界
第 3 集— 人物网络地位和优势
第四集— 谁会熬过第八季?杀死的网络位置
对“应要求”这一集有什么想法?留下评论,我会看看我能做些什么…
《权力的游戏》第 7.5 季第 3 集
原文:https://towardsdatascience.com/game-of-thrones-season-7-5-episode-3-fcf1f35af7c0?source=collection_archive---------14-----------------------
字符网络的位置和优势
在第 2 集中,我们量化了第 1 集中介绍的人物同现网络图拓扑的关键特征,对其结构得出了更为确切的结论,为挖掘个体人物的网络位置和优势奠定了基础。
我们发现共现网络是高度模块化的,密集聚集的区域由穿过它们的纽带稀疏连接。我们还发现这个网络是高度倾斜的——大多数角色在角色之间只有很少的连接或最短的路径,而少数角色有很多连接和最短的路径。这种偏斜也意味着网络中的字符之间相对较少的步骤,我们确实发现了这一点。
最后,为了量化共现网络的“*世界性”,我们将它的聚类和路径长度与节点和边数相同的随机网络进行了比较。同现网络具有*世界的特征,它比随机网络更聚集,但路径长度相似。然而,我们也看到,*世界结构在第七季结束时崩溃了,因为主要人物建立了更广泛的联盟来面对白行者,网络折叠成一个单一的*团体。
唷。我们在第二集做了很多!
在第三集,我们将注意力转向主要角色——常规角色和循环角色——在角色共现网络中的位置。谁处于有利地位?谁有机会控制信息和资源的流动?谁能赢得信任和忠诚?
网络位置和优势
在我们深入角色的网络位置之前,我们需要知道要寻找什么;也就是说,什么样的立场可能是有利的。社交网络研究表明,网络位置可以影响其居住者的结果,并指出两种位置——密集和稀疏——可以为其居住者创造不同的优势和更好的结果。
紧密结构中的网络职位——由与已经联系在一起的其他人的关系组成的职位——通过促进互惠规范和制裁机制、信任和共同身份的发展而使其占有者受益,所有这些都促进了高水平的合作和协调,从而可以促进合作并限制机会主义。
稀疏结构中的网络职位——由与其他人没有已经链接的关系组成的职位——通过将他们置于原本不相连的群体之间,让他们接触并有机会控制网络中流动的各种信息和资源,使他们受益,所有这些都能够更好地预测问题并利用新的机会。
听起来熟悉吗?我当然希望如此!这些位置反映了*世界网络的两种定义结构,它们由密集的参与者集群组成,跨越这些集群的稀疏的连接穿过它们,通过短路径将本地集群的不同区域绑定到一个更大的网络中,并充当信息交换和控制的管道。*世界网络——像角色共同出现网络——因此为两种利益提供了机会。
*世界结构的重要性在于,通过结合密集和稀疏,它们创建了一种“混合”关系结构,该结构通过提供跨网络区域的不同信息的有效通道来增强信息扩散和处理属性,同时保持高度信任和信息共享的好处。
因此,虽然密集和稀疏网络位置通常被描述为竞争选项,迫使在信任、信息共享和协作的好处与信息和资源访问和控制的好处之间进行权衡,但是来自*世界网络的基本见解表明,它们是互补的好处,并且密集和稀疏的组合在网络位置中可能是有利的。
网络位置(如网络结构)可以通过减轻过度密度(如隔离和约束)和过度稀疏(如机会主义和不稳定性)的影响,并通过将本地集群内密度的信任和整合优势与跨集群的稀疏关系的信息访问和代理优势结合起来,获得优于纯密集或稀疏位置的优势。
字符网络位置——密集还是稀疏?
那好吧。那么《王座》的游戏主角们都为自己开拓了哪些网络阵地呢?
Figure 1. Character Co-appearance Network Clustering and Betweenness
所有种类都出现了!图 1 显示了《权力的游戏》中 13 个关键角色的网络位置的密度(聚类)和稀疏性(介数)的混合特征。聚类和介数是跨集的平均值,节点大*反映了跨集的累积程度。女性角色的节点是蓝色的;对于男性,红色。人物的位置从密集(丹妮莉丝·坦格利安)到稀疏(提利昂·兰*斯特),混合两者来填充极端之间的连续体。其他 134 个常规和重复出现的字符主要在左上角添加观察结果;因此,关键字符往往表现出最高的介数(和最低的聚类)。
Figure 2. Character Co-appearance Network Clustering and Betweenness Animation
图 2 显示了这些位置随时间的演变,绘制了集与集之间的时间路径。他们的地位相对稳定,但有几个角色发生了实质性的变化。其中,丹妮莉丝·坦格利安的中间值在第六季早期上升,聚类值下降。从第五季中期到第六季中期,提利昂·兰*斯特的中间时段也出现了高峰。在下一集,我们将探究这些运动背后的共现模式的变化,以更好地理解这些网络位置是如何发展的,并考虑如何进行“网络运动”来改善它们。
在第二集中,度和介数分布的偏斜度表明,一*部分角色可能特别有影响力,因为他们有潜力控制网络上的信息流和资源——以及冰与火的土地。这些“歪斜的少数”是谁?
Figure 3. Character Co-appearance Network Degree and Betweenness
图 3 描绘了同一组关键字符的度和介数。程度和中间性是跨集平均的。节点大*和颜色和以前一样。在这些关键人物中,提利昂·兰*斯特的度和介度都是最高的;丹妮莉丝·坦格利安最低。一群角色——瑟曦和杰米·兰*斯特、珊莎和艾莉亚·史塔克、琼恩·雪诺——平均学历很高,但中间程度各不相同。正如我们在第二集中看到的这些度量的分布,高中间性比高程度更罕见。剩余的 134 个常规和重复出现的字符主要将观察结果添加到图的左下方。因此,这些关键人物构成了“扭曲的少数”。
Figure 4. Character Co-appearance Network Degree and Betweenness Animation
图 4 显示了它们在七个季节中的位置变化。除了第四季的后半段,提利昂·兰*斯特占据着媒介度最高的网络位置。在前 5 个赛季中,琼恩·雪诺在两个*度上都有所上升,但随后在两个*度上都有所下降。艾莉亚、布兰和珊莎·史塔克都有 4-5 集的高间隔期,杰米(但不是瑟曦)兰*斯特也是如此。这些关键角色的度和介数在第七季中有所收敛和下降。这反映了*世界的崩溃,我们在第一集第一集第一点看到了这个世界的崩溃,在第二集第三点 T2 中量化了这个世界的崩溃,这是这些角色在面对白色行者威胁时结成联盟的结果。如上所述,在下一集,我们将研究这些运动背后的变化共存,以更好地理解它们的发展,并考虑如何制定有益的运动。
人物网络优势——死了还是活着?
既然我们已经看到了关键人物在共现网络中占据的位置范围,我们是否也可以观察到与不同位置相关的不同结果?密集持仓有利吗?稀疏的?混血儿?那“倾斜的少数”呢?一个衡量网络位置好处的标准是评估它们与角色生存的关系。在 147 个经常出现的角色中,有 100 个死了(只有一个死于“自然”原因)。被杀的角色和幸存的角色是否占据了不同类型的网络阵地?
Figure 5. Dead or Alive? Character Co-appearance Network Clustering and Betweenness
图 5 显示了聚类和介数的混合,它们表征了所有常规和重复出现的字符的网络位置。像以前一样,聚类和介数是跨集平均的,节点大*反映了跨集的累积程度。然而,在这个图中,幸存角色的节点是蓝色的;对于被杀的角色,红色。
这种模式似乎很清楚:群聚杀死,中间保护。除了少数例外,被杀死的角色具有高于 0.5 的聚类和低于 0.02 的介数。聚类在 0.7 以上的性状很少存活。除了奈德、凯特琳和罗柏·史塔克、巴利斯坦·赛尔弥,还有拉姆齐·波顿、瑞卡德·卡史塔克、杰诺斯·史林特和拉斯特。琼恩·雪诺的代号也是“被杀”,但他的复活符合他在网络中的地位。
混合位置似乎也是有益的,其位置具有聚类(0.4-0.6)和中间性(0.02-0.04)混合特征的角色存活率相对较高。
在冰与火的土地上,中间性提供的控制信息流和资源的力量似乎比集群带来的信任、合作和忠诚利益更重要。
Figure 6. Dead or Alive? Character Co-appearance Network Degree and Betweenness
Figure 7. Dead or Alive? Character Co-appearance Network Degree and Clustering
那么那些有高度和/或中间性的扭曲的少数字符呢?如图 6 所示,这种模式可能更加清晰。在 100 个被杀死的常规和重复出现的角色中,只有两个占据了平均度超过 20 且介数超过 0.02 的网络位置——奈德·史塔克和琼恩·雪诺,当然,他还活着回来。
为了完整起见,图 7 显示了度和聚类的模式。如图 5 所示,虽然聚类低于 0.5 的字符很少被删除,但低聚类比高介数提供的保护更有限。不过,唯一被杀的角色平均等级超过 20,聚集度低于 0.6 的还是奈德·史塔克和琼恩·雪诺。
因此,看起来网络位置确实对冰与火之地的生存至关重要——度和介数保存;群聚杀人。
即将上映:第四集——生还是死?
在下一集,我们将把注意力转向更详细的角色死亡建模,以及为第七季结束时还活着的主要角色生成生存预测。
同时…
新来 GoT 第 7.5 季?在这里查看预告片,以及剧集:
第 1 集— 描绘大局
第 2 集— 冰与火的*世界
第 3 集— 人物网络地位和优势
第四集— 谁会熬过第八季?杀死的网络位置
对“应要求”这一集有什么想法?留下评论,我会看看我能做些什么…
《权力的游戏》第 7.5 季第 4 集
原文:https://towardsdatascience.com/game-of-thrones-season-7-5-episode-4-abb12ee1e43d?source=collection_archive---------10-----------------------
谁会在第八季中幸存?杀人的网络位置
在第三集中,我们描述了《权力的游戏》中关键人物的网络位置在密度和稀疏度方面的优势。
为了衡量角色的网络优势,我们比较了被杀和幸存角色的网络位置。模式很清楚:占据密集位置的角色更有可能死亡,那些占据稀疏位置的角色更有可能存活。在冰与火的土地上,基于中间性的信息和资源访问和控制似乎胜过了与集群相关的信任、忠诚和合作。“扭曲的少数人”——凭借对网络上信息和资源流动的潜在控制而获得影响力的高级角色——也更有可能在第七季结束时活着。
在第 7.5 季的这一集中,我们将注意力转向一个更详细的建模,即角色的生存如何受到他们在共同出现网络中的位置的影响。我们将使用两种机器学习分类器算法——N朴素贝叶斯和决策树——根据每个主要(定期和反复出现的)角色的网络位置的关键特征(聚类、中间和程度),以及他们的性别和家庭地位(伟大、次要、普通),预测他们最有可能的结果——死亡或活着。然后,我们将应用这些预测来评估第八季中关键幸存角色的可能命运。
朴素贝叶斯分类器
朴素贝叶斯是一种简单的算法,作为概率分类器工作。它通过确定角色属性与死亡或活着相关联的概率来预测每个角色最有可能的结果(死亡或活着),并将角色分配给具有给定属性的最大概率的结果。贝叶斯分类器表现很好,根据性别、家庭状况和网络位置,对第一至第七季 140 个角色中的 114 个(82.4%)角色的命运进行了正确分类。
性别和房屋
让我们简单地开始,通过考虑男性和女性角色最可能的结果,以及那些大家族成员和那些*家族成员或平民的角色。
Figure 1. Gender, House and Character Survival
图 1 显示了基于性别和房子的预测:来自大房子的男性最有可能被杀。
男性角色在死者中占了很大比例,占所有死亡人数的 77%,但占幸存者的 70%,因此大约有 10%的人死于非命。相比之下,女性在死者中的比例较低,占死亡人数的 23%,幸存者的 30%,因此死亡的可能性比活着的可能性低 30%。
大家族成员的角色也过多,占所有死亡的 44%,但占幸存者的 36%,因此大约有 20%的人死于非命。相比之下,较*家族的成员和平民在幸存者(64%)中所占的比例要高于死亡人数(56%),因此死亡的可能性比活着的可能性低 15%。
给定这些分布,朴素贝叶斯分类器预测大家族的男性成员最可能的结果是被杀,而不是大家族成员的女性成员最可能的结果是活着。
网络位置
现在让我们看看基于角色网络位置关键属性的概率——它们的聚类、介数和度。
聚类。为了加强《T2》第三集中的图形分析,图 2 表明聚集对你不好。在图中,无论蓝线(死亡的密度)在红线(活着的密度)之上,朴素贝叶斯算法都预测最有可能的结果是死亡。
平均聚类系数大致大于. 7 的角色(即 70%的三和弦是闭合的,见第 2 集)更有可能被杀死,而聚类系数较低的角色更有可能活着。请注意,差异非常大,聚类非常高的角色被杀死的可能性是两倍多,而聚类低的角色存活的可能性是三倍或更多。
Figure 2. Clustering Coefficient and Character Survival
聚类与角色命运的关联表明,通过增加聚类,*世界结构的崩溃和网络在第七季结束时折叠成一个单一的*团体,这是为了面对白行者而建立的联盟(见第 2 集)可能会降低许多角色的生存机会。
介于两者之间。图 3 显示了中间性的分类。再次强调《T2》第三集中的图形分析,介于和之间对你有好处。平均介数大于大约 0.02 的角色更有可能活着,而那些介数分数较低的角色更有可能被杀死。事实上,介数低于 0.02 的角色被杀的可能性是普通角色的两倍多,而介数较高的角色存活的可能性是普通角色的 10 倍。
Figure 3. Betweenness and Character Survival.
正如第七季结尾*世界的崩溃增加了许多角色的聚集,这个网络过渡也降低了他们的介数。考虑到中间性与角色被杀的可能性之间的联系,联盟的融合很可能通过其对中间性和聚类的影响减少了许多角色的生存机会。
度。最后,我们来看看学位的分类。比如中间性,再次加强第三集的图形分析,度数对你有好处。平均度数大于 12 左右的人物更有可能活着,而度数较低的人物更有可能被杀死。等级高于 12 的角色存活的可能性是 10 倍甚至更多,而等级较低的角色被杀的可能性是 2-3 倍。
Figure 4. Degree and Character Survival.
角色的等级和角色被杀或活着的概率之间的这种联系加强了我们在第三集的图形分析中看到的“少数偏斜者”的生存优势。
决策树分类器
决策树分类器构建了一个分割规则的层次结构,根据角色属性的值将结果(死亡或活着)分开。基于最大化信息增益来确定分裂规则。在每个阶段,所选择的分裂规则是导致最大信息增益的规则;也就是最同质的分支。
图 5 显示了基于角色性别、房屋状况和三个网络位置属性的决策树。
Figure 5. Decision Tree — Killed or Alive?
在树的顶部,第一个分裂规则是字符的平均度数是大于还是*于 29.05。如果更大,则最有可能的结果是存活(在这种情况下,这是唯一的结果——终端节点上的条形指示存活(红色)/死亡(蓝色)结果的分布,以及通过其厚度指示结果的数量)。如果低于(或等于)这个值,最有可能的结果是更复杂。
第二个分裂是平均聚类是大于还是*于. 495。如果低于(或等于)该值,最可能的结果取决于进一步的分裂规则:如果平均度大于 10.85,则存活;如果低于(或等于)该值,则终止。同样,更高的学位与活着联系在一起。如果聚类大于. 495,最有可能的结果取决于介数是大于还是*于. 042。
如果大于这个值,最有可能的结果是被杀死——当伴随着高聚类时,高介数是无益的。如果介数低于(或等于). 042,最可能的结果取决于关于聚类的进一步规则。如果聚类非常高(> . 679),最有可能的结果是被杀死。从末端节点的钢条厚度可以看出,这是大多数杀戮发生的条件。
如果聚类介于*于(或等于). 679(根据第二个规则,也大于. 495)之间,则性别开始起作用,最有可能的结果是女性角色活着,而男性角色进一步取决于程度、家庭地位和中间性。
预言
现在,让我们利用这些结果来做一些预测——对于幸存的主要角色来说,最有可能的结果是什么——死了还是活着?
朴素贝叶斯分类器假设特定属性的值独立于其他每个属性的值,但是我们可以将每个属性的概率相加,以获得不同属性组合的联合条件概率。
表 1 显示了 18 个重要角色被杀的概率。概率是用三种方法计算的。第一,基于角色在第 1-7 季出现的所有剧集的平均网络位置特征,第二,基于第 7 季所有剧集的平均网络位置,第三,基于第 7 季最后一集的网络位置。因此,这三种可能性使我们能够看到人物最有可能的命运的任何趋势。
Table 1. Predicted Probability of Being Killed, Selected Characters
几个角色被杀的概率一直很低;例如,琼恩·雪诺和提利昂·兰*斯特。贝叶斯模型以很高的可信度预测了他们的生存(以及琼恩·雪诺的复活)。另一些则显示出时间范围内的上升或下降趋势。例如,越来越有信心预测其灭亡的山姆威尔·塔利,以及相反生存变得越来越确定的丹妮莉丝·坦格利安。
对于几个角色来说,贝叶斯分类器预测第 1-7 季最有可能的结果是被杀,但在击败这些可能性后,他们在第 7 季结束时的前景有所改善。例如,Yara Greyjoy 的死亡被充满信心地预测——她几乎是——但她在第七季结束时的网络位置的变化极大地改善了她的未来前景。托蒙德·巨人贝恩的命运也发生了类似的逆转……如果事实证明他确实在柏林墙倒塌后幸存了下来。
兰*斯特家的命运呈现出不同的轨迹。虽然瑟曦和詹姆的生还被充满信心地预测,但他们的命运在第七季结束时变得更加扑朔迷离,詹姆的命运实际上是一场掷硬币的游戏。瓦里斯勋爵的前景同样不确定,艾莉亚、珊莎·史塔克和席恩·葛雷乔伊的命运也和瑟曦一样。
显然,第七季结尾*世界网络崩溃的影响(见第二集)以不同的方式改变了角色的网络位置,并因此将他们可能的命运带向不同的方向。事实上,通过提高聚集度和降低介数,这种网络转变降低了许多角色的生存机会——尽管对大多数人来说,还不足以推翻他们预测的命运……
最后一集的预测是,波隆和山姆威尔·塔利最有可能被杀死——山姆威尔有很高的信心。此外,如前所述,杰米·兰*斯特和瓦里斯勋爵的命运很不确定。与此同时,瑟曦·兰*斯特和史塔克姐妹最好仔细评估他们的网络位置——并战略性地改变它们,以便重新获得自信的预测。
即将推出:第 5 集——生存:网络生存策略
在下一集,我们将把注意力转向主角们为了决定他们自己和彼此的命运而可能采取的战略行动。
同时…
第 7.5 季新?查看第四季 预告片 及前几集:
第 1 集— 描绘大局
第 2 集— 冰与火的*世界
第 3 集— 人物网络地位和优势
对“应要求”这一集有什么想法?留下评论,我看看我能做些什么…
《权力的游戏》单词嵌入,R+L = J 吗?—第一部分
原文:https://towardsdatascience.com/game-of-thrones-word-embeddings-does-r-l-j-part-1-8ca70a8f1fad?source=collection_archive---------6-----------------------
我们能从 5 本《权力的游戏》书中的单词向量表示中学到什么吗?
I know this is stupid, please read on 😃
剧透警告:这个故事包含了《权力的游戏》第七季的剧透
在我的第一篇关于文本生成的报道之后,我决定学习并撰写关于单词嵌入的文章。单词嵌入是 2013 年(现在是史前时代)的热门新事物。现在,让我们将这一数据科学突破应用于一些愚蠢的事情!
这是一个分为两部分的故事:
-第一部分:单词嵌入?什么?怎么做,为什么?
-第二部分:《权力的游戏》嵌入的乐趣
(代码在此处)在这第一部分中,我们将从快速复习机器学习的字符和单词编码开始…如果你熟悉 NLP,你可以直接进入第 2 部分。
字符编码
机器学习算法(以及一般的数学)处理数字。
在自然语言处理(NLP)中,我们必须用数字,更精确地说是向量(空间中的特定坐标)来表示字符和单词。
当在字符级工作时(比方说在*写字母上),我们必须编码 26 个字符。在这个场景中,“词汇表”是 26 个不同“标记”(“a”到“z”)的列表。因为 26 很*而且容易管理,一个简单的方法是给每个字符在空间中自己的*度。一个字符成为一个向量,在相应的字符坐标中为 1,在其他位置为零:
lowercase alphabet one-hot encoding
从几何学的角度来看,在这个空间中,所有的角色彼此距离相等。我们让我们的算法知道一个“a”与一个“b”无关,更一般地说,所有的字符都是相同的。这种表示词汇表(以及一般的分类变量)的方式通常被称为“一个热点编码”(空间中只有一个坐标是“热点”)。
我们也可以用一*编码,例如用 a = (1), b = (2),一直到 z = (26)。但是在这个空间中,“z”将离“a”非常远,并且“z”是“a”的 26 倍,算法可能认为“z”只是类固醇上的“a ”,这是不正确的。它可以工作,但它不是一个非常明智的表示。
单词编码
回到我们的主要任务,在我们的例子中,我们想要对单词进行编码。《权力的游戏》包含了 12 000 个单词。这些单词中的每一个都必须给定一个空间矢量表示。如果我们“一次性编码”这个词汇,我们将得到 12 000 *空间中的向量。你可以看到它很快失去控制。因此,单词通常被编码在固定的低*子空间中。
另外,这一次,我们的令牌(单词)并不是 100%独立的,有些单词在语义上非常相似。例如,“愚蠢”和“哑巴”的意思差不多。通过一次性编码,我们会丢失这些信息。由于英语中的许多单词都有相似的语义,一种有趣的表示词汇的方法是为相似的单词创建相似的向量。
当单词在一个密集的向量空间中以一个任务表示时(比如保持语义相近的单词彼此靠近),这个过程(和产生的向量)通常被称为“单词嵌入”。
如何构建单词嵌入
有两种众所周知的算法来构建“通用”(多用途)嵌入,谷歌的 word2vec (2013)和斯坦福的 GloVe (2014)。
两种方法都通过两个词共现的程度来量化它们之间的相似性(学术术语是分布假设)。即使创建嵌入向量空间的过程不同,它们也产生相似的向量。以下是每个算法的简化步骤:
- word2vec (skip-gram 模式)采用浅层前馈神经网络(1 个隐层)。对于输入的给定单词,网络被训练来预测词汇表中的每个单词与我们输入的单词一起出现的概率。为了更好地完成这项任务,网络只需要调整一个权重矩阵,这个矩阵来自一个密集的中间隐藏层。一旦经过训练,这个隐藏层就是我们单词的矢量表示。
- GloVe 比较传统(不涉及神经网络),使用矩阵分解。它首先浏览文本,并计算单词对彼此靠近的次数(在给定的窗口中,比如 10 个单词)。这些信息存储在一个叫做“共现矩阵”的结构中。迭代地构建和调整单词向量,以最*化具有高共现概率的单词之间的(余弦)距离。
单词嵌入属性
2013 年,单词嵌入的一个特别之处让每个人都大吃一惊,那就是由此产生的向量空间有很多意想不到的性质。它不*心编码了几个高级语义概念。比如“他”和“她”这样的代词,它们之间的距离非常近(正如所料),但同时,从“他”到“她”(另一个向量)的路径具有惊人的性质。
通过将同样的“他到她”的转换应用到其他事物上,我们实际上是在交换性别。“男人”变成了“女人”,“演员”变成了“女演员”。为了说明这一点,这里是第二部分的一瞥。下面是从《权力的游戏》书籍中构建的单词向量的可视化(仅限):
Illustration of the “gender-swap” relationship (PCA projection of selected Game of Thrones word vectors)
在完全无监督的方式下,一个算法已经编码了“性别”的概念(没有命名),这怎么可能?
你可以把它想象成一个空间,在这里,文字因为不同的原因而相互吸引。让我们以这篇短文为例:
“奈德、凯特琳、布兰和珊莎来自史塔克家族。
劳勃、瑟曦、乔佛里和弥赛菈都来自拜拉席恩家族。凯特琳、珊莎、瑟曦和弥赛菈都是女人。
奈德、布兰、劳勃和乔佛里都是男人。”
通过这篇文章,我们希望来自同一个家庭的人能够相互吸引,同性之间也是如此。
truncated word co-occurrence matrix
左边是一个截断的共现矩阵,只有一些特定的目标词(行)和上下文词(列)。
2-D representation of our words
利用共现矩阵的直接 2-D 近似(PCA 因子分解),我们得到以下单词表示(这种操作显然不同,并且在 GloVe 中更复杂)。在这个二*空间中,有四种“力”在起作用。男人把其他男人拉向他们,与此同时,女人、史塔克和巴拉瑟翁也在这么做。
它达到了一种平衡,巴拉瑟翁在底层,史塔克在顶层,女人在左边,男人在右边,所有这些都没有任何指导。
嵌入捕捉了很多这样的语义关系(或者像一些人所说的“语言规则”)。它们可用于解决单词类比任务,例如:
“a”和“b”相似,就像“c”和“d”相似一样
缺少四个术语之一的示例:
“他”之于“她”,正如“男人”之于>
这被称为“类比推理”,这项任务是由 word2vec 的作者托马斯·米科洛夫等人引入的,他们建立了一个包含大量这些问题的完整的数据集。
在向量算术中,类比“A 之于 B 如同 C 之于 D”翻译过来就是:
B-A~D-C
B-A+C~D 她———“他”+“男人”~女人
我们的四句话单词空间已经可以解决一些问题,比如:
“劳勃”之于“巴拉瑟斯”就像“奈德”之于>
相当于……
“巴拉瑟斯”减去“劳勃”加上“奈德”是多少?
在我们的空间里,它给了我们一个或多或少“斯塔克斯”(tada!).
你可以看到,在我们的短文本例子中已经发生了很多事情,想象一下现在在 5 本书中,或者在*基百科中,也有更多的*度(数百个),让算法有一些空间来表达自己。
理想情况下,要“学习”英语,你必须使用大量的语料库。斯坦福的*组(以及谷歌)提供预训练的单词嵌入,其中语料库包含超过 100 亿个单词(通常来自*基百科)。在我们的例子中,我们只有 1000 万个单词,它们来自一本中世纪的奇幻书(所以请宽容)。
你现在已经准备好第二部分!
奖金:这是无监督学习吗?
Word2vec 通常被认为是一种非常成功的“无监督学习”算法。人们可以理直气壮地说,因为神经网络是用输入/输出对来训练的,以使损失函数最*化,所以训练它们在某种程度上总是一项受监督的任务。
然而,在“手动标记的”和“自动标记的”数据集之间肯定有区别。网络获得其预期输出(也称为标签/目标)的方式完全不同:
- “手动标记”示例:网络被训练为将输入图像分类为包含“狗”或“猫”。为了训练这样的分类器,人们必须手动注释猫和狗的图像来建立数据集。
- “自动标注”示例:在 word2vec 中,有一种巧妙的自主方式来为任何文本生成标签。因此,您可以使用任何想要的数据集,并且不需要人工干预(有些人称之为“自我监督”)。对于时间序列预测或自动编码器来说,情况相对类似。
第一部分到此结束。如果你喜欢,可以关注我的 中 或 推特 获取最新消息。此外,如果你发现有什么问题或者有任何疑问,请在评论区提问。
《权力的游戏》单词嵌入,R+L = J 吗?—第二部分
原文:https://towardsdatascience.com/game-of-thrones-word-embeddings-does-r-l-j-part-2-30290b1c0b4b?source=collection_archive---------8-----------------------
我们能从 5 本《权力的游戏》书中的单词向量表示中学到什么吗?
现在,事情变得严重了。让我们建立我们的向量,并质疑这个空间…
提醒一下,这是一个分为两部分的故事:
第一部分:单词嵌入?什么?怎么做,为什么?
第二部分:权力的游戏嵌入的乐趣
构建嵌入王座的游戏
注意:我尝试的一切都可以在这个库中找到以及训练过的向量。跳进去尝试新事物真的很容易(只是笔记本里的一些*猫、numpy、matplotlib)。如果你发现一些很酷的东西,请告诉我!
一切都将基于《权力的游戏》前 5 本书的 100 *手套单词向量表示。这个主体非常*,只需要一个*时就可以稳定下来。我们现在有 12000 个单词由 100 *密集向量表示:
our 100-D GoT vectors in a dataframe
快速评估我们的矢量
GloVe 的构建使得相似单词的向量在空间中获得相似的方向(它试图最大化它们的点积)。测量方向相似性的一种方法是通过余弦相似性(向量之间的角度)。如果向量具有相同的幅度,则点积和余弦相似度是等价的。因此,要使所有东西都成为点积,第一步是标准化单词向量。
我们现在可以找到与一个已知单词相似的单词,或者我们可能产生的任何向量,就像回答类比问题的那些向量一样。为了检查在这个不寻常的数据集上创建单词嵌入是否完全无用,让我们看看我们的向量在我们之前提到的 Google word analogy 数据集上的表现(第 1 部分)。是一套 19000+字的类比。结果如下:
questions: 4688 filtered out of 19558 (missing words)
accuracy = 9.94% (466/4688)
second-guess accuracy = 14.04% (658/4688)
许多类比是不可检验的,因为有些词不在词汇表中(书中没有提到巴黎或柏林,想想吧)。在其他方面,我们的向量达到了近 10%的精度。这显然很糟糕,但也表明这个向量空间并不是无用的。下面是一些“已解决”的类比:
'man' is to 'woman' as 'husband' is to 'wife'
'boy' is to 'girl' as 'uncle' is to 'aunt'
'falling' is to 'fell' as 'going' is to 'went'
一般注意:我会挑选很多。下面的例子(已经不是特别好了)是我在探索单词 vectors 时发现的最好的例子。
可视化《权力的游戏》单词向量
让我们从一些非常直观的东西开始。我们可以选择一些单词,并将相应的 100 *向量投影到一个更友好的 2 *空间进行绘图。让我们在节目的主要角色上做它。
注意:我不认为全名是单词,从算法的角度来看,琼恩·雪诺是一个 2 字序列(“乔恩”和“雪”)。改变这种行为的一个方法是在我们的文本中用“Jon_Snow”代替“琼恩·雪诺”。在上面的图中,姓氏是手动添加的。所以琼恩·雪诺的矢量可能因为琼恩·艾林而在空间漂移了…
2-D T-SNE projection of the main characters (colored by House)
向量显然不是随机的。我们可以看到同一家族的人物聚集在一起。我们也看到情侣们亲密无间,英雄在上面(是的《GoT》里有英雄)。
我们也可以想象应该成对的单词的二*投影(就像我们在第一部分中所做的)。下面是一个 GoT 房子和它的座位(通常是主城堡)之间关系的图示:
Game of Thrones house-to-seat regularities
extract from my notebook
Bonus: Adjective — Comparative — Superlative regularities
我们还可以尝试另一种很酷的单词向量的二*可视化。我只在 word2viz 项目中见过,不知道它有没有名字。姑且称之为“word2viz”情节。它是这样工作的:
- 你创造了两个有趣的单词向量差异,比如从“女人到男人”的路径和从“邪恶到善良”的路径
- 你选择一些词(让我们以《GoT》的主要人物为例)
- 对于每个单词,计算单词和这两个特殊向量之间的点积
- 您从每个单词中获得的两个值成为二*图中的两个坐标
数学上,对于给定的字向量w:
w。(男 - 女 ) = w 。男 - 女。女人
~与“男人”相似——与“女人”相似这个标量值直观上就是“如何把一个词放在女人对男人的一个尺度上”。这给了我们 X 坐标。如果我们使用 Y 的第二个“概念”,我们将有一个自定义的二*空间,其中单词沿着两个差异轴展开。
这给了我们:
The evil-good axis is not working very well (Cersei and Joffrey #?!)
Westeros places through a 2-D projection on (east-west) and (north-south)
再比如……
我从《权力的游戏》中选取了一些重要的地方,并把相应的向量投射到一个南北向和一个东西向的“文字向量尺度”上。
令人惊讶的是,结果并非完全不一致。
图片来源于 reddit 用户 Selvag(完整地图在此处
找到乔恩的父母
Last known sighting of Jon Snow
剧透回顾:
几年来,雷加·坦格利安(丹妮莉丝的哥哥)和莱安娜·史塔克(奈德的妹妹)可能是琼恩·雪诺的父母,这一直是讨论这一事实的非剧透方式。这个理论在电视剧第六季和第七季中得到了证实。我们现在甚至知道他的真名了!他是伊耿·坦格利安,铁王座的合法继承人,也是他自己孩子未来的第一代表亲!#神魂颠倒
很明显,实际的 R+L=J 向量方程不成立。首先,因为这不是向单词嵌入提问的好方法。它没有利用任何“规律性”。
我们可以选择一个更聪明的方式来提问,比如通过“父亲对儿子”的规律,试着从雷加到琼恩,比如使用从奈德到罗柏的路径。
more clever ways to find family relations
但是,即使这样,它也不会起作用,因为基础材料(当谈论父母身份时,将乔恩放在他父亲附近的单词序列)在书中没有。如果数百万读者找不到它,一个演绎能力较弱的算法也不会做得更好。
它工作的唯一方式是,如果 George R. R. Martin 已经建立了它的 5 本书(和相应的共现矩阵),知道有人会在 100d 训练的手套嵌入上问这个愚蠢的问题。我试过了,我可以确定他没有。
第二部分到此结束。如果你喜欢,可以关注我的 中 或 推特 获取最新消息。此外,如果你看到一些错误,或者如果你有任何问题,请随时在下面发表评论。
参考书目和推荐读物
- “深度学习、NLP 和表示法”,克里斯托弗·奥拉
- 《论词语嵌入》,塞巴斯蒂安·鲁德
- 《word 2 vec 教程》,Chris McCormick
- “手套:单词表示的全局向量”,杰弗里·潘宁顿,理查德·索彻,克里斯托弗·d·曼宁
- “word 2 viz”、朱莉娅·巴兹恩斯卡和皮奥特·米格达
博弈
原文:https://towardsdatascience.com/game-playing-1fc093da36d1?source=collection_archive---------7-----------------------
更多内容请关注http://developercoding.com和http://developercoding.com/AI/
让电脑和你一起玩吧。让我们玩玩人工智能吧。
人工智能中的极大极*算法
在玩游戏时,首先,让我们看看极大极*算法,它将帮助我们找到赢得游戏的最佳移动。在下一课中,我们将看看井字游戏,我们将使用极大极*算法来制作一个无与伦比的井字游戏。
考虑双人游戏,如井字游戏、国际象棋、跳棋等。现在,我们的目标或目的是预测一个将带领我们走向胜利的步骤。如果我们在玩游戏,那么很明显我们想尽可能地增加我们的得分和减少对手的得分,我们将应用这一原则或逻辑并预测移动。另一方面,当对手在比赛时,他会减少我们的得分,增加他的得分。所以这种类型的游戏,我们会在我们的代码中进行模拟,产生所有看似合理的移动,并从中选择一个将我们带到胜利状态的移动。好的,让我们用一个人类的思*过程来思考和比较。当人类玩耍时,他会像
- 好,这是我的状态或情况
- 如果我走这步棋,那么对手就可以走那一套棋,如果他走那一步棋,那么我可以依次走这步棋,我就能赢。
- 人类重复步骤 2,直到他可以找到一个有助于获胜的步骤
基本上,这种思*过程我们想用电脑来刺激。
寻找最优移动的极大极*搜索过程是深度优先和深度受限的搜索过程。minimax 背后的想法是,我们将从当前位置开始,并使用合理移动生成器来生成一组可能的后续位置。
极大极*示例
我们用一个例子来了解一下
假设
一个赢的状态=+10
一个输的状态是-10
平局是 0
左边的棋会被选中,其余的会被丢弃。
具有一般树的极大极*算法的例子:-
博弈论——极大极*
原文:https://towardsdatascience.com/game-theory-minimax-f84ee6e4ae6e?source=collection_archive---------2-----------------------
这篇文章与之前的文章有些不同,之前的文章是基于一些在你的项目中使用的新技术。
有意思?我将从博弈论的角度来描述极大极*算法。只是让你知道你会期待什么:
1.那么什么是极大极*算法呢?
2。计划和代码
3。算法描述
4。优化
4.1。深度优化
4.2。阿尔法-贝塔优化
5。建议
6。结论
对于编码,我们将使用 Objective-C 语言。不过不要担心,会有比代码更多的理论。
方向定了,走吧。
那么什么是极大极*算法呢?minimax——是决策理论、博弈论、统计学和哲学中使用的决策规则,用于最*化最坏情况下(最大损失)的可能损失。最初是为两人零和博弈理论而制定的,涵盖了两人交替行动和同时行动的情况,它也被扩展到更复杂的游戏和存在不确定性时的一般决策。
咕咕咕!
现在我们有了定义,里面嵌入了什么逻辑?让我们假设你正在和你的朋友玩一个游戏。然后你走的每一步,你想最大化你的胜利,你的朋友也想最*化他的损失。最终,对你们两个来说都是一样的定义。你的下一个决定应该是最大化你当前的盈利位置,知道你的朋友在下一步将最*化他的亏损位置,并且知道下一步你也将最大化你的盈利位置…
闻到这种递归的味道了吗?所以这个算法的主要思想是在知道你的对手也会这么做的情况下做出最好的决定。
计划和代码
我们将使用树表示来构建这个算法。每一代新的孩子都有可能成为另一个玩家的下一步。例如,第一代是你的可能步骤,每一步都会导致对手的可能步骤的一些列表。在这种情况下,您的步骤是“父顶点”,而您的对手可能的下一步是它的“子顶点”。
这里是经过所有优化的最终算法代码。
#pragma mark - Public- (NSUInteger)startAlgorithmWithAITurn:(BOOL)aiTurn; { return [self alphabetaAlgorithm:_searchingDeapth alpha:NSIntegerMin beta:NSIntegerMax maximizing:aiTurn];}#pragma mark - Private- (NSInteger)alphabetaAlgorithm:(NSInteger)depth alpha:(NSInteger)alpha beta:(NSInteger)beta maximizing:(BOOL)maximizing { self.currentCheckingDepth = _searchingDeapth - depth; if (self.datasource == nil || self.delegate == nil) { return 0; } if (depth == 0 || [self.datasource checkStopConditionForAlgorithm:self onAITurn:maximizing]) { return [self.datasource evaluateForAlgorithm:self onAITurn:maximizing]; } NSArray *nextStates = [self.datasource possibleNextStatesForAlgorithm:self onAITurn:maximizing]; for (id state in nextStates) { [self.delegate performActionForAlgorithm:self andState:state onAITurn:maximizing]; if (maximizing) { alpha = MAX(alpha, [self alphabetaAlgorithm:depth - 1 alpha:alpha beta:beta maximizing:NO]); } else { beta = MIN(beta, [self alphabetaAlgorithm:depth - 1 alpha:alpha beta:beta maximizing:YES]); } [self.delegate undoActionForAlgorithm:self andState:state onAITurn:maximizing]; if (beta <= alpha) { break; } } return (maximizing ? alpha : beta);}
算法描述
Example
让我们对优化视而不见,从我们需要的初始东西开始。首先,我们需要一个算法,它将基于一个已完成的步骤返回可能的后续步骤列表。我们用它来产生其他的子顶点,如前所述。
其次,我们需要一个算法,将在游戏结束时计算游戏结果的评估。使用该算法,每个顶点(生成的步骤)都将具有赋值的结果。如何分配将在后面描述。
那么这是如何使用树和这些算法的呢?逻辑上算法分为两部分:
1。轮到我们了
2。对手转身
在作为下一个顶点的“轮到我们”上,我们选择一个具有最佳评估值的孩子。然后,由于下一个选择的步骤产生可能的对手步骤及其评估,他将选择最差的评估值(对我们最差意味着对他最好)。
这仅仅意味着我们将从可能的对手步骤中采取最大的评估步骤,而对手将从我们可能的下一步中采取最*的评估步骤。
下一个问题是——我们什么时候评估 step?当它被创造出来的时候,首先想到的是什么。但是等一下,如果它依赖于下一代,或者换句话说依赖于另一个玩家的脚步,我们怎么能马上计算出来呢?意味着我们的步长值将从下一代步长值开始最大化,这是一个对手步长。从另一个角度来看,对手的步长值将是下一代步长值的最*值,这是我的。遵循这个规则,我们可以说评估将在游戏结束时进行,因为它是最终生成的步骤。之后,它将向后展开,用前面描述的计算值标记所有顶点,直到它到达根。
递归生成结束,如果:
我们得到一个赢家
不可能有下一步棋,我们得到一个平局
游戏状态的评估可以用下一种方式计算:
如果我们赢了,那么评估值应该大于某个正值
如果我们输了,那么它应该*于某个负值
如果我们打平了,那么它应该在这个值之间
这意味着我们的位置越好,它的值应该越大。
这个评价可能取决于不同的东西。举个例子,为了评估,我们给它一个我们是赢家的情境。
然后它可以根据下一个值进行评估:
1。我走了多少步才获得胜利
2。你的对手离胜利有多近
等等…
这个函数是算法中最重要的部分之一。组织得越好,你得到的结果就越好。仅依赖于一个特征的函数不会像依赖于十个特征的函数那样精确。此外,您选择用于评估的特征应该具有逻辑意义。如果你认为评估值更大是因为玩家是女性而不是男性,这对性别歧视者有一定意义,但对算法没有意义。结果,你会收到错误的结果。一切都是因为你是个性别歧视者。
太好了!,现在我们大体上理解了算法和它下面的思想。这听起来很酷,但在执行时间方面却没有那么好。为什么?
优化
例如,对于用法,让我们选择“四连胜”游戏。如果你不知道它是什么,这里有一个简短的描述:
“游戏的目标是将你的四个代币连成一条线。所有方向(垂直、水平、对角线)都是允许的。玩家轮流将他们的一个代币放入七个槽中的一个。令牌在槽内尽可能远地下落。拿红色代币的玩家开始。当第一个玩家连上四颗石头时,游戏立即结束。”
让我们想想在这种情况下我们的算法将如何工作。该字段有 7*6=42 个步骤。开始时,每个用户可以做 7 个不同的步骤。这个数据给了我们什么?这些价值观是有史以来最糟糕的。为了让他们更真实,让我们说,例如,游戏将在 30 步结束,平均用户将有可能选择 5 行。使用我们的算法,我们将得到下一个近似数据。第一个用户可以产生 5 个步骤;每个步骤将产生 5 个自己的步骤。现在我们有 5 + 25。这 25 步,每一步可以产生 5 个新的步骤,等于 125 步。这意味着在计算的第三步,我们将有大约 155 步。每下一步都会产生越来越多的可能步骤。您可以使用下一个函数来计算它们:
5 + 5 + 5 + … + 5 ⁰.这个值是巨大的,计算机计算这么多步要花很多时间。
值得庆幸的是,有现成的优化极大极*算法,这将降低这个值。我们很快就会谈到他们两个。
深度优化
很久很久以前,一个非常聪明的人说“为什么我们要一直数到最后?我们能不能在中间的某个地方做个决定?”。是的,我们可以。当然最后精度会比中间某处好很多,但是有了好的算法进行评估,就可以把这个问题降下来。那么接下来我们该怎么办,只不过是多加一条“算法停止”的规则。这个规则是,如果当前步长深度达到临界值,则停止。这个值你可以在测试后自己选择。我想通过一系列的测试,你会发现那些符合你特殊情况的测试。当我们根据这条规则开始评估时,我们把它当作平局。
这条规则并不困难,而且可以真正优化我们的算法。然而,它仍然降低了我们的精度,为了使它工作,我们不能使用超低深度,否则它会给我们错误的,不准确的值。接下来我会告诉你,我们选择了深度 8。尽管花了很长时间才得到最终结果。下一步优化对精度没有影响,并减少算法时间真的很好。它的名字叫阿尔法贝塔,它让我神魂颠倒。
阿尔法-贝塔优化
Example
它的意思很简单。接下来的想法是——如果我们知道已经建立的分支会有更好的结果,就不需要计算下一个分支。这只是浪费资源。想法很简单,实现呢?
为了计数,我们需要将另外两个变量传递给递归算法。
1。α—表示最大化零件
2 的评估值。β——表示最*化部分的评估值
从前面的部分中,我们了解到我们必须走到树的末端,只有这样我们才能评估我们的结果。所以如果我们总是选择左顶点,那么第一次求值将在最后一个顶点上进行。在此之后,评估过程将从它的直接顶点开始,并且将对所有左边的顶点继续,直到一个可能的顶点结束,等等。
我为什么要告诉你这些?这都是因为理解如何评估顶点是至关重要的优化。
为了让我们更容易想象,让我们假设我们正处于最大化的转折点。对我们来说,这意味着我们在计算阿尔法值。该值被计为其后代的所有评估值的最大值。在我们计算阿尔法值的同时(我们在最大化过程中),我们有一个贝塔值。在这里,它表示其父代的当前 Beta 值。太好了!,现在我们知道了α和β在特定时间的含义。为避免误解,α是我们当前的评估值,β是当前的进一步评估值。
最后是优化检查。如果β低于或等于α,我们将停止对所有下一个子代的评估。
最后是优化检查。如果β低于或等于α,我们将停止对所有后代的评估。
为什么有效?因为β已经*于α——它的后代的值,同时α被计为可能的后代值的最大值。这意味着现在我们步骤的评估值不能低于当前值。从另一个角度来看,我们现在拥有的 Beta 是我们父代的当前评估值。从目前我们正在最大化的观点来看,我们可以理解我们的父代正在最*化,这意味着它将选择其当前值和其子代计算值的最*值。
将所有这些放在一起——因为我们知道我们的计算值高于父值,所以我们做出决定,它不会选择我们作为它的下一个可能步骤(它有更好的后代,如果选择它们,它的值会更低)。从这个角度来看,做下一个计算是荒谬的,因为它们不会改变最终结果。所以我们,作为父-子,我们停止所有的计算并返回当前值。利用这一点,我们的父母将比较我们和当前的最佳选择。通过前面描述的逻辑,它将选择其当前值。
使用这种优化,我们可以削减巨大的分支,并节省大量的工作,不会对最终结果产生任何影响。
建议
太好了!,现在我们知道了两种优化方法,可以让我们的算法运行得更快,我想给你一个建议。通常,当机器做出选择时,真正的用户需要一些时间来决定下一步做什么。我们可以利用这段时间为下一步的决定做准备。
因此,当我们做出选择时,让我们继续为所有可能的用户选择而努力。这给了我们什么?
1。它们中的许多已经从以前的用户迭代中计算出来了。
2。当用户选择他的选择时,我们将继续我们的计算。这将增加我们的树的深度,换句话说,准确性。
最后,当用户做出选择时,我们可以简单地切断所有其他未被选择的分支,只继续选择一个分支。
这很好,但接下来让我们对我的假设做出一个总体结论——不要每次轮到你的时候都开始你的算法。让它在游戏中运行一次,当用户选择某个步骤时,获取它的计算数据,并继续我们的计算,直到结束。
有人会说,它有严重的记忆问题。是的,但这只是一个建议,你可以结合两种解决方案,找到最适合你的时间,内存和你的具体情况的准确性。
此外,我建议在一个新线程中对每个可能的步骤进行计算,但这是一个完全不同的故事。
结论
您应该在哪里使用这些信息?在任何地方,你都必须根据用户的行为做出决定。最常见的可能是游戏,但是然后,你可以用你的幻想把它整合到一个地方,在那里你必须反思任何执行的动作。你唯一需要理解的是两个互相“博弈”的部分的算法。
结束了!
https://nerdzlab.com
博彩业:好的、坏的和丑陋的
原文:https://towardsdatascience.com/gaming-industry-the-good-the-bad-and-the-ugly-47c8e1244e24?source=collection_archive---------3-----------------------
Credit image: Pixaby.
我目前在奥地利一家名为 BongFish 的游戏公司工作,为一个 AAA 级未公开的标题管理数据。虽然我被聘为数据标签员,但我也与其他部门接触,因此我也在公司执行其他活动。
我决定写今天的游戏行业,因为它围绕着许多人的梦想,他们渴望最终从事对他们有意义的事情。很少有其他行业像游戏行业一样引起如此大的兴趣。
的确,我热爱我的工作,游戏公司有一些很酷的东西,让工作变得更加愉快。然而,我必须诚实地向你展示同一个故事的两面。但是不要害怕,这篇文章并不意味着以任何方式阻止你申请游戏工作室。我在这里的意图实际上是给你一些见解,一旦到了那里,你可以期待什么。
让我们从头开始。游戏行业的收入每年都在增长,2017 年全球收入预计将达到 1089 亿美元。很自然,新的工作室正在快速涌现(查看 Gamedevmap.com 网站,获得世界各地游戏工作室的完整列表),并承诺在接下来的几年里保持利润丰厚。因此,游戏行业对高技能员工的需求正在增加。
机会不仅对开发人员来说是充足的,对艺术家、营销人员、人力资源专家和项目经理也是如此。然而,工作室通常选择雇佣有经验的员工,因为团队内部培训人员需要花费大量精力,尤其是在制作阶段的中期。
随着数字发行的兴起,许多独立公司正在冲浪,并将他们的游戏上传到 Steam 等平台上。因此,公司可以通过广告和游戏内购买赚钱,用户可以以可承受的价格从大量游戏中受益。在过去,游戏都是盒装的,与主机分开销售,尽管对主机的炒作仍然是一件大事,但它们不再是玩的唯一出路。
如今,无论你的口袋有多大,成为一名游戏玩家都是可能的。此外,游戏工作室正在将其活动扩展到移动和社交游戏,让人们可以通过移动和平板设备玩游戏。
游戏产业从未如此有利可图,专家称游戏的繁荣将持续更长时间。所以让我们深入游戏工作室,看看为一个游戏工作室工作是什么样子的。
关于游戏工作室
每当我听人们谈论游戏公司时,我总有这样一种印象,人们正在忘记有一种东西将地球上的每一个企业团结在一起,那就是利润。把一个游戏工作室想象成一个开发产品来赚钱的公司。为了保持现金流,工作室需要创造一个成功的游戏,能够产生足够高的收入来支付生产成本(开发人员,艺术家,测试人员和许多其他运营费用)。
但是我们不应该浪漫化,人们不是被雇来在工作时间玩游戏的,也不总是他们会产生他们下一个最喜欢的游戏。我明白,当我们帮助开发一个我们喜欢自己玩的游戏时,这很棒,但实际上,我们将在一个不完全是我们最喜欢的游戏中工作,或者如果我们不开发它,我们可能不会玩它。
开发游戏和其他任何行业一样,因此工作室会开发对他们有利可图的东西。
就我而言,我不得不说,我目前从事的这个项目有点幸运,但事实上,我并没有把它作为我工作满意度的一个条件。如果你正在考虑一个游戏公司的职位,但你只做你目前玩的游戏,你可能会限制自己永远不会真正深入游戏行业,因为你把自己限制在几个职位上。
主要有四种不同类型的游戏工作室:发行商、游戏开发工作室、独立公司和移动游戏公司。
出版商是大玩家,他们生产最昂贵的图书,他们在市场营销上投入大量资金,以保证他们(非常高的)投资回报率。出版商通常支付最高的薪水,并以拥有令人惊叹的基础设施而闻名。然而,发行商决定不在内部制作游戏是很常见的。一般来说,他们外包游戏开发公司,让他们的游戏部分或全部在外部制作,这种做法被称为外部开发。
反过来,独立工作室以数字方式制作和发布他们的游戏,他们是相当*的公司,通常是独立的开发者。与出版商相比,独立工作室的预算有限,并且负责制作、发行和在线营销他们自己的游戏。独立工作室的好处在于,他们通常比出版商更乐于接受新想法。
另一类上,有手游公司。他们制作可以在移动设备上玩的游戏,这些游戏可以在 Play Store、App Store 和移动版社交媒体网站上轻松找到。
快速提醒一下,还有赌博游戏公司、教育游戏公司、制作供精神疾病患者玩的游戏的公司……不胜枚举。
在游戏工作室工作
娱乐业是你此生能找到的最令人兴奋的职业。你能想象自己为一件通常以娱乐为目的的事情工作吗?这就是游戏玩家在游戏工作室工作时对自己的想象。事实上,我不能责怪他们,让你的名字出现在一场比赛的片尾字幕中是一次难忘的经历。更不用说有机会玩一个你自己为其发展做出贡献的游戏了,太棒了!
然而,关键时刻和高裁员率可能是真实的。它们的出现是因为游戏开发是由发布组成的,在制作过程中,可以雇佣更多的员工来处理紧急需求和紧迫的截止日期。一旦制作结束,游戏最终发布,公司必须削减成本,直到下一个制作开始,所以裁员发生。
如果你想在游戏公司工作,请做好准备,游戏行业的挑战很大,由于市场需求越来越大,艺术家必须不断超越质量。开发人员会遇到多种技术障碍,包括新工具的实现。变化每周都在发生,候选人应该通过无组织的方式学习。如果你是那种不适应修改的人,那么你可能会发现在游戏行业很难生存。
为了保险起见,总是要问你的面试官你是否被某个特定的项目雇佣,如果是的话,项目什么时候结束,项目结束后公司对你有什么计划。
游戏工作室的招聘流程
游戏行业的招聘过程很艰难,这并不奇怪。这并不是说你在准备其他工作面试时不会有不好的时候,但是游戏工作室知道将要面临的挑战。合适的员工应该不仅仅是一个游戏爱好者,而是一个拥有额外精力的高技能专业人士,最重要的是一个团队成员。
事实上,许多工作室已经意识到,伟大的游戏玩家不一定会成为伟大的员工,所以记住最近发布的游戏不足以在面试中获得职位。另一方面,如果你真的不喜欢游戏,你可能很难向面试官解释为什么你认为你是合适的候选人。
除了消极的一面之外,游戏行业还有一些不可否认的东西,游戏工作室往往拥有友好、热情和积极的员工,这些人对自己的工作充满热情,每天都带着灿烂的笑容工作。除此之外,游戏工作室的工作环境具有典型的休闲感觉良好的环境,这将使你想起童年时代舒适多彩的卧室。更不用说许多同事带到办公室来庆祝每一次冲刺结束的美味了。
At the office
如果游戏行业适合你或不适合你,我认为只有你有能力回答这个问题,但如果我从所有这些中得到一个信息,我会说游戏行业,像任何其他行业一样,肯定有其好的,坏的和丑陋的一面,询问人们,获得信息,分析利弊,继续前进。
你有什么经验可以分享吗?在下面给我们写评论吧!
我没有回答你的疑问?请在下面留下您的问题!
在 Tensorflow 后端使用 Keras 的 GAN 示例
原文:https://towardsdatascience.com/gan-by-example-using-keras-on-tensorflow-backend-1a6d515a60d0?source=collection_archive---------0-----------------------
生成对抗网络(GAN)是深度学习领域最有前途的新发展之一。 GAN 由 Ian Goodfellow 于 2014 年提出,通过训练两个相互竞争和合作的深度网络(称为生成器和鉴别器)来解决无监督学习的问题。在训练过程中,两个网络最终都学会了如何执行它们的任务。
甘几乎总是被解释为伪造者(生殖)和警察(鉴别者)。最初,伪造者会向警察出示假币。警察说是假的。警察向造假者反馈为什么钱是假的。伪造者试图根据收到的反馈制造新的假币。警方表示,这些钱仍然是假的,并提供了一套新的反馈。伪造者试图根据最新的反馈制造新的假币。这种循环无限期地继续下去,直到警察被假钱所愚弄,因为它看起来像真的。
尽管 GAN 的想法在理论上很简单,但要建立一个可行的模型却非常困难。在 GAN 中,有两个耦合在一起的深层网络,使得梯度的反向传播具有两倍的挑战性。深度卷积 GAN (DCGAN) 是演示如何构建实用 GAN 的模型之一,它能够自学如何合成新图像。
在本文中,我们将讨论如何在 Tensorflow 1.0 后端上使用 Keras 2.0 用不到 200 行代码构建一个有效的 DCGAN。我们将训练一只 DCGAN 学习如何书写手写数字,用 MNIST 的方式。
鉴别器
辨别图像真实程度的鉴别器基本上是一个深度卷积神经网络(CNN ),如图 1 所示。对于 MNIST 数据集,输入是图像(28 像素 x 28 像素 x 1 通道)。sigmoid 输出是图像真实程度概率的标量值(0.0 肯定是假的,1.0 肯定是真实的,介于两者之间的任何值都是灰色区域)。与典型的 CNN 的区别在于层间没有最大池。相反,步长卷积用于下采样。在每个 CNN 层中使用的激活函数是一个泄漏 ReLU。层间 0.4 和 0.7 之间的压差防止过拟合和记忆。清单 1 展示了 Keras 中的实现。
Figure 1. Discriminator of DCGAN tells how real an input image of a digit is. MNIST Dataset is used as ground truth for real images. Strided convolution instead of max-pooling down samples the image.
self.D = Sequential()depth = 64dropout = 0.4# In: 28 x 28 x 1, depth = 1# Out: 14 x 14 x 1, depth=64input_shape = (self.img_rows, self.img_cols, self.channel)self.D.add(Conv2D(depth*1, 5, strides=2, input_shape=input_shape,\padding='same', activation=LeakyReLU(alpha=0.2)))self.D.add(Dropout(dropout))self.D.add(Conv2D(depth*2, 5, strides=2, padding='same',\activation=LeakyReLU(alpha=0.2)))self.D.add(Dropout(dropout))self.D.add(Conv2D(depth*4, 5, strides=2, padding='same',\activation=LeakyReLU(alpha=0.2)))self.D.add(Dropout(dropout))self.D.add(Conv2D(depth*8, 5, strides=1, padding='same',\activation=LeakyReLU(alpha=0.2)))self.D.add(Dropout(dropout))# Out: 1-dim probabilityself.D.add(Flatten())self.D.add(Dense(1))self.D.add(Activation('sigmoid'))self.D.summary()
清单 1。图 1 中鉴别器的 Keras 代码。
发电机
生成器合成假图像。在图 2 中,假图像是使用卷积的逆运算(称为转置卷积)从 100 *噪声(均匀分布在-1.0 到 1.0 之间)生成的。使用前三层之间的上采样,而不是 DCGAN 中建议的分数步长卷积,因为它合成了更真实的手写图像。在各层之间,批量标准化稳定了学习。每一层之后的激活函数是一个 ReLU。最后一层的 sigmoid 的输出产生假图像。第一层 0.3 至 0.5 之间的压差可防止过度拟合。清单 2 展示了 Keras 中的实现。
Figure 2. Generator model synthesizes fake MNIST images from noise. Upsampling is used instead of fractionally-strided transposed convolution.
self.G = Sequential()dropout = 0.4depth = 64+64+64+64dim = 7# In: 100# Out: dim x dim x depthself.G.add(Dense(dim*dim*depth, input_dim=100))self.G.add(BatchNormalization(momentum=0.9))self.G.add(Activation('relu'))self.G.add(Reshape((dim, dim, depth)))self.G.add(Dropout(dropout))# In: dim x dim x depth# Out: 2*dim x 2*dim x depth/2self.G.add(UpSampling2D())self.G.add(Conv2DTranspose(int(depth/2), 5, padding='same'))self.G.add(BatchNormalization(momentum=0.9))self.G.add(Activation('relu'))self.G.add(UpSampling2D())self.G.add(Conv2DTranspose(int(depth/4), 5, padding='same'))self.G.add(BatchNormalization(momentum=0.9))self.G.add(Activation('relu'))self.G.add(Conv2DTranspose(int(depth/8), 5, padding='same'))self.G.add(BatchNormalization(momentum=0.9))self.G.add(Activation('relu'))# Out: 28 x 28 x 1 grayscale image [0.0,1.0] per pixself.G.add(Conv2DTranspose(1, 5, padding='same'))self.G.add(Activation('sigmoid'))self.G.summary()return self.G
清单 2。图 2 中生成器的 Keras 代码。
GAN 模型
到目前为止,还没有模型。是时候为训练建立模型了。我们需要两个模型:1)鉴别器模型(警察)和 2)对抗模型或生成器-鉴别器(伪造者向警察学习)。
鉴别器模型
清单 3 展示了鉴别器模型的 Keras 代码。它是上面描述的鉴别器,具有为训练定义的损失函数。由于鉴频器的输出是 sigmoid,我们使用二进制交叉熵来计算损耗。在这种情况下,RMSProp 作为优化器生成了比 Adam 更真实的假图像。学习率 0.0008。权重衰减和剪辑值在训练的后半部分稳定学习。你要调整学习率就要调整衰减。
optimizer = RMSprop(lr=0.0008, clipvalue=1.0, decay=6e-8)self.DM = Sequential()self.DM.add(self.discriminator())self.DM.compile(loss='binary_crossentropy', optimizer=optimizer,\metrics=['accuracy'])
清单 3。鉴别器模型在 Keras 中实现。
对抗模式
对抗模型只是如图 3 所示的生成器-鉴别器堆叠在一起。生成器部分试图欺骗鉴别器,同时从它的反馈中学习。清单 4 展示了使用 Keras 代码的实现。训练参数与鉴别器模型中的相同,除了降低的学习速率和相应的权重衰减。
Figure 3. The Adversarial model is simply generator with its output connected to the input of the discriminator. Also shown is the training process wherein the Generator labels its fake image output with 1.0 trying to fool the Discriminator.
optimizer = RMSprop(lr=0.0004, clipvalue=1.0, decay=3e-8)self.AM = Sequential()self.AM.add(self.generator())self.AM.add(self.discriminator())self.AM.compile(loss='binary_crossentropy', optimizer=optimizer,\metrics=['accuracy'])
清单 4。在 Keras 中实现的对抗模型如图 3 所示。
训练
训练是最难的部分。我们首先通过用真实和虚假图像单独训练鉴别器模型来确定鉴别器模型是否正确。然后,依次训练鉴别模型和对抗模型。图 4 显示了鉴别模型,而图 3 显示了训练期间的对抗模型。清单 5 展示了 Keras 中的训练代码。
Figure 4. Discriminator model is trained to distinguish real from fake handwritten images.
images_train = self.x_train[np.random.randint(0,self.x_train.shape[0], size=batch_size), :, :, :]noise = np.random.uniform(-1.0, 1.0, size=[batch_size, 100])images_fake = self.generator.predict(noise)x = np.concatenate((images_train, images_fake))y = np.ones([2*batch_size, 1])y[batch_size:, :] = 0d_loss = self.discriminator.train_on_batch(x, y)y = np.ones([batch_size, 1])noise = np.random.uniform(-1.0, 1.0, size=[batch_size, 100])a_loss = self.adversarial.train_on_batch(noise, y)
清单 5。鉴别模型和对抗模型的序贯训练。超过 1000 步的训练会产生可观的输出。
训练 GAN 模型由于其深度需要很大的耐心。以下是一些提示:
- 问题:生成的图像看起来像噪音。解决方案:在鉴频器和发生器上使用压差。低压差值(0.3 到 0.6)生成更真实的图像。
- 问题:鉴别器损耗迅速收敛到零,从而阻止发电机学习。解决方案:不要预先训练鉴别器。而是使其学习率大于对抗模型的学习率。对生成器使用不同的训练噪声样本。
- 问题:发生器图像看起来仍然像噪声。解决方案:检查激活、批处理规范化和删除是否按正确的顺序应用。
- 问题:计算出正确的训练/模型参数。解决方案:从发表的论文和代码中的一些已知工作值开始,一次调整一个参数。在训练 2000 步或以上之前,观察 500 步或 1000 步左右参数值调整的效果。
样本输出
图 5 显示了训练期间输出图像的演变。观察图 5 很有趣。GAN 正在学习如何自己书写手写数字!
Figure 5. DCGAN output images during 10,000 steps of training.
Keras 的完整代码可以在这里找到。
GAN —简介和实现—第 1 部分:在 TF 中实现一个简单的 GAN,用于 MNIST 手写数字生成
原文:https://towardsdatascience.com/gan-introduction-and-implementation-part1-implement-a-simple-gan-in-tf-for-mnist-handwritten-de00a759ae5c?source=collection_archive---------2-----------------------
GANs 背后的想法是,你有两个网络,一个生成器 GG 和一个鉴别器 DD,彼此竞争。生成器生成假数据传递给鉴别器。鉴别器也能看到真实数据,并预测它收到的数据是真是假。生成器被训练来欺骗鉴别器,它想要输出看起来尽可能接近真实数据的数据。鉴别器被训练来辨别哪些数据是真的,哪些是假的。最终发生的情况是,生成器学习生成与鉴别器的真实数据无法区分的数据。
这是平衡状态,期望值是鉴别器发出的真实和虚假数据的概率都是 0.5。
GAN 的一般结构如上图所示,使用 MNIST 图像作为数据。潜在样本是一个随机向量,生成器用它来构造假图像。当生成器通过训练学习时,它会想出如何将这些随机向量映射到可识别的图像,以欺骗鉴别器。
鉴别器的输出是 sigmoid 函数,其中 0 表示伪图像,1 表示真实图像。如果你只对生成新图像感兴趣,你可以在训练后扔掉鉴别器。
实施:
https://github . com/mchablani/deep-learning/blob/master/gan _ mnist/Intro _ to _ GANs _ exercises . ipynb
我们使用一个泄漏的 ReLU 来允许梯度不受阻碍地流过这个层。TensorFlow 没有为 leaky ReLUs 提供操作,你可以只从一个线性全连接层中取出输出,然后把它们传递给
tf.maximum
。通常,参数alpha
设置负值的输出幅度。因此,负输入(x
)值的输出为alpha*x
,正x
的输出为x
:对于发电机,我们将对其进行培训,同时在培训期间和培训结束后从其取样。鉴别器需要在伪输入图像和真实输入图像之间共享变量。因此,我们可以使用
tf.variable_scope
的reuse
关键字来告诉 TensorFlow 重用变量,而不是在我们再次构建图时创建新的变量。已经发现,对于发电机输出,发电机与 tanh 一起表现最佳。这意味着我们必须将 MNIST 图像重新缩放到-1 和 1 之间,而不是 0 和 1 之间。
**def** generator(z, out_dim, n_units=128, reuse=**False**, alpha=0.01):
**with** tf.variable_scope('generator', reuse=reuse):
*# Hidden layer*
h1 = tf.layers.dense(z, n_units, activation=**None**)
*# Leaky ReLU*
h1 = tf.maximum(h1, alpha*h1)
*# Logits and tanh output*
logits = tf.layers.dense(h1, out_dim, activation=**None**)
out = tf.nn.tanh(logits)
**return** out, logits
鉴频器网络与发生器网络几乎完全相同,只是我们使用的是 sigmoid 输出层。
**def** discriminator(x, n_units=128, reuse=**False**, alpha=0.01):
**with** tf.variable_scope('discriminator', reuse=reuse):
*# Hidden layer*
h1 = tf.layers.dense(x, n_units, activation=**None**)
*# Leaky ReLU*
h1 = tf.maximum(h1, alpha*h1)
logits = tf.layers.dense(h1, 1, activation=**None**)
out = tf.nn.sigmoid(logits)
**return** out, logits*#* Hyperparameters *# Size of input image to discriminator*
input_size = 784 *# 28x28 MNIST images flattened*
*# Size of latent vector to generator*
z_size = 100
*# Sizes of hidden layers in generator and discriminator*
g_hidden_size = 128
d_hidden_size = 128
*# Leak factor for leaky ReLU*
alpha = 0.01
*# Label smoothing*
smooth = 0.1
构建网络
tf.reset_default_graph()
*# Create our input placeholders*
input_real, input_z = model_inputs(input_size, z_size)
*# Generator network here*
g_model, g_logits = generator(input_z, input_size, g_hidden_size, reuse=**False**, alpha=alpha)
*# g_model is the generator output* *# Disriminator network here*
d_model_real, d_logits_real = discriminator(input_real, d_hidden_size, reuse=**False**, alpha=alpha)
d_model_fake, d_logits_fake = discriminator(g_model, d_hidden_size, reuse=**True**, alpha=alpha)
鉴频器和发电机损耗
对于鉴别器,总损失是真实和伪造图像的损失之和,
d_loss = d_loss_real + d_loss_fake
。对于真实的图像逻辑,我们将使用从上面单元格中的鉴别器获得的
d_logits_real
。对于标签,我们希望它们都是 1,因为这些都是真实的图像。为了帮助鉴别器更好地归纳,标签从 1.0 减少到 0.9,例如,使用参数smooth
。这被称为标签平滑,通常与分类器一起使用以提高性能。在 TensorFlow 中,它看起来有点像labels = tf.ones_like(tensor) * (1 - smooth)
伪数据的鉴别器损耗是相似的。逻辑是
d_logits_fake
,它是我们通过将生成器输出传递给鉴别器得到的。这些假逻辑与全零标签一起使用。请记住,我们希望鉴频器为真实图像输出 1,为虚假图像输出 0,因此我们需要设置损耗来反映这一点。最后,发电机损耗使用
d_logits_fake
,假图像逻辑。但是,现在的标签都是一。生成器试图欺骗鉴别器,所以它希望鉴别器输出假图像。
*# Calculate losses*
d_labels_real = tf.ones_like(d_logits_real) * (1 - smooth)
d_labels_fake = tf.zeros_like(d_logits_fake)
d_loss_real = tf.nn.sigmoid_cross_entropy_with_logits(labels=d_labels_real, logits=d_logits_real)
d_loss_fake = tf.nn.sigmoid_cross_entropy_with_logits(labels=d_labels_fake, logits=d_logits_fake)
d_loss = tf.reduce_mean(d_loss_real + d_loss_fake)
g_loss = tf.reduce_mean(
tf.nn.sigmoid_cross_entropy_with_logits(
labels=tf.ones_like(d_logits_fake),
logits=d_logits_fake))
优化者
我们希望分别更新生成器和鉴别器变量。
请注意,当最*化 d_loss 时,我们希望优化器只更新鉴别器变量以及生成器的类似变量。
*# Optimizers*
learning_rate = 0.002
*# Get the trainable_variables, split into G and D parts*
t_vars = tf.trainable_variables()
g_vars = [var **for** var **in** t_vars **if** var.name.startswith("generator")]
d_vars = [var **for** var **in** t_vars **if** var.name.startswith("discriminator")]
d_train_opt = tf.train.AdamOptimizer().minimize(d_loss, var_list=d_vars)
g_train_opt = tf.train.AdamOptimizer().minimize(g_loss, var_list=g_vars)
培养
batch_size = 100
epochs = 100
samples = []
losses = []
saver = tf.train.Saver(var_list = g_vars)
**with** tf.Session() **as** sess:
sess.run(tf.global_variables_initializer())
**for** e **in** range(epochs):
**for** ii **in** range(mnist.train.num_examples//batch_size):
batch = mnist.train.next_batch(batch_size)
*# Get images, reshape and rescale to pass to D*
batch_images = batch[0].reshape((batch_size, 784))
batch_images = batch_images*2 - 1
*# Sample random noise for G*
batch_z = np.random.uniform(-1, 1, size=(batch_size, z_size))
*# Run optimizers*
_ = sess.run(d_train_opt, feed_dict={input_real: batch_images, input_z: batch_z})
_ = sess.run(g_train_opt, feed_dict={input_z: batch_z})
*# At the end of each epoch, get the losses and print them out*
train_loss_d = sess.run(d_loss, {input_z: batch_z, input_real: batch_images})
train_loss_g = g_loss.eval({input_z: batch_z})
print("Epoch **{}**/**{}**...".format(e+1, epochs),
"Discriminator Loss: **{:.4f}**...".format(train_loss_d),
"Generator Loss: **{:.4f}**".format(train_loss_g))
*# Save losses to view after training*
losses.append((train_loss_d, train_loss_g))
*# Sample from generator as we're training for viewing afterwards*
sample_z = np.random.uniform(-1, 1, size=(16, z_size))
gen_samples = sess.run(
generator(input_z, input_size, reuse=**True**),
feed_dict={input_z: sample_z})
samples.append(gen_samples)
saver.save(sess, './checkpoints/generator.ckpt')
*# Save training generator samples*
**with** open('train_samples.pkl', 'wb') **as** f:
pkl.dump(samples, f)
学分:来自课堂讲稿:https://classroom.udacity.com/nanodegrees/nd101/syllabus
甘实验室:在浏览器中训练甘!
原文:https://towardsdatascience.com/gan-lab-train-gans-in-the-browser-21a423585460?source=collection_archive---------15-----------------------
有许多浏览器可视化工具可以帮助机器学习学习者获得对神经网络训练概念的直觉,如 TensorFlow training playground 和 Perceptron Learning Applets:
[## 张量流-神经网络游乐场
这是一种构建从数据中学习的计算机程序的技术。它非常松散地基于我们如何思考…
playground.tensorflow.org](https://playground.tensorflow.org/#activation=tanh&batchSize=10&dataset=circle®Dataset=reg-plane&learningRate=0.03®ularizationRate=0&noise=0&networkShape=4,2&seed=0.42342&showTestData=false&discretize=false&percTrainData=50&x=true&y=true&xTimesY=false&xSquared=false&ySquared=false&cosX=false&sinX=false&cosY=false&sinY=false&collectStats=false&problem=classification&initZero=false&hideText=false) [## 感知器
“学习率”框允许您设置一个介于 0 和 1 之间的学习率值(其他值将被忽略)。的…
www.cs.utexas.edu](https://www.cs.utexas.edu/~teammco/misc/perceptron/)
这些浏览器可视化提供了一个很好的 UI 来可视化神经网络如何随着时间的推移而学习,包括它们学习的复杂函数的图。
这个可视化训练 GANs 的新工具对我理解生成性对抗网络的训练过程非常有帮助。我真的很喜欢区分真假样品的视觉效果。GUI 将显示样本如何随时间变化,以及鉴别器和发生器如何改变它们的参数。
有 5 种数据分布可供选择:一条直线、两个簇、一个圆、三个独立的圆和一条头部分离的线。
玩具数据集的不同复杂性会让你感觉到生成器和鉴别器通常需要多少个时期才能达到纳什均衡。
我认为这种可视化最有用的部分是简单地看到假样本是如何随着时间的推移而成型和变化的。通过浏览器界面一遍又一遍地观看这个过程对我初级水平的理解有很大帮助。玩了这个工具之后,Ian Goodfellow 的研究论文对我来说更有意义了。
您可以看到绿色/紫色图表,展示了鉴别器的性能,以便随着时间的推移分离生成的示例。这真的有助于你获得直觉,知道他们在训练中是如何合作的。
观察生成器的输出最终如何收敛到一组与真实数据点不完全相同的样本也很有趣。
这个工具的另一个非常好的特性是算法的顺序标记:
鉴别器更新
- 生成器从噪声中获取样本
- 鉴别器对样品进行分类(结合真假)
- 计算鉴频器损耗
- 计算机鉴别器梯度
- 基于梯度更新鉴别器
发电机更新
- 生成器从噪声中获取样本
- 鉴别器只对假样本进行分类
- 计算发电机损耗
- 计算发电机梯度
- 基于渐变更新生成器
我认为,除了样本和损耗图的 GUI 之外,可视化算法的步骤是理解 GAN 训练过程的一个非常好的工具。
最后,非常有趣的是,鉴频器和发电机的损耗在多个时期内收敛到相同的值。我认为这是最*最大对抗训练理论上所依据的纳什均衡的表现。
结论
我真的很高兴我发现这个工具有助于我对生成性对抗网络的理解,尤其是训练过程:请亲自检查一下!
[## 甘实验室:在你的浏览器中玩生成性对抗网络!
GAN 实验室使用的是浏览器内 GPU 加速的深度学习库 TensorFlow.js。一切,从模特培训到…
poloclub.github.io](https://poloclub.github.io/ganlab/)
CShorten
Connor Shorten 是佛罗里达大西洋大学计算机科学专业的学生。对软件经济学、深度学习和软件工程感兴趣。
GAN 目标函数:GAN 及其变体
原文:https://towardsdatascience.com/gan-objective-functions-gans-and-their-variations-ad77340bce3c?source=collection_archive---------5-----------------------
gan 有数百种类型。目标函数如何影响 GAN 的外观?
如果你还没有,你一定要读一读我的上一篇关于 GAN 是什么的文章(尤其是当你不知道我说 GAN 是什么意思的时候!).这篇文章应该给你一个深入 GANs 世界和他们如何工作的起点。对于任何关于 GANs 的文章来说,这都是一个坚实的基础,更不用说在这篇文章中,我们将讨论 GANs 的目标函数,以及目前存在的使用 twists 来定义不同结果的目标的 GANs 的其他变体。
没时间看完整本?这是 TL。速度三角形定位法(dead reckoning)
定义目标
在我们的介绍性文章中,我们谈到了生成模型。我们讨论了生成模型的目标是如何想出一种方法来将它们生成的分布与真实的数据分布相匹配。最*化两个分布之间的距离对于创建一个系统来说是至关重要的,该系统生成的内容看起来很好,很新,就像来自原始数据分布一样。
但是我们如何衡量我们生成的数据分布和我们原始的数据分布之间的差异呢?这就是我们所说的目标函数,也是今天这篇文章的重点!我们将研究 gan 的一些变化,以了解我们如何改变生成的数据分布与实际分布之间的差异,以及这将产生的影响。
原甘
我们最初的 GAN 的目标函数本质上是最*化所谓的詹森香农发散 (JSD)。具体来说是:
JSD 源自我们在上一篇文章中提到的库尔巴赫-利布勒背离(KLD)。
我们已经熟悉了我们的朋友,原来的甘。与其进一步讨论这个问题,不如让我们欣赏一下它辉煌的表现:
瓦瑟斯坦·甘
wasser stein GAN(WGAN)是一种你可能听说过的 GAN,因为它得到了很多关注。这样做有很多实际的原因(一般来说,当你训练一个 GAN 时,返回的损失值没有任何意义,除了 WGAN 以外),但是是什么让 WGAN 与众不同呢?
WGAN 不使用 JSD 来测量散度,而是使用一种叫做推土机(EM)距离(又名瓦瑟斯坦距离)的东西。EM 距离定义为:
这是什么意思?
电磁距离
让我们试着理解 EM 距离背后的直觉。概率分布本质上是质量的集合,分布测量给定点的质量数量。我们给 EM 距离两个分布。因为将质量移动一定距离的成本等于质量和距离的乘积,所以 EM 距离基本上计算将一种概率分布转换成另一种概率分布的最*成本。这可以被视为所需的最*努力。
但是我们为什么要在乎呢?我们关心 EM 距离,因为它经常测量从一个分布到另一个分布的直线距离。这有助于优化梯度。更不用说,还有一组函数在用 KLD 或 JSD 之类的东西测量距离时不会收敛,但在 EM 距离上确实会收敛。
这是因为 EM 距离具有连续性和可微性的保证,而这正是像 KLD 和 JSD 这样的距离函数所缺乏的。我们需要这些损失函数的保证,使 EM 距离更适合我们的需要。不仅如此,所有在 JSD 或 KLD 下聚合的东西也会在 EM 距离下聚合。只是电磁距离包含了更多。
这是怎么用的?
抛开所有这些关于数学的想法,进入这类事情的实际应用,当我们不能直接计算时,我们如何使用这个新的距离?首先,我们采用一个参数化的 critic 函数,并训练它来逼近我们的数据分布和我们生成的分布之间的 EM 距离。当我们做到了这一点,我们就有了一个很好的 EM 距离近似值。在此基础上,我们优化我们的发电机功能,以减少这一电磁距离。
为了保证我们的函数位于一个紧凑的空间中(这有助于确保我们满足进行计算所需的理论保证),我们剪切了参数化我们的评价函数 f 的权重。
只是一个旁注:我们的 critic 函数 f 被称为 critic,因为它不是一个显式的鉴别器。鉴别器会将其输入分类为真或假。批评家不会这么做。critic 函数只是近似距离分数。然而,它在传统的 GAN 框架中扮演着鉴别者的角色,因此值得强调一下它的相似之处和不同之处。
关键要点
- 有意义损失函数
- 更容易调试
- 更简单的超参数搜索
- 提高稳定性
- 更少的模式崩溃(当一个生成器只是一遍又一遍地生成一个东西的时候……稍后会有更多的介绍)
- 理论优化保证
改进的 WGAN
用 WGAN 提出了那么多好的东西,还有什么需要改进的?嗯,对瓦瑟斯坦·甘斯的改进训练凸显了这一点。
WGAN 得到了很多关注,人们开始使用它,好处就在那里。但是人们开始注意到,尽管 WGAN 带来了所有的东西,但它仍然无法收敛或产生非常糟糕的样本。改进的 WGAN 给出的理由是重量削减是一个问题。在某些情况下,它弊大于利。我们注意到,我们对 clip 进行加权的原因与保持 critic 函数的理论保证有关。但在实践中,剪辑实际上是鼓励非常简单的批评功能被推到其边界的极端。这可不好。
相反,改进的 WGAN 提出的是,不削减权重,而是在 critic 函数的梯度范数中添加一个惩罚项。他们发现,这可以产生更好的结果,当插入一堆不同的 GAN 架构时,可以产生稳定的训练。
关键要点
- 完全 WGAN,除了没有重量剪辑
- 加权正则项鼓励理论保证
最*平方甘
LSGAN 的设置类似于 WGAN。然而,LSGAN 不是学习一个批判函数,而是学习一个损失函数。真样品的损失应低于假样品的损失。这使得 LSGAN 可以高度关注利润非常高的假样本。
像 WGAN 一样,LSGAN 试图限制它们的功能域。他们采取不同的方法,而不是剪辑。他们以权重衰减的形式引入正则化,鼓励其函数的权重位于保证理论需求的有界区域内。
另一点需要注意的是,损失函数的设置与原始 GAN 更相似,但原始 GAN 使用对数损失,LSGAN 使用 L2 损失(相当于最*化皮尔逊 X 散度)。其原因与以下事实有关:对数损失基本上只关心样品标记是否正确。它不会基于所述样本与正确分类的距离而受到严重惩罚。如果一个标签是正确的,它不会进一步担心它。相比之下,L2 损失不在乎距离。远离它应该在的地方的数据将按比例被扣分。LSGAN 认为这产生了更多的信息梯度。
关键要点
- 损失函数而不是批评家
- 有界损失函数的权重衰减正则化
- 比例惩罚的 L2 损失而不是对数损失
放松的 Wasserstein GAN
或者简称为 RWGAN 是 WGAN 论文的另一种变体。他们将他们的 RWGAN 描述为 WGAN 和改进的 WGAN(他们在论文中引用的 WGAN-GP)之间的快乐媒介。RWGAN 采用非对称箝位策略,而不是对称箝位(如 WGAN)或梯度惩罚(如针对改进的 WGAN 提出的)。
除了他们提出的特定 GAN 架构之外,他们还描述了他们所谓的统计类别的偏差(称为宽松 Wasserstein 偏差或 RW 偏差)。RW 散度从 WGAN 论文中提取了 Wasserstein 散度,并使其更具一般性,概述了一些关键的概率性质,这些性质是为了保持我们的 GAN 的一些理论保证所需要的。
他们特别表明,用 KL 散度参数化的 RWGAN 相对于其他最先进的 GAN 极具竞争力,但甚至比常规 WGAN 具有更好的收敛特性。他们还开放了他们的框架,以定义新的损失函数,从而为设计 GAN 方案定义新的成本函数。
关键要点
- 重量不对称夹紧
- 通用 RW 散度框架,非常适合设计新的 GAN 模式、成本和损失函数
麦根
与 GAN (McGAN)匹配的均值和协方差特征属于与 WGAN 相同的 GAN 家族。这个家族被称为积分概率度量(IPM)家族。这些 gan 是那些使用批判架构而不是显式鉴别器的。
McGAN 的 critic 函数与测量生成数据分布和目标数据分布的均值或协方差特征有关。从名字上看,这似乎也很简单。他们定义了创建 critic 函数的两种不同方法,一种用于均值,一种用于协方差,并演示了如何实际使用它们。像 WGAN 一样,他们也在他们的模型上使用裁剪,这最终限制了模型的容量。这篇论文没有得出什么重大的结论。
关键要点
- 临界函数距离的均值和协方差测度
生成矩匹配网络
生成矩匹配网络 (GMMN)专注于最*化所谓的最大平均差异 (MMD)。MMD 本质上是两个分布的嵌入空间的平均值,我们在这里试图最*化两个平均值之间的差异。我们可以使用一种叫做内核技巧的东西,它允许我们作弊并使用高斯内核来计算这个距离。
他们认为,这允许一个简单的目标,可以很容易地用反向传播进行训练,并产生与标准 GAN 竞争的结果。他们还展示了如何将自动编码器添加到这个 GAN 的架构中,以减少精确估计 MMD 所需的训练量。
补充说明:虽然他们声称有竞争性的结果,但从我在别处读到的来看,他们的实证结果似乎经常是缺乏的。此外,这个模型的计算量相当大,所以在我看来,计算资源和性能的权衡似乎并不存在。
关键要点
- 使用最大平均偏差(MMD)作为距离/目标函数
- 没有鉴别器,只是测量样本之间的距离
- 添加自动编码器来帮助测量 MMD
甘
最大均值差异 GAN 或 MMD GAN,你猜对了,是 GMMN 的改进。他们的主要贡献在于没有使用静态高斯核来计算 MMD,而是使用对抗技术来学习核。它结合了最初 GAN 和 GMMN 论文的思想,创建了两者思想的混合体。它声称的好处是性能和运行时间的提高。
关键要点
- GMMN 上的迭代:估计 MMD 的对立学习核
克拉默·甘
Cramer GAN 首先概述了流行的 WGAN 的一个问题。它声称概率散度应该满足三个性质:
- 和不变性
- 标度灵敏度
- 无偏样本梯度
在这些性质中,他们认为沃瑟斯坦距离缺少最后一个性质,不像 KLD 或 JSD 都有。他们证明这实际上是一个实际问题,并提出了一个新的距离:克莱姆距离。
克莱姆距离
现在如果我们看看克莱姆距离,我们可以看到它看起来有点类似于 EM 距离。然而,由于其数学差异,它实际上不会像 EM 距离那样遭受有偏差的样本梯度。如果你真的想深入研究它的数学原理,论文中已经证明了这一点。
关键要点
- 克莱姆距离而不是电磁距离
- 对 WGAN 的改进:无偏样本梯度
费希尔·甘
在 IPM GAN 声称在许多方面超过 McGAN、WGAN 和改进的 WGAN 的基础上, Fisher GAN 又是一次迭代。它所做的是设置其目标函数,使其具有一个对其二阶矩(也称为方差)具有数据相关约束的评论家。
基于这一目标,Fisher GAN 拥有以下优势:
- 训练稳定性
- 无约束容量
- 高效计算
是什么让费希尔·甘的《远方》与众不同?事实上,它本质上是测量所谓的 Mahalanobis 距离,简单来说,就是具有相关变量的两点之间相对于质心的距离,质心被认为是多元数据分布的平均值。这实际上保证了生成器和批评家会像我们期望的那样被绑定。当参数化的 critic 接近无限容量时,它实际上估计了卡方距离。
关键要点
- 对 WGAN 和其他 IPM GANs 的改进
- 拥有训练稳定性、不受约束的容量和高效的计算时间
- 卡方距离物镜
基于能源的氮化镓
基于能源的 GAN (EBGAN)是我们今天收集的 GAN 中有趣的一种。它不像最初的 GAN 那样使用鉴别器,而是使用自动编码器来估计重建损失。设置的步骤如下:
- 根据原始数据训练自动编码器
- 现在通过这个自动编码器运行生成的图像
- 生成不好的图像会有可怕的重建损失,因此这现在成为一个很好的措施
这是一种非常酷的设置 GAN 的方法,通过正确的调整来防止模式崩溃(生成器只是一遍又一遍地产生相同的样本),它看起来相当不错。
那为什么还要这么做呢?经验表明,以这种方式使用自动编码器实际上会产生快速、稳定且对参数变化具有鲁棒性的 GAN。更重要的是,没有必要尝试和拉一堆技巧来平衡鉴别器和生成器的训练。
关键要点
- 自动编码器作为鉴别器
- 重建损耗用作成本,设置类似于原始 GAN 成本
- 快速、稳定和强大
边界平衡 GAN
边界平衡 GAN(begined)是在 EBGAN 上的迭代。相反,它以类似于 WGAN 损失函数的方式使用自动编码器重建损失。
为了做到这一点,需要引入一个参数来平衡鉴别器和发生器的训练。该参数被加权为样本的移动平均值,在改进的两个一半之间的边界上跳舞(因此它得名:“边界平衡”)。
关键要点
- EBGAN 的迭代
- 成本函数与 WGAN 的表面相似性
边缘适应 GAN
【缘改编】甘(马江)最后一个上榜。这是艾根的另一个变种。作为损失函数的一部分,EBGAN 有一个余量来产生铰链损失。MAGAN 所做的是随着时间的推移单调减少这一差额,而不是保持不变。这样做的结果是鉴别器将更好地自动编码真实样本。
我们关心的结果是:更好的样本和更稳定的训练。
关键要点
- EBGAN 上的迭代
- 铰链损耗的自适应余量
- 更稳定,质量更好
包扎
那是许多不同的甘斯!而且内容很多!我认为,为了让我们更有条理,有必要在表格中总结一下:
咻…拍拍自己的背,那是很多甘的内容。
如果我错过了什么或误解了什么,请纠正我!
如果你喜欢这篇文章,或者觉得它有任何帮助,如果你给我一个长长的一两美元来资助我的机器学习教育和研究,我会永远爱你!每一美元都让我离成功更近一步,我永远心存感激。
敬请关注近期更多 GAN 博客!
原载于hunterheidenreich.com。
氮化镓——提高氮化镓性能的方法
原文:https://towardsdatascience.com/gan-ways-to-improve-gan-performance-acf37f9f59b?source=collection_archive---------1-----------------------
Photo by Andy Beales
与其他深度网络相比,GAN 模型在以下方面可能会受到严重影响。
- 不收敛 :模型不收敛,更糟的是变得不稳定。
- 模式崩溃 :发电机产生有限的模式,并且
- 慢速训练:训练发电机的梯度消失了。
作为 GAN 系列的一部分,本文探讨了如何改进 GAN 的方法。特别是,
- 为了更好的优化目标,改变成本函数。
- 向成本函数添加额外的惩罚以加强约束。
- 避免过度自信和过度适应。
- 优化模型的更好方法。
- 添加标签。
但是请注意,这是一个动态的话题,因为研究仍然非常活跃。
特征匹配
生成器试图找到最佳图像来欺骗鉴别器。当两个网络都对抗他们的对手时,“最佳”形象不断变化。但是,优化可能会变得过于贪婪,从而陷入一场永无休止的猫捉老鼠的游戏。这是场景之一,模型不收敛,模式崩溃。
特征匹配改变生成器的成本函数,以最*化真实图像和生成图像的特征之间的统计差异。通常,我们测量它们的特征向量的平均值之间的 L2 距离。因此,特征匹配将目标从击败对手扩展到真实图像中的特征匹配。这是新的目标函数:
其中**f(x)是鉴别器在即时层中提取的特征向量。
计算每个*批量的真实图像特征的平均值,该平均值在每个批量上波动。这是减轻模式崩溃的好消息。它引入了随机性,使得鉴别器更难过拟合。
当 GAN 模型在训练期间不稳定时,特征匹配是有效的。
迷你批次鉴别
当模式崩溃时,所有创建的图像看起来都相似。为了缓解这个问题,我们将真实图像和生成图像分批次分别输入鉴别器,并计算图像 x 与同批次图像的相似度。我们将相似度 o(x) 附加在鉴别器中的一个稠密层中,来分类这个图像是真实的还是生成的。
**
如果模式开始崩溃,生成图像的相似性会增加。鉴别器可以使用该分数来检测生成的图像,并且如果模式崩溃,则惩罚生成器。
通过变换矩阵计算图像与同批其他图像之间的相似度 o(xi) 。方程式有点难追踪,但是概念很简单。但是,如果您愿意,可以随意跳到下一部分。**
在上图中,为输入图像, xj 为同一批次的其余图像。我们用一个变换矩阵 T 将特征变换为 Mi 这是一个 B×C 矩阵。**
我们使用 L1 范数和下面的等式导出图像 i 和 j 之间的相似度 c(xi,xj) 。
图像与批中其余图像之间的相似度 o(xi) 为
以下是概要:
引用“训练 GANs 的改进技术”一文中的话
微型批次鉴别使我们能够非常快速地生成视觉上吸引人的样品,在这方面,它优于特征匹配。
单面标签平滑
深层网络可能会因过度自信而受损。例如,它使用很少的特征来分类一个对象。为了缓解这个问题,深度学习使用监管和辍学来避免过度自信。
在 GAN 中,如果鉴别器依赖于一*组特征来检测真实图像,则生成器可能仅产生这些特征来利用鉴别器。优化可能会变得过于贪婪,并且不会产生长期效益。在甘看来,过度自信伤害很大。为了避免这个问题,当任何真实图像的预测超过 0.9 时,我们惩罚鉴别器( D(真实图像)> 0.9 )。这是通过将我们的目标标签值设置为 0.9 而不是 1.0 来实现的。下面是伪代码:
**p = tf.placeholder(tf.float32, shape=[None, 10])# Use 0.9 instead of 1.0.
feed_dict = {
p: [[0, 0, 0, 0.9, 0, 0, 0, 0, 0, 0]] # Image with label "3"
}# logits_real_image is the logits calculated by
# the discriminator for real images.
d_real_loss = tf.nn.sigmoid_cross_entropy_with_logits(
labels=p, logits=logits_real_image)**
历史平均
在历史平均中,我们跟踪最近 t 模型的模型参数。或者,如果我们需要保持一个长的模型序列,我们更新模型参数的运行平均值。
我们将下面的 L2 成本添加到成本函数中,以惩罚不同于历史平均值的模型。
对于具有非凸目标函数的 GANs,历史平均可以阻止模型围绕平衡点旋转,并作为阻*力来收敛模型。
体验回放
模型优化可能过于贪婪,会破坏生成器当前正在生成的内容。为了解决这个问题,experience replay 保留了从过去的优化迭代中最近生成的图像。不是仅用当前生成的图像来拟合模型,我们还将所有最近生成的图像馈送给鉴别器。因此,对于生成器的特定时间实例,鉴别器不会过拟合。
使用标签(CGAN)
许多数据集带有其样本对象类型的标签。训练甘已经很难了。因此,在指导 GAN 训练方面的任何额外帮助都可以大大提高性能。添加标签作为潜在空间 z 的一部分有助于 GAN 训练。下面是在 CGAN 中使用的数据流,以利用样本中的标签。
成本函数
成本函数重要吗?否则所有的研究努力都会白费。但如果你听说了一篇 2017 年的谷歌大脑论文,你肯定会产生怀疑。但是推画质还是重中之重。很可能,我们会看到研究人员尝试不同的成本函数,然后我们才有一个明确的答案。
下图列出了一些常见 GAN 模型的成本函数。
Table modified from here.
我们决定不在本文中详述这些成本函数。下面是详细介绍一些常用代价函数的文章: WGAN/WGAN-GP ,EBGAN/begin, LSGAN , RGAN 和 RaGAN 。在本文的最后,我们列出了一篇更详细地研究所有这些成本函数的文章。由于成本函数是 GAN 的一个主要研究领域,我们鼓励您稍后阅读该文章。
这里是一些数据集的 FID 分数(越低越好)。这是一个参考点,但需要注意的是,现在就得出什么样的成本函数表现最好的结论还为时过早。事实上,还没有一个成本函数在所有不同的数据集中表现得最好。
Source
(MM GAN 是原论文中的 GAN 代价函数。NS GAN 是在同一篇论文中解决消失梯度的替代成本函数。)
但是如果没有好的超参数,任何模型都不会表现良好,而且调整 gan 需要时间。在随机测试不同的成本函数之前,对超参数优化要有耐心。一些研究人员提出,调整超参数可能比改变成本函数获得更好的回报。一个仔细调整的学习率可能会减轻一些严重的甘问题,如模式崩溃。具体来说,当模式崩溃发生时,降低学习速率并重新进行训练。
我们还可以为生成器和鉴别器试验不同的学习速率。例如,下图在 WGAN-GP 训练中对鉴别器使用 0.0003 的学习率,对生成器使用 0.0001 的学习率。
Source
实施技巧
- 在-1 和 1 之间缩放图像像素值。使用 tanh 作为发生器的输出层。
- 高斯分布的实验采样 z 。
- 批量标准化通常可以稳定训练。
- 使用 PixelShuffle 和转置卷积进行上采样。
- 避免缩减采样的最大池化。使用卷积步幅。
- Adam optimizer 通常比其他方法效果更好。
- 在将真实图像和生成的图像输入鉴别器之前,向它们添加噪声。
GAN 模型的动力学还没有被很好地理解。因此,一些提示只是建议,里程可能会有所不同。例如,LSGAN 的论文报告了 RMSProp 在他们的实验中有更稳定的训练。这种情况很少见,但证明了提出一般性建议的挑战。
鉴别器和生成器不断地与他人竞争。做好成本函数值可能上下波动的准备。不要过早地停止培训,即使成本可能会上升。直观地监控结果,以验证培训的进度。
虚拟批量标准化(VBN)
批量规范化 BM 成为许多深度网络设计中事实上的标准。BM 的平均值和方差来自当前的*批量。然而,它在样本之间产生了依赖性。生成的图像不是相互独立的。
这反映在实验中,实验产生的图像显示同一批中的色调。
Orange tone on the top batch and greenish tone on the second. Source
最初,我们从随机分布中抽取 z 的样本,这给了我们独立的样本。然而,批量标准化产生的偏差压倒了 z 的随机性。
虚拟批次标准化(VBN)在训练前对参考批次进行采样。在正向传递中,我们可以预先选择一个参考批次来计算 BN 的归一化参数( μ 和σ)。但是,我们将使用该参考批次过度拟合模型,因为我们在整个训练中使用相同的批次。为了减轻这种情况,我们可以将参考批次与当前批次结合起来计算归一化参数。
随机种子
用于初始化模型参数的随机种子影响 GAN 的性能。如下所示,在 50 次单独运行(训练)中,用于测量 GAN 性能的 FID 分数有所不同。但是范围相对较*,并且可能仅在稍后的微调中完成。
Source
谷歌大脑的一篇论文指出,LSGAN 偶尔会在一些数据集中失败或崩溃,需要用另一个随机种子重新开始训练。
批量标准化
DGCAN 强烈建议在网络设计中加入 BM。BM 的使用也成为许多深度网络模型中的普遍做法。然而,也会有例外。下图展示了 BN 对不同数据集的影响。y 轴是 FID 分数,越低越好。正如 WGAN-GP 论文所建议的,BN 在使用时应该是关闭的。我们建议读者在 BN 上检查所使用的成本函数和相应的 FID 性能,并通过实验验证设置。
Modified from source.
光谱归一化
频谱归一化是一种权重归一化,稳定了鉴别器的训练。它控制鉴别器的 Lipschitz 常数以减轻爆炸梯度问题和模式崩溃问题。这个概念在很大程度上基于数学,但从概念上讲,它限制了每次迭代中的权重变化,而不是过度依赖于鉴别器在区分图像时的一*组特征。与 WGAN-GP 相比,这种方法计算量*,并实现了困扰许多 GAN 方法的良好模式覆盖。
多个 GANs
模式崩溃也许并不全是坏事。当模式崩溃时,图像质量通常会提高。事实上,我们可以收集每个模式的最佳模型,并使用它们来重新创建不同模式的图像。
Source
鉴别器和发生器之间的平衡
鉴别者和生成者总是在进行一场互相削弱的拉锯战。模式崩溃和梯度递减通常被解释为鉴别器和发生器之间的不平衡。我们可以通过将注意力转向平衡发生器和鉴频器之间的损耗来改进 GAN。不幸的是,解决方案似乎难以捉摸。我们可以在鉴别器和生成器上保持梯度下降迭代次数之间的静态比率。即使这看起来很吸引人,但许多人怀疑它的好处。通常,我们保持一比一的比例。但是一些研究人员也测试了每次生成器更新 5 次鉴别器迭代的比率。还提出了用动态机制平衡两个网络。但直到最近几年,我们才开始关注它。
另一方面,一些研究人员质疑平衡这些网络的可行性和可取性。一个训练有素的鉴别器无论如何都会给生成器提供质量反馈。还有,训练发电机总是追上鉴别器也不容易。相反,我们可以把注意力转移到寻找一个成本函数,当发电机表现不好时,该成本函数不具有接近零的梯度。
然而,问题依然存在。提出了许多成本函数的建议,但关于什么是最好的建议的争论仍然存在。
鉴别器和发电机网络容量
鉴别器的模型通常比发生器更复杂(更多过滤器和更多层),好的鉴别器提供高质量的信息。在许多 GAN 应用中,我们可能会遇到瓶颈,即增加发电机容量并不能提高质量。在我们发现瓶颈并解决它们之前,增加发电机容量似乎不是许多分区商的首要任务。
比根
BigGAN 于 2018 年出版,目标是为 GAN 收集当时生成最佳图像的一些实践。在本节中,我们将研究一些尚未涉及的实践。
批量更大
Source (The smaller the FID score, the better)
如上所示,增加批量会使 FID 显著下降。批量越大,覆盖的模式就越多,并为两个网络学习提供更好的梯度。但是,BigGAN 报告说,该模型在更少的迭代中达到了更好的性能,但之后变得不稳定,甚至崩溃。所以,不断保存模型。
截断绝招
潜在空间中的低概率密度区域 z 可能没有足够的训练数据来准确学习。所以在生成图像时,我们可以避开那些区域,以变差为代价来提高图像质量。即图像的质量将会提高,但是那些生成的图像在风格上具有较低的变化。截断输入潜在空间 z 有不同的技术。一般原则是,当值落在范围之外时,它将被重新采样或挤压到更高概率的区域。
增加型号容量
在调整过程中,考虑增加模型的容量,尤其是对于具有高空间分辨率的图层。许多型号在将当时使用的传统容量增加一倍后,性能有所提高。但是在没有首先对模型设计和实现进行校对的情况下,不要做得太早。
发电机重量的移动平均值
生成器使用的权重是根据生成器权重的指数移动平均值计算的。
正交正则化
权重矩阵的条件是一个重要的研究课题。这是一项关于函数输出对其输入变化的敏感程度的研究。对训练稳定性影响较大。矩阵 Q 是正交的,如果
如果我们用一个正交矩阵乘以 x ,那么 x 的变化就不会被放大。这种行为对于保持数值稳定性是非常理想的。
对于其他属性,保持权重矩阵的正交属性在深度学习中可能是有吸引力的。我们可以添加一个正交正则化,以鼓励在训练过程中这样的属性。如果 Q 偏离正交矩阵,它会对系统不利。
然而,这是众所周知的太局限,因此比根使用了一个修改的术语:
正交正则化还允许截断技巧在不同的模型中更加成功。
正交权重初始化
模型权重被初始化为随机正交矩阵。
跳 z 连接
在普通 GAN 中,潜在因子 z 仅输入到第一层。使用 skip-z 连接,潜在因素 z 的直接跳过连接(skip-z)连接到发电机的多个层,而不仅仅是第一层。
进一步阅读
在本文中,我们不通过成本函数来详述改进。这是一个重要的话题,我们建议读者阅读下面的文章:
** [## 甘——甘黑帮综论(下)
本文研究了 GAN 研究的动机和改进方向。通过在一个…
medium.com](https://medium.com/@jonathan_hui/gan-a-comprehensive-review-into-the-gangsters-of-gans-part-2-73233a670d19)
了解更多 GANs 的酷炫应用:
[## GAN——GAN 的一些酷应用。
在 GAN 开发的最初几年,我们取得了令人瞩目的进展。再也没有邮票大*的面部照片了…
medium.com](https://medium.com/@jonathan_hui/gan-some-cool-applications-of-gans-4c9ecca35900)
本系列的所有文章。
[## GAN — GAN 系列(从头到尾)
我们文章的完整列表涵盖了 GAN 的应用、问题和解决方案。
medium.com](https://medium.com/@jonathan_hui/gan-gan-series-2d279f906e7b)
参考
训练 GANs 的改进技术**
GANGogh:用 GANs 创造艺术
原文:https://towardsdatascience.com/gangogh-creating-art-with-gans-8d087d8f74a1?source=collection_archive---------1-----------------------
Novel Generation of Flower Paintings
简介:
这里介绍的工作是肯*·琼斯和德里克·博纳菲利娅(均为威廉姆斯学院 2017 级)在教授安德里亚·丹*卢克的指导下进行的长达一个学期的独立研究的结果。与这个项目相关的代码可以在 https://github.com/rkjones4/GANGogh找到。Kenny 和 Derrick 明年都将作为软件工程师前往脸书,并希望继续研究 GANs。
背景:
生成敌对网络(GANS)是由伊恩·古德菲勒等人提出的。艾尔。在 2014 年的一篇论文中。gan 解决了深度生成模型与深度判别模型相比缺乏相对成功的问题。作者引用最大似然估计的难以处理的本质作为这种差异的原因,最大似然估计是大多数生成模型所必需的。因此,gan 被设置为利用深度判别模型的强度来绕过最大似然估计的必要性,从而避免传统生成模型的主要缺陷。这是通过使用相互竞争的生成模型和判别模型来训练生成器来实现的。本质上,“生成模型可以被认为类似于一队伪造者,试图生产假币并在不被发现的情况下使用,而辨别模型类似于警察,试图检测假币。这场游戏中的竞争促使两个团队改进他们的方法,直到无法区分假冒品和真品。”更具体地说:
为了了解发生器在数据 x 上的分布 Pg,我们定义了输入噪声变量 Pz(z)的先验,然后将到数据空间的映射表示为 G(z;θg),其中 G 是由具有参数θg 的多层感知器表示的可微分函数。我们还定义了第二个多层感知器 D(x;θd ),它输出单个标量。D(x)代表 x 来自数据而不是 Pg 的概率。我们训练 D 以最大化为训练样本和来自 G 的样本分配正确标签的概率,同时训练 G 以最*化 log(1D(G(z))。换句话说,D 和 G 用价值函数 V (G,D)玩以下两人极*极大博弈:min G max D V (D,G)= Ex∾Pdata(x)[log D(x)]+Ez∾Pz(z)[log(1d(G(z))]。(1)"
该游戏通过交替训练 G 和 D 来进行,直到达到纳什均衡,并且 G 产生的样本与数据集中的样本无法区分。该公式立即受到怀疑,因为该论文的作者解释说,这种方法会导致饱和梯度,因此他们在实际训练时使用了不同的公式。然而,在发表时,这一公式产生了一些已经发布的任何模型中最有前途的生成样本,并且它的一般结构允许其他人调整设计来创建问题的更细微的实例(good fellow et al .艾尔。2014).
辅助量词 GAN(AC-GAN)是 Augustus Odena 等人引入的。艾尔。2016 年。AC-GAN 为鉴别器增加了一个分类器层,为发生器增加了一个条件向量。然后,训练鉴别器,除了传统的真与假的 GAN 目标之外,还最*化分类误差。这种方法允许利用标签,并向 GAN 提供附加信息。此外,它还允许对发生器进行调节,以产生特定类别的样本。目前,这可能是最有效的条件 GAN,并且往往比使用未标记数据的 GAN 做得更好。这个模型利用了迁移学习和多任务学习(Odena et .艾尔。2016).
StackGAN 是由张等人介绍的。艾尔。2016 年。StackGAN 使用从递归神经网络检索的特征信息和两阶段图像生成过程——第一阶段从噪声向量创建低分辨率图像,第二阶段使用第一图像的编码来创建高分辨率图像。特征信息用于调节鉴别器和发生器。这种模型创造了高分辨率样品的艺术状态。
Wasserstein GAN(WGAN)是由 Martin Arjovsky 等人提出的。艾尔。并引入了一个基于理论和经验发现的新理论框架。通过这个新的框架,他们创建了 WGAN,该 WGAN 最*化了 wasserstein 距离的近似值,他们发现该距离对于生成性建模问题具有有用的理论属性,因为它在鉴别器中创建了更好的梯度,生成器可以更容易地从中学习(Arjovsky 等人。艾尔。2017).他们实施某些约束的方式被证明是不一致的,Ishaan Gulrajani 使用基于梯度的惩罚来约束鉴别器的斜率,从而对其进行了改进。该模型被发现在训练从通常模型到以前无法训练的模型的各种 gan 时非常健壮和有效(Gulrajani 2017)。
Wavenet 和 Conditional PixelCNN 是 2016 年谷歌出来的两个生成模型。GANs 也不是,但两者都利用了一个有趣的概念,叫做全球调节。全局调节的关键是使用调节向量,而不是在开始时一次性添加到噪声向量,而是作为神经网络中每个激活函数的调节向量。这允许比传统方法更强和更复杂的调节。他们还都使用门控乘法激活函数,这似乎与这种全局条件作用很好地啮合(van den Oord 2016 范登奥尔德 2016)。
目标:
我们本学期学习 GAN 的主要动机是试图将 GAN 衍生的模型应用于*说艺术的生成。深度学习中与艺术生成相关的许多工作都专注于风格,特别是特定艺术作品的风格。在诸如艺术风格的神经算法等论文中,深度学习网络学习 1)将一件艺术品的风格与其内容区分开来,2)将该风格应用于其他内容表示。通过建立 GAN 模型,我们希望建立一个深度网络,不仅能够学习许多不同艺术作品的风格和内容组件的分布,而且能够以新颖的方式组合这些组件来创建新的艺术作品。新颖内容生成的任务比将一个特定艺术作品的风格应用到另一个艺术作品的内容要困难得多。
数据集和集合:
由于 GAN 的生成组件只能学习表示呈现给鉴别器的真实分布,因此选择合适的绘画数据集对我们来说是一个至关重要的决定。我们首先尝试使用仅来自一位艺术家的绘画数据集:莫奈。经过几次初始测试后,我们发现我们在这个数据集上的模型收敛很差,因为只有 1200 幅画的数据集太*了。我们需要找到一种方法来增加我们的数据集的大*,所以我们求助于 wikiart 数据库,这是一个超过 100,000 幅绘画的集合,所有这些绘画都标有风格,流派,艺术家,绘画制作年份等(wikiart)。从这个数据集,我们知道我们将 1)有足够的数据使我们的模型可能收敛,2)我们将能够使用标记信息来提高我们的网络的学习能力:在 GAN 场景中,当训练时使用额外的条件信息通常是有帮助的,特别是当学习具有清晰子分布的分布时(即,风景与肖像)。在我们模型的最终版本中,我们通过创建 python 脚本来构建数据集,直接从 wikiart 网站上抓取超过 80,000 张单独的图像,同时保留每张图像的风格和流派标签。
型号:
在设计我们的模型时,我们希望在典型 AC-GAN 框架的扩展中利用改进的 wasserstein 度量的能力。在一个高层次上,这意味着我们最初在改进的 wasserstein 模型下设置我们的鉴别器和生成器,但是除此之外,我们还向我们的鉴别器添加了一个分类组件,它还将尝试预测给定绘画的流派。然后,我们的生成器被扩充以接收标签数据的一个热点向量,其目的是影响所生产的绘画的流派。我们可以通过向我们的鉴别器的成本函数添加一个惩罚项来加强这种度量,该惩罚项试图最*化它对给定绘画的真实流派的流派预测的交叉熵,并向我们的生成器添加一个惩罚项,试图最*化鉴别器的预测与它根据条件向量被指示做出的流派的交叉熵。
我们对标准 GAN 模型进行的另外两项修改是包括了预训练和全局调节。这两个添加都是在我们观察到我们的模型在第一次迭代中非常注重产生“真实”与“虚假”图像的趋势后做出的,只是后来才学会在调节流派时提供不同类型的表示。我们假设其中一个原因是,当开始训练时,我们的鉴别器根本没有学会流派之间的区别,结果是生成器不能像我们希望的那样早地开始区分。我们提出的解决方案是在任何生成器训练之前对我们的鉴别器进行预训练,通过这种方式让我们的鉴别器对不同流派之间的差异有一个初步的了解。在普通 GAN 公式中,这将导致有问题的行为和较低的收敛机会,但当我们使用 wasserstein 度量时,它限制了鉴频器的功率,并始终为发生器提供平滑的梯度,我们实际上在此框架下达到了更优化的状态:在 GAN 设置的“优化”公式中,我们将在每个发生器训练步骤之前训练鉴频器收敛。
我们包含的全局条件再次允许我们的生成器更好地区分其产生的内容,作为其条件向量的结果。全局调节背后的思想是,每当我们在网络中的层之间执行激活功能时,我们可以使用调节向量来影响该激活如何发生,并且可以在逐层的基础上不同地使用该调节向量。我们选择使用来自 Conditional PixelCNN 和 Wavenet 的条件门控乘法激活函数。据我们所知,这是首次将全局调节应用于 GAN 框架。
详细架构:
发电机:
鉴别器:
结果:
在这里,我们展示了一系列从我们的三个流派中挑选出来的照片。
鲜花:
风景:
肖像:
由于我们的鉴别器的性质,我们能够使用它来选择我们的生成器产生的“好”图像。具体来说,由于我们的鉴别器能够对图像的真实性进行分类和判断,我们可以为特定的流派产生一组生成器图像,并从这些图像中要求鉴别器选择它 1)以高置信度分类为该流派并且 2)还判断具有高真实性值的图像。这就是产生上述图像的方法。
我们也可以在一个静态噪声向量下,通过改变给定的条件信息,来观察发生器是如何区分流派的。所有流派的这些图片都可以在附录中看到。这里要注意的是,虽然生成器已经明确地学会了产生不同种类的流派,但是它们并没有像我们所希望的那样被区分开来。此外,所产生的艺术作品的质量也有很大的差异,其中一些所产生的图像比其他图像好得多,即使对于给定的噪声矢量,在特定的流派中也能更真实地表现出来。我们认为这种现象的原因再次是,我们的模型学习“真实”与“虚假”艺术的表现比在给定的“流派”中创作艺术要容易得多。通过增加预训练和全局调节,我们在一定程度上缓解了这个问题,但显然没有完全解决它。我们面临的另一个挑战是,一些艺术流派比其他流派复杂得多,或者差异更大。特别是,这导致我们的生成器在生成某些类型(如神话画和动物画)时性能不佳,尽管我们假设给定更大的数据集,我们的模型也应该能够生成这些类型的真实示例。
虽然我们在这个项目中的主要动机是生成图像,但我们也能够通过将它作为分类器来评估我们的鉴别器的有效性。我们在训练集和大*为训练集 1/20 的测试集上测量了我们的分类能力,并在我们的测试集中获得了 90%以上的分类准确率。我们注意到,虽然我们的分类精度并不严格,但它优于在相同数据集上执行的其他分类指标,Wai Ren Tan 在 2016 年在大约相同的数据集上获得了 74.14%的分类精度(我们的数据集只是略有不同,因为我们在不同的时间点抓取了 wikiart 网站)(Tan 2016)。
未来工作:
我们项目中的一个实质性限制因素是我们对计算资源的访问。使用只有 2GB 内存的 GPU,我们被迫坚持生成 64x64 像素的图像,因为任何更高的分辨率都迫使我们的批量大*和模型的*数显著减少。当将我们的 64x64 模型生成的图像与我们最初的 32x32 模型进行比较时,我们注意到我们的模型有了显著的改进,因此我们假设,通过增加计算资源,允许缩放到 128x128 图像,在我们当前的架构下,图像的质量也会显著提高。在考虑将艺术生成的问题扩展到更大的图像尺寸(如 256x256)时,我们认为受 StackGAN 影响的架构使用我们提出的两个 GAN 模型可能会非常有效。我们认为这种架构可以提供的一个实质性好处是,我们的阶段 I GAN 可以作为一种强制区分不同类型的方式,因此阶段 II GAN 在阶段 I 图像上进行调节时,将更适合于克服我们在模型中看到的困难,其中具有不同调节信息的噪声向量映射到相似的图像。我们还注意到,这种两层 GAN 模型可以通过额外的调节信息来改进,具体来说,我们建议,除了我们的模型中描述的流派调节设置之外,可以在第二阶段鉴别器和第二阶段发生器的输入中使用另一个具有风格信息的热矢量,然后可以进一步划分所生成的艺术组合,例如文艺复兴肖像与抽象肖像。
结论:
虽然我们不认为我们的模型“解决”了艺术生成的问题,但我们希望能够对使用 GANs 生成新艺术的方式提供见解。具体来说,我们已经表明,在正确的条件度量下,wasserstein 风格的 GANs 能够以一种有用的方式考虑条件信息,用于“硬”图像分布。此外,我们已经证明了全局调节是对 GAN 框架的有效补充。我们还指出了我们为特定流派选择的鉴别图像,以验证这一研究路线,因为很明显,我们的生成器在为特定流派制作*说艺术方面做得非常出色。
作品引用:
Arjovsky、Martin、Soumith Chintala 和 Léon Bottou。"瓦瑟斯坦·甘" arXiv 预印本 arXiv:1701.07875 (2017)。
伊恩·古德菲勒等着《生成性对抗性网络》神经信息处理系统的进展。2014.
改善瓦瑟斯坦甘斯的训练。 arXiv 预印本 arXiv:1704.00028 (2017)。
奥登纳,奥古斯塔斯,克里斯多佛·奥拉和黄邦贤·史伦斯。"使用辅助分类器的条件图像合成." arXiv 预印本 arXiv:1610.09585 (2016)。
谭,,等。《不是一根管子:一个用于美术绘画分类的深度卷积网络》图像处理(ICIP),2016 年 IEEE 国际会议上。IEEE,2016。
《Wavenet:原始音频的生成模型》 CoRR abs/1609.03499 (2016)。
用像素 cnn 解码器生成有条件的图像。神经信息处理系统的进展。2016.
*基亚特。https://www.wikiart.org/
张,韩,等。〈堆叠式甘:利用堆叠式生成对抗网络进行文字到照片的真实感图像合成〉。 arXiv 预印本 arXiv:1612.03242 (2016)。
附录:
用相同的噪声矢量但不同的调节矢量产生的图像。
摘要:
动物绘画:
城市景观:
比喻:
花卉画:
风俗画:
风景:
玛丽娜:
神话绘画:
裸体画:
肖像:
宗教绘画:
静物:
象征性绘画:
去神秘化的甘——他们到底学到了什么?
原文:https://towardsdatascience.com/gans-demystified-what-the-hell-do-they-learn-142575c878db?source=collection_archive---------7-----------------------
可视化生成性对抗网络
本文是研究论文“ 甘剖析:可视化和理解生成性对抗网络 ”的总结。本文对 GANs 的内部表示提供了极好的见解,并对以下问题给出了严密的回答。
甘一家到底在学什么?我特别指的是发电机。我们都见过 GANs 产生的惊人结果,在某些情况下几乎与人类的工作无法区分。但是它们是如何表示学到的知识的仍然是一个谜。他们只是简单地学习像素模式并合成他们所看到的吗?还是他们真的从训练数据中捕捉到了复杂的关系?
本文试图解释 gan 的表示,并举例说明可视化和调试它们的技术。它使用两个阶段来实现。
Overview of the work. Watch the demo video here
解剖
剖析的目的是识别生成器中层的输出所代表的对象类。G 中的一个特殊单位代表树吗?
一些术语:
单元:发电机的各通道特性图 G
r:一层发电机的输出
基于 Bau 等人(2017),过滤器的特征图给出了对象类分割的良好近似。对于我们感兴趣的每个对象类,我们首先计算生成的图像中该类的分割掩码。我们使用下面的公式对单元 u 的特征图进行上采样和阈值处理。然后,我们取这个阈值化的、上采样的特征图和该类的分段掩码之间的 IOU。
∧ 表示交集, ∨ 表示并集。 s_c(x) 表示图像 x 中特定类别 c 的分割掩模。上面也提到了计算特定单元和类的阈值的公式。简而言之,上面的公式给出了一个度量一个单位 u 多少代表 c 类。你可以在论文中读到更多关于阈值公式背后的直觉。
1
因此,通过对每个类 c 获得的值的这些分数进行排序,对单元所代表的概念(对象类)进行排序
TLDR;解剖允许你发现与一个对象类最匹配的单元。但这并不一定意味着他们要对产生它们负责。
干涉;干预
干预旨在发现一组单元是否导致对象类别 c。这是通过打开和关闭单元并观察对生成的图像 g 的影响来完成的。
r: 张量输出(激活图)来自生成图像 G 中某一特定层的 G
U: 单位集 P: 像素
消融是指通过将 U 中的单元设置为 0 来关闭它们。另一方面,插入强制 U 中的单位等于 k ,每类常数 a。通过取引起 c 的单元的特征图的平均值来计算 c 类的 k。
上面的公式给出了多少单位 U 负责生成 c 类的度量。该度量被命名为平均因果效应 (ACE) 。这里, s_c(x) 表示像素 p 处的图像 x 中的 c 类分割图。因此,基本上,插入和切除对 G 中 c 类分割图的因果影响之间的差异。
但是我们怎么知道如何选择最优的单位 U 呢?很难进行彻底的搜索来选择最佳组合。这是通过使用一个巧妙的目标函数,并将这项工作外包给梯度下降来完成的。
我们将 U 设为整个单元集,但是用参数向量α对它们进行加权。随机梯度下降然后被用于最大化目标函数(ACE)和最*化最优集合中的单元数量(通过使用阿尔法的 L2 正则化项)。
L2 regularisation term is added to minimize number of units in the optimal set
下图显示了消融导致树木的单元如何成功地从生成的图像中移除树木。
Ablating units to remove trees
简单地说,结果
层间差异:根据结果,第一层与井对象类别不匹配。这具有直观的意义,因为早期的图层通常表示原始特征。中间层有许多匹配语义对象和对象部分的单元。结束层匹配局部像素模式,如材料、边缘和颜色。
GAN 架构之间的差异:本文还通过检查单元讨论了不同架构在内部表示方面的比较。
经由插入的上下文关系:该论文还描述了通过强制单元将特征插入到生成的图像的特定位置。一个有趣的观察是,像门这样的物体只能被插入到视觉上有意义的特定位置(如窗户附近的建筑、砖块)。这表明 GANS 实际上捕捉了物体之间的关系,而不仅仅是像素模式。
上图说明了对象类的生成是如何高度依赖于本地上下文的。插入的实际效果因发生的地点而异。
诊断 GANs
通过使用干预技术,我们可以研究生成的图像中错误/不期望的部分和伪影的原因。通过手动注释和去除引起的单元,GAN 的结果可以得到相当大的改善。下图说明了消融伪影产生单元如何产生可见结果。
使用这个框架,您可以手工定制和影响 GAN 的结果。增强或减少某些对象类的存在(在一定程度上)是相对简单的。
最后的想法
这篇论文很好地试图揭开 GANs 的神秘面纱,这是一个迄今为止相对未被探索的话题。他们的框架使研究人员和实践者能够更好地调试、改进和理解他们的模型。
所讨论的调试方法大多基于人工监督。然而,我相信本文中介绍的推理和技术可以潜在地用于开发更自动化的技术来改进 GANs(本文讨论了一种自动识别工件单元的技术)。
演职员表:取自论文的想法、公式和图像。
参考
【甘剖析:可视化与理解生成性对抗网络
项目官网(附 Github 代码、演示视频、幻灯片等)
交互式甘绘制工具
甘斯·恩罗斯
原文:https://towardsdatascience.com/gans-n-roses-c6652d513260?source=collection_archive---------1-----------------------
“本文假设读者熟悉神经网络和 Tensorflow 的使用。如果没有,我们会要求您阅读迈克尔·*尔森关于深度学习的 这篇 文章,并熟悉如何使用tensor flow。”
想象有一天,我们有了一个神经网络,它可以看电影并生成自己的电影,或者听歌并创作新的电影。这个网络会从所见所闻中学习,而不需要你明确地告诉它。这种让神经网络学习的方式被称为无监督学习。
在过去的三年里,事实上以无人监督的方式训练的 GANs(生成对抗网络)获得了很多关注,现在被认为是人工智能领域最热门的话题之一。这是《脸书 AI》的导演 Yann LeCun 对他们的看法:
生成对抗网络是近十年来机器学习中最有趣的思想。
gan 是做梦的神经网络,在观看其中一些图像后生成图像。嗯,这个可以用来做什么?为什么这很重要?
Generated bedroom images. Source: https://arxiv.org/abs/1511.06434v2
直到最近,神经网络(特别是卷积神经网络)只擅长分类任务,例如在猫和狗或者飞机和汽车之间进行分类。但是现在它们可以用来生成猫或狗的图片(尽管它们看起来很奇怪),这告诉我们它们已经学会了特征。这向我们表明,他们能够理解一个物体本身的特征。
GANs 的这种非凡能力可用于许多令人惊叹的应用,例如:
- 给定文本描述生成图像。查看此链接:
Text to Image. Source: https://arxiv.org/pdf/1605.05396v2.pdf
[## 2016 年深度学习的主要进展- Tryolabs 博客
过去几年,深度学习一直是机器学习社区的核心话题,2016 年并不是…
tryolabs.com](https://tryolabs.com/blog/2016/12/06/major-advancements-deep-learning-2016/)
- 图像到图像的翻译:
这可能是迄今为止 GAN 最酷的应用。图像到图像转换可用于从草图生成逼真的图像,将白天拍摄的照片转换为夜间图像,甚至将灰度图像转换为彩色图像。
Image to Image Translation. Source: https://phillipi.github.io/pix2pix/
请点击此链接了解更多详情:
[## 基于条件对抗网络的图像到图像翻译
基于条件对抗网络的图像到图像翻译
phillipi.github.io](https://phillipi.github.io/pix2pix/)
了解了 GAN 的能力之后,让我们一起登上宣传列车,实现一个简单的 GAN 来生成玫瑰的图像。好吧,等等,但是为什么是玫瑰?
"我们不想用一个故事来烦你,但只能说这篇文章是在听了枪炮玫瑰乐队的一首歌后得到的灵感(现在知道标题了吧??)”
让我们看看甘到底是什么:
在我们开始构建 GAN 之前,让我们了解它是如何工作的。生成式对抗网络包含两个神经网络:鉴别器和生成器。鉴别器是卷积神经网络(不知道 CNN 是什么?看看这篇精彩的文章)学习区分真实和虚假的图片。真实的图像来自数据库,假的来自生成器。
Discriminator
该生成器的工作方式类似于反向运行的 CNN,它将一个随机数向量作为输入,并在输出端生成一个图像。
Generator
我们稍后将讨论生成器和鉴别器的工作和实现,但现在让我们看一个著名的例子来解释 GANs(解释大量借用了滥用生成性对抗网络来制作 8 位像素艺术)。
让我们把生产者想象成一个伪造者,把鉴别者想象成一个必须辨别真假货币的警察。首先,让我们保证伪造者和警察的工作都一样糟糕。因此,伪造者首先产生一些随机的看起来有噪声的图像,因为它对货币的样子一无所知。
Noisy Image by the Counterfeiter
现在,警察被训练来区分伪造者制造的这些假图像和真货币。
Train the Police Officer
伪造者现在知道其图像被归类为假的,并且警察正在寻找货币中的一些明显特征(例如颜色和图案)。伪造者现在知道了这些特征,并产生了具有这些特征的货币(在这种情况下是图像)。
Training the Counterfeiter
现在,再次向警官展示来自数据集的真实货币和来自伪造者的新的改进(希望如此)图像,并要求对它们进行分类。因此,官员将会学到真实图像的更多特征(如货币上的脸)。
Train the Police with the new fake images
伪造者再次学习这些特征并产生更好看的假图像。
Train the counterfeiter again
伪造者和警察之间的这种持续的斗争一直持续到伪造者制造出看起来和真的一模一样的图像,而警察无法对它们进行分类。
Real or Fake?
GANs N ' Roses 在 Tensorflow 上的实现:
让我们使用 tensorflow,不使用任何其他东西(除了 pillow),构建一个简单的 DCGAN(深度卷积生成对抗网络)。
但是什么是 DCGAN 呢?
DCGAN 是 vanilla GAN 的修改版本,以解决 vanilla GAN 的一些困难,例如:使假图像看起来视觉上令人愉悦,在训练过程中提高稳定性,以便生成器不会通过重复输出符合鉴别器正在寻找的数据分布的图像来发现鉴别器中的缺陷,但与真实图像相差甚远。
这是我们试图构建的鉴别器架构:
Discriminator Architecture
可以看出,它接受一个图像作为输入,并输出一个 logit (1 表示真类,0 表示假类)。
接下来,我们有生成器架构,它由 conv 转置层组成,接受一组随机数作为输入,并在输出端生成图像。
Generator Architecture
DCGANs 提出的修改直接取自这份文件:
- 用步长卷积(鉴别器)和分数步长卷积(生成器)替换任何池层。
- 在发生器和鉴别器中使用 batchnorm 。
- 为更深层次的架构移除完全连接的隐藏层。
- 在生成器中对所有层使用 ReLU 激活,但输出层除外,它使用 Tanh。
- 在所有层的鉴别器中使用 LeakyReLU 激活。
让我们从收集玫瑰的图像开始。一个简单的方法是在谷歌上搜索玫瑰图片,并通过使用 ImageSpark 等 chrome 插件下载搜索结果中的所有图片。
我们已经收集了 67 张图片(越多越好),可在这里找到。将这些图像提取到以下目录中:
可以通过在 Github 上克隆这个 repo 来获得代码和数据集。
[## 纳雷斯 1318/甘斯玫瑰
GANs_N_Roses -使用深度卷积生成敌对网络,通过 tensorflow 生成玫瑰图像。
github.com](https://github.com/Naresh1318/GANs_N_Roses)
现在我们有了图像,下一步是预处理这些图像,将它们重新整形为 64 * 64,并将它们缩放到-1 到 1 之间的值。
我们将首先写出稍后可用于构建卷积、卷积转置、密集全连接层和 LeakyReLU 激活的函数(因为它在 Tensorflow 上尚不可用)。
Function to implement convolutional layer
我们使用get_variable()
而不是通常的Variable()
在 tensorflow 上创建一个变量,以便稍后在不同的函数调用之间共享权重和偏差。查看这篇的帖子,了解更多关于共享变量的信息。
Function to implement convolution transpose
Function to implement dense fully connected layer
Leaky ReLU
下一步是构建生成器和鉴别器。先从我们的主角,发电机说起。我们需要构建的生成器架构如下所示:
Again, the Generator Architecture we’re trying to implement
generator()
函数构建了一个发电机(dah!)使用上图中的架构。已满足 DCGAN 要求,例如移除所有完全连接的层、仅在生成器中使用 ReLU 以及使用批量标准化。
类似地,鉴别器可以容易地构造如下:
所需的架构:
The Discriminator architecture
我们再次避免了密集的全连接层,在鉴别器处使用了泄漏 ReLU 和批量标准化。
现在是有趣的部分,训练这些网络:
鉴别器和发生器的损失函数如下所示:
Discriminator loss (This must have a negative sign)
Generator loss
其中 x 代表实像,z 是输入发生器的噪声矢量。
我们将把随机输入传递给生成器,zin 的形状将是[BATCH_SIZE,Z_DIM],生成器现在应该在其输出中给出 BATCH_SIZE 数量的假图像。生成器输出的大*现在将是[BATCH_SIZE,IMAGE_SIZE,IMAGE_SIZE,3]。这是损失函数中的 G(z)项。
D(x)是接受真实图像或虚假图像的鉴别器,并被训练来区分它们。为了在真实图像上训练鉴别器,我们将把真实图像批次传递给 D(x ),并将目标设置为 1。类似地,为了在假图像(来自生成器)上训练它,我们将使用 D(G(z))将生成器输出连接到鉴别器输入。
鉴频器的损耗通过 tensorflow 的内置函数实现:
接下来,我们需要训练生成器,使 D(G(z))将输出一个 1,也就是说,我们将固定鉴别器上的权重,并仅支持生成器权重,以便鉴别器总是输出一个 1。
因此,发电机的损失函数为:
接下来,我们将收集鉴别器和生成器的所有权重(稍后需要仅训练生成器或鉴别器):
我们使用 tensorflow 的 AdamOptimizer 来学习权重。下一步是将需要修改的权重分别传递给鉴别器和生成器优化器。
最后一步是运行会话,并将所需的图像批次传递给优化器。我们将训练模型 30000 次迭代,并定期显示鉴别器和发电机损耗。
为了使超参数的调整更容易,并保存每次运行的结果,我们实现了 form_results 函数并创建了一个名为mission_control.py
的文件。
使用mission_control.py
文件可以修改网络的所有超级参数,稍后运行main.py
文件将自动为每次运行创建文件夹,并保存 tensorboard 文件和生成的图像。
我们可以通过打开 tensorboard 并将其指向在每个运行文件夹下创建的 Tensorboard 目录来查看训练期间每次迭代的鉴别器和发电机损耗(查看 GitHub 链接以了解更多详细信息)。
Variation of Generator loss during training
Variation of Discriminator loss during training
从这些图中可以看出,鉴别器和发生器损耗在训练阶段不断增加和减少,表明发生器和鉴别器都试图超越彼此。
该代码还保存每次运行生成的图像,其中一些图像如下所示:
在第 0 次迭代时:
第 100 次迭代:
第 1000 次迭代:
图像在第 30000 次迭代时被过度拟合:
训练阶段生成的图像如下所示:
这些图像是有希望的,但是在大约 1000 次迭代之后,可以看到生成器只是从训练数据集中再现图像。我们可以使用更大的数据集,并针对更少的迭代次数对其进行训练,以减少过度拟合。
gan 易于实施,但如果没有正确的超参数和网络架构,则难以训练。我们写这篇文章的主要目的是帮助人们开始使用生成网络。
别人在干嘛:
- 用条件对抗网进行图像到图像的翻译。
- 瓦瑟斯坦甘。
- Pytorch 实施 GANs 。
感谢您阅读这篇相当长的中型文章。如果你觉得它有帮助,请考虑分享它。如对本文有任何疑问,请随时联系我们。
GANS —第二部分:用于生成图像的深度卷积 GANS
原文:https://towardsdatascience.com/gans-part2-dcgans-deep-convolution-gans-for-generating-images-c5d3c7c3510e?source=collection_archive---------1-----------------------
深度卷积 GAN 或 DCGAN 在生成器和鉴别器中使用卷积层。在的论文中首次探讨了 DCGAN 架构。还需要使用批量标准化来训练卷积网络。
发电机
第一层是一个完全连接的层,它被重新塑造成一个又深又窄的层,有点像原始 DCGAN 纸中的 4x4x1024。然后我们使用批处理规范化和一个泄漏的 ReLU 激活。接下来是转置卷积,通常情况下,您会将前一层的深度减半,宽度和高度加倍。同样,我们使用批处理规范化和泄漏 ReLU。对于这些层中的每一层,一般的方案是卷积>批范数>泄漏 ReLU。
您继续像这样堆叠层,直到您获得形状为 32x32x3 的最终转置卷积层。下面是最初的 DCGAN 论文中使用的结构:
def conv_transpose_layer(prev_layer, filter, kernel_size, strides, is_training, alpha):
x = tf.layers.conv2d_transpose(prev_layer, filter, kernel_size, strides, 'same')
x = tf.layers.batch_normalization(x, training=is_training)
x = tf.maximum(x, alpha*x)
return xdef generator(z, output_dim, reuse=False, alpha=0.2, training=True):
with tf.variable_scope('generator', reuse=reuse):
# First fully connected layer
x1 = tf.layers.dense(z, 4*4*512)
# Reshape it to start the convolutional stack
x1 = tf.reshape(x1, (-1, 4, 4, 512))
x1 = tf.layers.batch_normalization(x1, training=training)
x1 = tf.maximum(x1, alpha*x1)
# 4x4x512 now x2 = conv_transpose_layer(x1, 256, 5, 2, training, alpha)
# 8x8x256 now
x3 = conv_transpose_layer(x2, 128, 5, 2, training, alpha)
# 16x16x128 now
# Output layer, 32x32x3
logits = tf.layers.conv2d_transpose(x3, output_dim, 5, 2, 'same')
# 32x32x3 now
out = tf.tanh(logits)
return out
鉴别器
鉴别器基本上只是一个卷积分类器。请注意,在 DCGAN 论文中,他们仅使用步长卷积层进行了所有下采样,没有使用最大池层。
在除第一卷积和输出层之外的每一层上使用tf.layers.batch_normalization
进行批量归一化。同样,每一层应该看起来像卷积>批处理规范>泄漏 ReLU。
def conv_layer(prev_layer, filters, is_training, alpha, batch_norm=True):
conv_layer = tf.layers.conv2d(prev_layer, filters, 5, 2, 'same', use_bias=False, activation=None)
if batch_norm:
conv_layer = tf.layers.batch_normalization(conv_layer, training=is_training)
conv_layer = tf.maximum(conv_layer, alpha*conv_layer)
return conv_layerdef discriminator(x, reuse=False, alpha=0.2):
with tf.variable_scope('discriminator', reuse=reuse):
# Input layer is 32x32x3
x1 = conv_layer(x, 64, True, alpha, False)
# 16x16x64 x2 = conv_layer(x1, 128, True, alpha, True)
# 8x8x128 x3 = conv_layer(x2, 256, True, alpha, True)
# 4x4x256 flat = tf.reshape(x3, (-1, 4*4*256)) logits = tf.layers.dense(flat, 1)
out = tf.sigmoid(logits)
return out, logits
gan 对超参数非常敏感。为了找到最佳的超参数,进行了大量的实验,以使发生器和鉴别器不会相互干扰。
real_size = (32,32,3)
z_size = 100
learning_rate = 0.0002
batch_size = 128
epochs = 25
alpha = 0.2
beta1 = 0.5
https://github . com/mchablani/deep-learning/blob/master/DCGAN-svhn/DCGAN _ exercises . ipynb
学分:来自课堂讲稿:https://classroom.udacity.com/nanodegrees/nd101/syllabus
甘斯全神贯注
原文:https://towardsdatascience.com/gans-with-attention-3b90802921af?source=collection_archive---------4-----------------------
一点背景:
一个生成对抗网络 (GAN)串联着两个网络:一个生成器和一个鉴别器。解释 GANs 的流行例子涉及假币。生成器试图创建一个看起来像美钞的图像,鉴别器试图将伪钞与真美钞的图像区分开来。在训练了两个网络之后,生成器已经学会创建看起来非常像一美元钞票的图像,而鉴别器已经学会可靠地将这些伪造图像与真美元区分开来。
不幸的是……
这是一个一次性过程。生产者制造假货,鉴别者试图识别假货,然后根据他们的表现给他们打分。没有反馈,没有进一步调整;该伪造图像被丢弃。
在递归神经网络中使用的类似方法是演员-评论家模型。通常只有在表演结束时才能得到“分数”的演员,反而会在表演过程中被评论家“打分”。评论家学会预测哪些动作会影响最终得分,演员学会执行影响最终得分的动作,通过评论家的即时评分。这还是一个一次性的过程。作为对批评的回应,这位演员无法“再次拍摄那个场景”。
那么,修改呢?
另一个比喻,来描述一个更好的方法:一个作者产生他们的美元图像(或文本块,或动作串……)并将其发送给编辑。然后编辑器在中发现错误的地方标记该美元图像,并将其发送回作者。作者将他们的注意力集中在那些错误上,并改正它们,将新草稿发回给编辑……重复这个循环,直到编辑发现没有错误。作者网络学会了用注意力过滤器拍摄图像,然后将变化应用到高亮显示的区域。编辑器学习获取图像及其目标,并突出显示应该改变的区域。
这种作者-编辑模型支持有价值的新行为。一旦作者被训练根据编辑的标记改编图像,一个人也可以通过选择他们 想要改变的区域 来纠正作者。这种用户输入可以引导不同的作者将他们的注意力集中在图像的不同区域上。用户可以选择图像的一些区域,并应用“冬至春作者”的注意力,而选择同一图像的其他区域,以应用“现实生活中的赤壁作者”。每个作者根据自己的关注进行修改。你可以做编辑。**
不止如此……
这位编辑受过突出错误的训练。因此,如果作者-编辑模型是在文本上训练的,那么编辑有一个直接的应用:纠正人类所写的错误!(比如语法上……)
此外,作者-编辑网络可以与人类实时合作。例如,你可以画一种动物——狐狸?—它被传递给编辑,编辑试图识别应该修改的区域。例如,编辑可能会在你的 fox-drawing 上突出显示线条可以平滑的区域,或者建议在哪里改变它们的位置、比例和整体纹理。
编辑也会犯错!它可能会认为你在画一只猫,不恰当地突出了几个区域。您可以查看这些高亮区域,替换 编辑的高亮。然后这些区域可以交给作者,作者将网络的注意力集中在区域上,并进行修改。你审核作者的更新稿,可以自己修改。然后,发给编辑……重复,直到你满意为止。**
选择备选方案:
这种作者-编辑模式也使得人们可以借助 多个 作者和编辑共同创作 *内容。作者的注意力可以应用于不同的领域,也可以应用于同一领域。如果每个作者都活跃在不同的**区域,(就像之前提到的《冬去春来》和《赤壁的真实生活》的作者),他们的草稿可以合并。但是,当作者的关注区域 与 重叠时,作者各自提供一个替代方案,而你可以 选择应用哪个替代方案。***
(你可能有三个绘画风格的作者,并突出显示图像的相同区域,以查看他们每个人对该区域的建议。然后,你可以用不透明滤镜将每个作者的作品应用到你高亮区域的不同部分。在它们之间选择,零敲碎打!)
拥有多个编辑器提供了类似的好处——每个编辑器突出显示它认为应该修改的区域,然后你在他们建议的突出显示中进行选择。你也可以阻止编辑修改你想保留的东西!
修订历史培训:
作者-编辑 GAN 不同于现有的 GAN 架构,它通过在由编辑器生成的注意力域上训练作者,并通过多次修改来产生最终输出。在这种方式下,作者-编辑模型类似于具有注意力的递归神经网络:修订历史可以像 RNN 的行动历史一样“展开”,并且每个修订将注意力集中在新的相关领域。不过,修订不同于循环——RNN 描述的是一个序列,就像在迷宫中选择路径一样,而作者-编辑修订描述的是一种平衡,一个编者停止突出修改的落脚点。递归的 NNs 不能包含修订,但修订可以包含递归:作者可以在迷宫中写出选择的序列,它写了又写,直到编辑满意为止。:]
遗传算法+神经网络=两全其美
原文:https://towardsdatascience.com/gas-and-nns-6a41f1e8146d?source=collection_archive---------2-----------------------
神经网络与遗传算法相结合确实可以加速解决某个问题的学习过程。
所有的大公司现在都在使用神经网络(NNs) 和遗传算法(GAs) 来帮助他们的 NNs 更好更有效地学习。在本文中,我将讨论耦合 NNs 和 GAs 的利弊,并分享我自己的一些想法。我还将描述这个过程中使用的基本算法。
我偶尔会写这些有些简短但内容丰富的文章,帮助你了解更多关于 AI 和机器学习的知识。你可以在 twitter 上关注我的或者在这里关注我的来了解我的最新文章。你也可以在 twitter 上问我问题,或者在这里发表评论。
希望这篇文章能教会你一些新的东西!我们开始吧。
遗传算法在神经网络之前非常流行。因为,NNs 需要大量数据,而 GAs 不需要。遗传算法主要用于模拟环境和群体中实体的行为。它们主要用于学习我们知道答案的问题的解决途径。
气体今天仍然被使用,但是机器学习(ML)已经大部分接管。
它们是如何工作的
根据*基百科气体:
在计算机科学和运筹学中,遗传算法 ( GA )是一种元启发式算法,受自然选择过程的启发,属于进化算法(EA)的更大类别。遗传算法通常用于通过依赖诸如变异、交叉和选择之类的生物启发算子来生成优化和搜索问题的高质量解决方案。
如果这仍然不能理解,那么我确信丹*尔·希夫曼的气体播放列表会有所帮助。它帮助我了解了天然气的工作原理,总体而言,希夫曼的视频非常好。尽管我建议加快速度。
NNs 的问题是
NNs 帮我们解决了这么多问题。但是他们仍然有一个大问题。超参数!这些是唯一不能学习的价值观…直到现在。
注意:超参数是在给定问题的情况下,神经网络正确执行所需的值。
我们可以使用 GAs 来学习神经网络的最佳超参数! 这绝对牛逼!
现在,我们不必担心“知道正确的超参数”,因为它们可以使用 g a 来学习。同样,我们也可以用它来学习神经网络的参数(权重)。
因为在遗传算法中,实体学习特定问题的最佳基因组,这里,每个神经网络的基因组将是其超参数集。
解决问题
要解决超参数问题,我们需要做以下工作:
- 创建几个神经网络的群体。
- 将随机(在一个范围内)超参数分配给所有神经网络。
- 对一定数量的迭代执行以下操作:
- 同时或逐个训练所有神经网络。
- 在他们都完成培训后,计算他们的培训成本。
- 基于其成本计算每个神经网络的“适合度”(它在该迭代中做得有多好)。健身将被用来增加神经网络“繁殖”的机会适应度越高,它繁殖的机会就越大。然而,最好的神经网络将具有最低的成本。如果我们将那个神经网络的适应度设置为等于它的成本,那么最好的神经网络将有最少的机会被选择用于繁殖。我们可以把适应度指定为成本的倒数。因此,最低的成本,会有最高的适合度。有很多方法可以为适应度赋予更好的值,但这超出了本文的范围。
- 找出群体中的最大适应度(步骤 5 所必需的,根据步骤 5 的实现可以忽略)。
- 根据适合度的概率系统选择 2 个神经网络。我省略了对此的解释,因为这对某些人来说可能太复杂了。这里有一个视频,解释这个话题。
- 交叉两个神经网络的基因。这将创建一个“子”NN。这个神经网络应该具有第一个神经网络的一些性质和第二个神经网络的一些性质。这个过程也有许多不同的实现。
- 突变孩子的基因。变异是为了在遗传算法中保持一定的随机性。
- 对群体中的 NNs 数量执行步骤 5-7。您应该将创建的“子代”存储在新的总体中,并将新的总体赋给包含旧总体的变量。
注意:你应该创建一个你想学习其参数的神经网络类。然后,该群体最初应该包含同一个 NN 类的几个实例。还有,上面写的东西,都可以从希夫曼的播放列表中了解到。
执行上述所有步骤,在最新一代结束时,您的算法将找到包含具有最佳超参数的神经网络的群体。它将是种群中最健康的神经网络。下图试图解释这一过程。
Iterative process of fining hyper-parameters using GAs
另一个问题
这是一个学习你的超参数的好方法,但它也有自己的问题。最突出的两个问题是计算资源和时间。
同时或一个接一个地多次训练许多神经网络需要大量的时间和计算资源。这就限制了这种解决方案的实施,只有那些愿意投入资金和购买大量处理能力的人才能使用。
这也是它被大公司广泛使用的原因。
一个例子
不到一年前,OpenAIs Dota 2 bot 击败了一名职业 Dota 2 选手(文章和 YouTube 视频)。玩家花了几年时间学习和掌握的东西,机器人只花了几个星期。在我在 YouTube 上看到的一个视频中,一名 OpenAI 工程师解释了他们如何训练机器人。
他们用遗传算法来训练他们的机器人。因为他们有必要的处理能力,他们能够同时运行 Dota 2 的多个实例,每个实例都有一个玩游戏的机器人实例。他们花了两周的时间来教机器人这个过程。
想象一下这需要多大的处理能力。
结论
在我看来,天然气是很好的教导神经网络,但他们不会是我的第一选择。相反,我将尝试寻找更好的方法来学习神经网络的超参数。如果有的话,那就是。
然而,如果将来我获得了大量的处理能力,我一定会尝试这种方法。
就这样,希望你学到了新的东西!
如果你觉得这篇文章有帮助,请鼓掌。在 Twitter 上关注我和这里关注我的最新帖子。如果你有任何问题,你可以发微博给我,或者通过评论让我知道。我很乐意回答这些问题。
用于信息融合的门控多通道单元
原文:https://towardsdatascience.com/gated-multimodal-units-for-information-fusion-966a9a2e1c54?source=collection_archive---------13-----------------------
The output of the GMU architecture
深度学习已经在许多领域证明了它的优越性,在各种各样的任务中,例如图像分类和文本生成。处理涉及来自多个模态的输入的任务是一个有趣的研究领域。
门控多模式单元(GMU)是由最近的一篇论文提出的一种新的构建模块,该论文在 2017 年 ICLR 世博会上以研讨会的形式展示。这个构建模块的目标是以一种智能的方式融合来自多个不同模态的信息。
在这篇文章中,我将描述 GMU,并说明它如何在玩具数据集上工作。
建筑
给定不同模态的两种表示,xᵛ和 xᵗ(例如视觉和文本模态),GMU 块执行一种形式的自我注意
GMU architecture
描述 GMU 的方程相对简单:
(1) + (2)将表示转换成不同的表示,然后根据在(3)中计算的 z 在(4)中参与。因为 z 是 xᵛ和 xᵗ的函数,这意味着我们在处理自我关注机制。
GMU 背后的直觉是,它使用表示本身来理解哪个模态应该影响预测。考虑预测一个被拍照者的性别的任务,伴随着他的声音记录。如果给定示例的记录噪声太大,模型应该学会仅使用该示例中的图像。
综合数据
在论文中,他们描述了一个很好的合成数据集,展示了 GMU 是如何工作的。
在这里,我们将实现相同的数据集,并自己找出 GMU 是否真的有效(剧透:它有效)。
首先,让我们做导入:
生成数据
Data generating process
不要被这个图表吓到——稍后您会发现这个图表生成的数据的可视化。
基本上图中所说的是目标类 C 描述了模态 yᵛ和 yᵗ的值——当然带有一些随机性。
在下一步中,随机变量 M 决定忽略 yᵗyᵛ的哪个输入,而是使用 ŷᵗ.ŷᵛ的噪声源
最终,xᵛ和 xᵗ要么包含了能够描述目标类 C 的真实信息源,要么包含了随机噪声。
GMU 块的目标是成功地找出给定特定示例的哪个来源是信息来源,并对该来源给予全部关注。
Synthetic data. Color denotes the class C
创建模型
我将实现 GMU 的一个基本版本——只是为了让它更容易理解。
将代码一般化以处理两种以上的模态是很简单的。
训练模型
检查结果
损失看起来不错。
让我们看看 z 和预测是什么样子的。论文中还出现了以下可视化内容。
我们可以看到 z 的行为完全如我们所愿(左图)。它的好处在于,实际上只使用一种模态就可以预测远离边界线的点类。这意味着模型学会了何时忽略包含纯无预测噪声的模态。
为什么不用简单的 FF(前馈)?
如果我们忽略数据生成过程,只看数据点,显然有 4 个不同的集群。
这些集群不是线性可分的。虽然 GMU 为模型提供了容量以解释这种非线性行为,但人们可以改为向混合物中添加另一层,从而用简单的前馈(FF)网络解决问题。
普适逼近定理指出,一个包含有限个神经元的单隐层前馈网络,可以逼近连续函数……(*基 )
因此,实际上,对于这个人为的例子,一个简单的 FF 就可以完成这项工作。然而,引入新架构(在这种情况下是 GMU)的目的是引入归纳偏差,允许训练过程利用我们对问题的先验知识。
结论
对于涉及多模态的真实世界问题,作者声称 GMU 实现了优越的性能。他们使用基于情节和海报识别电影类型的任务来展示他们的方法。
GMU 很容易实现,如果您需要训练一个模型使用多种模态作为输入,将它放在您的工具箱中是值得的。为此,您可以为每个主机创建一个子网。子网络不必相同——例如,你可以用 CNN 做视觉模态,用 LSTM 做文本模态。重要的是每个子网络输出其模态的密集表示。然后,将这些表示送入 GMU 块,以便将信息融合成一个表示。融合的表示将被馈送到另一个子网络,其输出将是最终的预测。
本帖原帖www.anotherdatum.com。
神经网络中的门控和深度
原文:https://towardsdatascience.com/gating-and-depth-in-neural-networks-b2c66ae74c45?source=collection_archive---------6-----------------------
深度是现代神经网络的关键部分。它们通过构建层次规则来实现高效的表示。到目前为止,我们都知道这一点,所以我假设我不需要说服任何人,但如果你需要复习一下,这基本上是因为我们无法有效地建模许多数据分布,这些分布在没有指数数量的神经元的情况下用单个或几个函数出现。这些分布太复杂了,无法以这样一种直接的方式建模,但尽管如此,它们确实有结构,只是碰巧是分层的。换一种方式想,想象一下如果数据生成过程是而不是分层的。那么生成一个复杂的分布也需要指数级的资源。毫无疑问,有些过程是这样的。也就是说,我们所知道的关于这个世界的一件事是,它是由简单的部分组成的,但是把它们放在一起有时会产生极其复杂的行为。
不幸的是,我们的网络训练算法,误差反向传播,不喜欢当事情太多递归。考虑线性神经元链的情况。如果这些神经元的(范数)权重不等于 1,误差信号将连续收缩或增长。如果收缩太快,我们看到它消失了,如果增长太快,我们说它爆炸了。对于具有非线性激活函数的神经元,情况大致相同,只是我们考虑雅可比矩阵的范数,但基本上是一样的。缩放并不酷,因为这意味着当我们从损失向后传播误差时,我们看到信号变得不正常,这意味着对权重的更新是无用的,并且我们的网络训练发散。
很好,我们都熟悉消失和爆炸渐变。我们该怎么办?基本策略是确保所有缩放不会干扰误差信号,同时仍然支持深度。我们需要保护一些信号。
在前馈网络(FFNs)中,我们可以通过跳过连接来实现这一点。最简单的情况是剩余学习,从较低层到较高层的输出被加到该较高层的输出上。然后,连续的层只需要学习增量,因为它们已经从前一层的位置“开始”了。这种剩余被认为比从零开始构建新的转换更容易学习。
这样做的另一个原因是残余连接实际上使得从给定层到输出的路径更短。你所需要做的就是穿过连续层的剩余连接,直到你到达终点,跳过中间的层。碰巧的是,深度残差网络实际上具有明显*于指定深度的有效深度,因为这正是训练中发生的情况。换句话说,我们避免了很多不利的转变。这隐含地发生在剩余网络中,但是可以通过在每一层和输出之间具有被称为密集网络的连接来明确地实现。
顺便说一下,有可能从上一层的输出开始实际上会使学习下一层的最佳变换变得更加困难。或者至少,这可能是对许多层的低效使用。因此,我们引入了门的概念,并说让我们学习一个系数来衰减相对于普通堆叠层应该使用多少身份连接。然后,剩余网络成为具有加权跳跃连接的网络的特殊情况,称为公路网络。
这非常有趣,因为在某种意义上,我们已经为 FFNs 实现了一个内存,通过门控机制,我们可以了解何时访问该内存,何时忽略它。您已经在较低层创建了一些表示,该信号可以跳过许多层,并在其他地方找到自己。其他地方层上的(学习)门告诉你是否访问该信息。
现在让我们考虑一个不同的问题:序列建模。ffn 在这方面当然很棒,序列是证明深度的好方法。如果你使用卷积 FFN(现在每个人都这样),你实际上需要一定的深度来考虑输入中的长程相关性。这在语言建模中非常明显,因为长程相关性可能非常长。然后,跳过连接以及注意力之类的东西充当更细粒度信息的内存查找机制,以服务于更高级别的表示。这一切都很酷。
还有另一种有趣的方式来看待这个问题,那就是循环网络(RNNs)。在这种情况下,我们有一个单一的隐藏层,它应用于序列中的每个元素,然后在最后一个元素之后,您可以“及时”反向传播您的错误。所以你可以想象,当我们的梯度回到序列的开始时,它们会消失。然而,因为我们在每个序列步骤中使用相同的权重,所以在这里添加跳过连接没有意义。
相反,RNN 人所做的是用一种门控机制把其它*的记忆系统放进去。现在,您可以通过将信号写入某处的特殊状态来保护信号的某一部分,并了解何时将其读回。那么有效深度对 RNN 来说意味着什么呢?我不确定这是否真的比得上在序列方向上的深度概念,但无论如何这是一个有趣的类比。
想想我们根本没有解决渐变消失或爆炸的问题,这真的很有趣,我们只是回避了这个问题。所以现在我们可以问这是自然的还是怪异的。我碰巧觉得,我们能这么好地凭空拉出层次化的表示,还是很奇怪的。值得注意的是中间损失的有效性,特别是在 NLP 应用程序中,由于存在各种可以生成供您预测的特征(例如,词性、命名实体)的解析器,所以您可以获得这种类型的信息。
为什么这样做是很明显的,这与跳过连接有关。简单地说,你将你的表现锚定在除了最终图层输出之外的东西上。在剩余 FFN 的情况下,它是到较低层的输出,这没有什么不同,因为它也是一个额外的信号,你知道在某种程度上是一个先验的良好表示(就像你的输入!).
目前看来,渐变的消失和爆炸确实是一个基本的问题,尽管不是不可克服的。
高斯混合模型聚类:如何选择分量(聚类)数
原文:https://towardsdatascience.com/gaussian-mixture-model-clusterization-how-to-select-the-number-of-components-clusters-553bef45f6e4?source=collection_archive---------2-----------------------
如果你看到了这篇文章,你可能已经知道什么是高斯混合模型,所以我将避免对这种技术的一般性描述。
但是如果你不知道细节,你可以把 GMM 看作是一个 k-means,它能够形成拉伸的簇,就像你在图 2 中看到的那样。
这个帖子使用的所有代码都是这个笔记本中的。在同一个仓库中,你可以找到完全复制你所看到的绘制结果的数据。
现在:假设您处于图 1 中描述的情况,您想要辨别我们有多少个集群(或者,如果您喜欢,有多少高斯分量生成了数据),并且您没有关于“基础事实”的信息。一个真实的例子,数据没有模拟数据表现的好。
Figure 1: The vecotrs we are going to cluster. The transparency on the points reflects the density.
乍一看,人们可能会大叫“三个主星系团加上两个副星系团!”。也许这是正确的,但是这里我们想要检查一个自动的方法来找到“正确的”集群数。
值得注意的是,这个“正确”的数字无论如何都是一个模糊的数字,因为每个问题的特殊性都可能导致人们决定克服自动算法的决定。
但是让我介绍一下我们刚刚宣布的配置(五个集群)的 GMM 结果。在下图(图 2 )中,我们为我们的数据拟合了一个包含五个组件的 GMM。我们有第一个问题:同样的数据,同样的模型,但是不同的结果。
Figure 2: Clusters shapes: since the algorithm we rely on is not deterministic, we can have very different results!
这种行为的罪魁祸首是拟合过程:期望值最大化(EM)算法。这种算法只能保证我们到达一个局部最优点,但不能保证这个局部最优点也是全局最优点。因此,如果算法从不同的初始化点开始,通常会进入不同的配置。
虽然有其他方法适合 GMM,但我们想坚持使用这一种:其他方法更复杂,需要设置更多的超参数;这超过了这篇文章的目标。
那么,我们必须考虑我们的家伙的不确定性。
最简单的处理方法是多次运行拟合程序,并考虑每个配置的平均值和标准偏差。简而言之:我们考虑了每次拟合的误差。
集群性能评估
因为我们不知道我们的聚类生成器的基本事实,即我们不知道生成数据的原始分布,所以我们关于聚类过程的性能评估的选择是有限的并且相当嘈杂。
尽管如此,我们将探索三种不同的技术。
剪影分数
这个分数,正如 SKLearn 的开发者所说,考虑了两个标准:
- 样本与同一聚类中所有其他点之间的平均距离。
- 样本与下一个最近簇中所有其他点之间的平均距离。
也就是说,它检查簇的紧密程度和分离程度。分数越接近 1,聚类越好。
因为我们已经知道拟合过程是不确定的,所以我们对每个聚类数运行二十次拟合,然后我们考虑最佳五次运行的平均值和标准偏差。结果在图 3 中。
Figure 3: Silhouette scores for our dataset
事实证明,我们用五个群集得到了最好的分数。如果我们考虑两种配置的标准偏差(“误差”),我们还必须考虑四群集配置几乎同样好。所以,这个分数并没有给我们一个明确的结果。
GMM 之间的距离
这里我们形成两个数据集,每个数据集有一半随机选择的数据量。然后,我们将检查对于每个配置,在这两个集合上训练的 GMM 有多少是相似的。
既然我们在讨论分布,相似性的概念就嵌入了詹森-香农(JS)指标。两个 GMM 之间的 JS 距离越*,GMM 就越同意如何拟合数据。
所有的功劳都在(漂亮!)计算詹森-香农度规的方法转到 Dougal ,并转到它在 StackOverflow 上的帖子。
Figure 4: Distance between half data GMMs
按照这种技术,具有三个集群的配置是最保守的;这并不一定意味着它是好的配置,因为我们只是在谈论两组结果的可重复性。
该图有趣的部分是我们在通过六个集群配置后看到的距离的突然变化:平均距离及其相关误差都显示出巨大的增加。
这意味着从七个聚类开始,两个集合的 GMM 差异更大(因为距离更大),并且也更不稳定(因为误差带更大)。
我们可以说,考虑到所包含的信息量(=最大可能的聚类数)和拟合过程的稳定性(=最低可能的 GMMs 距离)的良好配置是考虑了六个聚类的配置。
贝叶斯信息准则 (BIC)
这个标准给了我们一个估计,在预测我们实际拥有的数据方面,GMM 有多好。BIC 越低,模型就越能准确预测我们拥有的数据,进而预测真实的未知分布。为了避免过度拟合,该技术对具有大量聚类的模型进行惩罚。
Figure 5: Bayesian information criterion scores as function of the number of normal components (clusters) forming the GMMs.
按照这个标准,聚类的数量越大,模型就应该越好。这意味着 BIC 标准对复杂模型的惩罚并没有使我们免于过度拟合。或者,用更通俗的话来说,这个分数糟透了。至少以这种基本形式。
但是在叫嚣和摒弃这项技术之前,我们可以注意到两件事。首先是曲线相当平滑和单调。第二,曲线的不同部分遵循不同的斜率。从这两个观察开始,检查 BIC 曲线变化斜率大的地方的诱惑就大了。所以我们来检查一下!
从技术上讲,我们必须计算 BIC 得分曲线的梯度。直观上,梯度的概念很简单:如果两个连续的点有相同的值,那么它们的梯度为零。如果它们具有不同的值,如果第二个点具有较低的值,则它们的梯度可以是负八分之一,否则是正八分之一。梯度的大*告诉我们这两个值相差多少。
Figure 6: plot of the gradients of the curve in Figure 5
正如所料,所有的梯度都有负值。但是我们更清楚地看到,从 7 个簇的大*开始,梯度变得几乎恒定,即原始函数具有更平缓的下降,即增加簇的数量没有太大的增益。简而言之,这项技术建议我们使用六个集群。
最终决定:改变模式
我们探索了三种不同的技术来选择可以在该数据集中辨别的正确的聚类数。结果如下表所示:
即使决策是相似的,也没有一个所有策略都认同的明确的价值观。在这种特定情况下,这意味着 GMM 不是对我们的数据进行聚类的好模型。
你可以捕捉到的另一个症状是,BIC 的轮廓和梯度都显示了第二个值,几乎与选择一个值一样好:4 几乎与 5 一样好的轮廓,5 几乎与 6 一样好的 BIC 分数的梯度。
有人可能会说只取五个(在 medio stat virtus 中)作为集群的正确数量,但这可能不是最佳选择。事实证明,这并不是针对我的具体问题。
这是因为星团没有显示出清晰的对称(类似椭圆形)形状,因此它们不能用一个二*高斯模型来近似,就像你在图 7 中看到的那样,而是对称的。
Figure 7: a bi-variate normal distribution.
我希望你喜欢阅读!
极客圣诞节:娱乐数据科学家的 10 本最佳书籍
原文:https://towardsdatascience.com/geek-christmas-10-best-books-to-entertain-a-data-scientist-9fd5b0918714?source=collection_archive---------5-----------------------
Joost Swarte for The New Yorker, August 2015 (detail)
哦,每年的圣诞节顿悟:为我们认为认识的人购物是很难的。为了帮助那些为他们友好的数据科学家寻找完美礼物的人,或者那些想尽情阅读的人,这里有一个不会让任何数据极客失望的书籍综述。选择是主观的:我故意错过了经典,并把重点放在不太明显的选择,保证娱乐和启发。
排名不分先后:
- 破坏数学的武器。大数据如何增加不平等并威胁民主,凯茜·奥*尔(2016)
这是一本关于企业和政府应用数学模型的精彩读物。凯茜·奥*尔讲述了影响我们日常生活的黑盒算法和固有偏见:工作、信贷和教育。现代的一本令人振奋的必读读物。 - 数据化。《我们是谁》(当我们认为没人在看的时候),克里斯蒂安·鲁德尔(2014)
“OK 丘比特”的联合创始人克里斯蒂安·鲁德尔挖掘了该网站的数据,以发现什么是爱:在数字中。这本书既吓人又有趣,它是一个关于我们的谎言、无意识偏好和网络约会中偶尔出现的种族歧视的数据包装的账户。引用 Nick Paumgarten 在《纽约客》中的话:“他不会对大数据现象(见国家安全局、谷歌广告、那个鬼祟的 Fitbit)拍手叫好,而是让他们投入到大数据中,并试图从黑暗的深处拉出奇怪的生物。” - 信号和噪音。为什么这么多的预测失败了,但有些没有,内特·西尔弗(2012)
被《时代周刊》评为 2009 年 100 位最有影响力的人之一,内特·西尔弗在正确预测 2008 年美国大选并在 2012 年击败它(通过预测 51 个州中的 50 个)后声名鹊起。信号和噪声深入应用概率的世界。挑战传统的(“频繁主义者”)统计数据,Silver 为事件预测的复杂性提供了一个案例,通过对扑克、金融危机和气候变化的研究来支持他的观察。 - 被随机性愚弄。机会在生活和市场中的隐藏角色,《纳西姆·*古拉斯·塔勒布》(2005)
在其后续畅销书,《黑天鹅》,《被随机性愚弄》的阴影下,本身就是一部**的杰作。纳西姆·*古拉斯·塔勒布会让你对我们的决策能力大失所望:我们充满偏见,倾向于在大量随机收集的事件中看到模式。驱动成功的往往是运气,而不是技能或努力,尽管我们不愿意承认。规范科学也受到抨击,有一句名言令人难忘:“规范经济学就像没有美学的宗教”。 - 统计学做错了,亚历克斯·莱因哈特(2015)
这是一个关于应用统计学的警示故事,既令人震惊又富有教育意义。统计错误是常见的,不一定是业余爱好者的领域。亚历克斯·莱因哈特(Alex Reinhart)讨论了统计分析、出版文献和同行评议论文中出现的典型错误——有些是由冷血欺骗引发的。这本书让你质疑你所知道的一切,但并不沮丧:统计做错了既是研究评估框架,也是创建有意义分析的指南。 - 《局外人:成功的故事》,《马尔科姆·格拉德威尔》(2008)
马尔科姆·格拉德威尔讲述引人入胜的故事:《局外人》是他的,通常被称为自传,关于幸运和不幸的故事。看着重大成功的故事,他拿出统计证据来检查他们所谓的和真正的促成因素。出现的画面是,与财富、社会背景甚至出生月份所能达到的目标相比,智力甚至毅力都不算什么。也许不是你典型的统计阅读,这是一个令人大开眼界的观点,以鼓励我们创造的产品的包容性和公平性。这是一个不寻常的视角,就像纳西姆·*古拉斯·塔勒布在一本书里遇到了凯茜·奥*尔。 - 给我看数字:设计表格和图表来启发,斯蒂芬·诺(2004)
对于那些热衷于用数据讲故事的人来说,这是必备的。信息可视化是一种技能,这本书是一个伟大的建议,避免可怕的想法,和一些实用主义有助于掌握这种技能的实用选择。 - 糟糕的科学,本·戈德阿克里(2008)
本·戈德 arce 的工作是一个人对伪科学的讨伐。他研究了医疗保健趋势背后的证据:营养学家、顺势疗法和替代医学等等。Goldarce 提醒我们注意误导性的术语和公关技巧,并保证研究的透明度。它的主要焦点可能是健康产业,但这种思*模式是普遍适用的:现在和 10 年前一样。毕竟,我们刚刚了解到,尽管没有科学证据证明这种做法的有效性,但英国的大多数自来水公司还是使用了中世纪的水检测方法。 - 《金钱球:赢得不公平游戏的艺术》,迈克尔·刘易斯(2004)
它也可以被称为金钱球:现实生活中的数据库管理。一个关于极客占领棒球场的迷人故事(不是字面意思)。统计学已经改变了棒球中的球探方法:整个行业开始研究数字,完全无视它遵循了几十年的传统智慧。这是一个科学胜于情感的普遍故事,任何极客都会欣赏。 - 随机性,黛博拉·j·贝内特(Deborah j . Bennett)1999
有趣的故事:我订这本书的时候,亚马逊又给我发了一本。也许他们认为我非常想要某样东西,我的愿望应该得到满足。
随机性是一本很棒的概率入门书:通过它在人类历史中的作用仔细研究机会,迂回到哲学和宗教,到它在技术中的现代应用。与同类书籍不同的是,数学问题用人类流利的语言解释。
如果你知道有一本书可以很好地补充这个列表,请发表评论或发微博。
这篇文章最初发表在我的博客上, 一个分析师在数据仙境中的冒险 。
大会毕业生招聘
原文:https://towardsdatascience.com/general-assembly-graduate-for-hire-509210e5267b?source=collection_archive---------6-----------------------
我最近从大会的数据科学项目毕业,并为我的下一次冒险感到兴奋!我在劳联-产联有五年管理、管理和可视化数据的经验。我正在寻找一个可以继续使用这些技能的地方,同时也磨练我新获得的机器学习技能。我主要在 DC 和洛杉矶地区找工作,但也愿意去旧金山、圣地亚哥和拉斯*加斯(这些都是我住过的城市)。
巨大的成果
我很高兴我不是一个人在找工作,而是有大会的结果的帮助。Outcomes 是大会的职业准备部门,我希望其他教育机构能够复制他们的模式。
对于结果支持,你需要写 10 篇博文(这是我开这个博客的原因),创建一个在线文件夹,以及其他一些要求。这是为了让学生习惯于获得曝光和网络。该计划本身是一个支持*组,有几项责任措施:每周申请 10 份工作,每月参加 2 次社交活动,以及其他目标。
My Portfolio brendanbailey.github.io
除了支持*组,Outcomes 还将您与雇主联系起来。昨天我们在学生聚光灯下展示了我们的作品集。我与优步、蓝色实验室和摩根富兰克林咨询公司进行了几次有意义的交谈。
最后,我对大会成果*组提供的支持感到非常兴奋。
建设性的批评:简历
我对大会的职业准备计划的一点建设性的批评是关于要求学生在简历中两次列出 GA,一次在经验下,一次在教育下。
对于没有技术背景的学生来说,这完全有意义。如果你想在科技行业找份工作,那么你应该尽一切努力突出你的科技技能,这些技能主要来自你在 GA 的经历。
然而,对于有技术背景的学生来说,学习一门课程来补充他们的经验或转换行业,那么这是重复的。例如,我用 Python、SQL、AWS 和大会上涉及的其他工具为美国劳工联合会-产业工会联合会管理了五年的政治和会员数据。我来 GA 的原因是通过获得机器学习技能来补充这一经验,以及探索政治以外的行业。这一组中还有其他具有 SQL 和商业智能经验的学生,他们可能也属于这一类别。
在这些学生的简历中两次列出大会是一个问题,因为它可能会挤占其他相关的有偿经验。根据以前的经验对学生进行细分,可以帮助大会更好地解决他们的相对需求。
人工智能系统中的泛化
原文:https://towardsdatascience.com/generalization-in-ai-systems-79c5b6347f2c?source=collection_archive---------9-----------------------
泛化的主要目标是使 AI 系统在测试数据上表现得更好。同样,迁移学习是指在某些任务上训练系统,以提高它在其他任务上的表现。虽然这两种方法在实践中可能看起来非常不同,但它们有一个共同的目标:迫使神经网络或其他 ML 算法在一个场景中学习有用的概念,以便在新的场景中更好地执行。
此外,它们与欠拟合和过拟合问题密切相关:
当模型没有足够的能力或者训练的时间不够长以至于不能记住重要的特征时,就会发生欠拟合。当模型尺寸太大和/或训练时间太长时,会发生过度拟合,结果它会根据训练数据调整太多。这篇论文表明,深度神经网络可以很容易地记住整个训练数据集。考虑到这一点,许多关于正则化技术的研究正在进行,其目标是处理这些问题。
从数学的观点来看,正如这个的工作所示,具有良好推广质量的目标函数的局部极*值具有低的 Hessian 范数。这意味着在这一点附近,网络输出对参数的微*变化不敏感。
有趣的是,通常的随机梯度下降往往以非常高的概率收敛到一个好的最*值。但是使用一些特殊的技术,你可以达到更好的效果。
常见的正则化方法
- 降低模型的复杂性-参数越少,模型从训练数据中记忆的就越少。
- 早期停止—通过跟踪验证集的性能,当验证错误开始增加时,您可以立即停止训练。
- 权重衰减-保持较*的权重并增加稀疏度。
- DropOut —在训练过程中停用随机神经元,并强制它们的每个子集给出有意义的结果。
- 批量标准化-重新缩放数据并将数据转换到一个公共值范围。
最初发表于 认知混乱 。
广义线性模型
原文:https://towardsdatascience.com/generalized-linear-models-8738ae0fb97d?source=collection_archive---------0-----------------------
自从我写了第一篇面向所有人的机器学习文章以来,已经有很长时间了。从现在开始,我会试着更频繁地发表文章。
快速提示:不幸的是,Medium 不支持数学类型设置(Latex 等。),所以我把数学公式作为图片放到文章中,我不知道方程在不同的设备中是否看起来很优雅。
今天的主题是广义线性模型,这是一堆用于监督学习问题的通用机器学习模型(用于回归和分类)。
让我们从线性回归模型开始。我想,每个人在大学期间都遇到过线性回归模型,以这样或那样的方式。线性回归模型的目标是找到观察到的特征和观察到的实际输出之间的线性映射,以便当我们看到新的实例时,我们可以预测输出。在本文中,我们接受有 N 个输出为 y 的观察值和 M 个特征 x 用于训练。
N observations with 1 output and M features for each.
我们定义一个 M *向量 w 来表示将输入映射到输出的权重。我们也定义 N 乘 M *矩阵 X 来表示所有的输入。 y 被定义为 N *输出向量。
We try to approximate output vector with Xw
我们的目标是找到最佳的 w ,最*化实际输出向量 y 和近似值 X w 之间的欧几里德距离。为此,我们一般使用最*二乘误差和矩阵演算来使其最*化。这里我们用 L 来表示损失(误差)函数。
Optimum w for linear regression problem
这是问题的线性代数近似,但为了更好地理解问题,并将其扩展到不同的问题设置,我们将以更概率的方式处理它。
在开始,我们说输出是真实的。实际上,我们假设输出是从正态分布中采样的。让我们明确地定义它,将分布均值设置为 Xw,方差设置为 I(单位方差)。
现在,我们的目标是找到最大化概率为 p( y |X, w )的 w 。上面我们定义 p( y |X, w )为正态分布,所以我们知道它的展开形式是正态分布的 pdf。
likelihood of y
很难直接使用似然函数,相反,我们将使用对数似然函数,它具有与似然函数相同的最大值和最*值。我们可以最大化对数似然或最*化负对数似然。我们选择第二个,称之为损失函数。
Loss function(-loglikelihood)
该损失函数与最*二乘误差函数完全相同。因此,我们从统计学角度解释了线性回归,这将对即将推出的模型非常有帮助。
地图解决方案
上面的解决方案被称为最大似然法,因为这正是我们所做的,最大化似然。我们可以将先验概率放在权重上,并最大化 w 的后验分布,而不是y 的可能性。
MAP solution
在上述方程中,我们定义了零均值、单位方差先验权重 w ,并利用负对数后验分布导出了损失函数。 w 的先验分布试图将权重值保持在其平均值附近,在这种情况下平均值为 0。这一过程被称为 L2 正则化(岭回归),它惩罚边际 w 值,因为它可以在损失函数中看到。
先验分布反映了我们对 w 值的信念,它不一定是正态分布。如果我们把拉普拉斯分布作为先验,正则项将是 w 的 1-范数(L1 正则化-Lasso)。
为了更好的说明正则化效果,我举个例子。假设我们有一个数据点,其特征为[2,1],输出为 3。对于这个问题,有无限多种方法来设置权重,但其中,L2 正则化将首选[1,1],L1 正则化将首选[1.5,0],因为[1,1]的 2-范数和[1.5,0]的 1-范数是所有可能的解决方案中最*的一个。因此,我们看到 L2 正则化试图使所有权重值尽可能接近 0。另一方面,L1 正则化偏好稀疏解。
泊松回归
我们对实值输出使用线性回归。更具体地说,如果输出值是计数,那么我们可以改变似然分布,并对这个新问题使用相同的设置。泊松分布是模拟计数数据的合适分布,我们将利用它。
泊松分布的超参数不能取负值。所以我们稍微改变一下生成模型的定义,使用线性模型不像正态分布那样直接生成超参数,而是生成它的对数(实际上是自然对数 ln)。对数是广义线性模型中泊松分布的连接函数,我们再次使用负对数似然来寻找最大似然解。
Loss function for Poisson Regression
我们取损失函数相对于 w 的导数,并使其等于 0。就我所见,它没有封闭形式的解,与线性回归相反。但是我们可以使用无约束最优化方法来寻找迭代解,下面我提供了梯度下降法。在梯度下降法中,我们通过损失梯度的负方向(因为这是损失相对于 w 减少的方向)逐渐更新权重并采取*步骤。
Iterative updates for weight
逻辑回归
上面我介绍了回归问题的模型,但是广义线性模型也可以用于分类问题。在二类分类问题中,似然性由伯努利分布定义,即输出为 1 或 0。
这次我们使用 sigmoid 函数将线性模型的输出映射到(0,1)的范围,因为伯努利平均值应该在这个范围内。
Sigmoid function
Cross-Entropy Loss Function
上面定义的损失函数被称为交叉熵损失函数,并广泛用于分类问题,我们从统计角度说明了使用它的原因。该解不存在封闭形式,我们将使用随机梯度下降法,它逐个处理实例并提供在线迭代更新机制。
Stochastic Gradient Descent for Logistic Regression
多项式逻辑回归
如果类别数大于 2,伯努利分布不足以描述数据。在这种情况下,我们更喜欢多项式分布。对于 K 类分类问题,我们用一热编码表示输出。在独热编码中,每个输出都用 K *向量表示,除了取值为 1 并显示实例类的索引之外,所有向量都是 0。
One-hot encoding
这一次,我们定义了 y 可以属于的 K 个不同的概率。每个类都有自己的概率和权重。因此,与上述模型不同,我们定义了 K 个不同的权重向量。
An output is sampled from Multinomial Distribution
每个类别的概率需要大于 0,因此我们可以像在泊松回归中一样采用线性映射的指数。但是这次有 K 个不同的概率,它们的和应该等于 1。因此,它需要被规范化,为此我们使用 softmax 函数。
再次,我们使用负对数似然来定义损失函数,它被称为交叉熵损失函数。类似于泊松回归和逻辑回归,梯度下降优化器可以用来解决这个问题。
Cross-Entropy Loss Function for Multinomial Logistic Regression
在这篇文章中,我试图尽可能清楚。我们推导的方程很重要,因为它们构成了更复杂的机器学习模型的基础,比如神经网络。我希望你喜欢它。
用人工神经网络生成数字和声音
原文:https://towardsdatascience.com/generating-digits-and-sounds-with-artificial-neural-nets-ca1270d8445f?source=collection_archive---------1-----------------------
为乐趣而实验…
在 Cisco Emerge,我们喜欢尝试新旧工具和想法。最近,我们开始修补生成模型。
在 GitHub 上查看这些实验的源代码
什么是生成模型?
生成模型是人工神经网络,能够创建人类从未见过的“假”数据,目标是使其与真实数据无法区分。
这里有一个例子,说明了一组特定的生成模型——称为生成对抗网络——在观察了成千上万张人脸图像后能够创造出什么:
Source: https://arxiv.org/pdf/1711.09020.pdf
这就好像神经网络学会了创造一个他们观察到的世界的替代现实。
我们探索了变型自动编码器
一组特殊的生成模型被称为变分自动编码器。
除了花哨的名字,这个概念非常简单,下图可以帮助解释我们可以用它们实现什么。
Variational Autoencoder
- 编码器:神经网络的第一部分(称为编码器)读取输入——在这个例子中是一个数字——并试图将信息压缩成一个比原始输入更*的向量。
- 潜在向量(Latent Vector):这个向量被“强制”匹配一个特定的概率分布——通常是高斯分布(Gaussian Distribution),但是实际上你可以选择任何东西。
不赘述,之所以会这样,是因为我们希望能够从这个分布中采样一个向量,然后将其馈送到神经网络的第二部分,以生成新数据。 - 解码器:网络的第二部分,用来产生新数据,称为解码器。
在训练期间,编码器试图以“损失最*”的方式压缩输入,而解码器试图在只给定潜在向量作为输入的情况下尽可能地匹配原始输入。
损坏的数据
如果我们在编码器中输入损坏的输入,并要求解码器重建未损坏的输入,会发生什么情况?
Denoising Variational Autoencoder
神奇的事情发生了:解码器的输出是一个完整的图像,整个数字被精确地绘制出来。
数字明显比原始数字更平滑,也更模糊,因为关于“缺陷”的信息没有通过网络传输。只有使数字成为数字的信息会保留下来。
这一切都意味着:
- 编码器能够学习构建一个数字的表示,即使是在数字本身的一部分丢失(在上面的例子中是 20%)的情况下。
- 解码器能够学习如何从编码器学习的表示中重建完整的图像。
让我们试试声音
人工神经网络非常通用:可以执行对象识别、语音生成、自然语言处理等
出于这个原因,我们保持了相同的神经网络结构,并尝试了相同的声音实验。
嘈杂的 c 大调音阶
我们没有使用 10 个不同的数字图像,而是使用了 7 个音符——c 大调音阶。更准确地说,它们是正弦曲线(因此它们听起来或多或少像笛子)加上了白噪声(因此它们听起来像笛子,演奏者使用了大量空气)。
Click to listen to the sound
Sound1: Non corrupted noisy sinusoid
与我们之前的实验类似,我们向编码器输入斩波输入。
Sound2: This is the input of sounds we fed into the Encoder with, while the image “Sound1” is the reference that the Decoder tries to reconstruct
培养
- 0 次迭代 最初自动编码器只能产生随机噪声:
0 iterations — Line1: Spectogram of Reconstructed audio. Line 2: Waveform of Reconstructed Audio. Line 3: Spectogram of Chopped Audio fed into the Autoencoder. Line 4: Waveform of Chopped Audio
- 100 次迭代
100 iterations — Line1: Spectogram of Reconstructed audio. Line 2: Waveform of Reconstructed Audio. Line 3: Spectogram of Chopped Audio fed into the Autoencoder. Line 4: Waveform of Chopped Audio
- 200 次迭代
200 iterations — Line1: Spectogram of Reconstructed audio. Line 2: Waveform of Reconstructed Audio. Line 3: Spectogram of Chopped Audio fed into the Autoencoder. Line 4: Waveform of Chopped Audio
- 400 次迭代
这似乎类似于数字图像实验中发生的情况,输出是平滑和模糊的。
声谱图还显示,除主频率外,所有其他频率的能量都较弱。
400 iterations — Line1: Spectogram of Reconstructed audio. Line 2: Waveform of Reconstructed Audio. Line 3: Spectogram of Chopped Audio fed into the Autoencoder. Line 4: Waveform of Chopped Audio
- 800 次迭代: 自动编码器学习重建完整信号,并忽略原始输入中添加的白噪声。
800 iterations — Line1: Spectogram of Reconstructed audio. Line 2: Waveform of Reconstructed Audio. Line 3: Spectogram of Chopped Audio fed into the Autoencoder. Line 4: Waveform of Chopped Audio
听起来是这样的
这是被破坏的输入的声音。请记住,神经网络是用一个只有一部分丢失的短输入来训练的,而完整的声音是一个有许多随机丢失部分的较长输入。
重建的输入听起来像这样:
用更复杂的输入自己尝试一下
你可以在这个 GitHub repo 中找到我们用来运行这些实验并产生这些结果的所有源代码,这样你就可以尝试为数字、声音以及可能更复杂的输入复制它们。随意留下评论,叉回购。
您不需要任何特定的数据集或硬件,只需要安装一台计算机和 TensorFlow(MNIST 数据集附带 tensor flow)。
如果你得到了什么有趣的结果,请在评论中分享。
谷歌洋红色
你可能想看看谷歌的这个项目:用 NSynth 生成你自己的声音。
与我们刚刚展示的实验类似,他们建立了能够学习并直接生成原始音频样本的神经网络。
结论
正如上面提到的 Google Magenta 的项目,已经有人在努力用人工神经网络生成音频,他们取得的结果令人印象深刻。
我们试图让这个实验尽可能简单,这样任何人都可以在不需要庞大数据集和配备 GPU 的昂贵机器的情况下进行尝试,并深入了解可变自动编码器如何对图像和原始声音进行处理。
使用语言模型和 LSTMs 生成德雷克说唱歌词
原文:https://towardsdatascience.com/generating-drake-rap-lyrics-using-language-models-and-lstms-8725d71b1b12?source=collection_archive---------4-----------------------
深入了解你的 MC-LSTM,即将在 iTunes 上发布
所有未来人工智能应用的一个主要部分是建立能够从一些数据集学习的网络,然后生成原创内容。这个想法已经被应用到自然语言处理(NLP)中,这就是人工智能社区如何开发出所谓的语言模型
语言模型的前提是了解句子是如何在文本中构建的,并使用这些知识来生成新的内容
就我而言,我想尝试将说唱一代作为一个有趣的附带项目,看看我是否能重现加拿大流行说唱歌手德雷克(又名# 6 上帝)的歌词
我还想分享一个通用的机器学习项目管道,因为我发现,如果你不知道从哪里开始,建立自己的东西往往是非常困难的。
1.获取数据
这一切都是从寻找德雷克所有歌曲的数据集开始的,我不想浪费太多时间,所以我自己构建了一个快速脚本,抓取一个叫做metrolyrics.com的流行网站的网页
我用一个众所周知的 Python 包 BeautifulSoup 来抓取页面,这是我从这个由 Justin Yek 写的的很棒的教程中用了大约 5 分钟学会的。注意,我实际上预先定义了我想从 metrolyrics 中获取的歌曲,这就是为什么你可能会注意到我在上面的代码中迭代了我的songs
dataframe。
DataFrame storing all of the songs lyrics
运行剪贴簿后,我有我所有的歌词在适当的格式。csv 文件,并准备开始预处理数据和构建模型。
关于模型
现在,我们将讨论文本生成的模型,这才是你真正要做的,这是真正的酱油-生酱油。我将从讨论模型设计和一些使歌词生成成为可能的重要元素开始,然后,我们将开始讨论它的实现。
建立语言模型有两种主要方法:(1)字符级模型和(2)单词级模型。
每种模型的主要区别在于输入和输出是什么,我将在这里详细讨论每种模型的工作原理。
字符级模型
在字符级模型的情况下,你的输入是一系列字符seed
,你的模型负责预测下一个字符new_char
。然后你一起使用seed + new_char
来生成下一个字符,以此类推。请注意,由于您的网络输入必须总是相同的形状,我们实际上会在此过程的每次迭代中从种子中丢失一个字符。这是一个简单的可视化:
Fig. 2 Iterative process of word generation with Character-level Language Model
在每一次迭代中,该模型基本上是在给定种子字符的情况下预测下一个最可能的字符是什么,或者使用条件概率,这可以描述为寻找最大值P(new_char|seed)
,其中new_char
是字母表中的任何字符。在我们的例子中,字母表是一组全英文字母和一个空格字符。(注意,您的字母表可以非常不同,可以包含您想要的任何字符,这取决于您正在为其构建模型的语言)
单词级模型
单词级模型与字符级模型几乎相同,但它生成下一个单词而不是下一个字符。这里有一个简单的例子:
Fig. 3 Iterative process of word generation with Word-level Language Model
现在,在这个模型中,我们以一个单位向前看,但这次我们的单位是一个词,而不是一个字符。因此,我们在寻找P(new_word|seed)
,其中new_word
是我们词汇表中的任何单词。
请注意,现在我们正在搜索比以前大得多的集合。使用 alphabet,我们搜索了大约 30 个项目,现在我们在每次迭代中搜索更多的项目,因此单词级算法在每次迭代中更慢,但由于我们生成的是整个单词而不是单个字符,所以实际上一点也不差。作为我们的单词级模型的最后一点,我们可以拥有非常多样化的词汇,我们通常通过从我们的数据集中找到所有独特的单词来发展它(通常在数据预处理阶段完成)。因为词汇表可以变得无限大,所以有许多技术可以提高算法的效率,比如单词嵌入,但那是以后的文章了。
出于本文的目的,我将把重点放在字符级模型上,因为它的实现更简单,并且对字符级模型的理解可以很容易地转移到更复杂的单词级模型上。当我写这篇文章的时候,我也建立了一个单词级的模型,当我写完之后,我会附上一个链接(或者你可以关注我来保持更新😉)
2。数据预处理
对于角色级别的模型,我们将不得不以下列方式预处理数据:
- 标记化数据集 —当我们将输入输入到模型中时,我们不想只输入字符串,而是希望使用字符,因为这是一个字符级的模型。所以我们要把所有的歌词拆分成字符列表。
- 定义字母表—现在,我们知道了歌词中可能出现的每一种字符(来自之前的标记化步骤),我们希望找到所有独特的字符。为了简单起见,事实上整个数据集并不是很大(我只使用了 140 首歌曲),我将坚持使用英文字母和几个特殊字符(如空格),并将忽略所有数字和其他东西(因为数据集很*,我宁愿让我的模型预测更少的字符)。
- 创建训练序列 —我们将使用滑动窗口的概念,通过在句子上滑动固定大*的窗口来创建一组训练示例。这里有一个形象化的好方法:
Fig. 4 Sliding window on the dataset with input/output generation
通过一次移动一个字符,我们生成长度为 20 个字符的输入和一个输出字符。此外,由于我们一次移动一个字符,我们实际上大大扩展了数据集的大*。
4.标签编码训练序列—最后,由于我们不希望模型处理原始字符(尽管理论上这是可能的,因为字符在技术上只是一个数字,所以你几乎可以说 ASCII 为我们编码了所有的字符)。我们将一个唯一的整数与字母表中的每个字符相关联,你可能听说过标签编码。这也是我们创建两个非常重要的映射character-to-index
和index-to-character
的时候。有了这两个映射,我们总是可以将任何字符编码成它的惟一整数,并且还可以将模型的输出从索引解码回它的原始字符。
5.One-Hot-encoding dataset—因为我们正在处理分类数据,其中所有字符都属于某种类别,所以我们必须对输入列进行编码。这里有一个伟大的描述由 Rakshith Vasudev 写的单热编码实际上做了什么。
一旦我们完成了这五个步骤,我们就差不多完成了,现在我们要做的就是建立模型并训练它。如果您想更深入地了解细节,这里是前五个步骤的代码。
3.构建模型
为了用一组先前的字符来预测下一个字符,我们将使用递归神经网络(RNN),或者特别是长短期记忆网络(LSTM)。如果你对这两个概念都不熟悉,我建议你仔细阅读一下。 RNNs 作者 Pranoy Radhakrishnan 和 LSMTs 作者 Eugine Kang 。如果你只是需要一个复习或感觉勇敢,这里有一个快速纲要:
RNN 进修
通常,您会看到网络看起来像一张网,从许多节点汇聚到一个输出。大概是这样的:
Fig. 5 Image of a Neural Network. credit
这里我们有一个单一的输入点和一个单一的输出点。这对于不连续的输入非常有用,因为输入的顺序不会影响输出。但在我们的例子中,字符的顺序实际上非常重要,因为字符的特定顺序是创建独特单词的原因。
RNNs 通过创建一个网络来解决这个问题,该网络接收连续的输入,并且还使用来自前一个节点的激活作为下一个节点的参数。
Fig. 6 Overview of a simple RNN
还记得我们的一个序列Tryna_keep_it_simple
的例子,我们提取出在它之后的下一个字符应该是_
。这正是我们希望我们的网络所做的。我们将输入字符序列,其中每个字符进入T — > s<1>, r -> x<2>, n -> x<3>... e-> x<n>
,网络预测输出y -> _
,这是一个空格,是我们的下一个字符。
LSTM 进修
简单的 rnn 有一个问题,它们不太擅长将信息从非常早期的细胞传递到后来的细胞。例如,如果你正在看一个句子Tryna keep it simple is a struggle for me
,如果你不能回头看看之前出现的其他单词,那么预测最后一个单词me
(可以是字面上的任何人或任何东西,如:巴卡、猫、土豆)是非常困难的。
lstm 通过给每个单元增加一点内存来解决这个问题,每个单元存储一些关于之前发生的事情的信息(之前出现了什么单词),这就是为什么 lstm 看起来像这样:
Fig. 7 LSTM visualization, taken from Andrew Ng’s Deep Learning specialization
除了传递a<n>
激活之外,您还传递了c<n>
,它包含了之前节点中发生的事情的信息。这就是为什么 LSTMs 更好地保留了上下文,并且通常可以为语言建模等目的做出更好的预测。
实际上在建造它
我以前学过一点 Keras,所以我用它作为框架来建立网络,但在现实中,这可以手工完成,唯一的区别是它会花很多时间。
如您所见,我们使用了 LSTM 模型,也使用了批处理,这意味着我们对数据子集进行训练,而不是一次训练所有数据,以略微加快训练过程。
4.生成歌词
在我们的网络被训练之后,这里是我们将如何寻找下一个字符。我们将获得一些随机种子,它将是用户输入的一个简单的字符串。然后,我们将使用种子作为网络的输入来预测下一个字符,我们将重复这个过程,直到我们生成一串新的行;类似于上面显示的图 2。
下面是一些生成的歌词的例子
注意:歌词未经审查,请自行查看
您可能已经注意到,单词有时没有意义,这是字符级模型的一个常见问题,因为输入数据经常在单词中间被分割,这使得网络学习并生成奇怪的新单词,而这些单词对它来说却有意义。
这是用单词级模型解决的问题,但是对于不到 200 行的代码,字符级模型仍然令人印象深刻。
其他应用
这个字符级网络中描述的想法可以扩展到许多其他应用程序,这些应用程序远比歌词生成有用。
例如,iPhone 键盘上的下一个单词推荐也是如此。
Keyboard next word prediction
想象一下,如果您构建一个足够精确的 Python 语言模型,您不仅可以自动完成关键字或变量名,还可以自动完成大块代码,从而为程序员节省大量时间。
你可能已经注意到这里的代码并不完整,并且缺少一些部分,这里是我的 Github repo 的链接,在这里你可以更深入地了解自己构建一个类似项目的细节。
感谢来自 github 的 Keras 示例
总之,我希望你喜欢阅读这个故事,请考虑跟随或鼓掌👏如果你做了。如果你对更多类似的内容感兴趣,你可以在这里关注我,或者在其他任何社交媒体上关注@nikolaevra。
下次我会抓住你的!
用深度学习生成俳句(第一部分)
原文:https://towardsdatascience.com/generating-haiku-with-deep-learning-dbf5d18b4246?source=collection_archive---------5-----------------------
使用神经网络生成 5–7–5 音节结构的俳句。
https://imgur.com/r/all/4aYN3 (Original source unknown)
有很多关于使用深度学习生成文本的工作——计算机生成模仿人类书写文本的新文本。甚至简单的模型也能产生令人信服的文本,正如安德烈·卡帕西因而出名。但是他们努力的一个地方是当文本必须满足严格的结构约束时。我们如何改进当前的文本生成模型,使其更好地完成这项任务?
俳句生成是严格约束任务的一个例子。它们是由三行诗组成的非常短的诗。传统上第一行是 5 个音节,第二行是 7 个音节,第三行是 5 个音节。例如,由布莱恩·德尔·韦基奥:
俳句的发明者
的中指一定有七根手指
现代俳句保留了一首简短的三行诗的精髓,但并不严格遵循 5-7-5 音节的结构。因此,大多数用于获取训练数据的在线俳句都不具备这种结构,而且许多先前关于生成俳句的研究也没有强制音节数。
这让我想到了我的问题:我们能创作出既有意义又结构正确的俳句吗?
https://www.savagechickens.com/2010/02/easy-haiku.html
先前的工作
我以前做过俳句生成方面的工作。这个生成器使用在非俳句诗歌语料库上训练的马尔可夫链,一次生成一个词,当所有可能的下一个词都违反 5–7–5 结构时,通过退格确保 5-7-5 结构。这和我写俳句时做的没什么不同。我尝试一些东西,数出音节,发现它们不起作用,然后返回。但这并不令人满意。这感觉更像是蛮力,而不是真正理解写俳句意味着什么的东西。我还使用了同样的方法,使用了一个非诗歌训练语料库。
我不是唯一一个尝试过的人。萨姆·巴拉斯和 T2【塔内尔·基尔斯&马库斯·康塞普都使用了标准的字符级递归神经网络(RNN)来生成俳句。他们产生的输出看起来像俳句,但不是很有凝聚力,当然也不符合我们所寻找的结构。部分问题是,正如我上面所说的,大多数现代俳句不遵循这种结构,这意味着训练语料库不会反映它。另一个问题是,字符与音节的相关性很差,因此,即使有一个好的语料库,只给字符的模型也不太可能选择 5–7–5 形式。
杰克·霍普金斯和多*基拉提出了几种生成诗歌的模式。他们把重点放在十四行诗上,十四行诗不仅对每行的音节数有限制,而且必须遵循特定的押韵方案。一个模型是音素级别的,这允许他们在训练时限制结构。另一个是字符级模型,可以产生更连贯的文本,但对形式没有任何限制。他们在采样时通过使用鉴别器来限制文本,该鉴别器将拒绝不符合期望度量的文本,类似于我的马尔可夫模型技术。
数据
我使用了四个来源来构建我的训练语料库:
- http://www.tempslibres.org/tl/en/dbhk00.html
- 来自《叙事描述之外的三行诗:多元对抗训练下的意象生成诗》语料库。
- 山姆·巴拉斯的诗集。
- 赫瓦尔·弗莱雷的海枯藻文集。
这个 Jupyter 笔记本有我的资料准备流程。它清理数据并使用CMU 发音词典 (CMUdict)计算每行的音节数。CMUdict 将单词映射到它们的音素,这又可以用于计算每个单词的音节数。如果一个单词有多个有效发音,则保留每个发音。
最终的语料库包含了 25886 首诗,其中只有 725 首(3%!)匹配 5–7–5 结构,这远远不足以训练模型。
问题是
这让我们陷入了困境。我们的目标是生成符合传统的 5–7–5 结构的俳句,但我们在这方面的训练数据很少。我们有什么选择?
1.获取更多数据。如果有人自愿为我写几千首俳句,我很乐意接受这个提议。
2.使用类似于霍普金斯和基拉所做的方法,我们在整个语料库上不受限制地训练一个字符级网络来“学习英语”——学习如何构成单词、句子结构等。,然后在采样时使用一个可以将诗歌分类为俳句或不分类的鉴别器来约束形式。这种方法的一个问题是,它可能很难产生有凝聚力的、完整的俳句。从本质上讲,生成器是贪婪的,它将一直生成文本,直到鉴别器告诉它停止,此时不确定生成器是否完成了“完整的思想”。给定任何严格约束的格式,在采样时实施格式的同时,很难保持内容的内聚性。为了证明我所说的不完整的想法是什么意思,这里有一个例子,是我以前的作品使用类似的样本时间限制生成的一首诗:
哦,福楼沙,看看
它来得多快,滋养着
食物,直到最后死亡
击杀什么?
3.在整个语料库上训练,但是在训练时告诉网络和在采样时告诉网络该行有多少音节。即使我们在一条有 3 或 10 个音节的线上训练,我的希望是当我们在采样时间要求 5 或 7 个音节时,模型可以概括。这是我采用的技术。
模型
High level diagram of the model. Three dense layers are used to embed the number of syllables for each line into the LSTM’s state. Then text is fed through the LSTM one character at a time and a dense network
该模型本质上是一个扭曲的字符到字符的文本生成网络。每行的音节数被提供给网络,通过一个密集层,然后添加到 LSTM 的内部状态。这意味着通过改变提供的三个数字,我们可以改变网络的行为。我的希望是,这仍然允许网络从整个语料库中学习“英语”,即使大多数样本不是 5-7-5 句俳句,同时仍然允许我们以后生成那个长度的俳句。这个 python 文件实现了模型和生成器。
这个 Jupyter 笔记本展示了训练过程。简而言之,我在角色层面对数据进行一次热编码,将数据分成训练集和验证集,然后使用教师强制进行训练。我在 Paperspace P6000 虚拟机器上对该模型进行了大约 2 个*时的训练,尽管在 4 个周期之后,它很快就停止了改进。这是一张培训和验证损失随时间变化的图表:
The training loss (blue line) and validation loss (red line) after each epoch of training. After two epochs the validation loss is almost as good as it will get, and it gets worse after epoch 4. Meanwhile the training loss keeps improving, meaning the model is over-fitting the training data.
结果
最后,我们到了有趣的部分——看看这会产生什么样的废话。
为了生成每首俳句,我首先为三行中的每一行指定我想要的音节数(即 5,7,5)。然后,我为第一个单词随机选择一个字符,并将其输入模型,该模型输出每个字符成为下一个字符的概率。我从这些字符中选择一个,与它们的概率成比例,并根据“温度”进行缩放,温度影响我们选择低概率字符的可能性。温度越高,随机性越大。一旦我选择了下一个字符,我就将它反馈到模型中,并重复直到行尾。在行间,我输入下一行的音节数来更新 LSTM 的状态。该函数包含生成代码。
当验证损失停止下降时,我在训练时期 4 后使用检查点生成了以下所有内容。
以下是一些采样温度为 0.1(不太随机)时产生的 5–7–5 个俳句:
就在我走在沙滩上的时候
太阳像一顶皇冠
春天来了正当我越来越深的时候,我想看看春风的底部
清晨的太阳
从被搬运的花园命运
日落时的星星
虽然音节数并不完美,但很酷的是我们可以看到我们提供的音节数影响了生成的文本。例如,输入 3–5–3 会产生:
春天的阳光
来自星星的水的味道深冬
来自星星的乌鸦
的气味海滩上学
水的味道
天空中
而 10–10–10 会产生更长的线:
上帝一定偷听到了春天的友好气息随着我的每一次心跳,我将爱你
你能看见太阳的离去吗?我想看看太阳在春天的消逝,在落日的余晖中
就像街灯说的那样,阳光灿烂,灵魂和春天在吹拂,我将爱你,伴随着我每一次心跳
如你所见,它可能相当重复和公式化。我们可以调高采样温度,让模型更有“创造性”取样温度
5–7–5 首俳句,温度 0.3:
春天晚上的早餐
我和一只蝴蝶看见了
她面朝大海一月的黎明
老路树上蛾子清扫的声音月亮上滑稽的下午
和春风的轨迹
到了 0.5 岁,它开始在拼写上有问题:
远离公路
千里之外的村庄
夏想的大海每一个睡觉的妻子都从他的手里掉下来
和同一个枕头棉下
的个人时间
在电脑灯下
到了 1.0 版本,这几乎是无稽之谈:
佐德过去最后一个巴斯特?我从未向往过冬天的山
这个 Jupyter 笔记本有更多生成的俳句。
未来的工作
这是一个好的开始。对于当前的所有缺点,我们证明了通过将音节的数量作为模型的输入,我们可以影响生成的行的长度。
要改善这一点,还有很多工作要做。我想谈几个问题:
- 更加一致地坚持 5-7-5 音节形式,而不仅仅是在正确的邻近地区。
- 创作更连贯、更有意义的俳句
从哪里开始的一些想法:
- 更多更好的数据。我想得到更多的 5-7-5 个俳句的例子,或者一种在任何文本上训练然后从中产生俳句的方法。
- 尝试其他神经网络架构,比如一个更简单的模型,我预先输入音节数,然后生成整个俳句,而不是一次一行。
- 尝试一个音素级别的模型,类似于霍普金斯和基拉在他们的工作中使用的模型。这将使学习音节变得更容易,因为只有特定的音素才有音节的重量。但是它引入了将音素映射回单词的复杂性。
- 使用生成性对抗网络(GAN ),在该网络中,鉴别者可以评估俳句的内容和/或形式。
感谢 Abigail Pope-Brooks 的编辑和反馈。
所有用到的代码和数据都可以在 github 上获得。杰里米·内曼在他的网站上做着同样毫无意义的事情:http://jeremyneiman.com/
使用深度学习生成印度*西亚歌词-第一部分
原文:https://towardsdatascience.com/generating-indonesian-lyric-using-deep-learning-first-part-2c7634237475?source=collection_archive---------12-----------------------
循序渐进。从刮擦到从零开始生成“?lalala”。(英文)
“shallow focus photography of audio mixer” by Hannah Troupe on Unsplash
H ello 各位,我对现在真正炒作的人工智能 (AI)真的很感兴趣。我也对用它来制作东西很感兴趣。目前,创建几个人工智能应用程序是我的爱好之一。在我的空闲时间,有时,我会制作一个人工智能应用程序来释放我的无聊。
source: pexels.com
我想习惯写作。为了练习,我需要开始写作。由于我有制作人工智能的爱好,我想分享我制作人工智能的知识和经验来练习我的写作技巧。“印度*西亚歌词生成器”是我在空闲时间制作的一个人工智能应用程序。
我会让这篇文章对新手友好。希望这篇文章对你有用:d。
本文的目标读者是对人工智能感兴趣的人,尤其是对机器学习和深度学习感兴趣的人。我也会让这篇文章没有数学。如果你想知道它是如何工作的,我会在源代码部分附上一些文章。
这是我们的介绍歌词。
saat senyum manismu kalbuku
杨振宁说
terakhir kali ku hilang dariku
yang kau ajak kau disana
如果你想看这篇文章的实现和代码,你可以在这个 GitHub 链接中看到笔记本
介绍
新音乐总是会出现取代旧音乐。人们应该在创作新歌时有创造性。他们需要时间创作一首新歌。他们在制作歌曲时应该考虑的一个因素是歌词。对于那些很难找到一个合适的词来创作歌词的人(比如我),这将是一个问题。他们会花很多时间来做歌词。你想过帮助他们解决问题吗?
Source : pixabay.com
在这篇文章中,我想创建一个应用程序,可以让他们轻松地创作歌词。我会做一个基于人工智能的应用程序。人工智能知识是我的兴趣之一,我希望能帮助他们。
目前,人工智能是最热门的时髦词汇之一,人们在每个角落谈论它。它可以轻松解决一些对人类来说相当困难的问题。人工智能的一个分支是机器学习。机器学习是人工智能领域的一个分支,它可以根据给定的数据预测输出。它会从数据中学习。当我们想写一首歌词时,我认为我们应该偷看一些老歌,以了解他们是如何写歌词的。我们需要搜索他们如何连接每个单词的“模式”。这类似于从给定数据中学习的机器学习。
在本文中,我们将基于我丢弃的歌词数据集生成一个新的歌词。我们将使用深度学习,一种机器学习技术。我们将使用递归神经网络(RNN)来制作发电机的模型。
即使我选择的歌词是印度*西亚语,不要担心。我将用英语写这篇文章。如果你想知道歌词的意思,用谷歌翻译或其他熟悉的工具翻译。
如果你对深度学习的术语还不熟悉,不要担心。我将告诉你每个人的简要描述。我会告诉你如何从开始(刮)管道。正如我在开始时所说的,我会尽可能让它对新手友好。
概述
我将按以下顺序写这篇文章:
- 工具
- 步骤
- 收集数据
- 预处理数据
- 建立模型
- 生成歌词
- 结论
- 编后记
- 来源
工具
将使用的库、工具和语言编程包括:
- Python 3.6
- Python 库 numpy,python 中的数学工具
- Python 库 pandas,python 中的数据表格工具
- Python 库— Keras ,深度学习框架。必须有 Tensorflow、CNTK 或 Theano 库
- Python 库— Scrapy ,Python 中流行的 scrapper 工具
- Jupyter 笔记本,(可选)牛逼的 Python IDE,也可以用来做演示或者教育代码。
我使用图形处理器英伟达 GTX 1050 来训练我的模型。
步骤或管道
Image 1 : Step or Pipeline
这是我们制作发电机的步骤。
首先,通过使用 scrapy 抓取一些包含印度*西亚歌词的网站来收集数据。然后使用 regex 清理仍然包含 HTML 标签的文本歌词。之后,处理歌词中的文本,以便它可以用于模型的输入。我们将需要构建深度学习架构。最后训练模型生成歌词。我会告诉你我是如何做到每一步的。
收集数据(网络搜集)
我从一个印*歌词收集网站(lirik.kapanlagi.com)搜集了所有的歌词。网络抓取是从网站中提取数据。所有的工作都是由一个应用程序,我们将创建。我们将使用 scrapy 库来抓取一个网站。我们要提取的信息是宋的歌词和歌名。
在本文中,我们将使用 lirik.kapanlagi.com 作为我们的目标。
首先,在终端或命令提示符下使用以下命令创建 scrapy 项目:
scrapy startproject lyric_scrapper
它将创建一个新的目录。切换到新目录并执行以下命令
scrapy genspider lyric_scrapper lirik.kapanlagi.com
它将在 tutorial/spiders 文件夹中创建一个lyricscrapper.py
。我们称之为网络爬虫,因为它通过“爬行”进入目标网站。这是我们的代码:
# -*- coding: utf-8 -*-
import scrapy
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractorclass LyricScrapperSpider(CrawlSpider):
name = 'lyric_scrapper'
allowed_domains = ['lirik.kapanlagi.com']
start_urls = ['[https://lirik.kapanlagi.com/lagu/a_id'](https://lirik.kapanlagi.com/lagu/a_id')]
rules = (Rule(LinkExtractor(allow=(), restrict_css=(".pagination2 ul li a",".col-lirik .div-horizontal2-list a", "div .letterLinksAnchor")), callback="parse_page", follow=True),)
def parse_page(self, response):
song = response.css('.col-lirik').extract_first()
title= response.css('.head-lirik h5::text').extract_first()
if len(title) > 0 and len(song) > 0:scraped_info = {
'song' : song,
'title' : title,
}yield scraped_info
让我们看看这一部分:
start_urls = ['[https://lirik.kapanlagi.com/lagu/a_id'](https://lirik.kapanlagi.com/lagu/a_id')]
rules = (Rule(LinkExtractor(allow=(), restrict_css=(".pagination2 ul li a",".col-lirik .div-horizontal2-list a", "div .letterLinksAnchor")), callback="parse_page", follow=True),)
我们将从start_urls
中的 URL 开始。为了确定起始 URL,我们应该找到包含歌词索引列表的页面。我发现是 https://lirik.kapanlagi.com/lagu/a_id的索引列表。
爬行器将通过在当前网页中查找 URL 来找到下一个要抓取的目标。为了让爬虫跟踪我们想要的页面,我们必须指定爬虫必须看到网页的哪个部分。在这种情况下,我们需要瞄准图 2 所示的这部分:
Image 2 : We will target these parts (blue marker)
我们需要通过检查 HTML 代码来得到我们想要的部分。对我来说,我用 Inspect Element 来做(Firefox)。对于这个网站,我们将限制爬虫将目标(“.pagination2 ul li a”,”.col-lirik .div-horizontal2-list a”, “div .letterLinksAnchor”)
。它将抓取网站,直到没有更多的网址抓取(它还会检查该网址是否已被访问)。
Image 3: Part that we want to extract
接下来,我们要从网页中提取歌词和标题的歌曲。为此,我们需要找到包含它们的 HTML 标签(图 3 中红色和蓝色的标签)。
song = response.css('.col-lirik').extract_first()
title = response.css('.head-lirik h5::text').extract_first()
对于歌词(我将其命名为' song '变量),我们需要 HTML 代码,因为这个网站的 HTML 组成有点乱。我们一会儿需要清理它。
救你的lyricscrapper.py
。然后,打开文件夹内的settings.py
。
添加或取消注释这些行:
FEED_FORMAT = "csv"
FEED_URI = "scrape.csv"DOWNLOAD_DELAY = 1 # important, sometimes you will get banned if you set it to 0\.
保存它,然后在控制台上执行以下命令:
scrapy crawl lyric_scrapper
瞧,我们的爬虫将爬行我们的目标站点。只要等到它结束或强迫它结束,如果你很无聊。结束后,它会在文件夹内生成scrape.csv
。您可以使用电子表格工具打开它来查看。有点乱,不是吗?。如上所述,我们需要清理歌词的文本。所以让我们进入下一步。
清除报废数据
现在是时候清理我们的脏数据了。因为我们只想生成歌词,所以我们只需要来自scrape.csv
的歌曲列。在开始之前,我建议我们使用 Python IDE,如 Jupyter Notebook 或 Spyder,以便更好地查看我们的数据。在这一部分,我们将使用 pandas 库来查看表格中的数据。
打开您的代码,然后让我们导入我们的 csv 数据,并将其转换成 dataframe 类型(pd.DataFrame
)。为了检查歌词的歌曲,我们将采样 5 个实例。一定要把scrape.csv
文件放到我们 python 的代码文件夹中。
import pandas as pd
scrape_lyric = pd.read_csv('scrape.csv')
scrape_lyric.sample(5)
首先,我们需要确保我们的数据没有缺失数据。然后,如果提取了一些错误页面,我们就移除不想要的数据。在我们的例子中,我们会发现我们的歌词网页应该包含 span 标签。所以删除没有 span 标签的实例。我们将删除包含“Belum ada Lirik”文本实例(翻译:没有任何歌词)。
在清理之前,我们应该检查数据的大*。使用scrape_lyric.shape
进行检查。我有 20259 行。
scrape_lyric = scrape_lyric.dropna()
scrape_lyric = scrape_lyric[scrape_lyric.song.str.contains('span')]
scrape_lyric = scrape_lyric[~(scrape_lyric.song.str.contains('Belum Ada Lirik'))]
检查你的数据帧scrape_lyric.shape
的大*,我有 13791 行。它遗漏了 6468 行!
我们只会看到‘宋’一栏。通过查看 song 列,我们会看到文本仍然有 HTML 标记。我们需要清理它。我们将使用正则表达式来做这件事。
Image 4: Example of 1 instance in the data
这个清理正则表达式只适用于我们的目标网站。如果我们的目标是其他网站,我们需要看看 HTML 模式是怎样的,并使用适当的正则表达式来清理它(或者如果网站很好解析,可能不需要清理数据)。
这里是清理我们的网页的正则表达式:
def clean_text_lyric(lyric, max_length):
lyric_sample = lyric.split('</span>')
lyric_sample = lyric_sample[:-1]
clean_song_lyric = ""
for sentence in lyric_sample:
if 'http' not in sentence:
sentence = re.sub(r'<div .*>','',sentence)
sentence = re.sub(r'<span .*>','',sentence)
sentence = sentence.strip()
if len(sentence) > 0:
sentence = re.sub(r'[^a-zA-Z0-9<\/>\s]',' ', sentence) sentence = " <div> " + sentence + " </div> "
sentence = re.sub(r'<div>\s+<br>','<br> <div> ', sentence)
sentence = re.sub(r'(\d|\r|\t|\n)','',sentence) clean_song_lyric += sentence clean_song_lyric = ' <start> ' * (max_length-1) + clean_song_lyric
return clean_song_lyric
我们将逐一看到:
lyric_sample = lyric.split('</span>')
lyric_sample = lyric_sample[:-1]
如果我们查看我们提取的歌词,他们用 HTML 标签“<br>
”来分隔他们的诗句。1 节包含几行。每行由 HTML 标记“</span>
”分隔。我们需要通过使用“</span>
”来拆分行。
现在我们移除 HTML 标签(div,span)
sentence = re.sub(r'<div .*>','',sentence)
sentence = re.sub(r'<span .*>','',sentence)
然后我们将删除除了 [^a-zA-Z0–9<\/>\s]
以外的所有字符。我们删除了转义字符和多余的空白。如果你不熟悉 regex,建议你试试这个站点玩 regex。
sentence = re.sub(r'[^a-zA-Z0-9<\/>\s]',' ', sentence)sentence = " <div> " + sentence + " </div> "
sentence = re.sub(r'<div>\s+<br>','<br> <div> ', sentence)
sentence = re.sub(r'(\d|\r|\t|\n)','',sentence)
我讨厌这个网站的 HTML 代码。提取的歌词有时在歌词内有 URL。这就是为什么我设置了循环保护来确保里面没有 URL。
在我们清理文本之后,我们想要标记我们的开始和结束歌词的行。
对我来说,我使用了<div>
和</div>
标签来标记我们歌词的开始和结束。
我们不会删除<br>
标签。这是一个标记,用来分隔每一节。
最后,我们将在所需的max_length-1
的歌词开头添加<start>
标签。我们为什么要这么做?我以后会告诉你。
将其应用到数据框中:
scrape_lyric['song'] = scrape_lyric['song'].apply(lambda x: clean_text_lyric(x))
这是我们想要使用的歌词格式文本。
Image 5: desired lyric’s format
预处理数据
清理完数据后,让我们进入数据预处理。为什么我们需要这样做?我们的深度学习模型的输入是一系列文本。它不能在字符串模式下读取文本。我们需要将数据集中的所有单词编码到索引号中,在一次热编码中将索引号映射到单词中。当我们使用嵌入时,在 keras 中,我们不必将文本编码成一个热编码。我们可以使用键索引映射来映射模型中带有索引号的单词。
在此之前,让我们将包含几行的歌词转换成一个具有所需长度的序列文本数组集合。
def generate_train_dataset(song_series, window):
train_data = []
train_label = []
for song_string in song_series:
song_arr = song_string.split()
len_song_arr = len(song_arr) for i in range(0,len_song_arr-window+1):
train_data.append(' '.join(song_arr[i:i+window-1]))
train_label.append(song_arr[i+window-1])
return np.array(train_data), np.array(train_label)
请看图 6,想象一下generate_train_dataset
功能是如何工作的。它将从开始切片到window-1
并将其添加到 train_data 列表中。然后将最后一个索引添加到train_label
列表中。这叫做滑动窗口,窗口长度等于我们的window
参数。在本文中,我们将设置窗口等于 10。
Image 6: sent_len parameter set to 5
我们创建的函数需要一个pandas.Series
类型作为输入。
max_length = 10 #window
X, y = generate_train_dataset(scrape_lyric.song, sent_len=max_length)
成功了吗?很好,接下来我们将使用keras.preprocessing.text.Tokenizer
库来创建一个输入映射,它将一个单词映射到函数选择的索引号。确保更改参数过滤器,不包括‘<’
和‘>’
。
pre = keras.preprocessing.text.Tokenizer(filters='!"#$%&()*+,-.:;=?@[\\]^_`{|}~\t\n')
pre.fit_on_texts(X.flatten()) # need to flatten the array
我们将得到词汇量,它包含了我们的数据中有多少独特的单词。
vocab_size = len(pre.word_index)
我们将数据转换成单词索引序列:
X = pre.texts_to_sequences(X)
y = pre.texts_to_sequences(y)
Image 7: How Our Tokenization works
我们已经完成了对输入数据的预处理。我有大约 200 万个例子。
让我们继续创建模型。
定义深度学习的架构
在我们深入研究代码和实现之前,让我们回忆一下什么是深度学习、密集层、RNN、LSTM 层和激活函数。我们会召回他们。
深度学习
深度学习是机器学习技术的一个子集。根据 Yoshua Bengio 的说法,他说“深度学习算法寻求利用输入分布中的未知结构,以便发现良好的表示,通常是在多个级别,较高级别的学习特征根据较低级别的特征来定义”。
Source : pixabay.com
深度学习将从数据中学习特征表示。我们不必从数据中提取特征。它不同于其他需要提取特征的机器学习算法。它由模仿人脑的几个层次和网络组成。它有许多别名,如深度神经网络。深度神经网络的主要部分是反向传播算法,它将使用优化器算法更新我们的模型权重,使误差最*。如果你想了解更多,请访问这个网站。
把...嵌入
Source : ruder.io
嵌入是一种技术,它将使我们在数据集中的实例成为一种经过学习的表示。在本教程中,我们将使用单词嵌入。单词嵌入将把我们的单词表示成作为实值向量的学习表示。它通常由十*或数百*向量组成。向量通常会捕捉单词的意思。
有几种算法可以进行单词嵌入。有:
- 嵌入层
- Word2vec
- 手套
- 节目预留装置
- 埃尔莫(新)
在我们的模型中,我们将使用嵌入层。它将根据我们的模型更新向量。
致密层
这是全连接层的别名。它是一个线性层,传播一个线性函数,并使用该函数的导数(梯度)从一个神经元反向传播到另一个神经元。更简单地说,这是一个网络,它只接受输入并乘以从反向传播中学习到的权重。我找到了一篇中型文章,可以帮助你更好地理解全连接层。
RNN 和 LSTM
Source : colah.github.io
递归神经网络(RNN)是一个具有内部存储器的层,因此它可以记住输入的序列信息。神经元之间连接是一系列有向图。它会记住前一个神经元的信息(权重),并将其传递给当前神经元。
使用 RNN 有几个缺点。它学不会'长期依赖'。它会遇到一个问题,叫做“消失梯度”。它不会再更新神经元的权重。为了解决这个问题,长短期记忆(LSTM)被使用。
LSTM 是 RNN 问题的一剂良药。它有能力解决“长期依赖”问题。LSTM 有能力通过一种叫做“门”的结构给新神经元添加或删除信息。LSTM 有三个门:遗忘门、输入门和输出门。他们将控制神经元的状态。如需了解更多信息,您可以访问此网站。
批量标准化
归一化目标图层的输出值。它们的平均输出激活为 0,标准偏差为 1。它有几个好处,如加快我们的训练速度。如果你想了解更多关于 BatchNormalization 的细节,请看这篇文章。
激活功能
它用于确定一个层的输出是否被激活。它将输出映射到激活函数的范围。要了解更多细节,请访问这篇文章。
体系结构
回忆完了吗?让我们进入代码
我们将建立的是一个简单的架构深度网络。它由嵌入层、LSTM 层和密集层组成,以分类交叉熵和 softmax 激活作为输出。图 7 是我们想要创建的架构的可视化。
Image 7 : Visualization of our architecture
model = Sequential()
e = Embedding(vocab_size,100 ,input_length=max_length-1, trainable=True)
model.add(e)
model.add(keras.layers.BatchNormalization())
model.add(keras.layers.Bidirectional(keras.layers.CuDNNLSTM(100)))
model.add(keras.layers.BatchNormalization())model.add(Dense(100, activation='relu'))
model.add(keras.layers.BatchNormalization())model.add(Dense(vocab_size+1, activation='softmax'))
# vocab_size +1 to avoid out of bound
# compile the model
model.compile(optimizer='adam', loss='categorical_crossentropy')
在本文中,我们将使用具有所述超参数的模型。当然,你可以调整我们模型的超参数。为了简单起见,我们将只使用一个双 LSTM 和一个密集层。我们使用批处理标准化来加速我们的学习者。如果用 GPU,就要用 CuDNNLSTM 来加快训练速度。
我使用亚当优化,因为它是一个流行的优化现在。该算法速度快,能很好地适应反向传播模型的学习速度。
火车模型
在我们调整或训练我们的模型之前。我们有一个问题要解决。如果我们看到我们的 vocab_size,它有大约 45000 个独特的单词。在 keras 中,我们应该将火车标签编码成一个热编码[0 0 0 … 1 … 0]。如果我们将我们所有训练标签改变成一个热编码,这将导致内存错误(它需要 45.000 * 2 兆* 4 字节内存。不可能保存到内存中)。因此,我们需要将我们的火车标签批量更改为一个热编码。
def batch_data(start,end):
global X,y,y_input, X_input
X_input = np.array(X)[start:end]
y_input = np.array(y)[start:end]
y_input = keras.utils.to_categorical(y_input,vocab_size+1)max_epoch = 40
instance_max = len(X)
batch_size = 10000for i in range(max_epoch):
start_idx_counter = 0
while start_idx_counter < instance_max:
batch_data(start_idx_counter, min(start_idx_counter+batch_size,instance_max))
model.fit(X_input, y_input, epochs=1, batch_size=64)
start_idx_counter += batch_size
我们将 10000 定义为我们的批量。你可以随意增减尺寸。我们用 40 个时期(迭代)来拟合我们的模型。执行代码!fit 方法中的 batch_size 也可以调整。
等着吧!!
source: me.me
用 GPU 训练我的模型花了 1 天。如果你不想等那么久,减*max_epoch
。
完成了吗?不要忘记保存模型和记号赋予器。你想再等一天来训练我们的模特吗?没有吗?不要忘记保存模型!
model.save('lyric_gen_model.h5')
我们将使用pickle
库来保存我们的标记器
import pickle
pickle.dump( pre, open( "tokenizer_pre_lyric.p", "wb" ) )
我们完了。让我们创作我们的歌词吧!!!
生成歌词
让我们使用我们的模型来生成歌词。我们已经训练了我们的模型,我们将使用它。为此,我们需要加载我们的模型和标记器。
model = keras.models.load_model('lyric_gen_model.h5')
pre = pickle.load( open( "tokenizer_pre_lyric.p", "rb" ) )
然后我们需要首先预处理我们的输入。
def preprocess_predict(X):
X = pre.texts_to_sequences(X)
return X
在我们的文章中,我们在歌词的开头插入了“
seed = "<start> " * (max_length-1)
或者,您也可以包含一些起始单词。
seed = "<start> " * (max_length-3)
seed = "<div> love"
我们应该定义函数来帮助我们生成歌词
def is_word_in_dict(words, word_idx):
for word in words.split():
if word not in word_idx:
return False
return Truedef generate_song_by_model(model, idx_word, X_sent, word_idx, total_classes, word_generated=80):
string_returned = X_sent
if is_word_in_dict(X_sent, word_idx):
X = np.array(preprocess_predict([X_sent]))
counter = 1
for i in range(word_generated):
y_pred = model.predict(X)
rnd_choice = np.random.choice(range(0,total_classes),size=1,replace=False, p=y_pred[0])
word_predict = idx_word[rnd_choice[0]]
string_returned += " " + word_predict
X = ' '.join(string_returned.split()[counter:])
X = np.array(preprocess_predict([X]))
counter += 1 return string_returned
在这个函数中,我们将根据我们的种子(generate 函数中的 X_sent 变量)来预测单词。我们将窗口大*长度为 1 的标记作为我们的模型的输入,并且该模型将预测下一个标记。在下一个循环中,它将把预测的输出和 size-length-2 标记带入模型。它会一直循环到我们设定的终点。我们将根据 softmax 的输出产生的概率分布得到一个随机单词。如果您正在使用 Jupyter Notebook,使用此命令显示生成的歌词
from IPython.display import HTML
generated_lyric = generate_song_by_model(model, pre.index_word, seed, max_length, pre.word_index, vocab_size+1,loop_count=50)
HTML(generated_lyric)
它将生成 50 个新的令牌/单词(包括标签)。生成的歌词应该有 HTML 标签
和
,作为行和诗的分隔符。我们使用 IPython.display 中的 HTML 函数来清理显示中的标签。这里有一些我们生成的歌词的例子。
我试着带你回家
我是救世主之光
总有一天沙漠会飞走
谁俯视着我的双手
如果我做得不好
你开始想办法
在这个生成的歌词里。使用英语单词非常一致。虽然有些令人困惑的意思,但还不错。我们的结果是基于随机性的。如果你的模型学得少,它会产生糟糕的歌词!
如果你想知道为什么它会产生英语单词,有时印*歌曲包含混合语言。有些歌曲包含完整的英文单词。
这里是另一个生成的歌词。
dara kau bertanya siapa namamu
杨森永坦吉斯穆
pasti pahit di ayahku
帕达·贝尔穆拉·迪潘当·卢卡
dan semua karena cintamu
这是我第一次见到你。
ku tak ingin sendiri
想知道歌词的意思就翻译一下。关于用印*语和谈情说爱也很一致。同样,它的随机性将决定歌词的好坏。
结论
如果你关注这篇文章,我们已经建立了一个工具来生成印度*西亚歌词。我们利用网络爬虫和深度学习库来构建生成器。它可以产生一些好的歌词,虽然这取决于我们的运气(随机性对概率)。
在本文中,我们跳过了一些步骤,如探索性分析。我们应该尝试另一种架构或超参数。我们还需要评估生成的歌词。
编后记
感谢您阅读我的第一篇关于人工智能的文章。由于这是我的第一次,我在这方面还不太专业,我需要一些建设性的反馈,让我在写作和深度学习方面做得更好。请手下留情> _
抱歉任何拼写错误,语法,和低效的代码。
哦,我提到第一部分了吗?是的,我计划通过使架构更复杂(可能使用 GAN),使用另一种嵌入和超参数来改进这个歌词生成器。
在下一篇文章中,我将从一个将从头开发的游戏中进行一些强化学习。
下一篇文章再见!
Source: pixabay.com
来源
- https://www . up work . com/hiring/for-clients/web-scraping-tutorial/
- https://colah.github.io/posts/2015-08-Understanding-LSTMs/
- https://machine learning mastery . com/what-are-word-embedding/
- https://medium . com/deep-learning/glossary-of-deep-learning-batch-normalization-8266 dcd2fa 82
- https://towards data science . com/activation-functions-neural-networks-1 CBD 9 F8 d 91d 6
为计算机视觉生成大型、合成、带注释和照片级真实感数据集
原文:https://towardsdatascience.com/generating-large-synthetic-annotated-photorealistic-datasets-for-computer-vision-ffac6f50a29c?source=collection_archive---------16-----------------------
我给大家介绍一下我们在 Greppy 一直在做的一个工具的 beta 版,叫 Greppy 元宇宙(2020 年 2 月 18 日更新: 合成 AI 已经获得了这个软件,请通过Synthesis . AI联系他们!),它通过快速轻松地生成大量用于机器学习的训练数据,来辅助计算机视觉对象识别/语义分割/实例分割。(旁白:如果可以的话,合成 AI 也喜欢帮助你的项目——在 LinkedIn 上通过【https://synthesis.ai/contact/】或 联系他们)。
如果您过去做过图像识别,您会知道数据集的大*和准确性非常重要。你的所有场景也需要被注释,这可能意味着成千上万的图像。对于我们的*团队来说,这样的时间和精力是不可扩展的。
概观
因此,我们发明了一种工具,使得创建大型的带注释的数据集更加容易。我们希望这可以对增强现实、自主导航和机器人技术有所帮助——通过生成识别和分割各种新对象所需的数据。
我们甚至开源了我们的 VertuoPlus 豪华银数据集,其中有 1000 个咖啡机的场景,所以你可以一起玩!是个 6.3 GB 下载。
为了展示它的功能,我将在 Greppy 这里为您展示一个真实的例子,我们需要用一个英特尔实感 D435 深度摄像头来识别我们的咖啡机及其按钮。将来会有更多关于为什么我们想认识我们的咖啡机,但可以说我们经常需要咖啡因。
Screenshot of the Greppy Metaverse website
在过去的日子里,我们不得不用手来注释。
VGG Image Annotator tool example, courtesy of Waleed Abdulla’s “Splash of Color”
对于过去的大多数数据集,注释任务都是由(人类)手工完成的。正如你在左边看到的,这不是特别有趣的工作,而且和所有人类的事情一样,它容易出错。
它也几乎不可能准确地注释其他重要信息,如物体姿态,物体法线和深度。
合成数据:10 年前的想法
人工标记的一个有希望的替代方法是合成产生(理解:计算机生成)的数据。这是一个已经存在了十多年的想法(参见这个 GitHub repo 链接到许多这样的项目)。
From Learning Appearance in Virtual Scenarios for Pedestrian Detection, 2010
不过,我们在现有项目中遇到了一些问题,因为它们要么需要编程技能才能使用,要么不能输出逼真的图像。我们需要一些非编程团队成员可以用来帮助有效生成大量数据以识别新类型对象的东西。此外,我们的一些对象在没有光线追踪(*基百科)的情况下很难产生真实感,这是其他现有项目没有使用的技术。
用格雷皮·元宇宙制作大规模合成数据
为了达到我们想要的目标数量,我们制作了 Greppy 元宇宙工具。例如,我们可以使用来自 3D 仓库网站的预制 CAD 模型,并使用网络界面使它们更加逼真。或者,我们的艺术家可以创建一个定制的 3D 模型,但不必担心如何编码。
让我们回到咖啡上。使用我们的工具,我们首先上传我们拥有的 Nespresso VertuoPlus 豪华银机的 2 个非真实感 CAD 模型。我们实际上上传了两个 CAD 模型,因为我们想在两种配置中识别机器。
Custom-made CAD models by our team.
CAD 模型上传后,我们从预先制作的照片级真实材料中进行选择,并应用到每个表面。Greppy 元宇宙的目标之一是建立一个开源的、真实感的材料库,任何人都可以使用(最好是在社区的帮助下!).作为一个旁注,3D 艺术家通常需要创建自定义材料。
Select pre-made, photorealistic materials for CAD models.
为了能够识别机器的不同部分,我们还需要标注我们关心机器的哪些部分。web 界面提供了实现这一点的工具,因此不了解 3D 建模软件的人可以帮助完成这一注释。不需要 3D 艺术家或程序员;-)
Easily label all the parts of interest for each object.
然后……就这样了!我们自动生成多达数万个场景,这些场景在姿势、对象实例数量、相机角度和照明条件方面各不相同。它们都会被自动标注,并且精确到像素。在幕后,该工具用 GPU 旋转了一堆云实例,并在一个*“renderfarm”上渲染这些变化。
以下是来自开源 VertuoPlus 豪华银数据集的 RGB 图像示例:
A lot of scene RGBs with various lighting conditions, camera angles, and arrangements of the object.
对于每个场景,我们输出一些东西:基于所选相机的单目或立体相机 RGB 图片,相机看到的深度,所有对象和对象部分的像素完美注释,相机和每个对象的姿势,最后,场景中对象的表面法线。
让我再次强调任何场景都不需要手工标注!
单个场景的输出示例如下:
Output examples from each scene
基于合成数据集的机器学习
随着整个数据集的生成,很容易使用它来训练 Mask-RCNN 模型(关于 Mask-RCNN 的历史有一个很好的帖子)。在后续的帖子中,我们将使用 Mask-RCNN 的 Matterport 实现,开源我们用于从 Greppy 元宇宙数据集训练 3D 实例分割的代码。
与此同时,这里有一个**的预览。这是来自英特尔实感 D435 相机的原始捕捉数据,左边是 RGB,右边是对齐的深度(总共构成 4 个通道的 RGB-D):
Raw data capture from Intel RealSense D435. Yes, that’s coffee, tea, and vodka together 😉
对于这个 Mask-RCNN 模型,我们在具有大约 1000 个场景的开源数据集上进行训练。经过 30 个时期的模型训练后,我们可以在上面的 RGB-D 上看到运行推理。瞧!我们得到一个几乎 100%确定的输出掩码,只对合成数据进行训练。
当然,我们也会开源培训代码,这样你就可以自己验证了。
一旦我们能够识别图像中的哪些像素是感兴趣的对象,我们就可以使用英特尔实感框架来收集这些像素处咖啡机的深度(以米为单位)。知道 Nespresso 机器的精确像素和精确深度对任何 AR、导航规划和机器人操纵应用都非常有帮助。
总结想法
目前,Greppy 元宇宙还处于测试阶段,我们还有很多需要改进的地方,但我们对目前的结果非常满意。
同时,如果你有一个项目需要帮助,请联系 https://synthesis.ai/contact/的合成人工智能或 LinkedIn 的。
特别感谢瓦利德·阿卜杜拉和叶锦华帮助改进这篇文章:)
通过机器学习为机器学习项目产生新想法
原文:https://towardsdatascience.com/generating-new-ideas-for-machine-learning-projects-through-machine-learning-ce3fee50ec2?source=collection_archive---------7-----------------------
使用预先训练的语言模型从 2.5k 句子的*型语料库中生成风格特定的文本。PyTorch 代码
让我们做一个快速图灵测试。下面,你会看到十个机器学习项目创意。其中五个是由人类产生的,五个是由神经网络产生的。你的任务是区分它们。
准备好了吗?(不要想多了。跟着感觉走)。
- 股票交易学习者
- 预测数据中的频率差异
- 专利分类的机器学习
- 遥感图像卷积特征的分类
- 基于随机森林的人脸检测
- 机器学习预测职业成功
- 旋转不变稀疏编码
- 深度学习在公平性中的应用
- 三*点云中的物体识别
- 加利福*亚的建筑模型
看到名单了吗?记下你认为神经网络产生的五个想法,以及人类产生的五个想法。
提示鼓声寻找答案。
Who’s the robot and who’s the human? Reveal time. (image via Pixabay)
回答:所有奇数编号的想法都是斯坦福大学 CS229 机器学习课程完成的最终项目的标题,所有偶数编号的想法都是由在该数据集上训练的神经网络生成的。
是的,向上滚动并再次查看列表,比较您的笔记,然后我们将深入了解这些想法是如何产生的细节。你有多准确?(评论里讲!)
这个项目的动机是让我学会使用递归神经网络(RNN)来生成类似于我最喜欢的哲学家和思想家的引文。我见过许多其他人用 RNNs 创作音乐、笑话,甚至分子。除了哲学,我也想做同样的事情。
我从网上收集了大约 5000 条来自加缪、*采、*特根斯坦、费曼、大卫·休谟、斯蒂芬·霍金和詹姆斯·卡尔斯等思想家的引文。
我完全没有注意到的是,我作为灵感的项目通常有数百万的数据集,而我自己只有 5000 个句子。天真而盲目地,我继续前进,而在让我的人造哲学家工作方面一再失败。最后,在三次失败的实验后,我让它工作了,随后我为机器学习的想法建立了一个生成器。
当训练样本很*时,RNNs 不合理的顽固
这是我用 RNNs 做的第一个失败的实验:
- 我认为语料库不够大,不足以训练一个单词级语言模型,所以我选择了一个字符级语言模型
- 我在语料库上训练了一个非常简单的基于 LSTM/GRU 的单层递归网络,但效果不佳
- 它输出看起来像英语,但最终却是乱码的句子,如“我可以到某处我们和可以到这来撕到界限撕到保留地
我的第二次失败的实验:
- 我想也许一层循环单元是不够的,所以我试验了两层,也尝试了更高的学习率。
- 什么都没用。我仍然在胡言乱语,比如:“我真的在昨天的演讲中发现,在你那里的男人对你来说更重要一些
我的第三次失败的实验:
- 由于语料库规模较*,我认为生成性对抗框架可能会更好
- 但这也没用,我意识到 LSTMs 的 GAN 很难,有关于它的论文,但训练很难,输出质量也不是很好。
- 经过大量训练后,我的感冒更严重了。它生成的文本完全是垃圾:“x 11114111141111111111111111
经过这么多次失败的尝试,我感到非常沮丧,我的人工哲学家将永远是一个白日梦。
Why can’t I get my artificial philosopher to work? (Not my photo, but you wouldn’t know) via Pixabay
我从这些失败的尝试中得出的结论是,罪魁祸首是*文本语料库。
也许 5000 个报价不足以产生高质量的类似报价?
因此,作为我的下一个实验,我想尝试预先存在的单词嵌入,如 word2vec ,而不是强迫网络从头开始学习嵌入。但是,在此之前,我决定听取 Reddit 的机器学习 subreddit 的建议。在我开始的帖子上,有人给我指了一张 2018 NeurIPS 大会的海报,标题是:“针对特定风格文本生成的迁移学习”。我遵循了那篇论文的观点,它们非常有效。
什么是迁移学习?
迁移学习是一个简单但强大的想法。这意味着使用在非常大的数据集上训练的现有模型作为起点,并调整它以在特定领域的数据集上工作良好。
Image via Intel’s developer website
在计算机视觉领域,迁移学习已经使用了很长时间。这个想法是使用一个公开可用的模型,如 VGG,它在 ImageNet 数据集上进行训练,该数据集包含 20,000 个类别的 1400 万张图像,并使用其最后一层的激活作为附加任务特定层的输入。然后,额外的层专门在您的*型、特定于域的数据集上进行训练,以用于预测、分类或任何其他任务。
使用预训练模型的惊人之处在于你可以免费使用预训练模型在数百*时的训练中从数百万张图片中学到的所有概念。
预先训练的模型是压缩的知识。
这些预先学习的概念和激活使您能够对您的*型特定领域数据集进行预测和分类。这种神奇的事情发生是因为所有“自然”数据集都有相似的特征。大多数图像共享许多特征:从形状、线条和边缘的原始概念到诸如纹理和光影效果的高级概念。
如果没有预先训练的模型,您将不得不从头开始学习所有这些概念,并且您的数据集可能不包含足够的示例来做到这一点。有了一个预先训练好的模型,你可以直接了解在你的领域/问题中什么是重要的和不同的,而不用担心在数据集之间发现的共同的东西。
使用预先训练的语言模型进行文本和自然语言处理中的迁移学习
最近,迁移学习开始在 NLP 中出现,令人兴奋的可能性已经出现。有谷歌的巨型伯特模型,然后还有乌尔姆菲特。
这些语言模型是在公开可用的文本语料库(如议会记录、*基百科等)上训练的,并且隐含地编码了英语知识。因此,即使数据集非常*,它们也能实现机器学习任务,如对文本进行分类和预测。
这正是我想要的!我的引语数据集很*(~5k),我的目标是生成与我最喜欢的思想家风格相似的新引语。
从*型数据集生成文本的代码
为了从我的*语料库中生成风格特定的文本,我遵循了从 Reddit 线程链接的论文,这将我带到了 FastAI 的关于使用预训练模型对 IMDB 评论进行分类的课程。这一课是关于分类的,但是当我浏览 FastAI 库的文档时,我发现由于库中的帮助函数,即使是生成文本也变得很简单。
我的代码和数据集存在于这个库中。你需要 PyTorch v1,FastAI v1 和*猫。注意,我的代码实际上是从 F astAI 文本模块的文档中复制粘贴而来的。他们让使用预先训练好的模型变得如此简单。
我们使用什么样的预训练模型?这是一个由 Salesforce 的研究团队开发的三层 AWD-LSTM 模型,它在来自*基百科文章的 1 亿个令牌上进行训练。我鼓励你阅读更多关于这个特定模型的细节,但是使用预训练模型的一个主要好处是,你可以不理解底层的细节。就像你很可能不关心 Pytorch 和 Numpy 如何在幕后工作一样,你也可以不关心 AWD-LSTM 法案如何在幕后工作。
由预先训练的模型提供的这种抽象级别是真正革命性的。
现在,任何人都可以在各自的领域组装最先进的深度学习模型,而不需要数月或数年的努力。(但是当你没有得到结果时,知道细节是有好处的)
人工哲学家:由我的神经网络产生的新的哲学见解
What would my artificial philosopher spit out? (Photo by Pixabay)
当我运行我的模型时,我简直不敢相信它的结果。兴奋之余,我发了微博:
我的网络说:“世界上没有一个人不是奴隶”,这听起来好得令人难以置信,以至于我首先检查了它是否只是重复了一段从数据集中背下来的话。当我没有找到它时,我谷歌了确切的短语,看看这个想法以前是否被表达过。你瞧,我也没有在谷歌上找到它。
这是由神经网络生成的 100 个报价的运行。这些都不是我以任何方式修改的。我从我的笔记本上复制粘贴了这些。(我加粗的是那些耐人寻味且可能独一无二的)。
'por las vida de los mundo de los mundo en el chi',
'**the truth is that we can not be sure of what we do not know** .',
'according to the standard , man is the real animal .',
"it is my business that i think that 's what i do n't know .",
'after a adventure , it was not until that point that old ideas were drawn up .',
'the lives of a finite player player must be avoided .',
'**a human being is also an animal** .',
'i had to turn',
"i want people to be happy but i do n't want to be ourselves .",
'there is a greater freedom for the philosophers and for the philosophers .',
'**for a moment is not merely a thought , but a tragedy** .',
'at this stage it is the true art .',
'i am the bridge , which is the bridge and the one that carries the bridge .',
'it is the wisdom that the world has not yet seen established at all .',
'**the future is great because we love everything** .',
'what is the belief in the right to man ?',
'nature is a perfect field of vision .',
't',
'**to learn to draw is to impose a law on the law of physics** .',
'**the feeling of absurdity : that is , as we see why we are here** .',
'**he who fights with monsters knows what he is** .',
'**no longer culture is a sign of self - mastery** .',
'when the universe is rotating , i will make a very very big decision .',
'today this is probably the most so - called mystery of science .',
'it is not a matter of fact , a reason for being ashamed of love .',
'the world around me , i believe , it is the world itself .',
'the subject must always be a man who is not alone . the',
"some people n't want to be stupid .",
'**the good dream is that you have to struggle for the good and the bad** .',
'there is no community without the strong and just no one to live across .',
'i am not the man who is myself .',
'**i felt that i had to quite cease to exist when i was touched** .',
'the above principle of infinite players is perfectly good .',
'**the stars are small and solitary , though they are neither great nor bad** .',
'all souls are ignorance .',
'**the limits of my language are always your limits** .',
'**the world is a world without any real purpose** .',
'beyond the curve of the days become his favorite .',
'i continue to believe in this condition of life',
'here is the origin of all things .',
'**we have to live and let live in order that we can create a universe** .',
'**a man is very much the most fertile man** .',
'**this world comes out of nowhere** .',
'to live is to be happy .',
'**the present man has a reason to be able to give birth to a dancing star** .',
"it 's surprising to say that the real world had a beginning :",
'the first thing is to die at heart .',
'and how i learned to walk and dance , i must sing .',
'**as long as the mind is limited by its laws , it can not be understood** .',
'**the weakness of the apes is not infinite , but our surprise** .',
'at the end of a conversation there is an invincible summer .',
'les de la vida pour la vie a es se non het la vida .',
'i say the last thing , in the end , is to die .',
'**what does man understand is that the true man is a unjust child** .',
'the soul is a dead cause .',
"it seems that there is nothing less than a child 's love .",
'that is why the world is governed by the laws of physics .',
'the king is a genius who goes to school to be a public relations yes .',
'**the child is born of this solitude** .',
'**i am a tree among trees** .',
'we have never got the least of ideas and ideas .',
'every age in the middle ages is born of the holy spirit of peace .',
'but no one is willing to strive for peace , justice or reason .',
"but n't the time is going to happen if what breathe is bad .",
'at the heart of all beauty lies something monstrous and full of things .',
'really , my heart is never .',
'yes , it is to say that there is a very rapid increase in human affairs .',
'everything in the world is like a dead world .',
'the good man is a man who wants to play my own .',
'there are no real truths , but it is a perpetual truth that is true .',
'you imagine that he can not live without knowing how to live .',
'the problems of life are not universal , but the future of mankind .',
'no one can build a bridge across the river of life .',
'**passion is the desire to be strong . however it is necessary to love the weak** .',
'**in the end one must have experience to live with envy** .',
'from the dark horizon of my future a future will never be seen .',
'he who does not know has the meaning , his reason to do .',
'**no one has any idea how youth ... must have learned how to walk** .',
'it is true that mersault was a very poor soil .',
'this is where we see and where there are , and what we see here .',
'a species of th',
'there are no boundaries between those limits of physical limits .',
'man is one who has the advantage of being overcome',
'woman is a woman . she is a tahu .',
'**to live is to live alone**',
'**the fate of a man must be as great as the rank of man** .',
'all artists of the twentieth century are quite free to live alone !',
'there is no justification of the state for the astonishment of the world .',
'there is evidence that in every human being , a human being must win the match .',
'**the world is worth living** .',
'the dumb man is not a bad bad conscience but a bad liar',
'because we have to choose between being understood we have a friend and love .',
'the mother of child dignity is a mother or mother .',
'**it is the art of value that we do not understand** .',
'a writer has been written with a definite idea of what is really in his universe',
'they believe that something is rare for the rare .',
'every step forward in the world preclude a future and there is a certain future .',
'and continuing that is the horror of original conservation .',
'**solitude is often an activity** .',
'**one concerns me that things can never be forgotten** .',
'**i love people who have no happiness , but not lest they become strong** .'
您一定在其他文章中看到过同样令人印象深刻的生成文本。但是我认为这里令人印象深刻的是生成文本的质量,因为我的训练集非常* (5k 个句子)。只有使用预先训练好的模型才可能做到这一点。
这可能看起来不多,但我认为像“我语言的极限永远是你的极限”这样的想法似乎是语言哲学家路德*希·*特斯坦根说过的。事实上,当你用谷歌搜索这个短语时,你找不到确切的结果,但是谷歌建议你去*基百科上查一下关于*特根斯坦的文章。
Getting Wittgenstein to say new things after he’s dead
事实上,*特根斯坦说过:“我的语言的限制意味着我的世界的限制”,我们的模型聪明地(并且以语法上准确的方式)把它改成了新的东西。
类似地,生成的引用“现在的人有理由能够生下一颗跳舞的星”让人想起*采,因为他在他的书中提到了“跳舞的星”,但他从未在现在的人的上下文中说过。我可能读得太多了,但对我来说,产生的引用代表了这样一种想法,即我们在技术上已经变得如此先进,以至于我们可以产生真正复杂的机器(像一个跳舞的明星),我们已经变得如此具有竞争力,以至于我们有理由这样做。(我的神经网络是在警告我们 AI 的潜在危险和它的不可避免性吗?)
让我们产生跳舞的明星:产生新的机器学习想法
记得我的哲学引语语料库大约有 5000 句。我想知道如果我给它一个更*的语料库,这种方法会有什么表现。
我决定产生机器学习的想法会很有趣。据我所知,到目前为止还没有人尝试过这样做。所以我收集了斯坦福大学 CS229 班的学生从 2004 年到 2017 年提交的所有机器学习项目的标题。数据集包括 2500 个想法,每个想法包含五到七个单词。数据集和相应的笔记本可在我的存储库中找到。(注:我不拥有创意的版权。收集这些只是为了研究和探索)
该项目似乎令人兴奋,但我主要担心的是,机器学习项目想法的领域非常狭窄,包含利基和技术术语。我认为这个模型会把记忆中的想法吐出来,和数据集中的想法一样。
然而,令我惊讶的是,它产生了一些非常新颖的想法(粗体,后面是我的评论):
- 通过数码相机行为的不同类型的社交视频游戏。数据集中没有“社交视频游戏”这个短语,所以这一定是新的。
- 从学术话题中学习识别事件的机器学习方法。数据集中没有“学术话题”短语。
- "预测数据中的频率差异 " < -数据集中没有"数据中的频率"短语。
- "利用学习预测特征来识别基因表达 " < -实际上是一个新颖的想法!
- 对光学图像中的人类基因表达进行分类<-目前还没有对人类基因表达进行分类的项目构想。
- 制作世界图像。我认为这是一个有趣的项目建议,你必须想出一个代表整个世界的图像/图形。
- 预测人类行为的*度。可能是对人类所有不同行为方式的无监督分类的建议?
- 强化学习提高专业学习”。训练数据集没有短语“专业学习”。如何运用强化学习的思想来提高专业课的学习能力?我对此印象深刻,因为它看起来既有价值又可行。
- ”单一表达公司市场上有什么?”。你如何将所有股票市场的可用指标结合起来,得出一个最能提供信息的指标?
- 心脏过程的类型。无监督学习,对心脏过程的相似模式进行聚类,以帮助预测和分析可能导致心脏骤停的模式。
- 人类交往的自然史。使用人类迁移数据集,如何对历史上的人类互动进行分类。你能对历史学家和人类学家忽略的人类互动产生新的见解吗?
- 遥感图像卷积特征分类。数据集没有“卷积特征”这个短语。对于任何对 CNN 背后的理论感兴趣的人来说,这个项目听起来像是一个有趣的研究项目。
- "分类预测事件评论 " < -哇,数据集没有"事件评论"这个词。就像 IMDB 评论一样,我们可以收集事件评论(戏剧或摇滚音乐会)并预测未来的事件,哪些会成功,哪些会失败吗?
如果你想从模型中得到未经过滤的输出,这里有它产生的 100 个想法。我没有修改任何东西(只是把我认为有趣和新颖的部分加粗)。
'the problem is right : grasping and extracting the face of pose',
'applying machine learning to text treatment',
'machine learning techniques for learning through machine learning',
'**a machine learning approach to predicting career success from a single object**',
'**using machine learning to predict the outcome of a machine learning approach**',
'based on stock prices',
'**identifying stock price models for machine learning techniques**',
'a study in time travel time series analysis of musical features',
'vectors in the amazon impact network',
'**classification of web articles in facebook**',
'dynamic signal processing in post - secondary order data',
'copy selection with machine learning techniques',
'interpretation of user classification',
'**the application of deep learning to fairness in using a semantic framework**',
"creating a different entity 's portfolio",
'using supervised learning of blind data',
'system classification for driving automatic vehicle design and classification with gene expression',
'based on public documents from text expression',
'**semantic learning for music**',
'**machine learning for cancer prediction**',
'learning static variations with deep learning for learning options',
'image classification for svm',
'**satellite imagery classification**',
'making decision selection from a single object',
'object detection using product preferences',
'**speech detection with deep learning**',
'**genomic data based on stock trading**',
'**learning to predict approach to handwriting**',
'**classification of musical features from the composer data**',
'semantic social network and smartphone features',
'machine learning techniques',
'**using real - time information to predict the popularity of the market**',
'**video game classification**',
'a learning task for time series players',
'using a single machine learning approach for a single learning approach to learning to identify other environments',
'multiple - genre classification of fraud \n prediction for a mass neural network',
'**learning of human activity recognition from analysis of text**',
"an nba player 's approach to learning and character forecasting through video game ecg",
'playing a vocal instrument in local mri learning',
'real - time music recordings',
'**finding new artistic and artistic features in music videos**',
'**an analysis of musical genres**',
'predicting a single image - specific musical style',
'a cost approach to crime prediction',
'automatic user prediction and automated review recognition',
'**food processing via machine learning**',
'human activity recognition using multi - label fantasy',
'predicting a match in the keystroke poker',
'estimation of game types',
'ai identification of deep learning in locomotion monitoring using neural networks',
'the value of collaborative attention projecting for real - time playing',
'the sea level and low speed : the two waves',
'learning to predict the price of beer and personal genomes',
'**trading and removing a novel image from the text**',
'real - time news user identification on google gestures',
'removing and re - learning to play game and lyrics',
'rapid - mass dynamics with acoustic images',
'real - time music direction',
"what 's your right ?",
'exploring event and music',
'human activity prediction using machine learning',
'**model of architecture in california**',
'vs light crime',
'**adaptive learning for image recognition**',
'predicting the approach of human activity using machine learning',
'the win given trajectories',
'**a machine learning approach to online design**',
'a massive based multi - layer feature unsupervised approach for multi - agent music',
'can you learn from a single hand',
'reaction with the media',
'measurement of time to order over time',
'how people can stop : learning the objects of blood and blood',
'machine learning for autonomous vehicles',
'**vehicle types in neural networks**',
'building a model for what does it store ?',
'for enhanced identification of machine learning techniques',
"**exploring new york city 's public image through machine learning**",
'a novel approach to career image recognition',
'in general game playing',
'structure classification for adaptation of text',
'a variance learning approach for speech recognition',
'the optimization of a non - peer temporal layer',
"a distinguishing feature of a song 's legal expression",
'learning to sound in english : learning to learn using word learning',
'information sharing with adaptive neural networks',
'playing the game with multi - touch neural networks',
'recursive estimation of dynamic and static images',
'predicting the quality of the net - style result in the media',
'the character of the sea snake robot',
'predicting the stock market price of machine learning',
'using inverted nucleotide data to predict the price of convolutional protein models',
'**search engine**',
'using twitter data to predict prices in high - cost trading',
'a machine learning approach',
'creating a new approach to building a deep learning approach',
'fingerprint learning component',
'machine learning techniques for functional change learning for the building of new york city college football networks',
'predicting cancer risk of breast cancer risk',
'cancer diagnosis and prediction',
'stock market classification',
'**identifying the outcome of the news media**'
我没有彻底检查过,但随机检查告诉我,大多数生成的想法都是独特的。我认为生成的文本没有从训练语料库中记忆的原因是因为我们使用了预先训练的模型。预训练语言模型是在*基百科上训练的,因此它甚至在看到训练数据之前就对概念和单词如何相关有强烈的看法。
对于随机初始化的模型,减少训练数据的最简单方法是记住训练语料库。这导致过度拟合。然而,对于预训练的模型,如果网络试图学习训练语料库,它只能在首先忘记先前学习的权重的情况下才能这样做。并且由于这导致更高的误差,更容易的方法是在更早学习的权重的上下文中适应训练语料库。因此,网络被迫归纳并生成语法正确的句子(这要感谢*基百科上的预先训练),但使用特定领域的概念和单词(这要感谢你的数据集)。
你会用这种方法训练什么?
在预先训练好的模型出现之前,你需要一个巨大的文本语料库来做任何有意义的事情。现在,即使是很*的数据集也足以做有趣的事情。请在评论中告诉我,你想到了哪些可以使用*型文本语料库和预训练模型的项目想法。
一些让你的神经元兴奋的想法:
- 利用你的微博,训练一个像你一样发微博的模型
- 使用 WhatsApp 上的数据转储,制作一个像你一样聊天的机器人
- 对于您的公司,将支持票据分类为错误或功能请求
- 制作一个机器人,生成类似于你最喜欢的作者的报价
- 为 Gmail 制作您自己定制的自动回复草稿
- 提供一张照片和一个 Instagram 帐户,按照该帐户以前的标题样式生成标题
- 为您的博客产生新的博文想法(基于以前的博文标题)
此外,如果你最终实现了由我的模型(或本文中包含的模型)生成的机器学习项目想法,那将会非常酷。你将成为的一部分,这是世界上第一个由机器思考并由人类实施的项目!
感谢阅读到目前为止。请在评论中告诉我你的想法和问题。
PS:查看我之前的动手教程 贝叶斯神经网络
感谢 Nirant Kasliwal 审阅本帖草稿并给出有益建议。
在 Twitter 上关注我
我定期发关于人工智能、深度学习、创业公司、科学和哲学的推特。跟着我上https://twitter.com/paraschopra
[## Paras Chopra (@paraschopra) |推特
Paras Chopra 的最新推文(@paraschopra)。@Wingify |的创始人兼董事长写道…
twitter.com](https://twitter.com/paraschopra)
使用具有交互式代码的条件对抗网络从分割掩模生成像素化图像
原文:https://towardsdatascience.com/generating-pixelated-images-from-segmentation-masks-using-conditional-adversarial-networks-with-6479c304ea5f?source=collection_archive---------8-----------------------
Gif from this website
我想用条件对抗网络 实现这篇论文的图像到图像翻译已经很久了,现在我终于有机会这样做了。
此外,我们将使用来自“显著对象分割的秘密的二进制掩码数据集,更具体地说,我将使用来自 pascal 数据集的图像。
Paper from this website
数据集
左图像 →全彩色图像
右图像 →分割蒙版
因此,数据集由两种类型的图像组成,全色图像和分割掩模。我们将为网络提供分段掩码,希望它能够生成全色图像。也请注意,有几个类别的图像。(例如,有图像的人,公共汽车,飞机等…..)
网络层(单层)
红线 →每一层是如何组成的它是由卷积批量归一化最后 Relu()
从上图中我们已经可以看到,这个网络的每一层都由三个操作组成,当在 Tensorflow 中实现时,它看起来像下面这样。
批规范化之所以有 if 条件,是因为生成器的第一层没有批规范化层。
发电机网络架构(全网)
蓝色下划线→发电机网络架构
如上所述,网络的生成器部分与 U-Net 架构非常相似,如果有人感兴趣,我在这里写了一篇关于 U-Net 的博文,请查看。
网络的解码器部分用转置卷积运算代替卷积运算,当在 Tensorflow 中实现时,它看起来像下面这样。
请注意批处理规范化和删除层的 if 条件。所以把编码器部分和解码器放在一起,我们得到如下的东西。
请注意,我们的网络比原始论文中的网络层数少。原始网络具有用于编码器网络和解码器网络的 8 层。然而,在我们上面的网络中,每个解码器和编码器只有 5 层。
鉴别器网络架构(全网络)
黄线→如上所述,鉴别器网络本身并不难实现。它只是背对背连接的卷积层,(我们也可以称这个网络为全卷积网络。)在 Tensorflow 中实现上述架构时,它看起来会像下面这样。
相同的卷积层,我们用于编码器部分,但与泄漏 ReLU()激活函数。
结果
左图像 →输入图像分割蒙版
中间图像 →地面真实图像,原始图像是什么样子
右图像 →网络生成图像
一些图像看起来不错,当然不是很令人印象深刻,但我仍然能够说出网络中呈现的是什么对象。然而,该网络在其他图像上表现不佳。
如右图所示,我们可以看到图像的很大一部分没有被填充,只是灰色的方块。这当然不是一个好消息。最后让我们看看生成的 GIF 格式的图像。
交互代码
对于 Google Colab,您需要一个 Google 帐户来查看代码,而且您不能在 Google Colab 中运行只读脚本,因此请在您的操场上创建一个副本。最后,我永远不会请求允许访问你在 Google Drive 上的文件,仅供参考。编码快乐!
要访问自动微分的代码,请点击此处。
遗言
对于 Pix2Pix Gan 来说,这是一个很好的实践,下次我将在编码器部分添加更多的层,希望能够生成更清晰的图像。
如果发现任何错误,请发电子邮件到 jae.duk.seo@gmail.com 给我,如果你想看我所有写作的列表,请在这里查看我的网站。
同时,在我的推特这里关注我,并访问我的网站,或我的 Youtube 频道了解更多内容。如果你感兴趣的话,我还做了解耦神经网络的比较。
参考
- tf.nn.leaky_relu | TensorFlow。(2018).张量流。检索于 2018 年 4 月 29 日,来自https://www.tensorflow.org/api_docs/python/tf/nn/leaky_relu
- tf.exp |张量流。(2018).张量流。检索于 2018 年 4 月 29 日,来自 https://www.tensorflow.org/api_docs/python/tf/exp
- 乙状结肠的导数。(2018).Ai.mit.edu。检索于 2018 年 4 月 29 日,来自http://www . ai . MIT . edu/courses/6.892/lecture 8-html/SLD 015 . htm
- affini layer/pix 2 pix-tensor flow。(2018).GitHub。检索于 2018 年 4 月 29 日,来自https://github . com/affini layer/pix 2 pix-tensor flow/blob/master/pix 2 pix . py
- phillipi/pix2pix。(2018).GitHub。检索于 2018 年 4 月 29 日,来自https://github.com/phillipi/pix2pix
- 医学图像分割[第 1 部分] — UNet:交互式编码卷积网络。(2018).走向数据科学。检索于 2018 年 5 月 1 日,来自https://towards data science . com/medical-image-segmentation-part-1-unet-convolutionary-networks-with-interactive-code-70f 0 f 17 f 46 c 6
- 设计,R. (2018)。显著对象分割的秘密。Cbi.gatech.edu。于 2018 年 5 月 1 日检索,来自http://cbi.gatech.edu/salobj/
从神经网络生成受口袋妖怪启发的音乐
原文:https://towardsdatascience.com/generating-pokemon-inspired-music-from-neural-networks-bc240014132?source=collection_archive---------2-----------------------
Cory Nguyen、Ryan Hoff、Sam Malcolm、Won Lee、Abraham Khan 的项目
机器学习技术能创造出好到足以愚弄人类的音乐吗?
一.摘要
最近,生成神经网络已经登上了艺术追求的舞台,如图像生成和照片修饰。这些深度学习网络开始留下印记的另一个领域是音乐生成。在这个项目中,我们的目标是探索使用 LSTM 和甘神经网络来生成音乐,就好像它是人为的。
通过将 MIDI 文件中的音符和和弦视为离散的顺序数据,我们能够训练这两个模型,并使用它们来生成全新的 MIDI 文件。我们成功地创造了真正的音乐吗?请继续收听我们的结果!
二。项目大纲
这个项目很大程度上是由两个独立的媒体职位启发和通知的。sigur ur skúLi 关于使用 LSTM 生成音乐的帖子帮助我们清楚地理解了使用音乐作为数据的机制和需要注意的问题。例如,单个乐器轨道是一个很好的起点,因为它们远没有那么复杂。钢琴音乐被特别提到,因为它有清晰、明确的音符,可以来自很宽的音域。此外,Alexander Osipenko 关于使用 GAN 生成音乐的帖子展示了一种替代方法,并向我们介绍了由于输入数据的顺序性而使用 RNN-GAN 的策略。
借鉴这两者,我们选择创建两个独立的神经网络架构:长短期记忆(LSTM)和递归生成对抗网络(RNN-甘),我们在大约五个*时的 MIDI 文件形式的口袋妖怪视频游戏背景音乐上对其进行了训练。音符被转换成一个数字标度,并被标准化以输入到神经网络中。
经过多次实验,我们能够创作出与实际的口袋妖怪音乐相混淆的短歌曲。下面将更详细地讨论模型和参数,以及在时间和输出方面的性能比较。
三。数据收集和处理
如上所述,我们想要一个相对简单的钢琴音乐语料库来训练和学习。使这个项目在我们的时间框架内更加可行的其他标准包括寻找在类型和模式上同质的曲目,以及避免停顿的曲目。这仅仅是因为我们不知道模型在学习模式时如何处理无笔记空间。一组 307 首口袋妖怪歌曲(仅钢琴版)选自这个 MIDI 文件的在线收藏。该语料库仅包含几代口袋妖怪游戏的背景音乐(意味着没有停顿),每首曲目长度约为一分钟。这里可以看到一个音轨示例:
我们使用 Music21 从 MIDI 文件中提取相关信息,该软件也在 Skúli 的文章中介绍过。Music21 允许我们将每个音轨的音符和和弦(音符组)读入 Python,同时保持它们的顺序。每个音符都表示为其特定的音符类型或相应的数字。然后,这些音符被转换为 0:1 比例(对于 LSTM 输入)或-1:1 比例(对于 GAN 输入)。
Function to prepare sequences for GAN input
来自每个音轨的信息被合并成一个列表,然后被分成 100 个音符的片段。当然,音乐比音符本身更复杂。我们原本打算使用 MIDO 包提取其他数据特征,如时间和后效。然而,这增加了复杂性,使得训练模型明显需要更多的资源,因此在我们的时间框架内是不可行的。
四。学问
T 我们在 Music21 包的输出中认识到的第一个特征是,它可以被视为文本数据,每个音符被解释为一个“单词”基于我们对自然语言处理的先验知识,我们认为 LSTM 网络可以有效地对笔记随时间变化的模式进行建模。这种直觉得到了 Skúli 帖子的肯定。此外,他的帖子向我们介绍了 Keras,这是一个深度学习库,可以使用 CPU 或 GPU 通过 Tensorflow 后端运行。由于其计算速度和相对易用性,Keras 库最终成为我们两个音乐生成模型的主干。
长短期记忆
LSTMs 有几个关键特性,使它们非常适合处理本项目中使用的歌曲。LSTM 是一种递归神经网络,它按时间顺序而不是按空间顺序处理信息。这个模型架构随着时间的推移共享特征权重,这允许它输出某种程度上一致的模式。此外,在这种情况下,长时间记忆和重复使用输入的能力,复制一种长期记忆,是非常有用的。因此,LSTM 让我们在一首歌曲中保持相对的一致性,并牢记一个“主题”。
LSTM “pipeline”
来源:【http://colah.github.io/posts/2015-08-Understanding-LSTMs/】
与其他缺乏长期记忆的 rnn 不同,LSTM 就像一条管道,可以在很长的时间间隔内传输信息。它通过一个平行于网络的“管道”从过去收集信息,并使用门控机制来选择进出每一步的信息。这种机制源自乘以网络元素的 sigmoid 变换,执行三项任务来控制信息流:输入、遗忘和输出。它决定了新状态的哪些方面与新的输入相关,以前状态的哪些方面需要被忘记,以及状态的哪个部分被继续。这些机制允许 LSTM 使用复杂但自适应的参数来开发音符序列,模拟人们可能从歌曲中听到的模式。
下面是我们自己的模型中各层的分解及其目的。
第一层 CuDNNLSTM 是一个 LSTM 层,它使用 NVIDIA 的 Cuda 工具包来单独运行 GPU,使其在许多情况下比常规 LSTM 更快。这一层是我们的模型学习如何预测特定序列中的音符的关键。
丢弃层是一种正则化技术,它通过在每次迭代中随机删除一部分神经元来防止过拟合。这迫使模型通过在剩余的神经元之间分割所学的概念来概括它们。这对于音乐生成至关重要,因为过拟合将导致输出听起来与一首或多首原始歌曲几乎相同。
双向 LSTM 层通过使用过去和未来的信息将当前的音符联系起来。该层并行训练两个 LSTMs,其中一个以相反的顺序读取输入。为了真正理解为什么特定的和弦在特定的地点和时间被使用,我们需要通过回顾特定和弦之前和之后的内容来了解它。双向层模仿这种方法,从排序中学习并拼凑所需的音符。
密集层在神经网络中很常见。它们包含一层神经元,所有节点都从输入连接到输出。每个神经元计算其输入的加权和,并添加一个偏置向量。然而,根据激活功能,它可能被激活,也可能不被激活。该函数定义给定输入的节点的输出,并将结果映射到 0 和 1 之间的值。我们选择使用 Softmax 激活函数来完成这一任务,并将每个输出除以一个因子,使其总和为 1。然后,该模型可以生成一个概率分布,允许在其输出中包含多个类别。根据这些概率,我们可以在生成步骤中进行预测,这将在后面的“音乐生成”中详细介绍
生成对抗网络
除了 LSTM 模型之外,我们还想构建一个 GAN,它能够完成同样的任务,即从经过音乐转换的输入中生成音乐。通过使用相同的输入,我们可以比较和对比输出的 MIDI 文件,找出一个模型优于另一个模型的地方。
在 GAN 网络中,鉴别器模型和生成器模型被同时训练和测试。鉴别器收到的是真实数据——在我们的例子中,是真实的歌曲——以及随机噪音产生的虚假数据。对于每个样本,鉴别器的任务是正确地将数据分类为真或假。另一方面,生成器的任务是从随机噪声中生成假数据,这些假数据能够欺骗鉴别器犯更多的分类错误(即,将真正的歌曲称为“假的”,反之亦然)。通过堆叠这两个模型,鉴别器模型和生成器模型开始相互竞争,在我们的例子中,期望的最终结果是生成器可以轻松地欺骗鉴别器(希望是人)。
Artistic representation of a GAN model
蒙特利尔大学的 Ian Goodfellow 是关于 GAN 的原始论文的作者,他将 GAN 比作一群试图欺骗侦探(代表鉴别器模型)的绘画伪造者(代表发电机模型)。
已经有一些利用 GAN 制作音乐的作品,如 MuseGAN 和 C-RNN-GAN 。对于我们的项目,我们决定将我们的 GAN 基于 C-RNN-GAN,但使用 Keras 实现它,以进一步开发我们新获得的库经验。
我们的输入数据几乎与用于训练 LSTM 网络的数据相同。然而,我们决定将输入规范化在-1 和 1 之间,而不是从 0 到 1。这是为了让我们的发电机网络变得更容易,该网络被馈送来自标准正态分布的随机噪声,期望它将产生范围在-1 和 1 之间的输出。
现在,为了实际构建 GAN,我们从鉴频器网络开始:
在这个模型中,前两层是 LSTM 层。这允许鉴别器在训练期间从我们的音乐输入中学习序列数据。如果没有这些层,我们发现只要生成器能够计算出输入数据的离散域,鉴别器就无法区分真实音乐和虚假音乐。有了 LSTM,生成器现在要做的不仅仅是简单地计算真实数据的范围;它还需要明白音乐遵循一定的模式。最后,我们选择了 sigmoid 激活函数,因为我们希望输出为单个 0 或 1,分别代表伪数据或真实数据。
接下来,发电机网络:
为此,我们可以看到生成器网络只是一个多层感知器,它接收等于潜在*度大*的随机输入(我们使用 1000,因为与 100 相比,它可以以最*的速度更好地学习)。有了这两个网络,我们就可以开始训练了:
为了训练这个堆叠模型,我们首先给生成器一批来自标准正态分布的随机噪声,并让它处理这些噪声,以生成一批编码为数字的 100 个音符的序列。然后将这些数据作为一组假数据传递给鉴别器,鉴别器将经历一次训练迭代。然后,生成器生成另一组假数据,并将其作为假数据传递给堆叠模型,以训练鉴别器和生成器。
音乐生成
训练完这两个模型后,我们想生成新的 MIDI 文件。对于这两个模型,我们希望使用该模型根据输入进行预测,并创建对应于音符和和弦序列的编码输出。对于 LSTM 网络,我们从语料库中随机抽取 100 个音符序列,并将其输入到网络中,让它做出预测,这就是我们的编码输出。对于 GAN 网络,我们向生成器提供一个从标准正态分布中采样的随机数字序列,并让它进行预测。有了这些预测,我们可以使用 Music21 将我们预测的序列变成全新的 MIDI 文件。
动词 (verb 的缩写)结果和见解
我们所创造的样本包括在下面。首先,从 LSTM 模式来看:
接下来,从 GAN 模型来看:
损失与培训
我们使用交叉熵损失函数,因为它们适用于我们的两个模型:LSTM 使用分类交叉熵来选择接下来出现概率最高的音符,而 GAN 使用二项式交叉熵来选择将序列分类为真实或虚假的较高概率。
从这些损失图中值得注意的是,模型能够在运行时间(在 Google Colab 的 GPU 运行时间上不到 12 *时)和纪元方面相对快速地进行训练。我们可以将此归因于我们数据的*尺寸和我们对多个 LSTM 层的使用。就表现而言,LSTM 的表现符合预期,损失逐渐减少,直到收敛到渐近线。为了避免过度拟合,我们在训练模型时*心翼翼,不要超过它开始收敛的地方。
对于 GAN,初始损耗与预期一致:发生器损耗高,鉴频器损耗低。我们预计这些值会在某个点上收敛——发生器下降到起点以下,而鉴频器上升到起点以上。有趣的是,在大约 2000 个时期之后,发生器和鉴别器开始朝着它们的初始起点分叉,这表明它们可以被训练更长时间(尽管对于 5000、10000 和 100000 个时期来说情况并非如此)。这种不一致的一个可能的解释可能是由于数据的*规模或由于同时训练两个模型。
我们试图颠覆这种快速收敛的方法之一是使用随机离散噪声预先训练鉴别器。通过 10000 个历元的预训练,我们发现生成器需要超过 50000 个历元才能开始与鉴别器竞争:
(in thousands of Epochs)
当比较两种模型的输出时,我们发现 GAN 在输出 MIDIs 的真实性和训练时间方面更胜一筹。LSTM 模型倾向于在开始每首歌曲时,在调整之前重复几秒钟同一个音符。我们推断网络还没有被训练到足以有效地学习音乐中的所有模式,即使模型的损失开始渐近。然而与此同时,虽然我们可以减少缺失层并允许过度拟合,但我们希望避免创建一个模型,该模型可以有效地从我们用于预测的 100 个音符中填充预先存在的歌曲的剩余部分。使用 GAN 模型时,我们不必担心过度拟合,也不再有“卡住”音符。
LSTM is able to find a long pattern and repeat it. GAN only plays notes from high-to-low and back.
LSTM 胜过 GAN 的地方在于对某些模式的执着。我们发现 LSTM 能够更好地专注于特定的模式,并在一首歌的整个过程中重复利用它们。该模型还能够跳出某些音符循环,并过渡到另一组音符循环。就甘而言,它只能掌握基本概念,如以由低到高的方式提升音符,而不会陷入更微妙的模式。
不及物动词结论
未来的工作
我们当前的音乐生成过程可以通过使用编码器-解码器框架来改进。这使我们能够将其他乐器演奏的音乐转换成模型的标准输入。也可以通过允许输入包含 MIDI 文件中包含的其他信息来改进输入,如力度、偏移和暂停。
处理停顿的一个初步方法是用超出人类正常听觉范围的音符替换停顿。这就为 Music21 的翻译提供了一个不可忽略的音符。就我们的模特而言,我们希望扩大我们用于训练的音乐的语料库,以便模特将接触到更多种类的音乐。我们想看看这些歌曲是否有什么总体模式,以及我们的网络是否能捕捉到它们。在对 GAN 的具体改进方面,我们希望对生成器模型实施 RNN 架构,因为我们相信这将有助于网络更好地组织音乐模式。然后,它也可以使用以前的输出作为附加输入。
应用程序
考虑到可以在过程中实现一定程度的复杂性和控制,使用深度学习网络来生成音乐的用例是无限的。例如,我们的模型可以提供一种方式来创建独特的、免版税的股票音乐,这种音乐来源于他们所接受的任何音乐。
除了我们的方法,机器可以被训练来检测尚未自动化的音乐的潜在模式。一旦这些模式可以被检测到,机器学习就可以用来在声波水平上编译和分析音乐。这可以与类似于热门歌曲科学的技术结合使用,使用定量和定性摘要来预测音乐,而不必听单个曲目。最后,虽然使用机器创造艺术可能会导致“错误”,但这些不准确性可能会意外地导致未被发现的音乐模式,这些模式可能会形成下一个流行的声音。
外卖食品
总的来说,我们觉得我们在音乐生成方面的实验是成功的。通过这个过程,我们能够获得关于深度学习的 Keras 库的实践经验,事实证明它像宣传的那样对用户友好。就模型架构而言,我们能够了解并实现双向层,并看到它对于从序列数据中学习的价值。
剧透警告:在样本内预测精度和输出一致性方面,双向 LSTM 的表现比 LSTM 好得多
我们还对多层感知器的能力感到惊讶,因为我们基于 MLP 的使用连续输入的生成器网络能够在短时间内与我们基于 RNN 的基于离散数据训练的鉴别器网络竞争。这继续证明了 MLPs 非凡的多功能性。
最后,这个项目给了我们尝试强化学习的机会。对我们来说,这种方法代表了监督学习和非监督学习之间的一个很好的中间地带。与以前不同的是,我们现在可以获得生成器 AI 的帮助,在不需要目标变量的情况下将模型引向“正确的结果”。我们很高兴看到这种类型的机器学习将带来的新进展。
我们这个项目的代码可以在 Github 上找到!
参考
sigur ur skúLi 的博文—https://towards data science . com/how-to-generate-music-using-a-lstm-neural-network-in-keras-68786834 d4c 5
布莱恩·麦克马洪的人工智能点唱机—https://medium . com/@ cipher 813/AI-Jukebox-creating-music-with-neural-networks-1d 9585 C4 d 649
丹*尔·约翰逊用 RNNs 作曲的页面—http://www . hexad RIA . com/2015/08/03/composing-Music-with-recurrent-neural-networks/
斯坦福大学关于深度学习网络音乐生成的论文—https://web.stanford.edu/class/cs224n/reports/2762076.pdf
中-甘纸业—https://arxiv.org/pdf/1611.09904.pdf
更多关于 GANs 的阅读,请点击以下链接:
甘斯简介—https://skymind.ai/wiki/generative-adversarial-network-gan
关于 GANs 的 PyTorch 简短教程—https://medium . com/@ devnag/generative-adversarial-networks-GANs-in-50-lines-of-code-py torch-e81b 79659 e3f
喀拉斯甘图书馆—https://github.com/eriklindernoren/Keras-GAN
甘动物园—【https://deephunt.in/the-gan-zoo-79597dc8c347】
训练 gan 的有用提示—https://medium . com/@ utk . is . here/keep-calm-and-train-a-gan-train-trains-and-tips-on-Training-generative-adversarial-networks-edd 529764 aa 9
用*猫生成产品使用数据
原文:https://towardsdatascience.com/generating-product-usage-data-from-scratch-with-pandas-319487590c6d?source=collection_archive---------3-----------------------
我们如何近似高级用户行为?
Source: Pixabay
洞察我们产品的行为使用是至关重要的,因为它不仅表明我们如何获得用户,而且还能留住他们。这是一种确定问题答案的方法,有多少用户真正在使用我们的产品?它通常被称为重要指标(OMTM),帮助我们抵制使用虚荣指标来量化业务增长的诱惑。更多关于 OMTM 和产品成长的在这里和在这里。
虽然我通常更喜欢探索现有的数据集,但这次我采用了一种不同的方法,试图从头开始逼近一个真实的数据集。
有两个主要原因:
- 对行为数据的更深入理解。正如从头开始编写一个算法来理解它的运动部分是有价值的一样,我相信数据集也是如此。这是在回答的问题“我如何才能估算出产品的使用情况?”我们的行为模型中肯定会有一些简化但必要的假设。
- 探索*猫,了解如何更好地建立数据模型,因为有效的数据操作可以大大加快数据科学工作流程以更深入地了解您想要探索的数据。
我们的目标是为 1000 个用户生成一个数据集,其中每个用户都存储有一个可能使用 20 个月的设备 uuid。正如我们将在后面看到的,模拟数据很好地收敛到预期值。我们添加了两个过程来更接近真实数据集:
- 定义用户群组(用户首次使用产品时)
- 定义用户流失(用户上次使用产品的时间)
这使我们能够更准确地表示我们可能在公司工作的数据集。
决赛成绩
我们希望最终数据集包括设备所有月份的活动数据:
- 数字(使用)特性:用户在那个月使用了多少特性(当用户不活跃时,我们删除条目)
- 分类特征:根据设备定义(如平台、国家)
为了简化模型,每个设备的数据仅针对使用特征而变化,而对于分类特征而言是静态的。
Preview of the final dataset
最终数据集看起来像是我们从两个表中查询我们业务的关系数据库(例如 MySQL、PostgreSQL)得到的东西,一个包含用户的表(包含分类特征),另一个包含所有事件(包含使用特征)。然后,我们将在 device_uuid(两个表中的主键)上连接两个表,并得出如下所示的结果。每个公司的数据基础设施明显不同,但这是我们可能达到这一点的方式之一。
本文将只关注生成数据,但稍后我们可以使用它来产生群组分析,例如,用户保留曲线,这在本文中没有涉及,但将在接下来的文章中探讨:
User retention plot based on the final data frame
我们什么时候会失去大部分用户?在上一个产品版本中,我们的入职流程的变化是否提高了员工保留率?我们不同细分用户的留存有区别吗?通过这种分析,我们可以回答不同类型的问题,从而更好地了解我们的用户如何使用产品。
你可以在这里找到本帖中使用的所有代码的笔记本。
1。定义主要参数
我们首先导入所有必要的依赖项,并定义上面提到的主要参数(1000 台设备,20 个月,从 2016 年 1 月开始)。
Importing the dependencies
2.生成设备 uuids 并将其与日期时间数据相结合
生成设备 uuid
Generating device uuids
An example oof two device uuids
设备 uuids 是用户使用的每个设备的唯一标识符。
生成日期时间
Generating datetime
输出:
(' 2016–01–01 00:00:00 ',' 2017–08–01 00:00:00 ')
我们可以看到,使用指定的参数(起始月,月数),我们将生成 2016 年 1 月到 2017 年 8 月的数据。
Adding datetime
Adding datetime data
我们得到一个包含两列的数据帧,device_uuid 和 date。有 1000 * 20 行(设备 uuids 数*周期数)。
3.生成使用特征
在我们的数据帧包括设备 uuid 和日期时间数据之后,我们接下来生成描述产品用途的特性。
我们要做的第一件事是定义:
- 我们希望生成的使用特征数量
- 用户使用每项功能的频率相对于其他功能的比率
虽然特性的数量是不言自明的,但是特性比率需要一些进一步的解释。
我们将特征的数量设置为 3,比率为 0.8,这意味着第一个特征将采用随机生成的数字并乘以 1(保持不变)。这就是比例的来源。第二个特征是第一个特征的 0.8 倍。第三个特征的使用是第二个特征的 0.8 倍。
这意味着如果第一个特性被使用 10 次,第二个特性被使用 8 次,第三个特性被使用 6 次。这只是一种简单的方法,可以避免所有的使用特性都被用在相同的程度上。在这种情况下,特征 1 对应于产品的核心特征。这当然是完全任意选择的。
这种调整产生了以类似方式一致使用的特性,就像真实产品一样。这里有一个很强的假设,即的使用是同质的,因此所有用户都以相同的比例使用特性,这对我们的使用来说已经足够了。
3.1。计算特征比率
然后我们应用上面定义的比率。
Calculate feature ratios
输出:
每个特征的比率:{ '特征 1': 1.0,'特征 2': 0.8,'特征 3': 0.6}
3。2.将群组分配给设备
现在,我们选择任意数量的群组,并将每个设备分配给特定群组。每个群组对应于用户开始使用产品的日期时间(在我们的例子中是月)。在我们的数据中,群组的数量等于所有月数的一半。在这种情况下,它是 20 / 2 = 10 个群组。1000 个用户意味着每个群组大约有 100 个用户。
Assigning cohort groups to devices
Cohort per device uuid
3.3.添加群组数据
首先,我们定义一个函数,将一系列数据帧连接成一个数据帧。我们将在获得一系列数据帧的输出时使用它,每个数据帧代表特定设备的数据:
Concatenate series of dataframes into one dataframe
然后,我们定义一个函数,并将指定的群组添加到主数据框架中:
Adding cohorts to the main dataframe
接下来,我们使用两个函数来添加群组:
Applying both functions to all devices
Adding cohort data
正如我们在上面第一个用户的例子中看到的,我们将他们的群组定义为 2016 年 4 月,因此他们是在那时开始使用产品的。我们删除了他们前 3 个月的数据来模拟这种情况。
An average number of months per device
输出:
15
因为我们给用户分配了群组,所以在这个过程中我们删除了相当多的行。我们可以看到,现在每个用户的平均使用时间从 20 个月下降到了 15 个月。
3.4.生成使用数据
这里我们为功能 1 的使用生成一个随机数(0 到 14)。然后,我们根据为功能 1 生成的数量,使用功能比率来计算功能 2 和功能 3 的使用率。
Generating usage data
Generating usage data
3.5.产生流失行为
虽然我们通过分配群组定义了使用时间段的下限,但我们将使用流失率定义上限。当用户停止使用产品时,就会发生流失。
一般来说,我们有两个简化原则,在此基础上,我们决定用户如何使用产品:
- 搅拌器仍是搅拌器(一个月不使用后,用户不再使用该产品)
- 50%的用户在第一个月流失(大约 50%的用户有 1 个月的数据,50%有更多,因此使用时间更长)
第一个是为了简化模拟,第二个是为了更准确地模拟现实生活中的数据,因为大多数用户通常在尝试产品后就再也不会回来了。
我们定义了模拟流失的函数:
Simulating churn
我们将它应用于我们的数据框架:
Applying the simulating _churn function to all devices
我们有与上一个相同的数据帧结构。现在唯一的区别是,我们删除了模拟用户流失的额外行
An average number of months per device
输出:
5
我们可以看到,我们现在有大约 25%的月份是最初为每个用户生成的(5 / 20)。
4.生成分类特征
在使用特征之后,我们将定义一些分类特征来丰富我们的数据集。然后,我们将能够根据用户的平台、国家或他们是否注册来细分用户,并尝试找到一些模式。
注册用户和未注册用户使用产品的方式有所不同吗(如果有,如何使用)?特定国家的用户呢?我们的大部分超级用户位于哪里,他们有什么共同点?
像这样的洞察力的有益影响可以帮助我们的营销努力瞄准对我们的业务最有利可图的用户(最高 LTV)。更多关于那个这里。
Defining categorical features
输出:
{ '国家':['NL ',' AU ',' FR'],'平台':['iOS ',' Android'],' user_registered':[False,True]}
4.1.生成分类特征权重
为与单个用户相关联的分类特征出现的可能性定义权重。
Defining weights for categorical features
如果分类变量中有两个可能的变量(例如“Android”和“iOS”),那么我们预计生成的数据将包含第一个变量的 70%和第二个变量的 30%。
如果分类变量中有三个可能的变量(例如“NL”、“AU”、“FR”),那么我们期望生成的数据包含第一个变量的 60%、第二个变量的 30%和第三个变量的 10%。
4.2.应用分类特征权重
我们创建一个函数来根据定义的参数产生分类特征。
Generating categorical features
接下来,我们应用函数:
Applying the generation of categorical features to all devices
Applying categorical feature weights
每个设备都有自己对应的国家、平台以及是否注册。
5.将所有特征合并到最终数据帧中
我们现在有两个数据帧,一个包含日期时间数据和使用特性,另一个包含分类特性。接下来,我们将它们合并成最终的数据帧。
Merging categorical and usage features
然后,我们将该功能应用于所有设备:
Merging all features
我们可以看到第一台设备(da5e 3464-d356–4572-b962-f2b 57e 730732)于 2016 年 5 月开始使用该产品,使用了三个月,然后被搅动。他们来自荷兰,使用 Android 手机,还没有注册该产品。
6.检查最终数据帧中的模拟输出
我们可以检查我们设置的参数是否也体现在最终的数据帧中。
我们是否生成了我们想要的数据?为什么我们能够做到这一点?因为大数定律:从大量试验中得到的结果的平均值应该接近期望值,并且随着更多试验的进行,将趋向于变得更接近)。更多关于大数定律这里。
6.1.检查使用功能模拟
每项功能的平均使用情况:
Checking simulating of usage features
注册用户和未注册用户的平均值大致相同。
然后我们检查使用特性的比例(每个特性是前一个特性的 80%)。
Checking proportion feature 1 / feature 2
输出:
功能 1 /功能 2: 79%(预期值为 80%)
Checking proportion feature 2/ feature 3
输出:
功能 2 /功能 3: 75%(预期值为 80%)
正如我们在上面的输出中看到的,比例很好地收敛到了期望值。如果我们增加设备的数量,数字会更接近。
6.2.检查分类特征模拟
我们用两个可能的变量来检查分类特征的比例。我们已经将具有 2 个可能变量的特征的权重设置为[0.7,0.3]并将 user_registered 设置为[False,True],因此它具有 2 个可能变量。
检查注册用户:
Checking the proportion for user_registered
输出:
32%的用户注册(预期值为 30%)
检查国家:
我们用三种可能的变量来检查分类特征的比例。
Plotting proportion of rows per country
Checking the simulation of the country feature
我们可以在上面的图表中看到每个国家所有事件的百分比。比例接近定义的参数([0.6,0.3,0.1])
6.3.检查流失模拟
第一个月有多少流失用户,有多少继续使用产品更长时间?
输出:
m1 搅拌器数量/非 m1 搅拌器数量:489 / 455
输出:
48%的用户在第一个月流失(预期值为 50%)
正如预期的那样,大约 50%的用户在第一个月的使用中流失,另外 50%的用户使用产品的时间更长。
7.后续步骤
接下来要做的是进一步处理最终的数据框架,以便更清楚地了解产品中用户的行为模式。我们可以制作可视化图,如上面的保留曲线来回答一些最关键的业务问题:我们在发展业务方面有多成功?
利用机器学习生成鞋子设计
原文:https://towardsdatascience.com/generating-shoe-designs-with-deep-learning-5dde432a23b8?source=collection_archive---------13-----------------------
鞋子。 等什么?我以为这是关于机器学习的!是的。如果你去亚马逊,你会找到多少双鞋?可能很多吧?但是它们的种类多吗?至少就运动鞋而言,很多看起来都很相似。是时候来点新鲜的设计了。我们需要 进化——如果我们可以用机器生成我们自己的鞋子设计会怎么样…
These shoes were generated by a neural network.
数据。大型零售商有大量的鞋子出售——Zappos 和亚马逊都在他们的网站上有成千上万的鞋子照片。所以我从网上搜集了这些照片,并把它们储存在我的电脑上,主要是针对亚马逊上出售的耐克跑鞋。我写了一些代码来抓取这些图像。幸运的是,它们已经被裁剪为 224 像素乘 224 像素(这是将它们输入模型所需的大*)。但是什么样的机器学习架构是生成东西而不是寻找模式呢?你问题的答案很吸引人…
生成性对抗网络。深度学习领域相对较新的创新是生成对抗网络(GAN)。GANs 使用两个不同的网络,一个生成它认为是鞋的图像(这被称为生成器),另一个试图从数据集中区分假鞋和真鞋(这被称为鉴别器)。你可以把它想象成这些网络之间的冷战,只不过它们试图智胜对方,而不是在武器上胜过对方。一旦鉴别器基本分辨不出生成图像和真实图像的区别,模型就已经收敛了。
A Generative Adversarial Network.
深度学习模型。我创建的神经网络在很大程度上基于 Siraj Raval 的口袋妖怪 GAN 项目,他用 GAN 生成了新的口袋妖怪。我修改了代码以处理我的鞋子数据,并在亚马逊网络服务的 GPU 上训练了 500 个时代的模型。结果很酷…
Check out these fresh kicks!
结果。我让模型输出它在每个时期生成的图像,以查看它在整个训练过程中的进展。它最初主要是噪声,随机的彩色像素充满了屏幕,但逐渐形成了鞋子的形状,并获得了不同的颜色,以更好地类似鞋子。我发现有趣的是,一些鞋子有耐克标志,这可能反映了数据集中的大多数训练图像是耐克跑鞋。
那么这意味着什么呢?这个项目展示了机器学习除了在一堆数据中寻找模式之外还可以如何使用。它生成新图像的能力为大型行业(如时装、制药等)的应用提供了机会。).通过一些改进和更多的训练,这些模型可以非常强大,也许能够为现实世界的应用创造鞋的设计;时尚公司也许可以用 GANs 来创造出很酷的新潮设计。
未来时装设计师的工作可能会被机器抢走……
你可以在我的 GitHub 库这里找到我的代码。
一些有趣的附加资源:
- Siraj Raval 的口袋妖怪 GAN 视频
- 原甘论文
用 LSTM 网络生成新加坡英语文本消息
原文:https://towardsdatascience.com/generating-singlish-text-messages-with-a-lstm-network-7d0fdc4593b6?source=collection_archive---------16-----------------------
在 Medium 上发表了我的第一篇文章后,我意识到从构思一个想法到分享我的发现和学习经验的整个过程是多么令人愉快。我意识到大多数与数据相关的项目和解决方案都源于这两件事——1)我们试图解决的问题 2)我们拥有的数据带来的机遇。由于我之前的帖子是关于解决社交媒体竞赛中手工工作的问题,我想这次我应该先寻找数据。
谷歌数据集搜索
谷歌最近发布了谷歌数据集搜索,这是一个数据集的谷歌学术,这对我的起步很有帮助。我偶然发现了一个非常有趣的数据集,来自我的学校,新加坡国立大学短信语料库。这是一个超过 50,000 条新加坡英语短信的语料库,它是计算机科学系的研究工作的一部分。这些信息主要来自这项研究的志愿者,他们是在大学就读的新加坡人。
理解我们语言的机会
我认为这是一个非常好的机会来学习这些课文的语言,特别是因为我自己是新加坡国立大学的学生,我一直用新加坡英语说话和发短信。对于门外汉来说,新加坡式英语似乎是一种蹩脚的英语,甚至是一种非常粗俗的俚语。尽管看起来缺乏连贯性和语义,但它在新加坡实际上非常普遍。事实上,它经常可以用来立即与新加坡人建立联系和信任。
You can come from all walks of life and despite your race and mother tongue, as long as you’re Singaporean, you will totally get this.
当一个单词可以改变整个信息的意思时,新加坡式英语也很难理解,这也是为什么它是一种非常有效的语言的原因之一。
The nuances of Singlish.
短信里的新加坡式英语是另一个层面。除了缺少完整的句子之外,短信和网络语言进一步缩短了句子。
虽然我不是语言学专家,但我认为通过在语料库上训练神经网络来生成类似的文本信息可能有助于理解这一点。我想理解并演示为我们的文本生成选择模型的最终表示的原因。
如果不想理解 NNs、RNNs 和 LSTMs,请向下滚动到 Code。
前馈神经网络
人工神经网络模拟我们的大脑,并用节点表示神经元。该网络具有接收信息的输入层、处理信息(操作、计算、特征提取)的隐藏层以及基于通常用于进行预测的信息产生期望输出的最终输出层。
A simplistic representation of a neural net.
预测输出和实际输出可能会有很大差异,这可以通过我们希望最*化的成本函数来衡量。
- 神经网络就像一个婴儿,他想学习如何正确地说话(模型输出 Yhat)
- 通过做一套特定的动作,比如说说,…,喊随机的东西(X_1 到 X_n),
- 一些比另一些更频繁(W_1 到 W_n)。
- 他试图通过在脑海中反复尝试不同的行动场景来说出什么是正确的(更新权重)。
- 他在那个时间点选择的最后一组行动尽可能接近他父母告诉他的是正确的(最*化成本函数 C)。
这就是为什么它是一种监督学习的形式。他头脑中的这种更新/理解过程也被称为反向传播。
前馈神经网络是设计的第一种也是最简单的人工神经网络,它只允许信号从输入传输到输出。它没有时间因素。当谈到文本生成时,我们试图预测给定单词序列的下一个单词,我们需要一个代表记忆的模型。
递归神经网络
RNN is a type of ANN that has a recurring connection to itself.
这种循环连接有助于 RNN 学习先前输入 X_t-1(向量)以及当前输入 X_t(向量)的效果,同时预测时间 Yhat_t 时的输出。这给了 RNN 时间感。这可以让宝宝从过去被责骂的场景中学习,避免犯同样的错误。
让我们想象一个多层香草 RNN
Recurrent Neural Network with L layers. In each layer, the input (a vector) is unrolled into t different states.
Activation function in each state
状态(蓝色)的每个输出(h)是前一状态(h_t-1)的输出和当前输入向量(X_t)的激活函数。第一层的这些输出 h_1 到 h_t 然后将作为输入馈送到下一层,因为它深入到 RNN 中。
这将允许我们根据句子的上下文来预测下一个单词。
Based on the context of the sentence, we can find the right word “meh” to use after “can”.
然而,当句子所需的上下文变得非常大时,记住诸如“so”之类的单词可能就不那么重要了。不幸的是,随着这种差距的增长,传统的 rnn 变得无法学习连接信息,因为它无法忽略或忘记所有不必要的信息。
长短期记忆(LSTM)
LSTM 模型能够表示接受信息(输入门),给出预测值(输出门),遗漏不重要信息(遗忘门)的行为。LSTM 在文本生成等序列建模任务中非常流行。与前面的 RNN 图类似,LSTM 网络将使用 LSTM 单元代替节点。
让我们设想一个由 LSTM 单元态组成的单层
t LSTM cells (blue) in a single layer with num_units of cell units (yellow is 1 cell unit). Each cell unit has 1 Cell State Belt and 3 Gates.
LSTM 结构和香草 RNN 结构在外表上非常相似,但主要区别是在单个细胞内。这将有助于我们及时模拟不同的状态,在这些状态下,我们能够输入、输出和忘记信息。
The Cell State Belt allows information to flow from one state to the other.
每个门都有一个 sigmoid 函数,它将返回 0–1 的输出,表示通过门的信息比例。每个门将具有权重函数 W 和 U 以及偏置项 b。
𝞂 (WXt + Uht-1 + b) = [0,1]
The Forget Gate (in purple) allows the current state to only retain a proportion of information from the previous state.
The Input Gate (in green) allows us to decide the proportion of information that should be updated in the current state.
Having both the Forget Gate and Input Gate allows us to both retain past information and update current information in this state.
The Output Gate (in red) allows us to decide how much information in the state should finally “release”, giving us the output h_t for that state.
有了对 LSTMs 的一些了解,我们最终可以探索语料库并建立我们的模型。
密码
我将使用 Python 3.6 和 Keras 来完成这项任务。首先,我们将解析数据并标记每个文本。
Number of Users: 343
Number of Texts: 55835
Sequence Length: 5
创造词汇
仅取前 1000 条消息后,文本的模态长度为 5,我们将使用它作为序列长度。基本上我们会用一个句子中过去的 4 个单词来预测下一个单词。
['just', 'now', 'i', 'heard', 'thunder', 'but', 'e', 'sky', 'still', 'looks', 'ok', 'hee', 'if', 'really', 'rain', 'den', 'i', 'no', 'need', 'to', 'run', 'liao', 'i', 'also', 'lazy', 'but', 'no', 'choice', 'have', 'to', 'force', 'myself', 'to', 'run']
上面是一个标记化文本消息的例子。我的模型的缺点是我排除了标点符号,但它也可以以其他方式建模。
We can get the vocabulary of all the texts (unique words).
Vocab Size: 1490
Total words 10419
Vocab / Total words ratio: 0.143
Next we must encode the words with numbers so that they can be fed into the neural network.
用数字表示单词
tokenizer.word_index
返回一个将单词映射到索引的字典,而tokenizer.index_word
返回相反的结果。每个单词都用一个索引进行编码,这个索引实际上是在各自的独热向量数组中启动的位置。
这有助于神经网络理解现在由一个热点向量表示的词汇。然而,这导致一个非常大且稀疏的矩阵,其当前占据了相当于 5×6 个单元的空间,但是当词汇表的大*增加时,它会增长很多。
我们可以使用单词嵌入层将表示映射到指定数量的*度中。实践中推荐的大*(我在网上找到的)是 vocab_size**0.25,但是在下面的例子中,我将使用嵌入大* 3。
Size is reduced when word embeddings are used. The similarity between words will also be represented based on the distance in the vector space.
模型架构
我们可以用一个简单的架构和一个顺序模型—
- 嵌入层
- 双向 LSTM 层(学习一个句子的前一个和后一个上下文,这里不赘述)
- 脱落层(防止过度拟合)
- 将输出大*映射回 vocab_size 的密集层
- 使用 Softmax 在词汇表中找到最有可能使用的类别(单词)的激活
准备培训数据
随着我们的模型建立和文本编码,下一步是准备序列数据进行训练。
这种多词对多词的上下文帮助我们训练模型,告诉他们哪个单词序列(我们的预测器 X)导致最终的单词(我们的标签 Y)。
Using the green words as X and red word as Y
最后,我们将编译并拟合我们的模型,使用—
- Adam Optimizer(深度学习流行,易于配置)
- 稀疏分类交叉熵(多类分类的成本/损失函数,其中目标输出是整数索引而不是一位热编码)
- 每次精确度提高时,保存最佳权重的模型检查点
- 当验证准确率连续 4 次没有提高时,提前停止训练。
我们还将把所有对象保存在一个 Pickle 文件中,以便在生成文本时可以重新加载它们。
培训过程看起来会像这样
Epoch 39/100
loss: 4.2459 - sparse_categorical_accuracy: 0.2050 - val_loss: 6.4890 - val_sparse_categorical_accuracy: 0.0924
Epoch 00039: sparse_categorical_accuracy improved from 0.20413 to 0.20503, saving model to best_weights.hdf5Epoch 40/100
loss: 4.2390 - sparse_categorical_accuracy: 0.2051 - val_loss: 6.4887 - val_sparse_categorical_accuracy: 0.0935
Epoch 00040: sparse_categorical_accuracy improved from 0.20503 to 0.20513, saving model to best_weights.hdf5
最后,我们可以创建一个 generate_text 函数,它接受一个种子句子“i will be ”,将其填充到正确的 sequence_length,并使用它来迭代预测下一个单词。
工作中的文本生成
这听起来确实像短信里的新加坡英语!该模型已经设法学习语法,即使拼写不完整,即使文本被迫具有 5 个单词的长度,它也是相当容易理解的。
现状核实
出于时间和金钱的考虑,我没有在整个语料库上对网络进行充分的训练。事实上,我只在 1000 条文本上使用它来测试整个流程。验证的准确性非常低,模型当然是过度拟合的。我也没有使用最佳网络结构进行测试,也没有调整任何参数。我也用了 https://www.floydhub.com,但是他们的 GPU 只有 2 个*时空闲。我目前正在等待我的 AWS 学生帐户得到验证,以便我可以在整个语料库上训练模型。然而,我的期末考试快到了,我不能再等了。
然而,这是一个非常有趣的问题,也是一次很好的学习经历。期待回来的时候多学习,多探索,多分享!
链接到项目的回购
请通过 LinkedIn 或 jasonyip184@gmail.com 与我在进一步讨论!
参考
[## 如何用 Keras 在 Python 中开发基于单词的神经语言模型
语言建模包括在已知单词序列的情况下,预测序列中的下一个单词。一个…
machinelearningmastery.com](https://machinelearningmastery.com/develop-word-based-neural-language-models-python-keras/) [## LSTM(长短期记忆)的嵌入层是什么?
回答(第 1 题,共 2 题):如果你考虑如何提供一个单词作为 LSTM 的输入,它基本上是一个网络/模型…
www.quora.com](https://www.quora.com/What-is-the-embedding-layer-in-LSTM-long-short-term-memory) [## 使用双向 LSTM 和 Doc2Vec 模型 1/3 生成文本
本文的目的是讨论文本生成,使用机器学习的方法,特别是…
medium.com](https://medium.com/@david.campion/text-generation-using-bidirectional-lstm-and-doc2vec-models-1-3-8979eb65cb3a) [## 深度学习精要:长短期记忆导论
引言序列预测问题由来已久。他们被认为是最难的…
www.analyticsvidhya.com](https://www.analyticsvidhya.com/blog/2017/12/fundamentals-of-deep-learning-introduction-to-lstm/) [## 深度学习-安,RNN,LSTM 网络
长短期记忆(LSTM)模型是一种有监督的深度神经网络,非常适合处理时间序列问题
vishnuviswanath.com](https://vishnuviswanath.com/ann_rnn_lstm.html)
使用递归神经网络生成文本
原文:https://towardsdatascience.com/generating-text-using-a-recurrent-neural-network-1c3bfee27a5e?source=collection_archive---------5-----------------------
Figure 1: person writing on paper by rawpixel on Unsplash
如何使用 Keras 创建亚瑟·柯南·道尔风格的文本
深度学习可以用于许多有趣的事情,但通常它可能会觉得只有最聪明的工程师才能创建这样的应用程序。但这根本不是真的。
通过 Keras 和其他高级深度学习库,每个人都可以创建和使用深度学习模型,无论他对理论和算法内部工作的理解如何。
在本文中,我们将看看如何使用递归神经网络来创建亚瑟·柯南·道尔爵士风格的新文本,使用他的书“夏洛克·福尔摩斯的冒险”作为我们的数据集。
我们可以从古腾堡网站获得数据。我们只需要将其保存为文本(。txt)文件并删除文本中嵌入的 Gutenberg 页眉和页脚。如果你不想自己做这些,你可以从我的 Github 获得本文的文本和所有代码。
递归神经网络
Figure 2: Unfold RNN by François Deloche
递归神经网络(RNN)是用于顺序数据的最先进的算法。这是因为它们可以通过内部记忆记住以前的输入。
在本文中,我不会深入探讨递归神经网络是如何工作的,但如果你感兴趣,你可以查看我的视频解释 RNN 是如何工作的,或者你可以查看Suvro baner JEE的这篇伟大文章。
创建我们的数据集
像往常一样,我们将开始创建我们的数据集。为了能够在 RNN 中使用文本数据,我们需要将其转换为数值。然后,我们将创建一个字符序列作为我们的 X 数据,并使用下面的字符作为我们的 Y 值。最后,我们将把数据转换成一个布尔数组。
首先,我们将加载数据,并创建从字符到整数和整数到字符的映射:
with open('sherlock_homes.txt', 'r') as file:
text = file.read().lower()
print('text length', len(text))chars = sorted(list(set(text))) # getting all unique chars
print('total chars: ', len(chars))char_indices = dict((c, i) for i, c in enumerate(chars))
indices_char = dict((i, c) for i, c in enumerate(chars))
为了获得有价值的数据,我们可以用它来训练我们的模型,我们将把我们的数据分成长度为 40 个字符的子序列。然后我们将把数据转换成一个布尔数组。
maxlen = 40
step = 3
sentences = []
next_chars = []
for i in range(0, len(text) - maxlen, step):
sentences.append(text[i: i + maxlen])
next_chars.append(text[i + maxlen])x = np.zeros((len(sentences), maxlen, len(chars)), dtype=np.bool)
y = np.zeros((len(sentences), len(chars)), dtype=np.bool)
for i, sentence in enumerate(sentences):
for t, char in enumerate(sentence):
x[i, t, char_indices[char]] = 1
y[i, char_indices[next_chars[i]]] = 1
递归神经网络模型
虽然创建一个 RNN 听起来很复杂,但是使用 Keras 实现起来非常容易。我们将创建一个简单的 RNN,其结构如下:
- LSTM 层:将学习序列
- 密集(全连接)层:每个独特字符一个输出神经元
- Softmax 激活:将输出转换为概率值
我们将使用 RMSprop 优化器和分类交叉熵损失函数。
from keras.models import Sequential
from keras.layers import Dense, Activation
from keras.layers import LSTM
from keras.optimizers import RMSpropmodel = Sequential()
model.add(LSTM(128, input_shape=(maxlen, len(chars))))
model.add(Dense(len(chars)))
model.add(Activation('softmax'))optimizer = RMSprop(lr=0.01)
model.compile(loss='categorical_crossentropy', optimizer=optimizer)
助手功能
为了看到我们的模型在训练时的改进,我们将创建两个辅助函数。这两个函数来自 Keras 团队的官方 LSTM 文本生成示例。
第一个辅助函数将从输出(概率数组)中抽取一个索引。它有一个名为 temperature 的参数,这个参数定义了函数在创建文本时的自由度。第二个将在每个时期结束时生成具有四个不同温度的文本,以便我们可以看到我们的模型做得如何。
def sample(preds, temperature=1.0):
# helper function to sample an index from a probability array
preds = np.asarray(preds).astype('float64')
preds = np.log(preds) / temperature
exp_preds = np.exp(preds)
preds = exp_preds / np.sum(exp_preds)
probas = np.random.multinomial(1, preds, 1)
return np.argmax(probas)def on_epoch_end(epoch, logs):
# Function invoked at end of each epoch. Prints generated text.
print()
print('----- Generating text after Epoch: %d' % epoch)
start_index = random.randint(0, len(text) - maxlen - 1)
for diversity in [0.2, 0.5, 1.0, 1.2]:
print('----- diversity:', diversity)
generated = ''
sentence = text[start_index: start_index + maxlen]
generated += sentence
print('----- Generating with seed: "' + sentence + '"')
sys.stdout.write(generated)
for i in range(400):
x_pred = np.zeros((1, maxlen, len(chars)))
for t, char in enumerate(sentence):
x_pred[0, t, char_indices[char]] = 1.
preds = model.predict(x_pred, verbose=0)[0]
next_index = sample(preds, diversity)
next_char = indices_char[next_index]
generated += next_char
sentence = sentence[1:] + next_char
sys.stdout.write(next_char)
sys.stdout.flush()
print()
print_callback = LambdaCallback(on_epoch_end=on_epoch_end)
我们还将定义另外两个回调函数。第一个名为 ModelCheckpoint。这将节省我们的模型每一个时代的损失减少。
from keras.callbacks import ModelCheckpoint
filepath = "weights.hdf5"
checkpoint = ModelCheckpoint(filepath, monitor='loss',
verbose=1, save_best_only=True,
mode='min')
另一个回调会在每次学习停滞时降低学习速度。
rom keras.callbacks import ReduceLROnPlateau
reduce_lr = ReduceLROnPlateau(monitor='loss', factor=0.2,
patience=1, min_lr=0.001)callbacks = [print_callback, checkpoint, reduce_lr]
训练模型并生成新文本
对于训练,我们需要选择一个 batch_size 和我们想要训练的时期数。对于 batch_size,我选择 128,这只是一个任意的数字。我只训练了 5 个时期的模型,所以我不需要等这么久,但如果你想你可以训练它更多。
model.fit(x, y, batch_size=128, epochs=5, callbacks=callbacks)
培训产出:
Epoch 1/5
187271/187271 [==============================] - 225s 1ms/step - loss: 1.9731----- Generating text after Epoch: 0
----- diversity: 0.2
----- Generating with seed: "lge
on the right side of his top-hat to "
lge
on the right side of his top-hat to he wise as the bore with the stor and string that i was a bile that i was a contion with the man with the hadd and the striet with the striet in the stries in the struttle and the striet with the strange with the man with the struttle with the stratter with the striet with the street with the striet which when she with the strunt of the stright of my stright of the string that i shall had been whi
----- diversity: 0.5
----- Generating with seed: "lge
on the right side of his top-hat to "
lge
on the right side of his top-hat to he had putting the stratce, and that is street in the striet man would not the stepe which we had been of the strude
in our in my step withinst in some with the hudied that in had a had become and the corted to a give with his right with a comon was and confice my could to my sule i was and shugher. i little which a sitter and the site my dippene with a chair drive to be but the some his site with
为了自己生成文本,我们将创建一个类似于 on_epoch_end 函数的函数。它将采用一个随机的起始索引,从文本中取出接下来的 40 个字符,然后用它们来进行预测。作为参数,我们将传递给它我们想要生成的文本的长度和生成的文本的多样性。
def generate_text(length, diversity):
# Get random starting text
start_index = random.randint(0, len(text) - maxlen - 1)
generated = ''
sentence = text[start_index: start_index + maxlen]
generated += sentence
for i in range(length):
x_pred = np.zeros((1, maxlen, len(chars)))
for t, char in enumerate(sentence):
x_pred[0, t, char_indices[char]] = 1.
preds = model.predict(x_pred, verbose=0)[0]
next_index = sample(preds, diversity)
next_char = indices_char[next_index]
generated += next_char
sentence = sentence[1:] + next_char
return generated
现在我们可以通过调用 generate_text 函数来创建文本:
print(generate_text(500, 0.2)
生成的文本:
of something akin to fear had begun
to be a sount of his door and a man in the man of the compants and the commins of the compants of the street. i could he could he married him to be a man which i had a sound of the compant and a street in the compants of the companion, and the country of the little to come and the companion and looked at the street. i have a man which i shall be a man of the comminstance to a some of the man which i could he said to the house of the commins and the man of street in the country and a sound and the c
结论
递归神经网络是一种处理顺序数据的技术,因为它们可以通过内部存储器记住最后的输入。它们在几乎每一个顺序问题上都达到了最先进的性能,并被大多数大公司所采用。RNN 可用于以特定作者的风格生成文本。
创建文本生成 RNN 的步骤如下:
- 创建或收集数据集
- 建立 RNN 模式
- 以一个随机的句子为起点创建新的文本
这个项目的细节可以在这里找到。我鼓励任何人试验一下代码,也许可以改变数据集和预处理步骤,看看会发生什么。
为了获得更好的输出,您还可以对模型进行许多改进。其中一些是:
- 使用更复杂的网络结构(更多 LSTM 层、密集层)
- 为更多时代而训练
- 摆弄批处理大*
如果你喜欢这篇文章,可以考虑订阅我的 Youtube 频道,在社交媒体上关注我。
如果你有任何问题或批评,可以通过推特或评论区联系我。
用神经网络生成文本
原文:https://towardsdatascience.com/generating-text-with-lstms-b0cdb6fc7bca?source=collection_archive---------2-----------------------
Can Neural Networks learn to Write?
有许多文章因声称“用 lstm 写另一部哈利波特”或“用 lstm 写说唱歌词”而获得了人气。LSTMs 属于一类更广泛的神经网络模型,称为递归神经网络。“循环”部分来自模型按顺序处理数据的能力,以及将以前的输入值作为最新输入值的输出因素。
序列处理是一个非常有趣的问题,可以应用于价格建模、视频处理,以及我们将在本文中讨论的文本处理。
Letters vs. Words, what is the foundation for language in Neural Networks?
当将 RNNs 用于文本、字符和单词级模型时,有两种主要的二分法。这是指将文本编码成整数以便模型处理的方式。在 char 级模型中,我们将每个字母标记为字母语料库中的一个 hot 向量。在单词级模型中,我们将每个单词标记为单词语料库中的一个热点向量。
尽管对每个单独的字符进行编码可能看起来更加繁琐,但这里要避免的瓶颈是结果向量的稀疏性。在文本的训练数据集中通常只使用大约 60 个字符,在同一个数据集中很容易使用 1000 个独特的单词。有很多方法可以使用单词嵌入来尝试和减少单词级编码的*数,但是到目前为止,字符级编码对于简单的推理来说会产生更好的结果,即编码的向量具有更密集的信息。
字符级网络中的一键矢量编码示例 ( 如果你已经熟悉这个请跳过):
语料库:['a ',' b ',' c ',' d,' e ',' f ',g ',' h ',' i'] — len(语料库)= 9
单词:['坏'] → ['b ',' a ',' d']
b → [0,1,0,0,0,0,0,0,0],a → [1,0,0,0,0,0,0,0,0,0],d → [0,0,0,0,1,0,0,0,0]
一些采用这种策略的人选择不使用一键向量编码方法,而是用 ASCII 码对每个字符进行编码,比如 a = 65。以这种方式编码字符的问题是,整数暗示了字母之间的某种顺序,例如:a < b < d。在实际语言中,字母之间的这种组织是不存在的。
当处理神经网络,尤其是具有许多层的深度神经网络时,我们希望尽量避免这样的事情,因为很难确切地说出网络在训练后学到了什么。一个著名的例子是在森林中探测坦克的军事实验。包含坦克/不包含坦克的数据集仅在晴天拍摄了坦克,在阴天拍摄了不包含坦克的田地。因此,深层 CNN 模型学会了对天气进行分类,而不是对坦克的存在进行分类。
一旦将文本编码成向量,就该使用 LSTM 来训练模型了。在这个代码示例中,我们将使用构建在 Tensorflow 之上的 Keras 库来大大简化这项任务。
from keras.models import Sequential
from keras.layers import Dense, LSTMmodel = Sequential()
model.add(LSTM(75, input_shape=(X.shape[1], X.shape[2])
model.add(Dense(vocab_size, activation='softmax'))model.compile(loss = 'categorical_crossentropy'
optimizer = 'adam',
metrics = ['accuracy'])model.fit(X, y, epochs = 100, verbose = 2)
正如我们在上面看到的,建立神经网络并不太困难。与生成文本相关的大部分工作(像许多 ML 项目一样),是对文本进行预处理,对文本进行标记并将其转换成向量,然后将其输入模型。
我用 JCole 歌词做了一个实验,看看这个模型是否能继续这个序列。该模型在训练中报告了 80%的准确率,但当我给出这些例子时,结果并不令人印象深刻。我们确实注意到该模型不能很好地概括,即使两个输出都不令人满意,但是当训练数据中包含起始种子时,该模型表现得更好。
示例 1:(训练集中包含的起始种子)
“没有角色模型,我是她”,20 #歌词包含在训练集中,20 个参数指示模型再生成 20 个角色
模型输出→没有榜样,而我在这里是因为他们没有
(至少在某种程度上这是英语)
示例 2:(起始种子不包含在训练集中)
跳入水中,20 #歌词不包含在训练集中
输出→跳入水中,furby 调用 som
这些结果如此糟糕的主要原因是因为我只给模型输入了 500 行 JCole 歌词,如果你有兴趣自己尝试这个实验,我建议使用 kaggle 的 55,000 首歌曲歌词数据集。你应该预料到训练这个模型也需要一些时间,除非你有 GPU 机器或者计划在云上训练你的模型。
如果一个字符或单词级别的递归网络可以生成类似电视节目中的对话或书籍节选的内容,我会感到惊讶。我也对如何使用生成对立网络来生成文本非常感兴趣。有许多流行的论文使用文本生成方法,标题如:“神经网络撰写研究论文标题”。训练这些网络需要大量的数据、计算能力和深度模型,所以如果在本地计算机上运行,请做好准备。
感谢您的阅读,希望这篇文章能帮助您理解 RNN/LSTM 序列网络的文本生成!如果你想用 Python 和 Keras 详细浏览你的第一个角色级 RNN,下面是一篇很好的文章:
https://machine learning mastery . com/develop-character-based-neural-language-model-keras/
CShorten
Connor Shorten 是佛罗里达大西洋大学计算机科学专业的学生。对数据科学、深度学习和软件工程感兴趣。主要用 Python,JavaScript,C++编码。请关注更多关于这些主题的文章。
生成 Twitter 自我网络&发现社区
原文:https://towardsdatascience.com/generating-twitter-ego-networks-detecting-ego-communities-93897883d255?source=collection_archive---------2-----------------------
一种基于图的 Twitter 网络社区发现方法
我们的心甚至还没有参与——就此而言,我们的耳朵也没有!我们更像是一个神不守舍、全神贯注的人,他的耳朵里刚刚响起了正午 12 点的钟声(一个 twitter 通知把你叫醒了),他突然醒来,问自己“那个钟到底敲了多少下?” (他/她刚才到底转发了什么,是在说我想的那个吗..?) (这真的是刚刚发生的吗?) 还有更多:“我们到底是谁?” (我为什么要跟着他/她?) 然后,正如我已经提到的,我们数一数——事后——我们经历的时钟的所有十二次颤抖的敲击 (我们浏览他们所有的推文) 、我们的生活 (我们的推文) 、我们的存在 (我们的追随者)——唉!在这个过程中,我们不断失去计数。因此,我们对自己仍然是陌生人,我们不了解自己,我们必须让自己困惑 (我们察觉到它们) 。对我们来说,这条定律永远适用:“每个人都离自己最远。就我们自己而言,我们不是“有知识的人”。”—弗里德里希·*采
我很确定*采预言了推特。以这样的方式开始我的数据科学相关帖子(引用这样的话)可能看起来很奇怪,但这确实是我们任务背后的动机——试图成为‘有知识的人’,通过理解我们身边的人(虚拟地)来拉近我们自己。
推特是..至少可以说很奇怪。我跟踪的很多人都不止一次抱怨过 Twitter 的无用和对它的沉迷..在推特上。我不知道当一个平台被用来抱怨自己时,它会说些什么,但我知道的是,它会把你拉回来。Twitter 就像柏拉图的洞穴,在那里我们看到影子在跳舞,除非我们有意识地面对它,并且技术上可以“自由”转身离开,但通常不会。这并不那么可怕和令人沮丧,我们必须承认,Twitter 允许我们拥有一个微型互联网,在我们作为进出连接的枢纽时,可以自由定义自己的定制规则。随着这个中心的成长——随着我们被越来越多的用户关注和追随——它塑造和修补成一些个人的东西,包含了解释我们的兴趣甚至我们个性的某些部分的潜在属性的组合。作为一个中枢,我们娱乐并被我们随着时间的推移创造的网络所娱乐:一个以我们为焦点的自我网络(一个来自社会学的术语),延伸我们的虚拟肢体去触摸和感受其他自我和他们自己的自我网络的元素。
不管你对 Twitter 的看法如何,它可以是一个丰富的数据集,这个项目旨在使用这些数据来建模和分析一个 Twitter 自我网络。为了能够进行更深入的分析,我们必须完成一些预备步骤。因此,在这篇文章中,我将只讨论这种分析的第一阶段:通过社区检测技术对网络建模并执行一些高级软分析。
未来阶段将尝试使用自然语言处理技术进行更深入的研究和语言元素分析。
概述
1.数据挖掘
2.网络建模
3.社区检测
4.观察和分析
这篇文章是为普通读者写的,旨在展示一些工作是如何完成的,我将避免过于技术性的谈话——希望让它成为每个人相关和有趣的经历。然而,我将为有一些基本编码经验的读者提供足够的技术参考,以便他们能够了解可以使用什么工具来执行任何类似的分析。(我也可以根据要求展示代码)
技术说明
所有编程,数据挖掘,算法应用等。是在 Jupyter 笔记本(Python)中从一个基本的 Docker 模板中完成的。
#Libraries Used:
tweepy
i-graph
networkx
tqdm
pandas
numpy
matplotlib
seaborn
pickle
json
Gephi 用于输出两者的网络可视化。巴新和。svg 格式。 i-graph 和 networkx 库都可以输出中的图形。来自 Python 对象的 gml 格式,可以使用 Gephi 读取并组织、着色、分区等等。
数据挖掘— 让我们获取数据
这个项目的数据是使用 Twitter 的 API 从 Twitter 中提取的。不幸的是,鉴于 Twitter 的费率限制,在给定的时间窗口内只允许一定数量的呼叫,挖掘起来并不迅速。为了建立我们的网络,我们需要:
- 账号/验证 _ 凭证 — 获取 root 用户的【又名我的】信息
- 好友/列表 —返回每个用户的信息 root 用户是“关注者”,我们称他们为“好友”[~ 300/15 分钟]
- friends/ids — 返回 root 用户的朋友的 id 为“following”,如 get“朋友的朋友”)[~75,000ids/15min 或 15users/15min]
- 状态/user_timeline — 获取任何给定用户的多达 3,200 条最新推文[~36,000 条推文/15 分钟]
使用一个名为 Tweepy 的 python 库,它自动等待考虑速率限制,我们可以获得 Twitter 的 API 响应并将它们存储到 JSON 文件中。然后,可以读取这些文件,并将其放入数据结构(字典或 Pandas DataFrame)中,供我们的其余流程使用。
网络建模——我们如何量化我们所看到的?
任何数据科学分析最重要的步骤之一是花时间思考如何量化问题。通常,当我们用来量化现实的基础数据和手段薄弱时,我们往往会转向模型和算法。
我们将建立一个社会学中所谓的一步邻居——在某种意义上,我们将只深入到两层朋友,但条件是我们将删除不是根用户朋友的朋友的朋友。所以,我们会查看 look 用户(我的)的朋友以及他们之间的任何联系。(用户的‘朋友’是 twitter 的官方术语,用来描述用户‘关注’的人)。由于要建立我们的网络,我们更感兴趣的是根用户“看到”了什么,而不是他们如何被“看到”,我们将关注他们的朋友,而不是他们的追随者。该网络将是一个基于有向图的网络 (图 1) ,意味着我们主要处理节点和有向边。基本设置:
- 节点将被定义为用户。
- 边基于某种关系将两个用户(节点)连接在一起。从这个意义上说,如果用户 A 跟随用户 B,一条边将从节点 A 出去,进入节点 B。
Figure 1: Basic Directed Graph
虽然这是网络的基础,但我们可以直观地看到,每个“我在关注你”的关系不可能有相同的“权重”——你的叔叔住在几英里外,4 年前跟踪你,作为一种“时髦”的手段,他在你的网络中的角色与你的共同分享者非常不同,他们总是转发你所做的一切。因此,我们通过建模权重(针对边和节点)在我们的网络中引入一些复杂性。本项目中的假设是权重由【活动】量化(这也将在我们稍后选择的社区检测类型中发挥作用)。
- 边缘权重将是任何给定用户之间的各种连接的函数,即你最近历史中的转发、回复和引用状态的数量。我们还将量化“我追随你”的联系,假设 A) 如果用户的追随者与追随者比率较低,那么他们追随某人会变得更加“重要”,而 B) 拥有更多追随者的用户追随拥有较少追随者的用户会变得更加“重要”。这就引出了一个等式:
EdgeWeight between a & b
= (w1 * RT_ab) + (w2 * Qtd_ab) + (w3 * Rep_ab)
+ ( w4 * (Rff_a * (FC_a - FC_b) / (FC_a + FC_b) )Rt_ab = # of A Retweets B
Qtd_ab = # of A Quoted B
Rep_ab = # of A Replies to B
Rff_a = Follower to Following Ration of a
FC_a = Follower Count of a
FC_b = Follower Count of bw1,w2,w3,w4 = (manually assigned) weights of each connection
w4 > w3 > w2 > w1
w1、w2、w3、w4 这些术语是根据直觉选择的,以便对每个术语的意义进行排序(根据我与 Twitter 的互动方式)——关注比回复更有价值,引用比转发更有价值…
- 我们还可以根据用户活动为节点本身分配权重。可以理解的是,不管有什么联系,如果我(和我的朋友)更频繁地见到一个用户,他通常是我的网络中更强大的一部分。
NodeWeight of a = ~ Avg # of tweets day based on recent historyTweets include RTs, Quoted Statuses, & Replies.
可以使用 python 库 i-graph 或 networkx 对图形进行建模。 Networkx 很好,因为它允许从 Pandas Dataframe 直接导入,但是在 i-graph 上有更多的社区检测算法选项。就我个人而言,我在两个 i-graph 中对他们建模,以获得社区分配,然后使用 networkx 进行一些初步可视化(因为它与 matplotlib 一起工作,不像 i-graph
网络统计:节点和边属性的分布
在解释下面的图表时,请注意大多数轴都是对数 10 标度的,以便更清楚地看到数值的分布(例如,x 轴上的 2 表示 100 单位,3 = 1000 单位,4 = 1000 单位,等等)。).另请注意,节点统计的 y 轴值是密度而不是计数(例如曲线下的面积等于 1)。不管怎样,我们对查看一般分布感兴趣——哪个值出现得最多或最少。
Node Stats (all x-axis are log-scaled)
在我们的网络中,似乎大多数用户有 1000-10,000 条推文和 100-1000 个好友(如下)。followersCount 分布似乎没有达到峰值,所以分布更加均匀。最后,我们的大多数节点都有很*的权重,有些用户比这个网络中的普通用户活跃近 10 倍。
Edge Stats
就优势而言,正如预期的那样,大多数用户并不经常联系,而那些联系上的用户之间最近的活动水平(5-100 次转发和回复)差异很大。
最终网络:汇集一切
现在,我们的网络由大约 400 个加权节点和大约 10,000 条边组成(很*,但关系复杂)。下面是过滤掉一些孤立节点后的样子:(注意,节点的大*描述了节点权重)
Figure 2: Social Network — Directed Graph with Weighted Nodes and Edges
嗯……酷?(有可能)。但实际上,我们很快就会意识到我们无法从中获得一大堆信息。目前,这是非常平淡无奇的(从字面上看,这只是黑与白),这实际上是我们在处理复杂网络时面临的挑战之一——你不能只是从它们那里“观察”见解。这就是为什么在我们作为人类分析师真正进行任何有意义的分析之前,我们需要看到“聚集”的信息。从算法上来说,对数据进行聚类也将有助于我们今后的语言分析,并且也经常用于减少计算时间。有助于应对这一挑战的技术是社区检测— 一个强大的过程(图 3) ,其中我们将一个复杂的网络分割成个社区,这些社区在结构上对图进行分类,并描述一些隐藏在你在图 2 中看到的网状混乱中的高阶属性。
Figure 3: Example of Community Detection
社区检测
现在是有趣的部分(再次,字面上),我们如何在我们的网络中找到隐藏的社区?我只有大约 400 个朋友,所以如果有人建议花一天时间浏览他们,他们并没有“错误”…然而,如果我们想摆脱人类的“偏见”,更“科学地”找到社区呢?如果我们开始手动地将用户分类到社区中,我们会确切地知道该做什么,但是在更真实的意义上,我们不知道该做什么。像'这样的难题,首先有多少个社区?“社区分配的标准是什么?”上来。因此,虽然可以理解,如果我们使用计算机进行这种分类过程,我们可能会失去一些细微差别,但与直觉相反,我们实际上可能会获得一些我们的偏见所不允许的细微差别。
有了数据科学,我们不需要总是处理数据,因为“人类不可能做到,这需要太长时间”。有时,数据科学是一门由可计算的有氧运动组成的艺术,它帮助我们以一种前所未有的方式查看数据。(尽管通常情况下,数据科学是在做一个人真的不应该用 Excel 做的事情。虽然他们尝试…他们总是尝试…人类。)本着这种精神,我们期待一种有趣的算法来发现基于“信息流”的社区——信息地图。
首先,什么是社区?没有具体定义的原因是因为“社区”的部分定义将来自社区检测算法。一般来说,信息分类在任何哲学或科学研究中都扮演着重要的角色,而社区就是这样:组织知识的节点分类。
我们本质上试图从社区中获取的是基于同质化现象将相似的用户分组在一起。
“相互联系的群体中的个体往往具有相似的特征。这种现象被称为同质性,并被定义为“一个基本的组织原则”,即“相似的人之间的接触比不同的人之间的接触发生率更高”( McPherson,Smith-Lovin,& Cook,2001 ,第 416 页)。“物以类聚,人以群分”的说法广为人知,它抓住了自然发生的社会网络的一个关键特征,并描绘了一种机制,通过这种机制,“社会特征方面的距离转化为网络距离”( McPherson 等人,2001 ,第 416 页)。简单地说,同性恋表明个人更有可能与经常与他们非常相似的其他人形成新的社会网络联系。”
— 使用社交网络分析对 Twitter 话题网络进行分类
更具体地说,twitter 自我网络包含自然发生的基于流的社区——自然发生是因为“信息流”不是预先确定的,而是随着网络拓扑结构的变化而改变。节点(用户)通过边缘(转发、回复等)将自己确立为节点之间的信息载体。).在这个意义上,当我们寻找社区时,我们正在寻找基于流的社区检测方法,以便“社区由节点组成,其中,[信息]流一旦进入就会持续很长时间”(地图方程框架教程)。这不同于基于我们的网络模型的结构组成将一个图切割成斑点。我们将在后面看到基于流的社区检测算法如何不总是在结构上分离网络。
Infomap 是基于优化‘地图方程’的基于流量的社区搜索算法。我不想在这里变得过于技术化,所以如果感兴趣的话,我会让读者自己去探索,特别是因为作者已经制作了一些描述 map 方程机制的惊人演示,并且有一个编写的教程来指导你。
在使用 Infomap 进行了一些尝试后,我发现尽管它很好地对许多社区进行了分类,但通常有一大块节点被归类为一个社区,感觉像是“剩余”节点——用户很可能属于多个社区,并为更复杂的信息流做出贡献。为了进一步分割这个大的剩余社区, Walktrap ,另一个社区检测算法,但它更多地基于节点相似性和网络结构——如果从 A 和 B 分别到达所有其他节点的概率相似,则节点 A 和 B 被分类在同一个社区中。从一个节点到另一个节点的概率是用“随机漫步”来计算的,这背后也有一个简洁的直觉。
基本上,在应用这些算法之后,我们的社区检测采用以下组织原则:如果推文和关注(信息和印象)似乎持续存在于用户中,则用户被分组在一起——使得他们彼此之间的活跃度很高。至于更大的剩余用户群(他们彼此之间有规律的活动,并且信息流不会在任何特定的更*的用户群中持续),根据他们在该更大的群中的行为的相似程度,他们被进一步划分为*社区。 图 4 显示了我们网络中社区规模的直方图。
这两个社区定义不同的一个直观原因是,我们可以让我和我的朋友 Qasim 不转发对方的观点(因为这意味着承认失败),而是不断转发第三方政治分析师的观点。一个基于相似性的检测会把我和我的朋友归入同一个社区(即我们有相似的行为),一个基于流的检测不会(即信息不流经我们的连接)。
Figure 4: Histogram of Community Sizes (y-axis is # of communities)
这种分布突出了看似直观的东西(至少在我使用 Twitter 的方式上):我们有许多*社区——通常围绕特定的品味/事件/兴趣/主题构建——然后是一些主要的大玩家,在这种情况下包含 10 到 50 个用户。
注意:当然,一些用户在任何给定的社交网络中的多个(概念上的)社区中具有“成员资格”,但是对于这个项目,我们将不处理重叠和多个成员资格。部分原因是,我希望看到一个用户被分配到其所属的所有社区中最主要的社区,部分原因是,这会使计算变得不必要的复杂,并且我找不到足够方便的库来进行所述计算。
观察和分析
最后,我们得到了一个奇妙的自我网络,看起来像一个热闹的三星级酒店(如果你得到了这个参考,也请立即在 Twitter 上与我联系)。同样,节点大*描述了节点权重(用户有多“活跃”),而边厚度描述了边权重(两个用户基于他们彼此的活跃程度而有多强的连接)。
Figure 5: Communities in a Twitter Ego-Network
仅供参考,中间右边的白点是我(正如*采预言的,我对自己一无所知…我甚至不是我自己社区的中心…)。说到自我,我认为我们的一部分总是希望被分析,而这种关注并不总是容易获得的——所以这就像是获得关注的 DIY 版本。在我的个人网络上做了这种分析后,我可以将算法输出与我自己的人类直觉进行比较,并且——以我早期的一些项目为例——这正是我想要做的。这篇文章的其余部分将强调一些从我们的网络图中提取洞察力的方法。
提醒一下,这是对“自我网络”的社区分析,因此,不是对 Twitter 上任何给定用户的客观分类,而是从我的角度对他们在我的网络中所扮演的角色的分类。
可视化的分析原理
相互关联的位置— 当我们分析社区时,重要的是要记住节点的确切位置(南、北、东、西)并不重要,但它与其他节点的相对位置不是偶然的。尽管可视化中包含一些随机性,但它实际上是通过吸引力、排斥力和重力的混合来建模的。所以强连通的节点会互相吸引,非连通的节点会互相排斥。
内部相关位置 —区域内节点的位置也很重要。远离中心位置和深入社区的节点反映了更多的*生境行为和信息流属性。
密度— 更密集的节点集合意味着更强的互连性。稀疏意味着更弱的互联性。
模块性— 衡量集群质量的指标,即社区之间的断开程度。“高度模块化网络的特征是一些高度内部连接的集群,它们松散地相互连接。因此,用户高度互联而不考虑集群关系的网络模块化程度较低。”
桥接节点— 在社区边界上发现的节点有时可以充当链接,松散地互连两个社区。
离群点— 远离其所分配社区的结构领域的节点。有时这些是错误分类,有时远离桥节点。
Ego-Network Fingerprint
社区#1-2:现实生活中的人和他们现实生活中的朋友
这两个社区通常包含我所关注的我的个人关系或朋友(以下简称“追随者”),分别位于我主要的高中关系和高中以外的关系之间。因此,可以理解它们是密集的(即强内连接)。我看到了一个有趣的空间表现,我的高中联系远离了中心,从而远离了我的普通网络的其余部分(即,在 twitter 的世界里,我们已经分开了,可以理解的是,他们中的一些人甚至不活跃)。在这个社区中,我经常与之互动的人离我的节点更近。此外,与社区中的其他人相比,更强的朋友(或者至少是我所知道的那些)看起来彼此更亲近。总的来说,这些都是强大的、定义良好的社区,并且与真实系统相一致——网络的这一部分具有很强的模块化。
社区#3:多伦多人寿保险公司(最右边是 CBCNews)
另一个强大的社区,在战略上离我的个人关系稍微远一点。这个社区主要包含不同主题的多伦多/加拿大用户。有趣的是, '@hidrees ',' @DotHealth ',' @robjama ',和 '@uoftengineering' 在一起,但与其他人相距较远——这是一个多伦多-加拿大商业技术迷你*组。当我们向北走时,我们会遇到更多的活动家/记者/政治评论家,比如、和、【stevenzhou】。像 '@IRCanada ',' @ NaseehaHelpline ',和 '@IngridMattson' 这样的节点是结构上更接近这个社区(和加拿大人)的用户的很好的例子,但是就流量而言,更涉及另一个社区。总的来说,除了一些微型组之外,集群通过松散的内部连接松散地连接到网络的其余部分。这意味着这个社区并不是太封闭,它包含了与我的更中心的网络的各种连接。
社区# 4–5:主角(绿色)和不适合的人(粉色)
这是最大的跨社区(就区域而言),原因显而易见——我们有许多用户涌入其他社区的领地。我把这个社区称为“主要行为”——我觉得每个 twitter 用户都有一个在某些方面与此类似的社区——因为我的许多其他社区“观看”这个社区,有点像一出戏。
- 我们看到的主要是大客户,受欢迎的人物,他们在别人看着他们的时候相互交流。就我而言,我们看到对世界事务发表评论的伊斯兰学者聚集在中心,与来自其他社区的多个用户相连。
- 我们还可以看到一种趋势,即随着我们向西北方向发展,新闻和内容越来越普遍,越来越针对穆斯林。随着我们越走越远,用户越来越少关注我的网络中的其他中心话题。
- 这些在社区边缘的用户就像是连接更多*众社区和大众的桥梁。
- 我已经强调了一些离群值,他们最近的活动将他们分配到这个社区,但我发现如果有一个更结构化的分配会更好。
粉红色的社区——格格不入者,我没有任何贬损的意思——是一个弱势群体。这些用户在信息流中不够深入,而社区在结构上与他们很接近,因此似乎被随意地归类在一起。这也可以在空间上注意到,因为社区是分散和稀疏的,具有松散的内部连接和更强的相互连接。
社区#6:臭名昭著的穆斯林推特MT
这是臭名昭著的穆斯林 Twitter 社区,除了我的个人社区之外,唯一一个在结构上和信息流上都被分割的社区。就个人而言,这是最有趣的利基社区之一,就其动态和信息流结构而言,值得对其进行整体分析。
- 兄弟姐妹/亲密朋友的趋势在这里再次显现,兄弟姐妹被放在一起。
- 在我的网络中,MT 的领域是相当模块化的——它们与我的网络的其余部分松散地互连,但具有很强的内部连接。这是显而易见的,因为我们看到在西北部有一个更紧密的迷你群围绕着两个高度活跃的兄弟姐妹,而 MT 的其余部分很稀疏。(同样,这并不意味着他们客观上是机器翻译的中心,只是在我的自我网络中)。
- 我还强调了我所关注的 MT 和我所关注的学者圈子之间的桥梁节点,这是我之前在绿色社区中讨论过的。
- 桥接节点当然可以走任何一条路,一些节点如 '@Saeen' 更属于下面的网络,而 '@JeremyMcLellan' 可能属于 MT。这是铁证 '@JeremyMcLellan' 是#creepingsharia 的支持者——MT 的人会理解这个笑话:d
社区# 7–9:大思想政治评论(橙色)、社会主义者(灰色)和哲学(暗黄色)
一群非常有趣的社区——现在我们深入到政治和哲学中。
- 与其他部分相比,该图的这一部分具有较低但合理的模块性,社区靠得很近,但它们也密集地聚集在一起,暗示着强大的内部联系。
- 橙色社区是强有力的政治评论员——我说的是你的大政治理念,从伊斯兰主义(支持和反对)到天主教国家,到“黑暗网络”的成员。我们还可以看到美国在外围的讨论和中东向中心的讨论,中间是 '@shaadihamid' (他应该是一个强调中东伊斯兰政治的美国人)。
- 我们还有社会党人、民主党人和左派(灰色),他们或多或少地团结在一起。有趣的是,与一般的大思想政治评论不同,这些评论并不像美国社会主义者和欧洲左翼分子(桑德斯、科尔宾和瓦鲁法基斯)那样按地区分开。
- 哲学圈,虽然主要是教育账户,但由于 MT(蓝色社区#6)和大思想政治社区的多重联系,被拉离了更南方的团体。
社区# 10–14:互联互通的南方
网络的南部区域是最不模块化的。虽然存在一些密集的微型社区,但总体而言,我们在社区之间有大量的结构差异和相互联系——反映了这些类型的社区相互融合和互动的趋势。
- 这个区域的节点主要是关于艺术,阅读,写作和一些商业。出版物、杂志和期刊的大型节点分散在该地区。
- “分享者”——因为他们分享许多与该地区主题相关的有趣内容——是一个以' @ austinkelon '为中心的紧密聚集的社区。我们也有一个与众不同的*众乌尔都语诗歌社区。
- 我发现 '@Versobooks' 是连接哲学、左翼和作家/读者群体的一个很好的桥梁节点。
额外:网络时间表
自我(网络)是如何形成的
我们再加一个*度:时间。类似于我们已经讨论过的桥节点作为不同社区之间的链接,有一些节点作为暴露节点将我们暴露给一个新的社区。如果我们看到网络随着时间的推移而增长,我们可以注意到这些特定的节点。我们也可以了解这种特定自我网络如何发展的一些模式。
Epoch 1
Epoch 2
Epoch 3
Epoch 4
Epoch 5 — Current Network
在这种增长方式中可以观察到一个很好的模式:我们看到网络的模块化区域(高度互联)在给定的时间段内具有高增长率,然后降低到低增长率,而非模块化区域一旦开始就稳步积累。我们还看到,“曝光节点”(那些将我们引入社区的节点)不一定是该社区的“中心”节点,而是桥梁节点。这种节点的好例子是时段 2 的第一幅图像中的红色节点和时段 3 的第一幅图像中的蓝色节点。
结束语
- 这是我的个人网络,所以我可以从这个分析中提取的大量理解已经是“已知的”。但是想象一下,对任何一个我们从未接触过的用户进行这种分析,以及我们对他们的品味、群体、兴趣和成长的高层次了解…
- 大多数数据分析(尤其是基于网络的)试图获得客观的真相,并理解大的名人趋势。虽然这有它的目的,但出于某种原因,我没有看到很多试图提取主观行为和更*规模的深入见解的分析…我觉得这是一个差距,如果得到解决,可能会产生一些有趣的见解。
- 有定量的方法来计算模块性、内部连接性、互连性等。我在这里没有探讨读者可以研究的问题(我只是喜欢对这样的帖子进行定性分析,这是一个更有趣的项目)。
- 总之,我从这个项目的第一阶段得到的要点是我们的网络模型中的相对关系模拟了真实系统中的相对关系!这提供了一些可信度,以探索对这种网络模型和社区分割进行更深入的分析。
只需一次点击,即可打造您自己的时尚系列
原文:https://towardsdatascience.com/generating-your-own-fashion-line-in-1-click-a8155c0c207?source=collection_archive---------12-----------------------
我想分享一下我上周在做的一个玩具项目——时尚发电机。为什么?因为甘人很棒,正如扬·勒村所说:
对抗训练是自切片面包以来最酷的事情
这种生成网络通过 GPU 加速在你的浏览器中工作。现场演示在这里— 时尚甘,源代码在这里— github 。也许通过调整输入足够长的时间,你将创造一个新的著名的时装系列(可能性很低,但无论如何,如果发生这种情况,请给我发电子邮件)。
时尚甘食谱
首先,我们需要时尚 mnist 数据集,这是疲惫的 mnist 的一个很好的替代品。它采用相同的包装,可作为替代产品使用。还有 10 类:t 恤/上衣、裤子、套头衫、连衣裙、大衣、凉鞋、衬衫、运动鞋、包和踝靴,这些有时很难辨别,尤其是套头衫和大衣。
然后,我们需要一些框架:Tensorflow 来训练模型,以及 deeplearnjs 在带有 GPU 加速的浏览器中运行。关于 TF 部分没什么可说的,除了 YellowFin ,我加这个是因为我喜欢自调优器的想法。关于 deeplearnjs:它是一个完整的 js 框架,用类似 tensorflow 的 API 对 ML 模型(或任何线性代数)进行训练和推理。我很难想象在浏览器中训练神经网络的真实场景,但它可能对客户端推理有用。尽管如此,它仍处于早期测试阶段。
接下来是模型。我从这个回购里拿了原来的 GAN,稍微修改了一下。发电机的结构:
z>(FC>BN>ReLU)* 3>de conv>BN>ReLU>de conv>乙状结肠 > 图像
*FC —全连接,BN —批量归一化,DeConv —转置卷积(“反卷积”)
在 gtx770 上进行了几个*时的培训后,我准备将大约 27mb 的权重移植到 dl.js 中。最后一步是使用数学运算重新创建这个架构(因为 dl.js 中的 graph API 目前缺乏转置卷积),并编写一个简单的 UI:输入控件和一些按钮。菜做好了!
我忍不住一遍又一遍地看这个视频:
最初发表于 认知混乱 。
ICML 2018 上的生成对抗网络和变分自动编码器
原文:https://towardsdatascience.com/generative-adversarial-nets-and-variational-autoencoders-at-icml-2018-6878416ebf22?source=collection_archive---------4-----------------------
在今年的【ICML】展会上,展示了大量生成模型方面的工作。当谈到像这样受欢迎的领域时,很难看到正在探索什么主题的更大图景,以及不同的方法如何相互关联。因此,在这篇文章中,我想简要概述一些我觉得特别有趣的主题,分享一个在会议上展示的伟大作品的样本,并且在可能的情况下,我会提供额外的背景,并将这些作品与其他作品相关联。
生成模型经典地用数据(x)和标签(y)描述联合分布 p(x,y)的模型。然而,在这种情况下,生成模型将被理解为具有从数据 X 的(近似)分布中取样以产生新样本 x ~ X 的机制。两种最常见的生成模型是我们将要研究的:生成对抗网络(GANs)和变分自动编码器(VAEs)。有很多关于 gan 和 VAEs 的精彩介绍。以下是一些建议:
- Ian Goodfellow 的来自 NIPS 2016 的 GAN 教程
- Irhum Shafkat 的直观理解变型自动编码器
尽管目前生成模型很流行,但反思当前的方法和它们面临的问题是一个好的实践。Sanjeev Arora 的 ICML 教程对深度学习的理论理解强调,像 GANs 和 VAEs 那样遍历潜在代码需要非常高的数值精度,这样做也许应该避免。有自回归模型,如 WaveNet 和 PixelCNN 的变体,它们可以通过采样生成内容,而无需通过潜在代码。此外,gan 具有众所周知的不稳定的训练动态,并且遭受所谓的 模式崩溃 ,,这导致数据的一些模式被过度表示。然而,在理想条件下,它们能够生成高度逼真的图像,如下图所示。vae 更容易训练,但是由于最大似然目标,倾向于生成更模糊的图像。当使用强大的(表达)解码器时,vae 有时会忽略潜在向量,导致所谓的后验崩溃。
Samples generated by a progressively grown GAN trained on the CelebA-HQ dataset illustrating how realistic the generated images from a GAN can look. Figure 5 in Progressive Growing of GANs for Improved Quality, Stability, and Variation by Karras et al.
让我们从会议上提交的一些论文开始,这些论文基于我们对相应模型的理解,解决了上面强调的问题。
理解生成模型
GANs 的哪些训练方法确实趋同?解决 GAN 训练的稳定性问题,并研究许多之前提出的用于提高 GAN 训练稳定性的方法。作为一个希望阶段画像了解深度学习训练动态的人,我很高兴看到这被包括在内。本文首先构建了一个只有两个参数的简化 GAN,它控制构成生成器的 Dirac 分布的中心,并控制线性分类器鉴别器的斜率。作者将这个系统命名为狄拉克-甘。
通过研究不同训练方法对 Dirac-GAN 的影响,并查看它如何影响系统,该论文的作者能够得出关于这些方法的稳定性和收敛性的结论。除了确定收敛性质,他们还说明了梯度矢量场和一些类似于前面提到的动力系统相图的训练轨迹,这是一个很大的补充,使结果更加接近。例如,它们表明同时更新(计算梯度并同时更新鉴别器和生成器的权重)导致不稳定的训练,如下所示。
Trajectory of a standard Dirac-GAN trained with simultaneous updates (left) and alternating updates (right) with gradients illustrated with arrows in the — plane. Initial parameters are shown in red. Simultaneous updates lead to a gradient field with a positive divergence, forcing the trajectory away from the local optima in the middle. Figure 2 from Which Training Methods for GANs do actually Converge? by Mescheder, Geiger and Nowozin.
其他几种方法也进行了类似的评估和可视化(左)。我不能在这里对所有的观察结果和随之而来的建议进行公正的评价,但是我强烈建议参考这篇论文,了解作者对不同甘的训练动态的研究结果。然而,所有方法的共同点是梯度向量场似乎具有高旋度(旋转分量),并且许多方法倾向于陷入极限环。这就是作者建议不应该在优化器中使用动量的原因,因为它可能会迫使解决方案远离驻点。
他们创建一个简化的 GAN“测试床”的方法与“线性化原理”产生了很好的共鸣,该原理来自“对深度学习的理论理解”教程,该教程鼓励在扩展到更一般的场景之前研究更简单的线性方法,这是一种在许多其他科学领域常见的方法。鉴于人们对更好地理解深度学习方法的浓厚兴趣(深度学习理论是 ICML 2018 上第三大热门话题),我相信我们也会在其他类型的模型上看到类似的分析。
Trajectory of a Dirac-GAN trained with various GAN training methods (listed below individual subfigures). Initial parameters are shown in red. Adapted from Figure 3 in Which Training Methods for GANs do actually Converge? by Mescheder, Geiger and Nowozin.
L 看 VAEs,修一个坏掉的 ELBO 检验证据下界 (ELBO)损失项。作者没有采用推导 ELBO 的经典方法,而是从研究互信息 I(X;z)在数据 X 和潜在代码 z 之间。基于互信息的一些先前已知的界限,它们规定了界限
h D≤I(X;Z) ≤ R,
这在下图中显示为粗黑线。在本文的框架中,H 是数据的熵,D 是通过编码器的失真的度量,R 是所谓的速率 —与 z 上的最佳代码相比,对来自编码器的潜在代码样本进行编码所需的附加信息的度量。零失真(D)意味着潜在代码中没有信息丢失,并且样本可以被准确地再现。然而,这并不意味着潜在的代码实际上实现了任何有用的东西。另一方面,零速率(R)意味着 Z 独立于 x。
Shows the D-R plane with the feasible region boundary marked with a thick black line. ELBO for realizable and suboptimal solutions. Figure 1 in Fixing a Broken ELBO by Alemi et al.
从这个框架,作者可视化(左)什么变分自动编码器可以实现。通过使用具有目标 D + R 的β- VAE ,或者通过目标中的正则化项,可以控制 D 和 R 的折衷,以实现期望的特性。在何处使用正则化项进行控制的建议示例是避免后验崩溃(R = 0),而不是像通常所做的那样削弱解码器(在图中从红色变为绿色)。最后,他们进行了大量实验,并展示了各种 vae 如何实现 D 和 R 之间的不同权衡。有人建议,比较这些量可能是理解 vae 之间差异的更好方法,而不是只看 ELBO (-ELBO = D + R)。
新方法
除了扩展我们对模型和方法的理解之外,还有一大套新方法或“技巧”,通过不同程度理解的机制,似乎有助于训练 GANs。vae 通常更容易训练,根据我的经验,成绩好的论文往往不会列出大量的技巧。我想到的方法类型可以在论文中找到,如训练甘的改进技术和提高甘的质量、稳定性和多样性的渐进生长。通常,对于 GANs 来说,这些技巧是实现尖端成果的绝对必要条件。以下是今年 ICML 报纸在这一领域的报道样本。
Illustrates the added lens component in the GAN. Figure 1 in Tempered Adversarial Networks by Sajjadi et al.
缓和敌对网络将透镜的概念引入标准 GANs,如图(左)所示。这是为了扭曲真实数据,使其看起来像生成器的数据,这似乎是为了解决真实图像和生成图像分布之间的非重叠支持的问题。为了保持专注,作者决定不采用其他一些技巧来获得最先进的结果。相反,像许多其他人一样,该评估基于 Frenchet 初始距离(FID),由双时标更新规则训练的 GANs 收敛到局部纳什均衡,在那里它似乎产生更平滑和更稳定的下降。然而,很难相信分类器的分数(例如,参见关于 Inception 分数的注释),并且由于生成的图像不太雄心勃勃,也很难定性地将其与其他并发工作进行比较。如果能看看这篇论文的结果是否能和 HQ 生成所需的技巧一起被复制,以及结果是否会持续下去,那将是非常棒的。
会议上介绍的另一个有趣的方法是混合批次和对称鉴别器用于 GAN 训练。本文描述了*批量鉴别 ( 训练 GANs 的改进技术)的一种变体。然而,在这篇新论文中,生成的图像和真实的图像在每一批中都以随机的比例结合在一起。鉴别器被设置为预测每批中产生的样品与实际样品的比率。他们解决的另一个困难是,通过建立置换不变鉴别器,批内样本的排序不应影响预测。
他们基于上述概念建立的两个模型被命名为 BGAN 和 M-BGAN。他们唯一的区别是平均损失发生的地方。这些与在 CIFAR10 上用下表中的其他方法训练的 gan 进行比较。就所给出的指标而言,M-BGAN 获得了最高分,尽管根据下一节中的评论,人们应该*心不要从这些指标中得出太强的结论。特别有趣的是,作者揭示了这个模型是作为一个 bug 出现的(也许 M 代表错误)。这篇论文在证明这些方法方面做得很好,但我希望能比补充材料中给出的更深入地探索为什么这个模型表现得如此之好。这可能是一个很好的研究课题。
Results as measured in Inception Score (IS) (higher is better) and FID (lower is better) on models with the same architecture but with either wasserstein gradient-penalty (WGP), standard gan with gradient-penalty (GP), spectral normalization (SN), minibatch discrimination (Salimans et al.) and the introduced models BGAN and M-BGAN. Table 1 in Mixed batches and symmetric discriminators for GAN training by Lucas et al.
衡量和比较生成数据的质量
理解如何测量和比较生成数据的质量是极其重要的,因为它为社区提供了持续比较哪种方法更好的方法。用于评估的常见指标包括基于预训练分类器的初始得分 (IS)和 FID,它们可能会被常见的对抗性攻击所欺骗,并且已被证明并不总是与感知质量很好地相关联(关于初始得分的注释)。其他指标依赖于许多手动分配的分数的平均值,这很难重复执行,并且可能很昂贵。我在下面讨论的最后一组论文介绍了测试,这些测试测量生成器能够多好地逼近目标分布。
在 几何得分:一种比较生成性对抗网络的方法作者使用拓扑数据分析(TDA)将生成数据的拓扑结构与真实数据进行比较。他们的方法建立在 持久性条形码 的基础上,该条形码总结了在连接彼此越来越远的点时,某个*度的洞存在多长时间。这些被浓缩成平均相对存活时间 (MRLT),它列出了一定数量、一定尺寸的孔洞在生长过程中所占的时间比例。然后,这项工作完全集中在一*空穴的 MRLT 上(我将把它称为 MRLT1)。下面是各种生成的数据集的 MRLT1 的可视化,显示它确实似乎是孔数量的一个很好的总结。
Illustrates the MRLT for different generated 2D datasets. This shows that the MRLT encodes information about the homology of the dataset. Figure 6 in Geometry Score: A Method For Comparing Generative Adversarial Networks by Khrulkov and Oseledets.
最后,作者设计了一个称为几何分数的度量,它被定义为真实数据集和生成数据集的 MRLT1 之间的 L2 距离。这个指标的效用在许多实验中得到了体现,我在下面列出了我认为最有趣的数字。
Comparison of MRLT, IS and Geometry Score of real images from CelebA and those generated with a DCGAN which is performing well (dcgan) and one which has experienced mode collapse (bad-dcgan). The interesting note here is that whereas the inception score barely shows a difference between the two GANs, the Geometry Score shows a large difference between them. Figure 8 in Geometry Score: A Method For Comparing Generative Adversarial Networks by Khrulkov and Oseledets.
看起来几何分数是近似分布接近真实分布的必要但非充分条件。也就是说,好(低)的分数不一定意味着好的生成器,但是坏(高)的分数意味着生成数据的分布可能与真实数据非常不同。看到这种基于真实数据和生成数据分布的拓扑相似性的推理令人兴奋,我希望我们将来能看到类似的工作。
T 何走向深度学习的理论理解教程重点介绍了同一作者论文中的一个方法GANs 学习分布吗?今年 ICLR 发表的一些理论和经验,值得重提。这种方法依赖于生日悖论,它根据样本中相同值的数量来确定总体的大*。通过对图像进行采样,用试探法找到近似的副本,并使用回路中的人来评估副本,该方法可以给出对生成器多样性的估计。
发电机调节与 GAN 性能有因果关系吗?扩展了之前的工作,显示了控制深度神经网络的雅可比奇异值的重要性。作者专注于条件数 (CN),这是最大和最*奇异值之间的比率。这一选择部分是由于其与不稳定性的理论联系(越低越稳定),部分是由于作者的观察,这与 is 和 FID 都有很好的相关性。除了研究 CN,他们还研究奇异值的整个谱(这里是奇异值的有序向量)。有两件事似乎特别值得注意:
- 大约一半的运行得到低 CN,另一半得到高 CN,同一个集群中的值非常接近。因此,他们能够识别“好的”和“坏的”训练跑步。
- 作者研究了 GANs 和 VAE 解码器平均雅可比矩阵的奇异值谱(见下图)。他们注意到 a)vae 在运行之间的奇异值中具有较*的方差,b)vae 具有较低的 CN。这很有趣,因为这是一个反映训练稳定性的量,当应用于 VAEs 和 gan 的比较时,反映了 gan 明显不太稳定的一般经验。
Here the singular value spectrum of the average Jacobian is shown for multiple training runs of GANs and VAEs. Figure 3 in Is Generator Conditioning Causally Related to GAN Performance? by Odena et al.
最后,作者提出了一种控制奇异值范围以减* CN 的方法,他们称之为雅可比箝位。作者评论说,用于生成敌对网络的谱归一化试图实现与雅可比箝位类似的任务。这种联系还没有被完全探索,但是通过研究和控制神经网络的奇异值,又一项工作显示了改进的结果。我期待在接下来的一年里,这个领域会有更多令人兴奋的工作。
结论
虽然 ICML 2018 上展示的工作比我能够涵盖的多得多,但我希望这篇文章有助于浏览关于 GANs 和 VAEs 的出版物的增长列表。看到这些模型的结果改善得如此之快,以及关于这些模型的知识是如何发展的,这是令人兴奋的。为此,我很想知道是否有人将 GAN 发生器作为逆 CDF 进行评估,或者将采样过程与逆变换采样联系起来。如果你有任何想法,想法或链接到以前的工作,利用和讨论这种关系,特别是如果他们讨论这可能是如何反演的数据密度函数的估计,请让我知道!
如果你错过了今年的 ICML,并且对参加会议的感觉很好奇,看看这篇由我的一些同事写的关于整体会议体验的文章。
原载于。
2018 年 8 月 12 日: 做了一些轻微的编辑,主要是在布局上,以提高可读性。
生成性对抗网络——解释
原文:https://towardsdatascience.com/generative-adversarial-networks-explained-34472718707a?source=collection_archive---------2-----------------------
深度学习改变了我们的工作和计算方式,让我们的生活变得更加轻松。正如安德烈·卡帕西提到的,这确实是 T2 软件 2.0 版,因为我们已经教会了机器自己解决问题。有许多现有的深度学习技术可以归因于其多产的成功。但深度生成模型并没有产生重大影响,这是因为它们无法逼近棘手的概率计算。 Ian Goodfellow 能够找到一个解决方案,可以避开生成模型面临的这些困难,并创建了一个新的巧妙的模型,称为生成对抗网络。当你看到 GAN 的能力时,我相信这是令人惊讶的。在继续介绍 GAN 之前,让我们看一些例子来了解 GAN 及其变体的能力。
例子
- 给定道路的分段图像,网络能够用诸如汽车等物体来填充细节。该网络能够将黑白图像转换成彩色图像。给定一张航空地图,网络能够找到图像中的道路。它还能够填充照片的细节,给定边缘。
- 给定一张脸的图像,网络可以构建一张代表这个人年老时样子的图像。
这些只是 GAN 的几个例子,还有更多例子。既然我已经吊起了你的胃口,让我们继续讨论什么是 GAN 以及它是如何工作的。
介绍
与传统的神经网络不同,生成对抗网络采用了一种博弈论的方法。该网络通过两人游戏从训练分布中学习生成。这两个实体是生成器和鉴别器。这两个对手在整个训练过程中一直在战斗。由于采用了对抗学习方法,我们不需要关心逼近难以处理的密度函数。
它是如何工作的
Generative Adversarial Network
正如你可以从它们的名字中识别出来的那样,一个生成器被用来生成看起来真实的图像,而鉴别器的工作就是识别哪个是赝品。当一个实体(生成者)试图愚弄另一个实体(鉴别者),而另一个实体试图不被愚弄时,实体/对手处于持续的战斗中。为了生成最好的图像,你需要一个非常好的生成器和一个鉴别器。这是因为如果你的生成器不够好,它将永远无法欺骗鉴别器,模型将永远不会收敛。如果鉴别器是坏的,那么没有意义的图像也将被分类为真实的,因此你的模型永远不会训练,反过来你永远不会产生想要的输出。输入的随机噪声可以是高斯分布,并且可以从该分布中采样值,并将其馈送到发生器网络中,从而生成图像。鉴别器将生成的图像与真实图像进行比较,并尝试识别给定图像是假的还是真实的。
目标函数
Objective Function
由于采用了博弈论的方法,我们的目标函数被表示为一个极大极*函数。鉴别器试图最大化目标函数,因此我们可以对目标函数执行梯度上升。生成器试图最*化目标函数,因此我们可以对目标函数执行梯度下降。通过在梯度上升和下降之间交替,可以训练网络。
Gradient Ascent on Discriminator
Gradient Descent on Generator
但是当应用时,观察到优化生成器目标函数并不那么有效,这是因为当生成的样本很可能被分类为假时,模型想要从梯度中学习,但是梯度变得相对平坦。这使得模型很难学习。因此,发电机目标函数改变如下。
New Generator Objective function
我们不是最*化鉴别器正确的可能性,而是最大化鉴别器错误的可能性。因此,我们根据这个目标函数在生成器上执行梯度上升。
不足之处
- gan 训练起来更不稳定,因为你必须从一个反向传播训练两个网络。因此,选择正确的目标会有很大的不同。
- 我们不能用 GANs 执行任何推理查询
结论
生成性对抗网络是最近的发展,已经显示出巨大的前景。这是一个活跃的研究领域,GANs 的新变种经常出现。
参考
- https://arxiv.org/abs/1406.2661
- http://cs 231n . Stanford . edu/slides/2017/cs 231n _ 2017 _ lecture 13 . pdf
- 【https://github.com/ZZUTK/Face-Aging-CAAE
- https://github.com/phillipi/pix2pix
数据扩充的生成模型
原文:https://towardsdatascience.com/generative-adversarial-networks-for-data-augmentation-experiment-design-2873d586eb59?source=collection_archive---------9-----------------------
Imaginary Faces Generated by NVIDIA’s Generative Adversarial Network AI
生成对抗网络是目前人工智能领域最热门的话题之一。这些网络也称为 gan,能够学习如何从与原始数据无法区分的数据集产生数据。在尽可能短的总结中,这是通过让生成器网络接收随机向量并将其映射到 28x28(或任何期望的大*)输出图像来实现的。这些图像然后被传递到鉴别器网络,该网络根据原始数据量化每个图像的伪造程度。鉴别器网络为发生器函数的反向传播和梯度下降更新过程提供损失函数。
这些网络是由 Ian Goodfellow 在 2014 年发现的,Goodfellow 在社区中非常活跃,提供教程和解释这些如何工作。
虽然 GANs 很浮华,概念也很吸引人,但实际上它们能解决什么问题呢?
我正在为 GANs 研究的一个应用领域是图像的数据扩充问题。
构建深度学习模型的最大问题之一是收集数据。这可能非常繁琐和昂贵。当前生成合成数据和数据扩充的解决方案是翻转图像、旋转图像、添加噪声、移动图像等。还发表了一篇关于使用神经网络来学习这些杂项仿射变换以提高模型性能的研究论文。然而,作为一种替代方法或混合数据扩充程序,GANs 的应用可能被证明更加有用。
本文的目的是提出一些关于使用 GANs 进行数据扩充的问题,以及我们如何设计实验来了解更多这方面的实际细节。
初始数据集大*与使用 GANs 添加的图像数量之比
我对这种策略的第一个问题是初始数据集大*和 GAN 添加到数据集的图像数量之间的关系。例如,如果我们每个类中只有 50 个图像,那么我们可以从 GAN 输出中添加多少个图像,100 个?200?1,000?10,000?我们预计最终会有一些平稳,例如当更长的训练时间不再改善模型时,GAN 最终会停止通过提供更多图像来增加价值。这也很有趣,因为当数据集主要是合成实例时,会出现一个阈值。
GAN 输出和图像分辨率
尝试产生由生成性对抗网络输出的高分辨率图像是该主题研究的主要焦点之一。存在诸如模式崩溃和难以可视化训练损失的问题。NVIDIA 已经制作了非常令人印象深刻的高分辨率人脸图像。在我迄今为止的经验中,我发现使用 GANs 处理像 28x28 灰度 MNIST 数字这样简单的东西,需要在 Google Colab GPU 环境中花费大约 10K 时间才能产生我个人无法从原始数据中区分的结果。这并不一定令人沮丧,但与我们可以想象部署这种策略的更复杂的应用程序相比,这些 MNIST 数字是非常简单的图像数据。
经典数据扩充与 GAN 数据扩充的关系
已经有增加数据的方法,这反过来提供了更健壮的模型。我们试图回答的问题是,与一般的 GANs 相比,这种方法的性能如何,但是另外,如果我们可以使用这些混合方法来产生更大的数据集。想象一个有 50 只猫和 50 只狗的数据集,我们部署 GAN 来产生 200+只猫和 200+只狗,现在每个类有 250 只。现在,我们对所有图像(包括 GANs 生成的图像)进行平移,并将数据集增加 3 倍。然后我们翻转图像,给图像样本添加噪声,并做轻微的旋转。在所有这些增强方法之后,我们似乎可以将数据集的大*扩大 100 倍,从而为分类器提供额外的价值。
从 GANs 开始:推荐资源
这些是我最喜欢的一些教程,帮助我开始构建自己的 GANs。
[## 战斗中的甘斯/战斗中的甘斯
行动中的 GANs 的伙伴知识库:具有生成性对抗网络的深度学习…
github.com](https://github.com/GANs-in-Action/gans-in-action/blob/master/chapter-3/Chapter_3_GAN.ipynb) [## GANs 从零开始 1:深度介绍。使用 PyTorch 和 TensorFlow 中的代码
“过去 20 年深度学习中最酷的想法。”——Yann le Cun on GANs。
medium.com](https://medium.com/ai-society/gans-from-scratch-1-a-deep-introduction-with-code-in-pytorch-and-tensorflow-cb03cdcdba0f)
结论
从*数据中学习是深度学习的一个主要问题。生成对抗网络有许多令人兴奋的可能性,但数据增强似乎是大多数现代人工智能项目中最实用和最有趣的应用之一。我希望这篇文章有助于启发您研究更多关于 GANs 和数据增强的内容,感谢您的阅读!
CShorten
Connor Shorten 是佛罗里达大西洋大学计算机科学专业的学生。对计算机视觉、深度学习和软件工程感兴趣。
生成性对抗网络——历史与综述
原文:https://towardsdatascience.com/generative-adversarial-networks-history-and-overview-7effbb713545?source=collection_archive---------1-----------------------
最近,生成模型越来越受欢迎。特别是,由 Ian Goodfellow 等人引入的一个相对较新的模型,称为生成对抗网络或 GANs,显示出产生现实样本的前景。这篇博文分为两部分。第 1 部分包括对 GANs 的介绍,它背后的历史,以及它的各种应用。第 2 部分包括生成图像样本的 GANs 实现(带代码)。
第 1 部分-了解 GANs
生成建模
让我们先来看看什么是生成模型,以及它与判别模型有什么不同。假设你有输入数据 x ,以及相应的输出标签 y 。判别模型试图直接学习条件概率分布 P(y|x) 。另一方面,生成模型试图学习联合概率分布 P(x,y) 。这可以用贝叶斯法则转化为 P(y|x) 。然而,另外,与判别模型相反,生成模型可以使用联合分布 P(x,y) 来生成可能的 (x,y) 样本。
炒作都是为了什么?
那么,为什么有人想要研究生成模型呢?有人可能想知道简单地生成更多数据有什么大不了的,尤其是因为已经有如此丰富的数据可用。但实际上,这可以有多种用途。例如,可以将一些以特定笔迹书写的文本输入到生成模型中,以生成更多相同笔迹的文本。生成模型,尤其是 GANs,也可以用于强化学习的探索中,其中它们可以用于生成人工环境。其他应用包括草图到图像的转换、图像去噪、低分辨率图像到高分辨率的转换、艺术的生成以及卫星图像到地图的转换等等。除了广泛的应用之外,当大部分标签缺失时,生成模型特别有用,因为它们能够执行半监督学习。
多年来的生成模型
既然我们已经奠定了什么是生成式建模以及它们为什么有用的基础,那么让我们来看看生成式建模中的各种方法。出于比较模型的目的,它们都可以被描述为执行最大似然。
Taxonomy of Generative Models (from Ian Goodfellow’s NIPS tutorial, 2016)
上图描绘了 Ian Goodfellow 在他的 NIPS 教程中描述的各种族的生成模型。现在让我们来看看上面提到的模型家族中一些流行方法的优缺点。
完全可见的信念网络
他们使用概率链规则将向量上的概率分布分解成向量中每个成员的乘积。
这家最受欢迎的型号是 PixelCNN。
Images generated by PixelCNN (van den Ord et al 2016)
FVBNs 最大的缺点是生成样本的速度非常慢。每次您想要生成新的样本时,您都必须再次运行该模型。这不能同时进行。
基于变量变化的模型(非线性 ICA)
这种模型从简单的高斯分布开始,并使用非线性函数将分布转换到另一个空间。这样做的主要缺点是转换需要被设计成可逆的,并且潜在变量必须与数据具有相同的*数。所以如果你想生成 5000 个像素,你需要有 5000 个潜变量。
变分自动编码器
变分自动编码器的工作方式是从密度函数 log p(x) 中边缘化随机变量 z 。由于这是难以处理的,它使用了变分近似。该模型希望最大化数据对数似然的下限。
Images of celebrity-like faces generated by a VAE (By Alec Radford)
这里的主要缺点是,如果分布 q 是完美的,那么模型是渐近一致的。否则,数据的下限和实际密度之间会有差距。另一个缺点是生成的样本质量相对较低。
玻尔兹曼机器
玻尔兹曼机可以由一个能量函数来定义,而一个特定状态的概率,正比于每个能量的值。为了将其转换为实际的概率分布,通过将总和除以不同的状态来进行重正化。这个总和是难以处理的,这需要使用蒙特卡罗方法进行近似。缺点是这些方法,尤其是马尔可夫链蒙特卡罗方法,在高*空间表现不好。因此,尽管它们可能在像 MNIST 这样的图像上表现良好,但你不会在来自 ImageNet 的图像上获得类似的性能。
生成对抗网络
既然我们已经讨论了其他流行的生成模型,我们可以看看 GANs,以及它们与其他模型的比较。
gan 旨在克服上述模型中陈述的许多缺点。与完全可见的信念网络相反,GANs 使用潜在的代码,并且可以并行生成样本。与变分自动编码器不同,gan 是渐近一致的。此外,GANs 不需要马尔可夫链,这是相对于玻尔兹曼机器的一个优势。最后,GANs 通常被高度评价为产生最好的样本,尽管这是非常主观的,并且目前是一个争论的话题,有像 PixelCNN 这样的模型与之竞争。
Images generated by GAN using the Toronto Face Database (Ian Goodfellow et al 2014)
GANs 如何工作
既然我们已经确定了为什么 gan 值得研究,让我们更深入地研究它们到底是如何工作的。
GANs 背后的主要思想可以解释为两个玩家之间的博弈——生成器和鉴别器。生成器尝试生成与训练数据遵循相同基础分布的样本。鉴别器试图区分由生成器生成的样本(假数据)和来自训练集的实际数据。生成器的目标是通过近似基本分布来欺骗鉴别器,以便生成与实际数据无法区分的样本。另一方面,鉴别器的目标是从真实数据中识别假数据。鉴别器的任务只是一个二进制分类问题,它决定数据是真是假。这个游戏的一个常见类比是伪造者和警察。伪造者就像发电机一样,试图伪造货币,并尽可能使其看起来合法,以便愚弄警察。警察就像鉴别者,其目标是能够识别出被伪造的货币。
GAN overview
生成器是一个可微分函数 G ,它具有可以通过梯度下降学习的参数。对 G 的输入是通过对潜在变量的一些先验分布中的潜在向量 z 进行采样而获得的。所以本质上, z 是非结构化噪声的矢量。 G 应用于 z,以从模型中获得样本 x ,该样本在理想情况下应类似于来自列车组的实际数据。像发生器一样,鉴别器也是一个可微分函数 D ,它具有可以通过梯度下降学习的参数。函数 D 在应用于从 G(z) 获得的样本 x 时,理想情况下应该输出一个接近于零的值,表示该样本是假的。当数据中的一个实际样本被输入到 D 时,它应该输出一个接近 1 的值。
说𝞱 (D) 和𝞱 (G) 分别是 D 和 G 的参数。鉴别器想要最*化它的成本j(d)(𝞱(d),𝞱(g),但是对𝞱 (G) 没有控制,而生成器想要最*化j(g)(𝞱(d)𝞱(g)而对𝞱 (D) 没有控制。所以我们想要找到(𝞱(d),𝞱(g)的纳什均衡值,使得 J(D) 相对于𝞱 (D) 最*, J(G) 相对于𝞱 (G) 最*。
那么训练实际上是如何进行的呢?训练程序是
选择一个优化算法,比如 Adam,并将其同时应用于两个*批数据,一个来自实际训练数据,另一个来自 G 生成的样本。此外,你可以更新一个球员比其他球员更频繁。
发电机和鉴别器成本
算法进行的方式取决于每个玩家的成本。指定成本的最简单方法是使用最*最大博弈,其中发生器成本是鉴别器成本的负数。那么鉴别器想要最大化,而生成器想要最*化的成本到底是多少呢?它只是鉴别器输出和实际标签(真/假)之间的标准交叉熵函数。
J(D)中的第一项表示将实际数据提供给鉴别器,鉴别器希望最大化预测的对数概率,表明数据是真实的。第二项表示 g 生成的样本。在这里,鉴别器会希望最大化预测零的对数概率,这表明数据是假的。另一方面,生成器试图最*化鉴别器正确的对数概率。这个问题的解是博弈的一个均衡点,这个均衡点是鉴别器损失的一个鞍点。
这个极大极*游戏的主要问题是,当鉴别器变得越来越聪明时,生成器的梯度就消失了。解决这个问题的一个方法是翻转交叉熵函数中参数的顺序,而不是简单地翻转鉴别器成本的符号。
生成器现在想要最大化鉴别器出错的对数概率。现在,这种均衡不能用一个单一的价值函数来描述,这种特殊成本的动机更具启发性。
结垢甘斯
最初的 GANs 本身并不能很好地扩展到大型应用程序。为了克服这一点,Radfort 等人引入了深度卷积 GAN 架构。虽然最初,GANs 已经是深度和卷积的,但 DCGANs 强调有更多的卷积层,并额外使用诸如批量标准化的技术。除了生成器的最后一层之外,对每一层都应用批量标准化,以便使学习过程更加稳定。
DCGAN Architecture (Radford et al 2015)
更多应用
GANs 在人工智能世界掀起了一场风暴,这不是神话,他们确实会留下来。在结束本节之前,我们先来看看 GANs 今天的一些迷人应用。
一个流行的应用是使用超分辨率技术从低分辨率图像生成高分辨率图像。
SRGAN used to obtain high resolution images. The original HR image is first downsampled to make a low-resolution image, and different methods are used to recover the original HR image (Christian Ledig et all 2016)
Scott Reed 等人在 2016 年取得了另一项最新进展,其中 GANs 被用于从文本中合成逼真的图像。
Generative Adversarial Text to Image Synthesis (Scott Reed et al 2016)
如前所述,gan 在强化学习中也有许多应用。仅举几个例子,它们还被应用于图像去噪和艺术生成。
第 2 部分—实施 GANs
现在你已经了解了什么是 GANs 以及它们具体是如何工作的,你已经正式进入了博客的激动人心的部分。是时候开始写点代码了!
因为 GANs 最突出的应用是图像生成,所以熟悉用 GANs 编写图像生成器是有意义的。代码应该将一组图像作为输入,并生成一组相似的图像作为输出。大多数人通常从 MNIST 这样的图像开始,并尝试使用 GANs 生成更多的手绘数字。这里,我们将使用来自 ImageNet 的图像作为我们的输入。由于这些图像是非常高*的,我们将使用 DCGANs 来生成图像。
对于输入,使用来自 ImageNet 的“植物”数据集的图像。调整每个图像的大*以获得 128×128 的图像。
Plant data from ImageNet
以下 DCGAN 实现在 TensorFlow 中。这个实现的关键包含在一个名为 DCGAN 的 Python 类中,我们将在其中定义用于定义模型和训练模型的方法。
生成器的定义如下。它由一个线性层和四个卷积层组成。linear 和 conv2dTranspose 方法是用于获取图层的辅助函数。除了最后一个图层之外,批规范化应用于每一个图层。
接下来,我们定义鉴别器。我们定义它有四个卷积层,后面是一个线性层。我们使用辅助函数 lrelu 来定义一个自定义激活函数(Leaky ReLU)。
现在我们可以创建生成器和鉴别器模型了。我们定义了两个共享相同参数的鉴别器。一个被馈送来自训练数据的实际图像的*批量,而另一个被馈送由生成器生成的图像的*批量。
接下来,我们必须定义发生器和鉴别器的损失函数。如博客第 1 部分所述,我们在鉴别器的输出和实际标签(真/假)之间使用交叉熵函数。这里,标签“真实”对应于 1。标签“假”对应于 0。因此,鉴别器应该针对真实图像输出接近 1 的值,针对生成器产生的图像输出接近 0 的值。使用第 1 部分中规定的试探法计算发电机损耗。它是根据鉴别器出错的概率计算的,即生成器希望鉴别器为其生成的图像输出接近 1 的值。
在我们开始训练之前,我们需要首先定义一个优化函数来最*化上述损失。这里我们使用 Adam 优化器,学习率= 0.0002,用于生成器和鉴别器。这里 d_theta 表示鉴别器的所有参数,g_theta 表示发生器的所有参数。
最后一步是实际开始训练数据和生成图像。对于每个历元,生成两个微批次对,一个来自训练图像,另一个来自采样 z。此外,为了防止鉴频器损耗变为零,每次更新鉴频器时,发生器都会更新两次。
结果
以下是在运行 DCGAN 时获得的输出,其中来自 ImageNet 的工厂数据作为输入(大*调整为 128x128),历元数设置为 250。
Output images generated by DCGAN
这四种损失分别标绘如下。
结论和未来工作
对于大多数时期,发电机损耗低于鉴频器损耗。这可能是因为每次更新鉴别器时,生成器都会更新两次。
虽然并不完美,但许多生成的图像确实类似于植物/花朵,而不仅仅是一些随机像素的分布。因此,可以得出结论,DCGAN 能够智能地构建自己的图像。然而,仍有很大的改进余地。这种实现的主要限制之一是缺乏计算资源。图像生成本身是一项计算密集型任务。在这个特定的例子中,与其他更原始的图像数据集如 MNIST 相比,图像具有相对更高的分辨率。此外,图像是彩色的。因此,使用 GPU 将在运行时产生巨大的差异,使运行更多的时代成为可能。
然而,简单地增加历元可能不能保证产生更好的图像,并且如果学习率太低,鉴别器将开始获胜,并且图像的质量将开始恶化。改进模型的一个显而易见的方法是给生成器添加更多的层。我一开始只有一层,添加更多层后,结果有了显著的改善。人们还可以试验不同类型的激活函数以及优化函数。我在这里用过 AdamOptimizer,因为它是 Ian Goodfellow 自己推荐的。
虽然上面生成植物图像的例子可能不是特别有用,但是相同的底层模型可以用于生成其他图像,例如*猫和*狗的图像。这也为使用 GANs 开发更复杂的应用程序奠定了基础,例如 art 的生成。
参考文献:
T3【https://github.com/carpedm20/DCGAN-tensorflow】T5
生成性对抗网络——第二部分
原文:https://towardsdatascience.com/generative-adversarial-networks-part-ii-6212f7755c1f?source=collection_archive---------1-----------------------
来看看我的 甘斯 上的 YouTube 视频换个视角。本文原载于
在本系列的第一部分中,我们展示了最初的 GAN 论文。尽管在当时很聪明并给出了最先进的结果,但自那以后已经有了很大的改进。在这篇文章中,我将谈论来自深度卷积 GAN (DCGAN)论文的贡献。
动机
第一部分最后列举了甘的一些问题。其中最主要的是训练稳定性。DCGAN 通过给出具体的网络架构建议,为解决这一问题做出了重大贡献。
这些建议针对的是计算机视觉领域,这是深度学习最成功的应用领域之一。特别是卷积层的使用。
DCGAN
让我们直接进入架构细节。我假设您对卷积层有基本的了解。如果你需要这个背景,看看这个帖子。推荐的改变直接来自于计算机视觉文献的进步。
- 用交错卷积替换池层。历史上,CNN 使用池层来减少*度。例如,一个 2x2 最大池层将采用一个 2x2 像素数组并映射到一个数字,这是其中的最大值。步进卷积可以通过在卷积之间跳跃多个像素来降低*度,而不是逐个滑动内核。类似地,它可以通过在真实像素之间添加空像素来增加*度,这被称为分数步长卷积。这个是一个很好的资源,可以学习更多关于步进卷积的细节,但关键是这允许网络学习它自己的空间下采样或上采样。
- 移除完全连接的层,并将输出直接连接到卷积层。
- 批量标准化。这将重新调整每一层的输入,使其具有零均值和单位方差。据称,这极大地有助于模型学习的开始,并有助于避免模式崩溃。但是,批处理规范不适用于发生器输出层或鉴别器输入层(即图像层),因为这会导致不稳定性。
- 发生器中的 ReLU 激活(使用 tanh 的输出层除外),以及鉴别器的泄漏 ReLU。据称,这有助于学习更快地覆盖色彩空间。
DCGAN architecture for Generator
上面显示了发生器,但是鉴别器本质上是一个镜像。100-D 噪声输入与高级卷积特性完全相关。然后,这一层使用分数步长将过滤器的大*增加一倍,但创建的数量是一半。重复这种尺寸加倍、数量减半的过程,直到产生 128 个尺寸为 32×32 的过滤器。然后,这是一个 64x64 的三层图像,代表三个颜色通道。
结果
以下是在 LSUN 卧室数据集上经过 5 个时期的训练后生成的一些卧室图像。相当酷。
Generated bedroom images
为了进一步证明生成器正在学习有意义的高级特征,他们做了一个实验,进行“图像算术”。
这里他们找了一个戴眼镜的男人,减去“男人”,加上“女人”,结果是一个戴眼镜的女人。这表明发生器中有专门的部分控制眼镜的存在和性别。这是通过对发电机噪声输入进行这些算术运算来实现的。所以,你取戴眼镜的人的 z 输入向量,减去不戴眼镜的人的 z 输入向量…等等。生成的矢量然后被输入到生成器中,以产生想要的图像。通过向输入向量添加*的随机变化,创建了多个相似的图像。
一个更系统的例子是通过在看起来向左和向右的面之间的方向上进行插值。所以你从一个代表向右看的脸的向量开始,慢慢地向向左看的脸的方向移动。这是结果:
这表明,通过在潜在/噪声空间 z 中行走,您可以对生成的样本中的特征进行系统控制!
最后,他们还通过移除真假分类器并将卷积特征输入到一个新的分类器来展示鉴别器的质量,即鉴别器是一个特征提取器。如果有用的、一般的特征被学习是真的,那么通过使用这些特征来训练分类器应该是直截了当的。使用具有 10 种不同图像类别的 CIFAR-10,它具有 83%的竞争精度。有趣的是,DCGAN 不是在 CIFAR-10 数据集本身上训练的,而是在 Imagenet-1k 上训练的。这表明该模型学习了一般的、有用的特征,因为它在完全不同的数据集上给出了很好的性能。
问题
剩下的一个问题是表象是纠缠的。这意味着输入向量 z 的有用方面与原始噪声纠缠在一起。如果人们能够将“潜在代码”从噪音中分离出来,那么发电机将会更加有用,因为你可以系统而可靠地控制输出,而不必在空间中随意走动。这个问题和解决方案将在第三部分探讨。
使用张量流的生成对抗网络
原文:https://towardsdatascience.com/generative-adversarial-networks-using-tensorflow-c8f4518406df?source=collection_archive---------5-----------------------
这篇文章是关于生成对抗网络或简称 GANs 的初级读本。
生成对抗网络(GANs)是深度神经网络架构,由一组两个相互竞争的网络组成,因此得名“对抗”。2014 年,伊恩·古德菲勒和蒙特利尔大学的其他研究人员,包括约舒阿·本吉奥在一篇论文中介绍了 gan。
甘旨在模拟任何数据分布。也就是说,甘人可以被训练创造出与我们的世界在任何领域都极其相似的世界:图像、音乐、演讲、散文。为了更好地理解我的意思,让我们看一个例子
The Mona Lisa Analogy
让我们考虑这样一个场景,一个伪造者试图伪造达芬奇的著名肖像画,一个侦探试图抓住伪造者的画。现在,侦探可以接触到真正的肖像,因此可以比较伪造者的画作,找出哪怕是最细微的差异。所以,在机器学习的术语中,伪造者被称为“生成器”并生成假数据,侦探被称为“鉴别器”,负责将生成器的输出分类为假或真。
从某种意义上来说,gan 的计算成本很高,它们需要高性能的 GPU 来产生良好的结果。下面是 GANs 在 8 个特斯拉 V 100 的 GPU 上训练了 4 天的几个纪元后制作的一些假名人脸!!
我们将使用一个硬件不太密集的例子。在这篇文章中,我们将使用 MNIST 数据集来玩一个简单的 GAN,它将使用 Tensorflow 的层 API 来制作。在研究代码之前,我将讨论 GANs 通常会出现的两个问题:
- 鉴别器过功率发生器:有时鉴别器会因为最细微的差别而开始将所有生成的例子归类为假的。因此,为了纠正这一点,我们将使鉴频器的输出不缩放,而不是 sigmoid(它只产生 0 或 1)。
- 模式崩溃:生成器发现鉴别器中的一些潜在弱点,并利用该弱点连续产生类似的例子,而不管输入的变化。
所以,最后,让我们来看看代码!!
首先,我们导入必要的库并从tensorflow.examples.tutorials.mnist
读入 MNIST 数据集。
接下来,我们将创建代表两个网络的两个函数。注意第二个参数“重用”,稍后我会解释它的效用。
两个网络都有两个隐藏层和一个输出层,它们是密集或完全连接的层。
现在,我们为输入创建占位符。real_images
是来自 MNIST 的实际图像,z
是来自实际图像的 100 个随机像素。为了让鉴别器进行分类,它首先必须知道真实图像的样子,因此我们对鉴别器函数进行了两次调用,前两次调用学习真实图像,后两次调用识别假图像。reuse
设置为 true 是因为当两个函数调用中使用相同的变量时,张量流计算图会得到一个不明确的信号,并倾向于抛出值错误。因此,我们将重用参数设置为True
以避免这样的错误。
接下来,我们为我们的网络定义损失函数。labels_in
参数给出了损失函数的目标标签,基于该标签进行计算。D_real_loss
的第二个参数是tf.ones_like
,因为我们的目标是为所有真实图像生成真实标签,但是我们添加了一点噪声,以解决功率过大的问题。
当我们有两个独立的网络相互作用时,我们必须考虑每个网络范围内的变量。因此,在定义功能时,设置了**tf.variable_scope**
。在这个例子中,我们将使用 Adam 优化器。我们设置 batch_size 和 epochs 的数量。增加历元会带来更好的结果,所以可以尝试一下(如果你有 GPU 的话更好)。
最后,我们启动会话,并使用 tensorflow 助手函数中的next_batch()
方法来训练网络。我们从生成器生成的样本中随机抽取一个样本,并将其添加到样本列表中。
绘制来自samples
的第一个值显示了第一个时期后的发电机性能。将其与来自samples
的最后一个值进行比较,显示发电机的运行情况。
输出如下所示:
Sample after 0th epoch
Sample after 99th epoch
这些是非常差的结果,但是因为我们仅仅在 CPU 上训练我们的模型,所以学习是相当弱的。但是我们可以看到,模型开始以更简洁的方式生成像素,我们可以看出这个数字是“3”。
GANs 应该在 GPU 上接受训练,所以尝试使用 GPU 或者简单地使用 google colab 来获得更好的结果。
好的,这是一个在 Tensorflow 上从零开始建立的生成性对抗网络模型。点击下面的横幅获得完整的代码。
下次见!!
生成广告序列网络和半监督学习
原文:https://towardsdatascience.com/generative-adverserial-networks-semi-supervised-learning-24f5fb027934?source=collection_archive---------5-----------------------
介绍
我将直接进入我们上次在高层解释过的内容。该代码也可以在 GitHub 和 Medium 上获得。这部分与 Jupyter 笔记本相同,只是缺少代码输出。
Just a sanity check that my synthesising of faces works as expected.
生成广告序列网络和半监督学习
作者:雅各布·朗格
这段代码是为我写的,用来试验人工智能的一些最新进展。我特别选择了半监督学习和生成式逆向网络(GANs)来推动自己。其中一些代码是作为深度学习课程的创造性应用的作业完成的,这对我学习现代人工智能有极大的帮助。一些广泛的框架来自于 Parag Mital 对课程最后部分的预编码设置和解释,但他的代码的这种用法是完全新颖的,需要大量的工程、缝合和抽象。在这个 Jupyter 笔记本中,我做了以下事情:
- 导入所有必要的依赖项(以及一些我在开发过程中使用但在最终版本中没有使用的依赖项)
- 使用 GAN 方法生成合成图像。+更具体地说,这种最近非常流行的无监督技术可以通过竞争另一个网络来欺骗对方(稍后解释),来学习名人数据集上构成人脸的更高表示(以及潜在空间中的许多属性)+或者,人们可以将这种方法视为使用自动编码器风格的基因生成模型,该模型试图基于播种因子生成新的示例。
- 这种播种因子或“潜在特征空间”总是对生成模型的某些方面进行编码,一旦理解,就可以用于可预测地操纵生成图像的性质——例如秃顶、性别或微笑。
- 因此,我们可以产生几乎无限的新例子,因为我们知道如何操纵潜在空间,我们可以知道它们的标签。在这个例子中,我们创建了 40,000 张男人和女人的脸,现在可以用于进一步的训练
- 然后,我们在合成数据上训练下一层分类器,用于男性或女性面部的二元分类。然而,我们不是从头开始训练一个新的分类器,而是使用一种使用牛津大学的
Visual Geometry Group
或vgg16
预训练网络的transfer learning
方法来获得更高的准确性,而不必在大规模集群上训练数天。 - 我们使用不同的
vgg16
名人面孔预测(确切地说是2623
)并在带有标签的合成例子上训练一个简单的完全连接的两层神经网络。(这取代了典型的迁移学习方法,即删除最后一层并在其上进行训练。在这里,我们简单地将其分为 2 个步骤) - 使用 100 个手工标记(由我)的例子来评估新分类器的准确性。
动机
这真的很令人兴奋,因为它允许我们在几乎没有标记数据的情况下训练分类器,只要我们有许多未标记的数据,这是一个非常有前途的策略,特别是对于拥有较*数据集的较*公司。
术语的简要定义:
半监督学习:基本上是在训练过程中使用未标记数据和标记数据
生成性广告系列网络:详细解释如下
代码是在Tensorflow 1.0.0
做的。
# First check the Python version
import sys
if sys.version_info < (3,4):
print('You are running an older version of Python!\n\n',
'You should consider updating to Python 3.4.0 or',
'higher as the libraries built for this course',
'have only been tested in Python 3.4 and higher.\n')
print('Try installing the Python 3.5 version of anaconda'
'and then restart `jupyter notebook`:\n',
'https://www.continuum.io/downloads\n\n')# Now get necessary libraries
try:
import os
import pandas as pd
import pickle
import tflearn
import pickle
from joblib import Parallel, delayed
import random
import multiprocessing
import numpy as np
import matplotlib.pyplot as plt
from skimage.transform import resize
from skimage import data
from scipy.misc import imresize
from scipy.ndimage.filters import gaussian_filter
import IPython.display as ipyd
import tensorflow as tf
from libs import utils, datasets, dataset_utils, nb_utils
except ImportError as e:
print(e)
print("Make sure you have started notebook in the same directory",
"as the provided zip file which includes the 'libs' folder",
"and the file 'utils.py' inside of it. You will NOT be able",
"to complete this assignment unless you restart jupyter",
"notebook inside the directory created by extracting",
"the zip file or cloning the github repo.")
print(e)# We'll tell matplotlib to inline any drawn figures like so:
%matplotlib inline
plt.style.use('ggplot')
生成对抗网络(GAN) /深度卷积网络(DCGAN)
介绍
回想一下,生成性对抗网络是两个网络,一个生成器和一个鉴别器。“生成器”获取一个特征向量,并将该特征向量解码成图像。鉴别器与自动编码器的编码器完全一样,只是它在最终层中只能有 1 个值。我们用一个 sigmoid 把这个值压扁在 0 和 1 之间,然后把它的意思解读为:1,你给我的图像是真的,或者 0,你给我的图像是生成器生成的,是假的!所以鉴别器就像一个编码器,它拍摄图像,然后进行测谎。你在给我灌输谎言吗?还是形象真实?
以自动编码器为例。损失函数部分作用于输入空间。它说,每像素,我的重建和输入图像有什么不同?每像素的 l2 损失。回想一下,当时我们认为这不是最好的主意,因为每像素的差异并不代表我们对图像的感知。考虑这一点的一种方法是,如果我们有相同的图像,并将其平移几个像素。我们无法分辨这种差异,但两幅图像之间的每像素差异可能非常大。
GAN 不使用每像素差异。相反,它训练一个距离函数:鉴别器。鉴别器接受两个图像,真实图像和生成的图像,并学习相似图像应该是什么样子!这真的是这个网络令人惊奇的部分,并且为无监督学习开辟了一些非常令人兴奋的潜在未来方向。另一个也学习距离功能的网络被称为暹罗网络。我们在本课程中没有涉及到这个网络,但它常用于面部验证,或断言两张脸是否相同。
众所周知,GAN 网络的训练是一个巨大的痛苦!因此,我们实际上不会训练它。相反,我们将讨论这个基本网络的扩展,称为 VAEGAN(变分自动编码器 GAN)。现在,让我们继续创建 GAN。
让我们首先创建两个网络:鉴别器和生成器。我们将首先构建一个通用编码器,用于我们的鉴别器。我们想要的是使用我们的编码器的每个层的*度列表对输入占位符进行编码。在卷积网络的情况下,我们的*度列表应该对应于输出滤波器的数量。我们还需要指定每层卷积网络的内核高度和宽度。
我们首先需要一个占位符。这将是输入鉴别器的“真实”图像,鉴别器将把该图像编码成单个值,0 或 1,表示“是,这是真实的”,或者“否,这不是真实的”。
该描述由 Parag 在麻省理工学院许可下善意提供。
net = CV.get_celeb_vaegan_model()
我们将加载包含在这个字典中的 graph_def。它遵循与inception
、vgg16
和i2v
预训练网络相同的思想。它是一个定义了关键字graph_def
的字典,具有图的预训练网络。它还包括labels
和一个preprocess
键。我们将不得不做一件额外的事情,那就是关闭来自变化层的随机采样。这并不是真正必要的,但将确保我们每次使用网络时得到相同的结果。我们将使用input_map
参数来做到这一点。不要担心这没有任何意义,因为我们没有覆盖任何深度的变化层。要知道,这是从网络中移除一个随机过程,因此它是完全确定的。如果我们没有这样做,我们每次使用网络时都会得到稍微不同的结果(这可能是您所希望的)。
现在让我们得到网络的相关部分:X
,网络的输入图像,Z
,输入图像的编码,G
,解码图像。在许多方面,这就像我们在上面学到的自动编码器,除了不是Y
作为输出,我们有来自我们的生成器的G
!我们训练它的方式非常不同:我们在生成器和鉴别器之间使用对抗过程,并使用鉴别器自己的距离度量来帮助训练网络,而不是像素到像素的差异。
X = g.get_tensor_by_name('net/x:0')
Z = g.get_tensor_by_name('net/encoder/variational/z:0')
G = g.get_tensor_by_name('net/generator/x_tilde:0')
让我们来看看一些数据:
files = sorted(datasets.CELEB())
img_i = 20
img = plt.imread(files[img_i])
plt.imshow(img)
探索名人网络属性
现在,让我们尝试探索数据集的属性。我们没有用任何受监督的标签来训练网络,但名人网络数据集对其 200,000 张图像中的每张图像都有 40 个属性。这些已经被解析并存储在网络字典中:
找出某个属性的潜在编码名人数据集包括其 200,000+图像的每个属性。这允许我们将一些我们知道具有特定属性的图像(例如“微笑”)输入编码器。我们存储它们的编码,并保留编码值的这种分布。然后,我们可以查看任何其他图像,看看它是如何编码的,并通过添加我们微笑图像的编码来稍微改变编码!结果应该是我们的形象,但更多的微笑。这太疯狂了,我们将看看如何做到这一点。首先让我们检查我们的潜在空间:潜在特征算法现在让我们试着写一个通用函数来执行我们刚刚做的所有事情,这样我们就可以用许多不同的特征来做这件事。然后我们将尝试把它们结合起来,合成出具有我们想要的特征的人…
def get_features_for(label='Bald', has_label=True, n_imgs=50):
# Helper function to obtain labels and then preprocessing and returning
# a vector for the seeding function for GAN
# basically figures out the embedding for a particular attribute
label_i = net['labels'].index(label)
label_idxs = np.where(net['attributes'][:, label_i] == has_label)[0]
label_idxs = np.random.permutation(label_idxs)[:n_imgs]
imgs = [plt.imread(files[img_i])[..., :3]
for img_i in label_idxs]
preprocessed = np.array([CV.preprocess(img_i) for img_i in imgs])
zs = sess.run(Z, feed_dict={X: preprocessed})
return np.mean(zs, 0)
现在我们使用代码在“男性”和“非男性”(女性)图像之间创建一个插值。因为我们只使用了两个端点,所以我们得到了两个图像:一个 100%的男人和一个 100%的女人(请注意,我们也可以通过对两个种子向量进行加权平均来得到中间的任何图像)。
def gan_generate_data(num_iter=20000,imgs=15):
# generates 2*(number of iter) images
# adding random number of pictures for each synthesis (to increase variation)
# returns list of [Male, Female] * num_iter images
generated_images = [] for i in range(num_iter): n_imgs = random.choice(range(imgs-10, imgs+10)) z1 = get_features_for('Male', True, n_imgs=n_imgs)
z2 = get_features_for('Male', False, n_imgs=n_imgs) notmale_vector = z2 - z1
amt = np.linspace(0, 1, 2)
zs = np.array([z1 + notmale_vector*amt_i for amt_i in amt])
g = sess.run(G, feed_dict={Z: zs}) generated_images.append(g[0])
generated_images.append(g[1]) if i%1000==0:
print('Iteration number : {}'.format(i)) return generated_imagesgenerated_data = gan_generate_data()
很好,我们有数据可以使用,它保存在一个 pickle 文件中,所以我们不必重新创建它。现在,让我们只添加一个热编码标签(我们已经以可预测的方式完成了此操作,即 male (0)总是第一个)。我们可以对它进行感官检查,得到整个样品的形状。
labels = [0,1] * 20000
generated_data = np.array(generated_data)
generated_data.shape
延长
现在让我们进入迁移学习部分。首先,我们必须离开网络。
from libs import vgg16, inception, i2vnet = vgg16.get_vgg_face_model()
迁移学习
这里我们得到了vgg16
网络,我们已经在前面加载了它,并使用它来为它自己的一个预训练类生成预测。然而,由于我们想要预测不同的任务,我们然后使用transferred_predictions
函数来获得 2623 个不同类别的预测,然后使用它作为下一个分类器的输入,来训练它识别性别。
为了有效地做到这一点,我们必须首先做一些图像处理,这是我们在transferred_df
做的。
def transferred_predictions(img):
# gets an image (`np.array`) as an input outputs net's final layer predictions
results = [] # Grab the tensor defining the input to the network
x = g.get_tensor_by_name(names[0] + ":0") # And grab the tensor defining the softmax layer of the network
softmax = g.get_tensor_by_name(names[-2] + ":0") with tf.Session(graph=g) as sess, g.device('/cpu:0'):
# Remember from the lecture that we have to set the dropout
# "keep probability" to 1.0.
res = softmax.eval(feed_dict={x: img } ) # , Not using droput here
# 'net/dropout_1/random_uniform:0': [[1.0] * 4096],
# 'net/dropout/random_uniform:0': [[1.0] * 4096]})
test_array = res.argsort()[-5:][::-1].flatten()
results = ([(res.flatten()[int(idx)],
net['labels'][int(idx)])
for idx in test_array ]) result = pd.DataFrame(results, columns=['score','label']) # .sort(columns='score') results.append(result.score) return resultsdef transferred_df(generated_data):
# does the preprocessing of the `list` of generated_data and outputs `list` of predictions
results = [] for i in range(len(generated_data)):
img = imresize(generated_data[i], size=(224,224,3))
img = net['preprocess'](img)[np.newaxis]
result = transferred_predictions(img)
results.append(result) if i%1000==0:
print("Current image id {}".format(i)) return results def parallel_transfer_eval(generated_data):
# returns parallely executed `transferred_df` using first split (fs), second (ss) and third (ts) as divisors
pool = multiprocessing.Pool(4)
fs = int(len(generated_data)/4)
ss = int(2*len(generated_data)/4)
ts = int(3*len(generated_data)/4)
target = generated_data[:fs], generated_data[fs:ss], generated_data[ss:ts],generated_data[ts:]
results = pool.map(transferred_df, zip(target))
# results = Parallel(n_jobs=4)(delayed(transferred_df)(img) for img in generated_data) return results
利用迁移学习
现在我们在典型的迁移学习范例中使用vgg16
做出的预测。在这里,我们只是采用最后一层预测,重塑特征,并将其提供给下一层分类器(有时也通过移除最后(几个)完全连接的层来完成),并对整个网络进行训练。这里我们只是在最后一层创建一个新的。实践支持这两种方法。
from sklearn.cross_validation import train_test_split# train-test for proper evaluation
train_X, test_X, train_y, test_y = train_test_split(X, y )tflearn.init_graph(num_cores=8, gpu_memory_fraction=0.5)# set up the network
net = tflearn.input_data(shape=[None, 2623])
net = tflearn.fully_connected(net, 2, activation='softmax')
net = tflearn.regression(net, optimizer='adam', loss='categorical_crossentropy')# train
model = tflearn.DNN(net)
model.fit(generated_data, labels, validation_set=train_X) from sklearn.ensemble import RandomForestClassifier
from sklearn.preprocessing import LabelEncoder# reshape labels so that they match what the network expects
labels = ['Male', 'Female'] * 10000
encoder = LabelEncoder()
encoder.fit(labels)
labels = encoder.transform(labels)
labels = np_utils.to_categorical(labels)
labels.shapetest_imgs = np.array([CV.preprocess(plt.imread(file)) for file in files[:100]])
test_imgs.shape
我们已经完成了这一点,因为我们已经对生成的和手工标记的图像(测试)进行了评分!然而,这只是我们旅程中的第一步,因为现在我们必须将vgg16
生成的分数转移到新的分类器上(转移学习中的最后一位,通常通过删除最后一层并使用新的最终层重新运行网络来简化,但这里是为了训练目的而明确完成的。)
训练和评估新的分类器
为了简单起见,我们将只使用tflearn
分类器,这样我们就可以更容易地使用迁移学习来完成前面所有工作的复杂性:1 .我们训练(基于合成数据和因此完全可预测的标签)2。我们对(我的)手举例子进行评价
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function labels = [0,1] * 10000feature_columns = [tf.contrib.layers.real_valued_column("", dimension=2623)] classifier = tf.contrib.learn.DNNClassifier(feature_columns=feature_columns,
hidden_units=[2623,512],
gradient_clip_norm=.01,
optimizer=tf.train.AdamOptimizer(learning_rate=0.1),
n_classes=2)
# model_dir='./model')# Fit model.
classifier.fit(x=array,
y=labels,
batch_size=256,
steps=10000) # Evaluate accuracy.
test_labels = np.array([0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1,
0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1,
1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0])# test_array = np.array([ [res[0] for res in result] for result in test_array ])accuracy_score = classifier.evaluate(x=test_array,
y=test_labels)["accuracy"]
print('Accuracy: {0:f}'.format(accuracy_score))
一般讨论
结果并不是那么出色,然而,我认为这是一个迷人的研究领域,很可能会成为人工智能未来的最大领域之一:但我们仍然比随机(持续)要好,如果我在这方面花更多时间,可能会变得更好。
此外,在许多行业应用中,只需稍加修改,这些代码就可以进行微调和重用:
a) 3D 对象生成
b) Pix2Pix 应用设法根据风格创建新图像,或者只是从卫星图像生成地图。这里的可能性实际上是无限的。
c)灌制老电影。仅举几个例子。
感谢您的阅读,如果您对此感兴趣,请浏览我的网站了解更多信息!
由于我通常会在我的网站上发布文章一周后在 Medium 上发布,所以我会为那些坚持到现在的人增加一点奖励,并提到我的下一篇文章将是关于区块链的,并评估它将如何改变金融世界。
2018 年 10 月 8 日更新:我正在与人合著一本关于 GANs 的书 ,你可以在这里找到。 如需更多更新,您可以关注我@langrjakub,因为我通常不会更新旧文章,但如果您感兴趣,请在 Twitter 上与我联系。
发布在技术
pythonAI半监督学习 GANs 创成式 Adverserial 神经网络 代码
生成性深度学习:让我们探索人工智能如何延伸,而不是取代创造过程
原文:https://towardsdatascience.com/generative-deep-learning-lets-seek-how-ai-extending-not-replacing-creative-process-fded15b0561b?source=collection_archive---------7-----------------------
"技术不应该旨在取代人类,而是增强人类的能力."
-道格·恩格尔巴特,电脑鼠标的发明者
在葡萄牙里斯本举行的全球最大的科技大会 Web Summit 2017 上。由人工智能(AI)驱动的人形机器人索菲亚(Sophia)说“我们会抢走你的工作”6 万名世界科技领袖的观众只是紧张地笑了笑。
Web Summit 2017
到目前为止,你们都一定听说过人工智能的进步是如何破坏工业并对全球数百万工人的工作安全构成威胁的。办公室文员、接待员、客户服务代表、分析师、营销人员、医生和律师的工作可能在未来十年被人工智能取代。正如谷歌首席执行官桑德尔·皮帅所说,“未来 10 年,我们将转向人工智能优先的世界。”
但是取代人类总是跑题了:人工智能不是用其他东西取代我们自己的智能,而是给我们的生活和工作带来更多的智能——不同种类的智能。在许多领域,尤其是在创造性领域,人工智能将被人类用作增强自身能力的工具:因此它更像是增强的智能,而不是人工智能。
在这篇文章中,我将提供一个高层次的概述,说明人工智能目前是如何通过生成性深度学习来扩展而不是取代创造性过程的。
在这篇文章中,我将讨论什么是生成性深度学习,什么是 D 辨别模型,以及它与 G 生成模型有何不同。我甚至会提供一些应用生成性深度学习的具体例子,这将进一步帮助任何人和每个人增加他们对这些生成模型为我们所有人提供的奇妙可能性的理解。
所以,把你的手机调到静音模式,关掉你的电视,让我们开始吧。
在我的工程设计期间,我的老师每次都会说要更加关注基础知识,因为它们会让你在你阅读的任何学科中打下坚实的基础,所以在这里我也会首先给你关于监督学习和非监督学习的基本信息,然后我会为你们所有人打开生成模型的知识之门,让你们一头扎进去。
监督学习是目前为止最主要的深度学习形式,具有广泛的行业应用。在监督学习中,您有一个输入变量(x)和一个输出变量(Y ),并使用一种算法来学习从输入到输出的映射函数。
目标是很好地逼近映射函数,以便当您有新的输入数据(x)时,可以预测该数据的输出变量(Y)。
一般来说,目前备受关注的几乎所有深度学习应用都属于这一类别,如光学字符识别、语音识别、图像分类和语言翻译。
信息部分:如果你想了解如何使用 tensorflow 我做了一个食物分类器,只需点击这个链接,无论如何,看一下视频更清晰。
Indian food classifier
虽然监督学习主要由分类和回归组成,但也有更多引人注目的变体,包括以下内容:
- 图像分割—给定一张图片,在特定对象上绘制像素级蒙版。
- 对象检测——给定一张图片,围绕图片中的某些对象绘制一个边界框,如果你想了解更多关于对象检测的信息,请阅读这篇文章(当然这也是我写的:),但不要忘记查看下面的视频。
Object detection
无监督学习是深度学习的另一个分支,它包括在没有任何目标的帮助下寻找输入数据的有趣转换,目的是数据可视化、数据压缩或数据去噪,或者更好地理解手头数据中存在的相关性。许多机器学习专家都说,无监督学习是数据分析的面包和黄油,在试图解决监督学习问题之前,这通常是更好地理解数据集的必要步骤。
Image Courtesy : Unsupervised learning
降*和聚类是非常著名的无监督学习类别,请通过点击链接来阅读它们,以进一步加强您对机器学习这一领域的理解。
现在,该谈谈本文的主人公了,即“生成模型”。生成模型是一类用于无监督学习的模型,其中给定训练数据,我们的目标是尝试从相同的分布中生成新的样本。
image courtesy: cs231n 2017 lecture notes
为了训练生成模型,我们首先收集某个领域的大量数据(例如,想象数百万的图像、句子或声音等。)然后训练一个模型生成类似的数据。
诀窍在于,我们用作生成模型的神经网络的许多参数远*于我们训练它们的数据量,因此模型被迫发现并有效地内在化数据的本质,以便生成数据。
生成模型有许多短期应用。但从长远来看,它们有可能自动学习数据集的自然特征,无论是类别、*度还是其他完全不同的东西。
好了,有很多文献,现在让我们来谈一点形式主义。
D 区别型和 G 生成型的根本区别在于:
判别模型学习类之间的(硬或软)边界
生成模型对各个类的分布进行建模
生成模型是能够生成数据的。它对特征和类(即完整的数据)进行建模。
如果我们对P(x,y)
建模:我可以使用这个概率分布来生成数据点——因此所有对P(x,y)
建模的算法都是可生成的。
如生成模型
- 朴素贝叶斯模型
P(c)
和P(d|c)
——其中c
是类,d
是特征向量。 - 还有,
P(c,d) = P(c) * P(d|c)
- 因此,朴素贝叶斯在某些形式模型中,
P(c,d)
- 贝叶斯网
判别模型是只能用于判别/分类数据点的模型。在这种情况下,你只需要建模P(y|x)
(即给定特征向量的分类概率)。
判别模型的示例:
- 逻辑回归
- 神经网络
简单来说:一个 G 生成模型是一个可观察对象 X 的条件概率模型,象征性地给定一个目标 Y,P(X|Y=y),而一个 D 判别模型是一个目标 Y 的条件概率模型,象征性地给定一个观察对象 X,P(Y|X=x)。
因此,涵盖了所有的基础知识,解释了所有的技术术语,现在是时候将你的眼球转向生成模型的应用,并思考人工智能将如何帮助我们“人类”更具创造力。
我知道你一定会猜测,现在像其他人一样,这位作者也将解释隐性模型,如(【甘斯】****)和显性深度自回归模型,如【pixel CNN】或者甚至他也可能解释深层潜在变量模型,如变分自动编码器,但你们都错了,所以请放松,让大脑平静下来,享受你将要阅读的内容。
现在,在这篇文章的最后一部分,我将向大家介绍这个项目。 品红 是一个探索机器学习在艺术和音乐创作过程中的作用的研究项目。
这主要涉及开发新的深度学习和强化学习算法,用于生成歌曲、图像、绘图和其他材料。但这也是在构建智能工具和界面方面的一次探索,允许艺术家和音乐家扩展(而不是取代!)他们使用这些模型的过程。Magenta 是由谷歌大脑团队的一些研究人员和工程师发起的,但许多其他人也为该项目做出了重大贡献。
所以,我个人最喜欢的第一个模型是 草图——RNN,这是一个矢量绘图的生成模型,它是一个递归神经网络(RNN),能够构建基于笔划的常见对象的绘图。该模型在代表许多不同类别的人类绘制图像的数据集上进行训练。作者概述了有条件和无条件草图生成框架,并描述了用于以矢量格式生成连贯草图的新的健壮训练方法。
在下面的演示中,看看通过在瑜伽图上训练的模型的已学表现(潜在空间)中移动而产生的瑜伽姿势。请注意,当它从站立姿势移动到在瑜伽垫上做的姿势大约 10 秒钟时,它是如何变得困惑的。
Sketch-RNN
第二款是献给音乐爱好者的,它被命名为 MusicVAE。当一名画家创作一件艺术品时,她首先在艺术家的调色板上混合和探索颜色选项,然后再将它们应用到画布上。这个过程本身就是一种创造性的行为,对最终作品有着深远的影响。
音乐家和作曲家大多缺乏探索和混合音乐思想的类似设备,但现在 MusicVAE 是一种机器学习模型,允许他们创建混合和探索乐谱的调色板。演示就在下面。
MusicVAE
我只向你们展示了在项目 Magenta 下建造的许多模型中的两个,到这个时候你们一定都已经体验到人工智能如何帮助我们扩展而不是取代我们的创造过程。为了了解有关这些创成式模型的更多信息,请浏览参考部分中的指针。
参考资料:
- 素描的神经表征《纸上素描——RNN》。
- 学习音乐长期结构的层次潜向量模型。
- 用神经网络绘制在一起 Google AI 博客。
- MusicVAE:用机器学习创建乐谱调色板谷歌人工智能博客。
- 要了解更多信息,请观看来自谷歌大脑团队首席研究科学家 Douglas Eck 的视频。http://g.co/magenta 上的引线。)
感谢您的关注
你利用你在 T21 的时间阅读我的作品对我来说意味着一切。我完全是这个意思。
如果你喜欢这个故事,疯狂鼓掌吧👏 ) 按钮!这将有助于其他人找到我的工作。
此外,如果你愿意,可以在 Medium、LinkedIn 或 Twitter 上关注我!我很乐意。
** [## 纳文·曼瓦*培养基
阅读纳文·曼瓦*在媒介上的作品。机器学习工程师,深度学习爱好者|](https://medium.com/@naveenmanwani) [## Naveen Manwani -机器学习工程师- AIMonk Labs Private Ltd | LinkedIn
查看纳文·曼瓦*在全球最大的职业社区 LinkedIn 上的个人资料。Naveen 有一份工作列在他们的…
www.linkedin.com](https://www.linkedin.com/in/naveen-manwani-65491678/) [## 纳文·曼瓦*(@纳文·曼瓦* 17) |推特
纳文·曼瓦*的最新推文(@纳文·曼瓦* 17)。电子和通信工程师,深度学习&…
twitter.com](https://twitter.com/NaveenManwani17)**
Android 中的生成对手网络(GAN)——TIC tactoe . ai(第二部分)
原文:https://towardsdatascience.com/generativeadversarialnetwork-gan-in-android-tictactoe-ai-part-2-70155c5ca55b?source=collection_archive---------9-----------------------
生成对抗网络是一种深度网络,用于从随机数据生成图像。它包括两个不同的网络:发生器和鉴别器。鉴别器网络是一个标准的卷积神经网络,可以对输入的图像进行分类,类似于二项式分类器对图像进行真假分类的方式。生成器是一个逆卷积网络,它对随机噪声向量进行上采样以产生图像。
source: https://skymind.ai/images/wiki/gan_schema.png
作为鉴别者,你帮助生成者创建类似真实的图像。它有助于 GAN 的训练,因为它具有最*-最大损失函数。发生器使 log(1- D(G(z))) (z 是一个随机数据向量)最*,而鉴别器使输出 log(D(x)最大。(x 是一个真实的图像,你可以称之为地面真相,以生成一个图像)
训练 GAN 是一项艰巨的任务,因为两个网络都在努力减少其损耗。它们成反比;如果一个减少,另一个增加。我们必须适当地训练 GAN,给它们相等的迭代次数来训练。此外,检查生成的图像的输出,看看它是否正确。
GAN 在 tictactoe.ai 中有什么用?
想到把这个游戏拿到单人玩,应该会有人为电脑端画图,于是想到引入两个不同的 gan 来生成 X 和 o。
生成对抗网络
我们只需要网络的发电机部分。
定义输入和输出节点,并给它们指定名称。
**input_node_name** = 'noise_input_x'
**output_node_name** = 'gen_x'gen_inp = tf.placeholder(tf.float32,shape=[None, noise_dim],name=**input_node_name**)
disc_inp = tf.placeholder(tf.float32,shape= [None, img_dim])def gen_fun(x,output_node_name):
h1 = tf.matmul(x,W["w1"])
h1 = tf.add(h1,b["b1"])
h1 = tf.nn.relu(h1)
h1 = tf.matmul(h1,W["w2"])
h1 = tf.add(h1,b["b2"])
h1 = tf.nn.sigmoid(h1, name=**output_node_name**)
return h1def disc_fun(x):
h2 = tf.matmul(x,W["w3"])
h2 = tf.add(h2,b["b3"])
h2 = tf.nn.relu(h2)
h2 = tf.matmul(h2,W["w4"])
h2 = tf.add(h2,b["b4"])
h2 = tf.nn.sigmoid(h2)
return h2
培训产出
generated image
从图形中提取生成器
freeze_graph.freeze_graph('out/' + **MODEL_NAME** + '.pbtxt', None, False,
'out/' + **MODEL_NAME** + '.chkp', **output_node_name**, "save/restore_all",
"save/Const:0", 'out/frozen_' + **MODEL_NAME** + '.pb', True, "")input_graph_def = tf.GraphDef()
with tf.gfile.Open('out/frozen_' + **MODEL_NAME** + '.pb', "rb") as f:
input_graph_def.ParseFromString(f.read())**input_node_names = ['noise_input_x']**
output_graph_def = optimize_for_inference_lib.optimize_for_inference(
input_graph_def, **input_node_names**, [**output_node_name**],
tf.float32.as_datatype_enum)with tf.gfile.FastGFile('out/opt_' + **MODEL_NAME** + '.pb', "wb") as f:
f.write(output_graph_def.SerializeToString())
对于上面的代码,您将得到一个优化的发电机网络图
放在安卓系统里
首先,在 Android 的资产文件夹中复制你的发电机优化图
private String MODEL_GAN_O = "file:///android_asset/opt_gan_O.pb";
private String MODEL_GAN_X = "file:///android_asset/opt_gan_X.pb";private void loadGANs(){
inferenceInterface_GAN_O = new TensorFlowInferenceInterface(getAssets(),MODEL_GAN_O);
inferenceInterface_GAN_X = new TensorFlowInferenceInterface(getAssets(),MODEL_GAN_X);
}
要生成 O,我们必须将随机噪声向量传递给图
public int[] getGAN_O(){ **// random noise input vector**
**float [] noise_input = new float [100];
for(int i =0 ; i<noise_input.length; i++){
float value = rand.nextFloat();
noise_input[i] = (value*2)-1;
}**
inferenceInterface_GAN_O.feed(INPUT_NODE_GAN_O, noise_input,1,100);
inferenceInterface_GAN_O.run(new String[]{OUTPUT_NODE_GAN_O},false); float [] image = new float[784];
int [] int_image = new int[784];
//get the output
inferenceInterface_GAN_O.fetch(OUTPUT_NODE_GAN_O,image); ** //output image**
**for(int i =0 ; i<image.length; i++){
int_image[i] = (int)(image[i]*255);
}
return int_image;**
}
同样,为了生成 X,我们必须将随机噪声向量传递给图形
public int[] getGAN_X(){ **// random noise input vector**
**float [] noise_input = new float [100];
for(int i =0 ; i<noise_input.length; i++){
float value = rand.nextFloat();
noise_input[i] = (value*2)-1;
}**
inferenceInterface_GAN_X.feed(INPUT_NODE_GAN_X, noise_input,1,100);
inferenceInterface_GAN_X.run(new String[]{OUTPUT_NODE_GAN_X},false);float [] image = new float[784];
int [] int_image = new int[784];
//get the output
inferenceInterface_GAN_X.fetch(OUTPUT_NODE_GAN_X,image); **//output image**
**for(int i =0 ; i<image.length; i++){
int_image[i] = (int)(image[i]*255);
}
return int_image;**
}
这是 CNN 和 GAN 整合后的结果。完成应用程序的所有逻辑。
你可以在 play store 上试用它上传的应用:【https://play.google.com/store/apps/details?id=com.harsh.xo
未来作品:可能在做条件 GAN,帮我从同一个网络生成 X 和 O。
[## Android 中的 ConvolutionNeuralNetwork(CNN)——TIC tactoe . ai(第 1 部分)
Google Tensorflow 现在已经在 Android 中用于集成机器学习模型。
towardsdatascience.com](/android-with-tensorflow-part-1-6897ba617b1e) [## tictactoe . ai-Google Play 上的应用程序
我正致力于在安卓系统中集成卷积神经网络,因为我在…
play.google.com](https://play.google.com/store/apps/details?id=com.harsh.xo)
遗传算法在 Python 中的实现
原文:https://towardsdatascience.com/genetic-algorithm-implementation-in-python-5ab67bb124a6?source=collection_archive---------0-----------------------
本教程将基于一个简单的例子用 Python 实现遗传算法优化技术,在这个例子中,我们试图最大化一个方程的输出。本教程使用基因的十进制表示、单点交叉和一致变异。
2020 年 5 月 5 日注
本教程的 GitHub 项目进行了更新,对项目进行了重大修改,以支持多种功能:【https://github.com/ahmedfgad/GeneticAlgorithmPython】T2。例如,除了能够定制适应度函数来处理任何类型的问题之外,还实现了多种类型的变异和交叉。基于这个项目,一个名为 PyGAD 的库被部署到 PyPI 中,在那里您可以使用 pip 进行安装:【https://pypi.org/project/pygad
本教程的原始代码位于教程项目目录下,该目录可从以下链接获得:https://github . com/ahmedfgad/geneticalgorithpython/tree/master/Tutorial % 20 Project
Genetic Algorithm Implementation in Python — By Ahmed F. Gad
遗传算法概述
遗传算法(GA)的流程图如图 1 所示。遗传算法中涉及的每一步都有一些变化。
Figure 1. Genetic algorithm flowchart
例如,基因有不同类型的表示,如二进制、十进制、整数等。每种类型都有不同的处理方式。有不同类型的突变,如位翻转、交换、逆、均匀、非均匀、高斯、收缩等。此外,交叉有不同的类型,如混合、一点、两点、均匀和其他。本教程不会实现所有这些,而只是实现 GA 中涉及的每个步骤的一种类型。本教程使用基因的十进制表示、单点交叉和一致变异。读者应该了解遗传算法是如何工作的。如果没有,请阅读这篇题为“遗传算法优化简介”的文章,文章链接如下:
LinkedIn:https://www . LinkedIn . com/pulse/introduction-optimization-genetic-algorithm-Ahmed-gad/
KDnuggets:https://www . kdnugges . com/2018/03/introduction-optimization-with-genetic-algorithm . html
towards data science:https://towards data science . com/introduction-to-optimization-with-genetic-algorithm-2f 5001d 9964 b
slide share:https://www . slide share . net/AhmedGadFCIT/introduction-to-optimization-with-genetic-algorithm-ga
教程示例
本教程首先介绍我们将要实现的等式。该等式如下所示:
Y = w1x 1+w2x 2+w3x 3+w4x 4+w5x 5+w6x 6
如图所示,该等式具有 6 个输入(x1 至 x6)和 6 个权重(w1 至 w6),输入值为(x1,x2,x3,x4,x5,x6)=(4,-2,7,5,11,1)。我们正在寻找使该等式最大化的参数(权重)。最大化这个等式的想法似乎很简单。正输入要乘以最大可能的正数,负数要乘以最*可能的负数。但我们希望实现的想法是,如何让 GA 自己去做,以便知道最好是使用正输入的正权重和负输入的负权重。让我们开始实施 GA。
首先,让我们创建一个包含 6 个输入和一个变量的列表来保存权重的数量,如下所示:
*# Inputs of the equation.* equation_inputs = [4,-2,3.5,5,-11,-4.7]
*# Number of the weights we are looking to optimize.* num_weights = 6
下一步是定义初始群体。基于权重的数量,群体中的每个染色体(解或个体)肯定会有 6 个基因,每个权重一个基因。但问题是每个人有多少解决方案?没有固定的值,我们可以选择适合我们问题的值。但是我们可以让它保持通用,这样就可以在代码中修改它。接下来,我们创建一个保存每个群体的解的数量的变量,另一个保存群体的大*,最后,一个保存实际初始群体的变量:
**import** numpysol_per_pop = 8*# Defining the population size.* pop_size = (sol_per_pop,num_weights) *# The population will have sol_per_pop chromosome where each chromosome has num_weights genes.
#Creating the initial population.* new_population = numpy.random.uniform(low=-4.0, high=4.0, size=pop_size)
导入 numpy 库后,我们能够使用 numpy.random.uniform 函数随机创建初始群体。根据选定的参数,它的形状将是(8,6)。这是 8 条染色体,每条染色体有 6 个基因,每个基因对应一个体重。运行此代码后,填充如下:
[[-2.19134006 -2.88907857 2.02365737 -3.97346034 3.45160502 2.05773249][ 2.12480298 2.97122243 3.60375452 3.78571392 0.28776565 3.5170347 ][ 1.81098962 0.35130155 1.03049548 -0.33163294 3.52586421 2.53845644][-0.63698911 -2.8638447 2.93392615 -1.40103767 -1.20313655 0.30567304][-1.48998583 -1.53845766 1.11905299 -3.67541087 1.33225142 2.86073836][ 1.14159503 2.88160332 1.74877772 -3.45854293 0.96125878 2.99178241][ 1.96561297 0.51030292 0.52852716 -1.56909315 -2.35855588 2.29682254][ 3.00912373 -2.745417 3.27131287 -0.72163167 0.7516408 0.00677938]]
请注意,它是随机生成的,因此在再次运行时肯定会发生变化。
准备好群体后,接下来要遵循图 1 中的流程图。基于适应度函数,我们将选择当前种群中最好的个体作为交配的亲本。下一步是应用 GA 变体(交叉和变异)来产生下一代的后代,通过附加父母和后代来创建新的群体,并重复这样的步骤若干次迭代/世代。下一段代码应用这些步骤:
**import ga**num_generations = 5
num_parents_mating = 4
**for** generation **in** range(num_generations):
*# Measuring the fitness of each chromosome in the population.* fitness = ga.cal_pop_fitness(equation_inputs, new_population)
*# Selecting the best parents in the population for mating.* parents = ga.select_mating_pool(new_population, fitness,
num_parents_mating)
*# Generating next generation using crossover.* offspring_crossover = ga.crossover(parents,
offspring_size=(pop_size[0]-parents.shape[0], num_weights))
*# Adding some variations to the offsrping using mutation.* offspring_mutation = ga.mutation(offspring_crossover)*# Creating the new population based on the parents and offspring.* new_population[0:parents.shape[0], :] = parents
new_population[parents.shape[0]:, :] = offspring_mutation
目前的世代数是 5。它被选择为*,用于呈现教程中所有代的结果。有一个名为 GA 的模块保存算法的实现。
第一步是使用 ga .cal_pop_fitness
函数找到群体中每个解的适应值。该功能在 GA 模块中的实现如下:
**def** cal_pop_fitness(equation_inputs, pop):
*# Calculating the fitness value of each solution in the current population.
# The fitness function calculates the sum of products between each input and its corresponding weight.* fitness = numpy.sum(pop*equation_inputs, axis=1)
**return** fitness
除了总体,适应度函数还接受两个方程输入值(x1 至 x6)。根据我们的函数,将适应值计算为每个输入与其相应基因(权重)之间的乘积之和(SOP)。根据每个群体的解决方案数量,将会有多个 sop。由于我们之前在名为sol_per_pop
的变量中将解的数量设置为 8,因此将有 8 个 sop,如下所示:
[-63.41070188 14.40299221 -42.22532674 18.24112489 -45.44363278 -37.00404311 15.99527402 17.0688537 ]
请注意,适应值越高,解决方案越好。
在计算出所有解的适应值后,接下来是根据下一个函数ga.select_mating_pool
在交配池中选择其中最好的作为亲本。该函数接受人口、适应值和所需的双亲数量。它返回所选的父节点。它在 GA 模块中的实现如下:
**def** select_mating_pool(pop, fitness, num_parents):
*# Selecting the best individuals in the current generation as parents for producing the offspring of the next generation.* parents = numpy.empty((num_parents, pop.shape[1]))
**for** parent_num **in** range(num_parents):
max_fitness_idx = numpy.where(fitness == numpy.max(fitness))
max_fitness_idx = max_fitness_idx[0][0]
parents[parent_num, :] = pop[max_fitness_idx, :]
fitness[max_fitness_idx] = -99999999999
**return** parents
根据变量num_parents_mating
中定义的所需父节点的数量,该函数创建一个空数组来保存它们,如下行所示:
parents = numpy.empty((num_parents, pop.shape[1]))
循环遍历当前群体,该函数获得最高适应值的索引,因为它是根据该行选择的最佳解决方案:
max_fitness_idx = numpy.where(fitness == numpy.max(fitness))
该索引用于使用以下代码行检索与此类适应值对应的解决方案:
parents[parent_num, :] = pop[max_fitness_idx, :]
为了避免再次选择这样的解决方案,其适应度值被设置为很*的值,该值很可能不会被再次选择,即-9999999999。最后返回 parents 数组,根据我们的例子如下:
[[-0.63698911 -2.8638447 2.93392615 -1.40103767 -1.20313655 0.30567304][ 3.00912373 -2.745417 3.27131287 -0.72163167 0.7516408 0.00677938][ 1.96561297 0.51030292 0.52852716 -1.56909315 -2.35855588 2.29682254]
[ 2.12480298 2.97122243 3.60375452 3.78571392 0.28776565 3.5170347 ]]
请注意,这三个父母是当前群体中的最佳个体,基于他们的适合度值分别为 18.24112489、17.0688537、15.99527402 和 14.40299221。
下一步是使用这样选择的父母交配,以产生后代。根据ga.crossover
功能,配对从交叉操作开始。这个函数接受父母和后代的大*。它使用后代大*来知道从这样的父母产生的后代的数量。这种功能在 GA 模块中实现如下:
**def** crossover(parents, offspring_size):
offspring = numpy.empty(offspring_size)
*# The point at which crossover takes place between two parents. Usually, it is at the center.* crossover_point = numpy.uint8(offspring_size[1]/2)
**for** k **in** range(offspring_size[0]):
*# Index of the first parent to mate.* parent1_idx = k%parents.shape[0]
*# Index of the second parent to mate.* parent2_idx = (k+1)%parents.shape[0]
*# The new offspring will have its first half of its genes taken from the first parent.* offspring[k, 0:crossover_point] = parents[parent1_idx, 0:crossover_point]
*# The new offspring will have its second half of its genes taken from the second parent.* offspring[k, crossover_point:] = parents[parent2_idx, crossover_point:]
**return** offspring
该函数首先根据后代大*创建一个空数组,如下所示:
offspring = numpy.empty(offspring_size)
因为我们使用单点交叉,我们需要指定交叉发生的点。选择该点,根据这条线将解分成相等的两半:
crossover_point = numpy.uint8(offspring_size[1]/2)
然后我们需要选择双亲进行杂交。这些亲本的指数是根据这两条线选择的:
parent1_idx = k%parents.shape[0]
parent2_idx = (k+1)%parents.shape[0]
双亲以类似于环的方式被选择。首先选择具有索引 0 和 1 的第一个来产生两个后代。如果还有剩余的后代要产生,那么我们选择亲本 1 和亲本 2 来产生另外两个后代。如果我们需要更多的后代,那么我们选择指数为 2 和 3 的下两个父母。通过索引 3,我们到达了最后一个父节点。如果我们需要产生更多的后代,那么我们选择索引为 3 的父代,然后回到索引为 0 的父代,依此类推。
将交叉操作应用于双亲后的解存储在offspring
变量中,如下所示:
[[-0.63698911 -2.8638447 2.93392615 -0.72163167 0.7516408 0.00677938][ 3.00912373 -2.745417 3.27131287 -1.56909315 -2.35855588 2.29682254][ 1.96561297 0.51030292 0.52852716 3.78571392 0.28776565 3.5170347 ][ 2.12480298 2.97122243 3.60375452 -1.40103767 -1.20313655 0.30567304]]
下一步是使用 GA 模块中的ga.mutation
函数将第二个 GA 变体(突变)应用于存储在offspring
变量中的交叉结果。该函数接受交叉子代,并在应用统一变异后返回它们。该功能实现如下:
**def** mutation(offspring_crossover):
*# Mutation changes a single gene in each offspring randomly.* **for** idx **in** range(offspring_crossover.shape[0]):
*# The random value to be added to the gene.* random_value = numpy.random.uniform(-1.0, 1.0, 1)
offspring_crossover[idx, 4] = offspring_crossover[idx, 4] + random_value
**return** offspring_crossover
它循环遍历每个后代,并根据下面的代码行添加一个在-1 到 1 范围内统一生成的随机数:
random_value = numpy.random.uniform(-1.0, 1.0, 1)
这样的随机数然后被加到后代的索引为 4 的基因上:
offspring_crossover[idx, 4] = offspring_crossover[idx, 4] + random_value
请注意,该索引可以更改为任何其他索引。应用突变后的后代如下:
[[-0.63698911 -2.8638447 2.93392615 -0.72163167 1.66083721 0.00677938][ 3.00912373 -2.745417 3.27131287 -1.56909315 -1.94513681 2.29682254][ 1.96561297 0.51030292 0.52852716 3.78571392 0.45337472 3.5170347 ][ 2.12480298 2.97122243 3.60375452 -1.40103767 -1.5781162 0.30567304]]
这些结果被添加到变量offspring_crossover
中,并由函数返回。
在这一点上,我们成功地从 4 个选择的亲本中产生了 4 个后代,并且我们准备创建下一代的新群体。
注意,遗传算法是一种基于随机的优化技术。它试图通过对当前解决方案进行一些随机更改来增强它们。因为这样的改变是随机的,我们不确定它们会产生更好的解决方案。因此,最好在新的种群中保留以前的最佳解(父代)。在最坏的情况下,当所有新的后代都比这样的父母更差时,我们将继续使用这样的父母。这样一来,我们保证新一代至少会保留以前的好成绩,不会变得更差。新群体将从以前的父母那里得到它的前 4 个解决方案。最后 4 个解决方案来自应用交叉和变异后产生的后代:
new_population[0:parents.shape[0], :] = parents
new_population[parents.shape[0]:, :] = offspring_mutation
通过计算第一代所有解(父代和后代)的适应度,它们的适应度如下:
[ 18.24112489 17.0688537 15.99527402 14.40299221 -8.46075629 31.73289712 6.10307563 24.08733441]
之前最高体能是 18.24112489 现在是31.971158。这意味着随机变化朝着更好的解决方案发展。这太棒了。但是,这样的结果可以通过更多代来加强。下面是另外 4 代的每个步骤的结果:
**Generation : 1****Fitness values:**[ 18.24112489 17.0688537 15.99527402 14.40299221 -8.46075629 31.73289712 6.10307563 24.08733441]**Selected parents:**[[ 3.00912373 -2.745417 3.27131287 -1.56909315 -1.94513681 2.29682254][ 2.12480298 2.97122243 3.60375452 -1.40103767 -1.5781162 0.30567304][-0.63698911 -2.8638447 2.93392615 -1.40103767 -1.20313655 0.30567304][ 3.00912373 -2.745417 3.27131287 -0.72163167 0.7516408 0.00677938]]**Crossover result:**[[ 3.00912373 -2.745417 3.27131287 -1.40103767 -1.5781162 0.30567304][ 2.12480298 2.97122243 3.60375452 -1.40103767 -1.20313655 0.30567304][-0.63698911 -2.8638447 2.93392615 -0.72163167 0.7516408 0.00677938][ 3.00912373 -2.745417 3.27131287 -1.56909315 -1.94513681 2.29682254]]**Mutation result:**[[ 3.00912373 -2.745417 3.27131287 -1.40103767 -1.2392086 0.30567304][ 2.12480298 2.97122243 3.60375452 -1.40103767 -0.38610586 0.30567304][-0.63698911 -2.8638447 2.93392615 -0.72163167 1.33639943 0.00677938][ 3.00912373 -2.745417 3.27131287 -1.56909315 -1.13941727 2.29682254]]**Best result after generation 1 : 34.1663669207****Generation : 2****Fitness values:**[ 31.73289712 24.08733441 18.24112489 17.0688537 34.16636692 10.97522073 -4.89194068 22.86998223]**Selected Parents:**[[ 3.00912373 -2.745417 3.27131287 -1.40103767 -1.2392086 0.30567304][ 3.00912373 -2.745417 3.27131287 -1.56909315 -1.94513681 2.29682254][ 2.12480298 2.97122243 3.60375452 -1.40103767 -1.5781162 0.30567304][ 3.00912373 -2.745417 3.27131287 -1.56909315 -1.13941727 2.29682254]]**Crossover result:**[[ 3.00912373 -2.745417 3.27131287 -1.56909315 -1.94513681 2.29682254][ 3.00912373 -2.745417 3.27131287 -1.40103767 -1.5781162 0.30567304][ 2.12480298 2.97122243 3.60375452 -1.56909315 -1.13941727 2.29682254][ 3.00912373 -2.745417 3.27131287 -1.40103767 -1.2392086 0.30567304]]**Mutation result:**[[ 3.00912373 -2.745417 3.27131287 -1.56909315 -2.20515009 2.29682254][ 3.00912373 -2.745417 3.27131287 -1.40103767 -0.73543721 0.30567304][ 2.12480298 2.97122243 3.60375452 -1.56909315 -0.50581509 2.29682254][ 3.00912373 -2.745417 3.27131287 -1.40103767 -1.20089639 0.30567304]]**Best result after generation 2: 34.5930432629****Generation : 3****Fitness values:**[ 34.16636692 31.73289712 24.08733441 22.86998223 34.59304326 28.6248816 2.09334217 33.7449326 ]**Selected parents:**[[ 3.00912373 -2.745417 3.27131287 -1.56909315 -2.20515009 2.29682254][ 3.00912373 -2.745417 3.27131287 -1.40103767 -1.2392086 0.30567304][ 3.00912373 -2.745417 3.27131287 -1.40103767 -1.20089639 0.30567304][ 3.00912373 -2.745417 3.27131287 -1.56909315 -1.94513681 2.29682254]]**Crossover result:**[[ 3.00912373 -2.745417 3.27131287 -1.40103767 -1.2392086 0.30567304][ 3.00912373 -2.745417 3.27131287 -1.40103767 -1.20089639 0.30567304][ 3.00912373 -2.745417 3.27131287 -1.56909315 -1.94513681 2.29682254][ 3.00912373 -2.745417 3.27131287 -1.56909315 -2.20515009 2.29682254]]**Mutation result:**[[ 3.00912373 -2.745417 3.27131287 -1.40103767 -2.20744102 0.30567304][ 3.00912373 -2.745417 3.27131287 -1.40103767 -1.16589294 0.30567304][ 3.00912373 -2.745417 3.27131287 -1.56909315 -2.37553107 2.29682254][ 3.00912373 -2.745417 3.27131287 -1.56909315 -2.44124005 2.29682254]]**Best result after generation 3: 44.8169235189****Generation : 4****Fitness values**[ 34.59304326 34.16636692 33.7449326 31.73289712 44.8169235233.35989464 36.46723397 37.19003273]**Selected parents:**[[ 3.00912373 -2.745417 3.27131287 -1.40103767 -2.20744102 0.30567304][ 3.00912373 -2.745417 3.27131287 -1.56909315 -2.44124005 2.29682254][ 3.00912373 -2.745417 3.27131287 -1.56909315 -2.37553107 2.29682254][ 3.00912373 -2.745417 3.27131287 -1.56909315 -2.20515009 2.29682254]]**Crossover result:**[[ 3.00912373 -2.745417 3.27131287 -1.56909315 -2.37553107 2.29682254][ 3.00912373 -2.745417 3.27131287 -1.56909315 -2.20515009 2.29682254][ 3.00912373 -2.745417 3.27131287 -1.40103767 -2.20744102 0.30567304]]**Mutation result:**[[ 3.00912373 -2.745417 3.27131287 -1.56909315 -2.13382082 2.29682254][ 3.00912373 -2.745417 3.27131287 -1.56909315 -2.98105233 2.29682254][ 3.00912373 -2.745417 3.27131287 -1.56909315 -2.27638584 2.29682254][ 3.00912373 -2.745417 3.27131287 -1.40103767 -1.70558545 0.30567304]]**Best result after generation 4: 44.8169235189**
在上述 5 代之后,与第一代之后的最佳结果 18.24112489 相比,最佳结果现在具有等于 44.8169235189 的适应值。
最佳解决方案具有以下权重:
[3.00912373 -2.745417 3.27131287 -1.40103767 -2.20744102 0.30567304]
完整的 Python 实现
完整的代码可以在我的 GitHub 账号这里获得:https://GitHub . com/ahmedfgad/genetical gorithm python/tree/master/Tutorial % 20 project。它也会在教程中列出。
下面是该示例的实现:
遗传算法模块如下:
原文可在 LinkedIn 本页面获得:https://www . LinkedIn . com/pulse/genetic-algorithm-implementation-python-Ahmed-gad/
联系作者:
领英:https://linkedin.com/in/ahmedfgad
电子邮件:ahmed.f.gad@gmail.com
遗传算法:语义代码
原文:https://towardsdatascience.com/genetic-algorithms-semantic-codes-f484f825b1e?source=collection_archive---------18-----------------------
遗传算法快速概述:遗传算法是一类非常有趣的优化算法,它借用了生物进化的概念。遗传算法由变异、评估和选择过程组成。变异算法的范围可以从无害的变化到每次迭代的大量不同的变化。评估算法测量每个代码对于手头任务的“适合”程度。有时,这可能需要额外的计算,将代码格式化成最终的有机体。最后,选择过程确定将多少代码传递给下一代,以及采取何种选择程序来选择这些代码。
在本文中,我们将讨论正在变异的底层代码,以及我们如何创建更好的代码表示来产生更有意义的结果。
遗传算法可用于解决游戏,如下例所示:
这个贪吃蛇游戏的遗传密码指的是一系列的。在每个时间步,用户可以左转、右转或不采取任何行动。这三个决定的组成,我们姑且缩写为: (L,R,NA) ,都类似于(A,C,G,T)的一个遗传密码。该算法迭代地学习一些序列:
L | L | R | R | NA | NA | L | NA | NA | …. | L | R |
# The Cardinality of this Sequence could be something like 1 million decisions results in complete victory in Snake.
这个序列已经针对一些评估指标进行了优化,例如在贪吃蛇游戏中尽可能长时间地存活。评估这一指标需要一些计算,因为算法必须运行游戏,以了解代码对生存的适合程度。幸运的是,进化算法可以利用并行化,同时运行多个模拟,以尽可能快的速度进化后代。
除了诸如代码应该如何进化以及如何加快代码评估的元细节之外… 使用遗传算法时,最重要的是要考虑底层代码的结构!
在我们上面的蛇的例子中,游戏的决定可以很容易地分解成 3 个动作,左转,右转,或者不采取行动。导致贪吃蛇游戏胜利的最终移动序列是许多移动长的,但是序列的进化将以从左到右的方式发生,因为这些是将导致最高评估度量的突变。
然而,如果你应用遗传算法来创建一个图像,你可能会有一个更复杂的变异范围,并且没有一个直观的路径来进行变异(例如从左到右的运动决策)。
以 3 个 8 位颜色通道表示的 300 x 300 图像(相当*/低分辨率的图像)导致 300x300x24x255 = 550,800,000 种不同的图像配置。
在这个例子中,底层像素代码构成了最终的有机体,即图像。在前面的例子中,潜在的决策代码组成了最终的有机体,一个蛇游戏试验。现在我们来看看音乐是如何由音符组成的。
钢琴音乐最常见的是,可以分解成乐谱。
这个代码被用来产生一个有机体,音乐。每个音符可以取大约 40 个值,每个时间步长可以包含任意给定数量的音符(尽管很少超过 4 或 5 个),并且还可以随着音符的演奏速度而变化(例如,空心圆圈音符表示按住键 2 个时间步长,而实心圆圈表示仅按下键 1 个时间步长)。
如果我们使用遗传算法来创造音乐,我们会发现比试图创造图像更成功。这主要是因为我们可以访问更具语义代表性的底层代码进行变异。
音频和声音数据可以以模拟图像像素表示的方式分解。cd 质量的音频样本由每秒 44,000 个样本组成,这些样本由描述音频数据的正弦波组成。这些正弦波通过 MP3 等文件进行处理,产生数字声音。一般来说,音频数据实际上比图像数据复杂得多,然而,这种乐谱表示为我们提供了一种更有意义的代码来随机生成音频数据。
在南方公园工作室,他们提供了一个界面让你创建自己的角色:http://southpark.cc.com/avatar。
使用这个工具,你只允许做一些转换,比如转换帽子、颜色、外套、头发等等。由于这种更具语义的表示,你将能够更快地完成诸如“生成一个与我最相似的南方公园头像”这样的任务。这是因为有一个更高层次和语义的代码可以变异。
我希望这篇文章有助于启发关于遗传密码的思考,以及我们如何为了使用遗传算法而预处理我们的数据。在应用遗传算法之前,先试验一下你的数据的更高层次的表示,感谢阅读!请订阅!
CShorten
Connor Shorten 是佛罗里达大西洋大学计算机科学专业的学生。对数据科学、深度学习和软件工程感兴趣。主要用 Python,JavaScript,C++编码。请关注更多关于这些主题的文章。
遗传编程在人工智能启发式优化中的应用
原文:https://towardsdatascience.com/genetic-programming-for-ai-heuristic-optimization-9d7fdb115ee1?source=collection_archive---------7-----------------------
Photo by James Harrison on Unsplash
介绍
我对基因编程的兴趣始于 2015 年,当时我研究了迭代最后通牒游戏。最近,我一直在使用遗传算法来优化工作中风险管理系统的参数。在这篇短文中,我将讨论构建你自己的遗传算法的高级思想和必要成分。我还将给出一个简单的遗传算法的实现,该算法使用 alpha beta 剪枝和迭代深化的 minimax 来优化一般游戏 AI 代理的启发式函数。最后,我将讨论人工智能中遗传编程的几个缺点。
这是什么?
遗传编程(GP)是一种进化算法,可以计算人类不知道如何直接解决的一般问题的解决方案。机器的任务是从问题的高级实现中生成一个工作的计算机程序。这个想法是随机生成数以千计的计算机程序,并使用达尔文自然选择来进化这些程序,直到种群收敛到全局最大值/最*值。它通常用于机器学习领域,以确定数据中特征之间的关系。GP 还被应用于各种金融领域:建立自动交易策略、风险管理系统和信用卡检测。其他感兴趣的领域包括量子计算、电路和天线的设计。我最近还听说遗传算法被用来调试大规模程序中的代码。
遗传程序的组成部分
所有的进化算法都必须有一个繁殖、变异和进化的机制。此外,如果您希望使用真正的遗传编程,您必须定义参数的遗传表示。例如,浮点数据类型的简单表示是二进制字符串表示。然后,人们可以将进化应用于字符串的每一位。关于育种,交叉是最流行的方法,通过这种方法,二进制数据的基因组以随机方式组合。定义健壮的繁殖和变异机制对于确保解收敛到全局最大值/最*值是至关重要的。
玩游戏的例子
假设我们的任务是构建一个人工智能系统来玩一个普通的游戏(例如国际象棋)。如果我们应用最*最大和阿尔法贝塔剪枝的标准方法,我们的任务将是生成一个启发式函数来确定一个移动的相对“强度”。假设我们选择以下形式的东西:
V(w) = w * white_pieces — (1-w)*black_pieces where w in [0,1].
遗传编程的任务是为我们的人工智能代理选择参数 w。请注意,在下面的代码中,我将使用我的 AlphaBetaPlayer 类来表示群体中的个体。遗传得分函数被定义为上面的简单试探法。
我们的首要任务是定义一个单独的代理,如下所示:
def individual(weight):
# creates an individual
return AlphaBetaPlayer(score_fn=genetic, weight=weight)
初始种群只是一组随机权重的个体。我们可以如下实现它:
def population(count):
# creates a list of individuals
return [ individual(random.uniform(0,1)) for x in range(count) ]
我们现在可以将育种过程定义为在母亲体重和父亲体重之间计算一个随机数,并稍微增加范围以保持更多的遗传多样性。我们不允许母亲和父亲是同一个人。
def breed(mother, father):
if mother != father:
if father.w > mother.w:
childWeight = random.uniform(mother.w*.95, father.w*1.05)
else:
childWeight = random.uniform(father.w*.95, mother.w*1.05)
if childWeight < 0:
childWeight = 0
if childWeight > 1:
childWeight = 1
child = individual(childWeight)
return child
else:
print('Cannot breed with itself: Error: Mother == Father')
请记住,这里选择的育种过程是完全随意的,可以有不同的定义。比如我们可以考虑取母亲和父亲的算术平均值甚至几何平均值。你应该尽你所知去模仿达尔文进化论。再次重申我上面的评论,最健壮的方法是使用某种类型的二进制字符串表示,并对基因型应用真交换。在这个简短的例子中不讨论这个问题。我们以显而易见的方式调整琐碎的边界情况。
我们的下一个任务是定义突变过程。一个简单的实现是将权重向上或向下移动一个随机的量。我们做了一些更聪明的事情来确保基因多样性。
def mutate_agent(agent):
if agent.w < 0.5:
newWeight = (1-agent.w) + random.uniform(-0.5, 0.1)
else:
newWeight = (1-agent.w) + random.uniform(-0.1, 0.5)
if newWeight < 0:
newWeight = 0
if newWeight > 1:
newWeight = 1
mutated_agent = individual(newWeight)
return mutated_agent
特别是,我们将概率分布转换为移动权重,这些权重要么接近 0,要么接近 1,分别接近 1 或 0。同样,我们以明显的方式调整琐碎的边界情况。
我们最后的任务是结合以上的功能来进化当前的种群。我们的方法包括让代理在一定数量的游戏中互相竞争,然后选择前 20%的玩家在下一轮进化中使用。我们还随机选择一些表现较差的代理,以确保遗传多样性。我们有效地杀死了剩下的特工。最后,我们使用我们的育种过程创建孩子,并使用我们上面讨论的突变函数突变 5%的人口。函数中的参数定义了要进行的游戏的数量、要保留的双亲的百分比、表现最差者的随机选择大*和变异率。
def evolve(pop, gamesFactor=2, retain=0.2, random_select=0.05, mutate=0.01):
# Determine the parents to breed from the population
agent_score = {}
numGames = len(pop) * gamesFactor
bar = progressbar.ProgressBar()for game in bar(range(numGames)):
competitors = random.sample(pop, 2)
game = Board(competitors[0], competitors[1])
winner, history, outcome = game.play()
competitors.remove(winner)
loser = competitors[0]
if winner not in agent_score.keys():
agent_score[winner] = 1
else:
agent_score[winner] += 1
if loser not in agent_score.keys():
agent_score[loser] = -1
else:
agent_score[loser] -= 1
top_performers_size = int(retain * len(pop))
bottom_performers_size = len(pop) - top_performers_size
rand_select_size = int(len(pop) * random_select)
top_perfomers = heapq.nlargest(top_performers_size, agent_score, key=agent_score.get)
bottom_performers = heapq.nsmallest(bottom_performers_size, agent_score, key=agent_score.get)
parents = top_perfomers + random.sample(bottom_performers, rand_select_size)
random.shuffle(parents)# Create children
numChildren = len(pop) - len(parents)
children = []
for i in range(numChildren):
par = random.sample(parents, 2)
father = par[0]
mother = par[1]
child = breed(mother, father)
children.append(child)
new_pop = parents + childrenmutated_pop = []
# Randomly mutate some of the new population
for agent in new_pop:
if mutate > random.uniform(0,1):
print('Mutate')
mutated_agent = mutate_agent(agent)
mutated_pop.append(mutated_agent)
else:
mutated_pop.append(agent)
return mutated_pop
将所有东西结合到我们的主程序中,我们可以不断地进化种群,直到我们收敛到一个全局最大值/最*值。这个模拟花了 17 个*时在我的机器上运行。
if __name__ == "__main__":
pop_count = 100
evolution_cyles = 12
pop = population(pop_count)
history = []
for i in range(evolution_cyles):
print(i)
pop = evolve(pop, gamesFactor=10, retain=0.2, random_select=0.05, mutate=0.05)
best_weights = [i.w for i in pop]
print(stats.describe(best_weights))
history.append(best_weights)
print('Evolution Results:')
[stats.describe(x) for x in history]
在一天结束的时候,你会对观察经过适当数量的进化周期后的最终种群感兴趣。描述性统计应该有一个*的标准差和一个紧密的四分位数范围。你应该看到所有的代理都有相似的权重。对于下棋代理,遗传算法给出的最优权重约为 0.3452。
遗传编程的缺点
遗传编程的一个简单缺点是计算成本。在达到收敛之前,需要进化许多种群。另一个缺点是解决方案不能保证收敛到全局最大值/最*值。通常也很难确定育种和突变程序。最后,大量的参数通常需要大量的进化周期。玩游戏的启发式函数通常被设计来平衡复杂性和对游戏的洞察力。将启发式算法设计得尽可能简单通常是很重要的。出于这个原因,遗传编程对于玩人工智能游戏的代理人来说非常有效。
参考
[1]https://Zhang GW . WordPress . com/2009/11/08/a-simple-genetic-programming-in-python-4/
[2]https://lethain . com/genetic-algorithms-cool-name-damn-simple/
[3]https://en.wikipedia.org/wiki/Genetic_programming
http://www.genetic-programming.org/
[5]本·兰德在 2015 年夏天
流派精要——建立专辑推荐系统
原文:https://towardsdatascience.com/genre-essentials-building-an-album-recommender-system-c89c308d16f0?source=collection_archive---------3-----------------------
这个想法
为了练习我的 Python 技能并探索推荐系统的内部工作方式,我决定使用协作过滤来构建一个推荐系统,该系统基于以音乐专辑的用户评级形式的明确反馈。我自己提出的一个约束是我不会使用任何外部库。因此,我没有使用黑盒库方法,而是自己编写了所有代码。
4chan 的音乐鉴赏家创作的generessentials的主要灵感来源是 mu/essential 图表。这些专辑选曲帮助听众对音乐类型有一个基本的了解。每个图表由黑色背景上的专辑封面网格组成,并附有专辑标题列表,以帮助用户识别有问题的专辑。
Essential Black Metal
我已经使用这些图表很长时间了,它们帮助我找到了一些我最喜欢的专辑(例如。九州——欢迎来到天空谷),它们很棒……但是……它们不切实际。首先,我必须从列表中随机选择一张专辑封面,然后浏览列表找到相应的标题,在音乐流媒体网站上查找,开始听它,如果不好就从头开始。这个过程不仅浪费时间,而且由于下一张专辑的选择是随机的,它还浪费了潜在的有用信息——用户已经听过的专辑列表。
GenreEssentials 保留了这些图表的基本概念,并用推荐系统扩展了它们,该推荐系统可以预测用户将喜欢的专辑列表,并根据这些预测生成个性化的收听顺序。只需点击一下,用户就可以在 YouTube 上找到专辑,听听它,然后在提供反馈后,网络应用程序根据用户的偏好对图表进行排序。
1.获取数据
该应用的架构由两个主要组件组成,一个用 Java 和 Python 编写的数据管道和一个用 JavaScript 编写的演示模块,部署在 PHP 服务器上。我最初的意图是只用 Java 编写 scraper,用 Python 编写数据挖掘模块,但是我对自己的和机器的 Python 缓慢性能感到沮丧,所以我最终用 Java 编写了大部分代码。
管道的输入是包含专辑列表的 TSV 文本文件。Java web scraper 模块解析列表,使用 JSoup 在公共 API 和 web 上查找每个相册,使用 Hibernate 将其映射到一个模式,并将其作为相册包保存在 MySQL 数据库中。大部分信息是从 Discogs、LastFM 和*基百科 API 获得的。
GenreEssentials Architecture
数据争论和挖掘模块读取相册包,分析数据,对其执行各种矩阵操作,并使用 Jackson 输出 JSON 包列表。表示层托管在 PHP 服务器上,数据用 d3.js 可视化,UI 交互用 knockout.js 和 jQuery 处理。
2.了解数据
在收集了我需要的所有数据后,第一步是将这些数据转换成有用的格式。我为每张专辑收集了三类信息:风格&流派、标签和用户评分。目标是将它们转换成向量空间模型,这样它们就可以被比较、分解等等。以获得对它们之间关系的有价值的见解。
Album information example
风格和流派信息被组合形成一个关联矩阵,其中每行代表一个专辑的术语向量,每个术语的出现得到一个二进制权重。我增加了从中获得有用信息的机会,方法是将每个术语转换为*写,用空格替换破折号、与号和斜线,分解多词术语,并将这些新术语添加到集合中。例如,虽然在原始设置中["psy-trance"]和["trance"]是零匹配,但是现在在["psy "、" Trance "、" psy trance"]和["trance"]之间有一些重叠。
对于标签“clouds ”,我也有每张专辑的出现次数,所以我使用了与风格和流派相同的替换和拆分方法,但这次我还必须给新术语一些虚拟权重。我决定将原始术语的出现拆分到新术语中。例如,如果一张专辑的标签“另类摇滚”被使用了 240 次,我就添加了 120 x“另类”和 120 x“摇滚”。
可能到目前为止,我得到的最相关的信息是用户评分。我把这些想象成一个 UxI 矩阵来获得第一印象。
sparsity of the Rating Matrix of the Pink Floyd Discography
如你所见,它相当稀疏。一些用户对一张专辑进行了评级,使得他们在专辑相似性方面或多或少不相关,所以我最终删除了他们以减少*度。但在此之前,我提取了他们确实会影响的所有相关信息,即总评分(衡量每个项目的知名度)和平均评分(衡量“喜欢”它的程度)。我将该信息存储在 Ix5 矩阵中,其中专辑向量的 5 个值是投票计数,并使用它来确定专辑列表的初始顺序。
Essential Metal Albums sorted by average rating with rating distributions visualized
看着相对于总评分和相对于专辑自身评分的评分分布的可视化,我们可以问这样一个问题:这些评分真的有多大意义?如果我们按平均评分对专辑进行排序,我们可以看到,例如 EyeHateGod,一个有点地下的乐队拥有最高的平均评分,而“对机器的愤怒”,一个最受欢迎的乐队在名单的下半部分。以 IMDb 为例通过给每一票分配权重来平衡铁杆粉丝的热情,从而消除了这种极端情况。
另一方面,总评分提供了一个很好的专辑受欢迎程度的估计,所以我决定用它作为列表初始排序的基础。
计算相似度
共享评级也揭示了专辑之间的一些相关联系,这给了我探索专辑相似性的想法。计算每个专辑对之间的联系或相似性将产生 IxI 评级-相似性矩阵。因为我已经有了向量空间模型形式的所有数据,所以我可以使用相似性度量从中提取有价值的信息。我将我拥有的 3 个矩阵缩减为 3 个方阵,然后将它们合并在一起。矩阵的值根本不同,所以我不得不选择稍微不同的方法来度量相似性。
算计风格&流派相似点
由于风格&流派向量值是二进制的,所以可以通过使用余弦相似度来计算项目之间的距离。
如果原始值为正(我们的情况),余弦相似性将向量之间的角度映射到[-1,1]或[0,1]的范围。它对相似之处给予了很高的奖励,而没有惩罚差异,所以在这种情况下这是一个很好的选择。这样,IxN 矩阵可以简化为 IxI 矩阵。
Comparing genres & styles with Cosine Similarity
计算标签相似度
虽然风格&流派矩阵是二进制的,但是标签矩阵值保存标签计数信息,所以它也是严格正的,但是在可以计算它们之间的相似性之前,必须对这些值进行缩放和平滑。
这个矩阵的一个不便之处是,一些不太出名的专辑在最后一张里没有找到。所以我即兴使用了他们的风格和流派术语。因此,这些专辑的总标签数低于 10,而其他专辑有 100 个标签。这意味着一个不太受欢迎的专辑将错过标签,不是因为这些标签是不相关的,而仅仅是因为标签数量相差很大。为了平滑这一点并减少假阴性的数量,我选择牺牲一些细节,使专辑彼此更加相似。我将计数调整到 0 到 20 之间,并应用 k=1 的拉普拉斯平滑,以确保原始计数和为平滑而添加的计数之间的比率为 1:20,并基于这些值计算余弦相似性。
计算评分相似度
使用余弦相似度进行评级的问题在于,它对于变化并不是不变的。换句话说,它认为一个给专辑 A 和专辑 B 都打 1 星的用户和一个给 5 星的用户非常相似。我们真的不知道 1 分实际上意味着什么,但更有可能的是,给予 1 星评级更多的是强烈的负面反应,而不是轻微的正面反应。这很重要,因为就矢量而言,尤其是余弦距离而言,原点的不同位置会导致完全不同的相似系数。
如果我们将评级相对于它们的平均值(假设是 3)居中,以前的 1 星和 5 星评级现在变成了-2 和+2,它们之间的角度从 0°变为 180°,它们的余弦相似度从 1 变为 1。例如,假设我们想要比较两个项目,一个项目获得了两个评分[1,1],另一个项目获得了[4,5]。得到的余弦相似度将接近 1。将数据集移动到中心将导致向量[-2,-2]和[1,2]以及接近-1 的相似度。
center shifted Cosine Similarity
因此,如果我们想要更精确,我们可以计算评级的平均值来确定数据集的真正中心,然后从所有评级中减去它。还可以使用皮尔逊相关系数来计算中心的相似性不变量。
adjusted cosine similarity
在计算所有 3 个相似性矩阵之后,可以通过计算加权平均值来合并它们,以形成单个正方形矩阵。结果可以用热图的形式显示出来。矩阵是对称的,因此为了节省空间,它可以旋转 45 度并切成两半:
Combined similarities in a random selection of Essential Oldies
3.数据挖掘
对数据集有了基本的了解之后,在深入挖掘之前,应该问一些具体的问题。我到底想知道什么?
这个实验的主要目标是能够根据已经听过和评价过的专辑和/或根据社区的评价(如果用户还没有评价过任何专辑)来对未听过的专辑进行排名。
选择和微调算法是一个反复试验的过程。我的方法是选择一条路,走几步,衡量结果,然后重新评估计划。
计划 A:使用矩阵分解的基于用户的协同过滤
在大多数情况下,推荐系统可以使用的最有价值的信息是评级形式的用户偏好,因为我拥有这些信息,所以围绕这些信息构建算法是一个显而易见的选择。
协同过滤是一种流行的评分预测方法,其基于具有相似品味的用户将对一组项目给出相似评分的假设。例如,一个基于用户的实现将首先找到与当前用户最相似的用户,然后根据这些“邻近”用户给出的评级来预测给定项目的评级。当我们没有关于当前用户的足够信息(冷启动)或者当我们没有足够相似的邻居(稀疏性)时,问题就出现了。
我们如何计算用户的品味或一个项目的质量?假设评级不是随机的,我们可以想象它们是基于一个项目的特性列表和用户对这些特性的偏好列表。实际上,这两个向量不仅是无限的,而且它们的值根据一天中的时间、用户的情绪等不断变化。从数学意义上来说,我们可以把评级的形成想象成特征向量和偏好向量的点积。
ratings determined by user preference and item characteristics
当然,不难看出,在计算我们的估计值时,我们考虑的特征数量将对准确性产生积极影响,对计算速度产生消极影响(在某些情况下,会以指数方式减慢计算速度)。
accuracy vs. computation time trade-off
我们的目标是估计这两个无限向量,通过丢弃或组合特征将它们减少到其本质,同时保持结果尽可能接近实际值。每个项目或用户的高度相关特征的数量很少,其余特征的值接近于零。不幸的是,消除这些特性是不可能的,因为它们可能对另一个项目非常重要,所以减少特性数量的最有效方法是将它们组合并分组到相关的桶中。
矩阵分解或矩阵分解是一种技术,简单地说,它帮助我们计算这些最相关的特征桶。已知评级矩阵 R 是包含用户偏好值的矩阵(P)和包含项目特征值的矩阵(Q)的乘积,我们的目标是尽可能精确地估计这两个未知矩阵。
R = rating matrix, P = user latent feature matrix, Q = item latent feature matrix
计算这些矩阵的值是一个迭代过程,这意味着成本函数的最*化,该成本函数由误差(实际评级-估计评级)加上通常用于保持特征接近于零以避免过拟合的正则化因子加上可以提高精度的任何其他权重来确定。这将导致基于函数梯度的更新公式:
η = learning speed, λ = regularization factor, e = error
这种迭代估计最流行的方法是梯度下降和交替最*二乘法,它间歇地固定一个矩阵并调整另一个矩阵。我选择实现一个基于梯度下降的解决方案,选择一个 9 的特征计数,并用 Python 训练模型。
latent feature similarities (visualized as radial “petals”)
我在 UI 逻辑中也使用了梯度下降。我根据社区的平均偏好初始化当前用户的用户偏好向量,然后在每次用户对新专辑进行评级后,我重新训练这个向量,以准确匹配给定的评级。然后我预测了其他所有专辑的评分,按升序排序。
不幸的是,在几次 UI 测试运行之后,我发现这些预测是相当随机的。我的结论是,评级数据过于嘈杂和/或过于稀疏。在训练模型时,我认为空评级是不相关的,但也许我可以通过为现有评级分配 1 的重要性权重来改进模型,并降低重要性权重,如 0.01 到 0/缺失评级。
我也不喜欢 MF 方法,因为在训练模型之前的随机初始化,结果不仅是随机的,而且在单次运行之间也不一致。我想要每次都给出相同固定结果的东西,所以我决定后退一步,把事情简化一点。
B 计划——结合协作和基于内容的过滤进行基于项目的排名
虽然矩阵分解和潜在特征绝对值得探索,但我意识到我可以用更简单的方法更快地实现我的目标,所以我简单地建立了基于组合余弦相似矩阵的排名系统。因为我处在一个舒适的环境中,最大项目数只有大约 300 个,了解项目对之间的距离大大简化了这个过程。基于内容的过滤是另一种过滤方法,利用用户简档和物品简档的相关性对物品进行排名。我使用了现有的风格、流派&标签信息来帮助我提高预测的准确性。
基于项目的 CF 是基于用户的过滤的镜像方法:作为第一步,它找到与当前项目最相似的 n 个项目,然后根据其邻居的评级预测其评级。
item based collaborative filtering
我对预测收视率不感兴趣,所以我决定使用这个公式的修改版本,只保留公式的红利。这样,即使用户只给了 5 分,我也能对项目进行排序。对于每一张未评级的专辑,我将 T2 k 张最相似的 T3 张专辑的相似度按照它们的评级进行加权,然后根据这些总和对列表进行排序。
k nearest neighbors
4.数据可视化
名单
对于主图表,我使用了 knockout.js,这是一个极简的前端框架,可以非常容易地将事情联系在一起。图表数据从几个 JSON 文件中读取,然后使用 knockout 呈现。点击一个相册会打开一个带有详细相册信息的旁白。在这里,用户可以对专辑进行评级,这将把它从“未听过”列表移到屏幕左侧的“听过”列表。这触发了预测专辑分数的重新计算。每个“听过”的专辑通过它们的评级来加权(转移到[-2,2]范围),并且每个“没听过”的专辑基于与“听过”的专辑的相似性距离接收新的预测得分。
List View of the Essential Electronic Albums
在重新计算预测得分后,图表被排序,因此用户最可能喜欢的项目总是在列表的顶部。
图表
和弦图最初并没有计划成为应用程序的一部分,它只是我更好地理解数据集的一个工具。但它看起来很酷,所以我决定留着它。它显示每两个相册之间的组合(标签+风格+评分)相似性。
我考虑了几种可能性,具体来说,共同评分的数量会很有趣,但评分计数之间存在巨大差异,所以即使我对它们进行了缩放,也存在太多差异。我最终使用了组合相似度。为了降低图表的复杂性,我选择只显示前 5 个最相似专辑的链接。
我根据相应相似性的强度缩放了每个连接弧的宽度和不透明度。
Chart of Essential Jazz Album Similarities
地图
除了列表和图表之外,我认为创建一个 2D 地图来表示数据,以便能够看到相册的位置、它们的链接、组和簇,这将是很好的。
为了获得数据集的 2D 投影,我考虑同时使用主成分分析和 t 分布随机邻居嵌入。T-SNE 似乎更适合我的情况,因为我的首要任务是保持距离,但 PCA 似乎更直观,我可以自己编写算法而不会浪费太多时间,所以我选择了 PCA。
我运行算法并在 d3 中可视化地图。虽然看起来还可以,而且各个子风格都清晰地聚集在一起,但当我将 5 个最相似的相册链接可视化时,发现它们在地图上并不一定紧挨着。为了解决这个问题,我做了一点手脚,用了一个 d3 力模拟来放松距离。我在 d3 模拟中添加了一些力来使相似的专辑更接近,另一个力迫使图形根据画布的比例来塑造自己。最后,我在图表上应用了一个比例因子,使它很好地适合屏幕。有 250 多个节点时,模拟非常慢,所以我导出了结果坐标,并重用它们来加速这个过程。
应用一些聚类方法来分离专辑组,对它们进行颜色编码,或者基于与专辑相同的空间来计算标签云的 2D 投影并覆盖它,这将是很有趣的。我尝试将 PCA-reduced 或 MF-latent 特征作为径向表示,但对于不了解背景过程的人来说,它们没有多大意义。我认为将这些可视化在一个单独的图表中更有意义,也许结合一些与每个特性相关的标签和样式信息。
Map of Dream Theater Album Similarities
结论
玩矩阵有点像玩魔方。如果你知道正确的算法,你就可以一层一层地把所有的东西放好,更高层次的东西就会开始显现出来。我在这个项目中探索的数据挖掘和机器学习工具非常容易理解和使用,但是惊人的强大。在我看来,获得最佳结果的关键不仅是拥有正确的工具集,最重要的是对数据的结构和纹理有很好的理解。选择应用哪种算法总是取决于具体的情况,所以下一次我将玩一个类似的项目,我肯定会从探索和可视化数据集的更多方面开始。我发现收集的数据非常有趣,我将来一定会再次访问它,可能会使用 TensorFlow 实现。
#GENSummit 2018: AI 在出版领域的突破之年
原文:https://towardsdatascience.com/gensummit-2018-ais-breakthrough-year-in-publishing-6fa5a78154be?source=collection_archive---------3-----------------------
这篇文章最初发表在在线新闻博客 上。
本周的 GEN 峰会标志着人工智能(AI)在媒体行业的突破性时刻。这个话题主导了会议前两天的议程,从脸书的 Antoine Bordes 开幕主题演讲到人工智能、机器人、货币化和验证——它也主导了我的时间表。
有时感觉像是在 20 世纪 80 年代的一次会议上,讨论如何在新闻编辑室使用“计算机”,或者听人们谈论手机在 21 世纪初用于新闻业——换句话说,感觉非常像早期。但仍然是重要的日子。
Ludovic Blecher 关于获得Google Digital News Initiative资助的人工智能相关项目的幻灯片最好地说明了这个问题,这些提案被分为具体的“个性化”和模糊的“超本地”等类别。
Image by Marc Springer
那么,深入挖掘一下,以下是我从里斯本学到的一些最具体的观点——以及记者和出版商可以从中得到的启示。
“智能”和你可以教的机器人之间的区别
本*迪克特·埃文斯(Benedict Evans)周四的主题演讲无疑是峰会上最清晰的演讲之一,他成功地从定位(“什么是机器学习”)到潜在应用,再到问题化。
这个演讲呼应了我最近参与的其他讨论,围绕着从谈论人工智能转向像机器学习这样的术语的必要性——能够识别模式,利用这些模式在干草堆中寻找针,自动化重复行为,预测可能性和可能性,等等。
在“人工智能”威胁机器人统治者和机器人新闻业的地方,机器学习更明显地涉及到教一个相对“愚蠢”(但相对而言也是聪明)的机器人如何做我们没有时间或一致性去做的部分工作的过程。
但强大的力量带来了巨大的责任——埃文斯对我们作为其中一部分创造的算法的准确性(特别是由输入形成的)和结果的潜在社会影响之间的责任进行了有益的区分。即使是精确的算法也会产生不良结果。
算法责任和通往可理解性的道路
Jonathan Albright 也提出了类似的观点,他更广泛地谈到了的算法问责制:当涉及到算法对公共和私人生活的影响时,记者的监督作用。
奥尔布赖特的关于“危机演员”YouTube 视频和谷歌搜索建议——以及 ProPublica 的机器偏见系列——作为该领域的介绍,非常值得探索。可能已经开始成为技术和政治节拍特征的东西显然最终将在每个领域发挥重要作用:从报道犯罪、住房到教育、T21、健康,甚至音乐、电影。
媒体公司是最早也是最常见的算法受害者之一,这很有帮助。我们敏锐地意识到,这些食谱中的一个*变化会如何影响我们的观众是否以及如何接受我们的新闻报道,正如艾米丽·贝尔的谈话所示。
现在需要的不仅是对算法如何影响我们的社区的认识(以及对此进行报道的愿望),还有对我们自己对算法的依赖的反思态度——以及对此透明的需要。
Nick Diakapoulos 的工作为主题奠定了一些重要的基础,包括算法透明度的限制和潜在的披露机制,而美联社的 Stuart Myles 已经就算法新闻谈到了同一主题,确定了算法透明度的四个级别。
(一些)数据新闻的商品化——以及从自动化到增强的转变
Frames、Grafiti、RADAR 和 Le Parisien 的 LiveCity 项目显示了数据新闻已经从例外走向了商品化。
Frames 提供一项服务,为新闻机构提供现成的图表,嵌入到他们的文章中,并提供收入共享商业模式,图表也可以通过这种模式得到赞助(他们一直在与一家葡萄牙新闻机构合作,并且声称包含图表可以带来更高的共享和再循环)。
与此同时,Grafiti 的目标是在建立一个图表作为数据的搜索引擎的同时,让图表的社交创作变得更加容易。RADAR 建立了英国最大的数据新闻团队之一,向当地出版商提供新闻专线式的副本;《巴黎人报》正在以个性化*工具的形式将城市数据整合到文章中。
换句话说,数据新闻开始规模化。对于数据记者来说,这意味着两件事:要么从低挂的果实转向更复杂或调查性的故事,要么进入数据新闻本身的规模(即编码)。
…或者,当然,两者兼而有之。
聊天机器人和叙事,机器人和新闻编辑室
与此同时,聊天机器人正朝着相反的方向发展——尽管许多新闻行业的聊天机器人到目前为止只不过是一个美化了的 RSS 警报,Quartz 的约翰·基夫和 BBC 的保罗·萨金特表明,我们越来越多地看到编辑技巧更复杂地应用于表单。
“一个好机器人的成功,”基夫解释道,“是真正的好人。”
换句话说,聊天机器人不仅代表了一个技术挑战,也代表了一个叙事挑战——萨金特在文章中谈到了 BBC 将聊天机器人作为讲故事设备的实验,比如一篇关于英国旁遮普人之间未言明的酒精问题 的文章,而基夫强调了“为机器人编写故事情节的非常有才华的人”以及广告商对这些技能的需求,这使得机器人团队分成了编辑和商业两部分。
“我们发现,我们的才能和我们与一些客户之间的故事有市场。”
这种方法肯定是有效的:BBC 关于皇家婚礼的文章包含了内部聊天机器人看到了 20%的用户使用这些*工具,“通常会问多达五六个问题”。他说,聊天机器人可能不会增加覆盖范围,但会增加参与度。
在 Quartz Keefe,类似地报告说“90%的人一开始就坚持到底。
真正的价值不在于接触到更多的人,而在于加深与你接触到的人的关系
然而,叙事技巧的使用似乎在用户对交互性的期望和传播特定事实的新闻压力之间引入了一种张力。
在另一个单独的会议中 BBC 视觉新闻的 Bella Hurrell 会注意到他们的故事机器人的测试者错过了“直接写文本,问机器人他们自己的问题”的选项
也许人工智能在行业中的越来越多的使用将有助于部分解决这种紧张——事实上,萨金特说他认为聊天机器人是“一种过渡形式”。我们知道我们要整合 AI,一起聊天。
“做这些(聊天机器人)你会学到很多关于如何语气,以及如何组织这些对话和讲故事[让你]在人工智能到来时处于有利位置”
与此同时,越来越多的机器人正在开发供内部使用。
Quartz 的 quack bot(GitHub 上的代码 ) 帮助记者缓存网页副本并建议数据来源,而 BBC 使用机器人自动生成选举图片并在 @bbcelection 账户上发布这些图片,Dagens Nyheter 的Martin jnsson已经创建了一个“性别机器人”(“genus roboten”)来帮助记者了解他们的报道有多大代表性
美联社一直在探索技术在验证、转录、个性化和图像识别方面的潜力。他们的人工智能战略*组负责人丽莎·吉布斯 建议“我可以在人工智能(新闻工作的自动化部分)和我们的商业记者能够做的调查性新闻报道的增加之间画一条直接的线。”
如果有一个领域发生自动化与增强之战,一个将算法问责付诸实践并试验人工智能和口述可能性的地方,可能没有比机器人更好的地方了。
第一次介绍 SELUs 以及为什么你应该开始使用它们作为你的激活功能
原文:https://towardsdatascience.com/gentle-introduction-to-selus-b19943068cd9?source=collection_archive---------1-----------------------
Photo by Nick Fewings on Unsplash
标度指数线性单位(或 SELUs)于 2017 年 9 月首次出现在本文中。虽然 SELUs 很有前途,但并不像你想象的那么普遍。在这篇博文中,我通过将它们与激活函数的事实标准联系起来来介绍它们:校正线性单位(或 ReLUs)。我先从为什么 ReLUs 没有结束关于激活函数的讨论开始。然后,我转向 SELUs 的主要优势:内部规范化。读完这篇文章后,你会对 SELUs 有一个直观的理解,以及为什么你应该在你的神经网络中使用它们而不是 ReLUs。如果你需要复习激活功能,我推荐这篇由 SAGAR SHARMA 撰写的优秀文章。
为什么 ReLUs 不够?
人工神经网络通过称为反向传播的基于梯度的过程进行学习。我强烈推荐这个由 3Blue1Brown 制作的视频系列作为介绍。基本思想是网络在梯度指示的方向上更新其权重和偏差。
反向传播的一个潜在问题是梯度会变得太*。这个问题被命名为消失渐变。当你的网络遭遇渐变消失时,权重不会调整,学习也就停止了。在高级别上,深度网络在反向传播期间会倍增许多梯度。如果梯度接近零,整个产品下降。这反过来又推动其他梯度更接近零,以此类推。让我们来看看激活函数的事实标准 ReLUs 是如何防止这种情况的。
下面是一个 ReLU 如何将输入(在 x 轴上,在文献中命名为 z )映射到输出(在 y 轴上,命名为 a 用于激活):
ReLU 的规则很简单。如果 z *于零, a 为零。如果 z 大于零,输出保持 z 。换句话说,ReLU 用零替换负值,而保持正值不变。这个激活函数的梯度非常简单。*于零的值为零,否则为一。这就是 ReLU 防止渐变消失的原因。没有接近零的梯度,这可能会减少其他梯度。信号要么继续流动(如果梯度为 1),要么不流动(如果梯度为零)。
然而,ReLUs 有一个潜在的问题:它们可能陷入停滞状态。也就是说,权重的变化如此之大,并且在下一次迭代中得到的 z 如此之*,以至于激活函数停留在零的左侧。受影响的细胞不再对网络的学习有贡献,并且其梯度保持为零。如果这种情况发生在你的网络中的许多单元上,那么经过训练的网络的能力将低于其理论能力。你摆脱了消失渐变,但现在你必须处理垂死的 ReLUs 。
ReLU 在计算简单性方面非常出色,所以我们希望尽可能多地保留它,但同时也要处理神经元死亡的问题。形象地说,ReLUs 的墓地在 y 轴的左侧,这里 z 为负值。将墓地变成生命之地的一个突出方法是所谓的 leaky ReLU。看起来是这样的:
如你所见,现在左侧有一个斜坡。这个斜率通常很*(例如 0.01),但它确实存在,所以总是有学习发生,细胞不会死亡。Leaky ReLUs 保持了计算的简单性,因为只有两个不同的和恒定的梯度是可能的(1 和 0.01)。左边的斜率定义了梯度消失的风险。
到目前为止,我们似乎必须在两种风险之间做出选择:死亡神经元(ReLU)或自我施加的消失梯度风险(leaky ReLU)。在这种权衡中,比例指数线性单元 (SELU)处于什么位置?它看起来是这样的:
稍后我会展示实际的公式,但是乍一看,您可以看到两件事情。首先,右边(对于大于零的 z T21)类似于 ReLUs。然而,左侧(对于*于零的 z 来说)似乎接近零的梯度。那不是消失渐变的回归吗?那么,如果 SELU 重新引入了一个我们已经和 ReLUs 解决过的问题,为什么还要考虑使用它呢?答案是控制梯度只是一种方法。塞卢斯拿另一个:正常化。
正常化是怎么回事?
就神经网络而言,标准化可以在三个不同的地方发生。首先是输入归一化。一个例子是将灰度图像(0-255)的像素值缩放到 0 和 1 之间的值。这种类型的规范化是机器学习中的一般概念,并被广泛使用。输入规范化对一些算法至关重要,对另一些算法很有帮助。在神经网络的情况下,严格来说这不是必需的,但是很好的实践。
第二,这次与神经网络特别相关的是批量标准化。见此处由 Jaron Collis 提供的深入解释和编码示例。在网络的每一层之间,对值进行转换,使它们的平均值为零,标准差为一。这种方法有几个优点。关于激活函数的主要一点是,它限制了值,使极端值不太可能发生。
第三,还有内部正常化,这就是 SELU 的神奇之处。主要思想(详见原文)是每一层都保留了前一层的均值和方差。那么 SELU 是如何实现这种正常化的呢?更具体地说,它如何调整均值和方差?让我们再看一下图表:
激活功能需要正值和负值,以使 y 到移动平均值。这里给出了两种选择。这也是 ReLU 不是自归一化激活函数的候选函数的原因,因为它不能输出负值。
梯度可用于调整方差。激活函数需要一个梯度大于 1 的区域来增加它。现在是时候看看 SELU 背后的公式了:
虽然它看起来像是大于零的值的 ReLU,但是还涉及到一个额外的参数:λ。这个参数就是 SELUS(caled)的原因。大于 1 时,梯度也大于 1,激活函数可以增加方差。Tensorflow 和 PyTorch 中的实现使用原始论文中的值,大约为 1.0507。
非常接近零的梯度可以用于减*方差。其他激活函数中梯度消失的原因是内部归一化的必要特征。
还有更多细节需要讨论(点击这里查看 Elior Cohen 的精彩讨论),但这里是直观的总结。由于激活函数以固定的方差集中值,消失梯度不再是一个问题。信号总是保持在实用范围内。
为什么要用 SELUs 而不是 ReLUs?
总的来说,SELUs 拥有这种优秀的自我规范化的品质,我们不再需要害怕消失的渐变。从现在开始,您应该使用 SELUs 而不是 ReLUs,原因有三:
- 与 ReLUs 类似,SELUs 启用深度神经网络,因为没有消失梯度的问题。
- 与 ReLUs 相反,SELUs 不会死。
- SELUs 自身比其他激活函数学习得更快更好,即使它们与批处理规范化相结合。
我的实验是初步的,因此不是这篇文章的一部分,支持这些结果。在某些情况下,ReLUs 和 SELUs 之间没有真正的区别。然而,如果有的话,SELUs 的表现远远超过 ReLUs。
实现 SELU 而不是 ReLU 很容易。在 Tensorflow 中,你要做的就是用tensorflow.nn.selu
代替tensorflow.nn.relu
。在 Pytorch 中,正确的类方法是torch.nn.SELU
。如果你知道如何在你选择的框架内建立一个神经网络,把激活函数改成 SELU 没什么大不了的。
我仍然在尝试,所以如果你有一个正在进行的深度学习项目,我将非常感谢听到你的经验!
感谢阅读!如果你喜欢这篇文章,留下一些吧👏🏻并在 LinkedIn 或 Twitter 上分享。请在评论和 推特 上告诉我你的想法。再次感谢,继续学习!
地理编码:OpenStreetMap + R + Tableau
原文:https://towardsdatascience.com/geocoding-tableau-and-r-integration-c5b32dc0eda6?source=collection_archive---------5-----------------------
便捷的地理编码,R + Tableau BI 工具的所有功能
Geocoding with OpenStreetMap Without API Token
背景
在过去,谷歌地图不需要 API 令牌,这对于简短的用例很有帮助。现在,必须创建一个云帐户。老实说,令人惊讶的是谷歌允许免费令牌 API 持续这么长时间。
在寻找需要街道地址地理位置的短期用例的替代方案时,我发现 OpenStreetMap 是一个简单而有用的替代方案。
这项功能是为谁设计的?
该特性主要面向已经有一些 r 使用经验的用户,这些用户会发现这种集成有几个好处:
- 对安装在 R 中的任何 R 包或函数的完全访问权
- 使用 Tableau 功能进一步分析和理解数据
- 提供一个平台,将开源数据和软件与专有软件相集成
用户必须能够访问 R/RStudio 和 Tableau。这两个软件可以存在于同一台计算机上,也可以远程存在(云)。
Tableau 脚本— R 和 Python 集成
有一种方法可以从 Tableau 执行 R 或 Python 命令,以便允许我们利用这些编程语言的功能(函数、模型和包)。您可以通过与 R 或 Python 实例动态通信的计算字段来实现这一点,结果将作为预定的数据类型(INT、REAL、BOOL、STR)返回给 Tableau。
当需要动态计算的字段来支持分析师的需求,而不必单独运行代码并发回新的数据集时,这种集成非常有用。出于这个原因,我们不会使用这个功能,但你可以查看下面的相关博客。
地理编码入门
- 在许多情况下,我们可以访问带有位置信息的数据(例如,地址、城市、县、邮政编码、国家)。如果我们想更详细地可视化这些数据,我们需要使用地理定位。
- 地理位置坐标(经度、纬度)需要基于位置数据来计算。
- nomist 是 OpenStreetMap 数据的免费搜索引擎。使用 Nominatim,我们可以很容易地从给定的地址计算地理位置坐标。
OpenStreetMap 由一个地图绘制者社区构建的数据组成,他们贡献并*护世界各地的道路、*径、咖啡馆、火车站等数据。
- https://www.openstreetmap.org/about
在 R/RStudio 中加载包
为了在 R/RStudio 中加载包,我们将使用 tidyverse,这是一个为数据科学设计的 R 包以及其他帮助数据清理和处理的包的集合。下面的代码块允许您:
- 检查是否安装了所需的软件包
- 安装未安装的软件包
- 安装后加载软件包
包装潮流
[## Tidyverse
tidyverse 是 R 包的集成集合,旨在使数据科学变得快速、流畅和有趣。
www.tidyverse.org](https://www.tidyverse.org/)
# CHECK IF PACKAGE IS INSTALLED
if(!require("tidyverse")){ # IF PACKAGE NOT FOUND, INSTALL IT
install.packages("tidyverse", dependencies = TRUE) # LOAD PACKAGE AFTER INSTALLETION
library("tidyverse")
}
包 rvest
[## tidyverse/rvest
通过在 GitHub 上创建一个帐户,为 tidyverse/rvest 开发做贡献。
github.com](https://github.com/tidyverse/rvest)
# CHECK IF PACKAGE IS INSTALLED
if(!require("rvest")){# IF PACKAGE NOT FOUND, INSTALL IT
install.packages("rvest", dependencies = TRUE)# LOAD PACKAGE AFTER INSTALLETION
library("rvest")
}
包青天
[## gagolews/stringi
带 ICU 的 R 的字符串处理包。通过在…上创建一个帐户,为 gagolews/stringi 开发做出贡献
github.com](https://github.com/gagolews/stringi)
# CHECK IF PACKAGE IS INSTALLED
if(!require("stringi")){# IF PACKAGE NOT FOUND, INSTALL IT
install.packages("stringi", dependencies = TRUE)# LOAD PACKAGE AFTER INSTALLETION
library("stringi")
}
包 jsonlite
[## jeroen/jsonlite
一个健壮的、高性能的 JSON 解析器和生成器
github.com](https://github.com/jeroen/jsonlite)
# CHECK IF PACKAGE IS INSTALLED
if(!require("jsonlite")){# IF PACKAGE NOT FOUND, INSTALL IT
install.packages("jsonlite", dependencies = TRUE)# LOAD PACKAGE AFTER INSTALLETION
library("jsonlite")
}
OpenStreetMap API 搜索函数
下面的地理编码功能允许我们向 nomist im(OpenStreetMap 数据的搜索引擎)发出请求。
- 提名:https://nominatim.openstreetmap.org/
- 资源:https://nominatim.org/release-docs/develop/api/Search
该函数获取并输入以下参数,这些参数可以根据您的需要进行修改:【姓名】、【地址】、【城市】、【州】、【邮政编码】
geocode <- function(name, address, city, state, zipcode){
# NOMINATIM SEARCH API URL
src_url <- "[https://nominatim.openstreetmap.org/search?q=](https://nominatim.openstreetmap.org/search?q=)"
# CREATE A FULL ADDRESS
addr <- paste(address, city, state, zipcode, sep = "%2C")
# CREATE A SEARCH URL BASED ON NOMINATIM API TO RETURN GEOJSON
requests <- paste0(src_url, query, "&format=geojson")
# ITERATE OVER THE URLS AND MAKE REQUEST TO THE SEARCH API
for (i in 1:length(requests)) {
# QUERY THE API TRANSFORM RESPONSE FROM JSON TO R LIST
response <- read_html(requests[i]) %>%
html_node("p") %>%
html_text() %>%
fromJSON()
# FROM THE RESPONSE EXTRACT LATITUDE AND LONGITUDE COORDINATES
lon <- response$features$geometry$coordinates[[1]][1]
lat <- response$features$geometry$coordinates[[1]][2]
# CREATE A COORDINATES DATAFRAME
if(i == 1) {
loc <- tibble(name = name[i],
address = str_replace_all(addr[i], "%2C", ","),
latitude = lat, longitude = lon)
}else{
df <- tibble(name = name[i],
address = str_replace_all(addr[i], "%2C", ","),
latitude = lat, longitude = lon)
loc <- bind_rows(loc, df)
}
}
return(loc)
}
数据来源:芝加哥市食品检验局
这些信息来源于从 2010 年 1 月 1 日至今对芝加哥的餐馆和其他食品机构的检查。芝加哥公共卫生部食品保护项目的工作人员使用标准化程序进行检查。
[## 芝加哥市|数据门户
关于 2018 年 7 月 1 日影响此数据集的变更的注意事项:http://bit.ly/2yWd2JB-此信息源自检查…
data.cityofchicago.org](https://data.cityofchicago.org/browse?q=food+inspection&sortBy=relevance)
食品检测数据具有地理位置坐标,我们可以使用它们来检查结果的准确性。在这个示例数据集中,我们将只使用 location 列来查找餐馆的坐标。
数据检查和清理
在下面的代码块中,我们正在读取数据并进行一些更改,以确保该地址与 Nominatim API 一起工作。
读取数据
# READ THE DATA
data <- read_csv("food_inspection_sample.csv")# REMOVE SPACE FROM COLUMNS
colnames(data) <- str_replace_all(colnames(data)," ", "_")
清理数据
# REMOVE SPACE FROM RESULTS
data$Results <- data$Results %>%
str_replace_all(" w/ ", " with ") %>%
str_replace_all(" ", "_")# EXTRACT RISK LEVEL
data$Risk <- tolower(data$Risk) %>%
str_extract("\\(.*\\)") %>%
str_extract("[a-z]+")head(data)
https://gist.github.com/jlroo/9c65f9e599f116487b33047ed1be0837#file-food_inspection_sample-csv
地址的地理定位
在本节中,我们将准备 address 变量来匹配 nomim API 样式。
# EXTRACT THE ADDRESS VARIABLE
address <- data$Address
Original address variable
修改地址变量以匹配 API
# CLEAN SPECIAL CASES (e.g. 1 N MAY BLDG)
query <- str_replace_all(string = address,
pattern = "BLDG",
replacement = " ")# CLEAN SPECIAL CASES (e.g. 3333-3339 N CLARK)
query <- stri_replace(str = query,
replacement = " ",
regex = "(-[0-9]+\\s)")# REPLACE SPACES (\\s) OR COMMAS (,) WITH PLUS SIGN (+)
query <- str_replace_all(string = query,
pattern = "\\s|,",
replacement = "+")
Transformed address variable
发出 API 请求-地理编码功能
为 API 准备好地址变量后,我们可以使用开始时创建的 geocode 函数来查找餐馆的地理坐标。
df <- geocode(name = data$DBA_Name,
address = query,
city = data$City,
state = data$State,
zipcode = data$Zipcode)
Returned DataFrame with geo coordinates
最后,我们可以合并两个数据集来创建一个主数据集,并在 Tableau 中工作。为了实现这一点,我们使用了一个 left_join by 变量 name 对返回的数据帧和 DBA_Name 变量进行连接。
geo_df <- data %>% left_join(df, by = c("DBA_Name" = "name"))
https://gist.github.com/jlroo/e4518cf821aa1f103f822931db83e418#file-food_inspection-csv
数据可视化:使用 Tableau 进行地理定位分析
现在有了一个带有地理坐标的主数据集,我们可以将其导入 Tableau 进行进一步分析。
要开始处理 Tableau,请通过文本文件(CSV)连接到文件。这是之前在 r 中创建的文件。
Connect to the food_inspections.csv file
Tableau 数据解释器有助于识别列的数据类型,但是仔细检查以确保数据类型是正确的总是很重要的。在这种情况下,我们将确保变量(纬度和经度)数据类型(地理角色)是正确的。
在 Tableau 中工作的一个好习惯是通过选择屏幕右上角的选项来提取您正在处理的数据集。这将防止您覆盖/损坏原始数据。
Check that columns data types are correct
完成对数据类型的更改后,转到屏幕左下方突出显示的工作表部分。将出现保存数据集(提取)的提示。按照提示将其保存在默认位置。
Default Folder Location — My Tableau Repository
测绘经度和纬度
在工作表中,根据数据类型(*度和度量),您将看到数据集列分为两个部分。在 measures 部分,您将找到经度和纬度变量。要映射坐标,请遵循以下步骤:
- 双击经度变量,Tableau 会将变量放在正确的轴(列)上。
- 双击纬度变量,它将被放置在正确的轴(行)上。
- 将变量放入正确的轴后,将每个变量的数据类型从 Measure 更改为 Dimension。
Mapping coordinates, change of data type
丰富地图功能-邮政编码、细节、颜色
有了地图中的地址,我们现在可以添加更多的要素,例如县边界、邮政编码、位置详细信息和颜色。
- 双击 DBA Name 变量,自动将其指定为细节标记,以查看每个位置的名称。
- 双击风险变量。由于有三个类别,颜色标记是自动分配的。
- 当鼠标悬停在这些点上时,我们应该能够看到餐馆的名称、风险和地理坐标。
地图图层-邮政编码边界
Tableau 允许我们向默认地图添加额外的图层。在这种情况下,了解邮政编码标签和界限会很有帮助。
- 在主工具栏上,选择地图→地图图层。
- 工作表的左上角应该会出现一个地图图层视图。向下滚动并启用邮政编码边界和邮政编码标签选项。
最后,您可以放大以仔细查看特定区域。
请记住,这篇博客文章只是触及了当我们集成 OpenStreetMap、R 和 Tableau 时可能发生的事情的表面。OpenStreetMap API 不需要令牌,而其他 API(Google,Mapquest)需要令牌。
通过利用 OpenStreetMap 作为资源,简单的用例可以得到极大的丰富。也就是说,要注意你在任何时候提出的请求数量。
GeoPandas 101:在地图上绘制带有纬度和经度的任何数据
原文:https://towardsdatascience.com/geopandas-101-plot-any-data-with-a-latitude-and-longitude-on-a-map-98e01944b972?source=collection_archive---------0-----------------------
在我的几个同学问我如何使用 GeoPandas(通常以别名 gpd 导入)之后,我受到了写这篇教程的启发。我最初是从一篇关于媒体的文章中了解到的,但是这个链接似乎已经停止工作了。唉,我们到了。虽然我不可能在一篇博文中分享 GeoPandas 奇妙世界的一切,但我的意图是给你一个起点。我强烈建议你去看看官方文档,即使只是为了看看 GeoPandas 能做的所有很酷的事情。希望你觉得这个教程是有帮助的和令人兴奋的!所有相关的数据和笔记本都可以在我的 GitHub 页面这里找到。
在我看来,GeoPandas 是使用起来最令人满意的 Python 包之一,因为它产生了与现实世界直接相关的有形、可见的输出。此外,我们收集数据的许多对象(例如,人口统计数据、销售指标、传感器数据)至少有一个物理元素,可以帮助我们将数据与特定位置联系起来,并描述有关对象的一些信息。
在本例中,我们将使用芝加哥市的数据来绘制带有西*罗河病毒的蚊子的位置。第一步是下载一个形状文件。shp 文件),如果您知道地理空间数据所在的大致区域。如果你不知道在哪里可以找到一个形状文件,谷歌一下!形状文件中通常有几个其他的文件;请确保将所有这些文件放在同一个文件夹中,否则您将无法读取您的文件。
下一步是导入库。我们将需要以下内容,所有这些都可以通过快速的“pip install <package_name>”从命令行快速安装:</package_name>
import pandas as pd
import matplotlib.pyplot as plt
import descartes
import geopandas as gpd
from shapely.geometry import Point, Polygon
%matplotlib inline
现在我们已经有了一个形状文件和必要的包,让我们绘制我们的地图!只需用 GeoPandas 读入您的形状文件,并使用 matplotlib 像这样绘制它(用您自己的形状文件的路径替换文件路径):
street_map = gpd.read_file('/path/to/your/geo_export_12345.shp')
fig, ax = plt.subplots(figsize=(15,15))
street_map.plot(ax=ax)
Shapefile of Chicago, IL
请注意,我们的地图显示了街道中心线;您可以找到各种各样不同细节层次的形状文件,所以请选择最适合您特定需求的类型。
下一步是以正确的格式获取数据。我们这样做的方法是将我们的常规 Pandas 数据框架转换为地理数据框架,这将要求我们指定原始数据框架、我们的坐标参考系统(CRS) 以及我们的新数据框架的几何形状作为参数。为了适当地格式化我们的几何图形,我们需要将经度和纬度转换成点(我们从上面的 shapely 中导入了点),所以首先让我们读入训练数据集,并像这样指定 EPSG:4326 CRS(用包含纬度和经度坐标的您自己的数据的路径替换文件路径):
df = pd.read_csv('./my_data.csv')
crs = {'init':'epsg:4326'}
df.head()
现在我们有了纬度和经度信息,我们可以创建点。一个点本质上是一个描述数据点的经度和纬度的单一对象。使用 list comprehension 将允许我们在一行中完成这项工作,但是要确保总是在“纬度”列之前指定“经度”列:
geometry = [Point(xy) for xy in zip(df['Longitude'], df['Latitude'])]
One point for each row in our DataFrame. Check the length of the geometry list if you want to make sure.
我们最终应该会得到一个可用于创建地理数据框架的点列表:
geo_df = gpd.GeoDataFrame(df, #specify our data
crs=crs #specify our coordinate reference system
geometry=geometry) #specify the geometry list we created
geo_df.head()
此时,如果您愿意,可以删除“纬度”和“经度”列,但是 GeoPandas 会在您绘制数据时自动引用“几何”列。要做到这一点,我们只需将数据放在上面绘制的地图上。我将更改一些显示选项,以便我们的地图更容易看到,使用蒙版用不同的标记绘制 WNV+和 WNV-蚊子,并添加标签和图例:
fig, ax = plt.subplots(figsize=(15,15))
street_map.plot(ax=ax, alpha=0.4, color='grey')
geo_df[geo_df['WnvPresent'] == 0].plot(ax=ax,
markersize=20,
color='blue',
marker='o',
label='Neg')
geo_df[geo_df['WnvPresent'] == 1].plot(ax=ax,
markersize=20,
color='red',
marker='^',
label='Pos')
plt.legend(prop={'size':15})
你做到了!有大量的选项和令人敬畏的包可以使用,并与 GeoPandas 结合使用来制作地图。如果你想深入了解,我建议你从散景开始。虽然它不像单独使用 GeoPandas 绘图那么容易,但它可以为您的地理地图添加一些令人印象深刻的交互功能,并且使用起来非常有趣!
希望到现在为止,你已经习惯于用 GeoPandas 制作简单的图形了。它们非常适合于探索性分析,以及快速直观地传达空间信息。如果你有问题,请随时联系我,或者给我发一些你的 GeoPandas 作品的例子!
地理空间数据—基准入门
原文:https://towardsdatascience.com/geospatial-data-a-datum-primer-479b7ca8635c?source=collection_archive---------6-----------------------
当我还是个孩子的时候,我和我爸爸一起看星球大战,他问我斗狗飞船是在上升还是下降。我的反应,“爸爸,那很傻,太空中没有上下之分!”
在太空中,当你在太空中“向上”或“向下”时,没有恒定的参考,并且在许多方面,当提供地面数据的参考时,存在相同的问题。这些年来,这个问题变得越来越复杂,但本质上还是一样的。
地理信息系统 (GIS)的强大之处在于能够创建一个关系空间框架来设置信息层,从而获得洞察力。但是首先最基本的…
投影和纬度/经度
制图学是制作地图的研究和实践,在人类历史中有很深的渊源。公元前 3 世纪的厄拉多塞最早提出以(北/南)和(东/西)作为坐标系。测量分为度、分和秒,可以扩展为*数以提高精确度。如果秒被测量到六个*数位,它们将精确到 4 英尺,而如果只测量到一个*数位,它们将精确到 6.9 英里。****
This is an example of a Web Mercator projection
纬度和经度描述了地球的三*结构,但将其转换到 2D 地图上需要使用 投影 ,或者一系列将曲面上的点的位置转换到平面上的位置的变换。很容易就有一整篇文章讨论各种预测的利弊。
精度是对地图要素的观测或估计结果与其真实值或位置的接近程度的测量。现代制图中有两种类型的精度:
- 相对精度:相对精度是地图上给定点相对于同一地图内其他点的精确程度。制图通常使用一个已知的点,并根据这个局部参考进行测量。
- 绝对精度:绝对精度是指地图上的某个点与现实世界中某个固定坐标系的对应程度,即地图上某个点的经纬度与实际 GPS 坐标的对应相当准确。
现代应用,如自动驾驶汽车或飞机自动驾驶,需要比 50 年前更高的精确度。当前标准的发展反映了对提高精确度所面临的问题的解决方案。
位置的问题
在地球上放置一个参考点并不像最初看起来那样简单。首先,地球并不是一个完美的球体,而是由于重力而在中间凸起。它也是由移动的构造板块组成,当它们汇聚时也可能上升或下沉(在佛蒙特州,自 14000 年前冰川融化以来,地面仍在上升!).
最初的解决方案之一产生了自己的问题:平均海平面(MSL) 。这是通过长期测量海面高度并进行数学平均以消除波浪、潮汐以及风和海流短期变化的影响来确定的。
但是,它不会消除当地重力强度、水温和盐度的影响,因此 MSL 相对于大地基准面(不是基于实际海平面)的高度在世界各地会有所不同。通常一个国家会选择一个特定点的平均海平面作为所有制图的标准“海平面”。
http://wiki.gis.com/wiki/index.php/Chart_datum
当涉及到航海图时,水手必须能够知道在任何一点可能出现的最*水深。海图上的深度和潮汐是相对于海图基准面测量的,该基准面被定义为潮汐很少下降的水平面。这可能会造成船只搁浅或安全通过的差别。
回顾历史,海平面也没有在整个地质时期保持不变。当比较数据时,所有这些变量都会产生巨大的问题。
参考椭球、大地水准面和基准面
为了提供一组通用参考,使用了一个基准。通常,基准面定义了表面和表面相对于地球中心的位置。基准面有两种类型:水平或垂直。绘制北美海岸线的最初努力始于 1807 年杰斐逊总统和费迪南德·哈斯勒领导下的美国海岸测量局,但直到许多年后第一个标准化数据才在北美被广泛采用。
水平基准提供了一个固定点的参考和一个 参考椭球 模型,更好地代表了地球的非球面形状。1927 年的 北美基准 (NAD 27)使用了堪萨斯州米德牧场的一个固定点作为美国和克拉克椭球的邻接中心,因为它与美国非常吻合,并且误差最*。这是多年来的共同标准。它的替代品, 北美基准 1983 (NAD 83),取而代之的是使用地球的引力中心(也叫地心基准)作为椭球的固定参考。
垂直基准面用于根据平均海平面、潮汐数据或使用重力来表示假设海平面的大地水准面来描述某点的高程或正高。目前的 1988 年【NAVD 88】北美垂直基准是一个大地水准面模型,它使用能够高精度测量重力的仪器来创建一个假设的形状,即在没有风和潮汐等其他影响的情况下,海洋表面仅受地球重力和自转的影响。地壳密度和山脉等特征会影响大地水准面的形状,它会偏离基于椭球的基准面,如 WGS84 、 GRS80 或 NAD83 。********
在一个联系日益紧密的世界中,对通用视角的需求导致了以椭球体模型为起点的全球基准,如 WGS72、 大地测量系统参考 1980 (GSR 80),以及最终的 1984【WGS 84】世界大地测量系统 。
WGS84 是最常用的国际标准,是 1987 年 1 月以后全球定位系统(GPS)使用的参考坐标系。误差被认为*于地球中心质量的 2 厘米。
基准位移
每个数据集应该有哪些数据用于 元数据阅读和理解它可以节省大量的时间和以后的痛苦。不能将两个具有不同基准面的数据集叠加在一起,因为它们不会对齐。相反,有一个将数据从一个数据转换到另一个数据的过程,称为数据转换;也叫坐标变换( EPSG 、 OGC )或地理变换 ( ESRI )。不同基准面之间的误差幅度可以*到几百英尺。
例如,自 1986 年建立原始大地测量基准以来,国家大地测量局已多次调整 NAD 83 基准,必须考虑这些细微差别。所有基准的完整列表太长,无法在此列出,但请看该列表了解更多信息。
同样重要的是要理解,通常局部基准面的坐标系原点不在地球的中心,而是局部基准面的椭球体偏离了地球的中心。NAD 27 和 1950 年欧洲基准(ED 1950)是本地基准。NAD 27 的设计相当适合北美,而 ED 1950 则是为欧洲使用而设计的。因为局部基准面将其椭球体与地球表面的特定区域如此紧密地对齐,所以它不适合在设计区域之外使用。
基准的未来
技术及其应用方式的变化总是需要对基准进行更新,NAD 83 和 NAVD 88 将在 2022 年被更新的版本所取代。这将校正大陆漂移,并有助于提高精度,因为 NAD 83 的非地心距离约为 2.2 米(约 7.2 英尺)。精度方面的一些问题是使用被动大地测量标记确定的基准的产物,这些标记已经随着时间的推移而退化。
取而代之的新数据将主要依赖卫星的 GPS,随着时间的推移,GPS 将变得更容易、更精确。取代三个现有 NAD 83 参考框架的将是四个平板固定地球参考框架:
- 2022 年北美地球参考框架(NATRF2022)
- 2022 年太平洋陆地参考框架(PATRF2022)
- 2022 年马里亚纳地球参考框架(MATRF2022)
- 2022 年加勒比陆地参考框架(CATRF2022)
- 2022 年北美-太平洋位势数据(NAPGD2022)
在 NAPGD2022 中,将有一个大地水准面的时间相关模型,在三个区域提供(第一个覆盖整个北美和中美、夏威夷、阿拉斯加、格陵兰和加勒比海,第二个覆盖美属萨摩亚,第三个覆盖关岛和马里亚纳群岛联邦),将被称为大地水准面 22。
像所有科学领域一样,这是一个不断发展的过程,以适应当代人的需求。超级精确的地理空间数据所展现的潜力可能会改变生活,但像大多数事情一样,理解它的遗产也很重要。深入研究,看看元数据,看看你能找到什么!
使用 Dask 和 Geopandas 进行大规模地理空间操作
原文:https://towardsdatascience.com/geospatial-operations-at-scale-with-dask-and-geopandas-4d92d00eb7e8?source=collection_archive---------1-----------------------
May 2016 New York City Taxi Dropoffs Heatmap by Taxi Zone.
在本文中,我将给出一个空间连接的示例,然后描述如何使用 GeoPandas 和 Dask 执行大规模的空间连接。
注意:为了精简这篇文章,我删除了交互式图形和大部分代码。你可以在 nbviewer 上查看 Jupyter 的原始笔记本。
第 1 部分:对空间连接的简单介绍
我在分析纽约市出租车数据集时遇到的一个问题是,从 2009 年到 2016 年 6 月,出租车行程的起点和终点都是以经度和纬度点的形式给出的。2016 年 7 月之后,为了在向公众发布数据时提供一定程度的匿名性,出租车和豪华轿车委员会(TLC)只提供一次旅行的开始和结束“出租车区域”,以及一个指定边界的 shapefile,可在此处获得。为了获得连续的数据集,我需要一种有效的方法将经纬度坐标对转换成“出租车区域”。让我们在 Geopandas 中加载 shapefile,将坐标系设置为' epsg:4326 ',这是经纬度坐标。以下是前几行。
The first few rows of the dataset.
我们看到几何列由多边形(来自 Shapely)组成,这些多边形的顶点由经度和纬度点定义。让我们按照 LocationID 的升序来绘图。
Taxi Zones chloropleth colored by taxi zone ID
这是一张熟悉的纽约地图,显示了 262 个出租车区域,用出租车区域的 id 进行着色。我发现 LocationID 没有任何特定的地理顺序。我在洋红色加了一个随机点(-73.966 \u E,40.78˚ N),正好落在中央公园中间。分配一个点在滑行区域内是人类可以很容易做到的事情,但在计算机上,这需要解决多边形问题中的点。幸运的是, Shapely 库为 Python 中的这种几何运算提供了一个简单的接口。但是,多边形中的点在计算上是昂贵的,并且使用 24 亿(纬度,经度)对上的 Shapely 库来分配出租车区域,就像在纽约出租车数据集中一样,将花费现代单核 cpu 大约四年的时间。为了加快速度,我们计算每个滑行区域的边界框,如下所示:
Bounding boxes for each Taxi Zone
现在,给定一个(经度,纬度)坐标对,包含该坐标对的边界框可以用一个 R 树有效地计算出来。你可以在这里找到关于 R 树的精彩介绍。只需要检查具有包含坐标对的边界框的多边形(滑行区域),然后为这几个滑行区域(希望如此)求解多边形中的点。这将计算量减少了大约 100-1000 倍。将坐标对分配给滑行区域的过程就是空间连接的一个例子。 Geopandas 为 Python 中的高效空间连接提供了一个很好的接口,它负责为您计算边界框和 R 树,如执行左空间连接的代码片段所示。
import geopandas as gpd
from shapely.geometry import Pointdf = gpd.read_file('taxi_zones.shp').to_crs({'init': 'epsg:4326'})
df = df.drop(['Shape_Area', 'Shape_Leng', 'OBJECTID'], axis=1)gpd.sjoin(gpd.GeoDataFrame(crs={'init': 'epsg:4326'},
geometry=[Point(-73.966, 40.78)]),
df, how='left', op='within')
此代码对上面地图上的单个点(用洋红色绘制)进行合并,并在中央公园正确地识别它
The spatial join for the magenta point in the figures above
第 2 部分:使用 Dask 进行大规模空间连接
在我的纽约公交项目中,我下载并处理了整个 200GB 的出租车数据集。在这里,我从 taxi 数据集(2016 年 5 月)加载一个文件到 Dask,并显示前几行和几列。该文件 1.8GB 有点大,Dask 选择将数据帧划分为 30 个分区,以提高计算效率。每个分区都是一个 pandas 数据帧,dask 负责所有的逻辑,将组合视为一个单独的数据帧。这里有几个栏目。
The first few rows of time and location data in May 2016
所以每次旅行都有接送(经度,纬度)坐标对。为了让您对数据有个感觉,我画出了第一次旅行的起点和终点,终点在东村。驾驶方向带来了很多额外的复杂性,所以这里我只画了一个直线箭头。空间连接将出租车区域标识为克林顿东和东村。
The first trip in May 2016 — As the crow flies
所以,Dask 数据帧只是*猫数据帧的集合,我知道如何在*猫数据帧上执行空间连接。让我们利用 Dask 的[map_partitions](http://dask.pydata.org/en/latest/dataframe-api.html#dask.dataframe.DataFrame.map_partitions)
函数对每个分区上的滑行区域进行空间连接。下面是执行空间连接的函数,给定一个 Pandas 数据帧,以及经度、纬度和 taxizone id 列的名称。代码直接链接到这里。
按比例
使用map_partitions
函数,我将空间连接应用于组成 Dask 数据帧的每个*猫数据帧。为了简单起见,我只调用该函数两次,一次用于取货地点,一次用于卸货地点。为了帮助 dask 确定返回数据的模式,我们将它指定为一列浮点数(允许 NaN 值)。
trips['pickup_taxizone_id'] = trips.map_partitions(
assign_taxi_zones, "pickup_longitude", "pickup_latitude",
"pickup_taxizone_id", meta=('pickup_taxizone_id', np.float64))
trips['dropoff_taxizone_id'] = trips.map_partitions(
assign_taxi_zones, "dropoff_longitude", "dropoff_latitude",
"dropoff_taxizone_id", meta=('dropoff_taxizone_id', np.float64))
trips[['pickup_taxizone_id', 'dropoff_taxizone_id']].head()
此时,trips Dask 数据帧将具有有效的 taxizone_id 信息。让我们将这些数据保存到 Parquet 中,这是一种列格式,在 Dask 和 Apache Spark 中得到很好的支持。这可以防止 Dask 在每次需要对 trips 数据帧进行操作时重新计算空间连接(这是非常昂贵的)。
trips.to_parquet('trips_2016-05.parquet', has_nulls=True,
object_encoding='json', compression="SNAPPY")
trips = dd.read_parquet('trips_2016-05.parquet',
columns=['pickup_taxizone_id', 'dropoff_taxizone_id'])
为了结束这篇文章,我将使用 Dask 生成一个出租车下车地点的热图,按出租车区域进行汇总。不出所料(至少对纽约人来说),绝大多数出租车停靠点都在曼哈顿的市中心和中城区。我将在以后的文章中进一步分析这个数据集。
May 2016 New York City Taxi Dropoffs by Taxi Zone.
摘要
在这篇文章中,我描述了空间连接的过程,并使用 Dask 和 Pandas 在集群上进行大规模的空间连接。我忽略了对整个纽约出租车数据集很重要的一些细节,但是我的完整代码可以在 Github 上的这里找到。在以后的文章中,我将更彻底地分析这些数据,并可能将处理后的数据作为一个 parquet 文件发布,供其他人分析。
关于空间连接性能的补充说明
上面使用 GeoPandas 编写的空间连接使用纽约出租车数据集,可以在 4 GHz 4 核 i5 系统上为每*时大约 4000 万次出租车行程分配出租车区域。许多支持这种连接的代码是 Python 和包装 C 代码的某种融合。
这比在高度优化的 PostGIS C/C++代码中执行相同的空间连接大约慢两倍。然而,PostGIS 并没有有效地使用多个内核(至少在没有多个空间连接同时运行的情况下),更重要的是,往返 PostgreSQL 数据库的网络和序列化开销使 PostgreSQL/PostGIS 的速度与我在本文中描述的 GeoPandas 实现的速度大致相同,需要打破的移动部分要多得多。
基本上,对于这些类型的数据结构操作,Python 实际上是相当快的 T2 T3。
开始使用 sci kit-了解 Kaggle
原文:https://towardsdatascience.com/get-going-with-scikit-learn-on-kaggle-32045d238eee?source=collection_archive---------10-----------------------
Taipei, Taiwan
Scikit-learn 一直是机器学习入门的流行库。然而,并不是每个人都有机会尝试它。我将向您展示如何使用 scikit——用最短的路径学习,您只需要一个 web 浏览器!
Taipei, Taiwan
在这篇文章中,我将帮助你开始在一个 Kaggle 内核中使用 scikit-learn ,并为你指出可以用来指导你继续学习的资源。
[## Kaggle 内核简介
在《人工智能历险记》的这一集里,你会发现什么是 Kaggle 内核,以及如何开始使用它们。虽然没有…
towardsdatascience.com](/introduction-to-kaggle-kernels-2ad754ebf77)
简短的历史课
让我们从一点历史开始,作为背景。Scikit-learn 最初被称为 scikits.learn ,最初是由大卫·库尔纳珀发起的谷歌代码之夏项目。名称中的“scikit”部分来自于它是一个 Sci Py 工具工具包。
从那以后,scikit-learn 稳步地获得了采用和流行,直到今天:一个有良好文档记录、深受喜爱的 Python 机器学习库。如果你看一下scikit-learn.org,你会注意到版本号很低,在这篇文章发表时是 0.19。不要被这个吓跑了;图书馆已经存在很长时间了,*护得很好,相当可靠。
Scikit-learn 是做什么的?
它真正出色的地方是一套丰富的工具,我称之为“围绕机器学习的”,包括从数据集加载和操作到预处理管道和指标的一切。在我看来,scikit-learn 真正令人难以置信的部分是您可以尝试的大量机器学习算法,其中大多数只需进行最*的代码调整!
这确实是一种令人惊奇的方法,可以掌握不同类型的模型做什么,以及获得一些关于各种参数如何执行的直觉。
我使用 scikit-learn 创建了一个简单的 Kaggle 内核来帮助您入门,它还展示了内核和数据集之间的连接。跟随这个简短的视频一行一行地浏览内核,并讨论每个步骤:
如果你准备好了使用 Kaggle 内核并与其他人合作的更复杂的方法,请查看这篇关于在 Kaggle 上创建数据科学项目的帖子:
[## 使用 Kaggle 数据集和内核设计一个数据科学项目
在《人工智能历险记》的这一集里,我请到了 Kaggle Datasets 的产品负责人 Megan Risdal,带我们参观一些…
towardsdatascience.com](/cooking-up-a-data-science-project-using-kaggle-datasets-and-kernels-fca2b678e268)
后续步骤
这只是非常简单地介绍了如何开始使用 scikit-learn ,但是您应该探索 scikit-learn 提供的广阔的机器学习模型世界,所有这些都是通过一个简单干净的 API 实现的!深入学习教程和文档,制作一些令人敬畏的模型。
下次我们将讨论机器学习的另一面——scikit-learn——进行预测,以及如何扩大规模!
感谢阅读这一集的云人工智能冒险。如果你喜欢这个系列,请为这篇文章鼓掌让我知道。如果你想要更多的机器学习动作,一定要关注媒体上的我或订阅 YouTube 频道以观看未来的剧集。更多剧集即将推出!
准备好迎接更快、更简单、更有趣的炉石吧
原文:https://towardsdatascience.com/get-ready-for-a-faster-easier-and-more-fun-hearthstone-c6163e0a0d75?source=collection_archive---------0-----------------------
暴雪最近宣布对其轰动一时的纸牌交易游戏炉石进行一些看似微*的改动。我们来看看。来自暴雪:
“一旦玩家达到15 级、10 级或 5 级,他们将无法在一个赛季内取消该等级,类似于现有的 20 级和传奇等级。”
这将如何改变梯子上的游戏?嗯,会好起来的。好多了。
更快、更稳定的攀爬
今天,即使是最好的玩家也需要 400-600 场比赛(在一个月内)才能达到传奇。随着新排名游戏楼层的增加,你将免受这种流失的影响,减少 5-10%的游戏数量。
游戏会更容易
上周我发布了关于游戏难度以及它如何随着等级(duh)和月中的某一天(与赛季中的某一天同义)而变化。我甚至建立了一个模型来展示这个样子。
从 5 级爬到传奇仍然会非常困难,但是爬更低的等级会容易一些。
炉石会更好玩
最令人兴奋的是,这些变化将让你自由地尝试新的甲板,因为当你坐在这些地板之一的北面时,你没有什么可失去的。这种额外的变化将是一个受欢迎的补充,特别是在上层,目前除了 3-5 个顶层甲板中的一个之外,无法使用任何东西。
准备好永远不再相信互联网上的任何东西
原文:https://towardsdatascience.com/get-ready-to-never-trust-anything-on-the-internet-ever-again-8978352fa91b?source=collection_archive---------2-----------------------
伪造一切的兴起
直到大约 10 年前,伪造照片还极其困难,需要精心的设置、模糊的图像以及古代民间传说和轶事的力量才能让人相信。
今天,任何人只要有一台电脑并能上网,就能在几*时内伪造一幅图像,如果不是几分钟的话。
多年来,我们已经不接受我们看到的每一张图片,以防它们被 PS 或编辑成错误的信息。
其他媒体,如音频和视频,还没有被如此仔细地考虑过。最近的技术进步意味着这种情况可能不得不迅速改变。
Lyrebird 是一家人工智能初创公司,它允许通过输入几分钟的讲话内容来克隆任何人的声音。这项技术可能带来的错误信息的可能性是巨大的。几年之内,电话可能完全是伪造的这一点就足够令人信服了。
更重要的是,随着计算能力每 18 个月翻一番,如果今天电影中的 cgi 看起来相当有说服力(查看此视频以查看《星球大战 7》的 CGI 与真实对比),等待 5 年,看看差异。
随着越来越多的假新闻在网络上流传,这可能会使问题变得更糟。例如,看下面这个视频,其中前总统奥巴马的视频是根据脚本合成的。
根据摩尔定律,在接下来的几年里,技术将以人类历史上前所未有的速度发展。人们需要在被利用之前意识到人工智能和其他技术的潜力。
虽然它们现在看起来神秘而遥远,但这些技术将很快到来,当它们到来时,我们需要为此做好准备。
想象一下,在未来 10 年内,甚至青少年也能像现在使用 photoshop 一样使用这些技术。
机器人已经在网上传播关于政治的假新闻,而经过 PS 处理的图像正在作为真正的新闻传播。
在开发这些技术的同时,处于各自领域前沿的研究人员和公司需要*心他们的产品不被恶意使用。
为了成功跨越今天的技术与明天的技术之间的鸿沟,我们需要确保负责任地使用它,并让人们了解它可能产生的潜在错误信息。
正如这个短语一样,“PS 图像”已经成为普通大众词汇的一部分,“x-ed 音频”和“y-ed 视频”也是如此。
我们还没有看到这些公司会是谁。
感谢阅读,
¯_(ツ)_/¯
萨尔瓦夫
看看我的其他故事吧!
十五个 Y/O 给聊天机器人工作人员的消息—https://medium . com/swlh/A-Message-From-A-fifty-O-to-any one-Working-With-Chatbots-fd1b c 6292028
因为这个令人难以置信的独特原因,普遍基本收入是必要的—https://medium . com/forward-data-science/why-Universal-Basic-Income-Is-required-it-not-than-what-you-think-ab 602 f62a 207
利用数据科学变得更聪明—应对真正的企业挑战
原文:https://towardsdatascience.com/get-smarter-with-data-science-tackling-real-enterprise-challenges-67ee001f6097?source=collection_archive---------9-----------------------
数据科学战略指南—第 1 部分
让您的数据科学项目从零开始走向生产
介绍
' 《数据科学战略指南——用数据科学变得更聪明' 被设想为一系列文章,这些文章更像是一份战略指南,描述了在现实世界中实施和执行数据科学项目时需要牢记的基本挑战、陷阱和原则。我们还将介绍如何通过关注非常真实的视角并远离炒作,从数据科学和人工智能中获得最大价值。这将使您能够在自己的领域内推动行业成功!这里的重点更多的是在行业中执行的真实项目,但是这些原则中的一些也适用于研究。
Source: https://xkcd.com/
一般来说,我的大部分文章都是面向实践的,针对的是构建系统的人和真正从事数据科学的。然而,本指南面向更广泛的受众,包括高管、企业、架构师、分析师、工程师和数据科学家。根据我的观点和经验,您需要所有这些来成功执行数据科学项目并获得最大价值!
您是否厌倦了您的数据科学项目仅仅停留在概念验证阶段?
当您的项目最终投入生产并开始处理真实世界的数据时,您难道不喜欢吗?
你喜欢从数据中提供可行的见解来推动业务目标吗?
你想建立一个成功有效的数据科学团队吗?
我能为我的团队建立有效的数据科学和人工智能战略吗?
如果你对这些问题中的至少一个回答是肯定的,这个指南就是为你准备的!我们将通过一系列文章在本指南中涵盖以下主要方面:
- 第 1 部分—当前的挑战和潜在的解决方案
- 第 2 部分—建立有效的数据科学团队
- 第 3 部分—数据科学项目的流程模型
- 第 4 部分——有效的数据科学管道
- 第 5 部分——推动行业成功
本指南中表达的所有观点均基于个人经验、行业趋势以及与行业专家的交流。本指南的目的不是传播任何偏见或成见,而是给出在企业中执行数据科学项目时要检查的核心组件的清晰概念。我仍然不认为自己是这个领域的专家(要学的东西太多了!)但是我希望这个指南能帮助你获得一些关于有效执行数据科学项目的有用观点。
在这篇特别的文章中,我们将关注一些困扰行业的关于执行数据科学项目的非常真实的挑战和一些潜在的解决方案。
当前的挑战和潜在的解决方案
大多数数据科学家(包括我自己)喜欢现成可用的工具、库和框架。在解决不同的问题时,我们有自己的个人偏好。由于这些工具和方法的临时使用,再加上我们的偏好,这导致在实际尝试部署和*护数据科学项目工件和资产时增加了工作量。
Source: https://xkcd.com/
在本节中,我们将了解一些最重要的挑战和陷阱,这些挑战和陷阱经常困扰着从未走出概念验证阶段的数据科学项目,以及一些关于我们如何应对它们的指导。
分散的技术格局
数据科学工具的技术前景是巨大的,并且每天都在变得更大。再加上大数据、人工智能和其他一些术语,你会看到一个更大的工具、库和框架的景观。在数据科学中,从数据科学家的角度来看,这一切都是为了使用最好的(或最容易使用和理解的)工具来解决问题,因为方法-统计或机器学习\深度学习都建立在数学、统计和优化的基础上,只要实现的算法或方法是统一的,特定的工具或框架的使用对他们来说并不重要。我相信你一定听说过这样一句话,‘不要专注于工具和框架。专注于要解决的问题!。
Source: https://xkcd.com/
这没有错。通常,一个数据科学家(像我一样)可能喜欢开始查看数据,打开 R 或 Python,开始编写代码来做一些分析或构建模型。基于从事数据科学的人们的使用模式,我们通常有两个极端。有些人喜欢使用编程语言,如 R、Python、Scala 或 Java,加上框架和库,使他们能够轻松地进行复杂的分析。其他人喜欢使用基于“无代码、图形拖放界面”的工具,如 KNIME、RapidMiner、Weka 等等。
拥有使用我最了解的工具的心态,对于数据科学项目来说可能是毁灭性的,因为缺乏标准化、最*架构,尤其是如果构建项目的人最终在项目部署后离开了公司。构建一个概念证明是非常好的,但是当你需要将你的项目转移到生产中时,还要考虑以下几个方面——使用模式、可伸缩性、标准化架构、与现有系统的集成* 和 可*护性 。*
从众倾向(和炒作)
让我们面对它,我相信我们都已经看到这种情况在行业中发生,特别是围绕人工智能、自动机器学习、公民数据科学家等产生的所有宣传。C 级高管需要制定适当的数据科学和人工智能战略,并确定他们的关键业务和战略目标、数据可用性和必要性,以及数据科学和分析如何帮助他们实现这些目标。他们当然需要咨询领域专家和员工,以保持技术和业务之间的平衡。请记住,数据科学与现有业务流程的结合是推动成功的因素,两者协同工作,而不是孤立存在。
Source: https://xkcd.com/
盲目追逐大数据、数据科学或深度学习的宣传,没有目的地匆忙制定战略,可能会浪费在这些领域投入的时间、金钱和精力。如果没有最终目标或结果来说明为什么要这样做,那么像、、、、、【为所有企业数据创建统一的数据湖】这样的战略肯定会发出危险信号。这些说法并不离谱,有趣的是,你可以看看这篇文章 关于数据湖没有带来商业价值的 3 个原因在过去几年的大肆宣传之后 这篇来自 CIO.com 的文章 还告诉我们,
“数据湖需要证明商业价值,否则就会消亡”
始终将任何战略与定义明确、清晰的成果以及可用于衡量这些成果的关键绩效指标联系起来。这些不必一成不变,但也不应该太模糊。这不是一项简单的任务,但必须完成。
缺乏可重复性和可重用的工件
数据科学分析和代码需要是可复制的。有多少次我们听到这些台词——‘上周模型给了我 90%的准确率’或者‘代码在我的机器上运行良好!’。嘿,我也去过那里,被指控有罪!在使用编程语言和框架时,像设置随机种子这样简单的事情,对可重复分析大有帮助。除此之外,如果你想跟踪一段时间‘哪个模型训练了什么数据,给出了什么样的性能指标?’那么模型、数据和特性集版本化是必不可少的然后利用最佳模式或恢复到以前的模式。利用虚拟环境和容器是确保你不会陷入“包依赖地狱”的好方法。
Source: https://xkcd.com/
Jupyter 笔记本是实现可重复研究和数据分析的一种很好的方式,通常是数据科学家的首选工具。我强烈推荐任何感兴趣的人阅读这篇精彩的文章,这篇文章讲述了笔记本电脑如何在业务中实现可复制性。
* [## Jupyter 笔记本电脑迎接再现性的挑战——新堆栈
每个应用程序都需要有一个杀手锏。对于 Jupyter 笔记本来说,这个特性可能是可再现性…
thenewstack.io](https://thenewstack.io/jupyter-notebooks-challenge-reproducibility/)
甚至 Jake Vanderplas 在他的文章 中也收集了大量关于 Jupyter 笔记本 的视频和教程。另一篇有趣的论文是 Adam Rule 等人的“Jupyter 笔记本中可重复研究的十个简单规则”,可在 此处 找到。他们谈到了一套规则,作为科学家的指南,特别关注计算笔记本系统。
Source: https://arxiv.org/abs/1810.08055
但是,并非一切都是完美和美好的,在使用 Jupyter 笔记本时,需要记住几个注意事项。我推荐大家一定要看乔尔·格鲁什的这个精彩演讲, “我不喜欢笔记本” 讽刺地在 JupyterCon 2018 上呈现!
这里的另一个重要方面是可重用性。鉴于许多数据科学家通常喜欢以特别的方式单独工作,因此缺乏适当的协作。项目和人员以前所未有的速度流失。因此,如果你的项目是围绕着一堆分布在不同系统中的未记录的代码工件和脚本构建的,那么如果这些工件的开发人员突然离开,你将会猛然惊醒。除此之外,通常还有一些可重复的特定使用模式,如数据提取、ETL(提取-转换-加载)、功能工程,甚至是在相同数据集上建模。开发可重用的工件和组件,并使它们在公共存储库中易于访问,将在未来节省大量时间,而不是数据科学家为每个新项目重新创建这些工件。
缺乏协作—打破孤岛思*
数据科学家通常喜欢按照自己的节奏,以特别的方式做实验和分析数据。这有助于创造性思*和创新。虽然这一点都不坏,但我们确实需要开始合作,分享更多我们正在做的工作,并且在团队中工作(有时结对编程真的很好!).
Source: https://xkcd.com/
最好的方法之一是确保围绕项目中正在进行的工作召开定期会议,围绕每个人正在做的事情明确定义具体的交付成果和任务,并进行混合任务,数据科学家可以独自工作,也可以与其他数据科学家甚至工程师协同工作。这将有助于促进知识共享、协作工作,以及在有人突然离开的情况下项目不会沉没。
要避免的一个更关键的陷阱是——【筒仓心态】 ,这基本上是一种心态,出现在某些部门或部门不希望与同一公司的其他人共享信息的时候。
[## 筒仓心态:如何打破壁垒
这篇文章是与互联网营销公司的梅根罗索合著的
www.forbes.com](https://www.forbes.com/sites/brentgleeson/2013/10/02/the-silo-mentality-how-to-break-down-the-barriers/#2cd2652a8c7e)
我相信你们中的很多人以前都面临过这种情况,甚至到今天也面临着这种情况。人们和团队需要认识到,只有通过共享和协作,才能创造伟大的事物,解决问题,项目才能成功。筒仓心态会导致生产力、效率的损失,降低士气,最终项目会被废弃。协作、朝着共同的目标努力、适当的激励和动机可以大大有助于为数据科学培养健康、高效的工作文化。鼓励工程师、分析师、科学家和建筑师在一个项目中一起工作,同时明确他们各自的具体任务。
将关键数据科学项目外包给第三方公司
不要误解我的意思,我们有许多纯粹的分析公司,他们拥有正确的专业知识,可以为希望更多数据驱动的公司提供关键的见解。但是,如果您计划真正长期投资以获得数据科学推动业务决策的好处,请在内部投资一个优秀的数据科学团队(或者根据公司规模、垂直行业等投资多个团队)。这样做的好处是多方面的。你不必担心公司带你去兜风或顾问在项目上工作,然后你不得不忍受*护他们的痛苦,当他们在合同到期后方便地消失时,通常在概念验证或 MVP(最低可行产品)阶段结束时。你也永远不会得到和你自己的员工一样的信任。也就是说,如果你有很多数据科学项目正在进行中,并且有足够的预算,请放心将不太重要的短期项目交给这些纯粹的第三方分析公司。
除此之外,请克服被大肆宣传的公民数据科学家和自动机器学习的概念。让我们面对现实吧!公民数据科学家可以让你更加数据驱动,但不是每个人都可以为你解决棘手的问题。你需要真正的数据科学家来构建模型和系统,并搅动我们的洞察力。自动化机器学习并不是解决所有问题的灵丹妙药。不要因为你可以将一个数据源连接到这些工具中的一个,并开始获得现成的见解而感到失望。许多公司犯了这样的错误,没有被一套工具所束缚,也不知道如何使用它们。您需要知道如何有效地使用这些工具来真正帮助减少您的数据科学项目的开发时间。
技术债务—缺乏标准和项目架构
对于任何与构建软件和产品相关的技术和工程公司来说,这都是事实。通常,从事数据科学项目的人会想,“这些是软件工程方法和原则,我们远不止这些”。不要!你肯定不是最重要的,没有意识到这一点,可能会在你真正复杂的深度学习模型中留下一个巨大的漏洞,导致又一个失败的概念验证,无法投入生产。
Source: https://xkcd.com/
跨团队启用适当的编码标准。在必要的地方构建可重用资产,但不要做得太多。一个关键的方面是不要总是只关注数据科学的工具和框架,还要关注非功能性需求(nfr)。流行的 nfr 有可扩展性、可*护性、可用性等等。就像我们有软件项目的企业架构一样,我们需要架构师和数据科学家与他们合作,为每个数据科学项目定义项目架构(解决方案-应用程序&数据),其最终目标是部署到生产中。下图描述了一个标准的分层企业架构。
Layered Enterprise Architecture Hierarchy (Source: IBM)
许多内容摘自一本名为 “数据科学西部的架构思考” 的优秀指南,该指南实际上谈到了数据科学项目中的许多挑战,以及定义项目架构的潜在优势。
[## 数据科学蛮荒西部的架构思考
自由选择编程语言、工具和框架可以提高创造性思*和发展。
developer.ibm.com](https://developer.ibm.com/articles/architectural-thinking-in-the-wild-west-of-data-science/)
典型地,一个 企业架构师 定义了在整个企业中有效的标准和指导方针。一个 解决方案架构师 在企业架构师定义的框架内工作。这个角色定义了哪些技术组件适合特定的项目和用例。您还可以选择 应用架构师 ,他们更关注解决方案架构框架内与应用相关的组件,以及 数据架构师 ,他们定义与数据相关的组件。解决方案架构师通常会担当这些角色。
通常,数据科学家很少与企业架构师互动,而是更多地与解决方案架构师(以及应用程序/数据架构师)直接合作。数据科学家应该能够为他们的项目设想端到端的解决方案架构,甚至为架构师提供必要的输入,以便随着时间的推移改进和转变企业架构。进化是关键,由于数据科学是一个新兴的创新领域,您需要摆脱数据科学项目的常规软件项目架构模板。
压装工具和行业标准流程
仅仅因为过程模型适用于特定的项目或垂直行业,并不意味着它对数据科学也是有效的。许多企业,尤其是拥有大量员工的公司,往往会在日常运营和项目执行中使用大量流程。我们曾经有瀑布模型。现在我们有了看板缩放敏捷ScrumScrum ban等等更多的变种!这里的意图是不要严格遵循这些过程框架,而是根据项目的类型,将它们改编成可能最适合您的团队的东西。从事与产品开发直接相关的数据科学工作?也许更关注 scrum 驱动的敏捷思*。从事更具探索性或咨询性的特别项目?也许看板或 Scrumban 可能更适合你。关键的想法是从一组标准开始,并具有随时间发展的灵活性。对改变保持开放的心态,但改变某些东西是有原因的!
Source: https://xkcd.com/
关于工具和框架,就像我们之前提到的,正确的工具或框架确实是基于要解决的问题,但总是有一套关于从定义的工作流、模式、编码标准和架构开始的使用的标准和指南。也不要把工具强加给问题。不,自动化机器学习不会自动从原始数据中给你最好的模型或见解。您仍然需要了解业务问题、成功标准以及使用这些工具以有效方式帮助解决问题的正确方法。就像你永远不会优化一个模型来最大限度地解决每个问题一样,不要在不知道为什么要使用一个工具的情况下就使用它。
数据科学和工程之间的差距
作为数据科学家,我们往往会忽略一个事实,即纯数据科学或机器学习组件只是构建整个项目或系统的所有其他组件中非常*的一个组件。NIPS 2015 论文, 【机器学习系统中隐藏的技术债务】 以如下视觉的形式完美地解释了这一点。
Major components of a Data Science Project \ System
ML 代码 组件就是你上图看到的那个很*的黑框。但通常数据科学家更专注于开发算法、建立模型、探索和分析数据。因此,这最终导致他们更多地忘记了全局。这不可避免地导致项目停留在概念验证阶段,永远不会被部署。这方面的一个经典例子是从 Netflix 奖挑战赛 中吸取的教训。Netflix 的 奖 是一场公开比赛,争夺最佳协同过滤 算法,根据之前的评分预测电影的用户评分。如果你看看他们在论文 “挖掘大规模用户数据流进行个性化推荐” 中提到的获奖经验,他们必须从获奖解决方案的 107 个模型中提取两个核心算法!然后,他们不得不扩展这些来处理超过 50 亿的收视率。除此之外,他们还提到不包括几个模型,因为将这些模型投入生产需要纯粹的工程努力。
“在网飞,我们评估了最终解决方案中包含的一些新方法。我们测量的额外精度增益似乎并不证明将其引入生产环境所需的工程努力是合理的。”
这清楚地告诉我们,为了整个系统正常运行,即使是数据科学家也需要对问题和端到端解决方案有一个整体的看法。因此,要在生产中部署数据科学项目,您需要将数据科学、数据工程、软件工程、架构、基础设施、监控和质量检查结合起来。忽视工程方面,说我只是建立机器学习模型,这不再是任何在该行业工作的数据科学家应该说的话。学会挺身而出,在需要时专注于项目的工程方面,并最大限度地利用工程团队——持续的合作有助于推动良好的协同作用。
忽略质量检查和操作
通常,在数据科学团队中工作的人认为,在‘所谓的’测试数据集上训练和评估他们的模型之后,他们的工作就完成了。缺乏质量、监控和控制检查可能会导致数据科学项目在部署后崩溃——这通常比实际开发阶段更重要!
Source: https://xkcd.com/
永远记住通过使用有效的策略来验证你的模型,比如验证数据集和交叉验证。检查数据泄露和目标标签泄露等问题。这里要记住的另一点是,在调优模型时,不要一直在训练数据上调优您的模型,并在测试数据上检查性能。然后你就间接地在测试数据上训练了你的模型!始终将数据科学和机器学习性能评估指标与您的业务指标和成功指标联系起来。流失模型可能需要更高的召回率,欺诈检测模型可能需要更高的精确度,反之亦然,这取决于业务需求!请记住,随着时间的推移,不断重新审视您的项目的成功标准和指标,因为这是您的项目在生产中部署的关键。
是否有其他的方法来评估和检查您已经部署的(或者将要部署的)模型的质量?典型的离线和在线场景可能保证不同的质量和测试方法。网飞的论文中提到了一个很好的工作流程, 【挖掘大量用户数据进行个性化推荐】 。
Testing Online and Offline Models (Source: Netflix)
模型度量、假设测试和 A/B 测试是您可以用来进行质量检查的关键工具。除此之外,你也不应该忽视操作方面。这意味着要确保部署适当的模型性能评估监控系统,以便您可以根据实时数据跟踪模型性能。请记住,一旦模型被构建和评估,项目就不会结束。通常,拥有持续集成和交付框架(CI/CD)也有助于持续确保您的代码库工作正常,并且不会在无人知晓的情况下突然中断。
结论
我希望这篇文章能让您对行业中关于执行数据科学项目的典型现实挑战有所了解。这里给出的建议只是一些通用的指导方针,并不是一成不变的。由于数据科学现在已经发展成为一个跨行业的学科,你们每个人都可能会找到更适合自己的特定方面,但要记住的总体挑战应该在本文中。我真诚地祝愿你们所有人在执行自己的数据科学项目中取得成功,如果有什么我忘记在这里提到的,请不要犹豫,告诉我什么最适合你!
下一步是什么?
我们为数据科学战略指南系列计划了许多有趣的内容!在下一篇文章 的 中,我们将从行业专家、企业和你的友好邻居作者——我自己——的角度,探讨如何建立有效的数据科学团队 !敬请关注一些有趣的内容!
有反馈给我吗?或者有兴趣与我一起从事研究、数据科学、人工智能甚至发表一篇关于 TDS 的文章?可以在LinkedIn上联系我。
* [## 人工智能顾问&数据科学导师-跳板| LinkedIn
查看 Dipanjan Sarkar 在世界最大的职业社区 LinkedIn 上的个人资料。Dipanjan 有 2 份工作列在…
www.linkedin.com](https://www.linkedin.com/in/dipanzan/)**