{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":67356,"databundleVersionId":8006601,"sourceType":"competition"}],"dockerImageVersionId":30732,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"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\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","execution":{"iopub.status.busy":"2024-06-16T22:58:05.805735Z","iopub.execute_input":"2024-06-16T22:58:05.806321Z","iopub.status.idle":"2024-06-16T22:58:06.299141Z","shell.execute_reply.started":"2024-06-16T22:58:05.80627Z","shell.execute_reply":"2024-06-16T22:58:06.297706Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install rdkit\n!pip install duckdb\n","metadata":{"execution":{"iopub.status.busy":"2024-06-16T22:58:06.301539Z","iopub.execute_input":"2024-06-16T22:58:06.302149Z","iopub.status.idle":"2024-06-16T22:58:36.46384Z","shell.execute_reply.started":"2024-06-16T22:58:06.302112Z","shell.execute_reply":"2024-06-16T22:58:36.462287Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\nfrom functools import partial\nimport time\n\nfrom scipy.spatial import distance\nfrom concurrent.futures import ProcessPoolExecutor\nimport torch\nimport torch.nn as nn\nfrom torch.nn.utils.rnn import pad_sequence\nfrom torch.profiler import profile, record_function, ProfilerActivity\nfrom rdkit import Chem\nfrom rdkit.Chem import rdMolDescriptors, DataStructs\nfrom rdkit.Chem import rdFingerprintGenerator\nfrom xgboost import XGBClassifier\nfrom sklearn.metrics import average_precision_score, classification_report\nfrom sklearn.ensemble import RandomForestClassifier\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import classification_report\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport pandas as pd\nimport pyarrow.parquet as pq\nimport pyarrow as pa\nimport duckdb\nimport gc","metadata":{"execution":{"iopub.status.busy":"2024-06-16T22:58:36.46571Z","iopub.execute_input":"2024-06-16T22:58:36.466116Z","iopub.status.idle":"2024-06-16T22:58:41.449024Z","shell.execute_reply.started":"2024-06-16T22:58:36.46608Z","shell.execute_reply":"2024-06-16T22:58:41.447762Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_path = '/kaggle/input/leash-BELKA/train.parquet'\ntest_path = '/kaggle/input/leash-BELKA/test.parquet'","metadata":{"execution":{"iopub.status.busy":"2024-06-16T22:58:41.451456Z","iopub.execute_input":"2024-06-16T22:58:41.451952Z","iopub.status.idle":"2024-06-16T22:58:41.456604Z","shell.execute_reply.started":"2024-06-16T22:58:41.451919Z","shell.execute_reply":"2024-06-16T22:58:41.455554Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_data_for_protein(protein_name, num_each_result):\n    '''\n    Get data for a specific protein (HSA, sEH, BRD4).\n    '''\n    con = duckdb.connect()\n\n    df = con.query(f\"\"\"(SELECT *\n                          FROM parquet_scan('{train_path}')\n                          WHERE binds = 0 AND protein_name = '{protein_name}'\n                          ORDER BY random()\n                          LIMIT {num_each_result})\n                          UNION ALL\n                          (SELECT *\n                          FROM parquet_scan('{train_path}')\n                          WHERE binds = 1 AND protein_name = '{protein_name}'\n                          ORDER BY random()\n                          LIMIT {num_each_result})\"\"\").df()\n\n    con.close()\n    return df\n","metadata":{"execution":{"iopub.status.busy":"2024-06-16T22:58:41.458375Z","iopub.execute_input":"2024-06-16T22:58:41.458827Z","iopub.status.idle":"2024-06-16T22:58:41.472805Z","shell.execute_reply.started":"2024-06-16T22:58:41.458788Z","shell.execute_reply":"2024-06-16T22:58:41.471672Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data = get_data_for_protein('HSA', 60000)\nprint(data)","metadata":{"execution":{"iopub.status.busy":"2024-06-16T22:58:41.474115Z","iopub.execute_input":"2024-06-16T22:58:41.474457Z","iopub.status.idle":"2024-06-16T22:59:26.087467Z","shell.execute_reply.started":"2024-06-16T22:58:41.474428Z","shell.execute_reply":"2024-06-16T22:59:26.085328Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define a function to generate fingerprints\ndef smiles_to_fp(smiles, fp_size=2048):\n    mol = Chem.MolFromSmiles(smiles)\n    if mol is None:\n        return np.zeros(fp_size, dtype=np.int8) \n    fpg = rdFingerprintGenerator.GetMorganGenerator(fpSize=fp_size)\n    fp = fpg.GetFingerprint(mol)\n    arr = np.zeros((fp_size,), dtype=np.int8)\n    DataStructs.ConvertToNumpyArray(fp, arr)\n    return arr\n","metadata":{"execution":{"iopub.status.busy":"2024-06-16T22:59:26.089486Z","iopub.execute_input":"2024-06-16T22:59:26.089854Z","iopub.status.idle":"2024-06-16T22:59:26.097172Z","shell.execute_reply.started":"2024-06-16T22:59:26.089821Z","shell.execute_reply":"2024-06-16T22:59:26.09579Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def parallel_apply(data, func, column, fp_size=2048):\n    with ProcessPoolExecutor() as executor:\n        f = partial(func, fp_size=fp_size)\n        results = list(executor.map(f, data[column]))\n    return results\n","metadata":{"execution":{"iopub.status.busy":"2024-06-16T22:59:26.098566Z","iopub.execute_input":"2024-06-16T22:59:26.098994Z","iopub.status.idle":"2024-06-16T22:59:26.115166Z","shell.execute_reply.started":"2024-06-16T22:59:26.098954Z","shell.execute_reply":"2024-06-16T22:59:26.113817Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Print the number of rows and columns in the dataframe\nprint(data.shape)\n\n# Print the data types of each column\nprint(data.dtypes)\n\n# Print the unique values of the \"protein_name\" column\nprint(data[\"protein_name\"].unique())\n\n# Calculate the number of missing values in each column\nprint(data.isnull().sum())\n\n# Calculate the mean and standard deviation of the \"binds\" column\nprint(data[\"binds\"].mean(), data[\"binds\"].std())","metadata":{"execution":{"iopub.status.busy":"2024-06-16T22:59:26.11709Z","iopub.execute_input":"2024-06-16T22:59:26.117622Z","iopub.status.idle":"2024-06-16T22:59:26.180235Z","shell.execute_reply.started":"2024-06-16T22:59:26.117588Z","shell.execute_reply":"2024-06-16T22:59:26.178748Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Random Forest","metadata":{}},{"cell_type":"code","source":"'''# Split the dataset\nX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)\n\n# Train a Random Forest classifier\nclf = RandomForestClassifier(n_estimators=100, random_state=42)\nclf.fit(X_train, y_train)\n\n# Make predictions\ny_pred = clf.predict(X_test)\n\n# Evaluate the model\nprint(classification_report(y_test, y_pred))\n\n'''","metadata":{"execution":{"iopub.status.busy":"2024-06-16T22:59:26.185607Z","iopub.execute_input":"2024-06-16T22:59:26.185997Z","iopub.status.idle":"2024-06-16T22:59:26.195081Z","shell.execute_reply.started":"2024-06-16T22:59:26.185969Z","shell.execute_reply":"2024-06-16T22:59:26.193733Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"XGBoost","metadata":{}},{"cell_type":"code","source":"\ndef train_model(data):\n    data['fp_block1'] = parallel_apply(data, smiles_to_fp, 'buildingblock1_smiles')\n    data['fp_block2'] = parallel_apply(data, smiles_to_fp, 'buildingblock2_smiles')\n    data['fp_block3'] = parallel_apply(data, smiles_to_fp, 'buildingblock3_smiles')\n    data['fp_molecule'] = parallel_apply(data, smiles_to_fp, 'molecule_smiles')\n    \n\n    fp_block1_df = pd.DataFrame(data['fp_block1'].tolist()).add_prefix('fp_block1_')\n    fp_block2_df = pd.DataFrame(data['fp_block2'].tolist()).add_prefix('fp_block2_')\n    fp_block3_df = pd.DataFrame(data['fp_block3'].tolist()).add_prefix('fp_block3_')\n    fp_molecule_df = pd.DataFrame(data['fp_molecule'].tolist()).add_prefix('fp_molecule_')\n    \n\n    data = pd.concat([data, fp_block1_df, fp_block2_df, fp_block3_df, fp_molecule_df], axis=1)\n    \n   \n    data.drop(columns=['fp_block1', 'fp_block2', 'fp_block3', 'fp_molecule'], inplace=True)\n    \n\n    data.drop(columns=['buildingblock1_smiles', 'buildingblock2_smiles', 'buildingblock3_smiles', 'molecule_smiles'], inplace=True)\n    \n    data = data.dropna()\n    \n\n    X = data.drop(columns=['binds']).values\n    y = data['binds'].values\n\n    scaler = StandardScaler()\n    X_scaled = scaler.fit_transform(X)\n    \n\n    X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42, stratify=y)\n    \n    smote = SMOTE(random_state=42)\n    X_train_resampled, y_train_resampled = smote.fit_resample(X_train, y_train)\n    \n    param_grid = {\n        'n_estimators': [100, 200, 300],\n        'max_depth': [3, 5, 7],\n        'learning_rate': [0.01, 0.1, 0.2],\n        'subsample': [0.8, 1.0]\n    }\n    \n    xgb_model = XGBClassifier(use_label_encoder=False, eval_metric='logloss', random_state=42)\n    \n    grid_search = GridSearchCV(estimator=xgb_model, param_grid=param_grid, scoring='average_precision', cv=StratifiedKFold(n_splits=5), verbose=1, n_jobs=-1)\n    grid_search.fit(X_train_resampled, y_train_resampled)\n    \n    best_model = grid_search.best_estimator_\n\n    results = grid_search.cv_results_\n    for mean_score, params in zip(results['mean_test_score'], results['params']):\n        print(f\"Accuracy: {mean_score:.4f} | Params: {params}\")\n    \n    y_pred = best_model.predict(X_test)\n    y_pred_proba = best_model.predict_proba(X_test)[:, 1]\n    \n    avg_precision = average_precision_score(y_test, y_pred_proba)\n    accuracy = accuracy_score(y_test, y_pred)\n    print(f'XGBoost Average Precision Score: {avg_precision:.4f}')\n    print(f'XGBoost Accuracy Score: {accuracy:.4f}')\n    print(classification_report(y_test, y_pred > 0.5))\n    \n    return best_model","metadata":{"execution":{"iopub.status.busy":"2024-06-16T22:59:26.197951Z","iopub.execute_input":"2024-06-16T22:59:26.198451Z","iopub.status.idle":"2024-06-16T22:59:26.216551Z","shell.execute_reply.started":"2024-06-16T22:59:26.198407Z","shell.execute_reply":"2024-06-16T22:59:26.215364Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Train the model\nxgb_model = train_model(data)","metadata":{"execution":{"iopub.status.busy":"2024-06-16T22:59:26.218121Z","iopub.execute_input":"2024-06-16T22:59:26.218623Z"},"trusted":true},"execution_count":null,"outputs":[]}]}