簡體   English   中英

這個 Haskell 代碼等價於這個 Python 代碼嗎?

[英]Is this Haskell code equivalent to this Python code?

我正在嘗試將 Python 程序移植到 Haskell,而且我對 NumPy(Python 程序使用的)相當陌生,所以我想知道為什么這段代碼不等效。 這是我的 Haskell 代碼:

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

和原始的 Python 代碼:

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

我正在嘗試將一個非常簡單的神經網絡程序從 Python 移植到 Haskell,因為我更喜歡 Haskell。 我還擔心我做錯了什么,因為 Haskell 代碼要冗長得多。

- 謝謝!

首先:請注意,Python 版本缺少deriving (Show, Eq, Ord)的等效項——嘗試實現相應的__magic__方法,看看添加了多少行代碼。 沒有這些, ==<=>以及print Network()幾乎沒有意義。

基本上,冗長主要來自類型簽名。 此外,您還可以移動randswhere下塊buildNetwork ,只是完全擺脫toFloat通過替換任何調用toFloatfromIntegral沒有類型注釋。 再加上可能還有其他一些微小的重構。

一般來說,在某些情況下,您可以期望在通常更簡潔的語言中,某些事情會更加冗長。 我敢肯定,隨着您的神經網絡程序朝着更充實的代碼庫發展,Haskell 將比 Python 更簡潔,忽略可能存在的 Python 神經網絡庫,這些庫可能比它們的(可能不存在的)Haskell 對應物更成熟.

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

好吧,您可以在buildNetwork進行一些微重構以刪除一些小的重復,但這只會縮短行數,並且可能會使代碼對領域專家的可讀性降低:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM