spark之特征提取

    科技2022-07-12  123

    1、特征处理分类

    特征抽取:从原始数据中抽取特征 特征转换:特征的维度、特征的转化、特征的修改 特征选取:从大规模特征集中选取一个子集

    2、特征提取

    2.1、TF-IDF 

    词频-逆向文件频率;词频TF(t,d)是词语t在文档d中出现的次数。文件频率DF(t,D)是包含词语的文档的个数。

    tf=|t|/|d|

    tf-idf=tf*idf

    公式中使用log函数,当词出现在所有文档中时,它的IDF值变为0。加1是为了避免分母为0的情况。

    Spark.mllib 中实现词频率统计使用特征hash的方式,原始特征通过hash函数,映射到一个索引值。后面只需要统计这些索引值的频率,就可以知道对应词的频率。这种方式避免设计一个全局1对1的词到索引的映射,这个映射在映射大量语料库时需要花费更长的时间。但需要注意,通过hash的方式可能会映射到同一个值的情况,即不同的原始特征通过Hash映射后是同一个值。为了降低这种情况出现的概率,我们只能对特征向量升维。i.e., 提高hash表的桶数,默认特征维度是 2^20 = 1,048,576.

    #tf-idf特征生成 from pyspark.ml.feature import HashingTF,IDF,Tokenizer sentenceData = spark.createDataFrame([(0, "the spark quick"),(0, "the hadoop test"),(1, "the saprk diff")]).toDF("label", "sentence") tokenizer = Tokenizer(inputCol="sentence", outputCol="words") wordsData = tokenizer.transform(sentenceData) #将词hash成特征向量 hashTF = HashingTF(inputCol="words", outputCol="rawFeatures", numFeatures=6) featurizedData = hashTF.transform(wordsData) featurizedData.show() #最后,使用IDF来对单纯的词频特征向量进行修正,使其更能体现不同词汇对文本的区别能力,IDF是一个Estimator,调用fit()方法并将词频向量传入,即产生一个IDFModel。 idf = IDF(inputCol="rawFeatures", outputCol="features") idfModel = idf.fit(featurizedData) rescaledData = idfModel.transform(featurizedData) rescaledData.show() rescaledData.select("label", "features").show()

    结果:

     

    2.2、Word2Vec

    Word2Vec 是一种著名的 词嵌入(Word Embedding) 方法,它可以计算每个单词在其给定语料库环境下的 分布式词向量(Distributed Representation,亦直接被称为词向量)。词向量表示可以在一定程度上刻画每个单词的语义。

    ​ Word2vec是一个Estimator,它采用一系列代表文档的词语来训练word2vecmodel。该模型将每个词语映射到一个固定大小的向量。word2vecmodel使用文档中每个词语的平均数来将文档转换为向量,然后这个向量可以作为预测的特征,来计算文档相似度计算等等。

    在ml库中,使用的是skip-gram方式,优化的目标函数如下:

    softmax直接计算:

    skip-gram采取了层次softmax来进行计算,计算复杂度从O(V)降到了O(log(V))

    from pyspark.ml.feature import Word2Vec documentDF = spark.createDataFrame([ ("Hi I heard about Spark".split(" "), ), ("I wish Java could use case classes".split(" "), ), ("Logistic regression models are neat".split(" "), ) ], ["text"]) word2Vec = Word2Vec(vectorSize=3, minCount=0, inputCol="text", outputCol="result") model = word2Vec.fit(documentDF) result = model.transform(documentDF) for row in result.collect(): print(row) text, vector = row print("Text: [%s] => \nVector: %s\n" % (", ".join(text), str(vector))) #寻找heard的同义词 model.findSynonyms("heard", 2).show() #显示词向量 model.getVectors().show() #句向量 df_vec=model.transform(documentDF) df_vec.show()

    heard相似词查询结果:

    句向量结果:

    2.3、CountVectorizer

    CountVectorizer旨在通过计数来将一个文档转换为向量。当不存在先验字典时,Countvectorizer作为Estimator提取词汇进行训练,并生成一个CountVectorizerModel用于存储相应的词汇向量空间。该模型产生文档关于词语的稀疏表示,其表示可以传递给其他算法,例如LDA。

    from pyspark.ml.feature import CountVectorizer df = spark.createDataFrame([ (0, "a b c".split(" ")), (1, "a b b c a".split(" ")) ], ["id", "words"]) # fit a CountVectorizerModel from the corpus. cv = CountVectorizer(inputCol="words", outputCol="features", vocabSize=3, minDF=2.0) model = cv.fit(df) result = model.transform(df) result.show()

    结果 :

    3、特征变换

    Spark ML包中提供了几个相关的转换器,StringIndexer、IndexToString、OneHotEncoder、VectorIndexer

    3.1、StringIndexer

    StringIndexer转换器可以把一列类别型的特征(或标签)进行编码,使其数值化,索引的范围从0开始,该过程可以使得相应的特征索引化。索引构建的顺序为标签的频率,优先编码频率较大的标签,所以出现频率最高的标签为0号。  

    3.2、IndexToString

    与StringIndexer相对应,IndexToString的作用是把标签索引的一列重新映射回原有的字符型标签。

    其主要使用场景一般都是和StringIndexer配合,先用StringIndexer将标签转化成标签索引,进行模型训练,然后在预测标签的时候再把标签索引转化成原有的字符标签。当然,你也可以另外定义其他的标签。

    3.3、OneHotEncoder

    ​独热编码(One-Hot Encoding) 是指把一列类别性特征(或称名词性特征,nominal/categorical features)映射成一系列的二元连续特征的过程,原有的类别性特征有几种可能取值,这一特征就会被映射成几个二元连续特征,每一个特征代表一种取值,若该样本表现出该特征,则取1,否则取0。

    3.4、VectorIndexer

    之前介绍的StringIndexer是针对单个类别型特征进行转换,倘若所有特征都已经被组织在一个向量中,又想对其中某些单个分量进行处理时,Spark ML提供了VectorIndexer类来解决向量数据集中的类别性特征转换。

    3.5、实例

    #特征变换 #StringIndexer:把一列类别型的特征转化为数字编码 from pyspark.ml.feature import StringIndexer df = spark.createDataFrame( [(0, "a"), (1, "b"), (2, "c"), (3, "a"), (4, "a"), (5, "c")], ["id", "category"]) indexer = StringIndexer(inputCol="category", outputCol="categoryIndex") model = indexer.fit(df) indexed = model.transform(df) indexed.show() #IndexToString还原标签索引为字符型标签 from pyspark.ml.feature import IndexToString converter = IndexToString(inputCol="categoryIndex", outputCol="originalCategory") converted = converter.transform(indexed) converted.show() #OneHotEncoder:指把一列类别性特征(或称名词性特征,nominal/categorical features)映射成一系列的二元连续特征 from pyspark.ml.feature import OneHotEncoder, StringIndexer #独热编码;setDropLast(False);不设置这个出现频率最低的将不会占用1位2进制位 encoder = OneHotEncoder(inputCol="categoryIndex", outputCol="categoryVec").setDropLast(False) encoded = encoder.transform(indexed) encoded.show() #之前介绍的StringIndexer是针对单个类别型特征进行转换,倘若所有特征都已经被组织在一个向量中,又想对其中某些单个分量进行处理时,Spark ML提供了VectorIndexer类来解决向量数据集中的类别性特征转换。 from pyspark.ml.feature import VectorIndexer from pyspark.ml.linalg import Vectors df = spark.createDataFrame([(Vectors.dense([-1.0, 0.0]),), (Vectors.dense([0.0, 1.0]),), (Vectors.dense([0.0, 2.0]),), (Vectors.dense([1.0, 2.0]),)], ["a"]) vectorIndexer = VectorIndexer(maxCategories=2, inputCol="a", outputCol="indexed") model = vectorIndexer.fit(df) vectorIndexed=model.transform(df) print(model.categoryMaps) vectorIndexed.show()

    4、特征选取

    特征选择(Feature Selection)指的是在特征向量中选择出那些“优秀”的特征,组成新的、更“精简”的特征向量的过程。它在高维数据分析中十分常用,可以剔除掉“冗余”和“无关”的特征,提升学习器的性能。

    特征选择方法和分类方法一样,也主要分为有监督(Supervised)和无监督(Unsupervised)两种,卡方选择则是统计学上常用的一种有监督特征选择方法,它通过对特征和真实标签之间进行卡方检验,来判断该特征和真实标签的关联程度,进而确定是否对其进行选择。

    卡方选择:

    https://blog.csdn.net/shuzfan/article/details/52993427

    https://www.cnblogs.com/massquantity/p/10486904.html

    卡方选择则是统计学上常用的一种有监督特征选择方法,它通过对特征和真实标签之间进行卡方检验,来判断该特征和真实标签的关联程度,进而确定是否对其进行选择。

    from pyspark.ml.feature import ChiSqSelector from pyspark.ml.linalg import Vectors df = spark.createDataFrame([ (7, Vectors.dense([0.0, 0.0, 18.0, 1.0]), 1.0,), (8, Vectors.dense([0.0, 1.0, 12.0, 0.0]), 0.0,), (9, Vectors.dense([1.0, 0.0, 15.0, 0.1]), 0.0,)], ["id", "features", "clicked"]) selector = ChiSqSelector(numTopFeatures=1, featuresCol="features", outputCol="selectedFeatures", labelCol="clicked") result = selector.fit(df).transform(df) result.show()

    结果:

    Processed: 0.011, SQL: 8