{"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","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":"none","dataSources":[{"sourceId":87793,"databundleVersionId":12276181,"sourceType":"competition"}],"dockerImageVersionId":31259,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Approach 2: Sklearn Ensemble RNA Structure Prediction\n\n**Core Principle**: Traditional ML can learn patterns\n\nThis approach implements:\n1. **Feature Engineering**: Extract sequence-derived features\n2. **Ensemble Models**: Multiple classical ML models\n3. **Coordinate Regression**: Direct coordinate prediction\n4. **Model Diversity**: Different algorithms for varied predictions","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nfrom sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor, ExtraTreesRegressor\nfrom sklearn.linear_model import Ridge, LinearRegression\nfrom sklearn.preprocessing import StandardScaler\nfrom sklearn.model_selection import train_test_split\nfrom pathlib import Path\nimport warnings\nwarnings.filterwarnings('ignore')\n\n# Load data\ndata_dir = Path(\"/kaggle/input/stanford-rna-3d-folding\")\ntrain_seq = pd.read_csv(data_dir / 'train_sequences.csv')\ntrain_labels = pd.read_csv(data_dir / 'train_labels.csv')\ntest_seq = pd.read_csv(data_dir / 'test_sequences.csv')\nsample_sub = pd.read_csv(data_dir / 'sample_submission.csv')\n\nprint(f\"Data loaded: {len(train_seq)} train, {len(test_seq)} test sequences\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-16T11:53:25.624620Z","iopub.execute_input":"2026-01-16T11:53:25.624963Z","iopub.status.idle":"2026-01-16T11:53:25.863860Z","shell.execute_reply.started":"2026-01-16T11:53:25.624936Z","shell.execute_reply":"2026-01-16T11:53:25.862851Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 1. Feature Engineering","metadata":{}},{"cell_type":"code","source":"class RNAFeatureExtractor:\n    def __init__(self):\n        self.nucleotide_map = {'A': 0, 'C': 1, 'G': 2, 'U': 3}\n        \n    def extract_basic_features(self, sequence):\n        \"\"\"\n        Extract basic sequence features\n        \"\"\"\n        features = {}\n        \n        # Length features\n        features['length'] = len(sequence)\n        \n        # Nucleotide composition\n        for nuc in ['A', 'C', 'G', 'U']:\n            features[f'{nuc}_count'] = sequence.count(nuc)\n            features[f'{nuc}_freq'] = sequence.count(nuc) / len(sequence)\n        \n        # GC content\n        features['gc_content'] = (sequence.count('G') + sequence.count('C')) / len(sequence)\n        \n        return features\n    \n    def extract_positional_features(self, sequence, position):\n        \"\"\"\n        Extract features for a specific position\n        \"\"\"\n        features = {}\n        \n        # Position information\n        features['position'] = position\n        features['position_norm'] = position / len(sequence)\n        features['position_from_end'] = len(sequence) - position\n        \n        # Current nucleotide\n        current_nuc = sequence[position] if position < len(sequence) else 'A'\n        features['current_nuc'] = self.nucleotide_map.get(current_nuc, 0)\n        \n        # Local context (window of 5 nucleotides)\n        window_size = 5\n        for i in range(-window_size//2, window_size//2 + 1):\n            pos = position + i\n            if 0 <= pos < len(sequence):\n                nuc = sequence[pos]\n                features[f'neighbor_{i}_nuc'] = self.nucleotide_map.get(nuc, 0)\n            else:\n                features[f'neighbor_{i}_nuc'] = 0\n        \n        return features\n    \n    def extract_global_features(self, sequence):\n        \"\"\"\n        Extract global sequence features\n        \"\"\"\n        features = {}\n        \n        # K-mer frequencies (2-mers)\n        kmer_counts = {}\n        for i in range(len(sequence) - 1):\n            kmer = sequence[i:i+2]\n            kmer_counts[kmer] = kmer_counts.get(kmer, 0) + 1\n        \n        total_kmers = sum(kmer_counts.values())\n        for kmer in ['AA', 'AC', 'AG', 'AU', 'CA', 'CC', 'CG', 'CU', 'GA', 'GC', 'GG', 'GU', 'UA', 'UC', 'UG', 'UU']:\n            features[f'kmer_{kmer}_freq'] = kmer_counts.get(kmer, 0) / max(total_kmers, 1)\n        \n        # Sequence complexity\n        unique_nucleotides = len(set(sequence))\n        features['complexity'] = unique_nucleotides / 4.0\n        \n        return features\n\n# Initialize feature extractor\nfeature_extractor = RNAFeatureExtractor()\nprint(\"Feature extractor initialized\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-16T11:53:25.865560Z","iopub.execute_input":"2026-01-16T11:53:25.865874Z","iopub.status.idle":"2026-01-16T11:53:25.880187Z","shell.execute_reply.started":"2026-01-16T11:53:25.865847Z","shell.execute_reply":"2026-01-16T11:53:25.879311Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Training Data Preparation\ndef prepare_training_data(train_seq, train_labels, max_length=200):\n    \"\"\"\n    Prepare training data with features and targets\n    \"\"\"\n    training_data = []\n    \n    for _, seq_row in train_seq.iterrows():\n        target_id = seq_row['target_id']\n        sequence = seq_row['sequence']\n        \n        # Skip very long sequences for memory efficiency\n        if len(sequence) > max_length:\n            continue\n            \n        # Get coordinates for this sequence\n        coords_data = train_labels[train_labels['ID'].str.startswith(target_id)].copy()\n        coords_data = coords_data.sort_values('resid')\n        \n        # Skip if missing coordinates\n        if coords_data[['x_1', 'y_1', 'z_1']].isna().any().any():\n            continue\n            \n        # Extract global features\n        global_features = feature_extractor.extract_global_features(sequence)\n        basic_features = feature_extractor.extract_basic_features(sequence)\n        \n        # Create training examples for each position\n        for i, nucleotide in enumerate(sequence):\n            if i >= len(coords_data):\n                break\n                \n            # Extract positional features\n            pos_features = feature_extractor.extract_positional_features(sequence, i)\n            \n            # Combine all features\n            all_features = {}\n            all_features.update(global_features)\n            all_features.update(basic_features)\n            all_features.update(pos_features)\n            \n            # Get target coordinates\n            coords = coords_data.iloc[i]\n            \n            training_data.append({\n                'features': all_features,\n                'x': coords['x_1'],\n                'y': coords['y_1'],\n                'z': coords['z_1'],\n                'sequence_length': len(sequence),\n                'position': i\n            })\n    \n    return training_data\n\n# Prepare training data\ntraining_data = prepare_training_data(train_seq, train_labels)\nprint(f\"Prepared {len(training_data)} training examples\")\n\n# Convert to DataFrame\nfeatures_df = pd.DataFrame([item['features'] for item in training_data])\ntargets_df = pd.DataFrame({\n    'x': [item['x'] for item in training_data],\n    'y': [item['y'] for item in training_data],\n    'z': [item['z'] for item in training_data]\n})\n\nprint(f\"Features shape: {features_df.shape}\")\nprint(f\"Targets shape: {targets_df.shape}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-16T11:53:25.881550Z","iopub.execute_input":"2026-01-16T11:53:25.881901Z","iopub.status.idle":"2026-01-16T11:53:54.009523Z","shell.execute_reply.started":"2026-01-16T11:53:25.881866Z","shell.execute_reply":"2026-01-16T11:53:54.008298Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Model Training","metadata":{}},{"cell_type":"code","source":"\nclass SklearnEnsembleModel:\n    def __init__(self):\n        # Initialize different models for diversity\n        self.models_x = {\n            'rf': RandomForestRegressor(n_estimators=100, random_state=42),\n            'gb': GradientBoostingRegressor(n_estimators=100, random_state=42),\n            'et': ExtraTreesRegressor(n_estimators=100, random_state=42),\n            'ridge': Ridge(alpha=1.0)\n        }\n        \n        self.models_y = {\n            'rf': RandomForestRegressor(n_estimators=100, random_state=42),\n            'gb': GradientBoostingRegressor(n_estimators=100, random_state=42),\n            'et': ExtraTreesRegressor(n_estimators=100, random_state=42),\n            'ridge': Ridge(alpha=1.0)\n        }\n        \n        self.models_z = {\n            'rf': RandomForestRegressor(n_estimators=100, random_state=42),\n            'gb': GradientBoostingRegressor(n_estimators=100, random_state=42),\n            'et': ExtraTreesRegressor(n_estimators=100, random_state=42),\n            'ridge': Ridge(alpha=1.0)\n        }\n        \n        self.scaler = StandardScaler()\n        self.feature_names = None\n    \n    def train(self, X, y_x, y_y, y_z):\n        \"\"\"\n        Train all models\n        \"\"\"\n        # Scale features\n        X_scaled = self.scaler.fit_transform(X)\n        self.feature_names = X.columns.tolist()\n        \n        # Train models for each coordinate\n        for name, model in self.models_x.items():\n            model.fit(X_scaled, y_x)\n            print(f\"Trained {name} model for x coordinates\")\n            \n        for name, model in self.models_y.items():\n            model.fit(X_scaled, y_y)\n            print(f\"Trained {name} model for y coordinates\")\n            \n        for name, model in self.models_z.items():\n            model.fit(X_scaled, y_z)\n            print(f\"Trained {name} model for z coordinates\")\n    \n    def predict(self, X, model_combination='rf'):\n        \"\"\"\n        Predict using specified model combination\n        \"\"\"\n        X_scaled = self.scaler.transform(X)\n        \n        # Predict using selected model\n        x_pred = self.models_x[model_combination].predict(X_scaled)\n        y_pred = self.models_y[model_combination].predict(X_scaled)\n        z_pred = self.models_z[model_combination].predict(X_scaled)\n        \n        return x_pred, y_pred, z_pred\n\n# Initialize and train model\nensemble_model = SklearnEnsembleModel()\nensemble_model.train(features_df, targets_df['x'], targets_df['y'], targets_df['z'])\nprint(\"Ensemble model training completed\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-16T11:53:54.011892Z","iopub.execute_input":"2026-01-16T11:53:54.012655Z","iopub.status.idle":"2026-01-16T11:58:34.004562Z","shell.execute_reply.started":"2026-01-16T11:53:54.012620Z","shell.execute_reply":"2026-01-16T11:58:34.002851Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Prediction Pipeline\ndef predict_sequence_structure(sequence, model, model_combination='rf'):\n    \"\"\"\n    Predict structure for a single sequence\n    \"\"\"\n    # Extract features for each position\n    features_list = []\n    \n    # Global features\n    global_features = feature_extractor.extract_global_features(sequence)\n    basic_features = feature_extractor.extract_basic_features(sequence)\n    \n    for i in range(len(sequence)):\n        # Positional features\n        pos_features = feature_extractor.extract_positional_features(sequence, i)\n        \n        # Combine all features\n        all_features = {}\n        all_features.update(global_features)\n        all_features.update(basic_features)\n        all_features.update(pos_features)\n        \n        features_list.append(all_features)\n    \n    # Convert to DataFrame\n    X = pd.DataFrame(features_list)\n    \n    # Add missing columns if needed\n    for col in model.feature_names:\n        if col not in X.columns:\n            X[col] = 0\n    \n    # Ensure same column order\n    X = X[model.feature_names]\n    \n    # Predict\n    x_pred, y_pred, z_pred = model.predict(X, model_combination)\n    \n    # Combine into coordinate array\n    coords = np.column_stack([x_pred, y_pred, z_pred])\n    \n    return coords\n\ndef generate_multiple_conformations(sequence, model, n_conformations=5):\n    \"\"\"\n    Generate multiple conformations using different model combinations\n    \"\"\"\n    model_combinations = ['rf', 'gb', 'et', 'ridge', 'rf']  # Repeat rf for 5th\n    \n    conformations = []\n    for i in range(n_conformations):\n        model_comb = model_combinations[i % len(model_combinations)]\n        coords = predict_sequence_structure(sequence, model, model_comb)\n        conformations.append(coords)\n    \n    return conformations","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Test prediction\ntest_sequence = test_seq['sequence'].iloc[0]\nprint(f\"Testing prediction for sequence: {test_sequence[:50]}...\")\n\nconformations = generate_multiple_conformations(test_sequence, ensemble_model, n_conformations=5)\nprint(f\"Generated {len(conformations)} conformations\")\nprint(f\"Each conformation shape: {conformations[0].shape}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-16T11:58:34.005537Z","iopub.execute_input":"2026-01-16T11:58:34.005830Z","iopub.status.idle":"2026-01-16T11:58:34.173508Z","shell.execute_reply.started":"2026-01-16T11:58:34.005799Z","shell.execute_reply":"2026-01-16T11:58:34.172523Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Generate submission","metadata":{}},{"cell_type":"code","source":"\ndef create_submission_sklearn(test_sequences, model):\n    \"\"\"\n    Create submission using sklearn ensemble approach\n    \"\"\"\n    submission_rows = []\n    \n    for idx, test_row in test_sequences.iterrows():\n        target_id = test_row['target_id']\n        sequence = test_row['sequence']\n        \n        print(f\"Processing {target_id}, length: {len(sequence)}\")\n        \n        # Generate 5 conformations\n        conformations = generate_multiple_conformations(sequence, model, n_conformations=5)\n        \n        # Create submission rows\n        for i, nucleotide in enumerate(sequence):\n            row_data = {\n                'ID': f\"{target_id}_{i+1}\",\n                'resname': nucleotide,\n                'resid': i + 1\n            }\n            \n            # Add coordinates for all 5 conformations\n            for conf_id in range(5):\n                if i < len(conformations[conf_id]):\n                    coords = conformations[conf_id][i]\n                    row_data[f'x_{conf_id+1}'] = coords[0]\n                    row_data[f'y_{conf_id+1}'] = coords[1]\n                    row_data[f'z_{conf_id+1}'] = coords[2]\n                else:\n                    row_data[f'x_{conf_id+1}'] = 0.0\n                    row_data[f'y_{conf_id+1}'] = 0.0\n                    row_data[f'z_{conf_id+1}'] = 0.0\n            \n            submission_rows.append(row_data)\n    \n    return pd.DataFrame(submission_rows)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"submission_sklearn = create_submission_sklearn(test_seq, ensemble_model)\nprint(f\"Generated submission with {len(submission_sklearn)} rows\")\nprint(f\"Expected rows: {sample_sub.shape[0]}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-16T11:58:34.175043Z","iopub.execute_input":"2026-01-16T11:58:34.175481Z","iopub.status.idle":"2026-01-16T11:58:35.981929Z","shell.execute_reply.started":"2026-01-16T11:58:34.175443Z","shell.execute_reply":"2026-01-16T11:58:35.980904Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Submission Generation","metadata":{}},{"cell_type":"code","source":"# Quality Validation and Final Submission\ndef validate_sklearn_submission(submission_df):\n    \"\"\"\n    Validate sklearn submission\n    \"\"\"\n    print(\"=== Sklearn Submission Validation ===\")\n    \n    # Check format\n    expected_cols = ['ID', 'resname', 'resid'] + [f'{coord}_{i}' for coord in ['x', 'y', 'z'] for i in range(1, 6)]\n    missing_cols = set(expected_cols) - set(submission_df.columns)\n    extra_cols = set(submission_df.columns) - set(expected_cols)\n    \n    print(f\"Missing columns: {missing_cols}\")\n    print(f\"Extra columns: {extra_cols}\")\n    print(f\"Shape: {submission_df.shape}\")\n    \n    # Check coordinate statistics\n    coord_cols = [f'{coord}_{i}' for coord in ['x', 'y', 'z'] for i in range(1, 6)]\n    coord_values = submission_df[coord_cols].values\n    \n    print(f\"Coordinate statistics:\")\n    print(f\"  Min: {coord_values.min():.3f}\")\n    print(f\"  Max: {coord_values.max():.3f}\")\n    print(f\"  Mean: {coord_values.mean():.3f}\")\n    print(f\"  Std: {coord_values.std():.3f}\")\n    \n    # Check for NaN values\n    nan_count = np.isnan(coord_values).sum()\n    print(f\"NaN values: {nan_count}\")\n    \n    return True\n\n# Validate submission\nvalidate_sklearn_submission(submission_sklearn)\n\n# Save submission\nsubmission_sklearn.to_csv('submission_sklearn.csv', index=False)\nprint(\"\\nSklearn submission saved as 'submission_sklearn.csv'\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-16T11:58:36.020173Z","iopub.execute_input":"2026-01-16T11:58:36.020500Z","iopub.status.idle":"2026-01-16T11:58:36.112589Z","shell.execute_reply.started":"2026-01-16T11:58:36.020453Z","shell.execute_reply":"2026-01-16T11:58:36.111604Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 5. Submission Generation","metadata":{}},{"cell_type":"code","source":"def create_submission_sklearn(test_sequences, model):\n    \"\"\"\n    Create submission using sklearn ensemble approach\n    \"\"\"\n    submission_rows = []\n    \n    for idx, test_row in test_sequences.iterrows():\n        target_id = test_row['target_id']\n        sequence = test_row['sequence']\n        \n        print(f\"Processing {target_id}, length: {len(sequence)}\")\n        \n        # Generate 5 conformations\n        conformations = generate_multiple_conformations(sequence, model, n_conformations=5)\n        \n        # Create submission rows\n        for i, nucleotide in enumerate(sequence):\n            row_data = {\n                'ID': f\"{target_id}_{i+1}\",\n                'resname': nucleotide,\n                'resid': i + 1\n            }\n            \n            # Add coordinates for all 5 conformations\n            for conf_id in range(5):\n                if i < len(conformations[conf_id]):\n                    coords = conformations[conf_id][i]\n                    row_data[f'x_{conf_id+1}'] = coords[0]\n                    row_data[f'y_{conf_id+1}'] = coords[1]\n                    row_data[f'z_{conf_id+1}'] = coords[2]\n                else:\n                    row_data[f'x_{conf_id+1}'] = 0.0\n                    row_data[f'y_{conf_id+1}'] = 0.0\n                    row_data[f'z_{conf_id+1}'] = 0.0\n            \n            submission_rows.append(row_data)\n    \n    return pd.DataFrame(submission_rows)\n\n# Generate submission\nsubmission_sklearn = create_submission_sklearn(test_seq, ensemble_model)\nprint(f\"Generated submission with {len(submission_sklearn)} rows\")\nprint(f\"Expected rows: {sample_sub.shape[0]}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-16T11:58:36.115394Z","iopub.execute_input":"2026-01-16T11:58:36.115709Z","iopub.status.idle":"2026-01-16T11:58:37.908526Z","shell.execute_reply.started":"2026-01-16T11:58:36.115681Z","shell.execute_reply":"2026-01-16T11:58:37.907401Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 6. Quality Validation and Final Submission","metadata":{}},{"cell_type":"code","source":"def validate_sklearn_submission(submission_df):\n    \"\"\"\n    Validate sklearn submission\n    \"\"\"\n    print(\"=== Sklearn Submission Validation ===\")\n    \n    # Check format\n    expected_cols = ['ID', 'resname', 'resid'] + [f'{coord}_{i}' for coord in ['x', 'y', 'z'] for i in range(1, 6)]\n    missing_cols = set(expected_cols) - set(submission_df.columns)\n    extra_cols = set(submission_df.columns) - set(expected_cols)\n    \n    print(f\"Missing columns: {missing_cols}\")\n    print(f\"Extra columns: {extra_cols}\")\n    print(f\"Shape: {submission_df.shape}\")\n    \n    # Check coordinate statistics\n    coord_cols = [f'{coord}_{i}' for coord in ['x', 'y', 'z'] for i in range(1, 6)]\n    coord_values = submission_df[coord_cols].values\n    \n    print(f\"Coordinate statistics:\")\n    print(f\"  Min: {coord_values.min():.3f}\")\n    print(f\"  Max: {coord_values.max():.3f}\")\n    print(f\"  Mean: {coord_values.mean():.3f}\")\n    print(f\"  Std: {coord_values.std():.3f}\")\n    \n    # Check for NaN values\n    nan_count = np.isnan(coord_values).sum()\n    print(f\"NaN values: {nan_count}\")\n    \n    return True\n\n# Validate submission\nvalidate_sklearn_submission(submission_sklearn)\n\n# Save submission\nsubmission_sklearn.to_csv('submission.csv', index=False)\nprint(\"\\nSklearn submission saved as 'submission.csv'\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-16T11:58:37.909824Z","iopub.execute_input":"2026-01-16T11:58:37.910164Z","iopub.status.idle":"2026-01-16T11:58:37.987951Z","shell.execute_reply.started":"2026-01-16T11:58:37.910121Z","shell.execute_reply":"2026-01-16T11:58:37.986988Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Approach 2 Summary\n\n**Key Strengths:**\n- Good with limited training data\n- Interpretable feature importance\n- Fast training and inference\n- Handles non-linear relationships\n\n**Key Components:**\n1. **Feature Engineering**: Sequence composition, k-mers, positional features\n2. **Ensemble Models**: Random Forest, Gradient Boosting, Extra Trees, Ridge\n3. **Coordinate Regression**: Direct prediction of x, y, z coordinates\n4. **Model Diversity**: Different algorithms for varied conformations\n5. **Feature Scaling**: Standardization for consistent performance\n\n**Expected Performance:**\n- Moderate performance on simple patterns\n- Limited by feature representation quality\n- Struggles with long-range dependencies\n- Good baseline for comparison with advanced methods","metadata":{}},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}