用户的流失预测分析

2024-04-21 11:28
文章标签 分析 用户 预测 流失

本文主要是介绍用户的流失预测分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

项目背景

  • 随着电信行业的持续发展,运营商们开始更加关注如何扩大他们的客户群体。研究表明,获取新客户所需的成本要远高于保留现有客户的成本。因此,在激烈的竞争中,保留现有客户成为了一个巨大的挑战。在电信行业中,可以通过数据挖掘等方法分析可能影响客户决策的各种因素,以预测他们是否会流失(停用服务或转投其他运营商)。

数据集

  • 数据集一共提供了7000余条用户样本,每条样本包含21列,由多个维度的客户信息以及用户是否最终流失的标签组成,客户信息具体如下:
  • 在21列原始属性中,除了最后一列Churn表示该数据集的目标变量(即标签列)外,其余20列按照原始数据集中的排列顺序刚好可以分为三类特征群:客户的基本信息、开通业务信息、签署的合约信息。列说明如下:
    在这里插入图片描述
  • 注意:
    • 电信用户流失预测中,运营商最为关心的是客户的召回率,即在真正流失的样本中,我们预测到多少条样本。其策略是宁可把未流失的客户预测为流失客户而进行多余的留客行为,也不漏掉任何一名真正流失的客户。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings('ignore') #忽略弹出的warnings信息
data = pd.read_csv('./user.csv')
data.head()

在这里插入图片描述

#是否用重复的行数据
data.duplicated().sum()#0表示不存在重复的行数据

0

#TotalCharges总费用,原始的数据类型是字符串,将其转换成浮点型。
data['TotalCharges'].astype('float')

ValueError: could not convert string to float: ‘’

#根据提示,存在空格,查找后得知,该列中存在11个空格的字符串,导致无法将其转换成浮点型数据
(data['TotalCharges'] == ' ').sum()

11

#将data['TotalCharges']列中对应的' '数据对应的行数据进行删除
drop_indexs = data.loc[data['TotalCharges'] == ' '].index
data.drop(index=drop_indexs,inplace=True)
#进行数据类型的转换
data['TotalCharges'] = data['TotalCharges'].astype('float')
data.info()

在这里插入图片描述

#列中是否存在缺失数据
data.isnull().any(axis=0)

在这里插入图片描述
对数值型的列进行异常数据的探索

#对SeniorCitizen是否为老年人进行异常数据的探索
data['SeniorCitizen'].value_counts()

0 5890
1 1142
Name: SeniorCitizen, dtype: int64

#对入网月数tenure进行箱型图的绘制
plt.boxplot(data['tenure'],vert=False)

在这里插入图片描述

#对MonthlyCharges每月费用进行箱型图的绘制
plt.boxplot(data['MonthlyCharges'],vert=False)

在这里插入图片描述

#对总费用TotalCharges进行箱型图的绘制
plt.boxplot(data['TotalCharges'],vert=False)

在这里插入图片描述

特征工程

特征抽取
  • 在特征介绍图中观察如下几列特征的组成元素:
    • ‘MultipleLines’,‘OnlineSecurity’, ‘OnlineBackup’, ‘DeviceProtection’, ‘TechSupport’, ‘StreamingTV’, ‘StreamingMovies’
    • 发现MultipleLines特征组成元素为:yes,no和No phone service
    • 剩下几列特征的组成元素为:yes,no和No internet service,那么No phone service就表示no,所以可以将其修改为no,从而减少特征组成元素的数量,方便后期进行特征值化。
data['MultipleLines'].replace('No phone service','No',inplace=True)internetCols = ['OnlineSecurity', 'OnlineBackup', 'DeviceProtection', 'TechSupport', 'StreamingTV', 'StreamingMovies']for col in internetCols:data[col].replace('No internet service','No',inplace=True)#将特征元素为Yes和No组成的特征进行特征值化操作:map映射
cols = ['Partner','Dependents','PhoneService','MultipleLines','OnlineSecurity', 'OnlineBackup', 'DeviceProtection', 'TechSupport', 'StreamingTV', 'StreamingMovies','PaperlessBilling']
for col in cols:data[col] = data[col].map({'Yes':1,'No':0})#对性别gender进行特征值化:map映射
data['gender'] = data['gender'].map({'Male':1,'Female':0})#将剩下的非数值型特征(组成元素大于两个)进行特征值化
cols_name = ['InternetService','Contract','PaymentMethod']
ret = pd.get_dummies(data[cols_name])
data = pd.concat((data,ret),axis=1).drop(columns=cols_name)
data.head()

在这里插入图片描述

#将标签数据Churn也转换成数值型数据
data['Churn'] = data['Churn'].map({'Yes':1,'No':0})
特征选择
  • 方差过滤
  • 相关系数
  • PCA降维
  • 在项目中,大部分的数据都是非数值型数据,然后经过了特征值化后,特征数据大部分变为了0-1分布。因此无法使用方差过滤、pca和相关系数进行特征选择。
通过可视化分析探测不重要的特征,进行特征选择
  • 基本特征对客户流失影响
    • 性别、是否老年人、是否有配偶、是否有家属特征对客户流失的影响(占比情况:例如在性别特征中,统计女性流失占不流失的比例and男性)
      • ‘gender’, ‘SeniorCitizen’, ‘Partner’, ‘Dependents’
      • 这些特征的组成元素只有【是和否】
    • 入网月数特征对客户流失的影响
      • ‘tenure’
      • 该特征的组成元素有多个
#以性别为列,观察不同性别对用户的流失是否会造成影响
#计算出来不同的性别对应的流失用户数量和未流失用户数量
ret = pd.crosstab(data['gender'],data['Churn'])
ret

在这里插入图片描述

#计算出男性和女性的流失用户占未流失用的占比
female_p = ret.iloc[0,1] / ret.iloc[0,0]
male_p = ret.iloc[1,1] / ret.iloc[1,0]
female_p,male_p

(0.36910377358490565, 0.3550973654066438)

#批量证实如下几列特征对用户流失是否会造成影响
baseCols = ['SeniorCitizen', 'Partner', 'Dependents']
for col in baseCols:col_df = pd.crosstab(data[col],data['Churn'])p_a = col_df.iloc[0,1] / col_df.iloc[0,0]p_b = col_df.iloc[1,1] / col_df.iloc[1,0]print(col,':',p_a,p_b)

SeniorCitizen : 0.3097620635979542 0.7147147147147147
Partner : 0.4920049200492005 0.24559471365638766
Dependents : 0.4551622418879056 0.18386914833615342
由数据可知:性别对客户流失基本没有影响;年龄对客户流失有影响;是否有配偶对客户流失有影响;是否有家属对客户流失有影响。

  • 观察流失率和入网月数之间的关系
    • 计算不同入网月数对应的流失率(不同入网月数的流失客户占总客户的比例)
#不同入网月数对应的流失用户的数量
s1 = data.groupby(by='tenure')['Churn'].sum() 
#不同入网月数对应的用户总量
s2 = data.groupby(by='tenure')['Churn'].count()#计算流失率
p = s1 / s2plt.plot(p)

在这里插入图片描述

  • 随着入网月数的增加流失率呈现下降的趋势!
  • 连续性特征的话使用分箱进行离散化后,探索和流失之间的关系。
#探究总费用TotalCharges流失率情况,先对TotalCharges进行分箱操作
bin = pd.cut(data['TotalCharges'],bins=10)#将分箱结果和流失结果Churn汇总到一个df中显示
ret = pd.DataFrame((bin,data['Churn'])).T
ret.head()

在这里插入图片描述

#计算每一个箱子对应的流失率
s1 = ret.groupby(by='TotalCharges')['Churn'].sum()
s2 = ret.groupby(by='TotalCharges')['Churn'].count()p = s1 / s2p.plot(x = p.values,y=[1,2,3,4,5,6,7,8,9,10])

在这里插入图片描述
随着总费用的增加,流失率是下降的趋势

  • 剩下的合约类型特征、业务类型特征同上进行分析即可,最终发现如下特征对目标标签没有影响,可以将其删除
    • ‘gender’、‘PhoneService’、‘StreamingTV’ 和 ‘StreamingMovies’
data.drop(labels=['gender','PhoneService','StreamingTV','StreamingMovies'],axis=1,inplace=True)

观察每月费用和总费用是否会存在较高的相关性

df_p = data[['TotalCharges','MonthlyCharges']]
df_p.corr()

在这里插入图片描述
其中 ‘TotalCharges’ 与MonthlyCharges特征的相关系数均大于0.6,即存在较强相关性,因此可以考虑删除该列

data.drop(columns='MonthlyCharges',inplace=True)
#用户id无用可以删除
data.drop(columns='customerID',inplace=True)
#目前保留下来的样本特征大部分都是0-1分布的(map映射和one-hot操作后的),因此没有必要再进行相关的无量纲化了
类别不平衡问题处理
  • 不同样本类别数量统计
data['Churn'].value_counts() #样本类别分布不均衡

在这里插入图片描述

#提取样本数据
feature = data.loc[:,data.columns != 'Churn']
target = data['Churn']
#使用过抽样处理样本类别分布不均衡的问题
from imblearn.over_sampling import SMOTE
tool = SMOTE(k_neighbors=5)
t_feature,t_target = tool.fit_resample(feature,target)t_target.value_counts()

在这里插入图片描述

模型选择&评估

  • 召回率代表的意义则是:在真正流失的样本中,我们预测到多少条样本。召回率是运营商们关心的指标,即宁可把未流失的客户预测为流失客户而进行多余的留客行为,也不漏掉任何一名真正流失的客户。
from sklearn.neighbors import KNeighborsClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.naive_bayes import MultinomialNBfrom sklearn.model_selection import train_test_split
from sklearn.metrics import f1_score

使用没有进行样本类别分布不均衡处理后的样本进行建模

x_train,x_test,y_train,y_test = train_test_split(feature,target,test_size=0.2,random_state=2020)
knn = KNeighborsClassifier()
lg = LogisticRegression()
svm = SVC()
mut = MultinomialNB()models = {'knn':knn,'lg':lg,'svm':svm,'mut':mut}
for model_name,model in models.items():model.fit(x_train,y_train)score = f1_score(y_test,model.predict(x_test))print('%s:%f'%(model_name,score))

knn:0.469291
lg:0.591252
svm:0.000000
mut:0.617371
使用进行样本类别分布不均衡处理后的样本进行建模

x_train,x_test,y_train,y_test = train_test_split(t_feature,t_target,test_size=0.2,random_state=2020)
knn = KNeighborsClassifier()
lg = LogisticRegression()
svm = SVC()
mut = MultinomialNB()models = {'knn':knn,'lg':lg,'svm':svm,'mut':mut}
for model_name,model in models.items():model.fit(x_train,y_train)score = f1_score(y_test,model.predict(x_test))print('%s:%f'%(model_name,score))

knn:0.783431
lg:0.815238
svm:0.601643
mut:0.779445
进行了样本类别分布不均衡处理后,相关模型表现的效果综合提升了,其中逻辑回归表现最好。
内容来自大数据分析课程。

这篇关于用户的流失预测分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/922964

相关文章

Spring事务中@Transactional注解不生效的原因分析与解决

《Spring事务中@Transactional注解不生效的原因分析与解决》在Spring框架中,@Transactional注解是管理数据库事务的核心方式,本文将深入分析事务自调用的底层原理,解释为... 目录1. 引言2. 事务自调用问题重现2.1 示例代码2.2 问题现象3. 为什么事务自调用会失效3

找不到Anaconda prompt终端的原因分析及解决方案

《找不到Anacondaprompt终端的原因分析及解决方案》因为anaconda还没有初始化,在安装anaconda的过程中,有一行是否要添加anaconda到菜单目录中,由于没有勾选,导致没有菜... 目录问题原因问http://www.chinasem.cn题解决安装了 Anaconda 却找不到 An

Spring定时任务只执行一次的原因分析与解决方案

《Spring定时任务只执行一次的原因分析与解决方案》在使用Spring的@Scheduled定时任务时,你是否遇到过任务只执行一次,后续不再触发的情况?这种情况可能由多种原因导致,如未启用调度、线程... 目录1. 问题背景2. Spring定时任务的基本用法3. 为什么定时任务只执行一次?3.1 未启用

C++ 各种map特点对比分析

《C++各种map特点对比分析》文章比较了C++中不同类型的map(如std::map,std::unordered_map,std::multimap,std::unordered_multima... 目录特点比较C++ 示例代码 ​​​​​​代码解释特点比较1. std::map底层实现:基于红黑

Spring、Spring Boot、Spring Cloud 的区别与联系分析

《Spring、SpringBoot、SpringCloud的区别与联系分析》Spring、SpringBoot和SpringCloud是Java开发中常用的框架,分别针对企业级应用开发、快速开... 目录1. Spring 框架2. Spring Boot3. Spring Cloud总结1. Sprin

mysql删除无用用户的方法实现

《mysql删除无用用户的方法实现》本文主要介绍了mysql删除无用用户的方法实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 1、删除不用的账户(1) 查看当前已存在账户mysql> select user,host,pa

Spring 中 BeanFactoryPostProcessor 的作用和示例源码分析

《Spring中BeanFactoryPostProcessor的作用和示例源码分析》Spring的BeanFactoryPostProcessor是容器初始化的扩展接口,允许在Bean实例化前... 目录一、概览1. 核心定位2. 核心功能详解3. 关键特性二、Spring 内置的 BeanFactory

MyBatis-Plus中Service接口的lambdaUpdate用法及实例分析

《MyBatis-Plus中Service接口的lambdaUpdate用法及实例分析》本文将详细讲解MyBatis-Plus中的lambdaUpdate用法,并提供丰富的案例来帮助读者更好地理解和应... 目录深入探索MyBATis-Plus中Service接口的lambdaUpdate用法及示例案例背景

MyBatis-Plus中静态工具Db的多种用法及实例分析

《MyBatis-Plus中静态工具Db的多种用法及实例分析》本文将详细讲解MyBatis-Plus中静态工具Db的各种用法,并结合具体案例进行演示和说明,具有很好的参考价值,希望对大家有所帮助,如有... 目录MyBATis-Plus中静态工具Db的多种用法及实例案例背景使用静态工具Db进行数据库操作插入

Go使用pprof进行CPU,内存和阻塞情况分析

《Go使用pprof进行CPU,内存和阻塞情况分析》Go语言提供了强大的pprof工具,用于分析CPU、内存、Goroutine阻塞等性能问题,帮助开发者优化程序,提高运行效率,下面我们就来深入了解下... 目录1. pprof 介绍2. 快速上手:启用 pprof3. CPU Profiling:分析 C