Spaces:
Running
Running
Download train.py from Queimo/tox21_tabicl_classifier: direct link, hf CLI and curl.
- Browser
- Download file 4.44 kB
-
https://huggingface.co/spaces/Queimo/tox21_tabicl_classifier/resolve/main/train.py
- Command line
-
hf download hf://spaces/Queimo/tox21_tabicl_classifier/train.py
-
curl -L -o train.py https://huggingface.co/spaces/Queimo/tox21_tabicl_classifier/resolve/main/train.py
4.44 kB
| """Fit preprocessing assets and the endpoint-specific TabICLv2 estimators.""" | |
| import os | |
| import json | |
| import random | |
| import logging | |
| import argparse | |
| import numpy as np | |
| from sklearn.preprocessing import StandardScaler | |
| from datetime import datetime | |
| from src.model import Tox21TabICL | |
| from src.utils import TASKS, KNOWN_DESCR, create_dir, write_pickle, normalize_config | |
| parser = argparse.ArgumentParser(description="TabICLv2 training script for Tox21") | |
| parser.add_argument( | |
| "--config", | |
| type=str, | |
| default="config/config.json", | |
| ) | |
| parser.add_argument( | |
| "--seed", | |
| type=int, | |
| default=None, | |
| ) | |
| def main(config): | |
| print("Preprocess train molecules") | |
| timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") | |
| # setup logger | |
| logger = logging.getLogger(__name__) | |
| script_name = os.path.splitext(os.path.basename(__file__))[0] | |
| logging.basicConfig( | |
| level=logging.INFO, | |
| format="%(asctime)s [%(levelname)s] %(message)s", | |
| handlers=[ | |
| logging.FileHandler( | |
| os.path.join( | |
| config["log_folder"], | |
| f"{script_name}_{timestamp}.log", | |
| ) | |
| ), | |
| logging.StreamHandler(), | |
| ], | |
| ) | |
| logger.info(config) | |
| # seeding | |
| random.seed(config["seed"]) | |
| np.random.seed(config["seed"]) | |
| train_data = np.load( | |
| os.path.join( | |
| config["data_folder"], f"tox21_train_cv{config['cvfold']}.npz" | |
| ) | |
| ) | |
| train_X = np.concatenate([train_data[descr] for descr in KNOWN_DESCR], axis=1) | |
| train_y = train_data["labels"] | |
| val_data = np.load( | |
| os.path.join( | |
| config["data_folder"], f"tox21_validation_cv{config['cvfold']}.npz" | |
| ) | |
| ) | |
| val_X = np.concatenate([val_data[descr] for descr in KNOWN_DESCR], axis=1) | |
| val_y = val_data["labels"] | |
| train_X = np.concatenate([train_X, val_X], axis=0) | |
| train_y = np.concatenate([train_y, val_y], axis=0) | |
| # remove molecules that couldn't be sanitized | |
| mask = ~np.isnan(train_X).any(axis=1) | |
| train_X = train_X[mask] | |
| train_y = train_y[mask] | |
| # select 500 features with most variance | |
| variances_ = np.nanvar(train_X, axis=0) | |
| order = np.argsort(variances_)[ | |
| : -(config["feature_selection"]["max_features"] + 1) : -1 | |
| ] | |
| logger.info( | |
| f"Save used feature order as: {os.path.join(config['data_folder'], 'feature_order.npy')}" | |
| ) | |
| np.save(os.path.join(config["data_folder"], "feature_order.npy"), order) | |
| train_X = train_X[:, order] | |
| max_samples = ( | |
| config["max_samples"] if config["max_samples"] > 0 else train_X.shape[0] | |
| ) | |
| resample_idxs = np.random.choice( | |
| np.arange(train_X.shape[0]), size=(max_samples,), replace=True | |
| ) | |
| train_X = train_X[resample_idxs] | |
| train_y = train_y[resample_idxs] | |
| # create and save scaler | |
| scaler = StandardScaler() | |
| train_X = scaler.fit_transform(train_X) | |
| logger.info( | |
| f"Save fitted scaler as: {os.path.join(config['data_folder'], 'scaler.pkl')}" | |
| ) | |
| write_pickle(os.path.join(config["data_folder"], "scaler.pkl"), scaler) | |
| if config["ckpt_path"]: | |
| logger.info( | |
| f"Fitted TabICLClassifier state will be saved in: {config['ckpt_path']}" | |
| ) | |
| else: | |
| logger.info("Fitted TabICLClassifier state will NOT be saved.") | |
| model = Tox21TabICL( | |
| seed=config["seed"], | |
| device=config["device"], | |
| model_config=config["model_config"], | |
| ) | |
| logger.info("Start training.") | |
| for i, task in enumerate(TASKS): | |
| logger.info(f"Fitting task: {task}") | |
| # select task-specific data | |
| task_train_y = train_y[:, i] | |
| task_mask = ~np.isnan(task_train_y) | |
| task_train_y = task_train_y[task_mask].astype(int) | |
| task_train_X = train_X[task_mask] | |
| print(f"Fit task {task} using {sum(task_mask)} samples") | |
| model.fit(task, task_train_X, task_train_y) | |
| log_text = f"Finished training." | |
| logger.info(log_text) | |
| if config["ckpt_path"]: | |
| model.save_model(config["ckpt_path"]) | |
| logger.info(f"Save model under: {config['ckpt_path']}") | |
| if __name__ == "__main__": | |
| args = parser.parse_args() | |
| with open(args.config, "r") as f: | |
| config = json.load(f) | |
| config = normalize_config(config) | |
| create_dir(config["log_folder"]) | |
| if args.seed is not None: | |
| config["seed"] = args.seed | |
| main(config) | |