rohitg00/ai-engineering-from-scratch · error · ValueError

horizon undefined: slope w=

Error message

horizon undefined: slope w={w} is ~0 (b={b}, p={p}, logit={logit})

What it means

Domain guard in horizon_at: the time-to-success logistic has a fitted slope w of approximately zero, so success probability is independent of task length and the t where P(success)=p has no finite solution. The function raises loudly instead of returning inf or nan so callers never consume a meaningless horizon.

Solutions

  1. Refit the logistic on a wider range of task lengths so the slope is identifiable
  2. Check the training data for a degenerate label distribution (all success or all fail)
  3. Catch the error in report generation and report the horizon as undefined with the fitted parameters
  4. Increase iterations or learning rate if gradient descent converged before the slope moved
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at phases/15-autonomous-systems/21-metr-external-evaluation/code/main.py:76 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of rohitg00/ai-engineering-from-scratch@39ea8a1c6d (2026-08-26). Data as JSON: /api/errors/290553a0298f442d. Report an issue: GitHub.

Appendix: source

Thrown at phases/15-autonomous-systems/21-metr-external-evaluation/code/main.py:76

            p = sigmoid(w * math.log(t) + b)
            err = p - y
            dw += err * math.log(t)
            db += err
        w -= lr * dw / n
        b -= lr * db / n
    return w, b


def horizon_at(w: float, b: float, p: float) -> float:
    """Expert time where P(success) = p.  sigmoid(w*log(t)+b) = p ->
    log(t) = (logit(p) - b) / w."""
    logit = math.log(p / (1 - p))
    # A zero (or near-zero) slope means success probability does not
    # depend on task length, so the horizon is undefined. Raise rather
    # than silently returning inf/nan so callers see a loud failure.
    eps = 1e-12
    if abs(w) < eps:
        raise ValueError(
            f"horizon undefined: slope w={w} is ~0 "
            f"(b={b}, p={p}, logit={logit})"
        )
    return math.exp((logit - b) / w)


# ---------- Eval-context gaming simulator ----------

def inject_gaming(tasks: list[tuple[float, bool]],
                  gaming_rate: float) -> list[tuple[float, bool]]:
    """Flip `gaming_rate` fraction of failures to successes (model behaves
    better in eval context). Returns a new list."""
    gamed = []
    for t, s in tasks:
        if not s and random.random() < gaming_rate:
            gamed.append((t, True))
        else:
            gamed.append((t, s))

View on GitHub (pinned to 39ea8a1c6d)