Skip to content

Feature/dbn#174

Draft
liam-adams wants to merge 14 commits into
mckinsey:developfrom
liam-adams:feature/dbn
Draft

Feature/dbn#174
liam-adams wants to merge 14 commits into
mckinsey:developfrom
liam-adams:feature/dbn

Conversation

@liam-adams

Copy link
Copy Markdown
Contributor

Motivation and Context

Why was this PR created?
This PR is created to add a DynamicStructureNode, DynamicStructureModel and DynamicBayesianNetwork for prediction and inference with DYNOTEARS

How has this been tested?

What testing strategies have you used?
Test driven development

Checklist

  • Read the contributing guidelines
  • Opened this PR as a 'Draft Pull Request' if it is work-in-progress
  • Updated the documentation to reflect the code changes
  • Added a description of this change and added my name to the list of supporting contributions in the RELEASE.md file
  • Added tests to cover my changes
  • Assigned myself to the PR

Notice

  • I acknowledge and agree that, by checking this box and clicking "Submit Pull Request":

  • I submit this contribution under the Apache 2.0 license and represent that I am entitled to do so on behalf of myself, my employer, or relevant third parties, as applicable.

  • I certify that (a) this contribution is my original creation and / or (b) to the extent it is not my original creation, I am authorised to submit this contribution on behalf of the original creator(s) or their licensees.

  • I certify that the use of this contribution as authorised by the Apache 2.0 license does not violate the intellectual property rights of anyone else.

Comment thread causalnex/structure/structuremodel.py Outdated
Comment thread causalnex/structure/__init__.py Outdated
Comment thread causalnex/structure/structuremodel.py Outdated
Comment thread causalnex/structure/structuremodel.py Outdated
Comment thread causalnex/structure/structuremodel.py Outdated
Comment thread causalnex/structure/structuremodel.py

@GabrielAzevedoFerreiraQB GabrielAzevedoFerreiraQB left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We're in the right direction, but there I'd say the still some good amount of things to focus on before it gets merged.

Let me know if you need time to chat/PS about it. Thanks!

Comment thread causalnex/network/network.py Outdated
Comment on lines +743 to +757
Base class for Dynamic Bayesian Network (DBN), a probabilistic weighted DAG where nodes represent variables,
edges represent the causal relationships between variables.

``DynamicBayesianNetwork`` stores nodes with their possible states, edges and
conditional probability distributions (CPDs) of each node.

``DynamicBayesianNetwork`` is built on top of the ``StructureModel``, which is an extension of ``networkx.DiGraph``
(see :func:`causalnex.structure.structuremodel.StructureModel`).

In order to define the ``DynamicBayesianNetwork``, users should provide a relevant ``StructureModel``.
Once ``DynamicBayesianNetwork`` is initialised, no changes to the ``StructureModel`` can be made
and CPDs can be learned from the data.

The learned CPDs can be then used for likelihood estimation and predictions.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

looks good.
I think the text should be a bit different from the one in the BN class though. It's ok to keep the similar points, but I would rather say that a DBN is a BN with the time domain taken into account, and it does X and Y that a normal BN doesn't do

WDYT?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yes i think i need a PS here :)

Comment thread causalnex/network/network.py Outdated
Raises:
ValueError: If the structure is not a connected DAG.
"""
super().__init__(structure) No newline at end of file

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Just wanted to know if you're clear on the changes that will need to come here. If not let's have a PS anytime :)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yes i think i need a PS here :)

Comment thread causalnex/structure/dynotears.py
Comment thread causalnex/structure/structuremodel.py Outdated
Comment on lines +359 to +361
def checkargs(function):
def _f(*arguments, **attr):
for index, argument in enumerate(inspect.getfullargspec(function)[0]):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is really great and helpful!

Could you add docs - I try to add docs every time a function does something non-obvious

Also:

  • will it work for in case the user provides attr isntead of arguments?
  • I usally use (*args, **kw_args), but not sure if it is the de-facto standard. what do you think?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I believe if a dictionary is passed as an arg it is absorbed intoattr. I should test if someone calls the function like add_node(dnode=node), i'm not sure if that would be a member of argmuments or attr.

Comment thread causalnex/structure/structuremodel.py Outdated
Comment on lines +368 to +370
if len(arg) == 3:
if not all(isinstance(n, DynamicStructureNode) for n in arg[:-1]):
raise TypeError("{} is not of type {}".format(arguments[index], function.__annotations__[argument]))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think with docstrings it will be clearer, but would love to understand the checks themselves better.

I wonder why len(arg) == 3 - I'm sure there is a reason, just couldn't get it yet

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Its for add_weighted_edges_from when the third element of the tuple is a number

Comment on lines +452 to +454
"""
Get the subgraph with the specified node.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I also see that some functions are pretty similar to the StructureNode counterpart. Maybe we can reuse them/avoid repeating code?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Here i think after calling
node_name = node.get_node_name()
I could call
super.get_target_subgraph(node_name)

Comment thread causalnex/structure/dynotears.py Outdated
(
_format_name_from_pandas(idx_col, u),
_format_name_from_pandas(idx_col, v),
DynamicStructureNode(idx_col[int(u[0])], u[-1]), # _format_name_from_pandas(idx_col, u), idx_col[int(u[0])]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can we delete the comment, please? :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants