A machine learning project that predicts whether a molecule is toxic or non-toxic from its computed chemical descriptors. It's a binary classification problem on an imbalanced dataset (about 108 non-toxic vs 51 toxic molecules), so a lot of the work is about feature selection and handling the class imbalance rather than just fitting a model.
The raw data has a very large number of molecular descriptors (topological, autocorrelation,
BCUT, ETA indices, etc.), far more than the ~159 molecules, so feature selection is the
core of the project. The notebook (XGBoost_molecule.ipynb) works through several
strategies and compares them:
- Dimensionality reduction: PCA, PCA + RFE, PCA + t-SNE
- Recursive feature elimination (RFE)
- A cardinality sweep that tests how many features give the best cross-validated accuracy, followed by iterative pruning
The sweep found that around 12 descriptors gave the best cross-validated accuracy (~0.82 mean CV), and pruning below that didn't help. Those 12 features are what the final model uses.
Toxicity.ipynb is the clean final pipeline:
- Keep the 12 selected descriptors.
SMOTEto oversample the minority (toxic) class on the training folds — this trades a little overall accuracy for better recall on toxic molecules, which is the right trade-off when a missed toxic molecule is the costly error.StandardScaler+XGBClassifier(100 trees, depth 3, learning rate 0.1).- Evaluated with 5-fold stratified cross-validation.
On a held-out test set the model reached about 0.78 accuracy, with recall on the toxic class around 0.70 — the metric that actually matters here.
pip install pandas numpy scikit-learn xgboost imbalanced-learn
Open Toxicity.ipynb for the final pipeline, or XGBoost_molecule.ipynb for the full
feature-selection exploration. Both expect the descriptor CSV in the same folder.