[英]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()
几乎没有意义。
基本上,冗长主要来自类型签名。 此外,您还可以移动rands
到where
下块buildNetwork
,只是完全摆脱toFloat
通过替换任何调用toFloat
与fromIntegral
没有类型注释。 再加上可能还有其他一些微小的重构。
一般来说,在某些情况下,您可以期望在通常更简洁的语言中,某些事情会更加冗长。 我敢肯定,随着您的神经网络程序朝着更充实的代码库发展,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.