📄 userclassifier.java
字号:
//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.
* @exception 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 {
/**
* 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;
public int m_attrib1;
public int m_attrib2;
public TreeClass m_set1;
public TreeClass m_set2;
public TreeClass m_parent;
/** A string to uniquely identify this node. */
public String m_identity;
public double m_weight;
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.
* @exception 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.
* @exception 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 a1 The first attribute.
* @param a2 The second attribute.
* @param ar The shapes at this node, null if leaf node, or
* alternate classifier.
* @exception 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.
* @exception 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.
* @exception 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 && !i.isMissingValue(x)) {
}
else if (((Double)tmp.elementAt(0)).intValue()
== HLINE && !i.isMissingValue(y)) {
}
else if (i.isMissingValue(x) || i.isMissingValue(y)) {
//System.out.println("miss");
//then go down both branches using their weights
rt = m_set1.calcClassType(i);
double[] tem = m_set2.calcClassType(i);
if (m_training.classAttribute().isNominal()) {
for (int nob = 0; nob < m_training.numClasses(); nob++) {
rt[nob] *= m_set1.m_weight;
rt[nob] += tem[nob] * m_set2.m_weight;
}
}
else {
rt[0] *= m_set1.m_weight;
rt[0] += tem[0] * m_set2.m_weight;
}
return rt;
}
else if (((Double)tmp.elementAt(0)).intValue() == RECTANGLE) {
//System.out.println("RECT");
if (x >= ((Double)tmp.elementAt(1)).doubleValue() &&
x <= ((Double)tmp.elementAt(3)).doubleValue() &&
y <= ((Double)tmp.elementAt(2)).doubleValue() &&
y >= ((Double)tmp.elementAt(4)).doubleValue()) {
//then falls inside the rectangle
//System.out.println("true");
rt = m_set1.calcClassType(i);
return rt;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -