深度学习3:手动实现L2正则化(L2 Regularization)
2017-12-15 19:27
459 查看
在神经网络中,正则化的作用是防止过拟合,本文将结合一个实例来讲解神经网络中的L2正则化,并手动(不使用框架)实现出来。
先来看代码运行结果:
增加L2正则化之前
增加L2正则化之后:
L2正则化为:λ2 m ||W|| 2 , 其中λ 是超参数, m是一个batch中数据个数, 除以2的原因是在求导的时候抵消掉。
这个神经网络有两个输入节点和一个输出节点。该模型可以完成简单的二分类功能。其中,增加L2正则化之后,前向传播的公式不变,代价函数和backward propogation需要修改。
原本的cost函数由:
J=−1m ∑ i=1 m (y (i) log(a [L](i) )+(1−y (i) )log(1−a [L](i) )) (1)
变成:
J regularized =−1m ∑ i=1 m (y (i) log(a [L](i) )+(1−y (i) )log(1−a [L](i) )) cross-entropy cost +1m λ2 ∑ l ∑ k ∑ j W [l]2 k,j L2 regularization cost (2)
其中,∑ k ∑ j W [l]2 k,j 表示第l 层W参数的和,实际上W [l] k,j 是一个矩阵,k和j表示该矩阵的行和列。所以,在python中可以使用下面代码求解
对于backward propogation, 原本的公式为:
变为(其他的公式不变):
dW [2] =1m dZ [2] A [1] .T+λm W [2]
dW [1] =1m dZ [1] X [1] .T+λm W [1]
对应的,我们知道该网络模型的前向传播公式为:
z [1](i) =W [1] x (i) +b [1](i) (1)
a [1](i) =tanh(z [1](i) ) (2)
z [2](i) =W [2] a [1](i) +b [2](i) (3)
y ^ (i) =a [2](i) =σ(z [2](i) ) (4)
y (i) prediction ={10 if a [2](i) >0.5otherwise (5)
现在就可以实现L2正则化了。因为L2正则化是在上面的模型上面增加进去了,所以,我们先来看一下在没有正则化的情况下如何实现上图所示的神经网络模型。
1. 生成模型训练数据:
代价函数
增加L2正则化之后变为:
3.
反向传播
增加正则化之后变为:
只需要改变dW2和dW1, 对cost表达式求偏导数之后,只有这两项的偏导数才有W2或者W1.
其他的地方跟没有增加L2正则化是一样的。下面是完整的代码:
先来看代码运行结果:
增加L2正则化之前
增加L2正则化之后:
L2正则化为:λ2 m ||W|| 2 , 其中λ 是超参数, m是一个batch中数据个数, 除以2的原因是在求导的时候抵消掉。
这个神经网络有两个输入节点和一个输出节点。该模型可以完成简单的二分类功能。其中,增加L2正则化之后,前向传播的公式不变,代价函数和backward propogation需要修改。
原本的cost函数由:
J=−1m ∑ i=1 m (y (i) log(a [L](i) )+(1−y (i) )log(1−a [L](i) )) (1)
变成:
J regularized =−1m ∑ i=1 m (y (i) log(a [L](i) )+(1−y (i) )log(1−a [L](i) )) cross-entropy cost +1m λ2 ∑ l ∑ k ∑ j W [l]2 k,j L2 regularization cost (2)
其中,∑ k ∑ j W [l]2 k,j 表示第l 层W参数的和,实际上W [l] k,j 是一个矩阵,k和j表示该矩阵的行和列。所以,在python中可以使用下面代码求解
np.sum(np.square(Wl))
对于backward propogation, 原本的公式为:
变为(其他的公式不变):
dW [2] =1m dZ [2] A [1] .T+λm W [2]
dW [1] =1m dZ [1] X [1] .T+λm W [1]
对应的,我们知道该网络模型的前向传播公式为:
z [1](i) =W [1] x (i) +b [1](i) (1)
a [1](i) =tanh(z [1](i) ) (2)
z [2](i) =W [2] a [1](i) +b [2](i) (3)
y ^ (i) =a [2](i) =σ(z [2](i) ) (4)
y (i) prediction ={10 if a [2](i) >0.5otherwise (5)
现在就可以实现L2正则化了。因为L2正则化是在上面的模型上面增加进去了,所以,我们先来看一下在没有正则化的情况下如何实现上图所示的神经网络模型。
1. 生成模型训练数据:
def get_case_data(example_num = 200): """ 获取点数据,需要进一步处理 :param example_num: 点的个数 :return: """ np.random.seed(6) X, y = sklearn.datasets.make_moons(example_num, noise=0.30) return X, y;
代价函数
def cost_compute(A2, Y, parameters, lambd): m = Y.shape[1] W1 = parameters['W1'] W2 = parameters['W2']; loss = Y * np.log(A2) + (1-Y)*np.log(1-A2+10**(-10)) cost1 = -np.sum(loss)/m return cost1
增加L2正则化之后变为:
def cost_compute(A2, Y, parameters, lambd): m = Y.shape[1] W1 = parameters['W1'] W2 = parameters['W2']; loss = Y * np.log(A2) + (1-Y)*np.log(1-A2+10**(-10)) cost1 = -np.sum(loss)/m l2_regularization_cost = lambd*(np.sum(np.square(W1)) + np.sum(np.square(W2)))/m/2 return cost1 + l2_regularization_cost
3.
反向传播
def backward_propagate(X, Y, parameters, cache, lambd): W1 = parameters['W1'] b1 = parameters['b1'] W2 = parameters['W2'] b2 = parameters['b2'] A1 = cache['A1'] Z1 = cache['Z1'] A2 = cache['A2'] m = Y.shape[1] dZ2 = A2 - Y dW2 = np.dot(dZ2, A1.T)/m db2 = np.sum(dZ2, axis=1, keepdims=True)/m dZ1 = np.multiply(np.dot(W2.T, dZ2), 1-np.power(A1, 2)) dW1 = np.dot(dZ1, X.T)/m db1 = np.sum(dZ1, axis=1, keepdims=True)/m W1 -= dW1 b1 -= db1 W2 -= dW2 b2 -= db2 return {'W1': W1, 'b1': b1, 'W2': W2, 'b2': b2}
增加正则化之后变为:
def backward_propagate(X, Y, parameters, cache, lambd): W1 = parameters['W1'] b1 = parameters['b1'] W2 = parameters['W2'] b2 = parameters['b2'] A1 = cache['A1'] Z1 = cache['Z1'] A2 = cache['A2'] m = Y.shape[1] dZ2 = A2 - Y dW2 = np.dot(dZ2, A1.T)/m + lambd / m * W2 db2 = np.sum(dZ2, axis=1, keepdims=True)/m dZ1 = np.multiply(np.dot(W2.T, dZ2), 1-np.power(A1, 2)) dW1 = np.dot(dZ1, X.T)/m + lambd / m * W1 db1 = np.sum(dZ1, axis=1, keepdims=True)/m W1 -= dW1 b1 -= db1 W2 -= dW2 b2 -= db2 return {'W1': W1, 'b1': b1, 'W2': W2, 'b2': b2}
只需要改变dW2和dW1, 对cost表达式求偏导数之后,只有这两项的偏导数才有W2或者W1.
其他的地方跟没有增加L2正则化是一样的。下面是完整的代码:
完整的代码
# encoding=utf8
import matplotlib.pyplot as plt
import numpy as np
import sklearn
import sklearn.datasets
import sklearn.linear_model
import matplotlib
learning_rate = 0.05
input_node_num = 2;
hidden_node_num = 8;
output_node_num = 1;
example_num = 200; # 输入数据点的个数
epoch_num = 30000; #迭代次数
# lambd = 0.001 # L2 正则化参数
lambd = 0.01 # L2 正则化参数
def get_case_data(example_num = 200): """ 获取点数据,需要进一步处理 :param example_num: 点的个数 :return: """ np.random.seed(6) X, y = sklearn.datasets.make_moons(example_num, noise=0.30) return X, y;
def process_data(X, Y):
"""
处理原始数据集
:param X:
:param Y: label
:return:
"""
Y = np.reshape(Y, (1, -1))
return X.T, Y;
def random_mini_batches(X, Y, batch_size=32):
"""
:param X:
:param Y:
:param batch_size:
:return:
"""
m = Y.shape[1]
permutation = np.random.permutation(Y.shape[1])
X_shuffle = X[:, permutation]
Y_shuffle = Y[:, permutation]
mini_batches = []
batch_num = m//batch_size
for i in range(batch_num):
mini_batch_x = X_shuffle[:, i * batch_size: (i + 1) * batch_size]
mini_batch_y = Y_shuffle[:, i * batch_size: (i + 1) * batch_size]
mini_batch = (mini_batch_x, mini_batch_y)
mini_batches.append(mini_batch)
if batch_num * batch_size < m:
mini_batch_x = X_shuffle[:, batch_num * batch_size: m]
mini_batch_y = Y_shuffle[:, batch_num * batch_size: m]
mini_batch = [mini_batch_x, mini_batch_y]
mini_batches.append(mini_batch)
mini_batches = np.array(mini_batches)
return mini_batches
def initialize_parameters():
"""
初始化参数
:return:
"""
W1 = np.random.randn(hidden_node_num, input_node_num) * 0.01;
b1 = np.zeros((hidden_node_num, 1))
W2 = np.random.randn(output_node_num, hidden_node_num) * 0.01;
b2 = np.zeros((output_node_num, 1))
assert (W1.shape == (hidden_node_num, input_node_num))
assert (b1.shape == (hidden_node_num, 1))
assert (W2.shape == (output_node_num, hidden_node_num))
assert (b2.shape == (output_node_num, 1))
return {'W1': W1, 'b1': b1, 'W2': W2, 'b2': b2}
def sigmoid(x):
s = 1 / (1 + (np.exp(-x)))
return s;
def forward_propagate(X, parameters):
W1 = parameters['W1']
b1 = parameters['b1']
W2 = parameters['W2']
b2 = parameters['b2']
z1 = np.dot(W1, X) + b1
a1 = np.tanh(z1)
z2 = np.dot(W2, a1) + b2
a2 = sigmoid(z2)
cache = {'A1':a1, 'Z1':z1, 'A2':a2, 'Z2':z2}
return cache
def cost_compute(A2, Y, parameters, lambd): m = Y.shape[1] W1 = parameters['W1'] W2 = parameters['W2']; loss = Y * np.log(A2) + (1-Y)*np.log(1-A2+10**(-10)) cost1 = -np.sum(loss)/m l2_regularization_cost = lambd*(np.sum(np.square(W1)) + np.sum(np.square(W2)))/m/2 return cost1 + l2_regularization_cost
def backward_propagate(X, Y, parameters, cache, lambd): W1 = parameters['W1'] b1 = parameters['b1'] W2 = parameters['W2'] b2 = parameters['b2'] A1 = cache['A1'] Z1 = cache['Z1'] A2 = cache['A2'] m = Y.shape[1] dZ2 = A2 - Y dW2 = np.dot(dZ2, A1.T)/m + lambd / m * W2 db2 = np.sum(dZ2, axis=1, keepdims=True)/m dZ1 = np.multiply(np.dot(W2.T, dZ2), 1-np.power(A1, 2)) dW1 = np.dot(dZ1, X.T)/m + lambd / m * W1 db1 = np.sum(dZ1, axis=1, keepdims=True)/m W1 -= dW1 b1 -= db1 W2 -= dW2 b2 -= db2 return {'W1': W1, 'b1': b1, 'W2': W2, 'b2': b2}
def do_predict(X, parameters):
cache = forward_propagate(X, parameters)
return np.around(cache['A2'])
def build_model():
X_original, Y_original = get_case_data(example_num)
X, Y = process_data(X_original, Y_original)
assert (Y.shape == (1, example_num))
assert (X.shape == (2, example_num))
parameters = initialize_parameters()
for i in range(epoch_num):
mini_batches = random_mini_batches(X, Y)
for j in range(mini_batches.shape[0]):
x_mini_batch, y_mini_batch = mini_batches[j]
cache = forward_propagate(x_mini_batch, parameters=parameters)
A2 = cache['A2']
cost = cost_compute(A2, y_mini_batch, parameters, lambd)
parameters = backward_propagate(x_mini_batch, y_mini_batch, parameters, cache, lambd)
if i % 300 == 0:
print(cost)
def predict(X):
return do_predict(X.T, parameters)
matplotlib.rcParams['figure.figsize'] = (5.0, 4.0)
plot_decision_boundary(X_original, Y_original, lambda x: predict(x))
# plt.scatter(X_original[:, 0], X_original[:, 1], c=Y_original, s=20, cmap=plt.cm.Spectral)
plt.title("model")
plt.show()
def plot_decision_boundary(X, y, pred_func):
"""
可视化结果
:param X:
:param y:
:param pred_func: 模型的predict函数
"""
# Set min and max values and give it some padding
x_min, x_max = X[:, 0].min() - .5, X[:, 0].max() + .5
y_min, y_max = X[:, 1].min() - .5, X[:, 1].max() + .5
h = 0.01
# Generate a grid of points with distance h between them
xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
# Predict the function value for the whole gid
Z = pred_func(np.c_[xx.ravel(), yy.ravel()])#
Z = np.reshape(Z, xx.shape)
# Plot the contour and training examples
plt.contourf(xx, yy, Z, cmap=plt.cm.Spectral)
plt.scatter(X[:, 0], X[:, 1], c=y, s=20, cmap=plt.cm.Spectral)
build_model()
总结:
L2正则化是常用的避免模型过拟合的方法。通过在代价函数中增加了λ2 m ||W|| 2 ,所以,在反向传播求导的时候需要做适当的修改。相关文章推荐
- 深度学习: Regularization (网络正则化)
- (Python实现)数据PCA降维白化和L2归一化-深度学习实践常用数据预处理
- Coursera deeplearning.ai 深度学习笔记2-1-Practical aspects of deep learning-神经网络实际问题分析(初始化&正则化&训练效率)与代码实现
- 【深度学习】L1正则化和L2正则化
- 深度学习--通过正则化regularization防止overfitting
- 深度学习:正则化(L2、dropout)
- 【深度学习理论】正则化方法:L1、L2、数据扩增、Dropout
- 神经网络与深度学习学习笔记:L2正则化
- [DeeplearningAI笔记]改善深层神经网络1.4_1.8深度学习实用层面_正则化Regularization与改善过拟合
- MXNet动手学深度学习笔记:Gluon实现正则化
- 深度学习-L1 Regularization、L2 Regularization、Dropout和人工扩大训练集减少Overfitting
- 一文搞懂深度学习正则化的L2范数
- 简洁常用权限系统的设计与实现(五):不维护节点的深度level,手动计算level,构造树
- 安卓学习记录之五(手动创建Activity,实现页面跳转)
- 深度学习及并行化实现概述
- 决策树学习(下)——ID3、C4.5、CART深度剖析及源码实现
- ufldl 深度学习入门 第一发:基于BP网络实现稀疏自编码器
- 正则化方法:L1和L2 regularization、数据集扩增、dropout
- Spring2.5学习3.3_@Autowire注解实现手动装配
- 决策树学习(上)——深度原理剖析及源码实现