現場で潰しが効くディープラーニング講座（オンライン）機械学習レポート課題

機械学習： 
「第 1 章：線形回帰モデル」
入力ベクトルの各要素は、説明変数（特徴量）、出力は、スカラー値（目的変数）と呼ぶ。線形回帰モデルとは、教師あり学習で、入力とm次元パラメータの線形結合（データを直線で表すもの）を出力するモデルであり、言い換えると、説明変数とパラメータベクトルの内積に切片を足し合わせたものを出力するモデル。入力ベクトルが多次元でも出力は１次元（スカラ）となる。出力されたデータは、回帰直線に誤差が加わり、観測されていると仮定。
パラメータの推定は、平均二乗誤差（MSE）で行い、MSEは、回帰直線との距離を示す。最小二乗法とは、学習データの平均二乗誤差を最小とするパラメータを探す方法で、その最小化は、その勾配が0になる点を求めれば良いので、平均二乗誤差を微分して求める。なお、最尤法により、パラメータを求める方法もあるが、回帰係数の結果は、同じとなる。

「第 2 章：非線形回帰モデル」
回帰関数として、基底関数（多項式関数、ガウス型基底関数、スプライン関数等）という既知の非線形関数とパラメータベクトルの線形結合を使用し、未知パラメータは、最小二乗法や最尤法により推定。
非線形関数の計画行列を作成して、予測値を計算する。
過学習（予測モデルが学習データに対して、小さな誤差は得られたが、テスト集合誤差との差が大きい場合）は、正則化法で回避する。
正則化法は、一定の制約（ridge推定量、Lasso推定量）のもとで、MSE（平均二乗誤差）を最小にする点（最小二乗推定量）を求めるもの。言い換えると、モデルの複雑さに伴って、その値が大きくなる「ペナルティ項（正則化項）」を課した関数の最小化を考えるもので、ペナルティ項がなくなると、最小二乗推定量となる。
縮小推定（パラメータを0に近づけるように推定）とスパース推定（いくつかのパラメータを0に推定）があり、スパース推定のメリットは、変数制約を推定と同時にすること。
正則化パラメータは、クロスバリデーション（交差検証）で選択するが、制約面の度合いは、正則化パラメータの強さによって決まる。
限られた手元のデータを学習用とテスト用に分け、予測精度や誤り率を推定するために使用する方法を「ホールドアウト法」という。テストの精度と学習の精度がトレードオフの関係になるため、手元に大量のデータがある場合を除いて、良い性能評価を与えないという欠点がある。
ホールドアウト法の欠点を補うものとして、クロスバリデーション（交差検証）がある。
これは、手元の各クラスのデータをそれぞれｍ個のグループに分割し、ｍ－１個のグループのデータを活用して識別器（クラシファイヤー）を学習し、残りの一つのグループの
データでテストを実行するもの。これをｍ回繰り返して、それらの誤り率（平均二乗誤差）の平均を性能予測値とする。すべてのイテレーターで、学習用と検証用のデータが異なり、また、手元にある全てのデータを学習とテストに利用するので、予測精度が高い。
全てのパターンのクロスバリデーションの値を算出し、CVの値を比較し、それが一番小さいモデルを予測誤差の意味で良いモデルとして商用化する。→「ハンズオン？？」
「第 3 章：ロジスティック回帰モデル」
分類問題を解くための機械学習モデルであり、入力からそのラベルを予測するシステムを構築するもので、入力とパラメータの線形結合をシグモイド関数に入力し、出力は、y=1になる確率の値になる。
ある入力とパラメータの線形結合の結果をロジスティック関数の入力とし、出力が１になる確率を表現するもの。ロジスティック関数のうち、シグモイド関数は、出力は、必ず０～１の間の値をとること、シグモイド関数の微分は、シグモイド関数自身で表現することが可能なこと（尤度関数の微分を行う際にこの事実を利用する）に特徴がある。
なお、機械学習では、MSE（平均二乗誤差）を最小にするパラメータを作ることが重要であり、目的関数（MSE（平均二乗誤差））の微分が必要となる。
ロジスティック回帰モデルとは、データのパラメータに対する線形結合の内積をシグモイド関数の入力とし、出力は、未知のデータが与えられたときのy=1になる確率に対応している。データは、確率が0.5以上であれば、１、それ未満であれば、0とする。
尤度関数を最大化するよりも、対数尤度関数を最大化する方が計算しやすい。これは、積が和、指数が積の演算に変換できること、対数尤度関数が最大になる点と尤度関数が最大になる点は同じであること、平均二乗誤差は、最小化であることから、対数尤度関数にマイナスをかけて「最小化」という指標で統一する。
ロジスティック回帰モデルでは、最尤法を使うため、対数尤度関数をパラメータで微分でして0になる値を求める必要があるが、この値を求めることは困難であるので、勾配降下法（反復学習により、パラメータを逐次的に更新するアプローチ、学習率ηというハイパーパラメータで、モデルのパラメータの収束しやすさを調整する特徴がある）により、対数尤度関数を係数とバイアスに関して微分する。パラメータが更新されなくなった場合、それは、勾配が0になったということで、反復学習で探索した範囲では、最適解が求められたことになる。η学習率は、収束のしやすさを示すもの。
勾配降下法の問題点は、パラメータを更新するのに、ｎ個全てのデータに対する和を求める必要があり、ｎが巨大になったときに、計算時間が膨大になることで、この点を解決するために確率的勾配降下法（データをランダムにｎ回選んで更新する方法）を用いる。なお、各エポックごとのデータをまたシャッフルして、学習することで学習に偏りが生じににくくなり、より最適な解を得やすくなる。ミニバッチ勾配降下法という方法もあり、これは、ｎ個のデータをｍ（＜ｎ）個ずつのかたまり（ミニバッチ）に分けて学習を行うもので、ｍ＝１のときに、確率的勾配降下法と同じになる。
分類には、適合率（Precision見逃しが多くても、より正確な予測をしたい場合：スパム等）、再現率（Recall誤りが多くても、抜け漏れを少なくしたい：病気等）、F値（PrecisionとRecallはトレードオフ）がある。

「第 4 章：主成分分析」
主成分分析は、データの特徴量間の関係性、つまり、相関を分析することでデータの構造をつかむ方法。特徴量の数が多い場合に用いられ、相関を持つ多数の特徴量から、相関のない少数の特徴量へと次元削減することが主な目的。学習データの分散が最大になる方向への線形変換を求める手法である。少数の特徴量を主成分といい、最大固有値に対応する固有ベクトルで線形変換された特徴量を第一主成分、ｋ番目の固有値に対応する固有ベクトルで変換された特徴量を第ｋ成分と呼ぶ。
寄与率：変換された特徴量の分散は、固有値に一致するので、全分散量は、元データの持つ全分散量と一致。第ｋ主成分の分散の全分散に対する割合を第ｋ成分の寄与率といい（第ｋ成分の持つ情報量の割合）、第ｋ成分での累積寄与率とは、第ｋ－１主成分までデータを圧縮したときの情報損失量の割合を指す。
固有値と固有ベクトルを求めれば、最大の固有値に対応、つまり、固有ベクトルが分散を最大にする主成分の向きになっている（分散共分散行列の固有ベクトルが解、分散の値は固有値と一致）。また、分散共分散行列は、実対象行列なので、固有ベクトルは、全て直交。

「第 5 章：アルゴリズム」
機械学習のアルゴリズムは、教師あり学習（入力とそれに対応すべき出力を写像する関数を生成する。）、教師なし学習（入力のみからモデルを構築する。半教師あり学習（ラベルありの例とラベルなしの例をどちらも扱えるようにしたもので、それによって近似関数または分類器を生成する。）、強化学習（周囲の環境を観測することでどう行動すべきかを学習する。行動によって必ず環境に影響を及ぼし、環境から報酬という形でフィードバックを得ることで学習アルゴリズムのガイドとする。）などがある。
このうち、講義で説明いただいたｋ近傍法は、分類問題のための機械学習手法で、近傍ｋ個のデータから識別し、ｋ個のクラスラベルの中で最も多いラベルを割り当てるもの。ｋを変えると、結果も変わり、ｋを大きくすると、決定境界は、滑らかになる。
ｋ平均法は、教師なし学習であり、クラスタリング手法（特徴の似ているもの同士をグループ化）として、与えられたデータをｋ個のクラスタに分類するものである。手順として、各クラスタの中心の初期値を設定し、次に、各データ点に対して、各クラスタ中心との距離を計算し、最も距離が近いクラスタを割り当てる。さらに、各クラスタの平均ベクトル（中心）を計算し、クラスタの再割り当てと中心の更新を繰り返して、収束するまで、処理を繰り返す。中心の初期値を変えるとクラスタリング結果も変わりうるし、ｋの値を変えると、クラスタリング結果も変わるが、ｋの値をどう設定するかは、知見であり、こうした分野に詳しいビジネスパーソンと連携して、チームワークで協議して、設定する方が良い。

「第 7 章：サポートベクターマシーン」
サポートベクターマシーンとは、２クラス分類のための機械学習手法で、マージン（決定境界と最も近いデータ点との距離）を最大化する決定境界（識別面）を求めるもの。
教師あり学習を用いるパターン認識モデルの一つで、分類や回帰へ適用できる。認識性能が優れた学習モデルの一つであり、その理由は、未学習データに対して高い識別性能を得るための工夫があるためである。線形モデルの正負で２値分類される。
ラグランジュ未定乗数法は、制約付き最適化問題を解くための手法で、訓練サンプルから、各データ点との距離が最大となるマージン最大化超平面を求めるという基準（超平面分離定理）で線形入力素子のパラメータを学習するもの。
分離超平面を構成する学習データは、サポートベクターだけで、残りのデータは、不要。サンプルを線形分離できないとき、誤差を許容し、誤差に対してペナルティを与えるものが、ソフトマージンＳＶＭであり、マージン内に入るデータや誤分類されたデータに対して、誤差を表す変数を導入するもの。パラメータの大小で、決定境界が変化する。線形分離できないときは、カーネル関数を用いてパターンを有限もしくは無限次元の特徴空間へ写像し、特徴空間上で線形分離を行う手法を用いる。カーネルトリックは、高次元ベクトルの内積をスカラー関数で表現するもので、特徴空間が高次元でも計算コストを抑えられる。非線形カーネルを用いたＳＶＭは、線形SVMでは解けないような非線形なデータに対してカーネルトリックを用いることで分離可能なデータにして学習するパターン認識法
変換後のベクトルの内積は、もとのベクトルの内積に等しいので、変換後のベクトルの内積を計算しないでも効率的に、もとのベクトルの内積を計算できるというカーネル法は、とても有用。多クラス分類への拡張とは、2クラス分類の組み合わせか多クラス分類可能なモデルに定式化を拡大する方法

サポートベクターマシーンの演習の考察

scikit-learn に実装されているサポートベクターマシン（SVM）を用いた学習。
scikit learn の実装例でよく用いられるアヤメデータセットを用いて実装。
過学習を避けるために交差検証と呼ばれる手法を用いてモデルを評価する必要があり、データセットをモデルの学習に用いられる「訓練データ」と、そのモデルの汎用的な性能を測る「テストデータ」に分割する。
現実のデータには異常値や欠損値などがあるということなので、その場合は、類似したデータや関連するデータから、正常な値を合理的方法で推測するなど、データの前処理をして綺麗なデータとしてデータセットを作成する必要がある。
モデルの精度を確認するために、トレーニングデータに対してどれくらいの精度が出たか確認し、さらに、過学習していないか確かめるためにテストデータを用いて精度を計測する。
過学習せず汎用的な性能があるモデルが作成できるまで、学習を行う。
その後、データを可視化して確認すると、分かりやすい。
実際に、実用的なモデルを作成する際には、トレーニングデータとテストデータの前処理はもちろん、それらをどう分割するか等、また、ライブラリの関数が更新されていることもあるので、エラーの原因を調べながら進める等、様々な工夫を重ねる必要があると感じた。
線形のみならず、非線形も含めて、様々なケースで実装を行い、慣れていくこと、また、最新の情報にキャッチアップしていく必要があると思った。

%matplotlib inline

from sklearn import datasets
import numpy as np

iris = datasets.load_iris()

# 3,4番目の特徴量の2次元データで使用
X = iris.data[:, [2,3]]
y = iris.target

from sklearn.cross_validation import train_test_split
from sklearn.preprocessing import StandardScaler 

# 訓練データを70%、テストデータ30%
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=None )

sc = StandardScaler()
sc.fit(X_train)
X_train_std = sc.transform(X_train)
X_test_std = sc.transform(X_test)

from sklearn.svm import SVC
model = SVC(kernel='linear', random_state=None)

model.fit(X_train_std, y_train)

from sklearn.linear_model import LogisticRegression
model = LogisticRegression(random_state=None)

from sklearn.metrics import accuracy_score

pred_train = model.predict(X_train_std)
accuracy_train = accuracy_score(y_train, pred_train)
print('トレーニングデータに対する正解率： %.2f' % accuracy_train)

pred_test = model.predict(X_test_std)
accuracy_test = accuracy_score(y_test, pred_test)
print('テストデータに対する正解率： %.2f' % accuracy_test)

#分類結果図示
import matplotlib.pyplot as plt
from mlxtend.plotting import plot_decision_regions
plt.style.use('ggplot') 

X_combined_std = np.vstack((X_train_std, X_test_std))
y_combined = np.hstack((y_train, y_test))

fig = plt.figure(figsize=(13,8))
plot_decision_regions(X_combined_std, y_combined, clf=model,  res=0.02)
plt.show()