逻辑回归模型介绍和程序实现
来源:互联网 发布:职业女装 知乎 编辑:程序博客网 时间:2024/05/16 15:21
逻辑回归原理及实现
虽然叫做“回归”,但是这个算法是用来解决分类问题的。回归与分类的区别在于:回归所预测的目标量的取值是连续的(例如房屋的价格);而分类所预测的目标变量的取值是离散的(例如判断邮件是否为垃圾邮件)。当然,为了便于理解,我们从二值分类(binary classification)开始,在这类分类问题中,y只能取0或1。更好的理解问题,先举个小例子:假如我们要制作一个垃圾邮件过滤系统,如果一封邮件是垃圾系统,y=1,否则y=0 。给定训练样本集,当然它们的特征和label都已知,我们就是要训练一个分类器,将它们分开。
回归分析用来描述自变量x和因变量Y之间的关系,或者说自变量X对因变量Y的影响程度,并对因变量Y进行预测。其中因变量是我们希望获得的结果,自变量是影响结果的潜在因素,自变量可以有一个,也可以有多个。一个自变量的叫做一元回归分析,超过一个自变量的叫做多元回归分析。下面是一组广告费用和曝光次数的数据,费用和曝光次数一一对应。其中曝光次数是我们希望知道的结果,费用是影响曝光次数的因素,我们将费用设置为自变量X,将曝光次数设置为因变量Y,通过一元线性回归方程和判定系数可以发现费用(X)对曝光次数(Y)的影响。
1、 逻辑回归模型
回归是一种极易理解的模型,就相当于y=f(x),表明自变量x与因变量y的关系。最常见问题有如医生治病时的望、闻、问、切,之后判定病人是否生病或生了什么病,其中的望闻问切就是获取自变量x,即特征数据,判断是否生病就相当于获取因变量y,即预测分类。
最简单的回归是线性回归,在此借用Andrew NG的讲义,有如图1.a所示,X为数据点——肿瘤的大小,Y为观测值——是否是恶性肿瘤。通过构建线性回归模型,如hθ(x)所示,构建线性回归模型后,即可以根据肿瘤大小,预测是否为恶性肿瘤hθ(x)≥.05为恶性,hθ(x)<0.5为良性。
图1 线性回归示例
然而线性回归的鲁棒性很差,例如在图1.b的数据集上建立回归,因最右边噪点的存在,使回归模型在训练集上表现都很差。这主要是由于线性回归在整个实数域内敏感度一致,而分类范围,需要在[0,1]。逻辑回归就是一种减小预测范围,将预测值限定为[0,1]间的一种回归模型,其回归方程与回归曲线如图2所示。逻辑曲线在z=0时,十分敏感,在z>>0或z<<0处,都不敏感,将预测值限定为(0,1)。
图2 逻辑方程与逻辑曲线
逻辑回归其实仅为在线性回归的基础上,套用了一个逻辑函数,但也就由于这个逻辑函数,逻辑回归成为了机器学习领域一颗耀眼的明星,更是计算广告学的核心。对于多元逻辑回归,可用如下公式似合分类,其中公式(4)的变换,将在逻辑回归模型参数估计时,化简公式带来很多益处,y={0,1}为分类结果。
对于训练数据集,特征数据x={x1, x2, … , xm}和对应的分类数据y={y1, y2, … , ym}。构建逻辑回归模型f(θ),最典型的构建方法便是应用极大似然估计。首先,对于单个样本,其后验概率为:
那么,极大似然函数为:
log似然是:
2、 梯度下降
由第1节可知,求逻辑回归模型f(θ),等价于:
采用梯度下降法:
从而迭代θ至收敛即可:
2.1 梯度下降算法
梯度下降算法的伪代码如下:
################################################
初始化回归系数为1
重复下面步骤直到收敛{
计算整个数据集的梯度
使用alpha x gradient来更新回归系数
}
返回回归系数值
################################################
注:因为本文中是求解的Logit回归的代价函数是似然函数,需要最大化似然函数。所以我们要用的是梯度上升算法。但因为其和梯度下降的原理是一样的,只是一个是找最大值,一个是找最小值。找最大值的方向就是梯度的方向,最小值的方向就是梯度的负方向。不影响我们的说明,所以当时自己就忘了改过来了,谢谢评论下面@wxltt的指出。另外,最大似然可以通过取负对数,转化为求最小值。代码里面的注释也是有误的,写的代码是梯度上升,注销成了梯度下降,对大家造成的不便,希望大家海涵。
2.2 随机梯度下降SGD (stochastic gradient descent)
梯度下降算法在每次更新回归系数的时候都需要遍历整个数据集(计算整个数据集的回归误差),该方法对小数据集尚可。但当遇到有数十亿样本和成千上万的特征时,就有点力不从心了,它的计算复杂度太高。改进的方法是一次仅用一个样本点(的回归误差)来更新回归系数。这个方法叫随机梯度下降算法。由于可以在新的样本到来的时候对分类器进行增量的更新(假设我们已经在数据库A上训练好一个分类器h了,那新来一个样本x。对非增量学习算法来说,我们需要把x和数据库A混在一起,组成新的数据库B,再重新训练新的分类器。但对增量学习算法,我们只需要用新样本x来更新已有分类器h的参数即可),所以它属于在线学习算法。与在线学习相对应,一次处理整个数据集的叫“批处理”。
随机梯度下降算法的伪代码如下:
###############################################
初始化回归系数为1
重复下面步骤直到收敛{
对数据集中每个样本
计算该样本的梯度
使用alpha xgradient来更新回归系数
}
返回回归系数值
###############################################
2.3 改进的随机梯度下降
1)在每次迭代时,调整更新步长alpha的值。随着迭代的进行,alpha越来越小,这会缓解系数的高频波动(也就是每次迭代系数改变得太大,跳的跨度太大)。当然了,为了避免alpha随着迭代不断减小到接近于0(这时候,系数几乎没有调整,那么迭代也没有意义了),我们约束alpha一定大于一个稍微大点的常数项,具体见代码。
2)每次迭代,改变样本的优化顺序。也就是随机选择样本来更新回归系数。这样做可以减少周期性的波动,因为样本顺序的改变,使得每次迭代不再形成周期性。
改进的随机梯度下降算法的伪代码如下:
################################################
初始化回归系数为1
重复下面步骤直到收敛{
对随机遍历的数据集中的每个样本
随着迭代的逐渐进行,减小alpha的值
计算该样本的梯度
使用alpha x gradient来更新回归系数
}
返回回归系数值
#################################################
3、Python实现
训练数据:
1 -0.017612 14.053064 0 2 -1.395634 4.662541 1 3 -0.752157 6.538620 0 4 -1.322371 7.152853 0 5 0.423363 11.054677 0 6 0.406704 7.067335 1 7 0.667394 12.741452 0 8 -2.460150 6.866805 1 9 0.569411 9.548755 010 -0.026632 10.427743 011 0.850433 6.920334 112 1.347183 13.175500 013 1.176813 3.167020 114 -1.781871 9.097953 015 -0.566606 5.749003 116 0.931635 1.589505 117 -0.024205 6.151823 118 -0.036453 2.690988 119 -0.196949 0.444165 120 1.014459 5.754399 121 1.985298 3.230619 122 -1.693453 -0.557540 123 -0.576525 11.778922 024 -0.346811 -1.678730 125 -2.124484 2.672471 126 1.217916 9.597015 027 -0.733928 9.098687 028 -3.642001 -1.618087 129 0.315985 3.523953 130 1.416614 9.619232 031 -0.386323 3.989286 132 0.556921 8.294984 133 1.224863 11.587360 034 -1.347803 -2.406051 135 1.196604 4.951851 136 0.275221 9.543647 037 0.470575 9.332488 038 -1.889567 9.542662 039 -1.527893 12.150579 040 -1.185247 11.309318 041 -0.445678 3.297303 142 1.042222 6.105155 143 -0.618787 10.320986 044 1.152083 0.548467 145 0.828534 2.676045 146 -1.237728 10.549033 047 -0.683565 -2.166125 148 0.229456 5.921938 149 -0.959885 11.555336 050 0.492911 10.993324 051 0.184992 8.721488 052 -0.355715 10.325976 053 -0.397822 8.058397 054 0.824839 13.730343 055 1.507278 5.027866 156 0.099671 6.835839 157 -0.344008 10.717485 058 1.785928 7.718645 159 -0.918801 11.560217 060 -0.364009 4.747300 161 -0.841722 4.119083 162 0.490426 1.960539 163 -0.007194 9.075792 064 0.356107 12.447863 065 0.342578 12.281162 066 -0.810823 -1.466018 167 2.530777 6.476801 168 1.296683 11.607559 069 0.475487 12.040035 070 -0.783277 11.009725 071 0.074798 11.023650 072 -1.337472 0.468339 173 -0.102781 13.763651 074 -0.147324 2.874846 175 0.518389 9.887035 076 1.015399 7.571882 077 -1.658086 -0.027255 178 1.319944 2.171228 179 2.056216 5.019981 180 -0.851633 4.375691 1
测试数据:
1 -1.510047 6.061992 0 2 -1.076637 -3.181888 1 3 1.821096 10.283990 0 4 3.010150 8.401766 1 5 -1.099458 1.688274 1 6 -0.834872 -1.733869 1 7 -0.846637 3.849075 1 8 1.400102 12.628781 0 9 1.752842 5.468166 110 0.078557 0.059736 111 0.089392 -0.715300 112 1.825662 12.693808 013 0.197445 9.744638 014 0.126117 0.922311 115 -0.679797 1.220530 116 0.677983 2.556666 117 0.761349 10.693862 018 -2.168791 0.143632 119 1.388610 9.341997 020 0.317029 14.739025 0
python 代码:
1 #!/usr/bin/python 2 import sys 3 import copy 4 import math 5 import time 6 import random 7 import getopt 8 9 def usage(): 10 print '''Help Information: 11 -h, --help: show help information; 12 -r, --train: train file; 13 -t, --test: test file; 14 -k, --ratio: study ratio; 15 -i, --iter: iter num; 16 -p, --type: optimize type:"gradDescent","stocGradDescent","smoothStocGradDescent"; 17 ''' 18 19 def getparamenter(): 20 try: 21 opts, args = getopt.getopt(sys.argv[1:], "hr:t:k:i:p:", ["help","train=","test=","kst=","iter=","type="]) 22 except getopt.GetoptError, err: 23 print str(err) 24 usage() 25 sys.exit(1) 26 27 sys.stderr.write("\ntrain.py : a python script for perception training.\n") 28 sys.stderr.write("Copyright 2016 sxron, search, Sogou. \n") 29 sys.stderr.write("Email: shixiang08abc@gmail.com \n\n") 30 31 train = '' 32 test = '' 33 kst = 0.01 34 iter = 100 35 type = 'gradDescent' 36 for i, f in opts: 37 if i in ("-h", "--help"): 38 usage() 39 sys.exit(1) 40 elif i in ("-r", "--train"): 41 train = f 42 elif i in ("-t", "--test"): 43 test = f 44 elif i in ("-k", "--ratio"): 45 kst = float(f) 46 elif i in ("-i", "--iter"): 47 iter = int(f) 48 elif i in ("-p", "--type"): 49 type = f 50 else: 51 assert False, "unknown option" 52 53 print "start trian parameter\ttrain:%s\ttest:%s\tkst:%f\titer:%d\ttype:%s" % (train,test,kst,iter,type) 54 55 return train,test,kst,iter,type 56 57 def loadData(file): 58 data = [] 59 label = [] 60 fin = open(file,'r') 61 while 1: 62 line = fin.readline() 63 if not line: 64 break 65 tokens = line.strip().split('\t') 66 fea = [] 67 try: 68 lab = float(tokens[-1]) 69 fea.append(1.0) 70 for i in range(0,len(tokens)-1,1): 71 value = float(tokens[i]) 72 fea.append(value) 73 except: 74 continue 75 label.append(lab) 76 data.append(fea) 77 return data,label 78 79 def sigmoid(inX): 80 return 1.0/(1+math.exp(-inX)) 81 82 def getMatResult(data,weights): 83 result = 0.0 84 for i in range(0,len(data),1): 85 result += data[i]*weights[i] 86 return result 87 88 def trainLogRegress(data,label,iter,kst,type): 89 weights = [] 90 for i in range(0,len(data[0]),1): 91 weights.append(1.0) 92 93 for i in range(0,iter,1): 94 errors = [] 95 if type=="gradDescent": 96 for k in range(0,len(data),1): 97 result = getMatResult(data[k],weights) 98 error = label[k] - sigmoid(result) 99 errors.append(error)100 for k in range(0,len(weights),1):101 updata = 0.0102 for idx in range(0,len(errors),1):103 updata += errors[idx]*data[idx][k]104 weights[k] += kst*updata105 106 elif type=="stocGradDescent":107 for k in range(0,len(data),1):108 result = getMatResult(data[k],weights)109 error = label[k] - sigmoid(result)110 for idx in range(0,len(weights),1):111 weights[idx] += kst*error*data[k][idx]112 113 elif type=="smoothStocGradDescent":114 dataIndex = range(len(data))115 for k in range(0,len(data),1):116 randIndex = int(random.uniform(0,len(dataIndex)))117 result = getMatResult(data[randIndex],weights)118 error = label[randIndex] - sigmoid(result)119 for idx in range(0,len(weights),1):120 weights[idx] += kst*error*data[randIndex][idx]121 else:122 print "Not support optimize method type!"123 return weights124 125 def testLogRegress(weights,data,label):126 testNum = 0127 matchNum = 0128 for i in range(0,len(data),1):129 result = getMatResult(data[i],weights)130 predict = 0131 if sigmoid(result)>0.5:132 predict = 1133 testNum += 1134 if predict==int(label[i]):135 matchNum += 1136 print "testNum:%d\tmatchNum:%d\tratio:%f" % (testNum,matchNum,float(matchNum)/testNum)137 138 def main():139 #set parameter140 train,test,kst,iter,type = getparamenter()141 142 #load train data143 trnData,trnLabel = loadData(train)144 testData,testLabel = loadData(test)145 146 #train logregress147 weights = trainLogRegress(trnData,trnLabel,iter,kst,type)148 149 #test logregress150 testLogRegress(weights,testData,testLabel)151 152 if __name__=="__main__":153 main()
- 逻辑回归模型介绍和程序实现
- Tensorflow实现逻辑回归模型
- 从零开始实现逻辑回归模型
- 逻辑回归模型和算法
- 回归模型-逻辑回归
- 逻辑回归原理介绍及Matlab实现
- 逻辑回归模型
- 逻辑回归模型
- 逻辑回归模型
- 复习:逻辑回归模型
- 逻辑Logistic回归原理和实现
- TensorFlow学习笔记(三):TensorFlow实现逻辑回归模型
- 极大熵模型和逻辑回归的等价性
- 统计学习-逻辑回归(LR)和最大熵模型
- 统计学习方法:逻辑斯蒂回归和最大熵模型
- 逻辑斯蒂回归模型
- 逻辑回归模型预测ctr
- 逻辑斯蒂回归模型
- LaTex分行分段分页与项目列表
- css伪类
- 积分系统(4)-详细公告页面的“B”层跟“D”层
- 已知先序和中序构建二叉树并且以层序输出
- 一张图看明白金融数据架构
- 逻辑回归模型介绍和程序实现
- 贪心算法为什么就是经典?
- win10 版本下的ZWMAX完全安装方法之更改UCG
- 计算机科学和编程导论-week3-对象
- 搞懂js继承方法
- Next Greater Element I
- 【学习笔记(JAVA从入门到精通)】Java数据类型&操作符【内含问题,Mark】
- 矩阵与斐波那契数列
- 搭建三层架构