1 TensorFlow 计算模型一一计算图node
1.1 计算图的概念python
TensorFlow 是一个经过计算图的形式来表述计算的编程系统 。计算图是 TensorFlow 中最基本的一个概念, TensorFlow 中的全部计算都会被转化为计算图上的节点 ,而节点之间的边描述了计算之间的依赖关系。TensorFlow 的基本计算模型以下图所示:git
1.2 计算图的使用github
2 TensorFlow 数据模型一一张量正则表达式
2.1 张量的概念算法
2.2 张量的使用编程
3 TensorFlow 运行模型一一会话后端
4 TensorFlow变量api
4.1 TensorFlow中变量的概念数组
4.2 建立和使用变量
除了使用随机数或者常数,TensorFlow 也支持经过其余变量 的初始值来初始化新的变量。 如下代码给出了具体的方法 。
w2 = tf.Variable(weights.initialized_value())
w3 = tf.Variable(weights.initialized_value()*2.0)
在 TensorFlow 中,一个变量的值在被使用以前,这个变量的初始化过程须要被明确地调用 ,即变量在使用以前须要初始化。 TensorFlow 提供了一种便捷的方式来完成变量初始化过程。如下程序展现了经过 tf.global_variables_initializer 函数实现初始化全部变量的过程 。
init_op = tf.global_variables_initializer()
sess.run(init_op)
4.3 TensorFlow目前支持的全部随机数生成器
函数名称 随机数分布 主要参数
tf.random_normal 正太分布 平均值、标准差、取值类型·
tf.truncated_normal 正太分布,但若是随机出来的值偏离平均值超过 2个标准差,那么这个数将会被从新随机 平均值、标准差、取值类型
tf.random.uniform 均匀分布 最小、最大取值、取值类型
tf.random_gamma Gamma 分布 形状参数 alpha、尺度参数 beta 、 取值类型
4.4 TensorFlow中经常使用的常量声明方法
函数名称 功能 样例
tf.zeros 产生全0的数组 tf.zeros([2, 3), int32) > ([0, 0, 0], [0, 0, 0]]
tf.ones 产生全1的数组 tf.ones([2, 3], int32) -> [[1,1,1],[1,1,1]]
tf.fill 产生一个所有为给定数字的数组 tf.fill([2, 3), 9) ->[ [9, 9, 9],[9, 9, 9]]
tf.constant 产生一个给定值的常量 tf.constant([1,2,3])—>[1,2,3]
4.5 案例:使用变量实现一个简单的计数器.
# 建立一个变量为计数器, 初始化为标量 0. state = tf.Variable(0, name="counter") # 建立一个变量, 其做用是使state增长1 one = tf.constant(1) new_value = tf.add(state, one) # 更新计数器 update = tf.assign(state, new_value) # 启动图后, 变量必须先通过变量初始化, init_op = tf.global_variables_initializer() # 启动图, 运行会话 with tf.Session() as sess: # 运行变量初始化 sess.run(init_op) # 打印 'state' 的初始值 print sess.run(state) # 运行更新 'state', 并打印 'state' for _ in range(3): sess.run(update) print sess.run(state)
4.6 命名空间与共享变量
定义一个相同名字的变量
var = tf.Variable(name='var', initial_value=[4], dtype=tf.float32)
var_double = tf.Variable(name='var', initial_value=[4], dtype=tf.float32)
<tf.Variable 'var:0' shape=() dtype=float32_ref>
<tf.Variable 'var_1:0' shape=() dtype=float32_ref>
使用tf.variable_scope()修改OP命名空间
with tf.variable_scope("name"):
var = tf.Variable(name='var', initial_value=[4], dtype=tf.float32)
var_double = tf.Variable(name='var', initial_value=[4], dtype=tf.float32)
<tf.Variable 'name/var:0' shape=() dtype=float32_ref>
<tf.Variable 'name/var_1:0' shape=() dtype=float32_ref>
tf.get_variable共享变量
经过tf.get_variable的初始化与Variable参数同样,可是要是实现共享须要打开tf.variable_scope("name")中的reuse=tf.AUTO_REUSE参数。
# 打开共享参数 # 或者 # with tf.variable_scope("name") as scope: # 在须要使用共享变量的前面定义: scope.reuse_variables() with tf.variable_scope("name", reuse=tf.AUTO_REUSE): var = tf.Variable(initial_value=4.0, name="var", dtype=tf.float32) var_double = tf.Variable(initial_value=4.0, name="var", dtype=tf.float32) var1 = tf.get_variable(initializer=tf.random_normal([2, 2], mean=0.0, stddev=1.0), name="var1", dtype=tf.float32) var1_double = tf.get_variable(initializer=tf.random_normal([2, 2], mean=0.0, stddev=1.0), name="var1", dtype=tf.float32) with tf.Session() as sess: sess.run(tf.global_variables_initializer()) print(var1) print(var1_double)
5 TensorFlow模型的保存和恢复
5.1 什么是Tensorflow模型?
5.2 为何要保存Tensorflow模型:
例如,假设您能够访问通过训练的 DNN,将图片分为 100 个不一样的类别,包括动物,植物,车辆和平常物品。 您如今想要训练一个 DNN 来对特定类型的车辆进行分类。 这些任务很是类似,所以您应该尝试从新使用第一个网络的一部分(请参见图 11-4)。
5.3 如何保存Tensorflow模型:
若是咱们但愿在迭代i次以后保存模型,能够把当前的迭代步数传进去:
# 每隔一百步保存一次模型
if i % 100 == 0:
saver.save(sess, 'my_test_model',global_step=i)
# 利用global_step参数能够把迭代的步数追加到文件名中
5.4 如何导入已经保存的模型
若是想用别人的预先训练好的模型做为咱们的模型的一部分,那么须要作两件事情:
5.5 复用TensorFlow模型
若是原始模型使用 TensorFlow 进行训练,则能够简单地将其恢复并在新任务上进行训练:
[...] # 构建原始模型
with tf.Session() as sess: # 还原模型 saver.restore(sess, "./my_model_final.ckpt") # 在新任务中继续训练模型...
然而,一般咱们只想要重用原有模型的一部分(咱们立刻就会讨论这种情况),一种简单的解决方案就是配置Saver使之在还原原模型时只还原全部参数的一个子集。举例来讲,下面的代码就只还原了隐藏层一、隐藏层2和隐藏层3:
"""
首先咱们创建新的模型,确保复制原始模型的隐藏层 1 到 3
"""
n_inputs = 28 * 28 # MNIST
n_hidden1 = 300 # reused
n_hidden2 = 50 # reused
n_hidden3 = 50 # reused
n_hidden4 = 20 # new!
n_outputs = 10 # new!
X = tf.placeholder(tf.float32, shape=(None, n_inputs), name="X") y = tf.placeholder(tf.int64, shape=(None), name="y") with tf.name_scope("dnn"): hidden1 = tf.layers.dense(X, n_hidden1, activation=tf.nn.relu, name="hidden1") # reused hidden2 = tf.layers.dense(hidden1, n_hidden2, activation=tf.nn.relu, name="hidden2") # reused hidden3 = tf.layers.dense(hidden2, n_hidden3, activation=tf.nn.relu, name="hidden3") # reused hidden4 = tf.layers.dense(hidden3, n_hidden4, activation=tf.nn.relu, name="hidden4") # new! logits = tf.layers.dense(hidden4, n_outputs, name="outputs") # new! with tf.name_scope("loss"): xentropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=logits) loss = tf.reduce_mean(xentropy, name="loss") with tf.name_scope("eval"): correct = tf.nn.in_top_k(logits, y, 1) accuracy = tf.reduce_mean(tf.cast(correct, tf.float32), name="accuracy") with tf.name_scope("train"): optimizer = tf.train.GradientDescentOptimizer(learning_rate) training_op = optimizer.minimize(loss) # 获取保存的模型中用trainable = True(这是默认值)建立的全部变量的列表 reuse_vars = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope="hidden[123]") # 咱们只保留那些范围与正则表达式hidden [123]相匹配的变量(即,咱们获得全部可训练的隐藏层 1 到 3 中的变量)。 # 咱们建立一个字典,将原始模型中每一个变量的名称映射到新模型中的名称中(一般须要保持彻底相同的名称) reuse_vars_dict = dict([(var.op.name, var) for var in reuse_vars]) # 建立一个SaverOP用来还原模型中的参数 restore_saver = tf.train.Saver(reuse_vars_dict) # to restore layers 1-3 init = tf.global_variables_initializer() # 建立一个新的SaverOP用来保存新模型 new_saver = tf.train.Saver() with tf.Session() as sess: init.run() # 从原始模型的层 1 到 3中恢复变量值 restore_saver.restore(sess, "./my_model_final.ckpt") for epoch in range(n_epochs): for iteration in range(mnist.train.num_examples // batch_size): X_batch, y_batch = mnist.train.next_batch(batch_size) sess.run(training_op, feed_dict={X: X_batch, y: y_batch}) accuracy_val = accuracy.eval(feed_dict={X: mnist.test.images, y: mnist.test.labels}) print(epoch, "Test accuracy:", accuracy_val) # 保存新模型 save_path = new_saver.save(sess, "./my_new_model_final.ckpt")
案例:识别手势数据集
"""
一天下午,咱们和一些朋友决定教咱们的电脑破译手语。咱们花了几个小时在白色的墙壁前拍照,因而就有了了如下数据集。如今,你的任务是创建一个算法,使有语音障碍的人与不懂手语的人交流。
训练集:有从0到5的数字的1080张图片(64x64像素),每一个数字拥有180张图片。
测试集:有从0到5的数字的120张图片(64x64像素),每一个数字拥有5张图片。
须要注意的是这是完整数据集的一个子集,完整的数据集包含更多的符号。
下面是每一个数字的样本,以及咱们如何表示标签的解释。这些都是原始图片,咱们实际上用的是64 * 64像素的图片。
"""
import numpy as np
import h5py
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow.python.framework import ops
import time
import math
from functools import partial
# %matplotlib inline #若是你使用的是jupyter notebook取消注释
np.random.seed(1)
class GestureSymbolRecognition(object):
def init(self):
self.learning_rate = 0.0001
self.num_epochs = 1000
self.minibatch_size = 32
self.regularazion_rate = 0.001
self.n_inputs = 12288 self.n_hidden1 = 200 self.n_hidden2 = 100 self.n_hidden3 = 100 self.n_outputs = 6 self.batch_norm_momentum = 0.9 def load_data(self): """ 加载数据集 :return: """ # 从文件中读取训练集数据 train_dataset = h5py.File('datasets/train_signs.h5', "r") # 从训练集数据中提取特征值与标签值数据 train_set_x_orig = np.array(train_dataset["train_set_x"][:]) train_set_y_orig = np.array(train_dataset["train_set_y"][:]) # 从文件中读取测试集数据 test_dataset = h5py.File('datasets/test_signs.h5', "r") # 从测试集数据中提取特征值与标签值数据 test_set_x_orig = np.array(test_dataset["test_set_x"][:]) test_set_y_orig = np.array(test_dataset["test_set_y"][:]) classes = np.array(test_dataset["list_classes"][:]) # 类别列表 classes_num = len(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])) X_train_flatten = train_set_x_orig.reshape(train_set_x_orig.shape[0], -1) # 每一列就是一个样本 X_test_flatten = test_set_x_orig.reshape(test_set_x_orig.shape[0], -1) # 归一化数据 X_train = X_train_flatten / 255 X_test = X_test_flatten / 255 # 转换为one-hot编码矩阵 Y_train = self.convert_to_one_hot(train_set_y_orig, len(classes)).T Y_test = self.convert_to_one_hot(test_set_y_orig, len(classes)).T return X_train, Y_train, X_test, Y_test, classes_num def convert_to_one_hot(self, Y, C): """ 实现one-hot编码 :param Y:标签矩阵 :param C:分类数量 :return:one_hot:one-hot矩阵 """ one_hot = np.eye(C)[Y.reshape(-1)].T return one_hot def random_mini_batches(self, X, Y, mini_batch_size, seed=0): """ 从数据集中建立一个随机的mini-batch列表 :param X: 输入数据,维度为(输入节点数量,样本数量) :param Y: 对应的目标值,维度为(1,样本数量) :param mini_batch_size: 每一个mini-batch的样本数量 :param seed: 随机数种子 :return: mini_batches:一个同步列表,维度为(mini_batch_X, mini_batch_Y) """ # 指定随机数种子 np.random.seed(seed) # 获取样本数 m = X.shape[0] # print('样本数量',m) # 建立一个同步列表 mini_batches = [] # 第一步:打乱样本的顺序 permutation = list(np.random.permutation(m)) # 返回一个长度为m的随机数组,且里面的数是0到m-1 shuffled_X = X[permutation, :] # 将每一列特征值数据按permutation的顺序来从新排列 shuffled_Y = Y[permutation, :] # .reshape((Y.shape[0], m)) # 将每一列的目标值数据按permutation的顺序来从新排列 # 第二步:分割训练集数据 num_complete_minibatches = math.floor(m / mini_batch_size) # 迭代完成整个训练集的次数 for k in range(0, num_complete_minibatches): mini_batch_X = shuffled_X[k * mini_batch_size:(k + 1) * mini_batch_size, :] mini_batch_Y = shuffled_Y[k * mini_batch_size:(k + 1) * mini_batch_size, :] mini_batch = (mini_batch_X, mini_batch_Y) mini_batches.append(mini_batch) # 若是训练集的大小不是mini_batch_size的整数倍,那么最后确定会剩下一些,取剩余的数据 if m % mini_batch_size != 0: # 获取剩余部分的数据 mini_batch_X = shuffled_X[mini_batch_size * num_complete_minibatches:, :] mini_batch_Y = shuffled_Y[mini_batch_size * num_complete_minibatches:, :] mini_batch = (mini_batch_X, mini_batch_Y) mini_batches.append(mini_batch) # 返回同步列表 return mini_batches def train(self, print_cost=True, is_plot=True): """ 实现一个三层的TensorFlow神经网络训练逻辑:LINEAR->RELU->LINEAR->RELU->LINEAR->SOFTMAX 参数: print_cost - 是否打印成本,每100代打印一次 is_plot - 是否绘制曲线图 """ # 加载数据集 x_train, y_train, x_test, y_test, label_classes_num = self.load_data() print("训练集样本数 = " + str(x_train.shape[0])) print("测试集样本数 = " + 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)) # 设置图级别的随机数种子 tf.set_random_seed(1) # 设置操做级别的随机数种子 seed = 3 # 获取输入节点数量和样本数 (m, n_x) = x_train.shape # 成本函数值列表 costs = [] # 给X和Y建立占位符节点 X = tf.placeholder(tf.float32, shape=(None, self.n_inputs), name="X") Y = tf.placeholder(tf.int32, shape=(None, label_classes_num), name="y") # 定义神经网络全链接层 with tf.name_scope("dnn"): # 使用He权重初始化方法初始化权重 he_init = tf.contrib.layers.variance_scaling_initializer(mode='FAN_AVG') # 定义全链接层,使用elu激活函数 hidden1 = tf.layers.dense(X, self.n_hidden1, name="hidden1", activation=tf.nn.elu, kernel_initializer=he_init) hidden2 = tf.layers.dense(hidden1, self.n_hidden2, name="hidden2", activation=tf.nn.elu, kernel_initializer=he_init) hidden3 = tf.layers.dense(hidden2, self.n_hidden3, name="hidden3", activation=tf.nn.elu, kernel_initializer=he_init) outputs = tf.layers.dense(hidden3, self.n_outputs, name="outputs") # 输出预测的类别 y_proba = tf.nn.softmax(outputs) # 定义损失函数计算损失 with tf.name_scope('loss'): # 前向传播要在Z3处中止,由于在TensorFlow中最后的线性输出层的输出做为计算损失函数的输入,因此不须要A3. xentropy = tf.nn.softmax_cross_entropy_with_logits(labels=Y, logits=outputs) loss = tf.reduce_mean(xentropy, name="loss") # 定义优化器 with tf.name_scope("train_optimizer"): optimizer = tf.train.AdamOptimizer(self.learning_rate) training_op = optimizer.minimize(loss) # 评估模型,使用准确性做为咱们的绩效指标 with tf.name_scope("eval"): # 计算当前的预测结果 # 检测使用了滑动平静模型的神经网络前向传播是否正确。tf.argmax(average_y,1) # 计算每个样例的预测答案。其中average_y是一个batch_size*10的二维数组,每 # 一行表示案例向前传播的结果。tf.argmax的第二个参数为1,表示选取最大值的 # 操做只在第一个维度上进行(x轴上),也就是说只在每一行选取最大值对应的下标 # 因而获得的结果是一个长度为batch的一维数组,这个一维数组中的值就表示了每 # 一个数字对应的样例识别的结果.tf.equal()判断每一个Tensor的每一维度是否相同 # 若是相等返回True,不然返回False. correct_prediction = tf.equal(tf.argmax(y_proba, 1), tf.argmax(Y, 1)) # 计算准确率 # 这个运算首先将一个布尔型的值转换为实数型,而后计算平均值。这一个平均值 # 就表明模型在这一组数据上的正确率 accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) """ 首先咱们创建新的模型,确保复制原始模型的隐藏层 1 到 2 """ # 获取保存的模型中用trainable = True(这是默认值)建立的全部变量的列表 # 咱们只保留那些范围与正则表达式hidden [123]相匹配的变量(即,咱们获得全部可训练的隐藏层 1 到 3 中的变量)。 reuse_vars = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope='hidden[12]') # 咱们建立一个字典,将原始模型中每一个变量的名称映射到新模型中的名称中(一般须要保持彻底相同的名称) reuse_vars_dict = dict([(var.op.name, var) for var in reuse_vars]) # 建立一个SaverOP用来还原模型中的参数 restore_saver = tf.train.Saver(reuse_vars_dict) # 建立初始化全部变量的节点 init = tf.global_variables_initializer() # 建立一个新的SaverOP用来保存新模型 new_saver = tf.train.Saver(max_to_keep=1) # 开始会话并计算 with tf.Session() as sess: # 初始化全部变量 sess.run(init) # 加载模型,从模型中找出与当前训练的模型代码当中(名字同样的OP操做),覆盖原来的值 checkpoin = tf.train.latest_checkpoint('./ckpt/') # 若是模型已经保存则加载模型 if checkpoin: # 从原始模型恢复变量值 restore_saver.restore(sess, './ckpt/my_test1_model.ckpt') # 正常训练模型 for epoch in range(self.num_epochs): epoch_cost = 0 # 每轮的成本函数值 num_minibatches = math.floor(m / self.minibatch_size) # 分红多少个mini-batch组 seed = seed + 1 minibatches = self.random_mini_batches(x_train, y_train, self.minibatch_size, seed) for minibatch in minibatches: # 选择一个minibatch (minibatch_X, minibatch_Y) = minibatch # 数据已经准备好了,开始运行session _, minibatch_cost = sess.run([training_op, loss], feed_dict={X: minibatch_X, Y: minibatch_Y}) # 计算这个minibatch在这一代中所占的偏差 epoch_cost = epoch_cost + minibatch_cost / num_minibatches if epoch % 5 == 0: # 将每轮迭代的代价函数值存入列表 costs.append(epoch_cost) # 打印每轮迭代的代价函数值: if print_cost and epoch % 100 == 0: print("epoch = " + str(epoch) + " epoch_cost = " + str(epoch_cost)) # 保存学习后的参数 new_saver.save(sess, './ckpt/my_test1_model.ckpt') # 绘制代价函数值的学习曲线 if is_plot: plt.plot(np.squeeze(costs)) plt.ylabel('cost') plt.xlabel('iterations (per tens)') plt.title("Learning rate =" + str(self.learning_rate)) plt.show() # 计算模型学习完成后的训练集及测试集准确率 train_acc = accuracy.eval({X: x_train, Y: y_train}) test_acc = accuracy.eval({X: x_test, Y: y_test}) print("训练集的准确率:", train_acc) print("测试集的准确率:", test_acc)
if name == 'main':
# 开始时间
start_time = time.clock()
# 开始训练
nn = GestureSymbolRecognition()
nn.train()
# 结束时间
end_time = time.clock()
# 计算时差
print("CPU的执行时间 = " + str(end_time - start_time) + " 秒")
5.6 冻结底层
5.7 缓存冻结层
由于冻结层不会变化,因此就有可能将每个训练实例的最高冻结层的输出缓存起来。因为训练会轮询整个数据集不少次,因此你将得到巨大的速度提高,由于你只须要在一个训练实例中遍历一次冻结层(而不是每一个全数据集一次)。举个例子,你能够第一次在低层跑完整个训练集(假设你有足够的RAM):
hidden2_outputs = sess.run(hidden2, feed_dict={X: X_train})
而后在训练中,你要作的不是构建批量的训练实例,而是批量构建隐藏层2的输出,而且将它们喂给训练操做:
import numpy as np
n_epochs = 100
n_batches = 500
for epoch in range(n_epochs):
shuffled_idx = rnd.permutation(len(hidden2_outputs))
hidden2_batches = np.array_split(hidden2_outputs[shuffled_idx], n_batches)
y_batches = np.array_split(y_train[shuffled_idx], n_batches)
for hidden2_batch, y_batch in zip(hidden2_batches, y_batches):
sess.run(training_op, feed_dict={hidden2: hidden2_batch, y: y_batch})
5.8 调整、丢弃或替换层
5.9 模型动物园
5.10 无监督的预训练
5.11 辅助任务中的预训练
6 TensorBoard:可视化学习
注意:路径不能出现中文,不然会打不开!!!
# 实现加法
con1 = tf.constant(11.0, name='input1')
con2 = tf.constant(12.0, name='input2')
sum_ = tf.add(con1, con2, name='add')
with tf.Session() as sess:
# 在会话中序列化events文件
file_writer = tf.summary.FileWriter('f:logs/', tf.get_default_graph())
file_writer.close()
7 Tensorflow案例—实现线性回归
7.1 线性回归原理复习
7.2 案例肯定
数据自己的分布为 y = 0.7 * x + 0.8
这里将数据分布的规律肯定,是为了使咱们训练出的参数跟真实的参数(即0.7和0.8)比较是否训练准确。
7.3 使用的API
7.4 示例代码
""" 使用Tensorflow实现线性回归 """ import tensorflow as tf class MyLinearRegression(object): """ 实现一个线性回归 """ def __init__(self, FLAGS): self.FLAGS = FLAGS # 定义学习率 self.learning_rate = 0.1 # 定义迭代次数 self.train_step = 1000 # 定义并初始化线性回归模型的权重与偏置参数,因为权重与偏置须要被训练与优化,所以需用使用变量OP定义 self.height = tf.Variable(tf.random_normal(shape=[1, 1], mean=0.0, stddev=1.0, name='height')) self.bais = tf.Variable(tf.random_normal(shape=[1], mean=0.0, stddev=1.0, name='bais')) def inputs(self): """ 获取须要训练的数据 :return: x_feature,y_target """ # 定义一个命名空间 with tf.variable_scope('get_inputs'): # 公式:y = x*0.7 + 0.8 # 生成符合正态分布的特征值 x_feature = tf.random_normal(shape=[100, 1], mean=0.0, stddev=1.0, name='x_feature') # 利用矩阵乘法计算得出目标值,注意矩阵相乘,维数要相同 y_target = tf.matmul(x_feature, [[0.7]]) + 0.8 return x_feature, y_target def inference(self, x_feature): """ 根据数据创建线性回归模型 :param x_feature: 特征值 :return: y_predic:预测结果 """ # 定义一个命名空间 with tf.variable_scope('linear_model'): # 计算预测值 y_predict = tf.matmul(x_feature, self.height) + self.bais return y_predict def loss(self, y_predict, y_target): """ 由线性回归模型的损失函数计算损失值 :param y_predict: 预测值 :param y_target: 目标值 :return: 损失值 """ # 定义一个命名空间 with tf.variable_scope('get_loss'): # 损失函数使目标值与预测值的均方差公式 # 先用tf.square()计算差的平方 # 再用tf.reduce_mean()对列表数据求和后再求平均值 loss = tf.reduce_mean(tf.square(y_predict - y_target)) return loss def sgd_op(self, loss): """ 使用随机梯度降低优化器来优化损失(优化模型参数) :param loss: 损失大小 :return: 梯度降低OP """ # 定义一个命名空间 with tf.variable_scope("sgd_op"): # 使用随机梯度降低API得出优化结果 train_op = tf.train.GradientDescentOptimizer(learning_rate=self.learning_rate).minimize(loss) return train_op def merge_summary(self, loss): """ 增长变量显示:在TensorBoard当中观察模型的参数、损失值等变量值的变化 :param loss:损失 :return: merged:合并的变量 """ # 1. 收集变量 tf.summary.scalar('loss', loss) tf.summary.histogram('w', self.height) tf.summary.histogram('b', self.bais) # 2. 合并变量 merged = tf.summary.merge_all() return merged def train(self): """ 用于实现线性回归模型训练逻辑 :return: """ # 开启一个默认的图 g = tf.get_default_graph() # 在默认的计算图中进行操做 with g.as_default(): # 获得输入数据 x_feature, y_target = self.inputs() # 创建线性回归模型,获得预测值 y_predict = self.inference(x_feature) # 根据损失函数求解损失值 loss = self.loss(y_predict, y_target) # 使用梯度降低优化器优化损失 train_op = self.sgd_op(loss) # 增长变量显示:在TensorBoard当中观察模型的参数、损失值等变量值的变化 merged = self.merge_summary(loss) # 定义一个保存模型的saveOP,设置要保留的最近检测点的模型的数量 saver = tf.train.Saver(max_to_keep=5) # 开启一个会话 with tf.Session() as sess: # 初始化变量,初始化后才能够在会话中运行 sess.run(tf.global_variables_initializer()) # 生成事件文件观察图结构 file_writer = tf.summary.FileWriter('F:/tensorflow/logs', graph=sess.graph) print("模型随机初始化的权重参数:{},偏置参数:{}".format(self.height.eval(), self.bais.eval())) # 加载模型,从模型当中找出与当前训练的模型代码当中(名字同样的op操做),覆盖原来的值 checkpoint = tf.train.latest_checkpoint('./ckpt/') # 判断模型是否存在,若存在则提取保存的模型 if checkpoint: saver.restore(sess, checkpoint) print("第一次加载保存模型的权重参数:{},偏置参数:{}".format(self.height.eval(), self.bais.eval())) # 使用梯度降低优化损失 for i in range(1, self.FLAGS.train_step + 1): # 运行梯度降低OP与合并OP _, summary = sess.run([train_op, merged]) print("第{}步优化,损失为{},权重参数:{},偏置参数:{}".format(i, loss.eval(), self.height.eval(), self.bais.eval())) # 将优化的变量写入事件文件 file_writer.add_summary(summary, i) # 每隔一百步保存一次模型 if i % 100 == 0: saver.save(sess, self.FLAGS.model_dir, global_step=i) # './ckpt/myregression.ckpt' if __name__ == '__main__': # 定义命令行参数 tf.app.flags.DEFINE_integer('train_step', 0, '训练步数') tf.app.flags.DEFINE_string('model_dir', '', "模型的保存路径") # 定义获取命令行的参数 FLAGS = tf.app.flags.FLAGS lr = MyLinearRegression(FLAGS) lr.train()
8 Tensorflow文件读取
8.1 获取数据到Tensorflow的方法
供给数据(Feeding): Python产生数据,再把数据喂给后端。
import tensorflow as tf
# 设计Graph
x1 = tf.placeholder(tf.int16)
x2 = tf.placeholder(tf.int16)
y = tf.add(x1, x2)
# 用Python产生数据
li1 = [2, 3, 4]
li2 = [4, 0, 1]
# 打开一个session --> 喂数据 --> 计算y
with tf.Session() as sess:
print sess.run(y, feed_dict={x1: li1, x2: li2})
""" 说明:在这里x1, x2只是占位符,没有具体的值,那么运行的时候去哪取值呢?这时候就要用到sess.run()中的feed_dict参数,将Python产生的数据喂给后端,并计算y。 """
预加载数据: 在TensorFlow图中定义常量或变量来保存全部数据(仅适用于数据量比较小的状况)。
import tensorflow as tf
# 设计Graph
x1 = tf.constant([2, 3, 4])
x2 = tf.constant([4, 0, 1])
y = tf.add(x1, x2)
# 打开一个session --> 计算y
with tf.Session() as sess:
print sess.run(y)
从文件读取数据(QueueRunner):简单来讲就是将数据读取模块的图搭好
8.2 TensorFlow文件读取数据流程
8.3 TensorFlow读取机制图解
首先须要思考的一个问题是,什么是数据读取?以图像数据为例,读取数据的过程能够用下图来表示: 假设咱们的硬盘中有一个图片数据集0001.jpg,0002.jpg,0003.jpg……咱们只须要把它们读取到内存中,而后提供给GPU或是CPU进行计算就能够了。这听起来很容易,但事实远没有那么简单。 事实上,咱们必需要把数据先读入后才能进行计算,假设读入用时0.1s,计算用时0.9s,那么就意味着每过1s,GPU都会有0.1s无事可作,这就大大下降了运算的效率。
如何解决这个问题?方法就是将读入数据和计算分别放在两个线程中,将数据读入内存的一个队列,以下图所示:
读取线程源源不断地将文件系统中的图片读入到一个内存的队列中,而负责计算的是另外一个线程,计算须要数据时,直接从内存队列中取就能够了。这样就能够解决GPU由于IO而空闲的问题! 而在tensorflow中,为了方便管理,在内存队列前又添加了一层所谓的“文件名队列”。 为何要添加这一层文件名队列?咱们首先得了解机器学习中的一个概念:epoch。对于一个数据集来说,运行一个epoch就是将这个数据集中的图片所有计算一遍。如一个数据集中有三张图片A.jpg、B.jpg、C.jpg,那么跑一个epoch就是指对A、B、C三张图片都计算了一遍。两个epoch就是指先对A、B、C各计算一遍,而后再所有计算一遍,也就是说每张图片都计算了两遍。 tensorflow使用文件名队列+内存队列双队列的形式读入文件,能够很好地管理epoch。下面咱们用图片的形式来讲明这个机制的运行方式。以下图,仍是以数据集A.jpg, B.jpg, C.jpg为例,假定咱们要跑一个epoch,那么咱们就在文件名队列中把A、B、C各放入一次,并在以后标注队列结束。
程序运行后,内存队列首先读入A(此时A从文件名队列中出队):
再依次读入B和C:
此时,若是再尝试读入,系统因为检测到了“结束”,就会自动抛出一个异常(OutOfRange)。外部捕捉到这个异常后就能够结束程序了。这就是tensorflow中读取数据的基本机制。若是咱们要跑2个epoch而不是1个epoch,那只要在文件名队列中将A、B、C依次放入两次再标记结束就能够了。
8.4 TensorFlow读取数据机制的对应函数
如何在tensorflow中建立文件名队列与内存队列呢?
对于文件名队列,咱们使用tf.train.string_input_producer函数。这个函数须要传入一个文件名list,系统会自动将它转为一个文件名队列。 此外tf.train.string_input_producer还有两个重要的参数,一个是num_epochs,它就是咱们上文中提到的epoch数。另一个就是shuffle,shuffle是指在一个epoch内文件的顺序是否被打乱。若设置shuffle=False,以下图,每一个epoch内,数据仍是按照A、B、C的顺序进入文件名队列,这个顺序不会改变:
若是设置shuffle=True,那么在一个epoch内,数据的先后顺序就会被打乱,以下图所示:
在tensorflow中,内存队列不须要咱们本身创建,咱们只须要使用reader对象从文件名队列中读取数据就能够了,具体实现能够参考下面的实战代码。 除了tf.train.string_input_producer外,咱们还要额外介绍一个函数:tf.train.start_queue_runners。在咱们使用tf.train.string_input_producer建立文件名队列后,整个系统其实仍是处于“停滞状态”的,也就是说,咱们文件名并无真正被加入到队列中(以下图所示)。此时若是咱们开始计算,由于内存队列中什么也没有,计算单元就会一直等待,致使整个系统被阻塞。
而使用tf.train.start_queue_runners以后,才会启动填充队列的线程,这时系统就再也不“停滞”。此后计算单元就能够拿到数据并进行计算,整个程序也就跑起来了,这就是函数tf.train.start_queue_runners的用处。
8.5 TensorFlow读取数据的线程操做
8.6 TensorFlow读取图片数据
图像基本知识
对于图像文件,咱们怎么进行转换成机器学习可以理解的数据?对于图片来说,组成图片的最基本单位是像素,因此咱们获取的是每张图片的像素值。接触的图片有两种,一种是黑白图片,另外一种是彩色图片。
案例:狗图片读取
代码
"""
狗图片读取案例
"""
import tensorflow as tf
import os
def picture_read(file_list):
"""
读取狗图片数据到张量
:param file_list:路径+文件名的列表
:return:
"""
# 1. 构造图片文件名队列
# 返回文件名队列
file_queue = tf.train.string_input_producer(file_list)
# 2. 构造一个图片读取器,利用图片读取器去读取队列中的内容
reader = tf.WholeFileReader()
# 默认一次读取一张图片,没有形状
key, value = reader.read(file_queue)
# 3. 对读取到的图片内容进行解码
# 数据类型从string---->unit8
# 形状从()---->(???)
image = tf.image.decode_jpeg(value)
# 4. 图片特征值处理:对图片进行批处理以前,进行形状与大小的固定
# 把图片固定成统一大小的目的是由于训练的数据集的每一个样本的特征值应该相同。
# 设置成固定的大小
image_resized = tf.image.resize_images(image, size=[200, 200])
# 设置固定的通道数,使用静态改变形状的方法:set_shape()
image_resized.set_shape([200, 200, 3])
# 5. 对图片数据进行批处理,批处理以前,每一个样本的形状必须固定
image_batch = tf.train.batch([image_resized], batch_size=10, num_threads=4, capacity=10)
# 在默认图中进行会话操做 g = tf.get_default_graph() with g.as_default(): # 开启会话 with tf.Session() as sess: # 1 手动开启子线程去进行批处理读取到队列操做 # 1.1 建立用于线程回收的协调器 coord = tf.train.Coordinator() # 1.2 开启子线程去读取数据,返回子线程实例 threads = tf.train.start_queue_runners(sess=sess, coord=coord) # 2. 获取样本数据 pic_data = sess.run([image_batch]) print(pic_data) # 3. 回收子线程 coord.request_stop() coord.join(threads)
if name == 'main':
# 生成文件名列表
file_name_list = os.listdir('../data/dog/')
# 构造文件名+路径列表
file_list = [os.path.join('../data/dog/', file) for file in file_name_list]
# 图片文件读取
picture_read(file_list)
8.7 TensorFlow利用二进制方式读取CIFAR10数据集
<1×标签> <3072×像素> ... <1×标签> <3072×像素>
代码
"""
CIFAR10数据集二进制版本的读取
"""
import tensorflow as tf
import os
class CifarRead(object):
"""
CIFAR二进制文件的读取
"""
def __init__(self, filename_list): """ 定义一些图片的样本属性 :param filename_list: """ self.filename_list = filename_list self.height = 32 self.width = 32 self.channel = 3 self.label_bytes = 1 self.image_bytes = self.height * self.width * self.channel self.bytes = self.label_bytes + self.image_bytes def read_and_decode(self): """ 读取二进制原始数据并解码成张量 :return: """ # 1. 构造文件队列 file_queue = tf.train.string_input_producer(self.filename_list) # 2. 使用二进制读取器读取内容 # 2.1 建立二进制读取器实例,实在一次读取的字节数 reader = tf.FixedLengthRecordReader(self.bytes) # 2.2 读取内容,一共读取1+3072=3073个字节,此时的value是某个文件的某个样本 key, value = reader.read(file_queue) # 3. 对二进制数据进行解码 decode_raw label_image = tf.decode_raw(value, tf.uint8) # 4. 切分图片的特征值与目标值:使用tf.slice(数据集,[起始下标],[结束下标])切片 label = tf.slice(label_image, [0], [self.label_bytes]) image = tf.slice(label_image, [self.label_bytes], [self.image_bytes]) # 5. 标签、图片的类型转换、形状转换 # 5.1 标签数据类型转换 tf.cast() label_cast = tf.cast(label, tf.int32) image = tf.cast(image, tf.float32) # 5.2 固定图片的特征值形状 # 5.2.1 shape:(3072,)--->[channel,height,width] depth_major = tf.reshape(image, [self.channel, self.height, self.width]) print(depth_major) # 5.2.2 tf.transpose:[channel,height,width]--->[heigt,width,channel] image_reshaped = tf.transpose(depth_major, [1, 2, 0]) print(image_reshaped) # 6.批处理图片数据 image_batch, label_batch = tf.train.batch([image_reshaped, label_cast], batch_size=10, num_threads=4, capacity=10) print(image_batch) print(label_batch) return image_batch, label_batch def run(self): """ 执行文件读取逻辑 :return: """ # 读取二进制原始数据并解码成张量,形状固定于批处理 image_batch, label_batch = self.read_and_decode() # 开启会话 with tf.Session() as sess: # 1. 手动开启子线程去进行数据的批处理读取到队列的操做 # 1.1 建立用于线程回收的协调器 coord = tf.train.Coordinator() # 1.2 开启子线程去读取数据 threads = tf.train.start_queue_runners(sess=sess, coord=coord) # 2. 获取样本数据 pic_data = sess.run([image_batch, label_batch]) print(pic_data) # 3. 回收子线程 coord.request_stop() coord.join(threads)
if name == 'main':
# 生成文件名列表
filename_list = os.listdir('../data/cifar10/cifar-10-batches-bin/')
# 生成文件名加路径列表
filename_list = [os.path.join('../data/cifar10/cifar-10-batches-bin/', file) for file in filename_list if
file[-3:] == 'bin']
# 实例化类
cr = CifarRead(filename_list)
cr.run()
In [7]: tf.reshape([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], [2, 2, 3]).eval()
Out[7]:
array([[[ 1, 2, 3],
[ 4, 5, 6]],
[[ 7, 8, 9], [10, 11, 12]]], dtype=int32)
In [8]: tf.reshape([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], [3, 2, 2]).eval()
Out[8]:
array([[[ 1, 2],
[ 3, 4]],
[[ 5, 6], [ 7, 8]], [[ 9, 10], [11, 12]]], dtype=int32)
In [17]: tf.transpose(depth_major, [1, 2, 0]).eval()
Out[17]:
array([[[ 1, 5, 9],
[ 2, 6, 10]],
[[ 3, 7, 11], [ 4, 8, 12]]], dtype=int32)
8.8 CIFAR10类图片的数据的TFRecords存储和读取
数据存入TFRecords文件
什么是TFRecords文件
什么是Example结构?
Feature字段中包含要写入的数据、并指明数据类型。这是一个样本的结构,批数据须要循环的存入这样的结构。
example = tr.train.Example(features=tf.train.Features(feature={
"特征值字段名":tf.train.Feature(特征值数据类型列表=tf.train.特征值数据类型列表类(value=[特征值字段名])),
"标签值字段名":tf.train.Feature(标签值数据类型列表=tf.train.标签值数据类型列表类(value=[标签值字段名]))
}))
写入数据到TFRecords中的主要步骤:
写入数据到TFRecords中的示例代码:
def wite_to_tfrecords(self, image_batch, label_batch): """ 将文件写入到TFRecords文件中 :param image_batch: :param label_batch: :return: """ # 1. 创建TFRecords文件存储器 writer = tf.python_io.TFRecordWriter('./1.tfrecords') # 设置路径及文件名 # 2. 循环取出每一个样本的值,构造example协议块 for i in range(10): # 由于每批量有10个样本数据 # 2.1 取出图片的值 # 写入文件的是值,而不是tensor类型,写入example须要bytes类型数据,须要用tostring()来转化 image = image_batch[i].eval().tostring() # 2.2 取出标签值,写入example中须要int类型,因此须要强制转换成int类型 label = int(label_batch[i].eval()[0]) # 2.3 构造每一个样本的example协议块 feature = { "image": tf.train.Feature(bytes_list=tf.train.BytesList(value=[image])), "label": tf.train.Feature(int64_list=tf.train.Int64List(value=[label])) } features = tf.train.Features(feature=feature) example = tf.train.Example(features=features) # 2.4 将example协议块序列化 example_serialized = example.SerializeToString() # 2.5 写入序列化后的值 writer.write(example_serialized) # 此处实际上是将其压缩成一个二进制数据 # 3. 关闭文件存储器 writer.close() return None
8.9 从TFRecords文件中读取数据
解析example
feature = tr.parse_single_example(values,features={ "image":tf.FixedLenFeature([],tf.string), "label":tf.FixedLenFeature([],tf.int64) })
从TFRecords文件中读取数据的主要步骤:
从TFRecords文件中读取数据示例代码:
def read_to_tfrecords(self): """ 从TFRecords文件中读取图片数据(解析example) :return: """ pass # 1. 构造文件队列 file_queue = tf.train.string_input_producer(['./1.tfrecords']) # 参数为文件名列表 # 2. 实例化TFRecords文件阅读器 reader = tf.TFRecordReader() # 读取数据 key, value = reader.read(file_queue) # 3. 解析example协议块,返回值是字典 features = { "image": tf.FixedLenFeature([], tf.string), "label": tf.FixedLenFeature([], tf.int64) } feature = tf.parse_single_example(value, features=features) # 4. 处理标签数据 # cast()只能在int和float之间进行转换,将数据类型int64 转换为int32 label = tf.cast(feature["label"], tf.int32) # 处理图片数据 # 因为是一个string,要进行解码, # 将字节转换为数字向量表示,字节为一字符串类型的张量 # 若是以前用了tostring(),那么必需要用decode_raw()转换为最初的int类型 # decode_raw()能够将数据从string,bytes转换为int,float类型 image = tf.decode_raw(feature['image'], tf.uint8) # 5. 转换图片的形状,此处须要用动态形状进行转换 image_tensor = tf.reshape(image, [self.height, self.width, self.channel]) # 6. 批处理 image_batch, label_batch = tf.train.batch([image_tensor, label], batch_size=10, num_threads=4, capacity=10) return image_batch, label_batch
CIFAR10类图片的数据的TFRecords存储和读取示例代码
import tensorflow as tf import os """ 读取二进制文件转换成张量,写进TFRecords,同时读取TFRcords """ # 命令行参数 FLAGS = tf.app.flags.FLAGS # 获取值 tf.app.flags.DEFINE_string("tfrecord_dir", "./tmp/cifar10.tfrecords", "写入图片数据文件的文件名") # 读取二进制转换文件 class CifarRead(object): """ 读取二进制文件转换成张量,写进TFRecords,同时读取TFRcords """ def __init__(self, file_list): """ 初始化图片参数 :param file_list:图片的路径名称列表 """ # 文件列表 self.file_list = file_list # 图片大小,二进制文件字节数 self.height = 32 self.width = 32 self.channel = 3 self.label_bytes = 1 self.image_bytes = self.height * self.width * self.channel self.bytes = self.label_bytes + self.image_bytes def read_and_decode(self): """ 解析二进制文件到张量 :return: 批处理的image,label张量 """ # 1.构造文件队列 file_queue = tf.train.string_input_producer(self.file_list) # 2.阅读器读取内容 reader = tf.FixedLengthRecordReader(self.bytes) key, value = reader.read(file_queue) # key为文件名,value为元组 print(value) # 3.进行解码,处理格式 label_image = tf.decode_raw(value, tf.uint8) print(label_image) # 处理格式,image,label # 进行切片处理,标签值 # tf.cast()函数是转换数据格式,此处是将label二进制数据转换成int32格式 label = tf.cast(tf.slice(label_image, [0], [self.label_bytes]), tf.int32) # 处理图片数据 image = tf.slice(label_image, [self.label_bytes], [self.image_bytes]) print(image) # 处理图片的形状,提供给批处理 # 由于image的形状已经固定,此处形状用动态形状来改变 depth_major = tf.reshape(image, [self.channel, self.height, self.width]) image_tensor = tf.transpose(depth_major, [1, 2, 0]) print(image_tensor) # 批处理图片数据 image_batch, label_batch = tf.train.batch([image_tensor, label], batch_size=10, num_threads=1, capacity=10) return image_batch, label_batch def write_to_tfrecords(self, image_batch, label_batch): """ 将文件写入到TFRecords文件中 :param image_batch: :param label_batch: :return: """ # 创建TFRecords文件存储器 writer = tf.python_io.TFRecordWriter('./1.tfrecords') # 传进去命令行参数 # 循环取出每一个样本的值,构造example协议块 for i in range(10): # 取出图片的值, #写进去的是值,而不是tensor类型, # 写入example须要bytes文件格式,将tensor转化为bytes用tostring()来转化 image = image_batch[i].eval().tostring() # 取出标签值,写入example中须要使用int形式,因此须要强制转换int label = int(label_batch[i].eval()[0]) # 构造每一个样本的example协议块 example = tf.train.Example(features=tf.train.Features(feature={ "image": tf.train.Feature(bytes_list=tf.train.BytesList(value=[image])), "label": tf.train.Feature(int64_list=tf.train.Int64List(value=[label])) })) # 写进去序列化后的值 writer.write(example.SerializeToString()) # 此处实际上是将其压缩成一个二进制数据 writer.close() return None def read_from_tfrecords(self): """ 从TFRecords文件当中读取图片数据(解析example) :param self: :return: image_batch,label_batch """ # 1.构造文件队列 file_queue = tf.train.string_input_producer(['./1.tfrecords']) # 参数为文件名列表 # 2.构造阅读器 reader = tf.TFRecordReader() key, value = reader.read(file_queue) # 3.解析协议块,返回的值是字典 feature = tf.parse_single_example(value, features={ "image": tf.FixedLenFeature([], tf.string), "label": tf.FixedLenFeature([], tf.int64) }) # feature["image"],feature["label"] # 处理标签数据 ,cast()只能在int和float之间进行转换 label = tf.cast(feature["label"], tf.int32) # 将数据类型int64 转换为int32 # 处理图片数据,因为是一个string,要进行解码, #将字节转换为数字向量表示,字节为一字符串类型的张量 # 若是以前用了tostring(),那么必需要用decode_raw()转换为最初的int类型 # decode_raw()能够将数据从string,bytes转换为int,float类型的 image = tf.decode_raw(feature["image"], tf.uint8) # 转换图片的形状,此处须要用动态形状进行转换 image_tensor = tf.reshape(image, [self.height, self.width, self.channel]) # 4.批处理 image_batch, label_batch = tf.train.batch([image_tensor, label], batch_size=10, num_threads=1, capacity=10) return image_batch, label_batch def run(self): """ 实现读取数据的主逻辑 :return: """ # 读取二进制文件 # image_batch,label_batch = self.read_and_decode() # 从已经存储的TFRecords文件中解析出原始数据 image_batch, label_batch = self.read_from_tfrecords() with tf.Session() as sess: # 线程协调器 coord = tf.train.Coordinator() # 开启线程 threads = tf.train.start_queue_runners(sess, coord=coord) print(sess.run([image_batch, label_batch])) print("存进TFRecords文件") # self.write_to_tfrecords(image_batch,label_batch) print("存进文件完毕") # 回收线程 coord.request_stop() coord.join(threads) if __name__ == '__main__': # 找到文件路径,名字,构造路径+文件名的列表,"A.csv"... # os.listdir() 方法用于返回指定的文件夹包含的文件或文件夹的名字的列表 filename = os.listdir('../data/cifar10/cifar-10-batches-bin/') # 加上路径 file_list = [os.path.join('../data/cifar10/cifar-10-batches-bin/', file) for file in filename if file[-3:] == "bin"] # 建立一个文件读取对象 cr = CifarRead(file_list) # 开始运行 cr.run()
9 Tensorflow中其它基础API与高级API
9.1 基础API
9.2 高级API
10 TensorFlow训练稀疏模型
TensorFlow 中的 layers 模块
TensorFlow 中的 layers 模块提供用于深度学习的更高层次封装的 API,利用它咱们能够轻松地构建模型,这一节咱们就来看下这个模块的 API 的具体用法。
11 TensorFlow中的layers模块
11.1 概览
layers 模块的路径写法为 tf.layers,这个模块定义在 tensorflow/python/layers/layers.py,其官方文档地址为:https://www.tensorflow.org/api_docs/python/tf/layers,TensorFlow 版本为 1.5。
这里面提供了多个类和方法以供使用,下面咱们分别予以介绍。
11.2 方法
tf.layers 模块提供的方法有:
11.2.1 tf.layers.Input
tf.layers.Input() 这个方法是用于输入数据的方法,其实相似于 tf.placeholder,至关于一个占位符的做用,固然也能够经过传入 tensor 参数来进行赋值。
Input( shape=None, batch_size=None, name=None, dtype=tf.float32, sparse=False, tensor=None )
参数说明以下:
返回值: 返回一个包含历史 Meta Data 的 Tensor。
咱们用一个实例来感觉一下:
x = tf.layers.Input(shape=[32]) print(x) y = tf.layers.dense(x, 16, activation=tf.nn.softmax) print(y)
首先咱们用 Input() 方法初始化了一个 placeholder,这时咱们没有传入 tensor 参数,而后调用了 dense() 方法构建了一个全链接网络,激活函数使用 softmax,而后将两者输出,结果以下:
Tensor("input_layer_1:0", shape=(?, 32), dtype=float32) Tensor("dense/Softmax:0", shape=(?, 16), dtype=float32)
这时咱们发现,shape 它给咱们作了转化,原本是 [32],结果它给转化成了 [?, 32],即第一维表明 batch_size,因此咱们须要注意,在调用此方法的时候不须要去关心 batch_size 这一维。
若是咱们在初始化的时候传入一个已有 Tensor,例如:
data = tf.constant([1, 2, 3]) x = tf.layers.Input(tensor=data) print(x)
结果以下:
data = tf.constant([1, 2, 3]) x = tf.layers.Input(tensor=data) print(x)
能够看到它能够自动计算出其 shape 和 dtype。
11.2.2 tf.layers.batch_normalization
此方法是批量标准化的方法,通过处理以后能够加速训练速度,其定义在 tensorflow/python/layers/normalization.py,论文能够参考:http://arxiv.org/abs/1502.03167 “Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift”。
batch_normalization( inputs, axis=-1, momentum=0.99, epsilon=0.001, center=True, scale=True, beta_initializer=tf.zeros_initializer(), gamma_initializer=tf.ones_initializer(), moving_mean_initializer=tf.zeros_initializer(), moving_variance_initializer=tf.ones_initializer(), beta_regularizer=None, gamma_regularizer=None, beta_constraint=None, gamma_constraint=None, training=False, trainable=True, name=None, reuse=None, renorm=False, renorm_clipping=None, renorm_momentum=0.99, fused=None, virtual_batch_size=None, adjustment=None )
参数说明以下:
最后的一些参数说明不够详尽,更详细的用法参考:https://www.tensorflow.org/api_docs/python/tf/layers/batch_normalization。
其用法很简单,在输入数据后面加一层 batch_normalization() 便可:
x = tf.layers.Input(shape=[32]) x = tf.layers.batch_normalization(x) y = tf.layers.dense(x, 20)
11.2.3 tf.layers.dense
dense,即全链接网络,layers 模块提供了一个 dense() 方法来实现此操做,定义在 tensorflow/python/layers/core.py 中,下面咱们来讲明一下它的用法。
dense( inputs, units, activation=None, use_bias=True, kernel_initializer=None, bias_initializer=tf.zeros_initializer(), kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, bias_constraint=None, trainable=True, name=None, reuse=None )
参数说明以下:
返回值: 全链接网络处理后的 Tensor。
下面咱们用一个实例来感觉一下它的用法:
x = tf.layers.Input(shape=[32]) print(x) y1 = tf.layers.dense(x, 16, activation=tf.nn.relu) print(y1) y2 = tf.layers.dense(y1, 5, activation=tf.nn.sigmoid) print(y2)
首先咱们用 Input 定义了 [?, 32] 的输入数据,而后通过第一层全链接网络,此时指定了神经元个数为 16,激活函数为 relu,接着输出结果通过第二层全链接网络,此时指定了神经元个数为 5,激活函数为 sigmoid,最后输出,结果以下:
x = tf.layers.Input(shape=[32]) print(x) y1 = tf.layers.dense(x, 16, activation=tf.nn.relu) print(y1) y2 = tf.layers.dense(y1, 5, activation=tf.nn.sigmoid) print(y2)
能够看到输出结果的最后一维度就等于神经元的个数,这是很是容易理解的。
11.2.4 tf.layers.convolution
convolution,即卷积,这里提供了多个卷积方法,如 conv1d()、conv2d()、conv3d(),分别表明一维、二维、三维卷积,另外还有 conv2d_transpose()、conv3d_transpose(),分别表明二维和三维反卷积,还有 separable_conv2d() 方法表明二维深度可分离卷积。它们定义在 tensorflow/python/layers/convolutional.py 中,其用法都是相似的,在这里以 conv2d() 方法为例进行说明。
conv2d( inputs, filters, kernel_size, strides=(1, 1), padding='valid', data_format='channels_last', dilation_rate=(1, 1), activation=None, use_bias=True, kernel_initializer=None, bias_initializer=tf.zeros_initializer(), kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, bias_constraint=None, trainable=True, name=None, reuse=None )
参数说明以下:
返回值: 卷积后的 Tensor。
下面咱们用实例感觉一下它的用法:
x = tf.layers.Input(shape=[20, 20, 3]) y = tf.layers.conv2d(x, filters=6, kernel_size=2, padding='same') print(y) 这里咱们首先声明了一个 [?, 20, 20, 3] 的输入 x,而后将其传给 conv2d() 方法,filters 设定为 6,即输出通道为 6,kernel_size 为 2,即卷积核大小为 2 x 2,padding 方式设置为 same,那么输出结果的宽高和原来必定是相同的,可是输出通道就变成了 6,结果以下: Tensor("conv2d/BiasAdd:0", shape=(?, 20, 20, 6), dtype=float32)
但若是咱们将 padding 方式不传入,使用默认的 valid 模式,代码改写以下:
x = tf.layers.Input(shape=[20, 20, 3]) y = tf.layers.conv2d(x, filters=6, kernel_size=2) print(y)
结果以下:
Tensor("conv2d/BiasAdd:0", shape=(?, 19, 19, 6), dtype=float32)
结果就变成了 [?, 19, 19, 6],这是由于步长默认为 1,卷积核大小为 2 x 2,因此获得的结果的高宽即为 (20 – (2 – 1)) x (20 – (2 – 1)) = 19 x 19。
固然卷积核咱们也能够变换大小,传入一个列表形式:
x = tf.layers.Input(shape=[20, 20, 3]) y = tf.layers.conv2d(x, filters=6, kernel_size=[2, 3]) print(y)
这时咱们的卷积核大小变成了 2 x 3,即高为 2,宽为 3,结果就变成了 [?, 19, 18, 6],这是由于步长默认为 1,卷积核大小为 2 x 2,因此获得的结果的高宽即为 (20 – (2 – 1)) x (20 – (3 – 1)) = 19 x 18。
若是咱们将步长也设置一下,也传入列表形式:
x = tf.layers.Input(shape=[20, 20, 3]) y = tf.layers.conv2d(x, filters=6, kernel_size=[2, 3], strides=[2, 2]) print(y)
这时卷积核大小变成了 2 x 3,步长变成了 2 x 2,因此结果的高宽为 ceil(20 – (2- 1)) / 2 x ceil(20 – (3- 1)) / 2 = 10 x 9,获得的结果即为 [?, 10, 9, 6]。
运行结果以下:
Tensor("conv2d_4/BiasAdd:0", shape=(?, 10, 9, 6), dtype=float32)
另外咱们还能够传入激活函数,或者禁用 bias 等操做,实例以下:
x = tf.layers.Input(shape=[20, 20, 3]) y = tf.layers.conv2d(x, filters=6, kernel_size=2, activation=tf.nn.relu, use_bias=False) print(y)
这样咱们就将激活函数改为了 relu,同时禁用了 bias,运行结果以下:
Tensor("conv2d_5/Relu:0", shape=(?, 19, 19, 6), dtype=float32)
另外还有反卷积操做,反卷积顾名思义即卷积的反向操做,即输入卷积的结果,获得卷积前的结果,其参数用法是彻底同样的,例如:
x = tf.layers.Input(shape=[20, 20, 3]) y = tf.layers.conv2d_transpose(x, filters=6, kernel_size=2, strides=2) print(y)
例如此处输入的图像高宽为 20 x 20,通过卷积核为 2,步长为 2 的反卷积处理,获得的结果高宽就变为了 40 x 40,结果以下:
Tensor("conv2d_transpose/BiasAdd:0", shape=(?, 40, 40, 6), dtype=float32)
11.2.5 tf.layers.pooling
pooling,即池化,layers 模块提供了多个池化方法,这几个池化方法都是相似的,包括 max_pooling1d()、max_pooling2d()、max_pooling3d()、average_pooling1d()、average_pooling2d()、average_pooling3d(),分别表明一维二维三维最大和平均池化方法,它们都定义在 tensorflow/python/layers/pooling.py 中,这里以 max_pooling2d() 方法为例进行介绍。
max_pooling2d( inputs, pool_size, strides, padding='valid', data_format='channels_last', name=None )
参数说明以下:
返回值: 通过池化处理后的 Tensor。
下面咱们用一个实例来感觉一下:
x = tf.layers.Input(shape=[20, 20, 3]) print(x) y = tf.layers.conv2d(x, filters=6, kernel_size=3, padding='same') print(y) p = tf.layers.max_pooling2d(y, pool_size=2, strides=2) print(p)
在这里咱们首先指定了输入 x,shape 为 [20, 20, 3],而后对其进行了卷积计算,而后池化,最后获得池化后的结果。结果以下:
Tensor("input_layer_1:0", shape=(?, 20, 20, 3), dtype=float32) Tensor("conv2d/BiasAdd:0", shape=(?, 20, 20, 6), dtype=float32) Tensor("max_pooling2d/MaxPool:0", shape=(?, 10, 10, 6), dtype=float32)
能够看到这里池化窗口用的是 2,步长也是 2,因此本来卷积后 shape 为 [?, 20, 20, 6] 的结果就变成了 [?, 10, 10, 6]。
11.2.6 tf.layers.dropout
dropout 是指在深度学习网络的训练过程当中,对于神经网络单元,按照必定的几率将其暂时从网络中丢弃,能够用来防止过拟合,layers 模块中提供了 dropout() 方法来实现这一操做,定义在 tensorflow/python/layers/core.py。下面咱们来讲明一下它的用法。
dropout( inputs, rate=0.5, noise_shape=None, seed=None, training=False, name=None )
参数说明以下:
返回: 通过 dropout 层以后的 Tensor。
咱们用一个实例来感觉一下:
x = tf.layers.Input(shape=[32]) print(x) y = tf.layers.dense(x, 16, activation=tf.nn.softmax) print(y) d = tf.layers.dropout(y, rate=0.2) print(d)
运行结果:
Tensor("input_layer_1:0", shape=(?, 32), dtype=float32) Tensor("dense/Softmax:0", shape=(?, 16), dtype=float32) Tensor("dropout/Identity:0", shape=(?, 16), dtype=float32)
在这里咱们使用 dropout() 方法实现了 droput 操做,并制定 dropout rate 为 0.2,最后输出结果的 shape 和原来是一致的。
11.2.7 tf.layers.flatten
flatten() 方法能够对 Tensor 进行展平操做,定义在 tensorflow/python/layers/core.py。
flatten( inputs, name=None )
参数说明以下:
返回结果: 展平后的 Tensor。
下面咱们用一个实例来感觉一下:
x = tf.layers.Input(shape=[5, 6]) print(x) y = tf.layers.flatten(x) print(y)
运行结果:
Tensor("input_layer_1:0", shape=(?, 5, 6), dtype=float32) Tensor("flatten/Reshape:0", shape=(?, 30), dtype=float32)
这里输入数据的 shape 为 [?, 5, 6],通过 flatten 层以后,就会变成 [?, 30],即将除了第一维的数据维度相乘,对原 Tensor 进行展平。
假如第一维是一个已知的数的话,它依然仍是一样的处理,示例以下:
Tensor("input_layer_1:0", shape=(?, 5, 6), dtype=float32) Tensor("flatten/Reshape:0", shape=(?, 30), dtype=float32)
结果以下:
Tensor("input_layer_1:0", shape=(?, 5, 6), dtype=float32) Tensor("flatten/Reshape:0", shape=(?, 30), dtype=float32)
12 TensorFlow 计算交叉熵错误问题解决
sparse_softmax_cross_entropy_with_logits(_sentinel=None, labels=None, logits=None, name=None)
在使用tf.nn.sparse_softmax_cross_entropy_with_logits(logits, labels)语句时产生以下错误:
import tensorflow as tf labels = [[0.2,0.3,0.5], [0.1,0.6,0.3]] logits = [[2,0.5,1], [0.1,1,3]]result1 = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=labels, logits=logits)若是这样用就会报这个错ValueError: Rank mismatch: Rank of labels (received 2) should equal rank of logits minus 1 (received 2).
下面演示一下,两个方法的正确用法:
import tensorflow as tf labels = [[0.2,0.3,0.5], [0.1,0.6,0.3]] logits = [[2,0.5,1], [0.1,1,3]]result1 = tf.nn.softmax_cross_entropy_with_logits(labels=labels, logits=logits) import tensorflow as tf labels = [0,2] logits = [[2,0.5,1], [0.1,1,3]] result1 = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=labels, logits=logits)
总结:
tf.nn.in_top_k函数的用法
'''
predictions: 你的预测结果(通常也就是你的网络输出值)大小是预测样本的数量乘以输出的维度
target: 实际样本类别的标签,大小是样本数量的个数
k: 每一个样本中前K个最大的数里面(序号)是否包含对应target中的值
'''
import tensorflow as tf
A = tf.Variable([[0.8, 0.4, 0.5, 0.6],[0.1, 0.9, 0.2, 0.4],[0.1, 0.9, 0.4, 0.2]])
B = tf.Variable([1, 1, 2])
result = tf.nn.in_top_k(A, B, 2)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print(sess.run(A))
print(sess.run(B))
print(sess.run(result))
'''
解释:
k取1的时候:
由于A中第一个元素的最大值为0.8,索引(序号)是0,而B是1,不包含B,因此返回False.
A中第二个元素的最大值为0.9,索引(序号)是1,而B是1,包含B,因此返回True.
A中第三个元素的最大值为0.9,索引(序号)是1,而B是2,不包含B,因此返回False.
k取2的时候:
由于A中前两个元素的最大值为0.8,0.6,索引(序号)是0,3,而B是1,不包含B,因此返回False.
A中前两个元素的最大值为0.9,0.4,索引(序号)是1,3,而B是1,包含B,因此返回True.
A中前两个元素的最大值为0.9,0.4,索引(序号)是1,2,而B是2,包含B,因此返回True.
'''
案例:TensorFlow1实现全链接神经网络识别手势数据集
""" 一天下午,咱们和一些朋友决定教咱们的电脑破译手语。咱们花了几个小时在白色的墙壁前拍照,因而就有了了如下数据集。如今,你的任务是创建一个算法,使有语音障碍的人与不懂手语的人交流。 训练集:有从0到5的数字的1080张图片(64x64像素),每一个数字拥有180张图片。 测试集:有从0到5的数字的120张图片(64x64像素),每一个数字拥有5张图片。 须要注意的是这是完整数据集的一个子集,完整的数据集包含更多的符号。 下面是每一个数字的样本,以及咱们如何表示标签的解释。这些都是原始图片,咱们实际上用的是64 * 64像素的图片。 """ import numpy as np import h5py import matplotlib.pyplot as plt import time import math import tensorflow as tf # %matplotlib inline #若是你使用的是jupyter notebook取消注释 np.random.seed(1) class GestureSymbolRecognition(object): def __init__(self): self.learning_rate = 0.0001 self.num_epochs = 1500 self.minibatch_size = 32 self.regularazion_rate = 0.001 self.n_inputs = 12288 self.n_hidden1 = 100 self.n_hidden2 = 100 self.n_hidden3 = 100 self.n_outputs = 6 self.batch_norm_momentum = 0.9 def load_data(self): """ 加载数据集 :return: """ # 从文件中读取训练集数据 train_dataset = h5py.File('datasets/train_signs.h5', "r") # 从训练集数据中提取特征值与标签值数据 train_set_x_orig = np.array(train_dataset["train_set_x"][:]) train_set_y_orig = np.array(train_dataset["train_set_y"][:]) # 从文件中读取测试集数据 test_dataset = h5py.File('datasets/test_signs.h5', "r") # 从测试集数据中提取特征值与标签值数据 test_set_x_orig = np.array(test_dataset["test_set_x"][:]) test_set_y_orig = np.array(test_dataset["test_set_y"][:]) classes = np.array(test_dataset["list_classes"][:]) # 类别列表 classes_num = len(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])) X_train_flatten = train_set_x_orig.reshape(train_set_x_orig.shape[0], -1) # 每一列就是一个样本 X_test_flatten = test_set_x_orig.reshape(test_set_x_orig.shape[0], -1) # 归一化数据 X_train = X_train_flatten / 255 X_test = X_test_flatten / 255 # 转换为one-hot编码矩阵 Y_train = self.convert_to_one_hot(train_set_y_orig, len(classes)).T Y_test = self.convert_to_one_hot(test_set_y_orig, len(classes)).T return X_train, Y_train, X_test, Y_test, classes_num def convert_to_one_hot(self, Y, C): """ 实现one-hot编码 :param Y:标签矩阵 :param C:分类数量 :return:one_hot:one-hot矩阵 """ one_hot = np.eye(C)[Y.reshape(-1)].T return one_hot def random_mini_batches(self, X, Y, mini_batch_size, seed=0): """ 从数据集中建立一个随机的mini-batch列表 :param X: 输入数据,维度为(输入节点数量,样本数量) :param Y: 对应的目标值,维度为(1,样本数量) :param mini_batch_size: 每一个mini-batch的样本数量 :param seed: 随机数种子 :return: mini_batches:一个同步列表,维度为(mini_batch_X, mini_batch_Y) """ # 指定随机数种子 np.random.seed(seed) # 获取样本数 m = X.shape[0] # print('样本数量',m) # 建立一个同步列表 mini_batches = [] # 第一步:打乱样本的顺序 permutation = list(np.random.permutation(m)) # 返回一个长度为m的随机数组,且里面的数是0到m-1 shuffled_X = X[permutation, :] # 将每一列特征值数据按permutation的顺序来从新排列 shuffled_Y = Y[permutation, :] # .reshape((Y.shape[0], m)) # 将每一列的目标值数据按permutation的顺序来从新排列 # 第二步:分割训练集数据 num_complete_minibatches = math.floor(m / mini_batch_size) # 迭代完成整个训练集的次数 for k in range(0, num_complete_minibatches): mini_batch_X = shuffled_X[k * mini_batch_size:(k + 1) * mini_batch_size, :] mini_batch_Y = shuffled_Y[k * mini_batch_size:(k + 1) * mini_batch_size, :] mini_batch = (mini_batch_X, mini_batch_Y) mini_batches.append(mini_batch) # 若是训练集的大小不是mini_batch_size的整数倍,那么最后确定会剩下一些,取剩余的数据 if m % mini_batch_size != 0: # 获取剩余部分的数据 mini_batch_X = shuffled_X[mini_batch_size * num_complete_minibatches:, :] mini_batch_Y = shuffled_Y[mini_batch_size * num_complete_minibatches:, :] mini_batch = (mini_batch_X, mini_batch_Y) mini_batches.append(mini_batch) # 返回同步列表 return mini_batches def train(self, print_cost=True, is_plot=True): """ 实现一个三层的TensorFlow神经网络训练逻辑:LINEAR->RELU->LINEAR->RELU->LINEAR->SOFTMAX 参数: print_cost - 是否打印成本,每100代打印一次 is_plot - 是否绘制曲线图 """ # 加载数据集 x_train, y_train, x_test, y_test, label_classes_num = self.load_data() print("训练集样本数 = " + str(x_train.shape[0])) print("测试集样本数 = " + 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)) # 设置图级别的随机数种子 tf.set_random_seed(1) # 设置操做级别的随机数种子 seed = 3 # 获取输入节点数量和样本数 (m, n_x) = x_train.shape # 成本函数值列表 costs = [] # 给X和Y建立占位符节点 X = tf.placeholder(tf.float32, shape=(None, self.n_inputs), name="X") Y = tf.placeholder(tf.int32, shape=(None, label_classes_num), name="y") # 定义神经网络全链接层 with tf.name_scope("dnn"): # 使用He权重初始化方法初始化权重 he_init = tf.variance_scaling_initializer(mode="fan_avg") # 定义全链接层,使用elu激活函数 hidden1 = tf.layers.dense(X, self.n_hidden1, name="hidden1", kernel_initializer=he_init, activation=tf.nn.elu, ) hidden2 = tf.layers.dense(hidden1, self.n_hidden2, name="hidden2", kernel_initializer=he_init, activation=tf.nn.elu) hidden3 = tf.layers.dense(hidden2, self.n_hidden3, name="hidden3", kernel_initializer=he_init, activation=tf.nn.elu) outputs = tf.layers.dense(hidden3, self.n_outputs, name="outputs") # 输出预测的类别 y_proba = tf.nn.softmax(outputs) # 定义损失函数计算损失 with tf.name_scope('loss'): # 前向传播要在Z3处中止,由于在TensorFlow中最后的线性输出层的输出做为计算损失函数的输入,因此不须要A3. xentropy = tf.nn.softmax_cross_entropy_with_logits(labels=Y, logits=outputs) loss = tf.reduce_mean(xentropy, name="loss") # 定义优化器 with tf.name_scope("train_optimizer"): optimizer = tf.train.AdamOptimizer(self.learning_rate) training_op = optimizer.minimize(loss) # # 使用梯度裁剪 # threshold = 1.0 # 设置梯度阈值 # # 定义优化器 # optimizer = tf.train.AdamOptimizer(self.learning_rate) # # 调用优化器的compute_gradients()方法计算梯度 # grads_and_vars = optimizer.compute_gradients(loss) # # 使用tf.clip_by_value()函数建立一个裁剪梯度的操做 # capped_gvs = [(tf.clip_by_value(grad, -threshold, threshold), var) for grad, var in grads_and_vars] # # 建立一个节点使用优化器的apply_gradients()函数应用裁剪的梯度 # training_op = optimizer.apply_gradients(capped_gvs) # 评估模型,使用准确性做为咱们的绩效指标 with tf.name_scope("eval"): # 计算当前的预测结果 # 检测使用了滑动平静模型的神经网络前向传播是否正确。tf.argmax(average_y,1) # 计算每个样例的预测答案。其中average_y是一个batch_size*10的二维数组,每 # 一行表示案例向前传播的结果。tf.argmax的第二个参数为1,表示选取最大值的 # 操做只在第一个维度上进行(x轴上),也就是说只在每一行选取最大值对应的下标 # 因而获得的结果是一个长度为batch的一维数组,这个一维数组中的值就表示了每 # 一个数字对应的样例识别的结果.tf.equal()判断每一个Tensor的每一维度是否相同 # 若是相等返回True,不然返回False. correct_prediction = tf.equal(tf.argmax(y_proba, 1), tf.argmax(Y, 1)) # 计算准确率 # 这个运算首先将一个布尔型的值转换为实数型,而后计算平均值。这一个平均值 # 就表明模型在这一组数据上的正确率 accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) # 建立初始化全部变量的节点 init = tf.global_variables_initializer() # 建立一个保存模型的saveOP,设置要保留的最近检测点的模型的数量 saver = tf.train.Saver(max_to_keep=1) # 开始会话并计算 with tf.Session() as sess: # 初始化全部变量 sess.run(init) # 加载模型,从模型中找出与当前训练的模型代码当中(名字同样的OP操做),覆盖原来的值 checkpoin = tf.train.latest_checkpoint('./ckpt/') # 若是模型已经保存则加载模型 if checkpoin: saver.restore(sess, checkpoin) # 计算模型预测的准确率 train_acc = accuracy.eval({X: x_train[100:200], Y: y_train[100:200]}) test_acc = accuracy.eval({X: x_test[100:200], Y: y_test[100:200]}) print("训练集的准确率:", train_acc) print("测试集的准确率:", test_acc) else: # 模型未保存,则开始训练模型 # 正常训练模型 for epoch in range(self.num_epochs): epoch_cost = 0 # 每轮的成本函数值 num_minibatches = math.floor(m / self.minibatch_size) # 分红多少个mini-batch组 seed = seed + 1 minibatches = self.random_mini_batches(x_train, y_train, self.minibatch_size, seed) for minibatch in minibatches: # 选择一个minibatch (minibatch_X, minibatch_Y) = minibatch # 数据已经准备好了,开始运行session _, minibatch_cost = sess.run([training_op, loss], feed_dict={X: minibatch_X, Y: minibatch_Y}) # 计算这个minibatch在这一代中所占的偏差 epoch_cost = epoch_cost + minibatch_cost / num_minibatches if epoch % 5 == 0: # 将每轮迭代的代价函数值存入列表 costs.append(epoch_cost) # 打印每轮迭代的代价函数值: if print_cost and epoch % 100 == 0: print("epoch = " + str(epoch) + " epoch_cost = " + str(epoch_cost)) # 保存学习后的参数 saver.save(sess, './ckpt/my_test1_model.ckpt') # 绘制代价函数值的学习曲线 if is_plot: plt.plot(np.squeeze(costs)) plt.ylabel('cost') plt.xlabel('iterations (per tens)') plt.title("Learning rate =" + str(self.learning_rate)) plt.show() # 计算模型学习完成后的训练集及测试集准确率 train_acc = accuracy.eval({X: x_train, Y: y_train}) test_acc = accuracy.eval({X: x_test, Y: y_test}) print("训练集的准确率:", train_acc) print("测试集的准确率:", test_acc) if __name__ == '__main__': # 开始时间 start_time = time.clock() # 开始训练 nn = GestureSymbolRecognition() nn.train() # 结束时间 end_time = time.clock() # 计算时差 print("CPU的执行时间 = " + str(end_time - start_time) + " 秒")