View Javadoc

1   /*
2    * Copyright (C) 2004-2006 Christian Siefkes <christian@siefkes.net>.
3    * Development of this software is supported by the German Research Society,
4    * Berlin-Brandenburg Graduate School in Distributed Information Systems
5    * (DFG grant no. GRK 316).
6    *
7    * This program is free software; you can redistribute it and/or modify
8    * it under the terms of the GNU General Public License as published by
9    * the Free Software Foundation; either version 2 of the License, or
10   * (at your option) any later version.
11   *
12   * This program is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   * GNU General Public License for more details.
16   *
17   * You should have received a copy of the GNU General Public License
18   * along with this program; if not, visit
19   * http://www.gnu.org/licenses/gpl.html or write to the Free Software
20   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21   */
22  package de.fu_berlin.ties.eval;
23  
24  import org.apache.commons.math.stat.descriptive.StatisticalSummary;
25  import org.apache.commons.math.stat.descriptive.SummaryStatistics;
26  
27  import de.fu_berlin.ties.io.FieldMap;
28  
29  /***
30   * {@link de.fu_berlin.ties.eval.FMetrics} extension that additionally
31   * calculates a {@link
32   * org.apache.commons.math.stat.descriptive.StatisticalSummary} of the
33   * intermediate precision, recall, and F1 metrics resulting from different
34   * {@link #update(long, long, long) update} operations. Values added by
35   * {@link de.fu_berlin.ties.eval.FMetrics#incFalseNeg() inc...} operations
36   * are <em>not</em> considered for summaries.
37   *
38   * <p>Especially the standard deviations might be interested -- thus they are
39   * {@linkplain #storeFields() serialized} in addition to the values stored by
40   * the superclass. The summaries cannot be restored during
41   * {@link #SummaryFMetrics(FieldMap) deserialization} because not all required
42   * information is serialized.
43   *
44   * @author Christian Siefkes
45   * @version $Revision: 1.7 $, $Date: 2006/10/21 16:04:11 $, $Author: siefkes $
46   */
47  public class SummaryFMetrics extends FMetrics implements FMetricsSummary {
48  
49      /***
50       * Prefix of serialization keys for standard deviations.
51       */
52      public static final String PREFIX_STD_DEVIATION = "Std. Deviation ";
53  
54      /***
55       * Summary statistics for the precision.
56       */
57      private final SummaryStatistics precisionSummary =
58          SummaryStatistics.newInstance();
59  
60      /***
61       * Summary statistics for the recall.
62       */
63      private final SummaryStatistics recallSummary =
64          SummaryStatistics.newInstance();
65  
66      /***
67       * Summary statistics for the F1 measure.
68       */
69      private final SummaryStatistics f1Summary = SummaryStatistics.newInstance();
70  
71      /***
72       * Creates a new empty instance.
73       */
74      public SummaryFMetrics() {
75          super();
76      }
77  
78      /***
79       * Creates a new instance from a field map, fulfilling the
80       * {@link de.fu_berlin.ties.io.Storable} contract. <strong>Any summary
81       * information stored in the initial instance will be lost, thus summaries
82       * calculated after restoring will be inaccurate.</strong>
83       *
84       * @param fieldMap map containing the serialized fields
85       * @throws IllegalArgumentException if at least one of the parameters is
86       * negative or missing
87       */
88      public SummaryFMetrics(final FieldMap fieldMap)
89              throws IllegalArgumentException {
90          super(fieldMap);
91      }
92  
93      /***
94       * Stores all relevant fields of this object in a field map for
95       * serialization. An equivalent object can be created by calling
96       * {@link de.fu_berlin.ties.io.FieldMap#createObject(Class)} on the created
97       * field map. The calculated values precision, recall, and F-measure and
98       * their standard deviations are also stored (they are ignored when
99       * {@linkplain #SummaryFMetrics(FieldMap) deserializing} a stored instance).
100      *
101      * @return the created field map
102      */
103     public FieldMap storeFields() {
104         // delegate to super + add standard deviations
105         final FieldMap result = super.storeFields();
106         result.put(PREFIX_STD_DEVIATION + KEY_PRECISION,
107             new Double(precisionSummary.getStandardDeviation()));
108         result.put(PREFIX_STD_DEVIATION + KEY_RECALL,
109             new Double(recallSummary.getStandardDeviation()));
110         result.put(PREFIX_STD_DEVIATION + KEY_F1_MEASURE,
111             new Double(f1Summary.getStandardDeviation()));
112         return result;
113     }
114 
115     /***
116      * Updates the statistics, increasing the stored values as specified and
117      * updating the statistical summaries.
118      *
119      * @param addTruePos the number of new true positives to add
120      * @param addFalseNeg the number of new false negatives to add
121      * @param addFalsePos the number of new false positives to add
122      * @throws IllegalArgumentException if at least one of the parameters is
123      * negative
124      */
125     public final void update(final long addTruePos, final long addFalseNeg,
126             final long addFalsePos) throws IllegalArgumentException {
127         // delegate to super + update summaries
128         super.update(addTruePos, addFalseNeg, addFalsePos);
129         final FMetrics newMetrics =
130             new FMetrics(addTruePos, addFalseNeg, addFalsePos);
131         precisionSummary.addValue(newMetrics.getPrecision());
132         recallSummary.addValue(newMetrics.getRecall());
133         f1Summary.addValue(newMetrics.getF1Measure());
134     }
135 
136     /***
137      * Returns a summary view on the F1 values. This is not a snapshot but
138      * will change whenever the underlying values are changed.
139      *
140      * @return a summary view on the F1 value
141      */
142     public StatisticalSummary viewF1Summary() {
143         return f1Summary;
144     }
145 
146     /***
147      * Returns a summary view on the precision values. This is not a snapshot
148      * but will change whenever the underlying values are changed.
149      *
150      * @return a summary view on the precision value
151      */
152     public StatisticalSummary viewPrecisionSummary() {
153         return precisionSummary;
154     }
155 
156     /***
157      * Returns a summary view on the recall values. This is not a snapshot but
158      * will change whenever the underlying values are changed.
159      *
160      * @return a summary view on the recall value
161      */
162     public StatisticalSummary viewRecallSummary() {
163         return recallSummary;
164     }
165 
166 }