Last active
October 12, 2017 05:53
-
-
Save Nnwww/e79ff5a252a5f54575da1e5aa3309175 to your computer and use it in GitHub Desktop.
naive sigmoid vs memorized sigmoid in Haskell
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
benchmarking sigmoid functions/naive | |
time 493.9 ms (467.9 ms .. 519.2 ms) | |
1.000 R² (0.999 R² .. 1.000 R²) | |
mean 490.2 ms (482.8 ms .. 493.5 ms) | |
std dev 6.459 ms (0.0 s .. 6.998 ms) | |
variance introduced by outliers: 19% (moderately inflated) | |
benchmarking sigmoid functions/SigTable | |
time 1.449 s (1.406 s .. 1.509 s) | |
1.000 R² (0.999 R² .. 1.000 R²) | |
mean 1.442 s (1.428 s .. 1.451 s) | |
std dev 13.47 ms (0.0 s .. 15.54 ms) | |
variance introduced by outliers: 19% (moderately inflated) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env stack | |
{- stack --resolver lts-8.23 --install-ghc runghc | |
--package criterion --package vector | |
-} | |
{-# LANGUAGE StrictData #-} | |
import Criterion.Main | |
import qualified Data.Vector.Unboxed as VU | |
setupEnv = pure $ replicate 1000000 (1 :: Double) | |
main = defaultMain [ | |
env setupEnv $ \ ~list -> bgroup "sigmoid functions" | |
[ bench "naive" $ nf (map sigmoid) list | |
, bench "SigTable" $ nf (map lookSigT) list | |
] | |
] | |
where | |
lookSigT = lookupSigTable sigt | |
sigt = initSigTable 512 8 | |
sigmoid :: Double -> Double | |
sigmoid lx = 1.0 / (1.0 + exp (negate lx)) | |
data SigTable = SigTable | |
{ sigTable :: {-# UNPACK #-} (VU.Vector Double) | |
, sigSize :: {-# UNPACK #-} Double | |
, sigMaxX :: {-# UNPACK #-} Double | |
} | |
initSigTable :: Int -> Double -> SigTable | |
initSigTable tableSize maxValue = SigTable | |
{sigTable = sigmoidTable, sigSize = floatingSize, sigMaxX = maxValue} | |
where | |
floatingSize = fromIntegral tableSize | |
sigmoidTable = VU.generate tableSize (lsigmoid . mapIndexToTableX . fromIntegral) | |
lsigmoid lx = 1.0 / (1.0 + exp (negate lx)) | |
mapIndexToTableX idx = (idx * 2.0 * maxValue) / floatingSize - maxValue | |
lookupSigTable :: SigTable -> Double -> Double | |
lookupSigTable SigTable{sigTable = sigT, sigSize = size, sigMaxX = maxX} x | |
| x < -maxX = 0.0 | |
| maxX < x = 1.0 | |
| otherwise = sigT `VU.unsafeIndex` mapInputToIndex x | |
where | |
mapInputToIndex lx = floor ((lx + maxX) * size / maxX / 2.0) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment