Skip to content

Commit

Permalink
tests and fixes for all masked
Browse files Browse the repository at this point in the history
  • Loading branch information
JesseLivezey committed Apr 28, 2021
1 parent fb18af3 commit f719da9
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 76 deletions.
118 changes: 61 additions & 57 deletions pyuoi/linear_model/logistic.py
Original file line number Diff line number Diff line change
Expand Up @@ -666,65 +666,71 @@ def func(x, g, *args):
coefs = list()
n_iter = np.zeros(len(Cs), dtype=np.int32)
for i, C in enumerate(Cs):
iprint = [-1, 50, 1, 100, 101][
np.searchsorted(np.array([0, 1, 2, 3]), verbose)]
if penalty == 'l2':
if coef_mask is None:
w0, loss, info = optimize.fmin_l_bfgs_b(
func, w0, fprime=None,
args=(X, target, 1. / C, coef_mask, sample_weight),
iprint=iprint, pgtol=tol, maxiter=max_iter)
if coef_mask is None or coef_mask.sum():
iprint = [-1, 50, 1, 100, 101][
np.searchsorted(np.array([0, 1, 2, 3]), verbose)]
if penalty == 'l2':
if coef_mask is None:
w0, loss, info = optimize.fmin_l_bfgs_b(
func, w0, fprime=None,
args=(X, target, 1. / C, coef_mask, sample_weight),
iprint=iprint, pgtol=tol, maxiter=max_iter)
else:
if fit_intercept:
if multi_class == 'multinomial':
mask = [coef_mask,
np.ones(n_classes)[:, np.newaxis]]
mask = np.concatenate(mask, axis=1)
else:
mask = np.concatenate([coef_mask, np.ones(1)])
else:
mask = coef_mask
mask = np.nonzero(mask.ravel())[0]
wp = w0[mask]
wp, loss, info = optimize.fmin_l_bfgs_b(
func, wp, fprime=None,
args=(X, target, 1. / C, mask, sample_weight),
iprint=iprint, pgtol=tol, maxiter=max_iter)
w0 = np.zeros_like(w0)
w0[mask] = wp

else:
if fit_intercept:
zeros_seen = [0]

def zero_coef(x, *args):
if multi_class == 'multinomial':
mask = np.concatenate([coef_mask,
np.ones(n_classes)[:, np.newaxis]], axis=1)
x = x.reshape(-1, classes.size)[:-1]
else:
mask = np.concatenate([coef_mask, np.ones(1)])
else:
mask = coef_mask
mask = np.nonzero(mask.ravel())[0]
wp = w0[mask]
wp, loss, info = optimize.fmin_l_bfgs_b(
func, wp, fprime=None,
args=(X, target, 1. / C, mask, sample_weight),
iprint=iprint, pgtol=tol, maxiter=max_iter)
w0 = np.zeros_like(w0)
w0[mask] = wp
else:
zeros_seen = [0]
x = x[:-1]
now_zeros = np.array_equiv(x, 0.)
if now_zeros:
zeros_seen[0] += 1
else:
zeros_seen[0] = 0
if zeros_seen[0] > 1:
return -2048
try:
args = (X, target, 0., coef_mask, sample_weight)
w0 = fmin_lbfgs(func, w0, orthantwise_c=1. / C,
args=args,
max_iterations=max_iter,
epsilon=tol,
orthantwise_end=coef_size,
progress=zero_coef)
except AllZeroLBFGSError:
w0 *= 0.
info = None
if info is not None and info["warnflag"] == 1:
warnings.warn("lbfgs failed to converge. Increase the number "
"of iterations.", ConvergenceWarning)
# In scipy <= 1.0.0, nit may exceed maxiter.
# See https://github.com/scipy/scipy/issues/7854.
if info is None:
n_iter_i = -1
else:
n_iter_i = min(info['nit'], max_iter)

def zero_coef(x, *args):
if multi_class == 'multinomial':
x = x.reshape(-1, classes.size)[:-1]
else:
x = x[:-1]
now_zeros = np.array_equiv(x, 0.)
if now_zeros:
zeros_seen[0] += 1
else:
zeros_seen[0] = 0
if zeros_seen[0] > 1:
return -2048
try:
w0 = fmin_lbfgs(func, w0, orthantwise_c=1. / C,
args=(X, target, 0., coef_mask, sample_weight),
max_iterations=max_iter,
epsilon=tol,
orthantwise_end=coef_size,
progress=zero_coef)
except AllZeroLBFGSError:
w0 *= 0.
info = None
if info is not None and info["warnflag"] == 1:
warnings.warn("lbfgs failed to converge. Increase the number "
"of iterations.", ConvergenceWarning)
# In scipy <= 1.0.0, nit may exceed maxiter.
# See https://github.com/scipy/scipy/issues/7854.
if info is None:
n_iter_i = -1
else:
n_iter_i = min(info['nit'], max_iter)
n_iter[i] = n_iter_i

if multi_class == 'multinomial':
n_classes = max(2, classes.size)
Expand All @@ -734,8 +740,6 @@ def zero_coef(x, *args):
w0 = np.reshape(w0, (-1, n_classes)).T
coefs.append(w0.copy())

n_iter[i] = n_iter_i

return np.array(coefs), np.array(Cs), n_iter


Expand Down
68 changes: 49 additions & 19 deletions tests/test_uoi_l1logistic.py
Original file line number Diff line number Diff line change
Expand Up @@ -474,40 +474,70 @@ def test_masked_logistic_standardize():
lr.fit(X, y, coef_mask=mask)


def test_masking_with_indexing_binary():
@pytest.mark.parametrize("n_classes,penalty,fit_intercept", [(3, "l2", True),
(3, "l2", False),
(3, "l1", True),
(3, "l1", False),
(2, "l2", True),
(2, "l2", False),
(2, "l1", True),
(2, "l1", False)])
def test_masking_with_indexing(n_classes, penalty, fit_intercept):
"""Check that indexing the masks gives the same results as masking with
binary logistic regression.
logistic regression.
"""
X, y, w, intercept = make_classification(n_samples=1000,
n_classes=2,
n_classes=n_classes,
n_features=20,
n_informative=10,
random_state=0)
mask = (w != 0.).ravel()
coefs, _, _ = _logistic_regression_path(X, y, [10.], coef_mask=mask)
coefs_old, _, _ = _logistic_regression_path_old(X, y, [10.], coef_mask=mask)
mask = w != 0.
if n_classes == 2:
mask = mask.ravel()
coefs, _, _ = _logistic_regression_path(X, y, [10.], coef_mask=mask,
penalty=penalty,
fit_intercept=fit_intercept)
coefs_old, _, _ = _logistic_regression_path_old(X, y, [10.], coef_mask=mask,
penalty=penalty,
fit_intercept=fit_intercept)
assert_allclose(coefs, coefs_old)
coefs, _, _ = _logistic_regression_path(X, y, [10.])
coefs_old, _, _ = _logistic_regression_path_old(X, y, [10.])
coefs, _, _ = _logistic_regression_path(X, y, [10.],
penalty=penalty,
fit_intercept=fit_intercept)
coefs_old, _, _ = _logistic_regression_path_old(X, y, [10.],
penalty=penalty,
fit_intercept=fit_intercept)
assert_allclose(coefs, coefs_old)


def test_masking_with_indexing_multiclass():
"""Check that indexing the masks gives the same results as masking with
multiclass logistic regression.
@pytest.mark.parametrize("n_classes,penalty,fit_intercept", [(3, "l2", True),
(3, "l2", False),
(3, "l1", True),
(3, "l1", False),
(2, "l2", True),
(2, "l2", False),
(2, "l1", True),
(2, "l1", False)])
def test_all_masked_with_indexing(n_classes, penalty, fit_intercept):
"""Check masking all of the coef either works with intercept or raises an error.
"""
X, y, w, intercept = make_classification(n_samples=1000,
n_classes=3,
n_classes=n_classes,
n_features=20,
n_informative=10,
random_state=0)
mask = w != 0.
coefs, _, _ = _logistic_regression_path(X, y, [10.], coef_mask=mask)
coefs_old, _, _ = _logistic_regression_path_old(X, y, [10.], coef_mask=mask)
assert_allclose(coefs, coefs_old)
coefs, _, _ = _logistic_regression_path(X, y, [10.])
coefs_old, _, _ = _logistic_regression_path_old(X, y, [10.])
assert_allclose(coefs, coefs_old)
mask = np.zeros_like(w)
if n_classes == 2:
mask = mask.ravel()
coefs, _, _ = _logistic_regression_path(X, y, [10.], coef_mask=mask,
fit_intercept=fit_intercept)
if fit_intercept:
if n_classes == 2:
assert_equal(coefs[0][:-1], 0.)
else:
assert_equal(coefs[0][:, :-1], 0.)
else:
assert_equal(coefs[0], 0.)


def test_estimation_score_usage():
Expand Down

0 comments on commit f719da9

Please sign in to comment.