I started with this code and modified and expanded it in Python. As an exercise/challenge to myself I decided to covert the original to Haskell. I either write imperatively or functionally. This is the first time I have tried converting from one logic to another. I ran into a lot of little issue along the way. I aimed to just get it to work and I want to make it work better now.
import Data.List import System.Random import Data.Matrix hiding (transpose, trace) import Debug.Trace flipSign::Num a => a -> a flipSign x = (-1) * x nonlin:: Bool -> Double -> Double nonlin True x = x*(1.0-x) nonlin False x = 1.0 / (1.0 + (exp $ flipSign x)) randomList :: (Random a) => Int -> [a] randomList seed = randoms (mkStdGen seed) sample:: [[Double]] sample = map (map fromIntegral)[ [0,0,1], [0,1,1], [1,0,1], [1,1,1] ] answers:: [[Double]] answers = transpose $ map (map fromIntegral) [[0,0,1,1]] syn0:: [[Double]] syn0 = [[x] | x<- take 3 (randomList 42 :: [Double])] dotp:: [[Double]] -> [[Double]] -> [[Double]] dotp x y = toLists newMatrix where mx = fromLists x my = fromLists y newMatrix = multStd mx my nextGeneration::[[Double]] -> [[Double]] -> ([[Double]], [[Double]]) -> ([[Double]],[[Double]]) nextGeneration x labels syn0_l1 = (new_syn0, l1) where l0 = x syn0 = fst syn0_l1 l1 = map (map $ nonlin False) $ dotp l0 syn0 l1_error = zipWith (zipWith (-)) labels l1 l1_delta = zipWith (zipWith (*)) l1_error $ map (map (nonlin True)) l1 new_syn0 = zipWith (zipWith (+)) syn0 $ dotp (transpose l0) l1_delta generations::([[Double]] -> [[Double]]) -> [[Double]] -> Int -> [[Double]] generations _ end 0 = end generations fun weights count = generations fun (fun weights) (count - 1) main = print $ snd $ iterate (nextGeneration sample answers ) (syn0, [] ) !!10000