特征工程——离散化与分箱

数据表示的最佳方法不仅取决于数据的语义,还取决于所使用的模型种类。线性模型与基于树的模型(比如决策树梯度提升树随机森林)是两种成员很多同时有非常常用的模型,它们在处理不同的特征表示时就具有非常不同的性质。我们先用线性模型和决策树来训练一个数据集。

PS:线性模型决策树模型之前都已经讲解过了,感兴趣的可以去点击相关链接看一下,这里就不再赘述了。

训练模型

1.数据来源

第一人称fps游戏csgo的等分数据:https://www.kaggle.com/sp1nalcord/mycsgo-data
在这里插入图片描述

csgo是一款第一人称的射击游戏,该数据包括每位玩家的网络延迟(ping),击杀数量,死亡数量,得分情况等等。
嘿嘿,游戏这方面我还是比较了解的,这也是博主唯一一个不用看原版数据的英文介绍,就能看懂各个维度的数据集了。

2.读取文件

import pandas as pd
import winreg
real_address = winreg.OpenKey(winreg.HKEY_CURRENT_USER,r'Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders',)
file_address=winreg.QueryValueEx(real_address, "Desktop")[0]
file_address+='\\'
file_origin=file_address+"\\源数据-分析\\model_data.csv"
csgo=pd.read_csv(file_origin)#https://www.kaggle.com/sp1nalcord/mycsgo-data

因为之前每次下载数据之后都要将文件转移到python根目录里面,或者到下载文件夹里面去读取,很麻烦。所以我通过winreg库,来设立绝对桌面路径,这样只要把数据下载到桌面上,或者粘到桌面上的特定文件夹里面去读取就好了,不会跟其它数据搞混。
其实到这一步都是在走流程,基本上每个数据挖掘都要来一遍,没什么好说的。

3.清洗数据
在这里插入图片描述
可以看到这个数据并不包括缺失值,而且各个特征值之间也没有属性重叠的状况,所以暂时不需要任何处理。

4.建模

import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeRegressor#决策树
from sklearn.linear_model import LinearRegression#线性模型
from sklearn.metrics import r2_score
X_train,X_test,y_train,y_test=train_test_split(csgo[["Ping","Kills","Assists","Deaths","MVP","HSP"]],csgo["Score"],random_state=1)
LR=LinearRegression()
LR.fit(X_train,y_train)
prediction=LR.predict(X_test)
print("线性模型评分:"+str(r2_score(y_test,prediction)))
tree=DecisionTreeRegressor(min_samples_split=300)
tree_prediction=tree.fit(X_train,y_train).predict(X_test)
print("决策树模型评分:"+str(r2_score(y_test,tree_prediction)))

结果如下所示:
在这里插入图片描述

分箱

正如大家所知,线性模型只能针对线性关系建模,对于单个特征的情况就是直线。决策树可以构建更为复杂的数据模型,但这强烈依赖于数据表示。有一种方法可以让线性模型在持续数据上变得更为强大。就是使用特征分离(也叫离散化)将其划分为多个特征。

我们假设将特征的输入范围(在上面的数据集中,我们只考虑kills特征)划分为固定个数的箱子,比如9个,那么数据点就可以用它所在的箱子来表示。为了确定这一点,我们首先需要定义箱子。在上面的数据集中,我们依据kills特征中的最大值和最小值,即在-4到64之间定义9个均匀分布的箱子。我们用np.linspace函数创建9个箱子,即两个连续边界之间的空间:
在这里插入图片描述
这里第一个箱子包含特征值在-4到3.56之间的所有数据点,第二个箱子包含特征值在3.56

接下来,我们记录每个数据点所属的箱子。这可以用np.digitize函数轻松计算出来:
在这里插入图片描述
我们在这里做的是将数据集中的连续输入特征(kills)变换为一个分类特征,用于表示数据点所在的箱子。要想在这个数据上使用scikit-learn模型,我们利用pd.get_dummies将这个离散特征变换为独热编码。

PS:独热编码的内容我之前也已经说过了,感兴趣的可以去点击相关链接看一下,这里就不再赘述了。

在这里插入图片描述
由于我们指定了10个元素,所以变换后的特征值包含10个特征。

重新训练

接下来,我们在独热编码后的数据上构建新的线性模型和新的决策树模型:

binned=pd.concat([csgo[["Ping","Kills","Assists","Deaths","MVP","HSP"]],kills_dummies],axis=1,ignore_index=False)###合并两个dataframe
X_train,X_test,y_train,y_test=train_test_split(binned,csgo["Score"],random_state=1)
LR=LinearRegression()
LR.fit(X_train,y_train)
prediction=LR.predict(X_test)
print("线性模型评分:"+str(r2_score(y_test,prediction)))
tree=DecisionTreeRegressor(min_samples_split=300)
tree_prediction=tree.fit(X_train,y_train).predict(X_test)
print("决策树模型评分:"+str(r2_score(y_test,tree_prediction)))

在这里插入图片描述
可以看出,线性模型的精度较之前有所上升(数据集越不适用于线性模型,分箱效果越好。),而决策树模型的评分较之前没有变化。对于每个箱子,二者都预测一个常数值。因为每个箱子内的特征是不变的,所以对于一个箱子内的所有点,任何模型都会预测相同的值。比较对特征进行分箱前后模型学到的内容,我们发现,线性模型变得更加灵活了,因为现在它对每个箱子具有不同的取值,而决策树模型灵活性降低了。分箱特征对基于树的模型通常不会产生更好的效果,因为这种模型可以学习在任何位置划分数据。从某种意义上来看,决策树可以学习如何分箱对预测这些数据最为有用。此外,决策树同时查看多个特征,而分箱通常针对的单个特征值。不过,线性模型的表现力在数据变换后得到了极大的提高。

对于特定的数据集,如果有充分的理由使用线性模型——比如数据集很大,维度很高,但有些特征与输出的关系是非线性的——那么分箱是提高建模能力的好方法。

个人博客:https://www.yyb705.com/
欢迎大家来我的个人博客逛一逛,里面不仅有技术文,也有系列书籍的内化笔记。
有很多地方做的不是很好,欢迎网友来提出建议,也希望可以遇到些朋友来一起交流讨论。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值