som 2.0 → 3.0
raw patch · 3 files changed
+102/−62 lines, 3 filesdep ~gridPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: grid
API changes (from Hackage documentation)
- Data.Datamining.Clustering.SOM: differences :: Pattern p v => p -> GridMap g k p -> GridMap g k v
- Data.Datamining.Clustering.SOM: diffs :: Pattern p v => GridMap g k p -> p -> GridMap g k v
- Data.Datamining.Clustering.SOMInternal: differences :: Pattern p v => p -> GridMap g k p -> GridMap g k v
- Data.Datamining.Clustering.SOMInternal: diffs :: Pattern p v => GridMap g k p -> p -> GridMap g k v
- Data.Datamining.Clustering.SOMInternal: instance (Floating a, Fractional a, Ord a, Eq a) => Pattern (NormalisedVector a) a
- Data.Datamining.Clustering.SOMInternal: instance (Fractional a, Ord a, Eq a) => Pattern (ScaledVector a) a
+ Data.Datamining.Clustering.SOM: diff :: (GridMap gm p, Pattern p, GridMap gm m, Metric p ~ m, BaseGrid gm p ~ BaseGrid gm m) => gm p -> p -> gm m
+ Data.Datamining.Clustering.SOMInternal: diff :: (GridMap gm p, Pattern p, GridMap gm m, Metric p ~ m, BaseGrid gm p ~ BaseGrid gm m) => gm p -> p -> gm m
+ Data.Datamining.Clustering.SOMInternal: instance (Floating a, Fractional a, Ord a, Eq a) => Pattern (NormalisedVector a)
+ Data.Datamining.Clustering.SOMInternal: instance (Fractional a, Ord a, Eq a) => Pattern (ScaledVector a)
- Data.Datamining.Clustering.SOM: class Pattern p v | p -> v
+ Data.Datamining.Clustering.SOM: class Pattern p where type family Metric p
- Data.Datamining.Clustering.SOM: classify :: (Ord v, Pattern p v) => GridMap g k p -> p -> k
+ Data.Datamining.Clustering.SOM: classify :: (GridMap gm p, Pattern p, GridMap gm m, Metric p ~ m, Ord m, k ~ Index (BaseGrid gm p), BaseGrid gm m ~ BaseGrid gm p) => gm p -> p -> k
- Data.Datamining.Clustering.SOM: classifyAndTrain :: (Eq k, Ord v, Pattern p v, Grid g s k) => (Int -> v) -> GridMap g k p -> p -> (k, GridMap g k p)
+ Data.Datamining.Clustering.SOM: classifyAndTrain :: (Ord m, GridMap gm p, GridMap gm m, GridMap gm (Int, p), GridMap gm (m, p), Grid (gm p), Pattern p, Metric p ~ m, Index (BaseGrid gm p) ~ Index (gm p), BaseGrid gm m ~ BaseGrid gm p) => gm p -> (Int -> m) -> p -> (Index (gm p), gm p)
- Data.Datamining.Clustering.SOM: diffAndTrain :: (Eq k, Ord v, Pattern p v, Grid g s k) => (Int -> v) -> GridMap g k p -> p -> (GridMap g k v, GridMap g k p)
+ Data.Datamining.Clustering.SOM: diffAndTrain :: (Ord m, GridMap gm p, GridMap gm m, GridMap gm (Int, p), GridMap gm (m, p), Grid (gm p), Pattern p, Metric p ~ m, Index (BaseGrid gm p) ~ Index (gm p), BaseGrid gm m ~ BaseGrid gm p) => gm p -> (Int -> m) -> p -> (gm m, gm p)
- Data.Datamining.Clustering.SOM: difference :: Pattern p v => p -> p -> v
+ Data.Datamining.Clustering.SOM: difference :: Pattern p => p -> p -> Metric p
- Data.Datamining.Clustering.SOM: makeSimilar :: Pattern p v => p -> v -> p -> p
+ Data.Datamining.Clustering.SOM: makeSimilar :: Pattern p => p -> Metric p -> p -> p
- Data.Datamining.Clustering.SOM: train :: (Ord v, Pattern p v, Grid g s k) => (Int -> v) -> GridMap g k p -> p -> GridMap g k p
+ Data.Datamining.Clustering.SOM: train :: (Ord m, GridMap gm p, GridMap gm m, GridMap gm (Int, p), GridMap gm (m, p), Grid (gm p), Pattern p, Metric p ~ m, Index (BaseGrid gm p) ~ Index (gm p), BaseGrid gm m ~ BaseGrid gm p) => gm p -> (Int -> m) -> p -> gm p
- Data.Datamining.Clustering.SOM: trainBatch :: (Ord v, Grid g s k, Pattern p v) => (Int -> v) -> GridMap g k p -> [p] -> GridMap g k p
+ Data.Datamining.Clustering.SOM: trainBatch :: (Ord m, GridMap gm p, GridMap gm m, GridMap gm (Int, p), GridMap gm (m, p), Grid (gm p), Pattern p, Metric p ~ m, Index (BaseGrid gm p) ~ Index (gm p), BaseGrid gm m ~ BaseGrid gm p) => gm p -> (Int -> m) -> [p] -> gm p
- Data.Datamining.Clustering.SOMInternal: adjustNode :: Pattern p v => p -> (v, p) -> p
+ Data.Datamining.Clustering.SOMInternal: adjustNode :: Pattern p => p -> (Metric p, p) -> p
- Data.Datamining.Clustering.SOMInternal: class Pattern p v | p -> v
+ Data.Datamining.Clustering.SOMInternal: class Pattern p where type family Metric p
- Data.Datamining.Clustering.SOMInternal: classify :: (Ord v, Pattern p v) => GridMap g k p -> p -> k
+ Data.Datamining.Clustering.SOMInternal: classify :: (GridMap gm p, Pattern p, GridMap gm m, Metric p ~ m, Ord m, k ~ Index (BaseGrid gm p), BaseGrid gm m ~ BaseGrid gm p) => gm p -> p -> k
- Data.Datamining.Clustering.SOMInternal: classifyAndTrain :: (Eq k, Ord v, Pattern p v, Grid g s k) => (Int -> v) -> GridMap g k p -> p -> (k, GridMap g k p)
+ Data.Datamining.Clustering.SOMInternal: classifyAndTrain :: (Ord m, GridMap gm p, GridMap gm m, GridMap gm (Int, p), GridMap gm (m, p), Grid (gm p), Pattern p, Metric p ~ m, Index (BaseGrid gm p) ~ Index (gm p), BaseGrid gm m ~ BaseGrid gm p) => gm p -> (Int -> m) -> p -> (Index (gm p), gm p)
- Data.Datamining.Clustering.SOMInternal: diffAndTrain :: (Eq k, Ord v, Pattern p v, Grid g s k) => (Int -> v) -> GridMap g k p -> p -> (GridMap g k v, GridMap g k p)
+ Data.Datamining.Clustering.SOMInternal: diffAndTrain :: (Ord m, GridMap gm p, GridMap gm m, GridMap gm (Int, p), GridMap gm (m, p), Grid (gm p), Pattern p, Metric p ~ m, Index (BaseGrid gm p) ~ Index (gm p), BaseGrid gm m ~ BaseGrid gm p) => gm p -> (Int -> m) -> p -> (gm m, gm p)
- Data.Datamining.Clustering.SOMInternal: difference :: Pattern p v => p -> p -> v
+ Data.Datamining.Clustering.SOMInternal: difference :: Pattern p => p -> p -> Metric p
- Data.Datamining.Clustering.SOMInternal: makeSimilar :: Pattern p v => p -> v -> p -> p
+ Data.Datamining.Clustering.SOMInternal: makeSimilar :: Pattern p => p -> Metric p -> p -> p
- Data.Datamining.Clustering.SOMInternal: train :: (Ord v, Pattern p v, Grid g s k) => (Int -> v) -> GridMap g k p -> p -> GridMap g k p
+ Data.Datamining.Clustering.SOMInternal: train :: (Ord m, GridMap gm p, GridMap gm m, GridMap gm (Int, p), GridMap gm (m, p), Grid (gm p), Pattern p, Metric p ~ m, Index (BaseGrid gm p) ~ Index (gm p), BaseGrid gm m ~ BaseGrid gm p) => gm p -> (Int -> m) -> p -> gm p
- Data.Datamining.Clustering.SOMInternal: trainBatch :: (Ord v, Grid g s k, Pattern p v) => (Int -> v) -> GridMap g k p -> [p] -> GridMap g k p
+ Data.Datamining.Clustering.SOMInternal: trainBatch :: (Ord m, GridMap gm p, GridMap gm m, GridMap gm (Int, p), GridMap gm (m, p), Grid (gm p), Pattern p, Metric p ~ m, Index (BaseGrid gm p) ~ Index (gm p), BaseGrid gm m ~ BaseGrid gm p) => gm p -> (Int -> m) -> [p] -> gm p
Files
- som.cabal +10/−3
- src/Data/Datamining/Clustering/SOM.hs +3/−4
- src/Data/Datamining/Clustering/SOMInternal.hs +89/−55
som.cabal view
@@ -1,5 +1,5 @@ name: som-version: 2.0+version: 3.0 synopsis: Self-Organising Maps description: A Kohonen Self-organising Map (SOM) maps input patterns onto a regular grid (usually two-dimensional) where each@@ -11,6 +11,13 @@ . In layman's terms, a SOM can be useful when you you want to discover the underlying structure of some data.+ .+ The userguide is available at + <https://github.com/mhwombat/som/wiki>.+ .+ NOTE: Version 3.0 changed the order of parameters+ for many functions. This makes it easier for the user+ to write mapping and folding operations. category: Math cabal-version: >=1.8@@ -28,7 +35,7 @@ base-unicode-symbols ==0.2.*, binary == 0.5.*, containers ==0.4.2.* || ==0.5.*,- grid ==3.*,+ grid ==4.*, MonadRandom ==0.1.* ghc-options: -Wall exposed-modules: Data.Datamining.Clustering.SOM,@@ -41,7 +48,7 @@ QuickCheck == 2.5.*, test-framework == 0.8.*, som,- grid ==3.*,+ grid ==4.*, base-unicode-symbols ==0.2.*, MonadRandom ==0.1.*, random ==1.0.*
src/Data/Datamining/Clustering/SOM.hs view
@@ -1,7 +1,7 @@ ------------------------------------------------------------------------ -- | -- Module : Data.Datamining.Clustering.SOM--- Copyright : (c) Amy de Buitléir 2012+-- Copyright : (c) Amy de Buitléir 2012-2013 -- License : BSD-style -- Maintainer : amy@nualeargais.ie -- Stability : experimental@@ -36,8 +36,7 @@ trainBatch, classify, classifyAndTrain,- diffs,- differences, -- TO BE REMOVED+ diff, diffAndTrain, -- * Numeric vectors as patterns -- ** Normalised vectors@@ -54,7 +53,7 @@ ) where import Data.Datamining.Clustering.SOMInternal (adjustVector, classify, - classifyAndTrain, diffs, differences, diffAndTrain, + classifyAndTrain, diff, diffAndTrain, euclideanDistanceSquared, normalise, NormalisedVector, scale, ScaledVector, train, trainBatch, Pattern(..))
src/Data/Datamining/Clustering/SOMInternal.hs view
@@ -1,7 +1,7 @@ ------------------------------------------------------------------------ -- | -- Module : Data.Datamining.Clustering.SOMInternal--- Copyright : (c) Amy de Buitléir 2012+-- Copyright : (c) Amy de Buitléir 2012-2013 -- License : BSD-style -- Maintainer : amy@nualeargais.ie -- Stability : experimental@@ -10,9 +10,12 @@ -- A module containing private @SOM@ internals. Most developers should -- use @SOM@ instead. This module is subject to change without notice. --+-- NOTE: Version 3.0 changed the order of parameters for many functions.+-- This makes it easier for the user to write mapping and folding+-- operations.+-- -------------------------------------------------------------------------{-# LANGUAGE UnicodeSyntax, MultiParamTypeClasses, FlexibleInstances, - FunctionalDependencies #-}+{-# LANGUAGE UnicodeSyntax, TypeFamilies, FlexibleContexts #-} module Data.Datamining.Clustering.SOMInternal (@@ -20,8 +23,7 @@ adjustVector, classify, classifyAndTrain,- differences, -- TO BE REMOVED- diffs,+ diff, diffAndTrain, euclideanDistanceSquared, magnitudeSquared,@@ -38,16 +40,18 @@ import Data.Eq.Unicode ((≡)) import Data.List (foldl', minimumBy) import Data.Ord (comparing)-import Math.Geometry.Grid (distance, Grid)-import Math.Geometry.GridMap (GridMap, mapWithKey, toList)+import Math.Geometry.GridMap (GridMap, Index, BaseGrid, distance, + mapWithKey, toList)+import Math.Geometry.Grid (Grid) import qualified Math.Geometry.GridMap as GM (map) -- | A pattern to be learned or classified by a self-organising map.-class Pattern p v | p → v where+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 → v+ 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@ @@ -55,79 +59,107 @@ -- 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 → v → p → p+ makeSimilar ∷ p → Metric p → p → p +-- | @'diff' c pattern@ returns the positions of all nodes in +-- @c@, paired with the difference between @pattern@ and the node's +-- pattern.+diff + ∷ (GridMap gm p, Pattern p, GridMap gm m,+ Metric p ~ m, BaseGrid gm p ~ BaseGrid gm m) ⇒ + gm p → p → gm m+diff c pattern = GM.map (pattern `difference`) c+ -- | @classify c pattern@ returns the position of the node in @c@ -- whose pattern best matches the input @pattern@.-classify ∷ (Ord v, Pattern p v) ⇒ GridMap g k p → p → k+classify+ ∷ (GridMap gm p, Pattern p, GridMap gm m,+ Metric p ~ m, Ord m, k ~ Index (BaseGrid gm p), + BaseGrid gm m ~ BaseGrid gm p) ⇒ + gm p → p → k classify c pattern = - fst $ minimumBy (comparing snd) $ toList $ differences pattern c---- | @pattern \`'differences'\` c@ returns the positions of all nodes in --- @c@, paired with the difference between @pattern@ and the node's --- pattern. This function has been replaced with @'diffs'@, which--- swaps the parameter order to be consistent with @'classify'@.-{-# DEPRECATED differences "Use diffs instead" #-}-differences ∷ Pattern p v ⇒ p → GridMap g k p → GridMap g k v-differences pattern = GM.map (pattern `difference`)---- | @'diffs' c pattern@ returns the positions of all nodes in --- @c@, paired with the difference between @pattern@ and the node's --- pattern.-diffs ∷ Pattern p v ⇒ GridMap g k p → p → GridMap g k v-diffs c pattern = GM.map (pattern `difference`) c+ fst $ minimumBy (comparing snd) $ toList $ diff c pattern -- | If @f d@ is a function that returns the learning rate to apply to a -- node based on its distance @d@from the node that best matches the--- input pattern, then @'train' f c pattern@ returns a modified copy+-- input pattern, then @'train' c f pattern@ returns a modified copy -- of the classifier @c@ that has partially learned the @target@.-train ∷ (Ord v, Pattern p v, Grid g s k) ⇒- (Int → v) → GridMap g k p → p → GridMap g k p-train f c pattern = snd $ classifyAndTrain f c pattern+train+ ∷ (Ord m, GridMap gm p, GridMap gm m,+ GridMap gm (Int, p), GridMap gm (m, p), Grid (gm p),+ Pattern p, Metric p ~ m, Index (BaseGrid gm p) ~ Index (gm p),+ BaseGrid gm m ~ BaseGrid gm p) ⇒+ gm p → (Int → m) → p → gm p+train c f pattern = snd $ classifyAndTrain c f pattern -- | Same as @train@, but applied to multiple patterns.-trainBatch ∷ (Ord v, Grid g s k, Pattern p v) ⇒- (Int → v) → GridMap g k p → [p] → GridMap g k p-trainBatch f = foldl' (train f)+trainBatch+ ∷ (Ord m, GridMap gm p, GridMap gm m,+ GridMap gm (Int, p), GridMap gm (m, p), Grid (gm p),+ Pattern p, Metric p ~ m, Index (BaseGrid gm p) ~ Index (gm p),+ BaseGrid gm m ~ BaseGrid gm p) ⇒+ gm p → (Int → m) → [p] → gm p+trainBatch c f ps = foldl' (\som → train som f) c ps -- | If @f@ is a function that returns the learning rate to apply to a -- node based on its distance from the node that best matches the --- @target@, then @'classifyAndTrain' f c target@ returns a tuple +-- @target@, then @'classifyAndTrain' c f target@ returns a tuple -- containing the position of the node in @c@ whose pattern best -- matches the input @target@, and a modified copy of the classifier -- @c@ that has partially learned the @target@.--- Invoking @classifyAndTrain f c p@ may be faster than invoking--- @(p `classify` c, train f c p)@, but they should give identical+-- Invoking @classifyAndTrain c f p@ may be faster than invoking+-- @(p `classify` c, train c f p)@, but they should give identical -- results.-classifyAndTrain ∷ (Eq k, Ord v, Pattern p v, Grid g s k) ⇒ - (Int → v) → GridMap g k p → p → (k, GridMap g k p)-classifyAndTrain f c pattern = (bmu, c')- where bmu = classify c pattern- dMap = mapWithKey (\k p → (distance c k bmu, p)) c- lrMap = GM.map (\(d,p) → (f d, p)) dMap- c' = GM.map (adjustNode pattern) lrMap+classifyAndTrain+ ∷ (Ord m, GridMap gm p, GridMap gm m,+ GridMap gm (Int, p), GridMap gm (m, p), Grid (gm p),+ Pattern p, Metric p ~ m, Index (BaseGrid gm p) ~ Index (gm p),+ BaseGrid gm m ~ BaseGrid gm p) ⇒+ gm p → (Int → m) → p → (Index (gm p), gm p)+classifyAndTrain c f pattern = (bmu, c')+ where (bmu, _, c') = reportAndTrain c f pattern -- | If @f@ is a function that returns the learning rate to apply to a -- node based on its distance from the node that best matches the --- @target@, then @'diffAndTrain' f c target@ returns a tuple +-- @target@, then @'diffAndTrain' c f target@ returns a tuple -- containing: -- 1. The positions of all nodes in @c@, paired with the difference -- between @pattern@ and the node's pattern -- 2. A modified copy of the classifier @c@ that has partially -- learned the @target@.--- Invoking @diffAndTrain f c p@ may be faster than invoking--- @(p `differences` c, train f c p)@, but they should give identical+-- Invoking @diffAndTrain c f p@ may be faster than invoking+-- @(p `diff` c, train c f p)@, but they should give identical -- results.-diffAndTrain ∷ (Eq k, Ord v, Pattern p v, Grid g s k) ⇒ - (Int → v) → GridMap g k p → p → (GridMap g k v, GridMap g k p)-diffAndTrain f c pattern = (ds, c')- where ds = pattern `differences` c+diffAndTrain+ ∷ (Ord m, GridMap gm p, GridMap gm m,+ GridMap gm (Int, p), GridMap gm (m, p), Grid (gm p),+ Pattern p, Metric p ~ m, Index (BaseGrid gm p) ~ Index (gm p),+ BaseGrid gm m ~ BaseGrid gm p) ⇒+ gm p → (Int → m) → p → (gm m, gm p)+diffAndTrain c f pattern = (ds, c')+ where (_, ds, c') = reportAndTrain c f pattern++reportAndTrain+ ∷ (Ord m, GridMap gm p, GridMap gm m,+ GridMap gm (Int, p), GridMap gm (m, p), Grid (gm p),+ Pattern p, Metric p ~ m, Index (BaseGrid gm p) ~ Index (gm p),+ BaseGrid gm m ~ BaseGrid gm p) ⇒+ gm p → (Int → m) → p → (Index (gm p), gm m, gm p)+reportAndTrain c f pattern = (bmu, ds, c')+ where ds = c `diff` pattern bmu = fst $ minimumBy (comparing snd) $ toList ds- dMap = mapWithKey (\k p → (distance c k bmu, p)) c+ c' = trainWithBMU c f bmu pattern++trainWithBMU+ ∷ (GridMap gm p, GridMap gm (Int, p), GridMap gm (m, p),+ Grid (gm p), Pattern p, Metric p ~ m, k ~ Index (BaseGrid gm p), + k ~ Index (gm p)) ⇒+ gm p → (Int → m) → k → p → gm p+trainWithBMU c f bmu pattern = GM.map (adjustNode pattern) lrMap+ where dMap = mapWithKey (\k p → (distance c k bmu, p)) c lrMap = GM.map (\(d,p) → (f d, p)) dMap- c' = GM.map (adjustNode pattern) lrMap -adjustNode ∷ (Pattern p v) ⇒ p → (v,p) → p+adjustNode ∷ (Pattern p) ⇒ p → (Metric p, p) → p adjustNode target (r,p) = makeSimilar target r p --@@ -171,7 +203,8 @@ where f x = x*x instance (Floating a, Fractional a, Ord a, Eq a) ⇒ - Pattern (NormalisedVector a) a where+ Pattern (NormalisedVector a) where+ type Metric (NormalisedVector a) = a difference (NormalisedVector xs) (NormalisedVector ys) = euclideanDistanceSquared xs ys makeSimilar (NormalisedVector xs) r (NormalisedVector ys) = @@ -210,7 +243,8 @@ quantify' = zipWith f where f (minX, maxX) x = (min minX x, max maxX x) -instance (Fractional a, Ord a, Eq a) ⇒ Pattern (ScaledVector a) a where+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) =