透彻理解逻辑回归(数学推导+python实现+sklearn相关包使用)

逻辑回归(数学推导+python实现+sklearn相关包使用)


1. 原理讲解及数学公式推导

逻辑回归(logistic regression)也叫做对数几率回归, 其实它是一种分类方法
在上一章,我们介绍了最基本的线性回归,那么如何进行分类任务呢?
注意上一章讲过的广义线性模型(generalized linear regression), 只要找到一个单调可微函数, 接近单位阶跃函数,但是要连续,可以把预测的回归值和输出标记 y ϵ{0,1} y   ϵ { 0 , 1 } 联系起来(二分类任务中)
我们只能寻找单位阶跃函数的替代函数(surrogate function), \ 接下来让我们请出Sigmoid函数中的代表: logistic function(逻辑回归函数或对数几率函数) :

g(z)=11+ez g ( z ) = 1 1 + e − z

函数图像如下:


sigmoid

图1   Logistic function

注: Sigmoid函数即形似S型的一类函数,logistic function是其最典型的代表
将此函数代入广义线性模型,得到的线性模型如下:
ϕ(z)=11+e(θTxx+b) ϕ ( z ) = 1 1 + e − ( θ T x x + b )

y y 可以被看成类后验概率p(y=1 | xx) 即被当作正例的概率, 很自然地让 y>=0.5 y >= 0.5 的归为正例, y<0.5 y < 0.5 则归为反例

代价函数

我们同样使用均方误差即误差的平方和来替代:

J(θθ)=i=1m(ϕ(z(i))y(i))2   ,z(i)=θθTx(i)x(i)+b J ( θ θ ) = ∑ i = 1 m ( ϕ ( z ( i ) ) − y ( i ) ) 2       , z ( i ) = θ θ T x ( i ) x ( i ) + b

但是如果我们将 ϕ(z)=11+e(θTxx+b) ϕ ( z ) = 1 1 + e − ( θ T x x + b ) 代入上式,会发现代价函数并不是个凸函数,这样不利于进行最优化求解。
因为 ϕ(z) ϕ ( z ) 可以看做正例的后验估计,那么可以得到:
p(y=1| x; θx; θ)=ϕ(z)=ϕ(θTxθTx+b) p ( y = 1 |   x ;   θ x ;   θ ) = ϕ ( z ) = ϕ ( θ T x θ T x + b )

p(y=0| x; θx; θ)=1ϕ(z)=1ϕ(θTxθTx+b) p ( y = 0 |   x ;   θ x ;   θ ) = 1 − ϕ ( z ) = 1 − ϕ ( θ T x θ T x + b )

这两个式子可以结合起来变为一般形式:
p(y| x; θx; θ)=ϕ(z)y(1ϕ(z))1y p ( y |   x ;   θ x ;   θ ) = ϕ ( z ) y ( 1 − ϕ ( z ) ) 1 − y

我们通过给定的数据集进行 极大似然法(maximum likelihood method)估计参数 θθ θ θ :
L(θθ)=i=1mp(y(i)| xx(i);θθ)=i=1mϕ(z(i))y(i)(1ϕ(z(i)))1y(i)(1)(2) (1) L ( θ θ ) = ∏ i = 1 m p ( y ( i ) |   x x ( i ) ; θ θ ) (2) = ∏ i = 1 m ϕ ( z ( i ) ) y ( i ) ( 1 − ϕ ( z ( i ) ) ) 1 − y ( i )

为了方便计算,我们在两边同时取对数,使用 对数似然(log likelihood):
l(θθ)=lnL(θθ)=i=1m[y(i)ln(ϕ(z(i)))+(1y(i))ln(1ϕ(z(i)))] l ( θ θ ) = l n L ( θ θ ) = ∑ i = 1 m [ y ( i ) l n ( ϕ ( z ( i ) ) ) + ( 1 − y ( i ) ) l n ( 1 − ϕ ( z ( i ) ) ) ]

现在思路清晰了,我们的目标就是要使它最大,那么代价函数就取个负号吧
J(θθ)=l(θθ)=i=1m[y(i)ln(ϕ(z(i)))(1y(i))ln(1ϕ(z(i)))] J ( θ θ ) = − l ( θ θ ) = ∑ i = 1 m [ − y ( i ) l n ( ϕ ( z ( i ) ) ) − ( 1 − y ( i ) ) l n ( 1 − ϕ ( z ( i ) ) ) ]

其实等同于:

J(θθ)={mi=1ln(ϕ(z(i)))mi=1ln(1ϕ(z(i))), y(i)=1, y(i)=0 J ( θ θ ) = { − ∑ i = 1 m l n ( ϕ ( z ( i ) ) ) ,   y ( i ) = 1 − ∑ i = 1 m l n ( 1 − ϕ ( z ( i ) ) ) ,   y ( i ) = 0

该函数第一部分在0时最大,1时最小取0,单调递减,即说明偏离1代价越来越大
第二部分越偏离0越大

最优化: 梯度下降

这一章我们来探讨为什么沿梯度反方向下降最快,根据泰勒展开,当 δδ δ δ 取无穷小, 我们有:
(注: 以下 xx x x δδ δ δ 都是向量):

f(x+δx+δ)f(xx)f(xx)δδ f ( x + δ x + δ ) − f ( x x ) ≈ f ′ ( x x ) ⋅ δ δ

f(xx)δδ=f(xx)δδcosθ f ′ ( x x ) ⋅ δ δ = ‖ f ′ ( x x ) ‖ ⋅ ‖ δ δ ‖ ⋅ c o s θ

则很明显,当 θ=π θ = π 时, 即沿 f(xx) f ′ ( x x ) 的负方向时下降是最快的
接下来让我们先对 logistic l o g i s t i c 函数求导:
g(z)=(11+ez)=1(1+ez)2 ez=ez(1+ez)2 g ( z ) = ( 1 1 + e − z ) ′ = − 1 ( 1 + e − z ) 2   ⋅ − e − z = e − z ( 1 + e − z ) 2

发现特别有意思的一点:
g(z)=g(z)(1g(z)) g ′ ( z ) = g ( z ) ( 1 − g ( z ) )

知道了这个有用的性质,让我们来手推梯度下降公式中求偏导部分吧:
J(θθ)θθj=mi=1[y(i)ln(ϕ(z(i)))(1y(i))ln(1ϕ(z(i)))]θθj=i=1m[y(i)ϕ(z(i))+(1y(i))1ϕ(z(i))]ϕ(z(i))θθj=i=1m[y(i)ϕ(z(i))+(1y(i))1ϕ(z(i))]ϕ(z(i))(1ϕ(z(i)))z(i)θθj=i=1m[(1ϕ(z(i)))y(i)+ϕ(z(i))(1y(i))]xx(i)j=i=1m(ϕ(z(i))y(i))xx(i)j(3)(4)(5)(6)(7) (3) ∂ J ( θ θ ) ∂ θ θ j = ∂ ∑ i = 1 m [ − y ( i ) l n ( ϕ ( z ( i ) ) ) − ( 1 − y ( i ) ) l n ( 1 − ϕ ( z ( i ) ) ) ] ∂ θ θ j (4) = ∑ i = 1 m [ − y ( i ) ϕ ( z ( i ) ) + ( 1 − y ( i ) ) 1 − ϕ ( z ( i ) ) ] ⋅ ∂ ϕ ( z ( i ) ) ∂ θ θ j (5) = ∑ i = 1 m [ − y ( i ) ϕ ( z ( i ) ) + ( 1 − y ( i ) ) 1 − ϕ ( z ( i ) ) ] ⋅ ϕ ( z ( i ) ) ⋅ ( 1 − ϕ ( z ( i ) ) ) ⋅ ∂ z ( i ) ∂ θ θ j (6) = ∑ i = 1 m [ − ( 1 − ϕ ( z ( i ) ) ) y ( i ) + ϕ ( z ( i ) ) ( 1 − y ( i ) ) ] x x j ( i ) (7) = ∑ i = 1 m ( ϕ ( z ( i ) ) − y ( i ) ) x x j ( i )

因此,梯度下降:
until convergence:{
    θθj=θθjαmi=1(ϕ(z(i))y(i))xx(i)j         θ θ j = θ θ j − α ⋅ ∑ i = 1 m ( ϕ ( z ( i ) ) − y ( i ) ) x x j ( i )
}
不过,要自己实现代码的话,一般来说代价函数要除以m(线性回归里除以2m是为了方便求导后消去2), 然后加上正则化项

正则化

为了解决过拟合,在逻辑回归里,有以下两种解决方案:
1. 减少特征量
2. 在现有特征情况下,减小 θj θ j
所以我们的代价函数就变成这种:

J(θθ)=1mi=1m[y(i)ln(ϕ(z(i)))(1y(i))ln(1ϕ(z(i)))]+λ2mj=1nθθ2j J ( θ θ ) = 1 m ∑ i = 1 m [ − y ( i ) l n ( ϕ ( z ( i ) ) ) − ( 1 − y ( i ) ) l n ( 1 − ϕ ( z ( i ) ) ) ] + λ 2 m ∑ j = 1 n θ θ j 2

注意两点:
1.正则化是从 θ1 θ 1 开始的,因为X第一列全是人为加上的常数项1,没有必要进行正则化
2.其中 λ λ 如果过大,会导致欠拟合;而 λ λ 过小,会导致过拟合

更新后的梯度下降:
until convergence:{
    θθ0=θθ0αmmi=1(ϕ(z(i))y(i))xx(i)0         θ θ 0 = θ θ 0 − α m ⋅ ∑ i = 1 m ( ϕ ( z ( i ) ) − y ( i ) ) x x 0 ( i )

    θθj=θθjαm[mi=1(ϕ(z(i))y(i))xx(i)j+λθθj]         θ θ j = θ θ j − α m ⋅ [ ∑ i = 1 m ( ϕ ( z ( i ) ) − y ( i ) ) x x j ( i ) + λ θ θ j ]
}

推广到线代形式

转化为我们写代码需要的线代公式,代价函数:

J(θθ)=1m((Y1)Tln(1ϕ(Xθθ))YTln(ϕ(Xθθ))+λ2θθTθθ) J ( θ θ ) = 1 m ( ( Y − 1 ) T l n ( 1 − ϕ ( X θ θ ) ) − Y T l n ( ϕ ( X θ θ ) ) + λ 2 θ θ T θ θ )

梯度:
注意结果是一个(n+1, 1)的向量
1m[XT(ϕ(Xθθ)Y)+λθθ] 1 m ⋅ [ X T ( ϕ ( X θ θ ) − Y ) + λ θ θ ]

梯度下降:
until convergence{
θθ=θθαm[XT(ϕ(Xθθ)Y)+λθθ] θ θ = θ θ − α m ⋅ [ X T ( ϕ ( X θ θ ) − Y ) + λ θ θ ]

}

2.python实现

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import math
import scipy

"""
    注意接收的X是个向量
"""
def sigmoid(X):
    return 1 / (1 + np.exp(-X))

"""
    代价函数
    theta: (n+1, 1) 参数向量
    X: (m, n+1) 矩阵
    y: (m, 1) 结果向量
    lamb: 标量,控制正则化程度
"""
def get_cost(theta, X, y, lamb):
    m = len(y)
    phi = sigmoid(np.dot(X, theta)) # 先计算phi(z)

    theta_add = theta.copy()
    theta_add[0] = 0 # theta 0 不需要加正则化,所以计算代价时让theta_0 = 0

    reg = np.dot(np.transpose(theta_add), theta_add) # 正则化项*2/lambda

    return (np.dot(np.transpose(y-1), np.log(1 - phi)) - np.dot(np.transpose(y), np.log(phi)) + (lamb / 2 * reg)) / m

"""
    计算梯度
"""
def get_gradient(theta, X, y, lamb):
    m = len(y)
    phi = sigmoid(np.dot(X, theta))

    theta_add = theta.copy()
    theta[0] = 0

    return (np.dot(np.transpose(X), (phi-y)) + lamb*theta_add) / m

未完待续

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值