TensorBoardにおけるデータのSmoothingのアルゴリズム
はじめに
tensorboardでスカラー表示のグラフのところに、smoothingを変更するスライダーがある。 名前的に滑らかさを調節するスライダーということはわかるが、どんなアルゴリズムで滑らかにしてるんだろうと思ったので調べた。
smoothingのアルゴリズム
stack overflowでの回答
stack overflowで回答されているのを見つけた。
ここでの回答によれば、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する方法である。