はじめに
機械学習における教師あり学習では、入力に対してパラメータ
を用いて関数
を構築し、正解データ
に対して損失
を定義し、これを最小化する手続きを取ります。
損失を、色々な
と
の組
に対して計算し、その総和が最小化されるように
を決めることを学習と呼びます。これにより未知のデータ
を入力した時に、それに対する正解を
が出力してくれることを期待するのです。
学習がの最小化という目標に従っている以上、この
をどのような形にするのかが重要になるのは言うまでもありません。
ニューラルネットワーク
ニューラルネットワークでは通常
- 回帰
正解と関数の出力
が近くなるようにする。
- 分類
正解と出力
をそれぞれ確率分布と見なして、確率分布を近づける。
という損失が用いられます。
損失関数を考えるモチベーション
上記の損失関数は「ベストである」という保証はどこにもありません。ただ、手元のデータを表すには、最尤推定という枠組みにおいて上記の形を取るというだけの話です(従って、特別な工夫なしでは必ず過学習すると思っていい)。
ニューラルネットには過学習を防ぐ様々な工夫が存在します。ドロップアウトや正則化などが代表的な例です。
一方で従来の機械学習では損失関数の形に様々な工夫を施すことで、上手いを構築してきました。
実用的な場面に置いては、データ量や計算コストが膨大なディープラーニングより、工夫された機械学習を用いた場合が良いケースもあります(というよりそれで済むならそうしたほうが良い)。
従って、ディープラーニングをやる人でも従来の機械学習の手法について知見は有していなければならないと思っています。
今回は分類に用いられる損失関数について一度まとめておこうと思います。
分類の損失関数
分類では正解データが離散的であり、関数が正解データ
を出力することを目的としています。この際、回帰との大きな違いは、出力値が正解データに近いか否かを、値の差を見るなどの単純な方法では測ることができないという点です。このことは分類問題を考える上では明確に意識して置かなければなりません。
そのことを知るために、2クラス分類における重要な基本的損失関数を先に見ておきます。
以下、正解データとし、学習させたい関数は
とし、データ点
は1つだけとします。(実際にはデータ点を大量に扱うが、1つ1つ計算して和を取るだけ)
0−1損失関数
分類における損失関数の基本
2クラス分類における正解データは
か
のいずれかです。通常、それぞれ負例と正例などと呼びます。この符号は、両者を区別する便宜的なものであり、数値に明確な意味があるわけではないことは意識しておいてください(故に単純に値を見ることに意味が見出だせない)。
この際の損失関数は
と定められます。とは
の符号が「負」なら「−1」を「正」なら「1」を返す関数としておきます。この式の意味するところは、「正解ラベル
と出力
の符号が一致しているならば損失は0(すなわち分類が成功)であり、符号が一致していなければ損失は1」ということです。
ここで見ているのはあくまで「符号」であることに注意してください。
が「10000000」を出力して正例だと分類しても、「0.00000001」と出力して正例だと分類しても構わないということです。分類を誤る場合においても、どのような大きさの値を出力しようが与えられる損失は「1」であることに変わりはありません。
0-1損失の問題点と代理損失
この0-1損失関数の問題は、既に気づかれていると思いますが、分類がギリギリ成功するケースと余裕を持って成功するケース、あるいは同様に失敗するケースに関して区別をできない点です。
しかし、注意して欲しいのは、だからといって分類がギリギリのものと、余裕をもって分類できるものに明確に損失の差を与えるのは必ずしも得策ではないということです。
仮に分類が成功したとしても、境界ギリギリだった場合に強く損失を与える方法を考えた場合には、「既に分類に成功しているようなデータを更に確実にすること」ばかりに学習が集中してしまう場合があるためです。本来の目的は正しく分類をすることです。
学習を行うにおいて本質的な問題点がまだあります。勾配法を今後応用する場合は、損失関数の微分が必要になりますが、この損失関数は微分値が常に0になるという状態であり最適化に適していません。
これらを解決するために、通常の学習では「代理損失」というものが使われます。
色々な損失関数
分類の損失を考える上で重要な「正解と出力の積」
2クラス分類の損失関数を見ていくうえでは、正解と出力
の積
が出てきます。この値は非常に以下に示すように良い性質を持っています。
正解が「1」であり、出力
が正 →
が正
正解が「1」であり、出力
が負 →
が負
正解が「-1」であり、出力
が正 →
が負
正解が「-1」であり、出力
が負 →
が正
となります。まとめればは「分類成功時に正となり、失敗時に負になる値」となります。
ロジスティック損失
ロジスティック回帰で用いられる損失関数です。の中身は先に述べたとおり正解と出力の積であり、分類に成功すれば「正」であり、失敗すれば「負」の値をとります。これは分類に成功しても、境界面ギリギリである場合には小さな損失を与えます。損失が
になることはありません。
指数損失
損失がになることはありません。分類が失敗しているケースに置いて非常に厳しい(非常に大きな値の)損失を与えます。
ヒンジ損失
サポートベクターマシンで用いられる損失関数です。これは分類に成功したとしても境界面付近である場合には損失を与えますが、一定以上離れた場合には損失を0にする働きがあります。
平滑化ヒンジ損失
ヒンジ損失におけるの領域を二次関数に変えて繋げたものです。
損失関数の図示
以下の図では、横軸を正解と出力
の積
とし、縦軸を
とします。
もう一度確認です。
正解は-1か1のみを取ります。
は実数値を出力します。その値の符号が分類結果となります。
従ってが正であれば分類に成功しており、負であれば分類に失敗しています。
正解
が「1」であり、出力
が正 →
が正
正解が「1」であり、出力
が負 →
が負
正解が「-1」であり、出力
が正 →
が負
正解が「-1」であり、出力
が負 →
が正
は大きな値である場合も小さな値である場合も分類結果は符号のみによって決められます。しかし、出力の大きさに関しては、10000と0.1では、「確実に正例」と「恐らく正例」くらいの差異があると考え損失の与え方を変えるのが通常の代理損失の設計方法です。
0-1損失で図の見方を確認
の領域は、分類に成功していることを意味しているので、損失を一切与えません。一方で
の領域では分類に失敗しているため、
という損失を与えます。
結果としてこの損失の値は、分類させたデータ点のうち、何個分類に失敗したのかを表しています。分類失敗の数が0になるのを目指して学習を行っていることになります。
ロジスティック損失
の領域は、分類に成功していることを意味しているのですが、
が0に近いうちは損失を与えるようにします。一方で
の領域では分類に失敗しているため、損失を与えます。更に、負の値が大きい場合には、激しく間違えていると考えて大きな損失を与えるようにします。
この損失関数は0になることは無いので、学習が進んだ末に分類が完全に成功したとしても損失は無くなりません。その場合の損失の大きさというのは、どれくらい確実に分類が上手くいっているのかの指標になります。
ロジスティック回帰で用いられる損失関数です。(名前は回帰だが、これは分類に使われる手法である)
指数損失
ロジスティック損失と考え方は似ていますが、分類の間違いに対して非常に厳しい損失を与えます。正直あまり利用している例を知らないです。
直感的には、間違いに対する損失を強くしておけば学習が速く進みそうな気分にはなりますが、仮に外れ値が紛れ込んでいた場合(つまりデータの一部自体がおかしい場合)に、そのデータの損失に大きく引きずられることとなります。
ヒンジ損失
(分類が間違っている領域)では、出力の絶対値に対して直線的に増加する損失を与えるようにします。ポイントは、
の点から損失を与え始めることです。この点を分類が確実に上手くいっていると言える境目とみなしていることになります(従ってそれ以降は損失は与えません)。
全てのデータ点を分類できるようになり、それが割と確実に分類できている()データばかりになれば損失は0となります(が通常は機械学習では分類精度100%を過学習と疑うべき)。
サポートベクターマシンに用いられる損失関数です。
サポートベクターマシンについては以下
平滑化ヒンジ損失
ヒンジ損失と基本的に考え方は同じです。の領域を二次関数にして、接続を滑らかにしたものです。数値的には、分類が成功しているがその確実性が低いと思われる場合への損失が、ヒンジ損失に比べると寛容です。
比較
基本的なのは「0-1損失」の間違えたら損失を与えるというものです。これは直接的に間違えた数を数えていることになります。他の損失は概ね、間違いの度合いが強いほど損失も強くし、正解していても、境界付近で怪しい場合には小さな損失を与えるようになっています。
通常0-1損失はあまり使われません。(最も単純なパーセプトロンでは学習性能自体を評価するために使われていました)
多くの場合は代理損失を立てて問題を考えていくことになります。
また、これらの損失関数は機械学習のモデルとある程度セットで用いられることが多いようです。
ヒンジ損失はサポートベクターマシンで用いられています。またロジスティック損失は、後の多層パーセプトロンやロジスティック回帰モデルで用いられています。
ロジスティック損失においては、今回のような単に分類結果をで割り振るというところから始まるのではなく、出力値を「あるクラスに属する確率」だと考えられるようにモデル化するところから始め、その最尤推定を考えた際に自然とロジスティック損失が尤度関数として導かれます。
最後に
モデル
の方の話
ニューラルネットの多クラス分類では交差エントロピーが用いられますが、ロジスティック損失と同様に最尤推定という形で導かれます。このようにモデルの出力を確率だと考えて、その確率が高いクラスに分類するという形で分類問題のモデルを考えるものを識別モデルと呼びます。
一方で、サポートベクターマシンのようにとにかく分類をできるような関数を考える場合、これを識別関数と呼びます。
今回は紹介していませんが、他に生成モデルというものもあり、データがあるクラスから生成される確率と、あるクラス自体の確率の積から、分類の確率を求める(ベイズの定理を用いる)モデルもあります。
実際に使う場合の話
確率分布から開始する識別モデルや生成モデルになるほど、損失関数を設計していくという概念は薄くなっていきます(なぜならモデルを立てて、それを上手く推定するということを考えると、自然と損失関数に相当する何かが出てくるため)。そして、そのモデルの意味が明確な状態で設計されていくため、パラメータの意味するところも人間にとって把握しやすいかもしれません。
一方で分類だけが目的の場合は、損失関数からスタートして識別関数をパパっと考えてしまったほうがコストも精度も良いということは多々あります。また、機械学習の発展の上では、とりあえず損失関数からスタートしてみて、分類が上手くいく手法が出来上がり、後から調べたら●●という確率モデルと同等であったという後付である場合の方が多いです(ニューラルネットだって本来は識別関数である。後から確率を出力する識別モデルと考えることができると分かった。実は生成モデルにもできる)。
ですから、識別関数や識別モデル、生成モデルの考え方の違いを明確に理解しつつ、実際に使うときには目的に応じて、簡単な方法(識別関数)から試したほうが良いかもしれません(簡単な方法といえど、結果的に生成モデルと同等の働きであることもある。それを明示していないだけ)。(もちろん目的が、データの生成をすることならば、生成モデルを考えなければならない)
学習の評価は「正解・不正解」だけでない
今回は2クラス分類という基本的なところからはじめました。実際に多クラスへ拡張する場合は、複数の2クラス分類器を組み合わせるなどの方法が取られます。
その際には、単に正解・不正解だけでなく、どんな間違え方をしているのか(どのクラスをどのクラスと間違ってしまったかなど)も重要な指標になってきます。
回帰における損失関数
回帰では、ダイレクトに正解と出力との距離を測ることで損失を決定します。(従って直感的にはこちらのほうが分かりやすい。一方で、モデルは出力を細かく連続的に変える必要がある点で、評価は難しい)