假设一个数据集有n个样本,每个样本有m个特征,样本标签y为{0, 1}。

数据集可表示为:

其中,x(ij)为第i个样本的第j个特征值,y(i)为第i个样本的标签。

X矩阵左侧的1相当于回归方程的常数项。

每个特征有一个权重(或系数),权重矩阵为:

开始可以将权重均初始化为1。

将特征及权重分别相乘得到Xw (即特征的线性组合,为n维列向量)。

经过Sigmoid函数处理得到预测值:




y为预测值(取值范围0-1),为n维列向量。

对于一个样本i,y(i)取值为1和0的概率分别是:

其中x(i)为第i个样本的特征向量,为m+1维行向量。

为了学习得到最佳的权重矩阵w,需要定义损失函数来优化。一个直观的想法是使用预测值y与观测值Y之间的误差平方和,但是这个损失函数是非凸函数,用梯度下降法不能得到全局极小值。所以我们采用最大似然法。

对于每一个样本,出现的概率为:

假设n个样本相互独立,概率相乘。似然函数为:

取对数,变乘法为加法,得到对数似然函数:

这就是我们需要最大化的目标函数。

 

梯度法

如采用梯度法,首先要对w求导:


其中,σ为Sigmoid函数。

最后使用梯度上升来更新权重:

其中α为步长。经过多次迭代后,求得似然函数的最大值及相应的w

 

牛顿法

如采用牛顿法,需要计算二阶导数:

这是一个m×m的矩阵,称为Hessian矩阵,用H表示。

如果定义:

 

则:

根据牛顿迭代公式:

经过有限次迭代,达到收敛。

预测分类

如果用来预测分类,进行如下运算:

如y(i) > 0.5 判定为1,如y(i) < 0.5,判定为0

权重系数与OR的关系

下面讨论一下权重w与OR的关系。

根据OR的定义:

当其他特征值不变的情况下,某x(i)增加1,相应的和xw增加w(i),OR值变为原来的exp(w(i)) 倍。

Python程序代码

from numpy import *
import matplotlib.pyplot as plt
 
# 加载数据
def loadDataSet():
    dataMat = []
    labelMat = []
    fr = open('data/testSet.txt')
    for line in fr.readlines():
        lineArr = line.strip().split(',')
        dataMat.append([1.0float(lineArr[0]), float(lineArr[1])])
        labelMat.append(int(lineArr[2]))
    fr.close()
    return dataMat, labelMat
 
# Sigmoid函数,注意是矩阵运算
def sigmoid(inX):
    return 1.0/(1+exp(-inX))
 
# 梯度上升算法
def gradAscent(dataMatIn, classLabels):
    dataMat = mat(dataMatIn)
    labelMat = mat(classLabels).transpose()
    m,n=shape(dataMat)
    alpha = 0.01
    maxCycles = 500
    weights = mat(ones((n,1)))
    weightsHis = [mat(ones((n,1)))] # 权重的记录,主要用于画图
    for in range(maxCycles):
        = sigmoid(dataMat*weights)
        error = labelMat - h
        weights = weights + alpha*dataMat.transpose()*error
        weightsHis.append(weights)
    return weights,weightsHis
 
 
 
# 简单的随机梯度上升,即一次处理一个样本
def stocGradAscent0(dataMatIn, classLabels):
    dataMat = mat(dataMatIn)
    labelMat = mat(classLabels).transpose()
    m,n=shape(dataMat)
    alpha = 0.01
    weights = mat(ones((n,1)))
    weightsHis = [mat(ones((n,1)))] # 权重的记录,主要用于画图
    for in range(m):
        = sigmoid(dataMat[i]*weights)
        error = labelMat[i] - 
        weights = weights + alpha* dataMat[i].transpose() * error
        weightsHis.append(weights)
    return weights,weightsHis
 
 
# 改进的随机梯度算法
def stocGradAscent1(dataMatIn, classLabels, numIter):
    dataMat = mat(dataMatIn)
    labelMat = mat(classLabels).transpose()
    m,n=shape(dataMat)
    alpha = 0.001
    weights = mat(ones((n,1)))    
    weightsHis = [mat(ones((n,1)))] # 权重的记录,主要用于画图
    for in range(numIter):
        dataIndex = list(range(m))
        for in range(m):
            alpha = 4/(1.0+j+i)+0.001  # 动态调整alpha
            randIndex = int(random.uniform(0,len(dataIndex))) # 随机选择样本
            = sigmoid(dataMat[randIndex]*weights)
            error = labelMat[randIndex]- h
            weights=weights + alpha * dataMat[randIndex].transpose() * error
            del(dataIndex[randIndex])
             
        weightsHis.append(weights)
         
    return weights,weightsHis
 
 
 
# 牛顿法
def newton(dataMatIn, classLabels, numIter):
    dataMat = mat(dataMatIn)
    labelMat = mat(classLabels).transpose()
    m,n=shape(dataMat)
    # 对于牛顿法,如果权重初始值设定为1,会出现Hessian矩阵奇异的情况.
    # 原因未知,谁能告诉我
    # 所以这里初始化为0.01
    weights = mat(ones((n,1)))-0.99 
    weightsHis = [mat(ones((n,1))-0.99)] # 权重的记录,主要用于画图    
    for in range(numIter):
        = eye(m)
        for in range(m):
            = sigmoid(dataMat[i]*weights)
            hh = h[0,0]
            A[i,i] = hh*(1-hh)
         
        error = labelMat - sigmoid(dataMat*weights)
        = dataMat.transpose() * * dataMat # Hessian矩阵                
        weights = weights + H**-1 * dataMat.transpose() * error
         
        weightsHis.append(weights)
         
    return weights,weightsHis
     
     
def plotWeights(w):     
    = array(w)     
    def f1(x):
        return w[x,0,0]
    def f2(x):
        return w[x,1,0]
    def f3(x):
        return w[x,2,0]         
    = len(w)
    = range(0,k,1)
    plt.plot(x,f1(x),'',x,f2(x),'',x,f3(x),'')
    plt.show()
     
 
# 画出分类边界
def plotBestFit(wei):
    weights = wei.getA()
    dataMat, labelMat = loadDataSet()
    dataArr = array(dataMat)
    = shape(dataArr)[0]
    xcord1=[]
    ycord1=[]
    xcord2=[]
    ycord2=[]
    for in range(n):  
        if int(labelMat[i])==1:
            xcord1.append(dataArr[i,1])
            ycord1.append(dataArr[i,2])
        else:
            xcord2.append(dataArr[i,1])
            ycord2.append(dataArr[i,2])
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.scatter(xcord1, ycord1, s=30, c='red', marker='s')
    ax.scatter(xcord2, ycord2, s=30, c='green')
    = arange(-3.0,3.0,0.1)
    y=(-weights[0]-weights[1]*x)/weights[2]
    ax.plot(x,y)
    plt.xlabel('x1')
    plt.ylabel('x2')
    plt.show()
 
# 测试    
data, labels = loadDataSet()
#weights,weightsHis = gradAscent(data, labels)
#weights0, weightsHis0 = stocGradAscent0(data, labels)
#weights1, weightsHis1 = stocGradAscent1(data, labels, 500)
weights3, weightsHis3 = newton(data, labels, 10)
 
plotBestFit(weights3)
print(weights3)
plotWeights(weightsHis3)
 
 

运行结果:

 
1、梯度法迭代500次的分类边界及权重收敛情况


2、随机梯度法迭代500次的分类边界及权重收敛情况



3、牛顿法迭代10次的分类边界及权重收敛情况,可以牛顿法要快很多。


转载于:http://blog.sina.com.cn/s/blog_44befaf60102wbbr.html
 
 

自己动手写Logistic回归算法的更多相关文章

  1. Logistic回归算法梯度公式的推导

    最近学习Logistic回归算法,在网上看了许多博文,笔者觉得这篇文章http://blog.kamidox.com/logistic-regression.html写得最好.但其中有个关键问题没有讲 ...

  2. 机器学习之Logistic 回归算法

    1 Logistic 回归算法的原理 1.1 需要的数学基础 我在看机器学习实战时对其中的代码非常费解,说好的利用偏导数求最值怎么代码中没有体现啊,就一个简单的式子:θ= θ - α Σ [( hθ( ...

  3. 机器学习之logistic回归算法与代码实现原理

    Logistic回归算法原理与代码实现 本文系作者原创,转载请注明出处:https://www.cnblogs.com/further-further-further/p/10033567.html ...

  4. 机器学习算法-logistic回归算法

    Logistic回归算法调试 一.算法原理 Logistic回归算法是一种优化算法,主要用用于只有两种标签的分类问题.其原理为对一些数据点用一条直线去拟合,对数据集进行划分.从广义上来讲这也是一种多元 ...

  5. 机器学习算法( 五、Logistic回归算法)

    一.概述 这会是激动人心的一章,因为我们将首次接触到最优化算法.仔细想想就会发现,其实我们日常生活中遇到过很多最优化问题,比如如何在最短时间内从A点到达B点?如何投入最少工作量却获得最大的效益?如何设 ...

  6. matlib实现logistic回归算法(序一)

    数据下载:http://archive.ics.uci.edu/ml/datasets/Adult 数据描述:http://archive.ics.uci.edu/ml/machine-learnin ...

  7. logistic回归算法及其matlib实现

    一般来说,回归不用在分类问题上,因为回归是连续型模型,而且受噪声影响比较大.如果非要使用回归算法,可以使用logistic回归. logistic回归本质上是线性回归,只是在特征到结果的映射中多加入了 ...

  8. 《转》Logistic回归 多分类问题的推广算法--Softmax回归

    转自http://ufldl.stanford.edu/wiki/index.php/Softmax%E5%9B%9E%E5%BD%92 简介 在本节中,我们介绍Softmax回归模型,该模型是log ...

  9. Logistic回归 python实现

    Logistic回归 算法优缺点: 1.计算代价不高,易于理解和实现2.容易欠拟合,分类精度可能不高3.适用数据类型:数值型和标称型 算法思想: 其实就我的理解来说,logistic回归实际上就是加了 ...

随机推荐

  1. leetcode 383. Ransom Note

    
Given
 an 
arbitrary
 ransom
 note
 string 
and 
another 
string 
containing 
letters from
 all 
th ...

  2. 关于Entity Framework使用的简单例子

    一.创建Code First模型 1.创建工程,这里我使用的是以.NET 4.0为目标的实体Web应用程序 2.安装Entity Framework 确保已安装NuGet,选择NuGet套件管理员&g ...

  3. spark编写word count

    创建SparkContext对象的时候需要传递SparkConf对象,SparkConf至少需要包含spark.master和spark.app.name这两个参数,不然的话程序不能正常运行 obje ...

  4. NET基础(4):引用类型和值类型

    CLR支持两种类型:引用类型和值类型.虽然FCL的大多数类型都是引用类型,但程序员用的最多的还是引用类型,引用类型总是从托管堆分配,c#的new操作符返回对象内存地址-即指向对象数据的内存地址.使用引 ...

  5. JAVA:通过poi读取excel

    POI是一个apache开源的jar包,可以通过搜索 java POI找到官网,并下载开发包. 包含的功能: 可以读取excel2003,2007,2010等. 读取excel2007/2010的代码 ...

  6. Windows Server 2008 任务计划无法自动运行的解决办法

    问题:编写的bat脚本,直接执行,成功:但是在任务管理器中配置该任务,运行不成功,结果显示为:0x1,系统环境为 Windows Server 2008. 分析:bat任务没有调用执行. 解决方案: ...

  7. Dapper

    前一段做一个技术分享关于dapper的,现在再总结一下,也好长时间没有更新博客了--,用到的东西 Dapper.AutoFac .AutoMapper.FluentValidation: 下面说一下D ...

  8. 【C#进阶】多播委托和委托数组像是一回事~

    这个MathOperation类有三静态方法,参数都是double,并且没有返回值,考虑用Action<>() 这种预定义的委托哦 class MathOperations { publi ...

  9. JdbcUtils.java

    package com.jdbc.dbutils; import java.lang.reflect.Field; import java.sql.Connection; import java.sq ...

  10. 2.多线程-GCD

    1.基本概念 同步任务:在当前线程按顺序执行,不开启新的线程 异步任务:有开新线程的欲望   串行队列:一个一个执行 并行队列:多个任务同时执行 --------------------------- ...