文章参考 https://www.cnblogs.com/chamie/p/4876149.html 【Machine Learning in Action --5】逻辑回归(LogisticRegression)从疝气病预测病马的死亡率

文章实例为疝气症预测病马死亡率,实例数据:http://archive.ics.uci.edu/ml/datasets/Horse+Colic


引言

logistic回归,一种广义的线性回归分析模型。常用于做二分类问题(非0即1),但是logsitic回归并不是分类器,是一种概率估计,下文中会做详细解释。


问题提出

给定  个个体 ,对每一组个体求预测值 ,使得  其中  为  维列向量, 中每一个元素都是个体特征,总共  个特征, 取值为0或1。

即是 

对于文章的实例,就是给出300组数据(300个个体),每组数据的  为病马的一些特征,例如年龄,呼吸频率等, 即是病马死亡(0)或病马存活(1)。


logistic函数

上述问题可用拟合的方法进行求解,由于是二分类问题,简单的线性回归  无法满足我们的需求(线性回归的值域为),那么引出了sigmoid函数

sigmoid函数 ,也称作logistic函数,特殊地

图像如图所示,简单可以看出sigmoid函数可以将线性回归  映射到  区间,问题并没有解决, 区间中仍有无限个点,不满足二分类,于是我们规定,这样logistic函数就满足了二分类问题。

值得注意的是,logistic回归并不是分类器,它只是一种概率估计,而是我们硬性的规定了分类标准(即大于0.5最终为1,小于0.5最终为0),于是,对于分类器的某些结果测量评估,logistic回归的结果可能是不理想的。


logistic回归

现在有了回归函数 ,利用回归函数可以得到一组 ,希望 ,即是预测值尽可能的“贴近”精确值,此时定义损失函数(Loss function),用于衡量单个个体的表现情况。

通常损失函数设计为均方误差,即 ,但是在logistic回归中,均方误差可能会产生非凸集(局部最优),于是logistic回归损失函数为:

此损失函数利用最大似然估计得到,,可以看出来损失函数越小表现情况越优秀。

还需要定义一个衡量全体个体表现情况的参量,代价函数(Cost function)

其中  为适当的缩放。可见  是一个凸函数,局部最小即是全体最小。我们的目的就是找到最佳拟合参数  使得  最小。

当然,也可以对  进行寻找极值求解  个方程得到最佳参数 ,然而对于实际问题求解方程是困难的,于是使用迭代法近似。


梯度下降法

常用的迭代法牛顿法、梯度下降法(最速下降法)、共轭迭代法、变尺度迭代法、最小二乘法。

梯度:对于可微的数量场 ,以  为分量的向量场称为  的梯度。

梯度是一个向量,表示某一函数在该点处的方向导数沿着该方向取得最大值,即函数在该点处沿着该方向(此梯度的方向)变化最快,变化率最大。总结一下即是,沿梯度正方向,函数上升最快;沿梯度反方向,函数下降最快。

如图所示,白线部分即为梯度下降过程。

必须注意的是,梯度下降法会遍历局部最低点,达到局部最优解,对于logistic回归, 函数不会出现局部最优,但考虑其他问题时,需谨慎。

假设特征数,由  ,  ,可以得到(推导公式省略):

,,则梯度下降公式为:

,其中  为学习率(即步长)


算法概述

符号说明:

假设特征数 ,迭代次数 

设立初始值 

 //迭代次数

 //计算logistic函数

 //计算梯度,累加

  //梯度下降


算法实现

使用python语言,方便之处在于python丰富强大的第三方库。

“算法概述”模块的实例我假设特征数 ,但实际中特征数会远多于2(例如实例中的21个),那么在算法实现中还需要一个for循环,那么整个算法3层for循环,如果使用python中的numpy库进行向量化运算,便可以减少运算时间。

例如,随机的1000维的行向量相加,for循环与numpy的时间比:

import numpy as np
import time
a = np.random.random((1000, 1))
b = np.random.random((1000, 1))
c = np.zeros((1000, 1))
start = time.perf_counter()
for i in range(a.shape[0]): #for-loopc[i] = a[i] + b[i]
end = time.perf_counter()
d = a + b #numpy
ennd = time.perf_counter()
print((end - start) * 1000, (ennd - end) * 1000)
'''
①2.272844999999996 0.00933100000000131
②2.300835000000001 0.008863999999997318
③2.272377999999992 0.008397000000021082
'''

可以清楚的看到,运行3次得到的结果都是numpy向量运算比for循环时间快了至少200倍。

这种巨大差异的原因,易于理解就是因为numpy是C语言写的,python是解释型语言,C是编译型语言,通常运算下C是比python快的。若探究巨大差异的本质的话,就是numpy可能会利用SIMD,超线程/多线程CPU,GPU进行向量化运算。(个人理解,有误请指出)

import numpy as np'''
logistic函数
参数为ndarray的1维向量
'''
def sigmoid(x):return 1 / (1 + np.exp(-1 * x))'''
logistic回归
参数为训练集(x,y),x为(m,n)维向量,y为(m,1)维向量
'''
def logisticRegression(x, y):alpha = 0.001 #alpha学习率cnt = 1000 #迭代次数n = x.shape[1] #特征个数w = np.ones(n)。reshape((n,1)) #初始化w向量,n阶列向量b = 0 #初始化bwhile cnt != 0:theta = sigmoid(np.dot(x, w) + b) #计算theta向量,m阶列向量dz = theta - y dw = 1 / n * np.dot(x.T, dz) #计算梯度,n阶列向量db = 1 / n * np.sum(dz)w = w - alpha * dw.T #梯度下降,n阶列向量b = b - alpha * dbreturn w, b

算法实现后的代码会有些难理解,因为我将“算法概述”中的两层for循环向量化了,不但代码长度减少,并且运算时间也减少了。例如:计算系数向量,其中 

dw = 1 / m * np.dot(x.T, dz) #与下方for循环代码作用一致
for i in range(m):for j in range(n):dw[i] = dw[i] + x[j][i] * dz[j]dw[i] = dw[i]/m

其余部分向量化代码就不做演示,自己理解。


实例练习

从开头的网址上下载horse-colic.data中有300个个体,作为训练集;horse-colic.test中有68个个体,作为测试集;horse-colic.names是对数据文档与个体特征的描述。

首先数据预处理,并不是所有的数据一拿到手就可以直接使用,需要人为的处理一下以便使用。观察文档,我们知道数据中有30%是缺失的,那么我们要丢掉这30%的数据吗?答案是不掉丢,因为有时数据相当昂贵,扔掉和重新获取都是不可取的,所以必须采用一些方法来解决这个问题。于是,对于缺失数据,我们有以下几种方法可选:

① 使用可用特征的均值来填补缺失值;

② 使用特征值来填补缺失值,如-1,0;

③ 忽略有缺失值的样本;(对于本实例此方法不可取,因为本实例数据量很小)

④ 使用相似样本的均值填补缺少值;

 使用另外的机器学习算法预测缺失值;

于此,我选择使用特征值0来填补缺失值,选择0的好处在于 ,这样一来缺失值对数据预测不具有任何倾向性,因此带来的误差可大大减少。这里的替换缺失值可以直接用txt的“替换”功能就可以了,简洁明了。

观察个体特征,总共有28个,但并不是28个都需要,第3项的医院编号并无预测价值,类似的还有24到28。第23项是马的最终结果(1=活着;2=死亡;3=安乐死),也就是 ,算法处理二分类,于是将2与3都设置为0(我理解为安乐死是疝气症不严重但无法救治,死亡是疝气症严重到无法救治)。

以下是实例代码,logistic回归函数做少许修改,并且减少测试次数。

import numpy as np'''
logistic函数
参数为ndarray的1维向量
'''
def sigmoid(x):return 1 / (1 + np.exp(-1 * x))'''
数据预处理函数
参数为文件路径
'''
def dataPreprocess(dataLoad):file = open(dataLoad)data = []for line in file.readlines():tmp = list(map(float, line.strip().split()))tmp = tmp[:2] + tmp[3:23] #去掉某些列if tmp[-1] > 1: #将死亡特征变成0或1tmp[-1] = 0data.append(tmp)return np.array(data) #将数据处理为ndarray类型'''
test测试函数
参数为特征参数w,位移量b,测试集testData
'''
def test(w, b, testData):error = 0for i in range(testData.shape[0]):tmp = testData[i][:-1].reshape((21, 1)) #取出特征ans = sigmoid(np.dot(w.T, tmp) + b)if ans > 0.5: #大于0.5规定为1ans = 1else: #小于0.5规定为0ans = 0if ans != testData[i][-1]: #预测失误error += 1errorRate = error / testData.shape[0]print("此次迭代的错误率为:" + str(errorRate))return errorRate'''
logistic回归
参数为训练集(x,y),x(300,21),y(300,1)
'''
def logisticRegression(trainData, testData):x = trainData[:,:-1]y = trainData[:,-1].reshape((300, 1))alpha = 0.001 #alpha学习率cnt = 10 #迭代次数n = x.shape[1] #特征个数w = np.ones(n).reshape((n, 1)) #初始化w向量(21,1)b = 0 #初始化bsum = 0while cnt != 0:theta = sigmoid(np.dot(x, w) + b) #计算theta向量(300,1)dz = theta - ydw = 1 / n * np.dot(x.T, dz) #计算梯度(21,1)db = 1 / n * np.sum(dz)w = w - alpha * dw #梯度下降(21,1)b = b - alpha * dbcnt = cnt - 1error = test(w, b, testData)sum += errorprint("10次迭代的平均错误率为:" + str(sum / 10))if __name__ == '__main__':trainData = dataPreprocess('horse_data.txt')testData = dataPreprocess('horse_test.txt')logisticRegression(trainData, testData)'''
此次迭代的错误率为:0.3088235294117647
此次迭代的错误率为:0.3088235294117647
此次迭代的错误率为:0.29411764705882354
此次迭代的错误率为:0.35294117647058826
此次迭代的错误率为:0.36764705882352944
此次迭代的错误率为:0.4264705882352941
此次迭代的错误率为:0.3235294117647059
此次迭代的错误率为:0.4852941176470588
此次迭代的错误率为:0.3088235294117647
此次迭代的错误率为:0.5
10次迭代的平均错误率为:0.36764705882352944
'''

由上述代码结果可知,平均预测错误率达到了0.3677,这个结果还是不错的,毕竟还有30%的数据缺失,且数据量太小。


结论

logistic回归是学习神经网络的基础之一,在此算法中还有许多可以改进的地方,比如我们可以用牛顿法进行迭代,收敛速度比较梯度下降打更快。

如果有发现我的错误,请指出,十分感谢!

Python与logistic回归——理解与实践相关推荐

  1. logistic回归 如何_第七章:利用Python实现Logistic回归分类模型

    免责声明:本文是通过网络收集并结合自身学习等途径合法获取,仅作为学习交流使用,其版权归出版社或者原创作者所有,并不对涉及的版权问题负责.若原创作者或者出版社认为侵权,请联系及时联系,我将立即删除文章, ...

  2. Python实现 logistic 回归算法

    Python实现 logistic 回归算法 1.算法介绍 模型描述: sigmoid函数: 原理: 优化目标:最小化 sigmoid(f(x)) 和真实标签的差别(有不同的 cost functio ...

  3. circle loss代码实现_Python全栈之路-23-使用Python实现Logistic回归算法

    视频讲解地址 使用Python实现Logistic回归算法_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili​www.bilibili.com 本文代码 地址​github.com Logistic ...

  4. 使用 python 实现 Logistic 回归

    使用 python 实现 Logistic 回归 原理回顾 预测函数 代价函数 参数更新 代码分析 算法的实现 算法的使用 算法的对比 全部代码 这节课我们将使用 numpy 实现 逻辑回归算法,然后 ...

  5. python基于logistic回归模型的预测概率和标签信息可视化ROC曲线

    python基于logistic回归模型的预测概率和标签信息可视化ROC曲线 目录 python基于logistic回归模型的预测概率和标签信息可视化ROC曲线

  6. Python进行Logistic回归

    Python进行Logistic回归 第一步,导入库和数据: 第二步,处理数据: 第三步,数据建模: 最后,模型评价. 第一步,导入库和数据: # 导入库 from sklearn import da ...

  7. python做logistic回归_用Python做Logistic回归

    为什么写这篇文章 本人初学python,碰巧做的东西需要用一下Logistic回归,自觉这个很基础的东西应该已经有很多比较好的实现了,于是我就很自觉地问了下度娘.结果大囧==..出来的相关结果少得可怜 ...

  8. python实现logistic回归对样本量有要求么_logistic回归样本量多少合适?

    以下内容由小兵精选自百度文库,分享给读者朋友们. 样本量的估计可能是临床最头疼的一件事了,其实很多的临床研究事前是从来不考虑样本量的,至少我接触的临床研究大都如此. 他们大都是想到就开始做,但是事后他 ...

  9. 用python计算贷款_Python基于Logistic回归建模计算某银行在降低贷款拖欠率的数据示例...

    本文实例讲述了Python基于Logistic回归建模计算某银行在降低贷款拖欠率的数据.分享给大家供大家参考,具体如下: 一.Logistic回归模型: 二.Logistic回归建模步骤 1.根据分析 ...

最新文章

  1. 运行Python的三种方法
  2. angularjs组件间通讯_详解Angular2组件之间如何通信
  3. HDU - 6184 Counting Stars(思维+三元环)
  4. Js判断是否在微信浏览器中打开和微信版本号
  5. 你知道吗?macOS Sierra修复漏洞超过60个
  6. 黑马程序员_java基础笔记(03)...面向对象
  7. python笔记图片_python功能笔记——图像处理
  8. matlab信号建模,Matlab在信号处理中的建模仿真
  9. php环境下cache失效,cache缓存失效高并发读数据库的问题
  10. SocksCap64应用程序通过SOCKS代理
  11. 联想主板9针开关接线图_空气开关、断路器、漏电保护,汇总学习一下
  12. 硬件PCB发热严重,天线信号不良的整改
  13. IndentationError: unindent does not match any outer indentation level
  14. 苹果鼠标怎么连接_用手机连接鼠标和键盘的方法(安卓和苹果都可以)
  15. STM32控制TFTLCD显示屏(理论)
  16. mysql交并补_集合交并补运算顺序是什么?
  17. 【算法练习】CodeVs1391 伊吹萃香(分层图最短路)
  18. C++:error C2084 函数已有主体
  19. android上调试H5小工具
  20. 最快的计算机操作,世界十大最快的超级计算机

热门文章

  1. linux线程同步的方法
  2. JS与jQuery小结
  3. 【STM32】STM32和PC串口的NRF24L01通信测试
  4. 微信域名检测官方接口 检测域名是否被报红屏蔽 简易开发思路
  5. Linux虚拟机配置桥接模式
  6. java打印大风车的代码_canvas画布js代码实现大风车的动画
  7. STM32 CCM内存使用
  8. 虚拟化服务器虚拟出的gpu的驱动,微软虚拟机显卡及驱动的设置
  9. [绍棠] ijkplayer 的编译、打包 framework 和 https 支持
  10. 家用投影仪有哪些优缺点?帮你避雷!