1.稀疏张量tf.SparseTensor
1.1 定义
是否还记得上一级中:基础数据类型API之strings与ragged_tensor中的ragged_tensor其实就是允许含有0元素的张量,但是,这种变量所有0都在非零数字的后面,那如果很多0穿插在张量中间怎么办?为此,引入了稀疏张量tf.SparseTensor(何为稀疏,就是很多0元素啦),这种结构只记录非零元素的位置和数值,就可以减少存储空间
1.2 创建
- indices为非零元素所在位置的索引,values为非零元素的数值
- dense_shape 为矩阵维度
s = tf.SparseTensor(indices=[[0,1],[1,0],[2,3]],
values=[1.,2.,3.],
dense_shape=[3,4])
print(s)
print(tf.sparse.to_dense(s))
结果:
SparseTensor(indices=tf.Tensor(
[[0 1]
[1 0]
[2 3]], shape=(3, 2), dtype=int64), values=tf.Tensor([1. 2. 3.], shape=(3,), dtype=float32), dense_shape=tf.Tensor([3 4], shape=(2,), dtype=int64))
tf.Tensor(
[[0. 1. 0. 0.]
[2. 0. 0. 0.]
[0. 0. 0. 3.]], shape=(3, 4), dtype=float32)
1.3 运算
与常数可以做乘法,不能做加法,否则会报错
# op on sparse tensors
s2 = s*2
print(s2)
try:
s3 = s+1
except TypeError as ex:
print(ex)
# 矩阵乘法
s4 = tf.constant([[11.,12.],
[22.,23],
[3.1,32.],
[41.,42.]])
print(tf.sparse.sparse_dense_matmul(s,s4))
结果:
SparseTensor(indices=tf.Tensor(
[[0 1]
[1 0]
[2 3]], shape=(3, 2), dtype=int64), values=tf.Tensor([2. 4. 6.], shape=(3,), dtype=float32), dense_shape=tf.Tensor([3 4], shape=(2,), dtype=int64))
unsupported operand type(s) for +: 'SparseTensor' and 'int'
tf.Tensor(
[[ 22. 23.]
[ 22. 24.]
[123. 126.]], shape=(3, 2), dtype=float32)
1.4 转换为密集矩阵
- 注意:tf.SparseTensor中的indices 需要是排好序的
- 否则在tf.sparse.to_dense时会报错
- 当然,可以使用tf.sparse.reorder自动排顺序
s5 = tf.SparseTensor(indices=[[1,1],[1,0],[2,3]],
values=[1.,2.,3.],
dense_shape=[3,4])
print(s)
s6=tf.sparse.reorder(s5)
print(tf.sparse.to_dense(s6))
结果:
SparseTensor(indices=tf.Tensor(
[[1 1]
[1 0]
[2 3]], shape=(3, 2), dtype=int64), values=tf.Tensor([1. 2. 3.], shape=(3,), dtype=float32), dense_shape=tf.Tensor([3 4], shape=(2,), dtype=int64))
tf.Tensor(
[[0. 0. 0. 0.]
[2. 1. 0. 0.]
[0. 0. 0. 3.]], shape=(3, 4), dtype=float32)
2. 变量tf.Variable
对于常量,在神经网络训练的过程中是不能变的,而变量时可以变的,变量与常量差不多,但是变量会多一些操作
2.1 创建
v = tf.Variable([[1,2,3],
[4,5,6]])
print(v)
print(v.value())
print(v.numpy())
结果:
<tf.Variable 'Variable:0' shape=(2, 3) dtype=int32, numpy=
array([[1, 2, 3],
[4, 5, 6]])>
tf.Tensor(
[[1 2 3]
[4 5 6]], shape=(2, 3), dtype=int32)
[[1 2 3]
[4 5 6]]
2.2 重新复制
在运行过程中,可以通过assign()函数重新赋值
v.assign(v*2)
print(v.numpy())
# print(v*2)
v[0,1].assign(12)
print(v.numpy())
v[0].assign([51,52,53])
print(v.numpy())
结果:
[[ 2 4 6]
[ 8 10 12]]
[[ 2 12 6]
[ 8 10 12]]
[[51 52 53]
[ 8 10 12]]
这里要注意,这里的重新赋值只能用assign()函数,不能用等号
try :
v[1] = [1,2,3]
except TypeError as ex:
print(ex)
结果:
'ResourceVariable' object does not support item assignment