{"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"},{"sourceId":12341942,"sourceType":"datasetVersion","datasetId":7780503},{"sourceId":12341538,"sourceType":"datasetVersion","datasetId":7780234}],"dockerImageVersionId":31041,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"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 # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\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},"outputs":[],"execution_count":null},{"cell_type":"code","source":"target_columns = ['Id', 'companyID', 'corporateTariffCode', 'frequentFlyer',\n       'nationality', 'isAccess3D', 'isVip', 'legs0_arrivalAt',\n       'legs0_departureAt', 'legs0_duration', 'legs0_segments0_aircraft_code',\n       'legs0_segments0_arrivalTo_airport_city_iata',\n       'legs0_segments0_arrivalTo_airport_iata',\n       'legs0_segments0_baggageAllowance_quantity',\n       'legs0_segments0_baggageAllowance_weightMeasurementType',\n       'legs0_segments0_cabinClass',\n       'legs0_segments0_departureFrom_airport_iata',\n       'legs0_segments0_duration', 'legs0_segments0_flightNumber',\n       'legs0_segments0_marketingCarrier_code',\n       'legs0_segments0_operatingCarrier_code',\n       'legs0_segments0_seatsAvailable', 'legs0_segments1_aircraft_code',\n       'legs0_segments1_arrivalTo_airport_city_iata',\n       'legs0_segments1_arrivalTo_airport_iata',\n       'legs0_segments1_baggageAllowance_quantity',\n       'legs0_segments1_baggageAllowance_weightMeasurementType',\n       'legs0_segments1_cabinClass',\n       'legs0_segments1_departureFrom_airport_iata',\n       'legs0_segments1_duration', 'legs0_segments1_flightNumber',\n       'legs0_segments1_marketingCarrier_code',\n       'legs0_segments1_operatingCarrier_code',\n       'legs0_segments1_seatsAvailable', 'legs1_arrivalAt',\n       'legs1_departureAt', 'legs1_duration', 'legs1_segments0_aircraft_code',\n       'legs1_segments0_arrivalTo_airport_city_iata',\n       'legs1_segments0_arrivalTo_airport_iata',\n       'legs1_segments0_baggageAllowance_quantity',\n       'legs1_segments0_baggageAllowance_weightMeasurementType',\n       'legs1_segments0_cabinClass',\n       'legs1_segments0_departureFrom_airport_iata',\n       'legs1_segments0_duration', 'legs1_segments0_flightNumber',\n       'legs1_segments0_marketingCarrier_code',\n       'legs1_segments0_operatingCarrier_code',\n       'legs1_segments0_seatsAvailable', 'miniRules0_monetaryAmount',\n       'miniRules0_statusInfos', 'miniRules1_monetaryAmount',\n       'miniRules1_statusInfos', 'pricingInfo_isAccessTP', 'profileId',\n       'ranker_id', 'searchRoute', 'sex', 'taxes', 'totalPrice',\n       'requestDate_year', 'requestDate_month', 'requestDate_day',\n       'requestDate_hour', 'requestDate_dow']","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom sklearn.metrics import accuracy_score, roc_auc_score, confusion_matrix\nfrom xgboost import XGBClassifier\nimport time\nimport joblib\nfrom tqdm import tqdm\nimport warnings\nwarnings.filterwarnings('ignore')\n\n# Configuration\nRANDOM_STATE = 42\nMODEL_TYPE = \"xgboost\"  # Options: \"xgboost\" or \"lightgbm\"\nUSE_GPU = True  # Set to True to enable GPU acceleration\n\ndef train_and_save_model(encoded_train_file, model_output_file):\n    \"\"\"Train model on already encoded dataset and save for later use\"\"\"\n    # Load already encoded training data\n    print(\"Loading encoded training data...\")\n    df = pd.read_csv(encoded_train_file)\n    print(f\"Data shape: {df.shape}\")\n    \n    # Prepare data\n    X = df.drop(columns=['selected', 'Id', 'ranker_id'])  # Features\n    y = df['selected']  # Target\n    \n    # Handle class imbalance\n    class_counts = y.value_counts()\n    scale_pos_weight = class_counts[0] / class_counts[1]\n    print(f\"\\nClass distribution:\\n{class_counts}\")\n    print(f\"Scale positive weight: {scale_pos_weight:.2f}\")\n    \n    # Initialize model with GPU support if available\n    if MODEL_TYPE == \"xgboost\":\n        print(\"\\nTraining XGBoost model on full dataset...\")\n        gpu_params = {'tree_method': 'gpu_hist', 'gpu_id': 0} if USE_GPU else {'tree_method': 'hist'}\n        model = XGBClassifier(\n            n_estimators=1000,\n            learning_rate=0.05,\n            max_depth=6,\n            subsample=0.8,\n            colsample_bytree=0.8,\n            scale_pos_weight=scale_pos_weight,\n            random_state=RANDOM_STATE,\n            n_jobs=-1,\n            **gpu_params\n        )\n    elif MODEL_TYPE == \"lightgbm\":\n        print(\"\\nTraining LightGBM model on full dataset...\")\n        from lightgbm import LGBMClassifier\n        gpu_params = {'device': 'gpu'} if USE_GPU else {}\n        model = LGBMClassifier(\n            n_estimators=1000,\n            learning_rate=0.05,\n            max_depth=6,\n            subsample=0.8,\n            colsample_bytree=0.8,\n            scale_pos_weight=scale_pos_weight,\n            random_state=RANDOM_STATE,\n            n_jobs=-1,\n            is_unbalance=True,\n            **gpu_params\n        )\n    \n    # Train model on full dataset\n    print(f\"Using GPU: {USE_GPU}\")\n    start_time = time.time()\n    model.fit(X, y)\n    training_time = time.time() - start_time\n    print(f\"\\nTraining completed in {training_time:.2f} seconds\")\n    \n    # Feature importance analysis\n    print(\"\\nAnalyzing feature importance...\")\n    feature_importance = model.feature_importances_\n    sorted_idx = np.argsort(feature_importance)[::-1]\n    top_n = min(30, len(feature_importance))\n    \n    # Create and save importance dataframe\n    importance_df = pd.DataFrame({\n        'Feature': X.columns[sorted_idx][:top_n],\n        'Importance': feature_importance[sorted_idx][:top_n]\n    })\n    importance_df.to_csv('feature_importance.csv', index=False)\n    \n    # Plot feature importance\n    plt.figure(figsize=(12, 10))\n    sns.barplot(x='Importance', y='Feature', data=importance_df, palette='viridis')\n    plt.title(f'Top {top_n} Feature Importance ({MODEL_TYPE.upper()})')\n    plt.tight_layout()\n    plt.savefig('feature_importance.png')\n    plt.close()\n    \n    # Save model\n    joblib.dump(model, model_output_file)\n    print(f\"\\nModel saved to {model_output_file}\")\n    print(\"Feature importance saved to feature_importance.csv and feature_importance.png\")\n    \n    return model\n\n# def predict_and_rank(model, encoded_test_file, output_file):\n#     \"\"\"Make predictions on encoded test set and rank flights, outputting with original values\"\"\"\n#     # Load the encoded test data (already preprocessed)\n#     print(\"Loading encoded test data...\")\n#     encoded_test_df = pd.read_csv(encoded_test_file)\n    \n#     # Load the encoders\n#     print(\"Loading encoders...\")\n#     try:\n#         encoders = joblib.load('/kaggle/input/encoded-test-dataset/label_encoders.pkl')\n#     except FileNotFoundError:\n#         raise FileNotFoundError(\"Encoder file not found. Please ensure label_encoders.pkl exists\")\n    \n#     # Create a copy for output with just the identifier columns\n#     output_df = encoded_test_df[['Id', 'ranker_id']].copy()\n    \n#     # Make predictions (probability of being selected)\n#     print(\"Making predictions...\")\n#     # Drop identifier columns for prediction\n#     features = encoded_test_df.drop(columns=['Id', 'ranker_id'])\n#     # Get probability predictions for class 1 (selected)\n#     pred_proba = model.predict_proba(features)[:, 1]\n#     encoded_test_df['prediction_score'] = pred_proba\n    \n#     # Rank flights within each ranker_id group (higher score = better rank)\n#     print(\"Ranking flights within each session...\")\n#     # Calculate ranks within each group\n#     ranks = encoded_test_df.groupby('ranker_id')['prediction_score'].rank(\n#         ascending=False, method='first'\n#     ).astype(int)\n#     output_df['selected'] = ranks\n    \n#     # Decode identifier columns back to original values (if they were encoded)\n#     print(\"Decoding identifier columns...\")\n#     for col in ['Id', 'ranker_id']:\n#         if col in encoders:\n#             le = encoders[col]\n#             output_df[col] = le.inverse_transform(output_df[col])\n    \n#     # Save results with required columns\n#     output_df = output_df[['Id', 'ranker_id', 'selected']]\n#     output_df.to_csv(output_file, index=False)\n#     print(f\"\\nPredictions saved to {output_file}\")\n    \n#     return output_df\nif __name__ == \"__main__\":\n    # Paths configuration\n    ENCODED_TRAIN_FILE = \"/kaggle/input/chopped-train-data/chopped_cleaned_train.csv\"  \n    ENCODED_TEST_DATA =  \"/kaggle/input/encoded-test-dataset/encoded_test_data.csv\"  # Your preprocessed test DataFrame\n    OUTPUT_FILE = \"flight_rank_predictions.csv\"\n    MODEL_FILE = f\"flight_selection_model_{MODEL_TYPE}.pkl\"\n    \n    # Train and save model\n    # model = train_and_save_model(ENCODED_TRAIN_FILE, MODEL_FILE)\n    # model =  joblib.load(\"/kaggle/input/xgboost-2/flight_selection_model_xgboost (1).pkl\")\n    \n    # # Make predictions on test set and rank flights\n    # try:\n    #     ranked_predictions = predict_and_rank(\n    #         model, \n    #         encoded_test_file=ENCODED_TEST_DATA,\n    #         output_file=OUTPUT_FILE\n    #     )\n    #     print(\"\\nSample of ranked predictions:\")\n    #     print(ranked_predictions.head())\n    # except Exception as e:\n    #     print(f\"\\nError processing test set: {str(e)}\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport joblib\nfrom tqdm import tqdm\nimport warnings\nwarnings.filterwarnings('ignore')\n\n# Configuration\nMODEL_TYPE = \"xgboost\"  # Options: \"xgboost\" or \"lightgbm\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-01T15:29:18.221999Z","iopub.execute_input":"2025-07-01T15:29:18.222525Z","iopub.status.idle":"2025-07-01T15:29:18.226309Z","shell.execute_reply.started":"2025-07-01T15:29:18.222501Z","shell.execute_reply":"2025-07-01T15:29:18.225612Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Load the pre-trained model\nmodel_path = \"/kaggle/input/xgboost-2/flight_selection_model_xgboost (1).pkl\"\nmodel = joblib.load(model_path)\nprint(\"Model loaded successfully!\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-01T15:29:20.111786Z","iopub.execute_input":"2025-07-01T15:29:20.112478Z","iopub.status.idle":"2025-07-01T15:29:21.230145Z","shell.execute_reply.started":"2025-07-01T15:29:20.112452Z","shell.execute_reply":"2025-07-01T15:29:21.229595Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Load test data\ntest_data_path = \"/kaggle/input/encoded-test-dataset/encoded_test_data.csv\"\nencoded_test_df = pd.read_csv(test_data_path)\nprint(f\"Test data loaded. Shape: {encoded_test_df.shape}\")\ndisplay(encoded_test_df.head())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-01T15:30:18.993147Z","iopub.execute_input":"2025-07-01T15:30:18.993808Z","iopub.status.idle":"2025-07-01T15:31:16.740415Z","shell.execute_reply.started":"2025-07-01T15:30:18.993784Z","shell.execute_reply":"2025-07-01T15:31:16.739769Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Load encoders\ntry:\n    encoders = joblib.load('/kaggle/input/encoded-test-dataset/label_encoders.pkl')\n    print(\"Encoders loaded successfully!\")\nexcept FileNotFoundError:\n    print(\"Encoder file not found. Please ensure label_encoders.pkl exists\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-01T15:31:36.588356Z","iopub.execute_input":"2025-07-01T15:31:36.588618Z","iopub.status.idle":"2025-07-01T15:31:36.638301Z","shell.execute_reply.started":"2025-07-01T15:31:36.588599Z","shell.execute_reply":"2025-07-01T15:31:36.637589Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Prepare features for prediction (drop ID columns)\nfeatures = encoded_test_df.drop(columns=['Id', 'ranker_id'])\nprint(\"Features prepared for prediction\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-01T15:31:44.309696Z","iopub.execute_input":"2025-07-01T15:31:44.310336Z","iopub.status.idle":"2025-07-01T15:31:45.487726Z","shell.execute_reply.started":"2025-07-01T15:31:44.310312Z","shell.execute_reply":"2025-07-01T15:31:45.487077Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Make predictions\nencoded_test_df['prediction_score'] = model.predict_proba(features)[:, 1]\nprint(\"Predictions completed\")\ndisplay(encoded_test_df[['Id', 'ranker_id', 'prediction_score']].head())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-01T15:31:51.579487Z","iopub.execute_input":"2025-07-01T15:31:51.580158Z","iopub.status.idle":"2025-07-01T15:32:38.796707Z","shell.execute_reply.started":"2025-07-01T15:31:51.580129Z","shell.execute_reply":"2025-07-01T15:32:38.796006Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Rank flights within each group\nsubmission = encoded_test_df[['Id', 'ranker_id']].copy().astype(int)\nsubmission['selected'] = encoded_test_df.groupby('ranker_id')['prediction_score'].rank(\n    ascending=False, method='first'\n).astype(int)\nprint(\"Ranking completed\")\ndisplay(submission.head())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-01T15:33:48.359292Z","iopub.execute_input":"2025-07-01T15:33:48.359604Z","iopub.status.idle":"2025-07-01T15:33:50.600724Z","shell.execute_reply.started":"2025-07-01T15:33:48.359580Z","shell.execute_reply":"2025-07-01T15:33:50.600132Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Decode ranker_id back to original string format\nif 'ranker_id' in encoders:\n    submission['ranker_id'] = encoders['ranker_id'].inverse_transform(submission['ranker_id'])\n    print(\"ranker_id decoded back to original strings\")\nelse:\n    print(\"Warning: No encoder found for ranker_id - keeping as is\")\n\n# Verify the decoded values\nprint(\"\\nDecoded submission sample:\")\ndisplay(submission.head())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-01T15:34:00.023150Z","iopub.execute_input":"2025-07-01T15:34:00.023427Z","iopub.status.idle":"2025-07-01T15:34:00.319654Z","shell.execute_reply.started":"2025-07-01T15:34:00.023405Z","shell.execute_reply":"2025-07-01T15:34:00.318876Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Save final output\noutput_file = \"submission.csv\"\nsubmission.to_csv(output_file, index=False)\nprint(f\"Predictions saved to {output_file}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-01T15:34:07.901424Z","iopub.execute_input":"2025-07-01T15:34:07.902163Z","iopub.status.idle":"2025-07-01T15:34:19.968297Z","shell.execute_reply.started":"2025-07-01T15:34:07.902131Z","shell.execute_reply":"2025-07-01T15:34:19.967519Z"}},"outputs":[],"execution_count":null}]}