如何在 Spark 中创建一组 ngram?
Posted
技术标签:
【中文标题】如何在 Spark 中创建一组 ngram?【英文标题】:How do I create a set of ngrams in Spark? 【发布时间】:2018-01-26 12:07:20 【问题描述】:我正在使用 Scala 从 Spark 2.2 数据帧列中提取 Ngram,因此(本例中为三元组):
val ngram = new NGram().setN(3).setInputCol("incol").setOutputCol("outcol")
如何创建包含所有 1 到 5 克的输出列?所以它可能是这样的:
val ngram = new NGram().setN(1:5).setInputCol("incol").setOutputCol("outcol")
但这不起作用。 我可以遍历 N 并为 N 的每个值创建新的数据帧,但这似乎效率低下。谁能指出我正确的方向,因为我的 Scala 是绳索的?
【问题讨论】:
【参考方案1】:如果您想将这些组合成向量,您可以将Python answer 重写为zero323。
import org.apache.spark.ml.feature._
import org.apache.spark.ml.Pipeline
def buildNgrams(inputCol: String = "tokens",
outputCol: String = "features", n: Int = 3) =
val ngrams = (1 to n).map(i =>
new NGram().setN(i)
.setInputCol(inputCol).setOutputCol(s"$i_grams")
)
val vectorizers = (1 to n).map(i =>
new CountVectorizer()
.setInputCol(s"$i_grams")
.setOutputCol(s"$i_counts")
)
val assembler = new VectorAssembler()
.setInputCols(vectorizers.map(_.getOutputCol).toArray)
.setOutputCol(outputCol)
new Pipeline().setStages((ngrams ++ vectorizers :+ assembler).toArray)
val df = Seq((1, Seq("a", "b", "c", "d"))).toDF("id", "tokens")
结果
buildNgrams().fit(df).transform(df).show(1, false)
// +---+------------+------------+---------------+--------------+-------------------------------+-------------------------+-------------------+-------------------------------------+
// |id |tokens |1_grams |2_grams |3_grams |1_counts |2_counts |3_counts |features |
// +---+------------+------------+---------------+--------------+-------------------------------+-------------------------+-------------------+-------------------------------------+
// |1 |[a, b, c, d]|[a, b, c, d]|[a b, b c, c d]|[a b c, b c d]|(4,[0,1,2,3],[1.0,1.0,1.0,1.0])|(3,[0,1,2],[1.0,1.0,1.0])|(2,[0,1],[1.0,1.0])|[1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0]|
// +---+------------+------------+---------------+--------------+-------------------------------+-------------------------+-------------------+-------------------------------------+
使用 UDF 可能会更简单:
val ngram = udf((xs: Seq[String], n: Int) =>
(1 to n).map(i => xs.sliding(i).filter(_.size == i).map(_.mkString(" "))).flatten)
spark.udf.register("ngram", ngram)
val ngramer = new SQLTransformer().setStatement(
"""SELECT *, ngram(tokens, 3) AS ngrams FROM __THIS__"""
)
ngramer.transform(df).show(false)
// +---+------------+----------------------------------+
// |id |tokens |ngrams |
// +---+------------+----------------------------------+
// |1 |[a, b, c, d]|[a, b, c, d, ab, bc, cd, abc, bcd]|
// +---+------------+----------------------------------+
【讨论】:
_.mkString(" ")
.
对不起,错了。应该是sliding
而不是grouped
。以上是关于如何在 Spark 中创建一组 ngram?的主要内容,如果未能解决你的问题,请参考以下文章