Code
from _api_doc_utils import *Low-level objective-plus-score M-estimation
Group: Estimation interfaces
MEstimator is the lowest-level public estimation interface. It minimizes a user-supplied objective with gradient and uses a user-supplied per-observation score matrix for covariance estimation:
\[ \hat\theta = \arg\min_\theta Q_n(\theta), \qquad \widehat V = A^{-1} B A^{-T} / n. \]
The bread \(A\) is the numerical Jacobian of the mean score and the meat \(B\) is the empirical score outer product. The class checks optimizer convergence and validates score dimensions before reporting inference.
Constructor: cm.MEstimator
Construct with MEstimator(objective_fn, score_fn, max_iterations=100, tolerance=1e-6, derivative_step=1e-5). objective_fn(theta, data) must return (objective, gradient). score_fn(theta, data) must return an (n, p) matrix. For bootstrap support, include n in data and have the objective respect optional data['indices'].
def obj(theta, data):
X, y = (data['X'], data['y'])
idx = data.get('indices', np.arange(len(y)))
r = y[idx] - X[idx] @ theta
return (0.5 * np.sum(r * r), -(X[idx].T @ r))
def score(theta, data):
r = data['y'] - data['X'] @ theta
return -data['X'] * r[:, None]
rng = np.random.default_rng(21)
X = rng.normal(size=(180, 2))
y = X @ np.array([1.0, -0.5]) + rng.normal(scale=0.2, size=180)
model = cm.MEstimator(obj, score, max_iterations=200)
model.fit({'X': X, 'y': y, 'n': len(y)}, np.zeros(2))
print(model.summary())summary() contractThe table below is generated by fitting the live class in this repository and then inspecting summary(). Shapes are shown because most values are plain NumPy arrays or scalars.
def obj(theta, data):
X, y = (data['X'], data['y'])
idx = data.get('indices', np.arange(len(y)))
r = y[idx] - X[idx] @ theta
return (0.5 * np.sum(r * r), -(X[idx].T @ r))
def score(theta, data):
r = data['y'] - data['X'] @ theta
return -data['X'] * r[:, None]
rng = np.random.default_rng(121)
X = rng.normal(size=(100, 2))
y = X @ np.array([1, -0.5]) + rng.normal(size=100) * 0.2
model = cm.MEstimator(obj, score, max_iterations=200)
model.fit({'X': X, 'y': y, 'n': len(y)}, np.zeros(2))
summary = model.summary()
display(HTML(html_table(["summary() key", "shape"], summary_shape_rows(summary))))