315
348

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

RossoAdvent Calendar 2017

Day 16

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

Last updated at Posted at 2017-12-15

概要

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使いこなせてないので、ガシガシ使っていきたいです!

315
348
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
315
348

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?