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

GPT2训练报错TypeError:仅单元素整数张量可转为索引的解决方法

GPT2训练报错:TypeError: only integer tensors of a single element can be converted to an index

问题代码

tokenizer = GPT2Tokenizer.from_pretrained('gpt2')
model = GPT2LMHeadModel.from_pretrained('gpt2')

train_data_path = 'train_dataset.txt'

with open(train_data_path, 'r', encoding='utf-8') as file:
    train_text = file.read()

train_encodings = tokenizer(train_text, return_tensors='pt', truncation=True, max_length=128)

train_dataset = TextDataset(
    tokenizer=tokenizer,
    file_path=train_encodings['input_ids'],
    block_size=128,
)

train_loader = DataLoader(train_dataset, batch_size=4, shuffle=True)

optimizer = torch.optim.AdamW(model.parameters(), lr=5e-5)

for epoch in range(3):  # Adjust the number of epochs as needed
    for batch in train_loader:
        inputs = batch["input_ids"]
        labels = batch["labels"]
        outputs = model(inputs, labels=labels)
        loss = outputs.loss
        loss.backward()
        optimizer.step()
        optimizer.zero_grad()

model.save_pretrained('D:/Data Science/2. Notebooks/')
tokenizer.save_pretrained('D:/Data Science/2. Notebooks/')

报错位置及信息

报错行:

train_dataset = TextDataset(tokenizer=tokenizer, file_path=train_encodings['input_ids'], block_size=128,)       
train_loader = DataLoader(train_dataset, batch_size=4, shuffle=True)

错误信息:

TypeError: only integer tensors of a single element can be converted to an index

train_encodings内容:

{'input_ids': tensor([[   42,    72, 16175,  1134, 10662,  1878,    80,  1031,   264, 30102,
             430, 12379, 33133, 21681, 30102,    77,   324,   133,   247,    74,
             334, 15201, 30102,    81,   198,  2202, 21681, 30102,    77,   331,
             263,   521,   133,   247, 28808,    72,   819,    75,   133,   247,
              81,   256,  1134,   346,    76,   133,   247,    75,   312,   343,
             198,   128,   108,   358,    72,   277,  1134, 12769,   299,   133,
             247, 15908,   390,    88, 17062,   133,   247,    77,   198,    48,
           30102,    89, 30102,    75,   479, 25236,   264,   361,   133,   247,
           28781,   133,   247,    81,   220,   133,   247, 18809,   133,   247,
           1225,   133,   247,    81,   133,   247,    74, 28808,    72,   512,
           21681,   331, 34174,    76, 30102, 46481, 21681,   198, 34458, 46481,
           20402,   465,    82,   133,   247,    75,   133,   247,  4372,   133,
             247,  1312, 46481,    75,   133,   247,    81,   308]]), 'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
          1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
          1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
          1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
          1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
          1, 1, 1, 1, 1, 1, 1, 1]])}

错误原因

TextDataset的file_path参数要求传入原始文本文件的路径字符串,它会自动读取文件内容并完成tokenize和分块操作。但你传入的是已经tokenize后的tensor(train_encodings['input_ids']),参数类型不匹配,导致内部处理索引时抛出类型错误。

解决方案

方案1:直接使用TextDataset加载原始文本文件(推荐)

这是TextDataset的标准用法,无需手动提前tokenize,它会自动处理所有流程:

# 替换原train_dataset创建代码
train_dataset = TextDataset(
    tokenizer=tokenizer,
    file_path=train_data_path,  # 传入原始文本文件路径
    block_size=128,
)

train_loader = DataLoader(train_dataset, batch_size=4, shuffle=True)

后续训练循环无需修改,保持原代码即可。

方案2:用TensorDataset处理已编码的数据

如果你已经提前完成了tokenize操作,可以用TensorDataset替代TextDataset,但需要手动处理维度和标签:

from torch.utils.data import TensorDataset

# 提取input_ids并调整维度(原input_ids是[1, 128],去掉多余的batch维度)
input_ids = train_encodings['input_ids'].squeeze(0)
# LM任务中标签与输入一致
labels = input_ids.clone()

# 创建TensorDataset
train_dataset = TensorDataset(input_ids, labels)
train_loader = DataLoader(train_dataset, batch_size=4, shuffle=True)

# 调整训练循环,确保输入维度符合模型要求(模型接受[batch_size, seq_len]格式)
for epoch in range(3):
    for batch in train_loader:
        inputs, labels = batch
        # 增加batch维度
        inputs = inputs.unsqueeze(0)
        labels = labels.unsqueeze(0)
        outputs = model(inputs, labels=labels)
        loss = outputs.loss
        loss.backward()
        optimizer.step()
        optimizer.zero_grad()

注意事项

  • 若训练数据量较大,优先选择方案1,TextDataset会自动处理文本分块、批量tokenize,避免手动处理维度问题。
  • 方案2仅适合小批量已编码数据,需严格确保输入维度与模型要求匹配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 23:14:52