LoginSignup
23
22

More than 5 years have passed since last update.

【翻訳】scikit-learn 0.18 User Guide 1.4. サポートベクターマシン

Last updated at Posted at 2016-12-21

http://scikit-learn.org/0.18/modules/svm.html 教師付き学習 を google 翻訳した
ユーザーガイド目次
scikit-learn 0.18 ユーザーガイド 1. 教師付き学習 より


1.4. サポートベクターマシン

サポートベクトルマシン(SVM)は、「分類」、「回帰」および「異常値検出」に使用される教師あり学習方法のセットです。

サポートベクターマシンの利点は次のとおりです。

  • 高次元空間で効果的です。
  • 次元の数が標本の数よりも多い場合でも効果的です。
  • 意思決定関数(サポートベクトルと呼ばれる)でトレーニングポイントのサブセットを使用するため、メモリ効率も高くなります。
  • 汎用:決定関数には異なるカーネル関数を指定できます。 共通のカーネルが提供されていますが、カスタムカーネルを指定することもできます。

サポートベクターマシンの欠点は次のとおりです。

  • フィーチャの数がサンプルの数よりもはるかに多い場合、この方法はパフォーマンスが低下する可能性があります。
  • SVMは確率推定値を直接提供するものではありませんが、高価な5倍交差検定を使用して計算されます(下記の参照: スコアと確率)。

scikit-learnのサポートベクターマシンは、高密度( numpy.ndarraynumpy.asarrayのそれに変換可能)とスパース(任意の scipy.sparse)のサンプルベクトルを入力としてサポートします。 しかし、疎なデータの予測を行うためにSVMを使用するには、そのようなデータに適合していなければなりません。 最適なパフォーマンスを得るには、 dtype = float64を使用してC順序付けされたnumpy.ndarray(密)または scipy.sparse.csr_matrix(疎)を使用してください。

1.4.1. 分類

SVCNuSVC、および LinearSVC は、データセットに対して多クラス分類を実行できるクラスです。

SVCとNuSVCは同様の方法ですが、わずかに異なるパラメータセットを受け入れ、異なる数学的定式化をします(see section数学的定式化)。 一方、LinearSVC は、線形カーネルの場合のサポートベクター分類器の別の実装です。 LinearSVCはキーワード kernel を受け入れないことに注意してください。これは線形であるとみなされます。 また、SVCやNuSVCのメンバーの一部には support_ のようなものがありません。
SVC、NuSVC、およびLinearSVCは、トレーニングサンプルを保持するサイズ [n_samples、n_features] の配列X、クラスラベル(文字列または整数)の配列y、サイズ [n_samples] の2つの配列を入力として取ります。

>>> from sklearn import svm
>>> X = [[0, 0], [1, 1]]
>>> y = [0, 1]
>>> clf = svm.SVC()
>>> clf.fit(X, y)  
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
    decision_function_shape=None, degree=3, gamma='auto', kernel='rbf',
    max_iter=-1, probability=False, random_state=None, shrinking=True,
    tol=0.001, verbose=False)

適合後、モデルを使用して新しい値を予測することができます。

>>> clf.predict([[2., 2.]])
array([1])

SVMの決定関数は、サポートベクトルと呼ばれるトレーニングデータのいくつかのサブセットに依存します。 これらのサポートベクトルのいくつかのプロパティは、メンバ support_vectors_support_ およびn_support にあります。

>>> # get support vectors
>>> clf.support_vectors_
array([[ 0.,  0.],
       [ 1.,  1.]])
>>> # get indices of support vectors
>>> clf.support_ 
array([0, 1]...)
>>> # get number of support vectors for each class
>>> clf.n_support_ 
array([1, 1]...)

1.4.1.1. 多クラス分類

SVCとNuSVCは、多クラス分類のために"one-against-one"アプローチを実装している(Knerrら、1990)。 n_class がクラス数である場合、n_class *(n_class - 1)/ 2 の分類器が構築され、それぞれが2つのクラスからのデータを訓練します。 他の分類器との一貫性のあるインターフェースを提供するために、 decision_function_shape オプションは、 "one-against-one"分類器の結果をshape (n_samples、n_classes) の決定関数に集約することを可能にします。

>>> X = [[0], [1], [2], [3]]
>>> Y = [0, 1, 2, 3]
>>> clf = svm.SVC(decision_function_shape='ovo')
>>> clf.fit(X, Y) 
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
    decision_function_shape='ovo', degree=3, gamma='auto', kernel='rbf',
    max_iter=-1, probability=False, random_state=None, shrinking=True,
    tol=0.001, verbose=False)
>>> dec = clf.decision_function([[1]])
>>> dec.shape[1] # 4 classes: 4*3/2 = 6
6
>>> clf.decision_function_shape = "ovr"
>>> dec = clf.decision_function([[1]])
>>> dec.shape[1] # 4 classes
4

一方、LinearSVCは "one-vs-rest" マルチクラス戦略を実装し、n_classモデルを訓練します。 クラスが2つしかない場合は、1つのモデルのみが訓練されます。

>>>
>>> lin_clf = svm.LinearSVC()
>>> lin_clf.fit(X, Y) 
LinearSVC(C=1.0, class_weight=None, dual=True, fit_intercept=True,
     intercept_scaling=1, loss='squared_hinge', max_iter=1000,
     multi_class='ovr', penalty='l2', random_state=None, tol=0.0001,
     verbose=0)
>>> dec = lin_clf.decision_function([[1]])
>>> dec.shape[1]
4

決定関数の完全な説明については、数式 を参照してください。
LinearSVCは multi_class='crammer_singer' オプションを使用してCrammerとSingerによって策定された、いわゆるマルチクラスSVMである代替マルチクラス戦略も実装しています。この方法は一貫しています。これは、"one-vs-rest" 分類には当てはまりません。実際には、結果はほとんど同じですが、実行時間は大幅に少なくなるため、通常は"one-vs-rest"分類が好まれます。
"one-vs-rest" LinearSVCの場合、coef_intercept_ の属性はそれぞれ [n_class, n_features][n_class] という形になります。係数の各行は、n_class 多くの "one-vs-rest" 分類器のうちの1つに対応し、"one" クラスの順に、インターセプトに対して類似している。
"one-vs-one" SVCの場合、属性のレイアウトはもう少し複雑です。線形カーネルの場合、 coef_intercept_ のレイアウトは、 coef_ の形状が [n_class * (n_class - 1) / 2, n_features] であることを除いて、上記LinearSVCで説明したものと同様です。多くのバイナリ分類子。クラス0からクラスnまでの順序は、「0対1」、「0対2」、...「0対n」、「1対2」、「1対3」、「1対n」。 。 。 "n-1対n"。
dual_coef_ の形状は [n_class-1、n_SV] であり、やや難しいレイアウトです。列は、 n_class *(n_class - 1)/ 2 "one-vs-one"分類子のいずれかに含まれるサポートベクトルに対応します。各サポートベクターは、 n_class - 1 分類子で使用されます。各行の n_class - 1 エントリは、これらの分類子の二重係数に対応します。
これは例でより明確になるかもしれません:
3つのサポートベクトル $v^{0}_0、v^{1}_0、v^{2}_0$ を有するクラス0、および、それぞれ2つのサポートベクトル $v ^{0}_1, v^{1}_1$ 、$v^{0}_2, v^{1}_2$ を持つクラス1とクラス2、3つのクラス問題を考える。各サポートベクトル $v^{j}_i$ には、2つの二重係数がある。クラス $i$ と $k$ $\alpha^{j}_{i,k}$ との間の分類器におけるサポートベクトルの係数 $v^{j}_i$ をコールしましょう。すると dual_coef_ は次のようになります。

$\alpha^{0}_{0,1}$ $\alpha^{0}_{0,2}$ クラス0のサポートベクトルの係数
$\alpha^{1}_{0,1}$ $\alpha^{1}_{0,2}$
$\alpha^{2}_{0,1} $ $\alpha^{2}_{0,2}$
$\alpha^{0}_{1,0}$ $\alpha^{0}_{1,2}$ クラス1のサポートベクトルの係数
$\alpha^{1}_{1,0}$ $\alpha^{1}_{1,2}$
$\alpha^{0}_{2,0}$ $\alpha^{0}_{2,1}$ クラス2のサポートベクトルの係数
$\alpha^{1}_{2,0}$ $\alpha^{1}_{2,1}$

1.4.1.2. スコアと確率

SVCメソッド decision_function は、各サンプル(またはバイナリのケースでは1つのサンプルにつき1つのスコア)ごとにクラスごとのスコアを与えます。コンストラクタオプションのprobabilityTrueに設定されると、(predict_probapredict_log_probaのメソッドからの)クラスメンバーシップ確率の見積もりが有効になります。バイナリの場合、確率はPlattスケーリングを使用して較正されます:SVMのスコアに対するロジスティック回帰、トレーニングデータに対する追加の相互検証による適合。マルチクラスの場合、これは Wuら(2004) のように拡張されている。
言うまでもなく、Plattスケーリングに含まれる相互検証は、大規模なデータセットに対しては高価な操作です。さらに、確率推定値は、スコアの「argmax」が確率のargmaxでないという意味で、スコアと矛盾している可能性がある。 (例えば、バイナリ分類では、predict_probaに従って確率が<½であるクラスに属するとpredictによって、サンプルをラベル付けすることができる)。Plattの方法は、理論的な問題も有することが知られている。信頼スコアが必要だが、これらが確率である必要がない場合は、probability = Falseを設定し、predict_probaの代わりにdecision_function を使用することをお勧めします。

1.4.1.3. 不均衡問題

特定のクラスまたは特定の個々のサンプルをより重要視することが望まれる問題では、キーワード class_weight および sample_weight を使用できます。
SVC(NuSVCではなく)は fit メソッドでキーワード class_weight を実装します。これは {class_label:value} という形式の辞書で、valueは class_label のパラメータ CC * value に設定する浮動小数点数> 0です。

SVC、NuSVC、SVR、NuSVR、およびOneClassSVMは、キーワード sample_weight を使用したメソッド fit の個々のサンプルについてもウェイトを実装します。 class_weight と同様に、これらは、i番目の例のパラメータ CC * sample_weight[i] に設定します。

1.4.2. 回帰

Support Vector Classificationの方法は、回帰問題を解決するために拡張することができます。この方法は、サポートベクトル回帰と呼ばれます。
モデルを構築するためのコスト関数はマージンを越えるトレーニングポイントを気にしないので、サポートベクトル分類(上記のように)によって生成されるモデルは、トレーニングデータのサブセットのみに依存する。同様に、サポートベクトル回帰によって生成されるモデルは、モデルを構築するコスト関数がモデル予測に近いトレーニングデータを無視するため、トレーニングデータのサブセットのみに依存します。
SVR、NuSVR、LinearSVRの3種類のサポートベクトル回帰の実装があります。 LinearSVRはSVRよりも高速な実装を提供しますが、NuSVRはSVRやLinearSVRとはわずかに異なる形式を実装していますが、線形カーネルのみを考慮しています。詳細については、実装の詳細を参照してください。
分類クラスと同様に、フィットメソッドは、引数ベクトルX、yとして取られます。この場合、yは整数値ではなく浮動小数点値を持つことが期待されます。

>>>
>>> from sklearn import svm
>>> X = [[0, 0], [2, 2]]
>>> y = [0.5, 2.5]
>>> clf = svm.SVR()
>>> clf.fit(X, y) 
SVR(C=1.0, cache_size=200, coef0=0.0, degree=3, epsilon=0.1, gamma='auto',
kernel='rbf', max_iter=-1, shrinking=True, tol=0.001, verbose=False)
>>> clf.predict([[1, 1]])
array([ 1.5])

1.4.3. 密度推定、新規性検出

1つのクラスのSVMが新規性検出に使用されます。つまり、一連のサンプルが与えられた場合、新しいセットをそのセットに属するものとして分類するように、そのセットのソフト境界を検出します。 これを実装するクラスはOneClassSVM です。
この場合、それは教師なし学習の一種であるため、 fit メソッドにはクラスラベルがなく、配列Xを入力として取ります。
この使用法の詳細については、セクション「新規性と異常値検出」を参照してください。

1.4.4. 複雑

サポートベクターマシンは強力なツールですが、トレーニングベクタの数が増えるにつれて、そのコンピューティングとストレージの要件は急速に増加します。 SVMのコアは、トレーニングベクトルの残りからサポートベクトルを分離する2次計画問題(QP)です。このlibsvm ベースの実装で使用されるQPソルバーは、libsvmキャッシュの効率性に応じて、 $O(n_{features} \times n_{samples}^2)$ と $O(n_{features} \times n_{samples}^3)$ 実際に使用されます(データセットに依存)。データが非常に疎である場合、 $n_ {features}$ は、サンプルベクトル内の非ゼロフィーチャの平均数で置き換えます。
また、線形の場合、LinearSVCでliblinear 実装で使用されるアルゴリズムは、libsvmベースのSVCコンパイラよりもはるかに効率的で、数百万のサンプルやフィーチャにほぼ線形に拡大縮小できます。

1.4.5. 実用上のヒント

  • データコピーの回避 :SVC、SVR、NuSVC、NuSVRの場合、特定のメソッドに渡されるデータが連続したC順序ではなく、倍精度の場合、元のC実装を呼び出す前にコピーされます。与えられた配列がC連続であるかどうかは、その flags 属性を調べることで調べることができます。
    • LinearSVC(および LogisticRegression )の場合、numpy配列として渡された入力はコピーされ、liblinearの内部疎データ表現(非ゼロのコンポーネントの倍精度浮動小数点数およびint32インデックス)に変換されます。高密度のC連続倍精度配列を入力としてコピーせずに大規模な線形分類器に適合させたい場合は、代わりに SGDClassifier クラスを使用することをお勧めします。目的関数は、LinearSVCモデルとほぼ同じに構成することができます。
  • カーネルキャッシュサイズ :SVC、SVR、nuSVC、およびNuSVRの場合、カーネルキャッシュのサイズは、より大きな問題の実行時間に大きな影響を与えます。十分なRAMがある場合は、cache_size をデフォルトの200(MB)より大きい値、たとえば500(MB)または1000(MB)に設定することをお勧めします。
  • Cの設定Cはデフォルトで1に設定されています。これはデフォルトの選択です。騒々しい観測が多い場合は、それを減らす必要があります。それはより多くの推定を正規化することに対応する。
  • サポートベクターマシンのアルゴリズムはスケール不変ではありませんので、 データをスケールすることを強くお勧めします。たとえば、入力ベクトルXの各属性を[0,1]または[-1、+1]にスケールするか、平均0と分散1になるように標準化します。テストベクトルには同じスケーリングを適用する必要があります。意味のある結果を得る。スケーリングと正規化の詳細については、「前処理する」を参照してください。
  • NuSVC / OneClassSVM / NuSVRのパラメータnuは、トレーニングエラーの割合とサポートベクトルを近似します。
  • SVCにおいて、分類のためのデータが不均衡である(例えば、多くの正および負の数である)場合、class_weight = 'balanced'を設定し、および/または異なるペナルティパラメータCを試みる。
  • 基本となるLinearSVCの実装では、モデルをフィッティングする際に、乱数ジェネレータを使用してフィーチャを選択します。したがって、同じ入力データに対してわずかに異なる結果を出すことは珍しくありません。それが起こるなら、より小さいtolパラメータで試してください。
  • LinearSVC(loss = 'l2'、penalty = 'l1'、dual = False) によって提供されるようなL1ペナルティを使用すると、疎な解が得られる。すなわち、フィーチャウェイトのサブセットのみがゼロと異なり、決定関数に寄与する。 Cを増やすと、より複雑なモデルが生成されます(より多くの機能が選択されます)。 「ヌル」モデル(すべての重みがゼロに等しい)を生成するC値は、l1_min_c を使用して計算できます。

1.4.6. カーネル関数

カーネル関数は、次のいずれかになります。

  • 線形: $ \langle x, x'\rangle$ .
  • 多項式: $ (\gamma \langle x, x'\rangle + r)^d$ . $d$ はキーワードdegree、 $r$ をcoef0 で指定します。
  • rbf: $\exp(-\gamma |x-x'|^2)$. $\gamma $はキーワード gamma によって指定され、0より大きくなければなりません。
  • sigmoid( $\tanh(\gamma \langle x,x'\rangle + r)$)。ここで $r$ は coef0 で指定されます。

異なるカーネルはキーワード kernel によって初期化時に指定されます:

>>> linear_svc = svm.SVC(kernel='linear')
>>> linear_svc.kernel
'linear'
>>> rbf_svc = svm.SVC(kernel='rbf')
>>> rbf_svc.kernel
'rbf'

1.4.6.1. カスタムカーネル

カーネルにPython関数を与えるか、またはグラム行列をあらかじめ計算することによって、独自のカーネルを定義することができます。
カスタムカーネルを持つ分類器は、以下の点を除いて他の分類器と同じように動作します。

  • フィールド support_vectors_ は空になりました。サポートベクトルのインデックスのみがsupport_ に格納されます
  • fit()メソッドの最初の引数の参照(およびコピーではない)は、後で参照するために保存されます。 その配列がfit()predict()の使用の間で変更された場合、予期しない結果が生じるでしょう。

1.4.6.1.1. Python関数をカーネルとして使用する

また、コンストラクターのキーワードkernel に関数を渡すことで、独自の定義済みカーネルを使用することもできます。
カーネルは、シェイプの2つの行列 (n_samples_1、n_features)(n_samples_2、n_features) を引数として取り、シェイプ (n_samples_1、n_samples_2) のカーネル行列を返す必要があります。
次のコードは、リニアカーネルを定義し、そのカーネルを使用する分類器インスタンスを作成します。

>>> import numpy as np
>>> from sklearn import svm
>>> def my_kernel(X, Y):
...     return np.dot(X, Y.T)
...
>>> clf = svm.SVC(kernel=my_kernel)

1.4.6.1.2. グラム行列の使用

kernel = 'precomputed' を設定し、fitメソッドでXの代わりにグラム行列を渡します。 現時点では、すべてのトレーニングベクトルとテストベクトルとの間のカーネル値が提供されなければならない。

>>> import numpy as np
>>> from sklearn import svm
>>> X = np.array([[0, 0], [1, 1]])
>>> y = [0, 1]
>>> clf = svm.SVC(kernel='precomputed')
>>> # linear kernel computation
>>> gram = np.dot(X, X.T)
>>> clf.fit(gram, y) 
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
    decision_function_shape=None, degree=3, gamma='auto',
    kernel='precomputed', max_iter=-1, probability=False,
    random_state=None, shrinking=True, tol=0.001, verbose=False)
>>> # predict on training examples
>>> clf.predict(gram)
array([0, 1])

1.4.6.1.3. RBFカーネルのパラメータ

Radial Basis Function(RBF) カーネルでSVMをトレーニングする場合は、Cgammaの2つのパラメータを考慮する必要があります。すべてのSVMカーネルに共通のパラメータCは、決定表の単純さに対してトレーニング例の誤分類を排除します。低いCは決定表を滑らかにし、高いCはすべての訓練例を正しく分類することを目指します。gammaは、1つのトレーニング例にどれだけの影響があるかを定義します。gammaが大きければ大きいほど、他の例が影響を受けているはずです。
Cgammaの適切な選択は、SVMの性能にとって重要です。 1つは、sklearn.model_selection.GridSearchCV をCと使用し、gammaを指数関数的に遠く離れて使用することをお勧めします。

1.4.7. 数学的処方

サポートベクターマシンは、分類、回帰または他のタスクのために使用される、高次元または無限次元の空間における超平面または超平面の組を構築する。直感的には、一般に、マージンが大きければ大きいほど分類器の一般化誤差が小さくなるので、どのクラスの最も近い訓練データ点(いわゆる関数マージン)との距離が最も大きい超平面によって良好な分離が達成される。

1.4.7.1. SVC

2つのクラスのトレーニングベクトル $ x_i \in \mathbb{R}^p$ 、 $i = 1...n$ と $ y \in \mathbb{R}^n$ $\varepsilon$ のベクトルyを与えられたSVCは、問題:

\min_ {w, b, \zeta} \frac{1}{2} w^T w + C \sum_{i=1}^{n} \zeta_i
\begin{align}
\textrm {subject to } & y_i (w^T \phi (x_i) + b) \geq 1 - \zeta_i,\\
 & \zeta_i \geq 0, i=1, ..., n
\end{align}

その二重

\min_{\alpha} \frac{1}{2} \alpha^T Q \alpha - e^T \alpha
\begin{align}
\textrm {subject to } & y^T \alpha = 0\\
& 0 \leq \alpha_i \leq C, i=1, ..., n
\end{align}

ここで、 $e$ はすべての1のベクトル、 $C> 0$ は上限、 $Q$ は n×n 正の半正定値行列、 $Q_{ij} \equiv y_i y_j K(x_i, x_j)$ 。ここで、 $K(x_i, x_j) = \phi (x_i)^T \phi (x_j)$ はカーネルです。ここで、訓練ベクトルは関数 $\phi$ によって高次元(多分無限次元)の空間に暗黙的に写像されます。
決定関数は次のとおりです。

\operatorname{sgn}(\sum_{i=1}^n y_i \alpha_i K(x_i, x) + \rho)

注意: libsvmおよびliblinearから派生したSVMモデルはCを正則化パラメータとして使用しますが、他のほとんどの推定子ではアルファを使用します。両方の関係は $C = \frac{n_samples}{alpha}.$ です。
このパラメータには、製品 $y_i \alpha_i$ を保持するメンバー dual_coef_ 、サポートベクトルを保持する support_vectors_ 、および独立項 $\rho$ を保持する intercept_ を介してアクセスできます。

1.4.7.2. NuSVC

サポートベクトルの数と訓練エラーを制御する新しいパラメータ $\nu$ を紹介します。パラメータ $\nu \in(0、
1]$ は、訓練誤差の割合の上限およびサポートベクトルの割合の下限である。
$\nu$-SVCの定式化はC-SVCの再パラメータ化であり、したがって数学的に同等であることが分かります。

1.4.7.3. SVR

与えられた訓練ベクトル $x_i \mathbb {R} ^ p$ 、i = 1、...、n と、ベクトル $\mathbb {R} ^ n \varepsilon$-SVR は、次のような問題を解決します。

    \min_ {w, b, \zeta, \zeta^*} \frac{1}{2} w^T w + C \sum_{i=1}^{n} (\zeta_i + \zeta_i^*)
\begin{align}
    \textrm {subject to } & y_i - w^T \phi (x_i) - b \leq \varepsilon + \zeta_i,\\
                          & w^T \phi (x_i) + b - y_i \leq \varepsilon + \zeta_i^*,\\
                          & \zeta_i, \zeta_i^* \geq 0, i=1, ..., n

\end{align}

その二重

   \min_{\alpha, \alpha^*} \frac{1}{2} (\alpha - \alpha^*)^T Q (\alpha - \alpha^*) + \varepsilon e^T (\alpha + \alpha^*) - y^T (\alpha - \alpha^*)
\begin{align}
   \textrm {subject to } & e^T (\alpha - \alpha^*) = 0\\
   & 0 \leq \alpha_i, \alpha_i^* \leq C, i=1, ..., n
\end{align}

ここで、 $e$ はすべての1のベクトル、 $C> 0$ は上限、$Q$は $n$ by $n$ 正の半正定値行列、 $Q_{ij} \equiv K(x_i, x_j) = \phi (x_i)^T \phi (x_j)$ はカーネルです。ここで、訓練ベクトルは関数 $\phi$ によって高次元(多分無限次元)の空間に暗黙的に写像されます。
決定関数は次のとおりです。

 \sum_{i=1}^n (\alpha_i - \alpha_i^*) K(x_i, x) + \rho

これらのパラメータには、差分 $\alpha_i - \alpha_i ^ *$ を保持するメンバーdual_coef_、サポートベクトルを保持する support_vectors_、および独立項 $\ρ$ を保持する intercept_ を通じてアクセスできる。

1.4.8. 実装の詳細

内部的には、すべての計算を処理するために libsvmliblinear を使用します。これらのライブラリは、CおよびCythonを使用してラップされます。


scikit-learn 0.18 ユーザーガイド 1. 教師付き学習 より

©2010 - 2016、scikit-learn developers(BSDライセンス)。

23
22
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
23
22