packages feed

som 4.0 → 4.1

raw patch · 3 files changed

+109/−67 lines, 3 files

Files

som.cabal view
@@ -1,5 +1,5 @@ name:           som-version:        4.0+version:        4.1 synopsis:       Self-Organising Maps description:    A Kohonen Self-organising Map (SOM) maps input patterns                  onto a regular grid (usually two-dimensional) where each
src/Data/Datamining/Clustering/SOM.hs view
@@ -16,7 +16,7 @@ -- -- In layman's terms, a SOM can be useful when you you want to discover -- the underlying structure of some data. A tutorial is available at--- <https://github.com/mhwombat/som/wiki>+-- <https://github.com/mhwombat/som/wiki>. -- -- References: --@@ -28,23 +28,20 @@ {-# LANGUAGE UnicodeSyntax #-} module Data.Datamining.Clustering.SOM   (+    -- * Construction     SOM,     defaultSOM,     customSOM,     gaussian,     decayingGaussian,-    toGridMap+    -- * Deconstruction+    toGridMap,+    -- * Advanced control+    trainNeighbourhood,+    incrementCounter   ) where  import Data.Datamining.Clustering.SOMInternal (SOM, defaultSOM,-  customSOM, gaussian, decayingGaussian, toGridMap)--{- $Vector-If you wish to use a SOM with raw numeric vectors, use @no-warn-orphans@-and add the following to your code:--> instance (Floating a, Fractional a, Ord a, Eq a) ⇒ Pattern [a] a where->   difference = euclideanDistanceSquared->   makeSimilar = adjustVector--}+  customSOM, gaussian, decayingGaussian, toGridMap, trainNeighbourhood,+  incrementCounter) 
src/Data/Datamining/Clustering/SOMInternal.hs view
@@ -16,14 +16,20 @@  module Data.Datamining.Clustering.SOMInternal   (+    -- * Construction     SOM(..),     defaultSOM,     customSOM,     gaussian,     decayingGaussian,-    toGridMap+    -- * Deconstruction+    toGridMap,+    -- * Advanced control+    trainNeighbourhood,+    incrementCounter   ) where +import qualified Data.Foldable as F (Foldable, foldr) import Data.List (foldl', minimumBy) import Data.Ord (comparing) import qualified Math.Geometry.Grid as G (Grid(..))@@ -32,6 +38,19 @@ import Data.Datamining.Clustering.Classifier(Classifier(..)) import Prelude hiding (lookup) +-- | A Self-Organising Map (SOM).+--+--   Although @SOM@ implements @GridMap@, most users will only need the+--   interface provided by @Classifier@. If you chose to use the +--   @GridMap@ functions, please note:+--+--   1. The functions @adjust@, and @adjustWithKey@ do not increment the+--      counter. You can do so manually with @incrementCounter@.+--+--   2. The functions @map@ and @mapWithKey@ are not implemented (they+--      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 gm k p = SOM   {     sGridMap ∷ gm p,@@ -39,10 +58,33 @@     sCounter ∷ Int   } +instance (F.Foldable gm) ⇒ F.Foldable (SOM gm k) where+  foldr f x g = F.foldr f x (sGridMap g)++instance (G.Grid (gm p)) ⇒ G.Grid (SOM gm k p) where+  type Index (SOM gm k p) = G.Index (gm p)+  indices = G.indices . sGridMap+  distance = G.distance . sGridMap+  neighbours = G.neighbours . sGridMap+  contains = G.contains . sGridMap+  viewpoint = G.viewpoint . sGridMap+  tileCount = G.tileCount . sGridMap+  null = G.null . sGridMap+  nonNull = G.nonNull . sGridMap++instance (F.Foldable gm, GM.GridMap gm p, G.Grid (GM.BaseGrid gm p)) ⇒ GM.GridMap (SOM gm k) p where+  type BaseGrid (SOM gm k) p = GM.BaseGrid gm p+  toGrid = GM.toGrid . sGridMap+  toMap = GM.toMap . sGridMap+  mapWithKey = error "Not implemented"+  adjustWithKey f k s = s { sGridMap=gm' }+    where gm = sGridMap s+          gm' = GM.adjustWithKey f k gm+ currentLearningFunction ∷ SOM gm k p → (Int → Metric p) currentLearningFunction s = (sLearningFunction s) (sCounter s) --- | Extract the grid and current models from the SOM.+-- | Extracts the grid and current models from the SOM. toGridMap ∷ GM.GridMap gm p ⇒ SOM gm k p → gm p toGridMap = sGridMap @@ -52,22 +94,29 @@ adjustNode g f target bmu k = makeSimilar target (f d)   where d = G.distance g bmu k -trainWithBMU+-- | Trains the specified node and the neighbourood around it to better+--   match a target.+--   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)) ⇒      SOM gm k p → G.Index (gm p) → p → SOM gm k p-trainWithBMU s bmu target = s { sGridMap=gm' }+trainNeighbourhood s bmu target = s { sGridMap=gm' }   where gm = sGridMap s         gm' = GM.mapWithKey (adjustNode gm f target bmu) gm         f = currentLearningFunction s +incrementCounter :: SOM gm k p → SOM gm k p+incrementCounter s = s { sCounter=sCounter 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)) ⇒      SOM gm k p → p → SOM gm k p-justTrain s p = trainWithBMU s bmu p+justTrain s p = trainNeighbourhood s bmu p   where ds = GM.toList . GM.map (p `difference`) . sGridMap $ s         bmu = fst . minimumBy (comparing snd) $ ds @@ -80,35 +129,33 @@   numModels = G.tileCount . sGridMap   models = GM.elems . sGridMap   differences s p = GM.toList . GM.map (p `difference`) . sGridMap $ s-  trainBatch s ps = (foldl' justTrain s ps) {sCounter=sCounter s + 1}-  reportAndTrain s p = (bmu, ds, s'')+  trainBatch s = incrementCounter . foldl' justTrain s+  reportAndTrain s p = (bmu, ds, incrementCounter s')     where ds = differences s p           bmu = fst . minimumBy (comparing snd) $ ds-          s' = trainWithBMU s bmu p-          s'' = s' { sCounter=sCounter s + 1}+          s' = trainNeighbourhood s bmu p  --- Creates a classifier with a default (bell-shaped) learning function.+-- | Creates a classifier with a default (bell-shaped) learning+--   function. Usage is @'defaultSOM' 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@] The learning rate to be applied to the BMU (Best Matching Unit)+--   at "time" zero. The BMU is the model which best matches the+--   current target pattern.+--+--   [@w@] The width of the bell curve at "time" zero.+--+--   [@t@] Controls how rapidly the learning rate decays. After this+--   time, any learning done by the classifier will be negligible.+--   We recommend setting this parameter to the number of patterns+--   (or pattern batches) that will be presented to the classifier. An+--   estimate is fine. defaultSOM -  ∷ Floating (Metric p) ⇒-  -- | The geometry and initial models for this classifier.-  --   A reasonable choice here is 'lazyGridMap g ps', where 'g' is a-  --   @'Math.Geometry.Grid.HexHexGrid'@, and 'ps' is a set of-  --   random patterns.-  gm p →-  -- | The learning rate to be applied to the BMU (Best Matching Unit)-  --   at "time" zero. The BMU is the model which best matches the-  --   current target pattern.-  Metric p →-  -- | The width of the bell curve at "time" zero.-  Metric p →-  -- | After this time, any learning done by the classifier will be-  --   negligible. Recommend setting this parameter to the number of-  --   patterns (or pattern batches) that will be presented to the-  --   classifier. An estimate is fine.-  Int →-  -- | The result-  SOM gm k p+  ∷ Floating (Metric p) ⇒ gm p → Metric p → Metric p → Int → SOM gm k p defaultSOM gm r w t =    SOM {          sGridMap=gm, @@ -116,26 +163,24 @@         sCounter=0       } --- Creates a classifier with a custom learning function.-customSOM ∷ -  -- | The geometry and initial models for this classifier.-  --   A reasonable choice here is 'lazyGridMap g ps', where 'g' is a-  --   @'Math.Geometry.Grid.HexHexGrid'@, and 'ps' is a set of-  --   random patterns.-  gm p →-  -- | A function used to adjust the models in the classifier.-  --   This function will be invoked with two parameters.-  --   The first parameter will indicate how many patterns (or pattern -  --   batches) have previously been presented to this classifier. -  --   Typically this is used to make the learning rate decay over time.-  --   The second parameter to the function 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.-  (Int → Int → Metric p) →-  -- | The result-  SOM gm k p+-- | Creates a classifier with a custom learning function. +--   Usage is @'customSOM' 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 adjust the models in the classifier.+--   This function will be invoked with two parameters.+--   The first parameter will indicate how many patterns (or pattern +--   batches) have previously been presented to this classifier. +--   Typically this is used to make the learning rate decay over time.+--   The second parameter to the function 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.+customSOM ∷ gm p → (Int → Int → Metric p) → SOM gm k p customSOM gm f =    SOM {         sGridMap=gm,@@ -158,11 +203,11 @@   where d' = fromIntegral d  -- | Configures a typical learning function for classifiers.---   @'decayingGaussian r w0 tMax' returns a bell curve-shaped function.---   At time zero, the maximum learning rate (applied to the BMU) is ---   @r@, and the neighbourhood width is @w@. Over time the bell curve---   shrinks and the learning rate tapers off, until at time @tMax@,---   the learning rate is negligible.+--   @'decayingGaussian' r w0 tMax@ returns a bell curve-shaped+--   function. At time zero, the maximum learning rate (applied to the +--   BMU) is @r@, and the neighbourhood width is @w@. Over time the bell+--   curve shrinks and the learning rate tapers off, until at time+--   @tMax@, the learning rate is negligible. decayingGaussian   ∷ Floating a ⇒ a → a → Int → (Int → Int → a) decayingGaussian r w0 tMax =