Python实现的边际希尔伯特谱积分方案是否符合解析表达式?
问题1:现有实现的问题与优化建议
- 冗余依赖matplotlib:你当前用
plt.hist2d计算联合概率密度,完全可以替换为numpy原生的np.histogram2d,功能完全一致,不需要额外启动绘图流程、关闭画布,避免不必要的性能开销和绘图后端兼容问题。 - 索引越界风险:
np.digitize的返回值默认范围是[1, len(edges)],刚好落在边界上的样本会得到等于len(edges)的索引,而你的Pjoint最后一维索引最大是len(A_edges)-2,直接用会触发索引越界。可以在digitize时添加right=True参数,或者用np.clip(n1, 1, len(A_edges)-1) - 1把索引映射到[0, bins_A-1]的合法范围。 - 循环逻辑效率低:你在双层循环里每次做布尔索引筛选样本,数据量越大冗余计算越多。可以提前用分组统计每个(j,k) bin内的A平方均值,不需要循环时逐次筛选,性能可以提升1~2个数量级。
- 只适配等宽幅值bin:你当前直接取
np.diff(A_edges)[0]作为所有bin的dA,仅支持等宽bin的情况。如果后续用到不等宽bin,需要改为取对应k位置的bin宽度np.diff(A_edges)[k]。 - 空bin处理冗余:没有样本的bin
Pjoint[j,k]本身就是0,乘nan也不会影响最终求和结果,不过可以提前跳过空bin减少计算量。
问题2:基于scipy的等效实现方案
边际希尔伯特谱的本质是对每个固定频率,沿幅值维度积分p(ω,A)·A²,你的求和本质是矩形法数值积分,完全可以用scipy的积分函数实现,示例代码如下:
import numpy as np from scipy.integrate import trapezoid # 替换plt.hist2d,直接用numpy算联合概率密度 Pjoint, f_edges, A_edges = np.histogram2d(IF_flat, IA_flat, bins=[bins_F, bins_A], density=True) # 计算每个幅值bin的中心,或者对应bin内A²的均值 A_centers = (A_edges[:-1] + A_edges[1:]) / 2 dA = np.diff(A_edges) # 对每个频率bin,沿幅值维度做积分 sum_h_scipy = np.zeros(Pjoint.shape[0]) for j in range(Pjoint.shape[0]): # 被积函数值:p(ω_j,A) * A² integrand = Pjoint[j, :] * (A_centers ** 2) # 用梯形法积分,也可以替换为simpson辛普森法精度更高 sum_h_scipy[j] = trapezoid(integrand, dx=dA[0]) if len(np.unique(dA))==1 else trapezoid(integrand, A_centers)
如果要和你原来的计算逻辑完全对齐(用每个bin内实际样本的A平方均值代替bin中心的平方),可以提前统计每个bin的A²均值:
# 预处理索引,映射到合法范围 n1 = np.clip(np.digitize(IA_flat, A_edges), 1, len(A_edges)-1) - 1 n2 = np.clip(np.digitize(IF_flat, f_edges), 1, len(f_edges)-1) - 1 bin_indices = n2 * len(A_edges) + n1 # 统计每个bin的A平方均值 bin_counts = np.bincount(bin_indices, minlength=Pjoint.size) bin_A2_sum = np.bincount(bin_indices, weights=IA_flat**2, minlength=Pjoint.size) bin_A2_mean = np.where(bin_counts==0, 0, bin_A2_sum / bin_counts).reshape(Pjoint.shape) # 积分计算 sum_h_scipy = trapezoid(Pjoint * bin_A2_mean, dx=dA[0], axis=1)
内容的提问来源于stack exchange,提问作者jokerp
相关产品推荐
相关产品推荐

