msdd’s blog

deep learning勉強中。プログラム関連のこと書きます。

TensorBoardにおけるデータのSmoothingのアルゴリズム

はじめに

tensorboardでスカラー表示のグラフのところに、smoothingを変更するスライダーがある。 名前的に滑らかさを調節するスライダーということはわかるが、どんなアルゴリズムで滑らかにしてるんだろうと思ったので調べた。

f:id:msdd:20191229172903p:plain
smoothingスライダー

smoothingのアルゴリズム

stack overflowでの回答

stack overflowで回答されているのを見つけた。

stackoverflow.com

ここでの回答によれば、exponential moving average(指数移動平均)というものが使われているらしい。

wikipediaによると、

重みは指数関数的に減少するので、最近のデータを重視するとともに古いデータを完全には切り捨てない(重みは完全にゼロにはならない)。

というものらしい。

時刻tでの値をY[t]とする。時刻tでの指数移動平均をS[t]、係数aとすると、

S_[t] = a * Y_[t-1] + (1 - a) * S_[t-1]

で計算できる。参照元のページも見てみると、 0<=a<1とあり、Y[t-1]はY[t]に置き換えたものもあると書いてある。

tensorboardでの実装

tensorboardのリポジトリでsmoothingしてところ探した。 ここのresmoothDatasetで行っているようだ。

コードで試す

[1, 2, 3, 4, 4, 6, 5, 3]の値にsmoothingしてみる。

scalars=[1,2,3,4,4,6,5,3]

tensorboardのsmoothingの値を0.2にした値は、 [1, 1.833, 2.774, 3.756 ,3.951, 5.59, 5.118, 3.424] となった。

stack overflowにあった関数をpythonで書いたもの

def smooth(scalars,weight):
    last=scalars[0]
    smoothed=[]
    for point in scalars:
        smoothed_val=last*weight+(1-weight)*point
        smoothed.append(smoothed_val)
        last=smoothed_val

    return smoothed

weight=0.2で実行してみる。

smoothed=smooth(scalars,0.2)
print(smoothed)

出てきたものは、[1.0, 1.8, 2.7600000000000002, 3.7520000000000002, 3.9504, 5.59008, 5.118016, 3.4236032000000005] 近い値は、出てきているが微妙に違う。

tensorboardのコード見に行って書いたのが下のもの。前のものと違う点は、 最初の値に0を使っている(last=0)のと、debias_weightを計算して、値を保存するときに、smooth_valをdebia_weightで割っているところが違う。 このdebias使う理由は、コードのコメントにかいてある。詳しくはわからないが、偏りが生じるのでそれをなくしているものと捉えている。

def debias_smooth(scalars,weight):
    last=scalars[0]
    last=0
    smoothed=[]
    for i,point in enumerate(scalars,start=1):
        smoothed_val=last*weight+(1-weight)*point
        last=smoothed_val

        debias_weight=1-weight**i
        smoothed_val=smoothed_val/debias_weight
        smoothed.append(smoothed_val)       

    return smoothed

同様にweigh=0.2で実行する。

smoothed=debias_smooth(scalars,0.2)
print(smoothed)

[1.0, 1.8333333333333337, 2.7741935483870974, 3.756410256410257, 3.9513444302176697, 5.590373783922171, 5.118068711279505, 3.423609404440076]となった。 tensorboard上の値と桁を整えれば一致している。

メモ

stack overflowのコードを式に直したら少し違っていたけど、よく見てみると一緒だった。

wikipediaの式では、

S_[t] = a * Y_[t-1] + (1 - a) * S_[t-1]

となっていた。 コードを直すと、

S_[t] = weight * S_[t-1] + (1 - weight) * Y_[t]

となる。wikipediaの式と違っていたのであれっとなった。

式変形してみる。weight=1-aとおく。

S_[t] = (1-a) * S_[t-1] + a * Y_[t]

順番入れ替えて、

S_[t] = a * Y_[t]  + (1-a) * S_[t-1]

あと違う部分は、Y_[t]の部分だけだが、wikipediaの参照元のページを見てみると、Y_[t-1]Y_[t]に置き換えているものもあるということだったので、 これはこのままでもよさそう。ということで、ほぼ一緒になった。

まとめ

tensorboardのsmoothing処理はexponential moving average(指数移動平均)を用いてsmoothing処理が行われていて、 この指数移動平均は、現在の値に重点を置いてsmoothingする方法である。

参考サイト