TensorBoard标量图中的平滑曲线是如何做的平滑?—— tensorflow TensorBoard标量图中“平滑”参数背后的数学原理是什么?—— 指数移动平均(EMA)

TensorFlow的tensorboard的平滑曲线的实现代码:

使用“指数移动平均”技术实现。


地址:
https://github.com/tensorflow/tensorboard/blob/34877f15153e1a2087316b9952c931807a122aa7/tensorboard/components/vz_line_chart2/line-chart.ts#L699


  private resmoothDataset(dataset: Plottable.Dataset) {
    let data = dataset.data();
    const smoothingWeight = this.smoothingWeight;
    // 1st-order IIR low-pass filter to attenuate the higher-
    // frequency components of the time-series.
    let last = data.length > 0 ? 0 : NaN;
    let numAccum = 0;
    const yValues = data.map((d, i) => this.yValueAccessor(d, i, dataset));
    // See #786.
    const isConstant = yValues.every((v) => v == yValues[0]);
    data.forEach((d, i) => {
      const nextVal = yValues[i];
      if (isConstant || !Number.isFinite(nextVal)) {
        d.smoothed = nextVal;
      } else {
        last = last * smoothingWeight + (1 - smoothingWeight) * nextVal;
        numAccum++;
        // The uncorrected moving average is biased towards the initial value.
        // For example, if initialized with `0`, with smoothingWeight `s`, where
        // every data point is `c`, after `t` steps the moving average is
        // ```
        //   EMA = 0*s^(t) + c*(1 - s)*s^(t-1) + c*(1 - s)*s^(t-2) + ...
        //       = c*(1 - s^t)
        // ```
        // If initialized with `0`, dividing by (1 - s^t) is enough to debias
        // the moving average. We count the number of finite data points and
        // divide appropriately before storing the data.
        let debiasWeight = 1;
        if (smoothingWeight !== 1) {
          debiasWeight = 1 - Math.pow(smoothingWeight, numAccum);
        }
        d.smoothed = last / debiasWeight;
      }
    });


等价的python代码:

def smooth(scalars: list[float], weight: float) -> list[float]:
    """
    EMA implementation according to
    https://github.com/tensorflow/tensorboard/blob/34877f15153e1a2087316b9952c931807a122aa7/tensorboard/components/vz_line_chart2/line-chart.ts#L699
    """
    last = 0
    smoothed = []
    num_acc = 0
    for next_val in scalars:
        last = last * weight + (1 - weight) * next_val
        num_acc += 1
        # de-bias
        debias_weight = 1
        if weight != 1:
            debias_weight = 1 - math.pow(weight, num_acc)
        smoothed_val = last / debias_weight
        smoothed.append(smoothed_val)
    return smoothed

指数移动平均是比较常见的平滑技术,但是和常见的计算公式不同,上面的计算中出现了一个 debias_weight 变量,最终的EMA值也是需要除以这个 debias_weight 获得的。


由于EMA的计算是对历史数据的指数加权,因此如果不除以 debias_weight 最终获得的数值是对历史数据的加权不等于1的,而这个 debias_weight 就是对历史数据的加权的权值。

EMA的等价的计算公式:

EMA = 0*s^(t) + c*(1 - s)*s^(t-1) + c*(1 - s)*s^(t-2) + ...
       = c*(1 - s^t)

加权权重的计算,并除以不为1的加权权重值,获得最终的平滑值:

debias_weight = 1 - math.pow(weight, num_acc)
smoothed_val = last / debias_weight


参考:

tensorflow TensorBoard标量图中“平滑”参数背后的数学原理是什么?



posted on 2024-02-15 10:08  Angry_Panda  阅读(742)  评论(0)    收藏  举报

导航