一、TensorFlow搭建深层神经网络DNN框架

1、初始化变量
2、构建session会话
3、训练算法
4、实现神经网络

框架不仅可以缩短编码时间,而且有时还可以实现加速代码的优化。

文件tf_utils.py的代码,在主文件中需要导入相应的包:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:ZhengzhengLiu

import math
import h5py
import numpy as np
import tensorflow as tf

#加载数据集
def load_datasets():
    train_dataset = h5py.File('cat_datasets/train_signs.h5', "r")
    train_set_x_orig = np.array(train_dataset["train_set_x"][:])  # your train set features
    train_set_y_orig = np.array(train_dataset["train_set_y"][:])  # your train set labels

    test_dataset = h5py.File('cat_datasets/test_signs.h5', "r")
    test_set_x_orig = np.array(test_dataset["test_set_x"][:])  # your test set features
    test_set_y_orig = np.array(test_dataset["test_set_y"][:])  # your test set labels

    classes = np.array(test_dataset["list_classes"][:])  # the list of classes

    train_set_y_orig = train_set_y_orig.reshape((1, train_set_y_orig.shape[0]))
    test_set_y_orig = test_set_y_orig.reshape((1, test_set_y_orig.shape[0]))

    return train_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig, classes


def random_mini_batches(X, Y, mini_batch_size=64, seed=0):
    """
    Creates a list of random minibatches from (X, Y)

    Arguments:
    X -- input data, of shape (input size, number of examples)
    Y -- true "label" vector (containing 0 if cat, 1 if non-cat), of shape (1, number of examples)
    mini_batch_size - size of the mini-batches, integer
    seed -- this is only for the purpose of grading, so that you're "random minibatches are the same as ours.

    Returns:
    mini_batches -- list of synchronous (mini_batch_X, mini_batch_Y)
    """

    m = X.shape[1]  # number of training examples
    mini_batches = []
    np.random.seed(seed)

    # Step 1: Shuffle (X, Y)
    permutation = list(np.random.permutation(m))
    shuffled_X = X[:, permutation]
    shuffled_Y = Y[:, permutation].reshape((Y.shape[0], m))

    # Step 2: Partition (shuffled_X, shuffled_Y). Minus the end case.
    num_complete_minibatches = math.floor(
        m / mini_batch_size)  # number of mini batches of size mini_batch_size in your partitionning
    for k in range(0, num_complete_minibatches):
        mini_batch_X = shuffled_X[:, k * mini_batch_size: k * mini_batch_size + mini_batch_size]
        mini_batch_Y = shuffled_Y[:, k * mini_batch_size: k * mini_batch_size + mini_batch_size]
        mini_batch = (mini_batch_X, mini_batch_Y)
        mini_batches.append(mini_batch)

    # Handling the end case (last mini-batch < mini_batch_size)
    if m % mini_batch_size != 0:
        mini_batch_X = shuffled_X[:, num_complete_minibatches * mini_batch_size: m]
        mini_batch_Y = shuffled_Y[:, num_complete_minibatches * mini_batch_size: m]
        mini_batch = (mini_batch_X, mini_batch_Y)
        mini_batches.append(mini_batch)

    return mini_batches


def convert_to_one_hot(Y, C):
    Y = np.eye(C)[Y.reshape(-1)].T      #np.eye 生成对角矩阵
    return Y


def predict(X, parameters):
    W1 = tf.convert_to_tensor(parameters["W1"])
    b1 = tf.convert_to_tensor(parameters["b1"])
    W2 = tf.convert_to_tensor(parameters["W2"])
    b2 = tf.convert_to_tensor(parameters["b2"])
    W3 = tf.convert_to_tensor(parameters["W3"])
    b3 = tf.convert_to_tensor(parameters["b3"])

    params = {"W1": W1,
              "b1": b1,
              "W2": W2,
              "b2": b2,
              "W3": W3,
              "b3": b3}

    x = tf.placeholder("float", [12288, 1])

    z3 = forward_propagation_for_predict(x, params)
    p = tf.argmax(z3)

    sess = tf.Session()
    prediction = sess.run(p, feed_dict={x: X})

    return prediction


def forward_propagation_for_predict(X, parameters):
    """
    Implements the forward propagation for the model: LINEAR -> RELU -> LINEAR -> RELU -> LINEAR -> SOFTMAX

    Arguments:
    X -- input dataset placeholder, of shape (input size, number of examples)
    parameters -- python dictionary containing your parameters "W1", "b1", "W2", "b2", "W3", "b3"
                  the shapes are given in initialize_parameters

    Returns:
    Z3 -- the output of the last LINEAR unit
    """

    # Retrieve the parameters from the dictionary "parameters"
    W1 = parameters['W1']
    b1 = parameters['b1']
    W2 = parameters['W2']
    b2 = parameters['b2']
    W3 = parameters['W3']
    b3 = parameters['b3']
    # Numpy Equivalents:
    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

二、TensorFlow库的小应用

1、计算一个样本的损失函数,公式如下:


#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:ZhengzhengLiu

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_datasets,random_mini_batch,convert_to_one_hot,predict

np.random.seed(1)

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")  #设置loss为变量

#当init在后边运行(session.run(init)时,变量loss被初始化并准备好计算。
init = tf.global_variables_initializer()

with tf.Session() as session:   #创建session会话并打印输出
    session.run(init)           #初始化变量
    print(session.run(loss))    #打印loss损失

#运行结果:
9
小结:在TensorFlow中编写和运行程序有以下的步骤:

初始化变量,创建会话并在会话内运行操作

(1)创建还没有未执行的张量(变量)。
(2)写入张量的操作。图中的节点被称为:opearation,一个op获得一个或多个张量执行计算。
(3)初始化张量。
(4)创建会话。
(5)运行会话。运行上面写入的操作。

因此,当我们为loss创建一个变量时,只是简单的将loss当做一个函数或其他的量,并没有计算它的值。

要计算loss,需要执行init=tf.global_variables_initializer()这初始化了loss变量,

在最后一行执行计算并打印出了loss的值。

2、占位符——placeholder

占位符是一个对象,其值只能在后面指定。指定一个占位符的值,你可以通过值用

 "feed dictionary" (feed_dict variable).下面的案例中创建了一个占位符(placeholder)x,

并在后边运行会话session时通过feed_dict指定一个值。代码如下:

sess = tf.Session()
x = tf.placeholder(tf.int64,name="any_thing")
print(sess.run(2*x,feed_dict={x:3}))
sess.close()

#运行结果:
6
小结:当第一次定义x时,不必为它指定一个值。占位符只是一个简单的变量, 将在后面

运行会话时分配数据。我们称:在运行会话session时,给占位符喂数据(feed data)。

当你指定一个计算所需的operations(操作)节点,告诉TensorFlow如何构建一个计算图。

计算图可以有一些占位符在后面指定值。最后,当运行会话,告诉TensorFlow要执行计算图。

3、线性函数


其中,W和X是随机生成的矩阵,b是随机生成的向量。

举例:W 的维度为 (4, 3), X维度为(3,1) b 的维度为 (4,1),定义X为一个维度为(3,1)的常量,代码如下:

还需要用到的函数及其作用如下:

  • tf.matmul(..., ...) ——矩阵相乘,左矩阵列数等于右矩阵行数
  • tf.add(..., ...) ——加法
  • np.random.randn(...)——随机初始化
#线性函数

def linear_function():
    """
    初始化 W 为一个随机的张量,维度为(4,3)
    初始化 X 为一个随机的张量,维度为(3,1)
    初始化 b 为一个随机的张量,维度为(4,1)

    Returns:
    result -- 执行session会话计算 Y = WX + b
    """
    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,name="Y")

    sess = tf.Session()
    result = sess.run(Y)
    sess.close()

    return result

print("result = "+str(linear_function()))

#运行结果:
result = [[-2.15657382]
 [ 2.95891446]
 [-1.08926781]
 [-0.84538042]]
4、计算sigmoid函数值

tensorflow提供了多种常用的神经网络的函数,如:tf.sigmoid  tf.softmax。

下面来计算输入sigmoid函数后的值。需要用到一个placeholder占位符x,在执行会话时,

通过输入值 z 使用feed_dict 给占位符x喂数据。

即:(1)创建占位符x。(2)定义operation操作节点通过tf.sigmoid计算sigmoid。(3)执行会话。


在tensorflow中有两种方式创建和使用session:



#sigmoid函数
def sigmoid(z):
    """
    计算z的sigmoid函数值
    param :
    z -- 输入值,可以是标量或向量

    return:
    result -- z的sigmoid值
    """
    #创建一个占位符placeholder  x
    x = tf.placeholder(tf.float32,name="x")

    #计算x的sigmoid值
    sigmoid = tf.sigmoid(x,name="sigmoid")

    #创建并执行session会话
    with tf.Session() as session:
        result = session.run(sigmoid,feed_dict={x:z})

    return result

print("sigmoid(0) = "+str(sigmoid(0)))
print("sigmoid(12) = "+str(sigmoid(10)))

#运行结果:
sigmoid(0) = 0.5
sigmoid(12) = 0.999955
5、计算目标函数


可以使用内置函数计算神经网络的成本/目标函数。因此,不需要编写代码来计算这个函数。
在tensorflow中只需要一行代码就可以实现:

注意:tensorflow中,分别叫 z 和 y 为 logits 和 labels,即:logits喂给z,labels喂给y

需要输入z,计算sigmoid得到a,然后计算交叉熵目标函数J,只要一行代码就可实现下面操作:


#计算目标函数cost
def cost(logits,labels):
    """
    计算目标函数用sigmoid交叉熵
    param :
    logits -- 含z的向量,最后一个线性单元的输出,在最后一个sigmoid激活之前
    labels -- 标签向量y(1 or 0)
    注意:在tensorflow中,分别叫 z 和 y 为 logits 和 labels,即:logits喂给z,labels喂给y

    return:
    cost  -- 执行session会话计算cost
    """
    #为"logits" (z) 和 "labels" (y)创建占位符
    z = tf.placeholder(tf.float32,name="z")
    y = tf.placeholder(tf.float32,name="y")

    #应用cost函数
    cost = tf.nn.sigmoid_cross_entropy_with_logits(logits=z,labels=y,name="cost")

    #创建并执行session会话
    with tf.Session() as session:
        cost = session.run(cost,feed_dict={z:logits,y:labels})

    return cost

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

#运行结果:
cost = [ 1.00538719  1.03664076  0.41385433  0.39956617]
6、独热编码 one-hot encoding

很多时候,深度学习中会有y向量在数字范围在0至C-1,其中,C是类别的数目,如果C是4,y向量转换如下图所示:


这叫做 独热编码(one hot encoding),因为在转换中,每个列中只有一个元素是“热”(意思是设置为1)。

在tensorflow中实现独热编码只需要下面一句代码:


#独热编码
def one_hot_matrix(labels,C):
    """
    创建一个矩阵的第i行对应于第i类别,第j列对应第j个训练样本。
    如果样本j有一个标签i,那么(i,j)将为1。
    param :
    labels -- 包含标签的向量
    C -- 分类的类别数目,独热编码的depth深度

    return:
    one_ hot -- 独热编码的矩阵
    """
    #创建一个常量 C (depth)
    C = tf.constant(C,name="C")

    #使用 tf.one_hot 在第0轴
    one_hot_matrix = tf.one_hot(labels,C,on_value=1,off_value=0,axis=0,name="one_hot_matrix")

    #创建并执行session会话
    with tf.Session() as session:
        one_hot = session.run(one_hot_matrix)

    return one_hot

lables = np.array([1,2,3,0,2,1])
one_hot = one_hot_matrix(lables,C=4)
print("one_hot = "+str(one_hot))

#运行结果:
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]]
7、初始化零阵和单位阵

在tensorflow中创建零阵和单位阵,使用以下的代码:


该函数输入参数为:维度形状,分别返回相应维度形状的零矩阵和单位阵。

#创建单位阵
def ones(shape):
    """
    创建维度为shape的单位阵
    param :
    shape -- 想要创建的数组的维度形状

    return:
    ones -- 定义维度形状的单位阵
    """
    ones = tf.ones(shape,name="ones")

    # 创建并执行session会话
    with tf.Session() as session:
        ones = session.run(ones)

    return ones

print("ones = "+str(ones((1,3))))

#运行结果:
ones = [[ 1.  1.  1.]]
三、在tensorflow上构建神经网络

在tensorflow中执行的两个部分:(1)创建计算图。(2)运行图。

(一)数据集介绍——SIGNS Datasets

教电脑破译手语,在白色的墙壁前拍照,得到以下数据集。

现在的任务是建立一个算法,使有语音障碍的人与不懂手语的人交流。


训练集:1080张图片,每张图片大小为:64*64,表示数字0至5,每个数字的图片为180张。

测试集:120张图片,每张图片大小为:64*64,表示数字0至5,每个数字的图片为20张。

得到如下结果:


12288来自于64*64*3,每一张图片是64*64像素,3表示RGB的3个颜色通道。

目标是建立一个能够识别高精度符号的算法。将建立一个tensorflow模型几乎和以前猫识别相同(使用softmax输出)

模型为: LINEAR -> RELU -> LINEAR -> RELU -> LINEAR -> SOFTMAX

输出层SIGMOID被SOFTMAX代替,原因:结果多于两个分类。

(二)创建占位符

首先,为X和Y创建占位符,在后面执行session会话的时候传递训练集数据。

#创建占位符
def create_placeholder(n_x,n_y):
    """
    为tensorflow session会话创建占位符
    param :
    n_x -- 标量,图片向量的大小(num_px * num_px = 64 * 64 * 3 = 12288)
    n_y -- 标量,分类的数目(从 0 至 5,为6)

    return:
    X -- 输入数据的占位符,大小为[n_x,None],类型为:float
    Y -- 输入标签值的占位符,大小为[n_y,None],类型为:float
    注:None表示关于样本数目这一维度可以是不固定的任意长度
    """
    X = tf.placeholder(dtype=tf.float32,shape=[n_x,None],name="X")
    Y = tf.placeholder(dtype=tf.float32,shape=[n_y,None],name="Y")

    return X,Y

X,Y = create_placeholder(12288,6)
print("X = "+str(X))
print("Y = "+str(Y))

#运行结果:
X = Tensor("X:0", shape=(12288, ?), dtype=float32)
Y = Tensor("Y:0", shape=(6, ?), dtype=float32)
(三)用tensorflow初始化参数

用Xavier 初始化权重 weights,用 Zero 初始化偏向 biases。具体如下:


#用tensorflow初始化参数
def initialize_parameters():
    """
    初始化参数用tensorflow构建深层神经网络,参数的维度大小如下:
    W1 : [25, 12288] 、b1 : [25, 1]、W2 : [12, 25]、
    b2 : [12, 1]、W3 : [6, 12]、b3 : [6, 1]

    return:
    parameters -- 字典类型的张量包含W1, b1, W2, b2, W3, b3
    """
    tf.set_random_seed(1)

    W1 = tf.get_variable(name="W1",shape=[25,12288],initializer=tf.contrib.layers.xavier_initializer(seed=1))
    b1 = tf.get_variable(name="b1",shape=[25,1],initializer=tf.zeros_initializer())
    W2 = tf.get_variable(name="W2",shape=[12,25],initializer=tf.contrib.layers.xavier_initializer(seed=1))
    b2 = tf.get_variable(name="b2",shape=[12,1],initializer=tf.zeros_initializer())
    W3 = tf.get_variable(name="W3",shape=[6,12],initializer=tf.contrib.layers.xavier_initializer(seed=1))
    b3 = tf.get_variable(name="b3",shape=[6,1],initializer=tf.zeros_initializer())

    parameters = {"W1":W1,"b1":b1,"W2":W2,"b2":b2,"W3":W3,"b3":b3}

    return parameters

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

#运行结果:
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>
(四)tensorflow中前向传播

该函数中会传入字典类型的参数来计算正向传播,需要用到的函数如下:


#tensorflow中的前向传播
def forward_propogation(X,parameters):
    """
    正向传播模型为:LINEAR -> RELU -> LINEAR -> RELU -> LINEAR -> SOFTMAX
    param :
    X -- 输入集作为占位符,维度大小为(输入大小,样本数目)
    parameters -- 字典类型的参数,包含"W1", "b1", "W2", "b2", "W3", "b3",
                    维度为初始化参数的initialize_parameters()函数给出

    return:
    Z3 -- 最后一个线性单元的输出
    """
    #取出参数
    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)
    A1 = tf.nn.relu(Z1)
    Z2 = tf.add(tf.matmul(W2,A1),b2)
    A2 = tf.nn.relu(Z2)
    Z3 = tf.add(tf.matmul(W3,A2),b3)

    return Z3

tf.reset_default_graph()

with tf.Session() as session:
    X,Y = create_placeholder(12288,6)
    parameters = initialize_parameters()
    Z3 = forward_propogation(X,parameters)
    print("Z3 = "+str(Z3))

#运行结果:
Z3 = Tensor("Add_2:0", shape=(6, ?), dtype=float32)
(五)计算目标函数

logits 和 lables 是函数  tf.nn.softmax_cross_entropy_with_logits 输入,tf.reduce_mean 表示求均值。
logits,它的shape是[batch_size,n_classes] 一般是神经网络的最后一层输出,Z3需要转置才能与logits维度相同
labels,它的shape也是[batch_size,n_classes] ,实际输出的标签值,Y需要转置才能与labels维度相同。

#计算目标函数
def compute_cost(Z3,Y):
    """
    param :
    Z3 -- 前向传播的输出,维度为(6,样本数目)
    Y -- 真实的标签值,占位符,与Z3维度相同

    return:
    cost -- 目标函数值,是个张量
    """
    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

tf.reset_default_graph()

with tf.Session() as sees:
    X,Y = create_placeholder(12288,6)
    parameters = initialize_parameters()
    Z3 = forward_propogation(X,parameters)
    cost = compute_cost(Z3,Y)
    print("cost = "+str(cost))

#运行结果:
cost = Tensor("Mean:0", shape=(), dtype=float32)
(六)反向传播及参数更新

在计算完目标函数之后,需要创建一个 optimizer对象,在运行 tf.session 时调用这个对象。

当调用时,它将根据所选择的方法和学习速率对给定的成本进行优化。举例:利用梯度下降最小化目标函数:



(七)利用tensorflow构建深层神经网络模型

#在tensorflow上构建神经网络

#1、加载数据集并展示其中的图片
X_train_orig,Y_train_orig,X_test_orig,Y_test_orig,classes = load_datasets()

index = 10
plt.imshow(X_train_orig[index])
pylab.show()
print("y = "+str(np.squeeze(Y_train_orig[:,index])))

#训练集和测试集的图片reshape的向量化处理
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 testing 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 hape: "+str(Y_test.shape))

#创建占位符
def create_placeholder(n_x,n_y):
    """
    为tensorflow session会话创建占位符
    param :
    n_x -- 标量,图片向量的大小(num_px * num_px = 64 * 64 * 3 = 12288)
    n_y -- 标量,分类的数目(从 0 至 5,为6)

    return:
    X -- 输入数据的占位符,大小为[n_x,None],类型为:float
    Y -- 输入标签值的占位符,大小为[n_y,None],类型为:float
    注:None表示关于样本数目这一维度可以是不固定的任意长度
    """
    X = tf.placeholder(dtype=tf.float32,shape=[n_x,None],name="X")
    Y = tf.placeholder(dtype=tf.float32,shape=[n_y,None],name="Y")

    return X,Y

X,Y = create_placeholder(12288,6)
print("X = "+str(X))
print("Y = "+str(Y))

#用tensorflow初始化参数
def initialize_parameters():
    """
    初始化参数用tensorflow构建深层神经网络,参数的维度大小如下:
    W1 : [25, 12288] 、b1 : [25, 1]、W2 : [12, 25]、
    b2 : [12, 1]、W3 : [6, 12]、b3 : [6, 1]

    return:
    parameters -- 字典类型的张量包含W1, b1, W2, b2, W3, b3
    """
    tf.set_random_seed(1)

    W1 = tf.get_variable(name="W1",shape=[25,12288],initializer=tf.contrib.layers.xavier_initializer(seed=1))
    b1 = tf.get_variable(name="b1",shape=[25,1],initializer=tf.zeros_initializer())
    W2 = tf.get_variable(name="W2",shape=[12,25],initializer=tf.contrib.layers.xavier_initializer(seed=1))
    b2 = tf.get_variable(name="b2",shape=[12,1],initializer=tf.zeros_initializer())
    W3 = tf.get_variable(name="W3",shape=[6,12],initializer=tf.contrib.layers.xavier_initializer(seed=1))
    b3 = tf.get_variable(name="b3",shape=[6,1],initializer=tf.zeros_initializer())

    parameters = {"W1":W1,"b1":b1,"W2":W2,"b2":b2,"W3":W3,"b3":b3}

    return parameters

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

#tensorflow中的前向传播
def forward_propogation(X,parameters):
    """
    正向传播模型为:LINEAR -> RELU -> LINEAR -> RELU -> LINEAR -> SOFTMAX
    param :
    X -- 输入集作为占位符,维度大小为(输入大小,样本数目)
    parameters -- 字典类型的参数,包含"W1", "b1", "W2", "b2", "W3", "b3",
                    维度为初始化参数的initialize_parameters()函数给出

    return:
    Z3 -- 最后一个线性单元的输出
    """
    #取出参数
    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)
    A1 = tf.nn.relu(Z1)
    Z2 = tf.add(tf.matmul(W2,A1),b2)
    A2 = tf.nn.relu(Z2)
    Z3 = tf.add(tf.matmul(W3,A2),b3)

    return Z3

tf.reset_default_graph()

with tf.Session() as session:
    X,Y = create_placeholder(12288,6)
    parameters = initialize_parameters()
    Z3 = forward_propogation(X,parameters)
    print("Z3 = "+str(Z3))

#计算目标函数
def compute_cost(Z3,Y):
    """
    param :
    Z3 -- 前向传播的输出,维度为(6,样本数目)
    Y -- 真实的标签值,占位符,与Z3维度相同

    return:
    cost -- 目标函数值,是个张量
    """
    logits = tf.transpose(Z3)
    labels = tf.transpose(Y)

    #logits,它的shape是[batch_size,n_classes] 一般是神经网络的最后一层输出
    #labels,它的shape也是[batch_size,n_classes] ,实际输出的标签值
    cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=logits,labels=labels))

    return cost

tf.reset_default_graph()

with tf.Session() as sees:
    X,Y = create_placeholder(12288,6)
    parameters = initialize_parameters()
    Z3 = forward_propogation(X,parameters)
    cost = compute_cost(Z3,Y)
    print("cost = "+str(cost))

#反向传播及参数更新

#利用tensorflow构建深层神经网络模型
def model(X_train,Y_train,X_test,Y_test,learning_rate = 0.0001,
          num_epochs = 1500,minibatch_size = 32,print_cost = True):
    """
    用tensorflow创建3层的神经网络, LINEAR->RELU->LINEAR->RELU->LINEAR->SOFTMAX.
    param :
    X_train -- 训练集图片,维度为(输入大小 = 12288, 训练样本数目 = 1080)
    Y_train -- 训练集真实标签值(输出大小 = 6, 训练样本数目 = 120)
    X_test --  测试集图片,维度为(输入大小 = 12288, 训练样本数目 = 1080)
    Y_test -- 测试集真实标签值(输出大小 = 6, 训练样本数目 = 120)
    learning_rate -- 学习率
    num_epochs -- 优化循环的epochs数目
    minibatch_size -- minibatch大小
    print_cost -- True表示每100个epochs打印cost

    return:
    parameters -- 模型学习的参数,也用来后面的预测
    """
    ops.reset_default_graph()
    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 = []

    #为X,Y创建占位符,维度为(n_x,n_y)
    X,Y = create_placeholder(n_x,n_y)

    #初始化参数
    parameters = initialize_parameters()

    #前向传播
    Z3 = forward_propogation(X,parameters)

    #计算目标函数
    cost = compute_cost(Z3,Y)

    #反向传播
    optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)

    #初始化所有的变量
    init = tf.global_variables_initializer()

    #创建session会话计算tensorflow图
    with tf.Session() as sess:
        sess.run(init)

        #循环
        for epoch in range(num_epochs):
            epoch_cost = 0      #定义一个与epoch相关的cost
            num_minibatches = int(m/minibatch_size)     #训练集中minibatch数目
            seed = seed + 1
            minibatches = random_mini_batches(X_train,Y_train,minibatch_size,seed)

            for minibatch in minibatches:
                (minibatch_X,minibatch_Y) = minibatch   #选择一个minibatch
                _,minibatch_cost = sess.run([optimizer,cost],feed_dict={X:minibatch_X,Y:minibatch_Y})

                epoch_cost += minibatch_cost/num_minibatches

            #打印cost
            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.savefig("DNN_tf.png")
        plt.show()

        #将参数保存到变量中
        parameters = sess.run(parameters)
        print("Parameters have been trained!")

        #计算正确的预测
        correct_prediction = tf.equal(tf.arg_max(Z3,0),tf.arg_max(Y,0))

        #在测试集上计算准确度
        accuracy = tf.reduce_mean(tf.cast(correct_prediction,"float"))

        #eval()  将字符串str当成有效的表达式来求值并返回计算结果
        print("Train Accuracy:",accuracy.eval({X:X_train,Y:Y_train}))
        print("Test Accuracy:",accuracy.eval({X:X_test,Y:Y_test}))

        return parameters

parameters = model(X_train,Y_train,X_test,Y_test,num_epochs=500)

#运行结果:
Cost after epoch 0 : 1.855702
Cost after epoch 100 : 1.016458
Cost after epoch 200 : 0.733102
Cost after epoch 300 : 0.572939
Cost after epoch 400 : 0.468774
Train Accuracy: 0.881481
Test Accuracy: 0.733333






Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐