Solving tips
- Log loss rewards confident-and-correct and punishes confident-and-wrong; the log term blows up as a probability heads toward the wrong extreme.
- Clip predictions into [eps, 1-eps] before taking any log — a raw 0.0 or 1.0 makes log(0) = -inf and the whole score becomes nan or inf.
- Write it as one vectorized expression: y*log(p) + (1-y)*log(1-p), then negate the mean.
Implement binary log loss, also called binary cross-entropy, from scratch with NumPy. It is the standard loss for binary classifiers that output probabilities (logistic regression, neural nets with a sigmoid head), and interviewers use it to check that you can both write the formula and handle the numerical edge case that breaks it.
Definition
For n samples with true labels y in {0, 1} and predicted probabilities p in [0, 1]:
log_loss = -(1/n) * sum_i [ y_i * log(p_i) + (1 - y_i) * log(1 - p_i) ]
A confident correct prediction (p near 1 when y = 1) contributes near-zero loss; a confident wrong prediction (p near 0 when y = 1) contributes a large loss because log(p) diverges to -inf.
Task
Complete log_loss(y_true, y_pred, eps=1e-15) so it returns the mean log loss as a float. Before taking any logarithm, clip y_pred into the range [eps, 1 - eps] so that a predicted probability of exactly 0.0 or 1.0 does not produce log(0). Do not call sklearn or any built-in log-loss / cross-entropy helper.
Example
y_true = np.array([1, 0, 1, 1])
y_pred = np.array([0.9, 0.1, 0.8, 0.7])
log_loss(y_true, y_pred) # -> 0.19763488164214868
The per-sample losses are [-log(0.9), -log(0.9), -log(0.8), -log(0.7)], whose mean is about 0.1976.
Constraints
1 <= n <= 10^6; use vectorized NumPy, not a Python loop.- Each
y_true[i]is0or1; eachy_pred[i]is in[0, 1]. - Values fit in float64;
0 < eps < 0.5.