在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%。
上述案例只是一個最簡案例,採用了最基本的數據預處理與效果評估的方法。實際數據分析以及神經網絡應用過程中,應該充分深入業務,理解數據含義,做好特徵工程、算法選型與調優,對分析結果進行細緻完善的評估。