【问题标题】:Haskell Infinite loop in a recursive function递归函数中的 Haskell 无限循环
【发布时间】:2020-10-11 19:34:23
【问题描述】:

我是 Haskell 的初学者,我正在尝试让神经元做到这一点,我需要为神经元的权重生成随机数,但我被困在随机函数中,它会引发无限循环 我不知道问题出在哪里,此外,当我在终端中询问编译时随机取 3 时,它总是给我相同的数字,我希望它每次取不同的随机数

l = [1,0,1,1,0,0,1,0]

toDec :: [Int] -> Float
toDec []     = 0
toDec (x:xs) = fromIntegral  x+2*(toDec xs)

next :: [Int] -> [Int]
next xs = xs'
 where xs' = v:(init xs)
       v   = xor (last xs) (xs!!4)

random :: [Float]
random = ran l
       where ran l = ( (toDec l) /  255.0):(ran (next l))

-- simple neuron
data Neuron = Neuron [Float]
      deriving (Read,Show)

n = Neuron (take 3 random)

【问题讨论】:

  • Haskell 是一种语言。这意味着一个函数的结果取决于它的参数,而不依赖于其他任何东西。如果您希望数字每次都不同,则需要给它某种种子作为参数,并使其每次都不同。
  • Haskell 是一种纯语言,恰好提供了相当不错的库来生成伪随机数。如果随机数的统计质量值得关注,这就是您想要使用的,而不是重新发明这些东西。例如,参见School of Haskell。注意:您的问题似乎定期以各种形式出现在 SO 中,例如 here

标签: haskell deep-learning


【解决方案1】:

你的函数工作非常好:它生成一个无限的伪随机数列表。

(这不是一个特别 PRNG - 对于严肃的应用程序,您最好使用库,random-fu 非常广泛 - 但出于教育目的它很好。)

但是,您需要清楚这实际上意味着什么。因为random 只是[Float] 类型的,它当然总是同一个列表。您可以仍然使用它来获得多个不同的有限列表,方法是拆分单个无限列表:

n₀, n₁, n₂ :: Neuron
(n₀:n₁:n₂:_) = Neuron <$> splits 3 random

-- | @splits n l@ gives a list of sublists of @l@, each of which has length @n@.
--   If the sublists are concatenated again, you get back @l@.
splits :: Int -> [a] -> [[a]]
splits nPerList l = case splitAt nPerList l of
   (h,[]) -> [h]
   (h,t) -> h : splits nPerList t

如果你想要一些行为类似于命令式语言中的“随机函数”的东西,即每次调用时都会给出不同值的东西......那么这不是一个函数,因为一个函数必须对于给定的输入总是产生同样的结果。但是,您可以在合适的 monad 中将其实现为 action。在命令式语言中,PRNG 会有一个隐含的状态。您也可以在 Haskell 中使用它,除了状态是显式的(这实际上在可靠性方面有很多优势)。

import Control.Monad.Trans.State

type RandSupply = State [Float]

oneRandom :: RandSupply Float
oneRandom = do
  ~(h:t) <- get   -- This is a bit of a hack†
  put t
  return h

randomNeuron :: Int -> RandSupply Neuron
randomNeuron nWeights = Neuron <$> replicateM nWeights oneRandom

然后你可以写类似的代码

import Control.Monad

     (`evalState`random) $ do
         ...
         n <- randomNeuron 3
         ...
         n₅ <- randomNeuron 5
         ...

nn₅ 将具有不同的权重,因为供应列表的状态在两者之间发生了变化。


无可辩驳的匹配~(h:t) 意味着如果您尝试仅在有限 供应随机数的情况下使用它,该操作可能会严重失败。再说一遍:正确的做法是使用 library 存储随机数,而不是自己滚动。

【讨论】:

  • 感谢您的回复,是的,正如您所说,因为 random 只是 [Float] 类型的值,它当然总是相同的列表,要获得更多值,我只需键入以 10 个随机为例
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-01-10
  • 1970-01-01
  • 2021-12-06
  • 2021-01-16
  • 2017-03-15
  • 1970-01-01
  • 2020-04-04
相关资源
最近更新 更多