HELLO CYBERNETICS

深層学習、機械学習、強化学習、信号処理、制御工学、量子計算などをテーマに扱っていきます

機械学習で抑えておくべき損失関数(回帰編)

 

 

follow us in feedly

f:id:s0sem0y:20170619064923p:plain

 

 

はじめに

機械学習における教師あり学習では、入力xに対してパラメータwを用いて関数f(w,x)を構築し、正解データtに対して損失L(t,f(w,x))を定義し、これを最小化する手続きを取ります。

 

損失L(t,f(w,x))を、色々なxtの組(x_i,t_i)に対して計算し、その総和が最小化されるようにwを決めることを学習と呼びます。これにより未知のデータx_?を入力した時に、それに対する正解をf(w,x_?)が出力してくれることを期待するのです。

 

学習がLの最小化という目標に従っている以上、このLをどのような形にするのかが重要になるのは言うまでもありません。

 

ニューラルネットワーク

ニューラルネットワークでは通常

 

  • 回帰

    \displaystyle L(t,f(w,x))=\sum_i(t_i-f(w,x_i))^2

    正解tと関数の出力f(w,x)が近くなるようにする。

  • 分類

    \displaystyle L(t,f(w,x))=-\sum_i t_i\log(f(w,x_i))

    正解t_iと出力f(w,x_i)をそれぞれ確率分布と見なして、確率分布を近づける。

 

という損失が用いられます。

 

損失関数を考えるモチベーション

 

上記の損失関数は「ベストである」という保証はどこにもありません。ただ、手元のデータを表すには、最尤推定という枠組みにおいて上記の形を取るというだけの話です(従って、特別な工夫なしでは必ず過学習すると思っていい)。

 

ニューラルネットには過学習を防ぐ様々な工夫が存在します。ドロップアウトや正則化などが代表的な例です。

 

s0sem0y.hatenablog.com

 

 

一方で従来の機械学習では損失関数の形に様々な工夫を施すことで、上手いf(w,x)を構築してきました(これが結果的に正則化と同じ効力を持っていたりする)。

 

実用的な場面に置いては、データ量や計算コストが膨大なディープラーニングより、工夫された機械学習を用いた場合が良いケースもあります(というよりそれで済むならそうしたほうが良い)。

 

従って、ディープラーニングをやる人でも従来の機械学習の手法について知見は有していなければならないと思っています。

 

今回は損失関数について一度まとめておこうと思います。

 

回帰の損失関数

回帰では正解データtが連続的であり、関数f(w,x)tになるべく近づくことを目的としています。遠ければ遠いほどペナルティを与える形式になっている必要があります。

以下簡単のため、入力するデータ点がxで学習させたい関数はf(w,x)、正解データがtとしますが、データ点は1つだけとします。(実際にはデータ点を大量に使うが、1つ1つ計算して和を取るだけ)

 

色々な損失関数

 

二乗損失

 

L=(t-f(w,x))^2

 

いわゆる最小二乗法。データの背景に正規分布を仮定した際の最尤推定になります。

 

τ-分位損失

 

L = (1-τ)\max(f-t,0) + τ\max(t-f,0)

 

分位点回帰に用いられます。

fが正解tの上にいるのか下にいるのかで損失の大きさが変わる点が特徴です。

 

Huber損失

ある正のδに対して

 

L= (t-f(w,x))^2 if f\in[t-δ,t+δ ]  else  2δ(|t-f|-\frac{δ}{2})

 

ロバスト回帰に用いられます。

fが正解tの近く(±δ内)であれば二乗、そうでなければ絶対値を少し工夫したものを損失として用います。

 

ε-感度損失(ε-許容損失)

ある正のεに対して

 

L=\max(|t-f(w,x)|-ε,0)

 

サポートベクター回帰に用いられます。

ftの近く(±ε内)であれば損失はなし、あれば絶対値からε引いたものを損失として用います。

 

 

損失関数の図示

直感的に損失の大きさを見るためには図示するのが一番良いでしょう。以下では、f-tを横軸に(つまりf-t=0⇔f=tが原点)、損失Lを縦軸にプロットします。

 

二乗損失

L=(t-f(w,x))^2

f:id:s0sem0y:20170619061415p:plain

二乗損失では、f-t=0からずれるに従って、そのズレの二乗の損失を与えます。例えば、f-t=2⇔f = t+2という値を出している場合には損失が4であると考えることになります。この損失は左右対称です。(正へのズレも負へのズレも同じ扱い)

 

τ-分位損失


L = (1-τ)\max(f-t,0) + τ\max(t-f,0)

f:id:s0sem0y:20170619061655p:plain

この損失ではf-t=2⇔f=t+2となっている場合とf-t=-2⇔f=t-2となっている場合では与える損失の大きさが異なっています。図のケースではfが大きくなりすぎた場合の方により重い損失を与えています。この度合いを調整するのがτの役割というわけです。

 

Huber損失

L= (t-f(w,x))^2 if f\in[t-δ,t+δ ]  else  2δ(|t-f|-\frac{δ}{2})

f:id:s0sem0y:20170619062019p:plain

この損失では、ズレがある範囲内ならば二乗損失を、それより外なら直線上に増加する損失を与えます。先ほど式が若干複雑に見えたかもしれませんが、それは単に線を滑らかに繫げるための調整をしているだけです。

一定範囲内に対しては厳しく損失を与え、逆に外の方では損失の増加が直線的になります。こうすることで学習データに仮に外れ値があった場合に、それらに引っ張られる学習が抑えられることとなります。

 

今回は分かりやすくδ=1と設定しています。

 

ε-感度損失(ε-許容損失)

L=\max(|t-f(w,x)|-ε,0)

f:id:s0sem0y:20170619062420p:plain

この損失ではズレが一定以内なら損失を与えないということにします。つまり、ズレが一定以内に収まっているデータは学習しないということです。上手く回帰ができていないデータに対してのみ重点的に学習を進めていくことになり、細かいことは気にしない学習になります。

ただし、悪いデータに対して重点的に学習をするうちに、真の関数に近づいていき、結果的に良いデータへの精度も良くなるかもしれません。これは、学習で集めたデータによりけりということになります。

 

今回は分かりやすくε=1と設定しています。

 

比較

f:id:s0sem0y:20170619064923p:plain

 

これだけ損失関数(すなわち学習の指標)が違えば学習結果も異なってくるでしょう。どのデータにどの損失関数を用いるかは通常は重要なことです。手元にあるデータに応じて適した損失関数が異なってくるはずです。

 

損失関数の使い分け1

基本的には回帰に置いては二乗損失を用いることになると思います。

 

しかし二乗損失は非常に外れ値に弱い性質を持っています。機械学習では正解データから明らかに大きく外れるデータ(それはたまたま混入してしまった例外で、データの本質ではない)であったとしても学習が行われます。二乗損失は、外れているほど二乗で損失を大きくするがゆえに、学習に大きな影響を与えてしまいます。

 

外れ値のデータに無理やり合わせようとするが故に過学習が起こってしまうわけです。

 

これは本来「過学習」と呼ぶべきものではないかもしれません。単に間違った学習です。しかし、データに対して外れ値を手作業で全て弾くのも難しい話であるため、それらも学習対象であると考えた場合には、手元のデータにフィッティングさせすぎ(過学習)と考えることもできます。

 

その点Huber損失は正解付近は二乗を、遠いところには線形の損失を考えます。学習を考慮するのですが、やけに大きな損失として考えることを防ぐことができるため、ロバストな推定が可能だとされています。

 

損失関数の使い分け2

今度は正解付近に値が集まっている場合を考えましょう。既にある程度は的を得た回帰が得られたとしても、機械学習では完全に一致しない限りは学習を進めようとします。

 

そのようなことをしたが故に、手元のデータに寸分の狂いもなく完全にフィットしてしまい、結果として過学習が起こります(本来の過学習)。手元の学習データは完璧ではありません。おそらく多少のノイズも含んでいるでしょう。

 

データの背景にある本質的なものではなく、関係のないノイズまでも学習してしまい、回帰曲線を無理矢理創りだしてしまうのです。

 

ε-感度損失では、ε内に収まっている場合にはそれ以上学習をさせないようにします。これは言い換えれば、その中でフィットしないのはデータ自体が完璧ではなく、ノイズが要因であると考えているということです。それ以上無理に合わせる必要はないと機械学習側に明示することになります。

 

この損失関数はサポートベクター回帰の基本になっており、疎な解が得られることでも知られています。(サポートベクター回帰ではHuber損失が使われる場合もある。これは結局正解付近をのように扱うかの違いだと言える)。

 

 

損失関数の使い分け3

手元にあるデータにバイアスが掛かっていることが分かっているとしましょう。

 

例えば、入力xから導かれる正解データtは、今回に限ってはやや高い値になっているような状況を考えます(今年はやけに景気が良かったので、株価tは高めに出ている。しかしxから導かれる株価の傾向は知りたいなど)。

 

すると普通に二乗損失で回帰をしてしまうと、高めに見積もられていることが分かっているにも関わらず、その値を参考にして回帰が行われてしまいます。

 

これは二乗損失で得られる結果が、背景に正規分布があるとした場合の平均値(期待値)を計算していることに相当するからです。だいたい分布しているデータ点の真ん中くらいに線が引かれるという結果が得られます。

  

s0sem0y.hatenablog.com

 

そういった場合に、τを使って分位点損失を用いれば、上にずれている場合と下にずれている場合の損失の与え方を調整できるため便利です。

 

今回のケースでは、学習データであるtが高めになっていることが分かっているため、回帰で得るf(w,x)に関しては、tより小さい値になっている場合には妥当であると考えた方がよく、

 

L = (1-τ)\max(f-t,0) + τ\max(t-f,0)

 

においてτは小さめにしたほうが良いでしょう。逆にfτを超えている場合には損失の重みを増やしたほうが良いわけです。

 

以下の記事が参考になります。(R使わなくとも読めばある程度分かる)

qiita.com

 

 

最後に

今回紹介したものはほんの一例です。しかし、最低限知っておいて損はないものを挙げました。ディープラーニングを学ぶことが目標だったとしても、従来手法に関して学んでおくことも有益でかつ大切なことです。

 

次は分類に関する損失関数についてもまとめます。

この話に関しては以下の記事も是非覗いてみてください。 

s0sem0y.hatenablog.com

 

分類に関する損失関数

 

s0sem0y.hatenablog.com