训练和测试集分割,使每个名称和目标类别的比例在训练和测试中都存在

0 投票
1 回答
26 浏览
提问于 2025-04-12 07:53

我正在尝试解决一个机器学习的问题,想知道一个人是否会送达订单。我的数据集非常不平衡。这里是我的数据集的一部分:

[{'order_id': '1bjhtj', 'Delivery Guy': 'John', 'Target': 0},
 {'order_id': '1aec', 'Delivery Guy': 'John', 'Target': 0},
 {'order_id': '1cgfd', 'Delivery Guy': 'John', 'Target': 0},
 {'order_id': '1bceg', 'Delivery Guy': 'Tom', 'Target': 0},
 {'order_id': '1a2fg', 'Delivery Guy': 'Tom', 'Target': 0},
 {'order_id': '1cbsf', 'Delivery Guy': 'Tom', 'Target': 1},
 {'order_id': '1bc5', 'Delivery Guy': 'Jay', 'Target': 0},
 {'order_id': '1a22', 'Delivery Guy': 'Jay', 'Target': 0},
 {'order_id': '1bzc5', 'Delivery Guy': 'Jay', 'Target': 0},
 {'order_id': '1av22', 'Delivery Guy': 'Jay', 'Target': 0},
 {'order_id': '1bsc5', 'Delivery Guy': 'Jay', 'Target': 1},
 {'order_id': '1a2t2', 'Delivery Guy': 'Jay', 'Target': 0},
 {'order_id': '1bc5b', 'Delivery Guy': 'Jay', 'Target': 0},
 {'order_id': '1a22a', 'Delivery Guy': 'Mary', 'Target': 0},
 {'order_id': '1c5bv', 'Delivery Guy': 'Mary', 'Target': 0},
 {'order_id': 'vb2er', 'Delivery Guy': 'Mary', 'Target': 0},
 {'order_id': '1bs5s', 'Delivery Guy': 'Mary', 'Target': 0},
 {'order_id': '1a22n', 'Delivery Guy': 'Mary', 'Target': 0},
 {'order_id': '122a', 'Delivery Guy': 'James', 'Target': 1},
 {'order_id': '1cw5bv', 'Delivery Guy': 'James', 'Target': 0},
 {'order_id': 'vb=er', 'Delivery Guy': 'James', 'Target': 0},
 {'order_id': '1b5s', 'Delivery Guy': 'James', 'Target': 0},
 {'order_id': '1a2n', 'Delivery Guy': 'James', 'Target': 1}]


这是我的表格:

| order_id | Delivery Guy | Target |
|----------|--------------|--------|
| 1bjhtj   | John         | 0      |
| 1aec     | John         | 0      |
| 1cgfd    | John         | 0      |
| 1bceg    | Tom          | 0      |
| 1a2fg    | Tom          | 0      |
| 1cbsf    | Tom          | 1      |
| 1bc5     | Jay          | 0      |
| 1a22     | Jay          | 0      |
| 1bzc5    | Jay          | 0      |
| 1av22    | Jay          | 0      |
| 1bsc5    | Jay          | 1      |
| 1a2t2    | Jay          | 0      |
| 1bc5b    | Jay          | 0      |
| 1a22a    | Mary         | 0      |
| 1c5bv    | Mary         | 0      |
| vb2er    | Mary         | 0      |
| 1bs5s    | Mary         | 0      |
| 1a22n    | Mary         | 0      |
| 122a     | James        | 1      |
| 1cw5bv   | James        | 0      |
| vb=er    | James        | 0      |
| 1b5s     | James        | 0      |
| 1a2n     | James        | 1      |

我希望我的机器学习模型能够理解每个人的特征,并预测这两种情况:

会送达 "0" 和

不会送达 "1"

我想把训练数据和测试数据分开,但要确保保留一些人的记录和一些目标类别的记录,这样模型才能学习到所有的模式。

到目前为止,我使用了这个方法:

X = df.drop(columns = "Target")
y = df.Target
X_train,X_test,y_train,y_test=train_test_split(X,y,train_size=0.7,stratify=y)

这个方法确实给了我每个送货员的输出,但它没有解决我想把“James”分开,让一个“1”在训练集中,另一个“1”在测试集中。有没有人能帮我换个方式来解决这个问题?

1 个回答

0

这里有一个方法可以确保:

每个 "送货员" 在训练集和测试集中都有代表。每个 "目标" 类别在这两个集合中也有足够的代表。

  • 这可以通过手动划分数据集来实现,同时考虑到 "送货员" 和 "目标" 这两列。下面是一步一步的操作指南:

第一步:按 "送货员" 划分数据:

  • 首先,根据 "送货员" 划分你的数据集,以确保每个送货员的数据被分在一起。
for name, group in df.groupby('Delivery Guy'):

第二步:对每个组,进一步按 "目标" 划分

  • 对于每个 "送货员",根据 "目标" 划分他们的数据,以确保你可以单独处理每个类别的代表性。
for target, target_group in group.groupby('Target'):

第三步:分配训练/测试数据

  • 对于每个子组(即每个 "送货员" 和特定 "目标"),将一部分数据分配给训练集,其余的分配给测试集。考虑到你的数据集可能不平衡,你可能希望确保每个 "送货员" 的每个 "目标" 至少有一个实例出现在训练集和测试集中,如果可能的话。

第四步:合并数据

在将每个 "送货员" 的两个 "目标" 类别分配到这两个集合后,将这些分配合并回你的最终训练集和测试集中。

下面是如何在 Python 中实现这一点:

df = pd.DataFrame(data)

train_list = []
test_list = []

# Split the dataset by 'Delivery Guy' ensuring each one is represented in both sets
for name, group in df.groupby('Delivery Guy'):
    for target, target_group in group.groupby('Target'):
        if len(target_group) > 1:
            target_train, target_test = train_test_split(target_group, test_size=0.5, random_state=42)
            train_list.append(target_train)
            test_list.append(target_test)
        else:
            # Decide to add the single sample group to the training set
            train_list.append(target_group)

# Concatenate all the lists into DataFrames at once
train = pd.concat(train_list, ignore_index=True)
test = pd.concat(test_list, ignore_index=True)

撰写回答