Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use a random generator-using function with fmap in haskell?

Tags:

random

haskell

I am researching with evolutionary neural networks, and am using HNN. My first question is if there exist any evolutionary algorithm frameworks in Haskell already, as I was not able to find any?

I am currently struggling to find a way to mutate the weights of the neural network in a general way. At the moment, I am trying to map a random function (of of the form (RandomGen g) => g -> a -> (b,g)) over the HMatrix of weights.

I would like a generalizable way to modify an existing fmap (or fold?) to make use of a random function if it can be done. For example, I might have a function that may or may not add some Gaussian noise to its input, and would like that to apply to the entire network. The problem I'm having is how to work with the random number generators.

For map, I am currently doing the following:

rmap :: (StdGen -> a -> (b,StdGen)) -> StdGen -> [a] -> ([b],StdGen)
rmap _ g [] = ([],g)
rmap f g (x:xs) = let (mapped, g') = rmap f g xs
                      (rVal, g'')  = f g' x
                   in (rVal:mapped, g'')

This seems like a hack to me, and I was hoping some of the better haskellers might have some advice on how to deal with this randomness more effectively?

like image 378
Eric Klinkhammer Avatar asked Feb 06 '17 22:02

Eric Klinkhammer


2 Answers

I cannot say anything about the neural networks side of this problem (I hope someone posts something about that). From a general Haskeller's perspective, it looks like you should be doing your computation inside some sort of random monad. For example, MonadRandom.

Then, your rmap's signature turns into something like:

rmap :: MonadRandom m => (a -> m b) -> [a] -> m [b]

Just looking at that signature, you may realize that rmap is traverse in disguise.

The key pattern to recognize here is that things that look like StdGen -> a -> (b,StdGen) can be transformed into a -> m b for a random monad (that may even be IO). Once you see that, you can start using the full power of Haskell's monad utilities.

like image 165
Alec Avatar answered Oct 21 '22 13:10

Alec


This is what the Traversable class is for. mapAccumL (along with its back-to-front twin mapAccumR) is a higher-order function which captures a sort of generalised fold-and-map operation, statefully working across a traversable structure and transforming the elements. Your randomised mapping function is an example of this pattern - as you can see, mapAccumL's type matches the type of your function quite closely:

mapAccumL :: Traversable t => (a      -> b -> (a, c))      -> a      -> t b -> (a, t c)
rmap      ::                  (StdGen -> a -> (b, StdGen)) -> StdGen -> [a] -> ([b], StdGen)

We can set t ~ [] and a ~ StdGen, so that rmap is basically another name for mapAccumL, after some tuple-flipping.

rmap f z = swap . mapAccumL (\x y -> swap (f x y)) z
like image 7
Benjamin Hodgson Avatar answered Oct 21 '22 13:10

Benjamin Hodgson