{"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":103436,"databundleVersionId":12476472,"sourceType":"competition"}],"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,"execution":{"iopub.status.busy":"2025-07-01T07:19:10.325892Z","iopub.execute_input":"2025-07-01T07:19:10.326159Z","iopub.status.idle":"2025-07-01T07:19:10.595730Z","shell.execute_reply.started":"2025-07-01T07:19:10.326138Z","shell.execute_reply":"2025-07-01T07:19:10.594933Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 1. Import Libraries và Setup","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport lightgbm as lgb\nfrom sklearn.model_selection import StratifiedKFold\nfrom sklearn.preprocessing import LabelEncoder\nfrom sklearn.metrics import f1_score, classification_report\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport warnings\nwarnings.filterwarnings('ignore')\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-01T07:19:14.306405Z","iopub.execute_input":"2025-07-01T07:19:14.306784Z","iopub.status.idle":"2025-07-01T07:19:19.666438Z","shell.execute_reply.started":"2025-07-01T07:19:14.306759Z","shell.execute_reply":"2025-07-01T07:19:19.665744Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 2. Load và Khám phá Dữ liệu","metadata":{}},{"cell_type":"code","source":"def load_and_explore_data():\n    \"\"\"Load và khám phá dữ liệu training\"\"\"\n    print(\"Loading training data...\")\n    \n    # Load các file training\n    delay_4_6 = pd.read_csv('/kaggle/input/ds-108-p-21-assigment-06/delay_4_6_CONDITION_PRODUCT_SUPPLIER.csv')\n    delay_7_9 = pd.read_csv('/kaggle/input/ds-108-p-21-assigment-06/delay_7_9_CONDITION_PRODUCT_SUPPLIER.csv')\n    not_delay_4_6 = pd.read_csv('/kaggle/input/ds-108-p-21-assigment-06/not_delay_4_6_CONDITION_PRODUCT_SUPPLIER.csv')\n    not_delay_7_9 = pd.read_csv('/kaggle/input/ds-108-p-21-assigment-06/not_delay_7_9_CONDITION_PRODUCT_SUPPLIER.csv')\n    \n    print(f\"Data shapes:\")\n    print(f\" - Delay 4-6: {delay_4_6.shape}\")\n    print(f\" - Delay 7-9: {delay_7_9.shape}\")\n    print(f\" - Not delay 4-6: {not_delay_4_6.shape}\")\n    print(f\" - Not delay 7-9: {not_delay_7_9.shape}\")\n    \n    # Thêm label\n    delay_4_6['label'] = 1  # delay\n    delay_7_9['label'] = 1  # delay\n    not_delay_4_6['label'] = 0  # not delay\n    not_delay_7_9['label'] = 0  # not delay\n    \n    # Gộp tất cả dữ liệu training\n    train_data = pd.concat([delay_4_6, delay_7_9, not_delay_4_6, not_delay_7_9], \n                          ignore_index=True)\n    \n    print(f\"\\n Combined training data shape: {train_data.shape}\")\n    print(f\" Label distribution:\")\n    label_counts = train_data['label'].value_counts()\n    print(f\" - Not delay (0): {label_counts[0]:,} ({label_counts[0]/len(train_data)*100:.1f}%)\")\n    print(f\" - Delay (1): {label_counts[1]:,} ({label_counts[1]/len(train_data)*100:.1f}%)\")\n    \n    return train_data\n\n# Load data\ntrain_df = load_and_explore_data()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-01T07:19:19.667692Z","iopub.execute_input":"2025-07-01T07:19:19.668465Z","iopub.status.idle":"2025-07-01T07:19:30.110082Z","shell.execute_reply.started":"2025-07-01T07:19:19.668443Z","shell.execute_reply":"2025-07-01T07:19:30.109422Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(f\"\\nColumns ({len(train_df.columns)}):\")\nfor i, col in enumerate(train_df.columns, 1):\n    print(f\"  {i:2d}. {col}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-01T07:21:35.471177Z","iopub.execute_input":"2025-07-01T07:21:35.471803Z","iopub.status.idle":"2025-07-01T07:21:35.476621Z","shell.execute_reply.started":"2025-07-01T07:21:35.471778Z","shell.execute_reply":"2025-07-01T07:21:35.475822Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(f\"\\nData Types:\")\nprint(train_df.dtypes.value_counts())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-01T07:21:35.822867Z","iopub.execute_input":"2025-07-01T07:21:35.823356Z","iopub.status.idle":"2025-07-01T07:21:35.828966Z","shell.execute_reply.started":"2025-07-01T07:21:35.823322Z","shell.execute_reply":"2025-07-01T07:21:35.828299Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"missing_data = train_df.isnull().sum()\nmissing_data = missing_data[missing_data > 0].sort_values(ascending=False)\nif len(missing_data) > 0:\n    print(missing_data.head(10))\nelse:\n    print(\"  No missing values found!\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-01T07:21:36.194266Z","iopub.execute_input":"2025-07-01T07:21:36.194536Z","iopub.status.idle":"2025-07-01T07:21:37.249452Z","shell.execute_reply.started":"2025-07-01T07:21:36.194519Z","shell.execute_reply":"2025-07-01T07:21:37.248848Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Load test data\ndef load_test_data():\n    \"\"\"Load dữ liệu test\"\"\"\n    test_data = pd.read_csv('/kaggle/input/ds-108-p-21-assigment-06/PILOT_10.csv')\n    print(f\"Test data shape: {test_data.shape}\")\n    return test_data\n\ntest_df = load_test_data()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-01T07:21:59.995816Z","iopub.execute_input":"2025-07-01T07:21:59.996633Z","iopub.status.idle":"2025-07-01T07:22:00.591421Z","shell.execute_reply.started":"2025-07-01T07:21:59.996606Z","shell.execute_reply":"2025-07-01T07:22:00.590711Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(f\"\\nTest data columns ({len(test_df.columns)}):\")\nfor i, col in enumerate(test_df.columns, 1):\n    print(f\"  {i:2d}. {col}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-01T07:22:01.758872Z","iopub.execute_input":"2025-07-01T07:22:01.759140Z","iopub.status.idle":"2025-07-01T07:22:01.763676Z","shell.execute_reply.started":"2025-07-01T07:22:01.759121Z","shell.execute_reply":"2025-07-01T07:22:01.763081Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 3. Data Preprocessing và Feature Engineering","metadata":{}},{"cell_type":"code","source":"def preprocess_data(train_df, test_df):\n    \"\"\"Tiền xử lý dữ liệu\"\"\"\n    print(\"Preprocessing data...\")\n    \n    # Chuẩn hóa tên cột - xử lý vấn đề SPECIAL DIV vs SPECIAL_DIV\n    print(\"Standardizing column names...\")\n    train_df = train_df.copy()\n    test_df = test_df.copy()\n    \n    # Rename columns để tránh conflict\n    if 'SPECIAL DIV' in train_df.columns and 'SPECIAL_DIV' in train_df.columns:\n        print(\"Found both 'SPECIAL DIV' and 'SPECIAL_DIV' - renaming...\")\n        train_df = train_df.rename(columns={'SPECIAL DIV': 'SPECIAL_DIV_SPACE'})\n    \n    if 'SPECIAL DIV' in test_df.columns and 'SPECIAL_DIV' in test_df.columns:\n        test_df = test_df.rename(columns={'SPECIAL DIV': 'SPECIAL_DIV_SPACE'})\n    \n    # Lấy các cột chung giữa train và test (trừ label)\n    train_cols = set(train_df.columns) - {'label'}\n    test_cols = set(test_df.columns) - {'ID'}\n    common_cols = list(train_cols.intersection(test_cols))\n    \n    print(f\"Common features: {len(common_cols)}\")\n    \n    # Chỉ giữ lại các cột chung\n    X_train = train_df[common_cols].copy()\n    y_train = train_df['label'].copy()\n    X_test = test_df[common_cols].copy()\n    \n    # Kiểm tra duplicate columns\n    print(\"Checking for duplicate columns...\")\n    duplicate_cols = X_train.columns[X_train.columns.duplicated()].tolist()\n    if duplicate_cols:\n        print(f\"Found duplicate columns: {duplicate_cols}\")\n        X_train = X_train.loc[:, ~X_train.columns.duplicated()]\n        X_test = X_test.loc[:, ~X_test.columns.duplicated()]\n        print(f\"After removing duplicates - Train: {X_train.shape}, Test: {X_test.shape}\")\n    \n    return X_train, y_train, X_test\n\n# Preprocess data\nX_train_raw, y_train, X_test_raw = preprocess_data(train_df, test_df)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-01T07:22:04.924335Z","iopub.execute_input":"2025-07-01T07:22:04.924611Z","iopub.status.idle":"2025-07-01T07:22:07.631346Z","shell.execute_reply.started":"2025-07-01T07:22:04.924591Z","shell.execute_reply":"2025-07-01T07:22:07.630650Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def feature_engineering(X_train, X_test):\n    \"\"\"Feature engineering\"\"\"\n    print(\"Feature engineering...\")\n    \n    # Xử lý datetime columns\n    datetime_cols = []\n    for col in X_train.columns:\n        if 'date' in col.lower() or 'time' in col.lower():\n            datetime_cols.append(col)\n    \n    print(f\"Datetime columns: {datetime_cols}\")\n    \n    # Convert datetime và extract features\n    for col in datetime_cols:\n        if col in X_train.columns:\n            try:\n                # Convert to datetime\n                X_train[col] = pd.to_datetime(X_train[col], errors='coerce')\n                X_test[col] = pd.to_datetime(X_test[col], errors='coerce')\n                \n                # Extract features\n                X_train[f'{col}_year'] = X_train[col].dt.year\n                X_train[f'{col}_month'] = X_train[col].dt.month\n                X_train[f'{col}_day'] = X_train[col].dt.day\n                X_train[f'{col}_dayofweek'] = X_train[col].dt.dayofweek\n                \n                X_test[f'{col}_year'] = X_test[col].dt.year\n                X_test[f'{col}_month'] = X_test[col].dt.month\n                X_test[f'{col}_day'] = X_test[col].dt.day\n                X_test[f'{col}_dayofweek'] = X_test[col].dt.dayofweek\n                \n                # Drop original datetime column\n                X_train = X_train.drop(col, axis=1)\n                X_test = X_test.drop(col, axis=1)\n                \n            except Exception as e:\n                print(f\"Error processing {col}: {e}\")\n    \n    # Xử lý categorical columns\n    categorical_cols = []\n    for col in X_train.columns:\n        if X_train[col].dtype == 'object':\n            categorical_cols.append(col)\n    \n    print(f\"Categorical columns: {len(categorical_cols)}\")\n    \n    # Label encoding cho categorical variables\n    label_encoders = {}\n    for col in categorical_cols:\n        le = LabelEncoder()\n        \n        # Combine train and test for consistent encoding\n        combined_values = pd.concat([X_train[col].astype(str), X_test[col].astype(str)])\n        le.fit(combined_values.fillna('missing'))\n        \n        X_train[col] = le.transform(X_train[col].astype(str).fillna('missing'))\n        X_test[col] = le.transform(X_test[col].astype(str).fillna('missing'))\n        \n        label_encoders[col] = le\n    \n    # Fill missing values cho numeric columns\n    for col in X_train.columns:\n        if X_train[col].dtype in ['int64', 'float64']:\n            median_val = X_train[col].median()\n            X_train[col] = X_train[col].fillna(median_val)\n            X_test[col] = X_test[col].fillna(median_val)\n    \n    print(f\"Final feature shape - Train: {X_train.shape}, Test: {X_test.shape}\")\n    \n    return X_train, X_test, label_encoders\n\n# Apply feature engineering\nX_train, X_test, label_encoders = feature_engineering(X_train_raw, X_test_raw)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-01T07:22:07.632522Z","iopub.execute_input":"2025-07-01T07:22:07.632769Z","iopub.status.idle":"2025-07-01T07:22:31.646978Z","shell.execute_reply.started":"2025-07-01T07:22:07.632752Z","shell.execute_reply":"2025-07-01T07:22:31.646226Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 4. Exploratory Data Analysis (EDA)","metadata":{}},{"cell_type":"code","source":"# Visualize label distribution\nplt.figure(figsize=(10, 6))\n\n# Subplot 1: Count plot\nplt.subplot(1, 2, 1)\nlabel_counts = y_train.value_counts()\nplt.bar(['Not Delay (0)', 'Delay (1)'], label_counts.values, color=['lightblue', 'salmon'])\nplt.title('Label Distribution (Count)')\nplt.ylabel('Count')\nfor i, v in enumerate(label_counts.values):\n    plt.text(i, v + 10000, f'{v:,}', ha='center', va='bottom')\n\n# Subplot 2: Percentage plot\nplt.subplot(1, 2, 2)\nplt.pie(label_counts.values, labels=['Not Delay (0)', 'Delay (1)'], \n        autopct='%1.1f%%', colors=['lightblue', 'salmon'])\nplt.title('Label Distribution (Percentage)')\n\nplt.tight_layout()\nplt.show()\n\nprint(f\"Class Imbalance Ratio: {label_counts[0]/label_counts[1]:.1f}:1\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-01T07:22:31.648229Z","iopub.execute_input":"2025-07-01T07:22:31.648470Z","iopub.status.idle":"2025-07-01T07:22:32.008301Z","shell.execute_reply.started":"2025-07-01T07:22:31.648453Z","shell.execute_reply":"2025-07-01T07:22:32.007549Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Feature correlation analysis\nprint(\"Feature Correlation Analysis:\")\nnumeric_features = X_train.select_dtypes(include=[np.number]).columns\nprint(f\"Numeric features: {len(numeric_features)}\")\n\nif len(numeric_features) > 1:\n    # Calculate correlation with target\n    correlations = []\n    for col in numeric_features:\n        corr = np.corrcoef(X_train[col], y_train)[0, 1]\n        if not np.isnan(corr):\n            correlations.append((col, abs(corr)))\n    \n    # Sort by correlation strength\n    correlations.sort(key=lambda x: x[1], reverse=True)\n    \n    print(\"\\nTop 10 features by correlation with target:\")\n    for i, (feature, corr) in enumerate(correlations[:10], 1):\n        print(f\"  {i:2d}. {feature}: {corr:.4f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-01T07:22:32.009149Z","iopub.execute_input":"2025-07-01T07:22:32.009413Z","iopub.status.idle":"2025-07-01T07:22:33.212693Z","shell.execute_reply.started":"2025-07-01T07:22:32.009395Z","shell.execute_reply":"2025-07-01T07:22:33.211840Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 5. Model Training với LightGBM","metadata":{}},{"cell_type":"code","source":"def train_lightgbm_model(X_train, y_train):\n    \"\"\"Training LightGBM model với cross-validation\"\"\"\n    print(\"Training LightGBM model...\")\n    \n    # LightGBM parameters\n    params = {\n        'objective': 'binary',\n        'metric': 'binary_logloss',\n        'boosting_type': 'gbdt',\n        'num_leaves': 31,\n        'learning_rate': 0.05,\n        'feature_fraction': 0.9,\n        'bagging_fraction': 0.8,\n        'bagging_freq': 5,\n        'verbose': -1,\n        'random_state': 42\n    }\n    \n    # Cross-validation với Macro F1-Score\n    skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)\n    \n    cv_scores = []\n    models = []\n    fold_results = []\n    \n    for fold, (train_idx, val_idx) in enumerate(skf.split(X_train, y_train)):\n        print(f\"\\nTraining fold {fold + 1}/5...\")\n        \n        X_fold_train, X_fold_val = X_train.iloc[train_idx], X_train.iloc[val_idx]\n        y_fold_train, y_fold_val = y_train.iloc[train_idx], y_train.iloc[val_idx]\n        \n        # Create LightGBM datasets\n        train_data = lgb.Dataset(X_fold_train, label=y_fold_train)\n        val_data = lgb.Dataset(X_fold_val, label=y_fold_val, reference=train_data)\n        \n        # Train model\n        model = lgb.train(\n            params,\n            train_data,\n            valid_sets=[val_data],\n            num_boost_round=1000,\n            callbacks=[lgb.early_stopping(100), lgb.log_evaluation(0)]\n        )\n        \n        # Predict và tính F1-score\n        val_pred = model.predict(X_fold_val)\n        val_pred_binary = (val_pred > 0.5).astype(int)\n        \n        f1_macro = f1_score(y_fold_val, val_pred_binary, average='macro')\n        cv_scores.append(f1_macro)\n        models.append(model)\n        \n        # Store fold results\n        fold_results.append({\n            'fold': fold + 1,\n            'f1_score': f1_macro,\n            'best_iteration': model.best_iteration\n        })\n        \n        print(f\"Fold {fold + 1} - F1-Score: {f1_macro:.4f}, Best iteration: {model.best_iteration}\")\n    \n    print(f\"\\nCross-Validation Results:\")\n    print(f\"  - Average CV Macro F1-Score: {np.mean(cv_scores):.4f} (±{np.std(cv_scores)*2:.4f})\")\n    print(f\"  - Best fold: {np.argmax(cv_scores)+1} (F1: {np.max(cv_scores):.4f})\")\n    print(f\"  - Worst fold: {np.argmin(cv_scores)+1} (F1: {np.min(cv_scores):.4f})\")\n    \n    return models, cv_scores, fold_results\n\n# Train model\nmodels, cv_scores, fold_results = train_lightgbm_model(X_train, y_train)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-01T07:22:33.214529Z","iopub.execute_input":"2025-07-01T07:22:33.214755Z","iopub.status.idle":"2025-07-01T07:25:00.391156Z","shell.execute_reply.started":"2025-07-01T07:22:33.214738Z","shell.execute_reply":"2025-07-01T07:25:00.390336Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Visualize CV results\nplt.figure(figsize=(12, 5))\n\n# Subplot 1: F1-scores by fold\nplt.subplot(1, 2, 1)\nfolds = [f\"Fold {i+1}\" for i in range(len(cv_scores))]\nplt.bar(folds, cv_scores, color='skyblue', alpha=0.7)\nplt.axhline(y=np.mean(cv_scores), color='red', linestyle='--', \n           label=f'Mean: {np.mean(cv_scores):.4f}')\nplt.title('F1-Score by Fold')\nplt.ylabel('Macro F1-Score')\nplt.legend()\nplt.xticks(rotation=45)\n\n# Add value labels on bars\nfor i, v in enumerate(cv_scores):\n    plt.text(i, v + 0.001, f'{v:.4f}', ha='center', va='bottom')\n\n# Subplot 2: Best iterations\nplt.subplot(1, 2, 2)\niterations = [result['best_iteration'] for result in fold_results]\nplt.bar(folds, iterations, color='lightcoral', alpha=0.7)\nplt.axhline(y=np.mean(iterations), color='blue', linestyle='--', \n           label=f'Mean: {np.mean(iterations):.0f}')\nplt.title('Best Iteration by Fold')\nplt.ylabel('Best Iteration')\nplt.legend()\nplt.xticks(rotation=45)\n\n# Add value labels on bars\nfor i, v in enumerate(iterations):\n    plt.text(i, v + 5, f'{v}', ha='center', va='bottom')\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-01T07:25:00.392067Z","iopub.execute_input":"2025-07-01T07:25:00.392337Z","iopub.status.idle":"2025-07-01T07:25:00.730491Z","shell.execute_reply.started":"2025-07-01T07:25:00.392316Z","shell.execute_reply":"2025-07-01T07:25:00.729687Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 6. Feature Importance Analysis","metadata":{}},{"cell_type":"code","source":"# Feature importance analysis\nprint(\"Feature Importance Analysis:\")\n\n# Calculate average feature importance across all folds\nfeature_importance = np.zeros(len(X_train.columns))\nfor model in models:\n    feature_importance += model.feature_importance(importance_type='gain')\n\nfeature_importance /= len(models)\n\n# Create feature importance dataframe\nfeature_importance_df = pd.DataFrame({\n    'feature': X_train.columns,\n    'importance': feature_importance\n}).sort_values('importance', ascending=False)\n\nprint(f\"\\nTop 15 Most Important Features:\")\nfor i, (_, row) in enumerate(feature_importance_df.head(15).iterrows(), 1):\n    print(f\"  {i:2d}. {row['feature']}: {row['importance']:.2f}\")\n\n# Plot feature importance\nplt.figure(figsize=(12, 8))\ntop_features = feature_importance_df.head(20)\nplt.barh(range(len(top_features)), top_features['importance'], color='lightgreen', alpha=0.7)\nplt.yticks(range(len(top_features)), top_features['feature'])\nplt.xlabel('Feature Importance (Gain)')\nplt.title('Top 20 Feature Importance')\nplt.gca().invert_yaxis()\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-01T07:25:00.731443Z","iopub.execute_input":"2025-07-01T07:25:00.731697Z","iopub.status.idle":"2025-07-01T07:25:01.022331Z","shell.execute_reply.started":"2025-07-01T07:25:00.731679Z","shell.execute_reply":"2025-07-01T07:25:01.021703Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 7. Model Predictions và Submission","metadata":{}},{"cell_type":"code","source":"def make_predictions(models, X_test, test_df):\n    \"\"\"Tạo predictions và file submission\"\"\"\n    print(\"Making predictions...\")\n    \n    # Average predictions từ tất cả models\n    predictions = np.zeros(len(X_test))\n    \n    for i, model in enumerate(models):\n        pred = model.predict(X_test)\n        predictions += pred\n        print(f\"Model {i+1}/5 predictions completed\")\n    \n    predictions /= len(models)\n    \n    # Convert to binary predictions\n    binary_predictions = (predictions > 0.5).astype(int)\n    \n    print(f\"\\nPrediction Statistics:\")\n    print(f\"- Probability mean: {predictions.mean():.4f}\")\n    print(f\"- Probability std: {predictions.std():.4f}\")\n    print(f\"- Probability min: {predictions.min():.4f}\")\n    print(f\"- Probability max: {predictions.max():.4f}\")\n    \n    # Tạo submission file\n    submission = pd.DataFrame({\n        'ID': test_df['ID'],\n        'label': binary_predictions\n    })\n    \n    submission.to_csv('submission.csv', index=False)\n    print(f\"\\nSubmission file saved as 'submission.csv'\")\n    print(f\"File shape: {submission.shape}\")\n    \n    pred_counts = pd.Series(binary_predictions).value_counts()\n    print(f\"\\nFinal Prediction Distribution:\")\n    print(f\"- Not delay (0): {pred_counts[0]:,} ({pred_counts[0]/len(binary_predictions)*100:.1f}%)\")\n    print(f\"- Delay (1): {pred_counts[1]:,} ({pred_counts[1]/len(binary_predictions)*100:.1f}%)\")\n    \n    return submission, predictions\n\n# Make predictions\nsubmission, prediction_probabilities = make_predictions(models, X_test, test_df)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-01T07:25:01.023083Z","iopub.execute_input":"2025-07-01T07:25:01.023277Z","iopub.status.idle":"2025-07-01T07:25:02.952066Z","shell.execute_reply.started":"2025-07-01T07:25:01.023254Z","shell.execute_reply":"2025-07-01T07:25:02.951268Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Visualize prediction results\nplt.figure(figsize=(15, 5))\n\n# Subplot 1: Prediction distribution\nplt.subplot(1, 3, 1)\npred_counts = submission['label'].value_counts()\nplt.bar(['Not Delay (0)', 'Delay (1)'], pred_counts.values, color=['lightblue', 'salmon'])\nplt.title('Prediction Distribution')\nplt.ylabel('Count')\nfor i, v in enumerate(pred_counts.values):\n    plt.text(i, v + 1000, f'{v:,}', ha='center', va='bottom')\n\n# Subplot 2: Prediction probabilities histogram\nplt.subplot(1, 3, 2)\nplt.hist(prediction_probabilities, bins=50, alpha=0.7, color='green')\nplt.axvline(x=0.5, color='red', linestyle='--', label='Threshold (0.5)')\nplt.xlabel('Prediction Probability')\nplt.ylabel('Frequency')\nplt.title('Prediction Probabilities Distribution')\nplt.legend()\n\n# Subplot 3: CV scores\nplt.subplot(1, 3, 3)\nfolds = [f\"Fold {i+1}\" for i in range(len(cv_scores))]\nplt.plot(folds, cv_scores, 'o-', color='purple', linewidth=2, markersize=8)\nplt.axhline(y=np.mean(cv_scores), color='red', linestyle='--', \n           label=f'Mean: {np.mean(cv_scores):.4f}')\nplt.title('Cross-Validation F1-Scores')\nplt.ylabel('Macro F1-Score')\nplt.legend()\nplt.xticks(rotation=45)\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-01T07:25:02.952852Z","iopub.execute_input":"2025-07-01T07:25:02.953041Z","iopub.status.idle":"2025-07-01T07:25:03.620693Z","shell.execute_reply.started":"2025-07-01T07:25:02.953019Z","shell.execute_reply":"2025-07-01T07:25:03.619983Z"}},"outputs":[],"execution_count":null}]}