尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Python打卡第17天

Python打卡第17天 浙大疏锦行加载 sklearn 红酒分类数据集→ 立即按类别分层划分训练集 / 测试集核心防泄露所有后续预处理、统计、采样均只在训练集上拟合→ 训练集缺失值处理采用中位数填充特征缺失值→ 训练集异常值处理基于 IQR 法则计算上下限并裁剪异常值→ 训练集不平衡检测计算「最大类样本数 / 最小类样本数」不平衡比→ 不平衡比1.5 时触发 SMOTE 过采样仅对训练集生效测试集不参与采样→ 构建随机森林分类器超参数搜索空间共 5 个核心参数→ 设定优化目标最大化 5 折分层交叉验证的 Macro-F1 分数→ 调用 NSGA-Ⅱ 遗传算法进行多代迭代寻优 → 输出全局最优超参数组合→ 使用全部训练集拟合最优参数的完整模型→ 输入测试集完成泛化性能验证→ 输出测试集 Macro-F1、Weighted-F1、分类报告及混淆矩阵Code001002003004005006007008009010011012013014015016017018019020021022023024025026027028029030031032033034035036037038039040041042043044045046047048049050051052053054055056057058059060061062063064065066067068069070071072073074075076077078079080081082083084085086087088089090091092093094095096097098099100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184importnumpy as npimportpandas as pdfromsklearn.datasetsimportload_winefromsklearn.model_selectionimporttrain_test_split, cross_val_scorefromsklearn.ensembleimportRandomForestClassifierfromsklearn.imputeimportSimpleImputerfromsklearn.baseimportBaseEstimator, TransformerMixinfromsklearn.metricsimportf1_score, classification_report, confusion_matrixfromimblearn.over_samplingimportSMOTEfromimblearn.pipelineimportPipeline# 保证SMOTE只作用于训练集frompymoo.core.problemimportProblemfrompymoo.algorithms.moo.nsga2importNSGA2frompymoo.operators.crossover.sbximportSBXfrompymoo.operators.mutation.pmimportPMfrompymoo.optimizeimportminimizefromsklearn.model_selectionimporttrain_test_split, cross_val_score, StratifiedKFold# ------------------------------------------------------# 1. 自定义异常值裁剪器IQR法兼容sklearn管道# ------------------------------------------------------classIQROutlierClipper(BaseEstimator, TransformerMixin):基于训练集计算IQR阈值对特征进行上下限裁剪防止异常值影响def__init__(self, factor1.5):self.factorfactorself.lowerNoneself.upperNonedeffit(self, X, yNone):Q1np.percentile(X,25, axis0)Q3np.percentile(X,75, axis0)IQRQ3-Q1self.lowerQ1-self.factor*IQRself.upperQ3self.factor*IQRreturnselfdeftransform(self, X):returnnp.clip(X,self.lower,self.upper)# ------------------------------------------------------# 2. 加载数据 第一步划分训练/测试集核心防泄露# ------------------------------------------------------wineload_wine()X, ywine.data, wine.targetX_train, X_test, y_train, y_testtrain_test_split(X, y, test_size0.2, random_state42, stratifyy)print(*50)print(f训练集样本数: {X_train.shape[0]}, 测试集样本数: {X_test.shape[0]})print(f特征维度: {X_train.shape[1]})print(f类别分布(训练集): {dict(pd.Series(y_train).value_counts())})# ------------------------------------------------------# 3. 不平衡数据集检测 SMOTE采样判定# ------------------------------------------------------class_countspd.Series(y_train).value_counts()imbalance_ratioclass_counts.max()/class_counts.min()print(f\n训练集不平衡比例(最大类/最小类): {imbalance_ratio:.2f})use_smoteimbalance_ratio 1.5print(f是否启用SMOTE采样: {use_smote})# ------------------------------------------------------# 4. 定义NSGA-Ⅱ优化问题最大化交叉验证F1分数# ------------------------------------------------------classRFHyperparamOpt(Problem):def__init__(self, X_train, y_train, use_smote):# 5个超参数搜索空间实数空间整数参数在评估时取整# 0: n_estimators [50, 300] 整数# 1: max_depth [3, 20] 整数# 2: min_samples_split [2, 10] 整数# 3: min_samples_leaf [1, 10] 整数# 4: max_features [0.1, 1.0] 浮点数xlnp.array([50,3,2,1,0.1])xunp.array([300,20,10,10,1.0])super().__init__(n_var5, n_obj1, n_constr0, xlxl, xuxu)self.X_trainX_trainself.y_trainy_trainself.use_smoteuse_smoteself.cvStratifiedKFold(n_splits5, shuffleTrue, random_state42)def_build_pipeline(self, params):# 关键修复前4个参数强制转整数第5个保留浮点n_estimatorsint(round(params[0]))max_depthint(round(params[1]))min_samples_splitint(round(params[2]))min_samples_leafint(round(params[3]))max_featuresfloat(params[4])# 保持浮点steps[(imputer, SimpleImputer(strategymedian)),(outlier_clipper, IQROutlierClipper(factor1.5))]ifself.use_smote:steps.append((smote, SMOTE(random_state42)))steps.append((classifier, RandomForestClassifier(n_estimatorsn_estimators,max_depthmax_depth,min_samples_splitmin_samples_split,min_samples_leafmin_samples_leaf,max_featuresmax_features,random_state42,n_jobs1)))returnPipeline(stepssteps)def_evaluate(self, x, out,*args,**kwargs):f1_scores[]forparamsinx:pipelineself._build_pipeline(params)scorecross_val_score(pipeline,self.X_train,self.y_train,cvself.cv, scoringf1_macro, n_jobs-1).mean()f1_scores.append(-score)# pymoo默认最小化取负out[F]np.array(f1_scores).reshape(-1,1)# ------------------------------------------------------# 5. 运行NSGA-Ⅱ遗传算法寻优# ------------------------------------------------------print(\n*50)print(开始NSGA-Ⅱ超参数优化...)problemRFHyperparamOpt(X_train, y_train, use_smote)# 关键修复移除IntegerRandomSampling改用默认实数采样algorithmNSGA2(pop_size20,n_offsprings10,crossoverSBX(prob0.9, eta15),mutationPM(eta20),eliminate_duplicatesTrue)resminimize(problem,algorithm,(n_gen,30),seed42,verboseTrue)# 提取最优参数并做类型转换best_params_rawres.X.flatten()best_params{n_estimators:int(round(best_params_raw[0])),max_depth:int(round(best_params_raw[1])),min_samples_split:int(round(best_params_raw[2])),min_samples_leaf:int(round(best_params_raw[3])),max_features:round(best_params_raw[4],3)}best_f1_train-res.F[0][0]print(\n*50)print(NSGA-Ⅱ寻优结果训练集交叉验证最优)fork, vinbest_params.items():print(f {k}: {v})print(f 交叉验证macro-F1: {best_f1_train:.4f})# ------------------------------------------------------# 6. 最优参数在测试集上验证# ------------------------------------------------------best_pipelineproblem._build_pipeline(best_params_raw)best_pipeline.fit(X_train, y_train)y_predbest_pipeline.predict(X_test)test_f1_macrof1_score(y_test, y_pred, averagemacro)test_f1_weightedf1_score(y_test, y_pred, averageweighted)print(\n*50)print(测试集最终验证结果)print(fMacro-F1: {test_f1_macro:.4f})print(fWeighted-F1: {test_f1_weighted:.4f})print(\n分类报告)print(classification_report(y_test, y_pred, target_nameswine.target_names))print(混淆矩阵)print(confusion_matrix(y_test, y_pred))
返回列表