神经网络

神经网络算法

感知机(Perceptron)

神经元(neuron)模型

  • 联结主义:神经网络是由具有适应性的简单单元组成的广泛并行互连的网络,它的组织能够模拟生物神经系统对真实世界物体所作出的交互反应。
  • 神经网络中最基本的成分是神经元(neuron)模型,即“简单单元”,在生物神经网络中,每个神经元与其他神经元相连,当它“兴奋”时,就会向相连的神经元发送化学物质,从而改变这些神经元内的电位;如果某神经元的电位超过一个“阈值(threshold)”,那么它就会被激活,即“兴奋” 起来,向其他神经元发送化学物质。

神经元

感知机模型

  • 感知机由单个神经元组成的单层神经网络,树突接收其他轴突传递来的信息,在通过自己的轴突传递出去。感知机三个功能:加权、求和、激励

感知机

  • 权重及阈值θ通过学习获得,阈值θ可看做一个固定输入为-1的哑结点(dummy node)所对应的权重 。这样权重和阈值可以统一学习。对训练样例(x,y),感知机输出 ,学习规则:wiwi+wiw_i←w_i+\nabla{w_i} wi=η(yy^)xi\nabla{w_i}=η(y-\widehat{y})x_i
  • η∈(0,1)称为学习率(learning rate)。

对偶形式

  • 每一轮迭代中我们都要判断某个输入实例是不是误判点,即yi(wxi+b)<=0y_i(wx_i+b)<=0则为误判,需要更新权重。时间复杂度O(n),n为特征数量。
  • 使用对偶形式,判断条件改为:yi(j=1Najyjxjxi+b)y_i(\sum_{j=1}^{N}a_jy_jx_jx_i+b),预先计算输入实例两两内积,得到Gram矩阵G=[xixj]NNG=[x_ix_j]_{N*N},时间复杂度为O(N),N为训练数据数量。
  • 对偶形式的目的是降低运算量,但是并不是在任何情况下都能降低运算量,而是在特征空间的维度很高时才起到作用。

感知机的问题

  • 感知机只有输出层神经元进行激活函数处理,即只拥有一层功能神经元。与或非问题都是线性可分(linearly separable)。感知机对线性可分学习过程一定收敛,非线性可分问题w难以稳定下来,不能求合适的解,如下图。

感知机无法解决非线性问题

  • 要解决非线性可分问题,需要考虑使用多层功能神经元

能解决非线性问题的两层感知机

多层感知机

多层感知机模型

多层感知机

网络结构

  • 输入层:xi(i=0,...d)x_i(i=0,...d)

  • 隐藏层:隐藏单元zh(h=1,...H)z_h(h=1,...H),只有一个隐藏层时,网络是两层网络。

  • 输出层:yi(i=0,...K)y_i(i=0,...K)

  • 多层感知机层与层之间是全连接的

  • 网络结构中,输入层与输出层之间的神经元层成为隐含层(hidden layer),每层神经元与下一层神经元完全互联,神经元之间不存在同层连接,也不存在跨层连接,称为多层前馈网络结构(multi-layer feedforward nerual networks)

    • 多层网络:包含隐层的网络
    • 前馈网络:神经元之间不存在同层连接也不存在跨层连接
  • 隐层和输出层具有激活函数,所以这两层的神经元亦称“功能单元”。多层前馈网络有强大的表示能力。只需一个包含足够多神经元的隐层,多层前馈神经网络就能以任意精度逼近任意复杂度的连续函数。设置隐层神经元数,通常用“试错法”。

    • 主要特点:信号是前向传播的,而误差是反向传播的。
    • 主要过程:信号的前向传播,从输入层经过隐含层,最后到达输出层
    • 误差的反向传播,从输出层到隐含层,最后到输入层,依次调节隐含层到输出层的权重和偏置,输入层到隐含层的权重和偏置

全连接层

全连接层

前向运算

  • 放射变换:Y=XW+BY=X \cdot W +B
  • X=(x0,...xn)X=(x_0,...x_n)

反向运算

  • J是代价函数
  • JX=(Jx0...)\frac{\partial J}{\partial X}=(\frac{\partial J}{\partial x_0}...)
  • JX=JYWT\frac{\partial J}{\partial X}=\frac{\partial J}{\partial Y}\cdot W^T
  • JW=XTJY\frac{\partial J}{\partial W}=X^T\cdot\frac{\partial J}{\partial Y}

激活函数

  • 隐层一般使用sigmoid、tanh、relu
  • 输出层根据任务不同,二分类问题使用sigmoid、tanh、relu,多分类使用softmax

阶跃函数

  • 理想激活函数是阶跃函数,0 表示抑制神经元,而1表示激活神经元
  • 阶跃函数具有不连续、不光滑等不好的性质,常用的是Sigmoid函数

stepfunc(x)=1  if  x>0  else  0stepfunc(x)=1\;if\;x>0\;else\;0

Sigmoid函数

  • Sigmoid函数可能在较大范围内变化的输入值挤压到(0,1)输出值范围内,因此有时也称为”挤压函数”
  • 把这样许多个神经元按一定的层次结构连接起来,就得到了神经网络。

Sigmoid函数

sigmoid(x)=11+exsigmoid(x)=\frac{1}{1+e^{-x}}

tanh函数

  • tanh函数趋近0的速度比sigmoid更为快

f(x)=tanh(x)=exexex+exf(x)=tanh(x)=\frac{e^{x}-e^{-x}}{e^{x}+e^{-x}}

x = np.linspace(-10,10)
y = np.tanh(x)

ReLu函数

relu(x)=max{0,x}relu(x)=max\{0,x\}

Leaky ReLu函数

relu(x)=max{0.1x,x}relu(x)=max\{0.1x,x\}

ELU函数

{x if x>0α(ex1) if x0\begin{cases} x & \text{ if } x>0 \\ \alpha (e^x-1) & \text{ if } x\le0\end{cases}

ReLU6函数

relu(x)=min(max{0,x},6)relu(x)=min(max\{0,x\},6)

二分类

  • 使用sigmoid函数:σ(ωTx+b)=11+e(ωTx+b)\sigma(\omega^Tx+b)=\frac{1}{1+e^{-(\omega^Tx+b)}}
  • 条件概率为:pw(y=1x)=σ(ωTx+b)p_w(y=1|x)=\sigma(\omega^Tx+b) pw(y=0x)=1σ(ωTx+b)p_w(y=0|x)=1-\sigma(\omega^Tx+b)

多分类

softmax

  • 假设有一个数组V,ViV_i表示V中的第i个元素,那么这个元素的softmax值为:
  • Si=eijejS_i=\frac{e^i}{\sum_j{e^j}}
  • 把大范围的输入转为[0,1]范围的概率形式

softmax

def softmax(x):
if x.ndim == 2:
x = x.T
x = x - np.max(x, axis=0)
y = np.exp(x) / np.sum(np.exp(x), axis=0)
return y.T
x = x - np.max(x) # 防止x过大导致exp结果溢出
return np.exp(x) / np.sum(np.exp(x))

损失函数

又称目标函数(objective function),或误差函数(error function),或代价函数(cost function) , 或经验风险(empirical risk);用来度量网络实际输出与期望输出之间的不一致程度,指导网络的参数学习和表示学习。

回归问题

  • SSE(Sum of Squared Error)均方误差和
  • J(θ)=12mi=1m(hθ(x(i))y(i))2+λj=1nθj2J(\theta)=\frac{1}{2m}\sum_{i=1}^{m}{(h_\theta(x^{(i)})-y^{(i)})^2}+\lambda\sum_{j=1}^{n}{\theta^2_j}

交叉熵损失

  • CE(Cross Entropy)交叉熵,对数损失

  • J(θ)=1mi=1my(i)lnhθ(x(i))+(1y(i))ln(1hθ(x(i)))+λj=1nθj2J(\theta)=-\frac{1}{m}\sum_{i=1}^{m}{y^{(i)}\ln{h_\theta(x^{(i)})+(1-y^{(i)})\ln{(1-h_\theta(x^{(i)})})}}+\lambda\sum^{n}_{j=1}{\theta^2_j}

  • 用于度量变量不确定性的程度:H(X)=i=1np(xi)logp(xi)H(X)=-\sum^{n}_{i=1}{p(x_i)\log{p(x_i)}},越大说明不确定性越高

  • 交叉熵用于度量两个概率分布间的差异性信息,越确信交叉熵越小

  • 设 p(x),q(x) 分别是离散随机变量X的两个概率分布,其中p(x)是目标分布,p和q的交叉熵可以看做是,使用分布q(x) 表示目标分布p(x)的困难程度:H(p,q)=ip(xi)log1logq(xi)=ip(xi)logq(xi)H(p,q)=\sum_i{p(x_i)\log{\frac{1}{\log{q(x_i)}}}}=-\sum_i{p(x_i)\log{q(x_i)}}

  • 交叉熵损失用于描述真实概率和模型预测概率的交叉熵

  • softmax得到预测的概率之后,把标签进行独热编码,再使用交叉熵损失函数优化模型。

  • p(y)p(y)q(y)q(y)完全匹配,交叉熵和熵的计算值相等。但其实交叉熵比在真实分布上计算出的熵具有更大的值,这种差异称为Kullback-Leibler Divergence。简称KL散度。度量两分布的差异:DKL(PQ)=xXp(x)logq(x)+xXp(x)logp(x)=H(P,Q)H(P)D_{KL}(P||Q)=-\sum_{x\in X}{p(x)\log{q(x)}}+\sum_{x\in X}{p(x)\log{p(x)}}=H(P,Q)-H(P)

def cross_entropy_error(y, t):
delta = 1e-7
return -np.sum(t * np.log(y + delta))

折页损失

  • 由于交叉熵损失需要先将输出经过softmax,当输出结果较多时,计算量指数增加。
  • 铰链损失函数(Hinge Loss)不需要输出的概率值,就可以得到输出损失

Loss=jyimax(0,f(xi,W)jf(xi,W)yj+)Loss=\sum_{j\ne y_i}^{}{max(0,f(x_i,W)_j-f(x_i,W)_{y_j}+\triangle)}

  • 一般固定=1\triangle=1

梯度下降法

  • 求解非线性无约束优化问题的基本方法
  • wi+1=wiaJxw_{i+1}=w_i-a\frac{\partial{J}}{\partial{x}}
  • J是损失函数,沿负梯度方向迭代求解最优参数,a是学习率

批量梯度下降

  • (Batch Gradient Descent )利用全部训练数据集计算损失函数的梯度来执行一次参数更新

  • θθηJ(θ)\theta\Rightarrow\theta-\eta\cdot\triangledown{J(\theta)}

  • 缺点:更新较慢、不能在线更新模型

  • 优点:对凹函数可得到全局最小,非凸函数可收敛到局部极小

随机梯度下降

  • SGD (Stochastic Gradient Descent)对每一个训练样本点和标签执行参数更新
  • θθηJ(θ;x(i);y(i))\theta\Rightarrow\theta-\eta\cdot\triangledown{J(\theta;x^{(i)};y^{(i)})}
  • 缺点:梯度精度差、目标函数下降过程出现较大波动、难以跳出局部极小值点和鞍点
  • 优点:速度快,可在线学习
class SGD:
def __init__(self, lr=0.01):
self.lr = lr
def update(self, params, grads):
for key in params.keys():
params[key] -= self.lr * grads[key]

小批量梯度下降

  • (Mini-batch Gradient Descent)每𝑚个训练样本点,进行一次参数更新
  • θθηJ(θ;x(i:i+m);y(i:i+m))\theta\Rightarrow\theta-\eta\cdot\triangledown{J(\theta;x^{(i:i+m)};y^{(i:i+m)})}
  • Batch-GD和单样本SGD方法的折衷
  • 优点:减小了参数更新的方差,可平稳收敛;速度快,可利用优化的矩阵运算库来高效的计算梯度
  • Batch大小根据问题来定。一般而言设为32、 64、 128或256即可。

梯度下降改进算法

动量法Momentum

  • 动量法,把过去时间步骤更新矢量的一部分(𝛾)加到当前更新矢量

  • v1=ηJ(θ)v1=\eta\triangledown{J(\theta)} vk=γvk1+ηJ(θk1),γ(0,1)v_k=\gamma v_{k-1}+\eta\triangledown J(\theta_{k-1}), \gamma\in(0,1) θk=θk1vk\theta_k=\theta_{k-1}-v_k

  • 动量项𝛾 一般设为0.9。可理解为“摩擦”效果,速度的逐渐增加是作为梯度的移动平均

class Momentum:
def __init__(self, lr=0.01, momentum=0.9):
self.lr = lr
self.momentum = momentum
self.v = None
def update(self, params, grads):
if self.v is None:
self.v = {}
for key, val in params.items():
self.v[key] = np.zeros_like(val)
for key in params.keys():
self.v[key] = self.momentum*self.v[key] - self.lr*grads[key]
params[key] += self.v[key]

NAG

  • NAG是为动量项提供预知能力的一种方法。
  • vk=γvk1+ηJ(θk1γvk1),γ(0,1)v_k=\gamma v_{k-1}+\eta\triangledown J(\theta{k-1}-\gamma v_{k-1}), \gamma\in(0,1) θk=θk1vk\theta_k=\theta_{k-1}-v_k

NAG

class Nesterov:
def __init__(self, lr=0.01, momentum=0.9):
self.lr = lr
self.momentum = momentum
self.v = None
def update(self, params, grads):
if self.v is None:
self.v = {}
for key, val in params.items():
self.v[key] = np.zeros_like(val)
for key in params.keys():
self.v[key] *= self.momentum
self.v[key] -= self.lr * grads[key]
params[key] += self.momentum * self.momentum * self.v[key]
params[key] -= (1 + self.momentum) * self.lr * grads[key]

Adagrad

  • Adagrad对不同的参数调整使用不同的学习率,学习率衰减(learning rate decay)

    • 对非频繁出现特征相关的参数执行较大的更新(即较大的学习率)
    • 对频繁出现特征相关的参数执行较小的学习率(即较小的学习率)
  • gt,i=J(θi,t)g_{t,i}=\triangledown J(\theta_{i,t}) θt+1,j=θt,iηGt,ii+εgt,i\theta_{t+1,j}=\theta{t,i}-\frac{\eta}{\sqrt{G_{t,ii}+\varepsilon}}\cdot g_{t,i}

  • 𝐺𝑡是一个对角矩阵,其每一个对角元素是到时间𝑡的梯度的平方之和,即i=1tgi2\sum^{t}_{i=1}g^2_i

  • 𝜖 是一个平滑项以避免除以零(通常大小为 1𝑒 − 8).

  • 缺点:分母的梯度平方逐步累计变大,可导致学习率不断收缩,收敛变慢,从而失去学习能力

class AdaGrad:
def __init__(self, lr=0.01):
self.lr = lr
self.h = None
def update(self, params, grads):
if self.h is None:
self.h = {}
for key, val in params.items():
self.h[key] = np.zeros_like(val)
for key in params.keys():
self.h[key] += grads[key] * grads[key]
params[key] -= self.lr * grads[key] / (np.sqrt(self.h[key]) + 1e-7)

Adadelta

  • Adagrad的改进版:
    • 计算历史梯度信息时引入时间窗,而非所有历史时间(引入衰减因子)

      • E[g2]t=γE[g2]t1+(1γ)g2E[g^2]_t=\gamma E[g^2]_{t-1}+(1-\gamma)g^2
      • θt=ηE[g2]t+εgt\triangle\theta_{t}=-\frac{\eta}{\sqrt{E[g^2]_t+\varepsilon}}g_t
      • θt=ηRMS[g]tgt\triangle\theta_t=-\frac{\eta}{RMS[g]_t}g_t
    • 累积参数历史更新量进行加速(类似于动量方法),由Hessian方法推导出一阶近似Hessian方法

      • E[θ2]t=γE[θ2]t1+(1γ)θt2E[\triangle\theta^2]_t=\gamma E[\triangle \theta2]_{t-1}+(1-\gamma)\triangle\theta^2_t
      • RMS[θ]t=E[θ2]t+εRMS[\triangle\theta]_t=\sqrt{E[\triangle\theta^2]_t+\varepsilon}

RMSprop

  • RMSProp是一个未正式发表的自适应学习率方法;由Geoff Hinton提出
  • E[g2]t=0.9E[g2]t1+0.1g2E[g^2]_t=0.9E[g^2]_{t-1}+0.1g^2 θt+1=θt1E[g2]t+εgt\theta_{t+1}=\theta_{t}-\frac{1}{\sqrt{E[g^2]_t+\varepsilon}}g_t
  • Hinton建议𝛾 设为 0.9, 学习率𝜂 的默认值为0.001
  • RMSProp方法并不是将过去所有的梯度一视同仁地相加,而是逐渐地遗忘过去的梯度,在做加法运算时将新梯度的信息更多地反映出来。即采用“指数移动平均”:最近 1/(1 − 𝛾) 个时间步的小批量随机梯度平方项的加权平均。
class RMSprop:
def __init__(self, lr=0.01, decay_rate = 0.99):
self.lr = lr
self.decay_rate = decay_rate
self.h = None
def update(self, params, grads):
if self.h is None:
self.h = {}
for key, val in params.items():
self.h[key] = np.zeros_like(val)
for key in params.keys():
self.h[key] *= self.decay_rate
self.h[key] += (1 - self.decay_rate) * grads[key] * grads[key]
params[key] -= self.lr * grads[key] / (np.sqrt(self.h[key]) + 1e-7)

Adam

  • Adam是另外一种为每一参数计算自适应学习率的方法,除了像Adadelta和RMSprop存储过去梯度平方的指数衰减平均值𝑣𝑡, Adam也保留了过去梯度的指数衰减平均值𝑚𝑡, 类似动量

  • mt=β1mt1+(1β1)gtm_t=\beta_1m_{t-1}+(1-\beta_1)g_t

  • vt=β2vt1+(1β2)gt2v_t=\beta_2v_{t-1}+(1-\beta_2)g_t^2

  • 𝑚𝑡 和𝑣𝑡分别是一阶矩(均值) 和梯度二阶矩(有偏方差) 的估计值,含有偏差校正(bias-corrected) 的一阶矩和二阶矩 的估计:m^t=mt1β1t\hat{m}_t=\frac{m_t}{1-\beta_1^t} v^t=vt1β2t\hat{v}_t=\frac{v_t}{1-\beta_2^t}

  • 参数 𝛽1、 𝛽2 ∈ [0, 1) 控制了这些移动均值(moving average)指数衰减率。

  • 更新规则θt+1=θtηv^t+εm^t\theta_{t+1}=\theta{t}-\frac{\eta}{\sqrt{\hat{v}_t}+\varepsilon}\hat{m}_t

  • Adam 的核心在于用指数滑动平均去估计梯度每个分量的一阶矩(动量)和二阶矩(用于自适应学习率),并用二阶矩去归一化一阶矩,得到每一步的更新量。通常而言, Adam是自适应学习率算法的较优选择

class Adam:
def __init__(self, lr=0.001, beta1=0.9, beta2=0.999):
self.lr = lr
self.beta1 = beta1
self.beta2 = beta2
self.iter = 0
self.m = None
self.v = None
def update(self, params, grads):
if self.m is None:
self.m, self.v = {}, {}
for key, val in params.items():
self.m[key] = np.zeros_like(val)
self.v[key] = np.zeros_like(val)
self.iter += 1
lr_t = self.lr * np.sqrt(1.0 - self.beta2**self.iter) / (1.0 - self.beta1**self.iter)
for key in params.keys():
self.m[key] += (1 - self.beta1) * (grads[key] - self.m[key])
self.v[key] += (1 - self.beta2) * (grads[key]**2 - self.v[key])
params[key] -= lr_t * self.m[key] / (np.sqrt(self.v[key]) + 1e-7)

误差逆传播算法——BP神经网络

  • 误差逆传播(error BackPropagation,简称BP)它是迄今为止最成功的神经网络学习算法,现实任务中使用神经网络时,大多在使用BP算法进行训练多层前馈神经网络,还可用于训练例如递归神经网络。

链式法则

  • y=g(x)y=g(x)z=h(y)z=h(y)
    • xyz\nabla{x}\rightarrow\nabla{y}\rightarrow\nabla{z}

    • dzdx=dzdydydx\frac{dz}{dx}=\frac{dz}{dy}\frac{dy}{dx}

  • x=g(s)x=g(s)y=h(s)y=h(s)z=k(x,y)z=k(x,y)
    • sx,yz\nabla{s}\rightarrow\nabla{x},\nabla{y}\rightarrow\nabla{z}

    • dzds=dzdxdxds+dzdydyds\frac{dz}{ds}=\frac{dz}{dx}\frac{dx}{ds}+\frac{dz}{dy}\frac{dy}{ds}

BP算法过程

  • 给定训练集:D=((x1,y1),(x2,y2)....(xm,ym)),xRd,yRl,D=((x_1,y_1),(x_2,y_2)....(x_m,y_m)),x∈\Bbb{R}^d,y∈\Bbb{R}^l,
  • 输入:d维特征向量,(d个属性);
  • 输出:L个输出值(l维实值向量);
  • 隐层:假定使用q个隐层神经元;
  • 输出层权重:wijw_{ij};隐层权重:vijv_{ij};输出层阈值:θiθ_i;隐层阈值:γiγ_i
  • 隐层输入ah=i=1dwhjxia_h=\sum^{d}_{i=1}{w_{hj}x_i}
  • 输出层输入βj=h=1qwhjbh\beta_j=\sum^{q}_{h=1}{w_{hj}b_h}
  • 隐层第h个神经元输出:bh;
  • 假定功能单元均使用Sigmoid函数 。

神经网络变量和符号

  • wjklw_{jk}^lw代表权重,l代表层数,k代表第l-1层的神经元编号,j代表第l层神经元编号

前馈传播

  • 对训练(xk,yk)(x_k,y_k)

  • P11=f1(w111x1+w121x2)P_{1}^1=f_1(w_{11}^1x_1+w_{12}^1x_2)

  • P21=f2(w211x1+w221x2)P_{2}^1=f_2(w_{21}^1x_1+w_{22}^1x_2)

  • P31=f3(w311x1+w321x2)P_{3}^1=f_3(w_{31}^1x_1+w_{32}^1x_2)

  • P12=f4(w112P11+w121P21+w132P31)P_{1}^2=f_4(w_{11}^2P_{1}^1+w_{12}^1P_{2}^1+w_{13}^2P_{3}^1)

  • P22=f5(w212P11+w221P21+w232P31)P_{2}^2=f_5(w_{21}^2P_{1}^1+w_{22}^1P_{2}^1+w_{23}^2P_{3}^1)

  • 输出为:y=f6(w113P12+w123P22)y=f6(w_{11}^3P_1^2+w_{12}^3P_2^2)

  • 矩阵形式:

zk×1l+1=wk×jl+1aj×1l+bk×1l+1z^{l+1}_{k\times 1}=w^{l+1}_{k\times j}\cdot a^{l}_{j\times 1}+b^{l+1}_{k\times 1}

ak×1l+1=σ(zk×1l+1)a^{l+1}_{k\times 1}=\sigma(z^{l+1}_{k\times 1})

反向传播

  • 则网络在(xk,yk)(x_k,y_k)的均方误差为Ek=12j=1l(y^jkyjk)2E_k=\frac{1}{2}\sum^{l}_{j=1}{(\hat{y}^k_j-y^k_j)^2},未知的参数包括隐层及输出层权值、阈值。

  • BP通过迭代学习,在每一轮采用广义的感知机学习规划对参数进行更新估计:vv+vv\leftarrow v+\triangle v

  • BP算法基于梯度下降策略(gradient descent),以目标负梯度方向对参数进行调整。对于误差Ek,给定学习率:η(0,1)\eta \in(0,1),控制迭代中的更新步长,太大容易震荡,太小则收敛过慢。其中wθ与vγ的学习率不一定相等。

  • 更新权重公式为:w113=w+w=w+ηyw113w_{11}^3=w+\triangle w=w+\eta -\frac{y}{w_{11}^3},将偏差反向传播,计算主要任务就是求解偏导。

  • 损失函数为J(θ)J(\theta),用于计算偏差

  • Jw113=Jyyw113\frac{\partial{J}}{\partial w_{11}^3}=\frac{\partial J}{\partial y}\cdot\frac{\partial y}{\partial w_{11}^3}

  • Jw123=Jyyw123\frac{\partial{J}}{\partial w_{12}^3}=\frac{\partial J}{\partial y}\cdot\frac{\partial y}{\partial w_{12}^3}

Jw232=JyyP22P22w232\frac{\partial J}{\partial w_{23}^2}=\frac{\partial J}{\partial y}\frac{\partial y}{\partial P_2^2}\frac{\partial P_2^2}{\partial w_{23}^2}

  • 其余的推导类似,利用链式法则将每个神经元的求导值、输入值都记录下来,使用动态规划的思想,可以使更新权重计算大大加快。

  • 矩阵形式
    误差项-输出层:$$\sigma^l_j=\frac{\partial C}{\partial z_j^l}=\frac{\partial C}{\partial a_j^l}\cdot\frac{\partial a_j^l}{\partial z_jl}=\triangledown_aC\odot\sigma’(z^l)$$

误差项-中间层:$$\sigma^l_j=\frac{\partial C}{\partial z_j^l}=\sum_k{\frac{\partial C}{\partial z_k^{l+1}}\cdot\frac{\partial z_k^{l+1}}{\partial z_k^l}}=\sum_k{\frac{\partial C}{\partial z_k^{l+1}}\cdot\frac{\partial z_k^{l+1}}{\partial a_j^l}\cdot\frac{\partial a_j^l}{\partial z_kl}}=(w{l+1}{j\times k})^T\odot \sigma’(z^l){j\times 1}$$

w矩阵:$$\frac{\partial C}{\partial w^{l+1}{kj}}=\frac{\partial C}{\partial z^{l+1}{k}}\cdot\frac{\partial z^{l+1}{k}}{\partial w{l+1}_{kj}}=\sigma{l+1}{k}\cdot\frac{\sum_j{w{l+1}_{kj}a_jl+b{l+1}_{k}}}{w{l+1}{kj}}=\sigma^{l+1}{k}\cdot a{l}_{j}=\sigma{l+1}_{k}\cdot (a{l}_{j})T$$

b矩阵:$$\frac{\partial C}{\partial b{l+1}_{k}}=\sigma{l+1}{k}\cdot\frac{\partial z^{l+1}{k}}{\partial b{l+1}_{k}}=\sigma{l+1}_{k}$$

BP算法流程

  • 算法的工作流程:

BP算法流程

导数计算

方程 求导
f(x)=xf(x)=x f(x)=1f'(x)=1
f(x)=0if  x<0  else  1f(x)=0 if\;x<0\;else\;1 f(x)=0f'(x)= 0
f(x)=sigmoid(x)=11+exf(x)=sigmoid(x)=\frac{1}{1+e^{-x}} f(x)=f(x)(1f(x))f'(x)=f(x)(1-f(x))
f(x)=relu(x)f(x)=relu(x) f(x)=0  if  x<0  else  1f'(x)=0\;if\;x<0\;else\;1
tanh(x)tanh(x) tanh(x)=1tanh(x)2tanh'(x)=1-tanh(x)^2
f(x)=softmax(x)=exij=1Jexjf(x)=softmax(x)=\frac{e^{x_i}}{\sum_{j=1}^{J}{e^{x_j}}} fi(x)xj=fi(x)(δijfj(x))\frac{\partial f_i(x)}{\partial x_j}=f_i(x)(\delta_{ij}-f_j(x))其中:δij=1  if  i==j  else  0\delta_{ij}=1\;if\;i==j\;else\;0

标准BP算法与累计BP算法

  • 主要目标:最小化训练集D上的累计误差 。前面算法更新规则是基于单个Ek推导的,也称作“标准BP算法”。若使用基于累计误差最小化的更新规则,成为累计误差逆传播算法(accumulated errror backpropagation)。两者都很常用:
算法 说明
标准BP算法 1、每次针对单个训练样例更新权值与阈值;
2、参数更新频繁,不同样例可以抵消,需要多次迭代
累计BP算法 1、其优化目标是最小化整个训练集上的累计误差;
2、读取整个训练集一遍才对参数进行更新,参数更新频率较低
  • 累计BP算法更新频率低,防止不同样例导致训练出现抵消的现象。在很多任务中,累计误差下降到一定程度后,进一步下降会非常缓慢,这是标准BP算法往往会获得较好的解,尤其当训练集非常大时效果更明显。

数据预处理

  • 均值归一化(batch normalization):随着网络的深度增加,每层特征值分布会逐渐的向激活函数的输出区间的上下两端(激活函数饱和区间)靠近,这样继续下去就会导致梯度消失。BN就是通过方法将该层特征值分布重新拉回标准正态分布,特征值将落在激活函数对于输入较为敏感的区间,输入的小变化可导致损失函数较大的变化,使得梯度变大,避免梯度消失,同时也可加快收敛。

  • 过程:input={x1,x2,x3…xn}

    1. 计算 x1-xn的均值u
    2. 计算x1-xn的方差v
    3. 每个xi=(xiu)/(sqrt(v2)+e)x_i = (x_i - u) / (sqrt(v^2)+ e) e是一个小小偏置,防止分母趋向于0.
    4. 在对结果进行scale于shift操作 xi=scalexi+shiftx_i = scale*x_i + shift
  • 第四步存在的原因是batch_normal后,数据趋向标准正态,会导致网络表达能力变差,这里加入后标准正态分布有些偏移,变得不那么标准了。这两个参数时学习而来。

  • 优点:减少梯度消失,加快了收敛过程。起到类似dropout一样的正则化能力,一定程度上防止过拟合。放宽了一定的调参要求。可以替代LRN。

  • 缺点:需要计算均值与方差,不适合动态网络或者RNN。计算均值方差依赖每批次,因此数据最好足够打乱。

模型初始化方法

  • 全零初始化 :无法进行模型训练
  • 随机初始化:使用小的随机数(高斯分布,零均值, 1e-2标准差)初始化。小网络可以,对于深度网络有问题 。网络输出数据分布的方差会随着神经元的个数而改变。
  • Xavier初始化:保证前向传播和反向传播时每一层的方差一致。根据每层的输入个数和输出个数来决定。参数随机初始化的分布范围。高斯分布的权重初始化为: 高斯分布的随机数乘上2nin+nout\frac{\sqrt{2}}{\sqrt{n_{in}+n_{out}}},nin和 nout分别表示该层输入和输出的参数(权重)个数。在tanh激活函数上有很好的效果,但不适用于ReLU激活函数。
  • He参数初始化:对Xavier方法的改进,将ReLU非线性映射造成的影响考虑进参数初始化中。高斯分布的权重初始化为: 高斯分布的随机数乘上2nin\frac{\sqrt{2}}{\sqrt{n_{in}}}
  • 一般情况下,偏置设为0
w = np.random.randn(node_num, node_num) * 1 # gauss
w = np.random.randn(node_num, node_num) * 0.01 # gauss fix mu
w = np.random.randn(node_num, node_num) * np.sqrt(1.0 / node_num) # Xavier
w = np.random.randn(node_num, node_num) * np.sqrt(2.0 / node_num) # He

超参数设定

  • 超参数包括:网络模型(结构、层数、激活函数等)、学习率、批次大小(batch size)、迭代次数 (epoch, iteration)、优化器
  • 通过交叉验证方法调整超参,将训练数据集分为:数据集+验证集,通过验证集结果来调整超参。划分方法分为:hold-out,k-fold

缓解过拟合

  • 主要策略

早停early stopping

  • 将训练数据分为训练集和验证集。训练集计算梯度和更新,验证估计误差。
    1. 若训练误差连续a轮的变化小于b,则停止训练
    2. 使用验证集:若训练误差降低,验证误差升高,则停止训练。
  • 返回具有最小验证误差的链接权重和阈值。

dropout

  • dropout可以看做是一种集成学习的方式。通过随机失活神经元,将不同网络分别训练,再进行结合。
  • 训练阶段:以概率𝑝随机移除网络中的神经元结点以及与之相连的所有输入和输出边
  • 测试阶段: 所有神经元处于激活态,但用系数(1 − 𝑝) 减少激活值来补偿训练时丢弃的激活
class Dropout:
def __init__(self, dropout_ratio=0.5):
self.dropout_ratio = dropout_ratio
self.mask = None
def forward(self, x, train_flg=True):
if train_flg: # 训练阶段
self.mask = np.random.rand(*x.shape) > self.dropout_ratio
return x * self.mask
else: # 测试阶段
return x * (1.0 - self.dropout_ratio)
def backward(self, dout):
return dout * self.mask

正则化

  • regularization在误差目标函数中,增加一项描述网络复杂度:例如连接权和阈值的平方和
  • 误差目标函数增加正则化项,用于对经验误差和网络复杂度进行折中。偏好比较小的连接权和阈值,使网络输出更“光滑”
  • l2范数正则化:J(θ)=J(θ)+λ2mw2J(\theta)=J(\theta)+\frac{\lambda}{2m}\sum{\left \| w \right \| }^2lambdalambda是正则化参数,l2正则化也叫做权重衰减
  • l1范数正则化:J(θ)=J(θ)+λ2mwJ(\theta)=J(\theta)+\frac{\lambda}{2m}\sum{\left \| w \right \| }

全局最小与局部极小

最小与极小

  • 神经网络的训练过程可看作一个参数寻优过程:在参数空间中,寻找一组最优参数使得误差最小

  • 特点:存在多个“局部极小”;只有一个“全局最小”

  • 常用策略跳出局部极小

    • 不同参数进行初始化
    • 模拟退火(simulated annealing) 以一定概率接收比当前解更差的结果,每部迭代中,接受次优解的概率随时间推移而降低。
    • 随机梯度下降 计算梯度时增加随机因素,即使陷入局部极小也有机会跳出继续搜索。
    • 遗传算法(genetic algorithms)

其他常见神经网络模型

RBF网络

  • RBF(Radial Basis Function,径向基函数)网络在分类任务中除BP之外最常用的一种

单隐层前馈神经网络

  • 使用径向基函数作为隐层神经元激活函数ρ: ,定义为样本x到数据中心ci之间欧式距离的单调函数,常用高斯径向基函数。 。ci表示隐层神经元对应的中心、wi表示权重。
  • 输出层是隐层神经元输出的线性组合

训练RBF网络:

  • 确定神经元中心ci,常用的方式包括随机采样、聚类等
  • 利用BP算法等确定参数wi和βi。

ART网络

  • ART(Adaptive Resonance Theory,自适应谐振理论)竞争学习的代表,是一种常用的无监督学习策略。该策略网络输出神经元相互竞争,每一时刻仅有一个竞争获胜的神经元被激活。其他神经元被抑制。包含比较层、识别层、识别阈值和重置模块。

SOM网络

  • SOM(Self-Organizing Map,自组织映射)网络是最常用的聚类方法之一:
    • 竞争型的无监督神经网络
    • 将高维数据映射到低维空间,并保持输入数据在高维空间的拓扑结构。即将高维空间中相似的样本点映射到网络输出层中邻近神经元
    • 每个神经元拥有一个权向量
    • 目标:为每个输出层神经元找到合适的权向量以保持拓扑结构
  • 训练
    • 网络接收输入样本后,将会确定输出层的“获胜”神经元(“胜者通吃”)
    • 获胜神经元的权向量将向当前输入样本移动

级联相关网络:“构造性”神经网络的代表

  • 构造性神经网络:将网络结构也当做学习的目标,并在训练过程中找到最符合的网络结构。是结构自适应网络的重要代表。
  • 训练
    • 开始时只有输入层和输出层
    • 级联(Cascade):新的隐层节点逐渐加入,从而创建起层级结构
    • 相关(Correlation):最大化新节点的输出与网络误差之间的相关性

Elman网络:递归神经网络的代表

  • 网络可以有环形结构,可让使一些神经元的输出反馈回来最为输入
  • t 时刻网络的输出状态: 由 t 时刻的输入状态和 t-1时刻的网络状态共同决定
  • Elman网络是最常用的递归神经网络之一
  • 结构与前馈神经网络很相似,但隐层神经元的输出被反馈回来
  • 使用推广的BP算法训练

Bolyzmann机:”基于能量的模型”的代表

深度学习

卷积神经网络CNN

深度学习

  • 每个卷积层包含多个特征映射,每个特征映射是一个由多个神经元构成的“平面”,通过一种卷积滤波器提取输入的一种特征

  • 采样层亦称“汇合层”,其作用是基于局部相关性原理进行亚采样,从而在减少数据量的同事保留有用信息

  • 连接层就是传统神经网络对隐层与输出层的全连接

  • 典型的深度学习模型就是很深层的神经网络