TensorFlow 基础知识

参考资料:

TensorFlow 采用数据流图进行数值计算。节点代表计算图中的数学操作,计算图的边表示多维数组,即张量。

在 TensorFlow 官网上将其定义为基于数据流图的数值计算库,TensorFlow 还提供了一个可使得用户用数学方法从零开始定义模型的函数和类的广泛套件。这使得具有一定技术背景的用户可迅速而直观地创建自定义、具有较高灵活性的模型。

TensorFlow 的计算模型是有向图,其中的每个节点(通常以圆圈或方框表示)代表了一些函数或计算,而(通常以箭头或线段表示)代表了数值、矩阵、张量。TensorFlow 能够自动计算任意节点关于其他对第一个节点的输出产生影响的任意节点的导数(即 Operation),还可以通过计算的分解,将计算分布在多个 CPU、GPU 以及其他计算设备上(只需要将完整的、较大的数据流图分解为一些较小的计算图,并借由一定的逻辑对不同设备间的共享信息进行调度来让每台计算设备负责一个独立的计算子图)。

定义数据流图

TensorFlow的核心工作模式:

1. 定义数据流图

2. 运行数据流图(在数据上)

import tensorflow as tf  
# 在“input”节点上输入数据
a = tf.constant(5, name= \'input_a\')
b = tf.constant(3, name= \'input_b\')

# 定义运算节点“Operation”(简称:Op)
c = tf.multiply(a, b, name= \'mul_c\')
d = tf.add(a, b, name= \'add_d\')
e = tf.add(c, d, name= \'add_e\')

# 运行数据流图
with tf.Session() as sess:
    s = sess.run(e)
    print(s)
23

创建summary.FileWriter对象,并赋值给writer

writer = tf.summary.FileWriter(\'./my_graph\', sess.graph)
writer.close()
sess.close()
a = tf.constant([5, 3], name= \'input_a\')
b = tf.reduce_prod(a, name= \'prod_b\')   # 所有元素的乘积
c = tf.reduce_sum(a, name= \'sum_c\')    # 所有元素的和
d = tf.add(c, d, name= \'add_d\')
with tf.Session() as sess:
    print(sess.run([a, b, c, d]))
[array([5, 3]), 15, 8, 16]

1 张量

1.1 Python原生类型

TensorFlow可接收Python数值、布尔值、字符串或由它们构成的列表。

单个数值将会被转化为0阶张量(或标量),数值列表将被转化为2阶张量(矩阵),以此类推。

t0 = 50             # 标量
t1 = [b\'apple\', b\'peach\', b\'grape\']  # 向量
t2 = [[1, 3], [3, 5]]    # 矩阵

可将张量视为一种以结构化格式保存任意数据的方式。

TensorFlow数据类型

数据类型(dtype)描述
tf.float3232位浮点型
tf.float6464位浮点型
tf.int88位由符号整数
tf.int1616位由符号整数
tf.int3232位由符号整数
tf.int6464位由符号整数
tf.uint88位由无符号整数
tf.string字符串(作为非Unicode编码的字节数组)
tf.bool布尔型
tf.complex64复数,实部和 虚部分别为32位浮点型
tf.qint88位有符号整数(用于量化)
tf.qint32832位有符号整数(用于量化)
tf.quint88位有无符号整数(用于量化)
tf.quint3232位无符号整数(用于量化)

1.2 Numpy

TensorFlow的数据类型是基于NumPy的数据类型:

import numpy as np
np.int64 == tf.int64
True

任何一个NumPy数组均可传递给TensorFlow Op:

字符串数据类型

对于数值类型和布尔类型TensorFlow和NumPy dtype属性是完全一致的。然而,在NumPy中并无与tf.string精确对应的类型。即TensorFlow可以从NumPy中完美地导入字符串数组,只是不要在NumPy中显式指定dtype。

在运行数据流图之前之后,都可以利用NumPy库的功能,因为从Session.run方法返回的张量均为NumPy数组。

t1 = np.array(50, dtype= np.int64)
# 在NumPy中使用字符串时,不要显式指定dtype属性
t2 = np.array([b\'apple\', b\'peach\', b\'grape\'])
t3 = np.array([[True, False, False],[False, False, True], [False, True, True]], dtype = np.bool)
t4 = np.array([[[1]]], dtype= np.float32)

虽然TensorFlow是为理解NumPy原生数据类型而设计的,但反之不然。请不要尝试用tf.int32去初始化一个NumPy数组。

a = np.array(3, np.int) # 不是np.int32
a.dtype  
dtype(\'int32\')
a = np.array(3, np.float) 
a.dtype  
dtype(\'float64\')
a = np.array(3, np.float64) 
a.dtype  
dtype(\'float64\')
a = np.array(3, np.float32) 
a.dtype  
dtype(\'float32\')

手工指定Tensor对象时,使用NumPy是推荐的方式。

  1. 深度学习框架太抽象?其实不外乎这五大核心组件
  2. 常见问题

1.3 张量的形状

“形状”是TensorFlow的专有术语,它同时刻画了张量的维(阶)数以及每一维的长度。形式可以是列表或元组。

t1.shape   # 标量
()
t2.shape   # 向量
(3,)
t3.shape  # 矩阵
(3, 3)
t4.shape  # 3维数组(张量)
(1, 1, 1)

也可以将None作为某一维的长度,使得该张量具有可变长度。

此外,将形状指定为None,将通知TensorFlow允许一个张量为任意形状。

如果需要在数据流图的中间获取某个张量的形状,可使用tf.shape Op。它的输入为希望获取形状的Tensor对象,输出为一个int32类型的向量。

shape = tf.shape(t3, name= \'t3_shape\')
shape
<tf.Tensor \'t3_shape:0\' shape=(2,) dtype=int32>
with tf.Session() as sess:
    print(sess.run(shape))
[3 3]

2 TensorFlow的Operation

在TensorFlow中,数据流图本质上是一组链接在一起的函数,每个函数都会将其输出传递给0个、1个或多个位于这个级联链上的其他函数。按照这种方式,用户可利用一些很小的、为人们所充分理解的数学函数构造数据的复杂变换。

数据流图的两个基本构件:节点和边。

2.1 节点(node)

节点通常以圆圈、椭圆和方框表示,代表了对数据所做的运算和某种操作。

“input”节点的作用仅仅是传递Tensor的输入值。

sess = tf.InteractiveSession()
# 初始化一些计算需要的张量
a = np.array([2, 3], dtype= np.int)  # input_Op(节点)
a.dtype
dtype(\'int32\')
b = np.array([4, 5], dtype= np.int) # input_Op
# 利用tf.add() 初始化一个"add" Op
# 变量c为指向该Op的Tensor对象的句柄
c = tf.add(a, b)   # add Op
s = c.eval()
s
array([6, 8])
type(c)   # c是Tensor对象
tensorflow.python.framework.ops.Tensor
type(s) # s是数组,即张量的输出值
numpy.ndarray

TensorFlow中,数据流图中的每个节点都被称为一个“Operation”(简记:Op)。各Op可接收0个或多个Tensor对象作为输入,并输出0个或多个Tensor对象。要创建一个Op,可调用与其关联的Python构造方法。比如:

# `tf.constant`创建了一个常量Op,可接收单个张量值,然后将同样的值输出给其直接连接的节点。
## 自动将标量值转化为了Tensor对象。
r = tf.constant(5, name= \'input_a\')
r
<tf.Tensor \'input_a_4:0\' shape=() dtype=int32>
type(r.eval())
numpy.int32
type(r)
tensorflow.python.framework.ops.Tensor

2.2 边(edge)

edge对应于向Operation传入和从Operation传出的实际数值(可以视为Tensor),通常以箭头表示。

可从概念上将边视为不同的Operation之间的连接,因为它们将信息从一个节点传输到另一个节点。

运算符重载

运算符|相关TensorFlow运算