一、Logistic回归模型

假定以下回归模型为:z=β0+β1x1+β2x2+⋯+βpxpz=\beta_0+\beta_1x_1+\beta_2x_2+\cdots+\beta_px_pz=β0+β1x1+β2x2++βpxp

则Logit变换为:
g(z)=11+e−(β0+β1x1+β2x2+⋯+βpxp)=hβ(X) g(z)=\frac{1}{1+e^{-(\beta_0+\beta_1x_1+\beta_2x_2+\cdots+\beta_px_p)}}=h_\beta(X) g(z)=1+e(β0+β1x1+β2x2++βpxp)1=hβ(X)
上式中的hβ(X)h_\beta(X)hβ(X)也被称为Logistic回归模型,它是将线性回归模型的预测值经过非线性的Logit函数转换为[0,1]之间的概率值。

Logit函数使得原本z∈(−∞,+∞)z\in(-\infin,+\infin)z(,+)的值,限制在(0,1)(0,1)(0,1)之间,从而进行概率分类。下图是Logit函数 g(z)=11+e−zg(z)=\frac{1}{1+e^{-z}}g(z)=1+ez1函数图像

img

01 模型变换

条件概率,y取值为1时的概率:P(y=1∣X;β)=hβ(X)=pP(y=1|X;\beta)=h_\beta(X)=pP(y=1X;β)=hβ(X)=p

条件概率,y取值为0时的概率:P(y=0∣X;β)=1−hβ(X)=1−pP(y=0|X;\beta)=1-h_\beta(X)=1-pP(y=0X;β)=1hβ(X)=1p

则两个概率的商为:
p1−p=hβ(X)1−hβ(X)=eβ0+β1x1+β2x2+⋯+βpxp \frac{p}{1-p}=\frac{h_\beta(X)}{1-h_\beta(X)}=e^{\beta_0+\beta_1x_1+\beta_2x_2+\cdots+\beta_px_p} 1pp=1hβ(X)hβ(X)=eβ0+β1x1+β2x2++βpxp

02 参数求解过程

对于上述两个条件概率式子,我们可以等价于:
P(y∣X;β)=hβ(X)y×(1−hβ(X))1−y,(y=1,0) P(y|X;\beta)=h_\beta(X)^y\times(1-h_\beta(X))^{1-y},(y=1,0) P(yX;β)=hβ(X)y×(1hβ(X))1y,(y=1,0)
构造似然函数:
L(β)=∏i=1nhβ(xi)yi×(1−hβ(xi))1−yi L(\beta)=\prod_{i=1}^nh_\beta(x^i)^{y^i}\times(1-h_\beta(x^i))^{1-y^i} L(β)=i=1nhβ(xi)yi×(1hβ(xi))1yi
似然函数对数化:
l(β)=log(L(β))=∑i=1n(yilog(hβxi))+(1−yi)log(1−hβxi) l(\beta)=log(L(\beta))=\sum_{i=1}^n(y^ilog(h_\beta x^i))+(1-y^i)log(1-h_\beta x^i) l(β)=log(L(β))=i=1n(yilog(hβxi))+(1yi)log(1hβxi)
由于直接求导函数为0无法构建完整的方程组,考虑梯度下降:
J(β)=−l(β)=−∑i=1n(yilog(hβxi)+(1−yi)log(1−hβxi)) J(\beta)=-l(\beta)=-\sum_{i=1}^n(y^ilog(h_\beta x^i)+(1-y^i)log(1-h_\beta x^i)) J(β)=l(β)=i=1n(yilog(hβxi)+(1yi)log(1hβxi))
于是,对每一个未知数βj\beta_jβj做梯度下降:
βj:=βj−α∂J(β)∂βj \beta_j:=\beta_j-\alpha\frac{\partial J(\beta)}{\partial \beta_j} βj:=βjαβjJ(β)
其中,alpha为学习率,也成为参数beta变化的步长,通常可取0.1、0.05、0.01等,设置的α\alphaα不可过小也不可过大。

03 参数含义的解释

以癌症为例,假设影响是否得癌症的因素有性别(β1)(\beta_1)(β1)和肿瘤体积(β2)(\beta_2)(β2)两个变量,则Logistic模型可以按照事件发生比的形式改写为:
odds=p1−p=eβ0+β1Gender+β2Volumn odds=\frac{p}{1-p}=e^{\beta_0+\beta_1Gender+\beta_2Volumn} odds=1pp=eβ0+β1Gender+β2Volumn
分别以性别变量和肿瘤体积变量为例,解释系数β1和β2\beta_1和\beta_2β1β2的含义。假设性别中男用1表示,女用0表示。则:
odds1odds0=eβ0×eβ1×1×eβ2Volumneβ0×eβ1×0×eβ2Volumn=eβ1 \frac{odds_1}{odds_0}=\frac{e^{\beta_0}\times e^{\beta_1\times1}\times e^{\beta_2Volumn}}{e^{\beta_0}\times e^{\beta_1\times0}\times e^{\beta_2Volumn}}=e^{\beta_1} odds0odds1=eβ0×eβ1×0×eβ2Volumneβ0×eβ1×1×eβ2Volumn=eβ1
所以,性别变量的发生比率为eβ1e^{\beta_1}eβ1,表示男性患癌的发生比约为女性患癌发生比的eβ1e^{\beta1}eβ1

对于连续型自变量而言,假设肿瘤体积为Volumn0Volumn_0Volumn0,当肿瘤体积增加1个单位时,体积为Volumn0+1Volumn_0+1Volumn0+1,则:
oddsVolumn0+1oddsVolumn0=eβ0×eβ1Gender×eβ2(Volumn0+1)eβ0×eβ1Gender×eβ2(Volumn0)=eβ2 \frac{odds_{Volumn_0+1}}{odds_{Volumn_0}}=\frac{e^{\beta_0}\times e^{\beta_1Gender}\times e^{\beta_2(Volumn_0+1)}}{e^{\beta_0}\times e^{\beta_1Gender}\times e^{\beta_2(Volumn_0)}}=e^{\beta_2} oddsVolumn0oddsVolumn0+1=eβ0×eβ1Gender×eβ2(Volumn0)eβ0×eβ1Gender×eβ2(Volumn0+1)=eβ2
所以,在其他变量不变的情况下,肿瘤体积每增加一个单位,将会使患癌发生比变化eβ2e^{\beta_2}eβ2倍。

二、模型评估

01 混淆矩阵

混淆矩阵的每一列代表了预测类别,每一列的总数表示预测为该类别的数据的数目;每一行代表了数据的真实归属类别,每一行的数据总数表示该类别的数据实例的数目。

img

其中:
正例覆盖率:Sensitivity=TPTP+FN负例覆盖率:Specificity=TNTN+FP 正例覆盖率:Sensitivity=\frac{TP}{TP+FN}\\负例覆盖率:Specificity=\frac{TN}{TN+FP} Sensitivity=TP+FNTPSpecificity=TN+FPTN

02 ROC曲线

受试者工作特征曲线 (receiver operating characteristic curve,简称ROC曲线),又称为感受性曲线(sensitivity curve)

img

在不使用模型的情况下,Sensitivity 和1-Specificity之比恒为1,上图蓝色曲线以下面积称为AUC,当AUC在0.8以上时,模型就可以接受了。

三、代码实现

01 sklearn包

LogisticRegression(tol=0.0001, fit_intercept=True, class_weight=None, max_iter=100)

  • tol:用于指定模型收敛的阈值
  • fit_intercept:是否拟合模型的截距项,默认为True
  • class_weight:用于指定因变量类别的权重,若为字典,则通过字典的形式{class_label:weight}传递每个类别的权重,若为字符串“balanced”,则每个分类的权重与实际样本中的比例成反比,当各分类存在严重不平衡时,设置为"balanced"较好;若为None,则表示每个分类的权重相等
  • max_iter:指定模型求解过程中的最大迭代次数,默认为100
# 导入第三方模块
import pandas as pd
import numpy as np
from sklearn import model_selection
from sklearn import linear_model

# 读取数据
sports = pd.read_csv(r'Run or Walk.csv')
# 提取出所有自变量名称
predictors = sports.columns[4:]
# 构建自变量矩阵
X = sports.ix[:,predictors]
# 提取y变量值
y = sports.activity
# 将数据集拆分为训练集和测试集
X_train, X_test, y_train, y_test = model_selection.train_test_split(X, y, test_size = 0.25, random_state = 1234)

# 利用训练集建模
sklearn_logistic = linear_model.LogisticRegression()
sklearn_logistic.fit(X_train, y_train)
# 返回模型的各个参数
print(sklearn_logistic.intercept_, sklearn_logistic.coef_)

结果为:

[ 4.35613952] [[ 0.48533325  6.86221041 -2.44611637 -0.01344578 -0.1607943   0.13360777]]

其中第一个为截距项,后边为各变量对应的偏回归系数。

# 模型预测
sklearn_predict = sklearn_logistic.predict(X_test)
# 预测结果统计
pd.Series(sklearn_predict).value_counts()

下面进行模型评估:

# 导入第三方模块
from sklearn import metrics
# 混淆矩阵
cm = metrics.confusion_matrix(y_test, sklearn_predict, labels = [0,1])
cm

结果为:

array([[9971, 1120],
       [2150, 8906]], dtype=int64)

计算Accuracy、Sensitivity、Specificity

Accuracy = metrics.scorer.accuracy_score(y_test, sklearn_predict)
Sensitivity = metrics.scorer.recall_score(y_test, sklearn_predict)
Specificity = metrics.scorer.recall_score(y_test, sklearn_predict, pos_label=0)
print('模型准确率为%.2f%%:' %(Accuracy*100))
print('正例覆盖率为%.2f%%' %(Sensitivity*100))
print('负例覆盖率为%.2f%%' %(Specificity*100))

结果为:

模型准确率为85.24%:
正例覆盖率为80.55%
负例覆盖率为89.90%

02 statsmodels.api包

# -----------------------第一步 建模 ----------------------- #
# 导入第三方模块
import statsmodels.api as sm
import pandas as pd
import numpy as np
from sklearn import metrics
from sklearn import model_selection
from sklearn import linear_model

# 读取数据
sports = pd.read_csv(r'Run or Walk.csv')
# 提取出所有自变量名称
predictors = sports.columns[4:]
# 构建自变量矩阵
X = sports.ix[:,predictors]
# 提取y变量值
y = sports.activity
# 将数据集拆分为训练集和测试集
X_train, X_test, y_train, y_test = model_selection.train_test_split(X, y, test_size = 0.25, random_state = 1234)
# 为训练集和测试集的X矩阵添加常数列1
X_train2 = sm.add_constant(X_train)
X_test2 = sm.add_constant(X_test)
# 拟合Logistic模型
sm_logistic = sm.Logit(y_train, X_train2).fit()
# 返回模型的参数
sm_logistic.params
# -----------------------第二步 预测构建混淆矩阵 ----------------------- #
# 模型在测试集上的预测
sm_y_probability = sm_logistic.predict(X_test2)
# 根据概率值,将观测进行分类,以0.5作为阈值
sm_pred_y = np.where(sm_y_probability >= 0.5, 1, 0)
# 混淆矩阵
cm = metrics.confusion_matrix(y_test, sm_pred_y, labels = [0,1])
cm
# -----------------------第三步 绘制ROC曲线 ----------------------- #
import matplotlib.pyplot as plt
# 计算真正率和假正率 
fpr,tpr,threshold = metrics.roc_curve(y_test, sm_y_probability)
# 计算auc的值  
roc_auc = metrics.auc(fpr,tpr)
# 绘制面积图
plt.stackplot(fpr, tpr, color='steelblue', alpha = 0.5, edgecolor = 'black')
# 添加边际线
plt.plot(fpr, tpr, color='black', lw = 1)
# 添加对角线
plt.plot([0,1],[0,1], color = 'red', linestyle = '--')
# 添加文本信息
plt.text(0.5,0.3,'ROC curve (area = %0.2f)' % roc_auc)
# 添加x轴与y轴标签
plt.xlabel('1-Specificity')
plt.ylabel('Sensitivity')
# 显示图形
plt.show()
Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐