标签 大数据 下的文章

随着网络中流动着越来越多的数据,由于领导力和技术问题,网络正在滞后于数据的发展速度。

又过了一周,另一项调查发现,IT 已经无法跟上不断膨胀的数据过载。这次的问题将主要是网络带宽和整体性能。

管理咨询公司埃森哲对 300 名 IT 专业人士进行的一项调查 发现,大多数人认为他们企业网络无法胜任处理大数据的任务和物联网部署的任务。只有 43% 的受访公司表示他们的网络已经准备好支持云服务、物联网和其他数字技术。

一个关键原因(58%)是“IT 与商业需求之间的错位”,这延缓了这些项目的进展。这是一个不同寻常的发现,因为 85% 的受访者还表示他们的网络已经完全或者大体上已经准备好支持企业的数字化计划。那么,究竟是哪一种情况呢?

第二和第三大时常提及的障碍是“业务需求和运营需求间固有的复杂性”以及“对带宽、性能等方面的需求超过交付能力”,各占 45%。

由于分析技术和其他大数据技术的推动,大量传输的数据持续涌入网络线路,网络瓶颈持续增长。调查发现,带宽需求并未得到满足,目前的网络性能依旧达不到要求。

其他原因还包括缺乏网络技术、设备扩展和设备老化。

网络性能问题的一个解决方案:SDN

埃森哲发现,大多数公司表示 软件定义网络(SDN) 是应对带宽和性能挑战的解决方案,77% 的受访企业在调查中表示正在部署 SDN 或者已完成部署。它指出,虽然 SDN 可能在组织的某部分中存在,它并不总是在整个企业范围内统一地推出。

如今看来,似乎从未有人有足够的预算来满足他们所有的 IT 雄心,但 31% 受访者认为为网络改善提供资金是“简单的”,而且是在网络基础设施团队的控制范围内,相较于直接下属(13%)或基础设施/网络主管和副总裁(19%),首席信息官/首席技术官更可能将融资过程报告为“轻松”(40%)。

报告指出,“仅靠传统网络无法支持数字时代所需的创新和性能。”报告呼吁拥抱新技术,但没有提到 SDN 的名字。同时它还呼吁首席执行官和他们直接下属间加强合作,因为很明显,双方在看待问题的方式上存在分歧。

报告总结说,“我们认为需要一种新的网络范式来确保网络满足当前和未来的业务需求。然而,尽管有进步的迹象,但变革的步伐缓慢。公司必须承担起重担,才能实现统一和标准化企业能力,提供必要的带宽、性能和安全,以支持当前和未来的业务需求”。


via: https://www.networkworld.com/article/3440519/most-enterprise-networks-cant-handle-big-data-loads.html

作者:Andy Patrizio 选题:lujun9972 译者:chenmu-kk 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

代码英雄讲述了开发人员、程序员、黑客、极客和开源反叛者如何彻底改变技术前景的真实史诗。

什么是《代码英雄》

代码英雄 Command Line Heroes 是世界领先的企业开源软件解决方案供应商红帽(Red Hat)精心制作的原创音频播客,讲述开发人员、程序员、黑客、极客和开源反叛者如何彻底改变技术前景的真实史诗。该音频博客邀请到了谷歌、NASA 等重量级企业的众多技术大牛共同讲述开源、操作系统、容器、DevOps、混合云等发展过程中的动人故事。

本文是《代码英雄》系列播客第二季(6):数据大爆炸音频脚本。

导语:大数据将有助于解决大问题:我们如何种植粮食、如何向需要的人运送物资、如何治疗疾病。但首先,我们需要弄清楚如何处理它。

现代生活充满了相互联系的组件。我们现在一天产生的数据比几千年来的数据还要多。 Kenneth Cukier 解释了数据是如何发生变化的,以及它是如何开始改变我们的。Ellen Grant 博士告诉我们波士顿儿童医院是如何使用开源软件将堆积如山的数据转化为个性化治疗方法。Sage Weil 则分享了 Ceph 的可扩展和弹性云存储如何帮助我们管理数据洪流。

收集信息是了解我们周围世界的关键。大数据正在帮助我们拓展永不停歇的探索使命。

00:00:03 - Saron Yitbarek

如果你把从人类历史早期到 2003 年创建的所有数据计算在内,你将得到大约 500 万 GB 的数据。我们昨天创建了多少 GB 数据?

00:00:15 - 问卷调查答案 1

哦,天哪,10 万。

00:00:21 - 问卷调查答案 2

可能是 500 万 GB 数据。

00:00:23 - 问卷调查答案 3

我们在昨天一天之内创建了多少 GB 的数据?1000 万 GB 数据?

00:00:31 - 问卷调查答案 4

我不太知道,可能是 200 万 GB 数据?

00:00:36 - 问卷调查答案 5

也许一天就有 100 万 GB 数据?

00:00:40 - Saron Yitbarek

答案是?超过 25 亿 GB 数据!

00:00:44 - 问卷调查答案 1

哇哦。

00:00:44 - 问卷调查答案 2

25 亿?

00:00:45 - 问卷调查答案 3

所以,我们已经打破了世界纪录。

00:00:45 - 问卷调查答案 4

那可真是很多个 G 啊。

00:00:45 - 问卷调查答案 5

我都不敢相信那有这么多的数据。

00:00:52 - Saron Yitbarek

在 2016 年,我们的年度在线数据流量首次超过了 1ZB。一个 ZB 是 1000^7 字节。好,记住这个数字了吗?现在把它乘以 3,因为那是我们将在 2021 年拥有的数据量大小。

00:01:10

我知道,大脑不是以 ZB 为单位进行思考的,但请你至少暂时记住这个数。 我们的 IP 流量将在五年内翻三番。 这是数据的洪流,而我们正处于其中。

00:01:24

在刚过去的一分钟里,人们发出了 1600 万条短信;与此同时,在我说出这句话的时间里,谷歌处理了 20 万条搜索。

00:01:37

如果我们能在数据洪流来临时做好准备、站稳脚跟,那么隐藏在其中的模式、答案和秘密可以极大地改善我们的生活。

00:01:50

我是 Saron Yitbarek,这里是《代码英雄》,一款红帽公司原创的播客节目。浪潮近在眼前。这里是第二季第六集,数据大爆炸。

00:02:17

我们如何处理如此大量的数据? 采集到这些数据后,我们如何利用它们? 大数据将为我们解决一些最复杂的问题:

00:02:29

如何管理交通、如何种植粮食、如何向需要的人提供物资,但这一切的前提是,我们必须弄清楚该怎么使用这些数据、以及该怎么在短得不能再短的时间内完成对它们的处理。

00:02:43 - Kenneth Cukier

通过获取更多的数据,我们可以深入到这些子群体、这些细节,而这是我们以前从来没有过的方式。

00:02:53 - Saron Yitbarek

Kenneth Cukier 是《 经济学人 The Economist 》的高级编辑,他也和我都在科技播客《Babbage》里。

00:03:01 - Kenneth Cukier

这并不是说我们以前无法收集数据。我们可以,但这真的、真的很昂贵。真正的革命性突破是,我们使数据搜集变得十分容易。

00:03:10

现在收集数据的成本极低,而且处理起来也超级简单,因为都是由电脑完成的。这已经成为我们这个时代的巨大革命,它可能是现代生活最显著的特征,在未来几十年甚至下个世纪都会如此。这也是大数据如此重要的原因。

00:03:33 - Saron Yitbarek

历史可以提醒我们这种变化是翻天覆地的。想想看,4000 年前,我们把所有的数据都刻在了干泥板上。

00:03:46 - Kenneth Cukier

这些黏土盘很重。黏土盘被烤干后,刻在其中的数据就无法更改。从古至今,信息处理、存储、传输、创建的方式都发生了变化,对吗?

00:04:04 - Saron Yitbarek

时代巨变。大约在 1450 年,印刷机的发明带来了第一次信息革命。今天,我们也迎来了一场革命。

00:04:16 - Kenneth Cukier

现在的存储介质很轻巧。信息的修改变得极度简单,借助现有的处理器,我们只需要使用删除键就能修改我们所拥有的信息实例,无论那是储存在磁带上还是晶体管里。我们可以以光速传输数据,不用携带什么黏土盘。

00:04:37 - Saron Yitbarek

在 15 世纪,借助印刷机,大量的数据得以传播。这些知识提升了人们对事物的认识,并促成了启蒙运动。

00:04:45

今天,大数据可以再次提升我们的知识水平,但我们必须要想办法充分利用这些数据。唯有修好大坝、备好轮机,才能让浪潮为人所用。

00:05:00 - Kenneth Cukier

当下,人们远没有做到对数据的充分利用。这一点非常重要,因为我们已经看到,数据中存在这种潜在的价值,而收集、存储和处理数据的成本在近百年来,乃至于近十年来,已经显著地降低了。

00:05:22 - Kenneth Cukier

这很振奋人心。但问题是,我们在文化上、在我们的组织流程上,甚至我们的 CFO 和 CIO 们拨给相关方面的预算中,并不重视这种价值,

00:05:35 - Saron Yitbarek

想着这种事肯定让人极度沮丧。启蒙运动在敲门,却无人应答。然而,我们不回答的部分原因是:门后到底是谁?这些数据能带来什么?

00:05:51

Kenneth 认为,某些公司不采用大数据,乃是因为它太过于新奇。

00:05:56 - Kenneth Cukier

一旦你收集了大量数据后,你能拿它干什么?我就直说吧,只有傻子才会以为自己知道。你绝对无法设想你今天收集到的数据明天能拿来做什么用。

00:06:12

最重要的是要有数据,并以开放的思想对待所有可以使用的方式。

00:06:18 - Saron Yitbarek

如果我们按照 Kenneth 说的那样以正确的方式对待大数据,我们将会发现一切的全新可能性。这将是一个人人 —— 而不只是数据科学家 —— 都能洞察趋势、分析细节的世界。

00:06:33 - Kenneth Cukier

如果我们能意识到,这个世界是可以通过收集经验证据来理解、改变和改善的,并且可以用一种自动化的方式进行改善,我们将会得到看待它的全新角度。我个人认为,现如今,在世界各地,上至政策制定者、下至星巴克咖啡师,都在经历这种引人深思的文化上或心理上的变化。

00:07:00

各行各业的人都有点数据基因,就像是被感染了似的。现在,无论他们专注于什么方面,他们都以大数据的方式思考。

00:07:15 - Saron Yitbarek

Kenneth Cukier 给我们讲了一个简短的故事来展现这种新数据思维方式的力量。微软的一些研究人员开始着手研究胰腺癌问题。

00:07:27

人们发现胰腺癌往往为时已晚,早期发现可以挽救生命。因此,研究人员开始询问这些患者,在开始搜索有关胰腺癌的信息之前几个月,他们搜索了什么? 而早在发现前数年,他们又搜索了什么?

00:07:46

研究人员开始寻找埋藏在所有搜索数据中的线索和模式。

00:07:54 - Kenneth Cukier

他们有了重大发现。通过分析患者在最终开始搜索“胰腺癌”之前的这段时间中所搜索的关键词,他们识别出了一套规律,可以非常准确地预测搜索者是否患有胰腺癌。

00:08:09

在这里,我们能学到一点:想象力与数据中潜在规律的结合,是可以挽救生命的。他们现在所要做的就是找到一种方法,通过方法来解释这一发现,这样当人们在搜索这些术语时,他们可以以一种微妙的方式干预,说,“你可能要去诊所检查一下。”

00:08:29

像这样使用数据,就能救人于水火之中。

00:08:37 - Saron Yitbarek

研究人员偶然发现的是一种新的癌症筛查方式,通过这种方法,患者可以提前一个月得知自己可能患癌。利用数据不仅仅是一个利润或效率最大化的问题。

00:08:52

它的意义远不止于此。对于人类而言,这些数据中确确实实存在着大量的潜在利好。抗拒使用大数据可能只是自欺欺人。接下来,我们要关注的是,这场将数据投入工作的持久战。

00:09:18

哈佛医学院的波士顿儿童医院去年完成了 26000 多台手术,进行约 25 万人次的儿童放射检查。

00:09:31

医护人员的表现令人称道,但有一个巨大的障碍挡在他们面前。

00:09:37 - Ellen Grant

在医院的环境中,尤其是作为医生,我们经常会遇到难以获取数据的问题。

00:09:45 - Saron Yitbarek

这位是 Ellen Grant 医生,她是波士顿儿童医院的儿科神经放射科医生,她在诊疗时依靠访问数据和分析医学图像。

00:09:56 - Ellen Grant

如果没有专门设置的环境,想要从 packs 里存储的图像进行额外的数据分析绝非易事。当你在一个只提供了普通的医院电脑的读片室里时,要做到这一点并不容易。

00:10:14

获取数据实际上是有障碍的。

00:10:17 - Saron Yitbarek

其实许多医院都会大量抛弃数据,因为存储它们的成本实在过于高昂。这部分数据就像这样丢失了。像 Grant 这样的放射科医生可能是第一批因为数据实在太多而感到沮丧的医务人员。

00:10:33

当医院走向数字化后,他们开始创造大量的数据,很快,这个量就大到无法处理了。

00:10:41 - Ellen Grant

我,作为一名临床医生,在读片室里的时候希望能将所有复杂的分析工作在研究环境中做完。但我无法随便就从 packs 中拿出来图像,拿到一些可以进行分析的地方,再拿回到我手里。

00:10:59 - Saron Yitbarek

顺便说一句,packs 就是医院存储其图像的数据仓库。Grant 医生知道有一些工具可以让这些图像 packs 发挥更大的功能,但成本太高。

00:11:12 - Ellen Grant

随着机器学习和 AI 时代的到来,数据的生产量将会日渐加大,我们会需要更多计算资源来进行这类大规模的数据库分析。

00:11:27 - Saron Yitbarek

数据已经堆积如山了,但处理能力却没有相称的增长。在这一前提下,对数据的彻底处理将变得遥不可及。而复杂、昂贵的超级计算机并不是医院的选择。

00:11:41

Grant 医生深感沮丧。

00:11:44 - Ellen Grant

我们能不能想出一个更好的办法,让我把数据拿到这里来,分析一下,然后放回去,这样我就可以在会诊的时候,一边解释临床图像,一边把分析做完,因为我希望可以在会诊上展示数据,在此同时进行快速分析。

00:11:56

我可不想在不同的电脑和存储器之间把这些数据挪来挪去,这不是我的工作。我的工作是理解非常复杂的医学疾病,并把相关的事实真相记在脑子里。

00:12:10

我想专注于我的技术领域,在此同时利用计算机领域的新兴技术;而不必这方面过于深入钻研。

00:12:21 - Saron Yitbarek

Grant 和世界各地的放射科医生们需要的是一种方法,只要点击图像就能运行详细分析,并让这一切都发生在云端,这样医院就不必建立自己的服务器场地,也不必把医务人员变成程序员。

00:12:40

他们需要一种方法来使他们的数据尽可能地拯救生命。这正是 Grant 医生和几位代码英雄决定去做的事。

00:12:55

Grant 在波士顿儿童医院的团队正在与红帽和马萨诸塞州开放云(MOC)合作。关于 MOC 的更多内容稍后再说。首先,我们需要请出 Rudolph Pienaar,他是医院的一名生物化学工程师,来描述一下他们的解决方案。它是一个开源的、基于容器的成像平台。

00:13:15 - Saron Yitbarek

它完全是在云端运行的,所以你不受医院本身计算能力的限制。他们称这一作品为 ChRIS。

00:13:24 - Rudolph Pienaar

ChRIS 有一个后台数据库,其实就是一个 Django Python 机器。它可以跟踪用户,并跟踪这些用户使用过的数据以及分析结果。

00:13:35

围绕这个数据库,有大量的服务群,这些服务都是作为自己的实例存在于容器中。它们处理与医院资源的通信,比如与医院数据库的通信。这些服务从资源中提取复杂的数据,将其推送给云端的、或者另一个实验室的、或者别的什么地方的其他服务处理。在计算数据的地方,有 Kubernetes 之类的编排服务,以及你需要使用的分析程序。数据处理结束之后,结果就会被发送回来。

00:14:11 - Saron Yitbarek

对于 Grant 医生来说,ChRIS 成像平台是一种让数据活起来的方法。更重要的是,这种数据处理方式能让她成为更好的医生。

00:14:21 - Ellen Grant

优秀的医生之所以优秀,是因为他们在一生中积累了丰富的从业经验。如果我们能把这一点融入到数据分析中,以此来获得更多的信息,我们就能知道得更多,并更有效地整合这些经验。

00:14:39

例如,我对特定病患的特定受伤方式的认识,取决于我的从医经验和对这些经验的整体理解。

00:14:52

现在,我可以根据真实数据创建受伤症状分布的概率图,并将其公之于众;我也可以寻找有相似模式的患者,并告诉他们在接受治疗时,什么对他们最有效,以便更接近精准医疗。

00:15:10

整合大量的数据,尝试探索我们过去的知识,并尽你所能,点明治疗病人的最佳方式。

00:15:21 - Saron Yitbarek

这对被送到医院的孩子意味着什么?Grant 医生说,ChRIS 平台能提供更有针对性的诊断和更个性化的护理。

00:15:31 - Ellen Grant

如果我们拥有更复杂的数据库,我们就能更好地理解信息之间繁杂的相互作用,因此就能更好地指导每个患者。我认为 ChRIS 就像是我进入超级大脑的接口,它能让我比平时更聪明,因为我不能一次把所有数据保存在我的大脑中。

00:15:53 - Saron Yitbarek

当赌注如此沉重时,我们要突破人类大脑的极限。这位是 Máirín Duffy。她是红帽团队中的设计师,她让 ChRIS 成为现实,而根据个人经验,她知道这件事其中的风险。

00:16:15 - Máirín Duffy

我父亲中风了,所以我一直作为病人家属等待医疗技术诊断,因为当一个人中风并被送到医院之后,医务人员必须弄清楚是哪种类型的中风。根据中风类型,有不同的治疗方法。

00:16:31

如果使用了错误的治疗方案,就可能发生极其糟糕的事。所以,在这种情况下,你能越快地把病人送来做核磁共振,就能越快地得到治疗方案。速度越快就有可能挽救他们的生命。

00:16:43

想想看,仅仅是把图像处理从云端推送出来,并行化处理,就能让它快很多。这样就能将这个过程从几小时、几天,缩短到几分钟。

00:16:55 - Saron Yitbarek

医学可能正迎来一个新的拐点。一个不是由药理学驱动,而是由计算机科学驱动的拐点。另外,想想像 ChRIS 这种东西的拓展性。

00:17:08

发展中国家的医生也可以受益于波士顿儿童医院的专业知识和数据集。任何有手机服务的人都可以通过网络访问能够拯救生命的数据和计算结果。

00:17:24

除了医学,很多其他领域也可能出现类似的拐点。但前提是,人们得知道如何从自己的数据中找到隐藏信息。为了做到这一点,他们需要探索一个全新的计算领域。

00:17:46

世界各地的人们都在学习如何利用数据。就像在波士顿儿童医院一样,将数据洪流导向目标。

00:17:56

换句话说,我们在处理这些数据。但我们之所以能做到这一点,是因为新一代的云计算使之成为可能。

00:18:11

对于像 ChRIS 这样的平台来说,一个关键因素是基于云计算的新型存储方式。请记住,很多医院都会把收集到的数据扔掉,因为他们根本无法容纳所有数据。

00:18:25

这就是我想重点讨论的数据泛滥的最后一块拼图:存储解决方案。对于 ChRIS 来说,存储解决方案是一个叫 Ceph 的开源项目。它使用的马萨诸塞州开放云,就基于 Ceph。

00:18:45

我和 Ceph 的创建者 Sage Weil 聊了聊,想了解更多关于像波士顿儿童医院这样的地方是如何在闪电般的时间内处理海量数据的。以下是我与 Sage 的对话。我认为,第一个重要问题是,什么是 Ceph,它能做什么?

00:19:05 - Sage Weil

当然,Ceph 是一个由软件定义的存储系统,它允许你提供可靠的存储服务,并在不可靠的硬件上提供各种协议。

00:19:14

它的设计从开始就是满足可扩展性,所以你可以拥有非常非常大的存储系统、非常大的数据集。于此同时,系统对硬件故障和网络故障有优秀的容忍性,所以即使出现了一些这类问题,存储中的数据仍然不会变得难于访问。

00:19:29 - Saron Yitbarek

现在,数据太多了。

00:19:31 - Sage Weil

是的。

00:19:33 - Saron Yitbarek

如此大的工作量。要处理的东西实在是太多了。你认为这个解决方案出现得是时候吗?

00:19:39 - Sage Weil

是的,肯定是这样。在当时,行业中这方面的严重不足是显而易见的。没有开源的解决方案可以解决可扩展的存储问题。所以,我们显然得造个轮子。

00:19:53 - Saron Yitbarek

考虑到我们每天要处理的数据量,以及它将来只会越来越多、越来越难管理的事实,你认为当今该怎么做才能解决这种日益增长的需求?

00:20:09 - Sage Weil

我认为有几方面。一方面,有令人难以置信的数据量正在产生,所以你需要可扩展的系统。它不仅可以在硬件和数据规模上进行扩展,而且,它的管理成本应该是一定的,至少应该基本固定。

00:20:25 - Saron Yitbarek

嗯。

00:20:26 - Sage Weil

你不会想就为每多 10PB 存储空间或类似的东西就多雇一个员工吧?我认为这套系统在运维上也必须可扩展。

00:20:33 - Saron Yitbarek

是的。

00:20:35 - Sage Weil

这是其中的一部分。我认为,人们利用存储空间的方式也在改变。一开始,都是文件存储,然后我们有了虚拟机的块存储,我觉得对象存储在某种程度上是行业的重要趋势。

00:20:51

我认为,下一个阶段的目标并不局限于提供一个对象存储端点,并将数据存储在集群中;我们需要将解决方案进一步升级,好让它能管理集群的集群,抑或是对分布于不同地理位置的云空间及私有数据中心储存空间中的数据进行管理。

00:21:13

例如说,你现在将数据写入一个位置,随着时间的推移,你可能会想将数据分层到到其他位置,因为它更便宜、或者服务器离你更近;或者,一旦数据太老、不会频繁使用了,你就需要将其移动到性能更低、容量更大的层次上,以保证存储的成本较低。

00:21:27

你可能也会为了遵循地方法规而移动数据。在欧洲的一些地区接收数据时,数据来源必须保持在特定的政治边界内。

00:21:39

在某些行业,像 HIPAA 这样的东西限制了数据的移动方式。我认为,随着现代 IT 组织越来越多地分布在不同的数据中心、公有和私有云中,统一地、自动化地管理它们的能力正变得越加重要。

00:21:58 - Saron Yitbarek

当你想到未来我们要如何管理和存储数据,以及如何处理数据的时候,开源在其中扮演了怎样的角色?你曾提到,你之所以要创建一个开源的解决方案,是因为你个人的理念和你对自由和开源软件的强烈感情。

00:22:16

你如何看待开源对未来其他解决方案的影响?

00:22:21 - Sage Weil

我认为,特别是在基础设施领域,解决方案正在向开源靠拢。我认为原因是基础设施领域的成本压力很大,特别是对于构建软件即服务(SaaS)或云服务的人来说,低成本的基础设施很重要,从他们的角度来看,开源显然是一个非常好的方法。

00:22:48

第二个原因更多地是社会因素,在这个快速发展的领域里有如此多新的工具、新的框架、新的协议、新的数据思维方式,这个领域中有这么多创新和变化,有这么多不同的产品和项目在相互作用,所以很难以传统方式做到这一点,比如说,让不同的公司互相签订合作协议,共同开发。

00:23:20

开源可以消除此事上的所有阻力。

00:23:28 - Saron Yitbarek

Sage Weil 是红帽公司的高级咨询工程师,也是 Ceph 项目的负责人。我要绕回到《经济学人》的 Kenneth Cukier,以从一个更整体的视角上进行讨论,因为我希望,我们能够记住他关于人与数据之间关系的看法,以及我们从泥板,到印刷机,再到像 Sage 打造的云端奇迹的进步历程。

00:23:55 - Kenneth Cukier

这关乎人类的进步,关乎我们如何更好地理解世界,如何从现实中总结经验,以及如何改善世界。这进步也是人类一直以来的使命。

00:24:08 - Saron Yitbarek

使命永无止境。但是,与此同时,学会处理我们收集到的数据并将其投入使用,是整整一代人的开源任务。我们将在田纳西州的 橡树岭国家实验室 Oak Ridge National Laboratory 短暂停留,结束我们的数据之旅。它是世界上最快的超级计算机 Summit 的所在地,至少在 2018 年是最快的超级计算机。

00:24:43

这台机器每秒能处理 20 万亿次计算。换个计量单位,就是 200 petaflops。这样的处理速度,对于医院、银行或者今天所有受益于高性能计算的成千上万的组织来说并不现实。

00:25:04

像 Summit 这样的超级计算机更多的是留给强子对撞机的领域。不过话说回来,我们曾经在泥板上记录的只是 100 字节的信息。

00:25:16

在数据存储和数据处理的领域中,非凡的壮举不断成为新的常态。有一天,我们或许能将 Summit 级别的超级计算机装进口袋。想一想,到时候我们能够搜索到的答案。

00:25:42

下一集,我们聊聊无服务器。第 7 集将会讲述我们与基于云的开发之间不断发展的关系。我们将会探究,在我们的工作中有多少可以抽象化的部分,以及在这个过程可能会失去的东西。

00:25:58 - Saron Yitbarek

同时,如果你想深入了 ChRIS 的故事,请访问 redhat.com/chris ,了解它是如何构建的,以及如何为项目本身做出贡献。

00:26:12 - Saron Yitbarek

《代码英雄》是一款红帽公司原创的播客。你可以在 Apple Podcast、Google Podcast 或任何你想做的事情上免费收听。

00:26:24 - Saron Yitbarek

我是 Saron Yitbarek。坚持编程,下期再见。

什么是 LCTT SIG 和 LCTT LCRH SIG

LCTT SIG 是 LCTT 特别兴趣小组 Special Interest Group ,LCTT SIG 是针对特定领域、特定内容的翻译小组,翻译组成员将遵循 LCTT 流程和规范,参与翻译,并获得相应的奖励。LCRH SIG 是 LCTT 联合红帽(Red Hat)发起的 SIG,当前专注任务是《代码英雄》系列播客的脚本汉化,已有数十位贡献者加入。敬请每周三、周五期待经过我们精心翻译、校对和发布的译文。

欢迎加入 LCRH SIG 一同参与贡献,并领取红帽(Red Hat)和我们联合颁发的专属贡献者证书。


via: https://www.redhat.com/en/command-line-heroes/season-2/the-data-explosion

作者:Red Hat 选题:bestony 译者:TimeBear 校对:Northurland, wxy

本文由 LCRH 原创编译,Linux中国 荣誉推出

介绍

KSQL 是 Apache Kafka 中的开源的流式 SQL 引擎。它可以让你在 Kafka 主题 topic 上,使用一个简单的并且是交互式的 SQL 接口,很容易地做一些复杂的流处理。在这个短文中,我们将看到如何轻松地配置并运行在一个沙箱中去探索它,并使用大家都喜欢的演示数据库源: Twitter。我们将从推文的原始流中获取,通过使用 KSQL 中的条件去过滤它,来构建一个聚合,如统计每个用户每小时的推文数量。

Confluent

首先, 获取一个 Confluent 平台的副本。我使用的是 RPM 包,但是,如果你需要的话,你也可以使用 tar、 zip 等等 。启动 Confluent 系统:

$ confluent start

(如果你感兴趣,这里有一个 Confluent 命令行的快速教程

我们将使用 Kafka Connect 从 Twitter 上拉取数据。 这个 Twitter 连接器可以在 GitHub 上找到。要安装它,像下面这样操作:

# Clone the git repo
cd /home/rmoff
git clone https://github.com/jcustenborder/kafka-connect-twitter.git
# Compile the code
cd kafka-connect-twitter
mvn clean package

要让 Kafka Connect 去使用我们构建的连接器, 你要去修改配置文件。因为我们使用 Confluent 命令行,真实的配置文件是在 etc/schema-registry/connect-avro-distributed.properties,因此去修改它并增加如下内容:

plugin.path=/home/rmoff/kafka-connect-twitter/target/kafka-connect-twitter-0.2-SNAPSHOT.tar.gz

重启动 Kafka Connect:

confluent stop connect
confluent start connect

一旦你安装好插件,你可以很容易地去配置它。你可以直接使用 Kafka Connect 的 REST API ,或者创建你的配置文件,这就是我要在这里做的。如果你需要全部的方法,请首先访问 Twitter 来获取你的 API 密钥

{
 "name": "twitter_source_json_01",
 "config": {
   "connector.class": "com.github.jcustenborder.kafka.connect.twitter.TwitterSourceConnector",
   "twitter.oauth.accessToken": "xxxx",
   "twitter.oauth.consumerSecret": "xxxxx",
   "twitter.oauth.consumerKey": "xxxx",
   "twitter.oauth.accessTokenSecret": "xxxxx",
   "kafka.delete.topic": "twitter_deletes_json_01",
   "value.converter": "org.apache.kafka.connect.json.JsonConverter",
   "key.converter": "org.apache.kafka.connect.json.JsonConverter",
   "value.converter.schemas.enable": false,
   "key.converter.schemas.enable": false,
   "kafka.status.topic": "twitter_json_01",
   "process.deletes": true,
   "filter.keywords": "rickastley,kafka,ksql,rmoff"
 }
}

假设你写这些到 /home/rmoff/twitter-source.json,你可以现在运行:

$ confluent load twitter_source -d /home/rmoff/twitter-source.json

然后推文就从大家都喜欢的网络明星 [rick] 滚滚而来……

$ kafka-console-consumer --bootstrap-server localhost:9092 --from-beginning --topic twitter_json_01|jq '.Text'
{
  "string": "RT @rickastley: 30 years ago today I said I was Never Gonna Give You Up. I am a man of my word - Rick x https://t.co/VmbMQA6tQB"
}
{
  "string": "RT @mariteg10: @rickastley @Carfestevent Wonderful Rick!!\nDo not forget Chile!!\nWe hope you get back someday!!\nHappy weekend for you!!\n❤…"
}

KSQL

现在我们从 KSQL 开始 ! 马上去下载并构建它:

cd /home/rmoff
git clone https://github.com/confluentinc/ksql.git
cd /home/rmoff/ksql
mvn clean compile install -DskipTests

构建完成后,让我们来运行它:

./bin/ksql-cli local --bootstrap-server localhost:9092
                       ======================================
                       =      _  __ _____  ____  _          =
                       =     | |/ // ____|/ __ \| |         =
                       =     | ' /| (___ | |  | | |         =
                       =     |  <  \___ \| |  | | |         =
                       =     | . \ ____) | |__| | |____     =
                       =     |_|\_\_____/ \___\_\______|    =
                       =                                    =
                       =   Streaming SQL Engine for Kafka   =
Copyright 2017 Confluent Inc.

CLI v0.1, Server v0.1 located at http://localhost:9098

Having trouble? Type 'help' (case-insensitive) for a rundown of how things work!

ksql> 

使用 KSQL, 我们可以让我们的数据保留在 Kafka 主题上并可以查询它。首先,我们需要去告诉 KSQL 主题上的 数据模式 schema 是什么,一个 twitter 消息实际上是一个非常巨大的 JSON 对象, 但是,为了简洁,我们只选出其中几行:

ksql> CREATE STREAM twitter_raw (CreatedAt BIGINT, Id BIGINT, Text VARCHAR) WITH (KAFKA_TOPIC='twitter_json_01', VALUE_FORMAT='JSON');

Message  
----------------
Stream created

在定义的模式中,我们可以查询这些流。要让 KSQL 从该主题的开始展示数据(而不是默认的当前时间点),运行如下命令:

ksql> SET 'auto.offset.reset' = 'earliest';  
Successfully changed local property 'auto.offset.reset' from 'null' to 'earliest'

现在,让我们看看这些数据,我们将使用 LIMIT 从句仅检索一行:

ksql> SELECT text FROM twitter_raw LIMIT 1;  
RT @rickastley: 30 years ago today I said I was Never Gonna Give You Up. I am a man of my word - Rick x https://t.co/VmbMQA6tQB
LIMIT reached for the partition.  
Query terminated
ksql>

现在,让我们使用刚刚定义和可用的推文内容的全部数据重新定义该流:

ksql> DROP stream twitter_raw;
Message
--------------------------------
Source TWITTER_RAW was dropped

ksql> CREATE STREAM twitter_raw (CreatedAt bigint,Id bigint, Text VARCHAR, SOURCE VARCHAR, Truncated VARCHAR, InReplyToStatusId VARCHAR, InReplyToUserId VARCHAR, InReplyToScreenName VARCHAR, GeoLocation VARCHAR, Place VARCHAR, Favorited VARCHAR, Retweeted VARCHAR, FavoriteCount VARCHAR, User VARCHAR, Retweet VARCHAR, Contributors VARCHAR, RetweetCount VARCHAR, RetweetedByMe VARCHAR, CurrentUserRetweetId VARCHAR, PossiblySensitive VARCHAR, Lang VARCHAR, WithheldInCountries VARCHAR, HashtagEntities VARCHAR, UserMentionEntities VARCHAR, MediaEntities VARCHAR, SymbolEntities VARCHAR, URLEntities VARCHAR) WITH (KAFKA_TOPIC='twitter_json_01',VALUE_FORMAT='JSON');
Message
----------------
Stream created

ksql>

现在,我们可以操作和检查更多的最近的数据,使用一般的 SQL 查询:

ksql> SELECT TIMESTAMPTOSTRING(CreatedAt, 'yyyy-MM-dd HH:mm:ss.SSS') AS CreatedAt,\
EXTRACTJSONFIELD(user,'$.ScreenName') as ScreenName,Text \
FROM twitter_raw \
WHERE LCASE(hashtagentities) LIKE '%oow%' OR \
LCASE(hashtagentities) LIKE '%ksql%';  

2017-09-29 13:59:58.000 | rmoff | Looking forward to talking all about @apachekafka & @confluentinc’s #KSQL at #OOW17 on Sunday 13:45 https://t.co/XbM4eIuzeG

注意这里没有 LIMIT 从句,因此,你将在屏幕上看到 “continuous query” 的结果。不像关系型数据表中返回一个确定数量结果的查询,一个持续查询会运行在无限的流式数据上, 因此,它总是可能返回更多的记录。点击 Ctrl-C 去中断然后返回到 KSQL 提示符。在以上的查询中我们做了一些事情:

  • TIMESTAMPTOSTRING 将时间戳从 epoch 格式转换到人类可读格式。(LCTT 译注: epoch 指的是一个特定的时间 1970-01-01 00:00:00 UTC)
  • EXTRACTJSONFIELD 来展示数据源中嵌套的用户域中的一个字段,它看起来像:
{
"CreatedAt": 1506570308000,
"Text": "RT @gwenshap: This is the best thing since partitioned bread :) https://t.co/1wbv3KwRM6",
[...]
"User": {
    "Id": 82564066,
    "Name": "Robin Moffatt \uD83C\uDF7B\uD83C\uDFC3\uD83E\uDD53",
    "ScreenName": "rmoff",
    [...]
  • 应用断言去展示内容,对 #(hashtag)使用模式匹配, 使用 LCASE 去强制小写字母。(LCTT 译注:hashtag 是twitter 中用来标注线索主题的标签)

关于支持的函数列表,请查看 KSQL 文档

我们可以创建一个从这个数据中得到的流:

ksql> CREATE STREAM twitter AS \
SELECT TIMESTAMPTOSTRING(CreatedAt, 'yyyy-MM-dd HH:mm:ss.SSS') AS CreatedAt,\
EXTRACTJSONFIELD(user,'$.Name') AS user_Name,\
EXTRACTJSONFIELD(user,'$.ScreenName') AS user_ScreenName,\
EXTRACTJSONFIELD(user,'$.Location') AS user_Location,\
EXTRACTJSONFIELD(user,'$.Description') AS  user_Description,\
Text,hashtagentities,lang \
FROM twitter_raw ;

Message  
----------------------------  
Stream created and running  

ksql> DESCRIBE twitter;
Field            | Type  
------------------------------------  
ROWTIME          | BIGINT  
ROWKEY           | VARCHAR(STRING)  
CREATEDAT        | VARCHAR(STRING)  
USER_NAME        | VARCHAR(STRING)  
USER_SCREENNAME  | VARCHAR(STRING)  
USER_LOCATION    | VARCHAR(STRING)  
USER_DESCRIPTION | VARCHAR(STRING)  
TEXT             | VARCHAR(STRING)  
HASHTAGENTITIES  | VARCHAR(STRING)  
LANG             | VARCHAR(STRING)  
ksql>

并且查询这个得到的流:

ksql> SELECT CREATEDAT, USER_NAME, TEXT \
FROM TWITTER \
WHERE TEXT LIKE '%KSQL%';  

2017-10-03 23:39:37.000 | Nicola Ferraro | RT @flashdba: Again, I'm really taken with the possibilities opened up by @confluentinc's KSQL engine #Kafka https://t.co/aljnScgvvs

聚合

在我们结束之前,让我们去看一下怎么去做一些聚合。

ksql> SELECT user_screenname, COUNT(*) \
FROM twitter WINDOW TUMBLING (SIZE 1 HOUR) \
GROUP BY user_screenname HAVING COUNT(*) > 1;  

oracleace | 2  
rojulman | 2
smokeinpublic | 2  
ArtFlowMe | 2  
[...]

你将可能得到满屏幕的结果;这是因为 KSQL 在每次给定的时间窗口更新时实际发出聚合值。因为我们设置 KSQL 去读取在主题上的全部消息(SET 'auto.offset.reset' = 'earliest';),它是一次性读取这些所有的消息并计算聚合更新。这里有一个微妙之处值得去深入研究。我们的入站推文流正好就是一个流。但是,现有它不能创建聚合,我们实际上是创建了一个表。一个表是在给定时间点的给定键的值的一个快照。 KSQL 聚合数据基于消息的事件时间,并且如果它更新了,通过简单的相关窗口重申去操作后面到达的数据。困惑了吗? 我希望没有,但是,让我们看一下,如果我们可以用这个例子去说明。 我们将申明我们的聚合作为一个真实的表:

ksql> CREATE TABLE user_tweet_count AS \
SELECT user_screenname, count(*) AS  tweet_count \
FROM twitter WINDOW TUMBLING (SIZE 1 HOUR) \
GROUP BY user_screenname ;

Message  
---------------------------  
Table created and running

看表中的列,这里除了我们要求的外,还有两个隐含列:

ksql> DESCRIBE user_tweet_count;

Field           | Type  
-----------------------------------  
ROWTIME         | BIGINT  
ROWKEY          | VARCHAR(STRING)  
USER_SCREENNAME | VARCHAR(STRING)  
TWEET_COUNT     | BIGINT  
ksql>

我们看一下这些是什么:

ksql> SELECT TIMESTAMPTOSTRING(ROWTIME, 'yyyy-MM-dd HH:mm:ss.SSS') , \
ROWKEY, USER_SCREENNAME, TWEET_COUNT \
FROM user_tweet_count \
WHERE USER_SCREENNAME= 'rmoff';  

2017-09-29 11:00:00.000 | rmoff : Window{start=1506708000000 end=-} | rmoff | 2  
2017-09-29 12:00:00.000 | rmoff : Window{start=1506711600000 end=-} | rmoff | 4  
2017-09-28 22:00:00.000 | rmoff : Window{start=1506661200000 end=-} | rmoff | 2  
2017-09-29 09:00:00.000 | rmoff : Window{start=1506700800000 end=-} | rmoff | 4  
2017-09-29 15:00:00.000 | rmoff : Window{start=1506722400000 end=-} | rmoff | 2  
2017-09-29 13:00:00.000 | rmoff : Window{start=1506715200000 end=-} | rmoff | 6

ROWTIME 是窗口开始时间, ROWKEYGROUP BYUSER_SCREENNAME)加上窗口的组合。因此,我们可以通过创建另外一个衍生的表来整理一下:

ksql> CREATE TABLE USER_TWEET_COUNT_DISPLAY AS \
SELECT TIMESTAMPTOSTRING(ROWTIME, 'yyyy-MM-dd HH:mm:ss.SSS') AS WINDOW_START ,\
USER_SCREENNAME, TWEET_COUNT \
FROM user_tweet_count;

Message  
---------------------------  
Table created and running

现在它更易于查询和查看我们感兴趣的数据:

ksql> SELECT WINDOW_START ,  USER_SCREENNAME, TWEET_COUNT \
FROM USER_TWEET_COUNT_DISPLAY WHERE TWEET_COUNT> 20;  

2017-09-29 12:00:00.000 | VikasAatOracle | 22  
2017-09-28 14:00:00.000 | Throne_ie | 50  
2017-09-28 14:00:00.000 | pikipiki_net | 22  
2017-09-29 09:00:00.000 | johanlouwers | 22  
2017-09-28 09:00:00.000 | yvrk1973 | 24  
2017-09-28 13:00:00.000 | cmosoares | 22  
2017-09-29 11:00:00.000 | ypoirier | 24  
2017-09-28 14:00:00.000 | pikisec | 22  
2017-09-29 07:00:00.000 | Throne_ie | 22  
2017-09-29 09:00:00.000 | ChrisVoyance | 24  
2017-09-28 11:00:00.000 | ChrisVoyance | 28

结论

所以我们有了它! 我们可以从 Kafka 中取得数据, 并且很容易使用 KSQL 去探索它。 而不仅是去浏览和转换数据,我们可以很容易地使用 KSQL 从流和表中建立流处理。

如果你对 KSQL 能够做什么感兴趣,去查看:

记住,KSQL 现在正处于开发者预览阶段。 欢迎在 KSQL 的 GitHub 仓库上提出任何问题, 或者去我们的 community Slack group 的 #KSQL 频道。


via: https://www.confluent.io/blog/using-ksql-to-analyse-query-and-transform-data-in-kafka

作者:Robin Moffatt 译者:qhwdw 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

有些时候我们想从 DQYDJ 网站的数据中分析点有用的东西出来,在过去,我们要用 R 语言提取固定宽度的数据,然后通过数学建模来分析美国的最低收入补贴,当然也包括其他优秀的方法。

今天我将向你展示对大数据的一点探索,不过有点变化,使用的是全世界最流行的微型电脑————树莓派,如果手头没有,那就看下一篇吧(可能是已经处理好的数据),对于其他用户,请继续阅读吧,今天我们要建立一个树莓派 Hadoop集群!

I. 为什么要建立一个树莓派的 Hadoop 集群?

由三个树莓派节点组成的 Hadoop 集群

我们对 DQYDJ 的数据做了大量的处理工作,但这些还不能称得上是大数据。

和许许多多有争议的话题一样,数据的大小之别被解释成这样一个笑话:

如果能被内存所存储,那么它就不是大数据。 ————佚名

似乎这儿有两种解决问题的方法:

  1. 我们可以找到一个足够大的数据集合,任何家用电脑的物理或虚拟内存都存不下。
  2. 我们可以买一些不用特别定制,我们现有数据就能淹没它的电脑:
    —— 上手树莓派 2B

这个由设计师和工程师制作出来的精致小玩意儿拥有 1GB 的内存, MicroSD 卡充当它的硬盘,此外,每一台的价格都低于 50 美元,这意味着你可以花不到 250 美元的价格搭建一个 Hadoop 集群。

或许天下没有比这更便宜的入场券来带你进入大数据的大门。

II. 制作一个树莓派集群

我最喜欢制作的原材料。

这里我将给出我原来为了制作树莓派集群购买原材料的链接,如果以后要在亚马逊购买的话你可先这些链接收藏起来,也是对本站的一点支持。(谢谢)

开始制作

  1. 首先,装好三个树莓派,每一个用螺丝钉固定在亚克力面板上。(看下图)
  2. 接下来,安装以太网交换机,用双面胶贴在其中一个在亚克力面板上。
  3. 用双面胶贴将 USB 转接器贴在一个在亚克力面板使之成为最顶层。
  4. 接着就是一层一层都拼好——这里我选择将树莓派放在交换机和USB转接器的底下(可以看看完整安装好的两张截图)

想办法把线路放在需要的地方——如果你和我一样购买力 USB 线和网线,我可以将它们卷起来放在亚克力板子的每一层

现在不要急着上电,需要将系统烧录到 SD 卡上才能继续。

烧录 Raspbian

按照这个教程将 Raspbian 烧录到三张 SD 卡上,我使用的是 Win7 下的 Win32DiskImager

将其中一张烧录好的 SD 卡插在你想作为主节点的树莓派上,连接 USB 线并启动它。

启动主节点

这里有一篇非常棒的“Because We Can Geek”的教程,讲如何安装 Hadoop 2.7.1,此处就不再熬述。

在启动过程中有一些要注意的地方,我将带着你一起设置直到最后一步,记住我现在使用的 IP 段为 192.168.1.50 – 192.168.1.52,主节点是 .50,从节点是 .51 和 .52,你的网络可能会有所不同,如果你想设置静态 IP 的话可以在评论区看看或讨论。

一旦你完成了这些步骤,接下来要做的就是启用交换文件,Spark on YARN 将分割出一块非常接近内存大小的交换文件,当你内存快用完时便会使用这个交换分区。

(如果你以前没有做过有关交换分区的操作的话,可以看看这篇教程,让 swappiness 保持较低水准,因为 MicroSD 卡的性能扛不住)

现在我准备介绍有关我的和“Because We Can Geek”关于启动设置一些微妙的区别。

对于初学者,确保你给你的树莓派起了一个正式的名字——在 /etc/hostname 设置,我的主节点设置为 ‘RaspberryPiHadoopMaster’ ,从节点设置为 ‘RaspberryPiHadoopSlave#’

主节点的 /etc/hosts 配置如下:

#/etc/hosts
127.0.0.1       localhost
::1             localhost ip6-localhost ip6-loopback
ff02::1         ip6-allnodes
ff02::2         ip6-allrouters

192.168.1.50    RaspberryPiHadoopMaster
192.168.1.51    RaspberryPiHadoopSlave1
192.168.1.52    RaspberryPiHadoopSlave2

如果你想让 Hadoop、YARN 和 Spark 运行正常的话,你也需要修改这些配置文件(不妨现在就编辑)。

这是 hdfs-site.xml

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>  
  <name>fs.default.name</name>
  <value>hdfs://RaspberryPiHadoopMaster:54310</value>
</property>  
<property>  
  <name>hadoop.tmp.dir</name>
  <value>/hdfs/tmp</value>
</property>  
</configuration>

这是 yarn-site.xml (注意内存方面的改变):

<?xml version="1.0"?>
<configuration>

<!-- Site specific YARN configuration properties -->
  <property>
    <name>yarn.nodemanager.aux-services</name>
    <value>mapreduce_shuffle</value>
  </property>
  <property>
    <name>yarn.nodemanager.resource.cpu-vcores</name>
    <value>4</value>
  </property>
  <property>
    <name>yarn.nodemanager.resource.memory-mb</name>
    <value>1024</value>
  </property>
  <property>
    <name>yarn.scheduler.minimum-allocation-mb</name>
    <value>128</value>
  </property>
  <property>
    <name>yarn.scheduler.maximum-allocation-mb</name>
    <value>1024</value>
  </property>
  <property>
    <name>yarn.scheduler.minimum-allocation-vcores</name>
    <value>1</value>
  </property>
  <property>
    <name>yarn.scheduler.maximum-allocation-vcores</name>
    <value>4</value>
  </property>
<property>
   <name>yarn.nodemanager.vmem-check-enabled</name>
   <value>false</value>
   <description>Whether virtual memory limits will be enforced for containers</description>
</property>
<property>
   <name>yarn.nodemanager.vmem-pmem-ratio</name>
   <value>4</value>
   <description>Ratio between virtual memory to physical memory when setting memory limits for containers</description>
</property>
<property>  
<name>yarn.resourcemanager.resource-tracker.address</name>  
<value>RaspberryPiHadoopMaster:8025</value>  
</property>  
<property>  
<name>yarn.resourcemanager.scheduler.address</name>  
<value>RaspberryPiHadoopMaster:8030</value>  
</property>  
<property>  
<name>yarn.resourcemanager.address</name>  
<value>RaspberryPiHadoopMaster:8040</value>  
</property> 
</configuration>

slaves

RaspberryPiHadoopMaster
RaspberryPiHadoopSlave1
RaspberryPiHadoopSlave2

core-site.xml

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>  
  <name>fs.default.name</name>
  <value>hdfs://RaspberryPiHadoopMaster:54310</value>
</property>  
<property>  
  <name>hadoop.tmp.dir</name>
  <value>/hdfs/tmp</value>
</property>  
</configuration>

设置两个从节点:

接下来按照 “Because We Can Geek”上的教程,你需要对上面的文件作出小小的改动。 在 yarn-site.xml 中主节点没有改变,所以从节点中不必含有这个 slaves 文件。

III. 在我们的树莓派集群中测试 YARN

如果所有设备都正常工作,在主节点上你应该执行如下命令:

start-dfs.sh
start-yarn.sh

当设备启动后,以 Hadoop 用户执行,如果你遵循教程,用户应该是 hduser

接下来执行 hdfs dfsadmin -report 查看三个节点是否都正确启动,确认你看到一行粗体文字 ‘Live datanodes (3)’:

Configured Capacity: 93855559680 (87.41 GB)
Raspberry Pi Hadoop Cluster picture Straight On
Present Capacity: 65321992192 (60.84 GB)
DFS Remaining: 62206627840 (57.93 GB)
DFS Used: 3115364352 (2.90 GB)
DFS Used%: 4.77%
Under replicated blocks: 0
Blocks with corrupt replicas: 0
Missing blocks: 0
Missing blocks (with replication factor 1): 0
————————————————-
Live datanodes (3):
Name: 192.168.1.51:50010 (RaspberryPiHadoopSlave1)
Hostname: RaspberryPiHadoopSlave1
Decommission Status : Normal

你现在可以做一些简单的诸如 ‘Hello, World!’ 的测试,或者直接进行下一步。

IV. 安装 SPARK ON YARN

YARN 的意思是另一种非常好用的资源调度器(Yet Another Resource Negotiator),已经作为一个易用的资源管理器集成在 Hadoop 基础安装包中。

Apache Spark 是 Hadoop 生态圈中的另一款软件包,它是一个毁誉参半的执行引擎和捆绑的 MapReduce。在一般情况下,相对于基于磁盘存储的 MapReduce,Spark 更适合基于内存的存储,某些运行任务能够得到 10-100 倍提升——安装完成集群后你可以试试 Spark 和 MapReduce 有什么不同。

我个人对 Spark 还是留下非常深刻的印象,因为它提供了两种数据工程师和科学家都比较擅长的语言—— Python 和 R。

安装 Apache Spark 非常简单,在你家目录下,wget "为 Hadoop 2.7 构建的 Apache Spark”来自这个页面),然后运行 tar -xzf “tgz 文件”,最后把解压出来的文件移动至 /opt,并清除刚才下载的文件,以上这些就是安装步骤。

我又创建了只有两行的文件 spark-env.sh,其中包含 Spark 的配置文件目录。

SPARK_MASTER_IP=192.168.1.50
SPARK_WORKER_MEMORY=512m

(在 YARN 跑起来之前我不确定这些是否有必要。)

V. 你好,世界! 为 Apache Spark 寻找有趣的数据集!

在 Hadoop 世界里面的 ‘Hello, World!’ 就是做单词计数。

我决定让我们的作品做一些内省式……为什么不统计本站最常用的单词呢?也许统计一些关于本站的大数据会更有用。

如果你有一个正在运行的 WordPress 博客,可以通过简单的两步来导出和净化。

  1. 我使用 Export to Text 插件导出文章的内容到纯文本文件中
  2. 我使用一些压缩库编写了一个 Python 脚本来剔除 HTML
import bleach

# Change this next line to your 'import' filename, whatever you would like to strip
# HTML tags from.
ascii_string = open('dqydj_with_tags.txt', 'r').read()


new_string = bleach.clean(ascii_string, tags=[], attributes={}, styles=[], strip=True)
new_string = new_string.encode('utf-8').strip()

# Change this next line to your 'export' filename
f = open('dqydj_stripped.txt', 'w')
f.write(new_string)
f.close()

现在我们有了一个更小的、适合复制到树莓派所搭建的 HDFS 集群上的文件。

如果你不能树莓派主节点上完成上面的操作,找个办法将它传输上去(scp、 rsync 等等),然后用下列命令行复制到 HDFS 上。

hdfs dfs -copyFromLocal dqydj_stripped.txt /dqydj_stripped.txt

现在准备进行最后一步 - 向 Apache Spark 写入一些代码。

VI. 点亮 Apache Spark

Cloudera 有个极棒的程序可以作为我们的超级单词计数程序的基础,你可以在这里找到。我们接下来为我们的内省式单词计数程序修改它。

在主节点上安装‘stop-words’这个 python 第三方包,虽然有趣(我在 DQYDJ 上使用了 23,295 次 the 这个单词),你可能不想看到这些语法单词占据着单词计数的前列,另外,在下列代码用你自己的数据集替换所有有关指向 dqydj 文件的地方。

import sys

from stop_words import get_stop_words
from pyspark import SparkContext, SparkConf

if __name__ == "__main__":

  # create Spark context with Spark configuration
  conf = SparkConf().setAppName("Spark Count")
  sc = SparkContext(conf=conf)

  # get threshold
  try:
    threshold = int(sys.argv[2])
  except:
    threshold = 5

  # read in text file and split each document into words
  tokenized = sc.textFile(sys.argv[1]).flatMap(lambda line: line.split(" "))

  # count the occurrence of each word
  wordCounts = tokenized.map(lambda word: (word.lower().strip(), 1)).reduceByKey(lambda v1,v2:v1 +v2)

  # filter out words with fewer than threshold occurrences
  filtered = wordCounts.filter(lambda pair:pair[1] >= threshold)

  print "*" * 80
  print "Printing top words used"
  print "-" * 80
  filtered_sorted = sorted(filtered.collect(), key=lambda x: x[1], reverse = True)
  for (word, count) in filtered_sorted: print "%s : %d" % (word.encode('utf-8').strip(), count)


  # Remove stop words
  print "\n\n"
  print "*" * 80
  print "Printing top non-stop words used"
  print "-" * 80
  # Change this to your language code (see the stop-words documentation)
  stop_words = set(get_stop_words('en'))
  no_stop_words = filter(lambda x: x[0] not in stop_words, filtered_sorted)
  for (word, count) in no_stop_words: print "%s : %d" % (word.encode('utf-8').strip(), count)

保存好 wordCount.py,确保上面的路径都是正确无误的。

现在,准备念出咒语,让运行在 YARN 上的 Spark 跑起来,你可以看到我在 DQYDJ 使用最多的单词是哪一个。

/opt/spark-2.0.0-bin-hadoop2.7/bin/spark-submit –master yarn –executor-memory 512m –name wordcount –executor-cores 8 wordCount.py /dqydj_stripped.txt

VII. 我在 DQYDJ 使用最多的单词

可能入列的单词有哪一些呢?“can, will, it’s, one, even, like, people, money, don’t, also“.

嘿,不错,“money”悄悄挤进了前十。在一个致力于金融、投资和经济的网站上谈论这似乎是件好事,对吧?

下面是的前 50 个最常用的词汇,请用它们刻画出有关我的文章的水平的结论。

我希望你能喜欢这篇关于 Hadoop、YARN 和 Apache Spark 的教程,现在你可以在 Spark 运行和编写其他的应用了。

你的下一步是任务是开始阅读 pyspark 文档(以及用于其他语言的该库),去学习一些可用的功能。根据你的兴趣和你实际存储的数据,你将会深入学习到更多——有流数据、SQL,甚至机器学习的软件包!

你怎么看?你要建立一个树莓派 Hadoop 集群吗?想要在其中挖掘一些什么吗?你在上面看到最令你惊奇的单词是什么?为什么 'S&P' 也能上榜?

(题图:Pixabay,CC0)


via: https://dqydj.com/raspberry-pi-hadoop-cluster-apache-spark-yarn/

作者:PK 译者:popy32 校对:wxy

本文由 LCTT 组织编译,Linux中国 荣誉推出

Big Data Marriage

Big Data Marriage

这幅漫画是作者假借大数据来吐槽自己的老婆太唠叨了。

也是一个非常有意思的比喻,作为男性可能都有所体会,在没有结婚的时候,甚至是说,单身的时候,自己的生活过的清净而惬意。一旦你结了婚,你的妻子为了生活而忙碌,便开始关注生活中的点点滴滴,会给你说大量的话,传递大量的信息,这何尝不是一种“大数据”呢?

via: https://turnoff.us/geek/bigdata-marriage/

作者:Daniel Stori 译者&点评:Bestony 校对:wxy 合成:GHLandy

本文由 LCTT 原创编译,Linux中国 荣誉推出

这是这个系列发布的第三篇关于如何构建数据 科学作品集 Data Science Portfolio 的文章。如果你喜欢这个系列并且想继续关注,你可以在订阅页面的底部找到链接

数据科学公司在决定雇佣时越来越关注你在数据科学方面的 作品集 Portfolio 。这其中的一个原因是,这样的作品集是判断某人的实际技能的最好的方法。好消息是构建这样的作品集完全要看你自己。只要你在这方面付出了努力,你一定可以取得让这些公司钦佩的作品集。

构建高质量的作品集的第一步就是知道需要什么技能。公司想要在数据科学方面拥有的、他们希望你能够运用的主要技能有:

  • 沟通能力
  • 协作能力
  • 技术能力
  • 数据推理能力
  • 动机和主动性

任何好的作品集都由多个项目表现出来,其中每个都能够表现出以上一到两点。这是本系列的第三篇,本系列我们主要讲包括如何打造面面俱到的数据科学作品集。在这一篇中,我们主要涵盖了如何构建组成你的作品集的第二个项目,以及如何创建一个端对端的机器学习项目。在最后,我们将拥有一个展示你的数据推理能力和技术能力的项目。如果你想看一下的话,这里有一个完整的例子。

一个端到端的项目

作为一个数据科学家,有时候你会拿到一个数据集并被问如何用它来讲故事。在这个时候,沟通就是非常重要的,你需要用它来完成这个事情。像我们在前一篇文章中用过的,类似 Jupyter notebook 这样的工具,将对你非常有帮助。在这里你能找到一些可以用的报告或者总结文档。

不管怎样,有时候你会被要求创建一个具有操作价值的项目。具有操作价值的项目将直接影响到公司的日常业务,它会使用不止一次,经常是许多人使用。这个任务可能像这样 “创建一个算法来预测周转率”或者“创建一个模型来自动对我们的文章打标签”。在这种情况下,技术能力比讲故事更重要。你必须能够得到一个数据集,并且理解它,然后创建脚本处理该数据。这个脚本要运行的很快,占用系统资源很小。通常它可能要运行很多次,脚本的可使用性也很重要,并不仅仅是一个演示版。可使用性是指整合进操作流程,并且甚至是是面向用户的。

端对端项目的主要组成部分:

  • 理解背景
  • 浏览数据并找出细微差别
  • 创建结构化项目,那样比较容易整合进操作流程
  • 运行速度快、占用系统资源小的高性能代码
  • 写好安装和使用文档以便其他人用

为了有效的创建这种类型的项目,我们可能需要处理多个文件。强烈推荐使用 Atom 这样的文本编辑器或者 PyCharm 这样的 IDE。这些工具允许你在文件间跳转,编辑不同类型的文件,例如 markdown 文件,Python 文件,和 csv 文件等等。结构化你的项目还利于版本控制,并上传一个类似 Github 这样的协作开发工具上也很有用。

Github 上的这个项目

在这一节中我们将使用 Pandasscikit-learn 这样的库,我们还将大量用到 Pandas DataFrames,它使得 python 读取和处理表格数据更加方便。

找到好的数据集

为一个端到端的作品集项目的找到好的数据集很难。在内存和性能的限制下,数据集需要尽量的大。它还需要是实际有用的。例如,这个数据集,它包含有美国院校的录取标准、毕业率以及毕业以后的收入,是个很好的可以讲故事的数据集。但是,不管你如何看待这个数据,很显然它不适合创建端到端的项目。比如,你能告诉人们他们去了这些大学以后的未来收入,但是这个快速检索却并不足够呈现出你的技术能力。你还能找出院校的招生标准和更高的收入相关,但是这更像是常理而不是你的技术结论。

这里还有内存和性能约束的问题,比如你有几千兆的数据,而且当你需要找到一些差异时,就需要对数据集一遍遍运行算法。

一个好的可操作的数据集可以让你构建一系列脚本来转换数据、动态地回答问题。一个很好的例子是股票价格数据集,当股市关闭时,就会给算法提供新的数据。这可以让你预测明天的股价,甚至预测收益。这不是讲故事,它带来的是真金白银。

一些找到数据集的好地方:

  • /r/datasets – 有上百的有趣数据的 subreddit(Reddit 是国外一个社交新闻站点,subreddit 指该论坛下的各不同版块)。
  • Google Public Datasets – 通过 Google BigQuery 使用的公开数据集。
  • Awesome datasets – 一个数据集列表,放在 Github 上。

当你查看这些数据集时,想一下人们想要在这些数据集中得到什么答案,哪怕这些问题只想过一次(“房价是如何与标准普尔 500 指数关联的?”),或者更进一步(“你能预测股市吗?”)。这里的关键是更进一步地找出问题,并且用相同的代码在不同输入(不同的数据)上运行多次。

对于本文的目标,我们来看一下 房利美 Fannie Mae 贷款数据。房利美是一家在美国的政府赞助的企业抵押贷款公司,它从其他银行购买按揭贷款,然后捆绑这些贷款为贷款证券来转卖它们。这使得贷款机构可以提供更多的抵押贷款,在市场上创造更多的流动性。这在理论上会带来更多的住房和更好的贷款期限。从借款人的角度来说,它们大体上差不多,话虽这样说。

房利美发布了两种类型的数据 – 它获得的贷款的数据,和贷款偿还情况的数据。在理想的情况下,有人向贷款人借钱,然后还款直到还清。不管怎样,有些人多次不还,从而丧失了抵押品赎回权。抵押品赎回权是指没钱还了被银行把房子给收走了。房利美会追踪谁没还钱,并且哪个贷款需要收回抵押的房屋(取消赎回权)。每个季度会发布此数据,发布的是滞后一年的数据。当前可用是 2015 年第一季度数据。

“贷款数据”是由房利美发布的贷款发放的数据,它包含借款人的信息、信用评分,和他们的家庭贷款信息。“执行数据”,贷款发放后的每一个季度公布,包含借贷人的还款信息和是否丧失抵押品赎回权的状态,一个“贷款数据”的“执行数据”可能有十几行。可以这样理解,“贷款数据”告诉你房利美所控制的贷款,“执行数据”包含该贷款一系列的状态更新。其中一个状态更新可以告诉我们一笔贷款在某个季度被取消赎回权了。

一个没有及时还贷的房子就这样的被卖了

选择一个角度

这里有几个我们可以去分析房利美数据集的方向。我们可以:

  • 预测房屋的销售价格。
  • 预测借款人还款历史。
  • 在获得贷款时为每一笔贷款打分。

最重要的事情是坚持单一的角度。同时关注太多的事情很难做出效果。选择一个有着足够细节的角度也很重要。下面的角度就没有太多细节:

  • 找出哪些银行将贷款出售给房利美的多数被取消赎回权。
  • 计算贷款人的信用评分趋势。
  • 找到哪些类型的家庭没有偿还贷款的能力。
  • 找到贷款金额和抵押品价格之间的关系。

上面的想法非常有趣,如果我们关注于讲故事,那是一个不错的角度,但是不是很适合一个操作性项目。

在房利美数据集中,我们将仅使用申请贷款时有的那些信息来预测贷款是否将来会被取消赎回权。实际上, 我们将为每一笔贷款建立“分数”来告诉房利美买还是不买。这将给我们打下良好的基础,并将组成这个漂亮的作品集的一部分。

理解数据

我们来简单看一下原始数据文件。下面是 2012 年 1 季度前几行的贷款数据:

100000853384|R|OTHER|4.625|280000|360|02/2012|04/2012|31|31|1|23|801|N|C|SF|1|I|CA|945||FRM|
100003735682|R|SUNTRUST MORTGAGE INC.|3.99|466000|360|01/2012|03/2012|80|80|2|30|794|N|P|SF|1|P|MD|208||FRM|788
100006367485|C|PHH MORTGAGE CORPORATION|4|229000|360|02/2012|04/2012|67|67|2|36|802|N|R|SF|1|P|CA|959||FRM|794

下面是 2012 年 1 季度的前几行执行数据:

100000853384|03/01/2012|OTHER|4.625||0|360|359|03/2042|41860|0|N||||||||||||||||
100000853384|04/01/2012||4.625||1|359|358|03/2042|41860|0|N||||||||||||||||
100000853384|05/01/2012||4.625||2|358|357|03/2042|41860|0|N||||||||||||||||

在开始编码之前,花些时间真正理解数据是值得的。这对于操作性项目优为重要,因为我们没有交互式探索数据,将很难察觉到细微的差别,除非我们在前期发现他们。在这种情况下,第一个步骤是阅读房利美站点的资料:

在看完这些文件后后,我们了解到一些能帮助我们的关键点:

  • 从 2000 年到现在,每季度都有一个贷款和执行文件,因数据是滞后一年的,所以到目前为止最新数据是 2015 年的。
  • 这些文件是文本格式的,采用管道符号|进行分割。
  • 这些文件是没有表头的,但我们有个文件列明了各列的名称。
  • 所有一起,文件包含 2200 万个贷款的数据。
  • 由于执行数据的文件包含过去几年获得的贷款的信息,在早些年获得的贷款将有更多的执行数据(即在 2014 获得的贷款没有多少历史执行数据)。

这些小小的信息将会为我们节省很多时间,因为这样我们就知道如何构造我们的项目和利用这些数据了。

构造项目

在我们开始下载和探索数据之前,先想一想将如何构造项目是很重要的。当建立端到端项目时,我们的主要目标是:

  • 创建一个可行解决方案
  • 有一个快速运行且占用最小资源的解决方案
  • 容易可扩展
  • 写容易理解的代码
  • 写尽量少的代码

为了实现这些目标,需要对我们的项目进行良好的构造。一个结构良好的项目遵循几个原则:

  • 分离数据文件和代码文件
  • 从原始数据中分离生成的数据。
  • 有一个 README.md 文件帮助人们安装和使用该项目。
  • 有一个 requirements.txt 文件列明项目运行所需的所有包。
  • 有一个单独的 settings.py 文件列明其它文件中使用的所有的设置

    • 例如,如果从多个 Python 脚本读取同一个文件,让它们全部 import 设置并从一个集中的地方获得文件名是有用的。
  • 有一个 .gitignore 文件,防止大的或密码文件被提交。
  • 分解任务中每一步可以单独执行的步骤到单独的文件中。

    • 例如,我们将有一个文件用于读取数据,一个用于创建特征,一个用于做出预测。
  • 保存中间结果,例如,一个脚本可以输出下一个脚本可读取的文件。

    • 这使我们无需重新计算就可以在数据处理流程中进行更改。

我们的文件结构大体如下:

loan-prediction
├── data
├── processed
├── .gitignore
├── README.md
├── requirements.txt
├── settings.py

创建初始文件

首先,我们需要创建一个 loan-prediction 文件夹,在此文件夹下面,再创建一个 data 文件夹和一个 processed 文件夹。data 文件夹存放原始数据,processed 文件夹存放所有的中间计算结果。

其次,创建 .gitignore 文件,.gitignore 文件将保证某些文件被 git 忽略而不会被推送至 GitHub。关于这个文件的一个好的例子是由 OSX 在每一个文件夹都会创建的 .DS_Store 文件,.gitignore 文件一个很好的范本在这里。我们还想忽略数据文件,因为它们实在是太大了,同时房利美的条文禁止我们重新分发该数据文件,所以我们应该在我们的文件后面添加以下 2 行:

data
processed

这里是该项目的一个关于 .gitignore 文件的例子。

再次,我们需要创建 README.md 文件,它将帮助人们理解该项目。后缀 .md 表示这个文件采用 markdown 格式。Markdown 使你能够写纯文本文件,同时还可以添加你想要的神奇的格式。这里是关于 markdown 的导引。如果你上传一个叫 README.md 的文件至 Github,Github 会自动处理该 markdown,同时展示给浏览该项目的人。例子在这里

至此,我们仅需在 README.md 文件中添加简单的描述:

Loan Prediction
-----------------------

Predict whether or not loans acquired by Fannie Mae will go into foreclosure.  Fannie Mae acquires loans from other lenders as a way of inducing them to lend more.  Fannie Mae releases data on the loans it has acquired and their performance afterwards [here](http://www.fanniemae.com/portal/funding-the-market/data/loan-performance-data.html).

现在,我们可以创建 requirements.txt 文件了。这会帮助其它人可以很方便地安装我们的项目。我们还不知道我们将会具体用到哪些库,但是以下几个库是需要的:

pandas
matplotlib
scikit-learn
numpy
ipython
scipy

以上几个是在 python 数据分析任务中最常用到的库。可以认为我们将会用到大部分这些库。这里是该项目 requirements.txt 文件的一个例子。

创建 requirements.txt 文件之后,你应该安装这些包了。我们将会使用 python3。如果你没有安装 python,你应该考虑使用 Anaconda,它是一个 python 安装程序,同时安装了上面列出的所有包。

最后,我们可以建立一个空白的 settings.py 文件,因为我们的项目还没有任何设置。

获取数据

一旦我们有了项目的基本架构,我们就可以去获得原始数据。

房利美对获取数据有一些限制,所以你需要去注册一个账户。在创建完账户之后,你可以找到在这里的下载页面,你可以按照你所需要的下载或多或少的贷款数据文件。文件格式是 zip,在解压后当然是非常大的。

为了达到我们这个文章的目的,我们将要下载从 2012 年 1 季度到 2015 年 1 季度的所有数据。接着我们需要解压所有的文件。解压过后,删掉原来的 .zip 格式的文件。最后,loan-prediction 文件夹看起来应该像下面的一样:

loan-prediction
├── data
│   ├── Acquisition_2012Q1.txt
│   ├── Acquisition_2012Q2.txt
│   ├── Performance_2012Q1.txt
│   ├── Performance_2012Q2.txt
│   └── ...
├── processed
├── .gitignore
├── README.md
├── requirements.txt
├── settings.py

在下载完数据后,你可以在 shell 命令行中使用 headtail 命令去查看文件中的行数据,你看到任何的不需要的数据列了吗?在做这件事的同时查阅列名称的 pdf 文件可能有帮助。

读入数据

有两个问题让我们的数据难以现在就使用:

  • 贷款数据和执行数据被分割在多个文件中
  • 每个文件都缺少列名标题

在我们开始使用数据之前,我们需要首先明白我们要在哪里去存一个贷款数据的文件,同时到哪里去存储一个执行数据的文件。每个文件仅仅需要包括我们关注的那些数据列,同时拥有正确的列名标题。这里有一个小问题是执行数据非常大,因此我们需要尝试去修剪一些数据列。

第一步是向 settings.py 文件中增加一些变量,这个文件中同时也包括了我们原始数据的存放路径和处理出的数据存放路径。我们同时也将添加其他一些可能在接下来会用到的设置数据:

DATA_DIR = "data"
PROCESSED_DIR = "processed"
MINIMUM_TRACKING_QUARTERS = 4
TARGET = "foreclosure_status"
NON_PREDICTORS = [TARGET, "id"]
CV_FOLDS = 3

把路径设置在 settings.py 中使它们放在一个集中的地方,同时使其修改更加的容易。当在多个文件中用到相同的变量时,你想改变它的话,把他们放在一个地方比分散放在每一个文件时更加容易。这里的是一个这个工程的示例 settings.py 文件

第二步是创建一个文件名为 assemble.py,它将所有的数据分为 2 个文件。当我们运行 Python assemble.py,我们在处理数据文件的目录会获得 2 个数据文件。

接下来我们开始写 assemble.py 文件中的代码。首先我们需要为每个文件定义相应的列名标题,因此我们需要查看列名称的 pdf 文件,同时创建在每一个贷款数据和执行数据的文件的数据列的列表:

HEADERS = {
    "Acquisition": [
        "id",
        "channel",
        "seller",
        "interest_rate",
        "balance",
        "loan_term",
        "origination_date",
        "first_payment_date",
        "ltv",
        "cltv",
        "borrower_count",
        "dti",
        "borrower_credit_score",
        "first_time_homebuyer",
        "loan_purpose",
        "property_type",
        "unit_count",
        "occupancy_status",
        "property_state",
        "zip",
        "insurance_percentage",
        "product_type",
        "co_borrower_credit_score"
    ],
    "Performance": [
        "id",
        "reporting_period",
        "servicer_name",
        "interest_rate",
        "balance",
        "loan_age",
        "months_to_maturity",
        "maturity_date",
        "msa",
        "delinquency_status",
        "modification_flag",
        "zero_balance_code",
        "zero_balance_date",
        "last_paid_installment_date",
        "foreclosure_date",
        "disposition_date",
        "foreclosure_costs",
        "property_repair_costs",
        "recovery_costs",
        "misc_costs",
        "tax_costs",
        "sale_proceeds",
        "credit_enhancement_proceeds",
        "repurchase_proceeds",
        "other_foreclosure_proceeds",
        "non_interest_bearing_balance",
        "principal_forgiveness_balance"
    ]
}

接下来一步是定义我们想要保留的数据列。因为我们要预测一个贷款是否会被撤回,我们可以丢弃执行数据中的许多列。我们将需要保留贷款数据中的所有数据列,因为我们需要尽量多的了解贷款发放时的信息(毕竟我们是在预测贷款发放时这笔贷款将来是否会被撤回)。丢弃数据列将会使我们节省下内存和硬盘空间,同时也会加速我们的代码。

SELECT = {
    "Acquisition": HEADERS["Acquisition"],
    "Performance": [
        "id",
        "foreclosure_date"
    ]
}

下一步,我们将编写一个函数来连接数据集。下面的代码将:

  • 引用一些需要的库,包括 settings
  • 定义一个函数 concatenate,目的是:

    • 获取到所有 data 目录中的文件名。
    • 遍历每个文件。

      • 如果文件不是正确的格式 (不是以我们需要的格式作为开头),我们将忽略它。
      • 通过使用 Pandas 的 read\_csv 函数及正确的设置把文件读入一个 DataFrame

        • 设置分隔符为,以便所有的字段能被正确读出。
        • 数据没有标题行,因此设置 headerNone 来进行标示。
        • HEADERS 字典中设置正确的标题名称 – 这将会是我们的 DataFrame 中的数据列名称。
        • 仅选择我们加在 SELECT 中的 DataFrame 的列。
  • 把所有的 DataFrame 共同连接在一起。
  • 把已经连接好的 DataFrame 写回一个文件。
import os
import settings
import pandas as pd

def concatenate(prefix="Acquisition"):
    files = os.listdir(settings.DATA_DIR)
    full = []
    for f in files:
        if not f.startswith(prefix):
            continue

        data = pd.read_csv(os.path.join(settings.DATA_DIR, f), sep="|", header=None, names=HEADERS[prefix], index_col=False)
        data = data[SELECT[prefix]]
        full.append(data)

    full = pd.concat(full, axis=0)

    full.to_csv(os.path.join(settings.PROCESSED_DIR, "{}.txt".format(prefix)), sep="|", header=SELECT[prefix], index=False)

我们可以通过调用上面的函数,通过传递的参数 AcquisitionPerformance 两次以将所有的贷款和执行文件连接在一起。下面的代码将:

  • 仅在命令行中运行 python assemble.py 时执行。
  • 将所有的数据连接在一起,并且产生 2 个文件:

    • processed/Acquisition.txt
    • processed/Performance.txt
if __name__ == "__main__":
    concatenate("Acquisition")
    concatenate("Performance")

我们现在拥有了一个漂亮的,划分过的 assemble.py 文件,它很容易执行,也容易建立。通过像这样把问题分解为一块一块的,我们构建工程就会变的容易许多。不用一个可以做所有工作的凌乱脚本,我们定义的数据将会在多个脚本间传递,同时使脚本间完全的彼此隔离。当你正在一个大的项目中工作时,这样做是一个好的想法,因为这样可以更加容易修改其中的某一部分而不会引起其他项目中不关联部分产生预料之外的结果。

一旦我们完成 assemble.py 脚本文件,我们可以运行 python assemble.py 命令。你可以在这里查看完整的 assemble.py 文件。

这将会在 processed 目录下产生 2 个文件:

loan-prediction
├── data
│   ├── Acquisition_2012Q1.txt
│   ├── Acquisition_2012Q2.txt
│   ├── Performance_2012Q1.txt
│   ├── Performance_2012Q2.txt
│   └── ...
├── processed
│   ├── Acquisition.txt
│   ├── Performance.txt
├── .gitignore
├── assemble.py
├── README.md
├── requirements.txt
├── settings.py

计算来自执行数据的值

接下来我们会计算来自 processed/Performance.txt 中的值。我们要做的就是推测这些资产是否被取消赎回权。如果能够计算出来,我们只要看一下关联到贷款的执行数据的参数 foreclosure_date 就可以了。如果这个参数的值是 None,那么这些资产肯定没有收回。为了避免我们的样例中只有少量的执行数据,我们会为每个贷款计算出执行数据文件中的行数。这样我们就能够从我们的训练数据中筛选出贷款数据,排除了一些执行数据。

下面是我认为贷款数据和执行数据的关系:

在上面的表格中,贷款数据中的每一行数据都关联到执行数据中的多行数据。在执行数据中,在取消赎回权的时候 foreclosure_date 就会出现在该季度,而之前它是空的。一些贷款还没有被取消赎回权,所以与执行数据中的贷款数据有关的行在 foreclosure_date 列都是空格。

我们需要计算 foreclosure_status 的值,它的值是布尔类型,可以表示一个特殊的贷款数据 id 是否被取消赎回权过,还有一个参数 performance_count ,它记录了执行数据中每个贷款 id 出现的行数。 

计算这些行数有多种不同的方法:

  • 我们能够读取所有的执行数据,然后我们用 Pandas 的 groupby 方法在 DataFrame 中计算出与每个贷款 id 有关的行的行数,然后就可以查看贷款 idforeclosure_date 值是否为 None

    • 这种方法的优点是从语法上来说容易执行。
    • 它的缺点需要读取所有的 129236094 行数据,这样就会占用大量内存,并且运行起来极慢。
  • 我们可以读取所有的执行数据,然后在贷款 DataFrame 上使用 apply 去计算每个贷款 id 出现的次数。

    • 这种方法的优点是容易理解。
    • 缺点是需要读取所有的 129236094 行数据。这样会占用大量内存,并且运行起来极慢。
  • 我们可以在迭代访问执行数据中的每一行数据,而且会建立一个单独的计数字典。

    • 这种方法的优点是数据不需要被加载到内存中,所以运行起来会很快且不需要占用内存。
    • 缺点是这样的话理解和执行上可能有点耗费时间,我们需要对每一行数据进行语法分析。

加载所有的数据会非常耗费内存,所以我们采用第三种方法。我们要做的就是迭代执行数据中的每一行数据,然后为每一个贷款 id 在字典中保留一个计数。在这个字典中,我们会计算出贷款 id 在执行数据中出现的次数,而且看看 foreclosure_date 是否是 None 。我们可以查看 foreclosure_statusperformance_count 的值 。

我们会新建一个 annotate.py 文件,文件中的代码可以计算这些值。我们会使用下面的代码:

  • 导入需要的库
  • 定义一个函数 count_performance_rows

    • 打开 processed/Performance.txt 文件。这不是在内存中读取文件而是打开了一个文件标识符,这个标识符可以用来以行为单位读取文件。
    • 迭代文件的每一行数据。
    • 使用分隔符|分开每行的不同数据。
    • 检查 loan_id 是否在计数字典中。

      • 如果不存在,把它加进去。
    • loan_idperformance_count 参数自增 1 次,因为我们这次迭代也包含其中。
    • 如果 date 不是 None ,我们就会知道贷款被取消赎回权了,然后为foreclosure\_status` 设置合适的值。
import os
import settings
import pandas as pd

def count_performance_rows():
    counts = {}
    with open(os.path.join(settings.PROCESSED_DIR, "Performance.txt"), 'r') as f:
        for i, line in enumerate(f):
            if i == 0:
                # Skip header row
                continue
            loan_id, date = line.split("|")
            loan_id = int(loan_id)
            if loan_id not in counts:
                counts[loan_id] = {
                    "foreclosure_status": False,
                    "performance_count": 0
                }
            counts[loan_id]["performance_count"] += 1
            if len(date.strip()) > 0:
                counts[loan_id]["foreclosure_status"] = True
    return counts

获取值

只要我们创建了计数字典,我们就可以使用一个函数通过一个 loan_id 和一个 key 从字典中提取到需要的参数的值:

def get_performance_summary_value(loan_id, key, counts):
    value = counts.get(loan_id, {
        "foreclosure_status": False,
        "performance_count": 0
    })
    return value[key]

上面的函数会从 counts 字典中返回合适的值,我们也能够为贷款数据中的每一行赋一个 foreclosure_status 值和一个 performance_count 值。如果键不存在,字典的 get 方法会返回一个默认值,所以在字典中不存在键的时候我们就可以得到一个可知的默认值。

转换数据

我们已经在 annotate.py 中添加了一些功能,现在我们来看一看数据文件。我们需要将贷款到的数据转换到训练数据集来进行机器学习算法的训练。这涉及到以下几件事情:

  • 转换所有列为数字。
  • 填充缺失值。
  • 为每一行分配 performance_countforeclosure_status
  • 移除出现执行数据很少的行(performance_count 计数低)。

我们有几个列是文本类型的,看起来对于机器学习算法来说并不是很有用。然而,它们实际上是分类变量,其中有很多不同的类别代码,例如 RS 等等. 我们可以把这些类别标签转换为数值:

通过这种方法转换的列我们可以应用到机器学习算法中。

还有一些包含日期的列 (first_payment_dateorigination_date)。我们可以将这些日期放到两个列中:

在下面的代码中,我们将转换贷款数据。我们将定义一个函数如下:

  • acquisition 中创建 foreclosure_status 列,并从 counts 字典中得到值。
  • acquisition 中创建 performance_count 列,并从 counts 字典中得到值。
  • 将下面的列从字符串转换为整数:

    • channel
    • seller
    • first_time_homebuyer
    • loan_purpose
    • property_type
    • occupancy_status
    • property_state
    • product_type
  • first_payment_dateorigination_date 分别转换为两列:

    • 通过斜杠分离列。
    • 将第一部分分离成 month 列。
    • 将第二部分分离成 year 列。
    • 删除该列。
    • 最后,我们得到 first_payment_monthfirst_payment_yearrigination_monthorigination_year
  • 所有缺失值填充为 -1
def annotate(acquisition, counts):
    acquisition["foreclosure_status"] = acquisition["id"].apply(lambda x: get_performance_summary_value(x, "foreclosure_status", counts))
    acquisition["performance_count"] = acquisition["id"].apply(lambda x: get_performance_summary_value(x, "performance_count", counts))
    for column in [
        "channel",
        "seller",
        "first_time_homebuyer",
        "loan_purpose",
        "property_type",
        "occupancy_status",
        "property_state",
        "product_type"
    ]:
        acquisition[column] = acquisition[column].astype('category').cat.codes

    for start in ["first_payment", "origination"]:
        column = "{}_date".format(start)
        acquisition["{}_year".format(start)] = pd.to_numeric(acquisition[column].str.split('/').str.get(1))
        acquisition["{}_month".format(start)] = pd.to_numeric(acquisition[column].str.split('/').str.get(0))
        del acquisition[column]

    acquisition = acquisition.fillna(-1)
    acquisition = acquisition[acquisition["performance_count"] > settings.MINIMUM_TRACKING_QUARTERS]
    return acquisition

聚合到一起

我们差不多准备就绪了,我们只需要再在 annotate.py 添加一点点代码。在下面代码中,我们将:

  • 定义一个函数来读取贷款的数据。
  • 定义一个函数来写入处理过的数据到 processed/train.csv
  • 如果该文件在命令行以 python annotate.py 的方式运行:

    • 读取贷款数据。
    • 计算执行数据的计数,并将其赋予 counts
    • 转换 acquisition DataFrame。
    • acquisition DataFrame 写入到 train.csv
def read():
    acquisition = pd.read_csv(os.path.join(settings.PROCESSED_DIR, "Acquisition.txt"), sep="|")
    return acquisition

def write(acquisition):
    acquisition.to_csv(os.path.join(settings.PROCESSED_DIR, "train.csv"), index=False)

if __name__ == "__main__":
    acquisition = read()
    counts = count_performance_rows()
    acquisition = annotate(acquisition, counts)
    write(acquisition)

修改完成以后,确保运行 python annotate.py 来生成 train.csv 文件。 你可以在这里找到完整的 annotate.py 文件。

现在文件夹看起来应该像这样:

loan-prediction
├── data
│   ├── Acquisition_2012Q1.txt
│   ├── Acquisition_2012Q2.txt
│   ├── Performance_2012Q1.txt
│   ├── Performance_2012Q2.txt
│   └── ...
├── processed
│   ├── Acquisition.txt
│   ├── Performance.txt
│   ├── train.csv
├── .gitignore
├── annotate.py
├── assemble.py
├── README.md
├── requirements.txt
├── settings.py

找到误差标准

我们已经完成了训练数据表的生成,现在我们需要最后一步,生成预测。我们需要找到误差的标准,以及该如何评估我们的数据。在这种情况下,因为有很多的贷款没有被取消赎回权,所以根本不可能做到精确的计算。

我们需要读取训练数据,并且计算 foreclosure_status 列的计数,我们将得到如下信息:

import pandas as pd
import settings

train = pd.read_csv(os.path.join(settings.PROCESSED_DIR, "train.csv"))
train["foreclosure_status"].value_counts()
False    4635982
True        1585
Name: foreclosure_status, dtype: int64

因为只有很少的贷款被取消赎回权,只需要检查正确预测的标签的百分比就意味着我们可以创建一个机器学习模型,来为每一行预测 False,并能取得很高的精确度。相反,我们想要使用一个度量来考虑分类的不平衡,确保我们可以准确预测。我们要避免太多的误报率(预测贷款被取消赎回权,但是实际没有),也要避免太多的漏报率(预测贷款没有别取消赎回权,但是实际被取消了)。对于这两个来说,漏报率对于房利美来说成本更高,因为他们买的贷款可能是他们无法收回投资的贷款。

所以我们将定义一个漏报率,就是模型预测没有取消赎回权但是实际上取消了,这个数除以总的取消赎回权数。这是“缺失的”实际取消赎回权百分比的模型。下面看这个图表:

通过上面的图表,有 1 个贷款预测不会取消赎回权,但是实际上取消了。如果我们将这个数除以实际取消赎回权的总数 2,我们将得到漏报率 50%。 我们将使用这个误差标准,因此我们可以评估一下模型的行为。

设置机器学习分类器

我们使用交叉验证预测。通过交叉验证法,我们将数据分为3组。按照下面的方法来做:

  • 用组 1 和组 2 训练模型,然后用该模型来预测组 3
  • 用组 1 和组 3 训练模型,然后用该模型来预测组 2
  • 用组 2 和组 3 训练模型,然后用该模型来预测组 1

将它们分割到不同的组,这意味着我们永远不会用相同的数据来为其预测训练模型。这样就避免了过拟合。如果过拟合,我们将错误地拉低了漏报率,这使得我们难以改进算法或者应用到现实生活中。

Scikit-learn 有一个叫做 crossvalpredict ,它可以帮助我们理解交叉算法.

我们还需要一种算法来帮我们预测。我们还需要一个分类器来做二元分类。目标变量 foreclosure_status 只有两个值, TrueFalse

这里我们用 逻辑回归算法,因为它能很好的进行二元分类,并且运行很快,占用内存很小。我们来说一下它是如何工作的:不使用像随机森林一样多树结构,也不像支持向量机一样做复杂的转换,逻辑回归算法涉及更少的步骤和更少的矩阵。

我们可以使用 scikit-learn 实现的逻辑回归分类器算法。我们唯一需要注意的是每个类的权重。如果我们使用等权重的类,算法将会预测每行都为 false,因为它总是试图最小化误差。不管怎样,我们重视有多少贷款要被取消赎回权而不是有多少不能被取消。因此,我们给逻辑回归类的 class_weight 关键字传递 balanced 参数,让算法可以为不同 counts 的每个类考虑不同的取消赎回权的权重。这将使我们的算法不会为每一行都预测 false,而是两个类的误差水平一致。

做出预测

既然完成了前期准备,我们可以开始准备做出预测了。我将创建一个名为 predict.py 的新文件,它会使用我们在最后一步创建的 train.csv 文件。下面的代码:

  • 导入所需的库
  • 创建一个名为 cross_validate 的函数:

    • 使用正确的关键词参数创建逻辑回归分类器
    • 创建用于训练模型的数据列的列表,移除 idforeclosure_status
    • 交叉验证 train DataFrame
    • 返回预测结果
import os
import settings
import pandas as pd
from sklearn import cross_validation
from sklearn.linear_model import LogisticRegression
from sklearn import metrics

def cross_validate(train):
    clf = LogisticRegression(random_state=1, class_weight="balanced")

    predictors = train.columns.tolist()
    predictors = [p for p in predictors if p not in settings.NON_PREDICTORS]

    predictions = cross_validation.cross_val_predict(clf, train[predictors], train[settings.TARGET], cv=settings.CV_FOLDS)
    return predictions

预测误差

现在,我们仅仅需要写一些函数来计算误差。下面的代码:

  • 创建函数 compute_error

    • 使用 scikit-learn 计算一个简单的精确分数(与实际 foreclosure_status 值匹配的预测百分比)
  • 创建函数 compute_false_negatives

    • 为了方便,将目标和预测结果合并到一个 DataFrame
    • 查找漏报率

      • 找到原本应被预测模型取消赎回权,但实际没有取消的贷款数目
      • 除以没被取消赎回权的贷款总数目
def compute_error(target, predictions):
    return metrics.accuracy_score(target, predictions)

def compute_false_negatives(target, predictions):
    df = pd.DataFrame({"target": target, "predictions": predictions})
    return df[(df["target"] == 1) & (df["predictions"] == 0)].shape[0] / (df[(df["target"] == 1)].shape[0] + 1)

def compute_false_positives(target, predictions):
    df = pd.DataFrame({"target": target, "predictions": predictions})
    return df[(df["target"] == 0) & (df["predictions"] == 1)].shape[0] / (df[(df["target"] == 0)].shape[0] + 1)

聚合到一起

现在,我们可以把函数都放在 predict.py。下面的代码:

  • 读取数据集
  • 计算交叉验证预测
  • 计算上面的 3 个误差
  • 打印误差
def read():
    train = pd.read_csv(os.path.join(settings.PROCESSED_DIR, "train.csv"))
    return train

if __name__ == "__main__":
    train = read()
    predictions = cross_validate(train)
    error = compute_error(train[settings.TARGET], predictions)
    fn = compute_false_negatives(train[settings.TARGET], predictions)
    fp = compute_false_positives(train[settings.TARGET], predictions)
    print("Accuracy Score: {}".format(error))
    print("False Negatives: {}".format(fn))
    print("False Positives: {}".format(fp))

一旦你添加完代码,你可以运行 python predict.py 来产生预测结果。运行结果向我们展示漏报率为 .26,这意味着我们没能预测 26% 的取消贷款。这是一个好的开始,但仍有很多改善的地方!

你可以在这里找到完整的 predict.py 文件。

你的文件树现在看起来像下面这样:

loan-prediction
├── data
│   ├── Acquisition_2012Q1.txt
│   ├── Acquisition_2012Q2.txt
│   ├── Performance_2012Q1.txt
│   ├── Performance_2012Q2.txt
│   └── ...
├── processed
│   ├── Acquisition.txt
│   ├── Performance.txt
│   ├── train.csv
├── .gitignore
├── annotate.py
├── assemble.py
├── predict.py
├── README.md
├── requirements.txt
├── settings.py

撰写 README

既然我们完成了端到端的项目,那么我们可以撰写 README.md 文件了,这样其他人便可以知道我们做的事,以及如何复制它。一个项目典型的 README.md 应该包括这些部分:

  • 一个高水准的项目概览,并介绍项目目的
  • 任何必需的数据和材料的下载地址
  • 安装命令

    • 如何安装要求依赖
  • 使用命令

    • 如何运行项目
    • 每一步之后会看到的结果
  • 如何为这个项目作贡献

    • 扩展项目的下一步计划

这里 是这个项目的一个 README.md 样例。

下一步

恭喜你完成了端到端的机器学习项目!你可以在这里找到一个完整的示例项目。一旦你完成了项目,把它上传到 Github 是一个不错的主意,这样其他人也可以看到你的文件夹的部分项目。

这里仍有一些留待探索数据的角度。总的来说,我们可以把它们分割为 3 类: 扩展这个项目并使它更加精确,发现其他可以预测的列,并探索数据。这是其中一些想法:

  • annotate.py 中生成更多的特性
  • 切换 predict.py 中的算法
  • 尝试使用比我们发表在这里的更多的房利美数据
  • 添加对未来数据进行预测的方法。如果我们添加更多数据,我们所写的代码仍然可以起作用,这样我们可以添加更多过去和未来的数据。
  • 尝试看看是否你能预测一个银行原本是否应该发放贷款(相对地,房利美是否应该获得贷款)

    • 移除 train 中银行在发放贷款时间的不知道的任何列

      • 当房利美购买贷款时,一些列是已知的,但之前是不知道的
    • 做出预测
  • 探索是否你可以预测除了 foreclosure_status 的其他列

    • 你可以预测在销售时资产值是多少?
  • 探索探索执行数据更新之间的细微差别

    • 你能否预测借款人会逾期还款多少次?
    • 你能否标出的典型贷款周期?
  • 将数据按州或邮政编码标出

    • 你看到一些有趣的模式了吗?

如果你建立了任何有趣的东西,请在评论中让我们知道!

如果你喜欢这篇文章,或许你也会喜欢阅读“构建你的数据科学作品集”系列的其他文章:


via: https://www.dataquest.io/blog/data-science-portfolio-machine-learning/

作者:Vik Paruchuri 译者:kokialoves, zky001, vim-kakali, cposture, ideas4u 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出