December 15, 2015
Rossmann Store Sales результаты и скрипт с описанием
Вчера завершился конкурс Rossmann Store Sales от Kaggle. Это второе мое участие в подобных мероприятиях. Участие в таком конкурсе дает очень много полезных навыков и знаний. Можно сравнить с большой задачей, которую ставят для страны (отправить человека на луну), которая тянет за собой развитие науки.
Чтобы некоторые знания все же не потерялись, я решил выложить скрипт, который который обеспечил мне 1468 место из 3423. В 50% я попал :)
import pandas as pd import numpy as np from pandas import Series, DataFrame import math from sklearn.ensemble import RandomForestClassifier from sklearn.ensemble import GradientBoostingClassifier from sklearn.linear_model.logistic import LogisticRegression from datetime import datetime from sklearn import cross_validation import xgboost as xgbb # преобразуем строки в числа, чтобы можно было скармливать алгоритмам def dataPrepare(data): data['StateHoliday'] = data['StateHoliday'].map({ '0': 0, 'a': 1, 'b': 2, 'c': 3, 0: 0 }).astype(int) data['Open'] = data['Open'].fillna(1) #CHECK return data train_file = 'train.csv' test_file = 'test.csv' output_file = 'predictions.csv' # Читаем данные, добавляем недостающие столбцы # индекс у нас тут - время # Парсим дату train = pd.read_csv(train_file, index_col='Date', parse_dates=['Date']) train['Date'] = train.index train['Week'] = train.index.week train['Year'] = train.index.year train['Month'] = train.index.month train['Quarter'] = train.index.quarter train = dataPrepare(train) test = pd.read_csv(test_file, parse_dates=['Date']) test = dataPrepare(test) # dt - для работы с datetime test['Week'] = test.Date.dt.week test['Year'] = test.Date.dt.year test['Month'] = test.Date.dt.month test['Quarter'] = test.Date.dt.quarter stories = [1,3,7,8,9]#set(test.Store.values) stories = set(test.Store.values) # Столбцы для предсказаний predictors = [ 'DayOfWeek', # 'Date', 'Week', 'Year', 'Month', 'Quarter', # 'Sales2', # 'Customers', 'Open', 'Promo', 'StateHoliday', 'SchoolHoliday' ] # Параметры для XGBoost алгоритма params = {"objective": "reg:linear", "eta": 0.02, "booster": "gbtree", "max_depth": 10, "min_child_weight": 15, "silent": 1, "subsample": 0.9, "colsample_bytree": 0.7} num_trees=1000 # Эта функци для дискредитации данных продаж. # Берётся распределение продаж и делится на равновероятные участки. # Каждой продаже присваивается номер. def saleCode(x, division): for i, value in enumerate(division[:-1]): if value - 1 < x < division[i + 1] + 1: return i break print('Start group') # Отличный алгоритм подсмотренный мною у лидеров. # Группируются записи по трём столбцам и делается предположение, # что медиана будет продолжаться и в предсказываемых месяцах columns = ['Store', 'DayOfWeek', 'Promo'] medians = train.groupby(columns)['Sales'].median() medians = medians.reset_index() test2 = pd.merge(test, medians, on = columns, how = 'left') assert(len(test2) == len(test)) test2.loc[ test2.Open == 0, 'Sales' ] = 0 test['Sales'] = test2['Sales'] print('Group stories finished') test.loc[:, 'Sales_rf'] = 0 test.loc[:, 'Sales_xgb'] = 0 # Дальше по каждому магазину рассчет отдельно for s in stories: # Первый алгоритм - распределение и RandomForest f1_full = train[train.Store==s] f1 = DataFrame(f1_full[f1_full.Open==1]) count,division = np.histogram(f1.Sales.values, 7) storeTrue = {} for i, value in enumerate(division[:-1]): storeTrue[i] = np.mean([value, division[i+1]]) f1.loc[:, 'Sales2'] = f1.apply(lambda row: saleCode(row['Sales'], division), axis=1) alg = RandomForestClassifier(random_state=1, n_estimators=100, min_samples_split=3, min_samples_leaf=3) alg.fit(f1[predictors], f1['Sales2']) t1_full = test[test.Store==s] t1 = t1_full[t1_full.Open==1] predictions = alg.predict(t1[predictors]) test.loc[(test.Store==s) & (test.Open==1), 'Sales_rf'] = list(map(lambda x: storeTrue[x], predictions)) test.loc[(test.Store==s) & (test.Open==0), 'Sales_rf'] = 0 print ('Random forest store done: ' + str(s)) # Второй алгоритм - XGBoost train1 = train[train.Store==s] test1 = test[test.Store==s] gbm1 = xgbb.train(params, xgbb.DMatrix(train1[predictors], train1["Sales"]), num_trees) test_probs = gbm1.predict(xgbb.DMatrix(test.loc[test.Store==s, predictors])) test.loc[test.Store==s, 'Sales_xgb'] = test_probs print ('XGBoost store done: ' + str(s)) test.loc[test.Open==0, 'Sales_xgb'] = 0 # Среднее значение для для всех трёх алгоритмов test.loc[:, 'Sales'] = test['Sales']/3.0 + test['Sales_rf']/3.0 + test['Sales_xgb']/3.0 test.loc[test.Open==0, 'Sales'] = 0 test.head(12) test.describe() assert(test2.Sales.isnull().sum() == 0) test[[ 'Id', 'Sales' ]].to_csv(output_file, index = False) print("Up the leaderboard!")