I am currently trying to understand what the example code provided as part of Spark's TF-IDF implementation is doing.
Given the example code block (taken from Spark's Github repository)
val sentenceData = sess.createDataFrame(Seq(
(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")
val tokenizer = new Tokenizer().setInputCol("sentence").setOutputCol("words")
val wordsData = tokenizer.transform(sentenceData)
wordsData.show(false)
val hashingTF = new HashingTF()
.setInputCol("words").setOutputCol("rawFeatures").setNumFeatures(20)
val featurizedData = hashingTF.transform(wordsData)
val idf = new IDF().setInputCol("rawFeatures").setOutputCol("features")
val idfModel = idf.fit(featurizedData)
featurizedData.show(false)
val rescaledData = idfModel.transform(featurizedData)
rescaledData.select("label", "features").show(false)
And the output for wordsData
:
+-----+-----------------------------------+------------------------------------------+
|label|sentence |words |
+-----+-----------------------------------+------------------------------------------+
|0.0 |Hi I heard about Spark |[hi, i, heard, about, spark] |
|0.0 |I wish Java could use case classes |[i, wish, java, could, use, case, classes]|
|1.0 |Logistic regression models are neat|[logistic, regression, models, are, neat] |
+-----+-----------------------------------+------------------------------------------+
And the output for featurizedData
:
+-----+-----------------------------------+------------------------------------------+-----------------------------------------+
|label|sentence |words |rawFeatures |
+-----+-----------------------------------+------------------------------------------+-----------------------------------------+
|0.0 |Hi I heard about Spark |[hi, i, heard, about, spark] |(20,[0,5,9,17],[1.0,1.0,1.0,2.0]) |
|0.0 |I wish Java could use case classes |[i, wish, java, could, use, case, classes]|(20,[2,7,9,13,15],[1.0,1.0,3.0,1.0,1.0]) |
|1.0 |Logistic regression models are neat|[logistic, regression, models, are, neat] |(20,[4,6,13,15,18],[1.0,1.0,1.0,1.0,1.0])|
+-----+-----------------------------------+------------------------------------------+-----------------------------------------+
And the output for rescaledData
:
+-----+----------------------------------------------------------------------------------------------------------------------+
|label|features |
+-----+----------------------------------------------------------------------------------------------------------------------+
|0.0 |(20,[0,5,9,17],[0.6931471805599453,0.6931471805599453,0.28768207245178085,1.3862943611198906]) |
|0.0 |(20,[2,7,9,13,15],[0.6931471805599453,0.6931471805599453,0.8630462173553426,0.28768207245178085,0.28768207245178085]) |
|1.0 |(20,[4,6,13,15,18],[0.6931471805599453,0.6931471805599453,0.28768207245178085,0.28768207245178085,0.6931471805599453])|
+-----+----------------------------------------------------------------------------------------------------------------------+
Why was 20
chosen as the number of features? And what do we mean by feature in this particular case?
What is the meaning of the first row value of column rawFeatures
of featurizedData
?
(20,[0,5,9,17],[1.0,1.0,1.0,2.0])
From plain eyesight, I can see that 20 has been appended from the number of features parameter, but I'm struggling to find the meaning of [0,5,9,17]
and [1.0,1.0,1.0,2.0]
.
rescaledData
seems to imply that some sort of scaling has been applied to the rawFeatures
column on featurizedData
, so I think I'm clear about that.
What conclusions and correlations can I establish between the vector pairs I'm receiving in the resulting dataframes from IDF and the words that were input?
I have tried to run a few example word sets from other websites with tutorials, but the resulting numbers they get in R or Python are totally different from what I'm seeing in Spark.
I ask this question since I am trying to understand this data science topic and overcome my ignorance.
Any help is appreciated!