尝试在Spark中使用TF-IDF和KMeans对文档进行集群。这段代码有什么问题?

时间:2017-03-24 14:47:07

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

我有一个带有文本字段的CSV文件,有2种语言(法语和英语)。我正在尝试执行聚类分析,并且由于语言的不同,有些期望将文本分组为2个聚类。

我提出了以下代码,但这些代码无法正常工作:

import org.apache.spark.sql.SQLContext
import org.apache.spark.sql.types.{StructType, StructField, StringType}
import org.apache.spark.ml.feature.{HashingTF, IDF, Tokenizer}
import org.apache.spark.ml.clustering.KMeans

val sqlContext = new SQLContext(sc)

val customSchema = StructType(Array(
    StructField("id_suivi", StringType, true),
    StructField("id_ticket", StringType, true),
    StructField("id_affectation", StringType, true),
    StructField("id_contact", StringType, true),
    StructField("d_date", StringType, true),
    StructField("n_duree_passe", StringType, true),
    StructField("isPublic", StringType, true),
    StructField("Ticket_Request_Id", StringType, true),
    StructField("IsDoneInHNO", StringType, true),
    StructField("commments", StringType, true),
    StructField("reponse", StringType, true)))

val tokenizer = new Tokenizer().setInputCol("reponse").setOutputCol("words")
val hashingTF = new HashingTF().setInputCol("words").setOutputCol("rawFeatures").setNumFeatures(32768)
val idf = new IDF().setInputCol("rawFeatures").setOutputCol("features")

val df = sqlContext.read.format("com.databricks.spark.csv").
    option("header", "true").
    option("delimiter", ";").
    schema(customSchema).
    load("C:/noSave/tmp/22/tickets1.csv").
    select("id_suivi", "reponse")

val tokenizedDF = tokenizer.transform(df)
val hashedDF = hashingTF.transform(tokenizedDF).cache()

val idfModel = idf.fit(hashedDF)

val rescaledDF = idfModel.transform(hashedDF).cache()

val kmeans = new KMeans().setK(2).setSeed(1L).setFeaturesCol("features")
val model = kmeans.fit(rescaledDF)

val clusteredDF = model.transform(rescaledDF)

我相信这段代码是正确的,或者至少我看不出错误在哪里。然而,某些事情确实是错误的,因为当我计算错误时,它真的很大:

scala> model.computeCost(rescaledDF)
res0: Double = 3.1555983509935196E7

我也为K尝试了不同的值(我认为2是一个很好的值,因为我的文本是2种语言(法语,英语)),例如10,100甚至更大,寻找“肘“的价值,但没有运气。

有人能指出我正确的方向吗?

非常感谢提前!

1 个答案:

答案 0 :(得分:2)

我会回答我自己的问题(希望这可以被SO的礼仪所接受),以防有一天对别人有用。

区分这两种语言的一种更简单的方法是考虑使用停用词(即:每种语言中常见的词)。

首先使用TF-IDF是一个坏主意,因为它会使停用词的贡献无效(其目的是将重点放在文档中“非常常见”的术语上)

我设法通过使用CountVectorizer更接近我的语言聚类目标,它创建了一个最常用术语的字典并计算每个文档的字典。

最常见的术语是停用词,我们最终通过使用停用词来对文档进行聚类,停用词在两种语言中都是不同的集合,因此按语言进行聚类。