Tensorflow编程基础笔记之二——图的基本操作和编程模型
- 图的基本操作
- 编程模型
2.1 图的基本操作
- 图的基本操作包括建立图、获取张量、获取节点操作、获取元素列表和获取对象
import numpy as np
import tensorflow as tf
import os
#张量c是在刚开始默认图中建立的,获得图的第一种方法
c=tf.constant(0.0)
print("查看程序初始默认图的内存地址:",c.graph)
g1=tf.get_default_graph()
print("将程序初始默认图命名为g1,查看g1的内存地址:",g1)
#获得图的第二种方法
g2=tf.Graph()
#with语句表示下面的所有操作如果没有指定图,那么都是在g图中的操作
with g2.as_default():
c1=tf.constant(0.0)
print("g2图中建立的张量c1:",c1.graph)
print("查看g2图的内存地址:",g2)
#获得图的第三种方法
#tf.resset_default_graph函数相当于重新建立了一张图来代替原来的默认图
#在使用tf.reset_default_graph函数时必须保证当前图的资源已经全部释放,否则会报错。
tf.reset_default_graph()
g3=tf.get_default_graph()
print("查看新建默认图g3的内存地址:",g3)
查看程序初始默认图的内存地址: <tensorflow.python.framework.ops.Graph object at 0x0000019B2A7AC390>
将程序初始默认图命名为g1,查看g1的内存地址: <tensorflow.python.framework.ops.Graph object at 0x0000019B2A7AC390>
g2图中建立的张量c1: <tensorflow.python.framework.ops.Graph object at 0x0000019B2A7ACB70>
查看g2图的内存地址: <tensorflow.python.framework.ops.Graph object at 0x0000019B2A7ACB70>
查看新建默认图g3的内存地址: <tensorflow.python.framework.ops.Graph object at 0x0000019B2A7ACC88>
2.2 获取张量
- 在图里面可以通过名字得到其对应的元素,如,get_tensor_by_name可以获得图里面的张量
- **注意:**不必花太多精力去关注TensorFlow中默认的命名规则。一般在需要使用名字时都会在定义的同时为它指定好固定的名字。
print(c1.name)
t=g2.get_tensor_by_name(name="Const:0")
print(t)
Const:0
Tensor("Const:0", shape=(), dtype=float32)
2.3 获取节点操作
- 获取节点操作OP的方法和获取张量的方法非常类似,使用的方法是get_operation_by_name。
- 计算图中每一个运算操作将作为一个节点(node,又称为operation,缩写成op),节点与节点之间的连接成为边(edge),而在计算图的边中流动(flow)的数据被称为张量(tensor)
- **注意:**节点操作OP和张量在定义节点时很容易被混淆。tensor1=tf.matmul()并不是OP,而是张量。OP其实是描述张量中的运算关系,是通过访问张量的op属性找到的
a=tf.constant([[1.0,2.0]])
b=tf.constant([[1.0],[3.0]])
tensor1=tf.matmul(a,b,name='exampleop')
print('·计算图中的默认张量名tensor1.name=',tensor1.name,'·图中定义的张量tensor1=',tensor1,sep='\n')
test=g3.get_tensor_by_name('exampleop:0')
print('·通过图中默认张量名[exampleop:0]获得结果张量:',test,sep='\n')
print('输出张量tensor1的节点操作名tensor1.op.name=',tensor1.op.name)
testop=g3.get_operation_by_name('exampleop')
print('·通过图中自定义节点操作名[exampleop]获得结果张量:',testop,sep='\n')
with tf.Session() as sess:
test=sess.run(test)
print('·通过图中自定义节点操作名[exampleop]输出结果张量:',test,sep='\n')
test=tf.get_default_graph().get_tensor_by_name('exampleop:0')
print('·通过图中默认张量名[exampleop:0]输出结果张量:',test,sep='\n')
·计算图中的默认张量名tensor1.name=
exampleop:0
·图中定义的张量tensor1=
Tensor("exampleop:0", shape=(1, 1), dtype=float32)
·通过图中默认张量名[exampleop:0]获得结果张量:
Tensor("exampleop:0", shape=(1, 1), dtype=float32)
输出张量tensor1的节点操作名tensor1.op.name= exampleop
·通过图中自定义节点操作名[exampleop]获得结果张量:
name: "exampleop"
op: "MatMul"
input: "Const"
input: "Const_1"
attr {
key: "T"
value {
type: DT_FLOAT
}
}
attr {
key: "transpose_a"
value {
b: false
}
}
attr {
key: "transpose_b"
value {
b: false
}
}
·通过图中自定义节点操作名[exampleop]输出结果张量:
[[ 7.]]
·通过图中默认张量名[exampleop:0]输出结果张量:
Tensor("exampleop:0", shape=(1, 1), dtype=float32)
2.4 获取元素列表
- 使用get_operations函数实现
- 由于运算多遍,导致输出的元素列表中有很多重复的元素。
tt2=g3.get_operations()
print(tt2)
[<tf.Operation 'Const' type=Const>, <tf.Operation 'Const_1' type=Const>, <tf.Operation 'exampleop' type=MatMul>]
2.5 获取对象
- 可以根据名字来获取元素,还可以根据对象来获取元素。使用tf.Graph.as_graph_element()函数,即传入一个对象,返回一个张量或是一个OP
- 该函数具有验证和转换功能,在多线程方面会偶尔用到。
tt3=g3.as_graph_element(a)
print(tt3)
Tensor("Const:0", shape=(1, 2), dtype=float32)
**注意:**张量本质上也是一个对象。
3.1 编程模型
- TensorFlow的命名来源于本身的运行原理。Tensor(张量)意味着N维数组,Flow(流)意味着基于数据流图的计算。TensorFlow是张量从图像的一端流动到另一端的计算过程,这也是TensorFlow的编程模型。
- TensorFlow的运行机制属于“定义”与“运行”相分离。从操作层面可以抽象成两种:模型构建和模型运行。
- 模型构建中的概念
类型 | 描述 | 用途 |
---|---|---|
Session | 会话 | 图必须在称之为“会话”的上下文中执行。会话将图的OP分发到诸如CPU或GPU上计算 |
Graph(计算图) | 描述结算过程 | 必须在Session中启动 |
tensor(张量) | 数据 | 数据类型之一,代表多维数组 |
图中的节点操作(operation,op) | 操作 | 图中的节点称之为op,一个op获得0或者多个Tensor,执行计算,产生0或者多个Tensor |
Variable(变量) | 变量 | 数据类型之一,运行过程中可以被改变,用于维护状态,常用于定义模型中的参数 |
placeholder(占位符) | 占位符 | 输入变量的载体。可理解成定义函数时的参数 |
feed(注入机制) | 赋值 | 为op的Tensor赋值,通过占位符向模型中传入数据 |
fetch(取回机制) | 取值 | 从op的Tensor中取值,从模型中得到结果 |
Constant(常量) | 常量 | 数据类型之一,不可变 |
- session将图的OP分发到如CPU或GPU之类的设备上,同时提供执行OP的方法,这些方法执行后,将产生的tensor返回。
- 在Python语言中,返回的tensor是numpy ndarray对象。
- 在模型中,实参就是输入的样本,形参就是占位符,运算过程就相当于函数体,得到的结果相当于返回值。
3.2 模型注入机制
使用注入机制,将具体的实参注入到相应的placeholder中。feed只在调用它的方法内有效,方法结束后feed就会消失。
import tensorflow as tf
a=tf.placeholder(tf.int16)
b=tf.placeholder(tf.int16)
add=tf.add(a,b)
mul=tf.multiply(a,b)
with tf.Session() as sess:
print("相加:%i"% sess.run(add,feed_dict={a:3,b:4}))
print("相乘:%i"% sess.run(mul,feed_dict={a:3,b:4}))
#一次将多个节点取出来
print(sess.run([mul,add],feed_dict={a:3,b:4}))
相加:7
相乘:12
[12, 7]
3.3 保存和载入模型
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
#确保生成的图片插入文档中
%matplotlib inline
#定义生成loss可视化的函数
plotdata={"batchsize":[],"loss":[]}
def moving_average(a,w=10):
if len(a)<w:
return a[:]
return [val if idx <w else sum(a[(idx-w):idx])/w for idx,val in enumerate(a)]
#生成模拟数据
train_X=np.linspace(-1,1,100)
train_Y=2 * train_X +np.random.randn(*train_X.shape) *0.3
#图形显示
plt.plot(train_X,train_Y,'ro',label='Original data')
plt.legend()
plt.show()
#创建模型
#占位符
X=tf.placeholder("float")
Y=tf.placeholder("float")
#模型参数,参数后面的name可用于保存模型时使用
W=tf.Variable(tf.random_normal([1]),name='weight')
b=tf.Variable(tf.zeros([1]),name='bias')
#前向结构
z=tf.multiply(X,W)+b
#TensorBoard可视化第一步
tf.summary.histogram('z',z) #将预测值以直方图形式显示,给直方图命名z
<tf.Tensor 'z:0' shape=() dtype=string>
#反向优化
cost=tf.reduce_mean(tf.square(Y-z))
learning_rate=0.01
optimizer=tf.train.GradientDescentOptimizer(learning_rate).minimize(cost) #梯度下降
#TensorBoard可视化第一步
tf.summary.scalar('loss_function',cost) #将损失值以标量形式显示,命名为loss_function
<tf.Tensor 'loss_function:0' shape=() dtype=string>
#初始化所有变量
init=tf.global_variables_initializer()
#定义学习参数
training_epochs=20
display_step=2
#设置模型保存的参数和路径,生成saver
saver=tf.train.Saver(max_to_keep=1)
savedir="log/"
#print("打印当前目录:",os.getcwd())
#启动图
with tf.Session() as sess:
sess.run(init) #先对模型初始化
plotdata={"batchsize":[],"loss":[]} #由于在网页中运行会多次存储,因此在这里重新初始化
#TensorBoard可视化第二步
merged_summary_op=tf.summary.merge_all() #合并所有summary
#创建summary_writer,用于写文件
summary_writer=tf.summary.FileWriter('log/mnist_with_summaries',sess.graph)
#向模型中输入数据
for epoch in range(training_epochs):
for (x,y) in zip(train_X,train_Y):
sess.run(optimizer,feed_dict={X:x,Y:y})
#TensorBoard可视化第三步——生成summary
summary_str=sess.run(merged_summary_op,feed_dict={X:x,Y:y})
summary_writer.add_summary(summary_str,epoch) #将summary写入文件
#显示训练中的详细信息
if epoch % display_step==0:
loss=sess.run(cost,feed_dict={X:train_X,Y:train_Y})
print("训练次数:",epoch+1,"cost=",loss,"W=",sess.run(W),"b=",sess.run(b))
if not(loss=="NA"):
plotdata["batchsize"].append(epoch)
plotdata["loss"].append(loss)
saver.save(sess,savedir+"linermodel.cpkt",global_step=epoch)
print("Finished!")
print("cost=",sess.run(cost,feed_dict={X:train_X,Y:train_Y}),"W=",sess.run(W),"b=",sess.run(b))
#显示模型
plt.plot(train_X,train_Y,'ro',label='Original data')
plt.plot(train_X,sess.run(W)*train_X+sess.run(b),label='Fitted Wline')
plt.legend()
plt.show()
训练次数: 1 cost= 2.06425 W= [-0.17830342] b= [ 0.60749894]
训练次数: 3 cost= 0.237772 W= [ 1.3914659] b= [ 0.18420461]
训练次数: 5 cost= 0.0860665 W= [ 1.81684232] b= [ 0.02398242]
训练次数: 7 cost= 0.0751848 W= [ 1.92715943] b= [-0.01830052]
训练次数: 9 cost= 0.0742996 W= [ 1.95568919] b= [-0.02924783]
训练次数: 11 cost= 0.0741998 W= [ 1.9630661] b= [-0.03207865]
训练次数: 13 cost= 0.0741826 W= [ 1.96497369] b= [-0.03281069]
训练次数: 15 cost= 0.0741787 W= [ 1.9654671] b= [-0.03300003]
训练次数: 17 cost= 0.0741778 W= [ 1.96559441] b= [-0.03304888]
训练次数: 19 cost= 0.0741775 W= [ 1.96562755] b= [-0.03306159]
Finished!
cost= 0.0741775 W= [ 1.96563327] b= [-0.03306378]
plotdata["avgloss"]=moving_average(plotdata["loss"])
plt.figure(1)
plt.subplot(211)
plt.plot(plotdata["batchsize"],plotdata["avgloss"],'b--')
plt.xlabel('Minibatch number')
plt.ylabel('Loss')
plt.title('Minibatch run vs Training loss')
plt.show()
#重启一个session,载入检查点(通过指定迭代次数获取检查点文件)
load_epoch=18
with tf.Session() as sess2:
sess2.run(tf.global_variables_initializer()) #先对模型初始化
#使用restore()方法,参数可以进行初始化,也可以不进行初始化,因为即使初始化了,初始化的值也会被restore的值给覆盖
saver.restore(sess2,savedir+"linermodel.cpkt-"+str(load_epoch))
print("x=0.2,z=",sess2.run(z,feed_dict={X:0.2}))
INFO:tensorflow:Restoring parameters from log/linermodel.cpkt-18
x=0.2,z= [ 0.36006391]
#重启一个session,使用其他方法载入检查点(tr.train.get_checkpoint_state(ckpt_dir))
with tf.Session() as sess3:
sess3.run(tf.global_variables_initializer())
ckpt=tf.train.get_checkpoint_state(savedir)
if ckpt and ckpt.model_checkpoint_path:
saver.restore(sess3,ckpt.model_checkpoint_path)
print("x=0.2,z=",sess3.run(z,feed_dict={X:0.2}))
INFO:tensorflow:Restoring parameters from log/linermodel.cpkt-18
x=0.2,z= [ 0.36006391]
#重启一个session,使用其他方法载入检查点(tr.train.latest_checkpoint(savedir))
with tf.Session() as sess4:
sess4.run(tf.global_variables_initializer())
kpt=tf.train.latest_checkpoint(savedir)
if kpt!=None:
saver.restore(sess4,kpt)
print("x=0.2,z=",sess4.run(z,feed_dict={X:0.2}))
INFO:tensorflow:Restoring parameters from log/linermodel.cpkt-18
x=0.2,z= [ 0.36006391]
#查看模型内容
from tensorflow.python.tools.inspect_checkpoint import print_tensors_in_checkpoint_file
print_tensors_in_checkpoint_file(savedir+"linermodel.cpkt-18",None,True)
tensor_name: bias
[-0.03306159]
tensor_name: weight
[ 1.96562755]
**注意:**通过模型内容可以看到,tensor_name:后面跟的就是创建的变量名,接着就是它的数值。