Easy way to make a pivot table

I often work with databases and sometimes I need to transform raw data into pivot table. Many people doesn’t know it might be done by using pivot_table() from pandas library.

Let’s say we have a table where id and key1_N are keys. And we want to transform it into a new form like this:

pivot_tables

How to do it:

import pandas as pd

df = pd.DataFrame({
 'id': [1,1,1,2,2,2],
 'key1_N': [1,2,3,1,2,3],
 'var1': [3,4,8,3,4,8],
 'var2': [5,1,6,6,1,1]
 })
df = df.pivot_table(index='id', columns='key1_N', values=['var1', 'var2'])

After using this operation we get a table with two-level columns. But we can change the value of df.columns:

import itertools 
df.columns = list([x[0] + '_' + str(x[1]) for x in itertools.product(df.columns.levels[0], df.columns.levels[1])])

I’ve moved to the US

My wife and I moved to the US a few weeks ago and now we live in San Jose, CA. It’s an amazing place, where I really love to be. Now I explore local life and looking for a job in machine learning field. I believe I can be very valuable for any tech company in this area. So if you read this post and you have any relevant positions write to me please 🙂

A few pictures from our new californian life:

IMG_8139

IMG_8171

IMG_8155

HiveQL: Partitioned Tables

I work on a project where we have a really huge dataset and we use a Hadoop cluster. I often need to select data from a specific table where one of columns is date. If table is really huge it takes a lot of time to make queries like this: “select * from table_name where day=’2015-05-01′”.

It’s better to use partitioned tables in this case (HiveQL querie example):

CREATE TABLE schema.table_A (field1 int, field2 string, field3 float)
PARTITIONED BY (day) stored as orc

Selecting data from this type of tables is much faster, because each day is actually stored in a separate file on a disk.

If we want to insert data into this table with overwriting we should use a query like this:

INSERT OVERWRITE TABLE schema.table_A PARTITION (day = '2015-05-01')
select * from table_B

 

 

How to find prime numbers

A simple function that allow to find first N prime numbers:

def primes(n):
    
    numbers = set(range(2, n))
    
    for j in range(2, int(np.sqrt(n))):
        numbers -= set(range(2*j, n, j))
    
    return sorted(list(numbers))

print(primes(n=100))

 

How to get a list of dates

Let’s say we have two different dates and we want to make a list of all dates that are between them. Here is an easy way to do it:

import datetime

date1 = datetime.datetime.strptime("2015-04-05", "%Y-%m-%d").date()
date2 = datetime.datetime.strptime("2015-06-30", "%Y-%m-%d").date()

DATES = [str(date1+datetime.timedelta(days=i)) for i in range((date2 - date1).days + 1) if date1+datetime.timedelta(days=i) <= date2]

 

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: Talking Data Mobile (TOP 5%)

В этой заметке хочу кратко описать основные действия в решении задачи на Kaggle от компании Talking Data Mobile.

По итогу соревнования  я вошел в ТОП 5%. Очень этому рад, так как это первое мое соревнование. Да и в принципе темой занимаюсь не так давно.

О чем задача

Если совсем кратко, то в задаче нужно было предсказать пол и возраст пользователей.

Теперь чуть подробнее… Компания Talking Data Mobile предоставила данные о пользователях мобильных приложениях из Китая:

tdmobile

(more…)

Read More