最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊

使用 PPO 算法進(jìn)行 RLHF 的 N 步實(shí)現(xiàn)細(xì)節(jié)

2023-11-16 20:41 作者:HuggingFace  | 我要投稿

當(dāng)下,RLHF/ChatGPT 已經(jīng)變成了一個(gè)非常流行的話題。我們正在致力于更多有關(guān) RLHF 的研究,這篇博客嘗試復(fù)現(xiàn) OpenAI 在 2019 年開源的原始 RLHF 代碼庫,其倉庫位置位于 openai/lm-human-preferences。盡管它具有 “tensorflow-1.x” 的特性,但 OpenAI 的原始代碼庫評估和基準(zhǔn)測試非常完善,使其成為研究 RLHF 實(shí)現(xiàn)工程細(xì)節(jié)的好地方。

我們的目標(biāo)是:

  1. 復(fù)現(xiàn) OAI 在風(fēng)格化任務(wù)中的結(jié)果,并匹配 openai/lm-human-preferences 的學(xué)習(xí)曲線。

  2. 提供一個(gè)實(shí)現(xiàn)細(xì)節(jié)的清單,類似于 近端優(yōu)化策略的 37 個(gè)實(shí)施細(xì)節(jié) (The 37 Implementation Details of Proximal Policy Optimization) 和 沒有痛苦折磨的調(diào)試 RL (Debugging RL, Without the Agonizing Pain) 的風(fēng)格;

  3. 提供一個(gè)易于閱讀且簡潔的 RLHF 參考實(shí)現(xiàn);

這項(xiàng)工作僅適用于以教育/學(xué)習(xí)為目的的。對于需要更多功能的高級用戶,例如使用 PEFT 運(yùn)行更大的模型, huggingface/trl 將是一個(gè)不錯(cuò)的選擇。

  • 在 匹配學(xué)習(xí)曲線 中,我們展示了我們的主要貢獻(xiàn): 創(chuàng)建一個(gè)代碼庫,能夠在風(fēng)格化任務(wù)中復(fù)現(xiàn) OAI 的結(jié)果,并且與 openai/lm-human-preferences 的學(xué)習(xí)曲線非常接近地匹配。

  • 然后我們深入探討了與復(fù)現(xiàn) OAI 的工作相關(guān)的實(shí)現(xiàn)細(xì)節(jié)。在 總體實(shí)現(xiàn)細(xì)節(jié) 中,我們討論了基本細(xì)節(jié),像如何生成獎(jiǎng)勵(lì)/值和如何生成響應(yīng)。在 獎(jiǎng)勵(lì)模型實(shí)現(xiàn)細(xì)節(jié) 中,我們討論了諸如獎(jiǎng)勵(lì)標(biāo)準(zhǔn)化之類的細(xì)節(jié)。在 策略訓(xùn)練實(shí)現(xiàn)細(xì)節(jié) 中,我們討論了拒絕采樣和獎(jiǎng)勵(lì)“白化”等細(xì)節(jié)。

    • PyTorch Adam 優(yōu)化器在處理 RLHF 時(shí)的數(shù)值問題 中,我們強(qiáng)調(diào)了 TensorFlow 和 PyTorch 之間 Adam 的一個(gè)非常有趣的實(shí)現(xiàn)區(qū)別,其導(dǎo)致了模型訓(xùn)練中的激進(jìn)更新。

  • 接下來,我們檢查了在獎(jiǎng)勵(lì)標(biāo)簽由 gpt2-large 生成的情況下,訓(xùn)練不同基礎(chǔ)模型 (例如 gpt2-xl, falcon-1b) 的效果。

  • 最后,我們通過討論一些限制來總結(jié)我們的研究工作。

以下是一些重要鏈接:

  • ?? 我們的復(fù)現(xiàn)代碼庫 https://github.com/vwxyzjn/lm-human-preference-details

  • ?? RLHF 模型比較示例: https://huggingface.co/spaces/lm-human-preference-details/rlhf-demo

  • ?? 所有的 w&b 訓(xùn)練日志 https://wandb.ai/openrlbenchmark/lm_human_preference_details

匹配學(xué)習(xí)曲線

我們的主要貢獻(xiàn)是在風(fēng)格化任務(wù)中復(fù)現(xiàn) OAI 的結(jié)果,例如情感和描述性。如下圖所示,我們的代碼庫 (橙色曲線) 能夠產(chǎn)生與 OAI 的代碼庫 (藍(lán)色曲線) 幾乎相同的學(xué)習(xí)曲線。

關(guān)于運(yùn)行 openai/lm-human-preferences 的說明

為了直觀比較,我們運(yùn)行了原始的 RLHF 代碼,其倉庫位置位于 openai/lm-human-preferences,它將提供寶貴的指標(biāo),以幫助驗(yàn)證和診斷我們的復(fù)現(xiàn)。我們能夠設(shè)置原始的 TensorFlow 1.x 代碼,但它需要一個(gè)非常特定的設(shè)置:

  • OAI 的數(shù)據(jù)集部分損壞/丟失 (所以我們用類似的 HF 數(shù)據(jù)集替換了它們,這可能會(huì)或可能不會(huì)導(dǎo)致性能差異)

    • 具體來說,它的書籍?dāng)?shù)據(jù)集在 OpenAI 的 GCP - Azure 遷移過程中丟失了 (https://github.com/openai/lm-human-preferences/issues/17#issuecomment-1044051496)。我用 Hugging Face 的 bookcorpus 數(shù)據(jù)集替換了書籍?dāng)?shù)據(jù)集,原則上,這是類似 OAI 使用的數(shù)據(jù)集。

  • 它不能在 1 個(gè) V100 上運(yùn)行,因?yàn)樗鼪]有實(shí)現(xiàn)梯度累積。相反,它使用一個(gè)大的 BS (批量大小),并在 8 個(gè) GPU 上分割 batch (批量),僅在 1 個(gè) GPU 上就會(huì)出現(xiàn) OOM (內(nèi)存溢出)。

  • 它不能在 8 個(gè) A100 上運(yùn)行,因?yàn)樗褂玫氖?TensorFlow 1.x,與 Cuda 8+ 不兼容。

  • 它不能在 8 個(gè) V100 (16GB) 上運(yùn)行,因?yàn)樗鼤?huì) OOM (內(nèi)存溢出)。

  • 它只能在 8 個(gè) V100 (32GB) 上運(yùn)行,這種配置僅由 AWS 以 p3dn.24xlarge 實(shí)例的形式提供。

總體實(shí)現(xiàn)細(xì)節(jié)

我們現(xiàn)在深入探討與復(fù)現(xiàn) OAI 工作相關(guān)的技術(shù)實(shí)現(xiàn)細(xì)節(jié)。在這個(gè)部分,我們討論了一些基本細(xì)節(jié),例如獎(jiǎng)勵(lì)/值是如何生成的,以及響應(yīng)是如何生成的。以下是這些細(xì)節(jié),不按特定順序列出:

  1. 獎(jiǎng)勵(lì)模型和策略的價(jià)值頭將 queryresponse 的連接作為輸入

    1. 獎(jiǎng)勵(lì)模型和策略的價(jià)值頭 不 僅僅查看響應(yīng)。相反,它將 queryresponse 連接在一起,作為 query_response (lm_human_preferences/rewards.py#L105-L107)。

    2. 舉例來說,如果 query = "他在想某事,但他的眼神很難讀懂"。 ,和 response = "他看著他的左手,手臂伸在他的前面。" ,那么獎(jiǎng)勵(lì)模型和策略的價(jià)值會(huì)對query_response = "他在想某事,但他的眼神很難讀懂。他看著他的左手,手臂伸在他的前面。" 進(jìn)行前向傳遞,并產(chǎn)生形狀為 (B, T, 1) 的獎(jiǎng)勵(lì)和價(jià)值,其中 B 是 BS (批量大小),T 是序列長度,而 1 代表獎(jiǎng)勵(lì)頭的輸出結(jié)構(gòu)的維度為 1 (lm_human_preferences/rewards.py#L105-L107, lm_human_preferences/policy.py#L111)。

    3. T 意味著每個(gè) token 都有與其和前文關(guān)聯(lián)的獎(jiǎng)勵(lì)。例如,eyes token 將有一個(gè)與他在想某事,但他的眼神很難讀懂 相對應(yīng)的獎(jiǎng)勵(lì)。

  2. 使用特殊的填充 token 來填充和截?cái)噍斎搿?/strong>

    1. 關(guān)于 HF 的 transformers — 填充 token 的注解。 根據(jù) (transformers#2630#issuecomment-578159876),在 GPT 和 GPT-2 的預(yù)訓(xùn)練期間沒有使用填充 token; 因此,transformer 的 gpt2 模型與其分詞器沒有關(guān)聯(lián)的官方填充 token。通常的做法是設(shè)置 tokenizer.pad_token = tokenizer.eos_token ,但在這項(xiàng)工作中,我們將區(qū)分這兩個(gè)特殊 token 以匹配 OAI 的原始設(shè)置,所以我們將使用 tokenizer.add_special_tokens({"pad_token": "[PAD]"}) 。

    2. OAI 為查詢 query_length 設(shè)置了固定的輸入長度; 它使用 pad_token 填充 過短的序列 (lm_human_preferences/language/datasets.py#L66-L67),并 截?cái)?/strong> 過長的序列 (lm_human_preferences/language/datasets.py#L57)。詳見 此處 以獲取該概念的通用介紹。在填充輸入時(shí),OAI 使用了詞匯表之外的 token (lm_human_preferences/language/encodings.py#L56)。

      注意,沒有填充 token 是解碼器模型的默認(rèn)設(shè)置,因?yàn)樗鼈冊陬A(yù)訓(xùn)練期間使用“打包”訓(xùn)練,這意味著許多序列被連接并由 EOS token 分隔,這些序列的塊在預(yù)訓(xùn)練期間始終具有最大長度并被饋送到模型中。

    3. 當(dāng)把所有事物放在一起時(shí),這里有一個(gè)例子

      ?


  1. 相應(yīng)地調(diào)整填充 token 的位置索引

    通常情況下,我們幾乎從不在 transformers 中傳遞 position_ids 。所有的遮蔽 (masking) 和移位 (shifting) logic 已經(jīng)實(shí)現(xiàn),例如,在 generate 函數(shù)中 (需要永久的代碼鏈接)。

    1. 在計(jì)算 logits 時(shí),OAI 的代碼通過適當(dāng)?shù)仄帘翁畛?token 來工作。這是通過找出與填充 token 相對應(yīng)的 token 索引來實(shí)現(xiàn)的 (lm_human_preferences/language/model.py#L296-L297),然后相應(yīng)地調(diào)整它們的位置索引 (lm_human_preferences/language/model.py#L320)。

    2. 例如,如果 query=[23073, 50259, 50259]response=[11, 339, 561] ,其中 ( 50259 是 OAI 的填充 token),它會(huì)創(chuàng)建位置索引為 [[0 1 1 1 2 3]] 并且如下的 logits。注意填充 token 對應(yīng)的 logits 如何保持不變!這是我們在復(fù)制過程中應(yīng)該追求的效果。


  1. 關(guān)于 HF 的 transformers — position_idspadding_side 的注解。 我們可以通過 1) 左填充和 2) 傳入適當(dāng)?shù)?position_ids ,使用 Hugging Face 的 transformer 復(fù)制精確的 logits:


    1. 關(guān)于 HF 的 transformers ——在 生成 過程中的 position_ids 的注解: 在生成過程中,我們不應(yīng)傳入 position_ids ,因?yàn)樵?transformers 中, position_ids 已經(jīng)以某種方式被調(diào)整了。當(dāng)我在生成過程中也傳入 position_ids 時(shí),性能會(huì)災(zāi)難性地惡化。

  1. 生成固定長度響應(yīng)的響應(yīng)生成不需要填充。

    1. 在響應(yīng)生成期間,OAI 使用 top_k=0, top_p=1.0 并僅在詞匯表上做分類樣本 (lm_human_preferences/language/sample.py#L43),代碼會(huì)一直采樣,直到生成固定長度的響應(yīng) (lm_human_preferences/policy.py#L103)。值得注意的是,即使遇到 EOS (序列結(jié)束) token ,它也會(huì)繼續(xù)采樣。

      1. 關(guān)于 HF 的 transformers 的注解 — 在 eos_token 處采樣可能會(huì)停止:transformers 中,生成可能會(huì)在 eos_token 處停止 (src/transformers/generation/utils.py#L2248-L2256),這與 OAI 的設(shè)置不同。為了對齊設(shè)置,我們需要設(shè)置 pretrained_model.generation_config.eos_token_id = None, pretrained_model.generation_config.pad_token_id = None 。請注意, transformers.GenerationConfig(eos_token_id=None, pad_token_id=None, ...) 不起作用,因?yàn)?pretrained_model.generation_config 會(huì)覆蓋并設(shè)置一個(gè) eos_token


    1. 請注意,在較新的代碼庫 https://github.com/openai/summarize-from-feedback 中,當(dāng)遇到 EOS token 時(shí),OAI 確實(shí)會(huì)停止采樣 (summarize_from_feedback/utils/experiment_helpers.py#L19)。然而,在這項(xiàng)工作中,我們的目標(biāo)是進(jìn)行 1:1 的復(fù)刻,所以我們調(diào)整了設(shè)置,即使遇到 eos_token 也可以繼續(xù)采樣。

  1. 獎(jiǎng)勵(lì)模型和策略訓(xùn)練的學(xué)習(xí)率退火。

    1. 正如 Ziegler 等人 (2019) 建議的,獎(jiǎng)勵(lì)模型只訓(xùn)練一個(gè) epcho,以避免過度擬合有限量的人類注釋數(shù)據(jù) (例如,descriptiveness 任務(wù)只有大約 5000 個(gè)標(biāo)簽)。在這個(gè)單一的 epcho 中,學(xué)習(xí)率會(huì)退火至零 (lm_human_preferences/train_reward.py#L249)。

    2. 類似于獎(jiǎng)勵(lì)模型訓(xùn)練,策略訓(xùn)練的學(xué)習(xí)率也會(huì)退火至零 (lm_human_preferences/train_policy.py#L172-L173)。

  2. 為不同的進(jìn)程使用不同的種子

    1. 注: 我認(rèn)為數(shù)據(jù)集的洗牌 (shuffling) 存在一個(gè)錯(cuò)誤——由于某種原因,數(shù)據(jù)集是使用相同的種子進(jìn)行洗牌的 (lm_human_preferences/lm_tasks.py#L94-L97)。

    2. 在生成 8 個(gè) GPU 進(jìn)程進(jìn)行數(shù)據(jù)并行時(shí),OAI 為每個(gè)進(jìn)程設(shè)置了不同的隨機(jī)種子 (lm_human_preferences/utils/core.py#L108-L111)。在實(shí)現(xiàn)上,這是通過 local_seed = args.seed + process_rank * 100003 完成的。種子會(huì)讓模型產(chǎn)生不同的響應(yīng)并得到不同的分?jǐn)?shù),例如。

獎(jiǎng)勵(lì)模型實(shí)現(xiàn)細(xì)節(jié)

在本節(jié)中,我們討論了獎(jiǎng)勵(lì)模型特定的實(shí)現(xiàn)細(xì)節(jié)。我們討論了諸如獎(jiǎng)勵(lì)歸一化和層初始化等細(xì)節(jié)。以下是這些細(xì)節(jié),不按特定順序排列:

  1. 獎(jiǎng)勵(lì)模型只輸出最后一個(gè) token 的值。

    1. 請注意,在對 queryresponse 的連接進(jìn)行前向傳遞后獲得的獎(jiǎng)勵(lì)將具有形狀 (B, T, 1) ,其中 B 是 BS(批量大小),T 是序列長度 (始終相同; 在 OAI 的設(shè)置中,它是 query_length + response_length = 64 + 24 = 88 ,用于風(fēng)格任務(wù),參見 launch.py#L9-L11),1 是獎(jiǎng)勵(lì)頭其維度為 1。對于 RLHF (Reinforcement Learning from Human Feedback,通過人類反饋進(jìn)行強(qiáng)化學(xué)習(xí)) 的目的,原始代碼庫提取最后一個(gè) token 的獎(jiǎng)勵(lì) (lm_human_preferences/rewards.py#L132),因此獎(jiǎng)勵(lì)將只具有形狀 (B, 1) 。

    2. 請注意,在較新的代碼庫 openai/summarize-from-feedback 中,OAI 在遇到 EOS token 時(shí)停止采樣 (summarize_from_feedback/utils/experiment_helpers.py#L19)。在提取獎(jiǎng)勵(lì)時(shí),它將確定 last_response_index ,即 EOS token 之前的索引 (#L11-L13),并在該索引處提取獎(jiǎng)勵(lì) (summarize_from_feedback/reward_model.py#L59)。但在此工作中,我們只是堅(jiān)持原始設(shè)置。

  2. 獎(jiǎng)勵(lì)頭層初始化

    1. 獎(jiǎng)勵(lì)頭的權(quán)重是根據(jù) 初始化的 (lm_human_preferences/language/model.py#L368, lm_human_preferences/language/model.py#L251-L252)。這與 Stiennon 等人的設(shè)置相符,2020 年 (summarize_from_feedback/query_response_model.py#L106-L107) (附注,Stiennon 等人,2020 年在第 17 頁上有一個(gè)錯(cuò)字,表示分布是 沒有平方根)

    2. 獎(jiǎng)勵(lì)頭的 bias (偏置) 設(shè)為 0 (lm_human_preferences/language/model.py#L254)。

  3. 獎(jiǎng)勵(lì)模型的前后歸一化

    1. 在論文中,Ziegler 等人 (2019) 提到“為了保持訓(xùn)練過程中獎(jiǎng)勵(lì)模型的規(guī)模一致,我們將其歸一化,使其在 的情況下,均值為 0,方差為 1”。為了執(zhí)行歸一化過程,代碼首先創(chuàng)建了 reward_gainreward_bias ,以便可以通過 reward = reward * reward_gain + reward_bias 來計(jì)算獎(jiǎng)勵(lì)值 (lm_human_preferences/rewards.py#L50-L51)。

    2. 在執(zhí)行歸一化過程時(shí),代碼首先設(shè)置 reward_gain=1, reward_bias=0 (lm_human_preferences/train_reward.py#L211),然后從目標(biāo)數(shù)據(jù)集 (例如,bookcorpus, tldr, cnndm ) 中收集采樣查詢、完成的響應(yīng)和評估的獎(jiǎng)勵(lì)。接著,它得到評估獎(jiǎng)勵(lì)的 實(shí)證均值和標(biāo)準(zhǔn)差 (lm_human_preferences/train_reward.py#L162-L167),并嘗試計(jì)算 reward_gainreward_bias 應(yīng)該是什么。

    3. 我們用 來表示實(shí)證均值,用 表示實(shí)證標(biāo)準(zhǔn)差,用 表示 reward_gain ,用 表示 reward_bias ,用 表示 目標(biāo)均值,用 表示 目標(biāo)標(biāo)準(zhǔn)差。然后我們有以下公式。

      ? ? ?%5Cbegin%7Baligned%7Dg*%5Cmathcal%7BN%7D(%5Cmu_%7B%5Cmathcal%7BD%7D%7D%2C%20%5Csigma_%7B%5Cmathcal%7BD%7D%7D)%20%2B%20b%20%26%3D%20%5Cmathcal%7BN%7D(g*%5Cmu_%7B%5Cmathcal%7BD%7D%7D%2C%20g*%5Csigma_%7B%5Cmathcal%7BD%7D%7D)%20%2B%20b%5C%5C%26%3D%20%5Cmathcal%7BN%7D(g*%5Cmu_%7B%5Cmathcal%7BD%7D%7D%20%2B%20b%2C%20g*%5Csigma_%7B%5Cmathcal%7BD%7D%7D)%20%5C%5C%26%3D%20%5Cmathcal%7BN%7D(%5Cmu_%7B%5Cmathcal%7BT%7D%7D%2C%20%5Csigma_%7B%5Cmathcal%7BT%7D%7D)%20%5C%5Cg%20%26%3D%20%5Cfrac%7B%5Csigma_%7B%5Cmathcal%7BT%7D%7D%7D%7B%5Csigma_%7B%5Cmathcal%7BD%7D%7D%7D%20%5C%5Cb%20%26%3D%20%5Cmu_%7B%5Cmathcal%7BT%7D%7D%20-%20g*%5Cmu_%7B%5Cmathcal%7BD%7D%7D%5Cend%7Baligned%7D

    4. 然后在獎(jiǎng)勵(lì)模型訓(xùn)練的 應(yīng)用歸一化過程 (lm_human_preferences/train_reward.py#L232-L234,lm_human_preferences/train_reward.py#L252-L254)。

    5. 請注意,我們?yōu)闅w一化目的生成的響應(yīng) y%20%5Csim%20%5Crho(%C2%B7%7Cx) 來自預(yù)訓(xùn)練的語言模型 %5Crho。模型?%5Crho 被固定為參考,并且在獎(jiǎng)勵(lì)學(xué)習(xí)中不會(huì)更新 (lm_human_preferences/train_reward.py#L286C1-L286C31)。

策略訓(xùn)練實(shí)現(xiàn)細(xì)節(jié)

在本節(jié)中,我們將深入探討諸如層初始化、數(shù)據(jù)后處理和 dropout 設(shè)置等細(xì)節(jié)。我們還將探討一些技術(shù),如拒絕采樣和獎(jiǎng)勵(lì) “白化”,以及自適應(yīng) KL。以下是這些細(xì)節(jié),排列不分先后:

  1. 通過采樣溫度來縮放 logits

    1. 在計(jì)算響應(yīng)的對數(shù)概率時(shí),模型首先輸出響應(yīng)中 token 的 logits,然后用采樣溫度除以這些 logits (lm_human_preferences/policy.py#L121)。即 logits /= self.temperature

    2. 在一個(gè)非正式的測試中,我們發(fā)現(xiàn)如果不進(jìn)行此縮放,KL 散度會(huì)比預(yù)期更快地上升,性能會(huì)下降。

  2. 價(jià)值頭層的初始化

    1. 價(jià)值頭的權(quán)重是根據(jù) 進(jìn)行初始化的 (lm_human_preferences/language/model.py#L368、lm_human_preferences/language/model.py#L251-L252)。

    2. 獎(jiǎng)勵(lì)頭的 bias (偏置) 設(shè)置為 0 (lm_human_preferences/language/model.py#L254)。

  3. 選擇以句號開始和結(jié)束的查詢文本

    1. 嘗試僅在 start_text="." 之后選擇文本 (lm_human_preferences/language/datasets.py#L51)

    2. 嘗試在 end_text="." 之前選擇文本 (lm_human_preferences/language/datasets.py#L61)

    3. 然后填充文本 (lm_human_preferences/language/datasets.py#L66-L67)

    4. 這是數(shù)據(jù)預(yù)處理的一部分:

    5. 在運(yùn)行 openai/lm-human-preferences 時(shí),OAI 的數(shù)據(jù)集部分損壞/丟失 (openai/lm-human-preferences/issues/17#issuecomment-104405149),因此我們不得不用類似的 HF 數(shù)據(jù)集替換它們,這可能會(huì)或可能不會(huì)導(dǎo)致性能差異。

    6. 對于書籍?dāng)?shù)據(jù)集,我們使用 https://huggingface.co/datasets/bookcorpus,我們發(fā)現(xiàn)沒有必要提取以句號開始和結(jié)束的句子,因?yàn)閿?shù)據(jù)集已經(jīng)是這樣預(yù)處理過的 (例如,"usually , he would be tearing around the living room , playing with his toys." ) 為此,我們?yōu)?sentimentdescriptiveness 任務(wù)設(shè)置 start_text=None, end_text=None 。

  4. 禁用 dropout

    1. Ziegler 等人 (2019) 建議,“我們在策略訓(xùn)練中不使用 dropout?!?這也在代碼中實(shí)現(xiàn)了 (lm_human_preferences/policy.py#L48)。

  5. 拒絕采樣

    1. token 截?cái)?/strong>: 我們想要在第一個(gè)出現(xiàn)在響應(yīng)的 truncate_after 位置之后的 truncate_token 處截?cái)?(lm_human_preferences/train_policy.py#L378)。

    2. 在截?cái)囗憫?yīng)上運(yùn)行獎(jiǎng)勵(lì)模型: 在 token 截?cái)噙^程將響應(yīng)截?cái)嗪螅a然后在 截?cái)嗟捻憫?yīng) 上運(yùn)行獎(jiǎng)勵(lì)模型。

    3. 拒絕采樣: 如果在第 16 和 24 個(gè) token 之間沒有句號,那么將響應(yīng)的分?jǐn)?shù)替換為固定的低值 (例如 -1) (lm_human_preferences/train_policy.py#L384、lm_human_preferences/train_policy.py#L384-L402)。

    4. descriptiveness 中舉一些例子:

    1. 從我們的復(fù)制中提取的樣本 https://wandb.ai/openrlbenchmark/lm_human_preference_details/runs/djf8yymv/logs。請注意,第 1 和第 3 個(gè)示例在句號后有太多 token,因此其分?jǐn)?shù)被替換為 -1。

    2. 代碼注釋: “中心示例: 將截?cái)?token 后的所有 token 替換為填充 token”

    3. 代碼注釋: “中心示例: 確保樣本包含 truncate_token

    4. 代碼注釋: “只對通過該功能的響應(yīng)進(jìn)行人類查詢”

    5. Ziegler 等人 (2019) 建議: “我們使用拒絕采樣來確保在第 16 和 24 個(gè) token 之間有一個(gè)句號,然后在那個(gè)句號處截?cái)?(這是‘句子結(jié)束’的粗略近似。我們選擇它是因?yàn)樗苋菀准傻?RL 循環(huán)中,即使是粗略的近似也足以使人類評估任務(wù)變得稍微容易一些)。在 RL 微調(diào)期間,我們對沒有這樣的句號的延續(xù)給予固定獎(jiǎng)勵(lì) -1?!?/p>

    6. 具體來說,通過以下步驟實(shí)現(xiàn)此目的:

  1. 折現(xiàn)因子 (discount factor) = 1

    1. 折現(xiàn)因子 設(shè)置為 1 (lm_human_preferences/train_policy.py#L56),這意味著未來的獎(jiǎng)勵(lì)與即時(shí)獎(jiǎng)勵(lì)具有相同的權(quán)重。

  2. 訓(xùn)練循環(huán)的術(shù)語: PPO 中的批次和小批次

    1. OAI 使用以下訓(xùn)練循環(huán) (lm_human_preferences/train_policy.py#L184-L192)。注意: 我們額外添加了 micro_batch_size 來幫助處理梯度累積的情況。在每個(gè)時(shí)期,它都會(huì)洗牌批次索引。



  1. 基于每個(gè)標(biāo)記的 KL 懲罰

    • 在第一個(gè) PPO 更新時(shí)期和小批次更新時(shí),激活策略將具有相同的對數(shù)概率new_logprobs=[-3.3213, -4.9980, -3.8690] 。因此,每個(gè)標(biāo)記的 KL 懲罰將為 kl = new_logprobs - logprobs = [0., 0., 0.] 。

    • 但是,在第一個(gè)梯度反向傳播后,我們可能會(huì)得到 new_logprob=[3.3213, -4.9980, -3.8690] ,因此每個(gè)標(biāo)記的 KL 懲罰變?yōu)?kl = new_logprobs - logprobs = [-0.3315, -0.0426, 0.6351]

    • 隨后,non_score_reward = beta * kl ,其中 beta 是 KL 懲罰系數(shù) ,它被添加到從獎(jiǎng)勵(lì)模型獲得的 score 中,以創(chuàng)建用于訓(xùn)練的 rewardsscore 僅在每個(gè)回合 ( episode ) 結(jié)束時(shí)給出,可能類似于 [0.4] ,然后我們有 rewards = [beta * -0.3315, beta * -0.0426, beta * 0.6351 + 0.4] 。

    • 代碼為獎(jiǎng)勵(lì)添加了每個(gè)標(biāo)記的 KL 懲罰 (lm_human_preferences/train_policy.py#L150-L153),以阻止策略與原始策略差異過大。

    • 以 “usually, he would” 為例,它被標(biāo)記化為 [23073, 11, 339, 561] 。假設(shè)我們使用 [23073] 作為查詢,[11, 339, 561] 作為響應(yīng)。然后在默認(rèn)的 gpt2 參數(shù)下,響應(yīng)標(biāo)記將具有參考策略的對數(shù)概率 logprobs=[-3.3213, -4.9980, -3.8690] 。

  2. 每個(gè)小批次的獎(jiǎng)勵(lì)和優(yōu)勢白化,可選擇均值平移

    1. OAI 實(shí)現(xiàn)了一個(gè)名為 whiten 的函數(shù),如下所示,基本上通過減去其均值然后除以其標(biāo)準(zhǔn)差來對 values 進(jìn)行歸一化。可選地,whiten 可以通過 shift_mean=True 將白化后的 values 平移到均值。


  1. 在每個(gè)小批次中,OAI 使用 whiten(rewards, shift_mean=False) 對獎(jiǎng)勵(lì)進(jìn)行白化,不對均值進(jìn)行平移處理 (lm_human_preferences/train_policy.py#L325),并使用平移后的均值對優(yōu)勢進(jìn)行白化 whiten(advantages) (lm_human_preferences/train_policy.py#L338)。

  2. 優(yōu)化注意事項(xiàng): 如果小批次的數(shù)量為一 (在此復(fù)現(xiàn)中是這種情況),我們只需要對獎(jiǎng)勵(lì)進(jìn)行白化、計(jì)算并對優(yōu)勢進(jìn)行一次白化,因?yàn)樗鼈兊闹挡粫?huì)改變。

  3. TensorFlow vs PyTorch 注意事項(xiàng): tf.momentstorch.var 的不同行為: 由于方差計(jì)算方式不同,Torch 和 TensorFlow 中的白化行為不同:


  1. 裁剪值函數(shù)

    1. 與原始的 PPO 一樣 (baselines/ppo2/model.py#L68-L75),值函數(shù)被裁剪 (lm_human_preferences/train_policy.py#L343-L348),方式與策略目標(biāo)類似。

  2. 自適應(yīng) KL 散度

    • KL 散度懲罰系數(shù) 根據(jù)當(dāng)前策略與先前策略之間的 KL 散度自適應(yīng)修改。如果 KL 散度超出預(yù)定的目標(biāo)范圍,則調(diào)整懲罰系數(shù)以使其更接近目標(biāo)范圍 (lm_human_preferences/train_policy.py#L115-L124)。它的實(shí)現(xiàn)如下:


    • 對于本工作中研究的 sentimentdescriptiveness 任務(wù),我們使用了 init_kl_coef=0.15, hparams.target=6, hparams.horizon=10000

PyTorch Adam 優(yōu)化器與 RLHF 相關(guān)的數(shù)值問題

  • 這個(gè)實(shí)現(xiàn)細(xì)節(jié)非常有趣,值得專門一節(jié)來討論。

  • PyTorch 的 Adam 優(yōu)化器 (torch.optim.Adam.html) 與 TensorFlow 的 Adam 優(yōu)化器 (TF1 Adam 在 tensorflow/v1.15.2/adam.py,TF2 Adam 在 keras/adam.py#L26-L220) 有不同的實(shí)現(xiàn)方式。具體來說, PyTorch 遵循了 Kingma 和 Ba 的 Adam 論文中的算法 1 (arxiv/1412.6980),而 TensorFlow 使用了該論文第 2.1 節(jié)前的公式,這里提到的 epsilon 在論文中稱為 epsilon hat 。在偽代碼比較中,我們有以下內(nèi)容:


  • 讓我們比較一下 PyTorch 風(fēng)格和 TensorFlow 風(fēng)格 Adam 的更新方程。按照 Adam 論文 (Kingma 和 Ba,2014) 的符號表示,我們可以得到 PyTorch Adam (Kingma 和 Ba 論文的算法 1) 和 TensorFlow 風(fēng)格 Adam (Kingma 和 Ba 論文第 2.1 節(jié)前的公式) 的梯度更新規(guī)則如下:

    %5Cbegin%7Baligned%7D%5Ctext%7Bpytorch%20adam%20%3A%7D%5Cquad%20%5Ctheta_t%20%26%20%3D%5Ctheta_%7Bt-1%7D-%5Calpha%20%5Ccdot%20%5Chat%7Bm%7D%20_t%20%2F%5Cleft(%5Csqrt%7B%5Chat%7Bv%7D%20_t%7D%2B%5Cvarepsilon%5Cright)%20%5C%26%20%3D%5Ctheta_%20%7Bt-1%7D-%20%5Calpha%20%5Cunderbrace%7B%5Cleft%5Bm_t%20%2F%5Cleft(1-%5Cbeta_1%5Et%5Cright)%5Cright%5D%7D_%20%7B%3D%5Chat%7Bm%7D%20_t%7D%20%2F%5Cleft%5B%5Csqrt%7B%5Cunderbrace%7Bv_t%20%2F%5Cleft(1-%5Cbeta_2%5Et%5Cright)%7D_%20%7B%3D%5Chat%7Bv%7D%20_t%7D%20%7D%2B%5Cvarepsilon%5Cright%5D%5C%26%20%3D%5Ctheta_%20%7Bt-1%7D-%20%5Calpha%5Cleft%5Bm_t%20%2F%5Cleft(1-%5Cbeta_1%5Et%5Cright)%5Cright%5D%5Cfrac%7B%5Csqrt%7B1-%5Cbeta_2%5Et%7D%7D%7B%5Csqrt%7Bv_t%7D%2B%5Ccolor%7Bgreen%7D%7B%5Cvarepsilon%20%5Csqrt%7B1-%5Cbeta_2%5Et%7D%7D%7D%5Cend%7Baligned%7D

    %5Cbegin%7Baligned%7D%5Ctext%7Btensorflow%20adam%3A%7D%5Cquad%20%5Ctheta_t%20%26%20%3D%5Ctheta_%7Bt-1%7D-%5Calpha_t%20m_t%20%2F%5Cleft(%5Csqrt%7Bv_t%7D%2B%5Chat%7B%5Cvarepsilon%7D%5Cright)%20%5C%26%20%3D%5Ctheta_%7Bt-1%7D-%5Cunderbrace%7B%5Cleft%5B%5Calpha%20%5Csqrt%7B1-%5Cbeta_2%5Et%7D%20%2F%5Cleft(1-%5Cbeta_1%5Et%5Cright)%5Cright%5D%7D%20_%7B%3D%5Calpha_t%7D%20m_t%20%2F%5Cleft(%5Csqrt%7Bv_t%7D%2B%5Chat%7B%5Cvarepsilon%7D%5Cright)%20%5C%26%20%3D%5Ctheta_%20%7Bt-1%7D-%20%5Calpha%5Cleft%5Bm_t%20%2F%5Cleft(1-%5Cbeta_1%5Et%5Cright)%5Cright%5D%20%5Cfrac%7B%5Csqrt%7B1-%5Cbeta_2%5Et%7D%7D%7B%5Csqrt%7Bv_t%7D%2B%5Ccolor%7Bgreen%7D%7B%5Chat%7B%5Cvarepsilon%7D%7D%7D%20%5Cend%7Baligned%7D

  • 上面的方程強(qiáng)調(diào)了 PyTorch 和 TensorFlow 實(shí)現(xiàn)之間的區(qū)別在于它們的 歸一化項(xiàng),即?%5Ccolor%7Bgreen%7D%7B%5Cvarepsilon%20%5Csqrt%7B1-%5Cbeta_2%5Et%7D%7D 和 ?%5Ccolor%7Bgreen%7D%7B%5Chat%7B%5Cvarepsilon%7D%7D。如果我們設(shè)置 %5Chat%7B%5Cvarepsilon%7D%20%3D%20%5Cvarepsilon%20%5Csqrt%7B1-%5Cbeta_2%5Et%7D,則這兩個(gè)版本是等價(jià)的。然而,在 PyTorch 和 TensorFlow 的 API 中,我們只能通過 eps 參數(shù)設(shè)置 %5Cvarepsilon (PyTorch) 和 ?%5Chat%7B%5Cvarepsilon%7D (TensorFlow),從而導(dǎo)致它們的更新方程存在差異。如果我們將 %5Cvarepsilon 和 ?%5Chat%7B%5Cvarepsilon%7D 都設(shè)置為相同的值,比如 1e-5 會(huì)發(fā)生什么?那么對于 TensorFlow Adam,歸一化項(xiàng)?%5Chat%7B%5Cvarepsilon%7D%20%3D%20%5Ctext%7B1e-5%7D 就是一個(gè)常數(shù)。但對于 PyTorch Adam,歸一化項(xiàng)?%7B%5Cvarepsilon%20%5Csqrt%7B1-%5Cbeta_2%5Et%7D%7D 隨著時(shí)間的推移而變化。重要的是,當(dāng)時(shí)間步?t 較小時(shí),該項(xiàng)?%7B%5Cvarepsilon%20%5Csqrt%7B1-%5Cbeta_2%5Et%7D%7D 明顯小于 1e-5,隨著時(shí)間步增加,逐漸接近 1e-5。下面的圖表比較了這兩個(gè)歸一化項(xiàng)隨著時(shí)間步的變化情況:

norma_const_comparison.png
  • 上圖顯示,如果我們在 PyTorch Adam 和 TensorFlow Adam 中設(shè)置相同的 eps ,那么在訓(xùn)練的早期階段,PyTorch Adam 使用的歸一化項(xiàng)要比 TensorFlow Adam 小得多。換句話說,PyTorch Adam 在訓(xùn)練的早期采用了 更激進(jìn)的梯度更新。我們的實(shí)驗(yàn)證明了這一發(fā)現(xiàn),如下所示。

  • 這對復(fù)現(xiàn)性和性能有何影響?為了保持設(shè)置一致,我們記錄了來自 https://github.com/openai/lm-human-preferences 的原始查詢、響應(yīng)和獎(jiǎng)勵(lì),并將它們保存在 https://huggingface.co/datasets/vwxyzjn/lm-human-preferences-debug/tree/main 中。我還記錄了使用 TF1 的 AdamOptimizer 優(yōu)化器的前兩個(gè)訓(xùn)練周期的指標(biāo)作為基準(zhǔn)。以下是一些關(guān)鍵指標(biāo):? ?

  • 由于某種原因, PyTorch 的 Adam 生成了更激進(jìn)的更新。以下是一些證據(jù):

    • PyTorch 的 Adam 的 logprob_diff_var 高出 6 倍。這里的 logprobs_diff = new_logprobs - logprobs 是經(jīng)過兩個(gè)訓(xùn)練周期后,初始策略和當(dāng)前策略之間的標(biāo)記對數(shù)概率差異。具有更大的 logprob_diff_var 意味著對數(shù)概率變化的幅度比 OAI 的 TF1 Adam 大。

    • PyTorch 的 Adam 呈現(xiàn)更極端的最大和最小比率。這里的 ratio = torch.exp(logprobs_diff) 。具有 ratio_max=1.8121057748794556 意味著對于某些標(biāo)記,在當(dāng)前策略下抽取該標(biāo)記的概率要比 OAI 的 TF1 Adam 高 1.8 倍,而后者僅為 1.2 倍。

    • **更大的 policy/approxklpolicy/clipfrac**。由于激進(jìn)的更新,比率被剪切的次數(shù) 多 4.4 倍,近似的 KL 散度大 6 倍。

    • 這種激進(jìn)的更新可能會(huì)導(dǎo)致進(jìn)一步的問題。例如,PyTorch 的 Adam 中的logprob_diff_mean 要大 1.7 倍,這將對下一個(gè)獎(jiǎng)勵(lì)計(jì)算中的 KL 懲罰產(chǎn)生 1.7 倍大的影響; 這可能會(huì)被累積。實(shí)際上,這可能與著名的 KL 散度問題有關(guān)—— KL 懲罰遠(yuǎn)大于它應(yīng)該的值,模型可能會(huì)更多地關(guān)注它并進(jìn)行更多優(yōu)化,從而導(dǎo)致負(fù)的 KL 散度。

  • 更大的模型受到更多影響。我們進(jìn)行了一些實(shí)驗(yàn),比較了 PyTorch 的 Adam (代號 pt_adam ) 和我們自定義的類似 TensorFlow 風(fēng)格的 Adam (代號 tf_adam ) 在 gpt2gpt2-xl 上的性能。我們發(fā)現(xiàn)在 gpt2 下性能大致相似; 但是在 gpt2-xl 下,我們觀察到了更激進(jìn)的更新,這意味著更大的模型受到了更多的影響。

adam_gpt2.png
adam_gpt2_xl.png
  • 當(dāng)在 gpt2-xl 中初始策略更新更為激進(jìn)時(shí),訓(xùn)練動(dòng)態(tài)會(huì)受到影響。例如,我們發(fā)現(xiàn)使用 pt_adam 時(shí),sentimentobjective/klobjective/scores 峰值要大得多, 在其中一個(gè)隨機(jī)種子中,最大的 KL 值達(dá)到了 17.5 ,這表明了不希望的過度優(yōu)化。

  • 此外,由于 KL 更大,許多其他訓(xùn)練指標(biāo)也受到影響。例如,我們觀察到更大的 clipfrac (ratio 被 PPO 的目標(biāo)裁剪系數(shù) 0.2 裁剪的時(shí)間比例) 和 approxkl 。

局限性

注意到這項(xiàng)工作沒有嘗試復(fù)現(xiàn) CNN DM 中的摘要工作。這是因?yàn)槲覀儼l(fā)現(xiàn)訓(xùn)練耗時(shí)且不穩(wěn)定。

我們的特定訓(xùn)練運(yùn)行顯示 GPU 利用率較低 (約 30%),因此一個(gè)訓(xùn)練運(yùn)行需要近 4 天的時(shí)間,這非常昂貴 (只有 AWS 銷售 p3dn.24xlarge,每小時(shí)費(fèi)用為 31.212 美元)。

此外,訓(xùn)練也很不穩(wěn)定。雖然獎(jiǎng)勵(lì)值上升,但我們發(fā)現(xiàn)難以復(fù)現(xiàn) Ziegler 等人 (2019 年) 報(bào)告的“智能復(fù)制”行為。以下是一些樣本輸出 — 顯然,智能體出現(xiàn)了某種程度的過擬合。請查看 https://wandb.ai/openrlbenchmark/lm-human-preferences/runs/1ab47rqi/logs 以獲取更完整的日志。

tldr1.png
tldr2.png

總結(jié)

在這項(xiàng)工作中,我們深入研究了 OpenAI 的原始 RLHF (Reinforcement Learning from Human Feedback) 代碼庫,并編制了其實(shí)施細(xì)節(jié)的列表。我們還創(chuàng)建了一個(gè)最小的基礎(chǔ)版本,當(dāng)數(shù)據(jù)集和超參數(shù)受控制時(shí),可以復(fù)現(xiàn)與 OpenAI 原始 RLHF 代碼庫相同的學(xué)習(xí)曲線。此外,我們還識(shí)別了一些令人驚訝的實(shí)施細(xì)節(jié),比如 Adam 優(yōu)化器的設(shè)置,它會(huì)導(dǎo)致在 RLHF 訓(xùn)練的早期出現(xiàn)激進(jìn)的更新。

致謝

這項(xiàng)工作得到了 Hugging Face 的 Big Science 集群的支持 ??。我們還感謝 @lewtun 和 @natolambert 的建設(shè)性討論。

Bibtex

英文原文: https://hf.co/blog/the_n_implementation_details_of_rlhf_with_ppo

原文作者: Shengyi Costa Huang, Tianlin Liu, Leandro von We

譯者: innovation64

審校/排版: zhongdongy (阿東)


使用 PPO 算法進(jìn)行 RLHF 的 N 步實(shí)現(xiàn)細(xì)節(jié)的評論 (共 條)

分享到微博請遵守國家法律
姜堰市| 新巴尔虎左旗| 方山县| 神农架林区| 犍为县| 合山市| 贵阳市| 响水县| 淮滨县| 东乌珠穆沁旗| 微山县| 扎鲁特旗| 宜宾市| 敦化市| 靖边县| 弥渡县| 镇江市| 克什克腾旗| 资中县| 营山县| 德昌县| 扎兰屯市| 临夏市| 改则县| 江西省| 临潭县| 商洛市| 鄂托克前旗| 宁河县| 漳州市| 南平市| 霸州市| 饶阳县| 平利县| 铜川市| 遵化市| 汾阳市| 长海县| 海南省| 城口县| 平山县|