一、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.9999555、计算目标函数
可以使用内置函数计算神经网络的成本/目标函数。因此,不需要编写代码来计算这个函数。
在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)(五)计算目标函数
tf.nn.softmax_cross_entropy_with_logits
输入,tf.reduce_mean 表示求均值。
#计算目标函数 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