Model Evaluation¶
Evaluate fitted models against ground truth: convergence diagnostics, mutation effect accuracy, shift sparsity, replicate correlations, and variant phenotype predictions.
Outline
Convergence diagnostics — check converged status, plot loss trajectories
Mutation effect accuracy — beta and shift vs ground truth, save
model_vs_truth_beta_shift.csvShift sparsity — fraction of shifts exactly zero, save
fit_sparsity.csvReplicate correlations — lib_1 vs lib_2 mutation parameters, save
library_replicate_correlation.csvVariant phenotype predictions — predicted vs true variant phenotypes, save
model_vs_truth_variant_phenotype.csvAdditional visualizations — latent vs functional score, pairplot, violin by variant class, phenotype vs lambda
[1]:
import warnings
warnings.filterwarnings("ignore")
import itertools
import os
import pickle
import sys
from collections import defaultdict
sys.path.insert(0, "notebooks")
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
import multidms
import multidms.plot
from multidms.model_collection import ModelCollection
from _common import (
load_config,
reconstruct_simulators,
)
%matplotlib inline
[2]:
config_path = "config/config.yaml"
downstream_config_path = "config/config_downstream.yaml"
output_dir = None
[3]:
# Parameters
config_path = "config/config.yaml"
downstream_config_path = "config/config_downstream.yaml"
output_dir = "results-prod-sim-vpl500-tol1e5"
[4]:
config = load_config(config_path, downstream_config_path)
sim = config["simulation"]
fit_config = sim["fitting"]
seed = config["seed"]
train_frac = config["train_frac"]
if output_dir is None:
output_dir = sim["output_dir"]
lasso_choice = sim["lasso_choice"]
os.makedirs(output_dir, exist_ok=True)
print(f"Output directory: {output_dir}")
Output directory: results-prod-sim-vpl500-tol1e5
Load data¶
[5]:
fit_collection_df = pickle.load(
open(os.path.join(output_dir, "fit_collection.pkl"), "rb")
)
mut_effects_df = pd.read_csv(
os.path.join(output_dir, "simulated_muteffects.csv")
)
func_scores = pd.read_csv(
os.path.join(output_dir, "simulated_func_scores.csv")
)
func_scores["func_score_type"] = pd.Categorical(
func_scores["func_score_type"],
categories=["observed_phenotype", "loose_bottle", "tight_bottle"],
ordered=True,
)
# Display-friendly titles for measurement types (used in all subplot titles)
NICE_TITLES = {
"observed_phenotype": "Observed Phenotype",
"loose_bottle": "Loose Bottleneck",
"tight_bottle": "Tight Bottleneck",
}
# Canonical ordering for measurement types
MT_ORDER = ["observed_phenotype", "loose_bottle", "tight_bottle"]
print(
f"Loaded {len(fit_collection_df)} fitted models, "
f"{len(mut_effects_df)} mutations, "
f"{len(func_scores)} functional scores"
)
Loaded 60 fitted models, 1000 mutations, 182256 functional scores
1. Convergence diagnostics¶
[6]:
model_collection = ModelCollection(fit_collection_df)
print("Convergence counts:")
print(model_collection.fit_models.converged.value_counts())
Convergence counts:
converged
True 60
Name: count, dtype: int64
[7]:
conv_data = model_collection.convergence_trajectory_df(
id_vars=("fusionreg", "measurement_type", "library")
)
multidms.plot.convergence_trajectory(
conv_data,
id_cols=["fusionreg", "measurement_type", "library"],
title="Convergence trajectories",
)
[7]: