python实现浅层神经网络算法
- 吴恩达第三周课后编程作业
- 首先load一些需要使用的包
- 下面需要load一些测试用的函数,都是课件里自己提供的
- 浅层神经网络实现流程
- 1.先定义sigmoid函数
- 2.再定义initialize函数
- 3.forward propagate
- 4.在forward propagate后计算成本
- 5.back propagate
- 6.updata parameters
- 梳理一下上面的几个流程:
- 7.加上循环将上面梳理的流程放在一起,命名为nn_model
- 8.通过nn_model可以得到经过num_iterations重复后的最新的parameters的值,这里再用最新的参数值计算最终的y的预测值
- 9.设置predict函数,用循环最后得出的W和b计算最终的预测值y
吴恩达第三周课后编程作业
第一次开始真正意义上接触算法,并且使用python来编码,用博客来梳理自己的学习思路。
首先load一些需要使用的包
import numpy as np
import matplotlib.pyplot as plt
import sklearn
import sklearn.datasets
import sklearn.linear_model
from planar_utils import plot_decision_boundary, sigmoid, load_planar_dataset, load_extra_datasets
np.random.seed(1) ###保证随机数生成的一样
下面需要load一些测试用的函数,都是课件里自己提供的
def layer_sizes_test_case():
np.random.seed(1)
X_assess = np.random.randn(5, 3)
Y_assess = np.random.randn(2, 3)
return X_assess, Y_assess
def initialize_parameters_test_case():
n_x, n_h, n_y = 2, 4, 1
return n_x, n_h, n_y
def forward_propagation_test_case():
np.random.seed(1)
X_assess = np.random.randn(2, 3)
parameters = {'W1': np.array([[-0.00416758, -0.00056267],
[-0.02136196, 0.01640271],
[-0.01793436, -0.00841747],
[ 0.00502881, -0.01245288]]),
'W2': np.array([[-0.01057952, -0.00909008, 0.00551454, 0.02292208]]),
'b1': np.array([[ 0.],
[ 0.],
[ 0.],
[ 0.]]),
'b2': np.array([[ 0.]])}
return X_assess, parameters
def compute_cost_test_case():
np.random.seed(1)
Y_assess = np.random.randn(1, 3)
parameters = {'W1': np.array([[-0.00416758, -0.00056267],
[-0.02136196, 0.01640271],
[-0.01793436, -0.00841747],
[ 0.00502881, -0.01245288]]),
'W2': np.array([[-0.01057952, -0.00909008, 0.00551454, 0.02292208]]),
'b1': np.array([[ 0.],
[ 0.],
[ 0.],
[ 0.]]),
'b2': np.array([[ 0.]])}
a2 = (np.array([[ 0.5002307 , 0.49985831, 0.50023963]]))
return a2, Y_assess, parameters
def backward_propagation_test_case():
np.random.seed(1)
X_assess = np.random.randn(2, 3)
Y_assess = np.random.randn(1, 3)
parameters = {'W1': np.array([[-0.00416758, -0.00056267],
[-0.02136196, 0.01640271],
[-0.01793436, -0.00841747],
[ 0.00502881, -0.01245288]]),
'W2': np.array([[-0.01057952, -0.00909008, 0.00551454, 0.02292208]]),
'b1': np.array([[ 0.],
[ 0.],
[ 0.],
[ 0.]]),
'b2': np.array([[ 0.]])}
cache = {'A1': np.array([[-0.00616578, 0.0020626 , 0.00349619],
[-0.05225116, 0.02725659, -0.02646251],
[-0.02009721, 0.0036869 , 0.02883756],
[ 0.02152675, -0.01385234, 0.02599885]]),
'A2': np.array([[ 0.5002307 , 0.49985831, 0.50023963]]),
'Z1': np.array([[-0.00616586, 0.0020626 , 0.0034962 ],
[-0.05229879, 0.02726335, -0.02646869],
[-0.02009991, 0.00368692, 0.02884556],
[ 0.02153007, -0.01385322, 0.02600471]]),
'Z2': np.array([[ 0.00092281, -0.00056678, 0.00095853]])}
return parameters, cache, X_assess, Y_assess
def update_parameters_test_case():
parameters = {'W1': np.array([[-0.00615039, 0.0169021 ],
[-0.02311792, 0.03137121],
[-0.0169217 , -0.01752545],
[ 0.00935436, -0.05018221]]),
'W2': np.array([[-0.0104319 , -0.04019007, 0.01607211, 0.04440255]]),
'b1': np.array([[ -8.97523455e-07],
[ 8.15562092e-06],
[ 6.04810633e-07],
[ -2.54560700e-06]]),
'b2': np.array([[ 9.14954378e-05]])}
grads = {'dW1': np.array([[ 0.00023322, -0.00205423],
[ 0.00082222, -0.00700776],
[-0.00031831, 0.0028636 ],
[-0.00092857, 0.00809933]]),
'dW2': np.array([[ -1.75740039e-05, 3.70231337e-03, -1.25683095e-03,
-2.55715317e-03]]),
'db1': np.array([[ 1.05570087e-07],
[ -3.81814487e-06],
[ -1.90155145e-07],
[ 5.46467802e-07]]),
'db2': np.array([[ -1.08923140e-05]])}
return parameters, grads
def nn_model_test_case():
np.random.seed(1)
X_assess = np.random.randn(2, 3)
Y_assess = np.random.randn(1, 3)
return X_assess, Y_assess
def predict_test_case():
np.random.seed(1)
X_assess = np.random.randn(2, 3)
parameters = {'W1': np.array([[-0.00615039, 0.0169021 ],
[-0.02311792, 0.03137121],
[-0.0169217 , -0.01752545],
[ 0.00935436, -0.05018221]]),
'W2': np.array([[-0.0104319 , -0.04019007, 0.01607211, 0.04440255]]),
'b1': np.array([[ -8.97523455e-07],
[ 8.15562092e-06],
[ 6.04810633e-07],
[ -2.54560700e-06]]),
'b2': np.array([[ 9.14954378e-05]])}
return parameters, X_assess
浅层神经网络实现流程
1.先定义sigmoid函数
def sigmoid(z):
A = 1/(1+np.exp(-z))
return A
2.再定义initialize函数
def initialize_with_zeros(X,y,n_h):
n_0, n_1, n_2 = X.shape[0],n_h,y.shape[0] ###这里是
W1 = np.random.randn(n_1,n_0)
b1 = np.zeros((n_1,1))
W2 = np.random.randn(n_2,n_1)
b2 = np.zeros((n_2,1))
params = {
'W1':W1,
'b1':b1,
'W2':W2,
'b2':b2
}
return params
犯过的错:
- n_0, n_1, n_2 是根据X和y的shape[0]定义的,shape[0]代表的特征值的数量。
- 这里np.zeros(()) 中间规定b1和b2的格式时需要再在中间加一个括号
- 这里最后加上一个n_h 是为了以后设定不同的隐藏层的值来画一组图
3.forward propagate
def forward_propagate(X,params):
W1 = params['W1']
b1 = params['b1']
W2 = params['W2']
b2 = params['b2']
A1 = np.tanh(np.dot(W1,X)+b1)
A2 = sigmoid(np.dot(W2,A1)+b2)
assert(A2.shape == (1,X.shape[-1]))
cache = {
'A1':A1,
'A2':A2
}
return cache
注意:最后决定W1和W2就不采取转置的模式了。
4.在forward propagate后计算成本
def compute_cost(y,cache):
m = y.shape[-1]
A2 = cache['A2']
cost = (-1/m)*np.sum((y*np.log(A2) + (1-y)*np.log(1-A2)))
cost = np.float(np.squeeze(cost))
return cost
犯过的错
(y*np.log(A2) + (1-y)*np.log(1-A2)) 这里是(1,m)乘(1,m)不是向量内积,最后得出来也是(1,m)的结果。所以最后需要用np.sum进行加和,并且用np.squeeze保证最后是一个实数。
5.back propagate
def backward_propagate(X,y,params,cache):
m = y.shape[-1]
W1=params['W1']
W2=params['W2']
A1=cache['A1']
A2=cache['A2']
dZ2 = A2-y
dW2 = (1/m)*np.dot(dZ2,A1.T) ##dw2是直接在w2上减的 所以就是(1,4)
db2 = (1/m)*np.sum(dZ2,axis = 1,keepdims=True)
dZ1 = np.multiply(np.dot(W2.T,dZ2),(1-np.power(A1,2))) ##这里这个公式记住(4,4)
dW1 = (1/m)*np.dot(dZ1,X.T)
db1 = (1/m)*np.sum(dZ1,axis = 1,keepdims=True)
assert(dW2.shape == (y.shape[0],n_h))
assert(dW1.shape == (n_h,X.shape[0]))
grads = {
'dW2':dW2,
'db2':db2,
'dW1':dW1,
'db1':db1
}
return grads
这里dZ1的计算公式要记牢:
用向量的代码形式就是下面:
dZ1 = np.multiply(np.dot(W2.T,dZ2),g`(Z1))
dW2的格式为(1,4)……(n_y,n_h)
db2的格式为(1,1)……(n_y,1)
dW1的格式为(4,3)……(n_h,n_x)
db1的格式为(4,1)….(n_h,1)
这里b1和b2的列数为1,因为每个训练对象的b相同,可以利用python中的broadcast来加到每个训练集上。
6.updata parameters
def update_parameters(params,grads,learning_rate = 1.2):
W1=params['W1']
b1=params['b1']
W2=params['W2']
b2=params['b2']
dW1 = grads['dW1']
db1 = grads['db1']
dW2 = grads['dW2']
db2 = grads['db2']
W1 = W1 - learning_rate*dW1
b1 = b1 - learning_rate*db1
W2 = W2 - learning_rate*dW2
b2 = b2 - learning_rate*db2
parameters ={
'W1':W1,
'b1':b1,
'W2':W2,
'b2':b2
}
return parameters
梳理一下上面的几个流程:
- 初始化w1,b1,w2,b2
- forward propagate计算A1和A2,A2也就是浅层神经网络中的y的预测值。
- 计算本次forward propagate的cost
- backward propagate计算dw1,db1,dw2,db2
- 更新参数得到新的w1,b1,w2,b2
- 回到第2步,开始新的forward propagate
7.加上循环将上面梳理的流程放在一起,命名为nn_model
def nn_model(X,y,num_iterations,print_cost=False):
params = initialize_with_zeros(X,y)
for i in range(num_iterations):
cache = foward_propagate(X,params)
cost = compute_cost(y,cache)
grads = backward_propagate(X,y,params,cache)
params = update_parameters(params,grads,learning_rate = 0.05)
if(print_cost) and i%1000 == 0:
print("第 ",i," 次循环,成本为:"+str(cost))
return params
8.通过nn_model可以得到经过num_iterations重复后的最新的parameters的值,这里再用最新的参数值计算最终的y的预测值
def predict(X,parameters):
cache = forward_propagate(X,parameters)
A2 = cache['A2']
y_predictions = np.round(A2)
return y_predictions
这里np.round的作用就是将大于0.5的预测值记录为1,小于0.5的预测值记录为0
9.设置predict函数,用循环最后得出的W和b计算最终的预测值y
def predict(X,parameters):
cache = forward_propagate(X,parameters)
A2 = cache['A2']
y_predictions = np.round(A2)
return y_predictions
以上便是浅层神经网络构建的全部代码,下面对模型进行测试:
parameters = nn_model(X,Y,4,5000,print_cost=True)
plot_decision_boundary(lambda x: predict(x.T, parameters),X, np.squeeze(Y))
plt.title("Decision Boundary for hidden layer size " + str(4))
predictions = predict(X, parameters)
print ('准确率: %d' % float((np.dot(Y, predictions.T) + np.dot(1 - Y, 1 - predictions.T)) / float(Y.size) * 100) + '%')
第 0 次循环,成本为:1.3228871944341336
第 1000 次循环,成本为:0.29683168219859646
第 2000 次循环,成本为:0.28305492191379644
第 3000 次循环,成本为:0.2761861074786332
第 4000 次循环,成本为:0.2713672098405463
准确率: 88%
下面改变n_h的值:
plt.figure(figsize=(16, 32))
hidden_layer_sizes = [1, 2, 3, 4, 5, 20, 50] #隐藏层数量
for i, n_h in enumerate(hidden_layer_sizes):
plt.subplot(5, 2, i + 1)
plt.title('Hidden Layer of size %d' % n_h)
parameters = nn_model(X, Y, n_h, num_iterations=10000)
plot_decision_boundary(lambda x: predict(x.T, parameters), X, np.squeeze(Y))
predictions = predict(X, parameters)
accuracy = float((np.dot(Y, predictions.T) + np.dot(1 - Y, 1 - predictions.T)) / float(Y.size) * 100)
print ("隐藏层的节点数量: {} ,准确率: {} %".format(n_h, accuracy))
隐藏层的节点数量: 1 ,准确率: 66.0 %
隐藏层的节点数量: 2 ,准确率: 64.75 %
隐藏层的节点数量: 3 ,准确率: 90.75 %
隐藏层的节点数量: 4 ,准确率: 90.75 %
隐藏层的节点数量: 5 ,准确率: 90.5 %
隐藏层的节点数量: 20 ,准确率: 90.5 %
隐藏层的节点数量: 50 ,准确率: 91.5 %