(kesci数据分类预测)提供银行精准营销解决方案练习赛

kesci的一个练习赛:https://www.kesci.com/home/competition/5c234c6626ba91002bfdfdd3/content

赛题描述

训练集有20000多条,测试集10000多条,16维特征,最后有两种结果分类:0(不会买银行的产品)和1(会买银行的产品):

数据预处理

先引入包和读入数据集(包括sklearn中的机器学习算法包和深度学习框架keras),关于分类预测算法可以看我之前的博文:https://blog.csdn.net/qq_43012160/article/details/96303739

import pandas as pd
import numpy as np
import time
import lightgbm as lg
from keras import models
from keras import layers
from keras.utils.np_utils import to_categorical
from keras.preprocessing.text import Tokenizer
from sklearn import metrics
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.neural_network import MLPClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import BernoulliNB
from sklearn.naive_bayes import GaussianNB
from sklearn.naive_bayes import MultinomialNB
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import AdaBoostClassifier
from sklearn.preprocessing import LabelEncoder
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn import svm
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import MinMaxScaler#读数据集:
train_data = pd.read_csv('train_set.csv', lineterminator='\n')
test_data=pd.read_csv('test_set.csv', lineterminator='\n')

观察数据集,pdays特征指客户上次与银行联系过去的天数,-1指没联系过。为了保证数据的单调性,即值越大表示用户与银行的联系越久远、越不活跃,用excel的筛选发现这一特征的最大值为854,所以把所有的-1都改成999:

#数据预处理:
print("数值处理:")
#数据中pdays=-1表示从未联络过,替换为999
train_data['pdays'].replace(-1,999,inplace=True)
test_data['pdays'].replace(-1,999,inplace=True)

之后提取一下训练集的分类标签,方便后面给分类器传参:

#提取训练集标签
def getLabel(data):listLable=[]for lable in data['y']:listLable.append(lable)return listLabletrainLable=np.array(getLabel(train_data))

因为现在有很多特征的值还是字符串,但是最后分类器接收的参数是全数值得二维矩阵,所以我们要给这些特征进行编码。因为编码耗时比较长,而且不管什么分类器都是用这一套编码后的数据,编码完可以保存到文件里,下次用的时候直接从文件里读入就行了。这里比较复杂,我们先大概浏览一下代码:

print("编码:")
#提取要编码的特征目录:
changeColumns=['job','marital','education','default','housing','loan','contact','month','poutcome']
dataColumns=[]
for elem in test_data.columns:if not(elem=='ID'): dataColumns.append(elem)#规格化编码特征标签:
print("标准化与规格化:")
def getReview(data):ResultReview=[]listReview=datale = LabelEncoder()std = StandardScaler()scl=MinMaxScaler()for column in changeColumns:listData=[]ResultData=[]for review in data[column]:listData.append(review)ResultData=le.fit_transform(listData)listReview[column]=ResultData#不同特征编码的归一化:for column in dataColumns:listReview[column]=scl.fit_transform(listReview[column].values.reshape(-1,1))#处理负数:min = 0for column in dataColumns:print('正在寻找最小值:',column,'...')for elem in listReview[column]:if elem < min: min = elemfor column in dataColumns:print('正在处理',column,'...')for i in range(len(listReview[column])):listReview.loc[i, column] = listReview.loc[i, column] - min#向量化:for i in range(len(data)):rowVec=[]for feature in dataColumns:rowVec.append(listReview.loc[i,feature])ResultReview.append(rowVec)return ResultReview#对处理完毕的训练集进行保存:
trainReview=np.array(getReview(train_data))
testReview=np.array(getReview(test_data))
np.save("trainReview.npy",trainReview)
np.save("testReview.npy",testReview)

LabelEncoder对特征进行编码

  for column in changeColumns:listData=[]ResultData=[]for review in data[column]:listData.append(review)ResultData=le.fit_transform(listData)listReview[column]=ResultData

我们看到比如特征poutcome,有四种取值:

因为最后传给分类器得训练集是全数值得二维矩阵,所以我们就要用LabelEncoder给特征进行编码,比如把failure编码为0,other编码为1,success为2,unknown为3。实际LabelEncoder编码的时候不是按先后顺序来的,但用的就是这样一个编码规则。

不同特征取值的归一化

做好编码之后我们的所有特征值就全都用数字表示了,但我们注意到不同的特征间的数据取值范围是有很大差异的,比如age特征就只有几十,但是balance就可能是几千。这就是分类预测中不同特征的量纲问题,为了解决这个问题就要谈到数据的归一化、标准化和正则化:
1.常用的线性归一化即对某一特征的取值使用函数 y=(x-min)/(max-min)进行变换,把数据变为(0,1)之间的小数。归一化是为了消除不同数据之间的量纲, 把有量纲表达式变换为无量纲表达式,成为纯量。经过归一化处理的数据,处于同一数量级,可以消除指标之间的量纲和量纲单位的影响,提高不同数据指标之间的可比性,方便分类器对不同特征统一处理。
2.常用的零-均值标准化: y=(x-μ)/σ。可以使原本分布不均的数据变为正态分布,方便后续处理。
3.正则化而是利用先验知识,在处理过程中引入正则化因子(regulator),增加引导约束的作用,比如在逻辑回归中使用正则化,可有效降低过拟合的现象。
原博:https://blog.csdn.net/zyf89531/article/details/45922151

这里我们是为了消除不同特征之间的量纲,所以选择归一化处理:

 for column in dataColumns:listReview[column]=scl.fit_transform(listReview[column].values.reshape(-1,1))

新版本sklearn包提供的归一化器MinMaxScaler()要求提供的参数必须是一个二维矩阵,所以这里用了listReview[column].values.reshape(-1,1)将列向量转化为1列的二维矩阵。

处理负数

由于sklearn包有的分类器不接受负数,所以要把数据中的所有数都变成正数(即减去最小的负数):

 #处理负数:min = 0for column in dataColumns:print('正在寻找最小值:',column,'...')for elem in listReview[column]:if elem < min: min = elemfor column in dataColumns:print('正在处理',column,'...')for i in range(len(listReview[column])):listReview.loc[i, column] = listReview.loc[i, column] - min

向量化

因为经过这些处理后的数组仍然是DataFrame,而分类器需要的参数是一个二维矩阵,矩阵由每条样本构成,而样本又是一个16维的向量,类似这样:
[[1,2,…,3,4],
[5,6,…,7,8],

[4,3,…,2,1]]
所以我们对DataFrame一行一行的处理,将每一行的数据(每条样本)处理为行向量,然后添加到目标数组中,再用np.array()方法将其转化为numpy矩阵:

    #向量化:for i in range(len(data)):rowVec=[]for feature in dataColumns:rowVec.append(listReview.loc[i,feature])ResultReview.append(rowVec)return ResultReview

函数调用、数组转numpy矩阵与保存:

#对处理完毕的训练集进行保存:
trainReview=np.array(getReview(train_data))
testReview=np.array(getReview(test_data))
np.save("trainReview.npy",trainReview)
np.save("testReview.npy",testReview)

建模与预测

加载处理后的数据:

trainReview = np.load("trainReview.npy")
testReview = np.load("testReview.npy")

传统机器学习模型,这里经过实测发现逻辑回归、MLP、和随机森林效果比较好:

#传统机器学习模型预测:
print('建模:')
model = MLPClassifier()
model.fit(trainReview, trainLable)
print(model)print('预测:')
pred_model = model.predict_proba(testReview)

深度学习模型(前馈神经网络,效果也不错):

#前馈神经网络模型预测:
print('建模:')
feature_num = trainReview.shape[1]
#求标签的独热编码矩阵
trainCate = to_categorical(trainLable)
#1 创建神经网络
network = models.Sequential()
#2 添加神经连接层
#第一层必须有并且一定是 [输入层], 必选
network.add(layers.Dense(     # 添加带有 relu 激活函数的全连接层units=100,activation='relu',input_shape=(feature_num, )))
#介于第一层和最后一层之间的称为 [隐藏层],可选
network.add(layers.Dense(     # 添加带有 relu 激活函数的全连接层units=100,activation='relu'))
#最后一层必须有并且一定是 [输出层], 必选
network.add(layers.Dense(     # 添加带有 softmax 激活函数的全连接层units=2,   #输出层感知器个数即标签维度/类数activation='softmax'))
#3 编译神经网络
network.compile(loss='categorical_crossentropy',  # 分类交叉熵损失函数optimizer='rmsprop',metrics=['accuracy']              # 准确率度量,也是选定evaluate的指标值为准确度)
#4 开始训练神经网络
network.fit(trainReview,     # 训练集特征trainCate,        # 训练集标签epochs=32,          # 迭代次数batch_size=100,    # 指定进行梯度下降时每个batch包含的样本数)
#利用模型进行预测
print('预测:')
pred_model = network.predict_proba(testReview)

为什么不用CNN

作为一个刚入门的初学者我最初也想CNN能不能用在这种分类问题上,后来发现是不行的。CNN主要的特点就是卷积和池化,而卷积和池化本身就建立在“数据的不同特征之间存在内在联系”,比如同一条文本的上下文或者同一张图片的相邻像素之间的。这里的分类特征之间是没有这种很强的不同特征之间的联系的(你要是硬说年龄越大越穷那我也没话说),所以CNN的卷积和池化对于这类分类问题是没有意义的,所以不用CNN来做这一类的分类预测。

结果的写入与展示

这里选取会买产品1(pos)和不会买产品0(neg)的占比打印:

print('写入结果:')
result=[]
for elem in pred_model:result.append(elem[1])
dataframe = pd.DataFrame({'ID':test_data['ID'],'pred':result})
dataframe.to_csv("preResult.csv",index=False,sep=',')#结果展示:
pos=0
neg=0
for elem in result:if elem>0.5:pos=pos+1else:neg=neg+1
print('pos:',pos/len(test_data))
print('neg:',neg/len(test_data))

这里经过我多次测试,测试集里1和0大概是11:89左右的关系,我跑出来的最好的结果使用MLP跑出来的,评分是0.90(菜的抠jio):
我看第一名1.0的正确率,神仙吧。

源码:
链接:https://pan.baidu.com/s/1Hs7ZHkNSrVkpBrZlR0HFPg
提取码:9htw

kesci数据分类练习赛:提供银行精准营销解决方案(附源码)相关推荐

  1. 「二分类算法」提供银行精准营销解决方案(样本不平衡问题)

    项目背景 项目来源于Kesci平台:提供银行精准营销解决方案 项目简介 本练习赛的数据,选自UCI机器学习库中的「银行营销数据集(Bank Marketing Data Set)」 这些数据与葡萄牙银 ...

  2. 「二分类算法」提供银行精准营销解决方案 代码存档

    「二分类算法」提供银行精准营销解决方案 代码存档 参考文章: (1)「二分类算法」提供银行精准营销解决方案 代码存档 (2)https://www.cnblogs.com/starcrm/p/1180 ...

  3. 「二分类算法」提供银行精准营销解决方案(各个模型汇总分析)baseline

    完整代码见 Github:「二分类算法」提供银行精准营销解决方案 赛事详情 1.比赛页面:「二分类算法」提供银行精准营销解决方案 2.数据与测评算法 训练集下载链接 测试集下载链接 字段说明 测评算法 ...

  4. 「二分类算法」提供银行精准营销解决方案

    银行精准营销解决方案 营销活动以电话为基础,一般,银行的客服人员需要联系客户至少一次. 数据集中包含有客户年龄,职业婚姻,教育水平等信息,通过这些信息建模,预测客户是否将认购该银行的产品 一.数据和库 ...

  5. 随机森林:提供银行精准营销解决方案

    原文地址:https://blog.csdn.net/weixin_34233679/article/details/88480912 本例是根据科赛网练习赛进行练手,学习巩固一下随机森林建模以及应用 ...

  6. 「二分类算法」提供银行精准营销解决方案详解(随机森林)

    这些数据与葡萄牙银行机构的营销活动相关.这些营销活动以电话为基础,一般,银行的客服人员需要联系客户至少一次,以此确认客户是否将认购该银行的产品(定期存款). 通过与葡萄牙银行机构的直销活动(电话)有关 ...

  7. easypoi 批量导出_POI导出大量数据的简单解决方案(附源码)

    说明:我的电脑 2.0CPU 2G内存 能够十秒钟导出 20W 条数据 ,12.8M的excel内容压缩后2.68M 我们知道在POI导出Excel时,数据量大了,很容易导致内存溢出.由于Excel ...

  8. 银行精准营销的概念讲解

    我们都知道,银行精准营销是一种不错的数据库营销手段.博主本文就为大家详细介绍一下如何进行银行精准营销哦. 目前我国大部分银行委托外包公司制作银企对账单,但其弊病非常明显:容易外泄客户名单.对账单无故丢 ...

  9. 如何助力银行精准营销

    如何助力银行精准营销已经越来越成为一个重要的研究课题.小编本文就详细为大家分析一下银行精准营销各方面内容. 在中国,随着富裕人群的不断崛起,银行会对不同资产额的客户提供不同的服务,对于个性化的要求会越 ...

最新文章

  1. Django 视图URLconf3.1
  2. ​两院院士评选“2021年中国/世界十大科技进展新闻”揭晓
  3. php注册表唯一电脑,PHP常见设计模式之注册表模式
  4. python动态语言解释_python是动态语言吗
  5. php resultset用法,PHP PDOStatement::nextRowset讲解
  6. Boost:can_require_concepr的使用测试程序
  7. 代理设置。 安卓工作室配置用http代理。gradle可能需要这些http代理设置去访问互联网。例如下载依赖。 你想要复制ide的代理配置到这个项目的gradle属性文件吗?...
  8. 【微信小程序开发•系列文章七】websocket
  9. [Python学习] Django 权限控制
  10. python中collections模块_Python的collections模块
  11. python程序设计课程设计二级减速器_二级减速器课程设计完整版
  12. untiy Socket通信一篇通
  13. 无意中学到的,感谢通用
  14. 文化袁探索专栏——React Native启动流程
  15. C语言-输入一个整数把每位数字转换为英文
  16. iis7无法写入配置文件,更换进入方式解决
  17. Python常用模块 hashlib,pymysql,logging和datetime模块习题检测
  18. 【转载】亡灵对抗人类的一点战术
  19. 上周技术关注:Alexa开放搜索爬虫接口
  20. PHP仿百度网盘文件分享dzzoffice网盘系统源码

热门文章

  1. python十年后的体重_测试一下你10年后的体重
  2. 正在启动 httpd:httpd:Could not reliably determine the server‘s fully qualif domain name,using ::1 for Se
  3. 智慧一体化档案库房管理系统建设方案
  4. oracle11gdw标识无效,Linux下oracle11g 导入导出操作详细
  5. 最通俗解释什么是(ip、网段、端口)?
  6. id,class选择器(CSS)
  7. class选择器的命名规范
  8. 小试牛刀--Oracle 基准测试 SLOB
  9. 趣图:搞笑程序员表情包 | 这代码......辣眼睛.....
  10. 【Week 15 作业C】ZJM与纸条