Spark機器學習庫中包含了兩種實現方式,一種是spark.mllib,這種是基礎的API,基於RDDs之上構建,另外一種是spark.ml,這種是higher-level API,基於DataFrames之上構建,spark.ml使用起來比較方便和靈活。sql
Spark機器學習中關於特徵處理的API主要包含三個方面:特徵提取、特徵轉換與特徵選擇。本文經過例子介紹和學習Spark.ml中提供的關於特徵處理的API。apache
特徵提取(Feature Extractors)app
1. TF-IDF (HashingTF and IDF)機器學習
TF-IDF是文本特徵提取中一個經常使用的方法,用以評估一字詞對於一個文件集或一個語料庫中的其中一份文件的重要程度。關於spark.ml中提供的HashingTF和IDF的原理和用法,在以前的文章http://lxw1234.com/archives/2016/01/605.htm中已經介紹過,這裏再也不介紹。工具
2. Word2Vec學習
Word2Vec是一個將單詞轉換成向量形式的工具。能夠把對文本內容的處理簡化爲向量空間中的向量運算,計算出向量空間上的類似度,來表示文本語義上的類似度。大數據
大數據學習交流羣:724693112 歡迎你們來一塊兒學習。spa
下面的例子將每一個文檔中的詞語轉換成長度爲3的向量:orm
package com.lxw1234.spark.featureshtm
import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
import org.apache.spark.ml.feature.Word2Vec
/**
* auth: http://lxw1234.com
*/
object TestWord2Vec {
def main(args : Array[String]) {
val conf = new SparkConf().setMaster("local").setAppName("lxw1234.com")
val sc = new SparkContext(conf)
val sqlContext = new org.apache.spark.sql.SQLContext(sc)
import sqlContext.implicits._
val documentDF = sqlContext.createDataFrame(Seq(
"蘋果 官網 蘋果 宣佈".split(" "),
"蘋果 梨 香蕉".split(" ")
).map(Tuple1.apply)).toDF("text")
val word2Vec = new Word2Vec().setInputCol("text").setOutputCol("result").setVectorSize(3).setMinCount(1)
val model = word2Vec.fit(documentDF)
val result = model.transform(documentDF)
result.collect().foreach(println)
}
}
程序運行輸出以下:
[WrappedArray(蘋果, 官網, 蘋果, 宣佈),[0.006021047011017799,-0.002911671996116638,0.05357655562693253]]
[WrappedArray(蘋果, 梨, 香蕉),[-0.10302492479483286,-0.059321289261182145,0.05107089380423228]]
3. CountVectorizer
該方法用於將全部的文本詞語進行編號,每一個詞語對應一個編號,並統計該詞語在文檔中的詞頻做爲特徵向量。
package com.lxw1234.spark.features
import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
import org.apache.spark.ml.feature.{CountVectorizer, CountVectorizerModel}
/**
* auth: http://lxw1234.com
*/
object TestCountVectorizer {
def main(args : Array[String]) {
val conf = new SparkConf().setMaster("local").setAppName("lxw1234.com")
val sc = new SparkContext(conf)
val sqlContext = new org.apache.spark.sql.SQLContext(sc)
import sqlContext.implicits._
val df = sqlContext.createDataFrame(Seq(
(0, Array("蘋果","官網","蘋果","宣佈")),
(1, Array("蘋果","梨","香蕉"))
)).toDF("id", "words")
var cvModel: CountVectorizerModel = new CountVectorizer()
.setInputCol("words")
.setOutputCol("features")
.setVocabSize(5) //設置詞語的總個數,詞語編號後的數值均小於該值
.setMinDF(1) //設置包含詞語的最少的文檔數
.fit(df)
println("output1:")
cvModel.transform(df).select("id","words","features").collect().foreach(println)
var cvModel2: CountVectorizerModel = new CountVectorizer()
.setInputCol("words")
.setOutputCol("features")
.setVocabSize(3) //設置詞語的總個數,詞語編號後的數值均小於該值
.setMinDF(2) //設置包含詞語的最少的文檔數
.fit(df)
println("output2:")
cvModel2.transform(df).select("id","words","features").collect().foreach(println)
}
}
程序output1的輸出以下:
[0,WrappedArray(蘋果, 官網, 蘋果, 宣佈),(5,[0,3,4],[2.0,1.0,1.0])]
[1,WrappedArray(蘋果, 梨, 香蕉),(5,[0,1,2],[1.0,1.0,1.0])]
程序output2的輸出以下:
[0,WrappedArray(蘋果, 官網, 蘋果, 宣佈),(1,[0],[2.0])]
[1,WrappedArray(蘋果, 梨, 香蕉),(1,[0],[1.0])]
由於setMinDF(2)設置了詞語最低出現的文檔數爲2,所以只保留了」蘋果」一詞。