{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceType":"competition","sourceId":20182,"databundleVersionId":1117628}],"dockerImageVersionId":31236,"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","trusted":true,"execution":{"iopub.status.busy":"2026-01-13T20:55:42.630060Z","iopub.execute_input":"2026-01-13T20:55:42.630609Z","iopub.status.idle":"2026-01-13T20:55:42.906310Z","shell.execute_reply.started":"2026-01-13T20:55:42.630582Z","shell.execute_reply":"2026-01-13T20:55:42.905683Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"\n- In the first notebook ([Gene Expression prediction (Baseline + 1D CNN)](http://www.kaggle.com/code/mariamali12/gene-expression-prediction-baseline-1d-cnn)), we built a 1D CNN model to predict the gene expression using histone markers as a feature.\n  \n- In the second notebook, [Gene Expression prediction (cell type feature)](http://www.kaggle.com/code/mariamali12/gene-expression-prediction-cell-type-feature), we extended our work and used cell type as an additional feature to improve the model performance\n\n- In this notebook, we will use the DNA sequence to see whether it has any effect on improving our model\n\n  ","metadata":{}},{"cell_type":"markdown","source":"### Training dataset structure:\n- **First column:** gene ID\n- **Second-sixth columns:** histone modification measurements\n- **Seventh column:** gene expression\n\n### Each cell type contains:\n- 16000 genes\n- 100 bins\n- 5 histone markers\n- Each gene–cell pair is treated as an independent training example.","metadata":{}},{"cell_type":"markdown","source":"# Libraries Importing ","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport tensorflow as tf\nfrom tensorflow.keras import layers, models\nfrom tensorflow.keras.callbacks import EarlyStopping\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.preprocessing import StandardScaler\nfrom sklearn.metrics import mean_squared_error, r2_score","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-13T20:55:42.907385Z","iopub.execute_input":"2026-01-13T20:55:42.907726Z","iopub.status.idle":"2026-01-13T20:55:46.347311Z","shell.execute_reply.started":"2026-01-13T20:55:42.907702Z","shell.execute_reply":"2026-01-13T20:55:46.346568Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#set random seed for reproducibility\n\nSEED = 42\nnp.random.seed(SEED)\ntf.random.set_seed(SEED)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-13T20:55:46.348267Z","iopub.execute_input":"2026-01-13T20:55:46.348835Z","iopub.status.idle":"2026-01-13T20:55:46.353385Z","shell.execute_reply.started":"2026-01-13T20:55:46.348803Z","shell.execute_reply":"2026-01-13T20:55:46.352075Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Load Training Data","metadata":{}},{"cell_type":"code","source":"#load training dataset\ntrain_data = np.load(\"/kaggle/input/gene-expression-prediction-cs1850-final/train.npz\")\n\ncells = list(train_data.keys())\ncell_to_id = {cell: i for i, cell in enumerate(cells)}","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-13T20:55:46.355209Z","iopub.execute_input":"2026-01-13T20:55:46.355561Z","iopub.status.idle":"2026-01-13T20:55:46.375931Z","shell.execute_reply.started":"2026-01-13T20:55:46.355528Z","shell.execute_reply":"2026-01-13T20:55:46.375209Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Extract data\nX_histone = [] \nX_cell = []\ny = []\ngene_ids = []\nfor cell in cells:\n    cell_array = train_data[cell]        \n    X_histone.append(cell_array[:, :, 1:6]) \n    y.append(cell_array[:, 0, 6])            \n    gene_ids.append(cell_array[:, 0, 0].astype(int))\n    X_cell.append(np.full(len(cell_array), cell_to_id[cell]))\nX_histone = np.concatenate(X_histone)\nX_cell = np.concatenate(X_cell)\ny = np.concatenate(y)\ngene_ids = np.concatenate(gene_ids)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-13T20:55:46.377099Z","iopub.execute_input":"2026-01-13T20:55:46.377460Z","iopub.status.idle":"2026-01-13T20:55:54.739803Z","shell.execute_reply.started":"2026-01-13T20:55:46.377430Z","shell.execute_reply":"2026-01-13T20:55:54.739150Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Train/val split","metadata":{}},{"cell_type":"code","source":"#using indices to split the data\nindices = np.arange(len(y))\n\ntrain_idx, val_idx = train_test_split(indices, test_size=0.2, random_state=SEED)\n\nXh_train, Xh_val = X_histone[train_idx], X_histone[val_idx]\nXc_train, Xc_val = X_cell[train_idx], X_cell[val_idx]\ny_train, y_val = y[train_idx], y[val_idx]\ngene_train, gene_val = gene_ids[train_idx], gene_ids[val_idx]\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-13T20:55:54.740803Z","iopub.execute_input":"2026-01-13T20:55:54.741108Z","iopub.status.idle":"2026-01-13T20:55:55.324596Z","shell.execute_reply.started":"2026-01-13T20:55:54.741078Z","shell.execute_reply":"2026-01-13T20:55:55.323770Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Scaling target","metadata":{}},{"cell_type":"code","source":"y_scaler = StandardScaler()\n\ny_train_scaled = y_scaler.fit_transform(y_train.reshape(-1,1)).ravel()\n\ny_val_scaled = y_scaler.transform(y_val.reshape(-1,1)).ravel()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-13T20:55:55.325461Z","iopub.execute_input":"2026-01-13T20:55:55.325729Z","iopub.status.idle":"2026-01-13T20:55:55.339348Z","shell.execute_reply.started":"2026-01-13T20:55:55.325707Z","shell.execute_reply":"2026-01-13T20:55:55.338858Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Loading Sequence Data ","metadata":{}},{"cell_type":"code","source":"seq_df = pd.read_csv(\"/kaggle/input/gene-expression-prediction-cs1850-final/seq_data.csv\",names=[\"gene_id\", \"sequence\"])\n\ngene_to_seq = dict(zip(seq_df.gene_id, seq_df.sequence))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-13T20:55:55.340375Z","iopub.execute_input":"2026-01-13T20:55:55.340656Z","iopub.status.idle":"2026-01-13T20:55:57.045595Z","shell.execute_reply.started":"2026-01-13T20:55:55.340623Z","shell.execute_reply":"2026-01-13T20:55:57.044978Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Creating fuction for sequence encoding\ndef encode_sequence(seq, max_len=1000):\n    mapping = {\"A\":0, \"C\":1, \"G\":2, \"T\":3}\n    encoded = np.zeros((max_len, 4), dtype=np.float32)\n\n    for i, base in enumerate(seq[:max_len]):\n        if base in mapping:\n            encoded[i, mapping[base]] = 1.0\n\n    return encoded","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-13T20:55:57.046375Z","iopub.execute_input":"2026-01-13T20:55:57.046614Z","iopub.status.idle":"2026-01-13T20:55:57.051412Z","shell.execute_reply.started":"2026-01-13T20:55:57.046593Z","shell.execute_reply":"2026-01-13T20:55:57.050638Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Building a class to extract a sequence into a generator\nclass SequenceDataGenerator(tf.keras.utils.Sequence):\n    def __init__(self, X_hist, X_cell, gene_ids, y,gene_to_seq, batch_size=32, shuffle=True):\n\n        self.X_hist = X_hist\n        self.X_cell = X_cell\n        self.gene_ids = gene_ids\n        self.y = y\n        self.gene_to_seq = gene_to_seq\n        self.batch_size = batch_size\n        self.shuffle = shuffle\n\n        self.indices = np.arange(len(y))\n        self.on_epoch_end()\n\n    def __len__(self):\n        return int(np.ceil(len(self.y) / self.batch_size))\n\n    def on_epoch_end(self):\n        if self.shuffle:\n            np.random.shuffle(self.indices)\n\n    def __getitem__(self, idx):\n        batch_idx = self.indices[\n            idx*self.batch_size:(idx+1)*self.batch_size\n        ]\n\n        Xh = self.X_hist[batch_idx]\n        Xc = self.X_cell[batch_idx]\n        yb = self.y[batch_idx]\n\n        Xs = np.array([\n            encode_sequence(self.gene_to_seq[g])\n            for g in self.gene_ids[batch_idx]\n        ])\n\n        return (Xh, Xs, Xc), yb","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-13T20:55:57.053452Z","iopub.execute_input":"2026-01-13T20:55:57.053693Z","iopub.status.idle":"2026-01-13T20:55:57.065687Z","shell.execute_reply.started":"2026-01-13T20:55:57.053673Z","shell.execute_reply":"2026-01-13T20:55:57.065159Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# instantiate the generator\ntrain_gen = SequenceDataGenerator(Xh_train, Xc_train, gene_train, y_train_scaled, gene_to_seq,batch_size=32)\nval_gen = SequenceDataGenerator(Xh_val, Xc_val, gene_val,y_val_scaled, gene_to_seq,batch_size=32, shuffle=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-13T20:55:57.066558Z","iopub.execute_input":"2026-01-13T20:55:57.066825Z","iopub.status.idle":"2026-01-13T20:55:57.098623Z","shell.execute_reply.started":"2026-01-13T20:55:57.066797Z","shell.execute_reply":"2026-01-13T20:55:57.097938Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Building Model","metadata":{}},{"cell_type":"code","source":"# Histone branch\nhist_in = layers.Input(shape=(100,5))\nh = layers.Conv1D(64, 5, activation=\"relu\", padding=\"same\")(hist_in)\nh = layers.GlobalAveragePooling1D()(h)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-13T20:55:57.099482Z","iopub.execute_input":"2026-01-13T20:55:57.099789Z","iopub.status.idle":"2026-01-13T20:55:58.147100Z","shell.execute_reply.started":"2026-01-13T20:55:57.099757Z","shell.execute_reply":"2026-01-13T20:55:58.146274Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Sequence branch\nseq_in = layers.Input(shape=(1000,4))\ns = layers.Conv1D(64, 7, activation=\"relu\", padding=\"same\")(seq_in)\ns = layers.MaxPooling1D(2)(s)\ns = layers.GlobalAveragePooling1D()(s)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-13T20:55:58.148326Z","iopub.execute_input":"2026-01-13T20:55:58.148947Z","iopub.status.idle":"2026-01-13T20:55:58.162868Z","shell.execute_reply.started":"2026-01-13T20:55:58.148914Z","shell.execute_reply":"2026-01-13T20:55:58.162255Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Cell embedding\ncell_in = layers.Input(shape=(1,))\nc = layers.Embedding(len(cells), 8)(cell_in)\nc = layers.Flatten()(c)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-13T20:55:58.163802Z","iopub.execute_input":"2026-01-13T20:55:58.164091Z","iopub.status.idle":"2026-01-13T20:55:58.175348Z","shell.execute_reply.started":"2026-01-13T20:55:58.164060Z","shell.execute_reply":"2026-01-13T20:55:58.174845Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Merge\nx = layers.Concatenate()([h, s, c])\nx = layers.Dense(128, activation=\"relu\")(x)\nx = layers.Dropout(0.3)(x)\nout = layers.Dense(1)(x)\n\nmodel = models.Model(inputs=[hist_in, seq_in, cell_in],outputs=out)\n\nmodel.compile(optimizer=tf.keras.optimizers.Adam(5e-4),loss=\"mse\")\n\nmodel.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-13T20:55:58.176302Z","iopub.execute_input":"2026-01-13T20:55:58.176754Z","iopub.status.idle":"2026-01-13T20:55:58.228592Z","shell.execute_reply.started":"2026-01-13T20:55:58.176718Z","shell.execute_reply":"2026-01-13T20:55:58.227936Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Train model\nhistory = model.fit(train_gen,validation_data=val_gen,batch_size=64,epochs=30,\n                    callbacks=[EarlyStopping(monitor=\"val_loss\", patience=5, restore_best_weights=True)])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-13T20:55:58.229467Z","iopub.execute_input":"2026-01-13T20:55:58.229749Z","iopub.status.idle":"2026-01-13T21:00:13.978474Z","shell.execute_reply.started":"2026-01-13T20:55:58.229722Z","shell.execute_reply":"2026-01-13T21:00:13.977263Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Evaluate the Model","metadata":{}},{"cell_type":"code","source":"y_pred_scaled = model.predict(val_gen).ravel()\n\ny_pred = y_scaler.inverse_transform(y_pred_scaled.reshape(-1,1)).ravel()\nprint(\"MSE:\", mean_squared_error(y_val, y_pred))\nprint(\"R²:\", r2_score(y_val, y_pred))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-13T21:00:13.979021Z","iopub.status.idle":"2026-01-13T21:00:13.979256Z","shell.execute_reply.started":"2026-01-13T21:00:13.979143Z","shell.execute_reply":"2026-01-13T21:00:13.979156Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}