逻辑回归由于其简单高效、易于解释,是工业应用最为广泛的模型之一,比如用于金融风控领域的评分卡、互联网的推荐系统。上文总结了逻辑回归的原理及其实现【全面解析并实现逻辑回归(Python)】。 本文从实际应用出发,以数据特征、优化算法、模型优化等方面,全面地归纳了逻辑回归(LR)优化技巧。
逻辑回归是简单的广义线性模型,模型的拟合能力很有限,无法学习到特征间交互的非线性信息:一个经典的示例是LR无法正确分类非线性的XOR数据,而通过引入非线性的特征(特征生成),可在更高维特征空间实现XOR线性可分,如下示例代码:
# 生成xor数据
import pandas as pd
xor_dataset = pd.DataFrame([[1,1,0],[1,0,1],[0,1,1],[0,0,0]],columns=['x0','x1','label'])
x,y = xor_dataset[['x0','x1']], xor_dataset['label']
xor_dataset.head()
# keras实现逻辑回归
from keras.layers import *
from keras.models import Sequential, Model
from tensorflow import random
np.random.seed(5) # 固定随机种子
random.set_seed(5)
model = Sequential()
model.add(Dense(1, input_dim=3, activation='sigmoid'))
model.summary()
model.compile(optimizer='adam', loss='binary_crossentropy')
xor_dataset['x2'] = xor_dataset['x0'] * xor_dataset['x1'] # 加入非线性特征
x,y = xor_dataset[['x0','x1','x2']], xor_dataset['label']
model.fit(x, y, epochs=10000,verbose=False)
print("正确标签:",y.values)
print("模型预测:",model.predict(x).round())
# 正确标签: [0 1 1 0] 模型预测: [0 1 1 0]
业界常说“数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已”。由于LR是简单模型,其特征质量基本决定了其最终效果(也就是简单模型要比较折腾特征工程)。
LR常用特征生成(提取)的方式主要有3种:
如POLY2、引入隐向量的因子分解机(FM)可以看做是LR的基础上,对所有特征进行了两两交叉,生成非线性的特征组合。
但FM等方法只能够做二阶的特征交叉,更为有效的是,利用GBDT自动进行筛选特征并生成特征组合。也就是提取GBDT子树的特征划分及组合路径作为新的特征,再把该特征向量当作LR模型输入,也就是推荐系统经典的GBDT +LR方法。(需要注意的,GBDT子树深度太深的化,特征组合层次比较高,极大提高LR模型拟合能力的同时,也容易引入一些噪声,导致模型过拟合)
如下GBDT+LR的代码实现(基于癌细胞数据集),提取GBDT特征,并与原特征拼接:
训练并评估模型有着较优的分类效果:
## GBDT +LR ,公众号阅读原文,可访问Github源码
from sklearn.preprocessing import OneHotEncoder
from sklearn.ensemble import GradientBoostingClassifier
gbdt = GradientBoostingClassifier(n_estimators=50, random_state=10, subsample=0.8, max_depth=6,
min_samples_split=20)
gbdt.fit(x_train, y_train) # GBDT 训练集训练
train_new_feature = gbdt.apply(x) # 返回数据在训练好的模型里每棵树中所处的叶子节点的位置
print(train_new_feature.shape)
train_new_feature = train_new_feature.reshape(-1, 50)
display(train_new_feature)
print(train_new_feature.shape)
enc = OneHotEncoder()
enc.fit(train_new_feature)
train_new_feature2 = np.array(enc.transform(train_new_feature).toarray()) # onehot表示
print(train_new_feature2.shape)
train_new_feature2
LR对于连续性的数值特征的输入,通常需要对特征做下max-min归一化(x =x-min/(max-min),转换输出为在 0-1之间的数,这样可以加速模型计算及训练收敛。但其实在工业界,很少直接将连续值作为逻辑回归模型的特征输入,而是先将连续特征离散化(常用的有等宽、等频、卡方分箱、决策树分箱等方式,而分箱的差异也直接影响着模型效果),然后做(Onehot、WOE)编码再输入模型。
之所以这样做,我们回到模型的原理,逻辑回归是广义线性模型,模型无非就是对特征线性的加权求和,在通过sigmoid归一化为概率。这样的特征表达是很有限的。以年龄这个特征在识别是否存款为例。在lr中,年龄作为一个特征对应一个权重w控制,输出值 = sigmoid(...+age * w+..),可见年龄数值大小在模型参数w的作用下只能呈线性表达。
但是对于年龄这个特征来说,不同的年龄值,对模型预测是否会存款,应该不是线性关系,比如0-18岁可能对于存款是负相关,19-55对于存款可能就正相关。这意味着不同的特征值,需要不同模型参数来更好地表达。也就是通过对特征进行离散化,比如年龄可以离散化以及哑编码(onehot)转换成4个特征(if_age<18, if_18<age<30,if_30<age<55,if_55<age )输入lr模型,就可以用4个模型参数分别控制这4个离散特征的表达:sigmoid(...+age1 * w1+age2 * w2..),这明显可以增加模型的非线性表达,提高了拟合能力。
在风控领域,特征离散后更常用特征表示(编码)还不是onehot,而是WOE编码。
woe编码是通过对当前分箱中正负样本的比值Pyi与所有样本中正负样本比值Pni的差异(如上式),计算出各个分箱的woe值,作为该分箱的数值表示。
经过分箱、woe编码后的特征很像是决策树的决策过程,以年龄特征为例:if age >18 and age<22 then return - 0.57(年龄数值转为对应WOE值); if age >44 then return 1.66;...;将这样的分箱及编码(对应树的特征划分、叶子节点值)输入LR,很类似于决策树与LR的模型融合,而提高了模型的非线性表达。
总结下离散化编码的优点:
特征选择用于筛选出显著特征、摒弃非显著特征。可以降低运算开销,减少干扰噪声,降低过拟合风险,提升模型效果。对于逻辑回归常用如下三种选择方法:
过滤法:利用缺失率、单值率、方差、pearson相关系数、VIF、IV值、PSI、P值等指标对特征进行筛选;(相关介绍及代码可见:【特征选择】)
嵌入法:使用带L1正则项的逻辑回归,有特征选择(稀疏解)的效果;
包装法:使用逐步逻辑回归,双向搜索选择特征。
其中,过滤法提到的VIF是共线性指标,其原理是分别尝试以各个特征作为标签,用其他特征去学习拟合,得到线性回归模型拟合效果的R^2值,算出各个特征的VIF。特征的VIF为1,即无法用其他特征拟合出当前特征,特征之间完全没有共线性(工程上常用VIF<10作为阈值)
共线性对于广义线性模型主要影响了特征实际的显著性及权重参数(比如,该特征业务上应该正相关,而权重值却是负的),也会消弱模型解释性以及模型训练的稳定性。
通过设置截距项(偏置项)b可以提高逻辑回归的拟合能力。截距项可以简单理解为模型多了一个参数b(也可以看作是新增一列常数项特征对应的参数w0),这样的模型复杂度更高,有更好的拟合效果。
如果没有截距项b呢?我们知道逻辑回归的决策边界是线性的(即决策边界为W * X + b),如果没有截距项(即W * X),决策边界就限制在必须是通过坐标圆点的,这样的限制很有可能导致模型收敛慢、精度差,拟合不好数据,即容易欠拟合。
通过设定正则项可以减少模型的过拟合风险,常用的正则策略有L1,L2正则化:
对带L2目标函数的模型参数更新权重,ϵ学习率:
从上式可以看出,加⼊权重衰减后会导致学习规则的修改,即在每步执⾏梯度更新前先收缩权重 (乘以 1 − ϵα ),有权重衰减的效果。
对带L1目标函数的模型参数更新权重(其中 sgn(x) 为符号函数,取参数的正负号):
可见,在-αsgn(w)项的作用下, w各元素每步更新后的权重向量都会平稳地向0靠拢,w的部分元素容易为0,造成稀疏性。
总结下L1,L2正则项:
L1,L2都是限制解空间,减少模型容量的方法,以到达减少过拟合的效果。L2范式约束具有产生平滑解的效果,没有稀疏解的能力,即参数并不会出现很多零。假设我们的决策结果与两个特征有关,L2正则倾向于综合两者的影响,给影响大的特征赋予高的权重;而L1正则倾向于选择影响较大的参数,而尽可能舍弃掉影响较小的那个(有稀疏解效果)。在实际应用中 L2正则表现往往会优于 L1正则,但 L1正则会压缩模型,降低计算量。
当逻辑回归应用于二分类任务时有两种主要思路,
如下softmax函数及对应的多分类目标函数:
softmax回归中,一般是假设多个类别是互斥的,样本在softmax中的概率公式中计算后得到的是样本属于各个类别的值,各个类别的概率之和一定为1,而采用logistic回归OVR进行多分类时,得到的是值是样本相对于其余类别而言属于该类别的概率,一个样本在多个分类器上计算后得到的结果不一定为1。因而当分类的目标类别是互斥时(例如分辨猫、猪、狗图片),常采用softmax回归进行预测,而分类目标类别不是很互斥时(例如分辨流行音乐、摇滚、华语),可以采用逻辑回归建立多个二分类器(也可考虑下多标签分类)。
逻辑回归使用最小化交叉熵损失作为目标函数,
为什么不能用MSE均方误差?
简单来说,有以下几点:
最大似然下的逻辑回归没有解析解,我们常用梯度下降之类的算法迭代优化得到局部较优的参数解。
如果是Keras等神经网络库建模,梯度下降算法类有SGD、Momentum、Adam等优化算法可选。对于大多数任务而言,通常可以直接先试下Adam,然后可以继续在具体任务上验证不同优化算法效果。
如果用的是scikitl-learn库建模,优化算法主要有liblinear(坐标下降)、newton-cg(拟牛顿法), lbfgs(拟牛顿法)和sag(随机平均梯度下降)。liblinear支持L1和L2,只支持OvR做多分类;“lbfgs”, “sag” “newton-cg”只支持L2,支持OvR和MvM做多分类;当数据量特别大,优先sag!
优化模型阈值(cutoff点) :当评估指标是分类Precision、Recall等指标时,可以通过优化模型阈值(默认0.5)提高分类效果。常用可以根据不同划分阈值下的presion与recall曲线(P-R曲线),做出权衡,选择合适的模型阈值。
逻辑回归模型很大的优势就是可解释性,上节提到通过离散化编码(如Onehot)可以提高拟合效果及解释性,如下特征离散后Onehot编码:
决策过程也就是对特征分箱Xn及其模型权重Wn的加权求和,然后sigmoid转为概率,而通过模型权重值的大小就可以知道各特征对于决策的实际影响程度,比如特征"年龄在[18,30]"对应学到权重值W为-0.8,也就是呈现负相关。