Python与logistic回归——理解与实践
文章参考 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回归——理解与实践相关推荐
- logistic回归 如何_第七章:利用Python实现Logistic回归分类模型
免责声明:本文是通过网络收集并结合自身学习等途径合法获取,仅作为学习交流使用,其版权归出版社或者原创作者所有,并不对涉及的版权问题负责.若原创作者或者出版社认为侵权,请联系及时联系,我将立即删除文章, ...
- Python实现 logistic 回归算法
Python实现 logistic 回归算法 1.算法介绍 模型描述: sigmoid函数: 原理: 优化目标:最小化 sigmoid(f(x)) 和真实标签的差别(有不同的 cost functio ...
- circle loss代码实现_Python全栈之路-23-使用Python实现Logistic回归算法
视频讲解地址 使用Python实现Logistic回归算法_哔哩哔哩 (゜-゜)つロ 干杯~-bilibiliwww.bilibili.com 本文代码 地址github.com Logistic ...
- 使用 python 实现 Logistic 回归
使用 python 实现 Logistic 回归 原理回顾 预测函数 代价函数 参数更新 代码分析 算法的实现 算法的使用 算法的对比 全部代码 这节课我们将使用 numpy 实现 逻辑回归算法,然后 ...
- python基于logistic回归模型的预测概率和标签信息可视化ROC曲线
python基于logistic回归模型的预测概率和标签信息可视化ROC曲线 目录 python基于logistic回归模型的预测概率和标签信息可视化ROC曲线
- Python进行Logistic回归
Python进行Logistic回归 第一步,导入库和数据: 第二步,处理数据: 第三步,数据建模: 最后,模型评价. 第一步,导入库和数据: # 导入库 from sklearn import da ...
- python做logistic回归_用Python做Logistic回归
为什么写这篇文章 本人初学python,碰巧做的东西需要用一下Logistic回归,自觉这个很基础的东西应该已经有很多比较好的实现了,于是我就很自觉地问了下度娘.结果大囧==..出来的相关结果少得可怜 ...
- python实现logistic回归对样本量有要求么_logistic回归样本量多少合适?
以下内容由小兵精选自百度文库,分享给读者朋友们. 样本量的估计可能是临床最头疼的一件事了,其实很多的临床研究事前是从来不考虑样本量的,至少我接触的临床研究大都如此. 他们大都是想到就开始做,但是事后他 ...
- 用python计算贷款_Python基于Logistic回归建模计算某银行在降低贷款拖欠率的数据示例...
本文实例讲述了Python基于Logistic回归建模计算某银行在降低贷款拖欠率的数据.分享给大家供大家参考,具体如下: 一.Logistic回归模型: 二.Logistic回归建模步骤 1.根据分析 ...
最新文章
- 运行Python的三种方法
- angularjs组件间通讯_详解Angular2组件之间如何通信
- HDU - 6184 Counting Stars(思维+三元环)
- Js判断是否在微信浏览器中打开和微信版本号
- 你知道吗?macOS Sierra修复漏洞超过60个
- 黑马程序员_java基础笔记(03)...面向对象
- python笔记图片_python功能笔记——图像处理
- matlab信号建模,Matlab在信号处理中的建模仿真
- php环境下cache失效,cache缓存失效高并发读数据库的问题
- SocksCap64应用程序通过SOCKS代理
- 联想主板9针开关接线图_空气开关、断路器、漏电保护,汇总学习一下
- 硬件PCB发热严重,天线信号不良的整改
- IndentationError: unindent does not match any outer indentation level
- 苹果鼠标怎么连接_用手机连接鼠标和键盘的方法(安卓和苹果都可以)
- STM32控制TFTLCD显示屏(理论)
- mysql交并补_集合交并补运算顺序是什么?
- 【算法练习】CodeVs1391 伊吹萃香(分层图最短路)
- C++:error C2084 函数已有主体
- android上调试H5小工具
- 最快的计算机操作,世界十大最快的超级计算机