はじめに
大学3年でRを使い始め早3年。私はTidyverseの沼にどっぷりと浸かって過ごしていました。Pythonにももちろん興味はありましたが、Tidyverseの底なし沼を抜けられるわけもなく・・・
しかし最近、機械学習をもっと幅広く学びたい欲が高まり、ようやくtidyverseの沼から一度出てみようと思ったわけです。
scikit-learn
scikit-learnとは今さら私が言うまでもなく、様々な機械学習を提供しているPythonライブラリです。主な特徴としては、
1. 利用できるアルゴリズムが豊富
scikit-learnは一般的な教師あり学習の回帰/分類は言うまでもなく、クラスタリング/次元削減といった教師なし学習などあらゆるアルゴリズムをサポートしています。
2. 学習だけではない、前後の処理も提供
scikit-learnは学習前のデータ分割や学習後のモデル評価など、モデル学習に限らず幅広く処理をサポートしています。
3. 情報量が豊富
scikit-learnは「機械学習といえば!!」と言う立場のライブラリであり (これは個人の意見です)、また書店やネット上には関連情報が立ち並んでいて、初心者でも学びやすい環境が整っています (これは事実でしょう)。
テンプレ
scikit-learnに限らず、機械学習の流れは以下のようになっていることが一般的です (多分)。
- 訓練データとテストデータに分割
- モデル式を設定
- 学習アルゴリズムを指定
- パラメータチューニング
- 訓練データをもとに学習
- テストデータをもとにモデルを評価
scikit-learnにおいてはモデル式は指定しなくても良いらしい (??)。
実際にscikit-learnでランダムフォレストを当てはめるには以下のようなコードになります。
データはirisを利用します。
訓練データとテストデータに分割
# 定番irisデータの読み込み
from sklearn.datasets import load_iris
iris = load_iris()
# 訓練データとテストデータに分割するtrain_test_split
from sklearn.model_selection import train_test_split
# x: 説明変数, y: 目的変数
train_x, test_x, train_y, test_y =
train_test_split(iris.data, iris.target, test_size = 0.1)
学習アルゴリズムを指定
scikit-learnの中のensembleの中にRandomForestClassifierがあります。
from sklearn.ensemble import RandomForestClassifier
rforest = RandomForestClassifier()
パラメータチューニング
ここではグリッドサーチを行います。
パラメータは辞書型で用意し、各々に対して配列で指定します。
ここでは、ノード分割に必要とする最小サンプル数のみチューニングを行いますが、参考までに作成する決定木の本数も書いておきます。
各パラメータのデフォルトは以下公式ドキュメントを参考にしてください。
RandomForestClassifier
from sklearn.model_selection import GridSearchCV
# ハイパーパラメータを辞書型で用意
params = {
'min_samples_split': [2, 5, 10],
# 'n_estimators': [10, 20, 30]
}
# グリッドサーチを行う
rforest = GridSearchCV(
rforest,
params,
verbose = 2
)
訓練データをもとに学習
ついでに最適なモデルも選択します。
rforest.fit(train_x, train_y)
# 最適なモデルを選択
best_rforest = rforest.best_estimator_
テストデータをもとにモデルを評価
# テストデータを使った予測
pred_y = best_rforest.predict(test_x)
# モデルの精度を計算
from sklearn.metrics import accuracy_score
accuracy = accuracy_score(test_y, pred_y)
print("モデルの精度: ", accuracy)
# モデルの精度: 0.9333333333333333
簡単ですね。
Tidymodels
ちなみに私が普段利用するR言語には、Tidymodels という機械学習をサポートするパッケージが存在します。まだまだ発展途上のものではありますが、名前の通りTidyverseとTidymodelsの相性が最高で、Rユーザーとしては大変心地良いものです。
Tidymodelsではランダムフォレストは以下のように書きます。
library(tidyverse)
library(tidymodels)
# irisデータ
data("iris")
# データの分割
data_split <- initial_split(iris, prop = 0.9)
#
train <- training(data_split)
test <- testing(data_split)
# モデル式の定義 (レシピ)
recipe <- train %>%
recipe(formula = Species ~ .)# %>%
# 特徴量エンジニアリングはここで設定できる
# step_normalize(all_predictors())
# アルゴリズムの指定 (スペック)
rforest_spec <-
rand_forest(
min_n = tune(), # ノード分割に必要とする最小サンプル数
# trees = tune(), # 木の本数
) %>%
set_engine('randomForest') %>%
set_mode('classification')
# パラメータチューニング
rforest_params <- rforest_spec %>%
tune_grid(
# レシピ
preprocessor = recipe,
# クロスバリデーション用のデータ
resample = vfold_cv(train, v = 5),
# 探索するパラメータの組み合わせ
grid = expand.grid(
min_n = c(2, 5, 10)
# trees = c(10, 20, 30)
)
)
# 最適なパラメータの選択とスペックの更新
rforest_best_spec <- rforest_params %>%
select_best(metric = "accuracy") %>%
finalize_model(x = rforest_spec, parameters = .)
# ワークフローの設定
rforest_flow <- workflow() %>%
add_recipe(recipe) %>%
add_model(rforest_best_spec)
# 訓練データをもとに学習
rforest_fitted <- rforest_flow %>% fit(data_train)
# テストデータを元に予測
rforest_fit %>%
augment(new_data = test) %>%
accuracy(Species, .pred_class)
Tidymodelsによる学習は、scikit-learnと比較してコードこそ長くなっていますが、dplyrでのデータ操作からそのまま学習に繋げられたり、学習の結果をパイプでggplot2に渡せたりと、Tidyverseとの連携が強いという大きなメリットがあります。
最後に
私はこれまで Tidy な世界に浸っていましたが、Pythonのscikit-learnを学ぶことで、新たな視点やスキルを得ることができました。R言語も楽しい言語ですが、異なるツールに触れることで自分の可能性を広げられると実感しています。
日々勉強ですね。