神经网络的代价函数
定义
L = 神经网络总层数
sl = 第l层的单元数(不包含bias unit)
K = output units/classes的数量
普通逻辑回归代价函数:
神经网络代价函数:
后面的正则化部分,θ矩阵的:
- 列数=当前层的节点数(包含bias unit)
- 行数=下一层的节点数(不包含bias unit)
反向传播
先正向推导:
再反向求代价:
D:delta矩阵,它正好是J(θ)的偏导函数
有点复杂。暂不深究细节,先会用。
反向传播和正向传播很像,只是换了个方向:
反向传播实现
参数展开
展开参数,作为一个输入:
thetaVector = [ Theta1(:); Theta2(:); Theta3(:); ]
deltaVector = [ D1(:); D2(:); D3(:) ]
在函数里面,还原出各个矩阵:
Theta1 = reshape(thetaVector(1:110),10,11)
Theta2 = reshape(thetaVector(111:220),10,11)
Theta3 = reshape(thetaVector(221:231),1,11)
在反向传播中的应用为:
梯度检查(Gradient Checking)
近似法求导数:
对于多个θ的矩阵,可以用近似法逐个求偏导:
当ε足够小时(比如ε = 10-4),可以得到近似的导数值。
计算gradApprox的伪代码如下:
epsilon = 1e-4;
for i = 1:n,
thetaPlus = theta;
thetaPlus(i) += epsilon;
thetaMinus = theta;
thetaMinus(i) -= epsilon;
gradApprox(i) = (J(thetaPlus) - J(thetaMinus))/(2*epsilon)
end;
梯度检查可以与DVec对比,检查自己求解是否正确。
这种方法的梯度检查效率比较低,在真正开始训练时要记得关闭梯度检查。
随机初始θ
如果上层每个节点的θij的值都相同(比如0),那么该节点输出到下个节点的结果就都相同,最终造成下层每个a都相同;更进一步,正向传播求时的偏导也相同,每次更新后,下层的每个a仍是相同的,相当于到了后面,只有一个特征了:
需要打破对称性,对每个θ矩阵内部引入随机数初始化:
伪代码为:
If the dimensions of Theta1 is 10x11, Theta2 is 10x11 and Theta3 is 1x11.
Theta1 = rand(10,11) * (2 * INIT_EPSILON) - INIT_EPSILON;
Theta2 = rand(10,11) * (2 * INIT_EPSILON) - INIT_EPSILON;
Theta3 = rand(1,11) * (2 * INIT_EPSILON) - INIT_EPSILON;
整体流程
架构设计
- 输入节点数:x的特征维度数
- 输出节点数:在多分析类问题中,等于类别数
- 隐藏层的节点数:越多效果越好,但计算量越大,需要权衡
- 默认值:1个隐藏层,若多于1个隐藏层,则每个隐藏层的节点数一样
计算流程
- 随机初始化权值(θ)
- 正向传播,计算hx
- 计算代价函数
- 反向传播,计算偏导数
- 用梯度检查确认反向传播是否正确。然后关闭提督检查。
- 使用梯度下降或优化算法,来最小化代价函数,求出最佳θ。
循环对每个样本进行正向、反向传播:
for i = 1:m,
Perform forward propagation and backpropagation using example (x(i),y(i))
(Get activations a(l) and delta terms d(l) for l = 2,...,L
神经网络的工作过程大致如下:
作业
θ的维度,就是 新特征数 * 旧特征数 。因为θ的作用,就是计算出新的维度。
% Theta1 has size 25 x 401
% Theta2 has size 10 x 26
作业有难度,反向传播部分代码参考了https://github.com/everpeace/ml-class-assignments
nnCostFunction.m
function [J grad] = nnCostFunction(nn_params, ...
input_layer_size, ...
hidden_layer_size, ..<