TensorFlow编程基础

TensorFlow编程相关基础知识,会逐渐补充,以备复习

编程模型

一个TensorFlow程序的执行过程一般分为3个阶段:

  • 创建计算图
  • 运行一个会话,以完成计算图中定义的操作
  • 输出数据集合和分析

用placeholder函数定义一个数据或张量需要3个参数。第一个是数据类型。第二个是占位
符 的形状,本例中为一个一维张量,含有一个条目,第三个是变量名

1
2
3
4
5
6
7
8
9
import tensorflow as tf
with tf.Session() as session: #创建一个对象包含计算图
x = tf.placeholder(tf.float32, [1], name="x") #利用占位符概念定义变量
y = tf.placeholder(tf.float32, [1], name="y")
z = tf.constant(2.0)
y = x * z
x_in = [100]#该程序可以处理非常大、非常复杂的x值,所以可以创建x_in列表,并使其指向占位符x。
y_output = session.run(y, {x: x_in}) #只有执行session.run()时,程序才会开始处理已定义的图元素
print(y_output)
[200.]

数据模型

TensorFlow的数据模型由张量表示。忽略那些复杂的数学定义,可以说( TensorFlow中的)
“张量”指的是一个多维数值阵列。
这种数据结构由3个参数描述——阶( rank)、 形状( shape) 和数据类型( type)

每个张量的维度单位用阶来描述。它定义了张量的维数,因此,也被称为一个张量的量级或
张量的n个维。零阶张量是一个标量,一阶张量是一个向量,二阶张量是一个矩阵

1
2
3
4
5
6
7
8
9
10
#定义TensorFlow中的标量,向量,矩阵,立方阵
import tensorflow as tf
scalar=tf.constant(100)
vector=tf.constant([1,2,3,4,5])
matrix=tf.constant([[1,2,3],[4,5,6]])
cube_matrix=tf.constant([[[1],[2],[3]],[[4],[5],[6]],[[7],[8],[9]]])
print(scalar.get_shape())
print(vector.get_shape())
print(matrix.get_shape())
print(cube_matrix.get_shape())
()
(5,)
(2, 3)
(3, 3, 1)

形状

张量的形状指的是其行数和列数
使用get_shape()函数

数据类型

TensorFlow中数据的传递需要通过其API与NumPy数组的交互来完成

tf.constant() 定义常量

tf.variable() 定义变量

取回

同时取回多个操作的输出

1
2
3
4
5
6
7
8
9
import tensorflow as tf
constant_A=tf.constant([100.0])
constant_B=tf.constant([300.0])
constant_C=tf.constant([3.0])
sum_=tf.add(constant_A,constant_B)
mul_=tf.multiply(constant_A,constant_C)
with tf.Session() as sess:
result=sess.run([sum_,mul_])
print(result)
[array([400.], dtype=float32), array([300.], dtype=float32)]

注入

注入机制将张量插入图节点,它用一个张量值暂时替代操作的输出。注入机制只用于在调用
run函数时,通过feed_dict传递参数。最常见的用法是使用tf.placeholder()创建feed操作,
并继承其他特定操作作为注入操作。

1
2
3
4
5
6
7
8
9
import tensorflow as tf
import numpy as np
a=3
b=2
x=tf.placeholder(tf.float32,shape=(a,b))
y=tf.add(x,x)
data=np.random.rand(a,b)
sess=tf.Session()
print(sess.run(y,feed_dict={x:data}))
[[1.1956241  0.17609641]
 [1.9851147  1.7567049 ]
 [0.4986568  0.8624873 ]]

TensorBoard

训练神经网络时,有时会需要监控网络的参数,一般是节点的输入和输出。这样即可在每次
训练迭代后检查误差函数是否最小化,从而了解你的模型是否正确学习。

TensorFlow提供了TensorBoard框架,用于分析和调试神经网络模型。

TensorBoard采用所谓的汇总来查看模型的参数;一旦TensorFlow代码执行,我们就可以调用TensorBoard的图形用户界面来查看汇总数据。

此外, TensorBoard还可以显示并学习TensorFlow的计算图。一个深度神经网络模型的计算图
往往会非常复杂

工作流程如下:

  • 编译你的计算图/代码;
  • 添加汇总op到你需要分析的节点上;
  • 照常运行你的计算图;
  • 同时附带运行汇总op;
  • 代码运行完成后, 启动TensorBoard;
  • 可视化汇总输出。

实例:实现一个单输入神经元

损失函数采用结果与期望值的差的平方,越小越好

优化函数采用梯度下降法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import tensorflow as tf
input_value=tf.constant(0.5,name="input_value") #输入值,不变
weight=tf.Variable(1.0,name="weight") #权值,会更新
expected_output=tf.constant(0.0,name="expected_output") #期望输出
model=tf.multiply(input_value,weight,"model") #操作,模型
loss_function=tf.pow(expected_output-model,2) #损失函数
optimizer=tf.train.GradientDescentOptimizer(0.025).minimize(loss_function) #优化函数

#接下来 tensorboard
for value in [input_value,weight,expected_output,model,loss_function]:
tf.summary.scalar(value.op.name,value)
summaries=tf.summary.merge_all() #为每个运行的结点添加分析,然后总结
sess=tf.Session()
log_path="../Tensorboardlog\og_simple_stats"
summary_writer=tf.summary.FileWriter(log_path,sess.graph) #声明路径
sess.run(tf.global_variables_initializer())
for i in range(100):
summary_writer.add_summary(sess.run(summaries),i) #写入信息
sess.run(optimizer)

实例

实例1:从一组看似混乱的数据中找出y=2x的规律

1
2
3
4
5
6
7
8
9
10
11
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
train_X=np.linspace(-1,1,100)
train_Y=2*train_X+np.random.randn(100)*0.3
#显示模拟数据点
plt.plot(train_X,train_Y,'ro',label='Original data')
plt.legend()
plt.show()

png

接下来进行模型搭建,正向和反向

创建模型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
X=tf.placeholder("float")
Y=tf.placeholder("float")
#模型参数
W=tf.Variable(tf.random_normal([1]),name="weight")
#tf.random_normal()函数用于从服从指定正态分布的数值中取出指定个数的值
b=tf.Variable(tf.zeros([1]),name="bias")
#前向结构
z=tf.multiply(X,W)+b #乘以权值加上偏差
#反向优化
cost=tf.reduce_mean(tf.square(Y-z))
#学习率一般小于1,小而精确且慢
learning_rate=0.01
#梯度下降
optimizer=tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)

接下来迭代训练模型,先进行全局初始化,然后设置训练迭代的次数,启动session开始运行任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
init=tf.global_variables_initializer()
#定义参数
training_epochs=20 #迭代次数
display_step=2
saver=tf.train.Saver()
savedir="log/"
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)]
#启动session
with tf.Session() as sess:
sess.run(init)
plotdata={"batchsize":[],"loss":[]} #存放批次值和损失值
#向模型输入数据
for epoch in range(training_epochs):
for (x,y) in zip(train_X,train_Y):
sess.run(optimizer,feed_dict={X:x,Y:y})

#显示训练中的详细信息
if epoch % display_step==0:
loss=sess.run(cost,feed_dict={X:train_X,Y:train_Y})
print("Epoch:",epoch+1,"cost=",loss,"W=",sess.run(W),"b=",sess.run(b))
if not (loss=="NA"):
plotdata["batchsize"].append(epoch)
plotdata["loss"].append(loss)
print("Finished!")
saver.save(sess,savedir+"linermodel.cpkt") #保存模型
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='Fittedline')
plt.legend()
plt.show()

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()

#模型训练后,使用模型
print("x=0.2,z=",sess.run(z,feed_dict={X:0.2}))
Epoch: 1 cost= 0.70816207 W= [0.75885475] b= [0.35309508]
Epoch: 3 cost= 0.12805094 W= [1.649097] b= [0.11414018]
Epoch: 5 cost= 0.08086114 W= [1.8904546] b= [0.02324806]
Epoch: 7 cost= 0.0777822 W= [1.9530506] b= [-0.00074375]
Epoch: 9 cost= 0.07760694 W= [1.9692401] b= [-0.00695578]
Epoch: 11 cost= 0.0776032 W= [1.9734255] b= [-0.00856198]
Epoch: 13 cost= 0.077605 W= [1.9745078] b= [-0.00897733]
Epoch: 15 cost= 0.07760566 W= [1.9747877] b= [-0.0090847]
Epoch: 17 cost= 0.077605836 W= [1.9748603] b= [-0.00911253]
Epoch: 19 cost= 0.07760589 W= [1.9748794] b= [-0.00911988]
Finished!
cost= 0.077605896 W= [1.9748821] b= [-0.00912086]

png

png

x=0.2,z= [0.3858556]

Tensorflow将中间结点及结点间的运算关系定义在图上,图是静态的,会话是动态的,只有启动会话后才会将数据流向图中

定义数据时可以通过占位符,也可以通过字典方式,也可以直接定义

记得在session创建后初始化所有变量,而变量定义在此之前


TensorFlow模型构建的概念

两个重要的机制:注入机制,取回机制

注入机制:占位符
placeholder,feed-dict

示例如下:

1
2
3
4
5
6
7
8
9
10
11
a=tf.placeholder(tf.int32)
b=tf.placeholder(tf.int32)
add=tf.add(a,b)
multiply=tf.multiply(a,b)
mysess=tf.Session()
print(mysess.run(add,feed_dict={a:1,b:2}))
print(mysess.run(multiply,feed_dict={a:1,b:2}))
#一次取出多个结点
print(mysess.run([add,multiply],feed_dict={a:1,b:2}))
mysess.close()

3
2
[3, 2]

建立session可以直接

也可以with tf.Session() as sess

然后还有方法是交换式session方式:

sess=tf.InteractiveSession()

另一种是Supervisor方式:该方式会更高级一些, 使用起来也更加复
杂, 可以自动来管理session中的具体任务, 例如, 载入/载出检查点文件、 写入TensorBoard等, 另外该方法还支持分布式训练的部署


保存和载入模型

保存模型

训练完模型后: tf.train.Saver().save(sess,”save_path/file_name”)

载入模型

调用saver的restore函数

保存载入模型实例

1
2
3
4
5
6
#保存模型见上文代码 中saver
#载入模型
with tf.Session() as sess2:
sess2.run(tf.global_variables_initializer())
saver.restore(sess2,savedir+"linermodel.cpkt")
print("x=0.2,z=",sess2.run(z,feed_dict={X:0.2}))
WARNING:tensorflow:From E:\Python\Anaconda\lib\site-packages\tensorflow\python\training\saver.py:1276: checkpoint_exists (from tensorflow.python.training.checkpoint_management) is deprecated and will be removed in a future version.
Instructions for updating:
Use standard file APIs to check for files with this prefix.
INFO:tensorflow:Restoring parameters from log/linermodel.cpkt
x=0.2,z= [0.3858556]

打印模型内容

1
2
3
4
from tensorflow.python.tools.inspect_checkpoint import print_tensors_in_checkpoint_file
savedir="log/"
print_tensors_in_checkpoint_file(savedir+"linermodel.cpkt",None,True)

tensor_name:  bias
[-0.00912086]
tensor_name:  weight
[1.9748821]
# Total number of params: 2


为模型添加保存检查点,继续修改原代码

完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
#定义生成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(100)*0.3

tf.reset_default_graph()
#创建模型
#占位符
X=tf.placeholder("float")
Y=tf.placeholder("float")
#模型参数
W=tf.Variable(tf.random_normal([1]),name="weight")
b=tf.Variable(tf.zeros([1]),name="bias")
#前向结构
z=tf.multiply(X,W)+b

#反向优化
cost=tf.reduce_mean(tf.square(Y-z))
learning_rate=0.01
optimizer=tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)
#初始化所有变量
init=tf.global_variables_initializer()
#定义学习参数
training_epochs=20
display_step=2
#生成saver
saver=tf.train.Saver(max_to_keep=1)
savedir="log/"
#启动图
with tf.Session() as sess:
sess.run(init)
#向模型中输入数据
for epoch in range(training_epochs):
for (x,y) in zip(train_X,train_Y):
sess.run(optimizer,feed_dict={X:x,Y:y})
#显示训练中的详细信息
if epoch % display_step==0:
loss=sess.run(cost,feed_dict={X:train_X,Y:train_Y})
print("Epoch:",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='Fittedline')
plt.legend()
plt.show()

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())
saver.restore(sess2,savedir+"linermodel.cpkt-"+str(load_epoch))
print("x=0.2,z=",sess2.run(z,feed_dict={X:0.2}))
Epoch: 1 cost= 1.4514498 W= [0.24221869] b= [0.5121559]
Epoch: 3 cost= 0.18433338 W= [1.5415516] b= [0.16298366]
Epoch: 5 cost= 0.07567732 W= [1.8937755] b= [0.03033424]
Epoch: 7 cost= 0.067009285 W= [1.9851238] b= [-0.00467777]
Epoch: 9 cost= 0.066090204 W= [2.0087478] b= [-0.01374275]
Epoch: 11 cost= 0.06594107 W= [2.014856] b= [-0.0160868]
Epoch: 13 cost= 0.06590843 W= [2.0164354] b= [-0.0166929]
Epoch: 15 cost= 0.06590037 W= [2.016844] b= [-0.0168497]
Epoch: 17 cost= 0.065898314 W= [2.0169504] b= [-0.01689044]
Epoch: 19 cost= 0.0658978 W= [2.0169766] b= [-0.0169006]
Finished!
cost= 0.06589771 W= [2.0169811] b= [-0.01690225]

png

png



模型操作相关函数

常用函数总结(见pdf书籍)

保存模型

数值操作相关函数

类型转换函数

形状变换函数

  • tf.shape(input,name=None)
    返回一个张量,值为输入参数input的shape,input可以是个张量,也可以是一个数组或list
  • tf.size(input,name=None)
    返回一个张量,内容为输入数据的元素数量
  • tf.rank(input,name=None)
    返回一个张量,其内容为输入数据input的rank,此处的rank看的是中括号的层数
  • tf.reshape(input,shape,name=None)
    将原有数据的shape按照指定形状进行变换,生成一个新的张量
  • tf.expand_dims(input,dim,name=None)
    插入维度1进入一个tensor中
  • tf.squeeze(input,dim,name=None)
    将dim指定的维度去掉(dim所指定的维度必须为1,如果不为1则会报错)

TensorFlow编程基础
https://shanhainanhua.github.io/2019/10/20/TensorFlow编程基础/
作者
wantong
发布于
2019年10月20日
许可协议