http://blog.csdn.net/Richard_More/article/details/53215142
分布式深层神经网络的Spark ML模型管线
该笔记本描述了如何使用Spark ML为分布式版本的Keras深度学习模型构建机器学习流水线。作为数据集,我们使用来自Kaggle的Otto产品分类挑战。我们选择这个数据的原因是它很小,结构非常好。这样,我们可以更多地关注技术组件,而不是进行复杂的处理。此外,具有较慢硬件或没有完整的Spark群集的用户应该能够在本地运行此示例,并且仍然会了解有关分布式模式的许多内容。
通常,模型训练不需要分配计算,而是建立数据流水线,即摄入,转换等。在训练中,深层神经网络往往在一台机器上的一个或多个GPU上做得相当好。大多数情况下,使用梯度下降方法,您将一个接一个地处理。即使如此,使用像Spark这样的框架也可能有益于将您的模型与您的周边基础架构相集成。除此之外,Spark ML管道提供的便利性非常有价值(在语法上非常接近你所知道的scikit-learn
)。
TL; DR:我们将展示如何使用分布式深层神经网络和Spark ML管道来解决分类问题,这个例子基本上是这里发现的分布式版本。
使用这个笔记本
当我们要使用elephas时,您将需要访问正在运行的Spark上下文才能运行此笔记本。如果您还没有,请按照本文提供的说明在本地安装Spark 。确保还导出SPARK_HOME
到您的路径并启动您的ipython / jupyter笔记本如下:
- 1
- 1
要测试您的环境,请尝试打印Spark上下文(提供sc
),即执行以下单元格。
- 1
- 2
- 1
- 2
<pyspark.context.SparkContext object at 0x1132d61d0>
奥托产品分类数据
培训和测试数据在这里可用。继续下载数据。检查它,您将看到提供的csv文件包含一个id列,93个整数特征列。train.csv
有一个额外的标签栏,test.csv
缺少。挑战是准确预测测试标签。对于本笔记本的其余部分,我们将假设存储数据data_path
,您应根据需要修改下面的数据。
- 1
- 1
加载数据比较简单,但是我们要照顾几件事情。首先,虽然你可以洗牌RDD,但通常不是很有效率。但是由于数据train.csv
按类别排序,所以我们必须洗牌才能使模型运行良好。这是shuffle_csv
下面的功能。接下来,我们用明文读入load_data_rdd
,以逗号分割,并将要素转换为浮点型向量。另外请注意,最后一列train.csv
表示具有Class_
前缀的类别。
定义数据帧
Spark有一些核心的数据结构,其中包括data frame
,这是一个分布式版本的命名列数据结构,现在很多都是来自R或熊猫。我们需要一个所谓的SQLContext
和可选的列到名称映射来创建从头开始的数据框架。
- 1
- 2
- 3
- 4
- 五
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 1
- 2
- 3
- 4
- 五
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
我们加载训练和测试数据,并使用方便的show
方法打印几行数据。
- 1
- 2
- 3
- 4
- 五
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 五
- 6
- 7
- 8
Train data frame:
+--------------------+--------+
| features|category|
+--------------------+--------+
|[0.0,0.0,0.0,0.0,...| Class_8|
|[0.0,0.0,0.0,0.0,...| Class_8|
|[0.0,0.0,0.0,0.0,...| Class_2|
|[0.0,1.0,0.0,1.0,...| Class_6|
|[0.0,0.0,0.0,0.0,...| Class_9|
|[0.0,0.0,0.0,0.0,...| Class_2|
|[0.0,0.0,0.0,0.0,...| Class_2|
|[0.0,0.0,0.0,0.0,...| Class_3|
|[0.0,0.0,4.0,0.0,...| Class_8|
|[0.0,0.0,0.0,0.0,...| Class_7|
+--------------------+--------+
only showing top 10 rows
Test data frame (note the dummy category):
+--------------------+--------+
| features|category|
+--------------------+--------+
|[1.0,0.0,0.0,1.0,...| Class_1|
|[0.0,1.0,13.0,1.0...| Class_1|
|[0.0,0.0,1.0,1.0,...| Class_1|
|[0.0,0.0,0.0,0.0,...| Class_1|
|[2.0,0.0,5.0,1.0,...| Class_1|
|[0.0,0.0,0.0,0.0,...| Class_1|
|[0.0,0.0,0.0,0.0,...| Class_1|
|[0.0,0.0,0.0,1.0,...| Class_1|
|[0.0,0.0,0.0,0.0,...| Class_1|
|[0.0,0.0,0.0,0.0,...| Class_1|
+--------------------+--------+
only showing top 10 rows
预处理:定义变压器
到目前为止,我们基本上只读原始数据。幸运的是,Spark ML
有很多预处理功能可用,所以我们唯一要做的就是定义数据帧的转换。
要继续,我们将首先将类别字符串转换为双精度值。这是由一个所谓的StringIndexer
。请注意,我们已经在这里进行了实际的转型,但这只是为了演示的目的。我们真正需要的是太多的定义,string_indexer
以便稍后再进行管理。
- 1
- 2
- 3
- 4
- 五
- 1
- 2
- 3
- 4
- 五
接下来,将功能规范化,这是一个很好的做法StandardScaler
。
- 1
- 2
- 3
- 4
- 五
- 1
- 2
- 3
- 4
- 五
- 1
- 2
- 1
- 2
The result of indexing and scaling. Each transformation adds new columns to the data frame:
+--------------------+--------+--------------+--------------------+
| features|category|index_category| scaled_features|
+--------------------+--------+--------------+--------------------+
|[0.0,0.0,0.0,0.0,...| Class_8| 2.0|[-0.2535060296260...|
|[0.0,0.0,0.0,0.0,...| Class_8| 2.0|[-0.2535060296260...|
|[0.0,0.0,0.0,0.0,...| Class_2| 0.0|[-0.2535060296260...|
|[0.0,1.0,0.0,1.0,...| Class_6| 1.0|[-0.2535060296260...|
|[0.0,0.0,0.0,0.0,...| Class_9| 4.0|[-0.2535060296260...|
|[0.0,0.0,0.0,0.0,...| Class_2| 0.0|[-0.2535060296260...|
|[0.0,0.0,0.0,0.0,...| Class_2| 0.0|[-0.2535060296260...|
|[0.0,0.0,0.0,0.0,...| Class_3| 3.0|[-0.2535060296260...|
|[0.0,0.0,4.0,0.0,...| Class_8| 2.0|[-0.2535060296260...|
|[0.0,0.0,0.0,0.0,...| Class_7| 5.0|[-0.2535060296260...|
+--------------------+--------+--------------+--------------------+
only showing top 10 rows
Keras深度学习模式
现在我们有一个具有处理特征和标签的数据框架,我们定义一个深层神经网络,我们可以使用它来解决分类问题。你有机会来这里,因为你知道一两件关于深入学习的东西。如果是这样,下面的模型看起来很简单。我们通过选择一组三个连续的密集层来建立一个keras模型,其中包含退出和ReLU激活。对于这个问题肯定有更好的架构,但是我们只是想在这里展示一般的流程。
- 1
- 2
- 3
- 4
- 五
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 1
- 2
- 3
- 4
- 五
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
分布式Elephas模型
为了将上述Keras提升model
到Spark,我们定义了一个Estimator
。一个Estimator
是,仍然有被训练模型的星火的化身。它本质上只有一个(必需)的方法,即fit
。一旦我们调用fit
了数据框架,我们就回到了一个Model
,这是一个训练有素的模型,transform
用来预测标签的方法。
我们通过初始化ElephasEstimator
和设置一些属性来实现。到目前为止,我们的输入数据框架将有很多列,我们必须通过列名告诉模型在哪里查找功能和标签。然后我们提供Keras模型和Elephas优化器的序列化版本。我们不能直接插入keras模型Estimator
,因为Spark将不得不将其序列化为与工作人员的沟通,所以最好自己提供序列化。事实上,虽然pyspark知道如何序列化model
,但它是非常低效的,如果模型变得太大,可能会破裂。Spark ML对参数特别挑剔(正确地),或多或少地禁止您提供后者的非原子类型和数组。大多数剩余的参数是可选的,而且是自我解释的。加,许多人,你知道如果你以前曾经运行过克拉斯模型。我们只是将他们包括在内,以显示全套培训配置。
- 1
- 2
- 3
- 4
- 五
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 1
- 2
- 3
- 4
- 五
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
ElephasEstimator_415398ab22cb1699f794
SparkML管道
现在的简单部分:定义管道真的像列出流水线阶段一样简单。我们可以提供Transformers
和Estimators
真正的任何配置,但是这里我们只需要先前定义的三个组件。请注意,string_indexer
并scaler
和互换,而estimator
有些明明已经来到最后的管道。
- 1
- 2
- 3
- 1
- 2
- 3
安装和评估管道
现在的最后一步是适应管道的培训数据和评估。我们对训练数据进行评估,即转换,因为只有在这种情况下,我们有标签来检查模型的准确性。如果你喜欢,你也可以改造test_df
。
- 1
- 2
- 3
- 4
- 五
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 五
- 6
- 7
- 8
- 9
- 10
- 11
- 12
61878/61878 [==============================] - 0s
+--------------+----------+
|index_category|prediction|
+--------------+----------+
| 2.0| 2.0|
| 2.0| 2.0|
| 0.0| 0.0|
| 1.0| 1.0|
| 4.0| 4.0|
| 0.0| 0.0|
| 0.0| 0.0|
| 3.0| 3.0|
| 2.0| 2.0|
| 5.0| 0.0|
| 0.0| 0.0|
| 4.0| 4.0|
| 0.0| 0.0|
| 4.0| 1.0|
| 2.0| 2.0|
| 1.0| 1.0|
| 0.0| 0.0|
| 6.0| 0.0|
| 2.0| 2.0|
| 1.0| 1.0|
| 2.0| 2.0|
| 8.0| 8.0|
| 1.0| 1.0|
| 5.0| 0.0|
| 0.0| 0.0|
| 0.0| 3.0|
| 0.0| 0.0|
| 1.0| 1.0|
| 4.0| 4.0|
| 2.0| 2.0|
| 0.0| 3.0|
| 3.0| 3.0|
| 0.0| 0.0|
| 3.0| 0.0|
| 1.0| 5.0|
| 3.0| 3.0|
| 2.0| 2.0|
| 1.0| 1.0|
| 0.0| 0.0|
| 2.0| 2.0|
| 2.0| 2.0|
| 1.0| 1.0|
| 6.0| 6.0|
| 1.0| 1.0|
| 0.0| 3.0|
| 7.0| 0.0|
| 0.0| 0.0|
| 0.0| 0.0|
| 1.0| 1.0|
| 1.0| 1.0|
| 6.0| 6.0|
| 0.0| 0.0|
| 0.0| 3.0|
| 2.0| 2.0|
| 0.0| 0.0|
| 2.0| 2.0|
| 0.0| 0.0|
| 4.0| 4.0|
| 0.0| 0.0|
| 6.0| 6.0|
| 2.0| 5.0|
| 0.0| 3.0|
| 3.0| 0.0|
| 0.0| 0.0|
| 3.0| 3.0|
| 4.0| 4.0|
| 0.0| 3.0|
| 0.0| 0.0|
| 0.0| 0.0|
| 4.0| 4.0|
| 3.0| 0.0|
| 2.0| 2.0|
| 1.0| 1.0|
| 7.0| 7.0|
| 0.0| 0.0|
| 0.0| 0.0|
| 0.0| 3.0|
| 1.0| 1.0|
| 1.0| 1.0|
| 5.0| 4.0|
| 1.0| 1.0|
| 1.0| 1.0|
| 4.0| 4.0|
| 3.0| 3.0|
| 0.0| 0.0|
| 2.0| 2.0|
| 4.0| 4.0|
| 7.0| 7.0|
| 2.0| 2.0|
| 0.0| 0.0|
| 1.0| 1.0|
| 0.0| 0.0|
| 4.0| 4.0|
| 1.0| 1.0|
| 0.0| 0.0|
| 0.0| 0.0|
| 0.0| 0.0|
| 0.0| 3.0|
| 0.0| 3.0|
| 0.0| 0.0|
+--------------+----------+
only showing top 100 rows
0.764132648114
结论
当然,需要一些时间掌握Keras和Spark的原理和语法,这取决于您来自哪里。然而,我们也希望您得出结论,一旦您超越了定义模型和预处理数据的艰巨阶段,构建和使用SparkML流水线的业务是非常优雅和有用的。
如果您喜欢您所看到的,请考虑进一步改善对Ceras或Spark的影响。你对这款笔记本电脑有什么建设性的意见吗?有什么要我澄清吗?无论如何,请随时与我联系。