You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于HuggingFace Transformers的大规模DNA序列嵌入提取优化求助

超大规模DNA数据集嵌入提取的内存优化方案

核心方案可行性确认

你提到的流式完成tokenize并逐批提取嵌入、不保存中间token文件的方案完全可行,且能从根源上避免中间分片占用磁盘与内存,更适配6000万+行的超大规模数据集,同时保证最终输出包含Chromosome、label、embeddings三列。

具体实现代码

方案一:Pandas分块流式处理(直接从原始数据端到端生成嵌入)

该方案无需加载全量数据到内存,按固定块大小分批处理,处理完一批立即释放内存并追加写入结果:

import pandas as pd
import torch
import gc
from transformers import AutoTokenizer, AutoModel

# 初始化模型与tokenizer
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
tokenizer = AutoTokenizer.from_pretrained("InstaDeepAI/nucleotide-transformer-500m-human-ref")
model = AutoModel.from_pretrained("InstaDeepAI/nucleotide-transformer-500m-human-ref").to(device)
model.eval()

# 配置参数
chunk_size = 2000  # 可根据内存/显存调整,显存不足则调小
output_columns = ['Chromosome', 'label', 'embeddings']
output_path = "final_embeddings.parquet"

# 初始化输出文件(写入表头)
pd.DataFrame(columns=output_columns).to_parquet(output_path, index=False)

# 分块遍历原始数据(替换为你的数据源路径,比如原element_final对应的存储文件)
for chunk in pd.read_csv("your_large_dna_dataset.csv", chunksize=chunk_size):
    # 保留必要列并过滤空值
    chunk = chunk[['Chromosome', 'sequence', 'label']].dropna()
    
    # 1. 对当前批次序列做tokenize
    tokenized = tokenizer.batch_encode_plus(
        chunk["sequence"].tolist(),
        return_tensors="pt",
        truncation=False,
        padding=False,
        max_length=80
    )
    input_ids = tokenized["input_ids"].to(device)
    
    # 2. 提取嵌入向量
    with torch.no_grad():
        outputs = model(input_ids=input_ids, output_hidden_states=True)
    embeddings = outputs.hidden_states[-1]
    averaged_embeddings = torch.mean(embeddings, dim=1).to(torch.float32).cpu().numpy()
    
    # 3. 整理结果并追加写入输出文件
    chunk['embeddings'] = list(averaged_embeddings)
    result_chunk = chunk[output_columns]
    result_chunk.to_parquet(
        output_path,
        mode='a',
        index=False,
        engine='pyarrow'
    )
    
    # 强制清理内存,避免泄漏
    del tokenized, input_ids, outputs, embeddings, averaged_embeddings, chunk, result_chunk
    torch.cuda.empty_cache()
    gc.collect()

方案二:用IterableDataset流式处理(适配Hugging Face数据集格式)

如果原始数据已转为Hugging Face Dataset,可转为流式数据集处理:

import pandas as pd
import torch
import gc
from datasets import load_dataset
from transformers import AutoTokenizer, AutoModel

# 初始化模型与tokenizer
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
tokenizer = AutoTokenizer.from_pretrained("InstaDeepAI/nucleotide-transformer-500m-human-ref")
model = AutoModel.from_pretrained("InstaDeepAI/nucleotide-transformer-500m-human-ref").to(device)
model.eval()

# 配置参数
batch_size = 2000
output_columns = ['Chromosome', 'label', 'embeddings']
output_path = "final_embeddings.parquet"

# 加载为流式数据集(避免全量加载)
dataset = load_dataset("csv", data_files="your_large_dna_dataset.csv", streaming=True)['train']
dataset = dataset.select_columns(['Chromosome', 'sequence', 'label'])

# 初始化输出文件
pd.DataFrame(columns=output_columns).to_parquet(output_path, index=False)

# 逐批处理流式数据
for batch in dataset.iter(batch_size=batch_size):
    # Tokenize当前批次
    tokenized = tokenizer.batch_encode_plus(
        batch["sequence"],
        return_tensors="pt",
        truncation=False,
        padding=False,
        max_length=80
    )
    input_ids = tokenized["input_ids"].to(device)
    
    # 提取嵌入
    with torch.no_grad():
        outputs = model(input_ids=input_ids, output_hidden_states=True)
    embeddings = outputs.hidden_states[-1]
    averaged_embeddings = torch.mean(embeddings, dim=1).to(torch.float32).cpu().numpy()
    
    # 整理结果并追加写入
    result_df = pd.DataFrame({
        'Chromosome': batch['Chromosome'],
        'label': batch['label'],
        'embeddings': list(averaged_embeddings)
    })
    result_df.to_parquet(
        output_path,
        mode='a',
        index=False,
        engine='pyarrow'
    )
    
    # 清理内存
    del tokenized, input_ids, outputs, embeddings, averaged_embeddings, batch, result_df
    torch.cuda.empty_cache()
    gc.collect()

关键优化点

  • 批次大小适配:根据GPU显存和内存情况调整chunk_size/batch_size,显存不足时可降至1000甚至更低
  • 内存强制清理:每批处理后手动删除临时变量+清理CUDA缓存,避免内存累积泄漏
  • 高效存储格式:用Parquet格式存储嵌入,比CSV占用空间更小,且支持高效追加写入与后续读取
  • 冗余数据剔除:全程仅保留必要列,处理完的临时数据立即删除,减少内存占用

原分片方案的兼容修复(可选)

如果仍想保留分片模式,可将原200分片拆分为更多小分片(比如1000个),同时调小单批处理的batch_size,避免加载分片时内存溢出:

# Step1 修改分片数量
tokenized_dataset.save_to_disk(f"tokenized_elements/tokenized_{ELEMENT}", num_shards=1000)

内容的提问来源于stack exchange,提问作者youtube

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 20:13:10