Tensorflow从入门到精通(二):附代码实战

1.Tensor介绍

Tensor(张量)是Tensorflow中最重要的数据结构,用来表示Tensorflow程序中的所有数据。Tensor本是广泛应用在物理、数学领域中的一个物理量。那么在Tensorflow中该如何理解Tensor的概念呢?

实际上,我们可以把Tensor理解成N维矩阵(N维数组)。其中零维张量表示的是一个标量,也就是一个数;一维张量表示的是一个向量,也可以看作是一个一维数组;二维张量表示的是一个矩阵;同理,N维张量也就是N维矩阵。

在计算图模型中,操作间所传递的数据都可以看做是Tensor。那Tensor的结构到底是怎样的呢?我们可以通过程序1-1更深入的了解一下Tensor。

程序1-1:

#导入tensorflow模块

import tensorflow as tf

a = tf.constant([[2.0,3.0]] ,name="a")

b = tf.constant([[1.0],[4.0]] ,name="b")

result = tf.matmul(a,b,name="mul")

print(result)

>> Tensor("mul_3:0", shape=(1, 1), dtype=float32)

程序1-1的输出结果表明:构建图的运算过程输出的结果是一个Tensor,且其主要由三个属性构成:Name、Shape和Type。Name代表的是张量的名字,也是张量的唯一标识符,我们可以在每个op上添加name属性来对节点进行命名,Name的值表示的是该张量来自于第几个输出结果(编号从0开始),上例中的“mul_3:0”说明是第一个结果的输出。Shape代表的是张量的维度,上例中shape的输出结果(1,1)说明该张量result是一个二维数组,且每个维度数组的长度是1。最后一个属性表示的是张量的类型,每个张量都会有唯一的类型,常见的张量类型如图1-1所示。

图1-1 常用的张量类型

我们需要注意的是要保证参与运算的张量类型相一致,否则会出现类型不匹配的错误。如程序1-2所示,当参与运算的张量类型不同时,Tensorflow会报类型不匹配的错误:

程序1-2:

import tensorflow as tf

m1 = tf.constant([5,1])

m2 = tf.constant([2.0,4.0])

result = tf.add(m1,m2)

TypeError: Input 'y' of 'Add' Op has type float32 that does not match type int32 of argument 'x'.

正如程序的报错所示:m1是int32的数据类型,而m2是float32的数据类型,两者的数据类型不匹配,所以发生了错误。所以我们在实际编程时,一定注意参与运算的张量数据类型要相同。

2 常量、变量及占位符

Tensorflow中对常量的初始化,不管是对数值、向量还是对矩阵的初始化,都是通过调用constant()函数实现的。因为constant()函数在Tensorflow中的使用非常频繁,经常被用于构建图模型中常量的定义,所以接下来,我们通过程序1-3了解一下constant()的相关属性:程序2-1:

import tensorflow as tf

a = tf.constant([2.0,3.0],name="a",shape=(2,0),dtype="float64",verify_shape="true")

print(a)

>> Tensor("a_11:0", shape=(2, 0), dtype=float64)

如程序2-1所示,函数constant有五个参数,分别为value,name,dtype,shape和verify_shape。其中value为必选参数,其它均为可选参数。Value为常量的具体值,可以是一个数字,一维向量或是多维矩阵。Name是常量的名字,用于区别其它常量。Dtype是常量的类型,具体类型可参见图2-2。Shape是指常量的维度,我们可以自行定义常量的维度。

verify_shape是验证shape是否正确,默认值为关闭状态(False)。也就是说当该参数true状态时,就会检测我们所写的参数shape是否与value的真实shape一致,若不一致就会报TypeError错误。如:上例中的实际shape为(2,0),若我们将参数中的shape属性改为(2,1),程序就会报如下错误:

TypeError: Expected Tensor's shape: (2, 1), got (2,).

Tensorflow还提供了一些常见常量的初始化,如:tf.zeros、tf.ones、tf.fill、tf.linspace、tf.range等,均可以快速初始化一些常量。例如:我们想要快速初始化N维全0的矩阵,我们可以利用tf.zeros进行初始化,如程序1-4所示:

程序2-2:

import tensorflow as tf

a=tf.zeros([2,2],tf.float32)

b=tf.zeros_like(a,optimize=True)

with tf.Session() as sess:

print(sess.run(a))

print(sess.run(b))

>> [[ 0. 0.]

[ 0. 0.]]

[[ 0. 0.]

[ 0. 0.]]

程序2-2向我们展示了tf.zeros和tf.zeros_like的用法。其它常见常量的具体初始化用法可以参考Tensorflow官方手册:https://www.tensorflow.org/api_guides/python/constant_op

此外,Tensorflow还可以生成一些随机的张量,方便快速初始化一些随机值。如:tf.random_normal()、tf.truncated_normal()、tf.random_uniform()、tf.random_shuffle()等。如程序1-5所示,我们以tf.random_normal()为例,来看一下随机张量的具体用法:

程序2-3:

import tensorflow as tf

random_num=tf.random_normal([2, 3], mean=-1, stddev=4,

dtype=tf.float32,seed=None,name='rnum')

with tf.Session() as sess:

print(sess.run(random_num))

>> [[-2.71897316 1.04246855 -3.12996817]

[-1.34851456 -0.13599336 4.60532522]]

随机张量random_normal()有shape、mean、stddev、dtype、seed、name六个属性。shape是指张量的形状,如上述程序是生成一个2行3列的tensor;mean是指正态分布的均值;stddev是指正太分布的标准差;dtype是指生成tensor的数据类型;seed是分发创建的一个随机种子;而name是给生成的随机张量命名。

Tensorflow中的其它随机张量的具体使用方法和属性介绍,可以参见Tensorflow官方手册:https://www.tensorflow.org/api_guides/python/constant_op。这里将不在一一赘述。

除了常量constant(),变量variable()也是在Tensorflow中经常会被用到的函数。变量的作用是保存和更新参数。执行图模型时,一定要对变量进行初始化,经过初始化后的变量才能拿来使用。变量的使用包括创建、初始化、保存、加载等操作。首先,我们通过程序2-4了解一下变量是如何被创建的:

程序2-4:

import tensorflow as tf

A = tf.Variable(3, name="number")

B = tf.Variable([1,3], name="vector")

C = tf.Variable([[0,1],[2,3]], name="matrix")

D = tf.Variable(tf.zeros([100]), name="zero")

E = tf.Variable(tf.random_normal([2,3], mean=1, stddev=2, dtype=tf.float32))

程序2-4展示了创建变量的多种方式。我们可以把函数variable()理解为构造函数,构造函数的使用需要初始值,而这个初始值是一个任何形状、类型的Tensor。也就是说,我们

既可以通过创建数字变量、一维向量、二维矩阵初始化Tensor,也可以使用常量或是随机常量初始化Tensor,来完成变量的创建。

当我们完成了变量的创建,接下来,我们要对变量进行初始化。变量在使用前一定要进行初始化,且变量的初始化必须在模型的其它操作运行之前完成。通常,变量的初始化有三种方式,如程序2-5所示:

程序2-5:

#初始化全部变量:

init = tf.global_variables_initializer()

with tf.Session() as sess:

sess.run(init)

#初始化变量的子集:

init_subset=tf.variables_initializer([b,c], name="init_subset")

with tf.Session() as sess:

sess.run(init_subset)

#初始化单个变量:

init_var = tf.Variable(tf.zeros([2,5]))

with tf.Session() as sess:

sess.run(init_var.initializer)

程序2-5说明了初始化变量的三种方式:初始化全部变量、初始化变量的子集以及初始化单个变量。首先,global_variables_initializer()方法是不管全局有多少个变量,全部进行初始化,是最简单也是最常用的一种方式;variables_initializer()是初始化变量的子集,相比于全部初始化化的方式更加节约内存;Variable()是初始化单个变量,函数的参数便是要初始化的变量内容。通过上述的三种方式,我们便可以实现变量的初始化,放心的使用变量了。

我们经常在训练模型后,希望保存训练的结果,以便下次再使用或是方便日后查看,这时就用到了Tensorflow变量的保存。变量的保存是通过tf.train.Saver()方法创建一个Saver管理器,来保存计算图模型中的所有变量。具体代码如程序2-6所示:

程序2-6:

import tensorflow as tf

var1 = tf.Variable([1,3], name="v1")

var2 = tf.Variable([2,4], name="v2")

#对全部变量进行初始化

init = tf.initialize_all_variables()

#调用Saver()存储器方法

saver = tf.train.Saver()

#执行图模型

with tf.Session() as sess:

sess.run(init)

#设置存储路径

save_path = saver.save(sess,"test/save.ckpt")

我们要注意,我们的存储文件save.ckpt是一个二进制文件,Saver存储器提供了向该二进制文件保存变量和恢复变量的方法。保存变量的方法就是程序中的save()方法,保存的内容是从变量名到tensor值的映射关系。完成该存储操作后,会在对应目录下生成如图2-1所示的文件:

图2-1 保存变量生成的相应文件

Saver提供了一个内置的计数器自动为checkpoint文件编号。这就支持训练模型在任意步骤多次保存。此外,还可以通过global_step参数自行对保存文件进行编号,例如:global_step=2,则保存变量的文件夹为model.ckpt-2。

那如何才能恢复变量呢?首先,我们要知道一定要用和保存变量相同的Saver对象来恢复变量。其次,不需要事先对变量进行初始化。具体代码如程序2-7所示:

程序2-7:

import tensorflow as tf

var1 = tf.Variable([0,0], name="v1")

var2 = tf.Variable([0,0], name="v2")

saver = tf.train.Saver()

module_file = tf.train.latest_checkpoint('test/')

with tf.Session() as sess:

saver.restore(sess,module_file)

print("Model restored.")

本程序示例中,我们要注意:变量的获取是通过restore()方法,该方法有两个参数,分别是session和获取变量文件的位置。我们还可以通过latest_checkpoint()方法,获取到该目录下最近一次保存的模型。

以上就是对变量创建、初始化、保存、加载等操作的介绍。此外,还有一些与变量相关的重要函数,如:eval()等。

认识了常量和变量,Tensorflow中还有一个非常重要的常用函数——placeholder。placeholder是一个数据初始化的容器,它与变量最大的不同在于placeholder定义的是一个模板,这样我们就可以session运行阶段,利用feed_dict的字典结构给placeholder填充具体的内容,而无需每次都提前定义好变量的值,大大提高了代码的利用率。Placeholder的具体用法如程序2-8所示:

程序序2-8:

import tensorflow as tf

a = tf.placeholder(tf.float32,shape=[2],name=None)

b = tf.constant([6,4],tf.float32)

c = tf.add(a,b)

with tf.Session() as sess:

print(sess.run(c,feed_dict={a:[10,10]}))

程序2-8演示了placeholder占位符的使用过程。Placeholder()方法有dtype,shape和name三个参数构成。dtype是必填参数,代表传入value的数据类型;shape是选填参数,代表传入value的维度;name也是选填参数,代表传入value的名字。我们可以把这三个参数看作为形参,在使用时传入具体的常量值。这也是placeholder不同于常量的地方,它不可以直接拿来使用,而是需要用户传递常数值。

最后,Tensorflow中还有一个重要的概念——fetch。Fetch的含义是指可以在一个会话中同时运行多个op。这就方便我们在实际的建模过程中,输出一些中间的op,取回多个tensor。Fetch的具体用法如程序2-9所示:

程序2-9:

import tensorflow as tf

a = tf.constant(5)

b = tf.constant(6)

c = tf.constant(4)

add = tf.add(b, c)

mul = tf.multiply(a, add)

with tf.Session() as sess:

result = sess.run([mul, add])

print(result)

>> [50,10]

程序2-10展示了fetch的用法,即我们利用session的run()方法同时取回多个tensor值,方便我们查看运行过程中每一步op的输出结果。

程序2-10:

import tensorflow as tf

var1 = tf.Variable([0,0], name="v1")

var2 = tf.Variable([0,0], name="v2")

Saver = tf.train.Saver()

module_file = tf.train.latest_checkpoint('test/')

with tf.Session() as sess:

saver.restore(sess,module_file)

print("Model restored.")

小结:本节旨在让大家学会Tensorflow的基础知识,为后边实战的章节打下基础。主要介绍了Tensor的概念,以及Tensorflow中的常量、变量、占位符、feed等知识点。

原文发布于微信公众号 - 磐创AI(xunixs)

原文发表时间:2018-03-29

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏机器学习从入门到成神

数据库中关系代数中的关系运算

这个概念的描述的非常抽象,刚开始学习的同学完全不知所云。这里通过一个实例来说明除法运算的求解过程:

1.8K20
来自专栏数据结构与算法

P1115 最大子段和

题目描述 给出一段序列,选出其中连续且非空的一段使得这段和最大。 输入输出格式 输入格式: 输入文件maxsum1.in的第一行是一个正整数N,表示了序列的长度...

30850
来自专栏机器学习和数学

[Tensorflow] TensorFlow之Hello World!(2)

TensorFlow入门的第一篇和大家聊了?graph图,op操作,node节点。对TensorFlow有了一个简单的认识,今天主要和大家分享的是TensorF...

40870
来自专栏逸鹏说道

博客园LaTex的测试,附带开启方法

单位矩阵是个方阵,从左上角到右下角的对角线(称为主对角线)上的元素均为1。其他全都为0,eg:

11530
来自专栏chenjx85的技术专栏

leetcode-79-单词搜索(用dfs解决)

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

45410
来自专栏数据处理

mat(矩阵)与array(数组)区别

35530
来自专栏贾志刚-OpenCV学堂

TensorFlow中常量与变量的基本操作演示

TensorFlow中常量与变量的基本操作演示 本文将介绍TensorFlow中的基本算法运算与矩阵运算,介绍Tensorflow中常量、变量、操作符等基本运算...

45380
来自专栏小樱的经验随笔

统计0到n之间1的个数[数学,动态规划dp](经典,详解)

问题描述 给定一个十进制整数N,求出从1到N的所有整数中出现”1”的个数。 例如:N=2时 1,2出现了1个 “1” 。 N=12时 1,2,3,4,5,6,...

36380
来自专栏WD学习记录

牛客网 和为S的两个数字

输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。

19540
来自专栏desperate633

LintCode 数字三角形题目分析1 (常规的动态规划解法)分析2 (如果你只用额外空间复杂度O(n)的条件)

给定一个数字三角形,找到从顶部到底部的最小路径和。每一步可以移动到下面一行的相邻数字上。 ** 注意事项 如果你只用额外空间复杂度O(n)的条件下完成可以获...

10920

扫码关注云+社区

领取腾讯云代金券