文章目錄
- 什么是GRPO
- 群組形成(Group Formation):讓大模型創建多種解決方案
- 偏好學習(Preference Learning):讓大模型理解何為好的解答
- 組內相對優勢
- 優化(optimization): 讓大模型從經驗中學習(learning from experience)
- 目標函數
- GRPO算法的偽碼表示
- GRPO算法的局限與挑戰
- 代碼實現
- GRPO訓練參數配置
- GRPO訓練器
- token對數概率計算
- 獎勵矩陣計算
- 組內優勢計算
- 計算損失函數
- 案例實戰:使用TRL庫實現GRPO訓練文本生成模型
- 推薦閱讀
- REF
什么是GRPO
GRPO(Groupwise relative policy optimization)群組相對策略優化是deepseek提出的一種RLHF(基于人類反饋的強化學習)技術。首次提出是在DeepSeekMath中,RL被證明在SFT階段后能有效提升LLM的數學推理能力。
在GRPO提出之前,有兩種流行的RLHF技術被廣泛用于大模型的對齊過程中,分別是PPO和DPO。
群組形成(Group Formation):讓大模型創建多種解決方案
GRPO算法的第一步非常直觀,類似于學生嘗試多種解法去解決同一個問題。對于給定的prompt,讓大模型嘗試生成多種解答(attempt)來解決同一個問題(通常4、8或16種的不同解答)。不同的解答示例如下圖所示。
偏好學習(Preference Learning):讓大模型理解何為好的解答
與其他的RLHF方法需要一個單獨的獎勵模型(reward model)不同,GRPO方法可以使用任何函數或模型來評估LLM解答(Solution)的質量。例如,可以使用一個長度函數作為評估器來獎勵模型生成更簡短的解答,或是使用一個數學求解器,來獎勵模型生成更準確的數學解答方案。
評估過程會從多個角度來衡量大模型生成解答方案的質量,包括:
1)最終答案是否正確;2)答案是否按指定的格式輸出(如XML標簽格式正確性);3)推理過程與提供的答案是否一致。
組內相對優勢
這種處理方式的巧妙之處還在于評分機制,GRPO不是簡單的給出絕對分數,而是對每個組內的獎勵進行歸一化處理。它采用了一個簡單但有效的方法來計算組內相對優勢:
A d v a t a g e = ( r e w a r d ? m e a n ( g r o u p r e w a r d s ) / s t d ( g r o u p r e w a r d s ) Advatage = (reward- mean(group_rewards)/ std(group_rewards) Advatage=(reward?mean(groupr?ewards)/std(groupr?ewards)
這種歸一化方法幫助大模型理解,哪些解答方案比同組內其他解答方案更好或更差,而不是簡單的反饋絕對得分給大模型。
優化(optimization): 讓大模型從經驗中學習(learning from experience)
GRPO的最后一步是根據解決方案組的評估結果,指導大模型進行改進。這一過程基于兩個主要原則:
- 鼓勵模型生成更多類似成功案例的解決方案,同時遠離效果不佳的方法;
- 使用KL散度懲罰作為安全機制,防止模型在訓練中一次發生過于劇烈的變化;
這種方法在實踐中被證明比傳統方法更穩定,原因在于:
- 同時考慮多個解決方案,而不局限于兩兩比較;
- 基于組的歸一化有助于避免獎勵縮放問題(reward scaling)
- KL散度懲罰作為安全網,保證模型在學習新知識的同時,不會忘記已經掌握的內容;
總結GRPO的關鍵創新在于:
- 直接從任何函數或模型中學習,消除了對單獨獎勵模型的依賴。
- 基于組的學習方式,比傳統的成對比較等方法更加穩定和高效。
目標函數
GRPO算法從舊的策略模型中采樣一組輸出 o 1 , o 2 , . . . , o G {o_1,o_2,...,o_G} o1?,o2?,...,oG?,并通過下面的目標函數來優化策略模型:
GRPO的目標函數通過組內相對優勢估計替代傳統優勢函數,并結合PPO的裁剪機制(限制策略更新幅度)和KL散度正則化(約束策略與參考模型的偏離),在最大化獎勵的同時確保策略穩定性:
- 函數中通過最大化組內相對優勢,增加生成優質結果的概率,減少生成劣質結果的概率;
- 通過KL散度懲罰項,確保模型策略不會過度偏離參考策略,從而保證優化過程的穩定性。
式中參數注釋如下:
θ : 當前策略模型的可學習參數,通過優化目標函數更新 q ~ P ( Q ) : 從問題分布中采樣的輸入(如用戶指令) G : 每個輸入生成的樣本數(組內樣本數) o i ~ π θ old ( O ∣ q ) : 舊策略生成的第? i 個輸出樣本 π θ old : 舊策略模型(生成樣本時固定) π θ : 當前策略模型(通過優化更新) O ∣ q : 輸入? q 條件下策略生成的輸出分布 ∣ o i ∣ : 輸出序列? o i 的長度(token數量) t : 序列生成的時間步(第? t 個token位置) A ^ i , t : 組內相對優勢(基于組內獎勵差值計算) ? : 裁剪范圍參數(限制策略更新幅度) β : KL散度正則化系數(控制策略與參考模型偏離) D KL ( π θ ∣ ∣ π ref ) : 當前策略與參考模型的KL散度 π ref : 參考模型(如初始SFT模型) \begin{aligned} &\theta &&: \text{當前策略模型的可學習參數,通過優化目標函數更新} \\ &q \sim P(Q) &&: \text{從問題分布中采樣的輸入(如用戶指令)} \\ &G &&: \text{每個輸入生成的樣本數(組內樣本數)} \\ &o_i \sim \pi_{\theta_{\text{old}}}(O|q) &&: \text{舊策略生成的第 }i\text{ 個輸出樣本} \\ &\pi_{\theta_{\text{old}}} &&: \text{舊策略模型(生成樣本時固定)} \\ &\pi_{\theta} &&: \text{當前策略模型(通過優化更新)} \\ &O|q &&: \text{輸入 }q\text{ 條件下策略生成的輸出分布} \\ &|o_i| &&: \text{輸出序列 }o_i\text{ 的長度(token數量)} \\ &t &&: \text{序列生成的時間步(第 }t\text{ 個token位置)} \\ &\hat{A}_{i,t} &&: \text{組內相對優勢(基于組內獎勵差值計算)} \\ &\epsilon &&: \text{裁剪范圍參數(限制策略更新幅度)} \\ &\beta &&: \text{KL散度正則化系數(控制策略與參考模型偏離)} \\ &D_{\text{KL}}(\pi_{\theta}||\pi_{\text{ref}}) &&: \text{當前策略與參考模型的KL散度} \\ &\pi_{\text{ref}} &&: \text{參考模型(如初始SFT模型)} \end{aligned} ?θq~P(Q)Goi?~πθold??(O∣q)πθold??πθ?O∣q∣oi?∣tA^i,t??βDKL?(πθ?∣∣πref?)πref???:當前策略模型的可學習參數,通過優化目標函數更新:從問題分布中采樣的輸入(如用戶指令):每個輸入生成的樣本數(組內樣本數):舊策略生成的第?i?個輸出樣本:舊策略模型(生成樣本時固定):當前策略模型(通過優化更新):輸入?q?條件下策略生成的輸出分布:輸出序列?oi??的長度(token數量):序列生成的時間步(第?t?個token位置):組內相對優勢(基于組內獎勵差值計算):裁剪范圍參數(限制策略更新幅度):KL散度正則化系數(控制策略與參考模型偏離):當前策略與參考模型的KL散度:參考模型(如初始SFT模型)?
其中?兩個超參數:𝜀是PPO機制中的裁剪范圍參數,限制策略更新幅度;𝛽是KL散度正則化系數,控制當前策略與參考模型 π r e f π_{ref} πref?的偏離程度。
這里的KL散度與傳統的KL散度計算方式不同,使用Schulman提出的無偏估計,確保結果是正數:
式中 o < t o_{<t} o<t?表示在時間步 t 之前的所有觀測(或輸出)序列 。
GRPO算法的偽碼表示
DeepSeekMath論文里給出了GRPO迭代優化的步驟:
基于上述流程,GRPO算法的偽碼可表示為:
Input:
- initial_policy: Starting model to be trained
- reward_function: Function that evaluates outputs
- training_prompts: Set of training examples
- group_size: Number of outputs per prompt (typically 4-16)Algorithm GRPO:
1. For each training iteration:a. Set reference_policy = initial_policy (snapshot current policy)b. For each prompt in batch:i. Generate group_size different outputs using initial_policyii. Compute rewards for each output using reward_functioniii. Normalize rewards within group:normalized_advantage = (reward - mean(rewards)) / std(rewards)iv. Update policy by maximizing the clipped ratio:min(prob_ratio * normalized_advantage, clip(prob_ratio, 1-epsilon, 1+epsilon) * normalized_advantage)- kl_weight * KL(initial_policy || reference_policy)where prob_ratio is current_prob / reference_probOutput: Optimized policy model
GRPO算法的局限與挑戰
GRPO算法在實踐中也面臨一些挑戰:
- 生成成本。為每個提示詞生成多個補全(4-16個)相比只生成一個或兩個補全的方法,顯著增加了計算需求。
- 批量大小限制。需要一起處理一組補全,這可能會限制有效的批量大小,增加訓練過程的復雜性,并可能減緩訓練速度。
- 獎勵函數的設計。訓練質量在很大程度上依賴于精心設計的獎勵函數。設計不佳的獎勵可能導致意外行為或優化錯誤的目標。
- 組大小的權衡。選擇最優的組大小需要在解決方案的多樣性與計算成本之間進行平衡。組內樣本太少可能無法提供足夠的多樣性,而樣本太多則會增加訓練時間和資源需求。
- KL散度調參。找到合適的KL散度懲罰平衡需要謹慎調整——過高會導致模型無法有效學習,過低則可能使其偏離初始能力過遠。
代碼實現
GRPO訓練參數配置
TRL庫中將GRPO算法封裝為GRPOConfig
參數配置器和GRPOTrainer
訓練器。
這里參考TRL庫的源碼,給出簡化版的代碼解讀。
將GRPO訓練所需參數封裝成 GRPOConfig數據類。用@dataclass裝飾器將 GRPOConfig定義為一個數據類,并通過field函數為類中的字段指定默認值、默認工廠函數、元數據等。
原代碼過長,這里只貼出控制GRPO訓練的參數:
@dataclass
class GRPOConfig(TrainingArguments):
# Parameters that control the traininglearning_rate: float = field(default=1e-6,metadata={"help": "Initial learning rate for `AdamW` optimizer. The default value replaces that of ""`transformers.TrainingArguments`."},)beta: float = field(default=0.04,metadata={"help": "KL coefficient. If `0.0`, the reference model is not loaded, reducing memory usage and improving ""training speed, but may be numerically unstable for long training runs."},) # KL散度部分的超參數$\beta$,控制KL散度懲罰項的大小num_iterations: int = field(default=1,metadata={"help": "Number of iterations per batch (denoted as μ in the algorithm)."},)epsilon: float = field(default=0.2,metadata={"help": "Epsilon value for clipping."},) # clip部分超參數,控制裁剪的范圍
控制每個獎勵函數的權重占比的參數:
reward_weights: Optional[list[float]] = field(default=None,metadata={"help": "Weights for each reward function. Must match the number of reward functions. If `None`, all ""rewards are weighted equally with weight `1.0`."},) # 每個獎勵函數的權重占比
TR-DPO論文中提出的控制參考模型動態更新的三個參數, 當前策略模型與舊參考模型的混合比例、是否啟用參考模型與當前策略模型的同步機制、參考模型與當前策略模型同步的頻率:
## >TR-DPO論文中提出的控制參考模型與當前策略模型同步機制以動態更新的三個參數# 是否啟用參考模型與當前策略模型的同步機制sync_ref_model: bool = field(default=False,metadata={"help": "Whether to synchronize the reference model with the active model every `ref_model_sync_steps` ""steps, using the `ref_model_mixup_alpha` parameter."},) # 控制參考模型更新時,當前策略模型與舊參考模型的混合比例# 加權因子alpha控制軟更新(soft update);aplha=1時更新方法變為硬更新(hard update),即將參考策略模型替換為當前策略模型ref_model_mixup_alpha: float = field(default=0.6,metadata={"help": "α parameter from the TR-DPO paper, which controls the mix between the current policy and the ""previous reference policy during updates. The reference policy is updated according to the equation: ""`π_ref = α * π_θ + (1 - α) * π_ref_prev`. To use this parameter, you must set `sync_ref_model=True`."},)# 控制參考模型與當前策略模型同步的頻率# 每隔 ref_model_sync_steps 步,參考模型會根據 ref_model_mixup_alpha 的規則與當前策略模型進行同步更新。ref_model_sync_steps: int = field(default=512,metadata={"help": "τ parameter from the TR-DPO paper, which determines how frequently the current policy is ""synchronized with the reference policy. To use this parameter, you must set `sync_ref_model=True`."},)
GRPO訓練器
將GRPO訓練過程封裝為一個Trainer
的一個子類。
class GRPOtrainer(Trainer):def __init__(self,model,reward_funcs,args,train_dataset,eval_dataset,processing_class,reward_processing_classes,callbacks,optimizers,peft_config,):# Training argumentsself.max_prompt_length = args.max_prompt_lengthself.max_completion_length = args.max_completion_length # = |o_i| in the GRPO paperself.num_generations = args.num_generations # = G in the GRPO paper# Multi-stepself.num_iterations = args.num_iterations # = 𝜇 in the GRPO paperself.epsilon = args.epsilon # $\epsilon$超參數用于梯度clip# Tracks the number of iterations (forward + backward passes), including those within a gradient accumulation cycle.self._step = 0self._buffered_inputs = [None] * args.gradient_accumulation_steps# Initialize the metricsself._metrics = {"train": defaultdict(list), "eval": defaultdict(list)}self.log_completions = args.log_completionssuper().__init__(model=model,args=args,data_collator=data_collator,train_dataset=train_dataset,eval_dataset=eval_dataset,processing_class=processing_class,callbacks=callbacks,optimizers=optimizers,)self.generation_config = GenerationConfig(max_new_tokens=self.max_completion_length,do_sample=True,pad_token_id=processing_class.pad_token_id,temperature=args.temperature,top_p=args.top_p,top_k=args.top_k,min_p=args.min_p,repetition_penalty=args.repetition_penalty,)
token對數概率計算
計算模型生成的每個token的對數概率,以控制模型在訓練中的策略更新:
# Get the per-token log probabilities for the completions for the model and the reference model@profiling_decorator # 性能分析def _get_per_token_logps(self, model, input_ids, attention_mask, logits_to_keep):# We add 1 to `logits_to_keep` because the last logits of the sequence is later excludedlogits = model(input_ids=input_ids, attention_mask=attention_mask, logits_to_keep=logits_to_keep + 1).logitslogits = logits[:, :-1, :] # (B, L-1, V), 排除最后一個 logit: 對應下一個token的預測input_ids = input_ids[:, -logits_to_keep:]logits = logits[:, -logits_to_keep:]return selective_log_softmax(logits, input_ids) # 計算每個輸入token的對數概率
獎勵矩陣計算
初始化獎勵矩陣后,遍歷所有預定義的獎勵函數(可靈活定義為pytorch模型或普通python函數),分別計算獎勵值后更新獎勵矩陣:
rewards_per_func = torch.zeros(len(prompts), len(self.reward_funcs), device=device) # 初始化獎勵矩陣for i, (reward_func, reward_processing_class) in enumerate(zip(self.reward_funcs, self.reward_processing_classes) # 遍歷所有的獎勵函數):if isinstance(reward_func, nn.Module): # Module instead of PretrainedModel for compat with compiled modelsreward_func_name = f"reward {reward_func.config._name_or_path.split('/')[-1]}"else:reward_func_name = reward_func.__name__with profiling_context(self, reward_func_name):if isinstance( # 基于pytorch模型計算獎勵值reward_func, nn.Module ): # Module instead of PretrainedModel for compat with compiled modelsif is_conversational(inputs[0]):messages = [{"messages": p + c} for p, c in zip(prompts, completions)]texts = [apply_chat_template(x, reward_processing_class)["text"] for x in messages]else:texts = [p + c for p, c in zip(prompts, completions)]reward_inputs = reward_processing_class(texts, return_tensors="pt", padding=True, padding_side="right", add_special_tokens=False)reward_inputs = super()._prepare_inputs(reward_inputs)with torch.inference_mode():rewards_per_func[:, i] = reward_func(**reward_inputs).logits[:, 0] # Shape (B*G,)else: # 基于python函數計算獎勵值# Repeat all input columns (but "prompt" and "completion") to match the number of generationskeys = [key for key in inputs[0] if key not in ["prompt", "completion"]]reward_kwargs = {key: [example[key] for example in inputs] for key in keys}output_reward_func = reward_func(prompts=prompts, completions=completions, **reward_kwargs)rewards_per_func[:, i] = torch.tensor(output_reward_func, dtype=torch.float32, device=device)
組內優勢計算
根據組內解答數(num_generations
),計算組內優勢:
rewards_per_func = gather(rewards_per_func)# Apply weights to each reward function's output and sumrewards = (rewards_per_func * self.reward_weights.to(device).unsqueeze(0)).sum(dim=1)# Compute grouped-wise rewardsmean_grouped_rewards = rewards.view(-1, self.num_generations).mean(dim=1)std_grouped_rewards = rewards.view(-1, self.num_generations).std(dim=1)# Normalize the rewards to compute the advantagesmean_grouped_rewards = mean_grouped_rewards.repeat_interleave(self.num_generations, dim=0)std_grouped_rewards = std_grouped_rewards.repeat_interleave(self.num_generations, dim=0)advantages = (rewards - mean_grouped_rewards) / (std_grouped_rewards + 1e-4)
計算損失函數
根據deepseek math論文中公式(4), 計算 D K L D_{KL} DKL?的無偏估計:
# 計算參考模型與當前模型之間的KL散度if self.beta != 0.0: # 當KL散度正則項的參數$beta$不為0時ref_per_token_logps = inputs["ref_per_token_logps"]per_token_kl = (torch.exp(ref_per_token_logps - per_token_logps) - (ref_per_token_logps - per_token_logps) - 1) # KL散度的無偏估計,,deepseek math論文中公式(4)
根據deepseek math 論文中的公式(3),計算損失函數:
# Compute the lossadvantages = inputs["advantages"]old_per_token_logps = inputs["old_per_token_logps"] if self.num_iterations > 1 else per_token_logps.detach()coef_1 = torch.exp(per_token_logps - old_per_token_logps) # 新舊模型token概率的比值(先取log再取指數便于計算)coef_2 = torch.clamp(coef_1, 1 - self.epsilon, 1 + self.epsilon) #clip截斷部分per_token_loss1 = coef_1 * advantages.unsqueeze(1) # 未截斷的概率比值計算的損失per_token_loss2 = coef_2 * advantages.unsqueeze(1) # 截斷的概率比值計算的損失per_token_loss = -torch.min(per_token_loss1, per_token_loss2) # 損失部分計算,最小化損失(最大化獎勵)if self.beta != 0.0:per_token_loss = per_token_loss + self.beta * per_token_kl # deepseek math 論文中的公式(3),GRPO目標函數loss = (per_token_loss * completion_mask).sum() / completion_mask.sum()
記錄KL散度平均值:
# 記錄KL散度的平均值if self.beta != 0.0:mean_kl = (per_token_kl * completion_mask).sum() / completion_mask.sum()self._metrics[mode]["kl"].append(self.accelerator.gather_for_metrics(mean_kl).mean().item())
計算截斷比例(clip ratio):
# 計算截斷比例is_clipped = (per_token_loss1 < per_token_loss2).float()clip_ratio = (is_clipped * completion_mask).sum() / completion_mask.sum() self._metrics[mode]["clip_ratio"].append(self.accelerator.gather_for_metrics(clip_ratio).mean().item())
案例實戰:使用TRL庫實現GRPO訓練文本生成模型
這里給出一個用GRPO算法,在smoltldr數據集上訓練SmolLM135M文本生成模型的demo例子。使用trl、peft庫實現GRPO和LORA微調。
數據集介紹
mlabonne/smoltldr 是一個包含短篇小說列表的數據集,由用戶 mlabonne 在 Hugging Face 上創建并維護。該數據集主要用于自然語言處理任務,例如文本生成、故事創作等。數據集中的每個樣本通常是一個短篇故事,內容可能涵蓋多種主題和風格。這些故事經過清洗和格式化,適合用于訓練語言模型。SmolLM-135M則是用于文本生成的小模型。
數據和模型加載
import torch
import wandb
from datasets import load_dataset
from peft import LoraConfig,get_peft_model
from transformers import AutoModelForCausalLM,AutoTokenizer
from trl import GRPOConfig,GRPOTrainerwandb.login() # 登錄wandb,輸入api key,保存訓練結果到wandb# 加載huggingface上的數據集
dataset = load_dataset("mlabonne/smoltldr")# 加載huggingface上的模型
model_id = "HuggingFaceTB/SmolLM-135M-Instruct"
model = AutoModelForCausalLM(model_id,torch_dtype = "auto",device_map = "auto",# attn_implementation = "flash_attention_2",attn_implementation = "eager",# GPU不支持flashattention時改用標準注意力
)
tokenizer = AutoTokenizer.from_pretrained(model_id)
LORA微調配置
# 加載PEFT庫中的lora配置
lora_config = LoraConfig(task_type = "CAUSAL_LM", # 生成式任務r=16, # 秩為16lora_alpha=32, # 低秩矩陣權重貢獻的縮放因子設為32target_modules = "all-linear",# 模型中的線性層應用lora
)
model = get_peft_model(model,lora_config) # 凍結預訓練模型的所有參數,根據lora_config在模型中添加低秩矩陣
print(model.print_trainable_parameters()) # 打印模型中可訓練參數的數量及占總參數的比例
定義獎勵函數
# 定義獎勵函數
def reward_len(completions,**kwargs):return [-abs(50-len(completion)) for completion in completions]
GRPO訓練參數設置
# GRPO訓練參數配置
training_args = GRPOConfig(output_dir="GRPO",run_name="GRPO_experi_0308_01",# wandb保存的實驗名稱learning_rate=2e-5,per_device_train_batch_size=4,# 批量大小設小一點減少顯存占用gradient_accumulation_steps=2, # 梯度累積步數max_prompt_length=512,max_completion_length=96,num_generations=4,# GRPO每組生成的解答數optim="adamW_8bit",num_train_epochs=1,# 訓練數據集訓練的總輪數bf16=True,report_to=["wandb"],remove_unused_columns=False,# 不移除數據集中未使用的列logging_steps=1,# 每隔一步記錄一次日志
)
# 設置訓練器
trainer = GRPOTrainer(model=model,reward_funcs = [reward_len],# 自定義的獎勵函數agrs=training_args,# GRPO的訓練配置train_dataset = dataset["train"],
)
訓練模型
# 訓練模型
wandb.init(project="GRPO") # 初始化wandb日志環境
trainer.train() # 開始訓練
上傳訓練完成的模型參數
# 保存模型參數,上傳到huggingface hub
merged_model = trainer.model.merge_and_unload() # 合并lora權重和預訓練權重
merged_model.push_to_hub("<your_username/your_modelname>",private=False) # 模型公開可見
下載訓練好的模型參數進行文本生成
prompt = """
# A long document about the CatThe cat (Felis catus), also referred to as the domestic cat or house cat, is a small
domesticated carnivorous mammal. It is the only domesticated species of the family Felidae.
Advances in archaeology and genetics have shown that the domestication of the cat occurred
in the Near East around 7500 BC. It is commonly kept as a pet and farm cat, but also ranges
freely as a feral cat avoiding human contact. It is valued by humans for companionship and
its ability to kill vermin. Its retractable claws are adapted to killing small prey species
such as mice and rats. It has a strong, flexible body, quick reflexes, and sharp teeth,
and its night vision and sense of smell are well developed. It is a social species,
but a solitary hunter and a crepuscular predator. Cat communication includes
vocalizations—including meowing, purring, trilling, hissing, growling, and grunting—as
well as body language. It can hear sounds too faint or too high in frequency for human ears,
such as those made by small mammals. It secretes and perceives pheromones.
"""
messages = [{"role":"user","content":prompt},
]from transformers import pipeline
generator = pipeline("text-generation",model="<your_username/your_modelname>")
generate_kwargs = {"max_new_tokens": 256,"do_sample":True, # 啟用采樣生成模式"temperature":0.5, "min_p":0.1,
}
generated_text = generator(messages,generate_kwargs=generate_kwargs)
print(generated_text)
訓練結果分析
隨著模型的學習,獎勵函數的獎勵值逐漸接近0。這表明模型正在學習生成正確長度的文本。
在GRPO中,損失函數的初始值為零,然后在訓練過程中增加。GRPO中的損失與KL散度(相對于原始策略的上限)成正比。隨著訓練的進行,模型學會了生成更好地符合獎勵函數的文本,導致它與初始策略的偏差越來越大。這種增加的偏差反映在上升的損失值中,實際上表明模型正在成功地適應以優化獎勵函數。
推薦閱讀
- 抱抱臉25年3月更新中的深度推理課程: https://huggingface.co/reasoning-course
- DeepSeekMath: Pushing the Limits of Mathematical Reasoning in Open Language Models: https://arxiv.org/pdf/2402.03300
REF
- DeepSeekMath: Pushing the Limits of Mathematical Reasoning in Open Language Models: https://arxiv.org/pdf/2402.03300
- https://github.com/huggingface/trl/blob/main/trl/trainer/grpo_trainer.py#L98
- https://github.com/huggingface/open-r1/blob/main/src/open_r1/grpo.py
- https://open-r1.com/#:~:text=Open%20R1%20is%20an%20open-source%20reproduction%20of%20DeepSeek-R1%2C,MIT%20license%2C%20though%20original%20training%20data%20remains%20proprietary.
- DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning https://arxiv.org/abs/2501.12948
- https://huggingface.co/learn/nlp-course/en/chapter12/1?fw=pt