001: /*
002: * This program is free software; you can redistribute it and/or modify
003: * it under the terms of the GNU General Public License as published by
004: * the Free Software Foundation; either version 2 of the License, or
005: * (at your option) any later version.
006: *
007: * This program is distributed in the hope that it will be useful,
008: * but WITHOUT ANY WARRANTY; without even the implied warranty of
009: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
010: * GNU General Public License for more details.
011: *
012: * You should have received a copy of the GNU General Public License
013: * along with this program; if not, write to the Free Software
014: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
015: */
016:
017: /*
018: * RuleNode.java
019: * Copyright (C) 2000 University of Waikato, Hamilton, New Zealand
020: *
021: */
022:
023: package weka.classifiers.trees.m5;
024:
025: import weka.classifiers.Classifier;
026: import weka.core.Instance;
027: import weka.core.Instances;
028: import weka.core.Utils;
029:
030: import java.io.Serializable;
031:
032: /**
033: * This class encapsulates a linear regression function. It is a classifier
034: * but does not learn the function itself, instead it is constructed with
035: * coefficients and intercept obtained elsewhere. The buildClassifier method
036: * must still be called however as this stores a copy of the training data's
037: * header for use in printing the model to the console.
038: *
039: * @author Mark Hall (mhall@cs.waikato.ac.nz)
040: * @version $Revision: 1.5 $
041: */
042: public class PreConstructedLinearModel extends Classifier implements
043: Serializable {
044:
045: /** for serialization */
046: static final long serialVersionUID = 2030974097051713247L;
047:
048: /** The coefficients */
049: private double[] m_coefficients;
050:
051: /** The intercept */
052: private double m_intercept;
053:
054: /** Holds the instances header for printing the model */
055: private Instances m_instancesHeader;
056:
057: /** number of coefficients in the model */
058: private int m_numParameters;
059:
060: /**
061: * Constructor
062: *
063: * @param coeffs an array of coefficients
064: * @param intercept the intercept
065: */
066: public PreConstructedLinearModel(double[] coeffs, double intercept) {
067: m_coefficients = coeffs;
068: m_intercept = intercept;
069: int count = 0;
070: for (int i = 0; i < coeffs.length; i++) {
071: if (coeffs[i] != 0) {
072: count++;
073: }
074: }
075: m_numParameters = count;
076: }
077:
078: /**
079: * Builds the classifier. In this case all that is done is that a
080: * copy of the training instances header is saved.
081: *
082: * @param instances an <code>Instances</code> value
083: * @exception Exception if an error occurs
084: */
085: public void buildClassifier(Instances instances) throws Exception {
086: m_instancesHeader = new Instances(instances, 0);
087: }
088:
089: /**
090: * Predicts the class of the supplied instance using the linear model.
091: *
092: * @param inst the instance to make a prediction for
093: * @return the prediction
094: * @exception Exception if an error occurs
095: */
096: public double classifyInstance(Instance inst) throws Exception {
097: double result = 0;
098:
099: // System.out.println(inst);
100: for (int i = 0; i < m_coefficients.length; i++) {
101: if (i != inst.classIndex() && !inst.isMissing(i)) {
102: // System.out.println(inst.value(i)+" "+m_coefficients[i]);
103: result += m_coefficients[i] * inst.value(i);
104: }
105: }
106:
107: result += m_intercept;
108: return result;
109: }
110:
111: /**
112: * Return the number of parameters (coefficients) in the linear model
113: *
114: * @return the number of parameters
115: */
116: public int numParameters() {
117: return m_numParameters;
118: }
119:
120: /**
121: * Return the array of coefficients
122: *
123: * @return the coefficients
124: */
125: public double[] coefficients() {
126: return m_coefficients;
127: }
128:
129: /**
130: * Return the intercept
131: *
132: * @return the intercept
133: */
134: public double intercept() {
135: return m_intercept;
136: }
137:
138: /**
139: * Returns a textual description of this linear model
140: *
141: * @return String containing a description of this linear model
142: */
143: public String toString() {
144: StringBuffer b = new StringBuffer();
145: b.append("\n" + m_instancesHeader.classAttribute().name()
146: + " = ");
147: boolean first = true;
148: for (int i = 0; i < m_coefficients.length; i++) {
149: if (m_coefficients[i] != 0.0) {
150: double c = m_coefficients[i];
151: if (first) {
152: b.append("\n\t"
153: + Utils.doubleToString(c, 12, 4).trim()
154: + " * "
155: + m_instancesHeader.attribute(i).name()
156: + " ");
157: first = false;
158: } else {
159: b.append("\n\t"
160: + ((m_coefficients[i] < 0) ? "- "
161: + Utils.doubleToString(Math.abs(c),
162: 12, 4).trim() : "+ "
163: + Utils.doubleToString(Math.abs(c),
164: 12, 4).trim()) + " * "
165: + m_instancesHeader.attribute(i).name()
166: + " ");
167: }
168: }
169: }
170:
171: b.append("\n\t"
172: + ((m_intercept < 0) ? "- " : "+ ")
173: + Utils.doubleToString(Math.abs(m_intercept), 12, 4)
174: .trim());
175: return b.toString();
176: }
177: }
|