import numpy as np, matplotlib.pyplot as plt
rng = np.random.default_rng(0); K, M, beta = 10, 4000, 2.6
z = rng.normal(0, 2.0, size=(M, K))
sm = lambda z: np.exp(z - z.max(1, keepdims=True)) / np.exp(z - z.max(1, keepdims=True)).sum(1, keepdims=True)
labels = np.array([rng.choice(K, p=p) for p in sm(z)]); correct = (z.argmax(1) == labels)
def reliability(conf, ax, title):
bins = np.linspace(0, 1, 11); acc, mid, e = [], [], 0
for i in range(10):
m = (conf > bins[i]) & (conf <= bins[i+1])
if m.sum(): acc.append(correct[m].mean()); mid.append(conf[m].mean()); e += abs(correct[m].mean()-conf[m].mean())*m.sum()/M
ax.plot([0,1],[0,1],"k--",lw=1); ax.bar(mid, acc, width=0.09, color="#5d2c80", alpha=0.8)
ax.set_title(f"{title}\nECE = {e:.3f}", fontsize=8); ax.set_xlabel("confidence", fontsize=7)
ax.set_xlim(0,1); ax.set_ylim(0,1); ax.set_ylabel("accuracy", fontsize=7)
fig, ax = plt.subplots(1, 2, figsize=(6.4, 2.8))
reliability(sm(z*beta).max(1), ax[0], "raw (overconfident)")
reliability(sm(z*beta/beta).max(1), ax[1], f"temperature-scaled (T={beta})")
plt.tight_layout(); plt.show()