实现具有单个隐藏层的2分类神经网络
使用具有非线性激活函数的神经元,例如tanh
一些笔记
在吴老师下一周的课程中有对前向传播和反向传播求导的结论,如图所示:
写作业
导入常用的包和老师提供的工具集
import numpy as np
import sklearn
import matplotlib.pyplot as plt
from planar_utils import plot_decision_boundary, load_planar_dataset,sigmoid,load_extra_datasets
%matplotlib inline
获取数据
X, Y = load_planar_dataset()
plt.scatter(X[0, :], X[1, :], c=Y.reshape(X[0,:].shape), s=40, cmap=plt.cm.Spectral)
测试逻辑回归能否实现该分类
使用sklearn内置函数执行该操作(说实话没看懂这个,没有学过这个函数,www)
clf = sklearn.linear_model.LogisticRegressionCV();
clf.fit(X.T, Y.T);
plot_decision_boundary(lambda x: clf.predict(x), X, Y)
plt.title("Logistic Regression")
LR_predictions = clf.predict(X.T)
print ('Accuracy of logistic regression: %d ' % float((np.dot(Y,LR_predictions) + np.dot(1-Y,1-LR_predictions))/float(Y.size)*100) +
'% ' + "(percentage of correctly labelled datapoints)")
由于数据集线性不可分,所以逻辑回归效果不佳,接下来使用神经网络进行测试
使用的神经网络模型
建立神经网络的一般方法是: 1、定义神经网络结构 2、初始化模型参数 3、循环:前向传播、损失函数、bp求导、梯度下降
通常构建函数来实现1-3步,之后将它们合并为model()函数
定义神经网络结构
- n_x:输入层的大小
- n_h_1:第一个隐藏层的大小(这里只有一个隐藏层,将其设置为4)
- n_y:输出层的大小
def layer_sizes(X,Y):
n_x=X.shape[0]
n_h_1=4
n_y=Y.shape[0]
return (n_x,n_h_1,n_y)
测试该函数
(n_x, n_h_1, n_y) = layer_sizes(X.T, Y.T)
print(n_x, n_h_1, n_y)
初始化模型参数
通过上面的笔记可以看出
X大小为(n_x,m),W1大小为(n_h_1,n_x),b_1大小为(n_h,1),Z1大小为(n_h_1,m),A1同Z1 W2大小为(n_y,n_h_1),b_2大小为(n_y,1),Z2大小为(n_y,m),A2同Z1同Y
权重矩阵不能跟线性回归一样设置为0,需要进步随机初始化,否则每层中不同神经元对应的Z都是一样的
使用随机值初始化权重矩阵。
- 使用:np.random.randn(a,b)* 0.01随机初始化维度为(a,b)的矩阵。
将偏差向量初始化为零。
- 使用:np.zeros((a,b)) 初始化维度为(a,b)零的矩阵。
def initialize_parameters(n_x, n_h, n_y):
np.random.seed(2)
W1 = np.random.randn(n_h,n_x) * 0.01
b1 = np.zeros((n_h,1))
W2 = np.random.randn(n_y,n_h) * 0.01
b2 = np.zeros((n_y,1))
parameters = {"W1": W1,
"b1": b1,
"W2": W2,
"b2": b2}
return parameters
循环梯度下降
首先实现前向传播,前向传播矩阵化见上面笔记
def forward_propagation(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 = {"Z1": Z1,
"A1": A1,
"Z2": Z2,
"A2": A2}
return A2, cache
实现代价函数的计算: 代价函数矩阵化见作业1
def compute_cost(A2, Y, parameters):
m = Y.shape[1]
logprobs = Y*np.log(A2) + (1-Y)* np.log(1-A2)
cost = -1/m * np.sum(logprobs)
cost = np.squeeze(cost)
return cost
实现反向传播,反向传播导数推导过程见笔记2:
def backward_propagation(parameters, cache, X, Y):
m = X.shape[1]
W1 = parameters["W1"]
W2 = parameters["W2"]
A1 = cache["A1"]
A2 = cache["A2"]
dZ2= A2 - Y
dW2 = 1 / m * np.dot(dZ2,A1.T)
db2 = 1 / m * np.sum(dZ2,axis=1,keepdims=True)
dZ1 = np.dot(W2.T,dZ2) * (1-np.power(A1,2))
dW1 = 1 / m * np.dot(dZ1,X.T)
db1 = 1 / m * np.sum(dZ1,axis=1,keepdims=True)
grads = {"dW1": dW1,
"db1": db1,
"dW2": dW2,
"db2": db2}
return grads
实现梯度下降函数:
def update_parameters(parameters, grads, learning_rate = 1.2):
W1 = parameters["W1"]
b1 = parameters["b1"]
W2 = parameters["W2"]
b2 = parameters["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
将上述函数集成到model中
def model(X,Y,n_h_1,n_iter=10000,print_cost=False):
np.random.seed(3)
n_x = layer_sizes(X, Y)[0]
n_y = layer_sizes(X, Y)[2]
parameters = initialize_parameters(n_x, n_h_1, n_y)
W1 = parameters["W1"]
b1 = parameters["b1"]
W2 = parameters["W2"]
b2 = parameters["b2"]
for i in range(0, n_iter):
A2, cache = forward_propagation(X, parameters)
cost = compute_cost(A2, Y, parameters)
grads = backward_propagation(parameters, cache, X, Y)
parameters = update_parameters(parameters, grads)
if print_cost and i % 1000 == 0:
print ("Cost after iteration %i: %f" %(i, cost))
return parameters
通过上述模型来预测结果
def predict(parameters, X):
A2, cache = forward_propagation(X, parameters)
predictions = np.round(A2)
return predictions
parameters = model(X, Y, n_h_1 = 4, n_iter = 10000, print_cost=True)
plot_decision_boundary(lambda x: predict(parameters, x.T), X, Y)
plt.title("Decision Boundary for hidden layer size " + str(4))
看准确率
predictions = predict(parameters, X)
print ('Accuracy: %d' % float((np.dot(Y,predictions.T) + np.dot(1-Y,1-predictions.T))/float(Y.size)*100) + '%')
调整隐藏层的大小看结果
plt.figure(figsize=(16, 32))
hidden_layer_sizes = [1, 2, 3, 4, 5, 10, 20]
for i, n_h_1 in enumerate(hidden_layer_sizes):
plt.subplot(5, 2, i+1)
plt.title('Hidden Layer of size %d' % n_h_1)
parameters = model(X, Y, n_h_1, n_iter = 5000)
plot_decision_boundary(lambda x: predict(parameters, x.T), X, Y)
predictions = predict(parameters, X)
accuracy = float((np.dot(Y,predictions.T) + np.dot(1-Y,1-predictions.T))/float(Y.size)*100)
print ("Accuracy for {} hidden units: {} %".format(n_h_1, accuracy))
aaa
只能说自己还是太菜,如果没有网上的笔记的话,可能写不出来,已经有些思路了,大致的模型搭建已经搞懂了,就是写不出来,有的函数想自己写,但是总是没有大佬写的简洁,加油啊。。。 补补微积分和线性代数,多推导,多实践。
|