在Spark中,目前包括的神经网络方面的算法仅有MLPC,即MultilayerPerceptronClassifier(多层感知分类器)。它在MLlib的Classification and regression(分类与回归)中。MLPC是基于前馈人工神经网络(ANN)的分类器,属于全连接神经网络,其中隐藏层的激活函数是sigmoid函数,输出层是softmax函数。关于MLPC的原理,网络上有比较多详细的介绍,这里不再累述。本博客主要通过一个应用案例展示MLPC的使用过程,包括原始数据的预处理、MLPC算法的使用以及效果的评估。
运行本实例代码请保证spark版本在2.3及以上。
数据源:
数据源是基于某行业的开放数据源。其中se是用户标签、sf是消费能力,pb、pc是产品参数,pa是要预测的结果,即某用户是否会消费某产品,0表示不购买,1表示购买。总数量20万条(相对于神经网络算法数据量偏少,这里只做案例演示),上图展示部分数据源。
数据预处理:
可以看到,数据源包含两种类型,第一是标签类型se,第二是数值类型sf、pb和pc,其中sf与pb、pc不在一个量纲与数量级。所以数据预处理的思路是先对se做独热编码,然后进行降维。最后对4种特征均进行标准化。
关于更多的Spark数据预处理的方法,可以参考博主关于spark特征工程的博文:
https://blog.csdn.net/u013090676/article/details/84191468
独热编码:
由于Spark中独热编码只能使用数值类型的输入,所以需要先将字符标签处理成int类型的标签(mRecord即数据源):
val indexer = new StringIndexer()
.setInputCol("se")
.setOutputCol("se_indexer");
val mRecord_indexed = indexer.fit(mRecord).transform(mRecord).drop("se");
//独热编码
val encoder = new OneHotEncoderEstimator()
.setInputCols(Array("se_indexer"))
.setOutputCols(Array("se_onehot"));
val mRecord_onehot = encoder.fit(mRecord_indexed).transform(mRecord_indexed).drop("se_indexer");
PCA降维:
独热编码后的数据一般维度都比较高,不适合直接作为输入,所以用PCA进行降维:
val mRecord_pac_onehot = new PCA()
.setInputCol("se_onehot")
.setOutputCol("se_pca_onehot")
.setK(2)
.fit(mRecord_onehot).transform(mRecord_onehot).drop("se_onehot");
特征合并:
将所有维度的特征合并成一个向量,作为MLPC的输入:
val mRecord_va = new VectorAssembler()
.setInputCols(Array("sf", "pb", "pc","se_pca_onehot"))
.setOutputCol("features")
.transform(mRecord_pac_onehot)
.drop("sf").drop("pb").drop("pc").drop("se_pca_onehot");
标准化:
对合并的向量进行标准化,标准化包括零均值和单位标准差:
val mRecord_ss = new StandardScaler()
.setInputCol("features")
.setOutputCol("scaledFeatures")
.setWithStd(true)
.setWithMean(true)
.fit(mRecord_va)
.transform(mRecord_va).drop("features");
MLPC神经网络训练与预测:
经过预处理的数据,按照6:4的比例分成两部分,一部分作为训练数据,一部分作为验证数据。其中layers表示神经网络的层数,是一个int类型的数据,第一位与输入特征的维度保持一致,最后一位与输出标签的数量保持一致,数组中间的位数表示隐藏层的层数以及每层的神经元数量:
val splits = mRecord_ss.randomSplit(Array(0.6, 0.4), seed = 1234L);
val train = splits(0);
val test = splits(1);
val layers = Array[Int](5, 3, 2);
val trainer = new MultilayerPerceptronClassifier()
.setFeaturesCol("scaledFeatures")
.setLabelCol("pa")
.setLayers(layers)
.setBlockSize(128)
.setSeed(1234L)
.setMaxIter(32)
val result = trainer.fit(train).transform(test).select("prediction", "pa");
MLPC效果评估:
val evaluator = new MulticlassClassificationEvaluator()
.setMetricName("accuracy")
.setLabelCol("pa")
.setPredictionCol("prediction");
println(s"准确度是 ${evaluator.evaluate(result)}");
最终得到的准确度是69%。
上述案例只是一个最简案例,采用了最基本的数据预处理与效果评估的方法。实际数据分析以及神经网络应用过程中,应该充分深入业务,理解数据含义,做好特征工程、算法选型与调优,对分析结果进行细致完善的评估。