【scikit-learn】入門-2解説【Python】

本ページでは以下のページを要約するとともに、個人的な解説も記載しています。独特な解釈をしている部分があるので、誤りなどの指摘はtwitterまでお願いします。

参考ページ
はじめに — scikit-learn 1.1.2 ドキュメント
https://scikit-learn.org/stable/getting_started.html
閲覧日:2022年10月5日

今回は入門-1の続きからです。
https://scikit-learn.org/stable/getting_started.html#transformers-and-pre-processors

トランスフォーマーとプリプロセッサー

※うまい訳し方が思いつかなかったので、そのまま記載していますがこちらでは前処理について解説を行います。

AIに予測をさせるということは様々な要素を組み合わせて行います。多くは、データの変換、前処理を行い、estimatorに予測をさせるという流れになっています。

scikit-learnでできる前処理の方法も、前回扱ったestimatorと同様に使用できます。(実際にこれらは全てBaseEstimatorというクラスを継承しています。)
前処理を行なうオブジェクトには、前回暑かったような予測結果を求めるpredictメソッドはありませんが、代わりに変換結果を出力するtransformメソッドがあります。

※サンプルのコードでは、前処理として特徴量同士のスケールを標準化によってそろえます。

from sklearn.preprocessing import StandardScaler
X = [[0, 15],
    [1, -10]]
# .fit(X)でXの標準偏差などを計算します。.transform(x)でデータを標準化しています。
StandardScaler().fit(X).transform(X)
#array([[-1.,  1.],
#       [ 1., -1.]])    
X2 =[[0.5,5]]
StandardScaler().fit(X).transform(X2) #未知のデータをXの標準偏差などを使用して、標準化を行います。
#array([[0. , 0.2]])

ColumnTransformerを使用すると他にも様々な変換方法を行うことができます。また、本ブログでも解説を行う予定です。

パイプライン: プリプロセッサとestimatorの結合

パイプラインとは未知のデータを予測するときの流れについてです。未知のデータを予測するには、データの前処理部分(プリプロセッサ)とestimatorに予測させる部分に分かれます。その2つを合わせた一連の流れをパイプラインと表現しています。
前処理とestimator部分をパイプラインとして一纏めにすることで、データリーケージを防げるということです。
※データリーケージは、AIモデルの性能を確認する際に学習データに、性能を確認するためのテストデータが含まれてしまっているがために本来の性能よりも良い結果が出てしまうことを指します。パイプラインを使うことで処理を簡潔にすることで、そのようなミスを減らせます。
他のメリットとしては、AIを使い続けていくときのプログラムを完結に記載できるということがあります。

次の例では、sickit-learnに標準で含まれるアヤメ(lris)のデータセットを使用し、ロジスティック回帰を使用した品種の分類するモデルをパイプラインで作成し、スコアまで求めます。

from  sklearn.preprocessing  import  StandardScaler
from  sklearn.linear_model  import  LogisticRegression
from  sklearn.pipeline  import  make_pipeline
from  sklearn.datasets  import  load_iris
from  sklearn.model_selection  import  train_test_split
from  sklearn.metrics  import  accuracy_score
# パイプラインオブジェクトを作成します。
pipe = make_pipeline(
StandardScaler(), #標準化オブジェクト
LogisticRegression() #ロジスティック回帰のオブジェクト
) 
# アヤメのデータセットを呼び出します。
X, y = load_iris(return_X_y=True)
# 学習データとテストデータに分割します。
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
# パイプラインオブジェクトに学習させます。
# 標準化→モデルに学習させる という流れが1行でできます。
pipe.fit(X_train, y_train)
#Pipeline(steps=[('standardscaler', StandardScaler()),
# ('logisticregression', LogisticRegression())])
# テストデータを使って予測精度を確認します。
#pipe.predict(X_test)でテストデータの予測を求めています。
#テストデータの予測結果とy_test(答え)を比較し、スコアを求めています。
accuracy_score(pipe.predict(X_test), y_test) 
#0.97...

このように、データの前処理から学習、スコアの算出までを1つのオブジェクトでできるので、完結に記載できデータリーケージも抑えることができます。
 パイプラインのメリットで検索しても、日本語のサイトには簡潔に記載できる、ということしか書いていないことがほとんどです。パイプライン化することでデータリーケージを防ぐことができるということも念頭におき使ってみると良いでしょう。

あと3項目ほどありますが、次回で入門部分は終わりにしたいと思います。