📄 bayesnetgenerator.java
字号:
/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *//* * BayesNet.java * Copyright (C) 2003 Remco Bouckaert * */package weka.classifiers.bayes.net;import weka.classifiers.bayes.BayesNet;import weka.classifiers.bayes.net.estimate.DiscreteEstimatorBayes;import weka.core.Attribute;import weka.core.FastVector;import weka.core.Instance;import weka.core.Instances;import weka.core.Option;import weka.core.OptionHandler;import weka.core.Utils;import weka.estimators.Estimator;import java.util.Enumeration;import java.util.Random;import java.util.Vector;/** <!-- globalinfo-start --> * Bayes Network learning using various search algorithms and quality measures.<br/> * Base class for a Bayes Network classifier. Provides datastructures (network structure, conditional probability distributions, etc.) and facilities common to Bayes Network learning algorithms like K2 and B.<br/> * <br/> * For more information see:<br/> * <br/> * http://www.cs.waikato.ac.nz/~remco/weka.pdf * <p/> <!-- globalinfo-end --> * <!-- options-start --> * Valid options are: <p/> * * <pre> -B * Generate network (instead of instances) * </pre> * * <pre> -N <integer> * Nr of nodes * </pre> * * <pre> -A <integer> * Nr of arcs * </pre> * * <pre> -M <integer> * Nr of instances * </pre> * * <pre> -C <integer> * Cardinality of the variables * </pre> * * <pre> -S <integer> * Seed for random number generator * </pre> * * <pre> -F <file> * The BIF file to obtain the structure from. * </pre> * <!-- options-end --> * * @author Remco Bouckaert (rrb@xm.co.nz) * @version $Revision: 1.11 $ */public class BayesNetGenerator extends BayesNet { /** the seed value */ int m_nSeed = 1; /** the random number generator */ Random random; /** for serialization */ static final long serialVersionUID = -7462571170596157720L; /** * Constructor for BayesNetGenerator. */ public BayesNetGenerator() { super(); } // c'tor /** * Generate random connected Bayesian network with discrete nodes * having all the same cardinality. * * @throws Exception if something goes wrong */ public void generateRandomNetwork () throws Exception { if (m_otherBayesNet == null) { // generate from scratch Init(m_nNrOfNodes, m_nCardinality); generateRandomNetworkStructure(m_nNrOfNodes, m_nNrOfArcs); generateRandomDistributions(m_nNrOfNodes, m_nCardinality); } else { // read from file, just copy parent sets and distributions m_nNrOfNodes = m_otherBayesNet.getNrOfNodes(); m_ParentSets = m_otherBayesNet.getParentSets(); m_Distributions = m_otherBayesNet.getDistributions(); random = new Random(m_nSeed); // initialize m_Instances FastVector attInfo = new FastVector(m_nNrOfNodes); // generate value strings for (int iNode = 0; iNode < m_nNrOfNodes; iNode++) { int nValues = m_otherBayesNet.getCardinality(iNode); FastVector nomStrings = new FastVector(nValues + 1); for (int iValue = 0; iValue < nValues; iValue++) { nomStrings.addElement(m_otherBayesNet.getNodeValue(iNode, iValue)); } Attribute att = new Attribute(m_otherBayesNet.getNodeName(iNode), nomStrings); attInfo.addElement(att); } m_Instances = new Instances(m_otherBayesNet.getName(), attInfo, 100); m_Instances.setClassIndex(m_nNrOfNodes - 1); } } // GenerateRandomNetwork /** * Init defines a minimal Bayes net with no arcs * @param nNodes number of nodes in the Bayes net * @param nValues number of values each of the nodes can take * @throws Exception if something goes wrong */ public void Init(int nNodes, int nValues) throws Exception { random = new Random(m_nSeed); // initialize structure FastVector attInfo = new FastVector(nNodes); // generate value strings FastVector nomStrings = new FastVector(nValues + 1); for (int iValue = 0; iValue < nValues; iValue++) { nomStrings.addElement("Value" + (iValue + 1)); } for (int iNode = 0; iNode < nNodes; iNode++) { Attribute att = new Attribute("Node" + (iNode + 1), nomStrings); attInfo.addElement(att); } m_Instances = new Instances("RandomNet", attInfo, 100); m_Instances.setClassIndex(nNodes - 1); setUseADTree(false);// m_bInitAsNaiveBayes = false;// m_bMarkovBlanketClassifier = false; initStructure(); // initialize conditional distribution tables m_Distributions = new Estimator[nNodes][1]; for (int iNode = 0; iNode < nNodes; iNode++) { m_Distributions[iNode][0] = new DiscreteEstimatorBayes(nValues, getEstimator().getAlpha()); } } // DefineNodes /** * GenerateRandomNetworkStructure generate random connected Bayesian network * @param nNodes number of nodes in the Bayes net to generate * @param nArcs number of arcs to generate. Must be between nNodes - 1 and nNodes * (nNodes-1) / 2 * @throws Exception if number of arcs is incorrect */ public void generateRandomNetworkStructure(int nNodes, int nArcs) throws Exception { if (nArcs < nNodes - 1) { throw new Exception("Number of arcs should be at least (nNodes - 1) = " + (nNodes - 1) + " instead of " + nArcs); } if (nArcs > nNodes * (nNodes - 1) / 2) { throw new Exception("Number of arcs should be at most nNodes * (nNodes - 1) / 2 = "+ (nNodes * (nNodes - 1) / 2) + " instead of " + nArcs); } if (nArcs == 0) {return;} // deal with patalogical case for nNodes = 1 // first generate tree connecting all nodes generateTree(nNodes); // The tree contains nNodes - 1 arcs, so there are // nArcs - (nNodes-1) to add at random. // All arcs point from lower to higher ordered nodes // so that acyclicity is ensured. for (int iArc = nNodes - 1; iArc < nArcs; iArc++) { boolean bDone = false; while (!bDone) { int nNode1 = random.nextInt(nNodes); int nNode2 = random.nextInt(nNodes); if (nNode1 == nNode2) {nNode2 = (nNode1 + 1) % nNodes;} if (nNode2 < nNode1) {int h = nNode1; nNode1 = nNode2; nNode2 = h;} if (!m_ParentSets[nNode2].contains(nNode1)) { m_ParentSets[nNode2].addParent(nNode1, m_Instances); bDone = true; } } } } // GenerateRandomNetworkStructure /** * GenerateTree creates a tree-like network structure (actually a * forest) by starting with a randomly selected pair of nodes, add * an arc between. Then keep on selecting one of the connected nodes * and one of the unconnected ones and add an arrow between them, * till all nodes are connected. * @param nNodes number of nodes in the Bayes net to generate */ void generateTree(int nNodes) { boolean [] bConnected = new boolean [nNodes]; // start adding an arc at random int nNode1 = random.nextInt(nNodes); int nNode2 = random.nextInt(nNodes); if (nNode1 == nNode2) {nNode2 = (nNode1 + 1) % nNodes;} if (nNode2 < nNode1) {int h = nNode1; nNode1 = nNode2; nNode2 = h;} m_ParentSets[nNode2].addParent(nNode1, m_Instances); bConnected[nNode1] = true; bConnected[nNode2] = true; // Repeatedly, select one of the connected nodes, and one of // the unconnected nodes and add an arc. // All arcs point from lower to higher ordered nodes // so that acyclicity is ensured. for (int iArc = 2; iArc < nNodes; iArc++ ) { int nNode = random.nextInt(nNodes); nNode1 = 0; // one of the connected nodes while (nNode >= 0) { nNode1 = (nNode1 + 1) % nNodes; while (!bConnected[nNode1]) { nNode1 = (nNode1 + 1) % nNodes; } nNode--; } nNode = random.nextInt(nNodes); nNode2 = 0; // one of the unconnected nodes while (nNode >= 0) { nNode2 = (nNode2 + 1) % nNodes; while (bConnected[nNode2]) { nNode2 = (nNode2 + 1) % nNodes; } nNode--; } if (nNode2 < nNode1) {int h = nNode1; nNode1 = nNode2; nNode2 = h;} m_ParentSets[nNode2].addParent(nNode1, m_Instances); bConnected[nNode1] = true; bConnected[nNode2] = true; } } // GenerateTree /** * GenerateRandomDistributions generates discrete conditional distribution tables * for all nodes of a Bayes network once a network structure has been determined. * @param nNodes number of nodes in the Bayes net * @param nValues number of values each of the nodes can take */ void generateRandomDistributions(int nNodes, int nValues) { // Reserve space for CPTs int nMaxParentCardinality = 1; for (int iAttribute = 0; iAttribute < nNodes; iAttribute++) { if (m_ParentSets[iAttribute].getCardinalityOfParents() > nMaxParentCardinality) { nMaxParentCardinality = m_ParentSets[iAttribute].getCardinalityOfParents(); } } // Reserve plenty of memory m_Distributions = new Estimator[m_Instances.numAttributes()][nMaxParentCardinality]; // estimate CPTs for (int iAttribute = 0; iAttribute < nNodes; iAttribute++) { int [] nPs = new int [nValues + 1]; nPs[0] = 0; nPs[nValues] = 1000; for (int iParent = 0; iParent < m_ParentSets[iAttribute].getCardinalityOfParents(); iParent++) { // fill array with random nr's for (int iValue = 1; iValue < nValues; iValue++) { nPs[iValue] = random.nextInt(1000); } // sort for (int iValue = 1; iValue < nValues; iValue++) { for (int iValue2 = iValue + 1; iValue2 < nValues; iValue2++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -