{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"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\n# Input data files are available in the read-only \"../input/\" directory\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_count":null,"outputs":[]},{"cell_type":"markdown","source":"# pytorch-lifestream (ptls)\n\nThis is library for sequential data: https://github.com/dllllb/pytorch-lifestream\n\nData preprocessed with https://www.kaggle.com/code/ivkireev/amex-ptls-data-preprocessing\n","metadata":{}},{"cell_type":"code","source":"!pip uninstall tensorflow-transform tfx-bsl -y\n!pip install pyspark\n!pip install git+https://github.com/dllllb/pytorch-lifestream.git@main\n!pip install pyarrow==5.0.0  # comment it for cpu kernel","metadata":{"_kg_hide-output":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Read the data\n\nData was prepared in `ptls` format. This is parquet files where each row represent one data sample - one client. Features are the sequential fields with arrays of length `sequence_length`\n\nDemo of data usage is in https://www.kaggle.com/code/ivkireev/ptls-data-usage","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport torch\nimport pickle\n\nfrom sklearn.model_selection import train_test_split\nfrom ptls.data_load.datasets import ParquetDataset, parquet_file_scan\nfrom ptls.data_load.iterable_processing import IterableShuffle\n","metadata":{"execution":{"iopub.status.busy":"2022-08-11T10:04:16.614285Z","iopub.execute_input":"2022-08-11T10:04:16.615684Z","iopub.status.idle":"2022-08-11T10:04:17.885036Z","shell.execute_reply.started":"2022-08-11T10:04:16.615577Z","shell.execute_reply":"2022-08-11T10:04:17.883569Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Load preprocessor which keep column names and dictionary sizes for categorical fields\nwith open('../input/amex-ptls-data/preprocessor.pickle', 'rb') as f:\n    preprocessor = pickle.load(f)","metadata":{"execution":{"iopub.status.busy":"2022-08-11T10:04:17.894883Z","iopub.execute_input":"2022-08-11T10:04:17.895789Z","iopub.status.idle":"2022-08-11T10:04:17.965870Z","shell.execute_reply.started":"2022-08-11T10:04:17.895741Z","shell.execute_reply":"2022-08-11T10:04:17.964427Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"preprocessor.get_category_dictionary_sizes()","metadata":{"execution":{"iopub.status.busy":"2022-08-11T10:04:17.967667Z","iopub.execute_input":"2022-08-11T10:04:17.968147Z","iopub.status.idle":"2022-08-11T10:04:17.984601Z","shell.execute_reply.started":"2022-08-11T10:04:17.968101Z","shell.execute_reply":"2022-08-11T10:04:17.983046Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_files = parquet_file_scan('../input/amex-ptls-data/data_train.parquet')\ntest_files = parquet_file_scan('../input/amex-ptls-data/data_test.parquet')\nlen(train_files), len(test_files)","metadata":{"execution":{"iopub.status.busy":"2022-08-11T10:04:17.990165Z","iopub.execute_input":"2022-08-11T10:04:17.990484Z","iopub.status.idle":"2022-08-11T10:04:18.006798Z","shell.execute_reply.started":"2022-08-11T10:04:17.990455Z","shell.execute_reply":"2022-08-11T10:04:18.005243Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_files, valid_files = train_test_split(train_files, test_size=0.05, random_state=242)\nlen(train_files), len(valid_files), len(test_files)","metadata":{"execution":{"iopub.status.busy":"2022-08-11T10:04:18.009990Z","iopub.execute_input":"2022-08-11T10:04:18.010788Z","iopub.status.idle":"2022-08-11T10:04:18.024563Z","shell.execute_reply.started":"2022-08-11T10:04:18.010724Z","shell.execute_reply":"2022-08-11T10:04:18.022569Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"In this notebook `train_files` and `test_files` used as unlabeled train data for unsupervides pretrain.\n`valid_files` used for track pretrain quality.","metadata":{}},{"cell_type":"code","source":"class NumConcat:\n    \"\"\"Concatenete numerical columns which a collected to single field\n    Work with one tensor is faster than iterating over 150+ numerical columns in amex dataset.\n    \"\"\"\n    def __call__(self, data):\n        self.data = data\n        return iter(self)\n        \n    def __iter__(self):\n        for rec in self.data:\n            rec['num_cols'] = np.stack(rec['num_cols'].tolist(), axis=1)\n            rec['num_cols'] = torch.from_numpy(rec['num_cols'])\n            yield rec\n","metadata":{"execution":{"iopub.status.busy":"2022-08-11T10:04:18.027162Z","iopub.execute_input":"2022-08-11T10:04:18.027996Z","iopub.status.idle":"2022-08-11T10:04:18.037121Z","shell.execute_reply.started":"2022-08-11T10:04:18.027950Z","shell.execute_reply":"2022-08-11T10:04:18.035257Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from ptls.data_load.iterable_processing import SeqLenFilter","metadata":{"execution":{"iopub.status.busy":"2022-08-11T10:04:18.038984Z","iopub.execute_input":"2022-08-11T10:04:18.039927Z","iopub.status.idle":"2022-08-11T10:04:18.050023Z","shell.execute_reply.started":"2022-08-11T10:04:18.039880Z","shell.execute_reply":"2022-08-11T10:04:18.048480Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# We will use ParquetDataset in iterable mode\ntrain_dataset = ParquetDataset(\n    train_files + test_files,\n    shuffle_files=True,\n    i_filters=[\n        SeqLenFilter(min_seq_len=4),\n        NumConcat(),\n        IterableShuffle(buffer_size=1000),  # this shuffle rows with buffer \n    ],\n)\nvalid_dataset = ParquetDataset(\n    valid_files,\n    i_filters=[\n        SeqLenFilter(min_seq_len=4),\n        NumConcat(),\n    ],\n)","metadata":{"execution":{"iopub.status.busy":"2022-08-11T10:04:18.052255Z","iopub.execute_input":"2022-08-11T10:04:18.053942Z","iopub.status.idle":"2022-08-11T10:04:18.064191Z","shell.execute_reply.started":"2022-08-11T10:04:18.053864Z","shell.execute_reply":"2022-08-11T10:04:18.062183Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Encoder network","metadata":{}},{"cell_type":"code","source":"import torch\n\nfrom ptls.data_load.padded_batch import PaddedBatch\nfrom ptls.nn import TrxEncoder, RnnEncoder, TransformerEncoder, PBLinear, PBLayerNorm, L2NormEncoder","metadata":{"execution":{"iopub.status.busy":"2022-08-11T10:04:18.066866Z","iopub.execute_input":"2022-08-11T10:04:18.068042Z","iopub.status.idle":"2022-08-11T10:04:18.917763Z","shell.execute_reply.started":"2022-08-11T10:04:18.067989Z","shell.execute_reply":"2022-08-11T10:04:18.915987Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class NaImputer(torch.nn.Module):\n    \"\"\"Replace NaN with 0 value\n    \"\"\"\n    def forward(self, x: PaddedBatch):\n        new_x = {k: self.impute(k, v) for k, v in x.payload.items()}\n        return PaddedBatch(new_x, x.seq_lens)\n    \n    def impute(self, k, v):\n        if not PaddedBatch.is_seq_feature(k, v):\n            return v\n        return v.masked_fill(torch.isnan(v), 0.0)","metadata":{"execution":{"iopub.status.busy":"2022-08-11T10:04:18.921710Z","iopub.execute_input":"2022-08-11T10:04:18.922183Z","iopub.status.idle":"2022-08-11T10:04:18.931936Z","shell.execute_reply.started":"2022-08-11T10:04:18.922132Z","shell.execute_reply":"2022-08-11T10:04:18.930356Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def sign_log(x):\n    return torch.log1p(torch.abs(x)) * torch.sign(x)\n    \nclass TrxEncoderExt(torch.nn.Module):\n    \"\"\"Supports numerical features stacked with `NumConcat`.\n    Implements the same behavior as `ptls.nn.TrxEncoder` but faster.\n    \"\"\"\n    def __init__(self, trx_encoder, numeric_count=177):\n        super().__init__()\n        \n        self.trx_encoder = trx_encoder\n        self.numeric_count = numeric_count\n        self.bn = torch.nn.BatchNorm1d(numeric_count)\n        \n    def forward(self, x):\n        x_new = self.trx_encoder(x)\n        \n        B, T, H = x.payload['num_cols'].size()\n        \n        num = self.bn(sign_log(x.payload['num_cols']).view(B * T, H)).view(B, T, H)\n        num = num * x.seq_len_mask.float().unsqueeze(2)\n        num = num.clamp(-3, 3)\n        return PaddedBatch(\n            torch.cat([x_new.payload, num], dim=2),\n            x.seq_lens,\n        )\n    \n    @property\n    def output_size(self):\n        return self.trx_encoder.output_size + self.numeric_count\n","metadata":{"execution":{"iopub.status.busy":"2022-08-11T10:04:18.934288Z","iopub.execute_input":"2022-08-11T10:04:18.935242Z","iopub.status.idle":"2022-08-11T10:04:18.951544Z","shell.execute_reply.started":"2022-08-11T10:04:18.935194Z","shell.execute_reply":"2022-08-11T10:04:18.950066Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class PBFeatureDropout(torch.nn.Module):\n    \"\"\"Zeros a feature for all transaction in batch\n    \n    Mask a different features in coles subsamlpes to get harder match\n    \n    Before:\n      Splits:     split_0       |     split_1        |\n        Time:  0     1     2    |   3     4     5    |\n    B_1:      0.11  0.10  0.09  |  0.11  0.10  0.09  |\n    B_2:      0.91  0.90  0.89  |  0.91  0.90  0.89  |\n    \n    After:\n      Splits:     split_0       |     split_1        |\n        Time:  0     1     2    |   3     4     5    |\n    B_1:      0.00  0.00  0.00  |  0.11  0.10  0.09  |\n    B_2:      0.91  0.90  0.89  |  0.00  0.00  0.00  |\n    \n    \"\"\"\n    def __init__(self, p):\n        super().__init__()\n        self.p = p\n        self.enabled = True\n        \n    def forward(self, x: PaddedBatch):\n        B, T, H = x.payload.size()\n        if self.enabled:\n            mask = torch.bernoulli(torch.ones(B, 1, H, device=x.device) * (1 - self.p))\n            return PaddedBatch(x.payload * mask / (1 - self.p), x.seq_lens)\n        return x","metadata":{"execution":{"iopub.status.busy":"2022-08-11T10:04:18.954242Z","iopub.execute_input":"2022-08-11T10:04:18.954857Z","iopub.status.idle":"2022-08-11T10:04:18.965640Z","shell.execute_reply.started":"2022-08-11T10:04:18.954778Z","shell.execute_reply":"2022-08-11T10:04:18.963584Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Metrics\n\nTaken from https://www.kaggle.com/code/inversion/amex-competition-metric-python\nand covered to `torchmetrics.Metric` for NN usage","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\n\n\ndef top_four_percent_captured(y_true: pd.DataFrame, y_pred: pd.DataFrame) -> float:\n    df = (pd.concat([y_true, y_pred], axis='columns')\n          .sort_values('prediction', ascending=False))\n    df['weight'] = df['target'].apply(lambda x: 20 if x==0 else 1)\n    four_pct_cutoff = int(0.04 * df['weight'].sum())\n    df['weight_cumsum'] = df['weight'].cumsum()\n    df_cutoff = df.loc[df['weight_cumsum'] <= four_pct_cutoff]\n    return (df_cutoff['target'] == 1).sum() / (df['target'] == 1).sum()\n\ndef weighted_gini(y_true: pd.DataFrame, y_pred: pd.DataFrame) -> float:\n    df = (pd.concat([y_true, y_pred], axis='columns')\n          .sort_values('prediction', ascending=False))\n    df['weight'] = df['target'].apply(lambda x: 20 if x==0 else 1)\n    df['random'] = (df['weight'] / df['weight'].sum()).cumsum()\n    total_pos = (df['target'] * df['weight']).sum()\n    df['cum_pos_found'] = (df['target'] * df['weight']).cumsum()\n    df['lorentz'] = df['cum_pos_found'] / total_pos\n    df['gini'] = (df['lorentz'] - df['random']) * df['weight']\n    return df['gini'].sum()\n\ndef normalized_weighted_gini(y_true: pd.DataFrame, y_pred: pd.DataFrame) -> float:\n    y_true_pred = y_true.rename(columns={'target': 'prediction'})\n    return weighted_gini(y_true, y_pred) / weighted_gini(y_true, y_true_pred)\n\ndef amex_metric(y_true: pd.DataFrame, y_pred: pd.DataFrame) -> float:\n    g = normalized_weighted_gini(y_true, y_pred)\n    d = top_four_percent_captured(y_true, y_pred)\n\n    return 0.5 * (g + d), g, d","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-08-11T10:04:18.973102Z","iopub.execute_input":"2022-08-11T10:04:18.973716Z","iopub.status.idle":"2022-08-11T10:04:18.991391Z","shell.execute_reply.started":"2022-08-11T10:04:18.973684Z","shell.execute_reply":"2022-08-11T10:04:18.989738Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Train\n\nPrepare `datamodule`, model as `pl.LightningModile` and `pl.Trainer`\n\nRun train with validation","metadata":{}},{"cell_type":"code","source":"import pytorch_lightning as pl\n\nfrom ptls.frames import PtlsDataModule\n\nfrom functools import partial","metadata":{"execution":{"iopub.status.busy":"2022-08-11T10:04:18.994456Z","iopub.execute_input":"2022-08-11T10:04:18.998518Z","iopub.status.idle":"2022-08-11T10:04:20.031631Z","shell.execute_reply.started":"2022-08-11T10:04:18.998483Z","shell.execute_reply":"2022-08-11T10:04:20.028073Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Let's try **Contrastive Learning for Event Sequences** ([CoLES](https://arxiv.org/abs/2002.08232))","metadata":{}},{"cell_type":"code","source":"from ptls.frames import coles","metadata":{"execution":{"iopub.status.busy":"2022-08-11T10:04:20.035634Z","iopub.execute_input":"2022-08-11T10:04:20.037081Z","iopub.status.idle":"2022-08-11T10:04:20.069986Z","shell.execute_reply.started":"2022-08-11T10:04:20.037013Z","shell.execute_reply":"2022-08-11T10:04:20.068187Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dm = PtlsDataModule(\n    train_data=coles.ColesIterableDataset(\n        train_dataset,\n        splitter=coles.split_strategy.SampleSlices(split_count=2, cnt_min=2, cnt_max=10),\n    ),\n    valid_data=coles.ColesIterableDataset(\n        valid_dataset, \n        splitter=coles.split_strategy.SampleSlices(split_count=2, cnt_min=2, cnt_max=10),\n    ),\n    train_batch_size=1024,\n    valid_batch_size=1024,\n    train_num_workers=0,\n    valid_num_workers=0,\n)\n\ntrx_encoder = TrxEncoderExt(TrxEncoder(\n    embeddings={col: {'in': d, 'out': 4} for col, d in preprocessor.get_category_dictionary_sizes().items()},\n    numeric_values={},\n#     numeric_values={col: 'identity' for col in num_fields},\n))\n\nseq_encoder = torch.nn.Sequential(\n    NaImputer(),\n    trx_encoder,\n    PBFeatureDropout(0.6),\n    PBLinear(trx_encoder.output_size, 160),\n    PBLayerNorm(160),\n    RnnEncoder(\n        input_size=160, \n        hidden_size=256,\n        is_reduce_sequence=True,\n    ),\n)\n\nmodel = coles.CoLESModule(\n    seq_encoder=seq_encoder,\n    head=L2NormEncoder(),\n    validation_metric=coles.metric.BatchRecallTopK(1),\n    loss=coles.losses.ContrastiveLoss(\n        margin=0.5,\n        sampling_strategy=coles.sampling_strategies.HardNegativePairSelector(neg_count=5),\n    ),\n    optimizer_partial=partial(torch.optim.Adam, lr=0.002, weight_decay=0),\n    lr_scheduler_partial=partial(\n        torch.optim.lr_scheduler.StepLR,\n        step_size=10,\n        gamma=0.9,\n    ),\n)\n\ntrainer = pl.Trainer(\n    gpus=1,\n    max_epochs=5,\n    limit_train_batches=150,\n    enable_checkpointing=False,\n    enable_progress_bar=False,\n    callbacks=[\n        pl.callbacks.LearningRateMonitor(),\n    ],\n)","metadata":{"execution":{"iopub.status.busy":"2022-08-11T10:06:37.045106Z","iopub.execute_input":"2022-08-11T10:06:37.045633Z","iopub.status.idle":"2022-08-11T10:06:37.088900Z","shell.execute_reply.started":"2022-08-11T10:06:37.045590Z","shell.execute_reply":"2022-08-11T10:06:37.087669Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pyarrow\nprint(f'pyarrow.cpu_count = {pyarrow.cpu_count()}')\npyarrow.set_io_thread_count(4)","metadata":{"execution":{"iopub.status.busy":"2022-08-11T10:06:37.185465Z","iopub.execute_input":"2022-08-11T10:06:37.188776Z","iopub.status.idle":"2022-08-11T10:06:37.197735Z","shell.execute_reply.started":"2022-08-11T10:06:37.188729Z","shell.execute_reply":"2022-08-11T10:06:37.196211Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('\\n'.join([\n    'Running...',\n    f'version = {trainer.logger.version}',\n]))\n\ntrainer.fit(model, dm)\n\nprint(trainer.logged_metrics)","metadata":{"execution":{"iopub.status.busy":"2022-08-11T10:06:37.564791Z","iopub.execute_input":"2022-08-11T10:06:37.565282Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Results","metadata":{}},{"cell_type":"code","source":"import ptls.tb_interface as tb\nimport matplotlib.pyplot as plt","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_tb = tb.get_scalars('lightning_logs/')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_tb['tag'].value_counts()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for tag in ['loss', 'recall_top_k']:\n    df = df_tb[lambda x: x['tag'] == tag].set_index(['step', 'version'])['value'].unstack()\n    df.plot(figsize=(8, 4), title=tag)\n    plt.show()\n    print(df.max())","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Inference","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nfrom ptls.data_load.utils import collate_feature_dict\nfrom ptls.frames.inference_module import InferenceModule","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_files = parquet_file_scan('../input/amex-ptls-data/data_train.parquet')\ntest_files = parquet_file_scan('../input/amex-ptls-data/data_test.parquet')\nlen(train_files), len(test_files)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataset = ParquetDataset(\n    train_files,\n    i_filters=[\n        NumConcat(),\n    ],\n)\ntest_dataset = ParquetDataset(\n    test_files,\n    i_filters=[\n        NumConcat(),\n    ],\n)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataloader = torch.utils.data.DataLoader(\n    train_dataset,\n    collate_fn=collate_feature_dict,\n    num_workers=2,\n    batch_size=1024,\n    \n)\ntest_dataloader = torch.utils.data.DataLoader(\n    test_dataset,\n    collate_fn=collate_feature_dict,\n    num_workers=2,\n    batch_size=1024,\n    \n)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Disable feature dropout\nmodel._seq_encoder[2].enabled = False","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_emb_train = trainer.predict(InferenceModule(model, model_out_name='emb'), train_dataloader)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_emb_test = trainer.predict(InferenceModule(model, model_out_name='emb'), test_dataloader)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_emb_train = pd.concat(df_emb_train, axis=0)\ndf_emb_test = pd.concat(df_emb_test, axis=0)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_emb_train.to_parquet('/kaggle/working/df_emb_train.parquet')\ndf_emb_test.to_parquet('/kaggle/working/df_emb_test.parquet')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Try to concat embeddings from `df_emb_train.parquet` and `df_emb_test.parquet` with your features","metadata":{}},{"cell_type":"markdown","source":"# Check embeddings quality","metadata":{}},{"cell_type":"code","source":"from lightgbm import LGBMClassifier","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"lgbm_model = LGBMClassifier(\n    n_estimators=500,\n    boosting_type='gbdt',\n    objective='binary',\n    metric='auc',\n    subsample=0.5,\n    subsample_freq=1,\n    learning_rate=0.02,\n    feature_fraction=0.75,\n    max_depth=6,\n    lambda_l1=1,\n    lambda_l2=1,\n    min_data_in_leaf=50,\n    random_state=42,\n    n_jobs=8,\n    reg_alpha=None,\n    reg_lambda=None,\n    colsample_bytree=None,\n    min_child_samples=None,\n)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train, df_valid = train_test_split(df_emb_train, test_size=0.2, stratify=df_emb_train['target'])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"x_col = [col for col in df_train.columns if col.startswith('emb_')]\nlen(x_col)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"lgbm_model.fit(df_train[x_col], df_train['target'])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predict = lgbm_model.predict_proba(df_valid[x_col])[:, 1]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"am = amex_metric(\n    y_true=pd.DataFrame({'target': df_valid['target'].values}),\n    y_pred=pd.DataFrame({'prediction': predict}),\n)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"am","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# More info about ptls\n\nLinks:\n- Repo: https://github.com/dllllb/pytorch-lifestream\n- Demos: https://github.com/dllllb/pytorch-lifestream/tree/main/demo\n- Docs: https://dllllb.github.io/pytorch-lifestream/","metadata":{}},{"cell_type":"code","source":"from IPython.display import HTML\n\nHTML('''\n<!-- Place this tag in your head or just before your close body tag. -->\n<script async defer src=\"https://buttons.github.io/buttons.js\"></script>\n\n<p>Star <code>pytorch-lifestream</code> on github if you like this notebook</p>\n<!-- Place this tag where you want the button to render. -->\n<a class=\"github-button\" href=\"https://github.com/dllllb/pytorch-lifestream\" data-icon=\"octicon-star\" data-size=\"large\" data-show-count=\"true\" aria-label=\"Star dllllb/pytorch-lifestream on GitHub\">Star</a>\n''')","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}