在面试中会经常碰到考察对数据挖掘算法的熟悉程度,面试官会出一道题或给出一些数据,让你结合实际谈谈你选择什么模型,该模型的大致原理是什么,使用条件有哪些,模型优缺点,如何选择特征,模型如何调参优化,如何评估模型效果等。
以下将要介绍逻辑回归,以历史数据判断银行或P2P金融机构客户贷款违约情况。
逻辑回归是用来做分类任务的。分类任务的目标是找一个函数,把观测值匹配到相关的类或标签上。算法必须用成对的特征向量和对应的标签来估计匹配函数的参数,从而实现更好的分类效果。在二元分类中,分类算法必须把一个实例配置两个类别。二元分类案例包括预测患者是否患有某种疾病,音频中是否含有人声,篮球队在NCAA比赛中的输赢。
普通的线性回归假设响应变量呈正态分布,也称为高斯分布或钟形曲线。正态分布数据是对称的,且均值,中位数和众数(mode)是一样的。很多自然现象都服从正态分布。比如,人类的身高就服从正态分布,姚明那样的高度极少,在99%之外了。
在某些问题里,响应变量不是正态分布的。比如,掷一个硬币获取正反两面的概率分布是伯努力分布,又称两点分布或者0-1分布。表示一个事件发生的概率是P,不发生的概率1−P,概率在{0,1}之间。线性回归假设解释变量值的变化会引起响应变量值的变化,如果响应变量的值是等概率的,这条假设就不满足了。广义线性回归去掉了这条假设,用一个联函数来描述解释变量与响应变量的关系。普通线性回归作为广义线性回归的特例使用的是恒等联连函数,将解释变量的通过线性组合的方式来联接服从正态分布的响应变量。如果响应变量不服从正态分布,就要用另外一种联连函数了。
在逻辑回归里,响应变量描述了类似于掷一个硬币结果为正面的概率。如果响应变量等于或超过了指定的临界值,预测结果就是正面,否则预测结果就是反面。响应变量是一个像线性回归中的解释变量构成的函数表示,称为逻辑函数,如下所示:
下面是t在(-6,6)的图形:
import matplotlib.pyplot as plt from matplotlib.font_manager import FontProperties font = FontProperties(fname=r"c:windowsfontsmsyh.ttc", size=10) import numpy as np plt.figure() plt.axis([-6, 6, 0, 1]) plt.grid(True) X = np.arange(-6,6,0.1) y = 1 / (1 + np.e ** (-X)) plt.plot(X, y, 'b-') plt.show()
在逻辑回归中,t 是解释变量的线性组合,公式如下:
对数函数(logit function)是逻辑函数的逆运算:
定义了逻辑回归的模型之后,我们用它来完成一个分类任务。
Logistic 回归 (LR)就是一个被logistic方程归一化后的线性回归,仅此而已。
至于所以用logistic而不用其它,是因为这种归一化的方法往往比较合理(人家都说自己叫logistic了嘛 呵呵),能够打压过大和过小的结果(往往是噪音),以保证主流的结果不至于被忽视。
Logistic回归(LR) 的适用性
1) 可用于概率预测,也可用于分类。
并不是所有的机器学习方法都可以做可能性概率预测(比如SVM就不行,它只能得到1或者-1)。可能性预测的好处是结果又可比性:比如我们得到不同广告被点击的可能性后,就可以展现点击可能性最大的N个。这样以来,哪怕得到的可能性都很高,或者可能性都很低,我们都能取最优的topN。当用于分类问题时,仅需要设定一个阈值即可,可能性高于阈值是一类,低于阈值是另一类。
2) 仅能用于线性问题
只有在feature和target是线性关系时,才能用Logistic Regression(不像SVM那样可以应对非线性问题)。这有两点指导意义,一方面当预先知道模型非线性时,果断不使用Logistic Regression; 另一方面,在使用Logistic Regression时注意选择和target呈线性关系的feature。
3) 各feature之间不需要满足条件独立假设,但各个feature的贡献是独立计算的。
逻辑回归不像朴素贝叶斯一样需要满足条件独立假设(因为它没有求后验概率)。但每个feature的贡献是独立计算的,即LR是不会自动帮你combine 不同的features产生新feature的 (时刻不能抱有这种幻想,那是决策树,LSA, pLSA, LDA或者你自己要干的事情)。举个例子,如果你需要TF*IDF这样的feature,就必须明确的给出来,若仅仅分别给出两维 TF 和 IDF 是不够的,那样只会得到类似 a*TF + b*IDF 的结果,而不会有 c*TF*IDF 的效果。
LR分类器(Logistic Regression Classifier),在分类情形下,经过学习之后的LR分类器其实就是一组权值w0,w1,w2,...,wm.
这一组权值是如何求得的呢?这就需要涉及到极大似然估计概念了,这里不作深究。
当加入测试样本集中的测试数据时,这一组权值按照与测试数据线性加和的方式,求出一个z值:
z = w0+ w1 * x1 + w2 * x2 + ... + wm * xm 。(其中x1,x2,...,xm是样本数据的各个特征,维度为m)
之后按照sigmoid函数的形式求出:
sigma(z) = 1/(1+exp(z))
由于sigmoid函数的定义域是(-inf,inf),而值域为(0,1)。因此最基本的LR分类器适合对两类目标进行分类。
我们将sigmoid函数看成是样本数据的概率密度函数,每一个样本点,都可以通过上述的公式计算出其概率密度。
LR建模过程
读取数据
#-*- coding: utf-8 -*- import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
data = pd.read_excel("E:/destop/text/bankloan.xls")
数据探索
数据探索是建模人员了解特征时使用的方法,可以通过数据表或是图形的方式了解整体数据。
print data.describe().T
查看数据的分布
# 去除缺失值
data1 = data[u'负债率'].dropna() sns.distplot(data1)
#用来正常显示中文标签
plt.rcParams['font.sans-serif'] = ['SimHei']
#用来正常显示负号
plt.rcParams['axes.unicode_minus'] = False plt.show()
查看离散情况
plt.boxplot(data1) plt.show()
特征选择
特征选择是模型成功的基础性重要工作。一般特征筛选方法有
(1)看模型系数显著性。通过F检验给出各个特征的F值和P值,选出F值大、P值小的变量。
(2)递归特征消除(RFE):反复构建模型,根据变量系数选择最好特征,然后再递归在剩余变量上重复该过程,直到遍历所有特征。特征被挑选出顺序就是特征重要性排序顺序。
(3)稳定性选择:在不同特征子集、数据子集上运行算法,不断重复,最终汇总特征选择结果。统计,各个特征被认为是重要性特征的频率作为其重要性得分(被选为重要特征次数除以它所在子集被测试次数)。
这里选用第3种:
x = data.iloc[:,:8].as_matrix()
y = data.iloc[:,8].as_matrix()
from sklearn.linear_model import LogisticRegression as LR
from sklearn.linear_model import RandomizedLogisticRegression as RLR
#建立随机逻辑回归模型,筛选变量,特征筛选用了默认阈值0.25
rlr = RLR(selection_threshold=0.25)
#训练模型
rlr.fit(x, y)
#获取特征筛选结果,也可以通过.scores_方法获取各个特征的分数
rlr.get_support()
print(u'有效特征为' % ','.join(data.columns[rlr.get_support()]))
模型筛选出的特征为: 工龄,地址,负债率,信用卡负债
x = data[data.columns[rlr.get_support()]].as_matrix()
#建立LR模型
lr = LR()
lr.fit(x, y)
print(u'模型的平均准确率' % lr.score(x, y))
LR模型训练结束,最终模型的平均正确率为:81.4%
用测试集预测
filename1 = 'E:/destop/text/te.xls' te = pd.read_excel(filename1)
# 8个属性 xte =te.iloc[:, :8].as_matrix()
# 第九列 结果标签 yte= te.iloc[:, 8].as_matrix()
#筛选特征
xte1 = te[te.columns[rlr.get_support()]].as_matrix()
#预测
pte=lr.predict(xte1)
Print pte
二元分类效果评估方法
二元分类的效果评估方法有很多,常见的包括准确率(accuracy),精确率(precision)和召回率(recall)三项指标,以及综合评价指标(F1 measure), ROC AUC值(Receiver Operating Characteristic ROC,Area Under Curve,AUC)。这些指标评价的样本分类是真阳性(true positives),真阴性(true negatives),假阳性(false positives),假阴性(false negatives)。阳性和阴性指1,0分类,真和假指预测的正确与否。
在本案例分类里,真阳性是指分类器将一个实际违约客户分辨为1(违约)类。真阴性是指分类器将一个正常客户分辨为0(不违约)类。假阳性是指分类器将一个正常短信分辨为1(违约)类。假阴性是指分类器将一个违约客户分辨为0(不违约)类。混淆矩阵(Confusion matrix),也称列联表分析(Contingency table)可以用来描述真假与阴阳的关系。矩阵的行表示实际类型,列表示预测类型。
预测类别 | |||
---|---|---|---|
实际类别 | 0(预测不违约) | 1(预测违约) | |
0(实际不违约) | TN | FP | |
1(实际违约) | FN | TP |
from sklearn.metrics import confusion_matrix import matplotlib.pyplot as plt plt.rcParams['font.sans-serif'] = ['SimHei'] #用来正常显示中文标签 plt.rcParams['axes.unicode_minus'] = False #用来正常显示负号 confusion_matrix = confusion_matrix(yte,pte) print(confusion_matrix) plt.matshow(confusion_matrix) plt.colorbar() plt.ylabel(u'实际类型') plt.xlabel(u'预测类型') plt.show()
预测类别 | |||
---|---|---|---|
实际类别 | 0(预测不违约) | 1(预测违约) | |
0(实际不违约) | 70 | 7 | |
1(实际违约) | 13 | 11 |
测试集一共有101条记录,正确分类的有81条,占比80.19%,错误分类的有20条,占比19.8%,其中有7个实际不违约的客户错误判别为“违约”,有13个实际违约客户错误判别为“不违约”。
在本案例分类器中,精确率是指分类器预测出的客户中真的是违约的比例:
召回率在医学领域也叫做灵敏度(sensitivity),在本例中是指所有真的违约客户被分类器正确找出来的比例。
精确率和召回率各自含有的信息都很少,它们对分类器效果的观察角度不同。精确率和召回率都不能从表现差的一种分类器中区分出好的分类器。例如,假设一个测试集包括10个阳性和0个阴性结果。分类器即使将每一个样本都预测为阳性,其召回率都是1:
分类器如果将每一个样本都预测为阴性,或者只是预测出假阳性和真阴性,其召回率都是0。类似的,一个分类器如果只预测一个样本,结果为阳性,而且这个样本确实为阳性,那么这个分类器就是100%精确的了。
scikit-learn结合真实类型数据,提供了一个函数来计算一组预测值的精确率和召回率。
import numpy as np import pandas as pd from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.linear_model.logistic import LogisticRegression from sklearn.cross_validation import train_test_split, cross_val_score precisions = cross_val_score(lr,xte1,yte, cv=5, scoring='precision') print(u"精确率:", np.mean(precisions), precisions) recalls = cross_val_score(lr,xte1,yte, cv=5, scoring='recall') print(u'召回率', np.mean(recalls), recalls)
(精确率:':0.5066666666666666, array([ 0.75, 0.33333333, 0.75, 0.5, 0.2))
(召回率: 0.37, array([ 0.6 , 0.2 , 0.6 , 0.2 , 0.25]))
我们的分类器精确率50.6%,分类器预测出的违约客户中50.6%都是真的违约。召回率比较低37%,就是说真实的违约客户中,63%被当作正常客户了,没有被识别出来。这些数据会不断变化,因为训练集和测试集是随机抽取的。
综合评价指标(F1 measure)是精确率和召回率的调和均值(harmonic mean),或加权平均值,也称为F-measure或fF-score。
即
综合评价指标平衡了精确率和召回率。一个二元分类模型,精确率和召回率为1,那么综合评价指标为1。如果精确率或召回率为0,那么综合评价指标为0。scikit-learn也提供了计算综合评价指标的函数。
f1s = cross_val_score(lr,xte1,yte, cv=5) print('综合评价指标:', np.mean(f1s), f1s)
综合评价指标:0.76060150375939839, array([ 0.85714286, 0.71428571, 0.85 , 0.75 , 0.63157895]))
本例的综合评价指标是76%
ROC曲线(Receiver Operating Characteristic,ROC curve)可以用来可视化分类器的效果。和准确率不同,ROC曲线对分类比例不平衡的数据集不敏感,ROC曲线显示的是对超过限定阈值的所有预测结果的分类器效果。ROC曲线画的是分类器的召回率与误警率(fall-out)的曲线。误警率也称假阳性率,是所有阴性样本中分类器识别为阳性的样本所占比例:
AUC是ROC曲线下方的面积,它把ROC曲线变成一个值,表示分类器随机预测的效果。scikit-learn提供了计算ROC和AUC指标的函数
from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.linear_model.logistic import LogisticRegression from sklearn.cross_validation import train_test_split, cross_val_score from sklearn.metrics import roc_curve, auc false_positive_rate, recall, thresholds = roc_curve(yte,pte) roc_auc = auc(false_positive_rate, recall) plt.title('Receiver Operating Characteristic') plt.plot(false_positive_rate, recall, 'b', label='AUC = %0.2f' % roc_auc) plt.legend(loc='lower right') plt.plot([0, 1], [0, 1], 'r--') plt.xlim([0.0, 1.0]) plt.ylim([0.0, 1.0]) plt.ylabel('Recall') plt.xlabel('Fall-out') plt.show()
。