m0_57965808 2026-01-01 19:31 采纳率: 90.9%
浏览 5

大模型在引用处理好的JSON数据文件时报错提示代码格式不对,但我检测没有问题。

大模型在引用我处理好的JSON数据文件时报错,请各位不吝赐教:
Generating train split: 0 examples [00:00, ? examples/s]Failed to load JSON from file 'F:\AI\warhammer--rabbit\KT\CS_data.JSON' with error <class 'pyarrow.lib.ArrowInvalid'>: JSON parse error: Column() changed from object to array in row 0
Generating train split: 0 examples [00:00, ? examples/s]
datasets.exceptions.DatasetGenerationError: An error occurred while generating the dataset; 我的模型代码和JSON数据如下:

from datasets import load_dataset
from transformers import AutoTokenizer
import torch
import os
#os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"  # 清华镜像,国内可访问

# 加载Phi-2的tokenizer(用于文本转数字编码)
tokenizer = AutoTokenizer.from_pretrained("./phi-2")
tokenizer.pad_token = tokenizer.eos_token  # 设置填充符

# 加载数据
data = load_dataset("json", data_files= [
    #"F:\\AI\\warhammer--rabbit\\KT\\KTZG_data.JSON",
    #"F:\\AI\\warhammer--rabbit\\KT\\PHZD_data.JSON",
    #"F:\\AI\\warhammer--rabbit\\KT\\TZB_data.JSON"
    "F:\\AI\\warhammer--rabbit\\KT\\CS_data.JSON"
])["train"]


# 预处理函数:将文本转为模型输入(input_ids和labels)
def preprocess_function(examples):
    # 合并问题和答案(或场景和决策)作为模型的训练样本
    if "question" in examples:
        texts = [f"问:{q}\n答:{a}" for q, a in zip(examples["question"], examples["answer"])]
    else:
        texts = [f"场景:{s}\n决策:{d}" for s, d in zip(examples["scene"], examples["decision"])]

    # 编码文本(截断到512 tokens,Phi-2的最大上下文)
    inputs = tokenizer(texts, truncation=True, max_length=512, padding="max_length")

    # labels与input_ids相同(语言模型训练:预测下一个token)
    inputs["labels"] = inputs["input_ids"].copy()
    return inputs

#Step 3:加载 Phi-2 模型并配置 LoRA
# 应用预处理
tokenized_data = data.map(preprocess_function, batched=True)


from transformers import AutoModelForCausalLM, BitsAndBytesConfig
from peft import LoraConfig, get_peft_model

# 配置4-bit量化(关键!减少显存占用,27亿参数模型量化后仅需~4GB显存)
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,  # 4位量化
    bnb_4bit_use_double_quant=True,  # 双量化,进一步压缩
    bnb_4bit_quant_type="nf4",  # 适合LLM的量化类型
    bnb_4bit_compute_dtype=torch.bfloat16  # 计算精度
)

# 加载Phi-2模型(自动应用量化)
model = AutoModelForCausalLM.from_pretrained(
    "./phi-2",
    quantization_config=bnb_config,
    device_map="auto"  # 自动分配到可用设备(GPU优先)
)

# 配置LoRA参数(核心!)
lora_config = LoraConfig(
    r=8,  # 低秩矩阵的秩(越小参数越少,8-32较常用)
    lora_alpha=32,  # 缩放因子(通常是r的2-4倍)
    target_modules=[  # Phi-2的注意力层名称(必须正确,否则无效)
        "q_proj", "k_proj", "v_proj", "dense"
    ],
    lora_dropout=0.05,  # 防止过拟合
    bias="none",  # 不训练偏置参数
    task_type="CAUSAL_LM"  # 因果语言模型(生成式任务)
)

# 将LoRA应用到模型
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()  # 查看可训练参数(通常只有几百万,占比<0.1%)



#Step 4:设置训练参数并开始训练
from transformers import TrainingArguments, Trainer

# 配置训练参数(根据你的显卡显存调整)
training_args = TrainingArguments(
    output_dir="./phi2_warhammer_lora",  # 模型保存路径
    per_device_train_batch_size=2,  # 单卡批次大小(显存小就设1)
    gradient_accumulation_steps=4,  # 梯度累积(等效增大批次)
    learning_rate=2e-4,  # 学习率(LoRA通常比全量微调大)
    num_train_epochs=3,  # 训练轮次(数据少就3-5轮,避免过拟合)
    logging_steps=10,  # 每10步打印一次日志
    save_steps=100,  # 每100步保存一次模型
    warmup_ratio=0.1,  # 学习率预热(避免初始震荡)
    fp16=True,  # 混合精度训练(加速且省显存)
    report_to="tensorboard"  # 用tensorboard看训练曲线
)

# 初始化Trainer
trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_data  # 预处理好的训练数据
)

# 开始训练!
trainer.train()



#Step 5:保存 LoRA 权重并测试效果
#训练完成后,只会保存 LoRA 的少量参数(几百 MB),而不是整个模型:
# 保存LoRA权重
model.save_pretrained("phi2_warhammer_lora_final")
from peft import PeftModel

tokenizer = AutoTokenizer.from_pretrained("./phi-2")  # ./表示当前目录的phi-2文件夹
tokenizer.pad_token = tokenizer.eos_token

# 加载本地模型(后续微调时的修改),#加载原始Phi-2模型 + LoRA权重
base_model = AutoModelForCausalLM.from_pretrained(
    "./phi-2",  # 本地模型路径
    quantization_config=bnb_config,
    device_map="auto"
)



lora_model = PeftModel.from_pretrained(base_model, "phi2_warhammer_lora_final")

# 提问测试
prompt = "问:射击相位中,目标在掩护地形时,命中判定有什么变化?\n答:"
inputs = tokenizer(prompt, return_tensors="pt").to("cuda")  # 转到GPU
outputs = lora_model.generate(
    **inputs,
    max_new_tokens=100,  # 最大生成长度
    temperature=0.1,  # 越低越稳定(规则类任务适合低温度)
    do_sample=True
)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))

JSON数据:

[{
        "question": "游戏的主要流程被称为什么?",
        "answer": "游戏的主要流程被称为战斗,特工将在这个流程中进行对决并尝试获得胜利。",
        "source": "战斗流程规则:主要流程名称"
    },
    {
        "question": "一场战斗被分成了多少个部分?",
        "answer": "一场战斗被分成了多个转折点。",
        "source": "战斗流程规则:战斗的划分部分"
    }]

  • 写回答

3条回答 默认 最新

  • 檀越@新空间 2026-01-01 19:33
    关注

    晚上好🌙🌙🌙
    本答案参考通义千问

    你遇到的错误信息是:

    Failed to load JSON from file 'F:\AI\warhammer--rabbit\KT\CS_data.JSON' with error <class 'pyarrow.lib.ArrowInvalid'>: JSON parse error: Column() changed from object to array in row 0
    

    这个错误表明在加载 JSON 文件时,数据格式不符合预期。尽管你认为 JSON 是正确的,但可能在某些字段中存在结构不一致的问题(例如:某一行中某个字段从对象变成了数组)。


    问题分析

    1. JSON 格式问题
      错误提示“Column() changed from object to array in row 0”说明在第 0 行中,某个字段从对象(object)变成了数组(array)。这可能是由于以下原因:

      • 某个字段在某些行中是字符串或对象,在另一些行中变成数组。
      • 数据中包含空值、缺失字段或嵌套结构错误。
    2. load_dataset("json", data_files=...) 的行为
      datasets 库会尝试将 JSON 文件解析为表格形式(类似于 DataFrame),如果某列在不同行中的类型不一致,就会报错。

    3. 路径和文件名问题
      虽然你提供的路径是 "F:\\AI\\warhammer--rabbit\\KT\\CS_data.JSON",但注意 Windows 路径中的反斜杠 \ 在 Python 中需要转义,或者使用原始字符串(r"...")。


    🔧 解决方案

    第一步:验证 JSON 文件内容

    请用文本编辑器(如 VS Code 或 Notepad++)打开你的 JSON 文件,检查其格式是否正确,尤其是第 0 行的数据结构是否与其他行一致。

    示例 JSON 结构应为:

    [
      {
        "question": "射击相位中,目标在掩护地形时,命中判定有什么变化?",
        "answer": "当目标位于掩护地形时,命中判定会受到掩护效果的影响,通常会增加命中难度。"
      },
      {
        "question": "如何计算射击距离?",
        "answer": "射击距离由目标与射手之间的直线距离决定,考虑地形因素后可能会有调整。"
      }
    ]
    

    如果你的 JSON 文件中某一行的 questionanswer 字段是数组而不是字符串,就会触发上述错误。


    第二步:确保路径正确并处理反斜杠

    Python 中的反斜杠 \ 需要转义,或者使用原始字符串。建议修改如下:

    data = load_dataset("json", data_files=[
        r"F:\AI\warhammer--rabbit\KT\CS_data.JSON"
    ])["train"]
    

    第三步:手动读取 JSON 并验证数据结构

    你可以先手动读取 JSON 文件,查看其结构是否符合预期,并进行预处理:

    import json
    
    with open(r"F:\AI\warhammer--rabbit\KT\CS_data.JSON", "r", encoding="utf-8") as f:
        data = json.load(f)
    
    # 打印前几条数据,检查结构是否一致
    for item in data[:5]:
        print(item)
    

    如果发现某条数据的字段不是字符串而是数组,可以进行修复:

    for item in data:
        if isinstance(item.get("question"), list):
            item["question"] = " ".join(item["question"])
        if isinstance(item.get("answer"), list):
            item["answer"] = " ".join(item["answer"])
    

    第四步:修改代码以避免格式错误

    如果你无法修改原始 JSON 文件,可以在加载数据时进行预处理,防止 datasets 报错。

    from datasets import Dataset
    
    # 读取 JSON 文件并转换为 Dataset 对象
    with open(r"F:\AI\warhammer--rabbit\KT\CS_data.JSON", "r", encoding="utf-8") as f:
        raw_data = json.load(f)
    
    # 创建 Dataset
    data = Dataset.from_list(raw_data)
    
    # 然后继续使用 data.map()
    tokenized_data = data.map(preprocess_function, batched=True)
    

    第五步:确保字段名称匹配

    你的 preprocess_function 中使用了:

    if "question" in examples:
        texts = [f"问:{q}\n答:{a}" for q, a in zip(examples["question"], examples["answer"])]
    else:
        texts = [f"场景:{s}\n决策:{d}" for s, d in zip(examples["scene"], examples["decision"])]
    

    请确认 JSON 文件中确实包含 questionanswer 字段,或者 scenedecision 字段,否则会导致 KeyError。


    🛠️ 修改后的完整代码示例

    import json
    from datasets import Dataset
    from transformers import AutoTokenizer
    import torch
    import os
    from datasets import load_dataset
    from peft import LoraConfig, get_peft_model
    from transformers import AutoModelForCausalLM, BitsAndBytesConfig, TrainingArguments, Trainer
    
    # 设置路径
    json_path = r"F:\AI\warhammer--rabbit\KT\CS_data.JSON"
    
    # 读取 JSON 文件并转换为 Dataset
    with open(json_path, "r", encoding="utf-8") as f:
        raw_data = json.load(f)
    
    # 预处理:确保字段类型一致
    for item in raw_data:
        if isinstance(item.get("question"), list):
            item["question"] = " ".join(item["question"])
        if isinstance(item.get("answer"), list):
            item["answer"] = " ".join(item["answer"])
    
    # 创建 Dataset
    data = Dataset.from_list(raw_data)
    
    # 加载 tokenizer
    tokenizer = AutoTokenizer.from_pretrained("./phi-2")
    tokenizer.pad_token = tokenizer.eos_token
    
    # 预处理函数
    def preprocess_function(examples):
        if "question" in examples:
            texts = [f"问:{q}\n答:{a}" for q, a in zip(examples["question"], examples["answer"])]
        else:
            texts = [f"场景:{s}\n决策:{d}" for s, d in zip(examples["scene"], examples["decision"])]
    
        inputs = tokenizer(texts, truncation=True, max_length=512, padding="max_length")
        inputs["labels"] = inputs["input_ids"].copy()
        return inputs
    
    # 应用预处理
    tokenized_data = data.map(preprocess_function, batched=True)
    
    # 其余训练部分保持不变...
    

    总结

    | 问题 | 解决方案 | |------|----------| | JSON 格式不一致 | 检查 JSON 文件,确保每行字段类型一致,尤其是 questionanswer | | 路径问题 | 使用原始字符串 r"..." 或转义反斜杠 \ | | 字段名称不匹配 | 确保 JSON 文件中包含 question/answerscene/decision | | 数据结构不一致 | 手动预处理 JSON 数据,确保字段类型统一 |


    如有更多关于 JSON 内容或具体错误日志,欢迎继续提供,我可以进一步帮你定位问题!

    评论

报告相同问题?

问题事件

  • 创建了问题 1月1日