Pythonによるグリッド探索最適化アルゴリズム

このチュートリアルでは、非常に強力な最適化(または自動化)アルゴリズム、すなわちグリッド探索アルゴリズムについて説明します。これは、機械学習モデルにおけるハイパーパラメータのチューニングに最もよく使用されます。Pythonを使った実装方法を学ぶとともに、実際のアプリケーションに適用して、どのようにモデルの最適なパラメータを選択し、その精度を向上させることができるかを見ていきたいと思います。それでは、はじめましょう。

前提条件

このチュートリアルに従うには、Pythonまたはその他のプログラミング言語の基本的な理解を持っている必要があります。機械学習の基本的な知識もあることが望ましいですが、必須ではありません。それ以外は、この記事は初心者に優しく、誰にでも従うことができます。

インストール

このチュートリアルを進めるには、以下のライブラリ/フレームワークがシステムにインストールされている必要があります。

  1. Python 3
  2. NumPy
  3. パンダ
  4. Keras
  5. Scikit-Learn

それぞれをクリックすると、各パッケージのウェブサイトに移動し、詳しいインストール方法を見ることができます。一般的に、パッケージはpipを使ってインストールすることができます。

$ pip install numpy pandas tensorflow keras scikit-learn


何か問題が発生した場合は、各パッケージの公式ドキュメントを参照してください。

グリッド検索とは?

グリッドサーチは基本的に最適化アルゴリズムの一つで、最適化問題に最適なパラメータを、パラメータオプションのリストから選択することで、「試行錯誤」手法を自動化するものです。多くの最適化問題に適用できますが、最もよく知られているのは、機械学習において、モデルが最高の精度を発揮するパラメータを求めるために使用することです。

ここでは、以下の3つのパラメータを入力とするモデルを想定しています。

  1. 隠れ層の数 [2, 4]
  2. 各層のニューロン数 [5, 10] 3.
  3. エポック数 [10, 50]

各パラメータの入力に対して、2つの選択肢(上記の角括弧の中)を試したいとすると、合計で23=8通りの組み合わせになります(例えば、1つの可能な組み合わせは [2,5,10] )。これを手作業で行うとなると、頭が痛くなります。

ここで、10種類の入力パラメータがあり、各パラメータについて5つの可能な値を試したいと考えたとします。この場合、パラメータの値を変更するたびに手動で入力し、コードを再実行し、パラメータのすべての組み合わせの結果を追跡する必要があります。グリッドサーチは、各パラメーターに取りうる値を取り、コードを実行してすべての組み合わせを試し、それぞれの組み合わせの結果を出力し、さらに最も精度の高い組み合わせを出力するだけなので、このプロセスを自動化することができます。便利でしょう?

グリッド・サーチの実装

さて、話はここまで。では、実際にGrid Searchをアプリケーションに適用してみましょう。機械学習やデータ前処理の部分はこのチュートリアルの範囲外なので、単純にそのコードを実行し、Grid Searchが登場する部分について詳しく説明します。それでは始めましょう。

Pima Indian Diabetes データセットを使用します。このデータセットには、血糖値や血圧などの属性に基づいて、患者が糖尿病であるかどうかの情報が含まれています。Pandasの read_csv() メソッドを使うと、オンラインリソースから直接データセットをインポートすることができます。

以下のスクリプトでは、必要なライブラリをインポートしています。

from sklearn.model_selection import GridSearchCV, KFold
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.wrappers.scikit_learn import KerasClassifier
from keras.optimizers import Adam
import sys
import pandas as pd
import numpy as np


次のスクリプトは、データセットをインポートし、データセットのカラムヘッダを設定します。

columns = ['num_pregnant', 'glucose_concentration', 'blood_pressure', 'skin_thickness',
           'serum_insulin', 'BMI', 'pedigree_function', 'age', 'class']


data_path = "https://raw.githubusercontent.com/mkhalid1/Machine-Learning-Projects-Python-/master/Grid%20Search/pima-indians-diabetes.csv"


df = pd.read_csv(data_path, names=columns)


データセットの最初の5行を見てみましょう。

df.head()


出力してみましょう。

見ての通り、この5行は各カラムを説明するためのラベルなので(実際には9つある)、何の役にも立たない。まず、これらのデータでない行を削除し、次に NaN 値をすべて 0 に置き換える。

# Remove first 9 non-data rows
df = df.iloc[9:]


# Replace NaN (Not a Number) values with 0 in each column
for col in columns:
    df[col].replace(0, np.NaN, inplace=True)


df.dropna(inplace=True) # Drop all rows with missing values
dataset = df.values # Convert dataframe to numpy array


次のスクリプトは、データを特徴量とラベルに分割し、標準的なスケーリングを適用する。

X = dataset[:,0:8]
Y = dataset[:, 8].astype(int)


# Normalize the data using sklearn StandardScaler
from sklearn.preprocessing import StandardScaler


scaler = StandardScaler().fit(X)


# Transform and display the training data
X_standardized = scaler.transform(X)


data = pd.DataFrame(X_standardized)


次のメソッドは簡単なディープラーニングモデルを作成する。

def create_model(learn_rate, dropout_rate):
    # Create model
    model = Sequential()
    model.add(Dense(8, input_dim=8, kernel_initializer='normal', activation='relu'))
    model.add(Dropout(dropout_rate))
    model.add(Dense(4, input_dim=8, kernel_initializer='normal', activation='relu'))
    model.add(Dropout(dropout_rate))
    model.add(Dense(1, activation='sigmoid'))


# Compile the model
    adam = Adam(lr=learn_rate)
    model.compile(loss='binary_crossentropy', optimizer=adam, metrics=['accuracy'])
    return model


データセットをロードし、前処理を行い、機械学習モデルを作成するために実行する必要があるコードは、これだけです。今回はGrid Searchの機能を見ることにしか興味がないので、train/testの分割は行わず、データセット全体に対してモデルを当てはめることにします。

次の章では、Grid Searchがどのようにパラメータを最適化し、我々の生活をより快適にしてくれるかを見ていきます。

グリッドサーチを用いないモデルの学習

以下のコードでは、ランダムに、あるいは直感的に決めたパラメータ値を使ってモデルを作成し、そのモデルのパフォーマンスを確認します。

# Declare parameter values
dropout_rate = 0.1
epochs = 1
batch_size = 20
learn_rate = 0.001


# Create the model object by calling the create_model function we created above
model = create_model(learn_rate, dropout_rate)


# Fit the model onto the training data
model.fit(X_standardized, Y, batch_size=batch_size, epochs=epochs, verbose=1)


出力

Epoch 1/1
130/130 [==============================] - 0s 2ms/step - loss: 0.6934 - accuracy: 0.6000


精度は「60.00%」となりました。これはかなり低いですが、心配することはありません。しかし、心配はいりません!まだグリッド検索があるので、その日のうちに試してみましょう。では、さっそくやってみましょう。

グリッドサーチによるハイパーパラメータの最適化

グリッドサーチを使用しない場合、上で作成したモデルに対して直接 fit() メソッドを呼び出すことができます。しかし、グリッド検索を使うためには、 create_model() 関数にいくつかのパラメータを渡す必要があります。さらに、各パラメータに対して試したいさまざまなオプションを指定して、グリッドを宣言する必要があります。これを部分的に実行しましょう。

まず、 create_model() 関数を修正して、呼び出し元の関数からパラメータを受け取れるようにします。

def create_model(learn_rate, dropout_rate):
    # Create model
    model = Sequential()
    model.add(Dense(8, input_dim=8, kernel_initializer='normal', activation='relu'))
    model.add(Dropout(dropout_rate))
    model.add(Dense(4, input_dim=8, kernel_initializer='normal', activation='relu'))
    model.add(Dropout(dropout_rate))
    model.add(Dense(1, activation='sigmoid'))


# Compile the model
    adam = Adam(lr=learn_rate)
    model.compile(loss='binary_crossentropy', optimizer=adam, metrics=['accuracy'])
    return model


# Create the model
model = KerasClassifier(build_fn=create_model, verbose=1)


これでグリッド探索アルゴリズムを実装し、データセットをフィットさせる準備が整いました。

# Define the parameters that you wish to use in your Grid Search along
# with the list of values that you wish to try out
learn_rate = [0.001, 0.02, 0.2]
dropout_rate = [0.0, 0.2, 0.4]
batch_size = [10, 20, 30]
epochs = [1, 5, 10]


seed = 42


# Make a dictionary of the grid search parameters
param_grid = dict(learn_rate=learn_rate, dropout_rate=dropout_rate, batch_size=batch_size, epochs=epochs )


# Build and fit the GridSearchCV
grid = GridSearchCV(estimator=model, param_grid=param_grid,
                    cv=KFold(random_state=seed), verbose=10)


grid_results = grid.fit(X_standardized, Y)


# Summarize the results in a readable format
print("Best: {0}, using {1}".format(grid_results.best_score_, grid_results.best_params_))


means = grid_results.cv_results_['mean_test_score']
stds = grid_results.cv_results_['std_test_score']
params = grid_results.cv_results_['params']


for mean, stdev, param in zip(means, stds, params):
    print('{0} ({1}) with: {2}'.format(mean, stdev, param))


出力

Best: 0.7959183612648322, using {'batch_size': 10, 'dropout_rate': 0.2, 'epochs': 10, 'learn_rate': 0.02}


出力では、最高の精度をもたらすパラメータの組み合わせが得られることがわかります。

グリッドサーチはPythonで実装するのが非常に簡単で、人手による時間を大幅に節約できたと言ってよいでしょう。調整したいパラメータをすべて列挙し、テストする値を宣言してコードを実行すれば、あとは忘れてしまうのです。もう、あなたの側からの入力は必要ありません。最適なパラメータの組み合わせが見つかれば、それを最終的なモデルに使うだけでいい。

結論

まとめると、グリッドサーチとは何か、グリッドサーチがどのようにモデルの最適化に役立つか、そして自動化などの利点について学びました。さらに、Python言語を使って数行のコードで実装する方法を学びました。また、Grid Searchの有効性を確認するために、Grid Searchを行った場合と行わなかった場合の機械学習モデルの学習を行ったところ、Grid Searchを行った場合の方が19%高い精度を得ることができました。

タイトルとURLをコピーしました