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
Enhancement/1089 build method clarity #1140
Enhancement/1089 build method clarity #1140
Conversation
Code Climate has analyzed commit 0e8865d and detected 5 issues on this pull request. Here's the issue category breakdown:
View more on Code Climate. |
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.
Hmm when this was refactoring was proposed, I was under the impression that build
(now in_out_tensors
) would be calling node_model
and link_model
internally (i.e. the two methods are the helper methods used by in_out_tensors
after checking multiplicity). But since this doesn't seem to be the case, is there any point in having those two private methods at all? Who are they intended to be used by?
This is going to be a bit annoying, but I feel like we really should have deprecations here. This is such a massive change that I imagine almost all users of StellarGraph will hit it (only those doing pure Node2vec or similar won't, I think), and as it stands, I think they'll hit an error like manual build methodsdef build(self, *args, **kwargs):
"""Deprecated: use :meth:`in_out_tensors`."""
warnings.warn("The 'build' method is deprecated, use 'in_out_tensors' instead.", DeprecationWarning, stacklevel=2)
return self.in_out_tensors(*args, **kwargs) defining a single function and setting it in each classWe could do the previous one somewhat magically, by defining a single instance of it (e.g. in def deprecated_model_build(object, *args, **kwargs):
"""Deprecated: use :meth:`in_out_tensors`."""
warnings.warn("The 'build' method is deprecated, use 'in_out_tensors' instead.", DeprecationWarning, stacklevel=2)
return object.in_out_tensors(*args, **kwargs) and then each model includes something like: from .misc import deprecated_model_build
class GCN:
...
build = deprecated_model_build defining a base class for models with a
|
I think having a seperate |
Some models like
I felt this fit into unifying the API to only use |
@huonw good point about the deprecations, I think I'll go for the |
Yeah, it's easy to do as a separate PR; in fact, I'd already opened #1145 doing it before I'd seen this PR. |
@@ -843,6 +843,10 @@ def __init__( | |||
) | |||
) | |||
|
|||
self.node_model = deprecated_model_function(self._node_model, "node_model") |
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.
Sorry to re-review before being suggested, but my original suggestion was careful to create these statically in each class. To be more specific, this would be like
class GAT:
...
def _node_model(self):
...
node_model = deprecated_model_function(_node_model, "node_model")
link_model = deprecated_model_function(_link_model, "link_model")
build = deprecated_model_function(in_out_tensors, "build")
This approach should mean they're still shown in the documentation, unlike dynamically assigning them when building each instance. After doing this, and moving the doc string from deprecated_model_function
to _function_wrapper
, the docs look like:
Compared to the current approach of this PR of https://stellargraph--1140.org.readthedocs.build/en/1140/api.html#stellargraph.layer.graph_attention.GAT.in_out_tensors which just shows in_out_tensors
.
Exact diff of changes
diff --git a/stellargraph/layer/graph_attention.py b/stellargraph/layer/graph_attention.py
index 65f5b8e0..a0a8df35 100644
--- a/stellargraph/layer/graph_attention.py
+++ b/stellargraph/layer/graph_attention.py
@@ -843,10 +843,6 @@ class GAT:
)
)
- self.node_model = deprecated_model_function(self._node_model, "node_model")
- self.link_model = deprecated_model_function(self._link_model, "link_model")
- self.build = deprecated_model_function(self.in_out_tensors, "build")
-
def __call__(self, inputs):
"""
Apply a stack of GAT layers to the input x_inp
@@ -964,3 +960,7 @@ class GAT:
"Node model requested but a generator not supporting nodes was supplied."
)
return self.in_out_tensors(multiplicity=1)
+
+ node_model = deprecated_model_function(_node_model, "node_model")
+ link_model = deprecated_model_function(_link_model, "link_model")
+ build = deprecated_model_function(in_out_tensors, "build")
diff --git a/stellargraph/layer/misc.py b/stellargraph/layer/misc.py
index f97de342..6512632f 100644
--- a/stellargraph/layer/misc.py
+++ b/stellargraph/layer/misc.py
@@ -97,9 +97,9 @@ class SqueezedSparseConversion(Layer):
def deprecated_model_function(function, old_name):
- """Deprecated: use :meth:`in_out_tensors`."""
def _function_wrapper(*args, **kwargs):
+ """Deprecated: use :meth:`in_out_tensors`."""
warnings.warn(
f"The '{old_name}' method is deprecated, use 'in_out_tensors' instead.",
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.
nice good point!
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.
@huonw my current approach isn't triggering deprecation warnings, can you see anything wrong?
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.
my current approach isn't triggering deprecation warnings, can you see anything wrong?
What do you mean by this specifically? How are you testing?
Per #1117, the stacklevel
needs to be set correctly (although it looks like it is), and, even with this, they'll only show up in Jupyter, or in script run with Python 3.7 not Python 3.6.
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.
I'm testing some models in test_deprecated_model_function
in test_misc.py
, and I've also tried using the depracted functions in jupyter notebooks. The functions work but I'm not getting a warning
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.
i'm getting jupyter warnings now nevermind, must just be my test
# Conflicts: # demos/node-classification/gcn/gcn-cora-node-classification-example.ipynb # stellargraph/layer/deep_graph_infomax.py # tests/layer/test_deep_graph_infomax.py # tests/layer/test_knowledge_graph.py
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.
pass | ||
|
||
|
||
def test_deprecated_model_functions(): |
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.
Epic test!
stellargraph/layer/rgcn.py
Outdated
return self._node_model() | ||
|
||
else: | ||
raise NotImplementedError( | ||
"Currently only node prediction if supported for RGCN." | ||
) | ||
|
||
node_model = deprecated_model_function(_node_model, "node_model") |
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.
The _node_model
method already wasn't public, so I'm not sure this is necessary?
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.
nice catch!
@@ -509,7 +509,7 @@ | |||
} | |||
], | |||
"source": [ | |||
"x_inp, x_out = gcn.build()\n", | |||
"x_inp, x_out = gcn.in_out_tensors()\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.
There's text above that should be updated via the `GCN.build` method:
-> via the `GCN.in_out_tensors` method:
.
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.
nice catch! I found another one in the cluster gcn demo
@@ -270,41 +270,6 @@ def test_hinsage_apply(): | |||
assert actual == pytest.approx(expected) | |||
|
|||
|
|||
def test_hinsage_default_model(): |
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.
Why delete this test? Despite the name, it was using build
?
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.
ah I was too hasty to delete this one, I'll ad it back and rename it
@@ -270,41 +270,6 @@ def test_hinsage_apply(): | |||
assert actual == pytest.approx(expected) | |||
|
|||
|
|||
def test_hinsage_default_model(): |
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.
Should we be trying to keep/update this test?
def test_hinsage_in_out_tensors():
...
xin, xout = hs.in_out_tensors()
...
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.
I was too hasty to delete this one, I'll ad it back and rename it
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.
Looks good to me!
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.
Thanks for doing this so efficiently! Hopefully the in_out_tensors
name is clearer 🤞
You'll need to merge with develop to resolve the conflicts caused by the rename in #1153.
This PR cleans up the API for creating models. It makes several core changes:
APPNP
,Attri2Vec
,GCN
,GAT
,GraphSAGE
,HinSAGE
,PPNP
, thenode_model
andlink_model
methods are now private. Migration:model.node_model()
: usemodel.in_out_tensors()
(if the model was created with a node generator) ormodel.in_out_tensors(multiplicity=1)
(otherwise)model.link_model()
: usemodel.in_out_tensors()
(if the model was created with a link generator) ormodel.in_out_tensors(multiplicity=1)
(otherwise)build
is renamed toin_out_tensors
for all model classes. Migration: replacemodel.build()
withmodel.in_out_tensors()
In support of this, it makes some other changes:
in_out_tensors
instead ofnode_model
/link_model
/build
/default_model
multiplicity
keyword arg intoin_out_tensors
for models with amultiplicity
attributeSee #1089 and #1116