zoukankan      html  css  js  c++  java
  • 基于naive bayes文本分类的spark实现

    文本分类有很多种方法,朴素贝叶斯应该算是里面最容易的一种了吧。这篇文章简单介绍朴素贝叶斯的原理,然后是spark上的实现方法。

    1,问题描述

    现实中可能会一些问题,比如一个邮件是不是垃圾邮件?一个新闻是属于社会类还是科技类还是娱乐类?这些问题都可以抽象成:给定一些已经分类好的样本集合{(di,yi)|di是文本,yi是类别},来了一个新的文档dx,那么它该被分为哪类?

    2,解决思路

    解决一个机器学习问题的思路一般是:构建样本->提取特征->选择、训练模型->模型评估。对于文本分类问题呢,也可以按照这个思路。

    (1)提取特征

    要处理的对象是文本,我们需要将文本表示成可量化、可计算的形式。这里用一种非常简单的One-hot Representation方法。如果词典有|V|个单词的话,每个文章会被生成一个|V|维的向量vec。对于每一个出现在文档中的单词wi,vec[i]都会被赋予大于0的某个值ci,其它没有出现在文档中的词,都会被赋予0。ci可以有多种赋值方法,常见的有01,频率,tf-idf值等。如果vec是个二值向量,也就是单词出现的位置为0,不出现的位置为1,这时叫做伯努利模型。如果ci是i位置单词出现的频率,那么这时就是多项式模型,tf-idf算是一种加权过后的频率。下面是具体的计算方式:

    1)多项式模型

    p(c) = 类c下单词出现的总次数/整个训练样本的单词总数
    p(tk|c) = 单词tk在类c的文档中出现的总次数+1/类c下单词总数+|V| 
    |V|是单词表的数量,这是一种平滑手段

    2)伯努利模型

    p(c) = 类c下文件总数/整个训练样本的文件总数
    p(tk|c) = (类c下包含单词tk的文件数+1)/类c文件数+2 

    资料[1]里面总结了很多特征选择的方法,感兴趣的话可以去阅读。

    (2)建立模型

    模型真的很简单,用贝叶斯概率公式:( P(y_j|d_i)=frac{P(y_j)P(d_i|y_j)}{P(d_i)} ),在类别y1,y2...yn上分别算一下,取此概率最大的类别。之所以叫朴素贝叶斯,是因为假设特征之间是相互独立的,所以(P(d_i|y_j)=P(w_1|y_j)*P(w_2|y_j)*...*P(w_n|y_j))。当然了,一篇文章词之间肯定不是独立的,但是没关系,朴素贝叶斯模型也可以用。

    朴素贝叶斯模型总结一下:

    1)它是一种线性模型,取对之后就变成加和了嘛

    2)假设特征之间相互独立

    3,spark上的实现

    import org.apache.spark.ml.classification.NaiveBayes
    import org.apache.spark.{ml, SparkContext, SparkConf}
    import org.apache.spark.ml.{PipelineModel, Pipeline}
    import org.apache.spark.ml.classification.{NaiveBayesModel, NaiveBayes}
    import org.apache.spark.ml.evaluation.MulticlassClassificationEvaluator
    import org.apache.spark.ml.feature._
    import org.apache.spark.mllib.linalg.{Vectors, Vector}
    import org.apache.spark.sql.{DataFrame, SaveMode, Row}
    import org.apache.spark.sql.functions._
    import org.apache.spark.sql.hive.HiveContext
    
    object NB {
      def bayesClassifierTest(dataSeg:DataFrame,sc:SparkContext,hiveCont:HiveContext) {
        import hiveCont.implicits._
    
        val labelIndexer = new StringIndexer()
          .setInputCol("new_final_type")
          .setOutputCol("indexedLabel")
          .fit(dataSeg)
        //构建特征
        val regexTokenizer = new RegexTokenizer()
          .setInputCol("food_name_seg")
          .setOutputCol("words")
          .setPattern(",")
        val hashingTF = new HashingTF()
          .setInputCol(regexTokenizer.getOutputCol)
          .setOutputCol("features")
    
        //分类器
        val nb = new ml.classification.NaiveBayes()
          .setLabelCol(labelIndexer.getOutputCol)
          .setFeaturesCol(hashingTF.getOutputCol)
    
        val labelConverter = new IndexToString()
          .setInputCol("prediction")
          .setOutputCol("predictedLabel")
          .setLabels(labelIndexer.labels)
    
        val splits = dataSeg.randomSplit(Array(0.7, 0.3), seed = 11L)
        val dataTraining = splits(0)
        val dataTest = splits(1)
    
        //训练模型
        val pipeline = new Pipeline().setStages(Array(labelIndexer,regexTokenizer,hashingTF,nb,labelConverter))
        val model = pipeline.fit(dataTraining)
    
        //预测数据
        val predictionResultDF = model.transform(dataTest)
    
    
        //计算准确率
        val evaluator = new MulticlassClassificationEvaluator()
          .setLabelCol("indexedLabel")
          .setPredictionCol("prediction")
          .setMetricName("precision")
    
        val predictionAccuracy = evaluator.evaluate(predictionResultDF)
        println("Testing Error = " + (1.0 - predictionAccuracy))
      }
    }
    

    基于朴素贝叶斯的文本分类到此为止,以后会接着探索其它的文本分类模型。

    这里是一些非常好的学习文本分类的资料:

    [1]文本分类相关综述性质的中文文章

    上篇:http://www.infoq.com/cn/articles/machine-learning-automatic-classification-of-text-data

    下篇:http://www.infoq.com/cn/articles/machine-learning-automatic-classification-of-text-data-part2?utm_source=infoq&utm_medium=related_content_link&utm_campaign=relatedContent_articles_clk

    [2]一篇文章彻底理解朴素贝叶斯

    http://sebastianraschka.com/Articles/2014_naive_bayes_1.html

    [3]spark关于naive bayes的文档

    http://spark.apache.org/docs/latest/mllib-naive-bayes.html,这是mlilib的,上文的代码用的是ml里面的。

    spark上naive bayes的模型可以调节的参数不多,一个是模型的选择,是多项式模型还是伯努利模型,一个是additive smooth的平滑参数,如果看api的话,还会一发现还可以手动设置后验概率输出到类别的阈值。

  • 相关阅读:
    Struts2整合Spring
    关于碰撞检测的相关信息
    直角三角形
    XNA 3.0初步——自定义游戏循环时间
    XNA 3.0初步——将你的XNA 3.0游戏部署到Zune
    XNA 3.0初步——开始第一个XNA 3.0项目
    创建场景和赛道——概览
    XNA 3.0初步——将你的XNA 3.0游戏部署到另一台PC
    创建场景和赛道——场景绘制
    创建场景和赛道——游戏比较
  • 原文地址:https://www.cnblogs.com/naniJser/p/5763933.html
Copyright © 2011-2022 走看看