【TensorFlow】基本概念:张量、常量、变量、占位符、计算图
Tensorflow是一个Google开发,基于数据流编程(dataflow programming)的符号数学系统,被广泛应用于各类机器学习(machine learning)算法的编程实现。
TensorFlow简介
顾名思义,TensorFlow就是以张量(Tensor)在计算图(Graph)上流动(Flow)的方式的实现和执行机器学习算法的框架。它具有以下特点:
灵活性。TensorFlow 不是一个严格的“神经网络”库(实际上TF的官方定位是 基于数据流图的科学计算库,而不仅仅是机器学习库)。只要可以将计算表示成数据流图,就可以使用TensorFlow,比如科学计算中的偏微分求解等。
可移植性。同一份代码几乎不经过修改既可以部署到有任意数量CPU、GPU或TPU(Tensor Processing Unit,Google专门为机器学习开发的处理器)的PC、服务器或移动设备上。
自动求微分。同Theano一样,TensorFlow也支持自动求微分,用户不需要再通过反向传播求解梯度。
多语言支持。TensorFlow官方支持Python、C++、Go和Java接口,用户可以在硬件配置较好的机器中用Python进行实验,在资源较紧张或需要低延迟的环境中用C++进行部署。
性能。虽然TensorFlow最开始发布时仅支持单机,在性能评测上并不出色,但是凭借Google强大的开发实力,TensorFlow性能已经追上了其他框架。
TensorFlow架构
TF的系统构架分为两部分:
前端:提供编程模型,负责构造计算图,提供Python,C++,Java,Go等多种语言支持。
后端:提供运行时环境,负责执行计算图,采用C++实现。
用户在搭建算法时,可以根据个人喜好和实际需求采用合适的前端语言来构建计算图。图搭建完成后,以Session为桥梁连接TF的后端,启动并执行图的计算过程。TF的后端根据当前硬件环境调用Operation的Kernal(Operation在某种硬件设备的特定实现)完成具体的计算。
TensorFlow编程模式
符号式编程 vs 命令式编程
和我们一般常用的命令式(Imperative)编程模式不同,TF采用的是符号式(Symbolic)编程。我们先认识一下两种编程模式:
命令式编程
是很常见的编程模式,大多数Python或C++程序都采用命令式编程。命令式编程 明确输入变量,根据程序逻辑逐步运算。下面是一段命令式编程的Python代码:
import numpy as np
a = np.ones(10)
b = np.ones(10) * 2
c = b * a
d = c + 1
执行完第一步a = np.ones(10)后,程序得到了输入变量a,第二句后得到了b,当执行c = b * a时,程序通过乘法计算而得到了c。
符号式编程
则 将计算过程抽象为计算图**,**即将所有输入节点、运算节点和输出节点(计算图的三个主体)均符号化处理。将上述命令式编程代码转换为符号式编程:
A = Variable('A')
B = Variable('B')
C = B * A
D = C + Constant(1)
# compiles the function
f = compile(D)
d = f(A=np.ones(10), B=np.ones(10)*2)
当前四步执行后,程序并没有A、B、C、D的值,仅仅是构建了由这四个符号构成的计算图(计算关系、计算流程),如下图所示:
大多数符号式编程的程序中都或显式或隐式地包含编译的步骤,将前面定义的计算图打包成可以调用的函数,而实际的计算则发生在编译后。
Theano和TensorFlow属于典型的符号式编程模式,而Torch则是命令式编程模式。在灵活性上,命令式编程模式更优,而在内存和计算上,符号式编程效率更高。
TensorFlow基本理念
使用TensorFlow,我们必须了解TensorFlow:
使用计算图(Graph)表示计算流程,计算图中的 节点(Nodes) 表示数学操作(Operation,op),节点的连线(edges) 表示在操作间传递流动的数据 (多维数组),即张量(tensor)。
在会话(Session)中执行图
使用常量(constant),变量(variable),占位符(placeholder)三种源op向计算图中引入数据
使用 Fetch 从操作中获取数据
1、张量(Tensor)
TF使用tensor表示所有数据,从0维的数值、一维的矢量、二维的矩阵到n维数组。TF中的tensor相当于Numpy中的ndarray。
Tensorflow 在设计之时参考了很多 numpy 的设计理念,故你可以感受到两者在使用上有很多相似之处。不过相比于Numpy,TensorFlow提供了创建张量函数的方法(这是什么?),以及导数的自动计算。
2、数学操作(Operation)
计算图中的节点(Node)表示数学操作(Operation,简称OP)。类似于门单元,每个OP接受0到多个Tensor
输入,执行计算,输出0到多个Tensor
。
常见的operation
① 算术函数
② 线性代数
3、源op
作为一种特殊的 op ,源op(source op),顾名思义,是数据的源头,作用是为计算图引入数据。具体地,源op不需要接受op输入,自己提供输出传递给其它op做运算。
TensorFlow 支持以下三种类型的源op:constant(常量):即 值不能改变 的量。
variable(变量):当一个量在会话中的 值需要更新 时,使用变量来表示。在机器学习算法中,模型参数在训练期间需要不断更新,故我们将其声明为变量类型。
placeholder(占位符):用于将外部数据导入计算图中。在机器学习算法中,通常用于提供样本数据。
1)常量(Constant)
t_1 = tf.constant(4) # 定义一个标量常量
t_2 = tf.constant([4,3,8]) # 定义一个向量常量
tf.zeros([M,N], tf.dtype = tf.int32) # 创建一个形状为 [M,N] 的零元素矩阵,dtype可以是 int32、float32等
tf.ones([M,N], tf.dtype) # 创建一个形状为 [M,N]、元素均为 1 的矩阵
tf.linspace(start, stop, num) # 创建一个从初值(start)到终值(stop),元素数目为num的等差序列
tf.range(start,limit,delta) # 创建一个从初值(start)到终值(limit),增量为 delta(默认值 = 1)的等差数列
创建具有不同分布的随机张量
# 均值为1(默认值=0.0)和标准差为2(默认值=1.0)、形状为 [M,N] 的正态分布随机数组
tf.random_normal([3,6],mean=1,stddev=2)
# 均值为1(默认值=0.0)和标准差为2(默认值=1.0)、形状为 [M,N] 的截尾正态分布随机数组
tf.truncated_normal([2,3],mean=2,stddev=4)
# 在种子的 [minval(default=0),maxval] 范围内创建形状为 [M,N] 的给定伽马分布随机数组
tf.random_uniform([3,6],maxval=10)
2)变量(Variable)
在机器学习中,Variable被用来存储和更新参数。
与Constant不同,Variable必须显式地进行初始化。另一方面,变量可以存储在磁盘中。
变量的创建
通过将一个constant作为初始值传入构造函数Variable()来创建变量。初始值张量的shape自动成为变量的shape。
变量的初始化
变量的初始化必须在模型的其它操作运行之前先明确地完成。最简单的方法就是添加一个给所有变量初始化的操作,并在使用模型之前(会话中的第一句)首先运行那个操作。
示例代码:简单计数器
# 创建一个变量, 初始化为标量 0.
state = tf.Variable(0, name="counter")
# 创建一个 op, 其作用是使 state 增加 1
one = tf.constant(1)
new_value = tf.add(state, one) #加法运算
update = tf.assign(state, new_value) #
# 启动图后, 变量必须先经过`初始化` (init) op 初始化,
# 首先必须增加一个`初始化` op 到图中.
init_op = tf.initialize_all_variables()
# 启动图, 运行 op
with tf.Session() as sess:
# 运行 'init' op
sess.run(init_op)
# 打印 'state' 的初始值
print sess.run(state)
# 运行 op, 更新 'state', 并打印 'state'
for _ in range(3):
sess.run(update)
print sess.run(state)
# 输出:
# 0
# 1
# 2
# 3
上述代码中assign()操作同add()一样,都是在构建计算图而没有执行实际的计算。直到run()函数才会真正执行赋值等计算操作。
3)占位符(placeholder)
placeholder用于引入外部数据。
placeholder一般与feed一起使用,在调用run方法时,通过使用feed_dict作为 run() 调用的参数来为占位符赋值。
feed 只在调用它的方法内有效, 方法结束, feed 就会消失。
占位符的创建
X = tf.placeholder(dtype=tf.float32, shape=[144, 10], name='X')
dtype:数据类型,必填,默认为value的数据类型,传入参数为tensorflow下的枚举值(float32,float64…)
shape:数据形状,选填,不填则随传入数据的形状自行变动,可以在多次调用中传入不同形状的数据
name:常量名,选填,默认值不重复,根据创建顺序为(Placeholder,Placeholder_1,Placeholder_2…)
input1 = tf.placeholder(tf.float32)
input2 = tf.placeholder(tf.float32)
output = tf.mul(input1, input2)
with tf.Session() as sess:
print(sess.run([output], feed_dict={input1:[7.], input2:[2.]}))
# output:
# [array([ 14.], dtype=float32)]
4、Fetch 获取数据
为了获得操作的输出值,需要执行会话session的run()函数,并且提供需要提取的op。我们可以同时取回多个op的值:
input1 = tf.constant([3.0])
input2 = tf.constant([2.0])
input3 = tf.constant([5.0])
intermed = tf.add(input2, input3)
mul = tf.mul(input1, intermed)
with tf.Session() as sess:
result = sess.run([mul, intermed])
print(result)
# output:
# [array([ 21.], dtype=float32), array([ 7.], dtype=float32)]
需要获取的多个 op 值,在一次运行中一起获得(而不是逐个去获取)。
5、计算图(graph)
上面说了,TF采用符号式编程模式,一个TF程序通常可以分为两部分:
图的构建。使用图构建计算流程的描述
图的执行。在Session中运行实际计算。Session将计算图的op分配到CPU或GPU等计算单元,并提供相关的计算方法,并且会返回op的结果。
1)图的构建
构建计算图,需要定义所有要使用的数据,同时定义要执行的所有计算。
构建图的第一步,是创建源op(source op),例如常量(constant)。源op的作用是为计算图引入数据,源op 不需要接受op的输入,其输出被传递给其它op做运算。
TensorFlow Python库有一个 默认图 (default graph) ,OP构造器可以为其增加节点。这个默认图对许多程序来说已经足够用了。(不是很懂)
import tensorflow as tf
# Create a Constant op that produces a 1x2 matrix. The op is
# added as a node to the default graph.
#
# The value returned by the constructor represents the output
# of the Constant op.
matrix1 = tf.constant([[3., 3.]])
# Create another Constant that produces a 2x1 matrix.
matrix2 = tf.constant([[2.],[2.]])
# Create a Matmul op that takes 'matrix1' and 'matrix2' as inputs.
# The returned value, 'product', represents the result of the matrix
# multiplication.
product = tf.matmul(matrix1, matrix2)
上面的代码里,我们在默认图中添加了三个节点:两个constant() op和一个matmul() op。要实际执行矩阵乘法,必须在Session中运行该计算图。
2)图的执行
构造阶段完成后, 才能启动图。
要执行计算图,首先需要创建 Session(会话) 对象,在Session里将图启动。如果不提供参数,Session构造器将运行默认图。
# Launch the default graph.
sess = tf.Session()
# To run the matmul op we call the session 'run()' method, passing 'product'
# which represents the output of the matmul op. This indicates to the call
# that we want to get the output of the matmul op back.
#
# All inputs needed by the op are run automatically by the session. They
# typically are run in parallel.
#
# The call 'run(product)' thus causes the execution of three ops in the
# graph: the two constants and matmul.
#
# The output of the op is returned in 'result' as a numpy `ndarray` object.
# 调用 sess 的 'run()' 方法来执行矩阵乘法 op, 传入 'product' 作为该方法的参数.
# 上面提到, 'product' 代表了矩阵乘法 op 的输出, 传入它是向方法表明, 我们希望取回
# 矩阵乘法 op 的输出.
result = sess.run(product)
print(result)
# ==> [[ 12.]]
# Close the Session when we're done.
sess.close()
Session结束后,需要关闭以释放资源。除了显式调用 close() 外, 用户也可以使用with控制语句自动关闭会话。
with tf.Session() as sess:
result = sess.run([product])
print(result)
TensorFlow学习资料整理
原文地址:https://blog.csdn.net/pearl8899/article/details/144333774
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!