haskell - 反向传播算法可以改变权重的符号吗?

标签 haskell backpropagation neural-network

我有一个业余项目,涉及使用动态数据集训练神经网络。我认为我已经正确实现了它,对于一些起始网络,我可以训练它们以匹配样本数据。我注意到训练时正权重不会变成负权重,反之亦然。这引出了两个问题:

  1. “0 处的障碍”是否限制给定起始的行为 网络可以学习吗?
  2. 如果是:我如何修改增量规则以便 权重可以在正数和负数之间变化吗?

这是我目前正在使用的代码(在 Haskell 中)。其中可能存在对其他人来说显而易见的错误,但它基本上是有效的。

import Data.List
import System.Random

type Layer = [[Double]]
type NNet = [Layer]

sigmoid :: Double -> Double
sigmoid t = 1 / (1 + exp (-t))

-- This is the derivative given the sigmoid value.
-- For the derivative given x: use sigmoidDerivative . sigmoid
sigmoidDerivative :: Double -> Double
sigmoidDerivative fx = fx * (1 - fx)

feedforward = flip (foldl' feedlayer)

feedlayer i = map (sigmoid . sum . zipWith (*) (1:i))

backprop :: Double -> [Double] -> [Double] -> NNet -> NNet
backprop rate i t n = fst $ backprop' i t n where
  backprop' i t (l:n) = (nw:r,be) where
    hs = feedlayer i l
    (r,e) = case n of
      [] -> ([], zipWith subtract hs t)
      x -> backprop' hs t n
    we = zipWith (\oe w ->
      map (*oe) w
     ) e l
    nw = zipWith3 (\wl dl h -> let sdh = sigmoidDerivative h in
      zipWith3 (\w d x ->
        w + rate * d * sdh * x
       ) wl dl (1:i)
     ) l we hs
    be = map sum $ transpose we

randomNNet :: RandomGen g => g -> [Int] -> NNet
randomNNet _ [_] = []
randomNNet gen (i:r@(n:_)) = let
  frl g _ = mapAccumL (\g _ -> let
    (a,g') = randomR (-0.05,0.05) g
    in (g',a)) g $ replicate (i+1) ()
  frg g = mapAccumL frl g $ replicate n ()
  (gen',l1) = frg gen
  in l1 : randomNNet gen' r

最佳答案

我犯了一个错误

当错误信号到达节点时,应该发生以下情况:

      -->Multiply by weights-->Propagate to earlier nodes
     /
error
     \
      -->Update weights.

我上面发布的代码中发生的事情是这样的:

                            -->Propagate to earlier nodes
                           /
error-->Multiply by weights
                           \
                            -->Update weights

这是固定代码,包括我插入的注释,以帮助自己弄清楚发生了什么。

backprop :: Double -> [Double] -> [Double] -> NNet -> NNet
backprop rate i t n = fst $ backprop' i t n where
  backprop' i t (l:n) = (nw:r,be) where
    -- hs: output of this layer
    hs = feedlayer i l
    -- r: the next layer updated
    -- e: the error of this layer's output
    (r,e) = case n of
      [] -> ([], zipWith subtract hs t)
      x -> backprop' hs t n
    -- we: Error divided among weights
    we = zipWith (\oe w ->
      map (*oe) w
     ) e l
    -- nw: New weights for this layer
    -- wl: weights leading to current node
    -- h: this node's output
    nw = zipWith3 (\wl d h -> let sdh = sigmoidDerivative h in
      -- w: The current weight
      -- d: The error assigned to the current node
      -- x: The input to the current synapse
      zipWith (\w x ->
        w + rate * d * sdh * x
       ) wl (1:i)
     ) l e hs
    -- be: Errors to propagate back to earlier nodes
    be = map sum $ transpose we

关于haskell - 反向传播算法可以改变权重的符号吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23707752/

相关文章:

tensorflow - 何时使用 @tf.function 装饰器,何时不使用?我知道 tf.function 构建图形。但是如何知道何时构建图呢?

python-3.x - 内核似乎已经死亡。它会自动重新启动。内存有问题吗?

machine-learning - 杰夫·欣顿 (Geoff Hinton) 在训练他的系统进行手写数字识别时,从图像中提取的深度信念网络到底有什么特征?

haskell - 了解filterM函数

haskell - 了解 Haskell 中的纯函数和副作用 - putStrLn

machine-learning - 如何判断一个神经网络?

python - 为什么 Pytorch autograd 需要另一个向量来向后而不是计算雅可比行列式?

mysql - 持久:将文本转换为 key

haskell - 设置graphics.gloss haskell

machine-learning - 如果我只有一个输出,则随时间反向传播的误差项是多少?