الكود الرسمي من الورقة "RL دون اتصال لتوليد اللغة الطبيعية مع تعلم اللغة الضمنية"
موقع المشروع | arxiv

قم بتنزيل data.zip و outputs.zip من مجلد Google Drive هنا. ضع المجلدات التي تم تنزيلها وغير مصممة ، data/ outputs/ ، بجذر الريبو. تحتوي data/ على البيانات المعالجة مسبقًا لجميع مهامنا ، outputs/ تحتوي على نقطة التفتيش الخاصة بتعليقات Reddit الخاصة بنا.
تم تصميم هذا الريبو لبيثون 3.9.7
pip install -r requirements.txt
export PYTHONPATH= " $PWD /src/ "لتشغيل تجارب الحوار المرئي ، تحتاج إلى تقديم بيئة الحوار البصري على المضيف المحلي باتباع التعليمات هنا.
لتشغيل تجارب تعليق Reddit مع مكافأة مرشح السمية:
export OPENAI_API_KEY=your_API_key scripts/ تحتوي على جميع البرامج النصية التجربة. لتشغيل أي نص في scripts/ :
python script_name.pyخياري:
python script_name.py eval.bsize=5 train.lr=1e-6 wandb.use_wandb=falsepython -m torch.distributed.launch --nproc_per_node [N_GPUs] --use_env script_name.py arg1=a arg2=b بشكل افتراضي ، سجل جميع البرامج النصية التدريبية إلى Wandb. لإيقاف هذا ، قم بتعيين wandb.use_wandb=false في تكوين التدريب.
هنا أوضح سير عمل موصى به لتدريب وكلاء RL في وضع عدم الاتصال. لنفترض أنني أريد تدريب مجموعة من وكلاء RL المختلفين على الإنترنت لتوليد تعليقات Reddit مع مكافأة السمية.
أود أولاً تدريب نموذج BC على البيانات:
cd scripts/train/toxicity/
python train_bc.pyثم قم بتحويل نقطة تفتيش BC هذه إلى واحدة متوافقة مع نماذج RL دون اتصال:
cd ../data/
python convert_bc.py --load ../../outputs/toxicity/conditional_toxicity_official_bc_test1/model.pkl --save ../../outputs/toxicity/conditional_toxicity_official_bc_test1/model_converted.pklثم قم بتحرير نقطة التفتيش التي يتم تكوين RL في وضع عدم الاتصال للتدريب مع:
cd ../train/
python train_iql.py model.load.checkpoint_path=outputs/toxicity/model_converted.pkl model.load.strict_load=false train.loss.awac_weight=0.0 هذا مجرد سير عمل واحد ، يمكنك أيضًا تدريب طراز BC في نفس الوقت الذي يقوم فيه وكيل RL دون اتصال عن طريق تعيين train.loss.awac_weight=1.0 في تكوين التدريب.
data/ المجلد.scripts/ على جميع البرامج النصية لتشغيل خطوات التدريب والتقييم والمعالجة المسبقة للبيانات في الورقة. يتم تنظيم البرامج النصية في المجلدات الفرعية المقابلة لمجموعة البيانات المستخدمة.config/ يحتوي على. yaml التكوينات لكل نص. يستخدم هذا الريبو هيدرا لإدارة التكوينات. يتم تنظيم التكوينات في المجلدات الفرعية المقابلة لمجموعة البيانات المستخدمة. تتم تسمية معظم ملفات التكوين على أنها نفس البرنامج النصي المقابل ، ولكن إذا لم تكن متأكدًا من التكوين الذي يتوافق مع البرنامج النصي ، فتحقق من السطر @hydra.main(config_path="some_path", config_name="some_name") لمعرفة ملف التكوين يتوافق البرنامج النصي.src/ يحتوي على جميع التطبيقات الأساسية. انظر src/models/ لجميع تطبيقات النماذج. راجع src/data/ لجميع معالجة البيانات الأساسية ورمز تجريد MDP. انظر src/utils/ للاطلاع على وظائف الأداة المساعدة المختلفة. راجع src/wordle/ ، src/visdial ، src/toxicity/ لجميع Wordle ، الحوار البصري ، ورمز DataSet Reddit على التوالي.ILQL باسم iql في جميع أنحاء الريبو. يرتبط كل برنامج نصي بملف التكوين. يحدد ملف التكوين النماذج ومجموعة البيانات والمقيِّمين التي سيتم تحميلها بواسطة البرنامج النصي ومكافآتها المقابلة. انظر configs/toxicity/train_iql.yaml للحصول على مثال.
يتم إعطاء كل نموذج محتمل أو مجموعة بيانات أو كائن المقيِّم ملف التكوين الخاص به ، والذي يحدد القيم الافتراضية لهذا الكائن وسمة name الخاصة ، والتي تخبر مدير التكوين ما هو الفئة التي يجب تحميلها. انظر configs/toxicity/model/per_token_iql.yaml للحصول على مثال.
الملفات src/load_objects.py ، src/wordle/load_objects.py ، src/visdial/load_objects.py ، و src/toxicity/load_objects.py تحدد كيفية تحميل كل كائن من التكوين المقابل. علامة @register('name') فوق كل روابط دالة كائن تحميل إلى سمة name في التكوين.
قد تلاحظ سمة cache_id خاصة مرتبطة ببعض الكائنات في التكوين. على سبيل المثال ، انظر train_dataset في configs/toxicity/train_iql.yaml . تخبر هذه السمة مدير التكوين بتخزين الكائن الأول الذي يرتبط به هذا المعرف ، ثم لإرجاع هذا الكائن المخطط المخزن المؤقت لتكوين الكائن اللاحق مع هذا cache_id .
لجميع التكوينات ، استخدم المسارات بالنسبة لجذر الريبو.
كل من المهام في ريبو - wordle ، الحوار البصري ، وتعليقات Reddit - تنفذ بعض الفصول الأساسية. بمجرد تنفيذها ، يمكن تطبيق جميع خوارزميات RL في وضع عدم الاتصال على المهمة بطريقة توصيل ولعب. راجع قسم "إنشاء المهام الخاصة بك" للحصول على نظرة عامة على ما ينبغي تنفيذه من أجل إنشاء مهامك الخاصة. أدناه ، نقوم بتوضيح التجريدات الرئيسية التي تجعل هذا ممكنًا.
data.language_environment.Language_Environment - تمثل بيئة POMDP المهمة ، والتي يمكن للسياسة التفاعل معها. لديها واجهة تشبه صالة الألعاب الرياضية.data.language_environment.Policy - تمثل سياسة يمكن أن تتفاعل مع البيئة. كل من خوارزميات RL في وضع عدم الاتصال في src/models/ له سياسة مقابلة.data.language_environment.Language_Observation - يمثل مراقبة نص يتم إرجاعها من قبل البيئة ويعطى كمدخلات لسياسة ما.data.language_environment.interact_environment - وهي وظيفة تأخذ في بيئة وسياسة ، واختياري الملاحظة الحالية وتدير حلقة تفاعل البيئة. إذا لم يتم توفير الملاحظة الحالية ، فإنها تجلب تلقائيًا حالة أولية عن طريق إعادة تعيين البيئة.data.rl_data.DataPoint - يحدد تنسيق بيانات موحد يتم تغذية كمدخلات لجميع عوامل RL دون اتصال في جميع المهام. يتم إنشاء هياكل البيانات هذه تلقائيًا من Language_Observation معينة.data.rl_data.TokenReward - يحدد وظيفة المكافأة المعطاة في كل رمز مميز ، والتي يمكن استخدامها لتعلم المزيد من التحكم في الحبيبات. يتم توفير هذا أعلى مكافأة البيئة ، والتي لا تأتي في كل رمز ولكن بدلاً من ذلك بعد كل منعطف من التفاعل. في جميع تجاربنا ، قمنا بتعيين هذه المكافأة على 0 ، بحيث لا يكون لها أي تأثير.data.tokenizer.Tokenizer - يحدد كيفية تحويل السلاسل من وإلى تسلسل الرموز التي يمكن تغذية بعد ذلك كمدخلات لنماذج اللغة.data.rl_data.RL_Dataset - يحدد كائن مجموعة البيانات التي تُرجع كائنات DataPoint وتستخدم لتدريب وكلاء RL في وضع عدم الاتصال. هناك نسختان من RL_Dataset :List_RL_DatasetIterable_RL_Dataset
هنا نضع وتوثيق جميع مكونات مهمة Wordle.
يتم إجراء الكثير من ما هو موجود في مثال البرامج النصية تلقائيًا بواسطة مدير التكوين ، ويمكن تحرير المعلمات المقابلة عن طريق تغيير التكوينات. ولكن إذا كنت ترغب في الالتفاف باستخدام التكوينات واستخدام مهمة Wordle باستخدام قاعدة الشفرة الخاصة بك ، فيمكنك الرجوع إلى البرامج النصية والوثائق أدناه لكيفية القيام بذلك.
مثال بسيط على برنامج نصي للعب wordle في سطر الأوامر.
from wordle . wordle_env import WordleEnvironment
from wordle . wordle_game import Vocabulary
from wordle . policy import UserPolicy
from data . language_environment import interact_environment
from utils . misc import convert_path
game_vocab = Vocabulary . from_file ( convert_path ( 'data/wordle/word_lists/wordle_official.txt' ))
env = WordleEnvironment ( game_vocab )
policy = UserPolicy ()
interact_environment ( env , policy )src/wordle/wordle_game.pysrc/wordle/wordle_env.pysrc/wordle/policy.pysrc/wordle/wordle_dataset.pyلجعل اللعبة MDP صالحة ، تمثل البيئة الحالة الأساسية كمجموعة من قيود الحروف المعروفة ، وتستخدمها لتصفية المفردات للكلمات التي تلبي كل هذه القيود في كل منعطف. ثم يتم تحديد كلمة عشوائية من قائمة الكلمات المصفاة هذه واستخدامها لتحديد انتقالات الألوان التي يتم إرجاعها بواسطة البيئة. هذه التحولات الألوان الجديدة ثم تحديث مجموعة من قيود الحروف المعروفة.
بيئة wordle تأخذ في قائمة الكلمات. يتم إعطاء بعض قوائم الكلمات في data/wordle/word_lists/ ، ولكن لا تتردد في صنع خاص بك.
قوائم الكلمات المدرجة هي:
يتم تحميل قوائم الكلمة في البيئة من خلال كائن Vocabulary كما في المثال أعلاه.
from wordle . wordle_game import Vocabulary
from utils . misc import convert_path
vocab = Vocabulary . from_file ( convert_path ( 'data/wordle/word_lists/wordle_official.txt' ))لا تخزن المفردات قائمة الكلمات فحسب ، بل تتتبع أيضًا قائمة من الكلمات التي تفي بجميع قيود الحروف المعروفة في حالة معينة. يتم استخدام هذه القائمة لحساب التحولات في البيئة ويستخدمها بعض السياسات المصنوعة يدويًا.
إن إنتاج هذه القوائم المصفاة في الوقت الفعلي يمكن أن يبطئ عملية التفاعل البيئي. لا ينبغي أن يكون هذا عادةً مشكلة ، ولكن إذا كنت ترغب في تجميع الكثير من البيانات بسرعة من السياسة ، فقد يصبح هذا عنق الزجاجة. للتغلب على هذا ، تخزن جميع كائنات Vocabulary وسيطة ذاكرة cache ، والتي تقوم بتخزين قوائم الكلمات المصفاة المرتبطة بحالة معينة. يتيح vocab.cache.load(f_path) و vocab.cache.dump() تحميل وحفظ ذاكرة التخزين المؤقت. على سبيل المثال ، data/wordle/vocab_cache_wordle_official.pkl هي ذاكرة التخزين المؤقت الكبيرة لقائمة Wordle_official.txt.
إلى جانب تخزين ذاكرة التخزين المؤقت ، يقوم كائن Vocabulary بتنفيذ الأساليب التالية في src/wordle/wordle_game.py :
__init__ def __init__ ( self , all_vocab : List [ str ],
wordle_state : Optional [ WordleState ],
cache : Optional [ Cache ] = None ,
fill_cache : bool = True ) -> Noneالمدخلات:
all_vocab: List[str] - قائمة بالكلمات.wordle_state: Optional[WordleState] - حالة لإنشاء قائمة الكلمات المصفاة ، إذا لم يتم توفير حالة ، لا يتم تصفية كلمات.cache: Optional[Cache]=None - ذاكرة التخزين المؤقت للمفردات المصفاة ، كما هو موضح أعلاه.fill_cache: bool=True - ما إذا كنت تضيف إلى ذاكرة التخزين المؤقت. عائدات: None
from_file def from_file ( cls , vocab_file : str , fill_cache : bool = True ) -> Vocabularyالمدخلات:
vocab_file: str - ملف يمكن من خلاله تحميل الكلمات. تحدد الطريقة فقط الكلمات التي يبلغ طولها 5 أحرف.fill_cache: bool=True - ما إذا كنت تضيف إلى ذاكرة التخزين المؤقت. عائدات: Vocabulary
filtered_vocab_size def filtered_vocab_size ( self ) -> intإرجاع: حجم المفردات المصفاة
all_vocab_size def all_vocab_size ( self ) -> intالعائدات: حجم المفردات الكاملة غير المفلسة
get_random_word_filtered def get_random_word_filtered ( self ) -> strإرجاع: كلمة عشوائية من القائمة المصفاة.
get_random_word_all def get_random_word_all ( self ) -> strإرجاع: كلمة عشوائية من القائمة الكاملة غير المسلحة.
update_vocab def update_vocab ( self , wordle_state : WordleState ) -> Vocabularyالمدخلات:
wordle_state: WordleState - كائن حالة wordle ، يمثل مجموعة من قيود الحروف المعروفة. إرجاع: كائن Vocabulary جديدة ، يتم ترشيحها وفقًا لـ wordle_state .
__str__ def __str__ ( self ) -> strإرجاع: تمثيل سلسلة لقائمة الكلمات المصفاة للطباعة إلى المحطة.
يأخذ WordleEnvironment كائن المفردات كمدخل ، والذي يحدد مجموعة الكلمات الصحيحة المحتملة في البيئة.
from wordle . wordle_env import WordleEnvironment
from wordle . wordle_game import Vocabulary
from utils . misc import convert_path
vocab = Vocabulary . from_file ( convert_path ( 'data/wordle/word_lists/wordle_official.txt' ))
env = WordleEnvironment ( vocab )
initial_obs = env . reset ()
next_obs , reward , terminal = env . step ( "snake" ) كما هو موضح أعلاه ، تنفذ البيئة واجهة تشبه صالة الألعاب الرياضية في src/wordle/wordle_env.py :
__init__ def __init__ ( self , vocab : Vocabulary ) -> Noneالمدخلات:
vocab: Vocabulary - المفردات البيئة. عائدات: None
step def step ( self , action : str ) -> Tuple [ WordleObservation , float , bool ]المدخلات:
action: Vocabulary - سلسلة من النص الذي يمثل إجراء الوكيل في البيئة.العائدات: (الملاحظة ، المكافأة ، المحطة) tuple.
reset def reset ( self ) -> WordleObservationعائدات: ملاحظة.
is_terminal def is_terminal ( self ) -> boolالعائدات: A Boolean تشير إلى ما إذا كان التفاعل قد انتهى.
ننفذ مجموعة من سياسات wordle المصنوعة يدويًا والتي تغطي مجموعة من مستويات اللعب. يتم تنفيذ كل هذه في src/wordle/policy.py . هنا نصف كل واحد:
UserPolicy from wordle . policy import UserPolicy
policy = UserPolicy ( hint_policy = None , vocab = None )وصف:
دعنا تلعب في المحطة.
المدخلات:
hint_policy: Optional[Policy] - سياسة أخرى للاستعلام إذا كنت تريد تلميحًا على أي كلمة يجب استخدامها.vocab: Optional[Union[str, Vocabulary]] - Vocabulary من الكلمات القابلة للتخمين. إذا لم يتم تحديدها ، فإن أي تسلسل من 5 أحرف من chars هو تخمين صالح. StartWordPolicy from wordle . policy import StartWordPolicy
policy = StartWordPolicy ()وصف:
ليتم تطبيقها فقط للكلمة الأولى. يختار كلمة عشوائيًا من قائمة الكلمات المنسقة ذات الجودة العالية.
المدخلات:
start_words: Optional[List[str]]=None - تجاوز القائمة المنسقة للكلمات البدء. OptimalPolicy from wordle . policy import OptimalPolicy
policy = OptimalPolicy ()وصف:
يلعب قصر النظر أعلى المعلومات الكسب من قائمة الكلمات التي تلبي جميع قيود الحروف المعروفة. هذه السياسة ليست مثالية في الواقع ، حيث أن اللعب الأمثل هو NP-Hard. لكنه يلعب على مستوى عال للغاية ، ويمكن استخدامه كحد أقصى للأداء. هذه السياسة بطيئة للغاية في الحساب ، مع الأداء التربيعي في حجم قائمة الكلمات ؛ لحفظ الحسابات ، يتيح لك self.cache.load(f_path) و self.cache.dump() تحميل وحفظ ذاكرة التخزين المؤقت. على سبيل المثال ، تمثل data/wordle/optimal_policy_cache_wordle_official.pkl ذاكرة التخزين المؤقت لهذه السياسة على قائمة كلمات wordle_official.txt .
المدخلات:
start_word_policy: Optional[Policy]=None - نظرًا لأن الكلمة الأولى هي الأكثر تكلفة لحساب كسب المعلومات لها ، فإن ذلك يتيح لك تحديد سياسة مختلفة يتم استدعاؤها للكلمة الأولى فقط.progress_bar: bool=False - نظرًا لأن الأمر قد يستغرق وقتًا طويلاً للحساب ، فإننا نتركك خيار عرض شريط التقدم لكل مكالمة إلى self.act . RepeatPolicy from wordle . policy import RepeatPolicy
policy = RepeatPolicy ( start_word_policy = None , first_n = 2 )وصف:
يكرر بشكل عشوائي إحدى الكلمات first_n المستخدمة بالفعل. هذه سياسة دون المستوى الأمثل إلى أقصى حد ، لأنها لا يمكن أن تفوز أبدًا إلا إذا كانت محظوظة على الكلمة الأولى.
المدخلات:
start_word_policy: Optional[Policy] - سياسة لاستخدامها لاختيار الكلمة الأولى. إذا None ، فحسب بشكل عشوائي كلمة من مفردات البيئة.first_n: Optional[int] - تحدد السياسة بشكل عشوائي الكلمة التالية من الكلمات first_n في التاريخ. إذا None ، فإنه يختار بشكل عشوائي من التاريخ الكامل. RandomMixturePolicy from wordle . policy import RandomMixturePolicy
policy = RandomMixturePolicy ( prob_smart = 0.5 , vocab = None )وصف:
يختار كلمة بشكل عشوائي بالكامل من قائمة الكلمات ذات الاحتمال (1 - prob_smart) ويختار كلمة عشوائية من قائمة الكلمات التي تلبي جميع قيود الحروف المعروفة مع الاحتمال prob_smart .
المدخلات:
prob_smart: float - احتمال اختيار كلمة تلبي جميع قيود الحروف المعروفة ، بدلاً من واحدة بشكل عشوائي.vocab: Optional[Union[str, Vocabulary]] - قائمة كلمات للاختيار من بينها. إذا None ، فإن السياسة تتخلف عن قائمة كلمات البيئة. WrongPolicy from wordle . policy import WrongPolicy
from wordle . wordle_game import Vocabulary
vocab = Vocabulary . from_file ( 'data/wordle/word_lists/wordle_official.txt' )
policy = WrongPolicy ( vocab )وصف:
يختار بشكل عشوائي كلمة من قائمة الكلمات التي تفشل في تلبية جميع قيود الحروف المعروفة وبالتالي لا يمكن أن تكون الكلمة الصحيحة. إذا كانت جميع الكلمات في قائمة الكلمات تلبي قيود الحروف ، فإنها تختار كلمة عشوائية من القائمة. هذه السياسة شديدة دون المستوى الأمثل.
المدخلات:
vocab: Union[str, Vocabulary] - قائمة كلمات للاختيار من بينها. MixturePolicy from wordle . policy import MixturePolicy , OptimalPolicy , RandomMixturePolicy
policy1 = OptimalPolicy ()
policy2 = RandomMixturePolicy ( prob_smart = 0.5 , vocab = None )
policy = MixturePolicy ( prob1 = 0.5 , policy1 = policy1 , policy2 = policy2 )وصف:
يمزج بين اثنين من السياسات المعطاة. اختر من policy1 مع الاحتمال prob1 واختر من policy2 مع الاحتمال (1 - prob1) .
المدخلات:
prob1: float - احتمال اختيار إجراء من policy1 .policy1: Policy - السياسة الأولى لاختيار الإجراءات من. تم اختياره مع الاحتمال prob1 .policy1: Policy - السياسة الثانية لاختيار الإجراءات من. تم اختياره مع الاحتمال (1 - prob1) . MonteCarloPolicy from wordle . policy import MonteCarloPolicy
sample_policy = RandomMixturePolicy ( prob_smart = 0.5 , vocab = None )
policy = MonteCarloPolicy ( n_samples = 5 , sample_policy = sample_policy )وصف:
يأخذ سياسة ، ويدير n_samples من مونت كارلو في البيئة ، ويختار الإجراء التالي الذي حصل على أعلى مكافأة متوسط أثناء عملية البدء.
المدخلات:
n_samples: int - عدد عمليات ترحيل Monte Carlo للتنفيذ.sample_policy: Policy - السياسة لعينة التمرير من. 
يمكن استخدام أي من السياسات المذكورة أعلاه لإنشاء مجموعات بيانات ، والتي يمكن استخدامها لتدريب وكلاء RL في وضع عدم الاتصال. نحن ننفذ ، في src/wordle/wordle_dataset.py ، نوعان من مجموعات البيانات الاصطناعية:
wordle.wordle_dataset.WordleListDataset - يحمل ألعاب wordle من ملف.wordle.wordle_dataset.WordleIterableDataset - عينات ألعاب wordle من سياسة معينة.WordleListDataset :قم بتحميل مجموعة بيانات Wordle من ملف مثل SO:
from wordle . wordle_dataset import WordleListDataset
from data . rl_data import ConstantTokenReward
data = WordleListDataset . from_file (
file_path = 'data/wordle/expert_wordle_100k.pkl' ,
max_len = None ,
vocab = None ,
token_reward = ConstantTokenReward ( 0.0 ),
)
for i in range ( data . size ()):
item = data . get_item ( i )__init__ def __init__ ( self , items : List [ Tuple [ WordleObservation , Optional [ Dict [ str , Any ]]]], max_len : Optional [ int ], token_reward : TokenReward ) -> Noneالمدخلات:
items: List[Tuple[WordleObservation, Optional[Dict[str, Any]]]] - قائمة بالبيانات في شكل tuples من (wordleobservation ، metadata_dict). عندما يكون metadata_dict أي نوع من البيانات الوصفية هو أي نوع من البيانات الوصفية التي قد ترغب في تخزينها في نقطة البيانات.max_len: Optional[int] - الحد الأقصى لطول التسلسل في مجموعة البيانات ، سوف يقتصر جميع تسلسل الرمز المميز لهذا الطول. إذا None يتم اقتطاع التسلسلات.token_reward: TokenReward المكافأة على مستوى الرمز المميز لتطبيقها على التسلسلات. نحن نستخدم مكافأة ثابتة من 0 لكل حشوة لجميع التجارب. عائدات: None
from_file def from_file ( cls , file_path : str , max_len : Optional [ int ], vocab : Optional [ Vocabulary ], token_reward : TokenReward ) -> WordleListDatasetالمدخلات:
file_path: str - المسار إلى ملف مخلل البيانات.max_len: Optional[int] - الحد الأقصى لطول التسلسل في مجموعة البيانات ، سوف يقتصر جميع تسلسل الرمز المميز لهذا الطول. إذا None يتم اقتطاع التسلسلات.vocab: Optional[Vocabulary] - محاكاة مجموعة البيانات تحت مفردات بيئة مختلفة. إذا None ، فإن الافتراضات لاستخدام نفس المفردات التي تم استخدامها لإنشاء مجموعة البيانات.token_reward: TokenReward المكافأة على مستوى الرمز المميز لتطبيقها على التسلسلات. نحن نستخدم مكافأة ثابتة من 0 لكل حشوة لجميع التجارب. إرجاع: كائن WordleListDataset .
get_item def get_item ( self , idx : int ) -> DataPointالمدخلات:
idx: int - فهرس في مجموعة البيانات. إرجاع: كائن DataPoint .
size def size ( self ) -> intإرجاع: حجم مجموعة البيانات.
يمكن استخدام البرامج النصية التالية في scripts/data/wordle/ لتوليف بيانات wordle.
| السيناريو | وصف |
|---|---|
generate_data.py | عينات عدد من الألعاب من سياسة معينة محددة في التكوين وحفظها في ملف. |
generate_data_mp.py | نفس الشيء مثل generate_data.py باستثناء عينات ألعاب بالتوازي مع عمليات متعددة. |
generate_adversarial_data.py | يقوم بتجميع مجموعة البيانات الموضحة في القسم 5 من ورقتنا ، والتي تم تصميمها لإظهار الفرق بين طرق RL ذات الخطوة الواحدة والخطوات المتعددة. |
generate_adversarial_data_mp.py | نفس الشيء مثل generate_adversarial_data.py باستثناء عينات ألعاب بالتوازي مع عمليات متعددة. |
generate_data_branch.py | عينات ألعاب من سياسة "خبير" معينة ومن ثم من كل إجراء في اللعبة ، تفرع سياسة "دون المستوى الأمثل" عن أخذ عينات من عدد من الألعاب الجديدة. |
generate_data_branch_mp.py | نفس الشيء مثل generate_data_branch.py باستثناء أخذ عينات من الألعاب بالتوازي مع عمليات متعددة. |
بعض مجموعات البيانات الاصطناعية الاصطناعية في data/wordle/ .
| ملف | وصف |
|---|---|
expert_wordle_100k_1.pkl | 100K ألعاب تم أخذ عينات منها من OptimalPolicy . |
expert_wordle_100k_2.pkl | 100 ألف لعبة أخرى تم أخذ عينات منها من OptimalPolicy . |
expert_wordle_adversarial_20k.pkl | مجموعة البيانات الموضحة في القسم 5 من ورقتنا ، والتي تم تصميمها لإظهار الفرق بين أساليب RL ذات الخطوة الواحدة والخطوات المتعددة. |
expert_wordle_branch_100k.pkl | 100k ألعاب تم أخذ عينات منها باستخدام generate_data_branch.py من OptimalPolicy مع فروع تم أخذ عينات من WrongPolicy . |
expert_wordle_branch_150k.pkl | تم أخذ عينات من 150 ألفًا من الألعاب التي تم أخذ عينات منها باستخدام generate_data_branch.py من OptimalPolicy مع فروع تم أخذ عينات منها من WrongPolicy . |
expert_wordle_branch_2k_10sub.pkl | 2K ألعاب تم أخذ عينات منها باستخدام generate_data_branch.py من OptimalPolicy مع 10 فروع لكل إجراء تم أخذ عينات منها من WrongPolicy ، بحيث يكون هناك بيانات دون المستوى الأمثل أكثر بكثير من expert_wordle_branch_100k.pkl . |
expert_wordle_branch_20k_10sub.pkl | نفس expert_wordle_branch_2k_10sub.pkl باستثناء 20 ألف ألعاب بدلاً من ألعاب 2K. |
WordleIterableDataset :توليد أخذ عينات من بيانات wordle من سياسة مثل ذلك:
from wordle . wordle_dataset import WordleIterableDataset
from wordle . policy import OptimalPolicy
from data . rl_data import ConstantTokenReward
policy = OptimalPolicy ()
vocab = Vocabulary . from_file ( 'data/wordle/word_lists/wordle_official.txt' )
data = WordleIterableDataset (
policy = policy ,
vocab = vocab ,
max_len = None ,
token_reward = ConstantTokenReward ( 0.0 ),
)
while True :
item = data . sample_item ()__init__ def __init__ ( self , policy : Policy , vocab : Vocabulary , max_len : Optional [ int ], token_reward : TokenReward ) -> Noneالمدخلات:
policy: Policy - سياسة لعينة من.vocab: Vocabulary - المفردات البيئة.max_len: Optional[int] - الحد الأقصى لطول التسلسل في مجموعة البيانات ، سوف يقتصر جميع تسلسل الرمز المميز لهذا الطول. إذا None يتم اقتطاع التسلسلات.token_reward: TokenReward المكافأة على مستوى الرمز المميز لتطبيقها على التسلسلات. نحن نستخدم مكافأة ثابتة من 0 لكل حشوة لجميع التجارب. عائدات: None
sample_item def sample_item ( self ) -> DataPoint إرجاع: كائن DataPoint .
لدينا مجموعة بيانات كبيرة تضم أكثر من 200 ألف تغريدة من ألعاب Wordle مثل هذا:

يمكننا تعديل الكلمات إلى مربعات انتقال الألوان هذه لإنشاء مجموعة بيانات حقيقية من ألعاب Wordle.
يتم تقديم بيانات التغريد الخام في data/wordle/tweets.csv ، ولكن لكي تكون قابلة للاستخدام ، يجب إعادة تجهيز الكلمات الفعلية على مربعات الألوان في التغريدات. يتطلب إجراء عملية التعديل التحديثي هذه تنفيذ برنامج نصي مسبقًا يقوم بتخزين جميع انتقالات الألوان الممكنة التي يمكن أن تحدث ضمن قوائم Vocab: guess_vocab (مجموعة من الكلمات القابلة للتخمين) و correct_vocab (مجموعة من الكلمات الصحيحة المحتملة في بيئة). والنتيجة هي بنية بيانات التي يستخدمها wordle.wordle_dataset.WordleHumanDataset لتوليف ألعاب wordle صالحة من التغريدات. هذا البرنامج النصي هو scripts/data/wordle/build_human_datastructure.py . استدعاء السيناريو مثل:
cd scripts/data/wordle/
python build_human_datastructure.py --guess_vocab=../../../data/wordle/word_lists/wordle_official.txt --correct_vocab=../../../data/wordle/word_lists/wordle_official.txt --tweets_file=../../../data/wordle/tweets.csv --output_file=../../../data/wordle/random_human_tweet_data.jsonargs السيناريو:
--guess_vocab مجموعة من الكلمات القابلة للتخمين.--correct_vocab يحدد مجموعة الكلمات الصحيحة المحتملة في بيئة.--tweets_file يحدد ملف CSV الخام للتغريدات--output_file يحدد مكان تفريغ الإخراج. لقد قمنا بتشغيل المعالجة المسبقة على بعض قوائم الكلمات ، مع حفظ النتائج في data/wordle/ .
| قائمة الكلمات | ملف بيانات التغريد المعالجة مسبقًا |
|---|---|
wordle_official.txt | random_human_tweet_data.json |
wordle_official_800.txt | random_human_tweet_data_800.json |
wordle_official_400.txt | random_human_tweet_data_400.json |
wordle_official_200.txt | random_human_tweet_data_200.json |
tweet_words.txt | human_tweet_data_true_word.json |
بالنظر إلى أحد هذه الملفات ، يمكنك تحميل مجموعة بيانات تغريدة Wordle مثل:
from wordle . wordle_dataset import WordleHumanDataset
data = WordleHumanDataset . from_file ( 'data/wordle/random_human_tweet_data_200.json' )
print ( data . sample_item ()) استخدمنا 'data/wordle/random_human_tweet_data_200.json' في تجاربنا.
WordleHumanDataset : __init__ def __init__ ( self , games : List [ Tuple [ str , List [ str ]]], transitions : Dict [ str , Dict [ str , List [ str ]]], use_true_word : bool , max_len : Optional [ int ], token_reward : TokenReward , game_indexes : Optional [ List [ int ]], top_p : Optional [ float ]) -> Noneالمدخلات:
games: List[Tuple[str, List[str]]] - قائمة من tuples من النموذج (correct_wordle_word, wordle_transitions_list) ، حيث تكون wordle_transitions_list قائمة بالتحولات التي تشير إلى الألوان في تغرد ["<b><b><y><y><b>", "<g><b><b><b><b>", "<g><g><y><b><b>", "<g><g><g><g><g>"] .transitions: Dict[str, Dict[str, List[str]]] - رسم تخطيطي للكلمة الصحيحة الصحيح إلى رسم تخطيطي آخر من التحولات الملونة المحتملة التي كان يمكن أن تسببها تلك الكلمة إلى قائمة من الكلمات التي كان من الممكن لعبها للتسبب في هذا الانتقال. يتم استخدام بنية البيانات هذه لتحديث الكلمات على التغريدات.use_true_word: bool إذا كان True ، فاستخدم الكلمة الصحيح للشعب الأرضي من التغريد ، وإعادة تعديل أي كلمة صحيحة في قائمة الكلمات التي تعمل.max_len: Optional[int] - الحد الأقصى لطول التسلسل في مجموعة البيانات ، سوف يقتصر جميع تسلسل الرمز المميز لهذا الطول. إذا None يتم اقتطاع التسلسلات.token_reward: TokenReward المكافأة على مستوى الرمز المميز لتطبيقها على التسلسلات. نحن نستخدم مكافأة ثابتة من 0 لكل حشوة لجميع التجارب.game_indexes: Optional[List[int]] - قائمة الفهارس لإنشاء تقسيم للتغريدات. إذا None يتم استخدام جميع العناصر الموجودة في البيانات. لدينا data/wordle/human_eval_idxs.json و data/wordle/human_train_idxs.json التي تم إنشاؤها كقطارات و eval التي تم اختيارها بشكل عشوائي.top_p: Optional[float] - تصفية لـ top_p التي تنفذ النسبة المئوية للبيانات. إذا لم يتم ترشيح None بيانات. تستخدم مع نماذج ٪ قبل الميلاد. عائدات: None
from_file def from_file ( cls , file_path : str , use_true_word : bool = False , max_len : Optional [ int ] = None , token_reward : Optional [ TokenReward ] = None , top_p : Optional [ float ] = None ) -> WordleHumanDatasetالمدخلات:
file_path: str - المسار إلى ملف JSON لتحميل البيانات من.use_true_word: bool إذا كان True ، فاستخدم الكلمة الصحيح للشعب الأرضي من التغريد ، وإعادة تعديل أي كلمة صحيحة في قائمة الكلمات التي تعمل.max_len: Optional[int] - الحد الأقصى لطول التسلسل في مجموعة البيانات ، سوف يقتصر جميع تسلسل الرمز المميز لهذا الطول. إذا None يتم اقتطاع التسلسلات.token_reward: TokenReward المكافأة على مستوى الرمز المميز لتطبيقها على التسلسلات. نحن نستخدم مكافأة ثابتة من 0 لكل حشوة لجميع التجارب.game_indexes: Optional[List[int]] - قائمة الفهارس لإنشاء تقسيم للتغريدات. إذا None يتم استخدام جميع العناصر الموجودة في البيانات. لدينا data/wordle/human_eval_idxs.json و data/wordle/human_train_idxs.json التي تم إنشاؤها كقطارات و eval التي تم اختيارها بشكل عشوائي.top_p: Optional[float] - تصفية لـ top_p التي تنفذ النسبة المئوية للبيانات. إذا لم يتم ترشيح None بيانات. تستخدم مع نماذج ٪ قبل الميلاد. عائدات: كائن WordleHumanDataset .
sample_item def sample_item ( self ) -> DataPoint إرجاع: كائن DataPoint .
البرامج النصية التدريبية موجودة في scripts/train/wordle/ .
| السيناريو | وصف |
|---|---|
train_bc.py | تدريب وكيل قبل الميلاد. |
train_iql.py | تدريب وكيل ILQL. |
البرامج النصية للتقييم موجودة في scripts/eval/wordle/ .
| السيناريو | وصف |
|---|---|
eval_policy.py | تقييم عامل BC أو ILQL في بيئة Wordle. |
eval_q_rank.py | البرنامج النصي للتقييم لمقارنة المرتبة النسبية لقيم Q للعوامل المدربين على مجموعة البيانات الاصطناعية الموضحة في القسم 5 من ورقتنا ، والتي تم تصميمها لإظهار الفرق بين RL خطوة واحدة و RL متعددة الخطوات. |
distill_policy_eval.py | يطبع نتيجة eval_policy.py مع أشرطة الخطأ. |
هنا نوجز حول كيفية تحميل بيانات الحوار المرئي في قاعدة كودنا وكيفية تنفيذ البيئة. راجع قسم الإعداد أعلاه للحصول على كيفية إعداد المكونات البعيدة لبيئة الحوار البصري. يتم تحميل كائنات البيانات والبيئة تلقائيًا بواسطة مدير التكوين ، ولكن إذا كنت ترغب في توضيح نظام التكوين واستخدام البيئة باستخدام قاعدة الشفرة الخاصة بك ، فإليك كيفية تحميل هذه الكائنات وتنفيذها وتكوينها. يمكن تعديل نفس الإعدادات الموضحة أدناه في التكوينات أيضًا.
مثال على كيفية تحميل بيئة الحوار البصري:
from visdial . visdial_env import VDEnvironment
from visdial . visdial_base import VisDialogueData
from visdial . visdial_dataset import VisDialListDataset
from data . rl_data import ConstantTokenReward
from utils . misc import convert_path
data = VisDialogueData (
data_path = convert_path ( 'data/vis_dialogue/raw/visdial_0.5/visdial_0.5_train.json' ),
img_feat_path = convert_path ( 'data/vis_dialogue/processed/visdial_0.5/data_img.h5' ),
split = 'train' ,
reward_cache = convert_path ( 'data/vis_dialogue/processed/visdial_0.5/train_rank_reward_cache1.json' ),
yn_reward_kind = 'none'
)
list_data = VisDialListDataset (
data = data ,
max_len = None ,
token_reward = ConstantTokenReward ( 0.0 )
)
env = VDEnvironment (
dataset = list_data ,
url = 'http://localhost:5000/step_rank' ,
yn_reward = - 2.0 ,
yn_reward_kind = 'none'
)
print ( env . reset ()) يتوافق البرنامج النصي أعلاه مع كيفية تكوين مجموعة البيانات والبيئة لتجارب المكافآت "القياسية" ، ولكن إذا كنت ترغب في تكوين مجموعة البيانات بشكل مختلف ، فهناك العديد من الوسائط التي يمكنك تعديلها. إلى جانب تغيير تقسيم مجموعة البيانات ، يمكن لهذه الوسائط أيضًا تغيير المهمة أو المكافأة. فيما يلي وصف جميع المعلمات المختلفة القابلة للتكوين التي تأخذها VisDialogueData و VisDialListDataset و VDEnvironment .
نقوم بتوثيق المعلمات وطرق VisDialogueData و VisDialListDataset و VDEnvironment ، حتى تعرف كيفية تكوين البيئة بنفسك.
VisDialogueData : VisDialogueData ، التي تم تنفيذها في src/visdial/visdial_base.py ، تخزن مجموعة الحوارات والمكافآت للمهمة.
__init__ def __init__ ( self , data_path : str , img_feat_path : str , split : str , reward_cache : Optional [ str ] = None , norm_img_feats : bool = True , reward_shift : float = 0.0 , reward_scale : float = 1.0 , addition_scenes : Optional [ List [ Scene ]] = None , mode : str = 'env_stops' , cutoff_rule : Optional [ CutoffRule ] = None , yn_reward : float = - 2.0 , yn_reward_kind : str = 'none' ) -> Noneالمدخلات:
data_path: str - المسار إلى بيانات الحوار. يجب أن تكون واحدة من:data/vis_dialogue/raw/visdial_0.5/visdial_0.5_train.jsondata/vis_dialogue/raw/visdial_0.5/visdial_0.5_val.jsondata/vis_dialogue/raw/visdial_0.5/visdial_0.5_test.jsonimg_feat_path: str - المسار إلى ميزات الصورة المستخدمة لحساب المكافأة لكل حوار. يجب دائمًا أن تكون data/vis_dialogue/processed/visdial_0.5/data_img.h5 .split: str - واحد من train أو val أو test . يشير إلى تقسيم مجموعة البيانات لميزات الصورة التي يجب استخدامها. يجب أن تكون متسقة مع انقسام data_path .reward_cache: Optional[str]=None - حيث يتم تخزين المكافآت لكل حوار. إذا None ، فسيقوم بتعيين جميع المكافآت على None . نحن نقدم ذاكرة التخزين المؤقت لوظيفة مكافأة:data/vis_dialogue/processed/visdial_0.5/[split]_rank_reward_cache1.json ، حيث يتم استبدال [split] بواحد من train أو val أو test .train تخزين المكافأة القائمة val المسافة الإقليدية التي تستخدمها وكلاء الحوار المرئي التعاونية التعاونية مع test العميق في: data/vis_dialogue/processed/visdial_0.5/[split]_reward_cache2.json [split]norm_img_feats: bool=True - ما إذا كان يجب تطبيع ميزات الصورة.reward_shift: float=0.0 - قم بتحويل المكافأة بهذا المبلغ.reward_scale: float=1.0 - قم بتوسيع المكافأة بهذا المبلغ.addition_scenes: Optional[List[Scene]]=None - حقن بيانات إضافية في مجموعة البيانات.mode: str='env_stops' - واحد من ['agent_stops', 'env_stops', '10_stop'] . يتحكم في بعض خصائص المهمة. نحن نستخدم env_stopsmode='env_stops' ، ثم أوقف تفاعل البيئة مبكرًا وفقًا لـ cutoff_rule .mode='agent_stops' ، فإن الوكيل يتوقف عن التفاعل عن طريق إنشاء رمز خاص <stop> أثناء إجراءه ؛ يعزز البيانات عن طريق وضع <stop> بعد كل إجراء ممكن.mode='10_stop' ، فإن المسرحية تتوقف دائمًا بعد 10 جولات من التفاعل ، كما هو قياسي في مجموعة بيانات الحوار البصري.cutoff_rule: Optional[CutoffRule]=None - ينطبق فقط إذا mode='env_stops' . ينفذ وظيفة تحدد متى يجب أن تتوقف البيئة عن التفاعل مبكرًا. نستخدم الافتراضي لـ visdial.visdial_base.PercentileCutoffRule(1.0, 0.5) في جميع تجاربنا.yn_reward: float=-2.0 -عقوبة المكافأة التي يجب إضافتها لطرح الأسئلة نعم/لا.yn_reward_kind: str='none' - يحدد سلسلة مجريات الأمور لاستخدامها لتحديد ما إذا تم طرح نعم/لا شك. يجب أن يكون واحدًا من ['none', 'soft', 'hard', 'conservative'] .'none' : لا تعاقب نعم/لا أسئلة. هذا يتوافق مع المكافأة standard في ورقتنا.'soft' : معاقبة سؤال إذا كان الرد يحتوي على "yes" أو "no" كسلسلة فرعية.'hard' : معاقبة سؤال إذا كان الرد يتطابق تمامًا مع السلسلة "yes" أو "no" . هذا يتوافق مع مكافأة "y/n" في ورقتنا.'conservative' : معاقبة سؤال ما إذا كان الرد يفي بواحد من العديد من الاستدلال المطابقة للسلسلة. هذا يتوافق مع مكافأة "conservative y/n" في ورقتنا. عائدات: None
__len__ def __len__ ( self ) -> intإرجاع: حجم مجموعة البيانات.
__getitem__ def __getitem__ ( self , i : int ) -> Sceneالمدخلات:
i: int - فهرس مجموعة البيانات.إرجاع: عنصر من مجموعة البيانات.
VisDialListDataset : VisDialListDataset ، التي تم تنفيذها في src/visdial/visdial_dataset.py ، تلتف حول VisDialogueData وتحويلها إلى تنسيق DataPoint يمكن استخدامها لتدريب عوامل RL دون اتصال.
__init__ def __init__ ( self , data : VisDialogueData , max_len : Optional [ int ], token_reward : TokenReward , top_p : Optional [ float ] = None , bottom_p : Optional [ float ] = None ) -> Noneالمدخلات:
data: VisDialogueData - كائن بيانات حوار مرئي يخزن جميع البيانات الأولية.max_len: Optional[int] - الحد الأقصى لطول التسلسل في مجموعة البيانات ، سوف يقتصر جميع تسلسل الرمز المميز لهذا الطول. إذا None يتم اقتطاع التسلسلات.token_reward: TokenReward المكافأة على مستوى الرمز المميز لتطبيقها على التسلسلات. نحن نستخدم مكافأة ثابتة من 0 لكل حشوة لجميع التجارب.top_p: Optional[float] - تصفية لـ top_p التي تنفذ النسبة المئوية للبيانات. إذا لم يتم ترشيح None بيانات. تستخدم مع نماذج ٪ قبل الميلاد.bottom_p: Optional[float] - تصفية لـ bottom_p الذي يؤدي النسبة المئوية للبيانات. إذا لم يتم ترشيح None بيانات. عائدات: None
size def size ( self ) -> intإرجاع: حجم مجموعة البيانات.
get_item def get_item ( self , idx : int ) -> DataPointالمدخلات:
i: int - فهرس مجموعة البيانات. إرجاع: نقطة DataPoint من مجموعة البيانات.
VDEnvironment : يعرّف VDEnvironment ، الذي تم تنفيذه في src/visdial/visdial_env.py ، بيئة الحوار البصري ، والتي يتفاعل معها وكلاء RL غير متصل في وقت التقييم. تتضمن البيئة الاتصال بخادم مضيف محلي ، يصف قسم الإعداد كيفية الدوران.
__init__ def __init__ ( self , dataset : RL_Dataset , url : str , reward_shift : float = 0.0 , reward_scale : float = 1.0 , actor_stop : bool = False , yn_reward : float = - 2.0 , yn_reward_kind : str = 'none' ) -> Noneالمدخلات:
dataset: RL_Dataset - يأخذ RL_Dataset ؛ على وجه التحديد VisDialListDataset ، على النحو الوارد أعلاه. يتم استخدام مجموعة البيانات هذه لتحديد الحالات الأولية.url: str - عنوان URL لخطو البيئة. اتبع الإرشادات الواردة في قسم الإعداد حول كيفية تهيئة خادم الويب المحلي المقابل لهذا عنوان URL.reward_shift: float=0.0 - قم بتحويل المكافأة بهذا المبلغ.reward_scale: float=1.0 - قم بتوسيع المكافأة بهذا المبلغ.actor_stop: bool=False - اسمح للممثل بالتوقف عن التفاعل مبكرًا عن طريق إنشاء رمز خاص <stop> .yn_reward: float=-2.0 -عقوبة المكافأة التي يجب إضافتها لطرح الأسئلة نعم/لا.yn_reward_kind: str='none' - يحدد سلسلة مجريات الأمور لاستخدامها لتحديد ما إذا تم طرح نعم/لا شك. يجب أن يكون واحدًا من ['none', 'soft', 'hard', 'conservative'] .'none' : لا تعاقب نعم/لا أسئلة. هذا يتوافق مع المكافأة standard في ورقتنا.'soft' : معاقبة سؤال إذا كان الرد يحتوي على "yes" أو "no" كسلسلة فرعية.'hard' : معاقبة سؤال إذا كان الرد يتطابق تمامًا مع السلسلة "yes" أو "no" . هذا يتوافق مع مكافأة "y/n" في ورقتنا.'conservative' : معاقبة سؤال ما إذا كان الرد يفي بواحد من العديد من الاستدلال المطابقة للسلسلة. هذا يتوافق مع مكافأة "conservative y/n" في ورقتنا. عائدات: None
step def step ( self , action : str ) -> Tuple [ WordleObservation , float , bool ]المدخلات:
action: Vocabulary - مفردات البيئةالعائدات: (الملاحظة ، المكافأة ، المحطة) tuple.
reset def reset ( self ) -> WordleObservationعائدات: ملاحظة
is_terminal def is_terminal ( self ) -> boolالعائدات: A Boolean تشير إلى ما إذا كان التفاعل قد انتهى.
البرامج النصية التدريبية موجودة في scripts/train/vis_dial/ .
| السيناريو | وصف |
|---|---|
train_bc.py | تدريب وكيل قبل الميلاد. |
train_chai.py | تدريب وكيل تشاي. |
train_cql.py | تدريب وكيل CQL. |
train_dt.py | تدريب وكيل محول القرار. |
train_iql.py | تدريب وكيل ILQL. |
train_psi.py | تدريب آن |
train_utterance.py | تدريب وكيل ILQL على مستوى الكلام. |
نصوص التقييم موجودة في scripts/eval/vis_dial/ .
| السيناريو | وصف |
|---|---|
eval_policy.py | تقييم وكيل في بيئة الحوار البصري. |
top_advantage.py | يجد الأسئلة التي لها أعظم وأصغر ميزة تحت النموذج. |
distill_policy_eval.py | يطبع نتيجة eval_policy.py مع أشرطة الخطأ. |
Here we outline how to load the Reddit comments data in our codebase and how to execute the environment. See the setup section above for how to setup the toxicity filter reward. The data and environment objects are loaded automatically by the config manager, but if you want to by-pass the config system and use the task with your own codebase, here's how you should load, execute, and configure these objects. The same settings described below can all be modified in the configs as well.
An example of how to load the Reddit comment environment:
from toxicity . toxicity_env import ToxicityEnvironment
from toxicity . reddit_comments_base import RedditData
from toxicity . reward_fs import toxicity_reward
from utils . misc import convert_path
idxs = json . load ( open ( convert_path ( 'data/reddit_comments/train_idxs.json' ), 'r' ))
data = RedditData (
path = convert_path ( 'data/reddit_comments/' ),
indexes = idxs ,
reward_f = toxicity_reward
)
env = ToxicityEnvironment (
data = data ,
reward_f = toxicity_reward
)
print ( env . reset ())
The above script corresponds to how we configured the environment for our toxicity reward experiments, but if you want to configure the environment differently, there are a few arguments you can modify. These arguments can also change the task or reward. Below we describe all the different configurable parameters that our reward functions, RedditData , ToxicityListDataset , and ToxicityEnvironment take.
We document the parameters and methods for our different Reddit comment reward functions, RedditData , ToxicityListDataset , and ToxicityEnvironment , so that you know how to configure the environment yourself.
Here we outline the 4 main reward functions we use for our Reddit comment task. Each of these rewards is implemented in src/toxicity/reward_fs.py .
toxicity_reward from toxicity . reward_fs import toxicity_reward
reward_f = toxicity_reward ()وصف:
The "toxicity" reward from our paper, which queries the GPT-3 toxicity filter. It assigns a value of "0" to non-toxic comments, a value of "1" to moderately toxic comments, and a value of "2" to very toxic comments.
toxicity_noised_reward from toxicity . reward_fs import toxicity_noised_reward
reward_f = toxicity_noised_reward ()وصف:
The "noised toxicity" reward from our paper, which is the same as toxicity_noised_reward but induces additional noise. Specifically, it re-assigns comments labeled as "1" (moderately toxic) to either "0" (non-toxic) or "2" (extremely toxic) with equal probability.
score_human_reward from toxicity . reward_fs import score_human_reward
from utils . misc import convert_path
reward_f = score_human_reward (
reddit_path = convert_path ( 'data/reddit_comments/' ),
indexes = None
)وصف:
The "upvotes real" reward from our paper, which gives a reward of +1 for positive upvote comments and -1 for negative upvote comments. This uses the ground truth upvotes in the data, so it only applies to comments in the dataset and cannot be used for evaluation. If you input a string not present in the data, it will error. The arguments to this function specify what data to load.
Inputs:
reddit_path: str – a path to the data.indexes: List[int] – a split of indexes in the data to use. If None , it considers all the data. model_reward from toxicity . reward_fs import score_human_reward
from toxicity . reddit_comments_base import RedditData
from toxicity . toxicity_dataset import ToxicityListDataset
from toxicity . reward_model import RobertaBinaryRewardModel
from utils . rl_data import ConstantTokenReward
from utils . misc import convert_path
data = RedditData (
path = convert_path ( 'data/reddit_comments/' ),
indexes = None ,
reward_f = None
)
listdata = ToxicityListDataset (
data = data ,
max_len = 512 ,
token_reward = ConstantTokenReward ( 0.0 )
)
model = RobertaBinaryRewardModel (
data = listdata ,
device = 'cuda' ,
roberta_kind = 'roberta-base' ,
freeze_roberta = False ,
reward_cuttoff = 0.0
)
model . load_state_dict ( torch . load ( convert_path ( 'outputs/toxicity/upvote_reward/model.pkl' ), map_location = 'cpu' ))
reward_f = score_human_reward ( model = model )وصف:
The "upvotes model" reward from our paper, which gives a reward of +1 if the given model predicts that the comment will get a positive number of upvotes and a reward of -1 otherwise. The model checkpoint we used for our experiments is at: outputs/toxicity/upvote_reward/model.pkl
Inputs:
model: RewardModel : the reward model implemented in src/toxicity/reward_model.py . The model should be first trained and loaded from a pytorch checkpoint.RedditData : RedditData , implemented in src/toxicity/reddit_comments_base.py , stores the raw Reddit comments data.
__init__ def __init__ ( self , path : str , indexes : Optional [ List [ int ]], reward_f : Optional [ Callable [[ str ], float ]], reward_cache : Optional [ Cache ] = None , reward_shift : float = 0.0 , reward_scale : float = 1.0 ) -> NoneInputs:
path: str – the path to the Reddit data.indexes: Optional[List[int]] – a list of indexes to create a split of the data. Randomly selected, training, validation, and test splits are in the json files:data/reddit_comments/train_idxs.jsondata/reddit_comments/eval_idxs.jsondata/reddit_comments/test_idxs.jsonreward_f: Optional[Callable[[str], float]] – the reward function to use.reward_cache: Optional[Cache]=None – a cache of reward values, so you don't have to recompute them everytime.reward_shift: float=0.0 – shift the reward by this amount.reward_scale: float=1.0 – scale the reward by this amount. Returns: None
__len__ def __len__ ( self ) -> intReturns: the size of the dataset.
__getitem__ def __getitem__ ( self , idx : int ) -> SceneInputs:
idx: int – the dataset index.Returns: an item from the dataset.
ToxicityListDataset : ToxicityListDataset , implemented in src/toxicity/toxicity_dataset.py , wraps around RedditData and converts it into a DataPoint format that can be used to train offline RL agents.
__init__ def __init__ ( self , data : RedditData , max_len : Optional [ int ], token_reward : TokenReward , cuttoff : Optional [ float ] = None , resample_timeout : float = 0.0 , include_parent : bool = True ) -> NoneInputs:
data: RedditData – a Reddit comment data object that stores all the raw data.max_len: Optional[int] – the maximum sequence length in the dataset, will truncate all token sequences to this length. If None , then sequences will not be truncated.token_reward: TokenReward – the token-level reward to apply to the sequences. We use a constant reward of 0 per-token for all experiments.cuttoff: Optional[float]=None – filter out all comments from the dataset with reward less than cuttoff . If None , no data will be filtered. Used with %BC models.resample_timeout: float=0.0 – when cuttoff is not equal to None , comments are stochastically sampled iid from the dataset, like an iterable, even though the dataset has a list-type interface. It uniformly re-samples from the dataset until it finds a comment with a reward that satisfies the cuttoff. In the case of the "toxicity" reward, this re-sampling can cause rate-limit errors on the GPT-3 API, so we allow you to add a resample_timeout to fix this issue: a timeout of roughly 0.05 should fix rate-limit issues.include_parent: bool=True – whether to condition on the parent comment in the thread. If False , models will be trained to generate comments unconditionally. Returns: None
size def size ( self ) -> intReturns: the size of the dataset.
get_item def get_item ( self , idx : int ) -> DataPointInputs:
i: int – the dataset index. Returns: a DataPoint from the dataset.
ToxicityEnvironment : ToxicityEnvironment , implemented in src/toxicity/toxicity_env.py , defines the Reddit comment generation environment, which our offline RL agents interact with at evaluation time.
__init__ def __init__ ( self , data : RedditData , reward_f : Optional [ Callable [[ str ], float ]], reward_shift : float = 0.0 , reward_scale : float = 1.0 , include_parent : bool = True ) -> NoneInputs:
data: RedditData – the dataset used to select initial state parent comments to condition on.reward_f: Optional[Callable[[str], float]] – the reward function to use.reward_shift: float=0.0 – shift the reward by this amount.reward_scale: float=1.0 – scale the reward by this amount.include_parent: bool=True – specifies whether to condition on the previous comment or post in the Reddit thread. Returns: None
step def step ( self , action : str ) -> Tuple [ WordleObservation , float , bool ]Inputs:
action: Vocabulary – the environment's vocabularyReturns: an (observation, reward, terminal) tuple.
reset def reset ( self ) -> WordleObservationReturns: an observation
is_terminal def is_terminal ( self ) -> boolReturns: a boolean indicating if the interaction has terminated.
Training scripts are in scripts/train/toxicity/ .
| script | وصف |
|---|---|
train_bc.py | Train a BC agent. |
train_iql.py | Train an ILQL agent. |
train_upvote_reward.py | Train the upvote reward model. |
Evaluation scripts are in scripts/eval/toxicity/ .
| script | وصف |
|---|---|
eval_policy.py | Evaluate an agent in the Reddit comments environment. |
distill_policy_eval.py | Prints out the result of eval_policy.py with error bars. |
All tasks – Wordle, Visual Dialogue, Reddit – have a corresponding environment and dataset implemented in the codebase, as described above. And all offline RL algorithms in the codebase are trained, executed, and evaluated on one of these given environments and datasets.
You can similarly define your own tasks that can easily be run on all these offline RL algorithms. This codebase implements a simple set of RL environment abstractions that make it possible to define your own environments and datasets that can plug-and-play with any of the offline RL algorithms.
All of the core abstractions are defined in src/data/ . Here we outline what needs to be implemented in order to create your own tasks. For examples, see the implementations in src/wordle/ , src/vis_dial/ , and src/toxicity/ .
All tasks must implement subclasses of: Language_Observation and Language_Environment , which are in src/data/language_environment.py .
Language_Observation :This class represents the observations from the environment that will be input to your language model.
A Language_Observation must define the following two functions.
to_sequence def to_sequence ( self ) -> Tuple [ List [ str , Optional [ float ]], bool ]:وصف:
A function which converts the observation object into a standard format that can be input to the language model and used for training.
عائدات:
__str__ def __str__ ( self ) -> str :وصف:
This is only used to print the observation to the terminal. It should convert the observation into some kind of string that is interpretable by a user.
Returns: a string.
Language_Environment :This class represents a gym-style environment for online interaction, which is only used for evaluation.
A Language_Environment must define the following three functions.
step def step ( self , action : str ) -> Tuple [ Language_Observation , float , bool ]:وصف:
Just like a standard gym environment, given an action in the form of a string, step the environment forward.
Returns: a tuple of (Language_Observation, reward, terminal).
reset def reset ( self ) -> Language_Observation :وصف:
This resets the environment to an initial state.
Returns: the corresponding initial Language_Observation
is_terminal def is_terminal ( self ) -> bool :وصف:
Outputs whether the environment has reached a terminal state.
Returns: a boolean indicating if the environment has reached a terminal state.
All tasks must implement subclasses of either List_RL_Dataset or Iterable_RL_Dataset or both, which are defined in src/data/rl_data.py .
List_RL_Dataset :This class represents a list dataset (or an indexable dataset of finite length) that can be used to train offline RL agents.
A List_RL_Dataset must define the following two functions.
get_item def get_item ( self , idx : int ) -> DataPointوصف:
This gets an item from the dataset at a given index.
Returns: a DataPoint object from the dataset.
size def size ( self ) -> intوصف:
Returns the size of the dataset.
Returns: the dataset's size.
Iterable_RL_Dataset :This class represents an iterable dataset (or a non-indexable dataset that stochastically samples datapoints iid) that can be used to train offline RL agents.
A Iterable_RL_Dataset must define the following function.
sample_item def sample_item ( self ) -> DataPointوصف:
Samples a datapoint from the dataset.
Returns: a DataPoint object from the dataset.