ろむめも

気になったこととか、調べたことをゆるくまとめます。主にプログラミング関連の話題が多いです。

深層学習

以下に学習時のメモをまとめます。

導入

紹介

ディープラーニングは様々な分野で利用されています。ディープラーニングニューラルネットで構成されます。たくさんのノードとパラメータで構成されます。簡単に言えば、例えば2値クラス分類タスクでデータを適切に分類するのがニューラルネットがやっていることです。
分類問題に関して例えば入試の結果と学業成績があるとして、その組み合わせからその学生を入学させるべきか考えます。その2変数の散布図を描くとどのあたりに境界線があるかというのがわかります。そしてその境界線こそがモデルです。ではどうやってその線を見つけるのでしょうか。二変数の直線はw1x1+w2x2+b=0で表すことが出来ます。そして、適切なw1,w2,bを見つけることが出来ればそれが境界線になります。これはニューロンの中で行われている計算と同じです。入力に変数があって、その入力にそれぞれ重みがあり、バイアスを足します。これがニューロンの演算で、その出力値が正か負かによって分類結果を変えます。そしてその分類結果は2値分類の場合ステップ関数のようになります。このステップ関数は後で別の関数に置き換えたりします。
同じようにニューロンは論理演算子としても働くことが出来ます。特にややこしいのはXORですがXORはOR/NAND/ANDの組み合わせで実現できるので、ニューラルネットでも実現することが出来ます。
境界線はどのように決定しますかという所に戻ります。これは境界線を引いて、それに基づいて分類をします。その結果が正しいか間違っているかで判断し、間違っていたら境界線を引き直します。どのように引き直すかというと、間違っている点が境界線の中に入るように境界線を動かします。複数の点がある場合、それらの全てを考慮して値を調整します。また、一気に変えてしまうと値が収束しない場合があるので、学習率と呼ばれる値を係数の変化分に掛けて緩やかに値を変化させていきます。これを繰り返すことで最適な解を求めることが出来ます。
次に例えば特徴量のデータを増やしたとします。この場合は3次元の空間に境界線を引くようなものなのですが、線ではなく面になります。このように入力の次元が増えていくと特徴量の空間は多次元になりますが、やっていることは変わりません。

誤差関数

誤差関数とは境界からの距離を測るものです。特に離散的な誤差関数を使ってしまうと、係数を変えても値が変わらないので、どちらに動かせばいいのかわからなくなります。例えば二値分類問題でyes/noの正解した数だけを評価関数としてしまうと、境界線をどのように動かせばいいのかわかりません。境界からの距離であれば連続値で表すことができるので、誤差関数はそういった連続関数が求められ、微分可能性が重要になります。また、誤差関数は間違えたものに大きなペナルティを与え、正しく分類できたものにはペナルティを与えません。特に間違えた点の距離に応じて値を変えると良いでしょう。

先程の例ではステップ関数でクラス分類を行ってきましたが、活性化関数としてシグモイド関数をつかうと、出力値が連続でかつ値の持ち方がステップ関数のように0~1になります。入力の値が離散的であったとしてもその値をシグモイド関数に入れると連続値にすることができます。これが連続な活性化関数を使う理由の一つです。

ディープラーニングでは多クラス分類も実現することが出来ます。その場合softmax関数を使います。これは出力された確率にもとづいてスコアを算出し、それを多クラス分類のスコアに変換します。単純にアベレージを取っただけでは、スコアが負の場合にどのように取り扱うかが難しい場合があるので、別の方法で変換します。ここでは値を正の値に制限したいので、出てきたスコアのexpを取ります。そして、その和を取って、特定のスコアの値を和で割ります。これをsoftmax関数と呼びます。その値がある意味確率のように働くのです。

ここまでの入力データは数値データでしたが、それ以外の場合はどうしますか。特に複数のクラス分類の場合、1,2,3等の値を入力するのではなく、それぞれのTrue/Falseを一つの特徴量にしてしまいます。例えば3クラス分類であれば3次元のベクトルで表し、それぞれの要素が犬であるかどうか、猫であるかどうか、鳥であるかどうかを表すようなものです。これをOne-Hot Encodingと呼びます。

上記の例でsoftmax関数について説明しました。これはある意味確率のように働きます。これをどのように取り扱うべきか考えますが、確率であれば、私たちがやるのは最尤推定と呼ばれる手法です。最尤推定は分類したそれぞれの点のもっともらしさを求めます。これは例えば確率のような形で表されてもよいです。それをすべての点について掛け算し、その値をスコアとします。このスコアが最も高いところが最もよく分類できている境界線であると決めることができます。これが最尤推定です。最尤決定線では、ほとんどの点を正しく分類することが出来ます。

ではそのスコアはどのように最大化しますか?各点のスコアは確率でした。その確率と誤差関数を結びつけることが出来れば、誤差関数を最小化することが、確率を最大化することにつながるので、そういう観点でこれまでの評価方法を見直します。これまでやってきた確率のようなものはすべてのスコアを掛け算していました。このlogを取ります。すると掛け算のスコアが和になります。ただ、確率なのでlnを取ると1より小さくマイナスになってしまいます。そこで-lnの和を取ることにします。この-lnを取った確率的スコアの各データ点に対する和を取った値のことをクロスエントロピーと呼びます。良いモデルは小さい値になり、悪いモデルは大きな値になります。これは良いモデルでは尤度は大きい値になるので1に近くなります。そのlnを取ると小さい値になるので、その和は値は小さくなります。反対に悪いモデルでは各点の尤度が小さい値になるので0に近い値になります。そのlnを取ると大きい値になるので、その和は大きくなります。また、間違えて分類されたデータ点の値は尤度が低いので必然的に大きな値になります。反対に正しく分類された値は小さい値になります。これは私たちがやりたかった誤差関数の考え方と同じです。即ちこのような誤差関数を定義することで、各点の尤度を最大化するという問題から、クロスエントロピーを最小化する問題に転換することが出来ました。

実際の各試行の中でこのクロスエントロピーを計算するには、試行の目がどちらであったかを考慮する必要があるので、yln(p)+(1-y)ln(1-p)として、yは出たかどうかであり、pは出現確率です。演算には出た時の確率値を加算する必要があるのでこのようにしています。

この演算を多クラスではどのように実装しますか考えます。基本的には同じですが、各試行に対して確率を持っています。実際の試行に対して評価を行うには同じように-yij*ln(pij)をとります。ここでyijはone-hot化したベクトル、M(=j=0toM)はクラスの数を表します。

エラー関数の最小値を探すのに、勾配降下法を考えます。それは重みに対する偏微分による勾配効果計算を行います。ここで、シグモイド関数はとてもいい性質があります。それは微分した形式にもシグモイド関数が登場するので、その値を再度計算する必要がなく、過去のシグモイド関数の計算結果を利用することができます。また、重みに対するエラー関数の偏微分を考えます。エラー関数がこれまで考えてきたような-yln(y_pred)-(1-y)ln(1-y_pred)で、y_pred=sigmoid(Wx+b)で与えられる場合、その偏微分を取ると、-(y-y_pred)*xとなります。このことが意味するのはある場合勾配を降下する際にはその値はラベルから遠ければ大きい値、近ければ小さい値が設定されるという事です。この偏微分による結果に学習率であるαをかけたものを重みに加算します。バイアスも同じようにかさんして、勾配降下していきます。エラーの平均を取っている場合はデータの数で割って平均を取ります。

データの境界線が非線形の場合も基本的には同じですが、非線形を表現できるモデルを使う必要があります。例えばSVMや、ニューラルネットはそれを表現することが出来ます。特にニューラルネットの場合は複数レイヤーを設けることでそれを実現することが出来ます。これはXORを実現するために学んだことと同じです。最初の層は入力レイヤーと呼びます。間のレイヤーは隠れ層と呼び最後の層を出力層と呼びます。例えば、隠れ層で犬と猫と鳥をそれぞれ分類できるものが出来たとすると最終層では犬猫鳥とそれ以外のものを分類できるようになります。レイヤーを深くするとこのような集約のような働きが出来るようになることがあります。多クラス分類をする場合は、クラスの数だけ出力ノードを設けて、それはsoftmax関数を通した値を入て、その最も大きな値を入れるのが良い事が多いです。

誤差の伝搬にはバックプロパゲーションが有効であり、それには合成関数の微分にかんする知識が必要です。





続く。。。。