{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":84493,"databundleVersionId":9849268,"sourceType":"competition"},{"sourceId":201259472,"sourceType":"kernelVersion"},{"sourceId":201281084,"sourceType":"kernelVersion"},{"sourceId":201389901,"sourceType":"kernelVersion"},{"sourceId":201390091,"sourceType":"kernelVersion"},{"sourceId":201390121,"sourceType":"kernelVersion"}],"dockerImageVersionId":30786,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Overview\nThis notebook is for performing inference using a model trained on [[JSR-TMDF] Gradient Boosting Models (Training)](https://www.kaggle.com/code/takaito/jsr-tmdf-gradient-boosting-models-training). Please refer to [[JSR-TMDF] Gradient Boosting Models (Training)](https://www.kaggle.com/code/takaito/jsr-tmdf-gradient-boosting-models-training) for the training.\n\n","metadata":{}},{"cell_type":"markdown","source":"To be updated!! (I plan to add more hints if the number of votes increases.)","metadata":{}},{"cell_type":"code","source":"# ====================================================\n# Library\n# ====================================================\nimport os\nimport gc\nimport warnings\nwarnings.filterwarnings('ignore')\nimport random\nimport scipy as sp\nimport numpy as np\nimport pandas as pd\nimport polars as pl\nfrom glob import glob\nfrom pathlib import Path\nimport joblib\nimport pickle\nimport itertools\nfrom tqdm.auto import tqdm\n\nimport torch\nfrom sklearn.model_selection import KFold, StratifiedKFold, train_test_split, GroupKFold\nfrom sklearn.metrics import log_loss, roc_auc_score, matthews_corrcoef, f1_score\nfrom sklearn.metrics import mean_squared_error, r2_score\nfrom sklearn.preprocessing import LabelEncoder\nimport lightgbm as lgb\nimport xgboost as xgb\nfrom catboost import Pool, CatBoostRegressor, CatBoostClassifier","metadata":{"execution":{"iopub.status.busy":"2024-10-16T12:36:54.956342Z","iopub.execute_input":"2024-10-16T12:36:54.956800Z","iopub.status.idle":"2024-10-16T12:37:03.157984Z","shell.execute_reply.started":"2024-10-16T12:36:54.956756Z","shell.execute_reply":"2024-10-16T12:37:03.156732Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import kaggle_evaluation.jane_street_inference_server","metadata":{"execution":{"iopub.status.busy":"2024-10-16T12:37:03.160264Z","iopub.execute_input":"2024-10-16T12:37:03.161028Z","iopub.status.idle":"2024-10-16T12:37:03.421445Z","shell.execute_reply.started":"2024-10-16T12:37:03.160977Z","shell.execute_reply":"2024-10-16T12:37:03.420106Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ====================================================\n# Configurations\n# ====================================================\nclass CFG:\n    VER = 1\n    AUTHOR = 'takaito'\n    COMPETITION = 'jane-street-real-time-market-data-forecasting'\n    DATA_PATH = Path('/kaggle/input/jane-street-real-time-market-data-forecasting')\n    OOF_DATA_PATH = Path('./oof')\n    MODEL_DATA_PATH = Path('./models')\n    METHOD_LIST = ['lightgbm', 'xgboost', 'catboost']\n    model_weight_dict = {'lightgbm': 0.60, 'xgboost': 0.10, 'catboost': 0.30}\n    USE_GPU = torch.cuda.is_available()\n    SEED = 42\n    N_SPLIT = 5\n    target_col = 'responder_6'\n    metric = 'r2_score'\n    metric_maximize_flag = True\n    ","metadata":{"execution":{"iopub.status.busy":"2024-10-16T12:37:03.422793Z","iopub.execute_input":"2024-10-16T12:37:03.423371Z","iopub.status.idle":"2024-10-16T12:37:03.431401Z","shell.execute_reply.started":"2024-10-16T12:37:03.423328Z","shell.execute_reply":"2024-10-16T12:37:03.430012Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ====================================================\n# Seed everything\n# ====================================================\ndef seed_everything(seed):\n    random.seed(seed)\n    np.random.seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\nseed_everything(CFG.SEED)","metadata":{"execution":{"iopub.status.busy":"2024-10-16T12:37:03.434269Z","iopub.execute_input":"2024-10-16T12:37:03.434741Z","iopub.status.idle":"2024-10-16T12:37:03.445115Z","shell.execute_reply.started":"2024-10-16T12:37:03.434684Z","shell.execute_reply":"2024-10-16T12:37:03.443743Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Custom R2 metric for CatBoost\nclass r2_cat(object):\n    def get_final_error(self, error, weight):\n        return 1 - error / (weight + 1e-38)\n\n    def is_max_optimal(self):\n        return True\n\n    def evaluate(self, approxes, target, weight):\n        assert len(approxes) == 1\n        assert len(target) == len(approxes[0])\n\n        approx = approxes[0]\n\n        error_sum = 0.0\n        weight_sum = 0.0\n\n        for i in range(len(approx)):\n            w = 1.0 if weight is None else weight[i]\n            weight_sum += w * (target[i] ** 2)\n            error_sum += w * ((approx[i] - target[i]) ** 2)\n\n        return error_sum, weight_sum","metadata":{"execution":{"iopub.status.busy":"2024-10-16T12:37:03.446565Z","iopub.execute_input":"2024-10-16T12:37:03.447071Z","iopub.status.idle":"2024-10-16T12:37:03.459019Z","shell.execute_reply.started":"2024-10-16T12:37:03.447014Z","shell.execute_reply":"2024-10-16T12:37:03.457838Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"original_features = ['feature_' + str(x).zfill(2) for x in range(78+1)]","metadata":{"execution":{"iopub.status.busy":"2024-10-16T12:37:03.460365Z","iopub.execute_input":"2024-10-16T12:37:03.460796Z","iopub.status.idle":"2024-10-16T12:37:03.479899Z","shell.execute_reply.started":"2024-10-16T12:37:03.460754Z","shell.execute_reply":"2024-10-16T12:37:03.478178Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model_list_dict = {}\nfor method in CFG.METHOD_LIST:\n    model_list_dict[method] = []\n    if method == 'lightgbm':\n        temp_method = 'lgb'\n    if method == 'xgboost':\n        temp_method = 'xgb'\n    if method == 'catboost':\n        temp_method = 'cat'\n    for fold in range(CFG.N_SPLIT):\n        model_list_dict[method].append(pickle.load(open(f'/kaggle/input/jsr-tmdf-training-simple-{temp_method}/models/{method}_fold{fold+1}_seed{CFG.SEED}_ver{CFG.VER}.pkl', 'rb')))","metadata":{"execution":{"iopub.status.busy":"2024-10-16T12:37:03.482121Z","iopub.execute_input":"2024-10-16T12:37:03.482528Z","iopub.status.idle":"2024-10-16T12:37:09.068879Z","shell.execute_reply.started":"2024-10-16T12:37:03.482488Z","shell.execute_reply":"2024-10-16T12:37:09.067585Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def lightgbm_inference(method: str, x_test: pd.DataFrame):\n    test_pred = np.zeros(len(x_test))\n    for fold in range(CFG.N_SPLIT):\n        model = model_list_dict[method][fold]\n        # Predict\n        pred = model.predict(x_test)\n        test_pred += pred\n    return test_pred / CFG.N_SPLIT\n\ndef xgboost_inference(method: str, x_test: pd.DataFrame):\n    test_pred = np.zeros(len(x_test))\n    for fold in range(CFG.N_SPLIT):\n        model = model_list_dict[method][fold]\n        # Predict\n        pred = model.predict(xgb.DMatrix(x_test))\n        test_pred += pred\n    return test_pred / CFG.N_SPLIT\n\ndef catboost_inference(method: str, x_test: pd.DataFrame):\n    test_pred = np.zeros(len(x_test))\n    for fold in range(CFG.N_SPLIT):\n        model = model_list_dict[method][fold]\n        # Predict\n        pred = model.predict(x_test)\n        test_pred += pred\n    return test_pred / CFG.N_SPLIT","metadata":{"execution":{"iopub.status.busy":"2024-10-16T12:37:09.070489Z","iopub.execute_input":"2024-10-16T12:37:09.071074Z","iopub.status.idle":"2024-10-16T12:37:09.081704Z","shell.execute_reply.started":"2024-10-16T12:37:09.070991Z","shell.execute_reply":"2024-10-16T12:37:09.080467Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"lags_ : pl.DataFrame | None = None\n\n\n# Replace this function with your inference code.\n# You can return either a Pandas or Polars dataframe, though Polars is recommended.\n# Each batch of predictions (except the very first) must be returned within 10 minutes of the batch features being provided.\ndef predict(test: pl.DataFrame, lags: pl.DataFrame | None) -> pl.DataFrame | pd.DataFrame:\n    \"\"\"Make a prediction.\"\"\"\n    # All the responders from the previous day are passed in at time_id == 0. We save them in a global variable for access at every time_id.\n    # Use them as extra features, if you like.\n    global lags_\n    if lags is not None:\n        lags_ = lags\n\n    predictions = test.select(\n        'row_id',\n        pl.lit(0.0).alias('responder_6'),\n    )\n    \n    x_test = test[original_features].to_pandas()\n    preds = np.zeros(len(x_test))\n    for method in CFG.METHOD_LIST:\n        if method == 'lightgbm':\n            temp_preds = lightgbm_inference(method, x_test)\n        if method == 'xgboost':\n            temp_preds = xgboost_inference(method, x_test)\n        if method == 'catboost':\n            temp_preds = catboost_inference(method, x_test)\n                \n        preds += CFG.model_weight_dict[method] * temp_preds\n    \n    predictions = predictions.with_columns(pl.Series('responder_6', preds.ravel()))\n\n    # The predict function must return a DataFrame\n    assert isinstance(predictions, pl.DataFrame | pd.DataFrame)\n    # with columns 'row_id', 'responer_6'\n    assert list(predictions.columns) == ['row_id', 'responder_6']\n    # and as many rows as the test data.\n    assert len(predictions) == len(test)\n\n    return predictions","metadata":{"execution":{"iopub.status.busy":"2024-10-16T12:37:09.083153Z","iopub.execute_input":"2024-10-16T12:37:09.083567Z","iopub.status.idle":"2024-10-16T12:37:09.111153Z","shell.execute_reply.started":"2024-10-16T12:37:09.083526Z","shell.execute_reply":"2024-10-16T12:37:09.109444Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"inference_server = kaggle_evaluation.jane_street_inference_server.JSInferenceServer(predict)\n\nif os.getenv('KAGGLE_IS_COMPETITION_RERUN'):\n    inference_server.serve()\nelse:\n    inference_server.run_local_gateway(\n        (\n            '/kaggle/input/jane-street-real-time-market-data-forecasting/test.parquet',\n            '/kaggle/input/jane-street-real-time-market-data-forecasting/lags.parquet',\n        )\n    )","metadata":{"execution":{"iopub.status.busy":"2024-10-16T12:37:09.114754Z","iopub.execute_input":"2024-10-16T12:37:09.115156Z","iopub.status.idle":"2024-10-16T12:37:09.762126Z","shell.execute_reply.started":"2024-10-16T12:37:09.115115Z","shell.execute_reply":"2024-10-16T12:37:09.760889Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{},"outputs":[],"execution_count":null}]}