• 快速求熵程序(续)


    这篇blog是对快速求熵程序的数学解释。

    首先,还是从熵的计算公式出发,略做一些推导:

    $ Entropy=-sum_{i=1}^{n}P(X_{i})log_{2}P(X_{i})$

    $=-sum_{i=1}^{n}frac{C(X_{i})}{T}log_{2}frac{C(X_{i})}{T}$

    $=-frac{1}{T}sum_{i=1}^{n}C(X_{i})(log_{2}C(X_{i})-log_{2}T)$

    $=-frac{1}{T}(sum_{i=1}^{n}C(X_{i})log_{2}C(X_{i})-log_{2}Tsum_{i=1}^{n}C(X_{i}))$

    $=frac{1}{T}(Tlog_{2}T-sum_{i=1}^{n}C(X_{i})log_{2}C(X_{i}))$

    令 $f(x)=2^{23}xlog_{2}x$,那么,

    $ Entropy=frac{1}{2^{23}T}(f(T)-sum_{i=1}^{n}f(C(X_{i})))$

    fast_entropy()的代码,就是上面公式的直接实现,其中_lxlogx()即为公式中的$f(x)$。

    double fast_entropy(int *counts, int n, int total)
    {
        long long s = 0;
        int i, c;
        for(i = 0; i < n; i++) {
            if(c = counts[i])
                s -= _lxlogx(c);
        }
        s += _lxlogx(total);
        s /= total;
        return 0.00000011920929 * s;
    }

     _lxlogx()的代码,只有4行。前3行完成了$2^{23}log_{2}x$的计算,考虑编译后的ASM指令,除了int->float的转换将产生一条FPU的FILD指令外,其余均为整数操作。

    static inline long long _lxlogx(int x)
    {
        float f = (float)x;
        int i = *(int *)&f;
        i += _u[(i & 0x007F8000) >> 15];
        return (long long)i * x; 
    }

     1个float浮点数占用4字节,按IEEE 754标准格式存储。假设有float浮点数$x$,我们把它的4个字节当做1个32-bit的整数读取,得到$I_{x}$,那么存在近似关系:

    $2^{23}log_{2}xapprox I_{x}-2^{23}(127-u)$

    这个关系的推导过程见这里。其中,$u (u > 0)$是一个自定义的数,它的数值影响近似程度。具体地,$u$的取值应该尽量让下面的近似误差更小:

    $log_{2}(1+x)approx x + u, (0leq x < 1, u > 0)$

    定义误差函数$e(u)=log_{2}(1+x)- (x+u)$,求解:$int_{0}^{1}e(u)dx=0$

    得到$ u^{*}=0.0573049591110366 $。$e(u^{*})$的图像为,

     有没有办法让误差更小呢?可以把$[0,1)$区间分成若干段,为每段找出不同的$u^{*}$。在fast_entropy中,我把$[0,1)$等分成了256个段,对于第 $i (i=0,1,2,...,255)$ 段来说,$u_{i}^{*}$满足:

    $int_{frac{i}{256}}^{frac{i+1}{256}}e(u_{i}^{*})dx=0$

    计算出256个 $u_{i}^{*}$。

    下面图像中,可以看到分段后的误差(紫色)和分段前(蓝色)相比,减小了很多。

    这也是fast_entropy中那个_u[256]的来源。当然_u是个32-bit整数数组,每一项是这样计算出来的,

    _u[$i$] = $left [ 2^{32}-2^{23}(127-u_{i}^{*}) ight ] $

    到这里,fast_entropy所有代码的原理已经解释完毕。

    _u数组是控制误差的所在,可以通过增加分段数量,即增加数组大小的方法来提高计算精度,而不会对计算效率产生明显影响。对于大多数实际应用,256项的_u的精度已经足够。

  • 相关阅读:
    第十四周课程总结&实验报告(简单记事本的实现)
    第十三周课程总结
    第十二周
    第十一周课程总结
    第十周课程总结
    第九周课程总结&实验报告(七)
    第八周课程总结&实验报告(六)
    第七周课程总结&实验报告(五)
    第六周&java实验报告四
    全局变量
  • 原文地址:https://www.cnblogs.com/daishuo/p/3955189.html
Copyright © 2020-2023  润新知