-
Notifications
You must be signed in to change notification settings - Fork 12
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
Feature/mle #1029
Feature/mle #1029
Conversation
autofit/non_linear/initializer.py
Outdated
info += f"{key}: Start[{value}]\n" | ||
|
||
except KeyError: | ||
|
||
info += f"{key} : {prior})\n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistent spacing before the :
info_start = self.search.initializer.info_from_model(model=self.model) | ||
self._save_model_start_point(info=info_start) | ||
except (NotImplementedError, AttributeError): | ||
pass |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could be worth logging something here as these errors may cover up code mistakes
""" | ||
|
||
self.logger.debug("Visualizing") | ||
|
||
if analysis.should_visualize(paths=self.paths, during_analysis=during_analysis): | ||
if paths_override is None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
paths = paths_override or self.paths
|
||
|
||
class AbstractBFGS(AbstractMLE): | ||
__identifier_fields__ = () |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably best not to define an empty identifier_fields - I think as it stands it would mean attributes would be ignored when creating an identifier for an AbstractBFGS meaning all AbstractBFGS runs of the same type would have the same identifier
def test__priors__samples_from_model(): | ||
model = af.Model(af.m.MockClassx4) | ||
model.one = af.UniformPrior(lower_limit=0.099, upper_limit=0.101) | ||
model.two = af.UniformPrior(lower_limit=0.199, upper_limit=0.201) | ||
model.three = af.UniformPrior(lower_limit=0.299, upper_limit=0.301) | ||
model.four = af.UniformPrior(lower_limit=0.399, upper_limit=0.401) | ||
|
||
initializer = af.InitializerPrior() | ||
|
||
( | ||
unit_parameter_lists, | ||
parameter_lists, | ||
figure_of_merit_list, | ||
) = initializer.samples_from_model( | ||
total_points=2, | ||
model=model, | ||
fitness=MockFitness(), | ||
paths=af.DirectoryPaths(), | ||
) | ||
|
||
assert 0.0 < unit_parameter_lists[0][0] < 1.0 | ||
assert 0.0 < unit_parameter_lists[1][0] < 1.0 | ||
assert 0.0 < unit_parameter_lists[0][1] < 1.0 | ||
assert 0.0 < unit_parameter_lists[1][1] < 1.0 | ||
assert 0.0 < unit_parameter_lists[0][2] < 1.0 | ||
assert 0.0 < unit_parameter_lists[1][2] < 1.0 | ||
assert 0.0 < unit_parameter_lists[0][3] < 1.0 | ||
assert 0.0 < unit_parameter_lists[1][3] < 1.0 | ||
|
||
assert 0.099 < parameter_lists[0][0] < 0.101 | ||
assert 0.099 < parameter_lists[1][0] < 0.101 | ||
assert 0.199 < parameter_lists[0][1] < 0.201 | ||
assert 0.199 < parameter_lists[1][1] < 0.201 | ||
assert 0.299 < parameter_lists[0][2] < 0.301 | ||
assert 0.299 < parameter_lists[1][2] < 0.301 | ||
assert 0.399 < parameter_lists[0][3] < 0.401 | ||
assert 0.399 < parameter_lists[1][3] < 0.401 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pytest.fixture
def model_and_samples():
model = af.Model(af.m.MockClassx4)
model.one = af.UniformPrior(lower_limit=0.099, upper_limit=0.101)
model.two = af.UniformPrior(lower_limit=0.199, upper_limit=0.201)
model.three = af.UniformPrior(lower_limit=0.299, upper_limit=0.301)
model.four = af.UniformPrior(lower_limit=0.399, upper_limit=0.401)
initializer = af.InitializerPrior()
unit_parameter_lists, parameter_lists, _ = initializer.samples_from_model(
total_points=2,
model=model,
fitness=MockFitness(),
paths=af.DirectoryPaths(),
)
return unit_parameter_lists, parameter_lists
@pytest.mark.parametrize("index, param_index, lower, upper", [
(0, 0, 0.0, 1.0),
(1, 0, 0.0, 1.0),
(0, 1, 0.0, 1.0),
(1, 1, 0.0, 1.0),
(0, 2, 0.0, 1.0),
(1, 2, 0.0, 1.0),
(0, 3, 0.0, 1.0),
(1, 3, 0.0, 1.0),
])
def test_unit_parameter_lists(model_and_samples, index, param_index, lower, upper):
unit_parameter_lists, _ = model_and_samples
assert lower < unit_parameter_lists[index][param_index] < upper
@pytest.mark.parametrize("index, param_index, lower, upper", [
(0, 0, 0.099, 0.101),
(1, 0, 0.099, 0.101),
(0, 1, 0.199, 0.201),
(1, 1, 0.199, 0.201),
(0, 2, 0.299, 0.301),
(1, 2, 0.299, 0.301),
(0, 3, 0.399, 0.401),
(1, 3, 0.399, 0.401),
])
def test_parameter_lists(model_and_samples, index, param_index, lower, upper):
_, parameter_lists = model_and_samples
assert lower < parameter_lists[index][param_index] < upper
Methods which found the maximum likelihood model were previously called
optimize
, which this PR renames to MLE (maximum likelihood estimator).This PR improves the MLE methods with functionality including:
Initializer
API.The
BFGS
andLBFGS
MLE searches have been improved in this PR, including visualization.The main use case is fits where a good starting point is known and simple gradient descent can find the maximum likelihood solution.
The intent is to use this for strong lens sensitivity mapping.