应用于图像分类的深度神经网络:应用

完成本节后,您将完成第4周的最后编程任务,也完成本课程的最后编程任务!

您将使用您在之前的作业中实施的函数来构建深度网络,并将其应用于猫与非猫分类。 希望相对于之前的逻辑回归实现,您将看到精度的提高。

完成这项任务后,您将能够:

建立和应用深度神经网络监督学习。

1 – 包

Let's first import all the packages that you will need during this assignment.

  • numpy is the fundamental package for scientific computing with Python.

  • matplotlib is a library to plot graphs in Python.

  • h5py is a common package to interact with a dataset      that is stored on an H5 file.

  • PIL and      scipy are used here      to test your model with your own picture at the end.

  • dnn_app_utils provides the      functions implemented in the "Building your Deep Neural Network: Step      by Step" assignment to this notebook.

  • np.random.seed(1) is used to keep      all the random function calls consistent. It will help us grade your work.

import timeimport numpy as npimport h5pyimport matplotlib.pyplot as pltimport scipyfrom PIL import Imagefrom scipy import ndimagefrom dnn_app_utils_v2 import *%matplotlib inlineplt.rcParams['figure.figsize'] = (5.0, 4.0) # set default size of plotsplt.rcParams['image.interpolation'] = 'nearest'plt.rcParams['image.cmap'] = 'gray'%load_ext autoreload%autoreload 2np.random.seed(1)

2 – 数据集

您将使用与“Logistic回归作为神经网络”(作业2)相同的“猫与非猫”数据集。 您之前建立的模型在分类猫和非猫图像时的测试准确率为70%。 希望你的新模型能更好地发挥作用!

Problem Statement: You are given a dataset ("data.h5") containing:

– a training set of m_train images labelled as cat (1) or non-cat (0)
– a test set of m_test images labelled as cat and non-cat
– each image is of shape (num_px, num_px, 3) where 3 is for the 3 channels (RGB).

让我们更熟悉数据集。 通过运行下面的单元格加载数据。

train_x_orig, train_y, test_x_orig, test_y, classes = load_data()#把所有的测试数据通过load_data()载入到前序变量中#train_x_orig保存训练数据的RGB数据,train_y训练数据的标记(1为猫,0非猫)

 

以下代码将显示数据集中的图像。 随意更改索引并重新运行单元格多次以查看其他图像。

# Example of a pictureindex = 7plt.imshow(train_x_orig[index])#画出第几个图片print("y="+str(train_y[0,index])+". It's a"+classes[train_y[0,index]].decode("utf-8")+"picture.")

 

以下代码显示样本集的尺寸信息

# Explore your datasetm_train = train_x_orig.shape[0]num_px = train_x_orig.shape[1]m_test = test_x_orig.shape[0] print ("Number of training examples: " + str(m_train))print ("Number of testing examples: " + str(m_test))print ("Each image is of size: (" + str(num_px) + ", " + str(num_px) + ", 3)")print ("train_x_orig shape: " + str(train_x_orig.shape))print ("train_y shape: " + str(train_y.shape))print ("test_x_orig shape: " + str(test_x_orig.shape))print ("test_y shape: " + str(test_y.shape))

像往常一样,在将图像馈送到网络之前,您会重塑图像的向量并对其进行标准化。代码在下面的单元格中给出。

1517667135794468.jpg

# Reshape the training and test examplestrain_x_flatten = train_x_orig.reshape(train_x_orig.shape[0], -1).T# The "-1" makes reshape flatten the remaining dimensionstest_x_flatten = test_x_orig.reshape(test_x_orig.shape[0], -1).T # 标准化数据,使他们的特征值为0或1train_x = train_x_flatten/255.test_x = test_x_flatten/255. print ("train_x's shape: " + str(train_x.shape))print ("test_x's shape: " + str(test_x.shape))

 

12288就是之前我们reshape向量时讲的,RGB的三个向量乘3,即64*64*3。

 

 

3 – 模型的结构

现在您已经熟悉数据集了,现在是构建一个深层神经网络来区分猫图像和非猫图像的时候了。

你将建立两个不同的模型,就像之前那个PART.1中一样,一个2层模型一个L层模型。

然后将要比较这两个模型。关于结构图在PART.1中都已经叙述,在此不再重述。

3.1 – 2层深度神经网络模型

对于2层模型来说,它可以被简单概括为: INPUT -> LINEAR -> RELU -> LINEAR -> SIGMOID -> OUTPUT.

关于2层模型的结构图做出下面解释:
– 输入是一个(64,64,3)的图像,然后reshape为(12288,1)。注意这是一个样本的向量
– 相应的矢量[x0,x1,…,x12287]T接下来就右乘权重矩阵W1,W1的尺寸为(n[l],12288)。要牢记权重矩阵的维度规律
– 然后,添加一个偏差项,并采用激活函数(采用RELU)获得以下向量: [a[1]0,a[1]1,…,a[1]n[1]1]T.
– 重复上述过程,得到每一个节点的值
– 继续将上面的结果的过程乘第二个权重矩阵W2,然后增加偏差项。
– 最后,利用sigmoid函数得到结果。如果结果大于0.5,则是猫,否则不是猫。

3.2 -L层深度神经网络模型

很难用以上的表示方法来表示一个L层深度神经网络模型。但是,在这里我们提供了一个简化的模型:

1517667181127511.jpg

模型可以被简单表述为: [LINEAR -> RELU] × (L-1) -> LINEAR -> SIGMOID

关于L层模型的结构图做出下面解释:
– 输入是一个(64,64,3)的图像,然后reshape为(12288,1)。注意这是一个样本的向量
– 相应的向量 [x0,x1,…,x12287]T 与权重矩阵W[1]相乘,增加偏差项b[1]。 结果被称为线性单元。
– 接下了对这个线性单元做RELU。然后这个过程重复做所需要的次数。
– 最后,利用sigmoid函数得到结果。如果结果大于0.5,则是猫,否则不是猫。

3.3 – 通用算法

按照下面的算法顺序来创建模型:

1.  初始化参数/定义超参数
2.循环num_iterations:
 (1)正向传播
 (2)计算成本函数
 (3)反向传播
 (4)更新参数(使用参数和backprop中的梯度)
4.使用训练的参数来预测标签

Let's now implement those two models!

4 – 两层深度网络

Question: 利用之前的作业中你已经完成的辅助函数安装下面的顺序来完成一个2层的深度神经网络: LINEAR -> RELU -> LINEAR -> SIGMOID。这些函数主要是:

def initialize_parameters(n_x, n_h, n_y):    ...    return parametersdef linear_activation_forward(A_prev, W, b, activation):    ...    return A, cachedef compute_cost(AL, Y):    ...    return costdef linear_activation_backward(dA, cache, activation):    ...    return dA_prev, dW, dbdef update_parameters(parameters, grads, learning_rate):    ...    return parameters
### CONSTANTS DEFINING THE MODEL ####n_x = 12288     # num_px * num_px * 3n_h = 7n_y = 1layers_dims = (n_x, n_h, n_y)

 

# GRADED FUNCTION: two_layer_model def two_layer_model(X,Y,layers_dims,learning_rate=0.0075,num_iterations=3000,print_cost=False):    """    Implements a two-layer neural network: LINEAR->RELU->LINEAR->SIGMOID.       Arguments:    X -- 样本数据, of shape (n_x, number of examples)    Y -- 真实标签向量 (0-猫,1-非猫), of shape (1, 例子的数量)    layers_dims -- 每一层的维度 (n_x, n_h, n_y)    num_iterations -- number of iterations of the optimization loop    learning_rate --梯度下降算法更新的学习速率    print_cost -- 如果设置正确,那么每100次打印一个代价数值       Returns:    parameters -- 一个包含有W1,W2,b1,b2的字典    """       np.random.seed(1)    grads = {}    costs = []          # to keep track of the cost    m = X.shape[1]        # number of examples    (n_x, n_h, n_y) = layers_dims       # 初始化参数字典,利用调用之前设计的辅助函数    ### START CODE HERE ### (≈ 1 line of code)    parameters = initialize_parameters(n_x, n_h, n_y)    ### END CODE HERE ###       # 从字典参数中得到W1, b1,W2和b2 。    W1 = parameters["W1"]    b1 = parameters["b1"]    W2 = parameters["W2"]    b2 = parameters["b2"]       #梯度下降算法的循环     for i in range(0, num_iterations):         # 前向传播 LINEAR -> RELU -> LINEAR -> SIGMOID.         #Inputs: "X, W1, b1". Output: "A1, cache1, A2, cache2".        ### START CODE HERE ### (≈ 2 lines of code)        A1, cache1 =linear_activation_forward(X, W1, b1, activation = "relu")        A2, cache2 = linear_activation_forward(A1, W2, b2, activation = "sigmoid")        ### END CODE HERE ###               # 计算代价函数        ### START CODE HERE ### (≈ 1 line of code)        cost = compute_cost(A2, Y)        ### END CODE HERE ###               # 初始化反向传播        dA2 = - (np.divide(Y, A2) - np.divide(1 - Y, 1 - A2))               # 反向传播. Inputs: "dA2, cache2, cache1". Outputs: "dA1, dW2, db2; also dA0 (not used), dW1, db1".        ### START CODE HERE ### (≈ 2 lines of code)        dA1, dW2, db2 = linear_activation_backward(dA2, cache2, activation = "sigmoid")        dA0, dW1, db1 = linear_activation_backward(dA1, cache1, activation = "relu")        ### END CODE HERE ###               # Set grads['dWl'] to dW1, grads['db1'] to db1,        #grads['dW2'] to dW2, grads['db2'] to db2        grads['dW1'] = dW1        grads['db1'] = db1        grads['dW2'] = dW2        grads['db2'] = db2               # 更新参数        ### START CODE HERE ### (approx. 1 line of code)        parameters = update_parameters(parameters, grads, learning_rate)        ### END CODE HERE ###         # Retrieve W1, b1, W2, b2 from parameters        W1 = parameters["W1"]        b1 = parameters["b1"]        W2 = parameters["W2"]        b2 = parameters["b2"]               # 每100个训练样本打印一次代价值        if print_cost and i % 100 == 0:            print("Cost after iteration {}: {}".format(i, np.squeeze(cost)))        if print_cost and i % 100 == 0:            costs.append(cost)          # 画出代价函数图像     plt.plot(np.squeeze(costs))    plt.ylabel('cost')    plt.xlabel('iterations (per tens)')    plt.title("Learning rate =" + str(learning_rate))    plt.show()   return parameters#返回参数

训练集训练:

parameters=two_layer_model(train_x,train_y,layers_dims=(n_x,n_h,n_y),num_iterations=2500,print_cost=True)

3.jpg

测试集测试:

predictions_test = predict(test_x, test_y, parameters)

精确度为72%

注意:您可能会注意到,以较少的迭代(例如1500)运行模型可以提高测试集的准确性。 这叫做“早停”,我们将在下一个课程中进行讨论。 提前停止是防止过拟合的一种方法。

恭喜! 看来你的2层神经网络比逻辑回归实现(70%,第二周作业数值)有更好的表现(72%)。 让我们看看你是否能用L层模型做得更好。

5 – L层深度网络

Question: 利用之前的作业中你已经完成的辅助函数安装下面的顺序来完成一个L层的深度神经网络: LINEAR -> RELU -> LINEAR -> SIGMOID。这些函数主要是:

 [LINEAR -> RELU]××(L-1) -> LINEAR -> SIGMOID. The functions you may need and their inputs are:

def initialize_parameters_deep(layer_dims):    ...    return parametersdef L_model_forward(X, parameters):    ...    return AL, cachesdef compute_cost(AL, Y):    ...    return costdef L_model_backward(AL, Y, caches):    ...    return gradsdef update_parameters(parameters, grads, learning_rate):    ...    return parameters
# GRADED FUNCTION: L_layer_modeldef L_layer_model(X, Y, layers_dims, learning_rate = 0.0075, num_iterations=3000,                   print_cost=False):#lr was 0.009    """    Implements a L-layer neural network: [LINEAR->RELU]*(L-1)->LINEAR->SIGMOID.        Arguments:    X -- 数据,numpy数组的尺寸(number of examples, num_px * num_px * 3)    Y -- 真实数据的标签 (0-猫,1-非猫), of shape (1, 例子的数量)    layers_dims -- 输入层尺寸和每一层尺寸所包含的列表 (数值为number of layers + 1).    learning_rate --梯度下降算法的学习速率    num_iterations -- 优化循环的迭代次数    print_cost --如果代码书写正确,每100次打印一个代价数据。        Returns:    parameters --通过模型学习到的参数,用来做预测。    """    np.random.seed(1)    costs = []                         # keep track of cost        # 初始化参数。    ### START CODE HERE ###    parameters = initialize_parameters_deep(layers_dims)    ### END CODE HERE ###        # 梯度下降的循环算法    for i in range(0, num_iterations):        # 前向传播: [LINEAR -> RELU]*(L-1) -> LINEAR -> SIGMOID.        ### START CODE HERE ### (≈ 1 line of code)        AL, caches = L_model_forward(X, parameters)        ### END CODE HERE ###                # 计算代价        ### START CODE HERE ### (≈ 1 line of code)        cost = compute_cost(AL, Y)        ### END CODE HERE ###            # 反向传播        ### START CODE HERE ### (≈ 1 line of code)        grads = L_model_backward(AL, Y, caches)        ### END CODE HERE ###         # 更新参数        ### START CODE HERE ### (≈ 1 line of code)        parameters = update_parameters(parameters, grads, learning_rate)        ### END CODE HERE ###                        # 每100个训练结果打印出代价        if print_cost and i % 100 == 0:            print ("迭代后的代价 %i: %f" %(i, cost))        if print_cost and i % 100 == 0:            costs.append(cost)                # plot the cost    plt.plot(np.squeeze(costs))    plt.ylabel('cost')    plt.xlabel('iterations (per tens)')    plt.title("learning rate =" + str(learning_rate))    plt.show()        return parameters

训练集做训练:

parameters=L_layer_model(train_x,train_y,layers_dims,num_iterations=2500,print_cost=True)

1517667505604757.png

训练集预测准确度代码:

pred_train = predict(train_x, train_y, parameters)
准确度:0.985645933014

测试集预测准确度代码:

pred_test = predict(test_x, test_y, parameters)

准确度:0.8

恭喜! 看起来你的5层神经网络比同样的测试集上的2层神经网络(72%)有更好的性能(80%)。

这对于这个任务来说是很好的表现。 不错的工作!

在下一课“改善深度神经网络”中,您将学习如何通过系统地搜索更好的超参数(learning_rate,layers_dims,num_iterations,以及在下一课程中学习的其他参数)来获得更高的准确性。

6 – 结果分析

首先,我们来看一些L层模型中标记不正确的例子。

1517667623747031.png

模型往往做得不好的几种类型的图像包括:

  1. 猫身体在一个不寻常的位置

  2. 猫出现在相似颜色的背景下

  3. 不寻常的猫的颜色和物种

  4. 相机角度问题

  5. 图片的亮度问题

  6. 比例变化(猫的图像非常大或很小)