关于for循环和减少的Python之谜

时间:2019-02-13 13:57:27

标签: python numpy lambda functional-programming

我正在尝试计算可执行文件的字节熵。在将直方图作为数组后,我首先使用for循环进行计算。然后,我尝试使用functools.reduce进行固定。有趣的是,我从相同的数组和相同的函数中获得了不同的结果,并且我想了解为什么。

我将其简化为一个简单的循环和两行代码块,但是,我不明白为什么其中之一是错误的。我比较了for循环中列表“ prob”和“ prob”的所有元素,所有值都相同。

sudo iotedge logs <yourModuleName>

AND

sudo iotedge logs <yourModuleName> -f --tail 100

其中一个捐献0.813826598594107,另一个捐献给0.8605594205272858。 “ hist”是一个numpy.ndarray。

2 个答案:

答案 0 :(得分:4)

您的初始值是不同的。 在循环版本中,您首先应用calc_entropy(0, prob[0]),但减少后,您的第一个应用是calc_entropy(prob[0], prob[1])。您可以通过使用初始值reduce调用reduce(calc_entropy, prob, 0)来更改它。

答案 1 :(得分:2)

问题是初始值,就像@YSelf在他的答案中指出的那样。

这是一个示范:

import functools
import math
import numpy as np

calc_entropy = lambda e, p: e - p*math.log(p, 256) if (p != .0) else e

def f1a(hist, bytes_len):
    prob = hist / bytes_len
    e = functools.reduce(calc_entropy, prob)              # no initial value
    return e


def f1b(hist, bytes_len):
    prob = hist / bytes_len
    e = functools.reduce(calc_entropy, prob, 0.0)         # with initial value
    return e


def f2(hist, bytes_len):
    e = 0.0
    for freq in hist:
        prob = freq / bytes_len
        e = calc_entropy(e, prob)
    return e

一些测试(我只显示一个测试,但是我用不同的数字进行了几个测试,所有测试的结论都如下):

>>> b = 5
>>> h = np.random.rand(10)
>>> h
[0.68968912 0.37621079 0.76577699 0.06287911 0.49159805 0.63960027
 0.50323918 0.56442714 0.28445216 0.03391277]

>>> f1a(h, b)
0.4449530941371813
>>> f1b(h, b)
0.3562920060014537
>>> f2(h, b)
0.3562920060014537

请注意f1b()f2()的结果如何相等,但与f1a()不同。