337
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

updated at

機械学習ライブラリ scikit-learnの便利機能の紹介

概要

Pythonの機械学習系ライブラリscikit-learnの基本的な使い方と、便利だなと思ったものを記載しました。

類似記事は沢山ありますが、自分自身の整理のためにもまとめてみました。
これから、scikit-learnを利用する人にとって、役立つ記事になったら嬉しいです。

準備

  1. Pythonインストール : Windows / Mac
  2. scikit-learnインストール
pip install scikit-learn

公式サイト

基本的なモデルクラスの使い方

  1. モデルインスタンス生成
  2. fitさせる (学習)
  3. predictする (予測)

scikit-learnはAPIが統一されていて、とてもわかりやすいです。

SVMの例

  • import文
svm.py
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
import numpy as np
import pandas as pd
  • データセットを適当に作成
svm.py
# class: 0
df_a = pd.DataFrame({'x1': np.random.randn(100),
                     'x2': np.random.randn(100),
                     'y' : 0})
# class: 1
df_b = pd.DataFrame({'x1': np.random.randn(100) + 5,
                     'x2': np.random.randn(100) + 3,
                     'y' : 1})
df = df_a.append(df_b)

# トレーニングデータとテストデータに分割
X_train, X_test, y_train, y_test = \
    train_test_split(df[['x1','x2']], df['y'], test_size=0.2)
  • モデルクラスを利用した学習と予測
svm.py
# 1. モデルインスタンス生成
clf = SVC()

# 2. fit 学習
clf.fit(X_train, y_train)

# 3. predict 予測
y_pred = clf.predict(X_test)

SVMによる予測結果がy_predに格納されます。

SVM.png

回帰も分類も生成するモデルのクラスを変えるだけで、様々なモデルを簡単に構築できます。

便利機能

ダミー変数変換

LabelEncoder と OneHotEncoder

LabelEncoder : 文字を数値に変換
OneHotEncoder : 数値をダミー変数に変換

合わせると、カテゴリカル変数をダミー変数に置き換えることができる。

class_report.py
from sklearn.preprocessing import OneHotEncoder, LabelEncoder

le = LabelEncoder()
oe = OneHotEncoder()
en = le.fit_transform(['orange','orange','apple','banana','apple'])
print(oe.fit_transform(en.reshape(-1, 1)).toarray())

dummy.png

イメージ
dummy_image.png

※次のバージョン(v0.20)でCategoricalEncoderが追加されるようです!
CategoricalEncoder

データ分割

train_test_split

学習用データとテストデータを分けるため、データセットをランダムに分割する。

data_split.py
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = \
       train_test_split(X, y, test_size=0.2, random_state=0)

交差検証(CV)

cross_val_score

k分割交差検証法の結果を出力。

cross_val.py
from sklearn.model_selection import cross_val_score

clf = LogisticRegression()

# 5等分の交差検証
print(cross_val_score(clf, X, y, cv=5))
>> array([ 0.96551724,  0.93103448,  0.96428571,  0.89285714,  0.92857143])

イメージ

cv_image.png

ハイパーパラメータ選択

GridSearchCV

グリッドサーチと交差検証を同時に行う。

探索したいハイパーパラメータをdict形式で定義し、GridSearchCVの引数として渡す。
GridSearchCVのfitは、交差検証で最も良いスコアとなるハイパーパラメータで学習してくれる。
便利すぎでしょ!!

grid_cv.py
from sklearn.model_selection import GridSearchCV
from sklearn.ensemble import RandomForestClassifier

# 探索したハイパーパラメータ
param_grid = {'n_estimators': [2, 5, 10],
              'max_depth': [2, 5]}

grid_search = GridSearchCV(RandomForestClassifier(random_state=0), param_grid, cv=5)

# 最適なパラメータで学習
grid_search.fit(X_train, y_train)

print('test_score : {}'.format(grid_search.score(X_test, y_test)))
print('best_params : {}'.format(grid_search.best_params_))

# 各パラメータのCV平均スコア
display(display(pd.DataFrame(grid_search.cv_results_)\
       [['param_max_depth', 'param_n_estimators', 'mean_train_score']]))

結果

>> test_score : 0.9444444444444444
>> best_params : {'max_depth': 5, 'n_estimators': 10}

gridcv_pd.png

イメージ
gridcv_image.png

パイプライン

Pipeline

一連の処理ステップをEstimatorとしてまとめることができる。
① 標準化 → ② 次元削減 → ③ ランダムフォレストで学習
の流れを、グリッドサーチ+CVで検証する場合の例を記載。

グリッドサーチの探索パラメータはPipelineで指定した任意の文字列に”__”(アンダースコア2つ)を付けて指定。

Pipelineで指定できるEstimatorは最後のもの以外はtransformメソッドが定義されている必要がある。

pipe_line.py
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA

# パイプライン生成
pipe = Pipeline([('scaler', StandardScaler()),
                 ('pca', PCA()),
                 ('rf', RandomForestClassifier(random_state=0))])

# グリッドサーチ用の探索ハイパーパラメータ設定
param_grid = {
    'pca__n_components': [2, 3, 4],
    'rf__n_estimators' : [2, 10, 100],
    'rf__max_depth' : [10, 100, 1000]
}

grid_search = GridSearchCV(pipe, param_grid , cv=5)
grid_search.fit(X_train, y_train)

print('test_score : {}'.format(grid_search.score(X_test, y_test)))
print('best_params : {}'.format(grid_search.best_params_))

結果

>> test_score : 0.9722222222222222
>> best_params : {'pca__n_components': 2, 'rf__max_depth': 10, 'rf__n_estimators': 10}

(標準化+PCAがランダムフォレストに適するかはスルーで)

make_pipeline

各ステップに明示的に名前をつけなくても、自動でクラス名の小文字によって名前を付けてくれる。

make_pipeline.py
from sklearn.pipeline import make_pipeline

pipe = make_pipeline(StandardScaler(), PCA(), RandomForestClassifier(random_state=0))

param_grid = {
    'pca__n_components': [2, 3, 4],
    'randomforestclassifier__n_estimators' : [2, 10, 100],
    'randomforestclassifier__max_depth' : [10, 100, 1000]
}

特徴量選択

SelectKBest

特徴量をk個に絞る。

  • 分類 ( score_func=f_classif ) はANOVAによって、関連が高い特徴量を選択している。

  • 回帰 ( score_func=f_regression ) は相関係数によって、関連が高い特徴量を選択している。

from sklearn.feature_selection import SelectKBest, f_regression

sb= SelectKBest(score_func=f_regression, k=10) 
sb.fit(X, y)
X_sb = sb.transform(X)

SelectPercentile

特徴量を割合で指定して絞る。

from sklearn.feature_selection import SelectPercentile

sp = SelectPercentile(percentile=50)
sp.fit(X, y)
X_sp = sp.transform(X)

評価(分類)

classification_report

分類問題の評価基準であるprecision(適合率)、recall(再現率)、f1-score(F値)、support(実際のサンプル数)を出力。

class_report.py
from sklearn.metrics import classification_report

classification_report(y_true, y_pred)

class_report.png

confusion_matrix

混同行列を出力

confusion_matrix.py
from sklearn.metrics import confusion_matrix

print(confusion_matrix(y_test, y_pred))

confusion_matrix.png

イメージ
confusion_matrix_image.png

評価(回帰)

mean_squared_error

平均二乗誤差を出力。

MSE = \frac{1}{n} \ \sum_{i=1}^{n} (f_{i}-y_{i})^2 \\
mse.py
from sklearn.metrics import mean_squared_error

# RMSE
np.sqrt(mean_squared_error(y_test, y_pred))
>> 0.62519679744672363

文章のTF-IDFベクトル変換

Tfidfvectorizer

文章内における単語の重要度を数値化するTF-IDF法の結果を出力。

tf-idf.py
from sklearn.feature_extraction.text import TfidfVectorizer

tf_idf = TfidfVectorizer()
X = tf_idf.fit_transform(['Hello mom.',
                          'I am tired.',
                          'I am lazy.',])
print(X.toarray())

結果

[[ 0.          0.70710678  0.          0.70710678  0.        ]
 [ 0.60534851  0.          0.          0.          0.79596054]
 [ 0.60534851  0.          0.79596054  0.          0.        ]]

データセット

データセットがついている。
とりあえず、何かデータセットが必要な時に便利。

API 説明      
load_boston   米国ボストン市郊外における地域別の住宅価格 回帰
load_iris    3 種類の品種のアヤメのがく片、花弁の幅および長さ  分類
load_diabetes    糖尿病患者の検査数値と1年後の疾患進行状況  回帰
load_digits    0~9の手書き文字の8×8画像  分類
load_linnerud    成人男性の生理学的特徴と運動能力 回帰
load_wine    3種類のワインの科学的特徴  分類
load_breast_cancer    乳がんの診断結果 分類

データの取得

from sklearn.datasets import load_wine

# ワインデータ取得
data, target = load_wine(return_X_y=True)

おわり

誤った記載がありましたら、ご指摘いただけたら嬉しいです。
まだまだ、sklearn使いこなせてないので、ガシガシ使っていきたいです!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
337
Help us understand the problem. What are the problem?