7

次の形式の 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 は文字列です。例:

453478692, Apple iPhone 4 8Go

ファイルから TF-IDF を作成して、MLlib の Naive Bayes Classifier に使用できるようにしようとしています。

これまでのところ、Spark for Scala を使用しており、公式ページと Berkley AmpCamp 3および4で見つけたチュートリアルを使用しています。

だから私はファイルを読んでいます:

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)))

しかし、私はここで立ち往生しており、そこからベクターを作成してTFIDFに変換する方法がわかりません。

ありがとう

4

1 に答える 1

8

これを自分で (pyspark を使用して) 行うために、まず、コーパスから 2 つのデータ構造を作成することから始めました。1つ目は、のキー、値の構造です

document_id, [token_ids]

2 番目は、次のような逆インデックスです。

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 をドライバー プログラムに取り込み、結合に使用できるようにすることは、間違っているように思えます。

もちろん、最初にトークン化して、ボキャブラリ内の各一意のトークンから何らかの token_id へのマッピングを作成する必要があります。

誰かがこれを改善できるなら、私は非常に興味があります。

于 2014-09-22T22:32:04.130 に答える