四时宝库

程序员的知识宝库

tensorflow基础:详细解释张量,Graph,占位符和变量等

上一篇文章学习数据流图的基础知识时,使用简单的标量值时很好的选择。我们掌握好了数据流图之后,下面不妨熟悉一下张量的概念。

所谓张量,就是n维矩阵的抽象。因此一维的张量等价于一维的矩阵,二维的张量等价于二维矩阵。如果用张量来描述上一篇文章中的数据流图(下图一),可以用下面图二的方式实现。

现在不再使用两个独立的输入节点了,而是换成了一个可接收向量(或者一阶张量)的节点。与标量的版本相比,这个新的数据流图有如下优点:

  • 输入节点只有一个,简化了输入。

  • 节点b和c都只需要依赖一个节点a即可,减少了依赖节点数量。

  • 最重要的一点,这个数据流图可以接收任意长度的向量,灵活性大大增强。

数据流图可以这样实现:

import tensorflow as tf

a=tf.constant([5,3])

b=tf.reduce_prod(a)

c=tf.reduce_sum(a)

d=tf.add(c,d)

这里reduce_prod定义为先接收入参的所有分量,然后分别将他们相乘。reduce_sum定义为将分量相加。

tensorflow中,所有节点之间传递的数据都是tensor对象。具体的tensor对象包括以下几类:

1).python原生类型

tensorflow可接收python数值、布尔值、字符串或者由它们构成的列表。下面给出tensorflow中可用数据类型的完整清单。

利用python类型制定tensor对象既容易又快捷,但有缺陷。例如python的整数只有一个类型,但tensor的却有8位,16位,32位和64位之分。因此更常见的作法是借助numpy数组手工定义tensor对象。

2)numpy数组

tensorflow的数据类型是基于numpy的数据类型的。实际上np.int32==tf.int32的结果为TRUE。任何numpy数组都可以传递给tensorflow op,而且可以用最小代价轻易指定所需要的数据类型。

对于数值型和布尔型,tensorflow和numpy的定义是完全一致的,然而numpy中并没有与tf.string精确对应的类型,我们只能按照numpy的方式,先把字符串转化为字符串数组,然后再通过numpy传递给tensorflow。也就是说,每用到tf.string类型。示例代码如下:

import numpy as np

t_0 = np.array(50,dtype=np.int32) #元素类型为32位的0阶张量

t_1=np.array([b"apple",b"peach",b"grape"]) #元素位字节字符串的一阶张量

另外,请不要尝试用tf.int32去初始化一个numpy数组。

tensorflow代码中经常遇到形状(shape)。这里形状是tensorflow的专用术语。它同时刻画了张量的阶数以及每一维的长度。举例如下:

s0_list = [ ] #指定0阶张量的形状

s0_tuple = ( ) #指定0阶张量的形状

s_1=[3] #指定了一个长度位3的向量的形状,例如[1,2,3]

s_2=(3,2) #指定了一个3*2矩阵的形状。

除了能将张量的每一维指定为固定长度,也可以将none作为某一维的值,使该张量具有可变长度。单独一个none表示一个任意形状的张量。

s1_flex=[None] #表示一阶张量,但长度任意

s_any=None #表示任意形状

s2_flxe = (None,3) #行数任意,列数为3

shape = tf.shape(d) #获取节点d输出的tensor的shape

下面介绍以下tensorflow的graph对象。这里可以学习如何创建更多的数据流图,以及如何让多个流图协同工作。

为了方便起见,当tensorflow库被加载时,它会自动创建一个Graph对象,并将其作为默认的数据流图。因此,如果我们不另外创建新的Graph,所有的tensorflow对象和OP都会放在这个自动创建的Graph对象中。大多数情况下,只使用默认数据流图就可以了。

当我们需要需要定义多个互相不存在依赖关系的模型时,创建多个Graph对象就很有用。此时最佳实践不是使用默认的数据流图,而是给每个数据流图创建一个Graph对象。

方法一:创建新的数据流图,弃用缺省的数据流图

g1=tf.Graph()

g2=tf.Graph()

with g1.as_default():

#定义g1数据流图

with g2.as_default():

#定义g2的数据流图

方法二:找到缺省数据流图的句柄,把它当作新的数据流图来使用。

g1=tf.get_default_graph()

g2=tf.Graph()

with g1.as_default():

#定义g1数据流图

with g2.as_default():

#定义g2的数据流图

tensorflow的Session类负责数据流图的执行,构造方法tf.Session()可接收3个参数:

  • target指定了所要使用的执行引擎,一般默认为空。在分布式设置中需要用到

  • graph指定了将要在Session中加载的Graph对象,默认为None,即使用缺省的Graph. 使用多个数据流图时,需要显示传入你希望运行的Graph对象。

  • config参数允许用户指定配置Session对象所需要的选项,如限制CPU或GPU的使用数目等。

session.run()方法一个参数fetches,以及其他三个可选参数:feed_dict,options和run_metadata。后面两个参数用到的较少,暂不做深入讨论。

fetches参数接收任意的数据流图元素(op,or tensor对象),如果指定为op,输出为None;如果指定为tensor对象,输出将为一个Numpy数组。另外,我们还可以同时指定多个数据流图元素。

sess.run([a,b]) #返回节点a和b的输出值。

feed_dict参数用于覆盖数据流图中的tensor对象值,它需要python字典对象作为输入。字典中的键位只想应当被覆盖的tensor对象,而字典中的值的类型必须与该tensor对象相同。

a=tf.add(2,5)

b=tf.mul(a,3)

sess=tf.Session()

rep_dict={a:15} #定义一个字典,将来a的值会被替换位15

sess.run(b,feed_dict=rep_dict) #最后返回值是15,而不是21.

利用session的as_default方法可以将session对象作为上下文管理器,session对象可被某些函数自动使用。例如Operation.run()和Tensor.eval()会将他们字节传入Session.run函数,而不需要显式调用session.run函数。

with sess.as_default():

a.eval() #等价于sess.run(a)

占位符与变量

之前,我们的例子都是使用确定的输入来完成一次运算。大多数情况,我们需要用数据流图定义好计算过程,然后输入用户的输入和输出来训练数据流图。因此我们需要输入节点只定义一个形状,而不是具体的值。这就需要用到占位符。

占位符的行为与tensor对象一致,但不需要指定具体的值,它的作用是为运算时即将到来的某个tensor对象预留为止。

a=tf.placeholder(tf.int32,shape=[2]) #占位符定义好类型和形状,这里类型是必须的,形状是可选参数。

为了给占位符传一个实际的值,需要使用session中的feed_dict参数。

input_dict={a:np.arrya([5,3],dtype=np.int32)}

sess.run(d,feed_dict=input_dict)

使用占位符,我们可以每次session.run中指定一个输入,但是如果我们需要在多次session.run中不停的调整权值,显然占位符不能胜任,此时就需要使用tf.Variable了。

my_var=tf.Variable(3) #初值为3的variable

Variable的初值通常是全0,全1,或者随机数。未达到这个目的,tensorflow提供了大量辅助op,tf.zeros,tf.ones,tf.random_normal,tf.random_uniform等等。

normal = tf.random_normal([3,3,3],mean=0.0,stddev=2.0) #均值为0,标准差为2.

variable对象与大多数其他tensorflow对象在Graph中存在的方式类似。但他们的状态实际上是由session对象管理的。因此为使用Variable对象,需要采取一些额外的步骤--必须在一个session对象内对variable对象进行初始化。variable对象的初始化通常是通过tf.initialize_all_variable()操作传给session.run完成的。

如果只需要对一个variabel对象初始化,可以使用tf.initialize_variables()操作。

要修改variable对象的值,可使用variable.assign方法。

my_var2=myvar.assign(myvar*2) #先把myval*2传给myval,再把myval的值传给myval2.

variable.assign_add()和variable.assign_sub是变量的自增和自减方法。

trainable参数缺省为true,当它为false时,表示这个变量不需要被优化类修改。

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接