module Metrics ( ae , se , sle , mae , mse , msle , rmse , rmsle , ll , logLoss , apk , mapk , auc, fstEqual, auc1, sumRank, sumEl , ce ) where import Data.List (groupBy, sort) import Math.Statistics (mean) ae :: Num a => a -> a -> a ae x y = abs (x-y) se :: Num a => a -> a -> a se x y = (x-y)^2 sle :: Double -> Double -> Double sle x y = ((log (x+1)) - (log (y+1)))^2 infinity :: Double infinity = -(log 0) meanZipWith :: (a -> b -> Double) -> [a] -> [b] -> Double meanZipWith = ((mean .) .) . zipWith meanInfZipWith :: (a -> b -> Double) -> [a] -> [b] -> Double meanInfZipWith f a1 a2 | any (==infinity) (zipWith f a1 a2) = infinity | otherwise = meanZipWith f a1 a2 mae :: [Double] -> [Double] -> Double mae = meanZipWith ae mse :: [Double] -> [Double] -> Double mse = meanZipWith se msle :: [Double] -> [Double] -> Double msle = meanZipWith sle rmse :: [Double] -> [Double] -> Double rmse = (sqrt .) . mse rmsle :: [Double] -> [Double] -> Double rmsle = (sqrt .) . msle ll :: Double -> Double -> Double ll 1 y = -log y ll 0 y = -log (1-y) logLoss :: [Double] -> [Double] -> Double logLoss = meanInfZipWith ll apk :: Int -> [Integer] -> [Integer] -> Double apk k actual predicted = (apsum actual (take k predicted) [] 0.0 0.0 0.0) / (fromIntegral (min k (length actual))) where apsum _ [] _ acc _ _ = acc apsum actual (p:ps) visited acc i j | (elem p actual) && (not (elem p visited)) = apsum actual ps (p:visited) (acc+(i+1.0)/(j+1.0)) (i+1.0) (j+1.0) | otherwise = apsum actual ps visited acc i (j+1.0) mapk :: Int -> [[Integer]] -> [[Integer]] -> Double mapk k = meanZipWith (apk k) auc :: [Double] -> [Double] -> Double auc a p = ((sumRank a p) - (sumEl 1 a)*(((sumEl 1 a)+1)/2.0)) / ((sumEl 1 a)*(sumEl 0 a)) fstEqual x y = (fst x) == (fst y) auc1 actual predicted = groupBy fstEqual (sort (zip predicted actual)) sumRank actual predicted = sumRankAccum (auc1 actual predicted) 0.0 0 where sumRankAccum [] rSum r = rSum sumRankAccum (x:xs) rSum r = sumRankAccum xs (rSum+curPos*(r+curRank)) (r+curRank) where curRank = (fromIntegral (1+(length x))) / 2.0 curPos = sum [1.0 | el <- x, (snd el)==1] sumEl el a = fromIntegral (length (filter (==el) a)) ce :: Eq a => [a] -> [a] -> Double ce actual predicted = ((sum [1.0 | (a,p) <- (zip actual predicted), a/=p]) / (fromIntegral (length actual)))