# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: AILS
#     language: python
#     name: ails
# ---

# + [markdown] id="view-in-github" colab_type="text"
# <a href="https://colab.research.google.com/github/m-wallner/drug-activity-sklearn/blob/main/drug-activity-sklearn.ipynb" target="_parent"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/></a>

# + [markdown] id="4lh3kSEcKEeK"
# # Drug Activity

# + [markdown] id="PQEfCdRXKRio"
# ## Project overview

# + [markdown] id="QMl2-zhNKgAy"
# The aim of this project was to predict the biological activity or toxicity of a drug or a molecule purely based on its chemical structure. A dataset of molecules in SMILES format was given (provided by the JKU Institute of Machine Learning, not available in this repository), together with activities of these molecules related to 11 different applications, and the goal was to train a machine learning model to predict the activities of new molecules based on the selected model.
#
# First, the molecules in SMILES format are transferred into sparse Morgan fingerprints of length 2048, then various classic machine learning models (Support Vector Regression, AdaBoost and Random Forest) contained in the sklearn library are trained and validated on the validation set. SVR showed the best results in terms of a mean ROC AUC score of 71.3% on the 11 different tasks contained in the test set.

# + [markdown] id="azHam8ZzMD7c"
# ## Imports

# + id="2Xdfm2KcKEeL"
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

import rdkit
from rdkit import Chem
from rdkit.Chem import AllChem, Draw

from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import SVR
from sklearn.ensemble import AdaBoostClassifier
from sklearn.ensemble import BaggingRegressor
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.metrics import roc_auc_score

from imblearn.over_sampling import ADASYN

# + [markdown] id="VludWf1LKEeN"
# ## Data inspection

# + [markdown] id="bhGT2WuaKEeP"
# ### Training data

# + id="QU3VUpcvKEeQ" outputId="a11f3565-f11e-490f-be5d-c9931da2ce54"
data_train = pd.read_csv('data_train.csv', index_col=0)
data_train

# + id="dtVxXLrKKEeS" outputId="1f7b4d67-aaa1-4c71-91a8-12d0288f4a6a"
# Visualisation of data using histograms
for i in range(1, 12):
    plt.hist(data_train['task' + str(i)], [-1.5, -0.5, 0.5, 1.5])
    plt.title('Task ' + str(i))
    plt.show()

# + [markdown] id="HBxDU0KZKEeT"
# ### Test data

# + id="5g_ed5a5KEeU" outputId="ed0d0e81-19ff-4750-8134-8e6e8dd4eecf"
data_test = pd.read_csv('smiles_test.csv')
data_test


# + [markdown] id="OmdH1CRdKEeV"
# ## Preprocessing

# + [markdown] id="nAbZR4kwKEeV"
# ### Smiles to Morgan fingerprints

# + id="bUy8bPBDKEeX"
# Turn molecules in smiles format into Morgan fingerprints
def smiles_to_morgan(data: np.array, fp_length=1024):
    desc_mtx = np.zeros((len(data), fp_length)) * np.nan

    # Get Morgan fingerprints
    for i, smiles in enumerate(data):
        mol = Chem.MolFromSmiles(smiles)
        desc_mtx[i] = AllChem.GetMorganFingerprintAsBitVect(mol, radius=3, nBits=fp_length)
        
    return desc_mtx


# + id="DaF8SdFKKEeX" outputId="6d69863e-4da5-4d58-90a6-63ef018052cf"
# Define train and test sets by getting Morgan fingerprints
X = smiles_to_morgan(np.array(data_train['smiles']), fp_length=2048)
X_test = smiles_to_morgan(np.array(data_test['smiles']), fp_length=2048)

print(X.shape, X_test.shape)

# + id="apwiauLnKEeY" outputId="b779856c-9a4e-40b6-a64b-e42293bb1b93"
# Create task-only dataframe
tasks = data_train.drop('smiles', axis=1)
tasks

# + id="1Y5-beNmKEeZ" outputId="f2079ec3-cec6-4b00-93e2-551c4fefa777"
# Get labels from tasks dataframe
y = [np.array(tasks[col]) for col in tasks]
y

# + id="qEdo2erLKEeZ" outputId="20eb6bc7-9877-4dd9-8905-46a2629e4eba"
# Create filters to mask out tasks with 0-labels
task_filters = [np.where(label!=0) for label in y]
task_filters[0]

# + [markdown] id="yJM7CSGXKEeZ"
# ## Support Vector Regression

# + id="8e5QP22CKEeZ" outputId="532fe706-3f08-40fd-9ad1-277f9084c219"
seed = 42
roc_auc_scores = []
predictions_testset = {}
param_grid = {
    'C': [0.1, 1, 10],
    'epsilon': [0.1, 1, 10]
}

for i, mask in enumerate(task_filters):
    
    # Train / Validation split
    X_train, X_valid, y_train, y_valid = train_test_split(X[mask], y[i][mask], test_size=0.1, random_state=seed)
    
    # Resample training data
    X_train, y_train = ADASYN().fit_resample(X_train, y_train)
    
    # Define and train model
    clf = GridSearchCV(SVR(kernel='rbf'), param_grid, n_jobs=-1)
    clf.fit(X_train, y_train)
    
    # Bagging regressor based on model
    clf_bagg = BaggingRegressor(base_estimator=clf, n_estimators=10, n_jobs=-1, random_state=seed)
    clf_bagg.fit(X_train, y_train)
    
    # Validation
    y_hat_proba = clf_bagg.predict(X_valid)
    roc_auc_scores.append(roc_auc_score(y_valid, y_hat_proba))
    print('ROC AUC score task ' + str(i + 1 )+ ':', roc_auc_scores[i])
    
    # Test
    predictions_testset['task' + str(i+1)] = clf.predict(X_test)

# Print mean score
print('Mean ROC AUC score:', np.mean(roc_auc_scores))
          
# Dump CSV file
pd.DataFrame(predictions_testset).to_csv('submission_svr.csv')

# + [markdown] id="xBcYp_daKEea"
# ## AdaBoost

# + id="wli3qSd2KEea" outputId="579ebbd2-1f6f-45da-fe54-133b1fcd760e"
seed = 42
roc_auc_scores = []
predictions_testset = {}

for i, mask in enumerate(task_filters):
    
    # Train / Validation split
    X_train, X_valid, y_train, y_valid = train_test_split(X[mask], y[i][mask], test_size=0.1, random_state=seed)
    
    # Resa mple training data
    X_train, y_train = ADASYN().fit_resample(X_train, y_train)
    
    # Define and train model
    clf = AdaBoostClassifier(n_estimators=100)
    clf.fit(X_train, y_train)
    
    # Bagging regressor based on model
    clf_bagg = BaggingRegressor(base_estimator=clf, n_estimators=100, random_state=seed)
    clf_bagg.fit(X_train, y_train)
    
    # Validation
    y_hat_proba = clf_bagg.predict(X_valid)
    roc_auc_scores.append(roc_auc_score(y_valid, y_hat_proba))
    print('ROC AUC score task ' + str(i + 1 )+ ':', roc_auc_scores[i])
    
    # Test
    predictions_testset['task' + str(i+1)] = clf.predict(X_test)

# Print mean score
print('Mean ROC AUC score:', np.mean(roc_auc_scores))
          
# Dump CSV file
pd.DataFrame(predictions_testset).to_csv('submission_adaboost.csv')

# + [markdown] id="clVQMY-aKEeb"
# ## Random Forest

# + id="wYZA_rJRKEeb" outputId="007cf952-7fd5-4fa1-bc80-892bb37c6226"
seed = 42
roc_auc_scores = []
predictions_testset = {}

for i, mask in enumerate(task_filters):
    
    # Train / Validation split
    X_train, X_valid, y_train, y_valid = train_test_split(X[mask], y[i][mask], test_size=0.1, random_state=seed)
    
    # Resample training data
    X_train, y_train = ADASYN().fit_resample(X_train, y_train)
    
    # Define and train model
    clf = RandomForestClassifier(n_estimators=20, random_state=seed)
    clf.fit(X_train, y_train)
    
    # Bagging regressor based on model
    clf_bagg = BaggingRegressor(base_estimator=clf, n_estimators=100, n_jobs=-1, random_state=seed)
    clf_bagg.fit(X_train, y_train)
    
    # Validation
    y_hat_proba = clf_bagg.predict(X_valid)
    roc_auc_scores.append(roc_auc_score(y_valid, y_hat_proba))
    print('ROC AUC score task ' + str(i + 1 )+ ':', roc_auc_scores[i])
    
    # Test
    predictions_testset['task' + str(i+1)] = clf.predict(X_test)

# Print mean score
print('Mean ROC AUC score:', np.mean(roc_auc_scores))
          
# Dump CSV file
pd.DataFrame(predictions_testset).to_csv('submission_rf_bagg.csv')

StarcoderdataJupyterScriptsDedupFiltered