最近在学习吴恩达老师深度学习的课程,实现了单隐藏层神经网络的实现,现在将自己在编程过程中遇到的问题记录下。
先将需要用到文件的分享
链接:https://pan.baidu.com/s/148VvXV-SWW-PrFS7mVK_oA 密码:rkk7
导入需要的库
import numpy as np
#Python绘制图形的库
import matplotlib.pyplot as plt
#testCases提供了一些测试示例来评估函数的正确性
from testCases import *
# sklearn为数据挖掘和数据分析提供了简单而有效的工具。
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)
对于每一个库的作用,我都加以解释了。需要注意的是我们添加了一个np.random.seed(1)种子,添加这句话的目的以及使用方法,可以参考我上一篇博客,这里不再赘述。
2.导入数据集以及可视化数据集
#获取要处理的数据集
X , Y=load_planar_dataset()
print(X.shape,Y.shape)
#可视化数据集
plt.scatter(X[0,:],X[1,:],c=np.squeeze(Y),s=40,cmap=plt.cm.Spectral)
shape_X=X.shape
shape_Y=Y.shape
m=shape_X[1]
在这里要注意,吴恩达老师在下面这段代码中c=Y,这是不正确的,应该改成c=np.squeeze(Y)
plt.scatter(X[0,:],X[1,:],c=np.squeeze(Y),s=40,cmap=plt.cm.Spectral)
数据导入好之后,我们可以直接用sklearn内置的函数检查线性回归在数据集上的表现
clf = sklearn.linear_model.LogisticRegressionCV()
clf.fit(X.T, Y.T)
plot_decision_boundary(lambda x: clf.predict(x), X,Y.ravel())
plt.title("Logistic Regression")
plt.show()
# Print accuracy
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)")
在这里同时需要注意,不然会有bug出现。
plot_decision_boundary(lambda x: clf.predict(x), X,Y.ravel())
我们来看一下这段代码,如果我们按照吴恩达老师给的讲解中直接使用
plot_decision_boundary(lambda x: clf.predict(x), X,Y)
会发现有警告,图像也画不出来,我们根据警告的提示修改代码,至于为什么要这么修改,我暂时的理解是因为这个函数的参数的限定,如果以后深入学习了发现有理解不对的,再回来修改。同时呢,我一开始直接用
Y=Y.ravel()
这样会导致Y的维数发生改变,会导致后面使用模型时输入的参数不匹配,导致出错。当然你也可以这样修改,不过在使用模型时记得reshape一下Y的维度。
我们可以看出效果是非常不好的。所以我们要考虑使用其他的模型,接下来就让我们一起实现第一个单隐藏层的神经网络模型吧。
首先我们定义神经网络结构
def layer_sizes(X,Y):
n_x=X.shape[0]
n_h=4
n_y=Y.shape[0]
return (n_x,n_h,n_y)
为了便于理解,我来说明一下语句含义,n_x:输入单元;n_h=4:隐藏层大小;n_y:输出单元。
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))
assert (W1.shape == (n_h,n_x))
assert (b1.shape == (n_h,1))
assert (W2.shape == (n_y,n_h))
assert (b2.shape == (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)
assert (A2.shape == (1,X.shape[1]))
cache = {"Z1":Z1,
"A1":A1,
"Z2":Z2,
"A2":A2}
return A2,cache
对于如何实现正向传播,吴恩达老师的视频中也已经做了详细的说明,可以参照视频中的讲解。
def computer_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)
assert (isinstance(cost,float))
return cost
A2, Y_assess, parameters = compute_cost_test_case()
print("cost = " + str(computer_cost(A2, Y_assess, parameters)))
在这里需要理解的就是cost = np.squeeze(cost)
,为了实现降维,因为我们cost想要的是一个数值。
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
def nn_model(X,Y,n_h,num_iterations = 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,n_y)
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 = computer_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, X_assess = predict_test_case()
predictions = predict(parameters, X_assess)
print("predictions mean = " + str(np.mean(predictions)))
#单隐藏层
parameters = nn_model(X,Y, n_h = 4, num_iterations = 10000, print_cost=True)
plot_decision_boundary(lambda x: predict(parameters, x.T), X, Y.ravel())
plt.title("Decision Boundary for hidden layer size " + str(4))
plt.show()
predictions=predict(parameters,X)
print("Accuracy:%d" % float((np.dot(Y,predictions.T)+np.dot(1-Y,1-predictions.T))/float(Y.size)*100)+"%")
我们可以看到效果是非常好的,准确率达到了90%
他作业中还比对了不同隐藏层大小对模型效果的影响,当隐藏层过多时就会出现过拟合,代码如下:
plt.figure(figsize=(16, 32))
hidden_layer_sizes = [1, 2, 3, 4, 5, 10, 20]
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 = 5000)
plot_decision_boundary(lambda x: predict(parameters, x.T), X, Y.ravel())
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, accuracy))
plt.show()
综上就是我在完成课后作业过程中遇到的一些问题以及代码分享。初学深度学习,多有理解误差,欢迎指正。