📄 userclassifier.java
字号:
return result; } /** * Returns default capabilities of the classifier. * * @return the capabilities of this classifier */ public Capabilities getCapabilities() { Capabilities result = super.getCapabilities(); // attributes result.enable(Capability.NOMINAL_ATTRIBUTES); result.enable(Capability.NUMERIC_ATTRIBUTES); result.enable(Capability.DATE_ATTRIBUTES); result.enable(Capability.STRING_ATTRIBUTES); result.enable(Capability.RELATIONAL_ATTRIBUTES); result.enable(Capability.MISSING_VALUES); // class result.enable(Capability.NOMINAL_CLASS); result.enable(Capability.NUMERIC_CLASS); result.enable(Capability.DATE_CLASS); result.enable(Capability.MISSING_CLASS_VALUES); // instances result.setMinimumNumberInstances(0); return result; } /** * Call this function to build a decision tree for the training * data provided. * @param i The training data. * @throws Exception if can't build classification properly. */ public void buildClassifier(Instances i) throws Exception { // can classifier handle the data? getCapabilities().testWithFail(i); // remove instances with missing class i = new Instances(i); i.deleteWithMissingClass(); //construct a visualizer //construct a tree displayer and feed both then do nothing //note that I will display at the bottom of each split how many //fall into each catagory m_classifiers = new GenericObjectEditor(true); m_classifiers.setClassType(Classifier.class); m_classifiers.setValue(new weka.classifiers.rules.ZeroR()); ((GenericObjectEditor.GOEPanel)m_classifiers.getCustomEditor()) .addOkListener(new ActionListener() { public void actionPerformed(ActionEvent e) { //I want to use the focus variable but to trust it I need //to kill the window if anything gets changed by either //editor try { m_focus.m_set1 = null; m_focus.m_set2 = null; m_focus.setInfo(m_focus.m_attrib1, m_focus.m_attrib2, null); m_focus.setClassifier((Classifier)m_classifiers.getValue()); m_classifiers = new GenericObjectEditor(); m_classifiers.setClassType(Classifier.class); m_classifiers.setValue(new weka.classifiers.rules.ZeroR()); ((GenericObjectEditor.GOEPanel)m_classifiers.getCustomEditor()) .addOkListener(this); m_tView = new TreeVisualizer(UserClassifier.this, graph(), new PlaceNode2()); m_tView.setHighlight(m_focus.m_identity); m_reps.setComponentAt(0, m_tView); m_iView.setShapes(null); } catch(Exception er) { System.out.println("Error : " + er); System.out.println("Part of user input so had to catch here"); } } }); m_built = false; m_mainWin = new JFrame(); m_mainWin.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { 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); blocker(false); } else { m_mainWin.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); } } }); m_reps = new JTabbedPane(); m_mainWin.getContentPane().add(m_reps); //make a backup of the instances so that any changes don't go past here. Instances te = new Instances(i, i.numInstances()); for (int noa = 0; noa < i.numInstances(); noa++) { te.add(i.instance(noa)); } te.deleteWithMissingClass(); //remove all instances with a missing class //from training m_top = new TreeClass(null, 0, 0, m_nextId, 1, te, null); m_focus = m_top; //System.out.println(graph()); m_tView = new TreeVisualizer(this, graph(), new PlaceNode1()); m_reps.add("Tree Visualizer", m_tView); //tree_frame = new JFrame(); //tree_frame.getContentPane().add(m_tView); //tree_frame.setSize(800,600); //tree_frame.setVisible(true); m_tView.setHighlight(m_top.m_identity); m_iView = new VisualizePanel(this); //m_iView.setSize(400, 300); m_iView.setInstances(m_top.m_training); m_iView.setColourIndex(te.classIndex()); //vis_frame = new JFrame(); //vis_frame.getContentPane().add(m_iView); //vis_frame.setSize(400, 300); //vis_frame.setVisible(true); m_reps.add("Data Visualizer", m_iView); m_mainWin.setSize(560, 420); m_mainWin.setVisible(true); blocker(true); //a call so that the main thread of //execution has to wait for the all clear message from the user. //so that it can be garbage if (m_propertyDialog != null) { m_propertyDialog.dispose(); m_propertyDialog = null; } //collected m_classifiers = null; m_built = true; } /** * Call this function to get a double array filled with the probability * of how likely each class type is the class of the instance. * @param i The instance to classify. * @return A double array filled with the probalities of each class type. * @throws Exception if can't classify instance. */ public double[] distributionForInstance(Instance i) throws Exception { if (!m_built) { return null; } double[] res = m_top.calcClassType(i); if (m_top.m_training.classAttribute().isNumeric()) { return res; } double most_likely = 0, highest = -1; double count = 0; for (int noa = 0; noa < m_top.m_training.numClasses(); noa++) { count += res[noa]; if (res[noa] > highest) { most_likely = noa; highest = res[noa]; } } if (count <= 0) { //not sure how this happened. return null; } for (int noa = 0; noa < m_top.m_training.numClasses(); noa++) { res[noa] = res[noa] / count; } //System.out.println("ret"); return res; } /** * Inner class used to represent the actual decision tree structure and data. */ private class TreeClass implements Serializable { /** for serialization */ static final long serialVersionUID = 595663560871347434L; /** * This contains the info for the coords of the shape converted * to attrib coords, * for polygon the first attrib is the number of points, * This is not more object oriented because that would * be over kill. */ public FastVector m_ranges; /** the first attribute */ public int m_attrib1; /** the second attribute */ public int m_attrib2; public TreeClass m_set1; public TreeClass m_set2; /** the parent */ public TreeClass m_parent; /** A string to uniquely identify this node. */ public String m_identity; /** the weight of this node */ public double m_weight; /** the training instances for this node */ public Instances m_training; /** Used instead of the standard leaf if one exists. */ public Classifier m_classObject; /** Used on the instances while classifying if one exists. */ public Filter m_filter; /** * Constructs a TreeClass node with all the important information. * @param r A FastVector containing the shapes, null if it's a leaf node. * @param a1 The first attribute. * @param a2 The second attribute. * @param id The unique id number for this node. * @param w The weight of this node. * @param i The instances that make it to this node from the training data. * @param p the parent * @throws Exception if can't use 'i' properly. */ public TreeClass(FastVector r, int a1, int a2, int id, double w, Instances i, TreeClass p) throws Exception { m_set1 = null; m_set2 = null; m_ranges = r; m_classObject = null; m_filter = null; m_training = i; m_attrib1 = a1; m_attrib2 = a2; m_identity = "N" + String.valueOf(id); m_weight = w; m_parent = p; m_nextId++; if (m_ranges == null) { setLeaf(); //this will fill the ranges array with the //number of times each class type occurs for the instances. /*m_ranges = new FastVector(1); m_ranges.addElement(new FastVector(i.numClasses() + 1)); FastVector tmp = (FastVector)m_ranges.elementAt(0); tmp.addElement(new Double(0)); for (int noa = 0; noa < i.numClasses(); noa++) { tmp.addElement(new Double(0)); } for (int noa = 0; noa < i.numInstances(); noa++) { tmp.setElementAt(new Double(((Double)tmp.elementAt ((int)i.instance(noa). classValue() + 1)).doubleValue() + i.instance(noa).weight()), (int)i.instance(noa).classValue() + 1); //this gets the current class value and alters it and replaces it }*/ } } /** * Call this to set an alternate classifier For this node. * @param c The alternative classifier to use. * @throws Exception if alternate classifier can't build classification. */ public void setClassifier(Classifier c) throws Exception { m_classObject = c; m_classObject.buildClassifier(m_training); } /** * Call this to set this node with different information to what * it was created with. * @param at1 The first attribute. * @param at2 The second attribute. * @param ar The shapes at this node, null if leaf node, or * alternate classifier. * @throws Exception if leaf node and cant't create leaf info. */ public void setInfo(int at1, int at2, FastVector ar) throws Exception { m_classObject = null; m_filter = null; m_attrib1 = at1; m_attrib2 = at2; m_ranges = ar; //FastVector tmp; if (m_ranges == null) { setLeaf(); /* //this will fill the ranges array with the number of times //each class type occurs for the instances. if (m_training != null) { m_ranges = new FastVector(1); m_ranges.addElement(new FastVector(m_training.numClasses() + 1)); tmp = (FastVector)m_ranges.elementAt(0); tmp.addElement(new Double(0)); for (int noa = 0; noa < m_training.numClasses(); noa++) { tmp.addElement(new Double(0)); } for (int noa = 0; noa < m_training.numInstances(); noa++) { tmp.setElementAt(new Double(((Double)tmp.elementAt ((int)m_training.instance(noa). classValue() + 1)).doubleValue() + m_training.instance(noa).weight()), (int)m_training.instance(noa).classValue() + 1); //this gets the current class val and alters it and replaces it } }*/ } } /** * This sets up the informtion about this node such as the s.d or the * number of each class. * @throws Exception if problem with training instances. */ private void setLeaf() throws Exception { //this will fill the ranges array with the number of times //each class type occurs for the instances. //System.out.println("ihere"); if (m_training != null ) { if (m_training.classAttribute().isNominal()) { FastVector tmp; //System.out.println("ehlpe"); m_ranges = new FastVector(1); m_ranges.addElement(new FastVector(m_training.numClasses() + 1)); tmp = (FastVector)m_ranges.elementAt(0); tmp.addElement(new Double(0)); for (int noa = 0; noa < m_training.numClasses(); noa++) { tmp.addElement(new Double(0)); } for (int noa = 0; noa < m_training.numInstances(); noa++) { tmp.setElementAt(new Double(((Double)tmp.elementAt ((int)m_training.instance(noa). classValue() + 1)).doubleValue() + m_training.instance(noa).weight()), (int)m_training.instance(noa).classValue() + 1); //this gets the current class val and alters it and replaces it } } else { //then calc the standard deviation. m_ranges = new FastVector(1); double t1 = 0; for (int noa = 0; noa < m_training.numInstances(); noa++) { t1 += m_training.instance(noa).classValue(); } if (m_training.numInstances() != 0) { t1 /= m_training.numInstances(); } double t2 = 0; for (int noa = 0; noa < m_training.numInstances(); noa++) { t2 += Math.pow(m_training.instance(noa).classValue() - t1, 2); } FastVector tmp; if (m_training.numInstances() != 0) { t1 = Math.sqrt(t2 / m_training.numInstances()); m_ranges.addElement(new FastVector(2)); tmp = (FastVector)m_ranges.elementAt(0); tmp.addElement(new Double(0)); tmp.addElement(new Double(t1)); } else { m_ranges.addElement(new FastVector(2)); tmp = (FastVector)m_ranges.elementAt(0); tmp.addElement(new Double(0)); tmp.addElement(new Double(Double.NaN)); } } } } /** * This will recursively go through the tree and return inside the * array the weightings of each of the class types * for this instance. Note that this function returns an otherwise * unreferenced double array so there are no worry's about * making changes. * * @param i The instance to test * @return A double array containing the results. * @throws Exception if can't use instance i properly. */ public double[] calcClassType(Instance i) throws Exception { //note that it will be the same calcs for both numeric and nominal //attrib types. //note the weightings for returning stuff will need to be modified //to work properly but will do for now. double x = 0, y = 0; if (m_attrib1 >= 0) { x = i.value(m_attrib1); } if (m_attrib2 >= 0) { y = i.value(m_attrib2); } double[] rt; if (m_training.classAttribute().isNominal()) { rt = new double[m_training.numClasses()]; } else { rt = new double[1]; } FastVector tmp; if (m_classObject != null) { //then use the classifier. if (m_training.classAttribute().isNominal()) { rt[(int)m_classObject.classifyInstance(i)] = 1; } else { if (m_filter != null) { m_filter.input(i); rt[0] = m_classObject.classifyInstance(m_filter.output()); } else { rt[0] = m_classObject.classifyInstance(i); } } //System.out.println("j48"); return rt; } else if (((Double)((FastVector)m_ranges.elementAt(0)). elementAt(0)).intValue() == LEAF) { //System.out.println("leaf"); //then this is a leaf //rt = new double[m_training.numClasses()]; if (m_training.classAttribute().isNumeric()) { setLinear(); m_filter.input(i); rt[0] = m_classObject.classifyInstance(m_filter.output()); return rt; } int totaler = 0; tmp = (FastVector)m_ranges.elementAt(0); for (int noa = 0; noa < m_training.numClasses();noa++) { rt[noa] = ((Double)tmp.elementAt(noa + 1)).doubleValue(); totaler += rt[noa]; } for (int noa = 0; noa < m_training.numClasses(); noa++) { rt[noa] = rt[noa] / totaler; } return rt; } for (int noa = 0; noa < m_ranges.size(); noa++) { tmp = (FastVector)m_ranges.elementAt(noa); if (((Double)tmp.elementAt(0)).intValue() == VLINE && !Instance.isMissingValue(x)) { } else if (((Double)tmp.elementAt(0)).intValue()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -