逻辑回归与它的名称相反,逻辑回归实际上用于解决分类问题。在回归问题中,有时候使用线性回归的拟合效果很牵强,那么就应该使用非线性回归。分类问题亦如此,如图3.16所示
。对于一个分类问题,如果可以找到一个超平面,使得超平面两边的数据点能够正确分类,则称其为线性可分问题。反之,如果找不到一个超平面使得数据点能够正确分类,则称该问题为线性不可分问题。
图3.16 线性可分问题与不可分问题
对于某些线性不可分问题,在误差允许的条件下,也可以视为线性可分,如图3.17所示。
图3.17 可视为线性可分问题的不可分问题
因此,线性分类器具有相当广泛的应用,逻辑回归即是其中之一。当然,使用核函数的方法,逻辑回归也可以用于解决线性不可分问题。读者可以参阅7.5.2节的内容,了解核函数的概念和原理。
Tips: 图3.16和图3.17所示的数据集可以用sklearn.datasets模块画出。sklearn.datasets可以方便、快捷地产生分类和回归数据集。除了load_xxx函数导入Sklearn自带的数据集,如Boston、IRIS数据集外,还可以用make_xxx函数自动产生分类或回归数据集。例如:用make_classification产生二分类和多分类数据集;用make_regression产生回归数据集。关于make_xxx函数还有很多形式,这里就不再赘述了。另外,也可以使用fetch_xxx从远程下载数据集,但由于网络原因,国内用户可能下载不了。
再次强调,虽然名为逻辑回归,但模型本质上是一个分类器。对于二分类问题 y ={0,1},假设存在一个容量为 m 的样本,对于每个个体 i ,用向量 x i 表示其特征向量。一般情况下,分类器的回答不应该是“某个体属于哪一类”,而是“个体属于某一类的概率是多少”。因此记 y i 属于类1的概率为 P ( y i =1| x i ),定义概率(odds)为:
可以看到,当 P ( y i =1| x i )→1时,odds→ ∞ ;反之,当 P ( y i =1| x i )→0时,odds→0。这样就把原本所要预测的 P ( y i =1| x i )∈[0,1],拓展到odds∈[0,∞)。如果再用一个常见的初等函数拟合上式,即:
对式(3.7)进行一些变换,就可用线性预测器 ω T x i 来预测 P ( y i =1| ω , x i )的取值:
于是将odds∈[0,∞)拓展到log(odds)∈(−∞,+∞),同时将问题转化为线性回归问题。从上式中亦可以看出逻辑回归本质上属于线性分类器,用它来解决线性不可分问题势必会存在误差。
同样由式(3.7)可以得出:
式(3.8)即为逻辑回归模型。
在2.3.1节中曾经讲过,对于不同模型,在同一 ω , x i 下, y i 服从不同的分布。我们已经证明线性回归对应正态分布,因为:
所以在逻辑回归模型下, y i 服从概率 P 与, ω , x i 有关的伯努利分布。
有了 P ( y i | ω , x i )的表达式,可以很容易想到使用极大似然法:
将似然函数取对数,整理可得:
可以看出,求解模型的过程实际就是求解优化问题。对于上述优化问题,很难找到像式(3.4)这样的解析解。因此,需要使用迭代的方法求解数值解,详细算法将在第5章介绍。结合3.2.2节所学,也可以使用MALTAB优化工具箱求解模型参数。
通过极大似然法可以求出模型的参数 ω ,用式(3.8)可以计算出概率 P ( y i =1| ω , x i )。一般认为,当 P ( y i =1| ω , x i )≥0.5时,可认为 y i =1。但在实际应用中,取0.5作为划分阈值并不理想。因此在机器学习领域里引入了诸多方法以选取合适的阈值,并顺势引入了新的评价分类模型的方法。
假设存在一个具有两个特征的数据集,如图3.18左图所示。
图3.18 待分类数据集与分类超平面
从图3.18中可以直观地看出,该问题明显属于线性不可分问题,但在误差允许范围之内,仍旧可以用线性分类器求解。应用逻辑回归,可以得出一个分类超平面,如图3.18右图所示,并得到形如式(3.7)的逻辑回归模型。于是,对于每个个体 x i ,都有:
由于 b 的选择不能主观断定,所以学者们引入了ROC(Receiver Operating Characteristic)曲线,以寻找最优的阈值。首先分别定义假阳性率(FPR)和真阳性率(TPR)为:
其中,FP、FN和TP等定义见2.4.1节。
对于每个阈值 b ,都可以计算出相应的FPR、TPR。分别以FPR、TPR为 x 轴和 y 轴,描出所有 b 值对应的FPR、TPR构成的曲线,这条曲线即为ROC曲线。
于是,对图3.18所示的数据集,在测试集上画出模型的ROC曲线如图3.19所示
。
图3.19 测试集上的ROC曲线
显然,我们希望TPR越高、FPR越低,因此应该选择图3.19中的圆圈部分。查出此处的阈值为 b =0.612。可见,0.5为阈值不一定是最好的。
同理,对于每一个阈值点,也可以通过式(2.23)和式(2.24)计算出相应的准确率(Precision)、回报率(Recall),并画出准确率-回报率曲线来选择阈值。
从2.4.1节中我们了解到,评价分类问题的指标有精确度、Jaccard系数、准确率、回报率和F-Beta值。除此之外,基于ROC曲线,机器学习学者们提出了另一个指标AUC(Area Under Curve,曲线下面积)。由于ROC曲线落在[0,1]处,如果ROC曲线以下的面积接近1,则证明该算法较为优异。这是因为如果AUC接近1,则表示无论阈值 b 取值为多少,分类器都能正确分类,所以模型的稳定性强。另外,AUC接近1,意味着TPR亦趋近1,模型的准确性较高。
因此,可以根据AUC的值评价模型的效果。就上例而言,可以目测出ROC曲线所围成的AUC已经接近1,可见该模型的效果可嘉。
现在有收集150条鸢尾花的特征与类别构成的数据(该数据集可以通过Sklearn自带的数据集导入),其中类别 y ={0,1,2},部分数据展示如表3.4所示。
表3.4 鸢尾花特征与类别数据(部分)
为了简化问题,这里将 y =2的所有数据点剔除,使之成为二分类问题。要求根据花的四个特征和提供的数据集,训练一个逻辑回归模型。
首先通过sklearn.datasets模块的load_iris函数导入IRIS数据集,删除类别为 y =2的所有个体后,将数据集按7∶3的比例拆分成训练集和测试集,代码如下。
注意: 这里省略了导入模块的代码,读者可直接参照代码文件进行获取。
通过sklearn.linear_model模块的LogisticRegression类,设置参数penalty为none,从而产生一个逻辑回归模型。然后分别在训练集和测试集中计算模型的精确度、准确率、召回率和F1值并将它们构成一个报表。该报表可以用sklearn.metrics模块的classification_report函数得到,实现代码如下(接上面的代码)。
运行上述代码,输出结果如下:
⑫ 0为类别0。将所有属于0的个体构成一个子数据集,然后计算模型在该子数据集中的拟合优度指标(support为子数据集的个体数)。
⑬将模型在各子数据集(子数据集由总数据集按类别划分而成)中的拟合优度取平均值得出。
从结果报表中可以看出,无论在测试集中还是训练集中,模型的拟合优度都是一流的。实际上,鸢尾花识别问题是一个线性可分问题,因此使用线性分类器能够正确地拟合它。至此,该问题已经告一段落。但为了巩固所学,这里将继续画出ROC曲线并计算AUC的值。
在Python中可以用sklearn.metrics模块中的roc_curve、auc函数,画出ROC曲线并计算AUC的值,代码如下。
运行以上代码即可画出ROC曲线,如图3.20所示,并得到AUC的值为1,从而进一步证明了模型是可取的。
图3.20 鸢尾花分类模型的ROC曲线
Tips: 使用sklearn.metrics模块可以计算出模型的拟合优度,如上述的classification_report、roc_curve和auc函数等。但在使用之前,务必要导入函数。除此之外,metrics中的make_scorer函数可以将metrics中的评价指标函数如accuray_score等封装到一个对象中,从而作为另一个函数的输入参数。这种做法通常在交叉验证(将后续章节介绍)及训练神经网络时。
就像硬币的两面一样,泾渭分明,机器学习也一样,如果训练集中两个类别的个体数为1∶1,则分类器不能“蒙混过关”。设想如果两类的个体数比例达到95∶5,那么一个只会点头的分类器也许能达到95%的精确度!这显然不是我们想要的。一般,我们称两个类别个体数相差过大为类别不均衡问题。
在实际应用中,这种95∶5的数据集是很常见的。例如,设计一个邮件过滤器时,人们都愿意提供他们的垃圾邮件,但在提供包含个人隐私的有效邮件时往往会犹豫不决。考虑到类别不均衡将会对模型产生严重的负面影响,本节将讨论类别不均衡的解决办法。
解决类别不均衡的一种方法是降低多数类的个体数,将该方法称为欠采样(under-sampling)。最容易想到的剔除方法是随机抽样删除,但因为随机抽样的方法剔除多数类个体会导致信息丢失,为了解决这个问题,学者们提出了如下思想并衍生了诸多方法。
一种是分组综合的思想。其是从多数类中随机采样,然后与少数类组合成多个类别平衡的训练集,接着训练多个模型再综合考虑其结果,如图3.21所示。
分组综合实现衍生的欠采样的方法有:简单集成(EasyEnsamble)和平衡级联(BalanceCascade)。两者的主要区分在于如何从子模型得到结果上。前者主要属于Bagging集成,后者使用了Boost集成。关于集成模型的内容将在第13章介绍。
图3.21 欠采样的基本思想
另一种缓解信息丢失的思想是原型选择(prototype selection),这种方法只保留多数类中具有代表性的样本,典型的方法是基于 K 近邻算法的NearMiss,其子方法和基本算法如表3.5所示。
表3.5 NearMiss方法与实现思路
另一种原型选择的算法是保留聚类中心:即采用聚类的算法,将特征相似的多数类个体聚成 M 个簇,仅保留 M 个簇的中心即可。
区别于原型保留,利用某种规则清理数据亦是欠采样的一种思想。常见的一种清理数据的方法仍是基于KNN算法:找出每个多数类个体的
k
个近邻,根据其与
k
个近邻的某种关系,考虑是否剔除这个个体。例如,编辑近邻算法
、重复编辑近邻算法
和AllkNN就是采用了这种方法。
清理数据法的一种最简单的实现为CNN(Condensed Nearest Neighbours,卷积神经网络)算法
,原理如下:
通常经过CNN算法后数据集仍旧处于不平衡状态,这时候往往结合KNN与CNN来剔除多数类数据点。例如近邻清理法则
算法,就用额外的KNN模型根据NearMiss方法,对CNN输出的数据集进一步剔除。
另一种是基于Tomek links。其定义为:假设两个不同类别的个体
x
i
,
y
j
,设
d
(
x
i
,
y
j
)为样本的距离
,如果不存在第3个样本个体
x
o
或
y
o
,使得
d
(
x
o
,
y
j
)<
d
(
x
i
,
y
j
)或
d
(
x
i
,
y
o
)<
d
(
x
i
,
y
j
)则称(
x
i
,
y
j
)为一个Tomek links对,如图3.22实线部分所示。
图3.22 Tomeklinks对示意
从图3.22中可以直观地看出,Tomek links包括多数类的边界点,如A、B、C,或噪声项,如D、E、F。但是对于95∶5的畸形数据来说,即使删除所有的Tomek links,也只是杯水车薪。虽然如此,我们还可以清理多余数据。例如虚线G内的个体分布比较密集,这时候就可以选择性地删除部分个体。实际上,上述的CNN算法正是实现了这一点。于是基于CNN与Tomek links就诞生了一种单边选择
算法,它剔除了多数类的边界、噪声项和多余数据。
综上所述,欠采样的方法如表3.6所示。如何选择这些算法,目前还没有通用的法则。如何选择算法,与其说是一门技术,不如说是一门艺术。根据实际效果选择算法才是合适的,这个原则也将贯穿机器学习的始末。
表3.6 欠采样方法总结
以单边选择算法为例,首先通过sklearn.datasets库的make_classification产生一个容量为1000、类别比例为95∶5的数据集,进行欠采样并输出处理后的数据集。与前面类似,imblearn实现欠采样亦是通过将函数封装在类中实现的。因此,在使用时需要先实例一个对象,再通过相应的接口采样数据。这里可以采用OneSidedSelection类来实现单边欠采样,并通过.fit_resample()接口实现类别不均衡。
运行上述代码,输出结果为“多数类个数:942;少数类个数:58;欠采样后多数类个数:826;欠采样后少数类个数:58”。
过采样旨在增加少数类样本来解决类别不均衡。同样,利用随机采样复制部分少数类样本的方法会导致过拟合。这是因为某些数据存在重复、权重变大现象,模型过分学习这些数据,从而导致泛化能力降低。因此,为了避免直接复制数据,可以考虑采用插值的方法。结合 K 近邻算法,学者们提出了SMOTE(Synthetic Minority Over-sampling Technique,合成少数类过采样技术)算法:
假设训练集的少数类个体数为 T ,向量 x i , i ∈(1,2,…, T )为其特征向量。定义每一个少数类个体需要合成的个体数为 N ( N >1),算法如下:
可以看出,SMOTE算法合成的少数类个体数为 NT ,其中, N 需要人工选定。为了避免人工选择,学者们提出了另一种自适应综合过采样算法(ADASYN),具体如下:
无论SMOTE还是ADASYN,少数类个体都以插值的方式产生新个体,这或多或少造成了某些区域个体过于密集的问题(overlapping),如图3.22的G所示。由于处于边界的个体更容易被错分,所以可以考虑适当地调整边界样本的权重以产生更多的个体,而不是让每个个体都产生同样个数的新个体,边界SMOTE(Borderline SMOTE)算法就是基于这种想法实现的。
对于带有离散变量的混合特征 x i ,( x j − x i )无法计算。因此,在产生新个体时,可以考虑用近邻中出现频率最高的值替代差值,如SMOTENC算法。
针对产生新个体 x newj 的方式,SVM-SMOTE算法结合了支持向量来合成新个体,从而避免了插值产生新个体造成的密集问题。
结合聚类中心,Kmeans-SMOTE算法考虑对少数类进行聚类,对聚类中心进行SMOTE,同时降低其余数据点产生新个体的数量。
综上所述,过采样的方法如表3.7所示。同样,如何选择这些算法需要根据实践的检验。
表3.7 过采样方法总结
同样用make_classification函数产生不均衡数据集,并使用边界SMOTE算法进行过采样。
运行以上代码,可得输出结果为“多数类个数:94;少数类个数:58;欠采样后多数类个数:942;欠采样后少数类个数:942”。
Tips: imblearn模块为Sklearn的扩展模块,亦需要通过pip下载和安装。可以看到,使用欠采样后,多数类个体数量降低,而少数类不变。但是,似乎欠采样得出的结果并不能完全解决类别不均衡问题,而过采样则可以比较完美地解决。因此在实际应用中,通常先进行欠采样,再使用过采样。这样做的好处是,在一定程度上避免了过采样的信息重复问题,同时也解决了欠采样无法解决类别不均衡的问题。
由于分类器本质上输出的不是 y 属于哪个类,而是 y 属于这个类的概率是多少,所以除了从数据集入手解决类别不均衡问题外,还可以调整分类器的阈值 b 。3.4.3节曾经讲过用ROC曲线寻找阈值,部分原因正是为了解决类别不均衡问题。除此之外,还可以直接设置阈值为:
其中, T ′为多数类样本的个体数, T 为少数类样本的个体数。
对于某些模型而言,如逻辑回归、支持向量机等,它们的输出为一个概率值或两种可能的取值,因此它们不可以直接运用于多分类问题中。可以考虑将多分类数据集“分而治之”,从而转换为多个二分类问题,进而采用多个二分类模型来解决。对数据集“分而治之”,有如下方法。
假设一共有 C 个类别,使用One vs Remain(OvR)的方法首先需要训练 C 个分类器,再根据这 C 个分类器判断最终分类。以 C =4为例,如图3.23(a)所示,首先将数据集按 y 划分为4份(不一定是等份),对于一份数据集,将其标记为对勾,将剩余的数据集标记成叉号并组成一个子训练集,共 C 组。训练 C 个模型,综合这 C 个模型的输出结果得出最终的结论。
图3.23 当 C =4时使用OvR与OvO方法求解多分类问题
One vs One(OvO)为每次从所有类别中挑选两个类别的数据集,进而训练
个分类器,并根据投票原则判断最终的分类。如图3.23(b)所示,以
C
=4为例,使用两两组合的数据集作为训练集来训练多个分类器,按照投票法决定最终结果。
仍旧以鸢尾花分类问题为例,这次我们保留所有类别。使用OvR的方式,应用逻辑回归模型进行多分类,代码如下。
注意: 为了突出重点,上述代码没有划分数据,这样做是不对的。
除了OvR和OvO以外,Many vs Many(MvM)亦是一种有效的办法。这里介绍一种常用的MvM方法,即纠错编码法(ECOC)。假设数据集共有 C 类,数据集的容量为 D 。首先将数据集分成为 M 等份,记每份为 D i , i ∈(1,2,…, M )。对每个 D i ,从 C 类中任选 n 1 个类别,记为正类、其余的 n 2 = n − n 1 为反类,训练 M 个二分类模型 f i 。
输入一个待分类特征向量 x ,令全体 f i 对其预测,得到 f i 对 x 的预测结果向量,从而根据距离判断 x 的所属类别。以 C =4, M =5为例,其方法如图3.24所示。首先将数据集拆分成5等份,分别用于训练子模型 f i ,其中,对应位置为+1表示在子数据集 D i 中,类 C i 被标为正类。如果在子数据集 D 1 里,属于 C 1 、 C 4 的为正类,其余为负类。
图3.24 以 C =4为例,利用多对多解决多分类问题
根据以上划分训练出 f 1~5 之后,将待分类个体通过模型 f 1~5 分别得出5个分类结果。之后,将这些结果构成一个向量r,并计算其与 C i =( f i 1 , f i 2 ,… f i 5 )的距离,距离最近的 C i 即为未知个体 x 的所属类。