module BioInf.PassiveAggressive where
import Control.Arrow
import Control.DeepSeq
import Control.Parallel (pseq)
import Data.List as L
import Data.Map as M
import Data.Set as S
import qualified Data.Vector.Unboxed as VU
import Text.Printf
import Biobase.TrainingData
import BioInf.Keys
import qualified BioInf.Params as P
import qualified BioInf.Params.Export as P
import qualified BioInf.Params.Import as P
import Statistics.ConfusionMatrix
import Statistics.PerformanceMetrics
defaultPA :: Double -> P.Params -> TrainingData -> PA
defaultPA aggressiveness params td@TrainingData{..}
| L.null $ pOnly++kOnly = PA
{ changes = []
, enerDif = edif
, accMeas = struc
, errors = []
}
| struc >= 0.999 = PA
{ changes = []
, enerDif = edif
, accMeas = struc
, errors = []
}
| otherwise = PA
{ changes = changes
, enerDif = edif
, accMeas = struc
, errors = eError
}
where
pFeatures = featureVector primary predicted
kFeatures = featureVector primary secondary
pOnly = pFeatures L.\\ kFeatures
kOnly = kFeatures L.\\ pFeatures
numChanges = genericLength $ pOnly ++ kOnly
changes = zip kOnly (repeat $ negate tau) ++ zip pOnly (repeat tau)
cur = VU.fromList . P.toList $ params
pScore = sum . L.map (cur VU.!) $ pFeatures
kScore = sum . L.map (cur VU.!) $ kFeatures
edif = kScore pScore
eError = if edif <= 0
then []
else ["S(known) < S(predicted)\n" ++ errorKnownTooGood td cur kFeatures pFeatures]
struc = case fmeasure (mkConfusionMatrix td) of
Left _ -> 1
Right v -> v
tau = min aggressiveness $ ( (min 0 $ kScore pScore) + sqrt (1struc)
) / (numChanges ^ 2)
errorKnownTooGood TrainingData{..} curPs kFeatures pFeatures = z where
z = printf "S(known) = %7.4f, S(pred) = %7.4f, S(known) - S(pred) = %7.4f\n"
kScore pScore (kScore pScore)
++ printf "%s\n%s\n" primary (concat $ intersperse "\n" comments)
kScore = sum . L.map (curPs VU.!) $ kFeatures
pScore = sum . L.map (curPs VU.!) $ pFeatures
data PA = PA
{ changes :: [(Int,Double)]
, enerDif :: Double
, accMeas :: Double
, errors :: [String]
} deriving (Show)
instance NFData PA where
rnf PA{..} = rnf changes `pseq` rnf enerDif `pseq` rnf accMeas `pseq` rnf errors
instance MkConfusionMatrix TrainingData where
mkConfusionMatrix TrainingData{..} = ConfusionMatrix
{ fn = Right . fromIntegral . S.size $ k `S.difference` p
, fp = Right . fromIntegral . S.size $ p `S.difference` k
, tn = Right . fromIntegral $ allPs S.size (k `S.union` p)
, tp = Right . fromIntegral . S.size $ k `S.intersection` p
} where
k = S.fromList secondary
p = S.fromList predicted
allPs = ((length primary) * (length primary 1)) `div` 2