Problem
The Tobit loss uses a single fixed sigma parameter for all records regardless of fidelity. This is a mis-specification:
- DRC records have typical pEC50 measurement noise of σ ≈ 0.15 (median std.error in well-characterized screens)
- PS records encode threshold uncertainty, where σ ≈ 0.5–1.0 is more appropriate
A single σ = 0.5 simultaneously underestimates DRC precision and overestimates PS precision.
Proposed Solution
Replace the fixed sigma scalar with learnable per-fidelity log-sigma parameters:
# moal/model.py
self.log_sigma_drc = nn.Parameter(torch.tensor(math.log(0.2))) # init ~0.2
self.log_sigma_ps = nn.Parameter(torch.tensor(math.log(0.5))) # init ~0.5
@property
def sigma_drc(self): return self.log_sigma_drc.exp()
@property
def sigma_ps(self): return self.log_sigma_ps.exp()
In _tobit_loss(), use sigma_drc for CensoringType.EXACT records and sigma_ps for LEFT/INTERVAL records.
Alternative (simpler): Keep sigma fixed but expose sigma_drc and sigma_ps as separate constructor parameters (no gradient through sigma).
Backward compatibility: Keep sigma as a constructor parameter that initializes both; deprecate when per-fidelity sigma is set.
Files
Problem
The Tobit loss uses a single fixed
sigmaparameter for all records regardless of fidelity. This is a mis-specification:A single σ = 0.5 simultaneously underestimates DRC precision and overestimates PS precision.
Proposed Solution
Replace the fixed
sigmascalar with learnable per-fidelity log-sigma parameters:In _tobit_loss(), use sigma_drc for CensoringType.EXACT records and sigma_ps for LEFT/INTERVAL records.
Alternative (simpler): Keep sigma fixed but expose sigma_drc and sigma_ps as separate constructor parameters (no gradient through sigma).
Backward compatibility: Keep sigma as a constructor parameter that initializes both; deprecate when per-fidelity sigma is set.
Files