Skip to content

Commit

Permalink
Make optimizer and gamma_0 an argument.
Browse files Browse the repository at this point in the history
  • Loading branch information
mlondschien committed Jul 9, 2024
1 parent ee69bda commit 977ac3b
Showing 1 changed file with 49 additions and 18 deletions.
67 changes: 49 additions & 18 deletions ivmodels/tests/lagrange_multiplier.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,19 @@ class _LM:
Projection of ``W`` onto the column space of ``Z``.
"""

def __init__(self, X, y, W, dof, Z=None, X_proj=None, y_proj=None, W_proj=None):
def __init__(
self,
X,
y,
W,
dof,
Z=None,
X_proj=None,
y_proj=None,
W_proj=None,
optimizer="bfgs",
gamma_0=None,
):

self.X = X
self.y = y.reshape(-1, 1)
Expand Down Expand Up @@ -87,6 +99,9 @@ def __init__(self, X, y, W, dof, Z=None, X_proj=None, y_proj=None, W_proj=None):
# for liml
self.yS_proj_at_yS = self.yS_proj.T @ self.yS_proj

self.optimizer = optimizer
self.gamma_0 = ["liml"] if gamma_0 is None else gamma_0

def liml(self, beta=None):
"""
Efficiently compute the LIML.
Expand Down Expand Up @@ -216,32 +231,48 @@ def lm(self, beta):
if self.mw == 0:
return self.derivative(beta, jac=False, hess=False)[0]

gamma_0 = self.liml(beta=beta)
methods_with_hessian = [
"newton-cg",
"dogleg",
"trust-ncg",
"trust-krylov",
"trust-exact",
]
hess = self.optimizer.lower() in methods_with_hessian

def _derivative(gamma):
result = self.derivative(beta, gamma, jac=True, hess=False)
return (result[0], result[1], result[2])
result = self.derivative(beta, gamma, jac=True, hess=hess)
return result

objective = MemoizeJacHess(_derivative)
jac = objective.derivative
hess = objective.hessian

res1 = scipy.optimize.minimize(
objective, jac=jac, hess=hess, x0=gamma_0, method="bfgs"
hess = (
objective.hessian
if self.optimizer.lower() in methods_with_hessian
else None
)

res2 = scipy.optimize.minimize(
objective,
jac=jac,
hess=hess,
method="bfgs",
x0=np.zeros_like(gamma_0),
)
results = []
for g in self.gamma_0:
if g == "liml":
gamma_0 = self.liml(beta=beta)
elif g == "zero":
gamma_0 = np.zeros(self.mw)
else:
raise ValueError(f"unknown gamma_0: {g}")

return np.min([res1.fun, res2.fun])
results.append(
scipy.optimize.minimize(
objective, jac=jac, hess=hess, x0=gamma_0, method=self.optimizer
)
)

return np.min([r.fun for r in results])

def lagrange_multiplier_test(Z, X, y, beta, W=None, C=None, fit_intercept=True):

def lagrange_multiplier_test(
Z, X, y, beta, W=None, C=None, fit_intercept=True, **kwargs
):
"""
Perform the Lagrange multiplier test for ``beta`` by :cite:t:`kleibergen2002pivotal`.
Expand Down Expand Up @@ -309,7 +340,7 @@ def lagrange_multiplier_test(Z, X, y, beta, W=None, C=None, fit_intercept=True):
X, y, Z, W = oproj(C, X, y, Z, W)

if W.shape[1] > 0:
statistic = _LM(X=X, y=y, W=W, Z=Z, dof=n - k - C.shape[1]).lm(beta)
statistic = _LM(X=X, y=y, W=W, Z=Z, dof=n - k - C.shape[1], **kwargs).lm(beta)

p_value = 1 - scipy.stats.chi2.cdf(statistic, df=mx)

Expand Down

0 comments on commit 977ac3b

Please sign in to comment.