好用的充电桩外观设计哪个技术强
2026/4/15 5:56:05
稀疏张量(tf.sparse.SparseTensor)是TensorFlow专为含大量零值(或空值)的张量设计的高效存储/处理方案,核心优势是仅存储非零值的坐标和值,大幅节省内存与计算资源。它广泛用于NLP(如TF-IDF编码)、计算机视觉(如含大量暗像素的图像)、嵌入层(embeddings)等超稀疏矩阵场景。
普通密集张量(tf.Tensor)会存储所有元素(包括大量零值),而稀疏张量仅存储:
例如,一个形状为[3,3]、仅含2个非零值的张量,密集存储需9个位置,而稀疏存储仅需2个位置的坐标+值,效率提升显著。
TensorFlow的稀疏张量基于COO(Coordinate List,坐标列表)格式编码,这是超稀疏矩阵(如embeddings)的最优编码方式。COO格式由三个核心组件构成:
| 组件 | 形状与类型 | 核心作用 |
|---|---|---|
values | 一维张量[N] | 存储所有非零值(N为非零值总数),顺序与indices一一对应 |
indices | 二维张量[N, rank] | 存储每个非零值的坐标:rank是稀疏张量的秩(维度数),每行对应一个非零值的坐标 |
dense_shape | 一维张量[rank] | 存储稀疏张量对应的密集张量形状(如[3,3]表示3行3列的二维张量) |
indices/values中编码的位置,默认值为0(稀疏张量的“零值”);values中(允许但不推荐,违背稀疏存储的初衷)。通常提及稀疏张量的“非零值”时,仅指values中的非隐式零值,显式零值一般不纳入统计。
importtensorflowastf# 示例:构造二维稀疏张量# 非零值:(0,1)=1.0,(1,2)=2.0,(2,0)=3.0indices=tf.constant([[0,1],[1,2],[2,0]],dtype=tf.int64)# [3,2](3个非零值,二维坐标)values=tf.constant([1.0,2.0,3.0],dtype=tf.float32)# [3](非零值列表)dense_shape=tf.constant([3,3],dtype=tf.int64)# [2](对应密集张量形状3x3)# 构造SparseTensorsparse_tensor=tf.sparse.SparseTensor(indices=indices,values=values,dense_shape=dense_shape)print("稀疏张量:",sparse_tensor)输出:
SparseTensor(indices=tf.Tensor( [[0 1] [1 2] [2 0]], shape=(3, 2), dtype=int64), values=tf.Tensor([1. 2. 3.], shape=(3,), dtype=float32), dense_shape=tf.Tensor([3 3], shape=(2,), dtype=int64))# 访问三个核心组件print("非零值(values):",sparse_tensor.values.numpy())print("非零值坐标(indices):",sparse_tensor.indices.numpy())print("密集形状(dense_shape):",sparse_tensor.dense_shape.numpy())# 转换为密集张量(验证)dense_tensor=tf.sparse.to_dense(sparse_tensor)print("\n对应密集张量:\n",dense_tensor.numpy())输出:
非零值(values): [1. 2. 3.] 非零值坐标(indices): [[0 1] [1 2] [2 0]] 密集形状(dense_shape): [3 3] 对应密集张量: [[0. 1. 0.] [0. 0. 2.] [3. 0. 0.]]tf.sparse.SparseTensor不强制indices/values的顺序,但TensorFlow多数稀疏算子(如tf.sparse.matmul)假设索引是行优先(row-major)顺序(即按行号升序、列号升序排列)。若索引无序,可能导致算子报错或结果异常。
# 构造无序索引的SparseTensorunordered_indices=tf.constant([[2,0],[0,1],[1,2]],dtype=tf.int64)unordered_sparse=tf.sparse.SparseTensor(indices=unordered_indices,values=values,dense_shape=dense_shape)# 重排序为行优先顺序ordered_sparse=tf.sparse.reorder(unordered_sparse)print("重排序后的索引:\n",ordered_sparse.indices.numpy())输出:
重排序后的索引: [[0 1] [1 2] [2 0]]稀疏张量支持部分TensorFlow核心运算(如加法、乘法),但需保证形状兼容,且运算结果仍为稀疏张量:
# 稀疏张量 + 标量(非零值加10)sparse_add=tf.sparse.map_values(lambdax:x+10,sparse_tensor)print("稀疏张量+10的非零值:",sparse_add.values.numpy())# 稀疏张量转换为密集张量后相乘dense_mul=dense_tensor*2print("\n密集张量×2:\n",dense_mul.numpy())输出:
稀疏张量+10的非零值: [11. 12. 13.] 密集张量×2: [[ 0. 2. 0.] [ 0. 0. 4.] [ 6. 0. 0.]]tf.sparse系列算子(如tf.sparse.reduce_sum)结果错误;tf.sparse.reorder确保索引有序。values中存储0(显式零值),这会浪费稀疏存储的优势;tf.sparse.retain:# 含显式零值的SparseTensorsparse_with_zero=tf.sparse.SparseTensor(indices=[[0,0],[0,1],[1,2]],values=[0.0,1.0,2.0],dense_shape=[2,3])# 过滤显式零值non_zero_sparse=tf.sparse.retain(sparse_with_zero,sparse_with_zero.values!=0)print("过滤后的非零值:",non_zero_sparse.values.numpy())输出:[1. 2.]| 类型 | 核心用途 | 存储方式 | 零值处理 |
|---|---|---|---|
| SparseTensor | 大量零值的张量 | 坐标+值(COO格式) | 隐式零值(不存储) |
| RaggedTensor | 可变长度的序列(无零值) | 扁平值+行分区 | 无零值,仅存有效元素 |
indices(坐标)、values(非零值)、dense_shape(密集形状);tf.sparse.reorder重排为行优先顺序;掌握SparseTensor的核心用法,能大幅优化高维稀疏数据的存储和计算效率,是TensorFlow处理大规模数据的必备技能。