Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

In GD, change objective_function --> f and deprecate objective_function argument #2006

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions Wrappers/Python/cil/optimisation/algorithms/GD.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class GD(Algorithm):
----------
initial: DataContainer (e.g. ImageData)
The initial point for the optimisation
objective_function: CIL function (:meth:`~cil.optimisation.functions.Function`. ) with a defined gradient method
f: CIL function (:meth:`~cil.optimisation.functions.Function`. ) with a defined gradient method
The function to be minimised.
step_size: positive real float or subclass of :meth:`~cil.optimisation.utilities.StepSizeRule`, default = None
If you pass a float this will be used as a constant step size. If left as None and do not pass a step_size_rule then the Armijio rule will be used to perform backtracking to choose a step size at each iteration. If a child class of :meth:`cil.optimisation.utilities.StepSizeRule`' is passed then it's method `get_step_size` is called for each update.
Expand All @@ -47,12 +47,19 @@ class GD(Algorithm):

"""

def __init__(self, initial=None, objective_function=None, step_size=None, rtol=1e-5, atol=1e-8, preconditioner=None, **kwargs):
def __init__(self, initial=None, f=None, step_size=None, rtol=1e-5, atol=1e-8, preconditioner=None, **kwargs):
'''GD algorithm creator
'''

self.alpha = kwargs.pop('alpha', None)
self.beta = kwargs.pop('beta', None)

if kwargs.get('objective_function') is not None:
warn('The argument `objective_function` will be deprecated in the future. Please use `f` instead.', DeprecationWarning, stacklevel=2)
if f is not None:
raise ValueError('The argument `objective_function` is being deprecated, replaced by `f`. Please use just `f` not both')
f = kwargs.pop('objective_function')


super().__init__(**kwargs)

Expand All @@ -61,18 +68,18 @@ def __init__(self, initial=None, objective_function=None, step_size=None, rtol=1

self.rtol = rtol
self.atol = atol
if initial is not None and objective_function is not None:
self.set_up(initial=initial, objective_function=objective_function,
if initial is not None and f is not None:
self.set_up(initial=initial, f=f,
step_size=step_size, preconditioner=preconditioner)

def set_up(self, initial, objective_function, step_size, preconditioner):
def set_up(self, initial, f, step_size, preconditioner):
'''initialisation of the algorithm

Parameters
----------
initial: DataContainer (e.g. ImageData)
The initial point for the optimisation
objective_function: CIL function with a defined gradient
f: CIL function with a defined gradient
The function to be minimised.
step_size: positive real float or subclass of :meth:`~cil.optimisation.utilities.StepSizeRule`, default = None
If you pass a float this will be used as a constant step size. If left as None and do not pass a step_size_rule then the Armijio rule will be used to perform backtracking to choose a step size at each iteration. If a child class of :meth:`cil.optimisation.utilities.StepSizeRule`' is passed then it's method `get_step_size` is called for each update.
Expand All @@ -84,7 +91,7 @@ def set_up(self, initial, objective_function, step_size, preconditioner):
log.info("%s setting up", self.__class__.__name__)

self.x = initial.copy()
self._objective_function = objective_function
self._objective_function = f

if step_size is None:
self.step_size_rule = ArmijoStepSizeRule(
Expand Down
32 changes: 16 additions & 16 deletions Wrappers/Python/test/test_algorithms.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,12 +118,12 @@ def test_GD(self):

step_size = norm2sq.L / 3.

alg = GD(initial=initial, objective_function=norm2sq, step_size=step_size,
alg = GD(initial=initial, f=norm2sq, step_size=step_size,
atol=1e-9, rtol=1e-6)
alg.run(1000,verbose=0)
self.assertNumpyArrayAlmostEqual(alg.x.as_array(), b.as_array())

alg = GD(initial=initial, objective_function=norm2sq, step_size=step_size,
alg = GD(initial=initial, f=norm2sq, step_size=step_size,
atol=1e-9, rtol=1e-6, update_objective_interval=2)
self.assertTrue(alg.update_objective_interval == 2)
alg.run(20, verbose=0)
Expand All @@ -144,7 +144,7 @@ def test_update_interval_0(self):
identity = IdentityOperator(ig)
norm2sq = LeastSquares(identity, b)
alg = GD(initial=initial,
objective_function=norm2sq,
f=norm2sq,
update_objective_interval=0,
atol=1e-9, rtol=1e-6)
self.assertTrue(alg.update_objective_interval == 0)
Expand All @@ -154,11 +154,11 @@ def test_update_interval_0(self):
self.assertNumpyArrayAlmostEqual(alg.x.as_array(), b.as_array())

def test_gd_step_size_init(self):
gd = GD(initial=self.initial, objective_function=self.f, step_size=0.002)
gd = GD(initial=self.initial, f=self.f, step_size=0.002)
self.assertEqual(gd.step_size_rule.step_size, 0.002)
self.assertEqual(gd.step_size, 0.002)

gd = GD(initial=self.initial, objective_function=self.f)
gd = GD(initial=self.initial, f=self.f)
self.assertEqual(gd.step_size_rule.alpha_orig, 1e6)
self.assertEqual(gd.step_size_rule.beta, 0.5)
self.assertEqual(gd.step_size_rule.max_iterations, np.ceil(
Expand All @@ -167,27 +167,27 @@ def test_gd_step_size_init(self):
gd.step_size

gd = GD(initial=self.initial,
objective_function=self.f, alpha=1e2, beta=0.25)
f=self.f, alpha=1e2, beta=0.25)
self.assertEqual(gd.step_size_rule.alpha_orig, 1e2)
self.assertEqual(gd.step_size_rule.beta, 0.25)
self.assertEqual(gd.step_size_rule.max_iterations, np.ceil(
2 * np.log10(1e2) / np.log10(2)))

with self.assertRaises(TypeError):
gd = GD(initial=self.initial, objective_function=self.f,
gd = GD(initial=self.initial, f=self.f,
step_size=0.1, step_size_rule=ConstantStepSize(0.5))

def test_gd_constant_step_size_init(self):
rule = ConstantStepSize(0.4)
self.assertEqual(rule.step_size, 0.4)
gd = GD(initial=self.initial,
objective_function=self.f, step_size=rule)
f=self.f, step_size=rule)
self.assertEqual(gd.step_size_rule.step_size, 0.4)
self.assertEqual(gd.step_size, 0.4)

def test_gd_fixed_step_size_rosen(self):

gd = GD(initial=self.initial, objective_function=self.f, step_size=0.002,
gd = GD(initial=self.initial, f=self.f, step_size=0.002,
update_objective_interval=500)
gd.run(3000, verbose=0)
np.testing.assert_allclose(
Expand All @@ -203,7 +203,7 @@ def test_armijo_step_size_init(self):
self.assertEqual(rule.max_iterations, np.ceil(2 * np.log10(1e6) / np.log10(2)))

gd = GD(initial=self.initial,
objective_function=self.f, step_size=rule)
f=self.f, step_size=rule)
self.assertEqual(gd.step_size_rule.alpha_orig, 1e6)
self.assertEqual(gd.step_size_rule.beta, 0.5)
self.assertEqual(gd.step_size_rule.max_iterations, np.ceil(
Expand All @@ -215,7 +215,7 @@ def test_armijo_step_size_init(self):
self.assertEqual(rule.max_iterations, 5)

gd = GD(initial=self.initial,
objective_function=self.f, step_size=rule)
f=self.f, step_size=rule)
self.assertEqual(gd.step_size_rule.alpha_orig, 5e5)
self.assertEqual(gd.step_size_rule.beta, 0.2)
self.assertEqual(gd.step_size_rule.max_iterations, 5)
Expand All @@ -234,17 +234,17 @@ def test_GDArmijo(self):

norm2sq = LeastSquares(identity, b)

alg = GD(initial=initial, objective_function=norm2sq)
alg = GD(initial=initial, f=norm2sq)
alg.run(100, verbose=0)
self.assertNumpyArrayAlmostEqual(alg.x.as_array(), b.as_array())
alg = GD(initial=initial, objective_function=norm2sq, update_objective_interval=2)
alg = GD(initial=initial, f=norm2sq, update_objective_interval=2)
self.assertTrue(alg.update_objective_interval==2)
alg.run(20, verbose=0)
self.assertNumpyArrayAlmostEqual(alg.x.as_array(), b.as_array())

def test_gd_armijo_rosen(self):
armj = ArmijoStepSizeRule(alpha=50, max_iterations=50, warmstart=False)
gd = GD(initial=self.initial, objective_function=self.f, step_size=armj,
gd = GD(initial=self.initial, f=self.f, step_size=armj,
update_objective_interval=500)
gd.run(3500,verbose=0)
np.testing.assert_allclose(
Expand All @@ -253,12 +253,12 @@ def test_gd_armijo_rosen(self):
gd.solution.array[1], self.scipy_opt_high.x[1], atol=1e-2)

def test_gd_run_no_iterations(self):
gd = GD(initial=self.initial, objective_function=self.f, step_size=0.002)
gd = GD(initial=self.initial, f=self.f, step_size=0.002)
with self.assertRaises(ValueError):
gd.run()

def test_gd_run_infinite(self):
gd = GD(initial=self.initial, objective_function=self.f, step_size=0.002)
gd = GD(initial=self.initial, f=self.f, step_size=0.002)
with self.assertRaises(ValueError):
gd.run(np.inf)

Expand Down
18 changes: 9 additions & 9 deletions Wrappers/Python/test/test_approximate_gradient.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ def test_toy_example(self):
stochastic_objective = self.stochastic_estimator(functions, sampler)

alg_stochastic = GD(initial=initial,
objective_function=stochastic_objective, update_objective_interval=1000,
f=stochastic_objective, update_objective_interval=1000,
step_size=0.05)
alg_stochastic.run(600, verbose=0)

Expand Down Expand Up @@ -246,7 +246,7 @@ def test_SAG_toy_example_warm_start(self):
stochastic_objective.warm_start_approximate_gradients(initial)

alg_stochastic = GD(initial=initial,
objective_function=stochastic_objective, update_objective_interval=1000,
f=stochastic_objective, update_objective_interval=1000,
step_size=0.05, max_iteration =5000)
alg_stochastic.run( 80, verbose=0)
np.testing.assert_allclose(p.value ,stochastic_objective(alg_stochastic.x) , atol=1e-1)
Expand Down Expand Up @@ -307,7 +307,7 @@ def test_SAGA_toy_example_warm_start(self):
stochastic_objective.warm_start_approximate_gradients(initial)

alg_stochastic = GD(initial=initial,
objective_function=stochastic_objective, update_objective_interval=1000,
f=stochastic_objective, update_objective_interval=1000,
step_size=0.05, max_iteration =5000)
alg_stochastic.run( 100, verbose=0)
np.testing.assert_allclose(p.value ,stochastic_objective(alg_stochastic.x) , atol=1e-1)
Expand Down Expand Up @@ -343,7 +343,7 @@ def test_SVRG_snapshot_update_interval_and_data_passes(self):
sampler = Sampler.random_with_replacement(self.n_subsets)
objective = SVRGFunction(self.f_subsets, sampler)
alg_stochastic = GD(initial=self.initial,
objective_function=objective, update_objective_interval=500,
f=objective, update_objective_interval=500,
step_size=5e-8, max_iteration=5000)
alg_stochastic.run(2, verbose=0)
self.assertNumpyArrayAlmostEqual(
Expand All @@ -366,7 +366,7 @@ def test_SVRG_snapshot_update_interval_and_data_passes(self):
objective = SVRGFunction(
self.f_subsets, self.sampler, snapshot_update_interval=3)
alg_stochastic = GD(initial=self.initial,
objective_function=objective, update_objective_interval=500,
f=objective, update_objective_interval=500,
step_size=5e-8, max_iteration=5000)
alg_stochastic.run(2, verbose=0)
self.assertNumpyArrayAlmostEqual(
Expand Down Expand Up @@ -418,7 +418,7 @@ def test_SVRG_toy_example_store_gradients(self):
stochastic_objective = SVRGFunction(functions, sampler, store_gradients=True)

alg_stochastic = GD(initial=initial,
objective_function=stochastic_objective, update_objective_interval=1000,
f=stochastic_objective, update_objective_interval=1000,
step_size=1/stochastic_objective.L)

alg_stochastic.run(10, verbose=0)
Expand Down Expand Up @@ -463,7 +463,7 @@ def test_LSVRG_init(self):
def test_LSVRG_data_passes_and_snapshot_update_probability_and_seed(self):
objective = LSVRGFunction(self.f_subsets, self.sampler, snapshot_update_probability=1)
alg_stochastic = GD(initial=self.initial, update_objective_interval=500,
objective_function=objective, step_size=5e-8, max_iteration=5000)
f=objective, step_size=5e-8, max_iteration=5000)
alg_stochastic.run(2, verbose=0)
self.assertNumpyArrayAlmostEqual(
np.array(objective.data_passes), np.array([1., 2,]))
Expand All @@ -474,7 +474,7 @@ def test_LSVRG_data_passes_and_snapshot_update_probability_and_seed(self):
self.assertNumpyArrayAlmostEqual(np.array(objective.data_passes_indices[-1]), np.array(list(range(self.n_subsets))))
objective = LSVRGFunction(self.f_subsets, self.sampler, seed=3)
alg_stochastic = GD(initial=self.initial,
objective_function=objective, update_objective_interval=500,
f=objective, update_objective_interval=500,
step_size=5e-8, max_iteration=5000)
alg_stochastic.run(10, verbose=0)
self.assertNumpyArrayAlmostEqual(np.array(objective.data_passes),
Expand Down Expand Up @@ -522,7 +522,7 @@ def test_LSVRG_toy_example_store_gradients(self):
stochastic_objective = LSVRGFunction(functions, sampler, store_gradients=True)

alg_stochastic = GD(initial=initial,
objective_function=stochastic_objective, update_objective_interval=1000,
f=stochastic_objective, update_objective_interval=1000,
step_size=1/stochastic_objective.L)


Expand Down
18 changes: 9 additions & 9 deletions Wrappers/Python/test/test_preconditioners.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def test_preconditioner_called(self):
A = IdentityOperator(ig)
test_precon = MagicMock(None)
f = LeastSquares(A=A, b=data, c=0.5)
alg = GD(initial=ig.allocate('random', seed=10), objective_function=f, preconditioner=test_precon,
alg = GD(initial=ig.allocate('random', seed=10), f=f, preconditioner=test_precon,
max_iteration=100, update_objective_interval=1, step_size=0.0000001)
alg.run(5)
self.assertEqual(len(test_precon.apply.mock_calls), 5)
Expand Down Expand Up @@ -63,7 +63,7 @@ def test_sensitivity_calculation(self):
2., 2., 2., 2., 0, 0, 0, 0, 0, 0]))

f = LeastSquares(A, data)
alg = GD(initial=ig.allocate(0), objective_function=f,
alg = GD(initial=ig.allocate(0), f=f,
max_iteration=100, update_objective_interval=1, step_size=1.)
alg.gradient_update = ig.allocate(2)
preconditioner.apply(alg, alg.gradient_update, out=alg.gradient_update)
Expand All @@ -84,17 +84,17 @@ def test_sensitivity_gd_against_sirt(self):
step_size = 1.
preconditioner = Sensitivity(A)

alg = GD(initial=ig.allocate(0), objective_function=f,
alg = GD(initial=ig.allocate(0), f=f,
max_iteration=100, update_objective_interval=1, step_size=step_size)
self.assertEqual(alg.preconditioner, None)

precond_pwls = GD(initial=ig.allocate(0), objective_function=f, preconditioner=preconditioner,
precond_pwls = GD(initial=ig.allocate(0), f=f, preconditioner=preconditioner,
max_iteration=100, update_objective_interval=1, step_size=step_size)

def correct_update_objective(alg):
# SIRT computes |Ax_{k} - b|_2^2
# GD with weighted LeastSquares computes the objective included the weight, so we remove the weight
return 0.5*(alg.objective_function.A.direct(alg.x) - alg.objective_function.b).squared_norm()
return 0.5*(alg._objective_function.A.direct(alg.x) - alg._objective_function.b).squared_norm()

precond_pwls.run(10)
np.testing.assert_allclose(
Expand Down Expand Up @@ -122,13 +122,13 @@ def test_sensitivity_ista_against_sirt(self):
max_iteration=100, update_objective_interval=1, step_size=step_size)
self.assertEqual(alg.preconditioner, None)

precond_pwls = GD(initial=ig.allocate(0), objective_function=f, preconditioner=preconditioner,
precond_pwls = GD(initial=ig.allocate(0), f=f, preconditioner=preconditioner,
max_iteration=100, update_objective_interval=1, step_size=step_size)

def correct_update_objective(alg):
# SIRT computes |Ax_{k} - b|_2^2
# GD with weighted LeastSquares computes the objective included the weight, so we remove the weight
return 0.5*(alg.objective_function.A.direct(alg.x) - alg.objective_function.b).squared_norm()
return 0.5*(alg._objective_function.A.direct(alg.x) - alg._objective_function.b).squared_norm()

precond_pwls.run(10)
np.testing.assert_allclose(
Expand Down Expand Up @@ -185,7 +185,7 @@ def test_adaptive_sensitivity_calculations(self):
2., 2., 2., 2., 0, 0, 0, 0, 0, 0]))

f = LeastSquares(A, data)
alg = GD(initial=ig.allocate(0), objective_function=f,
alg = GD(initial=ig.allocate(0), f=f,
max_iteration=100, update_objective_interval=1, step_size=1.)
alg.gradient_update = ig.allocate(1)
preconditioner.apply(alg, alg.gradient_update, out=alg.gradient_update)
Expand Down Expand Up @@ -242,7 +242,7 @@ def test_adaptive_sensitivity_gd_converges(self):
step_size = 1.
preconditioner = AdaptiveSensitivity(A, max_iterations=3000, delta=1e-8)

precond_pwls = GD(initial=initial, objective_function=f,
precond_pwls = GD(initial=initial, f=f,
preconditioner=preconditioner, update_objective_interval=1, step_size=step_size)

precond_pwls.run(3000)
Expand Down
Loading
Loading