自然言語処理勉強結果「ニューラルネットワーク」

自然言語処理学習結果

前回まで、自然言語処理における
単語の意味理解について解説していた。

今回もその手法の一つ…ではない。

というのも、それを解説するために、
また機械学習に戻らなければいけない。

今回は、機械学習における
ニューラルネットワークというものを解説しよう。

なお、本記事での目的としてはこれを使えることとする。

…実は、一部理解が追い付いていない部分がある。

なので、あくまで使えるように、ということだ。

今後もこのあたりを深掘りして勉強していくので、
分かったら追記、あるいは別記事で補足するとしよう。

なお、本講座は以下の本を参考に進めている。

もしよかったら、中身を覗いてみて欲しい。

Javaで学ぶ自然言語処理と機械学習
Javaで学ぶ自然言語処理と機械学習
スポンサーリンク

ニューラルネットワーク

ニューラルネットワークとは

ニューラルネットワークとは、
人の脳で行われている情報処理をモデル化したもの

教師あり学習の一つだ。

ちょっと、人の脳のお話をしよう。

人の脳は、1000億個くらいのニューロンという
ものが存在し、これが情報処理を行っている。

このニューロンは、他のニューロンから
信号を受け取り、その内容によって
他のニューロンにまた信号を送る

簡単に言ってしまうと、
これを機械で再現しよう、というのが
ニューラルネットワークである。

階層型ニューラルネットワーク

階層型ニューラルネットワークは単純なもので、
以下3層からなる。

  • 入力層
  • 中間層(隠れ層)
  • 出力層

それぞれの層で、ユニットと呼ばれるものが存在する。

このニューラルネットワークへ入力するものは、
ベクトルだ。

また、出力もベクトルとなる。

ただし、その次元数(ベクトルの要素数)は
異なっていても問題がない

入力層のユニット数を\(n\)、
中間層のユニット数を\(l\)、
出力層のユニット数を\(m\)とした場合の
概要図を以下に示そう。

階層型ニューラルネットワークの概要図

処理の流れとしては、
まずn個の要素を持つベクトルが入力される。

すると、中間層の\(u_i\)でその入力を受け取り、
バイアス項と呼ばれるパラメータを含めた計算式で、
ここでの出力\(o_i\)を決定する。

そして、出力層で\(u’_i\)としてここでの入力を受け取り、
再度計算して最終的な出力\(o’_i\)を決定する。

なお、図には入れてないが、
各ユニットを結ぶ辺にも重みが付けられている

実際の学習時には、
この辺の重みを調整していくことになる。

この中で使う、シグモイド関数と呼ばれる
関数を先にご紹介しよう。

シグモイド関数

これは、以下の式で示される関数だ。

$$f(x) = \frac{1}{1 + e^{-x}}$$

これは、入力を0より大きく、
1未満の範囲に写像してくれる関数だ。

どうやって使うかは、
実際の計算の中で提示しよう。

ニューラルネットワークの計算

まずは、単純にこの計算方法を見ていこう。

先に示した通り、
入力はベクトル\(x = (x_1, x_2, …, x_n)\)だ。

最初は、中間層への入力\(u_j\)を見てみよう。

ここに入力される値は、
以下の計算式で求められる。

$$u_j = \sum_{i = 1}^n w_{ji}x_i + b_j$$

ここで、\(w_{ji}\)が辺の重みだ。

入力層の\(x_i\)から、中間層の入力\(u_j\)に繋がっている
辺の重みを、\(w_{ji}\)で表している。

さらに、\(b_j\)というやつが、バイアス項だ。

次に、中間層の出力\(o_j\)を見る…が、
ここで出てくるのがシグモイド関数だ。

単純に、入力\(u_j\)をシグモイド関数へ入れた
結果を\(o_j\)とする。

$$o_j = f(u_j) = \frac{1}{1 + e^{-u_j}}$$

ここまで大丈夫だろうか。

大丈夫なら、出力層への入力\(u’_k\)を見ていこう。

とはいえ、ここでやっていることは
中間層へのものと全く同じだ。

入力がベクトル\(x\)からベクトル\(o\)に変わって、
また辺の重みも変わる。

中間層の\(j\)番目と出力層の\(k\)番目を
結ぶ重みを、\(w’_{kj}\)とする。

これで、出力層の\(k\)番目の入力\(u’_k\)、
出力\(o’_k\)
を求めると、

$$u’_k = \sum_{j=1}^l w’_{kj} o_j + b’_k$$

$$o’_k = f(u’_k) = \frac{1}{1 + e^{-u’_k}}$$

となる。

…さて、ちょっとこのままだと計算がしづらい。

というのも、二種類のパラメータ…
バイアス項辺の重みを学習しなければ
いけないからだ。

そこで、以下のように考える。

新たに0番目の入力\(x_0\)を追加し、
そこには常に1が入ってくるとする。

また、そこから\(j\)番目の中間層に向かう
辺の重みを\(w_{j0}\)
と置こう。

そして、この\(w_{j0}\)が\(b_j\)と等しいと置くと、
なんと式から\(b_j\)を消すことができる

どういうことかというと、式変形でお見せしよう。

$$
\begin{eqnarray}
u_j & = & \sum_{i = 1}^n w_{ji}x_i + b_j \\
& = &\sum_{i = 1}^n w_{ji}x_i +w_{j0}x_0 \\
& = &\sum_{i = 0}^n w_{ji}x_i
\end{eqnarray}
$$

こうなるわけだ。

中間層から出力層に向けても同じことができるので、
ここから先はバイアス項はなしで考えよう。

誤差逆伝搬学習

ここからが、学習の内容だ。

階層型ニューラルネットワークの学習は、
入力データを一つずつ入力層から入れて、
出力層のデータと正解データを比較し、
誤差を小さくなるように辺の重みを変化させる、
ということを繰り返す。

この辺の重みの調整は、
まず出力に直接影響を与える
中間層、出力層の間の辺の重みを調整し、
次に間接的に影響を与える
入力層と中間層の間の辺の重みを調整する。

この手法のことを、誤差逆伝搬法と呼ぶ。

…実はこのあたりがまだ理解不足だ。

調べたところ、
この誤差逆伝搬法あくまで一般的な手法の一つで、
それを今回学習に利用している、らしい。

詳細が知りたい方は、
調べれば出てくるのでそちらを参照してほしい。

ここでは、結果の数式だけお見せしよう。

前提として、
入力したベクトル\(x = (x_1, x_2, …, x_n)\)に対する
正解データが\(y = (y_1, y_2, …, y_m)\)とする。

このとき、\(j\)番目の中間層と\(k\)番目の出力層を繋ぐ
辺の重み\(w’_{kj}\)は、以下の式で更新される。

$$w’_{kj} – \eta \delta’_ko_j$$

ただし、\(\delta’_k\)は、

$$\delta’_k = (o’_k – y_k)(1 – o’_k)o’_k$$

で表される。

また、\(\eta\)は学習率と呼ばれる値で、
重みを1回にどの程度変化させるかの度合いを表す。

次に、\(i\)番目の入力層と\(j\)番目の中間層を繋ぐ
辺の重み\(w_{ji}\)は、以下の式で更新される。

$$w_{ji} – \eta \delta_j x_i$$

ただし、\(\delta_j\)は、

$$\delta_j = (\sum_{k=1}^mw’_{kj}\delta’_k)(1-o_j)o_j$$

で表される。

…ここで一度力尽きてしまったので、
詳細な解説は理解できてから行おう。

とりあえず、なんとなくの流れを
理解してもらえれば大丈夫だ。

おわりに

今回はニューラルネットワークについて説明した。

ちょっと理解が及ばず、
中途半端な形になってしまい、申し訳ない。

ただ、ここで詰まっていてもいけないので、
いったん先に進もう。

次回は、これを使った単語の意味理解を簡単に説明する。

…というのも、結局このあたりもツールで行えたり、
行った後のデータも公開されていたりするのだ。

本当は根本を理解した方がいいのだが、
使えるならいったんはそれで進めよう、という考え方だ。

今回の補足は…理解できたらするとしよう。

コメント

タイトルとURLをコピーしました