分类与预测之回归分析

分类

即构造一个分类模型,将每个样本映射到预先定义好的类别,输入样本的属性特征,输出类别。
分类模型建立在已有类标的数据集上,属于有监督的学习。
下图是分类算法与分类模型的过程。预测模型与之相似,首先通过训练机建立预测属性的函数模型,然后在模型通过检验后进行预测或控制。

常用的分类与预测算法

  • 回归分析
  • 决策树
  • 人工神经网络
  • 贝叶斯网络
  • 支持向量机

回归分析

回归分析是确定两种或两种以上变量间相互依赖的定量关系的一种统计分析方法,在图像上表现为一条努力拟合所有数据点的曲线/线段,其目标是使数据点和曲线间的距离最小化。
回归分析的优点有很多,主要表现在:
1.能显示因变量和自变量之间的显著关系;
2.能表现多个独立变量对因变量对不同影响程度。

常见的回归模型如下表所示:

回归模型 适用条件
线性回归 因变量与自变量是线性关系
非线性回归 因变量与自变量之间不都是线性关系
Logistic回归 因变量一般有1和0(是否)两种取值
岭回归 参与建模的自变量之间具有多重共线性
主成分回归 参与建模的自变量之间具有多重共线性

此外,还有Lasso回归、ElasticNet回归等模型

线性回归 Linear Regression

线性回归采用一条拟合直线在因变量(Y)和一个或多个自变量(X)之间建立关系:

回归就是求解回归系数$\theta$,一般有最小二乘法、梯度下降来求解。

Logistic回归

LR模型中的因变量只有1-0(是-否、发生-不发生)两种取值。

Logistic函数

假设在$p$个独立变量$x_1,x_2,…,x_p$作用下,$y$取1的概率是$p$,取0的概率是$1-p$,两种取值的概率比为$\frac{p}{1-p}$,被称为事件的优势比(odds),对其取自然对数就是Logistic变换:
令$Logit(p)=z$,那么$p=\frac{1}{1+e^{-z}}$就是Logistic函数,如下图所示:

Logistic回归模型

Logistic回归模型为:

Logistic回归建模

step1:根据挖掘目的设置特征(因变量和自变量),收集数据并筛选特征;
step2:$y$取1的概率是$p$,取0的概率是$1-p$,列出回归方程$ln(\frac{p}{1-p}=\beta_0+\beta_1x_1+…+\beta_px_p+\epsilon)$,并估计回归系数;
step3:进行模型检验,正确率、混淆矩阵、ROC曲线、KS值等;
step4:模型应用:输入自变量得到预测变量的值,或根据预测变量的值控制自变量的值。

实例:降低银行贷款拖欠率

部分银行贷款拖欠率数据如下图:

使用Scikit-Learn对该数据进行Logistic回归分析。
首先进行特征筛选:特征筛选主要包含在Scikit_Learn的feature_selection库中

  • 通过F检验(f_regression)给出各个特征的F值和P值,从而筛选变量(选择F值较大的或P值小的)
  • 递归特征消除(Recursive Feature Elimination,RFE)
  • 稳定性选择

这里采用稳定性选择的方法进行特征筛选,然后用筛选后的特征建立Logistic模型,并输出平均正确率。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#-*- coding: utf-8 -*—
import pandas as pd
data_path = '/data/bankloan.xls'
data = pd.read_excel(data_path)
x = data.iloc[:,:8].as_matrix()#数据前8列是特征
y = data.iloc[:,8].as_matrix()#数据第8列是标签

from sklearn.linear_model import LogisticRegression as LR
from sklearn.linear_model import RandomizedLogisticRegression as RLR
rlr = RLR()#建立随机逻辑回归模型,筛选变量,默认selection_threshold=0.25
rlr.fit(x,y)#训练模型
rlr.get_support()#获取特征筛选结果
#a = rlr.scores_ #也可以用.scores来获取各个特征的分数
print('--- 稳定性选择法-筛选特征已完成 ---')
#'numpy.ndarray' object has no attribute 'columns'
#所以不能采用x.columns[rlr.get_support()]
print('有效特征为:%s' % ','.join(data.iloc[:,:8].columns[rlr.get_support()]))
x = data[data.iloc[:,:8].columns[rlr.get_support()]].as_matrix()#特征筛选后的x
print(x)

lr = LR()#建立逻辑回归模型
lr.fit(x,y)#用筛选后的特征来训练模型
print('--- 逻辑回归模型训练结束 ---')
print('模型的平均正确率为:%s' % lr.score(x,y))

关于代码的解读已经打在注释里了,这里主要说明一下RLR一般被认为是属于维度规约的算法类,不属于常说的分类算法的范畴。
输出结果如图:

看到过这么一句话:
数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限。
可见特征的选择是一件重要的事情,减少特征数量并降维使得模型泛化能力更强并增强特征和特征值之间的理解。下面主要来讲一讲特征筛选。
训练模型时,我们要选择有意义的特征,主要从以下两方面进行考虑:
1.特征是否发散:如果特征不发散,比如方差接近0,那么可以认为样本在该特征上无差异,该特征对于区分样本是没有用的。
2.特征与目标的相关性:即选择与目标相关性高的特征。
根据特征选择的形式可以将特征选择法分为3种:Filter过滤法、Wrapper包装法、Embedded嵌入法。
1.Filter:按照发散性或相关性对各个特征进行评分,设定阈值或待选择阈值的个数来选择特征。

  • 去掉取值变化小的特征

非常简单的方法,简单的说就是如果一个特征的特征值只有0和1,并且大部分或者全部都是1,那么就可以认为该特征没有什么作用(如果是连续型变量,则要先离散化),但这种情况其实很少出现,所以该方法不太常用,一般作为特征选择的预处理,方便后续特征筛选。

1
2
3
from sklearn.feature_selection import VarianceThreshold as VT
VT(threshold = 3).fit_transform(data) #threshold为方差的阈值
#返回值为特征选择后的数据
Tip:在这里我想简单的说一下sklearn中fit_transform()和transform()的区别
两者都是对数据作某种统一处理,fit_transform(partData)是对数据先进行**拟合**,然后再作归一化处理;
fit完数据后,transform(restData),那么rest和part是按照同一标准进行数据处理的;
如果是fit_transform(partData),虽然也能做数据处理,但是与partData的处理不在相同标准下,处理完后会有明显差异;
如果没有fit,直接transform(partData),则会报错。
  • 单变量特征选择

对每个特征进行测试,衡量该特征和特征值之间的关系,根据评分去掉不好的特征。这种方法简单便于理解,但对于特征优化、提高模型泛化能力不一定有效。
对于分类问题(y离散),可采用:卡方检验、f_classif、mutual_info_classif、互信息
对于回归问题(y连续),可采用:皮尔森相关系数、f_regression、mutual_info_regression、最大信息系数
Pearson相关系数:最简单,帮助计算各个特征对目标值的相关系数以及相关系数的P值,衡量变量之间的线性相关性,结果取值$[-1,1]$,-1表示完全负相关、+1表示完全正相关、0表示没有线性相关。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from sklearn.feature_selection import SelectKBest#只保留K个最高分的特征
from sklearn.feature_selection import SelectPercentile#只保留用户指定百分比的最高得分的特征
#from sklearn.feature_selection import chi2#卡方检验
#from scipy.stats import pearsonr
#SelectKBest和SelectPerecntile能够返回特征评价的得分和P值
x = SelectKBest(score_fun,k=2).fit_transform(data,target)#K值自己设,percentile值也是自己设定
x = SelectPercentile(score_fun,percentile = 10)#score_fun为评分函数,例如卡方检验chi2等,具体的上文已经给出
#卡方检验
from sklearn.feature_selection import chi2
x_new = SelectKBest(chi2,k=2).fit_transform(x,y)#这时x变为两个特征
#皮尔森相关系数:要求变量变化关系单调
from scipy.stats import pearsonr
#pearsonr(x,y)的输入为特征矩阵和目标向量
pearson(X,Y) #输出为二元组(score,p-value)的数组
#SelectKBest(lambda X, Y: array(map(lambda x:pearsonr(x, Y), X.T)).T, k=2).fit_transform(data,target)
#互信息法:评价定性自变量对定性因变量的相关性
from minepy import MINE
m = MINE()
m.compute_score(x,y)
m.mic()

2.Wrapper:根据目标函数(一般是预测效果评分),每次选择若干特征,或排除若干特征。
递归特征消除RFE:使用一个基模型来进行多轮训练,每轮训练后,移除若干权值系数的特征,再基于新的特征集进行下一轮训练

递归特征消除的主要思想时反复的构建模(SVM、回归模型等)。
选出最好的(或最差的)特征,把选出来的特征放在一边,在剩余特征上重复该过程,遍历所有特征。
该过程中特征被消除的次序就是特征的排序。
Scikit-Learn中提供了RFE、RFECV,可以进行交叉验证。
1
2
3
4
5
from sklearn.feature_selection import RFE
from sklearn.linear_model import LogisticRegression
#estimator为基模型,这里为LR模型
#返回特征选择后的数据
RFE(estimator = LogisticRegression(),n_feature_to_select = 2).fit_transform(data,target)

3.Embedded:根据ML的算法和模型进行训练,得到各个特征的权值系数,根据系数从大到小选择特征,与Filter法类似,只不过是根据模型训练来选择特征。
SelectFromModel:能够用于拟合后任何拥有coef_或feature_importances_ 属性的预测模型。 如果特征对应的coef_ 或 feature_importances_ 值低于设定的阈值threshold,那么这些特征将被移除。

基于L1范数的特征选择:使用L1范数作为惩罚项的线性模型(Linear models)会得到稀疏解:大部分特征对应的系数为0。当你希望减少特征的维度以用于其它分类器时,可以通过feature_selection.SelectFromModel 来选择不为0的系数。
linear_model.Lasso(回归)linear_model.LogisticRegressionsvm.LinearSVC(分类)这些模型较为常用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from sklearn.svm import LinearSVC
from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectFromModel
iris = load_iris()
x,y = iris.data,iris.target

SelectModel(LinearSVC(penalty = 'l1',c = 0.01)).fit_transform(x,y)
#lsvc = LinearSVC(c = 0.01,penalty = 'l1',dual = False).fit(x,y) #C越小,被选中的特征越少
#model = SelectFromModel(lsvc,prefit = True)
#x_new = model.transform(x)

#带L1惩罚项的逻辑回归作为基模型的特征选择
from sklearn.linear_model import LogisticRegression
SelectModel(LogisticRegression(penalty = 'l1',c = 0.1)).fit_transform(x,y)

但是,该方法存在局限性:如果两个特征相关时,只会选择其中一个特征。

随机稀疏模型:为了解决上述问题,可以使用sklearn.linear_model中的stability selection这种随机化方法。在stability selection(稳定性选择)中,使用数据的子集去拟合模型,系数的随机子集的罚项将被小。

稳定性选择是一种基于二次抽样和选择算法(回归、SVM等)相结合的较新方法。
主要思想时在不同数据子集和特征子集上运行特征选择算法,不断重复,最紫红汇总特征选择结果。
理想特征得分接近100%,无用特征接近0。
Scikit-Learn在Lasso和RLR中都有稳定性选择的实现。

基于决策树的特征选择:可以算特征的重要程度,所以反过来也可以去除不相关的特征

1
2
3
4
5
6
7
8
9
10
11
12
from sklearn.ensemble import ExtraTreesClassifier
from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectFromModel
iris = load_iris()
x,y = iris.data,iris.target
#print(x.shape) #(150,4)
clf = ExtraTreesClassifier()
clf = clf.fit(x,y)
#print(clf.feature_importances_) #[0.04973085 0.05026085 0.49297071 0.4070376 ]
model = SelectFromModel(clf,prefit = true)
x_new = model.transform(x)
#print(x.shape) #(150,2)

逻辑回归本质上依然属于线性模型,被筛选掉的特征只是与结果不具有较强的线性关系而已,可能会具有非线性关系,具体问题具体分析。
对于非线性变量的筛选可以依靠决策树、神经网络等