gpt generated notes of learning the hsd3 repository
this is my gpt generated notes of learning the hsd3 repository.
Prelude: learn by homework (not GPT genrated)
I create a hsd3_learn dir, that contains the commented version of the original code. I make a try to let gpt4 turn the code into a programming homework (the one in Stanford CSw224 GNN) usng the promtps like
act as a Stanford CS TA for RL course who is humourous and good at 引导和启发 students. Please design a programming home work in a .py file : provide information and background like the purpose of function, variable meaning, library function usage and syntax etc. in the format comment, ask student to complete the function according to the prompt. Now i will give you functions or class from real codebase one by one, turn them into the homework.py. don’t skip, ensuring every line is the same with the original codes.
you need to make students understand the whole database by home work. in what order should you transform the code into homework, for better understanding Considering the complexity of the codebase and the interconnectedness of the various components, a good strategy would be to start with the fundamental building blocks and gradually move towards the more complex functionalities. Here’s a recommended order to transform the code into homework assignments
add comment, provide information and background like the purpose of function, variable meaning, library function usage and syntax etc. in the format comment, don’t skip, ensuring every line is the same with the original code
after finishing this helpful and interesting tutorial, one should be able to run the hsd3 and have a good understanding of the codebase.
to my surprise now GPT4 is capable of reading 300+line of code
Outline
prompts: you need to make students understand the whole database by home work. in what order should you transform the code into homework, for better understanding Considering the complexity of the codebase and the interconnectedness of the various components, a good strategy would be to start with the fundamental building blocks and gradually move towards the more complex functionalities. Here’s a recommended order to transform the code into homework assignments:
-
Exploring the codebase: Before diving into specific files, you could assign a task for students to explore the codebase. Ask them to document the purpose of each directory and file. This will give them a broad understanding of the codebase structure.
-
Requirements and Setup: Students should understand the software dependencies of the project. Assign them to study the
requirements.txtfile, install the necessary packages, and set up the project for development. -
Configuration Files: Start with the
configdirectory. Understanding these files will provide students with insights into how different parts of the system are set up, such as the agent and environment configurations. -
Utilities: The
hucc/utils.pyfile seems to contain utility functions that are likely used throughout the project. Understanding these will provide a good foundation. -
Models: Move on to the
hucc/modelsdirectory. Understanding the underlying models (e.g., bandits, blocks, traced) is key to comprehending the training process. -
Agents: Next, tackle the
hucc/agentsdirectory. Each file appears to define a different type of agent, and understanding how these agents are defined and operate is crucial. -
Environments: Understanding the environment in which the agents operate is also crucial. Students should therefore study the
hucc/envsdirectory next. -
Replay Buffer and Hash Count: The
hucc/replaybuffer.pyandhucc/hashcount.pyfiles seem to implement important aspects of the agent’s memory and state tracking. These should be covered next. -
Rendering and Spaces: The
hucc/render.pyandhucc/spaces.pyfiles probably deal with the visualization and the state/action spaces of the environments. Understanding these will help students visualize the agent’s actions and the environment. -
Training and Pretraining: Finally, students should study the
train.pyandpretrain.pyscripts, as well as the corresponding scripts in thelearn_hsd3directory. These scripts will tie together everything the students have learned so far and show them how all these components interact during the training process.
Remember, each of these steps could itself be broken down into several smaller tasks to make the process more manageable. Also, encourage students to constantly test their understanding by running the code and experimenting with it. This hands-on experience will greatly facilitate their learning process.
Exploring the codebase
prompts: **Exploring the codebase according the given tree . outpuut **: Before diving into specific files, explore the codebase document the purpose of each directory and file. give me a broad understanding of the codebase structure. (explain uncommon names like hucc) Sure, based on the structure you provided, here’s an overview of the directories and files:
-
CODE_OF_CONDUCT.md,CONTRIBUTING.md,LICENSE, andREADME.mdare standard files found in many repositories that provide guidance on how to interact with the project. -
config: This directory contains configuration files (in YAML format), which specify parameters for different parts of the system. Theagentsubdirectory contains configurations for different types of agents.common.yamlmight contain settings common to all configurations. -
hydra: Hydra is a framework for elegantly configuring complex applications. This directory might contain the setup for hydra and configurations related to it. Thelaunchersubdirectory probably contains configurations for launching jobs, for example, on a SLURM cluster. -
format,nohup.out: These files could contain output logs or formatting instructions, though without more context it’s hard to say. -
hucc: This directory seems to be the core of the project, containing several modules and files related to different aspects of the codebase. Based on the information and the code snippets you’ve provided, “HUCC” could potentially stand for “Hierarchical Unsupervised Control/Controller” or “Hierarchical Unsupervised Continuous Control” given the context of the research paper “Hierarchical Skills for Efficient Exploration”. The paper proposes a hierarchical skill learning framework for reinforcement learning in continuous control tasks, which could explain the usage of “HUCC”.agents: This module probably contains implementations of different types of learning agents.envs: This module likely contains different environments in which the agents can operate.hashcount.py: This might implement a data structure for counting occurrences of different items.models: This module may contain different models used by the agents.render.py: This file might be responsible for rendering or visualizing the agent’s behavior.replaybuffer.py: This file likely implements a replay buffer, which is a common component in reinforcement learning for storing past experiences.spaces.py: This file might define different types of spaces (like action or observation spaces).utils.py: This file likely contains utility functions used across the codebase.
-
learn_hsd3: This directory might contain scripts and instructions for learning a specific model or task (hsd3). -
pretrain.py,train.py: These scripts are likely the entry points for pre-training and training the agents. -
requirements.txt: This file usually lists the Python dependencies required by the project. -
scripts: This directory might contain auxiliary scripts for tasks like data preprocessing or analysis.
Please note that these are educated guesses based on the names and typical structure of machine learning projects. For precise information, you should refer to the project’s documentation or the comments and docstrings in the code.
Utilities:
The hucc/utils.py file seems to contain utility functions that are likely used throughout the project. Understanding these will provide a good foundation.
-
Optimizers in PyTorch: PyTorch provides several optimization algorithms that you can use to train your models. These are implemented in the
torch.optimmodule. To create an optimizer, you need to pass the parameters of the model that the optimizer should update, and the learning rate. -
Signal handling in Python: Python’s
signalmodule provides mechanisms to handle various types of system signals, including the SIGUSR1 signal. You can use thesignalfunction from this module to register a handler function that will be called when a specific signal is received. -
Tensor indexing in PyTorch: PyTorch provides several ways to index tensors. The simplest way is to use square brackets and indices. However, if you want to perform more complex indexing, you can use the
index_selectorgathermethods. You will need to use one of these methods in thedim_selectfunction. -
Sorting strings naturally: Python’s built-in
sortedfunction sorts strings lexicographically, which might not be what you want if your strings contain numbers. Thesorted_nicelyandsorted_nicely_sepfunctions should sort strings in a way that humans would expect, e.g., “2” should come before “10”. -
Recursive functions: A recursive function is a function that calls itself during its execution. This allows the function to be written in a more readable and elegant manner, at the expense of potentially higher memory usage. You will need to write a recursive function to handle the potentially nested optimizers in the
make_optimfunction.
Models:
Move on to the hucc/models directory. Understanding the underlying models (e.g., bandits, blocks, traced) is key to comprehending the training process.
The bandits, blocks, and traced files are all part of the codebase for a reinforcement learning system. They are grouped under the “models” directory because they collectively provide the components necessary for defining various aspects of the models used in reinforcement learning.
Here’s an overview of what each of these components does:
-
Bandits 老虎机: In the context of reinforcement learning, a bandit is a type of problem where an agent must choose between a set of actions, each with an uncertain reward. The goal of the agent is to find the action with the highest expected reward. The term comes from the idea of a gambler at a row of slot machines (sometimes known as “one-armed bandits”) who has to decide which machines to play, how many times to play each machine, and in which order to play them, to maximize their return. The
bandits.pyfile likely contains code for various bandit algorithms. -
Blocks 预定义的GNN模块: Blocks usually refer to pre-defined building blocks that can be used to construct neural networks. In this context, each “block” is a specific arrangement of layers in a neural network. Blocks can be combined and stacked to create complex network architectures. The
blocks.pyfile probably contains code defining these building blocks. -
Traced 模型跟踪: The
traced.pyfile likely contains code related to the tracing functionality provided by PyTorch’s JIT (Just-In-Time) compiler. Tracing allows you to convert your PyTorch model into a form that can be more efficiently executed in C++, while also allowing the model to be saved and loaded in different environments. TheTracedModuleclass, which you provided in the code snippet, is an example of this. It wraps a given PyTorch module and provides tracing functionality to it.
Why are they under the models directory?
In machine learning projects, it’s common to organize code into directories based on their role in the system. The models directory typically contains all code related to model definition, training, and inference. Since bandit algorithms, network building blocks, and model tracing are all directly related to models, it makes sense to place them in the models directory. This organization helps other developers and researchers understand and navigate the codebase.
bandit
prompts: again, turn it into homework
Homework: Multi-Armed Bandit Algorithms in Reinforcement Learning
The goal of this assignment is to understand the concept of multi-armed bandit problems and various strategies for solving them using reinforcement learning techniques.
The provided code defines a Bandit class and several subclasses, each of which implements a different strategy for solving the multi-armed bandit problem:
UniformBanditEpsGreedyBanditUCBBanditDiscountedUCBBanditSlidingWindowUCBBanditAgent57BanditThompsonBandit
Your task is to complete the following:
Task 1: Understanding Bandit Strategies
For each of the seven bandit strategies, provide a brief description of how the strategy works, and under what circumstances it might be a good choice. Use resources like textbooks, lecture notes, or online resources to aid your understanding.
Task 2: Implement New Bandit Strategy
Create a new class, YourBandit, that inherits from the Bandit class and implements a different strategy for the multi-armed bandit problem. Explain why you chose this strategy and in which circumstances it could be superior to the existing ones.
python
class YourBandit(Bandit):
def __init__(self, action_space: gym.Space):
super().__init__(action_space)
# TODO: Add any initialization code here
def update(self, action, r):
# TODO: Update estimates of action values
pass
def sample_action(self):
# TODO: Decide on an action to take
pass
def best_action(self):
# TODO: Return the current best action
pass
def dist(self):
# TODO: Return the current distribution over actions
pass
Task 3: Test Your Bandit Strategy
Test your bandit strategy on a multi-armed bandit problem of your choice. Compare its performance to the performance of the other bandit strategies. You can use the gym environment for creating the multi-armed bandit problem.
python
# TODO: Code for testing bandit strategies
Task 4: Discussion
Discuss the results of your experiments. Did your bandit strategy perform as expected? Why or why not? How did the different bandit strategies compare?
Submit your completed assignment as a Python script or Jupyter notebook.
Hints:
- You may find the PyTorch documentation helpful, particularly the sections on distributions (
torch.distributions) and operations (torch.nn.functional). - The
gymlibrary is used for the action spaces. Be sure to understand how it works before proceeding with the assignment. - For
Task 3, remember to average results over multiple runs to get reliable comparisons. The bandit problem has inherent randomness, so a single run may not be representative.
blocks
The provided code is a skeleton of some classes and functions that are commonly used in the domain of Reinforcement Learning (RL), particularly in policy gradient methods and model-based RL. These classes are typically used for different types of network architectures and the implementation of different types of policy and value functions.
Please note that without the full implementation details, I can only provide a high-level summary of the potential purpose of each class and function.
-
TransformedDistribution: This class could be a subclass ofD.TransformedDistribution, a PyTorch class that creates a distribution by applying a sequence of transformations to a base distribution. -
TransformDistribution: Likely a custom class to define a distribution transformed according to some specific rule. It’s a subclass ofnn.Module, suggesting that it might be a part of a neural network model. -
GaussianFromEmbedding: This class might be used to generate a Gaussian distribution from an embedding vector, often used in policy networks where the output is a continuous action. -
GaussianFromMulogstd: This class is probably used to generate a Gaussian distribution from a mean and log standard deviation. -
CategoricalFromEmbedding: This class might be used to create a categorical distribution from an embedding vector, often used in policy networks where the output is a discrete action. -
MHGaussianFromEmbedding: This class could be used for generating a multivariate Gaussian distribution from an embedding. The “MH” prefix might refer to “Metropolis-Hastings”, a famous algorithm in sampling. -
EmbedDiscreteSkill: This could be a class to create an embedding for a discrete skill, often used in hierarchical RL where an agent learns to perform a variety of “skills”. -
SplitTaskInput: A class that might be used to split task input into several parts. -
EinsumBilinear: This class might be an extension ofnn.Bilinearlayer that utilizes Einstein summation convention for a specific operation. -
SkipNetwork,SkipDoubleNetwork,BilinearSkipNetwork: These classes likely represent different types of neural network architectures with skip connections, which provide shortcuts between layers to help gradient flow during backpropagation and mitigate the vanishing gradient problem. -
GroupedLinear: This class might represent a linear layer where inputs are grouped and each group is processed separately. -
Expandtasksubgoal: Likely a class to process task and subgoal information in an RL context, possibly for a hierarchical RL setup. -
FlattenSpace: This class might take a complex state or action space and flatten it into a simpler space, which can be useful for preprocessing complex environments. -
Parallel: This class might be used to apply the same operation to multiple inputs in parallel. -
SqueezeLastDim: This class might remove the last dimension of the input, a common operation in tensor manipulation. -
shorthand: This function is likely a helper function to create a shorthand notation for something. Without more context, it’s hard to say exactly what it does. -
FactoryTypeandFactory: These are related to the Factory design pattern, which is used to create objects without specifying the exact class of object that will be created. This can make code more flexible, modular, and scalable. -
make_model: This function probably creates an instance of a model. Without more context, it’s hard to say exactly what kind of model it creates.
Remember that these are general descriptions based on typical use cases in reinforcement learning and the names of classes and functions. The actual implementation in your code may differ. It’s always best to refer to the specific documentation or comments provided with the code.
traced
The TracedModule class in the provided code is a subclass of PyTorch’s nn.Module. It’s used to convert a PyTorch model into TorchScript via tracing, which is a way to create a serializable and optimizable version of your model.
The main advantage of TorchScript is that it allows you to serialize your models, so you can save them to disk and load them in another environment (e.g., in a server doing inference). It also allows you to optimize your models and run them in a high-performance, strongly typed language.
Here is what each part of the TracedModule class does:
-
__init__: This is the constructor method that gets called when you create an instance ofTracedModule. It takes as input annn.Moduleobjectm, initializes the parentnn.Modulewithsuper().__init__()and assigns the input module to the instance variableself.m. It also setsself._tracedtoNone. This variable will later hold the traced version of the model. -
forward: This method is called when you pass input data through the module. Ifself._tracedisNone(meaning the model has not yet been traced), it uses thetracefunction fromtorch.jitto trace the modelself.mwith the input datainpand assigns the traced model toself._traced. Then it applies the traced model to the input data and returns the result.
The forward method ensures that the model is only traced the first time forward is called, and the traced model is reused for subsequent calls. This allows you to use TracedModule just like any other PyTorch module, but under the hood it automatically converts the model to TorchScript the first time it’s run.
Keep in mind that tracing has limitations: it can’t handle models with control flow (like if statements or loops) that depend on input data or model parameters, because it only captures the operations performed with the example input data it’s given. If your model has such control flow, you should use scripting instead of tracing.
Also note that the forward method traces the model every time it’s run if self._traced is None. In a multi-threaded environment, this could potentially result in the model being traced multiple times simultaneously. You might want to add thread-safety measures if you’re using this in a multi-threaded context.
Agents:
Next, tackle the hucc/agents directory. Each file appears to define a different type of agent, and understanding how these agents are defined and operate is crucial.
hsd3
prompts( it changes the code): add comment, provide information and background like the purpose of function, variable meaning, library function usage and syntax etc. in the format comment, don’t skip, ensuring every line is the same with the original codes.
This completes the _update_hi method which is responsible for updating the high-level policy. The method performs updates on the Q-function, the policy, and the temperature parameter. These updates are done based on the policy gradient approach. The logs of the losses are then returned. The target network is also updated after each iteration to maintain stability in learning
HiToLoInterface
In this code, HiToLo refers to a High-Level to Low-Level interface. It represents an interface between high-level and low-level sub-agents, likely within a Hierarchical Reinforcement Learning (HRL) context.
HRL is a type of reinforcement learning architecture that allows for learning and decision-making at various levels of abstraction. It typically involves high-level policies (or sub-agents) making more abstract, strategic decisions, and low-level policies carrying out the specific actions to achieve those strategic goals.
In this case, the HiToLoInterface class seems to be handling the translation between the high-level and low-level sub-agents, including parsing information from the high-level agent and translating it into a form that the low-level agent can use, and vice versa.
Here is the explanation of the Python code snippet you’ve provided:
This script defines a class HiToLoInterface which is a part of a Hierarchical Reinforcement Learning (HRL) system. The class represents the interface between a high-level and a low-level policy.
The main role of this class is to manage the transition between high-level policies (which decide on abstract goals) and low-level policies (which execute specific actions to achieve these goals).
Key methods and elements of the HiToLoInterface class:
-
__init__(self, env, cfg: DictConfig): The constructor of the class that takes in the environment and a configuration dictionary as arguments. It prepares all the necessary variables, configurations, and spaces based on the input configuration. It also sets up goal spaces and task maps. -
parse_lo_info(cfg): This static method loads low-level information from a provided configuration. It returns subsets and task maps. -
action_mask_hi(self): This method generates a mask for high-level actions based on subsets of features in the goal space. -
gs_obs(self, obs): This method returns the goal space observations from the overall observations. -
translate(self, gs_obs, task, subgoal, delta_gs_obs=None): This method translates the goal space observations, task and subgoal into the low-level policy’s action space. -
update_bp_subgoal(self, gs_obs, next_gs_obs, action_hi): This method updates the backprojected subgoal based on the current and next goal space observations, and the high-level action. -
observation_lo(self, o_obs, action_hi): This method constructs a low-level observation from the overall observation and the high-level action. -
dist_lo(self, gs_obs, task, subgoal): This method calculates the distance between the projected current state and the subgoal in the low-level policy’s action space. -
reward_lo(self, gs_obs, next_gs_obs, task, subgoal): This method calculates a potential-based reward for the low-level policy. -
log_goal_spaces(self): This method logs the information about the goal spaces.
This class heavily relies on PyTorch and the gym library for handling tensors and constructing spaces, respectively. It also uses some custom classes like CtrlgsPreTrainingEnv for certain operations.
Environments:
Understanding the environment in which the agents operate is also crucial. Students should therefore study the hucc/envs directory next.
add comment in a code review paradigm: provide information and background like the purpose of function, variable meaning, library function usage and syntax etc. in the format comment, make sure every line is the same with the original codes. when i say continue, directly generate the continuous upcomming content.
-
Replay Buffer and Hash Count: The
hucc/replaybuffer.pyandhucc/hashcount.pyfiles seem to implement important aspects of the agent’s memory and state tracking. These should be covered next. -
Rendering and Spaces: The
hucc/render.pyandhucc/spaces.pyfiles probably deal with the visualization and the state/action spaces of the environments. Understanding these will help students visualize the agent’s actions and the environment.
configure
Hydra is a powerful open-source library for developing applications that have complex configurations. It simplifies the handling of configurations for Python applications, allowing you to manage and organize your configurations efficiently. Hydra uses a structured configuration approach which enables easier configuration management and validation.
common.yml
Here is a brief introduction of some Hydra syntax and functionalities shown in the configuration file:
-
hydra.run.dir: This parameter defines the directory in which the application will be run. The.signifies that the application will run in the current directory. -
hydra.sweep.dir: This is used when running sweep jobs (multiple runs of the application with different configurations). The${now:%Y}-style syntax is used to interpolate the current date and time into the directory path. The${oc.env:USER}syntax retrieves the current user’s name from the environment variables. -
slurm: This section is specific to running the application on a Slurm workload manager, typically found on high-performance computing clusters. Parameters likepartition,cpus_per_task,gpus_per_task, etc., define the resources requested for the Slurm job. -
seed,device,log_level: These parameters specify the random seed, the device to use for computation (CPU or GPU), and the logging level for the application, respectively. -
visdom: Visdom is a visualization tool for PyTorch. Parameters under this key configure the Visdom server. -
checkpoint_path,keep_all_checkpoints: These parameters define where to save the model checkpoints and whether to keep all checkpoints or just the most recent one. -
env: This section configures the training and evaluation environments. -
eval: This section contains parameters related to the evaluation of the model, such as the interval between evaluations and the metrics to compute. -
video: This section contains parameters for recording videos of the training and evaluation sessions.
Hydra uses the YAML syntax for its configuration files. YAML is a human-readable data serialization standard that’s ideal for configuration files and data exchange between languages with different data structures. In the provided YAML file, keys and values are separated by a : and nested parameters are represented by indentation.
The ${...} syntax in Hydra is used for interpolation, where the value of one config parameter is used in another. For example, in ${env.args}, the value of env.args will be inserted in place of the entire ${env.args} string.
Finally, null in YAML signifies the absence of a value or that the value is not applicable in this context.
For a more comprehensive understanding, the official Hydra documentation is a great resource: https://hydra.cc/docs/intro/.
humanoid.yml
hsd3
Here’s a brief explanation of the parameters in the YAML configuration file:
-
defaults: This field includes references to other configuration files, essentially saying “include the settings defined in these files as a starting point”. The- commonand- agent: hsd3lines mean that the configuration defined in thecommon.yamlandhsd3.yamlfiles (under theagentdirectory) are loaded as defaults. If the same parameter is defined in this configuration file and in one of the default configuration files, the value in this configuration file will be used. -
max_steps: This is the maximum number of training steps. -
robot: Specifies the type of robot to be used in the environment. -
goal_space: Specifies the goal space (or the representation of the goals) for the task. -
subsets: This could be a parameter to specify which subsets of the data to use. -
action_interval: The number of environment steps between two actions. -
eps: This is typically a parameter related to the exploration strategy (epsilon-greedy, for instance), where a random action is selected with probabilityeps. -
auto_adapt: Flag for automatic adaptation of the configuration based on the environment. -
eval: This section configures the evaluation of the model, such as the interval between evaluations and the metrics to compute. -
video: This parameter controls the video recording of the training and evaluation sessions.nullmeans no video recording. -
visdom.offline: This parameter decides whether to use the offline mode of visdom for visualization. -
env: This section configures the training and evaluation environments. -
agent: This section contains parameters specific to the agent, such as the batch size, replay buffer size, number of updates, goal space, etc. -
model: This section defines the models to be used for the different components of the agent. -
optim: This section specifies the optimizers to be used for training the different components of the agent, along with their learning rates.
In the provided YAML file, keys and values are separated by a : and nested parameters are represented by indentation. The ${...} syntax in Hydra is used for interpolation, where the value of one config parameter is used in another. For example, in ${robot}, the value of robot will be inserted in place of the entire ${robot} string.
pretrain
Sure, here’s a brief explanation of the additional parameters in this YAML configuration file:
-
horizon: This could refer to the planning horizon, which is the number of steps into the future the agent should consider when making decisions. -
idle_steps: This might be the number of initial steps for which the agent takes no action. -
features: This specifies the type of features to be used for the task. -
feature_dims,feature_rank,feature_rank_max: These parameters could be related to feature selection or dimensionality reduction. -
ctrl_eps: This could be a parameter for controlling the agent’s exploration strategy. -
precision: This could be related to the precision of the goal representation or the precision with which the agent should achieve its goals. -
max_new_tasks,task_weighting,downrank,lp_new_task,lp_eps: These parameters appear to be related to the task generation and selection process. -
eval_mode: This could be a mode for the evaluation process. In this case,reachabilitycould mean that the agent is evaluated based on its ability to reach different goals. -
combine_after_steps: This might be the number of steps after which certain operations (like merging of tasks or updates) should be performed. -
backprop_fallover: This flag could control whether to use a specific technique (like fallover) during backpropagation. -
estimate_joint_spaces: This could be a flag for estimating the joint spaces of the robot.nullmeans this option is not used. -
init_model_from,checkpoint_path: These parameters could be used to initialize the agent’s model from a checkpoint. -
distributed: This section configures the distributed training setup, like the number of actors and learners and the path for storing rendezvous files. -
agent.flatten_obs: This parameter could decide whether to flatten the observation before feeding it into the agent’s model. -
agent.per_task_alpha: This could be a flag for using a differentalphaparameter (which usually controls the trade-off between exploration and exploitation) for each task. -
model.reachability: This could specify the model to be used for estimating the reachability of different goals.
The ${...} syntax in Hydra is used for interpolation, where the value of one config parameter is used in another. For example, in ${robot}, the value of robot will be inserted in place of the entire ${robot} string.
Remember, these explanations are based on general machine learning concepts and some educated guesses. The actual meaning of the parameters could be different and could be understood by reading the documentation or the code of the specific project.
Train & pretrain
use GPT to add comment is the most common use.
here we explore usage of using GPT-4 to learn codes
copy in blank pretrain.py
generate comment and the hide code, ask user to copy and paste according to the prompt.