《深入了解TensorFlow》笔记——Chapter 3.2 数据载体:张量


为了更方便地定义数学表达式、更准确地描述数学模型,TF使用张量(Tensor)统一表示所有数据。在实际计算式,即表达式的转化过程中,模型所对应的表达式中的数据由张量来承载。TF提供 TensorSparseTensor两种张量抽象,分别表示稠密数据和稀疏数据,后者旨在减少高维稀疏数据的内存占用。

张量:Tensor

TF Tensor具有极强的数据表达能力,这既体现在它对High dimensional data的抽象描述,又体现在它对多样化data type的支持。

Data typeTF 数据类型说明
DT_HALFtf.float16半精度浮点数
DT_FLOATtf.float32单精度浮点数
DT_DOUBLEtf.float64双精度浮点数
DT_BFLOAT16tf.bfloat16裁短浮点数
DT_INT8tf.int88位有符号整数
DT_INT16tf.int1616位有符号整数
DT_INT32tf.int3232位有符号整数
DT_INT64tf.int6464位有符号整数
DT_UINT8tf.uint88位无符号整数
DT_UINT16tf.uint1616位无符号整数
DT_STRINGtf.string字符串
DT_BOOLtf.bool布尔值
DT_COMPLEX64tf.complex64单精度复数
DT_COMPLEX128tf.complex128双精度复数
DT_QINT8tf.qint8量化8位有符号整数
DT_QINT16tf.qint16量化16位有符号整数
DT_QINT32tf.qint32量化32位有符号整数
DT_QUINT8tf.quint8量化8位无符号整数
DT_QUINT16tf.quint16量化16位无符号整数

TF张量在逻辑定义上是数据载体,但在物理实现时是一个句柄,它存储张量的meta info以及指向张量数据的memory buffer pointer。这样设计是为了实现内存复用。在某些前置操作的输出值被输入到多个后置操作的情况下,无需重复存储输入值。当一个张量不在被任何操作依赖后,TF会释放存储该tensor的memory buffer。TF内部通过引用计数方式判断是否应该释放张量数据的memory buffer。

创建张量

在TF Python API中,稠密张量抽象是Tensor类。不过一般情况下,用户不需要使用Tensor类的构造方法直接创建张量,而是通过操作间接创建张量。典型的张量创建操作包括常量定义操作和代数计算操作。

import tensorflow as tf
a = tf.constant(1.0)
b = tf.constant(2.0)
c = tf.add(a, b)
print(a, b, c)
# 输出
"""
Tensor("Const:0", shape=(), dtype=float32)
Tensor("Const_1:0", shape=(), dtype=float32)
Tensor("Add:0", shape=(), dtype=float32)
"""

以上三个变量都是张量。

求解

数据流图中的操作输出值由张量承载。如果想要求解特定张量值,则需要创建回话,然后执行张量的eval()方法或者session的run()方法。

with tf.Session() as sess:
	print(c.eval())
	print(sess.run(c))
#输出
"""
3.0
3.0
"""

成员方法

TF Tensor抽象除了支持多样化数据类型外,也提供一些成员方法来动态改变张量形状,以及查看张量的后置操作。

member namefunction
eval()取出张量值
get_shape()获取张量形状
set_shape()修改张量形状
consumers获取张量的后置操作

操作

TF为Tensor提供了大量的操作,以便构建数据流图,实现算法模型。如一元代数操作,二元代数操作,形状操作,规约操作,神经网络操作,条件操作。

示例

import tensorflow as tf
a = tf.constant([1, 1])
b = tf.constant([2, 3])
c = tf.add(a, b)
with tf.Session() as sess:
	print("a[0] = {}, a[1] = {}".format(a[0].eval(), a[1].eval()))
	print("c.name = {}".format(c.name))
	print("c.value = {}".format(c.eval()))
	print("c.shape = {}".format(c.shape))
	print("a.consumers = {}".format(a.consumers()))
	print("b.consumers = {}".format(b.consumers()))
	print("[c.op]: \n {}".format(c.op))
# 输出
"""
a[0] = 1, a[1] = 1
c.name = Add:0
c.value = [3 4]
c.shape = (2,)
a.consumers = [<tf.Operation 'Add' type=Add>]
b.consumers = [<tf.Operation 'Add' type=Add>]
[c.op]:
 name: "Add"
op: "Add"
input: "Const"
input: "Const_1"
attr {
 		key: "T"
 		value {
  			type: DT_INT32
 		}
}
"""

稀疏张量:SparseTensor

TF提供了专门用于处理高维稀疏数据的SparseTensor类,该类以键值对的形式表示高维稀疏数据,它包含indices, values, & dense_shape三个属性,其中,indices是一个形状为[N, ndims]的Tensor实例,N表示非零元素的个数,ndims表示张量的阶数。例如,当indices = [[0, 2], [1, 3], [2, 1]](N=2, ndims = 2),表示2阶系数张量中索引为[0, 2], [1, 3], [2, 1]的元素非零。values是一个形状为[N]的Tensor对象,用于保存indices中指定元素的值。dense_shape是一个形状为[ndims]的tensor实例,表示该稀疏张量对应稠密张量的形状。

创建

在TF中创建sparse tensor,一般直接使用SparseTensor类的构造方法。

import tensorflow as tf
sp = tf.SparseTensor(indices=[[0, 2], [1, 3], [2, 1]],
					values = [1, 3, 2],
					dense_shape = [3, 4])
with tf.Session() as sess:
	print(sp.eval())
	dense = tf.sparse_tensor_to_dense(sp)
	print(dense.eval())
"""
SparseTensorValue(indices=array([[0, 2],
      [1, 3],
      [2, 1]]), values=array([1, 3, 2], dtype=int32), dense_shape=array([3, 4]))
[[0 0 1 0]
[0 0 0 3]
[0 2 0 0]]
"""

操作

TF为sparse tensor提供了一些专门的操作,这样用户能够像处理Tensor一样处理SparseTensor。主要包括:转换操作、代数操作、集合操作、归约操作。

示例

import tensorflow as tf
sp = tf.SparseTensor(indices=[[0, 2], [1, 3], [2, 1]],
					values = [1, 3, 2],
					dense_shape = [3, 4])
reduce_x = [tf.sparse_reduce_sum(x),
			tf.sparse_reduce_sum(x, axis=1),
			tf.sparse_reduce_sum(x, axis=1, keep_dims=True),
			tf.sparse_reduce_sum(x, axis=[0, 1])]
with tf.session() as sess:
	dense = tf.sparse_tensor_to_dense(sp)
	print(dense.eval())
	print(sess.run(reduce_x))
# 输出
"""
dense_shape=array([3, 4]))
[[0 0 1 0]
[0 0 0 3]
[0 2 0 0]]
	
[6, array([1, 3, 2], dtype=int32), array([[1],
      [3],
      [2]], dtype=int32), 6]
"""

SparseTensor & SparseTensorValue区别

TF里关于sparse tensor有两个api接口,tf.SparseTensor() and tf.SparseTensorValue()。它们的使用区别在于:如果要在数据流图中定义sparse tensor,则使用tf.SparseTensor();而如果是给定义好的数据流图feed稀疏张量,那么要使用tf.SparseTensorValue()

tf.SparseTensor() 示例代码如下所示:

import tensorflow as tf

indices_i = tf.placeholder(dtype=tf.int64, shape=[2, 2])
values_i = tf.placeholder(dtype=tf.float32, shape=[2])
dense_shape_i = tf.placeholder(dtype=tf.int64, shape=[2])
st = tf.SparseTensor(indices=indices_i, values=values_i, dense_shape=dense_shape_i)

W = tf.Variable(tf.random_normal([6, 6]))
y = tf.sparse_tensor_dense_matmul(sp_a=st, b=W)

init = tf.global_variables_initializer()
gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.2)
sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options))
sess.run(init)

result = sess.run(y, feed_dict={indices_i:[[0, 0], [1, 2]], values_i:[1.1, 1.2], dense_shape_i:[2,6]})

print(result)

tf.SparseTensorValue()示例代码如下

import tensorflow as tf

x_sp = tf.sparse_placeholder(dtype=tf.float32)
W = tf.Variable(tf.random_normal([6, 6]))
y = tf.sparse_tensor_dense_matmul(sp_a=x_sp, b=W)

init = tf.global_variables_initializer()
gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.2)
sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options))
sess.run(init)

stv = tf.SparseTensorValue(indices=[[0, 0], [1, 2]], values=[1.1, 1.2], 
dense_shape=[2,6])
result = sess.run(y, feed_dict={x_sp:stv}

print(result)

可以看出tf.SparseTensorValue()是和tf.sparse_placeholder()对应的。但是tf.sparse_placeholder()除了通过tf.SparseTensorValue()进行feed,还支持元组(indices, values, shape)或者numpy数组。详见 chapter3.3 “数据节点:Placeholder”-“示例”。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Dongz__

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

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

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

打赏作者

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

抵扣说明:

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

余额充值