SparkでHashingTF
を使用して用語頻度を作成しました。各単語に_tf.transform
_を使用して頻度という用語を取得しました。
しかし、結果はこの形式で表示されています。
_[<hashIndexofHashBucketofWord1>,<hashIndexofHashBucketofWord2> ...]
,[termFrequencyofWord1, termFrequencyOfWord2 ....]
_
例えば:
_(1048576,[105,3116],[1.0,2.0])
_
tf.indexOf("Word")
を使用して、ハッシュバケット内のインデックスを取得できます。
しかし、インデックスを使用してWordを取得するにはどうすればよいですか?
まあ、できません。ハッシュは単射ではないため、逆関数はありません。つまり、無限の数のトークンを1つのバケットにマップできるため、実際にどのトークンが存在するかを判断することはできません。
大きなハッシュを使用していて、一意のトークンの数が比較的少ない場合は、バケットからデータセットの可能なトークンへのルックアップテーブルを作成してみてください。これは1対多のマッピングですが、上記の条件が満たされている場合、競合の数は比較的少ないはずです。
可逆変換が必要な場合は、combine Tokenizer
と StringIndexer
を使用して、スパース特徴ベクトルを手動で作成できます。
参照: どのハッシュ関数がSpark HashingTFに使用し、それを複製するにはどうすればよいですか?
編集:
Spark 1.5+(PySpark 1.6+))では、リバーシブル変換を適用して語彙を保存する CountVectorizer
を使用できます。
Python:
from pyspark.ml.feature import CountVectorizer
df = sc.parallelize([
(1, ["foo", "bar"]), (2, ["foo", "foobar", "baz"])
]).toDF(["id", "tokens"])
vectorizer = CountVectorizer(inputCol="tokens", outputCol="features").fit(df)
vectorizer.vocabulary
## ('foo', 'baz', 'bar', 'foobar')
Scala:
import org.Apache.spark.ml.feature.{CountVectorizer, CountVectorizerModel}
val df = sc.parallelize(Seq(
(1, Seq("foo", "bar")), (2, Seq("foo", "foobar", "baz"))
)).toDF("id", "tokens")
val model: CountVectorizerModel = new CountVectorizer()
.setInputCol("tokens")
.setOutputCol("features")
.fit(df)
model.vocabulary
// Array[String] = Array(foo, baz, bar, foobar)
ここで、0番目の位置の要素はインデックス0に対応し、1番目の位置の要素はインデックス1に対応します。