C/C++教程

Gemma2–2B 在 Colab 上的微调完整指南

本文主要是介绍Gemma2–2B 在 Colab 上的微调完整指南,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

Gemma2–2B 在 Colab 上的微调完整指南

简介

直到去年,开源大型语言模型的能力和效果主要都逊于其闭源的同类模型。目前,开源正在推动向一个新时代的转型。

谷歌于2024年6月发布了最新的顶级开源模型Gemma 2。这些模型提供270亿(27B)和90亿(9B)参数两种版本。自发布以来,27B版本迅速成为LMSYS Chatbot Arena排行榜上最突出的开源模型之一。事实上,它在实际对话中已经超过了参数量是其两倍多的流行模型。

Gemma 2 2B 是 Gemma 家族中一种新的 20 亿参数模型变体。它兼具强大的性能和效率,并且内置了安全改进。

在本文中,我们将使用 unsloth 并进行微调以提取合并收购信息。我们已经使用类似的方法与 Llama 3 进行了尝试。

未进行微调的结果

     ### 安装 Unsloth、Xformers(Flash Attention)和其他所有包!  
    !pip install "unsloth[colab-new] @ git+https://github.com/unslothai/unsloth.git"  
    !pip install --no-deps "xformers<0.0.27" "trl<0.9.0" peft accelerate bitsandbytes  

    ### 安装 Flash Attention 2 以支持软上限  
    import torch  
    if torch.cuda.get_device_capability()[0] >= 8:  
        !pip install --no-deps packaging ninja einops "flash-attn>=2.6.3"  
    ### 加载模型和分词器  
    from unsloth import FastLanguageModel  
    import torch  
    max_seq_length = 2048 # 选择任何值!我们内部自动支持 RoPE Scaling!  
    dtype = None # None 用于自动检测。Float16 用于 Tesla T4,V100,Bfloat16 用于 Ampere+  
    load_in_4bit = True # 使用 4bit 量化以减少内存使用。可以设为 False。  
    model, tokenizer = FastLanguageModel.from_pretrained(  
        model_name = "unsloth/gemma-2-2b-bnb-4bit",  
        max_seq_length = max_seq_length,  
        dtype = dtype,  
        load_in_4bit = load_in_4bit,  
    )  

    ### 指令格式  
    alpaca_prompt = """下面是一个描述任务的指令,附带一个提供更多上下文的输入。编写一个适当完成请求的响应。  

    ### 指令:  
    {}  

    ### 输入:  
    {}  

    ### 响应:  
    {}"""  

    EOS_TOKEN = tokenizer.eos_token # 必须添加 EOS_TOKEN  
    def formatting_prompts_func(examples):  
        instructions = examples["instruction"]  
        inputs       = examples["input"]  
        outputs      = examples["output"]  
        texts = []  
        for instruction, input, output in zip(instructions, inputs, outputs):  
            # 必须添加 EOS_TOKEN,否则生成将无限进行!  
            text = alpaca_prompt.format(instruction, input, output) + EOS_TOKEN  
            texts.append(text)  
        return { "text" : texts, }  
    pass  

    ### mna 新闻和指令  
    mna_news_input = """HCL Technologies 已完成对德国 IT 咨询公司 Gesellschaft für Banksysteme GmbH(“GBS”)51% 股权的收购。收购于 2022 年 1 月 5 日完成。"""  

    mna_news_instruction1 = """收购日期是什么。请精确回答"""  
    mna_news_instruction2 = """哪个公司是收购方。请精确回答"""  

    FastLanguageModel.for_inference(model) # 启用原生 2 倍更快的推理  

    inputs = tokenizer(  
    [  
        alpaca_prompt.format(  
           mna_news_instruction1,  
           mna_news_input,  
            "", # 输出 - 生成时留空!  
        )  
    ], return_tensors = "pt").to("cuda")  

    outputs = model.generate(**inputs, max_new_tokens = 64, use_cache = True)  
    tokenizer.batch_decode(outputs)[0].split("\n\n### 响应:\n")[1].split("\n\n### 解释:\n")[0]  

    ### 输出:收购日期是 2022 年 1 月 5 日。<eos>  
    inputs = tokenizer(  
    [  
        alpaca_prompt.format(  
           mna_news_instruction2,  
           mna_news_input,  
            "", # 输出 - 生成时留空!  
        )  
    ], return_tensors = "pt").to("cuda")  

    outputs = model.generate(**inputs, max_new_tokens = 64, use_cache = True)  
    tokenizer.batch_decode(outputs)[0].split("\n\n### 响应:\n")[1].split("\n\n### 解释:\n")[0]  

    ### 输出:HCL Technologies<eos>

结果非常令人印象深刻,但正如我们在第一次输出中看到的,“收购日期是2022年01月05日。”,我们只想提取日期。有多种方法可以做到这一点,但我们将借助微调来完成。

微调后的结果

     ### 数据集替换为自己的数据集  

    import pandas as pd  
    from pprint import pprint  

    list_ds =[  

    {"instruction":"获取收购日期", "input":"Peak Performance Corporation 收购 Power Forward Corporation 的日期为 28/Jul/2022", "output":"28/Jul/2022"},  
    {"instruction":"获取收购日期", "input":"纽约 - Empire Innovations Inc,一家领先的科技集团,宣布计划于 01MARCH2025 收购 Unique Ventures LLC,一家专注于颠覆性创业公司的知名风险投资公司", "output":"01MARCH2025"},  

    {"instruction":"哪一家公司是收购方", "input":"Peak Performance Corporation 收购 Power Forward Corporation 的日期为 28/Jul/2022", "output":"Peak Performance Corporation"},  
    {"instruction":"哪一家公司是收购方", "input":"Prime Solutions Group 通过战略合并收购 Dynamic Solutions Inc", "output":"Prime Solutions Group"},  
    ]  

    pprint(list_ds)  

    # 安装 Unsloth、Xformers(Flash Attention)和其他所有包  
    !pip install "unsloth[colab-new] @ git+https://github.com/unslothai/unsloth.git"  
    !pip install --no-deps "xformers<0.0.27" "trl<0.9.0" peft accelerate bitsandbytes  

    # 安装 Flash Attention 2 以支持软上限  
    import torch  
    if torch.cuda.get_device_capability()[0] >= 8:  
        !pip install --no-deps packaging ninja einops "flash-attn>=2.6.3"  

    ### 微调  

    from unsloth import FastLanguageModel  
    import torch  
    max_seq_length = 1024 # 选择任何值!我们内部自动支持 RoPE Scaling  
    dtype = None # None 表示自动检测。Float16 适用于 Tesla T4,V100,Bfloat16 适用于 Ampere+  
    load_in_4bit = True # 使用 4bit 量化以减少内存使用。可以设置为 False  

    model, tokenizer = FastLanguageModel.from_pretrained(  
        model_name = "unsloth/gemma-2-2b-bnb-4bit",  
        max_seq_length = max_seq_length,  
        dtype = dtype,  
        load_in_4bit = load_in_4bit,  
        # token = "hf_...", # 如果使用受保护的模型如 meta-llama/Llama-2-7b-hf,请使用 token  
    )  

    model = FastLanguageModel.get_peft_model(  
        model,  
        r = 16, # 选择任何大于 0 的数字!建议 8, 16, 32, 64, 128  
        target_modules = ["q_proj", "k_proj", "v_proj", "o_proj",  
                          "gate_proj", "up_proj", "down_proj",],  
        lora_alpha = 16,  
        lora_dropout = 0, # 支持任何值,但 = 0 是优化的  
        bias = "none",    # 支持任何值,但 = "none" 是优化的  
        # [NEW] "unsloth" 使用 30% 更少的 VRAM,适合 2 倍更大的批处理大小!  
        use_gradient_checkpointing = "unsloth", # True 或 "unsloth" 用于非常长的上下文  
        random_state = 3407,  
        use_rslora = False,  # 我们支持秩稳定的 LoRA  
        loftq_config = None, # 以及 LoftQ  
    )  

    alpaca_prompt = """下面是一个描述任务的指令,以及提供进一步上下文的输入。请编写一个适当完成请求的响应。  

    ### 指令:  
    {}  

    ### 输入:  
    {}  

    ### 响应:  
    {}"""  

    EOS_TOKEN = tokenizer.eos_token # 必须添加 EOS_TOKEN  
    def formatting_prompts_func(examples):  
        instructions = examples["instruction"]  
        inputs       = examples["input"]  
        outputs      = examples["output"]  
        texts = []  
        for instruction, input, output in zip(instructions, inputs, outputs):  
            # 必须添加 EOS_TOKEN,否则生成将无限进行!  
            text = alpaca_prompt.format(instruction, input, output) + EOS_TOKEN  
            texts.append(text)  
        return { "text" : texts, }  
    pass  

    import datasets  
    import pandas as pd  
    # 从字典数组创建数据集  

    df = pd.DataFrame(list_ds)  
    dataset = datasets.Dataset.from_pandas(df)  

    # 打印数据集  
    print(dataset)  
    dataset = dataset.map(formatting_prompts_func, batched = True,)  
    print(dataset)  

    from trl import SFTTrainer  
    from transformers import TrainingArguments  
    from unsloth import is_bfloat16_supported  

    trainer = SFTTrainer(  
        model = model,  
        tokenizer = tokenizer,  
        train_dataset = dataset,  
        dataset_text_field = "text",  
        max_seq_length = max_seq_length,  
        dataset_num_proc = 2,  
        packing = False, # 可以使短序列的训练速度提高 5 倍  
        args = TrainingArguments(  
            per_device_train_batch_size = 2,  
            gradient_accumulation_steps = 4,  
            warmup_steps = 5,  
            # num_train_epochs = 1, # 设置此值以进行一次完整的训练  
            max_steps = 60,  
            learning_rate = 2e-4,  
            fp16 = not is_bfloat16_supported(),  
            bf16 = is_bfloat16_supported(),  
            logging_steps = 1,  
            optim = "adamw_8bit",  
            weight_decay = 0.01,  
            lr_scheduler_type = "linear",  
            seed = 3407,  
            output_dir = "outputs",  
        ),  
    )  
    #### 实际训练  
    trainer_stats = trainer.train()  

    ##### 结果  

    FastLanguageModel.for_inference(model)  

    mna_news_input = """HCL Technologies 已完成对德国 IT 咨询公司 Gesellschaft für Banksysteme GmbH (“GBS”) 51% 股权的收购。收购日期为 2022 年 1 月 5 日。"""  

    mna_news_instruction1 = """获取收购日期。请精确回答"""  
    mna_news_instruction2 = """哪一家公司是收购方。请精确回答"""  

    inputs = tokenizer(  
    [  
        alpaca_prompt.format(  
           mna_news_instruction1,  
           mna_news_input,  
            "", # 输出 - 生成时留空!  
        )  
    ], return_tensors = "pt").to("cuda")  

    outputs = model.generate(**inputs, max_new_tokens = 64, use_cache = True)  
    tokenizer.batch_decode(outputs)[0].split("\n\n### 响应:\n")[1].split("\n\n### 解释:\n")[0]  
    ### 输出 : January 05, 2022<eos>  
    ### 上面的结果非常好,正是我们想要的  

    inputs = tokenizer(  
    [  
        alpaca_prompt.format(  
           mna_news_instruction2,  
           mna_news_input,  
            "", # 输出 - 生成时留空!  
        )  
    ], return_tensors = "pt").to("cuda")  

    outputs = model.generate(**inputs, max_new_tokens = 64, use_cache = True)  
    tokenizer.batch_decode(outputs)[0].split("\n\n### 响应:\n")[1].split("\n\n### 解释:\n")[0]  
    ### 输出 : HCL Technologies<eos>  

结论

我们通过微调得到了精确的结果。太棒了。使用T4和仅20亿参数的模型,效果更令人惊叹。

Colab ::COLAB:: 翻译为
COLAB::

这里保持了原始的双冒号格式,但由于直接翻译会有些不自然,建议直接保留原始格式或根据具体使用场景调整。如果必须翻译,可以理解为“谷歌协同”或“谷歌协作”,但根据上下文,这里可能更适合保留原始格式。

Google ColabEdit 描述colab.research.google.com Google ColabEdit 描述colab.research.google.com
这篇关于Gemma2–2B 在 Colab 上的微调完整指南的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!