Giter VIP home page Giter VIP logo

lukaszahradnik / pyneuralogic Goto Github PK

View Code? Open in Web Editor NEW
271.0 6.0 18.0 32.42 MB

PyNeuraLogic lets you use Python to create Differentiable Logic Programs

Home Page: https://pyneuralogic.readthedocs.io/

License: MIT License

Python 100.00%
machine-learning deep-learning graph-neural-networks relational-learning python geometric-deep-learning pytorch logic-programming differentiable-programming

pyneuralogic's Introduction

PyNeuraLogic

PyPI version License Tests Status Code Quality Status Documentation Status Tweet

Documentation | Examples | Papers

PyNeuraLogic lets you use Python to write Differentiable Logic Programs


About

Logic programming is a declarative coding paradigm in which you declare your logical variables and relations between them. These can be further composed into so-called rules that drive the computation. Such a rule set then forms a logic program, and its execution is equivalent to performing logic inference with the rules.

PyNeuralogic, through its NeuraLogic backend, then makes this inference process differentiable which, in turn, makes it equivalent to forward propagation in deep learning. This lets you learn numeric parameters that can be associated with the rules, just like you learn weights in neural networks.

SQL tutorial

What is this good for?

Many things! For instance - ever heard of Graph Neural Networks (GNNs)? Well, a graph happens to be a special case of a logical relation - a binary one to be more exact. Now, at the heart of any GNN model there is a so-called propagation rule for passing 'messages' between the neighboring nodes. Particularly, the representation ('message') of a node X is calculated by aggregating the previous representations of adjacent nodes Y, i.e. those with an edge between X and Y.

Or, a bit more 'formally':

Relation.message2(Var.X) <= (Relation.message1(Var.Y), Relation.edge(Var.Y, Var.X))

...and that's the actual code! Now for a classic learnable GNN layer, you'll want to add some weights, such as

Relation.message2(Var.X)[5,10] <= (Relation.message1(Var.Y)[10,20], Relation.edge(Var.Y, Var.X))

to project your [20,1] input node embeddings ('message1') through a learnable [10,20] layer before the aggregation, and subsequently a [5,10] layer after the aggregation.

If you don't like the default settings, you can of course specify various additional details, such as the particular aggregation and activation functions

(R.message2(V.X)[5,10] <= (R.message1(V.Y)[10,20], R.edge(V.Y, V.X))) | [Transformation.RELU, Aggregation.AVG]

to instantiate the classic GCN layer specification, which you can directly train now!

How is it different from other GNN frameworks?

Naturally, PyNeuralogic is by no means limited to GNN models, as the expressiveness of relational logic goes much further beyond graphs. Hence, nothing stops you from playing directly with:

  • multiple relations and object types
  • hypergraphs, nested graphs, relational databases
  • relational pattern matching, various subgraph GNNs
  • alternative propagation schemes
  • inclusion of logical background knowledge
  • and more...

In PyNeuraLogic, all these ideas take the same form of simple small logic programs. These are commonly highly transparent and easy to understand, thanks to their declarative nature. Consequently, there is no need to design a zoo of blackbox class names for each small modification of the GNN rule - you code directly at the level of the logical principles here!

The backend engine then creates the underlying differentiable computation (inference) graphs in a fully automated and dynamic fashion, hence you don't have to care about aligning everything into some static (tensor) operations.

How does it perform?

While PyNeuraLogic allows you to easily declare highly expressive models with capabilities far beyond the common GNNs, it does not come at the cost of performance for the basic GNNs either. On the contrary, for a range of common GNN models and applications, such as learning with molecules, PyNeuraLogic is actually considerably faster than the popular GNN frameworks, as demonstrated in our benchmarks.

Benchmark of PyNeuraLogic


We hope you'll find the framework useful in designing your own deep relational learning ideas beyond the GNNs! Please let us know if you need some guidance or would like to cooperate!

๐Ÿ’ก Getting started

Installation

To install PyNeuraLogic's latest release from the PyPI repository, use the following command:

$ pip install neuralogic

Prerequisites

To use PyNeuraLogic, you need to install the following prerequisites:

Python >= 3.8
Java >= 1.8

In case you want to use visualization provided in the library, it is required to have Graphviz installed.

๐Ÿ”ฌ Examples

Open In Colab Simple XOR example
Open In Colab Molecular GNNs
Open In Colab Recursive XOR generalization
Open In Colab Visualization

Open In Colab Subgraph Patterns
Open In Colab Distinguishing k-regular graphs
Open In Colab Distinguishing non-regular graphs


๐Ÿ“ฆ Predefined Modules

PyNeuraLogic has a set of predefined modules to get you quickly started with your experimenting! It contains, for example, predefined modules for:

  • Graph Neural Networks (GNNConv, SAGEConv, GINConv, RGCNConv, ...)
  • Meta graphs and meta paths (MetaConv, MAGNN, ...)
  • Transformer, LSTM, GRU, RNN, ...and more!

๐Ÿ“ Papers

๐Ÿ“˜ Articles

๐ŸŽฅ Videos

pyneuralogic's People

Contributors

gustiks avatar joaquincabezas avatar lukaszahradnik avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

pyneuralogic's Issues

[โœจ Feature Request]: raise a more descriptive exception when no queries are defined for a Dataset

Is your feature request related to a problem? Please describe.

While familiarizing myself with the framework, I defined a Dataset object and added some examples to it. At first, I forgot to add queries before attempting to call evaluator.train(dataset, generator=False) and received the following NullPointerException:

Py4JJavaError: An error occurred while calling o176.collect.
: java.lang.NullPointerException
at cz.cvut.fel.ida.neural.networks.structure.building.Neuralizer.getQueryMatchingLiterals(Neuralizer.java:250)
at cz.cvut.fel.ida.neural.networks.structure.building.Neuralizer.supervisedNeuralization(Neuralizer.java:171)
at cz.cvut.fel.ida.neural.networks.structure.building.Neuralizer.neuralize(Neuralizer.java:145)
at cz.cvut.fel.ida.pipelines.pipes.specific.SupervisedNeuralizationPipe.lambda$apply$1(SupervisedNeuralizationPipe.java:38)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
at java.base/java.util.stream.ReferencePipeline$11$1.accept(ReferencePipeline.java:442)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at py4j.reflection.MethodInvoker.invoke(MethodInvoker.java:244)
at py4j.reflection.ReflectionEngine.invoke(ReflectionEngine.java:357)
at py4j.Gateway.invoke(Gateway.java:282)
at py4j.commands.AbstractCommand.invokeMethod(AbstractCommand.java:132)
at py4j.commands.CallCommand.execute(CallCommand.java:79)
at py4j.GatewayConnection.run(GatewayConnection.java:238)
at java.base/java.lang.Thread.run(Thread.java:829)

Describe the solution you'd like

A more descriptive error could be raised in case the dataset does not contain any queries. Since it is an exception triggered by the Java backend, it is possible that it should be handled there. In that case, please let me know and I will move this issue to the backend repo.

Describe alternatives you've considered

No response

Additional context

No response

[๐Ÿ› Bug Report]: ImportError: cannot import name 'Aggregation' from 'neuralogic.core.settings'

Describe the bug

When trying to build the model from a template, using the PyG backend, it throws the following error:

Traceback (most recent call last):
  File "<input>", line 1, in <module>
    model = template.build(Backend.PYG, settings)
  File "/usr/local/lib/python3.8/site-packages/neuralogic/core/template.py", line 124, in build
    return get_neuralogic_layer(backend)(self.module_list)
  File "/usr/local/lib/python3.8/site-packages/neuralogic/nn/__init__.py", line 19, in get_neuralogic_layer
    from neuralogic.nn.native.pyg import NeuraLogic
  File "/usr/local/lib/python3.8/site-packages/neuralogic/nn/native/pyg.py", line 4, in <module>
    from neuralogic.core.settings import Activation, Aggregation
ImportError: cannot import name 'Aggregation' from 'neuralogic.core.settings' (/usr/local/lib/python3.8/site-packages/neuralogic/core/settings/__init__.py)

Steps to reproduce the behavior

This is the script that is being used:

from neuralogic.core import Relation, Dataset
from neuralogic.core import Template
from neuralogic.utils.templates import GCNConv, TemplateList
from neuralogic.core import Backend
from neuralogic.core import Settings, Optimizer

dataset = Dataset()
dataset.add_example([
    Relation.edge(1, 2), Relation.edge(2, 1), Relation.edge(1, 3),
    Relation.edge(3, 1), Relation.edge(2, 3), Relation.edge(3, 2),

    Relation.feature(1)[0],
    Relation.feature(2)[1],
    Relation.feature(3)[-1],
])

template = Template(module_list=TemplateList([
    GCNConv(in_channels=5, out_channels=5),
    GCNConv(in_channels=5, out_channels=1),
]))

settings = Settings(learning_rate=0.01, optimizer=Optimizer.SGD, epochs=100)

model = template.build(Backend.PYG, settings)

Expected behavior

The expected behaviour would be the creation of the model from the specified template.

Environment

macOS Monterey Version 12.2.1 (21D62)
python 3.8.12
neuralogic 0.1.3
torch-geometric 2.0.3

Additional context

No response

[๐Ÿ› Bug Report]: Drawing a template raises NullPointerException

Describe the bug

On Windows, when using the Template.draw method, I get the following error even though I have GraphViz installed and added to the Path (I tried out both System and User path variables):

Exception                                 Traceback (most recent call last)
File Drawer.java:80, in cz.cvut.fel.ida.drawing.Drawer.drawIntoFile()

Exception: Java Exception

The above exception was the direct cause of the following exception:

java.lang.NullPointerException            Traceback (most recent call last)
File ...\neuralogic\utils\visualize\__init__.py:75, in draw(drawer, obj, filename, show, img_type, *args, **kwargs)
     74 try:
---> 75     drawer.drawIntoFile(obj, os.path.abspath(filename))
     76 except jpype.java.lang.NullPointerException as e:

java.lang.NullPointerException: java.lang.NullPointerException: Cannot invoke "cz.cvut.fel.ida.algebra.weights.Weight.toString(java.text.NumberFormat)" because the return value of "cz.cvut.fel.ida.logic.constructs.template.components.WeightedRule.getWeight()" is null

...

Exception                                 Traceback (most recent call last)
File ...\neuralogic\core\template.py:159, in Template.draw(self, filename, show, img_type, value_detail, graphviz_path, model, *args, **kwargs)
    157 if model is None:
    158     model = self.build(Settings())
--> 159 return draw_model(model, filename, show, img_type, value_detail, graphviz_path, *args, **kwargs)

File ...\neuralogic\utils\visualize\__init__.py:153, in draw_model(model, filename, show, img_type, value_detail, graphviz_path, *args, **kwargs)
    150 template = model.template
    151 template_drawer = get_template_drawer(get_drawing_settings(img_type, value_detail, graphviz_path))
--> 153 return draw(template_drawer, template, filename, show, img_type, *args, **kwargs)

File ...\neuralogic\utils\visualize\__init__.py:77, in draw(drawer, obj, filename, show, img_type, *args, **kwargs)
     75         drawer.drawIntoFile(obj, os.path.abspath(filename))
     76     except jpype.java.lang.NullPointerException as e:
---> 77         raise Exception(
     78             "Drawing raised NullPointerException. Try to install GraphViz (https://graphviz.org/download/) on "
     79             "your Path or specify the path via the `graphviz_path` parameter"
     80         ) from e
     82     return
     84 data = drawer.drawIntoBytes(obj)

Exception: Drawing raised NullPointerException. Try to install GraphViz (https://graphviz.org/download/) on your Path or specify the path via the `graphviz_path` parameter

The exception seems to be at least misleading, as can be seen from the two examples below.

Steps to reproduce the behavior

While the following small example works just fine:

from neuralogic.core import Template, R, V

feature_dim = 1
hidden_dim = 3
output_dim = 1

template = Template()

template += (R.layer_1(V.X)[hidden_dim, feature_dim] <= (R.feature(V.Y), R._edge(V.Y, V.X)))
template += (R.predict[output_dim, hidden_dim] <= R.layer_1(V.X))
# {3, 1} layer_1(X) :- feature(Y), *edge(Y, X).
# {1, 3} predict :- layer_1(X).

template.draw('fig.png')

possibly suggesting the problem is not with Path or Graphviz, the next example throws the error above:

from neuralogic.core import Template
from neuralogic.nn.module import GCNConv

feature_dim = 1
hidden_dim = 3
output_dim = 1

template = Template()

template.add_module(
    GCNConv(in_channels=feature_dim, out_channels=hidden_dim, output_name="h0", feature_name="node", edge_name="edge")
)
# h0__edge(I, I).
# h0__edge(I, J) :- edge(I, J). [transformation=identity]
# h0__edge/2 [transformation=identity]
# h0__edge_count(I, J) :- h0__edge(J, X). [transformation=identity, aggregation=count]
# h0__edge_count(I, J) :- h0__edge(I, X). [transformation=identity, aggregation=count]
# h0__edge_count/2 [transformation=inverse, combination=product]
# {3, 1} h0(I) :- node(J), h0__edge(J, I), sqrt(h0__edge_count(J, I)). [transformation=identity, combination=product, aggregation=sum]
# h0/1 [transformation=identity]
template.draw('fig.png')  # <-- throws an error

Expected behavior

Drawing the graph representation of the template.

Environment

Windows 11 Home 10.0.22631
Python 3.12.3
neuralogic 0.7.11
torch 2.2.2
torch-geometric 2.5.2

Additional context

No response

[๐Ÿ› Bug Report]: Cycle breaking of recursive rules

Describe the bug

I am trying to implement a recursive path rule on the Mutagenesis dataset, and the rules are defined as below:

template.add_rules([
    (R.bond_embed(V.B)[3,] <= R.get(bond)(V.B)) for bond in ["b_1", "b_2", "b_3", "b_4", "b_5", "b_7"]
])

template += R.path(V.X, V.Y) <= (R.bond(V.X, V.Y, V.B), R.bond_embed(V.B)[3, 3]) 
template += R.path(V.X, V.Y) <= (R.bond(V.X, V.Z, V.B), R.bond_embed(V.B)[3, 3], R.path(V.Z, V.Y)[3, 3])

The problem is that when I have weights in the second rule, it cannot build the dataset and I get the following error:

Screenshot_1

Without weights, it does not produce any errors.

Steps to reproduce the behavior

Make a template with these rules and try to build the dataset.

Expected behavior

The dataset can be built with the given weighted rules.

Environment

No response

Additional context

No response

[๐Ÿ› Bug Report]: saving `state_dict` with torch or pickle causes an error

Describe the bug

As from the title, saving a state_dict with torch causes an error

_pickle.PicklingError: Can't pickle <java class 'java.lang.String'>: attribute lookup java.lang.String on jpype._jstring failed

Steps to reproduce the behavior

Assuming torch is loaded and we have a (trained) model initialised by model = template.build(settings), the error occurs with the following code

state_dict = model.state_dict()
torch.save(state_dict, save_file)

Expected behavior

The code does not cause a pickling error.

Environment

No response

Additional context

I have an easy workaround which does not seem to cause any issues by converting the strings into Python strings

state_dict = model.state_dict()
state_dict["weight_names"] = {k: str(v) for k, v in state_dict["weight_names"].items()}
torch.save(state_dict, save_file)

I don't seem to have any unexpected behaviour while doing this, e.g. loaded models have the same predictions.

[โœจ Feature Request]:

Is your feature request related to a problem? Please describe.

Currently, I am implementing Subgraph network rules for GNNs, and I need to operate on edges and create new graphs based on the connectivity of these edges, but I am not aware of any way to do it in this framework at this moment. I think it may be beneficial to add some feature which would allow creation of new nodes based on some given rules.

Describe the solution you'd like

I would need some way of creating new nodes and graphs based on the rules, for example some code similar to the following would be expected:

Relation.edge_node(V.E) <= Relation.edge(V.X, V.Y) # creates a node for each edge of the original graph
Relation.edge(V.X, V.Y, V.E) <= Relation.edge_node(V.E), Relation.edge(V.X, V.Y) # defines a relation that ties the edge node and its original nodes together

Relation.edge(V.E1, V.E2) <= (Relation.edge(V.X, V.Y, V.E1), Relation.edge(V.X, V.Z, V.E2))# creates edge between the nodes created above

Describe alternatives you've considered

No response

Additional context

No response

[โœจ Feature Request]: Preprocessing

Is your feature request related to a problem? Please describe.

As discussed in #47 I was thinking on a previous stage where we can be sure that some logic is applied just to the facts.

Describe the solution you'd like

As Gus posed it: "prune out the preprocessing subgraph (not just a chain as it is now), and make its end nodes the new fact neurons (hence effectively skipping it in training)."

Describe alternatives you've considered

Doing this outside the logic language, but was dissapointing

Additional context

No response

[โœจ Feature Request]: to_logic_form() and edge_attr

Is your feature request related to a problem? Please describe.

The to_logic_form() method defined here doesn't seem to consider the 'edge_attr' attribute.

Describe the solution you'd like

Should't it initialize the edge predicate weights with the values passed to edge_attr? Something in the lines of

Relation.get(edge_name)(int(u), int(v), int(w))[1].fixed() for u, v, w in zip(self.edge_index[0], self.edge_index[1], self.edge_attr[:, 0])

Describe alternatives you've considered

No response

Additional context

No response

[๐Ÿ› Bug Report]: IndexOutOfBoundsException while training the model

Describe the bug

I am trying to train a simple model using the PyNeraLogic framework on the CLUTRR dataset.

However, after creating my Dataset and setting up the Template, I am getting the following error before the first training epoch starts:

/usr/local/lib/python3.7/dist-packages/_jpype.cpython-37m-x86_64-linux-gnu.so in cz.cvut.fel.ida.neural.networks.computation.training.strategies.PythonTrainingStrategy.learnSamples()

/usr/local/lib/python3.7/dist-packages/_jpype.cpython-37m-x86_64-linux-gnu.so in cz.cvut.fel.ida.neural.networks.computation.training.strategies.trainers.SequentialTrainer$SequentialListTrainer.learnEpoch()

/usr/local/lib/python3.7/dist-packages/_jpype.cpython-37m-x86_64-linux-gnu.so in cz.cvut.fel.ida.neural.networks.computation.training.strategies.trainers.Trainer.learnFromSample()

/usr/local/lib/python3.7/dist-packages/_jpype.cpython-37m-x86_64-linux-gnu.so in cz.cvut.fel.ida.neural.networks.computation.training.strategies.trainers.Trainer.backpropSample()

/usr/local/lib/python3.7/dist-packages/_jpype.cpython-37m-x86_64-linux-gnu.so in cz.cvut.fel.ida.neural.networks.computation.iteration.actions.Backpropagation.backpropagate()

/usr/local/lib/python3.7/dist-packages/_jpype.cpython-37m-x86_64-linux-gnu.so in cz.cvut.fel.ida.neural.networks.computation.iteration.modes.Topologic$TDownVisitor.topdown()

/usr/local/lib/python3.7/dist-packages/_jpype.cpython-37m-x86_64-linux-gnu.so in java.util.ArrayList.get()

/usr/local/lib/python3.7/dist-packages/_jpype.cpython-37m-x86_64-linux-gnu.so in java.util.Objects.checkIndex()

/usr/local/lib/python3.7/dist-packages/_jpype.cpython-37m-x86_64-linux-gnu.so in jdk.internal.util.Preconditions.checkIndex()

/usr/local/lib/python3.7/dist-packages/_jpype.cpython-37m-x86_64-linux-gnu.so in jdk.internal.util.Preconditions.outOfBoundsCheckIndex()

/usr/local/lib/python3.7/dist-packages/_jpype.cpython-37m-x86_64-linux-gnu.so in jdk.internal.util.Preconditions.outOfBounds()

Exception: Java Exception

The above exception was the direct cause of the following exception:

java.lang.IndexOutOfBoundsException       Traceback (most recent call last)
[<ipython-input-96-4b77102c2769>](https://localhost:8080/#) in <module>()
      5 average_losses = []
      6 
----> 7 for i, current_total_loss, number_of_samples in enumerate(evaluator.train(dataset)):
      8     print(f"epoch: {i}")
      9     clear_output(wait=True)

[/usr/local/lib/python3.7/dist-packages/neuralogic/nn/evaluators/java.py](https://localhost:8080/#) in _train()
     42         def _train():
     43             for _ in range(epochs):
---> 44                 results, total_len = self.neuralogic_model(None, True)
     45                 yield sum(result[2] for result in results), total_len
     46             if dataset is not None:

[/usr/local/lib/python3.7/dist-packages/neuralogic/nn/java.py](https://localhost:8080/#) in __call__(self, samples, train, auto_backprop, epochs)
     80 
     81         if samples is None:
---> 82             results = self.strategy.learnSamples(epochs)
     83             deserialized_results = json.loads(str(results))
     84 

java.lang.IndexOutOfBoundsException: java.lang.IndexOutOfBoundsException: Index -1 out of bounds for length 9

Steps to reproduce the behavior

My Template is based on this example.

One sample graph in the CLUTRR dataset looks as follows

story: [('Donald', 'father', 'Michael'), ('Michael', 'sister', 'Dorothy')]	
target: ('Donald', 'aunt', 'Dorothy')

The input triplets and the target pair (Donald, Dorothy) are given and the task is to predict their relationship (aunt), it is thus an R-way classification task where R is the total number of relations (such as aunt, father, ...).

Below you can see the dataset creation process

for i in range(len(data.train)):
    sample = data.train[i]

    query = Relation.predict(*sample.target)
    
    persons = set(p for p, _, _ in sample.story)
    persons.update(p for _, _, p in sample.story)

    example = list(itertools.chain(
        (Relation.edge(u, r, v) for u, r, v in sample.story),
        (Relation.rel(r) for _, r, _ in sample.story + [sample.target]),
        (Relation.person(p) for p in persons)
    ))

    dataset.add_example(example)
    dataset.add_query(query)

This results in a dataset that looks like this:

Query:
predict(Donald, aunt, Dorothy).
Example:
['edge(Donald, father, Michael)', 'edge(Michael, sister, Dorothy)', 'rel(father)', 'rel(sister)', 'rel(aunt)', 'person(Dorothy)', 'person(Donald)', 'person(Michael)']

The template definition is equivalent to the definition of the example template mentioned above, but it is rewritten to the PyNeuraLogic syntax. It looks as follows:

template = Template()

# {3} @embed_nation(X) :- nation(X).
# {3} @embed_rel(X) :- rel(X).
template.add_rules([
    (R.person_embed(V.A)[3,] <= R.person(V.A)),
    (R.rel_embed(V.B)[3,] <= R.rel(V.B))
])

# embed_nat1(X) :- {3,3} embed_rel(R), {3,3} embed_nation(Y), {3} r(X,R,Y).
template.add_rule(
    R.person_embed1(V.X) <= (R.rel_embed(V.R)[3, 3], R.person_embed(V.Y)[3, 3], R.edge(V.X, V.R, V.Y)[3,])
)

# embed_nat2(Y) :- {3,3} embed_nation(X), {3,3} embed_rel(R), {3} r(X,R,Y).
template.add_rule(
    R.person_embed2(V.Y) <= (R.person_embed(V.X)[3, 3], R.rel_embed(V.R)[3, 3], R.edge(V.X, V.R, V.Y)[3,])
)

# {1,3} predict(X,R,Y) :- {3,3} embed_nat1(X), {3,3} embed_nat2(Y), {3,3} embed_rel(R).
template.add_rule(
    R.predict(V.X, V.R, V.Y)[1, 3] <= (R.person_embed1(V.X)[3, 3], R.person_embed2(V.Y)[3, 3], R.rel_embed(V.R)[3, 3])
)

The evaluator definition and part of training loop can be seen here. The last line triggers the exception.

settings = Settings(optimizer=Optimizer.ADAM, epochs=120, learning_rate=0.001, error_function=ErrorFunction.SQUARED_DIFF)
evaluator = get_evaluator(template, Backend.JAVA, settings)

for i, current_total_loss, number_of_samples in enumerate(evaluator.train(dataset)):
    ...

Expected behavior

calling evaluator.train(dataset) should yield (current_total_loss, number_of_samples) correctly instead of raising an exception

Environment

Google Colab (Python 3.6)

Additional context

Also, are there any other fundamental issues with the way I defined the dataset and architecture for this particular task? I am still trying to wrap my head around the way this framework works and how to rewrite PyG code to neuralogic language.

Thank you!

[๐Ÿ› Bug Report]: Visualization draw_model function crashes on None/Null

Describe the bug

From the This example notebook Visualization.ipynb:
Call to neuralogic.utils.visualize.draw_model function, draw_model(model), results in the following error:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-7-59797e1249fd> in <module>
      7 model = template.build(Backend.JAVA, Settings())
      8 
----> 9 draw_model(model)

...\lib\site-packages\neuralogic\utils\visualize\__init__.py in draw_model(model, filename, draw_ipython, img_type, value_detail, *args, **kwargs)
     93     template_drawer = get_template_drawer(get_drawing_settings(img_type=img_type, value_detail=value_detail))
     94 
---> 95     return draw(template_drawer, template, filename, draw_ipython, img_type, *args, **kwargs)
     96 
     97 

...\lib\site-packages\neuralogic\utils\visualize\__init__.py in draw(drawer, obj, filename, draw_ipython, img_type, *args, **kwargs)
     55         return
     56 
---> 57     data = bytes(drawer.drawIntoBytes(obj))
     58 
     59     if draw_ipython:

TypeError: cannot convert 'NoneType' object to bytes

Similarly, adding a filename to the call (draw_model(model, 'img.png'), see code snippets below) results in a NullPointerException:

---------------------------------------------------------------------------
Exception                                 Traceback (most recent call last)
...\lib\site-packages\_jpype.cp38-win_amd64.pyd in cz.cvut.fel.ida.drawing.Drawer.drawIntoFile()

...\lib\site-packages\_jpype.cp38-win_amd64.pyd in cz.cvut.fel.ida.drawing.GraphViz.writeImageToFile()

~\Anaconda3\envs\bakalarka\lib\site-packages\_jpype.cp38-win_amd64.pyd in java.io.FileOutputStream.write()

Exception: Java Exception

The above exception was the direct cause of the following exception:

java.lang.NullPointerException            Traceback (most recent call last)
<ipython-input-8-91eec29cdcf5> in <module>
      7 model = template.build(Backend.JAVA, Settings())
      8 
----> 9 draw_model(model, 'img.png')

...\lib\site-packages\neuralogic\utils\visualize\__init__.py in draw_model(model, filename, draw_ipython, img_type, value_detail, *args, **kwargs)
     93     template_drawer = get_template_drawer(get_drawing_settings(img_type=img_type, value_detail=value_detail))
     94 
---> 95     return draw(template_drawer, template, filename, draw_ipython, img_type, *args, **kwargs)
     96 
     97 

...\lib\site-packages\neuralogic\utils\visualize\__init__.py in draw(drawer, obj, filename, draw_ipython, img_type, *args, **kwargs)
     51 def draw(drawer, obj, filename: Optional[str] = None, draw_ipython=True, img_type="png", *args, **kwargs):
     52     if filename is not None:
---> 53         drawer.drawIntoFile(obj, os.path.abspath(filename))
     54 
     55         return

java.lang.NullPointerException: java.lang.NullPointerException

Steps to reproduce the behavior

I have come across this error in my own example codes, but it is enough to run the Visualization.ipynb notebook, concretely:

from neuralogic.utils.visualize import draw_model
from neuralogic.utils.data import XOR_Vectorized
from neuralogic.core import Settings, Backend


template, dataset = XOR_Vectorized()
model = template.build(Backend.JAVA, Settings())

draw_model(model)

For the NullPointerException, I used:

from neuralogic.utils.visualize import draw_model
from neuralogic.utils.data import XOR_Vectorized
from neuralogic.core import Settings, Backend


template, dataset = XOR_Vectorized()
model = template.build(Backend.JAVA, Settings())

draw_model(model, 'img.png')

Expected behavior

I should be able to visualize the model.

Environment

No response

Additional context

No response

[๐Ÿ› Bug Report]: AttributeError when testing the model

Describe the bug

I am trying to test a model using evaluator.test(test_dataset), but I am getting the following exception:

[<ipython-input-58-4d4659b17081>](https://localhost:8080/#) in test(test_dataset)
      2 def test(test_dataset: Dataset) -> float:
      3     correct = 0
----> 4     for y, y_hat in evaluator.test(test_dataset):
      5         # print(f"Expected: {y}, Predicted: {round(y_hat)} ({y_hat})")
      6         if round(y) == round(y_hat):

[/usr/local/lib/python3.7/dist-packages/neuralogic/nn/evaluators/java.py](https://localhost:8080/#) in _test()
     62             for sample in dataset.samples:
     63                 result = self.neuralogic_model(sample, False)
---> 64                 yield result.target(), result.output()
     65 
     66         if generator:

[/usr/local/lib/python3.7/dist-packages/neuralogic/nn/java.py](https://localhost:8080/#) in target(self)
     24 
     25     def target(self) -> float:
---> 26         return self.loss.getTarget().value
     27 
     28 

AttributeError: 'cz.cvut.fel.ida.algebra.values.VectorValue' object has no attribute 'value'

Steps to reproduce the behavior

I have my dataset and template set up as discussed in our recent discussion (I am using onehot encoding for the class labels). I am also using the following settings

settings = Settings(optimizer=Optimizer.ADAM, epochs=n_epochs, learning_rate=0.001, error_function=ErrorFunction.CROSSENTROPY)

I am able to successfully run the training loop, but as soon as I want to test the model I receive the AttributeError exception.

Expected behavior

I should be able to test the model without an error.

Environment

Google Colab

Additional context

No response

[โœจ Feature Request]: Adding gradients to NeuralSample for visualisation of importance

Is your feature request related to a problem? Please describe.

As described in discussion #59, I would like to visualize the importance of the nodes for the infered prediction.

Describe the solution you'd like

It would be best to have a way to get the node for some defined predicate, and extract the gradients and weights values.

Describe alternatives you've considered

No response

Additional context

No response

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.