吴恩达深度学习 第一课第三周课后编程作业

 

一个隐含层的平面数据分类

2020-07-21

欢迎来到第三周的编程作业。现在是构建第一个神经网络的时候了,它有一个隐藏层。您将看到此模型与使用逻辑回归实现的模型之间的巨大差异

您将学习如何:

•实现一个只有一个隐藏层的2分类神经网络
•使用具有非线性激活函数的单元,如tanh
•计算交叉熵损失
•实现向前和向后传播

本文作业是在jupyter notebook上一步一步做的,带有一些过程中查找的资料等(出处已标明)并翻译成了中文,如有错误,欢迎指正!


 

1 - Packages(包)

让我们首先导入在此任务中需要的所有包。

numpy是使用Python进行科学计算的基本包。
•sklearn为数据挖掘数据分析提供了简单而高效的工具。
matplotlib是Python中用于绘制图形的库
testcase提供了一些测试示例来评估函数的正确性
planar_utils提供了在这个赋值中使用的各种有用的函数

# Package imports
import numpy as np
import matplotlib.pyplot as plt
from testCases import *
import sklearn
import sklearn.datasets
import sklearn.linear_model
from planar_utils import plot_decision_boundary, sigmoid, load_planar_dataset, load_extra_datasets

%matplotlib inline #这行代码是由于在jupyter上运行才要的
#可以将matplotlib的图表直接嵌入到Notebook之中,或者使用指定的界面库显示图表,它有一个参数指定matplotlib图表的显示方式。inline表示将图表嵌入到Notebook中
#有了%matplotlib inline 就可以省掉plt.show()了

 


np.random.seed(1) # set a seed so that the results are consistent

python中我们常会用到numpy.random.seed()函数。
其基本用法或作用网上很多人都写过:

seed( ) 用于指定随机数生成时所用算法开始的整数值,如果使用相同的seed( )值,则每次生成的随即数都相同

关于numpy.random.seed()的参数说明 


 

2 - Dataset(数据集)

First, let's get the dataset you will work on. The following code will load a "flower" 2-class dataset into variables X and Y.

首先,让我们获得要处理的数据集。下面的代码将把一个“flower”2分类 数据集加载到变量X和Y中。

X, Y = load_planar_dataset()

 

 

 可以看到向量X是2X400就是2行400列,而Y是1X400就是1行400列

 

使用matplotlib可视化数据集。数据看起来像一朵“花”,有一些红色(标签y=0)和一些蓝色(y=1)点。您的目标是构建一个模型匹配这些数据

# Visualize the data:
plt.scatter(X[0, :], X[1, :], c=Y, s=40, cmap=plt.cm.Spectral);

(由于使用Jupyter Notebook在这周作业出现问题,运行不通过)问题如下:

 

 

 

 

 

 

 

 

参考了来自Miss思的吴恩达深度学习——第一课第三周课后编程作业Debug经历,链接:https://blog.csdn.net/weixin_43978140/article/details/85012675

以下转自:https://blog.csdn.net/weixin_43978140/article/details/85012675

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)

 

更改代码后:

# Visualize the data:
plt.scatter(X[0, :], X[1, :], c= np.squeeze(Y), s=40, cmap=plt.cm.Spectral);

 

 

(plt.scatter( ) 函数的使用方法), 来自:

matplotlib.pyplot.scatter(x, y, s=None, c=None, marker=None, cmap=None, norm=None, vmin=None, vmax=None, alpha=None, linewidths=None, verts=None, edgecolors=None, *, data=None, **kwargs)
plt.scatter()
参数的解释:

x,y:表示的是大小为(n,)的数组,也就是我们即将绘制散点图的数据点

s:是一个实数或者是一个数组大小为(n,),这个是一个可选的参数。

c:表示的是颜色,也是一个可选项。默认是蓝色'b',表示的是标记的颜色,或者可以是一个表示颜色的字符,或者是一个长度为n的表示颜色的序列等等,感觉还没用到过现在不解释了。但是c不可以是一个单独的RGB数字,也不可以是一个RGBA的序列。可以是他们的2维数组(只有一行)。

marker:表示的是标记的样式,默认的是'o'。

cmap:Colormap实体或者是一个colormap的名字,cmap仅仅当c是一个浮点数数组的时候才使用。如果没有申明就是image.cmap

norm:Normalize实体来将数据亮度转化到0-1之间,也是只有c是一个浮点数的数组的时候才使用。如果没有申明,就是默认为colors.Normalize。

vmin,vmax:实数,当norm存在的时候忽略。用来进行亮度数据的归一化。

alpha:实数,0-1之间。

linewidths:也就是标记点的长度。
plt.scatter参数说明

 

python中 x[:,0]和x[:,1] 理解和实例解析,来自

这里X[0, :]为第一行的所有数,X[1, :]为第二行的所有数

 你有:
一个包含你的特征(x1, x2)的数字数组(矩阵)X
一个包含标签(红色:0,蓝色:1)的数字数组(向量)Y。


首先让我们更好地了解我们的数据是什么样的。
练习:你有多少训练例子?另外,变量X和Y的形状是什么?
提示:如何得到一个numpy数组的形状?(帮助)

 

### START CODE HERE ### (≈ 3 lines of code)
shape_X = X.shape
shape_Y = Y.shape
m = shape_X[1]  # training set size
### END CODE HERE ###

print ('The shape of X is: ' + str(shape_X))
print ('The shape of Y is: ' + str(shape_Y))
print ('I have m = %d training examples!' % (m))

 

 

 这里m = shape_X[1] # training set size,1是代表横轴的方向,所以有400个训练样本

 


 

3 - Simple Logistic Regression(简单逻辑回归)

在建立一个完整的神经网络之前,让我们先看看逻辑回归在这个问题上的表现。您可以使用sklearn的内置函数来实现这一点。运行下面的代码来训练数据集上的逻辑回归分类器

# Train the logistic regression classifier
clf = sklearn.linear_model.LogisticRegressionCV();
clf.fit(X.T, Y.T);

注意上面的代码的Y也是需要转换为秩为1的数字:

# Train the logistic regression classifier
clf = sklearn.linear_model.LogisticRegressionCV();
clf.fit(X.T, np.squeeze(Y).T);

看到还有一种:

# Train the logistic regression classifier
clf = sklearn.linear_model.LogisticRegressionCV();
clf.fit(X.T, Y.T.ravel());#将多维数组降位一维

  numpy中的ravel()、flatten()、squeeze()的用法与区别 - 草稿,来自:爱学习的大丁

  fit()训练。调用fit(x,y)的方法来训练模型,其中x为数据的属性,y为所属类型。来自:静悟生慧LogisticRegression回归算法 Sklearn 参数详解

  sklearn逻辑回归(Logistic Regression,LR)类库使用小结,来自 :原文出处:http://www.cnblogs.com/pinard/p/6035872.html,在原文的基础上做了一些修订

  clf.fit需要转置,clf.fit填入数据进行训练

现在可以绘制这些模型的决策边界。运行下面的代码。

# Plot the decision boundary for logistic regression 绘制逻辑回归的决策边界
plot_decision_boundary(lambda x: clf.predict(x), X, Y)
plt.title("Logistic Regression")

# Print accuracy 打印精度
LR_predictions = clf.predict(X.T) #得到预测值Y_hat,标签
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)")

 

 

 

 绘制逻辑回归的决策边界是不是就是红蓝的分解线呢?

float((np.dot(Y,LR_predictions) + np.dot(1-Y,1-LR_predictions))/float(Y.size)*100)

到这里代码有些看不懂,plot_decision_boundary,这是一个函数吗?从最上面导入的情况来看是从属于planar_utils这个文件的,这个文件写了4个函数,如下

 1 import matplotlib.pyplot as plt
 2 import numpy as np
 3 import sklearn
 4 import sklearn.datasets
 5 import sklearn.linear_model
 6 
 7 def plot_decision_boundary(model, X, y):
 8     # Set min and max values and give it some padding
 9     x_min, x_max = X[0, :].min() - 1, X[0, :].max() + 1
10     y_min, y_max = X[1, :].min() - 1, X[1, :].max() + 1
11     h = 0.01
12     # Generate a grid of points with distance h between them
13     xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
14     # Predict the function value for the whole grid
15     Z = model(np.c_[xx.ravel(), yy.ravel()])
16     Z = Z.reshape(xx.shape)
17     # Plot the contour and training examples
18     plt.contourf(xx, yy, Z, cmap=plt.cm.Spectral)
19     plt.ylabel('x2')
20     plt.xlabel('x1')
21     plt.scatter(X[0, :], X[1, :], c=np.squeeze(y), cmap=plt.cm.Spectral)
22     
23 
24 def sigmoid(x):
25     """
26     Compute the sigmoid of x
27 
28     Arguments:
29     x -- A scalar or numpy array of any size.
30 
31     Return:
32     s -- sigmoid(x)
33     """
34     s = 1/(1+np.exp(-x))
35     return s
36 
37 def load_planar_dataset():
38     np.random.seed(1)
39     m = 400 # number of examples
40     N = int(m/2) # number of points per class
41     D = 2 # dimensionality
42     X = np.zeros((m,D)) # data matrix where each row is a single example
43     Y = np.zeros((m,1), dtype='uint8') # labels vector (0 for red, 1 for blue)
44     a = 4 # maximum ray of the flower
45 
46     for j in range(2):
47         ix = range(N*j,N*(j+1))
48         t = np.linspace(j*3.12,(j+1)*3.12,N) + np.random.randn(N)*0.2 # theta
49         r = a*np.sin(4*t) + np.random.randn(N)*0.2 # radius
50         X[ix] = np.c_[r*np.sin(t), r*np.cos(t)]
51         Y[ix] = j
52         
53     X = X.T
54     Y = Y.T
55 
56     return X, Y
57 
58 def load_extra_datasets():  
59     N = 200
60     noisy_circles = sklearn.datasets.make_circles(n_samples=N, factor=.5, noise=.3)
61     noisy_moons = sklearn.datasets.make_moons(n_samples=N, noise=.2)
62     blobs = sklearn.datasets.make_blobs(n_samples=N, random_state=5, n_features=2, centers=6)
63     gaussian_quantiles = sklearn.datasets.make_gaussian_quantiles(mean=None, cov=0.5, n_samples=N, n_features=2, n_classes=2, shuffle=True, random_state=None)
64     no_structure = np.random.rand(N, 2), np.random.rand(N, 2)
65     
66     return noisy_circles, noisy_moons, blobs, gaussian_quantiles, no_structure
planar_utils

 

解释:首先Y.size是400,因为Y是1X400的一个行向量,

 

可以看到逻辑回归分类准确率很低,无法正确分类。

解释:数据集不是线性可分的,所以logistic回归的效果不是很好。希望神经网络能做得更好。我们现在就来试试!


 

4 - Neural Network model

逻辑回归在“花数据集”上效果不佳。你要训练一个只有一个隐含层的神经网络

Here is our model:

 

 

 

数学上的:

对于一个样本的xi

 

 

 根据对所有例子的预测,您还可以计算代价J如下:

 

 

 提醒:构建神经网络的一般方法是:

1. 定义神经网络结构(输入单元,隐藏单元,等等)。
2. 初始化模型的参数
3.循环:
  实现正向传播
  计算损失
  实现反向传播,以获得梯度
  更新参数(梯度下降)

您经常构建辅助函数来计算步骤1-3,然后将它们合并到一个称为nn_model()的函数中。一旦构建了nn_model()并学习了正确的参数,就可以对新数据进行预测

 


 

4.1 -定义神经网络结构

练习:定义三个变量:

- n_x:输入层的大小
- n_h:隐藏层的大小(设置为4)
- n_y:输出层的大小

提示:使用X和Y的形状来查找n_x和n_y。同时,将隐藏层的大小硬编码为4。

# GRADED FUNCTION: layer_sizes

def layer_sizes(X, Y):
    """
    Arguments:
    X -- input dataset of shape (input size, number of examples)
    Y -- labels of shape (output size, number of examples)
    
    Returns:
    n_x -- the size of the input layer
    n_h -- the size of the hidden layer
    n_y -- the size of the output layer
    """
    ### START CODE HERE ### (≈ 3 lines of code)
    n_x = X.shape[0] # size of input layer X是2X400,2是不是就是2个特征,红和蓝其中为1
    n_h = 4
    n_y = Y.shape[0] # size of output layer Y是1X400
    ### END CODE HERE ###
    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("The size of the input layer is: n_x = " + str(n_x))
print("The size of the hidden layer is: n_h = " + str(n_h))
print("The size of the output layer is: n_y = " + str(n_y))

结果:

The size of the input layer is: n_x = 5
The size of the hidden layer is: n_h = 4
The size of the output layer is: n_y = 2

预期输出(这不是您将用于网络的大小,它们只是用于评估您刚刚编写的函数)。

 


 

4.2 - Initialize the model's parameters(初始化模型的参数)

练习:实现函数initialize_parameters()。

说明:

•确保参数大小正确。如有需要,请参考上面的神经网络图
•您将用随机值初始化权重矩阵

  ◾使用:np.random.randn (a, b) * 0.01随机初始化一个矩阵的形状(a, b)。

•将偏差向量初始化为零。

  ◾使用:np.zeros ((a, b))来初始化一个矩阵的形状与0 (a, b)。

 

# GRADED FUNCTION: initialize_parameters

def initialize_parameters(n_x, n_h, n_y):
    """
    Argument:
    n_x -- size of the input layer
    n_h -- size of the hidden layer
    n_y -- size of the output layer
    
    Returns:
    params -- python dictionary containing your parameters:
                    W1 -- weight matrix of shape (n_h, n_x)
                    b1 -- bias vector of shape (n_h, 1)
                    W2 -- weight matrix of shape (n_y, n_h)
                    b2 -- bias vector of shape (n_y, 1)
    """
    
    np.random.seed(2) # we set up a seed so that your output matches ours although the initialization is random.
    
    ### START CODE HERE ### (≈ 4 lines of code)
    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)) 
    ### END CODE HERE ###
    
    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
n_x, n_h, n_y = initialize_parameters_test_case()

parameters = initialize_parameters(n_x, n_h, n_y)
print("W1 = " + str(parameters["W1"]))
print("b1 = " + str(parameters["b1"]))
print("W2 = " + str(parameters["W2"]))
print("b2 = " + str(parameters["b2"]))

 

 

 


 

4.3 - The Loop(循环)

Question: Implement forward_propagation().(问题:实现forward_propagation ()。)

说明:

•看看上面的分类器的数学表示。
•可以使用函数sigmoid()。它是内置(导入)在笔记本电脑。
•可以使用函数np.tanh()。它是numpy库的一部分。
•你必须执行的步骤是:

1、通过使用parameters[".."],从字典"parameters" (是initialize_parameters()的输出)中检索每个参数。
2、实现向前传播。计算(你对训练集中所有例子的所有预测的向量)。


•反向传播所需的值存储在“缓存”中。缓存将作为反向传播函数的输入

 

 

 

 向前传播:

# GRADED FUNCTION: forward_propagation 先前传播

def forward_propagation(X, parameters):
    """
    Argument:
    X -- input data of size (n_x, m)
    parameters -- python dictionary containing your parameters (output of initialization function)
    #parameters——包含参数的python字典(初始化函数的输出)
    
    Returns:
    A2 -- The sigmoid output of the second activation
    cache -- a dictionary containing "Z1", "A1", "Z2" and "A2"
    """
    # Retrieve each parameter from the dictionary "parameters" Retrieve恢复、检索、重新得到
    ### START CODE HERE ### (≈ 4 lines of code)
    W1 = parameters["W1"]
    b1 = parameters["b1"]
    W2 = parameters["W2"]
    b2 = parameters["b2"]
    ### END CODE HERE ###
    
    # Implement Forward Propagation to calculate A2 (probabilities)
    ### START CODE HERE ### (≈ 4 lines of code)
    Z1 = np.dot(W1, X) + b1
    A1 = np.tanh(Z1)
    Z2 = np.dot(W2, A1) + b2
    A2 = sigmoid(Z2)
    ### END CODE HERE ###
    
    assert(A2.shape == (1, X.shape[1]))
    
    cache = {"Z1": Z1,
             "A1": A1,
             "Z2": Z2,
             "A2": A2}
    
    return A2, cache
X_assess, parameters = forward_propagation_test_case()

A2, cache = forward_propagation(X_assess, parameters)

# Note: we use the mean here just to make sure that your output matches ours. 注意:我们在这里使用平均值只是为了确保您的输出与我们的匹配。
print(np.mean(cache['Z1']) ,np.mean(cache['A1']),np.mean(cache['Z2']),np.mean(cache['A2']))

 

 

 

现在你已经算出了A【2】(在Python中是变量“A2”),其中对于每个样本都包含了一个a【2】(i),你可以计算成本函数如下:

 

 

练习:实现compute_cost()来计算代价J的值

说明:•有很多方法可以实现交叉熵损失。为了帮助你,我们告诉你我们将如何实施:

 

 

 

logprobs = np.multiply(np.log(A2),Y)

cost = - np.sum(logprobs)              # no need to use a for loop!

(you can use either np.multiply() and then np.sum() or directly np.dot()).

 

# GRADED FUNCTION: compute_cost

def compute_cost(A2, Y, parameters):
    """
    Computes the cross-entropy cost given in equation (13)
    
    Arguments:
    A2 -- The sigmoid output of the second activation, of shape (1, number of examples)
    Y -- "true" labels vector of shape (1, number of examples)
    parameters -- python dictionary containing your parameters W1, b1, W2 and b2
    
    Returns:
    cost -- cross-entropy cost given equation (13)
    """
    
    m = Y.shape[1] # number of example

    # Compute the cross-entropy cost
    ### START CODE HERE ### (≈ 2 lines of code)
    logprobs = np.multiply(np.log(A2), Y)
    cost = - np.sum(logprobs  + (1-Y) * np.log(1 - A2)) / m
    ### END CODE HERE ###
    
    cost = np.squeeze(cost)     # makes sure cost is the dimension we expect. 
                                # E.g., turns [[17]] into 17 
    assert(isinstance(cost, float))
    
    return cost
A2, Y_assess, parameters = compute_cost_test_case()

print("cost = " + str(compute_cost(A2, Y_assess, parameters)))

 

 

 

 

使用前向传播期间计算的缓存,现在可以实现后向传播。

问题:实现函数backward_propagation()。

 

说明:反向传播通常是深度学习中最难的部分。为了帮助你们,这里有一张关于反向传播的幻灯片。您需要使用这张幻灯片右边的六个方程,因为您正在构建一个向量化的实现

 

 

提示:

 

 

 

 

# GRADED FUNCTION: backward_propagation

def backward_propagation(parameters, cache, X, Y):
    """
    Implement the backward propagation using the instructions above.
    
    Arguments:
    parameters -- python dictionary containing our parameters 
    cache -- a dictionary containing "Z1", "A1", "Z2" and "A2".
    X -- input data of shape (2, number of examples)
    Y -- "true" labels vector of shape (1, number of examples)
    
    Returns:
    grads -- python dictionary containing your gradients with respect to different parameters
    """
    m = X.shape[1]
    
    # First, retrieve W1 and W2 from the dictionary "parameters".
    ### START CODE HERE ### (≈ 2 lines of code)
    W1 = parameters["W1"]
    W2 = parameters["W2"]
    ### END CODE HERE ###
        
    # Retrieve also A1 and A2 from dictionary "cache".
    ### START CODE HERE ### (≈ 2 lines of code)
    A1 = cache["A1"]
    A2 = cache["A2"]
    ### END CODE HERE ###
    
    # Backward propagation: calculate dW1, db1, dW2, db2. 
    ### START CODE HERE ### (≈ 6 lines of code, corresponding to 6 equations on slide above)
    dZ2 = A2 - Y
    dW2 = np.dot(dZ2, A1.T) / m
    db2 = np.sum(dZ2, axis = 1, keepdims = True) / m
    dZ1 = np.multiply(W2.T * dZ2, (1 - np.power(A1, 2)))
    dW1 = np.dot(dZ1, X.T) / m
    db1 = np.sum(dZ1, axis = 1, keepdims = True) / m
    ### END CODE HERE ###
    
    grads = {"dW1": dW1,
             "db1": db1,
             "dW2": dW2,
             "db2": db2}
    
    return grads
parameters, cache, X_assess, Y_assess = backward_propagation_test_case()

grads = backward_propagation(parameters, cache, X_assess, Y_assess)
print ("dW1 = "+ str(grads["dW1"]))
print ("db1 = "+ str(grads["db1"]))
print ("dW2 = "+ str(grads["dW2"]))
print ("db2 = "+ str(grads["db2"]))

 

 

 

问题:实现更新规则。用梯度下降法。为了更新(W1、b1、W2、b2),必须使用(dW1、db1、dW2、db2)。

一般梯度下降规则:式中,α为学习率,θ代表参数。

说明:学习率好的梯度下降算法(收敛)和坏的学习率(发散)。图片由亚当·哈雷提供。

# GRADED FUNCTION: update_parameters

def update_parameters(parameters, grads, learning_rate = 1.2):
    """
    Updates parameters using the gradient descent update rule given above
    
    Arguments:
    parameters -- python dictionary containing your parameters 
    grads -- python dictionary containing your gradients 
    
    Returns:
    parameters -- python dictionary containing your updated parameters 
    """
    # Retrieve each parameter from the dictionary "parameters"
    ### START CODE HERE ### (≈ 4 lines of code)
    W1 = parameters["W1"]
    b1 = parameters["b1"]
    W2 = parameters["W2"]
    b2 = parameters["b2"]
    ### END CODE HERE ###
    
    # Retrieve each gradient from the dictionary "grads"
    ### START CODE HERE ### (≈ 4 lines of code)
    dW1 = grads["dW1"]
    db1 = grads["db1"]
    dW2 = grads["dW2"]
    db2 = grads["db2"]
    ## END CODE HERE ###
    
    # Update rule for each parameter
    ### START CODE HERE ### (≈ 4 lines of code)
    W1 -= learning_rate * dW1
    b1 -= learning_rate * db1
    W2 -= learning_rate * dW2
    b2 -= learning_rate * db2
    ### END CODE HERE ###
    
    parameters = {"W1": W1,
                  "b1": b1,
                  "W2": W2,
                  "b2": b2}
    
    return parameters
parameters, grads = update_parameters_test_case()
parameters = update_parameters(parameters, grads)

print("W1 = " + str(parameters["W1"]))
print("b1 = " + str(parameters["b1"]))
print("W2 = " + str(parameters["W2"]))
print("b2 = " + str(parameters["b2"]))

结果:

 

 

 


 

4.4 - Integrate parts 4.1, 4.2 and 4.3 in nn_model() (4.4 -整合nn_model()中的4.1、4.2、4.3部分)

问题:在nn_model()构建你的神经网络模型。

说明:神经网络模型必须按照正确的顺序使用前面的函数。

 

 

 1 # GRADED FUNCTION: nn_model
 2 
 3 def nn_model(X, Y, n_h, num_iterations = 10000, print_cost=False):
 4     """
 5     Arguments:
 6     X -- dataset of shape (2, number of examples)
 7     Y -- labels of shape (1, number of examples)
 8     n_h -- size of the hidden layer
 9     num_iterations -- Number of iterations in gradient descent loop
10     print_cost -- if True, print the cost every 1000 iterations
11     
12     Returns:
13     parameters -- parameters learnt by the model. They can then be used to predict.
14     """
15     
16     np.random.seed(3)
17     n_x = layer_sizes(X, Y)[0]
18     n_y = layer_sizes(X, Y)[2]
19     
20     # Initialize parameters, then retrieve W1, b1, W2, b2. Inputs: "n_x, n_h, n_y". Outputs = "W1, b1, W2, b2, parameters".
21     ### START CODE HERE ### (≈ 5 lines of code)
22     parameters = initialize_parameters(n_x, n_h, n_y)
23     W1 = parameters["W1"]
24     b1 = parameters["b1"]
25     W2 = parameters["W2"]
26     b2 = parameters["b2"]
27     ### END CODE HERE ###
28     
29     # Loop (gradient descent)
30 
31     for i in range(0, num_iterations):
32          
33         ### START CODE HERE ### (≈ 4 lines of code)
34         # Forward propagation. Inputs: "X, parameters". Outputs: "A2, cache".
35         A2, cache = forward_propagation(X, parameters)
36         
37         # Cost function. Inputs: "A2, Y, parameters". Outputs: "cost".
38         cost = compute_cost(A2, Y, parameters)
39  
40         # Backpropagation. Inputs: "parameters, cache, X, Y". Outputs: "grads".
41         grads = backward_propagation(parameters, cache, X, Y)
42  
43         # Gradient descent parameter update. Inputs: "parameters, grads". Outputs: "parameters".
44         parameters = update_parameters(parameters, grads)
45         
46         ### END CODE HERE ###
47         
48         # Print the cost every 1000 iterations
49         if print_cost and i % 1000 == 0:
50             print ("Cost after iteration %i: %f" %(i, cost))
51         
52         
53 
54     return parameters
X_assess, Y_assess = nn_model_test_case()
parameters = nn_model(X_assess, Y_assess, 4, num_iterations=10000, print_cost=False)
print("W1 = " + str(parameters["W1"]))
print("b1 = " + str(parameters["b1"]))
print("W2 = " + str(parameters["W2"]))
print("b2 = " + str(parameters["b2"]))

结果:

 

 

 

 

 


 

 4.5 Predictions

 问题:通过构建predict()来使用您的模型进行预测。使用正向传播预测结果。

提示:

 

 

例如,如果您想根据阈值将矩阵X的项设置为0和1,您可以这样做:X_new = (X >阈值)

# GRADED FUNCTION: predict

def predict(parameters, X):
    """
    Using the learned parameters, predicts a class for each example in X
    
    Arguments:
    parameters -- python dictionary containing your parameters 
    X -- input data of size (n_x, m)
    
    Returns
    predictions -- vector of predictions of our model (red: 0 / blue: 1)
    """
    
    # Computes probabilities using forward propagation, and classifies to 0/1 using 0.5 as the threshold.
    ### START CODE HERE ### (≈ 2 lines of code)
    A2, cache = forward_propagation(X, parameters) #A2就是y hat
    predictions = np.round(A2)
    #round() 方法返回浮点数x的四舍五入值。
    ### END CODE HERE ###
    
    return predictions
parameters, X_assess = predict_test_case()

predictions = predict(parameters, X_assess)
print("predictions mean = " + str(np.mean(predictions)))

结果:

 

 

现在是时候运行模型,看看它在平面数据集上的表现如何。运行下面的代码,用一个隐藏层来测试您的模型,nh隐藏的单位。

 

# Build a model with a n_h-dimensional hidden layer
parameters = nn_model(X, Y, n_h = 4, num_iterations = 10000, print_cost=True) #这里n_h = 4 是隐藏层的神经元个数哦

# Plot the decision boundary
plot_decision_boundary(lambda x: predict(parameters, x.T), X, Y)
plt.title("Decision Boundary for hidden layer size " + str(4))

结果:

 

 

 

 

# Print accuracy
predictions = predict(parameters, X)
print ('Accuracy: %d' % float((np.dot(Y,predictions.T) + np.dot(1-Y,1-predictions.T))/float(Y.size)*100) + '%')

结果:

 

逻辑回归相比,它的准确性真的很高。模特学会了花的叶子图案!  与逻辑回归不同,神经网络能够学习甚至高度非线性的决策边界

现在,让我们尝试几种隐藏图层大小。

 


 

4.6 - Tuning hidden layer size (optional/ungraded exercise) (4.6 -调整隐藏层大小(可选/未分级练习))

运行以下代码。可能需要1-2分钟。您将观察不同隐藏层大小的模型的不同行为。

 

# This may take about 2 minutes to run

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)
    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))

结果:

 

 解释:

较大的模型(隐藏单元更多)能够更好地拟合训练集,直到最终最大的模型对数据进行过拟合
•最好的隐藏层大小似乎是在n_h = 5左右。实际上,这里的值似乎很适合数据,而不会引起明显的过拟合。
•稍后您还将学习正则化,它可以让您使用非常大的模型(如n_h = 50)而不会过度拟合。

 

可选的问题:

注意:记得提交作业,但点击右上角的蓝色“提交作业”按钮。

一些可选的/未评分的问题,你可以探索,如果你愿意:

•将tanh激活改为sigmoid激活或ReLU激活会发生什么?
•玩学习率。会发生什么呢?
•如果我们改变数据集会怎么样?(参见下面的第5部分!)

 

**你已经学会:** -建立一个完整的带有隐含层的神经网络-充分利用非线性单元-实现前向传播和后向传播,训练一个神经网络-看看改变隐含层大小的影响,包括过拟合

干得漂亮!!!

 


 

5) Performance on other datasets (5)其他数据集的性能)

如果需要,可以为以下每个数据集重新运行整个笔记本(减去数据集部分)。

# Datasets
noisy_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}

### START CODE HERE ### (choose your dataset)
dataset = "gaussian_quantiles"
### END CODE HERE ###

X, Y = datasets[dataset]
X, Y = X.T, Y.reshape(1, Y.shape[0])

# make blobs binary
if dataset == "blobs":
    Y = Y%2

# Visualize the data
plt.scatter(X[0, :], X[1, :], c= np.squeeze(Y), s=40, cmap=plt.cm.Spectral);

结果:

 

 祝贺你完成了这个编程任务!

Reference:

posted @ 2020-07-21 23:21  廖海清  阅读(2123)  评论(0编辑  收藏  举报