???? 关注一下~,更多商业数据分析案例等你来撩
利用逻辑回归进行客户流失预警建模中涵盖了许多比较细的知识点,思维导图只展示了极小的一部分,相关知识点链接将穿插在文中。
本文已在公众号 " 数据分析与商业实践 " 首发,源数据和包含详细步骤和注释的源代码可空降文末。
因为源代码中有一些自定义的长函数,直接放在文章中会非常占篇幅,而且阅读体验也不怎么好,而且分享有限,所以更多案例,操作,源数据可移步公众号,资源在精不在多,赶快开始吧!
churn = pd.read_csv('telecom_churn.csv', skipinitialspace=True)
churn.head()
# 列比较多,显示不完
churn.info() # 发现数据都比较整洁
数据属性说明
数据探索简洁版本,只是为了一元逻辑回归做的探索,毕竟实际情况中数据分析师们80%的时间可能都是用来清洗数据和结合具体业务来探索数据,所以探索数据方面并不是我们的侧重点。
churn 流失与否 是否与 posTrend 流量使用上升趋势有关
猜想:posTrend 为 1,即流量使用有上升趋势时,更不容易流失(用得越多越不容易流失)
交叉表分析
cross_table = pd.crosstab(index=churn.posTrend, columns=churn.churn,
margins=True)
# margins 就是为了在最后一行和最后一类后面添加个汇总的 all
cross_table
def perConvert(ser):
return ser/float(ser[-1])
cross_table.apply(perConvert, axis='columns')
卡方检验
print("""chisq = %6.4f
p-value = %6.4f
dof = %i
expected_freq = %s""" % stats.chi2_contingency(observed=cross_table.iloc[:2, :2]))
统计学库建模
一元逻辑回归
拆分测试集与训练集
train = churn.sample(frac=0.7, random_state=1234).copy()
test = churn[~ churn.index.isin(train.index)].copy()
print(f'训练集样本量:{len(train)}, 测试集样本量:{len(test)}')
statsmodels 库进行逻辑回归
lg = smf.glm(formula='churn ~ duration', data=churn,
family=sm.families.Binomial(sm.families.links.logit)).fit()
lg.summary()
使用建模结果进行预测
预测流失的可能性
train['proba'] = lg.predict(train)
test['proba'] = lg.predict(test)
test[['churn', 'proba']].head() # 我们可以假设 proba > 0.5 就算流失,
test['prediction'] = (test['proba'] > 0.5)*1
test[['churn', 'prediction']].sample(3)
检验预测结果
acc = sum(test['prediction'] == test['churn']) / np.float(len(test))
print(f'The accuracy is: {acc}')
import sklearn.metrics as metrics
fpr_test, tpr_test, th_test = metrics.roc_curve(test.churn, test.proba)
fpr_train, tpr_train, th_train = metrics.roc_curve(train.churn, train.proba)
plt.figure(figsize=[3, 3])
plt.plot(fpr_test, tpr_test, 'b--')
plt.plot(fpr_train, tpr_train, 'r--')
plt.title('ROC curve'); plt.show()
print(f'AUC = {metrics.auc(fpr_test, tpr_test)}')
建模结果越靠近左上角越好,模型精度比较高。
多元逻辑回归
逐步向前法筛选变量
当然,这里的变量还不算特别特别多,还可以使用分层抽样,假设检验,方差分析等方法筛选,这里不用多解释了。逻辑回归的逐步向前法已有优秀前人的轮子,直接拿来用即可。篇幅原因就不完全展示了。文末获取源数据与含有详细注释的源代码
def forward_select(data, response):
"""略,文末获取源数据与含有详细注释的源代码"""
candidates = churn.columns.tolist()[1:]
data_for_select = train[candidates]
lg_m1 = forward_select(data=data_for_select, response='churn')
lg_m1.summary()
print(f'原来有 {len(candidates)} 个变量')
print(f'筛选剩下 {len(lg_m1.params.index.tolist())} 个(包含 intercept 截距项)。')
方差膨胀因子检测
多元逻辑回归中也会存在多元共线性的干扰,其具体含义可查看如下文章:
多元共线性检测 – 方差膨胀因子
def vif(df, col_i):
from statsmodels.formula.api import ols
cols = list(df.columns)
cols.remove(col_i)
cols_noti = cols
formula = col_i + '~' + '+'.join(cols_noti)
r2 = ols(formula, df).fit().rsquared
return 1. / (1. - r2)
after_select = lg_m1.params.index.tolist()[1:] # Intercept 不算
exog = train[after_select]
for i in exog.columns:
print(i, '\t', vif(df=exog, col_i=i))
drop = ['prom', 'posTrend']
final_left = [x for x in after_select if x not in drop]
exog = train[final_left]
for i in exog.columns:
print(i, '\t', vif(df=exog, col_i=i))
再次进行建模与模型精度的检验
重复一元逻辑回归的步骤即可。
公众号会后续更新数据科学与商业实践常用的场景案例,丰富源数据源代码等你来撩 ~~