训练BiLSTM CRF模型时遇内存错误及零除错误求助
BiLSTM-CRF训练中的两个错误解决方法
一、MemoryError:无法分配31.1 GiB内存
错误原因
报错发生在CTIDatasetForBiLSTMCRF.__padding函数返回np.array(outputs)时,内存耗尽的核心原因:
- 字符串类型内存占用过高:数组元素是
<U3844类型(长度3844的Unicode字符串),单元素内存开销极大,21714×100的数组总需求达31GiB。 - 预生成全量滑动窗口数据:代码对每个句子生成了所有长度为
SEQ_LEN的滑动窗口子序列,样本量暴增且全部以字符串形式驻留内存。
解决方案
- 提前转整数索引:不要先存储字符串数组再转换,在预处理阶段直接用
vocab2idx把字符串转成整数索引。整数类型(如np.int64)内存占用远低于长字符串,能大幅压缩内存需求。修改__data_preprocess或__padding逻辑,优先完成索引转换。 - 动态生成样本而非预存:不在
Dataset的__init__中一次性生成所有滑动窗口数据,改为在__getitem__方法中动态处理当前样本的子序列(或仅做padding,若无需滑动窗口),减少内存驻留数据量。 - 调整滑动窗口策略:若非必须使用滑动窗口,直接将每个句子padding到
SEQ_LEN作为单个样本;若必须用滑动窗口,可限制子窗口数量(如仅取前N个),或用生成器分批处理。 - 减小
SEQ_LEN:根据任务需求适当降低序列长度,减少单样本内存占用。 - 用PyTorch Tensor替代NumPy数组:PyTorch Tensor能更高效管理内存,尤其是GPU环境下,整数Tensor的内存开销更低。
二、ZeroDivisionError:除以零
错误原因
报错出现在训练阶段的loss打印语句中,train_loss除以的分母为0,常见诱因:
- 训练样本数为0:缩减数组大小后,预处理后的训练样本量为0(如滑动窗口逻辑未生成有效样本,或原始
train_data为空)。 - 训练循环未处理任何batch:没有有效batch参与训练,导致
train_loss和分母(如batch数、总样本数)均为0。
解决方案
- 检查数据集有效性:创建
train_dataset后立即打印len(train_dataset),确认是否有样本。若为0,排查:- 原始数据:执行
print(len(train_data)),确认pd.read_csv+dropna后仍有数据。 - 滑动窗口逻辑:句子padding到
SEQ_LEN后,len(data)-sequence_len+1应为1,确保每个句子生成至少一个样本。
- 原始数据:执行
- 修复loss计算逻辑:计算平均loss前先判断分母是否为0,示例代码:
total_batches = len(train_dataloader) if total_batches > 0: avg_train_loss = train_loss / total_batches print(f'Epoch: {epoch}, Train Loss: {avg_train_loss}') else: print(f'Epoch: {epoch}, No valid training batches') - 排查预处理逻辑:检查
__data_std、__padding等函数,确保没有错误过滤或删除所有数据。
内容的提问来源于stack exchange,提问作者igneous spark
相关产品推荐
相关产品推荐

