乐趣区

关于机器学习:谷歌Gemma介绍微调量化和推理

谷歌的最新的 Gemma 模型是第一个应用与 Gemini 模型雷同的钻研和技术构建的开源 LLM。这个系列的模型目前有两种尺寸,2B 和 7B,并且提供了聊天的根本版和指令版。

用一句话来总结 Gemma 就是:学习了 Llama 2 和 Mistral 7B 的长处,应用了更多的 Token 和单词进行了训练了一个更好的 7B(8.5B)模型。所以这篇文章咱们将介绍 Gemma 模型,而后展现如何应用 Gemma 模型,包含应用 QLoRA、推理和量化微调。

Gemma 7B 其实是 8.5B

1、模型细节

谷歌的公布这份技术报告中提供了模型的更多细节

能够看到 Google 总结了每个模型的参数数量,并且辨别了嵌入参数和非嵌入参数。对于 7B 模型,有 7.7B 个非嵌入参数。如果思考参数总数,Gemma 7B 有 8.54B 个参数…

相比之下 Gemma 更靠近 9B。将 Gemma 作为“7B”LLM 公布能够算是一种误导,但这也很好了解,因为必定心愿将本人的 LLM 与之前公布的 7B 进行比拟,而更多的参数往往意味着更好的性能,对吧。

为了便于比拟,咱们总计了其余风行的“7B”模型的参数总数:

  • Llama 2 7B: 6.74B
  • Mistral 7B: 7.24B
  • Qwen-1.5 7B: 7.72B
  • Gemma 7B: 8.54B

能够看到,其实 Gemma 7B 比 Llama 2 7B 多 1.8B 个参数,依照参数越多,性能越好的实践,Gemma 比其余模型好是必然的。

在 google 的报告中还具体介绍了模型的架构:

能够解决多达 8k 个令牌的上下文。为了高效扩大,他们应用了 multi-query attention 和 RoPE 嵌入,并且兼容 FlashAttention-2。

Gemma 的嵌入词表是目前开源模型中最大的,有 256k 个。它比 Llama 2 的词汇量大 8 倍,比 Qwen-1.5 的词汇量大 1.7 倍,而 Qwen-1.5 的词汇量曾经被认为十分大了。除了词汇表大小之外,Gemma 架构十分规范。更大的嵌入词表通常意味着模型被训练成多语言的。然而谷歌却说这些模型次要是为英语工作训练的。

然而依据目前公布的模型来看,谷歌的确在涵盖多种语言的数据上训练了模型,如果针对多语言工作进行微调应该会产生良好的性能。

2、Gemma 的训练数据

Gemma 2B 和 7B 别离承受了 2 万亿个和 6 万亿个 token 的训练。这意味着 Gemma 7B 承受的 token 比 Llama 2 多 3 倍。这里猜想起因如下:

因为词汇表十分大,须要对模型进行更长的训练,以便更好地学习词汇表中所有标记的嵌入。扩充训练的 token 后损失应该还是升高的,这也与词汇表十分大绝对应。咱们能够这么了解词汇表越大,可能须要的训练 token 就越多,当然可能体现就会越好。

对于模型的指令版本,他们对由人类和合成数据组成的指令数据集进行了监督微调,而后进行了基于人类反馈的强化学习(RLHF)。

3、公共测试数据上的体现

谷歌在规范基准上对 Gemma 进行了评估,并将后果与 Llama 2(在论文中拼写为 lama -2…)和 Mistral 7B 进行了比拟。

在大多数工作中,Gemma 7B 比其余模型取得了更好的分数。然而这里有 2 个问题:

1、咱们还是要对这些基准分数持保留态度。因为谷歌没有通知咱们是如何计算这些分数的。

2、还是模型参数问题,8.5B 实践上应该就会比 7B 要好,所以分数进步是很失常的

本地运行 Gemma 2B 和 7B

Hugging Face 的 Transformers 和 vLLM 都曾经反对 Gemma 模型,硬件的要求是 18gb GPU。

咱们先介绍 vLLM

 import time
 from vllm import LLM, SamplingParams
 prompts = ["The best recipe for pasta is"]
 sampling_params = SamplingParams(temperature=0.7, top_p=0.8, top_k=20, max_tokens=150)
 loading_start = time.time()
 llm = LLM(model="google/gemma-7b")
 print("--- Loading time: %s seconds ---" % (time.time() - loading_start))
 generation_time = time.time()
 outputs = llm.generate(prompts, sampling_params)
 print("--- Generation time: %s seconds ---" % (time.time() - generation_time))
 for output in outputs:
     generated_text = output.outputs[0].text
     print(generated_text)
     print('------')

而后是 Transformers

 import torch
 from transformers import AutoTokenizer, AutoModelForCausalLM, set_seed
 set_seed(1234)  # For reproducibility
 prompt = "The best recipe for pasta is"
 checkpoint = "google/gemma-7b"
 tokenizer = AutoTokenizer.from_pretrained(checkpoint)
 model = AutoModelForCausalLM.from_pretrained(checkpoint, torch_dtype=torch.float16, device_map="cuda")
 inputs = tokenizer(prompt, return_tensors="pt").to('cuda')
 outputs = model.generate(**inputs, do_sample=True, max_new_tokens=150)
 result = tokenizer.decode(outputs[0], skip_special_tokens=True)
 print(result)

应用起来都是很简略的,与其余的开源模型根本一样。

Gemma 7B 的量化

AutoGPTQ 和 AutoAWQ 是 GPTQ 和 AWQ 量化最罕用的两个库,但在目前(2.29)它们并不反对 Gemma。所有咱们只能用 bitsandbytes NF4 量化 Gemma 7B。

GGUF 格局的块量化也能够用 llama.cpp 实现。Google 在与原始版本雷同的存储库中公布了 Gemma 的 GGUF 版本。

通过 bitsandbytes 量化 Gemma 7B 依然须要 7.1 GB 的 GPU RAM。所以还是那句话 这个“7B”的叫法是不是正确的呢?

以下是量化加载和推理的代码

 import torch
 from transformers import AutoTokenizer, AutoModelForCausalLM, set_seed, BitsAndBytesConfig
 
 set_seed(1234)  # For reproducibility
 prompt = "The best recipe for pasta is"
 checkpoint = "google/gemma-7b"
 compute_dtype = getattr(torch, "float16")
 bnb_config = BitsAndBytesConfig(
         load_in_4bit=True,
         bnb_4bit_quant_type="nf4",
         bnb_4bit_compute_dtype=compute_dtype,
         bnb_4bit_use_double_quant=True,
 )
 tokenizer = AutoTokenizer.from_pretrained(checkpoint)
 model = AutoModelForCausalLM.from_pretrained(checkpoint, quantization_config=bnb_config, device_map="cuda")
 inputs = tokenizer(prompt, return_tensors="pt").to('cuda')
 outputs = model.generate(**inputs, do_sample=True, max_new_tokens=150)
 result = tokenizer.decode(outputs[0], skip_special_tokens=True)
 print(result)

应用 QLORA 对 Gemma 7B 进行微调

bitsandbytes 量化曾经能够失常应用,所以咱们能够用 QLoRA 对 Gemma 7B 进行微调。当然如果应用很小的训练批大小和较短的 max_seq_length,也能够在消费者硬件上应用 LoRA(即不进行量化)对 Gemma 7B 进行微调。

以下是我应用 Gemma 7B 测试 QLoRA 微调的代码:

 import torch
 from datasets import load_dataset
 from peft import LoraConfig, PeftModel, prepare_model_for_kbit_training
 from transformers import (
     AutoModelForCausalLM,
     AutoTokenizer,
     BitsAndBytesConfig,
     AutoTokenizer,
     TrainingArguments,
 )
 from trl import SFTTrainer
 
 model_name = "google/gemma-7b"
 #Tokenizer
 tokenizer = AutoTokenizer.from_pretrained(model_name, add_eos_token=True, use_fast=True)
 tokenizer.pad_token = tokenizer.eos_token
 tokenizer.pad_token_id =  tokenizer.eos_token_id
 tokenizer.padding_side = 'left'
 ds = load_dataset("timdettmers/openassistant-guanaco")
 compute_dtype = getattr(torch, "float16")
 bnb_config = BitsAndBytesConfig(
         load_in_4bit=True,
         bnb_4bit_quant_type="nf4",
         bnb_4bit_compute_dtype=compute_dtype,
         bnb_4bit_use_double_quant=True,
 )
 model = AutoModelForCausalLM.from_pretrained(model_name, quantization_config=bnb_config, device_map={"": 0}
 )
 model = prepare_model_for_kbit_training(model)
 #Configure the pad token in the model
 model.config.pad_token_id = tokenizer.pad_token_id
 model.config.use_cache = False # Gradient checkpointing is used by default but not compatible with caching
 peft_config = LoraConfig(
         lora_alpha=16,
         lora_dropout=0.05,
         r=16,
         bias="none",
         task_type="CAUSAL_LM",
         target_modules= ['k_proj', 'q_proj', 'v_proj', 'o_proj', "gate_proj", "down_proj", "up_proj"]
 )
 training_arguments = TrainingArguments(
         output_dir="./results_qlora",
         evaluation_strategy="steps",
         do_eval=True,
         optim="paged_adamw_8bit",
         per_device_train_batch_size=4,
         per_device_eval_batch_size=4,
         log_level="debug",
         save_steps=50,
         logging_steps=50,
         learning_rate=2e-5,
         eval_steps=50,
         max_steps=300,
         warmup_steps=30,
         lr_scheduler_type="linear",
 )
 trainer = SFTTrainer(
         model=model,
         train_dataset=ds['train'],
         eval_dataset=ds['test'],
         peft_config=peft_config,
         dataset_text_field="text",
         max_seq_length=512,
         tokenizer=tokenizer,
         args=training_arguments,
 )
 trainer.train()

300 个训练步 (训练批大小为 4 个) 须要不到 1 小时。

总结

许多框架曾经很好地反对 Gemma 模型,GPTQ 和 AWQ 的量化也将很快就会公布的,通过量化后能够在 8gb GPU 上应用 Gemma 7B。

不可否认公布 Gemma 模型是谷歌后退的一步。Gemma 7B 看起来是 Mistral 7B 的一个很好的竞争对手,但咱们不要遗记它也比 Mistral 7B 多 10 亿个参数。另外我始终没想明确 Gemma 2B 的用例是什么,它的性能被其余相似尺寸的模型超过了(这个 2B 可能就真是 2B 了),并且能够看到谷歌这俩模型参数少的性能不行,性能好的参数又多很多。这种文字游戏阐明谷歌在 AI 赛道上确实使落后并且焦急了,而且目前还没有任何的方法进行超过。

这里是谷歌官网公布的 gemma-report,有趣味的能够查看

https://avoid.overfit.cn/post/6921505d228e4daa81e460e1c231eb49

作者:Benjamin Marie

退出移动版