新聞中心
這篇文章將為大家詳細(xì)講解有關(guān)基于Spark Mllib文本分類的示例分析,小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
創(chuàng)新互聯(lián)專注于企業(yè)成都營銷網(wǎng)站建設(shè)、網(wǎng)站重做改版、黔西網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、H5開發(fā)、成都商城網(wǎng)站開發(fā)、集團(tuán)公司官網(wǎng)建設(shè)、外貿(mào)網(wǎng)站建設(shè)、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性價(jià)比高,為黔西等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。
基于Spark Mllib的文本分類
文本分類是一個(gè)典型的機(jī)器學(xué)習(xí)問題,其主要目標(biāo)是通過對(duì)已有語料庫文本數(shù)據(jù)訓(xùn)練得到分類模型,進(jìn)而對(duì)新文本進(jìn)行類別標(biāo)簽的預(yù)測。這在很多領(lǐng)域都有現(xiàn)實(shí)的應(yīng)用場景,如新聞網(wǎng)站的新聞自動(dòng)分類,垃圾郵件檢測,非法信息過濾等。本文將通過訓(xùn)練一個(gè)手機(jī)短信樣本數(shù)據(jù)集來實(shí)現(xiàn)新數(shù)據(jù)樣本的分類,進(jìn)而檢測其是否為垃圾消息,基本步驟是:首先將文本句子轉(zhuǎn)化成單詞數(shù)組,進(jìn)而使用 Word2Vec 工具將單詞數(shù)組轉(zhuǎn)化成一個(gè) K 維向量,最后通過訓(xùn)練 K 維向量樣本數(shù)據(jù)得到一個(gè)前饋神經(jīng)網(wǎng)絡(luò)模型,以此來實(shí)現(xiàn)文本的類別標(biāo)簽預(yù)測。本文案例實(shí)現(xiàn)上采用 Spark ML 中的詞向量化工具 Word2Vec 和多層感知器分類器 (Multiple Layer Perceptron Classifier)
Word2Vec簡介
Word2Vec 是一個(gè)用來將詞表示為數(shù)值型向量的工具,其基本思想是將文本中的詞映射成一個(gè) K 維數(shù)值向量 (K 通常作為算法的超參數(shù)),這樣文本中的所有詞就組成一個(gè) K 維向量空間,這樣我們可以通過計(jì)算向量間的歐氏距離或者余弦相似度得到文本語義的相似度。Word2Vec 采用的是 Distributed representation 的詞向量表示方式,這種表達(dá)方式不僅可以有效控制詞向量的維度,避免維數(shù)災(zāi)難 (相對(duì)于 one-hot representation),而且可以保證意思相近的詞在向量空間中的距離較近。
Word2Vec 實(shí)現(xiàn)上有兩種模型 CBOW (Continuous Bag of Words, 連續(xù)詞袋模型) 和 Skip-Gram,簡單概括一下區(qū)別就是:CBOW 是根據(jù)語境預(yù)測目標(biāo)單詞,Skip-Gram 根據(jù)當(dāng)前單詞預(yù)測語境。Spark 的實(shí)現(xiàn)采用的是 Skip-Gram 模型 。假設(shè)我們有 N 個(gè)待訓(xùn)練的單詞序列樣本,記作 w1,w2...wn, Skip-Gram 模型的訓(xùn)練目標(biāo)是最大化平均對(duì)數(shù)似然,即
其中 N 是詞個(gè)數(shù),K 是詞上下文的窗口大小。Skip-Gram 模型中一定上下文窗口內(nèi)的詞兩兩之間都會(huì)計(jì)算概率,并且通常情況下,上下文窗口越大所能涵蓋的詞組合情況就越全面,這樣可以帶來更加精確的結(jié)果,但是缺點(diǎn)是也會(huì)增加訓(xùn)練時(shí)間。
在 Skip-Gram 模型里,每個(gè)單詞都關(guān)聯(lián)兩個(gè)向量,分別表示詞向量和上下文向量。也正是因?yàn)槿绱耍琖ord2Vec 較之傳統(tǒng)的 LDA(Latent Dirichlet Allocation) 過程,可以表達(dá)更加豐富和準(zhǔn)確的語義信息。
Spark 的 Word2Vec 實(shí)現(xiàn)提供以下主要可調(diào)參數(shù):
inputCol , 源數(shù)據(jù) DataFrame 中存儲(chǔ)文本詞數(shù)組列的名稱。
outputCol, 經(jīng)過處理的數(shù)值型特征向量存儲(chǔ)列名稱。
vectorSize, 目標(biāo)數(shù)值向量的維度大小,默認(rèn)是 100。
windowSize, 上下文窗口大小,默認(rèn)是 5。
numPartitions, 訓(xùn)練數(shù)據(jù)的分區(qū)數(shù),默認(rèn)是 1。
maxIter,算法求最大迭代次數(shù),小于或等于分區(qū)數(shù)。默認(rèn)是 1.
minCount, 只有當(dāng)某個(gè)詞出現(xiàn)的次數(shù)大于或者等于 minCount 時(shí),才會(huì)被包含到詞匯表里,否則會(huì)被忽略掉。
stepSize,優(yōu)化算法的每一次迭代的學(xué)習(xí)速率。默認(rèn)值是 0.025.
這些參數(shù)都可以在構(gòu)造 Word2Vec 實(shí)例的時(shí)候通過 setXXX 方法設(shè)置。
多層感知器
多層感知器 (MLP, Multilayer Perceptron) 是一種多層的前饋神經(jīng)網(wǎng)絡(luò)模型,所謂前饋型神經(jīng)網(wǎng)絡(luò),指其從輸入層開始只接收前一層的輸入,并把計(jì)算結(jié)果輸出到后一層,并不會(huì)給前一層有所反饋,整個(gè)過程可以使用有向無環(huán)圖來表示。該類型的神經(jīng)網(wǎng)絡(luò)由三層組成,分別是輸入層 (Input Layer),一個(gè)或多個(gè)隱層 (Hidden Layer),輸出層 (Output Layer),如圖所示:
Spark ML 在 1.5 版本后提供一個(gè)使用 BP(反向傳播,Back Propagation) 算法訓(xùn)練的多層感知器實(shí)現(xiàn),BP 算法的學(xué)習(xí)目的是對(duì)網(wǎng)絡(luò)的連接權(quán)值進(jìn)行調(diào)整,使得調(diào)整后的網(wǎng)絡(luò)對(duì)任一輸入都能得到所期望的輸出。BP 算法名稱里的反向傳播指的是該算法在訓(xùn)練網(wǎng)絡(luò)的過程中逐層反向傳遞誤差,逐一修改神經(jīng)元間的連接權(quán)值,以使網(wǎng)絡(luò)對(duì)輸入信息經(jīng)過計(jì)算后所得到的輸出能達(dá)到期望的誤差。Spark 的多層感知器隱層神經(jīng)元使用 sigmoid 函數(shù)作為激活函數(shù),輸出層使用的是 softmax 函數(shù)。
Spark 的多層感知器分類器 (MultilayerPerceptronClassifer) 支持以下可調(diào)參數(shù):
featuresCol:輸入數(shù)據(jù) DataFrame 中指標(biāo)特征列的名稱。
labelCol:輸入數(shù)據(jù) DataFrame 中標(biāo)簽列的名稱。
layers:這個(gè)參數(shù)是一個(gè)整型數(shù)組類型,第一個(gè)元素需要和特征向量的維度相等,最后一個(gè)元素需要訓(xùn)練數(shù)據(jù)的標(biāo)簽取值個(gè)數(shù)相等,如 2 分類問題就寫 2。中間的元素有多少個(gè)就代表神經(jīng)網(wǎng)絡(luò)有多少個(gè)隱層,元素的取值代表了該層的神經(jīng)元的個(gè)數(shù)。例如val layers = Array[Int](100,6,5,2)。
maxIter:優(yōu)化算法求解的最大迭代次數(shù)。默認(rèn)值是 100。
predictionCol:預(yù)測結(jié)果的列名稱。
tol:優(yōu)化算法迭代求解過程的收斂閥值。默認(rèn)值是 1e-4。不能為負(fù)數(shù)。
blockSize:該參數(shù)被前饋網(wǎng)絡(luò)訓(xùn)練器用來將訓(xùn)練樣本數(shù)據(jù)的每個(gè)分區(qū)都按照 blockSize 大小分成不同組,并且每個(gè)組內(nèi)的每個(gè)樣本都會(huì)被疊加成一個(gè)向量,以便于在各種優(yōu)化算法間傳遞。該參數(shù)的推薦值是 10-1000,默認(rèn)值是 128。
算法的返回是一個(gè) MultilayerPerceptronClassificationModel 類實(shí)例。
目標(biāo)數(shù)據(jù)集預(yù)覽
在引言部分,筆者已經(jīng)簡要介紹過了本文的主要任務(wù),即通過訓(xùn)練一個(gè)多層感知器分類模型來預(yù)測新的短信是否為垃圾短信。在這里我們使用的目標(biāo)數(shù)據(jù)集是來自 UCI 的 SMS Spam Collection 數(shù)據(jù)集,該數(shù)據(jù)集結(jié)構(gòu)非常簡單,只有兩列,第一列是短信的標(biāo)簽 ,第二列是短信內(nèi)容,兩列之間用制表符 (tab) 分隔。雖然 UCI 的數(shù)據(jù)集是可以拿來免費(fèi)使用的,但在這里筆者依然嚴(yán)正聲明該數(shù)據(jù)集的版權(quán)屬于 UCI 及其原始貢獻(xiàn)者。
數(shù)據(jù)集下載鏈接:http://archive.ics.uci.edu/ml/datasets/SMS+Spam+Collection
案例分析與實(shí)現(xiàn)
在處理文本短信息分類預(yù)測問題的過程中,筆者首先是將原始文本數(shù)據(jù)按照 8:2 的比例分成訓(xùn)練和測試數(shù)據(jù)集。整個(gè)過程分為下面幾個(gè)步驟
從本地讀取原始數(shù)據(jù)集,并創(chuàng)建一個(gè) DataFrame。
使用 StringIndexer 將原始的文本標(biāo)簽 (“Ham”或者“Spam”) 轉(zhuǎn)化成數(shù)值型的表型,以便 Spark ML 處理。
使用 Word2Vec 將短信文本轉(zhuǎn)化成數(shù)值型詞向量。
使用 MultilayerPerceptronClassifier 訓(xùn)練一個(gè)多層感知器模型。
使用 LabelConverter 將預(yù)測結(jié)果的數(shù)值標(biāo)簽轉(zhuǎn)化成原始的文本標(biāo)簽。
最后在測試數(shù)據(jù)集上測試模型的預(yù)測精確度。
算法的具體實(shí)現(xiàn)如下:
1, 首先導(dǎo)入包
import org.apache.spark.ml.Pipeline
import org.apache.spark.ml.classification.MultilayerPerceptronClassifier
import org.apache.spark.ml.evaluation.MulticlassClassificationEvaluator
import org.apache.spark.ml.feature.{IndexToString, StringIndexer, Word2Vec}
2, 創(chuàng)建 集并分詞
val parsedRDD = sc.textFile("file:///opt/datas/SMSSpamCollection").map(_.split(" ")).map(eachRow => {
(eachRow(0),eachRow(1).split(" "))
})
val msgDF = spark.createDataFrame(parsedRDD).toDF("label","message")
3, 將標(biāo)簽轉(zhuǎn)化為索引值
val labelIndexer = new StringIndexer().setInputCol("label").setOutputCol("indexedLabel").fit(msgDF)
4, 創(chuàng)建Word2Vec,分詞向量大小100
final val VECTOR_SIZE = 100
val word2Vec = new Word2Vec().setInputCol("message").setOutputCol("features").setVectorSize(VECTOR_SIZE).setMinCount(1)
5, 創(chuàng)建多層感知器
輸入層VECTOR_SIZE個(gè),中間層兩層分別是6,,5個(gè)神經(jīng)元,輸出層2個(gè)
val layers = Array[Int](VECTOR_SIZE,6,5,2)
val mlpc = new MultilayerPerceptronClassifier().setLayers(layers).setBlockSize(512).setSeed(1234L).setMaxIter(128).setFeaturesCol("features").setLabelCol("indexedLabel").setPredictionCol("prediction")
6, 將索引轉(zhuǎn)換為原有標(biāo)簽
val labelConverter = new IndexToString().setInputCol("prediction").setOutputCol("predictedLabel").setLabels(labelIndexer.labels)
7, 數(shù)據(jù)集分割
val Array(trainingData, testData) = msgDF.randomSplit(Array(0.8, 0.2))
8, 創(chuàng)建pipeline并訓(xùn)練數(shù)據(jù)
val pipeline = new Pipeline().setStages(Array(labelIndexer,word2Vec,mlpc,labelConverter))
val model = pipeline.fit(trainingData)
val predictionResultDF = model.transform(testData)
//below 2 lines are for debug use
predictionResultDF.printSchema
predictionResultDF.select("message","label","predictedLabel").show(30)
9, 評(píng)估訓(xùn)練結(jié)果
val evaluator = new MulticlassClassificationEvaluator().setLabelCol("indexedLabel").setPredictionCol("prediction").setMetricName("precision")
val predictionAccuracy = evaluator.evaluate(predictionResultDF)
println("Testing Accuracy is %2.4f".format(predictionAccuracy * 100) + "%")
關(guān)于“基于Spark Mllib文本分類的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。
網(wǎng)頁標(biāo)題:基于SparkMllib文本分類的示例分析
當(dāng)前地址:http://fisionsoft.com.cn/article/ihoigd.html