{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":105399,"databundleVersionId":12733338,"sourceType":"competition"}],"dockerImageVersionId":31041,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"## [More information about problems](https://www.kaggle.com/code/antonoof/0-score-one-love)","metadata":{}},{"cell_type":"code","source":"!pip install xgboost > /dev/null","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-24T12:02:25.272855Z","iopub.execute_input":"2025-06-24T12:02:25.273306Z","iopub.status.idle":"2025-06-24T12:02:29.154487Z","shell.execute_reply.started":"2025-06-24T12:02:25.273282Z","shell.execute_reply":"2025-06-24T12:02:29.153745Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport polars as pl # read train -> pd\nimport xgboost as xgb\nfrom sklearn.model_selection import train_test_split","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-06-24T12:02:29.156052Z","iopub.execute_input":"2025-06-24T12:02:29.156320Z","iopub.status.idle":"2025-06-24T12:02:30.805594Z","shell.execute_reply.started":"2025-06-24T12:02:29.156287Z","shell.execute_reply":"2025-06-24T12:02:30.804906Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## ‼️ Be careful, a large number of features may exceed the limits of memory, use: [Helper](https://www.kaggle.com/competitions/aeroclub-recsys-2025/discussion/585622)","metadata":{}},{"cell_type":"code","source":"features = ['bySelf', 'companyID', 'frequentFlyer', 'nationality', 'isAccess3D', 'isVip',\n            'legs0_segments0_baggageAllowance_quantity', 'legs0_segments0_baggageAllowance_weightMeasurementType', 'legs0_segments0_cabinClass',\n            'legs0_segments0_flightNumber', 'legs0_segments0_seatsAvailable', 'profileId', 'pricingInfo_isAccessTP', 'pricingInfo_passengerCount',\n            'legs0_segments0_arrivalTo_airport_iata', 'legs0_segments0_marketingCarrier_code',\n            'ranker_id', 'taxes', 'totalPrice'\n]\nfeatures_train = features + ['selected']","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-24T12:02:30.806243Z","iopub.execute_input":"2025-06-24T12:02:30.806538Z","iopub.status.idle":"2025-06-24T12:02:30.810510Z","shell.execute_reply.started":"2025-06-24T12:02:30.806511Z","shell.execute_reply":"2025-06-24T12:02:30.809864Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train = pl.read_parquet('/kaggle/input/aeroclub-recsys-2025/train.parquet')\ntrain = train.select(features_train)\ntrain = train.to_pandas()\ntest = pd.read_parquet('/kaggle/input/aeroclub-recsys-2025/test.parquet')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-24T12:02:30.812281Z","iopub.execute_input":"2025-06-24T12:02:30.812475Z","iopub.status.idle":"2025-06-24T12:03:05.890203Z","shell.execute_reply.started":"2025-06-24T12:02:30.812460Z","shell.execute_reply":"2025-06-24T12:03:05.889450Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Transformation of categorical data","metadata":{}},{"cell_type":"code","source":"categorical = ['frequentFlyer', 'legs0_segments0_flightNumber', 'legs0_segments0_arrivalTo_airport_iata', 'legs0_segments0_marketingCarrier_code']\nfor col in categorical:\n    train[col] = train[col].astype('category')\n    test[col] = test[col].astype('category')\n\nfor col in categorical:\n    train[col] = train[col].cat.codes\n    test[col] = test[col].cat.codes","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-24T12:03:05.891109Z","iopub.execute_input":"2025-06-24T12:03:05.891357Z","iopub.status.idle":"2025-06-24T12:03:11.831268Z","shell.execute_reply.started":"2025-06-24T12:03:05.891338Z","shell.execute_reply":"2025-06-24T12:03:11.830621Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train['ranker_id'] = train['ranker_id'].astype('category')\ntest['ranker_id'] = test['ranker_id'].astype('category')\n\nX = train[features]\ny = train['selected']","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-24T12:03:11.831985Z","iopub.execute_input":"2025-06-24T12:03:11.832210Z","iopub.status.idle":"2025-06-24T12:03:15.489818Z","shell.execute_reply.started":"2025-06-24T12:03:11.832192Z","shell.execute_reply":"2025-06-24T12:03:15.488911Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_categories = X['ranker_id'].cat.categories\n\nX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)\n\nX_train['ranker_id'] = X_train['ranker_id'].cat.codes\nX_test['ranker_id'] = X_test['ranker_id'].cat.set_categories(train_categories, ordered=True).cat.codes\n\ntrain_group_sizes = X_train['ranker_id'].value_counts().sort_index().tolist()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-24T12:03:15.490771Z","iopub.execute_input":"2025-06-24T12:03:15.491061Z","iopub.status.idle":"2025-06-24T12:03:21.729453Z","shell.execute_reply.started":"2025-06-24T12:03:15.491034Z","shell.execute_reply":"2025-06-24T12:03:21.728847Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model = xgb.XGBRanker(\n    objective='rank:pairwise',\n    n_estimators=3000,\n    max_depth=5,\n    learning_rate=0.002,\n    eval_metric='ndcg@3',\n    reg_alpha=0.6,\n    reg_lambda=0.8\n)\n\nmodel.fit(X_train, y_train, group=train_group_sizes)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-24T12:03:21.730269Z","iopub.execute_input":"2025-06-24T12:03:21.730535Z","iopub.status.idle":"2025-06-24T12:39:03.585417Z","shell.execute_reply.started":"2025-06-24T12:03:21.730512Z","shell.execute_reply":"2025-06-24T12:39:03.584686Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def take_rank(data, group_col, score_col, rank_col):\n    data[rank_col] = data.groupby(group_col, observed=False)[score_col].rank(method='first', ascending=False).astype(int)\n    return data","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-24T12:39:03.586202Z","iopub.execute_input":"2025-06-24T12:39:03.586737Z","iopub.status.idle":"2025-06-24T12:39:03.590342Z","shell.execute_reply.started":"2025-06-24T12:39:03.586711Z","shell.execute_reply":"2025-06-24T12:39:03.589758Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def HitRate3(data, rank_col, true_col):\n    positive = 0\n    Q = data['ranker_id'].nunique()\n\n    for _, group in data.groupby('ranker_id'):\n        preds_top_3 = group.nsmallest(3, rank_col) # top 3\n        if any(preds_top_3[true_col] == 1):\n            positive += 1\n\n    hit_rate = positive / Q\n    return hit_rate\n\nX_test['y_scores'] = model.predict(X_test[features])\nX_test = take_rank(X_test, 'ranker_id', 'y_scores', 'y_ranks')\nX_test['selected'] = y_test.values\n\nhitrate_score = HitRate3(X_test, 'y_ranks', 'selected')\nprint(f\"HitRate@3: {hitrate_score:.2f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-24T12:39:03.592019Z","iopub.execute_input":"2025-06-24T12:39:03.592199Z","iopub.status.idle":"2025-06-24T12:41:28.626470Z","shell.execute_reply.started":"2025-06-24T12:39:03.592186Z","shell.execute_reply":"2025-06-24T12:41:28.625617Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test['y_scores'] = model.predict(test[features])\n\ntest = take_rank(test, 'ranker_id', 'y_scores', 'selected')\n\nsubmission = test[['Id', 'ranker_id', 'selected']]\nsubmission.to_parquet('submission.parquet', index=False)\nsubmission.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-24T12:41:28.627282Z","iopub.execute_input":"2025-06-24T12:41:28.627680Z","iopub.status.idle":"2025-06-24T12:42:27.253336Z","shell.execute_reply.started":"2025-06-24T12:41:28.627657Z","shell.execute_reply":"2025-06-24T12:42:27.252700Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}