TensorFlow1学习

TensorFlow1学习

1.简介与基础

深度学习的框架有很多:TensorFlow、Caffe、Theano、Torch等,其中Keras是在TensorFlow基础上构建的高层API,Keras在TensorFlow中,本次使用的tensorflow为1.12.0。

tensorflow包括两个阶段:

  • 构建计算图(tf.Graph):

    • 张量/数据(Tensor):主要包括[名称、维度、类型],即[name,shape,type]

    • 操作(OPeration):我们构建的计算图的节点

  • 运行计算图/会话(tf.Session)

  • 以下为一个简单的tensorflow示例:

import tensorflow as tf

#第一阶段,构建计算图(用的是默认图)
a = tf.constant(2.0, dtype=tf.float32)
b = tf.constant(3.0)
c = tf.add(a, b)

print('a', a)
print('b', b)
print('c', c)

#第二阶段,运行计算图(默认图)
with tf.Session() as sess:
   print(sess.run(b))
   print('在会话中run后的加法结果', sess.run(c))

#运行结果
a Tensor("Const:0", shape=(), dtype=float32)
b Tensor("Const_1:0", shape=(), dtype=float32)
c Tensor("Add:0", shape=(), dtype=float32)
3.0
在会话中run后的加法结果 5.0

 

1.1 构建计算图(Graph)

1.1.1默认图

通常Tensorflow会默认帮我们创建一张图,查看默认图有两种方法;

  1. default_g = tf.get_default_graph() #创建一个默认图,赋值给default_g

  2. 使用上面代码的a与sess,a.graph或sess.graph,因为这两个便是节点与运行,且都有默认的graph属性。

    其运行的代码如下(拼接上面的代码,下面没有重新import的都一样,之后不重复说明):

default_g = tf.get_default_graph()
print('attribute', default_g)
print('attribute', a.graph)
print('attribute', sess.graph)
#结果显示
attribute <tensorflow.python.framework.ops.Graph object at 0x000001CB0F8DE748>
attribute <tensorflow.python.framework.ops.Graph object at 0x000001CB0F8DE748>
attribute <tensorflow.python.framework.ops.Graph object at 0x000001CB0F8DE748>

1.1.2创建新图

与上面的默认图差不多的形式:

new_g = tf.Graph() #创建一个新的图,赋值给new_g

如果要对新图进行相关处理,则用new_g.as_default()。

代码如下:

new_g = tf.Graph()
with new_g.as_default():
   a_new = tf.constant([15])
   print('a_new', a_new)
#结果显示
a_new Tensor("Const:0", shape=(1,), dtype=int32)

1.1.3Tensor张量/数据

张量Tensor有3个属性(attrtibute):名称(name)、维度(shape)、类型(type)

(1). 0阶张量
mammal = tf.Variable("Elephant", tf.string)
ignition = tf.Variable(451, tf.int16)
floating = tf.Variable(3.14159265359, tf.float64)
its_complicated = tf.Variable(12.3 - 4.85j, tf.complex64)
print(mammal, type(mammal))
print(ignition, type(ignition))
print(floating, type(floating))
print(its_complicated, type(its_complicated))
#结果显示
<tf.Variable 'Variable:0' shape=() dtype=string_ref> <class 'tensorflow.python.ops.variables.Variable'>
<tf.Variable 'Variable_1:0' shape=() dtype=int32_ref> <class 'tensorflow.python.ops.variables.Variable'>
<tf.Variable 'Variable_2:0' shape=() dtype=float32_ref> <class 'tensorflow.python.ops.variables.Variable'>
<tf.Variable 'Variable_3:0' shape=() dtype=complex128_ref> <class 'tensorflow.python.ops.variables.Variable'>

0阶张量就是一个数,其中tf.variable就是构造一个variable(变量)添加进图中,而variable()则是构造函数所需要的变量的初始值可以是一个任意形状、任意类型的张量/数据Tensor,而括号里的格式形如(initialization,name)分别是初始化的参数,即我们要的数据值,和数据的名字,所以下面一阶、二阶都用了,具体使用方法在下方变量相关操作中提到。

(2). 1阶张量
myst = tf.Variable(["Hello"], tf.string)
cool_numbers = tf.Variable((3.14159, 2.71828), tf.float32)
first_primes = tf.Variable((2, 3, 5, 7, 11), tf.int32)
its_very_complicated = tf.Variable([12.3 - 4.85j, 7.5 - 6.23j], tf.complex64)
print(myst, type(myst))
print(cool_numbers, type(cool_numbers))
print(first_primes, type(first_primes))
print(its_very_complicated, type(its_very_complicated))
#结果显示
<tf.Variable 'Variable_4:0' shape=(1,) dtype=string_ref> <class 'tensorflow.python.ops.variables.Variable'>
<tf.Variable 'Variable_5:0' shape=(2,) dtype=float32_ref> <class 'tensorflow.python.ops.variables.Variable'>
<tf.Variable 'Variable_6:0' shape=(5,) dtype=int32_ref> <class 'tensorflow.python.ops.variables.Variable'>
<tf.Variable 'Variable_7:0' shape=(2,) dtype=complex128_ref> <class 'tensorflow.python.ops.variables.Variable'>
(3). 2阶张量
mymat = tf.Variable([[7],[11]], tf.int16)
myxor = tf.Variable([[False, True],[True, False]], tf.bool)
linear = tf.Variable([[4], [9], [16], [25]], tf.int32)
squarish_squares = tf.Variable([ [4, 9], [16, 25] ], tf.int32)
rank = tf.rank(squarish_squares)
print(mymat, type(mymat))
print(myxor, type(myxor))
print(linear,type(linear))
print(squarish_squares,type(squarish_squares))
print(rank, type(rank))
#结果显示
<tf.Variable 'Variable_8:0' shape=(2, 1) dtype=int32_ref> <class 'tensorflow.python.ops.variables.Variable'>
<tf.Variable 'Variable_9:0' shape=(2, 2) dtype=bool_ref> <class 'tensorflow.python.ops.variables.Variable'>
<tf.Variable 'Variable_10:0' shape=(4, 1) dtype=int32_ref> <class 'tensorflow.python.ops.variables.Variable'>
<tf.Variable 'Variable_11:0' shape=(2, 2) dtype=int32_ref> <class 'tensorflow.python.ops.variables.Variable'>
Tensor("Rank:0", shape=(), dtype=int32) <class 'tensorflow.python.framework.ops.Tensor'>

其中tf.rank()为返回矩阵秩的函数, 注意:张量的秩与矩阵的秩不一样。张量的秩是唯一选择张量的每个元素所需的索引的数量。秩也被称为 “order”,“degree” 或 “ndims”。

在图像处理过程中,还有很多4阶张量,形如:

my_image = tf.zeros([10, 299, 299, 3]) #参数依次为:批处理大小、图像宽、图像高、图像颜色通道数
(4). 关于张量的一些操作
1.tf.reshape(x,shape)

作用是改变形状

matrix = tf.ones([3, 4, 5])
matrixA = tf.reshape(matrix, [6, 10])  #重塑成 6*10
matrixB = tf.reshape(matrixA, [3, -1])  # 重塑成 3x20
print(matrix)
print(matrixA)
print(matrixB)
#结果显示
Tensor("ones:0", shape=(3, 4, 5), dtype=float32)
Tensor("Reshape:0", shape=(6, 10), dtype=float32)
Tensor("Reshape_1:0", shape=(3, 20), dtype=float32)
2.Tensor中的常量(constant)
  • 生成0的张量函数 tf.zeros(shape=[2,2], dtypt=tf.float32, namhanghe=None)

  • 生成1的张量函数 tf.ones(shape=[2,2], dtypt=tf.float32, namhanghe=None)

  • 生成常数 tf.constant(value, dtype=None, Shape=None, name="Const")

  • numpy变为tensorflow数:data_tensor= tf.convert_to_tensor(data_numpy)

  • 生成都是value值的dims形状的张量 tf.fill(dims, value, name=None) ,形如:

import tensorflow as tf
t1 = tf.fill([2, 3], 3)
print(t1)
sess = tf.Session()#这部分其实是计算部分,先用,看我们的t1变成了什么
print(sess.run(t1))
#结果显示
Tensor("Fill:0", shape=(2, 3), dtype=int32)
[[3 3 3]
 [3 3 3]]
3.Tensor中的随机数(random)
  • tf.random_normal(shape, mean=0.0, stddev=1.0, dtype=tf.float32, seed=None, name=None)

    生成标准正态分布的随机张量

  • tf.truncated_normal(shape, mean=0.0, stddev=1.0, dtype=tf.float32, seed=None, name=None)

    shape表示生成张量的维度,mean是均值,stddev是标准差。这个函数产生截断的正态分布,就是说产生正态分布的值与均值的差值大于两倍的标准差,那就重新生成。和一般的正态分布的产生随机数据比起来,这个函数产生的随机数与均值的差距不会超过两倍的标准差,但是一般的别的函数是可能的。

  • tf.random_uniform(shape, minval=0, maxval=None, dtype=tf.float32, seed=None, name=None)

    从均匀分布中返回随机值,shape形状、minval最小值、maxval最大值。

  • tf.random_shuffle(value, seed=None, name=None)

    沿着要被洗牌的张量的第一个维度,随机打乱。value要洗牌的张量

4.Tensor中的初始化(initialize)
  • tf.constant_initializer(value=0, dtype=tf.float32)

也可以简写为tf.Constant(),初始化为常数,这个非常有用,通常偏置项就是用它初始化的。

  由它衍生出的几个初始化方法:

  1. tf.zeros_initializer(shape, dtype=tf.float32, partition_info=None)

  2. tf.ones_initializer(dtype=tf.float32, partition_info=None)

  3. tf.constant_initializer(0),tf.Constant(0)

  • tf.truncated_normal_initializer(mean=0.0, stddev=1.0, seed=None, dtype=tf.float32)

可简写为tf.TruncatedNormal(),生成截断正态分布的随机数,在tf中使用较多。

  • tf.ranndom_normal_initializer (mean=0.0, stddev=1.0, seed=None, dtype=tf.float32)

使用正态分布张量的初始化器,参数依次为:均值、方差、随机种子、数据类型

  • tf.random_uniform_initializer(minval=0, maxval=None, seed=None, dtype=tf.float32)

使用均匀分布张量的初始化器,参数依次为:最小值、最大值、随机种子、数据类型

  • tf.cast(x, dtype, name=None)

把张量x,变成任何的dtype,这里要与reshap分开,cast是变类型,如float32变成float16;reshap变的是维度,也就是我们说的形状,如zero[2, 3]变成zero[1, 6]。

注意:这些数据的类型都为float32,如果直接用都应该在tf.get_variable()中的initializer中

(5). 关于变量的一些操作

注意:所有变量进行相关操作都需要进行初始化。

1.变量创建variable相关

tf.Variable(initial_value=None, trainable=None, collections=None, validate_shape=True, caching_device=None, name=None, variable_def=None, dtype=None, expected_shape=None, import_scope=None, constraint=None, use_resource=None, shape=None)

在graph中创建变量,详细讲述请点击函数名,以下介绍了其常用参数。

  • initial_value:Tensor,定义Variable的初始值。

  • trainable:如果为True,则会默认将变量添加到图形集合GraphKeys.TRAINABLE_VARIABLES中,此集和用于优化器优化的默认变量列表 。

  • collections:graph集合列表的关键字。新变量将添加到这个集合中。默认为[GraphKeys.GLOBAL_VARIABLES]。

  • validate_shape:如果为True,则默认为initial_value的形状必须已知。如果为False,则允许使用未知形状的值初始化变量。

  • name:变量名,可选,默认为“Variable”并自动获取

  • dtype:数据类型

tf.get_variable(name,shape=None, dtype=None, initializer=None, regularizer=None, trainable=None, collections=None, caching_device=None, partitioner=None, validate_shape=True, use_resource=None, custom_getter=None, constraint=None)

这也是获取或创建一个变量的形式,与tf.Variable参数区别最主要在于如果新建变量名称原来存在,就会显示错误,不会像Variable一样,自动处理相同的变量名称,另外tf.get_variable还可以读取以前有的变量,也可以创建新的变量,而Variable只是直接创建,不管之前有没有存在,以下介绍了其常用参数。

  • name:新变量或现有变量的name

  • shape:新变量或现有变量的shape

  • dtype:新变量或现有变量的类型(默认为DT_FLOAT)。

  • initializer:变量的初始化方式

  • regularizer:函数(tensor-->tensor),将函数应用于新创建的变量,结果将添加到集合tf.GraphKeys.REGULARIZATION_LOSSES中,并可用于正则化。

  • trainable:如果为True,还将变量添加到图形集合GraphKeys.TRAINABLE_VARIABLES,此集和用于优化器优化的默认变量列表 。

  • collections:要将变量添加到的图表集合列表。默认为[GraphKeys.GLOBAL_VARIABLES](参见tf.Variable) 。

  • validate_shape:如果为True,则默认为initial_value的形状必须已知。如果为False,则允许使用未知形状的值初始化变量。

  • use_resource:如果为False,则创建常规变量。如果为true,则使用定义良好的语义创建实验性ResourceVariable。默认为False(以后版本中将更改为True)。在Eager模式下,此参数始终强制为True。

v = tf.get_variable("v", shape=(), initializer=tf.zeros_initializer())
u = tf.Variable([1, 2], trainable=True, validate_shape=True, name='u')
w = v + 1
w1 = u + 2

print(v, type(v))
print(u, type(u))
print(w, type(w))
print(w1, type(w1))
#结果显示
<tf.Variable 'v:0' shape=() dtype=float32_ref> <class 'tensorflow.python.ops.variables.Variable'>
<tf.Variable 'u:0' shape=(2,) dtype=int32_ref> <class 'tensorflow.python.ops.variables.Variable'>
Tensor("add:0", shape=(), dtype=float32) <class 'tensorflow.python.framework.ops.Tensor'>
Tensor("add_1:0", shape=(2,), dtype=int32) <class 'tensorflow.python.framework.ops.Tensor'>

tf.global_variables_initializer(),一般只用于统一初始化,因为其不会指定变量的初始化顺序,当一个变量的初始值取决于另一个变量的值时,使用这种方法可能会出现错误,所以我们要在命名时就进行初始化。

#形如:init = tf.global_variables_initializer()

使用assign与assign_add方法对tf.Variable进行值的变换

import tensorflow as tf

a = tf.Variable(initial_value=0, name='counter') # 创建一个变量,初始化为标量0
b = tf.constant(1)
c = tf.get_variable('c', shape=(), initializer=tf.zeros_initializer())

assignment = c.assign_add(1) # 利用assign_add实现变量c初始值+1
new_value = tf.add(a, b) # 利用add实现a与b的相加
update = tf.assign(a, new_value) # 将新的值new_value赋值给a,只是描绘图,并不会执行

#启动图前,变量必须经过初始化(init)
init = tf.global_variables_initializer() # 统一初始化

#启动图,运行op,这部分在运行计算图中会再详细介绍
with tf.Session() as sess:
    sess.run(init) # 运行‘init’
    print(sess.run(a)) # 打印‘a’的值
    print(sess.run(assignment)) # 打印‘assignment’的值
    #运行op,更新a,并打印a
    for _ in range(2): # 补充一个小知识,range是一种与list与tuple同等类型的数据类型
        sess.run(update)
        print(sess.run(update))
#结果显示
0
1.0
2
4
2.对列表中变量的相关操作
  • tf.add_to_collection:把变量放入一个集合,把很多变量变成一个列表

  • tf.get_collection:从一个列表中取出全部变量,是一个列表

  • tf.add_n:把一个列表的东西都依次加起来

import tensorflow as tf

v1 = tf.get_variable(name='v1', shape=[1], initializer=tf.constant_initializer(2))
tf.add_to_collection('loss', v1) # 将v1放入loss列表中
v2 = tf.get_variable(name='v2', shape=[1], initializer=tf.constant_initializer(1))
tf.add_to_collection('loss', v2)

init = tf.global_variables_initializer()

with tf.Session() as sess:
    sess.run(init)
    print(tf.get_collection('loss')) # 将上面加进去的v1与v2从loss列表取出并打印
    print(sess.run(tf.get_collection('loss')))
    print(sess.run(tf.add_n(tf.get_collection('loss')))) # 将v1与v2取出相加再打印最后运行的结果
#结果显示
[<tf.Variable 'v1:0' shape=(1,) dtype=float32_ref>,
 <tf.Variable 'v2:0' shape=(1,) dtype=float32_ref>]
[array([2.], dtype=float32),
 array([1.], dtype=float32)]
[3.]
3.变量命名空间
  • tf.name_scope() # 修改变量的命名空间

tf.name_scope主要结合tf.Variable()来使用,它的主要目的是为了方便管理参数命名,以下为它的一个简单示例:

import tensorflow as tf

with tf.name_scope('conv1'):
    weights1 = tf.Variable([1.0, 2.0], name='weights')
    bias1 = tf.Variable([0, 3], name='bias')

# 下面是在另一个命名空间来定义变量
with tf.name_scope('conv2'):
    weights2 = tf.Variable([4.0, 2.0], name='weights')
    bias2 = tf.Variable([0, 44], name='bias')

print(weights1.name)
print(weights2.name)

#如果重复执行,则会生成新的命名空间
with tf.name_scope('conv1'):
    weights1 = tf.Variable([1.0, 2.0], name='weights')
    bias1 = tf.Variable([0, 3], name='bias')

# 下面是在另一个命名空间来定义变量
with tf.name_scope('conv2'):
    weights2 = tf.Variable([4.0, 2.0], name='weights')
    bias2 = tf.Variable([0, 44], name='bias')

print(weights1.name)
print(weights2.name)
#结果显示
conv1/weights:0
conv2/weights:0
conv1_1/weights:0
conv2_1/weights:0
  • tf.variable_scope('scope_name')

这种方法主要是与tf.get_variable()来使用,实现变量共享,以下为它的一个简单示例:

with tf.variable_scope('v_scope'):
    Weights1 = tf.get_variable('Weights', shape=[2, 3])
    bias1 = tf.get_variable('bias', shape=[3, ])
# print(Weights1, type(Weights1))
# print(bias1, type(bias1))
# 下面共享上面已经定义好的变量
# 在下面的scope中的变量必须经过get.variable()定义过了,才能设置reuse=True,否则会报错
with tf.variable_scope('v_scope', reuse=True):
    Weights2 = tf.get_variable('Weights')

print(Weights1.name)
print(Weights2.name)
#结果显示
v_scope/Weights:0
v_scope/Weights:0

共享变量有两种方法:

#方法一:
with tf.variable_scope('name') as scope:
    我们定义的变量,最好使用tf.get_variable生成
#方法二:
with tf.variable_scope('name', reuse=True):
    我们定义的变量,只有tf.get_variable定义变量,才能是reuse(重复使用)为真的必要条件

总结:这两种都是变量空间操作,但是name_scope一般是与Variable一起用,variable_scope一般与tf.get_variable一起使用。

1.2 会话/运行计算图(Session)

要评估张量,就需要实例化一个tf.Session()对象,在会话/运行计算图中,调用run方法来运行图节点以及查看张量。

  • sess.run(张量)与Tensor.eval(),即张量.eval(),都是返回与张量内容相同的numpy数组。

  • Tensor.eval与sess.run方法能运行的前提都是tf.Session处于活跃状态。

下面是两种方法的简单示例(接的是一开始的总体简单示例):

with tf.Session() as sess:
    print(a.eval())
    print(sess.run(a))
#结果显示
2.0
2.0

1.2.1会话/运行计算图的两种方式

  • tf.Session(graph=None, config=None) #如果括号内什么都不写就默认为None。

也可以graph=new_graph  # new_graph是自定义创建的新的图的对象实例

config:清晰地显示操作运行在哪些设备上 如果想要知道设备信息,把config设置成config = tf.ConfigProto(allow_soft_placement=True, log_device_placement=True)

  • tf.InteractiveSession() #用于在交互模式中打开会话,ipython,shell,jupyter Notebook。

最后,会话/运行计算图(Session)在使用完后需要释放资源,除了使用sess.close()外,一般使用“with代码块”来自动关闭。

1.2.2会话/运行计算图的run

run(fetches, feed_dict=None, options=None, run_metadata=None)

其中的几个参数介绍:

  • fetches:单一的operation(操作或者叫节点),或者元组operation、列表operation

  • feed_dict:参数允许调用者覆盖图中张量的值,运行时赋值。与tf.placeholder(),即我们所说的feed操作配合使用,则会检测值的形状是否与占位符匹配。

以下为run的简单示例:

import tensorflow as tf

a = tf.constant(2.)
b = tf.constant(3.)
c = a + b

sess = tf.Session() # 等价与with tf.Session() as sess:
s = sess.run(c)
print(s)
print(c.eval(session=sess)) # 如果上面用的是with则Session是活跃的不用在()中再声明
#结果显示
5.0
5.0

以下是feed_dict的相关操作(接上面的代码):

input1 = tf.constant(2.0)
input2 = tf.constant(3.0)
input3 = tf.constant(4.0)
input4 = tf.add(input2, input3)
input5 = tf.multiply(input1, input4)

with tf.Session() as sess:
    result = sess.run([input5, input4])#通过run取回多个张量
    print(result, type(result))
#结果显示
[14.0, 7.0] <class 'list'>

结合tf.placeholder()进行相关操作:

import tensorflow as tf

a = tf.placeholder(tf.float32) # 就是用placeholder创建一个占位符,最后必须通过feed_dict进行参数替换
b = tf.placeholder(tf.float32)
c = tf.add(a, b)

with tf.Session() as sess:
    re1 = sess.run(c, feed_dict={a: 1, b: 2.5})
    print(re1)
    print(sess.run(c, feed_dict={a: [1., 2.], b: [2., 2.]}))
#结果显示
3.5
[3. 4.]

2.TensorBoard:可视化学习

TensorBoard是tensorflow的可视化工具,实现程序可视化的过程。

2.1数据序列化-event文件

tf.summary.FileWriter('path', garph=sess.graph) #在会话/运行计算图中写入事件文件,然后在path路径创建一个even文件。

  • path 事件文件的写入地址

  • graph 选择描绘的计算图,sess.graph或tf.get_default_graph()都是默认图,tf.graph()是新图

以下是一个简单示例:

import tensorflow as tf

a = tf.constant(20, name='ax')
b = tf.constant(30, name='bx')
c = a + b

with tf.Session() as sess:
    c = sess.run(c)
    writer = tf.summary.FileWriter('./', sess.graph) # 写入事件文件
    writer.close() # 写完之后的关闭操作,必须要有
#这只是写入事件的代码,并没有打印什么结果

2.2启动TensorBoard

  1. 将项目中的.py文件(这个py文件是拥有写入事件语句的)运行,生成event文件,如图:

  1. 在cmd中或者Git Bash中运行 tensorboard --logdir="path" (注意,一定要是在event存在的文件夹中打开cmd,在命令中path一定要用双引号,单引号会出错),如图:

  1. 然后在谷歌浏览器中 localhost:6006 就可以看到图了 ,如图:

下面是一个py文件显示tensorboard示例:

# 实现一个线性回归
import tensorflow as tf
import os
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2"

# 准备数据
X = tf.random_normal(shape=[100, 1])
y_true = tf.matmul(X, [[0.8]]) + 0.7

# 构建线性模型的tensor变量Weight, bias
Weight = 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, Weight) + bias

# 构建损失方程,优化器及训练模型操作train
loss = tf.reduce_mean(tf.square(y_predict - y_true))
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.5)
train = optimizer.minimize(loss)

init = tf.global_variables_initializer()     # 构建变量初始化操作init

with tf.Session() as sess:
   sess.run(init)
   writer = tf.summary.FileWriter("D:/project-minyuan/study/logs", sess.graph)

   for step in range(1000):
       sess.run(train)
       if step % 20 == 0:     # 每20次打印一次
           print(step, sess.run(Weight), sess.run(bias))

   writer.close()

 

2.3 增加变量显示功能

目的:在TensorBoard中观察模型参数、损失值等变量的变化

  1. 收集变量用于tensorboard可视化

  • tf.summary.scalar(name="", tensor) # 收集标量,例:loss、accuary、learing_rate

  • tf.summary.histogram(name="", tensor) # 收集高维度的变量,例:训练过程中的变量, 以直方图的形式显示变量分布情况 。

  • tf.summaty.image(name="", tensor) # 收集图片张量[image_num, height, width, channels],展示训练过程中记录的图像

  • tf.summaty.audio(name="", tensor) # 收集音频张量[audio_num, frames, channels],播放训练过程中记录的音频

数据的tensorboard可视化展现 :网址

import tensorflow as tf
import os
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2"

# 准备数据
X = tf.random_normal(shape=[100, 1])
y_true = tf.matmul(X, [[0.8]]) + 0.7

# 构建线性模型的tensor变量Weight, bias
Weight = 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, Weight) + bias

# 构建损失方程,优化器及训练模型操作train
loss = tf.reduce_mean(tf.square(y_predict - y_true))
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01)
train = optimizer.minimize(loss)

# 收集变量
tf.summary.scalar("error", loss)            # 收集标量
tf.summary.histogram("Weight", Weight)      # 收集高维变量
tf.summary.histogram("bias", bias)
merged = tf.summary.merge_all()             # 合并变量

init = tf.global_variables_initializer()        # 变量初始化操作

with tf.Session() as sess:
   sess.run(init)
   event_file = tf.summary.FileWriter("D:/project-minyuan/study/logs", sess.graph)     # 创建事件文件

   for step in range(100):
       sess.run(train)
       if step % 20 == 0:     # 每20次打印一次
           print(step, sess.run(Weight), sess.run(bias))

       summary = sess.run(merged)                  # 运行合并变量的操作
       event_file.add_summary(summary, step)       # 将每次迭代后的变量写入事件文件
   event_file.close()

其中一些参数的解释:

  • merged = tf.summary.merge_all() # 将所有的summary保存到磁盘,以便tensorboard可视化

  • event_file = tf.summary.FileWriter("./", sess.graph) # 在会话中创建事件文件保存图

  • summary = sess.run(merged) # 在会话中运行合并操作

  • event_file.add_summary(summary, step) # 将每次迭代更新后的summary写入事件文件

  • event_file.close() # 最后记得关闭事件文件

结果如图:

3.模型的保存与加载

3.1 模型保存

  1. saver = tf.train.Saver(var_list=None, max_to_keep=5) # 保存和加载模型

其中相关参数:

  • var_list:指定要保存的变量,可以作为一个dict或列表传递,如果为None,就是保存所有变量。

  • max_to_keep:保留检查点文件的数量,创建新文件时会删除旧的文件 。

  1. saver.save(sess, save_path="./liner.ckpt", global_step=step) # 保存模型

  • sess:会话名字 。

  • save_path:设定权重参数保存的路径和文件名。

  • global_step=step:将训练的次数作为后缀加入到模型名字中。

以下是一个简单训练模型并保存的示例:

import tensorflow as tf
import os
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2"

v1 = tf.get_variable("v1", shape=[3], initializer=tf.zeros_initializer)
v2 = tf.get_variable("v2", shape=(5), initializer=tf.zeros_initializer)
# inc_v1 = v1.assign(v1+1)       # v1变量+1
a = tf.constant(1.0)
b = tf.add(v1, a)
inc_v1 = tf.assign(v1, b)
dec_v2 = v2.assign(v2-1)        # v2变量-1

init = tf.global_variables_initializer()
saver = tf.train.Saver()        # 创建Saver对象

with tf.Session() as sess:
   sess.run(init)
   inc_v1.op.run()
   dec_v2.op.run()
   for epoch in range(300):
       if epoch % 10 ==0:
           # 在会话中保存模型
           save_path = saver.save(sess, save_path="./model/model.ckpt", global_step=epoch)
   print("Model saved in path: %s" % save_path)

运行完代码在model文件夹中生成下列几个文件:

其中几个文件名的意思如下:

  • checkpoint      记录最新的模型

  • ().data/ ().index   存储训练好的参数

  • ().meta        存储网络结构

3.2 模型加载

  1. saver.restore(sess, "./liner.ckpt") # 加载模型

  2. checkpoint = tf.train.latest_checkpoint("./model/") # 获取最新的模型

import tensorflow as tf
import os
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2"

v1 = tf.get_variable("v1", shape=[3])
v2 = tf.get_variable("v2", shape=[5])
tf.add_to_collection("variable", v1)
tf.add_to_collection("variable", v2)


def load_model(sess, ckpt):
   # ckpt是模型路径
   if os.path.isdir(ckpt):
       # 获取最新的模型
       checkpoint = tf.train.latest_checkpoint(ckpt)
   else:
       checkpoint = ckpt
   print(checkpoint) # ./model/model.ckpt-290
   meta = checkpoint + '.meta'  # ./model/model.ckpt-290.meta
   print(meta)

   saver = tf.train.import_meta_graph(meta)  # 加载graph图结构
   saver.restore(sess, checkpoint)  # 加载模型参数


with tf.Session() as sess:
   sess.run(tf.global_variables_initializer())
   model_dir = "./model/"
   load_model(sess, model_dir)
   # 从变量集和名为"variable"的集和中取出变量
   a, b = tf.get_collection('variable')
   print(a, b)

   print("模型恢复....")
   print("v1 : %s" % v1.eval())
   print("v2 : %s" % v2.eval())
#结果显示
./model/model.ckpt-290
./model/model.ckpt-290.meta
<tf.Variable 'v1:0' shape=(3,) dtype=float32_ref> <tf.Variable 'v2:0' shape=(5,) dtype=float32_ref>
模型恢复....
v1 : [-0.30017233  0.87121487 -0.7292707 ]
v2 : [-0.301401   -0.7233736   0.5275371   0.37816596 -0.61047554]

3.3 通过checkpoint找到模型文件名

tf.train.get_checkpoint_state(checkpoint_dir,latest_filename=None)

其中参数解释:

  • checkpoint_dir:checkpoint文件的路径

  • latest_filename:指定checkpoint的名字,返回的是CheckpointState proto对象,CheckpointState proto对象有两个可用属性。

命令行参数的使用

tensorflow支持程序从命令行接受参数,即使用tf.app.flag,tf.app.flag可以定义各种参数类型

  • 整形参数  tf.app.flag.DEFINE_integer(flag_name, default, docstring)

  • 字符串参数  tf.app.flag.DEFINE_string(flag_name, default, docstring)

  • 布尔值参数  tf.app.flag.DEFINE_boolean(flag_name, default, docstring)

  • 浮点值参数  tf.app.flag.DEFINE_float(flag_name, default, docstring)

4.一些小技巧

  1. tf.app.run()可以自动运行脚本中的main(argv)函数,如果脚本没有main(argv)函数,会报错。

  2. 运行tensorflow的时候,会出现红色警告I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2

如果不想看到这个,在脚本开始的时候,加

import os
os.environ["TF_CPP_MIN_LOG_LEVEL"]= "2"
posted @ 2020-05-28 19:47  代码界的小菜鸟  阅读(1468)  评论(0编辑  收藏  举报