Is this Haskell code equivalent to this Python code?

Christopher Dumas

I'm trying to port a Python program to Haskell, and I'm fairly new to NumPy (which the Python program uses) So I'm wondering why this code isn't equivalent. Here's my Haskell code:

data NNetwork = NNetwork { nlayers :: Int
                         , sizes   :: [Int]
                         , biases  :: [[Float]]
                         , weights :: [[Float]] }
                deriving (Show, Ord, Eq)

buildNetwork :: [Int] -> NNetwork
buildNetwork sizes = NNetwork { nlayers = length sizes
                              , sizes   = sizes
                              , biases  = map (\y -> replicate y (sig . toFloat . rands $ y)) sizes
                              , weights = map (\y -> replicate y (toFloat $ rands y)) sizes }
feedforward :: NNetwork -> Float -> [[Float]]
feedforward net a = map (equation a) (zip (weights net) (biases net))

toFloat x = fromIntegral x :: Float

sig :: Float -> Float
sig a = 1 / (1 + exp (-a))

rands :: Int -> Int
rands x = (7 * x) `mod` 11

equation :: Float -> ([Float], [Float]) -> [Float]
equation a (w, b) = map sig $ zipWith (+) (dot w (rep w a)) b
  where dot = zipWith (*)
        rep a b = replicate (length a) b

And the original Python code:

class Network(object):

    def __init__(self, sizes):
        self.num_layers = len(sizes)
        self.sizes = sizes
        self.biases = [np.random.randn(y, 1) for y in sizes[1:]]
        self.weights = [np.random.randn(y, x) 
                        for x, y in zip(sizes[:-1], sizes[1:])]

def sigmoid(z):
    return 1.0/(1.0+np.exp(-z))

def feedforward(self, a):
        """Return the output of the network if "a" is input."""
        for b, w in zip(self.biases, self.weights):
            a = sigmoid(np.dot(w, a)+b)
        return a

I'm trying to port a very simple neural network program from Python to Haskell, because I enjoy Haskell much more. I'm also worried that I'm doing something wrong, because the Haskell code is far more verbose.

- Thanks!

Erik Kaplun

First of all: note that the Python version lacks the equivalent of deriving (Show, Eq, Ord) — try implementing the corresponding __magic__ methods and see how many lines of code are added. Without these, ==, <=, >, as well as print Network() make little to no sense.

Basically the verbosity mainly comes from the type signatures. Also, you can move rands to a where block under buildNetwork and simply completely get rid of toFloat by replacing any calls to toFloat with fromIntegral with no type annotation. Plus perhaps some other tiny refactorings.

In general, you can expect, in some situations, for some things to be somewhat more verbose in languages that are generally much more concise. I'm sure as your neural network program progresses towards a more substantial code base, Haskell will be less verbose than Python, ignoring the possible existence of neural network libraries for Python that might be more mature than their (possibly non-existent) Haskell counterparts.

data NNetwork = NNetwork { nlayers :: Int
                         , sizes   :: [Int]
                         , biases  :: [[Float]]
                         , weights :: [[Float]] }
                deriving (Show, Ord, Eq)

buildNetwork sizes =
  NNetwork { nlayers = length sizes
           , sizes   = sizes
           , biases  = map (\y -> replicate y (sig . fromIntegral . rands $ y)) sizes
           , weights = map (\y -> replicate y (fromIntegral . rands $ y)) sizes }
  where rands x = (7 * x) `mod` 11

feedforward net a = map (equation a) (zip (weights net) (biases net))

sig a = 1 / (1 + exp (-a))

equation a (w, b) = map sig $ zipWith (+) (dot w rep) b
  where dot = zipWith (*)
        rep = replicate (length w) a

and well you can do some micro-refactorings in the buildNetwork to remove some minor duplication but that would just shorten the lines, and would possibly make the code less readable to a domain expert:

buildNetwork sizes =
  NNetwork { nlayers = length sizes
           , sizes   = sizes
           , biases  = nameMe sig
           , weights = nameMe id }
  where nameMe fn = map (replicate y (fn y')) sizes
        y'        = fromIntegral $ y * 7 `mod` 11

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Haskell equivalent of this Python code

From Dev

Is this Haskell code equivalent to this Python code?

From Dev

Is this Python code equivalent of Java code?

From Dev

Python equivalent for given MATLAB code

From Dev

Convert a Haskell code to Python or pseudocode

From Dev

C++ equivalent to python code: 'function(*list)'

From Dev

C++ equivalent to python code: 'function(*list)'

From Dev

R equivalent python code gives different output

From Dev

What's the equivalent of this Ruby code in Python?

From Dev

Equivalent Scala code for Java code

From Dev

What is the code equivalent to this css code?

From Dev

Are these lines of JavaScript code equivalent?

From Dev

C# Equivalent to this code

From Dev

Matlab equivalent code for file

From Dev

%timeit equivalent in code

From Dev

Equivalent code in IronPython

From Dev

C# Equivalent to this code

From Dev

Matlab equivalent code for file

From Dev

sed equivalent code for AIX

From Dev

Equivalent code without the library

From Dev

Is this Swift code equivalent?

From Dev

Why is this Haskell code so much slower than the C equivalent? Unboxed vectors and bangs already used

From Dev

What is the Python equivalent to this C++ code that reads from stdin?

From Dev

Why is this Go code the equivalent speed as that of Python (and not much faster)?

From Dev

How would a pythonista code the equivalent of the ++ increment operator in Python 3?

From Dev

Python equivalent of password encryption from RSA key Java code

From Dev

what is the equivalent perl and python code for unix command "mdb hostname"

From Dev

How to make python of exponential growth to code equivalent to c++?

From Dev

Python equivalent code for curl including elastic search queries

Related Related

  1. 1

    Haskell equivalent of this Python code

  2. 2

    Is this Haskell code equivalent to this Python code?

  3. 3

    Is this Python code equivalent of Java code?

  4. 4

    Python equivalent for given MATLAB code

  5. 5

    Convert a Haskell code to Python or pseudocode

  6. 6

    C++ equivalent to python code: 'function(*list)'

  7. 7

    C++ equivalent to python code: 'function(*list)'

  8. 8

    R equivalent python code gives different output

  9. 9

    What's the equivalent of this Ruby code in Python?

  10. 10

    Equivalent Scala code for Java code

  11. 11

    What is the code equivalent to this css code?

  12. 12

    Are these lines of JavaScript code equivalent?

  13. 13

    C# Equivalent to this code

  14. 14

    Matlab equivalent code for file

  15. 15

    %timeit equivalent in code

  16. 16

    Equivalent code in IronPython

  17. 17

    C# Equivalent to this code

  18. 18

    Matlab equivalent code for file

  19. 19

    sed equivalent code for AIX

  20. 20

    Equivalent code without the library

  21. 21

    Is this Swift code equivalent?

  22. 22

    Why is this Haskell code so much slower than the C equivalent? Unboxed vectors and bangs already used

  23. 23

    What is the Python equivalent to this C++ code that reads from stdin?

  24. 24

    Why is this Go code the equivalent speed as that of Python (and not much faster)?

  25. 25

    How would a pythonista code the equivalent of the ++ increment operator in Python 3?

  26. 26

    Python equivalent of password encryption from RSA key Java code

  27. 27

    what is the equivalent perl and python code for unix command "mdb hostname"

  28. 28

    How to make python of exponential growth to code equivalent to c++?

  29. 29

    Python equivalent code for curl including elastic search queries

HotTag

Archive