基于Spark的机器学习和数据挖掘

特征工程 One-Hot编码  Mlib  Pipeline 混淆矩阵

机器学习和数据挖掘

 基本数据的查看-描述性分析
 数据特征的确认
 机器学习/数据挖掘模型的展开
 模型评估和参数调整

1.基本数据特性:

      属性 attribute
      属性类型
    01.测量标度类型
      标称(nominal)、序数(ordinal)、 区间(interval)和比率(ratio)
       标称和序数属性统称定性的(qualitative) 或分类 的(categorical)属性  
       区间和比率    统称定量的(quantitative)或数值 的(numeric)属性  
    02.值的个数
       用值的个数描述属性:离散的(discrete)和连续的(continuous)   
    两者之间关系:
            计数属性(count attribute)是离散的,也是 比率属性
       非对称的属性(asymmetric attribute),出现非零属性值才是重要的
数据:
    初步了解数据
     基本情况: 查看数据的基本字段,字段的含义以及字段的顺序
     特征:     字段的数据类型以及可用的各种变换
     常规处理: 各个字段是否有缺失值,值的范围,数据是否有重复值,数据不一致情况
                缺失数据处理    
         数据和数据的对应关系    
     数据量的问题:数据量-数据不不均衡的情况

2.特征工程

  连续数据映射变化
  连续变量离散化
  离散变量编码
特征工程-数据的处理
01. 映射-
    一些数学函数,将原始值进行映射
    归一化处理
    离差标准化   |min-max标准化(Min-max normalization)  
       对原始数据的线性变换,使结果落到[0,1]  x = (x - min)/(max - min)
    标准差标准化 | z-score 0均值标准化(zero-mean normalization)
      x = (x - u)/σ
02.One-Hot编码
    离散变量
       定类-标称(nominal): 离散特征的取值之间没有大小的意义,比如color:[red,blue],那么就使用one-hot编码  
         定序-序数(ordinal):离散特征的取值有大小的意义,比如size:[X,XL,XXL],那么就使用数值的映射{X:1,XL:2,XXL:3}
    进行one-hot编码或哑变量编码 连续数据离散化
       虚拟变量又称虚设变量、名义变量或哑变量,用以反映质的属性的一个人工变量,是量化了的质变量,通常取值为0或1。
        Dummy Variable
    one-hot编码-一位有效编码,
        其方法是使用N位状态寄存器来对N个状态进行编码,每个状态都由他独立的寄存器位,并且在任意时候,其中只有一位有效
       one-hot在提取文本特征上的
    好处主要有:
       解决了分类器不好处理属性数据的问题,在一定程度上也起到了扩充特征的作用       
03.连续特征的离散化处理
  GBDT
  分箱-Binning_数据分箱    
    分箱就是将连续变量离散化,将多状态的离散变量合并成少状态
         对连续变量进行离散化,离散化通常采用分箱法   
    分箱方法分为无监督分箱和有监督分箱
        无监督分箱 
           等频分箱,等距分箱和聚类分箱。
        有监督分箱
             best-ks分箱和卡方分箱
    具体的分箱
      等频分箱
        区间的边界值要经过选择,使得每个区间包含大致相等的实例数量。
          比如说 N=10 ,每个区间应该包含大约10%的实例。

      等距分箱
        从最小值到最大值之间,均分为 N 等份。
        如果 A,B 为最小最大值, 则每个区间的长度为 W=(B−A)/N , 则区间边界值为A+W,A+2W,….A+(N−1)W 。
        这里只考虑边界,每个等份的实例数量可能不等

      卡方分箱
         卡方分箱是自底向上的(即基于合并的)数据离散化方法。
         它依赖于卡方检验:具有最小卡方值的相邻区间合并在一起,直到满足确定的停止准则。
         基本思想:对于精确的离散化,相对类频率在一个区间内应当完全一致。
             因此,如果两个相邻的区间具有非常类似的类分布,则这两个区间可以合并;
           否则,它们应当保持分开。而低卡方值表明它们具有相似的类分布
04.离散特征连续化
    分类变量转化为连续变量
      离散特征连续化的处理方法是独热编码 one-hot encoding
      特征嵌入embedding
特征工程-数据集处理:
样本数据量: 
正样本和负样本的数据量以及比例关系

有监督学习数据不平衡问题
  二分类中正负样本差两个及以上数量级情况下的数据不平衡问题  
 Imbalanced  解决方式:
  数据采样
     a)过抽样:通过复制少数类样本 -- 上采样(Oversampling)
     b)欠抽样:删除多数类样本  -- 下采样(Undersampling)
  数据合成
  加权
  正负样本极不均匀的问题,使用异常检测,或者一分类问题,也是一个思路。

基于Spark Mlib-机器学习实现

01.Spark Mlib的架构
API
算法库
底层基础
说明:
  01.底层基础:
    线性代数库 Breeze  
        breeze.linalg
    支持密集向量-稀疏向量-标量向量
    支持矩阵 --RowMatrix IndexedRowMatrix CoordinateMatrix
      org.apache.spark.ml.linalg.Vectors
          object Vectors {}
       org.apache.spark.ml.linalg.
          object Matrices {}
          sealed trait Matrix extends Serializable {}
Spark Mlib的版本说明
Machine Learning Library (MLlib)
 The MLlib DataFrame-based API is primary API          the spark.ml package
 The MLlib RDD-based API is now in maintenance mode    the spark.mllib package
02.Spark ML Pipeline 的设计思想和基本概念
若干个过程
  1、源数据ETL
  2、数据预处理
  3、特征选取
  4、模型训练与验证
 MLlib提供标准的接口来使联合多个算法到单个的管道或者工作流
 Pieline 相关的概念有: DataFrame 、 Transformer 、Estimator、Parameter等
   DataFrame    : DataFrame can use ML Vector types
   Transformer  : one DataFrame into another DataFrame
             a method transform()
   Estimator    :a DataFrame to produce a Transformer
               a method fit(), which accepts a DataFrame and produces a Model, which is a Transformer.
   an ML model is a Transformer 
   Pipeline: A Pipeline chains multiple Transformers and Estimators together to specify an ML workflow.
   Parameter: All Transformers and Estimators now share a common API for specifying parameters
   方法:
      LogisticRegression is an Estimator calling fit() trains a LogisticRegressionModel  - Transformer
    一些数据
       Pipeline  PipelineModel
       Predictor 类 (Estimator 的子类)
03.Spark ML Pipeline具体概念
标签数据(一般是字符串)转化成整数索引,而在计算结束又需要把  整数索引还原为标签。
  这就涉及到几个转换器:
    StringIndexer   StringIndexerModel
    VectorIndexer
    IndexToString  
    OneHotEncoder 
      针对类别特征的索引
特征目前多为string类型,而机器学习则要求其特征为numerical类型,在此需要对特征做转换,包括类型转换和缺失值的处理
    对categorical类型的特征进行numerical转换
VectorAssembler :
    VectorAssembler 是一个transformer ,将多列数据转化为单列的向量列

stage为Transformer和Estimator。
 Transformer 主要是用来操作一个DataFrame 数据并生成另外一个DataFrame 数据,
     比如svm模型、一个特征提取工具,都可以抽象为一个Transformer。
 Estimator 则主要是用来做模型拟合用的,用来生成一个Transformer
04.具体案例:
    /**
  * LogisticRegression 模型
  * setMaxIter 设置最大迭代次数(默认100),具体迭代次数可能在不足最大迭代次数停止
  * setTol 设置容错(默认1e-6),每次迭代会计算一个误差,误差值随着迭代次数增加而减小,当误差小于设置容错,则停止迭代
  * setRegParam 设置正则化项系数(默认0),正则化主要用于防止过拟合现象,如果数据集较小,特征维数又多,易出现过拟合,考虑增大正则化系数
  * setElasticNetParam 正则化范式比(默认0),正则化有两种方式:L1(Lasso)和L2(Ridge),L1用于特征的稀疏化,L2用于防止过拟合
  * setPredictionCol 设置预测列
  * setThreshold 设置二分类阈值
  */
   // 将数据随机划分为 train set 和 Test set集(30%进行测试)
   val Array(trainingDF, testDF) = vecDF.randomSplit(Array(0.7, 0.3))
   val  lr = new LogisticRegression()
                .setMaxIter(12)   //最大迭代次数
                .setRegParam(0.3) //正则化主要用于防止过拟合现象,如果数据集较小,特征维数又多,易出现过拟合,考虑增大正则化系数
                .setFamily("auto") //binomial(二分类)/multinomial(多分类)/auto,默认为auto。设为auto时,会根据schema或者样本中实际的class情况设置是二分类还是多分类,最好明确设置
                .setFeaturesCol("feature_colunms")//特征列
                .setLabelCol("label__colunm") //标签列
                .setThreshold(0.5) //设置二分类阈值
    //  .setStages(new PipelineStage[] {labelIndexer, featureIndexer, rf, labelConverter});
     // 构建完成一个 stage piple
      val lrPipeline = new Pipeline().setStages(Array(g_encoder,a_encoder,assembler, lr))


      // Fit the pipeline to training documents.
      val lrModel = lrPipeline.fit(train_data);
      //  Now we can optionally save the fitted pipeline to disk
      lrModel.write().overwrite().save("/mymodel);

源码中的案例:
 //Scala
 // val pipeline = new Pipeline().setStages(Array(tokenizer, stopWordsRemover, countVectorizer))
 //Java
 // Pipeline pipeline = new Pipeline().setStages(new PipelineStage[] {tokenizer, hashingTF, lr});
 源码: 
    abstract class Estimator[M <: Model[M]] extends PipelineStage

其他:
Dataset<Row> df = spark.createDataFrame(data, schema);
OneHotEncoderEstimator encoder = new OneHotEncoderEstimator()
          .setInputCols(new String[] {"categoryIndex1", "categoryIndex2"})
          .setOutputCols(new String[] {"categoryVec1", "categoryVec2"});

 OneHotEncoderModel model = encoder.fit(df);
 Dataset<Row> encoded = model.transform(df);

a method fit(), which accepts a DataFrame and produces a Model, which is a Transformer.  an ML model is a Transformer 
A learning model<a Transformer> might take a DataFrame  -- output a new DataFrame with predicted labels appended as a column

A feature transformer might take a DataFrame

3.模型调参

模型调参,
 第一步是要找准目标:我们要做什么?
 一般来说,这个目标是提升某个模型评估指标
  模型评估: 
模型评估
基本概念:
模型在未知数据上的准确率的指标,叫做泛化误差(Genelization error)。 
可视化工具
准确率 (Accuracy)
  Accuracy = (TP+TN)/(TP+FN+FP+TN)
   真正(True Positive , TP):被模型预测为正的正样本。
   真负(True Negative , TN):被模型预测为负的负样本   
召回率 (Recall)-- 查全率
  Recall = TP/(TP+FN),即正确预测的正例数 /实际正例总数

混淆矩阵
矩阵中的每一行代表实例的预测类别,每一列代表实例的真实类别
ROC曲线
  横坐标为False Positive Rate(FPR假正率), FPR=FP/(FP+TN),即被 预测为正的负样本数 /负样本实际数
  纵坐标为True Positive Rate(TPR真正率)    TPR=TP/(TP+FN),即被预测为正的正样本数 /正样本实际数
 ROC曲线中的四个点和一条线:
     点(0,1):即FPR=0, TPR=1,意味着FN=0且FP=0,将所有的样本都正确分类。
     点(1,0):即FPR=1,TPR=0,最差分类器,避开了所有正确答案。
     点(0,0):即FPR=TPR=0,FP=TP=0,分类器把每个实例都预测为负类。
     点(1,1):分类器把每个实例都预测为正类。
  ROC曲线越接近左上角,该分类器的性能越好
 AUC(Area Under Curve)被定义为ROC曲线下的面积(ROC的积分),
    通常大于0.5小于1。随机挑选一个正样本以及一个负样本,
    分类器判定正样本的值高于负样本的概率就是 AUC 值。AUC值(面积)越大的分类器,性能越好

4.参考:

如何解决机器学习中数据不平衡问题 https://www.cnblogs.com/zhaokui/p/5101301.html
Spark入门:标签和索引的转化:StringIndexer- IndexToString-VectorIndexer
http://dblab.xmu.edu.cn/blog/1297-2/ 
ML Pipelines  http://spark.apache.org/docs/latest/ml-pipeline.html
ML

blogroll

social