Skip to content
Merged
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: 17 additions & 4 deletions autofit/graphical/expectation_propagation/factor_optimiser.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ class AbstractFactorOptimiser(ABC):
"""
logger = logger.debug

def __init__(self, initial_values=None, deltas=None, inplace=False, delta=1):
def __init__(self, initial_values=None, deltas=None, inplace=False, delta=1, dynamic_delta=False):

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently the default optimiser would need to be passed with dynamic_delta=True explicitly. I'm tempted to make the default dynamic_delta=True

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once I test this feature set properly I suspect we'll end up making it True by default.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah makes sense. I also need to look at incorporating it into the Laplace optimiser

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh wait that's what this PR does lol

self.initial_values = initial_values or {}
self.inplace = inplace
self.delta = delta
self.deltas = deltas or {}
self.dynamic_delta = dynamic_delta

def update_model_approx(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest deleting this method and merging functionality into EPOptimiser class

self,
Expand All @@ -30,14 +31,26 @@ def update_model_approx(
status: Optional[Status] = Status(),
delta: Optional[float] = None,
) -> Tuple[EPMeanField, Status]:
delta = delta or self.deltas.get(factor_approx.factor) or self.delta
new_approx, status = model_approx.project_mean_field(

variable_message_count = model_approx.variable_message_count
min_value = min(variable_message_count.values())

delta = delta or self.delta

if factor_approx.factor in self.deltas:
delta = self.deltas[factor_approx.factor]
elif self.dynamic_delta:
delta = MeanField({
variable: self.delta * (min_value / message_count)
for variable, message_count in variable_message_count.items()
})

return model_approx.project_mean_field(
new_model_dist,
factor_approx,
delta=delta,
status=status,
)
return new_approx, status

@abstractmethod
def optimise(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method should have signature,

def optimise(
    self, factorApprox: FactorApproximation
) -> Tuple[FactorApproximation, Status]:

Expand Down
25 changes: 5 additions & 20 deletions autofit/non_linear/abstract_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def __init__(
session
An SQLAlchemy session instance so the results of the model-fit are written to an SQLite database.
"""
super().__init__(delta=kwargs.get("delta", 1.0))
super().__init__(delta=kwargs.get("delta", 1.0), dynamic_delta=kwargs.get("dynamic_delta", True))

from autofit.non_linear.paths.database import DatabasePaths

Expand Down Expand Up @@ -204,15 +204,13 @@ def __init__(

self.optimisation_counter = Counter()

self.dynamic_delta = kwargs.get("dynamic_delta", True)

__identifier_fields__ = tuple()

def optimise(
self,
factor: Factor,
model_approx: EPMeanField,
status: Optional[Status] = None
status: Status = Status(),
) -> Tuple[EPMeanField, Status]:
"""
Perform optimisation for expectation propagation. Currently only
Expand Down Expand Up @@ -289,25 +287,12 @@ def optimise(
result.projected_model.priors
)

variable_message_count = model_approx.variable_message_count
min_value = min(variable_message_count.values())

if self.dynamic_delta:
delta = MeanField({
variable: self.delta * (min_value / message_count)
for variable, message_count in variable_message_count.items()
})
else:
delta = self.delta

projection, status = factor_approx.project(

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This projection step does not occur anymore. @matthewghgriffiths is this correct?

new_model_dist,
delta=delta
model_approx, status = self.update_model_approx(
new_model_dist, factor_approx, model_approx, status
)

status.result = result

return model_approx.project(projection, status)
return model_approx, status

@property
def name(self):
Expand Down
1 change: 1 addition & 0 deletions test_autofit/graphical/regression/test_static.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ def __init__(self):
self._paths = af.DirectoryPaths()
self.delta = 1.0
self.dynamic_delta = False
self.deltas = {}

def fit(
self,
Expand Down