我是如何使计算提速>150 倍的
我是如何使计算提速>150倍的
我的原始文档:<https://www.yuque.com/lart/blog/lwgt38>
书接上文《我是如何使计算时间提速25.6倍》.
上篇文章提到, F-measure使用累计直方图可以进一步加速计算, 但是E-measure却没有改出来. 在写完上篇文章的那个晚上, 重新整理思路后, 我似乎想到了如何去使用累计直方图来再次提速.
速度的制约
虽然使用"解耦"的思路可以高效优化每一个阈值下指标的计算过程, 但是整体的 for
循环确实仍然会占用较大的时间. 又考虑到各个阈值下的计算实际上并无太大关联, 如果可以实现同时计算, 那必然可以进一步提升速度. 这里我们又要把目光放回到在计算F-measure时大放光彩的累计直方图的策略上.
在前面的解耦之后, 实际上获得的关键变量是 fg_fg_numel
和 fg_bg_numel
.
从这两个变量本身入手, 如果使用累计直方图的话, 实际上可以同时获得 >=不同阈值
下的前景像素(值为1)的数量, 计算的本质和 np.count_nonzero
是一样的东西. 所以我们可以进行直观的替换:
这样我们就获得了不同阈值下的对应的一系列 fg_fg_numel
和 fg_bg_numel
了. 这里需要注意的是, 使用的划分区间 bins
的设置. 由于默认的 histogram
划分的区间会包含最后一个端点, 所以比较合理的划分是 bins = np.linspace(0, 256, 257)
, 这样最后一个区间是 [255, 256]
, 就可以包含到最大的值, 又不会和 254
重复计数.
为了便于计算, 这里将后面会用到的 pred
前景统计 fg___numel_w_thrs
和背景统计 bg___numelw_thrs
直接写出来, 便于使用:
后面的步骤和之前的基本一致, numpy的广播机制使得不需要改动太多. 由于这部分代码实际上再多处位置会被使用, 所以提取成一个单独的方法.
后面计算 enhanced_matrix_sum
的部分也就顺理成章比较自然的可以写出来:
整体梳理
主要逻辑已经搞定, 接下来就是将这些代码与原始的代码融合起来, 也就是整合原始代码的 cal_em_with_threshold
和 cal_enhanced_matrix
两个方法.
结合前面代码中计算出的各个阈值下的前背景元素的统计值, 上面这里的代码实际上可以通过使用现有运算结果进行化简, 即 if
的前两个分支. 另外阈值划分也不需要显式处理, 因为已经在累计直方图中搞定了. 所以这里的代码对于动态阈值计算的情况下, 是可以被合并到 cal_enhanced_matrix
的计算过程中的. 直接得到最终的整合后的方法:
还是为了重用, cal_em_with_threshold
(该方法需要保留, 因为还有另一种E-measure的计算情况需要用到该方法)可以被重构:
效率对比
使用本地的845张灰度预测图和二值mask真值数据进行测试比较, 重新跑了一遍, 总体时间对比如下:
还是那句话, 虽然具体时间可能还受硬件限制, 但是相对快慢还是比较明显的.
测试代码可见我的 github
: https://github.com/lartpang/CodeForArticle/tree/main/sod_metrics
版权声明: 本文为 InfoQ 作者【Lart】的原创文章。
原文链接:【http://xie.infoq.cn/article/95ea9a2df68822c313fee8611】。文章转载请联系作者。
评论