LogoMark.png

MachineLearning の変更点


#author("2020-07-11T13:18:10+09:00;2020-07-11T12:06:59+09:00","default:inoue.ko","inoue.ko")
#author("2020-07-11T14:12:37+09:00;2020-07-11T13:18:10+09:00","default:inoue.ko","inoue.ko")
*機械学習
Machine Learning
~

機械学習(Machine Learning:ML) とは、データサイエンス、あるいは人工知能研究における手法の一つで、大量のデータを利用した反復的な学習(人間が行っている学習と同様のプロセス)によって、コンピュータ上にパターン認知や推論のためのモデルを構築する技術です。

コンピュータに与えるのは、学習ルールと、学習素材のデータセットで、コンピュータ自身が大量のデータから推論のルールを自動的に学習します。例えば、ヒト、犬、猫の大量の画像と、その画像がヒトか、犬か、猫かの「答え」です。この画像はヒト、この画像は犬・・と大量に与えていくことで、識別する能力が学習され、その「経験」が豊富になることで、識別能力が上がっていくのです。小さな子供に「これは犬です」、「これは猫です」・・と教えていくのと同じ手順です。

このときコンピュータの中に自動的に出来上がる「入力と出力の関係づけ」のことを「モデル」というのですが、与えるデータが画像であれば、画像認識モデルができあがり、音声を与えつづければ、音声認識モデルができあがります。

従来、物事の判別は人手によるプログラミング( if 条件文)で実装していましたが、現在の AI 、例えば自動運転における画像解析、買い物行動の動作解析、オンラインショップのレコメンド機能、スパムメールの検知など、いわゆるパターン認知機能と呼ばれるものの大半は、この機械学習によって実装されています。

機械学習で可能になるのは大きく2つ、「予測」と「発見」です。
-予測:過去のデータから未知のデータに対する予測を行う(教師あり)
-発見:過去のデータから未知のパターンを発見する(教師なし)

//モデルの生成には、以下のような手法があり、どの手法を用いるかは人間が選んでコンピュータに与えます。この部分でプログラマーは「神」になります。
~

***CONTENTS
#contents2_1

~

**はじめに

***機械学習の位置づけ
「機械学習」の周辺には、データサイエンス、データマイニング、AIなど、様々な用語があり、それぞれの領域が交錯するため、位置付けが理解しづらいものになっています。基本的には「機械学習」はデータサイエンスの一手法で、その応用先として AI がある・・という感じです。
 機械学習と[[データマイニング>DataMining]]の関係ですが、機械学習の立場からは、データマイニングは「教師なし学習」に位置付けれられる手法であり、データマイニングの立場からは機械学習はその一手法・・となります。
 両者の目的の違いから言うと、機械学習の主目的(昨今の話題の中心)が、パターン認知のためのモデルをつくること、すなわち入力データを「既知」の特徴と照合させる(「教師あり」で訓練)ことにあるのに対し、データマイニングの目的は、データから「未知」の特徴を発見する(「教師なし」)ことにある・・と説明することができます。応用先という視点で言えば、機械学習の(今話題の)応用先は AIシステム。データマイニングの応用先は新たなビジネス・・ということができます。
~

***機械学習の応用先
-予測:数値予測、ニーズ・意図予測、マッチングなど
-識別:情報の判断・仕分け・検索、音声・画像の認識、異常検知ど
-実行:作業の自動化、表現生成、行動の最適化など
~
~

**機械学習のタイプ
機械学習には、大きく4つのタイプがあります。
~

***教師あり学習|Supervised learning
教師あり学習とは、学習のときに正解のラベルを使う手法で、''既知の情報を用いて未来を予測する予測器を作ること''を目指します。一般に''問題(説明変数)と答え(目的変数)''のセットからなる大量のデータを必要とします。''主にカテゴリを予測する「分類」と、実数値を予測する「回帰」''があります。手法としては、ニューラルネットワーク、線形回帰などがあります。

今最も実用化が進んでいるのがこの分野です。要するに、大量の過去のデータから現象を記述するモデルを作成し、それを用いて未来に起こることを予測する・・。これは基本的には、私たちの脳が「経験を積むことで、未来予測ができるようになる」という話と同じですが、コンピュータの記憶容量と処理の高速化が進んだことで、それが人知を超えたレベルで実現できるようになったのです。

~

***教師なし学習|Unsupervised Learning
教師なし学習とは、学習のときに正解のラベルを使わずに、機械学習モデルに自力でデータの法則性を見つけさせる手法で、''サンプルをグループ分けする「クラスタリング」や、高次元の変数(多変数)を低次元に減らす「次元削減(次元圧縮)」''などがあります。k-means法、PCA などの手法があります。
~

***半教師あり学習|Semi-supervised learning
半教師あり学習とは、学習の際に少量の正解ラベルつきデータとラベルのない大量のデータを使う手法を指します。正解ラベルつきのデータを用意するのにコストが掛かりすぎる場合などに有効です。

~

***強化学習|Reinforcement learning
強化学習とは、正解ラベルの代わりに「報酬」を使う手法です。とるべき「行動」に無数の選択肢があり、明確な「答え」をあらかじめ与えることが難しい場合、「報酬」の大きな行動に高いスコア、「報酬」の少ない行動に低いスコアを与えていくことで、どう振る舞えば最大の報酬が得られるかを学習する・・というタイプのもので、囲碁や将棋などの AI に利用されています。Q-Learning や DQN(Deep Q Network)といった手法があります。

~
~

**教師あり学習の手法
大きく2種類、主にカテゴリを予測する「分類(クラス分類)」と、実数値を予測する「回帰」があります。
~

***分類
分類(クラス分類)とは、あるサンプルが与えられたときに、そのサンプルが所属するカテゴリを予測するものです。以下のような手法があります。

-''ロジスティック回帰'' > 詳細:[[LogisticRegression]]
&small(注)「回帰」という文字を使いますが、「分類」の手法に属します。);

-''サポートベクターマシン'' > 詳細:[[SupportVectorMachine]]

-''決定木'' > 詳細:[[DecisionTree]]

-''ランダムフォレスト'' > 詳細:[[RandomForest]]

-''ニューラルネットワーク'' > 詳細:[[NeuralNetwork]]
&small(ディープラーニングはこの技術の応用(中間層を増やしたもの)です。);
~

***回帰
回帰とは、あるサンプルが与えられたときに、そのサンプルに関する何らかの数値を予測するものです。例えば、複数の都市サンプルの情報、例えば「人口」、「面積」、「税収」といった特徴と「犯罪率」をセットにしたデータで学習を行い、未知の都市の特徴からその犯罪率(実数値)を予測する・・といったものが回帰の問題です。以下のような手法があります。

-''線形回帰'' > 詳細:[[LinearRegression]]

-非線形回帰

-以下、回帰の手法としても用いられます
--サポートベクターマシン
--ランダムフォレスト
--ニューラルネットワーク
~
~

**教師なし学習の手法

***クラスタリング
クラスタリングはサンプルを自動的にグループ分けする手法ですが、事前にカテゴリーを定義するのではなく、データの特徴のみを使って、それらをいくつかのグループに分ける・・というものです。よく似た言葉に「クラス分類」がありますが、クラス分類はカテゴリーが事前に決まっている「教師あり学習」に属するものです。

クラスタリングでは「いくつに分けるか」という「分類数」のみを分析者が事前に決定して、結果として見えてくる個々のグループに対しては、事後的に命名がなされます。「このデータは◯◯カテゴリーに属する」というような教師データ(事前データ)が存在しないのが、クラスタリングの特徴で、以下のような手法があります。

-''k-means'' > 詳細:[[k-meansClustering]]
-''k-means'' > 詳細:[[k-means]]
~

***次元削減(次元圧縮)
次元削減とは文字通り「データの次元数を減らす」ことですが、例えば「生徒」の学力特性を説明するのに「国語・数学・理科・社会」という4つのデータ(これを4次元データと言います)を使うところを、「理系得点・文系得点」という2つのデータ(2次元)に落とし込んで説明するような操作を意味します。

一般に、説明変数(特徴量)が多いと、対象を捉えて識別することが難しくなりますが、例えば数学と理科の点数のように「連動する(相関が高い)」もの同士をまとめて「理系得点」として一つの数字で表現すれば、対象を捉えやすくなります。次元削減はこのような処理を大量のサンプルを使って自動的に行うものです。以下のような手法があります。

-''主成分分析(PCA)'' > 詳細:[[PrincipalComponentAnalysis]]

-ニューラルネットワーク(オートエンコーダー系)

~
~

**用語解説
***説明変数と目的変数
関数モデルを '''y = f(X) ''' と書いた場合の、X が説明変数で、y が目的変数です((一般に入力の方が数(次元)が多いので y は小文字、X は大文字で書いたりします。y が値とすれば、X(大文字のエックス)はベクトル、 y がベクトルとすれば、Xは行列・・というイメージです。))。

-説明変数:explanatory variable
物事の原因となる変数。一般に X を使います。文献によっていろんな表現がありますが、以下、すべて同じ意味で使用されています。
--特徴量  feature / attribute
--予測変数 predictor variable
--独立変数 independent variable

-目的変数:target variable
物事の結果(予測)となる変数。一般に y を使います。文献によっていろんな表現がありますが、以下、すべて同じ意味で使用されています。
--ラベル  label
--応答変数 response variable
--従属変数 dependent variable

-付記:X vs Y の組み合わせは、以下のパターンが多いようです。
--説明変数 vs 目的変数
--特徴量 vs ラベル
--予測変数 vs 応答変数
--独立変数 vs 従属変数
~

***目的関数と損失関数
教師あり学習では、入力 x に対して成分 w を用いて目的関数 '''y = f ( w , x ) '''を構築するとともに、正解 y に対する損失 '''L ( y , f ( w , x ) )'''を定義して、これが最小となるように成分を調整していきます。
 目的関数の最適化問題を解くことは、すなわち、損失関数(誤差関数)を最小化すること・・と言えます。
 例えば回帰問題では、一般に以下のような「二乗損失」を用います。
-目的関数:'''y = f ( w, x )'''
-損失関数:'''L ( y , f ( w, x ) ) = ΣSUB{i}; ( ySUB{i}; − f ( w , xSUB{i};) ) SUP{2}; '''

~

***活性化関数
ニューラルネットワークにおいて線形変換(重み付き入力の総和)後に最終的な出力を決める関数のことを「活性化関数(Activation Function)」と言います。中間層と出力層では用いる関数が異なるのが一般的で、以下のように分類できます。

-中間層で用いる活性化関数
--''ステップ関数(形式ニューロン)''
結果が閾値θよりも大きいか否かで、出力が単純に0または1の2値に区別されるものです。
''' f( x ) = 0(x≦θ),  1(x>θ)'''
--''線形結合(単純パーセプトロン)''
結果の値にバイアスを加えただけです。出力は線形連続になります。
''' f( x ) = ax + b'''
--''シグモイド関数''
入力した値が大きければ大きいほど1に近づき、小さければ小さいほど0に近づく・・[[ロジスティック関数>LogisticCurve]]の特殊ケースにあたります。[[バックプロパゲーション>Google:バックプロパゲーション]]を伴うニューラルネットワークで使われます。
'''f( x ) = 1 / ( 1 + exp(-x) )'''
--''tanh関数''
出力が−1から1なので出力がゼロになることでシグモイド関数に比べて学習の収束が容易になります。
'''f( x ) = ( exp(x) - exp(-x) ) / ( exp(x) + exp(-x) )'''
--''ReLU(ランプ関数)''
入力が 0以下のときは 0、1より大きいときは入力をそのまま出力します。
''' f( x ) = 0(x<θ),  x(x≧θ)''' あるいは '''f( x ) = max( x, 0 )'''

-出力層で用いる活性化関数
--''ソフトマックス関数''
各出力 f( xSUB{i}; ) の値をすべての '''i''' について合計すると 100% になるもので、例えば画像認識問題で「猫:70%, トラ:20%, 犬:10%」 といったような回答を得たい場合に用います。([[結果表示の事例>https://koichi-inoue.github.io/TensorFlowJS_MobileNet/]])
''' f( xSUB{i}; ) = exp(xSUB{i};) / ΣSUB{j}; exp(xSUB{j}; )'''
--''恒等関数''
最もシンプル、入力値をそのまま出力するものです。
'''f( x ) = x '''
~

***最適化アルゴリズム(オプティマイザ)
ニューラルネットの文脈では、最適化とは「出力の誤差が最小になるように調整すること」を意味します。誤差を表す関数は何らかのカーブを示しますが、このカーブをたどって、最下点に至るように、パラメータを調整するわけです。その方法には様々あります。以下リンクで紹介します。
-[[SGD>Google:最適化 SGD]]:Stochastic Gradient Descent 確率的勾配降下法
-[[Momentum>Google:最適化 SGD]]
-[[Nesterov Accelerated Gradient>Google:最適化 Nesterov Accelerated Gradient]]
-[[Adaptive Learning Rate>Google:最適化 Adaptive Learning Rate]]
Momentum法と異なり、学習率を自動調整することを目指したのが Adaptive Learning Rate を用いた手法です。
Adagrad, RMSProp, Adadelta, Adam, Adamax, Eve,
-[[YellowFin>Google:最適化 YellowFin]]
~
~


***学習用データとテストデータ
機械学習(教師あり)では、手持ちのデータを「学習用データ」と「テストデータ」で分けるのが一般的です。
 手持ちのデータを全て学習用データとして使うと、そのデータに過度に適合したモデルができてしまい(過学習)、現実の予測に使おうとした場合に逆に精度が低くなってしまいます。そこで、一般には学習用データとテストデータに分割して、学習状況をテストデータでチェックしながら、テストデータに対して最も良い性能が出るように調整を繰り返します。
 データの分割には、以下のような方法があります。
-Hold-out:全体を一定の比率(例えば7:3)で分割
-Cross Validation:全体をn個に分割して、n-1個を学習用、1個をテスト用として、これを順にローテーションしながら利用
-Leave One Out:上記の特殊版。1個だけテストデータとしてローテーション


~
~


**サンプルプログラム|手書き文字認識
#image(DataScience/MNIST.jpg,right,30%)
ニュー ラルネットワーク(教師あり学習|分類)の技術で「0 〜 9 の手書き数字認識モデル」を生成するプログラムを紹介します(ライブラリには TensorFlow を使用しています)。手書き数字の画像データ(28 × 28px) と正解ラベルのペアを学習用 60,000個、評価用 10,000個をセットにしたデータサンプル「[[MNIST>http://yann.lecun.com/exdb/mnist/]]」を使用します。
#clear
~

***Python ソースコード
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 ]]
~

***解説
-1) データのインポート ライブラリからデータを読み込みます。
--x は入力画像、 y は正解ラベル。
--train が学習用、test が評価用です。

- 2) 入力画像データのスケール変換
--2次元画像 (28 × 28px) を1次元 (784px) に変形しています。 
--輝度(0〜255)を 最小値 0、最大値1にな るよう正規化しています。

-3) 正解ラベルの対応づけ
0 〜9の正解ラベルをカテゴリーデータに変形しています。

-4) 学習モデルの構築
--モデルには中間層の追加が簡単な Sequential モデルを選択
--入力層は、データ仕様から 784。
--中間層は 64 と設定しています。
ニューロンの出力を判定する活性化関数には relu( ランプ関数 ) を使用。
--出力層は、正解数の 10。
判定には Softmax 関数 を設定しています。

-5) モデルに訓練過程を設定
--model.compile で訓練過程を設定します。
--最適化の手法として、確率的勾配降下法 (SGD)を選択しています。
--損失関数に多値分類 (categorical_crossentropy) を選択しています。

-6) 機械学習の実行(数十秒かかります)
--model.fit で学習開始。
--epochs は学習反復回数 で、ここでは 10 回反復。
--loss は正解とのズレで、 0 に近いほど正解に近い。
--accuracy は正確性で、100% に近いほど正解に近い。

-7) 評価用のデータで正解率を検証
--評価用データに対する正解率を model.evaluate で計算。
--結果、94.3% 正解するモデルができています。 

-8) 混同行列でミスの発生状況を確認
--100 件のテストデータで、実際にどこにミスが生じているかを検証。
--出力された表は、混同行列
---行が予測された数字で、列が実際の正解に対応します。
---対角線上にあるのが正しく分類されたものです。
---対角線外のセルは、誤って予測されたものです。
--表からは、2 と 7、4 と 6、 5 と6を誤認するエラーが確認できます。
~

***付録:JupyterNotebook 
同様のサンプルを ipynb(JupyterNotebook)形式で GitHubに置いています。レンダリングがタイムアウトする場合は、下の nbviewer 経由でご覧下さい。

-GitHub:NeuralNetwork02.ipynb
-nbviewer:NeuralNetwork02.ipynb
~
~

**サンプルプログラム|画像認識
MobileNetの学習済みモデルと [[TensorFlow.js]]を利用して、画像の対象物を推論するサンプルです。手元の画像のドラッグ&ドロップで、対象を推論するサンプルです。上位4件の候補を、その確率とともに表示します(人や人物の顔は対象外なので、人物の画像を投入すると「T-シャツ」や「ネクタイ」が検知されます。)。

-CODE:https://github.com/koichi-inoue/TensorFlowJS_MobileNet
-DEMO:https://koichi-inoue.github.io/TensorFlowJS_MobileNet/

-WebGL経由でGPUを利用するので、古い環境では動かない場合があります。
-認識できる物体のラベル一覧は以下の検索でヒットします。
[[Google:imagenet 1000 classes list]]

~
~

**APPENDIX
***関連ページ
-[[DataScience]]
-[[Data]]
-[[Statistics]]
//-[[MachineLearning]]
-[[NeuralNetwork]]
-[[DataMining]]
-[[ArtificialIntelligence]]
-[[ArtificialIntelligence/Links]]
~
~
~
~