假设一个数据集有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. C# EF增删改查

    1.增 //1.创建一个EF数据上下文对象 MyDBEntities context=new MyDBEntities(); //2.将要添加的数据,封装成对象 Users user = new Us ...

  2. Python开发【前端】:HTML

    HTML HTML是英文Hyper Text Mark-up Language(超文本标记语言)的缩写,他是一种制作万维网页面标准语言(标记).相当于定义统一的一套规则,大家都来遵守他,这样就可以让浏 ...

  3. Static方法在多线程环境下的运行

    最近看了Jfinal 一致对model的那个static final dao有些疑惑,全局一个实例安全吗?同时也出了一个疑惑,静态方法执行会有并发影响吗?看代码 StaticThread.java p ...

  4. Spring操作指南-针对JDBC配置声明式事务管理(基于注解)

  5. expdp ORA-31693 ORA-31617 ORA-19505 ORA-27037

    使用expdp并行导出数据的时候报如下错误: Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64b ...

  6. ADO.NET、NHibernate和Entity Framework的比较

    ---原文地址:http://www.xuebuyuan.com/2162973.html 1,ADO.NET属于传统的数据访问工具,开发的时候需要我们手动去编写操作数据库的各种操作,当然性能也就不用 ...

  7. MATLAB入门教程

    MATLAB入门教程   1.MATLAB的基本知识 1-1.基本运算与函数    在MATLAB下进行基本数学运算,只需将运算式直接打入提示号(>>)之後,并按入Enter键即可.例如: ...

  8. Java Timer定时器时,每次重复执行了两次任务的解决方案

    web.xml监听配置 com.numenzq.mc.service.impl.TimerListener TimerListener类 public class TimerListener impl ...

  9. 无限分页//////////////zz

    由于网页的执行都是单线程的,在JS执行的过程中,页面会呈现阻塞状态.因此,如果JS处理的数据量过大,过程复杂,可能会造成页面的卡顿.传统的数据展现都以分页的形式,但是分页的效果并不好,需要用户手动点击 ...

  10. CSRF 攻击

    一.CSRF是什么? CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSR ...