Dictionary of Applied Machine Learning · effective dimension

effective dimension — Python demo

Numerical companion to the entry effective dimension: it recomputes what the entry states and prints one line per check

The entry's point: the effective dimension of a hypothesis space is a property of the pair (hypothesis space, probability distribution of the data), not of the hypothesis space alone. Two hypothesis spaces that differ only where the data never lie have the same effective dimension, and one hypothesis space has different effective dimensions under two distributions. The demo uses the 366 days of 2024 at Krems an der Donau (GeoSphere Austria archive), feature = minimum temperature of the day, label = maximum temperature of the day, and a linear model with the feature map phi(x) = (1, x, max(0, x - 25)): the third feature, a hinge at 25 degC, is zero for every day of the record, since the minimum temperature never reaches 25 degC. Self-contained (numpy/matplotlib only), no randomness beyond the fixed-seed choice of plotted days.

Run it without installing anything:
uv run https://dictionaryofml.org/terms/effdim.py
uv downloads this script and the pinned NumPy and Matplotlib it needs, then runs it; the script fetches any input file it uses. To keep the output files, download effdim.py into a folder and run uv run effdim.py there. With NumPy and Matplotlib already installed, python3 effdim.py, from any directory — it writes its output files into the current directory. Fixed seeds, so the printed numbers reproduce exactly. Download effdim.py · Notebook · Open in Colab

The script, block by block

One cell per block of the script: the code, and what that code printed when it last ran here

setup

"""
effdim.py — numerical companion to the glossary entry 'effdim'
(effective dimension).

The entry's point: the effective dimension of a hypothesis space is a
property of the pair (hypothesis space, probability distribution of the
data), not of the hypothesis space alone. Two hypothesis spaces that
differ only where the data never lie have the same effective dimension,
and one hypothesis space has different effective dimensions under two
distributions. The demo uses the 366 days of 2024 at Krems an der Donau
(GeoSphere Austria archive), feature = minimum temperature of the day,
label = maximum temperature of the day, and a linear model with the
feature map phi(x) = (1, x, max(0, x - 25)): the third feature, a hinge
at 25 degC, is zero for every day of the record, since the minimum
temperature never reaches 25 degC. Self-contained (numpy/matplotlib
only), no randomness beyond the fixed-seed choice of plotted days.

Blocks
------
[B-data]  The 366 days; the minimum temperature ranges over
          [-10.1, 20.8] degC, so the hinge feature max(0, x - 25) is
          identically zero on the record.
[B-rank]  The feature matrix of phi over the record has rank 2, not 3:
          the effective dimension of the hinge model relative to this
          data distribution is 2, the same as that of the affine model
          (1, x). The sample second-moment matrix of phi has the same
          rank.
[B-erm]   Least squares on both models delivers the same predictions on
          every day of the record and the same training error; the
          hinge coefficient is not identifiable (the minimum-norm
          solution sets it to 0, any other value gives the same
          training error). Outside the record's range, i.e., for x > 25,
          the two learned hypotheses differ.
[B-shift] Under another data distribution the ranks differ: with the
          maximum temperature of the day as the feature (range
          [-3.6, 34.3] degC), the hinge is active on the hot days, the
          feature matrix has rank 3, and least squares on the hinge
          model reaches a smaller training error than the affine model
          when predicting the next day's maximum.

Outputs
-------
effdim_points_plot.csv : 20 of the 366 days (every 19th in date order),
                         tmin, tmax.
effdim_lines.csv       : the two learned hypotheses of [B-erm] on a grid
                         over [-15, 40] degC, columns x, affine, hinge.
effdim_shift_plot.csv  : 20 of the 365 day pairs of [B-shift] (every
                         19th), tmax_today, tmax_next.
effdim_shift_lines.csv : the two learned hypotheses of [B-shift] on the
                         same grid, columns x, affine, hinge.
effdim.png             : preview figure (checking only).

Data generated by pythondemos/effdim.py.
"""

import json
import urllib.request
import numpy as np
import matplotlib

matplotlib.use("Agg")
import matplotlib.pyplot as plt
from pathlib import Path

OUT_DIR = Path(__file__).parent
ARCHIVE = "https://dataset.api.hub.geosphere.at/v1/station/historical/"
STATION = 3805                      # Krems an der Donau
KNOT = 25.0                         # the hinge sits at 25 degC
EVERY = 19                          # every 19th day is plotted: 20 of 366
GRID = np.linspace(-15.0, 40.0, 221)
report = []


def check(name, ok):
    report.append((name, bool(ok)))
    print(f"  [{'ok' if ok else 'FAIL'}] {name}")


def fetch(parameters, start, end):
    """Daily parameters of one station from the GeoSphere Austria archive."""
    url = (f"{ARCHIVE}klima-v2-1d?parameters={','.join(parameters)}"
           f"&station_ids={STATION}&start={start}&end={end}")
    with urllib.request.urlopen(url, timeout=180) as resp:
        payload = json.load(resp)
    values = payload["features"][0]["properties"]["parameters"]
    return np.stack([np.array(values[p]["data"], dtype=float)
                     for p in parameters], axis=1)


def phi_affine(x):
    return np.stack([np.ones_like(x), x], axis=1)


def phi_hinge(x):
    return np.stack([np.ones_like(x), x, np.maximum(0.0, x - KNOT)], axis=1)


def least_squares(X, y):
    """Minimum-norm least-squares weights and the average squared error."""
    w = np.linalg.lstsq(X, y, rcond=None)[0]
    return w, float(np.mean((X @ w - y) ** 2))


def write_rows(name, header, rows):
    with open(OUT_DIR / name, "w") as f:
        f.write(header + "\n")
        for r in rows:
            f.write(",".join(f"{v:.3f}" for v in r) + "\n")

B-data

The 366 days; the minimum temperature ranges over [-10.1, 20.8] degC, so the hinge feature max(0, x - 25) is identically zero on the record.

days = fetch(["tlmin", "tlmax"], "2024-01-01", "2024-12-31")
tmin, tmax = days[:, 0], days[:, 1]
m = tmin.size
print(f"[B-data] {m} days at Krems an der Donau, 2024; minimum temperature "
      f"in [{tmin.min():.1f}, {tmin.max():.1f}] degC, maximum in "
      f"[{tmax.min():.1f}, {tmax.max():.1f}] degC")
check("[B-data] one full (leap) year, no gaps", m == 366 and not np.isnan(days).any())
check("[B-data] the minimum temperature never reaches the hinge at 25 degC",
      tmin.max() < KNOT)
check("[B-data] so the hinge feature is identically zero on the record",
      np.all(phi_hinge(tmin)[:, 2] == 0.0))
plot_idx = np.arange(0, m, EVERY)[:20]
write_rows("effdim_points_plot.csv", "tmin,tmax",
           [(tmin[i], tmax[i]) for i in plot_idx])
check("[B-data] 20 of the 366 days are written for the plot", plot_idx.size == 20)
[B-data] 366 days at Krems an der Donau, 2024; minimum temperature in [-10.1, 20.8] degC, maximum in [-3.6, 34.3] degC
  [ok] [B-data] one full (leap) year, no gaps
  [ok] [B-data] the minimum temperature never reaches the hinge at 25 degC
  [ok] [B-data] so the hinge feature is identically zero on the record
  [ok] [B-data] 20 of the 366 days are written for the plot

B-rank

The feature matrix of phi over the record has rank 2, not 3: the effective dimension of the hinge model relative to this data distribution is 2, the same as that of the affine model (1, x). The sample second-moment matrix of phi has the same rank.

X_aff, X_hin = phi_affine(tmin), phi_hinge(tmin)
r_aff, r_hin = np.linalg.matrix_rank(X_aff), np.linalg.matrix_rank(X_hin)
M_hin = X_hin.T @ X_hin / m
print(f"[B-rank] rank of the feature matrix: affine model {r_aff}, hinge "
      f"model {r_hin} (three columns); rank of the sample second-moment "
      f"matrix of the hinge map {np.linalg.matrix_rank(M_hin)}")
check("[B-rank] the affine model has effective dimension 2", r_aff == 2)
check("[B-rank] the hinge model has effective dimension 2 on this "
      "distribution too, not 3", r_hin == 2)
check("[B-rank] the sample second-moment matrix of the hinge map has rank 2",
      np.linalg.matrix_rank(M_hin) == 2)
[B-rank] rank of the feature matrix: affine model 2, hinge model 2 (three columns); rank of the sample second-moment matrix of the hinge map 2
  [ok] [B-rank] the affine model has effective dimension 2
  [ok] [B-rank] the hinge model has effective dimension 2 on this distribution too, not 3
  [ok] [B-rank] the sample second-moment matrix of the hinge map has rank 2

B-erm

Least squares on both models delivers the same predictions on every day of the record and the same training error; the hinge coefficient is not identifiable (the minimum-norm solution sets it to 0, any other value gives the same training error). Outside the record's range, i.e., for x > 25, the two learned hypotheses differ.

w_aff, err_aff = least_squares(X_aff, tmax)
w_hin, err_hin = least_squares(X_hin, tmax)
pred_aff, pred_hin = X_aff @ w_aff, X_hin @ w_hin
print(f"[B-erm] affine: tmax = {w_aff[0]:.2f} + {w_aff[1]:.3f} tmin, training "
      f"error {err_aff:.2f}; hinge model: same two coefficients "
      f"({w_hin[0]:.2f}, {w_hin[1]:.3f}) and hinge coefficient {w_hin[2]:.3f}, "
      f"training error {err_hin:.2f}")
check("[B-erm] the two learned hypotheses agree on every day of the record",
      np.allclose(pred_aff, pred_hin))
check("[B-erm] and have the same training error", abs(err_aff - err_hin) < 1e-9)
w_other = w_hin.copy(); w_other[2] = 5.0
check("[B-erm] the hinge coefficient is not identifiable: any value gives "
      "the same training error",
      abs(np.mean((X_hin @ w_other - tmax) ** 2) - err_hin) < 1e-9)
line_hin = phi_hinge(GRID) @ w_other       # the hinge drawn with slope 5 beyond 25 degC
line_aff = phi_affine(GRID) @ w_aff
check("[B-erm] outside the record's range the two hypotheses differ",
      np.max(np.abs(line_hin[GRID > KNOT] - line_aff[GRID > KNOT])) > 10)
check("[B-erm] and on the record's range they coincide",
      np.allclose(line_hin[GRID <= KNOT], line_aff[GRID <= KNOT]))
write_rows("effdim_lines.csv", "x,affine,hinge",
           zip(GRID, line_aff, line_hin))
[B-erm] affine: tmax = 10.02 + 1.099 tmin, training error 19.17; hinge model: same two coefficients (10.02, 1.099) and hinge coefficient 0.000, training error 19.17
  [ok] [B-erm] the two learned hypotheses agree on every day of the record
  [ok] [B-erm] and have the same training error
  [ok] [B-erm] the hinge coefficient is not identifiable: any value gives the same training error
  [ok] [B-erm] outside the record's range the two hypotheses differ
  [ok] [B-erm] and on the record's range they coincide

B-shift

Under another data distribution the ranks differ: with the maximum temperature of the day as the feature (range [-3.6, 34.3] degC), the hinge is active on the hot days, the feature matrix has rank 3, and least squares on the hinge model reaches a smaller training error than the affine model when predicting the next day's maximum.

x2, y2 = tmax[:-1], tmax[1:]          # today's maximum predicts tomorrow's
X2_aff, X2_hin = phi_affine(x2), phi_hinge(x2)
r2_aff, r2_hin = np.linalg.matrix_rank(X2_aff), np.linalg.matrix_rank(X2_hin)
w2_aff, err2_aff = least_squares(X2_aff, y2)
w2_hin, err2_hin = least_squares(X2_hin, y2)
hot = int(np.sum(x2 > KNOT))
print(f"[B-shift] feature = maximum temperature: {hot} of {x2.size} days "
      f"exceed 25 degC; ranks affine {r2_aff}, hinge {r2_hin}; training "
      f"errors affine {err2_aff:.2f}, hinge {err2_hin:.2f}")
check("[B-shift] the hinge is active on some days", hot > 0)
check("[B-shift] the hinge model now has effective dimension 3", r2_hin == 3)
check("[B-shift] and least squares on it reaches a smaller training error "
      "than the affine model", err2_hin < err2_aff - 1e-6)
plot2 = np.arange(0, x2.size, EVERY)[:20]
write_rows("effdim_shift_plot.csv", "tmax_today,tmax_next",
           [(x2[i], y2[i]) for i in plot2])
write_rows("effdim_shift_lines.csv", "x,affine,hinge",
           zip(GRID, phi_affine(GRID) @ w2_aff, phi_hinge(GRID) @ w2_hin))

# ------------------------------------------------------------- preview
fig, ax = plt.subplots(1, 2, figsize=(9.5, 3.6))
ax[0].plot(tmin[plot_idx], tmax[plot_idx], "o", mfc="none", color="black",
           label="20 of the 366 days")
ax[0].plot(GRID, line_aff, "k-", label="affine model")
ax[0].plot(GRID, line_hin, "k--", label="affine + hinge at 25 degC")
ax[0].axvline(KNOT, color="0.6", linestyle=":", linewidth=1)
ax[0].set_xlabel("minimum temperature of the day (degC)")
ax[0].set_ylabel("maximum temperature of the day (degC)")
ax[0].set_title("[B-erm] same predictions where the data lie", fontsize=10)
ax[0].legend(frameon=False, fontsize=8)
ax[1].plot(x2[plot2], y2[plot2], "o", mfc="none", color="black",
           label="20 of the 365 day pairs")
ax[1].plot(GRID, phi_affine(GRID) @ w2_aff, "k-", label="affine model")
ax[1].plot(GRID, phi_hinge(GRID) @ w2_hin, "k--", label="affine + hinge at 25 degC")
ax[1].axvline(KNOT, color="0.6", linestyle=":", linewidth=1)
ax[1].set_xlabel("maximum temperature of the day (degC)")
ax[1].set_ylabel("maximum temperature of the next day (degC)")
ax[1].set_title("[B-shift] another feature: the hinge is active", fontsize=10)
ax[1].legend(frameon=False, fontsize=8)
fig.tight_layout()
fig.savefig(OUT_DIR / "effdim.png", dpi=110)
print(f"\n{sum(ok for _, ok in report)}/{len(report)} checks passed")
assert all(ok for _, ok in report)
[B-shift] feature = maximum temperature: 97 of 365 days exceed 25 degC; ranks affine 2, hinge 3; training errors affine 9.83, hinge 9.81
  [ok] [B-shift] the hinge is active on some days
  [ok] [B-shift] the hinge model now has effective dimension 3
  [ok] [B-shift] and least squares on it reaches a smaller training error than the affine model

15/15 checks passed
Preview figure produced by effdim.py
The preview figure the block B-shift writes when the script runs