Logistic Regression 原理及推导 python实现

一、问题引入

首先,Logistic回归是一种广义的线性回归模型,主要用于解决二分类问题。比如,现在我们有N个样本点,每个样本点有两维特征x1和x2,在直角坐标系中画出这N个样本的散点图如下图所示,

蓝色和红色分别代表两类样本。现在我们的目标是,根据这N个样本所表现出的特征以及他们各自对应的标签,拟合出一条直线对两类样本进行分类,直线的上侧属于第一类,直线的下侧属于第二类。那么我们如何寻找这条直线呢?我们知道,一条直线可以用简单的公式表示

y=θ0+θ1x1+θ2x2+...=θTx

参数θT的选择决定了直线的位置,如果我们选取了一组参数θ

导致直线的位置是这样的

那肯定不合理,因为两类样本完全没有被分开,而如果我们得到了这样一条直线

两类样本虽然存在一些小错误,但是基本上被分开了。由此,我们可以看到,Logistic Regression问题最终变成了求解最优参数θ的问题。

二、原理

样本的每一维特征的取值在经过参数θ线性组合之后取值范围是实数集(-inf, inf),而要想对实数进行二分类就要通过一个函数将实数投影到某个有限区间上,在有限区间内找到一个阈值,大于这个阈值分为第一类,小于等于这个阈值分为第二类。LR找到的这个投影函数就是sigmoid函数

g(z)=11+e?z

值域为(0,1),当x=0时,函数值为0.5。在实际分类中,由于假设样本均匀分布,所以阈值通常选取为0.5。

现在我们有N个样本x1,x2,x3...,每个样本有一个类别标签y(y=0 or y=1)与之对应,我们知道它们的对应关系可以由参数θ来估计,因此用极大似然估计法来求解我们我们的目标θ。

首先,把问题变成一个概率问题:

在某个x和θ的取值下,y=1的概率为hθ(x),

P(y=1|x;θ)=hθ(x)

在某个x和θ的取值下,y=0的概率为1?hθ(x),

P(y=0|x;θ)=1?hθ(x)

由于y只有两种取值:0和1,因此综合两种情况,对于每一个样本点来说,

P(y|x;θ)=(hθ(x))y(1?hθ(x))1?y

考虑样本集中的所有样本点,由于每个样本之间相互独立,因此它们的联合分布等于各自边际分布之积,

L(θ)=?i=1mP(yi|xi;θ)=(hθ(xi))yi(1?hθ(xi))1?yi

这就是我们求解θ需要的似然函数,我们通过他来求解在θ为何值时,x取某个值出现某个y的概率最大。

对J(θ)取对数,因为ln(x)和x单调性相同

l(θ)=lnL(θ)=∑i=1m(yilnhθ(xi)+(1?yi)ln(1?hθ(xi)))

给出损失函数J(θ)=?1ml(θ),对J(θ)求偏导,

理应令求偏导后的表达式等于零求极值,但是无法解析求解,因此用梯度下降法逐渐迭代,找到局部最优解。为什么梯度下降法能够做到呢?

可以看到θ的取值和J(θ)存在着一一对应的关系,让θ沿着J(θ)梯度的方向减小,可以最快速的逼近J(θ)的最小值,但其实往往找到的是极小值,局部最优。

由此可以得到θ的更新公式

三、Logistic回归算法步骤

  1. 初始化回归系数θ为1
  2. 重复下面步骤直至收敛

    {

    计算整个数据集的梯度

    使用α x gradient更新回归系数θ

    }

  3. 返回回归系数θ

四、python实现

现在,我们来解决一个实际问题:分类0/1数字。

在工程目录中有train和test两个文件夹,里面分别存有若干txt文件,每个txt文件用32*32的0/1矩阵表示一个数字0或者1,我们的目标是用train中的文件训练出一个logistic回归模型,也就是得到一组θ,能够用来分类test中的数据。

假设train中有m个文件,将每个文件中的数据拼接成一个1*1024(32*32=1024)的向量,相当于m个样本每个样本有1024维特征,这样训练出的θ也有1024维。同样,test中的n个文件也得到n*1024的矩阵,用之前训练好的θ进行分类。

"""
learned on Wed Feb 15 22:11:00 2017
@author maggie

description:
loadData function
load all the data from the given file, and return as mat

sigmoid function
sigmoid functon in logistic regression

gradAscent function
get the theta vector according to the gradient ascent method

classify function
using the theta vector to classify the test dataset

digitRecognition function
initialize all 

"""

#/usr/bin/python
from numpy import *
from os import listdir

def loadData(dir):
    trainfileList = listdir(dir)
    m = len(trainfileList)
    dataArray = zeros((m, 1024)) #store the data
    labelArray = zeros((m, 1))   #store the label
    for i in range(m):
        tempArray = zeros((1, 1024))
        filename = trainfileList[i]
        fr = open(‘%s/%s‘ %(dir, filename))
        for j in range(32):
            linestr = fr.readline()
            for k in range(32):
                tempArray[0, 32*j+k] = int(linestr[k])
        dataArray[i,:] = tempArray
        filename0 = filename.split(‘.‘)[0]
        label = filename0.split(‘_‘)[0]
        labelArray[i] = int(label)
    return dataArray, labelArray

def sigmoid(inX):
    return 1.0/(1+exp(-inX))

def gradAscent(dataArray, labelArray, alpha, maxCycles):
    dataMat = mat(dataArray)  #size : m x n
    labelMat = mat(labelArray)  #size : m x 1
    m, n = shape(dataMat)
    weigh = ones((n, 1))  #initialize the theta vector
    for i in range(maxCycles):
        h = sigmoid(dataMat * weigh)
        error = labelMat - h #size : m x 1
        weigh = weigh + alpha * dataMat.transpose() * error  #update the theta vector
    return weigh

def classify(testDir, weigh):
    dataArray, labelArray = loadData(testDir)
    dataMat = mat(dataArray)
    labelMat = mat(labelArray)
    h = sigmoid(dataMat * weigh)
    m = len(h)
    error = 0.0
    for i in range(m):
        if int(h[i]) > 0.5:
            print int(labelMat[i]), ‘is classified as : 1‘
            if int(labelMat[i]) != 1:
                error += 1
                print ‘error‘
        else:
            print int(labelMat[i]), ‘is classified as : 0‘
            if int(labelMat[i]) != 0:
                error += 1
                print ‘error‘
    print ‘error rate is ‘, ‘%.4f‘ %(error/m)

def digitRecognition(trainDir, testDir, alpha=0.07, maxCycles=10):
    data, label = loadData(trainDir)
    weigh = gradAscent(data, label, alpha, maxCycles)
    classify(testDir, weigh)
    print weigh

if __name__ == ‘__main__‘:
    digitRecognition(‘train‘,‘test‘)

得到的结果,可以看到错误率为0.018.

(train和test数据以及代码可以点击此处下载)(https://github.com/zjsghww/MachineLearning)

时间: 2024-08-27 04:32:18

Logistic Regression 原理及推导 python实现的相关文章

Logistic Regression & Regularization ----- Stanford Machine Learning(by Andrew NG)Course Notes

coursera上面Andrew NG的Machine learning课程地址为:https://www.coursera.org/course/ml 我曾经使用Logistic Regression方法进行ctr的预测工作,因为当时主要使用的是成型的工具,对该算法本身并没有什么比较深入的认识,不过可以客观的感受到Logistic Regression的商用价值. Logistic Regression Model A. objective function       其中z的定义域是(-I

机器学习算法与Python实践之(七)逻辑回归(Logistic Regression)

机器学习算法与Python实践这个系列主要是参考<机器学习实战>这本书.因为自己想学习Python,然后也想对一些机器学习算法加深下了解,所以就想通过Python来实现几个比较常用的机器学习算法.恰好遇见这本同样定位的书籍,所以就参考这本书的过程来学习了. 这节学习的是逻辑回归(Logistic Regression),也算进入了比较正统的机器学习算法.啥叫正统呢?我概念里面机器学习算法一般是这样一个步骤: 1)对于一个问题,我们用数学语言来描述它,然后建立一个模型,例如回归模型或者分类模型等

逻辑回归模型(Logistic Regression)及Python实现

逻辑回归模型(Logistic Regression)及Python实现 http://www.cnblogs.com/sumai 1.模型 在分类问题中,比如判断邮件是否为垃圾邮件,判断肿瘤是否为阳性,目标变量是离散的,只有两种取值,通常会编码为0和1.假设我们有一个特征X,画出散点图,结果如下所示.这时候如果我们用线性回归去拟合一条直线:hθ(X) = θ0+θ1X,若Y≥0.5则判断为1,否则为0.这样我们也可以构建出一个模型去进行分类,但是会存在很多的缺点,比如稳健性差.准确率低.而逻辑

【机器学习】Logistic Regression 的前世今生(理论篇)

Logistic Regression 的前世今生(理论篇) 本博客仅为作者记录笔记之用,不免有非常多细节不正确之处. 还望各位看官能够见谅,欢迎批评指正. 博客虽水,然亦博主之苦劳也. 如需转载,请附上本文链接,不甚感激! http://blog.csdn.net/cyh_24/article/details/50359055 写这篇博客的动力是源于看到了以下这篇微博: 我在看到这篇微博的时候大为触动,由于,如果是rickjin来面试我.我想我会死的非常慘,由于他问的问题我基本都回答不上来.

Logistic Regression 的前世今生(理论篇)

[机器学习]Logistic Regression 的前世今生(理论篇) 本博客仅为作者记录笔记之用,不免有很多细节不对之处. 还望各位看官能够见谅,欢迎批评指正. 博客虽水,然亦博主之苦劳也. 如需转载,请附上本文链接,不甚感激! http://blog.csdn.net/cyh_24/article/details/50359055 写这篇博客的动力是源于看到了下面这篇微博: 我在看到这篇微博的时候大为触动,因为,如果是rickjin来面试我,我想我会死的很惨,因为他问的问题我基本都回答不上

logistic regression教程3

在线性拟合的基础上,我们实现logistic regression. 如前所述,样本集是 {x1,y1},{x2,y2},...,{xn,yn}[1] 其中,xi=[1,xi,1,xi,2,xi,3,...,xi,k]T,且yi∈(0,1).注意,这里对yi有值上的要求,必须如此,如果值不再这个区间,要以归一化的方式调整到这个区间.对于分类问题,则yi的取值或者是0,或者是1,也就是yi∈{0,1}. 当然,从严格的意义上说,logistic regression拟合后,yi的值只能无限地逼近0

logistic regression教程1

实现线性拟合 我们用python2.7实现上一篇的推导结果.请先安装python matplotlib包和numpy包. 具体代码如下: #!/usr/bin/env python #! -*- coding:utf-8 -*- import matplotlib.pyplot as plt from numpy import * #创建数据集 def load_dataset(): n = 100 X = [[1, 0.005*xi] for xi in range(1, 100)] Y =

机器学习系列-Logistic Regression(1)

机器学习 这是记录自学的过程,目前的理论基础就是:大学高等数学+线性代数+概率论.编程基础:C/C++,python在观看机器学习实战这本书,慢慢介入.相信有读过以上三门课的人完全可以开始自学机器学习了,当然我上面这三门课学的一般,所以你只知道有这么一个公式或名词,不懂可以百度之深究之.在写这篇文章的时候作者机器学习还没学完,故文章中的错误还请不吝指出.再次声明,系列文章只是分享学习过程,学习点滴,不能保证文章的技术含量.后续再技术的不断完善中,我会重新再捋一遍这个学习过程,纠正其中错误. 目前

机器学习---逻辑回归(二)(Machine Learning Logistic Regression II)

在<机器学习---逻辑回归(一)(Machine Learning Logistic Regression I)>一文中,我们讨论了如何用逻辑回归解决二分类问题以及逻辑回归算法的本质.现在来看一下多分类的情况. 现实中相对于二分类问题,我们更常遇到的是多分类问题.多分类问题如何求解呢?有两种方式.一种是方式是修改原有模型,另一种方式是将多分类问题拆分成一个个二分类问题解决. 先来看一下第一种方式:修改原有模型.即:把二分类逻辑回归模型变为多分类逻辑回归模型. (二分类逻辑回归称为binary