Hadoop-数据分析高级教程-全-

Hadoop 数据分析高级教程(全)

原文:Pro Hadoop Data Analytics

协议:CC BY-NC-SA 4.0

一、概述:使用 Hadoop 构建数据分析系统

这本书是关于设计和实现摄取、分析和可视化大数据集的软件系统。在整本书中,我们将使用缩写词 BDA 或 BDAs(大数据分析系统)来描述这种软件。大数据本身值得解释一下。作为计算机程序员和架构师,我们知道我们现在所说的“大数据”已经存在了很长时间,事实上已经有几十年了,因为“大数据”一直是一个相对的多维术语,一个不仅仅由数据大小定义的空间。复杂性、速度、准确性,当然还有数据的大小和数量,都是任何现代“大数据集”的维度。

在本章中,我们将讨论什么是使用 Hadoop 的大数据分析系统(BDA ),为什么它们很重要,可以使用哪些数据源、接收器和存储库,以及适合和不适合使用 Hadoop 的分布式系统方法的候选应用程序。我们还简要讨论了构建这种类型系统的 Hadoop/Spark 范例的一些替代方案。

软件开发一直都有一种紧迫感,大数据分析的开发也不例外。即使在即将成为新兴行业的早期,大数据分析也要求能够以更快的速度和更深层次的理解来处理和分析越来越多的数据。当我们检查软件系统架构和开发的实际细节时,以更全面的方式处理越来越多的数据的基本需求一直是抽象计算机科学和应用计算机技术等的关键目标。同样,大数据应用和系统也不例外。如图 1-1 所示,当我们考虑到可用的全球数据资源在过去几年中是如何爆炸式增长的,这就不足为奇了。

A371868_1_En_1_Fig1_HTML.jpg

图 1-1。

Annual data volume statistics [Cisco VNI Global IP Traffic Forecast 2014–2019]

由于软件组件的快速发展和廉价的现成处理能力,再加上软件开发本身的快速发展,希望为自己的应用程序构建 BDA 的架构师和程序员常常会对他们在 BDA 舞台上面临的技术和战略选择感到不知所措。在这一介绍性章节中,我们将对 BDA 的景观做一个高层次的概述,并试图确定在建设 BDAs 时我们需要问自己的一些技术问题。

1.1 对分布式分析系统的需求

我们需要分布式大数据分析,因为传统的业务分析不足以满足现代分析应用程序对数据量、复杂性、多样性和高数据处理速率的需求。除了软件之外,大数据分析形势在另一方面发生了巨大变化。硬件成本——包括计算和存储——已经大幅下降。Hadoop 等工具依赖于成本相对较低的机器和磁盘集群,使分布式处理成为日常现实,对于大规模数据项目来说,分布式处理也是必要的。也有许多支持软件(框架、库和工具包)用于进行分布式计算。事实上,选择技术堆栈的问题已经成为一个严重的问题,仔细关注应用程序需求和可用资源是至关重要的。

历史上,硬件技术定义了软件组件的能力限制,尤其是在数据分析方面。传统的数据分析意味着对简单的基于文件的数据集或与关系数据存储的直接连接进行统计可视化(直方图、饼图和表格报告)。计算引擎通常使用单个服务器上的批处理来实现。在分布式计算这个勇敢的新世界中,使用计算机集群分而治之解决大数据问题已经成为一种标准的计算方式:这种可扩展性允许我们超越单台计算机的能力界限,并根据我们的需要(或我们的承受能力)添加尽可能多的现成硬件。Ambari、Zookeeper 或策展人等软件工具帮助我们管理集群,并提供集群资源的可伸缩性和高可用性。

1.2 Hadoop 核心和少量历史

一些软件想法已经存在了很长时间,以至于它甚至不再是计算机历史——而是计算机考古学。“map-reduce”问题解决方法的思想可以追溯到第二古老的编程语言 LISP(列表处理),可以追溯到 20 世纪 50 年代。"地图" "缩小"“send”和“lambda”是 LISP 语言本身的标准函数!几十年后,我们现在所知的 Apache Hadoop,即基于 Java 的开源分布式处理框架,并不是“从零开始”的。它是从 Apache Nutch 演化而来的,Apache Nutch 是一个开源的网络搜索引擎,而后者又是基于 Apache Lucene 的。有趣的是,R 统计库(我们也将在后面的章节中深入讨论)也受到 LISP 的影响,并且最初是用 LISP 语言编写的。

在我们谈论 Hadoop 生态系统之前,Hadoop 核心组件值得一提。顾名思义,Hadoop 核心是 Hadoop 框架的本质[图 1.1]。支持组件、架构,当然还有辅助库、问题解决组件和称为 Hadoop 生态系统的子框架都构建在 Hadoop 核心基础之上,如图 1-2 所示。请注意,在本书的范围内,我们将不会讨论 Hadoop 1,因为它已经被使用 YARN(又一个资源协商器)的新的重新实现所取代。请注意,在 Hadoop 2 系统中,MapReduce 并没有消失,它只是被模块化并抽象成一个组件,可以与其他数据处理模块很好地配合。

A371868_1_En_1_Fig2_HTML.jpg

图 1-2。

Hadoop 2 Core diagram

1.3 Hadoop 生态系统概述

Hadoop 及其生态系统,加上围绕它们发展起来的新框架和库,仍然是大数据分析领域不可忽视的力量。本书的其余部分将帮助您针对大数据分析挑战制定有针对性的应对措施,同时提供最基本的背景知识,帮助您学习解决大数据分析问题的新方法。Hadoop 及其生态系统通常分为四个主要类别或功能块,如图 1-3 所示。您会注意到,我们包括了几个额外的模块,以显示对软件“粘合”组件以及某种安全功能的需求。您还可以根据自己的需求向 BDA 系统添加支持库和框架。

A371868_1_En_1_Fig3_HTML.jpg

图 1-3。

Hadoop 2 Technology Stack diagram Note

在本书中,我们将继续强调免费的第三方组件,比如前面提到的 Apache 组件和库。这并不意味着您不能将您喜欢的图数据库(或者关系数据库)作为数据源集成到您的 BDAs 中。我们还将强调开源组件的灵活性和模块化,这允许您用最少的附加软件“粘合剂”将数据管道组件连接在一起在我们的讨论中,我们将使用 Spring 框架的 Spring 数据组件,以及 Apache Camel,来提供集成的“粘合”支持来链接我们的组件。

1.4 人工智能技术、认知计算、深度学习和大数据分析

大数据分析不再仅仅是简单的统计分析。随着 BDA 及其支持框架的发展,来自机器学习(ML)人工智能(AI)、图像和信号处理以及其他复杂技术(包括所谓的“认知计算”技术)的技术已经成熟,并成为数据分析师工具包的标准组件。

1.5 自然语言处理和 BDAs

事实证明,自然语言处理(NLP)组件在大量不同的领域都很有用,从扫描和解释收据和发票到复杂的药房处方数据和医院病历处理,以及大量存在非结构化和半结构化数据的许多其他领域。在处理这种“混合搭配”的数据源时,Hadoop 是一个自然的选择,在这种数据源中,条形码、签名、图像和信号、地理空间数据(GPS 位置)和其他数据类型可能会混合在一起。Hadoop 也是进行各种大规模文档分析的一种非常强大的手段。

我们将在单独的一章中讨论所谓的“语义网”技术,如分类法和本体论、基于规则的控制和 NLP 组件。现在,可以说 NLP 已经走出了研究领域,进入了实际应用程序开发的领域,有各种各样的工具包和库可供选择。我们将在本书中讨论的一些 NLP 工具包是基于 Python 的自然语言工具包(NLTK)、斯坦福 NLP 和 Digital Pebble 的庞然大物,这是一个基于 Apache Hadoop 的用于大规模文档分析的开源平台。 1

1.6 SQL 和 NoSQL 查询

除非被查询,否则数据是没有用的。查询数据集的过程——无论是键值对集合、Oracle 或 MySQL 的关系数据库结果集,还是 Neo4j 或 Apache Giraph 等图数据库中的顶点和边的表示——都需要我们对数据进行过滤、排序、分组、组织、比较、分区和评估。这导致了 SQL 等查询语言的发展,以及与 HBase、Cassandra、MongoDB、CouchBase 等“NoSQL”组件和数据库相关的查询语言的所有变种和变体。在本书中,我们将集中使用 read-eval-print 循环(REPLs)、交互式 shells(如 IPython)和其他交互式工具来表达我们的查询,并且我们将尽可能地将我们的查询与众所周知的 SQL 概念相关联,而不管它们与什么软件组件相关联。例如,一些图数据库如 Neo4j(我们将在后面的章节中详细讨论)有它们自己的类似 SQL 的查询语言。在整本书中,我们将尽可能地坚持类似 SQL 的查询传统,但是我们会指出一些有趣的 SQL 范例的替代方案。

1.7 必要的数学

在本书中,我们将保持数学最小化。然而,有时候,一个数学等式不仅仅是一个必要的邪恶。有时候,理解你的问题并实现你的解决方案的最佳方式是数学途径——同样,在某些情况下,“必要的数学”成为解决难题的关键因素。数据模型、神经网络、单个或多个分类器以及贝叶斯图技术要求至少对这些系统的潜在动态有所了解。而且,对于程序员和架构师来说,必要的数学几乎总是可以被转换成有用的算法,并从那里转换成有用的实现。

1.8 设计和构建 BDA 系统的循环流程

如今,在构建 BDAs 方面有很多好消息。Apache Spark 及其内存计算模型的出现是一个重要的积极因素,但是还有其他几个原因可以解释为什么构建 BDAs 从来没有这么简单。这些原因包括:

  • 丰富的框架和 ide 来帮助开发;
  • 成熟且经过充分测试的组件,用于帮助构建 BDAs,如果您需要,还可以使用公司支持的 BDA 产品。框架成熟度(比如 Spring 框架、Spring Data subframework、Apache Camel 等等)通过提供可靠的核心基础设施来帮助分布式系统开发。
  • 一个重要的在线和面对面的 BDA 开发社区,有无数的开发者论坛和聚会。如果您遇到了与 BDA 设计和开发相关的架构或技术问题,用户社区中的某个人可能会为您提供有用的建议。

在本书中,我们将使用以下九个步骤来指定和创建我们的 BDA 示例系统。这个过程只是提示性的。您可以按原样使用下面列出的过程,对其进行自己的修改,添加或减少结构或步骤,或者提出自己的开发过程。这取决于你。我们发现以下步骤对于规划和组织 BDA 项目以及我们开发和构建项目时出现的一些问题特别有用。

您可能会注意到问题和需求定义、实现、测试和文档被合并到一个整体过程中。这里描述的过程非常适合于快速迭代开发过程,其中所使用的需求和技术在开发周期中相对稳定。

定义和构建 BDA 系统的基本步骤如下。整体循环如图 1-4 所示。

  1. 确定 BDA 系统的要求。开发的初始阶段需要生成技术、资源、技术和策略以及实现目标所需的其他组件的概要。最初的目标集(当然会有变化)需要被固定、排序和明确定义。众所周知,随着对项目需求了解的加深,目标和其他要求也会发生变化。BDA 系统有特殊要求(可能包括 Hadoop 集群中的内容、特殊数据源、用户界面、报告和仪表板要求)。列出数据源类型、数据接收器类型、必要的解析、转换、验证和数据安全问题。能够使您的需求适应 BDA 技术的可塑性和易变的本质,将确保您能够以模块化、有组织的方式修改您的系统。确定组件中的计算和进程,确定是否需要批处理或流处理(或两者都需要),并绘制计算引擎的流程图。这将有助于定义和理解系统的“业务逻辑”。
  2. 定义初始技术堆栈。初始技术堆栈将包括一个 Hadoop 核心以及适合您在上一步中定义的要求的适当生态系统组件。如果您需要流支持,您可以包括 Apache Spark,或者您正在使用我们在本书后面讨论的基于 Spark 的机器学习库。记住你将要使用的编程语言。如果你使用的是 Hadoop,Java 语言将是栈的一部分。如果你用的是 Apache Spark,也会用到 Scala 语言。Python 有许多非常有趣的特殊应用,我们将在后面的章节中讨论。如果其他语言绑定是需求的一部分,也可以使用。
  3. 定义数据源、输入和输出数据格式以及数据清理过程。在需求收集阶段(步骤 0),您制作了数据源/接收器类型的初始列表,并制作了顶层流程图来帮助定义您的数据管道。在 BDA 系统中可能会用到很多外来的数据源,包括图像、地理空间位置、时间戳、日志文件等等,所以要保持一个数据源(和数据宿)的最新列表。)类型,就像您做最初的设计工作一样方便。
  4. 定义、收集和组织初始数据集。您可能有项目的初始数据、测试和训练数据(本书后面会有更多关于训练数据的内容)、来自以前系统的遗留数据,或者根本没有数据。考虑数据集的最小数量(数量、种类和容量),并制定一个获取或生成所需数据的计划。请注意,当您添加新代码时,可能需要新的数据集来执行充分的测试。初始数据集应该测试数据管道的每个模块,确保正确执行端到端处理。
  5. 定义要执行的计算。概念形式的业务逻辑来自需求阶段,但是这个逻辑是什么以及它是如何实现的将随着时间的推移而改变。在这个阶段,定义要在数据元素上执行的输入、输出、规则和转换。这些定义在步骤 6 中被转化为计算引擎的实现。
  6. 预处理数据集以供计算引擎使用。有时数据集需要预处理:验证、安全检查、清理、转换成更适合处理的格式,以及其他几个步骤。有一个要满足的预处理目标的清单,并在整个开发周期中继续关注这些问题,并随着开发的进展进行必要的修改。
  7. 定义计算引擎步骤;定义结果格式。计算引擎的业务逻辑、流程、结果的准确性、算法和实现的正确性以及效率将总是需要被质疑和改进。
  8. 将过滤后的结果放入数据接收器的结果存储库中。数据接收器是保存数据管道最终输出的数据仓库。在准备好报告或显示您的输出数据之前,可能有几个过滤或转换步骤。您的分析的最终结果可以存储在文件、数据库、临时存储库、报告或任何需求中。请记住,用户在 UI 或仪表板上的操作可能会影响输出的格式、音量和显示。这些交互结果中的一些可能需要持久存储回数据存储。组织专门针对数据输出、报告、表示和持久性的需求列表。
  9. 定义和构建输出报告、仪表板和其他输出显示和控制。生成的输出显示和报告清楚地显示了所有分析计算的结果。BDA 系统的这一组件通常至少部分是用 JavaScript 编写的,并且可以使用复杂的数据可视化库来辅助不同种类的仪表板、报告和其他输出显示。
  10. 记录、测试、提炼和重复。如果有必要的话,我们可以在细化需求、栈、算法、数据集等之后,再一次经历这些步骤。文档最初由您在最后七个步骤中所做的笔记组成,但是随着项目的进展,需要进行改进和重写。测试需要在每个周期中被创建、精炼和改进。顺便提一下,每个开发周期都可以被认为是一个版本,一次迭代,或者你喜欢的组织你的程序周期的方式。

A371868_1_En_1_Fig4_HTML.jpg

图 1-4。

A cyclic process for designing and building BDAs

这就是了。系统地使用这个迭代过程将使你能够设计和构建与本书中描述的系统相媲美的 BDA 系统。

1.9 Hadoop 生态系统如何实现大数据分析

Hadoop 生态系统通过在数据管道架构中将所有必要的分析要素(数据源、转换、基础设施、持久性和可视化)链接在一起来实现大数据分析,同时允许这些组件以分布式方式运行。Hadoop 核心(或者在某些情况下,Apache Spark 甚至是同时使用 Hadoop 和 Storm 的混合系统)通过 ZooKeeper、Curator 和 Ambari 等组件提供分布式系统基础设施和集群(节点)协调。在 Hadoop 核心之上,生态系统为分析、可视化、持久性和报告提供了复杂的库。

Hadoop 生态系统不仅仅是 Hadoop 核心功能的附加库。该生态系统提供了集成的无缝组件,Hadoop 核心专为解决特定的分布式问题而设计。例如,Apache Mahout 提供了一个分布式机器学习算法工具包。

拥有一些经过深思熟虑的 API 可以很容易地将我们的数据源链接到我们的 Hadoop 引擎和其他计算元素。借助 Apache Camel、Spring Framework、Spring Data 和 Apache Tika 的“粘合”功能,我们将能够将所有组件链接到一个有用的数据流引擎中。

1.10“图像即大数据”的理念(IABD)

图像——实际上是各种图片和信号——是“大数据类型”信息的最广泛、最有用、最复杂的来源之一。

图像有时被认为是称为像素的原子单元的二维阵列,事实上(以及一些相关联的元数据),这通常是图像在诸如 Java 的计算机编程语言中以及在诸如 Java 高级成像(JAI)、OpenCV 和 BoofCV 等相关联的图像处理库中的表示方式。然而,生物系统从这些“二维阵列”中“拉出东西”:线条和形状、颜色、元数据和上下文、边缘、曲线以及所有这些之间的关系。很快就变得显而易见的是,图像(顺便提一下,相关数据,如时间序列和来自传感器(如麦克风或测距仪)的“信号”)是大数据的最佳示例类型之一,有人可能会说,图像的分布式大数据分析是受生物系统的启发。毕竟,我们中的许多人每次驾驶汽车时都会将非常复杂的三维立体视觉处理作为一个分布式系统来执行。

关于将影像作为大数据源的好消息是,它不再像以前那样困难了。复杂的库可用于与 Hadoop 和其他必要的组件接口,如图数据库或 Apache Kafka 等消息传递组件。如有必要,OpenCV 或 BoofCV 等低级库可以提供图像处理原语。编写代码既简洁又容易。例如,我们可以用下面的 Java 类编写一个简单的、可滚动的图像查看器(如清单 1-1 所示)。

A371868_1_En_1_Fig5_HTML.jpg

图 1-5。

Sophisticated third-party libraries make it easy to build image visualization components in just a few lines of code

package com.kildane.iabt;

import java.awt.image.RenderedImage;

import java.io.File;

import java.io.IOException;

import javax.media.jai.JAI;

import javax.imageio.ImageIO;

import javax.media.jai.PlanarImage;

import javax.media.jai.widget.
ScrollingImagePanel;

import javax.swing.JFrame;

/**
 * Hello IABT world!
 * The worlds most powerful image processing toolkit (for its size)?
 */

public class App
{
    public static void main(String[] args)
    {
        JAI jai = new JAI();
        RenderedImage image = null;
                try {
                        image = ImageIO.read(new File("/Users/kerryk/Documents/SA1_057_62_hr4.png"));
                } catch (IOException e) {
                        e.printStackTrace();
                }
                if (image == null){ System.out.println("Sorry, the image was null"); return; }
                JFrame f = new JFrame("Image Processing Demo for Pro Hadoop Data Analytics");
        ScrollingImagePanel panel = new ScrollingImagePanel
(image, 512, 512);
        f.add(panel);
        f.setSize(512, 512);
        f.setVisible(true);
        System.out.println("Hello IABT World, version of JAI is: " + JAI.getBuildVersion());
    }

}

Listing 1-1.Hello image world: Java code for an image visualizer stub

as shown in Figure 1-5

然而,一个简单的图像浏览器只是图像 BDA 系统的开始。有低级别的图像处理、特征提取、转换成适当的数据表示以供分析,最后将结果加载到报告、仪表板或定制的结果显示中。

我们将在第十四章中更全面地探讨图像作为大数据(IABD)的概念。

使用的编程语言

首先,说一下编程语言。虽然 Hadoop 及其生态系统最初是用 Java 编写的,但现代 Hadoop 子系统拥有几乎所有可以想到的语言的语言绑定,包括 Scala 和 Python。这使得在一个应用程序中构建开发各种编程语言的有用特性所必需的多语言系统变得非常容易。

1 . 10 . 2 Hadoop 生态系统的多语言组件

在现代大数据分析领域,单一语言系统少之又少。虽然我们在本书中讨论的许多旧组件和库主要是用一种编程语言编写的(例如,Hadoop 本身是用 Java 编写的,而 Apache Spark 主要是用 Scala 编写的),但 BDA 通常是不同组件的组合,有时在同一个应用程序中使用 Java、Scala、Python 和 JavaScript。这些多语言、模块化的系统通常被称为多语言系统。

现代程序员习惯于多语言系统。对多语言方法的一些需求是不必要的:例如,为互联网编写仪表板适合于 JavaScript 这样的语言,尽管人们可以在被迫的情况下使用 Java Swing 在独立甚至 web 模式下编写仪表板。对于手头的应用程序来说,什么是最有效和最高效的,这完全是一个问题。在本书中,我们将拥抱多语言理念,本质上使用 Java 开发基于 Hadoop 的组件,使用 Scala 开发基于 Spark 的组件,根据需要使用 Python 和脚本,使用基于 JavaScript 的工具包开发前端、仪表盘、各种图形和绘图示例。

1.10.3 Hadoop 生态系统结构

虽然 Hadoop 核心提供了构建分布式系统功能的基础,但被称为“Hadoop 生态系统”的附加库和框架提供了与 API 和功能的有用连接,这些 API 和功能可解决应用问题并构建分布式系统。

我们可以将 Hadoop 生态系统想象成一种“太阳系”,生态系统的各个组件依赖于中心 Hadoop 组件,Hadoop 核心位于中心“太阳”位置,如图 1-6 所示。除了为 Hadoop 集群本身提供管理和簿记(例如 Zookeeper 和 Curator),Hive 和 Pig 等标准组件提供数据仓库,Mahout 等其他辅助库提供标准的机器学习算法支持。

A371868_1_En_1_Fig6_HTML.jpg

图 1-6。

A simplified “solar system” graph of the Hadoop ecosystem

Apache ZooKeeper(zookeeper.apache.org)是一个分布式协调服务,用于各种基于 Hadoop 和 Spark 的系统。它具有命名服务、组成员资格、用于分布式同步的锁和载体,以及高度可靠的集中式注册表。ZooKeeper 有一个由“znodes”组成的分层名称空间数据模型。Apache ZooKeeper 是开源的,由一个有趣的辅助组件 Apache Curator 支持,这是一个 ZooKeeper 的客户端包装器,也是一个支持以 ZooKeeper 为中心的组件的丰富框架。我们将在设置运行 Kafka 消息系统的配置时再次见到 ZooKeeper 和策展人。

1.11 关于“软件胶水”和框架的说明

“胶水”是任何建设项目都必须的,软件项目也不例外。事实上,一些软件组件,如自然语言处理(NLP)组件 Digital Pebble Behemoth(我们将在后面详细讨论)将自己称为“glueware”。幸运的是,也有一些通用集成库和包非常适合构建 BDA,如表 1-1 所示。

表 1-1。

Database types and some examples from industry

| 名字 | 位置 | 描述 | | --- | --- | --- | | 弹簧框架 | http://projects.spring.io/spring-framework/ | 一个基于 Java 的应用程序开发框架,对应用程序开发需求的几乎任何部分都有库支持 | | 阿帕奇是 | tika.apache.org | 从各种文件类型中检测和提取元数据 | | 阿帕奇骆驼 | Camel.apache.org | 实现企业集成模式(EIP)的“glueware”组件 | | 春季数据 | [`http://projects.spring.io/spring-data/`](http://projects.spring.io/spring-data/) | 数据访问工具包,与 Spring 框架的其余部分紧密耦合 | | 巨大的 | [`https://github.com/DigitalPebble/behemoth`](https://github.com/DigitalPebble/behemoth) | 大规模文档分析“glueware” |

为了有效地使用 Apache Camel,了解企业集成模式(EIP)很有帮助。有几本关于 EIP 的好书,它们对于使用 Apache Camel 尤其重要。 2

1.12 Apache Lucene、Solr 等等:开源搜索组件

对于分布式计算,尤其是大数据分析,搜索组件与查询引擎本身一样重要。事实上,有时候像 Apache Lucene 或 Apache Solr 这样的搜索引擎是查询引擎实现本身的关键部分。我们可以在图 1-7 中看到这些组件之间的相互作用。事实证明,Lucene 的 Solr 组件有自己的生态系统,尽管规模不如 Hadoop 生态系统大。尽管如此,Lucene 生态系统包含一些与大数据分析非常相关的软件资源。除了 Lucene 和 Solr,Lucene 生态系统还包括 Nutch,这是一个可扩展和高度可伸缩的网络爬虫(nutch.apache.org)。NGDATA 的 Lily 项目是一个非常有趣的软件框架,我们可以使用它无缝地利用 HBase、Zookeeper、Solr 和 Hadoop。Lily 客户端可以使用基于 Avro 的协议来提供到 Lily 的连接。回想一下,Apache Avro(avro.apache.org)是一个数据序列化系统,它提供了一种紧凑而快速的二进制数据格式,并与动态语言简单集成。

A371868_1_En_1_Fig7_HTML.jpg

图 1-7。

A relationship diagram between Hadoop and other Apache search-related components

1.13 用于构建大数据分析系统的架构

构建 BDAs 时的部分问题是,软件开发并不是真正在建造一座大楼。这只是一个比喻,尽管很有用。当我们设计一个软件时,我们已经在使用大量的隐喻和类比来思考我们正在做的事情。我们称之为软件架构,因为它是一个类似于建造房子的过程,一些基本原则适用于设计一个购物中心,就像设计一个软件系统一样。

我们希望从我们技术的历史中吸取教训,而不是重新发明轮子或犯与我们的前辈同样的错误。因此,我们有“最佳实践”、软件“模式”和“反模式”、诸如敏捷或迭代开发的方法,以及其他技术和策略的整个调色板。这些资源帮助我们实现质量,降低成本,并为我们的软件需求提供有效和可管理的解决方案。

“软件架构”的比喻因为软件开发的某些现实而不成立。如果你正在建造一个豪华酒店,你突然决定要给每个套房增加私人水疗室或壁炉,这是一个问题。很难重新设计平面图,或者使用什么品牌的地毯。改变主意会受到重罚。偶尔我们必须打破建筑的比喻,看看是什么使软件架构从根本上不同于它的比喻。

这种差异大部分与软件本身的动态和可变性质有关。需求变化,数据变化,软件技术快速发展。客户改变了他们对自己需要什么和如何需要的想法。经验丰富的软件工程师认为软件的这种可塑性和易弯曲性是理所当然的,这些现实——软件和数据的流动性——影响了从工具包到方法的一切,尤其是敏捷风格的方法,它几乎理所当然地假设快速变化的需求。

这些抽象的想法影响了我们实际的软件架构选择。简而言之,在设计大数据分析系统时,经受住时间考验的标准架构原则仍然适用。例如,我们可以使用任何标准 Java 编程项目通用的组织原则。我们可以使用企业集成模式(EIP)来帮助组织和集成整个项目中不同的组件。如果我们愿意,我们可以继续使用传统的 n 层、客户端-服务器或对等原则来组织我们的系统。

作为架构师,我们还必须了解分布式系统(尤其是 Hadoop)如何改变实际系统构建的等式。架构师必须考虑专门适用于 Hadoop 技术的模式:例如,mapReduce 模式和反模式。知识是关键。因此,在下一节中,我们将告诉您为了构建有效的 Hadoop BDAs,您需要知道些什么。

1.14 您需要了解的内容

当我们写这本书的时候,我们必须对你,读者,做一些假设。我们做了很多假设:您是一名经验丰富的程序员和/或架构师,您已经了解 Java,您了解一些 Hadoop,熟悉 Hadoop 2 核心系统(包括 YARN)、Hadoop 生态系统,并且您习惯于从头开始构建 Java 风格的应用程序的基本机制。这意味着你熟悉一个 IDE(比如 Eclipse,我们下面会简要介绍),你知道 Ant 和 Maven 等构建工具,你有一个大数据分析问题要解决。我们假设您非常熟悉您想要解决的技术问题:这些问题包括选择您的编程语言、您的技术栈,并且您知道您的数据源、数据格式和数据接收器。你可能也已经熟悉 Python 和 Scala 编程语言,但是我们在下一章包括了对这些语言的快速复习——以及关于它们特别有用的一些想法。Hadoop 生态系统有许多组件,其中只有一些与我们将要讨论的内容相关,因此在表 1-3 中,我们简要描述了我们将使用的一些 Hadoop 生态系统组件。

我们假设的不仅仅是你的编程能力。我们还假设你是一个战略思考者:你明白当软件技术改变、发展和变异时,合理的战略和方法(包括计算机科学和任何其他种类的科学)允许你适应新技术和新的问题领域。作为一名战略思考者,你对数据格式感兴趣。

虽然数据格式肯定不是大数据科学最迷人的方面,但它们是与架构师和软件工程师最相关的问题之一,因为数据源及其格式在一定程度上决定了任何数据管道的一个非常重要的部分:最初的软件组件或预处理器,它清理、验证、确认、确保安全性,并从数据源获取数据,以供管道的计算引擎阶段处理。Hadoop 是本书中讨论的大数据分析的关键组件,为了从本书中获得最大收益,您应该对 Hadoop 核心和 Hadoop 生态系统的基本组件有深刻的理解。这包括“经典生态系统”组件,如 Hive、Pig 和 HBase,以及 glue 组件,如 Apache Camel、Spring Framework、Spring Data 子框架和 Apache Kafka 消息传递系统。如果您对使用关系数据源感兴趣,了解标准 Java 编程中使用的 JDBC 和 Spring Framework JDBC 将会有所帮助。JDBC 在 Apache Phoenix(Phoenix . Apache . org)等组件中卷土重来,这是关系型技术和基于 Hadoop 的技术的有趣结合。Phoenix 提供对 HBase 数据的低延迟查询,在查询中使用标准的 SQL 语法。Phoenix 是一个客户端嵌入式 JDBC 驱动程序,因此只需一行 Java 代码就可以访问 HBase 集群。Apache Phoenix 还提供对模式定义、事务和元数据的支持。

表 1-2。

Database types and some examples from industry

| 数据库类型 | 例子 | 位置 | 描述 | | --- | --- | --- | --- | | 有关系的 | 关系型数据库 | mahout.apache.org | 这种类型的数据库已经存在了足够长的时间,可以获得复杂的支持框架和系统。 | | 文件 | 阿帕奇兔 | jackrabbit.apache.org | Java 中的内容存储库 | | 图表 | Neo4j | Neo4j.com | 多用途图数据库 | | 基于文件的 | 全文搜索引擎 | Lucene.apache.org | 通用统计 | | 混合物 | Solr+骆驼 | Camel.apache.org Lucene.apache.org/solr | Lucene、Solr 和 glue 合二为一 |

Note

设置和有效使用 Hadoop 的最佳参考之一是 Jason Venner 和 Sameer Wadkhar 所著的《Pro Apache Hadoop,第二版》,可从 Apress 出版社获得。

表 1-3。

A sampling of BDA components in and used with the Hadoop Ecosystem

| 名字 | 小贩 | 位置 | 描述 | | --- | --- | --- | --- | | 象夫 | 街头流氓 | mahout.apache.org | 面向 Hadoop 的机器学习 | | MLlib(密西西比州) | 街头流氓 | Spark.apache.org/mllib | Apache Spark 的机器学习 | | 稀有 |   | [`https://www.r-project.org`](https://www.r-project.org) | 通用统计 | | 新西兰黑秧鸡 | 新西兰怀卡托大学 | [`http://www.cs.waikato.ac.nz/ml/weka/`](http://www.cs.waikato.ac.nz/ml/weka/) | 统计分析和数据挖掘(基于 Java) | | H2O | H20 | H2o.ai | 基于 JVM 的机器学习 | | scikit_learn |   | scikit-learn.org | Python 中的机器学习 | | Spark | 街头流氓 | spark.apache.org | 开源集群计算框架 | | 卡夫卡 | 街头流氓 | kafka.apache.org | 分布式消息传递系统 |

表 1-3 简要总结了我们将讨论的一些工具包。

1.15 数据可视化和报告

数据可视化和报告可能是数据管道架构的最后一步,但它肯定与其他阶段一样重要。数据可视化允许系统的最终用户交互式地查看和操作数据。它可能是基于 web 的,使用 RESTful APIs 和浏览器、移动设备或设计为在高性能图形显示器上运行的独立应用程序。数据可视化的一些标准库如表 1-4 所示。

表 1-4。

A sampling of front-end components for data visualization

| 名字 | 位置 | 描述 | | --- | --- | --- | | D3 | `D3.org` | Javascript 数据可视化 | | Ggplot2 | `http://ggplot2.org` | Python 中的数据可视化 | | matplotlib | `http://matplotlib.org` | 用于基本绘图的 Python 库 | | 三. js | `http://threejs.org` | 用于三维图形和绘图的 JavaScript 库 | | 角度 JS | `http://angularjs.org` | 允许使用 JavaScript 创建模块化数据可视化组件的工具包。它特别有趣,因为 AngularJS 与 Spring 框架和其他管道组件集成得很好。 |

使用这些库或类似的库创建仪表板或前端用户界面非常简单。大多数高级 JavaScript 库包含高效的 API 来连接数据库、RESTful web 服务或 Java/Scala/Python 应用程序。

A371868_1_En_1_Fig8_HTML.jpg

图 1-8。

Simple data visualization displayed on a world map, using the DevExpress toolkit

使用 Hadoop 进行大数据分析是很特别的。对于 Hadoop 系统架构师来说,Hadoop BDA 提供并允许利用标准的主流架构模式、反模式和策略。例如,BDAs 可以使用标准的 ETL(提取-转换-加载)概念,以及在“云中”开发分析系统的架构原则来开发。标准的系统建模技术仍然适用,包括设计的“应用层”方法。

应用层设计的一个例子可能包含“服务层”(它提供应用程序的“计算引擎”或“业务逻辑”)和数据层(它存储和管理输入和输出数据,以及数据源和接收器,以及由系统用户访问的输出层,它向输出设备提供内容)。当内容被提供给 web 浏览器时,这通常被称为“web 层”。

Issues of the Platform

在本书中,我们在 Mac OS X 环境中表达了很多例子。这是故意的。我们使用 Mac 环境的主要原因是,它似乎是 Linux/Unix 语法(毕竟,这是 Hadoop 赖以生存的地方)和规模更小的开发环境之间的最佳妥协,在这种环境中,开发人员可以尝试这里显示的一些想法,而不需要大型 Hadoop 集群,甚至不需要一台笔记本电脑。这并不意味着你不能在 Cygwin 的 Windows 平台或类似的环境中运行 Hadoop。

A371868_1_En_1_Fig9_HTML.jpg

图 1-9。

A simple data pipeline

一个简单的数据管道如图 1-9 所示。在某种程度上,当考虑 BDAs 时,这个简单的管道就是“Hello world”程序。它对应于所有数据分析师都熟悉的那种简单的主流 ETL(提取-转换-加载)过程。管道的后续阶段转换先前的输出内容,直到数据被发送到最终的数据接收器或结果存储库。

1.15.1 使用 Eclipse IDE 作为开发环境

Eclipse IDE 已经存在很长时间了,关于使用 Eclipse 进行现代应用程序开发的争论在大多数使用 Java 或 Scala 的开发中心都很激烈。现在有许多替代 Eclipse 的 IDE,您可以选择其中任何一个来试验和扩展本书中开发的示例系统。或者,如果您愿意,您甚至可以使用常规的文本编辑器并从命令行运行系统,只要您身边有最新版本的 Apache Maven。附录 A 向您展示了如何为各种 ide 和平台(包括现代 Eclipse 环境)设置和运行示例系统。顺便提一下,Maven 是一个非常有效的工具,用于组织构成任何 BDA 的模块化的基于 Java 的组件(以及用 Scala 或 JavaScript 等其他语言实现的组件),并且被直接集成到 Eclipse IDE 中。Maven 在命令行上构建、测试和运行 BDA 同样有效。

我们发现,在开发本书中讨论的一些混合应用程序示例时,Eclipse IDE 特别有价值,但这可能是个人喜好的问题。请随意将示例导入到您选择的 IDE 中。

A371868_1_En_1_Fig10_HTML.jpg

图 1-10。

A useful IDE for development : Eclipse IDE with Maven and Scala built in Data Sources and Application Development

在主流应用程序开发中——大多数时候——我们只会遇到一些基本类型的数据源:关系、各种文件格式(包括原始的非结构化文本)、逗号分隔的值,甚至是图像(可能是流数据,甚至是更奇特的东西,比如 Neo4j 等图数据库的导出)。在大数据分析领域,可能会用到信号、图像和多种非结构化数据。这些可能包括空间或 GPS 信息、来自传感器的时间戳以及各种其他数据类型、元数据和数据格式。在本书中,特别是在示例中,我们将向您展示各种各样的常见数据格式以及外来数据格式,并提供关于如何对数据进行标准 ETL 操作的提示。在适当的时候,我们将根据需要讨论数据验证、压缩以及从一种数据格式到另一种数据格式的转换。

1.15.2 本书不是什么

既然我们已经注意到了这本书是关于什么的,我们现在必须检查它不是什么。

这本书不是对 Apache Hadoop、大数据分析组件或 Apache Spark 的介绍。已经有许多优秀的书籍描述了“vanilla Hadoop”(直接从 hadoop.apache.org 获得)及其生态系统的特性和机制,以及最近的 Apache Spark 技术,这些技术取代了 Hadoop 的原始 map-reduce 组件,并允许批处理和内存处理。

在整本书中,我们将描述有用的 Hadoop 生态系统组件,尤其是那些与我们将在本书其余部分构建的示例系统相关的组件。这些组件是我们的 BDAs 或大数据分析组件的构建模块,因此本书不会深入讨论组件功能。对于标准的 Hadoop 兼容组件,如 Apache Lucene、Solr、Apache Camel 或 Spring Framework,书籍和互联网教程比比皆是。

我们也不会深入讨论方法论(例如迭代或敏捷方法论),尽管这些是构建大数据分析系统的非常重要的方面。我们希望我们在这里讨论的系统对你有用,不管你选择什么样的方法风格。

How to Build The BDA Evaluation System

在这一节中,我们将简要介绍如何建立 BDA 评估系统。成功完成后,这将为您提供评估本书剩余部分中讨论的代码和示例所需的一切。各个组件在其各自的网站上都有完整的安装说明。

  1. 如果您还没有设置基本开发环境,请设置好。这包括 Java 8.0、Maven 和 Eclipse IDE。有关 Java 的最新安装说明,请访问 oracle.com。不要忘记相应地设置适当的环境变量,比如 JAVA_HOME。下载并安装 Maven (maven.apache.org),设置 M2_HOME 环境变量。要确保 Maven 已经正确安装,请在命令行中键入 mvn–version。还要在命令行上键入‘which mvn ’,以确保 Maven 可执行文件在您认为的位置。

  2. 确保安装了 MySQL。从 www.mysql.com/downloads 下载合适的安装包。使用本书中包含的示例模式和数据来测试功能。你应该可以运行“mysql”和“mysqld”。

  3. 安装 Hadoop 核心系统。在本书的例子中,我们使用 Hadoop 版本 2.7.1。如果你在 Mac 上,你可以用自制软件来安装 Hadoop,或者从网站上下载并按照说明安装。在. bash_profile 文件中设置 HADOOP_HOME 环境变量。

  4. Insure that Apache Spark is installed. Experiment with a single-machine cluster by following the instructions at http://spark.apache.org/docs/latest/spark-standalone.html#installing-spark-standalone-to-a-cluster . Spark is a key component for the evaluation system. Make sure the SPARK_HOME environment variable is set in your.bash_profile file .

    A371868_1_En_1_Fig11_HTML.jpg

    图 1-11。

    Successful installation and run of Apache Spark results in a status page at localhost:8080 To make sure the Spark system is executing correctly, run the program from the SPARK_HOME directory.

    ./bin/run-example SparkPi 10
    
    

    You will see a result similar to the picture in Figure 1-12.

    A371868_1_En_1_Fig12_HTML.jpg

    图 1-12。

    To test your Spark installation, run the Spark Pi estimator program. A console view of some expected results.

  5. 安装 Apache Mahout (mahout.apache.org)。这是一个非常有用的分布式分析工具包。设置适当的环境变量,包括 MAHOUT_HOME。运行 Mahout 测试套件以确保它安装正确。

  6. 安装 Apache Kafka (kafka.apache.org)。这个消息传递系统将在我们的示例中占据显著位置。第三章列出了建立和彻底运用卡夫卡体系的所有必要步骤。

  7. 安装你最喜欢的 NoSQL 和图数据库。其中可能包括 Cassandra (Cassandra.apache.org)、mongoDB ( https://www.mongodb.org/downloads#production )等。如果你对这本书的图形分析部分感兴趣,Neo4j ( http://neo4j.com )是一个非常受欢迎的图数据库。我们的图表分析示例都基于 Neo4j。在本书中,我们选择 Cassandra 作为我们的 NoSQL 数据库。

  8. 安装 Apache Solr(Lucene . Apache . org/Solr)。下载 Solr 服务器 zip 文件,解压缩,并遵循 README 文件中的附加说明。这种可配置的基于 Java 的搜索组件可以与 Hadoop 无缝耦合,利用 Hadoop 和 Spark 基础设施提供复杂、可扩展和可定制的搜索功能。

  9. 安装 Scala 编程语言和 Akka。确保您的 Eclipse IDE 中有一个支持 Scala 的插件。通过在命令行中键入“scalac–version”和“which scala ”,确保 Scala 和 Scala 编译器安装正确。

  10. 安装 Python 和 IPython。在 MacOS 系统上,Python 已经可以使用了。您可能希望安装 Anaconda 系统,它在一个包中提供了 Python、交互式 Python 和许多有用的库。

  11. 安装 H2O(H2O . ai)和苏打水。一旦安装了阿帕奇 Spark 和 Akka,我们就可以安装 H20 和苏打水组件。

  12. 安装合适的“粘合”组件。应该安装 Spring Framework、Spring Data、Apache Camel 和 Apache Tika。在附录 a 所示的 Maven pom.xml 中已经有了这些组件的适当依赖关系。您可能希望安装一些辅助组件,如 SpatialHadoop、distributed Weka for Hadoop 等。

当您安装完所有这些组件后,恭喜您。现在,您已经有了一个基本的软件环境,可以在其中彻底研究大数据分析系统(BDAs)。以这个基本系统为起点,我们准备探索各个模块,并为所提供的基本 BDA 功能编写一些扩展。

1.16 摘要

在这一介绍性章节中,我们探讨了不断变化的大数据环境,以及摄取、分析、存储、可视化和理解我们所处的不断增长的大数据海洋的方法。我们了解到,大数据源种类繁多,这些大数据源为有抱负的大数据分析师提出了新的挑战性问题。如今,大数据分析师面临的主要挑战之一是在可用于大数据分析的所有库和工具包、技术堆栈和方法中做出选择。

我们还简要概述了 Hadoop 框架,包括核心组件和相关的生态系统组件。尽管对 Hadoop 及其生态系统可以为我们这些数据分析师做些什么进行了必要的简要介绍,但我们随后探索了可供我们使用的架构和策略,目的是设计和实现有效的基于 Hadoop 的分析系统,或 BDA。这些系统将具有可扩展性和灵活性,以解决广泛的分析挑战。

在选择大数据工具包时,数据分析师有很多选择,能够浏览令人眼花缭乱的功能列表以提出有效的整体技术堆栈是成功开发和部署的关键。我们通过关注与 Hadoop 核心及其生态系统相对无缝集成的组件来保持简单(尽可能简单)。

在本书中,我们将试图向您证明,上面概述的设计和实现步骤可以产生适用于广泛领域和问题领域的可行的数据管道架构和系统。由于所讨论的系统的灵活性,我们将能够随着技术的变化“替换”模块化组件。例如,我们可能会发现一个机器学习或图像处理库更适合使用,并且我们可能希望用这些库中的一个来替换当前存在的应用程序库。首先,模块化设计让我们可以自由轻松地更换组件。在后面的章节中,当我们开发“作为大数据的图像”应用示例时,我们将看到这一原理的实际应用。

在下一章中,我们将快速回顾两种最流行的大数据分析语言——Scala 和 Python,并探索这两种语言特别有用的应用示例。

Footnotes 1

对“语义网”方法最好的介绍之一是 Dean Allemang 和 Jim Hendler 的“工作本体学家的语义网:RDFS 和 OWL 中的有效建模”,2008 年,摩根-考夫曼/爱思唯尔出版社,马萨诸塞州伯灵顿。国际标准书号 978-0-12-373556-0。

2

关于企业集成模式(EIPs)的最佳书籍是 Gregor Hohpe 和 Bobby Woolf 的《企业集成模式:设计、构建和部署消息传递解决方案》, 2004 年,Pearson Education Inc. Boston,MA。国际标准书号 0-321-20068-3。

二、Scala 和 Python 的回顾

本章包含了整本书使用的 Scala 和 Python 编程语言的快速回顾。这里讨论的内容主要针对需要快速复习 Scala 和 Python 的 Java/C++程序员。

Note

安装 Python 的一个简单方法是安装 Anaconda Python 发行版,可以在 www.continuum.io/downloads 获得。Anaconda 为数学和分析提供了许多额外的 Python 库,包括对 Hadoop、Weka、R 等的支持。

2.1 动机:选择正确的语言定义应用程序

为正确的任务选择正确的编程语言定义了应用程序。在许多情况下,选择看起来很自然:Java 用于以 Hadoop 为中心的组件,Scala 用于以 Spark 为中心的组件。使用 Java 作为 BDA 的主要语言允许访问 Spring Framework、Apache Tika 和 Apache Camel 来提供“glueware”组件。但是,从策略上来说(取决于您的 BDA 应用程序的性质),您可能需要包含其他语言和其他语言绑定。这反过来会影响整个技术堆栈和开发过程本身的性质。例如,一个移动应用程序可能需要与移动设备的底层代码进行交互,可能包括 Erlang 语言、C++或 C 等。

另一个需要谨慎选择编程语言的领域是用于显示和报告 BDA 结果的前端组件。如果前端仪表板和报告模块是基于 web 的,它们可能只包含不同复杂性的 JavaScript 库。然而,独立的科学应用可能是另一回事。这些可能使用 C、C++、Java 或 Python 中复杂的可视化库。

仔细控制、开发和质疑技术栈是非常重要的;但是为了选择技术栈组件及其语言绑定,我们必须首先比较语言特性。

2.1.1 语言特征—比较

我们现在将快速比较 Java、Scala 和 Python 为我们提供的十个最重要的特性,特别是在开发 BDA 系统方面。我们讨论的每一个特性都是现代编程语言的重要组成部分,但是对于 BDAs 来说尤其有用。这些有用的特性(我们最关心的特性)是:

  • 标准的逻辑、算术和控制结构。就基本的语言结构而言,Java、Scala 和 Python 有很多共同点。
  • 面向对象。我们的三种语言都有一个对象系统,Java、Scala 和 Python 之间的语法和语义有很大的不同。
  • 数据库连接。因为构建 BDA 的全部目的是建立端到端的数据处理管道,所以有效处理数据源以及导出到数据接收器是整体设计和技术堆栈选择的关键考虑因素。
  • 函数式编程支持。函数式编程一直是分布式应用程序开发的重要组成部分。
  • 图书馆支持,特别是机器学习和统计图书馆支持。许多不同的库都是用 Java、Scala 或 Python 编写的。库和框架选择是 BDA 设计者面临的最具挑战性的问题之一。然而,您选择的库的模块化和可扩展性是有效的 BDA 设计的关键要求。特定于任务的库,如用于机器学习的 MLlib,特别有用,但会产生对 Spark 和 Scala 的依赖。记住这些依赖关系尤其重要。
  • 仪表板和前端连接。通常 JavaScript 工具包和库(如 AngularJS、D3 等)足以构建复杂的仪表板和前端控件,但是——我们将在本书的其余部分看到——也有例外,特别是在移动应用程序开发中。
  • “胶件”连接和支持。这既包括以 Java 为中心的连接,也包括与其他库和框架的连接,甚至包括那些用 C++编写的库,如 Vowpal Wabbit 机器学习库。如果我们愿意,我们可以通过 web 服务,甚至通过 Java-native interface (JNI)支持库来访问 VW。
  • 读取-评估-打印循环支持。除了 Java 之外,所有现代语言都有 read-eval-print 循环(REPLs ),这在 Java 9 规范中得到了弥补。
  • 本机、多核支持和显式内存管理。正如我们将要讨论的,这在我们的语言之间有很大的不同。
  • 与 Hadoop、Spark、NoSQL 数据库及其生态系统的连接。PySpark、Spring Data Hadoop、Apache Camel-neo4j 等工具用于连接 BDA 中可能需要的不同组件。

2.2 Scala 的回顾

这篇对 Scala 语言的简短回顾由五个简单的代码片段组成,它们突出了我们在介绍性章节中描述的各种语言特性。Scala 特别有趣,因为它有内置的语言特性,比如类型推断、闭包、currying 等等。Scala 还有一个复杂的对象系统:每个值都是一个对象,每个操作都是方法调用。Scala 也兼容 Java 程序。现代语言总是包括对标准数据结构、集合、数组和向量的支持。Scala 也不例外,因为 Scala 与 Java 有着非常密切的关系,所以 Java 编程中所有你熟悉的数据结构仍然适用。

Note

在本书中,我们将讨论 Scala 2 . 11 . 7 版。在命令行中输入‘scala–version’来检查您安装的 Scala 版本。你也可以通过在命令行输入‘scalac–version’来检查你的 Scala 编译器版本。

2.2.1 Scala 及其交互式 Shell

让我们从快速排序算法的简单实现开始,然后在 Scala 交互式 shell 中测试这个例程。你可以看到清单 2-1 是一个简单的使用递归的声明式 Scala 程序。如果您将代码扔进您的交互式 Scala shell,您将看到如图 y.y 所示的结果。Java 程序员可以立即看出 Java 和 Scala 之间的相似性:Scala 也使用 JVM,并与 Java 协同工作。甚至“package”和“import”语句都是相似的,Scala 中“packages”对代码模块的组织也与 Java 包系统相似。

请注意,和 Java 一样,Scala 提供了一个方便的面向对象的打包系统。你也可以用类似于 Java 的方式定义一个可运行的“main”方法,如清单 2-1 所示。

A371868_1_En_2_Fig1_HTML.jpg

Figure 2-1.

/** An example of a quicksort implementation, this one uses a functional style. */

object Sorter {
  def sortRoutine(lst: List[Int]): List[Int] = {
    if (lst.length < 2)
      lst

    else {
      val pivel = lst(lst.length / 2)
      sortRoutine(lst.filter(_ < pivel)) :::
           lst.filter(_ == pivel) :::
           sortRoutine(lst.filter(_ > pivel))
    }
  }

  def main(args: Array[String]) {
    val examplelist = List(11,14,100,1,99,5,7)
    println(examplelist)
    println(sortRoutine(examplelist))
  }
}

Listing 2-1.Simple example of a Scala program which can be tried out in the interactive shell

Functional programming in Scala [includes the results from the Scala REPL as well]

scala> def closure1(): Int => Int = {
     | val next = 1
     | def addit(x: Int) = x + next
     | addit
     | }
closure1: ()Int => Int

scala> def closure2() = {
     | val y = 2
     | val f = closure1()
     | println(f(100))
     | }
closure2: ()Unit

Listing 2-2.An example of functional programming in Scala

您可以在任何交互式 Scala shells 中轻松使用 Spark,如清单 2-3 所示。

NOTE: Please make sure the bdasourcedatafile.dat file is present in your HDFS before running.

val bdaTextFile = sc.textFile("hdfs://bdasourcedatafile.dat")

val returnedErrors = bdaTextFile.filter(line => line.contains("ERROR"))
// Count all the errors
returnedErrors.count()
// Count errors mentioning ‘Pro Hadoop Analytics’
errors.filter(line => line.contains("Pro Hadoop Analytics")).count()
// Fetch the Pro Hadoop Analytics errors as an array of strings...
returnedErrors.filter(line => line.contains("Pro Hadoop Analytics")).collect()

Listing 2-3.Simple use of Apache Spark in Scala

KafkaWordCount program in Scala

package org.apache.spark.examples.streaming

import java.util.HashMap

import org.apache.kafka.clients.producer.{ProducerConfig, KafkaProducer, ProducerRecord}

import org.apache.spark.streaming._
import org.apache.spark.streaming.kafka._
import org.apache.spark.SparkConf

/**
 * Consumes messages from one or more topics in Kafka and does wordcount.
 * Usage: KafkaWordCount <zkQuorum> <group> <topics> <numThreads>
 *   <zkQuorum> is a list of one or more zookeeper servers that make quorum
 *   <group> is the name of kafka consumer group
 *   <topics> is a list of one or more kafka topics to consume from
 *   <numThreads> is the number of threads the kafka consumer should use
 *
 * Example:
 *    `$ bin/run-example \
 *      org.apache.spark.examples.streaming.KafkaWordCount zoo01,zoo02,zoo03 \
 *      my-consumer-group topic1,topic2 1`
 */
object KafkaWordCount {
  def main(args: Array[String]) {
    if (args.length < 4) {
      System.err.println("Usage: KafkaWordCount <zkQuorum> <group> <topics> <numThreads>")
      System.exit(1)
    }

    StreamingExamples.setStreamingLogLevels()

    val Array(zkQuorum, group, topics, numThreads) = args
    val sparkConf = new SparkConf().setAppName("KafkaWordCount")
    val ssc = new StreamingContext(sparkConf, Seconds(2))
    ssc.checkpoint("checkpoint")

    val topicMap = topics.split(",").map((_, numThreads.toInt)).toMap
    val lines = KafkaUtils.createStream(ssc, zkQuorum, group, topicMap).map(_._2)
    val words = lines.flatMap(_.split(" "))
    val wordCounts = words.map(x => (x, 1L))
      .reduceByKeyAndWindow(_ + _, _ - _, Minutes(10), Seconds(2), 2)
    wordCounts.print()

    ssc.start()
    ssc.awaitTermination()
  }
}

// Produces some random words between 1 and 100.
object KafkaWordCountProducer {

  def main(args: Array[String]) {
    if (args.length < 4) {
      System.err.println("Usage: KafkaWordCountProducer <metadataBrokerList> <topic> " +
        "<messagesPerSec> <wordsPerMessage>")
      System.exit(1)
    }

    val Array(brokers, topic, messagesPerSec, wordsPerMessage) = args

    // Zookeeper connection properties
    val props = new HashMap[String, Object]()
    props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, brokers)
    props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,
      "org.apache.kafka.common.serialization.StringSerializer")
    props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,
      "org.apache.kafka.common.serialization.StringSerializer")

    val producer = new KafkaProducerString, String

    // Send some messages
    while(true) {
      (1 to messagesPerSec.toInt).foreach { messageNum =>
        val str = (1 to wordsPerMessage.toInt).map(x => scala.util.Random.nextInt(10).toString)
          .mkString(" ")

        val message = new ProducerRecordString, String
        producer.send(message)
      }

      Thread.sleep(1000)
    }
  }

}

Listing 2-4.Scala example 4: using Apache Kafka to do word counting

惰性求值是一种“按需调用”的策略,可以在任何我们喜欢的语言中实现。清单 2-5 显示了一个简单的惰性评估练习的例子。

/* Object-oriented lazy evaluation in Scala */

package probdalazy

object lazyLib {

  /** Delay the evaluation of an expression until it is required. */
  def delayA: Susp[A] = new SuspImplA

  /** Get the value of a delayed expression. */
  implicit def forceA: A = s()

  /**
   * Data type of suspended computations. (The name froms from ML.)
   */
  abstract class Susp[+A] extends Function0[A]

  /**
   * Implementation of suspended computations, separated from the
   * abstract class so that the type parameter can be invariant.
   */
  class SuspImplA extends Susp[A] {
    private var maybeValue: Option[A] = None

    override def apply() = maybeValue match {
      case None =>

        val value = lazyValue
        maybeValue = Some(value)
        value
          case Some(value) =>

        value
    }

    override def toString() = maybeValue match {
      case None => "Susp(?)"
      case Some(value) => "Susp(" + value + ")"
    }
  }
}

object lazyEvaluation {
  import lazyLib._

  def main(args: Array[String]) = {
    val s: Susp[Int] = delay { println("evaluating..."); 3 }

    println("s     = " + s)       // show that s is unevaluated
    println("s()   = " + s())     // evaluate s
    println("s     = " + s)       // show that the value is saved
    println("2 + s = " + (2 + s)) // implicit call to force()

    val sl = delay { Some(3) }
    val sl1: Susp[Some[Int]] = sl
    val sl2: Susp[Option[Int]] = sl1   // the type is covariant

    println("sl2   = " + sl2)
    println("sl2() = " + sl2())
    println("sl2   = " + sl2)
  }
}

Listing 2-5.Lazy evaluation in Scala

2.3 Python 的回顾

在这一节中,我们将非常简洁地概述 Python 编程语言。Python 是构建 BDAs 的一个特别有用的资源,因为它具有高级的语言特性和与 Apache Spark 的无缝兼容性。像 Scala 和 Java 一样,Python 完全支持你所期望的所有常见数据结构类型。使用 Python 编程语言来构建 BDA 系统中的至少一些组件有很多好处。Python 在相对较短的时间内成为主流开发语言,部分原因是它是一种容易学习的语言。交互式外壳允许快速实验,并且能够以一种简单的方式尝试新的想法。有许多数字和科学库支持 Python,也有许多学习这种语言及其支持库的好书和在线教程。

Note

在整本书中,我们将使用 Python 版本 2.7.6 和交互式 Python (IPython)版本 4.0.0。要检查您已经安装的 python 版本,请在命令行上分别键入python –versionipython –version

A371868_1_En_2_Fig2_HTML.jpg

图 2-2。

Simple example of an IPython program, showingdatabase connectivity Note

要运行数据库连接示例,请记住我们主要使用 Oracle 的 MySQL 数据库。这意味着您必须从 Oracle 网站下载并安装 MySQL connector for Python,该网站位于 https://dev.mysql.com/downloads/connector/python/2.1.html 该连接器易于安装。在 Mac 上,只需双击 dmg 文件,然后按照说明进行操作。然后,您可以使用交互式 Python shell 来测试连通性。

清单 2-6 显示了 Python 中数据库连接的一个简单例子。熟悉 Java JDBC 结构的读者会看到相似之处。这个简单的例子建立一个数据库连接,然后关闭它。在这两条语句之间,程序员可以访问指定的数据库,定义表,并执行关系查询。

Database connectivity example in Python: import, connect, and release (close)

import mysql.connector

cnx = mysql.connector.connect(user='admin', password='',
                              host='127.0.0.1',
                              database='test')
cnx.close()

Listing 2-6.
Database connectivity

code with Python

各种算法都很容易在 Python 中实现,并且有大量的库可以帮助您。递归的使用和所有的标准编程结构都是可用的。清单 2-7 显示了一个递归程序的简单例子。

A simple Python code example using recursion

def FlattenList(a, result=None):
    result = []
    for x in a:
        if isinstance(x, list):
            FlattenList(x, result)
            else:
                result.append(x)
                return result

            FlattenList([ [0, 1, [2, 3] ], [4, 5], 6])

Listing 2-7.Recursive Python code that flattens a list

就像 Java 和 Scala 一样,用 Python“import”语句包含支持包很容易。清单 2-8 中显示了一个简单的例子。

显式规划导入列表是保持 Python 程序有组织并与开发团队和使用 Python 代码的其他人保持一致的关键。

Python example using time functions

import time
size_of_vec = 1000
def pure_python_version():
    t1 = time.time()
    X = range(size_of_vec)
    Y = range(size_of_vec)
    Z = []
    for i in range(len(X)):
        Z.append(X[i] + Y[i])
    return time.time() - t1
def numpy_version():
    t1 = time.time()
    X = np.arange(size_of_vec)
    Y = np.arange(size_of_vec)
    Z = X + Y
    return time.time() - t1
t1 = pure_python_version()
t2 = numpy_version()
print(t1, t2)
print("Pro Data Analytics Numpy in this example, is: " + str(t1/t2) + " faster!")

Listing 2-8.Python code example using time functions

IPython 中返回的答案类似于:

Pro Data Analytics

Hadoop Numpy in this example, is:  7.75 faster!

NumPy 库提供了 python 编程语言的扩展。

Python example using the NumPy library

import numpy as np
from timeit import Timer
size_of_vec = 1000
def pure_python_version():
    X = range(size_of_vec)
    Y = range(size_of_vec)
    Z = []
    for i in range(len(X)):
        Z.append(X[i] + Y[i])
def numpy_version():
    X = np.arange(size_of_vec)
    Y = np.arange(size_of_vec)
    Z = X + Y
#timer_obj = Timer("x = x + 1", "x = 0")
timer_obj1 = Timer("pure_python_version()", "from __main__ import pure_python_version")
timer_obj2 = Timer("numpy_version()", "from __main__ import numpy_version")
print(timer_obj1.timeit(10))
print(timer_obj2.timeit(10))
Listing 2-9.Python code example 4: Using the NumPy Library

清单 2-10 显示了一个自动启动文件的例子。

Python example:  using a startup file

import os
filename = os.environ.get('PYTHONSTARTUP')
if filename and os.path.isfile(filename):
    with open(filename) as fobj:
       startup_file = fobj.read()
    exec(startup_file)

import site

site.getusersitepackages()

Listing 2-10.Python code example 5: automatic startup behavior in Python

2.4 故障排除、调试、分析和记录

故障排除,无论您使用何种语言,都涉及到在运行您的程序时识别和解决即时和严重的问题。调试也是故障排除,但意味着不太严重的困难,如意外的错误条件、逻辑错误或其他意外的程序结果。这种区别的一个例子是权限问题。如果没有文件的执行权限,就不能运行程序。您可能需要执行“chmod”命令来修复此问题。

此外,我们认为故障诊断是一个心理过程。另一方面,调试可以得到显式工具的支持,帮助您找到 bug、逻辑错误、意外情况等。

2.4.1 在 Python 中调试资源

在 Python 中,可以通过键入以下命令来加载 pdb 调试器:

import pdb
import yourmodule
pdb.run (‘yourmodule.test()’)

或者,您可以通过键入以下命令直接将pdb用于 Python:

python –m pdb yourprogram.py

对于分析 Python,Robert Kern 的非常有用的行分析器( https://pypi.python.org/pypi/line_profiler/1.0b3 ))可以通过在命令行中键入以下命令来安装:

sudo pip install line_profiler

成功安装如图 2-3 所示。

A371868_1_En_2_Fig3_HTML.jpg

图 2-3。

Successful installation of the line profiler package

http://www.huyng.com/posts/python-performance-analysis/ 对剖析 Python 程序有很好的论述。

通过键入以下命令安装内存分析器:

sudo pip install -U memory_profiler

为什么不通过编写一个简单的 Python 程序来生成质数、斐波那契数列或您选择的其他小例程来测试您的分析器呢?

A371868_1_En_2_Fig4_HTML.jpg

图 2-4。

Profiling Python code using memory and line profilers

Python 的文档

当记录 Python 代码时,看一下 python.org 的文档风格指南是非常有帮助的。这可以在以下位置找到

https://docs.python.org/devguide/documenting.html

2.4.3 在 Scala 中调试资源

在这一部分,我们将讨论可以帮助你调试 Scala 程序的资源。调试程序最简单的方法之一就是在 Eclipse IDE 中安装 Scala 插件,在 Eclipse 中创建和构建 Scala 项目,并在那里调试和运行它们。关于如何做到这一点的大量教程,请参考 http://scala-ide.org

2.5 编程应用和示例

构建 BDA 意味着构建数据管道处理器。虽然有许多其他的方法来构思和构建软件系统——包括使用诸如敏捷之类的方法,诸如面向对象之类的技术概念,以及企业集成模式(EIPs)——但是一个不变的概念是管道概念。

2.6 摘要

在本章中,我们回顾了 Scala 和 Python 编程语言,并将它们与 Java 进行了比较。Hadoop 是一个以 Java 为中心的框架,而 Apache Spark 是用 Scala 编写的。大多数常用的 BDA 组件通常都有针对 Java、Scala 和 Python 的语言绑定,我们在较高层次上讨论了其中的一些组件。

每种语言都有其独特的优势,我们能够接触到 Java、Scala 和 Python 的一些合适的用例。

我们回顾了排除故障、调试、分析和记录 BDA 系统的方法,不管我们用什么语言编写 BDAs,我们还讨论了 Eclipse IDE 可用于 Python 和 Scala 的各种插件。

在下一章中,我们将着眼于 BDA 开发的必要成分:使用 Hadoop 和 Spark 构建 BDA 所必需的框架和库。

2.7 参考文献

鲍尔斯,迈克尔。Python 中的机器学习:预测分析的基本技术。印第安纳波利斯,约翰·威利父子公司,2015 年。

胡维茨,朱迪斯 s,考夫曼,马西娅,鲍尔斯,阿德里安。认知计算和大数据分析。印第安纳波利斯,约翰·威利父子公司,2015 年。

奥德斯基、马丁、斯普恩、莱克斯和凡纳斯、比尔。Scala 编程,第二版。加利福尼亚州核桃溪:Artima 出版社,2014 年。

杨克,杰夫。敏捷 Python 开发的基础。纽约州纽约市:纽约出版社,2008 年。

齐亚德,塔瑞克。Python 编程专家。英国伯明翰。,派克特出版社,2008 年。

三、Hadoop 和分析的标准工具包

在这一章中,我们来看看 BDA 系统的必要组成部分:对构建 BDAs 最有用的标准库和工具包。我们使用 Hadoop 和 Spark 生态系统中的标准工具包描述了一个示例系统(我们将在本书的剩余部分中开发该系统)。我们还使用其他分析工具包,如 R 和 Weka,以及主流开发组件,如 Ant、Maven、npm、pip、Bower 和其他系统构建工具。Apache Camel、Spring Framework、Spring Data、Apache Kafka、Apache Tika 等“Glueware 组件”可用于创建适合各种应用程序的基于 Hadoop 的系统。

Note

Hadoop 及其相关组件的成功安装是评估本书中示例的关键。在标题为“在 Mac 上安装 Hadoop 第一部分”的文章中的 http://amodernstory.com/2014/09/23/installing-hadoop-on-mac-osx-yosemite/ 中描述了在 Mac 上相对轻松地安装 Hadoop 的方法

3.1 库、组件和工具包:调查

没有一章可以描述所有的大数据分析组件,这些组件可以帮助您构建 BDA 系统。我们只能建议组件的类别,谈一些典型的例子,并在后面的章节中对这些例子进行扩展。

有大量的图书馆支持 BDA 系统的建设。为了了解可用技术的范围,考虑图 3-1 中所示的组件。这并不是组件类型的唯一列表,但是当您意识到每种组件类型都有各种各样的工具包、库、语言和框架可供选择时,定义 BDA 系统技术堆栈可能会在一开始就显得势不可挡。为了克服这个定义问题,系统模块化和灵活性是关键。

A371868_1_En_3_Fig1_HTML.jpg

图 3-1。

A whole spectrum of distributed techniques are available for building BDAs

构建模块化 BDA 系统最简单的方法之一是使用 Apache Maven 来管理依赖项,并为您完成大多数简单的组件管理。建立一个简单的 Maven pom.xml文件并在 Eclipse IDE 中创建一个简单的项目是让评估系统运行的好方法。我们可以从一个简单的 Maven pom.xml开始,类似于清单 2-1 中所示的那个。请注意,显示的唯一依赖项是 Hadoop 核心和 Apache Mahout,这是我们在第一章中讨论的 Hadoop 机器学习工具包,我们在示例中经常使用。我们将扩展 Maven pom 文件,以包含我们在本书后面使用的所有辅助工具包。你可以随意增加或减少组件,只需从pom.xml文件中移除依赖关系。

请记住,对于图表中显示的每种技术,都有几种备选方案。对于技术堆栈中的每个选择,通常都有方便的 Maven 依赖项,您可以将它们添加到您的评估系统中来检查功能,因此很容易混合和匹配组件。包含正确的“glueware”组件可以使不同库的集成不那么痛苦。

Note

为了有效地使用图书示例,需要设置以下重要的环境变量:

   export BDA_HOME="/Users/kerryk/workspace/bdt"

<project  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.kildane</groupId>
  <artifactId>bdt</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>Big Data Toolkit (BDT) Application</name>
  <url>http://maven.apache.org</url>
  <properties>
  <hadoop.version>0.20.2</hadoop.version>
  </properties>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-core</artifactId>
        <version>${hadoop.version}</version>
</dependency>
<dependency>
        <groupId>org.apache.mahout</groupId>
        <artifactId>mahout-core</artifactId>
        <version>0.9</version>
</dependency>
  </dependencies>
  <build>
    <finalName>BDT</finalName>
  </build>
</project>

Listing 3-1.A basic pom.xml file for the evaluation system

构建模块化 BDA 系统最简单的方法是使用 Apache Maven 来管理依赖项,并为您完成大多数简单的组件管理。使用一个简单的 pom.xml 来启动您的 BDA 项目是试验模块、锁定技术堆栈和定义系统功能的好方法——根据需要逐步修改您的依赖项和插件。

设置一个简单的 Maven pom.xml 文件并在 Eclipse IDE 中创建一个简单的项目是让评估系统运行的一种简单方法。我们可以从一个简单的 Maven pom.xml 开始,类似于清单 3-1 中所示。请注意,显示的唯一依赖项是 Hadoop Core 和 Apache Mahout,这是我们在第一章中讨论的 Hadoop 机器学习工具包,我们在示例中经常使用。我们将扩展 Maven pom 文件,以包含我们在本书后面使用的所有辅助工具包。只要从 pom.xml 文件中删除依赖项,就可以随意添加或删除组件。

让我们以举例的方式给评估系统添加一个规则系统。只需为 drools 规则系统添加适当的依赖项(对于 Drools 的大多数最新版本,请使用 Google“Drools maven 依赖项”)。清单 3-2 中显示了完整的pom.xml文件(基于我们的原始文件)。我们将在第八章的完整分析引擎示例中利用 JBoss Drools 的功能。请注意,我们提供依赖关系来连接 Drools 系统和 Apache Camel 以及 Drools 的 Spring 框架。

<project  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.kildane</groupId>
  <artifactId>bdt</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>Big Data Toolkit (BDT) Application, with JBoss Drools Component</name>
  <url>http://maven.apache.org</url>
  <properties>
  <hadoop.version>0.20.2</hadoop.version>
  </properties>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>

<!--  add these five dependencies to your BDA project to achieve rule-based support -->
<dependency>
        <groupId>org.drools</groupId>
        <artifactId>drools-core</artifactId>
        <version>6.3.0.Final</version>
</dependency>
<dependency>
        <groupId>org.drools</groupId>
        <artifactId>drools-persistence-jpa</artifactId>
        <version>6.3.0.Final</version>
</dependency>
<dependency>
        <groupId>org.drools</groupId>
        <artifactId>drools-spring</artifactId>
        <version>6.0.0.Beta2</version>
</dependency>
<dependency>
        <groupId>org.drools</groupId>
        <artifactId>drools-camel</artifactId>
        <version>6.0.0.Beta2</version>
</dependency>
<dependency>
        <groupId>org.drools</groupId>
        <artifactId>drools-jsr94</artifactId>
        <version>6.3.0.Final</version>
</dependency>
    <dependency>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-core</artifactId>
        <version>${hadoop.version}</version>
</dependency>
<dependency>
        <groupId>org.apache.mahout</groupId>
        <artifactId>mahout-core</artifactId>
        <version>0.9</version>
</dependency>
  </dependencies>
  <build>
    <finalName>BDT</finalName>
  </build>
</project>

Listing 3-2.Add JBoss Drools dependencies to add rule-based support to your analytical engine. A complete example of a Drools use case is in Chapter 8!

3.2 在评估系统中使用深度学习

DL4j ( http://deeplearning4j.org )是一个面向 Java 和 Scala 的开源分布式深度学习库。它集成了 Hadoop 和 Spark。

要安装:

git clone https://github.com/deeplearning4j/dl4j-0.4-examples.git

要构建系统:

cd $DL4J_HOME directory

然后:

mvn clean install -DskipTests -Dmaven.javadoc.skip=true

要验证 dl4j 组件是否正常运行,请键入以下内容:

mvn exec:java -Dexec.mainClass="org.deeplearning4j.examples.tsne.TSNEStandardExample" -Dexec.cleanupDaemonThreads=false

如果组件运行成功,您将看到类似于清单 y.y .的文本输出。

[INFO] --- exec-maven-plugin:1.4.0:java (default-cli) @ deeplearning4j-examples ---
o.d.e.t.TSNEStandardExample - Load & Vectorize data....
Nov 01, 2015 1:44:49 PM com.github.fommil.jni.JniLoader liberalLoad
INFO: successfully loaded /var/folders/kf/6fwdssg903x6hq7y0fdgfhxc0000gn/T/jniloader545087044337083844netlib-native_system-osx-x86_64.jnilib
o.d.e.t.TSNEStandardExample - Build model....
o.d.e.t.TSNEStandardExample - Store TSNE Coordinates for Plotting....
o.d.plot.Tsne - Calculating probabilities of data similarities..
o.d.plot.Tsne - Mean value of sigma 0.00
o.d.plot.Tsne - Cost at iteration 0 was 98.8718490600586
o.d.plot.Tsne - Cost at iteration 1 was 98.8718490600586
o.d.plot.Tsne - Cost at iteration 2 was 98.8718490600586
o.d.plot.Tsne - Cost at iteration 3 was 98.8718490600586
o.d.plot.Tsne - Cost at iteration 4 was 98.8718490600586
o.d.plot.Tsne - Cost at iteration 5 was 98.8718490600586
o.d.plot.Tsne - Cost at iteration 6 was 98.8718490600586
o.d.plot.Tsne - Cost at iteration 7 was 98.8718490600586
o.d.plot.Tsne - Cost at iteration 8 was 98.87185668945312
o.d.plot.Tsne - Cost at iteration 9 was 98.87185668945312
o.d.plot.Tsne - Cost at iteration 10 was 98.87186431884766
......    ......    ......   .......   .....  ......
o.d.plot.Tsne - Cost at iteration 98 was 98.99024963378906
o.d.plot.Tsne - Cost at iteration 99 was 98.99067687988281
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 23.075 s
[INFO] Finished at: 2015-11-01T13:45:06-08:00
[INFO] Final Memory: 21M/721M
[INFO] ------------------------------------------------------------------------
Listing 3-3.Output from the deep learning 4j test routine

为了在我们的评估系统中使用deeplearning4j组件,我们现在需要对我们的 BDA pom 文件进行迄今为止最广泛的修改。完整的文件如清单 3-4 所示。

<project  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.kildane</groupId>
        <artifactId>bdt</artifactId>
        <packaging>war</packaging>
        <version>0.0.1-SNAPSHOT</version>
        <name>Big Data Toolkit (BDT) Application</name>
        <url>http://maven.apache.org</url>
        <properties>
        <!--  new properties for deep learning (dl4j) components -->
                <nd4j.version>0.4-rc3.5</nd4j.version>
                <dl4j.version> 0.4-rc3.4 </dl4j.version>
                <canova.version>0.0.0.11</canova.version>
                <jackson.version>2.5.1</jackson.version>

                <hadoop.version>0.20.2</hadoop.version>
                <mahout.version>0.9</mahout.version>
        </properties>
        <!--  distribution management for dl4j  -->
        <distributionManagement>
                <snapshotRepository>
                        <id>sonatype-nexus-snapshots</id>
                        <name>Sonatype Nexus snapshot repository</name>
                        <url>https://oss.sonatype.org/content/repositories/snapshots</url>
                </snapshotRepository>
                <repository>
                        <id>nexus-releases</id>
                        <name>Nexus Release Repository</name>
                        <url>http://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
                </repository>
        </distributionManagement>
        <dependencyManagement>
                <dependencies>
                        <dependency>
                                <groupId>org.nd4j</groupId>
                                <artifactId>nd4j-jcublas-7.5</artifactId>
                                <version>${nd4j.version}</version>
                        </dependency>
                </dependencies>
        </dependencyManagement>
        <repositories>
                <repository>
                        <id>pentaho-releases</id>
                        <url>http://repository.pentaho.org/artifactory/repo/</url>
                </repository>
        </repositories>
        <dependencies>
                <!--  dependencies for dl4j components -->
                <dependency>
                        <groupId>org.deeplearning4j</groupId>
                        <artifactId>deeplearning4j-nlp</artifactId>
                        <version>${dl4j.version}</version>
                </dependency>
                <dependency>
                        <groupId>org.deeplearning4j</groupId>
                        <artifactId>deeplearning4j-core</artifactId>
                        <version>${dl4j.version}</version>
                </dependency>
                <dependency>
                        <groupId>org.nd4j</groupId>
                        <artifactId>nd4j-x86</artifactId>
                        <version>${nd4j.version}</version>
                </dependency>
                <dependency>
                        <groupId>org.jblas</groupId>
                        <artifactId>jblas</artifactId>
                        <version>1.2.4</version>
                </dependency>
                <dependency>
                        <artifactId>canova-nd4j-image</artifactId>
                        <groupId>org.nd4j</groupId>
                        <version>${canova.version}</version>
                </dependency>
                <dependency>
                        <groupId>com.fasterxml.jackson.dataformat</groupId>
                        <artifactId>jackson-dataformat-yaml</artifactId>
                        <version>${jackson.version}</version>
                </dependency>

                <dependency>
                        <groupId>org.apache.solr</groupId>
                        <artifactId>solandra</artifactId>
                        <version>UNKNOWN</version>
                </dependency>
                <dependency>
                        <groupId>junit</groupId>
                        <artifactId>junit</artifactId>
                        <version>3.8.1</version>
                        <scope>test</scope>
                </dependency>
                <dependency>
                        <groupId>org.apache.hadoop</groupId>
                        <artifactId>hadoop-core</artifactId>
                        <version>${hadoop.version}</version>
                </dependency>
                <dependency>
                        <groupId>pentaho</groupId>
                        <artifactId>mondrian</artifactId>
                        <version>3.6.0</version>
                </dependency>
                <!-- add these five dependencies to your BDA project to achieve rule-based
                        support -->
                <dependency>
                        <groupId>org.drools</groupId>
                        <artifactId>drools-core</artifactId>
                        <version>6.3.0.Final</version>
                </dependency>
                <dependency>
                        <groupId>org.drools</groupId>
                        <artifactId>drools-persistence-jpa</artifactId>
                        <version>6.3.0.Final</version>
                </dependency>
                <dependency>
                        <groupId>org.drools</groupId>
                        <artifactId>drools-spring</artifactId>
                        <version>6.0.0.Beta2</version>
                </dependency>
                <dependency>
                        <groupId>org.apache.spark</groupId>
                        <artifactId>spark-streaming_2.10</artifactId>
                        <version>1.5.1</version>
                </dependency>
                <dependency>
                        <groupId>org.drools</groupId>
                        <artifactId>drools-camel</artifactId>
                        <version>6.0.0.Beta2</version>
                </dependency>
                <dependency>
                        <groupId>org.drools</groupId>
                        <artifactId>drools-jsr94</artifactId>
                        <version>6.3.0.Final</version>
                </dependency>

                <dependency>
                        <groupId>com.github.johnlangford</groupId>
                        <artifactId>vw-jni</artifactId>
                        <version>8.0.0</version>
                </dependency>
                <dependency>
                        <groupId>org.apache.mahout</groupId>
                        <artifactId>mahout-core</artifactId>
                        <version>${mahout.version}</version>
                </dependency>
                <dependency>
                        <groupId>org.apache.mahout</groupId>
                        <artifactId>mahout-math</artifactId>
                        <version>0.11.0</version>
                </dependency>
                <dependency>
                        <groupId>org.apache.mahout</groupId>
                        <artifactId>mahout-hdfs</artifactId>
                        <version>0.11.0</version>
                </dependency>
        </dependencies>
        <build>
                <finalName>BDT</finalName>
                <plugins>
                        <plugin>
                                <groupId>org.codehaus.mojo</groupId>
                                <artifactId>exec-maven-plugin</artifactId>
                                <version>1.4.0</version>
                                <executions>
                                        <execution>
                                                <goals>
                                                        <goal>exec</goal>
                                                </goals>
                                        </execution>
                                </executions>
                                <configuration>
                                        <executable>java</executable>
                                </configuration>
                        </plugin>
                        <plugin>
                                <groupId>org.apache.maven.plugins</groupId>
                                <artifactId>maven-shade-plugin</artifactId>
                                <version>1.6</version>
                                <configuration>
                                        <createDependencyReducedPom>true</createDependencyReducedPom>
                                        <filters>
                                                <filter>
                                                        <artifact>*:*</artifact>
                                                        <excludes>
                                                                <exclude>org/datanucleus/**</exclude>
                                                                <exclude>META-INF/*.SF</exclude>
                                                                <exclude>META-INF/*.DSA</exclude>
                                                                <exclude>META-INF/*.RSA</exclude>
                                                        </excludes>
                                                </filter>
                                        </filters>
                                </configuration>
                                <executions>
                                        <execution>
                                                <phase>package</phase>
                                                <goals>
                                                        <goal>shade</goal>
                                                </goals>
                                                <configuration>
                                                        <transformers>
                                                                <transformer
                                                                        implementation="org.                                  apache.maven.plugins.shade.resource.AppendingTransformer">
                                                                        <resource>reference.conf</resource>
                                                                </transformer>
                                                                <transformer
                                                                        implementation="org.                         apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
                                                                <transformer
                                                                        implementation="org.                           apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                                                </transformer>
                                                        </transformers>
                                                </configuration>
                                        </execution>
                                </executions>
                        </plugin>
                        <plugin>
                                <groupId>org.apache.maven.plugins</groupId>
                                <artifactId>maven-compiler-plugin</artifactId>
                                <configuration>
                                        <source>1.7</source>
                                        <target>1.7</target>
                                </configuration>
                        </plugin>
                </plugins>
        </build>
</project>

Listing 3-4.Complete listing to include deeplearning 4j components

在扩充您的 BDA 评估项目以使用这个pom.xml之后,执行maven cleaninstallpackage任务以确保您的项目正确编译。

3.3 Spring 框架和 Spring 数据的使用

Spring 框架( https://spring.io )及其相关框架 Spring 数据(projects.spring.io/spring-data)是重要的 glueware 组件,但是 Spring 框架也提供了各种各样的功能资源。这些包括安全性、ORM 连接性、基于模型-视图-控制器(MVC)的应用程序开发等等。Spring Framework 使用面向方面的编程方法来解决横切关注点,并完全支持 Java 代码中各种称为“原型”的注释,最大限度地减少了手工制作样板文件的需要。

我们将在本书中使用 Spring Framework 来利用它提供的复杂功能资源,并研究 Spring Data Hadoop 组件(projects.spring.io/spring-hadoop/),这是 Hadoop 和 Spring 的无缝集成。特别是,我们将在第九章开发的完整分析系统中使用几个 Spring 框架组件。

3.4 数字和统计库:R、Weka 和其他

在这一节中,我们将讨论 R 和 Weka 统计库。R ( r-project.org)是一种专门为统计分析开发的解释性高级语言。Weka ( http://www.cs.waikato.ac.nz/ml/weka )是一个强大的统计库,为数据挖掘和其他分析任务提供机器学习算法。一个有趣的新发展是分布式 R 和分布式 Weka 工具包。有关 Mark Hall 的 DistributedWekaBase 和 Distributed Weka 的信息,请访问

3.5 分布式系统中的 OLAP 技术

OLAP(在线分析处理)是另一种古老的分析技术,它在 20 世纪 70 年代就已经出现,并在“大数据时代”复兴已经开发了几个强大的库和框架来支持大数据 OLAP 操作。其中最有趣的两个是 Pentaho 的 Mondrian ( http://community.pentaho.com/projects/mondrian/ )和 Apache 的一个新孵化器项目 Apache Kylin ( http://kylin.incubator.apache.org )。Pentaho Mondrian 提供了一个开源的分析引擎和自己的查询语言 MDX。要将 Pentaho Mondrian 添加到您的评估系统中,请将这个存储库和依赖项添加到您的pom.xml中:

<repository>
    <id>pentaho-releases</id>
    <url>http://repository.pentaho.org/artifactory/repo/</url>
  </repository>

<dependency>
  <groupId>pentaho</groupId>
  <artifactId>mondrian</artifactId>
  <version>3.6.0</version>
</dependency>

Apache Kylin 提供了 ANSI SQL 接口和多维分析,利用了 Hadoop 功能。Apache Kylin 也支持 Tableau ( get.tableau.com)等商业智能工具。

在第九章中,我们将使用 Apache Kylin 开发一个完整的分析引擎示例来提供 OLAP 功能。

3.6 用于分析的 Hadoop 工具包:Apache Mahout 和朋友

Apache Mahout ( mahout.apache.org)是一个机器学习库,专门设计用于 Apache Hadoop,以及更新版本的 Mahout 和 Apache Spark。像大多数现代软件框架一样,Mahout 与 Samsara 耦合,Samsara 是一个与 Mahout 协作的附加组件,为 Mahout 功能提供高级数学库支持。Apache Mahout 也可以与 MLlib 等兼容库一起使用。关于高级功能的更多信息可以在 Apache Mahout 和其他基于 Hadoop 的机器学习包的大量教程和书籍中找到。

Mahout 包含许多为分布式处理实现的标准算法。其中一些算法包括分类算法,如随机森林分类算法、多层感知器神经网络分类器的实现、朴素贝叶斯分类器和许多其他分类算法。这些可以单独使用,也可以作为数据管道中的阶段使用,甚至可以与正确的配置设置并行使用。

Vowpal Wabbit ( https://github.com/JohnLangford/vowpal_wabbit )是雅虎发起的一个开源项目并由微软研究院继续。大众的一些特性包括稀疏降维、快速特性查找、多项式学习和集群并行学习,所有这些都是在我们的 BDA 系统中使用的有效技术。VW 最有趣的扩展之一是 RESTful web 界面,可以在

关于 Vowpal-Wabbit 以及如何正确设置和运行 VW 的详细讨论,请参见 http://zinkov.com/posts/2013-08-13-vowpal-tutorial/

要安装大众系统,您可能需要先安装boost系统。

在 Mac OS 上,键入以下三个命令(如果您愿意,可以稍后重新chmod您的/usr/local/lib):

sudo chmod 777 /usr/local/lib
brew install boost
brew link boost

git clone git://github.com/JohnLangford/vowpal_wabbit.git
cd $VW_HOME
make
make test

你可能还想研究一下大众非常有趣的网络界面,可以在 https://github.com/eHarmony/vw-webservice 找到。要安装:

git clone https://github.com/eHarmony/vw-webservice.git
cd $VW_WEBSERVICE_HOME
mvn clean install package

3.7 Apache Mahout 中的可视化

Apache Mahout 具有基于java.awt图形包的内置集群可视化功能。聚类可视化的一个简单例子如图 3-2 所示。在可视化技术一章中,我们将讨论这个基本系统的扩展和替代方案,旨在提供更高级的可视化功能,扩展可视化控件和显示,以包括“作为大数据的图像”显示以及一些以 Mahout 为中心的仪表板。

A371868_1_En_3_Fig2_HTML.jpg

图 3-2。

A simple data point visualization using Apache Mahout

3.8 Apache Spark 库和组件

Apache Spark 库和组件对于本书中开发的 BDA 系统的开发是必不可少的。为了帮助开发人员,Spark 附带了 Python 交互式 shell 和 Scala 交互式 shell。随着本书的进展,我们将详细了解 Apache Spark,因为它是 Hadoop MapReduce 技术最有用的替代技术之一。在这一部分中,我们将提供对 Spark 技术及其生态系统的高水平概述。

3.8.1 多种不同的外壳可供选择

有许多 Python 和 Scala shells 可供选择,在 Java 9 中,我们可以期待一个基于 Java 的读取-评估-打印循环(REPL)。

要运行 Spark Python shell,请键入:

/bin/pyspark --master spark://server.com:7077 --driver-memory 4g --executor-memory 4g

要运行 Spark Scala shell,请键入:

./spark-1.2.0/bin/spark-shell --master spark://server.com:7077 --driver-memory 4g --executor-memory 4g

一旦你成功安装了sparkling-water包,你就可以使用如图 3-4 所示的闪亮外壳作为你的 Scala 外壳。为了方便起见,它已经有了一些到 Apache Spark 的方便挂钩。

3.8.2 Apache Spark 流

Spark Streaming 是一个容错、可伸缩和高吞吐量的流处理器。

Note

Apache 流正在积极开发中。关于 Spark 流的信息经常发生变化。请参考 http://spark.apache.org/docs/latest/streaming-programming-guide.html 以获取 Apache 流的最新信息。在本书中,我们主要指的是 Spark 1.5.1 版本。

要将 Spark 流添加到您的 Java 项目中,请将这个依赖项添加到您的pom.xml文件中(从 Spark 网站获取最新的版本参数以供使用):

<dependency>
    <groupId>org.apache.spark</groupId>
    <artifactId>spark-streaming_2.10</artifactId>
    <version>1.5.1</version>
</dependency>

图 3-3 中显示了 Spark 流系统的简图。输入数据流通过 Spark 引擎进行处理,并作为批量处理数据发出。

A371868_1_En_3_Fig3_HTML.jpg

图 3-3。

A simplified diagram of the Spark Streaming system

Spark Streaming 还兼容亚马逊 Kinesis ( https://aws.amazon.com/kinesis/ ),即 AWS 数据流平台。

3.8.3 苏打水和 H20 机器学习

苏打水(h20.ai)是 H20 机器学习工具包,集成到 Apache Spark 中。对于苏打水,您可以使用 Spark 数据结构作为 H20s 算法的输入,并且有一个 Python 接口允许您直接从 PyShe ll 使用苏打水。

A371868_1_En_3_Fig4_HTML.jpg

图 3-4。

Running the Sparkling Water shell to test your installation

3.9 组件使用和系统构建示例

在本节中,我们将使用 Solandra (Solr + Cassandra)系统作为构建 BDA 的简单示例,该系统具有执行大数据分析所需的所有要素。在第一章中,我们简要介绍了 Solr,一个开源的 RESTful 搜索引擎组件,它与 Hadoop 和卡珊德拉 NoSQL 数据库都兼容。我们的大部分设置可以使用 Maven 来完成,如清单 3-4 所示。您会注意到,这里列出的 pom 文件与我们最初的项目 pom 文件相同,增加了 Solr、Solandra 和 Cassandra 组件的依赖项。

  1. 从 Git 源( https://github.com/tjake/Solandra ):

    git clone https://github.com/tjake/Solandra.git
    
    

    下载 Solandra

  2. cd到 Solandra 目录,用 Maven:

    cd Solandra
    mvn -DskipTests clean install package
    
    

    创建 JAR 文件

  3. 将 JAR 文件添加到本地 Maven 存储库中,因为 Solandra 还没有标准的 Maven 依赖项:

    mvn install:install-file -Dfile=solandra.jar -DgroupId=solandra -DartifactId=solandra -Dpackaging=jar -Dversion=UNKNOWN
    
    
  4. 修改您的 BDA 系统pom.xml文件,并添加 Solandra 依赖项:

    <dependency>
            <groupId>org.apache.solr</groupId>
            <artifactId>solandra</artifactId>
            <version>UNKNOWN</version>
    </dependency>
    
    
  5. 测试你的新 BDA pom.xml :

    cd $BDA_HOME
    mvn clean install package
    
    

Building the Apache KAFKA Messaging System

在这一节中,我们将详细讨论如何设置和使用 Apache Kafka 消息传递系统,这是我们的示例 BDA 框架的一个重要组件。

  1. http://kafka.apache.org/downloads.html 下载阿帕奇卡夫卡 TAR 文件

  2. 设置KAFKA_HOME环境变量。

  3. 解压文件并转到KAFKA_HOME(在这种情况下KAFKA_HOME就是/Users/kerryk/Downloads/kafka_2.9.1-0.8.2.2)。

  4. 接下来,通过键入

    bin/zookeeper-server-start.sh  config/zookeeper.properties
    
    

    启动 ZooKeeper 服务器

  5. 一旦 ZooKeeper 服务启动并运行,输入:

    bin/kafka-server-start.sh config/server.properties
    
    
  6. 要测试主题创建,请键入:

    bin/kafka-topics.sh –create –zookeeper localhost:2181 –replication-factor 1 –partitions 1 –topic ProHadoopBDA0
    
    
  7. 要提供所有可用主题的列表,请键入:

    bin/kafka-topics.sh –list –zookeeper localhost:2181
    
    

    在这一阶段,结果将是ProHadoopBDA0,这是您在步骤 5 中定义的主题的名称。

  8. 从控制台发送一些消息来测试消息发送功能。键入:

    bin/kafka-console-producer.sh –broker-list localhost:9092 –topic ProHadoopBDA0
    
    

    现在在控制台中键入一些消息。

  9. 您可以通过修改适当的配置文件来配置多代理集群。查看 Apache Kafka 文档,了解如何实现这一点的分步过程。

3.10 示例系统的包装、测试和记录

在这一节中,我们将讨论 BDA 单元和集成测试。我们将讨论 Apache Bigtop ( bigtop.apache.com)和 Apache MRUnit ( mrunit.apache.com)。

import unittest

class TestStringMethods(unittest.TestCase):

  def test_upper(self):
      self.assertEqual('foo'.upper(), 'FOO')

  def test_isupper(self):
      self.assertTrue('FOO'.isupper())
      self.assertFalse('Foo'.isupper())

  def test_split(self):
      s = 'hello world'
      self.assertEqual(s.split(), ['hello', 'world'])
      # check that s.split fails when the separator is not a string

      with self.assertRaises(TypeError):
          s.split(2)

if __name__ == '__main__':
    unittest.main()

Listing 3-5.Example of Python unit testing
from 
https://docs.python.org/2/library/unittest.html

为了进行测试,整本书我们将使用来自 http://archive.ics.uci.edu/ml/machine-learning-databases/ 的测试数据集以及来自 http://www.dm.unibo.it/~simoncin/DATA.html 的博洛尼亚大学的数据库。对于 Python 测试,我们将使用 py unit(Java 单元测试 JUnit 框架的一个基于 Python 的版本)和 pytest ( pytest.org),一个替代的 Python 测试框架。清单 3-5 显示了 Python 测试组件的一个简单示例。

A371868_1_En_3_Fig5_HTML.jpg

图 3-5。

An architecture diagram for the “Sparkling Water” Spark + H20 System

3.11 摘要

在这一章中,我们使用了一个可扩展示例系统的第一部分来帮助激发我们关于基于 Hadoop 和 Spark 的大数据分析的标准库的讨论。我们还了解到,虽然有数不清的库、框架和工具包用于广泛的分布式分析领域,但是所有这些组件都可以通过小心使用良好的开发环境来驯服。我们选择了 Eclipse IDE、Scala 和 Python 插件支持,并使用 Maven、npm、easy_install 和 pip 构建工具来简化我们的工作并帮助组织我们的开发过程。仅使用 Maven 系统,我们就能够将大量工具集成到一个简单但功能强大的图像处理模块中,该模块拥有良好的 BDA 数据流水线应用程序的许多基本特征。

在本章中,我们反复回到了模块化设计的主题,展示了如何使用我们在第一章中讨论的标准十步流程来定义和构建各种数据管道系统。我们还了解了可用于帮助我们的库的类别,包括数学、统计、机器学习、图像处理和许多其他方面。我们详细讨论了如何安装和使用 Apache Kafka 消息传递系统,这是我们在本书其余部分的示例系统中使用的一个重要组件。

有许多语言绑定可用于这些大数据 Hadoop 包,但我们将讨论局限于 Java、Scala 和 Python 编程语言。如果应用程序需要,您可以自由使用其他语言绑定。

我们没有忽视我们的示例系统的测试和文档。虽然这些组件通常被视为“必要的邪恶”、“附加的”、“多余的”或“不必要的”,但是单元和集成测试仍然是任何成功的分布式系统的关键组件。我们讨论了 MRUnit 和 Apache Bigtop 作为评估 BDA 系统的可行测试工具。有效的测试和文档导致有效的剖析和优化,以及在许多其他方面的整体系统改进。

我们不仅学习了如何使用 Apache Mahout 构建以 Hadoop 为中心的 BDA,还学习了如何使用 Apache Spark 作为基础构建模块,使用 PySpark、MLlib、H20 和 Sparkling Water 库。用于机器学习和 BDA 构建的 Spark 技术现在是利用强大的机器学习、认知计算和自然语言处理库来构建和扩展您自己的 BDA 系统的成熟而有用的方法。

3.12 参考文献

贾科姆利,皮耶罗。阿帕奇看象人食谱。英国伯明翰。,派克特出版社,2013 年。

古普塔,阿希什。学习 Apache Mahout 分类。英国伯明翰。,派克特出版社,2015 年。

格兰杰、特雷和波特、蒂莫西。Solr 在行动。纽约州谢尔特岛:曼宁出版公司,2014 年。

穆罕默德·古勒。Spark 大数据分析:Spark 大规模数据分析实践指南。Apress/Springer 科学+商业媒体纽约,2015 年。

麦克肯多斯,迈克尔,哈奇,埃里克,还有高斯波德尼克,奥蒂斯。Lucene 在行动,第二版。纽约州谢尔特岛:曼宁出版公司,2010 年。

欧文、肖恩、安尼尔、罗伯特、邓宁、泰德和弗里德曼、艾伦。看象人在行动。纽约州谢尔特岛:曼宁出版公司,2011 年。

道格·特恩布尔和约翰·贝里曼。相关搜索:Solr 和 Elasticsearch 的应用。纽约州谢尔特岛:曼宁出版公司,2016 年。

四、关系数据库、NoSQL 数据库和图数据库

在本章中,我们描述了数据库在分布式大数据分析中的作用。数据库类型包括关系数据库、文档数据库、图数据库等,它们可以在我们的分析管道中用作数据源或接收器。这些数据库类型中的大多数都可以与 Hadoop 生态系统组件以及 Apache Spark 很好地集成。不同种类的数据库和 Hadoop/Apache Spark 分布式处理之间的连接可能由 Spring Data 或 Apache Camel 等“glueware”提供。我们描述了关系数据库,如 MySQL,NoSQL 数据库,如 Cassandra,图数据库,如 Neo4j,以及如何将它们与 Hadoop 生态系统集成。

有一系列数据库类型可供您使用,如图 4-1 所示。这些包括平面文件(甚至 CSV 文件也是一种数据库)、关系数据库(如 MySQL 和 Oracle)、关键值数据存储(如 Redis)、列数据库(如 HBase,Hadoop 生态系统的一部分)以及更奇特的数据库类型(如 graph 数据库,包括 Neo4J、GraphX 和 Giraph)

A371868_1_En_4_Fig1_HTML.jpg

图 4-1。

A spectrum of database types

我们可以将不同数据库类型的概念“抽象”为通用数据源,并提出一个公共 API 来连接、处理和输出这些数据源的内容。这让我们可以根据需要灵活地使用不同种类的数据库。有时有必要采用“即插即用”的方法进行评估,或者构建概念验证系统。在这些情况下,使用 NoSQL 数据库(如 MongoDB)并与 Cassandra 数据库甚至图数据库组件进行性能比较会很方便。评估后,根据您的需求选择合适的数据库。为此使用合适的 glueware,无论是 Apache Camel、Spring Data 还是 Spring Integration,都是构建可以快速更改的模块化系统的关键。glueware 的大部分代码可以保持与现有代码库相同或相似。如果胶制品选择得当,只需最少的返工。

上面显示的所有数据库类型都可以用作分布式系统数据源,包括关系数据库,如 MySQL 或 Oracle。使用关系数据源实现的典型的基于 ETL 的处理流程可能看起来像图 4-2 中所示的数据流。

  1. 循环开始。处理周期的开始是整个系统运行的入口部分。它是从哪里开始调度处理任务的参考点,也是系统必须重新启动时的返回点。
  2. 参考数据大楼。“引用数据”是指可以在单个表字段或键-值对的“值”部分中使用的有效数据类型。
  3. 源提取。从原始数据源中检索数据,并对数据进行任何必要的预处理。这可能是初步的数据清理或格式化步骤。
  4. 验证阶段。评估数据的一致性。
  5. 数据转换。对数据集执行“业务逻辑”操作以产生中间结果。
  6. 加载到临时表/数据缓存或存储库(如果使用的话)。临时表是中间数据存储区域,也可以是缓存或文档数据库。
  7. 报告审核(针对业务规则遵从性或诊断/修复阶段)。计算并格式化报告结果,导出为可显示的格式(可以是任何格式,从 CSV 文件到网页,再到复杂的交互式仪表板显示)。其他形式的报告可以指示数据处理的效率、定时和性能数据、系统健康数据等。这些辅助报告支持主报告任务,即一致地传达对原始数据源内容的数据分析操作的结果。
  8. 发布到目标表/存储库。到目前为止,结果被导出到指定的输出表或数据存储库,这些输出表或数据存储库可以采用多种形式,包括键/值缓存、文档数据库,甚至图数据库。
  9. 存档备份数据。拥有备份策略对于图数据和传统数据同样重要。复制、验证和高效恢复是必须的。
  10. 记录周期状态和错误。我们可以利用标准的日志结构,甚至在 Java 代码中的 Log4j 级别,或者我们可能希望在必要时使用更复杂的错误日志和报告。

A371868_1_En_4_Fig2_HTML.jpg

图 4-2。

Extract-Transform-Load (ETL) processing lifecycle

根据需要重复。您可以详细说明各个步骤,或者根据需要专门解决您的各个领域的问题。

4.1 图形查询语言:Cypher 和 Gremlin

Cypher ( http://neo4j.com/developer/cypher-query-language/ )和 Gremlin ( http://tinkerpop.incubator.apache.org/gremlin.html )是两种比较知名的图查询语言。大多数情况下,对于具有 SQL 风格查询语言背景的程序员来说,图形查询语言被设计得相对直观。图查询语言使用节点、边、关系和模式来形成关于被建模为图的数据集的断言和查询。有关 Gremlin 查询语言的更多信息,请参考 Apache TinkerPop 的网页( http://tinkerpop.incubator.apache.org )。

要使用新的 TinkerPop 3(撰写本书时正在酝酿项目),只需在 pom.xml 文件中包含以下依赖项:

<dependency>
  <groupId>org.apache.tinkerpop</groupId>
  <artifactId>gremlin-core</artifactId>
  <version>3.2.0-incubating</version>
</dependency>

一旦依赖关系在 Java 项目中就位,您就可以对 Java API 进行编程,如清单 4-1 和 4-2 所示。更多信息请参见在线文档: https://neo4j.com/developer/cypher-query-language/http://tinkerpop.incubator.apache.org

4.2 密码中的示例

要在 Cypher 中创建节点:

CREATE (kerry:Person {name:"Kerry"})

RETURN kerry

MATCH (neo:Database {name:"Neo4j"})

MATCH (arubo:Person {name:"Arubo"})

CREATE (anna)-[:FRIEND]->(:Person:Expert {name:"Arubo"})-[:WORKED_WITH]->(neo)

要使用 cURL 导出到 CSV 文件:

curl -H accept:application/json -H content-type:application/json \
     -d '{"statements":[{"statement":"MATCH (p1:PROFILES)-[:RELATION]-(p2) RETURN ... LIMIT 4"}]}' \
     http://localhost:7474/db/data/transaction/commit \
  | jq -r '(.results[0]) | .columns,.data[].row | @csv'

和计时性能,请使用

curl -H accept:application/json -H content-type:application/json \
     -d '{"statements":[{"statement":"MATCH (p1:PROFILES)-[:RELATION]-(p2) RETURN ..."}]}' \
     http://localhost:7474/db/data/transaction/commit \
     | jq -r '(.results[0]) | .columns,.data[].row | @csv' | /dev/null

4.3 Gremlin 中的示例

Gremlin 图形查询语言是 Cypher 的替代语言。

在图形中添加新顶点

g.addVertex([firstName:'Kerry',lastName:'Koitzsch',age:'50']); g.commit();

这将需要多个语句。注意变量(jdoe 和 mj)是如何定义的,只需从 Gremlin 查询中给它们赋值。

jdoe = g.addVertex([firstName:'John',lastName:'Doe',age:'25']);  mj = g.addVertex([firstName:'Mary',lastName:'Joe',age:'21']); g.addEdge(jdoe,mj,'friend'); g.commit();

在 id 为 1 和 2 的两个现有顶点之间添加关系

g.addEdge(g.v(1),g.v(2),'coworker'); g.commit();

从图形中移除所有顶点:

g.V.each{g.removeVertex(it)}
g.commit();

从图形中删除所有边

g.E.each{g.removeEdge(it)}
g.commit();

移除名字为' Kerry '的所有顶点

g.V('firstName','Kerry').each{g.removeVertex(it)}
g.commit();

移除 id 为 1 的顶点:

g.removeVertex(g.v(1));
g.commit();

移除 id 为 1 的边

g.removeEdge(g.e(1));
g.commit();

这是用您可能希望经常搜索的特定字段来索引图表。例如,“我的字段”

g.createKeyIndex("frequentSearch",Vertex.class);

也可以使用 TinkerPop 的 Java API 来构建图形。在这些例子中,我们将使用本书写作时的尖端版本(3-孵化)。

有关 TinkerPop 系统的详细讨论,请参见 http://tinkerpop.apache.org

出于管理数据的目的,参考数据由值集、状态代码或分类模式组成:这些是适用于事务的数据对象。例如,如果我们设想进行 ATM 取款交易,我们可以设想这种交易的相关状态代码,如“成功(S)”、“取消(CN)”、“资金不可用(FNA)、“卡已取消(CC)”等。

参考数据通常是统一的、全公司范围的,可以在一个国家内创建,也可以由外部标准化机构创建。某些类型的参考数据,如货币和货币代码,总是标准化的。其他的,比如一个组织内员工的职位,就不那么标准化了。

主数据和相关的事务数据被组合在一起,作为事务记录的一部分。

参考数据通常是高度标准化的,要么是在公司内部,要么是由为标准化目的而设立的外部机构提供的标准化代码。

与交易过程相关的数据对象被称为参考数据。这些对象可以是分类模式、值集或状态对象。

记录周期状态和错误可能非常简单,只需在编程的 Java 组件中设置“日志级别”,让基于程序的日志记录来完成剩下的工作,或者构建整个系统来完成复杂的日志记录、监控、警报和定制报告。当然,在大多数情况下,仅仅信任 Java 日志是不够的。

基于模型-视图-控制器(MVC)模式的简单图数据库应用程序如图 4-3 所示。图形查询语言可以是 Cypher 或 Gremlin,这是我们在本章前面讨论的两种图形查询语言。

A371868_1_En_4_Fig3_HTML.jpg

图 4-3。

MVC and graph database components

4.4 图数据库:Apache Neo4J

图数据库相对来说是 NoSQL 数据库领域的新人。Apache Neo4j 包(neo4j.org)是最流行和使用最广泛的图数据库之一。使用 Neo4j 的 Spring 数据组件( http://projects.spring.io/spring-data-neo4j/ ))可以很容易地将 Neo4j 图数据库集成到您的分布式分析应用程序中。只需确保 pom.xml Maven 文件中存在适当的依赖关系:

<dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-neo4j</artifactId>
        <version>4.1.1.RELEASE</version>
</dependency>

一定要记得提供正确的版本号,或者让它成为 pom.xml 标签中的属性之一。

在以 Hadoop 为中心的系统中,图数据库有很多用途。它们可以是中间结果存储库,保存计算的最终结果,甚至为仪表板组件提供一些相对简单的“开箱即用”的可视化功能,如图 4-4 所示。

A371868_1_En_4_Fig4_HTML.jpg

图 4-4。

Simple Neo4J data graph visualization

让我们尝试一个简单的加载和显示 Neo4j 程序来开始。该程序使用标准的 pom.xml,包含在本书包含的“大数据分析工具包”软件中:这个 pom.xml 包含运行我们程序所必需的依赖项,如清单 4-1 所示。

import org.neo4j.driver.v1.*;
public class Neo4JExample {
public static void main (String... args){
    // NOTE: on the next line, make sure you have a user defined with the appropriate password for your
    // authorization tokens.
    Driver driver = GraphDatabase.driver( "bolt://localhost", AuthTokens.basic( "neo4j", "datrosa2016" ) );
    Session session = driver.session();
    session.run( "CREATE (a:Person {name:'Kerry', role:'Programmer'})" );
    StatementResult result = session.run( "MATCH (a:Person) WHERE a.name = 'Kerry' RETURN a.name AS name, a.role AS role" );
    while ( result.hasNext() )
    {
        Record record = result.next();
        System.out.println( record.get( "role" ).asString() + " " + record.get("name").asString() );
    }
    System.out.println(".....Simple Neo4J Test is now complete....");
    session.close();
    driver.close();
}
}
Listing 4-1.package com.apress.probda.database;

4.5 关系数据库和 Hadoop 生态系统

关系数据库在 Hadoop 之前已经存在很长时间了,但它们与 Hadoop、Hadoop 生态系统以及 Apache Spark 非常兼容。我们可以使用 Spring Data JPA ( http://docs.spring.io/spring-data/jpa/docs/current/reference/html/ )将主流的关系数据库技术与分布式环境结合起来。Java Persistence API 是一个规范(用 Java 编写),用于管理、访问和持久化基于对象的 Java 数据和关系数据库,如 MySQL ( dev.mysql.com )。在这一节中,我们将使用 MySQL 作为关系数据库实现的例子。许多其他关系数据库系统可以用来代替 MySQL。

4.6 Hadoop 和统一分析(UA)组件

Apache Lens(lens.apache.org)是一种为 Hadoop 生态系统提供“统一分析”(UA)的新型组件,如图 4-5 所示。统一分析源于这样一种认识,即软件组件、语言方言和技术堆栈的激增使得至少部分分析任务的标准化变得至关重要。统一分析试图以同样的方式标准化数据访问语义,RESTful APIs 和语义 web 技术如 RDF(使用 RDF-REST: http://liris.cnrs.fr/~pchampin/rdfrest/ )和 OWL ( http://owlapi.hets.eu )提供标准化的语义。

A371868_1_En_4_Fig5_HTML.jpg

图 4-5。

Apache LENS architecture diagram

与我们在本书中讨论的大多数组件一样,Apache Lens 易于安装。下载网站的最新版本(我们的版本是 http://www.apache.org/dyn/closer.lua/lens/2.5-beta ),展开压缩的 TAR 文件,然后运行

mvn –DskipTests clean package

镜头系统,包括镜头 UI 组件,将会构建,包括如图 4-6 所示的 Apache 镜头 UI。

A371868_1_En_4_Fig6_HTML.jpg

图 4-6。

Apache LENS installed successfully using Maven on MacOSX

通过在任何浏览器中访问 localhost:8784 默认镜头网页来登录 Apache Lens。您的登录屏幕将出现如图 4-8 所示。

通过键入以下命令运行镜头 REPL:

./lens-cli.sh

你会看到类似图 4-7 的结果。在交互式 shell 中键入“help”以查看您可以尝试的 OLAP 命令列表。

A371868_1_En_4_Fig8_HTML.jpg

图 4-8。

Apache LENS login page .Use ‘admin’ for default username and ‘admin’ for default password.

A371868_1_En_4_Fig7_HTML.jpg

图 4-7。

Using the Apache Lens REPL

Apache Zeppelin ( https://zeppelin.incubator.apache.org )是一个基于 web 的多用途笔记本应用程序,支持数据摄取、发现和交互式分析操作。Zeppelin 兼容 Scala、SQL 和许多其他组件、语言和库。

A371868_1_En_4_Fig10_HTML.jpg

图 4-10。

Successful Maven build of the Zeppelin notebook

A371868_1_En_4_Fig9_HTML.jpg

图 4-9。

. Successfully running the Zeppelin browser UI

mvn clean package -Pcassandra-spark-1.5 -Dhadoop.version=2.6.0 -Phadoop-2.6DskipTests

然后

mvn verify

使用

bin/zeppelin-daemon.sh start

来启动 Zeppelin 服务器

bin/zeppelin-daemon.sh stop

停止齐柏林飞船的服务器。运行入门教程来测试在 https://zeppelin.apache.org/docs/0.6.0/quickstart/tutorial.html 使用齐柏林飞艇。Zeppelin 对于与 Apache Spark 应用程序以及 NoSQL 组件(如 Apache Cassandra)的接口特别有用。

A371868_1_En_4_Fig11_HTML.jpg

图 4-11。

Zeppelin-Lens-Cassandra architecture , with data sources

OLAP 在 Hadoop 生态系统中依然生机勃勃。例如,Apache Kylin ( http://kylin.apache.org )是用于 Hadoop 的开源 OLAP 引擎。Apache Kylin 支持分布式分析、内置安全性和交互式查询功能,包括 ANSI SQL 支持。

Apache Kylin 依赖 Apache 方解石( http://incubator.apache.org/projects/calcite.html )来提供一个“SQL 核心”

要使用 Apache 方解石,请确保 pom.xml 文件中有以下依赖项。

A371868_1_En_4_Fig12_HTML.jpg

图 4-12。

HSQLDB installation from the command line

<dependency>
        <groupId>org.apache.calcite</groupId>
        <artifactId>calcite-core</artifactId>
        <version>1.7.0</version>
</dependency>

要安装 HSQLDB 工具,只需执行

curl -L -O http://search.maven.org/remotecontent?filepath=org/hsqldb/sqltool/2.3.2/sqltool-2.3.2.jar

curl -L -O http://search.maven.org/remotecontent?filepath=org/hsqldb/hsqldb/2.3.2/hsqldb-2.3.2.jar

在命令行上。您应该会看到类似于图 4-13 的安装结果。如您所见,方解石与我们一直在谈论的许多数据库兼容。可以使用 Cassandra、Spark 和 Splunk 的组件。

A371868_1_En_4_Fig13_HTML.jpg

图 4-13。

Successful installation of Apache Calcite

4.7 总结

在本章中,我们讨论了各种数据库类型、可用的软件库以及如何以分布式方式使用数据库。应该强调的是,有很多数据库技术和库可以与 Hadoop 和 Apache Spark 一起使用。正如我们所讨论的,当将 BDA 系统与数据库技术集成时,Spring Data project、Spring Integration 和 Apache Camel 等“glueware”尤其重要,因为它们允许将分布式处理技术与更主流的数据库组件集成。由此产生的协同作用允许构建的系统利用关系、NoSQL 和图形技术来帮助实现业务逻辑、数据清理和验证、报告以及分析生命周期的许多其他部分。

我们讨论了两种最流行的图形查询语言,Cypher 和 Gremlin,并查看了一些简单的例子。我们看了看小精灵 REPL,在那里做了一些简单的操作。

当谈到图数据库时,我们将重点放在 Neo4j 图数据库上,因为它是一个易于使用的全功能包。不过请记住,有几个类似的包同样有用,包括 Apache Giraph (giraph.apache.org)、TitanDB ( http://thinkaurelius.github.io/titan/ )、OrientDB ( http://orientdb.com/orientdb/ )、Franz 的 AllegroGraph ( http://franz.com/agraph/allegrograph/ ))。

在下一章,我们将更详细地讨论分布式数据管道——它们的结构、必要的工具包,以及如何设计和实现它们。

4.8 参考文献

霍佩,格雷戈尔,和伍尔夫,鲍比。企业集成模式:设计、构建和部署消息传递解决方案。波士顿,麻州:艾迪生-卫斯理出版公司,2004 年。

易卜生,克劳斯,和斯特兰昌,詹姆斯。行动中的阿帕奇骆驼。纽约州谢尔特岛:曼宁出版公司,2010 年。

马尔泰拉,克罗迪奥,洛格西提斯,狄俄尼索斯,沙波什尼克,罗马。使用 Apache Giraph 的实用图形分析。纽约:新闻媒体,2015 年。

波拉克,马克,格尔克,奥利弗,里斯伯格,托马斯,布里斯班,约翰,和饥饿,迈克尔。Spring Data:企业 Java 的现代数据访问。塞瓦斯托波尔,加利福尼亚州:奥莱利媒体,2012 年。

拉杰索纳尔。Neo4J 高性能。英国伯明翰:PACKT 出版社,2015 年。

《七周七个数据库:现代数据库和 NoSQL 运动指南》。北卡罗来纳州罗利:务实的程序员,2012 年。

武科蒂奇,亚历克莎,瓦特,尼基。Neo4j 在行动。纽约州谢尔特岛:曼宁出版社,2015 年。

五、数据管道以及如何构建它们

在本章中,我们将讨论如何使用标准数据源和 Hadoop 生态系统构建基本的数据管道。我们提供了一个端到端的例子,说明如何使用 Hadoop 和其他分析组件来链接和处理数据源,以及这与标准 ETL 过程有何相似之处。我们将在第十五章更详细地阐述本章提出的观点。

A Note About the Example System Structure

由于我们将认真地开始开发示例系统,所以在这里对示例系统的包结构做一个说明是合适的。整本书中开发的示例系统的基本包结构如图 5-1 所示,附录 a 中也有再现。在进入数据管道构建之前,让我们简要检查一下包包含的内容及其作用。图 5-2 显示了 Probda 系统的一些主要子包的简要描述。

A371868_1_En_5_Fig2_HTML.jpg

图 5-2。

Brief description of the packages in the Probda example system

A371868_1_En_5_Fig1_HTML.jpg

图 5-1。

Fundamental package structure for the analytics system

在这一章中,我们将关注包com.apress.probda.pipeline中的类。

代码贡献中提供了五个基本 java 类,这将使您能够使用基本的数据管道策略来读取、转换和编写不同的数据源。有关更多详细信息,请参见代码贡献注释。

5.1 基础数据管道

一个基本的分布式数据管道可能看起来像图 5-3 中的架构图。

A371868_1_En_5_Fig3_HTML.jpg

图 5-3。

A basic data pipeline architecture diagram

我们可以使用标准的现成软件组件来实现这种类型的架构。

我们将使用 Apache Kafka、Beam、Storm、Hadoop、Druid 和 Gobblin(以前的 Camus)来构建我们的基本管道。

5.2 Apache Beam 简介

Apache Beam ( http://incubator.apache.org/projects/beam.html )是专门为构建数据管道而设计的工具包。它有一个统一的编程模型,并被设计成这样,因为我们在本书中的方法的核心是设计和构造分布式数据管道。无论是使用 Apache Hadoop、Apache Spark 还是 Apache Flink 作为核心技术,Apache Beam 都以一种非常符合逻辑的方式融入了技术堆栈。在写这本书的时候,Apache Beam 还是一个酝酿中的项目,所以请查看网页了解它的现状。

Apache 射束编程模型中的关键概念是:

  • “PCollection”:表示数据的集合,其大小可以是有界的或无界的
  • “PTransform”:表示将输入 PCollections 转换为输出 PCollections 的计算
  • “管道”:管理准备执行的 PTransforms 和 PCollections 的有向非循环图
  • “PipelineRunner”:指定管道应该在何处以及如何执行

这些基本元素可用于构建具有许多不同拓扑的管道,如清单 5-1 中的示例代码。

A371868_1_En_5_Fig4_HTML.jpg

图 5-4。

Successful Maven build of Apache Beam, showing the reactor summary

 static final String[] WORDS_ARRAY = new String[] {
 "probda analytics", "probda", "probda pro analytics",
 "probda one", "three probda", "two probda"};

 static final List<String> TEST_WORDS = Arrays.asList(WORDS_ARRAY);

 static final String[] WORD_COUNT_ARRAY = new String[] {
 "probda: 6", "one: 1", "pro: 1", "two: 1", "three: 1", "analytics: 2"};

 @Test
 @Category(RunnableOnService.class)
 public void testCountWords() throws Exception {
 Pipeline p = TestPipeline.create();

 PCollection<String> input = p.apply(Create.of(TEST_WORDS).withCoder(StringUtf8Coder.of()));

 PCollection<String> output = input.apply(new CountWords())
 .apply(MapElements.via(new FormatAsTextFn()));

 PAssert.that(output).containsInAnyOrder(WORD_COUNT_ARRAY);
 p.run().waitUntilFinish();
 }

cd to contribs/Hadoop and run the Maven file installation
    mvn clean package

Listing 5-1.Apache Beam test code snippet example

5.3 阿帕奇猎鹰简介

Apache Falcon(https://falcon.apache.org)是一个 feed 处理和 feed 管理系统,旨在使最终用户更容易在 Hadoop 集群上进行 feed 处理和执行 feed 管理。

Apache Falcon 提供了以下功能:

Apache Falcon ( https://falcon.apache.org ))可用于处理和管理 Hadoop 集群上的“feeds ”,从而提供一个管理系统,使实现 onboarding 和建立数据流变得更加简单。它还有其他有用的功能,包括:

  • 在 Hadoop 环境中建立各种数据和处理元素之间的关系
  • feed 管理服务,如 feed 保留、跨集群复制、归档等。
  • 易于采用新的工作流/管道,支持后期数据处理和重试策略
  • 与 metastore/目录(如 Hive/HCatalog)集成
  • 根据源组(相关源的逻辑组,可能会一起使用)的可用性向最终客户提供通知
  • 支持在 colo 和全局聚合中进行本地处理的用例
  • 捕获提要和进程的沿袭信息

5.4 数据源和接收器:使用 Apache Tika 构建管道

Apache Tika(tika.apache.org)是一个内容分析工具包。请参阅附录 a 中的 Apache Tika 安装说明。

使用 Apache Tika,几乎所有主流数据源都可以与分布式数据管道一起使用。

在本例中,我们将加载一种特殊的数据文件,采用 DBF 格式,使用 Apache Tika 处理结果,并使用 JavaScript 可视化工具观察我们的工作结果。

DBF 文件通常用于表示标准的数据库面向行的数据,如清单 5-2 所示。

Map: 26 has: 8 entries...
STATION-->Numeric
5203
MAXDAY-->Numeric
20
AV8TOP-->Numeric
9.947581
MONITOR-->Numeric
36203
LAT-->Numeric
34.107222
LON-->Numeric
-117.273611
X_COORD-->Numeric
474764.37263
Y_COORD-->Numeric
3774078.43207

DBF 文件通常用于表示标准的数据库面向行的数据,如清单 5-3 所示。

读取 DBF 文件的典型方法如清单 5-3 所示。

public static List<Map<String, Object>>readDBF(String filename){
                Charset stringCharset = Charset.forName("Cp866");
        List<Map<String,Object>> maps = new ArrayList<Map<String,Object>>();
                try {
                File file = new File(filename);
                DbfReader reader = new DbfReader(file);
                DbfMetadata meta = reader.getMetadata();
                DbfRecord rec = null;
                int i=0;
                while ((rec = reader.read()) != null) {
                        rec.setStringCharset(stringCharset);
                        Map<String,Object> map = rec.toMap();
                        System.out.println("Map: " + i + " has: " + map.size()+ " entries...");

                        maps.add(map);
                        i++;
                }
                reader.close();
                } catch (IOException e){ e.printStackTrace(); }
                catch (ParseException pe){ pe.printStackTrace(); }
                System.out.println("Read DBF file: " + filename + " , with : " + maps.size()+ " results...");
                return maps
}

goblin(http://gobblin.readthedocs.io/en/latest/))——原名加缪——是另一个基于我们之前谈到的“通用分析范式”的系统的例子。

“这里缺少一些东西:是一个通用的数据接收框架,用于从各种数据源(如数据库、rest APIs、FTP/SFTP 服务器、文件服务器等)提取、转换和加载大量数据。,到 Hadoop 上。Gobblin 处理所有数据摄取 ETL 所需的常见例行任务,包括作业/任务调度、任务划分、错误处理、状态管理、数据质量检查、数据发布等。Gobblin 在同一个执行框架中接收来自不同数据源的数据,并在一个地方管理不同来源的元数据。这一点,再加上其他特性,如自动可伸缩性、容错性、数据质量保证、可扩展性和处理数据模型演变的能力,使 Gobblin 成为一个易于使用、自助式和高效的数据摄取框架。”

图 5-5 显示了 Gobblin 系统的成功安装。

A371868_1_En_5_Fig5_HTML.jpg

图 5-5。

A successful installation of Gobblin

5.5 计算和转换

我们的数据流的计算和转换可以通过少量的简单步骤来执行。这部分处理管道有几个候选方案,包括 Splunk 和提供 Rocana Transform 的商业软件。

我们可以使用 Splunk 作为基础,也可以使用 Rocana Transform。Rocana 是一个商业产品,因此为了使用它,您可以购买它或使用免费的评估试用版。

Rocana ( https://github.com/scalingdata/rocana-transform-action-plugin ) Transform 是一个配置驱动的转换库,可以嵌入任何基于 JVM 的流处理或批处理系统,如 Spark Streaming、Storm、Flink 或 Apache MapReduce。

其中一个代码贡献示例展示了如何构建 Rocana 转换引擎插件,该插件可以在示例系统中执行事件数据处理。

在 Rocana 中,转换插件由两个重要的类组成,一个基于 Action 接口,另一个基于 ActionBuilder 接口,如代码贡献中所述。

5.6 可视化和报告结果

一些可视化和报告最好用面向笔记本的软件工具来完成。大多数基于 Python——比如 Jupyter 或 Zeppelin。回想一下,Python 生态系统看起来有点像图 5-6 。Jupyter 和 Zeppelin 将在“其他包和工具箱”标题下,但这并不意味着它们不重要。

A371868_1_En_5_Fig8_HTML.jpg

图 5-8。

Successful installation of the Anaconda Python system

A371868_1_En_5_Fig7_HTML.jpg

图 5-7。

Initial installer diagram for the Anaconda Python system

A371868_1_En_5_Fig6_HTML.jpg

图 5-6。

Basic Python ecosystem , with a place for notebook-based visualizers

在接下来的章节中,我们将会看到几个复杂的可视化工具包,但是现在让我们从一个更流行的基于 JavaScript 的工具包 D3 开始,它可以用来可视化各种各样的数据源和表示类型。这些包括地理位置和地图;标准饼图、折线图和条形图;表格报告;以及许多其他东西(定制的表示类型、图数据库输出等等)。

一旦 Anaconda 正常工作,我们就可以安装另一个非常有用的工具包 TensorFlow。TensorFlow ( https://www.tensorflow.org )是一个机器学习库,其中也包含对各种“深度学习”技术的支持。

A371868_1_En_5_Fig10_HTML.jpg

图 5-10。

Successfully installing Anaconda

A371868_1_En_5_Fig9_HTML.jpg

图 5-9。

Successfully running the Jupyter notebook program Note

回想一下,要构建 Zeppelin,请执行以下步骤:

mvn clean package -Pcassandra-spark-1.5 -Dhadoop.version=2.6.0 -Phadoop-2.6 -DskipTests

A371868_1_En_5_Fig11_HTML.jpg

图 5-11。

Sophisticated visualizations may be created using the Jupyter visualization feature .

5.7 总结

在本章中,我们讨论了如何构建一些基本的分布式数据管道,并概述了一些更有效的工具包、堆栈和策略来组织和构建您的数据管道。其中包括 Apache Tika、Gobblin、Spring Integration 和 Apache Flink。我们还安装了 Anaconda(这使得 Python 开发环境更容易设置和使用),以及一个重要的机器学习库 TensorFlow。

此外,我们还研究了各种输入和输出格式,包括古老但有用的 DBF 格式。

在下一章,我们将讨论使用 Lucene 和 Solr 的高级搜索技术,并介绍一些有趣的 Lucene 新扩展,如 ElasticSearch。

5.8 参考文献

Lewis,N.D .用 Python 一步步深度学习。2016.www.auscov.com

克里斯·马特曼和朱卡·齐汀。蒂卡在行动。纽约州谢尔特岛:曼宁出版公司,2012 年。

扎克内,吉安卡洛。TensorFlow 入门。英国伯明翰:PACKT 开源出版,2016 年。

六、Hadoop、Lucene 和 Solr 的高级搜索技术

在本章中,我们将描述 Apache Lucene 和 Solr 第三方搜索引擎组件的结构和使用,如何在 Hadoop 中使用它们,以及如何开发为分析应用程序定制的高级搜索功能。我们还将研究一些较新的基于 Lucene 的搜索框架,主要是 Elasticsearch,这是一个主要的搜索工具,特别适合构建分布式分析数据管道。我们还将讨论扩展的 Lucene/Solr 生态系统,以及一些如何在分布式大数据分析应用程序中使用 Lucene 和 Solr 的真实编程示例。

6.1 Lucene/SOLR 生态系统介绍

正如我们在第一章 Lucene 和 Solr 概述中所讨论的,Apache Lucene(lucene.apache.com)是构建定制搜索组件时需要了解的一项关键技术,这是有道理的。它是最古老的 Apache 组件之一,经历了很长时间才成熟。尽管年代久远,Lucene/Solr 项目一直是搜索技术中一些有趣的新发展的焦点。截至 2010 年,Lucene 和 Solr 已经合并为一个 Apache 项目。Lucene/Solr 生态系统的一些主要组件如图 6-1 所示。

A371868_1_En_6_Fig1_HTML.jpg

图 6-1。

The Lucene/SOLR ecosystem, with some useful additions

SolrCloud 是 Lucene/Solr 技术栈的新成员,它允许使用 RESTful 接口进行多核处理。要了解更多关于 SolrCloud 的信息,请访问信息页面 https://cwiki.apache.org/confluence/display/solr/SolrCloud

6.2 Lucene 查询语法

Lucene 查询在 Lucene 项目的生命周期中已经发展到包括一些对过去基本查询语法的复杂扩展。虽然 Lucene 查询语法可能会因版本而异(自 2001 年在 Apache 中引入以来已经有了很大的发展),但大多数功能和搜索类型保持不变,如表 6-1 所示。

表 6-1。

Lucene query types and how to use them

| 搜索组件的类型 | 句法 | 例子 | 描述 | | --- | --- | --- | --- | | 自由格式文本 | 单词或“短语” | `"to be or not to be"` | 不带引号的单词或带双引号的短语 | | 关键字搜索 | 字段名称:冒号值 | `city:Sunnyvale` | 要搜索的字段、冒号和要搜索的字符串 | | 助推 | 后跟提升值的术语或短语 | `term³` | 使用插入符号为术语提供新的提升值。 | | 通配符搜索 | 符号*可用于通配符。 | `*kerry` | 带有“*”或“?”的通配符搜索标志 | | 模糊搜索 | 使用波浪符号表示公制距离。 | `Hadoop∼` | 模糊搜索使用符号波浪号来表示使用 Levenschein 距离度量的接近程度。 | | 分组 | 普通括号提供分组。 | `(java or C)` | 使用括号提供子查询。 | | 字段分组 | 圆括号和冒号用于阐明查询字符串。 | `title:(+gift +"of the magi")` | 用字段名限定符分组,使用普通括号来提供分组 | | 范围搜索 | 字段名称和冒号,后跟范围子句 | `startDate:[20020101 TO 20030101]` `heroes:{Achilles TO Zoroaster}` | 方括号和允许构造 range 子句的关键字,例如{阿基里斯对琐罗亚斯德}。 | | 邻近搜索 | 术语颚化符接近值 | `Term∼` `10` | 近似搜索使用代字号符号来表示与匹配项的“接近程度”。 |

Installing Hadoop, Apache Solr, and NGDATA Lily

在这一节中,我们将简要概述如何安装 Hadoop、Lucene/Solr 和 NGData 的 Lily 项目,并建议一些“快速启动”技术来启动 Lily 安装并运行,以便进行开发和测试。

首先,安装 Hadoop。这是一个下载、解压缩、配置和运行的过程,类似于您在本书中遇到的许多其他过程。

当您成功安装和配置了 Hadoop,并设置了 HDFS 文件系统后,您应该能够执行一些简单的 Hadoop 命令,例如

hadoop fs –ls /

执行此操作后,您应该会看到类似于图 6-2 中的屏幕。

A371868_1_En_6_Fig2_HTML.jpg

图 6-2。

Successful test of installation of Hadoop and the Hadoop Distributed File System (HDFS)

第二,安装 Solr。这只是下载 zip 文件,解压缩,并刻录到二进制文件中,然后使用命令立即启动服务器。

Solr 的成功安装可以如图 6-3 所示进行测试。

A371868_1_En_6_Fig3_HTML.jpg

图 6-3。

A successful installation and start of the Solr server

第三,在 https://github.com/NGDATA/lilyproject 从 github 项目下载 NGDATA 的 Lily 项目。

让 Hadoop、Lucene、Solr 和 Lily 在同一个软件环境中协同工作可能会很棘手,因此我们提供了一些关于设置环境的技巧,这些技巧您可能已经忘记了。

Tips On Using HADOOP With SOLR and LUCENE

  1. 确保您可以使用“ssh”登录而无需密码。这是 Hadoop 正常工作的必要条件。时不时地测试一下你的 Hadoop 安装,以确保所有的活动组件都正常工作,这不会有什么坏处。只需几个命令,就可以在命令行上完成 Hadoop 功能的快速测试。例如:
  2. 确保您的环境变量设置正确,并适当配置您的 init 文件。这包括诸如你的。例如,如果您在 MacOS 上,bash_profile 文件。
  3. 经常测试组件交互。分布式系统中有许多移动组件。进行单独测试,以确保每个零件都能顺利工作。
  4. 在适当的时候,在独立、伪分布式和全分布式模式下测试交互。这包括调查可疑的性能问题、挂起、意外停止和错误,以及版本不兼容。
  5. 注意 pom.xml 中的版本不兼容性,并始终保持良好的 pom.xml 卫生。确保您的基础设施组件(如 Java、Maven、Python、npm、Node 和其他组件)是最新且兼容的。请注意:本书中的大多数示例使用 Java 8(并且一些示例依赖于 Java 8 中存在的高级特性),以及使用 Maven 3+。如有疑问,请使用 java 版本和 mvn 版本!
  6. 对您的整个技术体系进行“整体优化”。这包括 Hadoop、Solr 和数据源/接收器级别。识别瓶颈和资源问题。如果您在小型 Hadoop 集群上运行,请识别“问题硬件”,尤其是单个“问题处理器”。
  7. 经常在您的应用中使用多核功能。在复杂的应用程序中很少使用单个内核,所以要确保使用多个内核能够顺利工作。
  8. 虔诚地执行集成测试。
  9. 性能监控是必须的。使用标准的性能监控“脚本”,并根据以前的结果和当前的预期来评估性能。根据需要升级硬件和软件以改善性能结果,并重新监控以确保准确的分析。
  10. 不要忽视单元测试。在 https://wiki.apache.org/hadoop/HowToDevelopUnitTests 可以找到为当前版本的 Hadoop 编写单元测试的很好的介绍。

Apache Katta ( http://katta.sourceforge.net/about )是任何基于 Solr 的分布式数据管道架构的有用补充,并允许 Hadoop 索引到分片中,以及许多其他高级功能。

How to Install and Configure Apache Katta

  1. 从位于 https://sourceforge.net/projects/katta/files/ 的资源库下载 Apache Katta。解压文件。

  2. 将 Katta 环境变量添加到。bash_profile 文件(如果您在 MacOS 下运行),或者适当的启动文件(如果运行另一个版本的 Linux)。这些变量包括(请注意,这些只是示例;在这里替换您自己合适的路径值):

    export KATTA_HOME= /Users/kerryk/Downloads/kata-core-0.6.4
    
    

    并将 Katta 的二进制文件添加到路径中,这样您就可以直接调用它:

    export PATH=$KATTA_HOME/bin:$PATH
    
    
  3. Check to make sure the Katta process is running correctly by typing

    ps –al | grep katta
    
    

    on the command line. You should see an output similar to Figure 6-4.

    A371868_1_En_6_Fig4_HTML.jpg

    图 6-4。

    A successful initialization of the Katta Solr subsystem

  4. Successfully running the Katta component will produce results similar to those in Figure 6-4.

    A371868_1_En_6_Fig5_HTML.jpg

    图 6-5。

    Successful installation and run of Apache Katta screen

6.3 使用 SOLR 的编程示例

我们将通过一个完整的例子来使用 SOLR 加载、修改、评估和搜索我们从互联网上下载的标准数据集。我们将重点介绍 Solr 的几个特性。正如我们前面提到的,Solr 包含称为“核心”的独立数据存储库。每一个都可以有一个单独定义的模式与之相关联。Solr 内核可以在命令行上创建。

首先,从 URL http://samplecsvs.s3.amazonaws.com/SacramentocrimeJanuary2006.csv 下载样本数据集作为 csv 文件

您可以在下载文件夹中找到它,文件名为

yourDownLoadDirectory/SacramentocrimeJanuary2006.csv

使用以下命令创建新的 SOLR 核心:

./solr create –c crimecore1 –d basic_configs

如果您的核心创建成功,您将看到类似于图 6-2 中的屏幕。

A371868_1_En_6_Fig6_HTML.jpg

图 6-6。

Successful construction of a Solr core

通过在规范末尾添加正确的字段来修改模式文件 schema.xml。

<!— much more of the schema.xml file will be here -->

                                ............

<!--   you will now add the field specifications for the cdatetime,address,district,beat,grid,crimedescr,ucr_ncic_code,latitude,longitude
   fields found in the data file SacramentocrimeJanuary2006.csv
-->
    <field name="cdatetime" type="string" indexed="true" stored="true" required="true" multiValued="false" />  
    <field name="address" type="string" indexed="true" stored="true" required="true" multiValued="false" />  

    <field name="district" type="string" indexed="true" stored="true" required="true" multiValued="false" />  
<field name="beat" type="string" indexed="true" stored="true" required="true" multiValued="false" />  

<field name="grid" type="string" indexed="true" stored="true" required="true" multiValued="false" />  
<field name="crimedescr" type="string" indexed="true" stored="true" required="true" multiValued="false" />  

<field name="ucr_ncic_code" type="string" indexed="true" stored="true" required="true" multiValued="false" />  
<field name="latitude" type="string" indexed="true" stored="true" required="true" multiValued="false" />  

<field name="longitude" type="string" indexed="true" stored="true" required="true" multiValued="false" />  
   <field name="internalCreatedDate" type="date" indexed="true" stored="true" required="true" multiValued="false" />  

   <!--  the previous fields were added to the schema.xml file. Field type definition for currentcy is shown below  -->

    <fieldType name="currency" class="solr.CurrencyField" precisionStep="8" defaultCurrency="USD" currencyConfig="currency.xml" />

</schema>

通过向 CSV 文件的各个数据行添加关键字和附加数据,可以很容易地修改数据。清单 6-1 是这样一个 CSV 转换程序的简单例子。

通过向 CSV 文件添加唯一的键和创建日期来修改 Solr 数据。

清单 6-1 中显示了完成这项工作的程序。文件名将为com/apress/converter/csv/CSVConverter.java

向 CSV 数据集添加字段的程序几乎不需要解释。它逐行读取输入的 CSV 文件,向每行数据添加唯一的 ID 和日期字段。类中有两个助手方法,createInternalSolrDate()getCSVField()

在 CSV 数据文件中,标题和前几行如图 6-7 所示,如 Excel 所示。

A371868_1_En_6_Fig7_HTML.jpg

图 6-7。

Crime data CSV file . This data will be used throughout this chapter.

package com.apress.converter.csv;

import java.io.File;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.FileReader;

import java.io.FileWriter;

import java.io.IOException;

import java.io.LineNumberReader;

import java.text.DateFormat;

import java.text.SimpleDateFormat;

import java.util.ArrayList;

import java.util.Date;

import java.util.List;

import java.util.TimeZone;

import java.util.logging.Logger;

public class CSVConverter {
        Logger LOGGER = Logger.getAnonymousLogger();

        String targetSource = "SacramentocrimeJan2006.csv";
        String targetDest = "crime0.csv";

        /** Make a date Solr can understand from a regular oracle-style day string.
         *
         * @param regularJavaDate
         * @return

         */
        public String createInternalSolrDate(String regularJavaDate){
                if (regularJavaDate.equals("")||(regularJavaDate.equals("\"\""))){ return ""; }

                String answer = "";
                TimeZone tz = TimeZone.getTimeZone("UTC");
                DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'");
                df.setTimeZone(tz);
                try {
                answer = df.format(new Date(regularJavaDate));
                } catch (IllegalArgumentException e){
                        return "";
                }
                return answer

;
        }

        /** Get a CSV field in a CSV string by numerical index. Doesnt care if there are blank fields, but they count in the indices.
         *
         * @param s
         * @param fieldnum
         * @return

         */
        public String getCSVField(String s, int fieldnum){
                String answer = "";
                if (s != null) { s = s.replace(",,", ", ,");
                String[] them = s.split(",");
                int count = 0;
                for (String t : them){
                        if (fieldnum == count) answer = them[fieldnum];
                        count++;
                }        
                }
                return answer;
        }

        public CSVConverter()

{
                LOGGER.info("Performing CSV conversion for SOLR input");

                List<String>contents = new ArrayList<String>();
                ArrayList<String>result = new ArrayList<String>();
                String readline = "";
                LineNumberReader reader = null;
                FileOutputStream writer = null;
                try {
                         reader = new LineNumberReader(new FileReader(targetSource));
                         writer = new FileOutputStream (new File(targetDest));
                        int count = 0;
                        int thefield = 1;
                        while (readline != null){
                        readline = reader.readLine();
                        if (readline.split(","))<2){
                                LOGGER.info("Last line, exiting...");
                                break;
                        }
                        if (count != 0){
                                String origDate = getCSVField(readline, thefield).split(“ “)[0];
                                String newdate = createInternalSolrDate(origDate);
                                String resultLine = readline + "," + newdate+"\n";
                                LOGGER.info("===== Created new line: " + resultLine);
                                writer.write(resultLine.getBytes());
                                result.add(resultLine);
                        } else {
                                String resultLine = readline +",INTERNAL_CREATED_DATE\n";   // add the internal date for faceted search
                                writer.write(resultLine.getBytes());
                        }
                        count++;

                        LOGGER.info("Just read imported row: " + readline);
                        }
                } catch (FileNotFoundException e) {
                        e.printStackTrace();
                } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                }
                for (String line : contents){
                String newLine = "";        
                }
                try {
                reader.close();
                writer.close();
                } catch (IOException e){ e.printStackTrace(); }
                LOGGER.info("...CSV conversion complete...");
        }

        /** MAIN ROUTINE
         *
         * @param args
         */
        public static void main(String[] args){
                new CSVConverter(args[0], args[1]);
        }

}

Listing 6-1.Java source code for CSVConverter.java.

通过键入以下命令编译该文件:

javac com/apress/converter/csv/CSVConverter.java

如上所述正确设置 CSV 转换程序后,您可以通过键入

java com.apress.converter.csv.CSVConverter inputcsvfile.csv outputcsvfile.csv

将修改后的数据发布到 SOLR 核心:

./post –c crimecore1 ./modifiedcrimedata2006.csv

既然我们已经将数据发送到 Solr 核心,我们可以在 Splr 仪表板中检查数据集。为此,请转到 localhost:8983。您应该会看到类似于图 6-4 中的屏幕。

A371868_1_En_6_Fig8_HTML.jpg

图 6-8。

Initial Solr dashboard

我们还可以评估来自我们在本章前面创建的 Solandra 核心的数据,如图 _ _。

现在,从核心选择器下拉列表中选择 crimedata0 核心。单击 query,将输出格式(“wt”参数下拉菜单)更改为 csv,这样您就可以一次看到几行数据。您将看到类似于图 6-9 中的数据显示。

A371868_1_En_6_Fig10_HTML.jpg

图 6-10。

Result of Solr query using the dashboard (Sacramento crime data core)

A371868_1_En_6_Fig9_HTML.jpg

图 6-9。

Result of Solr query , showing the JSON output format

由于 Solr 的 RESTful 接口,我们可以通过仪表板(符合前面讨论的 Lucene 查询语法)或在命令行上使用 CURL 实用程序进行查询。

6.4 使用 ELK 堆栈(Elasticsearch、Logstash 和 Kibana)

正如我们之前提到的,Lucene、Solr 和 Nutch 都有替代品。根据系统的整体架构,您可以使用各种技术栈、语言、集成和插件助手库以及功能。其中一些组件可能使用 Lucene 或 Solr,或者通过集成助手库(如 Spring Data、Spring MVC 或 Apache Camel 等)与 Lucene/Solr 组件兼容。图 6-6 显示了一个替代基本 Lucene 堆栈的例子,称为“ELK 堆栈”。

elastic search(elasticsearch.org)是一个分布式高性能搜索引擎。在引擎盖下,Elasticsearch 使用 Lucene 作为核心组件,如图 6-3 所示。Elasticsearch 是 SolrCloud 的强大竞争对手,易于扩展、维护、监控和部署。

为什么会用 Elasticsearch 而不是 Solr?仔细查看 Solr 和 Elasticsearch 的特性矩阵可以发现,在许多方面,这两个工具包具有相似的功能。它们都利用了 Apache Lucene。Solr 和 Elasticsearch 都可以使用 JSON 作为数据交换格式,虽然 Solr 也支持 XML。

表 6-2。

Feature comparison table of Elasticsearch features vs. Apache Solr features

|   | 数据 | 可扩展置标语言 | 战斗支援车 | HTTP REST | 管理扩展 | 客户端库 | Lucene 查询解析 | 独立分布式集群 | 分片 | 形象化 | Web 管理界面 | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | | 使用 | X | X | X | X | X | 爪哇 | X |   | X | 吉婆那港(香蕉) |   | | 弹性搜索 | X |   |   | X |   | Java Python Javascript | X | X | X | 马纳人 |   |

log stash(logstash.net)是一个有用的应用程序,允许将各种不同类型的数据导入到 Elasticsearch 中,包括 CSV 格式的文件和普通的“日志格式”文件。基巴纳( https://www.elastic.co/guide/en/kibana/current/index.html )是一个开放源码的可视化组件,允许定制。Elasticsearch、Logstash 和 Kibana 一起构成了所谓的“ELK stack”,主要用于。在这一节中,我们将看一个运行中的 ELK 堆栈的小例子。

A371868_1_En_6_Fig12_HTML.jpg

图 6-12。

ELK stack in use: Elasticsearch search engine/pipeline architecture diagram

A371868_1_En_6_Fig11_HTML.jpg

图 6-11。

The so-called “ELK stack ”: Elasticsearch, Logstash, and Kibana visualization Installing Elasticsearch, Logstash, and Kibana

安装和试用 ELK 堆栈再简单不过了。如果你已经阅读了本书的介绍性章节,这是一个熟悉的过程。按照以下三个步骤安装和测试 ELK 堆栈:

  1. Download Elasticsearch from https://www.elastic.co/downloads/elasticsearch . Unzip the downloaded file to a convenient staging area. Then,

    cd $ELASTICSEARCH_HOME/bin/
    ./elasticsearch
    
    

    Elasticsearch will start up successfully with a display similar to that in Figure 6-3.

    A371868_1_En_6_Fig13_HTML.jpg

    图 6-13。

    Successful start-up of the Elasticsearch server from the binary directory Use the following Java program to import the crime data CSV file (or, with a little modification, any CSV formatted data file you wish):

    public static void main(String[] args)
        {
            System.out.println( "Import crime data" );
            String originalClassPath = System.getProperty("java.class.path");
            String[] classPathEntries = originalClassPath.split(";");
            StringBuilder esClasspath = new StringBuilder();
            for (String entry : classPathEntries) {
            if (entry.contains("elasticsearch") || entry.contains("lucene")) {
            esClasspath.append(entry);
            esClasspath.append(";");
            }
            }
            System.setProperty("java.class.path", esClasspath.toString());
            System.setProperty("java.class.path", originalClassPath);
            System.setProperty("es.path.home", "/Users/kerryk/Downloads/elasticsearch-2.3.1");
            String file = "SacramentocrimeJanuary2006.csv";
            Client client = null;
            try {
    
            client = TransportClient.builder().build()
             .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("localhost"), 9300));
    
            int numlines = 0;
            XContentBuilder builder = null;
    
            int i=0;
    
            String currentLine = "";
            BufferedReader br = new BufferedReader(new FileReader(file));
    
                while ((currentLine = br.readLine()) != null) {
                if (i > 0){
                System.out.println("Processing line: " + currentLine);
            String[] tokens = currentLine.split(",");
            String city = "sacramento";
            String recordmonthyear = "jan2006";
            String cdatetime = tokens[0];
            String address = tokens[1];
            String district = tokens[2];
            String beat = tokens[3];
            String grid = tokens[4];
            String crimedescr = tokens[5];
            String ucrnciccode = tokens[6]
    
    ;
            String latitude = tokens[7];
            String longitude = tokens[8];
            System.out.println("Crime description = " + crimedescr);
            i=i+1;
            System.out.println("Index is: " + i);
            IndexResponse response = client.prepareIndex("thread", "answered", "400"+new Integer(i).toString()).setSource(
    
            jsonBuilder()
            .startObject()
            .field("cdatetime", cdatetime)
            .field("address", address)
            .field("district", district)
            .field("beat", beat)
            .field("grid", grid)
            .field("crimedescr", crimedescr)
            .field("ucr_ncic_code", ucrnciccode)
            .field("latitude", latitude)
            .field("longitude", longitude)
            .field("entrydate", new Date())
            .endObject())
            .execute().actionGet();
    
                } else {
                    System.out.println("Ignoring first line...");
                    i++;
                }
            }
    
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
    
            }
            }
    
    

    Run the program in Eclipse or in the command line. You will see a result similar to the one in Figure 6-14. Please note that each row of the CSV is entered as a set of fields into the Elasticsearch repository. You can also select the index name and index type by changing the appropriate strings in the code example.

    A371868_1_En_6_Fig14_HTML.jpg

    图 6-14。

    Successful test of an Elasticsearch crime database import from the Eclipse IDE You can test the query capabilities of your new Elasticsearch set-up by using ‘curl’ on the command line to execute some sample queries, such as:

    A371868_1_En_6_Fig16_HTML.jpg

    图 6-16。

    Successful test of an Elasticsearch crime database query from the command line

    A371868_1_En_6_Fig15_HTML.jpg

    图 6-15。

    You can see the schema update logged in the Elasticsearch console

  2. Download Logstash from https://www.elastic.co/downloads/logstash . Unzip the downloaded file to the staging area.

    cd <your logstash staging area, LOGSTASH_HOME>
    
    

    After entering some text, you will see an echoed result similar to Figure 6-6.

    A371868_1_En_6_Fig17_HTML.jpg

    图 6-17。

    Testing your Logstash installation . You can enter text from the command line. You will also need to set up a configuration file for use with Logstash. Follow the directions found at  to make a configuration file such as the one shown in Listing 6-2.

    input { stdin { } }
    
    filter {
      grok {
        match => { "message" => "%{COMBINEDAPACHELOG}" }
      }
      date {
        match => [ "timestamp" , "dd/MMM/yyyy:HH:mm:ss Z" ]
      }
    }
    
    output {
      elasticsearch { hosts => ["localhost:9200"] }
      stdout { codec => rubydebug }
    }
    
    Listing 6-2.Typical Logstash configuration file
    
    listing
    
    
  3. Download Kibana from https://www.elastic.co/downloads/kibana . Unzip the downloaded file to the staging area. In a similar way to starting the Elasticsearch server:

    A371868_1_En_6_Fig18_HTML.jpg

    图 6-18。

    Successful start-up of the Kibana visualization component from its binary directory

      cd bin
    ./kibana
    
    

    You can easily query for keywords or more complex queries interactively using the Kibana dashboard as shown in Figure 6-19.

    A371868_1_En_6_Fig20_HTML.jpg

    图 6-20。

    Kibana dashboard example: highlighted search for “FRAUD.”

    A371868_1_En_6_Fig19_HTML.jpg

    图 6-19。

    Kibana dashboard example with crime dataset Add this schema for the crime data to Elasticsearch with this cURL command:

    curl -XPUT http://localhost:9200/crime2 -d '
    { "mappings" :
    { "crime2" : { "properties" : { "cdatetime" : {"type" : "string"}, "address" : {"type": "string"}, "district" : {"type" : "string"}, "beat": {"type" : "string"}, "grid": {"type" : "string"}, "crimedescr" : {"type": "string"}, "ucr_ncic_code": {"type": "string"},"latitude": {"type" : "string"}, "longitude": {"type" : "string"}, "location": {"type" : "geo_point"}}  
    } } }'
    
    

    Notice the “location” tag in particular, which has a geo_point-type definition. This allows Kibana to identify the physical location on a map for visualization purposes , as shown in Figure 6-21.

    A371868_1_En_6_Fig21_HTML.jpg

    图 6-21。

    The crime data for Sacramento as a visualization in Kibana

图 6-21 是理解复杂数据集的一个很好的例子。我们可以立即用红色标出“高犯罪率”地区。

6.5 Solr 与 ElasticSearch:特征和逻辑

在本节中,我们将在一个使用 Elasticsearch 的代码示例中使用所谓的 CRUD 操作(创建、替换、更新和删除方法,以及一个附加的搜索实用程序方法)作为示例。

package com.apress.main;

import java.io.IOException;

import java.util.Date;

import java.util.HashMap;

import java.util.Map;

import org.elasticsearch.action.delete.DeleteResponse;

import org.elasticsearch.action.get.GetResponse;

import org.elasticsearch.action.search.SearchResponse;

import org.elasticsearch.action.search.SearchType;

import org.elasticsearch.client.Client;

import static org.elasticsearch.index.query.QueryBuilders.fieldQuery;

import org.elasticsearch.node.Node;

import static org.elasticsearch.node.NodeBuilder.nodeBuilder;

import org.elasticsearch.search.SearchHit;

/**
 *
 * @author kerryk
 */

public class ElasticSearchMain {

          public static final String INDEX_NAME = "narwhal";
          public static final String THEME_NAME = "messages";

    public static void main(String args[]) throws IOException{

        Node node     = nodeBuilder().node();
        Client client = node.client();

        client.prepareIndex(INDEX_NAME, THEME_NAME, "1")
              .setSource(put("ElasticSearch: Java",
                                         "ElasticSeach provides Java API, thus it executes all operations " +
                                          "asynchronously by using client object..",
                                         new Date(),
                                         new String[]{"elasticsearch"},
                                         "Kerry Koitzsch", "iPad", "Root")).execute().actionGet();

        client.prepareIndex(INDEX_NAME, THEME_NAME, "2")
              .setSource(put("Java Web Application and ElasticSearch (Video)",
                                         "Today, here I am for exemplifying the usage of ElasticSearch which is an open source, distributed " +
                                         "and scalable full text search engine and a data analysis tool in a Java web application.",
                                         new Date(),
                                         new String[]{"elasticsearch"},
                                         "Kerry Koitzsch", "Apple TV", "Root")).execute().actionGet();

        get(client, INDEX_NAME, THEME_NAME, "1");

        update(client, INDEX_NAME, THEME_NAME, "1", "title", "ElasticSearch: Java API");
        update(client, INDEX_NAME, THEME_NAME, "1", "tags", new String[]{"bigdata"});

        get(client, INDEX_NAME, THEME_NAME, "1");

        search(client, INDEX_NAME, THEME_NAME, "title", "ElasticSearch");

        delete(client, INDEX_NAME, THEME_NAME, "1");

        node.close();
    }

    public static Map<String, Object> put(String title, String content, Date postDate,
                                                      String[] tags, String author, String communityName, String parentCommunityName){

        Map<String, Object> jsonDocument = new HashMap<String, Object>();

        jsonDocument.put("title", title);
        jsonDocument.put("content", content);
        jsonDocument.put("postDate", postDate);
        jsonDocument.put("tags", tags);
        jsonDocument.put("author", author);
        jsonDocument.put("communityName", communityName);
        jsonDocument.put("parentCommunityName", parentCommunityName);
        return jsonDocument;
    }

    public static void get(Client client, String index, String type, String id){

        GetResponse getResponse = client.prepareGet(index, type, id)
                                        .execute()
                                        .actionGet();
        Map<String, Object> source = getResponse.getSource();

        System.out.println("------------------------------");
        System.out.println("Index: " + getResponse.getIndex());
        System.out.println("Type: " + getResponse.getType());
        System.out.println("Id: " + getResponse.getId());
        System.out.println("Version: " + getResponse.getVersion());
        System.out.println(source);
        System.out.println("------------------------------");

    }

    public static void update(Client client, String index, String type,
                                      String id, String field, String newValue){

        Map<String, Object> updateObject = new HashMap<String, Object>();
        updateObject.put(field, newValue);

        client.prepareUpdate(index, type, id)
              .setScript("ctx._source." + field + "=" + field)
              .setScriptParams(updateObject).execute().actionGet();
    }

    public static void update(Client client, String index, String type,
                                      String id, String field, String[] newValue){

        String tags = "";
        for(String tag :newValue)
            tags += tag + ", ";

        tags = tags.substring(0, tags.length() - 2);

        Map<String, Object> updateObject = new HashMap<String, Object>();
        updateObject.put(field, tags);

        client.prepareUpdate(index, type, id)
                .setScript("ctx._source." + field + "+=" + field)
                .setScriptParams(updateObject).execute().actionGet();
    }

    public static void search(Client client, String index, String type,
                                      String field, String value){

        SearchResponse response = client.prepareSearch(index)
                                        .setTypes(type)
                                        .setSearchType(SearchType.QUERY_AND_FETCH)
                                        .setQuery(fieldQuery(field, value))
                                        .setFrom(0).setSize(60).setExplain(true)
                                        .execute()
                                        .actionGet();

        SearchHit[] results = response.getHits().getHits();

        System.out.println("Current results: " + results.length);
        for (SearchHit hit : results) {
            System.out.println("------------------------------");
            Map<String,Object> result = hit.getSource();   
            System.out.println(result);
        }
    }

    public static void delete(Client client, String index, String type, String id){

        DeleteResponse response = client.prepareDelete(index, type, id).execute().actionGet();
        System.out.println("===== Information on the deleted document:");
        System.out.println("Index: " + response.getIndex());
        System.out.println("Type: " + response.getType());
        System.out.println("Id: " + response.getId());
        System.out.println("Version: " + response.getVersion());
    }
}

Listing 6-3.
CRUD operations

for  Elasticsearch example

为搜索组件定义 CRUD 操作是定制组件如何“适应”系统其余部分的整体架构和逻辑的关键。

6.6 带有 Elasticsearch 和 Solr 的 Spring 数据组件

在这一节中,我们将开发一个代码示例,它使用 Spring 数据来实现同类组件,使用 Solr 和 Elasticsearch 作为“幕后”使用的搜索框架。

您可以为 pom.xml 文件分别定义 Elasticsearch 和 Solr 两个属性,如下所示:

<spring.data.elasticsearch.version>2.0.1.RELEASE</spring.data.elasticsearch.version>
<spring.data.solr.version>2.0.1.RELEASE</spring.data.solr.version>

<dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-elasticsearch</artifactId>
        <version>2.0.1.RELEASE</version>
</dependency>
and
<dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-solr</artifactId>
        <version>2.0.1.RELEASE</version>
</dependency>

我们现在可以开发基于 Spring 数据的代码示例,如清单 6-5 和清单 6-6 所示。

package com.apress.probda.solr.search;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import com.apress.probda.context.config.SearchContext;
import com.apress.probda.context.config.WebContext;
@Configuration
@ComponentScan
@EnableAutoConfiguration
@Import({ WebContext.class, SearchContext.class })
public class Application {
        public static void main(String[] args) {
                SpringApplication.run(Application.class, args);
        }
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.solr.repository.config.EnableSolrRepositories;

@Configuration
@EnableSolrRepositories(basePackages = { "org.springframework.data.solr.showcase.product" }, multicoreSupport = true)
public class SearchContext {

        @Bean
        public SolrServer solrServer(@Value("${solr.host}") String solrHost) {
                return new HttpSolrServer(solrHost);
        }

}

File: WebContext.java

import java.util.List;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.web.PageableHandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

/**
 * @author kkoitzsch
 */
@Configuration
public class WebContext {
        @Bean
        public WebMvcConfigurerAdapter mvcViewConfigurer() {
                return new WebMvcConfigurerAdapter() {
                        @Override
                        public void addViewControllers(ViewControllerRegistry registry) {

                                registry.addViewController("/").setViewName("search");
                                registry.addViewController("/monitor").setViewName("monitor");
                        }
                        @Override
                        public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
                                argumentResolvers.add(new PageableHandlerMethodArgumentResolver());
                        }
                };
        }
}

Listing 6-4.
NLP program
—main() executable method

public static void main(String[] args) throws IOException {
        String text = "The World is a great place";
        Properties props = new Properties();
        props.setProperty("annotators", "tokenize, ssplit, pos, lemma, parse, sentiment");
        StanfordCoreNLP pipeline = new StanfordCoreNLP(props);

        Annotation annotation = pipeline.process(text);
        List<CoreMap> sentences = annotation.get(CoreAnnotations.SentencesAnnotation.class);
        for (CoreMap sentence : sentences) {
            String sentiment = sentence.get(SentimentCoreAnnotations.SentimentClass.class);
            System.out.println(sentiment + "\t" + sentence);
        }
    }

Listing 6-5.Spring Data code example using Solr

package com.apress.probda.search.elasticsearch;

import com.apress.probda.search.elasticsearch .Application;

import com.apress.probda.search.elasticsearch .Post;

import com.apress.probda.search.elasticsearch.Tag;

import com.apress.probda.search.elasticsearch.PostService;

import org.junit.Before;

import org.junit.Test;

import org.junit.runner.RunWith;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.test.SpringApplicationConfiguration;

import org.springframework.data.domain.Page;

import org.springframework.data.domain.PageRequest;

import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;

import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.Arrays;

import static org.hamcrest.CoreMatchers.notNullValue;

import static org.hamcrest.core.Is.is;

import static org.junit.Assert.assertThat;

@RunWith(SpringJUnit4ClassRunner.class)

@SpringApplicationConfiguration(classes = Application.class)

public class PostServiceImplTest{

    @Autowired

    private PostService postService;

    @Autowired

    private ElasticsearchTemplate elasticsearchTemplate;

    @Before

    public void before() {

        elasticsearchTemplate.deleteIndex(Post.class);

        elasticsearchTemplate.createIndex(Post.class);

        elasticsearchTemplate.putMapping(Post.class);

        elasticsearchTemplate.refresh(Post.class, true);

    }

    //@Test

    public void testSave() throws Exception {

        Tag tag = new Tag();

        tag.setId("1");

        tag.setName("tech");

        Tag tag2 = new Tag();

        tag2.setId("2");

        tag2.setName("elasticsearch");

        Post post = new Post();

        post.setId("1");

        post.setTitle("Bigining with spring boot application and elasticsearch");

        post.setTags(Arrays.asList(tag, tag2));

        postService.save(post);

        assertThat(post.getId(), notNullValue());

        Post post2 = new Post();

        post2.setId("1");

        post2.setTitle("Bigining with spring boot application");

        post2.setTags(Arrays.asList(tag));

        postService.save(post);

        assertThat(post2.getId(), notNullValue());

    }

    public void testFindOne() throws Exception {

    }

    public void testFindAll() throws Exception {

    }

    @Test

    public void testFindByTagsName() throws Exception {

        Tag tag = new Tag();

        tag.setId("1");

        tag.setName("tech");

        Tag tag2 = new Tag();

        tag2.setId("2");

        tag2.setName("elasticsearch");

        Post post = new Post();

        post.setId("1");

        post.setTitle("Bigining with spring boot application and elasticsearch");

        post.setTags(Arrays.asList(tag, tag2));

        postService.save(post);

        Post post2 = new Post();

        post2.setId("1");

        post2.setTitle("Bigining with spring boot application");

        post2.setTags(Arrays.asList(tag));

        postService.save(post);

        Page<Post> posts  = postService.findByTagsName("tech", new PageRequest(0,10));

        Page<Post> posts2  = postService.findByTagsName("tech", new PageRequest(0,10));

        Page<Post> posts3  = postService.findByTagsName("maz", new PageRequest(0,10));

       assertThat(posts.getTotalElements(), is(1L));

        assertThat(posts2.getTotalElements(), is(1L));

        assertThat(posts3.getTotalElements(), is(0L));

    }

}

Listing 6-6.Spring Data code example using Elasticsearch (unit test)

6.7 使用 LingPipe 和 GATE 进行定制搜索

在这一节中,我们将回顾一对有用的分析工具,它们可以与 Lucene 和 Solr 一起使用,以增强分布式分析应用程序中的自然语言处理(NLP)分析能力。LingPipe ( http://alias-i.com/lingpipe/ )和 GATE(文本工程通用架构, https://gate.ac.uk )可用于为分析系统增加自然语言处理能力。基于 NLP 的分析系统的典型架构可能类似于图 6-22 。

A371868_1_En_6_Fig22_HTML.jpg

图 6-22。

NLP system architecture , using LingPipe, GATE, and NGDATA Lily

自然语言处理系统可以以类似于任何其他分布式流水线系统的方式来设计和构建。唯一的区别是针对数据和元数据本身的特殊性质进行了必要的调整。LingPipe、GATE、Vowpal Wabbit 和 StanfordNLP 允许处理、解析和“理解”文本,Emir/Caliph、ImageTerrier 和 HIPI 等软件包提供了分析和索引基于图像和信号的数据的功能。你可能还希望添加一些软件包来帮助地理定位,比如 SpatialHadoop ( http://spatialhadoop.cs.umn.edu ),这将在第十四章中详细讨论。

GATE 可以处理各种输入格式,包括原始文本、XML、HTML 和 PDF 文档,以及关系数据/JDBC 中介数据。这包括从 Oracle、PostgreSQL 等导入的数据。

Apache Tika 导入组件可能如清单 6-7 中所示实现。

Package com.apress.probda.io;

import java.io.*;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.apress.probda.pc.AbstractProbdaKafkaProducer;
import org.apache.commons.lang3.StringUtils;
import org.apache.tika.exception.TikaException;
import org.apache.tika.io.TikaInputStream;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.metadata.serialization.JsonMetadata;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.parser.Parser;
import org.apache.tika.parser.isatab.ISArchiveParser;
import org.apache.tika.sax.ToHTMLContentHandler;
import org.dia.kafka.solr.consumer.SolrKafkaConsumer;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;

import static org.dia.kafka.Constants.*;

public class ISAToolsKafkaProducer extends AbstractKafkaProducer {

    /**
     * Tag for specifying things coming out of LABKEY
     */
    public final static String ISATOOLS_SOURCE_VAL = "ISATOOLS";
    /**
     * ISA files default prefix
     */
    private static final String DEFAULT_ISA_FILE_PREFIX = "s_";
    /**
     * Json jsonParser to decode TIKA responses
     */
    private static JSONParser jsonParser = new JSONParser();
    ;

    /**
     * Constructor
     */
    public ISAToolsKafkaProducer(String kafkaTopic, String kafkaUrl) {
        initializeKafkaProducer(kafkaTopic, kafkaUrl);
    }

    /**
     * @param args
     */
    public static void main(String[] args) throws IOException {
        String isaToolsDir = null;
        long waitTime = DEFAULT_WAIT;
        String kafkaTopic = KAFKA_TOPIC;
        String kafkaUrl = KAFKA_URL;

        // TODO Implement commons-cli
        String usage = "java -jar ./target/isatools-producer.jar [--tikaRESTURL <url>] [--isaToolsDir <dir>] [--wait <secs>] [--kafka-topic <topic_name>] [--kafka-url]\n";

        for (int i = 0; i < args.length - 1; i++) {
            if (args[i].equals("--isaToolsDir")) {
                isaToolsDir = args[++i];
            } else if (args[i].equals("--kafka-topic")) {
                kafkaTopic = args[++i];
            } else if (args[i].equals("--kafka-url")) {
                kafkaUrl = args[++i];
            }
        }

        // Checking for required parameters
        if (StringUtils.isEmpty(isaToolsDir)) {
            System.err.format("[%s] A folder containing ISA files should be specified.\n", ISAToolsKafkaProducer.class.getSimpleName());
            System.err.println(usage);
            System.exit(0);
        }

        // get KafkaProducer
        final ISAToolsKafkaProducer isatProd = new ISAToolsKafkaProducer(kafkaTopic, kafkaUrl);
        DirWatcher dw = new DirWatcher(Paths.get(isaToolsDir));

        // adding shutdown hook for shutdown gracefully
        Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
            public void run() {
                System.out.println();
                System.out.format("[%s] Exiting app.\n", isatProd.getClass().getSimpleName());
                isatProd.closeProducer();
            }
        }));

        // get initial ISATools files
        List<JSONObject> newISAUpdates = isatProd.initialFileLoad(isaToolsDir);
        // send new studies to kafka
        isatProd.sendISAToolsUpdates(newISAUpdates);
        dw.processEvents(isatProd);

    }

    /**
     * Checks for files inside a folder
     *
     * @param innerFolder
     * @return
     */
    public static List<String> getFolderFiles(File innerFolder) {
        List<String> folderFiles = new ArrayList<String>();
        String[] innerFiles = innerFolder.list(new FilenameFilter() {
            public boolean accept(File dir, String name) {
                if (name.startsWith(DEFAULT_ISA_FILE_PREFIX)) {
                    return true;
                }
                return false;
            }
        });

        for (String innerFile : innerFiles) {
            File tmpDir = new File(innerFolder.getAbsolutePath() + File.separator + innerFile);
            if (!tmpDir.isDirectory()) {
                folderFiles.add(tmpDir.getAbsolutePath());
            }
        }
        return folderFiles;
    }

    /**
     * Performs the parsing request to Tika
     *
     * @param files
     * @return a list of JSON objects.
     */
    public static List<JSONObject> doTikaRequest(List<String> files) {
        List<JSONObject> jsonObjs = new ArrayList<JSONObject>();

        try {
            Parser parser = new ISArchiveParser();
            StringWriter strWriter = new StringWriter();

            for (String file : files) {
                JSONObject jsonObject = new JSONObject();

                // get metadata from tika
                InputStream stream = TikaInputStream.get(new File(file));
                ContentHandler handler = new ToHTMLContentHandler();
                Metadata metadata = new Metadata();
                ParseContext context = new ParseContext();
                parser.parse(stream, handler, metadata, context);

                // get json object
                jsonObject.put(SOURCE_TAG, ISATOOLS_SOURCE_VAL);
                JsonMetadata.toJson(metadata, strWriter);
                jsonObject = adjustUnifiedSchema((JSONObject) jsonParser.parse(new String(strWriter.toString())));
                //TODO Tika parsed content is not used needed for now
                //jsonObject.put(X_TIKA_CONTENT, handler.toString());
                System.out.format("[%s] Tika message: %s \n", ISAToolsKafkaProducer.class.getSimpleName(), jsonObject.toJSONString());

                jsonObjs.add(jsonObject);

                strWriter.getBuffer().setLength(0);
            }
            strWriter.flush();
            strWriter.close();

        } catch (IOException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (TikaException e) {
            e.printStackTrace();
        }
        return jsonObjs;
    }

    private static JSONObject adjustUnifiedSchema(JSONObject parse) {
        JSONObject jsonObject = new JSONObject();
        List invNames = new ArrayList<String>();
        List invMid = new ArrayList<String>();
        List invLastNames = new ArrayList<String>();

        Set<Map.Entry> set = parse.entrySet();
        for (Map.Entry entry : set) {
            String jsonKey = SolrKafkaConsumer.updateCommentPreffix(entry.getKey().toString());
            String solrKey = ISA_SOLR.get(jsonKey);

//            System.out.println("solrKey " + solrKey);
            if (solrKey != null) {
//                System.out.println("jsonKey: " + jsonKey + " -> solrKey: " + solrKey);
                if (jsonKey.equals("Study_Person_First_Name")) {
                    invNames.addAll(((JSONArray) JSONValue.parse(entry.getValue().toString())));
                } else if (jsonKey.equals("Study_Person_Mid_Initials")) {
                    invMid.addAll(((JSONArray) JSONValue.parse(entry.getValue().toString())));
                } else if (jsonKey.equals("Study_Person_Last_Name")) {
                    invLastNames.addAll(((JSONArray) JSONValue.parse(entry.getValue().toString())));
                }
                jsonKey = solrKey;
            } else {
                jsonKey = jsonKey.replace(" ", "_");
            }
            jsonObject.put(jsonKey, entry.getValue());
        }

        JSONArray jsonArray = new JSONArray();

        for (int cnt = 0; cnt < invLastNames.size(); cnt++) {
            StringBuilder sb = new StringBuilder();
            if (!StringUtils.isEmpty(invNames.get(cnt).toString()))
                sb.append(invNames.get(cnt)).append(" ");
            if (!StringUtils.isEmpty(invMid.get(cnt).toString()))
                sb.append(invMid.get(cnt)).append(" ");
            if (!StringUtils.isEmpty(invLastNames.get(cnt).toString()))
                sb.append(invLastNames.get(cnt));
            jsonArray.add(sb.toString());
        }
        if (!jsonArray.isEmpty()) {
            jsonObject.put("Investigator", jsonArray.toJSONString());
        }
        return jsonObject;
    }

    /**
     * Send message from IsaTools to kafka
     *
     * @param newISAUpdates
     */
    void sendISAToolsUpdates(List<JSONObject> newISAUpdates) {
        for (JSONObject row : newISAUpdates) {
            row.put(SOURCE_TAG, ISATOOLS_SOURCE_VAL);
            this.sendKafka(row.toJSONString());
            System.out.format("[%s] New message posted to kafka.\n", this.getClass().getSimpleName());
        }
    }

    /**
     * Gets the application updates from a directory
     *
     * @param isaToolsTopDir
     * @return
     */
    private List<JSONObject> initialFileLoad(String isaToolsTopDir) {
        System.out.format("[%s] Checking in %s\n", this.getClass().getSimpleName(), isaToolsTopDir);
        List<JSONObject> jsonParsedResults = new ArrayList<JSONObject>();
        List<File> innerFolders = getInnerFolders(isaToolsTopDir);

        for (File innerFolder : innerFolders) {
            jsonParsedResults.addAll(doTikaRequest(getFolderFiles(innerFolder)));
        }

        return jsonParsedResults;
    }

    /**
     * Gets the inner folders inside a folder
     *
     * @param isaToolsTopDir
     * @return
     */
    private List<File> getInnerFolders(String isaToolsTopDir) {
        List<File> innerFolders = new ArrayList<File>();
        File topDir = new File(isaToolsTopDir);
        String[] innerFiles = topDir.list();
        for (String innerFile : innerFiles) {
            File tmpDir = new File(isaToolsTopDir + File.separator + innerFile);
            if (tmpDir.isDirectory()) {
                innerFolders.add(tmpDir);
            }
        }
        return innerFolders;
    }
}

Listing 6-7.Apache Tika import routines for use throughout the PROBDA System

Installing and Testing Lingpipe, Gate, and Stanford Core NLP

  1. 首先从 http://alias-i.com/lingpipe/web/download.html 下载灵管发布 JAR 文件安装灵管。你也可以从 http://alias-i.com/lingpipe/web/models.html 下载你感兴趣的凌管模型。按照指示将模型放在正确的目录中,这样 LingPipe 就可以为需要它们的适当演示获取模型。

  2. 从谢菲尔德大学网站( https://gate.ac.uk )下载 GATE,使用安装程序安装 GATE 组件。安装对话框非常容易使用,允许你有选择地安装各种组件,如图 6-24 所示。

  3. We will also introduce the StanfordNLP ( http://stanfordnlp.github.io/CoreNLP/#human-languages-supported ) library component for our example. To get started with Stanford NLP, download the CoreNLP zip file from the GitHub link above. Expand the zip file. Make sure the following dependencies are in your pom.xml file:

               <dependency>
                <groupId>edu.stanford.nlp</groupId>
                <artifactId>stanford-corenlp</artifactId>
                <version>3.5.2</version>
                <classifier>models</classifier>
               </dependency>
               <dependency>
                <groupId>edu.stanford.nlp</groupId>
                <artifactId>stanford-corenlp</artifactId>
                <version>3.5.2</version>
               </dependency>
               <dependency>
                <groupId>edu.stanford.nlp</groupId>
                <artifactId>stanford-parser</artifactId>
                <version>3.5.2</version>
               </dependency>
    
    

    Go to Stanford NLP “home directory” (where the pom.xml file is located) and do

    mvn clean package
    
    

    then test the interactive NLP shell to insure correct behavior. Type

    ./corenlp.sh
    
    

    to start the interactive NLP shell. Type some sample text into the shell to see the parser in action. The results shown will be similar to those shown in Figure 6-17.

    A371868_1_En_6_Fig23_HTML.jpg

    图 6-23。

    StanfordNLP interactive shell in action

我们可以如下定义通用搜索的接口:

public interface ProbdaSearchEngine<T> {

  <Q> List<T> search(final String field, final Q query, int maximumResultCount);

  List<T> search(final String query, int maximumResultCount);
…………}

Listing 6-8.ProbdaSearchEngine java interface stub

search()有两个不同的方法签名。一个是专门针对字段和查询组合的。Query 是字符串形式的 Lucene 查询,maximumResultCount 将结果元素的数量限制在可管理的范围内。

我们可以定义 ProbdaSearchEngine 接口的实现,如清单 6-8 所示。

A371868_1_En_6_Fig24_HTML.jpg

图 6-24。

GATE Installation dialog. GATE is easy to install and use.

只需点击安装向导。请访问网站并安装提供的所有软件组件。

为了在程序中使用 LingPipe 和 GATE,让我们来看一个简单的例子,如清单 6-9 所示。请参考本章末尾的一些参考资料,以便更全面地了解 LingPipe 和 GATE 所能提供的特性。

package com.apress.probda.nlp;

import java.io.*;
import java.util.*;

import edu.stanford.nlp.io.*;
import edu.stanford.nlp.ling.*;
import edu.stanford.nlp.pipeline.*;
import edu.stanford.nlp.trees.*;
import edu.stanford.nlp.util.*;

public class ProbdaNLPDemo {

  public static void main(String[] args) throws IOException {
    PrintWriter out;
    if (args.length > 1) {
      out = new PrintWriter(args[1]);
    } else {
      out = new PrintWriter(System.out);
    }
    PrintWriter xmlOut = null;
    if (args.length > 2) {
      xmlOut = new PrintWriter(args[2]);
    }

    StanfordCoreNLP pipeline = new StanfordCoreNLP();
    Annotation annotation;
    if (args.length > 0) {
      annotation = new Annotation(IOUtils.slurpFileNoExceptions(args[0]));
    } else {
      annotation = new Annotation(“No reply from local Probda email site”);
    }

    pipeline.annotate(annotation);
    pipeline.prettyPrint(annotation, out);
    if (xmlOut != null) {
      pipeline.xmlPrint(annotation, xmlOut);
    }
    List<CoreMap> sentences = annotation.get(CoreAnnotations.SentencesAnnotation.class);
    if (sentences != null && sentences.size() > 0) {
      CoreMap sentence = sentences.get(0);
      Tree tree = sentence.get(TreeCoreAnnotations.TreeAnnotation.class);
      out.println();
      out.println("The first sentence parsed is:");
      tree.pennPrint(out);
    }
  }

}

Listing 6-9.LingPipe | GATE | StanfordNLP Java test program

,

imports

6.8 总结

在这一章中,我们对 Apache Lucene 和 Solr 生态系统做了一个快速的概述。有趣的是,虽然 Hadoop 和 Solr 一起作为 Lucene 生态系统的一部分开始,但它们后来分道扬镳,演变成了有用的独立框架。然而,这并不意味着 Solr 和 Hadoop 生态系统不能非常有效地协同工作。许多 Apache 组件,如 Mahout、LingPipe、GATE 和 Stanford NLP,都可以与 Lucene 和 Solr 无缝协作。Solr 中的新技术,比如 SolrCloud 和其他技术,使得使用 RESTful APIs 来连接 Lucene/Solr 技术变得更加容易。

我们完成了一个使用 Solr 及其生态系统的完整示例:从下载、按摩和输入数据集到转换数据和以各种数据格式输出结果。更加明显的是,Apache Tika 和 Spring 数据对于数据管道“粘合”非常有用。

我们没有忽视 Lucene/Solr 技术栈的竞争对手。我们讨论了 Elasticsearch,它是 Lucene/Solr 的一个强有力的替代品,并描述了使用 Elasticsearch 优于更“普通”的 Lucene/Solr 方法的优缺点。Elasticsearch 最有趣的部分之一是无缝的可视化数据的能力,正如我们在探索萨克拉门托的犯罪统计数据时所展示的那样。

在下一章中,我们将在目前所学的基础上,讨论一些对构建分布式分析系统特别有用的分析技术和算法。

6.9 参考文献

阿瓦德,玛丽埃特和卡纳,拉胡尔。高效的学习机器。纽约:2015 年出版发行。

巴本科,德米特里和马尔马尼,哈拉兰博斯。智能网的算法。庇护所岛:曼宁出版公司,2009 年。

穆罕默德·古勒。使用 Apache Spark 进行大数据分析。纽约:阿普瑞斯出版社,2015 年。

卡兰贝尔卡,赫里什克什。使用 Hadoop 和 Solr 扩展大数据。英国伯明翰:PACKT 出版社,2013 年。

曼努·孔查迪。构建搜索应用:Lucene,LingPipe 和 GATE。弗吉尼亚州奥克顿:穆斯特鲁出版社,2008 年。

克里斯·马特曼和兹廷、朱卡·蒂卡在行动。庇护所岛:曼宁出版公司,2012 年。

波拉克、马克、吉尔克、奥利弗、里斯伯格、托马斯、布里斯班、乔恩、亨格、迈克尔。Spring Data:企业 Java 的现代数据访问。塞瓦斯托波尔,加利福尼亚州:奥莱利媒体,2012 年。

万纳杰森。Pro Hadoop。纽约州纽约市:新闻出版社,2009 年。

七、分析技术和算法概述

在本章中,我们提供了四类算法的概述:统计、贝叶斯、本体驱动和混合算法,这些算法利用标准库中找到的更基本的算法来使用 Hadoop 执行更深入和准确的分析。

7.1 算法类型概述

事实证明,Apache Mahout 和大多数其他主流机器学习工具包支持我们感兴趣的各种算法。例如,参见图 7-1 查看 Apache Mahout 支持的算法。

| 数字 | 算法名称 | 算法类型 | 描述 | | --- | --- | --- | --- | | one | 奈伊夫拜厄斯 | 分类者 | 简单的贝叶斯分类器:存在于几乎所有的现代工具包中 | | Two | 隐马尔可夫模型 | 分类者 | 通过结果观察预测系统状态 | | three | (学习)随机森林 | 分类者 | 随机森林算法(有时也称为随机决策森林)是一种用于分类、回归和其他任务的集成学习方法,它在训练时构建决策树集合,输出作为分类类模式或单个树的均值预测(回归)的类。 | | four | (学习)多层感知机(LMP) | 分类者 | 也在 Theano 工具包和其他几个工具包中实现。 | | five | (学习)逻辑回归 | 分类者 | scikit-learn 中也支持。实际上是一种分类技术,而不是回归技术。 | | six | 随机梯度下降 | 优化器,模型查找 | H2O 和沃帕尔·瓦比特等人也支持目标函数最小化程序 | | seven | 遗传算法 | 遗传算法 | 根据维基百科,“在数学优化领域,遗传算法(GA)是一种模拟自然选择过程的搜索启发式算法。这种试探法(有时也称为元试探法)通常用于生成优化和搜索问题的有用解决方案。 | | eight | 奇异值分解 | 降维 | 降维的矩阵分解 | | nine | 协同过滤(CF) | 被推荐的 | 一些推荐系统使用的技术 | | Ten | 潜在狄利克雷分配 | 主题建模器 | 一个强大的算法(学习者),自动(和联合)将单词聚类成“主题”,并将文档聚类成主题“混合物” | | Eleven | 谱聚类 | 聚合 |   | | Twelve | 频繁模式挖掘 | 数据挖掘器 |   | | Thirteen | k 均值聚类 | 聚合 | 使用 Mahout 可以得到普通的和模糊的 k 均值 | | Fourteen | 树冠集群 | 聚合 | k-means 聚类器的预处理步骤:双阈值系统 |

A371868_1_En_7_Fig1_HTML.jpg

图 7-1。

Mean, standard deviation, and normal distribution are often used in statistical methods

统计和数值算法是我们可以使用的最直接的分布式算法。

统计技术包括使用标准统计计算,如图 7-1 所示。

贝叶斯技术是构建分类器、数据建模和其他目的的最有效的技术之一。

另一方面,本体驱动的算法是一整套算法,它们依赖于逻辑的、结构化的、层次化的建模、语法和其他技术来为建模、数据挖掘和对数据集进行推断提供基础设施。

混合算法将一个或多个由不同类型的算法组成的模块结合在一起,用 glueware 连接在一起,提供一个比单一算法类型更灵活、更强大的数据管道。例如,神经网络技术可以与贝叶斯技术和 ML 技术相结合来创建“学习贝叶斯网络”,这是通过使用混合方法可以获得的协同作用的一个非常有趣的例子。

7.2 统计/数字技术

示例系统中的统计类和支持方法可以在com.apress.probda.algorithms.statistics子包中找到。

我们可以在图 7-2 中看到一个使用 Apache Storm 的简单分布式技术栈。

A371868_1_En_7_Fig3_HTML.jpg

图 7-3。

An Apache Spark-centric technology stack

A371868_1_En_7_Fig2_HTML.jpg

图 7-2。

A distributed technology stack including Apache Storm

我们可以在图 7-4 中看到一个以超光速粒子为中心的技术堆栈。Tachyon 是一个容错分布式内存文件系统

A371868_1_En_7_Fig4_HTML.jpg

图 7-4。

A Tachyon-centric technology stack , showing some of the associated ecosystem

7.3 贝叶斯技术

我们在示例系统中实现的贝叶斯技术可以在包 com.prodba.algorithms.bayes 中找到

我们最流行的库所支持的一些贝叶斯技术(除了朴素贝叶斯算法之外)包括图 7-1 中所示的那些。

朴素贝叶斯分类器基于基本贝叶斯方程,如图 7-5 所示。

A371868_1_En_7_Fig5_HTML.jpg

图 7-5。

The fundamental Bayes equation

该方程包含四种主要的概率类型:后验概率、似然性、类先验概率和预测先验概率。这些术语在本章末尾的参考资料中有解释。

我们可以用一种简单的方式来尝试 Mahout 文本分类器。首先,下载一个基本数据集进行测试。

7.4 本体驱动的算法

本体驱动的组件和支持类可以在com.apress.probda.algorithms.ontology子包中找到。

要包含 Protégé Core 组件,请将以下 Maven 依赖项添加到您的项目 pom.xml 文件中。

<dependency>
        <groupId>edu.stanford.protege</groupId>
        <artifactId>protege-common</artifactId>
        <version>5.0.0-beta-24</version>
</dependency>

从网站注册并下载 protegé:

protege.stanford.edu/products.php#desktop-prot%C3%A9g%C3%A9

可以通过使用诸如斯坦福的 Protégé系统之类的本体编辑器来交互式地定义本体,如图 7-5 所示。

A371868_1_En_7_Fig6_HTML.jpg

图 7-6。

Setting up SPARQL functionality with the Stanford toolkit interactive setup

您可以安全地选择所有组件,或者只选择您需要的组件。请参考各个在线文档页面,查看这些组件是否适合您的应用。

A371868_1_En_7_Fig7_HTML.jpg

图 7-7。

Using an ontology editor to define ontologies, taxonomies, and grammars

7.5 混合算法:组合算法类型

Probda 示例系统中实现的混合算法可以在com.apress.prodbda.algorithms.hybrid子包中找到。

我们可以混合匹配算法类型来构建更好的数据管道。这些“混合系统”可能更复杂一些——当然,它们通常有几个额外的组件——但它们在实用性上弥补了这一点。

最有效的混合算法之一是所谓的“深度学习”组件。并非所有人都认为深度学习器是一种混合算法(在大多数情况下,它们本质上是建立在多层神经网络技术上的),但有一些令人信服的理由将深度学习器视为混合系统,正如我们将在下面讨论的那样。

所谓的“深度学习”技术包括图 yy-yy 所示的技术。DeepLearning4J 和 TensorFlow toolkit 是目前可用的两个比较流行和强大的深度学习库。在 https://www.tensorflow.org/versions/r0.10/get_started/basic_usage.htmlautoenc 查看 TensorFlow。Theano 是一个基于 Python 的多维数组库。查看 http://deeplearning.net/tutorial/dA.html 了解更多关于如何使用 Theano 的细节。

| 数字 | 算法名称 | 算法类型 | 工具包 | 描述 | | --- | --- | --- | --- | --- | | one | 深度信念网络 | 神经网络 | 深入学习 4j,tensorflow,Theano | 多层隐藏单元,仅具有层互连性 | | Two | (堆叠、去噪)自动编码器(DA) | 基本自动编码器原理的变体 | 深入学习 4j,tensorflow,Theano | 堆叠自动编码器是由多层稀疏自动编码器组成的神经网络,其中每层的输出都连接到连续层的输入。去噪自动编码器可以接受部分损坏的输入,同时恢复原始未损坏的输入。 | | three | 卷积神经网络(CNN) | 神经网络,MLP 的变体 | 深入学习 4j,tensorflow,Theano | 稀疏连接和共享权重是细胞神经网络的两个特征。 | | four | 长短期记忆单位(LSTM) | 递归神经网络,分类器,预测器 | Deeplearning4j, TensorFlow | 分类和时间序列预测,甚至情感分析 | | five | 递归神经网络 | 神经网络 | Deeplearning4j, TensorFlow | 分类,时间序列预测 | | six | 计算图 | 复杂网络架构构建器 | Deeplearning4j, TensorFlow | 计算用图形表示。 |

7.6 代码示例

在本节中,我们将讨论我们在前面章节中讨论的算法类型的一些扩展示例。

为了对一些算法比较有所了解,让我们使用电影数据集来评估我们已经讨论过的一些算法和工具包。

package com.apress.probda.datareader.csv;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;

public class FileTransducer {

        /**
         * This routine splits a line which is delimited into fields by the vertical
         * bar symbol '|'
         *
         * @param l
         * @return
         */
        public static String makeComponentsList(String l) {
                String[] genres = l.split("\\|");
                StringBuffer sb = new StringBuffer();
                for (String g : genres) {
                        sb.append("\"" + g + "\",");
                }
                String answer = sb.toString();
                return answer.substring(0, answer.length() - 1);
        }

        /**
         * The main routine processes the standard movie data files so that mahout
         * can use them.
         *
         * @param args
         */
        public static void main(String[] args) {
if (args.length < 4){
System.out.println("Usage: <movie data input><movie output file><ratings input file> <ratings output file>");
                        System.exit(-1);
                }
                File file = new File(args[0]);
                if (!file.exists()) {
                        System.out.println("File: " + file + " did not exist, exiting...");
                        System.exit(-1);
                }
                System.out.println("Processing file: " + file);
                BufferedWriter bw = null;
                FileOutputStream fos = null;
                String line;
                try (BufferedReader br = new BufferedReader(new FileReader(file))) {
                        int i = 1;
                        File fout = new File(args[1]);
                        fos = new FileOutputStream(fout);
                        bw = new BufferedWriter(new OutputStreamWriter(fos));
                        while ((line = br.readLine()) != null) {
                                String[] components = line.split("::");
                                String number = components[0].trim();
                                String[] titleDate = components[1].split("\\(");
                                String title = titleDate[0].trim();
                                String date = titleDate[1].replace(")", "").trim();
                                String genreList = makeComponentsList(components[2]);
                                String outLine = "{ \"create\" : { \"_index\" : \"bigmovie\", \"_type\" : \"film\", \"_id\" : \"" + i
                                                + "\" } }\n" + "{ \"id\": \"" + i + "\", \"title\" : \"" + title + "\", \"year\":\"" + date
                                                + "\" , \"genre\":[" + genreList + "] }";
                                i++;
                                bw.write(outLine);
                                bw.newLine();
                        }
                } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                } finally {
                        if (bw != null) {
                                try {
                                        bw.close();
                                } catch (IOException e) {
                                        // TODO Auto-generated catch block
                                        e.printStackTrace();
                                }
                        }
                }
                file = new File(args[2]);
                try (BufferedReader br2 = new BufferedReader(new FileReader(file))) {
                        File fileout = new File(args[3]);
                        fos = new FileOutputStream(fileout);
                        bw = new BufferedWriter(new OutputStreamWriter(fos));
                        while ((line = br2.readLine()) != null) {
                                String lineout = line.replace("::", "\t");
                                bw.write(lineout);
                        }
                } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                } finally {
                        if (bw != null) {
                                try {
                                        bw.close();
                                } catch (IOException e) {
                                        // TODO Auto-generated catch block
                                        e.printStackTrace();
                                }
                        }
                }
        }
}
Execute the following curl command on the command line to import the data set into elastic search:
curl -s -XPOST localhost:9200/_bulk --data-binary @index.json; echo

数据集可以通过命令行使用 CURL 命令导入到 Elasticsearch 中。图 7-8 就是执行这样一个命令的结果。Elasticsearch 服务器返回一个 JSON 数据结构,该数据结构显示在控制台上,并被索引到 Elasticsearch 系统中。

A371868_1_En_7_Fig9_HTML.jpg

图 7-9。

Using Kibana as a reporting and visualization tool

A371868_1_En_7_Fig8_HTML.jpg

图 7-8。

Importing a standard movie data set example using a CURL command

我们可以在图 7-7 中看到一个使用 Kibana 作为报告工具的简单例子。顺便说一句,在本书余下的大部分内容中,我们会遇到 Kibana 和 ELK Stack(elastic search–Logstash–Kibana)。虽然有使用 ELK 堆栈的替代方法,但这是从第三方构建块构建数据分析系统的更轻松的方法之一。

7.7 摘要

在这一章中,我们讨论了分析技术和算法以及一些评估算法有效性的标准。我们谈到了一些较老的算法类型:统计和数值分析函数。组合或混合算法在最近几天变得特别重要,因为来自机器学习、统计学和其他领域的技术可以以合作的方式非常有效地使用,正如我们在本章中所看到的。对于分布式算法的一般介绍,参见 Barbosa (1996)。

这些算法类型中有许多非常复杂。其中一些,例如贝叶斯技术,有专门的文献。对于贝叶斯技术的详细解释,特别是概率技术,见扎德(1992),

在下一章中,我们将讨论基于规则的系统,可用的规则引擎系统,如 JBoss Drools,以及基于规则的系统在智能数据收集、基于规则的分析和数据管道控制调度和编排方面的一些应用。

7.8 参考文献

分布式算法导论。麻省剑桥:麻省理工学院出版社,1996 年。

贝叶斯统计导论。纽约:威利 Inter-Science,威利父子公司,2004 年。

贾科姆利,皮可。阿帕奇看象人食谱。英国伯明翰:PACKT 出版社,2013 年。

古普塔,阿希什。学习 Apache Mahout 分类。英国伯明翰:PACKT 出版社,2015 年。

马尔马尼什,哈拉兰博斯和巴本科,德米特里。智能网的算法。康涅狄格州格林威治:曼宁出版社,2009 年。

Nakhaeizadeh,g .和 Taylor,C.C .(编辑)。机器学习和统计学:界面。纽约:约翰·威利父子公司,1997 年。

西蒙帕森斯。不确定条件下推理的定性方法。剑桥。马:麻省理工学院出版社,2001。

珀尔朱迪亚。智能系统中的概率推理:似是而非推理网络。加利福尼亚州圣马特奥:摩根-考夫曼出版社,1988 年。

扎德、洛夫蒂和卡普奇克(合编)。不确定性管理的模糊逻辑。纽约:约翰·威利父子公司,1992 年。

八、规则引擎、系统控制和系统编排

在本章中,我们将描述 JBoss Drools 规则引擎,以及如何使用它来控制和编排 Hadoop 分析管道。我们描述了一个基于规则的控制器示例,它可以与 Hadoop 生态系统结合使用,用于各种数据类型和应用程序。

Note

使用 JBoss Drools 系统的大部分配置都是通过 Maven 依赖项完成的。当我们讨论 JBoss Drools 的初始设置时,在第三章中显示了适当的依赖关系。有效使用 JBoss Drools 所需的所有依赖项都包含在示例 PROBDA 系统中,可以从代码下载站点获得。

8.1 规则系统介绍:JBoss Drools

JBoss Drools ( www.drools.org )在本章的所有例子中都有使用。这不是规则引擎的唯一选择。有许多免费的规则引擎框架,但是 Drools 是一个高性能的系统,可以立即用来定义许多不同种类的控制和架构系统。JBoss Drools 还有一个优势。关于 Drools 系统(docs.jboss.org)、编程方法和优化细节,以及基于规则的技术的解释,有大量的在线和印刷文档。本章末尾列出了一些 Drools 参考书。这些提供了对基于规则的控制系统、规则机制和编辑以及其他重要细节的全面介绍。

在这一章中,我们将通过一个具体的应用来简要概述基于规则的技术:定义一个复杂事件处理器(CEP)的例子。

CEPs 是数据管道主题的一个非常有用的变体,可以用在实际系统中,包括从信用卡欺诈检测系统到复杂的工厂控制系统。

在所有的规则系统中,有两种数据结构在起作用:当然是规则,它在基于规则的系统中提供“if-then-else”条件功能(然而,我们很快就会知道,这种类型的规则,称为“正向链接”规则,并不是我们将遇到的唯一规则;还有“反向链接”规则,稍后将对其进行描述)。使用的另一种数据结构是事实,它是单独的“数据项”这些被保存在一个叫做工作记忆库的储存库中。请参见图 8-1 了解这在 Drools 系统中是如何工作的。

A371868_1_En_8_Fig1_HTML.jpg

图 8-1。

Download the Drools software from the Drools web page Note

本书使用了 JBoss Drools 最新发布的版本,在写本书的时候是 6.4.0 版本。如果 JBoss Drools 的新版本可用并且您想要使用它,请更新 PROBDA 项目 pom.xml 中的 drools.system.version 属性。

让我们从安装 JBoss Drools 和测试一些基本功能开始。安装过程很简单。在 JBoss Drools 首页,点击下载按钮,下载 Drools 当前版本,如图 8-1 所示。

cd 到安装目录并运行 examples/run-examples.sh。您将看到一个类似于图 8-2 中的选择菜单。运行一些输出示例来测试 Drools 系统,并在控制台中观察输出,类似于图 8-3 ,或者一个面向 GUI 的示例,如图 8-4 。

A371868_1_En_8_Fig4_HTML.jpg

图 8-4。

JBoss Drools rule system architecture

A371868_1_En_8_Fig3_HTML.jpg

图 8-3。

JBoss Drools GUI-oriented example

A371868_1_En_8_Fig2_HTML.jpg

图 8-2。

Select some Drools examples and observe the results to test the Drools system

内置的 Drools 示例有一个菜单,您可以从中选择不同的测试示例,如图 8-2 所示。这是测试整个系统设置并了解 JBoss Drools 系统功能的好方法。

JBoss Drools 的一些示例组件有一个关联的 UI,如图 8-3 所示。

JBoss Drools 规则系统的基本架构如图 8-4 所示。

Note

此系统中的所有示例代码都可以在 Java 包 com.apress.probda.rulesystem 中附带的示例系统代码库中找到。有关安装、版本控制和使用的其他说明,请参见相关的自述文件和文档。

在我们的系统中,带有时间戳的 Probda 事件的界面再简单不过了:

package com.probda.rulesystem.cep.model;

import java.util.Date;

public interface IEvent extends Fact {

        public abstract Date getTimestamp();
}

IEvent 的实现如下所示:

IEvent 的实现如下所示:

清单 8-1。一个基本的 JBoss Drools 程序

让我们以举例的方式给评估系统添加一个规则系统。只需为 drools 规则系统添加适当的依赖项(Drools 最新版本的 Google“Drools maven 依赖项”)。清单 3-2 中显示了完整的 pom.xml 文件(构建于我们的原始文件之上)。我们将在第八章的完整分析引擎示例中利用 JBoss Drools 的功能。请注意,我们提供依赖关系来连接 Drools 系统和 Apache Camel 以及 Drools 的 Spring 框架。

8.2 基于规则的软件系统控制

基于规则的软件系统控制可以从一个调度组件(如 Oozie)结合 JBoss Drools 或其他规则框架中的适当功能来构建,如图 8-5 中的示例架构所示。

A371868_1_En_8_Fig5_HTML.jpg

图 8-5。

Rule-based software systems control architecture, using JBoss Drools as a controller

8.3 使用 JBoss Drools 的系统编排

在这一节中,我们将讨论一个简单的例子,说明如何使用 JBoss Drools 作为控制器来完成系统编排任务。我们将使用 Activiti 开源项目( http://activiti.org )以及一些如何将工作流编排器/控制器集成到基于 Spring 框架的项目中的例子。

git clone https://github.com/Activiti/Activiti.git
export ACTIVITI_HOME=/Users/kkoitzsch/activiti
             cd $ACTIVITI_HOME
mvn clean install

Don’t forget to generate the documentation by
        cd $ACTIVITI_HOME/userguide
        mvn install

Insure Tomcat is installed. On the Mac platform, do

brew install tomcat
Tomcat will then be installed at /usr/local/Cellar/tomcat/8.5.3

图 8-6 显示了在 Activiti 构建结束时,您可以从 Maven reactor 总结中得到什么。

A371868_1_En_8_Fig6_HTML.jpg

图 8-6。

Maven reactor summary for Activiti system install

export TOMCAT_HOME=/usr/local/Cellar/tomcat/8.5.3
cd $ACTIVITI_HOME/scripts

然后运行活动脚本

./start-rest-no-jrebel.sh

您将看到 Activiti 成功启动,如图 8-7 所示。

A371868_1_En_8_Fig7_HTML.jpg

图 8-7。

Activiti script running successfully

Activiti 程序成功运行的屏幕截图如图 8-7 所示。

图 8-8 显示了 Activiti Explorer 仪表盘成功运行的图片。

A371868_1_En_8_Fig8_HTML.jpg

图 8-8。

Activiti explorer dashboard running successfully

8.4 带规则控制的分析引擎示例

在本节中,我们将演示一个带有规则控制的分析引擎示例。

A371868_1_En_8_Fig11_HTML.jpg

图 8-11。

A Lucene-oriented system design, including user interactions and document processing , step 3

A371868_1_En_8_Fig10_HTML.jpg

图 8-10。

A Lucene-oriented system design, including user interactions and document processing , step 2

A371868_1_En_8_Fig9_HTML.jpg

图 8-9。

An initial Lucene-oriented system design, including user interactions and document processing

我们可以使用 Splunk 系统来接收数据。

我们可以使用面向时间序列的数据库,比如 OpenTSDB ( https://github.com/OpenTSDB/opentsdb/releases )作为中间数据存储库。

JBoss Drools 提供了基于规则的转换。

文档库功能可以由 Cassandra 数据库的实例提供。

Note

请注意,您没有义务使用图 8-12 中所示的技术组件。根据您的应用程序需求,您可以使用另一个消息传递组件,比如 RabbitMQ,而不是 Apache Kafka,或者 MongoDB,而不是 Cassandra。

A371868_1_En_8_Fig12_HTML.jpg

图 8-12。

An integrated system architecture with lifecycle, including the technology components used

8.5 总结

在本章中,我们讨论了将基于规则的控制器用于其他分布式组件,尤其是 Hadoop 和 Spark 生态系统组件。我们已经看到,基于规则的策略可以为分布式数据分析添加一个关键要素:以灵活且有逻辑的方式组织和控制数据流的能力。调度和优先化是这些基于规则的技术的自然结果,我们在本章中查看了一些基于规则的调度器的例子。

在下一章中,我们将讨论到目前为止我们所学的技术在一个集成的分析组件中的应用,它适用于各种用例以及问题域。

8.6 参考文献

阿玛多,卢卡斯。Drools 开发者食谱。英国伯明翰:PACKT 出版社,2012 年。

巴厘岛,米哈尔。Drools JBoss 规则 5.0 开发者指南。英国伯明翰:PACKT 出版社,2009 年。

布朗,保罗。JBoss 口水商业规则。英国伯明翰:PACKT 出版社,2009 年。

诺维格,彼得。人工智能范例:Common Lisp 案例研究。加利福尼亚州圣马特奥:摩根-考夫曼出版社,1992 年。

九、将所有这些放在一起:设计一个完整的分析系统

在本章中,我们将描述一个端到端的设计示例,使用到目前为止讨论过的许多组件。我们还讨论了在系统开发项目的需求获取、计划、架构、开发、测试和部署阶段使用的“最佳实践”。

Note

本章使用了本书其他地方讨论的许多软件组件,包括 Hadoop、Spark、Splunk、Mahout、Spring Data、Spring XD、Samza 和 Kafka。查看附录 A 中的组件摘要,并确保在尝试本章中的示例时可以使用它们。

构建一个完整的分布式分析系统比听起来容易。在前面的章节中,我们已经讨论了这样一个系统的许多重要组成部分。一旦您理解了您的数据源和汇点将会是什么,并且您对要使用的技术栈和要利用的“glueware”有了一个相当清晰的概念,编写业务逻辑和其他处理代码就可以成为一个相对简单的任务。

一个简单的端到端架构如图 9-1 所示。对于数据源、处理器、数据接收器和存储库以及输出模块实际使用的技术,这里显示的许多组件都留有余地,其中包括我们将在其他章节中看到的熟悉的仪表板、报告、可视化等。在本例中,我们将使用熟悉的导入工具 Splunk 来提供输入源。

A371868_1_En_9_Fig1_HTML.jpg

图 9-1。

A simple end-to-end analytics architecture

在下一节中,我们将介绍如何设置 Splunk 并将其与示例系统的其他组件集成。

How to Install Splunk for the Example System

Splunk ( https://www.splunk.com )是一个日志框架,非常容易下载、安装和使用。对于我们在这里展示的示例分析系统来说,它附带了许多非常有用的功能,包括一个内置的搜索工具。

要安装 Splunk,请转到下载网页,创建一个用户帐户,并下载适用于您的适当平台的 Splunk Enterprise。这里展示的所有例子都使用 MacOS 平台。

为您选择的平台正确安装 Splunk Enterprise。在 Mac 平台上,如果安装成功,您将看到 Splunk 出现在您的应用程序目录中,如图 9-2 所示。

A371868_1_En_9_Fig2_HTML.jpg

图 9-2。

Successful Splunk Enterprise installation for Mac OSX

关于如何启动 Splunk,请参考 http://docs.splunk.com/Documentation/Splunk/6.4.2/SearchTutorial/StartSplunk 。请注意,正确启动后,可以在http://localhost:8000找到 Splunk Web 界面。

A371868_1_En_9_Fig3_HTML.jpg

图 9-3。

Login page for Splunk Enterprise

当您将浏览器指向 localhost:8000 时,最初会看到 Splunk 登录页面。首先使用默认的用户名和密码,按照指示进行更改,并确保用于连接的 Java 代码使用更新的用户名(' admin ')和密码(' changename ')。

A371868_1_En_9_Fig4_HTML.jpg

图 9-4。

Change password during initial Splunk Enterprise setup

从 github 下载以下非常有用的库,splunk-library-javalogging:

git clone https://github.com/splunk/splunk-library-javalogging.git

cd splunk-library-javalogging

mvn clean install

在您的 Eclipse IDE 中,导入现有的 Maven 项目,如图 9-5 所示。

A371868_1_En_9_Fig5_HTML.jpg

图 9-5。

Import an existing Maven to use splunk-library-javalogging

图 9-5 显示了导入现有 Maven 项目以使用 splunk-library-javalogging 的对话框。

A371868_1_En_9_Fig6_HTML.jpg

图 9-6。

Select splunk-library-javalogging for import

如图 9-7 所示,选择合适的 pom.xml 是您在这一步需要做的全部工作。

A371868_1_En_9_Fig7_HTML.jpg

图 9-7。

Select the appropriate root directory for Maven construction

如图 9-8 所示,修改以包括适当的用户名和密码值通常是此安装步骤所必需的。

A371868_1_En_9_Fig8_HTML.jpg

图 9-8。

Eclipse IDE installation of Splunk test code

如图 9-9 所示,为 Splunk 配置 HadoopConnect 组件。

A371868_1_En_9_Fig9_HTML.jpg

图 9-9。

Configure the HadoopConnect component for Splunk

Splunk 仪表盘中的文本搜索可如图 9-10 所示完成。我们还可以选择一个合适的带时间戳的时间间隔来对数据集执行查询。

A371868_1_En_9_Fig10_HTML.jpg

图 9-10。

Searching for Pro Data Analytics events in the Splunk dashboard

可视化是这一整合过程的重要组成部分。查看本章底部的一些 D3 参考资料,了解一些可以与数据管道的其他组件结合使用的技术。

9.1 摘要

在这一章中,我们讨论了构建一个完整的分析系统,以及架构师和开发人员在这个过程中遇到的一些挑战。我们使用前几章中讨论的现已熟悉的技术组件构建了一个完整的端到端分析管道。特别是,我们讨论了如何使用 Splunk 作为输入数据源。Splunk 是一种特别通用和灵活的工具,可用于各种通用日志事件。

9.2 参考文献

莫克,德里克,约翰逊,保罗,迪亚昆,乔什。Splunk 运营情报指南。英国伯明翰:PACKT 出版社,2014 年。

朱,尼克齐。用 d3.js Cookbook 实现数据可视化。英国伯明翰:PACKT 出版社,2014 年。

十、数据可视化工具:查看分析并与之交互

在这一章中,我们将讨论如何查看—可视化—我们的分析结果。这其实是一个相当复杂的过程,或者说可以。这完全是为您的应用程序所需的可视化类型选择合适的技术堆栈的问题。分析应用程序中的可视化任务可以从创建简单的报表到成熟的交互系统。在本章中,我们将主要讨论 Angular JS 及其生态系统,包括 ElasticUI 可视化工具 Kibana,以及用于图形、图表和表格的其他可视化组件,包括一些基于 JavaScript 的工具,如 D3.js 和 sigma.js。

10.1 简单的可视化

最简单的可视化架构之一如图 10-1 所示。前端控制界面可以是基于网络的,或者是独立的应用程序。控制 UI 可以基于单个网页,或者更先进的软件插件或多个页面组件。前端的“Glueware”可能涉及可视化框架,比如 Angular JS,我们将在下面的小节中详细讨论。在后端,像 Spring XD 这样的 glueware 可以使可视化界面更加简单。

A371868_1_En_10_Fig1_HTML.jpg

图 10-1。

Typical visualization component architecture

让我们简单谈谈图 10-1 中的不同组件。每个圆圈代表使用分析软件组件时典型用例的不同方面。你可能会认为这些圆圈是我们试图解决的个别子问题或问题。例如,分组、排序、合并和整理可能由一个标准的表格结构来处理,如图 10-2 所示。大多数排序和分组问题都可以通过内置的表格功能来解决,比如单击一列来对行进行排序,或者对项目进行分组。

A371868_1_En_10_Fig2_HTML.jpg

图 10-2。

One tabular control can solve several visualization concerns

提供有效的显示功能非常简单,只需选择适当的表格组件用于面向行的数据。图 10-2 所示的表格组件是一个很好的例子,它提供了数据导入、排序、分页和易于编程的特性。此组件在 https://github.com/wenzhixin/bootstrap-table 可用。这里显示的控件利用一个名为 Bootstrap.js ( http://getbootstrap.com/javascript/ )的助手库来提供高级功能。能够将 JSON 数据集导入可视化组件是一个关键特性,它支持与其他 UI 和后端组件的无缝集成。

图 10-1 中发现的许多问题可以通过嵌入网页的前端控件来控制。例如,我们都熟悉“Google 风格”的文本搜索机制,它只包含一个文本字段和一个按钮。我们可以使用 d3 实现一个可视化工具,对脸书的推文进行简单的分析,作为数据可视化的介绍。如图 10-2 和图 10-3 所示,我们可以控制显示的“内容”以及“方式”:我们可以看到示例数据集的饼图、条形图和气泡图版本,它来自 Spring XD 数据流。

A371868_1_En_10_Fig3_HTML.jpg

图 10-3。

Simple data visualization example of Twitter tweets using Spring XD showing trending topics and languages

我们在图 10-1 中看到的大多数关注点(数据集选择、显示类型选择和其他)在图 10-3 和图 10-4 中有所体现。下拉框等标准控件用于选择数据集和显示类型。呈现类型可以包括各种图形和图表类型、二维和三维显示以及其他类型的呈现和报告格式。Apache POI ( https://poi.apache.org )等组件可用于编写与 Excel 兼容的微软格式的报告文件。

A371868_1_En_10_Fig4_HTML.jpg

图 10-4。

An additional simple data visualization example of Twitter tweets using Spring XD

当新的 tweet 数据通过 Spring XD 数据流到达时,这里显示的内容会动态更新。图 10-3 显示了推特数据的一个稍微不同的可视化,其中我们可以看到一些圆圈的大小是如何增长的,代表了推特中的数据“趋势”。

我们将在下一节讨论 Spring XD,因为它在构建可视化工具时作为 glueware 特别有用。

Setting Up the Spring XD Component

像所有 Spring 框架组件一样,设置 Spring XD 组件基本上很简单。

安装 Spring XD 后,在“单节点模式”下用

bin/xd-singlenode
cd bin

使用以下命令运行 XD shell

./xd-shell

使用以下命令创建流

 stream create tweets --definition "twitterstream | log"

 stream create tweetlang  --definition "tap:stream:tweets > field-value-counter --fieldName=lang" --deploy

stream create tweetcount --definition "tap:stream:tweets > aggregate-counter" --deploy

stream create tagcount --definition "tap:stream:tweets > field-value-counter --fieldName=entities.hashtags.text --name=hashtags" --deploy
stream deploy tweets

A371868_1_En_10_Fig5_HTML.jpg

图 10-5。

Architecture diagram for Twitter ➤ Spring XD ➤ visualization

A371868_1_En_10_Fig6_HTML.jpg

图 10-6。

Bringing up the Spring XD shell successfully

A371868_1_En_10_Fig7_HTML.jpg

图 10-7。

Using Spring XD to implement a Twitter tweet stream and then sdeploy the stream

在下一节中,我们将深入一些特别有用的工具包 Angular JS 的综合例子。

10.2 介绍 Angular JS 和朋友

Angular JS ( https://angularjs.org )是一个基于 JavaScript 的工具包,已经成为数据可视化库领域非常突出的竞争者。它有一个简单的模型-视图-控制器(MVC)架构,可以简化设计和实现过程。

顺便提一下,一些 Angular JS 组件,如 Elastic UI(elasticui.com ),可以直接开箱即用,与 Elastic 搜索引擎一起使用。带有 Kibana 的 ElasticUI 是添加可视化组件的一种快速且相对容易的方式。

我们将在本章余下的大部分时间里讨论如何使用 Angular JS 和一些其他可视化工具包来设置一些示例,包括一个非常有趣的新成员 JHipster。

10.3 使用 JHipster 集成 Spring XD 和 Angular JS

JHipster ( https://jhipster.github.io )是一个开源的 Yeoman()生成器,用于创建集成的 Spring Boot 和 Angular JS 组件。这使得以无缝的方式集成 Spring Framework 生态系统的其他组件成为可能。例如,您可以使用一个基于 Spring Data Hadoop 的组件来构建一个数据管道,在前端使用 AngularJS 编写摘要显示。

我们将构建一个简单的 JHipster 迷你项目来展示这可能是如何工作的。

A371868_1_En_10_Fig8_HTML.jpg

图 10-8。

Successful setup of a “probda-hipster” project How to Build the Angular JS Example System

构建一个 Angular JS 示例系统相对简单,我们将在本节中描述如何实现。

构建 Angular JS 示例系统的第一步是在命令行上创建原型项目。Cd 到您希望构建的主目录。然后执行下面的命令,如清单 13.1 所示。

mvn archetype:generate -DgroupId=nl.ivonet -DartifactId=java-angularjs-seed -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false

这将创建如清单 10-2 所示的目录和文件。Cd 到目录,并确保它们确实在那里。

./pom.xml
./src
./src/main
./src/main/resources
./src/main/webapp
./src/main/webapp/index.jsp
./src/main/webapp/WEB-INF
./src/main/webapp/WEB-INF/web.xml

构建新的文件和目录来配置项目,如清单 10-3 所示。

mkdir -p src/main/java
mkdir -p src/test/java
mkdir -p src/test/javascript/unit
mkdir -p src/test/javascript/e2e
mkdir -p src/test/resources
rm -f ./src/main/webapp/WEB-INF/web.xml
rm -f ./src/main/webapp/index.jsp
mkdir -p ./src/main/webapp/css
touch ./src/main/webapp/css/specific.css
mkdir -p ./src/main/webapp/js
touch ./src/main/webapp/js/app.js
touch ./src/main/webapp/js/controllers.js
touch ./src/main/webapp/js/routes.js
touch ./src/main/webapp/js/services.js
touch ./src/main/webapp/js/filters.js
touch ./src/main/webapp/js/services.js
mkdir -p ./src/main/webapp/vendor
mkdir -p ./src/main/webapp/partials
mkdir -p ./src/main/webapp/img
touch README.md
touch .bowerrc

运行 npm 初始化,以交互方式构建程序。“npm init”将提供一个逐步问答的方法来创建项目,如清单 x.y 所示

npm init

This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sane defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install  --save` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
name: (java-angularjs-seed)
version: (0.0.0)
description: A starter project for AngularJS combined with java and maven
entry point: (index.js)
test command: karma start test/resources/karma.conf.js
git repository: https://github.com/ivonet/java-angular-seed
keywords:
author: Ivo Woltring
license: (ISC) Apache 2.0
About to write to /Users/ivonet/dev/ordina/LabTime/java-angularjs-seed/package.json:

{
  "name": "java-angularjs-seed",
  "version": "0.0.0",
  "description": "A starter project for AngularJS combined with java and maven",
  "main": "index.js",
  "scripts": {
    "test": "karma start test/resources/karma.conf.js"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/ivonet/java-angular-seed"

  },
  "author": "Ivo Woltring",
  "license": "Apache 2.0",
  "bugs": {
    "url": "https://github.com/ivonet/java-angular-seed/issues"
  },
  "homepage": "https://github.com/ivonet/java-angular-seed"
}

Is this ok? (yes)

现在将以下内容添加到文件中:_ _ _ _ _ _ _。

A371868_1_En_10_Fig11_HTML.jpg

图 10-11。

Additional configuration file for the Angular JS example application

A371868_1_En_10_Fig10_HTML.jpg

图 10-10。

Configuration file for the Angular JS example

A371868_1_En_10_Fig9_HTML.jpg

图 10-9。

Building the Maven stub for the Angular JS project successfully on the command line

{
  "name": "java-angular-seed",
  "private": true,
  "version": "0.0.0",
  "description": "A starter project for AngularJS combined with java and maven",
  "repository": "https://github.com/ivonet/java-angular-seed",
  "license": "Apache 2.0",
  "devDependencies": {
    "bower": "¹.3.1",
    "http-server": "⁰.6.1",
    "karma": "∼0.12",
    "karma-chrome-launcher": "⁰.1.4",
    "karma-firefox-launcher": "⁰.1.3",
    "karma-jasmine": "⁰.1.5",
    "karma-junit-reporter": "⁰.2.2",
    "protractor": "∼0.20.1",
    "shelljs": "⁰.2.6"
  },
  "scripts": {
    "postinstall": "bower install",
    "prestart": "npm install",
    "start": "http-server src/main/webapp -a localhost -p 8000",
    "pretest": "npm install",
    "test": "karma start src/test/javascript/karma.conf.js",
    "test-single-run": "karma start src/test/javascript/karma.conf.js  --single-run",
    "preupdate-webdriver": "npm install",
    "update-webdriver": "webdriver-manager update",
    "preprotractor": "npm run update-webdriver",
    "protractor": "protractor src/test/javascript/protractor-conf.js",
    "update-index-async": "node -e \"require('shelljs/global'); sed('-i', /\\/\\/@@NG_LOADER_START@@[\\s\\S]*\\/\\/@@NG_LOADER_END@@/, '//@@NG_LOADER_START@@\\n' + cat('src/main/webapp/vendor/angular-loader/angular-loader.min.js') + '\\n//@@NG_LOADER_END@@', 'src/main/webapp/index.html');\""
  }
}

{
    "directory": "src/main/webapp/vendor"
}
bower install angular#1.3.0-beta.14
bower install angular-route#1.3.0-beta.14
bower install angular-animate#1.3.0-beta.14
bower install angular-mocks#1.3.0-beta.14
bower install angular-loader#1.3.0-beta.14
bower install bootstrap

bower init
[?] name: java-angularjs-seed
[?] version: 0.0.0
[?] description: A java / maven / angularjs seed project
[?] main file: src/main/webapp/index.html
[?] what types of modules does this package expose?
[?] keywords: java,maven,angularjs,seed
[?] authors: IvoNet
[?] license: Apache 2.0
[?] homepage: http://ivonet.nl
[?] set currently installed components as dependencies? Yes
[?] add commonly ignored files to ignore list? Yes
[?] would you like to mark this package as private which prevents it from being accidentally pub[?] would you like to mark this package as private which prevents it from being accidentally published to the registry? Yes

...

[?] Looks good? (Y/n) Y

{
    "name": "java-angularjs-seed",
    "version": "0.0.0",
    "authors": [
        "IvoNet <webmaster@ivonet.nl>"
    ],
    "description": "A java / maven / angularjs seed project",
    "keywords": [
        "java",
        "maven",
        "angularjs",
        "seed"
    ],
    "license": "Apache 2.0",
    "homepage": "http://ivonet.nl",
    "private": true,
    "ignore": [
        "**/.*",
        "node_modules",
        "bower_components",
        "src/main/webapp/vendor",

        "test",
        "tests"
    ],
    "dependencies": {
        "angular": "1.3.0-beta.14",
        "angular-loader": "1.3.0-beta.14",
        "angular-mocks": "1.3.0-beta.14",
        "angular-route": "1.3.0-beta.14",
        "bootstrap": "3.2.0"
    },
    "main": "src/main/webapp/index.html"
}
rm -rf ./src/main/webapp/vendor
npm install

现在我们配置。/src/test/JavaScript/karma . conf . js:

A371868_1_En_10_Fig13_HTML.jpg

图 10-13。

Data configuration in the package.json file

A371868_1_En_10_Fig12_HTML.jpg

图 10-12。

Console result of Angular component install

module.exports = function(config){
  config.set({

    basePath : '../../../',

    files : [
      'src/main/webapp/vendor/angular**/**.min.js',
      'src/main/webapp/vendor/angular-mocks/angular-mocks.js',
      'src/main/webapp/js/**/*.js',
      'src/test/javascript/unit/**/*.js'
    ],

    autoWatch : true,

    frameworks: ['jasmine'],

    browsers : ['Chrome'],

    plugins : [
            'karma-chrome-launcher',
            'karma-firefox-launcher',
            'karma-jasmine',
            'karma-junit-reporter'
            ],

    junitReporter : {
      outputFile: 'target/test_out/unit.xml',

      suite: 'src/test/javascript/unit'
    }

  });
};

把下面的内容放进去。/src/main/WEB app/we b-INF/beans . XML:

<?xml version="1.0" encoding="UTF-8"?>
<beans 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
       bean-discovery-mode="annotated">
</beans>

<project  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>nl.ivonet</groupId>
    <artifactId>java-angularjs-seed</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>

    <name>java-angularjs-seed Maven Webapp</name>

    <url>http://ivonet.nl</url>

    <properties>
        <artifact.name>app</artifact.name>
        <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-all</artifactId>
            <version>1.9.5</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>

            <version>7.0</version>
            <scope>provided</scope>
        </dependency>

    </dependencies>
    <build>
        <finalName>${artifact.name}</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <compilerArguments>
                        <endorseddirs>${endorsed.dir}</endorseddirs>
                    </compilerArguments>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.4</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.6</version>
                <executions>
                    <execution>
                        <phase>validate</phase>
                        <goals>
                            <goal>copy</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${endorsed.dir}</outputDirectory>
                            <silent>true</silent>
                            <artifactItems>
                                <artifactItem>
                                    <groupId>javax</groupId>
                                    <artifactId>javaee-endorsed-api</artifactId>

                                    <version>7.0</version>
                                    <type>jar</type>
                                </artifactItem>
                            </artifactItems>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

10.4 使用 d3.js、sigma.js 等

D3.js ( https://d3js.org )和 sigma.js ( http://sigmajs.org )是流行的用于数据可视化的 JavaScript 库。

d3 和 sigmajs 工具包可能实现的图形可视化示例

A371868_1_En_10_Fig15_HTML.jpg

图 10-15。

Another typical data visualization of a portion of a graph database

A371868_1_En_10_Fig14_HTML.jpg

图 10-14。

A portion of a sigma.js-based graph visualization example

我们可以手工制作用户界面来适应我们的应用程序,或者我们可以选择使用一些已经作为独立库、插件和工具包提供的复杂的可视化工具。

回想一下,我们也可以直接从图数据库中可视化数据集。例如,在 Neo4j 中,我们可以在加载 CSV 数据集后浏览萨克拉门托的犯罪统计数据。点击单个节点会导致字段摘要出现在图形显示的底部,如图 10-16 所示。

A371868_1_En_10_Fig16_HTML.jpg

图 10-16。

Browsing crime statistics as individual nodes from a query in a Neo4j graph database

10.5 摘要

在这一章中,我们看了分析问题的视觉方面:如何看到和理解我们分析过程的结果。可视化挑战的解决方案可以像 Excel 中的 CSV 报告一样简单,也可以是复杂的交互式仪表板。我们强调了 Angular JS 的使用,这是一个基于模型-视图-控制器(MVC)范式的复杂的可视化工具包。

在下一章中,我们将讨论基于规则的控制和编排模块的设计和实现。规则系统是一种在计算机软件中有着悠久历史的控制系统,并且随着时间的推移,已经在广泛的控制和调度应用中证明了它们的有效性。

我们将发现,基于规则的模块在分布式分析系统中是一个有用的组件,特别是对于在整个应用程序执行中调度和编排单个流程。

10.6 参考

福特,布莱恩和鲁贝克,卢卡斯。Angular JS 在行动。马萨诸塞州波士顿:奥赖利出版社,2015 年。

亚当·弗里曼。亲角。纽约州纽约市:阿普瑞斯出版社,2014 年。

弗里斯比,马特。AngularJS Web 应用程序开发指南。英国伯明翰:PACKT 出版社,2013 年。

默里斯科特。面向 Web 的交互式数据可视化。马萨诸塞州波士顿:奥赖利出版社,2013 年。

皮考夫,克利福德 a,图克斯伯里,斯图尔特 k(编辑)。科学可视化的前沿。纽约州纽约市:威利-Interscience,1994 年,

泰勒斯威兹克。用 d3.js 实现数据可视化。英国伯明翰:PACKT 出版公司,2013 年。

沃尔夫,罗伯特 s,耶格尔,拉里。自然现象的可视化。纽约州纽约市:泰洛斯/施普林格出版社,1993 年。

朱,尼克齐。用 D3.js Cookbook 实现数据可视化。英国伯明翰:PACKT 出版社,2013 年。

十一、生物信息学案例研究:分析显微镜载玻片数据

在这一章中,我们描述了一个分析显微载玻片数据的应用程序,例如在对病人样本的医学检查或犯罪现场的法医证据中可能发现的数据。我们举例说明了 Hadoop 系统如何用于组织、分析和关联生物信息学数据。

Note

本章使用一组免费提供的果蝇图像来展示如何分析显微镜图像。严格地说,这些图像来自电子显微镜,它能够实现比你可能在高中生物课上第一次遇到的普通光学显微镜更高的图像放大倍数和分辨率。然而,对传感器数据输出的分布式分析的原理是相同的。例如,您可以使用来自小型无人机的图像,并对无人机相机输出的图像进行分析。软件组件和许多分析操作保持不变。

11.1 生物信息学简介

生物学作为一门科学有着悠久的历史,跨越了许多世纪。然而,只是在过去的五十年左右,生物数据作为计算机数据才成为理解信息的一种方式。

生物信息学是将生物数据理解为计算机数据,并对计算机数据进行有规律的分析。我们通过利用专门的库来翻译和验证生物和医学数据集中包含的信息来执行生物信息学,这些数据包括 x 射线、显微镜载玻片图像、化学和 DNA 分析、传感器信息(如心电图、MRI 数据)以及许多其他类型的数据源。

光学显微镜已经存在了数百年,但是直到最近,图像处理软件才开始分析显微镜载玻片图像。最初,这些分析是以非常特别的方式进行的。然而,现在显微镜载玻片图像本身已经成为“大数据”集,可以通过使用数据分析管道进行分析,正如我们在整本书中所描述的那样。

在这一章中,我们检查了一个分布式分析系统,该系统专门用于执行我们在图 8-1 中看到的自动化显微镜载玻片分析。在我们的其他例子中,我们将使用标准的第三方库在 Apache Hadoop 和 Spark 基础设施上构建我们的分析系统。

对于医学生物信息学的技术和算法的深入描述,参见 Kalet (2009)。

在我们深入到这个例子之前,我们应该再次强调在前面介绍的节点中提出的观点。无论我们使用电子显微镜图像、显微镜载玻片的光学图像,还是更复杂的图像,例如通常代表 X 射线的 DICOM 图像。

Note

本案例研究需要几个特定领域的软件组件,包括一些专门设计的软件包,用于将显微镜及其摄像头集成到标准图像处理应用中。

我们将在本章讨论的示例代码基于图 11-1 所示的架构。大多数情况下,我们并不关心机械装置的物理力学,除非我们想要精确控制显微镜的设置。分析系统从该过程的图像采集部分结束的地方开始。与我们所有的示例应用程序一样,在开始定制代码之前,我们会经历一个简单的技术堆栈——组装阶段。使用显微镜是图像处理的一个特例,即“作为大数据的图像”,我们将在第十四章中对此进行更详细的讨论。

A371868_1_En_11_Fig1_HTML.jpg

图 11-1。

A microscope slide analytics example with software and hardware components

当我们为我们的技术堆栈选择软件组件时,我们也发展了我们希望在软件中实现的高层次图表。这种想法的一个结果可能如图 11-2 所示。我们有数据源(主要来自显微镜摄像头)、处理元素、分析元素和结果持久性。其他一些组件也是必要的,比如保存中间结果的缓存存储库。

A371868_1_En_11_Fig2_HTML.jpg

图 11-2。

A microscope slide software architecture: high-level software component diagram

11.2 自动化显微镜介绍

图 11-3 至 11-5 显示了载玻片在自动显微镜中经历的阶段。

A371868_1_En_11_Fig5_HTML.jpg

图 11-5。

Color-coded regions in the image

A371868_1_En_11_Fig4_HTML.jpg

图 11-4。

Contour extraction from the microscope image

A371868_1_En_11_Fig3_HTML.jpg

图 11-3。

Original electron microscope slide image, showing a fruit fly tissue slice

我们可以使用组织切片的几何模型,如图 11-6 所示。

A371868_1_En_11_Fig6_HTML.jpg

图 11-6。

Geometric computation of slice dimensions

我们可以使用三维可视化工具来分析一堆神经组织切片,如图 11-7 和 11-8 中的例子所示。

A371868_1_En_11_Fig8_HTML.jpg

图 11-8。

Another example of organizing neural tissue

A371868_1_En_11_Fig7_HTML.jpg

图 11-7。

An example of analyzing slices of neural tissue

11.3 代码示例:用图像填充 HDFS

我们将使用 HIPI 包( http://hipi.cs.virginia.edu/gettingstarted.html )将图像摄取到 HDFS。Apache Oozie 可以用来安排导入。我们可以按照 HIPI 的在线说明,从基本的 Hadoop 工作开始:

package com.apress.probda.image;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;
public class ImageProcess extends Configured implements Tool {
  public int run(String[] args) throws Exception {
    System.out.println("---- Basic HIPI Example ----");
    return 0;
  }
  public static void main(String[] args) throws Exception {

    ToolRunner.run(new ImageProcess(), args);
    System.exit(0);
  }
}

编辑、编译和运行程序以验证结果。

程序的第二次迭代如下:

package com.apress.probda.image;
import org.hipi.image.FloatImage;
import org.hipi.image.HipiImageHeader;
import org.hipi.imagebundle.mapreduce.HibInputFormat;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import java.io.IOException;
public class ImageProcess extends Configured implements Tool {

  public static class ImageProcessMapper extends Mapper<HipiImageHeader, FloatImage, IntWritable, FloatImage> {
    public void map(HipiImageHeader key, FloatImage value, Context context)
      throws IOException, InterruptedException {
    }
  }
  public static class ImageProcessReducer extends Reducer<IntWritable, FloatImage, IntWritable, Text> {
    public void reduce(IntWritable key, Iterable<FloatImage> values, Context context)
      throws IOException, InterruptedException {
    }
  }
  public int run(String[] args) throws Exception {
    // Check input arguments
    if (args.length != 2) {
      System.out.println("Usage: imageProcess <input HIB> <output directory>");
      System.exit(0);
    }
    // Initialize and configure MapReduce job
    Job job = Job.getInstance();
    // Set input format class which parses the input HIB and spawns map tasks
    job.setInputFormatClass(HibInputFormat.class);
    // Set the driver, mapper, and reducer classes which express the computation
    job.setJarByClass(ImageProcess.class);
    job.setMapperClass(ImageProcessMapper.class);
    job.setReducerClass(ImageProcessReducer.class);
    // Set the types for the key/value pairs passed to/from map and reduce layers
    job.setMapOutputKeyClass(IntWritable.class);
    job.setMapOutputValueClass(FloatImage.class);
    job.setOutputKeyClass(IntWritable.class);
    job.setOutputValueClass(Text.class);
    // Set the input and output paths on the HDFS
    FileInputFormat.setInputPaths(job, new Path(args[0]));
    FileOutputFormat.setOutputPath(job, new Path(args[1]));

    // Execute the MapReduce job and block until it complets
    boolean success = job.waitForCompletion(true);

    // Return success or failure
    return success ? 0 : 1;
  }
  public static void main(String[] args) throws Exception {
    ToolRunner.run(new ImageProcess(), args);
    System.exit(0);
  }
}

在代码贡献中寻找完整的代码示例。

A371868_1_En_11_Fig9_HTML.jpg

图 11-9。

Successful population of HDFS with University of Virginia’s HIPI system

通过在命令行中键入以下命令,检查图像是否已使用 HibInfo.sh 工具成功加载:

tools/hibInfo.sh flydata3.hib --show-meta

您应该会看到类似于图 11-10 中的结果。

A371868_1_En_11_Fig10_HTML.jpg

图 11-10。

Successful description of HDFS images (with metadata information included)

11.4 摘要

在本章中,我们描述了一个使用分布式生物信息学技术来分析显微镜载玻片数据的示例应用程序。

在下一章,我们将讨论一个基于贝叶斯分类和数据建模方法的软件组件。这被证明是一种非常有用的技术,可以补充我们的分布式数据分析系统,并已被用于各种领域,包括金融、法医和医疗应用。

11.5 参考

格哈德,斯蒂芬,芬克,简,马特尔,朱利安,卡多纳,阿尔伯特,和费特,理查德。"神经组织的分段各向异性系统数据集."检索到 2013 年 11 月 20 日 16:09(格林尼治时间) http://dx.doi.org/10.6084/m9.figshare.856713

生物医学信息学原理。英国伦敦:学术出版社 Elsevier,2009 年。

《计算机视觉的特征提取和图像处理》,第三版。英国伦敦:学术出版社 Elsevier,2008 年。

十二、贝叶斯分析组件:识别信用卡欺诈

在这一章中,我们描述了一个贝叶斯分析软件组件插件,该插件可用于分析信用卡交易流,以识别非法用户对信用卡的欺诈性使用。

Note

我们将主要使用 Apache Mahout 提供的朴素贝叶斯实现,但是我们将讨论使用贝叶斯分析的几种可能的解决方案。

12.1 贝叶斯分析简介

贝叶斯网络(也称为信念网络或概率因果网络)是观察、实验或假设的表示。“信念”和“贝叶斯网络”的整个概念是相辅相成的。当我们进行物理实验时,比如使用盖革计数器来识别放射性矿物,或者对土壤样本进行化学测试来推断天然气、煤炭或石油的存在,这些实验的结果都与“信念因素”有关。实验有多精确?实验的“数据模型”——前提、数据、数据变量之间的关系、方法——有多可靠?而我们又有多相信实验的“结论”呢?幸运的是,我们在过去几章中建立的许多基础设施对于处理各种贝叶斯技术非常有用,尤其是图数据库。几乎所有的贝叶斯网络问题都受益于用图形表示——毕竟,它们是网络——图数据库可以帮助无缝表示贝叶斯问题。

Note

贝叶斯分析是一个不断发展的概念和技术的巨大领域,现在包括深度学习和机器学习方面。本章末尾的一些参考资料提供了到目前为止在贝叶斯分析中使用的概念、算法和技术的概述。

贝叶斯技术与一个正在发生的金融问题特别相关:识别信用卡欺诈。让我们来看看一个简单的信用卡欺诈算法,如图 18-1 所示。所示的实现和算法基于 Triparthi 和 Ragha (2004)的工作。

我们将描述如何基于图 12-1 所示的算法构建一个分布式信用卡欺诈检测器,使用前几章中描述的一些现在已经很熟悉的策略和技术。

A371868_1_En_12_Fig1_HTML.jpg

图 12-1。

A credit card fraud detection algorithm, following Triparthi and Ragha (2004)

首先:将一个环境变量添加到您的。该应用程序的 bash_profile 文件:

  export CREDIT_CARD_HOME=/Users/kkoitzsch/probda/src/main/resources/creditcard

首先,让我们获取一些信用卡测试数据。我们从在 https://www.cs.purdue.edu/commugrate/data/credit_card/ 发现的数据集开始。这个数据集是 2009 年一个代码挑战的基础。我们只对这些文件感兴趣:

DataminingContest2009.Task2.Test.Inputs
DataminingContest2009.Task2.Train.Inputs
DataminingContest2009.Task2.Train.Targets

将文件下载到$CREDIT_CARD_HOME/data

让我们看看信用卡交易记录的结构。CSV 文件中的每一行都是由以下字段组成的交易记录:

amount,hour1,state1,zip1,custAttr1,field1,custAttr2,field2,hour2,flag1,total,field3,field4,indicator1,indicator2,flag2,flag3,flag4,flag5
000000000025.90,00,CA,945,1234567890197185,3,redjhmbdzmbzg1226@sbcglobal.net,0,00,0,000000000025.90,2525,8,0,0,1,0,0,2
000000000025.90,00,CA,940,1234567890197186,0,puwelzumjynty@aol.com,0,00,0,000000000025.90,3393,17,0,0,1,1,0,1
000000000049.95,00,CA,910,1234567890197187,3,quhdenwubwydu@earthlink.net,1,00,0,000000000049.95,-737,26,0,0,1,0,0,1
000000000010.36,01,CA,926,1234567890197202,2,xkjrjiokleeur@hotmail.com,0,01,1,000000000010.36,483,23,0,0,1,1,0,1
000000000049.95,01,CA,913,1234567890197203,3,yzlmmssadzbmj@socal.rr.com,0,01,0,000000000049.95,2123,23,1,0,1,1,0,1

…以及更多。

查看这个数据集中 CSV 行的标准结构,我们注意到关于字段 4 的一些情况:虽然它有一个 16 位的类似信用卡的代码,但它不符合可以通过 Luhn 测试的标准有效信用卡号。

我们编写一个程序,将事件文件修改为更合适的形式:每个记录的第四个字段现在将包含一个“有效的”Visa 或 Mastercard 随机生成的信用卡号,如图 12-2 所示。我们想引入一些“坏的”信用卡号码,以确保我们的检测器能够发现它们。

A371868_1_En_12_Fig2_HTML.jpg

图 12-2。

Merging valid and invalid “real” credit card numbers with test data

12.2 用于信用卡欺诈检测的贝叶斯组件

原则上,从数据集中识别信用卡欺诈的贝叶斯组件与我们讨论的许多其他类型的数据管道是相同的。这又回到了本书的基本原则:分布式分析系统总是某种数据管道,某种工作流处理。可以使用不同的布置、配置和技术选择,但是就整体设计而言,它们共享一些基本特性。

12.2.1 信用卡验证基础

我们从信用卡验证的基本原则开始。使用 Luhn 检查可以确定信用卡号码有效,如清单 12-1 所示。

public static boolean checkCreditCard(String ccNumber)
    {
            int sum = 0;
            boolean alternate = false;
            for (int i = ccNumber.length() - 1; i >= 0; i--)
            {
                    int n = Integer.parseInt(ccNumber.substring(i, i + 1));
                    if (alternate)
                    {
                            n *= 2;
                            if (n > 9)
                            {
                                    n = (n % 10) + 1;
                            }
                    }
                    sum += n;
                    alternate = !alternate;

            }
            return (sum % 10 == 0);
    }

Luhn 信用卡卡号验证算法如图 12-3 流程图所示。

A371868_1_En_12_Fig3_HTML.jpg

图 12-3。

The simple Luhn credit card validation algorithm .

我们可以将机器学习技术添加到欺诈检测组合中。

看一下图 12-4 中的算法流程图。该过程包括训练阶段和检测阶段。

A371868_1_En_12_Fig4_HTML.jpg

图 12-4。

Training and detection phases of a credit card fraud detection algorithm

在训练阶段,聚类过程创建数据模型。

在检测阶段,先前创建的模型用于检测(识别)新的输入事件。

训练/检测程序的实现如图 12-5 和图 12-6 所示。

A371868_1_En_12_Fig6_HTML.jpg

图 12-6。

Starting the Apache Storm supervisor from the command line

A371868_1_En_12_Fig5_HTML.jpg

图 12-5。

Starting Zookeeper from the command line or script is straightforward

您可以运行代码贡献中的完整示例。

12.3 摘要

在这一章中,我们讨论了一个围绕贝叶斯分类器开发的软件组件,专门用于识别数据集中的信用卡欺诈。这个应用程序已经被重做和重新思考了很多次,在这一章中,我们想要展示一个实现,在这个实现中,我们使用了我们在整本书中已经开发的一些软件技术来激发我们的讨论。

在下一章,我们将讨论一个现实世界的应用:用计算机模拟寻找矿产资源。“资源寻找”应用程序是一种常见的程序类型,在这种程序中,对现实世界的数据集进行挖掘、关联和分析,以确定“资源”的可能位置,这可能是从地下的石油到无人机图像中的树木簇,或者显微镜载玻片上的特定类型的细胞。

12.4 参考

贝叶斯统计导论。纽约州纽约市:约翰·威利父子公司,2004 年。

专家系统和概率网络模型。纽约州纽约市:施普林格出版社,1997 年。

阿德南·达威奇。贝叶斯网络建模与推理。纽约州纽约市:剑桥大学出版社,2009 年。

昆切娃,柳德米拉。组合模式分类器:方法和算法。新泽西州霍博肯:威利跨科学,2004 年。

专家系统中的概率推理:理论与算法。纽约州纽约市:约翰·威利父子公司,1990 年。

尚克,罗杰,里斯贝克,克里斯托弗。内部计算机理解:五个程序加缩影。新泽西州希尔斯代尔:劳伦斯厄尔鲍姆联合公司,1981 年。

特里帕蒂,克里希纳·库马尔和拉加,拉塔。“信用卡欺诈检测的混合方法”,国际软计算与工程杂志(IJSCE) ISSN: 2231-2307,第 3 卷,第 4 期,2013 年 9 月。

十三、寻找石油:Apache Mahout 地理数据分析

在本章中,我们将讨论分布式大数据分析的一个特别有趣的应用:使用一个领域模型来寻找有价值矿物的可能地理位置,如石油、铝土矿(铝矿石)或天然气。我们将介绍一些方便的技术包来获取、分析和可视化结果数据,尤其是那些非常适合处理地理位置和其他地理相关数据类型的数据。

Note

在本章中,我们使用 Elasticsearch 版。这个版本还提供了使用 MapQuest 地图可视化的工具,您将在本章和本书的其他地方看到。

13.1 基于域的 Apache Mahout 推理介绍

大数据分析有许多特定于领域的应用,我们可以使用 Apache Mahout 来有效地解决以领域为中心的问题。有时分析过程中涉及的知识库极其复杂;数据集可能不精确或不完整,或者数据模型可能有缺陷,考虑不周,或者根本不适合解决方案需求。Apache Mahout 作为一个久经考验的机器学习基础设施组件,以及它提供备受信任的算法和工具的方式,消除了构建基于领域的系统的一些头痛。

这种以领域为中心的应用程序的一个相关示例是“资源查找器”应用程序类型。这包括处理大量时间戳数据的分析系统(事实上,有时需要几年或几十年);验证、协调和关联数据;然后,通过使用特定领域的数据模型,计算分析(以及作为这些分析的输出的结果数据可视化),以识别特定“资源”(通常在地球或海洋中)的位置。不用说,数据的时间戳、校对和管理,以及地理位置数据的准确处理,是从这样的“资源查找器”系统产生准确、相关和及时的假设、解释、总结、建议和可视化的关键。

A371868_1_En_13_Fig1_HTML.jpg

图 13-1。

An abstract component view of a geographical data analytics process

在这种类型的系统中,根据可汗的“勘探者专家系统” https://www.scribd.com/doc/44131016/Prospector-Expert-System ,通常使用四种类型的知识源:规则(类似于 JBoss Drools 系统中发现的那些)、语义网和框架(一种有点混合的方法,在 Shank 和艾贝尔森(1981)中彻底讨论过)。像其他面向对象的系统一样,框架支持继承、持久化等等。

如图 16 所示。1 ,我们展示了一个“假设生成器”的抽象视图,通过这种方式,我们可以预测资源位置,例如石油。这个例子的假设生成器是基于 JBoss Drools 的,我们在第八章中讨论过。

A371868_1_En_13_Fig2_HTML.jpg

图 13-2。

A Mahout-based software component architecture for geographical data analysis

在示例程序中,我们使用一个 DBF 导入程序,如清单 13-1 所示,从 DBF 导入数据。

Elasticsearch 是一个非常灵活的数据仓库,可以导入各种数据格式。

下载一些标准数据集来适应弹性搜索机制。以下是一些示例:

https://www.elastic.co/guide/en/kibana/3.0/snippets/logs.jsonl

以及在

加载样本数据集只是为了最初测试 Elasticsearch 和 Kibana。你可以试试这些:

curl -XPOST 'localhost:9200/bank/account/_bulk?pretty' --data-binary @accounts.json
curl -XPOST 'localhost:9200/shakespeare/_bulk?pretty' --data-binary @shakespeare.json
curl -XPOST 'localhost:9200/_bulk?pretty' --data-binary @logs.jsonl

Note

在前一章中,我们使用 Apache Tika 来读取 DBF 文件。在这一章中,我们将使用 Sergey Polovko (Jamel)的另一种 DBF 读本。你可以从 GitHub 的 https://github.com/jamel/dbf 下载这个 DBF 阅读器。

package com.apress.probda.applications.oilfinder;

import java.io.File;
import java.util.Date;
import java.util.List;

/** We use a standard DBF reader from github.
 *
 */
import org.jamel.dbf.processor.DbfProcessor;
import org.jamel.dbf.processor.DbfRowMapper;
import org.jamel.dbf.utils.DbfUtils;

public class Main {

        static int rownum = 0;

        public static void main(String[] args) {
        File dbf = new File("BHL_GCS_NAD27.dbf"); // pass in as args[0]

        List<OilData> oildata = DbfProcessor.loadData(dbf, new DbfRowMapper<OilData>() {
            @Override
            public OilData mapRow(Object[] row) {

                for (Object o : row) {

                        System.out.println("Row object:  " + o);

                }
                System.out.println("....Reading row: " + rownum + " into elasticsearch....");

                rownum++;

                System.out.println("------------------------");
                return new OilData(); // customize your constructor here
           }
        });

       // System.out.println("Oil Data: " + oildata);
    }
}

/** We will flesh out this information class as we develop the example.
 *
 * @author kkoitzsch
 *
 */
class OilData {

        String _name;
        int _value;
        Date _createdAt;

        public OilData(String... args){

        }

        public OilData(){

        }

        public OilData(String name, int intValue, Date createdAt) {
                _name = name;
                _value = intValue;
                _createdAt = createdAt;
        }

}

Listing 13-1.A simple DBF reader for geological data source information

当然,阅读地理数据(包括 DBF 文件)只是分析过程的第一步。

A371868_1_En_13_Fig3_HTML.jpg

图 13-3。

A test query to verify Elasticsearch has been populated correctly with test data sets

使用 Elasticsearch-Hadoop 连接器( https://www.elastic.co/products/hadoop ))将 Elasticsearch 与基于 Hadoop 的应用程序组件连接起来。

要了解更多关于 Hadoop-Elasticsearch 连接器的信息,请参考网页 http://www.elastic.co/guide/en/elasticsearch/hadoop/index.html

A371868_1_En_13_Fig4_HTML.jpg

图 13-4。

The Elasticserch-Hadoop connector and its relationship to the Hadoop ecosystem and HDFS

我们可以将 Elasticsearch-Hadoop 连接器与 SpatialHadoop 结合使用,为我们想要处理的基于地理位置的数据提供分布式分析功能。

我们可以设定值的阈值,并提供对“兴趣点”(间距、每个类别有多少个兴趣点,以及其他因素)的约束,以生成显示预期结果可能性的可视化。

某些期望结果的证据和概率可以存储在同一个数据结构中,如图 13-5 所示。蓝色区域表示有证据支持预期结果的可能性,在这种情况下,表示存在石油或石油相关产品。红色和黄色圆圈表示假设空间中的高兴趣点和中等兴趣点。如果网格坐标恰好是地理位置,人们可以在类似于图 13-6 和图 13-7 所示的地图上绘制由此产生的假设。

A371868_1_En_13_Fig7_HTML.jpg

图 13-7。

Using the Spatial Solr Sandbox tool to query a Solr repository for geolocation data

A371868_1_En_13_Fig6_HTML.jpg

图 13-6。

Using Kibana and Elasticsearch for map visualiation in Texas example using latitude and logitude, and simple counts of an attribute

A371868_1_En_13_Fig5_HTML.jpg

图 13-5。

Probability/evidence grid: a simple example of grid-based hypothesis analytic

我们可以运行简单的测试来确保 Kibana 和 Elasticsearch 正确显示我们的地理位置数据。

现在是时候描述我们的 Mahout 分析组件了。对于这个例子,我们将保持分析非常简单,以概述我们的思维过程。不用说,现实世界资源寻找者的数学模型需要更加复杂,适应性更强,并允许数学模型中有更多的变量。

我们可以使用另一个非常有用的工具,通过 Ryan McKinley 的 Spatial Solr 沙盒工具( https://github.com/ryantxu/spatial-solr-sandbox )来原型化和查看驻留在 Solr 中的一些数据内容。

13.2 智能制图系统和 Hadoop 分析

智能制图(SC)系统是一种特殊类型的基于数据管道的软件应用程序,用于处理卫星图像,将卫星图像与已知精度的图像数据库(称为“地面实况”数据库)进行比较。地面实况数据库提供标准化的地理位置信息(例如矩形图像的四个角的纬度和经度、图像分辨率、比例和方向参数)以及帮助匹配过程的其他信息。

SC 系统向人工评估团队提供有用的图像匹配反馈,并可以帮助工程师和质量保证人员交互式地查看、验证、编辑、注释和比较输入的卫星图像与“地面实况”图像和元数据。由于消除了由于疲劳、观察误差等引起的人为误差,使用 SC 系统可以使一小组分析员在更短的时间内完成一个更大的评估小组的工作,并得到更准确的结果。

SC 系统可以使用各种传感器类型、图像格式、图像分辨率和数据摄取率,并可以使用机器学习技术、基于规则的技术或推理过程来改进和调整特征识别,以便在卫星图像特征(如位置(纬度经度信息)、图像特征(如湖泊、道路、飞机跑道或河流)和人造物体(如建筑物)之间进行更准确和有效的匹配。购物中心或机场)。

SC 系统的用户可以提供关于所计算的匹配的准确性的反馈,这反过来允许随着时间的推移,随着细化的进行,匹配过程变得更加准确。该系统可以专门对用户选择的特征进行操作,例如道路网络或诸如建筑物的人造特征。

最后,SC 匹配过程以报告或仪表板显示的形式向用户提供图像和地面真实数据之间匹配的准确性测量,以及完整的误差和异常值信息。

SC 系统可以提供一种高效且经济的方法来评估卫星图像的质量、精度和图像序列内的一致性,并可以解决高分辨率精度、任务完成时间、可扩展性和卫星图像的近实时处理等问题,以及为各种卫星图像评估任务提供高性能软件解决方案。

以地理位置为中心的系统中包含的一个有用的组件是 Spatial4j ( https://github.com/locationtech/spatial4j ),这是一个为 Java 程序提供空间和地理位置功能的助手库,它是从一些早期的工作(如前面讨论的 Spatial Solr 沙盒工具包)发展而来的。

A371868_1_En_13_Fig8_HTML.jpg

图 13-8。

Running the tests for Spatial4j, a commonly used geolocation java toolkit library

另一个有用的软件库是 SpatialHadoop ( http://spatialhadoop.cs.umn.edu )),这是 Hadoop 本身的一个基于 MapReduce 的扩展。SpatialHadoop 提供空间数据类型、索引和操作,允许使用简单的高级语言来控制基于 Hadoop 的程序对以地理位置为中心的数据的处理。

A371868_1_En_13_Fig9_HTML.jpg

图 13-9。

Generating a data file for use with SpatialHadoop

13.3 摘要

在本章中,我们讨论了使用大数据分析作为工具来搜索石油和其他自然资源的理论和实践。我们能够加载 DBF 数据,用基于 Mahout =的代码操作和分析数据,并将结果输出到一个简单的可视化工具。我们还讨论了一些包含在任何以地理位置为中心的应用程序中的有用的库,比如 Spatial4j 和 SpatialHadoop。

在下一章,我们将讨论大数据分析的一个特别有趣的领域:使用图像及其元数据作为我们分析管道的数据源。

13.4 参考

乔戈、拉杜、辛曼、马修·李和鲁索、罗伊。弹性搜索在行动。塞瓦斯托波尔,加利福尼亚州:奥赖利出版社,2015 年。

贾科姆利,皮耶罗。阿帕奇看象人食谱。英国伯明翰:PACKT 出版社,2013 年。

肖恩·欧文、罗宾·阿尼尔、泰德·邓宁和艾伦·弗里德曼。看象人在行动。纽约州谢尔特岛:曼宁出版公司,2011 年。

十四、“作为大数据的图像”系统:一些案例研究

在本章中,我们将简要介绍一个示例工具包,即 Image as Big Data Toolkit (IABDT),这是一个基于 Java 的开源框架,用于以可扩展、高度可用且可靠的方式执行各种分布式图像处理和分析任务。IABDT 是过去几年开发的图像处理框架,旨在应对大数据技术的快速发展,尤其是分布式图像处理技术。IABDT 设计为接受多种格式的图像、信号、传感器数据、元数据和视频作为数据输入。

讨论了图像分析、大数据存储以及图像和图像衍生数据的压缩方法的一般架构,以及图像作为大数据分析的标准技术。作为我们的图像分析架构的一个示例实现,IABDT 解决了图像分析开发人员经常遇到的一些挑战,包括将图像导入分布式文件系统或缓存、图像预处理和特征提取、应用分析和结果可视化。最后,我们展示了 IABDT 的一些特性,特别强调了显示、演示、报告、仪表板构建和用户交互案例研究,以激励和解释我们的设计和方法堆栈选择。

14.1 图像作为大数据的介绍

“大数据”软件技术发展的快速变化使得执行图像分析(自动分析和解释来自计算机图像的复杂半结构化和非结构化数据集)变得比以前更加容易、准确、灵活和快速,即使使用最复杂和高性能的单台计算机或数据中心也是如此。包括 Hadoop、Apache Spark 和分布式计算系统在内的“大数据处理范式”使许多应用领域受益于图像分析和将图像作为大数据处理,包括医疗、航空航天、地理空间分析和文档处理应用。模块化、高效和灵活的工具包仍处于形成或实验开发阶段。图像处理组件、数据流控制和图像分析的其他方面的集成仍然是不明确的和尝试性的。大数据技术的快速变化甚至使得选择“技术堆栈”来构建图像分析应用程序都成了问题。为了解决图像分析应用开发中的这些挑战,我们开发了一个专门用于分布式大数据图像分析支持的架构和基线框架实现。

在过去,低级图像分析和机器学习模块被结合在一个计算框架内,以完成特定领域的任务。随着分布式处理框架(如 Hadoop 和 Apache Spark)的出现,可以构建与其他分布式框架和库无缝连接的集成图像框架,其中“图像作为大数据”的概念已经成为框架架构的基本原则。

我们的示例工具包 IABDT 提供了一个灵活的、面向插件的模块化架构。这使得将许多不同的软件库、工具包、系统和数据源结合在一个集成的分布式计算框架中成为可能。IABDT 是一个以 Java 和 Scala 为中心的框架,因为它使用 Hadoop 及其生态系统以及 Apache Spark 框架及其生态系统来执行图像处理和图像分析功能。

IABDT 可与 NoSQL 数据库(如 MongoDB、Neo4j、Giraph 或 Cassandra)以及更传统的关系数据库系统(如 MySQL 或 Postgres)一起使用,以存储计算结果并用作图像处理管道中预处理和后处理阶段生成的中间数据的数据储存库。这些中间数据可能包括要素描述符、影像金字塔、边界、视频帧、辅助传感器数据(如激光雷达)或元数据。像 Apache Camel 和 Spring Framework 这样的软件库可以作为“粘合剂”将组件相互集成。

创建 IABDT 的动机之一是提供一个模块化的可扩展基础设施,用于执行预处理、分析以及分析结果的可视化和报告——特别是针对图像和信号。它们利用了分布式处理的能力(就像 Apache Hadoop 和 Apache Spark 框架一样),并受到 OpenCV、BoofCV、HIPI、Lire、Caliph、Emir、Image Terrier、Apache Mahout 等工具包的启发。表 14-1 总结了这些图像工具包的特征和特性。IABDT 提供框架、模块化库和可扩展示例,使用高效、可配置和分布式数据流水线技术对图像执行大数据分析。

表 14-1。

Mainstream image processing toolkit features and characteristics

| 工具包名称 | 位置 | 工具语言 | 描述 | | --- | --- | --- | --- | | 开放计算机视觉 | opencv.org | 许多语言绑定,包括 Java | 通用编程图像处理工具包 | | BoofCV | boofcv.org | 爪哇 | 基于 Java 的图像处理工具包 | | 嘘嘘嘘嘘嘘嘘嘘嘘嘘嘘嘘嘘嘘嘘 | hipi.cs.virginia.edu | 爪哇 | Hadoop 工具包的图像处理 | | 阅读/卡利夫/埃米尔 | semanticmetadata.net | 爪哇 | 使用 Lucene 的图像搜索工具包和库 | | 影像梗 | imageterrier.org | 爪哇 | 基于 Lucene 搜索引擎的图像索引和搜索 | | Java 高级成像 | oracle.com/technetwork/java/javase/overview/in… | 爪哇 | 通用图像处理工具包,古老但仍然有用 |

如图 14-1 所示,大数据工具包和组件正在成为基于 Apache Hadoop 和 Apache Spark 的其他分布式软件包中的资源。

A371868_1_En_14_Fig1_HTML.jpg

图 14-1。

Image as Big Data tookits as distributed systems

IABDT 中实现的图 14-1 中模块类型的一些分布式实现包括:

遗传系统。有许多遗传算法特别适合于图像分析 1 ,包括对大型解决方案空间进行采样、特征提取和分类的技术。前两类技术更适用于分析过程和分布式分类技术的图像预处理和特征提取阶段,甚至是那些使用多个分类器的技术。

贝叶斯技术。贝叶斯技术包括大多数机器学习工具包中的朴素贝叶斯算法,还有更多。

Hadoop 生态系统扩展。可以在现有 Hadoop 组件的基础上构建新的扩展,以提供定制的“大数据图像”功能。

聚类、分类和推荐。这三种类型的分析算法存在于大多数标准库中,包括 Mahout、MLib 和 H2O,它们构成了更复杂的分析系统的基础。

混合系统将许多不同类型的组件集成到一个集成的整体中,以执行单一功能。通常,混合系统包含一个控制组件,它可能是基于规则的系统,如 Drools,或者是其他标准的控制组件,如 Oozie,它可能用于调度任务或其他目的,如 Luigi for Python ( https://github.com/spotify/luigi),它带有内置的 Hadoop 支持。如果您想试用 Luigi,请使用 Git 安装 Luigi,并将其克隆到一个方便的子目录中:

A371868_1_En_14_Fig2_HTML.jpg

图 14-2。

Image as Big Data tookits as distributed systems

git clone

https://github.com/spotify/luigi?cm_mc_uid=02629589701314462628476&cm_mc_sid_50200000=1457296715

cd to the bin directory and start the server

./luigid

14.2 使用 HIPI 系统的第一个代码示例

在本节中,我们将介绍 HIPI Hadoop 图像处理系统,并展示一些简单的示例,说明如何将其用作图像的分布式数据处理管道组件。

hipi.cs.virginia.edu 是一个非常有用的基于 Hadoop 的图像处理工具,它起源于弗吉尼亚大学。它与 OpenCV 等更主流的标准图像处理库集成,以 Hadoop 为中心的方式提供广泛的图像处理和分析技术。

HIPI 系统包含了几个用于基本 Hadoop-centric 图像处理任务的基本工具。

这些工具包括创建“HIB”文件(HIPI 图像包)的工具,如图 14-3 所示。

A371868_1_En_14_Fig3_HTML.jpg

图 14-3。

A HIPI image data flow, consisting of bunding, culling, map/shuffle and reduce to end result

HIPI 映像包或“HIB”是 HIPI 用来将映像分组到一个物理单元中的结构化存储方法。剔除阶段允许根据适当的程序标准过滤掉每个 HIB。被剔除的图像没有被完全解码,这使得 HIPI 管道更加有效。剔除阶段的输出产生如图所示的图像集。每个图像集都有自己的贴图阶段,随后是洗牌阶段和相应的减少步骤,以创建最终结果。因此,如您所见,HIPI 数据流类似于标准的地图缩减数据流过程。我们重现了图 14-4 中的 Hadoop 数据流过程,供您参考。

A371868_1_En_14_Fig4_HTML.jpg

图 14-4。

A reference diagram of the classic map-reduce data flow, for comparison with 14-3 Installing a Basic Hipi System

下面是基本的 HIPI 安装说明。

  1. 首先,查看 http://hipi.cs.virginia.edu/gettingstarted.html 的“开始使用”页面,了解系统的最新动态和/或变化。

  2. 安装基本的 HIPI 软件,如“入门”页面所示:

    git clone git@github.com:uvagfx/hipi.git
    
    

这将把源代码安装到一个“hipi”目录中。Cd 到这个“hipi”目录和“ls”目录来查看内容。您将需要一个 Gradle 构建工具安装程序来从源代码进行安装。最终的构建将类似于图 14-5 。

A371868_1_En_14_Fig5_HTML.jpg

图 14-5。

Successful Gradle installation of the HIPI toolkit

Gradle 是另一个有用的安装和构建工具,类似于 Maven。有些系统,比如 HIPI,使用 Gradle 比使用 Maven 等其他技术更容易安装。

A371868_1_En_14_Fig6_HTML.jpg

图 14-6。

Example using HIPI info utility: Mage info about a 10-image HIB in the HIPI system

然而,安装 HIPI 只是第一步!我们必须将我们的 HIPI 处理器与分析组件集成在一起,才能得出我们的结果。

14.3 BDA 图像工具包利用高级语言功能

使用 Python 等现代解释语言的能力,以及交互式读取-评估-打印循环(REPLs)和函数式编程,是大多数现代编程语言的特性,包括 Java 9、Scala 和交互式 Python。IABDT 使用这些现代编程语言特性使系统更容易使用,结果 API 代码更加简洁。

IABDT 与 Hadoop 2 和 Apache Spark 无缝集成,并使用 Mahout、MLib、H20 和 Sparkling Water 等标准分布式库来提供分析功能。我们讨论的一个案例研究也在 Hadoop 中使用了标准的以 Java 为中心的统计库,比如 R 和 Weka。

14.4 什么是图像数据分析?

图像数据分析应用与一般数据分析相同的一般原则、模式和策略。区别在于数据来源。我们摆脱了分析数字、行项目、文本、文档、日志条目和其他基于文本的数据源的传统观念。与基于文本的数据源不同,我们现在处理的数据要简单得多:信号(本质上是时间序列)和图像(可以是带有 RGB 值的彩色像素的二维图像,甚至是附加了元数据、地理位置和叠加信息的更奇特的图像类型)。

需要专门的工具包来执行基本的图像数据流水线操作。在顶层,提供了许多预编码和可定制的方法来帮助您。这些方法的分类如表 14-2 所示。

A371868_1_En_14_Fig7_HTML.jpg

图 14-7。

Architecture of the Image as Big Data Toolkit

表 14-3。

Display methods for visualization provided by the IABDT. Most object types in the IABDT may be displayed using similar methods

| 方法名称 | 方法签名 | 利用工具包 | 描述 | | --- | --- | --- | --- | | 显示 | 显示(图像,属性集) | BoofCV |   | | 显示 | 显示(图像金字塔,属性集) | BoofCV |   | | 显示 | 显示(图像集,属性集) | BoofCV |   | | 显示 | 显示(图像、功能集、属性集) | BoofCV |   | | 显示 | 显示(图像、地理位置模型、属性集) | BoofCV |   | | 显示 | 显示(图像、结果集、属性集) | BoofCV |   |

表 14-2。

A selection of methods from the Image as Big Data Toolkit

| 方法名称 | 方法签名 | 输出类型 | 描述 | | --- | --- | --- | --- | | EJRCL | EJRCL(图像,属性集) | 计算结果 | 边缘、交汇点、区域、轮廓和线 | | 创建图像金字塔 | imagePyramid(图像特性集) | 图像金字塔 | 一个图像转换为图像金字塔,参数化 | | 项目贝叶斯 | 项目贝叶斯(图像集,贝叶斯模型,属性集) | BayesianResult 结果 | 将图像集投影到贝叶斯假设空间中 | | 计算统计数据 | 计算机统计(图像,属性集) | 计算结果 | 针对单个图像或图像集或图像金字塔计算的基本统计数据 | | deepLearn | deepLearn(图像集,学习者,属性集) | LearnerResult | 使用标准的分布式深度学习算法来处理图像集或金字塔 | | 多分类 | 多分类(图像集,分类模型,属性集) | 分类结果 | 使用多个分类器对图像集或图像金字塔进行分类 |

图像数据源处理器是负责数据采集、图像清理、格式转换和其他操作的组件,用于将数据“处理”成其他管道组件可接受的格式。

分析引擎组件可以是支持库,如 R 和 Weka。

中间数据源是初始分析计算的输出。

用户控制仪表板是一个事件处理程序、交互式组件。

控制和配置模块由 Drools 之类的规则组件或其他规则引擎或控制组件组成,并且可能包含用于诸如调度、数据过滤和细化以及整个系统控制和配置任务之类的任务的其他“助手”库。通常,动物园管理员和/或馆长可以用于协调和编排控制和配置任务。

分布式系统基础结构模块包含底层支持和“助手”库。

持久结果储存库可以是各种类型的数据接收器中的任何一种,包括关系型、图形型或 NoSQL 型数据库。如果合适,也可以使用内存中的键值数据存储。

报告模块通常由老式的分析结果的表格或图表表示组成。

用户交互、控制和反馈是由 IABDT 交互模块提供的,它包括用于常见用例的默认仪表板。

可视化模块由支持库组成,用于显示图像、叠加图、特征位置和其他可视化信息,使交互和理解数据集更加容易。

14.5 交互模块和仪表板

为分布式图像处理系统开发适当的显示器和仪表板的能力是对已完成实现的评估、测试、概念验证和优化的必要辅助。

IABDT 直接支持构建基本的用户界面和仪表板。一个简单的用户界面如图 14-8 所示。

A371868_1_En_14_Fig8_HTML.jpg

图 14-8。

A simple user interface build with the IABDT

相同对象的统一视图、处理图像序列的图像显示和图像叠加功能都由 IABD 工具包提供。

仪表板、显示器和交互式界面——包括独立应用程序和基于网络的界面——可通过 IABDT 用户界面构建模块构建。原型 IABDT 支持标准类型的显示,包括覆盖和地理位置数据。

14.6 添加新的数据管道和分布式特征发现

使用 IABDT 设计新的分析数据流非常简单。来自算法的等式可以被转换成独立代码,以及从独立代码转换成 map/reduce 实现,利用为与 Hadoop/Spark 生态系统集成而提供的许多工具包,包括弗吉尼亚大学的 HIPI 系统(hipi.cs.virginia.edu),如下所述。

已经为基于 Spark 的系统明确开发了一些分布式图像处理功能,因此在这里可能需要稍微偏离一下 Apache Spark 与 Hadoop 的争论。最近在文献中有一些关于 Apache Spark 是否已经杀死了 map/reduce 范式以及“杀死”了 Hadoop 生态系统的有用性的争论(例如,Apache Mahout 库最初只支持 map/reduce,但后来发展到支持 Apache Spark 甚至 H20)。随着 IABDT 原型系统的发展和开发,我们改变了自己的观点(随着时间的推移,Apache Spark 越来越成为一股不可忽视的力量),并逐渐认识到 Hadoop 和 Spark 是密切互补的技术,根本不应该分开。因此,我们将 IABDT 工具包设计为一个模块化和极其灵活的系统,以便我们可以轻松地使用 Hadoop 生态系统组件和 Spark 组件,即使在“混合”数据流开发中同时使用 Hadoop 和 Spark 技术,其中来自 M/R 和内存(Hadoop 和 Spark)处理的组件合作提供最终结果。

14.7 示例:分布式特征发现算法

可以使用所谓的“Hu 矩”的概念来构建分布式特征发现算法

Hu 矩用于计算特征形状。

按照 Kulkani (1994)的说法,我们可以用下面的几个方程来表达这一数学问题。

标准几何矩可以计算如下:

$$ {m}_{pq} = {\displaystyle \sum_{x=-n}^n}{\displaystyle \sum_{y=-n}n}{x}p{y}^qg\left(x,y\right) $$

其中 g(x,y)是图像 g 的二维索引。所谓的中心矩可以定义为

$$ {m}_{pq} = {\displaystyle \sum_{x=-n}^n}{\displaystyle \sum_{y=-n}n}{\left(x-{x}{\prime}\right)}p {\left(y-{y}{\prime}\right)}^q\ g\ \left(x,\ y\right) $$

其中 x' = m 10 /m 00 ,y' = m 01 /m00

并且当针对比例不变性进行归一化时。

$$ {\mu}_{pq} = {m}_{pq}^{\gamma } $$

其中

$$ \gamma =\frac{\left(p+q\right)}{2}+1 $$

旋转和缩放不变的中心矩可以刻画如下:胡:

$$ {\phi}_1=\left({\boldsymbol{\mu}}_{20} + {\boldsymbol{\mu}}_{02}\right) $$

$$ {\phi}_{2 = }{\left({\mu}_{20} - {\mu}_{02}\right)}²+4{\mu}_{11}² $$

$$ {\phi}_3 = {\left({\boldsymbol{\mu}}_{30} - 3{\boldsymbol{\mu}}_{12}\right)}² + {\left(3{\boldsymbol{\mu}}_{21} - {\boldsymbol{\mu}}_{03}\right)}² $$

$$ {\phi}_4 = {\left(\ {\mu}_{30} + {\mu}_{12}\right)}² + {\left({\mu}_{21} + {\mu}_{03}\ \right)}² $$

$$ \begin{array}{l}{\phi}_5=\left({\mu}_{30} - 3{\mu}_{12}\right)\left({\mu}_{30} + {\mu}_{12}\right)\left[{\left({\mu}_{30}\kern0.5em + {\mu}_{12}\right)}²-3{\left(\ {\mu}_{21}+{\mu}_{03}\kern0.5em \right)}²\right]\kern0.5em +\ {}\left(3{\mu}_{21} - {\mu}_{03}\right)\left({\mu}_{21} + {\mu}_{03}\right)\left[3{\left({\mu}_{30} + {\mu}_{12}\right)}²-{\left({\mu}_{12}+{\mu}_{03}\right)}²\right]\end{array} $$

$$ {\phi}_6 = \left({\mu}_{20} - {\mu}_{02}\ \right)\ \left[\ {\left({\mu}_{30} + {\mu}_{12}\right)}²\ \hbox{--}\ {\left({\mu}_{21} + {\mu}_{03}\right)}²\right] + 4{\mu}_{11}\left(\kern0.5em {\mu}_{30}+{\mu}_{12}\right)\left(\kern0.5em {\mu}_{21} + {\mu}_{03}\right) $$

$$ {\phi}_7=\kern0.5em \left(3{\mu}_{21} - {\mu}_{03}\right)\left(\kern0.5em {\mu}_{30} + {\mu}_{12}\right)\left[\ {\left({\mu}_{30} + {\mu}_{12}\right)}²-3{\left({\mu}_{21}+{\mu}_{03}\right)}²\right]\kern0.75em  - \left({\mu}_{30}-3{\mu}_{12}\ \right)\left(\kern0.5em {\mu}_{12} + {\mu}_{03}\right)\left[\ {\left(3{\mu}_{30} + {\mu}_{12}\right)}² - {\left({\mu}_{21}+{\mu}_{03}\right)}²\kern0.5em \right] $$

Hadoop 中的 map/reduce 任务可以根据矩方程显式编码,首先用 java 进行实验,以测试程序逻辑并确保计算值符合预期,然后转换为适当的 map/reduce 结构。清单 14-1 中显示了 java 实现的草图。我们使用一个标准的 java 类 com . a press . prob da . core . computational result 来保存答案和“质心”(也是由我们的算法计算的):

public ComputationResult computeMoments(int numpoints, double[] xpts, double[] ypts)
    {
         int i;
           // array where the moments go
            double[] moments = new double[7];
         double xm.ym,x,y,xsq,ysq, factor;
         xm = ym = 0.0;
             for (i = 0; i<n; i++){
                        xm += xpts[i];
                        ym += ypts[i];
                }
        // now compute the centroid
        xm /= (double) n;
        ym /= (double) n;
        // compute the seven moments for the seven equations above
        for (i=0; i<7; i++){
        x =xpts[i]-xm;
        y = ypts[i]-ym;
        // now the seven moments
        moments[0] += (xsq=x*x); // mu 20
        moments[1] += x*y;       // mu 11
        moments[2] += (ysq = y * y); // mu 02
        moments[3] += xsq *x;        // mu 30
        moments[4] += xsq *y;        // mu 21
        moments[5] += x * ysq;       // mu 12
        moments[6] += y * ysq;       // mu 03
        }
// factor to normalize the size
        factor = 1.0 / ((double)n *(double)n);
        // second-order moment computation
        moments[0] *= factor;
        moments[1] *= factor;
        moments[2] *= factor;
        factor /= sqrt((double)n);
        // third order moment computation
        moments[3] *= factor;
        moments[4] *= factor;
        moments[5] *= factor;
        moments[6] *= factor;
        // a variety of constructors for ComputationalResult exist.
// this one constructs a result with centroid and
//moment array. ComputationResult instances are persistable.
        return new ComputationResult(xm, ym, moments);
    }
Listing 14-1.Moment computation in Java

从这个简单的 java 实现中,我们可以实现带有签名的 map、reduce 和 combine 方法,如清单 14-2 所示。

// Method signatures for the map() and reduce() methods for
// moment feature extraction module
public void map(HipiImageHeader header, FloatImage image, Context context) throws IOException,
      InterruptedException

public void reduce(IntWritable key, Iterable momentComponents, Context context)
      throws IOException, InterruptedException

Listing 14-2.HIPI map/reduce method signatures for moment feature extraction computation

让我们回忆一下第十一章的显微镜例子。在某些方面,这是一个非常典型的非结构化数据管道处理分析问题。正如您所记得的,图像序列最初是一个有序的图像列表,它们可以按时间戳或更复杂的方式排列,如地理位置、立体配对或重要性顺序。您可以想象在一个医疗应用程序中,可能有几十个同一患者的医学图像,那些有威胁生命的异常情况应该尽快出现在队列的前面。

其他图像操作可能是分布式处理的良好候选,例如清单 14-3 中用 BoofCV 编码的 Canny edge 操作。

package com.apress.iabdt.examples;

import java.awt.image.BufferedImage;

import java.util.List;

import com.kildane.iabdt.model.Camera;

import boofcv.alg.feature.detect.edge.CannyEdge;

import boofcv.alg.feature.detect.edge.EdgeContour;

import boofcv.alg.filter.binary.BinaryImageOps;

import boofcv.alg.filter.binary.Contour;

import boofcv.factory.feature.detect.edge.FactoryEdgeDetectors;

import boofcv.gui.ListDisplayPanel;

import boofcv.gui.binary.VisualizeBinaryData;

import boofcv.gui.image.ShowImages;

import boofcv.io.UtilIO;

import boofcv.io.image.ConvertBufferedImage;

import boofcv.io.image.UtilImageIO;

import boofcv.struct.ConnectRule;

import boofcv.struct.image.ImageSInt16;

import boofcv.struct.image.ImageUInt8;

public class CannyEdgeDetector {

        public static void main(String args[]) {
                BufferedImage image = UtilImageIO

                                .loadImage("/Users/kerryk/Downloads/groundtruth-drosophila-vnc/stack1/membranes/00.png");

                ImageUInt8 gray = ConvertBufferedImage.convertFrom(image, (ImageUInt8) null);
                ImageUInt8 edgeImage = gray.createSameShape();

                // Create a canny edge detector which will dynamically compute the
                // threshold based on maximum edge intensity
                // It has also been configured to save the trace as a graph. This is the
                // graph created while performing
                // hysteresis thresholding.
                CannyEdge<ImageUInt8, ImageSInt16> canny = FactoryEdgeDetectors.canny(2, true, true, ImageUInt8.class, ImageSInt16.class);
                // The edge image is actually an optional parameter. If you don't need
                // it just pass in null
                canny.process(gray, 0.1f, 0.3f, edgeImage);
                // First get the contour created by canny

                List<EdgeContour> edgeContours = canny.getContours();
                // The 'edgeContours' is a tree graph that can be difficult to process.
                // An alternative is to extract
                // the contours from the binary image, which will produce a single loop
                // for each connected cluster of pixels.
                // Note that you are only interested in external contours.
                List<Contour> contours = BinaryImageOps.contour(edgeImage, ConnectRule.EIGHT, null);
                // display the results
                BufferedImage visualBinary = VisualizeBinaryData.renderBinary(edgeImage, false, null);
                BufferedImage visualCannyContour = VisualizeBinaryData.renderContours(edgeContours, null, gray.width, gray.height, null);
                BufferedImage visualEdgeContour = new BufferedImage(gray.width, gray.height, BufferedImage.TYPE_INT_RGB);
                VisualizeBinaryData.renderExternal(contours, (int[]) null, visualEdgeContour);
                ListDisplayPanel panel = new ListDisplayPanel();
                panel.addImage(visualBinary, "Binary Edges");
                panel.addImage(visualCannyContour, "Canny GraphTrace");
                panel.addImage(visualEdgeContour, "Canny Binary Contours");
                ShowImages.showWindow(panel, "Image As Big Data Toolkit Canny Edge Extraction: ", true);
        }
}

Listing 14-3.Canny Edge Detection Using BoofCV, before parallelization

兴趣点是定义明确、稳定的图像空间位置,具有“特定的兴趣”例如,你可能会注意到图 14-9 中感兴趣的点出现在连接图像中其他结构的连接点处。角点、交叉点、轮廓和模板可以用来识别我们在图像中寻找的内容,并且可以对我们找到的结果进行统计分析。

A371868_1_En_14_Fig9_HTML.jpg

图 14-9。

Finding interest points in an image: the circled + signs are the interest points

IABDT 的典型输入过程如图 14-10 所示。

A371868_1_En_14_Fig10_HTML.jpg

图 14-10。

Input process for IABD Toolkit, showing image preprocessing components

数据流管道可以以“批处理模式”或“流模式”处理数据源。数据源预处理器是。图像数据源预处理器可以执行以图像为中心的预处理,例如特征提取、区域识别、图像金字塔构建和其他任务,以使流水线的图像处理部分更容易。

14.8 IABD 工具包中的低级图像处理器

低级图像处理例程是 IABDT 的重要组成部分。大多数标准图像处理库,包括 JAI、OpenCV 和 BoofCV,都可以无缝地与 IABDT 一起使用,使用 Maven 对 IABDT pom.xml 文件的依赖性。IABDT 最初提供的一些标准低级图像处理包括傅立叶算子。傅立叶算子将图像数据映射到频率空间,如下式所示:

$$ F{P}_{u,v}=\frac{1}{N}{\displaystyle \sum_{x=0}^{N-1}{\displaystyle \sum_{y=0}{N-1}{P}_{x,y}{e}{-j\left(\frac{2\pi }{N}\right)\left(ux+vy\right)}}} $$

精明的边缘算子。Canny 算子可以通过高斯平滑、Sobel 算子——非最大抑制阶段、阈值处理(具有滞后——一种特殊的阈值处理)来连接边缘点的步骤来近似。提取的二维形状可以保存到 IABDT 数据源。

直线、圆和椭圆提取运算符。存在用于从二维图像数据中提取直线、圆和椭圆形状图元的特征提取算法。工具包中包含了几个示例实现。

14.9 术语

下面是与图像处理和“图像作为大数据”概念相关的一些术语的简要总结。

基于代理的系统:合作多代理系统,或代理,是设计和实现 IABD 系统的有效方法。各个代理节点进程在一个编程的网络拓扑中合作,以实现共同的目标。

贝叶斯图像处理:使用贝叶斯技术的基于阵列的图像处理通常涉及用贝叶斯网络进行构建和计算,贝叶斯网络是一个图,其中的节点被视为随机变量,图的边是条件依赖关系。随机变量和条件依赖是来自基本贝叶斯统计的标准贝叶斯概念。继奥珀和温瑟之后,我们可以将贝叶斯最优预测刻画为

$$ {y}^{Bayes}\left({D}_m,\kern0.5em x\right)=sgn\kern0.5em {\displaystyle \int df\kern0.5em p\left(f\Big|y\right)sgn\kern0.5em f} $$

目标假设、预测和传感器融合是贝叶斯图像处理的典型问题领域。

分类算法:IABDT 中的分布式分类算法包括大间隔和小间隔(间隔是分类的置信度)分类器。包括遗传算法、神经网络、增强和支持向量机(SVMs)在内的多种技术可用于分类。分布式分类算法,如标准 k-means 或模糊 k-means 技术,包含在标准支持库中,如 Apache Mahout。

深度学习(DL):机器学习的一个分支,基于基于学习的数据表示,以及对高级数据抽象进行建模的算法。深度学习使用多个复杂的处理级别和多个非线性转换。

分布式系统:基于网络硬件拓扑上的消息传递架构的软件系统。分布式系统可能部分由诸如 Apache Hadoop 和 Apache Spark 之类的软件框架实现。

图像作为大数据(IABD):IABD 概念要求在某些方面将信号、图像和视频视为任何其他“大数据”来源,包括“多样性、容量、速度和准确性”的 4V 概念基础。IABD 的特殊要求包括各种自动处理,如压缩、格式转换和特征提取。

机器学习(ML):机器学习技术可以用于各种图像处理任务,包括特征提取、场景分析、对象检测、假设生成、模型建立和模型实例化。

神经网络:神经网络是一种模拟人类高级推理的生物模型的数学模型。许多类型的分布式神经网络算法对于图像分析、特征提取以及从图像建立二维和三维模型是有用的。

本体驱动的建模:本体作为对模型中的实体以及这些实体之间的关系的描述,可以被开发来驱动和通知建模过程,其中模型精化、元数据、甚至新的本体形式和模式都作为建模过程的输出而发展。

传感器融合:将来自多个传感器或数据源的信息组合成一个集成的、一致的、同质的数据模型。传感器融合可以通过多种数学技术来完成,包括一些贝叶斯技术。

分类学:建立目录的分类和命名方案。通过利用分类法和相关的本体数据结构和处理技术,可以帮助定义、生成或建模对象的层次结构。

14.10 摘要

在本章中,我们讨论了“图像作为大数据”的概念,以及为什么它是大数据分析技术领域中的一个重要概念。描述了新的图像作为大数据工具包(IABDT)的当前架构、功能和用例。其中,Apache Hadoop 和 Apache Spark 的互补技术及其各自的生态系统和支持库已被统一起来,以提供低级图像处理操作,以及复杂的图像分析算法,可用于开发分布式、定制的图像处理管道。

在下一章中,我们将讨论如何使用我们在本书前几章中学到的许多技术和技术堆栈来构建一个通用的数据处理管道。

14.11 参考

阿克勒,塞利姆 G. (1989)。并行算法的设计与分析。新泽西州恩格尔伍德悬崖:普伦蒂斯霍尔。

j .阿洛伊莫诺斯和 d .舒尔曼(1989 年)。视觉模块的集成:Marr 范式的扩展。加利福尼亚州圣地亚哥:学术出版专业公司。

n . aya che(1991 年)。移动机器人的人工视觉:立体视觉和多感官知觉。麻省剑桥:麻省理工学院出版社。

巴乔博士、埃马米博士、埃斯科里瓦博士、马哈茂德博士、莱夫根博士、萨拉吉博士(2011 年)。通过实际的计算机视觉项目掌握 OpenCV。英国伯明翰:PACKT 出版公司。

巴尔博萨瓦尔米尔。(1996).分布式算法介绍。麻省剑桥:麻省理工学院出版社。

伯格,m .,昌,o .,克雷瓦尔德,V. M .,奥维马斯,m .(编辑。).(2008).算法与应用。柏林海德堡,德国:施普林格出版社。

贝兹德克,J. C .,帕尔,S. K. (1992 年)。(艾德。)模式识别的模糊模型:在数据中搜索结构的方法。纽约州纽约市:IEEE 出版社。

布莱克和尤耶。).(1992).主动视觉。麻省剑桥:麻省理工学院出版社。

布莱洛克,通用电气公司(1990 年)。数据并行计算的矢量模型。麻省剑桥:麻省理工学院出版社。

伯格,w .,&伯格,M. J。).(2016).数字图像处理:使用 Java 的算法介绍,第二版。英国伦敦:斯普林格出版社伦敦。

戴维斯,E.R .(编辑。).(2004).机器视觉:理论,算法,实用性。第三版。英国伦敦:摩根·考夫曼出版社。

福杰拉斯(1993 年)。三维计算机视觉:几何观点。麻省剑桥:麻省理工学院出版社。

弗里曼。) (1988).算法、架构和系统。马萨诸塞州波士顿:学术出版社。

贾科姆利,皮耶罗。(2013).阿帕奇看象人食谱。英国伯明翰:PACKT 出版公司。

格里姆森;t .洛扎诺-佩兹;Huttenlocher 博士(1990 年)。计算机识别物体:几何约束的作用。麻省剑桥:麻省理工学院出版社。

古普塔,阿希什。(2015).学习 Apache Mahout 分类。英国伯明翰:PACKT 出版公司。

Hare,j .,Samangooei,s .和 Dupplaw,D. P. (2011 年)。OpenIMAJ 和 ImageTerrier:用于可伸缩多媒体分析和图像索引的 Java 库和工具。第 19 届 ACM 多媒体国际会议论文集(MM '11)。美国纽约州纽约市 ACM,691-694。DOI = 10.1145/2072298.2072421http://doi.acm.org/10.1145/2072298.2072421

库尔卡尼(1994 年)。用于图像理解的人工神经网络。纽约州纽约市:范·诺斯特兰德·赖因霍尔德。

Kumar,v .,Gopalakrishnan,P.S .,Kanal,l .(编辑).(1990).机器智能和视觉的并行算法。纽约州纽约市:斯普林格出版社纽约公司。

Lud milla I . Kun cheva(2004 年)。组合模式分类器:方法和算法。美国新泽西州霍博肯:约翰·威利父子公司。

Laganiere,R. (2011 年)。OpenCV 2 计算机视觉应用编程食谱。英国伯明翰:PACKT 出版公司。

林德布拉德,t .金瑟,J.M。).(2005).使用脉冲耦合神经网络的图像处理,第二版,修订版。德国柏林海德堡,英国:施普林格出版社柏林海德堡。

Lux,M. (2015)。LIRE: Lucene 图像检索。2016 年 5 月 4 日检索自 http://www.lire-project.net/

Lux,M. (2015)。哈里发和埃米尔:MPEG-7 图像注释和检索 GUI 工具。哈里发-哈里发和埃米尔-基图布。第 17 届 ACM 多媒体国际会议论文集。美国计算机学会,2009 年。2016 年 5 月 4 日检索自 https://github.com/dermotte/CaliphEmir

Mallat,s .(编辑) (2009).一个小波信号处理之旅,稀疏方式。美国马萨诸塞州伯灵顿:爱思唯尔公司。

Mallot,H. A .,Allen,J.S .).(2000).计算视觉:感知和视觉行为中的信息处理,第二版。美国马萨诸塞州剑桥:麻省理工学院出版社。

t .马斯特斯(2015 年)。C++和 CUDA C 中的深度信念网第 1 卷:受限玻尔兹曼机器。作者发布:TimothyMasters.info

-c++和 CUDA C 中的深度信念网,第二卷:复数域中的自动编码。(2015).作者发布:TimothyMasters.info

尼克森硕士和阿瓜多硕士(2012)。计算机视觉的特征提取和图像处理,第三版。英国牛津:学术出版社爱思唯尔有限公司。

彭特兰,亚历克斯。(1986).从像素到谓词:计算和机器人视觉的最新进展。新泽西州诺伍德:Ablex 出版公司。

里夫,迈克(编辑。).(1989).并行处理和人工智能。英国奇切斯特:约翰·威利父子公司。

南安普顿大学 (2011-2015)。ImageTerrier 图像检索平台。2016 年 5 月 4 日检索自 http://www.imageterrier.org/

Tanimoto 和 and Kilnger(编辑).(1980).结构化计算机视觉:通过层次结构的机器感知。纽约:学术出版社。

乌尔曼,西蒙。(1996).高级视觉:物体识别和视觉认知。麻省剑桥:麻省理工学院出版社。

弗吉尼亚大学计算机图形实验室(2016)。HIPI-Hadoop 图像处理接口。2016 年 5 月 4 日检索自 http://hipi.cs.virginia.edu/

十五、构建通用数据管道

在这一章中,我们详细介绍了一个端到端的分析系统,该系统使用了我们在整本书中讨论的许多技术,以提供一个评估系统,用户可以扩展和编辑该系统来创建自己的 Hadoop 数据分析系统。讨论了开发数据管道时使用的五种基本策略。然后,我们看看如何应用这些策略来构建通用数据管道组件。

15.1 示例系统的架构和描述

我们在第五章构建了一些基本的数据管道。现在是时候将我们提到的思想扩展到更通用的数据管道应用程序中了。

请记住,最简单的数据管道类似于图 15-1 。它是由数据传输步骤连接起来的一系列数据处理阶段。数据传输步骤从数据源收集数据,并将其发送到数据接收器。对于不同的传输步骤,传输方法可能不同,并且数据处理级对数据输入执行转换,向后续级发出数据输出。最终输出被输出到数据存储或可视化/报告组件。

A371868_1_En_15_Fig1_HTML.jpg

图 15-1。

A simple abstraction of a general purpose data pipeline

让我们看一个更真实的通用数据管道的例子。图 15-2 显示了一种最简单的有用配置。它由一个数据源(在这个例子中是 HDFS)、一个处理元素(在这个例子中是 Mahout)和一个输出阶段(在这个例子中是一个 D3 可视化工具,它是附带的大数据工具包的一部分)。

A371868_1_En_15_Fig2_HTML.jpg

图 15-2。

A real-world distributed pipeline can consist of three basic elements

我们的第一个示例将一个数据集导入 HDFS,使用 Mahout 执行一些简单的分析处理,并将分析结果传递给一个简单的可视化组件。

15.2 如何获取和运行示例系统

示例系统是一个基于 Maven 的以 Java/Scala 为中心的系统,类似于本书中描述的许多软件组件,可以在 Apress code contribution 站点上找到。详见附录 A 和 B。这个示例系统的安装非常简单:只需遵循软件下载中包含的说明。Java、Ant 和 Maven 等基础设施工具的使用在整本书中都有详细描述,尽管组件的版本号可能已经改变。您可以轻松地在 pom.xml Maven 文件中为您的项目更新版本号。

15.3 管道建设的五大策略

本书的大部分内容都提到了数据管道构建的不同策略。虽然软件组件、平台、工具和库可能会发生变化,但数据管道设计的基本战略设计方法保持不变。

构建数据管道有许多策略,但是,从广义上讲,有五种基于“工作方式”的主要策略下面简要讨论这五种基本策略类型。

15.3.1 使用数据源和数据汇

当您有预先存在的或遗留的数据源要使用时,从数据源和接收器开始工作是一个很好的组织策略。特别是,这些可能包括关系数据、CSV 平面文件,甚至是充满图像或日志文件的目录。

当使用这种数据源和接收器策略时,一种有组织的方法将包括以下内容:

  • 确定数据源/接收器类型,并为数据接收、数据验证和数据清理(如果需要)提供组件。出于这个例子的目的,我们将使用 Splunk、Tika 和 Spring 框架。
  • 将“业务逻辑”视为黑盒。最初集中于数据输入和输出以及支持技术栈。如果业务逻辑相对简单,已经打包成一个库,定义良好并且易于实现,我们可以将业务逻辑组件视为一个自包含的模块或“插件”如果业务逻辑需要手工编码或者更复杂

中端开发

中间向外的开发意味着它所说的:从应用程序结构的“中间”开始,向任一端努力,在我们的例子中,这将总是过程开始时的数据源和数据管道末端的数据接收器或最终结果存储库。我们首先开发的“中间”本质上是要开发的“业务逻辑”或“目标算法”。我们可以从一般的技术栈考虑开始(比如选择使用 Hadoop、Spark 或 Flink,或者使用其中一种或多种的混合方法)。

15.3.3 基于企业集成模式(EIP)的开发

基于 EIP 的开发是开发管道的有用方式。正如我们所看到的,一些标准工具包是专门为实现 EIP 组件而设计的,系统的其他部分可以使用 EIPs 来概念化。让我们先看几张 EIP 图。

A371868_1_En_15_Fig3_HTML.jpg

图 15-3。

A simple Enterprise Integration Pattern (EIP)

我们可以使用任何免费提供的 EIP 图编辑器,如 draw.io 工具(draw.io)或 Omnigraffle (omnigraffle.com),来绘制 EIP 图。然后,我们可以使用 Spring Integration 或 Apache Camel 来实现管道。

关于 EIP 符号的完整描述可以在 Hohpe 和 Woolf (2004)中找到。

抽象图图 15-4 中显示的组件可以使用 Apache Camel 或 Spring 集成来实现。这两个端点分别是数据接收和数据持久化。类似电视屏幕的小符号表示数据可视化组件和/或管理控制台。

A371868_1_En_15_Fig4_HTML.jpg

图 15-4。

A more extended example of an EIP

15.3.4 基于规则的消息传递渠道开发

我们在第八章讨论了基于规则的系统以及它们如何用于控制、调度和面向 ETL 的操作。然而,基于规则的系统可以作为数据流水线流程的中心或核心控制机制,如图 15-5 所示。

A371868_1_En_15_Fig5_HTML.jpg

图 15-5。

A rule-based data flow pipeline architecture

图 15-5 显示了基于规则的数据管道的典型架构,其中管道中的所有处理组件都由基于规则的工作流/数据管理组件控制。让我们看看这样一个架构是如何实现的。

15.3.5 控制+数据(控制流)流水线

当我们定义一个控制机制和要控制的数据阶段时,我们基本上可以回到经典的管道-过滤器设计模式,如图 15-7 的 EIP 图所示。

A371868_1_En_15_Fig6_HTML.jpg

图 15-6。

An EIP diagram showing a different incarnation of the data pipeline

15.4 摘要

在本章中,我们讨论了通用数据管道的构建。通用数据管道是大数据分析系统的重要起点:无论是在概念上还是在现实世界的应用构建中。这些通用管道充当更多特定应用扩展以及实验性概念验证系统的暂存区,这些系统在进一步开发之前可能需要更多的修改和测试。从一个强大的通用技术基础开始,可以更容易有效地执行返工,并在应用程序需求发生变化时“后退一步”。

讨论了五种基本的管道构建策略:从源和汇开始工作,中间向外开发(以分析堆栈为中心的开发),企业集成模式(EIP)管道开发,基于规则的消息传递管道,以及控制+数据(控制流)管道。还讨论了支持这五种通用流水线策略的支持库、技术和代码。

在下一章也是最后一章,我们将讨论大数据分析的未来发展方向,以及这类系统的未来发展趋势。

15.5 参考

霍佩,格雷戈尔,和伍尔夫,鲍比。企业集成模式:设计、构建和部署消息传递解决方案。波士顿,麻州:艾迪生-卫斯理出版公司,2004 年。

易卜生,克劳斯,和安斯利,乔纳森。骆驼在行动。康涅狄格州斯坦福德:曼宁出版公司,2011 年。

卡维斯迈克尔。云计算服务模型的设计决策。新泽西州霍博肯:约翰·威利父子公司,2014 年。

麦,加里。春季食谱:解决问题的方法。纽约州纽约市:斯普林格出版社,2008 年。

十六、大数据分析的总结和未来

在这最后一章中,我们总结了我们在前面几章中学到的知识,并讨论了大数据分析的一些发展趋势,包括数据分析的“孵化器”项目和“年轻”项目。我们还推测大数据分析和 Hadoop 生态系统的未来——“未来 Hadoop”(可能还包括 Apache Spark 和其他产品)。

请记住,随着时间的推移,大数据的 4v(速度、准确性、容量和多样性)只会变得更大、更复杂。我们的主要结论是:大数据分析解决方案的范围、广度和有效性也必须相应地继续增长,以跟上可用数据的步伐!

16.1 结论和年表

在本书中,我们对分布式业务分析系统进行了技术调查——特别是 Hadoop 作为架构、实现、部署和应用的起点和构建模块。我们已经讨论了一些语言、工具包、库和框架,我们发现它们是启动和运行新的 Hadoop BDAs 的最有用的方法。在我们前进的过程中,我们试图遵守一些战略原则,以保持事情的灵活性,并适应未来几个月或几年可能出现的新需求和软件组件。

这些战略原则包括以下内容:

  1. 使用模块化设计/构建/测试策略来维护软件依赖性、版本和测试/集成。在我们的例子中,我们使用 Maven 和相关的软件工具来管理新软件模块的构建、测试、部署和模块化添加或减少,或者更新版本。这并不意味着我们排除其他必要的构建工具,比如 Bower、Gradle、Grunt 等等。相反,所有好的构建工具、内容管理器和测试框架都应该足够灵活,能够与其他工具协同工作。例如,在我们的实验系统中,经常可以看到 Maven、Grunt、Bower 和 Git 组件和谐共存,几乎没有摩擦或不兼容。
  2. 战略性地选择能够适应未来需求和不断变化的要求的技术组合。牢记一个架构“愿景”允许系统设计者一起工作来构建和维护一个连贯的技术栈,它解决了需求。对实现技术进行良好的初始选择是重要的,也是可取的,但是为了纠正错误,采用灵活的方法更为可取。
  3. 能够以尽可能无缝的方式适当地适应不同的编程语言。由于需要有选择地选择技术堆栈,现在甚至一些最简单的应用程序也是多语言应用程序,可能在一个框架中包含 Java、JavaScript、HTML、Scala 和 Python 组件。
  4. 为组件集成、测试和优化/部署选择合适的“胶件”。正如我们在本书的例子中所看到的,“胶合件”几乎和被胶合的组件一样重要!幸运的是,对于开发人员来说,有许多组件和框架可以用于这个目的,包括 Spring Framework、Spring Data、Apache Camel、Apache Tika 以及 Commons Imaging 等专用包。
  5. 最后但同样重要的是,保持一种灵活敏捷的方法来使系统适应新发现的需求、数据集、不断变化的技术以及数据源和接收器的容量/复杂性/数量。需求会不断变化,支持技术也会不断变化。从长远来看,适应性方法可以节省时间和返工。

总之,我们已经相信,遵循上述系统构建的战略方法将有助于架构师、开发人员和管理人员实现功能性业务分析系统,这些系统具有足够的灵活性、可伸缩性和适应性来适应不断变化的技术,并且能够处理具有挑战性的数据集、构建数据管道,并提供有用和有说服力的报告功能,包括正确的数据可视化以足够详细地表达您的结果。

16.2 大数据分析的现状

在这最后一章的剩余部分,我们将研究 Hadoop 的当前状态,并注意一些未来可能的方向和发展,推测“未来的 Hadoop”,这当然包括分布式技术的表现和发展,类似于 Apache Spark、YARN 和 Hadoop 2 如何成为 Hadoop 及其生态系统发展到今天的里程碑。

首先,我们必须回到十九世纪。

数据处理技术危机的第一次爆发至少可以追溯到 1880 年。在那一年,美国人口普查被计算为使用当时普遍使用的技术需要八年来处理。到 1952 年,美国人口普查使用 UNIVAC 计算机的协助进行。从那时起,时代对数据处理技术的挑战就有了一个又一个的解决方案:机械、电子和半导体硬件解决方案,伴随着软件技术(如通用编程语言)的发展和革命,以及媒体的组织(从最早的照片和录音到最新的电子流、视频处理和存储以及数字媒体记录技术)。

1944 年,富有远见的图书管理员弗里蒙特·莱德(Fremont Rider)对“信息危机” 1 (在那个年代,这意味着物理图书馆中物理存储的文件数量)提出了一种创新的解决方案,他称之为“微型卡”:一种在透明缩微胶片的一面上显示我们现在称为“元数据”的方式,而书籍本身的单页显示在相反的一面上。莱德建议,可以通过使用这些“微型卡”来保存珍贵的独一无二的书籍和手稿,以避免目前正在肆虐的战争的破坏。现在,随着“数据不朽”在网络上的 www.archive.com 等项目中被发现,我们看到了莱德的发明所预见的电子书籍的存档。

从穿孔卡片和机械计算器,到像莱德那样的缩微胶片解决方案,再到电子计算机,我们已经走过了漫长的道路;但是请记住,许多计算和分析问题保持不变。随着计算能力的提高,数据量和可用性(大量各种传感器输出数据)不仅需要大数据分析,还需要所谓的“传感器融合”过程,其中不同种类的结构化、半结构化和非结构化数据(信号、图像和各种形状和大小的流)必须集成到一个共同的分析画面中。无人机和机器人技术是“未来的 Hadoop”可能大放异彩的两个领域,强大的传感器融合项目已经在进行中。

无论软件和硬件组件变得多么先进,统计分析仍然在大数据分析的世界中占有一席之地。统计的“老派”可视化总会有一席之地,如图 16-1 和图 16-2 所示。至于分类、聚类、特征分析、趋势识别、共性、匹配等基本要素。,我们可以期待看到所有这些基本技术被改造成越来越强大的库。数据和元数据格式——最重要的是,它们的标准化和在整个大数据社区的采用——将允许我们在未来几十年内发展 BDAs 的软件编程范式。

A371868_1_En_16_Fig2_HTML.jpg

图 16-2。

“Old school” candlestick graphs can still be used to summarize chronological data

A371868_1_En_16_Fig1_HTML.jpg

图 16-1。

Different kinds of “old school” bar graphs can be used to summarize grouped data

当我们思考大数据分析的现状时,许多问题立即浮现在脑海中。一个迫在眉睫的问题是,当我们解决一个数据分析问题时,我们需要覆盖多少领域?就组件而言,业务分析的极限是什么(记住我们的问题定义和范围)?商业分析在哪里结束,信息技术和计算机科学的其他方面从哪里开始?

就组件而言,让我们快速回顾一下“业务分析”到底是什么。我们可以从一系列组件和功能开始,如下所示:

  1. 数据仓库组件。Apache Hive 最初是用于 Hadoop 的数据仓库技术,现在仍被大量软件应用程序广泛使用。
  2. 商业智能(BI)功能。“商业智能”(BI)的传统定义包括数据和流程挖掘、预测分析和事件处理组件,但在分布式 BI 时代,可能还包括涉及模拟、深度学习和复杂模型构建的组件。BI 可以提供数据集的历史、当前或预测视图,并可以在“运营分析”领域提供帮助,即通过应用 BI 解决方案来改善现有运营。
  3. 企业集成管理(EIM)。EIM 得到了整个企业集成模式(EIPs)领域的帮助。许多软件组件,包括 Apache Camel 这样的“glueware ”,都是基于 Hohpe 和 Woolf 的经典著作《企业集成模式》中所有或大部分 EIP 的实现。 2
  4. 企业绩效管理(EPM)。EPM 是一些供应商非常感兴趣的地区,尤其是 Cloudera。Bernard Marr 写了一篇有趣而有见地的文章,题为“大数据分析将改变企业绩效管理的三种方式”。 3
  5. 分析应用程序(单个组件和功能)。许多孵化和全新的图书馆和框架等待着!
  6. 关键功能需求:审计的治理、风险和法规遵从性管理。
  7. 在整个核心、支持生态系统和分布式分析应用中始终如一地提供安全性和集成安全性。在 Hadoop 开发的早期,Hadoop 生态系统中的许多组件都没有充分考虑安全性。数据来源和实时监控分布式系统只是“未来 Hadoop”面临的两个挑战,但它们是 Hadoop 和 Apache Spark 分布式系统中需要改进安全措施的重要例子。

大数据分析能力只会继续增长和繁荣。硬件和软件技术,包括人工智能研究和创新的新复兴,有助于机器学习和深度学习技术,这对大数据分析技术的进一步发展非常必要。开源库和蓬勃发展的软件社区使得新系统的开发更加容易,即使使用现成的组件也是如此。

16.3“孵化项目”和“年轻项目”

在整本书中,我们经常提到“成熟软件项目”、“孵化项目”和“年轻项目”在这一节中,我们想看看这些术语的含义,并指出它对架构师和开发人员跟踪可能在队列中的“孵化中”和“年轻的”项目是多么有用。请注意,我们的示例大多来自 Apache.org 网站,这是寻找成熟技术组件的最佳场所之一,但是也有许多其他网站可以满足特定领域的需求。例如,在 http://www.mmorph.com/resources.html 和许多其他类似的网站上列出了处于各种成熟、开发和使用阶段的各种图像处理工具包。

如果你看一下 apache.org 上的 Apache 软件组件列表( http://incubator.apache.org/projects/ ),你会看到许多项目要么正在孵化,要么已经从孵化中毕业,甚至已经“退休”了。孵化器的毕业生凭借自己的能力继续成为成熟的 Apache 项目,而退休的项目即使在“退休”事件之后也可以继续开发。

虽然孵化项目的列表在不断变化,但看看孵化项目如何与上面显示的商业分析组件和功能列表相匹配是有启发性的。一些例子包括 Apache Atlas ( http://atlas.incubator.apache.org )用于使用 Hadoop 的企业治理服务,使用“分类法业务注释”用于数据分类。提供了审计、搜索、沿袭和安全功能。与古老的 Apache Hive 数据仓库组件相比,Lens ( http://incubator.apache.org/projects/lens.html ))以无缝的方式将 Hadoop 与传统数据仓库集成在一起,提供了数据的单一视图。Lens 于 2015 年 8 月 19 日从孵化器毕业,成为一个成熟的 Apache 项目。

Apache Lenya ( http://incubator.apache.org/projects/lenya.html ),一个内容管理系统,也已经毕业,成为一个独立的 Apache 项目。

安全性是 Hadoop 分布式系统中的一个关键问题,有几个孵化组件可以解决这些问题。目前正在酝酿的一些项目包括:

密特隆( http://incubator.apache.org/projects/metron.html )是一款用于安全组织和分析的集中式工具,它集成了 Hadoop 生态系统中的许多组件,以提供可扩展的安全分析平台。

Ranger ( http://incubator.apache.org/projects/ranger.html ),一个跨 Hadoop 平台的全面数据安全的管理框架。

“分析应用程序”可能是上面组件和功能列表中列出的最常见的类别,目前有几个正在孵化的实现,它们支持组件集成、数据流构建、算法实现、仪表板、统计分析支持以及任何分布式分析应用程序的许多其他必要组件。

Apache 目前正在酝酿的一些以应用程序为中心的分析组件包括:

  1. Apache Beam ( http://incubator.apache.org/projects/beam.html ))是一组特定于语言的 SDK,用于定义和执行数据处理工作流以及其他类型的工作流,包括数据摄取、集成等。Beam 以类似于 Apache Camel 系统的方式支持 EIPs(企业集成模式)。
  2. HAWQ ( http://incubator.apache.org/projects/hawq.html )是一个企业级 SQL 分析引擎,包含一个 MPP(大规模并行处理)SQL 框架,源自 Pivotal 的 Greenplum Database 框架。HAWQ 是 Hadoop 的原生产品。
  3. Apache NiFi ( http://nifi.apache.org/index.html )是一个高度可配置的数据流系统,在撰写本文时是 Apache 孵化器的新成员。有趣的是,NiFi 提供了一个基于 web 的界面来设计、监控和控制数据流。
  4. MadLib ( http://madlib.incubator.apache.org )是一个大数据分析库,它依赖于 HAWQ SQL 框架( http://hawq.incubator.apache.org ),一个“近实时”的企业数据库和查询引擎。

16.4 对未来 Hadoop 及其继任者的推测

在撰写本书时,Apache Hadoop 已经伴随我们好几年了(2011–2016)。从 Apache Lucene 和 Solr 搜索引擎项目发展而来,它已经有了自己的生命,并激发了像 Apache Spark 和其他人这样的潜在“继承者”。对于大数据分析领域,Hadoop 核心和 Hadoop 生态系统发展的下一步是什么?

Hadoop 开发人员和架构师当前面临的一个问题是“Hadoop 过时了吗?”或者更准确地说,“鉴于 Hadoop 1 已经被 Hadoop 2 取代,Apache Spark 似乎已经在某些领域取代了 Hadoop,使用 Hadoop 及其生态系统的可行性如何?Hadoop 生态系统是否有其他更好的替代方案?”

在这最后一节,我们只能根据 Hadoop 生态系统的当前状态和未来发展的可能途径,对这些问题提供一个尝试性的答案。

请记住 Hadoop 当前的功能架构,如图 16-3 所示。让我们根据我们在前几章所学的内容得出一些结论。

A371868_1_En_16_Fig3_HTML.jpg

图 16-3。

A functional view of current Hadoop technologies and capabilities

16-3 中显示的数字将继续发展,随着时间的推移,一些额外的部分可能最终被增加或减少(例如,“编程语言绑定”和“备份、灾难恢复和风险管理”是我们可以做的明显的增加,但是这些主题需要它们自己的书长度的处理。

  1. 工作流和调度:工作流和调度可能由像 Oozie 这样的 Hadoop 组件处理。
  2. 查询和报告功能:查询和报告功能还可以包括可视化和仪表板功能。
  3. 安全、审计和合规性:Apache 保护伞下的新孵化项目解决了 Hadoop 生态系统中的安全、审计和合规性挑战。这些安全组件的例子包括 Apache Ranger ( http://hortonworks.com/apache/ranger/ ),一个 Hadoop 集群安全管理工具。
  4. 集群协调:集群协调通常由框架提供,如 ZooKeeper 和 Apache Curator 的库支持。
  5. 分布式存储:HDFS 不是分布式存储的唯一答案。像 NetApp 这样的供应商已经使用 Hadoop 连接器连接到 NFS 存储系统 4
  6. NoSQL 数据库:正如我们在第四章中看到的,有很多种 NoSQL 数据库技术可供选择,包括 MongoDB 和 Cassandra。像 Neo4j 和 Giraph 这样的图数据库也是流行的 NoSQL 框架,它们有自己的库用于数据转换、计算和可视化。
  7. 数据集成能力:数据集成和 glueware 也在继续发展,以适应不同的数据格式、遗留程序和数据、关系数据库和 NoSQL 数据库,以及 Solr/Lucene 等数据存储。
  8. 机器学习:机器学习和深度学习技术已经成为任何 BDAs 计算模块的重要组成部分。
  9. 脚本功能:Python 等高级语言中的脚本功能正在快速发展,交互式 shells 或 REPLs(读取-评估-打印循环)也是如此。甚至古老的 Java 语言也在版本 9 中包含了 REPL。
  10. 监控和系统管理:Ganglia、Nagios 和 Ambari 中用于监控和管理系统的基本功能将继续发展。一些较新的系统监控和管理条目包括 Cloudera Manager ( http://www.cloudera.com/products/cloudera-manager.html )。

16.5 不同的视角:Hadoop 的当前替代方案

如今,Hadoop 并不是分布式大数据分析的唯一选择。如今,标准 Hadoop 平台和生态系统有许多替代品,其中一些已经得到了 Apache foundation 的支持。请注意,其中一些包括 Apache Flink,(flink.apache.org),这是一个分布式大数据分析框架,为批处理和流数据处理提供了基础架构。

Flink 可以使用来自 Apache Kafka 等消息系统的数据。

阿帕奇风暴(storm.apache.org)是阿帕奇 Spark 的另一个潜在竞争对手。Storm 是一个实时、分布式流处理计算系统,支持机器学习、ETL 和“连续计算”

16.6 在“未来 Hadoop”中使用机器学习和深度学习技术

算法实现、“助手库”、机器学习和深度学习库和框架,以及对 Mahout 和 MLib 等经典库的改进,都是现代 BDA 实现的重要组成部分。它们支持我们每次构建数据处理管道时执行的各种任务。我们应该指出“机器学习”和所谓的“深度学习”之间的区别,深度学习是“多层神经网络”算法的一个相对较新的术语,以及其他技术。一个非常有趣的例子是 Apache Horn 孵化器项目,下面将详细描述。总体而言,机器学习通常被视为通往“人工智能”道路上的“进化前期”,而“深度学习”则是更进一步的进化。支持向量机、朴素贝叶斯算法和决策树算法通常被称为“浅层”学习技术,因为与深度学习器不同,在输出数据集发出之前,输入不会经过一个以上的非线性处理步骤。这些所谓的“浅层”技术被归入“机器学习”,而更高级的技术,通常使用许多处理阶段,是“深度学习”的一部分。

Apache(和其他地方)的一些解决 ML 和 DL 问题的孵化库(以及它们对各种技术栈和平台的支持)包括:

A371868_1_En_16_Fig4_HTML.jpg

图 16-4。

A feaure matrix of ML toolkits

  1. Apache SystemML ( http://systemml.apache.org )):这个库支持许多标准算法,这些算法可以使用 Hadoop 或 Spark 以分布式方式运行。SystemML 高效且可扩展,可以在独立模式下运行,也可以在 Hadoop 集群上运行。
  2. DL4J ( http://deeplearning4j.org ): DL4J 有很多高级特性,比如 GPU 编程支持。
  3. H2O 和闪闪水( http://h2o.org )):闪闪水是基于 H2O 和阿帕奇 Spark 的机器学习库。这些组件在 Scala 中是可编程的,具有多种算法。
  4. MLib for Apache Spark(Spark . Apache . org):MLib 是一个可扩展的 Spark 机器学习库。
  5. Apache Mahout(Apache . Mahout . com):Mahout 是 Hadoop 生态系统中一个古老而有价值的部分。
  6. Cloudera Oryx 机器学习库( https://github.com/cloudera/oryx ) : Oryx 是一个支持多种算法的机器学习库。
  7. 分布式 R | Weka ( https://github.com/vertica/distributedRhttp://weka.sourceforge.net/packageMetaData/distributedWekaHadoop/index.html ):分布式 R 和 Weka 是各种分布式统计分析的良好配对,R 和 Weka 可用的各种实现算法使实现数据管道更加简单。
  8. Apache Horn(https://horn.incubator.apache.org):Apache Horn 是一个简单易用的深度学习孵化项目。尽管 Apache Horn 还处于早期开发阶段,但它已经可以用于原型开发和构建基于神经网络的分布式分析组件。
  9. 并排查看这些工具包各自的功能是很有用的,因此这里包含了一个机器学习工具包的“功能矩阵”,供您参考。

*有关 Apache Horn 的最新信息,请参见位于 https://horn.incubator.apache.org 的孵化网站。

16.7 数据可视化和 BDAs 的新领域

数据可视化一直是大数据分析的一个关键组成部分,随着图数据库和复杂的可视化库(如 D3、sigmajs 和许多其他库)的结合,数据可视化也在不断涌现。创建、可视化和交互式编辑非常复杂和非常大的数据集变得更加简单。我们在可视化章节第十章看到了一些这样的例子。数据可视化的未来方向有很多,包括全息、虚拟现实和“远程呈现”技术的开发。虽然其中许多已经存在了一段时间,但随着“近实时”处理系统变得更加高效,分布式软件系统将使复杂的“现实系统”变得越来越可能。这将有助于实现处理更大和更复杂的数据集的目标,同时保持与现有分析库的兼容性、效率和无缝性。事实上,许多现代机器学习和深度学习框架,以及支持 BDAs 的统计框架(如 R 和 Weka)都包含自己的可视化组件和仪表板。尽管一些老派的可视化库是用 Java 甚至 C 编写的,但是许多现代的可视化库支持多种语言绑定,当然特别是 JavaScript,但是也支持基于 Scala 和 Python 的 API,正如我们在前面的章节中看到的。

16.8 结束语

当我们考虑“未来 Hadoop”的命运时,让我们记住当今大数据技术所面临的未来问题和挑战。

这些挑战包括:

  1. 成熟预测分析的可用性:能够从现有数据预测未来数据一直是业务分析的目标,但许多研究和系统建设仍有待完成。
  2. 作为大数据分析的图像和信号:在第十四章中,我们深入探讨了“作为大数据的图像”概念,正如那里所提到的,对这些复杂数据源的工作才刚刚开始,其中当然包括来自各种不同传感器的时间序列数据和“信号”,包括激光雷达、用于法医分析的化学传感器、医疗工业应用、来自车辆的加速度计和倾斜传感器数据,以及许多其他数据。
  3. 甚至更大的速度、种类和输入源数据量:至于数据处理所需的速度、结构和复杂性的种类和水平(或者缺乏它!),以及原始数据量,这些要求将变得越来越苛刻,因为硬件和软件将能够处理增加的架构挑战和“未来数据分析”将要求的更苛刻的问题集。
  4. 将不同类型的数据源合并到统一的分析中:“传感器融合”只是将数据合并到由传感器测量和绘制的数据环境的一个“统一画面”中的一个方面。分布式人工智能和机器学习的发展,以及相对较新的“深度学习”领域,通过提供意义、上下文和预测以及原始数据统计分析,提供了超越不同数据源的简单聚合和融合的潜在路径。这将实现复杂的模型构建、数据理解系统和高级决策系统应用。
  5. 人工智能(AI)和大数据分析的融合:人工智能、大数据和数据分析一直共存,甚至可以追溯到人工智能系统的最早历史。近年来,分布式机器学习(ML)和深度学习(DL)的进步更加模糊了这些领域之间的界限。深度学习库,如 Deeplearning4j,目前在 BDA 应用程序中经常使用,并且已经提出了许多有用的应用程序解决方案,其中人工智能组件已经与 BDAs 无缝集成。
  6. 基础设施和底层支持库演进(包括安全性):基于 Hadoop 的应用的基础设施支持工具包通常包括 Oozie、Azkaban、Schedoscope 和 Falcon。低级支持和集成库包括 Apache Tika、Apache Camel、Spring Data 和 Spring Framework 本身等等。针对 Hadoop、Spark 及其生态系统的专门安全组件包括 Accumulo、Apache Sentry、Apache Knox Gateway 以及许多其他最近的贡献。

无论您是程序员、架构师、经理还是分析师,现在都是进入大数据分析领域的好时机。许多有趣的、改变游戏规则的未来发展在等着我们。Hadoop 通常被视为向更强大的分布式分析系统发展的一个阶段,无论这种发展是朝着“我们所知的 Hadoop”之外的方向发展,还是我们已经知道的 Hadoop 系统发展其生态系统,以更好的方式处理更多数据,分布式大数据分析都将继续存在,Hadoop 是当前计算领域的主要参与者。我们希望您喜欢这次使用 Hadoop 的大数据分析技术调查,就像我们喜欢带给您一样。

Footnotes 1

在《学者与研究图书馆的未来》中,弗里蒙特·莱德描述了他对时代信息爆炸的解决方案。对于任何对基本技术问题如何随着时间的推移以不同形式重现感兴趣的人来说,这是一本好书。

2

格雷格·霍佩,鲍比·伍尔夫。(2003)企业集成模式设计、构建和部署消息传递系统。艾迪森.韦斯利。ISBN 978-0321200686

3

http://www.smartdatacollective.com/bernardmarr/47669/3-ways-big-data-analytics-will-change-enterprise-performance-management

只要这本书还在使用,上面的链接就有效吗?

4

有关 NetApp NFS | Hadoop 连接器的更多信息,请参见 http://www.netapp.com/us/solutions/big-data/nfs-connector-hadoop.aspx

第一部分:概念

Concepts

本书的第一部分描述了分布式分析软件系统的基本概念、结构和用途,为什么它有用,以及使用这种类型的分布式系统所需的一些必要工具。我们还将介绍一些构建系统所需的分布式基础设施,包括 Apache Hadoop 及其生态系统。

第二部分:架构和算法

Architectures and Algorithms

本书的第二部分讨论了使用 Hadoop 构建分析系统的标准架构、算法和技术。我们还研究了用于控制、调度和系统编排的基于规则的系统,并展示了基于规则的控制器如何成为基于 Hadoop 的分析系统的天然附件。

第三部分:组件和系统

Components and Systems

本书的第三部分描述了可以帮助我们构建分布式分析系统的组件和相关库。这包括基于各种不同编程语言、架构和数据模型的组件。

posted @   绝不原创的飞龙  阅读(69)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· [翻译] 为什么 Tracebit 用 C# 开发
· 腾讯ima接入deepseek-r1,借用别人脑子用用成真了~
· Deepseek官网太卡,教你白嫖阿里云的Deepseek-R1满血版
· DeepSeek崛起:程序员“饭碗”被抢,还是职业进化新起点?
· RFID实践——.NET IoT程序读取高频RFID卡/标签
点击右上角即可分享
微信分享提示