Оптимізація з алгоритмом Grid Search у Python

8 хв. читання

Вступ

У цьому посібнику ми поговоримо про потужний алгоритм оптимізації під назвою Grid Search. Найчастіше його використовують для оптимізації гіперпараметрів в моделях машинного навчання.

Після прочитання матеріалу ви навчитесь реалізовувати цей алгоритм у Python і використовувати його в реальних застосунках. Наприкінці ми проаналізуємо, як за допомогою Grid Search обрати найкращі параметри для моделей, щоб покращити їхню точність.

Почнемо!

Призначення

Аби ліпше зрозуміти, про що йде мова, ви повинні володіти основами Python або іншої мови програмування. Бажано (але не обов'язково) мати також базові знання з машинного навчання. Загалом матеріал буде зрозумілим та корисним як початківцю, так і досвіченому розробнику.

Приготування

Щоб повторювати кроки з посібника, встановіть такі бібліотеки та фреймворки:

Інструкції встановлення є на перелічених офіційних сайтах. Загалом пакети можна встановити за допомогою pip у такий спосіб:

$ pip install numpy pandas tensorflow keras scikit-learn

Якщо у вас виникнуть будь-які проблеми, зверніться до офіційної документації потрібного пакета.

Що таке Grid Search

Grid Search — це алгоритм, який обирає найкращі параметри для моделі з переліку варіантів, які ви пропонуєте. Тобто це своєрідна автоматизація методу «спроб і помилок».

Хоч алгоритм можна застосувати для розв'язання багатьох оптимізаційних проблем, найчастіше його використовують в алгоритмах машинного навчання — для отримання параметрів, за яких модель дає найкращу точність.

Припустимо, ваша модель приймає такі параметри:

  1. кількість прихованих шарів [2, 4];
  2. кількість нейронів на кожному рівні [5, 10];
  3. кількість епох [10, 50].

Якщо для кожного параметра на вході ми хочемо спробувати два варіанти значень (вказані у квадратних дужках), ми отримуємо 2^3 = 8 різних комбінацій (наприклад, одна з можливих комбінацій — [2,5,10]). Вручну перебирати всі варіанти було б неприємно.

Тепер уявімо ситуацію, коли є 10 вхідних параметрів і необхідно протестувати 5 різних варіантів значень для кожного. В такому випадку вам потрібно було б вручну вводити параметри при кожному новому значенні, повторно запускати код та слідкувати за результатами всіх комбінацій.

Grid Search автоматизує цей процес: алгоритм приймає можливі значення для кожного параметра, запускає код, виводить результат для кожної комбінації та сам обирає ту, яка дає найкращу точність. Корисно, чи не так?

Реалізація алгоритму Grid Search

Досить балачок, перейдемо до роботи. Використаємо Grid Search в реальному застосунку. Ми не фокусуватимемось на деталях машинного навчання та попередньої обробки даних, натомість звернемо увагу на ті моменти, де безпосередньо використовується алгоритм.

Для прикладу візьмемо набір даних про індійський діабет Піма. Датасет містить інформацію про стан пацієнта і наявність в нього захворювання, ґрунтуючись на таких параметрах, як кількість глюкози в крові, кров'яний тиск тощо.

З методом 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()

Результат:

Оптимізація з алгоритмом Grid Search у Python

Як бачимо, всі 5 рядків — це просто описання для кожної колонки (насправді їх 9). Їх потрібно позбутися, тож почнемо з видалення всіх рядків, де немає даних, а потім замінимо всі значення NaN на 0.

# Видаляємо перші 9 рядків без даних
df = df.iloc[9:]

# Змінюємо значення NaN (Not a Number) на 0 в кожній колонці
for col in columns:
    df[col].replace(0, np.NaN, inplace=True)

df.dropna(inplace=True) # Видаляємо всі рядки з пропущеними значеннями
dataset = df.values # Конвертуємо у numpy array

Цей скрипт поділяє дані на набори ознак і позначок та застосовує стандарте масштабування для датасету:

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

# Нормалізуємо дані, використовуючи sklearn StandardScaler
from sklearn.preprocessing import StandardScaler

scaler = StandardScaler().fit(X)

# Трансформуємо та демонструємо тренувальні дані 
X_standardized = scaler.transform(X)

data = pd.DataFrame(X_standardized)

Такий метод створює просту модель глибокого навчання:

def create_model(learn_rate, dropout_rate):
    # Створюємо модель
    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'))

    # Компілюємо модель
    adam = Adam(lr=learn_rate)
    model.compile(loss='binary_crossentropy', optimizer=adam, metrics=['accuracy'])
    return model

Це весь потрібний код, щоб завантажити набір даних, попередньо обробити його і створити модель машинного навчання. Та оскільки нас цікавить лише алгоритм Grid Search, ми не виконуємо розбиття на тренувальну й тестову вибірки, а використаємо модель на повному наборі даних.

Далі ми побачимо, як Grid Search спрощує наше життя, оптимізуючи параметри моделі.

Тренування моделі без Grid Search

У фрагменті коду нижче ми створимо модель, використовуючи значення параметрів, які ми обрали інтуїтивно. Поспостерігаємо, які результати дасть наша модель:

# Оголошуємо значення параметра
dropout_rate = 0.1
epochs = 1
batch_size = 20
learn_rate = 0.001

# Створюємо об'єкт моделі, викликаючи метод create_model, який ми створили вище
model = create_model(learn_rate, dropout_rate)

# Передаємо моделі тренувальні дані
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%, а це досить низький результат. Проте не варто турбуватись! Grid Search прийде нам на допомогу.

Оптимізація гіперпараметрів з Grid Search

Якщо ви не використовуєте алгоритм Grid Search, то можете напряму викликати метод fit() для створеної моделі. А от для Grid Search нам необхідно передати деякі параметри у функцію create_model(). Ба більше, нам необхідно проініціалізувати сітку (grid) різними значеннями, які ми хочемо спробувати для кожного з параметрів. Зробимо все поступово.

Спершу ми змінимо функцію create_model(), аби вона приймала параметри з функції, що викликається.

def create_model(learn_rate, dropout_rate):
    # Створюємо модель
    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'))

    # Компілюємо модель
    adam = Adam(lr=learn_rate)
    model.compile(loss='binary_crossentropy', optimizer=adam, metrics=['accuracy'])
    return model

# Створюємо модель
model = KerasClassifier(build_fn=create_model, verbose=1)

Тепер ми готові реалізувати алгоритм Grid Search і тренувати модель на наборі даних.

# Ініціалізуємо параметри, які ми хотіли б використовувати в алгоритмі,
# переліком значень 
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

# Створюємо словник параметрів grid search 
param_grid = dict(learn_rate=learn_rate, dropout_rate=dropout_rate, batch_size=batch_size, epochs=epochs )

# Збираємо та тренуємо GridSearchCV
grid = GridSearchCV(estimator=model, param_grid=param_grid,
                    cv=KFold(random_state=seed), verbose=10)

grid_results = grid.fit(X_standardized, Y)

# Підсумовуємо результати в читабельному форматі 
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}

Тут ми бачимо, що алгоритм дає нам комбінацію параметрів, з якими наша модель найточніша.

Можна сміливо сказати, що алгоритм Grid Search досить легко реалізувати в Python. До того ж він рятує розробника від значної кількості рутинної роботи. Ви просто передаєте перелік параметрів, оголошуєте значення, які хотіли б перевірити, запускаєте код — і забуваєте про головний біль. Більше жодного вводу даних з вашого боку. Одразу, як буде знайдено найкращу комбінацію параметрів, ви просто використаєте її для вашої моделі.

Висновок

В матеріалі ми розглянули сутність алгоритму Grid Search, його методи оптимізації моделі та переваги такого підходу. Ба більше, ми розглянули, як в декілька рядків реалізувати такий алгоритм у Python, а потім спробували натренувати реальну модель з використанням алгоритму та без нього. Точність моделі з використанням алгоритму Grid Search була більшою на 19%.

Помітили помилку? Повідомте автору, для цього достатньо виділити текст з помилкою та натиснути Ctrl+Enter
Codeguida 5.8K
Приєднався: 8 місяців тому
Коментарі (0)

    Ще немає коментарів

Щоб залишити коментар необхідно авторизуватися.

Вхід / Реєстрація