机器学习笔记(3): 神经网络初步

神经网络应该由若干神经元组成。

机器学习笔记(3): 神经网络初步

前面的每一个神经元都会给到一个参数,将传递的所有参数看作一个向量 (vec x),那么此神经元的净输入为:

[z = x omega + b ]

其中 (omega) 称为权重向量

这里认为 (x)向量,而 (omega)向量。

神经元还有一个激活函数 (f(cdot))

[a = f(z) ]

称为函数的活性值

一般来说,我们使用 Logistic 函数,即 (sigma(x) = frac 1 {1 + exp(-x)}) 作为激活函数。

激活函数

激活函数有很多很多种,一般来说要满足以下几点:

  1. 连续且可导的非线性函数。
  2. 函数本身和其导数要尽可能简单。
  3. 值域要在一个合适的区间内

这里列举几种常见的函数。

Sigmoid 型

指一类两端饱和的 S 型曲线。

饱和
(lim_limits{x to -infty} f'(x) = 0) 称为左饱和,(lim_limits{x to infty} f'(x) = 0) 称为右饱和。
同时满足则称为两端饱和。

常见的 Sigmoid 型函数有 LogisticTanh

  • Logistic 函数
[sigma(x) = frac 1 {1 + exp(-x)} ]

其导数:

[sigma'(x) = frac {exp(-x)}{(1 + exp(-x))^2} = sigma(x) (1 - sigma(x)) ]

  • Tanh 函数
[{rm tanh}(x) = frac {exp(x) - exp(-x)}{exp(x) + exp(-x)} ]

其可以看作缩放平移后的 (sigma),因为:

[{rm tanh}(x) = 2 sigma(2x) - 1 ]

自然其导数:

[{rm tanh}'(x) = 4 sigma(2x)(1 - sigma(2x)) = frac {4}{(exp(x) + exp(-x))^2} ]

实际上我们可以通过近似的方法去拟合这个函数,毕竟 (e^x) 也不是那么好算的。

  • Hard-LogisticHard-Tanh 函数
[{rm hard-sigma}(x) = begin{cases} 1 & x > 2 \ frac x 4 + frac 1 2 & x in [-2, 2] \ 0 & x < 2 end{cases} ]

或者利用 (min, max) 简化:

[{rm hard-sigma}(x) = max(min(frac x 4 + frac 1 2, 1), 0) ]

类似的:

[{rm hard-tanh}(x) = max(min(x, 1), -1) ]

机器学习笔记(3): 神经网络初步

机器学习笔记(3): 神经网络初步

ReLU

也就是 Rectified Linear Unit,线性修正单元,定义为:

[{rm ReLU}(x) = begin{cases} x & x ge 0 \ 0 & x < 0 end{cases} ]

也就是 ({rm ReLU}(x) = max(x, 0))

当然,因为可能出现 死亡 ReLU 问题,所以一般有如下变形:

[{rm PReLU}(x) = begin{cases} x & x ge 0 \ gamma x & x < 0 end{cases} ]

如果 (gamma = 0) 则退化为 (rm ReLU) 函数,如果 (gamma < 1),那么也可以写为:

[{rm LeakyLU(x)} = max(x, gamma x) ]

另一个变形是:

[{rm ELU}(x) = begin{cases} x & x ge 0 \ gamma(exp(x) - 1) & x < 0 end{cases} ]

还有一个则是:

[{rm Softplus}(x) = log(1 + exp(x)) ]

机器学习笔记(3): 神经网络初步

Swish 函数

这是一种自控门函数:

[{rm swish}(x) = x sigma(beta x) ]

机器学习笔记(3): 神经网络初步

网络结构

网络结构分三种:

  • 前馈网络
  • 记忆网络
  • 图网络

这里先讲述前馈网络

机器学习笔记(3): 神经网络初步

这是一个前馈网络的示意图,其中第一层为输入层,最后一层为输出层。

而中间的那些层称为隐藏层。隐藏层可以有多个,而这里只画出了一个。

每一层有若干神经元,而两层间的神经元两两相连。

现在我们定义一些符号:

  • (L) 表示总层数,注意这里输入层为第 (0) 层,不计入其中;输出层为第 (L) 层。
  • (M_l) 表示第 (l) 层的神经元数量。
  • (f_l(cdot)) 表示第 (l) 层的激活函数。
  • (W^{(l)} in mathbb{R}^{M_l times M_{l - 1}}) 表示第 (l - 1) 层到第 (l) 层的权重矩阵(若干权重向量组成)。
  • (b^{(l)} in mathbb{R}^{M_l}) 表示第 (l) 层的偏置。
  • (z^{(l)} in mathbb{R}^{M_l}) 表示净输入。
  • (a^{(l)} in mathbb{R}^{M_l}) 表示输出。

对于一组数据 ((vec x, y)),前馈神经网络通过如下算法进行传播:

[begin{aligned} z^{(l)} &= W^{(l)} a^{(l - 1)} + b^{(l)} \ a^{(l)} &= f_l(z^{(l)}) end{aligned} ]

参数学习

参数学习可能略有点复杂,证明过程我懒得写成 (LaTeX),这里就省略了。

我们利用反向传播算法进行学习,其步骤如下:

  • 选取一个数据,计算 (a^{(l)})(z^{(l)})
  • 反向传播每一层的误差 (delta^{(l)})
  • 计算每一层的偏导数,更新参数

显然的是 (delta^{(L)} = a^{(L)} - y)

经过一番神秘的推导,我们可以得到:

[delta^{(l)} = f_l'left(z^{(l)}right) cdot left( left( W^{(l + 1)} right)^T delta^{(l + 1)} right) in mathbb{R}^{M_l} ]

其中 (cdot) 表示元素一一相乘。

而计算偏导数的公式也不难:

[begin{aligned} frac {partial}{partial W^{(l)}} R(W) &= delta^{(l)} left( a^{(l - 1)} right)^T \ frac {partial}{partial b^{(l)}} R(W) &= delta^{(l)} end{aligned} ]

也就是参数更新方式为:

[begin{aligned} W^{(l)} &leftarrow W^{(l)} - alpha left( delta^{(l)} left( a^{(l - 1)} right)^T + lambda W^{(l)} right) \ b^{(l)} &leftarrow b^{(l)} - alpha delta^{(l)} end{aligned} ]

但是值得注意的是,一般我们都会将 (W^{(l)}) 的第一列作为 (b^{(l)}),也就是不分开,所以在代码实现上要好生注意!

这是吴恩达机器学习 ex4 的部分代码:

function [J grad] = nnCostFunction(nn_params, ...                                    input_layer_size, ...                                    hidden_layer_size, ...                                    num_labels, ...                                    X, y, lambda)  % Theta1 25 x 401 % Theta2 10 x 26  Theta1 = reshape(nn_params(1:hidden_layer_size * (input_layer_size + 1)), ...                  hidden_layer_size, (input_layer_size + 1));  Theta2 = reshape(nn_params((1 + (hidden_layer_size * (input_layer_size + 1))):end), ...                  num_labels, (hidden_layer_size + 1));                   temp1 = Theta1; temp2 = Theta2; temp1(:, 1) = 0; temp2(:, 1) = 0;  m = size(X, 1);           J = 0; Theta1_grad = zeros(size(Theta1)); Theta2_grad = zeros(size(Theta2));  % forward propagation A2 = sigmoid([ones(m, 1) X] * Theta1'); % m x 25 A3 = sigmoid([ones(m, 1) A2] * Theta2'); % m x 10  % caculate cost Y = zeros(m, num_labels); for i = 1:m 	Y(i, y(i)) = 1; end J -= sum(sum( log(A3) .* Y + log(1 - A3) .* (1 - Y) )); J += lambda / 2 * (sum(sum(temp1 .* temp1)) + sum(sum(temp2 .* temp2))); J /= m;  % Back Propagation  D1 = zeros(size(Theta1)); D2 = zeros(size(Theta2));  for i = 1:m 	a1 = X(i, :); % 1 x 400 	a2 = A2(i, :); % 1 x 25 	a3 = A3(i, :); % 1 x 10 	y = Y(i, :); % 1 x 10 	d3 = (a3 - y)'; % 10 x 1 	d2 = (Theta2' * d3) .* [1 a2]' .* (1 - [1 a2])'; % 26 x 1 	d2 = d2(2:end) ; % 25 x 1 	 	D1 += d2 * [1 a1]; 	D2 += d3 * [1 a2]; end  Theta1_grad = (D1 + lambda * temp1) / m; Theta2_grad = (D2 + lambda * temp2) / m;  % Unroll gradients grad = [Theta1_grad(:) ; Theta2_grad(:)];  end  

发表评论

评论已关闭。

相关文章