趋近智
虽然比较边际分布和基本统计数据能初步评估数据保真度,但这些方法通常会忽略数据集中变量间多样的关联。信息论提供一个有力的数学框架,用于量化 (quantization)不确定性和依赖性,从而提供更精密的工具来比较真实数据集 () 和合成数据集 () 的结构特征。
信息论度量不只是让我们问“均值是否相似?”,而是帮助我们提出“合成数据是否包含相同的信息量?”或“合成数据中是否保持了变量间的关系?”这样的问题。
熵是衡量随机变量不确定性或随机性的基本度量。对于具有可能取值 和概率质量函数 的离散随机变量 ,香农熵 定义为:
对数基数通常为2,以比特为单位衡量熵。熵值越高意味着不确定性越大或可预测性越低。
在合成数据评估中:
互信息(MI)衡量通过观察一个随机变量所获得的关于另一个随机变量的信息量。它量化了两个变量之间的依赖性,比简单相关性更能全面捕获非线性关系。对于两个离散变量 和 ,互信息 为:
它也可以用熵来表示:
始终非负,当且仅当 和 独立时为零。MI值越高表示依赖性越强。
在评估中的应用: 统计保真度的一个重要方面是保持变量之间的关系。我们可以计算真实数据集和合成数据集中特征对 的MI值: 对比 。
计算MI通常需要估计联合和边际概率分布。对于连续数据,这通常涉及离散化或使用专用估计器,例如scikit-learn等库中基于k近邻(KNN)的方法(sklearn.metrics.mutual_info_score 用于离散数据,sklearn.feature_selection.mutual_info_regression/mutual_info_classification 使用KNN估计用于连续/混合类型数据)。
import numpy as np
from sklearn.metrics import mutual_info_score
from sklearn.preprocessing import KBinsDiscretizer
# 假设 real_data 和 synth_data 是 pandas DataFrames
# 示例:比较“年龄”和“收入”之间的MI(假设它们是连续的)
# 使用 mutual_info_score 对连续特征进行离散化以计算MI
n_bins = 10 # 选择合适的分箱数量
kbd = KBinsDiscretizer(n_bins=n_bins, encode='ordinal', strategy='uniform', subsample=None)
# 在真实数据上拟合,并转换真实和合成数据
# 重要:仅在真实数据上拟合离散器
real_data_discrete = kbd.fit_transform(real_data[['Age', 'Income']])
synth_data_discrete = kbd.transform(synth_data[['Age', 'Income']])
# 计算列联矩阵(mutual_info_score 所需)
# 注意:mutual_info_score 需要标签,因此我们使用离散化后的值
# 我们需要联合分布 P(x,y),通常通过直方图/列联表估计
def calculate_mi(data_col1, data_col2):
""" 计算两个离散列之间的MI """
contingency_matrix = np.histogram2d(data_col1, data_col2, bins=n_bins)[0]
# 如有必要,添加一个小的epsilon以避免log(0),或进行适当处理
# mutual_info_score 在内部处理此问题
return mutual_info_score(None, None, contingency_matrix=contingency_matrix)
mi_real = calculate_mi(real_data_discrete[:, 0], real_data_discrete[:, 1])
mi_synth = calculate_mi(synth_data_discrete[:, 0], synth_data_discrete[:, 1])
print(f"互信息 (真实数据, 年龄 vs 收入): {mi_real:.4f}")
print(f"互信息 (合成数据, 年龄 vs 收入): {mi_synth:.4f}")
print(f"MI差异: {abs(mi_real - mi_synth):.4f}")
# 考虑对多个特征对执行此操作
代码片段演示了使用scikit-learn对真实和合成数据集中两个特征('年龄'、'收入')离散化后互信息的比较。
散度度量提供一种方法,用于量化两个概率分布 (表示真实数据分布)和 (表示合成数据分布)之间的差异。
Kullback-Leibler (KL) 散度: 衡量用 近似 时信息损失了多少。对于离散分布:
,当且仅当 时 。
Jensen-Shannon (JS) 散度: 一种从KL散度推导出的对称且有界的度量。
其中 是混合分布。
实际计算: 计算高维联合分布的散度有难度。常见方法包括:
诸如 scipy.stats.entropy 等库可以计算离散分布(表示为概率向量 (vector))之间的KL散度。JS散度可以使用KL散度函数实现。
from scipy.stats import entropy
import numpy as np
# 假设 p_real 和 q_synth 是 1D 概率分布(直方图)
# 例如,来自 np.histogram(data_feature, bins=..., density=True)[0]
# 确保它们总和为1,并且具有相同的分箱/支持域。添加小的 epsilon 以避免零。
epsilon = 1e-10
p_real = p_real + epsilon
p_real /= np.sum(p_real)
q_synth = q_synth + epsilon
q_synth /= np.sum(q_synth)
# KL 散度 (真实 || 合成)
kl_div_pq = entropy(p_real, q_synth, base=2)
# KL 散度 (合成 || 真实)
kl_div_qp = entropy(q_synth, p_real, base=2)
# JS 散度
m = 0.5 * (p_real + q_synth)
js_div = 0.5 * (entropy(p_real, m, base=2) + entropy(q_synth, m, base=2))
print(f"KL 散度 (P||Q): {kl_div_pq:.4f}")
print(f"KL 散度 (Q||P): {kl_div_qp:.4f}")
print(f"JS 散度 (P||Q): {js_div:.4f}") # 应在0到1之间
使用SciPy对两个一维概率分布进行KL和JS散度的基本计算。需要仔细的预处理(归一化 (normalization),处理零值)。
信息论度量提供一种基于理论的统计保真度评估方式:
优点:
难题:
尽管存在这些难题,但比较特征对之间的互信息,以及在低维边际(或仔细估计的联合分布)上使用JS散度,可以提供有价值的见解,了解合成数据复制真实数据统计结构的效果如何,显著补充了其他保真度评估技术。
这部分内容有帮助吗?
© 2026 ApX Machine Learning用心打造