NeuralNetwork
ニューラルネットワーク(Neural Network:NN)とは、人間の脳内にある神経細胞(ニューロン)とその回路網を、人工ニューロンという数式的なモデルで表現したものです。ニューラルネットワークモデルは、シナプスの結合強度を学習によって調整することで、入力データを識別する能力を獲得していきます。
人間の脳の中にはニューロンという神経細胞が約千億個あり、各ニューロンがシナプスと呼ばれる接合部位によって繋がっています。ニューロンは入力される電気信号の総和がある一定の量を超えると発火し、次のニューロンに電気信号を出力します。
この仕組みを模したのが「人工ニューロン(artificial neuron)」で、1943年に神経生理学者ウォーレン・マカロックと数学者ウォルター・ピッツが発表した「形式ニューロン(formal neuron 別名:Threshold Logic Unit )」がその最初のものです。 右図は1個の形式ニューロンの模式図で、中心のCELLが細胞。x1〜xn が入力信号で、それぞれが一定の重み(w:値の大きいものが影響力大)で、細胞に接続されています。その総和が閾値(θ)を超えると、細胞が「発火」して次の細胞へと信号を送り出します。式で表すと以下のようになります。
y = f ( w1・x1 + w2・x2 + ・・・・ + wn・xn - θ )
W = ( w1, w2, ・・wn )は、多次元空間における法線ベクトルで、関数式の内部ではまず、これとデータ X = ( x1, x2, ・・xn ) との内積をとっていることになります。法線ベクトルと同じ向きにあれば内積は + 、反対向きにあれば内積は - で、要するに、上の関数式は、データが存在する空間を分割する多次元空間上の境界(2次元なら直線、3次元なら平面)であるということができます(詳細は次節)。
一般に、出力 y は0または1。つまり、細胞は抑制されるか興奮するかの2状態しかありません。このような細胞が何個も並び、それが何層にも連結されたものがニューラルネットワークになります。
W の調整はどう行うのか、視覚的に説明してみましょう。x0, x1 を2軸とした平面に、データ X (x0,x1) が散布されていて、それらがTYPE A と TYPE B の2クラスに分類できる状態を仮定します(下図を参照)。
以下の式は、原点を通る直線で、その法線ベクトルは(w0, w1)です。
w0・x0 + w1・x1 = 0
図の状態を仮定して識別問題を考えた場合、w0, w1 が適切な値をとると、データは直線によってきれいに識別されることになります。学習による最適化とは、境界線の位置を学習データを読みながら調整する、すなわちこの場合、法線ベクトルの向きを回転させて2つのタイプの境界に位置するように調整する作業であるということができます。
(x0,x1)と法線ベクトルの内積 = w0・x0 + w1・x1 を計算すると同時に、それを正解ラベル( 1:TYPE A , -1:TYPE B )と照らすと、境界線が正しく2者を分離しているかどうかを判定することができます。
つまり、ひとつのサンプルについての判定とその後の作業は以下のように記述することができます。
修正は、以下のように行います。正解ラベル を学習率( Learning_Rate )を 0.1 とすると、学習は以下の式で実現できます。
W = W + X * 正解ラベル * 0.1
正解ラベルが 1, -1 に設定されていることで、2種類のエラータイプに対して、同じ計算式を適用できるわけです。
学習率とは「どの程度強く修正をかけるか」を意味する値で、これは人間が設定するしかない・・という意味で、ハイパーパラメータといいます。
以上、学習率を正しく見極めた上で、この手順で、データを読んでは修正を繰り返せば、境界線は正しい位置に収まります。
一般に高校の数学では、平面の式を \( z = ax + by \) のように書きますが、この式は次元を拡張して考えることができます。
右図はニューラルネットワークのイメージです。Input Layer(入力層)は、最初のデータが入ってくる部分、Hidden Layer(隠れ層)は入力信号を受けて様々な興奮状態をつくる中間処理機関、そして Output Layer(出力層)は結果としての興奮状態を表現する部分す。例えば、気温、湿度、現在時刻という3種類のデータから、1時間後が「晴れている」か「雨が降る」かを予測する(ちょっと無理がありますが例え話です)という場合は、入力層が3、出力層が2となるモデルをつくって、過去の大量の気象データから、気温・湿度・時刻(説明変数)、そして 1時間後の天気(目的変数)というデータセットをつくって学習させることになります。
ニューラルネットワークにおいて線形変換(重み付き入力の総和)後に最終的な出力を決める関数のことを「活性化関数(Activation Function)」と言います。中間層と出力層では用いる関数が異なるのが一般的で、以下のように分類できます。
ニューラルネットの文脈では、最適化とは「出力の誤差が最小になるように調整すること」を意味します。誤差を表す関数は何らかのカーブを示しますが、このカーブをたどって、最下点に至るように、パラメータを調整するわけです。その方法には様々あります。以下リンクで紹介します。
ニューラルネットワークの基本的なアイデアは3層構造ですが、中間層の数を数十〜百段階程度まで増やして、多段階の神経接続で出力を得よう・・という発想から誕生したのがディープラーニングです。多層化に耐えられるだけの計算力(演算速度向上とメモリの増大)が実現したことで、現在の人工知能はこの技術が主役になっています。
ディープラーニング を成立させるには、入力と出力のデータセット、言い換えれば、学習のための「問題と答え」を大量に用意して、それを読み込ませることが必要ですが、これを実現したのが、現代のインターネットです。例えば、インターネット上には大量の画像とそれにタグ付けされた単語が存在します。これを使えば、「この画像は犬」、「この画像は猫」という学習素材が大量に得られます。画像認識システムはこれらを使って、認識能力を高めています。
以下の5つの構造があります。
Iris は、植物学者 R. Fisher による「あやめ」のデータで、統計ソフトの練習用として最も有名です。 Iris setosa、 Iris virginica、Iris versicolor 3種について、がく片の長さ、がく片の幅、花弁の長さ、花弁の幅の4つの計測データが、各 50、計 150 件含まれます。
ipynb(JupyterNotebook)形式で、GitHubに置いています。
以下の項目をもつ150の計測データ
手書き数字の画像データ(28 × 28px) と正解ラベルのペアを学習用 60,000個、評価用 10,000個をセットにしたデータサンプル、MNISTを使用します。
以下に、サンプルを掲載しています。
手書き文字認識用のサンプルデータ
MobileNetの学習済みモデルと TensorFlow.jsを利用して、画像の対象物を推論するサンプルです。手元の画像のドラッグ&ドロップで、対象を推論するサンプルです。上位4件の候補を、その確率とともに表示します(人や人物の顔は対象外なので、人物の画像を投入すると「T-シャツ」や「ネクタイ」が検知されます。)。
ml5.js というJavaScriptAPI を利用した画像の分類その他について、以下のページにまとめています。
> ml5.js
サンプルプログラム1で紹介した「Iris の分類」を TensorFlow と Kerasを用いて実装した例です。
ipynb(JupyterNotebook)形式で、GitHubに置いています。
以下の項目をもつ150の計測データ
入力層4、中間層32、出力層3 で構築しています。
model = Sequntial() model.add(Dense(32, input_dim=4)) model.add(Activation('relu')) model.add(Dense(4)) model.add(Activation('softmax'))
サンプルプログラム2で紹介した「手書き文字認識」を TensorFlow と Kerasを用いて実装した例です。
以下に、サンプルを掲載しています。
手書き文字認識用のサンプルデータ
入力層 784、中間層 64、出力層 10(1-hot ベクトル)
オプティマイザーを2種類試しています。
mnist.py などの Python ファイルとしてお試し下さい。
#1. Load Data from tensorflow.python.keras.datasets import mnist (x_train, y_train), (x_test, y_test) = mnist.load_data() #2. Reshape X x_train = x_train.reshape(60000, 784) x_test = x_test.reshape(10000, 784) x_train = x_train/255. x_test = x_test/255. #3. Reshape Y from tensorflow.python.keras.utils import to_categorical y_train = to_categorical(y_train, 10) y_test = to_categorical(y_test, 10) #4. Model Setting from tensorflow.python.keras.models import Sequential from tensorflow.python.keras.layers import Dense model = Sequential() model.add( Dense( units=64, input_shape=(784,), activation='relu ') ) model.add( Dense( units=10, activation='softmax') ) #5. Model Compile model.compile(optimizer='sgd', loss='categorical_crossentropy', metrics=['accuracy']) #6. Train model.fit(x_train, y_train, epochs=10, batch_size=32, verbose=2, validation_split=0.2) #7. Result : Accuracy score = model.evaluate(x_test, y_test, batch_size = 1) print("accuracy =", score[1]) #8. Check 100 Test Data : Confusion Matrix import numpy as np from sklearn.metrics import confusion_matrix predict_classes = model.predict_classes(x_test[1:100,]) true_classes = np.argmax(y_test[1:100], 1) print(confusion_matrix(true_classes, predict_classes))
Epoch 1/10 - 2s - loss: 0.7345 - acc: 0.8129 - val_loss: 0.3914 - val_acc: 0.8964 Epoch 2/10 - 1s - loss: 0.3720 - acc: 0.8965 - val_loss: 0.3191 - val_acc: 0.9114 Epoch 3/10 - 1s - loss: 0.3199 - acc: 0.9099 - val_loss: 0.2861 - val_acc: 0.9203 Epoch 4/10 - 1s - loss: 0.2905 - acc: 0.9183 - val_loss: 0.2666 - val_acc: 0.9260 Epoch 5/10 - 1s - loss: 0.2693 - acc: 0.9239 - val_loss: 0.2497 - val_acc: 0.9315 Epoch 6/10 - 1s - loss: 0.2515 - acc: 0.9295 - val_loss: 0.2384 - val_acc: 0.9339 Epoch 7/10 - 1s - loss: 0.2364 - acc: 0.9335 - val_loss: 0.2252 - val_acc: 0.9379 Epoch 8/10 - 1s - loss: 0.2231 - acc: 0.9370 - val_loss: 0.2159 - val_acc: 0.9404 Epoch 9/10 - 1s - loss: 0.2119 - acc: 0.9401 - val_loss: 0.2071 - val_acc: 0.9430 Epoch 10/10 - 1s - loss: 0.2018 - acc: 0.9427 - val_loss: 0.1999 - val_acc: 0.9453 10000/10000 [==============================] - 2s 176us/step accuracy = 0.9434 [[ 8 0 0 0 0 0 0 0 0 0 ] [ 0 14 0 0 0 0 0 0 0 0 ] [ 0 0 7 0 0 0 0 1 0 0 ] [ 0 0 0 11 0 0 0 0 0 0 ] [ 0 0 0 0 13 0 1 0 0 0 ] [ 0 0 0 0 0 6 1 0 0 0 ] [ 0 0 0 0 0 0 10 0 0 0 ] [ 0 0 0 0 0 0 0 14 0 0 ] [ 0 0 0 0 0 0 0 0 2 0 ] [ 0 0 0 0 0 0 0 0 0 11 ]]