{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":82253,"databundleVersionId":8965849,"sourceType":"competition"}],"dockerImageVersionId":30746,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd\nfrom sklearn.preprocessing import LabelEncoder\nfrom sklearn.linear_model import LinearRegression\nfrom sklearn.metrics import mean_squared_error\nfrom lightgbm import LGBMRegressor\nfrom catboost import CatBoostRegressor\nfrom hyperopt import hp, fmin, tpe, Trials\nfrom hyperopt.pyll.base import scope\nimport numpy as np\nfrom sklearn.model_selection import train_test_split\n\n# Load data\ntrain_data = pd.read_csv('/kaggle/input/f1nalyze-datathon-ieeecsmuj/train.csv', low_memory=False)\nval_data = pd.read_csv('/kaggle/input/f1nalyze-datathon-ieeecsmuj/validation.csv', low_memory=False)\ntest_data = pd.read_csv('/kaggle/input/f1nalyze-datathon-ieeecsmuj/test.csv', low_memory=False)","metadata":{"execution":{"iopub.status.busy":"2024-07-26T20:06:59.001369Z","iopub.execute_input":"2024-07-26T20:06:59.002914Z","iopub.status.idle":"2024-07-26T20:07:40.578174Z","shell.execute_reply.started":"2024-07-26T20:06:59.002859Z","shell.execute_reply":"2024-07-26T20:07:40.576928Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Define columns to drop","metadata":{}},{"cell_type":"code","source":"columns_to_drop = ['resultId', 'racerId', 'driverId', 'constructorId', 'number', 'url_x', 'url_y',  'date', 'time_y', \n                   'fp1_date', 'fp1_time', 'fp2_date', 'fp2_time', 'fp3_date', 'fp3_time', 'quali_date',  \n                   'sprint_date', 'sprint_time', 'driverRef', 'driver_num',  'forename', 'surname', 'dob', \n                   'nationality', 'constructorRef', 'nationality_y', 'url', 'status']\n","metadata":{"execution":{"iopub.status.busy":"2024-07-26T20:07:40.581089Z","iopub.execute_input":"2024-07-26T20:07:40.581490Z","iopub.status.idle":"2024-07-26T20:07:40.587407Z","shell.execute_reply.started":"2024-07-26T20:07:40.581459Z","shell.execute_reply":"2024-07-26T20:07:40.586114Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"\n# Function to preprocess data","metadata":{}},{"cell_type":"code","source":"def preprocess_data(data, label_encoder):\n    # Remove duplicates\n    data = data.drop_duplicates()\n\n    # Drop unnecessary columns\n    data = data.drop(columns=[col for col in columns_to_drop if col in data.columns])\n\n    # Handle missing values\n    numeric_columns = data.select_dtypes(include=['number']).columns\n    data[numeric_columns] = data[numeric_columns].fillna(data[numeric_columns].mean())\n\n    categorical_columns = data.select_dtypes(include=['object']).columns\n    data[categorical_columns] = data[categorical_columns].fillna(data[categorical_columns].mode().iloc[0])\n\n    # Convert data types\n    data[numeric_columns] = data[numeric_columns].apply(pd.to_numeric, errors='coerce')\n\n    # Label encode categorical features\n    for col in ['company', 'grand_prix', 'driver_code']:\n        if col in data.columns:\n            data[col] = label_encoder.fit_transform(data[col])\n\n    # Convert specific columns to numeric\n    if 'position_x' in data.columns:\n        data['position_x'] = pd.to_numeric(data['position_x'], errors='coerce')\n    if 'positionText_x' in data.columns:\n        data = data.drop(columns='positionText_x')\n\n    time_columns = ['time_x', 'timetaken_in_millisec', 'fastestLap', 'fastestLapTime', 'quali_time', 'positionText_y']\n    data = data.drop(columns=[col for col in time_columns if col in data.columns])\n\n    if 'rank' in data.columns:\n        data['rank'] = pd.to_numeric(data['rank'], errors='coerce')\n    if 'max_speed' in data.columns:\n        data['max_speed'] = pd.to_numeric(data['max_speed'], errors='coerce')\n    if 'driver_code' in data.columns:\n        data['driver_code'] = pd.to_numeric(data['driver_code'], errors='coerce')\n\n    # Drop unnecessary columns after processing\n    data = data.drop(columns=[col for col in ['position_x', 'rank', 'max_speed', 'driver_code'] if col in data.columns])\n\n    return data\n","metadata":{"execution":{"iopub.status.busy":"2024-07-26T20:07:40.588867Z","iopub.execute_input":"2024-07-26T20:07:40.589227Z","iopub.status.idle":"2024-07-26T20:07:40.606751Z","shell.execute_reply.started":"2024-07-26T20:07:40.589193Z","shell.execute_reply":"2024-07-26T20:07:40.605617Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Initialize label encoder","metadata":{}},{"cell_type":"code","source":"label_encoder = LabelEncoder()","metadata":{"execution":{"iopub.status.busy":"2024-07-26T20:07:40.608120Z","iopub.execute_input":"2024-07-26T20:07:40.608572Z","iopub.status.idle":"2024-07-26T20:07:40.624628Z","shell.execute_reply.started":"2024-07-26T20:07:40.608531Z","shell.execute_reply":"2024-07-26T20:07:40.623355Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Preprocess data","metadata":{}},{"cell_type":"code","source":"train_data = preprocess_data(train_data, label_encoder)\nval_data = preprocess_data(val_data, label_encoder)\ntest_data = preprocess_data(test_data, label_encoder)","metadata":{"execution":{"iopub.status.busy":"2024-07-26T20:07:40.631456Z","iopub.execute_input":"2024-07-26T20:07:40.631864Z","iopub.status.idle":"2024-07-26T20:08:13.608947Z","shell.execute_reply.started":"2024-07-26T20:07:40.631836Z","shell.execute_reply":"2024-07-26T20:08:13.607507Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"markdown","source":"# Feature engineering","metadata":{}},{"cell_type":"code","source":"def feature_engineering(data):\n    if 'points_y' in data.columns and 'raceId_y' in data.columns:\n        data['average_points'] = data['points_y'] / data['raceId_y']\n    if 'driverStandingsId' in data.columns and 'wins' in data.columns:\n        data['cumulative_points'] = data.groupby('driverStandingsId')['wins'].cumsum()\n    return data\n\ntrain_data = feature_engineering(train_data)\nval_data = feature_engineering(val_data)\ntest_data = feature_engineering(test_data)\n","metadata":{"execution":{"iopub.status.busy":"2024-07-26T20:08:13.610462Z","iopub.execute_input":"2024-07-26T20:08:13.610885Z","iopub.status.idle":"2024-07-26T20:08:13.731767Z","shell.execute_reply.started":"2024-07-26T20:08:13.610847Z","shell.execute_reply":"2024-07-26T20:08:13.730737Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Combine training and validation data for final model training","metadata":{}},{"cell_type":"code","source":"X_train_val = pd.concat([train_data, val_data], axis=0)\ny_train_val = X_train_val['position']\nX_train_val = X_train_val.drop(columns='position')\n","metadata":{"execution":{"iopub.status.busy":"2024-07-26T20:08:13.733034Z","iopub.execute_input":"2024-07-26T20:08:13.733365Z","iopub.status.idle":"2024-07-26T20:08:14.007678Z","shell.execute_reply.started":"2024-07-26T20:08:13.733337Z","shell.execute_reply":"2024-07-26T20:08:14.006104Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_train_val, _, y_train_val, _ = train_test_split(X_train_val, y_train_val, test_size=0.8, random_state=42)\n","metadata":{"execution":{"iopub.status.busy":"2024-07-26T20:08:14.009137Z","iopub.execute_input":"2024-07-26T20:08:14.009509Z","iopub.status.idle":"2024-07-26T20:08:15.437557Z","shell.execute_reply.started":"2024-07-26T20:08:14.009479Z","shell.execute_reply":"2024-07-26T20:08:15.435932Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Define the search space for hyperparameter optimization","metadata":{}},{"cell_type":"code","source":"space = {\n    'num_leaves': scope.int(hp.quniform('num_leaves', 30, 100, 1)),  \n    'max_depth': scope.int(hp.quniform('max_depth', 3, 10, 1)),      \n    'learning_rate': hp.loguniform('learning_rate', -3, -1),         \n    'n_estimators': scope.int(hp.quniform('n_estimators', 50, 300, 1)),  \n    'subsample': hp.uniform('subsample', 0.6, 1),                   \n    'colsample_bytree': hp.uniform('colsample_bytree', 0.6, 1),     \n    'reg_alpha': hp.uniform('reg_alpha', 0, 1),\n    'reg_lambda': hp.uniform('reg_lambda', 0, 1),\n    'min_child_samples': scope.int(hp.quniform('min_child_samples', 5, 50, 1)),  \n    'verbose': -1,\n}","metadata":{"execution":{"iopub.status.busy":"2024-07-26T20:08:15.439039Z","iopub.execute_input":"2024-07-26T20:08:15.439424Z","iopub.status.idle":"2024-07-26T20:08:15.447956Z","shell.execute_reply.started":"2024-07-26T20:08:15.439385Z","shell.execute_reply":"2024-07-26T20:08:15.446521Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Define the objective function for hyperparameter optimization","metadata":{}},{"cell_type":"code","source":"def objective(space):\n    model = LGBMRegressor(**space)\n    model.fit(X_train_val, y_train_val)\n    y_pred = model.predict(val_data.drop(columns='position'))\n    return mean_squared_error(val_data['position'], y_pred)","metadata":{"execution":{"iopub.status.busy":"2024-07-26T20:08:15.449383Z","iopub.execute_input":"2024-07-26T20:08:15.449719Z","iopub.status.idle":"2024-07-26T20:08:15.460618Z","shell.execute_reply.started":"2024-07-26T20:08:15.449693Z","shell.execute_reply":"2024-07-26T20:08:15.459265Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Run the hyperparameter search","metadata":{}},{"cell_type":"code","source":"trials = Trials()\nbest_params = fmin(fn=objective, space=space, algo=tpe.suggest, max_evals=20, trials=trials)","metadata":{"execution":{"iopub.status.busy":"2024-07-26T20:09:17.109512Z","iopub.execute_input":"2024-07-26T20:09:17.110094Z","iopub.status.idle":"2024-07-26T20:16:18.221192Z","shell.execute_reply.started":"2024-07-26T20:09:17.110053Z","shell.execute_reply":"2024-07-26T20:16:18.219520Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Ensure integer parameters are cast to int","metadata":{}},{"cell_type":"code","source":"best_params['num_leaves'] = int(best_params['num_leaves'])\nbest_params['max_depth'] = int(best_params['max_depth'])\nbest_params['n_estimators'] = int(best_params['n_estimators'])\nbest_params['min_child_samples'] = int(best_params['min_child_samples'])","metadata":{"execution":{"iopub.status.busy":"2024-07-26T20:16:48.570223Z","iopub.execute_input":"2024-07-26T20:16:48.570828Z","iopub.status.idle":"2024-07-26T20:16:48.583371Z","shell.execute_reply.started":"2024-07-26T20:16:48.570788Z","shell.execute_reply":"2024-07-26T20:16:48.581874Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"markdown","source":"# Train the final model with the best hyperparameters","metadata":{}},{"cell_type":"code","source":"final_model = LGBMRegressor(**best_params, verbose=-1)\nfinal_model.fit(X_train_val, y_train_val)","metadata":{"execution":{"iopub.status.busy":"2024-07-26T20:16:53.342365Z","iopub.execute_input":"2024-07-26T20:16:53.342783Z","iopub.status.idle":"2024-07-26T20:17:22.196947Z","shell.execute_reply.started":"2024-07-26T20:16:53.342751Z","shell.execute_reply":"2024-07-26T20:17:22.195418Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Train the final model with the best hyperparameters","metadata":{}},{"cell_type":"code","source":"final_model = LGBMRegressor(**best_params, verbose=-1)\nfinal_model.fit(X_train_val, y_train_val)","metadata":{"execution":{"iopub.status.busy":"2024-07-26T20:17:27.038973Z","iopub.execute_input":"2024-07-26T20:17:27.039488Z","iopub.status.idle":"2024-07-26T20:17:57.659970Z","shell.execute_reply.started":"2024-07-26T20:17:27.039447Z","shell.execute_reply":"2024-07-26T20:17:57.658460Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Make predictions on the test data","metadata":{}},{"cell_type":"code","source":"y_test_pred = final_model.predict(test_data)","metadata":{"execution":{"iopub.status.busy":"2024-07-26T20:18:01.882726Z","iopub.execute_input":"2024-07-26T20:18:01.883113Z","iopub.status.idle":"2024-07-26T20:18:07.285135Z","shell.execute_reply.started":"2024-07-26T20:18:01.883085Z","shell.execute_reply":"2024-07-26T20:18:07.283896Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Convert predictions to integers","metadata":{}},{"cell_type":"code","source":"y_test_pred_int = np.round(y_test_pred).astype(int)","metadata":{"execution":{"iopub.status.busy":"2024-07-26T20:18:14.893311Z","iopub.execute_input":"2024-07-26T20:18:14.893775Z","iopub.status.idle":"2024-07-26T20:18:14.900104Z","shell.execute_reply.started":"2024-07-26T20:18:14.893740Z","shell.execute_reply":"2024-07-26T20:18:14.898961Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Create submission file","metadata":{}},{"cell_type":"code","source":"\nsubmission = pd.DataFrame({'position': y_test_pred_int, 'result_driver_standing': test_data['result_driver_standing']})\nsubmission.to_csv('submission.csv', index=False)\n\nsubmission.head()","metadata":{"execution":{"iopub.status.busy":"2024-07-26T20:18:22.397941Z","iopub.execute_input":"2024-07-26T20:18:22.399021Z","iopub.status.idle":"2024-07-26T20:18:22.742627Z","shell.execute_reply.started":"2024-07-26T20:18:22.398983Z","shell.execute_reply":"2024-07-26T20:18:22.741566Z"},"trusted":true},"execution_count":null,"outputs":[]}]}