Note: Tiêu đề và nội dung của bài viết này được lấy cảm hứng từ bài viết của sếp mình: "Hướng đi nào cho những người làm AI trong kỉ nguyên của các Super Large Models?". Recommend các bạn nên đọc để tìm thêm những hướng phát triển trong tương lai (nếu các bạn là AI Engineer).
Nếu các bạn chưa đọc phần 1, có thể bắt đầu từ link này trước để có một cái nhìn tổng quan nhất: Lightweight Fine-Tuning: Một hướng đi cho những người làm AI trong kỉ nguyên của các Super Large Models (Phần 1)
Như mình cũng có nói từ phần trước: "Generative AI phát triển, thời đại của những LLM nở rộ, và đây là chiến trường cạnh tranh của những Big Tech mà chúng ta không có cơ hội chen chân vào". Đặc biệt với những mô hình close-source, chỉ cung cấp API thì những nỗ lực duy nhất của chúng ta chỉ là design ra được những prompt template hiệu quả hơn, với kì vọng cho ra được một kết quả đáp ứng được nhu cầu của bản thân.
Một số nỗ lực khác cố gắng dựa vào những mô hình LLM open-source trong quá khứ, dưới sự guide của dữ liệu được sinh bởi những mô hình close-source như ChatGPT, GPT4, ... nhằm đạt được perfomance có thể chấp nhận được. Đặc biệt, sau khi Meta vô tình để lộ source code của LLaMA, hướng đi này đạt được những kết quả đáng kinh ngạc và dần có được sự chú ý của cộng đồng nghiên cứu cũng như các công ty "hơi big" Tech.
Bên cạnh việc cố gắng tạo ra một mô hình open-source LLM baseline tốt, nhiều nhóm nghiên cứu cũng phát triển những thuật toán Lightweight Finetuning, cho phép adapt tốt hơn nhưng yêu cầu cấu hình nhẹ hơn, đưa LLM phổ biến đến mọi người, mọi nhà.
Trong phần trước, mình đã trình bày về những phương pháp prompt-based (P-Tuning, Prompt Tuning, Prefix Tuning), nhưng những phương pháp thật sự tạo được tiếng vang, đưa lightweight finetuning lên đỉnh cao nghiên cứu lại là những phương pháp adapter-based (Adapter, LoRA, ...). Và đó cũng chính là những nội dung mình muốn đào sâu trong bài viết này. Bắt đầu thôi nào!
1. Mở đầu
Để có thể đi xa hơn trong thời đại mới, trong kỉ nguyên của các super LLM này, trước hết chúng ta hãy cùng nhìn lại lịch sử phát triển của GenerativeAI.
-
🎇 2014-2017: Thời kỳ VAE và GAN
Variational Auto-Encoder (VAE) được ra mắt lần đầu vào tháng 12 năm 2013, được coi như tia lửa đã thắp sáng ngòi nổ của GenerativeAI, theo sau đó là sự xuất hiện của Generative Adversarial Network (GAN) vào năm 2014. Ba năm sau đó, GAN thực sự bùng nổ khi xuất hiện hàng loạt các biến thể khác nhau như DCGAN (2015), Wasserstein GAN (2017), ProGAN (2017), ... cũng như phát triển các mô hình GAN giải quyết nhiều lĩnh vực mới như sinh ảnh (pix2pix, 2016 và CycleGAN, 2017), tạo nhạc (MuseGAN, 2017), ...
-
📝 2018-2019: Thời kỳ Transformer
Sau khi Transformer được Google giới thiệu năm 2017, một nhánh phát triển mô hình ngôn ngữ dựa trên decoder của transformer cũng nhanh chóng nổi lên, với sự khởi đầu là GPT-1. Những năm tiếp theo, nhánh này xây dựng các mô hình ngày càng lớn hơn, với GPT-2 (2018, 1.5B tham số) và T5 (2019, 11B tham số) là những ví dụ nổi bật và cũng đạt được những thành tựu nhất định.
-
🤖 2020-2022: Thời kỳ Mô hình Lớn
Thời kỳ này chứng kiến sự kết hợp ý tưởng từ các họ Generative AI khác nhau. Ví dụ, VQ-GAN (2020) mang GAN discriminator vào kiến trúc VQ-VAE và Vision Transformer (2020) cho thấy làm thế nào để huấn luyện một Transformer để hoạt động trên hình ảnh. Hai mô hình được giới thiệu vào năm 2020 đã đặt nền móng cho tất cả các mô hình sinh hình ảnh lớn trong tương lai - DDPM và DDIM. Đặc biệt là sự xuất hiện của Diffusion, mà nổi bật là Stable Diffusion
Ngoài ra, vào khoảng thời gian này, GPT-3 (2020) được phát hành - một Transformer có 175B tham số. Một loạt các mô hình ngôn ngữ lớn khác cũng được tạo ra để cạnh tranh với GPT-3, bao gồm Gopher (2021) và Chinchilla (2022) của DeepMind , LaMDA (2022) và PaLM (2022) của Google và OPT (2022) của Meta. Một số mô hình mã nguồn mở cũng xuất hiện, chẳng hạn như GPT-J (2021) và GPT-NeoX (2022) của EleutherAI và BLOOM (2022) của HuggingFace. Cuối năm 2022, ChatGPT ra đời, cho phép người dùng có những cuộc trò chuyện tự nhiên với AI, đã thực sự thu hút được sự chú ý lớn của công chúng.
Năm 2023 ...
Những dấu mốc đầu tiên đưa LLM đến mọi người, mọi nhà, mở ra kỉ nguyên của Open LLM
- 24/02/2023: Meta khởi chạy LLaMA (Large Language Model Meta AI), public source code nhưng không public weight. Ở thời điểm này, LLaMA chỉ đơn thuần là một mô hình ngôn ngữ, chưa thông qua instruction tuning hay conversation tuning (Để có khả năng giao tiếp như ChatGPT)
- 03/03/2023: Chỉ trong 1 tuần sau đó, LLaMA bị leak và toàn bộ thông tin bị public. Mặc dù đã có những licenses ngăn việc sử dụng LLaMA cho mục đích thương mại, nhưng giờ đây, bất cứ ai đều có thể hiểu và thí nghiệm với LLM
- 12/03/2023: Hơn một tuần sau đó, Artem Andreenko đưa được LLM xuống hoạt động với Raspberry Pi. Tại thời điểm này, mô hình chạy quá chậm để có thể thực hiện được do kích thước mô hình vẫn quá lớn.
- 13/03/2023: Ngay ngày hôm sau, Stanford giới thiệu Alpaca, thực hiện instruction tuning trên LLaMA. Đặc biệt Eric Wang's sử dụng Alpaca kết hợp với LoRA cho phép việc tuning diễn ra chỉ trong vòng vài giờ trên RTX 4090. Một cuộc đua khác bắt đầu diễn ra (cuộc đua mà chúng ta có thể tham gia): tối ưu chi phí finetuning. Và trên hết, sử dụng LoRA cho phép thêm các weight mới vào LLaMA, không còn là bộ weight ban đầu nữa, do đó, không vi phạm licenses được đặt ra và có thể sử dụng ở bất cứ đâu.
- 18/03/2023: Georgi Gerganov sử dụng 4-bit quantization để chạy LLaMA trên CPU MacBook. Đây là giải pháp “no GPU” đầu tiên đủ nhanh để có thể sử dụng trong thực tế
- 19/03/2023: Một nhóm các trường đại học hợp tác, cho ra mắt Vicuna, và sử dụng GPT-4 để đánh giá chất lượng của mô hình. Mặc dù phương pháp gây ra nhiều tranh cãi, nó vẫn được nhận định là giúp cải thiện hơn đáng kể so với các thí nghiệm trước đó
- 28/03/2023: LLaMA-Adapter sử dụng các Parameter Efficient Fine Tuning (PEFT) technique, thực hiện instruction tuning và multimodality chỉ trong 1 giờ, với 1.2M tham số cần học (thật sự ấn tượng).
- ... Và nhiều sự kiện liên tiếp nữa vẫn liên tục cập nhật đến tận bây giờ ... (Các bạn có thể theo dõi timeline của LLM ở đây)
2. Adapter, LoRA
Oke, bây giờ quay lại với chủ đề chính của bài viết này: Adapter based Lightweight Tuning.
Trước tiên sẽ là 2 mô hình cơ sở đầu tiên cho hướng nghiên cứu này, thậm chí trước cả khi LLM trở nên phổ biến rộng rãi như hiện nay
-
Adapter
- Paper: Parameter-Efficient Transfer Learning for NLP (2019 )
- Link: https://arxiv.org/abs/1902.00751
- Github: https://github.com/google-research/adapter-bert
Ý tưởng đằng sau Adapter khá đơn giản, sử dụng một mô hình được tiền huấn luyện lớn (BERT, GPT-3, ...), làm mô hình cơ sở, sau đó tiến hành thêm vào các mô-đun chuyển đổi nhỏ (adpater) giữa các lớp của mô hình. Các mô-đun này bản chất là các mạng nơ-ron hai lớp có kích thước nhỏ hơn nhiều so với các lớp của mô hình cơ sở. Chúng chỉ được huấn luyện cho nhiệm vụ mới, trong khi các tham số của mô hình cơ sở được giữ nguyên. Như vậy, Adapter có thể tạo ra một mô hình gọn nhẹ và linh hoạt, chỉ cần thêm vài tham số có thể huấn luyện cho mỗi nhiệm vụ, và có thể thêm nhiệm vụ mới mà không cần quay lại các nhiệm vụ trước đó.
Một số ưu điểm dễ thấy của Adapter:
- Tiết kiệm tham số và bộ nhớ khi thực hiện transfer learning
- Giữ nguyên các tham số của mô hình cơ sở, do đó giảm thiểu hiện tượng quên các nhiệm vụ trước đó.
- Linh hoạt và có thể dễ dàng mở rộng cho các nhiệm vụ và ngôn ngữ mới.
- Có thể kết hợp với nhiều phương pháp khác nhau để tăng hiệu suất
Tuy nhiên, chúng ta vẫn cần lưu ý một số vấn đề:
- Adapter có thể không phù hợp cho các nhiệm vụ có sự khác biệt lớn so với mô hình cơ sở, khi đó, cần phải finetuning toàn mô hình
- Adapter có thể bị ảnh hưởng bởi sự không tương thích giữa các mô-đun chuyển đổi và các lớp của mô hình cơ sở, do đó cần thiết kế kỹ càng các kiến trúc mô-đun.
Một fact thú vị ở đây, Transformer là mô hình do Google phát triển, đã trở thành 1 thành phần cơ sở không thể thiếu trong các mô hình LLM hiện nay. Và phương pháp Lightweight Finetuning đầu tiên: Adapter, cũng được giới thiệu bởi Google. Nhưng ông lớn này lại đang bị dẫn trước trong cuộc đua công nghệ do chính mình tạo ra 😂
Một số biến thể của Adapter có thể được kể đến như:
-
LoRA
- Paper: LoRA: Low-Rank Adaptation of Large Language Models (2021)
- Link: https://arxiv.org/abs/2106.09685
- Github: https://github.com/microsoft/LoRA
LoRA cũng cùng chung ý tưởng với Adapter, nhưng có đôi chút khác biệt trong cách triển khai. Thay vì sử dụng mạng nơ-ron, LoRA biểu diễn weight updates bằng 2 ma trận nhỏ hơn (gọi là update matrices) thông qua low-rank decomposition. Những ma trận này có thể được huấn luyện để adapt với dữ liệu mới trong khi giữ cho việc ảnh hưởng đến mô hình cơ sở là thấp nhất. Ma trận trọng số ban đầu vẫn được đóng băng và không nhận thêm bất kỳ điều chỉnh nào. Output sau cùng sẽ được kết hợp từ output của cả mô hình cơ sở cũng như output của update matrices.
Về nguyên tắc, "LoRA can be applied to any subset of weight matrices in a neural network to reduce the number of trainable parameters". Tuy nhiên, để đơn giản và hiệu quả hơn, trong các mô hình Transformer, LoRA thường chỉ áp dụng cho các khối Attention. Số lượng trainable params trong một mô hình LoRA phụ thuộc vào kích thước của các low-rank update matrices, được xác định chủ yếu bởi hạng R và số chiều (MxN) của ma trận trọng số ban đầu.
Một số ưu điểm của LoRA khi so với Adapter có thể kể đến như:
- LoRA có độ phức tạp tuyến tính theo số lượng token, trong khi adapters có độ phức tạp bậc hai.
- LoRA không gây ra thêm độ trễ, trong khi adapters tăng thêm chi phí tính toán và bộ nhớ trong quá trình inference.
- LoRA vượt trội hơn adapters trên nhiều nhiệm vụ hiểu và sinh ngôn ngữ tự nhiên, như GLUE, E2E NLG Challenge, DART và WebNLG
Dựa trên 2 mô hình cơ sở này, các nghiên cứu, thí nghiệm liên quan đến Lightweight Finetuning mọc ra như nấm. Nổi bật có thể kể đến LLaMA-Adapter và LLaMA-Adapter-V2, hay gần nhất (1 tuần trước), chúng ta có Q-LoRA (Efficient Finetuning of Quantized LLMs), mô hình cho phép finetuning 1 mô hình 65B tham số, chỉ trong vòng 24 giờ, trên 1 single GPU (48GB VRAM), và đạt được performance 99.3% so với ChatGPT.
3. PEFT: State-of-the-art Parameter-Efficient Fine-Tuning.
OK, có thể kết thúc phần lý thuyết ở đây được rồi. Hi vọng qua các phần giải thích ngắn gọn phía trước, các bạn có thể nắm được ý tưởng chính của Lightweight Finetuning cũng như các hướng phát triển trong tương lai.
Bây giờ chuyển qua công cụ và thực hành một chút. Trong phần này, mình sẽ giới thiệu về PEFT - một thư viện cực mạnh mẽ được HuggingFace phát triển, tích hợp hầu hết các phương pháp Lightweight Finetuning mới nhất hiện nay, bao gồm: P-Tuning, Prompt Tuning, Prefix Tuning, LoRA, AdaLoRA, LLaMA-Adapter, ...
- Homepage: https://huggingface.co/docs/peft/index
- Github: https://github.com/huggingface/peft
(QLoRA cũng được phát triển dựa trên PEFT: QLoRA uses bitsandbytes for quantization and is integrated with Huggingface's PEFT and transformers libraries.)
Một số usecase thú vị sử dụng PEFT (mà các bạn hoàn toàn có thể thực hiện được):
-
Sử dụng 🤗 PEFT LoRA kết hợp với 🤗 Accelerate's DeepSpeed để tuning mô hình bigscience/T0_3B model (3 tỷ tham số) chỉ với 11GB VRAM trên single GPU, ví dụ như Nvidia GeForce RTX 2080 Ti, Nvidia GeForce RTX 3080 - Điều này có nghĩa là chúng ta hoàn toàn có thể thực hiện được trên Google Colab: code
-
Sử dụng 🤗 PEFT LoRA và bitsandbytes, tiến hành INT8 tuning mô hình OPT-6.7b model (6.7 tỷ tham số) in Google Colab: code
-
Sử dụng 🤗 PEFT, thực hiện Stable Diffusion Dreambooth training chỉ với 11GB VRAM, thậm chí có thể giảm xuống 8GB VRAM nếu áp dụng DeepSpeed. Demo
Installation
Việc cài đặt PEFT khá đơn giản, chúng ta có thể sử dụng 2 cách
pip install peft
hoặc
pip install git+https://github.com/huggingface/peft
Quicktour
Một cách tổng quan, để sử dụng PEFT, chúng ta chỉ cần quan tâm 2 yếu tố: PeftConfig và PeftModel
- PeftConfig: Mỗi phương thức 🤗 PEFT được xác định bởi lớp PeftConfig, lưu trữ tất cả các tham số quan trọng để xây dựng PeftModel.
- PeftModel: Một PeftModel được tạo bởi hàm get_peft_model(). Nó lấy một mô hình cơ sở (có thể tải từ 🤗 Thư viện Transformers) - và PeftConfig chứa các hướng dẫn về cấu hình mô hình cho một phương pháp 🤗 PEFT cụ thể.
Mỗi một phương pháp Lightweight Tuning, đều có 1 class config và model riêng (xem thêm tại mục Tunners). Ở đây, chúng ta sẽ lấy 1 ví dụ với LoRA, do đó, chúng ta có LoraConfig
- Import thư viện
from transformers import AutoModelForSeq2SeqLM from peft import get_peft_model, LoraConfig, TaskType model_name_or_path = "bigscience/mt0-large" tokenizer_name_or_path = "bigscience/mt0-large"
- Khởi tạo config
peft_config = LoraConfig( task_type=TaskType.SEQ_2_SEQ_LM, inference_mode=False, r=8, lora_alpha=32, lora_dropout=0.1 )
- Wrap model
model = AutoModelForSeq2SeqLM.from_pretrained(model_name_or_path) model = get_peft_model(model, peft_config) model.print_trainable_parameters()
Output: trainable params: 2359296 || all params: 1231940608 || trainable%: 0.19151053100118282
- Save model
model.save_pretrained("output_dir")
- Inference
from transformers import AutoModelForSeq2SeqLM from peft import PeftModel, PeftConfig peft_model_id = "smangrul/twitter_complaints_bigscience_T0_3B_LORA_SEQ_2_SEQ_LM" config = PeftConfig.from_pretrained(peft_model_id) model = AutoModelForSeq2SeqLM.from_pretrained(config.base_model_name_or_path) model = PeftModel.from_pretrained(model, peft_model_id) tokenizer = AutoTokenizer.from_pretrained(config.base_model_name_or_path) model = model.to(device) model.eval() inputs = tokenizer("Tweet text : @HondaCustSvc Your customer service has been horrible during the recall process. I will never purchase a Honda again. Label :", return_tensors="pt") with torch.no_grad(): outputs = model.generate(input_ids=inputs["input_ids"].to("cuda"), max_new_tokens=10) print(tokenizer.batch_decode(outputs.detach().cpu().numpy(), skip_special_tokens=True)[0])
Output: 'complaint'
Các example chi tiết hơn, các bạn có thể xem ở phần Task Guide ở trang chủ của PEFT.
4. Kết
Done! Seriese kết thúc rồi. Tổng kết lại cả 2 phần của bài viết này, mình đã trình bày về:
- Xu hướng của Generative AI và LLM trong thời đại mới
- Sơ lược 1 chút về toàn bộ quá trình phát triển của Generative AI
- Các hướng nghiên cứu và phương pháp trong Lightweight Finetuning
- Giới thiệu một thư viện mạnh mẽ của HuggingFace cho phép chúng ta ứng dụng PEFT, tự training một model LLM của riêng mình trên 1 GPU cấu hình tầm trung.
- Và vài điều huyên thuyên khác.
Hi vọng bài viết hữu ích và giúp các bạn tìm được một hướng đi để phát triển trong tương lai. Hẹn gặp lại mọi người trong những bài viết tiếp theo (có thể sẽ khá lâu vì dạo này mình cũng hay "thợ lặn"). Nhớ đừng quên upvote bài viết để mình có thể động lực ngoi lên nha. See ya!