您好,登錄后才能下訂單哦!
這篇文章將為大家詳細(xì)講解有關(guān)基于Spark Mllib文本分類(lèi)的示例分析,小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
基于Spark Mllib的文本分類(lèi)
文本分類(lèi)是一個(gè)典型的機(jī)器學(xué)習(xí)問(wèn)題,其主要目標(biāo)是通過(guò)對(duì)已有語(yǔ)料庫(kù)文本數(shù)據(jù)訓(xùn)練得到分類(lèi)模型,進(jìn)而對(duì)新文本進(jìn)行類(lèi)別標(biāo)簽的預(yù)測(cè)。這在很多領(lǐng)域都有現(xiàn)實(shí)的應(yīng)用場(chǎng)景,如新聞網(wǎng)站的新聞自動(dòng)分類(lèi),垃圾郵件檢測(cè),非法信息過(guò)濾等。本文將通過(guò)訓(xùn)練一個(gè)手機(jī)短信樣本數(shù)據(jù)集來(lái)實(shí)現(xiàn)新數(shù)據(jù)樣本的分類(lèi),進(jìn)而檢測(cè)其是否為垃圾消息,基本步驟是:首先將文本句子轉(zhuǎn)化成單詞數(shù)組,進(jìn)而使用 Word2Vec 工具將單詞數(shù)組轉(zhuǎn)化成一個(gè) K 維向量,最后通過(guò)訓(xùn)練 K 維向量樣本數(shù)據(jù)得到一個(gè)前饋神經(jīng)網(wǎng)絡(luò)模型,以此來(lái)實(shí)現(xiàn)文本的類(lèi)別標(biāo)簽預(yù)測(cè)。本文案例實(shí)現(xiàn)上采用 Spark ML 中的詞向量化工具 Word2Vec 和多層感知器分類(lèi)器 (Multiple Layer Perceptron Classifier)
Word2Vec簡(jiǎn)介
Word2Vec 是一個(gè)用來(lái)將詞表示為數(shù)值型向量的工具,其基本思想是將文本中的詞映射成一個(gè) K 維數(shù)值向量 (K 通常作為算法的超參數(shù)),這樣文本中的所有詞就組成一個(gè) K 維向量空間,這樣我們可以通過(guò)計(jì)算向量間的歐氏距離或者余弦相似度得到文本語(yǔ)義的相似度。Word2Vec 采用的是 Distributed representation 的詞向量表示方式,這種表達(dá)方式不僅可以有效控制詞向量的維度,避免維數(shù)災(zāi)難 (相對(duì)于 one-hot representation),而且可以保證意思相近的詞在向量空間中的距離較近。
Word2Vec 實(shí)現(xiàn)上有兩種模型 CBOW (Continuous Bag of Words, 連續(xù)詞袋模型) 和 Skip-Gram,簡(jiǎn)單概括一下區(qū)別就是:CBOW 是根據(jù)語(yǔ)境預(yù)測(cè)目標(biāo)單詞,Skip-Gram 根據(jù)當(dāng)前單詞預(yù)測(cè)語(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ì)算概率,并且通常情況下,上下文窗口越大所能涵蓋的詞組合情況就越全面,這樣可以帶來(lái)更加精確的結(jié)果,但是缺點(diǎn)是也會(huì)增加訓(xùn)練時(shí)間。
在 Skip-Gram 模型里,每個(gè)單詞都關(guān)聯(lián)兩個(gè)向量,分別表示詞向量和上下文向量。也正是因?yàn)槿绱?,Word2Vec 較之傳統(tǒng)的 LDA(Latent Dirichlet Allocation) 過(guò)程,可以表達(dá)更加豐富和準(zhǔn)確的語(yǔ)義信息。
Spark 的 Word2Vec 實(shí)現(xiàn)提供以下主要可調(diào)參數(shù):
inputCol , 源數(shù)據(jù) DataFrame 中存儲(chǔ)文本詞數(shù)組列的名稱(chēng)。
outputCol, 經(jīng)過(guò)處理的數(shù)值型特征向量存儲(chǔ)列名稱(chēng)。
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í)候通過(guò) setXXX 方法設(shè)置。
多層感知器
多層感知器 (MLP, Multilayer Perceptron) 是一種多層的前饋神經(jīng)網(wǎng)絡(luò)模型,所謂前饋型神經(jīng)網(wǎng)絡(luò),指其從輸入層開(kāi)始只接收前一層的輸入,并把計(jì)算結(jié)果輸出到后一層,并不會(huì)給前一層有所反饋,整個(gè)過(guò)程可以使用有向無(wú)環(huán)圖來(lái)表示。該類(lèi)型的神經(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 算法名稱(chēng)里的反向傳播指的是該算法在訓(xùn)練網(wǎng)絡(luò)的過(guò)程中逐層反向傳遞誤差,逐一修改神經(jīng)元間的連接權(quán)值,以使網(wǎng)絡(luò)對(duì)輸入信息經(jīng)過(guò)計(jì)算后所得到的輸出能達(dá)到期望的誤差。Spark 的多層感知器隱層神經(jīng)元使用 sigmoid 函數(shù)作為激活函數(shù),輸出層使用的是 softmax 函數(shù)。
Spark 的多層感知器分類(lèi)器 (MultilayerPerceptronClassifer) 支持以下可調(diào)參數(shù):
featuresCol:輸入數(shù)據(jù) DataFrame 中指標(biāo)特征列的名稱(chēng)。
labelCol:輸入數(shù)據(jù) DataFrame 中標(biāo)簽列的名稱(chēng)。
layers:這個(gè)參數(shù)是一個(gè)整型數(shù)組類(lèi)型,第一個(gè)元素需要和特征向量的維度相等,最后一個(gè)元素需要訓(xùn)練數(shù)據(jù)的標(biāo)簽取值個(gè)數(shù)相等,如 2 分類(lèi)問(wèn)題就寫(xiě) 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ù)測(cè)結(jié)果的列名稱(chēng)。
tol:優(yōu)化算法迭代求解過(guò)程的收斂閥值。默認(rèn)值是 1e-4。不能為負(fù)數(shù)。
blockSize:該參數(shù)被前饋網(wǎng)絡(luò)訓(xùn)練器用來(lái)將訓(xùn)練樣本數(shù)據(jù)的每個(gè)分區(qū)都按照 blockSize 大小分成不同組,并且每個(gè)組內(nèi)的每個(gè)樣本都會(huì)被疊加成一個(gè)向量,以便于在各種優(yōu)化算法間傳遞。該參數(shù)的推薦值是 10-1000,默認(rèn)值是 128。
算法的返回是一個(gè) MultilayerPerceptronClassificationModel 類(lèi)實(shí)例。
目標(biāo)數(shù)據(jù)集預(yù)覽
在引言部分,筆者已經(jīng)簡(jiǎn)要介紹過(guò)了本文的主要任務(wù),即通過(guò)訓(xùn)練一個(gè)多層感知器分類(lèi)模型來(lái)預(yù)測(cè)新的短信是否為垃圾短信。在這里我們使用的目標(biāo)數(shù)據(jù)集是來(lái)自 UCI 的 SMS Spam Collection 數(shù)據(jù)集,該數(shù)據(jù)集結(jié)構(gòu)非常簡(jiǎn)單,只有兩列,第一列是短信的標(biāo)簽 ,第二列是短信內(nèi)容,兩列之間用制表符 (tab) 分隔。雖然 UCI 的數(shù)據(jù)集是可以拿來(lái)免費(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)
在處理文本短信息分類(lèi)預(yù)測(cè)問(wèn)題的過(guò)程中,筆者首先是將原始文本數(shù)據(jù)按照 8:2 的比例分成訓(xùn)練和測(cè)試數(shù)據(jù)集。整個(gè)過(guò)程分為下面幾個(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ù)測(cè)結(jié)果的數(shù)值標(biāo)簽轉(zhuǎn)化成原始的文本標(biāo)簽。
最后在測(cè)試數(shù)據(jù)集上測(cè)試模型的預(yù)測(cè)精確度。
算法的具體實(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文本分類(lèi)的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。