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

Attempting to cluster documents with TF-IDF and KMeans in Spark. What's wrong with this piece of code?

我有一个带有文本字段的 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 甚至更大,寻找"elbow" 值,但运气不好。

谁能指出我正确的方向?

非常感谢!

我会回答我自己的问题(希望这是 SO 的礼节可以接受的),以防有一天对其他人有用。

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

一开始使用 TF-IDF 是个坏主意,因为它抵消了停用词的作用(其目的是将焦点放在文档中的 "uncommonly common" 个术语上)

通过使用 CountVectorizer,我设法更接近按语言进行聚类的目标,CountVectorizer 创建了一个包含最常用术语的词典,并为每个文档计算这些术语。

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