{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# An implementation of Light Gradient Boost Machine to predict indoor locations\n### built from work by BIZEN https://www.kaggle.com/hiro5299834/wifi-features-with-lightgbm-kfold\n\n## The notebook reads in the data produced by the extract-wifi-features notebook that we are collaborating on\n- the wifi features are currently only extracted for a couple of buildings\n- the next version will be data for all buildings\n\n## Algorithm built by Microsoft based on decision trees\nDecision trees are trained to predict:\n- regression for X coordinate\n- regression for Y coordinate\n- multiclassification for floor\n","metadata":{}},{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n# ------------------------------------------------------------------------------\nimport numpy as np\nimport pandas as pd\nimport scipy.stats as stats\nfrom pathlib import Path\nimport glob\n\nfrom sklearn.model_selection import KFold\nimport lightgbm as lgb\n\nimport psutil\nimport random\nimport os\nimport time\nimport sys\nimport math\nfrom contextlib import contextmanager\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# ------------------------------------------------------------------------------\n# Fixed values\n# ------------------------------------------------------------------------------\nN_SPLITS = 10\nSEED = 1\n\n# ------------------------------------------------------------------------------\n# File path definition\n# ------------------------------------------------------------------------------\nLOG_PATH = Path(\"./log/\")\nLOG_PATH.mkdir(parents=True, exist_ok=True)\n\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# ------------------------------------------------------------------------------\n# Utilities\n# ------------------------------------------------------------------------------\n@contextmanager\ndef timer(name: str):\n    t0 = time.time()\n    p = psutil.Process(os.getpid())\n    m0 = p.memory_info()[0] / 2. ** 30\n    try:\n        yield\n    finally:\n        m1 = p.memory_info()[0] / 2. ** 30\n        delta = m1 - m0\n        sign = '+' if delta >= 0 else '-'\n        delta = math.fabs(delta)\n        print(f\"[{m1:.1f}GB({sign}{delta:.1f}GB): {time.time() - t0:.3f}sec] {name}\", file=sys.stderr)\n\n\ndef set_seed(seed=1):\n    random.seed(seed)\n    os.environ[\"PYTHONHASHSEED\"] = str(seed)\n    np.random.seed(seed)\n\n    \ndef comp_metric(xhat, yhat, fhat, x, y, f):\n    intermediate = np.sqrt(np.power(xhat-x, 2) + np.power(yhat-y, 2)) + 15 * np.abs(fhat-f)\n    return intermediate.sum()/xhat.shape[0]\n\n\ndef score_log(df: pd.DataFrame, num_files: int, nam_file: str, data_shape: tuple, n_fold: int, seed: int, mpe: float):\n    score_dict = {'n_files': num_files, 'file_name': nam_file, 'shape': data_shape, 'fold': n_fold, 'seed': seed, 'score': mpe}\n    # noinspection PyTypeChecker\n    df = pd.concat([df, pd.DataFrame.from_dict([score_dict])])\n    df.to_csv(LOG_PATH / f\"log_score.csv\", index=False)\n    return df\n\n\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# ------------------------------------------------------------------------------\n# Set seed\n# ------------------------------------------------------------------------------\nset_seed(SEED)\n\n# ------------------------------------------------------------------------------\n# Read data\n# ------------------------------------------------------------------------------\nfeature_dir = \"../input/indoor-navigation-and-location-wifi-features\"\n#feature_dir = \"../input/extract-wifi-features\"\ntrain_files = sorted(glob.glob(os.path.join(feature_dir, '*_train.csv')))\ntest_files = sorted(glob.glob(os.path.join(feature_dir, '*_test.csv')))\nsubm = pd.read_csv('../input/indoor-location-navigation/sample_submission.csv', index_col=0)\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# ------------------------------------------------------------------------------\n# Define parameters for models\n# ------------------------------------------------------------------------------\nlgb_params = {'objective': 'root_mean_squared_error',\n              'boosting_type': 'gbdt',\n              'n_estimators': 50000,\n              'learning_rate': 0.1,\n              'num_leaves': 90,\n              'colsample_bytree': 0.4,\n              'subsample': 0.6,\n              'subsample_freq': 2,\n              'bagging_seed': SEED,\n              'reg_alpha': 8,\n              'reg_lambda': 2,\n              'random_state': SEED,\n              'n_jobs': -1\n              }\n\ndef_lgb_params = {'objective': 'root_mean_squared_error',\n              'boosting_type': 'gbdt',\n              'n_estimators': 10000,\n              'learning_rate': 0.1,\n              'num_leaves': 80,\n              'colsample_bytree': 1,\n              'subsample': 1,\n              'subsample_freq': 0,\n              'bagging_seed': SEED,\n              'reg_alpha': 4,\n              'reg_lambda': 2,\n              'random_state': SEED,\n              'n_jobs': -1\n              }\n\nlgb_f_params = {'objective': 'multiclass',\n                'boosting_type': 'gbdt',\n                'n_estimators': 50000,\n                'learning_rate': 0.1,\n                'num_leaves': 90,\n                'colsample_bytree': 0.4,\n                'subsample': 0.6,\n                'subsample_freq': 2,\n                'bagging_seed': SEED,\n                'reg_alpha': 10,\n                'reg_lambda': 2,\n                'random_state': SEED,\n                'n_jobs': -1\n                }\n\ndef_lgb_f_params = {'objective': 'multiclass',\n                'boosting_type': 'gbdt',\n                'n_estimators': 10000,\n                'learning_rate': 0.1,\n                'num_leaves': 80,\n                'colsample_bytree': 1,\n                'subsample': 1,\n                'subsample_freq': 0,\n                'bagging_seed': SEED,\n                'reg_alpha': 4,\n                'reg_lambda': 2,\n                'random_state': SEED,\n                'n_jobs': -1\n                }\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"running\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# ------------------------------------------------------------------------------\n# Training and inference\n# ------------------------------------------------------------------------------\nscore_df = pd.DataFrame()\noof = list()\npredictions = list()\n\ncountFiles = 0\nsamp_xvy_df = pd.DataFrame()\n\nfor n_files, file in enumerate(train_files):    \n\n    #if file=='../input/indoor-navigation-and-location-wifi-features/5d27096c03f801723c31e5e0_train.csv':       \n\n\n    data = pd.read_csv(file, index_col=0)\n    test_data = pd.read_csv(test_files[n_files], index_col=0)\n\n    #if countFiles > 5:\n    #    break\n\n    countFiles += 1    \n\n    oof_x, oof_y, oof_f = np.zeros(data.shape[0]), np.zeros(data.shape[0]), np.zeros(data.shape[0])\n    preds_x, preds_y = 0, 0\n    preds_f_arr = np.zeros((test_data.shape[0], N_SPLITS))\n\n    kf = KFold(n_splits=N_SPLITS, shuffle=True, random_state=SEED)\n    for fold, (trn_idx, val_idx) in enumerate(kf.split(data.iloc[:, :-4])):\n        X_train = data.iloc[trn_idx, :-4]\n        y_trainx = data.iloc[trn_idx, -4]\n        y_trainy = data.iloc[trn_idx, -3]\n        y_trainf = data.iloc[trn_idx, -2]\n        y_trainP = data.iloc[trn_idx, -1]\n\n        X_valid = data.iloc[val_idx, :-4]\n        y_validx = data.iloc[val_idx, -4]\n        y_validy = data.iloc[val_idx, -3]\n        y_validf = data.iloc[val_idx, -2]\n        y_validp = data.iloc[val_idx, -1]\n\n        modelx = lgb.LGBMRegressor(**def_lgb_params)\n        with timer(\"fit X\"):\n            modelx.fit(X_train, y_trainx,\n                       eval_set=[(X_valid, y_validx)],\n                       eval_metric='rmse',\n                       verbose=False,\n                       early_stopping_rounds=20\n                       )\n\n        modely = lgb.LGBMRegressor(**def_lgb_params)\n        with timer(\"fit Y\"):\n            modely.fit(X_train, y_trainy,\n                       eval_set=[(X_valid, y_validy)],\n                       eval_metric='rmse',\n                       verbose=False,\n                       early_stopping_rounds=20\n                       )\n\n        modelf = lgb.LGBMClassifier(**def_lgb_f_params)\n        with timer(\"fit F\"):\n            modelf.fit(X_train, y_trainf,\n                       eval_set=[(X_valid, y_validf)],\n                       eval_metric='multi_logloss',\n                       verbose=False,\n                       early_stopping_rounds=20\n                       )\n\n        oof_x[val_idx] = modelx.predict(X_valid)\n        oof_y[val_idx] = modely.predict(X_valid)\n        oof_f[val_idx] = modelf.predict(X_valid).astype(int)\n\n        preds_x += modelx.predict(test_data.iloc[:, :-1]) / N_SPLITS\n        preds_y += modely.predict(test_data.iloc[:, :-1]) / N_SPLITS\n        preds_f_arr[:, fold] = modelf.predict(test_data.iloc[:, :-1]).astype(int)\n\n\n        score = comp_metric(oof_x[val_idx], oof_y[val_idx], oof_f[val_idx],\n                            y_validx.to_numpy(), y_validy.to_numpy(), y_validf.to_numpy())\n        print(f\"fold {fold}: mean position error {score}\")\n        score_df = score_log(score_df, n_files, os.path.basename(file), data.shape, fold, SEED, score)\n\n        #if file=='../input/indoor-navigation-and-location-wifi-features/5d27096c03f801723c31e5e0_train.csv':            \n        if file=='../input/indoor-navigation-and-location-wifi-features/5d27096c03f801723c31e5e0_train.csv':       \n            validx = y_validx.to_numpy()\n            validy = y_validy.to_numpy()\n            validf = y_validf.to_numpy()\n            validp = y_validp.to_numpy()\n            for f in range(0,len(validx)):                \n                newRow = {'path':validp[f], 'xPred':oof_x[val_idx[f]], 'yPred':oof_y[val_idx[f]], 'fPred':oof_f[val_idx[f]], 'xTrue':validx[f], 'yTrue':validy[f], 'fTrue':validf[f]}\n                samp_xvy_df = samp_xvy_df.append(newRow, ignore_index=True)\n                #print(oof_x[val_idx[f]], validx[f])\n\n\n    print(\"*+\"*40)\n    print(f\"file #{n_files}, shape={data.shape}, name={os.path.basename(file)}\")\n    score = comp_metric(oof_x, oof_y, oof_f,\n                        data.iloc[:, -4].to_numpy(), data.iloc[:, -3].to_numpy(), data.iloc[:, -2].to_numpy())\n    oof.append(score)\n    print(f\"mean position error {score}\")\n    print(\"*+\"*40)\n    score_df = score_log(score_df, n_files, os.path.basename(file), data.shape, 999, SEED, score)\n\n    preds_f_mode = stats.mode(preds_f_arr, axis=1)\n    preds_f = preds_f_mode[0].astype(int).reshape(-1)\n    test_preds = pd.DataFrame(np.stack((preds_f, preds_x, preds_y))).T\n    test_preds.columns = subm.columns\n    test_preds.index = test_data[\"site_path_timestamp\"]\n    test_preds[\"floor\"] = test_preds[\"floor\"].astype(int)\n    predictions.append(test_preds)\n\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"samp_xvy_df.head()\n#data.head()\n#data.iloc[trn_idx, -2]\n#trn_idx\n#data.head()\n#predictions[0]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nfig, ax = plt.subplots()\nfig.set_figheight(30)\nfig.set_figwidth(20)\ny_plot = lgb.plot_tree(modely, ax, orientation='vertical')\ny_plot = fig.add_subplot(y_plot)\nfig.savefig('yPlot_output.png')\n\nfig, ax = plt.subplots()\nfig.set_figheight(30)\nfig.set_figwidth(20)\ny_plot = lgb.plot_tree(modelx, ax, orientation='vertical')\ny_plot=fig.add_subplot(y_plot)\nfig.savefig('xPlot_output.png')\n\nfig, ax = plt.subplots()\nfig.set_figheight(20)\nfig.set_figwidth(20)\ny_plot = lgb.plot_tree(modelf, ax, figsize=(20,20), orientation='vertical')\ny_plot=fig.add_subplot(y_plot)\nfig.savefig('fPlot_output.png')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# ------------------------------------------------------------------------------\n# Submit the result\n# ------------------------------------------------------------------------------\nsamp_xvy_df.to_csv('sample_output.csv')\n\nall_preds = pd.concat(predictions)\nall_preds = all_preds.reindex(subm.index)\nall_preds.to_csv('submission.csv')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predictions","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}