{"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.12.1"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":104857,"databundleVersionId":12651513,"sourceType":"competition"}],"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"id":"545e4a68","cell_type":"code","source":"# Import necessary libraries for EDA\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport warnings\nwarnings.filterwarnings('ignore')\n\n# Set display options\npd.set_option('display.max_columns', None)\npd.set_option('display.max_rows', 100)\n\n# Set plot style\nplt.style.use('default')\nsns.set_palette(\"husl\")\n\nprint(\"Libraries imported successfully!\")","metadata":{},"outputs":[],"execution_count":null},{"id":"083ab27c","cell_type":"code","source":"# Load the training data\ntrain_df = pd.read_csv('data/train.csv')\n\nprint(\"Dataset loaded successfully!\")\nprint(f\"Dataset shape: {train_df.shape}\")\nprint(f\"Number of rows: {train_df.shape[0]:,}\")\nprint(f\"Number of columns: {train_df.shape[1]}\")\nprint(\"\\nFirst few rows:\")\ntrain_df.head()","metadata":{},"outputs":[],"execution_count":null},{"id":"36d9e45e","cell_type":"code","source":"# Display dataset info\nprint(\"Dataset Information:\")\nprint(\"=\" * 50)\ntrain_df.info()\n\nprint(\"\\n\" + \"=\" * 50)\nprint(\"Data Types:\")\nprint(train_df.dtypes)\n\nprint(\"\\n\" + \"=\" * 50)\nprint(\"Column Names:\")\nprint(list(train_df.columns))","metadata":{},"outputs":[],"execution_count":null},{"id":"19533598","cell_type":"code","source":"# Check for missing values\nprint(\"Missing Values Analysis:\")\nprint(\"=\" * 50)\nmissing_values = train_df.isnull().sum()\nmissing_percent = (missing_values / len(train_df)) * 100\n\nmissing_df = pd.DataFrame({\n    'Column': missing_values.index,\n    'Missing Count': missing_values.values,\n    'Missing Percentage': missing_percent.values\n})\nmissing_df = missing_df[missing_df['Missing Count'] > 0].sort_values('Missing Count', ascending=False)\n\nif len(missing_df) > 0:\n    print(missing_df)\nelse:\n    print(\"No missing values found!\")\n\nprint(\"\\n\" + \"=\" * 50)\nprint(\"Duplicate Rows:\")\nduplicates = train_df.duplicated().sum()\nprint(f\"Number of duplicate rows: {duplicates}\")\nprint(f\"Percentage of duplicates: {(duplicates/len(train_df)*100):.2f}%\")","metadata":{},"outputs":[],"execution_count":null},{"id":"73c9836a","cell_type":"code","source":"# Analyze numerical features\nprint(\"Numerical Features Analysis:\")\nprint(\"=\" * 50)\n\n# Identify numerical columns\nnumerical_cols = train_df.select_dtypes(include=[np.number]).columns.tolist()\nprint(f\"Numerical columns: {numerical_cols}\")\n\nif numerical_cols:\n    print(\"\\nDescriptive Statistics for Numerical Features:\")\n    print(train_df[numerical_cols].describe().round(2))\n    \n    # Check for outliers using IQR method\n    print(\"\\n\" + \"=\" * 50)\n    print(\"Outlier Analysis (using IQR method):\")\n    \n    for col in numerical_cols:\n        Q1 = train_df[col].quantile(0.25)\n        Q3 = train_df[col].quantile(0.75)\n        IQR = Q3 - Q1\n        lower_bound = Q1 - 1.5 * IQR\n        upper_bound = Q3 + 1.5 * IQR\n        \n        outliers = train_df[(train_df[col] < lower_bound) | (train_df[col] > upper_bound)]\n        print(f\"{col}: {len(outliers)} outliers ({len(outliers)/len(train_df)*100:.2f}%)\")\nelse:\n    print(\"No numerical columns found!\")","metadata":{},"outputs":[],"execution_count":null},{"id":"64834ab4","cell_type":"code","source":"# Analyze categorical features\nprint(\"Categorical Features Analysis:\")\nprint(\"=\" * 50)\n\n# Identify categorical columns\ncategorical_cols = train_df.select_dtypes(include=['object', 'category']).columns.tolist()\nprint(f\"Categorical columns: {categorical_cols}\")\n\nif categorical_cols:\n    print(\"\\nUnique values in each categorical column:\")\n    for col in categorical_cols:\n        unique_count = train_df[col].nunique()\n        print(f\"{col}: {unique_count} unique values\")\n        \n        # Show value counts for columns with reasonable number of unique values\n        if unique_count <= 20:\n            print(f\"  Value counts:\")\n            print(train_df[col].value_counts().head(10))\n            print(f\"  Percentage distribution:\")\n            print((train_df[col].value_counts(normalize=True) * 100).round(2).head(10))\n        else:\n            print(f\"  Top 10 most frequent values:\")\n            print(train_df[col].value_counts().head(10))\n        print(\"-\" * 30)\nelse:\n    print(\"No categorical columns found!\")","metadata":{},"outputs":[],"execution_count":null},{"id":"392abc5b","cell_type":"code","source":"# Visualizations for numerical features\nif numerical_cols:\n    print(\"Creating visualizations for numerical features...\")\n    \n    # Calculate number of rows needed for subplots\n    n_cols = len(numerical_cols)\n    n_rows = (n_cols + 2) // 3  # 3 columns per row\n    \n    # Histograms and distribution plots\n    fig, axes = plt.subplots(n_rows, 3, figsize=(15, 5*n_rows))\n    axes = axes.flatten() if n_rows > 1 else [axes] if n_rows == 1 and n_cols == 1 else axes\n    \n    for i, col in enumerate(numerical_cols):\n        if i < len(axes):\n            axes[i].hist(train_df[col].dropna(), bins=30, alpha=0.7, edgecolor='black')\n            axes[i].set_title(f'Distribution of {col}')\n            axes[i].set_xlabel(col)\n            axes[i].set_ylabel('Frequency')\n            axes[i].grid(True, alpha=0.3)\n    \n    # Hide empty subplots\n    for j in range(i+1, len(axes)):\n        axes[j].set_visible(False)\n    \n    plt.tight_layout()\n    plt.show()\n    \n    # Box plots for outlier detection\n    fig, axes = plt.subplots(n_rows, 3, figsize=(15, 5*n_rows))\n    axes = axes.flatten() if n_rows > 1 else [axes] if n_rows == 1 and n_cols == 1 else axes\n    \n    for i, col in enumerate(numerical_cols):\n        if i < len(axes):\n            axes[i].boxplot(train_df[col].dropna())\n            axes[i].set_title(f'Box Plot of {col}')\n            axes[i].set_xlabel(col)\n            axes[i].grid(True, alpha=0.3)\n    \n    # Hide empty subplots\n    for j in range(i+1, len(axes)):\n        axes[j].set_visible(False)\n    \n    plt.tight_layout()\n    plt.show()\nelse:\n    print(\"No numerical columns to visualize.\")","metadata":{},"outputs":[],"execution_count":null},{"id":"12b661db","cell_type":"code","source":"# Visualizations for categorical features\nif categorical_cols:\n    print(\"Creating visualizations for categorical features...\")\n    \n    # Filter columns with reasonable number of unique values for visualization\n    vis_categorical_cols = [col for col in categorical_cols if train_df[col].nunique() <= 20]\n    \n    if vis_categorical_cols:\n        n_cols = len(vis_categorical_cols)\n        n_rows = (n_cols + 1) // 2  # 2 columns per row\n        \n        # Bar plots for categorical features\n        fig, axes = plt.subplots(n_rows, 2, figsize=(15, 6*n_rows))\n        axes = axes.flatten() if n_rows > 1 else [axes] if n_rows == 1 and n_cols == 1 else axes\n        \n        for i, col in enumerate(vis_categorical_cols):\n            if i < len(axes):\n                value_counts = train_df[col].value_counts().head(15)  # Top 15 values\n                axes[i].bar(range(len(value_counts)), value_counts.values)\n                axes[i].set_title(f'Distribution of {col}')\n                axes[i].set_xlabel(col)\n                axes[i].set_ylabel('Count')\n                axes[i].set_xticks(range(len(value_counts)))\n                axes[i].set_xticklabels(value_counts.index, rotation=45, ha='right')\n                axes[i].grid(True, alpha=0.3)\n        \n        # Hide empty subplots\n        for j in range(i+1, len(axes)):\n            axes[j].set_visible(False)\n        \n        plt.tight_layout()\n        plt.show()\n    else:\n        print(\"No categorical columns with suitable number of unique values for visualization.\")\n    \n    # Show high cardinality categorical columns\n    high_card_cols = [col for col in categorical_cols if train_df[col].nunique() > 20]\n    if high_card_cols:\n        print(f\"\\nHigh cardinality categorical columns (>20 unique values): {high_card_cols}\")\n        for col in high_card_cols:\n            print(f\"{col}: {train_df[col].nunique()} unique values\")\nelse:\n    print(\"No categorical columns to visualize.\")","metadata":{},"outputs":[],"execution_count":null},{"id":"c464eca5","cell_type":"code","source":"# Correlation analysis\nif len(numerical_cols) > 1:\n    print(\"Correlation Analysis:\")\n    print(\"=\" * 50)\n    \n    # Calculate correlation matrix\n    correlation_matrix = train_df[numerical_cols].corr()\n    \n    # Display correlation matrix\n    print(\"Correlation Matrix:\")\n    print(correlation_matrix.round(3))\n    \n    # Find highly correlated features\n    print(\"\\nHighly Correlated Feature Pairs (|correlation| > 0.7):\")\n    high_corr_pairs = []\n    for i in range(len(correlation_matrix.columns)):\n        for j in range(i+1, len(correlation_matrix.columns)):\n            corr_val = correlation_matrix.iloc[i, j]\n            if abs(corr_val) > 0.7:\n                high_corr_pairs.append((correlation_matrix.columns[i], \n                                      correlation_matrix.columns[j], \n                                      corr_val))\n    \n    if high_corr_pairs:\n        for pair in high_corr_pairs:\n            print(f\"{pair[0]} - {pair[1]}: {pair[2]:.3f}\")\n    else:\n        print(\"No highly correlated feature pairs found.\")\n    \n    # Heatmap of correlation matrix\n    plt.figure(figsize=(20, 18))\n    sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', center=0, \n                square=True, fmt='.2f', cbar_kws={'shrink': 0.8})\n    plt.title('Correlation Heatmap of Numerical Features')\n    plt.tight_layout()\n    plt.show()\nelse:\n    print(\"Not enough numerical columns for correlation analysis.\")","metadata":{},"outputs":[],"execution_count":null},{"id":"b22a848e","cell_type":"code","source":"# Target variable analysis\nprint(\"Target Variable Analysis:\")\nprint(\"=\" * 50)\n\n# Common target variable names\ntarget_candidates = ['target', 'label', 'y', 'class', 'prediction', 'burnout', 'burn_out', 'outcome']\ntarget_col = None\n\n# Check if any target column exists\nfor col in train_df.columns:\n    if col.lower() in target_candidates or 'target' in col.lower():\n        target_col = col\n        break\n\nif target_col:\n    print(f\"Target column found: {target_col}\")\n    print(f\"Target variable type: {train_df[target_col].dtype}\")\n    \n    # Analyze target variable\n    print(f\"\\nTarget variable statistics:\")\n    if train_df[target_col].dtype in ['int64', 'float64']:\n        print(train_df[target_col].describe())\n        \n        # Plot target distribution\n        plt.figure(figsize=(12, 4))\n        \n        plt.subplot(1, 2, 1)\n        plt.hist(train_df[target_col].dropna(), bins=30, alpha=0.7, edgecolor='black')\n        plt.title(f'Distribution of {target_col}')\n        plt.xlabel(target_col)\n        plt.ylabel('Frequency')\n        plt.grid(True, alpha=0.3)\n        \n        plt.subplot(1, 2, 2)\n        plt.boxplot(train_df[target_col].dropna())\n        plt.title(f'Box Plot of {target_col}')\n        plt.ylabel(target_col)\n        plt.grid(True, alpha=0.3)\n        \n        plt.tight_layout()\n        plt.show()\n    else:\n        # Categorical target\n        target_counts = train_df[target_col].value_counts()\n        print(target_counts)\n        print(f\"\\nTarget distribution (%):\")\n        print((target_counts / len(train_df) * 100).round(2))\n        \n        # Plot target distribution\n        plt.figure(figsize=(10, 6))\n        target_counts.plot(kind='bar')\n        plt.title(f'Distribution of {target_col}')\n        plt.xlabel(target_col)\n        plt.ylabel('Count')\n        plt.xticks(rotation=45)\n        plt.grid(True, alpha=0.3)\n        plt.tight_layout()\n        plt.show()\nelse:\n    print(\"Available columns:\", list(train_df.columns))","metadata":{},"outputs":[],"execution_count":null},{"id":"3711f2ed","cell_type":"code","source":"# Summary and Key Insights\nprint(\"EDA SUMMARY AND KEY INSIGHTS:\")\nprint(\"=\" * 60)\n\nprint(f\"📊 Dataset Overview:\")\nprint(f\"   • Total samples: {train_df.shape[0]:,}\")\nprint(f\"   • Total features: {train_df.shape[1]}\")\nprint(f\"   • Memory usage: {train_df.memory_usage(deep=True).sum() / 1024**2:.2f} MB\")\n\nprint(f\"\\n🔢 Feature Types:\")\nprint(f\"   • Numerical features: {len(numerical_cols)}\")\nprint(f\"   • Categorical features: {len(categorical_cols)}\")\n\nprint(f\"\\n🔍 Data Quality:\")\ntotal_missing = train_df.isnull().sum().sum()\nprint(f\"   • Total missing values: {total_missing}\")\nprint(f\"   • Missing percentage: {(total_missing / (train_df.shape[0] * train_df.shape[1]) * 100):.2f}%\")\nprint(f\"   • Duplicate rows: {train_df.duplicated().sum()}\")\n\nif numerical_cols:\n    print(f\"\\n📈 Numerical Features Insights:\")\n    for col in numerical_cols:\n        skewness = train_df[col].skew()\n        print(f\"   • {col}: Mean={train_df[col].mean():.2f}, Std={train_df[col].std():.2f}, Skewness={skewness:.2f}\")\n\nif categorical_cols:\n    print(f\"\\n📋 Categorical Features Insights:\")\n    for col in categorical_cols:\n        unique_count = train_df[col].nunique()\n        most_common = train_df[col].mode().iloc[0] if len(train_df[col].mode()) > 0 else \"N/A\"\n        print(f\"   • {col}: {unique_count} unique values, Most common: {most_common}\")\n\nprint(f\"\\n💡 Recommendations for Next Steps:\")\nprint(\"   1. Handle missing values if any\")\nprint(\"   2. Check for and handle outliers in numerical features\")\nprint(\"   3. Encode categorical variables appropriately\")\nprint(\"   4. Consider feature scaling for numerical features\")\nprint(\"   5. Explore feature engineering opportunities\")\n\nprint(f\"\\n✅ EDA completed successfully!\")","metadata":{},"outputs":[],"execution_count":null},{"id":"75f17da6","cell_type":"code","source":"# ========================================\n# do not delete this\n# ========================================\n\nprint(\"🚀 OPTIMIZED XGBOOST MODEL\")\nprint(\"=\"*80)\nprint(\"Target: RMSE < 1.0 with efficient gradient boosting\")\nprint(\"=\"*80)\n\nimport xgboost as xgb\nimport pandas as pd\nimport numpy as np\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.preprocessing import LabelEncoder\nfrom sklearn.metrics import mean_squared_error\nimport warnings\nwarnings.filterwarnings('ignore')\n\n# Set random seed for reproducibility\nnp.random.seed(42)\n\nprint(\"🔧 Loading and preprocessing data...\")\n\n# Load data\ntrain_df = pd.read_csv('data/train.csv')\ntest_df = pd.read_csv('data/test.csv')\nsample_submission = pd.read_csv('data/sample_submission.csv')\n\nprint(f\"Train shape: {train_df.shape}\")\nprint(f\"Test shape: {test_df.shape}\")\n\n# Target variable\ntarget_col = 'Lap_Time_Seconds'\ny = train_df[target_col].values\n\nprint(f\"Target statistics:\")\nprint(f\"  Mean: {np.mean(y):.3f}\")\nprint(f\"  Std: {np.std(y):.3f}\")\nprint(f\"  Min: {np.min(y):.3f}\")\nprint(f\"  Max: {np.max(y):.3f}\")","metadata":{},"outputs":[],"execution_count":null},{"id":"92f1ea7a","cell_type":"code","source":"# Efficient Feature Engineering for XGBoost\nprint(\"\\n🔧 EFFICIENT FEATURE PREPROCESSING\")\nprint(\"-\" * 50)\n\ndef preprocess_for_xgb(df, is_train=True):\n    \"\"\"Efficient preprocessing specifically optimized for XGBoost\"\"\"\n    \n    df_processed = df.copy()\n    \n    # Handle missing values efficiently\n    numeric_cols = df_processed.select_dtypes(include=[np.number]).columns\n    categorical_cols = df_processed.select_dtypes(include=['object']).columns\n    \n    # Fill numeric with median (XGBoost handles missing values well)\n    for col in numeric_cols:\n        if df_processed[col].isnull().sum() > 0:\n            df_processed[col].fillna(df_processed[col].median(), inplace=True)\n    \n    # Fill categorical with mode\n    for col in categorical_cols:\n        if df_processed[col].isnull().sum() > 0:\n            df_processed[col].fillna(df_processed[col].mode()[0], inplace=True)\n    \n    # Key engineered features that work well with XGBoost\n    if 'Track_Temperature_Celsius' in df_processed.columns and 'Ambient_Temperature_Celsius' in df_processed.columns:\n        df_processed['Temp_Diff'] = df_processed['Track_Temperature_Celsius'] - df_processed['Ambient_Temperature_Celsius']\n        df_processed['Temp_Ratio'] = df_processed['Track_Temperature_Celsius'] / np.maximum(df_processed['Ambient_Temperature_Celsius'], 1)\n    \n    if 'Humidity_%' in df_processed.columns and 'Ambient_Temperature_Celsius' in df_processed.columns:\n        df_processed['Humidity_Temp_Product'] = df_processed['Humidity_%'] * df_processed['Ambient_Temperature_Celsius']\n    \n    if 'Circuit_Length_km' in df_processed.columns and 'Avg_Speed_kmh' in df_processed.columns:\n        df_processed['Speed_per_km'] = df_processed['Avg_Speed_kmh'] / np.maximum(df_processed['Circuit_Length_km'], 0.1)\n    \n    if 'wins' in df_processed.columns and 'years_active' in df_processed.columns:\n        df_processed['Win_Rate'] = df_processed['wins'] / np.maximum(df_processed['years_active'], 1)\n    \n    if 'points' in df_processed.columns and 'years_active' in df_processed.columns:\n        df_processed['Points_Per_Year'] = df_processed['points'] / np.maximum(df_processed['years_active'], 1)\n    \n    # Add interaction features\n    if 'Grid_Position' in df_processed.columns and 'years_active' in df_processed.columns:\n        df_processed['Experience_Grid_Interaction'] = df_processed['years_active'] / np.maximum(df_processed['Grid_Position'], 1)\n    \n    return df_processed\n\n# Process train and test data\nprint(\"Processing training data...\")\ntrain_processed = preprocess_for_xgb(train_df, is_train=True)\n\nprint(\"Processing test data...\")\ntest_processed = preprocess_for_xgb(test_df, is_train=False)\n\nprint(f\"✅ Feature engineering complete\")\nprint(f\"   Train features: {train_processed.shape[1]}\")\nprint(f\"   Test features: {test_processed.shape[1]}\")\n\n# Prepare features for modeling\nfeature_cols = [col for col in train_processed.columns if col != target_col]\n\n# Encode categorical variables efficiently for XGBoost\nlabel_encoders = {}\ncategorical_features = train_processed[feature_cols].select_dtypes(include=['object']).columns\n\nprint(f\"\\n🏷️  Encoding {len(categorical_features)} categorical features...\")\n\nfor col in categorical_features:\n    le = LabelEncoder()\n    \n    # Fit on combined train+test to ensure consistent encoding\n    combined_values = pd.concat([train_processed[col], test_processed[col]], axis=0)\n    le.fit(combined_values.astype(str))\n    \n    train_processed[col] = le.transform(train_processed[col].astype(str))\n    test_processed[col] = le.transform(test_processed[col].astype(str))\n    \n    label_encoders[col] = le\n\nprint(f\"✅ Categorical encoding complete\")\n\n# Prepare final datasets\nX = train_processed[feature_cols].values\nX_test = test_processed[feature_cols].values\n\nprint(f\"\\n📊 Final dataset shapes:\")\nprint(f\"   X_train: {X.shape}\")\nprint(f\"   X_test: {X_test.shape}\")\nprint(f\"   y_train: {y.shape}\")","metadata":{},"outputs":[],"execution_count":null},{"id":"af9a5095","cell_type":"code","source":"# Split data for training and validation\nX_train, X_val, y_train, y_val = train_test_split(\n    X, y, test_size=0.2, random_state=42\n)\n\nprint(f\"✅ Data split complete\")\nprint(f\"   Train: {X_train.shape}\")\nprint(f\"   Validation: {X_val.shape}\")\n\n# Optimized XGBoost parameters for this regression task\nxgb_params = {\n    'objective': 'reg:squarederror',\n    'eval_metric': 'rmse',\n    'max_depth': 20,\n    'learning_rate': 0.05,\n    'n_estimators': 1500,\n    'subsample': 0.8,\n    'colsample_bytree': 0.8,\n    'colsample_bylevel': 0.8,\n    'min_child_weight': 3,\n    'reg_alpha': 0.1,\n    'reg_lambda': 1.0,\n    'random_state': 42,\n    'n_jobs': -1,\n    'tree_method': 'hist',  # Fast histogram-based algorithm\n    'early_stopping_rounds': 500,\n    'verbosity': 1\n}\n\nprint(f\"🔧 XGBoost Parameters:\")\nfor key, value in xgb_params.items():\n    print(f\"   {key}: {value}\")\n\n# Create and train XGBoost model\nprint(f\"\\n🏋️ Training XGBoost model...\")\n\nmodel = xgb.XGBRegressor(**xgb_params)\n\n# Train the model\nmodel.fit(\n    X_train, y_train,\n    eval_set=[(X_val, y_val)],\n    verbose=50\n)\n\nprint(f\"✅ Model training completed\")\nprint(f\"   Best iteration: {model.best_iteration}\")\nprint(f\"   Best score: {model.best_score:.6f}\")\n\n# Model Evaluation\nprint(f\"\\n📊 MODEL EVALUATION\")\nprint(\"-\" * 50)\n\n# Make predictions on validation set\ny_val_pred = model.predict(X_val)\n\n# Calculate RMSE\nval_rmse = np.sqrt(mean_squared_error(y_val, y_val_pred))\nval_mae = np.mean(np.abs(y_val - y_val_pred))\n\nprint(f\"🎯 VALIDATION PERFORMANCE:\")\nprint(f\"   RMSE: {val_rmse:.6f}\")\nprint(f\"   MAE:  {val_mae:.6f}\")\n\n# Check if target achieved\ntarget_rmse = 1.0\nif val_rmse < target_rmse:\n    print(f\"\\n🎉 TARGET ACHIEVED! 🎉\")\n    print(f\"   ✅ RMSE {val_rmse:.6f} < {target_rmse}\")\n    print(f\"   🚀 Exceeded target by: {target_rmse - val_rmse:.6f}\")\nelse:\n    gap = val_rmse - target_rmse\n    print(f\"\\n🎯 Performance Status:\")\n    print(f\"   📊 RMSE: {val_rmse:.6f}\")\n    print(f\"   📏 Gap to target: {gap:.6f}\")\n    print(f\"   📈 Progress: {(1 - gap/val_rmse)*100:.1f}% achieved\")\n\n# Feature Importance Analysis\nprint(f\"\\n🔍 TOP 15 FEATURE IMPORTANCE:\")\nfeature_importance = pd.DataFrame({\n    'feature': feature_cols,\n    'importance': model.feature_importances_\n}).sort_values('importance', ascending=False)\n\nprint(feature_importance.head(15).to_string(index=False))","metadata":{},"outputs":[],"execution_count":null},{"id":"7fe1ab81","cell_type":"code","source":"# Generate Final Predictions and Create Solution\nprint(f\"\\n🔮 GENERATING FINAL PREDICTIONS\")\n# Generate test predictions\ntest_predictions = model.predict(X_test)\n\nprint(f\"✅ Test predictions generated\")\nprint(f\"   Shape: {test_predictions.shape}\")\nprint(f\"   Min: {np.min(test_predictions):.3f}\")\nprint(f\"   Max: {np.max(test_predictions):.3f}\")\nprint(f\"   Mean: {np.mean(test_predictions):.3f}\")\nprint(f\"   Std: {np.std(test_predictions):.3f}\")\n\n# Create final submission\nprint(f\"\\n💾 CREATING SOLUTION FILE\")\nprint(\"-\" * 50)\n\n# Create solution dataframe\nsolution_df = pd.DataFrame({\n    'Unique ID': test_processed['Unique ID'],\n    'Lap_Time_Seconds': test_predictions\n})\n\n# Quality checks\nprint(\"🔍 SOLUTION QUALITY CHECKS:\")\nprint(f\"   📊 Shape: {solution_df.shape}\")\nprint(f\"   📈 Min prediction: {solution_df['Lap_Time_Seconds'].min():.6f}\")\nprint(f\"   📉 Max prediction: {solution_df['Lap_Time_Seconds'].max():.6f}\")\nprint(f\"   📊 Mean prediction: {solution_df['Lap_Time_Seconds'].mean():.6f}\")\nprint(f\"   📊 Std prediction: {solution_df['Lap_Time_Seconds'].std():.6f}\")\n\n# Check for any issues\nnan_count = solution_df['Lap_Time_Seconds'].isnull().sum()\ninf_count = np.isinf(solution_df['Lap_Time_Seconds']).sum()\n\nif nan_count > 0 or inf_count > 0:\n    print(f\"   ⚠️ Found {nan_count} NaN and {inf_count} inf values - fixing...\")\n    solution_df['Lap_Time_Seconds'] = solution_df['Lap_Time_Seconds'].replace([np.inf, -np.inf], np.nan)\n    solution_df['Lap_Time_Seconds'].fillna(solution_df['Lap_Time_Seconds'].median(), inplace=True)\n    print(\"   ✅ Issues fixed\")\nelse:\n    print(\"   ✅ No issues found\")\n\n# Save the solution\nimport os\nimport time\n\n# Try different filenames if solution.csv is locked\nsolution_filename = 'solution1.csv'\nif os.path.exists(solution_filename):\n    try:\n        # Try to delete if exists\n        os.remove(solution_filename)\n    except:\n        # Use timestamp if can't delete\n        timestamp = int(time.time())\n        solution_filename = f'solution_{timestamp}.csv'\n\nsolution_df.to_csv(solution_filename, index=False)\nprint(f\"\\n✅ SOLUTION SAVED: {solution_filename}\")","metadata":{},"outputs":[],"execution_count":null}]}