一文看懂机器学习流程(客户流失率预测)
点击上方“程序员大咖”,选择“置顶公众号”
关键时刻,第一时间送达!
定义问题
当然, 实际的场景比本文例子复杂的多,如果想具体应用到项目, 还需要针对不同的场景和数据进行具体的分析。
从机器学习的分类来讲, 这是一个监督问题中的分类问题。 具体来说, 是一个二分类问题。 所有的数据中包括一些特征, 最后就是它的分类:流失或者在网。接下来我们就开始具体的处理。
分析数据
数据导入
通过pandas来导入csv, 然后我们来查看一下数据的基本情况
from __future__ import divisionimport pandas as pdimport numpy as npds = pd.read_csv('./churn.csv')col_names = ds.columns.tolist()print "Column names:"print col_namesprint(ds.shape)
输出:
Column names:['State', 'Account Length', 'Area Code', 'Phone', "Int'l Plan", 'VMail Plan', 'VMail Message', 'Day Mins', 'Day Calls', 'Day Charge', 'Eve Mins', 'Eve Calls', 'Eve Charge', 'Night Mins', 'Night Calls', 'Night Charge', 'Intl Mins', 'Intl Calls', 'Intl Charge', 'CustServ Calls', 'Churn?'](3333, 21)
可以看到, 整个数据集有3333条数据, 20个维度, 最后一项是分类。
基本信息以及类型
我们可以打印一些数据, 对数据和取值有一个基本的理解。
peek = data.head(5)print(peek)
输出:
State Account Length Area Code Phone Int'l Plan VMail Plan KS 128 415 382-4657 no yes 1 OH 107 415 371-7191 no yes 2 NJ 137 415 358-1921 no no 3 OH 84 408 375-9999 yes no 4 OK 75 415 330-6626 yes no Eve Charge Night Mins Night Calls Night Charge Intl Mins Intl Calls 16.78 244.7 91 11.01 10.0 3 1 16.62 254.4 103 11.45 13.7 3 2 10.30 162.6 104 7.32 12.2 5 3 5.26 196.9 89 8.86 6.6 7 4 12.61 186.9 121 8.41 10.1 3 Intl Charge CustServ Calls Churn? 0 2.70 1 False. 1 3.70 1 False. 2 3.29 0 False. 3 1.78 2 False. 4 2.73 3 False.
我们可以看到, 数据集有20项特征,分别是州名, 账户长度, 区号, 电话号码, 国际计划,语音邮箱, 白天通话分钟数, 白天电话个数, 白天收费, 晚间通话分钟数,晚间电话个数, 晚间收费, 夜间通话分钟数,夜间电话个数, 夜间收费, 国际分钟数, 国际电话个数, 国际收费, 客服电话数,流失与否.
可以看到这里面有个人信息,应该可以看到有些信息与流失与否关系不大。 州名, 区号可以指明客户的位置, 和流失有关系么, 不知道, 具体位置如果不分类, 应该完全没有关系。 而州名, 也许某个州有了某个强劲的竞争对手? 这也是瞎猜, 暂时意义不大, 删除。
账号长度, 电话号码, 不需要
国际计划, 语音邮箱。 可能有关系, 先留着吧。
分别统计了白天, 晚间, 夜间的通话分钟, 电话个数, 收费情况。 这是重要信息保留
客服电话, 客户打电话投诉多那流失率可能会大。 这个是重要信息保留。
流失与否。 这是分类结果。
然后我们可以看一下数据的类型, 如下:
ds.info()
输出:
RangeIndex: 3333 entries, 0 to 3332Data columns (total 21 columns):State 3333 non-null objectAccount Length 3333 non-null int64Area Code 3333 non-null int64Phone 3333 non-null objectInt'l Plan 3333 non-null objectVMail Plan 3333 non-null objectVMail Message 3333 non-null int64Day Mins 3333 non-null float64Day Calls 3333 non-null int64Day Charge 3333 non-null float64Eve Mins 3333 non-null float64Eve Calls 3333 non-null int64Eve Charge 3333 non-null float64Night Mins 3333 non-null float64Night Calls 3333 non-null int64Night Charge 3333 non-null float64Intl Mins 3333 non-null float64Intl Calls 3333 non-null int64Intl Charge 3333 non-null float64CustServ Calls 3333 non-null int64Churn? 3333 non-null objectdtypes: float64(8), int64(8), object(5)memory usage: 546.9+ KB
看见, 有int, float, object。 对于不是数据型的数据, 后面除非决策树等算法, 否则应该会转化成数据行。 所以我们把churn? 结果转化, 以及"Int'l Plan","VMail Plan", 这两个参数只有yes, no 两种, 所以也进行转化成01值。
描述性统计
describe() 可以返回具体的结果, 对于每一列。
数量 平均值 标准差 25% 分位 50% 分位数 75% 分位数 最大值 很多时候你可以得到NA的数量和比例。
TODO 对于非数据性的是没有返回的的
Account Length Area Code VMail Message Day Mins Day Calls count 3333.000000 3333.000000 3333.000000 3333.000000 3333.000000 mean 101.064806 437.182418 8.099010 179.775098 100.435644 std 39.822106 42.371290 13.688365 54.467389 20.069084 min 1.000000 408.000000 0.000000 0.000000 0.000000 25% 74.000000 408.000000 0.000000 143.700000 87.000000 50% 101.000000 415.000000 0.000000 179.400000 101.000000 75% 127.000000 510.000000 20.000000 216.400000 114.000000 max 243.000000 510.000000 51.000000 350.800000 165.000000 Day Charge Eve Mins Eve Calls Eve Charge Night Mins count 3333.000000 3333.000000 3333.000000 3333.000000 3333.000000 mean 30.562307 200.980348 100.114311 17.083540 200.872037 std 9.259435 50.713844 19.922625 4.310668 50.573847 min 0.000000 0.000000 0.000000 0.000000 23.200000 25% 24.430000 166.600000 87.000000 14.160000 167.000000 50% 30.500000 201.400000 100.000000 17.120000 201.200000 75% 36.790000 235.300000 114.000000 20.000000 235.300000 max 59.640000 363.700000 170.000000 30.910000 395.000000 Night Calls Night Charge Intl Mins Intl Calls Intl Charge count 3333.000000 3333.000000 3333.000000 3333.000000 3333.000000 mean 100.107711 9.039325 10.237294 4.479448 2.764581 std 19.568609 2.275873 2.791840 2.461214 0.753773 min 33.000000 1.040000 0.000000 0.000000 0.000000 25% 87.000000 7.520000 8.500000 3.000000 2.300000 50% 100.000000 9.050000 10.300000 4.000000 2.780000 75% 113.000000 10.590000 12.100000 6.000000 3.270000 max 175.000000 17.770000 20.000000 20.000000 5.400000 CustServ Calls count 3333.000000 mean 1.562856 std 1.315491 min 0.000000 25% 1.000000 50% 1.000000 75% 2.000000 max 9.000000
图形化理解你的数据
之前的一些信息, 只是一些很初步的理解, 但是对于机器学习算法来讲是不够的。 下面我们从几个维度去进一步理解你的数据。工具可以用数字表格, 也可以用图形(matplotlib) 这里画图较多。
特征自己的信息
特征和分类之间的关系
特征和特征之间的关系 -- 这里鉴于时间的关系, 有些关系并没有直接应用于算法本身, 但是在进一步的算法提升中是很有意义的, 这里更多的是一种展示。
特征本身的信息
我们先来看一下流失比例, 以及关于打客户电话的个数分布
import matplotlib.pyplot as plt%matplotlib inlinefig = plt.figure()fig.set(alpha=0.2) # 设定图表颜色alpha参数
plt.subplot2grid((2,3),(0,0)) # 在一张大图里分列几个小图ds['Churn?'].value_counts().plot(kind='bar')# plots a bar graph of those who surived vs those who did not. plt.title(u"stat for churn") # puts a title on our graphplt.ylabel(u"number") plt.subplot2grid((2,3),(0,2)) ds['CustServ Calls'].value_counts().plot(kind='bar')# plots a bar graph of those who surived vs those who did not. plt.title(u"stat for cusServCalls") # puts a title on our graphplt.ylabel(u"number") plt.show()
很容易理解。
然后呢, 我们的数据的特点是对白天, 晚上, 夜间,国际都有分钟数, 电话数, 收费三种维度。 那么我们拿白天的来举例。
import matplotlib.pyplot as plt%matplotlib inlinefig = plt.figure()fig.set(alpha=0.2) # 设定图表颜色alpha参数
plt.subplot2grid((2,5),(0,0)) # 在一张大图里分列几个小图ds['Day Mins'].plot(kind='kde') # plots a kernel desnsity estimate of customer plt.xlabel(u"Mins")# plots an axis lableplt.ylabel(u"density") plt.title(u"dis for day mins")plt.subplot2grid((2,5),(0,2)) ds['Day Calls'].plot(kind='kde') # plots a kernel desnsity estimate of customer plt.xlabel(u"call")# plots an axis lableplt.ylabel(u"density") plt.title(u"dis for day calls")plt.subplot2grid((2,5),(0,4)) ds['Day Charge'].plot(kind='kde') # plots a kernel desnsity estimate of customer plt.xlabel(u"Charge")# plots an axis lableplt.ylabel(u"density") plt.title(u"dis for day charge")plt.show()
可以看到分布基本上都是高斯分布, 这也符合我们的预期, 而高斯分布对于我们后续的一些算法处理是个好消息。
特征和分类的关联
我们来看一下一些特征和分类之间的关联。 比如下面int plan
import matplotlib.pyplot as pltfig = plt.figure()fig.set(alpha=0.2) # 设定图表颜色alpha参数
int_yes = ds['Churn?'][ds['Int'l Plan'] == 'yes'].value_counts()int_no = ds['Churn?'][ds['Int'l Plan'] == 'no'].value_counts()df_int=pd.DataFrame({u'int plan':int_yes, u'no int plan':int_no})df_int.plot(kind='bar', stacked=True)plt.title(u"statistic between int plan and churn")plt.xlabel(u"int or not") plt.ylabel(u"number")plt.show()
我们可以看到, 有国际电话的流失率较高。 猜测也许他们有更多的选择, 或者对服务有更多的要求。 需要特别对待。 也许你需要电话多收集一下意见了。
再来看一下
#查看客户服务电话和结果的关联fig = plt.figure()fig.set(alpha=0.2) # 设定图表颜色alpha参数
cus_0 = ds['CustServ Calls'][ds['Churn?'] == 'False.'].value_counts()cus_1 = ds['CustServ Calls'][ds['Churn?'] == 'True.'].value_counts()df=pd.DataFrame({u'churn':cus_1, u'retain':cus_0})df.plot(kind='bar', stacked=True)plt.title(u"Static between customer service call and churn")plt.xlabel(u"Call service") plt.ylabel(u"Num") plt.show()
基本上可以看出, 打客户电话的多少和最终的分类是强相关的, 打电话3次以上的流失率比例急速升高。 这是一个非常关键的指标。
准备数据
好的, 我们已经看了很多,对数据有了一定的理解。 下面我们开始具体对数据进行操作。
去除无关列
首先, 根据对问题的分析, 我们做第一件事情, 去除三列无关列。 州名, 电话, 区号。
我们和下一步一起做
转化成数值类型
对于有些特征, 本身不是数值类型的, 这些数据是不能被算法直接使用的, 所以我们来处理一下
# Isolate target datads_result = ds['Churn?']Y = np.where(ds_result == 'True.',1,0)dummies_int = pd.get_dummies(ds['Int'l Plan'], prefix='_int'l Plan')dummies_voice = pd.get_dummies(ds['VMail Plan'], prefix='VMail')ds_tmp=pd.concat([ds, dummies_int, dummies_voice], axis=1)# We don't need these columnsto_drop = ['State','Area Code','Phone','Churn?', 'Int'l Plan', 'VMail Plan']df = ds_tmp.drop(to_drop,axis=1)print "after convert "print df.head(5)
输出:
after convert 01 Account Length VMail Message Day Mins Day Calls Day Charge Eve Mins 0 128 25 265.1 110 45.07 197.4 1 107 26 161.6 123 27.47 195.5 2 137 0 243.4 114 41.38 121.2 3 84 0 299.4 71 50.90 61.9 4 75 0 166.7 113 28.34 148.3 Eve Calls Eve Charge Night Mins Night Calls Night Charge Intl Mins 0 99 16.78 244.7 91 11.01 10.0 1 103 16.62 254.4 103 11.45 13.7 2 110 10.30 162.6 104 7.32 12.2 3 88 5.26 196.9 89 8.86 6.6 4 122 12.61 186.9 121 8.41 10.1 Intl Calls Intl Charge CustServ Calls _int'l Plan_no _int'l Plan_yes 0 3 2.70 1 1 0 1 3 3.70 1 1 0 2 5 3.29 0 1 0 3 7 1.78 2 0 1 4 3 2.73 3 0 1 VMail_no VMail_yes 0 0 1 1 0 1 2 1 0 3 1 0 4 1 0
我们可以看到结果, 所有的数据都是数值型的, 而且除去了对我们没有意义的列。
scale 数据范围
我们需要做一些scale的工作。 就是有些属性的scale 太大了。
对于逻辑回归和梯度下降来说, 个属性的scale 差距太大, 会对收敛速度有很大的影响。
我们这里对所有的都做, 其实可以对一些突出的特征做这种处理。
#scaleX = df.as_matrix().astype(np.float)
# This is importantfrom sklearn.preprocessing import StandardScalerscaler = StandardScaler()X = scaler.fit_transform(X)
print "Feature space holds %d observations and %d features" % X.shapeprint "Unique target labels:", np.unique(y)
输出:
Feature space holds 3333 observations and 19 featuresUnique target labels: [0 1]
其他的呢, 还可以考虑降维等各种方式。 但是再实际使用中, 我们往往首先做出一个模型, 得到一个参考结果, 然后逐步优化。 所以我们准备数据就到这里。
评估算法
我们会使用多个算法来计算结果, 然后选择较好的。 如下
# prepare modelsmodels = []models.append(('LR', LogisticRegression()))models.append(('LDA', LinearDiscriminantAnalysis()))models.append(('KNN', KNeighborsClassifier()))models.append(('CART', DecisionTreeClassifier()))models.append(('NB', GaussianNB()))models.append(('SVM', SVC()))# evaluate each model in turnresults = []names = []scoring = 'accuracy'for name, model in models: kfold = KFold(n_splits=10, random_state=7) cv_results = cross_val_score(model, X, Y, cv=kfold, scoring=scoring) results.append(cv_results) names.append(name) msg = "%s: %f (%f)" % (name, cv_results.mean(), cv_results.std()) print(msg)# boxplot algorithm comparisonfig = pyplot.figure()fig.suptitle('Algorithm Comparison')ax = fig.add_subplot(111)pyplot.boxplot(results)ax.set_xticklabels(names)pyplot.show()
LR: 0.860769 (0.021660)LDA: 0.852972 (0.021163)KNN: 0.896184 (0.016646)CART: 0.920491 (0.012471)NB: 0.857179 (0.015487)SVM: 0.921091 (0.016828)
可以看到什么呢, 看到SVM 和 CART 效果相对较好。
提升结果
提升的部分, 如何使用提升算法。 比如随机森林。 xgboost
from sklearn.ensemble import RandomForestClassifiernum_trees = 100max_features = 3kfold = KFold(n_splits=10, random_state=7)model = RandomForestClassifier(n_estimators=num_trees, max_features=max_features)results = cross_val_score(model, X, Y, cv=kfold)print(results.mean())# 0.954696013379
from sklearn.ensemble import GradientBoostingClassifierseed = 7num_trees = 100kfold = KFold(n_splits=10, random_state=seed)model = GradientBoostingClassifier(n_estimators=num_trees, random_state=seed)results = cross_val_score(model, X, Y, cv=kfold)print(results.mean())# 0.953197209185
可以看到, 这两种算法对单个算法的提升还是很明显的。 进一步的, 也可以继续调整tree的数目, 但是效果应该差不多了。
展示结果
这里展示了如何保存这个算法, 以及如何取出然后应用。
#storefrom sklearn.model_selection import train_test_splitfrom pickle import dumpfrom pickle import loadX_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.33, random_state=7)from sklearn.ensemble import GradientBoostingClassifierseed = 7num_trees = 100kfold = KFold(n_splits=10, random_state=seed)model = GradientBoostingClassifier(n_estimators=num_trees, random_state=seed)model.fit(X_train, Y_train)# save the model to diskfilename = 'finalized_model.sav'dump(model, open(filename, 'wb'))# some time later...# load the model from diskloaded_model = load(open(filename, 'rb'))result = loaded_model.score(X_test, Y_test)print(result)
后记
本文展示了通过用户流失率问题, 如何把机器学习的预测过程应用到实际项目中。
从业务的角度, 这个只是一个demo性质的应用, 实际场景可能复杂的多。
从流程的角度, 通过对数据的分析可以进一步提升算法的性能, 对于某些的特征, 可以采取不同的处理方式。 比如缺失值的处理, 这里很完整, 就省去了这个步骤。
来自:开源中国
https://my.oschina.net/sizhe/blog/1594791
程序员大咖整理发布,转载请联系作者获得授权
【点击成为Python大神】
一文看懂机器学习流程(客户流失率预测)相关推荐
- 入门科普:一文看懂机器学习3种类型的概念、根本差别及应用 | 洞见
作者 | 塞巴斯蒂安·拉施卡.瓦希德·米尔贾利利 来源 | 出自<Python机器学习(原书第2版)> 转自 | 大数据(ID:hzdashuju) 导读:机器学习是使数据具有意义的算法的 ...
- 入门科普:一文看懂机器学习3种类型的概念、根本差别及应用
来源:大数据 作者:塞巴斯蒂安·拉施卡.瓦希德·米尔贾利利 本文约4700字,建议阅读7分钟. 本文将讨论机器学习的主要概念.不同类型及相关术语,为利用机器学习技术成功地解决实际问题奠定基础. [导 ...
- 一文看懂机器学习中的常用损失函数
作者丨stephenDC 编辑丨zandy 来源 | 大数据与人工智能(ID: ai-big-data) 导语:损失函数虽然简单,却相当基础,可以看做是机器学习的一个组件.机器学习的其他组件,还包括激 ...
- 一文看懂:芯片IC的封装/测试流程
一文看懂:芯片IC的封装/测试流程 流程 IC Package (IC的封装形式)指芯片(Die)和不同类型的框架(L/F)和塑封料(EMC)形成的不同外形的封装体. IC Package种类很多,可 ...
- 【机器学习】一文看懂贝叶斯优化/Bayesian Optimization
点击上方,选择星标,每天给你送干货! 来自:AI部落联盟 今天想谈的问题是:什么是贝叶斯优化/Bayesian Optimization,基本用法是什么? 本文的定位是:帮助未接触.仅听说过.初次接触 ...
- 《SOC芯片研究框架》深度科普,发展趋势、技术特点、产业链一文看懂
片上系统SoC(System on Chip),即在一块芯片上集成一整个信息处理系统,简单来说 SoC芯片是在中央处理器CPU的基础上扩展音视频功能和专用接口的超大规模集成电路,是智能设备的" ...
- [转帖] 一文看懂:边缘计算究竟是什么?为何潜力无限?
一文看懂:"边缘计算"究竟是什么?为何潜力无限? 转载cnbeta 云计算 雾计算 边缘计算... 知名创投调研机构CB Insights撰文详述了边缘计算的发展和应用前景.文章称 ...
- 一文看懂:互联网产品分析,该如何做?
总有同学们在抱怨:"说的是做产品分析,可实际上每天都在埋点,建表,写SQL,对口径,找bug,我分析啥了?到底啥是产品分析?"今天简单分享一下. 所谓产品分析,特指对互联网产品:A ...
- 用户画像标签维度_一文看懂用户画像标签体系(包括维度、应用场景)
一文看懂用户画像标签体系(包括维度.应用场景) 互联网相关企业在建立用户画像时一般除了基于用户维度(userid)建立一套用户标签体系外,还会基于用户使用设备维度(cookieid)建立相应的标签体系 ...
最新文章
- powerDesign设计随笔
- 大数据和高并发的解决方案汇总
- the more wites of color
- ubuntu 使用ccache加快linux内核编译速度
- 使用强大的 Mockito 测试框架来测试你的代码
- SpringBoot使用Jsp
- DCGAN baseline
- 中国节能吊扇行业市场供需与战略研究报告
- c语言输入y循环n结束,大佬们帮帮忙 帮我改改 怎样能在输入Y后 再次进行for循环...
- H5开发和原生开发的区别
- 打开GTA 5竟要跑19.8亿次if语句!黑客嘲讽R星代码烂,修改后直接省70%加载时间...
- 正则表达式匹配中文及符号、英文及符号数字空格换行符及常用正则表达式
- linux excel自动换行,Excel中巧用样式列表快速实现文本换行
- Windows 软件定义存储S2D 测试
- 微信公众号运营的七大问题,你遇到了吗?
- ENVI系列--使用矢量文件裁剪目标区域
- 数理逻辑初步:命题逻辑、一阶逻辑和二阶逻辑
- 新款智能枕头为人们的生活带来更佳体验
- 文献综述怎么弄和书写格式
- 微信小程序毕业设计 基于微信茶叶小程序商城系统前后功能和界面参考