机器学习笔记(3): 神经网络初步
神经网络应该由若干神经元组成。
前面的每一个神经元都会给到一个参数,将传递的所有参数看作一个向量 ,那么此神经元的净输入为:
其中 称为权重向量。
这里认为 是行向量,而 是列向量。
神经元还有一个激活函数 :
称为函数的活性值
一般来说,我们使用 Logistic 函数,即 作为激活函数。
激活函数
激活函数有很多很多种,一般来说要满足以下几点:
- 连续且可导的非线性函数。
- 函数本身和其导数要尽可能简单。
- 值域要在一个合适的区间内
这里列举几种常见的函数。
Sigmoid 型
指一类两端饱和的 S 型曲线。
饱和:
称为左饱和, 称为右饱和。
同时满足则称为两端饱和。
常见的 Sigmoid 型函数有 Logistic
和 Tanh
。
Logistic
函数
其导数:
Tanh
函数
其可以看作缩放平移后的 ,因为:
自然其导数:
实际上我们可以通过近似的方法去拟合这个函数,毕竟 也不是那么好算的。
Hard-Logistic
和Hard-Tanh
函数
或者利用 简化:
类似的:
ReLU
也就是 Rectified Linear Unit,线性修正单元,定义为:
也就是
当然,因为可能出现 死亡 ReLU 问题
,所以一般有如下变形:
如果 则退化为 函数,如果 ,那么也可以写为:
另一个变形是:
还有一个则是:
Swish 函数
这是一种自控门函数:
网络结构
网络结构分三种:
- 前馈网络
- 记忆网络
- 图网络
这里先讲述前馈网络。
这是一个前馈网络的示意图,其中第一层为输入层,最后一层为输出层。
而中间的那些层称为隐藏层。隐藏层可以有多个,而这里只画出了一个。
每一层有若干神经元,而两层间的神经元两两相连。
现在我们定义一些符号:
- 表示总层数,注意这里输入层为第 层,不计入其中;输出层为第 层。
- 表示第 层的神经元数量。
- 表示第 层的激活函数。
- 表示第 层到第 层的权重矩阵(若干权重向量组成)。
- 表示第 层的偏置。
- 表示净输入。
- 表示输出。
对于一组数据 ,前馈神经网络通过如下算法进行传播:
参数学习
参数学习可能略有点复杂,证明过程我懒得写成 ,这里就省略了。
我们利用反向传播算法进行学习,其步骤如下:
- 选取一个数据,计算 和 。
- 反向传播每一层的误差
- 计算每一层的偏导数,更新参数
显然的是
经过一番神秘的推导,我们可以得到:
其中 表示元素一一相乘。
而计算偏导数的公式也不难:
也就是参数更新方式为:
但是值得注意的是,一般我们都会将 的第一列作为 ,也就是不分开,所以在代码实现上要好生注意!
这是吴恩达机器学习 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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?