python数据建模案例源代码_万字案例⽤Python建⽴客户流失
预测模型(含源数据+代码)...
# # 电信客户流失预测
# ## 1、导⼊数据
# In[1]:
import numpy as npimport pandas as pdimport os
# In[2]:
# 导⼊相关的包import matplotlib.pyplot as pltimport seaborn as snsfrom pylab import as cm
import sklearnfrom sklearn import preprocessingfrom sklearn.preprocessing import LabelEncoder # 编码转换from sklearn.preprocessing import del_selection import StratifiedShuffleSplit
semble import RandomForestClassifier # 随机森林from sklearn.svm import SVC, LinearSVC # ⽀持向量机from sklearn.linear_model import LogisticRegression # 逻辑回归ighbors import KNeighborsClassifier # KNN 算法from sklearn.naive_bayes import GaussianNB # 朴素贝叶斯 import DecisionTreeClassifier # 决策树分类器from xgboost import XGBClassifierfrom catboost import semble import semble import GradientBoostingClassifier
ics import classification_report, precision_score, recall_score, f1_ics import confusion_del_selection import ics import make_semble import VotingClassifier
from sklearn.decomposition import PCAfrom sklearn.cluster import ics import silhouette_score import warningswarnings.filterwarnings('ignore')
get_ipython.magic('matplotlib inline')
# In[3]:
# 读取数据⽂件ad_csv(r"F:dataWA_Fn-UseC_-Telco-Customer-Churn.csv")
# ## 2、查看数据集信息
# In[4]:
telcom.head(10)
# In[5]:
# 查看数据集⼤⼩telcom.shape
# In[6]:
# 获取数据类型列的描述统计信息telcom.describe
# ## 3、数据清洗
# In[7]:
# 查缺失值pd.isnull(telcom).sum
# In[8]:
telcom["Churn"].value_counts
# 数据集中有5174名⽤户没流失,有1869名客户流失,数据集不均衡。
# In[9]:
telcom.info
# TotalCharges表⽰总费⽤,这⾥为对象类型,需要转换为float类型
# In[10]:
telcom['TotalCharges']=telcom['TotalCharges'].convert_objects(convert_numeric=True) # convert_numeric=True表⽰强制转换
数字(包括字符串),不可转换的值变为NaNtelcom["TotalCharges"].dtypes
# In[11]:
# 再次查是否存在缺失值pd.isnull(telcom["TotalCharges"]).sum
# 这⾥存在11个缺失值,由于数量不多我们可以直接删除这些⾏
# In[12]:
# 删除缺失值所在的⾏telcom.dropna(inplace=True)telcom.shape
# In[13]:
# 数据归⼀化处理# 对Churn 列中的值 Yes和 No分别⽤ 1和 0替换,⽅便后续处理telcom['Churn'].replace(to_replace = 'Yes', value
= 1,inplace = True)telcom['Churn'].replace(to_replace = 'No', value = 0,inplace = True)telcom['Churn'].head
# In[14]:
telcom['Churn'].replace(to_replace='Yes', value=1, inplace=True)telcom['Churn'].replace(to_replace='No', value=0,
inplace=True)telcom['Churn'].head
# ## 4、数据可视化呈现
# In[15]:
# 查看流失客户占⽐"""画饼图参数:labels (每⼀块)饼图外侧显⽰的说明⽂字explode (每⼀块)离开中⼼距离startangle 起始绘制⾓度,默
认图是从x轴正⽅向逆时针画起,如设定=90则从y轴正⽅向画起shadow 是否阴影labeldistance label 绘制位置,相对于半径的⽐例, 如<1则
绘制在饼图内侧autopct 控制饼图内百分⽐设置,可以使⽤format字符串或者format function'%1.1f'指⼩数点前后位数(没有⽤空格补
齐)pctdistance 类似于labeldistance,指定autopct的位置刻度radius 控制饼图半
径"""churnvalue=telcom["Churn"].value_countslabels=telcom["Churn"].value_counts.index
rcParams["figure.figsize"]=6,6plt.pie(churnvalue,labels=labels,colors=["whitesmoke","yellow"], explode=
(0.1,0),autopct='%1.1f%%', shadow=True)plt.title("Proportions of Customer Churn")plt.show
# In[16]:
# 性别、⽼年⼈、配偶、亲属对流客户流失率的影响f, axes = plt.subplots(nrows=2, ncols=2, figsize=(10,10))
plt.subplot(2,2,1)untplot(x="gender",hue="Churn",data=telcom,palette="Pastel2") # palette参数表⽰设置颜⾊,
这⾥设置为主题⾊Pastel2plt.xlabel("gender")plt.title("Churn by Gender")
plt.subplot(2,2,2)untplot(x="SeniorCitizen",hue="Churn",data=telcom,palette="Pastel2")plt.xlabel("senior citizen")plt.title("Churn by Senior Citizen")
plt.subplot(2,2,3)untplot(x="Partner",hue="Churn",data=telcom,palette="Pastel2")plt.xlabel("partner")plt.title("Ch by Partner")
plt.subplot(2,2,4)untplot(x="Dependents",hue="Churn",data=telcom,palette="Pastel2")plt.xlabel("dependents by Dependents")
# In[17]:
# 提取特征charges=telcom.iloc[:,1:20]# 对特征进⾏编码"""离散特征的编码分为两种情况:1、离散特征的取值之间没有⼤⼩的意义,⽐如color:[red,blue],那么就使⽤one-hot编码2、离散特征的取值有⼤⼩的意义,⽐如size:[X,XL,XXL],那么就使⽤数值的映射
{X:1,XL:2,XXL:3}"""corrDf = charges.apply(lambda x: pd.factorize(x)[0])corrDf .head
# In[18]:
# 构造相关性矩阵corr = rr
# In[19]:
# 使⽤热地图显⽰相关系数'''heatmap 使⽤热地图展⽰系数矩阵情况linewidths 热⼒图矩阵之间的间隔⼤⼩annot 设定是否显⽰每个⾊块的系数值'''plt.figure(figsize=(20,16))ax = sns.heatmap(corr, lumns,
lumns,linewidths=0.2, cmap="YlGnBu",annot=True)plt.title("Correlation between variables")
# 结论:从上图可以看出,互联⽹服务、⽹络安全服务、在线备份业务、设备保护业务、技术⽀持服务、⽹络电视和⽹络电影之间存在较强的相关性,多线业务和电话服务之间也有很强的相关性,并且都呈强正相关关系。
# In[20]:
# 使⽤one-hot编码tel_dummies = pd.get_dummies(telcom.iloc[:,1:21])tel_dummies.head
# In[21]:
# 电信⽤户是否流失与各变量之间的相关性plt.figure(figsize=(15,8))['Churn'].sort_values(ascending =
False).plot(kind='bar')plt.title("Correlations between Churn and variables")
# 由图上可以看出,变量gender 和 PhoneService 处于图形中间,其值接近于 0 ,这两个变量对电信客户流失预测影响⾮常⼩,可以直接舍弃。
# In[22]:
# ⽹络安全服务、在线备份业务、设备保护业务、技术⽀持服务、⽹络电视、⽹络电影和⽆互联⽹服务对客户流失率的影响covariables= ["OnlineSecurity", "OnlineBackup", "DeviceProtection", "TechSupport", "StreamingTV",
"StreamingMovies"]fig,axes=plt.subplots(nrows=2,ncols=3,figsize=(16,10))for i, item in
enumerate(covariables):plt.subplot(2,3,(i+1))untplot(x=item,hue="Churn",data=telcom,palette="Pastel2",order= ["Yes","No","No internet service"])plt.xlabel(str(item))plt.title("Churn by "+ str(item))i=i+1plt.show
# 由上图可以看出,在⽹络安全服务、在线备份业务、设备保护业务、技术⽀持服务、⽹络电视和⽹络电影六个变量中,没有互联⽹服务的客户流失率值是相同的,都是相对较低。## 这可能是因为以上六个因素只有在客户使⽤互联⽹服务时才会影响客户的决策,这六个因素不会对不使⽤互联⽹服务的客户决定是否流失产⽣推论效应。
# In[23]:
# 签订合同⽅式对客户流失率的影响sns.barplot(x="Contract",y="Churn", data=telcom, palette="Pastel1", order= ['Month-to-month', 'One year', 'Two year'])plt.title("Churn by Contract type")
# 由图上可以看出,签订合同⽅式对客户流失率影响为:按⽉签订 > 按⼀年签订 > 按两年签订,这可能表明,设定长期合同对留住现有客户更有效。
# In[24]:
# 付款⽅式对客户流失率的影响plt.figure(figsize=(10,5))sns.barplot(x="PaymentMethod",y="Churn", data=telcom,
palette="Pastel1", order= ['Bank transfer (automatic)', 'Credit card (automatic)', 'Electronic check','Mailed
check'])plt.title("Churn by PaymentMethod type")
# 由图上可以看出,在四种⽀付⽅式中,使⽤Electronic check的⽤户流流失率最⾼,其他三种⽀付⽅式基本持平,因此可以推断电⼦账单在设计上影响⽤户体验。
# ## 5、数据预处理
# 由前⾯结果可知,CustomerID表⽰每个客户的随机字符,对后续建模不影响,我这⾥选择删除CustomerID列;gender 和PhoneService 与流失率的相关性低,可直接忽略。
telcomvar=telcom.iloc[:,2:20]telcomvar.drop("PhoneService",axis=1, inplace=True)
# 提取IDtelcom_id = telcom['customerID']
telcomvar.head
# In[27]:
# 对客户的职位、⽉费⽤和总费⽤进⾏去均值和⽅差缩放,对数据进⾏标准化"""标准化数据,保证每个维度的特征数据⽅差为1,均值为0,使得预测结果不会被某些维度过⼤的特征值⽽主导。"""scaler = StandardScaler(copy=False)# fit_transform的作⽤就是先拟合数据,然后转化它将其转化为标准形式scaler.fit_transform(telcomvar[['tenure','MonthlyCharges','TotalCharges']])
# In[28]:
# tranform的作⽤是通过中⼼和缩放等实现标准化
telcomvar[['tenure','MonthlyCharges','TotalCharges']]=ansform(telcomvar[['tenure','MonthlyCharges','TotalCharges']])
# In[29]:
# 使⽤箱线图查看数据是否存在异常值plt.figure(figsize = (8,4))numbox =
sns.boxplot(data=telcomvar[['tenure','MonthlyCharges','TotalCharges']], palette="Set2")plt.title("Check outliers of standardized tenure, MonthlyCharges and TotalCharges")
# 由以上结果可以看出,在三个变量中不存在明显的异常值
# In[30]:
# 查看对象类型字段中存在的值def uni(columnlabel):print(columnlabel,"--" ,telcomvar[columnlabel].unique) # unique函数去除其中重复的元素,返回唯⼀值
telcomobject=telcomvar.select_dtypes(['object'])for i in range(0,lumns)):lumns[i])
# 综合之前的结果来看,在六个变量中存在No internet service,即⽆互联⽹服务对客户流失率影响很⼩,这些客户不使⽤任何互联⽹产品,因此可以将No internet service 和 No 是⼀样的效果,可以使⽤ No 替代 No internet service
# In[31]:
service', value='No', inplace=True)for i in range(0,lumns)):lumns[i])
# In[32]:
# 使⽤Scikit-learn标签编码,将分类数据转换为整数编码def labelencode(columnlabel):telcomvar[columnlabel] =
LabelEncoder.fit_transform(telcomvar[columnlabel])
for i in range(0,lumns)):lumns[i])
for i in range(0,lumns)):lumns[i])
# ## 6、构建模型
# ### (1)建⽴训练数据集和测试数据集
# In[33]:
"""我们需要将数据集拆分为训练集和测试集以进⾏验证。由于我们所拥有的数据集是不平衡的,所以最好使⽤分层交叉验证来确保训练集和测试集都包含每个类样本的保留⼈数。交叉验证函数StratifiedShuffleSplit,功能是从样本数据中随机按⽐例选取训练数据(train)和测试数据(test)参数 n_splits是将训练数据分成train/test对的组数,可根据需要进⾏设置,默认为10参数test_size和train_size是⽤来设置train/test对中train和test所占的⽐例参数 random_state控制是将样本随机打乱"""X=telcomvary=telcom["Churn"].values
sss=StratifiedShuffleSplit(n_splits=5, test_size=0.2, random_state=0)print(sss)print("训练数据和测试数据被分成的组
数:",_n_splits(X,y))
# 建⽴训练数据和测试数据for train_index, test_index in sss.split(X, y):print("train:", train_index, "test:",
test_index)X_train,X_test=X.iloc[train_index], X.iloc[test_index]y_train,y_test=y[train_index], y[test_in
dex]
# In[35]:
# 输出数据集⼤⼩print('原始数据特征:', X.shape,'训练数据特征:',X_train.shape,'测试数据特征:',X_test.shape)
print('原始数据标签:', y.shape,' 训练数据标签:',y_train.shape,' 测试数据标签:',y_test.shape)
# ### (2)选择机器学习算法
# In[36]:
# 使⽤分类算法,这⾥选⽤10种分类算法Classifiers=[["Random Forest",RandomForestClassifier],["Support Vector
Machine",SVC],["LogisticRegression",LogisticRegression],["KNN",KNeighborsClassifier(n_neighbors=5)],["Naive
Bayes",GaussianNB],["Decision Tree",DecisionTreeClassifier],["AdaBoostClassifier", AdaBoostClassi
fier], ["GradientBoostingClassifier", GradientBoostingClassifier],["XGB", XGBClassifier],["CatBoost",
CatBoostClassifier(logging_level='Silent')]]
# ### (3)训练模型
# In[37]:
Classify_result=[]names=[]prediction=[]for name,classifier in
Classifiers:classifier=classifierclassifier.fit(X_train,y_train)y_pred=classifier.predict(X_test)recall=recall_score(y_test,y_pred)precisio
# ### (4)评估模型
# In[38]:
# 评估模型"""召回率(recall)的含义是:原本为对的当中,预测为对的⽐例(值越⼤越好,1为理想状态)精确率、精度(precision)的
源代码1080p在线
含义是:预测为对的当中,原本为对的⽐例(值越⼤越好,1为理想状态)F1分数(F1-Score)指标综合了Precision与Recall的产出的结
果F1-Score的取值范围从0到1的,1代表模型的输出最好,0代表模型的输出结果最差。"""
names=pd.DataFrame(names)names=names[0].at(Classify_result,axis=lumns=namesresult.inde ["recall","precision","f1score"]result
# 综上所述,在10种分类算法中朴素贝叶斯(Naive Bayes)的F1分数最⼤为63.31%,所以使⽤朴素贝叶斯模型效果最好。
# ## 7、实施⽅案
# 预测数据集特征(由于没有提供预测数据集,这⾥选取后10⾏作为需要预测的数据集)pred_X = telcomvar.tail(10)
# 提取customerIDpre_id = telcom_id.tail(10)
# 使⽤朴素贝叶斯⽅法,对预测数据集中的⽣存情况进⾏预测model = GaussianNBmodel.fit(X_train,y_train)pred_y =
model.predict(pred_X)
# 预测结果predDf = pd.DataFrame({'customerID':pre_id, 'Churn':pred_y})predDf返回搜狐,查看更多
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论