with tf.Session() as sess:
sess.run(result) #得到关心的运算的结果
训练神经网络的步骤:
- 定义神经网络结构和前向传播的输出结果
- 定义损失函数以及选择反向传播优化的算法
- 生成会话并且在训练数据上反复运行反向传播优化算法
判断输出向量和期望向量有多接近?
交叉熵 cross entropy
t.eval() = tf.get_default_session().run(t)
学习率设置方法:指数衰减法
tf.train.exponential_decay(原始学习率,global_step,衰减速度,衰减率,staircase = True)
正则化
tf.contrib.layers.l2_regularizer(lambda)(w)
tf.contrib.layers.l1_regularizer
eg: tf.add_to_collection('losses', tf.contrib.layers.l2_regularizer(lambda)(var))
滑动平均模型
global_step = tf.Variable(0, trainable = False)
variable_averages = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY, global_step)
variable_averages_op = variable_averages.apply(tf.trainable_variables)
两种写法等价:都是在确保了参数顺序执行之后,再执行train_op。
①train_op = tf.group(train_step, variables_averages_op)
②with tf.control_dependecies([train_step, variables_averages_op]):
train_op = tf.no_op(name='train')\
变量管理
当神经网络的结构更加复杂、参数更多时,需要一个更好的方式来传递和管理神经网络中的参数。
Tensorflow提供了通过变量名称来创建或者获取变量的机制。通过这个机制,在不同的函数中可以直接通过变量的名字来使用变量,而不需要将变量通过参数的形式到处传递。
1.创建变量
v = tf.get_variable("v", shape=[1], initializer=tf.constant_initializer(1.0))
v = tf.Variable(tf.constant(1.0, shape=[1]), name="v")
这两个定义是等价的。
tf.Variable和tf.get_variable最大的区别是:对于tf.Variable函数,变量名称是个可选参数;但是对于tf.get_variable函数,变量名称是个必填参数。tf.get_variable会根据这个名字去创建或者获取变量。
如果需要通过tf.get_variable获取一个已经创建的变量,需要通过tf.variable_scope函数来生成一个上下文管理器,并明确指定在这个上下文管理器中,tf.get_variable将直接获取已经生成的变量。
变量初始化函数通过名称获取变量
tf.get_variable
tf.varaible_scope
定义变量和前向传播的时候使用
def inference(input_tensor, regularizer):
with tf.variable_scope('layer1'):
weights = get_weight_variable([INPUT_NODE, LAYER1_NODE], regularizer)
biases = tf.get_variable("biases", [LAYER1_NODE], initializer=tf.constant_initializer(0.0))
layer1 = tf.nn.relu(tf.matmul(input_tensor, weights) + biases)
with tf.variable_scope('layer2'):
weights = get_weight_variable([LAYER1_NODE, OUTPUT_NODE], regularizer)
biases = tf.get_variable("biases", [OUTPUT_NODE], initializer=tf.constant_initializer(0.0))
layer2 = tf.matmul(layer1, weights) + biases
return layer2
tf.train.Saver
保存:
saver = tf.train.Saver()
saver.save(sess, "/path/to/model/model.ckpt")
在这个文件目录下会出现三个文件。
- model.ckpt.meta:保存了计算图的结构
- model.ckpt:保存程序中每个变量的取值
- checkpoint文件:保存了一个目录下所有模型文件列表
加载:
- 将变量的值通过已经保存的模型加载进来
saver = tf.train.Saver()
saver.restore(sess, "/path/to/model/model.ckpt")
- 直接加载已经持久化的图,无需重复定义图上的运算
saver = tf.train.import_meta_graph("/path/to/model/model.ckpt/model.ckpt.meta")
saver.restore(sess, "/path/to/model/model.ckpt/model.ckpt")
print sess.run(tf.get_default_graph().get_tensor_by_name("add:0"))
为了保存或加载部分变量,在声明tf.train.Saver时可以提供一个列表来指定需要保存或加载的变量
saver = tf.train.Saver([v1])
为了方便加载时重命名滑动平均变量,tf.train.ExponentialMovingAverage类提供了variables_to_restore函数来生成tf.train.Saver类所需要的变量重命名字典。
eg:saver = tf.train.Saver(ema.variables_to_restore())
最佳实践
inference:定义前向传播过程以及参数
- 定义神经网络结构相关参数:
INPUT_NODE
OUTPUT_NODE
LAYER1_NODE
def get_weight_variable(shape, regularizer)
return weights
通过tf.get_variable函数来获取变量
def inference(input_tensor, regularizer)
return layer_n
声明各层神经网络变量和前向传播过程
train:训练过程
- 配置神经网络参数
BATCH_SIZE = 100 #batch大小
LEARNING_RATE_BASE = 0.8 #基础学习率
LEARNING_RATE_DECAY = 0.99 #学习率衰减系数
REGULARIZATION_RATE = 0.0001 #正则化系数
TRAINING_STEPS = 30000 #总训练次数
MOVING_AVERAGE_DECAY = 0.99 #滑动平均衰减率
MODEL_SAVE_PATH="MNIST_model/" #模型存储路径
MODEL_NAME="mnist_model" #模型名称
def train():
(1)定义输入输出placeholder
(2)定义regularizer
(3)前向传播
(4)global_step
(5)定义滑动平均操作
variable_averages
variable_averages_op
(6)定义损失函数
(7)定义学习率
(8)定义优化算法
train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=global_step)
(9)限定运行顺序
with tf.control_dependencies([train_step, variables_averages_op]):
train_op = tf.no_op(name='train')
(10)存储模型
(11)创建会话
初始化变量
获取xs, ys
循环训练: , loss_value, step = sess.run([train_op, loss, global_step], feed_dict={x: xs, y: ys}) 并存储模型
CNN
卷积层
卷积层过滤器只在长、宽维度移动
conv = tf.nn.conv2d(input, filter_weight, strides=[1, 1, 1, 1], padding='SAME')
input:四维矩阵,第一维对应输入batch,后三维对应节点矩阵
filter_weight:卷积层权重
strides:不同维度的步长,第一维和最后一维都是1,中间的分别为长和宽
padding:SAME是全0填充,VALID表示不添加
bias = tf.nn.bias_add(conv, biases)
矩阵上不同位置的节点都要加上同样的偏置项,不能直接使用加法
actived_conv = tf.nn.relu(bias)
池化层
作用:缩小矩阵尺寸,减少全连接层中的参数;加快计算速度并且防止过拟合
max pooling
average pooling
池化层过滤器在三个维度移动
pool = tf.nn.max_pool(actived_conv, ksize=[1,3,3,1], strides=[1,2,2,1], padding='SAME')
LeNet-5
Inception-v3
使用TensorFlow-Slim实现卷积层
with slim.arg_scope([slim.conv2d, slim.max_pool2d, slim.avg_pool2d], stride=1, padding='SAME'):
调用第一个参数的函数列表时,函数会自动使用默认的参数取值。
卷积神经网络迁移学习
迁移学习:将一个问题上训练好的模型通过简单的调整使其适用于一个新的问题。
TensorFlow图像处理
1. 图像编码处理
将图片还原成三维矩阵,需要进行解码。
解码
读取图像并解码
image_raw_data = tf.gfile.FastGFile("../../datasets/cat.jpg",'r').read()
with tf.Session() as sess:
img_data = tf.image.decode_jpeg(image_raw_data)
# 输出解码之后的三维矩阵。
print img_data.eval()
可视化图像
with tf.Session() as sess:
plt.imshow(img_data.eval())
plt.show()
编码
img_data = tf.image.convert_to_dtype(img_data, dtype=tf.float32)
encoded_image = tf.image.encode_jpeg(img_data)
with tf.gfile.GFile("/path/to/output", "wb") as f:
f.write(encoded_image.eval())
2.图像大小调整
普通插值调整
with tf.Session() as sess:
resized = tf.image.resize_images(img_data, [300, 300], method=0)
method参数取值
对图像裁剪或填充
croped = tf.image.resize_image_with_crop_or_pad(img_data, 1000, 1000)
padded = tf.image.resize_image_with_crop_or_pad(img_data, 3000, 3000)
通过比例调整
截取中间50%
with tf.Session() as sess:
central_cropped = tf.image.central_crop(img_data, 0.5)
plt.imshow(central_cropped.eval())
plt.show()
裁剪或填充给定区域的图像
tf.image.crop_to_bounding_box
tf.image.pad_to_bounding_box
3.图像翻转
with tf.Session() as sess:
# 上下翻转
flipped1 = tf.image.flip_up_down(img_data)
# 左右翻转
flipped2 = tf.image.flip_left_right(img_data)
#对角线翻转
transposed = tf.image.transpose_image(img_data)
plt.imshow(transposed.eval())
plt.show()
# 以一定概率上下翻转图片。
flipped = tf.image.random_flip_up_down(img_data)
# 以一定概率左右翻转图片。
flipped = tf.image.random_flip_left_right(img_data)
4.图像色彩调整
(1)亮度
with tf.Session() as sess:
# 将图片的亮度-0.5。
adjusted = tf.image.adjust_brightness(img_data, -0.5)
# 将图片的亮度-0.5
adjusted = tf.image.adjust_brightness(img_data, 0.5)
# 在[-max_delta, max_delta)的范围随机调整图片的亮度。
adjusted = tf.image.random_brightness(img_data, max_delta=0.5)
(2)对比度
# 将图片的对比度-5
adjusted = tf.image.adjust_contrast(img_data, -5)
# 将图片的对比度+5
adjusted = tf.image.adjust_contrast(img_data, 5)
# 在[lower, upper]的范围随机调整图的对比度。
adjusted = tf.image.random_contrast(img_data, lower, upper)
(3)色相
adjusted = tf.image.adjust_hue(img_data, 0.1)
# 在[-max_delta, max_delta]的范围随机调整图片的色相。max_delta的取值在[0, 0.5]之间。
adjusted = tf.image.random_hue(image, max_delta)
(4)饱和度
# 将图片的饱和度-5。
adjusted = tf.image.adjust_saturation(img_data, -5)
# 将图片的饱和度+5。
adjusted = tf.image.adjust_saturation(img_data, 5)
# 在[lower, upper]的范围随机调整图的饱和度。
adjusted = tf.image.random_saturation(img_data, lower, upper)
(5)自动图像标准化
# 将代表一张图片的三维矩阵中的数字均值变为0,方差变为1。
adjusted = tf.image.per_image_whitening(img_data)
5.处理标注框
tf.image.draw_bounding_boxes(batched, boxes)
batched:一batch的数据,多张图像组成的四维矩阵。
在只有单张图像时,需要将解码之后的图像矩阵加一维。
batched = tf.expand_dims(tf.image.convert_iamge_dtype(img_data, tf.float32), 0)
boxes:标注框集合,一个标注框有四个数字[ymin, xmin, ymax, xmax]。
boxes = tf.constant([[[0.05, 0.05, 0.9, 0.7], [0.35, 0.47, 0.5, 0.56]]])
添加标注框并裁剪
with tf.Session() as sess:
boxes = tf.constant([[[0.05, 0.05, 0.9, 0.7], [0.35, 0.47, 0.5, 0.56]]])
begin, size, bbox_for_draw = tf.image.sample_distorted_bounding_box(
tf.shape(img_data), bounding_boxes=boxes)
batched = tf.expand_dims(tf.image.convert_image_dtype(img_data, tf.float32), 0)
image_with_box = tf.image.draw_bounding_boxes(batched, bbox_for_draw)
distorted_image = tf.slice(img_data, begin, size)
plt.imshow(distorted_image.eval())
plt.show()
多线程输入数据处理框架
流程图队列与多线程
队列操作
q = tf.FIFOQueue(2, "int32")
init = q.enqueue_many(([0, 10],))
x = q.dequeue()
y = x + 1
q_inc = q.enqueue([y])
with tf.Session() as sess:
init.run()
for _ in range(5):
v, _ = sess.run([x, q_inc])
print v
FIFOQueue 先进先出
RandomShuffleQueue 随机元素出队
在TensorFlow中,队列不仅仅是一种数据结构,还是异步计算张量取值的一个重要机制。
Tensorflow提供了两个类来完成多线程协同的功能。
1.tf.Coordinator
用于协同多个线程一起停止,提供了should_stop、request_stop和join三个函数。
2.tf.QueueRunner
用于启动多个线程来操作同一个队列。
Holds a list of enqueue operations for a queue, each to be run in a thread.
使用tf.train.QueueRunner时,需要明确调用tf.train.start_queue_runners来启动所有线程。
queue = tf.FIFOQueue(100,"float")
enqueue_op = queue.enqueue([tf.random_normal([1])])
#[enqueue_op * 5]表示需要启动5个线程,每个线程运行enqueue操作
qr = tf.train.QueueRunner(queue, [enqueue_op] * 5)
tf.train.add_queue_runner(qr)
out_tensor = queue.dequeue()
with tf.Session() as sess:
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(sess=sess, coord=coord)
for _ in range(3): print sess.run(out_tensor)[0]
coord.request_stop()
coord.join(threads)
输入文件队列
1. tf.train.match_filenames_once
获取符合一个正则表达式的所有文件
使用这个函数,需要在session中初始化变量
tf.global_variables_initializer().run()
2. tf.train.string_input_producer
使用初始化时提供的文件列表创建一个输入队列,输入队列中原始元素为列表中的所有文件。
files = tf.train.match_filenames_once("Records/data.tfrecords-*")
filename_queue = tf.train.string_input_producer(files, shuffle=False)
例子
1、获取文件列表
files = tf.train.match_filenames_once("Records/data.tfrecords-*")
2、创建输入队列
filename_queue = tf.train.string_input_producer(files, shuffle=False)
3、读取并解析样本
reader = tf.TFRecordReader()
_, serialized_example = reader.read(filename_queue)
4、在session中声明coordinator类来协同不同线程,并启动线程
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(sess=sess, coord=coord)
组合训练数据(batching)
1. tf.train.batch
example_batch, label_batch = tf.train.batch([example, label], batch_size=batch_size, capacity=capacity)
2. tf.train.shuffle_batch
不同线程读取同一个文件。
example_batch, label_batch = tf.train.shuffle_batch([example, label], batch_size=batch_size, capacity=capacity, min_after_dequeue=30)
min_after_dequeue参数提供了限制出队时最少元素的个数来保证随机打乱顺序的作用。
3. tf.train.shuffle_batch_join
从输入文件队列中获取不同文件分配给不同线程。
循环神经网络
主要用于处理和预测序列数据。
循环神经网络的总损失为所有时刻上的损失函数的总和。
LTSM(长短时记忆网络)
定义基本的lstm:
lstm = tf.contrib.rnn.BasicLSTMCell(lstm_hidden_size)
设置全为0的初始状态:
state = lstm.zero_state(batch_size, tf.float32)
每一步处理时间序列的一个时刻:
lstm_output, state = lstm(current_input, state)
bi RNN(双向循环神经网络)
deep RNN(深层循环神经网络)
# 定义使用LSTM结构及训练时使用dropout。
lstm_cell = tf.contrib.rnn.BasicLSTMCell(HIDDEN_SIZE)
if is_training:
lstm_cell = tf.contrib.rnn.DropoutWrapper(lstm_cell, output_keep_prob=KEEP_PROB)
cell = tf.contrib.rnn.MultiRNNCell([lstm_cell]*NUM_LAYERS)
# 初始化最初的状态。
self.initial_state = cell.zero_state(batch_size, tf.float32)
网友评论