按80%/10%/10%比例拆分列表为3份的Python实现是否存在缺陷?
数据集拆分代码潜在缺陷
你的代码在样本量为10的整数倍、数据本身随机排序的场景下可以正常运行,但存在以下几个明显的潜在问题:
- 未做随机打乱,数据分布易偏移
直接按原数据顺序切分,如果原数据是按类别、时间或其他特征排序的,会导致训练集、验证集、测试集的数据分布差异极大,训练出的模型泛化能力会严重下降,甚至完全不可用。 - 比例计算存在截断误差,小数据集下偏差极大
你直接用int()截断浮点计算结果,当总样本量不是10的整数倍时,拆分比例会严重偏离预期。比如总样本量为9时,0.8*9=7.2截断为7,0.1*9=0.9截断为0,最终拆分比例为7:0:2,验证集直接为空,完全不符合10%的拆分要求。 - 无异常输入校验
如果传入空列表、不可切片的类型(如集合、生成器),代码要么返回无意义的空数据集,要么直接抛出索引错误,没有提前做合法性校验。 - 未考虑分类任务的分层抽样需求
如果是分类场景,哪怕加了随机打乱,也可能出现某类样本在验证集/测试集里完全缺失的情况,需要按标签分层抽样保证三个数据集的类别分布和原数据集一致。
优化实现示例(无第三方依赖)
import random def split_data(data, shuffle=True, train_ratio=0.8, val_ratio=0.1): total = len(data) # 输入合法性校验 if total == 0: raise ValueError("输入数据集不能为空") if abs(train_ratio + val_ratio - 0.9) > 1e-6: raise ValueError("训练集+验证集比例之和应为0.9,剩余部分为测试集") # 随机打乱(不修改原数据) if shuffle: data = data.copy() random.shuffle(data) # 计算切分点,用四舍五入减少截断误差 train_end = int(round(total * train_ratio)) val_end = train_end + int(round(total * val_ratio)) # 边界兜底,避免数据集为空 val_end = min(val_end, total - 1) train_end = min(train_end, val_end - 1) return data[:train_end], data[train_end:val_end], data[val_end:]
内容的提问来源于stack exchange,提问作者marlon
相关产品推荐
相关产品推荐

