Imputation, denoising, generation, and perturbation#

Open in Colab

A trained UniVI model is a generative model: its decoders map any latent point to every modality. This notebook uses that to

  • denoise measured expression, from one modality or several

  • evaluate cross-modal prediction feature by feature

  • generate new cells, unconditionally or for a chosen cell type, in all modalities at once

  • probe the model with an in-silico perturbation of one input feature

RNA is kept as log-normalized expression without z-scoring here, so that zero means “not expressed” and decoded values are on a familiar scale.

import sys

if "google.colab" in sys.modules:
    %pip install -q "univi[tutorials]>=1.0" "pandas==2.2.3"
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import scanpy as sc
import scipy.sparse as sp
import torch

import univi.datasets as uds
from univi import ModalityConfig, TrainingConfig, UniVIConfig, UniVIMultiModalVAE, UniVITrainer
from univi.evaluation import (denoise_adata, encode_adata, evaluate_cross_reconstruction,
                              fit_label_latent_gaussians, generate_from_latent, sample_latent_by_label)
from univi.perturbation import predict_feature_perturbation
from univi.plotting import compare_raw_vs_denoised_umap_features, plot_featurewise_reconstruction_scatter
from univi.preprocessing import ATACPreprocessor, RNAPreprocessor, split_by_label
from univi.utils.seed import set_seed
from univi.workflows import make_loader

device = "cuda" if torch.cuda.is_available() else ("mps" if torch.backends.mps.is_available() else "cpu")
set_seed(0)
dense = lambda x: x.toarray() if sp.issparse(x) else np.asarray(x)
C:\Users\ashfo\micromamba\envs\univi-release-050\Lib\site-packages\tqdm\auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html
  from .autonotebook import tqdm as notebook_tqdm
N_EPOCHS = 400
BATCH_SIZE = 256
N_HVG = 2000
N_LSI = 101
N_GENERATED = 2000

Train#

data = uds.pbmc_multiome_10k()
rna, atac = data["rna"], data["atac"]
splits = split_by_label(rna.obs["cell_type"], train_fraction=0.8, val_fraction=0.1, seed=0)
rna_prep = RNAPreprocessor(n_hvg=N_HVG, scale=False).fit(rna[splits["train"]])   # log1p, not z-scored
atac_prep = ATACPreprocessor(n_components=N_LSI, drop_first=True, scale=True).fit(atac[splits["train"]])
parts = {k: {"rna": rna_prep.transform(rna[i]), "atac": atac_prep.transform(atac[i])} for k, i in splits.items()}
train, val, test = parts["train"], parts["val"], parts["test"]

cfg = UniVIConfig(
    latent_dim=30, beta=1.25, gamma=4.35, encoder_dropout=0.10, decoder_dropout=0.05,
    kl_anneal_start=50, kl_anneal_end=85, align_anneal_start=75, align_anneal_end=110,
    modalities=[ModalityConfig("rna", train["rna"].n_vars, [512, 256, 128], [128, 256, 512]),
                ModalityConfig("atac", train["atac"].n_vars, [128, 64], [64, 128])],
)
model = UniVIMultiModalVAE(cfg, loss_mode="v1", v1_recon="avg", normalize_v1_terms=True)
UniVITrainer(model, make_loader(train, batch_size=BATCH_SIZE, shuffle=True, drop_last=True),
             make_loader(val, batch_size=1024),
             TrainingConfig(n_epochs=N_EPOCHS, batch_size=BATCH_SIZE, lr=1e-3, weight_decay=1e-4, device=device,
                            early_stopping=True, patience=50, best_epoch_warmup=110, log_every=50)).fit();

rna_test, atac_test = test["rna"], test["atac"]
rna_test.obsm["X_univi"] = encode_adata(model, rna_test, modality="rna", device=device, latent="modality_mean")
sc.pp.neighbors(rna_test, use_rep="X_univi")
sc.tl.umap(rna_test, random_state=0)
markers = [g for g in ["MS4A1", "CD79A", "CD3D", "IL7R", "NKG7", "GNLY", "LYZ", "FCGR3A"] if g in rna_test.var_names]
[2026-09-21 00:58:52,478] [UniVITrainer] [INFO] TrainingConfig:
[2026-09-21 00:58:52,478] [UniVITrainer] [INFO]   n_epochs: 400
[2026-09-21 00:58:52,479] [UniVITrainer] [INFO]   batch_size: 256
[2026-09-21 00:58:52,479] [UniVITrainer] [INFO]   lr: 0.001
[2026-09-21 00:58:52,479] [UniVITrainer] [INFO]   weight_decay: 0.0001
[2026-09-21 00:58:52,480] [UniVITrainer] [INFO]   device: 'cuda'
[2026-09-21 00:58:52,480] [UniVITrainer] [INFO]   log_every: 50
[2026-09-21 00:58:52,480] [UniVITrainer] [INFO]   grad_clip: None
[2026-09-21 00:58:52,480] [UniVITrainer] [INFO]   num_workers: 0
[2026-09-21 00:58:52,481] [UniVITrainer] [INFO]   seed: 0
[2026-09-21 00:58:52,481] [UniVITrainer] [INFO]   early_stopping: True
[2026-09-21 00:58:52,481] [UniVITrainer] [INFO]   patience: 50
[2026-09-21 00:58:52,482] [UniVITrainer] [INFO]   min_delta: 0.0
[2026-09-21 00:58:52,482] [UniVITrainer] [INFO]   best_epoch_warmup: 110
Training UniVI:   0%|          | 0/400 [00:00<?, ?it/s]
[2026-09-21 00:58:54,148] [UniVITrainer] [INFO] [Epoch 001] Train loss=925.2269 (beta=0.000, gamma=0.000)
[2026-09-21 00:58:54,238] [UniVITrainer] [INFO] [Epoch 001] Val loss=940.4916 (beta=1.250, gamma=4.350)
Training UniVI:   0%|          | 0/400 [00:01<?, ?it/s, beta=0.000, gamma=0.000, train_loss=925.2269, val_loss=940.4916]
Training UniVI:   0%|          | 1/400 [00:01<11:40,  1.76s/it, beta=0.000, gamma=0.000, train_loss=925.2269, val_loss=940.4916]
Training UniVI:   0%|          | 1/400 [00:03<11:40,  1.76s/it, beta=0.000, gamma=0.000, train_loss=739.9063, val_loss=909.4086]
Training UniVI:   0%|          | 2/400 [00:03<10:43,  1.62s/it, beta=0.000, gamma=0.000, train_loss=739.9063, val_loss=909.4086]
Training UniVI:   0%|          | 2/400 [00:04<10:43,  1.62s/it, beta=0.000, gamma=0.000, train_loss=696.6504, val_loss=930.3757]
Training UniVI:   1%|          | 3/400 [00:04<10:29,  1.59s/it, beta=0.000, gamma=0.000, train_loss=696.6504, val_loss=930.3757]
Training UniVI:   1%|          | 3/400 [00:06<10:29,  1.59s/it, beta=0.000, gamma=0.000, train_loss=678.9952, val_loss=962.8282]
Training UniVI:   1%|          | 4/400 [00:06<10:19,  1.57s/it, beta=0.000, gamma=0.000, train_loss=678.9952, val_loss=962.8282]
Training UniVI:   1%|          | 4/400 [00:07<10:19,  1.57s/it, beta=0.000, gamma=0.000, train_loss=652.7454, val_loss=1042.4561]
Training UniVI:   1%|▏         | 5/400 [00:07<10:12,  1.55s/it, beta=0.000, gamma=0.000, train_loss=652.7454, val_loss=1042.4561]
Training UniVI:   1%|▏         | 5/400 [00:09<10:12,  1.55s/it, beta=0.000, gamma=0.000, train_loss=631.2725, val_loss=1120.4171]
Training UniVI:   2%|▏         | 6/400 [00:09<10:07,  1.54s/it, beta=0.000, gamma=0.000, train_loss=631.2725, val_loss=1120.4171]
Training UniVI:   2%|▏         | 6/400 [00:10<10:07,  1.54s/it, beta=0.000, gamma=0.000, train_loss=622.6380, val_loss=1189.5018]
Training UniVI:   2%|▏         | 7/400 [00:10<10:07,  1.54s/it, beta=0.000, gamma=0.000, train_loss=622.6380, val_loss=1189.5018]
Training UniVI:   2%|▏         | 7/400 [00:12<10:07,  1.54s/it, beta=0.000, gamma=0.000, train_loss=615.0681, val_loss=1249.0157]
Training UniVI:   2%|▏         | 8/400 [00:12<10:02,  1.54s/it, beta=0.000, gamma=0.000, train_loss=615.0681, val_loss=1249.0157]
Training UniVI:   2%|▏         | 8/400 [00:14<10:02,  1.54s/it, beta=0.000, gamma=0.000, train_loss=609.7046, val_loss=1330.4464]
Training UniVI:   2%|▏         | 9/400 [00:14<09:59,  1.53s/it, beta=0.000, gamma=0.000, train_loss=609.7046, val_loss=1330.4464]
Training UniVI:   2%|▏         | 9/400 [00:15<09:59,  1.53s/it, beta=0.000, gamma=0.000, train_loss=605.8420, val_loss=1537.4929]
Training UniVI:   2%|▎         | 10/400 [00:15<09:56,  1.53s/it, beta=0.000, gamma=0.000, train_loss=605.8420, val_loss=1537.4929]
Training UniVI:   2%|▎         | 10/400 [00:17<09:56,  1.53s/it, beta=0.000, gamma=0.000, train_loss=601.0171, val_loss=1593.3953]
Training UniVI:   3%|▎         | 11/400 [00:17<09:57,  1.54s/it, beta=0.000, gamma=0.000, train_loss=601.0171, val_loss=1593.3953]
Training UniVI:   3%|▎         | 11/400 [00:18<09:57,  1.54s/it, beta=0.000, gamma=0.000, train_loss=597.4898, val_loss=1569.3445]
Training UniVI:   3%|▎         | 12/400 [00:18<09:53,  1.53s/it, beta=0.000, gamma=0.000, train_loss=597.4898, val_loss=1569.3445]
Training UniVI:   3%|▎         | 12/400 [00:20<09:53,  1.53s/it, beta=0.000, gamma=0.000, train_loss=594.7605, val_loss=1670.6594]
Training UniVI:   3%|▎         | 13/400 [00:20<09:52,  1.53s/it, beta=0.000, gamma=0.000, train_loss=594.7605, val_loss=1670.6594]
Training UniVI:   3%|▎         | 13/400 [00:21<09:52,  1.53s/it, beta=0.000, gamma=0.000, train_loss=592.3143, val_loss=1708.5619]
Training UniVI:   4%|▎         | 14/400 [00:21<09:50,  1.53s/it, beta=0.000, gamma=0.000, train_loss=592.3143, val_loss=1708.5619]
Training UniVI:   4%|▎         | 14/400 [00:23<09:50,  1.53s/it, beta=0.000, gamma=0.000, train_loss=590.6109, val_loss=1868.3799]
Training UniVI:   4%|▍         | 15/400 [00:23<09:48,  1.53s/it, beta=0.000, gamma=0.000, train_loss=590.6109, val_loss=1868.3799]
Training UniVI:   4%|▍         | 15/400 [00:24<09:48,  1.53s/it, beta=0.000, gamma=0.000, train_loss=589.2301, val_loss=2005.8770]
Training UniVI:   4%|▍         | 16/400 [00:24<09:49,  1.54s/it, beta=0.000, gamma=0.000, train_loss=589.2301, val_loss=2005.8770]
Training UniVI:   4%|▍         | 16/400 [00:26<09:49,  1.54s/it, beta=0.000, gamma=0.000, train_loss=587.5677, val_loss=2173.3894]
Training UniVI:   4%|▍         | 17/400 [00:26<09:48,  1.54s/it, beta=0.000, gamma=0.000, train_loss=587.5677, val_loss=2173.3894]
Training UniVI:   4%|▍         | 17/400 [00:27<09:48,  1.54s/it, beta=0.000, gamma=0.000, train_loss=586.1759, val_loss=2250.8472]
Training UniVI:   4%|▍         | 18/400 [00:27<09:51,  1.55s/it, beta=0.000, gamma=0.000, train_loss=586.1759, val_loss=2250.8472]
Training UniVI:   4%|▍         | 18/400 [00:29<09:51,  1.55s/it, beta=0.000, gamma=0.000, train_loss=585.3079, val_loss=2509.9011]
Training UniVI:   5%|▍         | 19/400 [00:29<09:59,  1.57s/it, beta=0.000, gamma=0.000, train_loss=585.3079, val_loss=2509.9011]
Training UniVI:   5%|▍         | 19/400 [00:30<09:59,  1.57s/it, beta=0.000, gamma=0.000, train_loss=583.7703, val_loss=2664.2834]
Training UniVI:   5%|▌         | 20/400 [00:30<09:50,  1.55s/it, beta=0.000, gamma=0.000, train_loss=583.7703, val_loss=2664.2834]
Training UniVI:   5%|▌         | 20/400 [00:32<09:50,  1.55s/it, beta=0.000, gamma=0.000, train_loss=582.7419, val_loss=2600.6580]
Training UniVI:   5%|▌         | 21/400 [00:32<09:44,  1.54s/it, beta=0.000, gamma=0.000, train_loss=582.7419, val_loss=2600.6580]
Training UniVI:   5%|▌         | 21/400 [00:34<09:44,  1.54s/it, beta=0.000, gamma=0.000, train_loss=581.5339, val_loss=2923.3806]
Training UniVI:   6%|▌         | 22/400 [00:34<09:43,  1.54s/it, beta=0.000, gamma=0.000, train_loss=581.5339, val_loss=2923.3806]
Training UniVI:   6%|▌         | 22/400 [00:35<09:43,  1.54s/it, beta=0.000, gamma=0.000, train_loss=580.4578, val_loss=3062.8464]
Training UniVI:   6%|▌         | 23/400 [00:35<09:47,  1.56s/it, beta=0.000, gamma=0.000, train_loss=580.4578, val_loss=3062.8464]
Training UniVI:   6%|▌         | 23/400 [00:37<09:47,  1.56s/it, beta=0.000, gamma=0.000, train_loss=579.1981, val_loss=3143.5354]
Training UniVI:   6%|▌         | 24/400 [00:37<09:43,  1.55s/it, beta=0.000, gamma=0.000, train_loss=579.1981, val_loss=3143.5354]
Training UniVI:   6%|▌         | 24/400 [00:38<09:43,  1.55s/it, beta=0.000, gamma=0.000, train_loss=578.2092, val_loss=3451.9287]
Training UniVI:   6%|▋         | 25/400 [00:38<09:40,  1.55s/it, beta=0.000, gamma=0.000, train_loss=578.2092, val_loss=3451.9287]
Training UniVI:   6%|▋         | 25/400 [00:40<09:40,  1.55s/it, beta=0.000, gamma=0.000, train_loss=577.5278, val_loss=3715.1768]
Training UniVI:   6%|▋         | 26/400 [00:40<09:37,  1.54s/it, beta=0.000, gamma=0.000, train_loss=577.5278, val_loss=3715.1768]
Training UniVI:   6%|▋         | 26/400 [00:41<09:37,  1.54s/it, beta=0.000, gamma=0.000, train_loss=576.4642, val_loss=3968.1199]
Training UniVI:   7%|▋         | 27/400 [00:41<09:36,  1.55s/it, beta=0.000, gamma=0.000, train_loss=576.4642, val_loss=3968.1199]
Training UniVI:   7%|▋         | 27/400 [00:43<09:36,  1.55s/it, beta=0.000, gamma=0.000, train_loss=575.6019, val_loss=4292.6929]
Training UniVI:   7%|▋         | 28/400 [00:43<09:33,  1.54s/it, beta=0.000, gamma=0.000, train_loss=575.6019, val_loss=4292.6929]
Training UniVI:   7%|▋         | 28/400 [00:44<09:33,  1.54s/it, beta=0.000, gamma=0.000, train_loss=574.5837, val_loss=4668.5850]
Training UniVI:   7%|▋         | 29/400 [00:44<09:29,  1.54s/it, beta=0.000, gamma=0.000, train_loss=574.5837, val_loss=4668.5850]
Training UniVI:   7%|▋         | 29/400 [00:46<09:29,  1.54s/it, beta=0.000, gamma=0.000, train_loss=573.9729, val_loss=5186.9058]
Training UniVI:   8%|▊         | 30/400 [00:46<09:26,  1.53s/it, beta=0.000, gamma=0.000, train_loss=573.9729, val_loss=5186.9058]
Training UniVI:   8%|▊         | 30/400 [00:47<09:26,  1.53s/it, beta=0.000, gamma=0.000, train_loss=572.8237, val_loss=5815.6777]
Training UniVI:   8%|▊         | 31/400 [00:47<09:24,  1.53s/it, beta=0.000, gamma=0.000, train_loss=572.8237, val_loss=5815.6777]
Training UniVI:   8%|▊         | 31/400 [00:49<09:24,  1.53s/it, beta=0.000, gamma=0.000, train_loss=572.0747, val_loss=5942.7363]
Training UniVI:   8%|▊         | 32/400 [00:49<09:22,  1.53s/it, beta=0.000, gamma=0.000, train_loss=572.0747, val_loss=5942.7363]
Training UniVI:   8%|▊         | 32/400 [00:50<09:22,  1.53s/it, beta=0.000, gamma=0.000, train_loss=571.1481, val_loss=6767.5635]
Training UniVI:   8%|▊         | 33/400 [00:50<09:18,  1.52s/it, beta=0.000, gamma=0.000, train_loss=571.1481, val_loss=6767.5635]
Training UniVI:   8%|▊         | 33/400 [00:52<09:18,  1.52s/it, beta=0.000, gamma=0.000, train_loss=570.4176, val_loss=7668.3345]
Training UniVI:   8%|▊         | 34/400 [00:52<09:16,  1.52s/it, beta=0.000, gamma=0.000, train_loss=570.4176, val_loss=7668.3345]
Training UniVI:   8%|▊         | 34/400 [00:54<09:16,  1.52s/it, beta=0.000, gamma=0.000, train_loss=569.6985, val_loss=8068.1196]
Training UniVI:   9%|▉         | 35/400 [00:54<09:30,  1.56s/it, beta=0.000, gamma=0.000, train_loss=569.6985, val_loss=8068.1196]
Training UniVI:   9%|▉         | 35/400 [00:55<09:30,  1.56s/it, beta=0.000, gamma=0.000, train_loss=569.1615, val_loss=10374.4326]
Training UniVI:   9%|▉         | 36/400 [00:55<09:25,  1.55s/it, beta=0.000, gamma=0.000, train_loss=569.1615, val_loss=10374.4326]
Training UniVI:   9%|▉         | 36/400 [00:57<09:25,  1.55s/it, beta=0.000, gamma=0.000, train_loss=568.3247, val_loss=10761.4268]
Training UniVI:   9%|▉         | 37/400 [00:57<09:25,  1.56s/it, beta=0.000, gamma=0.000, train_loss=568.3247, val_loss=10761.4268]
Training UniVI:   9%|▉         | 37/400 [00:58<09:25,  1.56s/it, beta=0.000, gamma=0.000, train_loss=567.9129, val_loss=11535.0811]
Training UniVI:  10%|▉         | 38/400 [00:58<09:23,  1.56s/it, beta=0.000, gamma=0.000, train_loss=567.9129, val_loss=11535.0811]
Training UniVI:  10%|▉         | 38/400 [01:00<09:23,  1.56s/it, beta=0.000, gamma=0.000, train_loss=567.0075, val_loss=12653.2656]
Training UniVI:  10%|▉         | 39/400 [01:00<09:20,  1.55s/it, beta=0.000, gamma=0.000, train_loss=567.0075, val_loss=12653.2656]
Training UniVI:  10%|▉         | 39/400 [01:01<09:20,  1.55s/it, beta=0.000, gamma=0.000, train_loss=566.3805, val_loss=14082.3701]
Training UniVI:  10%|█         | 40/400 [01:01<09:15,  1.54s/it, beta=0.000, gamma=0.000, train_loss=566.3805, val_loss=14082.3701]
Training UniVI:  10%|█         | 40/400 [01:03<09:15,  1.54s/it, beta=0.000, gamma=0.000, train_loss=566.0262, val_loss=15776.8379]
Training UniVI:  10%|█         | 41/400 [01:03<09:11,  1.54s/it, beta=0.000, gamma=0.000, train_loss=566.0262, val_loss=15776.8379]
Training UniVI:  10%|█         | 41/400 [01:04<09:11,  1.54s/it, beta=0.000, gamma=0.000, train_loss=565.5368, val_loss=14502.5410]
Training UniVI:  10%|█         | 42/400 [01:04<09:11,  1.54s/it, beta=0.000, gamma=0.000, train_loss=565.5368, val_loss=14502.5410]
Training UniVI:  10%|█         | 42/400 [01:06<09:11,  1.54s/it, beta=0.000, gamma=0.000, train_loss=565.1992, val_loss=16459.5488]
Training UniVI:  11%|█         | 43/400 [01:06<09:09,  1.54s/it, beta=0.000, gamma=0.000, train_loss=565.1992, val_loss=16459.5488]
Training UniVI:  11%|█         | 43/400 [01:07<09:09,  1.54s/it, beta=0.000, gamma=0.000, train_loss=564.5358, val_loss=17407.3164]
Training UniVI:  11%|█         | 44/400 [01:07<09:08,  1.54s/it, beta=0.000, gamma=0.000, train_loss=564.5358, val_loss=17407.3164]
Training UniVI:  11%|█         | 44/400 [01:09<09:08,  1.54s/it, beta=0.000, gamma=0.000, train_loss=564.0448, val_loss=18088.8574]
Training UniVI:  11%|█▏        | 45/400 [01:09<09:03,  1.53s/it, beta=0.000, gamma=0.000, train_loss=564.0448, val_loss=18088.8574]
Training UniVI:  11%|█▏        | 45/400 [01:11<09:03,  1.53s/it, beta=0.000, gamma=0.000, train_loss=563.4700, val_loss=20426.2793]
Training UniVI:  12%|█▏        | 46/400 [01:11<09:04,  1.54s/it, beta=0.000, gamma=0.000, train_loss=563.4700, val_loss=20426.2793]
Training UniVI:  12%|█▏        | 46/400 [01:12<09:04,  1.54s/it, beta=0.000, gamma=0.000, train_loss=563.0944, val_loss=20343.2051]
Training UniVI:  12%|█▏        | 47/400 [01:12<09:01,  1.53s/it, beta=0.000, gamma=0.000, train_loss=563.0944, val_loss=20343.2051]
Training UniVI:  12%|█▏        | 47/400 [01:14<09:01,  1.53s/it, beta=0.000, gamma=0.000, train_loss=563.2148, val_loss=21798.1953]
Training UniVI:  12%|█▏        | 48/400 [01:14<09:00,  1.53s/it, beta=0.000, gamma=0.000, train_loss=563.2148, val_loss=21798.1953]
Training UniVI:  12%|█▏        | 48/400 [01:15<09:00,  1.53s/it, beta=0.000, gamma=0.000, train_loss=562.4736, val_loss=23146.6523]
Training UniVI:  12%|█▏        | 49/400 [01:15<08:56,  1.53s/it, beta=0.000, gamma=0.000, train_loss=562.4736, val_loss=23146.6523]
[2026-09-21 01:00:09,553] [UniVITrainer] [INFO] [Epoch 050] Train loss=562.1614 (beta=0.000, gamma=0.000)
[2026-09-21 01:00:09,649] [UniVITrainer] [INFO] [Epoch 050] Val loss=26081.9082 (beta=1.250, gamma=4.350)
Training UniVI:  12%|█▏        | 49/400 [01:17<08:56,  1.53s/it, beta=0.000, gamma=0.000, train_loss=562.1614, val_loss=26081.9082]
Training UniVI:  12%|█▎        | 50/400 [01:17<08:56,  1.53s/it, beta=0.000, gamma=0.000, train_loss=562.1614, val_loss=26081.9082]
Training UniVI:  12%|█▎        | 50/400 [01:18<08:56,  1.53s/it, beta=0.036, gamma=0.000, train_loss=565.0509, val_loss=20405.1875]
Training UniVI:  13%|█▎        | 51/400 [01:18<08:52,  1.53s/it, beta=0.036, gamma=0.000, train_loss=565.0509, val_loss=20405.1875]
Training UniVI:  13%|█▎        | 51/400 [01:20<08:52,  1.53s/it, beta=0.071, gamma=0.000, train_loss=567.6949, val_loss=10759.2568]
Training UniVI:  13%|█▎        | 52/400 [01:20<08:49,  1.52s/it, beta=0.071, gamma=0.000, train_loss=567.6949, val_loss=10759.2568]
Training UniVI:  13%|█▎        | 52/400 [01:21<08:49,  1.52s/it, beta=0.107, gamma=0.000, train_loss=569.2496, val_loss=4566.3027]
Training UniVI:  13%|█▎        | 53/400 [01:21<08:46,  1.52s/it, beta=0.107, gamma=0.000, train_loss=569.2496, val_loss=4566.3027]
Training UniVI:  13%|█▎        | 53/400 [01:23<08:46,  1.52s/it, beta=0.143, gamma=0.000, train_loss=570.2328, val_loss=2327.6846]
Training UniVI:  14%|█▎        | 54/400 [01:23<08:45,  1.52s/it, beta=0.143, gamma=0.000, train_loss=570.2328, val_loss=2327.6846]
Training UniVI:  14%|█▎        | 54/400 [01:24<08:45,  1.52s/it, beta=0.179, gamma=0.000, train_loss=570.9169, val_loss=1457.9457]
Training UniVI:  14%|█▍        | 55/400 [01:24<08:43,  1.52s/it, beta=0.179, gamma=0.000, train_loss=570.9169, val_loss=1457.9457]
Training UniVI:  14%|█▍        | 55/400 [01:26<08:43,  1.52s/it, beta=0.214, gamma=0.000, train_loss=571.2664, val_loss=1105.2592]
Training UniVI:  14%|█▍        | 56/400 [01:26<08:41,  1.52s/it, beta=0.214, gamma=0.000, train_loss=571.2664, val_loss=1105.2592]
Training UniVI:  14%|█▍        | 56/400 [01:27<08:41,  1.52s/it, beta=0.250, gamma=0.000, train_loss=571.9915, val_loss=956.1557]
Training UniVI:  14%|█▍        | 57/400 [01:27<08:43,  1.53s/it, beta=0.250, gamma=0.000, train_loss=571.9915, val_loss=956.1557]
Training UniVI:  14%|█▍        | 57/400 [01:29<08:43,  1.53s/it, beta=0.286, gamma=0.000, train_loss=573.1311, val_loss=876.0720]
Training UniVI:  14%|█▍        | 58/400 [01:29<09:00,  1.58s/it, beta=0.286, gamma=0.000, train_loss=573.1311, val_loss=876.0720]
Training UniVI:  14%|█▍        | 58/400 [01:31<09:00,  1.58s/it, beta=0.321, gamma=0.000, train_loss=573.6634, val_loss=837.0106]
Training UniVI:  15%|█▍        | 59/400 [01:31<08:54,  1.57s/it, beta=0.321, gamma=0.000, train_loss=573.6634, val_loss=837.0106]
Training UniVI:  15%|█▍        | 59/400 [01:32<08:54,  1.57s/it, beta=0.357, gamma=0.000, train_loss=574.2770, val_loss=792.8387]
Training UniVI:  15%|█▌        | 60/400 [01:32<08:50,  1.56s/it, beta=0.357, gamma=0.000, train_loss=574.2770, val_loss=792.8387]
Training UniVI:  15%|█▌        | 60/400 [01:34<08:50,  1.56s/it, beta=0.393, gamma=0.000, train_loss=574.8395, val_loss=767.6216]
Training UniVI:  15%|█▌        | 61/400 [01:34<08:45,  1.55s/it, beta=0.393, gamma=0.000, train_loss=574.8395, val_loss=767.6216]
Training UniVI:  15%|█▌        | 61/400 [01:35<08:45,  1.55s/it, beta=0.429, gamma=0.000, train_loss=575.6789, val_loss=745.4875]
Training UniVI:  16%|█▌        | 62/400 [01:35<08:49,  1.57s/it, beta=0.429, gamma=0.000, train_loss=575.6789, val_loss=745.4875]
Training UniVI:  16%|█▌        | 62/400 [01:37<08:49,  1.57s/it, beta=0.464, gamma=0.000, train_loss=576.2234, val_loss=741.8503]
Training UniVI:  16%|█▌        | 63/400 [01:37<08:46,  1.56s/it, beta=0.464, gamma=0.000, train_loss=576.2234, val_loss=741.8503]
Training UniVI:  16%|█▌        | 63/400 [01:38<08:46,  1.56s/it, beta=0.500, gamma=0.000, train_loss=576.8146, val_loss=727.1196]
Training UniVI:  16%|█▌        | 64/400 [01:38<08:40,  1.55s/it, beta=0.500, gamma=0.000, train_loss=576.8146, val_loss=727.1196]
Training UniVI:  16%|█▌        | 64/400 [01:40<08:40,  1.55s/it, beta=0.536, gamma=0.000, train_loss=576.8060, val_loss=713.1837]
Training UniVI:  16%|█▋        | 65/400 [01:40<08:38,  1.55s/it, beta=0.536, gamma=0.000, train_loss=576.8060, val_loss=713.1837]
Training UniVI:  16%|█▋        | 65/400 [01:41<08:38,  1.55s/it, beta=0.571, gamma=0.000, train_loss=577.4569, val_loss=708.2587]
Training UniVI:  16%|█▋        | 66/400 [01:41<08:34,  1.54s/it, beta=0.571, gamma=0.000, train_loss=577.4569, val_loss=708.2587]
Training UniVI:  16%|█▋        | 66/400 [01:43<08:34,  1.54s/it, beta=0.607, gamma=0.000, train_loss=578.3580, val_loss=704.6484]
Training UniVI:  17%|█▋        | 67/400 [01:43<08:31,  1.54s/it, beta=0.607, gamma=0.000, train_loss=578.3580, val_loss=704.6484]
Training UniVI:  17%|█▋        | 67/400 [01:44<08:31,  1.54s/it, beta=0.643, gamma=0.000, train_loss=578.5693, val_loss=692.8246]
Training UniVI:  17%|█▋        | 68/400 [01:44<08:29,  1.53s/it, beta=0.643, gamma=0.000, train_loss=578.5693, val_loss=692.8246]
Training UniVI:  17%|█▋        | 68/400 [01:46<08:29,  1.53s/it, beta=0.679, gamma=0.000, train_loss=578.9652, val_loss=686.1740]
Training UniVI:  17%|█▋        | 69/400 [01:46<08:27,  1.53s/it, beta=0.679, gamma=0.000, train_loss=578.9652, val_loss=686.1740]
Training UniVI:  17%|█▋        | 69/400 [01:47<08:27,  1.53s/it, beta=0.714, gamma=0.000, train_loss=579.1409, val_loss=678.9684]
Training UniVI:  18%|█▊        | 70/400 [01:47<08:24,  1.53s/it, beta=0.714, gamma=0.000, train_loss=579.1409, val_loss=678.9684]
Training UniVI:  18%|█▊        | 70/400 [01:49<08:24,  1.53s/it, beta=0.750, gamma=0.000, train_loss=579.4756, val_loss=669.6049]
Training UniVI:  18%|█▊        | 71/400 [01:49<08:23,  1.53s/it, beta=0.750, gamma=0.000, train_loss=579.4756, val_loss=669.6049]
Training UniVI:  18%|█▊        | 71/400 [01:51<08:23,  1.53s/it, beta=0.786, gamma=0.000, train_loss=580.1237, val_loss=675.8754]
Training UniVI:  18%|█▊        | 72/400 [01:51<08:21,  1.53s/it, beta=0.786, gamma=0.000, train_loss=580.1237, val_loss=675.8754]
Training UniVI:  18%|█▊        | 72/400 [01:52<08:21,  1.53s/it, beta=0.821, gamma=0.000, train_loss=580.4073, val_loss=665.6043]
Training UniVI:  18%|█▊        | 73/400 [01:52<08:17,  1.52s/it, beta=0.821, gamma=0.000, train_loss=580.4073, val_loss=665.6043]
Training UniVI:  18%|█▊        | 73/400 [01:54<08:17,  1.52s/it, beta=0.857, gamma=0.000, train_loss=580.4204, val_loss=660.1317]
Training UniVI:  18%|█▊        | 74/400 [01:54<08:16,  1.52s/it, beta=0.857, gamma=0.000, train_loss=580.4204, val_loss=660.1317]
Training UniVI:  18%|█▊        | 74/400 [01:55<08:16,  1.52s/it, beta=0.893, gamma=0.000, train_loss=580.5357, val_loss=665.8461]
Training UniVI:  19%|█▉        | 75/400 [01:55<08:18,  1.53s/it, beta=0.893, gamma=0.000, train_loss=580.5357, val_loss=665.8461]
Training UniVI:  19%|█▉        | 75/400 [01:57<08:18,  1.53s/it, beta=0.929, gamma=0.124, train_loss=583.3665, val_loss=614.7459]
Training UniVI:  19%|█▉        | 76/400 [01:57<08:18,  1.54s/it, beta=0.929, gamma=0.124, train_loss=583.3665, val_loss=614.7459]
Training UniVI:  19%|█▉        | 76/400 [01:58<08:18,  1.54s/it, beta=0.964, gamma=0.249, train_loss=584.9337, val_loss=601.5826]
Training UniVI:  19%|█▉        | 77/400 [01:58<08:22,  1.56s/it, beta=0.964, gamma=0.249, train_loss=584.9337, val_loss=601.5826]
Training UniVI:  19%|█▉        | 77/400 [02:00<08:22,  1.56s/it, beta=1.000, gamma=0.373, train_loss=586.3592, val_loss=594.5400]
Training UniVI:  20%|█▉        | 78/400 [02:00<08:20,  1.55s/it, beta=1.000, gamma=0.373, train_loss=586.3592, val_loss=594.5400]
Training UniVI:  20%|█▉        | 78/400 [02:01<08:20,  1.55s/it, beta=1.036, gamma=0.497, train_loss=587.3823, val_loss=588.3367]
Training UniVI:  20%|█▉        | 79/400 [02:01<08:15,  1.54s/it, beta=1.036, gamma=0.497, train_loss=587.3823, val_loss=588.3367]
Training UniVI:  20%|█▉        | 79/400 [02:03<08:15,  1.54s/it, beta=1.071, gamma=0.621, train_loss=588.6284, val_loss=584.6346]
Training UniVI:  20%|██        | 80/400 [02:03<08:10,  1.53s/it, beta=1.071, gamma=0.621, train_loss=588.6284, val_loss=584.6346]
Training UniVI:  20%|██        | 80/400 [02:04<08:10,  1.53s/it, beta=1.107, gamma=0.746, train_loss=589.4200, val_loss=582.4034]
Training UniVI:  20%|██        | 81/400 [02:04<08:14,  1.55s/it, beta=1.107, gamma=0.746, train_loss=589.4200, val_loss=582.4034]
Training UniVI:  20%|██        | 81/400 [02:06<08:14,  1.55s/it, beta=1.143, gamma=0.870, train_loss=590.1598, val_loss=578.0100]
Training UniVI:  20%|██        | 82/400 [02:06<08:11,  1.55s/it, beta=1.143, gamma=0.870, train_loss=590.1598, val_loss=578.0100]
Training UniVI:  20%|██        | 82/400 [02:07<08:11,  1.55s/it, beta=1.179, gamma=0.994, train_loss=590.3864, val_loss=577.1531]
Training UniVI:  21%|██        | 83/400 [02:07<08:07,  1.54s/it, beta=1.179, gamma=0.994, train_loss=590.3864, val_loss=577.1531]
Training UniVI:  21%|██        | 83/400 [02:09<08:07,  1.54s/it, beta=1.214, gamma=1.119, train_loss=590.8575, val_loss=574.8228]
Training UniVI:  21%|██        | 84/400 [02:09<08:07,  1.54s/it, beta=1.214, gamma=1.119, train_loss=590.8575, val_loss=574.8228]
Training UniVI:  21%|██        | 84/400 [02:11<08:07,  1.54s/it, beta=1.250, gamma=1.243, train_loss=591.5443, val_loss=573.5441]
Training UniVI:  21%|██▏       | 85/400 [02:11<08:19,  1.59s/it, beta=1.250, gamma=1.243, train_loss=591.5443, val_loss=573.5441]
Training UniVI:  21%|██▏       | 85/400 [02:12<08:19,  1.59s/it, beta=1.250, gamma=1.367, train_loss=591.6175, val_loss=572.0430]
Training UniVI:  22%|██▏       | 86/400 [02:12<08:13,  1.57s/it, beta=1.250, gamma=1.367, train_loss=591.6175, val_loss=572.0430]
Training UniVI:  22%|██▏       | 86/400 [02:14<08:13,  1.57s/it, beta=1.250, gamma=1.491, train_loss=591.8157, val_loss=572.3853]
Training UniVI:  22%|██▏       | 87/400 [02:14<08:07,  1.56s/it, beta=1.250, gamma=1.491, train_loss=591.8157, val_loss=572.3853]
Training UniVI:  22%|██▏       | 87/400 [02:15<08:07,  1.56s/it, beta=1.250, gamma=1.616, train_loss=591.9002, val_loss=571.0907]
Training UniVI:  22%|██▏       | 88/400 [02:15<08:01,  1.54s/it, beta=1.250, gamma=1.616, train_loss=591.9002, val_loss=571.0907]
Training UniVI:  22%|██▏       | 88/400 [02:17<08:01,  1.54s/it, beta=1.250, gamma=1.740, train_loss=591.8035, val_loss=569.0499]
Training UniVI:  22%|██▏       | 89/400 [02:17<08:00,  1.55s/it, beta=1.250, gamma=1.740, train_loss=591.8035, val_loss=569.0499]
Training UniVI:  22%|██▏       | 89/400 [02:18<08:00,  1.55s/it, beta=1.250, gamma=1.864, train_loss=591.8622, val_loss=569.6931]
Training UniVI:  22%|██▎       | 90/400 [02:18<07:56,  1.54s/it, beta=1.250, gamma=1.864, train_loss=591.8622, val_loss=569.6931]
Training UniVI:  22%|██▎       | 90/400 [02:20<07:56,  1.54s/it, beta=1.250, gamma=1.989, train_loss=591.8622, val_loss=569.4761]
Training UniVI:  23%|██▎       | 91/400 [02:20<07:53,  1.53s/it, beta=1.250, gamma=1.989, train_loss=591.8622, val_loss=569.4761]
Training UniVI:  23%|██▎       | 91/400 [02:21<07:53,  1.53s/it, beta=1.250, gamma=2.113, train_loss=591.9935, val_loss=568.9213]
Training UniVI:  23%|██▎       | 92/400 [02:21<07:51,  1.53s/it, beta=1.250, gamma=2.113, train_loss=591.9935, val_loss=568.9213]
Training UniVI:  23%|██▎       | 92/400 [02:23<07:51,  1.53s/it, beta=1.250, gamma=2.237, train_loss=592.1414, val_loss=568.5129]
Training UniVI:  23%|██▎       | 93/400 [02:23<07:48,  1.53s/it, beta=1.250, gamma=2.237, train_loss=592.1414, val_loss=568.5129]
Training UniVI:  23%|██▎       | 93/400 [02:24<07:48,  1.53s/it, beta=1.250, gamma=2.361, train_loss=592.0294, val_loss=567.1006]
Training UniVI:  24%|██▎       | 94/400 [02:24<07:47,  1.53s/it, beta=1.250, gamma=2.361, train_loss=592.0294, val_loss=567.1006]
Training UniVI:  24%|██▎       | 94/400 [02:26<07:47,  1.53s/it, beta=1.250, gamma=2.486, train_loss=592.0440, val_loss=567.1113]
Training UniVI:  24%|██▍       | 95/400 [02:26<07:47,  1.53s/it, beta=1.250, gamma=2.486, train_loss=592.0440, val_loss=567.1113]
Training UniVI:  24%|██▍       | 95/400 [02:28<07:47,  1.53s/it, beta=1.250, gamma=2.610, train_loss=591.9583, val_loss=566.6970]
Training UniVI:  24%|██▍       | 96/400 [02:28<07:50,  1.55s/it, beta=1.250, gamma=2.610, train_loss=591.9583, val_loss=566.6970]
Training UniVI:  24%|██▍       | 96/400 [02:29<07:50,  1.55s/it, beta=1.250, gamma=2.734, train_loss=592.5014, val_loss=567.6807]
Training UniVI:  24%|██▍       | 97/400 [02:29<07:53,  1.56s/it, beta=1.250, gamma=2.734, train_loss=592.5014, val_loss=567.6807]
Training UniVI:  24%|██▍       | 97/400 [02:31<07:53,  1.56s/it, beta=1.250, gamma=2.859, train_loss=592.3454, val_loss=566.1569]
Training UniVI:  24%|██▍       | 98/400 [02:31<07:49,  1.55s/it, beta=1.250, gamma=2.859, train_loss=592.3454, val_loss=566.1569]
Training UniVI:  24%|██▍       | 98/400 [02:32<07:49,  1.55s/it, beta=1.250, gamma=2.983, train_loss=592.5273, val_loss=565.2050]
Training UniVI:  25%|██▍       | 99/400 [02:32<07:44,  1.54s/it, beta=1.250, gamma=2.983, train_loss=592.5273, val_loss=565.2050]
[2026-09-21 01:01:26,661] [UniVITrainer] [INFO] [Epoch 100] Train loss=592.2073 (beta=1.250, gamma=3.107)
[2026-09-21 01:01:26,750] [UniVITrainer] [INFO] [Epoch 100] Val loss=565.8599 (beta=1.250, gamma=4.350)
Training UniVI:  25%|██▍       | 99/400 [02:34<07:44,  1.54s/it, beta=1.250, gamma=3.107, train_loss=592.2073, val_loss=565.8599]
Training UniVI:  25%|██▌       | 100/400 [02:34<07:41,  1.54s/it, beta=1.250, gamma=3.107, train_loss=592.2073, val_loss=565.8599]
Training UniVI:  25%|██▌       | 100/400 [02:35<07:41,  1.54s/it, beta=1.250, gamma=3.231, train_loss=591.9524, val_loss=565.7328]
Training UniVI:  25%|██▌       | 101/400 [02:35<07:39,  1.54s/it, beta=1.250, gamma=3.231, train_loss=591.9524, val_loss=565.7328]
Training UniVI:  25%|██▌       | 101/400 [02:37<07:39,  1.54s/it, beta=1.250, gamma=3.356, train_loss=592.8247, val_loss=564.9425]
Training UniVI:  26%|██▌       | 102/400 [02:37<07:40,  1.55s/it, beta=1.250, gamma=3.356, train_loss=592.8247, val_loss=564.9425]
Training UniVI:  26%|██▌       | 102/400 [02:38<07:40,  1.55s/it, beta=1.250, gamma=3.480, train_loss=592.3044, val_loss=565.0009]
Training UniVI:  26%|██▌       | 103/400 [02:38<07:37,  1.54s/it, beta=1.250, gamma=3.480, train_loss=592.3044, val_loss=565.0009]
Training UniVI:  26%|██▌       | 103/400 [02:40<07:37,  1.54s/it, beta=1.250, gamma=3.604, train_loss=592.1323, val_loss=565.2573]
Training UniVI:  26%|██▌       | 104/400 [02:40<07:35,  1.54s/it, beta=1.250, gamma=3.604, train_loss=592.1323, val_loss=565.2573]
Training UniVI:  26%|██▌       | 104/400 [02:42<07:35,  1.54s/it, beta=1.250, gamma=3.729, train_loss=592.5538, val_loss=564.5836]
Training UniVI:  26%|██▋       | 105/400 [02:42<07:36,  1.55s/it, beta=1.250, gamma=3.729, train_loss=592.5538, val_loss=564.5836]
Training UniVI:  26%|██▋       | 105/400 [02:43<07:36,  1.55s/it, beta=1.250, gamma=3.853, train_loss=592.1316, val_loss=563.9470]
Training UniVI:  26%|██▋       | 106/400 [02:43<07:33,  1.54s/it, beta=1.250, gamma=3.853, train_loss=592.1316, val_loss=563.9470]
Training UniVI:  26%|██▋       | 106/400 [02:45<07:33,  1.54s/it, beta=1.250, gamma=3.977, train_loss=592.7560, val_loss=564.5496]
Training UniVI:  27%|██▋       | 107/400 [02:45<07:31,  1.54s/it, beta=1.250, gamma=3.977, train_loss=592.7560, val_loss=564.5496]
Training UniVI:  27%|██▋       | 107/400 [02:46<07:31,  1.54s/it, beta=1.250, gamma=4.101, train_loss=592.5773, val_loss=563.7704]
Training UniVI:  27%|██▋       | 108/400 [02:46<07:28,  1.54s/it, beta=1.250, gamma=4.101, train_loss=592.5773, val_loss=563.7704]
Training UniVI:  27%|██▋       | 108/400 [02:48<07:28,  1.54s/it, beta=1.250, gamma=4.226, train_loss=592.4919, val_loss=562.8469]
[2026-09-21 01:01:40,597] [UniVITrainer] [INFO] [Epoch 109] Best tracking warmup ends next epoch (best_epoch_warmup=110).
Training UniVI:  27%|██▋       | 109/400 [02:48<07:25,  1.53s/it, beta=1.250, gamma=4.226, train_loss=592.4919, val_loss=562.8469]
Training UniVI:  27%|██▋       | 109/400 [02:49<07:25,  1.53s/it, beta=1.250, gamma=4.350, train_loss=592.4761, val_loss=563.8130]
[2026-09-21 01:01:42,113] [UniVITrainer] [INFO] [Epoch 110] New best val loss: 563.8130
Training UniVI:  28%|██▊       | 110/400 [02:49<07:22,  1.53s/it, beta=1.250, gamma=4.350, train_loss=592.4761, val_loss=563.8130]
Training UniVI:  28%|██▊       | 110/400 [02:51<07:22,  1.53s/it, beta=1.250, gamma=4.350, train_loss=592.4321, val_loss=564.0607]
Training UniVI:  28%|██▊       | 111/400 [02:51<07:23,  1.54s/it, beta=1.250, gamma=4.350, train_loss=592.4321, val_loss=564.0607]
Training UniVI:  28%|██▊       | 111/400 [02:52<07:23,  1.54s/it, beta=1.250, gamma=4.350, train_loss=592.2151, val_loss=563.5482]
[2026-09-21 01:01:45,188] [UniVITrainer] [INFO] [Epoch 112] New best val loss: 563.5482
Training UniVI:  28%|██▊       | 112/400 [02:52<07:20,  1.53s/it, beta=1.250, gamma=4.350, train_loss=592.2151, val_loss=563.5482]
Training UniVI:  28%|██▊       | 112/400 [02:54<07:20,  1.53s/it, beta=1.250, gamma=4.350, train_loss=592.4882, val_loss=563.3478]
[2026-09-21 01:01:46,768] [UniVITrainer] [INFO] [Epoch 113] New best val loss: 563.3478
Training UniVI:  28%|██▊       | 113/400 [02:54<07:23,  1.55s/it, beta=1.250, gamma=4.350, train_loss=592.4882, val_loss=563.3478]
Training UniVI:  28%|██▊       | 113/400 [02:55<07:23,  1.55s/it, beta=1.250, gamma=4.350, train_loss=591.6003, val_loss=564.1714]
Training UniVI:  28%|██▊       | 114/400 [02:55<07:22,  1.55s/it, beta=1.250, gamma=4.350, train_loss=591.6003, val_loss=564.1714]
Training UniVI:  28%|██▊       | 114/400 [02:57<07:22,  1.55s/it, beta=1.250, gamma=4.350, train_loss=591.9966, val_loss=563.5090]
Training UniVI:  29%|██▉       | 115/400 [02:57<07:20,  1.55s/it, beta=1.250, gamma=4.350, train_loss=591.9966, val_loss=563.5090]
Training UniVI:  29%|██▉       | 115/400 [02:58<07:20,  1.55s/it, beta=1.250, gamma=4.350, train_loss=591.9016, val_loss=563.2977]
[2026-09-21 01:01:51,381] [UniVITrainer] [INFO] [Epoch 116] New best val loss: 563.2977
Training UniVI:  29%|██▉       | 116/400 [02:58<07:16,  1.54s/it, beta=1.250, gamma=4.350, train_loss=591.9016, val_loss=563.2977]
Training UniVI:  29%|██▉       | 116/400 [03:00<07:16,  1.54s/it, beta=1.250, gamma=4.350, train_loss=591.7722, val_loss=563.6526]
Training UniVI:  29%|██▉       | 117/400 [03:00<07:15,  1.54s/it, beta=1.250, gamma=4.350, train_loss=591.7722, val_loss=563.6526]
Training UniVI:  29%|██▉       | 117/400 [03:01<07:15,  1.54s/it, beta=1.250, gamma=4.350, train_loss=591.4247, val_loss=563.5334]
Training UniVI:  30%|██▉       | 118/400 [03:01<07:14,  1.54s/it, beta=1.250, gamma=4.350, train_loss=591.4247, val_loss=563.5334]
Training UniVI:  30%|██▉       | 118/400 [03:03<07:14,  1.54s/it, beta=1.250, gamma=4.350, train_loss=591.3850, val_loss=563.2593]
[2026-09-21 01:01:55,993] [UniVITrainer] [INFO] [Epoch 119] New best val loss: 563.2593
Training UniVI:  30%|██▉       | 119/400 [03:03<07:11,  1.54s/it, beta=1.250, gamma=4.350, train_loss=591.3850, val_loss=563.2593]
Training UniVI:  30%|██▉       | 119/400 [03:05<07:11,  1.54s/it, beta=1.250, gamma=4.350, train_loss=591.0233, val_loss=563.6340]
Training UniVI:  30%|███       | 120/400 [03:05<07:12,  1.54s/it, beta=1.250, gamma=4.350, train_loss=591.0233, val_loss=563.6340]
Training UniVI:  30%|███       | 120/400 [03:06<07:12,  1.54s/it, beta=1.250, gamma=4.350, train_loss=591.1945, val_loss=563.1671]
[2026-09-21 01:01:59,108] [UniVITrainer] [INFO] [Epoch 121] New best val loss: 563.1671
Training UniVI:  30%|███       | 121/400 [03:06<07:11,  1.55s/it, beta=1.250, gamma=4.350, train_loss=591.1945, val_loss=563.1671]
Training UniVI:  30%|███       | 121/400 [03:08<07:11,  1.55s/it, beta=1.250, gamma=4.350, train_loss=591.0008, val_loss=563.4450]
Training UniVI:  30%|███       | 122/400 [03:08<07:08,  1.54s/it, beta=1.250, gamma=4.350, train_loss=591.0008, val_loss=563.4450]
Training UniVI:  30%|███       | 122/400 [03:09<07:08,  1.54s/it, beta=1.250, gamma=4.350, train_loss=590.5717, val_loss=562.3444]
[2026-09-21 01:02:02,222] [UniVITrainer] [INFO] [Epoch 123] New best val loss: 562.3444
Training UniVI:  31%|███       | 123/400 [03:09<07:10,  1.55s/it, beta=1.250, gamma=4.350, train_loss=590.5717, val_loss=562.3444]
Training UniVI:  31%|███       | 123/400 [03:11<07:10,  1.55s/it, beta=1.250, gamma=4.350, train_loss=590.4162, val_loss=562.8185]
Training UniVI:  31%|███       | 124/400 [03:11<07:13,  1.57s/it, beta=1.250, gamma=4.350, train_loss=590.4162, val_loss=562.8185]
Training UniVI:  31%|███       | 124/400 [03:12<07:13,  1.57s/it, beta=1.250, gamma=4.350, train_loss=590.3469, val_loss=563.3680]
Training UniVI:  31%|███▏      | 125/400 [03:12<07:08,  1.56s/it, beta=1.250, gamma=4.350, train_loss=590.3469, val_loss=563.3680]
Training UniVI:  31%|███▏      | 125/400 [03:14<07:08,  1.56s/it, beta=1.250, gamma=4.350, train_loss=590.5577, val_loss=563.5060]
Training UniVI:  32%|███▏      | 126/400 [03:14<07:03,  1.54s/it, beta=1.250, gamma=4.350, train_loss=590.5577, val_loss=563.5060]
Training UniVI:  32%|███▏      | 126/400 [03:15<07:03,  1.54s/it, beta=1.250, gamma=4.350, train_loss=590.3604, val_loss=563.1414]
Training UniVI:  32%|███▏      | 127/400 [03:15<07:00,  1.54s/it, beta=1.250, gamma=4.350, train_loss=590.3604, val_loss=563.1414]
Training UniVI:  32%|███▏      | 127/400 [03:17<07:00,  1.54s/it, beta=1.250, gamma=4.350, train_loss=590.4595, val_loss=563.3854]
Training UniVI:  32%|███▏      | 128/400 [03:17<06:58,  1.54s/it, beta=1.250, gamma=4.350, train_loss=590.4595, val_loss=563.3854]
Training UniVI:  32%|███▏      | 128/400 [03:18<06:58,  1.54s/it, beta=1.250, gamma=4.350, train_loss=590.0556, val_loss=562.9994]
Training UniVI:  32%|███▏      | 129/400 [03:18<06:55,  1.53s/it, beta=1.250, gamma=4.350, train_loss=590.0556, val_loss=562.9994]
Training UniVI:  32%|███▏      | 129/400 [03:20<06:55,  1.53s/it, beta=1.250, gamma=4.350, train_loss=590.2075, val_loss=563.4799]
Training UniVI:  32%|███▎      | 130/400 [03:20<06:52,  1.53s/it, beta=1.250, gamma=4.350, train_loss=590.2075, val_loss=563.4799]
Training UniVI:  32%|███▎      | 130/400 [03:22<06:52,  1.53s/it, beta=1.250, gamma=4.350, train_loss=590.2020, val_loss=562.7233]
Training UniVI:  33%|███▎      | 131/400 [03:22<06:50,  1.52s/it, beta=1.250, gamma=4.350, train_loss=590.2020, val_loss=562.7233]
Training UniVI:  33%|███▎      | 131/400 [03:23<06:50,  1.52s/it, beta=1.250, gamma=4.350, train_loss=589.4321, val_loss=563.3311]
Training UniVI:  33%|███▎      | 132/400 [03:23<06:48,  1.52s/it, beta=1.250, gamma=4.350, train_loss=589.4321, val_loss=563.3311]
Training UniVI:  33%|███▎      | 132/400 [03:25<06:48,  1.52s/it, beta=1.250, gamma=4.350, train_loss=589.8997, val_loss=564.0758]
Training UniVI:  33%|███▎      | 133/400 [03:25<06:48,  1.53s/it, beta=1.250, gamma=4.350, train_loss=589.8997, val_loss=564.0758]
Training UniVI:  33%|███▎      | 133/400 [03:26<06:48,  1.53s/it, beta=1.250, gamma=4.350, train_loss=589.1749, val_loss=563.0874]
Training UniVI:  34%|███▎      | 134/400 [03:26<06:46,  1.53s/it, beta=1.250, gamma=4.350, train_loss=589.1749, val_loss=563.0874]
Training UniVI:  34%|███▎      | 134/400 [03:28<06:46,  1.53s/it, beta=1.250, gamma=4.350, train_loss=589.8703, val_loss=562.7892]
Training UniVI:  34%|███▍      | 135/400 [03:28<06:48,  1.54s/it, beta=1.250, gamma=4.350, train_loss=589.8703, val_loss=562.7892]
Training UniVI:  34%|███▍      | 135/400 [03:29<06:48,  1.54s/it, beta=1.250, gamma=4.350, train_loss=589.3388, val_loss=563.6404]
Training UniVI:  34%|███▍      | 136/400 [03:29<06:53,  1.57s/it, beta=1.250, gamma=4.350, train_loss=589.3388, val_loss=563.6404]
Training UniVI:  34%|███▍      | 136/400 [03:31<06:53,  1.57s/it, beta=1.250, gamma=4.350, train_loss=589.1556, val_loss=562.9666]
Training UniVI:  34%|███▍      | 137/400 [03:31<06:49,  1.56s/it, beta=1.250, gamma=4.350, train_loss=589.1556, val_loss=562.9666]
Training UniVI:  34%|███▍      | 137/400 [03:32<06:49,  1.56s/it, beta=1.250, gamma=4.350, train_loss=589.4346, val_loss=562.9344]
Training UniVI:  34%|███▍      | 138/400 [03:32<06:55,  1.59s/it, beta=1.250, gamma=4.350, train_loss=589.4346, val_loss=562.9344]
Training UniVI:  34%|███▍      | 138/400 [03:34<06:55,  1.59s/it, beta=1.250, gamma=4.350, train_loss=589.1638, val_loss=562.6082]
Training UniVI:  35%|███▍      | 139/400 [03:34<06:50,  1.57s/it, beta=1.250, gamma=4.350, train_loss=589.1638, val_loss=562.6082]
Training UniVI:  35%|███▍      | 139/400 [03:36<06:50,  1.57s/it, beta=1.250, gamma=4.350, train_loss=589.3590, val_loss=562.5450]
Training UniVI:  35%|███▌      | 140/400 [03:36<06:49,  1.58s/it, beta=1.250, gamma=4.350, train_loss=589.3590, val_loss=562.5450]
Training UniVI:  35%|███▌      | 140/400 [03:37<06:49,  1.58s/it, beta=1.250, gamma=4.350, train_loss=589.1050, val_loss=563.5695]
Training UniVI:  35%|███▌      | 141/400 [03:37<06:43,  1.56s/it, beta=1.250, gamma=4.350, train_loss=589.1050, val_loss=563.5695]
Training UniVI:  35%|███▌      | 141/400 [03:39<06:43,  1.56s/it, beta=1.250, gamma=4.350, train_loss=588.5941, val_loss=562.1112]
[2026-09-21 01:02:31,635] [UniVITrainer] [INFO] [Epoch 142] New best val loss: 562.1112
Training UniVI:  36%|███▌      | 142/400 [03:39<06:39,  1.55s/it, beta=1.250, gamma=4.350, train_loss=588.5941, val_loss=562.1112]
Training UniVI:  36%|███▌      | 142/400 [03:40<06:39,  1.55s/it, beta=1.250, gamma=4.350, train_loss=588.5826, val_loss=562.6511]
Training UniVI:  36%|███▌      | 143/400 [03:40<06:37,  1.55s/it, beta=1.250, gamma=4.350, train_loss=588.5826, val_loss=562.6511]
Training UniVI:  36%|███▌      | 143/400 [03:42<06:37,  1.55s/it, beta=1.250, gamma=4.350, train_loss=588.1487, val_loss=563.5067]
Training UniVI:  36%|███▌      | 144/400 [03:42<06:35,  1.54s/it, beta=1.250, gamma=4.350, train_loss=588.1487, val_loss=563.5067]
Training UniVI:  36%|███▌      | 144/400 [03:43<06:35,  1.54s/it, beta=1.250, gamma=4.350, train_loss=588.6915, val_loss=562.8868]
Training UniVI:  36%|███▋      | 145/400 [03:43<06:31,  1.54s/it, beta=1.250, gamma=4.350, train_loss=588.6915, val_loss=562.8868]
Training UniVI:  36%|███▋      | 145/400 [03:45<06:31,  1.54s/it, beta=1.250, gamma=4.350, train_loss=588.2909, val_loss=563.2031]
Training UniVI:  36%|███▋      | 146/400 [03:45<06:29,  1.53s/it, beta=1.250, gamma=4.350, train_loss=588.2909, val_loss=563.2031]
Training UniVI:  36%|███▋      | 146/400 [03:46<06:29,  1.53s/it, beta=1.250, gamma=4.350, train_loss=588.4942, val_loss=562.6237]
Training UniVI:  37%|███▋      | 147/400 [03:46<06:29,  1.54s/it, beta=1.250, gamma=4.350, train_loss=588.4942, val_loss=562.6237]
Training UniVI:  37%|███▋      | 147/400 [03:48<06:29,  1.54s/it, beta=1.250, gamma=4.350, train_loss=588.6310, val_loss=563.2789]
Training UniVI:  37%|███▋      | 148/400 [03:48<06:29,  1.54s/it, beta=1.250, gamma=4.350, train_loss=588.6310, val_loss=563.2789]
Training UniVI:  37%|███▋      | 148/400 [03:49<06:29,  1.54s/it, beta=1.250, gamma=4.350, train_loss=588.1923, val_loss=563.5789]
Training UniVI:  37%|███▋      | 149/400 [03:49<06:31,  1.56s/it, beta=1.250, gamma=4.350, train_loss=588.1923, val_loss=563.5789]
[2026-09-21 01:02:43,913] [UniVITrainer] [INFO] [Epoch 150] Train loss=588.4368 (beta=1.250, gamma=4.350)
[2026-09-21 01:02:44,003] [UniVITrainer] [INFO] [Epoch 150] Val loss=563.2269 (beta=1.250, gamma=4.350)
Training UniVI:  37%|███▋      | 149/400 [03:51<06:31,  1.56s/it, beta=1.250, gamma=4.350, train_loss=588.4368, val_loss=563.2269]
Training UniVI:  38%|███▊      | 150/400 [03:51<06:28,  1.55s/it, beta=1.250, gamma=4.350, train_loss=588.4368, val_loss=563.2269]
Training UniVI:  38%|███▊      | 150/400 [03:53<06:28,  1.55s/it, beta=1.250, gamma=4.350, train_loss=588.3859, val_loss=563.1212]
Training UniVI:  38%|███▊      | 151/400 [03:53<06:26,  1.55s/it, beta=1.250, gamma=4.350, train_loss=588.3859, val_loss=563.1212]
Training UniVI:  38%|███▊      | 151/400 [03:54<06:26,  1.55s/it, beta=1.250, gamma=4.350, train_loss=588.3397, val_loss=562.6656]
Training UniVI:  38%|███▊      | 152/400 [03:54<06:23,  1.55s/it, beta=1.250, gamma=4.350, train_loss=588.3397, val_loss=562.6656]
Training UniVI:  38%|███▊      | 152/400 [03:56<06:23,  1.55s/it, beta=1.250, gamma=4.350, train_loss=588.1694, val_loss=563.5648]
Training UniVI:  38%|███▊      | 153/400 [03:56<06:20,  1.54s/it, beta=1.250, gamma=4.350, train_loss=588.1694, val_loss=563.5648]
Training UniVI:  38%|███▊      | 153/400 [03:57<06:20,  1.54s/it, beta=1.250, gamma=4.350, train_loss=588.1359, val_loss=562.8400]
Training UniVI:  38%|███▊      | 154/400 [03:57<06:18,  1.54s/it, beta=1.250, gamma=4.350, train_loss=588.1359, val_loss=562.8400]
Training UniVI:  38%|███▊      | 154/400 [03:59<06:18,  1.54s/it, beta=1.250, gamma=4.350, train_loss=588.4912, val_loss=563.3677]
Training UniVI:  39%|███▉      | 155/400 [03:59<06:16,  1.54s/it, beta=1.250, gamma=4.350, train_loss=588.4912, val_loss=563.3677]
Training UniVI:  39%|███▉      | 155/400 [04:00<06:16,  1.54s/it, beta=1.250, gamma=4.350, train_loss=588.2675, val_loss=563.3976]
Training UniVI:  39%|███▉      | 156/400 [04:00<06:13,  1.53s/it, beta=1.250, gamma=4.350, train_loss=588.2675, val_loss=563.3976]
Training UniVI:  39%|███▉      | 156/400 [04:02<06:13,  1.53s/it, beta=1.250, gamma=4.350, train_loss=587.9288, val_loss=563.0774]
Training UniVI:  39%|███▉      | 157/400 [04:02<06:12,  1.53s/it, beta=1.250, gamma=4.350, train_loss=587.9288, val_loss=563.0774]
Training UniVI:  39%|███▉      | 157/400 [04:03<06:12,  1.53s/it, beta=1.250, gamma=4.350, train_loss=587.6100, val_loss=563.4537]
Training UniVI:  40%|███▉      | 158/400 [04:03<06:11,  1.53s/it, beta=1.250, gamma=4.350, train_loss=587.6100, val_loss=563.4537]
Training UniVI:  40%|███▉      | 158/400 [04:05<06:11,  1.53s/it, beta=1.250, gamma=4.350, train_loss=587.4532, val_loss=562.8994]
Training UniVI:  40%|███▉      | 159/400 [04:05<06:12,  1.54s/it, beta=1.250, gamma=4.350, train_loss=587.4532, val_loss=562.8994]
Training UniVI:  40%|███▉      | 159/400 [04:06<06:12,  1.54s/it, beta=1.250, gamma=4.350, train_loss=587.9470, val_loss=562.7375]
Training UniVI:  40%|████      | 160/400 [04:06<06:10,  1.54s/it, beta=1.250, gamma=4.350, train_loss=587.9470, val_loss=562.7375]
Training UniVI:  40%|████      | 160/400 [04:08<06:10,  1.54s/it, beta=1.250, gamma=4.350, train_loss=587.8138, val_loss=563.4728]
Training UniVI:  40%|████      | 161/400 [04:08<06:06,  1.53s/it, beta=1.250, gamma=4.350, train_loss=587.8138, val_loss=563.4728]
Training UniVI:  40%|████      | 161/400 [04:09<06:06,  1.53s/it, beta=1.250, gamma=4.350, train_loss=587.6317, val_loss=563.4167]
Training UniVI:  40%|████      | 162/400 [04:09<06:03,  1.53s/it, beta=1.250, gamma=4.350, train_loss=587.6317, val_loss=563.4167]
Training UniVI:  40%|████      | 162/400 [04:11<06:03,  1.53s/it, beta=1.250, gamma=4.350, train_loss=587.2909, val_loss=564.2297]
Training UniVI:  41%|████      | 163/400 [04:11<06:02,  1.53s/it, beta=1.250, gamma=4.350, train_loss=587.2909, val_loss=564.2297]
Training UniVI:  41%|████      | 163/400 [04:12<06:02,  1.53s/it, beta=1.250, gamma=4.350, train_loss=587.2202, val_loss=562.2927]
Training UniVI:  41%|████      | 164/400 [04:12<06:00,  1.53s/it, beta=1.250, gamma=4.350, train_loss=587.2202, val_loss=562.2927]
Training UniVI:  41%|████      | 164/400 [04:14<06:00,  1.53s/it, beta=1.250, gamma=4.350, train_loss=587.8414, val_loss=563.6866]
Training UniVI:  41%|████▏     | 165/400 [04:14<06:00,  1.53s/it, beta=1.250, gamma=4.350, train_loss=587.8414, val_loss=563.6866]
Training UniVI:  41%|████▏     | 165/400 [04:16<06:00,  1.53s/it, beta=1.250, gamma=4.350, train_loss=587.6000, val_loss=563.0455]
Training UniVI:  42%|████▏     | 166/400 [04:16<05:58,  1.53s/it, beta=1.250, gamma=4.350, train_loss=587.6000, val_loss=563.0455]
Training UniVI:  42%|████▏     | 166/400 [04:17<05:58,  1.53s/it, beta=1.250, gamma=4.350, train_loss=587.2424, val_loss=563.3159]
Training UniVI:  42%|████▏     | 167/400 [04:17<05:59,  1.54s/it, beta=1.250, gamma=4.350, train_loss=587.2424, val_loss=563.3159]
Training UniVI:  42%|████▏     | 167/400 [04:19<05:59,  1.54s/it, beta=1.250, gamma=4.350, train_loss=587.2845, val_loss=563.1484]
Training UniVI:  42%|████▏     | 168/400 [04:19<05:56,  1.53s/it, beta=1.250, gamma=4.350, train_loss=587.2845, val_loss=563.1484]
Training UniVI:  42%|████▏     | 168/400 [04:20<05:56,  1.53s/it, beta=1.250, gamma=4.350, train_loss=587.5021, val_loss=563.7892]
Training UniVI:  42%|████▏     | 169/400 [04:20<05:53,  1.53s/it, beta=1.250, gamma=4.350, train_loss=587.5021, val_loss=563.7892]
Training UniVI:  42%|████▏     | 169/400 [04:22<05:53,  1.53s/it, beta=1.250, gamma=4.350, train_loss=587.6455, val_loss=563.5106]
Training UniVI:  42%|████▎     | 170/400 [04:22<05:52,  1.53s/it, beta=1.250, gamma=4.350, train_loss=587.6455, val_loss=563.5106]
Training UniVI:  42%|████▎     | 170/400 [04:23<05:52,  1.53s/it, beta=1.250, gamma=4.350, train_loss=587.8624, val_loss=564.3004]
Training UniVI:  43%|████▎     | 171/400 [04:23<05:49,  1.53s/it, beta=1.250, gamma=4.350, train_loss=587.8624, val_loss=564.3004]
Training UniVI:  43%|████▎     | 171/400 [04:25<05:49,  1.53s/it, beta=1.250, gamma=4.350, train_loss=587.6509, val_loss=563.8875]
Training UniVI:  43%|████▎     | 172/400 [04:25<05:49,  1.53s/it, beta=1.250, gamma=4.350, train_loss=587.6509, val_loss=563.8875]
Training UniVI:  43%|████▎     | 172/400 [04:26<05:49,  1.53s/it, beta=1.250, gamma=4.350, train_loss=587.4847, val_loss=563.3040]
Training UniVI:  43%|████▎     | 173/400 [04:26<05:48,  1.53s/it, beta=1.250, gamma=4.350, train_loss=587.4847, val_loss=563.3040]
Training UniVI:  43%|████▎     | 173/400 [04:28<05:48,  1.53s/it, beta=1.250, gamma=4.350, train_loss=586.9467, val_loss=563.4670]
Training UniVI:  44%|████▎     | 174/400 [04:28<05:53,  1.57s/it, beta=1.250, gamma=4.350, train_loss=586.9467, val_loss=563.4670]
Training UniVI:  44%|████▎     | 174/400 [04:30<05:53,  1.57s/it, beta=1.250, gamma=4.350, train_loss=587.0496, val_loss=564.0400]
Training UniVI:  44%|████▍     | 175/400 [04:30<05:54,  1.57s/it, beta=1.250, gamma=4.350, train_loss=587.0496, val_loss=564.0400]
Training UniVI:  44%|████▍     | 175/400 [04:31<05:54,  1.57s/it, beta=1.250, gamma=4.350, train_loss=586.9175, val_loss=563.4199]
Training UniVI:  44%|████▍     | 176/400 [04:31<05:50,  1.56s/it, beta=1.250, gamma=4.350, train_loss=586.9175, val_loss=563.4199]
Training UniVI:  44%|████▍     | 176/400 [04:33<05:50,  1.56s/it, beta=1.250, gamma=4.350, train_loss=586.4289, val_loss=563.0624]
Training UniVI:  44%|████▍     | 177/400 [04:33<05:47,  1.56s/it, beta=1.250, gamma=4.350, train_loss=586.4289, val_loss=563.0624]
Training UniVI:  44%|████▍     | 177/400 [04:34<05:47,  1.56s/it, beta=1.250, gamma=4.350, train_loss=586.7579, val_loss=564.5703]
Training UniVI:  44%|████▍     | 178/400 [04:34<05:42,  1.54s/it, beta=1.250, gamma=4.350, train_loss=586.7579, val_loss=564.5703]
Training UniVI:  44%|████▍     | 178/400 [04:36<05:42,  1.54s/it, beta=1.250, gamma=4.350, train_loss=586.5503, val_loss=563.9557]
Training UniVI:  45%|████▍     | 179/400 [04:36<05:42,  1.55s/it, beta=1.250, gamma=4.350, train_loss=586.5503, val_loss=563.9557]
Training UniVI:  45%|████▍     | 179/400 [04:37<05:42,  1.55s/it, beta=1.250, gamma=4.350, train_loss=586.6799, val_loss=563.6429]
Training UniVI:  45%|████▌     | 180/400 [04:37<05:40,  1.55s/it, beta=1.250, gamma=4.350, train_loss=586.6799, val_loss=563.6429]
Training UniVI:  45%|████▌     | 180/400 [04:39<05:40,  1.55s/it, beta=1.250, gamma=4.350, train_loss=586.7406, val_loss=563.6834]
Training UniVI:  45%|████▌     | 181/400 [04:39<05:37,  1.54s/it, beta=1.250, gamma=4.350, train_loss=586.7406, val_loss=563.6834]
Training UniVI:  45%|████▌     | 181/400 [04:40<05:37,  1.54s/it, beta=1.250, gamma=4.350, train_loss=586.2413, val_loss=563.8001]
Training UniVI:  46%|████▌     | 182/400 [04:40<05:35,  1.54s/it, beta=1.250, gamma=4.350, train_loss=586.2413, val_loss=563.8001]
Training UniVI:  46%|████▌     | 182/400 [04:42<05:35,  1.54s/it, beta=1.250, gamma=4.350, train_loss=586.6578, val_loss=563.6293]
Training UniVI:  46%|████▌     | 183/400 [04:42<05:33,  1.54s/it, beta=1.250, gamma=4.350, train_loss=586.6578, val_loss=563.6293]
Training UniVI:  46%|████▌     | 183/400 [04:43<05:33,  1.54s/it, beta=1.250, gamma=4.350, train_loss=586.5840, val_loss=564.9703]
Training UniVI:  46%|████▌     | 184/400 [04:43<05:30,  1.53s/it, beta=1.250, gamma=4.350, train_loss=586.5840, val_loss=564.9703]
Training UniVI:  46%|████▌     | 184/400 [04:45<05:30,  1.53s/it, beta=1.250, gamma=4.350, train_loss=586.8725, val_loss=563.4805]
Training UniVI:  46%|████▋     | 185/400 [04:45<05:28,  1.53s/it, beta=1.250, gamma=4.350, train_loss=586.8725, val_loss=563.4805]
Training UniVI:  46%|████▋     | 185/400 [04:46<05:28,  1.53s/it, beta=1.250, gamma=4.350, train_loss=586.5367, val_loss=564.2125]
Training UniVI:  46%|████▋     | 186/400 [04:46<05:27,  1.53s/it, beta=1.250, gamma=4.350, train_loss=586.5367, val_loss=564.2125]
Training UniVI:  46%|████▋     | 186/400 [04:48<05:27,  1.53s/it, beta=1.250, gamma=4.350, train_loss=586.6665, val_loss=563.4631]
Training UniVI:  47%|████▋     | 187/400 [04:48<05:32,  1.56s/it, beta=1.250, gamma=4.350, train_loss=586.6665, val_loss=563.4631]
Training UniVI:  47%|████▋     | 187/400 [04:50<05:32,  1.56s/it, beta=1.250, gamma=4.350, train_loss=586.3489, val_loss=563.3010]
Training UniVI:  47%|████▋     | 188/400 [04:50<05:28,  1.55s/it, beta=1.250, gamma=4.350, train_loss=586.3489, val_loss=563.3010]
Training UniVI:  47%|████▋     | 188/400 [04:51<05:28,  1.55s/it, beta=1.250, gamma=4.350, train_loss=586.2512, val_loss=563.4144]
Training UniVI:  47%|████▋     | 189/400 [04:51<05:26,  1.55s/it, beta=1.250, gamma=4.350, train_loss=586.2512, val_loss=563.4144]
Training UniVI:  47%|████▋     | 189/400 [04:53<05:26,  1.55s/it, beta=1.250, gamma=4.350, train_loss=586.1596, val_loss=563.6163]
Training UniVI:  48%|████▊     | 190/400 [04:53<05:24,  1.54s/it, beta=1.250, gamma=4.350, train_loss=586.1596, val_loss=563.6163]
Training UniVI:  48%|████▊     | 190/400 [04:54<05:24,  1.54s/it, beta=1.250, gamma=4.350, train_loss=586.0810, val_loss=563.8258]
Training UniVI:  48%|████▊     | 191/400 [04:54<05:20,  1.53s/it, beta=1.250, gamma=4.350, train_loss=586.0810, val_loss=563.8258]
Training UniVI:  48%|████▊     | 191/400 [04:56<05:20,  1.53s/it, beta=1.250, gamma=4.350, train_loss=586.1165, val_loss=563.3881]
[2026-09-21 01:03:48,690] [UniVITrainer] [INFO] Early stopping at epoch 192 (best val loss=562.1112, best epoch=142)
Training UniVI:  48%|████▊     | 191/400 [04:56<05:24,  1.55s/it, beta=1.250, gamma=4.350, train_loss=586.1165, val_loss=563.3881]

[2026-09-21 01:03:48,723] [UniVITrainer] [INFO] Restored best model from epoch 142 (val loss=562.1112)

Denoise#

denoise_adata encodes cells and decodes the same modality into a new layer. With adata_by_mod, the encoding uses every modality supplied (the fused posterior), so accessibility also informs the denoised expression.

denoise_adata(model, rna_test, modality="rna", device=device, out_layer="denoised_rna_only")
denoise_adata(model, rna_test, modality="rna", device=device, out_layer="denoised_rna_atac", adata_by_mod=test)
compare_raw_vs_denoised_umap_features(rna_test, obsm_key="X_univi", features=markers[:4],
                                      denoised_layer="denoised_rna_atac")
../_images/b5ef020d900899ba86a69604585f0685fa6f2bb352de604ec99fcf651d232306.png

Denoised values are model estimates: good for visualization and for spotting marker patterns, but they are smoother than real biology and should not replace measured counts in differential-expression tests.

Cross-modal prediction, feature by feature#

rep = evaluate_cross_reconstruction(model, atac_test, rna_test, src_mod="atac", tgt_mod="rna", device=device)
print({k: round(float(v), 3) for k, v in rep["summary"].items()})
plot_featurewise_reconstruction_scatter(rep, features=markers[:4], title="ATAC to RNA: observed vs predicted")
{'mse_mean': 0.536, 'mse_median': 0.207, 'pearson_mean': 0.301, 'pearson_median': 0.278, 'per_cell_mean': 0.536}
../_images/f29abb67a70c68cb06af5466dcd30d33a8e459093d64c460540eeaed0a90ef32.png ../_images/aa80bbd37b1e0c4b39333ab333849ad3041e26f3d3f4950adea6dc756ba8ddb5.png ../_images/4eafadd8a8dd295a576bb1e564df747a662e86dabf16a080893d14125c5ae0bb.png ../_images/f4ed9415b69973357a0525ac4c713f65908307d056a041bd85ee4320c1873707.png

Generate cells#

From the prior#

Sampling latent points from the standard-normal prior and decoding them produces synthetic cells. With no target_mod, every modality is decoded from the same latent points, so the generated RNA and ATAC profiles belong together.

generated = generate_from_latent(model, n=N_GENERATED, device=device, z_source="prior")
{mod: x.shape for mod, x in generated.items()}
{'rna': (2000, 2000), 'atac': (2000, 100)}

A quick check: encode the generated RNA and look at it next to real test cells. Prior samples cover the whole region the model has learned, including the space between cell types, so they are useful for exploring the model but are not a substitute for a specific population. For that, sample per cell type (next section).

import anndata as ad

genes = pd.DataFrame(index=rna_test.var_names)
real = ad.AnnData(dense(rna_test.X), obs=rna_test.obs[["cell_type"]].copy(), var=genes)
fake = ad.AnnData(generated["rna"].astype(np.float32), var=genes)
fake.obs_names = [f"generated-{i}" for i in range(fake.n_obs)]
fake.obs["cell_type"] = "generated"
both = ad.concat({"real": real, "generated": fake}, label="source")
both.obsm["X_univi"] = encode_adata(model, both, modality="rna", device=device, latent="modality_mean")
sc.pp.neighbors(both, use_rep="X_univi")
sc.tl.umap(both, random_state=0)
sc.pl.umap(both, color=["source", "cell_type"], wspace=0.45, legend_fontsize=7)
../_images/756301724af401e24c4a3a72df30ab86ba00dbca3dd68423dc3020f3a94e0ffc.png

For a chosen cell type#

To generate a specific population, fit a Gaussian to each cell type’s latent embeddings and sample from it.

z_train = encode_adata(model, train["rna"], modality="rna", device=device, latent="modality_mean")
gauss = fit_label_latent_gaussians(z_train, train["rna"].obs["cell_type"].astype(str).to_numpy())
counts = train["rna"].obs["cell_type"].value_counts()
chosen = [c for c in counts.index if c in gauss][:4]

rows = {}
for cell_type in chosen:
    z = sample_latent_by_label(gauss, label=cell_type, n=500, random_state=0)
    fake = generate_from_latent(model, z=z, target_mod="rna", device=device)
    real = dense(rna_test[rna_test.obs["cell_type"] == cell_type].X)
    rows[cell_type] = {"generated": pd.Series(fake.mean(0), index=rna_test.var_names)[markers],
                       "real": pd.Series(real.mean(0), index=rna_test.var_names)[markers]}

fig, axes = plt.subplots(1, len(chosen), figsize=(3.2 * len(chosen), 3), sharey=True)
for ax, (cell_type, r) in zip(np.atleast_1d(axes), rows.items()):
    ax.bar(np.arange(len(markers)) - 0.2, r["real"], 0.4, label="real")
    ax.bar(np.arange(len(markers)) + 0.2, r["generated"], 0.4, label="generated")
    ax.set_xticks(range(len(markers)), markers, rotation=90)
    ax.set_title(cell_type)
np.atleast_1d(axes)[0].set_ylabel("mean log-normalized expression")
np.atleast_1d(axes)[0].legend(frameon=False, fontsize=8)
plt.tight_layout()
plt.show()
../_images/6c78cecf8645d3ed83571d7a6fad7d02b33813f34f0b0ee5f48287556946488e.png

In-silico perturbation#

predict_feature_perturbation edits one or more input features (set to zero, set to a value, add, or scale), runs the edited and original inputs through the model, and returns the change in the decoded output. Here we switch off a marker gene in the RNA input of the cells that express it most and ask which decoded genes move with it.

This measures what the model has learned to associate with the gene. It is a hypothesis generator, not evidence of causal regulation.

gene = markers[0]
by_type = pd.Series(dense(rna_test[:, gene].X).ravel(), index=rna_test.obs_names).groupby(
    rna_test.obs["cell_type"].astype(str)).mean()
target_type = by_type.idxmax()
cells = rna_test[rna_test.obs["cell_type"] == target_type].copy()

result = predict_feature_perturbation(model, cells, source_modality="rna", target_modality="rna",
                                      features=[gene], mode="off", device=device)
effect = pd.Series(result["delta"].mean(0), index=cells.var_names).drop(gene)
print(f"switched off {gene} in {cells.n_obs} {target_type} cells")
pd.concat({"largest decrease": effect.nsmallest(8), "largest increase": effect.nlargest(8)}).round(4)
switched off MS4A1 in 30 Intermediate B cells
                  genes     
largest decrease  TBC1D9       -0.0177
                  AL355076.2   -0.0174
                  ANK3         -0.0172
                  SNED1        -0.0149
                  AIM2         -0.0149
                  OSBPL10      -0.0142
                  COL4A3       -0.0126
                  CSGALNACT1   -0.0115
largest increase  IGHD          0.0232
                  TCL1A         0.0218
                  IGHM          0.0191
                  CAMK2D        0.0180
                  BACH2         0.0163
                  PCDH9         0.0151
                  COL19A1       0.0145
                  MARCH3        0.0132
dtype: float32