refer:https://www.tensorflow.org/programmers_guide/?hl=zh-cn
组成
Graph(Variable, Constant, placeholder), Session
高级别 API
1.Estimators
高级API
2.导入数据
tf.data.Dataset
# 1. 数据来源
# 1.1 from numpy
features, labels = (np.random.sample((100,2)), np.random.sample((100,1)))
dataset = tf.data.Dataset.from_tensor_slices((features,labels))
# 1.2 from tensor
dataset = tf.data.Dataset.from_tensor_slices(tf.random_uniform([100, 2]))
# 1.3 from placeholder
x = tf.placeholder(tf.float32, shape=[None,2])
dataset = tf.data.Dataset.from_tensor_slices(x)
# 1.4 from generator
sequence = np.array([[1],[2,3],[3,4]])
def generator():
for el in sequence:
yield el
dataset = tf.data.Dataset().from_generator(generator,
output_types=tf.float32,
output_shapes=[tf.float32])
# 2. build iterator
# 2.1 one-shot
# 创建iterator
train_it = train_dataset.make_one_shot_iterator()
# 一次获取一个clip
train_videos_clips_tensor = train_it.get_next()
# 2.2 initializablere
# 2.3 initializable
# 2.4 feedable
# 3. 使用数据
低级别 API
显式创建自己的图和会话
步骤
1.定义图
2.填数据
3.session下运行图(更新参数,返回计算结果)
rank | math entity | python example |
---|---|---|
0 | scalar(magnitude only) | 12 |
1 | vector(magnitude and direction) | [1,2,3] |
2 | matrix(table of number) | [[1,2],[2,3]] |
3 | 3-tensor(cube of numbers) | [[[1],[2]],[[3],[4]]] |
n | n-tensor | ... |
0. Tensor Definition
tf.Tensor
tensor包括tf.Variable,tf.constant,tf.placeholder,tf.SparseTensor
只有Variable可变
rank | math entity | python example |
---|---|---|
0 | scalar(magnitude only) | 12 |
1 | vector(magnitude and direction) | [1,2,3] |
2 | matrix(table of number) | [[1,2],[2,3]] |
3 | 3-tensor(cube of numbers) | [[[1],[2]],[[3],[4]]] |
n | n-tensor | ... |
1. Variable
tf.Variable
存储持久变量w,b 于磁盘,便于下次调用(模型保存)
多个session可以共用
1.两种创建变量方式
Variable和get_variable
Variable每次都会新建(自动处理冲突(重命名),get_variable对未存在变量会新建,已存在则报错;
import tensorflow as tf
w_1 = tf.Variable(3,name="w_1", dtype = tf.int32)
w_2 = tf.Variable(1,name="w_1")
print w_1.name
print w_2.name
#输出,自动为冲突重命名
#w_1:0
#w_1_1:0
w_1 = tf.get_variable(name="w_1", shape=(), initializer=tf.zeros_initializer())
w_2 = tf.get_variable(name="w_1",shape=(),initializer=tf.zeros_initializer())
#错误信息
#ValueError: Variable w_1 already exists, disallowed. Did
#you mean to set reuse=True in VarScope?
2.variable_scope和name_scope
name_scope:
用于定义命名空间,对变量和操作进行封装;
variable_scope:
除了新建新的变量,还可以通过设置reuse=True并使用tf.get_variable()实现变量共享
想要用共享变量,前面就一定要写上variable_scope,之后才能调用
with tf.variable_scope('generator', reuse=None):
...
with tf.variable_scope('generator', reuse=True):
...
3.定义变量Variable后,使用前一定要在session里先初始化
tf.contrib.slim、tf.estimator.Estimator 和 Keras 等大多数高级框架在训练模型前会自动初始化变量
添加操作进行初始化,再在session里先运行该操作进行变量初始化
import tensorflow as tf
# 此时只是定义了如何初始化,而并没有真正初始化
state = tf.Variable(0, name='counter')
# 定义常量 one
one = tf.constant(1)
# 定义加法步骤 (注: 此步并没有直接计算)
new_value = tf.add(state, one)
# 将 State 更新成 new_value
update = tf.assign(state, new_value)
# 1. 如果定义 Variable, 就一定要 initialize
# init = tf.initialize_all_variables() # tf 马上就要废弃这种写法
init = tf.global_variables_initializer() # 替换成这样就好
# 2 在Session里初始化
with tf.Session() as sess:
sess.run(init)
for _ in range(3):
sess.run(update)
print(sess.run(state))
4.设定是否需要计算梯度
默认情况下,每个 tf.Variable 都放置在以下两个集合中:
tf.GraphKeys.GLOBAL_VARIABLES - 可以在多个设备共享的变量
==tf.GraphKeys.TRAINABLE_VARIABLES== - TensorFlow 将计算其梯度的变量(一般是这个)
不计算变量梯度的方法:
1.放在tf.GraphKeys.LOCAL_VARIABLES
2.定义时设置
my_non_trainable = tf.get_variable("my_non_trainable",
shape=(),
trainable=False)
5.实际使用中,通过tf.contrib.layers 构造网络层,该高级操作接口已经封装了内部的变量Variable的创建和管理
2. placeholder
用作输入的占位符
Tensorflow 如果想要从外部传入data, 那就需要用到 tf.placeholder(), 然后以这种形式传输数据sess.run(***, feed_dict={input: **}).
import tensorflow as tf
#在 Tensorflow 中需要定义 placeholder 的 type ,一般为 float32 形式
input1 = tf.placeholder(tf.float32)
input2 = tf.placeholder(tf.float32)
# mul = multiply 是将input1和input2 做乘法运算,并输出为 output
ouput = tf.multiply(input1, input2)
with tf.Session() as sess:
print(sess.run(ouput, feed_dict={input1: [7.], input2: [2.]}))
# [ 14.]
3. 构建graph
构造graph(包含变量和操作op)
可以用tf.device制定操作运行的设备
# Operations created outside either context will run on the "best possible"
# device. For example, if you have a GPU and a CPU available, and the operation
# has a GPU implementation, TensorFlow will choose the GPU.
weights = tf.random_normal(...)
with tf.device("/device:CPU:0"):
# Operations created in this context will be pinned to the CPU.
img = tf.decode_jpeg(tf.read_file("img.jpg"))
with tf.device("/device:GPU:0"):
# Operations created in this context will be pinned to the GPU.
result = tf.matmul(weights, img)
4.Session.run
session拥有物理资源(例如 GPU 和网络连接),它通常用作上下文管理器(在 with 代码块中),该管理器可在您退出代码块时自动关闭会话
# Create a default in-process session.
with tf.Session() as sess:
# 可一次计算多个操作
y_val, output_val = sess.run([y, output])
# Create a remote session.
with tf.Session("grpc://example.org:2222"):
# ...
v = session.run(in)
v和in同维度v = session.run(in,feed_dict=xx)
用了placeholder的才需要feed_dictwith语句
Session 对象在使用完后需要关闭以释放资源. 除了显式调用 close 外, 也可以使用 "with" 代码块 来自动完成关闭动作;
扩展
1. tensorboard可视化
tf.summary.xxx定义需要保存的信息
Run:
$ tensorboard --logdir=./summary --port=10086
# add all to summaries
tf.summary.scalar(tensor=train_psnr_error, name='train_psnr_error')
tf.summary.scalar(tensor=test_psnr_error, name='test_psnr_error')
tf.summary.scalar(tensor=g_loss, name='g_loss')
tf.summary.scalar(tensor=adv_loss, name='adv_loss')
tf.summary.scalar(tensor=dis_loss, name='dis_loss')
tf.summary.image(tensor=train_outputs, name='train_outputs')
tf.summary.image(tensor=train_gt, name='train_gt')
tf.summary.image(tensor=test_outputs, name='test_outputs')
tf.summary.image(tensor=test_gt, name='test_gt')
summary_op = tf.summary.merge_all()
with tf.Session(config=config) as sess:
# summaries
summary_writer = tf.summary.FileWriter(summary_dir, graph=sess.graph)
sess.run([..., summary_op])
summary_writer.add_summary(_summaries, global_step=_step)
可以使用 tensorboard --help 查看tensorboard的详细参数
2. 保存和重载模型
主要用于TensorFlow Serving
TF Serving是一个将训练好的模型部署至生产环境的系统。
可以用同一份inference的代码(或者被封装成API)复用不同模型;
2.1 SavedModel方式
tensorflow推荐使用
SavedModel
是一种与语言无关,可恢复的密封式序列化格式
builder = tf.saved_model.builder.SavedModelBuilder(export_dir)
1.save
import tensorflow as tf
export_dir = 'savedModel_dir'
x1 = tf.placeholder(tf.float32, [3,])
x2 = tf.placeholder(tf.float32, [3,])
# Variable 在声明是必须要给定一个 初始值的
v = tf.Variable([1,1,1],dtype=tf.float32)
output = x1+x2+v
# build_tensor_info将信息序列化为 TensorInfo protocol buffer
# 为输入输出约定别名:input_x 和 output
# x 为输入tensor, keep_prob为dropout的prob tensor
inputs = {'input_x1': tf.saved_model.utils.build_tensor_info(x1),
'input_x2': tf.saved_model.utils.build_tensor_info(x2)}
# y 为最终需要的输出结果tensor
outputs = {'output' : tf.saved_model.utils.build_tensor_info(output)}
# 第三个参数method_name暂时先随便给一个
signature = tf.saved_model.signature_def_utils.build_signature_def(inputs, outputs, 'test_sig_name')
# export_dir 模型保存路径
builder = tf.saved_model.builder.SavedModelBuilder(export_dir)
# 初始化模型的参数
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init) # 执行初始化,此时变量被填值
# 导入图和变量
# 第一个参数就是当前的session
# 第二个参数是在保存的时候定义的meta graph的标签,导入时需要匹配标签
# signature_def_map 一个dict,value是是输入输出tensor信息的
print("result={}".format(sess.run(output, feed_dict={x1:[1,2,3],x2:[3,2,1]})))
builder.add_meta_graph_and_variables(sess,
["tag-orli"],
signature_def_map={'signature-orli':signature})
# 将模型序列化到指定目录
# 保存好以后到saved_model_dir目录下,会有一个saved_model.pb文件以及variables文件夹。
# # 顾名思义,variables保存所有变量,saved_model.pb用于保存模型结构等信息
builder.save()
2.1.1 load
import tensorflow as tf
export_dir = 'savedModel_dir'
signature_key = 'signature-orli'
input_key1 = 'input_x1'
input_key2 = 'input_x2'
output_key = 'output'
a = [3,2,1]
with tf.Session() as sess:
meta_graph_def = tf.saved_model.loader.load(sess, ["tag-orli"], export_dir)
# 从meta_graph_def中取出SignatureDef对象
signature = meta_graph_def.signature_def
# 从signature中找出具体输入输出的tensor name
x1_tensor_name = signature[signature_key].inputs[input_key1].name
x2_tensor_name = signature[signature_key].inputs[input_key2].name
y_tensor_name = signature[signature_key].outputs[output_key].name
# 通过获取tensor 并inference
# 使得输入输出的tensor名称被隐藏,实现复用
x1 = sess.graph.get_tensor_by_name(x1_tensor_name)
x2 = sess.graph.get_tensor_by_name(x2_tensor_name)
y = sess.graph.get_tensor_by_name(y_tensor_name)
print("result={}".format(sess.run(y, feed_dict={x1:[2,3,4], x2:[4,3,2]})))
2.2 MetaGraph方式
==不推荐使用==
两种方案:
1. 用 tf.train.Saver()
来保存变量,重新定义图并用saver.restore()
载入变量
2. 用 tf.train.Saver() 来保存/载入变量,再使用tf.train.import_meta_graph导入graph信息。
此法不需要重定义图,但只能通过graph.get_tensor_by_name()来获取定义的tensor。这样就需要再维护一个配置文件保存图定义时的tensor名称。
1.保存
saver.save(sess, FLAGS.train_dir, global_step=step)
# Create some variables.
v1 = tf.Variable(..., name="v1")
v2 = tf.Variable(..., name="v2")
...
# Add an op to initialize the variables.
init_op = tf.global_variables_initializer()
# Add ops to save and restore all the variables.
saver = tf.train.Saver()
使用这种方法保存模型,模型的图结构和变量会分开存储;
会产生三种binary文件:
.meta:存储metagraph 图结构
.data-00000-of-00001:保存图中variable的值
.index:用来indetify checkpoint
model.ckpt.data-00000-of-00001
model.ckpt.index
model.ckpt.meta
2.2.1复原
saver.restore(sess, FLAGS.train_dir)
==Even though there is no file named model.ckpt,== you still refer to the saved checkpoint by that name when restoring it;
重载模型:
1.图结构和变量都需要加载
```
with tf.Session() as sess:
saver = tf.train.import_meta_graph('/tmp/model.ckpt.meta')
saver.restore(sess, "/tmp/model.ckpt")
```
或者
2.重新定义相同的图,只加载变量
# Recreate the EXACT SAME variables
v1 = tf.Variable(..., name="v1")
v2 = tf.Variable(..., name="v2")
...
# Now load the checkpoint variable values
with tf.Session() as sess:
saver = tf.train.Saver()
saver.restore(sess, "/tmp/model.ckpt")
3. GPU占用
# 1. 会默认占用所有GPU显存
with tf.Session() as sess:
# 2. 按比例分配,占用每块的60%
config = tf.ConfigProto()
config.gpu_options.per_process_gpu_memory_fraction=0.6
with tf.Session(config=config) as sess:
# 3. 设置GPU的显存占用按需增长, default it will use full GPU
config = tf.ConfigProto()
config.gpu_options.allow_growth = True
sess = tf.Session(config=config)
1适合自己机器,多人服务器使用2,3.2存在GPU浪费风险,3则可能因为申请不到GPU内存而崩溃
4. 指定使用的GPU
import os
os.environ["CUDA_VISIBLE_DEVICES"] = "0"