因为此部分在之前的博文中提及,所以不再详细赘述其中原理,代码只展示核心部分。
激活函数在神经网络中具有重要的地位,常见的激活函数有sigmoid、tanh、ReLU(修正线性单元)和Leaky ReLU等。前两种是饱和激活函数、后两种则是非饱和激活函数,它可以解决“梯度消失”的问题并加快收敛速度。
以一个隐藏层为例,神经网络的梯度下降法公式及其代码向量化如下:
使用逻辑回归构建分类器,可以看出其表现不佳,未对两种数据很好地分类。
浅层神经网络
建立只有一个隐藏层的神经网络模型。
def nn_model(X, Y, n_h, num_iterations=10000, print_cost=False):
np.random.seed(3)
# 给出输入层大小,隐藏层大小,输出层大小
n_x, n_h, n_y = layer_sizes(X, Y)
# 随机初始化参数
parameters = initialize_parameters(n_x, n_h, n_y)
# 分离各个W和b参数
W1 = parameters['W1']
b1 = parameters['b1']
W2 = parameters['W2']
b2 = parameters['b2']
# 迭代进行梯度下降
for i in range(0, num_iterations):
# 前向传播,输出最终结果和中间计算数据
A2, cache = forward_propagation(X, parameters)
# 计算成本
cost = compute_cost(A2, Y, parameters)
# 反向传播,输出梯度
grads = backward_propagation(parameters, cache, X, Y)
# 更新梯度,输出各层的W和b参数,待下一次循环使用
parameters = update_parameters(parameters, grads)
# 打印成本
if print_cost and i % 1000 == 0:
print("Cost after iteration %i: %f" % (i, cost))
return parameters
从下图的输出可以看出,神经网络的准确度要远高于逻辑回归,它能够学习高度非线性的决策边界。
深层神经网络
深层神经网络用来拟合复杂的函数模型,多层神经网络模型代码如下:
def L_layer_model(X, Y, layers_dims, learning_rate=0.0075, num_iterations=3000, print_cost=False):
np.random.seed(1)
costs = []
# 参数初始化,初始化各层的W和b
parameters = initialize_parameters_deep(layers_dims)
# 梯度下降法迭代
for i in range(0, num_iterations):
# 前向传播: [LINEAR -> RELU]*(L-1) -> LINEAR -> SIGMOID.
AL, caches = L_model_forward(X, parameters)
# 计算成本
cost = compute_cost(AL, Y)
# 反向传播
grads = L_model_backward(AL, Y, caches)
# 更新参数(各层的W和b)
parameters = update_parameters(parameters, grads, learning_rate)
# 打印成本
if print_cost and i % 100 == 0:
print("Cost after iteration %i: %f" % (i, cost))
if print_cost and i % 100 == 0:
costs.append(cost)
# 绘制成本变化图
plt.plot(np.squeeze(costs))
plt.ylabel('cost')
plt.xlabel('iterations (per tens)')
plt.title("Learning rate =" + str(learning_rate))
plt.show()
return parameters
首次输出的结果图像如上图所示,可以看出遇到了梯度消失的问题。查资料后得知,深层神经网络的模型初始化不能像浅层网络那样,需要对权重W的选取进行一定修改,一个解决方法是从区间均匀随机取值。
def initialize_parameters_deep(layer_dims):
np.random.seed(3)
parameters = {}
L = len(layer_dims)
for l in range(1, L):
parameters['W' + str(l)] = np.random.randn(layer_dims[l], layer_dims[l-1]) / np.sqrt(layer_dims[l-1]) # 原语句:np.random.randn(layer_dims[l], layer_dims[l-1]) * 0.01
parameters['b' + str(l)] = np.zeros((layer_dims[l], 1))
return parameters
经过修改后可以看出,成本函数下降明显稳定了许多。
参考资料: 深度学习权重参数初始化要点