TensorFlow 学习笔记-3

TensorFlow 张量

张量的概念

在数学里,张量是一种几何实体,广义上表示任意形式的数据。

张量可以理解为0阶标量、1阶向量和2阶矩阵在高维空间上的推广,张量的阶描述它表示数据的最大维度。

在这里插入图片描述

在这里插入图片描述

TensorFlow 中的张量

TensorFlow 中的张量表示:某种相同数据类型的多维数组

因此,张量有两个重要属性:

  1. 数据类型(如浮点型、整型、字符串)
  2. 数组形状(各个维度的大小)

当我们去定义一个张量的时候,它里面的所有的元素都应该是相同的数据类型,并且还要明确的描述出这个数组的形状。

TensorFlow 中的张量的作用

  • 用来表示多维数据,可以用它来表示1~ n维的数据,那同时整个N 阶的数据都能够通过一个多维数组表示出来。

  • 张量是执行操作时的输入或输出数据。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cQIgAF7Y-1663421914899)(/Volumes/猪猪博雅/1.All 下载文件/Safari浏览器下载/2019-01-28-tensorflow-introduction-02-01.gif)]

这张图里边里面流动的就是数据(张量),边就是张量。每一个节点都是操作,在执行操作的时候需要输入数据的 ,例如:y=a+b,a和b就是我们的输入数据,需要张量流入到这个操作节点才能够进行运算,y又会作为下一个操作的一个输入数据。所以y=a+b这个操作的输出的数据也是由张量来表示的。

张量的类别

在 TensorFlow 中,有几类比较特别的张量,由以下操作产生:
tf.constant

  • 常量,用常量操作创建出来张量之后,张量的值是不可改变的

tf.placeholder

  • 占位符,可以简单理解为一个描述了数据的壳,本身是要通过数据流图外面的数据填充进来才可以得到数据的这么一种特殊的操作。甚至可以在填充数据的时候,再去定义深度到底是多少,就给的模型训练的数据填充留下足够灵活的接口。

tf.Variable

  • 变量,可以在整个数据流图的过程当中维护我的状态,达到保存值的一个效果。使得值在整个数据流图运行结束之后也不会被释放,会常驻在内存里面,使得的值能够保存下来。

如何创建一个张量

张量的创建并不是张量的类的构造方法去创建,而是直接通过执行一个操作来创建,开始有提到的形状属性很重要,很多时候说必须要定义形状,是指在实际的运行时, 必须要把形状定义下来。

比例:两个矩阵相乘,如果不清楚矩阵的形状,无法去做相乘。

在写代码的时候,其实是不一定能确定形状,因为跟输入数据有关。可以把形状具体某一部分缺审,然后在实际运行的时候通过形状推断(运算到这一层的时候,当前的张量或者说数组到底是什么形状)

# 0阶张量(通过操作的方式创建 0 阶张量)
mammal = tf.Variable('Elephant',tf.string)
ignition = tf.Variable(451,tf.int64)
floating = tf.Variable(3.1415926,tf.float64)
its_complicated = tf.Variable(12.3 - 4.85)
[mammal,ignition,floating,its_complicated]

输出:
[<tf.Variable ‘Variable:0’ shape=() dtype=string, numpy=b’Elephant’>,
<tf.Variable ‘Variable:0’ shape=() dtype=int32, numpy=451>,
<tf.Variable ‘Variable:0’ shape=() dtype=float32, numpy=3.1415925>,
<tf.Variable ‘Variable:0’ shape=() dtype=float32, numpy=7.45>]

# 1阶张量
mystr = tf.Variable(['Hello','World'],tf.string)
cool_numbers = tf.Variable([3.14159,2.71828],tf.float32)
first_primes = tf.Variable([2,3,4,7,11],tf.int32)
its_very_complicated = tf.Variable([12.3-4.85j,7.5-6.23j],tf.complex64)

# 2阶张量
mymat = tf.Variable([[7],[11]],tf.int64)
myxor = tf.Variable([[False,True],[True,False]],tf.bool)
linear_squares = tf.Variable([[4],[9],[16],[25]],tf.int32)
squarish_squares = tf.Variable([[4,9],[16,25]],tf.int32)
rank_of_squares = tf.rank(squarish_squares)
mymatC = tf.Variable([[7],[11]],tf.int32)

# 四阶的张量
my_image = tf.zeros([10,299,299,3])

TensorFlow 变量

变量的作用

变量一种特殊的张量,变量的主要作用:维护特定节点的状态
比如:深度学习或者机器学习当中的模型参数,w跟b就是变量。模型参数反复更新之后,仍然不会在内存当中释放,而是会常驻在内存里面。

变量与张量的异同

通过 tf.Variable 方法创建的变量,可以作为操作的输入和输出(与张量一样)。

不同之处在于:
张量的生命周期通常随依赖的计算完成而结束,内存也随即释放。
变量则常驻内存,维护他的状态。在每一步训练时不断更新其值,以实现模型参数的更新(减少不必要的开销:重载模型参数、重新初始化)。

# 创建变量
# 变量的初始值
# 名称:为了更好的在数据流途里面去展现它,尤其是很复杂的模型的时候,我们可以显示的去定义他这个变量名
# dtype(数据类型):不写也行,TensorFlow 能够自自行判断(初始值、计算过程)
w = tf.Variable(<initial-value>,name=<optional-name>)

# 将变量作为操作的输入
y = tf.matmul(w,...another variable or tensor...)
z = tf.sigmoid(w + y)

# 使用 assign 或 assign_xxx方法重新给变量赋值
w.assign(w + 1.0)
w.assign_ass(1.0)

整个创建变量的过程,实际可以理解为定义了一个规则(包括初始值、数据类型、形状等等),但在开始会话之前(开始整个图运算之前),其实是没有任何真正的计算执行。都只是一个抽象的图的定义,没有执行。那如果真正要开始执行的时候,其实需要去加载数据流图到会话里,然后通过初始化我们的变量(运行创建变量时定义的规则,可以理解为 C 语言语法,按照这个规则去初始化定义了一个变量)才能开始运算。所以真正开始执行一张数据流图的时,所有的变量都是需要初始化,定义跟初始化是完全分开的两个步骤?

大家可以认为创建变量操作是描述清楚了这个函数、变量长什么样子,他的初始值、类型等是什么,但是真正开始计算的时候,需要在会话里面去计算,需要去申请对应的资源。

当你放置到设备上之后,开始执行计算的时候,还需要去执行这个初始化的这么一个操作。

TensorFlow提供了一个给全局所有的变量做初始化的一个操作,可以把一张图里面的所有的变量按照定义或者创建的初始值进行一遍操作,把值给他填充进去(背后的原理:本身是在内部调用assign)

变量的典型使用流程

tf.Variable
整个TensorFlow变量的一个典型的使用流程,其实可以总结下来分为5块

在这里插入图片描述

  • 当我们创建一个变量的时候,我们可以通过初始值,给Variable去直接显示的去给他赋一个值

  • 当继续训练,从这个模型文件里面去加载这个模型参数的时候,也可以从checkpoint文件里去读取出上一次训练的变量的值,用checkpoint文件里的变量值去恢复当前数据,而不再是从头开始的初始值。

  • 每一步更新,其实都是在这个每一步训练完成之后才会做的事,那训练完成之后,更新完的模型参数,也需要不断的存储到模型文件里面。

tf.Variable可完成

  1. 创建(操作)

  2. 初始化(操作)
    把数据流图加载到会话中,然后通过一个全局初始化的操作,真正的把值赋给我们的变量
    那这个是在会话当中进行的

  3. 更新(操作)

    assign

tf.train.Saver
引入一个新的类(tf.train.Saver),跟真正的模型训练相关的一个很重要的类。
很多时候训练一个很大的模型不太可能会一次性就训练成功,可能你需要训练到中途的时候停下来,调整一些东西(超参数、训练的设备等)。这个时候你需要把你的模型参数持久化或者说保存到一个本地的文件里面或者远端的一个文件系统里。
这个时候需要用tf.train.Saver,把所有的变量或者说把需要训练的这个模型参数对应的变量保存下来,保存的文件就叫做checkpoint 文件。保存下来之后,还可以通过tf.train.Saver 去恢复这个文件。

TensorFlow 操作

操作就是数据流途当中的节点,数据流图是一种声明式的编程范式,更加偏向于函数以及算法模型的抽象表达。所以说通常用数据流图来表示算法模型,而操作作为节点才是真正模型功能的一个实际的载体。

操作的类别

按照功能的不同分为3种

  1. 存储节点:有状态的变量操作,通常用来存储模型参数;
  2. 计算节点:无状态的计算或控制操作,主要负责算法逻辑表达或流程控制;
  3. 数据节点:数据的占位符操作,用于描述图外输入数据的属性。(一个数据流图他的输入数据,其实就是通过数据节点,又是我们的占位符从图外输入)

操作的输入和输出可以是张量或操作(一个操作得到的结果用作下一个操作的输入)(函数式编程)

TensorFlow典型的计算和控制操作

在这里插入图片描述

TensorFlow占位符操作

占位符操作表示图外输入的数据(比如训练、测试数据),TensorFlow数据流图描述了算法模型的计算拓扑,其中的各个操作(节点)都是抽象的函数映射或数学表达式。
换句话说,数据流图本身是一个具有计算拓扑和内部结构的“壳”。在用户向数据流图(边和点:张量和操作)填充数据前,图中并没有真正执行任何计算。

所以说很多时候第一步开始执行,就是给数据流图填充数据。那填充数据是一个什么样的过程:利用了python的字典(feed_dict={x:2,y:3}

# x = tf.placeholder(dtype,shape,name)
# TF.placeholder,它其实是定义了占位符,需要3个初始参数

# 只是定义了两个整形的标量而已
x = tf.placeholder(tf.int16,shape=(),name='x')
y = tf.placeholder(tf.int16,shape=(),name='y')
with tf.Session() as sess:
  # 填充数据后,执行操作
  print(sess.run(add,feed_dict={x:2,y:3}))
  print(sess.run(mul,feed_dict={x:2,y:3}))

要从数据流图里面取数据一定要通过session这种方式去执行,那如果要往这个数据流图里面填充数据,通常是通过这个占位符操作往里填充。

在这里插入图片描述

数据流图没有在会话中正式执行之前,整个数据流图都只是一个壳(没有真实的数据在里面流动),
也就是没有图里面的流动的线条,因为我们的这个Tensor里面什么都没有。

TensorFlow 的 Python API 和 Python完全区分开来

Python是一个语言,但TensorFlow的Python API并不是Python,而是一种领域特定语言,他实现了一种声明式的编程范式,所以说如果用Python的逻辑,包括这个循环判断去理解这个数据流图的话,
有时可能会出现一些问题。并不能够在这个编译时刻或者说在编写代码的时刻去预测实际运行时的状况,也是尽量不要去使用TensorFlow的逻辑控制和调试的操作的一个原因。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

彩虹编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值