Smooth curves.

在生成损失函数等曲线时,由于噪声等高频点的波动导致曲线振荡明显。为了使曲线过渡更平滑,可以对曲线进行平滑处理。本文介绍一些常用的曲线平滑处理方法:

  1. 窗口移动平滑
  2. Savitzky-Golay平滑
  3. 指数移动平滑

1. 窗口移动平滑

窗口移动平滑是指预设一个长度为$n$的窗口,在曲线上进行移动。对于每个窗口位置处的中心点数值,使用该窗口内所有位置的算术平均值代替。

可以用一维卷积实现窗口移动平滑,其中步长为$1$,卷积核为$\frac{1}{n}$:

import numpy as np
y = np.convolve(x, np.ones((n,))/n, mode='same')
# mode指定填充格式,可选full, same, valid

2. Savitzky-Golay平滑

Savitzky-Golay滤波也是一种基于移动窗口的加权平均滤波算法,但其加权系数不是常数,而是通过在滑动窗口内对指定高阶多项式的最小二乘拟合得到的。

SG滤波预设窗口的宽度为$2m+1$(宽度为奇数),对于其中的测量点$[-m,-m+1,…,0,…,m]$构造$k-1$次多项式进行拟合:

\[y=w_0+w_1x+w_2x^2+ \cdots w_{k-1}x^{k-1}\]

因此在每个窗口构造$2m+1$个$k$元方程组,为使方程组有解应有$2m+1\geq k$。通过最小二乘法可拟合方程组的系数,并进一步获得$x=0$处的滤波结果$w_0$。

scipy中提供了Savitzky-Golay滤波方法:

import scipy.signal
y = scipy.signal.savgol_filter(x, window_length, polyorder)

3. 指数移动平滑

指数移动平滑是tensorboard中使用的曲线平滑方法,即使用指数移动平均的形式更新初始点到当前点的加权累计值:

\[\hat{y}_i = \beta \hat{y}_{i-1} + (1-\beta) y_{i}\]
def smooth(data, weight=0.8):
    last = data[0]
    res= []
    for point in data:
        smoothed_val = last * weight + (1 - weight) * point
        res.append(smoothed_val)
        last = smoothed_val
    return res