其实在讲解神经网络之前课程还有两项内容,一个是损失函数的最优化,一个是反向传播。但是个人认为这两点理解起来都比较容易——当然,你得先有一定的数学基础——所以在这里我只对这两项内容进行简单的介绍,不做详细的解释或者公式的推导。
——————————————————以下为正文——————————————————
最优化:寻找使loss最小的W参数
我们有以下几种方法:
1.随机搜索:随机为W赋值,取最优
2.随机本地搜索:从一个随机W开始,然后生成一个随机的扰动
,只有当
的损失值变低,才会更新
3.跟随梯度
梯度计算的代码实现:
def eval_numerical_gradient(f, x):
fx = f(x)
grad = np.zeros(x.shape)
h = 0.00001
# 对x中所有的索引进行迭代
it = np.nditer(x, flags=['multi_index'], op_flags=['readwrite'])
while not it.finished:
ix = it.multi_index
old_value = x[ix]
x[ix] = old_value + h
fxh = f(x)
x[ix] = old_value
# 计算偏导数
grad[ix] = (fxh - fx) / h
it.iternext() # 到下个维度
return grad
梯度下降:计算梯度并对参数进行更新
1.普通版
while True:
weights_grad = evaluate_gradient(loss_fun, data, weights)
weights += - step_size * weights_grad
2.小批量数据梯度下降:取大量数据集中的一部分数据做训练
例如取256个数据作为一个小批量:
while True:
data_batch = sample_training_data(data, 256) # 256个数据
weights_grad = evaluate_gradient(loss_fun, data_batch, weights)
weights += - step_size * weights_grad
随机梯度下降(SGD)是小批量数据梯度下降的极端情况:每个批量只有一个数据样本。
反向传播(BP)
反向传播其实就是求导的链式法则的应用,比较简单,这里我就不说了
神经网络
神经网络的向前传播:
class Neuron(object):
def forward(inputs):
cell_body_sum = np.sum(inputs * self.weights) + self.bias
firing_rate = 1.0 / (1.0 + math.exp(-cell_body_sum)) # sigmoid激活函数
return firing_rate
卷积层(convolution)
详细可见我之前的博客
注意:
1,卷积核也叫滤波层
2,处理之后的尺寸为:
,N为输入图片的尺寸,F为卷积核的尺寸,
为步长
池化层(pooling)
常见为最大池化层:即用最大值替代
池化层的作用:降采样,使参数更少
注意:
1,通常设置的步长使得移动时不会重叠
2,为什么最大池化好于均值池化?
因为最大值可代表卷积核在该区域的受激程度,用最大值激活
激活函数
1.sigmoid
表达式:
特点:将每个元素都压缩到[0,1]中
劣势:
1,当x特别大或者特别小的时候,位于函数的平滑区域,达到饱和,梯度消失(斜率为0)
2,函数不是以0为中心的函数,要么全为正要么全为负,梯度更新沿一个方向
3,含有指数函数,计算代价大
tanh(x)
表达式:
特点:将数据压缩到[-1,1]; 当数据的特征明显时效果好
劣势:饱和时梯度消失
ReLU
表达式:
特点:计算快,收敛速度快
劣势:
1,不是以0为中心的函数
2,梯度容易挂:某些神经元可能永远都不会激活,导致相应的参数永远都不会更新,挂的原因:参数初始化不合适或者学习率太大
Leaky ReLU
针对ReLU的这些劣势,做出了一些改变于是有了Leaky ReLU函数
表达式:
ELU
劣势:
1,存在饱和,梯度消失
2,存在指数函数,计算代价大
Maxout
表达式:
特点:是ReLU和Leaky ReLU的一个泛化
劣势:每个神经元的参数翻倍