机器学习论文结果复现:从原始数据到 CD 图的 5 步完整流程(附 Python 代码) 机器学习论文结果复现从原始数据到 CD 图的 5 步完整流程附 Python 代码在机器学习研究领域论文结果的复现一直是验证算法有效性的重要环节。许多研究者都曾遇到过这样的困境阅读一篇论文时虽然作者展示了漂亮的统计比较结果和图表但当自己尝试复现时却不知从何入手。本文将带你完整走一遍从原始数据到临界差异图CD 图的全流程不仅告诉你每一步怎么做还会解释为什么要这样做。1. 数据准备与预处理复现论文结果的第一步是获取原始数据。理想情况下论文作者会公开实验数据但很多时候我们需要从论文表格中手动提取。这里有几个实用技巧对于PDF格式的论文可以使用Tabula或Adobe Acrobat的表格提取功能对于图片中的表格可以尝试OCR工具如ABBYY FineReader对于网页版论文有时可以直接复制粘贴到Excel中常见数据格式问题及解决方案问题类型解决方法Python代码示例缺失值填充或删除df.fillna(0)或df.dropna()非数值数据类型转换df[column] pd.to_numeric(df[column])数据单位不统一标准化处理df[column] df[column] * conversion_factorimport pandas as pd # 读取原始数据 def load_data(file_path): try: if file_path.endswith(.csv): df pd.read_csv(file_path) elif file_path.endswith(.xlsx): df pd.read_excel(file_path) else: raise ValueError(Unsupported file format) # 基本数据清洗 df df.apply(pd.to_numeric, errorscoerce) # 尝试将所有列转为数值 df df.dropna(howall) # 删除全空行 return df except Exception as e: print(fError loading data: {str(e)}) return None提示在数据预处理阶段务必记录下所有处理步骤这对后续的结果验证至关重要。建议使用Jupyter Notebook逐步执行并保存中间结果。2. 计算平均排名AVG RANK排名计算是统计比较的基础。在机器学习论文中常见的是在不同数据集上比较多个算法的性能然后计算每个算法的平均排名。排名计算方法选择methodaverage默认方法相同值取平均排名methodmin相同值取最小排名methodmax相同值取最大排名methodfirst按出现顺序排名methoddense相同值同排名下一个值连续def calculate_ranks(df): 计算各算法在不同数据集上的排名 :param df: DataFrame每列代表一个算法每行代表一个数据集 :return: 排名DataFrame rank_df df.rank(axis1, ascendingFalse, methodaverage) avg_rank rank_df.mean(axis0).sort_values() return rank_df, avg_rank # 示例使用 data { Algorithm1: [0.85, 0.78, 0.92], Algorithm2: [0.82, 0.85, 0.88], Algorithm3: [0.78, 0.90, 0.85] } df pd.DataFrame(data) ranks, avg_ranks calculate_ranks(df) print(各数据集上的排名:\n, ranks) print(\n平均排名:\n, avg_ranks)排名结果解释在每个数据集上性能最好的算法获得排名1如果多个算法性能相同它们会获得平均排名如两个算法并列第一则都获得1.5的排名最终的平均排名是所有数据集上排名的平均值3. 统计显著性检验p值计算在得到排名后我们需要验证这些差异是否具有统计显著性。Wilcoxon符号秩检验是机器学习论文中最常用的非参数检验方法之一。为什么选择Wilcoxon检验不假设数据服从正态分布适用于小样本情况对异常值不敏感可以检测出算法间的系统性差异from scipy import stats def wilcoxon_test(df, control_algorithmNone): 执行Wilcoxon符号秩检验 :param df: 原始数据DataFrame :param control_algorithm: 作为对照的算法名称若为None则进行所有两两比较 :return: p值矩阵或p值列表 algorithms df.columns.tolist() n_algorithms len(algorithms) p_values [] if control_algorithm: # 与对照算法比较 control_data df[control_algorithm].values for algo in algorithms: if algo control_algorithm: continue algo_data df[algo].values _, p stats.wilcoxon(control_data, algo_data) p_values.append((control_algorithm, algo, p)) else: # 所有两两比较 for i in range(n_algorithms): for j in range(i1, n_algorithms): algo1 algorithms[i] algo2 algorithms[j] _, p stats.wilcoxon(df[algo1].values, df[algo2].values) p_values.append((algo1, algo2, p)) return p_values # 示例使用 p_values wilcoxon_test(df, control_algorithmAlgorithm1) print(\nWilcoxon检验p值:) for pair in p_values: print(f{pair[0]} vs {pair[1]}: p{pair[2]:.4f})注意Wilcoxon检验是配对检验要求比较的两个算法在所有数据集上都有结果。如果有缺失值需要先处理。4. 多重检验校正当做多次统计检验时假阳性率会显著增加。例如做20次检验时至少出现一个假阳性的概率高达64%。因此我们需要对p值进行校正。常用校正方法比较方法控制指标严格程度适用场景Bonferroni族错误率最严格检验次数少需要强控制Holm族错误率中等一般情况Hochberg族错误率较宽松检验间独立或正相关Benjamini-HochbergFDR较宽松探索性分析允许一定假阳性def adjust_pvalues(p_values, methodholm): 对p值进行多重检验校正 :param p_values: 原始p值列表格式为[(algo1, algo2, p), ...] :param method: 校正方法可选bonferroni, holm, hochberg, bh等 :return: 校正后的p值列表 from statsmodels.stats.multitest import multipletests # 提取原始p值 raw_p [p for _, _, p in p_values] # 进行校正 reject, adj_p, _, _ multipletests(raw_p, alpha0.05, methodmethod) # 构建结果 adjusted [] for i, (algo1, algo2, _) in enumerate(p_values): adjusted.append((algo1, algo2, adj_p[i], reject[i])) return adjusted # 示例使用 adjusted_p adjust_pvalues(p_values, methodholm) print(\n校正后的p值:) for result in adjusted_p: sig 显著 if result[3] else 不显著 print(f{result[0]} vs {result[1]}: 校正p{result[2]:.4f} ({sig}))5. 绘制临界差异图CD图临界差异图是直观展示算法性能比较结果的有效工具。它基于Nemenyi检验显示了哪些算法间的差异具有统计显著性。CD图关键元素解读算法按平均排名从左到右排列横轴表示排名临界差异CD表示最小显著差异算法间如果没有重叠的CD线则差异显著import Orange import matplotlib.pyplot as plt def plot_cd_diagram(avranks, names, datasets_num, alpha0.05): 绘制临界差异图 :param avranks: 各算法的平均排名列表 :param names: 算法名称列表 :param datasets_num: 数据集数量 :param alpha: 显著性水平 # 计算临界差异 cd Orange.evaluation.scoring.compute_CD(avranks, datasets_num, alphaalpha, testnemenyi) # 绘制CD图 plt.figure(figsize(10, 6)) Orange.evaluation.scoring.graph_ranks( avranks, names, cdcd, width8, textspace1.5, reverseTrue ) plt.title(f临界差异图 (α{alpha}, CD{cd:.2f})) plt.tight_layout() plt.show() # 示例使用 names [Algorithm1, Algorithm2, Algorithm3] avranks [2.0, 1.5, 2.5] # 示例平均排名 datasets_num 10 # 假设使用了10个数据集 plot_cd_diagram(avranks, names, datasets_num)CD图绘制技巧调整width和textspace参数确保算法名称显示完整对于大量算法考虑使用更大的画布尺寸可以尝试不同的显著性水平如0.01或0.1来观察结果变化保存高分辨率图片用于论文发表DPI≥300在实际项目中我经常遇到CD图显示效果不理想的情况。通过调整textspace参数和字体大小可以让图表更加清晰易读。另外如果算法名称较长可以考虑使用缩写或在图表下方添加图例说明。