Package mvpa :: Package misc :: Module errorfx

[hide private]
[frames] | no frames]

# Source Code for Module mvpa.misc.errorfx

      1  # emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
      2  # vi: set ft=python sts=4 ts=4 sw=4 et:
      3  ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
      4  #
      5  #   See COPYING file distributed along with the PyMVPA package for the
      6  #   copyright and license terms.
      7  #
      8  ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
      9  """Error functions helpers.
     10
     11  PyMVPA can use arbitrary function which takes 2 arguments: predictions
     12  and targets and spits out a scalar value. Functions below are for the
     13  convinience, and they confirm the agreement that 'smaller' is 'better'"""
     14
     15  __docformat__ = 'restructuredtext'
     16
     17
     18  import numpy as N
     19  from numpy import trapz
     20
     21  from mvpa.base import externals
     22
     23  # Various helper functions
     24 -def meanPowerFx(data):
     25      """Returns mean power
     26
     27      Similar to var but without demeaning
     28      """
     29      return N.mean(N.asanyarray(data)**2)
     30
     31 -def rootMeanPowerFx(data):
     32      """Returns root mean power
     33
     34      to be comparable against RMSE
     35      """
     36      return N.sqrt(meanPowerFx(data))
     37
     38
     39 -class _ErrorFx(object):
     40      """Common error function interface, computing the difference between
     41      some target and some predicted values.
     42      """
     43
     44      """XXX there is no reason to keep this class around imho -- it is
     45      just the skeleton for all the _ErrorFxs -- interface they
     46      must conform... and there is no reason to have all those ErrorFx
     47      as classes... may be they should be just functions?"""
     48
     49 -    def __str__(self):
     50          """Print class name when asked for string
     51          """
     52          return self.__class__.__name__
     53
     54 -    def __repr__(self):
     55          """Proper repr for _ErrorFx
     56          """
     57          return self.__class__.__name__ + "()"
     58
     59 -    def __call__(self, predicted, target):
     60          """Compute some error value from the given target and predicted
     61          values (both sequences).
     62          """
     63          raise NotImplemented
     64
     65
     66 -class RMSErrorFx(_ErrorFx):
     67      """Computes the root mean squared error of some target and some
     68      predicted values.
     69      """
     70 -    def __call__(self, predicted, target):
     71          """Both 'predicted' and 'target' can be either scalars or sequences,
     72          but have to be of the same length.
     73          """
     74          return N.sqrt(N.mean(N.subtract(predicted, target)**2))
     75
     76
     77 -class MeanMismatchErrorFx(_ErrorFx):
     78      """Computes the percentage of mismatches between some target and some
     79      predicted values.
     80      """
     81 -    def __call__(self, predicted, target):
     82          """Both 'predicted' and 'target' can be either scalars or sequences,
     83          but have to be of the same length.
     84          """
     85          return 1 - N.mean( predicted == target )
     86
     87
     88 -class AUCErrorFx(_ErrorFx):
     89      """Computes the area under the ROC for the given the
     90      target and predicted to make the prediction."""
     91 -    def __call__(self, predicted, target):
     92          """Requires all arguments."""
     93          # sort the target in descending order based on the predicted and
     94          # set to boolean
     95          self.t = t = N.asanyarray(target)[N.argsort(predicted)[::-1]] > 0
     96
     97          # calculate the true positives
     98          self.tp = tp = N.concatenate(
     99              ([0], N.cumsum(t)/t.sum(dtype=N.float), [1]))
    100
    101          # calculate the false positives
    102          self.fp = fp = N.concatenate(
    103              ([0], N.cumsum(~t)/(~t).sum(dtype=N.float), [1]))
    104
    105          return trapz(tp, fp)
    106
    107
    108  if externals.exists('scipy'):
    109      from scipy.stats import pearsonr
    110
    111 -    class CorrErrorFx(_ErrorFx):
    112          """Computes the correlation between the target and the
    113          predicted values. Resultant value is the 1 - correlation
    114          coefficient, so minimization leads to the best value (at 0)
    115
    116          """
    117 -        def __call__(self, predicted, target):
    118              """Requires all arguments."""
    119              return 1.0-pearsonr(predicted, target)[0]
    120
    121
    122 -    class CorrErrorPFx(_ErrorFx):
    123          """Computes p-value of correlation between the target and the predicted
    124          values.
    125
    126          """
    127 -        def __call__(self, predicted, target):
    128              """Requires all arguments."""
    129              return pearsonr(predicted, target)[1]
    130
    131  else:
    132      # slower(?) and bogus(p-value) implementations for non-scipy users
    133      # TODO: implement them more or less correcly with numpy
    134      #       functionality
    135 -    class CorrErrorFx(_ErrorFx):
    136          """Computes the correlation between the target and the predicted
    137          values. Return 1-CC
    138
    139          """
    140 -        def __call__(self, predicted, target):
    141              """Requires all arguments."""
    142              l = len(predicted)
    143              return 1.0 - N.corrcoef(N.reshape(predicted, l),
    144                                  N.reshape(target, l))[0,1]
    145
    146
    147 -    class CorrErrorPFx(_ErrorFx):
    148          """Computes p-value of correlation between the target and the predicted
    149          values.
    150
    151          """
    152 -        def __call__(self, predicted, target):
    153              """Requires all arguments."""
    154              from mvpa.base import warning
    155              warning("p-value for correlation is implemented only when scipy is "
    156                      "available. Bogus value -1.0 is returned otherwise")
    157              return -1.0
    158
    159
    160 -class RelativeRMSErrorFx(_ErrorFx):
    161      """Ratio between RMSE and root mean power of target output.
    162
    163      So it can be considered as a scaled RMSE -- perfect reconstruction
    164      has values near 0, while no reconstruction has values around 1.0.
    165      Word of caution -- it is not commutative, ie exchange of predicted
    166      and target might lead to completely different answers
    167      """
    168 -    def __call__(self, predicted, target):
    169          return RMSErrorFx()(predicted, target) / rootMeanPowerFx(target)
    170
    171
    172 -class Variance1SVFx(_ErrorFx):
    173      """Ratio of variance described by the first singular value component.
    174
    175      Of limited use -- left for the sake of not wasting it
    176      """
    177
    178 -    def __call__(self, predicted, target):
    179          data = N.vstack( (predicted, target) ).T
    180          # demean
    181          data_demeaned = data - N.mean(data, axis=0)
    182          u, s, vh = N.linalg.svd(data_demeaned, full_matrices=0)
    183          # assure sorting
    184          s.sort()
    185          s=s[::-1]
    186          cvar = s[0]**2 / N.sum(s**2)
    187          return cvar
    188