一、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)
(五)计算目标函数
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