热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

CDA营销项目

《产品营销模型之建置及预测》赛题说明最终成绩:0.8225背景:A公司有一款在线服务的P产品,公司的营销通路是100%的

《产品营销模型之建置及预测》赛题说明

最终成绩:0.8225

背景:
A公司有一款在线服务的P产品,公司的营销通路是100%的网络媒介。A公司希望提供30天免费的P产品后,期望顾客能正式签约购买P产品之服务。但A公司发现‚每隔1~2天便对数以万计的顾客发送电子营销文宣,不但购买率低下,甚至造成诸多客诉。同时,客户之预期获利是以人工经验评估之,没有量化或模型工具之协助,不晓得到底应该使用广告全投放还是机器学习模型来做投放?

目标:
A公司希望发掘用户购买产品的行为习惯,建立产品精准营销模型,对有意向的客户进行精准营销,增加收入,减少开支。

评分标准:
我们通过混淆矩阵(Confusion matrix)来评价分类模型的准确率。准确率越高,说明正确预测出响应营销效果越好。

提交结果:
选手以训练数据为基础,建立产品营销模型,并上传一个测试结果的档案results.csv,文档中只有两个字段,分别是客户ID以及预测客户是否会购买(Predicted_Results)的结果。

字段说明
在这里插入图片描述

代码

"""准备工具"""
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
#查看缺失值
import missingno as msno
#时间模块
import time
from sklearn.model_selection import train_test_split,GridSearchCV
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report,roc_auc_score,accuracy_score
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
import xgboost
from sklearn.naive_bayes import GaussianNB
import gc
import warnings
warnings.filterwarnings('ignore')
#解决显示中文错误
import matplotlib as mpl
mpl.rcParams['font.sans-serif'] = [u'SimHei']
mpl.rcParams['axes.unicode_minus'] = False
pd.set_option('display.max_columns',None)
pd.set_option('display.max_rows',None)

"""写入文件"""
train_data = pd.read_csv('df_training.csv',na_values='?',names=['客户ID','产品使用分数','用户地区','性别','年龄','使用累计时间','点数余额','产品服务使用量','是否为使用信用卡付月费','是否为活跃用户','估计薪资','购买与否'],header=0)

ID不是特征不使用,购买与否为要预测的标签,查看缺失值,判断是否为离散型数据

train_data.info()<class &#39;pandas.core.frame.DataFrame&#39;>
RangeIndex: 6000 entries, 0 to 5999
Data columns (total 12 columns):# Column Non-Null Count Dtype
--- ------ -------------- ----- 0 客户ID 6000 non-null int64 1 产品使用分数 4165 non-null float642 用户地区 4167 non-null object 3 性别 4156 non-null object 4 年龄 4179 non-null float645 使用累计时间 4207 non-null float646 点数余额 4232 non-null float647 产品服务使用量 4188 non-null float648 是否为使用信用卡付月费 4118 non-null float649 是否为活跃用户 4181 non-null float6410 估计薪资 4161 non-null float6411 购买与否 6000 non-null int64
dtypes: float64(8), int64(2), object(2)
memory usage: 562.6&#43; KB

这里认为nunique值大于15为连续性变量&#xff0c;反之则为离散变量

con &#61; [] #收集连续型数据
dis &#61; [] #收集离散型数据
for col in train_data.columns[1:-1]:print(col)print(train_data[col].value_counts())print(&#39;缺失值比例&#39;,train_data[col].isnull().sum()/train_data.shape[0])if train_data[col].nunique() > 15:print(&#39;连续型&#39;)con.append(col)else:print(&#39;离散型&#39;)dis.append(col)print()

先处理离散型数据&#xff0c;统一将空值填充为一个不影响的值&#xff0c;独热后将该列的独热列删除

data &#61; train_data.copy()
data &#61; data.fillna(&#39;999&#39;) #用xxx代表空值&#xff0c;便于独热后区分
hot_col &#61; [&#39;area&#39;,&#39;sex&#39;,&#39;time&#39;,&#39;service&#39;,&#39;monthly&#39;,&#39;active&#39;] #独热时的名字#将每一列进行独热编码&#xff0c;删除掉‘999’的独热列
area_hot &#61; pd.get_dummies(data[dis[0]],prefix&#61;hot_col[0])
area_hot &#61; area_hot.drop(&#39;area_999&#39;,axis&#61;1) #删
sex_hot &#61; pd.get_dummies(data[dis[1]],prefix&#61;hot_col[1])
sex_hot &#61; sex_hot.drop(&#39;sex_999&#39;,axis&#61;1) #删
time_hot &#61; pd.get_dummies(data[dis[2]],prefix&#61;hot_col[2])
time_hot &#61; time_hot.drop(&#39;time_999&#39;,axis&#61;1) #删
service_hot &#61; pd.get_dummies(data[dis[3]],prefix&#61;hot_col[3])
service_hot &#61; service_hot.drop(&#39;service_999&#39;,axis&#61;1) #删
monthly_hot &#61; pd.get_dummies(data[dis[4]],prefix&#61;hot_col[4])
monthly_hot &#61; monthly_hot.drop(&#39;monthly_999&#39;,axis&#61;1) #删
active_hot &#61; pd.get_dummies(data[dis[5]],prefix&#61;hot_col[5])
active_hot &#61; active_hot.drop(&#39;active_999&#39;,axis&#61;1) #删

数据格式转化&#xff0c;字符数据数值化

for col in dis[2:]:data[col] &#61; data[col].astype(&#39;float32&#39;)
for i in con:data[i] &#61; data[i].astype(&#39;float32&#39;)# 可以使用LabelEncoder
data[&#39;用户地区&#39;] &#61; data[&#39;用户地区&#39;].replace(&#39;Taipei&#39;,0)
data[&#39;用户地区&#39;] &#61; data[&#39;用户地区&#39;].replace(&#39;Taichung&#39;,1)
data[&#39;用户地区&#39;] &#61; data[&#39;用户地区&#39;].replace(&#39;Tainan&#39;,2)
data[&#39;用户地区&#39;] &#61; data[&#39;用户地区&#39;].astype(&#39;float32&#39;)
data[&#39;性别&#39;] &#61; data[&#39;性别&#39;].replace(&#39;Male&#39;,0)
data[&#39;性别&#39;] &#61; data[&#39;性别&#39;].replace(&#39;Female&#39;,1)
data[&#39;性别&#39;] &#61; data[&#39;性别&#39;].astype(&#39;float32&#39;)

对离散型数据进行缺失值填充&#xff0c;利用xgboost,用其他所有列对该列进行预测

for i in range(len(dis)):start &#61; time.time()print(&#39;当前特征列为&#xff1a;%s&#39;%(dis[i]))print(&#39;第一步:构造特征与标签--------------------&#39;)res &#61; data[dis[i]]y_train &#61; res[res!&#61;999]#将其余的独热编码后的列和连续型数据组合在一起来做训练com &#61; [area_hot,sex_hot,time_hot,service_hot,monthly_hot,active_hot,data[con],data[dis[i]]]df &#61; pd.concat(com,axis&#61;1)#分为训练测试集x_train &#61; df[df[dis[i]]!&#61;999].iloc[:,:-1]x_test &#61; df[df[dis[i]]&#61;&#61;999].iloc[:,:-1]print(&#39;第二步&#xff1a;建模与预测填充--------------------&#39;)xgb &#61; xgboost.XGBClassifier()xgb.fit(x_train,y_train)y_res &#61; xgb.predict(x_test)data[dis[i]][data[dis[i]]&#61;&#61;999] &#61; y_resend &#61; time.time()print(&#39;运行时间&#xff1a;%s&#39;%(end-start))print()

for i in range(len(con)):start &#61; time.time()print(&#39;当前特征列为&#xff1a;%s&#39;%(con[i]))print(&#39;第一步:构造特征与标签--------------------&#39;)res &#61; data[con[i]]y_train &#61; res[res!&#61;999]com &#61; [area_hot,sex_hot,time_hot,service_hot,monthly_hot,active_hot,data[con]]df &#61; pd.concat(com,axis&#61;1)x_train &#61; df[df[con[i]]!&#61;999].drop(con[i],axis&#61;1)x_test &#61; df[df[con[i]]&#61;&#61;999].drop(con[i],axis&#61;1)print(&#39;第二步&#xff1a;建模与预测填充--------------------&#39;)xgb &#61; xgboost.XGBClassifier()xgb.fit(x_train,y_train)res_y &#61; xgb.predict(x_test)data[con[i]][data[con[i]]&#61;&#61;999] &#61; res_yend &#61; time.time()print(&#39;运行时间&#xff1a;%s&#39;%(end-start))

上面一步将离散型数据填充完成&#xff0c;接下来用离散型数据填充连续性数据

for i in range(len(con)):start &#61; time.time()print(&#39;当前特征列为&#xff1a;%s&#39;%(con[i]))print(&#39;第一步:构造特征与标签--------------------&#39;)res &#61; data[con[i]]y_train &#61; res[res!&#61;999]com &#61; [area_hot,sex_hot,time_hot,service_hot,monthly_hot,active_hot,data[con]]df &#61; pd.concat(com,axis&#61;1)x_train &#61; df[df[con[i]]!&#61;999].drop(con[i],axis&#61;1)x_test &#61; df[df[con[i]]&#61;&#61;999].drop(con[i],axis&#61;1)print(&#39;第二步&#xff1a;建模与预测填充--------------------&#39;)xgb &#61; xgboost.XGBClassifier()xgb.fit(x_train,y_train)res_y &#61; xgb.predict(x_test)data[con[i]][data[con[i]]&#61;&#61;999] &#61; res_yend &#61; time.time()print(&#39;运行时间&#xff1a;%s&#39;%(end-start))

利用matplotlib,seaborn,pyechars可视化工具&#xff0c;查看各特征的分布&#xff0c;查看各特征与标签之前的关系&#xff0c;查看特征与特征之间的关系

"""查看各特征是否有异常值"""
for i in range(len(data.columns)):plt.figure(figsize&#61;(10,58))plt.subplot(len(data.columns),1,i&#43;1)sns.boxplot(data[data.columns[i]])年龄有异常值&#xff0c;对年龄大于60的数据进行单独查看,图中显示异常的部分只占总体的 3.9%&#xff0c;从数据上看&#xff0c;年龄符合人类正常寿命

"""离散型特征与标签"""
for i in range(len(dis)):sns.catplot(x&#61;dis[i],y&#61;&#39;购买与否&#39;,data&#61;data,kind&#61;&#39;bar&#39;,aspect&#61;2.5)用户地区&#xff0c;性别&#xff0c;使用累计时间&#xff0c;产品服务用量&#xff0c;是否为活跃用户对标签有比较明显的区分

"""连续型数据分箱查看与标签之间的关系"""
for i in range(len(con)):name &#61; &#39;%s_10&#39;%(con[i])data[name] &#61; pd.cut(data[con[i]],bins&#61;10)t &#61; data.groupby(name,as_index&#61;False)[[&#39;购买与否&#39;]].count().groupby(name,as_index&#61;False)[[&#39;购买与否&#39;]].sum()print(t) sns.catplot(x&#61;name,y&#61;&#39;购买与否&#39;,data&#61;t,kind&#61;&#39;point&#39;,aspect&#61;2.5)plt.xticks(rotation&#61;30)plt.show()产品使用分数&#xff0c;年龄对标签有比较明显的区分

"""查看相关系数"""
plt.figure(figsize&#61;(16,16))
sns.heatmap(data.iloc[:,:-4].corr(),annot&#61;True)

使用XGBOOST建模预测

"""选择比较好的特征"""
data_t &#61; data[[&#39;用户地区&#39;,&#39;性别&#39;,&#39;使用累计时间&#39;,&#39;产品服务使用量&#39;,&#39;是否为活跃用户&#39;,&#39;产品使用分数&#39;,&#39;年龄&#39;,&#39;购买与否&#39;]]"""划分数据集"""
x_train,x_test,y_train,y_test &#61; train_test_split(data_t.iloc[:,:-1],data_t.iloc[:,-1],test_size&#61;0.2,random_state&#61;42)"""利用网格搜索搜索超参数"""
xgb &#61; xgboost.XGBClassifier()
gs &#61; GridSearchCV(xgb,{&#39;max_depth&#39;:[2,4,6,7,9,10],&#39;n_estimators&#39;:[50,100,150,200],&#39;learning_rate&#39;:[1,0.1,0.01,0.001],&#39;n_jobs&#39;:[10]},cv&#61;10,refit&#61;True)
gs.fit(x_train,y_train)
pre &#61; gs.predict(x_test)

print(gc.best_params_)
print(accuracy_score(y_test,g)){&#39;learning_rate&#39;: 0.1, &#39;max_depth&#39;: 2, &#39;n_estimators&#39;: 150, &#39;n_jobs&#39;: 10}
0.8225


推荐阅读
author-avatar
mobiledu2502891957
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有