您的位置:首页 > 其它

逻辑回归(LR)

2016-09-19 11:31 483 查看





背景知识:

二元的分类问题

比如“是否为乳腺癌二分类问题”,我们可以用线性回归的方法求出适合数据的一条直线: 




鉴于线性回归模型只能预测连续的值,但是分类问题,我们需要输出0或1。我们可以预测是否为恶性肿瘤hθ(x)≥.05为恶性,hθ(x)<0.5为良性。
然而线性回归的鲁棒性很差,例如在图1.b的数据集上建立回归,因最右边噪点的存在,使回归模型在训练集上表现都很差。这主要是由于线性回归在整个实数域内敏感度一致,而分类范围,需要在[0,1]。
逻辑回归就是一种减小预测范围,将预测值限定为[0,1]间的一种回归模型,其回归方程与回归曲线如图2所示。逻辑曲线在z=0时,十分敏感,在z>>0或z<<0处,都不敏感,将预测值限定为(0,1)。



其实就是在线性回归的基础上,套用了一个逻辑函数:S形函数(Sigmoid function)

 

对模型的理解:

(1)


 

hθ(x)的作用是,对于给定的输入变量,根据选择的参数计算输出变量等于1 的可能性 :


例如,如果对于给定的 x,通过已经确定的参数计算得出 hθ(x)=0.7,则表示有 70%的几率 y 为正向类,相应地 y 为负向类的几率为 1-0.7=0.3。 
LR与线性回归的不同点在于:为了将线性回归输出的很大范围的数,例如从负无穷到正无穷,压缩到0和1之间,这样的输出值表达为“可能性”才能说服广大民众。

损失函数的选择:

我们知道线性回归模型的损失函数为所有误差的平方和:



理论上说,我们也可以沿用这个定义,但是我们将公式(1) 代入之后得到的 损失函数为 非凸函数。 有很多局部最优解,这将影响梯度下降算法寻找全局最小值。

重新定义:





hθ(x)与 Cost(hθ(x),y)之间的关系如下图所示: 



将构建的 Cost(hθ(x),y)简化如下:



带入代价函数得到:



在得到这样一个代价函数以后,我们便可以用梯度下降算法来求得能使代价函数最小的参数了。算法为:



求导后得到:




多类问题 



 

最后,在我们需要做预测时,我们将所有的分类机都运行一遍,然后对每一个输入变量, 都选择最高可能性的输出变量。 

 

正则化的逻辑回归模型



 

要最小化该代价函数,通过求导,得出梯度下降算法为:



 

注:看上去同线性回归一样,但是知道 hθ(x)=g(θTX),所以与线性回归不同。 


应用场景:

分类问题的首选吧,如果它的效果不怎么样,那么可以将它的结果作为基准来参考,在基础上与其他算法进行比较


算法优劣:


优点:

●实现简单,广泛的应用于工业问题上;

●分类时计算量非常小,速度很快,存储资源低;

●便利的观测样本概率分数;

对逻辑回归而言,多重共线性并不是问题,它可以结合L2正则化来解决该问题;(????)


缺点:

●当特征空间很大时,逻辑回归的性能不是很好;

●容易欠拟合,一般准确度不太高;

●不能很好地处理大量多类特征或变量;

●必须线性可分,对于非线性特征,需要进行转换;




算法评估:

对于LR分类模型的评估,常用AUC来评估。


实战案例:

某班级100名学生的语文和数学期末考试成绩,决定是否升学。根据打好标签的数据集,判断新的学生是否通过期末考试。

数据集:ex2data1.txt
语文数学是否通过
34.623659
c6e2
62451697
78.02469281536240
60.1825993862097686.308552095468261
。。。。。。
描述性分析:




代码:

Scala:
package com.dianping.www

/**
* Created by sun on 16/7/19.
*/

import org.apache.spark.mllib.classification.LogisticRegressionWithLBFGS
import org.apache.spark.mllib.evaluation.MulticlassMetrics
import org.apache.spark.mllib.linalg.Vectors
import org.apache.spark.mllib.regression.LabeledPoint
import org.apache.spark.{SparkConf, SparkContext}
object LR{
def main(args: Array[String]) {
val conf = new SparkConf().setAppName("LR1.0")
val sc = new SparkContext(conf)

// split args
val para = args(0).split(',')
// load data and transform to LabeledPoint format.
val data_tmp = sc.textFile(para(0))
val data = data_tmp.map( line => line.split(',')).map { r =>
val label = r(r.size - 1).toInt
val features = r.slice(0,r.size -1).map(_.toDouble)
LabeledPoint(label,Vectors.dense(features))
}
// Split data into training (60%) and test (40%).
val splits = data.randomSplit(Array(0.6, 0.4), seed = 11L)
val training = splits(0).cache()
val test = splits(1)

// Run training algorithm to build the model
val model = new LogisticRegressionWithLBFGS()
.setNumClasses(para(1).toInt) //two class.
.run(training)
 
// clear Threshold
// model.clearThreshold()
// Compute raw scores on the test set.
val predictionAndLabels = test.map { case LabeledPoint(label, features) =>
val prediction = model.predict(features)
(prediction, label)
}

// Get evaluation metrics.
val metrics = new MulticlassMetrics(predictionAndLabels)
val precision = metrics.precision
val recall = metrics.recall
println("Precision = " + precision + ",Recall = " + recall)
 
// Get AUC
val metrics2 = new BinaryClassificationMetrics(predictionAndLabels)
println("AreaUnderPR = " + metrics2.areaUnderPR() + "AUC = " + metrics2.areaUnderROC())

// Save and load model
//    model.save(sc, para(2))
sc.stop()
}
}


Reference:

逻辑回归模型(Logistic Regression, LR)基础
斯坦福大学2014机器学习个人笔记.pdf
常见机器学习算法比较
逻辑回归(logistic regression)
Linear Methods - spark.mllib
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: