editablebayesnet.java

来自「Weka」· Java 代码 · 共 1,981 行 · 第 1/5 页

JAVA
1,981
字号
package weka.classifiers.bayes.net;/* * 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. *//* * EditableBayesNet.java * */import java.io.Serializable;import java.io.StringReader;import java.util.StringTokenizer;import javax.xml.parsers.DocumentBuilderFactory;import org.w3c.dom.CharacterData;import org.w3c.dom.Document;import org.w3c.dom.Element;import org.w3c.dom.Node;import org.w3c.dom.NodeList;import weka.classifiers.bayes.BayesNet;import weka.classifiers.bayes.net.estimate.DiscreteEstimatorBayes;import weka.core.Attribute;import weka.core.FastVector;import weka.core.Instances;import weka.core.SerializedObject;import weka.estimators.Estimator;import weka.filters.Filter;import weka.filters.unsupervised.attribute.Reorder;/** <!-- globalinfo-start --> * Bayes Network that allows for editing operations on a Bayesian network * with undo/redo facilities. * * <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> -D *  Do not use ADTree data structure * </pre> * * <pre> -B &lt;BIF file&gt; *  BIF file to compare with * </pre> * * <pre> -Q weka.classifiers.bayes.net.search.SearchAlgorithm *  Search algorithm * </pre> * * <pre> -E weka.classifiers.bayes.net.estimate.SimpleEstimator *  Estimator algorithm * </pre> * <!-- options-end --> * * @author Remco Bouckaert (rrb@xm.co.nz) * @version $Revision: 1.1 $ */public class EditableBayesNet extends BayesNet {	/** for serialization */	static final long serialVersionUID = 746037443258735954L;	/** location of nodes, used for graph drawing * */	protected FastVector m_nPositionX;	protected FastVector m_nPositionY;	/** marginal distributions * */	protected FastVector m_fMarginP;	/** evidence values, used for evidence propagation * */	protected FastVector m_nEvidence;	/** standard constructor * */	public EditableBayesNet() {		super();		m_nEvidence = new FastVector(0);		m_fMarginP = new FastVector(0);		m_nPositionX = new FastVector();		m_nPositionY = new FastVector();		clearUndoStack();	} // c'tor	/** constructor, creates empty network with nodes based on the attributes in a data set */	public EditableBayesNet(Instances instances) {		try {			if (instances.classIndex() < 0) {				instances.setClassIndex(instances.numAttributes() - 1);			}			m_Instances = normalizeDataSet(instances);		} catch (Exception e) {			e.printStackTrace();		}		int nNodes = getNrOfNodes();		m_ParentSets = new ParentSet[nNodes];		for (int i = 0; i < nNodes; i++) {			m_ParentSets[i] = new ParentSet();		}		m_Distributions = new Estimator[nNodes][];		for (int iNode = 0; iNode < nNodes; iNode++) {			m_Distributions[iNode] = new Estimator[1];			m_Distributions[iNode][0] = new DiscreteEstimatorBayes(getCardinality(iNode), 0.5);		}		m_nEvidence = new FastVector(nNodes);		for (int i = 0; i < nNodes; i++) {			m_nEvidence.addElement(-1);		}		m_fMarginP = new FastVector(nNodes);		for (int i = 0; i < nNodes; i++) {			double[] P = new double[getCardinality(i)];			m_fMarginP.addElement(P);		}		m_nPositionX = new FastVector(nNodes);		m_nPositionY = new FastVector(nNodes);		for (int iNode = 0; iNode < nNodes; iNode++) {			m_nPositionX.addElement(iNode%10 * 50);			m_nPositionY.addElement(((int)(iNode/10)) * 50);		}	} // c'tor	/** constructor, copies Bayesian network structure from a Bayesian network	 * encapsulated in a BIFReader	 */	public EditableBayesNet(BIFReader other) {		m_Instances = other.m_Instances;		m_ParentSets = other.getParentSets();		m_Distributions = other.getDistributions();		int nNodes = getNrOfNodes();		m_nPositionX = new FastVector(nNodes);		m_nPositionY = new FastVector(nNodes);		for (int i = 0; i < nNodes; i++) {			m_nPositionX.addElement(other.m_nPositionX[i]);			m_nPositionY.addElement(other.m_nPositionY[i]);		}		m_nEvidence = new FastVector(nNodes);		for (int i = 0; i < nNodes; i++) {			m_nEvidence.addElement(-1);		}		m_fMarginP = new FastVector(nNodes);		for (int i = 0; i < nNodes; i++) {			double[] P = new double[getCardinality(i)];			m_fMarginP.addElement(P);		}		clearUndoStack();	} // c'tor	/**	 * constructor that potentially initializes instances as well	 *	 * @param bSetInstances	 *            flag indicating whether to initialize instances or not	 */	public EditableBayesNet(boolean bSetInstances) {		super();		m_nEvidence = new FastVector(0);		m_fMarginP = new FastVector(0);		m_nPositionX = new FastVector();		m_nPositionY = new FastVector();		clearUndoStack();		if (bSetInstances) {			m_Instances = new Instances("New Network", new FastVector(0), 0);		}	} // c'tor	/** Assuming a network structure is defined and we want to learn from data,	 * the data set must be put if correct order first and possibly discretized/missing	 * values filled in before proceeding to CPT learning.	 * @param instances data set to learn from	 * @exception when data sets are not compatible, e.g., a variable is missing	 * or a variable has different nr of values.	 */	public void setData(Instances instances) throws Exception {		// sync order of variables		int [] order = new int [getNrOfNodes()];		for (int iNode = 0; iNode < getNrOfNodes(); iNode++) {			String sName = getNodeName(iNode);			int nNode = 0;			while (nNode < getNrOfNodes() && !sName.equals(instances.attribute(nNode).name())) {				nNode++;			}			if (nNode >= getNrOfNodes()) {				throw new Exception("Cannot find node named [[[" + sName + "]]] in the data");			}			order[iNode] = nNode;		}		Reorder reorderFilter = new Reorder();		reorderFilter.setAttributeIndicesArray(order);		reorderFilter.setInputFormat(instances);		instances = Filter.useFilter(instances, reorderFilter);		// filter using discretization/missing values filter		Instances newInstances = new Instances(m_Instances, 0);		if (m_DiscretizeFilter == null && m_MissingValuesFilter == null) {			newInstances = normalizeDataSet(instances);		} else {			for (int iInstance = 0; iInstance < instances.numInstances(); iInstance++) {				newInstances.add(normalizeInstance(instances.instance(iInstance)));			}		}		//sanity check		for (int iNode = 0; iNode < getNrOfNodes(); iNode++) {			if (newInstances.attribute(iNode).numValues() != getCardinality(iNode)) {				throw new Exception("Number of values of node [[[" + getNodeName(iNode) + "]]] differs in (discretized) dataset." );			}		}		// if we got this far, all is ok with the data set and		// we can replace data set of Bayes net		m_Instances = newInstances;	} // setData	/** returns index of node with given name, or -1 if no such node exists	 * @param sNodeName name of the node to get index for	 */	public int getNode2(String sNodeName) {		int iNode = 0;		while (iNode < m_Instances.numAttributes()) {			if (m_Instances.attribute(iNode).name().equals(sNodeName)) {				return iNode;			}			iNode++;		}		return -1;	} // getNode2	/** returns index of node with given name. Throws exception if no such node exists	 * @param sNodeName name of the node to get index for	 */	public int getNode(String sNodeName) throws Exception {		int iNode = getNode2(sNodeName);		if (iNode < 0) {			throw new Exception("Could not find node [[" + sNodeName + "]]");		}		return iNode;	} // getNode	/**	 * Add new node to the network, initializing instances, parentsets,	 * distributions. Used for manual manipulation of the Bayesian network.	 *	 * @param sName	 *            name of the node. If the name already exists, an x is appended	 *            to the name	 * @param nCardinality	 *            number of values for this node	 * @throws Exception	 */	public void addNode(String sName, int nCardinality) throws Exception {		addNode(sName, nCardinality, 100 + getNrOfNodes() * 10, 100 + getNrOfNodes() * 10);	} // addNode	/** Add node to network at a given position, initializing instances, parentsets,	 * distributions. Used for manual manipulation of the Bayesian network.	 *	 * @param sName	 *            name of the node. If the name already exists, an x is appended	 *            to the name	 * @param nCardinality	 *            number of values for this node	 * @param nPosX x-coordiate of the position to place this node	 * @param nPosY y-coordiate of the position to place this node	 * @throws Exception	 */	public void addNode(String sName, int nCardinality, int nPosX, int nPosY) throws Exception {		if (getNode2(sName) >= 0) {			addNode(sName + "x", nCardinality);			return ;		}		// update instances		FastVector values = new FastVector(nCardinality);		for (int iValue = 0; iValue < nCardinality; iValue++) {			values.addElement("Value" + (iValue + 1));		}		Attribute att = new Attribute(sName, values);		m_Instances.insertAttributeAt(att, m_Instances.numAttributes());		int nAtts = m_Instances.numAttributes();		// update parentsets		ParentSet[] parentSets = new ParentSet[nAtts];		for (int iParentSet = 0; iParentSet < nAtts - 1; iParentSet++) {			parentSets[iParentSet] = m_ParentSets[iParentSet];		}		parentSets[nAtts - 1] = new ParentSet();		m_ParentSets = parentSets;		// update distributions		Estimator[][] distributions = new Estimator[nAtts][];		for (int iNode = 0; iNode < nAtts - 1; iNode++) {			distributions[iNode] = m_Distributions[iNode];		}		distributions[nAtts - 1] = new Estimator[1];		distributions[nAtts - 1][0] = new DiscreteEstimatorBayes(nCardinality, 0.5);		m_Distributions = distributions;		// update positions		m_nPositionX.addElement(nPosX);		m_nPositionY.addElement(nPosY);		// update evidence & margins		m_nEvidence.addElement(-1);		double[] fMarginP = new double[nCardinality];		for (int iValue = 0; iValue < nCardinality; iValue++) {			fMarginP[iValue] = 1.0 / nCardinality;		}		m_fMarginP.addElement(fMarginP);		// update undo stack		if (m_bNeedsUndoAction) {			addUndoAction(new AddNodeAction(sName, nCardinality, nPosX, nPosY));		}	} // addNode	/**	 * Delete node from the network, updating instances, parentsets,	 * distributions Conditional distributions are condensed by taking the	 * values for the target node to be its first value. Used for manual	 * manipulation of the Bayesian network.	 *	 * @param sName	 *            name of the node. If the name does not exists an exception is	 *            thrown	 * @throws Exception	 */	public void deleteNode(String sName) throws Exception {		int nTargetNode = getNode(sName);		deleteNode(nTargetNode);	} // deleteNode	/**	 * Delete node from the network, updating instances, parentsets,	 * distributions Conditional distributions are condensed by taking the	 * values for the target node to be its first value. Used for manual	 * manipulation of the Bayesian network.	 *	 * @param nTargetNode	 *            index of the node to delete.	 * @throws Exception	 */	public void deleteNode(int nTargetNode) throws Exception {		// update undo stack		if (m_bNeedsUndoAction) {			addUndoAction(new DeleteNodeAction(nTargetNode));		}		int nAtts = m_Instances.numAttributes() - 1;		int nTargetCard = m_Instances.attribute(nTargetNode).numValues();		// update distributions		Estimator[][] distributions = new Estimator[nAtts][];		for (int iNode = 0; iNode < nAtts; iNode++) {			int iNode2 = iNode;			if (iNode >= nTargetNode) {				iNode2++;			}			Estimator[] distribution = m_Distributions[iNode2];			if (m_ParentSets[iNode2].contains(nTargetNode)) {				// condense distribution, use values for targetnode = 0				int nParentCard = m_ParentSets[iNode2].getCardinalityOfParents();				nParentCard = nParentCard / nTargetCard;				Estimator[] distribution2 = new Estimator[nParentCard];				for (int iParent = 0; iParent < nParentCard; iParent++) {					distribution2[iParent] = distribution[iParent];				}				distribution = distribution2;			}			distributions[iNode] = distribution;		}		m_Distributions = distributions;		// update parentsets		ParentSet[] parentSets = new ParentSet[nAtts];		for (int iParentSet = 0; iParentSet < nAtts; iParentSet++) {			int iParentSet2 = iParentSet;			if (iParentSet >= nTargetNode) {				iParentSet2++;			}			ParentSet parentset = m_ParentSets[iParentSet2];

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?