本站原创文章,转载请说明来自《老饼讲解-机器学习》ml.bbbdata.com
逻辑回归是一个简单的模型,
在实际建模中,我们需要根据逻辑回归的特性
配以一系列相关操作,提高建模的实用性
本文讲述逻辑回归完整的建模流程
完整代码见《逻辑回归建模完整代码》
逻辑回归是一个简单的模型,
逻辑回归的建模效果对于入模变量极为敏感。
变量选择与预处理的意义
建模是一个混然一体的东西,
如果直接丢一堆数据进模型训练,
那么模型要面临处理的问题会非常多,
这对模型来说,是非常大负担的。
更好的做法是,
将问题层层简化,
尽量让最后交给模型的是一个简单的问题
特别对于逻辑回归这种拟合能力较为简单的模型,更需如此
例如,
业务层面能解决的,业务层面处理,
数据层面能处理的,数据处理,
把能解决的问题都尽量前置处理,
以变量选择为例,
如果我们能从业务层面,
把一些业务上就能否决的变量排掉,
再经数据分析层面,
把不相关变量排除掉,
那模型就不需要解决“去除无效变量”这个问题,
减轻模型的负担
总的来说,就是最好不要把问题全交给模型处理
反而要尽量让模型处理的问题越简单越纯粹越好
(二)逻辑回归的变量预处理流程
对于逻辑回归,一般要处理的是:
1.入模的单变量对y是线性相关的(不是线性也至少是单调的)。
2.缺失值处理
即选出与y相关的变量,并将数据尽量转换成与y线性相关。
数据归一化的意义
sklearn中的逻辑回归使用类似梯度下降之类的算法进行求解,
数据归一化对这类求解算法的速度与极大好处。
因此,在使用slearn调用逻辑回归前,
需要先对数据进行归一化。
数据归一化公式
归一化直接使用如下公式对数据缩放到[0,1]即可:
建模不建议直接调用逻辑回归,
以逐步回归的方式调用逻辑回归建模可以更好地避免逻辑回归的过拟合问题。
逐步回归对逻辑回归的意义
逻辑回归的过拟合主要来源于过多的特征。
在保障模型效果的前提下,
尽量选择更少的特征,
使模型更简单,避免模型过拟合。
逐步回归可以起到这个作用。
逐步回归流程
1. 历遍所有变量,将单个变量与目标建模,把模型结果最好的变量作为第一轮选择变
2. 在第一轮选择变量的基础上,添加第二个变量,
历遍剩余变量,添加哪个变量能令模型结果最好,就将其作为第二轮选择变量。
3. 在第二轮的基础上,添加第三个变量......
......
直到变量不再对拟合结果带来明显贡献时,就不再添加变量。
关键代码如下
#-----逐步回归挑选变量--------------------
select_var = [] # 已挑选的变量
var_pool = np.arange(X_norm.shape[1]) # 待挑选变量池
auc_rec = []
print("\n===========逐回步归过程===============")
while(len(var_pool)>0):
max_auc = 0
best_var = None
#---选出剩余变量中能带来最好效果的变量--------
for i in var_pool:
# -------将新变量和已选变量一起训练模型------
cur_x = X_norm[:,select_var+[i]] # 新变量和已选变量作为建模数据
clf.fit(cur_x,y) # 训练模型
pred_prob_y = clf.predict_proba(cur_x)[:,1] # 预测概率
cur_auc = metrics.roc_auc_score(y,pred_prob_y) # 计算AUC
# ------更新最佳变量---------------------------
if(cur_auc>max_auc):
max_auc = cur_auc
best_var = i
#-------检验新变量能否带来显著效果---------------------------
last_auc = auc_rec[-1] if len(auc_rec)>0 else 0.0001
valid = True if ((max_auc-last_auc)/last_auc>0.005) else False
# 如果有显著效果,则将该变量添加到已选变量
if(valid):
print("本轮最佳AUC:",max_auc,",本轮最佳变量:",feature_names[best_var])
auc_rec.append(max_auc)
select_var.append(best_var)
var_pool = var_pool[var_pool!=best_var]
# 如果没有显著效果,则停止添加变量
else:
print("本轮最佳AUC:",max_auc,",本轮最佳变量:",feature_names[best_var],',效果不明显,不再添加变量')
break
print("最终选用变量",len(select_var),"个:",feature_names[select_var])
#------模型训练--------------------------------
clf.fit(X_norm[:,select_var],y)
===========逐回步归过程===============
本轮最佳AUC: 0.9754505575815231 ,本轮最佳变量: worst perimeter
本轮最佳AUC: 0.9849637968394904 ,本轮最佳变量: worst smoothness
本轮最佳AUC: 0.9903017810897944 ,本轮最佳变量: mean texture
本轮最佳AUC: 0.9925611754135617 ,本轮最佳变量: radius error ,效果不明显,不再添加变量
最终选用变量 3 个: ['worst perimeter' 'worst smoothness' 'mean texture']
建模完成后,我们需要对模型的效果进行评估。
模型AUC
逻辑回归一般选用AUC作为评价指标。
一般来说,AUC达到0.65模型才开始有区分度,
达到0.70以上才开始有价值(这只是一个大概,具体看业务)。
关于AUC详细可看《二分类:ROC曲线与AUC值》
主要代码如下:
#------模型预测-------------------------------
pred_y = clf.predict(X_norm[:,select_var])
pred_prob_y = clf.predict_proba(X_norm[:,select_var])[:,1]
auc = metrics.roc_auc_score(y,pred_prob_y) #
print("\n============建模结果=================")
print("选用变量",len(select_var),"个:",feature_names[select_var])
print("AUC:",auc)
运行结果:
============建模结果=================
选用变量 3 个: ['worst perimeter' 'worst smoothness' 'mean texture']
AUC: 0.9903017810897944
业务角度审查系数
建模仅是从数据角度去寻找一组最佳的系数,
并不能系数在业务角度是合理的,
因此,我们还需要从业务角度去审查每个变量的系数是否符合业务逻辑。
我们打印模型系数如下,
=========对应归一化数据的模型参数========
模型系数(对应归一化数据): [-8.92825356 -3.87812186 -3.10331343]
模型阈值(对应归一化数据): [5.73863685]
=========对应原始数据的模型参数==========
模型系数(对应原始数据): [ -0.04446563 -25.60999711 -0.10494804]
模型阈值(对应原始数据): [10.82185811]
提取公式计算的概率与模型概率的最大误差 8.326672684688674e-16
常用审查角度
常用的审查角度有:
系数的正负符号是否合理,
系数权重是否合理,
系数绝对值是否过大等等
老饼的经历
笔者曾有两次遇到系数与业务逻辑不符合,
最后发现是因为没有对数据进行归一化
做了归一化后,训练出来的结果又符合业务逻辑了。
1.正则项的尝试
sklearn训练时默认会加L2正则项,以避免系数过大。
但这样会牺牲一定的求解精确度,
因此我们最好把加L2和不加任何正则项都尝试一下(即参数penalty=’l2‘/'none'),哪种效果更好,就用哪种。
2.测试数据
要不要留测试数据验证模型泛化能力,对于逻辑回归,与正则项一样,是把双刃剑。
在变量选择较好,模型训练合理的情况下,逻辑回归几乎不会过拟合。
留出数据验证模型是否过拟合,很多时候是多此一举
(逻辑回归模型简单,就是一个S型的模型,没有任何跌宕可言),
如果不留数据,有可能会造成过拟合(几率很小)而不知道,
而留数据,则又减少了训练数据(训练数据越多,模型肯定越好),的确是一把双刃剑。
在此情况下,留不留检验数据,还依据建模师根据自己的实际情况选择。
总而言之,逻辑回归不一定非要留检验数据不可。
End