XGBoost结合Bootstrap训练遇OSError内存访问违规求助
之前用XGBoost分类器训练模型一切正常,现在用Bootstrap方法对数据集做随机抽样(拆分训练/测试集后生成50份样本),再次训练时触发错误:
OSError: exception: access violation reading 0x0000000000000008
错误出现在model.fit()代码行,单独在循环外运行模型正常,用Bootstrap循环就报错。相关代码如下:
# Read each file and do analysis for i in range(50): # read train and test data train_data = pd.read_csv(train_path + "\\" + "train" + str(i) + ".csv") test_data = pd.read_csv(test_path + "\\" + "test" + str(i) + ".csv") # Covert gender to binary train_data['gender'] = train_data['gender'].map({1:1, 2:0}) test_data['gender'] = test_data['gender'].map({1:1, 2:0}) # Apply standard scalar to numerical columns sc = StandardScaler() train_data[['age', 'RXDCOUNT', 'income', 'RXDDAYS', 'ALQ130', 'OCD270', 'BMXBMI', 'BMXHT', 'BMXWT']] = sc.fit_transform(train_data[['age', 'RXDCOUNT', 'income', 'RXDDAYS', 'ALQ130', 'OCD270', 'BMXBMI', 'BMXHT', 'BMXWT']]) test_data[['age', 'RXDCOUNT', 'income', 'RXDDAYS', 'ALQ130', 'OCD270', 'BMXBMI', 'BMXHT', 'BMXWT']] = sc.fit_transform(test_data[['age', 'RXDCOUNT', 'income', 'RXDDAYS', 'ALQ130', 'OCD270', 'BMXBMI', 'BMXHT', 'BMXWT']]) # Create X_train, X_test, y_train, y_test y_train = train_data["depression"] y_test = test_data["depression"] X_train = train_data.drop("depression", axis=1, inplace=True) X_test = test_data.drop("depression", axis=1, inplace=True) #print(y_train) # Create model model = XGBClassifier(use_label_encoder=False) # Fit model with train data _= model.fit(X_train, y_train) # Predict on test set y_pred = model.predict(X_test) # Get accuracy of model acc = model.score(X_test, y_test) # get balanced accuracy balAcc = balanced_accuracy_score(y_test, y_pred) # roc_auc roc_auc = roc_auc_score(y_true=y_test,y_score=model.predict_proba(X_test)[:,1]) # add y_pred to test set predict_dataframe = prediction_dataframe(test_data, y_pred) # define protected attributes. p_attr1 = "gender" p_attr2 = "ethnicity" # compute TP, FP, TN, FN based on single protected attributes tp, fp, tn, fn = compute_metrics_s(predict_dataframe, p_attr1) # compute TPR based on single protected attributes tpr_male = list(tp.values())[0] / np.add(list(tp.values())[0], list(fn.values())[0]) tpr_female = list(tp.values())[1] / np.add(list(tp.values())[1], list(fn.values())[1]) EOD = np.subtract(tpr_male, tpr_female) dic_data["roc_auc"].append(roc_auc) dic_data["bacc"].append(balAcc) dic_data["EOD"].append(EOD) dic_data["tpr_male"].append(tpr_male) dic_data["tpr_female"].append(tpr_female) i += 1 if i == 49: df = pd.DataFrame.from_dict(dic_data) df.to_csv(results\\dataframe\\suppression\\gender.csv", index=True)
1. 修正特征集赋值错误(核心问题)
代码中X_train = train_data.drop("depression", axis=1, inplace=True)这一行,inplace=True会让drop方法直接修改原DataFrame并返回None,导致X_train和X_test都是None,传入model.fit()时触发内存访问错误。
修改为:
X_train = train_data.drop("depression", axis=1) X_test = test_data.drop("depression", axis=1)
如果需要保留原DataFrame不变,就不要用inplace=True;如果要用inplace=True,则不需要赋值,直接执行train_data.drop("depression", axis=1, inplace=True),之后X_train = train_data。
2. 修正StandardScaler的使用逻辑
测试集应该使用训练集拟合的Scaler做转换,避免数据泄露,同时提升结果一致性:
sc = StandardScaler() # 训练集fit_transform train_num_cols = ['age', 'RXDCOUNT', 'income', 'RXDDAYS', 'ALQ130', 'OCD270', 'BMXBMI', 'BMXHT', 'BMXWT'] train_data[train_num_cols] = sc.fit_transform(train_data[train_num_cols]) # 测试集用同一个scaler做transform test_data[train_num_cols] = sc.transform(test_data[train_num_cols])
3. 移除循环内多余的i += 1
for i in range(50)会自动迭代i的值,手动i +=1会导致i提前超出范围,最后保存结果的条件if i ==49可能无法触发。直接删除这一行即可。
4. 修正文件路径的转义问题
保存结果的路径存在缺少引号和转义错误,修改为:
df.to_csv(r"results\dataframe\suppression\gender.csv", index=True)
(用r前缀表示原始字符串,避免转义)
5. 可选:调整XGBoost的线程设置
如果上述修复后仍有内存访问问题,可能是多线程冲突导致,初始化XGBoost时指定单线程:
model = XGBClassifier(use_label_encoder=False, n_jobs=1)
内容的提问来源于stack exchange,提问作者ddq

