逻辑回归二分类算法python_(数据科学学习手札24)逻辑回归分类器原理详解&Python与R实现...

一、简介

逻辑回归(Logistic Regression),与它的名字恰恰相反,它是一个分类器而非回归方法,在一些文献里它也被称为logit回归、最大熵分类器(MaxEnt)、对数线性分类器等;我们都知道可以用回归模型来进行回归任务,但如果要利用回归模型来进行分类该怎么办呢?本文介绍的逻辑回归就基于广义线性模型(generalized linear model),下面我们简单介绍一下广义线性模型:

我们都知道普通线性回归模型的形式:

1344061-20180410184934003-1756675532.png

如果等号右边的输出值与左边y经过某个函数变换后得到的值比较贴切,如下面常见的“对数线性回归”(log-linear regression):

1344061-20180410185151850-383882322.png

这里对数函数ln(y)起到的作用便是将y转换为其对数值,且这个对数值与右边的线性模型的预测值更为贴切接近,我们管类似这里对数函数的套在y外面的单调可微函数(因为只有单调可微函数才存在反函数)叫做“联系函数”(link function),引出下面更一般的形式:

1344061-20180410185436575-446704681.png

我们在这里使用一个单调可微函数将分类任务的真实标记y与线性回归模型的预测值联系起来;

考虑二分类任务,其输出标记:

1344061-20180410183627034-493302111.png

而线性回归模型产出的预测值:

1344061-20180410183719210-2000393273.png

是连续域上的实值,因此我们需要把实值z转换为0/1值,最理想的是“单位阶跃函数”(unit-step function)

1344061-20180410183927926-2039833142.png

这里规定预测值z大于零就判为正例,小于零则判为反例,预测值为临界值零则可任意判别(事实上这种情况的样本本就存在一些问题而无法通过逻辑回归进行分类),下图展示了单位阶跃函数(红色)与对数几率函数(黑色):

1344061-20180410184144915-609413746.png

从上图可以看出,单位阶跃函数不连续,数学性质差,因此不能直接用作广义线性模型中的link function,于是我们的目的是找到在一定程度上近似单位阶跃函数的“替代函数”(surrogate function),并希望它单调可微。对数几率函数(logistic function)正是这样一个常用的替代函数:

1344061-20180410184548351-736098734.png

对数几率函数是一种“Sigmoid”函数(即形似S的函数,在神经网络的激励函数中有广泛应用),它将z值转化为一个接近0或1的y值,并且其输出值在z=0附近变化很陡。将该对数几率函数作为联系函数代入广义线性模型,可得:

1344061-20180410190518386-1063271751.png

我们对其进行如下推导变换:

1344061-20180410191223368-1410568216.png

若将y视为样本x作为正例的可能性,则1-y是其反例可能性,两者的比值:

1344061-20180410191331014-2115756395.png

称为“几率”(odds),反映了x作为正例的相对可能性。对几率取对数则得到“对数几率”(log odds,亦称logit):

1344061-20180410191515809-2106135769.png

由此可看出,这实际上是用线性回归模型的预测结果去逼近真实标记的对数几率,因此其对应的模型称为“对数几率回归”(logistic regression,亦称logit regression),这种方法具有诸多优点:

1.直接针对分类可能性进行建模,无需事先假设数据分布,这样就避免了假设分布不准确所带来的问题;

2.不仅输出预测类别,还输出了近似的预测概率,这对许多需要利用预测概率进行辅助决策的任务很有用;

3.对率函数是任意阶可导的凸函数,有很好的数学性质,现有的许多数值优化算法都可直接用于求取最优解

二、训练方法

根据一个样本集训练逻辑回归模型,实际上是要得到参数w与截距b,下面我们来仔细推导训练的思想:

前面我们得到了:

1344061-20180410193613188-1112851770.png

将其中的y视为类后验概率估计:

1344061-20180410193704683-477391811.png

则前面的式子可改写为:

1344061-20180410193740557-1051231890.png

下面根据上式对正例和反例的后验概率估计进行推导:

1344061-20180410194529678-1603096857.png

因此,我们可以通过“极大似然法”(maximum likelihood method)来估计w与b,给定数据集:

1344061-20180410195848483-1656843939.png

对率回归模型最大化“对数似然”(log-likelihood):

1344061-20180410200001933-1726373698.png

即令每个样本属于其真实标记的概率越大越好。令:

1344061-20180410221055668-1896059664.png

1344061-20180410221310743-1829258155.png

则:

1344061-20180410221518149-1903237610.png

再令:

1344061-20180410221809587-1442707960.png

则:

1344061-20180410222038944-1275508917.png

则最大化“对数似然”转换为:

1344061-20180410222319573-346854632.png

因为上式为关于β的高阶可导连续凸函数,由凸优化理论,使用经典的数值优化算法如梯度下降法(gradient decent method)、牛顿法(Newton method)等均可求得其最优解,即得到:

1344061-20180410222555809-931416124.png

则我们的逻辑回归模型训练完成。

三、Python实现

我们使用sklearn.linear_model中的LogisticRegression方法来训练逻辑回归分类器,其主要参数如下:

class_weight:用于处理类别不平衡问题,即这时的阈值不再是0.5,而是一个再缩放后的值;

fit_intercept:bool型参数,设置是否求解截距项,即b,默认True;

random_state:设置随机数种子;

solver:选择用于求解最大化“对数似然”的算法,有以下几种及其适用场景:

1.对于较小的数据集,使用"liblinear"更佳;

2.对于较大的数据集,"sag"、"saga"更佳;

3.对于多分类问题,应使用"newton-cg"、"sag"、"saga"、"lbfgs";

max_iter:设置求解算法的迭代次数,仅适用于solver设置为"newton-cg"、"lbfgs"、"sag"的情况;

multi_class:为多分类问题选择训练策略,有"ovr"、"multinomial" ,后者不支持"liblinear";

n_jobs:当处理多分类问题训练策略为'ovr'时,在训练时并行运算使用的CPU核心数量。当solver被设置为“liblinear”时,不管是否指定了multi_class,这个参数都会被忽略。如果给定值-1,则所有的核心都被使用,所以推荐-1,默认项为1,即只使用1个核心。

下面我们以威斯康辛州乳腺癌数据为例进行演示:

from sklearn importdatasetsfrom sklearn.model_selection importtrain_test_splitfrom sklearn.linear_model importLogisticRegressionfrom sklearn.metrics importf1_score as f1from sklearn.metrics importrecall_score as recallfrom sklearn.metrics importconfusion_matrix as cm'''导入威斯康辛州乳腺癌数据'''X,y= datasets.load_breast_cancer(return_X_y=True)'''分割训练集与验证集'''X_train,X_test,y_train,y_test= train_test_split(X,y,train_size=0.7,test_size=0.3)'''初始化逻辑回归分类器,这里对类别不平衡问题做了处理'''cl= LogisticRegression(class_weight='balanced')'''利用训练数据进行逻辑回归分类器的训练'''cl=cl.fit(X_train,y_train)'''打印训练的模型在验证集上的正确率'''

print('逻辑回归的测试准确率:'+str(cl.score(X_test,y_test))+'\n')'''打印f1得分'''

print('F1得分:'+str(f1(y_test,cl.predict(X_test)))+'\n')'''打印召回得分'''

print('召回得分(越接近1越好):'+str(recall(y_test,cl.predict(X_test)))+'\n')'''打印混淆矩阵'''

print('混淆矩阵:'+'\n'+str(cm(y_test,cl.predict(X_test)))+'\n')

1344061-20180411092543824-1996371504.png

四、R实现

在R中实现逻辑回归的过程比较细致,也比较贴近于统计学思想,我们使用glm()来训练逻辑回归模型,这是一个训练广义线性模型的函数,注意,这种方法不像sklearn中那样主要在乎的是输出的分类结果,而是更加注重模型的思想以及可解释性(即每个变量对结果的影响程度),下面对glm()的主要参数进行介绍:

formula:这里和R中常见的算法格式一样,传递一个因变量~自变量的形式;

family:这个参数可以传递一个字符串或family函数形式的输入,默认为gaussian,表示拟合出的函数的误差项服从正态分布,若使用family则可同时定义误差服从的分布和广义线性模型中的联系函数,例如本文所需的逻辑回归函数,就可以有两种设定方式:

1.传入gaussian

2.传入binomial(link='logit')

data:指定变量所属的数据框名称;

weights:传入一个numeric型向量,用于类别不平衡问题的再缩放,默认无,即将1与0类视作平衡;

model:逻辑型变量,用于控制是否输出最终训练的模型;

下面我们对威斯康辛州乳腺癌数据集进行逻辑回归分类训练,该数据集下载自https://archive.ics.uci.edu/ml/datasets.html

> rm(list=ls())> setwd('C:\\Users\\windows\\Desktop')>

>#read data> data <- read.table('breast.csv',sep=',')[,-1]> data[,1] = as.numeric(data[,1])-1

>

> #spilt the datasets into train-dataset and test-dataset with a proportion of 7:3

> sam <- sample(1:dim(data)[1],0.7*dim(data)[1])> train <-data[sam,]> test <- data[-sam,]>

> #method 1to train the logistic regression model> cl1 <- glm(V2~.,data=train,family=gaussian,model =T)>summary(cl1)

Call:

glm(formula= V2 ~ ., family = gaussian, data = train, model =T)

Deviance Residuals:

Min 1Q Median 3Q Max-0.5508 -0.1495 -0.0289 0.1313 0.8827Coefficients:

Estimate Std. Error t value Pr(>|t|)

(Intercept)-1.5799840 0.5155747 -3.065 0.002342 **V3-0.2599482 0.2154418 -1.207 0.228370V4-0.0079273 0.0095174 -0.833 0.405427V50.0081528 0.0305549 0.267 0.789754V60.0013896 0.0006602 2.105 0.035995 *V71.4228253 2.5709862 0.553 0.580315V8-3.6635584 1.5680864 -2.336 0.020012 *V90.7080702 1.2295130 0.576 0.565039V103.1537615 2.3451202 1.345 0.179514V110.1732304 0.8911542 0.194 0.845979V12-1.9387489 6.7295898 -0.288 0.773438V130.7726866 0.4147097 1.863 0.063233.

V14-0.0279811 0.0410619 -0.681 0.496025V15-0.1233500 0.0552559 -2.232 0.026195 *V160.0004280 0.0017295 0.247 0.804693V1712.4604521 9.3370259 1.335 0.182861V183.4109051 2.5982124 1.313 0.190074V19-3.2029680 1.4955409 -2.142 0.032877 *V205.8114764 6.7403058 0.862 0.389142V216.3245471 3.5132301 1.800 0.072649.

V22-3.8548911 13.9312795 -0.277 0.782160V230.2085364 0.0725441 2.875 0.004281 **V240.0163053 0.0082144 1.985 0.047892 *V250.0103947 0.0073762 1.409 0.159613V26-0.0015405 0.0004029 -3.823 0.000155 ***V270.3199127 1.7892352 0.179 0.858195V28-0.2059715 0.5003384 -0.412 0.680826V290.3228923 0.3129524 1.032 0.302863V300.4349610 1.1458239 0.380 0.704458V310.0973530 0.6204197 0.157 0.875398V323.6376056 2.9501115 1.233 0.218350

---Signif. codes:0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1(Dispersion parameterfor gaussian family taken to be 0.0537472)

Null deviance:91.048 on 397degrees of freedom

Residual deviance:19.725 on 367degrees of freedom

AIC:-2.3374Number of Fisher Scoring iterations:2

> pre <- predict(cl1,test[,2:dim(test)[2]])> predict <- data.frame(true=test[,1],predict=ifelse(pre > 0.5,1,0))>#print the confusion matrix>table(predict)

predicttrue 0 1

0 99 1

1 10 61

>#print the accuracy> cat('Accuracy:',sum(diag(prop.table(table(predict)))),'\n')

Accuracy:0.9356725

>

> #method 2to train the logistic regression model> cl2 <- glm(V2~.,data=train,family=binomial(link='logit'),model =T)

Warning messages:1: glm.fit:算法没有聚合2: glm.fit:拟合機率算出来是数值零或一>summary(cl2)

Call:

glm(formula= V2 ~ ., family = binomial(link = "logit"), data =train,

model=T)

Deviance Residuals:

Min 1Q Median 3Q Max-2.220e-04 -2.100e-08 -2.100e-08 2.100e-08 2.033e-04Coefficients:

Estimate Std. Error z value Pr(>|z|)

(Intercept)-8.758e+02 8.910e+05 -0.001 0.999V3-2.024e+02 1.990e+05 -0.001 0.999V43.032e+00 9.058e+03 0.000 1.000V54.306e+01 2.243e+04 0.002 0.998V62.976e-01 8.733e+02 0.000 1.000V75.400e+03 1.824e+06 0.003 0.998V8-6.629e+03 9.677e+05 -0.007 0.995V94.722e+03 1.151e+06 0.004 0.997V10-1.708e+03 2.175e+06 -0.001 0.999V11-1.363e+03 6.115e+05 -0.002 0.998V126.584e+03 7.757e+06 0.001 0.999V13-2.640e+01 6.282e+05 0.000 1.000V14-1.098e+02 7.760e+04 -0.001 0.999V151.270e+02 1.013e+05 0.001 0.999V164.578e+00 5.046e+03 0.001 0.999V17-1.474e+04 6.903e+06 -0.002 0.998V181.068e+04 3.621e+06 0.003 0.998V19-5.032e+03 8.410e+05 -0.006 0.995V204.981e+02 6.488e+06 0.000 1.000V21-1.025e+04 3.006e+06 -0.003 0.997V22-6.005e+04 2.600e+07 -0.002 0.998V23-2.170e+01 5.623e+04 0.000 1.000V241.412e+01 1.030e+04 0.001 0.999V25-1.807e+01 7.861e+03 -0.002 0.998V264.411e-01 4.646e+02 0.001 0.999V274.996e+02 9.163e+05 0.001 1.000V28-4.239e+02 4.489e+05 -0.001 0.999V291.159e+02 1.815e+05 0.001 0.999V301.786e+03 1.018e+06 0.002 0.999V312.349e+03 3.750e+05 0.006 0.995V32-8.331e+02 3.861e+06 0.000 1.000(Dispersion parameterfor binomial family taken to be 1)

Null deviance:5.1744e+02 on 397degrees of freedom

Residual deviance:4.1036e-07 on 367degrees of freedom

AIC:62Number of Fisher Scoring iterations:25

> pre <- predict(cl2,test[,2:dim(test)[2]])> predict <- data.frame(true=test[,1],predict=ifelse(pre > 0.5,1,0))>#print the confusion matrix>table(predict)

predicttrue 0 1

0 94 6

1 7 64

>#print the accuracy> cat('Accuracy:',sum(diag(prop.table(table(predict)))),'\n')

Accuracy:0.9239766

可以看出,方法1效果更佳;

以上就是关于逻辑回归的基本内容,今后也会不定时地在本文中增加更多内容,敬请期待。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,你的问题是关于Python函数第二次运行报错和retry的简单用法。 首先,如果一个Python函数在第二次运行时出现了错误,可能是由于函数内部的变量状态发生了变化,导致程序出错。为了解决这个问题,可以使用retry功能来多次尝试运行该函数,直到它成功为止。 使用retry功能可以在函数出现错误时自动重试,可以避免动重复运行该函数,从而提高效率。 下面是一个简单的示例代码,演示了如何使用retry功能: ```python import time from retry import retry @retry(delay=1, backoff=2, max_delay=4) def my_func(): print("Running my_func...") # 模拟函数出错 if time.time() % 2 == 0: raise ValueError("Oops! Something went wrong...") else: print("Success!") my_func() ``` 在这个示例代码中,我们使用了retry库中的retry装饰来装饰my_func函数,该函数会运行多次,直到成功为止。在retry装饰中,我们设置了最大延迟时间为4秒,每次重试前等待1秒,重试间隔时间呈指数级增长,即第一次重试后等待1秒,第二次重试后等待2秒,第三次重试后等待4秒,以此类推,直到达到最大延迟时间为止。 当my_func函数第一次运行时,它会输出“Running my_func...”和“Success!”,并正常结束。当函数第二次运行时,它会抛出一个ValueError异常,并重试多次,直到成功为止。 希望这个简单的示例可以帮助你理解如何使用retry功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值