LinearRegression.java
Upload User: rhdiban
Upload Date: 2013-08-09
Package Size: 15085k
Code Size: 23k
Category:

Windows Develop

Development Platform:

Java

  1. /*
  2.  *    This program is free software; you can redistribute it and/or modify
  3.  *    it under the terms of the GNU General Public License as published by
  4.  *    the Free Software Foundation; either version 2 of the License, or
  5.  *    (at your option) any later version.
  6.  *
  7.  *    This program is distributed in the hope that it will be useful,
  8.  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  9.  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  10.  *    GNU General Public License for more details.
  11.  *
  12.  *    You should have received a copy of the GNU General Public License
  13.  *    along with this program; if not, write to the Free Software
  14.  *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15.  */
  16. /*
  17.  *    LinearRegression.java
  18.  *    Copyright (C) 1999 Eibe Frank,Len Trigg
  19.  *
  20.  */
  21. package weka.classifiers.functions;
  22. import weka.classifiers.Classifier;
  23. import weka.classifiers.Evaluation;
  24. import weka.filters.supervised.attribute.NominalToBinary;
  25. import weka.filters.unsupervised.attribute.ReplaceMissingValues;
  26. import weka.filters.Filter;
  27. import java.io.*;
  28. import java.util.*;
  29. import weka.core.*;
  30. /**
  31.  * Class for using linear regression for prediction. Uses the Akaike 
  32.  * criterion for model selection, and is able to deal with weighted
  33.  * instances. <p>
  34.  *
  35.  * Valid options are:<p>
  36.  *
  37.  * -D <br>
  38.  * Produce debugging output. <p>
  39.  *
  40.  * -S num <br>
  41.  * Set the attriute selection method to use. 1 = None, 2 = Greedy
  42.  * (default 0 = M5' method) <p>
  43.  *
  44.  * -C <br>
  45.  * Do not try to eliminate colinear attributes <p>
  46.  *
  47.  * -R num <br>
  48.  * The ridge parameter (default 1.0e-8) <p>
  49.  *
  50.  * @author Eibe Frank (eibe@cs.waikato.ac.nz)
  51.  * @author Len Trigg (trigg@cs.waikato.ac.nz)
  52.  * @version $Revision: 1.18 $
  53.  */
  54. public class LinearRegression extends Classifier implements OptionHandler,
  55.   WeightedInstancesHandler {
  56.   /** Array for storing coefficients of linear regression. */
  57.   private double[] m_Coefficients;
  58.   /** Which attributes are relevant? */
  59.   private boolean[] m_SelectedAttributes;
  60.   /** Variable for storing transformed training data. */
  61.   private Instances m_TransformedData;
  62.   /** The filter for removing missing values. */
  63.   private ReplaceMissingValues m_MissingFilter;
  64.   /** The filter storing the transformation from nominal to 
  65.       binary attributes. */
  66.   private NominalToBinary m_TransformFilter;
  67.   /** The standard deviations of the class attribute */
  68.   private double m_ClassStdDev;
  69.   /** The mean of the class attribute */
  70.   private double m_ClassMean;
  71.   /** The index of the class attribute */
  72.   private int m_ClassIndex;
  73.   /** The attributes means */
  74.   private double[] m_Means;
  75.   /** The attribute standard deviations */
  76.   private double[] m_StdDevs;
  77.   /** True if debug output will be printed */
  78.   private boolean b_Debug;
  79.   /** The current attribute selection method */
  80.   private int m_AttributeSelection;
  81.   /* Attribute selection methods */
  82.   public static final int SELECTION_M5 = 0;
  83.   public static final int SELECTION_NONE = 1;
  84.   public static final int SELECTION_GREEDY = 2;
  85.   public static final Tag [] TAGS_SELECTION = {
  86.     new Tag(SELECTION_NONE, "No attribute selection"),
  87.     new Tag(SELECTION_M5, "M5 method"),
  88.     new Tag(SELECTION_GREEDY, "Greedy method")
  89.   };
  90.   /** Try to eliminate correlated attributes? */
  91.   private boolean m_EliminateColinearAttributes = true;
  92.   /** Turn off all checks and conversions? */
  93.   private boolean m_checksTurnedOff = false;
  94.   /** The ridge parameter */
  95.   private double m_Ridge = 1.0e-8;
  96.   /**
  97.    * Turns off checks for missing values, etc. Use with caution.
  98.    * Also turns off scaling.
  99.    */
  100.   public void turnChecksOff() {
  101.     m_checksTurnedOff = true;
  102.   }
  103.   /**
  104.    * Turns on checks for missing values, etc. Also turns
  105.    * on scaling.
  106.    */
  107.   public void turnChecksOn() {
  108.     m_checksTurnedOff = false;
  109.   }
  110.   /**
  111.    * Builds a regression model for the given data.
  112.    *
  113.    * @param data the training data to be used for generating the
  114.    * linear regression function
  115.    * @exception Exception if the classifier could not be built successfully
  116.    */
  117.   public void buildClassifier(Instances data) throws Exception {
  118.   
  119.     if (!m_checksTurnedOff) {
  120.       if (!data.classAttribute().isNumeric()) {
  121. throw new UnsupportedClassTypeException("Class attribute has to be numeric for regression!");
  122.       }
  123.       if (data.numInstances() == 0) {
  124. throw new Exception("No instances in training file!");
  125.       }
  126.       if (data.checkForStringAttributes()) {
  127. throw new UnsupportedAttributeTypeException("Cannot handle string attributes!");
  128.       }
  129.     }
  130.     // Preprocess instances
  131.     if (!m_checksTurnedOff) {
  132.       m_TransformFilter = new NominalToBinary();
  133.       m_TransformFilter.setInputFormat(data);
  134.       data = Filter.useFilter(data, m_TransformFilter);
  135.       m_MissingFilter = new ReplaceMissingValues();
  136.       m_MissingFilter.setInputFormat(data);
  137.       data = Filter.useFilter(data, m_MissingFilter);
  138.       data.deleteWithMissingClass();
  139.     } else {
  140.       m_TransformFilter = null;
  141.       m_MissingFilter = null;
  142.     }
  143.     m_ClassIndex = data.classIndex();
  144.     m_TransformedData = data;
  145.     // Turn all attributes on for a start
  146.     m_SelectedAttributes = new boolean[data.numAttributes()];
  147.     for (int i = 0; i < data.numAttributes(); i++) {
  148.       if (i != m_ClassIndex) {
  149. m_SelectedAttributes[i] = true;
  150.       }
  151.     }
  152.     m_Coefficients = null;
  153.     // Compute means and standard deviations
  154.     m_Means = new double[data.numAttributes()];
  155.     m_StdDevs = new double[data.numAttributes()];
  156.     for (int j = 0; j < data.numAttributes(); j++) {
  157.       if (j != data.classIndex()) {
  158. m_Means[j] = data.meanOrMode(j);
  159. m_StdDevs[j] = Math.sqrt(data.variance(j));
  160. if (m_StdDevs[j] == 0) {
  161.   m_SelectedAttributes[j] = false;
  162.       }
  163.     }
  164.     m_ClassStdDev = Math.sqrt(data.variance(m_TransformedData.classIndex()));
  165.     m_ClassMean = data.meanOrMode(m_TransformedData.classIndex());
  166.     // Perform the regression
  167.     findBestModel();
  168.     // Save memory
  169.     m_TransformedData = new Instances(data, 0);
  170.   }
  171.   /**
  172.    * Classifies the given instance using the linear regression function.
  173.    *
  174.    * @param instance the test instance
  175.    * @return the classification
  176.    * @exception Exception if classification can't be done successfully
  177.    */
  178.   public double classifyInstance(Instance instance) throws Exception {
  179.     // Transform the input instance
  180.     Instance transformedInstance = instance;
  181.     if (!m_checksTurnedOff) {
  182.       m_TransformFilter.input(transformedInstance);
  183.       m_TransformFilter.batchFinished();
  184.       transformedInstance = m_TransformFilter.output();
  185.       m_MissingFilter.input(transformedInstance);
  186.       m_MissingFilter.batchFinished();
  187.       transformedInstance = m_MissingFilter.output();
  188.     }
  189.     // Calculate the dependent variable from the regression model
  190.     return regressionPrediction(transformedInstance,
  191. m_SelectedAttributes,
  192. m_Coefficients);
  193.   }
  194.   /**
  195.    * Outputs the linear regression model as a string.
  196.    */
  197.   public String toString() {
  198.     if (m_TransformedData == null) {
  199.       return "Linear Regression: No model built yet.";
  200.     }
  201.     try {
  202.       StringBuffer text = new StringBuffer();
  203.       int column = 0;
  204.       boolean first = true;
  205.       
  206.       text.append("nLinear Regression Modelnn");
  207.       
  208.       text.append(m_TransformedData.classAttribute().name()+" =nn");
  209.       for (int i = 0; i < m_TransformedData.numAttributes(); i++) {
  210. if ((i != m_ClassIndex) 
  211.     && (m_SelectedAttributes[i])) {
  212.   if (!first) 
  213.     text.append(" +n");
  214.   else
  215.     first = false;
  216.   text.append(Utils.doubleToString(m_Coefficients[column], 12, 4)
  217.       + " * ");
  218.   text.append(m_TransformedData.attribute(i).name());
  219.   column++;
  220. }
  221.       }
  222.       text.append(" +n" + 
  223.   Utils.doubleToString(m_Coefficients[column], 12, 4));
  224.       return text.toString();
  225.     } catch (Exception e) {
  226.       return "Can't print Linear Regression!";
  227.     }
  228.   }
  229.   /**
  230.    * Returns an enumeration describing the available options.
  231.    *
  232.    * @return an enumeration of all the available options.
  233.    */
  234.   public Enumeration listOptions() {
  235.     
  236.     Vector newVector = new Vector(4);
  237.     newVector.addElement(new Option("tProduce debugging output.n"
  238.     + "t(default no debugging output)",
  239.     "D", 0, "-D"));
  240.     newVector.addElement(new Option("tSet the attribute selection method"
  241.     + " to use. 1 = None, 2 = Greedy.n"
  242.     + "t(default 0 = M5' method)",
  243.     "S", 1, "-S <number of selection method>"));
  244.     newVector.addElement(new Option("tDo not try to eliminate colinear"
  245.     + " attributes.n",
  246.     "C", 0, "-C"));
  247.     newVector.addElement(new Option("tSet ridge parameter (default 1.0e-8).n",
  248.     "R", 1, "-R <double>"));
  249.     return newVector.elements();
  250.   }
  251.   /**
  252.    * Parses a given list of options. Valid options are:<p>
  253.    *
  254.    * -D <br>
  255.    * Produce debugging output. <p>
  256.    *
  257.    * -S num <br>
  258.    * Set the attriute selection method to use. 1 = None, 2 = Greedy
  259.    * (default 0 = M5' method) <p>
  260.    *
  261.    * -C <br>
  262.    * Do not try to eliminate colinear attributes <p>
  263.    *
  264.    * -R num <br>
  265.    * The ridge parameter (default 1.0e-8) <p>
  266.    *
  267.    * @param options the list of options as an array of strings
  268.    * @exception Exception if an option is not supported
  269.    */
  270.   public void setOptions(String[] options) throws Exception {
  271.     String selectionString = Utils.getOption('S', options);
  272.     if (selectionString.length() != 0) {
  273.       setAttributeSelectionMethod(new SelectedTag(Integer
  274.   .parseInt(selectionString),
  275.   TAGS_SELECTION));
  276.     } else {
  277.       setAttributeSelectionMethod(new SelectedTag(SELECTION_M5,
  278.   TAGS_SELECTION));
  279.     }
  280.     String ridgeString = Utils.getOption('R', options);
  281.     if (ridgeString.length() != 0) {
  282.       setRidge(new Double(ridgeString).doubleValue());
  283.     } else {
  284.       setRidge(1.0e-8);
  285.     }
  286.     setDebug(Utils.getFlag('D', options));
  287.     setEliminateColinearAttributes(!Utils.getFlag('C', options));
  288.   }
  289.   /**
  290.    * Returns the coefficients for this linear model.
  291.    */
  292.   public double[] coefficients() {
  293.     double[] coefficients = new double[m_SelectedAttributes.length + 1];
  294.     int counter = 0;
  295.     for (int i = 0; i < m_SelectedAttributes.length; i++) {
  296.       if ((m_SelectedAttributes[i]) && ((i != m_ClassIndex))) {
  297. coefficients[i] = m_Coefficients[counter++];
  298.       }
  299.     }
  300.     coefficients[m_SelectedAttributes.length] = m_Coefficients[counter];
  301.     return coefficients;
  302.   }
  303.   /**
  304.    * Gets the current settings of the classifier.
  305.    *
  306.    * @return an array of strings suitable for passing to setOptions
  307.    */
  308.   public String [] getOptions() {
  309.     String [] options = new String [6];
  310.     int current = 0;
  311.     options[current++] = "-S";
  312.     options[current++] = "" + getAttributeSelectionMethod()
  313.       .getSelectedTag().getID();
  314.     if (getDebug()) {
  315.       options[current++] = "-D";
  316.     }
  317.     if (!getEliminateColinearAttributes()) {
  318.       options[current++] = "-C";
  319.     }
  320.     options[current++] = "-R";
  321.     options[current++] = "" + getRidge();
  322.     while (current < options.length) {
  323.       options[current++] = "";
  324.     }
  325.     return options;
  326.   }
  327.   
  328.   /**
  329.    * Get the value of Ridge.
  330.    *
  331.    * @return Value of Ridge.
  332.    */
  333.   public double getRidge() {
  334.     
  335.     return m_Ridge;
  336.   }
  337.   
  338.   /**
  339.    * Set the value of Ridge.
  340.    *
  341.    * @param newRidge Value to assign to Ridge.
  342.    */
  343.   public void setRidge(double newRidge) {
  344.     
  345.     m_Ridge = newRidge;
  346.   }
  347.   
  348.   /**
  349.    * Get the value of EliminateColinearAttributes.
  350.    *
  351.    * @return Value of EliminateColinearAttributes.
  352.    */
  353.   public boolean getEliminateColinearAttributes() {
  354.     
  355.     return m_EliminateColinearAttributes;
  356.   }
  357.   
  358.   /**
  359.    * Set the value of EliminateColinearAttributes.
  360.    *
  361.    * @param newEliminateColinearAttributes Value to assign to EliminateColinearAttributes.
  362.    */
  363.   public void setEliminateColinearAttributes(boolean newEliminateColinearAttributes) {
  364.     
  365.     m_EliminateColinearAttributes = newEliminateColinearAttributes;
  366.   }
  367.   
  368.   /**
  369.    * Get the number of coefficients used in the model
  370.    *
  371.    * @return the number of coefficients
  372.    */
  373.   public int numParameters()
  374.   {
  375.     return m_Coefficients.length-1;
  376.   }
  377.   /**
  378.    * Sets the method used to select attributes for use in the
  379.    * linear regression. 
  380.    *
  381.    * @param method the attribute selection method to use.
  382.    */
  383.   public void setAttributeSelectionMethod(SelectedTag method) {
  384.     
  385.     if (method.getTags() == TAGS_SELECTION) {
  386.       m_AttributeSelection = method.getSelectedTag().getID();
  387.     }
  388.   }
  389.   /**
  390.    * Gets the method used to select attributes for use in the
  391.    * linear regression. 
  392.    *
  393.    * @return the method to use.
  394.    */
  395.   public SelectedTag getAttributeSelectionMethod() {
  396.     
  397.     return new SelectedTag(m_AttributeSelection, TAGS_SELECTION);
  398.   }
  399.   /**
  400.    * Controls whether debugging output will be printed
  401.    *
  402.    * @param debug true if debugging output should be printed
  403.    */
  404.   public void setDebug(boolean debug) {
  405.     b_Debug = debug;
  406.   }
  407.   /**
  408.    * Controls whether debugging output will be printed
  409.    *
  410.    * @param debug true if debugging output should be printed
  411.    */
  412.   public boolean getDebug() {
  413.     return b_Debug;
  414.   }
  415.   /**
  416.    * Removes the attribute with the highest standardised coefficient
  417.    * greater than 1.5 from the selected attributes.
  418.    *
  419.    * @param selectedAttributes an array of flags indicating which 
  420.    * attributes are included in the regression model
  421.    * @param coefficients an array of coefficients for the regression
  422.    * model
  423.    * @return true if an attribute was removed
  424.    */
  425.   private boolean deselectColinearAttributes(boolean [] selectedAttributes,
  426.      double [] coefficients) {
  427.     double maxSC = 1.5;
  428.     int maxAttr = -1, coeff = 0;
  429.     for (int i = 0; i < selectedAttributes.length; i++) {
  430.       if (selectedAttributes[i]) {
  431. double SC = Math.abs(coefficients[coeff] * m_StdDevs[i] 
  432.      / m_ClassStdDev);
  433. if (SC > maxSC) {
  434.   maxSC = SC;
  435.   maxAttr = i;
  436. }
  437. coeff++;
  438.       }
  439.     }
  440.     if (maxAttr >= 0) {
  441.       selectedAttributes[maxAttr] = false;
  442.       if (b_Debug) {
  443. System.out.println("Deselected colinear attribute:" + (maxAttr + 1)
  444.    + " with standardised coefficient: " + maxSC);
  445.       }
  446.       return true;
  447.     }
  448.     return false;
  449.   }
  450.   /**
  451.    * Performs a greedy search for the best regression model using
  452.    * Akaike's criterion.
  453.    *
  454.    * @exception Exception if regression can't be done
  455.    */
  456.   private void findBestModel() throws Exception {
  457.     // For the weighted case we still use numInstances in
  458.     // the calculation of the Akaike criterion. 
  459.     int numInstances = m_TransformedData.numInstances();
  460.     if (b_Debug) {
  461.       System.out.println((new Instances(m_TransformedData, 0)).toString());
  462.     }
  463.     // Perform a regression for the full model, and remove colinear attributes
  464.     do {
  465.       m_Coefficients = doRegression(m_SelectedAttributes);
  466.     } while (m_EliminateColinearAttributes && 
  467.      deselectColinearAttributes(m_SelectedAttributes, m_Coefficients));
  468.     // Figure out current number of attributes + 1. (We treat this model
  469.     // as the full model for the Akaike-based methods.)
  470.     int numAttributes = 1;
  471.     for (int i = 0; i < m_SelectedAttributes.length; i++) {
  472.       if (m_SelectedAttributes[i]) {
  473. numAttributes++;
  474.       }
  475.     }
  476.     double fullMSE = calculateSE(m_SelectedAttributes, m_Coefficients);
  477.     double akaike = (numInstances - numAttributes) + 2 * numAttributes;
  478.     if (b_Debug) {
  479.       System.out.println("Initial Akaike value: " + akaike);
  480.     }
  481.     boolean improved;
  482.     int currentNumAttributes = numAttributes;
  483.     switch (m_AttributeSelection) {
  484.     case SELECTION_GREEDY:
  485.       // Greedy attribute removal
  486.       do {
  487. boolean [] currentSelected = (boolean []) m_SelectedAttributes.clone();
  488. improved = false;
  489. currentNumAttributes--;
  490. for (int i = 0; i < m_SelectedAttributes.length; i++) {
  491.   if (currentSelected[i]) {
  492.     // Calculate the akaike rating without this attribute
  493.     currentSelected[i] = false;
  494.     double [] currentCoeffs = doRegression(currentSelected);
  495.     double currentMSE = calculateSE(currentSelected, currentCoeffs);
  496.     double currentAkaike = currentMSE / fullMSE 
  497.       * (numInstances - numAttributes)
  498.       + 2 * currentNumAttributes;
  499.     if (b_Debug) {
  500.       System.out.println("(akaike: " + currentAkaike);
  501.     }
  502.     // If it is better than the current best
  503.     if (currentAkaike < akaike) {
  504.       if (b_Debug) {
  505. System.err.println("Removing attribute " + (i + 1)
  506.    + " improved Akaike: " + currentAkaike);
  507.       }
  508.       improved = true;
  509.       akaike = currentAkaike;
  510.       System.arraycopy(currentSelected, 0,
  511.        m_SelectedAttributes, 0,
  512.        m_SelectedAttributes.length);
  513.       m_Coefficients = currentCoeffs;
  514.     }
  515.     currentSelected[i] = true;
  516.   }
  517. }
  518.       } while (improved);
  519.       break;
  520.     case SELECTION_M5:
  521.       // Step through the attributes removing the one with the smallest 
  522.       // standardised coefficient until no improvement in Akaike
  523.       do {
  524. improved = false;
  525. currentNumAttributes--;
  526. // Find attribute with smallest SC
  527. double minSC = 0;
  528. int minAttr = -1, coeff = 0;
  529. for (int i = 0; i < m_SelectedAttributes.length; i++) {
  530.   if (m_SelectedAttributes[i]) {
  531.     double SC = Math.abs(m_Coefficients[coeff] * m_StdDevs[i] 
  532.  / m_ClassStdDev);
  533.     if ((coeff == 0) || (SC < minSC)) {
  534.       minSC = SC;
  535.       minAttr = i;
  536.     }
  537.     coeff++;
  538.   }
  539. }
  540. // See whether removing it improves the Akaike score
  541. if (minAttr >= 0) {
  542.   m_SelectedAttributes[minAttr] = false;
  543.   double [] currentCoeffs = doRegression(m_SelectedAttributes);
  544.   double currentMSE = calculateSE(m_SelectedAttributes, currentCoeffs);
  545.   double currentAkaike = currentMSE / fullMSE 
  546.     * (numInstances - numAttributes)
  547.     + 2 * currentNumAttributes;
  548.   if (b_Debug) {
  549.     System.out.println("(akaike: " + currentAkaike);
  550.   }
  551.   // If it is better than the current best
  552.   if (currentAkaike < akaike) {
  553.     if (b_Debug) {
  554.       System.err.println("Removing attribute " + (minAttr + 1)
  555.  + " improved Akaike: " + currentAkaike);
  556.     }
  557.     improved = true;
  558.     akaike = currentAkaike;
  559.     m_Coefficients = currentCoeffs;
  560.   } else {
  561.     m_SelectedAttributes[minAttr] = true;
  562.   }
  563. }
  564.       } while (improved);
  565.       break;
  566.     case SELECTION_NONE:
  567.       break;
  568.     }
  569.   }
  570.   /**
  571.    * Calculate the squared error of a regression model on the 
  572.    * training data
  573.    *
  574.    * @param selectedAttributes an array of flags indicating which 
  575.    * attributes are included in the regression model
  576.    * @param coefficients an array of coefficients for the regression
  577.    * model
  578.    * @return the mean squared error on the training data
  579.    * @exception Exception if there is a missing class value in the training
  580.    * data
  581.    */
  582.   private double calculateSE(boolean [] selectedAttributes, 
  583.       double [] coefficients) throws Exception {
  584.     double mse = 0;
  585.     for (int i = 0; i < m_TransformedData.numInstances(); i++) {
  586.       double prediction = regressionPrediction(m_TransformedData.instance(i),
  587.        selectedAttributes,
  588.        coefficients);
  589.       double error = prediction - m_TransformedData.instance(i).classValue();
  590.       mse += error * error;
  591.     }
  592.     return mse;
  593.   }
  594.   /**
  595.    * Calculate the dependent value for a given instance for a
  596.    * given regression model.
  597.    *
  598.    * @param transformedInstance the input instance
  599.    * @param selectedAttributes an array of flags indicating which 
  600.    * attributes are included in the regression model
  601.    * @param coefficients an array of coefficients for the regression
  602.    * model
  603.    * @return the regression value for the instance.
  604.    * @exception Exception if the class attribute of the input instance
  605.    * is not assigned
  606.    */
  607.   private double regressionPrediction(Instance transformedInstance,
  608.       boolean [] selectedAttributes,
  609.       double [] coefficients) 
  610.   throws Exception {
  611.     
  612.     double result = 0;
  613.     int column = 0;
  614.     for (int j = 0; j < transformedInstance.numAttributes(); j++) {
  615.       if ((m_ClassIndex != j) 
  616.   && (selectedAttributes[j])) {
  617. result += coefficients[column] * transformedInstance.value(j);
  618. column++;
  619.       }
  620.     }
  621.     result += coefficients[column];
  622.     
  623.     return result;
  624.   }
  625.   /**
  626.    * Calculate a linear regression using the selected attributes
  627.    *
  628.    * @param selectedAttributes an array of booleans where each element
  629.    * is true if the corresponding attribute should be included in the
  630.    * regression.
  631.    * @return an array of coefficients for the linear regression model.
  632.    * @exception Exception if an error occurred during the regression.
  633.    */
  634.   private double [] doRegression(boolean [] selectedAttributes) 
  635.   throws Exception {
  636.     if (b_Debug) {
  637.       System.out.print("doRegression(");
  638.       for (int i = 0; i < selectedAttributes.length; i++) {
  639. System.out.print(" " + selectedAttributes[i]);
  640.       }
  641.       System.out.println(" )");
  642.     }
  643.     int numAttributes = 0;
  644.     for (int i = 0; i < selectedAttributes.length; i++) {
  645.       if (selectedAttributes[i]) {
  646. numAttributes++;
  647.       }
  648.     }
  649.     // Check whether there are still attributes left
  650.     Matrix independent = null, dependent = null;
  651.     double[] weights = null;
  652.     if (numAttributes > 0) {
  653.       independent = new Matrix(m_TransformedData.numInstances(), 
  654.        numAttributes);
  655.       dependent = new Matrix(m_TransformedData.numInstances(), 1);
  656.       for (int i = 0; i < m_TransformedData.numInstances(); i ++) {
  657. Instance inst = m_TransformedData.instance(i);
  658. int column = 0;
  659. for (int j = 0; j < m_TransformedData.numAttributes(); j++) {
  660.   if (j == m_ClassIndex) {
  661.     dependent.setElement(i, 0, inst.classValue());
  662.   } else {
  663.     if (selectedAttributes[j]) {
  664.       double value = inst.value(j) - m_Means[j];
  665.       
  666.       // We only need to do this if we want to
  667.       // scale the input
  668.       if (!m_checksTurnedOff) {
  669. value /= m_StdDevs[j];
  670.       }
  671.       independent.setElement(i, column, value);
  672.       column++;
  673.     }
  674.   }
  675. }
  676.       }
  677.       
  678.       // Grab instance weights
  679.       weights = new double [m_TransformedData.numInstances()];
  680.       for (int i = 0; i < weights.length; i++) {
  681. weights[i] = m_TransformedData.instance(i).weight();
  682.       }
  683.     }
  684.     // Compute coefficients (note that we have to treat the
  685.     // intercept separately so that it doesn't get affected
  686.     // by the ridge constant.)
  687.     double[] coefficients = new double[numAttributes + 1];
  688.     if (numAttributes > 0) {
  689.       double[] coeffsWithoutIntercept  =
  690. independent.regression(dependent, weights, m_Ridge);
  691.       System.arraycopy(coeffsWithoutIntercept, 0, coefficients, 0,
  692.        numAttributes);
  693.     }
  694.     coefficients[numAttributes] = m_ClassMean;
  695.    
  696.     // Convert coefficients into original scale
  697.     int column = 0;
  698.     for(int i = 0; i < m_TransformedData.numAttributes(); i++) {
  699.       if ((i != m_TransformedData.classIndex()) &&
  700.   (selectedAttributes[i])) {
  701. // We only need to do this if we have scaled the
  702. // input.
  703. if (!m_checksTurnedOff) {
  704.   coefficients[column] /= m_StdDevs[i];
  705. }
  706. // We have centred the input
  707. coefficients[coefficients.length - 1] -= 
  708.   coefficients[column] * m_Means[i];
  709. column++;
  710.       }
  711.     }
  712.     return coefficients;
  713.   }
  714.  
  715.   /**
  716.    * Generates a linear regression function predictor.
  717.    *
  718.    * @param String the options
  719.    */
  720.   public static void main(String argv[]) {
  721.     
  722.     try {
  723.       System.out.println(Evaluation.evaluateModel(new LinearRegression(),
  724.   argv));
  725.     } catch (Exception e) {
  726.       e.printStackTrace();
  727.       System.out.println(e.getMessage());
  728.     }
  729.   }
  730. }
  731.