0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【翻訳】scikit-learn 0.18 チュートリアル 科学的データ処理のための統計学習のチュートリアル 教師あり学習:高次元の観測からの出力変数を予測する

Last updated at Posted at 2016-12-26

http://scikit-learn.org/0.18/tutorial/statistical_inference/supervised_learning.html を google翻訳した
scikit-learn 0.18 チュートリアル 目次
科学的データ処理のための統計学習のチュートリアル 目次
前のページ


教師あり学習:高次元の観測からの出力変数を予測する

教師あり学習で解決された問題

教師あり学習 は、観測データ X と、予測しようとしている外部変数 y (通常は「ターゲット」または「ラベル」と呼ばれる)の2つのデータセット間のリンクを学習することにあります。多くの場合、 y は長さ n_samples の一次元配列です。
scikit-learnの教師あり推定器はすべて、モデルに適合する fit(X, y) メソッドと、ラベルなしの観測値 X が与えられた場合に予測ラベル y を返す predict(X) メソッドを実装します。

ボキャブラリー:分類と回帰

予測タスクが一連の有限のラベルの中で観測を分類することである場合、言い換えれば観察されたオブジェクトの「名前を付ける」というタスクは、 分類 タスクと言われる。他方、目標が連続的な目標変数を予測することであるならば、それは 回帰 タスクであると言われる。
scikit-learnで分類を行うとき、 y は整数または文字列のベクトルです。
注意:scikit-learnで使用される基本的な機械学習語彙を簡単に実行する方法については、「scikit-learnチュートリアルによる機械学習入門」を参照してください。

最近傍と次元の呪い

iris を分類する:

iris データセットは、花弁と葉の長さと幅からアイリスの種類(Setosa、Versicolour、およびVirginica)を識別する分類タスクです。

>>> import numpy as np
>>> from sklearn import datasets
>>> iris = datasets.load_iris()
>>> iris_X = iris.data
>>> iris_y = iris.target
>>> np.unique(iris_y)
array([0, 1, 2])

k近傍分類器

最も単純な可能な分類器は、最近傍法 である。新しいサンプル X_test が与えられると、最も近い特徴ベクトルを用いた観測をトレーニングセット(すなわち、推定器を訓練するために使用されるデータ)で見つける。 (このタイプの分類器の詳細については、Scikit-onlineのオンラインマニュアルの「Nearest Neighbors」セクションを参照してください)。

トレーニングセットとテストセット

任意の学習アルゴリズムを試している間は、新しいデータに対する推定器​​パフォーマンスを評価できるようにするため、学習に用いたデータをテストしないことが重要です。このため、データセットは多くの場合、訓練データとテストデータに分割されます。

KNN(k最近傍点)分類例:

>>> # irisデータを訓練データとテストデータを分割する
>>> # データをランダムに分割するランダム置換
>>> np.random.seed(0)
>>> indices = np.random.permutation(len(iris_X))
>>> iris_X_train = iris_X[indices[:-10]]
>>> iris_y_train = iris_y[indices[:-10]]
>>> iris_X_test  = iris_X[indices[-10:]]
>>> iris_y_test  = iris_y[indices[-10:]]
>>> # 最近傍の分類器を作成して適合させる
>>> from sklearn.neighbors import KNeighborsClassifier
>>> knn = KNeighborsClassifier()
>>> knn.fit(iris_X_train, iris_y_train) 
KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
           metric_params=None, n_jobs=1, n_neighbors=5, p=2,
           weights='uniform')
>>> knn.predict(iris_X_test)
array([1, 2, 1, 0, 0, 0, 2, 1, 2, 0])
>>> iris_y_test
array([1, 1, 1, 0, 0, 0, 2, 1, 2, 0])

次元の呪い

推定器が効果的になるには、隣接ポイント間の距離が問題に依存する、ある値 $d$ 未満である必要があります。一次元では、これは平均 $n ~ 1/d$ 点を必要とする。上記の $k$-近傍 の例では、データが0から1の範囲の値を有するただ1つの特徴量によって記述され、 $n$ 回の訓練観測では、新しいデータは $1 / n$ より離れない。したがって、 $1 / n$ がクラス間特徴量の変動の規模に比べて小さいならば、最近傍決定規則は効率的である。
特徴量の数が $p$ の場合は、 $n〜1 / d ^ p$ ポイントが必要になります。 1次元で10ポイントが必要であるとしましょう。ここでは、 $[0、1]$ スペースを舗装するために $p$ 次元で $10 ^ p$ ポイントが必要です。 $p$ が大きくなるにつれ、良好な推定器に必要なトレーニングポイントの数は指数関数的に増加する。
例えば、各点が単なる数(8バイト)であれば、有効な $k$-近傍 推定器は、インターネット全体の現在の推定サイズ(±1000Exabytesまたはそれ以上)より多くのトレーニングデータを必要とする)。
これは 次元の呪い と呼ばれ、機械学習が取り組む中心的な問題です。

線形モデル:回帰から希薄さへ

糖尿病のデータセット

糖尿病のデータセットは、442人の患者の10の生理学的変数(年齢、性別、体重、血圧)、および1年後の疾患の進行の指標からなる:

>>> diabetes = datasets.load_diabetes()
>>> diabetes_X_train = diabetes.data[:-20]
>>> diabetes_X_test  = diabetes.data[-20:]
>>> diabetes_y_train = diabetes.target[:-20]
>>> diabetes_y_test  = diabetes.target[-20:]

現在の課題は、生理学的変数から疾患の進行を予測することである。

線形回帰

LinearRegression は、最も単純な形式で、モデルの残差の平方和をできるだけ小さくするために、一連のパラメータを調整することによって、線形モデルをデータセットに適合させます。

線形モデル:$y = X\beta + ε$

  • $X$ :データ
  • $y$ :目標変数
  • $\beta$ :係数
  • $ε$ :観測ノイズ
>>> from sklearn import linear_model
>>> regr = linear_model.LinearRegression()
>>> regr.fit(diabetes_X_train, diabetes_y_train)
LinearRegression(copy_X=True, fit_intercept=True, n_jobs=1, normalize=False)
>>> print(regr.coef_)
[   0.30349955 -237.63931533  510.53060544  327.73698041 -814.13170937
  492.81458798  102.84845219  184.60648906  743.51961675   76.09517222]

>>> # 平均二乗誤差
>>> np.mean((regr.predict(diabetes_X_test)-diabetes_y_test)**2)
2004.56760268...

>>> # 説明された分散スコア:1は完全予測であり、0はXとyとの間に線形関係がないことを意味する。
>>> regr.score(diabetes_X_test, diabetes_y_test) 
0.5850753022690...

収縮

1次元あたりのデータポイントが少ない場合、観測値のノイズは高い分散を引き起こします。

X = np.c_[ .5, 1].T
y = [.5, 1]
test = np.c_[ 0, 2].T
regr = linear_model.LinearRegression()

import matplotlib.pyplot as plt 
plt.figure() 

np.random.seed(0)
for _ in range(6): 
   this_X = .1*np.random.normal(size=(2, 1)) + X
   regr.fit(this_X, y)
   plt.plot(test, regr.predict(test)) 
   plt.scatter(this_X, y, s=3)  

高次統計学習の解は、回帰係数をゼロに縮小することです。任意の2つのランダムに選択された観測セットは、無相関である可能性があります。これは、リッジ 回帰と呼ばれます。

>>> regr = linear_model.Ridge(alpha=.1)

>>> plt.figure() 

>>> np.random.seed(0)
>>> for _ in range(6): 
...    this_X = .1*np.random.normal(size=(2, 1)) + X
...    regr.fit(this_X, y)
...    plt.plot(test, regr.predict(test)) 
...    plt.scatter(this_X, y, s=3) 

これは、バイアス/分散トレードオフの一例です。リッジ alpha パラメータが大きいほど、バイアスが高くなり、分散が小さくなります。
ミスアウトエラーを最小限に抑えるために alpha を選択できます。今回は、合成データではなく糖尿病データセットを使用しています。

>>> alphas = np.logspace(-4, -1, 6)
>>> from __future__ import print_function
>>> print([regr.set_params(alpha=alpha
...             ).fit(diabetes_X_train, diabetes_y_train,
...             ).score(diabetes_X_test, diabetes_y_test) for alpha in alphas]) 
[0.5851110683883..., 0.5852073015444..., 0.5854677540698..., 0.5855512036503..., 0.5830717085554..., 0.57058999437...]

注: 適合したパラメータでモデルを新しいデータに一般化するのを妨げるノイズを取り込むことをオーバーフィットといいます。リッジ回帰によって導入されたバイアスは、正則化と呼ばれます。

希薄性

フィッティング 特徴1と 特徴2 のみ

糖尿病_ols_1糖尿病_3糖尿病_ols_2

注意 完全な糖尿病データセットの表現には、11次元(10のフィーチャディメンションと1つのターゲット変数)が含まれます。そのような表現に直感を覚えるのは難しいですが、それはかなり疎な空間であることを覚えておくと便利かもしれません。

特徴2はフルモデルに強い係数を持ちますが、特徴1で考慮した場合、yについての情報はほとんど伝達していないことがわかります。
問題の状況を改善する(すなわち、次元の呪いを緩和する)ために、有益な特徴のみを選択し、特徴2のような非有益な特徴に0を設定することは興味深いだろう。リッジ回帰はそれらの寄与を減少させるが、それらをゼロに設定しない。Lasso(最小絶対縮小と選択演算子)と呼ばれる別のペナルティアプローチは、いくつかの係数をゼロに設定できます。このような方法はスパースメソッドと呼ばれ、希薄性はオッカムのカミソリの適用として見ることができます。

>>> regr = linear_model.Lasso()
>>> scores = [regr.set_params(alpha=alpha
...             ).fit(diabetes_X_train, diabetes_y_train
...             ).score(diabetes_X_test, diabetes_y_test)
...        for alpha in alphas]
>>> best_alpha = alphas[scores.index(max(scores))]
>>> regr.alpha = best_alpha
>>> regr.fit(diabetes_X_train, diabetes_y_train)
Lasso(alpha=0.025118864315095794, copy_X=True, fit_intercept=True,
   max_iter=1000, normalize=False, positive=False, precompute=False,
   random_state=None, selection='cyclic', tol=0.0001, warm_start=False)
>>> print(regr.coef_)
[   0.         -212.43764548  517.19478111  313.77959962 -160.8303982    -0.
 -187.19554705   69.38229038  508.66011217   71.84239008]

同じ問題の異なるアルゴリズム

同一の数学的問題を解決するために、異なるアルゴリズムを用いることができる。たとえば、scikit-learnのLassoオブジェクトは、大規模なデータセットで効率的な座標降下法を使用して、Lasso回帰問題を解決します。しかし、scikit-learnは、LARS algorthmを使用して LassoLars オブジェクトを提供します。これは、推定された重みベクトルが非常にまばらな問題(非常に少ない観察での問題)に対して非常に効率的です。

分類

アイリス分類タスクの場合と同様に、線形回帰は、決定フロンティアから遠く離れたデータに多大な重みを与えるので、適切なアプローチではありません。線形アプローチは、シグモイド関数またはロジスティック関数に適合することです。

y = \textrm{sigmoid}(X\beta - \textrm{offset}) + \epsilon =
\frac{1}{1 + \textrm{exp}(- X\beta + \textrm{offset})} + \epsilon
>>> logistic = linear_model.LogisticRegression(C=1e5)
>>> logistic.fit(iris_X_train, iris_y_train)
LogisticRegression(C=100000.0, class_weight=None, dual=False,
          fit_intercept=True, intercept_scaling=1, max_iter=100,
          multi_class='ovr', n_jobs=1, penalty='l2', random_state=None,
          solver='liblinear', tol=0.0001, verbose=0, warm_start=False)

これは LogisticRegression と呼ばれます。

マルチクラス分類

予測するクラスが複数ある場合、よく使用されるオプションは、1対すべての分類子に適合させてから最終決定に投票ヒューリスティックを使用することです。

ロジスティック回帰による収縮と希薄さ

C パラメータはLogisticRegressionオブジェクトの正規化の量を制御します.Cの値が大きいと正則化が少なくなります。 penalty="l2" は収縮(すなわち、非スパース係数)を与え、penalty="l2" はスパース性を与える。

エクセサイズ

最近傍と線形モデルを使用して数字データセットを分類してみてください。最後の10%を残して、これらの観察結果をテストします。

from sklearn import datasets, neighbors, linear_model

digits = datasets.load_digits()
X_digits = digits.data
y_digits = digits.target

答えはこちら

サポートベクターマシン(SVM)

リニアSVM

サポートベクトルマシンは、判別モデル群に属します。サンプルの組み合わせを見つけて、2つのクラス間のマージンを最大にする平面を構築しようとします。正則化は C パラメータによって設定されます。 C の値が小さい場合は、分割線の周りの観測の多くまたはすべてを使用してマージンが計算されることを意味します(さらに正則化)。 C の値が大きい場合は、分割線に近い観測値でマージンが計算される(正則化が少ない)ことを意味します。

未正則化 SVM 正則化SVM (デフォルト)
svm_margin_unreg svm_margin_reg

SVMは回帰-SVR(Support Vector Regression) - または分類-SVC(Support Vector Classification)で使用できます。

>>> from sklearn import svm
>>> svc = svm.SVC(kernel='linear')
>>> svc.fit(iris_X_train, iris_y_train)    
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
    decision_function_shape=None, degree=3, gamma='auto', kernel='linear',
    max_iter=-1, probability=False, random_state=None, shrinking=True,
    tol=0.001, verbose=False)
警告: データの正規化 SVMを含む多くの推定器では、データセットの各特徴量を単位標準偏差に保つことは、良い予測を得るために重要です。

カーネルの使用

クラスは、特徴空間では必ずしも線形に分離できない。解決策は、線形ではなく多項式である決定関数を構築することです。これは、カーネルを観測に配置することによって決定エネルギーを生成すると見なすことができるカーネルトリックを使用して行われます。

線形カーネル

>>> svc = svm.SVC(kernel='linear')

多項式カーネル

svm_kernel_poly

>>> svc = svm.SVC(kernel='poly',
...               degree=3)
>>> # degree: 多項式次数

RBFカーネル(Radial Basis Function)

svm_kernel_rbf

>>> svc = svm.SVC(kernel='rbf')
>>> # gamma: ラジアルカーネルのサイズの逆数

インタラクティブな例

svm_gui.pyをダウンロードするには、 SVM GUI を参照してください。両方のクラスのデータポイントを右ボタンと左ボタンで追加し、モデルにフィットさせ、パラメータとデータを変更します。

エクセサイズ

2つの最初の機能を備えたSVMでアイリスデータセットからクラス1とクラス2を分類してみてください。これらの観察に基づいて、各クラスの10%を残して予測パフォーマンスをテストします。

警告:クラスは注文され、最後の10%を残さないでください。あなたは1つのクラスでのみテストします。
ヒント:グリッドでdecision_functionメソッドを使用して直感を得ることができます。

iris = datasets.load_iris()
X = iris.data
y = iris.target

X = X[y != 0, :2]
y = y[y != 0]

回答はこちら


次のページ
©2010 - 2016、scikit-learn developers(BSDライセンス)。

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?