Python逻辑回归原理及实际案例应用
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Python逻辑回归原理及实际案例应⽤
前⾔
⽬录
1. 逻辑回归
2. 优缺点及优化问题
3. 实际案例应⽤
4. 总结
正⽂
在前⾯所介绍的线性回归, 岭回归和Lasso回归这三种回归模型中, 其输出变量均为连续型, ⽐如常见的线性回归模型为:
其写成矩阵形式为:
现在这⾥的输出为连续型变量, 但是实际中会有'输出为离散型变量'这样的需求, ⽐如给定特征预测是否离职(1表⽰离职, 0表⽰不离职). 显然这时不能直接使⽤线性回归模型, ⽽逻辑回归就派上⽤场了.
1. 逻辑回归
引⽤百度百科定义
逻辑(logistic)回归, ⼜称logistic回归分析,是⼀种⼴义的线性回归分析模型,常⽤于数据挖掘,疾病⾃动诊断,经济预测等领域。
也就是说逻辑回归是从线性回归模型推⼴⽽来的, 我们从假设函数开始说起.
1. 假设函数
现假设因变量取值0和1, 在⾃变量X的条件下因变量y=1的概率为p, 记作p=P(y=1|X), 那么y=0的概率就为1-p, 把因变量取1和取0的概率⽐值p/(1-p)称为优势⽐, 对优势⽐取⾃然对数, 则可以得到Sigmoid函数:
令Sigmoid(p)=z, 则有:
⽽Logistic回归模型则是建⽴在Sigmoid函数和⾃变量的线性回归模型之上(这可能就是为什么带有'回归'⼆字的原因吧), 那么Logistic回归模型可以表⽰为:
上式也常常被称为逻辑回归模型的假设函数, 其函数图像为:
通过图像可以看出
的取值范围为
, h(x)的取值范围为[0, 1], 对于⼆分类问题来说, h(x)>=0.5则y=1, h(x)<0.5则y=0, ⽽且通过图像得知:="">
时, h(x)>=0.5, 因此
时y=1, 否则y=0.
模型的假设函数知道了, 接下来看看损失函数.
2. 损失函数
既然逻辑回归是建⽴在线性回归模型之上, 那么我们先来回顾线性回归的损失函数:
如果将我们逻辑回归的假设函数代⼊上式损失函数, 绘制出来的图像则是⾮凸函数, 其很容易产⽣局部最优解, ⽽⾮全局最优解, 为了找到使得全局最优解, 我们需要构造⼀个凸函数.
由于对数函数能够简化计算过程, 因此这⾥也是通过对数函数来构建, 先来回归下对数函数的图像(原图来⾃百度百科):
通过上图可以发现绿线部分与我们要构造的凸函数较接近. 当a=e时, 绿线部分可以分别表⽰为: -log e(x)和-log e(1-x). 现将x替换为h(x)并同时加⼊输出变量y (取值为1或0), 则有:
当上式中的y=1时, 其结果为-log e h(x); 当y=0时, 其结果-log e[1-h(x)].
最后, 将上式代⼊我们的损失函数中, 则有:
当然, 也可以⽤统计学中的极⼤似然法构造出上式损失函数. 损失函数有了, 下⼀步则是求解损失函数最⼩的算法了.
3. 算法
常⽤的求解算法有梯度下降法, 坐标轴下降法, 拟⽜顿法. 下⾯只介绍梯度下降法(其他⽅法还未涉及)
你也许会有疑问, 既然是线性回归模型推⼴⽽来, 那么为什么没有最⼩⼆乘法呢? 最⼩⼆乘法是⽤来求解最⼩误差平⽅和的算法, ⽽误差的平⽅和正是我们上⾯提到的线性回归的损失函数, 通过其构造出来的逻辑回归的损失函数是⾮凸的不容易找到全局最优解, 故不选⽤最⼩⼆乘法, ⽽通过极⼤似然法则可以构造出凸函数, 进⽽可以使⽤梯度下降法进⾏求解.
对于梯度下降法的理解在这节, 这⾥直接给出其表⽰:
具体的求解过程:
因此, 我们的梯度下降法可以写成(其中, x0=1):
上式也被称为批量梯度下降法, 另外两种: 随机梯度下降法和⼩批量梯度下降法分别表⽰为:
2. 优缺点及优化问题
1. 优点
1) 模型简单, 训练速度快, 且对于输出变量有很好的概率解释
2) 可以适⽤连续型和离散型⾃变量.
3) 可以根据实际需求设定具体的阀值
2. 缺点
1) 只能处理⼆分类问题.
2) 适⽤较⼤样本量, 这是由于极⼤似然估计在较⼩样本量中表现较差.
3) 由于其是基于线性回归模型之上, 因此其同样会出现多重共线性问题.
4) 很难处理数据不均衡问题
3. 优化
1) 可以在⼆分类上进⾏推⼴, 将其推⼴到多分类回归模型
2) 对于多重共线性问题, 也可以通过删除⾃变量, 进⾏数据变换, 正则化, 逐步回归, 主成分分析等⽅法改善, 对于正则化逻辑回归同样有两种: L1和L2,其分别表⽰为:
L1正则化
L2正则化
3. 实际案例应⽤
1. 数据来源及背景
数据来源: https:///jiangzuo/hr-comma-sep/version/1
该数据集包含14999个样本以及10个特征, 通过现有员⼯是否离职的数据, 建⽴模型预测有可能离职的员⼯.
2. 数据概览
1) 查看前2⾏和后2⾏数据
import pandas as pddf = pd.read_csv(r'D:\Data\HR_comma_sep.csv')pd.set_option('display.max_rows', 4)df
10个字段分别是: 员⼯对公司满意度, 最新考核评估, 项⽬数, 平均每⽉⼯作时长, ⼯作年限, 是否出现⼯作事故, 是否离职, 过去5年是否升职, 岗位, 薪资⽔平.
员⼯岗位有10种, 其中最多的是销售, 多达4140.薪资⽔平共有3个等级, 最多的是低等, 多达7316.
2. 对公司满意度与是否离职的关系
3. 最新考核评估与是否离职的关系
boxplot = Boxplot('最新评估与是否离职关系图', title_pos='center')x_axis = ['在职', '离职']y_axis = [df[df.left == 0].evaluation.values, df[df.left == 1].evaluation.values]boxplot.add('', x_axis, boxplot.prepare_data(y_axis))boxplot.render()
5. 平均每⽉⼯作时长和是否离职的关系
boxplot = Boxplot('平均每⽉⼯作时长与是否离职关系图', title_pos='center')x_axis = ['在职', '离职6. ⼯作年限和是否离职的关系
7. 是否发⽣⼯作事故与是否离职的关系
8. 5年内是否升职与是否离职的关系
promotion_left = pd.crosstab(df.promotion, df.left)attr = promotion_left.indexbar = Bar('5年内是否升职与是否离职的关系图
title_pos='center')bar.add('离职', attr, promotion_left[1], is_stack=True)bar.add('在职', attr, promotion_left[0], is_stack=True, legend_pos='left' ,
10. 薪资⽔平和是否离职的关系
5. 特征⼯程
1. 离散型数据处理
离散型数据可分为两种: ⼀种是定序, ⼀种是定类.
1) 定序
薪资⽔平其含有顺序意义, 因此将其字符型转化为数值型
df['salary'] = df.salary.map({'low': 0, 'medium': 1, 'high': 2})df.salary.unique()array([0, 1, 2], dtype=int64)
2) 定类
岗位是定类型变量, 对其进⾏one-hot编码, 这⾥直接利⽤pandas的get_dummies⽅法.
df_one_hot = pd.get_dummies(df, prefix='dep')df_one_hot.shape(14999, 19)
2. 连续型数据处理
逻辑回归模型能够适应连续型变量, 因此可以不⽤进⾏离散化处理, ⼜由于多个特征之间差异差异较⼤会造成梯度下降算法收敛速度变慢, 故进⾏归⼀化处理
#采⽤max-min归⼀化⽅法hours = df_one_hot['hours']df_one_hot['hours'] = df_one_hot.hours.apply(lambda x: (x-hours.min()) / (hours.max()-hours.min()))
3. 相关系数
两个变量均是连续型且具有线性关系, 则可以使⽤⽪尔逊相关系数, 否则使⽤斯⽪尔曼相关系数, 这⾥采⽤斯⽪尔曼相关系数
#计算相关系数correlation = df_one_hot.corr(method = 'spearman')plt.figure(figsize=(18, 10))#绘制热⼒图sns.heatmap(correlation, linewidths=0.2, vmax=1, vmin=-1, linecolor='w',fmt='.2f', annot=True,annot_kws={'size':10},square=True)
6. 逻辑回归模型
1. 划分数据集
from sklearn.model_selection import train_test_split#划分训练集和测试集X = df_one_hot.drop(['left'], axis=1)y = df_one_hot['left']X_train, X_test,
y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1)
2. 训练模型
from sklearn.linear_model import LogisticRegressionLR = LogisticRegression()print(LR.fit(X_train, y_train))print('训练集准确率: ', LR.score(X_train, y_train))print('测试集准确率: ', LR.score(X_test, y_test))LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
intercept_scaling=1, max_iter=100, multi_class='warn', n_jobs=None, penalty='l2', random_state=None, solver='warn', tol=0.0001, verbose=0, warm_start=False)训练集准确率: 0.7978998249854155测试集准确率: 0.7966666666666666
参考官⽅⽂档说明, 参数C是正则化项参数的倒数, C的数值越⼩, 惩罚的⼒度越⼤. penalty可选L1, L2正则化项, 默认是L2正则化.
参数solver可选{‘newton-cg’, ‘lbfgs’, ‘liblinear’, ‘sag’, ‘saga’}这5个优化算法:
newton-cg, lbfgs是拟⽜顿法, liblinear是坐标轴下降法, sag, saga是随机梯度下降法, saga可以适⽤于L1和L2正则化项, ⽽sag只能⽤于L2正则化项. #指定随机梯度下降优化算法LR = LogisticRegression(solver='saga')print(LR.fit(X_train, y_train))print('训练集准确率: ', LR.score(X_train,
y_train))print('测试集准确率: ', LR.score(X_test, y_test))LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
intercept_scaling=1, max_iter=100, multi_class='warn', n_jobs=None, penalty='l2', random_state=None, solver='saga', tol=0.0001, verbose=0, warm_start=False)训练集准确率: 0.7980665055421285测试集准确率: 0.7973333333333333
在选择随机梯度下降法后, 训练集和测试集准确率均略有提升.
3. 调参
#⽤准确率进⾏10折交叉验证选择合适的参数Cfrom sklearn.linear_model import LogisticRegressionCVCs = 10**np.linspace(-10, 10, 400)lr_cv = LogisticRegressionCV(Cs=Cs, cv=10, penalty='l2', solver='saga', max_iter=10000, scoring='accuracy')lr_cv.fit(X_train,
y_train)lr_cv.C_array([25.52908068])
⽤该参数进⾏预测
LR = LogisticRegression(solver='saga', penalty='l2', C=25.52908068)print('训练集准确率: ', LR.score(X_train, y_train))print('测试集准确率: ',
LR.score(X_test, y_test))训练集准确率: 0.7984832069339112测试集准确率: 0.798
训练集和测试集准确率均有所提升, 对于⼆分类问题, 准确率有时不是很好的评估⽅法, 这时需要⽤到混淆矩阵
4. 混淆矩阵
from sklearn import metricsX_train_pred = LR.predict(X_train)X_test_pred = LR.predict(X_test)print('训练集混淆矩
阵:')print(metrics.confusion_matrix(y_train, X_train_pred))print('测试集混淆矩阵:')print(metrics.confusion_matrix(y_test, X_test_pred))
训练集混淆矩阵:[[8494 647] [1771 1087]]测试集混淆矩阵:[[2112 175] [ 431 282]]from sklearn.metrics import classification_reportprint('训练
集:')print(classification_report(y_train, X_train_pred))print('测试集:')print(classification_report(y_test, X_test_pred))训练集: precision recall f1-score support 0 0.83 0.93 0.88 9141 1 0.63 0.38 0.47 2858 micro avg 0.80 0.80 0.80 11999 macro avg 0.73 0.65 0.67 11999weighted avg 0.78 0.80 0.78 11999测试集: precision recall f1-score support 0 0.83 0.92 0.87 2287 1 0.62 0.40 0.48 713 micro avg 0.80 0.80 0.80 3000 macro avg 0.72 0.66 0.68 3000weighted avg 0.78 0.80 0.78 3000
在训练集有0.83的精准率和0.93的召回率, 在测试集上有0.83的精准率和0.92的召回率.
7. 朴素贝叶斯模型
朴素贝叶斯模型是基于特征条件独⽴假设和贝叶斯理论.
from sklearn.naive_bayes import GaussianNBfrom sklearn.model_selection import cross_val_score#构建⾼斯朴素贝叶斯模型gnb = GaussianNB()gnb.fit(X_train, y_train)print('训练集准确率: ', gnb.score(X_train, y_train))print('测试集准确率: ', gnb.score(X_test, y_test))X_train_pred =gnb.predict(X_train)X_test_pred = gnb.predict(X_test)print('训练集混淆矩阵:')print(metrics.confusion_matrix(y_train, X_train_pred))print('测试集混淆矩阵:')print(metrics.confusion_matrix(y_test, X_test_pred))print('训练集:')print(classification_report(y_train, X_train_pred))print('测试
集:')print(classification_report(y_test, X_test_pred))
训练集准确率: 0.7440620051670973测试集准确率: 0.741训练集混淆矩阵:[[6791 2350] [ 721 2137]]测试集混淆矩阵:[[1680 607] [ 170 543]]训练集: precision recall f1-score support 0 0.90 0.74 0.82 9141 1 0.48 0.75 0.58 2858 micro avg 0.74 0.74 0.74 11999 macro avg 0.69 0.75 0.70
11999weighted avg 0.80 0.74 0.76 11999测试集: precision recall f1-score support 0 0.91 0.73 0.81 2287 1 0.47 0.76 0.58 713 micro avg 0.74 0.74 0.74 3000 macro avg 0.69 0.75 0.70 3000weighted avg 0.80 0.74 0.76 3000
可以看到其准确率较逻辑回归低, 但是精准率⾼于逻辑回归.
8. ROC曲线
from sklearn import metricsfrom sklearn.metrics import roc_curve#将逻辑回归模型和⾼斯朴素贝叶斯模型预测出的概率均与实际值通过roc_curve⽐
ROC曲线越靠近左上⾓说明分类效果越好, 与之对应的auc的值就越⼤. 对于该数据集来说总结。