欢迎直接到我的博客查看最近文章:www.pkudodo.com。更新会比较快,评论回复我也能比较快看见,排版也会更好一点。

原始blog链接: http://www.pkudodo.com/2018/12/03/1-6/

前言

《统计学习方法》一书在前几天正式看完,由于这本书在一定程度上对于初学者是有一些难度的,趁着热乎劲把自己走过的弯路都写出来,后人也能走得更顺畅一点。

以下是我的github地址,其中有《统计学习方法》书中所有涉及到的算法的实现,也是在写博客的同时编写的。在编写宗旨上是希望所有人看完书以后,按照程序的思路再配合书中的公式,能知道怎么讲所学的都应用上。(有点自恋地讲)程序中的注释可能比大部分的博客内容都多。希望大家能够多多捧场,如果可以的话,为我的github打颗星,也能让更多的人看到。

github:

GitHub|手写实现李航《统计学习方法》书中全部算法

相关博文:

  1. 统计学习方法|感知机原理剖析及实现
  2. 统计学习方法|K近邻原理剖析及实现
  3. 统计学习方法|朴素贝叶斯原理剖析及实现
  4. 统计学习方法|决策树原理剖析及实现
  5. 统计学习方法|逻辑斯蒂原理剖析及实现

正文

逻辑斯蒂回归的直观理解

我们还记不记得感知机一章中给出的这张图?还记得感知机是怎么工作的吗?

感知机生成一个超平面(在二维中表现为一条直线),这个超平面可以将图中的两类点区分开。像下面这张图,图中的所有直线都可以作为感知机的超平面(因为它们都能把训练集中的点完美地分开)。

但是感知机存在一个很重要的问题,我们只用sign(w*x+b)输出的+1和-1来判断点的类别是不是太简单了?是不是有点生硬的感觉。

这么简单的判别方式真的会很有效吗?

当然了,虽然我们已经程序测试过正确率很高,但总是让人有点担心是否在很多情况下都能很好地工作。事实上我们从小到大一直会听到一些升学考试差一分两分的例子,那么差一分和高一分的学生真的就是天壤之别吗?感知器也是如此:在超平面左侧距离0.001的点和右边0.001距离的点输出就是+1和-1这天壤之别的差距真的合适吗?

此外我们也知道机器学习中通常会对目标函数进行微分进而梯度下降,但我们看上面这张图。很明显x=0是跳跃间断点,因此sign是一条不光滑的函数,没有办法进行微分。emmm......咦?那我记得感知器用了梯度下降,它是怎么去梯度下降的?

我们回忆一下感知器的梯度下降方式,确实用了梯度下降,但是发现没有,它把sign的壳子去掉了,对sign内部进行梯度下降,相对于其他能直接微分的算法来说,感知器的这种方式确实有点不太好。

因此既然我们要对感知器进行优化,那么上文的这两个主要的缺陷咱们得想想法子看看能不能弥补。我们首先试试解决第一个问题:

1.怎么解决极小距离差别带来的+1和-1的天壤之别?

在逻辑斯蒂回归中大致思想与感知器相同,但在输出+1与-1之间存在一些差别。在朴素贝叶斯中我们提到过P(Y|X),它表示在给定X条件下,Y发生的概率。逻辑斯蒂也使用了同样的概念,它使用p(Y=-1|X)和p(Y=1|X)来表示该样本分别为-1或1的概率(实际上逻辑斯蒂并非强制要求标签必须为1或-1,可以用任意标签来表示)。这样当再出现样本X1距离为-0.001时,可能P(Y=1|X1)=0.49,P(Y=0|X1)=0.51,那么我们觉得X1为0的概率更大一点,但我们同时也清楚程序可能并不太确定X1一定为0。

使用概率作为输出结果使得样本在距离很小的差别下不再强制地输出+1和-1这两种天壤之别的结果,而是通过概率的方式告诉你结果可能是多少,同时也告诉你预测的不确信程度。这样子看起来让人比较安心一点不是吗?

2.怎么让最终的预测式子可微呢?

虽然无法微分并不会阻碍感知器的正常工作(事实上只是避开了sign),但对于很多场合都需要微分的机器学习来说,能找到一个可以微分的最终式子是很重要的。为了解决第一个问题我们提出了一种概率输出模型,那么感知器的sign也需要被随之替换为一种能输出概率大小的函数。具体函数在下文中详细讲解,其中值得高兴的是,我们找到的概率输出式子是平滑的,可微的,所以第二个问题也就迎刃而解了。

逻辑斯蒂回归的数学角度(配合《统计学习方法》食用更佳)

与感知器一样,我们先不管内部怎么工作,最好能够得到一个函数f(x),我们将样本x放进去以后,它告诉我们属于1的概率是多少。比如说f(y=1|x)=0.2,f(y=0|x)=0.8,我们就知道该样本的标签大概率是0。总结一下也就是分别比较两种类别的概率大小,概率大的那一方则作为预测类别进行输出。f函数的定义如下图所示。

下图就是f(wx+b)的图像,我们假设一下点X在超平面右边,那么距离应当为正,如果距离无穷大时,exp(w*x + b)无穷大,P(Y=1|x)=1,也就是概率为1,表极其确信。如果wx+b是一个很接近0的数,exp(w*x + b)接近1,P(Y=1|x)=0.5,表示两边都有可能,不太确定。我们对于每一个样本点分别计算属于两类的概率,概率较大的一方作为预测的输出。

既然模型有了,那么就需要计算参数以此来得到划分的超平面。在计算参数上一般使用最大似然函数,关于最大似然函数的介绍可以在网上进行相关浏览。由于我们使用的sigmod函数很光滑,是可微函数,因此可以直接对似然函数求导,进行梯度下降找到参数的最优点。

关于似然函数关于W的求导式可以看下图:

结语:逻辑斯蒂在思想上与感知器极为相近,很多细节问题在感知器中已有说明因此在本文中并未详细展开。如果对部分地方有疑问可查看感知器一章节,此外也可以评论或邮箱的形式联系我。

贴代码:(建议去本文最上方的github链接下载,有书中所有算法的实现以及详细注释)

# coding=utf-8
# Author:Dodo
# Date:2018-11-27
# Email:lvtengchao@pku.edu.cn
# Blog:www.pkudodo.com'''
数据集:Mnist
训练集数量:60000
测试集数量:10000
------------------------------
运行结果:正确率:98.91%运行时长:59s
'''import time
import numpy as npdef loadData(fileName):'''加载Mnist数据集:param fileName:要加载的数据集路径:return: list形式的数据集及标记'''# 存放数据及标记的listdataList = []; labelList = []# 打开文件fr = open(fileName, 'r')# 将文件按行读取for line in fr.readlines():# 对每一行数据按切割福','进行切割,返回字段列表curLine = line.strip().split(',')# Mnsit有0-9是个标记,由于是二分类任务,所以将标记0的作为1,其余为0# 验证过<5为1 >5为0时正确率在90%左右,猜测是因为数多了以后,可能不同数的特征较乱,不能有效地计算出一个合理的超平面# 查看了一下之前感知机的结果,以5为分界时正确率81,重新修改为0和其余数时正确率98.91%# 看来如果样本标签比较杂的话,对于是否能有效地划分超平面确实存在很大影响if int(curLine[0]) == 0:labelList.append(1)else:labelList.append(0)#存放标记#[int(num) for num in curLine[1:]] -> 遍历每一行中除了以第一哥元素(标记)外将所有元素转换成int类型#[int(num)/255 for num in curLine[1:]] -> 将所有数据除255归一化(非必须步骤,可以不归一化)dataList.append([int(num)/255 for num in curLine[1:]])# dataList.append([int(num) for num in curLine[1:]])#返回data和labelreturn dataList, labelListdef predict(w, x):'''预测标签:param w:训练过程中学到的w:param x: 要预测的样本:return: 预测结果'''#dot为两个向量的点积操作,计算得到w * xwx = np.dot(w, x)#计算标签为1的概率#该公式参考“6.1.2 二项逻辑斯蒂回归模型”中的式6.5P1 = np.exp(wx) / (1 + np.exp(wx))#如果为1的概率大于0.5,返回1if P1 >= 0.5:return 1#否则返回0return 0def logisticRegression(trainDataList, trainLabelList, iter = 200):'''逻辑斯蒂回归训练过程:param trainDataList:训练集:param trainLabelList: 标签集:param iter: 迭代次数:return: 习得的w'''#按照书本“6.1.2 二项逻辑斯蒂回归模型”中式6.5的规则,将w与b合在一起,#此时x也需要添加一维,数值为1#循环遍历每一个样本,并在其最后添加一个1for i in range(len(trainDataList)):trainDataList[i].append(1)#将数据集由列表转换为数组形式,主要是后期涉及到向量的运算,统一转换成数组形式比较方便trainDataList = np.array(trainDataList)#初始化w,维数为样本x维数+1,+1的那一位是b,初始为0w = np.zeros(trainDataList.shape[1])#设置步长h = 0.001#迭代iter次进行随机梯度下降for i in range(iter):#每次迭代冲遍历一次所有样本,进行随机梯度下降for j in range(trainDataList.shape[0]):#随机梯度上升部分#在“6.1.3 模型参数估计”一章中给出了似然函数,我们需要极大化似然函数#但是似然函数由于有求和项,并不能直接对w求导得出最优w,所以针对似然函数求和#部分中每一项进行单独地求导w,得到针对该样本的梯度,并进行梯度上升(因为是#要求似然函数的极大值,所以是梯度上升,如果是极小值就梯度下降。梯度上升是#加号,下降是减号)#求和式中每一项单独对w求导结果为:xi * yi - (exp(w * xi) * xi) / (1 + exp(w * xi))#如果对于该求导式有疑问可查看我的博客 www.pkudodo.com#计算w * xi,因为后式中要计算两次该值,为了节约时间这里提前算出#其实也可直接算出exp(wx),为了读者能看得方便一点就这么写了,包括yi和xi都提前列出了wx = np.dot(w, trainDataList[j])yi = trainLabelList[j]xi = trainDataList[j]#梯度上升w +=  h * (xi * yi - (np.exp(wx) * xi) / ( 1 + np.exp(wx)))#返回学到的wreturn wdef test(testDataList, testLabelList, w):'''验证:param testDataList:测试集:param testLabelList: 测试集标签:param w: 训练过程中学到的w:return: 正确率'''#与训练过程一致,先将所有的样本添加一维,值为1,理由请查看训练函数for i in range(len(testDataList)):testDataList[i].append(1)#错误值计数errorCnt = 0#对于测试集中每一个测试样本进行验证for i in range(len(testDataList)):#如果标记与预测不一致,错误值加1if testLabelList[i] != predict(w, testDataList[i]):errorCnt += 1#返回准确率return 1 - errorCnt / len(testDataList)if __name__ == '__main__':start = time.time()# 获取训练集及标签print('start read transSet')trainData, trainLabel = loadData('../Mnist/mnist_train.csv')# 获取测试集及标签print('start read testSet')testData, testLabel = loadData('../Mnist/mnist_test.csv')# 开始训练,学习wprint('start to train')w = logisticRegression(trainData, trainLabel)#验证正确率print('start to test')accuracy = test(testData, testLabel, w)# 打印准确率print('the accuracy is:', accuracy)# 打印时间print('time span:', time.time() - start)

统计学习方法|逻辑斯蒂原理剖析及实现相关推荐

  1. 统计学习方法读书笔记(六)-逻辑斯蒂回归与最大熵模型(迭代尺度法(IIS))

    全部笔记的汇总贴:统计学习方法读书笔记汇总贴 逻辑斯谛回归 (logistic regression )是统计学习中的经典分类方法.最大熵是概率模型学习的一个准则,将其推广到分类问题得到最大熵模型(m ...

  2. 逻辑斯蒂回归_逻辑斯蒂回归详细解析 | 统计学习方法学习笔记 | 数据分析 | 机器学习...

    本文包括: 重要概念 逻辑斯蒂回归和线性回归 二项逻辑斯谛回归模型 逻辑斯蒂回顾与几率 模型参数估计 多项逻辑斯谛回归 其它有关数据分析,机器学习的文章及社群 1.重要概念: 在正式介绍逻辑斯蒂回归模 ...

  3. 李航统计学习方法 Chapter6 逻辑斯蒂回归

    第6章 逻辑斯蒂回归和最大熵模型 逻辑斯谛回归(LR)是经典的分类方法 1.逻辑斯谛回归模型是由以下条件概率分布表示的分类模型.逻辑斯谛回归模型可以用于二类或多类分类. P(Y=k∣x)=exp⁡(w ...

  4. 逻辑斯蒂回归(logistic regression)原理小结

    逻辑斯蒂回归(logistic regression)原理小结 1. 模型函数 2. 损失函数 3. 学习算法 4. 加正则项的逻辑斯蒂回归 5. 多项逻辑斯蒂回归 6. 模型综合评价 7. 二分类 ...

  5. 细讲逻辑斯蒂回归与朴素贝叶斯、最大熵原理的爱恨交织(长文)

    好早之前就发现逻辑斯蒂回归好像和朴素贝叶斯里面的后验概率公式还有最大似然.信息熵.交叉熵.伯努利分布.回归分析.几率(odds)等等有着千丝万缕CZFZ(错综复杂).PSML(扑朔迷离)的关系.一直感 ...

  6. 逻辑斯蒂回归原理(二分类、多分类)

    文章目录 逻辑斯蒂分布 二项逻辑回归模型 模型参数估计 多项逻辑斯蒂回归 逻辑斯蒂分布 逻辑斯蒂分布假设X是连续随机变量,且分布函数.密度函数如下: F(x)=P(X⩽x)=11+exp⁡(−(x−μ ...

  7. 对逻辑斯蒂回归的一些细节剖析

    首先声明:本博客的写作思路是对机器学习的一些基本算法做一些通俗性的灵活理解,以及对一些细节的进行简单剖析,还有记录本人在使用算法时的一些小经验小感想.本人一般不会对基本公式做大量推导,也不会写的太正式 ...

  8. 细讲逻辑斯蒂回归与朴素贝叶斯、最大熵原理的爱恨交织(五)

    第五节:分类器中的天真小弟 -- 朴素贝叶斯 朴素贝叶斯文本分类模型 考虑如下文本分类模型:P(yi,di)P(y_i, d_i)P(yi​,di​) 表示一篇文章以及它的 label 的联合概率.d ...

  9. 逻辑斯蒂回归原理及其概率计算

    目录 逻辑斯蒂回归 原理过程 预测函数 原理代码实现 例子 最大似然估计 原理 逻辑斯蒂回归概率计算 导包 手动计算 多分类概率计算 逻辑斯蒂回归 利用Logistics回归进行分类的主要思想是:根据 ...

最新文章

  1. NSDate NSCalendar NSString之间的故事以及转换
  2. 查看cananl是否启动_振动筛无法启动的3大原因及8大注意事项
  3. android otp接口,Android-高通平台调试camera的OTP参数
  4. easybcd 支持 windows 10 和 ubuntu 14.04 双系统启动
  5. 永久免费!原型设计利器摹客RP正式发布
  6. 床位的摆放有五大禁忌
  7. 远程服务器登入信息,远程登录服务器查看信息
  8. 边缘设备上的实时AI虫害消除:入门
  9. 爬虫初窥day1:urllib
  10. windows10-seaslog安装笔记
  11. cmos和ttl_TTL和CMOS有什么区别?
  12. 微信小程序直播是怎么做的
  13. 计算机组装维护课件,计算机组装与维护课件(全)
  14. 自动定时执行任务、定时任务执行的几种实现方法
  15. 在东京,月薪25万日元能过上什么样的日子啊
  16. Oliver的成绩(vector)
  17. python字典求平均值_查找字典中值的平均值
  18. 十年BAT架构履历,铁柱磨针成188页Java核心知识点
  19. 默纳克调试说明书_默纳克NICE3000调试使用说明(修改版)
  20. 美丽的汤 xlsx格式 csv 格式

热门文章

  1. LeetCode Restore IP Addresses(回溯法)
  2. Gallery的使用(一)
  3. HDU1002 Problem II(大数相加)(C++题解)
  4. SmartSVN11 Mac版 注册码序列号
  5. Luogu P1002 过河卒(DP)
  6. uva LCD-Display
  7. 一个免费的css编辑器——Free CSS Toolbox
  8. 利用OpenCV的Grabcut()函数实现图像的前景与背景的分割-并对Grabcut()作详细介绍
  9. mysql 并行复制搭建_基于GTID的主从实践系列之④并行复制搭建及测试
  10. mysql 故障处理_MySQL日志故障的处理和分析