逻辑回归优化 正则化

本文探讨了逻辑回归的优化方法,包括有无截距的选择、处理线性不可分问题、调整分类阈值以降低风险、增强模型鲁棒性(正则化)以防止过拟合,以及数据预处理中的归一化和正负值调整。正则化通过L1和L2范数控制模型复杂度,L1有助于特征选择,而L2则使权重整体偏小。最后提到了训练方法,推荐使用L-BFGS而非SGD,因为L-BFGS内置归一化且支持多分类。
摘要由CSDN通过智能技术生成
逻辑回归的优化
有无截距
对于逻辑回归分类,就是找到z那条直线,不通过原点有截距的直线与通过原点的直线相比,有截距更能将数据分类的彻底。

在这里插入图片描述
部分测试数据

0 1:1.0140641394573489 2:1.0053491794300906
1 1:2.012709390641638 2:2.001907117215239
0 1:1.0052568352996578 2:1.0162894218780352
1 1:2.0140249849545118 2:2.0042119386532122
0 1:1.0159829400919032 2:1.0194470820311243
1 1:2.007369501382139 2:2.0071524676923533
0 1:1.0013307693392184 2:1.0158450335581597
1 1:2.01517182545874 2:2.0052873772719177
0 1:1.0130231961501968 2:1.019126883631059
1 1:2.014080456651037 2:2.004348828637212
0 1:1.0094645373208078 2:1.0092571241891017
1 1:2.0146123422070037 2:2.0041283816779076
0 1:1.0154461959034868 2:1.0068067043554225
1 1:2.000952712854708 2:2.00379067854305
0 1:1.0118559068419697 2:1.0068456308316762
...

代码

package Test

import org.apache.spark.mllib.classification.{LogisticRegressionWithLBFGS, LogisticRegressionWithSGD}
import org.apache.spark.mllib.regression.LabeledPoint
import org.apache.spark.mllib.util.MLUtils
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}

/**
  * 有无截距
  */
object LogisticRegression1 {

  def main(args: Array[String]) {
    val conf = new SparkConf().setAppName("spark").setMaster("local[3]")
    val sc = new SparkContext(conf)
    val inputData: RDD[LabeledPoint] = MLUtils.loadLibSVMFile(sc, "测试数据.txt")
    /**
     * randomSplit(Array(0.7, 0.3))方法就是将一个RDD拆分成N个RDD,N = Array.length
     * 第一个RDD中的数据量和数组中的第一个元素值相关
     */
    val splits = inputData.randomSplit(Array(0.7, 0.3),11L)
    val (trainingData, testData) = (splits(0), splits(1))
    val lr = new LogisticRegressionWithSGD
    // 设置要有W0,也就是有截距
    lr.setIntercept(true)  
    val model=lr.run(trainingData)
    val result=testData.map{labeledpoint=>Math.abs(labeledpoint.label-model.predict(labeledpoint.features)) }
    println("正确率="+(1.0-result.mean()))
    println(model.weights.toArray.mkString(" "))
    println(model.intercept)
  }
}

线性不可分

对于线性不可分问题,可以使用升高维度的方式转换成线性可分问题。低维空间的非线性问题在高维空间往往会成为线性问题。
在这里插入图片描述
数据:

0 1:1.0021476396439248 2:1.0005277544365077
0 1:0.004780438916016197 2:0.004464089083318912
1 1:1.005957371386034 2:0.009488506452877079
1 1:0.0032888762213735202 2:1.0096142970365218
0 1:1.004487425006835 2:1.0108859204789946
...
package Test

import org.apache.spark.mllib.classification.{LogisticRegressionWithLBFGS, LogisticRegressionWithSGD}
import org.apache.spark.mllib.linalg.Vectors
import org.apache.spark.mllib.regression.LabeledPoint
import org.apache.spark.mllib.util.MLUtils
import org.apache.spark.{SparkConf, SparkContext}
/**
 *  线性不可分 ----升高维度
 */
object LogisticRegression2 {

  def main(args: Array[String]) {
    val conf = new SparkConf().setAppName("spark").setMaster("local[3]")
    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 convertFeature = Vectors.dense(array)
        new LabeledPoint(label, convertFeature)
      }
    val splits = inputData.randomSplit(Array(0.7, 0.3),11L)
    val (trainingData, testData) = (splits(0), splits(1))
    val lr = new LogisticRegressionWithLBFGS()
    lr.setIntercept(true)
    val model = lr.run(trainingData)
    val result = testData.map {point => Math.abs(point.label - model.predict(point.features)) }
    println("正确率=" + (1.0 - result.mean()))
    println(model.weights.toArray.mkString(" "))
    println(model.intercept)
  }
}

相乘可以使数据拉伸,相加只是线性,效果不明显

调整分类阈值

在一些特定的场景下,如果按照逻辑回归默认的分类阈值0.5来进行分类的话,可能存在一些潜在的风险,比如,假如使用逻辑回归预测一个病人得癌症的概率是0.49,那么按照0.5的阈值,病人推测出来是没有得癌症的,但是49%的概率得癌症,比例相对来说得癌症的可能性也是很高,那么我们就可以降低分类的阈值,比如将阈值设置为0.3,小于0.3认为不得癌症,大于0.3认为得癌症,这样如果病人真的是癌症患者,规避掉了0.49概率下推断病人是不是癌症的风险。
降低阈值会使逻辑回归整体的正确率下降,错误率增大,但是规避了一些不能接受的风险。

数据示例

1 1:80 2:1 3:1 4:3 5:3 6:3 
1 1:18 2:0 3:0 4:4 5:4 6:5 
1 1:56 2:1 3:1 4:4 5:4 6:3 
1 1:80 2:0 3:0 4:3 5:2 6:5 
1 1:43 2:1 3:0 4:3 5:4 6:3 
0 1:53 2:0 3:1 4:3 5:4 6:2 
0 1:32 2:1 3:0 4:2 5:4 6:4 
0 1:24 2:1 3:1 4:4 5:4 6:4 
0 1:18 2:0 3:1 4:2 5:3 6:3 
0 1:50 2:0 3:0 4:3 5:4 6:3 
0 1:40 2:1 3:0 4:4 5:3 6:3 
0 1:20 2:0 3:1 4:4 5:4 6:3 
...

原始的,直接是获取的类别编号

val conf = new SparkConf().setAppName("spark").setMaster("local[3]")
    val sc = new SparkContext(conf)
    /**
     * LabeledPoint = Vector+Y
     */
    val inputData = MLUtils.loadLibSVMFile(sc, "健康状况训练集.txt")
    val splits = inputData.randomSplit(Array(0.7, 0.3),11L)
    val (trainingData, testData) = (splits(0), splits(1))
    val lr = new LogisticRegressionWithLBFGS()
    lr.setIntercept(true)

    val model = lr.run(trainingData)
    val result = testData
      .map{point=>Math.abs(point.label-model.predict(point.features)) }
    println("正确率="+(1.0-result.mean()))
    println(model.weights.toArray.mkString(" "))
    println(model.intercept)

一般我们获取都是分类编号,如果我们想获取概率值,就需要调用clearThreshold方法

    val conf = new SparkConf().setAppName("spark").setMaster("local[3]")
    val sc = new SparkContext(conf)
    /**
     * LabeledPoint = Vector+Y
     */
    val inputData = MLUtils.loadLibSVMFile(sc, "健康状况训练集.txt")
    val splits = inputData.randomSplit(Array(0.7, 0.3),11L)
    val (trainingData, testData) = (splits(0), splits(1))
    val lr = new LogisticRegressionWithLBFGS()
    lr.setIntercept(true)
        /**
     * 如果在训练模型的时候没有调用clearThreshold这个方法,那么这个模型预测出来的结果都是分类号
     * 如果在训练模型的时候调用clearThreshold这个方法,那么这个模型预测出来的结果是一个概率
     */
    val model = lr.run(trainingData).clearThreshold()
    val errorRate = testData.map{p=>
      //score就是一个概率值
      val score = model.predict(p.features)
      // 癌症病人宁愿判断出得癌症也别错过一个得癌症的病人
      val result = score>0.3 match {case true => 1 ; case false => 0}
      Math.abs(result-p.label)
    }.mean()
    println(1-errorRate)
    
鲁棒性调优 (正则化)

鲁棒是Robust的音译,也就是健壮和强壮的意思,比如说,计算机软件在输入错误、磁盘故障、网络过载或有意攻击情况下,能不死机、不崩溃,就是该软件的鲁棒性,那么算法的鲁棒性就是指这个算法的抗干扰能力强。
逻辑回归的决策边界 z = w 0 + w 1 x 1 + w 2 x 2 = 0 z= w_0+w_1x_1+w_2x_2=0 z=w0+w1x1+w2x2=0如下。
当维度只有两个时,是一条直线
在这里插入图片描述
如下两个模型
0.5 x 1 + 0.4 x

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值