机器学习算法实现——神经网络

  Ng课学习笔记,只对其中我认为有难度或者很“beautiful”的地方进行了记录。  

  (1)多分类问题

  无论是线性classifier还是神经网络,一组样例的结果y(i)的表示形式是一个长度为k的向量(vector),k为最终类别的种类数。之所以进行这种形式转换是基于我们对最终预测结果的计算方法,即对于每一个类别,利用OneVsAll算法,计算该组样例为1的概率。

all_theta = zeros(num_labels, n + 1);

options = optimset('GradObj', 'on', 'MaxIter', 50);
for k = 1:num_labels
  initial_theta = zeros(n+1,1);
  theta=fmincg(@(t)(lrCostFunction(t,X,(y==k),lambda)),initial_theta,options);
  all_theta(k,:)=theta';
end

  即对于多酚类问题,我们不再单一的使用“一组”theta,而是使用“多组”theta,一组特定的theta能用来预测某组样例是该特定类别(class)的概率

  在理解了OneVsAll之后,我们便不难理解为什么要把样例的结果y和我们的预测值output layer的值扩展为一个长度为k的向量了。具体的扩展代码如下,非常的优美!

Y = eye(num_labels)(y,:);

  一开始没有看懂,后来想了一会儿明白了。等式的右边由两项构成,第一项是eye(num_labels),你可以给它看成一个矩阵,即A = eye(num_labels),然后右边的形式就容易理解了——A(y,:),即分别依次挑选出矩阵A中的“第y行”然后层层叠加起来形成一个新的行数不变、列数为k的0-1矩阵。即permutation!


  (2)Cost Function

  

  这个没什么好讲解的,就是照着公式在matlab/octave中正确的表示出来就行:

  a1 = [ones(size(X,1),1) X];
  z2 = a1*Theta1';
  a2 = [ones(size(X,1),1) sigmoid(z2)];
  z3 = a2*Theta2';
  a3 = sigmoid(z3);
  for i=1:m
    J += - ( Y(i,:) * log(a3(i,:)')  +  (1-Y(i,:)) * log(1-a3(i,:)') ) /m;
  end
  reg = lambda/(2*m)*(sumsq(Theta1(:,2:end)(:)) + sumsq(Theta2(:,2:end)(:)));
  J += reg;

  (3)BP算法

  具体讲解:http://ufldl.stanford.edu/wiki/index.php/%E5%8F%8D%E5%90%91%E4%BC%A0%E5%AF%BC%E7%AE%97%E6%B3%95  这是我在网上找到的讲的比较清晰的一篇了, 基本的公式推导都有,如果有条件的话可以结合周志华老师的西瓜书相关章节辅助一下,效果更佳。此处只给出BP算法的matlab实现

Delta1 = zeros(size(Theta1));
Delta2 = zeros(size(Theta2));

  for i = 1:m
    delta3 = a3(i,:)-Y(i,:);
    delta3 = delta3';
    
    delta2 = Theta2(:,2:end)'*delta3 .* sigmoidGradient(z2(i,:))';
    
    %对于特定的一组样例来说,误差函数关于某一层参数theta的导数是基于本层的预测值和下一层相对应的残差的乘积
    %(1)Accumulating the gradient for this example using the following formula.
    Delta2 += delta3*a2(i,:);
    Delta1 += delta2*a1(i,:);
    
  end    
    %(2)Obtain the (unregularized) gradient for the neural network cost function by dividing the 
    %accumulated gradients by 1/m.
    Theta2_grad = Delta2/m;
    Theta1_grad = Delta1/m;
    
    Theta2_grad(:,2:end) = Delta2(:,2:end)/m + lambda/m*Theta2(:,2:end);
    Theta1_grad(:,2:end) = Delta1(:,2:end)/m + lambda/m*Theta1(:,2:end);

  值得注意的是Ng的课将每个neuron的阀值给合并到theta当中的去了,名之bias term。因此在计算矩阵的过程中要格外注意多一列少一列的小细节,很容易出错。

原文地址:https://www.cnblogs.com/immortal-worm/p/6020859.html