【Kaggle】Telco Customer Churn 数据编码与模型训练

💬在上一部分中,我们已经完成了对数据集背景解读、数据预处理与探索性分析。在数据背景解读中,我们介绍了数据集来源、电信用户流失分析的基本业务背景,并详细解释了每个字段的基本含义;在数据预处理过程中,我们对数据集进行了缺失值和异常值分析,并且根据实际业务情况对缺失值进行了0值填补;而在探索性分析的过程中,我们对比分析了标签不同取值时特征取值的分布情况,并从中初步分析影响用户流失的关键因素。

本节开始,我们将围绕此前已经处理好的数据来进一步来进行用户流失预测。当然,要进行尽可能精准的用户流失预测,就离不开特征工程、模型选择与训练、参数调优和模型融合这些环节。考虑到该数据集的建模目标有两个,其一是希望能够进行尽可能精准的预测,同时由于该案例也包含数据分析背景,要求模型结果也能够为业务人员在业务开展过程中提供具体指导意见,因此无论是在模型选型过程还是特征工程环节,我们都将同时纳入这两个因素进行综合考虑。


本节我们将优先考虑具备模型可解释性的逻辑回归和决策树,这两个算法也是大多数在要求对结果进行解释的场景下优先考虑的模型,此外在实际建模过程中需要注意的是,不同模型需要带入的数据编码类型也各不相同,因此在本节中,我们也将详细介绍各类数据编码方法及其使用过程中的注意事项。

💤根据上一小节的分析结果,再次执行数据预处理过程:

import numpy as np
import pandas as pd

import seaborn as sns
import matplotlib.pyplot as plt

# 读取数据
tcc = pd.read_csv('WA_Fn-UseC_-Telco-Customer-Churn.csv')

# 标注连续/离散字段
# 离散字段
category_cols = ['gender', 'SeniorCitizen', 'Partner', 'Dependents',
                'PhoneService', 'MultipleLines', 'InternetService', 'OnlineSecurity', 'OnlineBackup', 
                'DeviceProtection', 'TechSupport', 'StreamingTV', 'StreamingMovies', 'Contract', 'PaperlessBilling',
                'PaymentMethod']

# 连续字段
numeric_cols = ['tenure', 'MonthlyCharges', 'TotalCharges']

# 标签
target = 'Churn'

# ID列
ID_col = 'customerID'

# 验证是否划分能完全
assert len(category_cols) + len(numeric_cols) + 2 == tcc.shape[1]

注意,此处我们暂时将tenure划为连续性字段,以防止后续One-Hot编码时候诞生过多特征。然后进行连续变量的缺失值填补:

tcc['TotalCharges']= tcc['TotalCharges'].apply(lambda x: x if x!= ' ' else np.nan).astype(float)
tcc['MonthlyCharges'] = tcc['MonthlyCharges'].astype(float)

tcc['TotalCharges'] = tcc['TotalCharges'].fillna(0)

tcc['Churn'].replace(to_replace='Yes', value=1, inplace=True)
tcc['Churn'].replace(to_replace='No',  value=0, inplace=True)

当然,清洗完后的数据需要进行进一步重编码后才能带入进行建模,在考虑快速验证不同模型的建模效果时,需要考虑到不同模型对数据编码要求是不同的,因此我们需要先介绍关于机器学习中特征编码的相关内容。

离散字段的数据重编码

在上一小节中,我们对离散特征进行哑变量的变换过程其实就是一个数据重编码的过程。当然,需要注意的是,不同类型的字段由不同的编码方式,例如文本类型字段可能需要用到CountVector或TF-IDF处理、时序字段可能需要分段字典排序等,并且,不同模型对于数据编码类型要求也不一样,例如逻辑回归需要对多分类离散变量进行哑变量变换,而CatBoost则明确要求不能对离散字段字段进行哑变量变换、否则会影响模型速度和效果。因此,本部分我们先介绍较为通用的离散字段的编码方法,然后再根据后续实际模型要求,选择不同编码方式对数据进行处理。

OrdinalEncoder自然数排序 

首先是自然数排序方法,该方法的过程较为简单,即先对离散字段的不同取值进行排序,然后对其进行自然数值取值转化;对于自然数排序过程,我们可以通过简单的pandas中的列取值调整来进行,例如就像此前对标签字段取值的调整过程,此外也可以直接考虑调用sklearn中的OrdinalEncoder()评估器(转化器)。

from sklearn import preprocessing
preprocessing.OrdinalEncoder()
X1 = np.array([['F'], ['M'], ['M'], ['F']])
enc = preprocessing.OrdinalEncoder()

enc.fit(X1)
enc.transform(X1) # 进行转换 类似模型的predict方法

array([[0.],
       [1.],
       [1.],
       [0.]])

这种转化器的使用方式,也为非常便于我们执行在训练集上进行训练、在测试集上进行测试这一过程。

💥独热编码与哑变量区别:

  • 哑变量:生成的特征数量为n-1(n为原始分类变量的类别数),因为需要选择一个基准类别。
  • 独热编码:生成的特征数量为n,即每个类别都对应一个独立的特征。

OneHotEncoder独热编码

独热编码过程其实和我们此前介绍的哑变量创建过程一致(至少在sklearn中并无差别)。对于独热编码的过程,我们可以通过pd.get_dummies函数实现,也可以通过sklearn中OneHotEncoder评估器(转化器)来实现。

preprocessing.OneHotEncoder()
X1

array([['F'],
       ['M'],
       ['M'],
       ['F']], dtype='<U1')

enc = preprocessing.OneHotEncoder()
enc.fit_transform(X1).toarray()

💢同样,训练完成后的转化器会记录转化规则:

enc.categories_

[array(['F', 'M'], dtype='<U1')]
# 该排序实际上也是字典顺序
'M' > 'F'

💢并能够对新的数据依据原转化规则进行转化:

X2

# array([['M'],
         ['F']], dtype='<U1')


enc.transform(X2).toarray()

#
array([[0., 1.],
       [1., 0.]])

对于独热编码的使用,有一点是额外需要注意的,那就是对于二分类离散变量来说,独热编码往往是没有实际作用的。例如对于上述极简数据集而言,Gender的取值是能是M或者F,独热编码转化后,某行Gender_F取值为1、则Gender_M取值必然为0,反之亦然。因此很多时候我们在进行独热编码转化的时候会考虑只对多分类离散变量进行转化,而保留二分类离散变量的原始取值。此时就需要将OneHotEncoder中drop参数调整为'if_binary',以表示跳过二分类离散变量列。

X3 = pd.DataFrame({'Gender': ['F', 'M', 'M', 'F'], 'Income': ['High', 'Medium', 'High', 'Low']})
drop_enc = preprocessing.OneHotEncoder(drop='if_binary')  # 跳过二分类离散变量
drop_enc.fit_transform(X3).toarray()

drop_enc.categories_

[array(['F', 'M'], dtype=object),
 array(['High', 'Low', 'Medium'], dtype=object)]

不过需要注意的是,对于sklearn的独热编码转化器来说,尽管其使用过程会更加方便,但却无法自动创建转化后的列名称,而在需要考察字段业务背景含义的场景中,必然需要知道每一列的实际名称(就类似于极简示例中每一列的名字,通过“原列名_字段取值”来进行命名),因此我们需要定义一个函数来批量创建独热编码后新数据集各字段名称的函数。

💢首先我们先尝试围绕上述极简数据集来提取(创建)独热编码后新数据集的字段名称:

# 提取原始列名称
cate_cols = X3.columns.tolist()
cate_cols

# ['Gender', 'Income']

# 新编码字段名称存储
cate_cols_new = []

# 提取独热编码后所有特征的名称
for i, j in enumerate(cate_cols):
    if len(drop_enc.categories_[i]) == 2:
        cate_cols_new.append(j)
    else:
        for f in drop_enc.categories_[i]:
            feature_name = j + '_' + f
            cate_cols_new.append(feature_name)


# 查看新字段名称提取结果
cate_cols_new

# ['Gender', 'Income_High', 'Income_Low', 'Income_Medium']

# 组合成新的DataFrame
pd.DataFrame(drop_enc.fit_transform(X3).toarray(), columns=cate_cols_new)

💫然后将上述过程封装为一个函数:

def cate_colName(Transformer, category_cols, drop='if_binary'):
    """
    离散字段独热编码后字段名创建函数
    
    :param Transformer: 独热编码转化器
    :param category_cols: 输入转化器的离散变量
    :param drop: 独热编码转化器的drop参数
    """
    
    cate_cols_new = []
    col_value = Transformer.categories_
    
    for i, j in enumerate(category_cols):
        if (drop == 'if_binary') & (len(col_value[i]) == 2):
            cate_cols_new.append(j)
        else:
            for f in col_value[i]:
                feature_name = j + '_' + f
                cate_cols_new.append(feature_name)
    return(cate_cols_new)

测试函数效果:

cate_colName(drop_enc, cate_cols)
# ['Gender', 'Income_High', 'Income_Low', 'Income_Medium']

💯至此完整介绍独热编码相关功能与数据集列名称提取函数的使用方法。

ColumnTransformer转化流水线

在执行单独的转化器时,我们需要单独将要转化的列提取出来,然后对其转化,并且在转化完成后再和其他列拼接成新的数据集。尽管很多时候表格的拆分和拼接不可避免,但该过程显然不够“自动化”。在sklearn的0.20版本中,加入了ColumnTransformer转化流水线评估器,使得上述情况得以改善。该评估器和pipeline类似,能够集成多个评估器(转化器),并一次性对输入数据的不同列采用不同处理方法,并输出转化完成并且拼接完成的数据。
from sklearn.compose import ColumnTransformer

 ColumnTransformer的使用过程并不复杂,其基本说明如下:

ColumnTransformer?

其中,transformers表示集成的转化器,例如,如果我们需要对tcc数据集中的离散字段进行多分类独热编码,则需要输入这样一个转化器参数:

('cat', preprocessing.OneHotEncoder(drop='if_binary'), category_cols)

当然,ColumnTransformer可以集成多个转化器,即可以在一个转化流水线中说明对所有字段的处理方法。例如上述转化器参数只说明了需要对数据集中所有category_cols字段进行OneHotEncoder(drop='if_binary')转化,而对于tcc数据集来说,还有numeric_cols,也就是连续性字段,当然我们其实目前并不需要对这些连续型字段进行处理,但仍然不妨输入一个处理连续型字段的转化器参数(原因稍后解释),该参数可以写成如下形式:

('num', 'passthrough', numeric_cols)

如果需要对连续变量进行处理,如需要对其进行归一化或者分箱,则将'passthrough'cabs关于改为对应转化器。

preprocess_col = ColumnTransformer([
    ('cat', preprocessing.OneHotEncoder(drop='if_binary'), category_cols), 
    ('num', 'passthrough', numeric_cols)
])

而此时preprocess_col则表示对数据集的离散变量进行多分类独热编码处理,对连续变量不处理。如果从效果上看,preprocess_col和我们单独使用多分类独热编码处理离散变量过程并无区别,但实际上我们更推荐使用preprocess_col来进行处理,原因主要有以下几点:其一,通过preprocess_col处理后的数据集无需再进行拼接工作,preprocess_col能够直接输出离散变量独热编码+连续变量保持不变的数据集;其二,preprocess_col过程还能够对未选择的字段进行删除或者保留、或者统一再使用某种转化器来进行转化(默认是删除其他所有列),通过remainder参数来进行说明。例如,我们现在可以借助preprocess_col直接对tcc数据集进行离散变量独热编码、连续变量保留、以及剔除ID列和标签列的操作:

# 训练转化器
preprocess_col.fit(tcc)
#
ColumnTransformer(transformers=[('cat', OneHotEncoder(drop='if_binary'),
                                 ['gender', 'SeniorCitizen', 'Partner',
                                  'Dependents', 'PhoneService', 'MultipleLines',
                                  'InternetService', 'OnlineSecurity',
                                  'OnlineBackup', 'DeviceProtection',
                                  'TechSupport', 'StreamingTV',
                                  'StreamingMovies', 'Contract',
                                  'PaperlessBilling', 'PaymentMethod']),
                                ('num', 'passthrough',
                                 ['tenure', 'MonthlyCharges', 'TotalCharges'])])

# 输出转化结果
pd.DataFrame(preprocess_col.transform(tcc))

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/763898.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

11集在Docker上编译tensorFlow Lite MCU例子工程-《MCU嵌入式AI开发笔记》

【11集在Docker上编译tensorFlow Lite MCU例子工程-《MCU嵌入式AI开发笔记》】 这一集咱们一步一步的在doc下面编译TensorFlow Lite的例程 https://tensorflow.google.cn/lite/tutorials?hlzh-cn 进入这个例子&#xff1a; https://codelabs.developers.google.cn/codelabs/…

Python学习笔记六

1.实现4*4随机矩阵 #生成一个随机4*4的数组 import numpy as np np.random.seed(1)#固定随机数 每次都是同一个 &#xff08;&#xff09;里面的数字不同 对应的随机数也不同 np.random.rand() anp.random.randint(0,100,16).reshape(4,4)#0~100的随机整数 包含16个元素 pri…

Java学习 (六) 面向对象--this、继承、方法重写、super

一、this 关键字 1、this 演示 vi Person.java public class Person {String name;int age;//显示声明构造器public Person(String s , int i){name s;age i;}public void setAge(int age){age age;}}vi PersonTest.java public class PersonTest {public static void m…

FuTalk设计周刊-Vol.063

#AI漫谈 热点捕手 1.设计师必看&#xff01;GPTs让你的创意飞起来&#xff01; 我们将深入探讨什么是GPTs、其强大功能和独特优势&#xff0c;以及一些值得推荐的GPT应用和获取途径。 链接https://mp.weixin.qq.com/s/EtVxF9XYvCu6ANFfotortA 2.Figma Config 2024 大会内容回…

考研生活day2--王道课后习题2.3.1、2.3.2、2.3.3

2.3.1 题目描述&#xff1a; 这题和曾经做过的LeetCode203.移除元素一模一样&#xff0c;所以我们就使用LeetCode进行书写&#xff0c;题目链接203. 移除链表元素 - 力扣&#xff08;LeetCode&#xff09; 解题思路 大家的第一反应肯定是根据书上所学的书写方法一样书写&…

为什么这几年参加PMP考试的人越来越多

参加PMP认证的人越来越多的原因我认为和社会发展、职场竞争、个人提升等等方面有着不小的关系。国际认证与国内认证的性质、发展途径会有一些区别&#xff0c;PMP引进到中国二十余年&#xff0c;报考人数持增长状态也是正常的。 具体可以从下面这几个点来展开论述。 市场竞争…

【技术追踪】SegGuidedDiff:基于分割引导扩散模型实现解剖学可控的医学图像生成(MICCAI-2024)

它来了它来了&#xff0c;它带着 mask 做生成了~ SegGuidedDiff&#xff1a;提出一种用于解剖学可控医学图像生成的扩散模型&#xff0c;在每个采样步骤都遵循多类解剖分割掩码并结合了随机掩码消融训练算法&#xff0c;可助力乳房 MRI 和 腹部/颈部到骨盆 CT 等任务涨点。 论文…

python中的包和模块

目录 一、包与模块 二、第三方包的安装 2.1 pip install 2.2使用 curl 管道 2.3其他安装方法 三、导入单元的构成 3.1pip的使用 四、模块的缓存 一、包与模块 Python 中除了函数库以外&#xff0c;还有非常多且优秀的第三方库、包、模块。 模块Module&#xff1a;以…

LangChain 开发智能Agent,你学会了吗?

Prompt Enginnering 是打开LLM宝库的一把金钥匙&#xff0c;如果prompt得法&#xff0c;并能将其技巧与某项工作深度结合&#xff0c;那必将大大增效。今天我们来聊聊如何优化Prompt设计、Prompt Template管理等技术和体力活&#xff0c;并赋能老喻干货店的营销活动。 LLM Pro…

基于机器学习的零售商品销售数据预测系统

1 项目介绍 1.1 研究目的和意义 在电子商务日益繁荣的今天&#xff0c;精准预测商品销售数据成为商家提升运营效率、优化库存管理以及制定营销策略的关键。为此&#xff0c;开发了一个基于深度学习的商品销售数据预测系统&#xff0c;该系统利用Python编程语言与Django框架&a…

Java服务器代码远程调试(IDEA版)

Java服务器代码远程调试 配置启动脚本参数配置IDEA远程调试工具操作步骤 注意&#xff1a;远程调试的代码需要与本地代码一致&#xff0c;远程调试目的是解决本地环境无法支持调试的情况下&#xff0c;解决线上&#xff08;测试&#xff09;环境调试问题。 配置启动脚本参数 n…

昇思25天学习打卡营第10天|linchenfengxue

基于MobileNetv2的垃圾分类 通过读取本地图像数据作为输入&#xff0c;对图像中的垃圾物体进行检测&#xff0c;并且将检测结果图片保存到文件中。 MobileNetv2模型原理介绍 MobileNet网络是由Google团队于2017年提出的专注于移动端、嵌入式或IoT设备的轻量级CNN网络&#x…

TikTok直播限流与网络的关系及解决方法

TikTok作为一款热门的社交平台&#xff0c;其直播功能吸引了大量用户。然而&#xff0c;一些用户可能会遇到TikTok直播限流的问题&#xff0c;例如直播过程中出现播放量低、直播画面质量差等情况。那么&#xff0c;TikTok直播限流与所使用的网络线路是否有关系&#xff1f;是否…

TypeScript Project References npm 包构建小实践

npm 包输出 es/cjs 产物 在开发一个 npm 包时&#xff0c;通常需要同时输出 ES 模块和 CommonJS 模块的产物供不同的构建进行使用。在只使用tsc进行产物编译的情况下&#xff0c;我们通常可以通过配置两个独立的 tsconfig.json 配置文件&#xff0c;并在一个 npm script 中 执…

typescript学习回顾(五)

今天来分享一下ts的泛型&#xff0c;最后来做一个练习 泛型 有时候&#xff0c;我们在书写某些函数的时候&#xff0c;会丢失一些类型信息&#xff0c;比如我下面有一个例子&#xff0c;我想提取一个数组的某个索引之前的所有数据 function getArraySomeData(newArr, n:numb…

Mouse Prealbumin ELISA Kit小鼠前白蛋白ELISA试剂盒

前白蛋白&#xff08;PRE&#xff09;是一种由4条相同的多肽链组成的四聚体蛋白。电泳时&#xff0c;它比血清白蛋白的迁移速度更快&#xff0c;PRE可以作为多种疾病患者营养评价的标志物。ICL的Mouse Prealbumin ELISA Kit应用双抗体夹心法测定小鼠样本中前白蛋白水平&#xf…

CentOS7源码安装nginx并编写服务脚本

华子目录 准备下载nginx源码包关闭防火墙关闭selinux安装依赖环境 解压编译安装测试编写服务脚本&#xff0c;通过systemctl实现服务启动与关闭测试 准备 下载nginx源码包 在源码安装前&#xff0c;我们得先下载nginx源码包https://nginx.org/download/这里我下载的是nginx-1…

《梦醒蝶飞:释放Excel函数与公式的力量》8.2 COUNTA函数

8.2 COUNTA函数 COUNTA函数是Excel中用于统计指定区域内所有非空单元格数量的函数。它能够统计数值、文本、错误值以及公式返回的结果&#xff0c;是数据分析中常用的统计工具。 8.2.1 函数简介 COUNTA函数用于统计指定区域中所有非空单元格的数量。它与COUNT函数不同&#…

transformer——多变量预测PyTorch搭建Transformer实现多变量多步长时间序列预测(负荷预测)——transformer多变量预测

写在最前&#xff1a; 在系统地学习了Transformer结构后&#xff0c;尝试使用Transformer模型对DNA序列数据实现二分类&#xff0c;好久前就完成了这个实验&#xff0c;一直拖着没有整理&#xff0c;今天系统的记录一下&#xff0c;顺便记录一下自己踩过的坑 &#xff08;需要…

OpenHarmony开发实战:GPIO控制器接口

功能简介 GPIO&#xff08;General-purpose input/output&#xff09;即通用型输入输出。通常&#xff0c;GPIO控制器通过分组的方式管理所有GPIO管脚&#xff0c;每组GPIO有一个或多个寄存器与之关联&#xff0c;通过读写寄存器完成对GPIO管脚的操作。 GPIO接口定义了操作GP…