为何循环中输出的Precision、Recall、F1值全部为1?
Bootstrap循环导致分类指标全为1的问题排查
问题现象
运行包含循环的bootstrap函数时,生成的DataFrame中每一行的Precision、Recall、F1值均为1;移除循环后,程序能输出合理的指标数据。
代码示例
def bootstrap(x, Nboot): x = np.array(x) models = [] resampled_stat = [] precision = [] recall = [] f1 = [] numb_rows = len(data) for k in range(Nboot): chosen_rows = np.random.choice(numb_rows, replace=True, size=numb_rows) bootstrap_sample = data.iloc[chosen_rows] resampled_stat.append(bootstrap_sample) X_train, X_test, Y_train, Y_test = train_test_split(x, y, test_size = 0.2, random_state = 1) model = tree.DecisionTreeClassifier().fit(X_train, Y_train) models.append(model) y_pred = model.predict(X_test) precision.append(metrics.precision_score(Y_test, y_pred, average="macro")) recall.append(metrics.recall_score(Y_test, y_pred, average="macro")) f1.append(metrics.f1_score(Y_test, y_pred, average="macro")) pred_df = pd.DataFrame( { "Precision": precision, "Recall": recall, "F1": f1, "Models": models, }) return pred_df
错误原因分析
- Bootstrap采样数据未被使用:循环内生成了重采样后的
bootstrap_sample,但后续训练完全没用到这个数据集,依旧使用全局的x和y,等于循环只是重复执行同一套训练流程,没有实现Bootstrap的核心逻辑。 - 固定随机种子导致拆分完全一致:
train_test_split设置了random_state=1,每次循环都会得到完全相同的训练集和测试集。如果这个固定拆分下模型能100%预测正确(比如数据集简单、模型过拟合训练集),就会所有指标都为1。 - 全局变量依赖问题:函数直接使用全局的
data和y,没有通过参数传入,既破坏了函数封装性,还可能导致采样数据与训练数据不匹配。
修正方案
调整代码,确保每次循环用Bootstrap采样后的数据集训练,并优化随机种子设置:
def bootstrap(data, Nboot): # 假设data包含特征和标签,标签列名为'y',可根据实际情况调整 models = [] resampled_stat = [] precision = [] recall = [] f1 = [] numb_rows = len(data) for k in range(Nboot): chosen_rows = np.random.choice(numb_rows, replace=True, size=numb_rows) bootstrap_sample = data.iloc[chosen_rows] resampled_stat.append(bootstrap_sample) # 从采样数据中提取特征和标签 X = bootstrap_sample.drop('y', axis=1) y = bootstrap_sample['y'] # 用循环变量k作为随机种子,保证每次拆分不同 X_train, X_test, Y_train, Y_test = train_test_split(X, y, test_size=0.2, random_state=k) model = tree.DecisionTreeClassifier().fit(X_train, Y_train) models.append(model) y_pred = model.predict(X_test) precision.append(metrics.precision_score(Y_test, y_pred, average="macro")) recall.append(metrics.recall_score(Y_test, y_pred, average="macro")) f1.append(metrics.f1_score(Y_test, y_pred, average="macro")) pred_df = pd.DataFrame( { "Precision": precision, "Recall": recall, "F1": f1, "Models": models, }) return pred_df
关键修改点:
- 将
data作为参数传入函数,消除全局变量依赖 - 从
bootstrap_sample中提取特征和标签,确保训练使用重采样后的数据集 - 把
random_state设为循环变量k,保证每次循环的训练测试拆分不同,符合Bootstrap的随机性要求
内容的提问来源于stack exchange,提问作者tommy
相关产品推荐
相关产品推荐

