Skip to content

can we precompute and cache features for all CV ? #29

Description

@guillaume-osmo

We recompute 25 times the same features which suboptimal for the 5x5 CV.

Can we cached them in order to use for example with import joblib ?

import os
import joblib
import pandas as pd
from tqdm import tqdm
from calc_osmordred import CalcOsmordred  
from concurrent.futures import ProcessPoolExecutor, as_completed

# Set up caching
CACHE_DIR = "./feature_cache"
os.makedirs(CACHE_DIR, exist_ok=True)
memory = joblib.Memory(CACHE_DIR, verbose=0)

def compute_osmordred(smiles):
    return CalcOsmordred(smiles)


def load_or_compute_features(df, version=2, n_jobs=4):
    """Loads cached features or computes them if missing, preserving indices for CV splits."""
    feature_file = f"{CACHE_DIR}/osmordred_features_v{version}.csv"

    #  Check if cached features exist
    if os.path.exists(feature_file) and os.path.getsize(feature_file) > 0:
        print(" Loading cached features...")
        feature_df = pd.read_csv(feature_file)

        #  Ensure feature_df has an index column
        if "Index" not in feature_df.columns:
            raise RuntimeError("Cached feature file is missing 'Index' column!")

        feature_df.set_index("Index", inplace=True)  # Restore original indices
        return feature_df

    print("Computing new features...")
    results = []

    with ProcessPoolExecutor(max_workers=n_jobs) as executor:
        futures = {executor.submit(compute_osmordred, smi): idx for idx, smi in df.SMILES.items()}

        for future in tqdm(as_completed(futures), total=len(futures), desc="Computing Features"):
            idx = futures[future]  # Get dataset index
            try:
                result = future.result()
                if result is not None:
                    results.append((idx, result))
            except Exception as e:
                print(f"Error processing index {idx}: {e}")

    if results:
        feature_df = pd.DataFrame([res[1] for res in sorted(results, key=lambda x: x[0])])
        feature_df.insert(0, "Index", [res[0] for res in sorted(results, key=lambda x: x[0])])
        feature_df.to_csv(feature_file, index=False)
        feature_df.set_index("Index", inplace=True)  # Ensure proper indexing
        return feature_df
    else:
        raise RuntimeError("All feature computations failed! No data to save.")

def get_features_for_split(split_df, all_features_df):
    """Selects the correct precomputed features for a given CV split."""
    return all_features_df.loc[split_df.index]

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions