{"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":"nvidiaTeslaT4","dataSources":[{"sourceType":"competition","sourceId":4120,"databundleVersionId":44256}],"dockerImageVersionId":31329,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# import os\n# import sys\n# import subprocess\n\n# # ==========================================\n# # 1. TẢI SOURCE CODE TỰ ĐỘNG\n# # ==========================================\n# repo_path = '/kaggle/working/CTR'\n# if not os.path.exists(repo_path):\n#     print(\"Đang tải mã nguồn từ Github...\")\n#     result = subprocess.run([\"git\", \"clone\", \"https://github.com/w4ngg/CTR.git\", repo_path], capture_output=True, text=True)\n#     if result.returncode != 0:\n#         raise Exception(\"❌ LỖI: Không tải được code. Hãy chắc chắn bạn đã bật Internet bên cột phải (Settings -> Internet: ON)\")\n#     print(\"✅ Tải mã nguồn thành công!\")\n\n# # Ép hệ thống chuyển thư mục làm việc vào trong thư mục CTR\n# os.chdir(repo_path)\n# sys.path.insert(0, repo_path)\n\n# # ==========================================\n# # 2. IMPORT THƯ VIỆN & MODEL\n# # ==========================================\n# import pandas as pd\n# import torch\n# import torch.nn as nn\n# import torch.optim as optim\n# from model import NAFI \n\n# # ==========================================\n# # 3. CẤU HÌNH CƠ BẢN\n# # ==========================================\n# DEVICE = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n# print(f\"✅ Đang chạy trên thiết bị: {DEVICE}\")\n\n# CHUNK_SIZE = 1_000_000  # Đọc 500k dòng mỗi lần\n# VOCAB_SIZE = 200_000  # Kích thước không gian Hash\n# BATCH_SIZE = 4096     # Kích thước đưa vào GPU mỗi lần\n\n# # Các cột phân loại của bộ Avazu\n# cat_features = ['C1', 'site_id', 'site_domain', 'site_category', \n#                 'app_id', 'app_domain', 'app_category', \n#                 'device_id', 'device_ip', 'device_model', 'device_type', \n#                 'device_conn_type', 'C14', 'C15', 'C16', 'C17', 'C18', 'C19', 'C20', 'C21']\n\n# # ==========================================\n# # 4. KHỞI TẠO MÔ HÌNH NAFI\n# # ==========================================\n# field_dims = [VOCAB_SIZE] * len(cat_features)\n# model = NAFI(field_dims=field_dims, embed_dim=16).to(DEVICE)\n# optimizer = optim.Adam(model.parameters(), lr=0.001)\n# criterion = nn.BCELoss()\n\n# # ==========================================\n# # 5. QUÁ TRÌNH TRAINING CHỐNG TRÀN RAM\n# # ==========================================\n# epochs = 1\n# csv_path = '/kaggle/input/competitions/avazu-ctr-prediction/train.gz'\n\n\n# if not os.path.exists(csv_path):\n#     raise Exception(f\"❌ LỖI: Không tìm thấy file {csv_path}. Bạn đã Add Data 'avazu-ctr-prediction' chưa?\")\n\n# print(\"🔥 Bắt đầu huấn luyện...\")\n# for epoch in range(epochs):\n#     chunk_iterator = pd.read_csv(csv_path, chunksize=CHUNK_SIZE)\n    \n#     for batch_idx, chunk in enumerate(chunk_iterator):\n        \n#         # --- ÁP DỤNG HASHING TRICK ---\n#         for col in cat_features:\n#             chunk[col] = chunk[col].astype(str).apply(lambda x: hash(x) % VOCAB_SIZE)\n        \n#         # Chuyển đổi thành PyTorch Tensor\n#         X_chunk = torch.tensor(chunk[cat_features].values, dtype=torch.long)\n#         y_chunk = torch.tensor(chunk['click'].values, dtype=torch.float32).unsqueeze(1)\n        \n#         # Tạo mini-batch (DataLoader)\n#         dataset = torch.utils.data.TensorDataset(X_chunk, y_chunk)\n#         loader = torch.utils.data.DataLoader(dataset, batch_size=BATCH_SIZE, shuffle=True)\n        \n#         # --- TRAINING TRÊN GPU ---\n#         model.train()\n#         total_loss = 0\n        \n#         for X_batch, y_batch in loader:\n#             X_batch, y_batch = X_batch.to(DEVICE), y_batch.to(DEVICE)\n            \n#             optimizer.zero_grad()\n#             outputs = model(X_batch)\n#             loss = criterion(outputs, y_batch)\n#             loss.backward()\n#             optimizer.step()\n            \n#             total_loss += loss.item()\n            \n#         print(f\"Epoch {epoch+1} | Chunk {batch_idx+1} (Đã train {(batch_idx+1)*CHUNK_SIZE:,} dòng) | Loss trung bình: {total_loss/len(loader):.4f}\")\n        \n#         # Giải phóng RAM ngay lập tức để đón chunk tiếp theo\n#         del chunk, X_chunk, y_chunk, dataset, loader\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport subprocess\n\nrepo_path = '/kaggle/working/CTR'\nif not os.path.exists(repo_path):\n    print(\"Đang tải mã nguồn từ Github...\")\n    subprocess.run([\"git\", \"clone\", \"https://github.com/w4ngg/CTR.git\", repo_path])\n    \nprint(\"✅ Tải mã nguồn thành công! Sẵn sàng.\")\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!python /kaggle/working/CTR/test_shape.py\n!python /kaggle/working/CTR/kaggle_test_nafi.py\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport sys\nimport pandas as pd\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nimport hashlib # Thêm thư viện băm dữ liệu chống trùng lặp\nfrom sklearn.metrics import roc_auc_score, log_loss\n\n# 1. Trỏ đường dẫn tới thư mục code\nrepo_path = '/kaggle/working/CTR'\nos.chdir(repo_path)\nsys.path.insert(0, repo_path)\n\nfrom model import NAFI \n\n# 2. Cấu hình phần cứng và tham số\nDEVICE = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nprint(f\"🚀 Đang chạy trên: {DEVICE}\")\n\nCHUNK_SIZE = 2_000_000  # Cắt 1 triệu dòng mỗi mẻ\nVOCAB_SIZE = 1_000_000  # ĐÃ TĂNG LÊN 3 TRIỆU ĐỂ TRÁNH ĐỤNG ĐỘ DATA\nBATCH_SIZE = 4096       # Kích thước đưa vào GPU\n\ncat_features = ['C1', 'site_id', 'site_domain', 'site_category', \n                'app_id', 'app_domain', 'app_category', \n                'device_id', 'device_ip', 'device_model', 'device_type', \n                'device_conn_type', 'C14', 'C15', 'C16', 'C17', 'C18', 'C19', 'C20', 'C21']\n\n# 3. Khởi tạo Mô hình\nfield_dims = [VOCAB_SIZE] * len(cat_features)\nmodel = NAFI(field_dims=field_dims, embed_dim=16).to(DEVICE)\noptimizer = optim.Adam(model.parameters(), lr=0.001)\ncriterion = nn.BCELoss()\n\n# 4. TRAINING VÀ VALIDATION TRÊN BIG DATA\nepochs = 3\ncsv_path = '/kaggle/input/competitions/avazu-ctr-prediction/train.gz'\n\nprint(\"🔥 Bắt đầu Pipeline Huấn luyện...\")\nfor epoch in range(epochs):\n    chunk_iterator = pd.read_csv(csv_path, chunksize=CHUNK_SIZE)\n    \n    val_y_true, val_y_pred = [], []\n    \n    for batch_idx, chunk in enumerate(chunk_iterator):\n        \n        # SỬ DỤNG HASHLIB THAY CHO HASH THƯỜNG\n        for col in cat_features:\n            chunk[col] = chunk[col].astype(str).apply(\n                lambda x: int(hashlib.md5(f\"{col}_{x}\".encode('utf-8')).hexdigest(), 16) % VOCAB_SIZE\n            )\n            \n        X_chunk = torch.tensor(chunk[cat_features].values, dtype=torch.long)\n        y_chunk = torch.tensor(chunk['click'].values, dtype=torch.float32).unsqueeze(1)\n        \n        dataset = torch.utils.data.TensorDataset(X_chunk, y_chunk)\n        loader = torch.utils.data.DataLoader(dataset, batch_size=BATCH_SIZE, shuffle=True)\n        \n        # LOGIC CHIA DATA: 35 chunk đầu làm Train, còn lại làm Test\n        if batch_idx < 35:\n            model.train()\n            total_loss = 0\n            for X_batch, y_batch in loader:\n                X_batch, y_batch = X_batch.to(DEVICE), y_batch.to(DEVICE)\n                optimizer.zero_grad()\n                loss = criterion(model(X_batch), y_batch)\n                loss.backward()\n                optimizer.step()\n                total_loss += loss.item()\n            print(f\"Epoch {epoch+1} | TRAIN Chunk {batch_idx+1:02d}/41 | Loss trung bình: {total_loss/len(loader):.4f}\")\n            \n        else:\n            model.eval()\n            with torch.no_grad():\n                for X_batch, y_batch in loader:\n                    X_batch = X_batch.to(DEVICE)\n                    preds = model(X_batch)\n                    val_y_true.extend(y_batch.numpy().flatten())\n                    val_y_pred.extend(preds.cpu().numpy().flatten())\n            print(f\"Epoch {epoch+1} | VAL Chunk {batch_idx+1:02d}/41 | (Đang thu thập kết quả Test...)\")\n\n        del chunk, X_chunk, y_chunk, dataset, loader\n\n    # TÍNH TOÁN ĐIỂM SỐ KHI KẾT THÚC EPOCH\n    if len(val_y_true) > 0:\n        auc_score = roc_auc_score(val_y_true, val_y_pred)\n        logloss_score = log_loss(val_y_true, val_y_pred) \n        print(\"\\n\" + \"=\"*60)\n        print(\"🏆 KẾT QUẢ ĐÁNH GIÁ MÔ HÌNH (Bỏ vào Báo cáo Đồ án):\")\n        print(f\"   - Chỉ số AUC:     {auc_score:.4f} (Lớn hơn 0.72 là xuất sắc)\")\n        print(f\"   - Chỉ số LogLoss: {logloss_score:.4f} (Dưới 0.45 là xuất sắc)\")\n        print(\"=\"*60 + \"\\n\")\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ==========================================\n# CELL 4: DỰ ĐOÁN TẬP TEST & TẠO FILE SUBMISSION KAGGLE\n# ==========================================\nimport gc \nimport hashlib # Đừng quên thêm dòng này ở đây\n\ntest_path = '/kaggle/input/competitions/avazu-ctr-prediction/test.gz'\nsubmission_path = '/kaggle/working/submission.csv'\n\nprint(\"🚀 Đang chạy dự đoán trên tập Test để nộp bài...\")\n\nwith open(submission_path, 'w') as f:\n    f.write('id,click\\n')\n\nmodel.eval()\n\n# Ép kiểu 'id': str để không bị lỗi nộp Kaggle\ntest_iterator = pd.read_csv(test_path, chunksize=CHUNK_SIZE, dtype={'id': str})\n\nwith torch.no_grad(): \n    for batch_idx, chunk in enumerate(test_iterator):\n        \n        # Áp dụng Hashlib y hệt như lúc Train\n        for col in cat_features:\n            chunk[col] = chunk[col].astype(str).apply(\n                lambda x: int(hashlib.md5(f\"{col}_{x}\".encode('utf-8')).hexdigest(), 16) % VOCAB_SIZE\n            )\n        \n        X_chunk = torch.tensor(chunk[cat_features].values, dtype=torch.long)\n        \n        dataset = torch.utils.data.TensorDataset(X_chunk)\n        loader = torch.utils.data.DataLoader(dataset, batch_size=BATCH_SIZE, shuffle=False)\n        \n        chunk_preds = []\n        for X_batch in loader:\n            X_batch = X_batch[0].to(DEVICE)\n            preds = model(X_batch).cpu().numpy().flatten()\n            chunk_preds.extend(preds)\n        \n        sub_chunk = pd.DataFrame({'id': chunk['id'], 'click': chunk_preds})\n        sub_chunk.to_csv(submission_path, mode='a', header=False, index=False)\n        \n        print(f\" Đã dự đoán và lưu xong Test Chunk {batch_idx+1}\")\n        \n        del chunk, X_chunk, dataset, loader, chunk_preds, sub_chunk\n        torch.cuda.empty_cache()\n        gc.collect()\n\nprint(\"=\"*60)\nprint(f\"✅ HOÀN TẤT! File nộp bài chuẩn 100% đã được tạo ra. Bạn hãy đem submit nhé!\")\nprint(\"=\"*60)\n","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}