XGBoost,二元分类:每个用户的观察次数奇数

数据挖掘 机器学习 Python 分类 数据集 xgboost
2021-10-08 06:57:08

我正在使用 XGBoost 解决二进制分类问题,并且我有一个数据集,每个用户的观察次数不均匀。对于某些用户,有超过 100 个观察值,而对于某些用户,只有少数几个。“USER_ID”功能不用作 XGBoost 的输入。

更具体地说,我正在尝试对睡眠质量方面的用户身体活动(从可穿戴追踪器收集的数据)进行建模,其中一些变量是人口统计特征,例如年龄和性别,以及步数、心率等。考虑到不同的从用户那里收集的数据量很大,由于观察的数量,一些用户行为(如夜班工作)在数据中的表现比其他行为更多。

在使用 XGBoost 时我应该如何考虑这一点?

USER_ID  AGE  SEX  X1  X2    ...  y
1        20   M    65  3000  ...  1
1        ...  ...  ... ...   ...  0
1        ...  ...  ... ...   ...  1
2        30   F    80  2500  ...  0
2        ...  ...  ... ...   ...  1
3        40   M    77  8000  ...  0

这些类是平衡的,我能够为分类器获得良好的性能。

2个回答

您可能需要考虑一种分层交叉验证方法,在这种方法中,您专门对来自具有大量观察值的用户的数据进行过采样,或者从具有较少观察值的用户中进行过采样。

另一种可能也有效的方法是用较少的观察来复制一些用户的观察,这将平衡不同类型观察的权重。

- 添加以回答评论中的其他问题

有许多方法可以对多数人进行欠采样或对少数人进行过采样。以下是如何处理这种情况的概述(一般而言)。

要对大多数进行欠采样,只需删除每次运行中占多数的训练数据的一部分。

要对少数进行过采样,请复制您希望具有更高权重的值。

此外,还有一个用于 XGBoost (scale_pos_weight) 的参数,可让您设置不同样本的权重,请参见此处此外,您可以利用imblearn库中的 SMOTE。

所以,我最终使用了 SMOTE,但我选择的不是二进制类标签,而是“USER_ID”作为 SMOTE 的标签。结果看起来很有希望,数据的描述性统计几乎保持不变,分类器的性能也有所提高。

请注意,在我的分类问题中,我使用某些切点从连续变量创建了二进制目标,因此此时二进制目标不存在,因为我在此测试中仅使用了数字变量,但显然 SMOTE 也支持分类变量。

任何人都可以使用这种方法发现任何谬误吗?这应该在训练/测试拆分之前还是之后完成?

import pandas as pd
from imblearn.over_sampling import SMOTE

df = pd.read_csv("data.csv")
df = df.select_dtypes(include=["number"])
df["USER_ID"] = df["USER_ID"].astype(str)

X = df.drop(["USER_ID"], axis=1)
y = df["USER_ID"]

smote = SMOTE(sampling_strategy="auto", k_neighbors=5)

X_sm, y_sm = smote.fit_sample(X, y)

values = pd.DataFrame(data=X_sm, columns=X.columns)
users = pd.DataFrame(data=y_sm, columns=["USER_ID"])

sampled = pd.concat([users, values], axis=1, sort=False)