{"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.10.12"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":87793,"databundleVersionId":11228175,"sourceType":"competition"},{"sourceId":7395079,"sourceType":"datasetVersion","datasetId":4299455},{"sourceId":7639698,"sourceType":"datasetVersion","datasetId":4299272},{"sourceId":224703571,"sourceType":"kernelVersion"}],"dockerImageVersionId":30919,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true},"papermill":{"default_parameters":{},"duration":26.275472,"end_time":"2025-02-28T09:16:02.559366","environment_variables":{},"exception":null,"input_path":"__notebook__.ipynb","output_path":"__notebook__.ipynb","parameters":{},"start_time":"2025-02-28T09:15:36.283894","version":"2.6.0"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"Ensemble of two solution\n\n1. https://www.kaggle.com/code/kumarandatascientist/lb-0-179-rna-3d-lr-adjusted (0.179)\n2. https://www.kaggle.com/code/michaelrowen/rna-folding-starter#CNN-model (0.076)","metadata":{"execution":{"iopub.status.busy":"2025-03-04T12:46:38.842276Z","iopub.execute_input":"2025-03-04T12:46:38.842554Z","iopub.status.idle":"2025-03-04T12:46:38.848413Z","shell.execute_reply.started":"2025-03-04T12:46:38.842529Z","shell.execute_reply":"2025-03-04T12:46:38.847150Z"}}},{"cell_type":"markdown","source":"### === 1 ===","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport torch\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport torch\nimport random\nimport pickle\n\ntest_data=pd.read_csv(\"/kaggle/input/stanford-rna-3d-folding/test_sequences.csv\")\n\nfrom torch.utils.data import Dataset, DataLoader\n\nclass RNADataset(Dataset):\n    def __init__(self,data):\n        self.data=data\n        self.tokens={nt:i for i,nt in enumerate('ACGU')}\n\n    def __len__(self):\n        return len(self.data)\n    \n    def __getitem__(self, idx):\n        sequence=[self.tokens[nt] for nt in (self.data.loc[idx,'sequence'])]\n        sequence=np.array(sequence)\n        sequence=torch.tensor(sequence)\n\n        return {'sequence':sequence}\n\ntest_dataset=RNADataset(test_data)\n\nimport sys\n\nsys.path.append(\"/kaggle/input/ribonanzanet2d-final\")\n\n\nfrom Network import *\nimport yaml\n\nclass Config:\n    def __init__(self, **entries):\n        self.__dict__.update(entries)\n        self.entries=entries\n\n    def print(self):\n        print(self.entries)\n\ndef load_config_from_yaml(file_path):\n    with open(file_path, 'r') as file:\n        config = yaml.safe_load(file)\n    return Config(**config)\n\nclass finetuned_RibonanzaNet(RibonanzaNet):\n    def __init__(self, config, pretrained=False):\n        config.dropout=0.2\n        super(finetuned_RibonanzaNet, self).__init__(config)\n        if pretrained:\n            self.load_state_dict(torch.load(\"/kaggle/input/ribonanzanet-weights/RibonanzaNet.pt\",map_location='cpu'))\n        # self.ct_predictor=nn.Sequential(nn.Linear(64,256),\n        #                                 nn.ReLU(),\n        #                                 nn.Linear(256,64),\n        #                                 nn.ReLU(),\n        #                                 nn.Linear(64,1)) \n        self.dropout=nn.Dropout(0.0)\n        self.xyz_predictor=nn.Linear(256, 3)\n\n    def forward(self,src):\n        \n        #with torch.no_grad():\n        sequence_features, pairwise_features=self.get_embeddings(src, torch.ones_like(src).long().to(src.device))\n\n        xyz=self.xyz_predictor(sequence_features)\n\n        return xyz\n\nmodel=finetuned_RibonanzaNet(load_config_from_yaml(\"/kaggle/input/ribonanzanet2d-final/configs/pairwise.yaml\"),pretrained=False).cuda()\n\nmodel.load_state_dict(torch.load(\"/kaggle/input/ribonanzanet-3d-finetune/RibonanzaNet-3D.pt\"))\n\nmodel.eval()\npreds=[]\nfor i in range(len(test_dataset)):\n    src=test_dataset[i]['sequence'].long()\n    src=src.unsqueeze(0).cuda()\n\n    model.train()\n\n    tmp=[]\n    for i in range(4):\n        with torch.no_grad():\n            xyz=model(src).squeeze()\n        tmp.append(xyz.cpu().numpy())\n\n    model.eval()\n    with torch.no_grad():\n        xyz=model(src).squeeze()\n    tmp.append(xyz.cpu().numpy())\n\n    tmp=np.stack(tmp,0)\n    #exit()\n    preds.append(tmp)\n\npreds1 = preds","metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","papermill":{"duration":3.972204,"end_time":"2025-02-28T09:15:42.839651","exception":false,"start_time":"2025-02-28T09:15:38.867447","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2025-03-08T07:57:17.034539Z","iopub.execute_input":"2025-03-08T07:57:17.034757Z","iopub.status.idle":"2025-03-08T07:57:37.015587Z","shell.execute_reply.started":"2025-03-08T07:57:17.034735Z","shell.execute_reply":"2025-03-08T07:57:37.014889Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### === 2 ===","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\n\ntrain_labels = pd.read_csv(\"/kaggle/input/stanford-rna-3d-folding/train_labels.csv\")\ntrain_sequence = pd.read_csv(\"/kaggle/input/stanford-rna-3d-folding/train_sequences.csv\")\nval_labels = pd.read_csv(\"/kaggle/input/stanford-rna-3d-folding/validation_labels.csv\")\nval_sequence = pd.read_csv(\"/kaggle/input/stanford-rna-3d-folding/validation_sequences.csv\")\ntest_sequence = pd.read_csv(\"/kaggle/input/stanford-rna-3d-folding/test_sequences.csv\")\n\nprint(\"Train Seq: \" + str(train_sequence.shape))\nprint(\"Train Label: \" + str(train_labels.shape))\nprint(\"Validation Seq: \" + str(val_sequence.shape))\nprint(\"Validation Label: \" + str(val_labels.shape))\nprint(\"Test: \"+str(test_sequence.shape))\n\ntrain_labels.fillna(0, inplace=True)\nval_labels.fillna(0, inplace=True)\n\nseq_dict = {'A': 1, 'C': 2, 'G': 3, 'U': 4}\ndef seq_map(seq):\n    return [seq_dict.get(char, 0) for char in seq]\n\ntrain_sequence['encoded_seq'] = train_sequence['sequence'].apply(seq_map)\ntest_sequence['encoded_seq'] = test_sequence['sequence'].apply(seq_map)\nval_sequence['encoded_seq'] = val_sequence['sequence'].apply(seq_map)\n\ndef generate_label_coord(df):\n    result = {}\n    df[\"label\"] = df.ID.str.rsplit('_', n=1, expand=True).iloc[:,0]\n    for _, row in df.iterrows():\n        label = row['label']\n        resid = row['resid']\n        if label not in result:\n            result[label] = []\n        else:\n            coord = np.array([row['x_1'], row['y_1'], row['z_1']], dtype=np.float32)\n            result[label].append((resid, coord))\n    for key in result:\n        coords = np.stack([c for r, c in result[key]])\n        result[key] = coords\n    return result\n\ntrain_stacked_coords = generate_label_coord(train_labels)\nval_stacked_coords = generate_label_coord(val_labels)\ntrain_stacked_coords[list(train_stacked_coords.keys())[0]]\n\ndef generate_dataset(seq, stacked_coords):\n    X, y, tids = [], [], []\n    for idx, row in seq.iterrows():\n        tid = row['target_id']\n        if tid in stacked_coords:\n            X.append(row['encoded_seq'])\n            y.append(stacked_coords[tid])\n            tids.append(tid)\n    return X, y, tids\n\ntrain_X, train_y, train_tids = generate_dataset(train_sequence, train_stacked_coords)\nval_X, val_y, val_tids = generate_dataset(val_sequence, val_stacked_coords)\n\nimport tensorflow as tf\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.layers import Input, Embedding, Conv1D, BatchNormalization, Dropout\nfrom tensorflow.keras.preprocessing.sequence import pad_sequences\nfrom tensorflow.keras.callbacks import EarlyStopping\n\nmax_len = max(len(seq) for seq in train_X)\n\ntrain_X_pad = pad_sequences(train_X, maxlen=max_len, padding='post', value=0)\nval_X_pad = pad_sequences(val_X, maxlen=max_len, padding='post', value=0)\ntest_X = test_sequence['encoded_seq'].tolist()\ntest_X_pad = pad_sequences(test_X, maxlen=max_len, padding='post', value=0)\ntrain_X_pad.shape\n\ndef pad_coords(coords, max_len):\n    L = coords.shape[0]\n    if L < max_len:\n        pad_width = ((0, max_len-L), (0, 0)) # pad only vertically\n        return np.pad(coords, pad_width, mode='constant', constant_values = 0)\n    else:\n        return coords\n\ntrain_y_pad = np.array([pad_coords(y, max_len) for y in train_y])\nval_y_pad = np.array([pad_coords(y, max_len) for y in val_y])\ntrain_y_pad.shape\n\nclass CNN:\n    def __init__(self, X_train_pad, y_train_pad, X_val_pad, y_val_pad):\n        self.x_train = X_train_pad\n        self.y_train = y_train_pad\n        self.x_val = X_val_pad\n        self.y_val = y_val_pad\n        self.config = {\n            'seq_mapping_size':max(seq_dict.values()) + 1,\n            'embedding_dim':16,\n            'num_filters':64,\n            'kernel_size':3,\n            'drop_rate':0.2,\n            'train_epochs':50,\n            'batch_size':16\n        }\n        self.model= None\n    def first_conv(self, max_length):\n        input_seq = Input(shape=(max_len,), name='input_seq')\n        x_cnn = Embedding(input_dim=self.config[\"seq_mapping_size\"],\n                         output_dim=self.config[\"embedding_dim\"],\n                         mask_zero=True,\n                         name='embedding')(input_seq)\n        x_cnn = Conv1D(filters=self.config[\"num_filters\"],\n                      kernel_size=self.config[\"kernel_size\"],\n                      padding='same',\n                      activation='relu',\n                      name='conv1')(x_cnn)\n        x_cnn = BatchNormalization(name='norm1')(x_cnn)\n        x_cnn = Dropout(self.config['drop_rate'], name='drop1')(x_cnn)\n        \n        return input_seq, x_cnn\n        \n    def second_conv_full_c(self, x_cnn):\n        x_cnn = Conv1D(filters=self.config[\"num_filters\"],\n                      kernel_size=self.config[\"kernel_size\"],\n                      padding='same',\n                      activation='relu',\n                      name='conv2')(x_cnn)\n        x_cnn = BatchNormalization(name='norm2')(x_cnn)\n        x_cnn = Dropout(self.config['drop_rate'], name='drop2')(x_cnn)\n        full_c = Conv1D(filters=3, kernel_size=1,\n                       padding='same',\n                       activation='linear',\n                       name='predicted_coords')(x_cnn)\n        return full_c\n    def build_model(self, max_length):\n        input_seq, x_cnn = self.first_conv(max_length)\n        full_c = self.second_conv_full_c(x_cnn)\n        model = Model(inputs=input_seq,\n                     outputs=full_c)\n        model.compile(optimizer='adam', loss='mae')\n        self.model=model\n        return model.summary()\n        \n    def train(self):\n        history_cnn = self.model.fit(\n            self.x_train,\n            self.y_train,\n            validation_data=(self.x_val, self.y_val),\n            epochs=self.config[\"train_epochs\"],\n            batch_size=self.config[\"batch_size\"],\n            verbose=1\n        )\n        return self.model\n\ncnn = CNN(train_X_pad, train_y_pad, val_X_pad, val_y_pad)\ncnn.build_model(max_len)\nmodel = cnn.train()\n\npred = model.predict(test_X_pad)\npred.shape\n\npreds2 = pred","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-08T07:57:37.016381Z","iopub.execute_input":"2025-03-08T07:57:37.016840Z","iopub.status.idle":"2025-03-08T07:58:26.296863Z","shell.execute_reply.started":"2025-03-08T07:57:37.016809Z","shell.execute_reply":"2025-03-08T07:58:26.296212Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### === Ensemble ===","metadata":{}},{"cell_type":"code","source":"def concat(input, target, alpha):\n    centroid_input = input.mean(axis=0, keepdims=True)\n    centroid_target = target.mean(axis=0, keepdims=True)\n\n    # Center the points\n    input_centered = input - centroid_input\n    target_centered = target - centroid_target\n\n    # Compute covariance matrix\n    cov_matrix = input_centered.T @ target_centered\n\n    # SVD to find optimal rotation\n    U, S, Vt = np.linalg.svd(cov_matrix)\n\n    # Compute rotation matrix\n    R = Vt @ U.T\n\n    # Ensure a proper rotation (det(R) = 1, no reflection)\n    if np.linalg.det(R) < 0:\n        Vt[-1, :] *= -1\n        R = Vt @ U.T\n\n    # Rotate input\n    aligned_input = (input_centered @ R.T) + centroid_target\n\n    return alpha * aligned_input + (1 - alpha) * target\n\nsubmission_rows = []\nfor idx, row in test_sequence.iterrows():\n    target_id = row['target_id']\n    coords = preds2[idx]\n    seq_length = len(row['encoded_seq'])\n\n    coords1 = preds1[idx][0]\n    coords2 = coords[:seq_length, :]\n\n    coords = concat(coords1, coords2, 0.95)\n\n    for i in range(seq_length):\n        x, y, z = coords[i, :]\n\n        submission_rows.append(\n        {\n            'ID':f\"{target_id}_{i+1}\",\n            'resname':row['sequence'][i],\n            'resid':i+1,\n             **{f\"x_{j+1}\": x for j in range(5)},\n             **{f\"y_{j+1}\": y for j in range(5)},\n             **{f\"z_{j+1}\": z for j in range(5)}\n            \n        }\n        )\nsubmission = pd.DataFrame(submission_rows)\n\nsubmission.to_csv(\"submission.csv\", index=False)\n\n# i = idx\n# k = i\n# j = k\n# kk = x,y,z","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-08T08:04:48.131443Z","iopub.execute_input":"2025-03-08T08:04:48.131721Z","iopub.status.idle":"2025-03-08T08:04:48.223541Z","shell.execute_reply.started":"2025-03-08T08:04:48.131700Z","shell.execute_reply":"2025-03-08T08:04:48.222845Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"submission","metadata":{"papermill":{"duration":0.036003,"end_time":"2025-02-28T09:16:01.035444","exception":false,"start_time":"2025-02-28T09:16:00.999441","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2025-03-08T08:04:52.308262Z","iopub.execute_input":"2025-03-08T08:04:52.308547Z","iopub.status.idle":"2025-03-08T08:04:52.326884Z","shell.execute_reply.started":"2025-03-08T08:04:52.308526Z","shell.execute_reply":"2025-03-08T08:04:52.325858Z"}},"outputs":[],"execution_count":null}]}