Optimizing hyperparameters with hyperopt

I sometimes use hyperopt library when I need to tune hyperparameters. It works good and can give you a better result. A simple example how to use it for classification problems:

  • Input data: X, y
  • Output: best (best parameters)
import time
from hyperopt import fmin, tpe, hp, STATUS_OK, Trials
import xgboost as xgb

def objective(params):
    params['max_depth'] = int(params['max_depth'])
    params['learning_rate'] = float(params['learning_rate'])
    params['subsample'] = float(params['subsample'])
    params['colsample_bytree'] = float(params['colsample_bytree'])
    params['min_child_weight'] = float(params['min_child_weight'])
    params['objective'] = 'multi:softprob'
    params['eval_metric'] = 'merror'
    params['booster'] = 'gbtree'
    params['num_class'] = 5
    params['silent'] = 1
    params['nthread'] = 10
    params['seed'] = 2017
    
    global X, y, best
    
    RANDOM_STATE = 2
    n_folds = 18
    scores = []
    
    kf = StratifiedKFold(n_folds, random_state=RANDOM_STATE, shuffle = True)
    print('..........................')

    for i, (train_index, test_index) in enumerate(kf.split(X, y)):
        X_train, X_val = X[train_index], X[test_index]
        y_train, y_val = y[train_index], y[test_index]    

        xgtrain = xgb.DMatrix(X_train, label=y_train)

        X_val2 = xgb.DMatrix(X_val, label=y_val)

        watchlist = [(xgtrain, 'train'), (X_val2, 'eval')]

        model = xgb.train(params, xgtrain, 60000, watchlist, early_stopping_rounds=100, verbose_eval=False) 
        
        lg = model.predict(X_val2, ntree_limit=model.best_ntree_limit) 
        res = [np.argmax(lg[i]) for i in range(lg.shape[0])]
        scores.append(accuracy_score(y_val, res))
        print('Xgboost', scores[-1])
    
    score = np.mean(scores)
    
    print("############### Score: {0}".format(score))
    print("############### Prms: ", params)
    print('..........................')
    
    return {
        'loss': 1-score,
        'status': STATUS_OK,
        'eval_time': time.time(),
        }

xgb_space = {
        'learning_rate': hp.quniform('eta', 0.005, 0.05, 0.005),
        'max_depth': hp.quniform('max_depth', 3, 14, 1),
        'min_child_weight': hp.quniform('min_child_weight', 1, 10, 1),
        'subsample': hp.quniform('subsample', 0.5, 1, 0.05),
        'gamma': hp.quniform('gamma', 0.5, 1, 0.01),
        'colsample_bytree': hp.quniform('colsample_bytree', 0.4, 1, 0.05),
        
}

                                  
trials = Trials()
best = fmin(objective,
    space=xgb_space,
    algo=tpe.suggest,
    max_evals=100,
    trials=trials)

print (best)

 

XGBoost: полезности, трюки, наблюдения

Буду сюда записывать всякие фишки xgboost.

“Ранняя” остановка обучения модели

Early stoppping rounds – позволяет остановить обучение, если на  протяжении N шагов не было улучшения результата:

bst = xgb.train(params, dtrain, num_rounds, watchlist, early_stopping_rounds=N)

Изменение eta в процессе обучения модели

Один из основных параметров xgboost – eta непосредственно влияет на скорость обучения. Иногда возникает потребность динамически менять этот параметр во время обучения. В этом случае в методе train можно передать аргумент learning_rates. В качестве значения может выступать функция или список.

Например, можно сделать так, чтобы сначала eta была больше, а потом постепенно уменьшалась.

Идея в целом богатая, но не всегда это хорошо влияет на итоговое решение. Грубо говоря, 50 деревьев строятся быстрее, чем 500, но точность результата может быть ниже.

Вывод результатов кросс-валидации через каждые N шагов обучения

Иногда нет смысла выводить промежуточные оценки на каждом шаге обучения. Убирать вывод этой информации совсем тоже не всегда удобно. В этом случае можно использовать параметр verbose_eval=N — в этом случае оценки будут выводиться через каждые N шагов. Очень удобно, когда строится большое количество деревьев.

Sparse матрицы

Иногда xgboost падает по неведомым причинам, если использовать csr_matrix. Где-то читал, что это происходит, если в последней колонке все нули. При этом  csс_matrix не вызывает подобных проблем.

Преобразование списков: избавление от вложенности

Предположим, у нас есть список вида:

data = [[2,3,4], [5], [6,7]]

Нужно убрать вложенность и привести его к виду: [2, 3, 4, 5, 6, 7]

Решения:

a). Генератор списков:

[x for element in data for x in element]

a). Неочевидный вариант:

sum(data, [])

Первый вариант в разы быстрее. Второй, скорее, для баловства (подсмотрел на Хабре)

Задача с Kaggle: Predicting Red Hat Business Value

В этой заметке задокументирую основные шаги решения конкурсной задачи от Red Hat. Конкурс проходил на площадке Kaggle.

Времени лично у меня было очень мало – около 7-10 дней. Поэтому финальный результат – ТОП 12%, хотя до последнего дня держался в ТОП 9%. В принципе это неплохо (учитывая, что это мое второе подобное соревнование), но можно было лучше.

Вот здесь можно скачать упрощенный вариант моего решения. Эта версия кода дает результат порядка 99% AUC (это далеко не лучшее мое решение, но зато очень наглядное и простое; в финальном варианте я использовал микс из более сложных моделей)

Исходные данные

Компания Red Hat предоставила для соревнования информацию о своих клиентах. Данные, как и во многих задачах, обезличены. В одной таблице хранится какая-то персональная информация о людях. В другой информация об их активности (возможно, это какие-то покупки, предзаказы, обращения в службу поддержки или что-то типа этого).

В задаче нужно выявить людей, которые потенциально могут принести наибольшую пользу бизнесу. Фактически нужно поставить 1 или 0 напротив каждой активности.

Используемая метрика: AUC. (more…)

Read More

Линейная регрессия. Простая реализация на Python.

Захотелось глубже разобраться с основными алгоритмами машинного обучения и анализа данных. Для этой цели решил сделать собственные реализации этих алгоритмов на языке Python. Начну с обычной линейной регрессии, а в дальнейшем сделаю аналогичные заметки про нейронные сети, решающие деревья и т.д.

Цитата из Wiki: Линейная регрессия (англ. Linear regression) — используемая в статистике регрессионная модель зависимости одной (объясняемой, зависимой) переменной от другой или нескольких других переменных (факторов, регрессоров, независимых переменных) с линейной функцией зависимости.

Итак. Буду делать упрощенный аналог LinearRegression() из sklearn.

Финальный вариант кода можно скачать или посмотреть на github. (more…)

Read More

Преобразование элементов списка из типа str в int

Недавно потребовалось проделать такую операцию:

  • преобразовать список символов [‘1’, ‘2’, ‘3’, ‘4’, ‘5’] в список чисел [1, 2, 3, 4, 5]

Делается это так:

s = ['1', '2', '3', '4', '5']
s = map(int, s)

Аналогично можно сделать преобразование с другими типами.