Handling floating point imprecision in creating exponential smoothing weights
我想从此处创建一个如公式(7.2)所示的指数平滑权重数组。我知道递归定义,但需要实际权重。我想出了以下简单的实现方法:
1 2 3 4 5 | import numpy as np def create_weights(n, alpha = 1.0): wghts = alpha*(1-alpha)**np.arange(n) return wghts |
权重之和应为1.0,但是,如该测试所示,较小的alpha并非如此,我猜是由于浮点数引起的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | np.set_printoptions(precision=3) for alpha in np.arange(1.0, 0.0, -0.1): print("%.3f, %s, %.3f" % (alpha, create_weights(5, alpha) , create_weights(5, alpha).sum())) Out: 1.000, [1. 0. 0. 0. 0.], 1.000 0.900, [9.e-01 9.e-02 9.e-03 9.e-04 9.e-05], 1.000 0.800, [0.8 0.16 0.032 0.006 0.001], 1.000 0.700, [0.7 0.21 0.063 0.019 0.006], 0.998 0.600, [0.6 0.24 0.096 0.038 0.015], 0.990 0.500, [0.5 0.25 0.125 0.062 0.031], 0.969 0.400, [0.4 0.24 0.144 0.086 0.052], 0.922 0.300, [0.3 0.21 0.147 0.103 0.072], 0.832 0.200, [0.2 0.16 0.128 0.102 0.082], 0.672 0.100, [0.1 0.09 0.081 0.073 0.066], 0.410 |
类似于这里的解决方案,我可以简单地对其进行"规范化",以再次扩大规模:
1 2 3 4 | def create_weights(n, alpha = 1.0): wghts = alpha*(1-alpha)**np.arange(n) wghts /= wghts.sum() return wghts |
结果为:
1 2 3 4 5 6 7 8 9 10 | 1.000, [1. 0. 0. 0. 0.], 1.000 0.900, [9.e-01 9.e-02 9.e-03 9.e-04 9.e-05], 1.000 0.800, [0.8 0.16 0.032 0.006 0.001], 1.000 0.700, [0.702 0.211 0.063 0.019 0.006], 1.000 0.600, [0.606 0.242 0.097 0.039 0.016], 1.000 0.500, [0.516 0.258 0.129 0.065 0.032], 1.000 0.400, [0.434 0.26 0.156 0.094 0.056], 1.000 0.300, [0.361 0.252 0.177 0.124 0.087], 1.000 0.200, [0.297 0.238 0.19 0.152 0.122], 1.000 0.100, [0.244 0.22 0.198 0.178 0.16 ], 1.000 |
现在总和为1.0,但对于较小的alpha而言,其第一权重与预期值相差太大(预期与alpha相同)。
是否存在另一种实现权重属性的方法,将权重加到1.0(-小误差),而第一个权重为alpha(-小误差)?
这与浮点精度无关。即使使用无限精度实数运算,您生成的数组也不会加到1。类似地生成的一个无限数列的总和为1,但您的数组在5个元素处停止而不是永远持续下去。
简单的指数平滑不会任意停止在5个元素上。过去,对足够远的元素应用权重是很合理的,因为它们的权重很小,但是如果不进行归一化,则在每个alpha处停止为5会产生不合理的结果。