为什么在训练期间需要调用zero_grad() ?

|  zero_grad(self)
|      Sets gradients of all model parameters to zero.

我试图在Haskell中实现一个神经网络架构,并在MNIST上使用它。

我在线性代数中使用hmatrix包。 我的训练框架是使用pipes包构建的。

我的代码编译并没有崩溃。但问题是,某些层大小(比如1000)、小批大小和学习率的组合会在计算中产生NaN值。经过一些检查,我看到非常小的值(1e-100的顺序)最终出现在激活中。但是,即使这种情况没有发生,培训仍然不起作用。它的损失和准确性都没有改善。

我检查了又检查了我的代码,我不知道问题的根源可能是什么。

下面是反向传播训练,它计算每一层的增量:

backward lf n (out,tar) das = do
    let δout = tr (derivate lf (tar, out)) -- dE/dy
        deltas = scanr (\(l, a') δ ->
                         let w = weights l
                         in (tr a') * (w <> δ)) δout (zip (tail $ toList n) das)
    return (deltas)

Lf是损失函数,n是网络(每一层的权重矩阵和偏置向量),out和tar是网络的实际输出和目标(期望)输出,das是每一层的激活导数。

在批处理模式下,out、tar是矩阵(行是输出向量),das是矩阵列表。

下面是实际的梯度计算:

  grad lf (n, (i,t)) = do
    -- Forward propagation: compute layers outputs and activation derivatives
    let (as, as') = unzip $ runLayers n i
        (out) = last as
    (ds) <- backward lf n (out, t) (init as') -- Compute deltas with backpropagation
    let r  = fromIntegral $ rows i -- Size of minibatch
    let gs = zipWith (\δ a -> tr (δ <> a)) ds (i:init as) -- Gradients for weights
    return $ GradBatch ((recip r .*) <$> gs, (recip r .*) <$> squeeze <$> ds)

这里,lf和n和上面一样,i是输入,t是目标输出(都是以批处理的形式,作为矩阵)。

通过对每一行求和,Squeeze将一个矩阵转换为一个向量。也就是说,ds是一个增量矩阵的列表,其中每一列都对应于小批中一行的增量。偏差的梯度是所有小批量中增量的平均值。g也是一样的,它对应于权重的梯度。

下面是实际的更新代码:

move lr (n, (i,t)) (GradBatch (gs, ds)) = do
    -- Update function
    let update = (\(FC w b af) g δ -> FC (w + (lr).*g) (b + (lr).*δ) af)
        n' = Network.fromList $ zipWith3 update (Network.toList n) gs ds
    return (n', (i,t))

Lr是学习率。FC是该层的构造函数,af是该层的激活函数。

梯度下降算法确保为学习率传递一个负值。梯度下降的实际代码只是一个围绕grad和move组合的循环,并带有参数化的停止条件。

最后,这是一个均方误差损失函数的代码:

mse :: (Floating a) => LossFunction a a
mse = let f (y,y') = let gamma = y'-y in gamma**2 / 2
          f' (y,y') = (y'-y)
      in  Evaluator f f'

Evaluator只是捆绑了一个损失函数及其导数(用于计算输出层的delta)。

其余的代码在GitHub: NeuralNetwork上。

所以,如果有人对这个问题有见解,或者只是检查一下我是否正确地实现了算法,我会很感激。

ANN(人工神经网络)和SVM(支持向量机)是监督机器学习和分类的两种流行策略。对于一个特定的项目,通常不清楚哪种方法更好,我确定答案总是“视情况而定”。通常,两者结合使用贝叶斯分类。

这些关于Stackoverflow的问题已经被问到关于ANN和SVM的问题:

神经网络与支持向量机分类

在我的分类问题中,ANN, SVM和KNN有什么区别

支持向量机或人工神经网络的文本处理?

在这个问题中,我想具体知道人工神经网络(特别是多层感知器)的哪些方面可能比支持向量机更可取?我问这个问题的原因是很容易回答相反的问题:支持向量机通常优于ann,因为它们避免了ann的两个主要弱点:

(1)人工神经网络通常收敛于局部极小值,而不是全局极小值,这意味着它们有时本质上“看不到大局”(或只见树不见林)。

(2)如果训练时间过长,人工神经网络通常会过拟合,这意味着对于任何给定的模式,人工神经网络可能会开始考虑噪声作为模式的一部分。

支持向量机不会遭受这两个问题中的任何一个。然而,目前还不清楚svm是否可以完全取代ann。那么,与支持向量机相比,人工神经网络有哪些特定的优势,可能使其适用于某些情况?我已经列出了支持向量机相对于人工神经网络的特定优势,现在我想看看人工神经网络的优势(如果有的话)。

对于任何Keras层(层类),有人能解释一下如何理解input_shape,单位,暗淡等之间的区别吗?

例如,文档说单位指定一个层的输出形状。

在神经网络的图像中,隐藏层1有4个单元。这是否直接转换为图层对象的单位属性?或者Keras中的单位是否等于隐藏层中每个权重的形状乘以单位的数量?

简而言之,如何理解/可视化模型的属性-特别是层-与下面的图像?

在接下来的TensorFlow函数中,我们必须在最后一层中输入人工神经元的激活。我能理解。但我不明白为什么叫logits?这不是一个数学函数吗?

loss_function = tf.nn.softmax_cross_entropy_with_logits(
     logits = last_layer,
     labels = target_output
)

我知道梯度下降和反向传播算法。我不明白的是:什么时候使用偏见是重要的,你如何使用它?

例如,在映射AND函数时,当我使用两个输入和一个输出时,它不会给出正确的权重。然而,当我使用三个输入(其中一个是偏差)时,它给出了正确的权重。