Tensorflow的结构
Tensorflow程序通常被组织成一个构建图阶段和一个执行图阶段。
构建图阶段,数据与操作的执行步骤被描述成一个图。构建图
执行阶段,使用会话执行构建好的图中的操作。会话
图和会话:
--图是 Tensorflow将计算表示为指令直接的依赖关系的一种表示法
--会话 Tensorflow在一个或多个本地或远程设备运行数据流图的机制
张量:Tensorflow中的基本数据对象
节点:提供图当中执行的操作
import tensorflow as tf
import os
os.environ['TF_CPP_MIN_LOG_LEVEL']='2'
def tensorflow_demo():
#原生python加法运算
a = 2
b = 3
c = a + b
print("python 加法运算结果:\n",c)
#Tensorflow实现加法
aT = tf.constant(2)
bT = tf.constant(3)
cT = aT + bT
print("Tensor 加法运算结果:\n",cT)
#会话
with tf.Session() as sess:
cT_value = sess.run(cT)
print("cT的值是: \n",cT_value)
return None
if __name__ == '__main__':
tensorflow_demo()
图相关的操作
默认图
通常Tensorflow会默认帮我们创建一张图。所谓的图结构就是数据(tensor)+操作(operation)
查看默认图的两种方法:
--调用:通过tf.get_default_graph()访问,要将操作添加到默认图形中,直接创建OP即可
--查看属性 .graph
op、sess都含有graph属性,默认在一张图中
import tensorflow as tf
def graph_demo():
at = tf.constant(2)
bt = tf.constant(3)
ct = at + bt
print("ct = \n",ct)
#查看默认图
default_graph = tf.get_default_graph()
print("default_graph: \n",default_graph)
print("at的属性: \n", at.graph)
print("ct的属性: \n", ct.graph)
#with tf.Session() as sess:
# ct_value = sess.run(ct)
# print("ct_value: \n",ct_value)
# print("sess的图属性: \n",sess.graph)
#自定义图
new_graph = tf.Graph()
with new_graph.as_default():
a_new = tf.constant(20)
b_new = tf.constant(30)
c_new = a_new+b_new
print("c_new: \n",c_new)
with tf.Session() as sess:
ct_value = sess.run(ct)
#运行自定义图中的数据会报错
#c_new_value = sess.run((c_new))
#print("c_new_value: \n",c_new_value)
print("ct_value: \n", ct_value)
print("sess的属性: \n",sess.graph)
#开启new_graph的会话
with tf.Session(graph=new_graph) as new_sess:
c_new_value = new_sess.run((c_new))
print("c_new_value: \n",c_new_value)
print("new_sess的属性: \n", new_sess.graph)
if __name__ == '__main__':
graph_demo()
可视化
1数据序列化 -events文件
TensorBoard通过读取Tensorflow的事件文件来运行,需要将数据生成一个序列化的Summary protobuf对象。
tf.summary.FileWriter('./tmp/tensorflow/summary/test/', graph=sess.graph) 将在指定目录中生成一个event文件,其名称格式是 : events.out.tfevents.{timestamp}.{hostname}
2 启动TensorBoard
tensorboard -- logdir"./tmp/tensorflow/summary/test/"
在浏览器中打开TensorBoard的图页面127.0.0.1:6006
with tf.Session() as sess:
ct_value = sess.run(ct)
#运行自定义图中的数据会报错
#c_new_value = sess.run((c_new))
#print("c_new_value: \n",c_new_value)
print("ct_value: \n", ct_value)
print("sess的属性: \n",sess.graph)
tf.summary.FileWriter("E:/test/pythontest/",graph=sess.graph)
OP
常见OP
类型 | 实例 |
标量运算 | add, sub, mul, div, exp, log. greater, less, equal |
向量运算 | concat, slice, splot, constant, rank, shape, shufhe |
矩阵运算 | matmul, matrixinverse, matrixdateminant |
带状态的运算 | Variable, assgin, assginadd |
神经网络组件 | softmax, sigmoid, relu,convolution,max. pool |
存储、恢复 | Save, Restroe |
队列及同步运算 | Enqueue, Dequeue, MutexAcquire, MutexRelease |
控制流 | Merge, Switch, Enter Leave, Nextiteration |
注意:不同的版本op是不一样的,如果保 no module的错误就是新版本的名字不同,比如sub为substract,mul为multiply
一个操作对象(Operation) 是TensorFlow图中的一个节点,可以接收0个或者多个输入Tensor,并且可以输出0个或者多个Tensor, Operation对象是通过op构造函数(如f.matmul) 创建的。例如: c = tf.matmul(a, b)创建了一个Operation对象,类型为MatMul类型,它将张量a, b作为输入,c作为输出.,并且输出数据,打印的时候也是打印的数据。其中tf.matmul()是函数,在执行matmul函数的过程中会通过MatMul类创建一个与之对应的对象。
>>> import tensorflow as tf
>>> consta = tf.constant(3.0)
>>> constb = tf.constant(4.0)
>>> sumc = tf.add(consta,constb)
>>> print("consta \n",consta)
consta
Tensor("Const:0", shape=(), dtype=float32)
>>> print("constb \n",constb)
constb
Tensor("Const_1:0", shape=(), dtype=float32)
>>> print("sumc \n", sumc)
sumc
Tensor("Add:0", shape=(), dtype=float32)
指令名称
tf.Graph对象为其包含的tf.Operation对象定义的一个命名空间。TensorFlow 会自动为图中的每个指令选择一个唯一名称, 用户也可以指定描述性名称。每个创建新的tf.Operation或返回新的tf.Tensor的API函数可以接受可选的name参数。例如,tf.constant(42.0. name="answer")创建了一个名为"answer"的新tf.Operation并返回一个名为"answer:0"的tf.Tensor,如果默认图已包含名为"answer"的指令,则TensorFlow会在名称上附加“1"、“2" 等字符,以便让名称具有唯一性。当修改好之后,我们在Tensorboard显示的名字也会被修改a = tf.constant(3.0, nane="a" ) b = tf.constant(4.0, name="b" )
注意,打印出来的是张量值,可以理解成OP当中包含了这个值。并且每一个OP指令都对应一个唯一的名称,如上面的Const:0,这个在TensorBoard上面也可以显示请注意,tf.Tensor 对象以输出该张量的tf.Operation明确命名。张量名称的形式为"<OP. NAME>:<i>",其中:'<OP_ NAME>'是生成该张量的指令的名称,'<OP_ NAME>'是生成该张量的指令的名称。
会话
1 __init__(target='',graph=None,config=None)
2 run()
3 feed
一个运行Tensorflow operation的类。会话包含一下两种开启方式
1)tf.Session:用于完整的程序当中
2)tf.InteractiveSession:用于交互式上下文中的Tensorflow,例如shell
初始化init
target:如果将此参数留空(默认),会话将仅使用本地计算机中的设备。可以指定grpc://网址,以便指定Tensorflow服务器地址,这使得会话可以访问该服务器控制的计算机上的所有设备。
graph:默认情况下,新的tf.Session将绑定到当前的默认图
config:此参数允许您指定一个tf.ConfigProto以便控制会话的行为。例如ConfigProto协议用于打印设备使用信息
#运行会话并打印设备信息
sess = tf.Session(config=tf.ConfigProto(allow_soft_placement=True,log_device_placement=True))
run()
run(fethes,feed_dict=None,option=None,run_metadata=None)
通过使用sess.run()来运行operation ,fetches:单一的operation,或者列表、元组(其他不属于tensorflow的类型不行),feed_dict:参数允许调用这覆盖图中张量的值,运行时赋值(与tf.placeholder搭配使用,则会检查值得形状是否与占位符兼容)
使用tf.operation.eval也可运行operation,但需要在会话中运行
feed操作
placeholder提供占位符,run时候通过feed_dict指定参数
import tensorflow as tf
def session_run_demo():
a = tf.placeholder(tf.float32)
b = tf.placeholder(tf.float32)
sum_ab = tf.add(a,b)
print("sum_ab: \n",sum_ab)
with tf.Session()as sess:
print("占位符结果: \n",sess.run(sum_ab,feed_dict={a:3.0, b:4.0}))
if __name__ == '__main__':
session_run_demo()
张量Tensor
Tensorflow的张量就是一个n维数组,类型为tf.Tensor。
张量的类型
数据类型 | 数据类型 | Python类型 |
DT_ FLOAT | tf.float32 | 32位浮点数. |
DT_ DOUBLE | t.float64 | 64位浮点数. |
DT_ INT64 | tf.int64 | 64位有符号整型. |
DT_ INT32 | tf.int32 | 32位有符号整型. |
DT_ INT16 | tf.int16 | 16位有符号整型. |
DT_ INT8 | tf.int8 | 8位有符号整型. |
DT_ UINT8 | tf.uint8 | 8位无符号整型 |
DT_ STRING | tf.string | 可变长度的字节数组,每一个张量元素都是一个字节数组. |
DT_ BOOL | tf.bool | 布尔型. |
DT_ COMPLEX64 | tf. complex64 | 由两个32位浮点数组成的复数:实数和虚数. |
DT._QINT32 | tf.qint32 | 用于量化Ops的32位有符号整型. |
DT._QINT8 | tf.qint8 | 用于量化Ops的8位有符号整型. |
DT_ QUINT8 | tf.quint8 | 用于量化Ops的8位无符号整型. |
张量的阶
0阶张量 标量 一个数
1阶张量 向量 一维数组 v=[1.1,2.2,3.3]
2阶张量 矩阵 二维数组 m=[[1,2,3],[4,5,6],[7,8,9]]
3阶张量 三维数组 t=[[[2],[4],[6]],[[8],[10],[12]],[[14],[16],[18]]]
...
>>> tensor1 = tf.constant(4.0)
>>> tensor2 = tf.constant([1,2,3,4])
>>> tensor3 = tf.constant([[4],[9],[16],[25]],dtype=tf.int32)
>>> print(tensor1.shape)
()
>>> print(tensor2.shape)
(4,)
>>> print(tensor3.shape)
(4, 1)
创建张量函数
固定值张量
tl.zeros(shape, dtype=t.float32, name=None)
#创建所有元素设置为零的张量。此操作返回一个dtype具有形状shape和所有元素设置为零的类型的张量
tf.zeros.like(tensor, dtype=None, name=None)
#给tensor定单张量(),此操作返回tensor与 所有元素设置为零相同的类型和形状的张量
tf.ones(shape, dtype=tf.float32, name=None)
#创建一个所有元素设置为1的张量。此操作返回-个类型的张量,dtype形状shape和所有元素设置为1
tf.ones.like(tensor, dtype=None, name=None)
#给tensor定单张量() .此操作返回tensor与所有元素设置为1相同的类型和形状的张量
tf.fill(dims, value, name=None)
#创建一个填充了标量值的张量。此操作创建一个张量的形状dims并填充它value.
tf.constant(value, dtype=None, shope=None, name='Const‘)
#创建一个常数张量
随机张量
tf.truncated_normal(shape,mean=0.0,stddev=1.0,dtype=tf.float32,seed=None,name=None)
从截断的正态分布中输出随机值,和tf.random_normal()一样,但是所有数字都不超过两个标准差
tf.random_normal(shape,mean=0.0,stddev=1.0,dtype=tf.float32,seed=None,name=None)
从正太分布中输出随机值,由随机正太分布的数字组成的矩阵
>>> sess = tf.InteractiveSession()
>>> tf.random_normal(shape=[2,3],mean=1.75,stddev=0.12)
<tf.Tensor 'random_normal_2:0' shape=(2, 3) dtype=float32>
>>> tf.random_normal(shape=[2,3],mean=1.75,stddev=0.12).eval()
array([[1.7925383, 1.5559976, 1.6293504],
[1.7484223, 1.8618195, 1.5761713]], dtype=float32)
张量的变换
1 类型改变
tf.string_to_number(string_tensor,out_type=None,name=None)
tf.to_double(x,name='ToDouble')
tf.to_float(x,name='ToFloat')
tf.to_bfloat16(x,name='ToBFloat16')
tf.to_int32(x,name='ToInt32')
tf.to_int64(x,name='ToInt64')
tf.cast(x,dtype,name=None)
def tensor_demo():
tensor1 = tf.constant(4.0)
tensor2 = tf.constant([1,2,3,4])
linear_square = tf.constant([[4],[9],[16],[25]],dtype=tf.int32)
print("tensor1: \n",tensor1)
print("tensor2: \n",tensor2)
print("linear_square_before: \n",linear_squares)
#类型修改
l_cast = tf.cast(linear_squares, dtype=tf.float32)
print("linear_squares_after: \n", linear_squares)
print("l_cast: \n",l_cast)
if __name__ == '__main__':
tensor_demo()
tensor1:
Tensor("Const:0", shape=(), dtype=float32)
tensor2:
Tensor("Const_1:0", shape=(4,), dtype=int32)
linear_square_before:
Tensor("Const_2:0", shape=(4, 1), dtype=int32)
linear_squares_after:
Tensor("Const_2:0", shape=(4, 1), dtype=int32) //不变
l_cast:
Tensor("Cast:0", shape=(4, 1), dtype=float32)
在numpy中ndarray类型修改用astype,ndarray.astype(type),tensorflow中用tf.cast(tensor,dtype),cast不会改变原始的tensor,返回新的改变类型后的tensor
2 形状改变
两种形状变换,动态形状和静态形状 tf.reshape tf.set.shape
静态形状 转换静态形状的时候,1-D到1-D,2-D到2-D,不能跨阶数改变形状;对于已经固定的张量的静态形状的张量,不能再次设置静态形状
动态形状 tf.reshape()动态创建新张量时,张量的元素个数必须匹配
#更新/改变静态形状
#定义占位符
#没有完全固定下来的静态形状
>>> ap = tf.placeholder(dtype=tf.float32,shape=[None,None])
>>> bp = tf.placeholder(dtype=tf.float32,shape=[None,10])
>>> cp = tf.placeholder(dtype=tf.float32,shape=[3,2])
>>> print("ap= \n",ap)
ap=
Tensor("Placeholder:0", shape=(?, ?), dtype=float32)
>>> print("bp= \n",bp)
bp=
Tensor("Placeholder_1:0", shape=(?, 10), dtype=float32)
>>> print("cp= \n",cp)
cp=
Tensor("Placeholder_2:0", shape=(3, 2), dtype=float32)
#更新形状未确定的部分
>>> ap.set_shape([2,3])
>>> bp.set_shape([2,10])
>>> print("ap= \n",ap)
ap=
Tensor("Placeholder:0", shape=(2, 3), dtype=float32)
>>> print("bp= \n",bp)
bp=
Tensor("Placeholder_1:0", shape=(2, 10), dtype=float32)
#动态形状修改
>>> ap_reshape = tf.reshape(ap,shape=[2,3,1])
>>> print("ap:\n",ap)
ap:
Tensor("Placeholder:0", shape=(2, 3), dtype=float32)
>>> print("ap_reshape:\n",ap_reshape)
ap_reshape:
Tensor("Reshape:0", shape=(2, 3, 1), dtype=float32)
变量OP
创建变量
tf.Variable(initial_value=None,trainable=True,collections=None,name=None)
#initial_value:初始化的值
#trainable:是否被训练
#collections:新变量将添加到列出的图的集合中collections,默认是[GraphKeys.GLOBAL_VARIABLES],如果trainable是True.
变量也被添加到图行集合GraphKeys.TRAINABLE_VARIABLES
#变量需要显示初始化才能运行值
def variable_demo():
a = tf.Variable(initial_value=30)
b = tf.Variable(initial_value=40)
sum = tf.add(a,b)
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
print("sum: ",sess.run(sum))
return None
if __name__ == '__main__':
variable_demo()
def variable_demo():
a = tf.Variable(initial_value=30)
b = tf.Variable(initial_value=40)
sum = tf.add(a,b)
print("a:" ,a)
print("b:" ,b)
print("sum:" ,sum)
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
a_value, b_value, sum_value = sess.run([a,b,sum])
print("a_value:" ,a_value)
print("b_value:" ,b_value)
print("sum_value:" ,sum_value)
return None
if __name__ == '__main__':
variable_demo()
#输出
a: <tf.Variable 'Variable:0' shape=() dtype=int32_ref>
b: <tf.Variable 'Variable_1:0' shape=() dtype=int32_ref>
sum: Tensor("Add:0", shape=(), dtype=int32)
a_value: 30
b_value: 40
sum_value: 70
修改变量命名空间 tf.variable_scope()
def variable_demo():
with tf.variable_scope("my_scope"):
a = tf.Variable(initial_value=50)
b = tf.Variable(initial_value=40)
sum = tf.add(a,b)
print("a:" ,a)
print("b:" ,b)
print("sum:" ,sum)
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
a_value, b_value, sum_value = sess.run([a,b,sum])
print("a_value:" ,a_value)
print("b_value:" ,b_value)
print("sum_value:" ,sum_value)
return None
if __name__ == '__main__':
variable_demo()
#输出
a: <tf.Variable 'my_scope/Variable:0' shape=() dtype=int32_ref>
b: <tf.Variable 'my_scope/Variable_1:0' shape=() dtype=int32_ref>
sum: Tensor("my_scope/Add:0", shape=(), dtype=int32)
API
tf.app 这个模块相当于为Tensorflow进行脚本提供一个main函数入口,可以定义脚本运行的flags。
tf.image Tensorflow的图像处理操作,主要是一些颜色变换变形和图像的编码和解码
tf.gfile 这个模块提供了一组文件操作函数
tf.summary 用来生成TensorBoard可用的统计日志,目前Summary主要提供了4种类型:audio、image、histogram、scalar
tf.python_io 用来读写TFRecords文件
tf.train 这个模块提供了一些训练器,与tf.nn组合起来,实现一些网络优化计算
tf.nn 这个模块提供过了一些构建神经网络的底层函数。TensorFlow构建网络的核心模块。其中包含了添加各种层的函数,比如添加卷积层、池化层等
高级API
tf.keras Keras本身就是一个独立的深度学习库
tf.layers 高级API,以更高级的概念层来定义一个模型。类型tf.keras
tf.contrib tf.contirb.layer提供够将计算图种的网络层、正则化、摘要操作,是构建计算图的高级操作,但是tf.contib包含不稳定和实验代码
tf.estimator 一个Estimator相当于Model+Training+Ealuate的合体。在模块中,已经实现了几种简单的分类器和回归器,包括Baseline,Learning和DNN。这里的DNN的网络只是全连接网络,没有提供卷积之类的
线性回归
API
矩阵运算 tf.matmul(x,w)
平方 tf.square(error)
均值 tf.reduce_mean(error)
梯度下降 tf.train.GradientDescentOptimizer(learning_rate)
import tensorflow as tf
def linearRegre():
#数据
X = tf.random_normal(shape=[100,1])
y_true = tf.matmul(X,[[0.8]]) + 0.7
#模型
weights = tf.Variable(initial_value = tf.random_normal(shape=[1,1]))
blas = tf.Variable(initial_value=tf.random_normal(shape=[1,1]))
y_predict = tf.matmul(X,weights) + blas
#构造损失函数
error =tf.reduce_mean(tf.square(y_predict - y_true))
#优化
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01).minimize(error)
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
print("训练前模型参数为: 权重%f,偏置%f,损失为%f" %(weights.eval(),blas.eval(),error.eval()))
#训练
for i in range(1000):
sess.run(optimizer)
print("第%d训练后模型参数为:权重%f,偏置%f, 损失为%f" %(i+1,weights.eval(),blas.eval(),error.eval()))
return None
if __name__ == '__main__':
linearRegre()
变量的trainable参数,指定是否训练
weights = tf.Variable(initial_value = tf.random_normal(shape=[1,1]),trainable=False)
增加功能
变量Tensorboard显示
增加命名空间
模型保存与加载
命令行参数设置
1、增加变量显示
目的:在TensorBoard当中观察模型的参数、损失值等变量值的变化
1、收集变量
tf.summary.scalar(name='',tensor) 收集对于损失函数和准确率等单值变量,name为变量的名字,tensor为值
tf.summary.histogram(name='',tensor)收集高纬度的变量参数
tf.summary.image(name='',tensor)收集输入图片张量能显示图片
2、合并变量写入事件文本
merged = tf.summary.merge_all()
运行合并:summary = sess.run(merged),每次迭代都需运行
添加:FileWriter.add_summary(summary,i) i表示第几次的值
import tensorflow as tf
def linearRegre():
#数据
X = tf.random_normal(shape=[100,1])
y_true = tf.matmul(X,[[0.8]]) + 0.7
#模型
weights = tf.Variable(initial_value = tf.random_normal(shape=[1,1]))
bias = tf.Variable(initial_value=tf.random_normal(shape=[1,1]))
y_predict = tf.matmul(X,weights) + bias
#构造损失函数
error =tf.reduce_mean(tf.square(y_predict - y_true))
#优化
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01).minimize(error)
#收集变量
tf.summary.scalar("error",error)
tf.summary.histogram("weights",weights)
tf.summary.histogram("bias",bias)
#合并变量
merged = tf.summary.merge_all()
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
#创建事件文件
file_writer = tf.summary.FileWriter("E:/test/pythontest",graph=sess.graph)
print("训练前模型参数为: 权重%f,偏置%f,损失为%f" %(weights.eval(),bias.eval(),error.eval()))
#训练
for i in range(100):
sess.run(optimizer)
print("第%d训练后模型参数为:权重%f,偏置%f, 损失为%f" %(i+1,weights.eval(),bias.eval(),error.eval()))
summary = sess.run(merged)
#写入事件文件
file_writer.add_summary(summary,i)
return None
if __name__ == '__main__':
linearRegre()
增加命名空间
with tf.Variable_scope("lr_model")
import tensorflow as tf
def linearRegre():
#数据
with tf.variable_scope("prepare_data"):
X = tf.random_normal(shape=[100,1])
y_true = tf.matmul(X,[[0.8]]) + 0.7
#模型
with tf.variable_scope("create_model"):
weights = tf.Variable(initial_value = tf.random_normal(shape=[1,1]))
bias = tf.Variable(initial_value=tf.random_normal(shape=[1,1]))
y_predict = tf.matmul(X,weights) + bias
#构造损失函数
with tf.variable_scope("loss_function"):
error =tf.reduce_mean(tf.square(y_predict - y_true))
#优化
with tf.variable_scope("optimizer"):
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01).minimize(error)
#收集变量
tf.summary.scalar("error",error)
tf.summary.histogram("weights",weights)
tf.summary.histogram("bias",bias)
#合并变量
merged = tf.summary.merge_all()
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
#创建事件文件
file_writer = tf.summary.FileWriter("E:/test/pythontest",graph=sess.graph)
print("训练前模型参数为: 权重%f,偏置%f,损失为%f" %(weights.eval(),bias.eval(),error.eval()))
#训练
for i in range(100):
sess.run(optimizer)
print("第%d训练后模型参数为:权重%f,偏置%f, 损失为%f" %(i+1,weights.eval(),bias.eval(),error.eval()))
summary = sess.run(merged)
#写入事件文件
file_writer.add_summary(summary,i)
return None
if __name__ == '__main__':
linearRegre()
模型的保存与加载
tf.train.Saver(var_list=None,max_to_keep=5)
保存和加载模型(保存文件格式:checkpoint文件)
var_list:指定将要保存和还原的变量。它可以作为一个dict或一个列表传递
max_to_keep:指示要保留的最近检查点文件的最大数量。创建新文件时,会删除较旧的文件。如果无或0,则保留所有 检查点文件。
默认为5(即保留最新的5个检查点文件)
保存: saver.save(sess,path)
加载:saver.restore(sess,path)
使用
指定目录+模型名字
saver.save(sess,'/tmp/ckpt/test/myregression.ckpt')
saver.restore(sess,'/tmp/ckpt/test/myregression.ckpt')
判断模型是否存在,直接指定目录
checkpoint = tf.train.latest_checkpoint("./tmp/model/")
saver.restore(sess,checkpoint)
命令行参数使用
1、tf.app.flags,它支持应用从命令行接受参数,可以用来指定集群配置等。在tf.app.flags下面有各种定义参数的类型
DEFINE_string(flag_name, default_value, docstring)
DEFINE_integer(flag_name, default_value, docstring)
DEFINE_boolean(flag_name, default_value, docstring)
DEFINEL_flat(flag_name, default_value, docstring)
2、tf.app.flags.,在flags有一个FLAGS标志,它在程序中可以调用到我们前面具体定义的flag_name
3、通过tf.app.run()启动main(argv)函数
#定义一些常用命令行参数
#训练步数
tf.app.flags.DEFINE_integer("max_step",0,"训练模型的步数")
#定义模型的路径
tf.app.flags.DEFINE_string("model_dir"," ","模型保存的路径+模型名字")#定义获取命令行参数
FLAGS = tf.app.flags.FLAGS#开启训练
#训练的步数(依据模型大小而定)
for i in range(FLAGS.max_step):
sess.run(train_op)#通过FLAGS.max_step调用命令行中传过来的参数
import tensorflow as tf
tf.app.flags.DEFINE_integer("max_step",100,"训练模型的步数")
tf.app.flags.DEFINE_string("model_dir","Unknown","模型保存的路径+模型名字")
FLAGS = tf.app.flags.FLAGS
def command_demo():
print("max_step:\n",FLAGS.max_step)
print("model_dir:\n",FLAGS.model_dir)
return None
def main(argv):
print(argv)
return None
if __name__ == "__main__":
#command_demo()
tf.app.run()
文件读取
三种获取数据到Tensorflow程序的方法:
1、QueueRuner:基于队列的输入管道从Tensorflow图形开头的文件中读取数据
2、Feeding:运行每一步时,Python代码提供数据
3、预加载数据:TensorFlow图中的张量包含所有数据(对于小数据集)
文件读取流程 多线程+队列
1 构造文件名队列
2 读取与解码
3 批处理
注意:这些操作需要启动运行这些队列操作的线程,以便我们在进行文件读取的过程中能够顺进行入队出队操作
1、构造文件名队列
将需要读取的文件的文件名放入文件名队列
tf.train.string_input_producer(string_tensor,shuffle=True)
string_tensor:含有文件名+路径的1阶张量
num_epochs:过几遍数据,默认无限过数据
return 文件队列
读取文件
阅读器默认每次只读取一个样本,具体来说
文本文件默认一次读取一行 图片文件默认一次读取一张图片 二进制文件一次读取指定字节数(最好是一个样本的字节数) TFRecords默认一次读取一个exampletf.TextLineReader:
阅读文本文件逗号分隔值(csv)格式,默认按行读取
return:读取器实例
tf.WholeFileReader:用于读取图片文件
return:读取器实例
tf.FixedLengthRecordReader(record_bytes):二进制文件
要读取每个记录是固定输了字节的二进制文件
record_bytes:整型,指定每次读取(一个样本)的字节数
return:读取器实例
tf.TFRecordReader:读取TFRcords文件
return:读取器实例它们有共同的读取方法:read(file_queue),并且都会返回一个Tensor元组(key文件名字,value默认的内容(一个样本))
由于默认只会读取一个样本,所以如果想要进行批处理,需要使用tf.train.batch或tf.train.shuffle_batch进行批处理操作,便于之后指定每批次多个样本训练
解码
解码
读取不同类型的文件,他应该对读取到的不同类型的内容进行相对应的解码操作,解码成同意的Tensor格式
tf.decode_csv:解码文本文件内容
tf.image.decode_jpeg(contents) tf.image.decode_png(contents)
将JPEG编码的图像解码为unit8张量
return:unit8张量,3-D形状[height,width,channels]
tf.decode_raw: 解码二进制文件内容
与tf.FixedLengthRecordReader搭配使用,二进制读取为unit8类型
解码阶段,默认所有的内容都解码成tf.unit8类型,如果之后需要转换成指定类型则可使用tf.catf()进行相应转换。
批处理
解码之后,可以直接获取默认的一个样本内容了,但如果想要获取多个样本,需要加入到新的队列进行批处理。
tf.train.batch(tensors,batch_suize,num_threads=1,capacity=32,name=None)
读取指定大小(个数)的张量
tensors:可以是包含张量的列表,批处理的内容放到列表当中
batch_size:从队列中读取的批处理大小
num_threads:进入队列的线程数
capacity:整数,队列中元素的最大数量
return:tensors
tf.train.shuffle_batch
线程操作
以上用到的队列都是tf.train.QueueRuner对象。
每个QueueRunner都负责一个阶段,tf.train.start_queue_runners函数会要去途中的每个QueueRunner启动它的运行队列操作的线程。(这些操作需要在会话中开启)
tf.train.start_queue_runners(sess=None,coord=None)
收集图中所有的队列线程,默认同时启动线程
sess:所在的会话
coord:线程协调器
return:返回所有线程
tf.train.Coordinator()
线程协调员,对线程进行管理和协调
request_stop():请求停止
should_stop*():粗纹是否结束
join(threads=None,stop_grace_period_secs=120):回收线程
return:线程协调员实例
图片特征值处理
缩放图片
tf.image.resize_images(images,size)
缩小放大图片
images:4-D形状[batch,height,width,channels]或3-D形状[height,width,channels]的图片数据
size:1-D int32张量:new_height,new_width,图像的新尺寸
返回4-D格式或者3-D格式图片
数据格式
存储:unit8
矩阵计算:float3
读取图片
import tensorflow as tf
import os
def picture_read(file_list):
#1构造文件名队列
file_queue = tf.train.string_input_producer(file_list)
#2读取与解码
reader = tf.WholeFileReader()
#key文件名 value一张图片的原始编码形式
key,value=reader.read(file_queue)
print("key:\n",key)
print("value:\n",value)
#解码
image = tf.image.decode_jpeg(value,channels=3)
print("image")
#图像形状、类型修改
image_resized = tf.image.resize_images(image,[400,400])
print("image_resized:\n",image_resized)
#3批处理
image_batch = tf.train.batch([image_resized],batch_size=10,num_threads=1,capacity=100)
print("image_batch\n",image_batch)
#开启会话
with tf.Session() as sess:
#开启线程
#线程协调员
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(sess=sess,coord=coord)
key_new,value_new,image_new,image_resized_new = sess.run([key,value,image,image_resized])
print("key_new:\n",key_new)
print("value_new:\n",value_new)
print("image_new:\n",image_new)
print("image_resized_new:\n",image_resized_new)
#回收线程
coord.request_stop()
coord.join(threads)
return None
if __name__ =="__main__":
#构造路径+文件名的列表
filename = os.listdir("E:/aa")
#filename = "E:/test/pythontest"
#拼接路径+文件名
file_list = [os.path.join("E:/aa/",file) for file in filename]
print(file_list)
picture_read(file_list)
读取流程
构造图片文件名队列
读取图片数据并进行解码
处理图片数据形状,放入批处理队列
开启会话线程运行
CIFAR10 二进制数据读取
构造文件队列
读取二进制数据并进行解码
处理图片数据形状及数据类型,批处理返回
开启会话线程运行
CIFAR10二进制数据集 一个样本是3073个字节,1个目标值加上3072像素,读取流程
import tensorflow as tf
import os
class Cifar(object):
def __init__(self):
self.height=32
self.width=32
self.channels =3
#字节数
self.image_bytes = self.height * self.width*self.channels
self.label_bytes = 1
self.all_bytes = self.label_bytes + self.image_bytes
def read_and_decode(self,file_list):
#1、构造文件名队列
file_queue = tf.train.string_input_producer(file_list)
#读取与解码
reader = tf.FixedLengthRecordReader(self.all_bytes)
key,value = reader.read(file_queue)
print("key:\n",key)
print("value:\n",value)
#解码
decoded = tf.decode_raw(value,tf.unit8)
print("decoded:\n",decoded)
#将目标值和特征值切片切开
label = tf.slice(decoded,[0],[self.label_bytes])
image = tf.slice(decoded,[self.label_bytes],[self.image_bytes])
print("label:\n",label)
print("image:\n",image)
#调整图片形状
image_reshaped = tf.reshape(image,shape=[self.channels,self.height,self.width])
print("image_reshaped: \n",image_reshaped)
#转置
image_transposed = tf.transposed(image_reshaped,[1,2,0])
print("image_transposed:\n",image_transposed)
#调整图像类型
image_cast = tf.cast(image_transposed,tf.float32)
#批处理
label_batch,image_batch = tf.train.batch([label,image_cast],batch_size=100,capacity=100)
print("label_batch:\n",label_batch)
print("image_batch:\n",image_batch)
with tf.Session() as sess:
coord = tf.train.Coordinator()
threads = tf.train.start_queuue_runners(sess=sess,coord=coord)
key_new,value_new,decode_new,label_new,image_new,image_reshaped_new = \
sess.run([key,value,decoded,label,image,image_reshape])
#回收线程
coord.request_stop()
coord.join(threads)
return None
if __name__ == "__main__":
file_name = os.listdir("./cifar-10-batches-bin")
print("file_name:\n",file_name)
file_list = [os.path.join("./cifar-10-batches-bin/",file) for file in file_name if file[-3:] == "bin"]
print("file_list:",file_list)
cifar = CIfar()
cifar.read_and_decode(file_list)
TFRecords文件
TFRecords是一种二进制文件,能更好利用内存方便赋值和移动,并且不需要单独的标签文件。
使用步骤:
1)获取数据
2)将数据填入到Example 协议内存块(protocol buffer)
3)将协议内存块序列化字符串,并且通过tf.python_io.TFRecordWriter写入到TFRecords文件
文件格式 *.tfrecords
Example结构
Example:
features{
fearutes{
key:"image"
value{
bytes_list{
value:"\377\374\375\372\356\351\365\361\350\356\352\350"
}
}
}
features{
key:"label"
value{
int64_list{
value:9
}
}
}
}
tf.train.Example 协议内存块(protocol buffer)(协议内存块包含了字段Features)
features包含了一个Feature字段
Feature中包含要写入的数据,并指明数据类型。
这是一个样本的结构,批数据需要循环存入这样的结构
Example = tf.train.Example(features=tf.train.Features(feature={
"image":tf.train.Feature(bytes_list=tf.train.BytesList)
"label":tf.train.Feature(int64_list=tf.train.Int64List)
}))tf.train.Example(features=None)
写入tfrecords文件
features:tf.train.Features类型的特征实例
return:example格式协议块
tf.train.Features(feature=None)
构建每个样本的信息键值对
feature:字典数据,key为要保存的名字
value为tf.train.Feature实例
return:Feature类型
tf.train.Feature(options)
options:例如
bytes_list=tf.train.BytesList(value=[Bytes])
int64_list=tf.train.Int64List(value=[Value])
支持存入的类型如下
tf.train.Int64List(value=[value])
tf.train.BytesList(value=[Bytes])
tf.train.FloatList(value=[value])
这种数据结构很好的实现了数据和标签(训练的类别标签)或者其他属性数据存储在同一个文件中
CIFAR10数据存入TFRecords文件
import tensorflow as tf
class Cifar():
def __init__(self):
self.height = 32
self.width = 32
self.channel = 3
self.image = self.height*self.width*self.channel
self.label = 1
self.sample = self.image + label.label
def write_to_tfrecords(self,image_batch,label_batch):
#将样本的特征值和目标值一起写入tfrecord文件
with tf.python_io.write_to_tfrecordsWriter("cifar10.tfrecords") as writer:
#循环构造example对象,并序列化写入文件
for i in range(100):
image = image_batch[i].tostring()
label = label_batch[i][0]
#print("tfrecords_image:\n",image)
#print("tfrecords_label:\n",label)
example = tf.train.Example(features = tf.train.Features(feature={
"image":tf.train.Feature(bytes_list = tf.train.ByteList(value=[image])),
"label":tf.train.Feature(int64_list=tf.train.Int64List(value=[label])),
}))
#example.SerializeToString()
#将序列化后的example写入文件
writer.write(example.SerializeToString())
return None
if __name__ == "__main__":
cifar = Cifar()
image_value,label_value = cifar.read_binary()
cifar.write_to_tfrecords(image_value,label_value)
读取CIFAR的TFRecords文件
读取CIFAR的TFRecords文件
1)使用tf.train.string_input_producer构造文件队列
2)tf.TFRecordReader读取TFRecords数据并运行解析
tf.parse_single_example进行解析
3) tf.decode_raw解码
类型是bytes类型需要解码
其他类型不需要
处理图片数据形状以及数据类型,加入批处理队列
开启会话线程运行读取TFRecords文件API
读取这种文件整个过程与其他文件一样,只不过需要有个解析Example的步骤。从TFRecords文件中读取数据,可以使用tf.TFRecordReader的tf.parse_single_example解析器,这个操作可以将将Example协议内存块(protocol buffer)解析为张量。
#多了解析example的一个步骤
feature = tf.parse_single_example(values,features={
"image":tf.FixedLenFeature([],tf.string)
"label":tf.FixedLenFeature([],tf.int64)
})
tf.parse_single_example(serialized,features=None,name=None)
解析一个单一的Example原型
serialized:标量字符串Tensor,一个序列化的Example
features:dict字典数据,键为读取的名字,值为FixedLenFeature
return:一个键值对组成的字典,键为读取的名字
tf.FixedLenFeature(shape,dtype)
shape:输入数据的形状,一般不指定,为空列表
dtype:输入数据类型,与存储文件的类型要一致
类型只能是float32,int64,string
def read_tfrecords(self):
#1 构造文件名队列
file_queue = tf.train.string_input_producer(["cifar10.tfrecords"])
#2 读取与解码
#读取
reader = tf.TFRecordReader()
key,value = reader.read(file_queue)
#解析example
feature = tf.parse_single_example(value,features={
"image":tf.FixedLenFeature([],tf.string),
"lable":tf.FixedLenFeature([],tf.int64),
})
image = feature["image"]
lable = feature["label"]
print("read_tf_image:\n",image)
print("read_tf_label:\n",label)
#解码
image_decoded = tf.decode_raw(image,tf.uint8)
print("image_decoded:\n",image_decoded)
#调整图像形状
image_reshaped = tf.reshape(images_decoded,[self.height,self,width,self.channel])
#构造批处理队列
image_batch,label_batch=
tf.train.batch([image_reshaped,label],batch_size=100,num_threads=2,capacity=100)
print("image_batch:\n",image_batch)
print("label_batch:\n",label_batch)
with tf.Session() as sess:
#开启线程
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runner(sess=sess,coord=coord)
image_value,label_value = sess.run([image_batch,label_batch])
coord.requst_stop()
coord.join(threads)
return None