Spark n-gram模型

1、概念

n-gram是一种基于统计语言模型的算法。它的基本思想是将文本里面的内容按照字节进行大小为n的滑动窗口操作,形成了长度是n 的字节片段序列。

每一个字节片段称为gram,对所有gram的出现频度进行统计,并且按照事先设定好的阈值进行过滤,形成关键gram列表,也就是这个文本的向量特征空间,列表中的每一种gram就是一个特征向量维度。

该模型基于马尔科夫假设即:假设在一段文本中,第N个词的出现只与前面n-1个词相关,而与其他任何词都不相关。

基于这样一种假设,可以评估文本中每一个词出现的概率,整句的概率就是各个词出现概率的乘积。

这些概率可以通过直接从语料中统计N个词同时出现的次数得到。常用的二元的Bi-Gram和三元的Tri-Gram.
搜索引擎(Google或者Baidu)、或者输入法的猜想或者提示。你在用百度时,输入一个或几个词,搜索框通常会以下拉菜单的形式给出几个备选,这些备选其实是在猜想你想要搜索的那个词串。

再者,当你用输入法输入一个汉字的时候,输入法通常可以联系出一个完整的词,例如我输入一个“刘”字,通常输入法会提示我是否要输入的是“刘备”。

这其实是以N-Gram模型为基础来实现的。
利用N-Gram计算字符串间距离

模糊匹配的关键在于如何衡量两个长得很像的单词(或字符串)之间的“差异”。这种差异通常又称为“距离”。
这方面的具体算法有很多,例如基于编辑距离的概念,人们设计出了 Smith-Waterman 算法和Needleman-Wunsch 算法,其中后者还是历史上最早的应用动态规划思想设计的算法之一。
现在Smith-Waterman 算法和Needleman-Wunsch 算法在生物信息学领域也有重要应用,研究人员常常用它们来计算两个DNA序列片段之间的“差异”(或称“距离”) 调用函数需要引用lucene的JAR包,我所使用的是lucene-suggest-5.0.0.jar 前面我们所给出的算法计算所得为一个绝对性的距离分值。而Java中所给出的函数在此基础上进行了归一化,也就是说所得之结果是一个介于0~1之间的浮点数,即0的时候表示两个字符串完全不同,而1则表示两个字符串完全相同。 import org.apache.lucene.search.spell.*; public class NGram_distance { public static void main(String[] args) { NGramDistance ng = new NGramDistance(); float score1 = ng.getDistance("Gorbachev", "Gorbechyov"); System.out.println(score1); float score2 = ng.getDistance("girl", "girlfriend"); System.out.println(score2); } }

2、code

package com.home.spark.ml

import org.apache.spark.SparkConf
import org.apache.spark.ml.feature.NGram
import org.apache.spark.sql.SparkSession

/**
  * @Description:
  * 一种特征转换器,将输入的字符串数组转换为n元语法的数组。
  * 输入数组中的空值将被忽略,它将返回一个n-gram数组,其中每个n-gram均由以空格分隔的单词字符串表示。
  * 当输入为空时,将返回一个空数组。 当输入数组的长度小于n(每n-gram的元素数)时,不返回n-gram。
  *
  **/
object Ex_nGram {
  def main(args: Array[String]): Unit = {
    val conf: SparkConf = new SparkConf(true).setMaster("local[2]").setAppName("spark ml")
    val spark = SparkSession.builder().config(conf).getOrCreate()

    val wordDataFrame = spark.createDataFrame(Seq(
      (0, Array("Hi", "I", "heard", "about", "Spark")),
      (1, Array("I", "wish", "Java", "could", "use", "case", "classes")),
      (2, Array("Logistic", "regression", "models", "are", "neat"))
    )).toDF("id", "words")

    val gram = new NGram().setInputCol("words").setOutputCol("nGrams")
      //Default: 2, bigram features
      .setN(2)
    val result = gram.transform(wordDataFrame)
    
    result.show(false)

    spark.stop()
  }
}
posted @ 2020-01-15 15:25  我是属车的  阅读(671)  评论(0编辑  收藏  举报