美文网首页
Spark ML处理样本类别不均衡问题

Spark ML处理样本类别不均衡问题

作者: 架构师老狼 | 来源:发表于2021-12-21 11:45 被阅读0次

    样本类别分布不均衡导致的危害?

    • 样本类别不均衡将导致样本量少的分类所包含的特征过少,并很难从中提取规律;
    • 即使得到分类模型,也容易产生过度依赖与有限的数据样本而导致过拟合问题,当模型应用到新的数据上时,模型的准确性会很差

    解决类别不平衡数据

    1 过采样代表性算法-SMOTE
    1.1 算法思想
    • 为了解决随机过采样中造成模型过拟合问题,⼜能保证实现数据集均衡的⽬的,出现了过采样法代表性的算法SMOTE 算法。
    • SMOTE算法是对随机过采样⽅法的⼀个改进算法,由于随机过采样⽅法是直接对少数类进⾏重采⽤,会使训练集中有 很多重复的样本,容易造成产⽣的模型过拟合问题。
    1. SMOTE合成少数样本的思想:
    2. 先随机选定⼀个少数类样本i;
    3. 找出这个少数类样本i的K个近邻(假设K=5),5个近邻已经被圈出;
    4. 随机从这K个近邻中选出⼀个样本j;
    5. 在少数类样本i和被选中的这个近邻样本j之间的连线上,随机找⼀点。这个点就是⼈⼯合成的新的样本点(绿⾊正号标出)
    1.2 spark实现
    def generateSamples1(data: RDD[(Long, Vector)], k: Int, N: Int): RDD[Vector] = {
        // 1.k-neighbours: 先分组,再笛卡尔积,排除自己减少计算
        val groupedRDD = data.groupBy(_._1)
        val vecAndNeis: RDD[(Vector, Array[Vector])] = groupedRDD.flatMap { case (id, iter) =>
          val vecArr = iter.toArray.map(_._2)
    
          //2.对每个vector产生笛卡尔积
          val cartesianArr: Array[(Vector, Vector)] = vecArr.flatMap(vec1 => {
            vecArr.map(vec2 => (vec1, vec2))
          }).filter(tuple => tuple._1 != tuple._2)
    
          cartesianArr.groupBy(_._1).map { case (vec, vecArr) => {
            (vec, vecArr.sortBy(x => Vectors.sqdist(x._1, x._2)).take(k).map(_._2))
          }
          }
        }
    
        // 3.从这k个近邻中随机挑选一个样本,以该随机样本为基准生成N个新样本
        vecAndNeis.flatMap { case (vec, neighbours) =>
          (1 to N).map { i =>
            val rn = neighbours(Random.nextInt(k))
            val diff = rn.copy
            BLASUDF.axpy(-1.0, vec, diff)
    
            val newVec = vec.copy
            BLASUDF.axpy(Random.nextDouble(), diff, newVec)
            newVec
          }.iterator
        }
      } 
    
    2 欠采样
    2.1 算法思想
    1. 即从多数类S中随机选择⼀些样样本组成样本集E
    2. 然后将样本集从S中移除。新的数据集!
    2.2 spark实现
    // 1 找出样本多的类别
    val faudDF = creaditDf.where("Class=1")
    val faudNumber = BigDecimal(faudDF.count())
    val normalDF = creaditDf.where("Class=0")
    val normalNumber = BigDecimal(normalDF.count())
    
    // 2 按比例随机采样
    val ratio = faudNumber./(normalNumber)
    val sampleNormalDF = normalDF.sample(false, ratio.toDouble, 10)
    val underDF = faudDF.union(sampleNormalDF)
    //数据标准化
    val vecUnder = new VectorAssembler()
        .setInputCols(Array("Amount"))
        .setOutputCol("vectorAmount")
        .transform(underDF)
    
    val scaler = new StandardScaler()
        .setInputCol("vectorAmount")
        .setOutputCol("scaledAmount")
        .setWithStd(true)
        .setWithMean(false)
    
    val scalerModel = scaler.fit(vecUnder)
    val scaledUnder = scalerModel.transform(vecUnder).drop("vectorAmount")
    

    相关文章

      网友评论

          本文标题:Spark ML处理样本类别不均衡问题

          本文链接:https://www.haomeiwen.com/subject/yvqxqrtx.html