【问题标题】:How can I create a TF-IDF for Text Classification using Spark?如何使用 Spark 创建用于文本分类的 TF-IDF?
【发布时间】:2014-08-24 06:11:27
【问题描述】:

我有一个格式如下的 CSV 文件:

product_id1,product_title1
product_id2,product_title2
product_id3,product_title3
product_id4,product_title4
product_id5,product_title5
[...]

product_idX 是整数,product_titleX 是String,例如:

453478692, Apple iPhone 4 8Go

我正在尝试从我的文件创建 TF-IDF,以便我可以将它用于 MLlib 中的朴素贝叶斯分类器。

到目前为止,我正在使用 Spark for Scala,并使用我在官方页面和 Berkley AmpCamp 34 上找到的教程。

所以我正在阅读文件:

val file = sc.textFile("offers.csv")

然后我将它映射到元组RDD[Array[String]]

val tuples = file.map(line => line.split(",")).cache

在我将元组转换成对之后RDD[(Int, String)]

val pairs = tuples.(line => (line(0),line(1)))

但我被困在这里,我不知道如何从中创建 Vector 以将其转换为 TFIDF。

谢谢

【问题讨论】:

  • 如果我能很好地理解您的问题,每个产品都可以出现多次。每个产品的出现次数是您的频率 (TF),我无法理解在您的情况下 IDF 是什么。你能详细说明一下吗?
  • tf-idf 是词频-逆文档频率的缩写,是一种数值统计数据,旨在反映一个词对集合或语料库中的文档的重要性。它通常用作信息检索和文本挖掘中的加权因子。
  • 我不明白的是,在您的示例中,我没有看到 collection 或 corpus 的提及。
  • 我的最后一条评论是 tf-idf 的定义,集合或语料库是一组您想要使用数据挖掘技术的文档。在我的例子中,我们将 CSV 行视为一个文档,集合或语料库是包含这些文档的 CSV 文件。
  • 对不起,我还是不明白。这是我的理解:你想要每个产品的 TF-IDF。每条生产线有一种产品。您可以多次拥有相同的产品。知道这一点,并且根据您的最后评论,一个产品的 IDF 将是包含该产品的行数的倒数。在这种情况下,TF 会是什么?

标签: scala apache-spark apache-spark-mllib tf-idf


【解决方案1】:

为了自己做这件事(使用 pyspark),我首先从语料库中创建了两个数据结构。首先是一个键、值结构的

document_id, [token_ids]

第二个是倒排索引,比如

token_id, [document_ids]

我将分别调用这些语料库和 inv_index。

要获得 tf,我们需要计算每个文档中每个标记的出现次数。所以

from collections import Counter
def wc_per_row(row):
    cnt = Counter()
    for word in row:
        cnt[word] += 1
    return cnt.items() 

tf = corpus.map(lambda (x, y): (x, wc_per_row(y)))

df 只是每个术语的倒排索引的长度。由此我们可以计算出 idf。

df = inv_index.map(lambda (x, y): (x, len(y)))
num_documnents = tf.count()

# At this step you can also apply some filters to make sure to keep
# only terms within a 'good' range of df. 
import math.log10
idf = df.map(lambda (k, v): (k, 1. + log10(num_documents/v))).collect()

现在我们只需要在 term_id 上做一个连接:

def calc_tfidf(tf_tuples, idf_tuples):
    return [(k1, v1 * v2) for (k1, v1) in tf_tuples for
        (k2, v2) in idf_tuples if k1 == k2]

tfidf = tf.map(lambda (k, v): (k, calc_tfidf(v, idf)))

不过,这并不是一个特别高效的解决方案。调用 collect 将 idf 带入驱动程序以便它可用于连接似乎是错误的做法。

当然,它需要首先标记化并创建从词汇表中的每个 uniq 标记到某个 token_id 的映射。

如果有人可以改进这一点,我很感兴趣。

【讨论】:

    猜你喜欢
    • 2020-08-27
    • 2020-03-22
    • 2021-02-06
    • 2017-05-08
    • 2018-10-24
    • 2017-02-27
    • 2019-05-28
    • 2018-05-17
    • 1970-01-01
    相关资源
    最近更新 更多