tensorflow 简明教程

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_ FLOATtf.float3232位浮点数.
DT_ DOUBLEt.float6464位浮点数.
DT_ INT64tf.int6464位有符号整型.
DT_ INT32tf.int3232位有符号整型.
DT_ INT16tf.int1616位有符号整型.
DT_ INT8tf.int88位有符号整型.
DT_ UINT8tf.uint88位无符号整型
DT_ STRINGtf.string可变长度的字节数组,每一个张量元素都是一个字节数组.
DT_ BOOLtf.bool布尔型.
DT_ COMPLEX64       tf. complex64         由两个32位浮点数组成的复数:实数和虚数.
DT._QINT32tf.qint32用于量化Ops的32位有符号整型.
DT._QINT8tf.qint8用于量化Ops的8位有符号整型.
DT_ QUINT8tf.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默认一次读取一个example

tf.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

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值