import pandas as pd
import xgboost as xgb
from sklearn.model_selection import KFold
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error
from skopt import BayesSearchCV
from skopt.space import Real, Integer
from sklearn.metrics import r2_score
import numpy as np
import os
# 限制 xgboost 或其它库使用的最大线程数
os.environ['OMP_NUM_THREADS'] = '8'
os.environ['MKL_NUM_THREADS'] = '8'
# 加载数据
file_path = '/bigdat2/user/zhangj/FI/00_cox/02_IDP/pub/IDP_FI_overlap.csv'
data = pd.read_csv(file_path)
# 假设数据中的 'age' 列是目标变量
exclude_columns = ['eid', 'age', 'sex', 'fi']
X = data.drop(columns=exclude_columns)
y = data['age'] # 目标变量
# 标准化特征
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
rng = np.random.RandomState(123)
kf = KFold(n_splits=5, shuffle=True, random_state=rng)
# 定义超参数搜索空间
param_space = {
'learning_rate': Real(0.01, 0.3, prior='uniform'), # 学习率范围
'max_depth': Integer(3, 8), # 树的最大深度
'n_estimators': Integer(50, 400), # 基学习器数目
'subsample': Real(0.6, 1.0, prior='uniform'), # 训练时使用的子样本比例
'colsample_bytree': Real(0.6, 1.0, prior='uniform'), # 特征选择比例
'gamma': Real(0.0, 1.0, prior='uniform'), # 最小化损失函数
'lambda': Real(0.0, 5.0, prior='uniform'), # L2正则化项,避免过拟合
'alpha': Real(0.0, 5.0, prior='uniform'), # L1正则化项,用于特征选择
}
# 保存所有预测结果
all_true_values = []
all_pred_values = []
# 使用 KFold 进行交叉验证
for fold, (train_index, test_index) in enumerate(kf.split(X_scaled)):
X_train, X_test = X_scaled[train_index], X_scaled[test_index]
y_train, y_test = y[train_index], y[test_index]
# 创建 XGBoost 回归器
xgb_model = xgb.XGBRegressor(objective='reg:squarederror', eval_metric='rmse', n_jobs=2)
# 创建贝叶斯优化器
opt = BayesSearchCV(
xgb_model,
param_space,
n_iter=30, # 尝试的不同参数组合数目
cv=5, # 五折交叉验证
scoring='neg_root_mean_squared_error', # 用RMSE评分
n_jobs=8,
verbose=1, # 显示进度
)
# 执行贝叶斯优化调参
opt.fit(X_train, y_train)
# 输出最佳超参数
print(f"Best parameters found for fold {fold}: ", opt.best_params_)
# 输出交叉验证得分
print(f"Best cross-validation score for fold {fold}: ", opt.best_score_)
# 使用最优参数创建最终模型
best_model = opt.best_estimator_
# 训练最终模型
best_model.fit(X_train, y_train)
# 预测
y_test_pre = best_model.predict(X_test)
# 保存每折的预测结果
fold_predictions = pd.DataFrame({
'eid': data['eid'].iloc[test_index],
'y_true': y_test,
'y_pred': y_test_pre
})
fold_predictions.to_csv(f"/bigdat2/user/zhangj/FI/00_cox/02_IDP/pub/fold_{fold}_predictions.csv", index=False)
# 更新所有真实值和预测值
all_true_values.extend(y_test)
all_pred_values.extend(y_test_pre)
# 计算均方误差
mse = mean_squared_error(y_test, y_test_pre)
rmse = mse ** 0.5
print(f'Final Model RMSE for fold {fold}: {rmse}')
# 计算 R² 分数
r2 = r2_score(y_test, y_test_pre)
print(f'Final Model R² for fold {fold}: {r2}')
# 计算 Pearson 相关系数
pcc = np.corrcoef(y_test, y_test_pre)[0, 1]
print(f"Final Model PCC for fold {fold}: {pcc}")
# 计算所有数据的 Pearson 相关系数
all_true_values = np.array(all_true_values)
all_pred_values = np.array(all_pred_values)
overall_pcc = np.corrcoef(all_true_values, all_pred_values)[0, 1]
# 计算所有数据的 R²
overall_r2 = r2_score(all_true_values, all_pred_values)
# 打印所有数据的 Pearson 相关系数和 R²
print(f"Overall Pearson Correlation Coefficient (PCC): {overall_pcc}")
print(f"Overall R²: {overall_r2}")
# 合并所有折的预测结果
predictions_df = pd.DataFrame({
'eid': data['eid'],
'y_true': all_true_values,
'y_pred': all_pred_values
})
# 保存合并后的预测结果到 CSV 文件
output_path = '/bigdat2/user/zhangj/FI/00_cox/02_IDP/pub/IDP_FI_overlap_age_new.csv'
predictions_df.to_csv(output_path, index=False)
print(f'Predictions saved to {output_path}')