8 scikit-learnを使った機械学習

このセクションでは, Python で機械学習をするのに欠かせないモジュール/フレームワークである scikit-learn を紹介します. 機械学習の理論的な挙動と扱い方をある程度知らなければ, 活用するのは難しいです. よって, ここではあくまで基本的な構文やエコシステムの効率的な活用の仕方についてのみ取り上げ, 機械学習のモデルに何を選ぶか, どう評価するか, といった問題や, 応用の範囲を広げるための理論の解説は極力避けています (それらは 10 章 - 13 で説明します). よって, このセクションの内容の多くは scikit-learn公式ドキュメントに既に書かれていることですが, 公式ドキュメントと比較してより実際の作業を意識し, 効率よく書くポイントを強調するようにしています.

Buitinck et al. (2013)scikit-learn のAPIデザインに5原則を挙げています.

  1. 一貫性」全てのオブジェクトのインターフェースとそのドキュメントは一貫したルールを共有する
  2. 閲覧性」全てのパラメータ(ユーザが設定するものと学習アルゴリズムが決定したもの両方)を外部から参照できる. 他の環境への移植を容易にするため.
  3. クラスの不拡散」データセットはNumPyの配列(またはSciPyのスパース行列クラス)だけで, ハイパーパラメータはPythonの標準的な数値や文字列だけで表現するため, 煩雑にクラスを定義したりしない. よってscikit-learnは使用することも他のライブラリとの連結することも容易になる
  4. コンポネント化」多くの学習アルゴリズムはデータ変換の組み合わせまたは流れ作業として表現可能である. よって実現可能でありさえすれば既存の部品の組み合わせで実装できる.
  5. 意味のあるデフォルト設定」パラメータはユーザが定義すべきものでも, 適切なデフォルト値を設定することを課す.

例えば, ロジスティック回帰は sklearn.linear_model.LogisticRegression, ランダムフォレストは sklearn.ensemble.RandomForestClassifier というクラスが用意されています(これらのクラスは, estimator と呼ばれます. 以降は「学習器」と表現します). それぞれ異なるモデルなので必要なハイパーパラメータも異なりますが, インターフェースは共通しています. これらを使ってデータを学習させ, 予測値を出すまでの処理は, データが X, y という numpy 配列で与えられていたとして, 以下のようになります.

from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
import numpy as np

rng = np.random.default_rng(42)
X = rng.normal(size=20 * 5).reshape(20, 5)
y = rng.binomial(n=1, p=.5, size=20)

# logistic regression
logis = LogisticRegression(
  random_state=42, solver='lbfgs', penalty='l2', C=1.0)
logis.fit(X, y)
## LogisticRegression(random_state=42)
logis.predict(X)[:5, ]
## array([0, 1, 0, 1, 0])
logis.predict_proba(X)[:5, ]

# random forest
## array([[0.53631218, 0.46368782],
##        [0.45493085, 0.54506915],
##        [0.50990038, 0.49009962],
##        [0.32308101, 0.67691899],
##        [0.5685927 , 0.4314073 ]])
rf = RandomForestClassifier(random_state=42, n_estimators=10)
rf.fit(X, y)
## RandomForestClassifier(n_estimators=10, random_state=42)
rf.predict(X)[:5, ]
## array([0, 1, 1, 1, 0])
rf.predict_proba(X)[:5, ]
## array([[0.6, 0.4],
##        [0.1, 0.9],
##        [0.3, 0.7],
##        [0.2, 0.8],
##        [0.7, 0.3]])

このように, 学習器オブジェクトを宣言する際のコンストラクタ以外は, .fit(), .predict(), .predict_proba() など, メソッド名と入力データの形式に一貫性があります. よって, データの入出力だけ揃えておけばモデルはそっくり別のものに置き換えるのも容易ですし, 自分で新たに独自のクラスを作ることも容易です.

参考文献一覧

Buitinck, Lars, Gilles Louppe, Mathieu Blondel, Fabian Pedregosa, Andreas Mueller, Olivier Grisel, Vlad Niculae, et al. 2013. API Design for Machine Learning Software: Experiences from the Scikit-Learn Project.” In ECML PKDD Workshop: Languages for Data Mining and Machine Learning, 108–22.