### [Deeplearning.ai GenAI/LLM系列課程筆記](https://learn.deeplearning.ai/) #### [Large Language Models with Semantic Search。大型語言模型與語義搜索 ](https://hackmd.io/@YungHuiHsu/rku-vjhZT) #### [Finetuning Large Language Models。微調大型語言模型](https://hackmd.io/@YungHuiHsu/HJ6AT8XG6) - [為何要微調(Why finetune)](https://hackmd.io/@YungHuiHsu/HJ6AT8XG6) - [微調的適用範圍(Where finetuning fits in)](https://hackmd.io/@YungHuiHsu/Bkfyyh7zp) - [指令調整(Instruction-tuning)](https://hackmd.io/@YungHuiHsu/B18Hg2XMa) - [資料準備(Data preparation)](https://hackmd.io/@YungHuiHsu/ByR-G24GT) - [訓練過程(Training process)](https://hackmd.io/@YungHuiHsu/rJP6F2Vf6) - [評估與迭代(Evaluation and iteration)](https://hackmd.io/@YungHuiHsu/ryfM524Ga) - [考量與開始(Considerations on getting started now)](https://hackmd.io/@YungHuiHsu/r1KGob8fT) --- ### 其他重要參考資源(蒐集中) #### [State of Open Source AI Book - 2023 Edition](https://book.premai.io/state-of-open-source-ai/) --- # Finetuning Large Language Models ## [訓練過程(Training process)](https://learn.deeplearning.ai/finetuning-large-language-models/lesson/6/training-process) ### 課程概要 - 提供完整的訓練流程demo * LLM的訓練過程與其他神經網絡相似,涉及添加訓練數據、計算損失和更新權重 * 使用PyTorch和HuggingFace可以進行深入的模型訓練,且有專用代碼示範 * Lamini Llama庫提供簡化的模型訓練方法,只需三行代碼即可完成 * 訓練後的模型可以在本地保存並加載,並進行微調以提高效 ### 訓練:與其他神經網絡相同(Training: same as other neural networks) ![](https://hackmd.io/_uploads/rJRSReHfT.png =400x) - 訓練過程的核心 * 添加訓練數據:首先,你需要提供一定量的訓練數據,這些數據將用於訓練模型,使其能夠更好地執行特定任務 * 計算損失:模型在初次預測時可能會有所偏差,因此需要計算模型的預測與實際結果之間的差異,這稱為損失 * 透過模型進行反向傳播(Backprop through model):當模型計算出損失後,它將使用反向傳播算法來找出哪些權重和偏差導致了高損失 * 更新權重:根據計算出的損失,模型的權重將進行調整,以改善其預測能力 - 超參數(Hyperparameters) - 學習率(Learning rate) - 這是一個控制模型學習速度的參數。太高的學習率可能會導致模型在訓練過程中忽略某些細節,而太低的學習率則可能會使訓練過程過於緩慢 - 學習率計劃器(Learning rate scheduler) - 這是一種動態調整學習率的方法,通常會在訓練過程中根據某些條件減少學習率 - 優化器超參數(Optimizer hyperparameters) - 這些參數控制優化器的行為,優化器是用於更新模型權重的工具。不同的優化器和其超參數可以影響模型的訓練速度和效果 ### 訓練流程的程式碼示意(Run through general chunks of training process in code) 這邊用的範例是pytorch的訓練流程 ![](https://hackmd.io/_uploads/Bkwq4bBf6.png =400x) - 訓練流程概述 * 設定訓練循環(Epochs):一個epoch代表模型已經過整個訓練數據集一次。根據需要,你可能會多次遍歷整個數據集 * 數據分批(Batching):數據被分成多個小批次,每個批次包含一定數量的數據。這些批次在訓練過程中逐一送入模型 * 模型輸出:將每個批次的數據放入模型以獲得輸出 * 計算損失:根據模型的輸出和真實的答案計算損失 * 反向傳播(Backpropagation):這是一個重要的步驟,用於計算每個參數的梯度 * 更新優化器:使用先前計算的梯度更新模型的參數 - 用Lamini的lib可以簡化到3行 是否又會重演keras很難debug又讓人無法了解細節的問題呢? 總之是加快普及應用,但要做客製化的處理可能還是需要底層點的工具 ```PYTHON= from llama import BasicModelRunner model = BasicModelRunner("EleutherAI/pythia-410m") model.load_data_from_jsonlines("lamini_docs.jsonl", input_key="question", output_key="answer") model.train(is_public=True) ``` ### lab 05_Training_lab_student 直接看使用模型跟推理的部分 - Set up the model, training config, and tokenizer ```py= model_name = "EleutherAI/pythia-70m" training_config = { "model": { "pretrained_name": model_name, "max_length" : 2048 }, "datasets": { "use_hf": use_hf, "path": dataset_path }, "verbose": True } tokenizer = AutoTokenizer.from_pretrained(model_name) tokenizer.pad_token = tokenizer.eos_token train_dataset, test_dataset = tokenize_and_split_data(training_config, tokenizer) ``` - Load the base model ```python= base_model = AutoModelForCausalLM.from_pretrained(model_name) base_model.to(device) ``` - 檢視模型內部 ```text= GPTNeoXForCausalLM( (gpt_neox): GPTNeoXModel( (embed_in): Embedding(50304, 512) (emb_dropout): Dropout(p=0.0, inplace=False) (layers): ModuleList( (0-5): 6 x GPTNeoXLayer( (input_layernorm): LayerNorm((512,), eps=1e-05, elementwise_affine=True) (post_attention_layernorm): LayerNorm((512,), eps=1e-05, elementwise_affine=True) (post_attention_dropout): Dropout(p=0.0, inplace=False) (post_mlp_dropout): Dropout(p=0.0, inplace=False) (attention): GPTNeoXAttention( (rotary_emb): GPTNeoXRotaryEmbedding() (query_key_value): Linear(in_features=512, out_features=1536, bias=True) (dense): Linear(in_features=512, out_features=512, bias=True) (attention_dropout): Dropout(p=0.0, inplace=False) ) (mlp): GPTNeoXMLP( (dense_h_to_4h): Linear(in_features=512, out_features=2048, bias=True) (dense_4h_to_h): Linear(in_features=2048, out_features=512, bias=True) (act): GELUActivation() ) ) ) (final_layer_norm): LayerNorm((512,), eps=1e-05, elementwise_affine=True) ) (embed_out): Linear(in_features=512, out_features=50304, bias=False) ``` - 訓練的各種超參數設定 Setup training - 各種細節都包在class `TrainingArguments`內了,範例code有提供註解,以下摘錄比較重要的參數設定說明 - max_steps=max_steps - 最大訓練步驟數:每一步對應於一批數據的訓練。如果此值不為-1,它將覆蓋num_train_epochs,意味著訓練將在達到這個步驟數時停止 - gradient_accumulation_steps=4 - 梯度累積步驟數:在這麼多的步驟中,梯度將被累積,然後一次性更新模型。這允許使用更大的有效批次大小,而不增加記憶體使用量 - metric_for_best_model="eval_loss" - 用於選擇最佳模型的指標:在這種情況下,它是評估損失 - greater_is_better=False - 指標的方向:對於損失,較低的值是更好的,所以設為False 大致現代模型的各種奇淫巧計(?)都被封裝在裡面了,以前可是手刻了好多功能,相信沒有訓練經驗的人也能很快上手 ```python= training_args = TrainingArguments( # Learning rate learning_rate=1.0e-5, # Number of training epochs num_train_epochs=1, # Max steps to train for (each step is a batch of data) # Overrides num_train_epochs, if not -1 max_steps=max_steps, # Batch size for training per_device_train_batch_size=1, # Directory to save model checkpoints output_dir=output_dir, # Other arguments overwrite_output_dir=False, # Overwrite the content of the output directory disable_tqdm=False, # Disable progress bars eval_steps=120, # Number of update steps between two evaluations save_steps=120, # After # steps model is saved warmup_steps=1, # Number of warmup steps for learning rate scheduler per_device_eval_batch_size=1, # Batch size for evaluation evaluation_strategy="steps", logging_strategy="steps", logging_steps=1, optim="adafactor", gradient_accumulation_steps = 4, gradient_checkpointing=False, # Parameters for early stopping load_best_model_at_end=True, save_total_limit=1, metric_for_best_model="eval_loss", greater_is_better=False ) ``` - 檢視模型占用的記憶體及運算量 - 浮點運算次數(FLOPs)是一個常用於評估模型計算複雜性的指標 - 計算模型在給定的輸入長度和梯度累積步驟下的總浮點運算次數 ```python= model_flops = ( base_model.floating_point_ops( { "input_ids": torch.zeros( (1, training_config["model"]["max_length"]) ) } ) * training_args.gradient_accumulation_steps ) # print(base_model) print("Memory footprint", base_model.get_memory_footprint() / 1e9, "GB") # Memory footprint 0.30687256 GB print("Flops", model_flops / 1e9, "GFLOPs") # Flops 2195.667812352 GFLOPs ``` - 各種材料都丟進`Trainer`內開啟訓練 - 包含模型、資料(訓練與驗證資料)、超參數設定等 - 比較特別的是模型運量也要丟入(model_flops) ```py= trainer = Trainer( model=base_model, model_flops=model_flops, total_steps=max_steps, args=training_args, train_dataset=train_dataset, eval_dataset=test_dataset, ) training_output = trainer.train() ``` 後面的lab範例還包括: - 運行更大的訓練模型並探索調節(Run much larger trained model and explore moderation) - 使用更大的模型進行inference,並探索如何使用調節來改善輸出 - 使用小模型探索調節(Explore moderation using small model) - 使用小型模型進行推斷,並探索如何使用調節來改善輸出。 - 使用Lamini的3行代碼微調模型(Finetune a model in 3 lines of code using Lamini) - 顯示如何使用Lamini的llama庫以極少的代碼進行模型微調 放上一些lab的範例比較不同模型的表現,看看簡單訓練過的小模型表現(trained model) ![](https://hackmd.io/_uploads/ryeHRZSf6.png)