opcode81 / ProbCog

A toolbox for statistical relational learning and reasoning.
GNU General Public License v3.0
101 stars 26 forks source link

Simple preconditions as precondition nodes #6

Closed jpauwels closed 6 years ago

jpauwels commented 8 years ago

As a simple exercise to understand the concept of precondition nodes, I'm trying to convert the simple style preconditions, e.g. +next(before,after) in the hmm example, to a precondition node (green box). I tried simply with next(before,after) in a green box, and EXIST before (next(before,after)) and some variants, but I can't get it to work. What would be the right way to do this?

opcode81 commented 8 years ago

In this case, "+next(before, after)" is not only a precondition but also serves to determine the value of before through the functional property of predicate next (relationKey). (Note that before would be free otherwise.) The mapping is currently only implemented for the +-type notation, so it can't be replaced by a green precondition node. Sorry about this not being stated in the documentation.

jpauwels commented 8 years ago

Thanks for your quick answer. What I actually want to do, is to create a second order Markov model such that rain(t) not only depends on rain(t-1), but also on rain(t-2). I unsuccessfully tried creating the following network: hmm-2nd-order

and adding the following lines to the blnd:

logical boolean nextTwo(time, time);
prolog nextTwo(X,Y) :- V is X+2, Y=V.
relationKey nextTwo(_,y);

What am I doing wrong?

Moving beyond this problem, I'd eventually like to move the prolog nextTwo(X,Y) :- V is X+2, Y=V. rule out of the blnd into a blnl such that I can easily try other network architectures. It seems that the blnl uses another syntax though, and my tries are not working (e.g. Y=X+2 => nextTwo(X,Y).). Eventually, I also might want to provide the nextTwo predicates as evidence. Is this possible and does it make sense in the first place?

opcode81 commented 8 years ago

Sorry about the late response, I completely forgot about your response and only now was reminded...

Anway, "+nextTwo(two_back,after)" should be a parent of "rain(after)" instead of "#rain(two_back)", because the instantiation of "rain(after)" needs the information to resolve the variable "two_back" in its parent "#rain(two_back)". Have you tried that?

A node starting with "#" should, by the way, never have any parents, as it is a mere auxiliary node which does not define a fragment itself (though I understand where you're coming from).

As for the blnl, it is only for hard logical constraints that are to appear in the final probabilistic model. It can't be used to define prolog rules which are evaluated prior to the instantiation of the probabilistic model (in a preprocessing stage). While the logical rules will typically affect non-evidence predicates, prolog rules can be used only for predicates that are purely evidence predicates; the determination of the evidence (i.e. which atoms are true/false) can happen through prolog.

jpauwels commented 8 years ago

Thanks, that makes sense. I think I'm getting closer but still not there yet. My next try is this network: bln-2nd-order-hmm

I actually tried without the decision nodes first, but I figured something needs to handle the first two states as a special case. For reference, this is the unrolled chain I try to achieve: goal-2nd-order-hmm

What's worse, even if I delete the "#rain(two_ago)" node entirely, I still get the same grounding error for the variable rain(1).

opcode81 commented 8 years ago

You have defined two of the necessary fragments for the predicate "rain": the one with two predecessors, i.e. "rain(after)", and the one without any predecessors, i.e. "rain(before)" with the precondition "before=0" (note that this can be simplified to "rain(0)" without any parents). What's missing is the fragment with one predecessor. The easiest way of defining it is to add a node "rain(1)" and add as its parent "#rain(0)".

And remember: an auxiliary node (such as "#rain(two_ago") must not have any parents; these parents are simply ignored... Also: you needn't define any distributions for these variables; they serve only to specify what a parent of another variable is, nothing more.

jpauwels commented 8 years ago

I finally got the 2nd order HMM to work thanks to your suggestions. The "rain(before)" and "before=0" nodes cannot be simplified to "rain(0)" though, because then every node is connected to the first one instead of forming a chain. For future reference, here's the solution: hmm-2nd-order

I think I sort of found the errors in my reasoning too: you cannot draw edges from logic, you can only use logic to make already connected nodes appear/disappear. The former is more how I usually think about problems, but I guess this would make it hard to generate the required conditional probability tables. Let me know if I'm wrong about this though.

Now for the actual problem that I'd like to solve: starting from a first order HMM, I'd like to draw additional edges between non-adjacent nodes if a predicate "connect(a,b)" given as evidence is true. What I came up with is this: hmm-arbitrary

Just saving this network crashes the editor though and cuts a part of the xml-file such that it becomes unreadable. It's not the first time this behaviour happens and it's highly irritable because then I can't run the program and even loose all my work. Can you tell me if this is at least going in the right direction?

The network is inspired by Fig. 4 in your Technical Report, but as far as I can see its code is nowhere available. It would be hugely useful if that example and others from the TR could be found somewhere online.

opcode81 commented 8 years ago

To clarify: are you saving the file as .xml or .pmml? Because .xml is not recommended for BLNs.

jpauwels commented 8 years ago

Using a pmml file indeed solved the editor problem. I also finally understood the benefits of using auxiliary nodes to clean up the graph. The result is the following: hmm-arbitrary2

I'm getting closer, because the network can be grounded and does what I want when no "connect" predicates are given (or when they are false). But when I specify "connect(1,3)=True", I get the following error: "No relational node was found that could serve as the template for the variable rain(3)". I guess the value (=1) given for "longer_ago" in the evidence predicate fails to propagate to "rain(longer_ago)", such that the grounding of "rain(3)" fails due to an unknown parent, but I don't know how to correct this.