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

news2024/11/17 5:37:39

一、下载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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2066610.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

3.2.5 宙之CPU的时分复用

点击查看系列文章 》 Interrupt Pipeline系列文章大纲-CSDN博客 3.2.5.1 __primary_switched开始构建0号进程 宙者&#xff0c;古往今来&#xff0c;时间为宙。盘古为了开天辟地&#xff0c;必须分开空间和时间。在时间维度&#xff0c;要对CPU的运行时间进行切分&#xff0c;…

netty编程之自定义编解码器

写在前面 源码 。 本文看下netty如何自定义编解码器。为此netty专门定义抽象类io.netty.handler.codec.MessageToByteEncoder和io.netty.handler.codec.ByteToMessageDecoder,后续我们实现自定义的编解码器就继承这两个类来做。 1&#xff1a;正戏 server 启动类&#xff1a…

卖一辆亏6万搞倾销,极越汽车高管掀了小米汽车遮羞布?

"炮轰解决不了极越销量问题" 作者 | 魏 强 编辑 | 卢旭成 8月22日早9点40分&#xff0c;极越汽车公关负责人徐继业发朋友圈炮轰小米汽车创始人雷军&#xff1a;“雷军这样的企业家&#xff0c;有点公德心和羞耻心好不好&#xff1f;每台车亏6万&#xff0c;亏那么…

Springboot中的mapper与entity难以觉察的匹配问题,困扰我几天时间,形成很大的压力!

最近&#xff0c;应好友邀请&#xff0c;替她做了一个心理疗愈项目的小系统&#xff0c;在编制后台API代码时&#xff0c;遇到了一个不易觉察的问题&#xff0c;终于查找出来&#xff0c;并且解决了&#xff0c;现奉献出来&#xff0c;供大家碰到类似问题&#xff0c;进行参考。…

面试题详解

前言&#xff1a;这一期我们专门来巩固所学知识&#xff0c;同时见识一些面试题。对知识做出一个总结。 1 不创建临时变量交换两个整数 . 第一种方法 #include<stdio.h> int main() {int a 0;int b 0;scanf("%d %d", &a, &b);printf("交换前…

中央空调安装8个标准流程指南

1、内机安装施工队进场第一步就是吊装内机&#xff0c;这里只要注意2个点就可以避免后续问题。 ① 内机离房顶距离不得小于1公分&#xff0c;避免机器运行时与墙顶产生共振。② 内机吊装需考虑百分之一的坡度&#xff0c;接冷凝水的一侧要稍微低一些&#xff0c;避免冷凝水排不…

单个像素的威胁:微小的变化如何欺骗深度学习系统

深度学习&#xff08;DL&#xff09;是人工智能&#xff08;AI&#xff09;的基本组成部分。它的目标是使机器能够执行需要决策机制的任务&#xff0c;这些决策机制往往近似于人类推理。深度学习模型是许多先进应用的核心&#xff0c;例如医疗诊断和自动驾驶汽车。不幸的是&…

饿了么后端登录模块

一、回顾 高并发集群 饿了么后端的登录模块 1、数据库 1. 主从复制(高可用) 2. 传统的主从复制 3. gtids事务型的主从复制 4. 注意 1. server_id唯一 2. 8.x版本需要get_ssl_pub_key 3. 5.x不需要 4. change master to 5. stop | start slave 5. 非交互 import pymy…

uniapp 地图map画出地市轮廓

最近做uniapp项目 H5微信小程序&#xff0c;需要在地图中打点并把相对应的区域轮廓给画出来。 首先查看uniapp官方文档&#xff1a;https://uniapp.dcloud.net.cn/component/map.html 想在uniapp中使用map直接写map标签即可 <view class"page-section page-section-…

CSS实现鼠标hover展开菜单

效果图&#xff1a; HTML源码&#xff1a; 背景图地址需要更改 <!-- 软件介绍 --> <div class"software-box"><div class"software-container"><div class"software-title"><h2>&ldquo; 一个软件搞定所有 &am…

创客匠人老蒋在「IP私域发售六脉神剑落地班」现场金句频出

破认知&#xff0c;提新知&#xff0c;老蒋的观点&#xff0c;再一次带你穿越周期 2024&#xff0c;变革不断&#xff0c;知识服务行业到底该怎么做&#xff1f;「IP私域发售六脉神剑落地班」现场&#xff0c;老蒋作为大课导师&#xff0c;再一次为大家带来了新鲜且颠覆的行业知…

基于SpringBoot的在线笔记网站的设计与实现

目录 项目技术和环境 页面展示 登录注册 管理员页面 用户页面 在线网址 源代码 本系统由十大核心模块构成&#xff0c;包括用户登录与注册模块、个人中心模块、笔记分类与笔记管理模块、笔记详情展示模块、分享协作与收藏管理模块、回收站与用户管理模块&#xff0c;以及…

CoppeliaSim(V-Rep)与ROS1、ROS2接口变迁-2024-

Webots&#xff1a;Webots与ROS1、ROS2接口变迁 Gazebo&#xff1a;Gazebo与ROS1、ROS2接口变迁 ROS1 2016&#xff1a;ROS_Kinetic_18 使用V-Rep3.3.1和Matlab2015b&#xff08;vrep_ros_bridge&#xff09;续 vrep_ros_bridge 插件 一、项目背景与目标 vrep_ros_bridge 是…

[数据集][目标检测]光伏发电板红外图像鸟粪检测数据集VOC+YOLO格式173张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;173 标注数量(xml文件个数)&#xff1a;173 标注数量(txt文件个数)&#xff1a;173 标注类别…

Windows—RAW编程

客服端骨架&#xff1a; #include <iostream> #include <WinSock2.h> #pragma comment(lib,"ws2_32.lib")int main() {WORD wVersionRequested MAKEWORD(2, 2);WSADATA lpWSAData;WSAStartup(wVersionRequested, &lpWSAData);SOCKADDR_IN saddr{ …

如何在没有密码的情况下解锁iPhone?

如果您的 iPhone 被锁定&#xff0c;知道如何在没有密码的情况下解锁它会派上用场。有几种方法可以帮助您重新使用无价的小工具&#xff0c;无论您是忘记了密码&#xff0c;还是现在只想使用手机。这篇博客文章将讨论在 iPhone 上设置密码的价值、忘记密码的典型原因以及在没有…

什么是DDOS攻击?DDOS攻击一小时多少钱?DDOS攻击如何防御?

什么是DDOS攻击? 拒绝服务攻击&#xff08;DDOS&#xff09;亦称洪水攻击&#xff0c;是一种网络攻击手法&#xff0c;其目的在于使目标计算机的网络或系统资源耗尽&#xff0c;使服务暂时中断或停止&#xff0c;导致其正常用户无法访问。当黑客使用网络上两个或以上被攻陷的计…

AWK的高级用法、三剑客总结

1、定义引用变量 -v:声明变量 案例一: 将系统的变量a,在awk里赋值为变量b,然后调用变量b -v 选项将其传递给 awk直接调用的话需要先用双引号再用单引号awk直接定义变量并引用调用函数getline,读取一行数据的时候并不是得到当前行而是当前行的下一行打印整个行面下面含有ro…

mp4怎么转换成mp3?看了就会的8种mp4转mp3方法!

mp4怎么转换成mp3&#xff1f;MP4作为广泛应用的视频格式&#xff0c;在日常娱乐与工作中扮演着重要角色&#xff0c;但它在特定情境下也带来了一些不便&#xff0c;你是否曾遇到过这样的困扰&#xff0c;当视频内容中的画面并非焦点&#xff0c;而你只对其中的音频感兴趣时&am…

鸿蒙Harmony编程开发:服务端证书锁定防范中间人攻击示例

1. TLS通讯中间人攻击及防范简介 TLS安全通讯的基础是基于对操作系统或者浏览器根证书的信任&#xff0c;如果CA证书签发机构被入侵&#xff0c;或者设备内置证书被篡改&#xff0c;都会导致TLS握手环节面临中间人攻击的风险。其实&#xff0c;这种风险被善意利用的情况还是很…