ナード戦隊データマン

データサイエンスを用いて悪と戦うぞ

機械学習アルゴリズムの訓練時間・予測時間・精度を比較する

機械学習アルゴリズムをどのように使い分けるべきかを実験によって調べる場合、訓練時間・予測時間・スコアを比較することができます。ここでは、scikit learnで4種類のデータセットを用いて機械学習アルゴリズムを比較します。

実行の前提

  1. ハイパーパラメータの設定は全てデフォルト。
  2. fitメソッド、scoreメソッド、cross_val_scoreメソッドの実行時間と実行結果を保存。
  3. wine, breast_cancer, iris, digitsのデータセットを使用。
  4. Logistic Regression, SVM, Neural Network, Decision Tree, Random Forest, Naive Baysを比較する。
  5. Jupyter notebook上で実行する。

機械学習アルゴリズムとデータの準備

In[1]:

import time
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
from sklearn.datasets import load_wine, load_breast_cancer, load_digits, load_iris
from sklearn.neural_network import MLPClassifier
from sklearn.svm import SVC
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.linear_model import LogisticRegression

names = ["Logistic Regression", "SVM",
         "Decision Tree", "Random Forest", "Neural Net", "Naive Bayes"]

classifiers = [
    LogisticRegression(),
    SVC(kernel="linear"),
    DecisionTreeClassifier(),
    RandomForestClassifier(),
    MLPClassifier(),
    GaussianNB()]

wine = load_wine()
cancer = load_breast_cancer()
digits = load_digits()
iris = load_iris()

def feature2df(features, feature_names):
    return pd.DataFrame(features, columns=feature_names)

wine_X = feature2df(wine.data, wine.feature_names)
cancer_X = feature2df(cancer.data, cancer.feature_names)
digits_X = feature2df(digits.data, range(digits.data.shape[1]))
iris_X = feature2df(iris.data, iris.feature_names)

まず、上記では機械学習アルゴリズムとデータを準備しています。データはpandasのデータフレームに変換します。これは、後にget_dummiesを使うためです。

比較のための関数の定義

In[2]:

from sklearn.model_selection import cross_val_score
def calc_function(f, args):
    start = time.time()
    result = f(*args)
    end = time.time()
    return end-start, result

def comparison_algorithms(names, classifiers, X, y):
    X = pd.get_dummies(X)
    X = MinMaxScaler().fit_transform(X)
    
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.4, random_state=42)

    train_times = []
    predict_times = []
    scores = []
    cv_times = []
    cv_scores = []
    for name, clf in zip(names, classifiers):
        train_time,_ = calc_function(clf.fit, (X_train, y_train))
        train_times.append(train_time)
    
        predict_time,score = calc_function(clf.score, (X_test, y_test))
        predict_times.append(predict_time)
        scores.append(score)
    
        cv_time, cv_score = calc_function(cross_val_score, (clf, X, y, None, None, 5))
        cv_times.append(cv_time)
        cv_scores.append(np.mean(cv_score))
        
    df = pd.DataFrame()
    df["name"] = names
    df["train_time"] = train_times
    df["predict_time"] = predict_times
    df["score"] = scores
    df["cv_time"] = cv_times
    df["cv_score"] = cv_scores
    return df

あるデータに対して、定義された機械学習アルゴリズムを比較するための関数を作成します。関数内では、訓練時間、予測時間、スコアが保存され、リターンされます。

計測する

In[3]:

out = []
out.append(comparison_algorithms(names, classifiers, wine_X, wine.target))
out.append(comparison_algorithms(names, classifiers, cancer_X, cancer.target))
out.append(comparison_algorithms(names, classifiers, digits_X, digits.target))
out.append(comparison_algorithms(names, classifiers, iris_X, iris.target))

datanames = ["wine", "cancer", "digits", "iris"]
for dataname, result in zip(datanames, out):
    print("Data Name:{}".format(dataname))
    print(result)
    print("\n")

Out[3]:

Data Name:wine
                  name  train_time  predict_time     score   cv_time  cv_score
0  Logistic Regression    0.002610      0.000641  0.986111  0.018054  0.966790
1                  SVM    0.001496      0.000908  0.986111  0.023191  0.966790
2        Decision Tree    0.001209      0.000566  0.944444  0.021478  0.860202
3        Random Forest    0.023875      0.001569  1.000000  0.100898  0.950901
4           Neural Net    0.243258      0.001059  0.972222  1.522032  0.961385
5          Naive Bayes    0.000902      0.000476  1.000000  0.009933  0.955839


Data Name:cancer
                  name  train_time  predict_time     score   cv_time  cv_score
0  Logistic Regression    0.001921      0.000329  0.956140  0.020056  0.959600
1                  SVM    0.001695      0.000872  0.982456  0.021814  0.975406
2        Decision Tree    0.006896      0.000444  0.938596  0.046264  0.922709
3        Random Forest    0.022626      0.001710  0.973684  0.149544  0.957922
4           Neural Net    0.821436      0.001606  0.978070  5.262588  0.964971
5          Naive Bayes    0.000998      0.000587  0.942982  0.010320  0.928080


Data Name:digits
                  name  train_time  predict_time     score    cv_time  \
0  Logistic Regression    0.088956      0.001013  0.969402   0.623225   
1                  SVM    0.034714      0.022917  0.984701   0.306310   
2        Decision Tree    0.014316      0.000580  0.844228   0.107324   
3        Random Forest    0.033000      0.002935  0.942976   0.215034   
4           Neural Net    5.767171      0.012475  0.980529  33.911854   
5          Naive Bayes    0.002985      0.004757  0.810848   0.040868   

   cv_score  
0  0.929271  
1  0.949429  
2  0.779795  
3  0.899857  
4  0.936545  
5  0.797558  


Data Name:iris
                  name  train_time  predict_time     score   cv_time  cv_score
0  Logistic Regression    0.000795      0.000267  0.850000  0.009913  0.840000
1                  SVM    0.000545      0.000353  0.983333  0.008677  0.966667
2        Decision Tree    0.000418      0.000269  0.966667  0.007484  0.966667
3        Random Forest    0.016869      0.001472  0.983333  0.096257  0.953333
4           Neural Net    0.181788      0.000909  0.950000  1.093229  0.920000
5          Naive Bayes    0.001649      0.000819  0.966667  0.014592  0.953333

比較のための関数をデータごとに実行して計測します。

考察

計測結果から概ねわかることは以下です。

  1. ランダムフォレスト、ニューラルネットワークは訓練時間が最もかかる。
  2. ランダムフォレスト、ニューラルネットワークは予測時間が最もかかる。
  3. digitsデータでは、線形性を持ったアルゴリズムの精度が高い。
  4. Naive Bayesは訓練時間が極めて早い。
  5. SVMはどのデータでも良い精度が出ている。

一般にニューラルネットワークは精度が高いと言われますが、ハイパーパラメータの調整がうまく行かなければそれほど高い精度ではないことがわかります。ただし、ここで使われているデータはどれも単純なので、複雑なデータにおける結果でより顕著な差が見られる可能性はあります。

また、ここで比較されていないことは、以下のようなことです。

  1. 各モデル固有のフィールド(coef, feature_importances等)
  2. ハイパーパラメータに関して。
  3. より複雑なデータに対する予測精度。
  4. 特徴量エンジニアリングが与える影響の度合い。
  5. モデルの視覚化に関して。
  6. モデルの解釈の容易性に関して。

例えば、決定木はここで行われた比較ではあまり良い精度ではありませんでしたが、視覚化や解釈の容易性という観点から見れば優れたアルゴリズムといえます。また、ロジスティック回帰は、係数を見ることによって各特徴量の重要さがどの程度なのか理解するのに役立てられます。ランダムフォレストは特徴量の重要性を保存していますが、影響の方向までは特定できません。

参考

  1. https://docs.microsoft.com/ja-jp/azure/machine-learning/studio/algorithm-choice
  2. http://scikit-learn.org/stable/auto_examples/classification/plot_classifier_comparison.html