2014年2月28日金曜日

Drools - ベイジアンネットワーク インテグレーション

原文: Drools - Bayesian Belief Network Integration by Mark Proctor (Drools & jBPM)

プラグイン機構の信念システム(pluggable belief system)の開発は次のステージへと進んでいます。現在、ベイジアンネットワークサブシステムとのインテグレーションに取り組んでいます。何がおこっているのかしっかりと理解したかったので、私は独自実装を進めています。

私はこの素晴らしいチュートリアルを実践しています:
http://www.mathcs.emory.edu/~whalen/Papers/BNs/Intros/BayesianNetworksTutorial.pdf

このチュートリアルも実践しています:
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.135.7921&rep=rep1&type=pdf

与えられたグラフから最適なジャンクションツリー(junction trees)を生成する非常に効率的なアルゴリズムができました。最終的なジャンクションツリーを生成する前に、まず moralise し triangulate します。ジャンクションツリーアルゴリズムはグラフをツリーに変換します。よって、実行時に発生するネットワークの伝播は NP困難(NP-hard)ではなくなりました。

全ての小さな作業パーツに対して、ローレベルなユニットテストをたくさん書きました。しっかりとした物を作れていることを確認したかったですし、最終的な変換結果を単純にテストするだけでは充分ではないからです。どのようなものかアイディアをつかむ為、前述した2つのチュートリアルにある例を対象としたユニットテストを作りました。注意点としては効率化する為、クリークをエンコードするのにビットセットを使っています。最初のmainベイジアンネットワークのみグラフオブジェクトとして表記されています。その後、 隣接行列(adjacency matrix)によりすべて変換されます。-軽量性と高速性は維持されます。

オラシオ(Horacio)はベイジアンネットワークのUIに取り組んできました。まだ初期段階ですが、ベイジアン XML BIF標準を解析し、ノードを表示することができます。次に彼がコネクターを追加した後、私達は編集機能の実装に取り組む予定です。動画をご覧いただけます:
http://vimeo.com/85732009

次に、私はメッセージの伝播(message propagation)に取り組む予定です。完全にインテグレートされて利用可能なプラグイン機構の信念システムを 4~6週間後にご提供できればと思います。進捗状況はブログでお伝えします。

例1
@Test
public void testFullExample1() {
    // from "Bayesian Belief Network Propagation Engine In Java"
    // the result here is slightly different, due to ordering, but it's still correct.
    // http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.135.7921&rep=rep1&type=pdf
    Graph<BayesVariable> graph = new GraphImpl<BayesVariable>();
    Vertex xa = addVertex( graph );
    Vertex xb = addVertex( graph );
    Vertex xc = addVertex( graph );
    Vertex xd = addVertex( graph );
    Vertex xe = addVertex( graph );
    Vertex xf = addVertex( graph );
    Vertex xg = addVertex( graph );
    Vertex xh = addVertex( graph );

    connectParentToChildren(xa, xb, xc);
    connectParentToChildren(xb, xd);
    connectParentToChildren(xc, xe, xg);
    connectParentToChildren(xd, xf);
    connectParentToChildren(xe, xf, xh);
    connectParentToChildren(xg, xh);


    BitSet clique1 = bitSet("00000111"); // a, b, c
    BitSet clique2 = bitSet("00001110"); // b, c, d
    BitSet clique3 = bitSet("00011100"); // c, d, e
    BitSet clique4 = bitSet("01010100"); // c, e, g
    BitSet clique5 = bitSet("11010000"); // e, g, h
    BitSet clique6 = bitSet("00111000"); // d, e, f


    BitSet clique1And2 = bitSet("00000110"); // b, c
    BitSet clique2And3 = bitSet("00001100"); // c, d
    BitSet clique3And4 = bitSet("00010100"); // c, e
    BitSet clique4And5 = bitSet("01010000"); // e, g
    BitSet clique3And6 = bitSet("00011000"); // d, e

    // clique1
    JunctionTreeBuilder jtBuilder = new JunctionTreeBuilder( graph );
    JunctionTreeNode<BayesVariable> root = jtBuilder.build();
    assertEquals( clique1, root.getBitSet() );


    // clique2
    assertEquals(1, root.getSeparators().size());
    JunctionTreeSeparator sep =  root.getSeparators().get(0);
    assertEquals( clique1And2, sep.getBitSet() );
    JunctionTreeNode<BayesVariable> jtNode2 =sep.getNode2();
    assertEquals( clique1, sep.getNode1().getBitSet() );
    assertEquals( clique2, jtNode2.getBitSet() );
    assertEquals(2, jtNode2.getSeparators().size());

    // clique3
    assertSame( sep, jtNode2.getSeparators().get(0));
    sep =  jtNode2.getSeparators().get(1);
    assertEquals( clique2And3, sep.getBitSet() );
    JunctionTreeNode<BayesVariable>  jtNode3 =sep.getNode2();
    assertEquals( clique2, sep.getNode1().getBitSet() );
    assertEquals( clique3, jtNode3.getBitSet() );
    assertEquals( 3, jtNode3.getSeparators().size());

    // clique4
    assertSame( sep, jtNode3.getSeparators().get(0));
    sep =  jtNode3.getSeparators().get(1);
    assertEquals( clique3And4, sep.getBitSet() );
    JunctionTreeNode<BayesVariable> jtNode4 = sep.getNode1();
    assertEquals( clique3, sep.getNode2().getBitSet() );
    assertEquals( clique4, jtNode4.getBitSet() );
    assertEquals( 2, jtNode4.getSeparators().size());

    // clique5
    assertSame( sep, jtNode4.getSeparators().get(0));
    sep =  jtNode4.getSeparators().get(1);
    assertEquals( clique4And5, sep.getBitSet() );
    JunctionTreeNode<BayesVariable> jtNode5 = sep.getNode1();
    assertEquals( clique4, sep.getNode2().getBitSet() );
    assertEquals( clique5, jtNode5.getBitSet() );
    assertEquals( 1, jtNode5.getSeparators().size());

    //clique 6
    sep =  jtNode3.getSeparators().get(2);
    assertEquals( clique3And6, sep.getBitSet() );
    JunctionTreeNode<BayesVariable> jtNode6 = sep.getNode1();
    assertEquals( clique3, sep.getNode2().getBitSet() );
    assertEquals( clique6, jtNode6.getBitSet() );
    assertEquals( 1, jtNode6.getSeparators().size());
}


例2
@Test
public void testFullExample2() {
    // Bayesian Networks -  A Self-contained introduction with implementation remarks
    // http://www.mathcs.emory.edu/~whalen/Papers/BNs/Intros/BayesianNetworksTutorial.pdf
    Graph<BayesVariable> graph = new GraphImpl<BayesVariable>();
    Vertex xElectricity = addVertex( graph );   // 0
    Vertex xTelecom = addVertex( graph );       // 1
    Vertex xRail = addVertex( graph );          // 2
    Vertex xAirTravel = addVertex( graph );     // 3
    Vertex xTransportation = addVertex( graph );// 4
    Vertex xUtilities = addVertex( graph );     // 5
    Vertex xUSBanks = addVertex( graph );       // 6
    Vertex xUSStocks = addVertex( graph );      // 7

    connectParentToChildren( xElectricity, xRail, xAirTravel, xUtilities, xTelecom );
    connectParentToChildren( xTelecom, xUtilities, xUSBanks );
    connectParentToChildren( xRail, xTransportation );
    connectParentToChildren( xAirTravel, xTransportation );
    connectParentToChildren( xUtilities, xUSStocks );
    connectParentToChildren( xUSBanks, xUSStocks );
    connectParentToChildren( xTransportation, xUSStocks );


    BitSet clique1 = bitSet("11110000"); // Utilities, Transportation, USBanks, UStocks
    BitSet clique2 = bitSet("01110001"); // Electricity, Transportation, Utilities, USBanks
    BitSet clique3 = bitSet("01100011"); // Electricity, Telecom, Utilities, USBanks
    BitSet clique4 = bitSet("00011101"); // Electricity, Rail, AirTravel, Transportation

    BitSet clique1And2 = bitSet("01110000"); // Utilities, Transportation, USBanks
    BitSet clique2And3 = bitSet("01100001"); // Electricity, Utilities, USBanks
    BitSet clique2And4 = bitSet("00010001"); // Electricity, Transportation


    xElectricity.setContent(new BayesVariable("Electricity", xElectricity.getId(),
                                              new Object[]{"Working", "Reduced", "NotWorking"}, new double[][]{{0.6, 0.3, 0.099}}));

    xTelecom.setContent(new BayesVariable("Telecom", xTelecom.getId(),
                                          new Object[]{"Working", "Reduced", "NotWorking"}, new double[][]{{0.544, 0.304, 0.151}}));

    xRail.setContent(new BayesVariable("Rail", xRail.getId(),
                                       new Object[]{"Working", "Reduced", "NotWorking"}, new double[][]{{0.579, 0.230, 0.190}}));

    xAirTravel.setContent(new BayesVariable("AirTravel", xAirTravel.getId(),
                                            new Object[]{"Working", "Reduced", "NotWorking"}, new double[][]{{0.449, 0.330, 0.219}}));

    xTransportation.setContent(new BayesVariable("Transportation", xTransportation.getId(),
                                                 new Object[]{"Working", "Moderate", "Severe", "Failure"}, new double[][]{{0.658, 0.167, 0.097, 0.077}}));

    xUtilities.setContent(new BayesVariable("Utilities", xUtilities.getId(),
                                             new Object[]{"Working", "Moderate", "Severe", "Failure"}, new double[][]{{0.541, 0.272, 0.097, 0.088}}));

    xUSBanks.setContent(new BayesVariable("USBanks", xUSBanks.getId(),
                                          new Object[]{"Working", "Reduced", "NotWorking"}, new double[][]{{0.488, 0.370, 0.141}}));

    xUSStocks.setContent(new BayesVariable("USStocks", xUSStocks.getId(),
                                          new Object[]{"Up", "Down", "Crash"}, new double[][]{{0.433, 0.386, 0.179}}));

    JunctionTreeBuilder jtBuilder = new JunctionTreeBuilder( graph );
    JunctionTreeNode<BayesVariable> root = jtBuilder.build();


    // clique1
    assertEquals( clique1, root.getBitSet() );
    assertEquals( 1, root.getSeparators().size() );

    // clique2
    JunctionTreeSeparator sep =  root.getSeparators().get(0);
    assertEquals( clique1And2, sep.getBitSet() );
    JunctionTreeNode<BayesVariable> jtNode2 = sep.getNode2();
    assertEquals( clique1, sep.getNode1().getBitSet() );
    assertEquals( clique2, jtNode2.getBitSet() );
    assertEquals(3, jtNode2.getSeparators().size());

    // clique3
    assertSame( sep, jtNode2.getSeparators().get(0) );
    sep =  jtNode2.getSeparators().get(1);
    assertEquals( clique2And3, sep.getBitSet() );
    JunctionTreeNode<BayesVariable> jtNode3 = sep.getNode1();
    assertEquals( clique2, sep.getNode2().getBitSet() );
    assertEquals( clique3, jtNode3.getBitSet() );
    assertEquals(1, jtNode3.getSeparators().size());

    // clique4
    sep =  jtNode2.getSeparators().get(2);
    assertEquals( clique2And4, sep.getBitSet() );
    JunctionTreeNode<BayesVariable> jtNode4 = sep.getNode1();
    assertEquals( clique2, sep.getNode2().getBitSet() );
    assertEquals( clique4, jtNode4.getBitSet() );
    assertEquals(1, jtNode4.getSeparators().size());
}

原文: Drools - Bayesian Belief Network Integration by Mark Proctor (Drools & jBPM)

1 件のコメント:

  1. Droolsの未来が見える内容です。pluggable belief systemで、ベイジアンネットワークとインテグレートしようという開発日記です。ベイジアンネットワークUIの話もあり、ワクワクしますよ

    原文の開発日記はすでにPart3まで進んでいます。翻訳を待てない方はどうぞ。
    Drools - Bayesian Belief Network Integration Part 2
    http://blog.athico.com/2014/04/drools-bayesian-belief-network.html

    Drools - Bayesian Belief Network Integration Part 3
    http://blog.athico.com/2014/05/drools-bayesian-belief-network.html

    返信削除