0

我正在尝试为多层前馈神经网络实现反向传播算法,但我在让它收敛到好的结果时遇到了问题。原因是,梯度下降卡在均方根误差的板上。

在此处输入图像描述

正如您在图中看到的,前 70 个 epoch 左右的 rms 值几乎没有变化。因此梯度下降找到了一个最小值并停止。为了解决这个问题,我设置了一个要求,即除了变化率低于给定值之外,rms 误差必须低于 0.3。但是,我认为这并不好,因为我认为我的实现有问题。

以下是红宝石代码:

def train eta, criteria
    rms = 1
    old_rms = 0

    rms_window = Array.new 20, 0
    new_avg = 10
    old_avg = 0
    diff = 100 
    epoch = 0

    @data[:training].shuffle!

    while (diff > criteria || rms > 0.3) do
    #while (diff > criteria) do

        rms = 0
        old_avg = new_avg
        new_avg = 0

        classification_error = 0
        sample_num = 0

        @data[:training].each_with_index do |s, s_i|

            # Forward Propagation

            inputs = [1, s[1], s[2]]

            @hidden_layers.each_with_index do |hl, hl_i|
                outputs = Array.new

                # Bias Term
                outputs << 1

                # Compute the output for each neuron
                hl.each do |p|
                    outputs << p.compute_output(inputs)
                end

                inputs = outputs
            end

            # Compute System Outputs
            outputs = Array.new
            @outputs.each do |p|
                outputs << p.compute_output(inputs)
            end

            # Comput Errors
            errors = Array.new
            desired = @desired_values[s[0]-1]

            @outputs.length.times do |x|
                errors[x] = desired[x] - outputs[x]
                rms += errors[x]**2
            end

            decision = outputs.each_with_index.max[1]

            if decision+1 != s[0]
                classification_error += 1
            end


            # Back Propagation

            gradients = Array.new
            local_gradient = Array.new
            next_layer = Array.new

            @outputs.each_with_index do |o, i|
                local_gradient << errors[i] * o.activation_prime(o.output)

                o.weights.length.times do |x|
                    o.weights[x] += eta * local_gradient[i] * o.inputs[x]
                end
            end

            gradients << local_gradient

            next_layer = @outputs

            @hidden_layers.reverse_each do |hl|
                local_gradient = Array.new

                hl.each do |p|
                    gradient = 0

                    gradients.last.each_with_index do |g, i|
                        gradient += g * next_layer[i].weights[p.index+1]
                    end

                    gradient *= p.activation_prime(p.output)
                    local_gradient << gradient

                    p.weights.each_index do |x|
                        p.weights[x] += eta * gradient * p.inputs[x]
                    end
                end

                gradients << local_gradient

                next_layer = hl
            end

            if s_i == 0
            #puts "Epoch: #{epoch}\nOutputs: #{outputs}\nGradients:\n#{gradients[0]}\n#{gradients[1]}\n#{gradients[2]}\n\n"
            #puts "Epoch #{epoch}\nError: #{errors}\nSE: #{rms}"
        end

        end

        rms = Math::sqrt(rms / (@data[:training].length * 4))

        rms_window[0] = rms
        rms_window.rotate!

        rms_window.each do |x|
            new_avg += x
        end

        new_avg /= 20

        diff = (new_avg - old_avg).abs

        @rms << rms
        epoch += 1

        if classification_error == 0
            break
        end

        #puts "RMS: #{rms}\tDiff: \t#{diff}\tClassification: #{classification_error}\n\n"
    end

    self.rms_plot "Plot"
    self.grid_eval "Test", 250
end

显示的图表是一个 2 隐藏层网络,每个隐藏层有 5 个神经元。有 2 个输入和 4 个输出。也许这是正常行为,但对我来说似乎有些不对劲。任何帮助将不胜感激。

4

2 回答 2

0

需要调整许多参数才能使多层神经网络正常工作。根据我的实验,我的第一个建议是:

1-给它一小组合成数据并运行一个婴儿项目以查看框架是否有效。

2-使用更凸的成本函数。没有函数可以保证凸性,但有许多函数比 RMS 更凸。

3- 尝试在 (-1,1) 中缩放输入数据,在 (0,1) 中缩放输出数据。

4-尝试不同的学习率值。

于 2014-10-24T16:59:45.963 回答
0

除了已经说过的:

  • 稍微改变初始权重的范围(例如 0 - 1)

  • 确保您的输入数据正确规范化 - 我认为这不能经常说

  • 改变学习率,从 0.05 之类的开始,然后以小步长不断增加/减少(如果你发现改变学习率对网络性能的影响过于极端,那么你可能没有适当地标准化你的输入数据)

  • 在每个 epoch 之前打乱输入数据

  • 尝试使用动量(这本质上意味着,在梯度陡峭时提高学习率,如果变得更平坦则降低),这通常有助于跳过局部最优

  • 尝试使用正则化

  • 对结构进行实验(添加另一个隐藏层,增加隐藏层中的单元数)

于 2014-10-25T07:21:26.043 回答