信息在你和你的朋友中流动
使用社交媒体信息的可预测性上限,即使一个人已经删除了他们的社交媒体存在
你已经喝得够多了。婴儿照片,朋友们的政治演说,甚至可爱的猫的照片!担心你的隐私和未来的职业安全。你决定删除你在脸书、推特和 Instagram 上的账户。你有一个好公司:数百万脸书用户在 2017 年开始离开该平台,未来看起来也不会太好。 Twitter 努力寻找新用户以保持活跃用户群不变,只有 Instagram 在增长。删除你的账户和你发布的所有内容后,你和数百万人都认为你是安全的。结果,你不是。因为,从信息论的角度来看,就像你从未离开过。
相反,如果你是一名数据科学家,试图建立基于社交媒体信息的预测性机器学习模型(社交媒体创造了每天产生的 2.5 万亿字节数据的很大一部分),你可能会认为能够使用个人数据进行预测会非常有用。从 Target 在受影响者的父母知道之前识别怀孕到预测政治忠诚度和选举结果,社交媒体数据是数据科学和机器学习的名副其实的宝库。因此,如果你是一名数据科学家,你很幸运!因为即使你感兴趣的人和他们生成的所有内容可能已经从社交媒体上消失,你仍然有机会预测他们的行为或情绪。以下是方法。

Limits of text predictability based on the availability of data from friends and the individual.
我们在这里引用的是佛蒙特大学的 James P. Bagrow、Xipei Liu 和 Lewis Mitchell 最近在自然人类行为杂志上发表的一篇文章。在这项工作中,作者探索了你可以从社交媒体中提取多少预测能力的极限,特别是在有问题的个人删除他们的社交媒体资料的情况下。原来,还挺多的!高达 95% 的预测力围着你转,不用你也能聚集。该怪谁呢?你的朋友!在你的封闭社会环境中嵌入了太多关于你的信息,数据科学家原则上不需要个体本身在场就能达到合理的预测准确度。在文章的最后,我们将讨论这种方法的潜在局限性,所以请不要离开。
但是让我们回到实际的出版物。进行这项研究的研究人员以信息论为指导。由贝尔实验室研究员克劳德·香农在第二次世界大战后构想的信息论是一门对通信过程中的数据丢失和压缩,或者简而言之,信息流等主题感兴趣的整体学科。香农还在信息论中引入了熵的概念,用事件的预期结果来表示不确定性的数量。熵值为 1 意味着我们根本无法预测哪一个事件会发生(例如,硬币的哪一面是由抛硬币产生的),而熵值为零意味着预期结果没有不确定性。这很重要,因为在这种情况下预测个人行为意味着根据过去预测他们未来(在 Twitter 上)会写什么。因此,较低的熵意味着你能够更好地预测一个人接下来会说什么,或者在给定提示的情况下会说什么(例如政治)。
在他们的工作中,Bagrow 等人使用预测未来文本所需的信息比特中给出的熵率。4 比特的熵率将对应于从 24 = 16 个字中随机选择每个预测字。这听起来可能不多,但考虑到社交媒体用户拥有大约 5000 个单词的词汇量,这是一个巨大的进步!这里一个重要的考虑是,信息论处理通信的限制,因此给定的熵率及其相应的可预测性意味着给定该数据的预测生成模型的上限。随机可预测性(词汇量为 5000 个单词)将为 0.02%,而 Twitter 用户在他们的数据集中的平均可预测性为 53%(对应于 6.6 位的熵率)。这意味着,在一个建立在 Twitter 数据上的理想模型中,超过每秒钟预测的单词都是正确的。
然而,这个故事的主要部分是关于你的朋友。类似于熵,交叉熵是预测你的短信所需的来自你朋友的比特数。在这篇文章中,作者为每个人选择了 15 个最亲密的朋友(这是这个人在 Twitter 上最常提到的)。第一个重要的点是,你的社交圈里有关于你的信息。将你和你的朋友的预测信息结合起来,可预测性增加到 60%以上(无限数量的朋友为 64%),尽管这里肯定存在收益递减,这意味着添加到模型中的第一个朋友的影响比第十个朋友的影响更明显。这一切都很好,可以改善预测,但现在来了弥天大谎。将你自己从社交媒体网络中移除,并且只使用你的朋友来预测你的文本,你最终对 15 个朋友的预测率为 56%,对无限多个朋友的预测率为 61%。我要明确一点:仅仅使用 8-9 个朋友(不使用个人本身),你就可以打破使用真实个人的信息,你可以获得个人+朋友的最大可预测性的 95%!
如果你是一个想要利用这一点的数据科学人士,这里有另一个见解:这种可预测性对于发布很多帖子(从而强烈影响/影响他们的朋友)的个人以及不发布很多帖子(否则他们的表达会太多样化)并经常提到个人的朋友来说尤其明显。因此,当一个人删除个人资料时,他在网络中留下的印记会因其个性和网络而异。
以下是这项研究的一些注意事项/限制:与所有此类研究一样,不幸的是,这种社交嵌入效应仅在实践中有效,前提是你在某个时候是社交媒体的积极用户,以便确定你的社交圈。然而,如果有其他方法将你和你的朋友联系起来(GPS 协同定位,在没有标签的帖子中提及,等等)。)如果他们在社交媒体上,这条警告就无效了。另一个考虑是,通过社交媒体获得的可预测性可能仅限于发布在社交媒体上的文本。虽然这仍然允许探索情绪和态度,但建立在此基础上的模型可能无法准确预测,比如说,个人撰写的长篇文章。最重要的限制,也是作者提到的,是这些嵌入的信息可能会随着你的社交圈的发展而改变(见鬼,他们中的一些人甚至会退出社交媒体)。因此,从个人退出社交媒体的那一刻起,你可能有很短的时间来开发一个表现良好的模型(这对你来说是好事,个人!).有趣的是,看看这是否可以通过在模型中包括更多的朋友,仔细选择“变化”程度低的朋友来保持嵌入,或者简单地依赖于旧的存档社交媒体数据(互联网什么都不会忘记)来缓解。

This is why prediction from your friends after you quit social media will be important. Source: Google Trends
总之,我认为这篇文章是我们在环境中保存信息的一个很好的例子。以城市为例。除了十字路口、天然港湾和商路的记忆,它们还能是什么?同样,我们的朋友至少代表了我们的一部分,并带着我们的信息。显然,如果有足够多的朋友,这足以教会一个模型比直接“研究”我们更好地了解我们。随着前面提到的传统社交媒体平台的大量涌现,对于对你的政治倾向感兴趣的广告公司或机构来说,这可能是一个黄金机会,可以利用机器学习和数据挖掘来保持或扩大他们的预测潜力。我想知道仅仅建立在朋友基础上的机器学习模型在实践中有多容易建立/强大!如果你尝试一下,请告诉我!
您可能会对文章中的一些附加注释/琐事感兴趣:
-社交媒体文本比“传统文本”更极端,有些很容易预测,有些很难处理。
-基于认知极限,邓巴的数字假设每个人最多有 150 个左右的朋友。然而,脸书好友的平均数量超过 300,而 LinkedIn 好友的平均数量超过 500。这意味着与传统的友谊网络相比,社交媒体平台可能会产生相当大的影响。
-与他们的朋友相比,个人自己的帖子中有更多的长期信息。与最近的帖子相比,前一段时间朋友的帖子对个人文本预测产生的收益递减影响清楚地表明了这一点。
-由于作者从他们的数据中排除了超链接,这里给出的限制可能是可扩展的。使用共同训练或其他方法可能会产生一个包括关于这些超链接的信息的模型,因此能够利用更多的信息并实现更好的预测。
启动数据科学的数据计划要素

Fig. 1 by Marjorie Sarnat. From left to right: Data Scientist, Business Manager, Data Analyst
在过去的几年里,我遇到了一些数据科学家,他们在统计分析和机器学习领域大有可为,但当他们进入商业领域时,他们面临着许多挑战,这些挑战让他们难以起步。他们很快就被提供即时结果的压力所淹没,而孤岛式数据源的复杂环境又进一步加剧了这种压力。
在本文中,我为您的数据程序提出了一些要素,以帮助数据科学家更快地入门,这些要素也可以更广泛地应用于一般的数据工作者。
魔法?
如果你将“数据科学”和“魔术”这两个词一起谷歌,你会发现许多文章解释说,数据科学不是魔术的黑盒子(像这篇文章,或者这篇)。作者表达了当数据科学家的工作被误解或他们没有做好工作所需的东西时,他们所面临的挫折感。
如果你是一名渴望利用数据科学来发展业务的商业专业人士,那么被告知“数据科学不是魔法”可能会降低你的热情——就像当一个孩子第一次被告知圣诞老人不是真实的一样。
我想知道我如何才能鼓励人们继续对数据科学保持兴奋,同时也阐明我们需要数据科学计划取得成功的一些因素…然后,在万圣节前的一周,我有了以下想法。我一直在我家附近散步,意识到这是一个穿上戏服假装的季节。所以…
让我们假装一个数据科学家是一种魔术师…

Fig. 2 by Roel Punzalan
比方说,你让你的数据科学家为你调制一种药剂。你请他施展魔法,将数据转化为源源不断的精彩见解,供你的企业使用。当这个白胡子巫师向你走来时,你搓着双手,满怀期待。他把他的手杖重重地摔在地上,说道:
“首先,我需要 1)一个洞穴,2)一口大锅,3)一个巨大的火炉.”
你挠了挠头,然后指着小房间里桌子上的一台笔记本电脑。
他摇了摇头,再次将他的手杖重重地砸向地面,重复道:“一个洞穴,一个大锅,一个巨大的熔炉……”
一个洞穴(情境+协作环境)
数据科学家首先需要的是背景。
很多时候,数据科学家被要求进行研究,却没有被告知他们应该解决的问题的足够背景,或者他们需要依赖的现有数据流。
因此,数据科学家花费大量时间试图理解和跟上他们需要的数据流,但这些数据流存在于他们自己的环境之外。
更为复杂的是,由于业务需求不断变化,数据流也在不断变化。
如果来自这种隔离环境的研究需要传递给希望在生产中使用该研究的某个方面的工程团队,这种隔离将在未来带来挑战。
这些挑战可以通过在现有环境中满足数据科学家的需求来解决:
- 邀请他们作为(可选)参与者参加您的所有团队会议,这样他们可以熟悉您的团队、您的业务目标和现有的技术环境。
- 考虑一下他们研究工作的节奏,以及它与你现有的 scrum 流程的关系。这可以被认为是一种类似于你如何管理 UX 设计需求的方式。
- 为他们提供一种方法,让他们了解您的整个数据流和对象集。
- 将路线图的一部分专门用于在现有环境中为数据科学研究开辟空间。
大锅(容器+计算能力)
在现有环境中开辟空间以满足数据科学需求通常需要考虑以下常见因素:
- 存储和管理可再生研究的地方(例如 jupyter 笔记本)
- 分享研究的方法
- 一种安全存储凭证的方法,同时以其他人可以输入自己的凭证的方式共享研究
- 一种安全连接到所需数据集的方法
- 访问存储和计算资源,他们可以根据需要增加或减少存储和计算资源。
数据科学专业的毕业生通常能够自我管理这些元素,但理想情况下,他们会获得一个环境的钥匙,让他们能够自我管理存储和计算资源(例如 AWS 或 GCP)。
与您的工程团队一起协调这些需求是一个好主意,他们可能能够将这些需求纳入现有的 repos 和 docker 映像,以便可以在本地环境以及您的 VPC(虚拟私有云)上的各种其他环境中共享和测试研究。
一个巨大的熔炉(实时数据)
您需要帮助您的数据科学家开始工作的最后一个障碍是为他们提供一个紧密代表实际生产数据的数据流。
如果研究要求需要进入生产:
- 就安全考虑事项与您的安全团队协调
- 与您的工程团队协作,通过 API、Kafka 流或相关生产数据库的副本来公开生产数据(通常,直接访问生产数据库不是一个好主意)
如果研究需求没有明确要求访问生产环境,请记住,生产环境通常包含难以在暂存环境中复制的脏数据。数据科学家通常需要考虑这些因素,并在通过算法运行数据之前运行清理/清理功能。使用虚拟数据测试的机器学习算法只有在虚拟数据代表生产数据的程度上才真正成功。
药剂(示例业务用例)
说了这么多,做了这么多——你有了一个洞穴、一口大锅和一个巨大的熔炉,并且正在运行——你的数据科学家会问你,“你到底需要我的药水做什么?”
你想预测未来的收入吗?优化你的供应链?为客户提供更好的产品推荐?或者,确定客户终止订阅的最重要原因?
虽然这些都是数据科学可以实现价值的好例子,但可以考虑从小处着手,获得“第一次胜利” ⁶ 。例如,将客户反馈分为正面或负面(类似于垃圾邮件过滤器),或者更简单地,验证数据中的现有计算。
有时,企业会意识到他们需要一名数据科学家,但不知道具体原因。这可能是一个不错的开始,但是你很快就会想去做一些具体的事情。如果您为数据科学家提供足够的业务目标背景,他们可能会帮助您确定要测试的假设,从而帮助您确定行动方案。
为什么这很重要——即使你没有数据科学家
虽然在本文中,我主要关注数据科学家面临的挑战,但这些挑战可以归因于更广泛的数据工作者网络。数据和分析越来越被视为构成任何组织命脉的关键企业资产。
“到 2022 年,90%的企业战略将明确提到信息是关键的企业资产,分析是一项基本能力。
到 2022 年,30%的[首席数据官]将与他们的首席财务官合作,正式评估组织的信息资产,以改善信息管理和收益。
到 2023 年,数据素养将成为商业价值的明确而必要的驱动因素,这表现在它被正式纳入超过 80%的数据和分析战略以及变革管理计划中。”——高德纳公司
附加帮助
数据科学已经发展成为一个庞大的学科体系。寻找一名优秀的数据科学家有时等同于寻找一只独角兽。思考这一挑战的另一种方式是将数据科学视为更多的团队工作。与其在一个人身上寻找一整套技能,不如在您的数据策略中考虑一些其他角色:
首席数据/分析官
CDO 或 CAO 通过分析计划推动业务价值,并定义跨业务垂直领域的标准
数据分析师
专注于将信息转化为有意义的见解,并利用现有工具实现标准数据管道。
数据工程师
关注特定于分析的架构需求,并构建自定义数据管道。
决策科学家
关注分析工作的成本,并跟踪投资回报(ROI)
数据管家
拥有特定的数据集并管理质量和可靠性
无服务器技术
过去几年云技术的进步为启动您的数据科学项目提供了一些绝佳的机会。
最后的想法
GitLab 的数据团队一直是我的灵感来源,影响着我如何思考创建一个为成功而设置的数据程序。他们的理念、过程和数据管道都可以在他们的手册和数据团队知识库中公开获得。他们的 CI/CD 方法使数据工作者能够比我迄今为止遇到的任何方法都更快、更可持续地投入工作。
您的数据团队是否花费更多时间收集和移动数据,或者分析和提供见解?
你如何将你的数据科学家纳入你的软件开发过程?
我很想听到关于这些想法是否对任何人有帮助的反馈。
感谢阅读!谢谢你,Edwin——谢谢你帮我审阅我的文章,还有Roel——谢谢你的向导插图:)
神经网络的初始化技术
因为有个好的开始总是更好!!

在这篇博客中,我们将看到深度学习中使用的一些初始化技术。任何在机器学习方面没有多少背景的人都必须知道,我们需要学习权重或超参数来建立模型。这些参数决定了我们的算法在未知数据上的表现。为了学习模型,我们需要初始化参数,应用损失函数,然后优化它。在这篇博客中,我们将关注网络的初始化部分。
如果你曾经构建过任何机器学习算法,你一定听说过我们需要“随机”初始化我们的权重作为起点,然后开始学习过程。随机这个词本身就很模糊。我们将会看到 random 这个词背后的真正含义以及不同的初始化技术。
- 零初始化
这是初始化权重的最简单方法之一,方法是将所有权重都设置为零。现在让我们用一个简单的两层网络来想象这种技术的含义。

由于我们已经设置了所有的权重,即 w= 0,我们可以很容易地看到,在向前传递期间:
a1 = w1x1 + w2x2 + w3x3, h1 = g(w1x1 + w2x2 + w3x3)
a2 = w4x1 + w5x2 + w6x3, h2 = g(w4x1 + w5x2 + w6x3)
a3 = w7x1 + w8x2 + w9*x3,H3= g(w7 * x1+w8 * x2+w9 * x3)
y= g(h1 * w10+H2 * w11+H3 * w12)
很清楚的看到 a1 = a2 = a3 = 0,h1 = h2 = h3。-> (1)
现在让我们看看反向传播会发生什么
∇w1=∂l(w)̇/∂w1 =∂l(w)̇/∂l(y)̇∂l(y)̇/∂l(h1)̇∂l(h1)̇/∂l(a1)̇* ̇x1
∇w4=∂l(w)̇/∂w4 =∂l(w)̇/∂l(y)̇∂l(y)̇/∂l(h2)̇∂l(h2)̇/∂l(a2)̇* ̇x1
∇w7=∂l(w)̇/∂w7 =∂l(w)̇/∂l(y)̇∂l(y)̇/∂l(h3)̇∂l(h3)̇/∂l(a3)̇* ̇x1
由此我们可以看出,∇w1 = ∇w4 = ∇w7(从 1),同理∇w2= ∇w5= ∇w7 和∇w3 = ∇w6 = ∇w9
从上面的论证中,我们可以看出每一步重量的变化是相同的。因此,隐藏层中的所有节点都在学习输入的相同参数,这导致冗余,并使我们的网络不太灵活,因此不太准确。这也叫做对称性问题。因此零初始化不是一个好的技术。
2.用相同的随机值初始化
在这种技术中,我们用相同的随机值初始化所有的权重。我希望你已经得到了这个技术的问题,因为它非常类似于零初始化,我们只是使用了一个随机值,但同样的问题仍然存在,因为权重的更新将再次处于相同的顺序。因此也不使用这种技术。
3.用小随机值初始化
在该技术中,我们从具有均值 0 和方差 1 的单变量“高斯”(正态)分布中随机初始化所有权重,并将它们乘以 10 的负幂以使它们变小。我们可以使用 numpy 在 Python 中这样做,如下所示
W = np.random.randn(输入 _ 层 _ 神经元,隐藏 _ 层 _ 神经元)*0.01
通过绘制梯度值,我们可以得到一个类似于的正态曲线。

现在,我们将运行学习算法,看看分布如何随着不同的 eopchs 而变化

After 10 epochs

After 20 epochs

After 50 epochs
从上面的图中,我们可以很容易地看到方差在减小,梯度饱和到 0。这就是所谓的**渐变消失问题。**人们也可以将此形象化,因为每个梯度是作为导数相乘链的结果而获得的,并且每个值远小于 1,因此梯度为零。
当这些梯度用具有 sigmoid 激活的神经元向前传播时,当 sigmoid(0) = 0.5 时,神经元的输出接近 0.5,而在 tanh 的情况下,它将与梯度图一样以 0 为中心。

Applying sigmoid activation
因此,我们可以得出结论,如果我们取小的随机值,梯度在重复链倍增时消失,并且神经元在 sigmoid 的情况下达到饱和值 0.5,在 tanh 的情况下达到饱和值 0。因此,我们不能使用小的随机值作为初始化。
4.用大随机值初始化
我们刚刚看到,在小随机值的情况下,梯度消失。现在让我们看看当我们用大的随机值初始化权重时会发生什么。我们可以使用 numpy 在 Python 中这样做,如下所示
W = np.random.randn(输入 _ 层 _ 神经元,隐藏 _ 层 _ 神经元)
当我们将权重初始化为大值时,绝对和 WiXi 将非常大,并且神经元在正向传递期间饱和到极限,如下所示。

Saturation with sigmoid activation

Saturation with tanh activation
下图显示,在饱和状态下,sigmoid 的导数为零。类似的论点也适用于 tanh。

现在,当我们通过网络反向传播时,导数将趋于零,因此在这种情况下梯度也将消失。因此,如果您认为我们已经初始化了较大的权重,因此梯度将会爆炸而不是消失,这与 sigmoid 和 tanh 由于在较大值饱和而激活的情况不同。
上面的两个论点告诉我们,在这两种情况下,无论是将权重初始化为小值还是大值,它们都会消失。在小值中,梯度因重复的链乘法而消失,而在大值中,梯度因导数本身变为零而消失。因此它们都不能使用。
在尝试任何新的方法之前,我们将试图建立一些直觉,为什么它会发生在数学上。
让我们来谈谈你的神经网络的输入,你必须知道,在输入网络之前,我们把输入标准化。为了便于讨论,让我们假设我们的输入来自均值为 0、方差为 1 的正态分布。对于 n 个输入,我们将上述网络中 a1 的等式推广为
a1 = w1x1 + w2x2 + w3x3 + ……+ wnxn
现在我们将计算 a1 的方差
Var(a1) = Var(∑WiXi)
=σVar(WiXi)
=σ[(E[Wi])Var(Xi)+(E[Xi])Var(Wi)+Var(Wi)Var(Xi)]
将输入和权重都视为零均值,前两项将相互抵消。
=σVar(Wi)Var(Xi)
因为所有的 WiXi 都是同分布的,所以我们可以写
=nVar(Wi)Var(Xi)
我们发现*Var(a1)=(nVar(Wi))Var(Xi)*或者我们可以说我们的输入 Xi 被缩放到 (nVar(Wi)) 倍方差。更多的数学知识,我们将能够证明第 k 个隐藏层,var(AK)=([(nvar(wi))]^k)var(xi).)的方差这种说法的物理意义是,隐藏层中的任何神经元现在可以变化 n 倍的输入变化(这也是前一层输入的 n 倍方差),或者如果我们绘制分布,我们会发现 Var(ak)比 Var(Xi)的分布更广

现在让我们看看 (nVar(Wi))^k )在 (nVar(Wi)) 的不同值下会发生什么
如果 (nVar(Wi)) > >为 1,渐变将爆发
如果 (nVar(Wi)) < <为 1,渐变将消失
因此,我们的工作是限制 (nVar(Wi)) = 1 ,这避免了爆炸或消失梯度的问题,并且方差的传播将在整个网络中保持恒定。
(nVar(Wi)) = 1
Var(Wi) = 1/n
因此,如果我们将从均值为 0、方差为 1 的高斯分布获得的权重缩放至 1/ √n,,则我们有
nVar(Wi) = nVar(W/√n)
= n * 1/n Var(W)
=1
最后,我们的任务是从方差为 1 的正态分布初始化权重,并将其缩放到 1/ *√n,*其中 n 是前一层中的节点数。在 Python 中,我们可以使用
W = np.random.randn(输入 _ 层 _ 神经元,隐藏 _ 层 _ 神经元)* sqrt(1/输入 _ 层 _ 神经元)
这也被称为 Xavier 初始化或Glorot 初始化http://proceedings.mlr.press/v9/glorot10a/glorot10a.pdf
在 ReLU 激活函数的情况下,我们乘以 √ 2/ √n 来说明负的一半(x < 0)对任何方差都没有贡献。这也被称为**贺初始化。**这是在https://arxiv.org/pdf/1502.01852v1.pdf提出的
W = np.random.randn(输入 _ 层 _ 神经元,隐藏 _ 层 _ 神经元)* sqrt(2/输入 _ 层 _ 神经元)
Xavier 初始化的一些其他变体包括除以输入层神经元和当前隐藏层神经元的数量之和。爱尔兰共和国
Var(Wi) = 2/(输入 _ 层 _ 神经元+隐藏 _ 层 _ 神经元)
Tensorflow 实现文档https://www . tensor flow . org/API _ docs/python/TF/contrib/layers/Xavier _ initializer
诸如 Keras 之类的高级 API 也使用 Glorot 初始化,尽管底层分布可以是高斯分布或均匀分布。下面是 Keras 中初始化器函数的 GitHub 链接。
人类的深度学习。通过在 GitHub 上创建一个帐户,为 keras-team/keras 开发做出贡献。
github.com](https://github.com/keras-team/keras/blob/62d097c4ff6fa694a4dbc670e9c7eb9e2bc27c74/keras/layers/core.py#L798)
让我们总结一下
如果你能跟上一些令人难以置信的数学。太棒了。因此,我们首先看到,我们不能使用零或相同的初始化,因为所有的权重往往以相同的幅度更新,因此阻碍了学习过程。此外,我们看到,如果我们将权重初始化为太小或太大的值,那么它们往往会饱和,梯度下降到 0。因此,需要初始化权重,以使隐藏层中神经元之间的变化保持恒定,Xavier 初始化允许我们这样做,因此它是任何网络初始化的最明显选择。
有一些技术,如批量标准化,它倾向于在将神经元传播到下一层之前,标准化每个隐藏层的神经元,就像我们在将输入输入到网络之前所做的一样。这减少了对权重初始化的强烈依赖,并允许我们对初始化有点粗心。
感谢阅读这篇文章。
更多这样的博客,你可以关注我,这样每当我有新的帖子时,你都会得到通知。
干杯!
还有,我们来连线一下 Twitter , Linkedin , Github 。
初始化神经网络

设置
让我们从获取 MNIST 数据集开始。因为我们经常这样做,所以我们将定义一个函数来这样做。

现在让我们计算数据的平均值和标准差。



注意,我们用train_mean而不是valid_mean来标准化验证集,以保持训练集和验证集在相同的规模上。
由于平均值(或 sd)永远不会精确地为 0(或 1),我们还定义了一个函数来测试它们是否接近 0(有一些阈值)。

接下来,让我们初始化我们的神经网络。


初始化问题
初始化神经网络 是深度学习的重要组成部分。这就是为什么我们可以让我们的神经网络像今天这样深的核心。初始化决定了我们是否收敛得好,收敛得快。
我们希望以这样一种方式初始化我们的权重,即当我们通过不同的层时,均值和方差保持不变。我们当前的初始化不会发生这种情况。

我们可以看到,仅仅一层之后,我们的激活值(一层的输出)相差甚远。如果我们对许多层重复这个过程,它将导致 渐变爆炸 ,如下所示。

我们模型的激活增长远远超过合理的值,以至于达到无穷大。这甚至不需要 100 次乘法运算就能实现。

那么我们该如何应对呢?也许我们可以把它们缩小一个系数来防止它们爆炸。

那也没用。虽然想法是正确的,但选择错误的因子会导致 渐变 (值达到 0)。
选择正确的比例因子— Xavier init
比例因子的值应该是多少?
答案是(1 /⎷input).这种初始化技术被称为 Xavier 初始化 。如果你想了解相同背后的数学,可以阅读原文或者本文末尾提到的参考文章之一。阅读研究论文的一个好建议是搜索总结论文的文章。

除以⎷input 确实有效。注意,如果我们想在反向传递中保持梯度,我们将除以⎷output.
Xavier 初始化文档也提供了如下所示的一些很好的可视化效果。


Xavier 初始化有问题
Xavier init 论文假设我们的激活函数将是线性的(事实并非如此)。因此,它忽略了激活函数对均值和方差的影响。让我们想想 ReLU。

一个 ReLU 把分布中所有的负值都变成 0。这当然不能保持我们数据的均值和方差。如果说有什么不同的话,那就是它们的价值只有原来的一半。每一层都会发生这种情况,所以 1/2 会累加起来。

在一篇名为深入研究整流器:在 ImageNet 分类上超越人类水平的性能的论文中提出了这个问题的解决方案。
简单的想法是,由于我们的值每次都减少一半,我们只需在分子中增加一个额外的 2 来抵消它。这种初始化技术被称为初始化或 何初始化 。

尽管我们的均值不太好,但它确实有助于我们的标准差。好的初始化能做的事情是惊人的。
有一篇名为 Fixup initialization 的论文,作者仅通过仔细的初始化,就训练了一个 10000 层深度的神经网络,没有任何归一化。这应该足以让你相信很好地初始化神经网络是重要的。
如果你想了解更多关于深度学习的知识,可以看看我在这方面的系列文章:
我所有关于深度学习的文章的系统列表
medium.com](https://medium.com/@dipam44/deep-learning-series-30ad108fbe2b)
参考资料:
先天知识和深度学习
我们生来就有某种先天知识吗?天赋论正在获得神经科学证据,并可能塑造人工智能和深度学习的下一个 R&D 步骤。


Figure 1: An elder Plato walks alongside Aristotle, The School of Athens, Raphael
“天赋论”…]认为人类的头脑生来就有想法或知识。这种信念,最著名的是由柏拉图作为他的形式理论提出的,后来由笛卡尔在他的《沉思录》中提出,目前正在获得神经科学的证据,可以证实我们生来就有关于我们世界的先天知识的信念。
天赋论与“纯粹主义”的机器学习方法相冲突,在“纯粹主义”的机器学习方法中,机器学习算法只从数据中学习,而没有显式编程或配备预编程的计算和逻辑模块。“思想的实际内容极其复杂,不可救药;我们应该停止试图寻找简单的方法来思考头脑的内容,例如思考空间、物体、多重代理或对称的简单方法。所有这些都是任意的、内在复杂的外部世界的一部分。它们不是应该内置的,因为它们的复杂性是无穷无尽的;相反,我们应该只构建能够发现和捕获这种任意复杂性的元方法。 " ( 来源)
截然不同的是,一个不同的思想流派建议将符号人工智能技术与深度学习相结合。
深度学习的未来
纽约大学教授加里·马库斯(Gary Marcus)等人提出了一种想法,即深度学习需要与更古老的象征性人工智能技术相结合,以达到人类水平的智能,辛顿对此表示蔑视。辛顿将此比作仅使用电动机来驱动汽油发动机的燃料喷射器,尽管电的能效要高得多。 " ( 来源)
与此同时,混合模型可能会解决深度学习的明显限制,特别是“深度学习目前缺乏一种通过明确的口头定义来学习抽象的机制,当有数千、数百万甚至数十亿个训练示例时效果最佳”。(来源)
是否应该更好地将 GOFAI 融入深度学习?这场争论正在激烈地进行着。
新的神经学证据
在我看来,讨论最终归结为一个问题——我们人类是从经验中学习一切,还是天生就具备某种形式的先天知识?
发表在《美国国家科学院院刊》(PNAS)上的一项研究称,“发现了一种突触组织原理,它以一种在动物中常见的方式对神经元进行分组,因此独立于个体经历”(来源)。这样的集群包含了物理世界中某些简单工作的表现。神经元群或细胞集合体,在动物的新皮质中不断出现,本质上是细胞的“积木”。那么,在许多动物中,学习、感知和记忆可能是将这些片段放在一起的结果,而不是形成新的细胞组合(来源)。
一条狭窄的分界线
鉴于越来越多的神经学证据支持先天知识的存在,为深度学习配备“先天”计算模块或原语可能是有意义的。很可能一些这样的原语将基于借鉴或受 GOFAI 启发的想法。
另一方面,很难预见深度学习架构在未来会是什么样子。Yoshua Bengio 自己承认,“然而,在神经网络能够与人脑拥有的一般智能相匹配之前,需要深度学习的新架构”。
在我看来,符号操作很可能会与神经架构深度耦合和纠缠在一起,而不是简单的并列,例如,神经后端和符号前端(如图 2 所示)。“M 模型更接近于通用计算机程序,建立在比我们当前的可区分层丰富得多的原语之上——这就是我们将如何达到推理和抽象,当前模型的根本弱点”(来源 )。.)

Figure 2: Deep Symbolic Reinforcement Learning, the neural back end learns to map raw sensor data into a symbolic representation, which is used by the symbolic front end to learn an effective policy (source)
这表明两种方法之间的分界线,“纯粹型”和“混合型”之间的界限非常模糊。因此,我认为,观点上的差异更多的是侧重点的差异,而不是根本性的差异。
Python 中的简单神经网络
什么是神经网络?
神经网络大致基于人类大脑的工作方式:许多神经元连接到其他神经元,通过它们的连接传递信息,并在神经元的输入超过特定阈值时触发。我们的人工神经网络将由人工神经元和突触组成,信息在它们之间传递。突触或连接将根据神经元对决定输出的影响强度进行加权。这些突触权重将经历一个被称为反向传播的优化过程。对于训练过程中的每次迭代,反向传播将用于返回网络的各层,并根据它们对神经网络误差的贡献来调整权重。
神经网络本质上是将输入映射到正确输出的自我优化功能。然后,我们可以将一个新的输入放入函数中,它将根据用训练数据创建的函数来预测输出。

神经网络的目标
像所有的神经网络一样,这个神经网络必须学习数据中的重要特征,以产生输出。特别地,该神经网络将被给予具有六个样本的输入矩阵,每个样本具有三个仅由 0 和 1 组成的特征列。例如,训练集中的一个样本可能是[0,1,1]。每个样本的输出将是单一的 1 或 0。输出将由数据样本的第一个特征列中的数字决定。使用前面给出的例子,[0,1,1]的输出将是 0,因为第一列包含 0。下面将给出一个示例图表来演示每个输入样本的输出。

完整代码
https://gist.github.com/a-i-dan/8d0a40b8690b40d9a46c4cb1d326fce5
Output:[[0.99089925]] - Correct: 1
[[0.006409]] - Correct: 0

代码分解
import numpy as np
import matplotlib.pyplot as plt
在开始之前,我们需要导入必要的库。这个例子只需要两个库,如果不画出损失,我们只需要 Numpy。Numpy 是一个 python 数学库,主要用于线性代数应用。Matplotlib 是一个可视化工具,我们将使用它来创建一个图,以显示我们的误差如何随着时间的推移而减少。
inputs **=** np**.**array([[0, 1, 0],
[0, 1, 1],
[0, 0, 0],
[1, 0, 0],
[1, 1, 1],
[1, 0, 1]])
outputs **=** np**.**array([[0], [0], [0], [1], [1], [1]])
如前所述,神经网络需要数据来学习。我们将使用 Numpy 的.array()函数创建输入数据矩阵和相应的输出矩阵。输入中的每个样本由三个由 0 和 1 组成的特征列组成,这些特征列产生一个 0 或 1 的输出。我们想让神经网络知道输出是由每个样本中的第一个特征列决定的。
**class** **NeuralNetwork**:
**def** **__init__**(self, inputs, outputs):
self**.**inputs **=** inputs
self**.**outputs **=** outputs
self**.**weights **=** np**.**array([[**.**50], [**.**50], [**.**50]])
self**.**error_history **=** []
self**.**epoch_list **=** []
我们将采用面向对象的方法来构建这个特定的神经网络。我们可以首先创建一个名为“NeuralNetwork”的类,并通过定义__init__函数来初始化该类。我们的__init__函数将输入和输出作为参数。我们还需要定义我们的权重,为了简单起见,从每个权重为. 50 开始。因为数据中的每个要素都必须连接到隐藏层,所以我们需要数据中每个要素的权重(三个权重)。出于绘图目的,我们还将创建两个空列表:loss_history 和 epoch_list。这将跟踪我们的神经网络在训练过程中每个时期的错误。
**def** **sigmoid**(self, x, deriv**=**False):
**if** deriv **==** True:
**return** x ***** (1 **-** x)
**return** 1 **/** (1 **+** np**.**exp(**-**x))
该神经网络将使用 sigmoid 函数或逻辑函数作为激活函数。sigmoid 函数是一种流行的非线性激活函数,其范围为(0–1)。该函数的输入将总是被压缩,以适应在 y=0 和 y=1 处的 sigmoid 函数的两条水平渐近线。sigmoid 函数有一些限制其使用的众所周知的问题。当我们看下面的曲线时,我们注意到当我们到达曲线的两端时,这些点的导数变得非常小。当这些小导数在反向传播过程中相乘时,它们会变得越来越小,直到变得无用。由于导数或梯度变得越来越小,神经网络中的权重将不会更新太多,如果有的话。这将导致神经网络停滞不前,每增加一次训练迭代,情况就会变得越来越糟。

sigmoid 函数可以写成:

sigmoid 函数的导数可以写成:
s′(x)=s(x)⋅(1−s(x)
如何求导
导数只是一个花哨的词,用来表示给定点的斜率或切线。仔细看看上图中的 sigmoid 函数曲线。其中 x=0 处的斜率远大于 x=4 或 x=-4 处的斜率。权重的更新量基于导数。如果斜率是较低的值,则神经网络对其预测有信心,并且需要较少的权重移动。如果斜率是更高的值,则神经网络的预测更接近 0.50,或 50%(对于 sigmoid 函数,可能的最高斜率值是在 x=0 和y = 0.5。 y 是预测。).这意味着神经网络对其预测不是很有信心,并且需要对权重进行更大的更新。
我们可以通过以下步骤找到 sigmoid 函数的导数:

然后我们可以用一个很酷的技巧来继续简化:给 e^-x 加一减一。加一减一不会改变什么,因为它们相互抵消了。这是一种奇特的加零方式。

通过在分子中加减一,我们可以再次拆分分数,并拉出另一个 sigmoid 函数!

现在我们可以简化,最后得到 sigmoid 函数的简化导数。

如果我们将 sigmoid 函数写成 S(x) ,那么导数可以写成:
=(s(x)⋅(1−s(x))
**def** **feed_forward**(self):
self**.**hidden **=** self**.**sigmoid(np**.**dot(self**.**inputs, self**.**weights))
在我们的神经网络的训练过程中,输入数据将通过网络的权重和函数被前馈。这个前馈函数的结果将是隐藏层的输出,或者是隐藏层对给定权重的最佳猜测。输入数据中的每个要素对于其与隐藏图层的连接都有自己的权重。我们将从每个特征的总和乘以其相应的权重开始。一旦我们将输入矩阵和权重矩阵相乘,我们就可以将结果通过 sigmoid 函数压缩成介于(0–1)之间的概率。前向传播函数可以写成这样,其中 xᵢ 和 wᵢ 是矩阵中的单个特征和权重:

再次重申,隐藏层将按以下步骤计算:
- 将每个特征列与其权重相乘
- 对特征和权重的乘积求和
- 将总和传递给 sigmoid 函数以产生输出 y ^ \hat y y^。

上图显示了将每个特征与其对应的权重相乘,然后对乘积求和的过程。训练数据中的每一行都将这样计算。得到的 4x1 矩阵将被输入到 sigmoid 激活函数中,如下所示:

上述过程将导致隐藏层的预测。 ∑xw 矩阵中的每一行都将进入 sigmoid 函数。颜色代表∑ xw 矩阵中每一行的单独过程。注意:这个计算只代表一次训练迭代,所以得到的 ŷ 矩阵不会很精确。通过以这种方式计算隐藏层,然后使用反向传播进行多次迭代,结果将更加准确。
**def** **backpropagation**(self):
self**.**error **=** self**.**outputs **-** self**.**hidden
delta **=** self**.**error ***** self**.**sigmoid(self**.**hidden, deriv**=**True)
self**.**weights **+=** np**.**dot(self**.**inputs**.**T, delta)
这是整个神经网络中最酷的部分:反向传播。反向传播将通过神经网络的层返回,确定哪些权重对输出和误差有贡献,然后基于隐藏层输出的梯度改变权重。这将被进一步解释,但是现在,整个过程可以被写成这样,其中 y 是正确的输出, ŷ 是隐藏层预测:

为了计算隐藏层预测的误差,我们将简单地取正确输出矩阵 y 和隐藏层矩阵 ŷ 之间的差。这个过程将在下面显示。

我们现在可以将误差和隐藏层预测的导数相乘。我们知道 sigmoid 函数的导数是 S(x)(1 — S(x)) 。因此,每个隐藏层预测的导数将是[(ŷ)(1-ŷ)]。例如,隐藏层的预测矩阵中的第一行包含值 0.62 0.62 0.62。我们可以用 0.62 美元代替 ŷ ,结果将是预测的导数。*0.62 (1–0.62)= 0.2356。对 ŷ 矩阵中的每一行重复这一过程,将得到一个 4×1 的导数矩阵,然后与误差矩阵相乘。

将误差和导数相乘可以得到所需的变化。当 sigmoid 函数输出具有更高置信度的值(接近 0 或接近 1)时,导数将更小,因此所需的变化将更小。如果 sigmoid 函数输出更接近. 50 的值,则导数是更大的值,这意味着需要更大的变化,以便神经网络变得更有信心。

这一步将导致添加到权重中的更新。我们可以通过将上述步骤中的“误差加权导数”与输入相乘来获得此更新。如果输入中的要素为 0,则权重的更新将为 0,如果输入中的要素为 1,则更新将添加到中。这将产生一个(3×1)矩阵,它与我们的权重矩阵的形状相匹配。

一旦我们有了更新的矩阵,我们可以将它添加到我们的权重矩阵中,以正式更改权重,使其变得更强。即使在一次训练迭代之后,也有一些明显的进步!如果查看更新后的权重矩阵,您可能会注意到矩阵中的第一个权重值更高。记住,我们的神经网络必须知道输入中的第一个特征决定了输出。我们可以看到,在每个输入示例中,我们的神经网络已经为连接到第一个特征的权重分配了更高的值!

**def** **train**(self, epochs**=**25000):
**for** epoch **in** range(epochs):
self**.**feed_forward()
self**.**backpropagation()
self**.**error_history**.**append(np**.**average(np**.**abs(self**.**error)))
self**.**epoch_list**.**append(epoch)
训练神经网络的时候到了。在训练过程中,神经网络将“学习”输入数据中的哪些特征与其输出相关,并且它将学习做出准确的预测。为了训练我们的神经网络,我们将创建具有 25,000 个历元或迭代次数的训练函数。这意味着神经网络将重复权重更新过程 25,000 次。在 train 函数中,我们将调用我们的feed_forward()函数,然后调用backpropagation()函数。对于每次迭代,我们还将跟踪在feed_forward()函数完成后产生的错误。我们将通过将错误和纪元附加到先前初始化的列表来跟踪这一点。我确信有一种更简单的方法可以做到这一点,但是对于快速原型开发来说,这种方法现在已经很好了。
对于我们神经网络中的每个权重,训练过程遵循以下等式:
- xᵢ —输入数据中的特征
- wᵢ —正在更新的重量
- Xᵀ —转置输入数据
- y —正确输出
- ŷ —预测产量
- (y — ŷ ) —错误
- ∑xᵢwᵢ-输入特征和权重的乘积之和
- S(∑xᵢwᵢ) —乙状结肠功能

**def** **predict**(self, new_input):
prediction **=** self**.**sigmoid(np**.**dot(new_input, self**.**weights))
**return** prediction
既然神经网络已经被训练并且已经学习了输入数据中的重要特征,我们就可以开始进行预测了。预测函数看起来类似于隐藏层,或feedforward()函数。前向传播函数本质上也进行预测,然后反向传播检查误差并更新权重。我们的预测函数将使用与前馈函数相同的方法:将输入矩阵和权重矩阵相乘,然后通过 sigmoid 函数返回 0-1 之间的值。希望我们的神经网络能够做出尽可能接近实际输出的预测。
NN = NeuralNetwork(inputs, outputs)
我们将从 NeuralNetwork 类创建 NN 对象,并传入输入矩阵和输出矩阵。
NN.train()
然后我们可以在我们的神经网络对象上调用.train()函数。
example **=** np**.**array([[1, 1, 0]])
example_2 **=** np**.**array([[0, 1, 1]])
**print**(NN**.**predict(example), ' - Correct: ', example[0][0])
**print**(NN**.**predict(example_2), ' - Correct: ', example_2[0][0])
输出
[[0.99089925]] - Correct: 1
[[0.006409]] - Correct: 0
现在我们可以创建两个新的例子,我们希望我们的神经网络对其进行预测。我们将这些称为“示例”和“示例 _2”。然后我们可以调用.predict()函数并传递数组。我们知道,输入中的第一个数字或特征决定了输出。第一个示例“example”在第一列中有一个 1,因此输出应该是 1。第二个示例在第一列中有一个 0,因此输出应该是 0。
plt**.**figure(figsize**=**(15,5))
plt**.**plot(NN**.**epoch_list, NN**.**error_history)
plt**.**xlabel('Epoch')
plt**.**ylabel('Loss')
训练完成后,我们可以绘制每次训练迭代的误差。该图显示,在较早的时期,误差有很大的下降,但是在大约 5000 次迭代之后,误差稍微稳定下来。

我希望这是对使用 python 和面向对象方法的神经网络的一个很好的介绍。
简而言之:ML 奖学金令人不安的趋势
简要回顾 ML 出版中的错误。

Photo courtesy of Robbie Sproule/ CC BY 2.0
机器学习研究人员很早就注意到同行评议的科学成果质量不高。(这并不是说该领域的学术严谨程度普遍较低,而是说非常不一致。)
本文基于 Z. C. Lipton 和 J. Steinhardt 的论文机器学习学术中令人不安的趋势,传播了 ML 文献中常见的质量问题。它总结了要点,并添加了一些额外的评论。如果你是一名(有抱负的)ML 研究者或者对这个话题感兴趣,我强烈推荐这篇可读性很强的原创论文。
我们是怎么到这里的?
在过去十年中,机器学习社区的规模实际上呈爆炸式增长。2010 年代初的巨大成功激起了人们的兴奋,导致了大量的资金,许多年轻的研究人员加入了这个社区。虽然对该领域的这种兴趣自然有利于进步,但它也带来了自身的一系列问题,我们可以推测它们导致了不一致的出版质量。
该领域研究人员的突然增加增加了向相关同行评审场所提交的数量。这给审查者带来了沉重的负担,他们随后每次审查花费的资源更少,但这也意味着人才库中有许多年轻和缺乏经验的审查者。很明显,在这种情况下,评论质量和出版质量必然会受到影响。
此外,ML 研究与行业利益和投资密切相关,一些研究人员还创办了初创企业,将他们的发现投入到盈利实践中。虽然学术成果被转化为有用的系统是一个受欢迎的趋势,但由此产生的对行业资金和媒体报道的依赖可能会刺激研究人员以耸人听闻的方式传播他们的发现,并牺牲写作的精确性和方法的严谨性来换取可销售的主张。
也许,由于强大的实证结果是最近社区扩展的基础,基准方面的进展似乎对一些研究来说已经足够了,并被用作不太严谨的写作的借口。
实际问题是什么?
作者挑出了四个在 ML 社区中相对常见的糟糕学术的具体例子。当然,它们不是 ML 研究独有的,但由于该领域的当前状态,可能更普遍,如上所述。
解释和推测往往不能清楚地分开。虽然两者都在学术出版物中占有一席之地,但重要的是读者能容易地区分它们。如果不是这样的话,作者冒着读者把推测误认为有根据的主张的风险,并在他们自己的写作中延续它。
一些人工智能论文的另一个弱点是,它们无法准确指出它们的经验收益来自哪里。当同时引入多个架构创新时,一些作者未能调查这些变化中的哪一个实际上有助于提高性能。此外,更好的结果可能只是不同训练程序的结果,例如更好的超参数调整。消融研究,其中一个或多个创新被遗漏的时间,是一个有价值的工具,调查来源的经验收益。
*数学陈述的加入与论文的实际内容没有很强的联系。作者称这种趋势为 *mathiness,可能是另一种让论文看起来更有根据并给没有经验的同行评审留下深刻印象的方式。数学对于精确传达服从于这种表述的思想是无价的,但是仅仅为了显得更“科学”而提供数学陈述或定理会损害可读性并混淆出版物的信息。
语言使用不准确。这一趋势有多个方面。首先,也许是由于该领域大量缺乏经验的研究人员和大量的研究成果,技术术语并不总是按其原意使用。这导致一些术语积累了多重含义,并在使用这些术语时产生歧义。
其次,引入带有暗示意义的术语,往往将机器拟人化。这导致了意识或公平等宏大概念与简单的统计特性或算法设计选择的融合。这种语言的使用不仅不真诚,而且会让其他领域的专家和外行人感到困惑。
如何从这里着手?
作者提到了好的出版物所具有的特点,并给作者和评论者提供了如何改善 ML 文献的建议。
好的论文应该为读者提供直觉,而不仅仅是陈述事实,此外,它应该总是考虑对观察到的效应的替代解释,在经验和理论分析之间有明确的联系,并使用精确和表达性的术语。
除了避免上面的反模式,作者建议进行错误分析、消融研究和健壮性检查,以阐明什么有效以及为什么有效。
关于在相关工作中已经取得的成就和尚未解决或已经解决的问题的语言应该是清楚的,以免使读者困惑。
评价者可以更有利地看待负面结果的报告,并且出版商可以促进使用冷静和精确语言的清晰书面评价论文的创建。
感谢阅读,别忘了查看原文:https://arxiv.org/abs/1807.03341。它充满了正面和负面的同行评议科学交流的例子。
内部无头 CMS
学习并理解 headless CMS 的强大功能,它是可以加速应用程序开发的工具。
在本文中,我们将了解无头 CMS,了解它的优点,以及何时应该使用它。我们还将讨论主要的局限性。为了更好地理解 HCMS 是如何在幕后工作的,我将解释我如何设计和构建 RawCMS,一个 Aspnet。具有 Oauth2、扩展插件系统和业务逻辑支持的核心无头 CMS。该解决方案在 GitHub 上可用,并作为演示发布在 Docker Hub 上。

Photo by Sincerely Media on Unsplash
什么是无头 CMS?
传统的内容管理系统将内容和呈现部分结合在一起,而无头的内容管理系统只关注内容。这似乎是一个限制,因为几乎不说话你会失去一些东西。HCMS 的目的是将逻辑从内容中分离出来,使变更管理变得简单,并将复杂的应用程序分解成许多组件,每个组件都有自己的职责。
朝着这个方向发展,HCMS 可以取代你所说的后端,并节省大量创建 CRUD 语句的有用工作。
HCMS 生来就是为了创建一个多组件的应用程序,你可以在其中快速改变表示逻辑和设计,当你在现代网站或应用程序上工作时,这是一个很大的改进,因为业务需求,你需要每年重新设计\改变 UI 一次。
许多供应商销售他们的产品并贴上“HCMS”的标签,只是因为它是分离的(因为它听起来很酷,可能会促进销售)…).在我看来,我与最初的 integralist 定义严格相关:headless cms 意味着 API 优先,非单片 cms,与接口或其他组件完全解耦。
无头 CMS 的优势
为什么要用无头 CMS?我可以简单地说,在某些场景中,解耦系统、简化前端替换和加速开发阶段可能是有用的,但是我觉得有必要使用项目列表来更好地解释。
- 全渠道就绪性:在无头 CMS 中创建的内容是“纯”的,您可以在任何您想要的上下文中使用。如果你在上面存储了一些新闻内容,你也可以在公共网站或内部网发布,把数据输入保存在一个地方。
- 低运营成本:无头 CMS 是一个产品,所以,一旦你选择了一个好的,我希望它将即插即用。此外,与定制解决方案相比,供应商免费提供更新和错误修复。
- 缩短上市时间:无头 CMS 促进了敏捷的工作方式。您可以让多个团队参与后端和前端工作,这样可以减少时间。此外,因为 HCMS 地区有一个关于 API 消费的数据存储的垂直解决方案,大部分事情都已经完成了,所以你必须专注于数据设计而不是技术细节(就像浪费时间去考虑有效负载,而你可以免费使用 Odata 或 Grahql)。
- 垂直解决方案:HCMS 做了一件事,这使得它非常容易学习和维护。
- 灵活性:一旦你选择了你的 HCMS(本地或云),你的开发者可以使用任何他们喜欢的语言来实现前端。这意味着你可以不受技术的限制。
无头 CMS 解决方案的局限性
与传统的 CMS 相比,HCMS 还很年轻,因此,即使很多产品在过去几年诞生,大多数产品还没有成熟到完全取代传统的 API 后端。在这一段中,我将分享我发现的局限性的经验。根据具体的产品以及是本地解决方案还是 saas 解决方案,功能可能会有很大差异。
实际上,CMS 的无头限制主要有两种:
- 使用 HCMS 的缺点
- 您安装的产品的限制
使用 HCMS 的缺点
HCMS 需要雇佣多个团队来从工作并行化中获益。此外,由于 HCMS 没有任何渲染,所有的表示逻辑都需要客户端来完成。这有利于解耦,但在所有情况下,您只有一个消费者。解耦的优势不太相关,并且您会在数据获取过程中引入更多的复杂性和延迟。另一个问题是关于商业逻辑。在哪里实施?如果你不想在 HCMS 中实现,你必须把它放到表示层,并且有多个消费者,你会复制它,当逻辑在多个地方时,你会遇到问题。否则,尝试将其放入 HMS 时,您会发现大多数云解决方案\产品并不那么灵活。这就引出了下一个话题,HCMS 的局限性是什么?
HCMS 的局限性
测试最重要的 HCMS 解决方案会遇到许多困难,以下是最常见的限制列表。考虑到这取决于产品,有人可能有或没有,但一般来说,大多数是相当普遍的。
- 针对外部提供者的身份验证:大多数解决方案不允许针对外部系统对用户进行身份验证。我说的是最常见的场景,其中您有一个中央身份认证系统,所有各方都通过用户令牌\票证来代表用户进行操作。换句话说,如果我有一个 oauth2 服务器,我想在前端进行身份验证,并使用令牌调用内部网的所有应用程序,而不仅仅是 HCMS,并被识别为我自己。
- 非标准输出格式:有些使用 GraphQL 或 Odata,这很好,因为它提供了一种数据消耗的标准方法。问题是“一些”并不意味着“全部”,所以你必须注意选择你的 HCMS。
- 业务逻辑:在大多数情况下,不可能在运行时定义业务逻辑,在某些情况下,也不能扩展核心应用程序。可扩展性:很难找到一个可以编写自己的代码、修改业务逻辑或添加额外内容的解决方案。这部分是因为许多供应商将其 HCMS 设计为哑数据存储,部分是因为管理可扩展性的复杂性。
何时何地使用无头 CMS?
Headless CMS 是一个很好的机会,但我们必须了解什么是利用它来优化成本效益比的最佳方案。问题是,使用常规 HCMS,定制是非常有限的,所以如果你不是在正确的场景中,将很难混合 HCMS 来实现业务需求。此外,使用它就像一个光秃秃的数据存储使它毫无意义的事情。
当使用 HCMS 方便时:
- 在这段时间里,用户界面发生了很多变化
- 共享相同信息的许多应用程序和管理这些信息的一个团队
- 你对数据没有什么商业逻辑
- 你可以雇佣多个团队(be+fe)
何时不使用 HCMS:
- 有一种垂直解决方案可以满足您的需求。你想用 WordPress 写博客)
- 你很有商业逻辑
- 你不是数据的主人
兴趣点
HCMS 很棒,因为它们通过设计将表示层与后端分离,这是一个很好的驱动因素。HCMS 是一个很好的机会,但是现在,除非有非常简单的业务逻辑和定义良好的行为,否则很难在实际项目中使用。如果能克服这些限制并将其用作“通用后端”就太好了,在这里,您只需花时间来教授系统有关数据模式、关系的知识,并只调整非标准的内容。问题是,总的来说,这很难实现。
在这里你可以找到关于无头 CMS 和关于我的实现的源代码的 git-hub 的完整文章。
觉得这篇文章有用?在 Medium 上关注我(丹尼尔·丰塔尼),看看我下面最受欢迎的文章!请👏这篇文章分享一下吧!
- Docker 到底是什么?
- 【Kubernetes 到底是什么?
- 如何使用 Kubernetes 部署 web 应用程序
对傅里叶变换的理解及其简单实现

source: https://pa1.narvii.com/6397/fbeec74f0468cf51eb46f4f869190563cf50829b_hq.gif
在这篇文章中,我不会给你一个傅立叶变换或傅立叶级数的推导细节。相反,我们将探索这种转换的输出以及它是如何工作的。
因此,我们将在这个故事中讨论的傅里叶变换公式被称为离散傅里叶变换(DFT)。公式是这样的。

X is the output of DFT (signal in frequency spectrum), x is signal input (signal in time spectrum), N is a number of sample and k is frequency (limited in 0 to N-1 Hz). Source: https://en.wikipedia.org/wiki/Discrete_Fourier_transform
它用于将信号的有限样本从时间频谱转换到频率频谱。坚持住!时间谱和频率谱中的信号是什么?我所指的时间频谱中的信号只是一个时间序列数据,如随时间变化的股价、随时间变化的降雨率等。

example of time series data: USGS streamflow over time data. Source: https://d32ogoqmya1dw8.cloudfront.net/images/geoinformatics/steps/1354035151.png
如果我们在 2d 图中绘制时间序列数据,我们将在 x 轴上得到时间,在 y 轴上得到幅度(或在波的情况下的振幅)。因此,与频谱中的信号不同的是,如果我们将其绘制在 2d 图中,我们将在 x 轴获得频率,在 y 轴获得幅度。
好了,现在我们知道了 DFT 的实际输出,但是它是如何工作的?你知道你可以用 DFT 公式的一部分产生任意频率的周期正弦波吗?你可以用这个零件来生产那个。

您可以使用下面的脚本来可视化这个公式生成的波。
#!/usr/bin/python3import numpy as np
from matplotlib import pyplot as plt#setting
k = 2
res = 400t = np.linspace(0, res, res)time = np.linspace(0, 1, res)
hz = np.exp(-2j * np.pi * k * t / len(t))plt.ylabel("Amplitude")
plt.xlabel("Time")
plt.plot(t, hz)
plt.show()
你会得到这样的东西

对于 k =2,我们得到一个 2 Hz 正弦波,如果我们设置 k = 10

我们得到了一个 10 赫兹的正弦波。
(再)坚持住!这个公式有一个“I”,这意味着输出必须有一个虚部。是,右边这个部分公式的输出是幅度+(相位)I。在这个上下文中,相位大约是正弦波的一个角度。

在这个故事中,为了简单起见,我们将忽略虚部,也就是所谓的相位,并且我们不会在这个故事中使用它作为我们的实现示例。
在 DFT 的完整公式中,你要在你的实信号和 k Hz 的正弦信号之间做一个点运算。这就是为什么你可以从真实信号中提取 k Hz 正弦波的一个分量。你将从 0 Hz 提取到 k-1 Hz** 。但是,有一个情节转折?在现实世界中,我们不会使用普通的 DFT 来提取它,而是使用快速傅立叶变换(FFT)来提取。FFT 只是一种更有效的计算 DFT 的方法。我们不会在这个故事中讨论 FFT 算法,但是为了你的信息,普通 DFT 和 FFT 的结果几乎是相同的。**
这就是理论,现在我们将实施它。通过傅立叶变换,我们将尝试计算出哔哔声的频率。我们将在这个实验中使用这个声音。让我们用这个脚本来看看这个声音的“形状”。
#!/usr/bin/python3from scipy.io import wavfile
from matplotlib import pyplot as plt
import numpy as np#setting
datasound = '7detik.wav'fs, data = wavfile.read(datasound)
data = np.array(data, dtype=float)#normalize
data = (data - np.mean(data)) / np.std(data)time = range(len(data))plt.ylabel("Amplitude")
plt.xlabel("Time")
plt.plot(time, data)
我们得到了这个。

要将这些数据从时间频谱转换到频率频谱,也就是 FFT,让我们运行下面的脚本。
#!/usr/bin/python3from scipy.io import wavfile
from matplotlib import pyplot as plt
import numpy as np#setting
datasound = '7detik.wav'fs, data = wavfile.read(datasound)
data = np.array(data, dtype=float)
#print(len(data), np.shape(data), fs)#normalize
data = (data - np.mean(data)) / np.std(data)time = range(len(data))fftdata = np.fft.fft(data)
fftdatafreq = np.zeros((len(data)))
for i in range(len(fftdata)):
fftdatafreq[i] = abs(fftdata[i].real)plt.ylabel("Amplitude")
plt.xlabel("Frequency")
plt.plot(time, fftdatafreq)
plt.show()
你会得到这样一个图表。

哇,在一些或一个频率和另一个频率之间有一个巨大的差异振幅。其实,FFT 的输出是对称的(看看上图就知道了,)。这意味着我们只需要一半的频率来显示。
plt.plot(time[:len(fftdatafreq) // 2], fftdatafreq[:len(fftdatafreq) // 2])
我们得到了下图。

好了,现在是有趣的部分。我们将尝试计算出这种哔哔声的频率。让我们用这个代码检查具有最高振幅的 bin。
maxfreq = np.argmax(fftdatafreq)
print('dominant freq ', maxfreq)
结果是
dominant freq 6009
6009?这是不是意味着这个嘟嘟声的频率是 6009?没那么快!我们在这里使用的 FFT 函数
fftdata = np.fft.fft(data)
假设我们数据的总持续时间是 1 秒,尽管实际上并不是这样。让我们检查一下哔哔声的实际持续时间。该功能
fs, data = wavfile.read(datasound)
返回 1 秒(fs)内的采样率和声音(data)的数组真实数据。让我们检查 fs 的值和数据数组的长度。
print(len(data), fs)
是回归
265039 44100
所以数组的长度是 265039,采样率是 44100。并且查看声音的持续时间是 265039 / 44100 = 6.009954648526077 秒。
表示在这 6.009954648526077 秒中,我们的主频已经形成了 6009 个当时的正弦波。从逻辑上思考,所以主频是6009/6.009954648526077 = 999.8411554525939Hz或者我们可以把这个数四舍五入到 1000 Hz 。总结一下,我们的嘟嘟声的频率是 1000 Hz。要验证它只需谷歌“1000 赫兹声音”。

播放视频并与我们的哔哔声进行比较。非常相似不是吗?
仅此而已。FFT 的应用非常广泛,尤其是在电气工程中。最初的计划是我想用 FFT 计算出每日降雨量的模式,但是我的降雨量数据并不充分。另一篇文章再见。
检查 15 年 CDC 慢性病数据集
使用 Python 和数据科学技术对人口健康指标进行探索性数据分析

Photo by Dan Gribbin on Unsplash
最近,我接受了一个个人项目,以应用我一直在学习的 Python 和机器学习。由于我对人口健康感兴趣,我决定从了解我在 Kaggle 上找到的 15 年人口健康特定数据集开始。这个数据集来自美国疾病控制和预防中心的慢性病指标。在这个博客系列中,我想用 exploration 演示数据集中有什么。稍后,我将深入探讨数据可视化。目前,我不确定我是否看到只有这个数据集的实际机器学习的机会。
根据 Kaggle 的概述,该数据集中提供的有限背景信息指出,这些指标是从 2001 年到 2016 年在州一级收集的,共有 202 个指标。使用 jupyter notebook 和文件上的 pd.read_csv(),有 403,984 行,34 列,或属性。通过跑步。info()方法,下面输出中的第二列显示我们有一些丢失的数据。在下面的最后一列中,有不同类型的数据,其中一些是数字型的,比如整数和浮点值,而另一些是包含字符串的对象。
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 403984 entries, 0 to 403983
Data columns (total 34 columns):
YearStart 403984 non-null int64
YearEnd 403984 non-null int64
LocationAbbr 403984 non-null object
LocationDesc 403984 non-null object
DataSource 403984 non-null object
Topic 403984 non-null object
Question 403984 non-null object
Response 79323 non-null object
DataValueUnit 374119 non-null object
DataValueType 403984 non-null object
DataValue 297817 non-null object
DataValueAlt 273666 non-null float64
DataValueFootnoteSymbol 188019 non-null object
DatavalueFootnote 187853 non-null object
LowConfidenceLimit 246819 non-null float64
HighConfidenceLimit 246819 non-null float64
StratificationCategory1 403984 non-null object
Stratification1 403984 non-null object
StratificationCategory2 79323 non-null object
Stratification2 79323 non-null object
StratificationCategory3 79323 non-null object
Stratification3 79323 non-null object
GeoLocation 401416 non-null object
ResponseID 79323 non-null object
LocationID 403984 non-null int64
TopicID 403984 non-null object
QuestionID 403984 non-null object
DataValueTypeID 403984 non-null object
StratificationCategoryID1 403984 non-null object
StratificationID1 403984 non-null object
StratificationCategoryID2 79324 non-null object
StratificationID2 79324 non-null object
StratificationCategoryID3 79323 non-null object
StratificationID3 79323 non-null object
让我们了解一下每个专栏都是关于什么的。虽然有些列名相对来说不言自明,但我使用 set(dataframe[‘ColumnName’])来更好地理解唯一的分类数据。以下是一些例子:
题目 : 400k+行数据分为以下 17 类。有一个名为 TopicID 的对应列,它只是给出了一个缩写的标签。
{'Alcohol',
'Arthritis',
'Asthma',
'Cancer',
'Cardiovascular Disease',
'Chronic Kidney Disease',
'Chronic Obstructive Pulmonary Disease',
'Diabetes',
'Disability',
'Immunization',
'Mental Health',
'Nutrition, Physical Activity, and Weight Status',
'Older Adults',
'Oral Health',
'Overarching Conditions',
'Reproductive Health',
'Tobacco'}

Distribution of the data by topic. Diabetes, Chronic Obstructive Pulmonary Disease, and Cardiovascular Disease are the top 3 topics
问题:在每个话题中,都有一些问题。我们将使用相应的列 QuestionID。这些是数据集具有值的 202 个唯一指标,我们将对此进行进一步分析。
{'Activity limitation due to arthritis among adults aged >= 18 years',
'Adults aged >= 18 years with arthritis who have taken a class to learn how to manage arthritis symptoms',
'Adults with diagnosed diabetes aged >= 18 years who have taken a diabetes self-management course',
'Alcohol use among youth',
'Alcohol use before pregnancy',
'All teeth lost among adults aged >= 65 years',
'Amount of alcohol excise tax by beverage type (beer)',... 'State child care regulation supports onsite breastfeeding',
'States that allow stronger local tobacco control and prevention laws',
'States with strong polices that require retail licenses to sell tobacco products',
'Taking medicine for high blood pressure control among adults aged >= 18 years with high blood pressure',
'Television viewing among high school students',
'Timeliness of routine health care checkup among women aged 18-44 years',
'Visits to dentist or dental clinic among adults aged >= 18 years',
'Visits to dentist or dental clinic among adults aged >= 18 years with diagnosed diabetes'}
数据源:考虑到我们有这么多的指标,有 33 个数据源我并不奇怪。然而,下面的直方图显示,大部分数据来自两个来源,BRFSS,即 CDC 的行为风险因素监测系统和 NVSS,即国家生命统计系统。
{'ACS 1-Year Estimates',
'ACS 5-Year Estimates',
'AEDS',
'ANRF',
'APIS',
'ASHW',
'BRFSS',
'Birth Certificate, NVSS',
'CDC Breastfeeding Report Card',
"CDC Children's Food Environment State Indicator Report",
'CDC School Health Profiles',
'CMS CCW',
'CMS Part A Claims Data',
'Current Population Survey',
'Death certificate',
'HRSA, UDS',
'InfoUSA; USDA',
'Legal Research',
'NSCH',...

CDC’s BRFSS and NVSS make up almost the entirety of this dataset
data value unit:data value 中的值由以下单位组成,包括百分比、金额、年份和千例数。
{' ',
'$',
'%',
'Number',
'Number ',
'Years',
'cases per 1,000',
'cases per 1,000,000',
'cases per 10,000',
'cases per 100,000',
'gallons',
nan,
'pack sales per capita',
'per 100,000',
'per 100,000 residents'}
DataValueType :以下几个类别很有见地,表明当我们想要查看跨州数据比较时,有年龄调整后的数字与原始数字相比较,这有助于我们进行比较。
{'Adjusted by age, sex, race and ethnicity',
'Age-adjusted Mean',
'Age-adjusted Prevalence',
'Age-adjusted Rate',
'Average Annual Age-adjusted Rate',
'Average Annual Crude Rate',
'Average Annual Number',
'Commercial host (dram shop) liability status for alcohol service',
'Crude Prevalence',
'Crude Rate',
'Local control of the regulation of alcohol outlet density',
'Mean',
'Median',
'Number',
'Per capita alcohol consumption',
'Percent',
'Prevalence',
'US Dollars',
'Yes/No'}
数据值 vs 数据值 Alt :数据值似乎是我们未来分析的目标数据列。使用。head()方法,该列由 string 对象形式的数值组成,而 DataValueAlt 是数值 float64。后来,我想使用 pandas pivot_table 方法,它只需要数字数据。因此,我将使用 DataValueAlt 进行后续分析。
分层和分层类别相关列:与分层相关的列有 12 列,是性别、种族、年龄等每个指标内的子组。在分层类别 1 中,有性别、总体和种族。例如,在分层 1 中,值由种族类型组成。在 ID 列中,如分层 ID1,我们有相应的种族标签。
缺失数据:
使用下面的 matplotlib 和 seaborn 生成热图,很容易看到哪里有数据,哪里缺少数据以及缺少多少数据。黄色代表丢失的数据。列是每个指标,纵轴是 40 万行数据。
import matplotlib.pyplot as plt
%matplotlib inlineplt.figure(figsize=(16, 6))sns.heatmap(df.isnull(),yticklabels=False,cbar=False,cmap='viridis')

Large portions of missing data is related to Stratification Categories 2 and 3 and the related Stratification 2 and 3. The horizontal axis consists of the column names.
在热图中,响应和与分层类别 2/3 和分层 2/3 相关的列包含的数据不到 20%。虽然分层类别 1 和分层 1 似乎有潜在有用的数据,但让我们确认 2 和 3 中有什么数据。对于每个分层列,我遵循类似的方法:
df['StratificationCategory2'].count()df_strat2cat = []for i in df['StratificationCategory2']:
if (pd.isnull(i) is False):
if i is not ' ':
df_strat2cat.append(i)
例如,列的计数返回 79k,其中包含数据。我想看看里面有什么,所以我设置了 for 循环来遍历特定分层 2 或 3 列中的每个元素,并将非空值或带有空格的值追加到一个名为 df_strat2cat 的新数组中。这意外地产生了一个没有值的数组。在对其他分层列重复此操作后,我删除了这组列。
df_new = df.drop(['Response','ResponseID','StratificationCategory2','StratificationCategory3','Stratification2','Stratification3','StratificationCategoryID2','StratificationCategoryID3','StratificationID2','StratificationID3' ],axis = 1)<class 'pandas.core.frame.DataFrame'>
RangeIndex: 403984 entries, 0 to 403983
Data columns (total 24 columns):
YearStart 403984 non-null int64
YearEnd 403984 non-null int64
LocationAbbr 403984 non-null object
LocationDesc 403984 non-null object
DataSource 403984 non-null object
Topic 403984 non-null object
Question 403984 non-null object
DataValueUnit 374119 non-null object
DataValueType 403984 non-null object
DataValue 297817 non-null object
DataValueAlt 273666 non-null float64
DataValueFootnoteSymbol 188019 non-null object
DatavalueFootnote 187853 non-null object
LowConfidenceLimit 246819 non-null float64
HighConfidenceLimit 246819 non-null float64
StratificationCategory1 403984 non-null object
Stratification1 403984 non-null object
GeoLocation 401416 non-null object
LocationID 403984 non-null int64
TopicID 403984 non-null object
QuestionID 403984 non-null object
DataValueTypeID 403984 non-null object
StratificationCategoryID1 403984 non-null object
StratificationID1 403984 non-null object
dtypes: float64(3), int64(3), object(18)
使用 df_new,seaborn 热图显示最少的黄色和大部分紫色。如果我们想更进一步,我们可以填充缺失的数据,但此时,我将把额外的工作留到稍后阶段。

概括地说,我使用 pandas 将 CSV 数据文件导入到数据帧中。然后,我使用各种方法来更好地理解每一列中的数据,因为上下文信息非常有限。分层 2 和 3 列的组是无用的,并且这些被移除。在下一篇文章的中,我们将采用生成的数据框架来理解数据,甚至进一步理解具体指标之间的关系。
受到乐观主义的启发,与技术联姻,跨越人工智能鸿沟

下面的视频(长度 17 分钟。)在今年早些时候出版了,我仍然发现它鼓舞人心,并惊叹于由影响力和资源支持的乐观主义的力量。
技术如何成为解决自动化和人工智能导致的预期失业的积极力量?
根据一项研究,在未来十年,数百万工人可能需要改变职业,根据自动化/人工智能的采用速度,占全球劳动力的 2-14%。
如果你是下面图表中的一种工作类型(来自《经济学家》关于人工智能在全球的影响),并且你目前正在做卷饼、给建筑物换墙板或打扫房间,那么获得自动化取代风险较低的工作的道路可能会很陡峭。

这就引出了一个问题,即乐观情绪如何传播到美国人口中,根据这份麦肯锡报告,这些人口预计在经济上受自动化和人工智能影响最大:
“我们测量了到 2030 年因自动化而可能失去的工作岗位的百分比,发现由于他们集中在面临自动化风险的职业中,与其他群体相比,非裔美国人的潜在工作岗位转移率最高。”这意味着“到 2030 年,由于自动化,可能会失去大约 132,000 个非裔美国人的工作岗位。”
这些挑战对男性来说可能比女性更大。麦肯锡的论文指出,例如,非裔美国女性在 K-12 教育、护理和其他护理职业中的参与率较高,这使她们有更多机会获得医疗保健和教育部门的预期就业增长。这些工作*“自动化潜力较低,因为需要动态的、身体的运动和深层的人际关系。”*
虽然有些人提议以土地的形式进行赔偿,作为对非裔美国人当前和未来似乎根深蒂固的不平等的答案,但也许还有其他方法。
如果像小学教师或护士助理(和监狱看守)这样的“高接触”护理工作在不久的将来流失的风险很低,但对教育要求最低的入门级工作却有很高的风险,那么许多企业应该承担什么责任,这些企业更愿意雇用拥有“立即进入角色”的技术技能的工人,而不是培训他们所需的技能?
虽然有些人认为大学教育补贴是答案,但引用我一个更保守的 T2 熟人的话:
“研究表明,受教育程度越高的人挣钱越多。但这完全是误导。拥有私人飞机的人也赚更多的钱,但这并不意味着你买了湾流就会变得更富有。”
我想知道,是否有理由让人们更容易获得工具和 MOOCs,以比传统大学或训练营低得多的成本提供技能培训。如果像斯科特·贝尔斯基在“创造力是新的生产力”中所提出的那样,创造性工作不太可能自动化,那么或许获得这一新的繁荣所需的设备和软件就是答案。

Image by James Doucette
进入“创造力与生产力”领域存在成本障碍。例如,为了开始使用 Adobe 套件,你需要一台电脑(约 1000 美元)、软件(约 600 美元)、互联网接入(约 60 美元)和认证测试(约 80 美元)。对于每月最低工资估计为 1084.40 美元(税后)的人来说,这可能是一个挑战。然而,更有可能的障碍是围绕大学学位要求和微观证书的招聘实践。虽然像 EdX 这样的机构提供“微观硕士”,但接受独立于机构的成绩单而不是完整的学位(区块链?)是否能被招聘机构同等程度地接受,似乎还很遥远。
解决方案可能来自公私合作,就像最近宣布的 Udacity 一样。Udacity 承诺每年向 2 万名申请人提供免费的入门技术培训课程,面向“希望学习获得高薪工作和职业发展所需的热门技能的低收入个人。”此外,“该公司还将考虑向完成初步培训的人提供认证,以此表明成就,并展示对潜在雇主有意义的技能。”这一决定可能是因为大多数工人没有为“更强大的纳米学位项目”做好准备。如果候选人范围变得更窄,需要熟练技术员工的公司会愿意绕过对非大学学位申请者的“筛选”吗?或者那些有技能但没有学位的人会成为亚马逊土耳其人的奴隶吗?
是像商业圆桌会议的学徒制 2020 那样的努力,专注于目前在芝加哥城市学院注册的大学生(新内容/旧交付模式),还是 Udacity 的奖学金(直接面向社区经理的消费者——面向自学者)提供解决方案?还是会有其他更有机的方式,对社区做出承诺的公司不仅通过在施粥场做志愿者和粉刷公园长椅,还通过激发灵感为那些很快被落在后面的人提供替代路线来回报。在就业中心做志愿者?在大厅借笔记本电脑?或者像 Sans Institute 这样不那么依赖股东的组织会开始在网络安全方面培训高中生吗?(一些最优秀的黑客才十几岁)。

Image by James Doucette
不管是好是坏,我们的未来都与科技结下了不解之缘,注意到在所有的关系中,分开一段时间没有坏处。解决不平等的挑战摆在我们面前,有待我们去解决。
对于那些喜欢更深入地阅读第二版“恩格尔的停顿”的人来说,可以随意深入阅读 80 多页,点击这里的“技术为好”。
Instacart 市场购物篮分析第一部分:哪些杂货商品受欢迎?
深入分析
通过土星云对 Instacart 订单的探索性数据分析
作为一名数据科学家,我的很大一部分职责是与业务利益相关方分享我的成果。作为一名数据记者,我的很大一部分职责是与我的读者分享代码块。
现在,我分享的报告需要在网络上正确呈现。我分享的代码也需要是可复制的。

土星云为我解决了这两个用例。
怎么会?
在这个由 3 部分组成的博客系列中,我将通过一个例子向您展示我如何使用土星云来传达我的结果。特别是,我将致力于 Instacart 市场购物篮分析,显示 Instacart 消费者会再次购买哪些产品的结果。
Instacart 数据集
Instacart 是一款杂货订购和配送应用,是我最喜欢的技术平台之一。作为一名学业繁忙的研究生,我根本没有时间去买菜。Instacart 的目标是让网上购物变得简单,只需轻触一个按钮。顾客通过 Instacart 应用程序选择产品后,个人购物者会审核订单,并为顾客进行店内购物和送货。你可以把 Instacart 想象成杂货店购物的优步。
早在 2017 年,该公司宣布了其首次公开数据集发布,该数据集是匿名的,包含来自 20 多万 Instacart 用户的 300 多万份杂货订单样本。目标是预测哪些以前购买的产品将出现在用户的下一个订单中。在这篇文章中,我将做一些探索性的分析,以获得关于数据集的一些表层见解。

产品
首先,让我们探索 Instacart 产品的数据。有两个 CSV 文件,即 order_products_train 和 order_products_prior ,指定每个订单购买了哪些产品。更具体地说, order_products_prior 包含所有客户以前的订单产品,而 order_products_train 仅包含某些客户的最新订单产品。
订单 _ 产品 _ 列车文件中有 1384617 件产品,订单 _ 产品 _ 之前文件中有 32434489 件产品。两个文件都有 4 个特征列:
- 订单的 ID(order _ ID
- 产品的 ID(product _ ID
- 订单中产品的排序( add_to_cart_order )
- 该产品是否被重新订购(重新订购)。
总体而言,49,685 种独特产品有 3,346,083 个独特订单。我们可以在下图中观察到,人们通常会订购 5 件左右的产品。

特别是,订购最多的前 5 种产品是香蕉(491,291)、袋装有机香蕉(394,930)、有机草莓(275,577)、有机小菠菜(251,705)和有机帽子鳄梨(220,877)。

约 59%的订购产品是客户之前订购的。下图显示了通常最有可能重新订购的产品。按照概率,重新订购最多的前五种产品是 Serenity Ultimate Extrema 隔夜垫(0.933)、巧克力爱心棒(0.922)、玛卡毛茛(0.894)、Benchbreak Chardonnay (0.892)和有机蓝莓 B Mega (0.889)。

订单
现在让我们来研究 Instacart 订单的数据。 orders.csv 文件有 3421083 个订单和 7 个特征列:
- 订单的 ID(order _ ID)
- 客户的 ID(用户 id )
- 订单所在的评估数据集——先前、训练或测试( eval_set )
- 订单的编号( order_number )
- 订单发生的星期几( order_dow )
- 订单发生的时间(订单时间)
- 自上一订单以来的天数( days_since_prior_order
看起来 Instacart 的客户通常在早上 8 点到晚上 7 点之间下单。

看起来他们大多在周末下订单(0 表示周六,1 表示周日)。

下图显示了 Instacart 客户的再订购周期。在第 7 天和第 30 天有明显的峰值,表明人们通常在一周或一个月后再订购。

该数据集中总共有 206,209 个不同的客户。如下图所示,大多数客户下了大约 4 个订单。

部门和过道
我们来看看最重要的部门,按产品数量排序。排名前 5 位的部门分别是个人护理(6,563)、小吃(6,264)、茶水间(5,371)、饮料(4,365)和冷冻(4,007)。

让我们看看所有部门中最重要的过道,按照产品数量进行分类。忽略“缺失”值,我们的前 5 名分别是巧克力糖(1,258)、冰淇淋(1,091)、维生素补充剂(1,038)、酸奶(1,026)和薯片椒盐卷饼(989)。

按订单数量排序的部门和通道的详细信息如何?按订单排序,最畅销的前 5 个部门是农产品(409,087)、乳制品鸡蛋(217,051)、零食(118,862)、饮料(114,046)和冷冻食品(100,426)。

最后,我们查看所有部门中按照订单数量排序的最佳销售通道。前 5 名分别是新鲜蔬菜(150609)、新鲜水果(150473)、包装蔬菜水果(78493)、酸奶(55240)、包装奶酪(41699)。

结论
进行这种分析让我能够更细致地了解 Instacart 平台上客户购物行为的细节。了解最常购买的商品是 Instacart 优化其软件产品并在顾客购物时为他们推荐商品的第一步。
如果你有兴趣自己复制这个结果,你可以从insta cart 网站下载数据集,并在土星云上查看我的笔记本。就个人而言,快速轻松地共享笔记本的能力对任何数据科学家都非常有帮助。
在这个博客系列的下一部分,我将把客户分成不同的组,这可以帮助 Instacart 针对不同的需求提供更多个性化的推荐。此外,我将探索 Saturn 的特性,该特性允许我扩展云计算,因为我有更高的计算需求。
Instacart 市场购物篮分析第二部分:哪些群体的客户是相似的?
深入分析
通过土星云对 Instacart 客户进行聚类
数据科学环境正在快速变化,变得越来越成熟。无论你是一名开发前沿深度学习算法的经验丰富的数据科学家,还是一名正在进行学校项目的研究生,能够几乎不费吹灰之力地在 Jupyter 笔记本(数据科学中的默认工作台)上发布和协作都是非常关键的。
到目前为止,还没有很多简单的共享笔记本的解决方案可供您的团队协作。如果你是一名刚从学校毕业的入门级数据科学家,这可能是一个大问题。我最近被介绍到土星云,发现共享工作和使用基于云的计算非常简单。

这是 3 部分文章系列的第 2 部分,我给出了一个例子,说明我如何使用 Saturn Cloud 来交流我在 Instacart 市场篮子分析挑战中的工作结果。在第 1 部分的中,我进行了探索性数据分析阶段,以深入了解 Instacart 平台上客户购物行为的细节。
客户细分
在第 2 部分中,我将尝试找到一种可能的客户细分方法,使我们能够根据客户的不同购买行为对他们进行分类。客户细分是将客户群细分为具有相似特征的独立群体。这种方法是识别未满足的客户需求的有效方法。利用这些信息,Instacart 可以通过开发独特的吸引人的产品和服务来超越竞争对手。此外,该信息还将有助于下一个预测任务,该任务可用于向客户推荐新商品。

由于数据集中有成千上万的产品,我将依赖于代表产品类别的通道。即使有过道,功能的数量仍然会太多。因此,我将使用主成分分析来寻找新的维度,沿着这些维度聚类将更容易,然后尝试为已识别的聚类找到可能的解释。
数据预处理
继续第 1 部分中的数据探索,这是我对数据集结构的理解:
- 用户由 orders.csv 文件中的 user_id 标识。 orders.csv 文件的每一行代表一个用户的订单。订单通过其 order_id 进行识别。
- 用户的每个订单都由一个 order_number 来表征,该订单指定了该订单何时相对于同一用户的其他订单做出。
- 每个订单都由一组产品组成,每个产品都有一个 add_to_cart_order 特性,表示它们被添加到购物车的顺序。
- 对于每个用户,我们可能有(n — 1)个先前订单和 1 个训练订单或(n — 1)个先前订单和 1 个测试订单,其中我们必须说明哪些产品已经重新订购。
为了便于分析,我将所有不同的数据帧合并成一个名为 mt. 的数据帧
_mt = pd.merge(prior,products, on = ['product_id','product_id'])_mt = pd.merge(_mt,orders,on=['order_id','order_id'])mt = pd.merge(_mt,aisles,on=['aisle_id','aisle_id'])

我们正在处理 134 种类型的过道和 49,677 种不同的产品。如左侧所示,最畅销的前 5 种商品是新鲜水果、新鲜蔬菜、包装蔬菜水果、酸奶和包装奶酪。
使用 PCA 和 K-Means 进行聚类
目标是在不同的客户中找到所有可能的集群,并用假设他们所属的集群替换单个 user_id。这将最终提高下一个预测模型的性能。
首先要做的是创建一个数据框,其中包含每个用户的所有购买行为。这个 cust_prod 有 206,209 个用户和 134 列。
cust_prod = pd.crosstab(mt['user_id'], mt['aisle'])cust_prod.head(10)

然后,我将主成分分析算法应用于 cust_prod 数据框架。这有助于将功能的数量从通道的数量减少到 6,这是我选择的主要组件的数量。
土星云在这里真的很有帮助,因为 PCA 算法的计算代价很高。由于我将我的笔记本托管在他们支持云的平台上,我可以利用 Saturn 提供的 GPU 来执行这个昂贵的操作。
from sklearn.decomposition import PCApca = PCA(n_components=6)pca.fit(cust_prod)pca_samples = pca.transform(cust_prod)ps = pd.DataFrame(pca_samples)ps.head()

在绘制了几对组件并为 K-Means 聚类寻找了一个合适的组件对之后,我选择了(PC4,PC1)对,如下所示。由于每个组件都是原始数据集所有点的投影,我认为每个组件都很好地代表了数据集。

这是我们的星团是如何出现的。您可以看到有 4 个集群与 4 种不同的颜色(蓝色、绿色、紫色和橙色)相关联。值为 0,1,2,3 的圆是每个簇的质心。

我想我已经找到了 Instacart 客户的可能聚类。让我们来看看每个集群的人们购买的前 10 种商品是什么。我将首先依赖绝对数据,然后依赖每个集群的前 8 个产品的百分比。
集群特征
以下是分类 0 中的前 10 种产品。
c0.sort_values(ascending=False)[0:10]

以下是第 1 类中的前 10 种产品。
c1.sort_values(ascending=False)[0:10]

以下是第 2 类中的前 10 种产品。
c2.sort_values(ascending=False)[0:10]

以下是第 3 类中排名前 10 的产品。
c3.sort_values(ascending=False)[0:10]

对聚类的粗略分析证实了最初的假设,即(1)新鲜水果,(2)新鲜蔬菜,(3)包装的蔬菜水果,(4)酸奶,(5)包装的奶酪,(6)牛奶,(7)苏打水,和(8)脆片椒盐卷饼是大多数顾客通常购买的产品。
我在这里可以检查的是,相对于这些货物,集群在数量和比例上是否有所不同,或者一个集群的特征是否是一些不在此列表中的货物。例如,我已经看到第 3 类的特点是“婴儿食品配方”产品,这与其他类有很大的不同。
下表描述了这些商品相对于每个聚类中其他前 8 名商品的百分比。集群之间很容易出现一些有趣的差异。

- 看起来第一组的人比其他组的人购买更多的新鲜蔬菜。如绝对数据所示,聚类 1 也是包括购买比任何其他顾客多得多的商品的顾客的聚类。
- 第二组的人比其他组的人买更多的酸奶。
- 第三组的人购买了大量的“婴儿食品配方奶粉”,这些产品甚至没有列在前八名,但却是这一组的主要特征。与这个观察一致(我认为),他们比其他人买更多的牛奶。
我认为另一个有趣的信息可能来自于查看每个集群中第 10 到第 15 个最常购买的产品,其中不包括通用产品(即蔬菜、水果、水等)。)谁都买。
在聚类 0 中,第 10 到第 15 位最常购买的商品是冷藏、冰淇淋、冷冻产品、鸡蛋和饼干。
c0.sort_values(ascending=False)[10:15]

在第 1 组中,第 10 到第 15 位最常购买的商品是无乳糖大豆、面包、饼干、麦片和巧克力糖。
c1.sort_values(ascending=False)[10:15]

在聚类 2 中,第 10 到第 15 位最常购买的商品是鸡蛋、罐装罐装蔬菜、面包、薯片、椒盐卷饼和冷藏食品。
c2.sort_values(ascending=False)[10:15]

在聚类 3 中,第 10 到第 15 位最常购买的商品是不含乳糖的大豆、冷冻产品、苏打水、冷冻食品和鸡蛋。
c3.sort_values(ascending=False)[10:15]

正如您所注意到的,考虑更多的产品后,聚类开始明显不同。
结论
对于任何企业来说,进行客户细分都有多种优势:确定合适的产品定价、制定有效的定制营销活动、设计最佳分销策略、选择具体的产品功能进行部署,以及对新产品开发工作进行优先排序。正如我的分析所证明的,Instacart 可以通过多种方式,利用公司拥有的庞大客户群,执行上述任何一种商业战略。
如果你有兴趣自己复制这个结果,你可以从 Instacart 网站下载数据集,并在土星云上查看我的笔记本。在这个博客系列的最后一部分,我将尝试进行关联规则挖掘,这是一种机器学习技术,有助于显示 Instacart 订单数据集中购买的产品之间的关系概率。
Instacart 市场购物篮分析第三部分:应向购物者推荐哪几组产品?
深入分析
基于土星云的 Instacart 产品关联规则挖掘
欢迎来到充满希望的数据科学和机器学习平台时代!这些平台具有开箱即用的优势,因此团队可以从第一天就开始分析数据。使用开源工具,你需要手工组装很多部件,可以这么说,任何做过 DIY 项目的人都可以证明,理论上比实践上容易得多。明智地选择一个数据科学和 ML 平台(指的是一个灵活的、允许合并和继续使用开源的平台)可以让企业两全其美:尖端的开源技术和对数据项目的可访问、可治理的控制。

最终,数据科学和 ML 平台是关于时间的。当然,这意味着在流程的所有部分节省时间(从连接数据到构建 ML 模型到部署)。但这也是为了减轻人工智能入门的负担,让企业现在就开始投入,而不是等到技术确定下来,人工智能世界变得更加清晰(因为剧透警告:这可能永远不会发生)。开始人工智能之旅令人生畏,但数据科学和 ML 平台可以减轻这一负担,并提供一个框架,允许公司边走边学习。
土星云
土星云允许数据科学家轻松地在云上提供和托管他们的工作,而不需要专门的开发人员。然后,数据科学家可以在 Juptyer 笔记本中工作,该笔记本位于您指定的服务器上,由系统创建。所有软件、网络、安全和图书馆的设置都由土星云系统自动处理。然后,数据科学家可以专注于实际的数据科学,而不是围绕它的乏味的基础设施工作。
您还可以使用链接与公众或团队成员共享您的 Juypter 笔记本。这消除了理解如何使用 GitHub 进行基础数据科学项目的需要。如果您确实知道如何使用 GitHub,它仍然提供了一种快速方便的方法来测试和开发代码。因此,数据科学家可以专注于数据科学,并以比其他方式更快的速度完成项目。

这是 3 篇文章系列的最后一篇,我将举例说明如何使用 Saturn Cloud 来应对 Instacart 市场购物篮分析挑战。在第 1 部分中,我探索了数据集,以更细致地了解 Instacart 平台上客户购物行为的细节。在《T4》第二部中,我对客户进行了细分,以找出是什么因素将他们区分开来。
动机
我希望使用 Apriori 算法在 Python 中运行关联分析,以导出形式为 {A} - > {B} 的规则。然而,我很快发现它不是标准 Python 机器学习库的一部分。尽管存在一些实现,但我找不到一个能够处理大型数据集的实现。在我的例子中,“大”是一个包含 3200 万条记录的 orders 数据集,包含 320 万个不同的订单和大约 50K 个不同的项目(文件大小刚刚超过 1 GB)。
因此,我决定自己实现算法来生成那些简单的 {A} - > {B} 关联规则。因为我只关心理解任何给定的项目对之间的关系,所以使用先验知识来得到大小为 2 的项目集就足够了。我经历了各种迭代,将数据分成多个子集,这样我就可以在内存小于 10 GB 的机器上运行 cross-tab 和 combinations 等功能。但是,即使使用这种方法,在我的内核崩溃之前,我也只能处理大约 1800 个项目……这时,我了解了 Python 生成器的奇妙世界。

Python 生成器
简而言之,生成器是一种特殊类型的函数,它返回可迭代的项目序列。然而,与一次返回所有值的常规函数不同,生成器一次生成一个值。要获得集合中的下一个值,我们必须请求它——要么通过显式调用生成器的内置“next”方法,要么通过 for 循环隐式调用。
这是生成器的一个重要特性,因为这意味着我们不必一次将所有的值都存储在内存中。我们可以一次加载并处理一个值,完成后丢弃该值,然后继续处理下一个值。这个特性使得生成器非常适合创建项目对并计算它们的共现频率。
这里有一个具体的例子来说明我们正在努力实现的目标:
- 获取给定订单的所有可能商品对
order 1: apple, egg, milk —-> item pairs: {apple, egg}, {apple, milk}, {egg, milk}order 2: egg, milk --> item pairs: {egg, milk}
- 统计每个项目对出现的次数
eg: {apple, egg}: 1{apple, milk}: 1{egg, milk}: 2
下面是实现上述任务的生成器:
def get_item_pairs(order_item): # For each order, generate a list of items in that order for order_id, order_object in groupby(orders, lambda x: x[0]): item_list = [item[1] for item in order_object] # For each item list, generate item pairs, one at a time for item_pair in combinations(item_list, 2): yield item_pair
上面编写的 get_item_pairs() 函数为每个订单生成一个商品列表,并为该订单生成商品对,一次一对。
- 第一个项目对被传递给计数器,计数器记录一个项目对出现的次数。
- 获取下一个项目对,并再次传递给计数器。
- 这个过程一直持续到不再有项目对。
- 使用这种方法,我们最终不会使用太多内存,因为在计数更新后,项目对会被丢弃。
Apriori 算法
Apriori 是一种在事务数据库上进行频繁项集挖掘和关联规则学习的算法。它通过识别数据库中频繁出现的单个项目,并将其扩展到越来越大的项目集,只要这些项目集在数据库中出现得足够频繁。
Apriori 使用“自下而上”的方法,一次扩展一个频繁子集(这一步被称为候选生成),并根据数据测试候选组。当没有找到进一步的成功扩展时,算法终止。

Apriori 使用广度优先搜索和哈希树结构来有效地计算候选项目集。它从长度为(k — 1)的项集生成长度为 k 的候选项集。然后,它修剪具有不频繁子模式的候选。根据向下闭包引理,候选集包含所有频繁 k 长项目集。之后,它扫描事务数据库以确定候选项中的频繁项集。
下面是一个先验的例子,假设最小发生阈值为 3:
order 1: apple, egg, milkorder 2: carrot, milkorder 3: apple, egg, carrotorder 4: apple, eggorder 5: apple, carrotIteration 1: Count the number of times each item occursitem set occurrence count{apple} 4{egg} 3{milk} 2{carrot} 2=> {milk} and {carrot} are eliminated because they do not meet the minimum occurrence threshold. Iteration 2: Build item sets of size 2 using the remaining items from Iteration 1item set occurence count{apple, egg} 3=> Only {apple, egg} remains and the algorithm stops since there are no more items to add.
如果我们有更多的订单和商品,我们可以继续迭代,构建包含 2 个以上元素的商品集。对于我们试图解决的问题(即:寻找项目对之间的关系),实现先验以获得大小为 2 的项目集就足够了。
关联规则挖掘
一旦使用 apriori 生成了项目集,我们就可以开始挖掘关联规则。假设我们只查看大小为 2 的项目集,我们将生成的关联规则将采用{ A }–> { B }的形式。这些规则的一个常见应用是在推荐系统的领域,其中购买了商品 A 的顾客被推荐商品 b。

以下是评估关联规则时要考虑的 3 个关键指标:
1 —支架
这是包含项目集的订单的百分比。在上面的示例中,总共有 5 个订单,{apple,egg}出现在其中的 3 个订单中,因此:
support{apple,egg} = 3/5 or 60%
apriori 所需的最小支持阈值可以根据您对领域的了解来设置。例如,在这个杂货数据集中,由于可能有数千个不同的商品,而一个订单只能包含这些商品中的一小部分,因此将支持阈值设置为 0.01%可能是合理的。
2 —置信度
给定两个商品 A 和 B,置信度度量商品 B 被购买的次数的百分比,给定商品 A 被购买。这表示为:
confidence{A->B} = support{A,B} / support{A}
置信值的范围是从 0 到 1,其中 0 表示在购买 A 时从不购买 B,1 表示每当购买 A 时总是购买 B。请注意,置信度是有方向性的。这意味着,我们还可以计算出商品 A 被购买的次数百分比,假设商品 B 被购买:
confidence{B->A} = support{A,B} / support{B}
在我们的例子中,假设苹果被购买,鸡蛋被购买的次数百分比是:
confidence{apple->egg} = support{apple,egg} / support{apple}= (3/5) / (4/5)= 0.75 or 75%
这里我们看到所有包含 egg 的订单也包含 apple。但是,这是否意味着这两个项目之间有关系,或者它们只是偶然以相同的顺序同时出现?为了回答这个问题,我们来看看另一个衡量标准,它考虑了这两个项目的受欢迎程度。
3 —升降机
给定两个项目 A 和 B,lift 表示 A 和 B 之间是否存在关系,或者这两个项目是否只是偶然地(即:随机地)以相同的顺序一起出现。与置信度度量不同,其值可能随方向而变化(例如:置信度{A->B}可能不同于置信度{B->A}), lift 没有方向。这意味着升力{A,B}总是等于升力{B,A}:
lift{A,B} = lift{B,A} = support{A,B} / (support{A} * support{B})
在我们的例子中,我们计算升力如下:
lift{apple,egg} = lift{egg,apple}= support{apple,egg} / (support{apple} * support{egg})= (3/5) / (4/5 * 3/5)= 1.25
理解 lift 的一种方法是将分母视为 A 和 B 以相同顺序出现的可能性,如果它们之间没有关系的话。在上面的例子中,如果 apple 出现在 80%的订单中,egg 出现在 60%的订单中,那么如果它们之间没有关系,我们会期望它们在 48%的时间里以相同的顺序一起出现(即:80% * 60%)。另一方面,分子代表苹果和鸡蛋以相同顺序出现的频率。在这个例子中,这是 60%的时间。取分子并除以分母,我们得到苹果和鸡蛋实际上以相同的顺序出现的次数比它们之间没有关系时多多少次(即:它们只是随机出现在一起)。
总之,lift 可以采用以下值:
- lift = 1 暗示 A 和 B 之间没有关系(即:A 和 B 只是偶然出现在一起)
- lift > 1 暗示 A 和 B 之间存在正相关关系(即:A 和 B 一起出现的次数比随机出现的次数多)
- lift < 1 暗示 A 和 B 之间存在负相关关系(即:A 和 B 一起出现的频率低于随机出现的频率)
在这个例子中,苹果和鸡蛋一起出现的次数比随机出现的次数多 1.25 倍,所以我断定它们之间存在正相关关系。有了 apriori 和关联规则挖掘的知识,让我们深入到数据和代码中,看看我能展现什么关系!
insta cart 数据上的关联规则挖掘
云中木星笔记本入门使用土星云非常直观。笔记本运行后,我可以轻松地从笔记本内部与公众分享。为了证明这一点,你可以在这里查看我的关联规则挖掘笔记本中的完整代码。
在数据预处理步骤之后,我编写了几个助手函数来辅助主要的关联规则函数:
- freq() 返回项目和项目对的频率计数。
- order_count() 返回唯一订单的数量。
- get_item_pairs() 返回生成项目对的生成器,一次一个。
- merge_item_stats() 返回与项目相关联的频率和支持。
- merge_item_name() 返回与项目相关的名称。
下面的 GitHub Gist 中显示了大的 association_rules() 函数:
Full Link: https://gist.github.com/khanhnamle1994/934d4c928c836d38879d3dd6637d9904
此时,我能够利用 Saturn Cloud 的 GPU 功能来处理我的工作负载。本质上,土星云让我只需点击一下鼠标就能部署 Spark 或 Dask 集群。这简化了处理非常昂贵的计算的问题,只需点击一下鼠标就可以实现分布式计算。考虑到这种关联规则挖掘算法相当昂贵,访问 GPU 在这里是一个明显的赢家。
在最小支持度为 0.01 的订单数据帧上调用 association_rules() 函数后,得到如下结果(正在挖掘的 7 个规则样本):

从上面的输出中,我观察到顶级关联并不令人惊讶,一种口味的商品与同一商品系列中的另一种口味一起购买(例如:草莓 Chia 农家奶酪与蓝莓 Acai 农家奶酪,鸡肉猫粮与土耳其猫粮,等等)。如上所述,关联规则挖掘的一个常见应用是在推荐系统领域。一旦项目对被确定为具有积极的关系,就可以向顾客提出建议以增加销售。希望在这个过程中,我们还可以向顾客介绍他们以前从未尝试过甚至想象不到的东西!
结论
当试图启动数据科学团队项目时,开发运维可能会非常困难。在幕后,有很多工作要做,以建立数据科学家用于工作的实际平台:创建服务器,安装必要的软件和环境,设置安全协议,等等。使用 Saturn Cloud 托管 Jupyter 笔记本电脑,同时还负责版本管理,并能够根据需要进行扩展,这可以极大地简化您的生活,缩短上市时间,降低成本和对专业云技能的需求。
我希望你喜欢这个由 3 部分组成的系列,通过 Instacart 市场购物篮分析挑战来了解使用 Saturn Cloud 的好处。作为数据科学和机器学习平台运动的一部分,当团队不必在管理、组织或重复任务上花费宝贵的时间时,像土星云这样的框架可以打开真正的数据创新之门。事实是,在人工智能时代,任何规模的企业都无法承受没有数据科学平台的工作,该平台不仅可以支持和提升他们的数据科学团队,还可以将整个公司提升到最高水平的数据能力,以实现最大可能的影响。
使用全景和模式的 Instagram 数据分析

picture credits to panoply.io
背景
该项目建立在 Panoply 于 2019 年 4 月发布的数据挑战之上。Panoply 是一个云数据仓库,你可以从不同的数据源(如 S3 自动气象站,谷歌分析等)收集数据。),然后连接到不同的商业智能工具(即 Chartio、Mode 等。)进行分析和洞察。
Panoply 最近将他们的数据仓库与 Instagram API 集成在一起,以收集数据。这个挑战是关于使用 Panoply 作为 ETL 工具来探索 Instagram 数据的营销用途(即推广、细分等)。).
在这项挑战中,挑战者被要求建立一个 Panoply 帐户,并连接到 self Instagram 或提供的 Instagram 数据,以进行分析,得出见解,并为讲故事建立可视化。如果您有 Instagram 帐户,您可以使用自己 Instagram 帐户中的数据。或者,如果您更喜欢使用 Panoply 提供的数据,您可以从两个帐户中选择:
- Kirsten Alana:insta gram 的顶级影响者。
- Shinesty :一个创新和前卫的服装品牌。
然后,您可以使用您选择的任何 BI 工具进行数据可视化。本次挑战的最终交付成果将采用英语,数据可视化,用于交流您的发现和您使用过的 SQL 查询。
项目设计
我的项目步骤是:
- 探索 Panoply,使用它在自己的网站上为挑战和文档提供的资源。
- 创建 Panoply 免费试用帐户,连接到提供的数据源,连接到商业智能工具。
- 探索数据集,理解模式和关系。
- 研究并提出 Instagram 所有者希望跟踪和回答的问题/指标/关键绩效指标。这样他们就能获得发展品牌的洞察力。
- 使用模式构建可视化并接受挑战。
工具
我将在这个项目中使用的工具和技术将是 Panoply,Instagram data,SQL 和模式。
过程
我开始阅读 Panoply 提供的资源,并探索他们的网站,以更好地了解 Panoply 是什么以及它如何在数据分析过程中发挥作用。然后我创建了 Panoply 帐户的免费试用版,并按照他们的文档连接到亚马逊 S3 收集提供的 Instagram 数据。
创建一个 Panoply 帐户
下面是唱出一个全景账户的流程:
- 转到 https://panoply.io 。

panoply.io landing page screenshot
2.使用电子邮件帐户注册一个免费的 21 天试用帐户。

sign-up page screenshot
连接到数据源并收集数据
下面是连接到亚马逊 S3 并使用 API 收集 Instagram 数据的流程。在这个挑战中,我使用了 Shinesty 的数据作为我的分析目标,Shinesty 是一个创新和前卫的服装品牌。
- 转到数据源选项卡。

Data Sources tab screenshot
2.选择你想连接的数据源,对于这个项目,我使用亚马逊 S3。
输入您的凭证并开始从您的数据源收集数据到 Panoply 数据仓库。

Amazon S3 api info page screenshot
3.你的桌子准备好了。

Tables tab screenshot
用于分析的表格
收集数据后,我发现总共有 31 张表。经过探索和检查,我确定了 5 个最有用的表格,并用它们得出有意义的见解。下面是我使用过的表格和列。

shinestyinstagram_instagram_user table screenshot

shinestyinstagram_instagram_media table screenshot

shinestyinstagram_instagram_comment table screenshot

shinestyinstagram_instagram_media_tags table screenshot

shinestyinstagram_instagram_media_location table screenshot
韵律学
经过我的研究,我确定了一些 Instagram 账户所有者希望了解的指标和问题,以便在 API 提供数据的情况下提高他们的账户认知度。
- 每个标签的参与度。
- 一段时间内的表现。
- 用户评论时按星期几使用的性能。
- 当用户发表评论时,按一天中的小时使用性能。
- 创建帖子时按小时使用的绩效。
- 按媒体类型划分的性能。
- 不同介质的过滤性能。
- 使用位置标签的性能。
- 有位置标签的帖子与没有标签的帖子的性能差异。
- 最活跃的评论者。
- 队列分析。
可视化的连接模式
- 前往 https://mode.com的创建一个免费的非商业账户。

Mode home page screenshot
2.进入您的帐户控制面板后,点击左侧您姓名旁边的向下箭头。

home dashboard screenshot
3.然后会出现一个新的下拉菜单,选择 Connect a Database 选项卡。

drop down menu for connecting a database screenshot
4.然后,您可以使用您的凭证连接到不同的数据库。

connect to database screenshot
对于这个项目,我们使用了 Amazon Redshift,因为这是 Panoply 用来存储我们的表的数据库。在您进入并收集到您的 Panoply 数据库后,Mode 将开始收集所有表格到您的帐户数据库中。一旦完成,您就可以开始使用 SQL 来分析模式中的数据。

using SQL to analyze the data in Mode screenshot
分析
下面是我用来回答指标部分的问题的查询。
- 为使用的每个标签寻找参与度:
with t AS
(SELECT
value as hashtag,
likes_count as likes,
comments_count as comments
FROM public.shinestyinstagram_instagram_media m
left JOIN public.shinestyinstagram_instagram_media_tags mt
ON m.id = mt.instagram_media_id
)
select
hashtag,
AVG(likes) as avg_likes,
AVG(comments) as avg_comments
from
t
where hashtag is not null
group by 1
下面的视频告诉你每个标签的平均赞数,# housetonstrong 和#theperfectcrime 的平均赞数最多。

Average Likes vs. Hashtag
下面的视频告诉你每个标签的平均评论,其中#buttstuff 和#macrobrews 的表现最好。

Average Comments vs. Hashtag
下面视觉结合以上两者。

Performance By Hashtag
- 了解一段时间内的表现:
SELECT
DATE_TRUNC(‘week’, created_time)::DATE as week,
SUM(comments_count) AS total_comments,
AVG(comments_count) AS avg_comments,
SUM(likes_count) AS total_likes,
AVG(likes_count) AS avg_likes,
count(distinct id) as nums_of_post
FROM
public.shinestyinstagram_instagram_media
GROUP BY
1
ORDER BY
1

Performance Over Time
- 使用 when a user comment 按星期几查找性能:
select
TO_CHAR(created_time, ‘DY’) as day,
COUNT(distinct media_id) AS nums_of_post_got_commented,
COUNT(distinct from_username) AS nums_of_commenter,
ROUND((nums_of_commenter/ cast(nums_of_post_got_commented as FLOAT)), 0) as average_commenter_per_post
from
public.shinestyinstagram_instagram_comments
group by
1
order by
1
下图显示,周四和周五是用户最喜欢评论的时间。

Engagement Performance by Day of Week
- 使用用户何时发表评论来查找一天中每个小时的表现:
select
TO_CHAR(created_time, ‘HH24’) as hour,
COUNT(distinct media_id) AS nums_of_post_got_commented,
COUNT(distinct from_username) AS nums_of_commenter,
ROUND((nums_of_commenter/ cast(nums_of_post_got_commented as FLOAT)), 0) as average_commenter_per_post
from
public.shinestyinstagram_instagram_comments
group by
1
order by
1

Engagement Performance by Hour
- 使用帖子创建时间查找一天中的小时绩效:
SELECT
TO_CHAR(created_time, ‘HH24’) as hour,
SUM(comments_count) AS total_comments,
AVG(comments_count) AS avg_comments,
SUM(likes_count) AS total_likes,
AVG(likes_count) AS avg_likes,
count(distinct id) as nums_of_post
FROM
public.shinestyinstagram_instagram_media
GROUP BY
1
ORDER BY 1
我展示这个查询的目的是因为我认为在一天的早上 7 点到下午 4 点使用这个洞察力来推荐发布 IG 帖子是不合适的。因为这个查询在创建帖子时使用来计算赞和评论的数量。相比之下,当用户发表评论时用来计算性能的最后一个视觉效果,我认为会更准确。所以我建议@shinestythreads 在每天晚上 11 点到凌晨 2 点发布,以获得更多的评论参与度。不幸的是,API 没有提供相同的信息,我想用它来计算喜欢的参与度。

Performance by Hour
- 按媒体类型查找绩效:
SELECT
type,
SUM(likes_count) as total_likes,
AVG(likes_count) as avg_likes,
SUM(comments_count) as total_comments,
AVG(comments_count) as avg_comments,
COUNT(distinct id) as nums_of_post
FROM
public.shinestyinstagram_instagram_media
GROUP BY
1
IG 目前提供三种类型的媒体:图像、视频和轮播。下图显示了视频媒体的平均评论数最多,轮播媒体的平均点赞数最多。而视频媒体表明自己是获得参与度的最佳媒体。

Performance by Media Type using average comments

Performance by Media Type using average likes
- 通过过滤器查找不同介质的性能:
SELECT
filter,
type,
SUM(likes_count) as total_likes,
AVG(likes_count) as avg_likes,
SUM(comments_count) as total_comments,
AVG(comments_count) as avg_comments,
COUNT(distinct id) as nums_of_post
FROM
public.shinestyinstagram_instagram_media
GROUP BY
1, 2
在下图中,我们可以看到除了普通的图像媒体滤镜之外,名为 Crema 的滤镜具有最佳的性能。

Performance by Filter for Image Media
在下面的视频中,我们可以看到除了视频媒体的普通过滤器之外,名为 Ashby 的过滤器具有最佳性能。

Performance by Filter for Video Media
对于轮播媒体,我们可以做同样的事情来获得洞察力,但我没有在这里这样做,因为@shinestythreads 只有针对轮播媒体的普通过滤器。
- 通过使用的位置标签了解性能:
SELECT
location,
SUM(likes_count) as total_likes,
AVG(likes_count) as avg_likes,
SUM(comments_count) as total_comments,
AVG(comments_count) as avg_comments
FROM
(SELECT
name as location,
m.likes_count,
m.comments_count
FROM
public.shinestyinstagram_instagram_media_location l
LEFT JOIN public.shinestyinstagram_instagram_media m
ON l.instagram_media_id = m.id
) as t
GROUP BY
1
该图向我们展示了在所有带有位置标签的帖子中,奥古斯特国家高尔夫俱乐部的平均喜欢和评论参与度最高。

Performance by Location Tag
- 找出有位置标签的帖子与没有位置标签的帖子的性能差异:
WITH t AS
(SELECT
m.id,
m.likes_count,
m.comments_count,
l.name as location
FROM
public.shinestyinstagram_instagram_media m
LEFT JOIN
public.shinestyinstagram_instagram_media_location l
ON
m.id = l.instagram_media_id
),w as
(SELECT
*,
(CASE WHEN location IS NULL THEN 0 ELSE 1 END) AS have_location
FROM t
)SELECT
have_location,
SUM(likes_count) as total_likes,
AVG(likes_count) as avg_likes,
SUM(comments_count) as total_comments,
AVG(comments_count) as avg_comments
FROM
w
GROUP BY
1
与没有位置标签的帖子相比,有位置标签的帖子有更多的平均喜欢,但平均评论稍少。

Performance of Location Tag vs. No Location Tag
- 找出最活跃的评论者:
SELECT
*
FROM
(SELECT
from_username as username,
COUNT(media_id) as nums_of_comments,
RANK() OVER(ORDER BY nums_of_comments DESC)
FROM
public.shinestyinstagram_instagram_comments
GROUP BY
1
ORDER BY
2 DESC
) as t
WHERE
rank >1 and rank <=15
这个视图向我们展示了谁是最活跃的评论者(用户),不包括用户@shinestythreads。

Most Active Commenters
- 队列分析:
with t AS(selectmedia_id,from_username as username,DATE_TRUNC('week', created_time) as weekfrompublic.shinestyinstagram_instagram_comments),w AS(selectusername,min(week) as first_time_commentingfromtGROUP by1)SELECTx.cohort::DATE AS week,MAX(x.week_number) OVER (PARTITION BY x.cohort) AS total_nums_of_week,x.week_number,MAX(x.nums_of_commenter) OVER (PARTITION BY x.cohort) AS nums_of_new_commenter,x.nums_of_commenter,x.nums_of_commenter/MAX(x.nums_of_commenter) OVER (PARTITION BY x.cohort)::FLOAT AS retention_rateFROM(SELECTw.first_time_commenting as cohort,FLOOR(EXTRACT('day' FROM t.week - w.first_time_commenting)/7) AS week_number,COUNT(DISTINCT t.username) AS nums_of_commenterFROMt tLEFT JOINw wONt.username = w.usernameGROUP BY1,2) as xORDER BY 1,2,3

以上是我为这个项目所做的所有分析。对于我用过的数据,因为保密的原因,我没有上传到我的 Github 上。如果你有兴趣了解我为这个项目使用了哪些资源,请访问我的 Github repo 。
如有疑问,欢迎在下方评论。非常感谢您的阅读!
在 AWS 的 Ubuntu 上安装一个 Kafka 集群
通过 AWS 中的 Kafka 消息主干构建实时数据功能

概观
数以万计的组织正在使用 Kafka,包括超过三分之一的财富 500 强公司。这些公司包括十大旅游公司、十大银行中的 7 家、十大保险公司中的 8 家、十大电信公司中的 9 家,等等。LinkedIn、微软和网飞每天用 Kafka 处理四条逗号消息(10 亿条)。它是管理和处理数据流运动的核心。
Kafka 经常在实时流数据架构中使用,以提供实时分析。由于 Kafka 是一个快速、可伸缩、持久和容错的发布-订阅消息传递系统,因此 Kafka 用于 JMS 和 RabbitMQ 由于容量和响应性而可能不被考虑的用例中。Kafka 具有更高的吞吐量、可靠性和复制特性,这使其适用于跟踪服务呼叫(跟踪每个呼叫)或跟踪 IOT 传感器数据等传统 MOM 可能不考虑的事情。
在这篇文章中,我将介绍在 AWS 中的 Linux Ubuntu 上安装 Kafka 的过程,并开始运行一些简单的示例。我将在以后的文章中介绍 Kafka 是如何工作的,以及一些使用 Java 和 Node 的用例。
入门指南
登录您的 AWS 帐户,如果您没有帐户,请创建一个新帐户。如果您使用免费服务,将不会被收费。点击了解有关免费层的更多信息。
让我们生成一个密钥对。转到 EC2- >键对。密钥对将允许您 SSH 并连接到您的 EC2 实例。选择您喜欢的地区并点击创建配对或导入一个已经存在的配对。

下载您的密钥对。
请确保限制文件的权限:
chmod 400 <key pair name>.pem
设置您的实例
让我们为 EC2 实例提供一个 Ubuntu 映像。
转到 EC2 仪表板并点击启动实例。
选择 Ubuntu 图像。

保留所有默认选项,点击查看并启动。
请注意,Kafka 的官方建议是最低 t2.medium,但此选项不在免费层范围内,会让您花钱,因此在本练习中,我们将使用 t2.micro。
选择在上一步中生成的密钥对。
回到 Instances 列表,您应该看到新的 EC2 实例启动了。
连接到您的实例
单击实例,并在描述选项卡上复制公共 DNS (IPv4)
ssh -i ~/.ssh/<key pair name.pem> ubuntu@<Public DNS (IPv4)>
您应该会看到 Ubuntu 欢迎屏幕:

太好了!!您已连接到 EC2 实例

安装 Java
让我们开始安装吧。第一步是更新实例并安装 Java。
运行以下命令:
sudo apt-get update
sudo apt upgrade
sudo add-apt-repository ppa:linuxuprising/java
sudo apt install openjdk-11-jre-headless
测试您的 Java 安装:

安装卡夫卡
现在,让我们使用以下命令安装合流 Kafka:
wget -qO - https://packages.confluent.io/deb/5.2/archive.key | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://packages.confluent.io/deb/5.2 stable main"
sudo apt-get update && sudo apt-get install confluent-platform-2.12
恭喜你!!您现在已经在 AWS 中的 Ubuntu 上安装了一个 Kafka 服务器。
配置 Kafka
让我们用 1 个 Kafka 代理和 1 个主题来配置 Kafka 的最小安装。
导航到您的 Kafka 安装
卡夫卡经纪人
编辑文件服务器.属性
sudo nano /etc/kafka/server.properties
取消对以下行的注释:
metric.reporters=io.confluent.metrics.reporter.ConfluentMetricsReporter
confluent.metrics.reporter.bootstrap.servers=localhost:9092
confluent.metrics.reporter.topic.replicas=1
用 Ctrl+0 和 Ctrl+X 保存以退出
控制中心
编辑文件控制中心生产属性
sudo nano /etc/confluent-control-center/control-center.properties
取消对以下行的注释,并编辑为您的服务器名称或本地主机:
bootstrap.servers=localhost:9092
zookeeper.connect=localhost:2181
在文件末尾添加以下几行:
confluent.controlcenter.internal.topics.partitions=1 confluent.controlcenter.internal.topics.replication=1 confluent.controlcenter.command.topic.replication=1 confluent.monitoring.interceptor.topic.partitions=1 confluent.monitoring.interceptor.topic.replication=1
连接器
sudo nano /etc/kafka/connect-distributed.properties
在文件末尾添加以下几行:
consumer.interceptor.classes=io.confluent.monitoring.clients.interceptor.MonitoringConsumerInterceptor producer.interceptor.classes=io.confluent.monitoring.clients.interceptor.MonitoringProducerInterceptor
开始卡夫卡
让我们开始 Kafka 服务:
sudo systemctl start confluent-zookeeper
sudo systemctl start confluent-kafka
sudo systemctl start confluent-schema-registry
sudo systemctl start confluent-kafka-connect
sudo systemctl start confluent-kafka-rest
sudo systemctl start confluent-ksql
sudo systemctl start confluent-control-center
您可以使用以下命令检查服务状态:
systemctl status confluent*
服务将在以下端口上运行:
ComponentPortKafka 经纪人(纯文本)9092
合流控制中心 9021
Kafka 连接 REST API 8083
KSQL 服务器 REST API 8088
REST 代理 8082
模式注册表 REST API 8081
动物园管理员 2181
要访问您的控制中心,请确保在 AWS 中打开端口 9021。
转到您的实例描述选项卡,并单击安全组已创建。包括端口 9021 的新入站规则。你可以限制你的 IP 地址或者允许所有人访问。

导航到您的 <公共 DNS (IPv4) > :9021 ,您应该会看到您的控制中心。

恭喜你!!

在 Windows 上安装 Shapely

Shapely 是一个 Python 包,它充满了用几何图形处理数据的各种可能性。
但是,如果你在 Windows 操作系统上工作,安装 Shapely 并不是一件简单的事情。
幸运的是,一旦你知道了细节,就没那么难了。
- F 查明您使用的是 32 位还是 64 位 Windows。转到
Settings => System => About => System Type。 - 找出你的 python 版本。打开命令提示符,输入
python --version并记住前两个数字。例如,我的版本是Python 3.7.3,所以我应该记得号码37。 pip install wheel- 在此处和下载项目 1-2 对应的车轮。例如,我有 64 位操作系统和 Python3.70.3,所以我需要下载文件
Shapely-1.6.4.post2-cp**37**-cp**37**m-win_amd**64**.whl。 pip install <path-to-Downloads>\<filename_from_item_4>。例如,我输入了
pip install C:\Users\Dalya\Downloads\Shapely-1.6.4.post2-cp**37**-cp**37**m-win_amd**64**.whl。
就是这样!
使用 conda 安装
这真的很简单!
关于为什么conda install shapely有时不工作,以及为什么需要第一行的更多信息,请到这里。
conda config --add channels conda-forge
conda install shapely
就是这样!
在 Windows 10 上安装 Apache PySpark
产品推荐数据科学项目的 Apache Spark 安装说明

在过去的几个月里,我一直在从事一个数据科学项目,该项目处理一个巨大的数据集,因此有必要使用 Apache PySpark 提供的分布式环境。
在 Windows 10 上安装 PySpark 的时候纠结了很多。所以我决定写这篇博客来帮助任何人在 Windows 10 机器上轻松安装和使用 Apache PySpark。
1.第一步
PySpark 需要 Java 版本 7 或更高版本和 Python 版本 2.6 或更高版本。让我们首先检查它们是否已经安装或安装,并确保 PySpark 可以与这两个组件一起工作。
安装 Java
检查您的机器上是否安装了 Java 版本 7 或更高版本。为此,在命令提示符下执行以下命令。

如果安装了 Java 并配置为从命令提示符运行,那么运行上面的命令应该会将关于 Java 版本的信息打印到控制台。否则,如果您收到如下消息:
‘Java’不被识别为内部或外部命令、可操作程序或批处理文件。
然后你得装 java。
a)为此下载 java 从下载免费 Java 软件
b)获得 Windows x64(如 jre-8u92-windows-x64.exe ),除非您使用的是 32 位版本的 Windows,在这种情况下,您需要获得 Windows x86 离线版本。
c)运行安装程序。
d)安装完成后,关闭当前的命令提示符(如果它已经打开),重新打开并检查是否可以成功运行 java - version 命令。
2。步骤 2
Python
Python 被许多其他软件工具使用。因此,很可能您的计算机上已经有了所需的版本(在我们的例子中是 2.6 或更高版本)。要检查 Python 是否可用并找到其版本,请打开命令提示符并键入命令 python - version
如果安装了 Python 并将其配置为从命令提示符运行,那么运行上面的命令应该会将 Python 版本的信息打印到控制台。例如,我在笔记本电脑上得到以下输出:
C:\Users\uug20>python 版本
Python 3.7.3
相反,如果您收到一条类似这样的消息
“‘python’不被识别为内部或外部命令、可操作程序或批处理文件。”
意味着你需要安装 Python。为此,
a)进入 Python 下载页面。
b)点击最新 Python 2 版本链接。
c)下载 Windows x86–64 MSI 安装程序文件。如果您使用 32 位版本的 Windows,请下载 Windows x86 MSI 安装程序文件。
d)运行安装程序时,在自定义 Python 部分,确保选择了选项将 python.exe 添加到路径。如果未选择此选项,某些 PySpark 实用程序(如 pyspark 和 spark-submit)可能无法工作。
e)安装完成后,关闭命令提示符(如果它已经打开),重新打开并检查您是否可以成功运行 python - version 命令。
3。第三步
安装 Apache Spark
a)转到 Spark 下载页面。
b)选择 Spark 的最新稳定版本。
c) 选择包类型:s 选择为最新版本的 Hadoop 预构建的版本,如为 Hadoop 2.6 预构建的版本。
d) 选择下载类型:选择直接下载。
e)点击下载 Spark 旁边的链接,下载一个压缩的 tar 文件,文件结尾为。tgz 扩展如 spark-1.6.2-bin-hadoop2.6.tgz。
f)安装 Apache Spark 时,您不必运行任何安装程序。使用 7Zip 工具/其他工具将下载的 tar 文件解压缩到您选择的任何文件夹中。
确保包含 Spark 文件的文件夹路径和文件夹名称不包含任何空格。
我在我的 D 盘上创建了一个名为 spark 的文件夹,并在一个名为 spark-2.4.3-bin-hadoop2.7 的文件夹中提取压缩的 tar 文件。因此,所有 spark 文件都在一个名为 D:\ Spark \ Spark-2 . 4 . 3-bin-Hadoop 2.7 的文件夹中。在本文中,我们将这个文件夹称为 SPARK_HOME。
要测试安装是否成功,请打开命令提示符,转到 SPARK_HOME 目录并键入 bin\pyspark。这将启动 PySpark shell,它可用于与 Spark 交互工作。
最后一条消息提示了如何使用 sc 或 sqlContext 名称在 PySpark shell 中使用 Spark。例如,在 shell 中键入 sc.version 应该会打印出 Spark 的版本。您可以像退出任何 Python shell 一样退出 PySpark shell 通过键入 exit()。
PySpark shell 在退出时输出一些消息。因此,您需要按 enter 键返回到命令提示符。
4。步骤 4
配置火花装置
最初,当您启动 PySpark shell 时,它会生成大量类型为 INFO、ERROR 和 WARN 的消息。让我们看看如何删除这些消息。
默认情况下,Windows 上的 Spark 安装不包括 Spark 使用的 winutils.exe 实用程序。如果您没有告诉您的 Spark 安装在哪里寻找 winutils.exe,您将会在运行 PySpark shell 时看到如下错误消息
“错误外壳:在 hadoop 二进制文件路径 Java . io . io 中找不到 winutils 二进制文件异常:在 Hadoop 二进制文件中找不到可执行文件 null\bin\winutils.exe。”
该错误消息不会阻止 PySpark shell 启动。但是,如果您尝试使用 bin\spark-submit 实用程序运行一个独立的 Python 脚本,您将会得到一个错误。例如,当您在 SPARK_HOME 目录中时,尝试在命令提示符下运行 examples 文件夹中的 wordcount.py 脚本。
" bin \ spark-submit examples \ src \ main \ python \ word count . py readme . MD "
安装 winutils
让我们下载 winutils.exe 并配置我们的 Spark 安装来找到 winutils.exe。
a)在 SPARK_HOME 文件夹中创建一个 hadoop\bin 文件夹。
b)下载 hadoop 版本的winutils.exe,Spark 安装就是针对该版本构建的。在我的例子中,hadoop 版本是 2.6.0。于是我下载了Hadoop 2 . 6 . 0 的 winutils.exe,复制到 SPARK_HOME 文件夹下的 hadoop\bin 文件夹。
c)在 Windows 中创建一个名为 SPARK_HOME 的系统环境变量,指向 SPARK_HOME 文件夹路径。
d)在 Windows 中创建另一个名为 HADOOP_HOME 的系统环境变量,该变量指向 SPARK_HOME 文件夹中的 HADOOP 文件夹。
由于 hadoop 文件夹位于 SPARK_HOME 文件夹内,因此最好使用值%SPARK_HOME%\hadoop 来创建 HADOOP_HOME 环境变量。这样,如果 SPARK_HOME 更新了,您就不必更改 HADOOP_HOME。
如果现在从 Windows 命令提示符下运行 bin\pyspark 脚本,与 winutils.exe 相关的错误消息应该会消失。
5。步骤 5
配置火花的日志级别
每当您启动或退出 PySpark shell 或运行 spark-submit 实用程序时,控制台中仍然会有许多额外的信息消息。因此,让我们对我们的 Spark 安装再做一个更改,以便只将警告和错误消息写入控制台。为了做到这一点:
a)将 SPARK_HOME\conf 文件夹中的 log4j.properties.template 文件复制为 SPARK_HOME\conf 文件夹中的 log4j.propertiesfile。
b)将 log4j.rootCategory 属性值设置为 WARN,console。
c)保存 log4j.properties 文件。
现在,任何信息性消息都不会记录到控制台中。
总结
为了使用 PySpark,启动命令提示符并切换到 SPARK_HOME 目录。
a)要启动 PySpark shell,请运行 bin\pyspark 实用程序。进入 PySpark shell 后,使用 sc 和 sqlContext 名称并键入 exit()返回到命令提示符。
b)要运行独立的 Python 脚本,请运行 bin\spark-submit 实用程序,并在命令提示符下指定 Python 脚本的路径以及 Python 脚本需要的任何参数。例如,要从 SPARK_HOME 文件夹中的 examples 目录运行 wordcount.py 脚本,可以运行以下命令:
“bin \ spark-提交示例\ src \ main \ python \ word count . py readme . MD”
6。第六步
重要提示:我在安装时遇到了一个问题
在我的 Windows 10 机器上完成安装程序后,我得到了以下错误信息。
文件" C:\ Users \ uug 20 \ anaconda 3 \ lib \ site-packages \ zmq \ back end \ cy thon \ _ _ init _ _。py”,第 6 行,在 from。import(常量,错误,消息,上下文,import 错误:DLL 加载失败:找不到指定的模块。
解决方案:
我刚想出如何修复它!
在我的例子中,我没有意识到我必须向 PATH 环境变量添加三个与 miniconda 相关的路径。
C:\ Users \ uug 20 \ anaconda 3
C:\ Users \ uug 20 \ anaconda 3 \ Scripts
C:\ Users \ uug 20 \ anaconda 3 \ Library \ bin
之后,我没有收到任何错误信息,pyspark 开始正常工作,并在命令提示符下键入 pyspark 后打开了 Jupyter 笔记本。
希望这对你也有用!
数据科学多领域知识与技术实践
893

被折叠的 条评论
为什么被折叠?



