這一部分我們主要介紹和特征處理相關的算法,大體分為以下三類:
特征抽取:從原始數據中抽取特征
特征轉換:特征的維度、特征的轉化、特征的修改
特征選取:從大規模特征集中選取一個子集
特征提取
TF-IDF (HashingTF and IDF)
“詞頻-逆向文件頻率”(TF-IDF)是一種在文本挖掘中廣泛使用的特征向量化方法,它可以體現一個文檔中詞語在語料庫中的重要程度。
? 詞語由t表示,文檔由d表示,語料庫由D表示。詞頻TF(t,d)是詞語t在文檔d中出現的次數。文件頻率DF(t,D)是包含詞語的文檔的個數。如果我們只使用詞頻來衡量重要性,很容易過度強調在文檔中經常出現,卻沒有太多實際信息的詞語,比如“a”,“the”以及“of”。如果一個詞語經常出現在語料庫中,意味著它并不能很好的對文檔進行區分。TF-IDF就是在數值化文檔信息,衡量詞語能提供多少信息以區分文檔。其定義如下:
? 此處 是語料庫中總的文檔數。公式中使用log函數,當詞出現在所有文檔中時,它的IDF值變為0。加1是為了避免分母為0的情況。TF-IDF 度量值表示如下:
? 此處
是語料庫中總的文檔數。公式中使用log函數,當詞出現在所有文檔中時,它的IDF值變為0。加1是為了避免分母為0的情況。TF-IDF 度量值表示如下:
? 在Spark ML庫中,TF-IDF被分成兩部分:TF (+hashing) 和 IDF。
TF: HashingTF 是一個Transformer,在文本處理中,接收詞條的集合然后把這些集合轉化成固定長度的特征向量。這個算法在哈希的同時會統計各個詞條的詞頻。
IDF: IDF是一個Estimator,在一個數據集上應用它的fit()方法,產生一個IDFModel。 該IDFModel 接收特征向量(由HashingTF產生),然后計算每一個詞在文檔中出現的頻次。IDF會減少那些在語料庫中出現頻率較高的詞的權重。
? Spark.mllib 中實現詞頻率統計使用特征hash的方式,原始特征通過hash函數,映射到一個索引值。后面只需要統計這些索引值的頻率,就可以知道對應詞的頻率。這種方式避免設計一個全局1對1的詞到索引的映射,這個映射在映射大量語料庫時需要花費更長的時間。但需要注意,通過hash的方式可能會映射到同一個值的情況,即不同的原始特征通過Hash映射后是同一個值。為了降低這種情況出現的概率,我們只能對特征向量升維。i.e., 提高hash表的桶數,默認特征維度是 2^20 = 1,048,576.
在下面的代碼段中,我們以一組句子開始。首先使用分解器Tokenizer把句子劃分為單個詞語。對每一個句子(詞袋),我們使用HashingTF將句子轉換為特征向量,最后使用IDF重新調整特征向量。這種轉換通常可以提高使用文本特征的性能。
首先,導入TFIDF所需要的包:
from pyspark.ml.feature import HashingTF,IDF,Tokenizer
準備工作完成后,我們創建一個簡單的DataFrame,每一個句子代表一個文檔。
sentenceData = spark.createDataFrame([(0, "I heard about Spark and I love Spark"),(0, "I wish Java could use case classes"),(1, "Logistic regression models are neat")]).toDF("label", "sentence")
在得到文檔集合后,即可用tokenizer對句子進行分詞
tokenizer = Tokenizer(inputCol="sentence", outputCol="words")
wordsData = tokenizer.transform(sentenceData)
得到分詞后的文檔序列后,即可使用HashingTF的transform()方法把句子哈希成特征向量,這里設置哈希表的桶數為2000。
hashingTF = HashingTF(inputCol="words", outputCol="rawFeatures", numFeatures=20)
featurizedData = hashingTF.transform(wordsData)
?可以看到,分詞序列被變換成一個稀疏特征向量,其中每個單詞都被散列成了一個不同的索引值,特征向量在某一維度上的值即該詞匯在文檔中出現的次數。
最后,使用IDF來對單純的詞頻特征向量進行修正,使其更能體現不同詞匯對文本的區別能力,IDF是一個Estimator,調用fit()方法并將詞頻向量傳入,即產生一個IDFModel。
idf = IDF(inputCol="rawFeatures", outputCol="features")
idfModel = idf.fit(featurizedData)
很顯然,IDFModel是一個Transformer,調用它的transform()方法,即可得到每一個單詞對應的TF-IDF度量值。
rescaledData = idfModel.transform(featurizedData)
rescaledData.select("label", "features").show()
可以看到,特征向量已經被其在語料庫中出現的總次數進行了修正,通過TF-IDF得到的特征向量,在接下來可以被應用到相關的機器學習方法中。