{"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":"nvidiaTeslaT4","dataSources":[{"sourceId":4120,"databundleVersionId":44256,"sourceType":"competition"}],"dockerImageVersionId":30733,"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","execution":{"iopub.status.busy":"2024-06-09T09:05:12.306132Z","iopub.execute_input":"2024-06-09T09:05:12.306852Z","iopub.status.idle":"2024-06-09T09:05:12.726371Z","shell.execute_reply.started":"2024-06-09T09:05:12.306816Z","shell.execute_reply":"2024-06-09T09:05:12.725304Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# unzip input data","metadata":{}},{"cell_type":"markdown","source":"import gzip\nimport shutil\n\n# define input and output path \ninput_file_path = [\n    '/kaggle/input/avazu-ctr-prediction/sampleSubmission.gz',\n    '/kaggle/input/avazu-ctr-prediction/train.gz',\n    '/kaggle/input/avazu-ctr-prediction/test.gz'\n]\n\noutput_file_path = [\n    '/kaggle/working/sampleSubmission.csv',\n    '/kaggle/working/train.csv',\n    '/kaggle/working/test.csv'\n]\n\n# unzip\nfor i in range(len(input_file_path)):\n    with gzip.open(input_file_path[i], 'rb') as f_in:\n        with open(output_file_path[i], 'wb') as f_out:\n            shutil.copyfileobj(f_in, f_out)","metadata":{"execution":{"iopub.status.busy":"2024-06-08T19:45:39.454775Z","iopub.execute_input":"2024-06-08T19:45:39.455166Z","iopub.status.idle":"2024-06-08T19:46:24.533924Z","shell.execute_reply.started":"2024-06-08T19:45:39.455141Z","shell.execute_reply":"2024-06-08T19:46:24.532717Z"}}},{"cell_type":"code","source":"# 读取解压缩后的文件\nfile_path_train = '/kaggle/working/train.csv'\nfile_path_test = '/kaggle/working/test.csv'\n# file_path_train = '/kaggle/working/preprocessed_sampled_train.csv'\n\n\n# decrease variable precision to put all data into RAM\ndtype = {\n    'id' : 'uint32',\n    'click' : 'int16',\n    'hour' : 'int32',\n    'C1' : 'int16',\n    'banner_pos' : 'int16',\n    'device_type' : 'int16',\n    'device_conn_type' : 'int16',\n    'C14' : 'int16',\n    'C15' : 'int16',\n    'C16' : 'int16',\n    'C17' : 'int16',\n    'C18' : 'int16',\n    'C19' : 'int16',\n    'C20' : 'int32',\n    'C21' : 'int16',\n}\n\ntrain = pd.read_csv(file_path_train, dtype = dtype)\n# test = pd.read_csv(file_path_test, dtype = dtype)\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# data analysis","metadata":{}},{"cell_type":"markdown","source":"import pandas as pd\nimport matplotlib.pyplot as plt\n\n# check data content\nprint(train.info())\nprint(train.isnull().any())\nprint(train.describe())\n\n# check each variable frequency\nvariable = 'hour'\nprint(len(train[variable].unique()))\nprint(train[variable].value_counts(normalize=True).head(100))\nprint(train[variable].info())\nprint(0.000368*len(train[variable]))\n# threshold = 0.001\n# print((train[variable].value_counts(normalize=True)>threshold).sum())\n\n# bar plot for Discrete variable\nvariable = 'banner_pos'\nplt.figure(figsize=(10, 6))\n# train[variable].value_counts(normalize=True).head(variable_top_dim[variable]).plot(kind='bar')\ntrain[variable].value_counts(normalize=True).plot(kind='bar')\nplt.title(f'Distribution of {variable}')\nplt.xlabel(variable)\nplt.ylabel('precentage')\nplt.show()\nprint(train[variable].value_counts(normalize=True).head(variable_top_dim[variable]))\n\n#hist plot for continuous variable\nvariable = 'banner_pos'\nplt.figure(figsize=(10, 6))\nplt.hist(train[variable], bins=30, edgecolor='k', alpha = 0.7)\nplt.title(f'Distribution of {variable}')\nplt.xlabel(variable)\nplt.ylabel('Frequency')\nplt.show()\nprint(train[variable].describe())\n\n","metadata":{"execution":{"iopub.status.busy":"2024-06-08T16:52:28.906563Z","iopub.execute_input":"2024-06-08T16:52:28.907265Z","iopub.status.idle":"2024-06-08T16:52:29.827947Z","shell.execute_reply.started":"2024-06-08T16:52:28.907234Z","shell.execute_reply":"2024-06-08T16:52:29.826943Z"}}},{"cell_type":"markdown","source":"# Preprocess(train)","metadata":{}},{"cell_type":"code","source":"from sklearn.model_selection import StratifiedShuffleSplit\nfrom tqdm import tqdm\n# preprocess include\n# 1.hour data('YYMMDDHH') will transform to day(0-6) and hour(0-23).\n# 2.Encode discrtet features to one hot based on it's frequency.\n# 3.Sample 1000000 data from original training set,sample data equally from each hours, and keep same click ratio)\n\n# Dict[str : int] : variable_to_dim describe each discrtet variable dimension(site_id -> 21)\nvariable_to_dim = {\n    'banner_pos' : 3,\n    'site_id' : 22,\n    'site_domain' : 25,\n    'site_category' : 10,\n    'app_id' : 19,\n    'app_domain' : 10,\n    'app_category' : 9,\n    'device_id' : 2,\n    'device_model': 15,\n    'device_type' : 5,\n    'device_conn_type': 4,\n    'C15' : 8,\n    'C16' : 9,\n    'C1' : 7,\n    'C18' : 4,\n}\n# build Dict[str, Dict[str : int]] describe each variable map to it's encoder (site_id -> $34234das3 -> 1)\nvariable_encode_map = {}\nfor var in variable_to_dim.keys():\n    variable_encode_map[var] = {}\n    top_n_var = train[var].value_counts().nlargest(variable_to_dim[var] - 1)\n    for i, nth_var in enumerate(top_n_var.index):\n        variable_encode_map[var][str(nth_var)] = i\n# filepath = '/kaggle/working/variable_encode_map.pkl'\n# with open(filepath, 'wb') as f:\n#     pickle.dump(variable_encode_map, f)\n\nprint('-----transform hour to date-----')\n# transform hour data('YYMMDDHH') to day(0-6) and hour(0-23).\ntrain['hour_str'] = train['hour'].astype(str)\ntrain['MMDD'] = train['hour_str'].str[2:6]\ntrain['day'] = (train['MMDD'].astype(int) - 1021) % 7 + 1\ntrain['hour'] = train['hour_str'].str[6:8].astype(int)\ntrain = train.drop(columns=['hour_str', 'MMDD'])\n\nprint('-----feature encode-----')\n# feature encode(if not in map, group then together)\nfor var in tqdm(variable_to_dim.keys()):\n    train[var] = train[var].astype(str).map(variable_encode_map[var]).fillna(variable_to_dim[var]-1)\n\nprint(train['hour'].value_counts())\nprint(train['click'].value_counts(normalize=True))\n\n# sample data to sample_train\ntrain_number = 1200000\nsampled_train = pd.DataFrame()\n\nprint('-----sample train-----')\n# 對每個'hour'值分別進行採樣\nfor hour_value in tqdm(train['hour'].unique()):\n    subset = train[train['hour'] == hour_value]\n    X = subset[['hour']]\n    y = subset['click']\n    \n    sss = StratifiedShuffleSplit(n_splits=1, test_size = train_number//len(train['hour'].unique()), random_state=42)\n    \n    for _, test_index in sss.split(X, y):\n        stratified_sample = subset.iloc[test_index]\n        sampled_train = pd.concat([sampled_train, stratified_sample])\n\nprint('---after---')\nprint(sampled_train['hour'].value_counts())\nprint(sampled_train['click'].value_counts(normalize=True))\n\nsampled_train.to_csv('/kaggle/working/preprocessed_sampled_train.csv', index=False)\n\n# # transform hour data('YYMMDDHH') to day(0-6) and hour(0-23).\n# test['hour_str'] = test['hour'].astype(str)\n# test['MMDD'] = test['hour_str'].str[2:6]\n# test['day'] = (test['MMDD'].astype(int) - 1021) % 7 + 1\n# test['hour'] = test['hour_str'].str[6:8].astype(int)\n# test = test.drop(columns=['hour_str', 'MMDD'])\n\n# # feature encode(if not in map, group then together)\n# for var in tqdm(variable_to_dim.keys()):\n#     test[var] = test[var].astype(str).map(variable_encode_map[var]).fillna(variable_to_dim[var]-1)\n\n# test.to_csv('/kaggle/working/preprocessed_test.csv',index=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"n_samples_per_hour = 200000 // 24\n\n# 存储采样后的 DataFrame\nsampled_dfs = []\n\nfor hour in range(24):\n    hour_df = sampled_train[sampled_train['hour'] == hour]\n    \n    # 根据 click 列的分布按比例采样\n    click_0_df = hour_df[hour_df['click'] == 0]\n    click_1_df = hour_df[hour_df['click'] == 1]\n    \n    n_click_0 = int((len(click_0_df) / len(hour_df)) * n_samples_per_hour)\n    n_click_1 = n_samples_per_hour - n_click_0\n    \n    sampled_click_0 = click_0_df.sample(n=n_click_0)\n    sampled_click_1 = click_1_df.sample(n=n_click_1)\n    \n    sampled_dfs.append(pd.concat([sampled_click_0, sampled_click_1]))\n\n# 合并所有采样的数据\ns_df = pd.concat(sampled_dfs)\n\n# 从 original_df 中删除采样后的数据\nsampled_train = sampled_train.drop(s_df.index)\n\n# 打印结果以检查\nprint(f\"Sampled DataFrame Shape: {s_df.shape}\")\nprint(f\"Original DataFrame Shape after sampling: {sampled_train.shape}\")\n\n# 检查每个小时的样本数量是否均匀\nprint(s_df['hour'].value_counts())\nprint(s_df['click'].value_counts(normalize=True))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Pytorch Imports\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nimport torch.nn.functional as F\nfrom torch.optim import lr_scheduler\nfrom torch.utils.data import Dataset, DataLoader\nfrom torch.cuda import amp\n# from pytorch_toolbelt import losses as L\n\n# Utils\nfrom tqdm import tqdm\nfrom sklearn.metrics import accuracy_score\nfrom sklearn.metrics import recall_score\nfrom sklearn.metrics import balanced_accuracy_score","metadata":{"execution":{"iopub.status.busy":"2024-06-09T09:06:34.31683Z","iopub.execute_input":"2024-06-09T09:06:34.317798Z","iopub.status.idle":"2024-06-09T09:06:34.806401Z","shell.execute_reply.started":"2024-06-09T09:06:34.317749Z","shell.execute_reply":"2024-06-09T09:06:34.805359Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# CFG ","metadata":{}},{"cell_type":"code","source":"import pickle\n\n# load csv dtype \ndtype = {\n    'id' : 'uint32',\n    'click' : 'int16',\n    'hour' : 'int32',\n    'C1' : 'int16',\n    'banner_pos' : 'int16',\n    'device_type' : 'int16',\n    'device_conn_type' : 'int16',\n    'C14' : 'int16',\n    'C15' : 'int16',\n    'C16' : 'int16',\n    'C17' : 'int16',\n    'C18' : 'int16',\n    'C19' : 'int16',\n    'C20' : 'int32',\n    'C21' : 'int16',\n}\n\n# load pickle file\nfilepath = '/kaggle/working/continuous_variable_min_max.pkl'\nwith open(filepath, 'rb') as f:\n    cont_var_min_max = pickle.load(f)\n    \n# numbers of categorical features node\nvariable_to_dim = {\n    'banner_pos' : 3,\n    'site_id' : 22,\n    'site_domain' : 25,\n    'site_category' : 10,\n    'app_id' : 19,\n    'app_domain' : 10,\n    'app_category' : 9,\n    'device_id' : 2,\n    'device_model': 15,\n    'device_type' : 5,\n    'device_conn_type': 4,\n    'C15' : 8,\n    'C16' : 9,\n    'C1' : 7,\n    'C18' : 4,\n}\n\n#continuous features\ncontinuous_variable = [\n    'C14',\n    'C17',\n    'C19',\n    'C20',\n    'C21',\n    'hour',\n    'day'\n]\n# training setting   \nCFG = {\n    'epoch': 10,    \n    'batch_size': 1024,\n    'gradient_accumulation': 1,\n    'lr': 1e-4,\n    'weight_decay': 0,\n    'load_model':'',\n    'save_model': '/kaggle/working'\n}\n    \n\n","metadata":{"execution":{"iopub.status.busy":"2024-06-09T13:15:26.853524Z","iopub.execute_input":"2024-06-09T13:15:26.854232Z","iopub.status.idle":"2024-06-09T13:15:26.863399Z","shell.execute_reply.started":"2024-06-09T13:15:26.854189Z","shell.execute_reply":"2024-06-09T13:15:26.862442Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# model","metadata":{}},{"cell_type":"code","source":"class CTRPredictor(nn.Module):\n    def __init__(self, variable_to_dim, continuous_variable):\n        super(CTRPredictor, self).__init__()\n\n        # Embedding layers for one-hot encoded categorical variables\n        self.embeddings = nn.ModuleDict({\n            var: nn.Embedding(dim, 16) for var, dim in variable_to_dim.items()\n        })\n\n        # Calculate the input dimension after concatenating embeddings and continuous variables\n        self.input_dim = 16 * len(variable_to_dim) + len(continuous_variable)\n\n        # Hidden layers\n        self.fc1 = nn.Linear(self.input_dim, 512)\n        self.bn1 = nn.BatchNorm1d(512)\n\n        self.fc2 = nn.Linear(512, 128)\n        self.bn2 = nn.BatchNorm1d(128)\n\n        self.fc3 = nn.Linear(128, 16)\n        self.bn3 = nn.BatchNorm1d(16)\n\n        # Output layer\n        self.output = nn.Linear(16, 1)\n        \n    def forward(self, x_cat, x_cont):\n        # Apply embeddings and concatenate\n        x = [self.embeddings[var](x_cat[:, i]) for i, var in enumerate(self.embeddings)]\n        x = torch.cat(x, dim=1)\n\n        # Concatenate continuous variables\n        x = torch.cat([x, x_cont], dim=1)\n\n        # Forward pass through hidden layers with batch normalization\n        x = torch.sigmoid(self.fc1(x))\n        x = self.bn1(x)\n\n        x = torch.sigmoid(self.fc2(x))\n        x = self.bn2(x)\n\n        x = torch.sigmoid(self.fc3(x))\n        x = self.bn3(x)\n\n        # Output layer with sigmoid activation\n        x = self.output(x)\n        return x","metadata":{"execution":{"iopub.status.busy":"2024-06-09T09:14:17.612048Z","iopub.execute_input":"2024-06-09T09:14:17.612968Z","iopub.status.idle":"2024-06-09T09:14:17.623933Z","shell.execute_reply.started":"2024-06-09T09:14:17.612933Z","shell.execute_reply":"2024-06-09T09:14:17.622959Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# dataset","metadata":{}},{"cell_type":"code","source":"class CTRDataset(Dataset):\n    def __init__(self, df, variable_to_dim, continuous_variable, cont_var_min_max):\n        self.df = df\n        self.variable_to_dim = variable_to_dim\n        self.continuous_variable = continuous_variable\n        self.cont_var_min_max = cont_var_min_max\n\n        # Normalize continuous variables using provided min-max values\n        for var in continuous_variable:\n            min_val = cont_var_min_max[var]['min']\n            max_val = cont_var_min_max[var]['max']\n            if var == 'C20':\n                self.df[var] = self.df[var].apply(lambda x: -1 if x == -1 else (x - min_val) / (max_val - min_val))\n            else :\n                self.df[var] = (self.df[var] - min_val) / (max_val - min_val)\n                \n    def __len__(self):\n        return len(self.df)\n\n    def __getitem__(self, idx):\n        row = self.df.iloc[idx]\n        \n        # Extract categorical and continuous features\n        x_cat = torch.tensor([row[var] for var in self.variable_to_dim.keys()], dtype=torch.long)\n        x_cont = torch.tensor([row[var] for var in self.continuous_variable], dtype=torch.float)\n\n        # Extract label\n        y = torch.tensor(row['click'], dtype=torch.float)\n        \n        return x_cat, x_cont, y\n ","metadata":{"execution":{"iopub.status.busy":"2024-06-09T09:05:46.943767Z","iopub.execute_input":"2024-06-09T09:05:46.944128Z","iopub.status.idle":"2024-06-09T09:05:46.954448Z","shell.execute_reply.started":"2024-06-09T09:05:46.944102Z","shell.execute_reply":"2024-06-09T09:05:46.953607Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# train","metadata":{}},{"cell_type":"code","source":"def train_epoch(dataloader, model, criterion, optimizer):\n    scaler= amp.GradScaler()\n    model.train()\n\n    ep_loss_bce = []\n    for data in tqdm(dataloader):\n        x_cat, x_cont, y = data\n        x_cat = x_cat.to('cuda')\n        x_cont = x_cont.to('cuda')\n        y = y.to('cuda')\n        \n        with amp.autocast():\n            output = model(x_cat, x_cont)\n            loss_bce = criterion(output, y.unsqueeze(1))\n            ep_loss_bce.append(loss_bce.item())\n            scaler.scale(loss_bce).backward()\n            scaler.step(optimizer)\n            scaler.update()\n            \n    return np.mean(ep_loss_bce)","metadata":{"execution":{"iopub.status.busy":"2024-06-09T09:14:11.249378Z","iopub.execute_input":"2024-06-09T09:14:11.249785Z","iopub.status.idle":"2024-06-09T09:14:11.256994Z","shell.execute_reply.started":"2024-06-09T09:14:11.249756Z","shell.execute_reply":"2024-06-09T09:14:11.256002Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# eval","metadata":{}},{"cell_type":"code","source":"def valid_epoch(valid_loader, model, criterion):\n    model.eval()\n    ep_valid_loss_bce, ep_acc = [], []\n    preds, labels = [], [] \n    with torch.no_grad():\n        for data in tqdm(valid_loader):\n            x_cat, x_cont, y = data\n            x_cat = x_cat.to('cuda')\n            x_cont = x_cont.to('cuda')\n            y = y.to('cuda')\n            output = model(x_cat, x_cont)\n            loss_bce = criterion(output, y.unsqueeze(1))\n            ep_valid_loss_bce.append(loss_bce.item())\n            \n            output = torch.sigmoid(output)\n            output = torch.where(output >= 0.5, 1, 0).cpu().numpy()\n            preds.extend(output)\n            labels.extend(y.cpu().numpy())\n            \n    ep_bacc = balanced_accuracy_score(labels, preds)    \n    ep_acc = accuracy_score(labels, preds)\n    return np.mean(ep_valid_loss_bce), ep_bacc, ep_acc","metadata":{"execution":{"iopub.status.busy":"2024-06-09T15:19:13.57669Z","iopub.execute_input":"2024-06-09T15:19:13.577051Z","iopub.status.idle":"2024-06-09T15:19:13.585518Z","shell.execute_reply.started":"2024-06-09T15:19:13.577019Z","shell.execute_reply":"2024-06-09T15:19:13.584508Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# train(all)","metadata":{}},{"cell_type":"code","source":"file_path_train = '/kaggle/working/preprocessed_sampled_train.csv'\nfile_path_valid = '/kaggle/working/preprocessed_sampled_validation.csv'\n\ntrain_df = pd.read_csv(file_path_train, dtype = dtype)\nvalid_df = pd.read_csv(file_path_valid, dtype = dtype)\nprint(f'train dataset: {len(train_df)}')\nprint(f'valid dataset: {len(valid_df)}')\n\ntrain_dataset = CTRDataset(train_df, variable_to_dim, continuous_variable, cont_var_min_max)\nvalid_dataset = CTRDataset(valid_df, variable_to_dim, continuous_variable, cont_var_min_max)\ntrain_loader = DataLoader(train_dataset, batch_size= CFG['batch_size'], shuffle=True)\nvalid_loader= DataLoader(valid_dataset, batch_size=CFG['batch_size'], shuffle=False)\n\n# create model\nmodel = CTRPredictor(variable_to_dim, continuous_variable).to('cuda')\n\n# lossfunction and optimizer\ncriterion = nn.BCEWithLogitsLoss()\noptimizer = optim.AdamW(model.parameters(), lr= CFG['lr'], weight_decay= CFG['weight_decay'])\n\n## start training\nbest_score= 0 \nfor ep in range(0, CFG['epoch']+1):\n    print(f'ep: {ep}')\n    train_loss_bce = train_epoch(train_loader, model, criterion, optimizer)\n    valid_loss_bce, valid_bacc, valid_acc = valid_epoch(valid_loader, model, criterion)\n    print(f'train loss bce: {train_loss_bce}')\n    print(f'valid loss bce: {valid_loss_bce}')\n    print(f'valid bacc: {valid_bacc}, valid acc:{valid_acc}')\n\n    if valid_bacc >= best_score:\n        best_score = valid_bacc\n        torch.save(model, f\"{CFG['save_model']}/ctr_mlp.pth\")\n        print(f'model save at score: {best_score}')\n\n#     ## save model every epoch\n#     torch.save(model, f\"{CFG['save_model']}/cv{CFG['fold']}_ep{ep}.pth\")","metadata":{"execution":{"iopub.status.busy":"2024-06-09T15:19:20.344219Z","iopub.execute_input":"2024-06-09T15:19:20.34506Z","iopub.status.idle":"2024-06-09T15:34:25.428054Z","shell.execute_reply.started":"2024-06-09T15:19:20.345025Z","shell.execute_reply":"2024-06-09T15:34:25.426097Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# valid_loss_bce, valid_bacc, valid_acc = valid_epoch(valid_loader, model, criterion)\n# valid_dataset = CTRDataset(valid_df, variable_to_dim, continuous_variable, cont_var_min_max)\nprint(model(valid_dataset[0][0].unsqueeze(0).to('cuda'),valid_dataset[0][1].unsqueeze(0).to(to('cuda'))))\n\n# valid_dataset[0][0].unsqueeze(0).shape","metadata":{"execution":{"iopub.status.busy":"2024-06-09T15:06:24.086207Z","iopub.execute_input":"2024-06-09T15:06:24.086568Z","iopub.status.idle":"2024-06-09T15:06:24.121794Z","shell.execute_reply.started":"2024-06-09T15:06:24.086539Z","shell.execute_reply":"2024-06-09T15:06:24.120575Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cnt = 0\nmodel.eval()\nfor i in range(10000):\n    x1 = valid_dataset[i][0].unsqueeze(0).to('cuda')\n    x2 = valid_dataset[i][1].unsqueeze(0).to('cuda')\n    y = \n    if torch.sigmoid(model(x1,x2))> 0.5:\n        cnt += 1\nprint(cnt)\n                                         ","metadata":{"execution":{"iopub.status.busy":"2024-06-09T15:11:22.850943Z","iopub.execute_input":"2024-06-09T15:11:22.851771Z","iopub.status.idle":"2024-06-09T15:11:41.393008Z","shell.execute_reply.started":"2024-06-09T15:11:22.851736Z","shell.execute_reply":"2024-06-09T15:11:41.392065Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"valid_df['click'].value_counts(normalize=True)","metadata":{"execution":{"iopub.status.busy":"2024-06-09T14:50:18.836081Z","iopub.execute_input":"2024-06-09T14:50:18.836496Z","iopub.status.idle":"2024-06-09T14:50:18.851218Z","shell.execute_reply.started":"2024-06-09T14:50:18.836465Z","shell.execute_reply":"2024-06-09T14:50:18.850335Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# inference","metadata":{}},{"cell_type":"code","source":"model= torch.load('/kaggle/working/ctr_mlp.pth', map_location= 'cuda')\ntest_df = pd.read_csv('/kaggle/working/preprocessed_test.csv',dtype = dtype)\nclass CTR_inference_Dataset(Dataset):\n    def __init__(self, df, variable_to_dim, continuous_variable, cont_var_min_max):\n        self.df = df\n        self.variable_to_dim = variable_to_dim\n        self.continuous_variable = continuous_variable\n        self.cont_var_min_max = cont_var_min_max\n\n        # Normalize continuous variables using provided min-max values\n        for var in continuous_variable:\n            min_val = cont_var_min_max[var]['min']\n            max_val = cont_var_min_max[var]['max']\n            if var == 'C20':\n                self.df[var] = self.df[var].apply(lambda x: -1 if x == -1 else (x - min_val) / (max_val - min_val))\n            else:\n                self.df[var] = (self.df[var] - min_val) / (max_val - min_val)\n\n    def __len__(self):\n        return len(self.df)\n\n    def __getitem__(self, idx):\n        row = self.df.iloc[idx]\n        \n        # Extract categorical and continuous features\n        x_cat = torch.tensor([row[var] for var in self.variable_to_dim.keys()], dtype=torch.long)\n        x_cont = torch.tensor([row[var] for var in self.continuous_variable], dtype=torch.float)\n\n        return row['id'].astype('int64'), x_cat, x_cont\n\ntest_dataset = CTR_inference_Dataset(test_df, variable_to_dim, continuous_variable, cont_var_min_max)\ntest_loader = DataLoader(test_dataset, batch_size=1024, shuffle=False)\n\nmodel.eval()\nresult = []\n\nwith torch.no_grad():\n    for data in test_loader:\n        ids, x_cat, x_cont = data\n        x_cat = x_cat.to('cuda')\n        x_cont = x_cont.to('cuda')\n        \n        # 模型预测\n        output = model(x_cat, x_cont)\n        probabilities = torch.sigmoid(output).cpu().numpy()\n        \n        # 组合 id 和预测结果\n        for id, prob in zip(ids, probabilities):\n            result.append({'id': id.item(), 'click': prob.item()})\n\n# 创建结果 DataFrame\nresult_df = pd.DataFrame(result)\n\n# 保存结果 DataFrame 到 CSV 文件\nresult_df.to_csv('submission.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2024-06-09T15:40:50.741861Z","iopub.execute_input":"2024-06-09T15:40:50.742547Z","iopub.status.idle":"2024-06-09T15:58:42.275439Z","shell.execute_reply.started":"2024-06-09T15:40:50.742514Z","shell.execute_reply":"2024-06-09T15:58:42.274555Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"result = pd.read_csv('/kaggle/working/submission.csv')\nresult.head()","metadata":{"execution":{"iopub.status.busy":"2024-06-09T15:59:45.761642Z","iopub.execute_input":"2024-06-09T15:59:45.762454Z","iopub.status.idle":"2024-06-09T15:59:47.302406Z","shell.execute_reply.started":"2024-06-09T15:59:45.76241Z","shell.execute_reply":"2024-06-09T15:59:47.301428Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ptint(typetest_df['id'])","metadata":{},"execution_count":null,"outputs":[]}]}