{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":59094,"databundleVersionId":6541963,"sourceType":"competition"}],"dockerImageVersionId":30558,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-11-20T08:22:23.469496Z","iopub.execute_input":"2023-11-20T08:22:23.469874Z","iopub.status.idle":"2023-11-20T08:22:23.936681Z","shell.execute_reply.started":"2023-11-20T08:22:23.469842Z","shell.execute_reply":"2023-11-20T08:22:23.935387Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nfrom torch.utils.data import Dataset\nimport torch.nn as nn\nfrom torch.utils.data import DataLoader\nimport torch.optim.lr_scheduler as lr_scheduler\n\nfrom sklearn import preprocessing","metadata":{"execution":{"iopub.status.busy":"2023-11-20T08:22:23.941316Z","iopub.execute_input":"2023-11-20T08:22:23.941869Z","iopub.status.idle":"2023-11-20T08:22:29.415074Z","shell.execute_reply.started":"2023-11-20T08:22:23.941829Z","shell.execute_reply":"2023-11-20T08:22:29.413642Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"de_train = pd.read_parquet('../input/open-problems-single-cell-perturbations/de_train.parquet')\noutput_names = de_train.iloc[:,5:].columns.values.tolist()\nde_train","metadata":{"execution":{"iopub.status.busy":"2023-11-20T08:22:29.418040Z","iopub.execute_input":"2023-11-20T08:22:29.418767Z","iopub.status.idle":"2023-11-20T08:22:32.561016Z","shell.execute_reply.started":"2023-11-20T08:22:29.418720Z","shell.execute_reply":"2023-11-20T08:22:32.559634Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(list(de_train['cell_type'].unique()))\nprint(len(list(de_train['sm_name'].unique())))","metadata":{"execution":{"iopub.status.busy":"2023-11-20T08:22:32.563728Z","iopub.execute_input":"2023-11-20T08:22:32.564151Z","iopub.status.idle":"2023-11-20T08:22:32.574775Z","shell.execute_reply.started":"2023-11-20T08:22:32.564118Z","shell.execute_reply":"2023-11-20T08:22:32.573349Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"id_map = pd.read_csv('/kaggle/input/open-problems-single-cell-perturbations/id_map.csv',index_col=0)\nprint(list(id_map['cell_type'].unique()))\nprint(len(list(id_map['sm_name'].unique())))","metadata":{"execution":{"iopub.status.busy":"2023-11-20T08:22:32.576810Z","iopub.execute_input":"2023-11-20T08:22:32.577597Z","iopub.status.idle":"2023-11-20T08:22:32.602929Z","shell.execute_reply.started":"2023-11-20T08:22:32.577561Z","shell.execute_reply":"2023-11-20T08:22:32.601665Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Prepare data","metadata":{}},{"cell_type":"code","source":"encoder = preprocessing.LabelEncoder()","metadata":{"execution":{"iopub.status.busy":"2023-11-20T08:22:32.604734Z","iopub.execute_input":"2023-11-20T08:22:32.605232Z","iopub.status.idle":"2023-11-20T08:22:32.611081Z","shell.execute_reply.started":"2023-11-20T08:22:32.605190Z","shell.execute_reply":"2023-11-20T08:22:32.610047Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"de_train['cell_type_num'] = encoder.fit_transform(de_train['cell_type'])\nde_train['sm_name_num'] = encoder.fit_transform(de_train['sm_name'])\n#de_train['sm_lincs_id_num'] =encoder.fit_transform(de_train['sm_lincs_id'])\n#de_train['smiles_num'] =encoder.fit_transform(de_train['SMILES'])\n#de_train['control_num'] = encoder.fit_transform(de_train['control'])\nde_train.drop(['cell_type', 'sm_name', 'sm_lincs_id','SMILES','control'], axis = 1,inplace=True)\nde_train","metadata":{"execution":{"iopub.status.busy":"2023-11-20T08:22:32.612399Z","iopub.execute_input":"2023-11-20T08:22:32.613610Z","iopub.status.idle":"2023-11-20T08:22:32.703016Z","shell.execute_reply.started":"2023-11-20T08:22:32.613572Z","shell.execute_reply":"2023-11-20T08:22:32.701623Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predict_df = pd.DataFrame()\npredict_df['cell_type'] =encoder.fit_transform(id_map['cell_type'])\npredict_df['sm_name'] =encoder.fit_transform(id_map['sm_name'])\nprint(predict_df['cell_type'].unique())","metadata":{"execution":{"iopub.status.busy":"2023-11-20T08:22:32.704633Z","iopub.execute_input":"2023-11-20T08:22:32.705046Z","iopub.status.idle":"2023-11-20T08:22:32.722177Z","shell.execute_reply.started":"2023-11-20T08:22:32.705013Z","shell.execute_reply":"2023-11-20T08:22:32.719700Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n\nX_train, X_test, y_train, y_test = train_test_split(de_train.iloc[:,18211:18213], de_train.iloc[:,:18211], test_size=0.3, shuffle=True)","metadata":{"execution":{"iopub.status.busy":"2023-11-20T08:22:32.724760Z","iopub.execute_input":"2023-11-20T08:22:32.725370Z","iopub.status.idle":"2023-11-20T08:22:32.978209Z","shell.execute_reply.started":"2023-11-20T08:22:32.725319Z","shell.execute_reply":"2023-11-20T08:22:32.976495Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# make training and test sets in torch\n#train dataset - all dataset\nX_train = torch.from_numpy(de_train.iloc[:,18211:18213].values).type(torch.Tensor)\ny_train = torch.from_numpy(de_train.iloc[:,:18211].values).type(torch.Tensor)\n\nX_test = torch.from_numpy(X_test.values).type(torch.Tensor)\ny_test = torch.from_numpy(y_test.values).type(torch.Tensor)\n","metadata":{"execution":{"iopub.status.busy":"2023-11-20T08:22:57.271170Z","iopub.execute_input":"2023-11-20T08:22:57.271627Z","iopub.status.idle":"2023-11-20T08:22:57.382126Z","shell.execute_reply.started":"2023-11-20T08:22:57.271589Z","shell.execute_reply":"2023-11-20T08:22:57.380848Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(X_train.shape)\nprint(y_train.shape)\nprint(X_test.shape)\nprint(y_test.shape)","metadata":{"execution":{"iopub.status.busy":"2023-11-20T08:22:57.581805Z","iopub.execute_input":"2023-11-20T08:22:57.582247Z","iopub.status.idle":"2023-11-20T08:22:57.588957Z","shell.execute_reply.started":"2023-11-20T08:22:57.582214Z","shell.execute_reply":"2023-11-20T08:22:57.587759Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Create the model","metadata":{}},{"cell_type":"markdown","source":"### Model based on RNNs. \n#### I also added genes's values from input data as the additional input in my model. It necessary, because we had lack of data for good predictions.","metadata":{}},{"cell_type":"markdown","source":"![nn_2gru.png](attachment:4674c9bf-5297-47ec-9a08-2292a1e13d1a.png)","metadata":{},"attachments":{"4674c9bf-5297-47ec-9a08-2292a1e13d1a.png":{"image/png":"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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsARKj2CCpXerXQAAAABJRU5ErkJggg=="}}},{"cell_type":"code","source":"class MLR(nn.Module):\n    def __init__(self, hidden_dim, output_dim):\n        super (MLR, self).__init__()\n        \n        self.hidden_dim = hidden_dim\n        self.num_layers = 2\n        \n        self.gru1 = nn.GRU(2, hidden_dim, self.num_layers, dropout=0.25)\n        self.ln1 = nn.Linear(hidden_dim, output_dim)\n        \n        self.gru2 = nn.GRU(18211, hidden_dim, self.num_layers, dropout=0.4)\n        self.ln2 = nn.Linear(hidden_dim, output_dim)\n\n    def forward(self, x, genes):\n        \n        h0_1 = torch.zeros(self.num_layers, self.hidden_dim).requires_grad_()\n        out1,_ = self.gru1(x, h0_1.detach())\n        out1 = self.ln1(out1)\n        \n        h0_2 = torch.zeros(self.num_layers, self.hidden_dim).requires_grad_()\n        out2,_ = self.gru2(genes, h0_2.detach())\n        out2 = self.ln2(out2)\n\n        out = out1+out2\n        return out","metadata":{"execution":{"iopub.status.busy":"2023-11-20T08:22:59.124795Z","iopub.execute_input":"2023-11-20T08:22:59.126107Z","iopub.status.idle":"2023-11-20T08:22:59.135918Z","shell.execute_reply.started":"2023-11-20T08:22:59.126064Z","shell.execute_reply":"2023-11-20T08:22:59.135023Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = MLR(16, 18211)","metadata":{"execution":{"iopub.status.busy":"2023-11-20T08:22:59.489715Z","iopub.execute_input":"2023-11-20T08:22:59.490592Z","iopub.status.idle":"2023-11-20T08:22:59.524418Z","shell.execute_reply.started":"2023-11-20T08:22:59.490556Z","shell.execute_reply":"2023-11-20T08:22:59.523262Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"torch.save(model, 'single_cell_perturdations.pth')\nprint(model)","metadata":{"execution":{"iopub.status.busy":"2023-11-20T08:22:59.897073Z","iopub.execute_input":"2023-11-20T08:22:59.897483Z","iopub.status.idle":"2023-11-20T08:22:59.916574Z","shell.execute_reply.started":"2023-11-20T08:22:59.897447Z","shell.execute_reply":"2023-11-20T08:22:59.915036Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Train the model","metadata":{}},{"cell_type":"code","source":"import torch.optim as optim\noptimizer = optim.Adam(model.parameters(), lr = 0.05)\nloss = torch.nn.L1Loss(reduction='mean')","metadata":{"execution":{"iopub.status.busy":"2023-11-20T08:23:00.731996Z","iopub.execute_input":"2023-11-20T08:23:00.732775Z","iopub.status.idle":"2023-11-20T08:23:00.739819Z","shell.execute_reply.started":"2023-11-20T08:23:00.732716Z","shell.execute_reply":"2023-11-20T08:23:00.738561Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train_model(x_train, y_train, model, loss_function, optimizer):\n    num_batches = len(x_train)\n    total_loss = 0\n    scheduler = lr_scheduler.ExponentialLR(optimizer, gamma = 0.9)\n    model.train()\n\n    output = model(x_train, y_train)\n    loss = loss_function(output, y_train)\n\n    optimizer.zero_grad()\n    loss.backward()\n    optimizer.step()\n\n    total_loss += loss.item()\n\n    avg_loss = total_loss / num_batches\n    \n    #oprimize learning rate\n    before_lr = optimizer.param_groups[0][\"lr\"]\n    scheduler.step()\n    after_lr = optimizer.param_groups[0][\"lr\"]\n    print(f\"Train loss: {avg_loss}\\n Learning rate: {before_lr} -> {after_lr}\\n\")","metadata":{"execution":{"iopub.status.busy":"2023-11-20T08:23:01.222881Z","iopub.execute_input":"2023-11-20T08:23:01.223900Z","iopub.status.idle":"2023-11-20T08:23:01.232587Z","shell.execute_reply.started":"2023-11-20T08:23:01.223859Z","shell.execute_reply":"2023-11-20T08:23:01.231314Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def test_model(x_test, y_test, model):\n    num_batches = len(x_test)\n    total_loss = 0\n    model.eval()\n    with torch.no_grad():\n        output = model(x_test, y_test)\n        \n        total_loss += np.abs(output - y_test).mean()\n        \n        # Calculate Mean Rowwise Root Mean Squared Error (MRRMSE)\n        output = output.numpy().reshape(x_test.size(0), -1)\n        y_test = y_test.numpy().reshape(y_test.size(0), -1)\n        mrrmse_score = np.sqrt(np.square(y_test - output).mean(axis=1)).mean()\n\n    avg_loss = total_loss / num_batches\n    print(f\"Test loss: {avg_loss}\\n MRRMSE = {mrrmse_score}\\n\")\n    return mrrmse_score","metadata":{"execution":{"iopub.status.busy":"2023-11-20T08:23:01.748202Z","iopub.execute_input":"2023-11-20T08:23:01.748750Z","iopub.status.idle":"2023-11-20T08:23:01.759846Z","shell.execute_reply.started":"2023-11-20T08:23:01.748715Z","shell.execute_reply":"2023-11-20T08:23:01.758236Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mrrmse_list = []\nfor ix_epoch in range(20):\n    print(f\"Epoch {ix_epoch}\\n---------\")\n    train_model(X_train, y_train, model, loss, optimizer)\n    mrrmse_score = test_model(X_test, y_test, model)\n    mrrmse_list.append(mrrmse_score)","metadata":{"execution":{"iopub.status.busy":"2023-11-20T08:23:03.385825Z","iopub.execute_input":"2023-11-20T08:23:03.386331Z","iopub.status.idle":"2023-11-20T08:23:23.528283Z","shell.execute_reply.started":"2023-11-20T08:23:03.386297Z","shell.execute_reply":"2023-11-20T08:23:23.526836Z"},"collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Predict","metadata":{}},{"cell_type":"code","source":"inputs = torch.from_numpy(predict_df.values).type(torch.Tensor)\ny_pred_tensor = model(inputs, y_train[:inputs.shape[0]])\ny_pred = y_pred_tensor.detach().cpu().numpy()","metadata":{"execution":{"iopub.status.busy":"2023-11-20T08:24:45.933269Z","iopub.execute_input":"2023-11-20T08:24:45.933854Z","iopub.status.idle":"2023-11-20T08:24:46.091991Z","shell.execute_reply.started":"2023-11-20T08:24:45.933811Z","shell.execute_reply":"2023-11-20T08:24:46.091022Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"solution = pd.DataFrame(y_pred,index=id_map.index, columns=output_names)\nprint(solution.info())\nsolution","metadata":{"execution":{"iopub.status.busy":"2023-11-20T08:24:46.453679Z","iopub.execute_input":"2023-11-20T08:24:46.454447Z","iopub.status.idle":"2023-11-20T08:24:47.877397Z","shell.execute_reply.started":"2023-11-20T08:24:46.454388Z","shell.execute_reply":"2023-11-20T08:24:47.876430Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"solution.to_csv('submission.csv')","metadata":{"execution":{"iopub.status.busy":"2023-11-20T08:24:47.879066Z","iopub.execute_input":"2023-11-20T08:24:47.879888Z","iopub.status.idle":"2023-11-20T08:24:57.303761Z","shell.execute_reply.started":"2023-11-20T08:24:47.879855Z","shell.execute_reply":"2023-11-20T08:24:57.302431Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Analyse the results","metadata":{}},{"cell_type":"code","source":"print(f\"We have: {solution.isnull().sum().unique()} NaN values\")","metadata":{"execution":{"iopub.status.busy":"2023-11-20T08:24:57.305388Z","iopub.execute_input":"2023-11-20T08:24:57.306136Z","iopub.status.idle":"2023-11-20T08:24:57.324828Z","shell.execute_reply.started":"2023-11-20T08:24:57.306092Z","shell.execute_reply":"2023-11-20T08:24:57.323540Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predict_mean_values = []\ninput_mean_values = []\nfor i in output_names:\n    input_mean_values.append(de_train[i].mean())\n    predict_mean_values.append(solution[i].mean())","metadata":{"execution":{"iopub.status.busy":"2023-11-20T08:24:57.329596Z","iopub.execute_input":"2023-11-20T08:24:57.331162Z","iopub.status.idle":"2023-11-20T08:25:02.018710Z","shell.execute_reply.started":"2023-11-20T08:24:57.331119Z","shell.execute_reply":"2023-11-20T08:25:02.017486Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"corr_coef = np.corrcoef(np.asarray(input_mean_values), np.asarray(predict_mean_values))\nprint(f\"Corellation between input and predict mean values is {corr_coef[0,1]}\")","metadata":{"execution":{"iopub.status.busy":"2023-11-20T08:25:02.020243Z","iopub.execute_input":"2023-11-20T08:25:02.021025Z","iopub.status.idle":"2023-11-20T08:25:02.035765Z","shell.execute_reply.started":"2023-11-20T08:25:02.020983Z","shell.execute_reply":"2023-11-20T08:25:02.034485Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.DataFrame({'input_mean_values' : input_mean_values,\n                   'predict_mean_values' : predict_mean_values})\ndf.head(5)","metadata":{"execution":{"iopub.status.busy":"2023-11-20T08:25:02.037062Z","iopub.execute_input":"2023-11-20T08:25:02.037404Z","iopub.status.idle":"2023-11-20T08:25:02.068491Z","shell.execute_reply.started":"2023-11-20T08:25:02.037377Z","shell.execute_reply":"2023-11-20T08:25:02.067216Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Visualisation","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport seaborn as sns","metadata":{"execution":{"iopub.status.busy":"2023-11-20T08:25:10.040846Z","iopub.execute_input":"2023-11-20T08:25:10.041309Z","iopub.status.idle":"2023-11-20T08:25:10.418838Z","shell.execute_reply.started":"2023-11-20T08:25:10.041275Z","shell.execute_reply":"2023-11-20T08:25:10.417535Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.plot(mrrmse_list)\nplt.xlabel('Iterations')\nplt.ylabel('MRRMSE')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-11-20T08:25:10.559807Z","iopub.execute_input":"2023-11-20T08:25:10.561283Z","iopub.status.idle":"2023-11-20T08:25:10.884515Z","shell.execute_reply.started":"2023-11-20T08:25:10.561231Z","shell.execute_reply":"2023-11-20T08:25:10.883275Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"corr = sns.scatterplot(x=\"input_mean_values\", y=\"predict_mean_values\", data=df)\ncorr.set(title = 'Correlation between mean values of all 18211 genes')","metadata":{"execution":{"iopub.status.busy":"2023-11-20T08:25:12.177040Z","iopub.execute_input":"2023-11-20T08:25:12.177541Z","iopub.status.idle":"2023-11-20T08:25:12.712054Z","shell.execute_reply.started":"2023-11-20T08:25:12.177497Z","shell.execute_reply":"2023-11-20T08:25:12.711041Z"},"trusted":true},"execution_count":null,"outputs":[]}]}