{"cells":[
 {
  "cell_type": "code",
  "execution_count": null,
  "metadata": {
   "collapsed": false
  },
  "outputs": [],
  "source": "'''\nBased on https://www.kaggle.com/justdoit/rossmann-store-sales/xgboost-in-python-with-rmspe/code\nScore : 0.\n'''\n\n\nimport pandas as pd\nimport numpy as np\nfrom sklearn import cross_validation\nimport xgboost as xgb\nfrom datetime import date, timedelta\n\n\n#set random seed for reproducibility\nnp.random.seed(14566433)\n\n# Thanks to Chenglong Chen for providing this in the forum\ndef ToWeight(y):\n    w = np.zeros(y.shape, dtype=float)\n    ind = y != 0\n    w[ind] = 1./(y[ind]**2)\n    return w\n\n\ndef rmspe(yhat, y):\n    w = ToWeight(y)\n    rmspe = np.sqrt(np.mean( w * (y - yhat)**2 ))\n    return rmspe\n\n\ndef rmspe_xg(yhat, y):\n    # y = y.values\n    y = y.get_label()\n    y = np.exp(y) - 1\n    yhat = np.exp(yhat) - 1\n    w = ToWeight(y)\n    rmspe = np.sqrt(np.mean(w * (y - yhat)**2))\n    return \"rmspe\", rmspe\n\ndef factor(series):\n    dic = {}\n    for i,val in enumerate(series.value_counts().index):\n        dic[val] = i\n    return [ dic[val] for val in series.values ]   \n\n\n# Gather some features\ndef build_features(features, data, dates):\n    # remove NaNs\n    data.fillna(0, inplace=True)\n    data.loc[data.Open.isnull(), 'Open'] = 1\n        \n    # Use some properties directly\n    features.extend(['Store', 'CompetitionDistance', 'CompetitionOpenSinceMonth',\n                     'CompetitionOpenSinceYear', 'Promo', 'Promo2', 'Promo2SinceWeek', 'Promo2SinceYear'])\n\n    # add some more with a bit of preprocessing\n    #features.append('SchoolHoliday')\n    #data['SchoolHoliday'] = data['SchoolHoliday'].astype(float)\n    \n    features.append('StateHoliday')\n    data['StateHoliday'] = factor(data.StateHoliday)\n\n    features.append('DayOfWeek')\n    features.append('month')\n    features.append('day')\n    features.append('year')\n    data['Date'] = pd.to_datetime(data.Date)\n    data['Date'] = pd.DatetimeIndex(data.Date)\n    data = data.join(dates,on='Date')\n\n    features.append('StoreType')\n    data['StoreType'] = factor(data.StoreType) \n\n    features.append('Assortment')\n    data['Assortment'] = factor(data.Assortment) \n    \n    #add data from yesterday and tomorrow\n    features.extend(['OpenY','dayY',\n                     'OpenT','dayT'])\n                    \n    yesterday = data.copy(deep=True)\n    yesterday['Date'] = yesterday.Date + timedelta(days=1)\n    yesterday = yesterday.set_index(['Store','Date'])\n\n    tomorrow = data.copy(deep=True)\n    tomorrow['Date'] = tomorrow.Date - timedelta(days=1)\n    tomorrow = tomorrow.set_index(['Store','Date'])\n    data = data.join(yesterday[['Open','day']], on=['Store','Date'],rsuffix='Y')\n    data = data.join(tomorrow[['Open','day']], on=['Store','Date'],rsuffix='T')\n   \n    # remove new NaNs\n    # maybe assume smarter values later\n    data.fillna(0, inplace=True)\n    data.loc[data.Open.isnull(), 'Open'] = 1    \n    \n    return data\n\n\nprint(\"Load the training, test and store data using pandas\")\ntrain = pd.read_csv(\"../input/train.csv\")\ntest = pd.read_csv(\"../input/test.csv\")\nstore = pd.read_csv(\"../input/store.csv\")\n\nprint(\"Generate Dates Table\")\ndates = pd.DataFrame(pd.date_range(train.Date.min(),test.Date.max()),columns=['Date']).set_index('Date')\ndates['day']   = dates.index.day.astype(int)\ndates['month'] = dates.index.month.astype(int)\ndates['year']  = dates.index.year.astype(int)\n\nprint(\"Assume store open, if not provided\")\ntest.fillna(1, inplace=True)\n\nprint(\"Consider only open stores for training. Closed stores wont count into the score.\")\ntrain = train[train[\"Open\"] != 0]\n\nprint(\"Join with store\")\ntrain = pd.merge(train, store, on='Store')\ntest = pd.merge(test, store, on='Store')\n\nfeatures = []\n\nprint(\"Augment features\")\ntrain = build_features(features, train, dates)\ntest  = build_features([], test, dates)\nprint(features)\n\nparams = {\"objective\": \"reg:linear\",\n          \"eta\": 0.1,\n          \"max_depth\": 10,\n          \"subsample\": 0.85,\n          \"colsample_bytree\": 0.75,\n          \"silent\": 1\n          }\nnum_trees = 2000\n\nprint(\"Train a XGBoost model\")\nval_size = 100000\ntrain = train.sort(['Date'])\nprint(train.tail(1)['Date'])\n\n\nX_train, X_test = cross_validation.train_test_split(train, test_size=0.01)\n#X_train, X_test = train.head(len(train) - val_size), train.tail(val_size)\ndtrain = xgb.DMatrix(X_train[features], np.log(X_train[\"Sales\"] + 1))\ndvalid = xgb.DMatrix(X_test[features], np.log(X_test[\"Sales\"] + 1))\ndtest = xgb.DMatrix(test[features])\nwatchlist = [(dvalid, 'eval'), (dtrain, 'train')]\ngbm = xgb.train(params, dtrain, num_trees, evals=watchlist, early_stopping_rounds=50, feval=rmspe_xg, verbose_eval=True)\n\nprint(\"Validating\")\ntrain_probs = gbm.predict(xgb.DMatrix(X_test[features]))\nindices = train_probs < 0\ntrain_probs[indices] = 0\nerror = rmspe(np.exp(train_probs) - 1, X_test['Sales'].values)\nprint('error', error)\n\nprint(\"Make predictions on the test set\")\ntest_probs = gbm.predict(xgb.DMatrix(test[features]))\nindices = test_probs < 0\ntest_probs[indices] = 0\nsubmission = pd.DataFrame({\"Id\": test[\"Id\"], \"Sales\": np.exp(test_probs) - 1})\nsubmission.to_csv(\"xgboost_kscript_submission.csv\", index=False)"
 }
],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"}}, "nbformat": 4, "nbformat_minor": 0}