forum.hugin.com
User Forums => HUGIN API Discussion => Java => Topic started by: jack on July 20, 2011, 17:46:33
-
Hi,
can anybody please tell me how to pass database for EM learning using JAVA HUGIN API.
I realized that you should do with the method learnTable () of the class domain ,
but I haven't understand how to pass to the method my database (MySQL).
Please help!
Thanks
-
There is no direct method for inserting cases from a mysql database.
What you have to do is to write some code that first creates the cases in the Domain from your mysql data, and then invokes the learnTables method.
In code you will have to iterate each case in your mysql database, and use HUGIN API methods for creating the case in the Domain.
Add a new case to the domain
int Domain.newCase()
Set a discrete node to a specific state for a given case
void DiscreteNode.setCaseState(int c, int state)
When all cases have been created in the Domain, invoke learnTables.
-
thanks for the quick answer.
-
I must to add a new case for each state of node with:
"int Domain.newCase() "??
Another, instead of using:
void DiscreteNode.setCaseState(int c, int state)
I used
void LabelledDCNode.setStateLabel(int state, java.lang.String newLabel)
because the state of my node are words and they aren't number
-
int Domain.newCase()
This method creates a new empty case in Domain.
void DiscreteNode.setCaseState(int c, int state)
This method sets the state of a node in a specific case. It is necessary to invoke this method for each node in each case to construct a complete set of cases (i.e., a set of cases with no missing values). You may consider using DiscreteNode.getStateIndex (String) to identify the state index corresponding to a particular String.
void LabelledDCNode.setStateLabel(int state, java.lang.String newLabel)
This method sets the state label of a LabelledDCNode to newLabel.
-
Thanks for the quick answer....
My codes generates error :
"Errore: An Api function was called with an invalid argument(e.g., a NULL object was passed to a function that expects a non-NULL argument).
I have written some code that creates the cases in the Domain from your mysql data:
...................
String a;
int p=0;
LabelledDCNode node1 = new LabelledDCNode(myDomain);
node1.setName.........
node1.setLabel...........
......................
Resulset rset = stmt.executeQuery("SELECT ....... FROM .......;")
int statenode1=0;
while(rset.next()){
p.myDomain.newCase();
node1.setCaseState(p,statenode1);
a = rset.getString("node1");
node1.setStateLabel(statenode1,a);
statenode1++;
}
Resulset rset2............
.........................
.................
myDomain.compile();
myDomain.learnTables();
.............
and I have written some code that print tables for all discrete node
public static void printTable(Table CPT)..........
..................
...................
You could help me solve this problem?
Thanks a lot
P.S. ...and to use the algorythm PC?
I use void Domain.learnStructure() instead learnTable?
-
The error message ""Error: An Api function was called with an invalid argument(e.g., a NULL object was passed to a function that expects a non-NULL argument)" states that one of the arguments to a HUGIN method is NULL. From your code example it is difficult to say which one. (I assume
p.myDomain.newCase();
is in fact p=myDomain.newCase();
).
The error could be caused by "a" being NULL. It is good practice to including error testing code and printing a stack-trace will help to locate the cause of the problem. You should test for NULL arguments before calling HUGIN methods.
The learn the structure of a network using the PC algorithm you invoke "learnStructure ()".
-
thank you for the quick answer but the error isn't that......
i have the same error
My code complete is:
import java.sql.*;
import java.util.*;
import COM.hugin.HAPI.*;
public class Test{
public static void main (String []args throws ExceptionHugin{
try{
java.lang.Class.forName("com.mysql.jdbc.Driver");
}
catch (Exception exc){
System.out.println("Error - Driver jdbc not present: "+exc.getMessage());
}
try{
String a,b;
Domain myDomain=new Domain();
int p=0;
int q=0;
LabelledDCNode one = new LabelledDCNode(myDomain);
one.setLabel("one");
one.setName("one");
one.setNumberOfStates(40);
LabelledDCNode two = new LabelledDCNode(myDomain);
two.addParent(one);
two.setLabel("two");
two.setName("two");
two.setNumberOfStates(40);
Connection conn = DriverManager.getConnection("url","user","password");
Statement stmt = conn.createStatement();
Resulset rset = stmt.executeQuery("SELECT one FROM table;");
int statenode1 = 0;
while(rset.next()){
p=myDomain.newCase();
one.setCaseState(p,statenode1);
a = rset.getString("one");
//System.out.println(a);
one.setStateLabel(statenode1,a);
statenode1++
}
Resulset rset2 = stmt.executeQuery("SELECT two FROM table;");
int statenode2 = 0;
while(rset2.next()){
q=myDomain.newCase();
two.setCaseState(q,statenode2);
b=rset2.getString("two");
//System.out.println(b);
two.setStateLabel(statenode2,b);
statenode2++
}
myDomain.compile();
myDomain.learnTable(); // or myDomain.learnStructure();
Table t = two.getTable();
printTable(t);
Table t1 = one.getTable();
printTable(t1);
rset.close();
rset2.close();
stmt.close();
conn.close();
}
catch(Exception exc){
System.out.println("Error:"+exc.getMessage());
}
}
public static void printTable(Table CPT) throws ExceptionHugin{
NodeList nodes = CPT.getNodes();
int[] configuration = new int [nodes.size()];
int tableSize = CPT.getSize();
for(int i=0;i<tableSize;i++){
CPT.getConfiguration(configuration,i);
for (int j=0;j<nodes.size();j++){
Node n = (Node)nodes.get(j);
System.out.print(n.getName()+"="+configuration[j]+" ");
}
System.out.println(":= "+CPT.getDataItem(i));
}
}
}
...........If I print a and b, I can see which they are the values of my databases.
I think which the error is generated by learntable() or learnStructure()
-
I cannot test your code at I do not have a database connection...
The error message indicates an error in a parameter to a HUGIN method. Domain.learnTables and Domain.learnStrcucture does not take any argument. Please test the input values to each HUGIN method invocation.
Here is a working example showing how to enter and learn (CPTs) from data:
/*
* This simple Java program illustrates how to learn (the parameters)
* of a Bayesian network from data
*
* The result is stored in a file name learning.net
*
*
* Author: Anders L Madsen @ HUGIN EXPERT A/S
*
* For any questions or comments, please contact the author at
* alm@hugin.com
*/
import COM.hugin.HAPI.*;
import java.text.DecimalFormat;
class EnterDataExample {
// the model
Domain dom = null;
// the nodes / variables in the model
LabelledDCNode Sex, Height;
public EnterDataExample ()
{
try {
// Create domain. Done once.
dom = new Domain ();
Sex = new LabelledDCNode(dom); Sex.setName ("Sex");
Height = new LabelledDCNode(dom); Height.setName ("Height");
Sex.setNumberOfStates (2);
Sex.setStateLabel (0, "Female");
Sex.setStateLabel (1, "Male");
Height.setNumberOfStates (2);
Height.setStateLabel (0, "Low");
Height.setStateLabel (1, "High");
// Add Sex as parent of Height. Comment this line if you
// uncomment "dom.learnStructure ();" below
Height.addParent (Sex);
// create Experience tables to enable CPT estimatio
Sex.getExperienceTable ();
Height.getExperienceTable ();
} catch (Exception e) {
e.printStackTrace ();
System.err.println (e.getMessage ());
}
}
// Data is an array of strings. First entry is Sex and second is
// Height;
String dataArray[][] =
{
{"Male", "High"},
{"Male", "High"},
{"Male", "High"},
{"Female", "High"},
{"Female", "Low"},
{"Male", "Low"},
{"Female", "Low"},
{"Male", "High"},
{"Male", ""},
{"Female", "Low"}
};
;
int N=10;
// Main procedure.
protected void doLearning () {
try{
// enter data
enterData ();
// (learn structure) compile and estimate parameters
// dom.learnStructure (); // uncomment this line (and the
// addParent line) above to learn structure from data
dom.compile ();
dom.learnTables ();
// save domain in file
dom.saveAsNet ("learning.net");
} catch (Exception e) {
e.printStackTrace ();
System.err.println (e.getMessage ());
}
}
//
protected void enterData () {
try{
long j, s;
for (int i = 0; i < N; i++) {
j = dom.newCase ();
s = Sex.getStateIndex (dataArray[i][0]);
if (s >= 0)
Sex.setCaseState (j, s);
s = Height.getStateIndex (dataArray[i][1]);
if (s >= 0)
Height.setCaseState (j, s);
}
//... more data
} catch (Exception e) {
e.printStackTrace ();
System.err.println (e.getMessage ());
}
}
static public void main (String args[])
{
EnterDataExample ede = new EnterDataExample ();
ede.doLearning ();
}
}
-
thanks a lot.............
I added
one.getExperienceTable();
two.getExperienceTable();
before of myDomain.compile() and now my code is running with learnTable().
If I use learnStructure() (algorithm PC) get the same output:
"Error: An Api function was called with an invalid argument(e.g., a NULL object was passed to a function that expects a non-NULL argument)".
-
please send me you updated code.
-
import java.sql.*;
import java.util.*;
import COM.hugin.HAPI.*;
public class Test{
public static void main (String []args throws ExceptionHugin{
try{
java.lang.Class.forName("com.mysql.jdbc.Driver");
}
catch (Exception exc){
System.out.println("Error - Driver jdbc not present: "+exc.getMessage());
}
try{
String a,b;
Domain myDomain=new Domain();
int p=0;
int q=0;
LabelledDCNode one = new LabelledDCNode(myDomain);
one.setLabel("one");
one.setName("one");
one.setNumberOfStates(40);
LabelledDCNode two = new LabelledDCNode(myDomain);
two.setLabel("two");
two.setName("two");
two.setNumberOfStates(40);
Connection conn = DriverManager.getConnection("url","user","password");
Statement stmt = conn.createStatement();
Resulset rset = stmt.executeQuery("SELECT one FROM table;");
int statenode1 = 0;
while(rset.next()){
p=myDomain.newCase();
one.setCaseState(p,statenode1);
a = rset.getString("one");
//System.out.println(a);
one.setStateLabel(statenode1,a);
statenode1++
}
Resulset rset2 = stmt.executeQuery("SELECT two FROM table;");
int statenode2 = 0;
while(rset2.next()){
q=myDomain.newCase();
two.setCaseState(q,statenode2);
b=rset2.getString("two");
//System.out.println(b);
two.setStateLabel(statenode2,b);
statenode2++
}
two.addParent(one);
one.getExperienceTable();
two.getExperienceTable();
myDomain.compile();
myDomain.learnStructure();
Table t = two.getTable();
printTable(t);
Table t1 = one.getTable();
printTable(t1);
rset.close();
rset2.close();
stmt.close();
conn.close();
}
catch(Exception exc){
System.out.println("Error:"+exc.getMessage());
}
}
public static void printTable(Table CPT) throws ExceptionHugin{
NodeList nodes = CPT.getNodes();
int[] configuration = new int [nodes.size()];
int tableSize = CPT.getSize();
for(int i=0;i<tableSize;i++){
CPT.getConfiguration(configuration,i);
for (int j=0;j<nodes.size();j++){
DiscreteNode n = (DiscreteNode)nodes.get(j);
int h=configuration[j];
System.out.print(n.getStateLabel(h)+" ");
}
System.out.println(":= "+CPT.getDataItem(i));
}
}
}
P.S.On your code EnterDataExample i have two error:
Sex.setCaseState(j,s);
Height.setCaseState(j,s);
Error:The metod setCaseState(int,int) in the type DiscreteNode is not applicable for the arguments(long,long)
-
You should not call Domain.compile before Domain.learnStructure. This will make Domain.learnStructure fail. Call Domain.compile after Domain.learnStructure.
P.S.On your code EnterDataExample i have two error:
Sex.setCaseState(j,s);
Height.setCaseState(j,s);
Error:The metod setCaseState(int,int) in the type DiscreteNode is not applicable for the arguments(long,long)
I'm using 64-bit version. If you use 32-bit, then change the long to int.
-
Thank you.
If I call Domain.compile after Domain.learnStructure I have always the same output:
"Error: An API function was called with an invalid argument (e.g., a NULL object was passed to a function that expects a non-NULL argument)."
.......I can't understand wher's this error.
-
Put in some error handling code (try-catch with a printStackTrace call) and identify which line produces the error.
Also, it would be useful as debugging to save the data entered into the domain as file - use Domain.saveCases ().
Please reread the example I posted previously and adapt this example to your situation. Notice the method setStateLabel should not be used as part of entering data and read the documentation on setCaseState.
-
thank you.
I added try-catch with a printStackTrace call and the output is:
"COM.hugin.HAPI.ExceptionUsage: An API function was called with an invalid argument (e.g., a NULL object was passed to a function that expects a non-NULL argument).
at COM.hugin.HAPI.ExceptionHugin.throwException(ExceptionHugin.java:115)
at COM.hugin.HAPI.Domain.learnStructure(Domain.java:1451)
at Prova.main(Test.java:80)"
to the line 80 of Test.java there is :
myDomain.learnStructure();
-
What about the data file? If there is no data entered into the domain, then this error message may be produced. Save the cases to file before calling Domain.learnStructure and inspect the file (or post it here).
-
I think, my error is this, but I cannot understand how I pass cases to the domain.
For the my code, I haven't data file but I have the data of my database.
In the while loops after
p=myDomain.newCase();
I save the cases with Domain.saveCase(String) in a txt file but I have a file empty.
How I save the cases???
-
Please read section 11.1 on data and entering data of the HUGIN API Reference Manual and study the example sent to you previously.
You need to use Domain.saveCases (and not Domain.saveCase) to debug.
-
thanks..........
I used
Domain.saveCases();
and I could see the .dat file:
# - one - two
1 - "car" - #0
1 - #1 - "red"
1 - #2 - #2
1 - #3 - #3
1 - "house" - #4
1 - "computer" - "green"
the. dat file generated doesn't contain all the values but it has in some position #0,#1,#2..............
Why???
If I print with System.out.println() those values I have the right values
-
Please attach the data file.
The tokens "#0, #1, ..." refers to state indexes. Chapter 11 of the HUGIN API Reference Manual describes the learning process and the structure of the data files in great detail. PLEASE read this chapter.
-
thanks....
I have always the same error:
"COM.hugin.HAPI.ExceptionUsage: An API function was called with an invalid argument (e.g., a NULL object was passed to a function that expects a non-NULL argument).
at COM.hugin.HAPI.ExceptionHugin.throwException(ExceptionHugin.java:115)
at COM.hugin.HAPI.Domain.learnStructure(Domain.java:1451)
at Prova.main(Test.java:80)"
In my code:
1 - in the while loop I pass the value of record of my database to the states of nodes
2 - I use Domain.saveCases(java.lang.String fileName, NodeList nodes, int[] cases, boolean caseCounts, java.lang.String separator, java.lang.String missingData) to save the cases in a file "cases.dat"
3 - I use Domain.parseCases(java.lang.String fileName, ParseListener parseListener) to pass the cases stored in "cases.dat" and enters the cases into this Domain.
4 - I use Domain.leanStructure for PC-algorithm
5 - I use Domain.compile()
6 - I use Domain.learnTables()
This is a part of my new code:
...........................
int cases[]=new int[30];
int p=0;
int z=0;
boolean caseCount=true;
int statenode = 0;
NodeList nodes = new NodeList();
nodes.add(one);
nodes.add(two);
Resulset rset = stmt.executeQuery("SELECT one FROM table;");
Resulset rset2 = stmt2.executeQuery("SELECT two FROM table;");
while(rset.next()&&rset2.next()){
p=myDomain.newCase();
cases[z]=p;
one.setCaseState(p,statenode);
two.setCaseState(p,statenode);
a = rset.getString("one");
b = rset2.getString("two");
one.setStateLabel(statenode,a);
two.setStateLabel(statenode,b);
statenode++;
z++
}
two.addParent(one);
myDomain.saveCases("cases.dat",nodes,cases,caseCount," "," ");
myDomain.parseCases("cases.dat",new DefaultClassParseListener());
myDomain.learnStructure();
myDomain.compile();
myDomain.learnTables();
........................
-
PLEASE attach the "cases.dat" file.
-
This is my new file "cases.dat":
# one two
1 "car" "yellow"
1 "pen" "red"
1 "train" "white"
1 "bag" "black"
1 "house" "blue"
1 "computer" "green"
If I use "pen","bag","yellow" and "black" two or three times instead of "train","bag","yellow"and "white", I have values #0,#1,.........
This is my old file "cases.dat":
# one two
1 "car" #0
1 #1 "red"
1 #2 #2
1 #3 #3
1 "house" #4
1 "computer" "green"
-
As described in the example I posted, you should not use "addParent" when invoking "learnStructure".
Page 157 of the HUGIN API Reference Manual states under the description of "learnStructure":
This function creates directed links (found by the PC algorithm) between the
nodes of domain, which is assumed to contain only discrete chance nodes
and no edges.
Hence, it is an usage error to use "addParent" before invoking "learnStructure".
-
OK..................
Thanks, thanks thanks..........................
Now I have a problem to the print of tables.
I use to the print tables the metod "printTable (Table CPT)" of post "How to pass .dat file using JAVA HUgin API for EM learning.":
//print tables for all discrete chance nodes
public static void printTable (Table CPT) throws ExceptionHugin {
NodeList nodes = CPT.getNodes();
int[] configuration = new int[nodes.size()];
int tableSize = CPT.getSize();
for (int i = 0; i < tableSize; i++) {
CPT.getConfiguration(configuration, i);
for (int j = 0; j < nodes.size(); j++) {
Node n = (Node)nodes.get(j);
System.out.print(n.getName() + "=" + configuration[j] + " ");
}
System.out.println(":= " + CPT.getDataItem(i));
}
}
Now in output I have the print of table but the values are not equal to those obtained by Hugin GUI:
table of node "one" with hugin GUI:
car := 0.166667
pen :=0.5
house :=0.166667
computer:=0.166667
table of node "one" with hugin java output:
one=0 := 0.16666666666666669
one=1 := 0.16666666666666669
one=2 := 0.16666666666666669
one=3 := 0.16666666666666669
one=4 := 0.16666666666666669
one=5 := 0.16666666666666669
but the value of one=1,one=2,one=3 is "pen" and then I should have a single value with probability value 0.5 as well in hugin gui
-
Please study again the example I posted earlier. It illustrates how you first create the nodes and their states of the network. Once the nodes are created you either use "learnStructure" followed by "learnTables" or create the structure (using "addParent") and followed by "learnTables" to estimate the parameters from data.
In the code you explicitly create one state for each data item. Also, you assume that each node should have 40 states.
-
ok now everything works well.
But I have yet another question.
I do not know a priori the number of states of the node, but if I don't set first setNumberOfStates I cannot call setStateLabel.
How can I solve this problem?
thaanks,thanks,thanks very very much
-
You need to determine the number of states of each node and their labels prior to creating the Domain object. You cannot do this on the fly (or at least you have to be very careful not to create two or more states for the same label). This best approach is to make two passes through the data. One for determining the number of states and labels and the second pass for entering the data to the Domain object.