对数几率回归-Logistic Regression

Logistic Regression是一个经典的判别学习分类方法。参考资料—西瓜书&&机器学习公开课-Andrew Ng。
首先我们来看为什么Logistic Regression被称为对数几率回归。

几率:将一个实例映射到正例或者负例的可能性比率。令 P(y=1|x;θ) P ( y = 1 | x ; θ ) 表示将样本分类成正例的概率。那么 P(y=0|x;θ)=1P(y=1|x;θ) P ( y = 0 | x ; θ ) = 1 − P ( y = 1 | x ; θ ) 就表示将样本分类成负例的概率。那么这里的几率表示为:
P(y=1|x;θ)1P(y=1|x;θ) P ( y = 1 | x ; θ ) 1 − P ( y = 1 | x ; θ )

对数几率:对数几率就是对上式求对数。

回归就是线性回归方法。因此:对数几率回归的表达式如下:
logP(y=1|x;θ)1P(y=1|x;θ)=θTx l o g P ( y = 1 | x ; θ ) 1 − P ( y = 1 | x ; θ ) = θ T x
经过简单的代数运算,我们得到
P(y=1|x;θ)=eθTx1+eθTx P ( y = 1 | x ; θ ) = e θ T x 1 + e θ T x ;以及
P(y=0|x;θ)=11+eθTx P ( y = 0 | x ; θ ) = 1 1 + e θ T x

我们看到 P(y=1|x;θ) P ( y = 1 | x ; θ ) P(y=0|x;θ) P ( y = 0 | x ; θ ) 的表达式实际上就是Sigmoid函数。那么为什么要这样做呢?

通过线性回归的方法做分类,理想的情况下是这样来做:

z=θTx z = θ T x ,当z<0,样本被分类成负例;当z>0,样本被分类成正例;当z=0,样本可以任意分类。显然,这里预测函数为单位阶跃函数

y=hθ(x)=g(z)=0.1,z>0,5,z=0,0,z<0(33) (33) y = h θ ( x ) = g ( z ) = { 1 , z > 0 , 0. 5 , z = 0 , 0 , z < 0

g(z)的函数图像如下图红线所示:
这里写图片描述
而单位阶跃函数是不连续不可微的,这对于我们求解参数带来了很大的不便。
因此,科学家们就想到用另外一个连续可微函数近似替代这个阶跃函数。常用的替代函数如上图黑线所示,它也被称为Sigmoid函数,也可以被称为对数几率函数。同样地,当对数几率函数值大于0.5,样本被分类成正例;小于0.5,样本被分类成负例;等于0.5,样本可被任意分类。

上面就是对对数几率函数的一些解释。咱们继续,在得到了 P(y=1|x;θ) P ( y = 1 | x ; θ ) P(y=0|x;θ) P ( y = 0 | x ; θ ) 之后,我们得到后验概率如下,对某一个训练样本:

P(yi|xi;θ)=yiP(yi=1|xi;θ)+(1yi)P(yi=0|xi;θ) P ( y i | x i ; θ ) = y i P ( y i = 1 | x i ; θ ) + ( 1 − y i ) P ( y i = 0 | x i ; θ )

写出对数似然函数:
L(θ)=logni=1P(yi|xi;θ)=ni=1logP(yi|xi;θ) L ( θ ) = l o g ∏ i = 1 n P ( y i | x i ; θ ) = ∑ i = 1 n l o g P ( y i | x i ; θ )

诶 忽然发现有些不对,
logP(yi|xi;θ)=log[yiP(yi=1|xi;θ)+(1yi)P(yi=0|xi;θ)] l o g P ( y i | x i ; θ ) = l o g [ y i P ( y i = 1 | x i ; θ ) + ( 1 − y i ) P ( y i = 0 | x i ; θ ) ] 不好处理。于是,我们改写:
P(yi|xi;θ) P ( y i | x i ; θ )
=yiP(yi=1|xi;θ)+(1yi)P(yi=0|xi;θ) = y i P ( y i = 1 | x i ; θ ) + ( 1 − y i ) P ( y i = 0 | x i ; θ )
=P(yi=1|xi;θ)yiP(yi=0|xi;θ)1yi = P ( y i = 1 | x i ; θ ) y i P ( y i = 0 | x i ; θ ) 1 − y i
于是,
L(θ)=ni=1[yilogP(yi=1|xi;θ)+(1yi)logP(yi=0|xi;θ)] L ( θ ) = ∑ i = 1 n [ y i l o g P ( y i = 1 | x i ; θ ) + ( 1 − y i ) l o g P ( y i = 0 | x i ; θ ) ]
=ni=1[yilogeθTxi1+eθTxi+(1yi)log11+eθTxi] = ∑ i = 1 n [ y i l o g e θ T x i 1 + e θ T x i + ( 1 − y i ) l o g 1 1 + e θ T x i ]
=ni=1[yi(θTxilog(1+eθTxi))(1yi)log(1+eθTxi)] = ∑ i = 1 n [ y i ( θ T x i − l o g ( 1 + e θ T x i ) ) − ( 1 − y i ) l o g ( 1 + e θ T x i ) ]
=ni=1[yiθTxilog(1+eθTxi)] = ∑ i = 1 n [ y i θ T x i − l o g ( 1 + e θ T x i ) ]
极大化对数似然等价于极小化其负数

minθL(θ)=ni=1[yiθTxi+log(1+eθTxi)]=L̂ (θ) m i n θ − L ( θ ) = ∑ i = 1 n [ − y i θ T x i + l o g ( 1 + e θ T x i ) ] = L ^ ( θ )

从损失函数的角度也可以导出上述式子

定义损失函数

Cost(hθ(x),y)={log(hθ(x)),y=1,log(1hθ(x)),y=0.(34) (34) C o s t ( h θ ( x ) , y ) = { − l o g ( h θ ( x ) ) , y = 1 , − l o g ( 1 − h θ ( x ) ) , y = 0.

化简得到 Cost(hθ(x),y)=log[(hθ(x))y(1hθ(x))1y] C o s t ( h θ ( x ) , y ) = − l o g [ ( h θ ( x ) ) y ( 1 − h θ ( x ) ) 1 − y ]
训练数据总体损失
J(θ)=ni=1Cost(hθ(xi),yi)=ni=1[yiloghθ(xi)+(1yi)log(1hθ(xi))]=L̂ (θ) J ( θ ) = ∑ i = 1 n C o s t ( h θ ( x i ) , y i ) = − ∑ i = 1 n [ y i l o g h θ ( x i ) + ( 1 − y i ) l o g ( 1 − h θ ( x i ) ) ] = L ^ ( θ )

最终目标为
minθJ(θ) m i n θ J ( θ )
目标函数对 θ θ 求偏导可得
θJ(θ)=ni=1[yixi+xieθTxi1+eθTxi] ∂ ∂ θ J ( θ ) = ∑ i = 1 n [ − y i x i + x i e θ T x i 1 + e θ T x i ]
这个式子的解析解不容易给出,于是利用标准梯度下降法给出 θ θ 的迭代公式如下:

θ(j+1):=θ(j)αθJ(θ(j)) θ ( j + 1 ) := θ ( j ) − α ∂ ∂ θ J ( θ ( j ) )

当然,也可以通过牛顿法,随机梯度下降等其他经典的方法求解。

下面附上代码(Python实现),建议在PyCharm下运行,数据集采用的是《机器学习实战》的Logistic回归测试数据:

# -*- coding:utf-8 -*-
# This class is built for logistic regression
__author__ = 'yanxue'

import numpy as np
from numpy import random
from numpy import linalg
from matplotlib import pyplot as plt
import math

class LogisticRegression:
    def __init__(self):
        pass

    def learning(self, data, label, learning_rate=0.1, convergence_rate=1):
        """Learning process of the logistic regression"""
        n, d = data.shape
        self.theta = random.randn(d + 1)
        theta0 = random.randn(d + 1)
        count = 0
        c_error = 0
        for j, x in enumerate(data):
            pLabel = lr.classify(x)
            c_error += pLabel != label[j]
        yield c_error, theta0
        ind = 0
        while linalg.norm(theta0 - self.theta) > convergence_rate:
            print('theta_{} = {}'.format(count, theta0))
            self.theta = theta0.copy()
            # gradient decent
            theta0 -= learning_rate * sum(map(self.__fun, [(data[i], label[i]) for i in range(n)]))
            # Stochastic gradient descent
            # theta0 -= learning_rate * self.__fun((data[ind % n], label[ind % n]))
            # ind += 1
            # Batch gradient descent
            # theta0 -= learning_rate * sum(map(self.__fun, [(data[i % n], label[i % n]) for i in range(ind, ind + 10)]))
            # ind += 10
            c_error = 0
            for j, x in enumerate(data):
                pLabel = lr.classify(x)
                c_error += pLabel != label[j]
            yield c_error, self.theta
            count += 1

    def __fun(self, trainx):
        return -trainx[1] * np.append(trainx[0], 1) + np.append(trainx[0], 1) * self.s(trainx[0])

    def classify(self, x):
        if self.s(x) < 0.5:
            return 0
        elif self.s(x) >= 0.5:
            return 1

    def s(self, inx):
        """Sigmoid function value"""
        try:
            re = 1 / (1 + math.exp(-np.dot(self.theta, np.append(inx, 1))))
        except OverflowError as e:
            print(e)
            re = 1
        return re

    def __str__(self):
        return "Logistic regression"

trainData = np.loadtxt('data/LogisticRegressionTestSet.txt', delimiter='\t')
trainX = trainData[:, [0, 1]]
trainY = trainData[:, 2]
lr = LogisticRegression()
# ------ Plot the data points ------
x1 = np.arange(-4.0, 3.2, 0.1)
plt.close()
plt.ion()  #interactive mode on
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
# ------ End of plot ------
for c_error, c_theta in lr.learning(trainX, trainY):
    # ------ Plot the iterative process ------
    plt.grid()
    plt.scatter(trainX[trainY == 0, 0], trainX[trainY == 0, 1], c='r')  # plot positive instances
    plt.scatter(trainX[trainY == 1, 0], trainX[trainY == 1, 1], c='b')  # plot negative instances
    plt.xlabel('$x_1$')
    plt.ylabel('$x_2$')
    plt.title('Logistic Regression Demo')
    x2 = (-c_theta[0] * x1 - c_theta[2]) / c_theta[1]
    plt.plot(x1, x2)
    plt.text(-4, 12.5, 'errorNum = {}'.format(c_error))
    # ------ End of plot ------
    plt.pause(0.2)
  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值