Chem-World / scripts /run_temp.py
TianyouBai's picture
Upload 16 files
fc8da88 verified
Raw
History Blame Contribute Delete
6.13 kB
import argparse
import os
import torch
import sys
import copy
import pandas as pd
import numpy as np
from torch.utils.data import DataLoader
from torch.utils.data import Subset
from omegaconf import OmegaConf
from mixhub.data.dataset import MixtureTask
from mixhub.data.data import DATA_CATALOG
from mixhub.data.featurization import FEATURIZATION_TYPE
from mixhub.data.collate import custom_collate
from mixhub.data.splits import SplitLoader
from mixhub.model.train import train
from mixhub.model.predict import predict
from mixhub.model.model_builder import build_mixture_model
def main(
config,
experiment_name,
wandb_logger=None,
):
config = copy.deepcopy(config)
torch.manual_seed(config.seed)
device = torch.device(config.device)
print(f"Running on: {device}")
root_dir = config.root_dir
os.makedirs(root_dir, exist_ok=True)
featurization = config.dataset.featurization
if FEATURIZATION_TYPE[featurization] == "graphs" and config.mixture_model.mol_encoder.type != "gnn":
raise ValueError(f"featurization is:{FEATURIZATION_TYPE[featurization]} but molecule encoder is: {config.mol_encoder.type}")
if FEATURIZATION_TYPE[featurization] == "tensors" and config.mixture_model.mol_encoder.type == "gnn":
raise ValueError(f"featurization is:{FEATURIZATION_TYPE[featurization]} but molecule encoder is: {config.mol_encoder.type}")
# Dataset
dataset = DATA_CATALOG[config.dataset.name]()
property = config.dataset.property
mixture_task = MixtureTask(
property=property,
dataset=dataset,
featurization=featurization,
)
# Split Loader
split_loader = SplitLoader(split_type="temperature")
for i in range(5):
run_name = f"temp_{i}"
print(f"Training/validating on split {i}")
train_indices, val_indices, test_indices = split_loader(
property=mixture_task.property,
cache_dir=mixture_task.dataset.data_dir,
split_num=i,
)
# Data Loader
train_dataset = Subset(mixture_task, train_indices.tolist())
val_dataset = Subset(mixture_task, val_indices.tolist())
train_loader = DataLoader(
train_dataset,
batch_size=config.batch_size,
shuffle=True,
collate_fn=custom_collate,
num_workers=config.num_workers,
pin_memory=True,
)
val_loader = DataLoader(
val_dataset,
batch_size=config.batch_size,
collate_fn=custom_collate,
num_workers=config.num_workers,
)
model = build_mixture_model(config=config.mixture_model)
model = model.to(device)
# Save hyper parameters
OmegaConf.save(config, f"{root_dir}/hparams_{experiment_name}.yaml")
# Training
train(
root_dir=root_dir,
model=model,
train_loader=train_loader,
val_loader=val_loader,
loss_type=config.loss_type,
lr_mol_encoder=config.lr_mol_encoder,
lr_other=config.lr_other,
device=device,
weight_decay=config.weight_decay,
max_epochs=config.max_epochs,
patience=config.patience,
experiment_name=run_name,
wandb_logger=wandb_logger,
)
print(f"Testing on split {i}")
# Data Loader (one big batch)
test_dataset = Subset(mixture_task, test_indices.tolist())
test_loader = DataLoader(
test_dataset,
batch_size=test_dataset.__len__(),
collate_fn=custom_collate,
num_workers=config.num_workers,
)
metric_dict, y_pred, y_test = predict(
model=model,
test_loader=test_loader,
device=device,
)
print(metric_dict)
test_metrics = pd.DataFrame(metric_dict, index=["metrics"]).transpose()
test_metrics.to_csv(os.path.join(config.root_dir, f"{run_name}_test_metrics.csv"))
y_pred = y_pred.detach().cpu().numpy().flatten()
y_test = y_test.detach().cpu().numpy().flatten()
test_predictions = pd.DataFrame(
{
"Predicted_Experimental_Values": y_pred,
"Ground_Truth": y_test,
"MAE": np.abs(y_pred - y_test),
},
index=range(len(y_pred)),
)
test_predictions.to_csv(os.path.join(config.root_dir, f"{run_name}_test_predictions.csv"), index=False)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Run temperature split experiment")
parser.add_argument("config", type=str, help="Path to the YAML configuration file")
parser.add_argument(
"--physics_based",
action="store_true",
help="Switch the regressor to the physics-based law and write outputs to the physics_based results directory",
)
parser.add_argument("--wandb_project", type=str, default=None, help="Name of the wandb project (optional)")
args = parser.parse_args()
config = OmegaConf.load(args.config)
experiment_name = f"{config.dataset.featurization}_{config.mixture_model.mix_encoder.type}"
config.root_dir = os.path.abspath(f"../results/temp_split/baseline/{experiment_name}/{config.dataset.name}/{config.dataset.property.lower().replace(' ', '_')}")
if args.physics_based:
config.mixture_model.regressor.type = "physics_based"
config.root_dir = config.root_dir.replace("baseline", "physics_based")
if args.wandb_project is not None:
try:
from torchtune.training.metric_logging import WandBLogger
except ImportError as exc:
raise ImportError(
"torchtune is required for WandB logging. Install torchtune/torchao or run without --wandb_project."
) from exc
wandb_logger = WandBLogger(project=args.wandb_project)
else:
wandb_logger = None
main(
config=config,
experiment_name=experiment_name,
wandb_logger=wandb_logger,
)