{"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":"### Stanford Ribonanza RNA Folding Challange\nPS: I am not an an expert, I am doing some chatgpt google research to possible solutions or baseline to such problem, my background in Physics but always loved biology too. \nMy main motivation to learn and provide simple starter code for people\n\n- Tasks: apply GNNs","metadata":{}},{"cell_type":"code","source":"import tqdm\nimport pandas as pd \nimport os \nfrom tqdm import tqdm as tq\nfrom collections import defaultdict\nimport numpy as np\nimport multiprocessing","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-10-19T18:28:26.330472Z","iopub.execute_input":"2023-10-19T18:28:26.330857Z","iopub.status.idle":"2023-10-19T18:28:26.599725Z","shell.execute_reply.started":"2023-10-19T18:28:26.330832Z","shell.execute_reply":"2023-10-19T18:28:26.598820Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"let's read sample data","metadata":{}},{"cell_type":"code","source":"test = pd.read_csv('/kaggle/input/stanford-ribonanza-rna-folding/test_sequences.csv')[:20000]\ntrain = pd.read_csv('/kaggle/input/stanford-ribonanza-rna-folding/train_data.csv')[:100000]\ntrain.head()","metadata":{"execution":{"iopub.status.busy":"2023-10-19T18:28:26.601698Z","iopub.execute_input":"2023-10-19T18:28:26.602225Z","iopub.status.idle":"2023-10-19T18:29:54.132243Z","shell.execute_reply.started":"2023-10-19T18:28:26.602190Z","shell.execute_reply":"2023-10-19T18:29:54.131294Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.info()","metadata":{"execution":{"iopub.status.busy":"2023-10-19T18:29:54.133226Z","iopub.execute_input":"2023-10-19T18:29:54.133463Z","iopub.status.idle":"2023-10-19T18:29:54.166211Z","shell.execute_reply.started":"2023-10-19T18:29:54.133443Z","shell.execute_reply":"2023-10-19T18:29:54.165499Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def reduce_dataframe_size(df):\n    # Make a copy of the DataFrame to avoid modifying the original\n    df_copy = df.copy()\n\n    # Define a mapping of column names to more memory-efficient data types\n    column_type_mapping = {}\n\n    for column in df_copy.columns:\n        dtype = df_copy[column].dtype\n\n        if dtype == 'object':\n            # Handle object columns (e.g., strings)\n            unique_values = df_copy[column].nunique()\n\n            if unique_values == 1:\n                # If a column has only one unique value, convert it to the appropriate data type\n                if 'int' in dtype.name:\n                    column_type_mapping[column] = 'int64'\n                elif 'float' in dtype.name:\n                    column_type_mapping[column] = 'float64'\n                elif 'datetime' in dtype.name:\n                    column_type_mapping[column] = 'datetime64'\n                else:\n                    column_type_mapping[column] = 'category'\n            elif unique_values < len(df_copy) / 2:\n                # If a column has less than half unique values, convert it to category\n                column_type_mapping[column] = 'category'\n        elif dtype == 'float64':\n            # Reduce float64 columns to float32 or float16\n            column_type_mapping[column] = 'float32'\n        elif dtype == 'int64':\n            # Reduce int64 columns to int32 or int16\n            column_type_mapping[column] = 'int32'\n        elif dtype == 'datetime64':\n            # Reduce datetime64 columns to datetime32\n            column_type_mapping[column] = 'datetime32'\n    \n    # Apply the data type conversions based on the mapping\n    df_copy = df_copy.astype(column_type_mapping)\n\n    return df_copy\nreduced_train = reduce_dataframe_size(train)","metadata":{"execution":{"iopub.status.busy":"2023-10-19T18:29:54.167276Z","iopub.execute_input":"2023-10-19T18:29:54.167589Z","iopub.status.idle":"2023-10-19T18:29:54.472166Z","shell.execute_reply.started":"2023-10-19T18:29:54.167560Z","shell.execute_reply":"2023-10-19T18:29:54.471427Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test.info()","metadata":{"execution":{"iopub.status.busy":"2023-10-19T18:29:54.474098Z","iopub.execute_input":"2023-10-19T18:29:54.474343Z","iopub.status.idle":"2023-10-19T18:29:54.485949Z","shell.execute_reply.started":"2023-10-19T18:29:54.474322Z","shell.execute_reply":"2023-10-19T18:29:54.485163Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"reduced_test = reduce_dataframe_size(test)\nreduced_test.info()","metadata":{"execution":{"iopub.status.busy":"2023-10-19T18:29:54.486921Z","iopub.execute_input":"2023-10-19T18:29:54.487198Z","iopub.status.idle":"2023-10-19T18:29:54.522057Z","shell.execute_reply.started":"2023-10-19T18:29:54.487178Z","shell.execute_reply":"2023-10-19T18:29:54.521370Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.info()","metadata":{"execution":{"iopub.status.busy":"2023-10-19T18:29:54.522774Z","iopub.execute_input":"2023-10-19T18:29:54.523010Z","iopub.status.idle":"2023-10-19T18:29:54.635348Z","shell.execute_reply.started":"2023-10-19T18:29:54.522983Z","shell.execute_reply":"2023-10-19T18:29:54.634346Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"reduced_train.info()","metadata":{"execution":{"iopub.status.busy":"2023-10-19T18:29:54.636403Z","iopub.execute_input":"2023-10-19T18:29:54.636673Z","iopub.status.idle":"2023-10-19T18:29:54.656800Z","shell.execute_reply.started":"2023-10-19T18:29:54.636652Z","shell.execute_reply":"2023-10-19T18:29:54.656021Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"reduced_train","metadata":{"execution":{"iopub.status.busy":"2023-10-19T18:29:54.657889Z","iopub.execute_input":"2023-10-19T18:29:54.658249Z","iopub.status.idle":"2023-10-19T18:29:54.716209Z","shell.execute_reply.started":"2023-10-19T18:29:54.658219Z","shell.execute_reply":"2023-10-19T18:29:54.715306Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Getting txt file as a single dataframe which is base-pairing probability matrix of each sequences in our train and test dataset. Definition:\n- **A base-pairing probability matrix** (BPPM) stores the probabilities for every possible base pair in an RNA sequence and has been used in many algorithms in RNA informatics (e.g., RNA secondary structure prediction and motif search). [source](http://www.ncbi.nlm.nih.gov/pmc/articles/PMC3514005/)\n","metadata":{}},{"cell_type":"code","source":"root_dir = '/kaggle/input/stanford-ribonanza-rna-folding/Ribonanza_bpp_files/extra_data'\nfile_paths = []\nfor folder, _, files in tq(os.walk(root_dir), total=len(os.listdir(root_dir))):\n    for file in files:\n        file_paths.append(os.path.join(folder, file))\n# Now, file_paths contains the list of all file paths within the specified directory and its subdirectories.","metadata":{"execution":{"iopub.status.busy":"2023-10-19T18:29:54.717166Z","iopub.execute_input":"2023-10-19T18:29:54.717394Z","iopub.status.idle":"2023-10-19T18:40:06.900298Z","shell.execute_reply.started":"2023-10-19T18:29:54.717375Z","shell.execute_reply":"2023-10-19T18:40:06.899510Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- filter sequences only in dataset","metadata":{}},{"cell_type":"code","source":"import os\nfrom concurrent.futures import ThreadPoolExecutor\nfrom tqdm import tqdm\n\n# Get unique sequence_id values from both dataframes\nunique_sequence_ids = set(reduced_train['sequence_id']) | set(reduced_test['sequence_id'])\n\n# Convert file_paths to a set for faster lookup\nfile_paths_set = set(file_paths)\n\n# Function to filter file paths\ndef filter_file_path(filepath):\n    return os.path.splitext(os.path.basename(filepath))[0] in unique_sequence_ids\n\n# Initialize tqdm with the total number of file paths\nwith ThreadPoolExecutor() as executor, tqdm(total=len(file_paths_set), desc=\"Filtering Files\") as pbar:\n    # Filter file paths using parallel processing\n    filtered_file_paths = list(filter(filter_file_path, file_paths_set))\n    pbar.update(len(filtered_file_paths))  # Update the progress bar to completion\n","metadata":{"execution":{"iopub.status.busy":"2023-10-19T18:40:06.901502Z","iopub.execute_input":"2023-10-19T18:40:06.901778Z","iopub.status.idle":"2023-10-19T18:40:11.288065Z","shell.execute_reply.started":"2023-10-19T18:40:06.901754Z","shell.execute_reply":"2023-10-19T18:40:11.287196Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- We can get avarage of probability for each sequence_id","metadata":{}},{"cell_type":"code","source":"# Create a defaultdict to store sequence_id and their corresponding probabilities\nsequence_probabilities = defaultdict(list)\n\n# Initialize tqdm with the list of text files\nwith tq(total=len(filtered_file_paths), desc=\"Processing Files\") as pbar:\n    # Iterate through each file path\n    for filepath in filtered_file_paths:\n        with open(filepath, \"r\") as file:\n            for line in file:\n                # Split each line into values\n                values = line.strip().split()  # Split based on spaces\n\n                # Ensure that there are at least 3 values (pair1, pair2, probability)\n                if len(values) < 3:\n                    continue\n\n                # Extract pair1, pair2, and probability\n                _, _, probability = values[:3]\n\n                # Use the filename (without extension) as the key\n                sequence_id = os.path.splitext(os.path.basename(filepath))[0]\n\n                # Append the probability to the list for the sequence_id\n                sequence_probabilities[sequence_id].append(float(probability))\n\n        pbar.update(1)  # Update the progress bar\n\n# Calculate the average probability for each sequence_id\naverage_probabilities = {}\nfor sequence_id, probabilities in sequence_probabilities.items():\n    average_prob = sum(probabilities) / len(probabilities)\n    average_probabilities[sequence_id] = average_prob","metadata":{"execution":{"iopub.status.busy":"2023-10-19T18:40:11.289220Z","iopub.execute_input":"2023-10-19T18:40:11.289549Z","iopub.status.idle":"2023-10-19T18:58:42.574161Z","shell.execute_reply.started":"2023-10-19T18:40:11.289518Z","shell.execute_reply":"2023-10-19T18:58:42.573017Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"delete some memory","metadata":{}},{"cell_type":"code","source":"del train\ndel test\ndel file_paths\ndel filtered_file_paths\ndel sequence_probabilities","metadata":{"execution":{"iopub.status.busy":"2023-10-19T18:58:42.575445Z","iopub.execute_input":"2023-10-19T18:58:42.575807Z","iopub.status.idle":"2023-10-19T18:58:44.998239Z","shell.execute_reply.started":"2023-10-19T18:58:42.575773Z","shell.execute_reply":"2023-10-19T18:58:44.997153Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- Adding average probability to train and test dataset and drop null columns","metadata":{}},{"cell_type":"code","source":"avg_p = pd.DataFrame(average_probabilities, index=[0]).T.reset_index()\navg_p.columns = ['sequence_id', 'avg_probability']\nreduced_train_new  = reduced_train.merge(avg_p, on='sequence_id', how='left').dropna(axis=1,how='all')\nreduced_test_new  = reduced_test.merge(avg_p, on='sequence_id', how='left').dropna(axis=1,how='all')","metadata":{"execution":{"iopub.status.busy":"2023-10-19T18:58:45.002194Z","iopub.execute_input":"2023-10-19T18:58:45.002458Z","iopub.status.idle":"2023-10-19T18:58:46.357638Z","shell.execute_reply.started":"2023-10-19T18:58:45.002436Z","shell.execute_reply":"2023-10-19T18:58:46.356893Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"del reduced_train\ndel reduced_test\ndel average_probabilities\ndel avg_p","metadata":{"execution":{"iopub.status.busy":"2023-10-19T18:58:46.358691Z","iopub.execute_input":"2023-10-19T18:58:46.358966Z","iopub.status.idle":"2023-10-19T18:58:46.372180Z","shell.execute_reply.started":"2023-10-19T18:58:46.358943Z","shell.execute_reply":"2023-10-19T18:58:46.371106Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"reduced_train_new","metadata":{"execution":{"iopub.status.busy":"2023-10-19T18:58:46.373568Z","iopub.execute_input":"2023-10-19T18:58:46.373792Z","iopub.status.idle":"2023-10-19T18:58:46.436232Z","shell.execute_reply.started":"2023-10-19T18:58:46.373773Z","shell.execute_reply":"2023-10-19T18:58:46.435325Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"reduced_test_new","metadata":{"execution":{"iopub.status.busy":"2023-10-19T18:58:46.437377Z","iopub.execute_input":"2023-10-19T18:58:46.437715Z","iopub.status.idle":"2023-10-19T18:58:46.449625Z","shell.execute_reply.started":"2023-10-19T18:58:46.437691Z","shell.execute_reply":"2023-10-19T18:58:46.448767Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- Folding RNA structures, using swifter for faster apply.","metadata":{}},{"cell_type":"code","source":"!pip install viennarna\n!pip install swifter","metadata":{"execution":{"iopub.status.busy":"2023-10-19T18:58:46.450627Z","iopub.execute_input":"2023-10-19T18:58:46.450891Z","iopub.status.idle":"2023-10-19T18:59:06.816976Z","shell.execute_reply.started":"2023-10-19T18:58:46.450859Z","shell.execute_reply":"2023-10-19T18:59:06.815804Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from ViennaRNA import fold\nimport swifter","metadata":{"execution":{"iopub.status.busy":"2023-10-19T18:59:06.818430Z","iopub.execute_input":"2023-10-19T18:59:06.818724Z","iopub.status.idle":"2023-10-19T18:59:10.423600Z","shell.execute_reply.started":"2023-10-19T18:59:06.818700Z","shell.execute_reply":"2023-10-19T18:59:10.422915Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with tq(total=len(reduced_train_new), desc=\"Processing Data\") as pbar:\n    reduced_train_new['complex_structure_features'] = reduced_train_new['sequence'].swifter.apply(fold)\n    pbar.update(len(reduced_train_new))","metadata":{"execution":{"iopub.status.busy":"2023-10-19T18:59:10.424614Z","iopub.execute_input":"2023-10-19T18:59:10.425038Z","iopub.status.idle":"2023-10-19T19:34:01.933627Z","shell.execute_reply.started":"2023-10-19T18:59:10.425013Z","shell.execute_reply":"2023-10-19T19:34:01.911093Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with tq(total=len(reduced_test_new), desc=\"Processing Data\") as pbar:\n    reduced_test_new['complex_structure_features'] = reduced_test_new['sequence'].swifter.apply(fold)\n    pbar.update(len(reduced_test_new))","metadata":{"execution":{"iopub.status.busy":"2023-10-19T19:34:01.934834Z","iopub.execute_input":"2023-10-19T19:34:01.935184Z","iopub.status.idle":"2023-10-19T19:41:41.552018Z","shell.execute_reply.started":"2023-10-19T19:34:01.935153Z","shell.execute_reply":"2023-10-19T19:41:41.541595Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install forgi\nimport forgi.visual.mplotlib as fvm\nimport forgi.graph.bulge_graph as fgb\nimport random\nimport matplotlib.pyplot as plt\n\n# Number of random structures to plot\nnum_structures_to_plot = 5\n\n# Get random indices from your DataFrame\nrandom_indices = random.sample(range(len(reduced_train_new)), num_structures_to_plot)\n\n# Create subplots for each structure\nplt.figure(figsize=(15, 5 * num_structures_to_plot))\n\nfor i, idx in enumerate(random_indices, 1):\n    structure = reduced_train_new['complex_structure_features'][idx][0]\n    sequence = reduced_train_new['sequence'][idx]\n\n    plt.subplot(num_structures_to_plot, 1, i)\n    bg = fgb.BulgeGraph.from_fasta_text(f'>rna{idx}\\n{structure}\\n{sequence}')[0]\n    fvm.plot_rna(bg, lighten=0.5, text_kwargs={\"fontweight\": None})\n    plt.title(f\"RNA Structure {idx}\")\n\nplt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-10-19T19:41:41.553238Z","iopub.execute_input":"2023-10-19T19:41:41.553584Z","iopub.status.idle":"2023-10-19T19:41:59.579620Z","shell.execute_reply.started":"2023-10-19T19:41:41.553543Z","shell.execute_reply":"2023-10-19T19:41:59.578866Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Function to count parentheses\ndef count_parentheses(structure_string):\n    count = structure_string.count(\")\")\n    return count\n\n# Apply the function to the DataFrame column\n\ntq.pandas()\nreduced_train_new['parentheses_counts'] = reduced_train_new['complex_structure_features'].astype(str).apply(count_parentheses)\nreduced_test_new['parentheses_counts'] = reduced_test_new['complex_structure_features'].astype(str).apply(count_parentheses)\n","metadata":{"execution":{"iopub.status.busy":"2023-10-19T19:41:59.581105Z","iopub.execute_input":"2023-10-19T19:41:59.581432Z","iopub.status.idle":"2023-10-19T19:41:59.877398Z","shell.execute_reply.started":"2023-10-19T19:41:59.581405Z","shell.execute_reply":"2023-10-19T19:41:59.876518Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"reduced_train_new = reduced_train_new.drop(columns=reduced_train_new.filter(like='error').columns)","metadata":{"execution":{"iopub.status.busy":"2023-10-19T19:41:59.878429Z","iopub.execute_input":"2023-10-19T19:41:59.878667Z","iopub.status.idle":"2023-10-19T19:41:59.983068Z","shell.execute_reply.started":"2023-10-19T19:41:59.878647Z","shell.execute_reply":"2023-10-19T19:41:59.982429Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"reactivity_columns = reduced_train_new.columns[reduced_train_new.columns.str.startswith('reactivity_0')]\nreduced_train_new['mean_reacs'] = reduced_train_new[reactivity_columns].mean(axis=1)\nreduced_train_new = reduced_train_new.drop(columns=reactivity_columns)","metadata":{"execution":{"iopub.status.busy":"2023-10-19T19:41:59.984186Z","iopub.execute_input":"2023-10-19T19:41:59.984500Z","iopub.status.idle":"2023-10-19T19:42:00.158825Z","shell.execute_reply.started":"2023-10-19T19:41:59.984471Z","shell.execute_reply":"2023-10-19T19:42:00.157874Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"reduced_train_new","metadata":{"execution":{"iopub.status.busy":"2023-10-19T19:42:00.160068Z","iopub.execute_input":"2023-10-19T19:42:00.160360Z","iopub.status.idle":"2023-10-19T19:42:00.182220Z","shell.execute_reply.started":"2023-10-19T19:42:00.160337Z","shell.execute_reply":"2023-10-19T19:42:00.181317Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"reduced_test_new","metadata":{"execution":{"iopub.status.busy":"2023-10-19T19:42:00.183436Z","iopub.execute_input":"2023-10-19T19:42:00.183764Z","iopub.status.idle":"2023-10-19T19:42:00.199553Z","shell.execute_reply.started":"2023-10-19T19:42:00.183734Z","shell.execute_reply":"2023-10-19T19:42:00.198702Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"index_cols = ['sequence_id', 'sequence','dataset_name', 'reads',\n       'signal_to_noise', 'SN_filter', 'avg_probability',\n      'complex_structure_features', 'parentheses_counts']\n\n# Convert lists in index_cols to tuples\nreduced_train_new['complex_structure_features'] = reduced_train_new['complex_structure_features'].apply(tuple)\nreduced_train_new_pivoted = pd.pivot(reduced_train_new, index=index_cols, columns='experiment_type', values='mean_reacs').reset_index()\nreduced_train_new_pivoted[\"DMS_MaP_s\"] = reduced_train_new_pivoted[\"DMS_MaP\"].shift(-1)\nreduced_train_new_pivoted.drop('DMS_MaP', axis=1, inplace=True)\nreduced_train_new_pivoted.dropna(axis=0, inplace=True)","metadata":{"execution":{"iopub.status.busy":"2023-10-19T19:42:00.200628Z","iopub.execute_input":"2023-10-19T19:42:00.200936Z","iopub.status.idle":"2023-10-19T19:42:00.765990Z","shell.execute_reply.started":"2023-10-19T19:42:00.200908Z","shell.execute_reply":"2023-10-19T19:42:00.765292Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"del reduced_train_new","metadata":{"execution":{"iopub.status.busy":"2023-10-19T19:42:00.767085Z","iopub.execute_input":"2023-10-19T19:42:00.767358Z","iopub.status.idle":"2023-10-19T19:42:00.771586Z","shell.execute_reply.started":"2023-10-19T19:42:00.767331Z","shell.execute_reply":"2023-10-19T19:42:00.770657Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"reduced_train_new_pivoted","metadata":{"execution":{"iopub.status.busy":"2023-10-19T19:42:00.772521Z","iopub.execute_input":"2023-10-19T19:42:00.772727Z","iopub.status.idle":"2023-10-19T19:42:00.796763Z","shell.execute_reply.started":"2023-10-19T19:42:00.772709Z","shell.execute_reply":"2023-10-19T19:42:00.796034Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def encode_nucleotide(nucleotide):\n    mapping = {'A': [1, 0, 0, 0],\n               'U': [0, 1, 0, 0],\n               'G': [0, 0, 1, 0],\n               'C': [0, 0, 0, 1]}\n    return mapping[nucleotide]\n\ndef encode_sequence(sequence):\n    return [encode_nucleotide(n) for n in sequence]\ndef flatten_extend(matrix):\n    flat_list = []\n    for row in matrix:\n        flat_list.extend(row)\n    return flat_list\n\nreduced_train_new_pivoted['encoded_sequence'] = reduced_train_new_pivoted['sequence'].apply(encode_sequence).apply(flatten_extend)","metadata":{"execution":{"iopub.status.busy":"2023-10-19T19:42:00.797841Z","iopub.execute_input":"2023-10-19T19:42:00.798198Z","iopub.status.idle":"2023-10-19T19:42:07.750381Z","shell.execute_reply.started":"2023-10-19T19:42:00.798168Z","shell.execute_reply":"2023-10-19T19:42:07.749479Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"reduced_test_new['encoded_sequence'] = reduced_test_new['sequence'].apply(encode_sequence).apply(flatten_extend)","metadata":{"execution":{"iopub.status.busy":"2023-10-19T19:42:07.751568Z","iopub.execute_input":"2023-10-19T19:42:07.752003Z","iopub.status.idle":"2023-10-19T19:42:12.969403Z","shell.execute_reply.started":"2023-10-19T19:42:07.751947Z","shell.execute_reply":"2023-10-19T19:42:12.968679Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch.nn as nn\nimport torch\nimport torch.optim as optim\nfrom torch.nn.utils.rnn import pad_sequence\nfrom torch.utils.data import DataLoader, TensorDataset, random_split\n\ndevice = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n\n\nclass RNASeq2SeqModel(nn.Module):\n    def __init__(self, embedding_dim, hidden_dim, num_layers):\n        super(RNASeq2SeqModel, self).__init__()\n        self.embedding = nn.Embedding(4, embedding_dim)  # Embedding layer\n        self.rnn = nn.LSTM(embedding_dim, hidden_dim, num_layers, batch_first=True)\n        self.fc = nn.Linear(hidden_dim, 1)  # Predicting reactivity for each nucleotide\n        \n    def forward(self, x):\n        x = x.long()  # Assuming x is already one-hot encoded and in LongTensor format\n        x = self.embedding(x)\n        rnn_out, _ = self.rnn(x)\n        output = self.fc(rnn_out[:, -1, :])  # Get the last time step's output\n        return output\n\n\n    \n    \n# Load data\nrna_2A3 = reduced_train_new_pivoted[['encoded_sequence', '2A3_MaP']]\n#rna_2A3[\"encoded_sequence\"] = rna_2A3[\"encoded_sequence\"].apply(lambda x: list(map(int, x)))\n\nsequence_matrix = rna_2A3['encoded_sequence'].tolist()\nsequence_tensor_list = [torch.LongTensor(seq) for seq in sequence_matrix]\n\n\n# Pad sequences for same length\npadded_sequences = pad_sequence(sequence_tensor_list, batch_first=True)\n\nreactivities = rna_2A3['2A3_MaP'].tolist()\n\n# Convert data to PyTorch tensors\nsequence_tensor = torch.LongTensor(padded_sequences)\nreactivities_tensor = torch.FloatTensor(reactivities).view(-1, 1)  # Assuming 1D target, reshape to (batch_size, 1)","metadata":{"execution":{"iopub.status.busy":"2023-10-19T19:42:12.970342Z","iopub.execute_input":"2023-10-19T19:42:12.970579Z","iopub.status.idle":"2023-10-19T19:42:14.742798Z","shell.execute_reply.started":"2023-10-19T19:42:12.970559Z","shell.execute_reply":"2023-10-19T19:42:14.742023Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sequence_tensor.shape","metadata":{"execution":{"iopub.status.busy":"2023-10-19T19:42:14.743877Z","iopub.execute_input":"2023-10-19T19:42:14.744458Z","iopub.status.idle":"2023-10-19T19:42:14.749982Z","shell.execute_reply.started":"2023-10-19T19:42:14.744434Z","shell.execute_reply":"2023-10-19T19:42:14.749099Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create a DataLoader\ndataset = TensorDataset(sequence_tensor, reactivities_tensor)\ntrain_size = int(0.8 * len(dataset))\nval_size = len(dataset) - train_size\ntrain_dataset, val_dataset = random_split(dataset, [train_size, val_size])\n\ntrain_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)\nval_loader = DataLoader(val_dataset, batch_size=32)","metadata":{"execution":{"iopub.status.busy":"2023-10-19T19:42:14.751105Z","iopub.execute_input":"2023-10-19T19:42:14.751425Z","iopub.status.idle":"2023-10-19T19:42:14.770062Z","shell.execute_reply.started":"2023-10-19T19:42:14.751396Z","shell.execute_reply":"2023-10-19T19:42:14.769373Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Training loop\nembedding_dim = 128\nhidden_dim = 64\nnum_layers = 2\nmodel = RNASeq2SeqModel(embedding_dim, hidden_dim, num_layers).to(device)\ncriterion = nn.MSELoss()  # Mean Squared Error loss for regression task\noptimizer = optim.Adam(model.parameters(), lr=0.001)\n\nnum_epochs = 50\nfor epoch in range(num_epochs):\n    model.train()\n    total_loss = 0\n    for batch_seq, batch_reactivity in train_loader:\n        batch_seq, batch_reactivity = batch_seq.to(device), batch_reactivity.to(device)\n        optimizer.zero_grad()\n        output = model(batch_seq)\n        # Squeeze target tensor to match the output shape\n        loss = criterion(output, batch_reactivity.squeeze(1))\n        loss.backward()\n        optimizer.step()\n        total_loss += loss.item()\n    average_loss = total_loss / len(train_loader)\n    print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {average_loss:.4f}')","metadata":{"execution":{"iopub.status.busy":"2023-10-19T19:46:26.066326Z","iopub.execute_input":"2023-10-19T19:46:26.066678Z","iopub.status.idle":"2023-10-19T19:50:35.488018Z","shell.execute_reply.started":"2023-10-19T19:46:26.066654Z","shell.execute_reply":"2023-10-19T19:50:35.487109Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Validation\nmodel.eval()\nval_loss = 0\nwith torch.no_grad():\n    for batch_seq, batch_reactivity in val_loader:\n        batch_seq, batch_reactivity = batch_seq.to(device), batch_reactivity.to(device)\n        output = model(batch_seq)\n        # Squeeze target tensor to match the output shape\n        val_loss += criterion(output, batch_reactivity.squeeze(1)).item()\naverage_val_loss = val_loss / len(val_loader)\nprint(f'Validation Loss: {average_val_loss:.4f}')","metadata":{"execution":{"iopub.status.busy":"2023-10-19T19:53:25.930127Z","iopub.execute_input":"2023-10-19T19:53:25.930501Z","iopub.status.idle":"2023-10-19T19:53:26.438350Z","shell.execute_reply.started":"2023-10-19T19:53:25.930477Z","shell.execute_reply":"2023-10-19T19:53:26.437485Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Notebooks helped me:\n- https://www.kaggle.com/code/wrecked22/starters-eda-fastai-rnn\n- https://www.kaggle.com/code/mishazybin/simple-baseline-submit-medians","metadata":{}}]}