反向传播算法的暴力理解

1 Backpropagation 反向传播算法

我们在学习和实现反向传播算法的时候,往往因为其计算的复杂性,计算内涵的抽象性,只是机械的按照公式模板去套用算法。但是这种形式的算法使用甚至不如直接调用一些已有框架的算法实现来得方便。

我们实现反向传播算法,就是要理解为什么公式这么写,为什么这么算。这是非常重要的一件事情!

可能有一些教学会将算法的顺序步骤抽象为一个“反向传播“的过程,将计算转为一种图形或是动画的模式。但在你真正知道为什么这么算之前,这些都是无根之萍。

对于为什么这么算,我们的方法就是正面G

至于什么是正面G,意思是我们只要理解导数就可以了,其他的所有理解在这里都被摒弃。我们只是计算,用计算来推导公式

There are no meanings. There are just laws of arithmetic.

下面的文章大多带有英文。提前预警。因为数学公式的使用,建议大屏设备观看

2 Terminology[1]

image

  • L = total number of layers in the network

  • sl = number of units (not counting bias unit) in layer l

  • K = number of output units/classes

  • Binary classification: y = 0 or y = 1, K=1;

  • Multi-class classification: K>=3;

ai(j)="activation" of unit i in layer jΘ(j)=matrix of weights controlling function mapping from layer j to layer j+1

If network has sj units in layer j and sj+1 units in layer j+1 then Θ(j) will be of dimension sj+1×(sj+1).

z(j+1)=Θ(j)a(j)

Example

z1(3)=Θ10(2)a0(2)+Θ11(2)a1(2)+Θ12(2)a2(2)a1(3)=g(z1(3))z2(3)=Θ20(2)a0(2)+Θ21(2)a1(2)+Θ22(2)a2(2)a2(3)=g(z2(3))adda0(3)=1

Θ10(1)a0(1)

  • (1) : 第一层向第二层的权重
  • 10 :
    • 1 :对应第二层的第一个激活单元 a1(2)
    • 0 :对应第一层的第0个参数 a0(1)

3 Feedforward computation

对于上面的4层的神经网络,下面是一个详细的实现算法。要实现反向传播,我们首先要实现前向传播。

前向传播的精髓就是计算一层的输出值,作为下一层的输入值。

3.1 Layer 1

a1(1)=x1a2(1)=x2adda0(1)=1

3.2 Layer 2

z1(2)=Θ10(1)a0(1)+Θ11(1)a1(1)+Θ12(1)a2(1)a1(2)=g(z1(2))z2(2)=Θ20(1)a0(1)+Θ21(1)a1(1)+Θ22(1)a2(1)a2(2)=g(z2(2))adda0(2)=1

3.3 Layer 3

z1(3)=Θ10(2)a0(2)+Θ11(2)a1(2)+Θ12(2)a2(2)a1(3)=g(z1(3))z2(3)=Θ20(2)a0(2)+Θ21(2)a1(2)+Θ22(2)a2(2)a2(3)=g(z2(3))adda0(3)=1

3.4 Layer 4

z1(4)=Θ10(3)a0(3)+Θ11(3)a1(3)+Θ12(3)a2(3)a1(4)=g(z1(4))hΘ(x)=a1(4)

4 Hypothesis expansion

hΘ(x)=a1(4)=g(z1(4))=g(Θ10(3)a0(3)+Θ11(3)a1(3)+Θ12(3)a2(3))=g(Θ10(3)a0(3)+Θ11(3)g(z1(3))+Θ12(3)g(z2(3)))=g(Θ10(3)a0(3)+Θ11(3)g(Θ10(2)a0(2)+Θ11(2)a1(2)+Θ12(2)a2(2))+Θ12(3)g(Θ20(2)a0(2)+Θ21(2)a1(2)+Θ22(2)a2(2)))=g(Θ10(3)a0(3)+Θ11(3)g(Θ10(2)a0(2)+Θ11(2)g(z1(2))+Θ12(2)g(z2(2)))+Θ12(3)g(Θ20(2)a0(2)+Θ21(2)g(z1(2))+Θ22(2)g(z2(2))))=g(Θ10(3)a0(3)+Θ11(3)g(Θ10(2)a0(2)+Θ11(2)g(Θ10(1)a0(1)+Θ11(1)a1(1)+Θ12(1)a2(1))+Θ12(2)g(Θ20(1)a0(1)+Θ21(1)a1(1)+Θ22(1)a2(1)))+Θ12(3)g(Θ20(2)a0(2)+Θ21(2)g(Θ10(1)a0(1)+Θ11(1)a1(1)+Θ12(1)a2(1))+Θ22(2)g(Θ20(1)a0(1)+Θ21(1)a1(1)+Θ22(1)a2(1))))

5 对应三个权重矩阵

Θ(1)=2×3=(Θ10(1)Θ11(1)Θ12(1)Θ20(1)Θ21(1)Θ22(1))

Θ(2)=2×3=(Θ10(2)Θ11(2)Θ12(2)Θ20(2)Θ21(2)Θ22(2))

Θ(3)=1×3=(Θ10(3)Θ11(3)Θ12(3))

6 导数部分

单分类:

J(Θ)=1mi=1m[y(i) log(hθ(x(i)))+(1y(i)) log(1hθ(x(i)))]

多分类:

J(Θ)=1mt=1mk=1K[yk(t) log(hΘ(x(t)))k+(1yk(t)) log(1hΘ(x(t))k)]

这里我们实现单分类的求导,为了简便我们假设只有一个样本 m = 1, 多样本没有什么不一样的,就是向量化的一个样本的实现。同时没有 regularization 简化推导。

反向传播就是计算每一个Θ对应的导数值,而Θ又存在于J(Θ)之中。所以直接利用链式法则,追根溯源,最终计算到需要计算的Θ身上。

1 单分类 Θ(3) 1x3

J(Θ)Θ10(3)=J(Θ)a1(4)a1(4)z1(4)z1(4)Θ10(3)=(a1(4)y)a0(3)

J(Θ)Θ11(3)=J(Θ)a1(4)a1(4)z1(4)z1(4)Θ11(3)=(a1(4)y)a1(3)

J(Θ)Θ12(3)=J(Θ)a1(4)a1(4)z1(4)z1(4)Θ12(3)=(a1(4)y)a2(3)

2 单分类 Θ(2) 2x3

z1(4)a1(3)=Θ11(3)a1(3)z1(3)=a1(3)(1a1(3))z1(3)Θ10(2)=a0(2)

J(Θ)Θ10(2)=J(Θ)a1(4)a1(4)z1(4)z1(4)a1(3)a1(3)z1(3)z1(3)Θ10(2)=(a1(4)y)Θ11(3)a1(3)(1a1(3))a0(2)

J(Θ)Θ11(2)=J(Θ)a1(4)a1(4)z1(4)z1(4)a1(3)a1(3)z1(3)z1(3)Θ11(2)=(a1(4)y)Θ11(3)a1(3)(1a1(3))a1(2)

J(Θ)Θ12(2)=J(Θ)a1(4)a1(4)z1(4)z1(4)a1(3)a1(3)z1(3)z1(3)Θ12(2)=(a1(4)y)Θ11(3)a1(3)(1a1(3))a2(2)

z1(4)a2(3)=Θ12(3)a2(3)z2(3)=a2(3)(1a2(3))z2(3)Θ20(2)=a0(2)

J(Θ)Θ20(2)=J(Θ)a1(4)a1(4)z1(4)z1(4)a2(3)a2(3)z2(3)z2(3)Θ20(2)=(a1(4)y)Θ12(3)a2(3)(1a2(3))a0(2)

J(Θ)Θ21(2)=J(Θ)a1(4)a1(4)z1(4)z1(4)a2(3)a2(3)z2(3)z2(3)Θ21(2)=(a1(4)y)Θ12(3)a2(3)(1a2(3))a1(2)

J(Θ)Θ22(2)=J(Θ)a1(4)a1(4)z1(4)z1(4)a2(3)a2(3)z2(3)z2(3)Θ22(2)=(a1(4)y)Θ12(3)a2(3)(1a2(3))a2(2)

3 单分类 Θ(1) 2x3

J(Θ)Θ10(1)=J(Θ)a1(4)a1(4)z1(4)(z1(4)a1(3)a1(3)z1(3)z1(3)a1(2)+z1(4)a2(3)a2(3)z2(3)z2(3)a1(2))a1(2)z1(2)z1(2)Θ10(1)=(a1(4)y)[Θ11(3)a1(3)(1a1(3))Θ11(2)+Θ12(3)a2(3)(1a2(3))Θ21(2)]a1(2)(1a1(2))a0(1)

J(Θ)Θ11(1)=J(Θ)a1(4)a1(4)z1(4)(z1(4)a1(3)a1(3)z1(3)z1(3)a1(2)+z1(4)a2(3)a2(3)z2(3)z2(3)a1(2))a1(2)z1(2)z1(2)Θ11(1)=(a1(4)y)[Θ11(3)a1(3)(1a1(3))Θ11(2)+Θ12(3)a2(3)(1a2(3))Θ21(2)]a1(2)(1a1(2))a1(1)

J(Θ)Θ12(1)=J(Θ)a1(4)a1(4)z1(4)(z1(4)a1(3)a1(3)z1(3)z1(3)a1(2)+z1(4)a2(3)a2(3)z2(3)z2(3)a1(2))a1(2)z1(2)z1(2)Θ12(1)=(a1(4)y)[Θ11(3)a1(3)(1a1(3))Θ11(2)+Θ12(3)a2(3)(1a2(3))Θ21(2)]a1(2)(1a1(2))a2(1)

J(Θ)Θ20(1)=J(Θ)a1(4)a1(4)z1(4)(z1(4)a1(3)a1(3)z1(3)z1(3)a2(2)+z1(4)a2(3)a2(3)z2(3)z2(3)a2(2))a2(2)z2(2)z2(2)Θ20(1)=(a1(4)y)[Θ11(3)a1(3)(1a1(3))Θ12(2)+Θ12(3)a2(3)(1a2(3))Θ22(2)]a2(2)(1a2(2))a0(1)

J(Θ)Θ21(1)=J(Θ)a1(4)a1(4)z1(4)(z1(4)a1(3)a1(3)z1(3)z1(3)a2(2)+z1(4)a2(3)a2(3)z2(3)z2(3)a2(2))a2(2)z2(2)z2(2)Θ21(1)=(a1(4)y)[Θ11(3)a1(3)(1a1(3))Θ12(2)+Θ12(3)a2(3)(1a2(3))Θ22(2)]a2(2)(1a2(2))a1(1)

J(Θ)Θ22(1)=J(Θ)a1(4)a1(4)z1(4)(z1(4)a1(3)a1(3)z1(3)z1(3)a2(2)+z1(4)a2(3)a2(3)z2(3)z2(3)a2(2))a2(2)z2(2)z2(2)Θ22(1)=(a1(4)y)[Θ11(3)a1(3)(1a1(3))Θ12(2)+Θ12(3)a2(3)(1a2(3))Θ22(2)]a2(2)(1a2(2))a2(1)

Tips

image

我们已经看到,单分类 Θ(1) 2x3 的导数公式计算J(Θ)Θ(1), 因为函数嵌套越发深入,如果从头开始,计算量将会十分复杂

J(Θ)z(j+1)=δ(j+1) 是一个接口,它一方面可以找到 Θj 也就是我们最终要计算的导数(在此即可终止)。也可以找到aj(再次出发), 利用aj解开zj从而又形成下一层的接口J(Θ)z(j)=δ(j)。找到下一层Θ的导数。

因此δ是公式上的存档,我们要做的就是。并且只是。首先开解 z(j+1)a(j),再开解a(j)z(j)。分别对应Θ 以及 sigmoid的导数。并保存为下一个存档。如此往复

δ4=a4yδ3=(Θ(3))Tδ4.a(3)(1a(3))removeδ03δ2=(Θ(2))Tδ3.a(2)(1a(2))removeδ02

因为隐藏层的bais unit是一个常数,并不对应下一层的接口。从公式上也可以得出,bais unit的δ对应值为零。所以我们删除他们,同时也使得下一层的δ计算时符合矩阵运算的维度要求。

J(Θ)Θ(3)=δ4a3=(a4y)a3J(Θ)Θ(2)=δ3a2J(Θ)Θ(1)=δ2a1

δ(l) is vector, a(l1) is matrix.

多分类怎么计算呢?自己想一想吧。

代码示例

image

这是手写数字数据集的反向传播实践。X 5000张手写数字的400像素灰度图片。两个权重 Theta1 Theta2.

通过前向传播计算costJ,通过反向传播计算 J(Θ)Θ(j)

10分类,3层神经网络。

image

% ----X = 5000x400; y = 5000x1; Theta1 = 25x401; Theta2 = 10x26----
% ----Feedforward----
a1 = X;
a1 = [ones(m,1) a1];	% 5000x401

z2 = a1 * Theta1';		% 5000x401 401x25
a2 = sigmoid(z2);
a2 = [ones(size(a2,1),1) a2];	%5000x26

z3 = a2 * Theta2';		% 5000x26 26x10
a3 = sigmoid(z3);

% ----Cost By For Loop and Not Regularized----
%for k=1:num_labels,
%	y_k = (y==k);
%	J = J -(1/m) * (y_k' * log(a3(:,k)) + (1 - y_k') * log(1 - a3(:,k)));
%end

% ----Cost By Matrix and Not Regularized----
% y_K = 5000x10. Notice that " .* ";
y_K = zeros(m, num_labels);
for k=1:num_labels,
	y_K(:,k) = (y==k);
end

% First Part Not Regularied
%J = -(1/m) * sum(sum((y_K .* log(a3) + (1 - y_K) .* log(1 - a3))));

Theta1_fix = [zeros(size(Theta1,1),1) Theta1(:,2:end)];
Theta2_fix = [zeros(size(Theta2,1),1) Theta2(:,2:end)];
Theta_fix = [Theta1_fix(:);Theta2_fix(:)];

% Regularied
J = -(1/m) * sum(sum((y_K .* log(a3) + (1 - y_K) .* log(1 - a3)))) + (lambda/(2*m)) * sum(Theta_fix .^2);

gDz2 = sigmoidGradient(z2);		% 5000x25
deltaL3 = (a3 .- y_K)';			% 5000*10' = 10*5000
deltaL2 = Theta2' * deltaL3 .*  [zeros(size(gDz2,1),1) gDz2]';	% 26*5000 .* 26*5000

% First Part Not Regularied
%Theta2_grad = (1/m) * deltaL3 * a2 ;
%Theta1_grad = (1/m) * deltaL2(2:end,:) * a1 ;

Theta2_grad = (1/m) * deltaL3 * a2 + (lambda/m) * Theta2_fix;
Theta1_grad = (1/m) * deltaL2(2:end,:) * a1 + (lambda/m) * Theta1_fix;

Reference

[1] Andrew NG. Coursera Machine Learning Deep Learning. Cost Function and BackPropagation.

文章会随时改动,要到博客园里看偶。一些网站会爬取本文章,但是可能会有出入。
转载请注明出处哦( ̄︶ ̄)↗ 
https://www.cnblogs.com/asmurmur/

posted @   Dba_sys  阅读(316)  评论(0编辑  收藏  举报
编辑推荐:
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
阅读排行:
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
点击右上角即可分享
微信分享提示