alv*_*vas 5 python math product list geometric-mean
如果列表中没有0,我们可以轻松地在列表中项目的产品与列表中项目的对数之和进行转换,例如:
>>> from operator import mul
>>> pn = [0.4, 0.3, 0.2, 0.1]
>>> math.pow(reduce(mul, pn, 1), 1./len(pn))
0.22133638394006433
>>> math.exp(sum(0.25 * math.log(p) for p in pn))
0.22133638394006436
Run Code Online (Sandbox Code Playgroud)
我们应该如何处理列表和Python中有0的情况 (以编程和数学方式正确)?
更具体地说,我们应该如何处理以下情况:
>>> pn = [0.4, 0.3, 0, 0]
>>> math.pow(reduce(mul, pn, 1), 1./len(pn))
0.0
>>> math.exp(sum(1./len(pn) * math.log(p) for p in pn))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <genexpr>
ValueError: math domain error
Run Code Online (Sandbox Code Playgroud)
返回0真的是处理这个问题的正确方法吗?什么是优雅的解决方案,我们认为列表中的0但不是最终为0?
因为它是某种几何平均值(列表的乘积),当我们返回0时它不是很有用,因为列表中只有一个0.
从Math Stackexchange溢出:https://math.stackexchange.com/questions/1727497/resolving-zeros-in-product-of-items-in-list ,没有数学人的回答,也许是蟒蛇/代码Jedis有解决这个问题的更好的想法.
TL; DR:是的,返回0是唯一正确的方法.(但见结论.)
在实际分析中(即不是复数),当考虑对数时,我们传统上假设域log
是真正的正数.我们有这样的身份:
x = exp(log(x)), for x>0.
Run Code Online (Sandbox Code Playgroud)
它可以自然地扩展到,x=0
因为右手侧表达的极限被明确定义为x->0+
等于0.此外,它是合法的设置log(0)=-inf
和exp(-inf)=0
(再次:仅对于真实的,而不是复杂的数字).在形式上,我们扩展实数的集合,添加两个元素-inf
,+inf
并定义一致的算术等(对于我们的目的,我们需要inf + x = inf
,x * inf = inf
对于真实的x inf + inf = inf
等)
另一个身份x = log(exp(x))
不那么麻烦,适用于所有实数(甚至x=-inf
或者+inf
).
几何平均数
可以为非负数(可能等于零)定义几何平均数.对于两个数字a
,b
(它自然地推广到更多数字,所以我将仅使用两个数字),它是
gm(a,b) = sqrt(a*b), for a,b >= 0.
Run Code Online (Sandbox Code Playgroud)
当然,gm(0,b)=0
.记录日志,我们得到:
log(gm(a,b)) = (log(a) + log(b))/2
Run Code Online (Sandbox Code Playgroud)
如果a
或b
为零,则定义明确.(log(0) = -inf
由于我们之前定义的扩展算法,我们可以插入并且身份仍然成立.)
解释
毫不奇怪,几何平均数的概念来自几何,最初(在古希腊)用于严格的正数.
假设,我们有长的边的矩形a
和b
.找到面积等于矩形区域的正方形.不难看出,该正方形的边的几何平均值a
和b
.
现在,如果我们采取a = 0
,那么我们并没有真正的矩形,这种几何解释打破了.其他解释也可能出现类似的问题.我们可以通过考虑例如退化的矩形和正方形来减轻它,但它可能并不总是合理的方法.
结论
这取决于用户(数学家,工程师,程序员)如何理解几何平均值为零的含义.如果它导致解释结果的严重问题或打破计算机程序,那么首先,可能几何平均值的选择不合理作为数学模型.
正如在其他答案中已经提到的,python已经实现了无穷大.它在执行时会引发运行时警告(除以零),np.exp(np.log(0))
但操作结果是正确的.