训练和测试集分割,使每个名称和目标类别的比例在训练和测试中都存在
我正在尝试解决一个机器学习的问题,想知道一个人是否会送达订单。我的数据集非常不平衡。这里是我的数据集的一部分:
[{'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)