【TF笔记】之TensorFlow的基本用法

一 、简介:

  • TensorFlow™ 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库。TensorFlow 最初由Google大脑小组(隶属于Google机器智能研究机构)的研究员和工程师们开发出来,用于机器学习和深度神经网络方面的研究,但这个系统的通用性使其也可广泛用于其他计算领域。它是谷歌基于DistBelief进行研发的第二代人工智能学习系统。2015年11月9日,Google发布人工智能系统TensorFlow并宣布开源。
  • 其命名来源于本身的原理,Tensor(张量)意味着N维数组,Flow(流)意味着基于数据流图的计算。Tensorflow运行过程就是张量从图的一端流动到另一端的计算过程。张量从图中流过的直观图像是其取名为“TensorFlow”的原因。

  二、TensorFlow的基本用法

       TensorFlow可以认为是一种编程工具,使用TensorFlow来实现具体的业务需求,所以我们可以认为TensorFlow就是一个“工具箱”,然后我们使用TensorFlow这个“工具箱”中的各种“工具”(方法/API)来实现各种功能,比如使用TensorFlow实现基本的数值计算、机器学习、深度学习等。

        首先得熟悉以下五个概念:

  • 图(graph):使用图(graph)来表示计算任务,描述计算过程;
  • 会话(session):在会话(session)的上下文中执行图,会话会将图的OP分发到CPU/GPU上进行执行;
  • 张量(tensor):使用张量(tensor)表示数据,每一个Tensor是个类型化的多维数组;
  • 变量(Variable)来:通过变量(Variable)来维护状态,运行 过程可以被改变;
  • 操作(Operation/op):使用feed和fetch可以为任意的操作(Operation/op)赋值或者从其中获取数据

2.1 TensorFlow之图

  • TensorFlow编程的重点是根据业务需求,使用TensorFlow的API将业务转换为执行图(有向无环图);图中的节点是Tensor,节点之间的连线是节点之间的操作,连线前的节点可以认为是操作的输入,连线后的节点可以认为操作的输出;根据节点的特性(是否有输入输出),可以将节点分为源节点、中间节点和最终的结果节点。
  • 图构建的第一步就是创建源op(source op); 源op不需要任何的输入。op构造器的返回值代表被构造出的op的输出,这些返回值可以传递给其它op构造器作为输入或者直接获取结果。
  • TensorFlow库中有一个默认图(default graph),op构造器可以直接为其添加节点,一般情况下,使用默认的Graph即可完成程序代码的实现。不过TensorFlow也支持通过Graph类管理多个图。

在默认图上定义两个constant节点(op),一个matmul节点(op):

import tensorflow as tf

# 1、定义常量矩阵a、b
a = tf.constant([[1,2],[3,4]], dtype=tf.int32, name='a')
print(a)
b = tf.constant([5, 6, 7, 8], dtype=tf.int32, shape=[2, 2])
print(b)

# 2、以a、b为输入,进行矩阵乘法操作
c = tf.matmul(a,b)
print(c)

输出:  

  

注意:(一般做深度学习模型构建时最好在一张图中构建计算过程,不要使用多个图)

      TensorFlow编程时可以不使用默认图(Graph),使用多个图来进行编程;但是注意:操作必须属于同一个图,不同图中的节点不能相连。

import tensorflow as tf

# 定义一个常量
a = tf.constant([[1,2],[3,4]], dtype=tf.int32, name='a')
print(a)

## 使用新的构建的图
graph = tf.Graph()
with graph.as_default():
    # 此时在这个代码块中,使用的就是新的定义的图graph(相当于把默认图换成了graph)
    d = tf.constant(5.0, name='d')
    print("变量d是否在新图graph中:{}".format(d.graph is graph))
    
# 另一种写法
with tf.Graph().as_default() as g2:
    e = tf.constant(6.0, name='e')
    print("变量e是否在新图g2中:{}".format(e.graph is g2))

print("变量a是否在默认图中:{}".format(a.graph is g2))

输出:

2.2 TensorFlow之会话

  • 当执行图构建完成后,才能给启动图,进入到执行阶段;启动图的第一步就是创建一个Session对象,如果无任何参数的情况下,会话构造器将启动默认图。
import tensorflow as tf

# 1、定义常量矩阵a、b
a = tf.constant([[1,2],[3,4]], dtype=tf.int32, name='a')
print(a)
b = tf.constant([5, 6, 7, 8], dtype=tf.int32, shape=[2, 2], name='b')
print(b)

# 2、以a、b为输入,进行矩阵乘法操作
c = tf.matmul(a, b, name='matmul')
print(c)

# 3、以a、b为输入,进行矩阵加法操作
g = tf.add(a, b, name='add')
print(g, type(g))

# 4、
h = tf.subtract(b, a, name='b-a')
l = tf.matmul(h, c)
r = tf.add(g, l)

# 会话构建&启动(默认情况下(不给定Session的graph参数的情况下),创建的Session属于默认的图)
sess = tf.Session()
print(sess)

#  调用sess的run方法来执行矩阵的乘法,得到c的结果值(所以将c作为参数传递进去)
#  不需要考虑图中间的运算,在运行的时候只需要关注最终结果对应的对象以及所需要的输入数据值
#  只需要传递进去所需要得到的结果对象,会自动的根据图中的依赖关系触发所有相关的OP操作的执行
#  如果op之间没有依赖关系,tensorflow底层会并行的执行op(有资源) --> 自动进行
#  如果传递的fetches是一个列表,那么返回值是一个list集合
#  fetches:表示获取那个op操作的结果值
result = sess.run(fetches=[r, c])
print("type:{}, value:\n{}".format(type(result), result))

# 会话关闭,当一个会话关闭后,不能再使用了
sess.close()


## 推荐使用的会话方式:
# 使用with语句块,会在with语句块执行完成后,自动的关闭session
with tf.Session() as sess2:
    print(sess2)
    # 获取张量c的结果: 通过Session的run方法获取
    print("sess2 run:{}".format(sess2.run(c)))
    # 获取张量r的结果:通过张量对象的eval方法获取,和Session的run方法一致
    print("c eval:{}".format(r.eval()))

输出:

【TF笔记】之TensorFlow的基本用法_第1张图片

以上程序的所构建的图:

【TF笔记】之TensorFlow的基本用法_第2张图片

  • tf.Session在构建会话的时候,如果不给定任何参数,那么构建出来Session对应的内部的Graph其实就是默认Graph,不过我们可以通过参数给定具体对应的是那一个Graph以及当前Session对应的配合参数。Session的构造主要有三个参数,作用如下:
  • target:给定连接的url,只有当分布式运行的时候需要给定(后面分布式运行讲);
  • graph:给定当前Session对应的图,默认为TensorFlow中的默认图;
  • config:给定当前Session的相关参数,参数详见https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/protobuf/config.proto中的[ConfigProto]

通过Session的config参数可以对TensorFlow的应用的执行进行一些优化调整,主要涉及到的参数如下:

【TF笔记】之TensorFlow的基本用法_第3张图片

  • 在TensorFlow中,除了可以使用Session表示这个会话外,还可以通过InteractiveSession来表示会话,InteractiveSession的意思是:交互式会话,使用交互式会话可以降低代码的复杂度,使用Tensor.eval()或者Operation.run()来代替Session.run()方法,这样可以避免一个变量来维持会话;备注:Session也可以使用Tensor.eval()和Operation.run()获取数据/执行操作(只要明确当前会话)。
# # 交互式会话构建
 sess3 = tf.InteractiveSession()
 print(r.eval())

2.3  TensorFlow之张量

TensorFlow使用张量(Tensor)数据结构来代表所有数据,计算图中,操作间传递的数据都是Tensor。Tensor可以看作是一个n维的数组或者列表,一个Tensor主要由一个静态数据类型和动态类型的维数(Rank、Shape)组成。Tensor可以在图中的节点之间流通。

【TF笔记】之TensorFlow的基本用法_第4张图片

2.4 TensorFlow之变量

  • 变量(Variables)是维护图执行过程中的状态信息。在训练模型过程中,可以通过变量来存储和更新参数。变量包含张量(Tensor)存放于内存的缓存区。建模的时候变量必须被明确的初始化,模型训练后变量必须被存储到磁盘。这些变量的值可以在之后的模型训练和分析中被加载。
  • 在构建变量的时候,必须将一个张量或者可以转化为张量的Python对象作为初始值传入构造函数Variable中。
  • 特别注意:变量的全局初始化(tf.initialize_all_variables())是并行执行的,如果存在变量之间的依赖关系的时候,在进行初始化的时候要特别注意。(1.4版本之后该问题就不存在了)
 import tensorflow as tf

# 1. 定义变量,常量
 w1 = tf.Variable(tf.random_normal(shape=[10], stddev=0.5, seed=28, dtype=tf.float32), name='w1')
 a = tf.constant(value=2.0, dtype=tf.float32)
 w2 = tf.Variable(w1.initialized_value() * a, name='w2')

 # 2. 进行初始化操作(推荐:使用全局所有变量初始化API)
 # 相当于在图中加入一个初始化全局变量的操作
 init_op = tf.global_variables_initializer()
 print(type(init_op))

 # 3. 图的运行
with tf.Session(config=tf.ConfigProto(log_device_placement=True) as sess:
     # 运行init op进行变量初始化,一定要放到所有运行操作之前
     sess.run(init_op)
     # init_op.run() # 这行代码也是初始化运行操作,但是要求明确给定当前代码块对应的默认session(tf.get_default_session())是哪个,底层使用默认session来运行
     # 获取操作的结果
     print("result:{}".format(sess.run(w1)))
     print("result:{}".format(w2.eval()))

输出:

2.5 TensorFlow之fetch/feed

2.5.1 TensorFlow Fetch

  • 为了取回操作的输出内容,可以在使用Session对象的run方法调用执行图的时候,传入一些tensor,通过run方法就可以获取这些tensor对应的结果值。
  • 如果需要获取多个tensor的值,那么尽量一次运行就获取所有的结果值,而不是采用逐个获取的方式。
import tensorflow as tf

# 1. 定义变量,常量
w1 = tf.Variable(tf.random_normal(shape=[10], stddev=0.5, seed=28, dtype=tf.float32), name='w1')
a = tf.constant(value=2.0, dtype=tf.float32)
w2 = tf.Variable(w1.initialized_value() * a, name='w2')

# 2. 进行初始化操作(推荐:使用全局所有变量初始化API)
# 相当于在图中加入一个初始化全局变量的操作
init_op = tf.global_variables_initializer()
print(type(init_op))

# 启动图
with tf.Session() as sess:
    # 变量初始化
    sess.run(init_op)
    #
    results = sess.run([w1, w2])
    print("w1:{}\nw2:{}".format(results[0], results[1]))

输出:

2.5.1 TensorFlow Feed

  • Tensorflow还提供了填充机制(feed),可以在构建图时使用placeholder类型的API临时替代任意操作的张量(占位符),在调用Session对象的run()方法去执行图时,使用填充数据作为调用的参数,调用结束后,填充数据就消失了。
  • feed使用一个tensor值临时替换一个操作的输出结果,在获取数据的时候必须给定对应的feed数据作为参数。feed只有在调用它的方法内有效,方法结束,feed就消失了。
  • feed可以使用placeholder类型的API创建占位符,常见API:tf.placeholder、tf.placeholder_with_default
import tensorflow as tf

# 构建一个矩阵的乘法,但是矩阵在运行的时候给定
m1 = tf.placeholder(dtype=tf.float32, shape=[2, 3], name='placeholder_1')
m2 = tf.placeholder(dtype=tf.float32, shape=[3, 2], name='placeholder_2')
m3 = tf.matmul(m1, m2)

with tf.Session(config=tf.ConfigProto(log_device_placement=True, allow_soft_placement=True)) as sess:
    print("result:\n{}".format(
        sess.run(fetches=m3, feed_dict={m1: [[1, 2, 3], [4, 5, 6]], m2: [[9, 8], [7, 6], [5, 4]]})))
    print("result:\n{}".format(m3.eval(feed_dict={m1: [[1, 2, 3], [4, 5, 6]], m2: [[9, 8], [7, 6], [5, 4]]})))

输出:

【TF笔记】之TensorFlow的基本用法_第5张图片

你可能感兴趣的:(TensorFlow,TensorFlow,TensorFlow基本用法)