Windows微调Qwen2-7B-Instruct-甄嬛

一、下载Anaconda

在下载Anaconda之前建议先将电脑原有的python卸载,避免造成冲突。

之后一直Next即可,不过要记得在环境变量中添加Anaconda(在安装完成之前会有一个Add PATH选项,可以选上)

安装完成之后打开CMD,输入python,看一下能否唤起python(python是由Anaconda支持的)

二、配置环境

打开CMD,创建虚拟环境

conda create -n 虚拟环境名

打开Pycharm,找到python解释器

添加解释器

找到Anaconda中的conda.exe,之后再点击加载环境,选择之前创建的虚拟环境

三、下载模型(以Qwen-7B-Instruct为例)

打开魔塔社区,找到Qwen-7B-Instruct

模型下载脚本

from modelscope import snapshot_download
model_dir = snapshot_download('qwen/qwen2-7b-instruct',local_dir="D:\模型文件夹\Qwen2")

其中local_dir是保存模型文件的地址

四、部署WebDemo

代码如下:

# 导入所需的库
from transformers import AutoTokenizer, AutoModelForCausalLM, GenerationConfig
import torch
import streamlit as st

# 在侧边栏中创建一个标题和一个链接
with st.sidebar:
    st.markdown("## Qwen2 LLM")
    "[开源大模型食用指南 self-llm]()"
    # 创建一个滑块,用于选择最大长度,范围在0到1024之间,默认值为512
    max_length = st.slider("max_length", 0, 1024, 512, step=1)

# 创建一个标题和一个副标题
st.title("💬 Qwen2 Chatbot")
st.caption("🚀 A streamlit chatbot powered by Self-LLM")

# 定义模型路径
mode_name_or_path = r'D:\模型文件夹\Qwen2'


# 定义一个函数,用于获取模型和tokenizer
@st.cache_resource
def get_model():
    # 从预训练的模型中获取tokenizer
    tokenizer = AutoTokenizer.from_pretrained(mode_name_or_path, use_fast=False)
    # 从预训练的模型中获取模型,并设置模型参数
    model = AutoModelForCausalLM.from_pretrained(mode_name_or_path, torch_dtype=torch.bfloat16, device_map="auto")

    return tokenizer, model


# 加载Qwen2-7B-Chat的model和tokenizer
tokenizer, model = get_model()

# 如果session_state中没有"messages",则创建一个包含默认消息的列表
if "messages" not in st.session_state:
    st.session_state["messages"] = [{"role": "assistant", "content": "有什么可以帮您的?"}]

# 遍历session_state中的所有消息,并显示在聊天界面上
for msg in st.session_state.messages:
    st.chat_message(msg["role"]).write(msg["content"])

# 如果用户在聊天输入框中输入了内容,则执行以下操作
if prompt := st.chat_input():
    # 将用户的输入添加到session_state中的messages列表中
    st.session_state.messages.append({"role": "user", "content": prompt})
    # 在聊天界面上显示用户的输入
    st.chat_message("user").write(prompt)

    # 构建输入
    input_ids = tokenizer.apply_chat_template(st.session_state.messages, tokenize=False, add_generation_prompt=True)
    model_inputs = tokenizer([input_ids], return_tensors="pt").to('cuda')
    generated_ids = model.generate(model_inputs.input_ids, max_new_tokens=512)
    generated_ids = [
        output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
    ]
    response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
    # 将模型的输出添加到session_state中的messages列表中
    st.session_state.messages.append({"role": "assistant", "content": response})
    # 在聊天界面上显示模型的输出
    st.chat_message("assistant").write(response)

运行命令:

streamlit run ./chatBot.py --server.address 127.0.0.1 --server.port 6006
#其中./chatBot.py就是WebDemo文件的路径,这里是相对路径,也可写成绝对路径

代码解析:

tokenizer = AutoTokenizer.from_pretrained(mode_name_or_path, use_fast=False)
#mode_name_or_path:该参数就是用于选择作为分词器的模型
#use_fast:该参数为选择是否使用快速分词器,为True时会提高速度,但不支持所有功能

tokenizer是加载了一个分词器,可以简单地将分词器理解为用户的输入经过分词器的转换变成了模型可以理解的张量。具体而言,分词器的作用有:

1. 分词:将输入的文本字符串分割成更小的单元,这些单元可以是单词、子词或者其他有意义的文本片段。例如,单词 "transformers" 可能会被分割成 "trans", "form", "ers" 等子词。

2. 编码:将分词后的文本单元转换为模型可以理解的数值形式。这通常涉及到将文本单元映射到一个预定义的词汇表中的索引。每个索引对应一个特定的词嵌入向量。

3. 添加特殊标记:为了适应特定的任务,如机器翻译或文本生成,分词器可能会在输入的开始或结束添加特殊标记,如 `[BOS]`(句子开始)、`[EOS]`(句子结束)等。

4. 转换为张量:将编码后的序列转换为张量格式,以便可以被深度学习模型处理。这一步通常涉及到将序列转换为固定长度,不足的部分会用特殊标记如 `[PAD]` 填充。

5. 位置编码:在某些模型中,如Transformer,还需要将位置信息编码到输入张量中,以便模型能够理解单词在句子中的顺序。

input_ids = tokenizer.apply_chat_template(st.session_state.messages, tokenize=False, add_generation_prompt=True)

上述代码是利用了聊天模板的apply_chat_template()方法,参数tokenize=False表示该方法不需要对输入进行标记化,add_generation_prompt=True表示在处理文本时添加一个生成提示来引导模型回答。

model_inputs = tokenizer([input_ids], return_tensors="pt").to('cuda')

这段代码是对输入文本进行分词,变成模型可以理解的形式,return_tensors="pt": 这是一个参数,指示tokenizer方法返回的数据类型。在这里,"pt"表示PyTorch张量(tensors)。这意味着tokenizer方法将返回PyTorch框架中的张量对象。.to('cuda'): 这是一个方法调用,用于将数据移动到GPU上。在PyTorch中,.to('cuda')将张量移动到GPU内存中,以便利用GPU加速计算。

generated_ids = model.generate(model_inputs.input_ids, max_new_tokens=512)

model是之前加载的模型,generate是一个方法 ,用于生成文本,该方法用于将输入提供给模型来使模型预测要输出的内容(NLP的本质就是根据上文来推测接下来各种输出的概率,并选择概率大的),max_new_tokens限制了模型单次输出的的最大tokens

    generated_ids = [
        output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
    ]

output_ids[len(input_ids):]是列表切片操作,用于从output_ids列表中提取从len(input_ids)索引开始到列表结束的部分。该操作的目的是获取新生成的token(也就是模型回答的token)。zip(model_inputs.input_ids,generated_ids)是将这两部分打包成元组列表,每个元组包含两个列表中对应位置的元素,这样,就可以在列表推导式中同时遍历输入令牌和生成的令牌。

最后,output_ids[len(input_ids):] for input_ids,output_ids in zip(model_inputs.input_ids,generated_ids)是列表推导式,他提取outpu_ids中新生成的token,并将这些部分收集到新列表

response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]

这段代码是将模型的回答解码成用户可以看明白的输出,skip_special_tokens=True表示batch_decode方法在解码时跳过特殊令牌,特殊令牌是一些在模型训练中用于表示特定功能的令牌,如句子开始和结束标记、填充标记等。设置这个参数为True意味着在解码回文本时,这些特殊令牌不会被包括在内。索引[0]是从batch_decode方法返回的结果中提取第一个元素,因为batch_decode方法返回结果是一个列表,而之前的generated_ids只包含一个token序列,所以只需要第一个解码结果。

五、Windows的Lora微调脚本

from datasets import Dataset
import pandas as pd
from transformers import (AutoTokenizer,AutoModelForCausalLM,DataCollatorForSeq2Seq,TrainingArguments,
                          Trainer,GenerationConfig)
import torch
from peft import LoraConfig, TaskType, get_peft_model

df=pd.read_json(r'D:\数据集\huanhuan-100.json')
ds=Dataset.from_pandas(df)

tokenizer=AutoTokenizer.from_pretrained(r"D:\模型文件夹\Qwen2",
                                        use_fast=False,trust_remote_code=True)
def process_func(example):
    MAX_LENGTH = 384    # Llama分词器会将一个中文字切分为多个token,因此需要放开一些最大长度,保证数据的完整性
    input_ids, attention_mask, labels = [], [], []
    instruction = tokenizer(f"<|im_start|>system\n现在你要扮演皇帝身边的女人--甄嬛<|im_end|>\n<|im_start|>user\n{example['instruction'] + example['input']}<|im_end|>\n<|im_start|>assistant\n", add_special_tokens=False)  # add_special_tokens 不在开头加 special_tokens
    response = tokenizer(f"{example['output']}", add_special_tokens=False)
    input_ids = instruction["input_ids"] + response["input_ids"] + [tokenizer.pad_token_id]
    attention_mask = instruction["attention_mask"] + response["attention_mask"] + [1]  # 因为eos token咱们也是要关注的所以 补充为1
    labels = [-100] * len(instruction["input_ids"]) + response["input_ids"] + [tokenizer.pad_token_id]
    if len(input_ids) > MAX_LENGTH:  # 做一个截断
        input_ids = input_ids[:MAX_LENGTH]
        attention_mask = attention_mask[:MAX_LENGTH]
        labels = labels[:MAX_LENGTH]
    return {
        "input_ids": input_ids,
        "attention_mask": attention_mask,
        "labels": labels
    }

tokenized_id = ds.map(process_func, remove_columns=ds.column_names)

model = AutoModelForCausalLM.from_pretrained(r"D:\模型文件夹\Qwen2", device_map="auto",torch_dtype=torch.bfloat16)
model.enable_input_require_grads() # 开启梯度检查点时,要执行该方法

config = LoraConfig(
    task_type=TaskType.CAUSAL_LM,
    target_modules=["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"],
    inference_mode=False, # 训练模式
    r=8, # Lora 秩
    lora_alpha=32, # Lora alaph,具体作用参见 Lora 原理
    lora_dropout=0.1# Dropout 比例
)

model = get_peft_model(model, config)

model.print_trainable_parameters()

args = TrainingArguments(
    output_dir=r"D:\微调后的模型\Qwen2-7B-甄嬛",
    per_device_train_batch_size=4,
    gradient_accumulation_steps=4,
    logging_steps=10,
    num_train_epochs=3,
    save_steps=100,
    learning_rate=1e-4,
    save_on_each_node=True,
    gradient_checkpointing=True
)

trainer = Trainer(
    model=model,
    args=args,
    train_dataset=tokenized_id,
    data_collator=DataCollatorForSeq2Seq(tokenizer=tokenizer, padding=True),
)

trainer.train()

代码解析:

df=pd.read_json(r'D:\数据集\huanhuan-100.json')

使用Python的Pandas库来读取一个存储在本地的JSON文件,并将其内容加载到一个Pandas DataFrame对象中

ds=Dataset.from_pandas(df)

from_pandas方法是将Pandas DataFrame转换为datasets库中的Dataset对象。

tokenizer=AutoTokenizer.from_pretrained(r"D:\模型文件夹\Qwen2",
                                        use_fast=False,trust_remote_code=True)

加载模型作为分词器,use_fast=False表示不使用快速tokenizer。快速tokenizer可以更快的处理文本,但是不支持所有的模型。trust_remote_code=True该参数表示是否信任远程代码,因为在加载预训练模型时,transformers库可能会从远程服务器下载代码。

instruction = tokenizer(f"<|im_start|>system\n现在你要扮演皇帝身边的女人--甄嬛<|im_end|>\n<|im_start|>user\n{example['instruction'] + example['input']}<|im_end|>\n<|im_start|>assistant\n", add_special_tokens=False)

f"<|im_start|>system\n现在你要扮演皇帝身边的女人--甄嬛<|im_end|>\n<|im_start|>user\n{example['instruction'] + example['input']}<|im_end|>\n<|im_start|>assistant\n": 这是一个格式化字符串,用于构建一个包含多个角色指令的文本。使用了Python的f-string语法来插入变量和文本。字符串中的<|im_start|><|im_end|>是用于标记不同角色发言开始和结束的特殊标记。

add_special_tokens该参数表示在编码文本时是否添加特殊令牌,在NLP中,特殊令牌通常用于表示句子的开始和结束,或者用于分隔句子中的不同部分。

example['instruction'] + example['input']: 使用数据集构建用户角色的发言内容。example是一个字典,它包含了instructioninput两个键,分别对应用户角色的指令和输入文本。

response = tokenizer(f"{example['output']}", add_special_tokens=False)

用分词器将数据集中的回答部分进行编码,使模型可以理解

input_ids = instruction["input_ids"] + response["input_ids"] + [tokenizer.pad_token_id]

instruction["input_ids"]用于获取之前数据集中instruction部分编码的token ID列表,response["input_ids"]用于获取之前数据集中response部分编码的token ID列表

+[tokenizer.pad_token_id],这是一个列表操作,用于在前两个tokenID列表合并后的结果末尾添加一个填充令牌的ID。tokenizer.pad_token_id是tokenizer对象的一个属性,它表示填充令牌的ID。在NLP模型中,填充令牌通常用于确保所有输入序列的长度相同。

总的来说,就是将数据集中的问答编码后的形式合并到一个列表中作为之后模型的输入

attention_mask = instruction["attention_mask"] + response["attention_mask"] + [1]

instruction["attention_mask"]是从之前编码的指令文本(instruction变量)中获取的注意力掩码。注意力掩码是一个与输入序列等长的列表,其中的值通常为0或1。值为1表示对应的输入是实际数据,值为0表示对应的输入是填充数据。response["attention_mask"]是是从之前编码的响应文本(response变量)中获取的注意力掩码。

+[1] 用于在前两个注意力掩码列表合并后的结果末尾添加一个值为1的元素。用于表示在合并后的序列末尾添加的元素(如填充令牌或其他特殊标记)是实际数据,而不是填充数据。

labels = [-100] * len(instruction["input_ids"]) + response["input_ids"] + [tokenizer.pad_token_id]

[-100] * len(instruction["input_ids"]) 这是一个列表,其中包含len(instruction["input_ids"])-100的元素。这个操作通常用于创建一个初始的标签列表,其中每个元素都设置为-100。在Hugging Face的transformers库中,-100通常用作一个特殊的标记,表示在计算损失时忽略对应的标签。这通常用于那些不应该被模型预测的令牌,比如特殊令牌或填充令牌。

+response["input_ids"]这是一个列表操作,用于将数据集中文本(response变量)的tokenID列表添加到初始的标签列表中。这些ID代表了正确的输出标签,用于训练模型。

    if len(input_ids) > MAX_LENGTH:  # 做一个截断
        input_ids = input_ids[:MAX_LENGTH]
        attention_mask = attention_mask[:MAX_LENGTH]
        labels = labels[:MAX_LENGTH]

限制模型单次输出的token

tokenized_id = ds.map(process_func, remove_columns=ds.column_names)

ds是一个Dataset对象,表示已经加载的数据集。

.map(process_func, remove_columns=ds.column_names): 这是Dataset对象的一个方法,用于将一个函数process_func应用到数据集的每个元素上。

remove_columns=ds.column_names用于指定在应用process_func函数后,从结果中移除哪些列。在这里,ds.column_names是数据集ds中所有列名的列表,这意味着process_func处理后的每个样本将只保留新生成的列,原始列将被移除。

model = AutoModelForCausalLM.from_pretrained(r"D:\模型文件夹\Qwen2", device_map="auto",torch_dtype=torch.bfloat16)

加载本地模型,device_map="auto"表示模型自己选择在哪个设备上运行(CPU或GPU,默认是GPU)。torch_dtype=torch.bfloat16用于指定模型使用的PyTorch数据类型。在这里,torch.bfloat16表示使用16位的浮点数

model.enable_input_require_grads()

enable_input_require_grads()是模型实例的一个方法。默认情况下,在PyTorch中,模型的输入不需要计算梯度(requires_grad属性为False),因为通常我们只需要计算模型参数的梯度。方法的作用是将模型输入的requires_grad属性设置为True,这样在模型的前向传播过程中,PyTorch将会计算和存储这些输入的梯度。

config = LoraConfig(
    task_type=TaskType.CAUSAL_LM,
    target_modules=["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"],
    inference_mode=False, # 训练模式
    r=8, # Lora 秩
    lora_alpha=32, # Lora alaph,具体作用参见 Lora 原理
    lora_dropout=0.1# Dropout 比例
)

这里是设置Lora微调的参数

参数名含义
rlora的秩,矩阵A和矩阵B相连接的宽度,r<<d
lora_alpha归一化超参数,lora参数 \Delta Wx会被以\frac{\alpha }{r}归一化,以便减少改变r时需要重新训练的计算量
lora_dropoutlora层的dropout比率
model = get_peft_model(model, config)

当前的模型实例和配置对象传递给get_peft_model方法。函数的返回值(也是一个模型实例)被赋值给变量model

model.print_trainable_parameters()

print_trainable_parameters是模型实例的一个方法。当调用这个方法时,它会打印出模型中所有可训练参数的详细信息,通常包括参数的名称和形状。

args = TrainingArguments(
    output_dir=r"D:\微调后的模型\Qwen2-7B-甄嬛",
    per_device_train_batch_size=4,
    gradient_accumulation_steps=4,
    logging_steps=10,
    num_train_epochs=3,
    save_steps=100,
    learning_rate=1e-4,
    save_on_each_node=True,
    gradient_checkpointing=True
)
参数名含义
output_dir指定了训练过程中保存模型和日志的输出目录。这里的路径使用了原始字符串r,以确保路径中的反斜杠被正确解释。
per_device_train_batch_size指定了每个设备上的训练批次大小。在这个例子中,每个设备将处理4个样本的批次。
gradient_accumulation_steps用于设置梯度累积的步数。梯度累积是一种技术,允许模型在多个前向传播过程中累积梯度,然后一次性执行反向传播,这在内存有限的情况下非常有用。
logging_steps指定了日志记录的频率。每进行10个训练步骤,就会记录一次日志。
num_train_epochs=3指定了训练的轮数。在这个例子中,数据将被遍历3次。
save_steps=100指定了保存模型的频率。每进行100个训练步骤,就会保存一次模型。
learning_rate指定了学习率。学习率是训练过程中用于更新模型权重的步长。
save_on_each_node=True指定是否在每个节点上保存模型。在分布式训练环境中,如果设置为True,则每个节点都会保存模型。
gradient_checkpointing用于启用梯度检查点。梯度检查点是一种优化内存使用的技术,它通过在每次反向传播后丢弃一些中间梯度来减少内存消耗。
trainer = Trainer(
    model=model,
    args=args,
    train_dataset=tokenized_id,
    data_collator=DataCollatorForSeq2Seq(tokenizer=tokenizer, padding=True),
)

创建一个Trainner类实例,train_dataset=tokenized_id是加载前面已经处理好的数据集;data_collator定义如何在每个批次中收集和处理数,DataCollatorForSeq2Seq,专门用于序列到序列(Seq2Seq)任务的数据收集。它处理批次中的多个序列,确保它们可以被模型有效处理。参数tokenizer指定了分词器;padding=True使DataCollatorForSeq2Seq在创建批次时对序列进行填充,使得批次中的所有序列长度相同。

trainer.train()

调用train方法开始微调

六、加载微调后的模型

from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
from peft import PeftModel

model_path = '/root/autodl-tmp/qwen/Qwen2-7B-Instruct/'
lora_path = './output/Qwen2_instruct_lora/checkpoint-10'  # 这里改为你的 lora 输出对应 checkpoint 地址

# 加载tokenizer
tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)

# 加载模型
model = AutoModelForCausalLM.from_pretrained(model_path, device_map="auto", torch_dtype=torch.bfloat16, trust_remote_code=True).eval()

# 加载lora权重
model = PeftModel.from_pretrained(model, model_id=lora_path)

# 将模型移到适当的设备
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)

print("开始对话(输入 '退出' 来结束对话):")
while True:
    prompt = input("你:")
    if prompt == "退出":
        print("对话结束。")
        break

    inputs = tokenizer.apply_chat_template([{"role": "user", "content": prompt}],
                                           add_generation_prompt=True,
                                           tokenize=True,
                                           return_tensors="pt",
                                           return_dict=True).to(device)

    gen_kwargs = {"max_length": 2500, "do_sample": True, "top_k": 1}
    with torch.no_grad():
        outputs = model.generate(**inputs, **gen_kwargs)
        outputs = outputs[:, inputs['input_ids'].shape[1]:]
        response = tokenizer.decode(outputs[0], skip_special_tokens=True)
        print("模型:", response)

代码解析:

model = PeftModel.from_pretrained(model, model_id=lora_path)

模型加载路径选择如图:

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

指定模型和数据运行设备(GPU优先)

model.to(device)

将模型的所有参数和缓冲区转移到指定的设备device上

inputs = tokenizer.apply_chat_template([{"role": "user", "content": prompt}],
                                           add_generation_prompt=True,
                                           tokenize=True,
                                           return_tensors="pt",
                                           return_dict=True).to(device)

add_generation_prompt=True表示tokenizer在处理输入时,是否添加特定的生成提示(generation prompt)。这通常用于指导模型生成文本时的上下文或风格。

tokenize=True表示tokenizer是否应该对输入的文本进行分词处理

return_tensors="pt"指定返回的tensors的类型。在这里,"pt"表示PyTorch tensors,这意味着tokenizer将返回PyTorch的数据结构。

return_dict=True表示tokenizer是否应该以字典的形式返回处理后的数据。

.to(device)是在调用tokenizer方法后,对返回的结果使用.to(device)方法,将数据移动到之前定义的设备(device)上。这通常是必要的,因为模型和数据需要在同一个设备上才能进行计算。

gen_kwargs = {"max_length": 2500, "do_sample": True, "top_k": 1}

"max_length"表示单次输出最大token

"do_sample"表示模型在生成文本时是否应该进行采样。当设置为 True 时,模型在生成每个token时会从概率分布中随机选择,而不是总是选择概率最高的token。这有助于增加生成文本的多样性,避免生成过于确定性和单调的文本。

"top_k"指定在生成每个token时,模型应该考虑的概率最高的token的数量。设置为1,意味着模型在生成每个token时只会考虑概率最高的那个token。这通常会使得生成的文本更加确定性和一致性,但可能会牺牲一些多样性。

with torch.no_grad():
        outputs = model.generate(**inputs, **gen_kwargs)
        outputs = outputs[:, inputs['input_ids'].shape[1]:]
        response = tokenizer.decode(outputs[0], skip_special_tokens=True)
        print("模型:", response)

with torch.no_grad是上下文管理器,用于在代码块执行期间暂时禁用PyTorch的梯度计算功能。因为在推理阶段不需要进行梯度下降优化,因此禁用梯度计算可以减少内存消耗并加快计算速度。

outputs = model.generate(**inputs, **gen_kwargs)该方法用于生成文本,**inputs是将inputs(用户输入)字典中的所有键值对作为参数传递给model.generate方法。**gen_kwargs: 这是将之前定义的生成参数(如max_lengthdo_sampletop_k等)作为参数传递给model.generate方法。

outputs = outputs[:, inputs['input_ids'].shape[1]:],进行切片操作来去除输入部分的token ID,只保留模型生成的部分。inputs['input_ids'].shape[1]: 这是获取输入数据中token ID的第二维的大小,即序列长度。outputs[:, ...]: 这是对outputs进行切片,保留从输入序列长度之后的所有token ID,这些是模型生成的token ID

tokenizer.decode用于对模型输出进行解码,使其变成文字形式。outputs[0]是选择outputs中的第一个序列。skip_special_tokens=True表示在解码过程中跳过特殊token,如开始、结束、填充等token。

七、遇到问题及解决方法

Traceback (most recent call last):

File "D:\PycharmFile\Qwen2\模型微调.py", line 1, in <module> from datasets import Dataset File "D:\Anaconda\envs\Qwen2\Lib\site-packages\datasets\__init__.py", line 18, in <module> from .arrow_dataset import Dataset

File "D:\Anaconda\envs\Qwen2\Lib\site-packages\datasets\arrow_dataset.py", line 60, in <module> import pyarrow as pa

File "D:\Anaconda\envs\Qwen2\Lib\site-packages\pyarrow\__init__.py", line 65, in <module> import pyarrow.lib as _lib ImportError: DLL load failed while importing lib: 找不到指定的程序。

遇到上述问题,我的解决方法是打开CMD,然后唤出python,依次输入问题代码。如:

回车,看是否能正常导入,如果正常,则继续输入下一行;如果报错则将相应库卸载并重新安装,这里我重新安装了pyarrow和datasets两个库

ImportError: huggingface-hub>=0.23.2,<1.0 is required for a normal functioning of this module, but found huggingface-hub==0.23.1.

Try: `pip install transformers -U` or `pip install -e '.[dev]'` if you're working with git main

根据系统给出的建议执行命令

RuntimeError: Failed to import transformers.trainer because of the following error (look up to see its traceback):

cannot import name 'is_mlu_available' from 'accelerate.utils' (D:\Anaconda\envs\Qwen2\Lib\site-packages\accelerate\utils\__init__.py)

pip install -U accelerate

八、参考链接

https://github.com/datawhalechina/self-llm/blob/master/models/Qwen2/05-Qwen2-7B-Instruct%20Lora.ipynb

  • 31
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值