【问题标题】:PySpark vs sklearn TFIDFPySpark vs sklearn TFIDF
【发布时间】:2023-03-09 22:00:02
【问题描述】:

我是 PySpark 的新手。我在玩 tfidf。只是想检查他们是否给出相同的结果。但它们并不相同。这就是我所做的。

# create the PySpark dataframe
sentenceData = sqlContext.createDataFrame((
  (0.0, "Hi I heard about Spark"),
  (0.0, "I wish Java could use case classes"),
  (1.0, "Logistic regression models are neat")
)).toDF("label", "sentence")

# tokenize
tokenizer = Tokenizer().setInputCol("sentence").setOutputCol("words")
wordsData = tokenizer.transform(sentenceData)

# vectorize
vectorizer = CountVectorizer(inputCol='words', outputCol='vectorizer').fit(wordsData)
wordsData = vectorizer.transform(wordsData)

# calculate scores
idf = IDF(inputCol="vectorizer", outputCol="tfidf_features")
idf_model = idf.fit(wordsData)
wordsData = idf_model.transform(wordsData)

# dense the current response variable
def to_dense(in_vec):
    return DenseVector(in_vec.toArray())
to_dense_udf = udf(lambda x: to_dense(x), VectorUDT())

# create dense vector
wordsData = wordsData.withColumn("tfidf_features_dense", to_dense_udf('tfidf_features'))

我将 PySpark df 转换为 pandas

wordsData_pandas = wordsData.toPandas()

然后,只需使用 sklearn 的 tfidf 计算如下

def dummy_fun(doc):
    return doc

# create sklearn tfidf
tfidf = TfidfVectorizer(
    analyzer='word',
    tokenizer=dummy_fun,
    preprocessor=dummy_fun,
    token_pattern=None)  

# transform and get idf scores
feature_matrix = tfidf.fit_transform(wordsData_pandas.words)

# create sklearn dtm matrix
sklearn_tfifdf = pd.DataFrame(feature_matrix.toarray(), columns=tfidf.get_feature_names())

# create PySpark dtm matrix
spark_tfidf = pd.DataFrame([np.array(i) for i in wordsData_pandas.tfidf_features_dense], columns=vectorizer.vocabulary)

但不幸的是,我为 PySpark 得到了这个

<table border="1" class="dataframe">  <thead>    <tr style="text-align: right;">      <th></th>      <th>i</th>      <th>are</th>      <th>logistic</th>      <th>case</th>      <th>spark</th>      <th>hi</th>      <th>about</th>      <th>neat</th>      <th>could</th>      <th>regression</th>      <th>wish</th>      <th>use</th>      <th>heard</th>      <th>classes</th>      <th>java</th>      <th>models</th>    </tr>  </thead>  <tbody>    <tr>      <th>0</th>      <td>0.287682</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.693147</td>      <td>0.693147</td>      <td>0.693147</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.693147</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.000000</td>    </tr>    <tr>      <th>1</th>      <td>0.287682</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.693147</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.693147</td>      <td>0.000000</td>      <td>0.693147</td>      <td>0.693147</td>      <td>0.000000</td>      <td>0.693147</td>      <td>0.693147</td>      <td>0.000000</td>    </tr>    <tr>      <th>2</th>      <td>0.000000</td>      <td>0.693147</td>      <td>0.693147</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.693147</td>      <td>0.000000</td>      <td>0.693147</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.693147</td>    </tr>  </tbody></table>

这对于 sklearn,

<table border="1" class="dataframe">  <thead>    <tr style="text-align: right;">      <th></th>      <th>i</th>      <th>are</th>      <th>logistic</th>      <th>case</th>      <th>spark</th>      <th>hi</th>      <th>about</th>      <th>neat</th>      <th>could</th>      <th>regression</th>      <th>wish</th>      <th>use</th>      <th>heard</th>      <th>classes</th>      <th>java</th>      <th>models</th>    </tr>  </thead>  <tbody>    <tr>      <th>0</th>      <td>0.355432</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.467351</td>      <td>0.467351</td>      <td>0.467351</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.467351</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.000000</td>    </tr>    <tr>      <th>1</th>      <td>0.296520</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.389888</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.389888</td>      <td>0.000000</td>      <td>0.389888</td>      <td>0.389888</td>      <td>0.000000</td>      <td>0.389888</td>      <td>0.389888</td>      <td>0.000000</td>    </tr>    <tr>      <th>2</th>      <td>0.000000</td>      <td>0.447214</td>      <td>0.447214</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.447214</td>      <td>0.000000</td>      <td>0.447214</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.000000</td>      <td>0.447214</td>    </tr>  </tbody></table>

我确实尝试了use_idfsmooth_idf 参数。但似乎没有一个使两者相同。我错过了什么?任何帮助表示赞赏。提前致谢。

【问题讨论】:

    标签: python apache-spark scikit-learn pyspark


    【解决方案1】:

    这是因为两者的 IDF 计算方式略有不同。

    来自sklearn的documentation

    与 pyspark 的 documentation 比较:

    除了在 IDF 中添加 1 之外,sklearn TF-IDF 使用 pyspark 不使用的 l2 范数

    TfidfTransformer(norm='l2', use_idf=True, smooth_idf=True, sublinear_tf=False)
    

    【讨论】:

    • @HakunaMaData,如果我们在 Sklearn 中将 norm 设置为 None,我们可以使用 sklearn 得到相同的结果。
    【解决方案2】:

    tfidf 分数的 Python 和 Pyspark 实现是相同的。请参阅相同的 Sklearn 文档,但在下一行,

    它们之间的关键区别在于,Sklearn 默认使用l2 规范,而 Pyspark 则不然。如果我们将 norm 设置为 None,我们也会在 sklearn 中得到相同的结果。

    from sklearn.feature_extraction.text import TfidfVectorizer
    import numpy as np
    import pandas as pd
    
    corpus = ["I heard about Spark","I wish Java could use case classes","Logistic regression models are neat"]
    corpus = [sent.lower().split() for sent in corpus]
    
    def dummy_fun(doc):
        return doc
    
    tfidfVectorizer=TfidfVectorizer(norm=None,analyzer='word',
                                    tokenizer=dummy_fun,preprocessor=dummy_fun,token_pattern=None)
    
    tf=tfidfVectorizer.fit_transform(corpus)
    tf_df=pd.DataFrame(tf.toarray(),columns= tfidfVectorizer.get_feature_names())
    tf_df
    

    请参阅我的回答 here 以了解 norm 如何与 tf-idf 矢量化器一起使用。

    【讨论】:

      猜你喜欢
      • 2019-09-15
      • 2016-11-12
      • 2019-08-21
      • 2018-07-02
      • 1970-01-01
      • 2017-02-27
      • 2017-03-27
      • 2018-12-27
      • 2023-04-04
      相关资源
      最近更新 更多