神经网络y = f(x)回归

时间:2018-08-20 19:35:17

标签: neural-network regression

受到MNIST分类取得成功的鼓舞,我想解决一些神经网络的“实际”问题。 任务似乎很简单:

我们有:

  • 一些x值(例如1:1:100)
  • 一些y值(例如x ^ 2)

我想训练一个具有1个输入(对于1个x值)和一个输出(对于1个y值)的网络。一个隐藏层。

这是我的基本程序:

  1. 将我的x值切成不同的批次(例如,每批次10个元素)

  2. 在每一批中计算网络的输出,然后应用反向传播,计算权重和偏差更新

  3. 每批次平均计算出的权重和偏差后,实际上会更新权重和偏差

  4. 重复步骤1.-3.多次

此过程对于MNIST效果很好,但是对于回归而言,它完全失败。 我想知道我是否做错了什么。 我尝试了不同的批处理大小,直到对所有x个值取平均值。

基本上,网络训练得不好。手动调整权重和偏差(带有2个隐藏的神经元)后,我可以很好地近似y = f(x),但是当网络学习参数时,它将失败。

当我只有一个用于x的元素和一个用于y的元素并且我训练网络时,它对于这一对特定的对象训练得很好。

也许有人对我有暗示。我是否会误解神经网络的回归?

到目前为止,我认为代码本身还可以,因为它适用于MNIST,并且适用于“一对x / y对示例”。我宁愿认为我的总体方法(参见上文)可能不适合回归。

谢谢

吉姆

ps:我明天要发布一些代码...

下面是代码(MATLAB)。就像我说的,它是一个隐藏的层,带有两个隐藏的神经元:

% init hyper-parameters
hidden_neurons=2;
input_neurons=1;
output_neurons=1;
learning_rate=0.5;
batchsize=50;

% load data
training_data=d(1:100)/100;
training_labels=v_start(1:100)/255;

% init weights
init_randomly=1;
if init_randomly
    % initialize weights and bias with random numbers between -0.5 and +0.5
    w1=rand(hidden_neurons,input_neurons)-0.5;    
    b1=rand(hidden_neurons,1)-0.5;
    w2=rand(output_neurons,hidden_neurons)-0.5;
    b2=rand(output_neurons,1)-0.5;

else
    % initialize with manually determined values
    w1=[10;-10];
    b1=[-3;-0.5];
    w2=[0.2 0.2];
    b2=0;

end

for epochs =1:2000 % looping over some epochs

    for i = 1:batchsize:length(training_data) % slice training data into batches

        batch_data=training_data(i:min(i+batchsize,length(training_data))); % generating training batch
        batch_labels=training_labels(i:min(i+batchsize,length(training_data))); % generating training label batch

        % initialize weight updates for next batch
        w2_update=0;
        b2_update =0;
        w1_update =0;
        b1_update =0;        

        for k = 1: length(batch_data) % looping over one single batch

            % extract trainig sample

            x=batch_data(k); % extracting one single training sample
            y=batch_labels(k); % extracting expected output of training sample

            % forward pass

            z1 = w1*x+b1; % sum of first layer
            a1 = sigmoid(z1); % activation of first layer (sigmoid)

            z2 = w2*a1+b2; % sum of second layer
            a2=z2; %activation of second layer (linear)

            % backward pass

            delta_2=(a2-y); %calculating delta of second layer assuming quadratic cost; derivative of linear unit is equal to 1 for all x.
            delta_1=(w2'*delta_2).* (a1.*(1-a1)); % calculating delta of first layer

            % calculating the weight and bias updates averaging over one
            % batch

            w2_update = w2_update +(delta_2*a1') * (1/length(batch_data));
            b2_update = b2_update + delta_2 * (1/length(batch_data));
            w1_update = w1_update + (delta_1*x') * (1/length(batch_data));
            b1_update = b1_update + delta_1 * (1/length(batch_data));

        end

        % actually updating the weights. Updated weights will be used in
        % next batch

        w2 = w2 - learning_rate * w2_update;
        b2 = b2 - learning_rate * b2_update;        
        w1 = w1 - learning_rate * w1_update;
        b1 = b1 - learning_rate * b1_update;        

    end       
end

这是随机初始化的结果,显示预期的输出,训练之前的输出以及训练之后的输出: training with random init

有人可以说蓝线已经比黑线更近了,从这个意义上说,网络已经优化了结果。但是我不满意。 这是我手动调整的值的结果: training with pre-init

黑线对于两个隐藏的神经元来说还不错,但是我的期望是,这样的黑线是从随机初始化开始训练的结果。

任何建议我做错了什么? 谢谢!

2 个答案:

答案 0 :(得分:1)

好吧,经过一些研究,我发现了一些有趣的观点:

  • 我尝试学习的功能似乎特别难以学习(不确定原因)
  • 在相同的设置下,我尝试学习了一些成功的三次多项式(成本<1e-6)
  • 随机分配训练样本似乎可以改善学习(对于多项式和我的初始函数)。我知道这在文献中是众所周知的,但在执行过程中我总是跳过这一部分。所以我自己了解了它的重要性。
  • 对于学习“曲线/摆动”功能,我发现S形比ReLu更好。 (输出层仍为“线性”,建议回归)
  • 0.1的学习率对我最终想要执行的曲线拟合效果很好
  • 较大的批处理大小将使成本与历时图(惊奇...)保持一致
  • 在我的应用程序中,初始化介于-5和+5之间的重量比-0.5和0.5更好。

最后,我打算在网络上学习的内容得到了令人信服的结果:)

答案 1 :(得分:0)

您是否尝试过以更低的学习率进行尝试?通常,学习率0.001是一个很好的起点,在大多数情况下,学习率0.5太大。

还要注意,您的预定义权重在Sigmoid函数的一个非常平坦的区域(sigmoid(10)= 1,sigmoid(-10)= 0),两个位置的导数都接近0。这意味着反向传播从这样的职位(或这样的职位)非常困难;正是由于这个原因,有些人更喜欢使用ReLUs而不是S型,因为它只有一个“死”区域用于负激活。

此外,看到您只有100个训练样本,我是否正确?您可以尝试使用较小的批量,或增加采样数量。另外,不要忘记在每个时期之后对样本进行洗牌。原因很多,例如here