吳恩達深度學習 第四課第一周編程作業_Convolutional Neural Networks: Application


Convolutional Neural Networks: Application  卷積神經網絡應用

本文參考了深度學習吳恩達小迷弟 的文章,鏈接:https://blog.csdn.net/weixin_47440593/article/details/107938235

 

歡迎來到課程4的第二次作業!在這個筆記本里,你會:

·實現在實現TensorFlow模型時將使用的輔助函數
·使用TensorFlow實現一個功能完整的卷積網絡

After this assignment you will be able to:

·針對一個分類問題,在TensorFlow中建立並訓練一個卷積網絡
我們假設你已經熟悉TensorFlow了。如果你不是,請參考課程2第三周的TensorFlow教程(“改善深度神經網絡”)。

1.0 - TensorFlow model TensorFlow模型

在上一個任務中,您使用numpy構建了幫助函數,以理解卷積神經網絡背后的機制。目前,深度學習的大多數實際應用程序都是使用編程框架構建的,這些框架具有許多可以簡單調用的內置函數

像往常一樣,我們將從裝入包開始。

 

import math
import numpy as np
import h5py
import matplotlib.pyplot as plt
import scipy
from PIL import Image
from scipy import ndimage
import tensorflow as tf
from tensorflow.python.framework import ops
from cnn_utils import *

%matplotlib inline
np.random.seed(1)

這里好的答案或者參考都沒有使用scipy,暫時還不知道原因

運行下一個單元格以加載將要使用的“sign”數據集。

# Loading the data (signs)
X_train_orig, Y_train_orig, X_test_orig, Y_test_orig, classes = load_dataset()

提醒一下,符號數據集是6個符號的集合,它們代表從0到5的數字。

下一個單元格將向您展示數據集中的標記圖像示例。您可以隨意更改下面的index值並重新運行以查看不同的示例。

# Example of a picture
index = 8
plt.imshow(X_train_orig[index])
print ("y = " + str(np.squeeze(Y_train_orig[:, index])))

運行結果:

 

 在課程2中,您已經為這個數據集構建了一個完全連接的網絡。但由於這是一個圖像數據集,應用卷積神經網絡更自然

首先,讓我們研究一下數據的形狀。

在課程2中,我們已經建立過一個神經網絡,我想對這個數據集應該不陌生吧~我們再來看一下數據的維度,如果你忘記了獨熱編碼的實現,請看這里

X_train = X_train_orig/255.
X_test = X_test_orig/255.
Y_train = convert_to_one_hot(Y_train_orig, 6).T
Y_test = convert_to_one_hot(Y_test_orig, 6).T
print ("number of training examples = " + str(X_train.shape[0]))
print ("number of test examples = " + str(X_test.shape[0]))
print ("X_train shape: " + str(X_train.shape))
print ("Y_train shape: " + str(Y_train.shape))
print ("X_test shape: " + str(X_test.shape))
print ("Y_test shape: " + str(Y_test.shape))
conv_layers = {}

執行結果:

number of training examples = 1080
number of test examples = 120
X_train shape: (1080, 64, 64, 3)
Y_train shape: (1080, 6)
X_test shape: (120, 64, 64, 3)
Y_test shape: (120, 6)

 

1.1 - Create placeholders 創建占位符

TensorFlow要求您為運行會話時將輸入到模型中的輸入數據創建占位符。現在我們要實現創建占位符的函數,因為我們使用的是小批量數據塊,輸入的樣本數量可能不固定,所以我們在數量那里我們要使用None作為可變數量。輸入X的維度為**[None,n_H0,n_W0,n_C0],對應的Y是[None,n_y]**

 1 # GRADED FUNCTION: create_placeholders
 2 
 3 def create_placeholders(n_H0, n_W0, n_C0, n_y):
 4     """
 5     Creates the placeholders for the tensorflow session. 為session創建占位符
 6     
 7     Arguments:
 8     n_H0 -- scalar, height of an input image 實數,輸入圖像的高度
 9     n_W0 -- scalar, width of an input image 實數,輸入圖像的寬度
10     n_C0 -- scalar, number of channels of the input 實數,輸入的通道數
11     n_y -- scalar, number of classes 實數, 分類數
12         
13     Returns:
14     X -- placeholder for the data input, of shape [None, n_H0, n_W0, n_C0] and dtype "float"
15         輸入數據的占位符,維度為[None, n_H0, n_W0, n_C0],類型為"float"
16     Y -- placeholder for the input labels, of shape [None, n_y] and dtype "float"
17         輸入數據的標簽的占位符,維度為[None, n_y],維度為"float"
18     """
19 
20     ### START CODE HERE ### (≈2 lines)
21     X = tf.compat.v1.placeholder(tf.float32, [None, n_H0, n_W0, n_C0])
22     Y = tf.compat.v1.placeholder(tf.float32, [None, n_y])
23     ### END CODE HERE ###
24     
25     return X, Y
# GRADED FUNCTION: create_placeholders
tf.compat.v1.disable_eager_execution() #這里因為是使用TF2.x的原因,不加會報錯

X, Y = create_placeholders(64, 64, 3, 6)
print ("X = " + str(X))
print ("Y = " + str(Y))

執行結果:

 

 tf.placeholder() is not compatible with eager execution的解決方法

 

1.2 - Initialize parameters  初始化參數

現在我們將使用tf.contrib.layers.xavier_initializer(seed = 0) 來初始化權值/過濾器W1、W2。您不需要擔心偏差變量,因為您很快就會看到TensorFlow函數會處理偏差。還要注意,需要注意的是我們只需要初始化為2D卷積函數,全連接層TensorFlow會自動初始化的。

 練習:實現initialize_parameters()。下面提供了每組過濾器的尺寸。提醒——初始化參數𝑊形狀(1、2、3、4)在Tensorflow,使用:

W = tf.get_variable("W", [1,2,3,4], initializer = ...)
 1 # GRADED FUNCTION: initialize_parameters
 2 
 3 def initialize_parameters():
 4     """
 5     初始化權值矩陣,這里我們把權值矩陣硬編碼:
 6     Initializes weight parameters to build a neural network with tensorflow. The shapes are:
 7                         W1 : [4, 4, 3, 8]
 8                         W2 : [2, 2, 8, 16]
 9     Returns:
10     parameters -- a dictionary of tensors containing W1, W2 包含了tensor類型的W1、W2的字典
11     """
12     
13 #     tf.set_random_seed(1)                              # so that your "random" numbers match ours 由於使用tf2.x 所以換成
14     tf.random.set_seed(1)    
15     ### START CODE HERE ### (approx. 2 lines of code)
16     W1 = tf.compat.v1.get_variable('W1', [4, 4, 3, 8], initializer = tf.initializers.GlorotUniform(seed=1))
17     W2 = tf.compat.v1.get_variable('W2', [2, 2, 8, 16], initializer = tf.initializers.GlorotUniform(seed=1))
18     ### END CODE HERE ###
19 
20     parameters = {"W1": W1,
21                   "W2": W2}
22     
23     return parameters
# GRADED FUNCTION: initialize_parameters
# tf.reset_default_graph() 使用的tf2.x 這個不適用
ops.reset_default_graph()
with tf.compat.v1.Session() as sess_test:
    parameters = initialize_parameters()
    init = tf.compat.v1.global_variables_initializer()
    sess_test.run(init)
    print("W1 = " + str(parameters["W1"].eval()[1,1,1]))
    print("W2 = " + str(parameters["W2"].eval()[1,1,1]))

執行結果:

 

 (這里因為是使用tf2.x版本的原因,更改了許多的代碼,權重的初始化也換了一個,不知是否是這個原因導致結果和預期不一致)

 

 1.2 - Forward propagation 前向傳播

 在TensorFlow中,有一些內置函數可以幫你完成卷積步驟。

·tf.nn.conv2d(X,W1, strides = [1,s,s,1], padding = 'SAME'):給定輸入 X 和一組過濾器 W1 ,這個函數將會自動使用 W1 來對 X 進行卷積,第三個輸入參數是**[1,s,s,1]**是指對於輸入(m, n_H_prev, n_W_prev, n_C_prev)而言,每次滑動的步伐。你也可以點這里閱讀文檔

 

 ·tf.nn.max_pool(A, ksize = [1,f,f,1], strides = [1,s,s,1], padding = 'SAME'):給定輸入 X ,該函數將會使用大小為(f, f)以及步伐為(s, s)的窗口對其進行滑動取最大值,你也可以看一下文檔

 

·tf.nn.relu(Z1):計算 Z1 的ReLU函數,點這里閱讀文檔

 

·tf.contrib.layers.flatten(P):給定一個輸入P,此函數將會把每個樣本轉化成一維的向量,然后返回一個tensor變量,其維度為(batch_size,k).點這里閱讀文檔

 

 ·tf.contrib.layers.fully_connected(F, num_outputs):給定一個已經一維化了的輸入F,此函數將會返回一個由全連接層計算過后的輸出。點這里閱讀文檔

 

使用tf.contrib.layers.fully_connected(F, num_outputs)的時候,全連接層會自動初始化權值且在你訓練模型的時候它也會一直參與,所以當我們初始化參數的時候我們不需要專門去初始化它的權值。

我們實現前向傳播的時候,我們需要定義一下我們模型的大概樣子:

CONV2D -> RELU -> MAXPOOL -> CONV2D -> RELU -> MAXPOOL -> FLATTEN -> FULLYCONNECTED

我們具體實現的時候,我們需要使用以下的步驟和參數:

  • Conv2d : 步伐:1,填充方式:“SAME”
  • ReLU
  • Max pool : 過濾器大小:8x8,步伐:8x8,填充方式:“SAME”
  • Conv2d : 步伐:1,填充方式:“SAME”
  • ReLU
  • Max pool : 過濾器大小:4x4,步伐:4x4,填充方式:“SAME”
  • 一維化上一層的輸出
  • 全連接層(FC):使用沒有非線性激活函數的全連接層。這里不要調用SoftMax, 這將導致輸出層中有6個神經元,然后再傳遞到softmax。 在TensorFlow中,softmax和cost函數被集中到一個函數中,在計算成本時您將調用不同的函數。

 

 1 # GRADED FUNCTION: forward_propagation
 2 
 3 def forward_propagation(X, parameters):
 4     """
 5     Implements the forward propagation for the model:  實現前向傳播
 6     CONV2D -> RELU -> MAXPOOL -> CONV2D -> RELU -> MAXPOOL -> FLATTEN -> FULLYCONNECTED
 7     
 8     Arguments:
 9     X -- input dataset placeholder, of shape (input size, number of examples) 輸入數據的placeholder,維度為(輸入節點數量,樣本數量)
10     parameters -- python dictionary containing your parameters "W1", "W2"
11                   the shapes are given in initialize_parameters 包含了“W1”和“W2”的python字典。
12 
13     Returns:
14     Z3 -- the output of the last LINEAR unit 最后一個LINEAR節點的輸出
15     """
16     
17     # Retrieve the parameters from the dictionary "parameters" 
18     W1 = parameters['W1']
19     W2 = parameters['W2']
20     
21     ### START CODE HERE ###
22     # CONV2D: stride of 1, padding 'SAME'
23     Z1 = tf.nn.conv2d(X, W1, strides=[1, 1, 1, 1], padding = 'SAME')
24     # RELU
25     A1 = tf.nn.relu(Z1)
26     # MAXPOOL: window 8x8, sride 8, padding 'SAME'
27     P1 = tf.nn.max_pool(A1, ksize = [1, 8, 8, 1], strides = [1, 8, 8, 1], padding = 'SAME')
28     # CONV2D: filters W2, stride 1, padding 'SAME'
29     Z2 = tf.nn.conv2d(P1, W2, strides = [1, 1, 1, 1], padding = 'SAME')
30     # RELU
31     A2 = tf.nn.relu(Z2)
32     # MAXPOOL: window 4x4, stride 4, padding 'SAME'
33     P2 = tf.nn.max_pool(A2, ksize = [1, 4, 4, 1], strides = [1, 4, 4, 1], padding = 'SAME')
34     # FLATTEN 一維化,
35     P2 = tf.compat.v1.layers.flatten(P2)
36     
37     # FULLY-CONNECTED without non-linear activation function (not not call softmax).全連接層(FC):使用沒有非線性激活函數的全連接層
38     # 6 neurons in output layer. Hint: one of the arguments should be "activation_fn=None" 
39     Z3 = tf.compat.v1.layers.dense(P2, 6) #這里由於tf2.x刪除了contrib,暫時未找到替換的方法,因為跑出的答案不一樣
40 #     Z3 = tf.contrib.layers.fully_connected(P,6,activation_fn=None)
41     ### END CODE HERE ###
42 
43     return Z3
# GRADED FUNCTION: forward_propagation
# tf.reset_default_graph()
ops.reset_default_graph()

with tf.compat.v1.Session() as sess:
    np.random.seed(1)
    X, Y = create_placeholders(64, 64, 3, 6)
    parameters = initialize_parameters()
    Z3 = forward_propagation(X, parameters)
    
    init = tf.compat.v1.global_variables_initializer()
    sess.run(init)
    
    a = sess.run(Z3, {X: np.random.randn(2,64,64,3), Y: np.random.randn(2,6)})
    print("Z3 = " + str(a))
    
    sess.close()

執行結果:

 

 

1.3 - Compute cost 計算成本

我們要在這里實現計算成本的函數,下面的兩個函數是我們要用到的:

  • tf.nn.softmax_cross_entropy_with_logits(logits = Z3 , lables = Y):計算softmax的損失函數。這個函數既計算softmax的激活,也計算其損失,你可以閱讀手冊

  • tf.reduce_mean:計算的是平均值,使用它來計算所有樣本的損失來得到總成本。你可以閱讀手冊

現在,我們就來實現計算成本的函數::

 1 # GRADED FUNCTION: compute_cost 
 2 
 3 def compute_cost(Z3, Y):
 4     """
 5     Computes the cost 計算成本
 6     
 7     Arguments:
 8     Z3 -- output of forward propagation (output of the last LINEAR unit), of shape (6, number of examples)
 9     正向傳播最后一個LINEAR節點的輸出,維度為(6,樣本數)
10     Y -- "true" labels vector placeholder, same shape as Z3
11     標簽向量的placeholder,和Z3的維度相同
12     
13     Returns:
14     cost - Tensor of the cost function  代價函數的張量
15     """
16     
17     ### START CODE HERE ### (1 line of code)
18     cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits = Z3, labels = Y))
19     ### END CODE HERE ###
20     
21     return cost
# GRADED FUNCTION: compute_cost
# tf.reset_default_graph()
ops.reset_default_graph()

with tf.compat.v1.Session() as sess:
    np.random.seed(1)
    X, Y = create_placeholders(64, 64, 3, 6)
    parameters = initialize_parameters()
    Z3 = forward_propagation(X, parameters)
    cost = compute_cost(Z3, Y)
    init = tf.compat.v1.global_variables_initializer()
    sess.run(init)
    a = sess.run(cost, {X: np.random.randn(4,64,64,3), Y: np.random.randn(4,6)})
    print("cost = " + str(a))
    sess.close()

執行結果:

 

 

1.4 Model 構建模型

最后,我們已經實現了我們所有的函數,我們現在就可以實現我們的模型了。

我們之前在課程2就實現過random_mini_batches()這個函數,它返回的是一個mini-batches的列表。

在實現這個模型的時候我們要經歷以下步驟:

  • 創建占位符
  • 初始化參數
  • 前向傳播
  • 計算成本
  • 反向傳播
  • 創建優化器

最后,我們將創建一個session來運行模型。

  1 # GRADED FUNCTION: model
  2 
  3 def model(X_train, Y_train, X_test, Y_test, learning_rate = 0.009,
  4           num_epochs = 100, minibatch_size = 64, print_cost = True):
  5     """
  6     Implements a three-layer ConvNet in Tensorflow:     使用TensorFlow實現三層的卷積神經網絡
  7     CONV2D -> RELU -> MAXPOOL -> CONV2D -> RELU -> MAXPOOL -> FLATTEN -> FULLYCONNECTED
  8     
  9     Arguments:
 10     X_train -- training set, of shape (None, 64, 64, 3) 訓練數據,維度為(None, 64, 64, 3)
 11     Y_train -- test set, of shape (None, n_y = 6) 訓練數據對應的標簽,維度為(None, n_y = 6)
 12     X_test -- training set, of shape (None, 64, 64, 3) 測試數據,維度為(None, 64, 64, 3)
 13     Y_test -- test set, of shape (None, n_y = 6) 訓練數據對應的標簽,維度為(None, n_y = 6)
 14     learning_rate -- learning rate of the optimization 學習率
 15     num_epochs -- number of epochs of the optimization loop  遍歷整個數據集的次數
 16     minibatch_size -- size of a minibatch 每個小批量數據塊的大小
 17     print_cost -- True to print the cost every 100 epochs 是否打印成本值,每遍歷100次整個數據集打印一次
 18     
 19     Returns:
 20     train_accuracy -- real number, accuracy on the train set (X_train)  實數,訓練集的准確度
 21     test_accuracy -- real number, testing accuracy on the test set (X_test) 實數,測試集的准確度
 22     parameters -- parameters learnt by the model. They can then be used to predict. 學習后的參數,然后可以用作預測
 23     """
 24     
 25     ops.reset_default_graph()                         # to be able to rerun the model without overwriting tf variables 能夠重新運行模型而不覆蓋tf變量
 26     tf.random.set_seed(1)                             # to keep results consistent (tensorflow seed) 確保你的數據和我一樣
 27     seed = 3                                          # to keep results consistent (numpy seed) 指定numpy的隨機種子
 28     (m, n_H0, n_W0, n_C0) = X_train.shape             
 29     n_y = Y_train.shape[1]                            
 30     costs = []                                        # To keep track of the cost
 31     
 32     # Create Placeholders of the correct shape 為當前維度創建占位符
 33     ### START CODE HERE ### (1 line)
 34     X, Y = create_placeholders(n_H0, n_W0, n_C0, n_y)
 35     ### END CODE HERE ###
 36 
 37     # Initialize parameters 初始化參數
 38     ### START CODE HERE ### (1 line)
 39     parameters = initialize_parameters()
 40     ### END CODE HERE ###
 41     
 42     # Forward propagation: Build the forward propagation in the tensorflow graph 前向傳播:在TensorFlow圖中
 43     ### START CODE HERE ### (1 line)
 44     Z3 = forward_propagation(X, parameters)
 45     ### END CODE HERE ###
 46     
 47     # Cost function: Add cost function to tensorflow graph 計算成本
 48     ### START CODE HERE ### (1 line)
 49     cost = compute_cost(Z3, Y)
 50     ### END CODE HERE ###
 51     
 52     # Backpropagation: Define the tensorflow optimizer. Use an AdamOptimizer that minimizes the cost.
 53 #     反向傳播,由於框架已經實現了反向傳播,我們只需要選擇一個優化器就行了
 54     ### START CODE HERE ### (1 line)
 55     optimizer = tf.compat.v1.train.AdamOptimizer(learning_rate = learning_rate).minimize(cost)
 56     ### END CODE HERE ###
 57     
 58     # Initialize all the variables globally 全局初始化所有變量
 59     init = tf.compat.v1.global_variables_initializer()
 60      
 61     # Start the session to compute the tensorflow graph
 62     with tf.compat.v1.Session() as sess:
 63         
 64         # Run the initialization
 65         sess.run(init)
 66         
 67         # Do the training loop 開始遍歷數據集
 68         for epoch in range(num_epochs):
 69 
 70             minibatch_cost = 0.
 71             num_minibatches = int(m / minibatch_size) # number of minibatches of size minibatch_size in the train set
 72             seed = seed + 1
 73             minibatches = random_mini_batches(X_train, Y_train, minibatch_size, seed)
 74 
 75             for minibatch in minibatches:
 76 
 77                 # Select a minibatch 選擇一個數據塊
 78                 (minibatch_X, minibatch_Y) = minibatch
 79                 # IMPORTANT: The line that runs the graph on a minibatch.
 80                 # Run the session to execute the optimizer and the cost, the feedict should contain a minibatch for (X,Y).
 81 #                 最小化這個數據塊的成本
 82                 ### START CODE HERE ### (1 line)
 83                 _ , temp_cost = sess.run([optimizer, cost], feed_dict = {X:minibatch_X, Y:minibatch_Y})
 84                 ### END CODE HERE ###
 85 #                 累加數據塊的成本值
 86                 minibatch_cost += temp_cost / num_minibatches
 87                 
 88 
 89             # Print the cost every epoch
 90             if print_cost == True and epoch % 5 == 0:
 91                 print ("Cost after epoch %i: %f" % (epoch, minibatch_cost))
 92             if print_cost == True and epoch % 1 == 0:
 93                 costs.append(minibatch_cost)
 94         
 95         
 96         # plot the cost        數據處理完畢,繪制成本曲線
 97         plt.plot(np.squeeze(costs))
 98         plt.ylabel('cost')
 99         plt.xlabel('iterations (per tens)')
100         plt.title("Learning rate =" + str(learning_rate))
101         plt.show()
102 
103          #開始預測數據
104         # Calculate the correct predictions 計算當前的預測情況
105         predict_op = tf.argmax(Z3, 1)
106         correct_prediction = tf.equal(predict_op, tf.argmax(Y, 1))
107         
108         # Calculate accuracy on the test set 計算准確度
109         accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
110         print("corrent_prediction accuracy= " + str(accuracy))
111         
112         train_accuracy = accuracy.eval({X: X_train, Y: Y_train})
113         test_accuracy = accuracy.eval({X: X_test, Y: Y_test})
114         
115         print("Train Accuracy:", train_accuracy)
116         print("Test Accuracy:", test_accuracy)
117                 
118         return train_accuracy, test_accuracy, parameters
# GRADED FUNCTION: model
_, _, parameters = model(X_train, Y_train, X_test, Y_test)

執行結果:

 

 

 

 

恭喜你!您已經完成了任務,並建立了一個在測試集上具有80%准確率的識別手語的模型。如果您願意,可以進一步使用這個數據集。實際上,您可以通過花費更多時間調優超參數或使用正則化(因為這個模型顯然有很高的方差)來提高其准確性。

再一次,我為你的工作豎起大拇指!

 

 

 

 

 

 

 

 




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM