{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceType":"competition","sourceId":132373,"databundleVersionId":15871996}],"dockerImageVersionId":31287,"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":"2026-03-01T12:40:13.355856Z","iopub.execute_input":"2026-03-01T12:40:13.356202Z","iopub.status.idle":"2026-03-01T12:40:14.295620Z","shell.execute_reply.started":"2026-03-01T12:40:13.356167Z","shell.execute_reply":"2026-03-01T12:40:14.294830Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport os\nimport re\nfrom sklearn.model_selection import StratifiedKFold\nfrom sklearn.metrics import roc_auc_score\nfrom sklearn.preprocessing import LabelEncoder\nimport lightgbm as lgb\nimport warnings\nwarnings.filterwarnings('ignore')\n\n# Set data path based on Kaggle environment\nDATA_PATH = \"/kaggle/input/competitions/global-e-commerce-customer-purchase-prediction/\"\n\nprint(\"Loading data...\")\ntrain = pd.read_csv(os.path.join(DATA_PATH, \"train.csv\"))\ntest = pd.read_csv(os.path.join(DATA_PATH, \"test.csv\"))\nsample_sub = pd.read_csv(os.path.join(DATA_PATH, \"sample_submission.csv\"))\n\ncustomers = pd.read_csv(os.path.join(DATA_PATH, \"customers.csv\"))\nsessions = pd.read_csv(os.path.join(DATA_PATH, \"sessions.csv\"))\ntransactions = pd.read_csv(os.path.join(DATA_PATH, \"transactions.csv\"))\ngeo_data = pd.read_csv(os.path.join(DATA_PATH, \"geo_data.csv\"))\n# marketing_campaigns = pd.read_csv(os.path.join(DATA_PATH, \"marketing_campaigns.csv\"))\n\n# ==========================================\n# 1. CLEANING FUNCTIONS\n# ==========================================\nprint(\"Cleaning data...\")\ndef clean_currency(x):\n    if pd.isna(x): return np.nan\n    if isinstance(x, (int, float)): return x\n    # Remove everything except numbers and decimal points\n    return float(re.sub(r'[^\\d.]', '', str(x)))\n\n# Clean Customers\ncustomers['age'] = pd.to_numeric(customers['age'], errors='coerce')\ncustomers['credit_limit'] = customers['credit_limit'].apply(clean_currency)\ncustomers['country_code'] = customers['country_code'].astype(str).str.lower().str.strip()\ncustomers['customer_tier'] = customers['customer_tier'].astype(str).str.lower()\n\n# Clean Transactions\ntransactions['order_value'] = transactions['order_value'].apply(clean_currency)\ntransactions['items_count'] = pd.to_numeric(transactions['items_count'], errors='coerce')\n\n# Clean Sessions\nsessions['pages_viewed'] = pd.to_numeric(sessions['pages_viewed'], errors='coerce')\n\n# ==========================================\n# 2. FEATURE ENGINEERING & AGGREGATION\n# ==========================================\nprint(\"Aggregating Transaction Data...\")\ntxn_agg = transactions.groupby('customer_id').agg({\n    'order_value': ['sum', 'mean', 'max', 'count'],\n    'items_count': ['sum', 'mean']\n}).reset_index()\ntxn_agg.columns = ['customer_id', 'txn_total_value', 'txn_mean_value', 'txn_max_value', 'txn_count', 'txn_total_items', 'txn_mean_items']\n\nprint(\"Aggregating Session Data...\")\nsess_agg = sessions.groupby('customer_id').agg({\n    'session_duration': ['sum', 'mean', 'count'],\n    'pages_viewed': ['sum', 'mean'],\n    'cart_additions': ['sum', 'max']\n}).reset_index()\nsess_agg.columns = ['customer_id', 'sess_total_duration', 'sess_mean_duration', 'sess_count', \n                    'sess_total_pages', 'sess_mean_pages', 'sess_total_cart_additions', 'sess_max_cart_additions']\n\n# ==========================================\n# 3. MERGING ALL TABLES\n# ==========================================\nprint(\"Merging Datasets...\")\ndef merge_data(df):\n    df = df.merge(customers, on='customer_id', how='left')\n    df = df.merge(txn_agg, on='customer_id', how='left')\n    df = df.merge(sess_agg, on='customer_id', how='left')\n    df = df.merge(geo_data, left_on='region', right_on='geo_ip_region', how='left').drop(columns=['geo_ip_region'])\n    return df\n\ntrain_df = merge_data(train)\ntest_df = merge_data(test)\n\n# ==========================================\n# 4. PREPARING FOR MODELING\n# ==========================================\n# Drop unnecessary columns like IDs, dates, and target from features\ncols_to_drop = ['customer_id', 'target', 'signup_date', 'referral_code']\nfeatures = [c for c in train_df.columns if c not in cols_to_drop]\n\n# Encode Categorical Variables\ncategorical_features = train_df[features].select_dtypes(include=['object', 'category']).columns.tolist()\n\nfor col in categorical_features:\n    train_df[col] = train_df[col].astype(str).fillna('missing')\n    test_df[col] = test_df[col].astype(str).fillna('missing')\n    \n    le = LabelEncoder()\n    # Fit on combined data to ensure we catch all classes\n    le.fit(list(train_df[col]) + list(test_df[col]))\n    train_df[col] = le.transform(train_df[col])\n    test_df[col] = le.transform(test_df[col])\n\nX = train_df[features]\ny = train_df['target']\nX_test = test_df[features]\n\n# ==========================================\n# 5. MODEL TRAINING (LightGBM with K-Fold)\n# ==========================================\nprint(\"Training LightGBM Model...\")\nNFOLDS = 5\nfolds = StratifiedKFold(n_splits=NFOLDS, shuffle=True, random_state=42)\n\noof_preds = np.zeros(len(X))\ntest_preds = np.zeros(len(X_test))\n\n# LightGBM hyperparameters\nlgb_params = {\n    'objective': 'binary',\n    'metric': 'auc',\n    'learning_rate': 0.05,\n    'max_depth': 6,\n    'num_leaves': 31,\n    'feature_fraction': 0.8,\n    'n_estimators': 1500,\n    'random_state': 42,\n    'n_jobs': -1,\n    'verbose': -1\n}\n\nfor fold, (train_idx, valid_idx) in enumerate(folds.split(X, y)):\n    X_train, y_train = X.iloc[train_idx], y.iloc[train_idx]\n    X_valid, y_valid = X.iloc[valid_idx], y.iloc[valid_idx]\n    \n    model = lgb.LGBMClassifier(**lgb_params)\n    \n    model.fit(\n        X_train, y_train,\n        eval_set=[(X_valid, y_valid)],\n        categorical_feature=categorical_features,\n        callbacks=[lgb.early_stopping(stopping_rounds=100, verbose=False)]\n    )\n    \n    # Predict validation fold\n    val_preds = model.predict_proba(X_valid)[:, 1]\n    oof_preds[valid_idx] = val_preds\n    fold_auc = roc_auc_score(y_valid, val_preds)\n    print(f\"Fold {fold + 1} | AUC: {fold_auc:.4f}\")\n    \n    # Predict test data\n    test_preds += model.predict_proba(X_test)[:, 1] / NFOLDS\n\n# Print Overall Validation Score\ncv_auc = roc_auc_score(y, oof_preds)\nprint(f\"\\n✅ Overall Cross-Validation AUC: {cv_auc:.4f}\")\n\n# ==========================================\n# 6. SUBMISSION\n# ==========================================\nsub = test[['customer_id']].copy()\nsub['target'] = test_preds\nsub.to_csv(\"submission.csv\", index=False)\nprint(\"Submission saved as 'submission.csv'!\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-01T12:43:05.368539Z","iopub.execute_input":"2026-03-01T12:43:05.368906Z","iopub.status.idle":"2026-03-01T12:43:30.140764Z","shell.execute_reply.started":"2026-03-01T12:43:05.368877Z","shell.execute_reply":"2026-03-01T12:43:30.140084Z"}},"outputs":[],"execution_count":null}]}