【机器学习算法实现】logistic回归__基于Python和Numpy函数库

【机器学习算法实现】系列文章将记录个人阅读机器学习论文、书籍过程中所碰到的算法,每篇文章描述一个具体的算法、算法的编程实现、算法的具体应用实例。争取每个算法都用多种语言编程实现。所有代码共享至github:https://github.com/wepe/MachineLearning-Demo 
   欢迎交流指正!

(2)logistic回归__基于Python和Numpy函数库

1、算法简介

本文的重点放在算法的工程实现上,关于算法的原理不具体展开,logistic回归算法很简单,可以看看Andrew Ng的视频:https://class.coursera.org/ml-007,也可以看看一些写得比较好的博文:洞庭之子的博文。下面我只列出一些个人认为重要的点。

回归的概念:假设有一些数据点,我们用一条直线对这些点进行拟合,这个拟合过程就称作回归。

logistic回归算法之所以称作“logistic”,是因为它运用了logistic函数,即sigmoid函数

logistic回归算法一般用于二分类问题(当然也可以多类别,后面会讲)。

logistic回归的算法思想:

用上面的图来分析,每个O或X代表一个特征向量,这里是二维的,可以表示成向量形式x=(x1,x2)。用logistic回归进行分类的主要思想就是根据这些数据集(上面的点),对分类边界(上面的直线)建立回归公式,前面提到了,“回归”所做的其实就是拟合,所以logistic回归就是要找到最佳的拟合参数

在上图的例子,拟合参数可以表示为向量形式 Θ=( Θ1, Θ2),根据现有的数据集(即训练集)我们可以训练得出这个参数 Θ,之后每输入一个测试样本(x1,x2),就计算Θ1*x1+Θ2*x2,将这个和作为sigmoid函数的输入,根据sigmoid函数的输出来预测该测试样本所属的类别。用公式表述:

以上就是logistic回归的思想,重点在于怎么根据训练数据求得最佳拟合参数Θ?这可以用最优化算法来求解,比如常用的梯度上升算法,关于梯度上升算法这里也不展开,同样可以参考上面推荐的博文。

所谓的梯度,就是函数变化最快的方向,我们一开始先将参数Θ设为全1,然后在算法迭代的每一步里计算梯度,沿着梯度的方向移动,以此来改变参数Θ,直到Θ的拟合效果达到要求值或者迭代步数达到设定值。Θ的更新公式:

alpha是步长,一系列推导后:

这个公式也是下面写代码所用到的。

后话:理解logistic回归之后可以发现,其实它的本质是线性回归,得到的过程跟线性回归是一样的,只不过后面又将作为logistic函数的输入,然后再判断类别。

2、工程实例

logistic回归一般用于二分类问题,比如判断一封邮件是否为垃圾邮件,判断照片中的人是男是女,预测一场比赛输还是赢......当然也可以用于多分类问题,比如k类别,就进行k次logistic回归。

我的前一篇文章:kNN算法__手写识别 讲到用kNN算法识别数字0~9,这是个十类别问题,如果要用logistic回归,得做10次logistic回归,第一次将0作为一个类别,1~9作为另外一个类别,这样就可以识别出0或非0。同样地可以将1作为一个类别,0、2~9作为一个类别,这样就可以识别出1或非1........

本文的实例同样是识别数字,但为了简化,我只选出0和1的样本,这是个二分类问题。下面开始介绍实现过程:

(1)工程文件说明

在我的工程文件目录下,有训练样本集train和测试样本集test,源代码文件命名为logistic regression.py

训练样本集train和测试样本集test里面只有0和1样本:

logistic
regression.py实现的功能:从train里面读取训练数据,然后用梯度上升算法得出参数Θ,接着用参数Θ来预测test里面的测试样本,同时计算错误率。

(2)源代码解释

  • loadData(direction)函数

实现的功能就是从文件夹里面读取所有训练样本,每个样本(比如0_175.txt)里有32*32的数据,程序将32*32的数据整理成1*1024的向量,这样从每个txt文件可以得到一个1*1024的特征向量X,而其类别可以从文件名“0_175.txt”里截取0出来。因此,从train文件夹我们可以获得一个训练矩阵m*1024和一个类别向量m*1,m是样本个数。

def loadData(direction):
    trainfileList=listdir(direction)
    m=len(trainfileList)
    dataArray= zeros((m,1024))
    labelArray= zeros((m,1))
    for i in range(m):
        returnArray=zeros((1,1024))  #每个txt文件形成的特征向量
        filename=trainfileList[i]
        fr=open('%s/%s' %(direction,filename))
        for j in range(32):
            lineStr=fr.readline()
            for k in range(32):
                returnArray[0,32*j+k]=int(lineStr[k])
        dataArray[i,:]=returnArray   #存储特征向量

        filename0=filename.split('.')[0]
        label=filename0.split('_')[0]
        labelArray[i]=int(label)     #存储类别
    return dataArray,labelArray
    

代码里面用到python os模块里的listdir(),用于从文件夹里读取所有文件,返回的是列表。

python里的open()函数用于打开文件,之后用readline()一行行读取

  • sigmoid(inX)函数
<span style="font-size:18px;">def sigmoid(inX):
    return 1.0/(1+exp(-inX))</span>
  • gradAscent(dataArray,labelArray,alpha,maxCycles)函数

用梯度下降法计算得到回归系数,alpha是步长,maxCycles是迭代步数。

<span style="font-size:18px;">def gradAscent(dataArray,labelArray,alpha,maxCycles):
    dataMat=mat(dataArray)    #size:m*n
    labelMat=mat(labelArray)      #size:m*1
    m,n=shape(dataMat)
    weigh=ones((n,1))
    for i in range(maxCycles):
        h=sigmoid(dataMat*weigh)
        error=labelMat-h    #size:m*1
        weigh=weigh+alpha*dataMat.transpose()*error
    return weigh</span>

用到numpy里面的mat,矩阵类型。shape()用于获取矩阵的大小。

这个函数返回参数向量Θ,即权重weigh

  • classfy(testdir,weigh)函数

分类函数,根据参数weigh对测试样本进行预测,同时计算错误率

def classfy(testdir,weigh):
    dataArray,labelArray=loadData(testdir)
    dataMat=mat(dataArray)
    labelMat=mat(labelArray)
    h=sigmoid(dataMat*weigh)  #size:m*1
    m=len(h)
    error=0.0
    for i in range(m):
        if int(h[i])>0.5:
            print int(labelMat[i]),'is classfied as: 1'
            if int(labelMat[i])!=1:
                error+=1
                print 'error'
        else:
            print int(labelMat[i]),'is classfied as: 0'
            if int(labelMat[i])!=0:
                error+=1
                print 'error'
    print 'error rate is:','%.4f' %(error/m)
  • digitRecognition(trainDir,testDir,alpha=0.07,maxCycles=10)函数

整合上面的所有函数,调用这个函数进行数字识别,alpha和maxCycles有默认形参,这个可以根据实际情况更改。

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

用loadData函数从train里面读取训练数据,接着根据这些数据,用gradAscent函数得出参数weigh,最后就可以用拟合参数weigh来分类了。

3、试验结果

工程文件可以到这里下载:github地址

运行logistic regression.py,采用默认形参:alpha=0.07,maxCycles=10,看下效果,错误率0.0118

>>> digitRecognition('train','test')

改变形参,alpah=0.01,maxCycles=50,看下效果,错误率0.0471

>>> digitRecognition('train','test',0.01,50)

这两个参数可以根据实际情况调整

时间: 2024-12-21 17:14:11

【机器学习算法实现】logistic回归__基于Python和Numpy函数库的相关文章

【机器学习算法实现】kNN算法__手写识别——基于Python和NumPy函数库

[机器学习算法实现]系列文章将记录个人阅读机器学习论文.书籍过程中所碰到的算法,每篇文章描述一个具体的算法.算法的编程实现.算法的具体应用实例.争取每个算法都用多种语言编程实现.所有代码共享至github:https://github.com/wepe/MachineLearning-Demo     欢迎交流指正! (1)kNN算法_手写识别实例--基于Python和NumPy函数库 1.kNN算法简介 kNN算法,即K最近邻(k-NearestNeighbor)分类算法,是最简单的机器学习算

复习机器学习算法:Logistic 回归

区别于线性回归,不是把每个特征直接乘以系数,而是用一个S型函数(Logistic函数).如下: 使用这种形式函数的原因(概率.求导). 代价函数,也不是线性回归中的误差平方和,而是基于对数似然函数,如下: 单个样本的后验概率为:(y = 0, 1) 类似于二项分布的概率密度函数. 整个样本集的后验概率: 对数似然函数对于代价函数,如下: 梯度下降法求解,对上面的代价函数求导,如下: 误差乘以对应的属性值,再求和.形式和线性回归一致,解释了为何设计这样的S型函数和代价函数.这样的梯度下降法的计算量

《机器学习实战》Logistic回归算法(1)

===================================================================== <机器学习实战>系列博客是博主阅读<机器学习实战>这本书的笔记也包含一些其他python实现的机器学习算法 算法实现均采用python github 源码同步:https://github.com/Thinkgamer/Machine-Learning-With-Python ==================================

机器学习算法的基本知识(使用Python和R代码)

本篇文章是原文的译文,然后自己对其中做了一些修改和添加内容(随机森林和降维算法).文章简洁地介绍了机器学习的主要算法和一些伪代码,对于初学者有很大帮助,是一篇不错的总结文章,后期可以通过文中提到的算法展开去做一些实际问题. Google的自驾车和机器人得到了很多新闻,但公司的真正未来是机器学习,这种技术使计算机变得更智能,更个性化.-Eric Schmidt (Google Chairman) 我们可能生活在人类历史上最具影响力的时期--计算从大型主机到PC移动到云计算的时期. 但是使这段时期有

机器学习(4)之Logistic回归

机器学习(4)之Logistic回归 1. 算法推导 与之前学过的梯度下降等不同,Logistic回归是一类分类问题,而前者是回归问题.回归问题中,尝试预测的变量y是连续的变量,而在分类问题中,y是一组离散的,比如y只能取{0,1}. 假设一组样本为这样如图所示,如果需要用线性回归来拟合这些样本,匹配效果会很不好.对于这种y值只有{0,1}这种情况的,可以使用分类方法进行. 假设,且使得 其中定义Logistic函数(又名sigmoid函数): 下图是Logistic函数g(z)的分布曲线,当z

【机器学习基础】Logistic回归基础

soft binary classification Logistics回归模型要解决的是分类问题,在之前的二元分类问题中,我们将数据分成正例和负例,但是像PLA算法一样,用单位阶跃函数来处理的这种瞬间跳跃的过程有时很难处理.于是,我们希望能得到正例的概率值是多少. logistic regression的假设 我们在PLA和线性回归算法中都用数据的加权来计算一个分数s,在logistic回归中,我们用sigmoid函数来将这个分数s转化成0到1的概率值. 所以,用下面的h(x)来表示一个假设,

机器学习之线性回归---logistic回归---softmax回归

1 摘要 本报告是在学习斯坦福大学机器学习课程前四节加上配套的讲义后的总结与认识.前四节主要讲述了回归问题,回归属于有监督学习中的一种方法.该方法的核心思想是从连续型统计数据中得到数学模型,然后将该数学模型用于预测或者分类.该方法处理的数据可以是多维的. 讲义最初介绍了一个基本问题,然后引出了线性回归的解决方法,然后针对误差问题做了概率解释.之后介绍了logistic回归.最后上升到理论层次,提出了一般回归. 2 问题引入 这个例子来自http://www.cnblogs.com/LeftNot

机器学习实战 logistic回归

logistic回归 梯度上升法 import numpy as np """ function: 加载数据 parameter: 无 returns: dataMat - 数据集 labelMat - 标签集 """ def loadDataSet(): dataMat = []#数据集 labelMat = []#标签集 fr = open('testSet.txt') for line in fr.readlines(): lineArr

Python机器学习之NumPy函数库

NumPy函数库是Python开发环境的一个独立模块,而且大多数Python发行版没有默认安装NumPy函数库,因此在安装Python之后必须单独安装NumPy函数库. 在Python shell开发环境中输入下列命令: >>> from numpy import * 如果没报错就表明NumPy函数库正确安装. 上述命令将NumPy函数库中的所有模块引入当前的命名空间. 然后在Python shell开发环境中输入下述命令: >>> random.rand(4,4) a