欢迎来到第三周的编程作业。现在是构建第一个神经网络的时候了,它有一个隐藏层。您将看到此模型与使用逻辑回归实现的模型之间的巨大差异。
您将学习如何:
实现一个只有一个隐藏层的2分类神经网络使用具有非线性激活函数的单元,如tanh计算交叉熵损失实现向前和向后传播
本文作业是在jupyternotebook上一步一步做的,带有一些过程中查找的资料等(出处已标明)并翻译成了中文,如有错误,欢迎指正!
让我们首先导入在此任务中需要的所有包。
numpy是使用Python进行科学计算的基本包。sklearn为数据挖掘和数据分析提供了简单而高效的工具。matplotlib是Python中用于绘制图形的库。testcase提供了一些测试示例来评估函数的正确性planar_utils提供了在这个赋值中使用的各种有用的函数
#Packageimportsimportnumpyasnpimportmatplotlib.pyplotaspltfromtestCasesimport*importsklearnimportsklearn.datasetsimportsklearn.linear_modelfromplanar_utilsimportplot_decision_boundary,sigmoid,load_planar_dataset,load_extra_datasets%matplotlibinline#这行代码是由于在jupyter上运行才要的#可以将matplotlib的图表直接嵌入到Notebook之中,或者使用指定的界面库显示图表,它有一个参数指定matplotlib图表的显示方式。inline表示将图表嵌入到Notebook中#有了%matplotlibinline就可以省掉plt.show()了
np.random.seed(1)#setaseedsothattheresultsareconsistentpython中我们常会用到numpy.random.seed()函数。其基本用法或作用网上很多人都写过:
seed()用于指定随机数生成时所用算法开始的整数值,如果使用相同的seed()值,则每次生成的随即数都相同
First,let'sgetthedatasetyouwillworkon.Thefollowingcodewillloada"flower"2-classdatasetintovariablesXandY.
首先,让我们获得要处理的数据集。下面的代码将把一个“flower”2分类数据集加载到变量X和Y中。
可以看到向量X是2X400就是2行400列,而Y是1X400就是1行400列
使用matplotlib可视化数据集。数据看起来像一朵“花”,有一些红色(标签y=0)和一些蓝色(y=1)点。您的目标是构建一个模型来匹配这些数据。
#Visualizethedata:plt.scatter(X[0,:],X[1,:],c=Y,s=40,cmap=plt.cm.Spectral);(由于使用JupyterNotebook在这周作业出现问题,运行不通过)问题如下:
1、数据可视化
#plt.scatter(X[0,:],X[1,:],c=Y,s=40,cmap=plt.cm.Spectral)plt.scatter(X[0,:],X[1,:],c=np.squeeze(Y),*s=40,cmap=plt.cm.Spectral)这里进行数据可视化的时候,纯用c=Y会出错,出错原因及解决方法如下:在机器学习和深度学习中,通常算法的结果是可以表示向量的数组(即包含两对或以上的方括号形式[[]]),如果直接利用这个数组进行画图可能显示界面为空(见后面的示例)。我们可以利用squeeze()函数将表示向量的数组转换为秩为1的数组,这样利用matplotlib库函数画图时,就可以正常的显示结果了。
2、关于plot_decision_boundar函数这里主要也是要注意里面的参数,Y的部分要变成np.squeeze(Y)
更改代码后:
这里X[0,:]为第一行的所有数,X[1,:]为第二行的所有数
你有:一个包含你的特征(x1,x2)的数字数组(矩阵)X一个包含标签(红色:0,蓝色:1)的数字数组(向量)Y。
这里m=shape_X[1]#trainingsetsize,1是代表横轴的方向,所以有400个训练样本
在建立一个完整的神经网络之前,让我们先看看逻辑回归在这个问题上的表现。您可以使用sklearn的内置函数来实现这一点。运行下面的代码来训练数据集上的逻辑回归分类器。
#Trainthelogisticregressionclassifierclf=sklearn.linear_model.LogisticRegressionCV();clf.fit(X.T,Y.T);注意上面的代码的Y也是需要转换为秩为1的数字:
#Trainthelogisticregressionclassifierclf=sklearn.linear_model.LogisticRegressionCV();clf.fit(X.T,np.squeeze(Y).T);看到还有一种:
现在可以绘制这些模型的决策边界。运行下面的代码。
绘制逻辑回归的决策边界是不是就是红蓝的分解线呢?
float((np.dot(Y,LR_predictions)+np.dot(1-Y,1-LR_predictions))/float(Y.size)*100)
到这里代码有些看不懂,plot_decision_boundary,这是一个函数吗?从最上面导入的情况来看是从属于planar_utils这个文件的,这个文件写了4个函数,如下
解释:首先Y.size是400,因为Y是1X400的一个行向量,
可以看到逻辑回归分类准确率很低,无法正确分类。
解释:数据集不是线性可分的,所以logistic回归的效果不是很好。希望神经网络能做得更好。我们现在就来试试!
逻辑回归在“花数据集”上效果不佳。你要训练一个只有一个隐含层的神经网络。
Hereisourmodel:
数学上的:
对于一个样本的xi:
根据对所有例子的预测,您还可以计算代价J如下:
提醒:构建神经网络的一般方法是:
1.定义神经网络结构(输入单元,隐藏单元,等等)。2.初始化模型的参数3.循环:实现正向传播计算损失实现反向传播,以获得梯度更新参数(梯度下降)
您经常构建辅助函数来计算步骤1-3,然后将它们合并到一个称为nn_model()的函数中。一旦构建了nn_model()并学习了正确的参数,就可以对新数据进行预测。
练习:定义三个变量:
-n_x:输入层的大小-n_h:隐藏层的大小(设置为4)-n_y:输出层的大小
提示:使用X和Y的形状来查找n_x和n_y。同时,将隐藏层的大小硬编码为4。
#GRADEDFUNCTION:layer_sizesdeflayer_sizes(X,Y):"""Arguments:X--inputdatasetofshape(inputsize,numberofexamples)Y--labelsofshape(outputsize,numberofexamples)Returns:n_x--thesizeoftheinputlayern_h--thesizeofthehiddenlayern_y--thesizeoftheoutputlayer"""###STARTCODEHERE###(≈3linesofcode)n_x=X.shape[0]#sizeofinputlayerX是2X400,2是不是就是2个特征,红和蓝其中为1n_h=4n_y=Y.shape[0]#sizeofoutputlayerY是1X400###ENDCODEHERE###return(n_x,n_h,n_y)X_assess,Y_assess=layer_sizes_test_case()(n_x,n_h,n_y)=layer_sizes(X_assess,Y_assess)print("Thesizeoftheinputlayeris:n_x="+str(n_x))print("Thesizeofthehiddenlayeris:n_h="+str(n_h))print("Thesizeoftheoutputlayeris:n_y="+str(n_y))结果:
Thesizeoftheinputlayeris:n_x=5Thesizeofthehiddenlayeris:n_h=4Thesizeoftheoutputlayeris:n_y=2预期输出(这不是您将用于网络的大小,它们只是用于评估您刚刚编写的函数)。
练习:实现函数initialize_parameters()。
说明:
确保参数大小正确。如有需要,请参考上面的神经网络图。您将用随机值初始化权重矩阵。
使用:np.random.randn(a,b)*0.01随机初始化一个矩阵的形状(a,b)。将偏差向量初始化为零。
使用:np.zeros((a,b))来初始化一个矩阵的形状与0(a,b)。
Question:Implementforward_propagation().(问题:实现forward_propagation()。)
看看上面的分类器的数学表示。可以使用函数sigmoid()。它是内置(导入)在笔记本电脑。可以使用函数np.tanh()。它是numpy库的一部分。你必须执行的步骤是:
反向传播所需的值存储在“缓存”中。缓存将作为反向传播函数的输入。
向前传播:
现在你已经算出了A【2】(在Python中是变量“A2”),其中对于每个样本都包含了一个a【2】(i),你可以计算成本函数如下:
练习:实现compute_cost()来计算代价J的值
说明:有很多方法可以实现交叉熵损失。为了帮助你,我们告诉你我们将如何实施:
logprobs=np.multiply(np.log(A2),Y)
cost=-np.sum(logprobs)#noneedtouseaforloop!
(youcanuseeithernp.multiply()andthennp.sum()ordirectlynp.dot()).
使用前向传播期间计算的缓存,现在可以实现后向传播。
问题:实现函数backward_propagation()。
说明:反向传播通常是深度学习中最难的部分。为了帮助你们,这里有一张关于反向传播的幻灯片。您需要使用这张幻灯片右边的六个方程,因为您正在构建一个向量化的实现。
提示:
问题:实现更新规则。用梯度下降法。为了更新(W1、b1、W2、b2),必须使用(dW1、db1、dW2、db2)。
说明:学习率好的梯度下降算法(收敛)和坏的学习率(发散)。图片由亚当·哈雷提供。
问题:在nn_model()构建你的神经网络模型。
说明:神经网络模型必须按照正确的顺序使用前面的函数。
问题:通过构建predict()来使用您的模型进行预测。使用正向传播来预测结果。
例如,如果您想根据阈值将矩阵X的项设置为0和1,您可以这样做:X_new=(X>阈值)
#GRADEDFUNCTION:predictdefpredict(parameters,X):"""Usingthelearnedparameters,predictsaclassforeachexampleinXArguments:parameters--pythondictionarycontainingyourparametersX--inputdataofsize(n_x,m)Returnspredictions--vectorofpredictionsofourmodel(red:0/blue:1)"""#Computesprobabilitiesusingforwardpropagation,andclassifiesto0/1using0.5asthethreshold.###STARTCODEHERE###(≈2linesofcode)A2,cache=forward_propagation(X,parameters)#A2就是yhatpredictions=np.round(A2)#round()方法返回浮点数x的四舍五入值。###ENDCODEHERE###returnpredictionsparameters,X_assess=predict_test_case()predictions=predict(parameters,X_assess)print("predictionsmean="+str(np.mean(predictions)))结果:
现在是时候运行模型,看看它在平面数据集上的表现如何。运行下面的代码,用一个隐藏层来测试您的模型,nh隐藏的单位。
#Buildamodelwithan_h-dimensionalhiddenlayerparameters=nn_model(X,Y,n_h=4,num_iterations=10000,print_cost=True)#这里n_h=4是隐藏层的神经元个数哦#Plotthedecisionboundaryplot_decision_boundary(lambdax:predict(parameters,x.T),X,Y)plt.title("DecisionBoundaryforhiddenlayersize"+str(4))结果:
#Printaccuracypredictions=predict(parameters,X)print('Accuracy:%d'%float((np.dot(Y,predictions.T)+np.dot(1-Y,1-predictions.T))/float(Y.size)*100)+'%')结果:
与逻辑回归相比,它的准确性真的很高。模特学会了花的叶子图案!与逻辑回归不同,神经网络能够学习甚至高度非线性的决策边界。现在,让我们尝试几种隐藏图层大小。
运行以下代码。可能需要1-2分钟。您将观察不同隐藏层大小的模型的不同行为。
#Thismaytakeabout2minutestorunplt.figure(figsize=(16,32))hidden_layer_sizes=[1,2,3,4,5,10,20]fori,n_hinenumerate(hidden_layer_sizes):plt.subplot(5,2,i+1)plt.title('HiddenLayerofsize%d'%n_h)parameters=nn_model(X,Y,n_h,num_iterations=5000)plot_decision_boundary(lambdax: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("Accuracyfor{}hiddenunits:{}%".format(n_h,accuracy))结果:
解释:
较大的模型(隐藏单元更多)能够更好地拟合训练集,直到最终最大的模型对数据进行过拟合。最好的隐藏层大小似乎是在n_h=5左右。实际上,这里的值似乎很适合数据,而不会引起明显的过拟合。稍后您还将学习正则化,它可以让您使用非常大的模型(如n_h=50)而不会过度拟合。
可选的问题:
注意:记得提交作业,但点击右上角的蓝色“提交作业”按钮。
一些可选的/未评分的问题,你可以探索,如果你愿意:
将tanh激活改为sigmoid激活或ReLU激活会发生什么玩学习率。会发生什么呢如果我们改变数据集会怎么样(参见下面的第5部分!)
**你已经学会:**-建立一个完整的带有隐含层的神经网络-充分利用非线性单元-实现前向传播和后向传播,训练一个神经网络-看看改变隐含层大小的影响,包括过拟合。
干得漂亮!!!
如果需要,可以为以下每个数据集重新运行整个笔记本(减去数据集部分)。
#Datasetsnoisy_circles,noisy_moons,blobs,gaussian_quantiles,no_structure=load_extra_datasets()datasets={"noisy_circles":noisy_circles,"noisy_moons":noisy_moons,"blobs":blobs,"gaussian_quantiles":gaussian_quantiles}###STARTCODEHERE###(chooseyourdataset)dataset="gaussian_quantiles"###ENDCODEHERE###X,Y=datasets[dataset]X,Y=X.T,Y.reshape(1,Y.shape[0])#makeblobsbinaryifdataset=="blobs":Y=Y%2#Visualizethedataplt.scatter(X[0,:],X[1,:],c=np.squeeze(Y),s=40,cmap=plt.cm.Spectral);