特征处理相关的算法,大体分为以下三类:
特征抽取:从原始数据中抽取特征
特征转换:特征的维度、特征的转化、特征的修改
特征选取:从大规模特征集中选取一个子集
特征抽取–TF-IDF (HashingTF and IDF)
“词频-逆向文件频率”(TF-IDF)是一种在文本挖掘中广泛使用的特征向量化方法,它可以体现一个文档中词语在语料库中的重要程度。
词语由t表示,文档由d表示,语料库由D表示。词频TF(t,d)是词语t在文档d中出现的次数。文件频率DF(t,D)是包含词语的文档的个数。
如果我们只使用词频来衡量重要性,很容易过度强调在文档中经常出现,却没有太多实际信息的词语,比如“a”,“the”以及“of”,意味着它并不能很好的对文档进行区分。想想如果一个词语的TF很高,但是IDF比较低,不就说明这个词语很能代表此文档吗?
在Spark ML库中,TF-IDF被分成两部分:TF (+hashing) 和 IDF。
TF: HashingTF 是一个Transformer,在文本处理中,接收词条的集合然后把这些集合转化成固定长度的特征向量。这个算法在哈希的同时会统计各个词条的词频。
IDF: IDF是一个Estimator,在一个数据集上应用它的fit()方法,产生一个IDFModel。 该IDFModel 接收特征向量(由HashingTF产生),然后计算每一个词在文档中出现的频次。IDF会减少那些在语料库中出现频率较高的词的权重。
我们尝试一下生成tfidf向量:
mashu@mashu-Inspiron-5458:/usr/local/spark/python_code/ML$ vim ml_tfidf.py
from pyspark.sql import SparkSession
from pyspark.ml.feature import HashingTF, IDF, Tokenizer
spark = SparkSession.builder.master("local").appName("Word Tfidf").getOrCreate()
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")
# Split words with tokenizer.transform()
tokenizer = Tokenizer(inputCol="sentence",outputCol="words")
wordsData = tokenizer.transform(sentenceData)
# Hash sentence word to TF feature vec by hashingTF.transform()
hashingTF = HashingTF(inputCol="words",outputCol="rawFeatures",numFeatures=20)
featurizedData = hashingTF.transform(wordsData)
# Add IDF to modify TF vec to create tfidf feature vec
idf = IDF(inputCol="rawFeatures",outputCol="features")
idfModel = idf.fit(featurizedData)
rescaledData = idfModel.transform(featurizedData)
rescaledData.select("label","features").show(truncate=False) #不删减内容显示
输出结果如下:
特征抽取–Word2Vec
Word2Vec 是一种著名的 词嵌入(Word Embedding) 方法,它可以计算每个单词在其给定语料库环境下的 分布式词向量(Distributed Representation,亦直接被称为词向量)。词向量表示可以在一定程度上刻画每个单词的语义。
Word2Vec具有两种模型,其一是 CBOW ,其思想是通过每个词的上下文窗口词词向量来预测中心词的词向量。其二是 Skip-gram,其思想是通过每个中心词来预测其上下文窗口词,并根据预测结果来修正中心词的词向量。两种方法示意图如下图所示:
在ml库中,Word2vec 的实现使用的是skip-gram模型。Skip-gram的训练目标是学习词表征向量分布,其优化目标是在给定中心词的词向量的情况下,最大化以下似然函数:
下面介绍ML库中Word2Vec类的使用。
我们首先用一组文档,其中一个词语序列代表一个文档。对于每一个文档,我们将其转换为一个特征向量。此特征向量可以被传递到一个学习算法。
首先,导入Word2Vec所需要的包,并创建三个词语序列,每个代表一个文档:
from pyspark.sql import SparkSession
from pyspark.ml.feature import Word2Vec
spark = SparkSession.builder.master("local").appName("Word Tfidf").getOrCreate()
documentDF = spark.createDataFrame([
("Hi I heard about Spark".split(" "),),
("I wish Java could use case classes".split(" "),),
("Logistic regression models are neat".split(" "),)],
["text"])
# Create a word2vec model
word2vec = Word2Vec(vectorSize=3, minCount=0, inputCol="text", outputCol="result")
model = word2vec.fit(documentDF)
# Transform document to feature vector
result = model.transform(documentDF)
for row in result.collect():
text,vector = row
print("Text:[%s] => \nVector:%s\n" % (", ".join(text),str(vector)))
输出结果如下:
可以看到,文档被转变为了一个3维的特征向量,这些特征向量就可以被应用到相关的机器学习方法中。