Move methods in cinnabar.stats concerning MLE to the MLEEstimator class - #211
Conversation
|
pre-commit.ci autofix |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #211 +/- ##
==========================================
- Coverage 97.53% 97.46% -0.07%
==========================================
Files 22 22
Lines 2470 2403 -67
==========================================
- Hits 2409 2342 -67
Misses 61 61 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
pre-commit.ci autofix |
for more information, see https://pre-commit.ci
| ) | ||
|
|
||
| @staticmethod | ||
| def mle(graph: nx.DiGraph, factor: str = "f_ij", node_factor: Union[str, None] = None) -> (np.ndarray, np.ndarray): |
There was a problem hiding this comment.
We are free to change this however we want, lets update the factor and node_factor names to be more meaningful or if you think its okay we can leave them.
There was a problem hiding this comment.
I've renamed them:
factor->edge_data_labelnode_factor->node_data_label
| # populate the edges of the graph along with their computational binding free energies | ||
| for m in filter(lambda m: m.computational, measurements): | ||
| if isinstance(m.labelA, ReferenceState): | ||
| # TODO this is never hit in the tests and should be supported behavior |
There was a problem hiding this comment.
Good point lets move this to another PR we should be able to support absolute computational values in the solver as well!
There was a problem hiding this comment.
Agreed, another PR would be a good place for this
| z[i] += -deltaij / varij | ||
| z[j] += deltaij / varij | ||
|
|
||
| F_matrix[i, i] += 1 / varij | ||
| F_matrix[j, j] += 1 / varij | ||
| F_matrix[i, j] += -1 / varij | ||
| F_matrix[j, i] += -1 / varij |
There was a problem hiding this comment.
Nice this should allow for the forward and backward results do you want to add support for that in this PR? We have some example data in #133 so we can add a test we can punt to another if you want though.
There was a problem hiding this comment.
Even if we don't test with a full network, I think this should be a halfway decent start for bi-directionality 6fb6c2b
| return f_i, Finv | ||
|
|
||
| @staticmethod | ||
| def form_edge_matrix(graph: nx.Graph, label: str, step=None, action=None, node_label=None) -> np.ndarray: |
There was a problem hiding this comment.
Lets just remove this if its not needed anymore and all tests associated with it!
jthorton
left a comment
There was a problem hiding this comment.
Looking great just a couple of things to look at.
Additionally, I removed a comment referencing bayesian_f_ij that doesn't seem to apply to any code in the repository.
The meaning of the "factor" naming convention is unclear. "node_factor", which represents the harmonic wells restraining the movement of individual nodes from a fixed absolute free energy, has been renamed to "node_data_label". "factor", referring to the harmonic restraints between pairs of nodes, has been renamed to "edge_data_label".
f030064 to
4c61f18
Compare
|
pre-commit.ci autofix |
for more information, see https://pre-commit.ci
| raise ValueError( | ||
| f"Multiple edges detected between nodes {m.labelA} and {m.labelB}. " | ||
| "MLE cannot be performed on graphs with multiple edges between the " | ||
| "same nodes. The results should be combined into a single estimate " | ||
| "and uncertainty before performing MLE. " | ||
| "See https://cinnabar.openfree.energy/en/latest/concepts/estimators.html" | ||
| "#limitations for more details." | ||
| ) |
There was a problem hiding this comment.
The plan is to fix this at the FEMap level in another PR. Issue - #232
jthorton
left a comment
There was a problem hiding this comment.
Thanks @ianmkenney this looks great we can handle the FEMap fixes in a nother PR.
IAlibay
left a comment
There was a problem hiding this comment.
This is amazing!
Everything looks good, but I am going to block over the one test - it should be an easy fix.
| # if we have bidirectional edge results we need to raise an error as they can not be used with MLE | ||
| # track the edges we have seen | ||
| edges = [] | ||
| for a, b in graph.edges: | ||
| edge_name = (a, b) if str(a) < str(b) else (b, a) | ||
| edges.append(edge_name) |
There was a problem hiding this comment.
| # if we have bidirectional edge results we need to raise an error as they can not be used with MLE | |
| # track the edges we have seen | |
| edges = [] | |
| for a, b in graph.edges: | |
| edge_name = (a, b) if str(a) < str(b) else (b, a) | |
| edges.append(edge_name) |
Is this leftover code that needs removing?
There was a problem hiding this comment.
Does this need removing?
| def test_mle_repeated_edge(): | ||
| graph = nx.DiGraph() | ||
| graph.add_edge(0, 1, f_ij=1.0, f_dij=0.5) | ||
| graph.add_edge(0, 1, f_ij=1.5, f_dij=0.1) # repeated edge | ||
| output_absolutes, _ = MLEEstimator.mle(graph, edge_data_label="f_ij", node_data_label="f_i") | ||
| output_absolutes -= output_absolutes[0] | ||
| assert output_absolutes[1] > 1.25 | ||
| assert output_absolutes[1] < 1.5 |
There was a problem hiding this comment.
I don't think this does what the test claims it do do.
If you just add an edge it willl overwrite the previous entry. See the notes here: https://networkx.org/documentation/stable/reference/classes/generated/networkx.Graph.add_edge.html
I think you need to use a MultiDiGraph here, so:
| def test_mle_repeated_edge(): | |
| graph = nx.DiGraph() | |
| graph.add_edge(0, 1, f_ij=1.0, f_dij=0.5) | |
| graph.add_edge(0, 1, f_ij=1.5, f_dij=0.1) # repeated edge | |
| output_absolutes, _ = MLEEstimator.mle(graph, edge_data_label="f_ij", node_data_label="f_i") | |
| output_absolutes -= output_absolutes[0] | |
| assert output_absolutes[1] > 1.25 | |
| assert output_absolutes[1] < 1.5 | |
| def test_mle_repeated_edge(): | |
| graph = nx.MultiDiGraph() | |
| graph.add_edge(0, 1, f_ij=1.0, f_dij=0.5) | |
| graph.add_edge(0, 1, f_ij=1.5, f_dij=0.1) # repeated edge | |
| output_absolutes, _ = MLEEstimator.mle(graph, edge_data_label="f_ij", node_data_label="f_i") | |
| output_absolutes -= output_absolutes[0] | |
| expected = (1.0 / 0.5**2 + 1.5 / 0.1**2) / (1 / 0.5**2 + 1 / 0.1**2) | |
| assert output_absolutes[1] == pytest.approx(expected) |
Co-authored-by: Irfan Alibay <IAlibay@users.noreply.github.com>
Co-authored-by: Irfan Alibay <IAlibay@users.noreply.github.com>
Co-authored-by: Irfan Alibay <IAlibay@users.noreply.github.com>
Co-authored-by: Irfan Alibay <IAlibay@users.noreply.github.com>
I don't mind either way, I'm happy for it to be removed with the idea that femap testing / fixes will be dealt with before the next release. |
Allowing parallel edges in the MLEEstimator removes the ValueError normally produced by the FEMap.generate_absolute_values method. The test expecting this ValueError has been removed, but does not explicity mean that FEMap supports parallel edges.
Perfect, I've removed it from the FEMap testing. It should be addressed after #232. |
No description provided.