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

PyTorch DataLoader训练遇UserWarning:列表转张量过慢问题求助

解决PyTorch DataLoader训练时的"从numpy数组列表创建张量过慢"警告

警告信息

/usr/local/lib/python3.10/dist-packages/sentence_transformers/SentenceTransformer.py:547:
UserWarning: Creating a tensor from a list of numpy.ndarrays is
extremely slow. Please consider converting the list to a single
numpy.ndarray with numpy.array() before converting to a tensor.
(Triggered internally at ../torch/csrc/utils/tensor_new.cpp:245.)
labels = torch.tensor(labels)

用户代码

from torch.utils.data import DataLoader
from sentence_transformers import losses
from sentence_transformers import ParallelSentencesDataset
from sentence_transformers import models
from sentence_transformers import SentenceTransformer

xlmr = models.Transformer('xlm-roberta-base')
pooler = models.Pooling(
    xlmr.get_word_embedding_dimension(),
    pooling_mode_mean_tokens=True
)

student = SentenceTransformer(modules=[xlmr, pooler])
teacher = SentenceTransformer('paraphrase-distilroberta-base-v2')

data = ParallelSentencesDataset(
    student_model=student,
    teacher_model=teacher,
    batch_size=32,
    use_embedding_cache=True
)
data.load_data('/path/to/somefile', max_sentence_length=512)

loader = DataLoader(data, shuffle=True, batch_size=32)
loss = losses.MSELoss(model=student)
  
epochs=1
student.fit(
    train_objectives=[(loader, loss)],
    epochs=epochs,
    warmup_steps=int(len(loader) * epochs * 0.1), # 10% of data
    output_path='./xlmr-ted',
    optimizer_params={'lr': 2e-5, 'eps': 1e-6},
    save_best_model=True,
    show_progress_bar=True
)

解决方案

警告根源是ParallelSentencesDataset生成的批量标签是numpy数组的列表,而非单个numpy数组,导致torch.tensor()转换效率低下。以下是几种可行方案:

方案1:自定义数据集的collate函数

通过包装原数据集,重写批量处理逻辑,将标签列表转换为单个numpy数组后再转张量:

import numpy as np
from torch.utils.data import Dataset

class NumpyArrayDataset(Dataset):
    def __init__(self, base_dataset):
        self.base_dataset = base_dataset
    
    def __len__(self):
        return len(self.base_dataset)
    
    def __getitem__(self, idx):
        return self.base_dataset[idx]
    
    def collate_fn(self, batch):
        # 拆分输入与标签
        inputs = [item[0] for item in batch]
        labels = [item[1] for item in batch]
        
        # 将标签列表转为单个numpy数组
        labels = np.array(labels)
        return inputs, labels

修改DataLoader的创建代码:

wrapped_data = NumpyArrayDataset(data)
loader = DataLoader(wrapped_data, shuffle=True, batch_size=32, collate_fn=wrapped_data.collate_fn)

方案2:预计算教师模型嵌入(更高效)

利用use_embedding_cache=True的特性,提前计算所有教师模型的嵌入并保存为单个numpy数组,避免动态生成数组列表:

# 预计算所有句子的教师嵌入,直接得到numpy数组
teacher_embeddings = teacher.encode(data.sentences, batch_size=32, convert_to_numpy=True)
# 替换数据集的缓存嵌入
data.teacher_embeddings = teacher_embeddings

# 正常创建DataLoader即可,此时批量标签会直接是数组切片,转换张量时无性能问题

方案3:修改源码(不推荐)

直接修改SentenceTransformer.py第547行的代码,将标签列表转为numpy数组后再转张量:

import numpy as np
labels = torch.tensor(np.array(labels))

此方法依赖特定版本的源码,库更新后会失效,不建议采用。

方案1和方案2均可有效解决警告,方案2还能减少训练时的重复计算,进一步提升整体训练效率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 05:42:45