scikit-learnの推定器APIをfit・predict・transformから理解する
ホームに戻る
scikit-learnの推定器APIをfit・predict・transformから理解する
scikit-learnで繰り返し登場するfit・predict・transformの役割を、Irisデータセットを動かしながら整理した。
目次
機械学習初学者による、絶望のアウトプット記録。
scikit-learnのサンプルコードを読んでいると、どのモデルにも同じように
fit() が登場する。ロジスティック回帰とデータの標準化では役割が違うはずなのに、なぜ同じメソッドを使うのか。調べてみると、その理由は「推定器」という共通設計にあった。今回は
fit()、predict()、transform() の3つに絞って、自分なりに整理する。scikit-learnでできること
scikit-learnは、機械学習を試すためのPythonライブラリだ。分類・回帰・クラスタリング・次元削減に加えて、前処理やモデル評価の道具も揃っている。
最初は機能の多さに圧倒されたが、基本的な使い方はかなり統一されている。モデルが変わっても、データを渡して学習し、予測または変換するという流れは大きく変わらない。
推定器という共通の入口
scikit-learnでは、データから何かを学ぶオブジェクトを推定器(Estimator)と呼ぶ。推定器は基本的に
fit() を持ち、役割に応じて別のメソッドも実装する。| 役割 | 主なメソッド | 例 |
|---|---|---|
| 推定器 | fit() | LogisticRegression、StandardScaler |
| 予測器 | predict() | 分類器、回帰器 |
| 変換器 | transform() | StandardScaler、PCA |
ひとつのクラスが複数の役割を持つこともある。
LogisticRegression は学習と予測を行い、StandardScaler はデータから平均・標準偏差を学んでから値を変換する。「どれも同じ書き方で使える」という設計が、scikit-learnの扱いやすさにつながっている。
fit()でデータから学ぶ
fit() は、渡されたデータから必要な値を学ぶメソッドだ。ロジスティック回帰なら、特徴量と正解ラベルから分類に使う係数を学習する。
from sklearn.linear_model import LogisticRegression
model = LogisticRegression()
model.fit(X_train, y_train)StandardScaler の場合は、訓練データの平均と標準偏差を記憶する。from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaler.fit(X_train)同じ
fit() でも、何を学ぶかは推定器によって違う。fit()にテストデータを渡さない
テストデータを使って平均や係数を学ぶと、本来は未知であるはずの情報がモデルに漏れてしまう。これをデータリークという。
fit() は訓練データだけに使う。predict()で未知データを予測する
predict() は、学習済みのモデルへ新しいデータを渡し、クラスや数値を予測するメソッドだ。y_pred = model.predict(X_test)
print(y_pred)分類器ならクラスラベル、回帰器なら連続した数値が返る。確率出力に対応している分類器では、
predict_proba() を使って各クラスに属する確率も取得できる。proba = model.predict_proba(X_test)
print(proba)すべての分類器が
predict_proba() を持つわけではない点には注意が必要だ。transform()でデータを変換する
transform() は、学習済みの変換器を使ってデータを別の表現へ変えるメソッドだ。標準化では、訓練データで覚えた平均と標準偏差を使い、訓練データとテストデータを同じ基準で変換する。
scaler = StandardScaler()
scaler.fit(X_train)
X_train_scaled = scaler.transform(X_train)
X_test_scaled = scaler.transform(X_test)訓練データに対しては、
fit() と transform() を続けて呼ぶ fit_transform() も使える。X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)fit_transform()を一般化しすぎない
StandardScaler では fit_transform(X_train) と fit(X_train) 後の transform(X_train) は同じ結果になる。ただし、すべての変換器で同じとは限らない。まずは使うクラスのドキュメントを確認する。Irisデータセットで一連の流れを試す
アヤメのIrisデータセットを使い、標準化してからロジスティック回帰で分類してみる。
from sklearn.datasets import load_iris
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
# データを読み込む
iris = load_iris()
X, y = iris.data, iris.target
# 訓練用とテスト用に分ける
X_train, X_test, y_train, y_test = train_test_split(
X,
y,
test_size=0.2,
random_state=42,
stratify=y,
)
# 訓練データで基準を学び、両方を同じ基準で変換する
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# モデルを学習する
model = LogisticRegression()
model.fit(X_train_scaled, y_train)
# 未知データを予測して評価する
y_pred = model.predict(X_test_scaled)
print(f"正解率: {accuracy_score(y_test, y_pred):.3f}")コードを追うと、処理の役割がきれいに分かれている。
scaler.fit_transform()で訓練データの基準を学びながら変換するscaler.transform()でテストデータを同じ基準に揃えるmodel.fit()で分類モデルを学習するmodel.predict()で未知データを予測する
最初は
fit()、predict()、transform() が別々の呪文に見えていた。実際には、学ぶ・予測する・変換するという役割を揃えた共通インターフェースだった。モデルを別のアルゴリズムへ差し替えても、基本の流れはほとんど変わらない。次は前処理とモデルを
Pipeline にまとめる方法を試してみたい。