MXNet 稀疏 NDArray 实战指南:CSRNDArray、RowSparseNDArray 与稀疏梯度训练
2026/9/21 16:17:27 网站建设 项目流程
  • 深度学习
  • 机器学习
  • 人工智能

【免费下载链接】mxnet

Lightweight, Portable, Flexible Distributed/Mobile Deep Learning with Dynamic, Mutation-aware Dataflow Dep Scheduler; for Python, R, Julia, Scala, Go, Javascript and more

项目地址:https://gitcode.com/gh_mirrors/mxnet1/mxnet
点击查看免费下载

导读

本指南以 docs/python_docs/python/tutorials/packages/ndarray/sparse/index.rst 所索引的 MXNet 稀疏 NDArray 教程套件为核心,系统讲解两大数据结构——压缩稀疏行格式的CSRNDArray与面向稀疏梯度的RowSparseNDArray——的存储原理、创建方式、存储类型转换与稀疏算子推断机制,并延伸到基于稀疏符号(Sparse Symbol)+ Module API 以及 Gluon API 的完整稀疏训练流程。读完本文,你将掌握稀疏数据从生成、落盘(LibSVM 格式)、批量加载、模型定义到稀疏优化器(lazy_update)的端到端实战能力,并理解stype(storage type)在 MXNet 中如何贯穿张量、符号与优化器三个层次。

该教程套件由index.rst中的toctree聚合了五个文档:csr.mdrow_sparse.mdtrain.mdtrain_gluon.md(含符号训练)等,本文逐一展开并辅以仓库源码佐证。


一、为什么需要稀疏 NDArray:从高维稀疏特征说起

推荐系统、文本分类等真实场景常常面对百万量级的类别与用户维度:例如每个用户只购买过极少量商品,导致数据矩阵中绝大多数元素为零(密度常低至 1% 甚至更低)。用默认稠密结构存储和计算这类矩阵,内存与算力都被大量零值浪费。

MXNet 为此提供了两种专用稀疏张量,二者均继承自NDArray

存储类型(stype)类名适用场景特点
csrCSRNDArray二维矩阵、列数巨大、每行仅少量非零压缩稀疏行格式,显著降低内存、加速矩阵向量乘法
row_sparseRowSparseNDArray多维数组、绝大多数行切片全为零(典型如稀疏梯度)只存非零行切片,配合稀疏优化器实现懒更新
defaultNDArray普通稠密数组默认存储类型

从源码结构看,二者均定义在 python/mxnet/ndarray/sparse.py(class CSRNDArray(BaseSparseNDArray)class RowSparseNDArray(BaseSparseNDArray)),是NDArray的稀疏子类。与 SciPy 的 CSR 实现相比,CSRNDArray继承了NDArray的非阻塞异步求值与自动并行化能力(详见仓库 NDArray 基础教程),并且所有NDArray都新增了stype属性用于标识存储类型:稠密数组为"default",CSR 数组为"csr",行稀疏数组为"row_sparse"


二、CSRNDArray:压缩稀疏行(CSR)格式详解

2.1 存储结构:data / indices / indptr

一个CSRNDArray将二维矩阵拆成三个一维数组:

  • data:按行主序存储所有非零元素;
  • indices:记录data中每个非零元素的列索引(每行内升序排列,同一行不允许出现重复列索引);
  • indptr:行指针数组,indptr[i]表示第i行第一个非零元素在data中的偏移,行i的元素位于data[indptr[i]:indptr[i+1]],对应列索引为indices[indptr[i]:indptr[i+1]]indptr恒以 0 开头,长度恒为“行数 + 1”。

以文档中的 3×4 矩阵为例:

[[7, 0, 8, 0] [0, 0, 0, 0] [0, 9, 0, 0]]

按行主序去掉零值得到data = [7, 8, 9];对应列索引为indices = [0, 2, 1]indptr累计每行非零个数:首行 2 个 →indptr[1]=2,全零行不增长 →indptr[2]=2,末行 1 个 →indptr[3]=3,即indptr = [0, 2, 2, 3]。重建稠密矩阵时,第 0 行取data[0:2]/indices[0:2],第 1 行取data[2:2](空区间,全零行),第 2 行取data[2:3]/indices[2:3]

2.2 创建 CSRNDArray

文档提供了四种主要创建路径(构造函数mx.nd.sparse.csr_matrix在 python/mxnet/ndarray/sparse.py 中支持csr_matrix(D)csr_matrix(S)csr_matrix((M, N))csr_matrix((data, indices, indptr))csr_matrix((data, (row, col)))等多种签名):

import mxnet as mx import numpy as np # 1) 用 Python 列表 + (data, indices, indptr) 三元组创建 shape = (3, 4) a = mx.nd.sparse.csr_matrix(([7, 8, 9], [0, 2, 1], [0, 2, 2, 3]), shape=shape) a.asnumpy() # array([[ 7., 0., 8., 0.], # [ 0., 0., 0., 0.], # [ 0., 9., 0., 0.]], dtype=float32) # 2) 用 NumPy 数组创建 b = mx.nd.sparse.csr_matrix((np.array([7, 8, 9]), np.array([0, 2, 1]), np.array([0, 2, 2, 3])), shape=shape) # 3) 从 SciPy 稀疏矩阵转换(需安装 scipy,否则报 ImportError) import scipy.sparse as spsp c = spsp.csr.csr_matrix((np.array([7, 8, 9]), np.array([0, 2, 1]), np.array([0, 2, 2, 3])), shape=shape) d = mx.nd.sparse.array(c) # mx.nd.sparse.array 支持 scipy.sparse.csr.csr_matrix 输入 # 4) 从稠密数组直接转换:tostype('csr') 自动推导 data/indices/indptr big_array = mx.nd.round(mx.nd.random.uniform(low=0, high=1, shape=(1000, 100))) big_array_csr = big_array.tostype('csr') big_array_csr.data # 访问 data 数组 big_array_csr.indices # 访问列索引数组 big_array_csr.indptr # 访问行指针数组

dtype参数接受 NumPy 类型,默认float32mx.nd.sparse.array(a)得到float32mx.nd.array(a, dtype=np.float16)得到float16

2.3 检查与属性

  • .asnumpy():把稀疏内容填充到稠密numpy.ndarray以便查看;
  • .data/.indices/.indptr:直接查看内部三个分量(均为NDArray);
  • .stype:返回'csr'

2.4 存储类型转换

两种等价方式在defaultcsr之间互转:

ones = mx.nd.ones((2, 2)) csr = ones.tostype('csr') # 方法形式 dense = mx.nd.sparse.cast_storage(ones, 'csr') # 算子形式

2.5 复制与切片

  • a.copy():深拷贝,返回新数组;
  • c[:] = aa.copyto(d):拷贝到已有数组;若源与目标stype不一致,目标stype保持不变(源会被临时转换)。文档中的验证显示e.stypef.stype保持'csr',而g.stype'default'
  • 切片:a[1:2]沿第 0 轴切片并返回新的CSRNDArray;多维索引或沿其他轴切片目前不支持。

2.6 稀疏算子与存储类型推断

专为稀疏实现的算子位于mx.nd.sparse命名空间(如mx.nd.sparse.dotmx.nd.sparse.cast_storagemx.nd.sparse.zeros等,均定义于 python/mxnet/ndarray/sparse.py)。以dot(csr, dense)为例:

a = mx.nd.sparse.csr_matrix(([7, 8, 9], [0, 2, 1], [0, 2, 2, 3]), shape=(3, 4)) rhs = mx.nd.ones((4, 1)) out = mx.nd.sparse.dot(a, rhs) # [[15.], [0.], [9.]] <NDArray 3x1 @cpu(0)>

存储类型推断:稀疏算子的输出stype由输入推导。例如b = a * 2输出仍为csr(零乘 2 还是零),而c = a + mx.nd.ones((3, 4))输出为稠密default。可读算子文档或直接查看输出.stype确认。

存储类型回退(Fallback):不支持稀疏的稠密算子仍可接收稀疏输入,但会临时转为稠密计算;若提供稀疏输出,则把稠密结果再转回稀疏格式,并打印警告(Jupyter 中警告输出到终端控制台)。示例:mx.nd.log(a)输出stype='default',而mx.nd.log(a, out=e)e保持csr

2.7 稀疏数据加载

  • mx.io.NDArrayIter:可直接从CSRNDArray分批读取,batch.data[0]返回CSRNDArray批次;
  • mx.io.LibSVMIter:读取 LibSVM 格式文件,格式为<label> <col_idx1>:<value1> <col_idx2>:<value2> ...,每行记录标签与非零项的“列索引:值”。注意列索引按行升序且为0-based(而非 LibSVM 传统 1-based)。
data_path = 'data.t' with open(data_path, 'w') as fout: fout.write('1.0 0:1 2:2\n') fout.write('1.0 0:3 5:4\n') fout.write('-1 0:0.5 9:1.5\n') # ...更多行 data_train = mx.io.LibSVMIter(data_libsvm=data_path, data_shape=(10,), label_shape=(1,), batch_size=3) for batch in data_train: print(data_train.getdata()) # <CSRNDArray 3x10 @cpu(0)> print(data_train.getlabel())

2.8 GPU 支持

默认所有CSRNDArray算子在 CPU 执行;在 GPU 上创建需显式指定ctxmx.nd.sparse.zeros('csr', (100, 100), ctx=mx.gpu())。无 GPU 时将报错,可改用mx.cpu()


三、RowSparseNDArray:为稀疏梯度而生

3.1 动机:为什么梯度会是“行稀疏”的

X为 1×2 矩阵[[1, 0]]W为 2×3 矩阵,Y = XW。计算dY/dW(即grad_W)时:

grad_W = X.T · ones_like(Y) # [[1, 1, 1], # [0, 0, 0]]

由于X的第 1 列全为零,grad_W的第 1 行全为零。真实场景中,与稀疏输入交互的参数,其梯度常常有大量行切片完全为零。稠密存储与计算浪费在零行上;而 SGD、AdaGrad、Adam 等基于梯度的优化方法可以充分利用稀疏梯度提高效率。RowSparseNDArray正是为“大部分行切片全为零”的数组设计的。

3.2 格式定义

RowSparseNDArray用两个一维数组表示形状为[LARGE0, D1, ..., Dn]的多维数组:

  • data:任意 dtype、形状[D0, D1, ..., Dn],保存所有非零行切片;
  • indices:int64 一维数组、形状[D0],值升序排列,记录非零行切片的行号。

对应稠密关系为:dense[rsp.indices[i], :, :, ...] = rsp.data[i, :, :, ...]。例如 5×3 矩阵中非零行在第 0、2 行,则data = [[1, 2, 3], [4, 0, 5]]indices = [0, 2];它也支持三维及以上张量。查询其stype返回'row_sparse'

3.3 创建与检查

shape = (6, 2) a = mx.nd.sparse.row_sparse_array(([[1, 2], [3, 4]], [1, 4]), shape=shape) # 列表 b = mx.nd.sparse.row_sparse_array((np.array([[1, 2], [3, 4]]), np.array([1, 4])), shape=shape) # NumPy a.asnumpy() # array([[0., 0.], [1., 2.], [0., 0.], [0., 0.], [3., 4.], [0., 0.]]) a.data # [[1, 2], [3, 4]] a.indices # [1, 4]

row_sparse_array构造函数同样定义于 python/mxnet/ndarray/sparse.py,支持row_sparse_array(D)row_sparse_array(S)row_sparse_array((D0, D1, ...))row_sparse_array((data, indices))等签名。其常用方法与CSRNDArray一致:.dtype.asnumpy.data.indices.tostype.cast_storage.copy.copytodtype默认float32

3.4 保留行切片:retain

mx.nd.sparse.retain(rsp, rows)可从RowSparseNDArray中按行号保留指定子集:

rsp = mx.nd.sparse.row_sparse_array(([[1, 2], [3, 4], [5, 6]], [0, 2, 3]), shape=(5, 2)) rsp_retained = mx.nd.sparse.retain(rsp, mx.nd.array([0, 1])) # 仅保留第 0、1 行:[[1, 2], [0, 0], [0, 0], [0, 0], [0, 0]]

3.5 稀疏算子与存储类型推断

mx.nd.sparse.dot(lhs, rhs, transpose_a=True)在输入为csr与稠密时,输出被推断为row_sparse(行稀疏点积结果):

lhs = mx.nd.sparse.csr_matrix(([7, 8, 9], [0, 2, 1], [0, 2, 2, 3]), shape=(3, 5)) rhs = mx.nd.ones((3, 2)) transpose_dot = mx.nd.sparse.dot(lhs, rhs, transpose_a=True) # <RowSparseNDArray 5x2>

与 CSR 相同:a * 2保持row_sparsea + mx.nd.ones(...)回退为稠密;不支持稀疏的稠密算子会触发存储类型回退并打印警告。

3.6 稀疏优化器与懒更新(lazy_update)

MXNet 中,当梯度为row_sparse存储且优化器以lazy_update=True创建时,应用稀疏梯度懒更新:只更新gradient.indices中出现过的行切片对应的权重与状态。以 SGD 为例,稠密更新规则为:

rescaled_grad = learning_rate * rescale_grad * clip(grad, clip_gradient) + weight_decay * weight state = momentum * state + rescaled_grad weight = weight - state

而稀疏梯度下的默认懒更新为:

for row in grad.indices: rescaled_grad[row] = learning_rate * rescale_grad * clip(grad[row], clip_gradient) + weight_decay * weight[row] state[row] = momentum * state[row] + rescaled_grad[row] weight[row] = weight[row] - state[row]

注意:当weight_decaymomentum非零时,懒更新与稠密更新的结果会不同;如需关闭,可在创建优化器时设置lazy_update=False。从 python/mxnet/optimizer/optimizer.py 源码可见,SGDAdamAdaGrad三个优化器的__init__均接收lazy_update=True参数,并在update内部调用sgd_update(weight, grad, out=weight, lazy_update=self.lazy_update, ...)等底层算子;这也是文档明确说明的仅 SGD、Adam、AdaGrad 支持稀疏更新的实现依据。

文档给出的更新示例:权重为 4×2 的row_sparse全 1 矩阵,梯度row_sparse_array(([[1, 2], [4, 5]], [1, 2]))SGD(learning_rate=0.01, momentum=0.01),调用sgd.update(0, weight, grad, momentum)后,只有第 1、2 行的权重与动量被更新(第 0、3 行保持原值),验证了“只更新梯度索引涉及的行”。

3.7 GPU 支持

与 CSR 相同:默认 CPU 执行,创建时需显式指定ctx(如mx.nd.sparse.zeros('row_sparse', (100, 100), ctx=mx.gpu())),无 GPU 时改用mx.cpu()


四、用稀疏符号(Sparse Symbol)训练线性回归

4.1 变量的存储类型

mx.sym.Variablestype属性声明其持有数组的存储格式,默认"default",可设为"csr""row_sparse"

a = mx.sym.Variable('a') # 稠密 b = mx.sym.Variable('b', stype='csr') # CSRNDArray c = mx.sym.Variable('c', stype='row_sparse')# RowSparseNDArray

4.2 绑定与求值:simple_bind

simple_bind(ctx, **shape_dict)实例化执行器,它会按各变量的存储类型分配零数组;executor.forward()求值,executor.outputs取结果,executor.arg_dict可更新变量持有的数组:

b_exec = b.simple_bind(ctx=mx.cpu(), b=(2, 2)) b_exec.forward() # 输出 <CSRNDArray 2x2 @cpu(0)>(零数组) b_exec.arg_dict['b'][:] = mx.nd.ones((2, 2)).tostype('csr') b_exec.forward() # 输出更新为全 1

4.3 符号组合与存储类型推断

稀疏符号位于mx.sym.sparse包。输出存储类型由输入推导:

d = mx.sym.elemwise_add(a, a) # default e = mx.sym.sparse.negative(b) # csr f = mx.sym.sparse.elemwise_add(c, c) # row_sparse add_exec = mx.sym.Group([d, e, f]).simple_bind(ctx=mx.cpu(), a=(2,2), b=(2,2), c=(2,2))

运行后dense_add.stype='default'csr_add.stype='csr'rsp_add.stype='row_sparse'。不支持某稀疏组合的算子(如elemwise_add(csr, row_sparse)log(csr))会回退到稠密实现并打印警告。调试时可将环境变量MXNET_INFER_STORAGE_TYPE_VERBOSE_LOGGING设为"1",让 MXNet 在计算图中记录各算子输入输出的存储类型信息(文档示例:datacsrweightrow_sparsesparse.dot输出的线性分类网络)。

4.4 端到端线性回归:Module API

目标函数为y = x1 + 2x2 + ... + 100x100。完整流程:

# 1) 准备数据:生成 1000 个样本、100 维特征、密度 1% 的 CSR 训练数据 feature_dimension = 100 train_data = mx.test_utils.rand_ndarray((1000, feature_dimension), 'csr', 0.01) target_weight = mx.nd.arange(1, feature_dimension + 1).reshape((feature_dimension, 1)) train_label = mx.nd.dot(train_data, target_weight) train_iter = mx.io.NDArrayIter(train_data, train_label, batch_size=1, last_batch_handle='discard', label_name='label') # 2) 定义模型:变量显式声明存储类型 initializer = mx.initializer.Normal(sigma=0.01) X = mx.sym.Variable('data', stype='csr') Y = mx.symbol.Variable('label') weight = mx.symbol.Variable('weight', stype='row_sparse', shape=(feature_dimension, 1), init=initializer) bias = mx.symbol.Variable('bias', shape=(1,)) pred = mx.sym.broadcast_add(mx.sym.sparse.dot(X, weight), bias) lro = mx.sym.LinearRegressionOutput(data=pred, label=Y, name="lro") # 3) 创建 Module 并初始化 mod = mx.mod.Module(symbol=lro, data_names=['data'], label_names=['label']) mod.bind(data_shapes=train_iter.provide_data, label_shapes=train_iter.provide_label) mod.init_params(initializer=initializer) sgd = mx.optimizer.SGD(learning_rate=0.05, rescale_grad=1.0/1, momentum=0.9) mod.init_optimizer(optimizer=sgd) # 4) 训练 10 轮 metric = mx.metric.create('MSE') for epoch in range(10): train_iter.reset(); metric.reset() for batch in train_iter: mod.forward(batch, is_train=True) mod.update_metric(metric, batch.label) mod.backward() mod.update() print('Epoch %d, Metric = %s' % (epoch, metric.get())) assert metric.get()[1] < 1.0 # 文档中的训练收敛到 MSE ≈ 0.36

其中weight声明为row_sparse的意义在于:权重被初始化为RowSparseNDArray,且优化器会对其执行稀疏更新规则;sparse.dot针对csr输入与row_sparse权重调用稀疏实现。

4.5 多机 / 多设备分布式训练

MXNet 支持带row_sparse权重与梯度的分布式训练,可显著降低大模型的通信开销。多机训练时需在forwardsave_checkpoint之前调用prepare,具体可参考仓库 example/sparse/linear_classification 目录下的示例。


五、Gluon 与稀疏数据:从 LibSVM 落盘到稀疏梯度训练

5.1 生成稀疏数据与内存对比

mx.test_utils.rand_ndarray生成 1000 个样本、每样本 1,000,000 维特征、密度 0.001%(每样本约 10 个非零特征)的 CSR 数据:

num_samples, num_features = 1000, 1000000 data = mx.test_utils.rand_ndarray((num_samples, num_features), stype='csr', density=0.00001) label = data.sum(axis=1) > data.sum(axis=1).mean() # 行和高于均值记为 1

dataindicesindptr分量统计字节数(get_nbytes),同一份数据稠密版约4000 MB,CSR 版仅约0.128 MB——高稀疏场景下约 3 万倍的内存节省。文档同时提醒:当非零比例升高,差距会缩小;当非零占比超过约 1/3 时,稀疏存储反而比稠密更占内存,需按密度谨慎选择。

5.2 写入 LibSVM 格式

自定义save_as_libsvm函数将CSRNDArray逐行写出,每行以标签开头,后接列索引:值的空格分隔对:

def save_as_libsvm(filepath, data, label): with open(filepath, 'w') as openfile: for row_idx in range(data.shape[0]): data_sample, label_sample = data[row_idx], label[row_idx] col_idxs = data_sample.indices.asnumpy().tolist() values = data_sample.data.asnumpy().tolist() value_strs = ['{}:{}'.format(idx, v) for idx, v in zip(col_idxs, values)] openfile.write('{} {}\n'.format(label_sample.asscalar(), " ".join(value_strs)))

落盘文件示例行:0.0 35454:0.22486 80954:0.39130 81941:0.19885 ...。序列化为字符会引入少量开销(示例中 250 KB 文件 vs 原始 132 KB),但与 4 GB 稠密数组相比微不足道。

5.3 用 LibSVMIter 读取稀疏批次

Gluon 的DataLoader目前会在组批前把每个样本转成稠密,因此推荐用mx.io.LibSVMIter直接加载稀疏批次(返回DataBatch而非tuple):

data_iter = mx.io.LibSVMIter(data_libsvm=filepath, data_shape=(num_features,), label_shape=(1,), batch_size=10) for batch in data_iter: print(batch.data[0].stype) # csr print(batch.label[0].stype) # default

此外,稀疏数据从 CPU 迁移到 GPU 也显著更快:文档测得单批稀疏数据约 0.0013 MB、传输约 192 µs,而稠密版约 40 MB、传输约 4 ms(约 25 倍差距,具体数值随硬件与稀疏度变化)。

5.4 自定义稀疏全连接层:FullyConnectedSparse

Gluon 的nn.Dense底层使用FullyConnected算子,并未针对CSRNDArray输入优化。文档实现了一个利用mx.nd.sparse.dot的替代HybridBlock,把权重形状设为(in_units, units)以避免前向中的转置(这是后续获得行稀疏梯度的关键前提):

class FullyConnectedSparse(mx.gluon.HybridBlock): def __init__(self, in_units, units, weight_grad_stype='default'): super(FullyConnectedSparse, self).__init__() with self.name_scope(): self._units = units self.weight = self.params.get('weight', shape=(in_units, units), init=None, allow_deferred_init=True, dtype='float32', stype='default', grad_stype=weight_grad_stype) self.bias = self.params.get('bias', shape=(units), init='zeros', allow_deferred_init=True, dtype='float32', stype='default', grad_stype='default') def hybrid_forward(self, F, x, weight, bias): return F.sparse.dot(x, weight) + bias

三层网络(128 → 8 → 1,sigmoid 激活)对比实验(结果均为文档在特定软硬件环境下的实测值,仅供理解趋势):

方案每轮迭代耗时(timeit 均值)第一层权重内存第一层梯度内存
nn.DenseFullyConnected~532 ms512 MB(99.999%)512 MB(99.999%)
FullyConnectedSparse(前向用 sparse.dot)~528 ms512 MB(99.999%)512 MB(99.999%)
FullyConnectedSparse+weight_grad_stype='row_sparse'~334 ms512 MB0.059 MB(93.49%)

第一层把 1,000,000 维压到 128 维,其权重矩阵占用绝大部分内存;改用sparse.dot后前向显著变快(文档中 Profiler 显示dot+add约 0.26 ms vs 1.54 ms),但反向与参数更新仍处理稠密梯度。将第一层weightgrad_stype设为'row_sparse'后,梯度内存从 512 MB 骤降至约 0.06 MB,参数更新大幅加速,整体迭代从约 532 ms 降至约 334 ms。

5.5 进阶:稀疏 weight

若任务合适,还可进一步把权重本身的stype设为'row_sparse'(是否合理取决于具体任务),仓库 python/mxnet/gluon/contrib/nn/basic_layers.py 中的contrib.SparseEmbedding即此类示例。注意并非所有优化器都支持稀疏梯度,使用前请查阅对应优化器文档。


六、仓库源码速查

主题仓库路径
稀疏 NDArray 教程索引(toctree)docs/python_docs/python/tutorials/packages/ndarray/sparse/index.rst
CSRNDArray 教程docs/python_docs/python/tutorials/packages/ndarray/sparse/csr.md
RowSparseNDArray 教程docs/python_docs/python/tutorials/packages/ndarray/sparse/row_sparse.md
稀疏符号 + Module 训练教程docs/python_docs/python/tutorials/packages/ndarray/sparse/train.md
Gluon 稀疏训练教程docs/python_docs/python/tutorials/packages/ndarray/sparse/train_gluon.md
稀疏张量实现(csr_matrixrow_sparse_arrayzerosarrayretaintostypepython/mxnet/ndarray/sparse.py
稀疏优化器与lazy_update实现(SGD/Adam/AdaGrad)python/mxnet/optimizer/optimizer.py
分布式稀疏训练示例example/sparse/linear_classification

七、总结与选型建议

围绕stype这一贯穿始终的存储类型标识,MXNet 的稀疏能力可分为三层:张量层CSRNDArray用 data/indices/indptr 压缩二维稀疏矩阵,RowSparseNDArray用 data/indices 压缩全零行切片)、符号层mx.sym.sparse中的稀疏算子自动推断输出存储类型,不支持时回退稠密并告警)、优化器层lazy_update只更新梯度索引涉及的行,由 SGD/Adam/AdaGrad 支持)。实操中建议:

  1. 数据密度很低(如 <1%)且每行仅少量非零时优先csr;权重或梯度存在大量全零行切片时使用row_sparse
  2. 使用LibSVMIter/NDArrayIter保持数据端到端稀疏,避免DataLoader的稠密化;
  3. 对稀疏输入的前向计算用mx.nd.sparse.dot替代FullyConnected,并把权重形状设计为(in_units, units)以获得行稀疏梯度,再结合grad_stype='row_sparse'lazy_update优化器显著降低内存与更新开销;
  4. 借助MXNET_INFER_STORAGE_TYPE_VERBOSE_LOGGING=1排查计算图中的存储类型推断与回退情况。
  • 深度学习
  • 机器学习
  • 人工智能

【免费下载链接】mxnet

Lightweight, Portable, Flexible Distributed/Mobile Deep Learning with Dynamic, Mutation-aware Dataflow Dep Scheduler; for Python, R, Julia, Scala, Go, Javascript and more

项目地址:https://gitcode.com/gh_mirrors/mxnet1/mxnet
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询