📄 userclassifier.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. *//* * UserClassifier.java * Copyright (C) 1999 Malcolm Ware * */package weka.classifiers.trees;import weka.classifiers.Classifier;import weka.classifiers.functions.LinearRegression;import weka.core.Capabilities;import weka.core.Drawable;import weka.core.FastVector;import weka.core.Instance;import weka.core.Instances;import weka.core.TechnicalInformation;import weka.core.TechnicalInformationHandler;import weka.core.Utils;import weka.core.Capabilities.Capability;import weka.core.TechnicalInformation.Field;import weka.core.TechnicalInformation.Type;import weka.filters.Filter;import weka.filters.unsupervised.attribute.Remove;import weka.gui.GenericObjectEditor;import weka.gui.PropertyDialog;import weka.gui.treevisualizer.PlaceNode1;import weka.gui.treevisualizer.PlaceNode2;import weka.gui.treevisualizer.TreeDisplayEvent;import weka.gui.treevisualizer.TreeDisplayListener;import weka.gui.treevisualizer.TreeVisualizer;import weka.gui.visualize.VisualizePanel;import weka.gui.visualize.VisualizePanelEvent;import weka.gui.visualize.VisualizePanelListener;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;import java.io.Serializable;import javax.swing.JFrame;import javax.swing.JOptionPane;import javax.swing.JTabbedPane;/** <!-- globalinfo-start --> * Interactively classify through visual means. You are Presented with a scatter graph of the data against two user selectable attributes, as well as a view of the decision tree. You can create binary splits by creating polygons around data plotted on the scatter graph, as well as by allowing another classifier to take over at points in the decision tree should you see fit.<br/> * <br/> * For more information see:<br/> * <br/> * Malcolm Ware, Eibe Frank, Geoffrey Holmes, Mark Hall, Ian H. Witten (2001). Interactive machine learning: letting users build classifiers. Int. J. Hum.-Comput. Stud.. 55(3):281-292. * <p/> <!-- globalinfo-end --> * <!-- technical-bibtex-start --> * BibTeX: * <pre> * @article{Ware2001, * author = {Malcolm Ware and Eibe Frank and Geoffrey Holmes and Mark Hall and Ian H. Witten}, * journal = {Int. J. Hum.-Comput. Stud.}, * number = {3}, * pages = {281-292}, * title = {Interactive machine learning: letting users build classifiers}, * volume = {55}, * year = {2001}, * PS = {http://www.cs.waikato.ac.nz/~ml/publications/2000/00MW-etal-Interactive-ML.ps} * } * </pre> * <p/> <!-- technical-bibtex-end --> * <!-- options-start --> * Valid options are: <p/> * * <pre> -D * If set, classifier is run in debug mode and * may output additional info to the console</pre> * <!-- options-end --> * * @author Malcolm Ware (mfw4@cs.waikato.ac.nz) * @version $Revision: 1.26 $ */public class UserClassifier extends Classifier implements Drawable, TreeDisplayListener, VisualizePanelListener, TechnicalInformationHandler { /** for serialization */ static final long serialVersionUID = 6483901103562809843L; /** I am not sure if these are strictly adhered to in visualizepanel * so I am making them private to avoid confusion, (note that they will * be correct in this class, VLINE and HLINE aren't used). */ private static final int LEAF = 0; private static final int RECTANGLE = 1; private static final int POLYGON = 2; private static final int POLYLINE = 3; private static final int VLINE = 5; private static final int HLINE =6; /** The tree display panel. */ private transient TreeVisualizer m_tView = null; /** The instances display. */ private transient VisualizePanel m_iView = null; /** Two references to the structure of the decision tree. */ private TreeClass m_top, m_focus; /** The next number that can be used as a unique id for a node. */ private int m_nextId; /** The tabbed window for the tree and instances view. */ private transient JTabbedPane m_reps; /** The window. */ private transient JFrame m_mainWin; /** The status of whether there is a decision tree ready or not. */ private boolean m_built=false; /** A list of other m_classifiers. */ private GenericObjectEditor m_classifiers; /** A window for selecting other classifiers. */ private PropertyDialog m_propertyDialog; /** Register the property editors we need */ static { GenericObjectEditor.registerEditors(); } /** * Main method for testing this class. * * @param argv should contain command line options (see setOptions) */ public static void main(String [] argv) { runClassifier(new UserClassifier(), argv); } /** * @return a string that represents this objects tree. */ public String toString() { if (!m_built) { return "Tree Not Built"; } StringBuffer text = new StringBuffer(); try { m_top.toString(0, text); m_top.objectStrings(text); } catch(Exception e) { System.out.println("error: " + e.getMessage()); } return text.toString(); } /** * Receives user choices from the tree view, and then deals with these * choices. * @param e The choice. */ public void userCommand(TreeDisplayEvent e) { if (m_propertyDialog != null) { m_propertyDialog.dispose(); m_propertyDialog = null; } try { if (m_iView == null || m_tView == null) { //throw exception } if (e.getCommand() == TreeDisplayEvent.NO_COMMAND) { //do nothing } else if (e.getCommand() == TreeDisplayEvent.ADD_CHILDREN) { //highlight the particular node and reset the vis panel if (m_top == null) { //this shouldn't happen , someone elses code would //have to have added a trigger to this listener. System.out.println("Error : Received event from a TreeDisplayer" + " that is unknown to the classifier."); } else { m_tView.setHighlight(e.getID()); /*if (m_iView == null) { m_iView = new VisualizePanel(this); m_iView.setSize(400, 300); }*/ m_focus = m_top.getNode(e.getID()); m_iView.setInstances(m_focus.m_training); if (m_focus.m_attrib1 >= 0) { m_iView.setXIndex(m_focus.m_attrib1); } if (m_focus.m_attrib2 >= 0) { m_iView.setYIndex(m_focus.m_attrib2); } m_iView.setColourIndex(m_focus.m_training.classIndex()); if (((Double)((FastVector)m_focus.m_ranges.elementAt(0)). elementAt(0)).intValue() != LEAF) { m_iView.setShapes(m_focus.m_ranges); } //m_iView.setSIndex(2); } } else if (e.getCommand() == TreeDisplayEvent.REMOVE_CHILDREN) { /*if (m_iView == null) { m_iView = new VisualizePanel(this); m_iView.setSize(400, 300); }*/ m_focus = m_top.getNode(e.getID()); m_iView.setInstances(m_focus.m_training); if (m_focus.m_attrib1 >= 0) { m_iView.setXIndex(m_focus.m_attrib1); } if (m_focus.m_attrib2 >= 0) { m_iView.setYIndex(m_focus.m_attrib2); } m_iView.setColourIndex(m_focus.m_training.classIndex()); if (((Double)((FastVector)m_focus.m_ranges.elementAt(0)). elementAt(0)).intValue() != LEAF) { m_iView.setShapes(m_focus.m_ranges); } //m_iView.setSIndex(2); //now to remove all the stuff m_focus.m_set1 = null; m_focus.m_set2 = null; m_focus.setInfo(m_focus.m_attrib1, m_focus.m_attrib2, null); //tree_frame.getContentPane().removeAll(); m_tView = new TreeVisualizer(this, graph(), new PlaceNode2()); //tree_frame.getContentPane().add(m_tView); m_reps.setComponentAt(0, m_tView); //tree_frame.getContentPane().doLayout(); m_tView.setHighlight(m_focus.m_identity); } else if (e.getCommand() == TreeDisplayEvent.CLASSIFY_CHILD) { /*if (m_iView == null) { m_iView = new VisualizePanel(this); m_iView.setSize(400, 300); }*/ m_focus = m_top.getNode(e.getID()); m_iView.setInstances(m_focus.m_training); if (m_focus.m_attrib1 >= 0) { m_iView.setXIndex(m_focus.m_attrib1); } if (m_focus.m_attrib2 >= 0) { m_iView.setYIndex(m_focus.m_attrib2); } m_iView.setColourIndex(m_focus.m_training.classIndex()); if (((Double)((FastVector)m_focus.m_ranges.elementAt(0)). elementAt(0)).intValue() != LEAF) { m_iView.setShapes(m_focus.m_ranges); } m_propertyDialog = new PropertyDialog(m_classifiers, m_mainWin.getLocationOnScreen().x, m_mainWin.getLocationOnScreen().y); //note property dialog may change all the time //but the generic editor which has the listeners does not //so at the construction of the editor is when I am going to add //the listeners. //focus.setClassifier(new IB1()); //tree_frame.getContentPane().removeAll(); //////m_tView = new Displayer(this, graph(), new PlaceNode2()); //tree_frame.getContentPane().add(m_tView); //tree_frame.getContentPane().doLayout(); /////////////reps.setComponentAt(0, m_tView); m_tView.setHighlight(m_focus.m_identity); } /*else if (e.getCommand() == e.SEND_INSTANCES) { TreeClass source = m_top.getNode(e.getID()); m_iView.setExtInstances(source.m_training); }*/ else if (e.getCommand() == TreeDisplayEvent.ACCEPT) { int well = JOptionPane.showConfirmDialog(m_mainWin, "Are You Sure...\n" + "Click Yes To Accept The" + " Tree" + "\n Click No To Return", "Accept Tree", JOptionPane.YES_NO_OPTION); if (well == 0) { m_mainWin.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); m_mainWin.dispose(); blocker(false); //release the thread waiting at blocker to //continue. } } } catch(Exception er) { System.out.println("Error : " + er); System.out.println("Part of user input so had to catch here"); er.printStackTrace(); } } /** * This receives shapes from the data view. * It then enters these shapes into the decision tree structure. * @param e Contains the shapes, and other info. */ public void userDataEvent(VisualizePanelEvent e) { if (m_propertyDialog != null) { m_propertyDialog.dispose(); m_propertyDialog = null; } try { if (m_focus != null) { double wdom = e.getInstances1().numInstances() + e.getInstances2().numInstances(); if (wdom == 0) { wdom = 1; } TreeClass tmp = m_focus; m_focus.m_set1 = new TreeClass(null, e.getAttribute1(), e.getAttribute2(), m_nextId, e.getInstances1().numInstances() / wdom, e.getInstances1(), m_focus); m_focus.m_set2 = new TreeClass(null, e.getAttribute1(), e.getAttribute2(), m_nextId, e.getInstances2().numInstances() / wdom, e.getInstances2(), m_focus); //this needs the other instance //tree_frame.getContentPane().removeAll(); m_focus.setInfo(e.getAttribute1(), e.getAttribute2(), e.getValues()); //System.out.println(graph()); m_tView = new TreeVisualizer(this, graph(), new PlaceNode2()); //tree_frame.getContentPane().add(m_tView); //tree_frame.getContentPane().doLayout(); m_reps.setComponentAt(0, m_tView); m_focus = m_focus.m_set2; m_tView.setHighlight(m_focus.m_identity); m_iView.setInstances(m_focus.m_training); if (tmp.m_attrib1 >= 0) { m_iView.setXIndex(tmp.m_attrib1); } if (tmp.m_attrib2 >= 0) { m_iView.setYIndex(tmp.m_attrib2); } m_iView.setColourIndex(m_focus.m_training.classIndex()); if (((Double)((FastVector)m_focus.m_ranges.elementAt(0)). elementAt(0)).intValue() != LEAF) { m_iView.setShapes(m_focus.m_ranges); } //m_iView.setSIndex(2); } else { System.out.println("Somehow the focus is null"); } } catch(Exception er) { System.out.println("Error : " + er); System.out.println("Part of user input so had to catch here"); //er.printStackTrace(); } } /** * Constructor */ public UserClassifier() { //do nothing here except set alot of variables to default values m_top = null; m_tView = null; m_iView = null; m_nextId = 0; } /** * Returns the type of graph this classifier * represents. * @return Drawable.TREE */ public int graphType() { return Drawable.TREE; } /** * @return A string formatted with a dotty representation of the decision * tree. * @throws Exception if String can't be built properly. */ public String graph() throws Exception { //create a dotty rep of the tree from here StringBuffer text = new StringBuffer(); text.append("digraph UserClassifierTree {\n" + "node [fontsize=10]\n" + "edge [fontsize=10 style=bold]\n"); m_top.toDotty(text); return text.toString() +"}\n"; } /** * A function used to stop the code that called buildclassifier * from continuing on before the user has finished the decision tree. * @param tf True to stop the thread, False to release the thread that is * waiting there (if one). */ private synchronized void blocker(boolean tf) { if (tf) { try { wait(); } catch(InterruptedException e) { } } else { notifyAll(); } //System.out.println("out"); } /** * This will return a string describing the classifier. * @return The string. */ public String globalInfo() { return "Interactively classify through visual means." + " You are Presented with a scatter graph of the data against two user" + " selectable attributes, as well as a view of the decision tree." + " You can create binary splits by creating polygons around data" + " plotted on the scatter graph, as well as by allowing another" + " classifier to take over at points in the decision tree should you" + " see fit.\n\n" + "For more information see:\n\n" + getTechnicalInformation().toString(); } /** * Returns an instance of a TechnicalInformation object, containing * detailed information about the technical background of this class, * e.g., paper reference or book this class is based on. * * @return the technical information about this class */ public TechnicalInformation getTechnicalInformation() { TechnicalInformation result; result = new TechnicalInformation(Type.ARTICLE); result.setValue(Field.AUTHOR, "Malcolm Ware and Eibe Frank and Geoffrey Holmes and Mark Hall and Ian H. Witten"); result.setValue(Field.YEAR, "2001"); result.setValue(Field.TITLE, "Interactive machine learning: letting users build classifiers"); result.setValue(Field.JOURNAL, "Int. J. Hum.-Comput. Stud."); result.setValue(Field.VOLUME, "55"); result.setValue(Field.NUMBER, "3"); result.setValue(Field.PAGES, "281-292"); result.setValue(Field.PS, "http://www.cs.waikato.ac.nz/~ml/publications/2000/00MW-etal-Interactive-ML.ps");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -