def test_inv_assumptions(app_inst: ArrayApplication): # pylint: disable=no-member, unused-variable np_Z = sample_sym_pd_mat(shape=(10, 10)) # Compute the inverse of np_Z using sym_psd routine. Z = app_inst.array(np_Z, np_Z.shape) Z_inv = app_inst.inv(Z).get() Z_true_inv = np.linalg.inv(np_Z) assert np.allclose(Z_true_inv, Z_inv) # Try Cholesky approach. np_L = np.linalg.cholesky(np_Z) np_L_inv = np.linalg.inv(np_L) Z_cho_inv = np_L_inv.T @ np_L_inv assert np.allclose(Z_cho_inv, Z_true_inv) # Test backsub. assert np_L.dtype == np.float64 lp_L_inv, _ = lapack.dtrtri(np_L, lower=1, unitdiag=0, overwrite_c=0) assert np.allclose(np_L_inv, lp_L_inv) # Test overwrite. overwrite_L_inv = np_L.copy(order="F") overwrite_L_inv_res, info = lapack.dtrtri(overwrite_L_inv, lower=1, unitdiag=0, overwrite_c=1) assert np.allclose(overwrite_L_inv_res, overwrite_L_inv) assert np.allclose(np_L_inv, overwrite_L_inv) # This should copy. overwrite_L_inv = np_L.copy(order="C") overwrite_L_inv_res, info = lapack.dtrtri(overwrite_L_inv, lower=1, unitdiag=0, overwrite_c=1) assert not np.allclose(overwrite_L_inv_res, overwrite_L_inv) # scipy cholesky tests. scipy_L_inv, info = lapack.dtrtri(scipy.linalg.cholesky(np.asfortranarray(np_Z), lower=True, overwrite_a=True, check_finite=False), lower=1, unitdiag=0, overwrite_c=1) assert np.allclose(scipy_L_inv, np_L_inv) # Benchmark test. np_Z = sample_sym_pd_mat((1500, 1500)) scipy_runtime = time.time() scipy_L_inv, info = lapack.dtrtri(scipy.linalg.cholesky(np.asfortranarray(np_Z), lower=True, overwrite_a=True, check_finite=False), lower=1, unitdiag=0, overwrite_c=1) scipy_Z_inv = scipy_L_inv.T @ scipy_L_inv scipy_runtime = time.time() - scipy_runtime np_runtime = time.time() np_Z_inv = np.linalg.inv(np_Z) np_runtime = time.time() - np_runtime assert scipy_runtime < np_runtime
def test_inv(app_inst: ArrayApplication): shape = (5, 5) for dtype in (np.float32, np.float64): mat = app_inst.array(sample_sym_pd_mat(shape=shape).astype(dtype), block_shape=shape) _, r = np.linalg.qr(mat.get()) r_inv = app_inst.inv(app_inst.array(r, block_shape=shape)).get() assert np.allclose(np.linalg.inv(r), r_inv, rtol=1e-4, atol=1e-4) L = app_inst.cholesky(mat).get() assert np.allclose(np.linalg.cholesky(mat.get()), L, rtol=1e-4, atol=1e-4)
def newton(app: ArrayApplication, model: GLM, beta, X: BlockArray, y: BlockArray, tol: BlockArray, max_iter: int): for _ in range(max_iter): mu: BlockArray = model.forward(X, beta) g = model.gradient(X, y, mu, beta=beta) # These are PSD, but inv is faster than psd inv. beta += -app.inv(model.hessian(X, y, mu)) @ g if g.T @ g < tol: break return beta
def irls(app: ArrayApplication, model: LogisticRegression, beta, X: BlockArray, y: BlockArray, tol: BlockArray, max_iter: int): for _ in range(max_iter): eta: BlockArray = X @ beta mu: BlockArray = model.link_inv(eta) s = mu * (1 - mu) + 1e-16 XT_s = (X.T * s) # These are PSD, but inv is faster than psd inv. XTsX_inv = app.inv(XT_s @ X) z = eta + (y - mu) / s beta = XTsX_inv @ XT_s @ z gnorm = model.grad_norm_sq(X, y, beta) if gnorm < tol: break return beta
def update_theta(app: ArrayApplication, g, hess, local_theta): return local_theta - app.inv(hess) @ g