spark中ml机器学习库的朴素贝叶斯模型实现中文文本信息的文类预测

数据预处理

这里写图片描述

原始数据如图所示,我们要提取用户的输入文本信息,即“日本件如何收费”
首先过滤掉其他不含用户输入的文本行
然后以特定字符“含中文”为切割
提取文本信息

中文分词

采用ansj中文分词工具,对预处理后的数据进行分词

建立训练语料

自定义五个类别及其标签:0 运费、1 寄件、2 人工、3 改单、4 催单、5 其他业务类。
从原数据中挑选一部分作为训练语料和测试语料
这里写图片描述

建立模型测试并保存

import org.apache.spark.ml.classification.NaiveBayes
import org.apache.spark.ml.evaluation.MulticlassClassificationEvaluator
import org.apache.spark.ml.feature.{HashingTF, IDF, LabeledPoint, Tokenizer}
import org.apache.spark.ml.linalg.{Vector, Vectors}
import org.apache.spark.sql.Row
import org.apache.spark.{SparkConf, SparkContext}

object shunfeng {

  case class RawDataRecord(label: String, text: String)

    def main(args : Array[String]) {

      val config = new SparkConf().setAppName("createModel").setMaster("local[4]")
      val sc =new  SparkContext(config)
      val sqlContext = new org.apache.spark.sql.SQLContext(sc)
      //开启RDD隐式转换,利用.toDF方法自动将RDD转换成DataFrame;
      import sqlContext.implicits._

      val TrainDf = sc.textFile("E:\\train.txt").map {
        x =>
           val data = x.split("\t")
           RawDataRecord(data(0),data(1))
       }.toDF()
      val TestDf= sc.textFile("E:\\test.txt").map {
        x =>
          val data = x.split("\t")
          RawDataRecord(data(0),data(1))
      }.toDF()
      //tokenizer分解器,把句子划分为词语
      val TrainTokenizer = new Tokenizer().setInputCol("text").setOutputCol("words")
      val TrainWords = TrainTokenizer.transform(TrainDf)
      val TestTokenizer = new Tokenizer().setInputCol("text").setOutputCol("words")
      val TestWords = TestTokenizer.transform(TestDf)
      //特征抽取,利用TF-IDF
      val TrainHashingTF = new HashingTF().setInputCol("words").setOutputCol("rawFeatures").setNumFeatures(5000)
      val TrainData = TrainHashingTF.transform(TrainWords)
      val TestHashingTF = new HashingTF().setInputCol("words").setOutputCol("rawFeatures").setNumFeatures(5000)
      val TestData = TestHashingTF.transform(TestWords)

      val TrainIdf = new IDF().setInputCol("rawFeatures").setOutputCol("features")
      val TrainIdfmodel = TrainIdf.fit(TrainData)
      val TrainForm = TrainIdfmodel.transform(TrainData)
      val TestIdf = new IDF().setInputCol("rawFeatures").setOutputCol("features")
      val TestIdfModel = TestIdf.fit(TestData)
      val TestForm = TestIdfModel.transform(TestData)
      //把数据转换成朴素贝叶斯格式
      val TrainDF = TrainForm.select($"label",$"features").map {
        case Row(label: String, features: Vector) =>
          LabeledPoint(label.toDouble, Vectors.dense(features.toArray))
      }
      val TestDF = TestForm.select($"label",$"features").map {
          case Row(label: String, features: Vector) =>
            LabeledPoint(label.toDouble, Vectors.dense(features.toArray))
        }
      //建立模型
      val model =new NaiveBayes().fit(TrainDF)
      val predictions = model.transform(TestDF)
      predictions.show()
      //评估模型
      val evaluator = new MulticlassClassificationEvaluator()
        .setLabelCol("label")
        .setPredictionCol("prediction")
        .setMetricName("accuracy")
      val accuracy = evaluator.evaluate(predictions)
      println("准确率:"+accuracy)
      //保存模型
      model.write.overwrite().save("model")
    }
}

模型评估:
这里写图片描述
这里写图片描述

使用模型预测

import org.ansj.recognition.impl.StopRecognition
import org.ansj.splitWord.analysis.{DicAnalysis, ToAnalysis}
import org.apache.spark.ml.classification.NaiveBayesModel
import org.apache.spark.ml.feature._
import org.apache.spark.sql.SparkSession
import org.apache.spark.{SparkConf, SparkContext}

object stest {
  case class RawDataRecord(label: String)
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setMaster("local[4]").setAppName("shunfeng")
    val sc = new SparkContext(conf)
    val spark = SparkSession.builder().config(conf).getOrCreate()
    import spark.implicits._
    val frdd = sc.textFile("C:\\Users\\Administrator\\Desktop\\01\\*")
    val filter = new StopRecognition()
    filter.insertStopNatures("w") //过滤掉标点
    val rdd = frdd.filter(_.contains("含中文"))
      .filter(!_.contains("▃▂▁机器人丰小满使用指引▁▂▃"))
      .map(_.split("含中文")(0))
      .map(_.split("\\|")(3))
      .filter(_.length>1)
      .map{x =>
        val temp = ToAnalysis.parse(x.toString)
        RawDataRecord(DicAnalysis.parse(x.toString).recognition(filter).toStringWithOutNature(" "))
      }.toDF()

    val tokenizer = new Tokenizer().setInputCol("label").setOutputCol("words")
    val wordsData = tokenizer.transform(rdd)

    //setNumFeatures的值越大精度越高,开销也越大
    val hashingTF = new HashingTF().setInputCol("words").setOutputCol("rawFeatures").setNumFeatures(5000)
    val PreData = hashingTF.transform(wordsData)

    val idf = new IDF().setInputCol("rawFeatures").setOutputCol("features")
    val idfModel = idf.fit(PreData)
    val PreModel = idfModel.transform(PreData)
    //加载模型
    val model =NaiveBayesModel.load("model")
     model.transform(PreModel).select("words","prediction").show()

  }

}

结果:

这里写图片描述

总结

spark的ml库与mlib在使用上的区别还是挺大的,比如利用了mlib的库的模型就不能使用ml的Vectors,LabeledPoint,必须使用模型对应的数据类型,在导入包的时候尤其要小心。另外,对于分类结果的准确性,这里虽然很高,一部分程度由于源数据的数据种类较少,可识别度比较高,另一方面测试和训练语句较少,重复较多,如果想要提高预测准确度,训练语句很关键,其次就是中文分词工具的使用。

ps:如有不足,欢迎批评指正

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值