逻辑回归算法的优化

一:有无截距:

        逻辑回归算法的优化

如上图。可以知道,有截距的线条数比无截距的线条数(过原点的线条)要多。所以在选择逻辑回归的时候,通常要设置截距。增加正确的概率。

        代码:

                val lr = new LogisticRegressionWithSGD()   ----创建逻辑回归对象

                lr.setIntercept(true) -----设置截距  

二:线性不可分的时候,增加维度。

逻辑回归算法的优化

如图:当找不到一条线可以正确分类的时候,可以通过增加维度,找到一个面,正确的分类。而新维度的添加不能是随意的,是根据之前的维度,进行一些计算得到(具体的执行什么计算,是要通过大量的测试得出来的)。

代码:

def main(args:Array[String]){

    val conf  = new SparkConf().setAppName("lr").setMaster("local[*]")

    val sc = new SparkContext(conf)

    val inputdata = MLUtils.loadLibSVMFile(sc,"线性不可分的数据集.txt")

            .map{

                    labelpoint=>

                    val label = labelpoint.label

                    val feature = labelpoint.features

                    //新维度的值,必须建立在已有维度的基础上,经过一系列的数据变换得来,本例就是通过已有的两个维度进行求乘积得到的新的维度

                    val array = Array(feature(0),feature(1),feature(0)*feature(1))

                    val converFeature = Vectors.dense(array) --转成向量

                    new LabeledPoint(label,converFeature)

                    .......

                }

}

三:调整分类的阈值

    在一些特定的场合下,如果按照逻辑回归默认的分类阈值(0.5)来进行分类的话,可能会存在一些潜在的风险,比如:

            --癌症病人的判断:

                        --如果病人是癌症     判断成不是癌症   (可能会耽误病人的最佳治疗时间)

                        --如果病人不是癌症  判断成癌症    

     如果病人不是癌症的概率是45%,这个时候我们应该判断成是癌症,因为该概率太接近中间值。也是有很大的几率是癌症的,判断成是癌症可能导致错误率变大,但是却可以规避一些不能接受的风险。就可以调整成以0.3作为阈值。

代码:

        val lr = new LogisticRegressionWithLBFGS()

        //如果在训练模型的时候没有调用clearThreshold()这个方法,那个这个模型预测出来的结果都是分类号

        //如果在训练模型的时候调用clearThreshold()这个方法,那个这个模型预测出来的结果是一个概率

        val model = lr.run(tariningdata).clearThreshold()  //tariningdata训练模型的数据集

        val errorrate = testData.map{p=>   //testData测试数据

                val score = model.predict(p.features)//得到的是概率

                val result = score > 0.3 macth{  //修改阈值为0.3

                    case true =>1;case false=>0

                    Math.abs(result-p.label)

}.mean()

}

四:鲁棒性调优

      鲁棒是Robus的英译,也就是健壮和强壮的意思,例如:计算机软件在输入错误,磁盘故障,网络过载或者有意攻击情况下,能不死机,不崩溃,这就是该软件的鲁棒性。所以算法的鲁棒性就是指这个算法的抗干扰能力。

代码:

    val lr = LogisticRegressionWithLBFGS()

    lr.optimizer.setRegParam(0.4)  //这块设置lambda,越大越看推广能力(鲁棒性越好),一般不会超过1,0.4很好

    val model = lr.run(trainingData)

  五:归一化数据

  •   最大值最小值归一化(每个值x 转变成 =x-min/(max-min)得到的值都是在 0-1之间的数
  •   方差归一化

代码:

    val inputData = MLUtils.loadLibSVMFile(sc,"测试.txt")

    val vectors = inputData.map(._features)

    /*

    *scalerModel 这个对象中已经有每一列的均值和方差

    *withStd:代表的方差归一化  withMean:代表的是均值归一化  scalerModel 存放每一列的方差值

    */

    val scalerModel = new StandardScaler(withMean=true,withStd=true).fit(vectors)

    val normalizeInputData = inputData.map{point=>

            val label = point.label

            //对每一条数据进行归一化

            val features = scalerModel.transform(point.features.toDense)

            bew LabeledPoint(label,features)

}