当前位置:   article > 正文

Python吴恩达深度学习作业10 -- 深度学习框架TensorFlow入门 + 完整图像识别实战_result = sess.run函数的使用

result = sess.run函数的使用

TensorFlow教程

到目前为止,你一直使用numpy来构建神经网络。现在,我们将引导你使用深度学习框架,改框架将使你可以更轻松地构建神经网络。TensorFlow,PaddlePaddle,Torch,Caffe,Keras等机器学习框架可以极大地加速你的机器学习开发速度。所有这些框架也都有好多文档,你应该随时阅读学习。在此笔记本中,你将学习在TensorFlow中执行以下操作:

  • 初始化变量
  • 创建自己的会话(session)
  • 训练算法
  • 实现神经网络

编程框架不仅可以缩短编码时间,而且有时可以进行优化以加快代码速度。

1 探索Tensorflow库

首先,导入库:

import math
import numpy as np
import h5py
import matplotlib.pyplot as plt
import tensorflow as tf

from tensorflow.python.framework import ops
from tf_utils import load_dataset, random_mini_batches, convert_to_one_hot, predict

# tf.disable_v2_behavior()
# tf.compat.v1.disable_eager_execution()
%matplotlib inline
np.random.seed(1)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

现在,你已经导入了库,我们将引导你完成其不同的应用程序。你将从一个示例开始:计算一个训练数据的损失。
l o s s = L ( y ^ , y ) = ( y ^ ( i ) − y ( i ) ) 2 (1) loss = \mathcal{L}(\hat{y}, y) = (\hat y^{(i)} - y^{(i)})^2 \tag{1} loss=L(y^,y)=(y^(i)y(i))2(1)

# tf.compat.v1.disable_eager_execution()

y_hat = tf.constant(36, name = 'y_hat') # 定义y_hat常数。设置为36。
y = tf.constant(39, name = 'y') # 定义y,设为39

loss = tf.Variable((y - y_hat) ** 2, name = 'loss') # 为损失创建一个变量

init = tf.global_variables_initializer() # 当init稍后运行时(session.run(init)),损失变量将被初始化并准备进行计算

with tf.Session() as session: # 创建一个会话并打印输出
    session.run(init) # 初始化变量
    print(session.run(loss)) # 打印的损失
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
9
  • 1

在TensorFlow中编写和运行程序包含以下步骤:

  1. 创建尚未执行的张量(变量)。
  2. 在这些张量之间编写操作。
  3. 初始化张量。
  4. 创建一个会话。
  5. 运行会话,这将运行你上面编写的操作。

因此,当我们为损失创建变量时,我们仅将损失定义为其他数量的函数,但没有验证其值。为了验证它,我们必须运行init = tf.global_variables_initializer()初始化损失变量,在最后一行中,我们终于能够验证loss的值并打印它。

现在让我们看一个简单的例子。运行下面的单元格:

a = tf.constant(2)
b = tf.constant(10)
c = tf.multiply(a, b)
print(c)
  • 1
  • 2
  • 3
  • 4
Tensor("Mul:0", shape=(), dtype=int32)
  • 1

不出所料,看不到结果20!而是得到一个张量,是一个不具有shape属性且类型为"int32"的张量。你所做的所有操作都已放入"计算图"中,但你尚未运行此计算。为了实际将两个数字相乘,必须创建一个会话并运行它。

sess = tf.Session()
print(sess.run(c))
  • 1
  • 2
20
  • 1

Great!总而言之,记住要初始化变量,创建一个会话并在该会话中运行操作。

接下来,你还必须了解placeholders(占位符)。占位符是一个对象,你只能稍后指定其值。

要为占位符指定值,你可以使用"feed dictionary"(feed_dict变量)传入值。在下面,我们为x创建了一个占位符,以允许我们稍后再允许会话时传递数字。

# 在feed_dict中更改x的值
x = tf.placeholder(tf.int64, name = 'x')
print(sess.run(2 * x, feed_dict = {x : 3}))
sess.close()
  • 1
  • 2
  • 3
  • 4
6
  • 1

当你首次定义x时,不必为其指定值。占位符只是一个变量,你在运行会话时才将数据分配给该变量。也就是说你在运行会话时向这些占位符“提供数据”。

当你指定计算所需的操作时,你在告诉TensorFlow如何构造计算图。计算图可以具有一些占位符,你将在稍后指定它们的值。最后,在运行会话时,你要告诉TensorFlow执行计算图。

1.1 线性函数

让我们开始此编程练习,计算以下方程式: Y = W X + b Y = WX + b Y=WX+b,其中 W W W X X X是随机矩阵, b b b是随机变量。

练习:计算 W X + b WX + b WX+b,其中 W W W X X X b b b是从随机正态分布中得到的, W W W的维度是(4, 3), X X X的维度为(3, 1), b b b的维度为(4, 1)。例如,下面是定义维度为(3, 1)的常量X的方法:

X = tf.constant(np.random.randn(3,1), name = "X") 
  • 1

你可能会发现以下函数很有用:

  • tf.matmul(…, …)进行矩阵乘法
  • tf.add(…, …)进行加法
  • np.random.randn(…)随机初始化
def linear_function():
    
    np.random.seed(1)
    
    X = tf.constant(np.random.randn(3, 1), name = "X")
    W = tf.constant(np.random.randn(4, 3), name = "W")
    b = tf.constant(np.random.randn(4,1), name = "b")  
    Y = tf.add(tf.matmul(W,X),b)
    
    # 使用tf.Session()创建会话,并在要计算的变量上使用sess.run(…)运行它
    sess = tf.Session()
    result = sess.run(Y)
    
    # 关闭会话
    sess.close()
    
    return result
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
'
运行
print( "result = " + str(linear_function()))
  • 1
result = [[-2.15657382]
 [ 2.95891446]
 [-1.08926781]
 [-0.84538042]]
  • 1
  • 2
  • 3
  • 4

1.2 计算Sigmoid

Great! 你刚刚实现了线性函数。TensorFlow提供了各种常用的神经网络函数,例如tf.sigmoidtf.softmax。对于本练习,让我们计算输入的sigmoid函数值。

你将使用占位符变量x进行此练习。在运行会话时,应该使用feed字典传入输入z。在本练习中,你必须:

  1. 创建一个占位符x;
  2. 使用tf.sigmoid定义计算Sigmoid所需的操作;
  3. 然后运行该会话

练习:实现下面的Sigmoid函数。你应该使用以下内容:

  • tf.placeholder(tf.float32, name = "...")
  • tf.sigmoid(...)
  • sess.run(..., feed_dict = {x: z})

注意,在tensorflow中创建和使用会话有两种典型的方法:

方法一

sess = tf.Session()  
# 运行变量初始化(如果需要),运行操作  
result = sess.run(..., feed_dict = {...})  
sess.close() # 关闭会话
  • 1
  • 2
  • 3
  • 4

方法二

with tf.Session() as sess:   
    # 运行变量初始化(如果需要),运行操作  
    result = sess.run(..., feed_dict = {...})  
    # 这将负责为您关闭会话
  • 1
  • 2
  • 3
  • 4
def sigmoid(z):
    # 为x创建一个占位符,命名为“x”。
    x = tf.placeholder(tf.float32, name = "x")
    
    # 计算sigmoid(x)
    sigmoid = tf.sigmoid(x)
    # 创建一个会话,并运行它。请使用上面解释的方法2。
    # 你应该使用feed_dict将z的值传递给x。
    with tf.Session() as sess:
        # 运行会话并调用输出“result”
        result = sess.run(sigmoid, feed_dict={x : z})# 这里的sigmoid函数等于tf.sigmoid(x)
        
    return result
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
'
运行
print ("sigmoid(0) = " + str(sigmoid(0)))
print ("sigmoid(12) = " + str(sigmoid(12)))
  • 1
  • 2
sigmoid(0) = 0.5
sigmoid(12) = 0.9999938
  • 1
  • 2

总而言之,你知道如何

  1. 创建占位符
  2. 指定运算相对应的计算图
  3. 创建会话
  4. 如果需要指定占位符变量的值,使用feed字典运行会话。

1.3 计算损失

你还可以使用内置函数来计算神经网络的损失。因此,对于 i = 1... m i = 1...m i=1...m,无需编写代码来将其为 a [ 2 ] ( i ) a^{[2](i)} a[2](i) y ( i ) y^{(i)} y(i)的函数来计算:
J = − 1 m ∑ i = 1 m ( y ( i ) log ⁡ a [ 2 ] ( i ) + ( 1 − y ( i ) ) log ⁡ ( 1 − a [ 2 ] ( i ) ) ) (2) J = - \frac{1}{m} \sum_{i = 1}^m \large ( \small y^{(i)} \log a^{ [2] (i)} + (1-y^{(i)})\log (1-a^{ [2] (i)} )\large )\small\tag{2} J=m1i=1m(y(i)loga[2](i)+(1y(i))log(1a[2](i)))(2)
你可以使用tensorflow的一行代码中做到这一点!

练习:实现交叉熵损失,你将使用的函数是:

  • tf.nn.sigmoid_cross_entropy_with_logits(logits = ..., labels = ...)

你的代码应该输入z,计算出sigmoid(得到a),然后计算出交叉熵损失 J J J,所有这些操作都可以通过调用tf.nn.sigmoid_cross_entropy_with_logits来完成:
− 1 m ∑ i = 1 m ( y ( i ) log ⁡ σ ( z [ 2 ] ( i ) ) + ( 1 − y ( i ) ) log ⁡ ( 1 − σ ( z [ 2 ] ( i ) ) ) (2) - \frac{1}{m} \sum_{i = 1}^m \large ( \small y^{(i)} \log \sigma(z^{[2](i)}) + (1-y^{(i)})\log (1-\sigma(z^{[2](i)})\large )\small\tag{2} m1i=1m(y(i)logσ(z[2](i))+(1y(i))log(1σ(z[2](i)))(2)

# 计算损失
def cost(logits, labels):
    """
    参数:
    logits -- 包含z的向量,最后一个线性单位的输出(在最终sigmoid函数激活之前)
    labels -- 标签向量y(1或0)
    
    注意:我们在课堂上所说的z和y分别被称为logits和labels
    在TensorFlow文档中。所以logits输入z, labels输入y。
    
    """
    # 为“logits”(z)和“labels”(y)创建占位符
    z = tf.placeholder(tf.float32, name = "z")
    y = tf.placeholder(tf.float32, name = "y")
    
    # 使用损失函数
    cost = tf.nn.sigmoid_cross_entropy_with_logits(logits = z, labels = y)
    
    # 创建会话,使用方法1
    sess = tf.Session()
    
    # 运行会话
    cost = sess.run(cost, feed_dict = {z:logits, y:labels})
    
    # 关闭会话
    sess.close()
    
    return cost
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
'
运行
logits = sigmoid(np.array([0.2,0.4,0.7,0.9]))
cost = cost(logits, np.array([0,0,1,1]))
print ("cost = " + str(cost))
  • 1
  • 2
  • 3
cost = [1.0053872  1.0366408  0.41385433 0.39956617]
  • 1

1.4 使用独热(One Hot)编码

在深度学习中,很多时候你会得到一个y向量,其数字范围从0到C-1,其中C是类的数量。例如C是4,那么你可能具有以下y向量,你将需要按以下方式对其进行转换:

在这里插入图片描述

这称为独热编码,因为在转换后的表示形式中,每一列中的一个元素正好是“hot”(设为1)。要以numpy格式进行此转换,你可能需要编写几行代码。在tensorflow中,你可以只使用一行代码:

  • tf.one_hot(labels, depth, axis)

练习:试下以下函数,以获取一个标签向量和 C C C类的总数,并返回一个独热编码。使用tf.one_hot()来做到这一点。

def one_hot_matrix(labels, C):
    """
    创建一个矩阵,其中第i行对应第i个类号,第j列对应第j个训练示例。如果例子j有一个标签i,那么条目(i,j)就是1。                 
    参数:
    labels -- 包含标签的向量 
    C -- 类的数量,热度维度的深度
    """
    C =tf.constant(C, name = "C")
    
    one_hot_matrix = tf.one_hot(labels, C, axis=0)
    
    sess = tf.Session() 
    
    one_hot = sess.run(one_hot_matrix)
    
    sess.close()
    
    return one_hot
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
'
运行
labels = np.array([1,2,3,0,2,1])
one_hot = one_hot_matrix(labels, C = 4)
print ("one_hot = " + str(one_hot))
  • 1
  • 2
  • 3
one_hot = [[0. 0. 0. 1. 0. 0.]
 [1. 0. 0. 0. 0. 1.]
 [0. 1. 0. 0. 1. 0.]
 [0. 0. 1. 0. 0. 0.]]
  • 1
  • 2
  • 3
  • 4

1.5 使用0和1初始化

现在,你将学习如何初始化0和1的向量。 你将要调用的函数是tf.ones()。要使用零初始化,可以改用tf.zeros()。这些函数采用一个维度,并分别返回一个包含0和1的维度数组。

练习:实现以下函数以获取维度并返回维度数组。

  • tf.ones(shape)
def ones(shape):
    ones = tf.ones(shape)
    
    sess = tf.Session()
    
    ones = sess.run(ones)
    
    sess.close()
    
    return ones
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
'
运行
print ("ones = " + str(ones([3])))
  • 1
ones = [1. 1. 1.]
  • 1

使用Tensorflow构建你的第一个神经网络

在这一部分作业中,你将使用tensorflow构建神经网络。请记住,实现tensorflow模型包含两个部分:

  • 创建计算图
  • 运行计算图

让我们深入研究你要解决的问题!

2.0 问题陈述:SIGNS 数据集

一个下午,我们决定和一些朋友一起用计算机来解密手语。我们花了几个小时在白墙前拍照,并提出了以下数据集。现在,你的工作就是构建一种算法,以帮助语音障碍者和不懂手语的人的交流。

  • 训练集:1080张图片(64 x 64像素)的手势表示从0到5的数字(每个数字180张图片)。
  • 测试集:120张图片(64 x 64像素)的手势表示从0到5的数字(每个数字20张图片)。

请注意,这是SIGNS数据集的子集。完整的数据集包含更多的手势。

这是每个数字的示例,以及如何解释标签的方式。这些是原始图片,然后我们将图像分辨率降低到64 x 64像素。
在这里插入图片描述

运行以下代码以加载数据集。

# 加载数据集
X_train_orig, Y_train_orig, X_test_orig, Y_test_orig, classes = load_dataset()
  • 1
  • 2

更改下面的索引并运行单元格以可视化数据集中的一些示例。

# 图片的例子
index = 0
plt.imshow(X_train_orig[index])
print ("y = " + str(np.squeeze(Y_train_orig[:, index])))
  • 1
  • 2
  • 3
  • 4
y = 5
  • 1

在这里插入图片描述

通常先将图像数据集展平,然后除以255以对其进行归一化。最重要的是将每个标签转换为一个独热向量,如图1所示。运行下面的单元格即可转化。

# 将训练和测试图像压平
X_train_flatten = X_train_orig.reshape(X_train_orig.shape[0], -1).T
X_test_flatten = X_test_orig.reshape(X_test_orig.shape[0], -1).T
# 归一化图像向量
X_train = X_train_flatten/255.
X_test = X_test_flatten/255.
# 将训练和测试标签转换为一个独热矩阵
Y_train = convert_to_one_hot(Y_train_orig, 6)
Y_test = convert_to_one_hot(Y_test_orig, 6)

print ("number of training examples = " + str(X_train.shape[1]))
print ("number of test examples = " + str(X_test.shape[1]))
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))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
number of training examples = 1080
number of test examples = 120
X_train shape: (12288, 1080)
Y_train shape: (6, 1080)
X_test shape: (12288, 120)
Y_test shape: (6, 120)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

注意 12288 = 64 × 64 × 3 12288 = 64 \times 64 \times 3 12288=64×64×3,每个图像均为正方形,64 x 64像素,其中3为RGB颜色。请确保理解这些数据的维度意义,然后再继续。

你的目标是建立一种能够高精度识别符号的算法。为此,你将构建一个tensorflow模型,该模型与你先前在numpy中为猫识别构建的tensorflow模型几乎相同(但现在使用softmax输出)。这是将numpy实现的模型与tensorflow进行比较的好机会。

模型为LINEAR-> RELU-> LINEAR-> RELU-> LINEAR-> SOFTMAX 。 SIGMOID输出层已转换为SOFTMAX。SOFTMAX层将SIGMOID应用到两个以上的类。

2.1 创建占位符

你的第一个任务是为X和X创建占位符,方便你以后再运行会话时传递训练数据。

练习:实现以下函数以在tensorflow中创建占位符。

def create_placeholders(n_x, n_y):
    """
    创建tensorflow会话的占位符。
    参数:
        n_x -- 标量,图像向量的大小(num_px * num_px = 64 * 64 * 3 = 12288)
        n_y -- 标量,类的数量(从0到5,因此-> 6)
    """
    X = tf.placeholder(shape = [n_x, None], dtype = tf.float32)
    Y = tf.placeholder(shape = [n_y, None], dtype = tf.float32)
    
    return X, Y
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
'
运行
X, Y = create_placeholders(12288, 6)
print ("X = " + str(X))
print ("Y = " + str(Y))
  • 1
  • 2
  • 3
X = Tensor("Placeholder:0", shape=(12288, ?), dtype=float32)
Y = Tensor("Placeholder_1:0", shape=(6, ?), dtype=float32)
  • 1
  • 2

2.2 初始化参数

你的第二个任务是初始化tensorflow中的参数。

练习:实现以下函数以初始化tensorflow中的参数。使用权重的Xavier初始化和偏差的零初始化。维度如下,对于W1和b1,你可以使用:

W1 = tf.get_variable("W1", [25,12288], initializer = tf.contrib.layers.xavier_initializer(seed = 1))  
b1 = tf.get_variable("b1", [25,1], initializer = tf.zeros_initializer())
  • 1
  • 2

请使用seed = 1来确保你的结果与我们的结果相符。

def initialize_parameters():
    """
    使用tensorflow初始化参数来构建神经网络。形状:
                        W1 : [25, 12288]
                        b1 : [25, 1]
                        W2 : [12, 25]
                        b2 : [12, 1]
                        W3 : [6, 12]
                        b3 : [6, 1]
    """
    tf.set_random_seed(1)
    
    W1 = tf.get_variable("W1", [25,12288], initializer = tf.contrib.layers.xavier_initializer(seed = 1))
    b1 = tf.get_variable("b1", [25,1], initializer = tf.zeros_initializer())  
    W2 = tf.get_variable("W2", [12,25], initializer = tf.contrib.layers.xavier_initializer(seed = 1))  
    b2 = tf.get_variable("b2", [12,1], initializer = tf.zeros_initializer())  
    W3 = tf.get_variable("W3", [6,12], initializer = tf.contrib.layers.xavier_initializer(seed = 1))  
    b3 = tf.get_variable("b3", [6,1], initializer = tf.zeros_initializer()) 
    
    
    parameters = {"W1": W1,
                  "b1": b1,
                  "W2": W2,
                  "b2": b2,
                  "W3": W3,
                  "b3": b3}
    
    return parameters
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
'
运行
tf.reset_default_graph()
with tf.Session() as sess:
    parameters = initialize_parameters()
    print("W1 = " + str(parameters["W1"]))
    print("b1 = " + str(parameters["b1"]))
    print("W2 = " + str(parameters["W2"]))
    print("b2 = " + str(parameters["b2"]))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
W1 = <tf.Variable 'W1:0' shape=(25, 12288) dtype=float32_ref>
b1 = <tf.Variable 'b1:0' shape=(25, 1) dtype=float32_ref>
W2 = <tf.Variable 'W2:0' shape=(12, 25) dtype=float32_ref>
b2 = <tf.Variable 'b2:0' shape=(12, 1) dtype=float32_ref>
  • 1
  • 2
  • 3
  • 4

2.3 Tensorflow中的正向传播

你现在将在tensorflow中实现正向传播模块。该函数将接收参数字典,并将完成正向传递。你将使用的函数是:

  • tf.add(...,...)进行加法
  • f.matmul(...,...)进行矩阵乘法
  • tf.nn.relu(...)以应用ReLU激活

问题:实现神经网络的正向传递。我们为你注释了numpy等式,以便你可以将tensorflow实现与numpy实现进行比较。重要的是要注意,前向传播在z3处停止。原因是在tensorflow中,最后的线性层输出作为计算损失函数的输入。因此,你不需要a3!

def forward_propagation(X, parameters):
    
    W1 = parameters['W1']
    b1 = parameters['b1']
    W2 = parameters['W2']
    b2 = parameters['b2']
    W3 = parameters['W3']
    b3 = parameters['b3']
    
    Z1 = tf.add(tf.matmul(W1,X),b1)  # Z1 = np.dot(W1, X) + b1  
    A1 = tf.nn.relu(Z1)              # A1 = relu(Z1)  
    Z2 = tf.add(tf.matmul(W2,A1),b2) # Z2 = np.dot(W2, a1) + b2  
    A2 = tf.nn.relu(Z2)              # A2 = relu(Z2)  
    Z3 = tf.add(tf.matmul(W3,A2),b3) # Z3 = np.dot(W3,Z2) + b3 
    
    return Z3
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
'
运行
tf.reset_default_graph()

with tf.Session() as sess:
    X, Y = create_placeholders(12288, 6)
    parameters = initialize_parameters()
    Z3 = forward_propagation(X, parameters)
    print("Z3 = " + str(Z3))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
Z3 = Tensor("Add_2:0", shape=(6, ?), dtype=float32)
  • 1

你可能已经注意到,正向传播不会输出任何缓存。当我们开始进行传播时,你将在下面理解为什么。

2.4 计算损失

如前所述,使用以下方法很容易计算损失:

tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits = ..., labels = ...))
  • 1

问题:实现以下损失函数。

  • 重要的是要知道tf.nn.softmax_cross_entropy_with_logits的"logits"和"labels"输入应具有一样的维度(数据数,类别数)。 因此,我们为你转换了Z3和Y。
  • 此外,tf.reduce_mean是对所以数据进行求和。
def compute_cost(Z3, Y):
    logits = tf.transpose(Z3)
    labels = tf.transpose(Y)
    
    cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits = logits, labels = labels))
    
    return cost
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
'
运行
tf.reset_default_graph()

with tf.Session() as sess:
    X, Y = create_placeholders(12288, 6)
    parameters = initialize_parameters()
    Z3 = forward_propagation(X, parameters)
    cost = compute_cost(Z3, Y)
    print("cost = " + str(cost))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
cost = Tensor("Mean:0", shape=(), dtype=float32)
  • 1

2.5 反向传播和参数更新

所有反向传播和参数更新均可使用1行代码完成,将这部分合并到模型中非常容易。

计算损失函数之后,你将创建一个"optimizer"对象。运行tf.session时,必须与损失一起调用此对象。调用时,它将使用所选方法和学习率对给定的损失执行优化。

例如,对于梯度下降,优化器将是:

optimizer = tf.train.GradientDescentOptimizer(learning_rate = learning_rate).minimize(cost)
  • 1

要进行优化,你可以执行以下操作:

_ , c = sess.run([optimizer, cost], feed_dict={X: minibatch_X, Y: minibatch_Y})
  • 1

通过相反顺序的tensorflow图来计算反向传播。从损失到输入。

注意编码时,我们经常使用_作为“throwaway”变量来存储以后不再需要使用的值。这里_代表了我们不需要的optimizer的评估值(而 c 代表了 cost变量的值)。

2.6 建立模型

现在,将它们组合在一起!

练习:调用之前实现的函数构建完整模型。

def model(X_train, Y_train, X_test, Y_test, learning_rate = 0.0001,
          num_epochs = 1500, minibatch_size = 32, print_cost = True):
    
    ops.reset_default_graph() # 能够在不覆盖tf变量的情况下重新运行模型
    tf.set_random_seed(1) # 为了保持一致的结果
    seed = 3 # 为了保持一致的结果
    (n_x, m) = X_train.shape # (n_x:输入大小,m:训练集中的样本数量)
    n_y = Y_train.shape[0] # n_y:输出大小
    costs = [] # 成本
    
    # Step1:创建形状占位符(n_x, n_y)
    X, Y = create_placeholders(n_x, n_y)
    
    # Step2:初始化参数
    parameters = initialize_parameters()
    
    # Step3:前向传播:在tensorflow图中构建前向传播
    Z3 = forward_propagation(X, parameters)
    
    # Step4:代价函数:将代价函数添加到tensorflow图中
    cost = compute_cost(Z3, Y)
    
    # Step5:反向传播:定义tensorflow优化器。使用一个AdamOptimizer。
    optimizer = tf.train.AdamOptimizer(learning_rate = learning_rate).minimize(cost)
    
    # Step6:初始化所有变量
    init = tf.global_variables_initializer()
    
    # Step7:启动会话来计算tensorflow图
    with tf.Session() as sess:
        
        # Step8:运行初始化
        sess.run(init)
        
        # Step9:进行循环训练
        for epoch in range(num_epochs):
            
            epoch_cost = 0.  # 定义与epoch相关的成本
            num_minibatches = int(m / minibatch_size) # 在序列集中大小为minibatch_size的小批量的数量
            seed = seed + 1
            minibatches = random_mini_batches(X_train, Y_train, minibatch_size, seed)
            
            for minibatch in minibatches:
                
                # 选择一个minibatch
                (minibatch_X, minibatch_Y) = minibatch  
                
                # 运行会话来执行“优化器”和“成本”,feedict应该包含一个小批量(X,Y)。
                _ , minibatch_cost = sess.run([optimizer, cost], feed_dict={X: minibatch_X, Y: minibatch_Y})   
                
                epoch_cost += minibatch_cost / num_minibatches
            
            if print_cost == True and epoch % 100 == 0:  
                print ("Cost after epoch %i: %f" % (epoch, epoch_cost))  
            if print_cost == True and epoch % 5 == 0:  
                costs.append(epoch_cost)  
                
        plt.plot(np.squeeze(costs))  
        plt.ylabel('cost')  
        plt.xlabel('iterations (per tens)')  
        plt.title("Learning rate =" + str(learning_rate))  
        plt.show()
        
        # 让我们将参数保存在一个变量中
        parameters = sess.run(parameters)  
        print ("Parameters have been trained!")
        
        # 计算出正确的预测
        correct_prediction = tf.equal(tf.argmax(Z3), tf.argmax(Y))  
        
        # 计算测试集上的精度
        accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
        
        print ("Train Accuracy:", accuracy.eval({X: X_train, Y: Y_train}))  
        print ("Test Accuracy:", accuracy.eval({X: X_test, Y: Y_test}))  
          
        return parameters  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
'
运行

运行以下单元格来训练你的模型!在我们的机器上大约需要5分钟。 你的“100epoch后的损失”应为1.016458。如果不是,请不要浪费时间。单击笔记本电脑上方栏中的正方形(⬛),以中断训练,然后尝试更正你的代码。如果损失正确,请稍等片刻,然后在5分钟内回来!

parameters = model(X_train, Y_train, X_test, Y_test)
  • 1
Cost after epoch 0: 1.855702
Cost after epoch 100: 1.017255
Cost after epoch 200: 0.733184
Cost after epoch 300: 0.573071
Cost after epoch 400: 0.468573
Cost after epoch 500: 0.381228
Cost after epoch 600: 0.313815
Cost after epoch 700: 0.253624
Cost after epoch 800: 0.203897
Cost after epoch 900: 0.166472
Cost after epoch 1000: 0.146867
Cost after epoch 1100: 0.107288
Cost after epoch 1200: 0.086557
Cost after epoch 1300: 0.059360
Cost after epoch 1400: 0.052275
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

在这里插入图片描述

Parameters have been trained!
Train Accuracy: 0.9990741
Test Accuracy: 0.725
  • 1
  • 2
  • 3

评价

  • 你的模型足够强大,可以很好地拟合训练集。但是,鉴于训练和测试精度之间的差异,你可以尝试添加L2或dropout正则化以减少过拟合。
  • 将会话视为训练模型的代码块。每次你在小批次上运行会话时,它都会训练参数。总的来说,你已经运行了该会话多次(1500个epoch),直到获得训练有素的参数为止。

2.7 使用自己的图像进行测试

现在,你可以拍张手的照片并查看模型的输出。要做到这一点:

  1. 单击此笔记本上部栏中的 “File” ,然后单击"Open"以在Coursera Hub上运行。
  2. 将图像添加到Jupyter Notebook的目录中,在 “images” 文件夹中
  3. 在以下代码中写下你的图片名称
  4. 运行代码,然后检查算法是否正确!
import scipy
from PIL import Image
from scipy import ndimage

## START CODE HERE ## (PUT YOUR IMAGE NAME) 
my_image = "thumbs_up.jpg"
## END CODE HERE ##

# 我们会根据你的算法对你的图像进行预处理。
fname = my_image
image = np.array(ndimage.imread(fname, flatten=False))
my_image = scipy.misc.imresize(image, size=(64,64)).reshape((1, 64*64*3)).T
my_image_prediction = predict(my_image, parameters)

plt.imshow(image)
print("Your algorithm predicts: y = " + str(np.squeeze(my_image_prediction)))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
Your algorithm predicts: y = 3
  • 1

在这里插入图片描述

尽管你看到算法似乎对它进行了错误分类,但你确实值得“竖起大拇指”。原因是训练集不包含任何“竖起大拇指”,因此模型不知道如何处理! 我们称其为“数据不平衡”,它是下一章“构建机器学习项目”中的学习课程之一。

你应该记住:

  • Tensorflow是深度学习中经常使用的编程框架
  • Tensorflow中的两个主要对象类别是张量和运算符。
  • 在Tensorflow中进行编码时,你必须执行以下步骤:
    • 创建一个包含张量(变量,占位符…)和操作(tf.matmul,tf.add,…)的计算图
    • 创建会话
    • 初始化会话
    • 运行会话以执行计算图
  • 你可以像在model()中看到的那样多次执行计算图
  • 在“优化器”对象上运行会话时,将自动完成反向传播和优化。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/煮酒与君饮/article/detail/836911
推荐阅读
相关标签
  

闽ICP备14008679号