Python Scikit-learn 線形モデルSGDClassifierの徹底解説
基本的な考え方
SGDClassifier()
は、与えられたデータ(特徴量)に基づいて、入力されたデータがどのクラスに属するかを予測するモデルを学習します。内部的には、線形関数(重みとバイアスの組み合わせ)を用いて各クラスに対するスコアを計算し、そのスコアに基づいてクラスを決定します。
主な特徴
- 効率性
特に大規模なデータセットに対して、他の線形モデルよりも高速に学習できる場合があります。 - 柔軟性
損失関数や正則化の種類、学習率などを細かく調整できるため、様々な分類問題に対応できます。 - 正則化 (regularization)
モデルの過学習を防ぐために、正則化項を加えることができます。主な正則化の種類は以下の通りです。l1
: L1正則化(Lasso)。特徴量の選択を促し、不要な特徴量の重みをゼロにする傾向があります。l2
: L2正則化(Ridge)。特徴量の重みを小さくする傾向があります。elasticnet
: L1正則化とL2正則化を組み合わせたものです。
- 様々な損失関数 (loss function)
分類タスクの種類に応じて、様々な損失関数を選択できます。代表的なものには以下のようなものがあります。hinge
: 線形SVM(サポートベクターマシン)で用いられる損失関数です。log
: ロジスティック回帰で用いられる損失関数です。確率的な出力を得たい場合に適しています。modified_huber
: スムーズなヒンジ損失で、外れ値の影響を受けにくいとされています。squared_hinge
: ヒンジ損失の二乗です。perceptron
: パーセプトロンアルゴリズムで用いられる損失関数です。
- 確率的勾配降下法 (Stochastic Gradient Descent)
学習データ全体ではなく、ランダムに選ばれた一部のデータ(ミニバッチ)を使って、モデルのパラメータを少しずつ更新していく最適化手法です。これにより、大規模なデータセットに対しても効率的に学習を進めることができます。
基本的な使い方 (Pythonコード例)
from sklearn.linear_model import SGDClassifier
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_iris
from sklearn.metrics import accuracy_score
# データのロード
iris = load_iris()
X = iris.data
y = iris.target
# データの分割(訓練データとテストデータ)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# SGDClassifier のインスタンス作成(ロジスティック回帰を損失関数として使用)
sgd_classifier = SGDClassifier(loss='log_loss', random_state=42)
# モデルの学習
sgd_classifier.fit(X_train, y_train)
# テストデータでの予測
y_pred = sgd_classifier.predict(X_test)
# 精度評価
accuracy = accuracy_score(y_test, y_pred)
print(f"Accuracy: {accuracy}")
コードの説明
from sklearn.linear_model import SGDClassifier
:SGDClassifier
クラスを scikit-learn のlinear_model
モジュールからインポートします。from sklearn.model_selection import train_test_split
: データを訓練用とテスト用に分割するための関数をインポートします。from sklearn.datasets import load_iris
: Iris(アヤメ)のサンプルデータをロードするための関数をインポートします。from sklearn.metrics import accuracy_score
: モデルの精度を評価するための関数をインポートします。- データのロードと分割は、一般的な機械学習のワークフローです。
sgd_classifier = SGDClassifier(loss='log_loss', random_state=42)
:SGDClassifier
のインスタンスを作成しています。loss='log_loss'
は損失関数としてロジスティック回帰を指定しています。random_state
は乱数生成のシードを固定し、結果の再現性を確保するために指定します。sgd_classifier.fit(X_train, y_train)
: 訓練データを使ってモデルを学習させます。y_pred = sgd_classifier.predict(X_test)
: 学習済みのモデルを使って、テストデータの予測を行います。accuracy = accuracy_score(y_test, y_pred)
: テストデータの正解ラベルと予測ラベルを比較し、精度を計算します。
より詳細な設定
SGDClassifier()
のインスタンス作成時には、様々なハイパーパラメータを指定できます。
tol
: 収束判定の閾値を指定します。max_iter
: 学習を行うエポック(訓練データ全体を何回繰り返して学習するか)の最大数を指定します。eta0
: 学習率の初期値を指定します。learning_rate
: 学習率のスケジューリング方法 ('constant', 'optimal', 'invscaling', 'adaptive') を指定します。penalty
: 使用する正則化の種類 ('l1', 'l2', 'elasticnet') を指定します。alpha
: 正則化の強度を制御するパラメータです。
これらのパラメータを調整することで、モデルの性能を向上させることができます。
よくあるエラーとトラブルシューティング
-
- 原因
学習データや予測データに、NaN
(Not a Number) や無限大 (inf
) の値が含まれている場合に発生します。SGD はこれらの値を適切に処理できません。 - トラブルシューティング
- データセット全体を確認し、
NaN
やinf
の値がないか調べます。Pandas のisnull()
やisinf()
メソッドなどが役立ちます。 - 欠損値 (
NaN
) がある場合は、適切な方法で補完します(例:平均値、中央値、最頻値での補完、または欠損値を含む行・列の削除)。scikit-learn のSimpleImputer
を使用することもできます。 - 無限大 (
inf
) の値がある場合は、データの生成過程を見直し、原因を特定して修正します。極端な外れ値が原因であれば、適切な前処理(例:スケーリング、対数変換)を検討します。
- データセット全体を確認し、
- 原因
-
ValueError: y should be a 1d array, got an array of shape (n_samples, n_classes)
(または類似のエラー)- 原因
教師データy
が 1次元の配列(各サンプルのクラスラベルが一つだけ)であるべきなのに、2次元以上の配列になっている場合に発生します。One-Hot Encoding されたラベルなどが誤って渡されることがあります。 - トラブルシューティング
- 教師データ
y
の形状 (.shape
属性) を確認し、1次元であることを確認します。 - もし One-Hot Encoding されたラベルを使用している場合は、
np.argmax(y, axis=1)
などを使って元のクラスラベルに戻します。 - 意図せず多次元の配列になっている場合は、データの生成過程や前処理のコードを見直します。
- 教師データ
- 原因
-
NotFittedError: This SGDClassifier instance is not fitted yet. Call 'fit' with appropriate arguments before using this estimator.
- 原因
fit()
メソッドを呼び出してモデルを学習させる前に、predict()
やscore()
などのメソッドを使用しようとした場合に発生します。 - トラブルシューティング
- 必ず
SGDClassifier
のインスタンスを作成した後、訓練データX_train
と教師データy_train
を使ってfit()
メソッドを呼び出します。
- 必ず
- 原因
-
学習が遅い、または収束しない
- 原因
- 学習率 (learning rate) の設定が不適切
学習率が高すぎるとパラメータが振動して収束せず、低すぎると学習に時間がかかりすぎる可能性があります。 - 特徴量のスケールが揃っていない
特徴量のスケールが大きく異なると、一部の重みが支配的になり、学習が不安定になることがあります。 - 正則化 (regularization) の強度が不適切
正則化が強すぎるとモデルが単純になりすぎて学習不足に陥り、弱すぎると過学習を引き起こしやすくなります。 - エポック数 (max_iter) が不足している
学習が十分に繰り返されていない可能性があります。
- 学習率 (learning rate) の設定が不適切
- トラブルシューティング
- 学習率の調整
learning_rate
パラメータをconstant
,optimal
,invscaling
,adaptive
など様々なオプションで試したり、eta0
パラメータで初期学習率を調整したりします。GridSearchCV
やRandomizedSearchCV
を使って最適な学習率を探索することも有効です。 - 特徴量のスケーリング
StandardScaler
やMinMaxScaler
などを使って、特徴量のスケールを揃えます。学習前にスケーリングを行い、テストデータにも同じ変換を適用することが重要です。 - 正則化強度の調整
alpha
パラメータの値を様々に変えてモデルの性能を評価します。penalty
パラメータで正則化の種類を変えることも検討します。 - エポック数の増加
max_iter
パラメータの値を増やして、より多くの学習を試みます。ただし、過学習には注意が必要です。 - 収束判定の調整
tol
パラメータの値を調整して、収束の閾値を変更します。 - データのシャッフル
学習データの順番が偏っている場合、shuffle=True
(デフォルト) を確認するか、明示的にシャッフルします。
- 学習率の調整
- 原因
-
過学習 (Overfitting) / 未学習 (Underfitting)
- 原因
- 過学習
モデルが訓練データに対して過剰に適合してしまい、未知のデータに対する汎化性能が低い状態です。訓練データに対して精度が高いのに、テストデータに対して精度が低い場合に疑われます。 - 未学習
モデルが訓練データを十分に学習できておらず、訓練データとテストデータの両方に対して精度が低い状態です。
- 過学習
- トラブルシューティング
- 過学習の場合
- より多くの訓練データを収集します。
- 特徴量の数を減らします(特徴量選択)。
- 正則化の強度 (
alpha
) を強くします。 - モデルの複雑さを減らします。
- 交差検証 (Cross-Validation) を行い、汎化性能をより正確に評価します。
- 早期終了 (Early Stopping) を検討します(
validation_fraction
パラメータと関連)。
- 未学習の場合
- より複雑なモデルを試します(ただし、線形モデルの範囲内で)。
- より多くの特徴量を追加します(特徴量エンジニアリング)。
- 正則化の強度 (
alpha
) を弱くします。 max_iter
を増やして学習を長く行います。
- 過学習の場合
- 原因
-
AttributeError
など、メソッドや属性が見つからないというエラー- 原因
scikit-learn のバージョンが古い、またはインストールが正しく行われていない可能性があります。 - トラブルシューティング
- scikit-learn のバージョンを確認し (
sklearn.__version__
)、最新バージョンにアップデートしてみます (pip install -U scikit-learn
またはconda update scikit-learn
)。 - scikit-learn が正しくインストールされているか確認します (
import sklearn
を実行してエラーが出ないか確認)。
- scikit-learn のバージョンを確認し (
- 原因
トラブルシューティングの一般的なヒント
- 簡単な例から試す
複雑なデータセットや設定で問題が発生する場合は、まずは簡単なデータセットと基本的な設定で動作確認を行い、徐々に複雑にしていくと原因を特定しやすくなります。 - ドキュメントやオンラインリソースを参照する
scikit-learn の公式ドキュメントや、Stack Overflow などの Q&A サイトで類似のエラーや問題が報告されていないか検索してみます。 - print デバッグ
変数の値やデータの形状などをprint()
関数で出力して、プログラムの実行状況を把握します。 - コードの該当箇所を確認する
エラーが発生した行や、その周辺のコードに問題がないか丁寧に確認します。 - エラーメッセージをよく読む
エラーメッセージには、問題の原因や解決のヒントが含まれていることが多いです。
基本的な分類の例 (Iris データセット)
これは、SGDClassifier
を使って Iris (アヤメ) のデータを分類する基本的な例です。
from sklearn.linear_model import SGDClassifier
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_iris
from sklearn.metrics import accuracy_score
# 1. データのロード
iris = load_iris()
X = iris.data # 特徴量
y = iris.target # クラスラベル
# 2. データの分割 (訓練データとテストデータ)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 3. SGDClassifier のインスタンス作成
# ここでは、損失関数としてロジスティック回帰 ('log_loss') を指定
# random_state は結果の再現性のために指定
sgd_classifier = SGDClassifier(loss='log_loss', random_state=42)
# 4. モデルの学習
sgd_classifier.fit(X_train, y_train)
# 5. テストデータでの予測
y_pred = sgd_classifier.predict(X_test)
# 6. モデルの評価 (精度)
accuracy = accuracy_score(y_test, y_pred)
print(f"Accuracy: {accuracy}")
# (オプション) 予測確率の取得 (loss='log_loss' の場合)
if sgd_classifier.loss == 'log_loss':
y_prob = sgd_classifier.predict_proba(X_test)
print("\n予測確率:")
print(y_prob[:5])
この例のポイント
- (オプション) 予測確率
loss='log_loss'
を指定した場合、predict_proba()
メソッドを使うことで、各クラスに属する確率を取得できます。 - 評価
accuracy_score()
関数を使って、予測結果 (y_pred
) と正解ラベル (y_test
) を比較し、モデルの精度を計算します。 - 予測
学習済みのモデルのpredict()
メソッドにテストデータ (X_test
) を渡して、予測を行います。 - モデルの学習
fit()
メソッドに訓練データ (X_train
,y_train
) を渡して、モデルを学習させます。 - SGDClassifier のインスタンス作成
SGDClassifier()
を呼び出して分類器のオブジェクトを作成します。loss
パラメータで損失関数を指定します。ここではロジスティック回帰 ('log_loss'
) を使用しています。random_state
を指定することで、乱数による処理を固定し、実行ごとの結果を同じにすることができます。 - データの分割
train_test_split()
関数を使って、データを訓練用とテスト用に分割します。これにより、学習したモデルの汎化性能を評価できます。 - データのロード
load_iris()
関数を使って、scikit-learn に付属の Iris データセットを読み込みます。
様々な損失関数と正則化を試す例
この例では、SGDClassifier
の loss
パラメータと penalty
パラメータを変更して、異なる損失関数と正則化手法を試します。
from sklearn.linear_model import SGDClassifier
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_iris
from sklearn.metrics import accuracy_score
iris = load_iris()
X = iris.data
y = iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 異なる損失関数と正則化を試す
losses = ['hinge', 'log_loss', 'modified_huber', 'squared_hinge', 'perceptron']
penalties = ['l1', 'l2', 'elasticnet', None]
for loss in losses:
for penalty in penalties:
print(f"\nLoss: {loss}, Penalty: {penalty}")
sgd_classifier = SGDClassifier(loss=loss, penalty=penalty, max_iter=1000, tol=1e-3, random_state=42)
sgd_classifier.fit(X_train, y_train)
y_pred = sgd_classifier.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print(f"Accuracy: {accuracy}")
この例のポイント
penalty=None
は、正則化を行わない設定です。max_iter
(最大イテレーション数) とtol
(収束判定の閾値) を明示的に設定しています。これらのパラメータは、学習の終了条件を制御します。- ネストされたループを使って、それぞれの組み合わせで
SGDClassifier
を学習し、評価します。 losses
リストとpenalties
リストで、試したい損失関数と正則化の種類を定義します。
特徴量のスケーリングの効果を見る例
SGD は特徴量のスケールに敏感な場合があります。この例では、スケーリングの有無で精度がどのように変わるかを確認します。
from sklearn.linear_model import SGDClassifier
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_iris
from sklearn.metrics import accuracy_score
from sklearn.preprocessing import StandardScaler
iris = load_iris()
X = iris.data
y = iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# スケーリングなし
sgd_no_scale = SGDClassifier(loss='log_loss', random_state=42)
sgd_no_scale.fit(X_train, y_train)
y_pred_no_scale = sgd_no_scale.predict(X_test)
accuracy_no_scale = accuracy_score(y_test, y_pred_no_scale)
print(f"Accuracy (no scaling): {accuracy_no_scale}")
# スケーリングあり
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
sgd_scaled = SGDClassifier(loss='log_loss', random_state=42)
sgd_scaled.fit(X_train_scaled, y_train)
y_pred_scaled = sgd_scaled.predict(X_test_scaled)
accuracy_scaled = accuracy_score(y_test, y_pred_scaled)
print(f"Accuracy (with scaling): {accuracy_scaled}")
この例のポイント
- スケーリングなしの場合と、スケーリングありの場合で
SGDClassifier
を学習し、精度を比較します。多くの場合、特徴量をスケーリングすることで SGD の性能が向上します。重要なのは、訓練データでfit()
したスケーラーを、テストデータに対してtransform()
のみ適用することです。 StandardScaler
を使って、特徴量を標準化します(平均を0、標準偏差を1にします)。
パイプラインを使った前処理とモデルの組み合わせ
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import SGDClassifier
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_iris
from sklearn.metrics import accuracy_score
iris = load_iris()
X = iris.data
y = iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# パイプラインの作成
pipeline = Pipeline([
('scaler', StandardScaler()),
('sgd', SGDClassifier(loss='log_loss', random_state=42))
])
# パイプラインを使った学習
pipeline.fit(X_train, y_train)
# パイプラインを使った予測
y_pred = pipeline.predict(X_test)
# 評価
accuracy = accuracy_score(y_test, y_pred)
print(f"Accuracy (with pipeline): {accuracy}")
- パイプラインを使うことで、前処理とモデル学習の流れが整理され、テストデータに対する誤った前処理(訓練データで
fit
していないスケーラーを使うなど)を防ぐことができます。 - 同様に、
predict()
メソッドをパイプラインに対して呼び出すと、テストデータがスケーリングされ、その後スケーリングされたデータで予測が行われます。 - パイプライン全体に対して
fit()
メソッドを呼び出すと、各ステップが順番に実行されます(スケーラーが訓練データにfit
され、その後スケーリングされたデータでSGDClassifier
がfit
されます)。 Pipeline
をインポートし、ステップのリストを作成します。各ステップは(名前, 処理)
の形式で指定します。ここでは、StandardScaler()
によるスケーリングとSGDClassifier()
による分類を順番に行うパイプラインを作成しています。
他の線形モデル (損失関数と正則化を固定したクラス)
SGDClassifier
は様々な損失関数と正則化手法を組み合わせられる汎用的なクラスですが、特定の組み合わせに対して、より特化したクラスも用意されています。
-
linear_model.Perceptron
パーセプトロンアルゴリズムを実装したクラスです。SGDClassifier(loss='perceptron')
と同様の目的で使用できますが、学習ルールが若干異なります。線形分離可能なデータに対して高速に学習できます。from sklearn.linear_model import Perceptron from sklearn.model_selection import train_test_split from sklearn.datasets import load_iris from sklearn.metrics import accuracy_score iris = load_iris() X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.3, random_state=42) # Perceptron のインスタンス作成 perceptron = Perceptron(random_state=42) perceptron.fit(X_train, y_train) y_pred = perceptron.predict(X_test) accuracy = accuracy_score(y_test, y_pred) print(f"Accuracy (Perceptron): {accuracy}")
-
svm.LinearSVC
線形サポートベクターマシン (SVM) を行うためのクラスです。SGDClassifier(loss='hinge')
と似た目的で使用できますが、正則化の種類(L1 または L2)や損失関数の定式化が若干異なります。大規模なデータセットに対しても比較的効率的に動作し、正則化パラメータC
を調整することでマージンの幅を制御できます。from sklearn.svm import LinearSVC from sklearn.model_selection import train_test_split from sklearn.datasets import load_iris from sklearn.metrics import accuracy_score iris = load_iris() X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.3, random_state=42) # LinearSVC のインスタンス作成 linear_svc = LinearSVC(random_state=42, C=1.0) # C は正則化パラメータ linear_svc.fit(X_train, y_train) y_pred = linear_svc.predict(X_test) accuracy = accuracy_score(y_test, y_pred) print(f"Accuracy (LinearSVC): {accuracy}")
-
linear_model.LogisticRegression
ロジスティック回帰を行うためのクラスです。内部的には、solver
パラメータで最適化アルゴリズム('newton-cg'
,'lbfgs'
,'liblinear'
,'sag'
,'saga'
)を選択できます。SGDClassifier(loss='log_loss')
と似た目的で使用できますが、最適化アルゴリズムが異なります。小規模なデータセットや、より解釈性の高いモデルが必要な場合に適しています。from sklearn.linear_model import LogisticRegression from sklearn.model_selection import train_test_split from sklearn.datasets import load_iris from sklearn.metrics import accuracy_score iris = load_iris() X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.3, random_state=42) # LogisticRegression のインスタンス作成 logistic_reg = LogisticRegression(random_state=42, solver='liblinear') # solver を指定 logistic_reg.fit(X_train, y_train) y_pred = logistic_reg.predict(X_test) accuracy = accuracy_score(y_test, y_pred) print(f"Accuracy (LogisticRegression): {accuracy}")
異なる最適化アルゴリズムの利用 (solver パラメータ)
SGDClassifier
は確率的勾配降下法 (SGD) を用いてモデルを最適化しますが、他の線形モデルでは異なる最適化アルゴリズムを選択できる場合があります。例えば、LogisticRegression
の solver
パラメータを変更することで、LBFGS、Newton-CG、Liblinear、SAG、SAGA などの最適化手法を試すことができます。これらのアルゴリズムは、データの規模や特性によって学習速度や精度が異なる場合があります。
非線形モデルの利用
データが線形分離可能でない場合や、より複雑な決定境界を学習したい場合は、線形モデルの代替として非線形モデルを検討できます。
-
k-近傍法 (neighbors.KNeighborsClassifier)
新しいデータの分類を、訓練データの中で最も近い k 個のデータのクラスに基づいて行います。単純で直感的なアルゴリズムですが、データ量が多い場合には計算コストが高くなることがあります。from sklearn.neighbors import KNeighborsClassifier from sklearn.model_selection import train_test_split from sklearn.datasets import load_iris from sklearn.metrics import accuracy_score iris = load_iris() X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.3, random_state=42) # KNeighborsClassifier のインスタンス作成 (k=3) knn_clf = KNeighborsClassifier(n_neighbors=3) knn_clf.fit(X_train, y_train) y_pred = knn_clf.predict(X_test) accuracy = accuracy_score(y_test, y_pred) print(f"Accuracy (KNeighborsClassifier): {accuracy}")
-
決定木 (tree.DecisionTreeClassifier) およびそのアンサンブル (ensemble.RandomForestClassifier, ensemble.GradientBoostingClassifier など)
これらのモデルは、データを階層的に分割することで決定境界を学習します。非線形な関係性を捉えるのに優れており、特徴量のスケールにも比較的影響を受けにくいです。from sklearn.tree import DecisionTreeClassifier from sklearn.model_selection import train_test_split from sklearn.datasets import load_iris from sklearn.metrics import accuracy_score iris = load_iris() X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.3, random_state=42) # DecisionTreeClassifier のインスタンス作成 tree_clf = DecisionTreeClassifier(random_state=42) tree_clf.fit(X_train, y_train) y_pred = tree_clf.predict(X_test) accuracy = accuracy_score(y_test, y_pred) print(f"Accuracy (DecisionTreeClassifier): {accuracy}")
-
svm.SVC
カーネル関数(線形、RBF、多項式など)を用いて非線形な決定境界を学習できるサポートベクターマシンです。LinearSVC
よりも計算コストが高くなる場合がありますが、複雑なデータに対して高い性能を発揮することがあります。from sklearn.svm import SVC from sklearn.model_selection import train_test_split from sklearn.datasets import load_iris from sklearn.metrics import accuracy_score iris = load_iris() X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.3, random_state=42) # SVC のインスタンス作成 (RBF カーネルを使用) svc = SVC(random_state=42, kernel='rbf', C=1.0) svc.fit(X_train, y_train) y_pred = svc.predict(X_test) accuracy = accuracy_score(y_test, y_pred) print(f"Accuracy (SVC with RBF kernel): {accuracy}")
より高度な最適化ライブラリの利用
scikit-learn に組み込まれている最適化アルゴリズム以外にも、より高度な最適化ライブラリ(例:scipy.optimize
、optuna
など)を利用して、独自の損失関数や制約条件を持つモデルを実装することも可能です。ただし、これはより専門的な知識が必要となります。
代替手法を選択する際の考慮事項
- 性能
目的とする予測精度。 - 解釈性
モデルの予測理由を理解したいかどうか。 - 計算コスト
学習時間や予測時間。 - モデルの複雑さ
学習したい決定境界の複雑さ。 - データの特性
データの規模、次元数、線形分離可能性など。