{"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":"markdown","source":"# MSCI Multiome Torch Quickstart Submission\nThis notebook creates submissions from the models trained in [this notebook](https://www.kaggle.com/fabiencrom/msci-multiome-torch-quickstart-w-sparse-tensors).\n\nWe only predict the Multiome data and then merge in the CITEseq results from [this notebook](https://www.kaggle.com/code/ambrosm/msci-citeseq-keras-quickstart/notebook) by AmbrosM, which has the highest public score at the time I am publishing.\n\nSo far we do not get better results than the one obtained by the much simpler PCA+Ridge Regression method (that you can find in [this notebook](https://www.kaggle.com/code/ambrosm/msci-multiome-quickstart) as initially proposed by AmbrosM or in [this notebook](https://www.kaggle.com/code/fabiencrom/msci-multiome-quickstart-w-sparse-matrices) for a version using sparse matrices for better results). But I expect it can be made to perform better after improving the architecture/hyperparameters.\n","metadata":{}},{"cell_type":"code","source":"import os\nimport copy\nimport gc\nimport math\nimport itertools\nimport pickle\nimport glob\nimport joblib\nimport json\nimport random\nimport re\nimport operator\n\nimport collections\nfrom collections import defaultdict\nfrom operator import itemgetter, attrgetter\n\nfrom tqdm.notebook import tqdm\n\nimport torch\nimport torch.nn as nn\n\nimport numpy as np\nimport pandas as pd\nimport plotly.express as px\n\nimport scipy\n\nimport sklearn\nimport sklearn.cluster\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.model_selection import KFold\nimport sklearn.preprocessing\n\nimport copy","metadata":{"execution":{"iopub.status.busy":"2022-09-04T12:56:25.191413Z","iopub.execute_input":"2022-09-04T12:56:25.192055Z","iopub.status.idle":"2022-09-04T12:56:30.872989Z","shell.execute_reply.started":"2022-09-04T12:56:25.191991Z","shell.execute_reply":"2022-09-04T12:56:30.872009Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def partial_correlation_score_torch_faster(y_true, y_pred):\n    \"\"\"Compute the correlation between each rows of the y_true and y_pred tensors.\n    Compatible with backpropagation.\n    \"\"\"\n    y_true_centered = y_true - torch.mean(y_true, dim=1)[:,None]\n    y_pred_centered = y_pred - torch.mean(y_pred, dim=1)[:,None]\n    cov_tp = torch.sum(y_true_centered*y_pred_centered, dim=1)/(y_true.shape[1]-1)\n    var_t = torch.sum(y_true_centered**2, dim=1)/(y_true.shape[1]-1)\n    var_p = torch.sum(y_pred_centered**2, dim=1)/(y_true.shape[1]-1)\n    return cov_tp/torch.sqrt(var_t*var_p)\n\ndef correl_loss(pred, tgt):\n    \"\"\"Loss for directly optimizing the correlation.\n    \"\"\"\n    return -torch.mean(partial_correlation_score_torch_faster(tgt, pred))","metadata":{"execution":{"iopub.status.busy":"2022-09-04T12:59:56.197937Z","iopub.execute_input":"2022-09-04T12:59:56.198328Z","iopub.status.idle":"2022-09-04T12:59:56.207055Z","shell.execute_reply.started":"2022-09-04T12:59:56.198297Z","shell.execute_reply":"2022-09-04T12:59:56.205952Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Utility functions for loading and batching the sparse data in device memory","metadata":{}},{"cell_type":"code","source":"# Strangely, current torch implementation of csr tensor do not accept to be moved to the gpu. \n# So we make our own equivalent class\nTorchCSR = collections.namedtuple(\"TrochCSR\", \"data indices indptr shape\")\n\ndef load_csr_data_to_gpu(train_inputs):\n    \"\"\"Move a scipy csr sparse matrix to the gpu as a TorchCSR object\n    This try to manage memory efficiently by creating the tensors and moving them to the gpu one by one\n    \"\"\"\n    th_data = torch.from_numpy(train_inputs.data).to(device)\n    th_indices = torch.from_numpy(train_inputs.indices).to(device)\n    th_indptr = torch.from_numpy(train_inputs.indptr).to(device)\n    th_shape = train_inputs.shape\n    return TorchCSR(th_data, th_indices, th_indptr, th_shape)\n\ndef make_coo_batch(torch_csr, indx):\n    \"\"\"Make a coo torch tensor from a TorchCSR object by taking the rows indicated by the indx tensor\n    \"\"\"\n    th_data, th_indices, th_indptr, th_shape = torch_csr\n    start_pts = th_indptr[indx]\n    end_pts = th_indptr[indx+1]\n    coo_data = torch.cat([th_data[start_pts[i]: end_pts[i]] for i in range(len(start_pts))], dim=0)\n    coo_col = torch.cat([th_indices[start_pts[i]: end_pts[i]] for i in range(len(start_pts))], dim=0)\n    coo_row = torch.repeat_interleave(torch.arange(indx.shape[0], device=device), th_indptr[indx+1] - th_indptr[indx])\n    coo_batch = torch.sparse_coo_tensor(torch.vstack([coo_row, coo_col]), coo_data, [indx.shape[0], th_shape[1]])\n    return coo_batch\n\n\ndef make_coo_batch_slice(torch_csr, start, end):\n    \"\"\"Make a coo torch tensor from a TorchCSR object by taking the rows within the (start, end) slice\n    \"\"\"\n    th_data, th_indices, th_indptr, th_shape = torch_csr\n    if end > th_shape[0]:\n        end = th_shape[0]\n    start_pts = th_indptr[start]\n    end_pts = th_indptr[end]\n    coo_data = th_data[start_pts: end_pts]\n    coo_col = th_indices[start_pts: end_pts]\n    coo_row = torch.repeat_interleave(torch.arange(end-start, device=device), th_indptr[start+1:end+1] - th_indptr[start:end])\n    coo_batch = torch.sparse_coo_tensor(torch.vstack([coo_row, coo_col]), coo_data, [end-start, th_shape[1]])\n    return coo_batch\n","metadata":{"execution":{"iopub.status.busy":"2022-09-04T12:56:30.877247Z","iopub.execute_input":"2022-09-04T12:56:30.877741Z","iopub.status.idle":"2022-09-04T12:56:30.892719Z","shell.execute_reply.started":"2022-09-04T12:56:30.877696Z","shell.execute_reply":"2022-09-04T12:56:30.891677Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# GPU memory DataLoader","metadata":{}},{"cell_type":"code","source":"class DataLoaderCOO:\n    \"\"\"Torch compatible DataLoader. Works with in-device TorchCSR tensors.\n    Args:\n         - train_inputs, train_targets: TorchCSR tensors\n         - train_idx: tensor containing the indices of the rows of train_inputs and train_targets that should be used\n         - batch_size, shuffle, drop_last: as in torch.utils.data.DataLoader\n    \"\"\"\n    def __init__(self, train_inputs, train_targets, train_idx=None, \n                 *,\n                batch_size=512, shuffle=False, drop_last=False):\n        self.batch_size = batch_size\n        self.shuffle = shuffle\n        self.drop_last = drop_last\n        \n        self.train_inputs = train_inputs\n        self.train_targets = train_targets\n        \n        self.train_idx = train_idx\n        \n        self.nb_examples = len(self.train_idx) if self.train_idx is not None else train_inputs.shape[0]\n        \n        self.nb_batches = self.nb_examples//batch_size\n        if not drop_last and not self.nb_examples%batch_size==0:\n            self.nb_batches +=1\n        \n    def __iter__(self):\n        if self.shuffle:\n            shuffled_idx = torch.randperm(self.nb_examples, device=device)\n            if self.train_idx is not None:\n                idx_array = self.train_idx[shuffled_idx]\n            else:\n                idx_array = shuffled_idx\n        else:\n            if self.train_idx is not None:\n                idx_array = self.train_idx\n            else:\n                idx_array = None\n            \n        for i in range(self.nb_batches):\n            slc = slice(i*self.batch_size, (i+1)*self.batch_size)\n            if idx_array is None:\n                inp_batch = make_coo_batch_slice(self.train_inputs, i*self.batch_size, (i+1)*self.batch_size)\n                if self.train_targets is None:\n                    tgt_batch = None\n                else:\n                    tgt_batch = make_coo_batch_slice(self.train_targets, i*self.batch_size, (i+1)*self.batch_size)\n            else:\n                idx_batch = idx_array[slc]\n                inp_batch = make_coo_batch(self.train_inputs, idx_batch)\n                if self.train_targets is None:\n                    tgt_batch = None\n                else:\n                    tgt_batch = make_coo_batch(self.train_targets, idx_batch)\n            yield inp_batch, tgt_batch\n            \n            \n    def __len__(self):\n        return self.nb_batches","metadata":{"execution":{"iopub.status.busy":"2022-09-04T12:56:30.894949Z","iopub.execute_input":"2022-09-04T12:56:30.895745Z","iopub.status.idle":"2022-09-04T12:56:30.913418Z","shell.execute_reply.started":"2022-09-04T12:56:30.895701Z","shell.execute_reply":"2022-09-04T12:56:30.912372Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Simple Model: MLP","metadata":{}},{"cell_type":"code","source":"class MLP(nn.Module):\n    def __init__(self, layer_size_lst, add_final_activation=False):\n        super().__init__()\n        \n        assert len(layer_size_lst) > 2\n        \n        layer_lst = []\n        for i in range(len(layer_size_lst)-1):\n            sz1 = layer_size_lst[i]\n            sz2 = layer_size_lst[i+1]\n            layer_lst += [nn.Linear(sz1, sz2)]\n            if i != len(layer_size_lst)-2 or add_final_activation:\n                 layer_lst += [nn.ReLU()]\n        self.mlp = nn.Sequential(*layer_lst)\n        \n    def forward(self, x):\n        return self.mlp(x)\n    \ndef build_model():\n    model = MLP([INPUT_SIZE] + config[\"layers\"] + [OUTPUT_SIZE])\n    if config[\"head\"] == \"softplus\":\n        model = nn.Sequential(model, nn.Softplus())\n    else:\n        assert config[\"head\"] is None\n    return model","metadata":{"execution":{"iopub.status.busy":"2022-09-04T12:56:30.916224Z","iopub.execute_input":"2022-09-04T12:56:30.917901Z","iopub.status.idle":"2022-09-04T12:56:30.928793Z","shell.execute_reply.started":"2022-09-04T12:56:30.917800Z","shell.execute_reply":"2022-09-04T12:56:30.927655Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# test_fn function","metadata":{}},{"cell_type":"code","source":"def test_fn_ensemble(model_list, dl_test):\n\n    res = torch.empty(\n        (dl_test.nb_examples, OUTPUT_SIZE), \n        device=device, dtype=torch.float32)\n    \n#     all_preds = []\n    for model in model_list:\n        model.eval()\n        \n    cur = 0\n    for inpt, tgt in tqdm(dl_test):\n        mb_size = inpt.shape[0]\n\n        with torch.no_grad():\n            pred_list = []\n            for model in model_list:\n                pred = model(inpt)\n                pred_list.append(pred)\n            pred = sum(pred_list)/len(pred_list)\n            \n#         print(res.shape, cur, cur+pred.shape[0], res[cur:cur+pred.shape[0]].shape, pred.shape)\n        res[cur:cur+pred.shape[0]] = pred\n        cur += pred.shape[0]\n            \n    return {\"preds\":res}\n","metadata":{"execution":{"iopub.status.busy":"2022-09-04T12:56:30.930425Z","iopub.execute_input":"2022-09-04T12:56:30.930851Z","iopub.status.idle":"2022-09-04T12:56:30.940465Z","shell.execute_reply.started":"2022-09-04T12:56:30.930758Z","shell.execute_reply":"2022-09-04T12:56:30.939324Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Loading Data","metadata":{}},{"cell_type":"code","source":"if torch.cuda.is_available():\n    device = torch.device(\"cuda:0\")\n    print(f\"machine has {torch.cuda.device_count()} cuda devices\")\n    print(f\"model of first cuda device is {torch.cuda.get_device_name(0)}\")\nelse:\n    device = torch.device(\"cpu\")\n","metadata":{"execution":{"iopub.status.busy":"2022-09-04T12:56:30.944041Z","iopub.execute_input":"2022-09-04T12:56:30.944383Z","iopub.status.idle":"2022-09-04T12:56:31.032795Z","shell.execute_reply.started":"2022-09-04T12:56:30.944358Z","shell.execute_reply":"2022-09-04T12:56:31.031604Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"INPUT_SIZE = 228942 \nOUTPUT_SIZE = 23418","metadata":{"execution":{"iopub.status.busy":"2022-09-04T12:56:31.034328Z","iopub.execute_input":"2022-09-04T12:56:31.034932Z","iopub.status.idle":"2022-09-04T12:56:31.049733Z","shell.execute_reply.started":"2022-09-04T12:56:31.034897Z","shell.execute_reply":"2022-09-04T12:56:31.048775Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"max_inputs = np.load(\"../input/msci-multiome-torch-quickstart-w-sparse-tensors/max_inputs.npz\")[\"max_inputs\"]\nmax_inputs = torch.from_numpy(max_inputs)[0].to(device)","metadata":{"execution":{"iopub.status.busy":"2022-09-04T12:57:03.953516Z","iopub.execute_input":"2022-09-04T12:57:03.954211Z","iopub.status.idle":"2022-09-04T12:57:07.047685Z","shell.execute_reply.started":"2022-09-04T12:57:03.954177Z","shell.execute_reply":"2022-09-04T12:57:07.046683Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\ntest_inputs = scipy.sparse.load_npz(\n    \"../input/multimodal-single-cell-as-sparse-matrix/test_multi_inputs_values.sparse.npz\")","metadata":{"execution":{"iopub.status.busy":"2022-09-04T12:57:07.049434Z","iopub.execute_input":"2022-09-04T12:57:07.049825Z","iopub.status.idle":"2022-09-04T12:57:39.125964Z","shell.execute_reply.started":"2022-09-04T12:57:07.049785Z","shell.execute_reply":"2022-09-04T12:57:39.124837Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\ntest_inputs = load_csr_data_to_gpu(test_inputs)\ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2022-09-04T12:57:39.128052Z","iopub.execute_input":"2022-09-04T12:57:39.128391Z","iopub.status.idle":"2022-09-04T12:57:39.891701Z","shell.execute_reply.started":"2022-09-04T12:57:39.128355Z","shell.execute_reply":"2022-09-04T12:57:39.890707Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_inputs.data[...] /= max_inputs[test_inputs.indices.long()]","metadata":{"execution":{"iopub.status.busy":"2022-09-04T12:57:39.893197Z","iopub.execute_input":"2022-09-04T12:57:39.893843Z","iopub.status.idle":"2022-09-04T12:57:39.921429Z","shell.execute_reply.started":"2022-09-04T12:57:39.893805Z","shell.execute_reply":"2022-09-04T12:57:39.920587Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"torch.max(test_inputs.data)","metadata":{"execution":{"iopub.status.busy":"2022-09-04T12:57:39.924146Z","iopub.execute_input":"2022-09-04T12:57:39.924545Z","iopub.status.idle":"2022-09-04T12:57:39.951273Z","shell.execute_reply.started":"2022-09-04T12:57:39.924508Z","shell.execute_reply":"2022-09-04T12:57:39.950256Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Load trained models","metadata":{}},{"cell_type":"code","source":"model_list = []\nfor fn in tqdm(glob.glob(\"../input/msci-multiome-torch-quickstart-w-sparse-tensors/*_best_params.pth\")):\n    prefix = fn[:-len(\"_best_params.pth\")]\n    config_fn = prefix + \"_config.pkl\"\n    \n    config = pickle.load(open(config_fn, \"rb\"))\n    \n    model = build_model() \n    model.to(device)\n    \n    params = torch.load(fn)\n    model.load_state_dict(params)\n    \n    model_list.append(model)","metadata":{"execution":{"iopub.status.busy":"2022-09-04T13:00:37.984365Z","iopub.execute_input":"2022-09-04T13:00:37.984745Z","iopub.status.idle":"2022-09-04T13:00:44.452256Z","shell.execute_reply.started":"2022-09-04T13:00:37.984712Z","shell.execute_reply":"2022-09-04T13:00:44.451113Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Generate Multiome predictions","metadata":{}},{"cell_type":"code","source":"dl_test = DataLoaderCOO(test_inputs, None, train_idx=None,\n                batch_size=512, shuffle=False, drop_last=False)","metadata":{"execution":{"iopub.status.busy":"2022-09-04T13:00:49.478689Z","iopub.execute_input":"2022-09-04T13:00:49.479050Z","iopub.status.idle":"2022-09-04T13:00:49.485191Z","shell.execute_reply.started":"2022-09-04T13:00:49.479011Z","shell.execute_reply":"2022-09-04T13:00:49.484108Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_pred = test_fn_ensemble(model_list, dl_test)[\"preds\"]","metadata":{"execution":{"iopub.status.busy":"2022-09-04T13:00:50.945576Z","iopub.execute_input":"2022-09-04T13:00:50.946265Z","iopub.status.idle":"2022-09-04T13:01:13.893066Z","shell.execute_reply.started":"2022-09-04T13:00:50.946229Z","shell.execute_reply":"2022-09-04T13:01:13.891992Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"del model_list\ndel dl_test\ndel test_inputs\ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2022-09-04T13:01:38.826316Z","iopub.execute_input":"2022-09-04T13:01:38.826742Z","iopub.status.idle":"2022-09-04T13:01:39.003502Z","shell.execute_reply.started":"2022-09-04T13:01:38.826707Z","shell.execute_reply":"2022-09-04T13:01:39.002522Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_pred.shape","metadata":{"execution":{"iopub.status.busy":"2022-09-04T13:01:39.242321Z","iopub.execute_input":"2022-09-04T13:01:39.243035Z","iopub.status.idle":"2022-09-04T13:01:39.250119Z","shell.execute_reply.started":"2022-09-04T13:01:39.243000Z","shell.execute_reply":"2022-09-04T13:01:39.248921Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Creating the final submission","metadata":{}},{"cell_type":"code","source":"%%time\n# Read the table of rows and columns required for submission\neval_ids = pd.read_parquet(\"../input/multimodal-single-cell-as-sparse-matrix/evaluation.parquet\")\n\n# Convert the string columns to more efficient categorical types\n#eval_ids.cell_id = eval_ids.cell_id.apply(lambda s: int(s, base=16))\n\neval_ids.cell_id = eval_ids.cell_id.astype(pd.CategoricalDtype())\neval_ids.gene_id = eval_ids.gene_id.astype(pd.CategoricalDtype())","metadata":{"execution":{"iopub.status.busy":"2022-09-04T13:01:39.853418Z","iopub.execute_input":"2022-09-04T13:01:39.853744Z","iopub.status.idle":"2022-09-04T13:02:12.293971Z","shell.execute_reply.started":"2022-09-04T13:01:39.853715Z","shell.execute_reply":"2022-09-04T13:02:12.292793Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Prepare an empty series which will be filled with predictions\nsubmission = pd.Series(name='target',\n                       index=pd.MultiIndex.from_frame(eval_ids), \n                       dtype=np.float32)\nsubmission","metadata":{"execution":{"iopub.status.busy":"2022-09-04T13:02:12.296044Z","iopub.execute_input":"2022-09-04T13:02:12.296498Z","iopub.status.idle":"2022-09-04T13:02:32.321477Z","shell.execute_reply.started":"2022-09-04T13:02:12.296457Z","shell.execute_reply":"2022-09-04T13:02:32.320490Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\ny_columns = np.load(\"../input/multimodal-single-cell-as-sparse-matrix/train_multi_targets_idxcol.npz\",\n                   allow_pickle=True)[\"columns\"]\n\ntest_index = np.load(\"../input/multimodal-single-cell-as-sparse-matrix/test_multi_inputs_idxcol.npz\",\n                    allow_pickle=True)[\"index\"]","metadata":{"execution":{"iopub.status.busy":"2022-09-04T13:02:32.323659Z","iopub.execute_input":"2022-09-04T13:02:32.324617Z","iopub.status.idle":"2022-09-04T13:02:32.412841Z","shell.execute_reply.started":"2022-09-04T13:02:32.324577Z","shell.execute_reply":"2022-09-04T13:02:32.411593Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cell_dict = dict((k,v) for v,k in enumerate(test_index)) \nassert len(cell_dict)  == len(test_index)\n\ngene_dict = dict((k,v) for v,k in enumerate(y_columns))\nassert len(gene_dict) == len(y_columns)\n\neval_ids_cell_num = eval_ids.cell_id.apply(lambda x:cell_dict.get(x, -1))\neval_ids_gene_num = eval_ids.gene_id.apply(lambda x:gene_dict.get(x, -1))\n\nvalid_multi_rows = (eval_ids_gene_num !=-1) & (eval_ids_cell_num!=-1)","metadata":{"execution":{"iopub.status.busy":"2022-09-04T13:02:32.415487Z","iopub.execute_input":"2022-09-04T13:02:32.415884Z","iopub.status.idle":"2022-09-04T13:02:35.498520Z","shell.execute_reply.started":"2022-09-04T13:02:32.415846Z","shell.execute_reply":"2022-09-04T13:02:35.497508Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"valid_multi_rows = valid_multi_rows.to_numpy()","metadata":{"execution":{"iopub.status.busy":"2022-09-04T13:02:35.503779Z","iopub.execute_input":"2022-09-04T13:02:35.504137Z","iopub.status.idle":"2022-09-04T13:02:35.512513Z","shell.execute_reply.started":"2022-09-04T13:02:35.504103Z","shell.execute_reply":"2022-09-04T13:02:35.511152Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"eval_ids_gene_num[valid_multi_rows].to_numpy()","metadata":{"execution":{"iopub.status.busy":"2022-09-04T13:02:35.514290Z","iopub.execute_input":"2022-09-04T13:02:35.516732Z","iopub.status.idle":"2022-09-04T13:02:37.183728Z","shell.execute_reply.started":"2022-09-04T13:02:35.516681Z","shell.execute_reply":"2022-09-04T13:02:37.182581Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission.iloc[valid_multi_rows] = test_pred[eval_ids_cell_num[valid_multi_rows].to_numpy(),\neval_ids_gene_num[valid_multi_rows].to_numpy()].cpu().numpy()\n\ndel eval_ids_cell_num, eval_ids_gene_num, valid_multi_rows, eval_ids, test_index, y_columns\ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2022-09-04T13:02:37.185339Z","iopub.execute_input":"2022-09-04T13:02:37.185734Z","iopub.status.idle":"2022-09-04T13:02:40.186917Z","shell.execute_reply.started":"2022-09-04T13:02:37.185699Z","shell.execute_reply":"2022-09-04T13:02:40.186004Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission","metadata":{"execution":{"iopub.status.busy":"2022-09-04T13:02:40.188218Z","iopub.execute_input":"2022-09-04T13:02:40.188606Z","iopub.status.idle":"2022-09-04T13:02:40.202991Z","shell.execute_reply.started":"2022-09-04T13:02:40.188569Z","shell.execute_reply":"2022-09-04T13:02:40.201741Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission.reset_index(drop=True, inplace=True)\nsubmission.index.name = 'row_id'\n","metadata":{"execution":{"iopub.status.busy":"2022-09-04T13:02:40.205453Z","iopub.execute_input":"2022-09-04T13:02:40.206230Z","iopub.status.idle":"2022-09-04T13:02:40.356240Z","shell.execute_reply.started":"2022-09-04T13:02:40.206194Z","shell.execute_reply":"2022-09-04T13:02:40.355148Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Merging in the CITEseq submission\n\nWe take the CITEseq results from [this notebook](https://www.kaggle.com/code/ambrosm/msci-citeseq-keras-quickstart/notebook) by AmbrosM.","metadata":{}},{"cell_type":"code","source":"cite_submission = pd.read_csv(\"../input/msci-citeseq-keras-quickstart/submission.csv\")\ncite_submission = cite_submission.set_index(\"row_id\")\ncite_submission = cite_submission[\"target\"]","metadata":{"execution":{"iopub.status.busy":"2022-09-04T13:02:40.361442Z","iopub.execute_input":"2022-09-04T13:02:40.362129Z","iopub.status.idle":"2022-09-04T13:03:02.045402Z","shell.execute_reply.started":"2022-09-04T13:02:40.362093Z","shell.execute_reply":"2022-09-04T13:03:02.044227Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission[submission.isnull()] = cite_submission[submission.isnull()]","metadata":{"execution":{"iopub.status.busy":"2022-09-04T13:03:02.047164Z","iopub.execute_input":"2022-09-04T13:03:02.047574Z","iopub.status.idle":"2022-09-04T13:03:03.834347Z","shell.execute_reply.started":"2022-09-04T13:03:02.047519Z","shell.execute_reply":"2022-09-04T13:03:03.833311Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission","metadata":{"execution":{"iopub.status.busy":"2022-09-04T13:03:03.836024Z","iopub.execute_input":"2022-09-04T13:03:03.838005Z","iopub.status.idle":"2022-09-04T13:03:03.848211Z","shell.execute_reply.started":"2022-09-04T13:03:03.837829Z","shell.execute_reply":"2022-09-04T13:03:03.847057Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission.isnull().any()","metadata":{"execution":{"iopub.status.busy":"2022-09-04T13:03:03.849838Z","iopub.execute_input":"2022-09-04T13:03:03.850465Z","iopub.status.idle":"2022-09-04T13:03:03.902620Z","shell.execute_reply.started":"2022-09-04T13:03:03.850426Z","shell.execute_reply":"2022-09-04T13:03:03.901603Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission.to_csv(\"submission.csv\")","metadata":{"execution":{"iopub.status.busy":"2022-09-04T13:03:03.904005Z","iopub.execute_input":"2022-09-04T13:03:03.904619Z","iopub.status.idle":"2022-09-04T13:05:03.305177Z","shell.execute_reply.started":"2022-09-04T13:03:03.904543Z","shell.execute_reply":"2022-09-04T13:05:03.304120Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!head submission.csv","metadata":{"execution":{"iopub.status.busy":"2022-09-04T13:05:03.307064Z","iopub.execute_input":"2022-09-04T13:05:03.307522Z","iopub.status.idle":"2022-09-04T13:05:04.349048Z","shell.execute_reply.started":"2022-09-04T13:05:03.307481Z","shell.execute_reply":"2022-09-04T13:05:04.347894Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}