python 逻辑回归

逻辑回归模型所做的假设是:

这里写图片描述

相应的决策函数为: y=1,if P(y=1|x)>0.5
(实际应用时特定的情况可以选择不同阈值,如果对正例的判别准确性要求高,可以选择阈值大一些,对正例的召回要求高,则可以选择阈值小一些)

那么,给定一个逻辑回归模型,如何来调整参数θ?首先我们假设:

这里写图片描述

上面两个公式是为了,方便后面的计算。

假设我们有n个独立的训练样本{(x1, y1) ,(x2, y2),…, (xn, yn)},y={0, 1}。那每一个观察到的样本(xi, yi)出现的概率是:

这里写图片描述

当y=1的时候,后面那一项没有了(为1),那就只剩下x属于1类的概率,当y=0的时候,第一项没有了(为1),那就只剩下后面那个x属于0的概率(1减去x属于1的概率)

求θ最优值相当于求,θ使得已知样本出现的最大概率。

因为每个样本都是独立的,所以n个样本出现的概率就是他们各自出现的概率相乘,假设生成m个训练样本相互独立,我们可以写出关于参数θ的似然函数:

这里写图片描述

(为了方便计算)将它转换为log似然函数:

这里写图片描述

如何最大化似然函数呢?我们可以使用梯度下降即:

这里写图片描述

类似于其他算法,例如神经网络BP,根据输入样本,已知的x,每次更新θ),其中α为学习速率。

接下来的问题就是对于L(θ)对θ求导了。

首先,设g(z)为 sigmoid函数,有如下公式g’(z)=g(z)(1-g(z)):

这里写图片描述

这里写图片描述

上式中,我们使用了g’(z)=g(z)(1-g(z))。最终得出随机梯度下降法则:

这里写图片描述


代码实现

  1. 数据集见github,方便起见,数据集的读取使用pandas。
import pandas as pd
def get_data():
    path = '../dataset/logistic_regression/lr_ml_action.txt'

    data = pd.read_csv(path, delim_whitespace=True,
                          names=['f1', 'f2', 'label'],
                          dtype={'A': np.float64, 'B': np.float64, 'C': np.int64})

    # add bias w0 (添加逻辑回归的第一项即偏置W0)
    data['f0'] = 1
    print data.head()
    features = ['f0', 'f1', 'f2']
    # 输出转化为 numpy array
    return data[features].values, data.label.values

输出的前五行如下:

         f1         f2  label  f0
0 -0.017612  14.053064      0   1
1 -1.395634   4.662541      1   1
2 -0.752157   6.538620      0   1
3 -1.322371   7.152853      0   1
4  0.423363  11.054677      0   1

类如下:

import numpy as np

class LogisticRegression(object):
    def __init__(self):
        self._map_method()
        pass

    def _map_method(self):
        self._do_train = {"gd": self._gd, "sgd": self._sgd}

    def _sigmoid(self, x):
        return 1.0 / (1 + np.exp(-x))

    def fit(self, X, Y, **opt):
        m, n = X.shape
        self._weight = np.ones((n, 1))
        max_iter = opt.get("max_iter", 100)
        alpha = opt.get("alpha", 0.01)
        method = opt.get("method", "sgd")

        for k in xrange(max_iter):
            try:
                # 训练
                self._do_train[method](X, Y, alpha)
                # 输出当前迭代次数的错误率
                print "iter %s error rate %s" % (k, self._get_error_rate(X, Y))
            except KeyError:
                raise ValueError('method error')

    def _sgd(self, X, Y, alpha):
        """
        stochastic gradient descent随机梯度下降法
        """
        m, n = X.shape
        for i in xrange(m):
            # pred = self._sigmoid(X[i, :] * self._weight)
            pred = self._sigmoid(np.dot(X[i, :], self._weight))
            error = Y[i] - pred
            self._weight = self._weight + alpha * np.matrix(X[i, :]).T * error

    def _gd(self, X, Y, alpha):
        """
        gradient descent梯度下降法
        """
        pred = self._sigmoid(X * self._weight)
        error = Y - pred
        self._weight = self._weight + alpha * X.T * error

    def _get_error_rate(self, X, Y):
        all_num = len(Y)
        error_num = 0
        for i in xrange(all_num):
            pred = self._sigmoid(np.dot(X[i, :], self._weight)) > 0.5
            if pred != bool(Y[i]):
                error_num += 1

        return error_num * 1.0 / all_num

训练代码如下:

def test_lr():
    X, Y = get_data()

    lr = LogisticRegression()
    lr.fit(X, Y)

程序运行的结果如下(可见错误率一直在下降):

这里写图片描述

具体代码见github


参考

李航《统计学习方法》
《机器学习实战》

http://blog.csdn.net/zouxy09/article/details/20319673

http://blog.yhat.com/posts/logistic-regression-and-python.html

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值