朴素贝叶斯算法(快速入门)

1、NaiveBayes简介及原理

(1)简介

常用于分类与预测的问题,且都是概率预测

比如邮箱中每天收到大量的邮件,如何预测哪些邮件是垃圾邮件?
比如一个电商网站,有大量的客户对店家或商品的评价,如何预测是好评还是中评、差评?

(2)数学原理

贝叶斯定理:P(A|B)=P(B|A)P(A)/P(B)(详询度娘)

意义:如果求 P( A | B) 不好直接计算,则可以通过贝叶斯定理转换成计算P( B | A)。
即:求一个事物属于那种类别的概率不好求,转而通过求 经验类别样本中该事物各特征出现的概率。
在这里插入图片描述

2、入门案例

(1)经验样本数据
name,job,income,age,sex,label
张飞,老师,,青年,,出轨
赵云,老师,,中年,,出轨
韩信,老师,,青年,,没出
花满楼,老师,,老年,,出轨
碧瑶,老师,,青年,,没出
廉颇,程序员,,青年,,没出
安琪拉,程序员,,青年,,出轨
刘婵,程序员,,中年,,没出
白起,程序员,,中年,,没出
任我行,程序员,,老年,,出轨
郭靖,公务员,,老年,,没出
黄蓉,公务员,,老年,,没出
段正淳,公务员,,中年,,出轨
段誉,公务员,,中年,,没出
虚竹,公务员,,青年,,出轨
(2)需求

有3个人特征如下,问他们将来是否会出轨?

name,job,income,age,sex
曹操,老师,,青年,女
小乔,程序员,,中年,女
吕布,公务员,,青年,

3、思路详解

和 AI 处理是一样的阶段:

(1)数据预处理(数据准备/特征工程)

根据预处理后的下游不同,数据预处理可能是批处理也有可能是流处理,计算类型和下游一致。

(2)模型训练

目前而言 AI 训练阶段基本上是批计算(离线训练)产生静态模型(Static Model)的过程。因为目前绝大多数的模型是从大量的训练样本中找到特征和标签之间的统计相关性(Correlation),这些统计相关性通常不会突然变化,因此在一批样本上训练出的数据在另一批具有相同的特征分布的样本上依然适用。

(3)推理预测

推理预测环节的环境和计算类型比较丰富,既有批处理(离线预测)又有流处理。流式预测又大致可以分为在线 (Online) 预测和近线 (Nearline) 预测。在线预测通常处于用户访问的关键链路(Critical Path 中),因此对 latency 的要求极高,比如毫秒级。而近线预测要求略低一些,通常在亚秒级到秒级。

4、代码开干

(1)数据预处理 - 模型训练输出
package cn.ianlou.bayes

import org.apache.log4j.{Level, Logger}
import org.apache.spark.ml.classification.{NaiveBayes, NaiveBayesModel}
import org.apache.spark.ml.linalg.Vectors
import org.apache.spark.sql.{DataFrame, SparkSession}
import scala.collection.mutable

/**
 * @date: 2020/2/21 14:28
 * @site: www.ianlou.cn
 * @author: lekko 六水
 * @qq: 496208110
 * @description: 使用朴素贝叶斯算法,预测人物出轨的几率
 */
object BayesModuleTrainer {
  def main(args: Array[String]): Unit = {
    Logger.getLogger("org.apache.spark").setLevel(Level.WARN)

    val spark: SparkSession = SparkSession
      .builder()
      .appName(this.getClass.getSimpleName)
      .master("local[*]")
      .getOrCreate()

    // 1、读取经验样本数据
    val sampleDF: DataFrame = spark.read
      .option("header", true)
      .csv("userProfile/data/bayes/chugui/sample/sample.csv")


    // 2、加工样本特征
    
    // ① 特征数值化 -> SparkMllib中的算法,需要输入的特征值是double类型
    val sample1: DataFrame = sampleDF.selectExpr(
      "cast(case job when '老师' then 1.0 when '程序员' then 2.0 else 3.0 end as double) as job",
      "cast(case income when '低' then 1.0 when '中' then 2.0 else 3.0 end as double) as income",
      "cast(case age when '青年' then 1.0 when '中年' then 2.0 else 3.0 end as double) as age",
      "cast(case sex when '男' then 1.0 else 2.0 end as double) as sex",
      //朴素贝叶斯算法,默认预测结果中的类别是用0.0开始编号的
      "cast(case label when '没出' then 0.0  else 1.0 end as double) as label"
    )

    /** 特征数值化的数据:
     * +---+------+---+---+-----+
     * |job|income|age|sex|label|
     * +---+------+---+---+-----+
     * |1.0|   2.0|1.0|1.0|  1.0|
     * |1.0|   1.0|1.0|2.0|  0.0|
     * |2.0|   3.0|1.0|1.0|  0.0|
     * |2.0|   2.0|2.0|1.0|  0.0|
     * |2.0|   2.0|3.0|1.0|  1.0|
     * |3.0|   2.0|3.0|2.0|  0.0|
     * |    .............       |
     * +---+------+---+---+-----+
     */

    // ② 特征向量化 ->自定义函数,将特征数组 转化成 特征向量(Vector类型)

    val to_vector = (arr: mutable.WrappedArray[Double]) => {
      Vectors.dense(arr.toArray)
    }
    spark.udf.register("to_vector", to_vector)

    val sample2: DataFrame = sample1.selectExpr(
      "label",
      "to_vector(array(job,income,age,sex)) as feature"
    )

    /** 特征向量化后的数据:
     * +-----+-----------------+
     * |label|          feature|
     * +-----+-----------------+
     * |  1.0|[1.0,2.0,1.0,1.0]|
     * |  1.0|[1.0,2.0,2.0,2.0]|
     * |  0.0|[2.0,2.0,2.0,1.0]|
     * |  1.0|[2.0,2.0,3.0,1.0]|
     * |  0.0|[3.0,2.0,3.0,2.0]|
     * |  0.0|[3.0,1.0,3.0,2.0]|
     * |     ...........       |
     * +-----+-----------------+
     */

    // 3、构建NaiveBayes算法对象
    val bayes: NaiveBayes = new NaiveBayes()
      .setFeaturesCol("feature") //设置样本数据中,特征数据所在的字段
      .setLabelCol("label") //设置样本数据中,类别标签所在字段
      .setSmoothing(1.0) //拉普拉斯平滑系数

    // 4、对样本数据和算法,进行模型训练
    val model: NaiveBayesModel = bayes.fit(sample2)

    // 5、模型写出
    model.save("userProfile/data/bayes/model")

    spark.close()
  }
}
(2)输入模型中待分析数据,进行预测
package cn.ianlou.bayes

import org.apache.log4j.{Level, Logger}
import org.apache.spark.ml.classification.{NaiveBayes, NaiveBayesModel}
import org.apache.spark.ml.linalg.Vectors
import org.apache.spark.sql.{DataFrame, SparkSession}
import scala.collection.mutable

/**
 * @date: 2020/2/21 15:03
 * @site: www.ianlou.cn
 * @author: lekko 六水
 * @qq: 496208110
 * @description:
 *
 */
object BayesPredict {
  def main(args: Array[String]): Unit = {
    Logger.getLogger("org.apache.spark").setLevel(Level.WARN)

    val spark: SparkSession = SparkSession
      .builder()
      .appName(this.getClass.getSimpleName)
      .master("local[*]")
      .getOrCreate()

    // 1、加载待预测数据
    val preDF: DataFrame = spark.read
      .option("header", true)
      .csv("userProfile/data/bayes/chugui/test/test.csv")


    // 2、数据处理-特征加工
    // ① 特征数值化
    val preDF2: DataFrame = preDF.selectExpr(
      "name",
      "cast(case job when '老师' then 1.0 when '程序员' then 2.0 else 3.0 end as double) as job",
      "cast(case income when '低' then 1.0 when '中' then 2.0 else 3.0 end as double) as income",
      "cast(case age when '青年' then 1.0 when '中年' then 2.0 else 3.0 end as double) as age",
      "cast(case sex when '男' then 1.0 else 2.0 end as double) as sex"
    )

    // ② 特征向量化 -> udf
    val to_vector = (arr: mutable.WrappedArray[Double]) => {
      Vectors.dense(arr.toArray)
    }
    spark.udf.register("to_vector", to_vector)

    val preDF3 = preDF2.selectExpr("name", "to_vector(array(job,income,age,sex)) as feature")


    // 3. 加载训练好的模型 -> 静态方法
    val model: NaiveBayesModel = NaiveBayesModel.load("userProfile/data/bayes/model")

    // 4. 将处理好的数据,输入模型,得出预测结果
    val predict: DataFrame = model.transform(preDF3)

    predict
      .drop("rawPrediction", "feature")
      .show(50, false)

    /** 预测结果:
     * +----+-----------------------------------------+----------+
     * |name|         probability                     |prediction|
     * +----+-----------------------------------------+----------+
     * |曹操  |[0.4838286313370446,0.5161713686629554] | 1.0      |
     * |小乔  |[0.4674001229257888,0.5325998770742112] | 1.0      |
     * |吕布  |[0.6142050318416438,0.3857949681583561] | 0.0      |
     * +----+---------------------------------------+------------+
     */

    spark.close()
  }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值