
在使用bert等大型预训练模型生成长文本词向量时,常遇到内存溢出(oom)问题,尤其是在处理大量数据或长序列时。本文提供一套基于hugging face `transformers`库的标准解决方案,通过合理利用`autotokenizer`和`automodel`进行高效分词与模型推理,并重点介绍如何通过调整批处理大小(batch size)来有效管理gpu内存,确保词向量生成过程的稳定性和效率。
生成BERT模型词向量时,常见的内存溢出(Out of Memory, OOM)问题通常源于以下几个因素:
用户在尝试对包含2370行长文本的数据集生成词向量时,即使设置了max_length=512并尝试使用GPU,仍然遭遇了OutOfMemoryError,这正是上述因素共同作用的结果。错误提示“Tried to allocate 3.47 GiB. GPU 0 has a total capacity of 14.75 GiB of which 3.26 GiB is free. Process 69733 has 11.49 GiB memory in use”清晰地表明现有进程已占用大量GPU内存,导致新的内存分配失败。
为了高效且稳定地生成BERT词向量,推荐使用Hugging Face transformers库提供的AutoModel和AutoTokenizer,它们提供了统一且灵活的接口来处理各种预训练模型。
首先,根据你选择的BERT模型(例如"indolem/indobert-base-uncased"),加载对应的模型和分词器。AutoModel和AutoTokenizer能够自动识别并加载与模型名称匹配的类。
import torch
from transformers import AutoModel, AutoTokenizer
# 假设有一组待处理的文本数据
texts = [
"这是一个示例文本,用于演示如何使用BERT生成词向量。",
"BERT模型在自然语言处理任务中表现出色,但内存管理是关键。",
# ... 更多文本
]
# 加载预训练模型和分词器
# 替换为你要使用的BERT模型名称
model_name = "bert-base-uncased" # 或者 "indolem/indobert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModel.from_pretrained(model_name)
# 如果有GPU可用,将模型移动到GPU
if torch.cuda.is_available():
model.to('cuda')
print("模型已加载到GPU。")
else:
print("GPU不可用,模型将在CPU上运行。")Hugging Face的tokenizer对象可以直接处理文本列表,并提供灵活的参数来控制分词行为。这是推荐的方式,因为它内部优化了批处理和内存使用。
# 对文本进行分词,并进行填充、截断和返回PyTorch张量
tokenized_texts = tokenizer(texts,
max_length=512, # 最大序列长度
truncation=True, # 超过max_length的部分进行截断
padding=True, # 填充到max_length
return_tensors='pt') # 返回PyTorch张量
print(f"分词后的输入ID形状: {tokenized_texts['input_ids'].shape}")
print(f"分词后的注意力掩码形状: {tokenized_texts['attention_mask'].shape}")这里的关键参数:
分词完成后,将input_ids和attention_mask传递给模型进行前向传播。为了节省内存和计算资源,在推理阶段应使用torch.no_grad()上下文管理器。
# 将输入数据移动到GPU(如果模型在GPU上)
if torch.cuda.is_available():
input_ids = tokenized_texts['input_ids'].to('cuda')
attention_mask = tokenized_texts['attention_mask'].to('cuda')
else:
input_ids = tokenized_texts['input_ids']
attention_mask = tokenized_texts['attention_mask']
# 前向传播生成词向量
with torch.no_grad():
outputs = model(input_ids=input_ids,
attention_mask=attention_mask)
# 获取最后一层隐藏状态作为词向量
word_embeddings = outputs.last_hidden_state
# 打印词向量的形状
# 形状通常是 [batch_size, num_seq_tokens, embed_size]
# 例如:[2, 512, 768] 表示批次大小为2,序列长度为512,词向量维度为768
print(f"生成的词向量形状: {word_embeddings.shape}")outputs.last_hidden_state即为模型最后一层的隐藏状态,它包含了每个token对应的上下文嵌入向量。其形状为[batch_size, num_seq_tokens, embed_size],其中embed_size通常为BERT base模型的768。
尽管上述标准流程已经相对优化,但面对极长的文本或极大的数据集,OOM问题仍可能出现。此时,最有效的解决方案是降低批处理大小(Batch Size)。
当整个数据集一次性处理时导致内存不足,可以将其拆分成更小的批次进行迭代处理。这意味着你需要手动控制每次模型推理的数据量。
# 假设原始文本列表为 all_texts
all_texts = [
"这是一个非常长的文本样本,可能导致内存问题...",
# ... 2370行文本
]
# 定义一个合适的批处理大小,例如 8, 16, 32,根据GPU内存调整
batch_size = 16
all_word_embeddings = []
for i in range(0, len(all_texts), batch_size):
batch_texts = all_texts[i:i + batch_size]
# 对当前批次文本进行分词
tokenized_batch = tokenizer(batch_texts,
max_length=512,
truncation=True,
padding=True,
return_tensors='pt')
# 将输入数据移动到GPU
if torch.cuda.is_available():
input_ids_batch = tokenized_batch['input_ids'].to('cuda')
attention_mask_batch = tokenized_batch['attention_mask'].to('cuda')
else:
input_ids_batch = tokenized_batch['input_ids']
attention_mask_batch = tokenized_batch['attention_mask']
# 模型前向传播
with torch.no_grad():
outputs_batch = model(input_ids=input_ids_batch,
attention_mask=attention_mask_batch)
word_embeddings_batch = outputs_batch.last_hidden_state
# 将当前批次的词向量添加到总列表中
all_word_embeddings.append(word_embeddings_batch.cpu()) # 移回CPU以释放GPU内存
# 显式清空CUDA缓存,有助于防止内存碎片化
if torch.cuda.is_available():
torch.cuda.empty_cache()
# 合并所有批次的词向量
final_word_embeddings = torch.cat(all_word_embeddings, dim=0)
print(f"最终合并的词向量形状: {final_word_embeddings.shape}")通过这种迭代方式,每次只将少量数据加载到GPU进行计算,大大降低了单次操作的内存需求。word_embeddings_batch.cpu()操作将结果移回CPU,进一步释放GPU内存,而torch.cuda.empty_cache()则可以清理CUDA内部的缓存,减少内存碎片化。
在BERT模型生成长文本词向量时,内存溢出是常见挑战。通过采用Hugging Face transformers库的标准流程,即使用AutoTokenizer和AutoModel进行高效分词和模型推理,可以构建稳定可靠的词向量生成管道。当遇到内存瓶颈时,最有效的策略是降低批处理大小并分批次处理数据,结合torch.cuda.empty_cache()等内存管理工具,可以显著缓解OOM问题,确保即使在资源受限的环境下也能顺利完成词向量生成任务。
以上就是BERT模型长文本词向量生成与内存优化实践的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号