source: branches/MetisMQI/src/main/java/weka/classifiers/evaluation/output/prediction/HTML.java

Last change on this file was 29, checked in by gnappo, 14 years ago

Taggata versione per la demo e aggiunto branch.

File size: 8.1 KB
Line 
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/*
18 * HTML.java
19 * Copyright (C) 2009 University of Waikato, Hamilton, New Zealand
20 */
21
22package weka.classifiers.evaluation.output.prediction;
23
24import weka.classifiers.Classifier;
25import weka.core.Instance;
26import weka.core.Utils;
27
28/**
29 <!-- globalinfo-start -->
30 * Outputs the predictions in HTML.
31 * <p/>
32 <!-- globalinfo-end -->
33 *
34 <!-- options-start -->
35 * Valid options are: <p/>
36 *
37 * <pre> -p &lt;range&gt;
38 *  The range of attributes to print in addition to the classification.
39 *  (default: none)</pre>
40 *
41 * <pre> -distribution
42 *  Whether to turn on the output of the class distribution.
43 *  Only for nominal class attributes.
44 *  (default: off)</pre>
45 *
46 * <pre> -decimals &lt;num&gt;
47 *  The number of digits after the decimal point.
48 *  (default: 3)</pre>
49 *
50 * <pre> -file &lt;path&gt;
51 *  The file to store the output in, instead of outputting it on stdout.
52 *  Gets ignored if the supplied path is a directory.
53 *  (default: .)</pre>
54 *
55 * <pre> -suppress
56 *  In case the data gets stored in a file, then this flag can be used
57 *  to suppress the regular output.
58 *  (default: not suppressed)</pre>
59 *
60 <!-- options-end -->
61 *
62 * @author  fracpete (fracpete at waikato dot ac dot nz)
63 * @version $Revision: 5987 $
64 */
65public class HTML
66  extends AbstractOutput {
67 
68  /** for serialization. */
69  private static final long serialVersionUID = 7241252244954353300L;
70
71  /**
72   * Returns a string describing the output generator.
73   *
74   * @return            a description suitable for
75   *                    displaying in the GUI
76   */
77  public String globalInfo() {
78    return "Outputs the predictions in HTML.";
79  }
80 
81  /**
82   * Returns a short display text, to be used in comboboxes.
83   *
84   * @return            a short display text
85   */
86  public String getDisplay() {
87    return "HTML";
88  }
89
90  /**
91   * Replaces certain characters with their HTML entities.
92   *
93   * @param s           the string to process
94   * @return            the processed string
95   */
96  protected String sanitize(String s) {
97    String      result;
98   
99    result = s;
100    result = result.replaceAll("&", "&amp;");
101    result = result.replaceAll("<", "&lt;");
102    result = result.replaceAll(">", "&gt;");
103    result = result.replaceAll("\"", "&quot;");
104   
105    return result;
106  }
107 
108  /**
109   * Performs the actual printing of the header.
110   */
111  protected void doPrintHeader() {
112    append("<html>\n");
113    append("<head>\n");
114    append("<title>Predictions for dataset " + sanitize(m_Header.relationName()) + "</title>\n");
115    append("</head>\n");
116    append("<body>\n");
117    append("<div align=\"center\">\n");
118    append("<h3>Predictions for dataset " + sanitize(m_Header.relationName()) + "</h3>\n");
119    append("<table border=\"1\">\n");
120    append("<tr>\n");
121    if (m_Header.classAttribute().isNominal())
122      if (m_OutputDistribution)
123        append("<td>inst#</td><td>actual</td><td>predicted</td><td>error</td><td colspan=\"" + m_Header.classAttribute().numValues() + "\">distribution</td>");
124      else
125        append("<td>inst#</td><td>actual</td><td>predicted</td><td>error</td><td>prediction</td>");
126    else
127      append("<td>inst#</td><td>actual</td><td>predicted</td><td>error</td>");
128   
129    if (m_Attributes != null) {
130      append("<td>");
131      boolean first = true;
132      for (int i = 0; i < m_Header.numAttributes(); i++) {
133        if (i == m_Header.classIndex())
134          continue;
135
136        if (m_Attributes.isInRange(i)) {
137          if (!first)
138            append("</td><td>");
139          append(sanitize(m_Header.attribute(i).name()));
140          first = false;
141        }
142      }
143      append("</td>");
144    }
145   
146    append("</tr>\n");
147  }
148
149  /**
150   * Builds a string listing the attribute values in a specified range of indices,
151   * separated by commas and enclosed in brackets.
152   *
153   * @param instance    the instance to print the values from
154   * @return            a string listing values of the attributes in the range
155   */
156  protected String attributeValuesString(Instance instance) {
157    StringBuffer text = new StringBuffer();
158    if (m_Attributes != null) {
159      boolean firstOutput = true;
160      m_Attributes.setUpper(instance.numAttributes() - 1);
161      for (int i=0; i<instance.numAttributes(); i++)
162        if (m_Attributes.isInRange(i) && i != instance.classIndex()) {
163          if (!firstOutput)
164            text.append("</td>");
165          if (m_Header.attribute(i).isNumeric())
166            text.append("<td align=\"right\">");
167          else
168            text.append("<td>");
169          text.append(sanitize(instance.toString(i)));
170          firstOutput = false;
171        }
172      if (!firstOutput)
173        text.append("</td>");
174    }
175    return text.toString();
176  }
177
178  /**
179   * Store the prediction made by the classifier as a string.
180   *
181   * @param classifier  the classifier to use
182   * @param inst        the instance to generate text from
183   * @param index       the index in the dataset
184   * @throws Exception  if something goes wrong
185   */
186  protected void doPrintClassification(Classifier classifier, Instance inst, int index) throws Exception {
187    int prec = m_NumDecimals;
188
189    Instance withMissing = (Instance)inst.copy();
190    withMissing.setDataset(inst.dataset());
191    withMissing.setMissing(withMissing.classIndex());
192    double predValue = classifier.classifyInstance(withMissing);
193
194    // index
195    append("<tr>");
196    append("<td>" + (index+1) + "</td>");
197
198    if (inst.dataset().classAttribute().isNumeric()) {
199      // actual
200      if (inst.classIsMissing())
201        append("<td align=\"right\">" + "?" + "</td>");
202      else
203        append("<td align=\"right\">" + Utils.doubleToString(inst.classValue(), prec) + "</td>");
204      // predicted
205      if (Utils.isMissingValue(predValue))
206        append("<td align=\"right\">" + "?" + "</td>");
207      else
208        append("<td align=\"right\">" + Utils.doubleToString(predValue, prec) + "</td>");
209      // error
210      if (Utils.isMissingValue(predValue) || inst.classIsMissing())
211        append("<td align=\"right\">" + "?" + "</td>");
212      else
213        append("<td align=\"right\">" + Utils.doubleToString(predValue - inst.classValue(), prec) + "</td>");
214    } else {
215      // actual
216      append("<td>" + ((int) inst.classValue()+1) + ":" + sanitize(inst.toString(inst.classIndex())) + "</td>");
217      // predicted
218      if (Utils.isMissingValue(predValue))
219        append("<td>" + "?" + "</td>");
220      else
221        append("<td>" + ((int) predValue+1) + ":" + sanitize(inst.dataset().classAttribute().value((int)predValue)) + "</td>");
222      // error?
223      if (!Utils.isMissingValue(predValue) && !inst.classIsMissing() && ((int) predValue+1 != (int) inst.classValue()+1))
224        append("<td>" + "+" + "</td>");
225      else
226        append("<td>" + "&nbsp;" + "</td>");
227      // prediction/distribution
228      if (m_OutputDistribution) {
229        if (Utils.isMissingValue(predValue)) {
230          append("<td>" + "?" + "</td>");
231        }
232        else {
233          append("<td align=\"right\">");
234          double[] dist = classifier.distributionForInstance(withMissing);
235          for (int n = 0; n < dist.length; n++) {
236            if (n > 0)
237              append("</td><td align=\"right\">");
238            if (n == (int) predValue)
239              append("*");
240            append(Utils.doubleToString(dist[n], prec));
241          }
242          append("</td>");
243        }
244      }
245      else {
246        if (Utils.isMissingValue(predValue))
247          append("<td align=\"right\">" + "?" + "</td>");
248        else
249          append("<td align=\"right\">" + Utils.doubleToString(classifier.distributionForInstance(withMissing) [(int)predValue], prec) + "</td>");
250      }
251    }
252
253    // attributes
254    append(attributeValuesString(withMissing) + "</tr>\n");
255  }
256 
257  /**
258   * Does nothing.
259   */
260  protected void doPrintFooter() {
261    append("</table>\n");
262    append("</div>\n");
263    append("</body>\n");
264    append("</html>\n");
265  }
266}
Note: See TracBrowser for help on using the repository browser.