为基于树的机器学习模型构建更好的建模数据集的10个小技巧!

点击上方关注,All in AI中国

为基于树的机器学习模型构建更好的建模数据集的10个小技巧!

为了使模型更准确 - 只需对所有分类特征进行独热编码并将所有缺失值归零都可能是不够的。

假设有一个业务问题可以转换为机器学习问题,表格数据作为输入,明确定义了标签和指标(例如,用于回归问题的RMSE或用于分类问题的ROCAUC)。在数据集中,有一堆分类变量、数值变量和一些缺失值,基于树的ML模型将建立在数据集之上(决策树、随机森林或梯度增强树)。在应用ML算法之前是否有一些技巧来改进数据?

此过程可能与数据集有很大不同。但是我想指出一些适用于一系列数据集的一般原则,并解释其中的原因。基于树的ML算法的一些知识可以帮助读者更好地消化部分材料。

两个kaggle数据集将用于更好地演示一些技巧背后的思想。他们是

  1. 俄罗斯联邦储蓄银行房地产市场数据集 - train.csv「链接」
  2. 归属信用违约风险数据集 - application_train.csv「链接」

Tip#1.不要仅根据与标签的相关性选择特征

假设我们想预测一家连锁餐厅不同商店的净收入。我们会有一些变量,如城市、10英里内的其他餐馆数量、员工人数、餐厅面积......等。

假设'餐厅面积'与标签(净收入)的相关性非常小。那么在一些可能听起来不会赚大钱的农村地区有大型的餐厅,也可能在利润很可观的大城市中有一些地理位置优越的小型餐厅。

即使相关性很小,当“餐厅面积”功能与“城市”功能相结合时,也就是说,它可能仍会显示更多价值 - 较大的餐厅可以在昂贵的地区赚更多钱,但在价格较低的地区,这种趋势并不明显。使用树模型,在通过“城市”变量将数据分成两组之后,“餐厅面积”将在一些城市中显示其预测能力(这些城市是先前分割的子节点)。这是变量交互的一个示例,基于树的模型很擅长捕获这些交互。

仅使用与标签的相关性来评估特征重要性就像说变量交互根本不重要一样。

Tip#2.在合理的设置中输入缺失值

对于在基于树的模型中拆分的每个节点,仅使用一个特征和一个阈值。比如说要预测一个人患有糖尿病的可能性,条件'年龄<60'用于分裂节点,然后将年轻人和老年人分成两组。

如果人的年龄信息缺失,并被估算为0,那么年轻人和没有年龄信息的人将被放入同一组,这是没有意义的。在这种情况下,将年龄缺失信息归为平均值可能是更好的选择,或者对于某些基于树的算法(如XGBoost或LightGBM)来说是一个好的选择,我们可以在那里留下缺失值并让算法决定在每个节点中做什么分裂。

让我举一个家庭信用违约风险数据集的例子,目标是预测客户是否能够偿还贷款。在所有功能中,有3个感兴趣的功能,EXT_SOURCE_1,EXT_SOURCE_2,EXT_SOURCE_3,表示来自外部数据资源的信用评分,分数范围从0.0到1.0。在此数据集中,将缺失值计算为0意味着为这些记录分配最低分数,这其实是比较荒谬的。

Tip#3.正确编码顺序变量

对于序数分类变量,当我们在树模型中执行节点分割时,在许多情况下,将组中较高级别的记录分组,会比将较低级别的记录分组到另一组中会更有意义。

例如,为了预测一些综合因素是否会导致癌症,我们有来自实验室老鼠的经验数据。其中一个变量是“糖摄入量”,水平“高”、“中”、“低”,我们可以更好地将它们编码为2,1,0(或0,1,2),但这不是基于每个水平的数据量。

(Spark ML用户的提示:当您使用StringIndexers时,变量仅根据数据量进行编码,这对于树模型是不推荐的。)

Tip#4.仔细编码分类变量

如果分类变量是有序的,那么读者可以按照Tip#3对它们进行编码。如果没有,那么有两种常见的方法来编码分类变量:

  1. 将它们替换为每个类别中的平均值(回归或0,1分类)
  2. 独热编码

但是当分类变量中存在太多不同的值时,它们不能很好地工作。对于方法1,模型可能过度拟合。对于方法2,训练数据可能太大,并且每个单热编码特征可能具有非常弱的预测能力(在这种情况下需要仔细选择特征)。所以将它们进一步分组可能是一个好主意(最好用足够的领域知识来做)。

Tip#5.用常识来纠正部分数据

让我以俄罗斯联邦储蓄银行(Sberbank)俄罗斯住房市场数据中的一些特征为例。

[1]'build year'包含0、1、2或甚至值> 3000的值。

[2]'kitch_sq'>'life_sq'。这意味着厨房面积>房屋面积?

[3]'floor'>'max_floor'。在一个10层的公寓里说,它位于15楼?

...

错误的值需要替换为空值。 (或者,如果数据量很大,您可以考虑删除这些记录)

Tip#6.拆分具有不同结构的数据

让我再次以俄罗斯联邦储蓄银行(Sberbank)的俄罗斯房地产市场数据为例。如果你做

train = pd.read_csv('train.csv')
train[(train['product_type'] == 'Investment') &
 (train['price_doc'] >= 4000000)& 
 (train['price_doc'] <= 5000000)]['price_doc'].hist(bins=80)

然后用'OwnerOccupier'替换上面代码中的'Investment',你会发现这些发布看起来很不一样:

为基于树的机器学习模型构建更好的建模数据集的10个小技巧!

为基于树的机器学习模型构建更好的建模数据集的10个小技巧!

这只是一个指示器,显示两个数据集具有非常不同的结构。实际上,如果您根据'product_type'将数据集拆分为两个不同的数据集,您会发现模型的准确性得到了提高。

对于树模型,执行此操作就像使用条件'product_type = Investment'拆分根节点一样。

有时你的模型可以从这个技巧中受益,有时候不会(因为数据大小减少)。所以要仔细使用这个技巧。

Tip#7.处理高度相关的变量

如果有几个变量高度相互关联,以下是一些建议。

[1]如果您想要更好的可解释性和更少的模型训练时间(但牺牲一点模型精度),您可以选择具有最高特征重要性的那个并丢弃其他的。

[2]在进行特征选择时,这些相关变量可能会提供大量信息,但是由于它们是相似的,因此可能会发生每个单独的特征具有较低的特征重要性。因此,在发生这种情况时要小心选择特性。

[3]逻辑回归将受到多重共线性影响,但不受树模型的影响。如果您只是在模型中保留所有相关功能,那么它不会受到太大伤害。

Tip#8.确保您构建模型的行确实是真正不同的

数据集中的多个记录实际上可以引用相同的记录。假设当我们在每个人身上建立模型时,我们使用“名称”为每个人分配一个ID,这可能会导致两种类型的错误,具有相同名称的不同人被视为同一个人,或者同一个人有不同的记录(John Smith / John A. Smith)的数据。 DOB / SSN可能存在其他问题。

Tip#9.检测来自奇怪变量分布的数据问题

假设我们想使用患者数据构建模型,并且我们从不同的数据资源(例如,不同的医院)收集数据。然后我们发现,对于医院X,患者的平均医疗费用远低于其他医院。我们对结果感到困惑,因此我们深入研究数据集,并发现存在记录链接问题 - 医院X的大量记录应该组合在一个较小的集合中,包含更少的患者。

这只是一个简单的例子。当您在数据中看到奇怪的统计数据时,请持怀疑态度。

Tip#10.建模需要多少数据?

让我解释为什么很难找到一个好的答案。

假设我们想预测2019年A市的房价。在我们的训练数据集中,我们只有标签(房价)。如果我们假设所有记录都是独立收集的,从整个人口中以相同的概率随机抽取,那么简单地取房价的平均值(y1 + ... + y_n)/ n就可以最小化测试集的RMSE。

但实际上,上述假设不成立,样本不会是id(独立且相同分布),置信区间的计算不会非常精确,我们的数据集中也会有很多其他特征,我们的树模型将比上面的估算器更加复杂,并且每个记录的模型预测也不会是id。

要点:首先要弄清楚数据。不要指望在收集之前可以找到适当数量的数据。

为基于树的机器学习模型构建更好的建模数据集的10个小技巧!

编译出品

相关推荐