packages feed

som 7.5.0 → 8.0.0

raw patch · 14 files changed

+607/−696 lines, 14 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Data.Datamining.Clustering.DSOM: customDSOM :: gm p -> (Metric p -> Metric p -> Metric p -> Metric p) -> DSOM gm k p
- Data.Datamining.Clustering.DSOM: defaultDSOM :: (Eq (Metric p), Ord (Metric p), Floating (Metric p)) => gm p -> Metric p -> Metric p -> DSOM gm k p
- Data.Datamining.Clustering.DSOMInternal: customDSOM :: gm p -> (Metric p -> Metric p -> Metric p -> Metric p) -> DSOM gm k p
- Data.Datamining.Clustering.DSOMInternal: defaultDSOM :: (Eq (Metric p), Ord (Metric p), Floating (Metric p)) => gm p -> Metric p -> Metric p -> DSOM gm k p
- Data.Datamining.Clustering.DSOMInternal: instance (Foldable gm, GridMap gm p, FiniteGrid (BaseGrid gm p)) => GridMap (DSOM gm k) p
- Data.Datamining.Clustering.DSOMInternal: instance (GridMap gm p, k ~ Index (BaseGrid gm p), Pattern p, FiniteGrid (gm p), GridMap gm (Metric p), k ~ Index (gm p), k ~ Index (BaseGrid gm (Metric p)), Ord k, Ord (Metric p), Num (Metric p), Fractional (Metric p)) => Classifier (DSOM gm) k p
- Data.Datamining.Clustering.DSOMInternal: instance Foldable gm => Foldable (DSOM gm k)
- Data.Datamining.Clustering.DSOMInternal: instance Grid (gm p) => Grid (DSOM gm k p)
- Data.Datamining.Clustering.DSOMInternal: sGridMap :: DSOM gm k p -> gm p
- Data.Datamining.Clustering.DSOMInternal: sLearningFunction :: DSOM gm k p -> (Metric p -> Metric p -> Metric p -> Metric p)
- Data.Datamining.Clustering.SOM: DecayingGaussian :: a -> a -> a -> a -> a -> DecayingGaussian a
- Data.Datamining.Clustering.SOM: data DecayingGaussian a
- Data.Datamining.Clustering.SOM: learningFunction :: SOM f t gm k p -> f
- Data.Datamining.Clustering.SOMInternal: ConstantFunction :: a -> ConstantFunction a
- Data.Datamining.Clustering.SOMInternal: DecayingGaussian :: a -> a -> a -> a -> a -> DecayingGaussian a
- Data.Datamining.Clustering.SOMInternal: StepFunction :: a -> StepFunction a
- Data.Datamining.Clustering.SOMInternal: class LearningFunction f where type family LearningRate f
- Data.Datamining.Clustering.SOMInternal: data ConstantFunction a
- Data.Datamining.Clustering.SOMInternal: data DecayingGaussian a
- Data.Datamining.Clustering.SOMInternal: data StepFunction a
- Data.Datamining.Clustering.SOMInternal: instance (Eq f, Eq t, Eq (gm p)) => Eq (SOM f t gm k p)
- Data.Datamining.Clustering.SOMInternal: instance (Floating a, Fractional a, Num a) => LearningFunction (DecayingGaussian a)
- Data.Datamining.Clustering.SOMInternal: instance (Foldable gm, GridMap gm p, Grid (BaseGrid gm p)) => GridMap (SOM f t gm k) p
- Data.Datamining.Clustering.SOMInternal: instance (Fractional a, Eq a) => LearningFunction (StepFunction a)
- Data.Datamining.Clustering.SOMInternal: instance (GridMap gm p, k ~ Index (BaseGrid gm p), Pattern p, Grid (gm p), GridMap gm (Metric p), k ~ Index (gm p), k ~ Index (BaseGrid gm (Metric p)), Ord (Metric p), LearningFunction f, Metric p ~ LearningRate f, Num (LearningRate f), Integral t) => Classifier (SOM f t gm) k p
- Data.Datamining.Clustering.SOMInternal: instance (Show f, Show t, Show (gm p)) => Show (SOM f t gm k p)
- Data.Datamining.Clustering.SOMInternal: instance Constructor C1_0ConstantFunction
- Data.Datamining.Clustering.SOMInternal: instance Constructor C1_0DecayingGaussian
- Data.Datamining.Clustering.SOMInternal: instance Constructor C1_0StepFunction
- Data.Datamining.Clustering.SOMInternal: instance Datatype D1ConstantFunction
- Data.Datamining.Clustering.SOMInternal: instance Datatype D1DecayingGaussian
- Data.Datamining.Clustering.SOMInternal: instance Datatype D1StepFunction
- Data.Datamining.Clustering.SOMInternal: instance Eq a => Eq (ConstantFunction a)
- Data.Datamining.Clustering.SOMInternal: instance Eq a => Eq (DecayingGaussian a)
- Data.Datamining.Clustering.SOMInternal: instance Eq a => Eq (StepFunction a)
- Data.Datamining.Clustering.SOMInternal: instance Foldable gm => Foldable (SOM f t gm k)
- Data.Datamining.Clustering.SOMInternal: instance Fractional a => LearningFunction (ConstantFunction a)
- Data.Datamining.Clustering.SOMInternal: instance Generic (ConstantFunction a)
- Data.Datamining.Clustering.SOMInternal: instance Generic (DecayingGaussian a)
- Data.Datamining.Clustering.SOMInternal: instance Generic (SOM f t gm k p)
- Data.Datamining.Clustering.SOMInternal: instance Generic (StepFunction a)
- Data.Datamining.Clustering.SOMInternal: instance Grid (gm p) => Grid (SOM f t gm k p)
- Data.Datamining.Clustering.SOMInternal: instance Show a => Show (ConstantFunction a)
- Data.Datamining.Clustering.SOMInternal: instance Show a => Show (DecayingGaussian a)
- Data.Datamining.Clustering.SOMInternal: instance Show a => Show (StepFunction a)
- Data.Datamining.Clustering.SOMInternal: learningFunction :: SOM f t gm k p -> f
- Data.Datamining.Clustering.SOMInternal: rate :: LearningFunction f => f -> LearningRate f -> LearningRate f -> LearningRate f
- Data.Datamining.Clustering.SSOM: Exponential :: a -> a -> Exponential a
- Data.Datamining.Clustering.SSOM: data Exponential a
- Data.Datamining.Clustering.SSOM: learningFunction :: SSOM f t k p -> f
- Data.Datamining.Clustering.SSOMInternal: Exponential :: a -> a -> Exponential a
- Data.Datamining.Clustering.SSOMInternal: class LearningFunction f where type family LearningRate f
- Data.Datamining.Clustering.SSOMInternal: data Exponential a
- Data.Datamining.Clustering.SSOMInternal: instance (Eq f, Eq t, Eq k, Eq p) => Eq (SSOM f t k p)
- Data.Datamining.Clustering.SSOMInternal: instance (Floating a, Fractional a, Num a) => LearningFunction (Exponential a)
- Data.Datamining.Clustering.SSOMInternal: instance (Pattern p, Ord (Metric p), LearningFunction f, Metric p ~ LearningRate f, Num (LearningRate f), Ord k, Integral t) => Classifier (SSOM f t) k p
- Data.Datamining.Clustering.SSOMInternal: instance (Show f, Show t, Show k, Show p) => Show (SSOM f t k p)
- Data.Datamining.Clustering.SSOMInternal: instance Constructor C1_0Exponential
- Data.Datamining.Clustering.SSOMInternal: instance Datatype D1Exponential
- Data.Datamining.Clustering.SSOMInternal: instance Eq a => Eq (Exponential a)
- Data.Datamining.Clustering.SSOMInternal: instance Generic (Exponential a)
- Data.Datamining.Clustering.SSOMInternal: instance Generic (SSOM f t k p)
- Data.Datamining.Clustering.SSOMInternal: instance Show a => Show (Exponential a)
- Data.Datamining.Clustering.SSOMInternal: learningFunction :: SSOM f t k p -> f
- Data.Datamining.Clustering.SSOMInternal: rate :: LearningFunction f => f -> LearningRate f -> LearningRate f
- Data.Datamining.Pattern: class Pattern p where type family Metric p
- Data.Datamining.Pattern: difference :: Pattern p => p -> p -> Metric p
- Data.Datamining.Pattern: instance (Floating a, Fractional a, Ord a, Eq a) => Pattern (NormalisedVector a)
- Data.Datamining.Pattern: instance (Fractional a, Ord a, Eq a) => Pattern (ScaledVector a)
- Data.Datamining.Pattern: makeSimilar :: Pattern p => p -> Metric p -> p -> p
+ Data.Datamining.Clustering.DSOM: DSOM :: gm p -> (x -> x -> x -> x) -> (p -> p -> x) -> (p -> x -> p -> p) -> DSOM gm x k p
+ Data.Datamining.Clustering.DSOM: difference :: DSOM gm x k p -> p -> p -> x
+ Data.Datamining.Clustering.DSOM: gridMap :: DSOM gm x k p -> gm p
+ Data.Datamining.Clustering.DSOM: learningRate :: DSOM gm x k p -> (x -> x -> x -> x)
+ Data.Datamining.Clustering.DSOM: makeSimilar :: DSOM gm x k p -> p -> x -> p -> p
+ Data.Datamining.Clustering.DSOMInternal: difference :: DSOM gm x k p -> p -> p -> x
+ Data.Datamining.Clustering.DSOMInternal: gridMap :: DSOM gm x k p -> gm p
+ Data.Datamining.Clustering.DSOMInternal: instance (Foldable gm, GridMap gm p, FiniteGrid (BaseGrid gm p)) => GridMap (DSOM gm x k) p
+ Data.Datamining.Clustering.DSOMInternal: instance (GridMap gm p, k ~ Index (BaseGrid gm p), FiniteGrid (gm p), GridMap gm x, k ~ Index (gm p), k ~ Index (gm x), k ~ Index (BaseGrid gm x), Ord k, Ord x, Num x, Fractional x) => Classifier (DSOM gm) x k p
+ Data.Datamining.Clustering.DSOMInternal: instance Foldable gm => Foldable (DSOM gm x k)
+ Data.Datamining.Clustering.DSOMInternal: instance Grid (gm p) => Grid (DSOM gm x k p)
+ Data.Datamining.Clustering.DSOMInternal: learningRate :: DSOM gm x k p -> (x -> x -> x -> x)
+ Data.Datamining.Clustering.DSOMInternal: makeSimilar :: DSOM gm x k p -> p -> x -> p -> p
+ Data.Datamining.Clustering.SOM: constantFunction :: x -> t -> d -> x
+ Data.Datamining.Clustering.SOM: decayingGaussian :: Floating x => x -> x -> x -> x -> x -> x -> x -> x
+ Data.Datamining.Clustering.SOM: difference :: SOM t d gm x k p -> p -> p -> x
+ Data.Datamining.Clustering.SOM: learningRate :: SOM t d gm x k p -> t -> d -> x
+ Data.Datamining.Clustering.SOM: makeSimilar :: SOM t d gm x k p -> p -> x -> p -> p
+ Data.Datamining.Clustering.SOM: stepFunction :: (Num d, Fractional x, Eq d) => x -> t -> d -> x
+ Data.Datamining.Clustering.SOMInternal: constantFunction :: x -> t -> d -> x
+ Data.Datamining.Clustering.SOMInternal: decayingGaussian :: Floating x => x -> x -> x -> x -> x -> x -> x -> x
+ Data.Datamining.Clustering.SOMInternal: difference :: SOM t d gm x k p -> p -> p -> x
+ Data.Datamining.Clustering.SOMInternal: instance (Foldable gm, GridMap gm p, Grid (BaseGrid gm p)) => GridMap (SOM t d gm x k) p
+ Data.Datamining.Clustering.SOMInternal: instance (GridMap gm p, k ~ Index (BaseGrid gm p), Grid (gm p), GridMap gm x, k ~ Index (gm p), k ~ Index (BaseGrid gm x), Num t, Ord x, Num x, Num d) => Classifier (SOM t d gm) x k p
+ Data.Datamining.Clustering.SOMInternal: instance Foldable gm => Foldable (SOM t d gm x k)
+ Data.Datamining.Clustering.SOMInternal: instance Generic (SOM t d gm x k p)
+ Data.Datamining.Clustering.SOMInternal: instance Grid (gm p) => Grid (SOM t d gm x k p)
+ Data.Datamining.Clustering.SOMInternal: instance Selector S1_0_3SOM
+ Data.Datamining.Clustering.SOMInternal: instance Selector S1_0_4SOM
+ Data.Datamining.Clustering.SOMInternal: learningRate :: SOM t d gm x k p -> t -> d -> x
+ Data.Datamining.Clustering.SOMInternal: makeSimilar :: SOM t d gm x k p -> p -> x -> p -> p
+ Data.Datamining.Clustering.SOMInternal: stepFunction :: (Num d, Fractional x, Eq d) => x -> t -> d -> x
+ Data.Datamining.Clustering.SSOM: difference :: SSOM t x k p -> p -> p -> x
+ Data.Datamining.Clustering.SSOM: exponential :: Floating a => a -> a -> a -> a
+ Data.Datamining.Clustering.SSOM: learningRate :: SSOM t x k p -> t -> x
+ Data.Datamining.Clustering.SSOM: makeSimilar :: SSOM t x k p -> p -> x -> p -> p
+ Data.Datamining.Clustering.SSOMInternal: difference :: SSOM t x k p -> p -> p -> x
+ Data.Datamining.Clustering.SSOMInternal: exponential :: Floating a => a -> a -> a -> a
+ Data.Datamining.Clustering.SSOMInternal: instance (Num t, Ord x, Num x, Ord k) => Classifier (SSOM t) x k p
+ Data.Datamining.Clustering.SSOMInternal: instance Generic (SSOM t x k p)
+ Data.Datamining.Clustering.SSOMInternal: instance Selector S1_0_3SSOM
+ Data.Datamining.Clustering.SSOMInternal: instance Selector S1_0_4SSOM
+ Data.Datamining.Clustering.SSOMInternal: learningRate :: SSOM t x k p -> t -> x
+ Data.Datamining.Clustering.SSOMInternal: makeSimilar :: SSOM t x k p -> p -> x -> p -> p
- Data.Datamining.Clustering.Classifier: class Classifier (c :: * -> * -> *) k p where classify c p = f $ differences c p where f [] = error "classifier has no models" f xs = fst $ minimumBy (comparing snd) xs train c p = c' where (_, _, c') = reportAndTrain c p classifyAndTrain c p = (bmu, c') where (bmu, _, c') = reportAndTrain c p diffAndTrain c p = (ds, c') where (_, ds, c') = reportAndTrain c p
+ Data.Datamining.Clustering.Classifier: class Classifier (c :: * -> * -> * -> *) v k p where classify c p = f $ differences c p where f [] = error "classifier has no models" f xs = fst $ minimumBy (comparing snd) xs train c p = c' where (_, _, c') = reportAndTrain c p classifyAndTrain c p = (bmu, c') where (bmu, _, c') = reportAndTrain c p diffAndTrain c p = (ds, c') where (_, ds, c') = reportAndTrain c p
- Data.Datamining.Clustering.Classifier: classify :: (Classifier c k p, Pattern p, Ord v, v ~ Metric p) => c k p -> p -> k
+ Data.Datamining.Clustering.Classifier: classify :: (Classifier c v k p, Ord v) => c v k p -> p -> k
- Data.Datamining.Clustering.Classifier: classifyAndTrain :: (Classifier c k p, Ord v, v ~ Metric p) => c k p -> p -> (k, c k p)
+ Data.Datamining.Clustering.Classifier: classifyAndTrain :: Classifier c v k p => c v k p -> p -> (k, c v k p)
- Data.Datamining.Clustering.Classifier: diffAndTrain :: (Classifier c k p, Ord v, v ~ Metric p) => c k p -> p -> ([(k, v)], c k p)
+ Data.Datamining.Clustering.Classifier: diffAndTrain :: Classifier c v k p => c v k p -> p -> ([(k, v)], c v k p)
- Data.Datamining.Clustering.Classifier: differences :: (Classifier c k p, Pattern p, v ~ Metric p) => c k p -> p -> [(k, v)]
+ Data.Datamining.Clustering.Classifier: differences :: Classifier c v k p => c v k p -> p -> [(k, v)]
- Data.Datamining.Clustering.Classifier: models :: Classifier c k p => c k p -> [p]
+ Data.Datamining.Clustering.Classifier: models :: Classifier c v k p => c v k p -> [p]
- Data.Datamining.Clustering.Classifier: numModels :: Classifier c k p => c k p -> Int
+ Data.Datamining.Clustering.Classifier: numModels :: Classifier c v k p => c v k p -> Int
- Data.Datamining.Clustering.Classifier: reportAndTrain :: (Classifier c k p, Ord v, v ~ Metric p) => c k p -> p -> (k, [(k, v)], c k p)
+ Data.Datamining.Clustering.Classifier: reportAndTrain :: Classifier c v k p => c v k p -> p -> (k, [(k, v)], c v k p)
- Data.Datamining.Clustering.Classifier: toList :: Classifier c k p => c k p -> [(k, p)]
+ Data.Datamining.Clustering.Classifier: toList :: Classifier c v k p => c v k p -> [(k, p)]
- Data.Datamining.Clustering.Classifier: train :: (Classifier c k p, Ord v, v ~ Metric p) => c k p -> p -> c k p
+ Data.Datamining.Clustering.Classifier: train :: Classifier c v k p => c v k p -> p -> c v k p
- Data.Datamining.Clustering.Classifier: trainBatch :: Classifier c k p => c k p -> [p] -> c k p
+ Data.Datamining.Clustering.Classifier: trainBatch :: Classifier c v k p => c v k p -> [p] -> c v k p
- Data.Datamining.Clustering.DSOM: data DSOM gm k p
+ Data.Datamining.Clustering.DSOM: data DSOM gm x k p
- Data.Datamining.Clustering.DSOM: toGridMap :: GridMap gm p => DSOM gm k p -> gm p
+ Data.Datamining.Clustering.DSOM: toGridMap :: GridMap gm p => DSOM gm x k p -> gm p
- Data.Datamining.Clustering.DSOM: trainNeighbourhood :: (Pattern p, FiniteGrid (gm p), GridMap gm p, Num (Metric p), Ord k, k ~ Index (gm p), k ~ Index (BaseGrid gm p), Fractional (Metric p)) => DSOM gm t p -> k -> p -> DSOM gm k p
+ Data.Datamining.Clustering.DSOM: trainNeighbourhood :: (FiniteGrid (gm p), GridMap gm p, k ~ Index (gm p), k ~ Index (BaseGrid gm p), Ord k, Num x, Fractional x) => DSOM gm x t p -> k -> p -> DSOM gm x k p
- Data.Datamining.Clustering.DSOMInternal: DSOM :: gm p -> (Metric p -> Metric p -> Metric p -> Metric p) -> DSOM gm k p
+ Data.Datamining.Clustering.DSOMInternal: DSOM :: gm p -> (x -> x -> x -> x) -> (p -> p -> x) -> (p -> x -> p -> p) -> DSOM gm x k p
- Data.Datamining.Clustering.DSOMInternal: adjustNode :: (Pattern p, FiniteGrid (gm p), GridMap gm p, k ~ Index (gm p), Ord k, k ~ Index (BaseGrid gm p), Num (Metric p), Fractional (Metric p)) => gm p -> (Metric p -> Metric p -> Metric p) -> p -> k -> k -> p -> p
+ Data.Datamining.Clustering.DSOMInternal: adjustNode :: (FiniteGrid (gm p), GridMap gm p, k ~ Index (gm p), k ~ Index (BaseGrid gm p), Ord k, Num x, Fractional x) => gm p -> (p -> x -> p -> p) -> (p -> p -> x) -> (x -> x -> x) -> p -> k -> k -> (p -> p)
- Data.Datamining.Clustering.DSOMInternal: data DSOM gm k p
+ Data.Datamining.Clustering.DSOMInternal: data DSOM gm x k p
- Data.Datamining.Clustering.DSOMInternal: justTrain :: (Pattern p, FiniteGrid (gm p), GridMap gm p, Num (Metric p), Ord (Metric p), Ord (Index (gm p)), GridMap gm (Metric p), Fractional (Metric p), Index (BaseGrid gm (Metric p)) ~ Index (gm p), Index (BaseGrid gm p) ~ Index (gm p)) => DSOM gm t p -> p -> DSOM gm (Index (gm p)) p
+ Data.Datamining.Clustering.DSOMInternal: justTrain :: (FiniteGrid (gm p), GridMap gm p, GridMap gm x, k ~ Index (gm p), k ~ Index (gm x), k ~ Index (BaseGrid gm p), k ~ Index (BaseGrid gm x), Ord k, Ord x, Num x, Fractional x) => DSOM gm x t p -> p -> DSOM gm x k p
- Data.Datamining.Clustering.DSOMInternal: toGridMap :: GridMap gm p => DSOM gm k p -> gm p
+ Data.Datamining.Clustering.DSOMInternal: toGridMap :: GridMap gm p => DSOM gm x k p -> gm p
- Data.Datamining.Clustering.DSOMInternal: trainNeighbourhood :: (Pattern p, FiniteGrid (gm p), GridMap gm p, Num (Metric p), Ord k, k ~ Index (gm p), k ~ Index (BaseGrid gm p), Fractional (Metric p)) => DSOM gm t p -> k -> p -> DSOM gm k p
+ Data.Datamining.Clustering.DSOMInternal: trainNeighbourhood :: (FiniteGrid (gm p), GridMap gm p, k ~ Index (gm p), k ~ Index (BaseGrid gm p), Ord k, Num x, Fractional x) => DSOM gm x t p -> k -> p -> DSOM gm x k p
- Data.Datamining.Clustering.DSOMInternal: withGridMap :: (gm p -> gm p) -> DSOM gm k p -> DSOM gm k p
+ Data.Datamining.Clustering.DSOMInternal: withGridMap :: (gm p -> gm p) -> DSOM gm x k p -> DSOM gm x k p
- Data.Datamining.Clustering.SOM: SOM :: gm p -> f -> t -> SOM f t gm k p
+ Data.Datamining.Clustering.SOM: SOM :: gm p -> (t -> d -> x) -> (p -> p -> x) -> (p -> x -> p -> p) -> t -> SOM t d gm x k p
- Data.Datamining.Clustering.SOM: counter :: SOM f t gm k p -> t
+ Data.Datamining.Clustering.SOM: counter :: SOM t d gm x k p -> t
- Data.Datamining.Clustering.SOM: data SOM f t gm k p
+ Data.Datamining.Clustering.SOM: data SOM t d gm x k p
- Data.Datamining.Clustering.SOM: gridMap :: SOM f t gm k p -> gm p
+ Data.Datamining.Clustering.SOM: gridMap :: SOM t d gm x k p -> gm p
- Data.Datamining.Clustering.SOM: toGridMap :: GridMap gm p => SOM f t gm k p -> gm p
+ Data.Datamining.Clustering.SOM: toGridMap :: GridMap gm p => SOM t d gm x k p -> gm p
- Data.Datamining.Clustering.SOM: trainNeighbourhood :: (Pattern p, Grid (gm p), GridMap gm p, Index (BaseGrid gm p) ~ Index (gm p), LearningFunction f, Metric p ~ LearningRate f, Num (LearningRate f), Integral t) => SOM f t gm k p -> Index (gm p) -> p -> SOM f t gm k p
+ Data.Datamining.Clustering.SOM: trainNeighbourhood :: (Grid (gm p), GridMap gm p, Index (BaseGrid gm p) ~ Index (gm p), Num t, Num x, Num d) => SOM t d gm x k p -> Index (gm p) -> p -> SOM t d gm x k p
- Data.Datamining.Clustering.SOMInternal: SOM :: gm p -> f -> t -> SOM f t gm k p
+ Data.Datamining.Clustering.SOMInternal: SOM :: gm p -> (t -> d -> x) -> (p -> p -> x) -> (p -> x -> p -> p) -> t -> SOM t d gm x k p
- Data.Datamining.Clustering.SOMInternal: adjustNode :: (Pattern p, Grid g, k ~ Index g, Num t) => g -> (t -> Metric p) -> p -> k -> k -> p -> p
+ Data.Datamining.Clustering.SOMInternal: adjustNode :: (Grid g, k ~ Index g, Num t) => g -> (t -> x) -> (p -> x -> p -> p) -> p -> k -> k -> p -> p
- Data.Datamining.Clustering.SOMInternal: counter :: SOM f t gm k p -> t
+ Data.Datamining.Clustering.SOMInternal: counter :: SOM t d gm x k p -> t
- Data.Datamining.Clustering.SOMInternal: currentLearningFunction :: (LearningFunction f, Metric p ~ LearningRate f, Num (LearningRate f), Integral t) => SOM f t gm k p -> (LearningRate f -> Metric p)
+ Data.Datamining.Clustering.SOMInternal: currentLearningFunction :: Num t => SOM t d gm x k p -> (d -> x)
- Data.Datamining.Clustering.SOMInternal: data SOM f t gm k p
+ Data.Datamining.Clustering.SOMInternal: data SOM t d gm x k p
- Data.Datamining.Clustering.SOMInternal: gridMap :: SOM f t gm k p -> gm p
+ Data.Datamining.Clustering.SOMInternal: gridMap :: SOM t d gm x k p -> gm p
- Data.Datamining.Clustering.SOMInternal: incrementCounter :: Num t => SOM f t gm k p -> SOM f t gm k p
+ Data.Datamining.Clustering.SOMInternal: incrementCounter :: Num t => SOM t d gm x k p -> SOM t d gm x k p
- Data.Datamining.Clustering.SOMInternal: justTrain :: (Ord (Metric p), Pattern p, Grid (gm p), GridMap gm (Metric p), GridMap gm p, Index (BaseGrid gm (Metric p)) ~ Index (gm p), Index (BaseGrid gm p) ~ Index (gm p), LearningFunction f, Metric p ~ LearningRate f, Num (LearningRate f), Integral t) => SOM f t gm k p -> p -> SOM f t gm k p
+ Data.Datamining.Clustering.SOMInternal: justTrain :: (Ord x, Grid (gm p), GridMap gm x, GridMap gm p, Index (BaseGrid gm x) ~ Index (gm p), Index (BaseGrid gm p) ~ Index (gm p), Num t, Num x, Num d) => SOM t d gm x k p -> p -> SOM t d gm x k p
- Data.Datamining.Clustering.SOMInternal: toGridMap :: GridMap gm p => SOM f t gm k p -> gm p
+ Data.Datamining.Clustering.SOMInternal: toGridMap :: GridMap gm p => SOM t d gm x k p -> gm p
- Data.Datamining.Clustering.SOMInternal: trainNeighbourhood :: (Pattern p, Grid (gm p), GridMap gm p, Index (BaseGrid gm p) ~ Index (gm p), LearningFunction f, Metric p ~ LearningRate f, Num (LearningRate f), Integral t) => SOM f t gm k p -> Index (gm p) -> p -> SOM f t gm k p
+ Data.Datamining.Clustering.SOMInternal: trainNeighbourhood :: (Grid (gm p), GridMap gm p, Index (BaseGrid gm p) ~ Index (gm p), Num t, Num x, Num d) => SOM t d gm x k p -> Index (gm p) -> p -> SOM t d gm x k p
- Data.Datamining.Clustering.SOMInternal: withGridMap :: (gm p -> gm p) -> SOM f t gm k p -> SOM f t gm k p
+ Data.Datamining.Clustering.SOMInternal: withGridMap :: (gm p -> gm p) -> SOM t d gm x k p -> SOM t d gm x k p
- Data.Datamining.Clustering.SSOM: SSOM :: Map k p -> f -> t -> SSOM f t k p
+ Data.Datamining.Clustering.SSOM: SSOM :: Map k p -> (t -> x) -> (p -> p -> x) -> (p -> x -> p -> p) -> t -> SSOM t x k p
- Data.Datamining.Clustering.SSOM: counter :: SSOM f t k p -> t
+ Data.Datamining.Clustering.SSOM: counter :: SSOM t x k p -> t
- Data.Datamining.Clustering.SSOM: data SSOM f t k p
+ Data.Datamining.Clustering.SSOM: data SSOM t x k p
- Data.Datamining.Clustering.SSOM: sMap :: SSOM f t k p -> Map k p
+ Data.Datamining.Clustering.SSOM: sMap :: SSOM t x k p -> Map k p
- Data.Datamining.Clustering.SSOM: toMap :: SSOM f t k p -> Map k p
+ Data.Datamining.Clustering.SSOM: toMap :: SSOM t x k p -> Map k p
- Data.Datamining.Clustering.SSOM: trainNode :: (Pattern p, LearningFunction f, Metric p ~ LearningRate f, Num (LearningRate f), Ord k, Integral t) => SSOM f t k p -> k -> p -> SSOM f t k p
+ Data.Datamining.Clustering.SSOM: trainNode :: (Num t, Ord k) => SSOM t x k p -> k -> p -> SSOM t x k p
- Data.Datamining.Clustering.SSOMInternal: SSOM :: Map k p -> f -> t -> SSOM f t k p
+ Data.Datamining.Clustering.SSOMInternal: SSOM :: Map k p -> (t -> x) -> (p -> p -> x) -> (p -> x -> p -> p) -> t -> SSOM t x k p
- Data.Datamining.Clustering.SSOMInternal: counter :: SSOM f t k p -> t
+ Data.Datamining.Clustering.SSOMInternal: counter :: SSOM t x k p -> t
- Data.Datamining.Clustering.SSOMInternal: data SSOM f t k p
+ Data.Datamining.Clustering.SSOMInternal: data SSOM t x k p
- Data.Datamining.Clustering.SSOMInternal: incrementCounter :: Num t => SSOM f t k p -> SSOM f t k p
+ Data.Datamining.Clustering.SSOMInternal: incrementCounter :: Num t => SSOM t x k p -> SSOM t x k p
- Data.Datamining.Clustering.SSOMInternal: justTrain :: (Ord (Metric p), Pattern p, LearningFunction f, Metric p ~ LearningRate f, Num (LearningRate f), Ord k, Integral t) => SSOM f t k p -> p -> SSOM f t k p
+ Data.Datamining.Clustering.SSOMInternal: justTrain :: (Num t, Ord k, Ord x) => SSOM t x k p -> p -> SSOM t x k p
- Data.Datamining.Clustering.SSOMInternal: sMap :: SSOM f t k p -> Map k p
+ Data.Datamining.Clustering.SSOMInternal: sMap :: SSOM t x k p -> Map k p
- Data.Datamining.Clustering.SSOMInternal: toMap :: SSOM f t k p -> Map k p
+ Data.Datamining.Clustering.SSOMInternal: toMap :: SSOM t x k p -> Map k p
- Data.Datamining.Clustering.SSOMInternal: trainNode :: (Pattern p, LearningFunction f, Metric p ~ LearningRate f, Num (LearningRate f), Ord k, Integral t) => SSOM f t k p -> k -> p -> SSOM f t k p
+ Data.Datamining.Clustering.SSOMInternal: trainNode :: (Num t, Ord k) => SSOM t x k p -> k -> p -> SSOM t x k p

Files

som.cabal view
@@ -1,5 +1,5 @@ Name:              som-Version:           7.5.0+Version:           8.0.0 Stability:         experimental Synopsis:          Self-Organising Maps. Description:       A Kohonen Self-organising Map (SOM) maps input patterns @@ -18,7 +18,7 @@ Category:          Math License:           BSD3 License-file:      LICENSE-Copyright:         (c) Amy de Buitléir 2010-2014+Copyright:         (c) Amy de Buitléir 2010-2015 Homepage:          https://github.com/mhwombat/som Bug-reports:       https://github.com/mhwombat/som/issues Author:            Amy de Buitléir@@ -33,7 +33,7 @@ source-repository this   type:     git   location: https://github.com/mhwombat/som.git-  tag:      7.5.0+  tag:      8.0.0   library
src/Data/Datamining/Clustering/Classifier.hs view
@@ -1,7 +1,7 @@ ------------------------------------------------------------------------ -- | -- Module      :  Data.Datamining.Clustering.Classifier--- Copyright   :  (c) Amy de Buitléir 2012-2014+-- Copyright   :  (c) Amy de Buitléir 2012-2015 -- License     :  BSD-style -- Maintainer  :  amy@nualeargais.ie -- Stability   :  experimental@@ -16,45 +16,42 @@     Classifier(..)   ) where -import Data.Datamining.Pattern (Pattern, Metric) import Data.List (minimumBy) import Data.Ord (comparing)  -- | A machine which learns to classify input patterns.  --   Minimal complete definition: @trainBatch@, @reportAndTrain@.-class Classifier (c :: * -> * -> *) k p where+class Classifier (c :: * -> * -> * -> *) v k p where   -- | Returns a list of index\/model pairs.-  toList :: c k p -> [(k, p)]+  toList :: c v k p -> [(k, p)]    -- | Returns the number of models this classifier can learn.-  numModels :: c k p -> Int+  numModels :: c v k p -> Int    -- | Returns the current models of the classifier.-  models :: c k p -> [p]+  models :: c v k p -> [p]    -- | @'differences' c target@ returns the indices of all nodes in    --   @c@, paired with the difference between @target@ and the    --   node's model.-  differences :: (Pattern p, v ~ Metric p) => c k p -> p -> [(k, v)]+  differences :: c v k p -> p -> [(k, v)]    -- | @classify c target@ returns the index of the node in @c@    --   whose model best matches the @target@.-  classify :: (Pattern p, Ord v, v ~ Metric p) => c k p -> p -> k+  classify :: Ord v => c v k p -> p -> k   classify c p = f $ differences c p     where f [] = error "classifier has no models"           f xs = fst $ minimumBy (comparing snd) xs    -- | @'train' c target@ returns a modified copy   --   of the classifier @c@ that has partially learned the @target@.-  train-    :: (Ord v, v ~ Metric p) => -      c k p -> p -> c k p+  train :: c v k p -> p -> c v k p   train c p = c'     where (_, _, c') = reportAndTrain c p    -- | @'trainBatch' c targets@ returns a modified copy   --   of the classifier @c@ that has partially learned the @targets@.-  trainBatch :: c k p -> [p] -> c k p+  trainBatch :: c v k p -> [p] -> c v k p    -- | @'classifyAndTrain' c target@ returns a tuple containing the   --   index of the node in @c@ whose model best matches the input@@ -63,9 +60,7 @@   --   may be faster than invoking @(p `classify` c, train c p)@, but    --   they   --   should give identical results.-  classifyAndTrain -    :: (Ord v, v ~ Metric p) => -      c k p -> p -> (k, c k p)+  classifyAndTrain :: c v k p -> p -> (k, c v k p)   classifyAndTrain c p = (bmu, c')     where (bmu, _, c') = reportAndTrain c p @@ -77,9 +72,7 @@   --   Invoking @diffAndTrain c p@ may be faster than invoking   --   @(p `diff` c, train c p)@, but they should give identical   --   results.-  diffAndTrain-    :: (Ord v, v ~ Metric p) => -      c k p -> p -> ([(k, v)], c k p)+  diffAndTrain :: c v k p -> p -> ([(k, v)], c v k p)   diffAndTrain c p = (ds, c')     where (_, ds, c') = reportAndTrain c p @@ -93,8 +86,6 @@   --   Invoking @diffAndTrain c p@ may be faster than invoking   --   @(p `diff` c, train c p)@, but they should give identical   --   results.-  reportAndTrain -    :: (Ord v, v ~ Metric p) => -      c k p -> p -> (k, [(k, v)], c k p)+  reportAndTrain :: c v k p -> p -> (k, [(k, v)], c v k p)  
src/Data/Datamining/Clustering/DSOM.hs view
@@ -1,7 +1,7 @@ ------------------------------------------------------------------------ -- | -- Module      :  Data.Datamining.Clustering.SOM--- Copyright   :  (c) Amy de Buitléir 2012-2014+-- Copyright   :  (c) Amy de Buitléir 2012-2015 -- License     :  BSD-style -- Maintainer  :  amy@nualeargais.ie -- Stability   :  experimental@@ -23,16 +23,13 @@ module Data.Datamining.Clustering.DSOM   (     -- * Construction-    DSOM,-    defaultDSOM,-    customDSOM,-    rougierLearningFunction,+    DSOM(..),     -- * Deconstruction     toGridMap,+    -- * Learning functions+    rougierLearningFunction,     -- * Advanced control     trainNeighbourhood   ) where -import Data.Datamining.Clustering.DSOMInternal (DSOM, defaultDSOM,-  customDSOM, rougierLearningFunction, toGridMap, trainNeighbourhood)-+import Data.Datamining.Clustering.DSOMInternal
src/Data/Datamining/Clustering/DSOMInternal.hs view
@@ -1,7 +1,7 @@ ------------------------------------------------------------------------ -- | -- Module      :  Data.Datamining.Clustering.DSOMInternal--- Copyright   :  (c) Amy de Buitléir 2012-2014+-- Copyright   :  (c) Amy de Buitléir 2012-2015 -- License     :  BSD-style -- Maintainer  :  amy@nualeargais.ie -- Stability   :  experimental@@ -21,7 +21,6 @@ import Data.Ord (comparing) import qualified Math.Geometry.Grid as G (Grid(..), FiniteGrid(..)) import qualified Math.Geometry.GridMap as GM (GridMap(..))-import Data.Datamining.Pattern (Pattern(..)) import Data.Datamining.Clustering.Classifier(Classifier(..)) import Prelude hiding (lookup) @@ -38,34 +37,52 @@ --      just return an @error@). It would be problematic to implement --      them because the input DSOM and the output DSOM would have to --      have the same @Metric@ type.-data DSOM gm k p = DSOM+data DSOM gm x k p = DSOM   {-    sGridMap :: gm p,-    sLearningFunction :: (Metric p -> Metric p -> Metric p -> Metric p)+    -- | Maps patterns to tiles in a regular grid.+    --   In the context of a SOM, the tiles are called "nodes"+    gridMap :: gm p,+    -- | A function which determines the how quickly the SOM learns.+    learningRate :: (x -> x -> x -> x),+    -- | A function which compares two patterns and returns a +    --   /non-negative/ numberrepresenting how different the patterns+    --   are.+    --   A result of @0@ indicates that the patterns are identical.+    difference :: p -> p -> x,+    -- | A function which updates models.+    --   If this function is @f@, then @f target amount pattern@ returns+    --   a modified copy of @pattern@ that is more similar to @target@+    --   than @pattern@ is.+    --   The magnitude of the adjustment is controlled by the @amount@+    --   parameter, which should be a number between 0 and 1.+    --   Larger values for @amount@ permit greater adjustments.+    --   If @amount@=1, the result should be identical to the @target@.+    --   If @amount@=0, the result should be the unmodified @pattern@.+    makeSimilar :: p -> x -> p -> p   } -instance (F.Foldable gm) => F.Foldable (DSOM gm k) where-  foldr f x g = F.foldr f x (sGridMap g)+instance (F.Foldable gm) => F.Foldable (DSOM gm x k) where+  foldr f x g = F.foldr f x (gridMap g) -instance (G.Grid (gm p)) => G.Grid (DSOM gm k p) where-  type Index (DSOM gm k p) = G.Index (gm p)-  type Direction (DSOM gm k p) = G.Direction (gm p)-  indices = G.indices . sGridMap-  distance = G.distance . sGridMap-  neighbours = G.neighbours . sGridMap-  contains = G.contains . sGridMap-  viewpoint = G.viewpoint . sGridMap-  directionTo = G.directionTo . sGridMap-  tileCount = G.tileCount . sGridMap-  null = G.null . sGridMap-  nonNull = G.nonNull . sGridMap+instance (G.Grid (gm p)) => G.Grid (DSOM gm x k p) where+  type Index (DSOM gm x k p) = G.Index (gm p)+  type Direction (DSOM gm x k p) = G.Direction (gm p)+  indices = G.indices . gridMap+  distance = G.distance . gridMap+  neighbours = G.neighbours . gridMap+  contains = G.contains . gridMap+  viewpoint = G.viewpoint . gridMap+  directionTo = G.directionTo . gridMap+  tileCount = G.tileCount . gridMap+  null = G.null . gridMap+  nonNull = G.nonNull . gridMap  instance   (F.Foldable gm, GM.GridMap gm p, G.FiniteGrid (GM.BaseGrid gm p)) =>-    GM.GridMap (DSOM gm k) p where-  type BaseGrid (DSOM gm k) p = GM.BaseGrid gm p-  toGrid = GM.toGrid . sGridMap-  toMap = GM.toMap . sGridMap+    GM.GridMap (DSOM gm x k) p where+  type BaseGrid (DSOM gm x k) p = GM.BaseGrid gm p+  toGrid = GM.toGrid . gridMap+  toMap = GM.toMap . gridMap   mapWithKey = error "Not implemented"   delete k = withGridMap (GM.delete k)   adjustWithKey f k = withGridMap (GM.adjustWithKey f k)@@ -73,25 +90,26 @@   alter f k = withGridMap (GM.alter f k)   filterWithKey f = withGridMap (GM.filterWithKey f) -withGridMap :: (gm p -> gm p) -> DSOM gm k p -> DSOM gm k p-withGridMap f s = s { sGridMap=gm' }-    where gm = sGridMap s+withGridMap :: (gm p -> gm p) -> DSOM gm x k p -> DSOM gm x k p+withGridMap f s = s { gridMap=gm' }+    where gm = gridMap s           gm' = f gm  -- | Extracts the grid and current models from the DSOM.-toGridMap :: GM.GridMap gm p => DSOM gm k p -> gm p-toGridMap = sGridMap+toGridMap :: GM.GridMap gm p => DSOM gm x k p -> gm p+toGridMap = gridMap  adjustNode-  :: (Pattern p, G.FiniteGrid (gm p), GM.GridMap gm p,-      k ~ G.Index (gm p), Ord k, k ~ G.Index (GM.BaseGrid gm p),-      Num (Metric p), Fractional (Metric p)) => -     gm p -> (Metric p -> Metric p -> Metric p) -> p -> k -> k -> p -> p-adjustNode gm f target bmu k = makeSimilar target amount-  where diff = difference (gm GM.! k) target+  :: (G.FiniteGrid (gm p), GM.GridMap gm p,+      k ~ G.Index (gm p), k ~ G.Index (GM.BaseGrid gm p),+      Ord k, Num x, Fractional x) => +     gm p -> (p -> x -> p -> p) -> (p -> p -> x) -> (x -> x -> x) -> p -> k -> k+       -> (p -> p)+adjustNode gm fms fd fr target bmu k = fms target amount+  where diff = fd (gm GM.! k) target         dist = scaleDistance (G.distance gm bmu k)                  (G.maxPossibleDistance gm)-        amount = f diff dist+        amount = fr diff dist  scaleDistance :: (Num a, Fractional a) => Int -> Int -> a scaleDistance d dMax@@ -103,39 +121,40 @@ --   Most users should use @train@, which automatically determines --   the BMU and trains it and its neighbourhood. trainNeighbourhood-  :: (Pattern p, G.FiniteGrid (gm p), GM.GridMap gm p, Num (Metric p),-      Ord k, k ~ G.Index (gm p),-      k ~ G.Index (GM.BaseGrid gm p), Fractional (Metric p)) =>-     DSOM gm t p -> k -> p -> DSOM gm k p-trainNeighbourhood s bmu target = s { sGridMap=gm' }-  where gm = sGridMap s-        gm' = GM.mapWithKey (adjustNode gm f target bmu) gm-        f = (sLearningFunction s) bmuDiff-        bmuDiff = difference (gm GM.! bmu) target+  :: (G.FiniteGrid (gm p), GM.GridMap gm p,+      k ~ G.Index (gm p), k ~ G.Index (GM.BaseGrid gm p),+      Ord k, Num x, Fractional x) => +      DSOM gm x t p -> k -> p -> DSOM gm x k p+trainNeighbourhood s bmu target = s { gridMap=gm' }+  where gm = gridMap s+        gm' = GM.mapWithKey (adjustNode gm fms fd fr target bmu) gm+        fms = makeSimilar s+        fd = difference s+        fr = (learningRate s) bmuDiff+        bmuDiff = (difference s) (gm GM.! bmu) target  justTrain-  :: (Pattern p, G.FiniteGrid (gm p), GM.GridMap gm p,-      Num (Metric p), Ord (Metric p), Ord (G.Index (gm p)),-      GM.GridMap gm (Metric p), Fractional (Metric p),-      G.Index (GM.BaseGrid gm (Metric p)) ~ G.Index (gm p),-      G.Index (GM.BaseGrid gm p) ~ G.Index (gm p)) =>-     DSOM gm t p -> p -> DSOM gm (G.Index (gm p)) p+  :: (G.FiniteGrid (gm p), GM.GridMap gm p, GM.GridMap gm x,+      k ~ G.Index (gm p), k ~ G.Index (gm x),+      k ~ G.Index (GM.BaseGrid gm p), k ~ G.Index (GM.BaseGrid gm x),+      Ord k, Ord x, Num x, Fractional x) => +     DSOM gm x t p -> p -> DSOM gm x k p justTrain s p = trainNeighbourhood s bmu p-  where ds = GM.toList . GM.map (p `difference`) $ sGridMap s+  where ds = GM.toList . GM.map (difference s p) $ gridMap s         bmu = f ds         f [] = error "DSOM has no models"         f xs = fst $ minimumBy (comparing snd) xs  instance-  (GM.GridMap gm p, k ~ G.Index (GM.BaseGrid gm p), Pattern p,-    G.FiniteGrid (gm p), GM.GridMap gm (Metric p), k ~ G.Index (gm p),-    k ~ G.Index (GM.BaseGrid gm (Metric p)), Ord k, Ord (Metric p),-    Num (Metric p), Fractional (Metric p)) =>-   Classifier (DSOM gm) k p where-  toList = GM.toList . sGridMap-  numModels = G.tileCount . sGridMap-  models = GM.elems . sGridMap-  differences s p = GM.toList . GM.map (p `difference`) $ sGridMap s+  (GM.GridMap gm p, k ~ G.Index (GM.BaseGrid gm p), +    G.FiniteGrid (gm p), GM.GridMap gm x, k ~ G.Index (gm p),+    k ~ G.Index (gm x), k ~ G.Index (GM.BaseGrid gm x), Ord k, Ord x,+    Num x, Fractional x) =>+   Classifier (DSOM gm) x k p where+  toList = GM.toList . gridMap+  numModels = G.tileCount . gridMap+  models = GM.elems . gridMap+  differences s p = GM.toList . GM.map (difference s p) $ gridMap s   trainBatch s = foldl' justTrain s   reportAndTrain s p = (bmu, ds, s')     where ds = differences s p@@ -143,53 +162,6 @@           f [] = error "DSOM has no models"           f xs = fst $ minimumBy (comparing snd) xs           s' = trainNeighbourhood s bmu p----- | Creates a classifier with a default (bell-shaped) learning---   function. Usage is @'defaultDSOM' gm r w t@, where:------   [@gm@] The geometry and initial models for this classifier.---   A reasonable choice here is @'lazyGridMap' g ps@, where @g@ is a---   @'HexHexGrid'@, and @ps@ is a set of random patterns.------   [@r@] and [@p@] are the first two parameters to the---   @'rougierLearningFunction'@.-defaultDSOM-  :: (Eq (Metric p), Ord (Metric p), Floating (Metric p)) =>-     gm p -> Metric p -> Metric p -> DSOM gm k p-defaultDSOM gm r p =-  DSOM {-        sGridMap=gm,-        sLearningFunction=rougierLearningFunction r p-      }---- | Creates a classifier with a custom learning function.---   Usage is @'customDSOM' gm g@, where:------   [@gm@] The geometry and initial models for this classifier.---   A reasonable choice here is @'lazyGridMap' g ps@, where @g@ is a---   @'HexHexGrid'@, and @ps@ is a set of random patterns.------   [@f@] A function used to determine the learning rate (for---   adjusting the models in the classifier).---   This function will be invoked with three parameters.---   The first parameter will indicate how different the BMU is from---   the input pattern.---   The second parameter indicates how different the pattern of the---   node currently being trained is from the input pattern.---   The third parameter is the grid distance from the BMU to the node---   currently being trained, as a fraction of the maximum grid---   distance.---   The output is the learning rate for that node (the amount by---   which the node's model should be updated to match the target).---   The learning rate should be between zero and one.-customDSOM-  :: gm p -> (Metric p -> Metric p -> Metric p -> Metric p) -> DSOM gm k p-customDSOM gm f =-  DSOM {-        sGridMap=gm,-        sLearningFunction=f-      }  -- | Configures a learning function that depends not on the time, but --   on how good a model we already have for the target. If the
src/Data/Datamining/Clustering/SOM.hs view
@@ -1,7 +1,7 @@ ------------------------------------------------------------------------ -- | -- Module      :  Data.Datamining.Clustering.SOM--- Copyright   :  (c) Amy de Buitléir 2012-2014+-- Copyright   :  (c) Amy de Buitléir 2012-2015 -- License     :  BSD-style -- Maintainer  :  amy@nualeargais.ie -- Stability   :  experimental@@ -40,13 +40,15 @@   (     -- * Construction     SOM(..),-    DecayingGaussian(..),     -- * Deconstruction     toGridMap,+    -- * Learning functions+    decayingGaussian,+    stepFunction,+    constantFunction,     -- * Advanced control     trainNeighbourhood   ) where -import Data.Datamining.Clustering.SOMInternal (SOM(..),-  DecayingGaussian(..), toGridMap, trainNeighbourhood)+import Data.Datamining.Clustering.SOMInternal 
src/Data/Datamining/Clustering/SOMInternal.hs view
@@ -1,7 +1,7 @@ ------------------------------------------------------------------------ -- | -- Module      :  Data.Datamining.Clustering.SOMInternal--- Copyright   :  (c) Amy de Buitléir 2012-2014+-- Copyright   :  (c) Amy de Buitléir 2012-2015 -- License     :  BSD-style -- Maintainer  :  amy@nualeargais.ie -- Stability   :  experimental@@ -21,28 +21,12 @@ import Data.Ord (comparing) import qualified Math.Geometry.Grid as G (Grid(..)) import qualified Math.Geometry.GridMap as GM (GridMap(..))-import Data.Datamining.Pattern (Pattern(..)) import Data.Datamining.Clustering.Classifier(Classifier(..)) import GHC.Generics (Generic) import Prelude hiding (lookup) --- | A function used to adjust the models in a classifier.-class LearningFunction f where-  type LearningRate f-  -- | @'rate' f t d@ returns the learning rate for a node.-  --   The parameter @f@ is the learning function.-  --   The parameter @t@ indicates how many patterns (or pattern-  --   batches) have previously been presented to the classifier.-  --   Typically this is used to make the learning rate decay over time.-  --   The parameter @d@ is the grid distance from the node being-  --   updated to the BMU (Best Matching Unit).-  --   The output is the learning rate for that node (the amount by-  --   which the node's model should be updated to match the target).-  --   The learning rate should be between zero and one.-  rate :: f -> LearningRate f -> LearningRate f -> LearningRate f- -- | A typical learning function for classifiers.---   @'DecayingGaussian' r0 rf w0 wf tf@ returns a bell curve-shaped+--   @'decayingGaussian' r0 rf w0 wf tf@ returns a bell curve-shaped --   function. At time zero, the maximum learning rate (applied to the --   BMU) is @r0@, and the neighbourhood width is @w0@. Over time the --   bell curve shrinks and the learning rate tapers off, until at time@@ -58,33 +42,23 @@ -- --   where << means "is much smaller than" (not the Haskell @<<@ --   operator!)-data DecayingGaussian a = DecayingGaussian a a a a a-  deriving (Eq, Show, Generic)--instance (Floating a, Fractional a, Num a)-    => LearningFunction (DecayingGaussian a) where-  type LearningRate (DecayingGaussian a) = a-  rate (DecayingGaussian r0 rf w0 wf tf) t d = r * exp (-(d*d)/(2*w*w))-    where a = t/tf-          r = r0 * ((rf/r0)**a)-          w = w0 * ((wf/w0)**a)+decayingGaussian :: Floating x => x -> x -> x -> x -> x -> x -> x -> x+decayingGaussian r0 rf w0 wf tf t d = r * exp (-x/y)+  where a = t / tf+        r = r0 * ((rf/r0)**a)+        w = w0 * ((wf/w0)**a)+        x =  (d*d)+        y =  (2*w*w)  -- | A learning function that only updates the BMU and has a constant --   learning rate.-data StepFunction a = StepFunction a deriving (Eq, Show, Generic)--instance (Fractional a, Eq a)-  => LearningFunction (StepFunction a) where-  type LearningRate (StepFunction a) = a-  rate (StepFunction r) _ d = if d == 0 then r else 0.0+stepFunction :: (Num d, Fractional x, Eq d) => x -> t -> d -> x+stepFunction r _ d = if d == 0 then r else 0.0  -- | A learning function that updates all nodes with the same, constant --   learning rate. This can be useful for testing.-data ConstantFunction a = ConstantFunction a deriving (Eq, Show, Generic)--instance (Fractional a) => LearningFunction (ConstantFunction a) where-  type LearningRate (ConstantFunction a) = a-  rate (ConstantFunction r) _ _ = r+constantFunction :: x -> t -> d -> x+constantFunction r _ _ = r  -- | A Self-Organising Map (SOM). --@@ -99,26 +73,52 @@ --      just return an @error@). It would be problematic to implement --      them because the input SOM and the output SOM would have to have --      the same @Metric@ type.-data SOM f t gm k p = SOM+data SOM t d gm x k p = SOM   {     -- | Maps patterns to tiles in a regular grid.     --   In the context of a SOM, the tiles are called "nodes"     gridMap :: gm p,-    -- | The function used to update the nodes.-    learningFunction :: f,+    -- | A function which determines the how quickly the SOM learns.+    --   For example, if the function is @f@, then @f t d@ returns the+    --   learning rate for a node.+    --   The parameter @t@ indicates how many patterns (or pattern+    --   batches) have previously been presented to the classifier.+    --   Typically this is used to make the learning rate decay over+    --   time.+    --   The parameter @d@ is the grid distance from the node being+    --   updated to the BMU (Best Matching Unit).+    --   The output is the learning rate for that node (the amount by+    --   which the node's model should be updated to match the target).+    --   The learning rate should be between zero and one.+    learningRate :: t -> d -> x,+    -- | A function which compares two patterns and returns a +    --   /non-negative/ numberrepresenting how different the patterns+    --   are.+    --   A result of @0@ indicates that the patterns are identical.+    difference :: p -> p -> x,+    -- | A function which updates models.+    --   If this function is @f@, then @f target amount pattern@ returns+    --   a modified copy of @pattern@ that is more similar to @target@+    --   than @pattern@ is.+    --   The magnitude of the adjustment is controlled by the @amount@+    --   parameter, which should be a number between 0 and 1.+    --   Larger values for @amount@ permit greater adjustments.+    --   If @amount@=1, the result should be identical to the @target@.+    --   If @amount@=0, the result should be the unmodified @pattern@.+    makeSimilar :: p -> x -> p -> p,     -- | A counter used as a "time" parameter.     --   If you create the SOM with a counter value @0@, and don't     --   directly modify it, then the counter will represent the number     --   of patterns that this SOM has classified.     counter :: t-  } deriving (Eq, Show, Generic)+  } deriving (Generic) -instance (F.Foldable gm) => F.Foldable (SOM f t gm k) where+instance (F.Foldable gm) => F.Foldable (SOM t d gm x k) where   foldr f x g = F.foldr f x (gridMap g) -instance (G.Grid (gm p)) => G.Grid (SOM f t gm k p) where-  type Index (SOM f t gm k p) = G.Index (gm p)-  type Direction (SOM f t gm k p) = G.Direction (gm p)+instance (G.Grid (gm p)) => G.Grid (SOM t d gm x k p) where+  type Index (SOM t d gm x k p) = G.Index (gm p)+  type Direction (SOM t d gm x k p) = G.Direction (gm p)   indices = G.indices . gridMap   distance = G.distance . gridMap   neighbours = G.neighbours . gridMap@@ -130,8 +130,8 @@   nonNull = G.nonNull . gridMap  instance (F.Foldable gm, GM.GridMap gm p, G.Grid (GM.BaseGrid gm p))-    => GM.GridMap (SOM f t gm k) p where-  type BaseGrid (SOM f t gm k) p = GM.BaseGrid gm p+    => GM.GridMap (SOM t d gm x k) p where+  type BaseGrid (SOM t d gm x k) p = GM.BaseGrid gm p   toGrid = GM.toGrid . gridMap   toMap = GM.toMap . gridMap   mapWithKey = error "Not implemented"@@ -141,27 +141,26 @@   alter f k = withGridMap (GM.alter f k)   filterWithKey f = withGridMap (GM.filterWithKey f) -withGridMap :: (gm p -> gm p) -> SOM f t gm k p -> SOM f t gm k p+withGridMap :: (gm p -> gm p) -> SOM t d gm x k p -> SOM t d gm x k p withGridMap f s = s { gridMap=gm' }     where gm = gridMap s           gm' = f gm  currentLearningFunction-  :: (LearningFunction f, Metric p ~ LearningRate f,-    Num (LearningRate f), Integral t)-      => SOM f t gm k p -> (LearningRate f -> Metric p)+  :: (Num t)+    => SOM t d gm x k p -> (d -> x) currentLearningFunction s-  = rate (learningFunction s) (fromIntegral $ counter s)+  = (learningRate s) (counter s)  -- | Extracts the grid and current models from the SOM. --   A synonym for @'gridMap'@.-toGridMap :: GM.GridMap gm p => SOM f t gm k p -> gm p+toGridMap :: GM.GridMap gm p => SOM t d gm x k p -> gm p toGridMap = gridMap  adjustNode-  :: (Pattern p, G.Grid g, k ~ G.Index g, Num t) =>-     g -> (t -> Metric p) -> p -> k -> k -> p -> p-adjustNode g f target bmu k = makeSimilar target (f d)+  :: (G.Grid g, k ~ G.Index g, Num t) =>+     g -> (t -> x) -> (p -> x -> p -> p) -> p -> k -> k -> p -> p+adjustNode g rateF adjustF target bmu k = adjustF target (rateF d)   where d = fromIntegral $ G.distance g bmu k  -- | Trains the specified node and the neighbourood around it to better@@ -169,42 +168,40 @@ --   Most users should use @'train'@, which automatically determines --   the BMU and trains it and its neighbourhood. trainNeighbourhood-  :: (Pattern p, G.Grid (gm p), GM.GridMap gm p,-      G.Index (GM.BaseGrid gm p) ~ G.Index (gm p), LearningFunction f,-      Metric p ~ LearningRate f, Num (LearningRate f), Integral t) =>-     SOM f t gm k p -> G.Index (gm p) -> p -> SOM f t gm k p+  :: (G.Grid (gm p), GM.GridMap gm p,+      G.Index (GM.BaseGrid gm p) ~ G.Index (gm p), Num t, Num x,+      Num d) =>+     SOM t d gm x k p -> G.Index (gm p) -> p -> SOM t d gm x k p trainNeighbourhood s bmu target = s { gridMap=gm' }   where gm = gridMap s-        gm' = GM.mapWithKey (adjustNode gm f target bmu) gm-        f = currentLearningFunction s+        gm' = GM.mapWithKey (adjustNode gm f1 f2 target bmu) gm+        f1 = currentLearningFunction s+        f2 = makeSimilar s -incrementCounter :: Num t => SOM f t gm k p -> SOM f t gm k p+incrementCounter :: Num t => SOM t d gm x k p -> SOM t d gm x k p incrementCounter s = s { counter=counter s + 1}  justTrain-  :: (Ord (Metric p), Pattern p, G.Grid (gm p),-      GM.GridMap gm (Metric p), GM.GridMap gm p,-      G.Index (GM.BaseGrid gm (Metric p)) ~ G.Index (gm p),-      G.Index (GM.BaseGrid gm p) ~ G.Index (gm p), LearningFunction f,-      Metric p ~ LearningRate f, Num (LearningRate f), Integral t) =>-     SOM f t gm k p -> p -> SOM f t gm k p+  :: (Ord x, G.Grid (gm p), GM.GridMap gm x, GM.GridMap gm p,+      G.Index (GM.BaseGrid gm x) ~ G.Index (gm p),+      G.Index (GM.BaseGrid gm p) ~ G.Index (gm p), Num t, Num x,+      Num d) =>+     SOM t d gm x k p -> p -> SOM t d gm x k p justTrain s p = trainNeighbourhood s bmu p-  where ds = GM.toList . GM.map (p `difference`) $ gridMap s+  where ds = GM.toList . GM.map (difference s p) $ gridMap s         bmu = f ds         f [] = error "SOM has no models"         f xs = fst $ minimumBy (comparing snd) xs  instance-  (GM.GridMap gm p, k ~ G.Index (GM.BaseGrid gm p), Pattern p,-  G.Grid (gm p), GM.GridMap gm (Metric p), k ~ G.Index (gm p),-  k ~ G.Index (GM.BaseGrid gm (Metric p)), Ord (Metric p),-  LearningFunction f, Metric p ~ LearningRate f, Num (LearningRate f),-  Integral t)-    => Classifier (SOM f t gm) k p where+  (GM.GridMap gm p, k ~ G.Index (GM.BaseGrid gm p), G.Grid (gm p),+  GM.GridMap gm x, k ~ G.Index (gm p), k ~ G.Index (GM.BaseGrid gm x),+  Num t, Ord x, Num x, Num d)+    => Classifier (SOM t d gm) x k p where   toList = GM.toList . gridMap   numModels = G.tileCount . gridMap   models = GM.elems . gridMap-  differences s p = GM.toList . GM.map (p `difference`) $ gridMap s+  differences s p = GM.toList . GM.map (difference s p) $ gridMap s   trainBatch s = incrementCounter . foldl' justTrain s   reportAndTrain s p = (bmu, ds, incrementCounter s')     where ds = differences s p
src/Data/Datamining/Clustering/SSOM.hs view
@@ -1,7 +1,7 @@ ------------------------------------------------------------------------ -- | -- Module      :  Data.Datamining.Clustering.SSOM--- Copyright   :  (c) Amy de Buitléir 2012-2014+-- Copyright   :  (c) Amy de Buitléir 2012-2015 -- License     :  BSD-style -- Maintainer  :  amy@nualeargais.ie -- Stability   :  experimental@@ -34,13 +34,13 @@   (     -- * Construction     SSOM(..),-    Exponential(..),     -- * Deconstruction     toMap,+    -- * Learning functions+    exponential,     -- * Advanced control-    trainNode,+    trainNode   ) where -import Data.Datamining.Clustering.SSOMInternal (SSOM(..),-  Exponential(..), toMap, trainNode)+import Data.Datamining.Clustering.SSOMInternal 
src/Data/Datamining/Clustering/SSOMInternal.hs view
@@ -1,7 +1,7 @@ ------------------------------------------------------------------------ -- | -- Module      :  Data.Datamining.Clustering.SSOMInternal--- Copyright   :  (c) Amy de Buitléir 2012-2014+-- Copyright   :  (c) Amy de Buitléir 2012-2015 -- License     :  BSD-style -- Maintainer  :  amy@nualeargais.ie -- Stability   :  experimental@@ -18,30 +18,17 @@  import Data.List (foldl', minimumBy) import Data.Ord (comparing)-import Data.Datamining.Pattern (Pattern(..)) import Data.Datamining.Clustering.Classifier(Classifier(..)) import qualified Data.Map.Strict as M import GHC.Generics (Generic) import Prelude hiding (lookup) --- | A function used to adjust the models in a classifier.-class LearningFunction f where-  type LearningRate f-  -- | @'rate' f t@ returns the learning rate for a node.-  --   The parameter @f@ is the learning function.-  --   The parameter @t@ indicates how many patterns (or pattern-  --   batches) have previously been presented to the classifier.-  --   Typically this is used to make the learning rate decay over time.-  --   The output is the learning rate for that node (the amount by-  --   which the node's model should be updated to match the target).-  --   The learning rate should be between zero and one.-  rate :: f -> LearningRate f -> LearningRate f- -- | A typical learning function for classifiers.---   @'Exponential' r0 d@ returns a function to calculate the---   learning rate. At time zero, the learning rate is @r0@. Over time---   the learning rate decays exponentially. Normally the parameters---   should be chosen such that:+--   @'exponential' r0 d t@ returns the learning rate at time @t@.+--   When @t = 0@, the learning rate is @r0@.+--   Over time the learning rate decays exponentially; the decay rate is+--   @d@.+--   Normally the parameters are chosen such that: -- --   * 0 < r0 < 1 --@@ -49,67 +36,85 @@ -- --   where << means "is much smaller than" (not the Haskell @<<@ --   operator!)-data Exponential a = Exponential a a-  deriving (Eq, Show, Generic)--instance (Floating a, Fractional a, Num a)-    => LearningFunction (Exponential a) where-  type LearningRate (Exponential a) = a-  rate (Exponential r0 d) t = r0 * exp (-d*t)+exponential :: Floating a => a -> a -> a -> a+exponential r0 d t = r0 * exp (-d*t)  -- | A Simplified Self-Organising Map (SSOM).-data SSOM f t k p = SSOM+--   @x@ is the type of the learning rate and the difference metric.+--   @t@ is the type of the counter.+--   @k@ is the type of the model indices.+--   @p@ is the type of the input patterns and models.+data SSOM t x k p = SSOM   {     -- | Maps patterns to nodes.     sMap :: M.Map k p,-    -- | The function used to update the nodes.-    learningFunction :: f,+    -- | A function which determines the learning rate for a node.+    --   The input parameter indicates how many patterns (or pattern+    --   batches) have previously been presented to the classifier.+    --   Typically this is used to make the learning rate decay over+    --   time.+    --   The output is the learning rate for that node (the amount by+    --   which the node's model should be updated to match the target).+    --   The learning rate should be between zero and one.+    learningRate :: t -> x,+    -- | A function which compares two patterns and returns a +    --   /non-negative/ numberrepresenting how different the patterns+    --   are.+    --   A result of @0@ indicates that the patterns are identical.+    difference :: p -> p -> x,+    -- | A function which updates models.+    --   For example, if this function is @f@, then+    --   @f target amount pattern@ returns a modified copy of @pattern@+    --   that is more similar to @target@ than @pattern@ is.+    --   The magnitude of the adjustment is controlled by the @amount@+    --   parameter, which should be a number between 0 and 1.+    --   Larger values for @amount@ permit greater adjustments.+    --   If @amount@=1, the result should be identical to the @target@.+    --   If @amount@=0, the result should be the unmodified @pattern@.+    makeSimilar :: p -> x -> p -> p,     -- | A counter used as a "time" parameter.     --   If you create the SSOM with a counter value @0@, and don't     --   directly modify it, then the counter will represent the number     --   of patterns that this SSOM has classified.     counter :: t-  } deriving (Eq, Show, Generic)+  } deriving (Generic)  -- | Extracts the current models from the SSOM. --   A synonym for @'sMap'@.-toMap :: SSOM f t k p -> M.Map k p+toMap :: SSOM t x k p -> M.Map k p toMap = sMap  -- | Trains the specified node to better match a target. --   Most users should use @'train'@, which automatically determines --   the BMU and trains it. trainNode-  :: (Pattern p, LearningFunction f, Metric p ~ LearningRate f,-    Num (LearningRate f), Ord k, Integral t)-      => SSOM f t k p -> k -> p -> SSOM f t k p+  :: (Num t, Ord k)+      => SSOM t x k p -> k -> p -> SSOM t x k p trainNode s k target = s { sMap=gm' }   where gm = sMap s-        gm' = M.adjust (makeSimilar target r) k gm-        r = rate (learningFunction s) (fromIntegral $ counter s)+        gm' = M.adjust (makeSimilar s target r) k gm+        r = (learningRate s) (counter s) -incrementCounter :: Num t => SSOM f t k p -> SSOM f t k p+incrementCounter :: Num t => SSOM t x k p -> SSOM t x k p incrementCounter s = s { counter=counter s + 1}  justTrain-  :: (Ord (Metric p), Pattern p, LearningFunction f,-    Metric p ~ LearningRate f, Num (LearningRate f), Ord k, Integral t)-      => SSOM f t k p -> p -> SSOM f t k p+  :: (Num t, Ord k, Ord x)+      => SSOM t x k p -> p -> SSOM t x k p justTrain s p = trainNode s bmu p-  where ds = M.toList . M.map (p `difference`) . toMap $ s+  where ds = M.toList . M.map (difference s p) . toMap $ s         bmu = f ds         f [] = error "SSOM has no models"         f xs = fst $ minimumBy (comparing snd) xs  instance-  (Pattern p, Ord (Metric p), LearningFunction f,-    Metric p ~ LearningRate f, Num (LearningRate f), Ord k, Integral t)-      => Classifier (SSOM f t) k p where+  (Num t, Ord x, Num x, Ord k)+    => Classifier (SSOM t) x k p where   toList = M.toList . toMap   -- TODO: If the # of models is fixed, make more efficient   numModels = length . M.keys . sMap   models = M.elems . toMap-  differences s p = M.toList . M.map (p `difference`) $ toMap s+  differences s p = M.toList . M.map (difference s p) $ toMap s   trainBatch s = incrementCounter . foldl' justTrain s   reportAndTrain s p = (bmu, ds, s')     where ds = differences s p
src/Data/Datamining/Pattern.hs view
@@ -1,7 +1,7 @@ ------------------------------------------------------------------------ -- | -- Module      :  Data.Datamining.Pattern--- Copyright   :  (c) Amy de Buitléir 2012-2014+-- Copyright   :  (c) Amy de Buitléir 2012-2015 -- License     :  BSD-style -- Maintainer  :  amy@nualeargais.ie -- Stability   :  experimental@@ -13,15 +13,11 @@ {-# LANGUAGE TypeFamilies, FlexibleContexts, MultiParamTypeClasses #-} module Data.Datamining.Pattern   (-    -- * Patterns-    Pattern(..),     -- * Numbers as patterns-    -- $Num     adjustNum,     absDifference,     -- * Numeric vectors as patterns     -- ** Raw vectors-    -- $Vector     adjustVector,     euclideanDistanceSquared,     magnitudeSquared,@@ -36,22 +32,6 @@  import Data.List (foldl') --- | A pattern to be learned or classified.-class Pattern p where-  type Metric p-  -- | Compares two patterns and returns a /non-negative/ number-  --   representing how different the patterns are. A result of @0@-  --   indicates that the patterns are identical.-  difference :: p -> p -> Metric p-  -- | @'makeSimilar' target amount pattern@ returns a modified copy of-  --   @pattern@ that is more similar to @target@ than @pattern@ is. The-  --   magnitude of the adjustment is controlled by the @amount@-  --   parameter, which should be a number between 0 and 1. Larger-  --   values for @amount@ permit greater adjustments. If @amount@=1,-  --   the result should be identical to the @target@. If @amount@=0,-  --   the result should be the unmodified @pattern@.-  makeSimilar :: p -> Metric p -> p -> p- -- -- Using numbers as patterns. --@@ -63,23 +43,12 @@ adjustNum target r x   | r < 0     = error "Negative learning rate"   | r > 1     = error "Learning rate > 1"-  | r == 1     = x   | otherwise = adjustNum' r target x  -- Note that parameters are swapped adjustNum' :: Num a => a -> a -> a -> a adjustNum' r target x = x + r*(target - x) -{- $Num-If you wish to use, say, a @Double@ as a pattern, one option is to-use @no-warn-orphans@ and add the following to your code:--> instance Double => Pattern Double where->   type Metric Double = Double->   difference = absDifference->   makeSimilar = adjustNum--}- -- -- Using numeric vectors as patterns. --@@ -118,14 +87,6 @@ norm xs = sqrt $ sum (map f xs)   where f x = x*x -instance (Floating a, Fractional a, Ord a, Eq a) =>-    Pattern (NormalisedVector a) where-  type Metric (NormalisedVector a) = a-  difference (NormalisedVector xs) (NormalisedVector ys) =-    euclideanDistanceSquared xs ys-  makeSimilar (NormalisedVector xs) r (NormalisedVector ys) =-    normalise $ adjustVector xs r ys- -- | A vector that has been scaled so that all elements in the vector --   are between zero and one. To scale a set of vectors, use --   @'scaleAll'@. Alternatively, if you can identify a maximum and@@ -158,20 +119,3 @@ quantify' :: Ord a => [(a,a)] -> [a] -> [(a,a)] quantify' = zipWith f   where f (minX, maxX) x = (min minX x, max maxX x)--instance (Fractional a, Ord a, Eq a) => Pattern (ScaledVector a) where-  type Metric (ScaledVector a) = a-  difference (ScaledVector xs) (ScaledVector ys) =-    euclideanDistanceSquared xs ys-  makeSimilar (ScaledVector xs) r (ScaledVector ys) =-    ScaledVector $ adjustVector xs r ys--{- $Vector-If you wish to use raw numeric vectors as a pattern, one option is to-use @no-warn-orphans@ and add the following to your code:--> instance (Floating a, Fractional a, Ord a, Eq a) => Pattern [a] where->   type Metric [a] = a->   difference = euclideanDistanceSquared->   makeSimilar = adjustVector--}
test/Data/Datamining/Clustering/DSOMQC.hs view
@@ -1,7 +1,7 @@ ------------------------------------------------------------------------ -- | -- Module      :  Data.Datamining.Clustering.DSOMQC--- Copyright   :  (c) Amy de Buitléir 2012-2014+-- Copyright   :  (c) Amy de Buitléir 2012-2015 -- License     :  BSD-style -- Maintainer  :  amy@nualeargais.ie -- Stability   :  experimental@@ -19,23 +19,23 @@     test   ) where -import Data.Datamining.Pattern (Pattern, Metric, difference,-  euclideanDistanceSquared, magnitudeSquared, makeSimilar)+import Data.Datamining.Pattern (euclideanDistanceSquared,+  magnitudeSquared, adjustNum, absDifference) import Data.Datamining.Clustering.Classifier(classify,   classifyAndTrain, differences, diffAndTrain, models,   numModels, train, trainBatch) import Data.Datamining.Clustering.DSOMInternal  import Control.Applicative ((<$>), (<*>))-import Data.Function (on) import Data.List (sort)+import Math.Geometry.Grid (size) import Math.Geometry.Grid.Hexagonal (HexHexGrid, hexHexGrid)-import Math.Geometry.GridMap ((!))+import Math.Geometry.GridMap ((!), elems) import Math.Geometry.GridMap.Lazy (LGridMap, lazyGridMap) import Test.Framework as TF (Test, testGroup) import Test.Framework.Providers.QuickCheck2 (testProperty) import Test.QuickCheck ((==>), Gen, Arbitrary, arbitrary, choose,-  Property, property, sized, suchThat, vectorOf)+  Property, property, sized, suchThat, vectorOf, shrink)  positive :: (Num a, Ord a, Arbitrary a) => Gen a positive = arbitrary `suchThat` (> 0)@@ -64,128 +64,127 @@ prop_rougierFunction_r_if_inelastic (RougierArgs r _ _ _ _) =   property $ rougierLearningFunction r 1.0 1.0 1.0 0 == r -newtype TestPattern = MkPattern Double deriving Show+fractionDiff :: [Double] -> [Double] -> Double+fractionDiff xs ys = if denom == 0 then 0 else d / denom+  where d = sqrt $ euclideanDistanceSquared xs ys+        denom = max xMag yMag+        xMag = sqrt $ magnitudeSquared xs+        yMag = sqrt $ magnitudeSquared ys -instance Eq TestPattern where-  (==) = (==) `on` toDouble+approxEqual :: [TestPattern] -> [TestPattern] -> Bool+approxEqual xs ys = fractionDiff xs' ys' <= 0.1+  where xs' = map toDouble xs+        ys' = map toDouble ys -instance Ord TestPattern where-  compare = compare `on` toDouble+-- We need to ensure that the absolute value of the difference+-- between any two test patterns is on the unit interval. -instance Pattern TestPattern where-  type Metric TestPattern = Double-  difference (MkPattern a) (MkPattern b) = abs (a - b)-  makeSimilar orig@(MkPattern a) r (MkPattern b)-    | r < 0     = error "Negative learning rate"-    | r > 1     = error "Learning rate > 1"-    | r == 1     = orig-    | otherwise = MkPattern (b + delta)-        where diff = a - b-              delta = r*diff+newtype TestPattern = TestPattern {toDouble :: Double}+ deriving ( Eq, Ord, Show, Read)  instance Arbitrary TestPattern where-  arbitrary = MkPattern <$> choose (0,1)--toDouble :: TestPattern -> Double-toDouble (MkPattern a) = a--absDiff :: [TestPattern] -> [TestPattern] -> Double-absDiff xs ys = euclideanDistanceSquared xs' ys'-  where xs' = map toDouble xs-        ys' = map toDouble ys+  arbitrary = fmap TestPattern $ choose (0,1)+  shrink (TestPattern x) =+    [ TestPattern x' | x' <- shrink x, x' >= 0, x' <= 1] -fractionDiff :: [TestPattern] -> [TestPattern] -> Double-fractionDiff xs ys = if denom == 0 then 0 else d / denom-  where d = sqrt $ euclideanDistanceSquared xs' ys'-        denom = max xMag yMag-        xMag = sqrt $ magnitudeSquared xs'-        yMag = sqrt $ magnitudeSquared ys'-        xs' = map toDouble xs-        ys' = map toDouble ys+testPatternDiff :: TestPattern -> TestPattern -> Double+testPatternDiff (TestPattern a) (TestPattern b) = absDifference a b -approxEqual :: [TestPattern] -> [TestPattern] -> Bool-approxEqual xs ys = fractionDiff xs ys <= 0.1+adjustTestPattern :: TestPattern -> Double -> TestPattern -> TestPattern+adjustTestPattern (TestPattern target) r (TestPattern x)+  = TestPattern $ adjustNum target r x -data DSOMandTargets = DSOMandTargets (DSOM (LGridMap HexHexGrid) (Int, Int)-  TestPattern) [TestPattern] String+-- | A classifier and a training set. The training set will consist of+--   @j@ vectors of equal length, where @j@ is the number of patterns+--   the classifier can model. After running through the training set a+--   few times, the classifier should be very accurate at identifying+--   any of those @j@ vectors.+data DSOMTestData+  = DSOMTestData+    {+      som1 :: DSOM (LGridMap HexHexGrid) Double (Int, Int) TestPattern,+      params1 :: RougierArgs,+      trainingSet1 :: [TestPattern]+    } -instance Show DSOMandTargets where-  show (DSOMandTargets _ _ desc) = desc+instance Show DSOMTestData where+  show s = "buildDSOMTestData " ++ show (size . gridMap . som1 $ s)+    ++ " " ++ show (elems . gridMap . som1 $ s)+    ++ " (" ++ show (params1 s) +    ++ ") " ++ show (trainingSet1 s)  -buildDSOMandTargets-  :: Int -> [TestPattern] -> Double -> Double -> [TestPattern] -> DSOMandTargets-buildDSOMandTargets len ps r p targets = DSOMandTargets s targets desc+buildDSOMTestData+  :: Int -> [TestPattern] -> RougierArgs -> [TestPattern] -> DSOMTestData+buildDSOMTestData len ps rp@(RougierArgs r p _ _ _) targets =+  DSOMTestData s rp targets     where g = hexHexGrid len           gm = lazyGridMap g ps-          s = defaultDSOM gm r p-          desc = "buildDSOMandTargets " ++ show len ++ " " ++ show ps ++-            " " ++ show r ++ " " ++ show p ++ " " ++ show targets+          fr = rougierLearningFunction r p+          s = DSOM gm fr testPatternDiff adjustTestPattern  -- | Generate a classifier and a training set. The training set will --   consist @j@ vectors of equal length, where @j@ is the number of --   patterns the classifier can model. After running through the --   training set a few times, the classifier should be very accurate at --   identifying any of those @j@ vectors.-sizedDSOMandTargets :: Int -> Gen DSOMandTargets-sizedDSOMandTargets n = do+sizedDSOMTestData :: Int -> Gen DSOMTestData+sizedDSOMTestData n = do   sideLength <- choose (1, min (n+1) 5) --avoid long tests   let tileCount = 3*sideLength*(sideLength-1) + 1   let numberOfPatterns = tileCount   ps <- vectorOf numberOfPatterns arbitrary-  r <- choose (0, 1)-  p <- choose (0, 1)+  rp <- arbitrary   targets <- vectorOf numberOfPatterns arbitrary-  return $ buildDSOMandTargets sideLength ps r p targets+  return $ buildDSOMTestData sideLength ps rp targets -instance Arbitrary DSOMandTargets where-  arbitrary = sized sizedDSOMandTargets+instance Arbitrary DSOMTestData where+  arbitrary = sized sizedDSOMTestData  -- | If we use a fixed learning rate of one (regardless of the distance --   from the BMU), and train a classifier once on one pattern, then all --   nodes should match the input vector.-prop_global_instant_training_works :: DSOMandTargets -> Property-prop_global_instant_training_works (DSOMandTargets s xs _) =+prop_global_instant_training_works :: DSOMTestData -> Property+prop_global_instant_training_works (DSOMTestData s _ xs) =   property $ finalModels `approxEqual` expectedModels     where x = head xs           gm = toGridMap s :: LGridMap HexHexGrid TestPattern-          f = (\_ _ _ -> 1) -              :: Metric TestPattern -> Metric TestPattern -> Metric TestPattern -> Metric TestPattern-          s2 = customDSOM gm f :: DSOM (LGridMap HexHexGrid) (Int, Int) TestPattern+          f _ _ _ = 1+          s2 = DSOM gm f testPatternDiff adjustTestPattern           s3 = train s2 x           finalModels = models s3 :: [TestPattern]           expectedModels = replicate (numModels s) x :: [TestPattern] -prop_training_works :: DSOMandTargets -> Property-prop_training_works (DSOMandTargets s xs _) = errBefore /= 0 ==>+prop_training_works :: DSOMTestData -> Property+prop_training_works (DSOMTestData s _ xs) = errBefore /= 0 ==>   errAfter < errBefore     where (bmu, s') = classifyAndTrain s x           x = head xs-          errBefore = abs $ toDouble x - toDouble (sGridMap s ! bmu)-          errAfter = abs $ toDouble x - toDouble (sGridMap s' ! bmu)+          errBefore = testPatternDiff x (gridMap s ! bmu)+          errAfter = testPatternDiff x (gridMap s' ! bmu)  --   Invoking @diffAndTrain f s p@ should give identical results to --   @(p `classify` s, train s f p)@.-prop_classifyAndTrainEquiv :: DSOMandTargets -> Property-prop_classifyAndTrainEquiv (DSOMandTargets s ps _) = property $-  bmu == s `classify` p && sGridMap s1 == sGridMap s2+prop_classifyAndTrainEquiv :: DSOMTestData -> Property+prop_classifyAndTrainEquiv (DSOMTestData s _ ps) = property $+  bmu == s `classify` p && gridMap s1 == gridMap s2     where p = head ps           (bmu, s1) = classifyAndTrain s p           s2 = train s p  --   Invoking @diffAndTrain f s p@ should give identical results to --   @(s `diff` p, train s f p)@.-prop_diffAndTrainEquiv :: DSOMandTargets -> Property-prop_diffAndTrainEquiv (DSOMandTargets s ps _) = property $-  diffs == s `differences` p && sGridMap s1 == sGridMap s2+prop_diffAndTrainEquiv :: DSOMTestData -> Property+prop_diffAndTrainEquiv (DSOMTestData s _ ps) = property $+  diffs == s `differences` p && gridMap s1 == gridMap s2     where p = head ps           (diffs, s1) = diffAndTrain s p           s2 = train s p  --   Invoking @trainNeighbourhood s (classify s p) p@ should give --   identical results to @train s p@.-prop_trainNeighbourhoodEquiv :: DSOMandTargets -> Property-prop_trainNeighbourhoodEquiv (DSOMandTargets s ps _) = property $-  sGridMap s1 == sGridMap s2+prop_trainNeighbourhoodEquiv :: DSOMTestData -> Property+prop_trainNeighbourhoodEquiv (DSOMTestData s _ ps) = property $+  gridMap s1 == gridMap s2     where p = head ps           s1 = trainNeighbourhood s (classify s p) p           s2 = train s p@@ -193,49 +192,56 @@ -- | The training set consists of the same vectors in the same order, --   several times over. So the resulting classifications should consist --   of the same integers in the same order, over and over.-prop_batch_training_works :: DSOMandTargets -> Property-prop_batch_training_works (DSOMandTargets s xs _) = property $+prop_batch_training_works :: DSOMTestData -> Property+prop_batch_training_works (DSOMTestData s _ xs) = property $   classifications == (concat . replicate 5) firstSet   where trainingSet = (concat . replicate 5) xs         s' = trainBatch s trainingSet         classifications = map (classify s') trainingSet         firstSet = take (length xs) classifications -data SpecialDSOMandTargets = SpecialDSOMandTargets (DSOM (LGridMap HexHexGrid) (Int, Int)-  TestPattern) [TestPattern] String+data SpecialDSOMTestData+  = SpecialDSOMTestData+    {+      som2 :: DSOM (LGridMap HexHexGrid) Double (Int, Int) TestPattern,+      params2 :: Double,+      trainingSet2 :: [TestPattern]+    } -instance Show SpecialDSOMandTargets where-  show (SpecialDSOMandTargets _ _ desc) = desc+instance Show SpecialDSOMTestData where+  show s = "buildDSOMTestData " ++ show (size . gridMap . som2 $ s)+    ++ " " ++ show (elems . gridMap . som2 $ s)+    ++ " (" ++ show (params2 s) +    ++ ") " ++ show (trainingSet2 s)   stepFunction :: Double -> Double -> Double -> Double -> Double stepFunction r _ _ d = if d == 0 then r else 0.0 -buildSpecialDSOMandTargets-  :: Int -> [TestPattern] -> Double -> [TestPattern] -> SpecialDSOMandTargets-buildSpecialDSOMandTargets len ps r targets =-  SpecialDSOMandTargets s targets desc+buildSpecialDSOMTestData+  :: Int -> [TestPattern] -> Double -> [TestPattern] -> SpecialDSOMTestData+buildSpecialDSOMTestData len ps r targets =+  SpecialDSOMTestData s r targets     where g = hexHexGrid len           gm = lazyGridMap g ps-          s = customDSOM gm (stepFunction r)-          desc = "buildSpecialDSOMandTargets " ++ show len ++ " "-            ++ show ps ++ " " ++ show r ++ " " ++ show targets+          fr = stepFunction r+          s = DSOM gm fr testPatternDiff adjustTestPattern  -- | Generate a classifier and a training set. The training set will --   consist @j@ vectors of equal length, where @j@ is the number of --   patterns the classifier can model. After running through the --   training set a few times, the classifier should be very accurate at --   identifying any of those @j@ vectors.-sizedSpecialDSOMandTargets :: Int -> Gen SpecialDSOMandTargets-sizedSpecialDSOMandTargets n = do+sizedSpecialDSOMTestData :: Int -> Gen SpecialDSOMTestData+sizedSpecialDSOMTestData n = do   sideLength <- choose (1, min (n+1) 5) --avoid long tests   let tileCount = 3*sideLength*(sideLength-1) + 1-  let ps = map MkPattern $ take tileCount [0,100..]+  let ps = map TestPattern $ take tileCount [0,100..]   r <- choose (0.001, 1)-  let targets = map MkPattern $ take tileCount [5,105..]-  return $ buildSpecialDSOMandTargets sideLength ps r targets+  let targets = map TestPattern $ take tileCount [5,105..]+  return $ buildSpecialDSOMTestData sideLength ps r targets -instance Arbitrary SpecialDSOMandTargets where-  arbitrary = sized sizedSpecialDSOMandTargets+instance Arbitrary SpecialDSOMTestData where+  arbitrary = sized sizedSpecialDSOMTestData  -- | If we train a classifier once on a set of patterns, where the --   number of patterns in the set is equal to the number of nodes in@@ -243,12 +249,12 @@ --   representation of the training set. The initial models and training --   set are designed to ensure that a single node will NOT train to --   more than one pattern (which would render the test invalid).-prop_batch_training_works2 :: SpecialDSOMandTargets -> Property-prop_batch_training_works2 (SpecialDSOMandTargets s xs _) =+prop_batch_training_works2 :: SpecialDSOMTestData -> Property+prop_batch_training_works2 (SpecialDSOMTestData s _ xs) =   errBefore /= 0 ==> errAfter < errBefore     where s' = trainBatch s xs-          errBefore = absDiff (sort xs) (sort (models s))-          errAfter = absDiff (sort xs) (sort (models s'))+          errBefore = euclideanDistanceSquared (map toDouble . sort $ xs) (map toDouble . sort . models $ s)+          errAfter = euclideanDistanceSquared (map toDouble . sort $ xs) (map toDouble . sort . models $ s')  test :: Test test = testGroup "QuickCheck Data.Datamining.Clustering.DSOM"
test/Data/Datamining/Clustering/SOMQC.hs view
@@ -1,7 +1,7 @@ ------------------------------------------------------------------------ -- | -- Module      :  Data.Datamining.Clustering.SOMQC--- Copyright   :  (c) Amy de Buitléir 2012-2014+-- Copyright   :  (c) Amy de Buitléir 2012-2015 -- License     :  BSD-style -- Maintainer  :  amy@nualeargais.ie -- Stability   :  experimental@@ -19,18 +19,17 @@     test   ) where -import Data.Datamining.Pattern (Pattern, Metric, difference,-  euclideanDistanceSquared, magnitudeSquared, makeSimilar)+import Data.Datamining.Pattern (euclideanDistanceSquared,+  magnitudeSquared, adjustNum, absDifference) import Data.Datamining.Clustering.Classifier(classify,   classifyAndTrain, reportAndTrain, differences, diffAndTrain, models,   numModels, train, trainBatch) import Data.Datamining.Clustering.SOMInternal -import Control.Applicative-import Data.Function (on) import Data.List (sort)+import Math.Geometry.Grid (size) import Math.Geometry.Grid.Hexagonal (HexHexGrid, hexHexGrid)-import Math.Geometry.GridMap ((!))+import Math.Geometry.GridMap ((!), elems) import Math.Geometry.GridMap.Lazy (LGridMap, lazyGridMap) import System.Random (Random) import Test.Framework as TF (Test, testGroup)@@ -38,101 +37,59 @@ import Test.QuickCheck ((==>), Gen, Arbitrary, arbitrary, choose,   Property, property, sized, suchThat, vectorOf) --- data GaussianArgs = GaussianArgs Double Double Int deriving Show- positive :: (Num a, Ord a, Arbitrary a) => Gen a positive = arbitrary `suchThat` (> 0) --- instance Arbitrary GaussianArgs where---   arbitrary = GaussianArgs <$> choose (0,1) <*> positive <*> positive---- arbDecayingGaussian :: Gen (DecayingGaussian--- prop_decayingGaussian_small_after_tMax :: GaussianArgs -> Property--- prop_decayingGaussian_small_after_tMax (GaussianArgs r w0 tMax) =---   property $ decayingGaussian r w0 tMax (tMax+1) 0 < exp(-1)---- prop_decayingGaussian_small_far_from_bmu :: GaussianArgs -> Property--- prop_decayingGaussian_small_far_from_bmu (GaussianArgs r w0 tMax)---   = property $---       decayingGaussian r w0 tMax 0 (2*(ceiling w0)) < r * exp(-1)+data DecayingGaussianParams a = DecayingGaussianParams a a a a a+  deriving (Eq, Show)  instance   (Random a, Num a, Ord a, Arbitrary a)-  => Arbitrary (DecayingGaussian a) where+  => Arbitrary (DecayingGaussianParams a) where   arbitrary = do     r0 <- choose (0,1)     rf <- choose (0,r0)     w0 <- positive     wf <- choose (0,w0)     tf <- positive-    return $ DecayingGaussian r0 rf w0 wf tf+    return $ DecayingGaussianParams r0 rf w0 wf tf  prop_DecayingGaussian_starts_at_r0-  :: DecayingGaussian Double -> Property-prop_DecayingGaussian_starts_at_r0 f@(DecayingGaussian r0 _ _ _ _)-  = property $ abs ((rate f 0 0) - r0) < 0.01+  :: DecayingGaussianParams Double -> Property+prop_DecayingGaussian_starts_at_r0 (DecayingGaussianParams r0 rf w0 wf tf)+  = property $ abs ((decayingGaussian r0 rf w0 wf tf 0 0) - r0) < 0.01  prop_DecayingGaussian_starts_at_w0-  :: DecayingGaussian Double -> Property-prop_DecayingGaussian_starts_at_w0 f@(DecayingGaussian r0 _ w0 _ _)+  :: DecayingGaussianParams Double -> Property+prop_DecayingGaussian_starts_at_w0 (DecayingGaussianParams r0 rf w0 wf tf)   = property $-    rate f 0 inside >= r0 * exp (-0.5) && rate f 0 outside < r0 * exp (-0.5)+    decayingGaussian r0 rf w0 wf tf 0 inside >= r0 * exp (-0.5)+      && decayingGaussian r0 rf w0 wf tf 0 outside < r0 * exp (-0.5)   where inside = w0 - 0.001         outside = w0 + 0.001  prop_DecayingGaussian_decays_to_rf-  :: DecayingGaussian Double -> Property-prop_DecayingGaussian_decays_to_rf f@(DecayingGaussian _ rf _ _ tf)-  = property $ abs ((rate f tf 0) - rf) < 0.01+  :: DecayingGaussianParams Double -> Property+prop_DecayingGaussian_decays_to_rf (DecayingGaussianParams r0 rf w0 wf tf)+  = property $ abs ((decayingGaussian r0 rf w0 wf tf tf 0) - rf) < 0.01  prop_DecayingGaussian_shrinks_to_wf-  :: DecayingGaussian Double -> Property-prop_DecayingGaussian_shrinks_to_wf f@(DecayingGaussian _ rf _ wf tf)+  :: DecayingGaussianParams Double -> Property+prop_DecayingGaussian_shrinks_to_wf (DecayingGaussianParams r0 rf w0 wf tf)   = property $-    rate f tf inside >= rf * exp (-0.5) && rate f tf outside < rf * exp (-0.5)+    decayingGaussian r0 rf w0 wf tf tf inside >= rf * exp (-0.5)+      && decayingGaussian r0 rf w0 wf tf tf outside < rf * exp (-0.5)   where inside = wf - 0.001         outside = wf + 0.001 -newtype TestPattern = MkPattern Double deriving Show--instance Eq TestPattern where-  (==) = (==) `on` toDouble--instance Ord TestPattern where-  compare = compare `on` toDouble--instance Pattern TestPattern where-  type Metric TestPattern = Double-  difference (MkPattern a) (MkPattern b) = abs (a - b)-  makeSimilar orig@(MkPattern a) r (MkPattern b)-    | r < 0     = error "Negative learning rate"-    | r > 1     = error "Learning rate > 1"-    | r == 1     = orig-    | otherwise = MkPattern (b + delta)-        where diff = a - b-              delta = r*diff--instance Arbitrary TestPattern where-  arbitrary = MkPattern <$> arbitrary--toDouble :: TestPattern -> Double-toDouble (MkPattern a) = a--absDiff :: [TestPattern] -> [TestPattern] -> Double-absDiff xs ys = euclideanDistanceSquared xs' ys'-  where xs' = map toDouble xs-        ys' = map toDouble ys--fractionDiff :: [TestPattern] -> [TestPattern] -> Double+fractionDiff :: [Double] -> [Double] -> Double fractionDiff xs ys = if denom == 0 then 0 else d / denom-  where d = sqrt $ euclideanDistanceSquared xs' ys'+  where d = sqrt $ euclideanDistanceSquared xs ys         denom = max xMag yMag-        xMag = sqrt $ magnitudeSquared xs'-        yMag = sqrt $ magnitudeSquared ys'-        xs' = map toDouble xs-        ys' = map toDouble ys+        xMag = sqrt $ magnitudeSquared xs+        yMag = sqrt $ magnitudeSquared ys -approxEqual :: [TestPattern] -> [TestPattern] -> Bool+approxEqual :: [Double] -> [Double] -> Bool approxEqual xs ys = fractionDiff xs ys <= 0.1  -- | A classifier and a training set. The training set will consist of@@ -140,22 +97,32 @@ --   the classifier can model. After running through the training set a --   few times, the classifier should be very accurate at identifying --   any of those @j@ vectors.-data SOMandTargets = SOMandTargets (SOM (DecayingGaussian Double)-  Int (LGridMap HexHexGrid) (Int, Int) TestPattern) [TestPattern]-    deriving (Eq, Show)+data SOMTestData+  = SOMTestData+    {+      som1 :: SOM Double Double (LGridMap HexHexGrid) Double (Int, Int) Double,+      params1 :: DecayingGaussianParams Double,+      trainingSet1 :: [Double]+    } -buildSOMandTargets-  :: Int -> [TestPattern] -> Double -> Double -> Double -> Double -> Int-     -> [TestPattern] -> SOMandTargets-buildSOMandTargets len ps r0 rf w0 wf tf targets =-  SOMandTargets s targets+instance Show SOMTestData where+  show s = "buildSOMTestData " ++ show (size . gridMap . som1 $ s)+    ++ " " ++ show (elems . gridMap . som1 $ s)+    ++ " (" ++ show (params1 s) +    ++ ") " ++ show (trainingSet1 s) ++buildSOMTestData+  :: Int -> [Double] -> DecayingGaussianParams Double+     -> [Double] -> SOMTestData+buildSOMTestData len ps p@(DecayingGaussianParams r0 rf w0 wf tf) targets =+  SOMTestData s p targets     where g = hexHexGrid len           gm = lazyGridMap g ps-          tf' = fromIntegral tf-          s = SOM gm (DecayingGaussian r0 rf w0 wf tf') 0+          fr = decayingGaussian r0 rf w0 wf tf+          s = SOM gm fr absDifference adjustNum 0 -sizedSOMandTargets :: Int -> Gen SOMandTargets-sizedSOMandTargets n = do+sizedSOMTestData :: Int -> Gen SOMTestData+sizedSOMTestData n = do   sideLength <- choose (1, min (n+1) 5) --avoid long tests   let tileCount = 3*sideLength*(sideLength-1) + 1   let numberOfPatterns = tileCount@@ -166,37 +133,37 @@   wf <- choose (0, w0)   tf <- choose (1, 10)   targets <- vectorOf numberOfPatterns arbitrary-  return $ buildSOMandTargets sideLength ps r0 rf w0 wf tf targets+  return $ buildSOMTestData sideLength ps (DecayingGaussianParams r0 rf w0 wf tf) targets -instance Arbitrary SOMandTargets where-  arbitrary = sized sizedSOMandTargets+instance Arbitrary SOMTestData where+  arbitrary = sized sizedSOMTestData  -- | If we use a fixed learning rate of one (regardless of the distance --   from the BMU), and train a classifier once on one pattern, then all --   nodes should match the input vector.-prop_global_instant_training_works :: SOMandTargets -> Property-prop_global_instant_training_works (SOMandTargets s xs) =+prop_global_instant_training_works :: SOMTestData -> Property+prop_global_instant_training_works (SOMTestData s _ xs) =   property $ finalModels `approxEqual` expectedModels     where x = head xs-          gm = toGridMap s :: LGridMap HexHexGrid TestPattern-          f = (ConstantFunction 1)-          s2 = SOM gm f 0+          gm = toGridMap s :: LGridMap HexHexGrid Double+          f _ _ = 1+          s2 = SOM gm f absDifference adjustNum 0           s3 = train s2 x-          finalModels = models s3 :: [TestPattern]-          expectedModels = replicate (numModels s) x :: [TestPattern]+          finalModels = models s3 :: [Double]+          expectedModels = replicate (numModels s) x :: [Double] -prop_training_reduces_error :: SOMandTargets -> Property-prop_training_reduces_error (SOMandTargets s xs) = errBefore /= 0 ==>+prop_training_reduces_error :: SOMTestData -> Property+prop_training_reduces_error (SOMTestData s _ xs) = errBefore /= 0 ==>   errAfter < errBefore     where (bmu, s') = classifyAndTrain s x           x = head xs-          errBefore = abs $ toDouble x - toDouble (gridMap s ! bmu)-          errAfter = abs $ toDouble x - toDouble (gridMap s' ! bmu)+          errBefore = abs $ x - (gridMap s ! bmu)+          errAfter = abs $ x - (gridMap s' ! bmu)  --   Invoking @diffAndTrain f s p@ should give identical results to --   @(p `classify` s, train s f p)@.-prop_classifyAndTrainEquiv :: SOMandTargets -> Property-prop_classifyAndTrainEquiv (SOMandTargets s ps) = property $+prop_classifyAndTrainEquiv :: SOMTestData -> Property+prop_classifyAndTrainEquiv (SOMTestData s _ ps) = property $   bmu == s `classify` p && gridMap s1 == gridMap s2     where p = head ps           (bmu, s1) = classifyAndTrain s p@@ -204,8 +171,8 @@  --   Invoking @diffAndTrain f s p@ should give identical results to --   @(s `diff` p, train s f p)@.-prop_diffAndTrainEquiv :: SOMandTargets -> Property-prop_diffAndTrainEquiv (SOMandTargets s ps) = property $+prop_diffAndTrainEquiv :: SOMTestData -> Property+prop_diffAndTrainEquiv (SOMTestData s _ ps) = property $   diffs == s `differences` p && gridMap s1 == gridMap s2     where p = head ps           (diffs, s1) = diffAndTrain s p@@ -213,8 +180,8 @@  --   Invoking @trainNeighbourhood s (classify s p) p@ should give --   identical results to @train s p@.-prop_trainNeighbourhoodEquiv :: SOMandTargets -> Property-prop_trainNeighbourhoodEquiv (SOMandTargets s ps) = property $+prop_trainNeighbourhoodEquiv :: SOMTestData -> Property+prop_trainNeighbourhoodEquiv (SOMTestData s _ ps) = property $   gridMap s1 == gridMap s2     where p = head ps           s1 = trainNeighbourhood s (classify s p) p@@ -223,8 +190,8 @@ -- | The training set consists of the same vectors in the same order, --   several times over. So the resulting classifications should consist --   of the same integers in the same order, over and over.-prop_batch_training_works :: SOMandTargets -> Property-prop_batch_training_works (SOMandTargets s xs) = property $+prop_batch_training_works :: SOMTestData -> Property+prop_batch_training_works (SOMTestData s _ xs) = property $   classifications == (concat . replicate 5) firstSet   where trainingSet = (concat . replicate 5) xs         s' = trainBatch s trainingSet@@ -233,41 +200,51 @@  -- | WARNING: This can fail when two nodes are close enough in --   value so that after training they become identical.+--   This only happens rarely, so if the test fails, try again. prop_classification_is_consistent-  :: SOMandTargets -> Property-prop_classification_is_consistent (SOMandTargets s (x:_))+  :: SOMTestData -> Property+prop_classification_is_consistent (SOMTestData s _ (x:_))   = property $ bmu == bmu'   where (bmu, _, s') = reportAndTrain s x         (bmu', _, _) = reportAndTrain s' x prop_classification_is_consistent _ = error "Should not happen" --- | Same as SOMandTargets, except that the initial models and training+-- | Same as SOMTestData, except that the initial models and training --   set are designed to ensure that a single node will NOT train to --   more than one pattern.-data SpecialSOMandTargets = SpecialSOMandTargets (SOM-  (StepFunction Double) Int (LGridMap HexHexGrid) (Int, Int)-  TestPattern) [TestPattern]-    deriving (Eq, Show)+data SpecialSOMTestData+  = SpecialSOMTestData+    {+      som2 :: SOM Int Int (LGridMap HexHexGrid) Double (Int, Int) Double,+      params2 :: Double,+      trainingSet2 :: [Double]+    } -buildSpecialSOMandTargets-  :: Int -> [TestPattern] -> Double -> [TestPattern] -> SpecialSOMandTargets-buildSpecialSOMandTargets len ps r targets =-  SpecialSOMandTargets s targets+instance Show SpecialSOMTestData where+  show s = "buildSpecialSOMTestData " ++ show (size . gridMap . som2 $ s)+    ++ " " ++ show (elems . gridMap . som2 $ s)+    ++ " " ++ show (params2 s) +    ++ " " ++ show (trainingSet2 s) ++buildSpecialSOMTestData+  :: Int -> [Double] -> Double -> [Double] -> SpecialSOMTestData+buildSpecialSOMTestData len ps r targets =+  SpecialSOMTestData s r targets     where g = hexHexGrid len           gm = lazyGridMap g ps-          s = SOM gm (StepFunction r) 0+          s = SOM gm (stepFunction r) absDifference adjustNum 0 -sizedSpecialSOMandTargets :: Int -> Gen SpecialSOMandTargets-sizedSpecialSOMandTargets n = do+sizedSpecialSOMTestData :: Int -> Gen SpecialSOMTestData+sizedSpecialSOMTestData n = do   sideLength <- choose (1, min (n+1) 5) --avoid long tests   let tileCount = 3*sideLength*(sideLength-1) + 1-  let ps = map MkPattern $ take tileCount [0,100..]+  let ps = take tileCount [0,100..]   r <- choose (0.001, 1)-  let targets = map MkPattern $ take tileCount [5,105..]-  return $ buildSpecialSOMandTargets sideLength ps r targets+  let targets = take tileCount [5,105..]+  return $ buildSpecialSOMTestData sideLength ps r targets -instance Arbitrary SpecialSOMandTargets where-  arbitrary = sized sizedSpecialSOMandTargets+instance Arbitrary SpecialSOMTestData where+  arbitrary = sized sizedSpecialSOMTestData  -- | If we train a classifier once on a set of patterns, where the --   number of patterns in the set is equal to the number of nodes in@@ -275,30 +252,40 @@ --   representation of the training set. The initial models and training --   set are designed to ensure that a single node will NOT train to --   more than one pattern (which would render the test invalid).-prop_batch_training_works2 :: SpecialSOMandTargets -> Property-prop_batch_training_works2 (SpecialSOMandTargets s xs) =+prop_batch_training_works2 :: SpecialSOMTestData -> Property+prop_batch_training_works2 (SpecialSOMTestData s _ xs) =   errBefore /= 0 ==> errAfter < errBefore     where s' = trainBatch s xs-          errBefore = absDiff (sort xs) (sort (models s))-          errAfter = absDiff (sort xs) (sort (models s'))+          errBefore = euclideanDistanceSquared (sort xs) (sort (models s))+          errAfter = euclideanDistanceSquared (sort xs) (sort (models s')) -data IncompleteSOMandTargets = IncompleteSOMandTargets (SOM-  (DecayingGaussian Double) Int (LGridMap HexHexGrid) (Int, Int)-  TestPattern) [TestPattern] deriving Show+data IncompleteSOMTestData+  = IncompleteSOMTestData+    {+      som3 :: SOM Double Double (LGridMap HexHexGrid) Double (Int, Int) Double,+      params3 :: DecayingGaussianParams Double,+      trainingSet3 :: [Double]+    } -buildIncompleteSOMandTargets-  :: Int -> [TestPattern] -> Double -> Double -> Double -> Double -> Int-     -> [TestPattern] -> IncompleteSOMandTargets-buildIncompleteSOMandTargets len ps r0 rf w0 wf tf targets =-  IncompleteSOMandTargets s targets+instance Show IncompleteSOMTestData where+  show s = "buildIncompleteSOMTestData " ++ show (size . gridMap . som3 $ s)+    ++ " " ++ show (elems . gridMap . som3 $ s)+    ++ " " ++ show (params3 s) +    ++ " " ++ show (trainingSet3 s) ++buildIncompleteSOMTestData+  :: Int -> [Double] -> DecayingGaussianParams Double+     -> [Double] -> IncompleteSOMTestData+buildIncompleteSOMTestData len ps p@(DecayingGaussianParams r0 rf w0 wf tf) targets =+  IncompleteSOMTestData s p targets     where g = hexHexGrid len           gm = lazyGridMap g ps-          tf' = fromIntegral tf-          s = SOM gm (DecayingGaussian r0 rf w0 wf tf') 0+          fr = decayingGaussian r0 rf w0 wf tf+          s = SOM gm fr absDifference adjustNum 0 --- | Same as sizedSOMandTargets, except some nodes don't have a value.-sizedIncompleteSOMandTargets :: Int -> Gen IncompleteSOMandTargets-sizedIncompleteSOMandTargets n = do+-- | Same as sizedSOMTestData, except some nodes don't have a value.+sizedIncompleteSOMTestData :: Int -> Gen IncompleteSOMTestData+sizedIncompleteSOMTestData n = do   sideLength <- choose (2, min (n+2) 5) --avoid long tests   let tileCount = 3*sideLength*(sideLength-1) + 1   numberOfPatterns <- choose (1,tileCount-1)@@ -309,18 +296,18 @@   wf <- choose (0, w0)   tf <- choose (1, 10)   targets <- vectorOf numberOfPatterns arbitrary-  return $ buildIncompleteSOMandTargets sideLength ps r0 rf w0 wf tf targets+  return $ buildIncompleteSOMTestData sideLength ps (DecayingGaussianParams r0 rf w0 wf tf) targets -instance Arbitrary IncompleteSOMandTargets where-  arbitrary = sized sizedIncompleteSOMandTargets+instance Arbitrary IncompleteSOMTestData where+  arbitrary = sized sizedIncompleteSOMTestData -prop_can_train_incomplete_SOM :: IncompleteSOMandTargets -> Property-prop_can_train_incomplete_SOM (IncompleteSOMandTargets s xs) = errBefore /= 0 ==>+prop_can_train_incomplete_SOM :: IncompleteSOMTestData -> Property+prop_can_train_incomplete_SOM (IncompleteSOMTestData s _ xs) = errBefore /= 0 ==>   errAfter < errBefore     where (bmu, s') = classifyAndTrain s x           x = head xs-          errBefore = abs $ toDouble x - toDouble (gridMap s ! bmu)-          errAfter = abs $ toDouble x - toDouble (gridMap s' ! bmu)+          errBefore = abs $ x - (gridMap s ! bmu)+          errAfter = abs $ x - (gridMap s' ! bmu)  test :: Test test = testGroup "QuickCheck Data.Datamining.Clustering.SOM"
test/Data/Datamining/Clustering/SSOMQC.hs view
@@ -1,7 +1,7 @@ ------------------------------------------------------------------------ -- | -- Module      :  Data.Datamining.Clustering.SSOMQC--- Copyright   :  (c) Amy de Buitléir 2012-2014+-- Copyright   :  (c) Amy de Buitléir 2012-2015 -- License     :  BSD-style -- Maintainer  :  amy@nualeargais.ie -- Stability   :  experimental@@ -19,115 +19,102 @@     test   ) where -import Data.Datamining.Pattern (Pattern, Metric, difference,-  euclideanDistanceSquared, makeSimilar)+import Data.Datamining.Pattern (euclideanDistanceSquared, adjustNum,+  absDifference) import Data.Datamining.Clustering.Classifier(classify,   classifyAndTrain, reportAndTrain, differences, diffAndTrain, models,   train, trainBatch) import Data.Datamining.Clustering.SSOMInternal import qualified Data.Map.Strict as M -import Control.Applicative-import Data.Function (on) import Data.List (sort) import System.Random (Random) import Test.Framework as TF (Test, testGroup) import Test.Framework.Providers.QuickCheck2 (testProperty)-import Test.QuickCheck ((==>), Gen, Arbitrary, arbitrary, choose,-  Property, property, sized, suchThat, vectorOf)+import Test.QuickCheck ((==>), Gen, Arbitrary, Property, Positive,+  arbitrary, shrink, choose, property, sized, suchThat, vectorOf,+  getPositive) -positive :: (Num a, Ord a, Arbitrary a) => Gen a-positive = arbitrary `suchThat` (> 0)+newtype UnitInterval a = UnitInterval {getUnitInterval :: a}+ deriving ( Eq, Ord, Show, Read) -instance-  (Random a, Num a, Ord a, Arbitrary a)-  => Arbitrary (Exponential a) where-  arbitrary = do-    r0 <- choose (0,1)-    d <- positive-    return $ Exponential r0 d+instance Functor UnitInterval where+  fmap f (UnitInterval x) = UnitInterval (f x) +instance (Num a, Ord a, Random a, Arbitrary a)+    => Arbitrary (UnitInterval a) where+  arbitrary = fmap UnitInterval $ choose (0,1)+  shrink (UnitInterval x) =+    [ UnitInterval x' | x' <- shrink x, x' >= 0, x' <= 1]+ prop_Exponential_starts_at_r0-  :: Exponential Double -> Property-prop_Exponential_starts_at_r0 f@(Exponential r0 _)-  = property $ abs (rate f 0 - r0) < 0.01+  :: UnitInterval Double -> Positive Double -> Property+prop_Exponential_starts_at_r0 r0 d+  = property $ abs (exponential r0' d' 0 - r0') < 0.01+  where r0' = getUnitInterval r0+        d' = getPositive d  prop_Exponential_ge_0-  :: Exponential Double -> Double -> Property-prop_Exponential_ge_0 f t-  = property $ rate f t' >= 0-  where t' = abs t--newtype TestPattern = MkPattern Double deriving Show--instance Eq TestPattern where-  (==) = (==) `on` toDouble--instance Ord TestPattern where-  compare = compare `on` toDouble--instance Pattern TestPattern where-  type Metric TestPattern = Double-  difference (MkPattern a) (MkPattern b) = abs (a - b)-  makeSimilar orig@(MkPattern a) r (MkPattern b)-    | r < 0     = error "Negative learning rate"-    | r > 1     = error "Learning rate > 1"-    | r == 1     = orig-    | otherwise = MkPattern (b + delta)-        where diff = a - b-              delta = r*diff--instance Arbitrary TestPattern where-  arbitrary = MkPattern <$> arbitrary--toDouble :: TestPattern -> Double-toDouble (MkPattern a) = a+  :: UnitInterval Double -> Positive Double -> Positive Double -> Property+prop_Exponential_ge_0 r0 d t = property $ exponential r0' d' t' >= 0+  where r0' = getUnitInterval r0+        d' = getPositive d+        t' = getPositive t -absDiff :: [TestPattern] -> [TestPattern] -> Double-absDiff xs ys = euclideanDistanceSquared xs' ys'-  where xs' = map toDouble xs-        ys' = map toDouble ys+positive :: (Num a, Ord a, Arbitrary a) => Gen a+positive = arbitrary `suchThat` (> 0)  -- | A classifier and a training set. The training set will consist of --   @j@ vectors of equal length, where @j@ is the number of patterns --   the classifier can model. After running through the training set a --   few times, the classifier should be very accurate at identifying --   any of those @j@ vectors.-data SSOMandTargets = SSOMandTargets (SSOM (Exponential Double)-  Int Int TestPattern) [TestPattern]-    deriving (Eq, Show)+data SSOMTestData+  = SSOMTestData+    {+      som1 :: SSOM Double Double Int Double,+      learningRateDesc1 :: String,+      trainingSet1 :: [Double]+    } -buildSSOMandTargets-  :: [TestPattern] -> Double -> Double -> [TestPattern] -> SSOMandTargets-buildSSOMandTargets ps r0 d targets =-  SSOMandTargets s targets+instance Show SSOMTestData where+  show s = "buildSSOMTestData " ++ show (M.elems . sMap . som1 $ s)+    ++ " " ++ learningRateDesc1 s +    ++ " " ++ show (trainingSet1 s) ++buildSSOMTestData+  :: [Double] -> Double -> Double -> [Double] -> SSOMTestData+buildSSOMTestData ps r0 d targets =+  SSOMTestData s desc targets     where gm = M.fromList . zip [0..] $ ps-          s = SSOM gm (Exponential r0 d) 0+          lrf = exponential r0 d+          s = SSOM gm lrf absDifference adjustNum 0+          desc = show r0 ++ " " ++ show d -sizedSSOMandTargets :: Int -> Gen SSOMandTargets-sizedSSOMandTargets n = do+sizedSSOMTestData :: Int -> Gen SSOMTestData+sizedSSOMTestData n = do   let len = n + 1   ps <- vectorOf len arbitrary   r0 <- choose (0, 1)   d <- positive   targets <- vectorOf len arbitrary-  return $ buildSSOMandTargets ps r0 d targets+  return $ buildSSOMTestData ps r0 d targets -instance Arbitrary SSOMandTargets where-  arbitrary = sized sizedSSOMandTargets+instance Arbitrary SSOMTestData where+  arbitrary = sized sizedSSOMTestData -prop_training_reduces_error :: SSOMandTargets -> Property-prop_training_reduces_error (SSOMandTargets s xs) = errBefore /= 0 ==>+prop_training_reduces_error :: SSOMTestData -> Property+prop_training_reduces_error (SSOMTestData s _ xs) = errBefore /= 0 ==>   errAfter < errBefore     where (bmu, s') = classifyAndTrain s x           x = head xs-          errBefore = abs $ toDouble x - toDouble (toMap s M.! bmu)-          errAfter = abs $ toDouble x - toDouble (toMap s' M.! bmu)+          errBefore = abs $ x - (toMap s M.! bmu)+          errAfter = abs $ x - (toMap s' M.! bmu)  --   Invoking @diffAndTrain f s p@ should give identical results to --   @(p `classify` s, train s f p)@.-prop_classifyAndTrainEquiv :: SSOMandTargets -> Property-prop_classifyAndTrainEquiv (SSOMandTargets s ps) = property $+prop_classifyAndTrainEquiv :: SSOMTestData -> Property+prop_classifyAndTrainEquiv (SSOMTestData s _ ps) = property $   bmu == s `classify` p && toMap s1 == toMap s2     where p = head ps           (bmu, s1) = classifyAndTrain s p@@ -135,8 +122,8 @@  --   Invoking @diffAndTrain f s p@ should give identical results to --   @(s `diff` p, train s f p)@.-prop_diffAndTrainEquiv :: SSOMandTargets -> Property-prop_diffAndTrainEquiv (SSOMandTargets s ps) = property $+prop_diffAndTrainEquiv :: SSOMTestData -> Property+prop_diffAndTrainEquiv (SSOMTestData s _ ps) = property $   diffs == s `differences` p && toMap s1 == toMap s2     where p = head ps           (diffs, s1) = diffAndTrain s p@@ -144,8 +131,8 @@  --   Invoking @trainNode s (classify s p) p@ should give --   identical results to @train s p@.-prop_trainNodeEquiv :: SSOMandTargets -> Property-prop_trainNodeEquiv (SSOMandTargets s ps) = property $+prop_trainNodeEquiv :: SSOMTestData -> Property+prop_trainNodeEquiv (SSOMTestData s _ ps) = property $   toMap s1 == toMap s2     where p = head ps           s1 = trainNode s (classify s p) p@@ -154,8 +141,8 @@ -- | The training set consists of the same vectors in the same order, --   several times over. So the resulting classifications should consist --   of the same integers in the same order, over and over.-prop_batch_training_works :: SSOMandTargets -> Property-prop_batch_training_works (SSOMandTargets s xs) = property $+prop_batch_training_works :: SSOMTestData -> Property+prop_batch_training_works (SSOMTestData s _ xs) = property $   classifications == (concat . replicate 5) firstSet   where trainingSet = (concat . replicate 5) xs         s' = trainBatch s trainingSet@@ -164,39 +151,50 @@  -- | WARNING: This can fail when two nodes are close enough in --   value so that after training they become identical.-prop_classification_is_consistent :: SSOMandTargets -> Property-prop_classification_is_consistent (SSOMandTargets s (x:_))+prop_classification_is_consistent :: SSOMTestData -> Property+prop_classification_is_consistent (SSOMTestData s _ (x:_))   = property $ bmu == bmu'   where (bmu, _, s') = reportAndTrain s x         (bmu', _, _) = reportAndTrain s' x prop_classification_is_consistent _ = error "Should not happen" --- | Same as SSOMandTargets, except that the initial models and training+-- | Same as SSOMTestData, except that the initial models and training --   set are designed to ensure that a single node will NOT train to --   more than one pattern.-data SpecialSSOMandTargets = SpecialSSOMandTargets (SSOM-  (Exponential Double) Int Int TestPattern) [TestPattern]-    deriving (Eq, Show)+data SpecialSSOMTestData+  = SpecialSSOMTestData+    {+      som2 :: SSOM Double Double Int Double,+      learningRateDesc2 :: String,+      trainingSet2 :: [Double]+    } -buildSpecialSSOMandTargets-  :: [TestPattern] -> Double -> Double -> [TestPattern]-    -> SpecialSSOMandTargets-buildSpecialSSOMandTargets ps r0 d targets =-  SpecialSSOMandTargets s targets+instance Show SpecialSSOMTestData where+  show s = "buildSpecialSSOMTestData "+    ++ show (M.elems . sMap . som2 $ s)+    ++ " " ++ learningRateDesc2 s +    ++ " " ++ show (trainingSet2 s) ++buildSpecialSSOMTestData+  :: [Double] -> Double -> Double -> [Double] -> SpecialSSOMTestData+buildSpecialSSOMTestData ps r0 d targets =+  SpecialSSOMTestData s desc targets     where gm = M.fromList . zip [0..] $ ps-          s = SSOM gm (Exponential r0 d) 0+          lrf = exponential r0 d+          s = SSOM gm lrf absDifference adjustNum 0+          desc = show r0 ++ " " ++ show d -sizedSpecialSSOMandTargets :: Int -> Gen SpecialSSOMandTargets-sizedSpecialSSOMandTargets n = do+sizedSpecialSSOMTestData :: Int -> Gen SpecialSSOMTestData+sizedSpecialSSOMTestData n = do   let len = n + 1-  let ps = map MkPattern $ take len [0,100..]+  let ps = take len [0,100..]   r0 <- choose (0, 1)   d <- positive-  let targets = map MkPattern $ take len [5,105..]-  return $ buildSpecialSSOMandTargets ps r0 d targets+  let targets = take len [5,105..]+  return $ buildSpecialSSOMTestData ps r0 d targets -instance Arbitrary SpecialSSOMandTargets where-  arbitrary = sized sizedSpecialSSOMandTargets+instance Arbitrary SpecialSSOMTestData where+  arbitrary = sized sizedSpecialSSOMTestData  -- | If we train a classifier once on a set of patterns, where the --   number of patterns in the set is equal to the number of nodes in@@ -204,44 +202,56 @@ --   representation of the training set. The initial models and training --   set are designed to ensure that a single node will NOT train to --   more than one pattern (which would render the test invalid).-prop_batch_training_works2 :: SpecialSSOMandTargets -> Property-prop_batch_training_works2 (SpecialSSOMandTargets s xs) =+prop_batch_training_works2 :: SpecialSSOMTestData -> Property+prop_batch_training_works2 (SpecialSSOMTestData s _ xs) =   errBefore /= 0 ==> errAfter < errBefore     where s' = trainBatch s xs-          errBefore = absDiff (sort xs) (sort (models s))-          errAfter = absDiff (sort xs) (sort (models s'))+          errBefore = euclideanDistanceSquared (sort xs) (sort (models s))+          errAfter = euclideanDistanceSquared (sort xs) (sort (models s')) -data IncompleteSSOMandTargets = IncompleteSSOMandTargets (SSOM-  (Exponential Double) Int Int TestPattern) [TestPattern] deriving Show+-- | Same as sizedSSOMTestData, except some nodes don't have a value.+data IncompleteSSOMTestData+  = IncompleteSSOMTestData+    {+      som3 :: SSOM Double Double Int Double,+      learningRateDesc3 :: String,+      trainingSet3 :: [Double]+    } -buildIncompleteSSOMandTargets-  :: [TestPattern] -> Double -> Double -> [TestPattern]-    -> IncompleteSSOMandTargets-buildIncompleteSSOMandTargets ps r0 d targets =-  IncompleteSSOMandTargets s targets+instance Show IncompleteSSOMTestData where+  show s = "buildIncompleteSSOMTestData "+    ++ show (M.elems . sMap . som3 $ s)+    ++ " " ++ learningRateDesc3 s +    ++ " " ++ show (trainingSet3 s) ++buildIncompleteSSOMTestData+  :: [Double] -> Double -> Double -> [Double] -> IncompleteSSOMTestData+buildIncompleteSSOMTestData ps r0 d targets =+  IncompleteSSOMTestData s desc targets     where gm = M.fromList . zip [0..] $ ps-          s = SSOM gm (Exponential r0 d) 0+          lrf = exponential r0 d+          s = SSOM gm lrf absDifference adjustNum 0+          desc = show r0 ++ " " ++ show d --- | Same as sizedSSOMandTargets, except some nodes don't have a value.-sizedIncompleteSSOMandTargets :: Int -> Gen IncompleteSSOMandTargets-sizedIncompleteSSOMandTargets n = do+sizedIncompleteSSOMTestData :: Int -> Gen IncompleteSSOMTestData+sizedIncompleteSSOMTestData n = do   let len = n + 1   ps <- vectorOf len arbitrary   r0 <- choose (0, 1)   d <- positive   targets <- vectorOf len arbitrary-  return $ buildIncompleteSSOMandTargets ps r0 d targets+  return $ buildIncompleteSSOMTestData ps r0 d targets -instance Arbitrary IncompleteSSOMandTargets where-  arbitrary = sized sizedIncompleteSSOMandTargets+instance Arbitrary IncompleteSSOMTestData where+  arbitrary = sized sizedIncompleteSSOMTestData -prop_can_train_incomplete_SSOM :: IncompleteSSOMandTargets -> Property-prop_can_train_incomplete_SSOM (IncompleteSSOMandTargets s xs) = errBefore /= 0 ==>+prop_can_train_incomplete_SSOM :: IncompleteSSOMTestData -> Property+prop_can_train_incomplete_SSOM (IncompleteSSOMTestData s _ xs) = errBefore /= 0 ==>   errAfter < errBefore     where (bmu, s') = classifyAndTrain s x           x = head xs-          errBefore = abs $ toDouble x - toDouble (toMap s M.! bmu)-          errAfter = abs $ toDouble x - toDouble (toMap s' M.! bmu)+          errBefore = abs $ x - (toMap s M.! bmu)+          errAfter = abs $ x - (toMap s' M.! bmu)  test :: Test test = testGroup "QuickCheck Data.Datamining.Clustering.SSOM"
test/Data/Datamining/PatternQC.hs view
@@ -1,7 +1,7 @@ ------------------------------------------------------------------------ -- | -- Module      :  Data.Datamining.PatternQC--- Copyright   :  (c) Amy de Buitléir 2012-2014+-- Copyright   :  (c) Amy de Buitléir 2012-2015 -- License     :  BSD-style -- Maintainer  :  amy@nualeargais.ie -- Stability   :  experimental
test/Main.hs view
@@ -1,7 +1,7 @@ ------------------------------------------------------------------------ -- | -- Module      :  Main--- Copyright   :  (c) Amy de Buitléir 2012-2014+-- Copyright   :  (c) Amy de Buitléir 2012-2015 -- License     :  BSD-style -- Maintainer  :  amy@nualeargais.ie -- Stability   :  experimental