From 967e4ace4cf68be2f0beb97351f747aba427f6b2 Mon Sep 17 00:00:00 2001 From: Caselles Date: Thu, 14 Mar 2019 11:56:46 +0100 Subject: [PATCH 001/141] Added targets files --- .../omnirobot_utils/blue_square_480_480.png | Bin 0 -> 1770 bytes .../omnirobot_utils/green_triangle_480_480.png | Bin 0 -> 4963 bytes real_robots/omnirobot_utils/red_dot_480_480.png | Bin 0 -> 12784 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 real_robots/omnirobot_utils/blue_square_480_480.png create mode 100644 real_robots/omnirobot_utils/green_triangle_480_480.png create mode 100644 real_robots/omnirobot_utils/red_dot_480_480.png diff --git a/real_robots/omnirobot_utils/blue_square_480_480.png b/real_robots/omnirobot_utils/blue_square_480_480.png new file mode 100644 index 0000000000000000000000000000000000000000..fff1e5622e8576759b24d91b299ff8bb2a899167 GIT binary patch literal 1770 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 literal 0 HcmV?d00001 diff --git a/real_robots/omnirobot_utils/red_dot_480_480.png b/real_robots/omnirobot_utils/red_dot_480_480.png new file mode 100644 index 0000000000000000000000000000000000000000..0243e13e9db21f046ac9ee536d858be1e596c20c GIT binary patch literal 12784 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 Date: Thu, 14 Mar 2019 18:01:35 +0100 Subject: [PATCH 002/141] new tasks for continual learning: random target, circular and square shaped movement --- environments/dataset_generator.py | 18 ++++++- environments/omnirobot_gym/omnirobot_env.py | 15 ++++-- real_robots/omnirobot_simulator_server.py | 40 ++++++++++++--- real_robots/omnirobot_utils/blue_square.png | Bin 0 -> 148 bytes real_robots/omnirobot_utils/green_square.png | Bin 0 -> 148 bytes .../omnirobot_utils/omnirobot_manager_base.py | 47 ++++++++++++++---- real_robots/omnirobot_utils/red_square.png | Bin 0 -> 148 bytes 7 files changed, 95 insertions(+), 25 deletions(-) create mode 100644 real_robots/omnirobot_utils/blue_square.png create mode 100644 real_robots/omnirobot_utils/green_square.png create mode 100644 real_robots/omnirobot_utils/red_square.png diff --git a/environments/dataset_generator.py b/environments/dataset_generator.py index 67ff3b4a3..8316e40a9 100644 --- a/environments/dataset_generator.py +++ b/environments/dataset_generator.py @@ -51,7 +51,10 @@ def env_thread(args, thread_num, partition=True, use_ppo2=False): "record_data": not args.no_record_data, "multi_view": args.multi_view, "save_path": args.save_path, - "shape_reward": args.shape_reward + "shape_reward": args.shape_reward, + "simple_continual_target": args.simple_continual, + "circular_continual_move": args.circular_continual, + "square_continual_move": args.square_continual } if partition: @@ -145,6 +148,16 @@ def main(): help='number of timesteps to run PPO2 on before generating the dataset') parser.add_argument('--toward-target-timesteps-proportion', type=float, default=0.0, help="propotion of timesteps that use simply towards target policy, should be 0.0 to 1.0") + parser.add_argument('--simple-continual', action='store_true', default=False, + help = 'Simple red dot target for task 1 of continual learning scenario. ' + + 'The task is: robot should reach the target.') + parser.add_argument('--circular-continual', action='store_true', default=False, + help='Blue square target for task 2 of continual learning scenario. ' + + 'The task is: robot should turn in circle around the target.') + parser.add_argument('--square-continual', action='store_true', default=False, + help = 'Green triangle target for task 3 of continual learning scenario. ' + + 'The task is: robot should turn in square around the target.') + args = parser.parse_args() assert (args.num_cpu > 0), "Error: number of cpu must be positive and non zero" @@ -158,6 +171,9 @@ def main(): args.num_cpu = args.num_episode printYellow("num_cpu cannot be greater than num_episode, defaulting to {} cpus.".format(args.num_cpu)) + assert sum([args.simple_continual, args.circular_continual, args.square_continual]) <= 1, \ + "For continual SRL and RL, please provide only one scenario at the time !" + # this is done so seed 0 and 1 are different and not simply offset of the same datasets. args.seed = np.random.RandomState(args.seed).randint(int(1e10)) diff --git a/environments/omnirobot_gym/omnirobot_env.py b/environments/omnirobot_gym/omnirobot_env.py index 9e8e6c35f..d781e5939 100644 --- a/environments/omnirobot_gym/omnirobot_env.py +++ b/environments/omnirobot_gym/omnirobot_env.py @@ -72,7 +72,8 @@ class OmniRobotEnv(SRLGymEnv): def __init__(self, renders=False, name="Omnirobot", is_discrete=True, save_path='srl_zoo/data/', state_dim=-1, learn_states=False, srl_model="raw_pixels", record_data=False, action_repeat=1, random_target=True, - shape_reward=False, env_rank=0, srl_pipe=None, **_): + shape_reward=False, simple_continual_target=False, circular_continual_move=False, + square_continual_move=False, env_rank=0, srl_pipe=None, **_): super(OmniRobotEnv, self).__init__(srl_model=srl_model, relative_pos=RELATIVE_POS, @@ -128,8 +129,11 @@ def __init__(self, renders=False, name="Omnirobot", is_discrete=True, save_path= learn_states=learn_states, path=save_path) if USING_OMNIROBOT_SIMULATOR: - self.socket = OmniRobotSimulatorSocket( - output_size=[RENDER_WIDTH, RENDER_HEIGHT], random_target=self._random_target) + self.socket = OmniRobotSimulatorSocket(simple_continual_target=simple_continual_target, + circular_continual_move=circular_continual_move, + square_continual_move=square_continual_move, + output_size=[RENDER_WIDTH, RENDER_HEIGHT], + random_target=self._random_target) else: # Initialize Baxter effector by connecting to the Gym bridge ROS node: self.context = zmq.Context() @@ -194,7 +198,8 @@ def step(self, action): # Send the action to the server self.socket.send_json( - {"command": "action", "action": self.action, "is_discrete": self._is_discrete}) + {"command": "action", "action": self.action, "is_discrete": self._is_discrete, + "step_counter": self._env_step_counter}) # Receive state data (position, etc), important to update state related values self.getEnvState() @@ -274,7 +279,7 @@ def reset(self): self._env_step_counter = 0 # set n contact count self.n_contacts = 0 - self.socket.send_json({"command": "reset"}) + self.socket.send_json({"command": "reset", "step_counter": self._env_step_counter}) # Update state related variables, important step to get both data and # metadata that allow reading the observation image self.getEnvState() diff --git a/real_robots/omnirobot_simulator_server.py b/real_robots/omnirobot_simulator_server.py index caa184e22..5af8f3401 100755 --- a/real_robots/omnirobot_simulator_server.py +++ b/real_robots/omnirobot_simulator_server.py @@ -27,7 +27,7 @@ def __init__(self, init_x, init_y, init_yaw, origin_size, cropped_size, back_ground_path, camera_info_path, robot_marker_path, robot_marker_margin, target_marker_path, target_marker_margin, robot_marker_code, target_marker_code, - robot_marker_length, target_marker_length, output_size, **_): + robot_marker_length, target_marker_length, output_size, history_size=10, **_): """ Class for rendering Omnirobot environment :param init_x: (float) initial x position of robot @@ -63,6 +63,9 @@ def __init__(self, init_x, init_y, init_yaw, origin_size, cropped_size, self.robot_pos = np.float32([0, 0]) self.robot_yaw = 0 # in rad + self.history_size = history_size + self.robot_pos_past_k_steps = [] + # Last velocity command, used for simulating the controlling of velocity directly self.last_linear_velocity_cmd = np.float32( [0, 0]) # in m/s, in robot local frame @@ -185,6 +188,14 @@ def renderRobot(self): self.pos_transformer.phyPosGround2PixelPos( self.robot_pos.reshape(2, 1)), self.robot_yaw, self.robot_marker_size_proprotion) + def getHistorySize(self): + return self.history_size + + def appendToHistory(self, pos): + self.robot_pos_past_k_steps.append(pos) + + def popOfHistory(self): + self.robot_pos_past_k_steps.pop(0) def getCroppedImage(self): return self.image[self.cropped_range[0]:self.cropped_range[1], self.cropped_range[2]:self.cropped_range[3], :] @@ -361,15 +372,11 @@ def __init__(self, **args): :param **args arguments ''' - super(OmniRobotSimulatorSocket, self).__init__( - second_cam_topic=SECOND_CAM_TOPIC) - defalt_args = { + default_args = { "back_ground_path": "real_robots/omnirobot_utils/back_ground.jpg", "camera_info_path": CAMERA_INFO_PATH, "robot_marker_path": "real_robots/omnirobot_utils/robot_margin3_pixel_only_tag.png", "robot_marker_margin": [3, 3, 3, 3], - # for black target, use target_margin4_pixel.png", - "target_marker_path": "real_robots/omnirobot_utils/red_target_margin4_pixel_480x480.png", "target_marker_margin": [4, 4, 4, 4], "robot_marker_code": None, "target_marker_code": None, @@ -380,10 +387,27 @@ def __init__(self, **args): "init_y": 0, "init_yaw": 0, "origin_size": ORIGIN_SIZE, - "cropped_size": CROPPED_SIZE + "cropped_size": CROPPED_SIZE, + "circular_move": False } # overwrite the args if it exists - self.new_args = {**defalt_args, **args} + self.new_args = {**default_args, **args} + + if self.new_args["simple_continual_target"]: + self.new_args["target_marker_path"] = "real_robots/omnirobot_utils/red_square.png" + + elif self.new_args["circular_continual_move"]: + self.new_args["target_marker_path"] = "real_robots/omnirobot_utils/blue_square.png" + + elif self.new_args["square_continual_move"]: + self.new_args["target_marker_path"] = "real_robots/omnirobot_utils/green_square.png" + else: + # for black target, use target_margin4_pixel.png", + self.new_args["target_marker_path"] = "real_robots/omnirobot_utils/red_target_margin4_pixel_480x480.png" + + super(OmniRobotSimulatorSocket, self).__init__(simple_continual_target=self.new_args["simple_continual_target"], + circular_continual_move=self.new_args["circular_continual_move"], + square_continual_move=self.new_args["square_continual_move"]) assert len(self.new_args['robot_marker_margin']) == 4 assert len(self.new_args['target_marker_margin']) == 4 diff --git a/real_robots/omnirobot_utils/blue_square.png b/real_robots/omnirobot_utils/blue_square.png new file mode 100644 index 0000000000000000000000000000000000000000..db3e9a12b5ce1d613621e3d69af41b5e19f4dfb8 GIT binary patch literal 148 zcmeAS@N?(olHy`uVBq!ia0vp^<{-?$1SHjWx(WiRXipc%kcv5P&mH7#P+(v%Oc9ZL zw|~BT_=AfqzUzd)M1425%b&-WllgK>NtBiD+-ZK^%a>lhM40<;V-4e(XvU5G%m;*k P)-ZUw`njxgN@xNAv356% literal 0 HcmV?d00001 diff --git a/real_robots/omnirobot_utils/green_square.png b/real_robots/omnirobot_utils/green_square.png new file mode 100644 index 0000000000000000000000000000000000000000..29624d4d710f5d755b05363c6027b39489c88425 GIT binary patch literal 148 zcmeAS@N?(olHy`uVBq!ia0vp^<{-?$1SHjWx(WiRXipc%kcv5P&pGlo7%(twG<3Y& zQ15HAVT1c*$D+^+uj{V;*i&h>Vd>J#moi^&DT%Vuojc9XdpSYw&*Pt1Z7djX6snyM Q1X{!3>FVdQ&MBb@0C{sdKmY&$ literal 0 HcmV?d00001 diff --git a/real_robots/omnirobot_utils/omnirobot_manager_base.py b/real_robots/omnirobot_utils/omnirobot_manager_base.py index be44cf702..050efadb6 100644 --- a/real_robots/omnirobot_utils/omnirobot_manager_base.py +++ b/real_robots/omnirobot_utils/omnirobot_manager_base.py @@ -4,7 +4,8 @@ class OmnirobotManagerBase(object): - def __init__(self, second_cam_topic=None): + def __init__(self, simple_continual_target=False, circular_continual_move=False, square_continual_move=False, + lambda_c=1.0, radius=0.5): """ This class is the basic class for omnirobot server, and omnirobot simulator's server. This class takes omnirobot position at instant t, and takes the action at instant t, @@ -13,6 +14,11 @@ def __init__(self, second_cam_topic=None): super(OmnirobotManagerBase, self).__init__() self.second_cam_topic = SECOND_CAM_TOPIC self.episode_idx = 0 + self.simple_continual_target = simple_continual_target + self.circular_continual_move = circular_continual_move + self.square_continual_move = square_continual_move + self.lambda_c = lambda_c + self.radius = radius # the abstract object for robot, # can be the real robot (Omnirobot class) @@ -141,14 +147,33 @@ def processMsg(self, msg): print("Unsupported action: ", action) # Determinate the reward for this step - - # Consider that we reached the target if we are close enough - # we detect that computing the difference in area between TARGET_INITIAL_AREA - # current detected area of the target - if np.linalg.norm(np.array(self.robot.robot_pos) - np.array(self.robot.target_pos)) \ - < DIST_TO_TARGET_THRESHOLD: - self.reward = REWARD_TARGET_REACH - elif has_bumped: - self.reward = REWARD_BUMP_WALL + + if self.circular_continual_move or self.square_continual_move: + step_counter = msg.get("step_counter", None) + assert step_counter is not None + + self.robot.appendToHistory(self.robot.robot_pos) + + ord = None + if self.square_continual_move: + ord = np.inf + self.reward = 1 - (np.linalg.norm(self.robot.robot_pos, ord=ord) - self.radius) ** 2 + + if step_counter < self.robot.getHistorySize(): + pass + else: + self.robot.popOfHistory() + self.reward += \ + self.lambda_c * np.linalg.norm(self.robot.robot_pos - self.robot.robot_pos_past_k_steps[-1]) + else: - self.reward = REWARD_NOTHING + # Consider that we reached the target if we are close enough + # we detect that computing the difference in area between TARGET_INITIAL_AREA + # current detected area of the target + if np.linalg.norm(np.array(self.robot.robot_pos) - np.array(self.robot.target_pos)) \ + < DIST_TO_TARGET_THRESHOLD: + self.reward = REWARD_TARGET_REACH + elif has_bumped: + self.reward = REWARD_BUMP_WALL + else: + self.reward = REWARD_NOTHING diff --git a/real_robots/omnirobot_utils/red_square.png b/real_robots/omnirobot_utils/red_square.png new file mode 100644 index 0000000000000000000000000000000000000000..5b6cb4fe3cc8d19e93ca317e9925865cc6403811 GIT binary patch literal 148 zcmeAS@N?(olHy`uVBq!ia0vp^<{-?$1SHjWx(WiRXipc%kcv5P&mH7#P+(v%Oc9oQ zw|}00_=AfqzUzd)RJ}8`%b&-WllgK>NtBiD+-ZK^%a>lhM40<;V-2J9Va7Git~zQ! PYZyFT{an^LB{Ts5yCXLH literal 0 HcmV?d00001 From 8f23671bc12d77197825dc2a1f6de603ee15661a Mon Sep 17 00:00:00 2001 From: kalifou Date: Fri, 15 Mar 2019 11:09:55 +0100 Subject: [PATCH 003/141] adding args for learning the CL tasks --- environments/dataset_generator.py | 16 ++++++++-------- rl_baselines/train.py | 12 ++++++++++++ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/environments/dataset_generator.py b/environments/dataset_generator.py index 8316e40a9..ebb7c2311 100644 --- a/environments/dataset_generator.py +++ b/environments/dataset_generator.py @@ -148,15 +148,15 @@ def main(): help='number of timesteps to run PPO2 on before generating the dataset') parser.add_argument('--toward-target-timesteps-proportion', type=float, default=0.0, help="propotion of timesteps that use simply towards target policy, should be 0.0 to 1.0") - parser.add_argument('--simple-continual', action='store_true', default=False, - help = 'Simple red dot target for task 1 of continual learning scenario. ' + - 'The task is: robot should reach the target.') - parser.add_argument('--circular-continual', action='store_true', default=False, + parser.add_argument('-sc', '--simple-continual', action='store_true', default=False, + help='Simple red square target for task 1 of continual learning scenario. ' + + 'The task is: robot should reach the target.') + parser.add_argument('-cc', '--circular-continual', action='store_true', default=False, help='Blue square target for task 2 of continual learning scenario. ' + - 'The task is: robot should turn in circle around the target.') - parser.add_argument('--square-continual', action='store_true', default=False, - help = 'Green triangle target for task 3 of continual learning scenario. ' + - 'The task is: robot should turn in square around the target.') + 'The task is: robot should turn in circle around the target.') + parser.add_argument('-sqc', '--square-continual', action='store_true', default=False, + help='Green square target for task 3 of continual learning scenario. ' + + 'The task is: robot should turn in square around the target.') args = parser.parse_args() diff --git a/rl_baselines/train.py b/rl_baselines/train.py index b4239d2bc..cc385b376 100644 --- a/rl_baselines/train.py +++ b/rl_baselines/train.py @@ -207,6 +207,15 @@ def main(): help='load the latest learned model (location:srl_zoo/logs/DatasetName/)') parser.add_argument('--load-rl-model-path', type=str, default=None, help="load the trained RL model, should be with the same algorithm type") + parser.add_argument('-sc', '--simple-continual', action='store_true', default=False, + help='Simple red square target for task 1 of continual learning scenario. ' + + 'The task is: robot should reach the target.') + parser.add_argument('-cc', '--circular-continual', action='store_true', default=False, + help='Blue square target for task 2 of continual learning scenario. ' + + 'The task is: robot should turn in circle around the target.') + parser.add_argument('-sqc', '--square-continual', action='store_true', default=False, + help='Green square target for task 3 of continual learning scenario. ' + + 'The task is: robot should turn in square around the target.') # Ignore unknown args for now args, unknown = parser.parse_known_args() @@ -236,6 +245,9 @@ def main(): break assert found, "Error: srl_model {}, is not compatible with the {} environment.".format(args.srl_model, args.env) + assert sum([args.simple_continual, args.circular_continual, args.square_continual]) <= 1 and args.env == "OmnirobotEnv-v0", \ + "For continual SRL and RL, please provide only one scenario at the time and use OmnirobotEnv-v0 environment !" + ENV_NAME = args.env ALGO_NAME = args.algo VISDOM_PORT = args.port From daff917cc7d3726cc8500106bb12bc4ad496555c Mon Sep 17 00:00:00 2001 From: kalifou Date: Fri, 15 Mar 2019 11:48:07 +0100 Subject: [PATCH 004/141] collect CL args for replay --- replay/enjoy_baselines.py | 5 +++++ rl_baselines/train.py | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/replay/enjoy_baselines.py b/replay/enjoy_baselines.py index 218b11840..7502a2bd0 100644 --- a/replay/enjoy_baselines.py +++ b/replay/enjoy_baselines.py @@ -103,6 +103,11 @@ def loadConfigAndSetup(load_args): else: env_kwargs["force_down"] = env_globals.get('force_down', False) + if train_args["env"] == "OmnirobotEnv-v0": + env_kwargs["simple_continual_target"] = env_globals["simple_continual_target"] + env_kwargs["circular_continual_move"] = env_globals["circular_continual_move"] + env_kwargs["square_continual_move"] = env_globals["square_continual_move"] + srl_model_path = None if train_args["srl_model"] != "raw_pixels": train_args["policy"] = "mlp" diff --git a/rl_baselines/train.py b/rl_baselines/train.py index cc385b376..0425183cc 100644 --- a/rl_baselines/train.py +++ b/rl_baselines/train.py @@ -98,6 +98,11 @@ def configureEnvAndLogFolder(args, env_kwargs, all_models): srl_model_path = models['log_folder'] + path env_kwargs["srl_model_path"] = srl_model_path + # Use of continual learning env + env_kwargs["simple_continual_target"] = args.simple_continual + env_kwargs["circular_continual_move"] = args.circular_continual + env_kwargs["square_continual_move"] = args.square_continual + # Add date + current time args.log_dir += "{}/{}/".format(ALGO_NAME, datetime.now().strftime("%y-%m-%d_%Hh%M_%S")) LOG_DIR = args.log_dir From bc21db4e7923c49253b96d58d1d71d6e204fb174 Mon Sep 17 00:00:00 2001 From: Caselles Date: Sun, 24 Mar 2019 16:19:15 +0100 Subject: [PATCH 005/141] WIP on continual tasks --- environments/omnirobot_gym/omnirobot_env.py | 67 ++++++++++++++++--- real_robots/constants.py | 4 ++ real_robots/omnirobot_simulator_server.py | 6 +- .../omnirobot_utils/omnirobot_manager_base.py | 20 +++--- rl_baselines/train.py | 7 +- 5 files changed, 82 insertions(+), 22 deletions(-) diff --git a/environments/omnirobot_gym/omnirobot_env.py b/environments/omnirobot_gym/omnirobot_env.py index d781e5939..2b4078506 100644 --- a/environments/omnirobot_gym/omnirobot_env.py +++ b/environments/omnirobot_gym/omnirobot_env.py @@ -102,6 +102,9 @@ def __init__(self, renders=False, name="Omnirobot", is_discrete=True, save_path= self.target_pos = None self.saver = None self._random_target = random_target + self.simple_continual_target = simple_continual_target + self.circular_continual_move = circular_continual_move + self.square_continual_move = square_continual_move if self._is_discrete: self.action_space = spaces.Discrete(N_DISCRETE_ACTIONS) @@ -358,10 +361,14 @@ def initVisualizeBoundary(self): self.boundary_coner_pixel_pos = np.zeros((2,4)) # assume that image is undistorted - self.boundary_coner_pixel_pos[:,0] = pos_transformer.phyPosGround2PixelPos([MIN_X, MIN_Y], return_distort_image_pos=False).squeeze() - self.boundary_coner_pixel_pos[:,1] = pos_transformer.phyPosGround2PixelPos([MAX_X, MIN_Y], return_distort_image_pos=False).squeeze() - self.boundary_coner_pixel_pos[:,2] = pos_transformer.phyPosGround2PixelPos([MAX_X, MAX_Y], return_distort_image_pos=False).squeeze() - self.boundary_coner_pixel_pos[:,3] = pos_transformer.phyPosGround2PixelPos([MIN_X, MAX_Y], return_distort_image_pos=False).squeeze() + self.boundary_coner_pixel_pos[:,0] = pos_transformer.phyPosGround2PixelPos([MIN_X, MIN_Y], + return_distort_image_pos=False).squeeze() + self.boundary_coner_pixel_pos[:,1] = pos_transformer.phyPosGround2PixelPos([MAX_X, MIN_Y], + return_distort_image_pos=False).squeeze() + self.boundary_coner_pixel_pos[:,2] = pos_transformer.phyPosGround2PixelPos([MAX_X, MAX_Y], + return_distort_image_pos=False).squeeze() + self.boundary_coner_pixel_pos[:,3] = pos_transformer.phyPosGround2PixelPos([MIN_X, MAX_Y], + return_distort_image_pos=False).squeeze() # transform the corresponding points into cropped image self.boundary_coner_pixel_pos = self.boundary_coner_pixel_pos - (np.array(ORIGIN_SIZE) - np.array(CROPPED_SIZE)).reshape(2,1) / 2.0 @@ -372,12 +379,54 @@ def initVisualizeBoundary(self): self.boundary_coner_pixel_pos = np.around(self.boundary_coner_pixel_pos).astype(np.int) + + if self.square_continual_move: + + + self.boundary_coner_pixel_pos_continual = np.zeros((2, 4)) + # assume that image is undistorted + self.boundary_coner_pixel_pos_continual[:, 0] = pos_transformer.phyPosGround2PixelPos([-RADIUS, -RADIUS], + return_distort_image_pos=False).squeeze() + self.boundary_coner_pixel_pos_continual[:, 1] = pos_transformer.phyPosGround2PixelPos([RADIUS, -RADIUS], + return_distort_image_pos=False).squeeze() + self.boundary_coner_pixel_pos_continual[:, 2] = pos_transformer.phyPosGround2PixelPos([RADIUS, RADIUS], + return_distort_image_pos=False).squeeze() + self.boundary_coner_pixel_pos_continual[:, 3] = pos_transformer.phyPosGround2PixelPos([-RADIUS, RADIUS], + return_distort_image_pos=False).squeeze() + + # transform the corresponding points into cropped image + self.boundary_coner_pixel_pos_continual = self.boundary_coner_pixel_pos_continual - ( + np.array(ORIGIN_SIZE) - np.array(CROPPED_SIZE)).reshape(2, 1) / 2.0 + + # transform the corresponding points into resized image (RENDER_WIDHT, RENDER_HEIGHT) + self.boundary_coner_pixel_pos_continual[0, :] *= RENDER_WIDTH / CROPPED_SIZE[0] + self.boundary_coner_pixel_pos_continual[1, :] *= RENDER_HEIGHT / CROPPED_SIZE[1] + + self.boundary_coner_pixel_pos_continual = np.around(self.boundary_coner_pixel_pos_continual).astype(np.int) + + def visualizeBoundary(self): """ - visualize the unvisible boundary, should call initVisualizeBoundary firstly + visualize the unvisible boundary, should call initVisualizeBoundary first """ self.observation_with_boundary = self.observation.copy() - cv2.line(self.observation_with_boundary,tuple(self.boundary_coner_pixel_pos[:,0]),tuple(self.boundary_coner_pixel_pos[:,1]),(200,0,0),3) - cv2.line(self.observation_with_boundary,tuple(self.boundary_coner_pixel_pos[:,1]),tuple(self.boundary_coner_pixel_pos[:,2]),(200,0,0),3) - cv2.line(self.observation_with_boundary,tuple(self.boundary_coner_pixel_pos[:,2]),tuple(self.boundary_coner_pixel_pos[:,3]),(200,0,0),3) - cv2.line(self.observation_with_boundary,tuple(self.boundary_coner_pixel_pos[:,3]),tuple(self.boundary_coner_pixel_pos[:,0]),(200,0,0),3) \ No newline at end of file + #Add boundary continual + if self.square_continual_move: + cv2.line(self.observation_with_boundary,tuple(self.boundary_coner_pixel_pos_continual[:,0]), + tuple(self.boundary_coner_pixel_pos_continual[:,1]),(0,0,200),3) + cv2.line(self.observation_with_boundary,tuple(self.boundary_coner_pixel_pos_continual[:,1]), + tuple(self.boundary_coner_pixel_pos_continual[:,2]),(0,0,200),3) + cv2.line(self.observation_with_boundary,tuple(self.boundary_coner_pixel_pos_continual[:,2]), + tuple(self.boundary_coner_pixel_pos_continual[:,3]),(0,0,200),3) + cv2.line(self.observation_with_boundary,tuple(self.boundary_coner_pixel_pos_continual[:,3]), + tuple(self.boundary_coner_pixel_pos_continual[:,0]),(0,0,200),3) + + #Add boundary of env + cv2.line(self.observation_with_boundary, tuple(self.boundary_coner_pixel_pos[:, 0]), + tuple(self.boundary_coner_pixel_pos[:, 1]), (200, 0, 0), 3) + cv2.line(self.observation_with_boundary, tuple(self.boundary_coner_pixel_pos[:, 1]), + tuple(self.boundary_coner_pixel_pos[:, 2]), (200, 0, 0), 3) + cv2.line(self.observation_with_boundary, tuple(self.boundary_coner_pixel_pos[:, 2]), + tuple(self.boundary_coner_pixel_pos[:, 3]), (200, 0, 0), 3) + cv2.line(self.observation_with_boundary, tuple(self.boundary_coner_pixel_pos[:, 3]), + tuple(self.boundary_coner_pixel_pos[:, 0]), (200, 0, 0), 3) \ No newline at end of file diff --git a/real_robots/constants.py b/real_robots/constants.py index 6f2c4bdb5..fc6bc1188 100644 --- a/real_robots/constants.py +++ b/real_robots/constants.py @@ -158,3 +158,7 @@ class Move(IntEnum): D_KEY = 100 # the letter "d" U_KEY = 117 # The letter "u" R_KEY = 114 # the letter "r" + + +# Constants for Continual setup +RADIUS = 0.5 #Radius of square or circle in continual scenarios: square-continual and circle-continual diff --git a/real_robots/omnirobot_simulator_server.py b/real_robots/omnirobot_simulator_server.py index 5af8f3401..1bea22ee0 100755 --- a/real_robots/omnirobot_simulator_server.py +++ b/real_robots/omnirobot_simulator_server.py @@ -27,7 +27,7 @@ def __init__(self, init_x, init_y, init_yaw, origin_size, cropped_size, back_ground_path, camera_info_path, robot_marker_path, robot_marker_margin, target_marker_path, target_marker_margin, robot_marker_code, target_marker_code, - robot_marker_length, target_marker_length, output_size, history_size=10, **_): + robot_marker_length, target_marker_length, output_size, history_size=2, **_): """ Class for rendering Omnirobot environment :param init_x: (float) initial x position of robot @@ -84,7 +84,7 @@ def __init__(self, init_x, init_y, init_yaw, origin_size, cropped_size, self.target_yaw_cmd = 0.0 # Target's real position on the grid - self.target_pos = np.float32([0, 0]) + self.target_pos = np.float32([0,0]) self.target_yaw = 0 # status of moving @@ -435,7 +435,7 @@ def resetEpisode(self): ) * NOISE_VAR_ROBOT_SIZE_PROPOTION + 1.0 # target reset - if self._random_target or self.episode_idx == 0: + if self._random_target: random_init_x = np.random.random_sample() * (TARGET_MAX_X - TARGET_MIN_X) + \ TARGET_MIN_X random_init_y = np.random.random_sample() * (TARGET_MAX_Y - TARGET_MIN_Y) + \ diff --git a/real_robots/omnirobot_utils/omnirobot_manager_base.py b/real_robots/omnirobot_utils/omnirobot_manager_base.py index 050efadb6..488354a8f 100644 --- a/real_robots/omnirobot_utils/omnirobot_manager_base.py +++ b/real_robots/omnirobot_utils/omnirobot_manager_base.py @@ -5,7 +5,7 @@ class OmnirobotManagerBase(object): def __init__(self, simple_continual_target=False, circular_continual_move=False, square_continual_move=False, - lambda_c=1.0, radius=0.5): + lambda_c=5.0): """ This class is the basic class for omnirobot server, and omnirobot simulator's server. This class takes omnirobot position at instant t, and takes the action at instant t, @@ -18,7 +18,6 @@ def __init__(self, simple_continual_target=False, circular_continual_move=False, self.circular_continual_move = circular_continual_move self.square_continual_move = square_continual_move self.lambda_c = lambda_c - self.radius = radius # the abstract object for robot, # can be the real robot (Omnirobot class) @@ -27,7 +26,7 @@ def __init__(self, simple_continual_target=False, circular_continual_move=False, def rightAction(self): """ - Let robot excute right action, and checking the boudary + Let robot execute right action, and checking the boundary :return has_bumped: (bool) """ if self.robot.robot_pos[1] - STEP_DISTANCE > MIN_Y: @@ -39,7 +38,7 @@ def rightAction(self): def leftAction(self): """ - Let robot excute left action, and checking the boudary + Let robot execute left action, and checking the boundary :return has_bumped: (bool) """ if self.robot.robot_pos[1] + STEP_DISTANCE < MAX_Y: @@ -51,7 +50,7 @@ def leftAction(self): def forwardAction(self): """ - Let robot excute forward action, and checking the boudary + Let robot execute forward action, and checking the boundary :return has_bumped: (bool) """ if self.robot.robot_pos[0] + STEP_DISTANCE < MAX_X: @@ -63,7 +62,7 @@ def forwardAction(self): def backwardAction(self): """ - Let robot excute backward action, and checking the boudary + Let robot execute backward action, and checking the boundary :return has_bumped: (bool) """ if self.robot.robot_pos[0] - STEP_DISTANCE > MIN_X: @@ -75,7 +74,7 @@ def backwardAction(self): def moveContinousAction(self, msg): """ - Let robot excute continous action, and checking the boudary + Let robot execute continous action, and checking the boundary :return has_bumped: (bool) """ if MIN_X < self.robot.robot_pos[0] + msg['action'][0] < MAX_X and \ @@ -157,14 +156,17 @@ def processMsg(self, msg): ord = None if self.square_continual_move: ord = np.inf - self.reward = 1 - (np.linalg.norm(self.robot.robot_pos, ord=ord) - self.radius) ** 2 + self.reward = 1 - (np.linalg.norm(self.robot.robot_pos, ord=ord) - RADIUS) ** 2 + #print(self.reward, 'REWARD SQUARE/CIRCLE') if step_counter < self.robot.getHistorySize(): pass else: self.robot.popOfHistory() self.reward += \ - self.lambda_c * np.linalg.norm(self.robot.robot_pos - self.robot.robot_pos_past_k_steps[-1]) + self.lambda_c * np.linalg.norm(self.robot.robot_pos - self.robot.robot_pos_past_k_steps[0]) + #print(self.lambda_c * np.linalg.norm(self.robot.robot_pos - self.robot.robot_pos_past_k_steps[0]), 'ADDITIONAL REWARD') + else: # Consider that we reached the target if we are close enough diff --git a/rl_baselines/train.py b/rl_baselines/train.py index 0425183cc..42250f238 100644 --- a/rl_baselines/train.py +++ b/rl_baselines/train.py @@ -285,6 +285,11 @@ def main(): env_kwargs["action_repeat"] = args.action_repeat # Random init position for button env_kwargs["random_target"] = args.random_target + + #If in simple continual scenario, then the target should be initialized randomly. + if args.simple_continual == True: + env_kwargs["random_target"] = True + # Allow up action # env_kwargs["force_down"] = False @@ -308,7 +313,7 @@ def main(): globals_env_param = sys.modules[env_class.__module__].getGlobals() super_class = registered_env[args.env][1] - # reccursive search through all the super classes of the asked environment, in order to get all the arguments. + # recursive search through all the super classes of the asked environment, in order to get all the arguments. rec_super_class_lookup = {dict_class: dict_super_class for _, (dict_class, dict_super_class, _, _) in registered_env.items()} while super_class != SRLGymEnv: From c68baeba30f806727531c93c66b7d22812c2eedb Mon Sep 17 00:00:00 2001 From: Caselles Date: Tue, 26 Mar 2019 09:57:57 +0100 Subject: [PATCH 006/141] Continual tasks: added vizu and solved a few bugs --- environments/omnirobot_gym/omnirobot_env.py | 39 ++++++++++++++++--- real_robots/constants.py | 2 +- real_robots/omnirobot_simulator_server.py | 2 + .../omnirobot_utils/omnirobot_manager_base.py | 9 ++--- rl_baselines/train.py | 1 + 5 files changed, 42 insertions(+), 11 deletions(-) diff --git a/environments/omnirobot_gym/omnirobot_env.py b/environments/omnirobot_gym/omnirobot_env.py index 2b4078506..b13443979 100644 --- a/environments/omnirobot_gym/omnirobot_env.py +++ b/environments/omnirobot_gym/omnirobot_env.py @@ -379,7 +379,7 @@ def initVisualizeBoundary(self): self.boundary_coner_pixel_pos = np.around(self.boundary_coner_pixel_pos).astype(np.int) - + # Create square for vizu of objective in continual square task if self.square_continual_move: @@ -404,6 +404,32 @@ def initVisualizeBoundary(self): self.boundary_coner_pixel_pos_continual = np.around(self.boundary_coner_pixel_pos_continual).astype(np.int) + elif self.circular_continual_move: + self.center_coordinates = pos_transformer.phyPosGround2PixelPos([0, 0], + return_distort_image_pos=False).squeeze() + self.center_coordinates = self.center_coordinates - ( + np.array(ORIGIN_SIZE) - np.array(CROPPED_SIZE)) / 2.0 + # transform the corresponding points into resized image (RENDER_WIDHT, RENDER_HEIGHT) + self.center_coordinates[0] *= RENDER_WIDTH / CROPPED_SIZE[0] + self.center_coordinates[1] *= RENDER_HEIGHT / CROPPED_SIZE[1] + + self.center_coordinates = np.around(self.center_coordinates).astype(np.int) + + + # Points to convert radisu in env space + self.boundary_coner_pixel_pos_continual = pos_transformer.phyPosGround2PixelPos([0, RADIUS], + return_distort_image_pos=False).squeeze() + + # transform the corresponding points into cropped image + self.boundary_coner_pixel_pos_continual = self.boundary_coner_pixel_pos_continual - ( + np.array(ORIGIN_SIZE) - np.array(CROPPED_SIZE)) / 2.0 + + # transform the corresponding points into resized image (RENDER_WIDHT, RENDER_HEIGHT) + self.boundary_coner_pixel_pos_continual[0] *= RENDER_WIDTH / CROPPED_SIZE[0] + self.boundary_coner_pixel_pos_continual[1] *= RENDER_HEIGHT / CROPPED_SIZE[1] + + self.boundary_coner_pixel_pos_continual = np.around(self.boundary_coner_pixel_pos_continual).astype(np.int) + def visualizeBoundary(self): """ @@ -413,13 +439,16 @@ def visualizeBoundary(self): #Add boundary continual if self.square_continual_move: cv2.line(self.observation_with_boundary,tuple(self.boundary_coner_pixel_pos_continual[:,0]), - tuple(self.boundary_coner_pixel_pos_continual[:,1]),(0,0,200),3) + tuple(self.boundary_coner_pixel_pos_continual[:,1]),(0,0,200),2) cv2.line(self.observation_with_boundary,tuple(self.boundary_coner_pixel_pos_continual[:,1]), - tuple(self.boundary_coner_pixel_pos_continual[:,2]),(0,0,200),3) + tuple(self.boundary_coner_pixel_pos_continual[:,2]),(0,0,200),2) cv2.line(self.observation_with_boundary,tuple(self.boundary_coner_pixel_pos_continual[:,2]), - tuple(self.boundary_coner_pixel_pos_continual[:,3]),(0,0,200),3) + tuple(self.boundary_coner_pixel_pos_continual[:,3]),(0,0,200),2) cv2.line(self.observation_with_boundary,tuple(self.boundary_coner_pixel_pos_continual[:,3]), - tuple(self.boundary_coner_pixel_pos_continual[:,0]),(0,0,200),3) + tuple(self.boundary_coner_pixel_pos_continual[:,0]),(0,0,200),2) + elif self.circular_continual_move: + radius_converted = np.linalg.norm(self.center_coordinates - self.boundary_coner_pixel_pos_continual) + cv2.circle(self.observation_with_boundary, tuple(self.center_coordinates), np.float32(radius_converted), (0,0,200),2) #Add boundary of env cv2.line(self.observation_with_boundary, tuple(self.boundary_coner_pixel_pos[:, 0]), diff --git a/real_robots/constants.py b/real_robots/constants.py index fc6bc1188..a6b09fe21 100644 --- a/real_robots/constants.py +++ b/real_robots/constants.py @@ -161,4 +161,4 @@ class Move(IntEnum): # Constants for Continual setup -RADIUS = 0.5 #Radius of square or circle in continual scenarios: square-continual and circle-continual +RADIUS = 0.7 #Radius of square or circle in continual scenarios: square-continual and circle-continual diff --git a/real_robots/omnirobot_simulator_server.py b/real_robots/omnirobot_simulator_server.py index 1bea22ee0..3863f64de 100755 --- a/real_robots/omnirobot_simulator_server.py +++ b/real_robots/omnirobot_simulator_server.py @@ -416,6 +416,8 @@ def __init__(self, **args): self.robot = OmniRobotEnvRender(**self.new_args) self.episode_idx = 0 self._random_target = self.new_args["random_target"] + if self.new_args["simple_continual_target"]: + self._random_target = True self.resetEpisode() # for a random target initial position def resetEpisode(self): diff --git a/real_robots/omnirobot_utils/omnirobot_manager_base.py b/real_robots/omnirobot_utils/omnirobot_manager_base.py index 488354a8f..b7597a136 100644 --- a/real_robots/omnirobot_utils/omnirobot_manager_base.py +++ b/real_robots/omnirobot_utils/omnirobot_manager_base.py @@ -5,7 +5,7 @@ class OmnirobotManagerBase(object): def __init__(self, simple_continual_target=False, circular_continual_move=False, square_continual_move=False, - lambda_c=5.0): + lambda_c=1.0): """ This class is the basic class for omnirobot server, and omnirobot simulator's server. This class takes omnirobot position at instant t, and takes the action at instant t, @@ -156,8 +156,8 @@ def processMsg(self, msg): ord = None if self.square_continual_move: ord = np.inf - self.reward = 1 - (np.linalg.norm(self.robot.robot_pos, ord=ord) - RADIUS) ** 2 - #print(self.reward, 'REWARD SQUARE/CIRCLE') + self.reward = 1 - 100 * (np.linalg.norm(self.robot.robot_pos, ord=ord) - RADIUS) ** 2 + print(self.reward, 'REWARD SQUARE/CIRCLE') if step_counter < self.robot.getHistorySize(): pass @@ -165,8 +165,7 @@ def processMsg(self, msg): self.robot.popOfHistory() self.reward += \ self.lambda_c * np.linalg.norm(self.robot.robot_pos - self.robot.robot_pos_past_k_steps[0]) - #print(self.lambda_c * np.linalg.norm(self.robot.robot_pos - self.robot.robot_pos_past_k_steps[0]), 'ADDITIONAL REWARD') - + print(self.lambda_c * np.linalg.norm(self.robot.robot_pos - self.robot.robot_pos_past_k_steps[0]), 'ADDITIONAL REWARD') else: # Consider that we reached the target if we are close enough diff --git a/rl_baselines/train.py b/rl_baselines/train.py index 42250f238..925ea9ab7 100644 --- a/rl_baselines/train.py +++ b/rl_baselines/train.py @@ -150,6 +150,7 @@ def callback(_locals, _globals): # Save Best model if mean_reward > best_mean_reward and n_episodes >= MIN_EPISODES_BEFORE_SAVE: + #if True: # Try saving the running average (only valid for mlp policy) try: if 'env' in _locals: From a1d4da93f848dc1b3b7f15449ba5afc9252a8fa3 Mon Sep 17 00:00:00 2001 From: Caselles Date: Tue, 26 Mar 2019 17:34:15 +0100 Subject: [PATCH 007/141] Solved bug on history not getting emptied between episodes --- real_robots/omnirobot_simulator_server.py | 5 ++++- .../omnirobot_utils/omnirobot_manager_base.py | 15 +++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/real_robots/omnirobot_simulator_server.py b/real_robots/omnirobot_simulator_server.py index 3863f64de..548aef77f 100755 --- a/real_robots/omnirobot_simulator_server.py +++ b/real_robots/omnirobot_simulator_server.py @@ -27,7 +27,7 @@ def __init__(self, init_x, init_y, init_yaw, origin_size, cropped_size, back_ground_path, camera_info_path, robot_marker_path, robot_marker_margin, target_marker_path, target_marker_margin, robot_marker_code, target_marker_code, - robot_marker_length, target_marker_length, output_size, history_size=2, **_): + robot_marker_length, target_marker_length, output_size, history_size=6, **_): """ Class for rendering Omnirobot environment :param init_x: (float) initial x position of robot @@ -197,6 +197,9 @@ def appendToHistory(self, pos): def popOfHistory(self): self.robot_pos_past_k_steps.pop(0) + def emptyHistory(self): + self.robot_pos_past_k_steps = [] + def getCroppedImage(self): return self.image[self.cropped_range[0]:self.cropped_range[1], self.cropped_range[2]:self.cropped_range[3], :] diff --git a/real_robots/omnirobot_utils/omnirobot_manager_base.py b/real_robots/omnirobot_utils/omnirobot_manager_base.py index b7597a136..0c3e5ed50 100644 --- a/real_robots/omnirobot_utils/omnirobot_manager_base.py +++ b/real_robots/omnirobot_utils/omnirobot_manager_base.py @@ -18,6 +18,7 @@ def __init__(self, simple_continual_target=False, circular_continual_move=False, self.circular_continual_move = circular_continual_move self.square_continual_move = square_continual_move self.lambda_c = lambda_c + #self.reward_total = [] # the abstract object for robot, # can be the real robot (Omnirobot class) @@ -101,6 +102,7 @@ def resetEpisode(self): random_init_position = self.sampleRobotInitalPosition() self.robot.setRobotCmd(random_init_position[0], random_init_position[1], 0) + def processMsg(self, msg): """ Using this steps' msg command the determinate the correct position that the robot should be at next step, @@ -112,6 +114,10 @@ def processMsg(self, msg): if command == 'reset': action = None self.episode_idx += 1 + + # empty list of previous states + self.robot.emptyHistory() + self.resetEpisode() elif command == 'action': @@ -149,6 +155,7 @@ def processMsg(self, msg): if self.circular_continual_move or self.square_continual_move: step_counter = msg.get("step_counter", None) + print(step_counter, 'step_counter') assert step_counter is not None self.robot.appendToHistory(self.robot.robot_pos) @@ -156,8 +163,9 @@ def processMsg(self, msg): ord = None if self.square_continual_move: ord = np.inf - self.reward = 1 - 100 * (np.linalg.norm(self.robot.robot_pos, ord=ord) - RADIUS) ** 2 - print(self.reward, 'REWARD SQUARE/CIRCLE') + #self.reward = 1 - 100 * (np.linalg.norm(self.robot.robot_pos, ord=ord) - RADIUS) ** 2 + self.reward = 0 + #print(self.reward, 'REWARD SQUARE/CIRCLE') if step_counter < self.robot.getHistorySize(): pass @@ -167,6 +175,9 @@ def processMsg(self, msg): self.lambda_c * np.linalg.norm(self.robot.robot_pos - self.robot.robot_pos_past_k_steps[0]) print(self.lambda_c * np.linalg.norm(self.robot.robot_pos - self.robot.robot_pos_past_k_steps[0]), 'ADDITIONAL REWARD') + #self.reward_total.append(self.reward) + #print(self.robot.robot_pos_past_k_steps) + else: # Consider that we reached the target if we are close enough # we detect that computing the difference in area between TARGET_INITIAL_AREA From bf9c6c95d44f768349123fdde7541d3267bc9b6f Mon Sep 17 00:00:00 2001 From: kalifou Date: Tue, 26 Mar 2019 17:51:43 +0100 Subject: [PATCH 008/141] add penality for bumping --- real_robots/omnirobot_simulator_server.py | 2 +- .../omnirobot_utils/omnirobot_manager_base.py | 14 +++++++------- replay/enjoy_baselines.py | 3 ++- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/real_robots/omnirobot_simulator_server.py b/real_robots/omnirobot_simulator_server.py index 548aef77f..ee29845f8 100755 --- a/real_robots/omnirobot_simulator_server.py +++ b/real_robots/omnirobot_simulator_server.py @@ -27,7 +27,7 @@ def __init__(self, init_x, init_y, init_yaw, origin_size, cropped_size, back_ground_path, camera_info_path, robot_marker_path, robot_marker_margin, target_marker_path, target_marker_margin, robot_marker_code, target_marker_code, - robot_marker_length, target_marker_length, output_size, history_size=6, **_): + robot_marker_length, target_marker_length, output_size, history_size=10, **_): """ Class for rendering Omnirobot environment :param init_x: (float) initial x position of robot diff --git a/real_robots/omnirobot_utils/omnirobot_manager_base.py b/real_robots/omnirobot_utils/omnirobot_manager_base.py index 0c3e5ed50..2d0d65bc5 100644 --- a/real_robots/omnirobot_utils/omnirobot_manager_base.py +++ b/real_robots/omnirobot_utils/omnirobot_manager_base.py @@ -5,7 +5,7 @@ class OmnirobotManagerBase(object): def __init__(self, simple_continual_target=False, circular_continual_move=False, square_continual_move=False, - lambda_c=1.0): + lambda_c=10.0): """ This class is the basic class for omnirobot server, and omnirobot simulator's server. This class takes omnirobot position at instant t, and takes the action at instant t, @@ -16,7 +16,7 @@ def __init__(self, simple_continual_target=False, circular_continual_move=False, self.episode_idx = 0 self.simple_continual_target = simple_continual_target self.circular_continual_move = circular_continual_move - self.square_continual_move = square_continual_move + self.square_continual_move = square_continual_move self.lambda_c = lambda_c #self.reward_total = [] @@ -155,7 +155,6 @@ def processMsg(self, msg): if self.circular_continual_move or self.square_continual_move: step_counter = msg.get("step_counter", None) - print(step_counter, 'step_counter') assert step_counter is not None self.robot.appendToHistory(self.robot.robot_pos) @@ -163,21 +162,22 @@ def processMsg(self, msg): ord = None if self.square_continual_move: ord = np.inf - #self.reward = 1 - 100 * (np.linalg.norm(self.robot.robot_pos, ord=ord) - RADIUS) ** 2 - self.reward = 0 - #print(self.reward, 'REWARD SQUARE/CIRCLE') + self.reward = self.lambda_c * (1 - (np.linalg.norm(self.robot.robot_pos, ord=ord) - RADIUS) ** 2) + if step_counter < self.robot.getHistorySize(): pass else: self.robot.popOfHistory() self.reward += \ self.lambda_c * np.linalg.norm(self.robot.robot_pos - self.robot.robot_pos_past_k_steps[0]) - print(self.lambda_c * np.linalg.norm(self.robot.robot_pos - self.robot.robot_pos_past_k_steps[0]), 'ADDITIONAL REWARD') #self.reward_total.append(self.reward) #print(self.robot.robot_pos_past_k_steps) + if has_bumped: + self.reward += self.lambda_c * REWARD_BUMP_WALL + else: # Consider that we reached the target if we are close enough # we detect that computing the difference in area between TARGET_INITIAL_AREA diff --git a/replay/enjoy_baselines.py b/replay/enjoy_baselines.py index 7502a2bd0..967e6de96 100644 --- a/replay/enjoy_baselines.py +++ b/replay/enjoy_baselines.py @@ -331,10 +331,11 @@ def main(): n_done += np.sum(dones) if (n_done - last_n_done) > 1: + last_n_done = n_done _, mean_reward = computeMeanReward(log_dir, n_done) print("{} episodes - Mean reward: {:.2f}".format(n_done, mean_reward)) - + print("print: ", n_done, log_dir) _, mean_reward = computeMeanReward(log_dir, n_done) print("{} episodes - Mean reward: {:.2f}".format(n_done, mean_reward)) From 7de393de5d086f58557416d980222373c4ff3f9a Mon Sep 17 00:00:00 2001 From: kalifou Date: Tue, 26 Mar 2019 18:20:52 +0100 Subject: [PATCH 009/141] coeff for circular task --- real_robots/omnirobot_utils/omnirobot_manager_base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/real_robots/omnirobot_utils/omnirobot_manager_base.py b/real_robots/omnirobot_utils/omnirobot_manager_base.py index 2d0d65bc5..be31e0195 100644 --- a/real_robots/omnirobot_utils/omnirobot_manager_base.py +++ b/real_robots/omnirobot_utils/omnirobot_manager_base.py @@ -163,8 +163,8 @@ def processMsg(self, msg): if self.square_continual_move: ord = np.inf - self.reward = self.lambda_c * (1 - (np.linalg.norm(self.robot.robot_pos, ord=ord) - RADIUS) ** 2) - + self.reward = 2 * (1 - (np.linalg.norm(self.robot.robot_pos, ord=ord) - RADIUS) ** 2) + if step_counter < self.robot.getHistorySize(): pass else: From edd82fa249a9e7c645661c059d85973cb52f6445 Mon Sep 17 00:00:00 2001 From: kalifou Date: Wed, 27 Mar 2019 14:49:15 +0100 Subject: [PATCH 010/141] fix reward shaping with the product operator --- real_robots/constants.py | 8 ++++---- real_robots/omnirobot_utils/omnirobot_manager_base.py | 11 +++-------- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/real_robots/constants.py b/real_robots/constants.py index a6b09fe21..27d61bba9 100644 --- a/real_robots/constants.py +++ b/real_robots/constants.py @@ -136,6 +136,10 @@ class Move(IntEnum): CAMERA_ROT_EULER_COORD_GROUND = [0, 180, 0] ORIGIN_SIZE = [640, 480] # camera's original resolution CROPPED_SIZE = [480, 480] # cropped to a square, attention, this is not the output image size (RENDER_SIZE) + + # Constants for Continual setup + RADIUS = 0.6125 # Radius of square or circle in continual scenarios: square-continual and circle-continual + # Gazebo else: LEFT_ARM_INIT_POS = [0.6, 0.30, 0.20] @@ -158,7 +162,3 @@ class Move(IntEnum): D_KEY = 100 # the letter "d" U_KEY = 117 # The letter "u" R_KEY = 114 # the letter "r" - - -# Constants for Continual setup -RADIUS = 0.7 #Radius of square or circle in continual scenarios: square-continual and circle-continual diff --git a/real_robots/omnirobot_utils/omnirobot_manager_base.py b/real_robots/omnirobot_utils/omnirobot_manager_base.py index be31e0195..0eb1aa6f3 100644 --- a/real_robots/omnirobot_utils/omnirobot_manager_base.py +++ b/real_robots/omnirobot_utils/omnirobot_manager_base.py @@ -18,7 +18,6 @@ def __init__(self, simple_continual_target=False, circular_continual_move=False, self.circular_continual_move = circular_continual_move self.square_continual_move = square_continual_move self.lambda_c = lambda_c - #self.reward_total = [] # the abstract object for robot, # can be the real robot (Omnirobot class) @@ -163,20 +162,16 @@ def processMsg(self, msg): if self.square_continual_move: ord = np.inf - self.reward = 2 * (1 - (np.linalg.norm(self.robot.robot_pos, ord=ord) - RADIUS) ** 2) + self.reward = self.lambda_c * (1 - (np.linalg.norm(self.robot.robot_pos, ord=ord) - RADIUS) ** 2) if step_counter < self.robot.getHistorySize(): pass else: self.robot.popOfHistory() - self.reward += \ - self.lambda_c * np.linalg.norm(self.robot.robot_pos - self.robot.robot_pos_past_k_steps[0]) - - #self.reward_total.append(self.reward) - #print(self.robot.robot_pos_past_k_steps) + self.reward *= np.linalg.norm(self.robot.robot_pos - self.robot.robot_pos_past_k_steps[0]) if has_bumped: - self.reward += self.lambda_c * REWARD_BUMP_WALL + self.reward += self.lambda_c * self.lambda_c * REWARD_BUMP_WALL else: # Consider that we reached the target if we are close enough From ed6923cf1de0c489e9b49aeae89023c9ad93473a Mon Sep 17 00:00:00 2001 From: kalifou Date: Mon, 1 Apr 2019 16:19:02 +0200 Subject: [PATCH 011/141] adding new task - eight shape (draft) --- environments/omnirobot_gym/omnirobot_env.py | 4 +++- real_robots/omnirobot_simulator_server.py | 5 +++-- .../omnirobot_utils/omnirobot_manager_base.py | 17 +++++++++++++---- replay/enjoy_baselines.py | 1 + rl_baselines/train.py | 8 ++++++-- 5 files changed, 26 insertions(+), 9 deletions(-) diff --git a/environments/omnirobot_gym/omnirobot_env.py b/environments/omnirobot_gym/omnirobot_env.py index b13443979..26495c30f 100644 --- a/environments/omnirobot_gym/omnirobot_env.py +++ b/environments/omnirobot_gym/omnirobot_env.py @@ -73,7 +73,7 @@ class OmniRobotEnv(SRLGymEnv): def __init__(self, renders=False, name="Omnirobot", is_discrete=True, save_path='srl_zoo/data/', state_dim=-1, learn_states=False, srl_model="raw_pixels", record_data=False, action_repeat=1, random_target=True, shape_reward=False, simple_continual_target=False, circular_continual_move=False, - square_continual_move=False, env_rank=0, srl_pipe=None, **_): + square_continual_move=False, eight_continual_move=False, env_rank=0, srl_pipe=None, **_): super(OmniRobotEnv, self).__init__(srl_model=srl_model, relative_pos=RELATIVE_POS, @@ -105,6 +105,7 @@ def __init__(self, renders=False, name="Omnirobot", is_discrete=True, save_path= self.simple_continual_target = simple_continual_target self.circular_continual_move = circular_continual_move self.square_continual_move = square_continual_move + self.eight_continual_move = eight_continual_move if self._is_discrete: self.action_space = spaces.Discrete(N_DISCRETE_ACTIONS) @@ -135,6 +136,7 @@ def __init__(self, renders=False, name="Omnirobot", is_discrete=True, save_path= self.socket = OmniRobotSimulatorSocket(simple_continual_target=simple_continual_target, circular_continual_move=circular_continual_move, square_continual_move=square_continual_move, + eight_continual_move=eight_continual_move, output_size=[RENDER_WIDTH, RENDER_HEIGHT], random_target=self._random_target) else: diff --git a/real_robots/omnirobot_simulator_server.py b/real_robots/omnirobot_simulator_server.py index ee29845f8..05266f93e 100755 --- a/real_robots/omnirobot_simulator_server.py +++ b/real_robots/omnirobot_simulator_server.py @@ -402,7 +402,7 @@ def __init__(self, **args): elif self.new_args["circular_continual_move"]: self.new_args["target_marker_path"] = "real_robots/omnirobot_utils/blue_square.png" - elif self.new_args["square_continual_move"]: + elif self.new_args["square_continual_move"] or self.new_args["eight_continual_move"]: self.new_args["target_marker_path"] = "real_robots/omnirobot_utils/green_square.png" else: # for black target, use target_margin4_pixel.png", @@ -410,7 +410,8 @@ def __init__(self, **args): super(OmniRobotSimulatorSocket, self).__init__(simple_continual_target=self.new_args["simple_continual_target"], circular_continual_move=self.new_args["circular_continual_move"], - square_continual_move=self.new_args["square_continual_move"]) + square_continual_move=self.new_args["square_continual_move"], + eight_continual_move=self.new_args["eight_continual_move"]) assert len(self.new_args['robot_marker_margin']) == 4 assert len(self.new_args['target_marker_margin']) == 4 diff --git a/real_robots/omnirobot_utils/omnirobot_manager_base.py b/real_robots/omnirobot_utils/omnirobot_manager_base.py index 0eb1aa6f3..a2646c307 100644 --- a/real_robots/omnirobot_utils/omnirobot_manager_base.py +++ b/real_robots/omnirobot_utils/omnirobot_manager_base.py @@ -5,7 +5,7 @@ class OmnirobotManagerBase(object): def __init__(self, simple_continual_target=False, circular_continual_move=False, square_continual_move=False, - lambda_c=10.0): + eight_continual_move=False, lambda_c=10.0): """ This class is the basic class for omnirobot server, and omnirobot simulator's server. This class takes omnirobot position at instant t, and takes the action at instant t, @@ -17,6 +17,7 @@ def __init__(self, simple_continual_target=False, circular_continual_move=False, self.simple_continual_target = simple_continual_target self.circular_continual_move = circular_continual_move self.square_continual_move = square_continual_move + self.eight_continual_move = eight_continual_move self.lambda_c = lambda_c # the abstract object for robot, @@ -152,17 +153,25 @@ def processMsg(self, msg): # Determinate the reward for this step - if self.circular_continual_move or self.square_continual_move: + if self.circular_continual_move or self.square_continual_move or self.eight_continual_move: step_counter = msg.get("step_counter", None) assert step_counter is not None self.robot.appendToHistory(self.robot.robot_pos) ord = None - if self.square_continual_move: + if self.square_continual_move or self.eight_continual_move: ord = np.inf - self.reward = self.lambda_c * (1 - (np.linalg.norm(self.robot.robot_pos, ord=ord) - RADIUS) ** 2) + if self.circular_continual_move or self.square_continual_move: + self.reward = self.lambda_c * (1 - (np.linalg.norm(self.robot.robot_pos, ord=ord) - RADIUS) ** 2) + elif self.eight_continual_move: + plus = self.robot.robot_pos[0]**2 + self.robot.robot_pos[1]**2 + #np.linalg.norm(self.robot.robot_pos, ord=ord) ** 2 # self.robot.robot_pos[0] ** 4 + minus = 2 * (RADIUS ** 2) * (self.robot.robot_pos[0] ** 2 - self.robot.robot_pos[1] ** 2) + self.reward = self.lambda_c * (1 - (plus - minus) ** 2) + else: + pass if step_counter < self.robot.getHistorySize(): pass diff --git a/replay/enjoy_baselines.py b/replay/enjoy_baselines.py index 967e6de96..ef39bee36 100644 --- a/replay/enjoy_baselines.py +++ b/replay/enjoy_baselines.py @@ -107,6 +107,7 @@ def loadConfigAndSetup(load_args): env_kwargs["simple_continual_target"] = env_globals["simple_continual_target"] env_kwargs["circular_continual_move"] = env_globals["circular_continual_move"] env_kwargs["square_continual_move"] = env_globals["square_continual_move"] + env_kwargs["eight_continual_move"] = env_globals["eight_continual_move"] srl_model_path = None if train_args["srl_model"] != "raw_pixels": diff --git a/rl_baselines/train.py b/rl_baselines/train.py index 925ea9ab7..1c391599a 100644 --- a/rl_baselines/train.py +++ b/rl_baselines/train.py @@ -102,6 +102,7 @@ def configureEnvAndLogFolder(args, env_kwargs, all_models): env_kwargs["simple_continual_target"] = args.simple_continual env_kwargs["circular_continual_move"] = args.circular_continual env_kwargs["square_continual_move"] = args.square_continual + env_kwargs["eight_continual_move"] = args.eight_continual # Add date + current time args.log_dir += "{}/{}/".format(ALGO_NAME, datetime.now().strftime("%y-%m-%d_%Hh%M_%S")) @@ -150,7 +151,6 @@ def callback(_locals, _globals): # Save Best model if mean_reward > best_mean_reward and n_episodes >= MIN_EPISODES_BEFORE_SAVE: - #if True: # Try saving the running average (only valid for mlp policy) try: if 'env' in _locals: @@ -222,6 +222,9 @@ def main(): parser.add_argument('-sqc', '--square-continual', action='store_true', default=False, help='Green square target for task 3 of continual learning scenario. ' + 'The task is: robot should turn in square around the target.') + parser.add_argument('-ec', '--eight-continual', action='store_true', default=False, + help='Green square target for task 4 of continual learning scenario. ' + + 'The task is: robot should do the eigth with the target as center of the shape.') # Ignore unknown args for now args, unknown = parser.parse_known_args() @@ -251,7 +254,8 @@ def main(): break assert found, "Error: srl_model {}, is not compatible with the {} environment.".format(args.srl_model, args.env) - assert sum([args.simple_continual, args.circular_continual, args.square_continual]) <= 1 and args.env == "OmnirobotEnv-v0", \ + assert sum([args.simple_continual, args.circular_continual, args.square_continual, args.eight_continual]) \ + <= 1 and args.env == "OmnirobotEnv-v0", \ "For continual SRL and RL, please provide only one scenario at the time and use OmnirobotEnv-v0 environment !" ENV_NAME = args.env From 1920de41e80d04ab4f56fda2fcf64351525238d4 Mon Sep 17 00:00:00 2001 From: kalifou Date: Thu, 11 Apr 2019 13:46:30 +0200 Subject: [PATCH 012/141] On-Policy dataset-generator --- environments/dataset_generator.py | 79 ++++++++++++++++++++++++------- 1 file changed, 63 insertions(+), 16 deletions(-) diff --git a/environments/dataset_generator.py b/environments/dataset_generator.py index ebb7c2311..c11e8ea27 100644 --- a/environments/dataset_generator.py +++ b/environments/dataset_generator.py @@ -9,13 +9,19 @@ import numpy as np from stable_baselines import PPO2 +from stable_baselines.common import set_global_seeds from stable_baselines.common.vec_env import DummyVecEnv, VecNormalize from stable_baselines.common.policies import CnnPolicy +import tensorflow as tf + from environments import ThreadingType from environments.registry import registered_env +from replay.enjoy_baselines import createEnv, loadConfigAndSetup +from rl_baselines.utils import WrapFrameStack from srl_zoo.utils import printRed, printYellow + os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' # used to remove debug info of tensorflow @@ -34,6 +40,19 @@ def convertImagePath(args, path, record_id_start): return args.name + "/record_{:03d}".format(new_record_id) + "/" + image_name +def vecEnv(env_kwargs_local, env_class): + """ + Local Env Wrapper + :param env_kwargs_local: arguments related to the environment wrapper + :param env_class: class of the env + :return: env for the pretrained algo + """ + train_env = env_class(**{**env_kwargs_local, "record_data": False, "renders": False}) + train_env = DummyVecEnv([lambda: train_env]) + train_env = VecNormalize(train_env, norm_obs=True, norm_reward=False) + return train_env + + def env_thread(args, thread_num, partition=True, use_ppo2=False): """ Run a session of an environment @@ -55,6 +74,7 @@ def env_thread(args, thread_num, partition=True, use_ppo2=False): "simple_continual_target": args.simple_continual, "circular_continual_move": args.circular_continual, "square_continual_move": args.square_continual + } if partition: @@ -62,18 +82,31 @@ def env_thread(args, thread_num, partition=True, use_ppo2=False): else: env_kwargs["name"] = args.name + if args.run_policy == "custom": + args.log_dir = args.log_custom_policy + args.render = args.display + args.plotting, args.action_proba = False, False + + train_args, load_path, algo_name, algo_class, _, env_kwargs_extra = loadConfigAndSetup(args) + env_kwargs["srl_model"] = env_kwargs_extra["srl_model"] + env_class = registered_env[args.env][0] env = env_class(**env_kwargs) - model = None - if use_ppo2: - # Additional env when using a trained ppo agent to generate data - # instead of a random agent - train_env = env_class(**{**env_kwargs, "record_data": False, "renders": False}) - train_env = DummyVecEnv([lambda: train_env]) - train_env = VecNormalize(train_env, norm_obs=True, norm_reward=False) + if use_ppo2 or args.run_policy == 'custom': + + # Additional env when using a trained agent to generate data + train_env = vecEnv(env_kwargs, env_class) - model = PPO2(CnnPolicy, train_env).learn(args.ppo2_timesteps) + if use_ppo2: + model = PPO2(CnnPolicy, train_env).learn(args.ppo2_timesteps) + else: + _, _, algo_args = createEnv(args, train_args, algo_name, algo_class, env_kwargs) + + tf.reset_default_graph() + set_global_seeds(args.seed) + printYellow("Compiling Policy function....") + model = algo_class.load(load_path, args=algo_args) frames = 0 start_time = time.time() @@ -83,8 +116,10 @@ def env_thread(args, thread_num, partition=True, use_ppo2=False): seed = args.seed + i_episode + args.num_episode // args.num_cpu * thread_num + \ (thread_num if thread_num <= args.num_episode % args.num_cpu else args.num_episode % args.num_cpu) - env.seed(seed) - env.action_space.seed(seed) # this is for the sample() function from gym.space + if not args.run_policy == 'custom': + env.seed(seed) + env.action_space.seed(seed) # this is for the sample() function from gym.space + obs = env.reset() done = False t = 0 @@ -94,6 +129,8 @@ def env_thread(args, thread_num, partition=True, use_ppo2=False): if use_ppo2: action, _ = model.predict([obs]) + elif args.run_policy == 'custom': + action = [model.getAction(obs, done)] else: if episode_toward_target_on and np.random.rand() < args.toward_target_timesteps_proportion: action = [env.actionPolicyTowardTarget()] @@ -101,11 +138,15 @@ def env_thread(args, thread_num, partition=True, use_ppo2=False): action = [env.action_space.sample()] action_to_step = action[0] - _, _, done, _ = env.step(action_to_step) + new_obs, _, done, _ = env.step(action_to_step) + + if args.run_policy == 'custom': + obs = new_obs frames += 1 t += 1 if done: + if np.random.rand() < args.toward_target_timesteps_proportion: episode_toward_target_on = True else: @@ -115,7 +156,6 @@ def env_thread(args, thread_num, partition=True, use_ppo2=False): if thread_num == 0: print("{:.2f} FPS".format(frames * args.num_cpu / (time.time() - start_time))) - def main(): parser = argparse.ArgumentParser(description='Deteministic dataset generator for SRL training ' + '(can be used for environment testing)') @@ -142,8 +182,12 @@ def main(): help='Shape the reward (reward = - distance) instead of a sparse reward') parser.add_argument('--reward-dist', action='store_true', default=False, help='Prints out the reward distribution when the dataset generation is finished') - parser.add_argument('--run-ppo2', action='store_true', default=False, - help='runs a ppo2 agent instead of a random agent') + parser.add_argument('--run-policy', type=str, default="random", + choices=['random', 'ppo2', 'custom'], + help='Policy to run for data collection ' + + '(random, localy pretrained ppo2, pretrained custom policy)') + parser.add_argument('--log-custom-policy', type=str, default='', + help='Logs of the custom pretained policy to run for data collection') parser.add_argument('--ppo2-timesteps', type=int, default=1000, help='number of timesteps to run PPO2 on before generating the dataset') parser.add_argument('--toward-target-timesteps-proportion', type=float, default=0.0, @@ -174,6 +218,9 @@ def main(): assert sum([args.simple_continual, args.circular_continual, args.square_continual]) <= 1, \ "For continual SRL and RL, please provide only one scenario at the time !" + assert len(args.log_custom_policy) >= 0 and args.run_policy == "custom", \ + "If using a custom policy, please specify a valid log folder for loading it." + # this is done so seed 0 and 1 are different and not simply offset of the same datasets. args.seed = np.random.RandomState(args.seed).randint(int(1e10)) @@ -189,13 +236,13 @@ def main(): os.mkdir(args.save_path + args.name) if args.num_cpu == 1: - env_thread(args, 0, partition=False, use_ppo2=args.run_ppo2) + env_thread(args, 0, partition=False, use_ppo2=args.run_policy=="ppo2") else: # try and divide into multiple processes, with an environment each try: jobs = [] for i in range(args.num_cpu): - process = multiprocessing.Process(target=env_thread, args=(args, i, True, args.run_ppo2)) + process = multiprocessing.Process(target=env_thread, args=(args, i, True, args.run_policy=="ppo2")) jobs.append(process) for j in jobs: From e6bdde157f0bf373503d3d9721368c89a305cb5f Mon Sep 17 00:00:00 2001 From: kalifou Date: Thu, 11 Apr 2019 13:59:02 +0200 Subject: [PATCH 013/141] add small fix --- environments/dataset_generator.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/environments/dataset_generator.py b/environments/dataset_generator.py index c11e8ea27..a29756a40 100644 --- a/environments/dataset_generator.py +++ b/environments/dataset_generator.py @@ -53,13 +53,12 @@ def vecEnv(env_kwargs_local, env_class): return train_env -def env_thread(args, thread_num, partition=True, use_ppo2=False): +def env_thread(args, thread_num, partition=True): """ Run a session of an environment :param args: (ArgumentParser object) :param thread_num: (int) The thread ID of the environment session :param partition: (bool) If the output should be in multiple parts (default=True) - :param use_ppo2: (bool) Use ppo2 to generate the dataset """ env_kwargs = { "max_distance": args.max_distance, @@ -93,12 +92,13 @@ def env_thread(args, thread_num, partition=True, use_ppo2=False): env_class = registered_env[args.env][0] env = env_class(**env_kwargs) model = None - if use_ppo2 or args.run_policy == 'custom': + + if args.run_policy in ['custom', 'ppo2']: # Additional env when using a trained agent to generate data train_env = vecEnv(env_kwargs, env_class) - if use_ppo2: + if args.run_policy == 'ppo2': model = PPO2(CnnPolicy, train_env).learn(args.ppo2_timesteps) else: _, _, algo_args = createEnv(args, train_args, algo_name, algo_class, env_kwargs) @@ -127,7 +127,7 @@ def env_thread(args, thread_num, partition=True, use_ppo2=False): while not done: env.render() - if use_ppo2: + if args.run_policy == 'ppo2': action, _ = model.predict([obs]) elif args.run_policy == 'custom': action = [model.getAction(obs, done)] @@ -218,7 +218,7 @@ def main(): assert sum([args.simple_continual, args.circular_continual, args.square_continual]) <= 1, \ "For continual SRL and RL, please provide only one scenario at the time !" - assert len(args.log_custom_policy) >= 0 and args.run_policy == "custom", \ + assert not (args.log_custom_policy == '' and args.run_policy == 'custom'), \ "If using a custom policy, please specify a valid log folder for loading it." # this is done so seed 0 and 1 are different and not simply offset of the same datasets. @@ -236,13 +236,13 @@ def main(): os.mkdir(args.save_path + args.name) if args.num_cpu == 1: - env_thread(args, 0, partition=False, use_ppo2=args.run_policy=="ppo2") + env_thread(args, 0, partition=False) else: # try and divide into multiple processes, with an environment each try: jobs = [] for i in range(args.num_cpu): - process = multiprocessing.Process(target=env_thread, args=(args, i, True, args.run_policy=="ppo2")) + process = multiprocessing.Process(target=env_thread, args=(args, i, True)) jobs.append(process) for j in jobs: From a5b6623a002641c02c0979c9ac8cce27d21404c5 Mon Sep 17 00:00:00 2001 From: kalifou Date: Fri, 12 Apr 2019 11:54:22 +0200 Subject: [PATCH 014/141] Generative Replay for Dataset generation --- environments/dataset_generator.py | 48 ++++++++++++++++++--- environments/omnirobot_gym/omnirobot_env.py | 8 ++-- environments/srl_env.py | 2 +- 3 files changed, 48 insertions(+), 10 deletions(-) diff --git a/environments/dataset_generator.py b/environments/dataset_generator.py index a29756a40..01ef4eaca 100644 --- a/environments/dataset_generator.py +++ b/environments/dataset_generator.py @@ -2,10 +2,14 @@ import argparse import glob +import cv2 import multiprocessing import os import shutil +import tensorflow as tf import time +import torch as th +from torch.autograd import Variable import numpy as np from stable_baselines import PPO2 @@ -13,14 +17,17 @@ from stable_baselines.common.vec_env import DummyVecEnv, VecNormalize from stable_baselines.common.policies import CnnPolicy -import tensorflow as tf - from environments import ThreadingType from environments.registry import registered_env from replay.enjoy_baselines import createEnv, loadConfigAndSetup -from rl_baselines.utils import WrapFrameStack from srl_zoo.utils import printRed, printYellow +from srl_zoo.preprocessing.utils import deNormalize +from state_representation.models import loadSRLModel +RENDER_HEIGHT = 224 +RENDER_WIDTH = 224 +VALID_MODELS = ["forward", "inverse", "reward", "priors", "episode-prior", "reward-prior", "triplet", + "autoencoder", "vae", "dae", "random"] os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' # used to remove debug info of tensorflow @@ -92,6 +99,7 @@ def env_thread(args, thread_num, partition=True): env_class = registered_env[args.env][0] env = env_class(**env_kwargs) model = None + generated_obs = None if args.run_policy in ['custom', 'ppo2']: @@ -108,6 +116,12 @@ def env_thread(args, thread_num, partition=True): printYellow("Compiling Policy function....") model = algo_class.load(load_path, args=algo_args) + if args.replay_generative_model: + use_cuda = args.cuda_generative_replay + device = th.device("cuda" if th.cuda.is_available() and use_cuda else "cpu") + srl_model = loadSRLModel(args.log_generative_model, th.cuda.is_available()) + srl_state_dim = srl_model.state_dim + srl_model = srl_model.model.model frames = 0 start_time = time.time() # divide evenly, then do an extra one for only some of them in order to get the right count @@ -120,7 +134,15 @@ def env_thread(args, thread_num, partition=True): env.seed(seed) env.action_space.seed(seed) # this is for the sample() function from gym.space - obs = env.reset() + if args.replay_generative_model: + sample = Variable(th.randn(1, srl_state_dim)) + if th.cuda.is_available(): + sample = sample.cuda() + generated_obs = srl_model.decode(sample) + generated_obs = generated_obs[0].detach().cpu().numpy().transpose(1, 2, 0) + generated_obs = deNormalize(generated_obs) + + obs = env.reset(generated_observation=generated_obs) done = False t = 0 episode_toward_target_on = False @@ -137,8 +159,16 @@ def env_thread(args, thread_num, partition=True): else: action = [env.action_space.sample()] + if args.replay_generative_model: + sample = Variable(th.randn(1, srl_state_dim)) + if th.cuda.is_available(): + sample = sample.cuda() + generated_obs = srl_model.decode(sample) + generated_obs = generated_obs[0].detach().cpu().numpy().transpose(1, 2, 0) + generated_obs = deNormalize(generated_obs) + action_to_step = action[0] - new_obs, _, done, _ = env.step(action_to_step) + new_obs, _, done, _ = env.step(action_to_step, generated_observation=generated_obs) if args.run_policy == 'custom': obs = new_obs @@ -188,6 +218,11 @@ def main(): '(random, localy pretrained ppo2, pretrained custom policy)') parser.add_argument('--log-custom-policy', type=str, default='', help='Logs of the custom pretained policy to run for data collection') + parser.add_argument('-rgm', '--replay-generative-model', type=str, default="vae", choices=['vae'], + help='Generative model to replay for generating a dataset (for Continual Learning purposes)') + parser.add_argument('--log-generative-model', type=str, default='', + help='Logs of the custom pretained policy to run for data collection') + parser.add_argument('--cuda-generative-replay', action='store_true', default=False, help='enables CUDA for replay') parser.add_argument('--ppo2-timesteps', type=int, default=1000, help='number of timesteps to run PPO2 on before generating the dataset') parser.add_argument('--toward-target-timesteps-proportion', type=float, default=0.0, @@ -221,6 +256,9 @@ def main(): assert not (args.log_custom_policy == '' and args.run_policy == 'custom'), \ "If using a custom policy, please specify a valid log folder for loading it." + assert not (args.log_generative_model == '' and args.replay_generative_model == 'custom'), \ + "If using a custom policy, please specify a valid log folder for loading it." + # this is done so seed 0 and 1 are different and not simply offset of the same datasets. args.seed = np.random.RandomState(args.seed).randint(int(1e10)) diff --git a/environments/omnirobot_gym/omnirobot_env.py b/environments/omnirobot_gym/omnirobot_env.py index 26495c30f..e8ae871b8 100644 --- a/environments/omnirobot_gym/omnirobot_env.py +++ b/environments/omnirobot_gym/omnirobot_env.py @@ -181,7 +181,7 @@ def actionPolicyTowardTarget(self): else: return DELTA_POS if self.robot_pos[1] < self.target_pos[1] else -DELTA_POS - def step(self, action): + def step(self, action, generated_observation=None): """ :action: (int) :return: (tensor (np.ndarray)) observation, int reward, bool done, dict extras) @@ -210,7 +210,7 @@ def step(self, action): self.getEnvState() # Receive a camera image from the server - self.observation = self.getObservation() + self.observation = self.getObservation() if generated_observation is None else generated_observation * 255 done = self._hasEpisodeTerminated() self.render() @@ -274,7 +274,7 @@ def getRobotPos(self): """ return self.robot_pos - def reset(self): + def reset(self, generated_observation=None): """ Reset the environment :return: (numpy ndarray) first observation of the env @@ -288,7 +288,7 @@ def reset(self): # Update state related variables, important step to get both data and # metadata that allow reading the observation image self.getEnvState() - self.observation = self.getObservation() + self.observation = self.getObservation() if generated_observation is None else generated_observation * 255 if self.saver is not None: self.saver.reset(self.observation, self.getTargetPos(), self.getGroundTruth()) diff --git a/environments/srl_env.py b/environments/srl_env.py index 4c6be4f34..43ce13809 100644 --- a/environments/srl_env.py +++ b/environments/srl_env.py @@ -81,7 +81,7 @@ def close(self): # TODO: implement close function to close GUI pass - def step(self, action): + def step(self, action, generated_observation=None): """ :param action: (int or [float]) """ From 71f29fa92c6b734fa40b5d076d87e7a4e6f065c7 Mon Sep 17 00:00:00 2001 From: kalifou Date: Fri, 12 Apr 2019 16:20:29 +0200 Subject: [PATCH 015/141] fix to on-policy generation for srl based policies --- environments/dataset_generator.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/environments/dataset_generator.py b/environments/dataset_generator.py index 01ef4eaca..c919c1c83 100644 --- a/environments/dataset_generator.py +++ b/environments/dataset_generator.py @@ -20,9 +20,10 @@ from environments import ThreadingType from environments.registry import registered_env from replay.enjoy_baselines import createEnv, loadConfigAndSetup +from rl_baselines.utils import MultiprocessSRLModel from srl_zoo.utils import printRed, printYellow from srl_zoo.preprocessing.utils import deNormalize -from state_representation.models import loadSRLModel +from state_representation.models import loadSRLModel, getSRLDim RENDER_HEIGHT = 224 RENDER_WIDTH = 224 @@ -95,12 +96,15 @@ def env_thread(args, thread_num, partition=True): train_args, load_path, algo_name, algo_class, _, env_kwargs_extra = loadConfigAndSetup(args) env_kwargs["srl_model"] = env_kwargs_extra["srl_model"] + env_kwargs["srl_model_path"] = env_kwargs_extra.get("srl_model_path", None) + env_kwargs["state_dim"] = getSRLDim(env_kwargs_extra.get("srl_model_path", None)) + srl_model = MultiprocessSRLModel(args.num_cpu, args.env, env_kwargs) + env_kwargs["srl_pipe"] = srl_model.pipe env_class = registered_env[args.env][0] env = env_class(**env_kwargs) model = None generated_obs = None - if args.run_policy in ['custom', 'ppo2']: # Additional env when using a trained agent to generate data @@ -110,18 +114,18 @@ def env_thread(args, thread_num, partition=True): model = PPO2(CnnPolicy, train_env).learn(args.ppo2_timesteps) else: _, _, algo_args = createEnv(args, train_args, algo_name, algo_class, env_kwargs) - tf.reset_default_graph() set_global_seeds(args.seed) printYellow("Compiling Policy function....") model = algo_class.load(load_path, args=algo_args) - if args.replay_generative_model: + if len(args.replay_generative_model) > 0: use_cuda = args.cuda_generative_replay device = th.device("cuda" if th.cuda.is_available() and use_cuda else "cpu") srl_model = loadSRLModel(args.log_generative_model, th.cuda.is_available()) srl_state_dim = srl_model.state_dim srl_model = srl_model.model.model + frames = 0 start_time = time.time() # divide evenly, then do an extra one for only some of them in order to get the right count @@ -134,14 +138,13 @@ def env_thread(args, thread_num, partition=True): env.seed(seed) env.action_space.seed(seed) # this is for the sample() function from gym.space - if args.replay_generative_model: + if len(args.replay_generative_model) > 0: sample = Variable(th.randn(1, srl_state_dim)) if th.cuda.is_available(): sample = sample.cuda() generated_obs = srl_model.decode(sample) generated_obs = generated_obs[0].detach().cpu().numpy().transpose(1, 2, 0) generated_obs = deNormalize(generated_obs) - obs = env.reset(generated_observation=generated_obs) done = False t = 0 @@ -159,7 +162,7 @@ def env_thread(args, thread_num, partition=True): else: action = [env.action_space.sample()] - if args.replay_generative_model: + if len(args.replay_generative_model) > 0: sample = Variable(th.randn(1, srl_state_dim)) if th.cuda.is_available(): sample = sample.cuda() @@ -218,7 +221,7 @@ def main(): '(random, localy pretrained ppo2, pretrained custom policy)') parser.add_argument('--log-custom-policy', type=str, default='', help='Logs of the custom pretained policy to run for data collection') - parser.add_argument('-rgm', '--replay-generative-model', type=str, default="vae", choices=['vae'], + parser.add_argument('-rgm', '--replay-generative-model', type=str, default="", choices=['vae'], help='Generative model to replay for generating a dataset (for Continual Learning purposes)') parser.add_argument('--log-generative-model', type=str, default='', help='Logs of the custom pretained policy to run for data collection') From 413c4474d04fa74c9cdeaed2e4f4ff93568eb241 Mon Sep 17 00:00:00 2001 From: kalifou Date: Fri, 12 Apr 2019 16:30:32 +0200 Subject: [PATCH 016/141] fix to loading args for replay --- replay/enjoy_baselines.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/replay/enjoy_baselines.py b/replay/enjoy_baselines.py index ef39bee36..f48172c59 100644 --- a/replay/enjoy_baselines.py +++ b/replay/enjoy_baselines.py @@ -104,10 +104,10 @@ def loadConfigAndSetup(load_args): env_kwargs["force_down"] = env_globals.get('force_down', False) if train_args["env"] == "OmnirobotEnv-v0": - env_kwargs["simple_continual_target"] = env_globals["simple_continual_target"] - env_kwargs["circular_continual_move"] = env_globals["circular_continual_move"] - env_kwargs["square_continual_move"] = env_globals["square_continual_move"] - env_kwargs["eight_continual_move"] = env_globals["eight_continual_move"] + env_kwargs["simple_continual_target"] = env_globals.get("simple_continual_target", False) + env_kwargs["circular_continual_move"] = env_globals.get("circular_continual_move", False) + env_kwargs["square_continual_move"] = env_globals.get("square_continual_move", False) + env_kwargs["eight_continual_move"] = env_globals.get("eight_continual_move", False) srl_model_path = None if train_args["srl_model"] != "raw_pixels": From 6082a682e9cebaa38a4417500705e0caf1cd86ee Mon Sep 17 00:00:00 2001 From: TLESORT Date: Fri, 12 Apr 2019 18:33:32 +0200 Subject: [PATCH 017/141] first steps towards policy distillation --- Distilation_Readme.md | 80 ++++++++ rl_baselines/registry.py | 4 +- rl_baselines/supervised_rl/__init__.py | 0 .../supervised_rl/policy_distillation.py | 189 ++++++++++++++++++ rl_baselines/train.py | 7 + 5 files changed, 279 insertions(+), 1 deletion(-) create mode 100644 Distilation_Readme.md create mode 100644 rl_baselines/supervised_rl/__init__.py create mode 100644 rl_baselines/supervised_rl/policy_distillation.py diff --git a/Distilation_Readme.md b/Distilation_Readme.md new file mode 100644 index 000000000..ef804a236 --- /dev/null +++ b/Distilation_Readme.md @@ -0,0 +1,80 @@ + + + +# Steps for Distillation + + + + + +# 1 - Train Baselines + + +### 0 - Generate datasets for SRL (random policy) + +``` +cd srl_zoo +# Dataset 1 +python -m environments.dataset_generator --num-cpu 6 --name Omnibot_circular --env OmnirobotEnv-v0 --simple-continual --num-episode 250 +# Dataset 2 +python -m environments.dataset_generator --num-cpu 6 --name Omnibot_random_simple --env OmnirobotEnv-v0 --circular-continual --num-episode 250 +``` + +### 1.1) Train SRL + +``` +# Dataset 1 +python train.py --data-folder data/simple-continual -bs 32 --epochs 30 --state-dim 200 --training-set-size 30000 --losses autoencoder inverse +# Dataset 2 +python train.py --data-folder data/circular-continual -bs 32 --epochs 30 --state-dim 200 --training-set-size 30000 --losses autoencoder inverse +``` + + +### 1.2) Train policy + +``` +cd .. + +# Dataset 1 +python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --num-timesteps 1000000 --env OmnirobotEnv-v0 --log-dir logs/circular/ --num-cpu 8 --simple-continual --latest +# Dataset 2 +python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --num-timesteps 1000000 --env OmnirobotEnv-v0 --log-dir logs/circular/ --num-cpu 8 --circular-continual --latest + +``` + + + +# 2 - Train Distillation + + +### 2.1) Generate dataset on Policy + + +``` +# Dataset 1 +python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 50 --num-cpu 8 --run-policy custom --log-custom-policy logs/simple-continual +# Dataset 2 +python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 50 --num-cpu 8 --run-policy custom --log-custom-policy logs/circular-continual +# Merge Datasets + +? +``` + +### 2.3) Train SRL 1&2 + +``` +# Dataset 1 +python train.py --data-folder data/simple_continual_on_policy -bs 32 --epochs 2 --state-dim 200 --training-set-size 3000 --losses autoencoder inverse +# Dataset 2 +python train.py --data-folder data/circular_continual_on_policy -bs 32 --epochs 2 --state-dim 200 --training-set-size 3000 --losses autoencoder inverse +``` + + +### 2.3) Run Distillation + +``` +# Dataset 1 +python -m rl_baselines.train --algo distillation --srl-model srl_combination --num-timesteps 1000000 --env OmnirobotEnv-v0 --log-dir logs/simple/ --simple-continual --latest --teacher-data-folder srl_zoo/data/simple_continual_on_policy/ +# Dataset 2 +python -m rl_baselines.train --algo distillation --srl-model srl_combination --num-timesteps 1000000 --env OmnirobotEnv-v0 --log-dir logs/circular/ --circular-continual --latest --teacher-data-folder srl_zoo/data/circular_continual_on_policy/ +``` diff --git a/rl_baselines/registry.py b/rl_baselines/registry.py index 8fb8824d6..6f92a3cc4 100644 --- a/rl_baselines/registry.py +++ b/rl_baselines/registry.py @@ -12,6 +12,7 @@ from rl_baselines.random_agent import RandomAgentModel from rl_baselines.rl_algorithm.sac import SACModel from rl_baselines.rl_algorithm.trpo import TRPOModel +from rl_baselines.supervised_rl.policy_distillation import PolicyDistillationModel # Register, name: (algo class, algo type, list of action types) registered_rl = { @@ -26,7 +27,8 @@ "ppo2": (PPO2Model, AlgoType.REINFORCEMENT_LEARNING, [ActionType.DISCRETE, ActionType.CONTINUOUS]), "random_agent": (RandomAgentModel, AlgoType.OTHER, [ActionType.DISCRETE, ActionType.CONTINUOUS]), "sac": (SACModel, AlgoType.REINFORCEMENT_LEARNING, [ActionType.CONTINUOUS]), - "trpo": (TRPOModel, AlgoType.REINFORCEMENT_LEARNING, [ActionType.DISCRETE, ActionType.CONTINUOUS]) + "trpo": (TRPOModel, AlgoType.REINFORCEMENT_LEARNING, [ActionType.DISCRETE, ActionType.CONTINUOUS]), + "distillation": (PolicyDistillationModel, AlgoType.REINFORCEMENT_LEARNING, [ActionType.DISCRETE, ActionType.CONTINUOUS]) } # Checking validity of the registered RL algorithms diff --git a/rl_baselines/supervised_rl/__init__.py b/rl_baselines/supervised_rl/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/rl_baselines/supervised_rl/policy_distillation.py b/rl_baselines/supervised_rl/policy_distillation.py new file mode 100644 index 000000000..a539a811d --- /dev/null +++ b/rl_baselines/supervised_rl/policy_distillation.py @@ -0,0 +1,189 @@ +import time +import pickle + +import numpy as np +from stable_baselines.common.vec_env.subproc_vec_env import SubprocVecEnv +from stable_baselines.common.vec_env.vec_frame_stack import VecFrameStack +from stable_baselines.common.vec_env.vec_normalize import VecNormalize + +from rl_baselines.base_classes import BaseRLObject +from environments import ThreadingType +from environments.registry import registered_env +from environments.utils import makeEnv +from rl_baselines.utils import loadRunningAverage, MultiprocessSRLModel, softmax +from srl_zoo.utils import printYellow + + +############ DEV ################ +from tqdm import tqdm +from torch import nn +from torch.nn import functional as F +from srl_zoo.preprocessing.data_loader import SupervisedDataLoader +from srl_zoo.utils import loadData +from sklearn.model_selection import train_test_split +BATCH_SIZE = 32 +TEST_BATCH_SIZE = 256 + +class MLP(nn.Module): + def __init__(self, output_size, input_size, hidden_size=400): + super(MLP, self).__init__() + + self.input_size = input_size + self.hidden_size = hidden_size + self.output_size = output_size + + self.fc1 = nn.Linear(self.input_size, self.hidden_size) + self.fc2 = nn.Linear(self.hidden_size, self.hidden_size) + self.fc3 = nn.Linear(self.hidden_size, self.hidden_size) + self.fc4 = nn.Linear(self.hidden_size, self.output_size) + + def forward(self, input): + + input=input.view(-1, self.input_size) + + x = F.relu(self.fc1(input)) + x = F.relu(self.fc2(x)) + x = F.relu(self.fc3(x)) + x = F.relu(self.fc4(x)) + return x + + +class PolicyDistillationModel(BaseRLObject): + """ + Implementation of PolicyDistillation + """ + def __init__(self): + super(PolicyDistillationModel, self).__init__() + # pytorch model to distillate the policy + #self.model = MLP(input_size=1, hidden_size=400, output_size=1) + + def save(self, save_path, _locals=None): + assert self.M is not None, "Error: must train or load model before use" + with open(save_path, "wb") as f: + pickle.dump(self.__dict__, f) + + @classmethod + def load(cls, load_path, args=None): + with open(load_path, "rb") as f: + class_dict = pickle.load(f) + loaded_model = PolicyDistillationModel() + loaded_model.__dict__ = class_dict + return loaded_model + + def customArguments(self, parser): + parser.add_argument('--nothing4instance', help='Number of population (each one has 2 threads)', type=bool, + default=True) + + return parser + + def getActionProba(self, observation, dones=None, delta=0): + """ + returns the action probability distribution, from a given observation. + :param observation: (numpy int or numpy float) + :param dones: ([bool]) + :param delta: (numpy float or float) The exploration noise applied to the policy, set to 0 for no noise. + :return: (numpy float) + """ + assert self.model is not None, "Error: must train or load model before use" + action = self.model.forward(observation) + return softmax(action) + + def getAction(self, observation, dones=None, delta=0): + """ + From an observation returns the associated action + :param observation: (numpy int or numpy float) + :param dones: ([bool]) + :param delta: (numpy float or float) The exploration noise applied to the policy, set to 0 for no noise. + :return: (numpy float) + """ + assert self.model is not None, "Error: must train or load model before use" + + self.model.eval() + return np.argmax(self.model.forward(observation)) + + def loss_fn_kd(self, outputs, labels, teacher_outputs): + """ + + :param outputs: output from the student model + :param labels: label + :param teacher_outputs: output from the teacher_outputs model + :return: loss + """ + + + """ + inspired from : https://github.com/peterliht/knowledge-distillation-pytorch + Compute the knowledge-distillation (KD) loss given outputs, labels. + "Hyperparameters": temperature and alpha + NOTE: the KL Divergence for PyTorch comparing the softmaxs of teacher + and student expects the input tensor to be log probabilities! See Issue #2 + """ + alpha = 0.9 + T = 0.01 # temperature empirically found in "policy distillation" + KD_loss = nn.KLDivLoss()(F.log_softmax(outputs / T, dim=1), + F.softmax(teacher_outputs / T, dim=1)) + + # formula from https://github.com/peterliht/knowledge-distillation-pytorch + # KD_loss = nn.KLDivLoss()(F.log_softmax(outputs / T, dim=1), + # F.softmax(teacher_outputs / T, dim=1)) * (alpha * T * T) + \ + # F.cross_entropy(outputs, labels) * (1. - alpha) + + return KD_loss + + + def train(self, args, callback, env_kwargs=None, train_kwargs=None): + + #env = self.makeEnv(args, env_kwargs) + N_EPOCHS = args.epochs_distillation + print("mopdel state dim: ", self.model.output_size) + self.model = MLP(input_size=env_kwargs["state_dim"], hidden_size=400, + output_size=env_kwargs["N_DISCRETE_ACTIONS"]) + + #criterion = nn.MSELoss() + criterion = self.loss_fn_kd() + + + print("We assumed SRL training already done") + + print('Loading data for distillation ') + training_data, ground_truth, true_states, _ = loadData(args.teacher_data_folder) + rewards, episode_starts = training_data['rewards'], training_data['episode_starts'] + images_path = ground_truth['images_path'] + actions = training_data['actions'] + + limit = args.training_set_size + actions = actions[:limit] + + true_states = true_states.astype(np.float32) + x_indices = np.arange(len(true_states)).astype(np.int64) + + # Split into train/validation set + x_train, x_val, y_train, y_val = train_test_split(x_indices, true_states, + test_size=0.33, random_state=self.seed) + + train_loader = SupervisedDataLoader(x_train, y_train, images_path, batch_size=BATCH_SIZE, + max_queue_len=4, shuffle=True) + val_loader = SupervisedDataLoader(x_val, y_val, images_path, batch_size=TEST_BATCH_SIZE, + max_queue_len=1, shuffle=False) + + epoch_train_loss = [[] for _ in range(N_EPOCHS)] + epoch_val_loss = [[] for _ in range(N_EPOCHS)] + + for epoch in range(N_EPOCHS): + # In each epoch, we do a full pass over the training data: + train_loss, val_loss = 0, 0 + pbar = tqdm(total=len(train_loader)) + self.model.train() # Restore train mode + + print("The train_loader should contains observation and target_action ") + for obs, target_action in train_loader: + obs, target_action = obs.to(self.device), target_action.to(self.device) + + pred_action = self.model(obs) + self.optimizer.zero_grad() + loss = criterion(pred_action, target_action.detach()) + loss.backward() + self.optimizer.step() + train_loss += loss.item() + epoch_train_loss[epoch].append(loss.item()) + diff --git a/rl_baselines/train.py b/rl_baselines/train.py index 1c391599a..0250f4edb 100644 --- a/rl_baselines/train.py +++ b/rl_baselines/train.py @@ -225,6 +225,10 @@ def main(): parser.add_argument('-ec', '--eight-continual', action='store_true', default=False, help='Green square target for task 4 of continual learning scenario. ' + 'The task is: robot should do the eigth with the target as center of the shape.') + parser.add_argument('--teacher-data-folder', type=str, default="", + help='Dataset folder of the teacher(s) policy(ies)', required=True) + parser.add_argument('--epochs-distillation', type=int, default=30, metavar='N', + help='number of epochs to train for distillation(default: 30)') # Ignore unknown args for now args, unknown = parser.parse_known_args() @@ -258,6 +262,9 @@ def main(): <= 1 and args.env == "OmnirobotEnv-v0", \ "For continual SRL and RL, please provide only one scenario at the time and use OmnirobotEnv-v0 environment !" + assert args.algo == "distillation" and args.teacher_data_folder != '' and args.continuous_actions is False, \ + "For performing policy distillation, make sure use specify a valid teacher dataset!" + ENV_NAME = args.env ALGO_NAME = args.algo VISDOM_PORT = args.port From 4fb1e7b22b2fbcee4c7cd6a61cadf7690f108aa7 Mon Sep 17 00:00:00 2001 From: sun-te Date: Mon, 15 Apr 2019 22:26:05 +0200 Subject: [PATCH 018/141] cross-evaluation --- rl_baselines/train.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/rl_baselines/train.py b/rl_baselines/train.py index 1c391599a..f28c5182c 100644 --- a/rl_baselines/train.py +++ b/rl_baselines/train.py @@ -78,7 +78,7 @@ def configureEnvAndLogFolder(args, env_kwargs, all_models): env_kwargs["shape_reward"] = args.shape_reward # Actions in joint space or relative position space env_kwargs["action_joints"] = args.action_joints - args.log_dir += args.env + "/" + args.log_dir += ENV_NAME + "/" models = all_models[args.env] PLOT_TITLE = args.srl_model @@ -259,6 +259,14 @@ def main(): "For continual SRL and RL, please provide only one scenario at the time and use OmnirobotEnv-v0 environment !" ENV_NAME = args.env + if(args.circular_continual): + ENV_NAME+="-cc" + if(args.eight_continual): + ENV_NAME+="-ec" + if(args.simple_continual): + ENV_NAME+="-sc" + if(args.square_continual): + ENV_NAME+="-sqc" ALGO_NAME = args.algo VISDOM_PORT = args.port EPISODE_WINDOW = args.episode_window @@ -272,6 +280,7 @@ def main(): ALGO = algo + # if callback frequency needs to be changed LOG_INTERVAL = algo.LOG_INTERVAL SAVE_INTERVAL = algo.SAVE_INTERVAL From deaf4500ca9dbedf227141bd1071bd813878c2d8 Mon Sep 17 00:00:00 2001 From: sun-te Date: Mon, 15 Apr 2019 22:29:22 +0200 Subject: [PATCH 019/141] cross-evaluation --- rl_baselines/pipeline_cross.py | 161 +++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 rl_baselines/pipeline_cross.py diff --git a/rl_baselines/pipeline_cross.py b/rl_baselines/pipeline_cross.py new file mode 100644 index 000000000..97feaa2dd --- /dev/null +++ b/rl_baselines/pipeline_cross.py @@ -0,0 +1,161 @@ +""" +baseline benchmark script for openAI RL Baselines +""" +import os +import argparse +import subprocess + +import yaml +import numpy as np + +from rl_baselines.registry import registered_rl +from environments.registry import registered_env +from state_representation.registry import registered_srl +from state_representation import SRLType +from srl_zoo.utils import printGreen, printRed + +os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' # used to remove debug info of tensorflow + + +def main(): + parser = argparse.ArgumentParser(description="OpenAI RL Baselines Benchmark", + epilog='After the arguments are parsed, the rest are assumed to be arguments for' + + ' rl_baselines.train') + parser.add_argument('--algo', type=str, default='ppo2', help='OpenAI baseline to use', + choices=list(registered_rl.keys())) + parser.add_argument('--env', type=str, nargs='+', default=["OmnirobotEnv-v0"], help='environment ID(s)', + choices=list(registered_env.keys())) + parser.add_argument('--srl-model', type=str, nargs='+', default=["raw_pixels"], + help='SRL model(s) to use', + choices=list(registered_srl.keys())) + parser.add_argument('--num-timesteps', type=int, default=1e6, help='number of timesteps the baseline should run') + parser.add_argument('-v', '--verbose', action='store_true', default=False, help='Display baseline STDOUT') + parser.add_argument('--num-iteration', type=int, default=15, + help='number of time each algorithm should be run for each unique combination of environment ' + + ' and srl-model.') + parser.add_argument('--seed', type=int, default=0, + help='initial seed for each unique combination of environment and srl-model.') + parser.add_argument('--srl-config-file', type=str, default="config/srl_models.yaml", + help='Set the location of the SRL model path configuration.') + + parser.add_argument('--tasks', type=str, nargs='+', default=["cc"], + help='The tasks for the robot', + choices=["cc","ec","sqc","sc"]) +# parser.add_argument('--srl-modell', type=str, default="",help='') + # returns the parsed arguments, and the rest are assumed to be arguments for rl_baselines.train + args, train_args = parser.parse_known_args() + + print("--------------") + print("The tasks that will be exacuted: {}".format(args.tasks)) + print('****************') + + + + # Sanity check + assert args.num_timesteps >= 1, "Error: --num-timesteps cannot be less than 1" + assert args.num_iteration >= 1, "Error: --num-iteration cannot be less than 1" + + # Removing duplicates and sort + srl_models = list(set(args.srl_model)) + envs = list(set(args.env)) + tasks=list(set(args.tasks)) + tasks.sort() + srl_models.sort() + envs.sort() + tasks=['-'+t for t in tasks] + + # LOAD SRL models list + assert os.path.exists(args.srl_config_file), \ + "Error: cannot load \"--srl-config-file {}\", file not found!".format(args.srl_config_file) + with open(args.srl_config_file, 'rb') as f: + all_models = yaml.load(f) + +# print(all_models) + + + + # Checking definition and presence of all requested srl_models + valid = True + for env in envs: + # validated the env definition + if env not in all_models: + printRed("Error: 'srl_models.yaml' missing definition for environment {}".format(env)) + valid = False + continue # skip to the next env, this one is not valid + + # checking log_folder for current env + missing_log = "log_folder" not in all_models[env] + if missing_log: + printRed("Error: 'srl_models.yaml' missing definition for log_folder in environment {}".format(env)) + valid = False + + # validate each model for the current env definition + for model in srl_models: + if registered_srl[model][0] == SRLType.ENVIRONMENT: + continue # not an srl model, skip to the next model + elif model not in all_models[env]: + printRed("Error: 'srl_models.yaml' missing srl_model {} for environment {}".format(model, env)) + valid = False + elif (not missing_log) and (not os.path.exists(all_models[env]["log_folder"] + all_models[env][model])): + # checking presence of srl_model path, if and only if log_folder exists + printRed("Error: srl_model {} for environment {} was defined in ".format(model, env) + + "'srl_models.yaml', however the file {} it was tagetting does not exist.".format( + all_models[env]["log_folder"] + all_models[env][model])) + valid = False + + assert valid, "Errors occured due to malformed 'srl_models.yaml', cannot continue." + + # check that all the SRL_models can be run on all the environments + valid = True + for env in envs: + for model in srl_models: + if registered_srl[model][1] is not None: + found = False + for compatible_class in registered_srl[model][1]: + if issubclass(compatible_class, registered_env[env][0]): + found = True + break + if not found: + valid = False + printRed("Error: srl_model {}, is not compatible with the {} environment.".format(model, env)) + assert valid, "Errors occured due to an incompatible combination of srl_model and environment, cannot continue." + + # the seeds used in training the baseline. + seeds = list(np.arange(args.num_iteration) + args.seed) + + if args.verbose: + # None here means stdout of terminal for subprocess.call + stdout = None + else: + stdout = open(os.devnull, 'w') + + printGreen("\nRunning {} benchmarks {} times...".format(args.algo, args.num_iteration)) + print("\nSRL-Models:\t{}".format(srl_models)) + print("environments:\t{}".format(envs)) + print("verbose:\t{}".format(args.verbose)) + print("timesteps:\t{}".format(args.num_timesteps)) + + + + for model in srl_models: + for env in envs: + for task in tasks: + for i in range(args.num_iteration): + + printGreen( + "\nIteration_num={} (seed: {}), Environment='{}', SRL-Model='{}' , Task='{}'".format(i, seeds[i], env, model, task)) + + # redefine the parsed args for rl_baselines.train + loop_args = ['--srl-model', model, '--seed', str(seeds[i]), + '--algo', args.algo, '--env', env, + '--num-timesteps', str(int(args.num_timesteps)), + '--srl-config-file', args.srl_config_file, task] + ok = subprocess.call(['python', '-m', 'rl_baselines.train'] + train_args + loop_args, stdout=stdout) + + if ok != 0: + # throw the error down to the terminal + raise ChildProcessError("An error occured, error code: {}".format(ok)) + + +if __name__ == '__main__': + main() From ca5df7780a2b671222ff62d080d70c59af372586 Mon Sep 17 00:00:00 2001 From: sun-te Date: Mon, 15 Apr 2019 14:11:06 +0200 Subject: [PATCH 020/141] read-me update --- README.md | 12 ++++++++++++ environment.yml | 3 +-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 48fcc90be..1760bb1da 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,13 @@ python -m rl_baselines.train --algo rl_algo --env env1 --log-dir logs/ --srl-mod To use the robot's position as input instead of pixels, just pass `--srl-model ground_truth` instead of `--srl-model raw_pixels` +To perform a cross evaluation for the different srl model, one could run in the terminal: + +``` +python -m rl_baselines.pipeline_cross --algo ppo2 --log-dir logs/ --srl-model srl_comnbination ground_truth --num-iteration 5 --num-timesteps 1000000 --task cc sqc sc +``` +This will output the learning result into the repository logs. + ## Installation @@ -191,6 +198,11 @@ If you have troubles installing mpi4py, make sure you the following installed: sudo apt-get install libopenmpi-dev openmpi-bin openmpi-doc ``` +If you have troubles building wheel for ```atari```, you could fix that by running: +``` +sudo apt-get install cmake libz-dev +``` + ## Known issues The inverse kinematics function has trouble finding a solution when the arm is fully straight and the arm must bend to reach the requested point. diff --git a/environment.yml b/environment.yml index 125fbfc3d..7f06f8ec5 100644 --- a/environment.yml +++ b/environment.yml @@ -1,4 +1,4 @@ -name: py35 +name: robot channels: - menpo - pytorch @@ -9,7 +9,6 @@ dependencies: - html5lib=0.9999999=py35_0 - markdown=2.6.9=py35_0 - protobuf=3.4.1=py35he6b9134_0 - - tensorflow-gpu=1.8.0 - werkzeug=0.14.1=py35_0 - bzip2=1.0.6=h6d464ef_2 - ca-certificates=2017.08.26=h1d4fec5_0 From a6dbfe861b92db0ed566752b3cb4468066b058af Mon Sep 17 00:00:00 2001 From: kalifou Date: Mon, 15 Apr 2019 15:17:32 +0200 Subject: [PATCH 021/141] small fix (init OmniRobotManagerBase) --- real_robots/omnirobot_utils/omnirobot_manager_base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/real_robots/omnirobot_utils/omnirobot_manager_base.py b/real_robots/omnirobot_utils/omnirobot_manager_base.py index a2646c307..8ce30a9a8 100644 --- a/real_robots/omnirobot_utils/omnirobot_manager_base.py +++ b/real_robots/omnirobot_utils/omnirobot_manager_base.py @@ -5,14 +5,14 @@ class OmnirobotManagerBase(object): def __init__(self, simple_continual_target=False, circular_continual_move=False, square_continual_move=False, - eight_continual_move=False, lambda_c=10.0): + eight_continual_move=False, lambda_c=10.0, second_cam_topic=None): """ This class is the basic class for omnirobot server, and omnirobot simulator's server. This class takes omnirobot position at instant t, and takes the action at instant t, to determinate the position it should go at instant t+1, and the immediate reward it can get at instant t """ super(OmnirobotManagerBase, self).__init__() - self.second_cam_topic = SECOND_CAM_TOPIC + self.second_cam_topic = second_cam_topic self.episode_idx = 0 self.simple_continual_target = simple_continual_target self.circular_continual_move = circular_continual_move From bc224b8d15db01f67c7284762799b03b8c8fecbe Mon Sep 17 00:00:00 2001 From: kalifou Date: Mon, 15 Apr 2019 16:43:20 +0200 Subject: [PATCH 022/141] cleaning pkgs imports --- .../supervised_rl/policy_distillation.py | 24 +++++-------------- 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/rl_baselines/supervised_rl/policy_distillation.py b/rl_baselines/supervised_rl/policy_distillation.py index a539a811d..78d358ab3 100644 --- a/rl_baselines/supervised_rl/policy_distillation.py +++ b/rl_baselines/supervised_rl/policy_distillation.py @@ -1,29 +1,18 @@ -import time -import pickle - import numpy as np -from stable_baselines.common.vec_env.subproc_vec_env import SubprocVecEnv -from stable_baselines.common.vec_env.vec_frame_stack import VecFrameStack -from stable_baselines.common.vec_env.vec_normalize import VecNormalize +import pickle +from torch import nn +from torch.nn import functional as F +from sklearn.model_selection import train_test_split from rl_baselines.base_classes import BaseRLObject -from environments import ThreadingType -from environments.registry import registered_env -from environments.utils import makeEnv from rl_baselines.utils import loadRunningAverage, MultiprocessSRLModel, softmax -from srl_zoo.utils import printYellow - - -############ DEV ################ -from tqdm import tqdm -from torch import nn -from torch.nn import functional as F from srl_zoo.preprocessing.data_loader import SupervisedDataLoader from srl_zoo.utils import loadData -from sklearn.model_selection import train_test_split + BATCH_SIZE = 32 TEST_BATCH_SIZE = 256 + class MLP(nn.Module): def __init__(self, output_size, input_size, hidden_size=400): super(MLP, self).__init__() @@ -186,4 +175,3 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): self.optimizer.step() train_loss += loss.item() epoch_train_loss[epoch].append(loss.item()) - From bcb12db05939ebf3a3a28f32daf556ae5eb3c825 Mon Sep 17 00:00:00 2001 From: kalifou Date: Mon, 15 Apr 2019 18:31:40 +0200 Subject: [PATCH 023/141] clean up & loading srl model in distillation script --- rl_baselines/registry.py | 2 +- .../supervised_rl/policy_distillation.py | 58 +++++++++---------- rl_baselines/train.py | 4 +- 3 files changed, 33 insertions(+), 31 deletions(-) diff --git a/rl_baselines/registry.py b/rl_baselines/registry.py index 6f92a3cc4..94534fddf 100644 --- a/rl_baselines/registry.py +++ b/rl_baselines/registry.py @@ -28,7 +28,7 @@ "random_agent": (RandomAgentModel, AlgoType.OTHER, [ActionType.DISCRETE, ActionType.CONTINUOUS]), "sac": (SACModel, AlgoType.REINFORCEMENT_LEARNING, [ActionType.CONTINUOUS]), "trpo": (TRPOModel, AlgoType.REINFORCEMENT_LEARNING, [ActionType.DISCRETE, ActionType.CONTINUOUS]), - "distillation": (PolicyDistillationModel, AlgoType.REINFORCEMENT_LEARNING, [ActionType.DISCRETE, ActionType.CONTINUOUS]) + "distillation": (PolicyDistillationModel, AlgoType.REINFORCEMENT_LEARNING, [ActionType.DISCRETE]) } # Checking validity of the registered RL algorithms diff --git a/rl_baselines/supervised_rl/policy_distillation.py b/rl_baselines/supervised_rl/policy_distillation.py index 78d358ab3..37fac3608 100644 --- a/rl_baselines/supervised_rl/policy_distillation.py +++ b/rl_baselines/supervised_rl/policy_distillation.py @@ -1,13 +1,16 @@ import numpy as np import pickle +import tqdm from torch import nn from torch.nn import functional as F from sklearn.model_selection import train_test_split +from environments.registry import registered_env from rl_baselines.base_classes import BaseRLObject from rl_baselines.utils import loadRunningAverage, MultiprocessSRLModel, softmax from srl_zoo.preprocessing.data_loader import SupervisedDataLoader from srl_zoo.utils import loadData +from state_representation.registry import registered_srl, SRLType BATCH_SIZE = 32 TEST_BATCH_SIZE = 256 @@ -43,8 +46,6 @@ class PolicyDistillationModel(BaseRLObject): """ def __init__(self): super(PolicyDistillationModel, self).__init__() - # pytorch model to distillate the policy - #self.model = MLP(input_size=1, hidden_size=400, output_size=1) def save(self, save_path, _locals=None): assert self.M is not None, "Error: must train or load model before use" @@ -91,56 +92,42 @@ def getAction(self, observation, dones=None, delta=0): return np.argmax(self.model.forward(observation)) def loss_fn_kd(self, outputs, labels, teacher_outputs): - """ - - :param outputs: output from the student model - :param labels: label - :param teacher_outputs: output from the teacher_outputs model - :return: loss - """ - - """ inspired from : https://github.com/peterliht/knowledge-distillation-pytorch Compute the knowledge-distillation (KD) loss given outputs, labels. "Hyperparameters": temperature and alpha NOTE: the KL Divergence for PyTorch comparing the softmaxs of teacher and student expects the input tensor to be log probabilities! See Issue #2 - """ - alpha = 0.9 - T = 0.01 # temperature empirically found in "policy distillation" - KD_loss = nn.KLDivLoss()(F.log_softmax(outputs / T, dim=1), - F.softmax(teacher_outputs / T, dim=1)) # formula from https://github.com/peterliht/knowledge-distillation-pytorch # KD_loss = nn.KLDivLoss()(F.log_softmax(outputs / T, dim=1), # F.softmax(teacher_outputs / T, dim=1)) * (alpha * T * T) + \ # F.cross_entropy(outputs, labels) * (1. - alpha) + :param outputs: output from the student model + :param labels: label + :param teacher_outputs: output from the teacher_outputs model + :return: loss + """ + alpha = 0.9 + T = 0.01 # temperature empirically found in "policy distillation" + KD_loss = nn.KLDivLoss()(F.log_softmax(outputs / T, dim=1), + F.softmax(teacher_outputs / T, dim=1)) return KD_loss - def train(self, args, callback, env_kwargs=None, train_kwargs=None): - #env = self.makeEnv(args, env_kwargs) N_EPOCHS = args.epochs_distillation - print("mopdel state dim: ", self.model.output_size) - self.model = MLP(input_size=env_kwargs["state_dim"], hidden_size=400, - output_size=env_kwargs["N_DISCRETE_ACTIONS"]) - - #criterion = nn.MSELoss() - criterion = self.loss_fn_kd() - + self.seed = args.seed print("We assumed SRL training already done") print('Loading data for distillation ') - training_data, ground_truth, true_states, _ = loadData(args.teacher_data_folder) + training_data, ground_truth, true_states, _ = loadData(args.teacher_data_folder, complete=True) rewards, episode_starts = training_data['rewards'], training_data['episode_starts'] images_path = ground_truth['images_path'] actions = training_data['actions'] - - limit = args.training_set_size + limit = args.distillation_training_set_size actions = actions[:limit] true_states = true_states.astype(np.float32) @@ -158,11 +145,24 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): epoch_train_loss = [[] for _ in range(N_EPOCHS)] epoch_val_loss = [[] for _ in range(N_EPOCHS)] + action_set = set(actions) + n_actions = int(np.max(actions) + 1) + # assert env_kwargs is not None and registered_srl[args.srl_model][0] == SRLType.SRL, \ + # "Please specify a valid srl model for training your policy !" + + self.srl_model = MultiprocessSRLModel(1, args.env, env_kwargs) + env_kwargs["state_dim"] = self.srl_model.state_dim + env_kwargs["srl_pipe"] = self.srl_model.pipe + self.policy = MLP(input_size=env_kwargs["state_dim"], hidden_size=400, + output_size=n_actions) + + + for epoch in range(N_EPOCHS): # In each epoch, we do a full pass over the training data: train_loss, val_loss = 0, 0 pbar = tqdm(total=len(train_loader)) - self.model.train() # Restore train mode + self.srl_model.eval() # Restore train mode print("The train_loader should contains observation and target_action ") for obs, target_action in train_loader: diff --git a/rl_baselines/train.py b/rl_baselines/train.py index 0250f4edb..01f12f955 100644 --- a/rl_baselines/train.py +++ b/rl_baselines/train.py @@ -229,7 +229,9 @@ def main(): help='Dataset folder of the teacher(s) policy(ies)', required=True) parser.add_argument('--epochs-distillation', type=int, default=30, metavar='N', help='number of epochs to train for distillation(default: 30)') - + parser.add_argument('--distillation-training-set-size', type=int, default=-1, + help='Limit size (number of samples) of the training set (default: -1)') + # Ignore unknown args for now args, unknown = parser.parse_known_args() env_kwargs = {} From c2d0405898c464a7e137451b71cbed0fbc1efbd5 Mon Sep 17 00:00:00 2001 From: sun-te Date: Tue, 16 Apr 2019 09:23:15 +0200 Subject: [PATCH 024/141] plot results --- replay/aggregate_plots.py | 1 + replay/pipeline.py | 235 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 236 insertions(+) create mode 100644 replay/pipeline.py diff --git a/replay/aggregate_plots.py b/replay/aggregate_plots.py index 0fe7d5f8a..cd8197f08 100644 --- a/replay/aggregate_plots.py +++ b/replay/aggregate_plots.py @@ -206,3 +206,4 @@ def plotGatheredExperiments(folders, algo, y_limits, window=40, title="", min_nu plotGatheredExperiments(folders, train_args['algo'], y_limits=y_limits, window=args.episode_window, title=title, min_num_x=args.min_x, no_display=args.no_display, timesteps=args.timesteps, output_file=args.output_file) +#python -m replay.aggregate_plots --log-dir logs/OmnirobotEnv-v0/srl_combination/ppo2/ --timesteps --min-x 1000 -o logs/plot/ \ No newline at end of file diff --git a/replay/pipeline.py b/replay/pipeline.py new file mode 100644 index 000000000..87af908cc --- /dev/null +++ b/replay/pipeline.py @@ -0,0 +1,235 @@ +import argparse +import os + +import matplotlib.pyplot as plt +import numpy as np +import seaborn as sns +from matplotlib.ticker import FuncFormatter +import json + +from rl_baselines.visualize import movingAverage, loadCsv,loadData +from replay.aggregate_plots import lightcolors, darkcolors, Y_LIM_SHAPED_REWARD, Y_LIM_SPARSE_REWARD, millions +from srl_zoo.utils import printGreen, printRed, printYellow + +# Init seaborn +sns.set() +# Style for the title +fontstyle = {'fontname': 'DejaVu Sans', 'fontsize': 16} + + + + +def loadEpisodesData(folder): + """ + :param folder: (str) + :return: (numpy array, numpy array) or (None, None) + """ + result, _ = loadCsv(folder) + + if len(result) == 0: + return None, None + + y = np.array(result)[:, 1] + x = np.arange(len(y)) + return x, y + + +def plotGatheredData(x_list,y_list,y_limits, timesteps,title,legends,no_display,truncate_x=-1,normalization=False): + assert len(legends)==len(y_list) + printGreen("{} Experiments".format(len(y_list))) + #print("Min, Max rewards:", np.min(y_list), np.max(y_list)) + + lengths = list(map(len, x_list)) + min_x, max_x = np.min(lengths), np.max(lengths) + + + if truncate_x > 0: + min_x = min(truncate_x, min_x) + x = np.array(x_list[0][:min_x]) + + print(lengths,x.shape) + fig = plt.figure(title) + for i in range(len(y_list)): + label = legends[i] + y = y_list[i][:, :min_x] + + print('{}: {} experiments'.format(label, len(y))) + # Compute mean for different seeds + m = np.mean(y, axis=0) + # Compute standard error + s = np.squeeze(np.asarray(np.std(y, axis=0))) + n = y.shape[0] + plt.fill_between(x, m - s / np.sqrt(n), m + s / np.sqrt(n), color=lightcolors[i % len(lightcolors)], alpha=0.5) + plt.plot(x, m, color=darkcolors[i % len(darkcolors)], label=label, linewidth=2) + + if timesteps: + formatter = FuncFormatter(millions) + plt.xlabel('Number of Timesteps') + fig.axes[0].xaxis.set_major_formatter(formatter) + else: + plt.xlabel('Number of Episodes') + plt.ylabel('Rewards') + + plt.title(title, **fontstyle) + plt.ylim(y_limits) + + plt.legend(framealpha=0.8, frameon=True, labelspacing=0.01, loc='lower right', fontsize=16) + + if not no_display: + plt.show() + + + + +def GatherExperiments(folders, algo, window=40, title="", min_num_x=-1, + timesteps=False, output_file="",): + """ + Compute mean and standard error for several experiments and plot the learning curve + :param folders: ([str]) Log folders, where the monitor.csv are stored + :param window: (int) Smoothing window + :param algo: (str) name of the RL algo + :param title: (str) plot title + :param min_num_x: (int) Minimum number of episode/timesteps to keep an experiment (default: -1, no minimum) + :param timesteps: (bool) Plot timesteps instead of episodes + :param y_limits: ([float]) y-limits for the plot + :param output_file: (str) Path to a file where the plot data will be saved + :param no_display: (bool) Set to true, the plot won't be displayed (useful when only saving plot) + """ + y_list = [] + x_list = [] + ok = False + for folder in folders: + if timesteps: + x, y = loadData(folder, smooth=1, bin_size=100) + if x is not None: + x, y = np.array(x), np.array(y) + else: + x, y = loadEpisodesData(folder) + + if x is None or (min_num_x > 0 and y.shape[0] < min_num_x): + printYellow("Skipping {}".format(folder)) + continue + + if y.shape[0] <= window: + printYellow("Folder {}".format(folder)) + printYellow("Not enough episodes for current window size = {}".format(window)) + continue + ok = True + y = movingAverage(y, window) + y_list.append(y) + + # Truncate x + x = x[len(x) - len(y):] + x_list.append(x) + + if not ok: + printRed("Not enough data to plot anything with current config." + + " Consider decreasing --min-x") + return + + lengths = list(map(len, x_list)) + min_x, max_x = np.min(lengths), np.max(lengths) + + print("Min x: {}".format(min_x)) + print("Max x: {}".format(max_x)) + + for i in range(len(x_list)): + x_list[i] = x_list[i][:min_x] + y_list[i] = y_list[i][:min_x] + + x = np.array(x_list)[0] + y = np.array(y_list) + # if output_file != "": + # printGreen("Saving aggregated data to {}.npz".format(output_file)) + # np.savez(output_file, x=x, y=y) + return x,y + + +def comparePlots(path, algo,y_limits,title="Learning Curve", + timesteps=False, truncate_x=-1, no_display=False,normalization=False): + """ + :param path: (str) path to the folder where the plots are stored + :param plots: ([str]) List of saved plots as npz file + :param y_limits: ([float]) y-limits for the plot + :param title: (str) plot title + :param timesteps: (bool) Plot timesteps instead of episodes + :param truncate_x: (int) Truncate the experiments after n ticks on the x-axis + :param no_display: (bool) Set to true, the plot won't be displayed (useful when only saving plot) + """ + + folders = [] + other = [] + legends=[] + for folder in os.listdir(path): + folders_srl=[] + other_srl=[] + tmp_path = "{}/{}/{}/".format(path, folder, algo) + legends.append(folder) + for f in os.listdir(tmp_path): + paths = "{}/{}/{}/{}/".format(path, folder, algo,f) + env_globals = json.load(open(paths + "env_globals.json", 'r')) + train_args = json.load(open(paths + "args.json", 'r')) + if train_args["shape_reward"] == args.shape_reward: + folders_srl.append(paths) + else: + other_srl.append(paths) + folders.append(folders_srl) + other.append(other_srl) + + + x_list,y_list=[],[] + for folders_srl in folders: + x,y=GatherExperiments(folders_srl, algo, window=40, title=title, min_num_x=-1, + timesteps=timesteps, output_file="") + x_list.append(x) + y_list.append(y) + + plotGatheredData(x_list,y_list,y_limits,timesteps,title,legends,no_display,truncate_x,normalization) + + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description="Plot trained agent") + parser.add_argument('-i', '--input-dir', help='folder with the plots as npz files', type=str, required=True) + parser.add_argument('-t', '--title', help='Plot title', type=str, default='Learning Curve') + parser.add_argument('--episode_window', type=int, default=40, + help='Episode window for moving average plot (default: 40)') + parser.add_argument('--shape-reward', action='store_true', default=False, + help='Change the y_limit to correspond shaped reward bounds') + parser.add_argument('--y-lim', nargs=2, type=float, default=[-1, -1], help="limits for the y axis") + parser.add_argument('--truncate-x', type=int, default=-1, + help="Truncate the experiments after n ticks on the x-axis (default: -1, no truncation)") + parser.add_argument('--timesteps', action='store_true', default=False, + help='Plot timesteps instead of episodes') + parser.add_argument('--no-display', action='store_true', default=False, help='Do not display plot') + parser.add_argument('--algo',type=str,default='ppo2',help='The RL algorithms result to show') + parser.add_argument('--norm', action='store_true', default=False, help='To normalize the output by the maximum reward') + # + # parser.add_argument('--tasks', type=str, nargs='+', default=["cc"], + # help='The tasks for the robot', + # choices=["cc", "ec", "sqc", "sc"]) + + + + args = parser.parse_args() + + y_limits = args.y_lim + if y_limits[0] == y_limits[1]: + if args.shape_reward: + y_limits = Y_LIM_SHAPED_REWARD + else: + y_limits = Y_LIM_SPARSE_REWARD + print("Using default limits:", y_limits) + + + ALGO_NAME=args.algo + + + x_list=[] + y_list=[] + + comparePlots(args.input_dir, args.algo, title=args.title, y_limits=y_limits, no_display=args.no_display, + timesteps=args.timesteps, truncate_x=args.truncate_x,normalization=args.norm) + + +#python -m replay.pipeline -i logs/OmnirobotEnv-v0/ --algo ppo2 --title cc \ No newline at end of file From 89aa1844d1214798fd2dfbfcea47358e62a9b3dc Mon Sep 17 00:00:00 2001 From: sun-te Date: Tue, 16 Apr 2019 14:56:07 +0200 Subject: [PATCH 025/141] cross evaluation and comparison plot --- replay/pipeline.py | 25 +++++-- rl_baselines/pipeline_cross.py | 117 ++++++++++++++++++++------------- 2 files changed, 90 insertions(+), 52 deletions(-) diff --git a/replay/pipeline.py b/replay/pipeline.py index 87af908cc..dd842ae67 100644 --- a/replay/pipeline.py +++ b/replay/pipeline.py @@ -37,17 +37,26 @@ def loadEpisodesData(folder): def plotGatheredData(x_list,y_list,y_limits, timesteps,title,legends,no_display,truncate_x=-1,normalization=False): assert len(legends)==len(y_list) printGreen("{} Experiments".format(len(y_list))) - #print("Min, Max rewards:", np.min(y_list), np.max(y_list)) lengths = list(map(len, x_list)) min_x, max_x = np.min(lengths), np.max(lengths) - - if truncate_x > 0: min_x = min(truncate_x, min_x) x = np.array(x_list[0][:min_x]) - print(lengths,x.shape) + #To reformulize the data by the min_x + for i in range(len(y_list)): + y_list[i]=y_list[i][:, :min_x] + y_list=np.array(y_list) + + print("Min, Max rewards:", np.min(y_list), np.max(y_list)) + + + #Normalize the data between 0 and 1. + if (normalization): + y_limits = [-0.05, 1.05] + y_list =(y_list-np.min(y_list))/(np.max(y_list)-np.min(y_list)) + fig = plt.figure(title) for i in range(len(y_list)): label = legends[i] @@ -68,8 +77,10 @@ def plotGatheredData(x_list,y_list,y_limits, timesteps,title,legends,no_display, fig.axes[0].xaxis.set_major_formatter(formatter) else: plt.xlabel('Number of Episodes') - plt.ylabel('Rewards') - + if(normalization): + plt.ylabel('Normalized Rewards') + else: + plt.ylabel('Rewards') plt.title(title, **fontstyle) plt.ylim(y_limits) @@ -232,4 +243,4 @@ def comparePlots(path, algo,y_limits,title="Learning Curve", timesteps=args.timesteps, truncate_x=args.truncate_x,normalization=args.norm) -#python -m replay.pipeline -i logs/OmnirobotEnv-v0/ --algo ppo2 --title cc \ No newline at end of file +#python -m replay.pipeline -i logs_to_plot_with_200Combination/OmnirobotEnv-v0-cc --algo ppo2 --title cc --timesteps \ No newline at end of file diff --git a/rl_baselines/pipeline_cross.py b/rl_baselines/pipeline_cross.py index 97feaa2dd..ea7b2d99a 100644 --- a/rl_baselines/pipeline_cross.py +++ b/rl_baselines/pipeline_cross.py @@ -12,11 +12,22 @@ from environments.registry import registered_env from state_representation.registry import registered_srl from state_representation import SRLType -from srl_zoo.utils import printGreen, printRed +from srl_zoo.utils import printGreen, printRed, printYellow os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' # used to remove debug info of tensorflow +''' +example: +------------------------------------------------------------------------------ +python -m rl_baselines.pipeline_cross --algo ppo2 --log-dir logs/ +--srl-model srl_combination ground_truth --num-iteration 1 --num-timesteps 100000 +--task sc cc +--srl-config-file config/srl_models.yaml config/srl_models_test.yaml +------------------------------------------------------------------------------ +--srl-config-file : a list of config_file which should have the same number as tasks. (or only one, it will take this one for all tasks by default) +''' + def main(): parser = argparse.ArgumentParser(description="OpenAI RL Baselines Benchmark", epilog='After the arguments are parsed, the rest are assumed to be arguments for' + @@ -24,8 +35,8 @@ def main(): parser.add_argument('--algo', type=str, default='ppo2', help='OpenAI baseline to use', choices=list(registered_rl.keys())) parser.add_argument('--env', type=str, nargs='+', default=["OmnirobotEnv-v0"], help='environment ID(s)', - choices=list(registered_env.keys())) - parser.add_argument('--srl-model', type=str, nargs='+', default=["raw_pixels"], + choices=["OmnirobotEnv-v0"])#list(registered_env.keys())) + parser.add_argument('--srl-model', type=str, nargs='+', default=["ground_truth"], help='SRL model(s) to use', choices=list(registered_srl.keys())) parser.add_argument('--num-timesteps', type=int, default=1e6, help='number of timesteps the baseline should run') @@ -35,7 +46,7 @@ def main(): ' and srl-model.') parser.add_argument('--seed', type=int, default=0, help='initial seed for each unique combination of environment and srl-model.') - parser.add_argument('--srl-config-file', type=str, default="config/srl_models.yaml", + parser.add_argument('--srl-config-file', nargs='+', type=str, default=["config/srl_models.yaml"], help='Set the location of the SRL model path configuration.') parser.add_argument('--tasks', type=str, nargs='+', default=["cc"], @@ -45,9 +56,7 @@ def main(): # returns the parsed arguments, and the rest are assumed to be arguments for rl_baselines.train args, train_args = parser.parse_known_args() - print("--------------") - print("The tasks that will be exacuted: {}".format(args.tasks)) - print('****************') + @@ -63,47 +72,58 @@ def main(): srl_models.sort() envs.sort() tasks=['-'+t for t in tasks] - + config_files=args.srl_config_file + # LOAD SRL models list - assert os.path.exists(args.srl_config_file), \ - "Error: cannot load \"--srl-config-file {}\", file not found!".format(args.srl_config_file) - with open(args.srl_config_file, 'rb') as f: - all_models = yaml.load(f) - -# print(all_models) + if len(config_files)==1: + printYellow("Your are using the same config file: {} for all training tasks".format(config_files[0])) - # Checking definition and presence of all requested srl_models - valid = True - for env in envs: - # validated the env definition - if env not in all_models: - printRed("Error: 'srl_models.yaml' missing definition for environment {}".format(env)) - valid = False - continue # skip to the next env, this one is not valid - - # checking log_folder for current env - missing_log = "log_folder" not in all_models[env] - if missing_log: - printRed("Error: 'srl_models.yaml' missing definition for log_folder in environment {}".format(env)) - valid = False - - # validate each model for the current env definition - for model in srl_models: - if registered_srl[model][0] == SRLType.ENVIRONMENT: - continue # not an srl model, skip to the next model - elif model not in all_models[env]: - printRed("Error: 'srl_models.yaml' missing srl_model {} for environment {}".format(model, env)) + config_files = [config_files[0] for i in range(len(tasks))] + else: + assert len(config_files)==len(tasks), \ + "Error: {} config files given for {} tasks".format(len(config_files),len(tasks)) + + for file in config_files: + assert os.path.exists(file), \ + "Error: cannot load \"--srl-config-file {}\", file not found!".format(file) + + for file in config_files: + with open(file, 'rb') as f: + all_models = yaml.load(f) + # Checking definition and presence of all requested srl_models + valid = True + for env in envs: + # validated the env definition + if env not in all_models: + printRed("Error: 'srl_models.yaml' missing definition for environment {}".format(env)) valid = False - elif (not missing_log) and (not os.path.exists(all_models[env]["log_folder"] + all_models[env][model])): - # checking presence of srl_model path, if and only if log_folder exists - printRed("Error: srl_model {} for environment {} was defined in ".format(model, env) + - "'srl_models.yaml', however the file {} it was tagetting does not exist.".format( - all_models[env]["log_folder"] + all_models[env][model])) + continue # skip to the next env, this one is not valid + + # checking log_folder for current env + missing_log = "log_folder" not in all_models[env] + if missing_log: + printRed("Error: '{}' missing definition for log_folder in environment {}".format(file, env)) valid = False - assert valid, "Errors occured due to malformed 'srl_models.yaml', cannot continue." + # validate each model for the current env definition + for model in srl_models: + if registered_srl[model][0] == SRLType.ENVIRONMENT: + continue # not an srl model, skip to the next model + elif model not in all_models[env]: + printRed("Error: '{}' missing srl_model {} for environment {}".format(file, model, env)) + valid = False + elif (not missing_log) and (not os.path.exists(all_models[env]["log_folder"] + all_models[env][model])): + # checking presence of srl_model path, if and only if log_folder exists + printRed("Error: srl_model {} for environment {} was defined in ".format(model, env) + + "'{}', however the file {} it was tagetting does not exist.".format( + file, all_models[env]["log_folder"] + all_models[env][model])) + valid = False + + assert valid, "Errors occurred due to malformed {}, cannot continue.".format(file) + + # check that all the SRL_models can be run on all the environments valid = True @@ -134,22 +154,29 @@ def main(): print("environments:\t{}".format(envs)) print("verbose:\t{}".format(args.verbose)) print("timesteps:\t{}".format(args.num_timesteps)) - + + num_tasks=len(tasks) + + + printGreen("The tasks that will be exacuted: {}".format(args.tasks)) + printGreen("with following config files: {}".format(config_files)) for model in srl_models: + for env in envs: - for task in tasks: + for iter_task in range(num_tasks): + for i in range(args.num_iteration): printGreen( - "\nIteration_num={} (seed: {}), Environment='{}', SRL-Model='{}' , Task='{}'".format(i, seeds[i], env, model, task)) + "\nIteration_num={} (seed: {}), Environment='{}', SRL-Model='{}' , Task='{}', Config_file='{}'".format(i, seeds[i], env, model, tasks[iter_task]),config_files[iter_task]) # redefine the parsed args for rl_baselines.train loop_args = ['--srl-model', model, '--seed', str(seeds[i]), '--algo', args.algo, '--env', env, '--num-timesteps', str(int(args.num_timesteps)), - '--srl-config-file', args.srl_config_file, task] + '--srl-config-file', config_files[iter_task], tasks[iter_task]] ok = subprocess.call(['python', '-m', 'rl_baselines.train'] + train_args + loop_args, stdout=stdout) if ok != 0: From 7e07c299581f6543a1541bb49bebe043113ba0fb Mon Sep 17 00:00:00 2001 From: kalifou Date: Tue, 16 Apr 2019 18:29:21 +0200 Subject: [PATCH 026/141] On-policy generation: Fix to save action proba --- environments/dataset_generator.py | 4 +++- environments/omnirobot_gym/omnirobot_env.py | 4 ++-- environments/srl_env.py | 2 +- state_representation/episode_saver.py | 9 ++++++++- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/environments/dataset_generator.py b/environments/dataset_generator.py index c919c1c83..5d6c03ba9 100644 --- a/environments/dataset_generator.py +++ b/environments/dataset_generator.py @@ -156,6 +156,7 @@ def env_thread(args, thread_num, partition=True): action, _ = model.predict([obs]) elif args.run_policy == 'custom': action = [model.getAction(obs, done)] + action_proba = model.getActionProba(obs, done) else: if episode_toward_target_on and np.random.rand() < args.toward_target_timesteps_proportion: action = [env.actionPolicyTowardTarget()] @@ -171,7 +172,8 @@ def env_thread(args, thread_num, partition=True): generated_obs = deNormalize(generated_obs) action_to_step = action[0] - new_obs, _, done, _ = env.step(action_to_step, generated_observation=generated_obs) + new_obs, _, done, _ = env.step(action_to_step, generated_observation=generated_obs, + action_proba=action_proba) if args.run_policy == 'custom': obs = new_obs diff --git a/environments/omnirobot_gym/omnirobot_env.py b/environments/omnirobot_gym/omnirobot_env.py index e8ae871b8..9df8cf927 100644 --- a/environments/omnirobot_gym/omnirobot_env.py +++ b/environments/omnirobot_gym/omnirobot_env.py @@ -181,7 +181,7 @@ def actionPolicyTowardTarget(self): else: return DELTA_POS if self.robot_pos[1] < self.target_pos[1] else -DELTA_POS - def step(self, action, generated_observation=None): + def step(self, action, generated_observation=None, action_proba=None): """ :action: (int) :return: (tensor (np.ndarray)) observation, int reward, bool done, dict extras) @@ -217,7 +217,7 @@ def step(self, action, generated_observation=None): if self.saver is not None: self.saver.step(self.observation, action, - self.reward, done, self.getGroundTruth()) + self.reward, done, self.getGroundTruth(), action_proba=action_proba) if self.use_srl: return self.getSRLState(self.observation), self.reward, done, {} else: diff --git a/environments/srl_env.py b/environments/srl_env.py index 43ce13809..c7e8d6951 100644 --- a/environments/srl_env.py +++ b/environments/srl_env.py @@ -81,7 +81,7 @@ def close(self): # TODO: implement close function to close GUI pass - def step(self, action, generated_observation=None): + def step(self, action, generated_observation=None, action_proba=None): """ :param action: (int or [float]) """ diff --git a/state_representation/episode_saver.py b/state_representation/episode_saver.py index 842cd3582..87579306b 100644 --- a/state_representation/episode_saver.py +++ b/state_representation/episode_saver.py @@ -36,6 +36,7 @@ def __init__(self, name, max_dist, state_dim=-1, globals_=None, learn_every=3, l printYellow("Folder already exist") self.actions = [] + self.actions_proba = [] self.rewards = [] self.images = [] self.target_positions = [] @@ -111,10 +112,11 @@ def reset(self, observation, target_pos, ground_truth): self.ground_truth_states.append(ground_truth) self.saveImage(observation) - def step(self, observation, action, reward, done, ground_truth_state): + def step(self, observation, action, reward, done, ground_truth_state, action_proba=None): """ :param observation: (numpy matrix) BGR Image :param action: (int) + :param action_proba: (list float) probability of taking each action :param reward: (float) :param done: (bool) whether the episode is done or not :param ground_truth_state: (numpy array) @@ -124,6 +126,9 @@ def step(self, observation, action, reward, done, ground_truth_state): self.n_steps += 1 self.rewards.append(reward) self.actions.append(action) + if action_proba is not None: + self.actions_proba.append(action_proba) + if reward > 0: self.episode_success = True @@ -145,10 +150,12 @@ def save(self): assert len(self.actions) == len(self.images_path) assert len(self.actions) == len(self.ground_truth_states) assert len(self.target_positions) == self.episode_idx + 1 + assert len(self.actions_proba) == 0 or len(self.actions_proba) == len(self.actions) data = { 'rewards': np.array(self.rewards), 'actions': np.array(self.actions), + 'actions_proba': np.array(self.actions_proba), 'episode_starts': np.array(self.episode_starts) } From c05bf7d23082058f5bc70a3b08ad9b0be1e8cb7e Mon Sep 17 00:00:00 2001 From: kalifou Date: Tue, 16 Apr 2019 18:30:04 +0200 Subject: [PATCH 027/141] draft: Policy distillation --- .../supervised_rl/policy_distillation.py | 161 +++++++++++++----- 1 file changed, 114 insertions(+), 47 deletions(-) diff --git a/rl_baselines/supervised_rl/policy_distillation.py b/rl_baselines/supervised_rl/policy_distillation.py index 37fac3608..55f8354cb 100644 --- a/rl_baselines/supervised_rl/policy_distillation.py +++ b/rl_baselines/supervised_rl/policy_distillation.py @@ -1,20 +1,24 @@ import numpy as np import pickle -import tqdm +import torch as th + +from tqdm import tqdm from torch import nn from torch.nn import functional as F from sklearn.model_selection import train_test_split -from environments.registry import registered_env from rl_baselines.base_classes import BaseRLObject from rl_baselines.utils import loadRunningAverage, MultiprocessSRLModel, softmax -from srl_zoo.preprocessing.data_loader import SupervisedDataLoader +from srl_zoo.preprocessing.data_loader import SupervisedDataLoader, DataLoader from srl_zoo.utils import loadData +from state_representation.models import loadSRLModel, getSRLDim from state_representation.registry import registered_srl, SRLType +N_WORKERS = 4 BATCH_SIZE = 32 TEST_BATCH_SIZE = 256 - +VALIDATION_SIZE = 0.2 # 20% of training data for validation +MAX_BATCH_SIZE_GPU = 256 # For plotting, max batch_size before having memory issues class MLP(nn.Module): def __init__(self, output_size, input_size, hidden_size=400): @@ -91,7 +95,7 @@ def getAction(self, observation, dones=None, delta=0): self.model.eval() return np.argmax(self.model.forward(observation)) - def loss_fn_kd(self, outputs, labels, teacher_outputs): + def loss_fn_kd(self, outputs, teacher_outputs): """ inspired from : https://github.com/peterliht/knowledge-distillation-pytorch Compute the knowledge-distillation (KD) loss given outputs, labels. @@ -110,7 +114,7 @@ def loss_fn_kd(self, outputs, labels, teacher_outputs): """ alpha = 0.9 - T = 0.01 # temperature empirically found in "policy distillation" + T = 0.01 # temperature empirically found in "policy distillation" KD_loss = nn.KLDivLoss()(F.log_softmax(outputs / T, dim=1), F.softmax(teacher_outputs / T, dim=1)) return KD_loss @@ -119,59 +123,122 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): N_EPOCHS = args.epochs_distillation self.seed = args.seed - + self.batch_size = BATCH_SIZE print("We assumed SRL training already done") print('Loading data for distillation ') training_data, ground_truth, true_states, _ = loadData(args.teacher_data_folder, complete=True) rewards, episode_starts = training_data['rewards'], training_data['episode_starts'] images_path = ground_truth['images_path'] + images_path_copy = ["srl_zoo/data/" + images_path[k] for k in range(images_path.shape[0])] + images_path = np.array(images_path_copy) actions = training_data['actions'] + actions_proba = training_data['actions_proba'] limit = args.distillation_training_set_size actions = actions[:limit] - true_states = true_states.astype(np.float32) - x_indices = np.arange(len(true_states)).astype(np.int64) - - # Split into train/validation set - x_train, x_val, y_train, y_val = train_test_split(x_indices, true_states, - test_size=0.33, random_state=self.seed) - - train_loader = SupervisedDataLoader(x_train, y_train, images_path, batch_size=BATCH_SIZE, - max_queue_len=4, shuffle=True) - val_loader = SupervisedDataLoader(x_val, y_val, images_path, batch_size=TEST_BATCH_SIZE, - max_queue_len=1, shuffle=False) - - epoch_train_loss = [[] for _ in range(N_EPOCHS)] - epoch_val_loss = [[] for _ in range(N_EPOCHS)] - - action_set = set(actions) - n_actions = int(np.max(actions) + 1) - # assert env_kwargs is not None and registered_srl[args.srl_model][0] == SRLType.SRL, \ - # "Please specify a valid srl model for training your policy !" - - self.srl_model = MultiprocessSRLModel(1, args.env, env_kwargs) - env_kwargs["state_dim"] = self.srl_model.state_dim - env_kwargs["srl_pipe"] = self.srl_model.pipe - self.policy = MLP(input_size=env_kwargs["state_dim"], hidden_size=400, - output_size=n_actions) - - + num_samples = images_path.shape[0] - 1 # number of samples + + # indices for all time steps where the episode continues + indices = np.array([i for i in range(num_samples) if not episode_starts[i + 1]], dtype='int64') + np.random.shuffle(indices) + + # split indices into minibatches. minibatchlist is a list of lists; each + # list is the id of the observation preserved through the training + minibatchlist = [np.array(sorted(indices[start_idx:start_idx + self.batch_size])) + for start_idx in range(0, len(indices) - self.batch_size + 1, self.batch_size)] + data_loader = DataLoader(minibatchlist, images_path, n_workers=N_WORKERS, multi_view=False, + use_triplets=False, is_training=True, complete_path=True) + + test_minibatchlist = DataLoader.createTestMinibatchList(len(images_path), MAX_BATCH_SIZE_GPU) + test_data_loader = DataLoader(test_minibatchlist, images_path, n_workers=N_WORKERS, multi_view=False, + use_triplets=False, max_queue_len=1, is_training=False, complete_path=True) + + # Number of minibatches used for validation: + n_val_batches = np.round(VALIDATION_SIZE * len(minibatchlist)).astype(np.int64) + val_indices = np.random.permutation(len(minibatchlist))[:n_val_batches] + # Print some info + print("{} minibatches for training, {} samples".format(len(minibatchlist) - n_val_batches, + (len(minibatchlist) - n_val_batches) * BATCH_SIZE)) + print("{} minibatches for validation, {} samples".format(n_val_batches, n_val_batches * BATCH_SIZE)) + assert n_val_batches > 0, "Not enough sample to create a validation set" + + # Stats about actions + if not args.continuous_actions: + print('Discrete action space:') + action_set = set(actions) + n_actions = int(np.max(actions) + 1) + print("{} unique actions / {} actions".format(len(action_set), n_actions)) + n_pairs_per_action = np.zeros(n_actions, dtype=np.int64) + n_obs_per_action = np.zeros(n_actions, dtype=np.int64) + for i in range(n_actions): + n_obs_per_action[i] = np.sum(actions == i) + + print("Number of observations per action") + print(n_obs_per_action) + + else: + print('Continuous action space:') + print('Action dimension: {}'.format(self.dim_action)) + + assert env_kwargs is not None and registered_srl[args.srl_model][0] == SRLType.SRL, \ + "Please specify a valid srl model for training your policy !" + + self.state_dim = getSRLDim(env_kwargs.get("srl_model_path", None)) + self.srl_model = loadSRLModel(env_kwargs.get("srl_model_path", None), + th.cuda.is_available(), self.state_dim, env_object=None) + self.device = th.device("cuda" if th.cuda.is_available() else "cpu") + + self.policy = MLP(input_size=self.state_dim, hidden_size=400, output_size=n_actions) + if th.cuda.is_available(): + self.policy.cuda() + + learnable_params = [param for param in self.policy.parameters() if param.requires_grad] + self.optimizer = th.optim.Adam(learnable_params, lr=1e-3) for epoch in range(N_EPOCHS): # In each epoch, we do a full pass over the training data: - train_loss, val_loss = 0, 0 - pbar = tqdm(total=len(train_loader)) - self.srl_model.eval() # Restore train mode - - print("The train_loader should contains observation and target_action ") - for obs, target_action in train_loader: - obs, target_action = obs.to(self.device), target_action.to(self.device) - - pred_action = self.model(obs) + epoch_loss, epoch_batches = 0, 0 + val_loss = 0 + pbar = tqdm(total=len(minibatchlist)) + + for minibatch_num, (minibatch_idx, obs, _, _, _) in enumerate(data_loader): + + obs = obs.to(self.device) + validation_mode = minibatch_idx in val_indices + if validation_mode: + self.policy.eval() + else: + self.policy.train() + + # Actions associated to the observations of the current minibatch + actions_st = actions[minibatchlist[minibatch_idx]] + actions_proba_st = actions_proba[minibatchlist[minibatch_idx]] + + if not args.continuous_actions: + # Discrete actions, rearrange action to have n_minibatch ligns and one column, containing the int action + actions_st = th.from_numpy(actions_st).view(-1, 1).requires_grad_(False).to(self.device) + actions_proba_st = th.from_numpy(actions_proba_st).view(-1, 1).requires_grad_(False).to(self.device) + else: + # Continuous actions, rearrange action to have n_minibatch ligns and dim_action columns + actions_st = th.from_numpy(actions_st).view(-1, self.dim_action).requires_grad_(False).to( + self.device) + + state = self.srl_model.model.getStates(obs)[0].to(self.device).detach() + pred_action = self.policy(state) self.optimizer.zero_grad() - loss = criterion(pred_action, target_action.detach()) + loss = self.loss_fn_kd(pred_action, actions_proba_st) loss.backward() - self.optimizer.step() - train_loss += loss.item() - epoch_train_loss[epoch].append(loss.item()) + if validation_mode: + val_loss += loss.item() + # We do not optimize on validation data + # so optimizer.step() is not called + else: + self.optimizer.step() + epoch_loss += loss.item() + epoch_batches += 1 + pbar.update(1) + pbar.close() + + train_loss = epoch_loss / float(epoch_batches) + val_loss /= float(n_val_batches) From a6125711327bef764cb03cd8e7e4c2c063555621 Mon Sep 17 00:00:00 2001 From: kalifou Date: Tue, 16 Apr 2019 19:03:51 +0200 Subject: [PATCH 028/141] loss update --- .../supervised_rl/policy_distillation.py | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/rl_baselines/supervised_rl/policy_distillation.py b/rl_baselines/supervised_rl/policy_distillation.py index 55f8354cb..e97e21a6c 100644 --- a/rl_baselines/supervised_rl/policy_distillation.py +++ b/rl_baselines/supervised_rl/policy_distillation.py @@ -20,6 +20,7 @@ VALIDATION_SIZE = 0.2 # 20% of training data for validation MAX_BATCH_SIZE_GPU = 256 # For plotting, max batch_size before having memory issues + class MLP(nn.Module): def __init__(self, output_size, input_size, hidden_size=400): super(MLP, self).__init__() @@ -95,18 +96,14 @@ def getAction(self, observation, dones=None, delta=0): self.model.eval() return np.argmax(self.model.forward(observation)) - def loss_fn_kd(self, outputs, teacher_outputs): + def loss_fn_kd(self, outputs, labels, teacher_outputs): """ inspired from : https://github.com/peterliht/knowledge-distillation-pytorch Compute the knowledge-distillation (KD) loss given outputs, labels. - "Hyperparameters": temperature and alpha NOTE: the KL Divergence for PyTorch comparing the softmaxs of teacher and student expects the input tensor to be log probabilities! See Issue #2 - # formula from https://github.com/peterliht/knowledge-distillation-pytorch - # KD_loss = nn.KLDivLoss()(F.log_softmax(outputs / T, dim=1), - # F.softmax(teacher_outputs / T, dim=1)) * (alpha * T * T) + \ - # F.cross_entropy(outputs, labels) * (1. - alpha) + Hyperparameters: temperature and alpha :param outputs: output from the student model :param labels: label :param teacher_outputs: output from the teacher_outputs model @@ -116,7 +113,8 @@ def loss_fn_kd(self, outputs, teacher_outputs): alpha = 0.9 T = 0.01 # temperature empirically found in "policy distillation" KD_loss = nn.KLDivLoss()(F.log_softmax(outputs / T, dim=1), - F.softmax(teacher_outputs / T, dim=1)) + F.softmax(teacher_outputs / T, dim=1)) * (alpha * T * T) + \ + F.cross_entropy(outputs, labels) * (1. - alpha) return KD_loss def train(self, args, callback, env_kwargs=None, train_kwargs=None): @@ -216,18 +214,21 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): actions_proba_st = actions_proba[minibatchlist[minibatch_idx]] if not args.continuous_actions: - # Discrete actions, rearrange action to have n_minibatch ligns and one column, containing the int action - actions_st = th.from_numpy(actions_st).view(-1, 1).requires_grad_(False).to(self.device) - actions_proba_st = th.from_numpy(actions_proba_st).view(-1, 1).requires_grad_(False).to(self.device) + # Discrete actions, rearrange action to have n_minibatch ligns and one column, + # containing the int action + #print("shapes:", actions_st.shape, actions_proba_st.shape) + actions_st = th.from_numpy(actions_st).requires_grad_(False).to(self.device) + actions_proba_st = th.from_numpy(actions_proba_st).requires_grad_(False).to(self.device) else: # Continuous actions, rearrange action to have n_minibatch ligns and dim_action columns actions_st = th.from_numpy(actions_st).view(-1, self.dim_action).requires_grad_(False).to( self.device) - state = self.srl_model.model.getStates(obs)[0].to(self.device).detach() + state = self.srl_model.model.getStates(obs).to(self.device).detach() pred_action = self.policy(state) self.optimizer.zero_grad() - loss = self.loss_fn_kd(pred_action, actions_proba_st) + loss = self.loss_fn_kd(pred_action, actions_st, actions_proba_st) + loss.backward() if validation_mode: val_loss += loss.item() @@ -238,7 +239,7 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): epoch_loss += loss.item() epoch_batches += 1 pbar.update(1) - pbar.close() - train_loss = epoch_loss / float(epoch_batches) val_loss /= float(n_val_batches) + pbar.close() + print("Epoch {:3}/{}, train_loss:{:.4f} val_loss:{:.4f}".format(epoch + 1, N_EPOCHS, train_loss, val_loss)) From 94aba323c2dcc461a8410fe0399da33c8c6366f9 Mon Sep 17 00:00:00 2001 From: sun-te Date: Wed, 17 Apr 2019 09:34:33 +0200 Subject: [PATCH 029/141] bug-fix for pipeline cross --- rl_baselines/pipeline_cross.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/rl_baselines/pipeline_cross.py b/rl_baselines/pipeline_cross.py index ea7b2d99a..6b788f111 100644 --- a/rl_baselines/pipeline_cross.py +++ b/rl_baselines/pipeline_cross.py @@ -67,8 +67,7 @@ def main(): # Removing duplicates and sort srl_models = list(set(args.srl_model)) envs = list(set(args.env)) - tasks=list(set(args.tasks)) - tasks.sort() + tasks=args.tasks srl_models.sort() envs.sort() tasks=['-'+t for t in tasks] @@ -80,7 +79,8 @@ def main(): if len(config_files)==1: printYellow("Your are using the same config file: {} for all training tasks".format(config_files[0])) - config_files = [config_files[0] for i in range(len(tasks))] + for i in range(len(tasks)-1): + config_files.append(config_files[0]) else: assert len(config_files)==len(tasks), \ "Error: {} config files given for {} tasks".format(len(config_files),len(tasks)) @@ -156,7 +156,7 @@ def main(): print("timesteps:\t{}".format(args.num_timesteps)) num_tasks=len(tasks) - + print(num_tasks) printGreen("The tasks that will be exacuted: {}".format(args.tasks)) printGreen("with following config files: {}".format(config_files)) @@ -168,9 +168,8 @@ def main(): for iter_task in range(num_tasks): for i in range(args.num_iteration): - printGreen( - "\nIteration_num={} (seed: {}), Environment='{}', SRL-Model='{}' , Task='{}', Config_file='{}'".format(i, seeds[i], env, model, tasks[iter_task]),config_files[iter_task]) + "\nIteration_num={} (seed: {}), Environment='{}', SRL-Model='{}' , Task='{}',Config_file='{}'".format(i, seeds[i], env, model, tasks[iter_task],config_files[iter_task])) # redefine the parsed args for rl_baselines.train loop_args = ['--srl-model', model, '--seed', str(seeds[i]), From c69e558fa0aba46757cbee8b6a023c7ae3bf627c Mon Sep 17 00:00:00 2001 From: kalifou Date: Wed, 17 Apr 2019 10:37:18 +0200 Subject: [PATCH 030/141] format --- rl_baselines/supervised_rl/policy_distillation.py | 8 +++----- srl_zoo | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/rl_baselines/supervised_rl/policy_distillation.py b/rl_baselines/supervised_rl/policy_distillation.py index e97e21a6c..95d9c2400 100644 --- a/rl_baselines/supervised_rl/policy_distillation.py +++ b/rl_baselines/supervised_rl/policy_distillation.py @@ -5,7 +5,6 @@ from tqdm import tqdm from torch import nn from torch.nn import functional as F -from sklearn.model_selection import train_test_split from rl_baselines.base_classes import BaseRLObject from rl_baselines.utils import loadRunningAverage, MultiprocessSRLModel, softmax @@ -125,7 +124,7 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): print("We assumed SRL training already done") print('Loading data for distillation ') - training_data, ground_truth, true_states, _ = loadData(args.teacher_data_folder, complete=True) + training_data, ground_truth, true_states, _ = loadData(args.teacher_data_folder, absolute_path=True) rewards, episode_starts = training_data['rewards'], training_data['episode_starts'] images_path = ground_truth['images_path'] images_path_copy = ["srl_zoo/data/" + images_path[k] for k in range(images_path.shape[0])] @@ -146,11 +145,11 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): minibatchlist = [np.array(sorted(indices[start_idx:start_idx + self.batch_size])) for start_idx in range(0, len(indices) - self.batch_size + 1, self.batch_size)] data_loader = DataLoader(minibatchlist, images_path, n_workers=N_WORKERS, multi_view=False, - use_triplets=False, is_training=True, complete_path=True) + use_triplets=False, is_training=True, absolute_path=True) test_minibatchlist = DataLoader.createTestMinibatchList(len(images_path), MAX_BATCH_SIZE_GPU) test_data_loader = DataLoader(test_minibatchlist, images_path, n_workers=N_WORKERS, multi_view=False, - use_triplets=False, max_queue_len=1, is_training=False, complete_path=True) + use_triplets=False, max_queue_len=1, is_training=False, absolute_path=True) # Number of minibatches used for validation: n_val_batches = np.round(VALIDATION_SIZE * len(minibatchlist)).astype(np.int64) @@ -216,7 +215,6 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): if not args.continuous_actions: # Discrete actions, rearrange action to have n_minibatch ligns and one column, # containing the int action - #print("shapes:", actions_st.shape, actions_proba_st.shape) actions_st = th.from_numpy(actions_st).requires_grad_(False).to(self.device) actions_proba_st = th.from_numpy(actions_proba_st).requires_grad_(False).to(self.device) else: diff --git a/srl_zoo b/srl_zoo index 438a05ab6..97b357a94 160000 --- a/srl_zoo +++ b/srl_zoo @@ -1 +1 @@ -Subproject commit 438a05ab625a2c5ada573b47f73469d92de82132 +Subproject commit 97b357a94f32235dea1db0fba8738f5cfe42a0ce From a352a77192f63a39ebbca440669bd8947580d1b2 Mon Sep 17 00:00:00 2001 From: kalifou Date: Wed, 17 Apr 2019 10:37:18 +0200 Subject: [PATCH 031/141] format and update data loader in submodule (srl_zoo) --- rl_baselines/supervised_rl/policy_distillation.py | 8 +++----- srl_zoo | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/rl_baselines/supervised_rl/policy_distillation.py b/rl_baselines/supervised_rl/policy_distillation.py index e97e21a6c..95d9c2400 100644 --- a/rl_baselines/supervised_rl/policy_distillation.py +++ b/rl_baselines/supervised_rl/policy_distillation.py @@ -5,7 +5,6 @@ from tqdm import tqdm from torch import nn from torch.nn import functional as F -from sklearn.model_selection import train_test_split from rl_baselines.base_classes import BaseRLObject from rl_baselines.utils import loadRunningAverage, MultiprocessSRLModel, softmax @@ -125,7 +124,7 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): print("We assumed SRL training already done") print('Loading data for distillation ') - training_data, ground_truth, true_states, _ = loadData(args.teacher_data_folder, complete=True) + training_data, ground_truth, true_states, _ = loadData(args.teacher_data_folder, absolute_path=True) rewards, episode_starts = training_data['rewards'], training_data['episode_starts'] images_path = ground_truth['images_path'] images_path_copy = ["srl_zoo/data/" + images_path[k] for k in range(images_path.shape[0])] @@ -146,11 +145,11 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): minibatchlist = [np.array(sorted(indices[start_idx:start_idx + self.batch_size])) for start_idx in range(0, len(indices) - self.batch_size + 1, self.batch_size)] data_loader = DataLoader(minibatchlist, images_path, n_workers=N_WORKERS, multi_view=False, - use_triplets=False, is_training=True, complete_path=True) + use_triplets=False, is_training=True, absolute_path=True) test_minibatchlist = DataLoader.createTestMinibatchList(len(images_path), MAX_BATCH_SIZE_GPU) test_data_loader = DataLoader(test_minibatchlist, images_path, n_workers=N_WORKERS, multi_view=False, - use_triplets=False, max_queue_len=1, is_training=False, complete_path=True) + use_triplets=False, max_queue_len=1, is_training=False, absolute_path=True) # Number of minibatches used for validation: n_val_batches = np.round(VALIDATION_SIZE * len(minibatchlist)).astype(np.int64) @@ -216,7 +215,6 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): if not args.continuous_actions: # Discrete actions, rearrange action to have n_minibatch ligns and one column, # containing the int action - #print("shapes:", actions_st.shape, actions_proba_st.shape) actions_st = th.from_numpy(actions_st).requires_grad_(False).to(self.device) actions_proba_st = th.from_numpy(actions_proba_st).requires_grad_(False).to(self.device) else: diff --git a/srl_zoo b/srl_zoo index 438a05ab6..97b357a94 160000 --- a/srl_zoo +++ b/srl_zoo @@ -1 +1 @@ -Subproject commit 438a05ab625a2c5ada573b47f73469d92de82132 +Subproject commit 97b357a94f32235dea1db0fba8738f5cfe42a0ce From 3d133ab4ba7845c243a276a0e0effed207649442 Mon Sep 17 00:00:00 2001 From: kalifou Date: Wed, 17 Apr 2019 14:45:06 +0200 Subject: [PATCH 032/141] fix for off-policy generation --- environments/dataset_generator.py | 1 + 1 file changed, 1 insertion(+) diff --git a/environments/dataset_generator.py b/environments/dataset_generator.py index 5d6c03ba9..ba8d77763 100644 --- a/environments/dataset_generator.py +++ b/environments/dataset_generator.py @@ -147,6 +147,7 @@ def env_thread(args, thread_num, partition=True): generated_obs = deNormalize(generated_obs) obs = env.reset(generated_observation=generated_obs) done = False + action_proba = None t = 0 episode_toward_target_on = False while not done: From b79765795866b9f6ddcab1b6484d22bafa469401 Mon Sep 17 00:00:00 2001 From: kalifou Date: Wed, 17 Apr 2019 14:47:37 +0200 Subject: [PATCH 033/141] distillation: handling ts size & saving model --- .../supervised_rl/policy_distillation.py | 46 +++++++++++++------ 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/rl_baselines/supervised_rl/policy_distillation.py b/rl_baselines/supervised_rl/policy_distillation.py index 95d9c2400..351fc1b6c 100644 --- a/rl_baselines/supervised_rl/policy_distillation.py +++ b/rl_baselines/supervised_rl/policy_distillation.py @@ -34,7 +34,6 @@ def __init__(self, output_size, input_size, hidden_size=400): self.fc4 = nn.Linear(self.hidden_size, self.output_size) def forward(self, input): - input=input.view(-1, self.input_size) x = F.relu(self.fc1(input)) @@ -52,7 +51,7 @@ def __init__(self): super(PolicyDistillationModel, self).__init__() def save(self, save_path, _locals=None): - assert self.M is not None, "Error: must train or load model before use" + assert self.model is not None, "Error: must train or load model before use" with open(save_path, "wb") as f: pickle.dump(self.__dict__, f) @@ -62,6 +61,7 @@ def load(cls, load_path, args=None): class_dict = pickle.load(f) loaded_model = PolicyDistillationModel() loaded_model.__dict__ = class_dict + return loaded_model def customArguments(self, parser): @@ -93,7 +93,8 @@ def getAction(self, observation, dones=None, delta=0): assert self.model is not None, "Error: must train or load model before use" self.model.eval() - return np.argmax(self.model.forward(observation)) + observation = th.from_numpy(observation).float().requires_grad_(False).to(self.device) + return np.argmax(self.model.forward(observation).detach().cpu().numpy()) def loss_fn_kd(self, outputs, labels, teacher_outputs): """ @@ -112,8 +113,9 @@ def loss_fn_kd(self, outputs, labels, teacher_outputs): alpha = 0.9 T = 0.01 # temperature empirically found in "policy distillation" KD_loss = nn.KLDivLoss()(F.log_softmax(outputs / T, dim=1), - F.softmax(teacher_outputs / T, dim=1)) * (alpha * T * T) + \ - F.cross_entropy(outputs, labels) * (1. - alpha) + F.softmax(teacher_outputs / T, dim=1)) + # * (alpha * T * T) + \ + # F.cross_entropy(outputs, labels) * (1. - alpha) return KD_loss def train(self, args, callback, env_kwargs=None, train_kwargs=None): @@ -126,13 +128,19 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): print('Loading data for distillation ') training_data, ground_truth, true_states, _ = loadData(args.teacher_data_folder, absolute_path=True) rewards, episode_starts = training_data['rewards'], training_data['episode_starts'] + images_path = ground_truth['images_path'] - images_path_copy = ["srl_zoo/data/" + images_path[k] for k in range(images_path.shape[0])] - images_path = np.array(images_path_copy) actions = training_data['actions'] actions_proba = training_data['actions_proba'] - limit = args.distillation_training_set_size - actions = actions[:limit] + + if args.distillation_training_set_size > 0: + limit = args.distillation_training_set_size + actions = actions[:limit] + images_path = images_path[:limit] + episode_starts = episode_starts[:limit] + + images_path_copy = ["srl_zoo/data/" + images_path[k] for k in range(images_path.shape[0])] + images_path = np.array(images_path_copy) num_samples = images_path.shape[0] - 1 # number of samples @@ -186,13 +194,16 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): th.cuda.is_available(), self.state_dim, env_object=None) self.device = th.device("cuda" if th.cuda.is_available() else "cpu") - self.policy = MLP(input_size=self.state_dim, hidden_size=400, output_size=n_actions) + self.model = MLP(input_size=self.state_dim, hidden_size=400, output_size=n_actions) if th.cuda.is_available(): - self.policy.cuda() + self.model.cuda() - learnable_params = [param for param in self.policy.parameters() if param.requires_grad] + learnable_params = [param for param in self.model.parameters() if param.requires_grad] self.optimizer = th.optim.Adam(learnable_params, lr=1e-3) + best_error = np.inf + best_model_path = "{}/distillation_model.pkl".format(args.log_dir) + for epoch in range(N_EPOCHS): # In each epoch, we do a full pass over the training data: epoch_loss, epoch_batches = 0, 0 @@ -204,9 +215,9 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): obs = obs.to(self.device) validation_mode = minibatch_idx in val_indices if validation_mode: - self.policy.eval() + self.model.eval() else: - self.policy.train() + self.model.train() # Actions associated to the observations of the current minibatch actions_st = actions[minibatchlist[minibatch_idx]] @@ -223,7 +234,7 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): self.device) state = self.srl_model.model.getStates(obs).to(self.device).detach() - pred_action = self.policy(state) + pred_action = self.model(state) self.optimizer.zero_grad() loss = self.loss_fn_kd(pred_action, actions_st, actions_proba_st) @@ -241,3 +252,8 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): val_loss /= float(n_val_batches) pbar.close() print("Epoch {:3}/{}, train_loss:{:.4f} val_loss:{:.4f}".format(epoch + 1, N_EPOCHS, train_loss, val_loss)) + + # Save best model + if val_loss < best_error: + best_error = val_loss + self.save(best_model_path) From e4464892842a853d3c55567bc7897287b92727c1 Mon Sep 17 00:00:00 2001 From: kalifou Date: Wed, 17 Apr 2019 16:48:14 +0200 Subject: [PATCH 034/141] fix for replay --- rl_baselines/supervised_rl/policy_distillation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rl_baselines/supervised_rl/policy_distillation.py b/rl_baselines/supervised_rl/policy_distillation.py index 351fc1b6c..3fb382acd 100644 --- a/rl_baselines/supervised_rl/policy_distillation.py +++ b/rl_baselines/supervised_rl/policy_distillation.py @@ -94,7 +94,7 @@ def getAction(self, observation, dones=None, delta=0): self.model.eval() observation = th.from_numpy(observation).float().requires_grad_(False).to(self.device) - return np.argmax(self.model.forward(observation).detach().cpu().numpy()) + return [np.argmax(self.model.forward(observation).detach().cpu().numpy())] def loss_fn_kd(self, outputs, labels, teacher_outputs): """ From 9de7d58e496ad814fd7639fe5dbb336d55b1bcdc Mon Sep 17 00:00:00 2001 From: kalifou Date: Wed, 17 Apr 2019 17:07:12 +0200 Subject: [PATCH 035/141] additional fix for replay --- rl_baselines/supervised_rl/policy_distillation.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rl_baselines/supervised_rl/policy_distillation.py b/rl_baselines/supervised_rl/policy_distillation.py index 3fb382acd..2d6288395 100644 --- a/rl_baselines/supervised_rl/policy_distillation.py +++ b/rl_baselines/supervised_rl/policy_distillation.py @@ -79,7 +79,8 @@ def getActionProba(self, observation, dones=None, delta=0): :return: (numpy float) """ assert self.model is not None, "Error: must train or load model before use" - action = self.model.forward(observation) + observation = th.from_numpy(observation).float().requires_grad_(False).to(self.device) + action = self.model.forward(observation).detach().cpu().numpy() return softmax(action) def getAction(self, observation, dones=None, delta=0): From 9e8bfb8cbe9813a7962055c148a29ee33bd794f4 Mon Sep 17 00:00:00 2001 From: TLESORT Date: Wed, 17 Apr 2019 17:24:31 +0200 Subject: [PATCH 036/141] change loss for distillation for mse, it seems to work better --- rl_baselines/supervised_rl/policy_distillation.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/rl_baselines/supervised_rl/policy_distillation.py b/rl_baselines/supervised_rl/policy_distillation.py index 2d6288395..634c84e26 100644 --- a/rl_baselines/supervised_rl/policy_distillation.py +++ b/rl_baselines/supervised_rl/policy_distillation.py @@ -97,7 +97,7 @@ def getAction(self, observation, dones=None, delta=0): observation = th.from_numpy(observation).float().requires_grad_(False).to(self.device) return [np.argmax(self.model.forward(observation).detach().cpu().numpy())] - def loss_fn_kd(self, outputs, labels, teacher_outputs): + def loss_fn_kd(self, outputs, teacher_outputs): """ inspired from : https://github.com/peterliht/knowledge-distillation-pytorch Compute the knowledge-distillation (KD) loss given outputs, labels. @@ -106,7 +106,6 @@ def loss_fn_kd(self, outputs, labels, teacher_outputs): Hyperparameters: temperature and alpha :param outputs: output from the student model - :param labels: label :param teacher_outputs: output from the teacher_outputs model :return: loss """ @@ -119,6 +118,11 @@ def loss_fn_kd(self, outputs, labels, teacher_outputs): # F.cross_entropy(outputs, labels) * (1. - alpha) return KD_loss + def loss_mse(self, outputs, teacher_outputs): + MSELoss = nn.MSELoss()(outputs, teacher_outputs) + + return MSELoss + def train(self, args, callback, env_kwargs=None, train_kwargs=None): N_EPOCHS = args.epochs_distillation @@ -237,7 +241,8 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): state = self.srl_model.model.getStates(obs).to(self.device).detach() pred_action = self.model(state) self.optimizer.zero_grad() - loss = self.loss_fn_kd(pred_action, actions_st, actions_proba_st) + #loss = self.loss_fn_kd(pred_action, actions_proba_st) + loss = self.loss_mse(pred_action, actions_proba_st) loss.backward() if validation_mode: From b19da9f6dca10001c41fb809092d3c919a367c18 Mon Sep 17 00:00:00 2001 From: kalifou Date: Wed, 17 Apr 2019 18:54:07 +0200 Subject: [PATCH 037/141] update Distillation loss: swith to MSE --- rl_baselines/supervised_rl/policy_distillation.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/rl_baselines/supervised_rl/policy_distillation.py b/rl_baselines/supervised_rl/policy_distillation.py index 2d6288395..038645a7f 100644 --- a/rl_baselines/supervised_rl/policy_distillation.py +++ b/rl_baselines/supervised_rl/policy_distillation.py @@ -110,14 +110,7 @@ def loss_fn_kd(self, outputs, labels, teacher_outputs): :param teacher_outputs: output from the teacher_outputs model :return: loss """ - - alpha = 0.9 - T = 0.01 # temperature empirically found in "policy distillation" - KD_loss = nn.KLDivLoss()(F.log_softmax(outputs / T, dim=1), - F.softmax(teacher_outputs / T, dim=1)) - # * (alpha * T * T) + \ - # F.cross_entropy(outputs, labels) * (1. - alpha) - return KD_loss + return nn.MSELoss()(outputs, teacher_outputs) def train(self, args, callback, env_kwargs=None, train_kwargs=None): From 1bb20a5ff29548f917ef4cceabb90237606af2cf Mon Sep 17 00:00:00 2001 From: kalifou Date: Thu, 18 Apr 2019 15:09:23 +0200 Subject: [PATCH 038/141] format, fix args safety & load --- environments/dataset_generator.py | 43 +++++++++++++++----------- replay/diagram_replay.py | 50 +++++++++++++++++++++++++++++++ replay/enjoy_baselines.py | 2 -- rl_baselines/train.py | 6 ++-- 4 files changed, 79 insertions(+), 22 deletions(-) create mode 100644 replay/diagram_replay.py diff --git a/environments/dataset_generator.py b/environments/dataset_generator.py index ba8d77763..15f1fbfbf 100644 --- a/environments/dataset_generator.py +++ b/environments/dataset_generator.py @@ -2,7 +2,6 @@ import argparse import glob -import cv2 import multiprocessing import os import shutil @@ -81,7 +80,6 @@ def env_thread(args, thread_num, partition=True): "simple_continual_target": args.simple_continual, "circular_continual_move": args.circular_continual, "square_continual_move": args.square_continual - } if partition: @@ -89,6 +87,12 @@ def env_thread(args, thread_num, partition=True): else: env_kwargs["name"] = args.name + load_path, train_args, algo_name, algo_class = None, None, None, None + model = None + srl_model = None + srl_state_dim = 0 + generated_obs = None + if args.run_policy == "custom": args.log_dir = args.log_custom_policy args.render = args.display @@ -96,15 +100,17 @@ def env_thread(args, thread_num, partition=True): train_args, load_path, algo_name, algo_class, _, env_kwargs_extra = loadConfigAndSetup(args) env_kwargs["srl_model"] = env_kwargs_extra["srl_model"] - env_kwargs["srl_model_path"] = env_kwargs_extra.get("srl_model_path", None) - env_kwargs["state_dim"] = getSRLDim(env_kwargs_extra.get("srl_model_path", None)) - srl_model = MultiprocessSRLModel(args.num_cpu, args.env, env_kwargs) - env_kwargs["srl_pipe"] = srl_model.pipe + env_kwargs["random_target"] = env_kwargs_extra.get("random_target", False) + env_kwargs["use_srl"] = env_kwargs_extra.get("use_srl", False) + if env_kwargs["use_srl"]: + env_kwargs["srl_model_path"] = env_kwargs_extra.get("srl_model_path", None) + env_kwargs["state_dim"] = getSRLDim(env_kwargs_extra.get("srl_model_path", None)) + srl_model = MultiprocessSRLModel(args.num_cpu, args.env, env_kwargs) + env_kwargs["srl_pipe"] = srl_model.pipe env_class = registered_env[args.env][0] env = env_class(**env_kwargs) - model = None - generated_obs = None + if args.run_policy in ['custom', 'ppo2']: # Additional env when using a trained agent to generate data @@ -120,8 +126,6 @@ def env_thread(args, thread_num, partition=True): model = algo_class.load(load_path, args=algo_args) if len(args.replay_generative_model) > 0: - use_cuda = args.cuda_generative_replay - device = th.device("cuda" if th.cuda.is_available() and use_cuda else "cpu") srl_model = loadSRLModel(args.log_generative_model, th.cuda.is_available()) srl_state_dim = srl_model.state_dim srl_model = srl_model.model.model @@ -139,25 +143,31 @@ def env_thread(args, thread_num, partition=True): env.action_space.seed(seed) # this is for the sample() function from gym.space if len(args.replay_generative_model) > 0: + sample = Variable(th.randn(1, srl_state_dim)) if th.cuda.is_available(): sample = sample.cuda() + generated_obs = srl_model.decode(sample) generated_obs = generated_obs[0].detach().cpu().numpy().transpose(1, 2, 0) generated_obs = deNormalize(generated_obs) + obs = env.reset(generated_observation=generated_obs) done = False action_proba = None t = 0 episode_toward_target_on = False + while not done: - env.render() + env.render() if args.run_policy == 'ppo2': action, _ = model.predict([obs]) + elif args.run_policy == 'custom': action = [model.getAction(obs, done)] action_proba = model.getActionProba(obs, done) + else: if episode_toward_target_on and np.random.rand() < args.toward_target_timesteps_proportion: action = [env.actionPolicyTowardTarget()] @@ -165,19 +175,18 @@ def env_thread(args, thread_num, partition=True): action = [env.action_space.sample()] if len(args.replay_generative_model) > 0: + sample = Variable(th.randn(1, srl_state_dim)) + if th.cuda.is_available(): sample = sample.cuda() + generated_obs = srl_model.decode(sample) generated_obs = generated_obs[0].detach().cpu().numpy().transpose(1, 2, 0) generated_obs = deNormalize(generated_obs) action_to_step = action[0] - new_obs, _, done, _ = env.step(action_to_step, generated_observation=generated_obs, - action_proba=action_proba) - - if args.run_policy == 'custom': - obs = new_obs + obs, _, done, _ = env.step(action_to_step, generated_observation=generated_obs, action_proba=action_proba) frames += 1 t += 1 @@ -192,6 +201,7 @@ def env_thread(args, thread_num, partition=True): if thread_num == 0: print("{:.2f} FPS".format(frames * args.num_cpu / (time.time() - start_time))) + def main(): parser = argparse.ArgumentParser(description='Deteministic dataset generator for SRL training ' + '(can be used for environment testing)') @@ -228,7 +238,6 @@ def main(): help='Generative model to replay for generating a dataset (for Continual Learning purposes)') parser.add_argument('--log-generative-model', type=str, default='', help='Logs of the custom pretained policy to run for data collection') - parser.add_argument('--cuda-generative-replay', action='store_true', default=False, help='enables CUDA for replay') parser.add_argument('--ppo2-timesteps', type=int, default=1000, help='number of timesteps to run PPO2 on before generating the dataset') parser.add_argument('--toward-target-timesteps-proportion', type=float, default=0.0, diff --git a/replay/diagram_replay.py b/replay/diagram_replay.py new file mode 100644 index 000000000..ae27821d7 --- /dev/null +++ b/replay/diagram_replay.py @@ -0,0 +1,50 @@ +import numpy as np +import matplotlib.pyplot as plt +from matplotlib import rc +import seaborn as sns +import pandas + +if __name__ == '__main__': + rc('font', weight='bold') + ae = [216, 240, 237, 236, 240, 224, 230, 214] + raw_pixels = [89, 156, 8, 6, -2, -2, 0, 0] + gt = [245, 243, 239, 241, 242, 246, 243, 230] + srl_combination = [187, 191, 191, 206, 140, 185, 81, 69] + srl_splits = [223, 183, 227, 194, 193, 185, 181, 184] + supervised = [240, 243, 240, 237, 239, 239, 240, 237] + random = [99, 50, 65, 116, 224, 211, 198, 50] + + perfs_replay_real = gt + supervised + srl_splits + ae + srl_combination + random + raw_pixels + + ae = [241, 228, 217, 245, 241, 235, 237, 242] + raw_pixels = [194, 165, -2, 226, 235, 136, 124, 224] + gt = [236, 240, 243, 246, 247, 237, 246, 240] + srl_combination = [235, 224, 225, 231, 209, 228, 242, 235] + srl_splits = [244, 239, 230, 206, 242, 238, 241, 240] + supervised = [235, 241, 243, 246, 248, 235, 240, 245] + random = [225, 177, 213, 174, 235, 207, 225, 229] + + perfs_replay_sim = gt + supervised + srl_splits + ae + srl_combination + random + raw_pixels + tags_replay = ["Ground Truth" for i in range(8)] + ["Supervised" for i in range(8)] + \ + ["SRL Splits" for i in range(8)] + ["Auto-encoder" for i in range(8)] + \ + ["SRL Combination" for i in range(8)] + ["Random Feat." for i in range(8)] +\ + ["Raw Pixels" for i in range(8)] + + df = pandas.DataFrame({'SRL Method': tags_replay, "Real": perfs_replay_real, + "Simulation": perfs_replay_sim}) + print(df["Real"]) + sns.set(style="ticks", palette="colorblind") + + # Draw a nested boxplot to show bills by day and time + dd = pandas.melt(df, id_vars=['SRL Method'], value_vars=['Simulation', 'Real'], var_name='Setting') + b = sns.boxplot(x='SRL Method', y='value', data=dd, hue='Setting') + b.tick_params(labelsize=15) + + #b.set_xlabel(, fontsize=20) + #b.set_ylabel("Rewards", fontsize=20) + + plt.xlabel("SRL Method", fontsize=20, fontweight='bold') + plt.ylabel("Rewards", fontsize=20, fontweight='bold') + plt.setp(b.get_legend().get_texts(), fontsize='22') # for legend text + plt.setp(b.get_legend().get_title(), fontsize='24') + plt.show() diff --git a/replay/enjoy_baselines.py b/replay/enjoy_baselines.py index f48172c59..bac017cc8 100644 --- a/replay/enjoy_baselines.py +++ b/replay/enjoy_baselines.py @@ -6,12 +6,10 @@ import os from datetime import datetime -import yaml import numpy as np import tensorflow as tf from stable_baselines.common import set_global_seeds import matplotlib.pyplot as plt -from mpl_toolkits.mplot3d import Axes3D from sklearn.decomposition import PCA import seaborn as sns diff --git a/rl_baselines/train.py b/rl_baselines/train.py index 01f12f955..61246c501 100644 --- a/rl_baselines/train.py +++ b/rl_baselines/train.py @@ -226,7 +226,7 @@ def main(): help='Green square target for task 4 of continual learning scenario. ' + 'The task is: robot should do the eigth with the target as center of the shape.') parser.add_argument('--teacher-data-folder', type=str, default="", - help='Dataset folder of the teacher(s) policy(ies)', required=True) + help='Dataset folder of the teacher(s) policy(ies)', required=False) parser.add_argument('--epochs-distillation', type=int, default=30, metavar='N', help='number of epochs to train for distillation(default: 30)') parser.add_argument('--distillation-training-set-size', type=int, default=-1, @@ -264,8 +264,8 @@ def main(): <= 1 and args.env == "OmnirobotEnv-v0", \ "For continual SRL and RL, please provide only one scenario at the time and use OmnirobotEnv-v0 environment !" - assert args.algo == "distillation" and args.teacher_data_folder != '' and args.continuous_actions is False, \ - "For performing policy distillation, make sure use specify a valid teacher dataset!" + assert not(args.algo == "distillation" and (args.teacher_data_folder == '' or args.continuous_actions is True)), \ + "For performing policy distillation, make sure use specify a valid teacher dataset and discrete actions !" ENV_NAME = args.env ALGO_NAME = args.algo From 9f64156179a9c9f0fbfdf34b015aa4fd4a86e233 Mon Sep 17 00:00:00 2001 From: kalifou Date: Thu, 18 Apr 2019 18:13:29 +0200 Subject: [PATCH 039/141] remove useless script, fix distillation with raw pixels & dataset fusioner --- environments/dataset_fusioner.py | 3 +- replay/diagram_replay.py | 50 ------------------- .../supervised_rl/policy_distillation.py | 18 ++++--- 3 files changed, 12 insertions(+), 59 deletions(-) delete mode 100644 replay/diagram_replay.py diff --git a/environments/dataset_fusioner.py b/environments/dataset_fusioner.py index 2ba941bd9..fe8bad59a 100644 --- a/environments/dataset_fusioner.py +++ b/environments/dataset_fusioner.py @@ -25,7 +25,6 @@ def main(): assert (not os.path.exists(args.merge[2])), "Error: dataset '{}' already exists, cannot rename '{}' to '{}'"\ .format(args.merge[2], args.merge[0], args.merge[2]) # create the output - print(args) os.mkdir(args.merge[2]) # copy files from first source @@ -103,7 +102,7 @@ def main(): for prepro_load in [preprocessed_load, preprocessed_load_2]: for arr in prepro_load.files: pr_arr = prepro_load[arr] - preprocessed[arr] = np.concatenate((preprocessed.get(arr, []), pr_arr), axis=0) + preprocessed[arr] = np.concatenate((preprocessed.get(arr, np.zeros(pr_arr.shape)), pr_arr), axis=0) if arr == "episode_starts": preprocessed[arr] = preprocessed[arr].astype(bool) else: diff --git a/replay/diagram_replay.py b/replay/diagram_replay.py deleted file mode 100644 index ae27821d7..000000000 --- a/replay/diagram_replay.py +++ /dev/null @@ -1,50 +0,0 @@ -import numpy as np -import matplotlib.pyplot as plt -from matplotlib import rc -import seaborn as sns -import pandas - -if __name__ == '__main__': - rc('font', weight='bold') - ae = [216, 240, 237, 236, 240, 224, 230, 214] - raw_pixels = [89, 156, 8, 6, -2, -2, 0, 0] - gt = [245, 243, 239, 241, 242, 246, 243, 230] - srl_combination = [187, 191, 191, 206, 140, 185, 81, 69] - srl_splits = [223, 183, 227, 194, 193, 185, 181, 184] - supervised = [240, 243, 240, 237, 239, 239, 240, 237] - random = [99, 50, 65, 116, 224, 211, 198, 50] - - perfs_replay_real = gt + supervised + srl_splits + ae + srl_combination + random + raw_pixels - - ae = [241, 228, 217, 245, 241, 235, 237, 242] - raw_pixels = [194, 165, -2, 226, 235, 136, 124, 224] - gt = [236, 240, 243, 246, 247, 237, 246, 240] - srl_combination = [235, 224, 225, 231, 209, 228, 242, 235] - srl_splits = [244, 239, 230, 206, 242, 238, 241, 240] - supervised = [235, 241, 243, 246, 248, 235, 240, 245] - random = [225, 177, 213, 174, 235, 207, 225, 229] - - perfs_replay_sim = gt + supervised + srl_splits + ae + srl_combination + random + raw_pixels - tags_replay = ["Ground Truth" for i in range(8)] + ["Supervised" for i in range(8)] + \ - ["SRL Splits" for i in range(8)] + ["Auto-encoder" for i in range(8)] + \ - ["SRL Combination" for i in range(8)] + ["Random Feat." for i in range(8)] +\ - ["Raw Pixels" for i in range(8)] - - df = pandas.DataFrame({'SRL Method': tags_replay, "Real": perfs_replay_real, - "Simulation": perfs_replay_sim}) - print(df["Real"]) - sns.set(style="ticks", palette="colorblind") - - # Draw a nested boxplot to show bills by day and time - dd = pandas.melt(df, id_vars=['SRL Method'], value_vars=['Simulation', 'Real'], var_name='Setting') - b = sns.boxplot(x='SRL Method', y='value', data=dd, hue='Setting') - b.tick_params(labelsize=15) - - #b.set_xlabel(, fontsize=20) - #b.set_ylabel("Rewards", fontsize=20) - - plt.xlabel("SRL Method", fontsize=20, fontweight='bold') - plt.ylabel("Rewards", fontsize=20, fontweight='bold') - plt.setp(b.get_legend().get_texts(), fontsize='22') # for legend text - plt.setp(b.get_legend().get_title(), fontsize='24') - plt.show() diff --git a/rl_baselines/supervised_rl/policy_distillation.py b/rl_baselines/supervised_rl/policy_distillation.py index 038645a7f..895f62d56 100644 --- a/rl_baselines/supervised_rl/policy_distillation.py +++ b/rl_baselines/supervised_rl/policy_distillation.py @@ -18,7 +18,8 @@ TEST_BATCH_SIZE = 256 VALIDATION_SIZE = 0.2 # 20% of training data for validation MAX_BATCH_SIZE_GPU = 256 # For plotting, max batch_size before having memory issues - +RENDER_HEIGHT = 224 +RENDER_WIDTH = 224 class MLP(nn.Module): def __init__(self, output_size, input_size, hidden_size=400): @@ -180,12 +181,15 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): print('Continuous action space:') print('Action dimension: {}'.format(self.dim_action)) - assert env_kwargs is not None and registered_srl[args.srl_model][0] == SRLType.SRL, \ - "Please specify a valid srl model for training your policy !" + # Here the default SRL model is assumed to be raw_pixels + self.state_dim = RENDER_HEIGHT *RENDER_WIDTH + self.srl_model = None - self.state_dim = getSRLDim(env_kwargs.get("srl_model_path", None)) - self.srl_model = loadSRLModel(env_kwargs.get("srl_model_path", None), - th.cuda.is_available(), self.state_dim, env_object=None) + # TODO: add sanity checks & test for all possible SRL for distillation + if env_kwargs["srl_model"] is "raw_pixels": + self.state_dim = getSRLDim(env_kwargs.get("srl_model_path", None)) + self.srl_model = loadSRLModel(env_kwargs.get("srl_model_path", None), + th.cuda.is_available(), self.state_dim, env_object=None) self.device = th.device("cuda" if th.cuda.is_available() else "cpu") self.model = MLP(input_size=self.state_dim, hidden_size=400, output_size=n_actions) @@ -227,7 +231,7 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): actions_st = th.from_numpy(actions_st).view(-1, self.dim_action).requires_grad_(False).to( self.device) - state = self.srl_model.model.getStates(obs).to(self.device).detach() + state = obs if self.srl_model is None else self.srl_model.model.getStates(obs).to(self.device).detach() pred_action = self.model(state) self.optimizer.zero_grad() loss = self.loss_fn_kd(pred_action, actions_st, actions_proba_st) From 39c5d22f305c49e1c8f79a41c6d1c5e28554ec76 Mon Sep 17 00:00:00 2001 From: kalifou Date: Thu, 18 Apr 2019 19:26:08 +0200 Subject: [PATCH 040/141] fix for distillation using RL from raw_pixels --- environments/dataset_generator.py | 1 + rl_baselines/supervised_rl/policy_distillation.py | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/environments/dataset_generator.py b/environments/dataset_generator.py index 15f1fbfbf..fa7e2468e 100644 --- a/environments/dataset_generator.py +++ b/environments/dataset_generator.py @@ -186,6 +186,7 @@ def env_thread(args, thread_num, partition=True): generated_obs = deNormalize(generated_obs) action_to_step = action[0] + obs, _, done, _ = env.step(action_to_step, generated_observation=generated_obs, action_proba=action_proba) frames += 1 diff --git a/rl_baselines/supervised_rl/policy_distillation.py b/rl_baselines/supervised_rl/policy_distillation.py index 895f62d56..887ac1b53 100644 --- a/rl_baselines/supervised_rl/policy_distillation.py +++ b/rl_baselines/supervised_rl/policy_distillation.py @@ -35,8 +35,8 @@ def __init__(self, output_size, input_size, hidden_size=400): self.fc4 = nn.Linear(self.hidden_size, self.output_size) def forward(self, input): - input=input.view(-1, self.input_size) + input = input.view(-1, self.input_size) x = F.relu(self.fc1(input)) x = F.relu(self.fc2(x)) x = F.relu(self.fc3(x)) @@ -182,17 +182,17 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): print('Action dimension: {}'.format(self.dim_action)) # Here the default SRL model is assumed to be raw_pixels - self.state_dim = RENDER_HEIGHT *RENDER_WIDTH + self.state_dim = RENDER_HEIGHT * RENDER_WIDTH * 3 self.srl_model = None # TODO: add sanity checks & test for all possible SRL for distillation - if env_kwargs["srl_model"] is "raw_pixels": + if env_kwargs["srl_model"] != "raw_pixels": self.state_dim = getSRLDim(env_kwargs.get("srl_model_path", None)) self.srl_model = loadSRLModel(env_kwargs.get("srl_model_path", None), th.cuda.is_available(), self.state_dim, env_object=None) self.device = th.device("cuda" if th.cuda.is_available() else "cpu") - self.model = MLP(input_size=self.state_dim, hidden_size=400, output_size=n_actions) + self.model = MLP(n_actions, self.state_dim, hidden_size=400) if th.cuda.is_available(): self.model.cuda() @@ -231,10 +231,10 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): actions_st = th.from_numpy(actions_st).view(-1, self.dim_action).requires_grad_(False).to( self.device) - state = obs if self.srl_model is None else self.srl_model.model.getStates(obs).to(self.device).detach() + state = obs.detach() if self.srl_model is None else self.srl_model.model.getStates(obs).to(self.device).detach() pred_action = self.model(state) self.optimizer.zero_grad() - loss = self.loss_fn_kd(pred_action, actions_st, actions_proba_st) + loss = self.loss_fn_kd(pred_action, actions_st, actions_proba_st.float()) loss.backward() if validation_mode: From 1edda899acfb870de9b6a530b5a20602dec9680e Mon Sep 17 00:00:00 2001 From: sun-te Date: Tue, 23 Apr 2019 11:17:13 +0200 Subject: [PATCH 041/141] cross evaluation during training --- environments/dataset_fusioner.py | 3 +- environments/dataset_generator.py | 77 ++++- environments/omnirobot_gym/omnirobot_env.py | 10 +- environments/srl_env.py | 2 +- rl_baselines/cross_eval.py | 269 ++++++++++++++++++ rl_baselines/registry.py | 4 +- rl_baselines/supervised_rl/__init__.py | 0 .../supervised_rl/policy_distillation.py | 257 +++++++++++++++++ rl_baselines/train.py | 44 ++- rl_baselines/visualize.py | 36 +++ 10 files changed, 666 insertions(+), 36 deletions(-) create mode 100644 rl_baselines/cross_eval.py create mode 100644 rl_baselines/supervised_rl/__init__.py create mode 100644 rl_baselines/supervised_rl/policy_distillation.py diff --git a/environments/dataset_fusioner.py b/environments/dataset_fusioner.py index 2ba941bd9..fe8bad59a 100644 --- a/environments/dataset_fusioner.py +++ b/environments/dataset_fusioner.py @@ -25,7 +25,6 @@ def main(): assert (not os.path.exists(args.merge[2])), "Error: dataset '{}' already exists, cannot rename '{}' to '{}'"\ .format(args.merge[2], args.merge[0], args.merge[2]) # create the output - print(args) os.mkdir(args.merge[2]) # copy files from first source @@ -103,7 +102,7 @@ def main(): for prepro_load in [preprocessed_load, preprocessed_load_2]: for arr in prepro_load.files: pr_arr = prepro_load[arr] - preprocessed[arr] = np.concatenate((preprocessed.get(arr, []), pr_arr), axis=0) + preprocessed[arr] = np.concatenate((preprocessed.get(arr, np.zeros(pr_arr.shape)), pr_arr), axis=0) if arr == "episode_starts": preprocessed[arr] = preprocessed[arr].astype(bool) else: diff --git a/environments/dataset_generator.py b/environments/dataset_generator.py index a29756a40..15f1fbfbf 100644 --- a/environments/dataset_generator.py +++ b/environments/dataset_generator.py @@ -5,7 +5,10 @@ import multiprocessing import os import shutil +import tensorflow as tf import time +import torch as th +from torch.autograd import Variable import numpy as np from stable_baselines import PPO2 @@ -13,14 +16,18 @@ from stable_baselines.common.vec_env import DummyVecEnv, VecNormalize from stable_baselines.common.policies import CnnPolicy -import tensorflow as tf - from environments import ThreadingType from environments.registry import registered_env from replay.enjoy_baselines import createEnv, loadConfigAndSetup -from rl_baselines.utils import WrapFrameStack +from rl_baselines.utils import MultiprocessSRLModel from srl_zoo.utils import printRed, printYellow +from srl_zoo.preprocessing.utils import deNormalize +from state_representation.models import loadSRLModel, getSRLDim +RENDER_HEIGHT = 224 +RENDER_WIDTH = 224 +VALID_MODELS = ["forward", "inverse", "reward", "priors", "episode-prior", "reward-prior", "triplet", + "autoencoder", "vae", "dae", "random"] os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' # used to remove debug info of tensorflow @@ -73,7 +80,6 @@ def env_thread(args, thread_num, partition=True): "simple_continual_target": args.simple_continual, "circular_continual_move": args.circular_continual, "square_continual_move": args.square_continual - } if partition: @@ -81,6 +87,12 @@ def env_thread(args, thread_num, partition=True): else: env_kwargs["name"] = args.name + load_path, train_args, algo_name, algo_class = None, None, None, None + model = None + srl_model = None + srl_state_dim = 0 + generated_obs = None + if args.run_policy == "custom": args.log_dir = args.log_custom_policy args.render = args.display @@ -88,10 +100,16 @@ def env_thread(args, thread_num, partition=True): train_args, load_path, algo_name, algo_class, _, env_kwargs_extra = loadConfigAndSetup(args) env_kwargs["srl_model"] = env_kwargs_extra["srl_model"] + env_kwargs["random_target"] = env_kwargs_extra.get("random_target", False) + env_kwargs["use_srl"] = env_kwargs_extra.get("use_srl", False) + if env_kwargs["use_srl"]: + env_kwargs["srl_model_path"] = env_kwargs_extra.get("srl_model_path", None) + env_kwargs["state_dim"] = getSRLDim(env_kwargs_extra.get("srl_model_path", None)) + srl_model = MultiprocessSRLModel(args.num_cpu, args.env, env_kwargs) + env_kwargs["srl_pipe"] = srl_model.pipe env_class = registered_env[args.env][0] env = env_class(**env_kwargs) - model = None if args.run_policy in ['custom', 'ppo2']: @@ -102,12 +120,16 @@ def env_thread(args, thread_num, partition=True): model = PPO2(CnnPolicy, train_env).learn(args.ppo2_timesteps) else: _, _, algo_args = createEnv(args, train_args, algo_name, algo_class, env_kwargs) - tf.reset_default_graph() set_global_seeds(args.seed) printYellow("Compiling Policy function....") model = algo_class.load(load_path, args=algo_args) + if len(args.replay_generative_model) > 0: + srl_model = loadSRLModel(args.log_generative_model, th.cuda.is_available()) + srl_state_dim = srl_model.state_dim + srl_model = srl_model.model.model + frames = 0 start_time = time.time() # divide evenly, then do an extra one for only some of them in order to get the right count @@ -120,28 +142,51 @@ def env_thread(args, thread_num, partition=True): env.seed(seed) env.action_space.seed(seed) # this is for the sample() function from gym.space - obs = env.reset() + if len(args.replay_generative_model) > 0: + + sample = Variable(th.randn(1, srl_state_dim)) + if th.cuda.is_available(): + sample = sample.cuda() + + generated_obs = srl_model.decode(sample) + generated_obs = generated_obs[0].detach().cpu().numpy().transpose(1, 2, 0) + generated_obs = deNormalize(generated_obs) + + obs = env.reset(generated_observation=generated_obs) done = False + action_proba = None t = 0 episode_toward_target_on = False + while not done: - env.render() + env.render() if args.run_policy == 'ppo2': action, _ = model.predict([obs]) + elif args.run_policy == 'custom': action = [model.getAction(obs, done)] + action_proba = model.getActionProba(obs, done) + else: if episode_toward_target_on and np.random.rand() < args.toward_target_timesteps_proportion: action = [env.actionPolicyTowardTarget()] else: action = [env.action_space.sample()] - action_to_step = action[0] - new_obs, _, done, _ = env.step(action_to_step) + if len(args.replay_generative_model) > 0: + + sample = Variable(th.randn(1, srl_state_dim)) + + if th.cuda.is_available(): + sample = sample.cuda() - if args.run_policy == 'custom': - obs = new_obs + generated_obs = srl_model.decode(sample) + generated_obs = generated_obs[0].detach().cpu().numpy().transpose(1, 2, 0) + generated_obs = deNormalize(generated_obs) + + action_to_step = action[0] + obs, _, done, _ = env.step(action_to_step, generated_observation=generated_obs, action_proba=action_proba) frames += 1 t += 1 @@ -156,6 +201,7 @@ def env_thread(args, thread_num, partition=True): if thread_num == 0: print("{:.2f} FPS".format(frames * args.num_cpu / (time.time() - start_time))) + def main(): parser = argparse.ArgumentParser(description='Deteministic dataset generator for SRL training ' + '(can be used for environment testing)') @@ -188,6 +234,10 @@ def main(): '(random, localy pretrained ppo2, pretrained custom policy)') parser.add_argument('--log-custom-policy', type=str, default='', help='Logs of the custom pretained policy to run for data collection') + parser.add_argument('-rgm', '--replay-generative-model', type=str, default="", choices=['vae'], + help='Generative model to replay for generating a dataset (for Continual Learning purposes)') + parser.add_argument('--log-generative-model', type=str, default='', + help='Logs of the custom pretained policy to run for data collection') parser.add_argument('--ppo2-timesteps', type=int, default=1000, help='number of timesteps to run PPO2 on before generating the dataset') parser.add_argument('--toward-target-timesteps-proportion', type=float, default=0.0, @@ -221,6 +271,9 @@ def main(): assert not (args.log_custom_policy == '' and args.run_policy == 'custom'), \ "If using a custom policy, please specify a valid log folder for loading it." + assert not (args.log_generative_model == '' and args.replay_generative_model == 'custom'), \ + "If using a custom policy, please specify a valid log folder for loading it." + # this is done so seed 0 and 1 are different and not simply offset of the same datasets. args.seed = np.random.RandomState(args.seed).randint(int(1e10)) diff --git a/environments/omnirobot_gym/omnirobot_env.py b/environments/omnirobot_gym/omnirobot_env.py index 26495c30f..9df8cf927 100644 --- a/environments/omnirobot_gym/omnirobot_env.py +++ b/environments/omnirobot_gym/omnirobot_env.py @@ -181,7 +181,7 @@ def actionPolicyTowardTarget(self): else: return DELTA_POS if self.robot_pos[1] < self.target_pos[1] else -DELTA_POS - def step(self, action): + def step(self, action, generated_observation=None, action_proba=None): """ :action: (int) :return: (tensor (np.ndarray)) observation, int reward, bool done, dict extras) @@ -210,14 +210,14 @@ def step(self, action): self.getEnvState() # Receive a camera image from the server - self.observation = self.getObservation() + self.observation = self.getObservation() if generated_observation is None else generated_observation * 255 done = self._hasEpisodeTerminated() self.render() if self.saver is not None: self.saver.step(self.observation, action, - self.reward, done, self.getGroundTruth()) + self.reward, done, self.getGroundTruth(), action_proba=action_proba) if self.use_srl: return self.getSRLState(self.observation), self.reward, done, {} else: @@ -274,7 +274,7 @@ def getRobotPos(self): """ return self.robot_pos - def reset(self): + def reset(self, generated_observation=None): """ Reset the environment :return: (numpy ndarray) first observation of the env @@ -288,7 +288,7 @@ def reset(self): # Update state related variables, important step to get both data and # metadata that allow reading the observation image self.getEnvState() - self.observation = self.getObservation() + self.observation = self.getObservation() if generated_observation is None else generated_observation * 255 if self.saver is not None: self.saver.reset(self.observation, self.getTargetPos(), self.getGroundTruth()) diff --git a/environments/srl_env.py b/environments/srl_env.py index 4c6be4f34..c7e8d6951 100644 --- a/environments/srl_env.py +++ b/environments/srl_env.py @@ -81,7 +81,7 @@ def close(self): # TODO: implement close function to close GUI pass - def step(self, action): + def step(self, action, generated_observation=None, action_proba=None): """ :param action: (int or [float]) """ diff --git a/rl_baselines/cross_eval.py b/rl_baselines/cross_eval.py new file mode 100644 index 000000000..6288176c1 --- /dev/null +++ b/rl_baselines/cross_eval.py @@ -0,0 +1,269 @@ +""" +Modified version of https://github.com/ikostrikov/pytorch-a2c-ppo-acktr/blob/master/visualize.py +Script used to send plot data to visdom +""" +import glob +import os +import json +import numpy as np +import tensorflow as tf +from scipy.signal import medfilt +from rl_baselines.utils import WrapFrameStack,computeMeanReward +from rl_baselines import AlgoType +from rl_baselines.registry import registered_rl +from srl_zoo.utils import printYellow, printGreen,printBlue,printRed +from datetime import datetime + +def loadConfigAndSetup(log_dir): + algo_name = "" + for algo in list(registered_rl.keys()): + if algo in log_dir: + algo_name = algo + break + algo_class, algo_type, _ = registered_rl[algo_name] + if algo_type == AlgoType.OTHER: + raise ValueError(algo_name + " is not supported for evaluation") + + env_globals = json.load(open(log_dir + "env_globals.json", 'r')) + train_args = json.load(open(log_dir + "args.json", 'r')) + env_kwargs = { + "renders": False, + "shape_reward": False, #TODO, since we dont use simple target, we should elimanate this choice? + "action_joints": train_args["action_joints"], + "is_discrete": not train_args["continuous_actions"], + "random_target": train_args.get('random_target', False), + "srl_model": train_args["srl_model"] + } + + # load it, if it was defined + if "action_repeat" in env_globals: + env_kwargs["action_repeat"] = env_globals['action_repeat'] + + # Remove up action + if train_args["env"] == "Kuka2ButtonGymEnv-v0": + env_kwargs["force_down"] = env_globals.get('force_down', True) + else: + env_kwargs["force_down"] = env_globals.get('force_down', False) + + if train_args["env"] == "OmnirobotEnv-v0": + env_kwargs["simple_continual_target"] = env_globals.get("simple_continual_target", False) + env_kwargs["circular_continual_move"] = env_globals.get("circular_continual_move", False) + env_kwargs["square_continual_move"] = env_globals.get("square_continual_move", False) + env_kwargs["eight_continual_move"] = env_globals.get("eight_continual_move", False) + + srl_model_path = None + if train_args["srl_model"] != "raw_pixels": + train_args["policy"] = "mlp" + path = env_globals.get('srl_model_path') + + if path is not None: + env_kwargs["use_srl"] = True + # Check that the srl saved model exists on the disk + assert os.path.isfile(env_globals['srl_model_path']), "{} does not exist".format(env_globals['srl_model_path']) + srl_model_path = env_globals['srl_model_path'] + env_kwargs["srl_model_path"] = srl_model_path + + return train_args, algo_name, algo_class, srl_model_path, env_kwargs + +def listEnvsKwargs(tasks,env_kwargs): + + tasks_env_kwargs=[] + tmp=env_kwargs.copy() + tmp['simple_continual_target'] = False + tmp['circular_continual_move'] = False + tmp['square_continual_move'] = False + tmp['eight_continual_move'] = False + for t in tasks: + #For every tasks we create a special env_kwargs to generate different envs + if (t=='sc'): + tmp['simple_continual_target']=True + tasks_env_kwargs.append(tmp.copy()) + tmp['simple_continual_target']=False + elif (t=='cc'): + + tmp['circular_continual_move']=True + tasks_env_kwargs.append(tmp.copy()) + tmp['circular_continual_move']=False + elif (t=='sqc'): + tmp['square_continual_move']=True + tasks_env_kwargs.append(tmp.copy()) + tmp['square_continual_move']=False + elif (t=='ec'): + tmp['eight_continual_move']=True + tasks_env_kwargs.append(tmp.copy()) + tmp['eight_continual_move']=False + return tasks_env_kwargs + +def createEnv( model_dir,train_args, algo_name, algo_class, env_kwargs, log_dir="/tmp/gym/test/",num_cpu=1,seed=0): + + # Log dir for testing the agent + log_dir += "{}/{}/".format(algo_name, datetime.now().strftime("%y-%m-%d_%Hh%M_%S_%f")) + os.makedirs(log_dir, exist_ok=True) + args = { + "env": train_args['env'], + "seed":seed, + "num_cpu": num_cpu, + "num_stack": train_args["num_stack"], + "srl_model": train_args["srl_model"], + "algo_type": train_args.get('algo_type', None), + "log_dir": log_dir + } + algo_args = type('attrib_dict', (), args)() # anonymous class so the dict looks like Arguments object + envs = algo_class.makeEnv(algo_args, env_kwargs=env_kwargs, load_path_normalise=model_dir) + + return log_dir, envs, algo_args + + + + +def policyEval(envs,model_path,log_dir,algo_class,algo_args,num_timesteps=1000,num_cpu=1): + tf.reset_default_graph() + method = algo_class.load(model_path, args=algo_args) + using_custom_vec_env = isinstance(envs, WrapFrameStack) + obs = envs.reset() + if using_custom_vec_env: + obs = obs.reshape((1,) + obs.shape) + n_done = 0 + last_n_done = 0 + episode_reward=[] + dones = [False for _ in range(num_cpu)] + + for i in range(num_timesteps): + actions=method.getAction(obs,dones) + obs, rewards, dones, _ = envs.step(actions) + if using_custom_vec_env: + obs = obs.reshape((1,) + obs.shape) + if using_custom_vec_env: + if dones: + obs = envs.reset() + obs = obs.reshape((1,) + obs.shape) + + n_done += np.sum(dones) + if (n_done - last_n_done) > 1: + last_n_done = n_done + _, mean_reward = computeMeanReward(log_dir, n_done) + episode_reward.append(mean_reward) + + _, mean_reward = computeMeanReward(log_dir, n_done) + + episode_reward.append(mean_reward) + + episode_reward=np.array(episode_reward) + return episode_reward + + + + +def printEnvTasks(list_env_kwargs,tasks): + """ + A Debugger to verify the env_kwargs have the tasks that we want + :param list_env_kwargs: + :param tasks: + :return: + """ + i=0 + for env_kwargs in list_env_kwargs: + + print("For env kwargs {} and task: {}".format(i,tasks[i])) + print("sc :",env_kwargs['simple_continual_target']) + print("ec :", env_kwargs['eight_continual_move']) + print("sqc:", env_kwargs['square_continual_move']) + print("cc :", env_kwargs['circular_continual_move']) + i+=1 + + +def listEnvs(tasks,env_kwargs,train_args, algo_name, algo_class,model_dir): + # For different tasks, we create a list of envs_kwargs to create different envs + list_envs_kwargs = listEnvsKwargs(tasks, env_kwargs) + log_dirs = [] + environments = [] + algo_args_list = [] + for kwargs in list_envs_kwargs: + log_dir, envs, algo_args = createEnv( model_dir, train_args, algo_name, algo_class, kwargs) + log_dirs.append(log_dir) + environments.append(envs) + algo_args_list.append(algo_args) + return (log_dirs,environments,algo_args_list) + + +def latestPolicy(log_dir,algo_name): + files= glob.glob(os.path.join(log_dir+algo_name+'_*_model.pkl')) + files_list = [] + for file in files: + eps=int((file.split('_')[-2])) + files_list.append((eps,file)) + + def sortFirst(val): + return val[0] + + files_list.sort(key=sortFirst) + if len(files_list)>0: + #episode,latest model file path, OK + return files_list[-1][0],files_list[-1][1],True + else: + #No model saved yet + return 0,'',False + +def policyCrossEval(log_dir,tasks,num_timesteps=2000): + + + train_args, algo_name, algo_class, srl_model_path, env_kwargs = loadConfigAndSetup(log_dir) + + episode, model_path,OK=latestPolicy(log_dir,algo_name) + if(not OK): + #no latest model saved yet + return None, None, False + else: + OK=True + printGreen("Evaluation from the model saved at: {}, with evaluation time steps: {}".format(model_path, num_timesteps)) + + log_dirs, environments, algo_args_list = listEnvs( tasks=tasks, env_kwargs=env_kwargs, + train_args=train_args, algo_name=algo_name, algo_class=algo_class, + model_dir=log_dir) + rewards=[] + + for i in range(len(tasks)): + rewards.append(policyEval(environments[i], model_path, log_dirs[i], algo_class, algo_args_list[i], num_timesteps)) + + + #Just a trick to save the episode number of the reward,but need a little bit more space to store + tmp=rewards[-1].copy() + rewards.append(tmp) + rewards=np.array(rewards) + rewards[-1]=episode + + return rewards, OK + + +''' +The most important function +''' +def episodeEval(log_dir,tasks,save_name='episode_eval.npy'): + #log_dir='logs/OmnirobotEnv-v0/ground_truth/ppo2/19-04-19_14h35_31/' + + file_name=log_dir+save_name + + num_timesteps=1000 + if(os.path.isfile(file_name)): + #print(file_name) + eval_reward=np.load(file_name) + # eval_reward: (np.array) [times of evaluation,number of tasks+1,number of episodes in one evaluation ] + episodes=np.unique(eval_reward[:, -1,: ]) + printRed(episodes) + rewards, ok = policyCrossEval(log_dir, tasks, num_timesteps) + # rewards shape: [number of tasks+1, number of episodes in one evaluation] + + if (ok): + current_episode =np.unique(rewards[-1,:])[0] + #Check if the latest episodes policy is already saved + if (current_episode not in episodes): + eval_reward=np.append(eval_reward,[rewards],axis=0) + np.save(file_name, eval_reward) + else: #There is still not a episodes rewards evaluation registered + rewards, ok = policyCrossEval(log_dir, tasks, num_timesteps) + eval_reward = [] + if(ok): + eval_reward.append(rewards) + eval_reward=np.array(eval_reward) + np.save(file_name, eval_reward) + return diff --git a/rl_baselines/registry.py b/rl_baselines/registry.py index 8fb8824d6..94534fddf 100644 --- a/rl_baselines/registry.py +++ b/rl_baselines/registry.py @@ -12,6 +12,7 @@ from rl_baselines.random_agent import RandomAgentModel from rl_baselines.rl_algorithm.sac import SACModel from rl_baselines.rl_algorithm.trpo import TRPOModel +from rl_baselines.supervised_rl.policy_distillation import PolicyDistillationModel # Register, name: (algo class, algo type, list of action types) registered_rl = { @@ -26,7 +27,8 @@ "ppo2": (PPO2Model, AlgoType.REINFORCEMENT_LEARNING, [ActionType.DISCRETE, ActionType.CONTINUOUS]), "random_agent": (RandomAgentModel, AlgoType.OTHER, [ActionType.DISCRETE, ActionType.CONTINUOUS]), "sac": (SACModel, AlgoType.REINFORCEMENT_LEARNING, [ActionType.CONTINUOUS]), - "trpo": (TRPOModel, AlgoType.REINFORCEMENT_LEARNING, [ActionType.DISCRETE, ActionType.CONTINUOUS]) + "trpo": (TRPOModel, AlgoType.REINFORCEMENT_LEARNING, [ActionType.DISCRETE, ActionType.CONTINUOUS]), + "distillation": (PolicyDistillationModel, AlgoType.REINFORCEMENT_LEARNING, [ActionType.DISCRETE]) } # Checking validity of the registered RL algorithms diff --git a/rl_baselines/supervised_rl/__init__.py b/rl_baselines/supervised_rl/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/rl_baselines/supervised_rl/policy_distillation.py b/rl_baselines/supervised_rl/policy_distillation.py new file mode 100644 index 000000000..895f62d56 --- /dev/null +++ b/rl_baselines/supervised_rl/policy_distillation.py @@ -0,0 +1,257 @@ +import numpy as np +import pickle +import torch as th + +from tqdm import tqdm +from torch import nn +from torch.nn import functional as F + +from rl_baselines.base_classes import BaseRLObject +from rl_baselines.utils import loadRunningAverage, MultiprocessSRLModel, softmax +from srl_zoo.preprocessing.data_loader import SupervisedDataLoader, DataLoader +from srl_zoo.utils import loadData +from state_representation.models import loadSRLModel, getSRLDim +from state_representation.registry import registered_srl, SRLType + +N_WORKERS = 4 +BATCH_SIZE = 32 +TEST_BATCH_SIZE = 256 +VALIDATION_SIZE = 0.2 # 20% of training data for validation +MAX_BATCH_SIZE_GPU = 256 # For plotting, max batch_size before having memory issues +RENDER_HEIGHT = 224 +RENDER_WIDTH = 224 + +class MLP(nn.Module): + def __init__(self, output_size, input_size, hidden_size=400): + super(MLP, self).__init__() + + self.input_size = input_size + self.hidden_size = hidden_size + self.output_size = output_size + + self.fc1 = nn.Linear(self.input_size, self.hidden_size) + self.fc2 = nn.Linear(self.hidden_size, self.hidden_size) + self.fc3 = nn.Linear(self.hidden_size, self.hidden_size) + self.fc4 = nn.Linear(self.hidden_size, self.output_size) + + def forward(self, input): + input=input.view(-1, self.input_size) + + x = F.relu(self.fc1(input)) + x = F.relu(self.fc2(x)) + x = F.relu(self.fc3(x)) + x = F.relu(self.fc4(x)) + return x + + +class PolicyDistillationModel(BaseRLObject): + """ + Implementation of PolicyDistillation + """ + def __init__(self): + super(PolicyDistillationModel, self).__init__() + + def save(self, save_path, _locals=None): + assert self.model is not None, "Error: must train or load model before use" + with open(save_path, "wb") as f: + pickle.dump(self.__dict__, f) + + @classmethod + def load(cls, load_path, args=None): + with open(load_path, "rb") as f: + class_dict = pickle.load(f) + loaded_model = PolicyDistillationModel() + loaded_model.__dict__ = class_dict + + return loaded_model + + def customArguments(self, parser): + parser.add_argument('--nothing4instance', help='Number of population (each one has 2 threads)', type=bool, + default=True) + + return parser + + def getActionProba(self, observation, dones=None, delta=0): + """ + returns the action probability distribution, from a given observation. + :param observation: (numpy int or numpy float) + :param dones: ([bool]) + :param delta: (numpy float or float) The exploration noise applied to the policy, set to 0 for no noise. + :return: (numpy float) + """ + assert self.model is not None, "Error: must train or load model before use" + observation = th.from_numpy(observation).float().requires_grad_(False).to(self.device) + action = self.model.forward(observation).detach().cpu().numpy() + return softmax(action) + + def getAction(self, observation, dones=None, delta=0): + """ + From an observation returns the associated action + :param observation: (numpy int or numpy float) + :param dones: ([bool]) + :param delta: (numpy float or float) The exploration noise applied to the policy, set to 0 for no noise. + :return: (numpy float) + """ + assert self.model is not None, "Error: must train or load model before use" + + self.model.eval() + observation = th.from_numpy(observation).float().requires_grad_(False).to(self.device) + return [np.argmax(self.model.forward(observation).detach().cpu().numpy())] + + def loss_fn_kd(self, outputs, labels, teacher_outputs): + """ + inspired from : https://github.com/peterliht/knowledge-distillation-pytorch + Compute the knowledge-distillation (KD) loss given outputs, labels. + NOTE: the KL Divergence for PyTorch comparing the softmaxs of teacher + and student expects the input tensor to be log probabilities! See Issue #2 + + Hyperparameters: temperature and alpha + :param outputs: output from the student model + :param labels: label + :param teacher_outputs: output from the teacher_outputs model + :return: loss + """ + return nn.MSELoss()(outputs, teacher_outputs) + + def train(self, args, callback, env_kwargs=None, train_kwargs=None): + + N_EPOCHS = args.epochs_distillation + self.seed = args.seed + self.batch_size = BATCH_SIZE + print("We assumed SRL training already done") + + print('Loading data for distillation ') + training_data, ground_truth, true_states, _ = loadData(args.teacher_data_folder, absolute_path=True) + rewards, episode_starts = training_data['rewards'], training_data['episode_starts'] + + images_path = ground_truth['images_path'] + actions = training_data['actions'] + actions_proba = training_data['actions_proba'] + + if args.distillation_training_set_size > 0: + limit = args.distillation_training_set_size + actions = actions[:limit] + images_path = images_path[:limit] + episode_starts = episode_starts[:limit] + + images_path_copy = ["srl_zoo/data/" + images_path[k] for k in range(images_path.shape[0])] + images_path = np.array(images_path_copy) + + num_samples = images_path.shape[0] - 1 # number of samples + + # indices for all time steps where the episode continues + indices = np.array([i for i in range(num_samples) if not episode_starts[i + 1]], dtype='int64') + np.random.shuffle(indices) + + # split indices into minibatches. minibatchlist is a list of lists; each + # list is the id of the observation preserved through the training + minibatchlist = [np.array(sorted(indices[start_idx:start_idx + self.batch_size])) + for start_idx in range(0, len(indices) - self.batch_size + 1, self.batch_size)] + data_loader = DataLoader(minibatchlist, images_path, n_workers=N_WORKERS, multi_view=False, + use_triplets=False, is_training=True, absolute_path=True) + + test_minibatchlist = DataLoader.createTestMinibatchList(len(images_path), MAX_BATCH_SIZE_GPU) + test_data_loader = DataLoader(test_minibatchlist, images_path, n_workers=N_WORKERS, multi_view=False, + use_triplets=False, max_queue_len=1, is_training=False, absolute_path=True) + + # Number of minibatches used for validation: + n_val_batches = np.round(VALIDATION_SIZE * len(minibatchlist)).astype(np.int64) + val_indices = np.random.permutation(len(minibatchlist))[:n_val_batches] + # Print some info + print("{} minibatches for training, {} samples".format(len(minibatchlist) - n_val_batches, + (len(minibatchlist) - n_val_batches) * BATCH_SIZE)) + print("{} minibatches for validation, {} samples".format(n_val_batches, n_val_batches * BATCH_SIZE)) + assert n_val_batches > 0, "Not enough sample to create a validation set" + + # Stats about actions + if not args.continuous_actions: + print('Discrete action space:') + action_set = set(actions) + n_actions = int(np.max(actions) + 1) + print("{} unique actions / {} actions".format(len(action_set), n_actions)) + n_pairs_per_action = np.zeros(n_actions, dtype=np.int64) + n_obs_per_action = np.zeros(n_actions, dtype=np.int64) + for i in range(n_actions): + n_obs_per_action[i] = np.sum(actions == i) + + print("Number of observations per action") + print(n_obs_per_action) + + else: + print('Continuous action space:') + print('Action dimension: {}'.format(self.dim_action)) + + # Here the default SRL model is assumed to be raw_pixels + self.state_dim = RENDER_HEIGHT *RENDER_WIDTH + self.srl_model = None + + # TODO: add sanity checks & test for all possible SRL for distillation + if env_kwargs["srl_model"] is "raw_pixels": + self.state_dim = getSRLDim(env_kwargs.get("srl_model_path", None)) + self.srl_model = loadSRLModel(env_kwargs.get("srl_model_path", None), + th.cuda.is_available(), self.state_dim, env_object=None) + self.device = th.device("cuda" if th.cuda.is_available() else "cpu") + + self.model = MLP(input_size=self.state_dim, hidden_size=400, output_size=n_actions) + if th.cuda.is_available(): + self.model.cuda() + + learnable_params = [param for param in self.model.parameters() if param.requires_grad] + self.optimizer = th.optim.Adam(learnable_params, lr=1e-3) + + best_error = np.inf + best_model_path = "{}/distillation_model.pkl".format(args.log_dir) + + for epoch in range(N_EPOCHS): + # In each epoch, we do a full pass over the training data: + epoch_loss, epoch_batches = 0, 0 + val_loss = 0 + pbar = tqdm(total=len(minibatchlist)) + + for minibatch_num, (minibatch_idx, obs, _, _, _) in enumerate(data_loader): + + obs = obs.to(self.device) + validation_mode = minibatch_idx in val_indices + if validation_mode: + self.model.eval() + else: + self.model.train() + + # Actions associated to the observations of the current minibatch + actions_st = actions[minibatchlist[minibatch_idx]] + actions_proba_st = actions_proba[minibatchlist[minibatch_idx]] + + if not args.continuous_actions: + # Discrete actions, rearrange action to have n_minibatch ligns and one column, + # containing the int action + actions_st = th.from_numpy(actions_st).requires_grad_(False).to(self.device) + actions_proba_st = th.from_numpy(actions_proba_st).requires_grad_(False).to(self.device) + else: + # Continuous actions, rearrange action to have n_minibatch ligns and dim_action columns + actions_st = th.from_numpy(actions_st).view(-1, self.dim_action).requires_grad_(False).to( + self.device) + + state = obs if self.srl_model is None else self.srl_model.model.getStates(obs).to(self.device).detach() + pred_action = self.model(state) + self.optimizer.zero_grad() + loss = self.loss_fn_kd(pred_action, actions_st, actions_proba_st) + + loss.backward() + if validation_mode: + val_loss += loss.item() + # We do not optimize on validation data + # so optimizer.step() is not called + else: + self.optimizer.step() + epoch_loss += loss.item() + epoch_batches += 1 + pbar.update(1) + train_loss = epoch_loss / float(epoch_batches) + val_loss /= float(n_val_batches) + pbar.close() + print("Epoch {:3}/{}, train_loss:{:.4f} val_loss:{:.4f}".format(epoch + 1, N_EPOCHS, train_loss, val_loss)) + + # Save best model + if val_loss < best_error: + best_error = val_loss + self.save(best_model_path) diff --git a/rl_baselines/train.py b/rl_baselines/train.py index f28c5182c..ff37c0e50 100644 --- a/rl_baselines/train.py +++ b/rl_baselines/train.py @@ -20,7 +20,8 @@ from rl_baselines.registry import registered_rl from rl_baselines.utils import computeMeanReward from rl_baselines.utils import filterJSONSerializableObjects -from rl_baselines.visualize import timestepsPlot, episodePlot +from rl_baselines.visualize import timestepsPlot, episodePlot,episodesEvalPlot +from rl_baselines.cross_eval import episodeEval,policyCrossEval from srl_zoo.utils import printGreen, printYellow from state_representation import SRLType from state_representation.registry import registered_srl @@ -33,6 +34,8 @@ ENV_NAME = "" PLOT_TITLE = "" EPISODE_WINDOW = 40 # For plotting moving average +EVAL_TASK=['cc','sc','sqc'] + viz = None n_steps = 0 SAVE_INTERVAL = 0 # initialised during loading of the algorithm @@ -41,7 +44,7 @@ params_saved = False best_mean_reward = -10000 -win, win_smooth, win_episodes = None, None, None +win, win_smooth, win_episodes, win_crossEval= None, None, None, None os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' # used to remove debug info of tensorflow @@ -78,7 +81,7 @@ def configureEnvAndLogFolder(args, env_kwargs, all_models): env_kwargs["shape_reward"] = args.shape_reward # Actions in joint space or relative position space env_kwargs["action_joints"] = args.action_joints - args.log_dir += ENV_NAME + "/" + args.log_dir += args.env + "/" models = all_models[args.env] PLOT_TITLE = args.srl_model @@ -120,7 +123,7 @@ def callback(_locals, _globals): :param _locals: (dict) :param _globals: (dict) """ - global win, win_smooth, win_episodes, n_steps, viz, params_saved, best_mean_reward + global win, win_smooth, win_episodes, win_crossEval,n_steps, viz, params_saved, best_mean_reward # Create vizdom object only if needed if viz is None: viz = Visdom(port=VISDOM_PORT) @@ -163,6 +166,11 @@ def callback(_locals, _globals): best_mean_reward = mean_reward printGreen("Saving new best model") ALGO.save(LOG_DIR + ALGO_NAME + "_model.pkl", _locals) + if n_episodes >0 and n_episodes%20==0: + # Cross evaluation for all tasks: + ALGO.save(LOG_DIR + ALGO_NAME +"_"+str(n_episodes)+ "_model.pkl", _locals) + printYellow(EVAL_TASK) + episodeEval(LOG_DIR, EVAL_TASK) # Plots in visdom if viz and (n_steps + 1) % LOG_INTERVAL == 0: @@ -171,6 +179,8 @@ def callback(_locals, _globals): is_es=is_es) win_episodes = episodePlot(viz, win_episodes, LOG_DIR, ENV_NAME, ALGO_NAME, window=EPISODE_WINDOW, title=PLOT_TITLE + " [Episodes]", is_es=is_es) + win_crossEval= episodesEvalPlot(viz,win_crossEval,LOG_DIR,ENV_NAME,EVAL_TASK, + title=PLOT_TITLE +" [Cross Evaluation]") n_steps += 1 return True @@ -225,7 +235,15 @@ def main(): parser.add_argument('-ec', '--eight-continual', action='store_true', default=False, help='Green square target for task 4 of continual learning scenario. ' + 'The task is: robot should do the eigth with the target as center of the shape.') - + parser.add_argument('--teacher-data-folder', type=str, default="", + help='Dataset folder of the teacher(s) policy(ies)') + parser.add_argument('--epochs-distillation', type=int, default=30, metavar='N', + help='number of epochs to train for distillation(default: 30)') + parser.add_argument('--distillation-training-set-size', type=int, default=-1, + help='Limit size (number of samples) of the training set (default: -1)') + parser.add_argument('--eval-tasks', type=str, nargs='+', default=['cc','sqc','sc'], + help='A cross evaluation from the latest stored model to all tasks') + # Ignore unknown args for now args, unknown = parser.parse_known_args() env_kwargs = {} @@ -258,20 +276,16 @@ def main(): <= 1 and args.env == "OmnirobotEnv-v0", \ "For continual SRL and RL, please provide only one scenario at the time and use OmnirobotEnv-v0 environment !" + assert not(args.algo == "distillation" and (args.teacher_data_folder == '' or args.continuous_actions is True)), \ + "For performing policy distillation, make sure use specify a valid teacher dataset and discrete actions !" + ENV_NAME = args.env - if(args.circular_continual): - ENV_NAME+="-cc" - if(args.eight_continual): - ENV_NAME+="-ec" - if(args.simple_continual): - ENV_NAME+="-sc" - if(args.square_continual): - ENV_NAME+="-sqc" ALGO_NAME = args.algo VISDOM_PORT = args.port EPISODE_WINDOW = args.episode_window MIN_EPISODES_BEFORE_SAVE = args.min_episodes_save + if args.no_vis: viz = False @@ -280,7 +294,6 @@ def main(): ALGO = algo - # if callback frequency needs to be changed LOG_INTERVAL = algo.LOG_INTERVAL SAVE_INTERVAL = algo.SAVE_INTERVAL @@ -363,7 +376,8 @@ def main(): hyperparams["learning_rate"] = lambda f: f * 1.0e-4 # Train the agent - + # episodeEval(LOG_DIR,EVAL_TASK) + # return if args.load_rl_model_path is not None: algo.setLoadPath(args.load_rl_model_path) algo.train(args, callback, env_kwargs=env_kwargs, train_kwargs=hyperparams) diff --git a/rl_baselines/visualize.py b/rl_baselines/visualize.py index 16b308105..3bce727b1 100644 --- a/rl_baselines/visualize.py +++ b/rl_baselines/visualize.py @@ -213,3 +213,39 @@ def timestepsPlot(viz, win, folder, game, name, bin_size=100, smooth=1, title="" "legend": [name] } return viz.line(ty, tx, win=win, opts=opts) + +def episodesEvalPlot(viz, win, folder, game, name, window=1, title=""): + + folder+='episode_eval.npy' + if(os.path.isfile(folder)): + result = np.load(folder) + else: + return win + + if len(result) == 0: + return win + + + y = np.mean(result[:,:-1,:], axis=2) + + x = result[:, -1,:][:,0][:,None] + x = x*np.ones(shape=y.shape) + print(y.shape,x.shape,name) + + if y.shape[0] < window: + return win + + # y = movingAverage(y, window) + + if len(y) == 0: + return win + + + opts = { + "title": "{}\n{}".format(game, title), + "xlabel": "Episodes", + "ylabel": "Rewards", + "legend": name + } + + return viz.line(y, x, win=win, opts=opts) \ No newline at end of file From 9cace2145f33832ceaa44d4dfa759109d5b4f5b7 Mon Sep 17 00:00:00 2001 From: kalifou Date: Tue, 23 Apr 2019 15:19:30 +0200 Subject: [PATCH 042/141] fix for distillation from raw_pixels --- .../supervised_rl/policy_distillation.py | 47 +++++++++++++------ 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/rl_baselines/supervised_rl/policy_distillation.py b/rl_baselines/supervised_rl/policy_distillation.py index 887ac1b53..de98a9f81 100644 --- a/rl_baselines/supervised_rl/policy_distillation.py +++ b/rl_baselines/supervised_rl/policy_distillation.py @@ -7,11 +7,10 @@ from torch.nn import functional as F from rl_baselines.base_classes import BaseRLObject -from rl_baselines.utils import loadRunningAverage, MultiprocessSRLModel, softmax +from srl_zoo.models.models import CustomCNN from srl_zoo.preprocessing.data_loader import SupervisedDataLoader, DataLoader from srl_zoo.utils import loadData from state_representation.models import loadSRLModel, getSRLDim -from state_representation.registry import registered_srl, SRLType N_WORKERS = 4 BATCH_SIZE = 32 @@ -21,9 +20,10 @@ RENDER_HEIGHT = 224 RENDER_WIDTH = 224 -class MLP(nn.Module): + +class MLPPolicy(nn.Module): def __init__(self, output_size, input_size, hidden_size=400): - super(MLP, self).__init__() + super(MLPPolicy, self).__init__() self.input_size = input_size self.hidden_size = hidden_size @@ -40,10 +40,19 @@ def forward(self, input): x = F.relu(self.fc1(input)) x = F.relu(self.fc2(x)) x = F.relu(self.fc3(x)) - x = F.relu(self.fc4(x)) + x = F.softmax(self.fc4(x), dim=1) return x +class CNNPolicy(nn.Module): + def __init__(self, output_size): + super(CNNPolicy, self).__init__() + self.model = CustomCNN(state_dim=output_size) + + def forward(self, input): + return F.softmax(self.model(input), dim=1) + + class PolicyDistillationModel(BaseRLObject): """ Implementation of PolicyDistillation @@ -80,9 +89,11 @@ def getActionProba(self, observation, dones=None, delta=0): :return: (numpy float) """ assert self.model is not None, "Error: must train or load model before use" + if len(observation.shape) > 2: + observation = np.transpose(observation, (0, 3, 2, 1)) observation = th.from_numpy(observation).float().requires_grad_(False).to(self.device) action = self.model.forward(observation).detach().cpu().numpy() - return softmax(action) + return action #softmax(action) def getAction(self, observation, dones=None, delta=0): """ @@ -95,6 +106,8 @@ def getAction(self, observation, dones=None, delta=0): assert self.model is not None, "Error: must train or load model before use" self.model.eval() + if len(observation.shape) > 2: + observation = np.transpose(observation, (0, 3, 2, 1)) observation = th.from_numpy(observation).float().requires_grad_(False).to(self.device) return [np.argmax(self.model.forward(observation).detach().cpu().numpy())] @@ -111,7 +124,7 @@ def loss_fn_kd(self, outputs, labels, teacher_outputs): :param teacher_outputs: output from the teacher_outputs model :return: loss """ - return nn.MSELoss()(outputs, teacher_outputs) + return (outputs - teacher_outputs).pow(2).sum(1).mean() def train(self, args, callback, env_kwargs=None, train_kwargs=None): @@ -186,17 +199,20 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): self.srl_model = None # TODO: add sanity checks & test for all possible SRL for distillation - if env_kwargs["srl_model"] != "raw_pixels": + if env_kwargs["srl_model"] == "raw_pixels": + self.model = CNNPolicy(n_actions) + else: self.state_dim = getSRLDim(env_kwargs.get("srl_model_path", None)) self.srl_model = loadSRLModel(env_kwargs.get("srl_model_path", None), th.cuda.is_available(), self.state_dim, env_object=None) + self.model = MLPPolicy(n_actions, self.state_dim) + self.device = th.device("cuda" if th.cuda.is_available() else "cpu") - self.model = MLP(n_actions, self.state_dim, hidden_size=400) if th.cuda.is_available(): self.model.cuda() - learnable_params = [param for param in self.model.parameters() if param.requires_grad] + learnable_params = self.model.parameters() self.optimizer = th.optim.Adam(learnable_params, lr=1e-3) best_error = np.inf @@ -231,10 +247,11 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): actions_st = th.from_numpy(actions_st).view(-1, self.dim_action).requires_grad_(False).to( self.device) - state = obs.detach() if self.srl_model is None else self.srl_model.model.getStates(obs).to(self.device).detach() - pred_action = self.model(state) - self.optimizer.zero_grad() - loss = self.loss_fn_kd(pred_action, actions_st, actions_proba_st.float()) + state = obs.detach() if self.srl_model is None \ + else self.srl_model.model.getStates(obs).to(self.device).detach() + pred_action = self.model.forward(state) + + loss = self.loss_fn_kd(pred_action, actions_st, actions_proba_st) loss.backward() if validation_mode: @@ -246,6 +263,8 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): epoch_loss += loss.item() epoch_batches += 1 pbar.update(1) + self.optimizer.zero_grad() + train_loss = epoch_loss / float(epoch_batches) val_loss /= float(n_val_batches) pbar.close() From dd8cba7147e7f60204f42bbe7631e8eae5fe0937 Mon Sep 17 00:00:00 2001 From: kalifou Date: Wed, 24 Apr 2019 10:37:26 +0200 Subject: [PATCH 043/141] fix data fusioner --- environments/dataset_fusioner.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/environments/dataset_fusioner.py b/environments/dataset_fusioner.py index fe8bad59a..2e6d7e532 100644 --- a/environments/dataset_fusioner.py +++ b/environments/dataset_fusioner.py @@ -102,11 +102,19 @@ def main(): for prepro_load in [preprocessed_load, preprocessed_load_2]: for arr in prepro_load.files: pr_arr = prepro_load[arr] - preprocessed[arr] = np.concatenate((preprocessed.get(arr, np.zeros(pr_arr.shape)), pr_arr), axis=0) + + to_class = None if arr == "episode_starts": - preprocessed[arr] = preprocessed[arr].astype(bool) + to_class = bool + elif arr == "actions_proba": + to_class = float + else: + to_class = int + if preprocessed.get(arr, None) is None: + preprocessed[arr] = pr_arr.astype(to_class) else: - preprocessed[arr] = preprocessed[arr].astype(int) + preprocessed[arr] = np.concatenate((preprocessed[arr].astype(to_class), + pr_arr.astype(to_class)), axis=0) np.savez(args.merge[2] + "/preprocessed_data.npz", ** preprocessed) From 6e865aafbf840607bcbb130e3f9762df82242307 Mon Sep 17 00:00:00 2001 From: kalifou Date: Wed, 24 Apr 2019 10:38:37 +0200 Subject: [PATCH 044/141] Option for generating shorter episodes (SC) and fix --- environments/dataset_generator.py | 5 ++++- environments/omnirobot_gym/omnirobot_env.py | 14 +++++++++----- .../omnirobot_utils/omnirobot_manager_base.py | 3 +-- rl_baselines/supervised_rl/policy_distillation.py | 4 +--- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/environments/dataset_generator.py b/environments/dataset_generator.py index fa7e2468e..e75937281 100644 --- a/environments/dataset_generator.py +++ b/environments/dataset_generator.py @@ -79,7 +79,8 @@ def env_thread(args, thread_num, partition=True): "shape_reward": args.shape_reward, "simple_continual_target": args.simple_continual, "circular_continual_move": args.circular_continual, - "square_continual_move": args.square_continual + "square_continual_move": args.square_continual, + "short_episodes": args.short_episodes } if partition: @@ -252,6 +253,8 @@ def main(): parser.add_argument('-sqc', '--square-continual', action='store_true', default=False, help='Green square target for task 3 of continual learning scenario. ' + 'The task is: robot should turn in square around the target.') + parser.add_argument('--short-episodes', action='store_true', default=False, + help='Generate short episodes (only 10 contacts with the target allowed).') args = parser.parse_args() diff --git a/environments/omnirobot_gym/omnirobot_env.py b/environments/omnirobot_gym/omnirobot_env.py index 9df8cf927..7f08df70e 100644 --- a/environments/omnirobot_gym/omnirobot_env.py +++ b/environments/omnirobot_gym/omnirobot_env.py @@ -29,7 +29,7 @@ def recvMatrix(socket): RENDER_HEIGHT = 224 RENDER_WIDTH = 224 RELATIVE_POS = True -N_CONTACTS_BEFORE_TERMINATION = 3 +N_CONTACTS_BEFORE_TERMINATION = 10 DELTA_POS = 0.1 # DELTA_POS for continuous actions N_DISCRETE_ACTIONS = 4 @@ -73,7 +73,8 @@ class OmniRobotEnv(SRLGymEnv): def __init__(self, renders=False, name="Omnirobot", is_discrete=True, save_path='srl_zoo/data/', state_dim=-1, learn_states=False, srl_model="raw_pixels", record_data=False, action_repeat=1, random_target=True, shape_reward=False, simple_continual_target=False, circular_continual_move=False, - square_continual_move=False, eight_continual_move=False, env_rank=0, srl_pipe=None, **_): + square_continual_move=False, eight_continual_move=False, short_episodes=False, env_rank=0, + srl_pipe=None, **_): super(OmniRobotEnv, self).__init__(srl_model=srl_model, relative_pos=RELATIVE_POS, @@ -106,6 +107,7 @@ def __init__(self, renders=False, name="Omnirobot", is_discrete=True, save_path= self.circular_continual_move = circular_continual_move self.square_continual_move = square_continual_move self.eight_continual_move = eight_continual_move + self.short_episodes = short_episodes if self._is_discrete: self.action_space = spaces.Discrete(N_DISCRETE_ACTIONS) @@ -301,13 +303,14 @@ def _hasEpisodeTerminated(self): """ Returns True if the episode is over and False otherwise """ - if self.episode_terminated or self._env_step_counter > MAX_STEPS: + if self.episode_terminated or self._env_step_counter > MAX_STEPS or \ + (self.n_contacts >= N_CONTACTS_BEFORE_TERMINATION and self.short_episodes): return True if np.abs(self.reward - REWARD_TARGET_REACH) < 0.000001: # reach the target self.n_contacts += 1 else: - self.n_contacts = 0 + self.n_contacts += 0 return False def closeServerConnection(self): @@ -450,7 +453,8 @@ def visualizeBoundary(self): tuple(self.boundary_coner_pixel_pos_continual[:,0]),(0,0,200),2) elif self.circular_continual_move: radius_converted = np.linalg.norm(self.center_coordinates - self.boundary_coner_pixel_pos_continual) - cv2.circle(self.observation_with_boundary, tuple(self.center_coordinates), np.float32(radius_converted), (0,0,200),2) + cv2.circle(self.observation_with_boundary, tuple(self.center_coordinates), np.float32(radius_converted), + (0, 0, 200), 2) #Add boundary of env cv2.line(self.observation_with_boundary, tuple(self.boundary_coner_pixel_pos[:, 0]), diff --git a/real_robots/omnirobot_utils/omnirobot_manager_base.py b/real_robots/omnirobot_utils/omnirobot_manager_base.py index 8ce30a9a8..ddc5d2ead 100644 --- a/real_robots/omnirobot_utils/omnirobot_manager_base.py +++ b/real_robots/omnirobot_utils/omnirobot_manager_base.py @@ -102,7 +102,6 @@ def resetEpisode(self): random_init_position = self.sampleRobotInitalPosition() self.robot.setRobotCmd(random_init_position[0], random_init_position[1], 0) - def processMsg(self, msg): """ Using this steps' msg command the determinate the correct position that the robot should be at next step, @@ -146,7 +145,7 @@ def processMsg(self, msg): has_bumped = self.backwardAction() elif action == 'Continuous': has_bumped = self.moveContinousAction(msg) - elif action == None: + elif action is None: pass else: print("Unsupported action: ", action) diff --git a/rl_baselines/supervised_rl/policy_distillation.py b/rl_baselines/supervised_rl/policy_distillation.py index de98a9f81..9d4dbf3b6 100644 --- a/rl_baselines/supervised_rl/policy_distillation.py +++ b/rl_baselines/supervised_rl/policy_distillation.py @@ -182,7 +182,6 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): action_set = set(actions) n_actions = int(np.max(actions) + 1) print("{} unique actions / {} actions".format(len(action_set), n_actions)) - n_pairs_per_action = np.zeros(n_actions, dtype=np.int64) n_obs_per_action = np.zeros(n_actions, dtype=np.int64) for i in range(n_actions): n_obs_per_action[i] = np.sum(actions == i) @@ -250,8 +249,7 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): state = obs.detach() if self.srl_model is None \ else self.srl_model.model.getStates(obs).to(self.device).detach() pred_action = self.model.forward(state) - - loss = self.loss_fn_kd(pred_action, actions_st, actions_proba_st) + loss = self.loss_fn_kd(pred_action, actions_st, actions_proba_st.float()) loss.backward() if validation_mode: From 87978847a9611b0df63babe57897466092059737 Mon Sep 17 00:00:00 2001 From: TLESORT Date: Wed, 24 Apr 2019 14:29:15 +0200 Subject: [PATCH 045/141] command for distillation readme updated --- Distilation_Readme.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Distilation_Readme.md b/Distilation_Readme.md index ef804a236..b136367f3 100644 --- a/Distilation_Readme.md +++ b/Distilation_Readme.md @@ -13,20 +13,20 @@ ### 0 - Generate datasets for SRL (random policy) ``` -cd srl_zoo # Dataset 1 -python -m environments.dataset_generator --num-cpu 6 --name Omnibot_circular --env OmnirobotEnv-v0 --simple-continual --num-episode 250 +python -m environments.dataset_generator --num-cpu 6 --name Omnibot_circular --env OmnirobotEnv-v0 --simple-continual --num-episode 250 -f # Dataset 2 -python -m environments.dataset_generator --num-cpu 6 --name Omnibot_random_simple --env OmnirobotEnv-v0 --circular-continual --num-episode 250 +python -m environments.dataset_generator --num-cpu 6 --name Omnibot_random_simple --env OmnirobotEnv-v0 --circular-continual --num-episode 250 -f ``` ### 1.1) Train SRL ``` +cd srl_zoo # Dataset 1 -python train.py --data-folder data/simple-continual -bs 32 --epochs 30 --state-dim 200 --training-set-size 30000 --losses autoencoder inverse +python train.py --data-folder data/Omnibot_random_simple -bs 32 --epochs 30 --state-dim 200 --training-set-size 30000 --losses autoencoder inverse # Dataset 2 -python train.py --data-folder data/circular-continual -bs 32 --epochs 30 --state-dim 200 --training-set-size 30000 --losses autoencoder inverse +python train.py --data-folder data/Omnibot_circular -bs 32 --epochs 30 --state-dim 200 --training-set-size 30000 --losses autoencoder inverse ``` @@ -52,9 +52,9 @@ python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --num-times ``` # Dataset 1 -python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 50 --num-cpu 8 --run-policy custom --log-custom-policy logs/simple-continual +python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 50 --num-cpu 8 --run-policy custom --log-custom-policy logs/simple-continual -f # Dataset 2 -python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 50 --num-cpu 8 --run-policy custom --log-custom-policy logs/circular-continual +python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 50 --num-cpu 8 --run-policy custom --log-custom-policy logs/circular-continual -f # Merge Datasets ? @@ -76,5 +76,5 @@ python train.py --data-folder data/circular_continual_on_policy -bs 32 --epochs # Dataset 1 python -m rl_baselines.train --algo distillation --srl-model srl_combination --num-timesteps 1000000 --env OmnirobotEnv-v0 --log-dir logs/simple/ --simple-continual --latest --teacher-data-folder srl_zoo/data/simple_continual_on_policy/ # Dataset 2 -python -m rl_baselines.train --algo distillation --srl-model srl_combination --num-timesteps 1000000 --env OmnirobotEnv-v0 --log-dir logs/circular/ --circular-continual --latest --teacher-data-folder srl_zoo/data/circular_continual_on_policy/ +python -m rl_baselines.train --algo distillation --srl-model srl_combination --num-timesteps 1000000 --env OmnirobotEnv-v0 --log-dir logs/circularOmnirobotEnv-v0/OmnirobotEnv-v0/ --circular-continual --latest --teacher-data-folder srl_zoo/data/circular_continual/ ``` From 159947fa51f54732d6e97d384f0a0e6129d663b7 Mon Sep 17 00:00:00 2001 From: TLESORT Date: Wed, 24 Apr 2019 14:46:02 +0200 Subject: [PATCH 046/141] command for distillation readme updated --- Distilation_Readme.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Distilation_Readme.md b/Distilation_Readme.md index b136367f3..d054c1031 100644 --- a/Distilation_Readme.md +++ b/Distilation_Readme.md @@ -24,9 +24,9 @@ python -m environments.dataset_generator --num-cpu 6 --name Omnibot_random_simpl ``` cd srl_zoo # Dataset 1 -python train.py --data-folder data/Omnibot_random_simple -bs 32 --epochs 30 --state-dim 200 --training-set-size 30000 --losses autoencoder inverse +python train.py --data-folder data/Omnibot_random_simple -bs 32 --num-cpu 6 --epochs 30 --state-dim 200 --training-set-size 30000 --losses autoencoder inverse # Dataset 2 -python train.py --data-folder data/Omnibot_circular -bs 32 --epochs 30 --state-dim 200 --training-set-size 30000 --losses autoencoder inverse +python train.py --data-folder data/Omnibot_circular -bs 32 --num-cpu 6 --epochs 30 --state-dim 200 --training-set-size 30000 --losses autoencoder inverse ``` @@ -52,9 +52,9 @@ python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --num-times ``` # Dataset 1 -python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 50 --num-cpu 8 --run-policy custom --log-custom-policy logs/simple-continual -f +python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 50 --num-cpu 6 --run-policy custom --log-custom-policy logs/simple-continual -f # Dataset 2 -python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 50 --num-cpu 8 --run-policy custom --log-custom-policy logs/circular-continual -f +python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 50 --num-cpu 6 --run-policy custom --log-custom-policy logs/circular-continual -f # Merge Datasets ? From 8ddd31793aeb1a7777f57b1d358e1d75991648fe Mon Sep 17 00:00:00 2001 From: Caselles Date: Wed, 24 Apr 2019 15:05:46 +0200 Subject: [PATCH 047/141] loss MSE for distillation --- rl_baselines/supervised_rl/policy_distillation.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/rl_baselines/supervised_rl/policy_distillation.py b/rl_baselines/supervised_rl/policy_distillation.py index d99598847..2cb8138e7 100644 --- a/rl_baselines/supervised_rl/policy_distillation.py +++ b/rl_baselines/supervised_rl/policy_distillation.py @@ -126,9 +126,8 @@ def loss_fn_kd(self, outputs, teacher_outputs): return (outputs - teacher_outputs).pow(2).sum(1).mean() def loss_mse(self, outputs, teacher_outputs): - MSELoss = nn.MSELoss()(outputs, teacher_outputs) - - return MSELoss + #MSELoss = nn.MSELoss()(outputs, teacher_outputs) + return (outputs - teacher_outputs).pow(2).sum(1).mean() def train(self, args, callback, env_kwargs=None, train_kwargs=None): From 570251dd2e22e507b20b3ff1ebd41b522f8b737c Mon Sep 17 00:00:00 2001 From: kalifou Date: Wed, 24 Apr 2019 15:23:26 +0200 Subject: [PATCH 048/141] Update Readme for distillation --- Distilation_Readme.md | 52 +++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/Distilation_Readme.md b/Distilation_Readme.md index d054c1031..00b8ae76a 100644 --- a/Distilation_Readme.md +++ b/Distilation_Readme.md @@ -13,20 +13,21 @@ ### 0 - Generate datasets for SRL (random policy) ``` -# Dataset 1 -python -m environments.dataset_generator --num-cpu 6 --name Omnibot_circular --env OmnirobotEnv-v0 --simple-continual --num-episode 250 -f -# Dataset 2 -python -m environments.dataset_generator --num-cpu 6 --name Omnibot_random_simple --env OmnirobotEnv-v0 --circular-continual --num-episode 250 -f +cd srl_zoo +# Dataset 1 (random reaching target) +python -m environments.dataset_generator --num-cpu 6 --name Omnibot_circular --env OmnirobotEnv-v0 --simple-continual --num-episode 250 +# Dataset 2 (Circular task) +python -m environments.dataset_generator --num-cpu 6 --name Omnibot_random_simple --env OmnirobotEnv-v0 --circular-continual --num-episode 250 ``` ### 1.1) Train SRL ``` cd srl_zoo -# Dataset 1 -python train.py --data-folder data/Omnibot_random_simple -bs 32 --num-cpu 6 --epochs 30 --state-dim 200 --training-set-size 30000 --losses autoencoder inverse -# Dataset 2 -python train.py --data-folder data/Omnibot_circular -bs 32 --num-cpu 6 --epochs 30 --state-dim 200 --training-set-size 30000 --losses autoencoder inverse +# Dataset 1 (random reaching target) +python train.py --data-folder data/simple-continual -bs 32 --epochs 30 --state-dim 200 --training-set-size 30000 --losses autoencoder inverse +# Dataset 2 (Circular task) +python train.py --data-folder data/circular-continual -bs 32 --epochs 30 --state-dim 200 --training-set-size 30000 --losses autoencoder inverse ``` @@ -35,15 +36,13 @@ python train.py --data-folder data/Omnibot_circular -bs 32 --num-cpu 6 --epochs ``` cd .. -# Dataset 1 +# Dataset 1 (random reaching target) python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --num-timesteps 1000000 --env OmnirobotEnv-v0 --log-dir logs/circular/ --num-cpu 8 --simple-continual --latest -# Dataset 2 +# Dataset 2 (Circular task) python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --num-timesteps 1000000 --env OmnirobotEnv-v0 --log-dir logs/circular/ --num-cpu 8 --circular-continual --latest ``` - - # 2 - Train Distillation @@ -51,30 +50,35 @@ python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --num-times ``` -# Dataset 1 -python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 50 --num-cpu 6 --run-policy custom --log-custom-policy logs/simple-continual -f -# Dataset 2 -python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 50 --num-cpu 6 --run-policy custom --log-custom-policy logs/circular-continual -f +# Dataset 1 (random reaching target) +python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 600 --run-policy custom --log-custom-policy logs/simple-continual --short-episodes --save-path data/ --name reaching_on_policy -sc + +# Dataset 2 (Circular task) +python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 100 --run-policy custom --log-custom-policy logs/circular-continual --save-path data/ --name circular_on_policy -cc + # Merge Datasets +python -m environments.dataset_fusioner --merge data/circular_on_policy/ data/reaching_on_policy/ data/merge_CC_SC -? +# Copy the merged Dataset to srl_zoo repository +cp -r data/merge_CC_SC srl_zoo/data/merge_CC_SC ``` ### 2.3) Train SRL 1&2 ``` # Dataset 1 -python train.py --data-folder data/simple_continual_on_policy -bs 32 --epochs 2 --state-dim 200 --training-set-size 3000 --losses autoencoder inverse -# Dataset 2 -python train.py --data-folder data/circular_continual_on_policy -bs 32 --epochs 2 --state-dim 200 --training-set-size 3000 --losses autoencoder inverse +python train.py --data-folder data/merge_CC_SC -bs 32 --epochs 2 --state-dim 200 --training-set-size 30000--losses autoencoder inverse + +# Update your RL logs to load the proper SRL model for future distillation, i.e distillation: new-log/srl_model.pth ``` ### 2.3) Run Distillation ``` -# Dataset 1 -python -m rl_baselines.train --algo distillation --srl-model srl_combination --num-timesteps 1000000 --env OmnirobotEnv-v0 --log-dir logs/simple/ --simple-continual --latest --teacher-data-folder srl_zoo/data/simple_continual_on_policy/ -# Dataset 2 -python -m rl_baselines.train --algo distillation --srl-model srl_combination --num-timesteps 1000000 --env OmnirobotEnv-v0 --log-dir logs/circularOmnirobotEnv-v0/OmnirobotEnv-v0/ --circular-continual --latest --teacher-data-folder srl_zoo/data/circular_continual/ +# make a new log folder +mkdir logs/CL_SC_CC + +# Merged Dataset +python -m rl_baselines.train --algo distillation --srl-model srl_combination --env OmnirobotEnv-v0 --log-dir logs/CL_SC_CC --teacher-data-folder srl_zoo/data/merge_CC_SC -cc --distillation-training-set-size 40000 --epochs-distillation 20 ``` From db434a58c6dd9622de1a336f5771adcc3d597e93 Mon Sep 17 00:00:00 2001 From: Caselles Date: Wed, 24 Apr 2019 15:23:02 +0200 Subject: [PATCH 049/141] Added KL loss for distilaltion --- rl_baselines/supervised_rl/policy_distillation.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/rl_baselines/supervised_rl/policy_distillation.py b/rl_baselines/supervised_rl/policy_distillation.py index 2cb8138e7..417aa93ba 100644 --- a/rl_baselines/supervised_rl/policy_distillation.py +++ b/rl_baselines/supervised_rl/policy_distillation.py @@ -20,6 +20,8 @@ RENDER_HEIGHT = 224 RENDER_WIDTH = 224 +TEMPERATURE = 1 + class MLPPolicy(nn.Module): def __init__(self, output_size, input_size, hidden_size=400): @@ -113,17 +115,17 @@ def getAction(self, observation, dones=None, delta=0): def loss_fn_kd(self, outputs, teacher_outputs): """ - inspired from : https://github.com/peterliht/knowledge-distillation-pytorch - Compute the knowledge-distillation (KD) loss given outputs, labels. - NOTE: the KL Divergence for PyTorch comparing the softmaxs of teacher - and student expects the input tensor to be log probabilities! See Issue #2 - Hyperparameters: temperature and alpha :param outputs: output from the student model :param teacher_outputs: output from the teacher_outputs model :return: loss """ - return (outputs - teacher_outputs).pow(2).sum(1).mean() + T = TEMPERATURE + KD_loss = F.softmax(teacher_outputs/T) * F.log((F.softmax(teacher_outputs/T) / F.softmax(outputs))) + + print(KD_loss.shape, 'DEBUG FOR KL LOSS') + + return KD_loss.mean() def loss_mse(self, outputs, teacher_outputs): #MSELoss = nn.MSELoss()(outputs, teacher_outputs) From be399f731786b0e0078cf54dc7621be763e3dc3c Mon Sep 17 00:00:00 2001 From: TLESORT Date: Wed, 24 Apr 2019 15:43:38 +0200 Subject: [PATCH 050/141] change cpu_number to 6 --- Distilation_Readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Distilation_Readme.md b/Distilation_Readme.md index d054c1031..1dd20a7a5 100644 --- a/Distilation_Readme.md +++ b/Distilation_Readme.md @@ -36,9 +36,9 @@ python train.py --data-folder data/Omnibot_circular -bs 32 --num-cpu 6 --epochs cd .. # Dataset 1 -python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --num-timesteps 1000000 --env OmnirobotEnv-v0 --log-dir logs/circular/ --num-cpu 8 --simple-continual --latest +python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --num-timesteps 1000000 --env OmnirobotEnv-v0 --log-dir logs/simple/ --num-cpu 6 --simple-continual --latest # Dataset 2 -python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --num-timesteps 1000000 --env OmnirobotEnv-v0 --log-dir logs/circular/ --num-cpu 8 --circular-continual --latest +python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --num-timesteps 1000000 --env OmnirobotEnv-v0 --log-dir logs/circular/ --num-cpu 6 --circular-continual --latest ``` From 85b588fc037ff1d286b3db9ce59181cf3626c50d Mon Sep 17 00:00:00 2001 From: TLESORT Date: Wed, 24 Apr 2019 16:57:06 +0200 Subject: [PATCH 051/141] file added to be able to run all experiments at once --- Distilation_Readme.md | 15 +++- config/srl_models_circular.yaml | 145 ++++++++++++++++++++++++++++++++ config/srl_models_simple.yaml | 145 ++++++++++++++++++++++++++++++++ 3 files changed, 304 insertions(+), 1 deletion(-) create mode 100644 config/srl_models_circular.yaml create mode 100644 config/srl_models_simple.yaml diff --git a/Distilation_Readme.md b/Distilation_Readme.md index f7969adda..dc459572a 100644 --- a/Distilation_Readme.md +++ b/Distilation_Readme.md @@ -36,11 +36,24 @@ python train.py --data-folder data/circular-continual -bs 32 --epochs 30 --stat ``` cd .. +# save config file +cp config/srl_models.yaml config/srl_models_temp.yaml + # Dataset 1 (random reaching target) -python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --num-timesteps 1000000 --env OmnirobotEnv-v0 --log-dir logs/circular/ --num-cpu 6 --simple-continual --latest +cp config/srl_models_simple.yaml config/srl_models.yaml +python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --num-timesteps 1000000 --env OmnirobotEnv-v0 --log-dir logs/simple/ --num-cpu 6 --simple-continual --latest + # Dataset 2 (Circular task) +cp config/srl_models_circular.yaml config/srl_models.yaml python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --num-timesteps 1000000 --env OmnirobotEnv-v0 --log-dir logs/circular/ --num-cpu 6 --circular-continual --latest +# restore config file +cp config/srl_models_temp.yaml config/srl_models.yaml + +# plot results +python -m replay.plots --log-dir /logs/simple/OmnirobotEnv-v0/srl_combination/ppo/ --latest + +python -m replay.plots --log-dir /logs/circular/OmnirobotEnv-v0/srl_combination/ppo/ --latest ``` diff --git a/config/srl_models_circular.yaml b/config/srl_models_circular.yaml new file mode 100644 index 000000000..a3ead3cf3 --- /dev/null +++ b/config/srl_models_circular.yaml @@ -0,0 +1,145 @@ +KukaButtonGymEnv-v0: + # Base path to SRL log folder + log_folder: srl_zoo/logs/kuka_button_relative/ + # Path to the different trained SRL models + autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth + vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth + supervised: baselines/supervised_custom_cnn_SEED1_EPOCHS25_BS32/srl_supervised_model.pth + pca: baselines/pca_ST_DIM5/pca.pkl + robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth + inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth + forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth + multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth + srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth + srl_splits: 18-08-10_15h20_21_custom_cnn_ST_DIM200_autoencoder_reward_inverse/srl_model.pth + +Kuka2ButtonGymEnv-v0: + # Base path to SRL log folder + log_folder: srl_zoo/logs/kuka_2_button/ + # Path to the different trained SRL models + autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth + vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth + supervised: baselines/supervised_custom_cnn_SEED1_EPOCHS25_BS32/srl_supervised_model.pth + pca: baselines/pca_ST_DIM32/pca.pkl + robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth + inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth + forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth + multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth + srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth + +KukaRandButtonGymEnv-v0: + # Base path to SRL log folder + log_folder: srl_zoo/logs/kuka_rand_button/ + # Path to the different trained SRL models + autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth + vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth + supervised: baselines/supervised_custom_cnn_SEED1_EPOCHS25_BS32/srl_supervised_model.pth + pca: baselines/pca_ST_DIM10/pca.pkl + robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth + inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth + forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth + multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth + srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth + +KukaMovingButtonGymEnv-v0: + # Base path to SRL log folder + log_folder: srl_zoo/logs/kuka_moving_button_big/ + # Path to the different trained SRL models + autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth + vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth + supervised: baselines/supervised_custom_cnn_SEED1_EPOCHS25_BS32/srl_supervised_model.pth + pca: baselines/pca_ST_DIM32/pca.pkl + robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth + inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth + forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth + multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth + srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth + +MobileRobotGymEnv-v0: + # Base path to SRL log folder + log_folder: srl_zoo/logs/mobile_robot_relative/ + # Path to the different trained SRL models + autoencoder: 18-07-22_13h36_14_custom_cnn_ST_DIM200_autoencoder/srl_model.pth + vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth + supervised: baselines/supervised_resnet_SEED1_EPOCHS25_BS32/srl_supervised_model.pth + pca: baselines/pca_ST_DIM32/pca.pkl + robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth + inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth + forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth + multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth + autoencoder_reward: 18-07-22_13h20_45_custom_cnn_ST_DIM200_autoencoder_reward/srl_model.pth + autoencoder_inverse: 18-07-22_12h30_10_custom_cnn_ST_DIM200_autoencoder_inverse/srl_model.pth + srl_combination: 18-07-21_12h11_17_custom_cnn_ST_DIM200_autoencoder_inverse_reward/srl_model.pth + reward_inverse: 18-07-23_11h02_28_custom_cnn_ST_DIM200_reward_inverse/srl_model.pth + reward: 18-07-23_18h58_24_custom_cnn_ST_DIM200_reward/srl_model.pth + srl_splits: 18-08-14_12h53_54_custom_cnn_ST_DIM200_autoencoder_reward_inverse/srl_model.pth + # srl_splits: 18-08-10_12h58_43_custom_cnn_ST_DIM200_reward_inverse_autoencoder/srl_model.pth + random: 18-08-10_11h50_25_custom_cnn_ST_DIM200_random/srl_model.pth + random_inverse: 18-08-10_11h38_05_custom_cnn_ST_DIM200_inverse_random/srl_model.pth + autoencoder_forward: 18-08-14_10h35_47_custom_cnn_ST_DIM200_autoencoder_forward/srl_model.pth + +MobileRobot2TargetGymEnv-v0: + # Base path to SRL log folder + log_folder: srl_zoo/logs/mobile_robot_2target/ + # Path to the different trained SRL models + autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth + vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth + supervised: baselines/supervised_resnet_SEED1_EPOCHS25_BS32/srl_supervised_model.pth + pca: baselines/pca_ST_DIM32/pca.pkl + robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth + inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth + forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth + multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth + srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth + +MobileRobot1DGymEnv-v0: + # Base path to SRL log folder + log_folder: srl_zoo/logs/mobile_robot_slider/ + # Path to the different trained SRL models + autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth + vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth + supervised: baselines/supervised_resnet_SEED1_EPOCHS25_BS32/srl_supervised_model.pth + pca: baselines/pca_ST_DIM32/pca.pkl + robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth + inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth + forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth + multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth + srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth + +MobileRobotLineTargetGymEnv-v0: + # Base path to SRL log folder + log_folder: srl_zoo/logs/mobile_line_target/ + # Path to the different trained SRL models + autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth + vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth + supervised: baselines/supervised_resnet_SEED1_EPOCHS25_BS32/srl_supervised_model.pth + pca: baselines/pca_ST_DIM32/pca.pkl + robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth + inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth + forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth + multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth + srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth + +CarRacingGymEnv-v0: + # Base path to SRL log folder + log_folder: srl_zoo/logs/car_racing/ + # Path to the different trained SRL models + autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth + vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth + supervised: baselines/supervised_resnet_SEED1_EPOCHS25_BS32/srl_supervised_model.pth + pca: baselines/pca_ST_DIM32/pca.pkl + robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth + inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth + forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth + multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth + autoencoder_inverse: 18-07-20_12h13_18_custom_cnn_ST_DIM200_autoencoder_inverse/srl_model.pth + autoencoder_reward: 18-07-20_14h35_43_custom_cnn_ST_DIM200_autoencoder_reward/srl_model.pth + srl_combination: 18-07-19_18h16_03_custom_cnn_ST_DIM200_reward_autoencoder_inverse/srl_model.pth + +OmnirobotEnv-v0: + # Base path to SRL log folder + # log_folder: srl_zoo/logs/Omnibot_random_simple/ + log_folder: srl_zoo/logs/Omnibot_circular/ + autoencoder: 19-02-04_23h27_22_custom_cnn_ST_DIM200_autoencoder_reward_inverse_forward/srl_model.pth + + diff --git a/config/srl_models_simple.yaml b/config/srl_models_simple.yaml new file mode 100644 index 000000000..11d6daa73 --- /dev/null +++ b/config/srl_models_simple.yaml @@ -0,0 +1,145 @@ +KukaButtonGymEnv-v0: + # Base path to SRL log folder + log_folder: srl_zoo/logs/kuka_button_relative/ + # Path to the different trained SRL models + autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth + vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth + supervised: baselines/supervised_custom_cnn_SEED1_EPOCHS25_BS32/srl_supervised_model.pth + pca: baselines/pca_ST_DIM5/pca.pkl + robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth + inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth + forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth + multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth + srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth + srl_splits: 18-08-10_15h20_21_custom_cnn_ST_DIM200_autoencoder_reward_inverse/srl_model.pth + +Kuka2ButtonGymEnv-v0: + # Base path to SRL log folder + log_folder: srl_zoo/logs/kuka_2_button/ + # Path to the different trained SRL models + autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth + vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth + supervised: baselines/supervised_custom_cnn_SEED1_EPOCHS25_BS32/srl_supervised_model.pth + pca: baselines/pca_ST_DIM32/pca.pkl + robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth + inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth + forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth + multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth + srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth + +KukaRandButtonGymEnv-v0: + # Base path to SRL log folder + log_folder: srl_zoo/logs/kuka_rand_button/ + # Path to the different trained SRL models + autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth + vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth + supervised: baselines/supervised_custom_cnn_SEED1_EPOCHS25_BS32/srl_supervised_model.pth + pca: baselines/pca_ST_DIM10/pca.pkl + robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth + inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth + forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth + multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth + srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth + +KukaMovingButtonGymEnv-v0: + # Base path to SRL log folder + log_folder: srl_zoo/logs/kuka_moving_button_big/ + # Path to the different trained SRL models + autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth + vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth + supervised: baselines/supervised_custom_cnn_SEED1_EPOCHS25_BS32/srl_supervised_model.pth + pca: baselines/pca_ST_DIM32/pca.pkl + robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth + inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth + forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth + multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth + srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth + +MobileRobotGymEnv-v0: + # Base path to SRL log folder + log_folder: srl_zoo/logs/mobile_robot_relative/ + # Path to the different trained SRL models + autoencoder: 18-07-22_13h36_14_custom_cnn_ST_DIM200_autoencoder/srl_model.pth + vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth + supervised: baselines/supervised_resnet_SEED1_EPOCHS25_BS32/srl_supervised_model.pth + pca: baselines/pca_ST_DIM32/pca.pkl + robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth + inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth + forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth + multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth + autoencoder_reward: 18-07-22_13h20_45_custom_cnn_ST_DIM200_autoencoder_reward/srl_model.pth + autoencoder_inverse: 18-07-22_12h30_10_custom_cnn_ST_DIM200_autoencoder_inverse/srl_model.pth + srl_combination: 18-07-21_12h11_17_custom_cnn_ST_DIM200_autoencoder_inverse_reward/srl_model.pth + reward_inverse: 18-07-23_11h02_28_custom_cnn_ST_DIM200_reward_inverse/srl_model.pth + reward: 18-07-23_18h58_24_custom_cnn_ST_DIM200_reward/srl_model.pth + srl_splits: 18-08-14_12h53_54_custom_cnn_ST_DIM200_autoencoder_reward_inverse/srl_model.pth + # srl_splits: 18-08-10_12h58_43_custom_cnn_ST_DIM200_reward_inverse_autoencoder/srl_model.pth + random: 18-08-10_11h50_25_custom_cnn_ST_DIM200_random/srl_model.pth + random_inverse: 18-08-10_11h38_05_custom_cnn_ST_DIM200_inverse_random/srl_model.pth + autoencoder_forward: 18-08-14_10h35_47_custom_cnn_ST_DIM200_autoencoder_forward/srl_model.pth + +MobileRobot2TargetGymEnv-v0: + # Base path to SRL log folder + log_folder: srl_zoo/logs/mobile_robot_2target/ + # Path to the different trained SRL models + autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth + vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth + supervised: baselines/supervised_resnet_SEED1_EPOCHS25_BS32/srl_supervised_model.pth + pca: baselines/pca_ST_DIM32/pca.pkl + robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth + inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth + forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth + multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth + srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth + +MobileRobot1DGymEnv-v0: + # Base path to SRL log folder + log_folder: srl_zoo/logs/mobile_robot_slider/ + # Path to the different trained SRL models + autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth + vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth + supervised: baselines/supervised_resnet_SEED1_EPOCHS25_BS32/srl_supervised_model.pth + pca: baselines/pca_ST_DIM32/pca.pkl + robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth + inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth + forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth + multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth + srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth + +MobileRobotLineTargetGymEnv-v0: + # Base path to SRL log folder + log_folder: srl_zoo/logs/mobile_line_target/ + # Path to the different trained SRL models + autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth + vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth + supervised: baselines/supervised_resnet_SEED1_EPOCHS25_BS32/srl_supervised_model.pth + pca: baselines/pca_ST_DIM32/pca.pkl + robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth + inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth + forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth + multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth + srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth + +CarRacingGymEnv-v0: + # Base path to SRL log folder + log_folder: srl_zoo/logs/car_racing/ + # Path to the different trained SRL models + autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth + vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth + supervised: baselines/supervised_resnet_SEED1_EPOCHS25_BS32/srl_supervised_model.pth + pca: baselines/pca_ST_DIM32/pca.pkl + robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth + inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth + forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth + multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth + autoencoder_inverse: 18-07-20_12h13_18_custom_cnn_ST_DIM200_autoencoder_inverse/srl_model.pth + autoencoder_reward: 18-07-20_14h35_43_custom_cnn_ST_DIM200_autoencoder_reward/srl_model.pth + srl_combination: 18-07-19_18h16_03_custom_cnn_ST_DIM200_reward_autoencoder_inverse/srl_model.pth + +OmnirobotEnv-v0: + # Base path to SRL log folder + # log_folder: srl_zoo/logs/Omnibot_random_simple/ + log_folder: srl_zoo/logs/Omnibot_random_simple/ + autoencoder: 19-02-04_23h27_22_custom_cnn_ST_DIM200_autoencoder_reward_inverse_forward/srl_model.pth + + From cb160b77a547fc0449fb8a4774e1bbc98d6c16ec Mon Sep 17 00:00:00 2001 From: TeTe <32313299+sun-te@users.noreply.github.com> Date: Wed, 24 Apr 2019 17:29:55 +0200 Subject: [PATCH 052/141] Update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1760bb1da..012b472f6 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ To use the robot's position as input instead of pixels, just pass `--srl-model g To perform a cross evaluation for the different srl model, one could run in the terminal: ``` -python -m rl_baselines.pipeline_cross --algo ppo2 --log-dir logs/ --srl-model srl_comnbination ground_truth --num-iteration 5 --num-timesteps 1000000 --task cc sqc sc +python -m rl_baselines.pipeline_cross --algo ppo2 --log-dir logs/ --srl-model srl_comnbination ground_truth --num-iteration 5 --num-timesteps 1000000 --task cc sqc sc --srl-config-file config/srl_models1.yaml config/srl_models2.yaml config/srl_models3.yaml ``` This will output the learning result into the repository logs. From 257488893ee698a2e7074626c7cc9a8fd2726db0 Mon Sep 17 00:00:00 2001 From: kalifou Date: Wed, 24 Apr 2019 17:36:25 +0200 Subject: [PATCH 053/141] add args for replay when loading specific env task (Omnirobot) --- replay/enjoy_baselines.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/replay/enjoy_baselines.py b/replay/enjoy_baselines.py index bac017cc8..58880bcb3 100644 --- a/replay/enjoy_baselines.py +++ b/replay/enjoy_baselines.py @@ -6,10 +6,12 @@ import os from datetime import datetime +import yaml import numpy as np import tensorflow as tf from stable_baselines.common import set_global_seeds import matplotlib.pyplot as plt +from mpl_toolkits.mplot3d import Axes3D from sklearn.decomposition import PCA import seaborn as sns @@ -58,6 +60,18 @@ def parseArguments(): help='display in the latent space the current observation.') parser.add_argument('--action-proba', action='store_true', default=False, help='display the probability of actions') + parser.add_argument('-sc', '--simple-continual', action='store_true', default=False, + help='Simple red square target for task 1 of continual learning scenario. ' + + 'The task is: robot should reach the target.') + parser.add_argument('-cc', '--circular-continual', action='store_true', default=False, + help='Blue square target for task 2 of continual learning scenario. ' + + 'The task is: robot should turn in circle around the target.') + parser.add_argument('-sqc', '--square-continual', action='store_true', default=False, + help='Green square target for task 3 of continual learning scenario. ' + + 'The task is: robot should turn in square around the target.') + args, unknown = parser.parse_known_args() + assert sum([args.simple_continual, args.circular_continual, args.square_continual]) <= 1, \ + "For continual SRL and RL, please provide only one scenario at the time and use OmnirobotEnv-v0 environment !" return parser.parse_args() @@ -107,6 +121,12 @@ def loadConfigAndSetup(load_args): env_kwargs["square_continual_move"] = env_globals.get("square_continual_move", False) env_kwargs["eight_continual_move"] = env_globals.get("eight_continual_move", False) + if sum([load_args.simple_continual, load_args.circular_continual, load_args.square_continual]) >= 1: + env_kwargs["simple_continual_target"] = load_args.simple_continual + env_kwargs["circular_continual_move"] = load_args.circular_continual + env_kwargs["square_continual_move"] = load_args.square_continual + env_kwargs["random_target"] = not (load_args.circular_continual or load_args.square_continual) + srl_model_path = None if train_args["srl_model"] != "raw_pixels": train_args["policy"] = "mlp" From 487df1b14adaa9d08fe98a1f437b9272d17f7887 Mon Sep 17 00:00:00 2001 From: TLESORT Date: Thu, 25 Apr 2019 13:36:34 +0200 Subject: [PATCH 054/141] fix command for random dataset generator --- Distilation_Readme.md | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/Distilation_Readme.md b/Distilation_Readme.md index dc459572a..f40a296fa 100644 --- a/Distilation_Readme.md +++ b/Distilation_Readme.md @@ -15,9 +15,9 @@ ``` cd srl_zoo # Dataset 1 (random reaching target) -python -m environments.dataset_generator --num-cpu 6 --name Omnibot_circular --env OmnirobotEnv-v0 --simple-continual --num-episode 250 +python -m environments.dataset_generator --num-cpu 6 --name Omnibot_random_simple --env OmnirobotEnv-v0 --simple-continual --num-episode 250 # Dataset 2 (Circular task) -python -m environments.dataset_generator --num-cpu 6 --name Omnibot_random_simple --env OmnirobotEnv-v0 --circular-continual --num-episode 250 +python -m environments.dataset_generator --num-cpu 6 --name Omnibot_circular --env OmnirobotEnv-v0 --circular-continual --num-episode 250 ``` ### 1.1) Train SRL @@ -33,6 +33,8 @@ python train.py --data-folder data/circular-continual -bs 32 --epochs 30 --stat ### 1.2) Train policy +Train + ``` cd .. @@ -49,6 +51,17 @@ python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --num-times # restore config file cp config/srl_models_temp.yaml config/srl_models.yaml +``` + +Visualize and plot + +``` +# Visualize episodes + +python -m replay.enjoy_baselines --log-dir *file* --num-timesteps 10000 --render --action-proba +example : python -m replay.enjoy_baselines --log-dir logs/simple/OmnirobotEnv-v0/srl_combination/ppo2/19-04-25_10h19_42/ --num-timesteps 10000 --render --action-proba + + # plot results python -m replay.plots --log-dir /logs/simple/OmnirobotEnv-v0/srl_combination/ppo/ --latest From 3687a75ea5bce15942facf7e2d4e3318607c2f03 Mon Sep 17 00:00:00 2001 From: Caselles Date: Thu, 25 Apr 2019 16:12:09 +0200 Subject: [PATCH 055/141] Added sample flag for getAction and fixed KL loss for distillation. --- .../supervised_rl/policy_distillation.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/rl_baselines/supervised_rl/policy_distillation.py b/rl_baselines/supervised_rl/policy_distillation.py index 417aa93ba..1d7ef9f2c 100644 --- a/rl_baselines/supervised_rl/policy_distillation.py +++ b/rl_baselines/supervised_rl/policy_distillation.py @@ -97,7 +97,7 @@ def getActionProba(self, observation, dones=None, delta=0): action = self.model.forward(observation).detach().cpu().numpy() return action #softmax(action) - def getAction(self, observation, dones=None, delta=0): + def getAction(self, observation, dones=None, delta=0, sample=False): """ From an observation returns the associated action :param observation: (numpy int or numpy float) @@ -111,7 +111,12 @@ def getAction(self, observation, dones=None, delta=0): if len(observation.shape) > 2: observation = np.transpose(observation, (0, 3, 2, 1)) observation = th.from_numpy(observation).float().requires_grad_(False).to(self.device) - return [np.argmax(self.model.forward(observation).detach().cpu().numpy())] + + if sample: + proba_actions = self.model.forward(observation).detach().cpu().numpy().flatten() + return np.random.choice(range(len(proba_actions)), 1, p=proba_actions) + else: + return [np.argmax(self.model.forward(observation).detach().cpu().numpy())] def loss_fn_kd(self, outputs, teacher_outputs): """ @@ -121,9 +126,8 @@ def loss_fn_kd(self, outputs, teacher_outputs): :return: loss """ T = TEMPERATURE - KD_loss = F.softmax(teacher_outputs/T) * F.log((F.softmax(teacher_outputs/T) / F.softmax(outputs))) - - print(KD_loss.shape, 'DEBUG FOR KL LOSS') + KD_loss = F.softmax(teacher_outputs/T, dim=1) * \ + th.log((F.softmax(teacher_outputs/T, dim=1) / F.softmax(outputs, dim=1))) return KD_loss.mean() @@ -254,8 +258,8 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): state = obs.detach() if self.srl_model is None \ else self.srl_model.model.getStates(obs).to(self.device).detach() pred_action = self.model.forward(state) - #loss = self.loss_fn_kd(pred_action, actions_proba_st) - loss = self.loss_mse(pred_action, actions_proba_st.float()) + loss = self.loss_fn_kd(pred_action, actions_proba_st) + #loss = self.loss_mse(pred_action, actions_proba_st.float()) loss.backward() if validation_mode: From 44730bc0d8cfe6c204f5d4f4016c343aa285d043 Mon Sep 17 00:00:00 2001 From: TLESORT Date: Thu, 25 Apr 2019 17:00:36 +0200 Subject: [PATCH 056/141] fix command for train SRL and added a force flag for dataset generator --- Distilation_Readme.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Distilation_Readme.md b/Distilation_Readme.md index f40a296fa..940fb1f77 100644 --- a/Distilation_Readme.md +++ b/Distilation_Readme.md @@ -15,9 +15,9 @@ ``` cd srl_zoo # Dataset 1 (random reaching target) -python -m environments.dataset_generator --num-cpu 6 --name Omnibot_random_simple --env OmnirobotEnv-v0 --simple-continual --num-episode 250 +python -m environments.dataset_generator --num-cpu 6 --name Omnibot_random_simple --env OmnirobotEnv-v0 --simple-continual --num-episode 250 -f # Dataset 2 (Circular task) -python -m environments.dataset_generator --num-cpu 6 --name Omnibot_circular --env OmnirobotEnv-v0 --circular-continual --num-episode 250 +python -m environments.dataset_generator --num-cpu 6 --name Omnibot_circular --env OmnirobotEnv-v0 --circular-continual --num-episode 250 -f ``` ### 1.1) Train SRL @@ -25,9 +25,9 @@ python -m environments.dataset_generator --num-cpu 6 --name Omnibot_circular --e ``` cd srl_zoo # Dataset 1 (random reaching target) -python train.py --data-folder data/simple-continual -bs 32 --epochs 30 --state-dim 200 --training-set-size 30000 --losses autoencoder inverse +python train.py --data-folder data/Omnibot_random_simple -bs 32 --epochs 20 --state-dim 200 --training-set-size 20000 --losses autoencoder inverse # Dataset 2 (Circular task) -python train.py --data-folder data/circular-continual -bs 32 --epochs 30 --state-dim 200 --training-set-size 30000 --losses autoencoder inverse +python train.py --data-folder data/Omnibot_circular -bs 32 --epochs 20 --state-dim 200 --training-set-size 20000 --losses autoencoder inverse ``` @@ -43,7 +43,7 @@ cp config/srl_models.yaml config/srl_models_temp.yaml # Dataset 1 (random reaching target) cp config/srl_models_simple.yaml config/srl_models.yaml -python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --num-timesteps 1000000 --env OmnirobotEnv-v0 --log-dir logs/simple/ --num-cpu 6 --simple-continual --latest +python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --num-timesteps 1000000 --env OmnirobotEnv-v0 --log-dir logs/simple/ --num-cpu 8 --simple-continual --latest # Dataset 2 (Circular task) cp config/srl_models_circular.yaml config/srl_models.yaml From a3a0784db15cbadae8b2b627fc63479f83744f7a Mon Sep 17 00:00:00 2001 From: kalifou Date: Thu, 25 Apr 2019 17:20:39 +0200 Subject: [PATCH 057/141] update datafusionner to log task labels to each obs --- environments/dataset_fusioner.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/environments/dataset_fusioner.py b/environments/dataset_fusioner.py index 2e6d7e532..9d3d97b21 100644 --- a/environments/dataset_fusioner.py +++ b/environments/dataset_fusioner.py @@ -8,10 +8,16 @@ import numpy as np from tqdm import tqdm +CONTINUAL_LEARNING_LABELS = ['CC', 'SC', 'EC', 'SQC'] +CL_LABEL_KEY = "continual_learning_label" + def main(): parser = argparse.ArgumentParser(description='Dataset Manipulator: useful to fusion two datasets by concatenating ' 'episodes. PS: Deleting sources after fusion into destination folder.') + parser.add_argument('--continual-learning-labels', type=str, nargs=2, metavar=('label_1', 'label_2'), + default=argparse.SUPPRESS, + help='Labels for the continual learning RL distillation task.') group = parser.add_mutually_exclusive_group() group.add_argument('--merge', type=str, nargs=3, metavar=('source_1', 'source_2', 'destination'), default=argparse.SUPPRESS, @@ -24,6 +30,10 @@ def main(): assert os.path.exists(args.merge[0]), "Error: dataset '{}' could not be found".format(args.merge[0]) assert (not os.path.exists(args.merge[2])), "Error: dataset '{}' already exists, cannot rename '{}' to '{}'"\ .format(args.merge[2], args.merge[0], args.merge[2]) + if 'continual_learning_labels' in args: + assert args.continual_learning_labels[0] in CONTINUAL_LEARNING_LABELS \ + and args.continual_learning_labels[1] in CONTINUAL_LEARNING_LABELS, \ + "Please specify a valid Continual learning label to each dataset to be used for RL distillation !" # create the output os.mkdir(args.merge[2]) @@ -99,7 +109,10 @@ def main(): preprocessed_load = np.load(args.merge[0] + "/preprocessed_data.npz") preprocessed_load_2 = np.load(args.merge[1] + "/preprocessed_data.npz") - for prepro_load in [preprocessed_load, preprocessed_load_2]: + dataset_1_size = preprocessed_load["actions"].shape[0] + dataset_2_size = preprocessed_load_2["actions"].shape[0] + + for idx, prepro_load in enumerate([preprocessed_load, preprocessed_load_2]): for arr in prepro_load.files: pr_arr = prepro_load[arr] @@ -115,6 +128,13 @@ def main(): else: preprocessed[arr] = np.concatenate((preprocessed[arr].astype(to_class), pr_arr.astype(to_class)), axis=0) + if 'continual_learning_labels' in args: + if preprocessed.get(CL_LABEL_KEY, None) is None: + preprocessed[CL_LABEL_KEY] = np.array([args.continual_learning_labels[idx] for _ in range(dataset_1_size)]) + else: + preprocessed[CL_LABEL_KEY] = np.concatenate((preprocessed[CL_LABEL_KEY], + np.array([args.continual_learning_labels[idx] + for _ in range(dataset_2_size)])), axis=0) np.savez(args.merge[2] + "/preprocessed_data.npz", ** preprocessed) From 059a190854651913af29b00a7a039ed2c1427a04 Mon Sep 17 00:00:00 2001 From: kalifou Date: Thu, 25 Apr 2019 17:21:46 +0200 Subject: [PATCH 058/141] update option for shorter eps (CC) --- environments/omnirobot_gym/omnirobot_env.py | 3 ++- real_robots/constants.py | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/environments/omnirobot_gym/omnirobot_env.py b/environments/omnirobot_gym/omnirobot_env.py index 7f08df70e..27ca35e4b 100644 --- a/environments/omnirobot_gym/omnirobot_env.py +++ b/environments/omnirobot_gym/omnirobot_env.py @@ -304,7 +304,8 @@ def _hasEpisodeTerminated(self): Returns True if the episode is over and False otherwise """ if self.episode_terminated or self._env_step_counter > MAX_STEPS or \ - (self.n_contacts >= N_CONTACTS_BEFORE_TERMINATION and self.short_episodes): + (self.n_contacts >= N_CONTACTS_BEFORE_TERMINATION and self.short_episodes) or \ + (self._env_step_counter > MAX_STEPS_CIRCULAR_TASK_SHORT_EPISODES and self.short_episodes): return True if np.abs(self.reward - REWARD_TARGET_REACH) < 0.000001: # reach the target diff --git a/real_robots/constants.py b/real_robots/constants.py index 27d61bba9..7d0310198 100644 --- a/real_robots/constants.py +++ b/real_robots/constants.py @@ -88,6 +88,7 @@ class Move(IntEnum): # Max number of steps per episode MAX_STEPS = 250 + MAX_STEPS_CIRCULAR_TASK_SHORT_EPISODES = 75 # Boundaries MIN_X, MAX_X = -0.85, 0.85 # center of robot should be in this interval MIN_Y, MAX_Y = -0.85, 0.85 From 1a42fdd1e9025620311a6bafc0b3766270bb5e0b Mon Sep 17 00:00:00 2001 From: kalifou Date: Thu, 25 Apr 2019 17:23:05 +0200 Subject: [PATCH 059/141] update: add option in distillation loss for temperature depending on task label --- .../supervised_rl/policy_distillation.py | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/rl_baselines/supervised_rl/policy_distillation.py b/rl_baselines/supervised_rl/policy_distillation.py index 1d7ef9f2c..a935cd103 100644 --- a/rl_baselines/supervised_rl/policy_distillation.py +++ b/rl_baselines/supervised_rl/policy_distillation.py @@ -20,7 +20,12 @@ RENDER_HEIGHT = 224 RENDER_WIDTH = 224 -TEMPERATURE = 1 +CONTINUAL_LEARNING_LABELS = ['CC', 'SC', 'EC', 'SQC'] +CL_LABEL_KEY = "continual_learning_label" + +TEMPERATURES = {'CC': 0.1, 'SC': 0.1, 'EC': 0.1, 'SQC': 0.1, "default": 0.1} +# run with 0.1 to have good results! +# 0.01 worse reward for CC, better SC class MLPPolicy(nn.Module): @@ -95,7 +100,7 @@ def getActionProba(self, observation, dones=None, delta=0): observation = np.transpose(observation, (0, 3, 2, 1)) observation = th.from_numpy(observation).float().requires_grad_(False).to(self.device) action = self.model.forward(observation).detach().cpu().numpy() - return action #softmax(action) + return action def getAction(self, observation, dones=None, delta=0, sample=False): """ @@ -118,21 +123,26 @@ def getAction(self, observation, dones=None, delta=0, sample=False): else: return [np.argmax(self.model.forward(observation).detach().cpu().numpy())] - def loss_fn_kd(self, outputs, teacher_outputs): + def loss_fn_kd(self, outputs, teacher_outputs, labels=None, adaptive_temperature=False): """ Hyperparameters: temperature and alpha :param outputs: output from the student model :param teacher_outputs: output from the teacher_outputs model :return: loss """ - T = TEMPERATURE - KD_loss = F.softmax(teacher_outputs/T, dim=1) * \ - th.log((F.softmax(teacher_outputs/T, dim=1) / F.softmax(outputs, dim=1))) + if labels is not None and adaptive_temperature: + T = th.from_numpy(np.array([TEMPERATURES[labels[idx_elm]] for idx_elm in range(BATCH_SIZE)])).cuda().float() + KD_loss = F.softmax(th.div(teacher_outputs.transpose(1, 0), T).transpose(1, 0), dim=1) * \ + th.log((F.softmax(th.div(teacher_outputs.transpose(1, 0).transpose(1, 0), T), dim=1) / F.softmax( + th.div(outputs.transpose(1, 0).transpose(1, 0), T), dim=1))) + else: + T = TEMPERATURES["default"] + KD_loss = F.softmax(teacher_outputs/T, dim=1) * \ + th.log((F.softmax(teacher_outputs/T, dim=1) / F.softmax(outputs, dim=1))) return KD_loss.mean() def loss_mse(self, outputs, teacher_outputs): - #MSELoss = nn.MSELoss()(outputs, teacher_outputs) return (outputs - teacher_outputs).pow(2).sum(1).mean() def train(self, args, callback, env_kwargs=None, train_kwargs=None): @@ -149,6 +159,7 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): images_path = ground_truth['images_path'] actions = training_data['actions'] actions_proba = training_data['actions_proba'] + cl_labels = training_data[CL_LABEL_KEY] if args.distillation_training_set_size > 0: limit = args.distillation_training_set_size @@ -244,6 +255,7 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): # Actions associated to the observations of the current minibatch actions_st = actions[minibatchlist[minibatch_idx]] actions_proba_st = actions_proba[minibatchlist[minibatch_idx]] + cl_labels_st = cl_labels[minibatchlist[minibatch_idx]] if not args.continuous_actions: # Discrete actions, rearrange action to have n_minibatch ligns and one column, @@ -258,8 +270,9 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): state = obs.detach() if self.srl_model is None \ else self.srl_model.model.getStates(obs).to(self.device).detach() pred_action = self.model.forward(state) - loss = self.loss_fn_kd(pred_action, actions_proba_st) - #loss = self.loss_mse(pred_action, actions_proba_st.float()) + + loss = self.loss_fn_kd(pred_action, actions_proba_st.float(), + labels=cl_labels_st, adaptive_temperature=True) loss.backward() if validation_mode: @@ -276,7 +289,7 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): train_loss = epoch_loss / float(epoch_batches) val_loss /= float(n_val_batches) pbar.close() - print("Epoch {:3}/{}, train_loss:{:.4f} val_loss:{:.4f}".format(epoch + 1, N_EPOCHS, train_loss, val_loss)) + print("Epoch {:3}/{}, train_loss:{:.6f} val_loss:{:.6f}".format(epoch + 1, N_EPOCHS, train_loss, val_loss)) # Save best model if val_loss < best_error: From 62bb031398b6dfd9c884b8abfdfe6b053865a0e7 Mon Sep 17 00:00:00 2001 From: kalifou Date: Thu, 25 Apr 2019 17:25:28 +0200 Subject: [PATCH 060/141] fix adaptive loss --- rl_baselines/supervised_rl/policy_distillation.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rl_baselines/supervised_rl/policy_distillation.py b/rl_baselines/supervised_rl/policy_distillation.py index a935cd103..26c80b4a0 100644 --- a/rl_baselines/supervised_rl/policy_distillation.py +++ b/rl_baselines/supervised_rl/policy_distillation.py @@ -133,9 +133,9 @@ def loss_fn_kd(self, outputs, teacher_outputs, labels=None, adaptive_temperature if labels is not None and adaptive_temperature: T = th.from_numpy(np.array([TEMPERATURES[labels[idx_elm]] for idx_elm in range(BATCH_SIZE)])).cuda().float() - KD_loss = F.softmax(th.div(teacher_outputs.transpose(1, 0), T).transpose(1, 0), dim=1) * \ - th.log((F.softmax(th.div(teacher_outputs.transpose(1, 0).transpose(1, 0), T), dim=1) / F.softmax( - th.div(outputs.transpose(1, 0).transpose(1, 0), T), dim=1))) + KD_loss = F.softmax(th.div(teacher_outputs.transpose(1, 0), T), dim=1) * \ + th.log((F.softmax(th.div(teacher_outputs.transpose(1, 0), T), dim=1) / F.softmax( + th.div(outputs.transpose(1, 0), T), dim=1))) else: T = TEMPERATURES["default"] KD_loss = F.softmax(teacher_outputs/T, dim=1) * \ @@ -272,7 +272,7 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): pred_action = self.model.forward(state) loss = self.loss_fn_kd(pred_action, actions_proba_st.float(), - labels=cl_labels_st, adaptive_temperature=True) + labels=cl_labels_st, adaptive_temperature=False) loss.backward() if validation_mode: From 2a6c0db27d02d7c833a64195729a95508d8f3dc5 Mon Sep 17 00:00:00 2001 From: kalifou Date: Thu, 25 Apr 2019 17:37:19 +0200 Subject: [PATCH 061/141] update safety --- rl_baselines/supervised_rl/policy_distillation.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/rl_baselines/supervised_rl/policy_distillation.py b/rl_baselines/supervised_rl/policy_distillation.py index 26c80b4a0..a671796ac 100644 --- a/rl_baselines/supervised_rl/policy_distillation.py +++ b/rl_baselines/supervised_rl/policy_distillation.py @@ -22,8 +22,8 @@ CONTINUAL_LEARNING_LABELS = ['CC', 'SC', 'EC', 'SQC'] CL_LABEL_KEY = "continual_learning_label" - -TEMPERATURES = {'CC': 0.1, 'SC': 0.1, 'EC': 0.1, 'SQC': 0.1, "default": 0.1} +USE_ADAPTIVE_TEMPERATURE = False +TEMPERATURES = {'CC': 0.1, 'SC': 0.1, 'EC': 0.1, 'SQC': 0.1, "default": 0.001} # run with 0.1 to have good results! # 0.01 worse reward for CC, better SC @@ -159,7 +159,10 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): images_path = ground_truth['images_path'] actions = training_data['actions'] actions_proba = training_data['actions_proba'] - cl_labels = training_data[CL_LABEL_KEY] + if USE_ADAPTIVE_TEMPERATURE: + cl_labels = training_data[CL_LABEL_KEY] + else: + cl_labels_st = None if args.distillation_training_set_size > 0: limit = args.distillation_training_set_size @@ -255,7 +258,9 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): # Actions associated to the observations of the current minibatch actions_st = actions[minibatchlist[minibatch_idx]] actions_proba_st = actions_proba[minibatchlist[minibatch_idx]] - cl_labels_st = cl_labels[minibatchlist[minibatch_idx]] + + if USE_ADAPTIVE_TEMPERATURE: + cl_labels_st = cl_labels[minibatchlist[minibatch_idx]] if not args.continuous_actions: # Discrete actions, rearrange action to have n_minibatch ligns and one column, @@ -272,7 +277,7 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): pred_action = self.model.forward(state) loss = self.loss_fn_kd(pred_action, actions_proba_st.float(), - labels=cl_labels_st, adaptive_temperature=False) + labels=cl_labels_st, adaptive_temperature=USE_ADAPTIVE_TEMPERATURE) loss.backward() if validation_mode: From f3b21a8c4c65d96720654f6d8c5176d8755415e2 Mon Sep 17 00:00:00 2001 From: TLESORT Date: Thu, 25 Apr 2019 19:29:28 +0200 Subject: [PATCH 062/141] distillation readme fully tested, normally everything is written in it, but the full experiment can still not be run at once --- Distilation_Readme.md | 10 ++- config/srl_models_merged.yaml | 145 ++++++++++++++++++++++++++++++++++ 2 files changed, 153 insertions(+), 2 deletions(-) create mode 100644 config/srl_models_merged.yaml diff --git a/Distilation_Readme.md b/Distilation_Readme.md index 940fb1f77..9b48ea91d 100644 --- a/Distilation_Readme.md +++ b/Distilation_Readme.md @@ -75,6 +75,10 @@ python -m replay.plots --log-dir /logs/circular/OmnirobotEnv-v0/srl_combination/ ### 2.1) Generate dataset on Policy +(le dossier "data" ne se créé pas tout seul donc executer : "mkdir data" si besoin) + + +(pas completement automatisé "log_custom_policy" doit etre mis manuellement) ``` # Dataset 1 (random reaching target) @@ -93,8 +97,9 @@ cp -r data/merge_CC_SC srl_zoo/data/merge_CC_SC ### 2.3) Train SRL 1&2 ``` +cd srl_zoo # Dataset 1 -python train.py --data-folder data/merge_CC_SC -bs 32 --epochs 2 --state-dim 200 --training-set-size 30000--losses autoencoder inverse +python train.py --data-folder data/merge_CC_SC -bs 32 --epochs 20 --state-dim 200 --training-set-size 30000--losses autoencoder inverse # Update your RL logs to load the proper SRL model for future distillation, i.e distillation: new-log/srl_model.pth ``` @@ -105,7 +110,8 @@ python train.py --data-folder data/merge_CC_SC -bs 32 --epochs 2 --state-dim 20 ``` # make a new log folder mkdir logs/CL_SC_CC +cp config/srl_models_merged.yaml config/srl_models.yaml # Merged Dataset -python -m rl_baselines.train --algo distillation --srl-model srl_combination --env OmnirobotEnv-v0 --log-dir logs/CL_SC_CC --teacher-data-folder srl_zoo/data/merge_CC_SC -cc --distillation-training-set-size 40000 --epochs-distillation 20 +python -m rl_baselines.train --algo distillation --srl-model srl_combination --env OmnirobotEnv-v0 --log-dir logs/CL_SC_CC --teacher-data-folder srl_zoo/data/merge_CC_SC -cc --distillation-training-set-size 40000 --epochs-distillation 20 --latest ``` diff --git a/config/srl_models_merged.yaml b/config/srl_models_merged.yaml new file mode 100644 index 000000000..fb540bb09 --- /dev/null +++ b/config/srl_models_merged.yaml @@ -0,0 +1,145 @@ +KukaButtonGymEnv-v0: + # Base path to SRL log folder + log_folder: srl_zoo/logs/kuka_button_relative/ + # Path to the different trained SRL models + autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth + vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth + supervised: baselines/supervised_custom_cnn_SEED1_EPOCHS25_BS32/srl_supervised_model.pth + pca: baselines/pca_ST_DIM5/pca.pkl + robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth + inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth + forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth + multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth + srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth + srl_splits: 18-08-10_15h20_21_custom_cnn_ST_DIM200_autoencoder_reward_inverse/srl_model.pth + +Kuka2ButtonGymEnv-v0: + # Base path to SRL log folder + log_folder: srl_zoo/logs/kuka_2_button/ + # Path to the different trained SRL models + autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth + vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth + supervised: baselines/supervised_custom_cnn_SEED1_EPOCHS25_BS32/srl_supervised_model.pth + pca: baselines/pca_ST_DIM32/pca.pkl + robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth + inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth + forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth + multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth + srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth + +KukaRandButtonGymEnv-v0: + # Base path to SRL log folder + log_folder: srl_zoo/logs/kuka_rand_button/ + # Path to the different trained SRL models + autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth + vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth + supervised: baselines/supervised_custom_cnn_SEED1_EPOCHS25_BS32/srl_supervised_model.pth + pca: baselines/pca_ST_DIM10/pca.pkl + robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth + inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth + forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth + multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth + srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth + +KukaMovingButtonGymEnv-v0: + # Base path to SRL log folder + log_folder: srl_zoo/logs/kuka_moving_button_big/ + # Path to the different trained SRL models + autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth + vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth + supervised: baselines/supervised_custom_cnn_SEED1_EPOCHS25_BS32/srl_supervised_model.pth + pca: baselines/pca_ST_DIM32/pca.pkl + robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth + inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth + forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth + multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth + srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth + +MobileRobotGymEnv-v0: + # Base path to SRL log folder + log_folder: srl_zoo/logs/mobile_robot_relative/ + # Path to the different trained SRL models + autoencoder: 18-07-22_13h36_14_custom_cnn_ST_DIM200_autoencoder/srl_model.pth + vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth + supervised: baselines/supervised_resnet_SEED1_EPOCHS25_BS32/srl_supervised_model.pth + pca: baselines/pca_ST_DIM32/pca.pkl + robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth + inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth + forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth + multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth + autoencoder_reward: 18-07-22_13h20_45_custom_cnn_ST_DIM200_autoencoder_reward/srl_model.pth + autoencoder_inverse: 18-07-22_12h30_10_custom_cnn_ST_DIM200_autoencoder_inverse/srl_model.pth + srl_combination: 18-07-21_12h11_17_custom_cnn_ST_DIM200_autoencoder_inverse_reward/srl_model.pth + reward_inverse: 18-07-23_11h02_28_custom_cnn_ST_DIM200_reward_inverse/srl_model.pth + reward: 18-07-23_18h58_24_custom_cnn_ST_DIM200_reward/srl_model.pth + srl_splits: 18-08-14_12h53_54_custom_cnn_ST_DIM200_autoencoder_reward_inverse/srl_model.pth + # srl_splits: 18-08-10_12h58_43_custom_cnn_ST_DIM200_reward_inverse_autoencoder/srl_model.pth + random: 18-08-10_11h50_25_custom_cnn_ST_DIM200_random/srl_model.pth + random_inverse: 18-08-10_11h38_05_custom_cnn_ST_DIM200_inverse_random/srl_model.pth + autoencoder_forward: 18-08-14_10h35_47_custom_cnn_ST_DIM200_autoencoder_forward/srl_model.pth + +MobileRobot2TargetGymEnv-v0: + # Base path to SRL log folder + log_folder: srl_zoo/logs/mobile_robot_2target/ + # Path to the different trained SRL models + autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth + vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth + supervised: baselines/supervised_resnet_SEED1_EPOCHS25_BS32/srl_supervised_model.pth + pca: baselines/pca_ST_DIM32/pca.pkl + robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth + inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth + forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth + multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth + srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth + +MobileRobot1DGymEnv-v0: + # Base path to SRL log folder + log_folder: srl_zoo/logs/mobile_robot_slider/ + # Path to the different trained SRL models + autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth + vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth + supervised: baselines/supervised_resnet_SEED1_EPOCHS25_BS32/srl_supervised_model.pth + pca: baselines/pca_ST_DIM32/pca.pkl + robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth + inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth + forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth + multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth + srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth + +MobileRobotLineTargetGymEnv-v0: + # Base path to SRL log folder + log_folder: srl_zoo/logs/mobile_line_target/ + # Path to the different trained SRL models + autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth + vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth + supervised: baselines/supervised_resnet_SEED1_EPOCHS25_BS32/srl_supervised_model.pth + pca: baselines/pca_ST_DIM32/pca.pkl + robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth + inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth + forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth + multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth + srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth + +CarRacingGymEnv-v0: + # Base path to SRL log folder + log_folder: srl_zoo/logs/car_racing/ + # Path to the different trained SRL models + autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth + vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth + supervised: baselines/supervised_resnet_SEED1_EPOCHS25_BS32/srl_supervised_model.pth + pca: baselines/pca_ST_DIM32/pca.pkl + robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth + inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth + forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth + multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth + autoencoder_inverse: 18-07-20_12h13_18_custom_cnn_ST_DIM200_autoencoder_inverse/srl_model.pth + autoencoder_reward: 18-07-20_14h35_43_custom_cnn_ST_DIM200_autoencoder_reward/srl_model.pth + srl_combination: 18-07-19_18h16_03_custom_cnn_ST_DIM200_reward_autoencoder_inverse/srl_model.pth + +OmnirobotEnv-v0: + # Base path to SRL log folder + # log_folder: srl_zoo/logs/Omnibot_random_simple/ + log_folder: srl_zoo/logs/merge_CC_SC/ + autoencoder: 19-02-04_23h27_22_custom_cnn_ST_DIM200_autoencoder_reward_inverse_forward/srl_model.pth + + From 74fe98352f8702bd8fd94fd59f2c8846056ddb9e Mon Sep 17 00:00:00 2001 From: TLESORT Date: Thu, 25 Apr 2019 19:30:12 +0200 Subject: [PATCH 063/141] default temperature changed to 0.1 --- rl_baselines/supervised_rl/policy_distillation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rl_baselines/supervised_rl/policy_distillation.py b/rl_baselines/supervised_rl/policy_distillation.py index a671796ac..6afa37193 100644 --- a/rl_baselines/supervised_rl/policy_distillation.py +++ b/rl_baselines/supervised_rl/policy_distillation.py @@ -23,7 +23,7 @@ CONTINUAL_LEARNING_LABELS = ['CC', 'SC', 'EC', 'SQC'] CL_LABEL_KEY = "continual_learning_label" USE_ADAPTIVE_TEMPERATURE = False -TEMPERATURES = {'CC': 0.1, 'SC': 0.1, 'EC': 0.1, 'SQC': 0.1, "default": 0.001} +TEMPERATURES = {'CC': 0.1, 'SC': 0.1, 'EC': 0.1, 'SQC': 0.1, "default": 0.1} # run with 0.1 to have good results! # 0.01 worse reward for CC, better SC From f6a5d726bc906083409fe3518ba42bbbf6d7e306 Mon Sep 17 00:00:00 2001 From: TLESORT Date: Fri, 26 Apr 2019 10:35:05 +0200 Subject: [PATCH 064/141] short episode flag added into dataset_generator for cc --- Distilation_Readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Distilation_Readme.md b/Distilation_Readme.md index 9b48ea91d..6922f9b52 100644 --- a/Distilation_Readme.md +++ b/Distilation_Readme.md @@ -82,10 +82,10 @@ python -m replay.plots --log-dir /logs/circular/OmnirobotEnv-v0/srl_combination/ ``` # Dataset 1 (random reaching target) -python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 600 --run-policy custom --log-custom-policy logs/simple-continual --short-episodes --save-path data/ --name reaching_on_policy -sc +python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 600 --run-policy custom --log-custom-policy logs/*path2policy* --short-episodes --save-path data/ --name reaching_on_policy -sc # Dataset 2 (Circular task) -python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 100 --run-policy custom --log-custom-policy logs/circular-continual --save-path data/ --name circular_on_policy -cc +python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 100 --run-policy custom --log-custom-policy logs/*path2policy* --short-episodes --save-path data/ --name circular_on_policy -cc # Merge Datasets python -m environments.dataset_fusioner --merge data/circular_on_policy/ data/reaching_on_policy/ data/merge_CC_SC From 3cbd0935214aacc46ba1c38fe93090e027ca992b Mon Sep 17 00:00:00 2001 From: sun-te Date: Fri, 26 Apr 2019 10:43:27 +0200 Subject: [PATCH 065/141] cross evaluation for model trained by srl --- rl_baselines/cross_eval.py | 291 +++------------------------ rl_baselines/cross_eval_utils.py | 327 +++++++++++++++++++++++++++++++ rl_baselines/train.py | 2 +- rl_baselines/visualize.py | 11 +- 4 files changed, 364 insertions(+), 267 deletions(-) create mode 100644 rl_baselines/cross_eval_utils.py diff --git a/rl_baselines/cross_eval.py b/rl_baselines/cross_eval.py index 6288176c1..1bd2dea1d 100644 --- a/rl_baselines/cross_eval.py +++ b/rl_baselines/cross_eval.py @@ -1,269 +1,42 @@ -""" -Modified version of https://github.com/ikostrikov/pytorch-a2c-ppo-acktr/blob/master/visualize.py -Script used to send plot data to visdom -""" -import glob -import os -import json -import numpy as np -import tensorflow as tf -from scipy.signal import medfilt -from rl_baselines.utils import WrapFrameStack,computeMeanReward -from rl_baselines import AlgoType -from rl_baselines.registry import registered_rl -from srl_zoo.utils import printYellow, printGreen,printBlue,printRed -from datetime import datetime - -def loadConfigAndSetup(log_dir): - algo_name = "" - for algo in list(registered_rl.keys()): - if algo in log_dir: - algo_name = algo - break - algo_class, algo_type, _ = registered_rl[algo_name] - if algo_type == AlgoType.OTHER: - raise ValueError(algo_name + " is not supported for evaluation") - - env_globals = json.load(open(log_dir + "env_globals.json", 'r')) - train_args = json.load(open(log_dir + "args.json", 'r')) - env_kwargs = { - "renders": False, - "shape_reward": False, #TODO, since we dont use simple target, we should elimanate this choice? - "action_joints": train_args["action_joints"], - "is_discrete": not train_args["continuous_actions"], - "random_target": train_args.get('random_target', False), - "srl_model": train_args["srl_model"] - } - - # load it, if it was defined - if "action_repeat" in env_globals: - env_kwargs["action_repeat"] = env_globals['action_repeat'] - - # Remove up action - if train_args["env"] == "Kuka2ButtonGymEnv-v0": - env_kwargs["force_down"] = env_globals.get('force_down', True) - else: - env_kwargs["force_down"] = env_globals.get('force_down', False) - - if train_args["env"] == "OmnirobotEnv-v0": - env_kwargs["simple_continual_target"] = env_globals.get("simple_continual_target", False) - env_kwargs["circular_continual_move"] = env_globals.get("circular_continual_move", False) - env_kwargs["square_continual_move"] = env_globals.get("square_continual_move", False) - env_kwargs["eight_continual_move"] = env_globals.get("eight_continual_move", False) - srl_model_path = None - if train_args["srl_model"] != "raw_pixels": - train_args["policy"] = "mlp" - path = env_globals.get('srl_model_path') - - if path is not None: - env_kwargs["use_srl"] = True - # Check that the srl saved model exists on the disk - assert os.path.isfile(env_globals['srl_model_path']), "{} does not exist".format(env_globals['srl_model_path']) - srl_model_path = env_globals['srl_model_path'] - env_kwargs["srl_model_path"] = srl_model_path +import subprocess +import numpy as np +import pickle - return train_args, algo_name, algo_class, srl_model_path, env_kwargs +# log_dir = 'logs/OmnirobotEnv-v0/srl_combination/ppo2/19-04-24_10h36_52/' +# tasks=['cc'] +# episodeEval(log_dir,tasks,save_name='episode_eval.npy',num_timesteps=300) +# for i in range(10): +# time.sleep(1) +# print(i) -def listEnvsKwargs(tasks,env_kwargs): +#episodeEval(log_dir,tasks,save_name='episode_eval.npy',num_timesteps=300) - tasks_env_kwargs=[] - tmp=env_kwargs.copy() - tmp['simple_continual_target'] = False - tmp['circular_continual_move'] = False - tmp['square_continual_move'] = False - tmp['eight_continual_move'] = False +def dict2array(tasks,data): + res=[] for t in tasks: - #For every tasks we create a special env_kwargs to generate different envs - if (t=='sc'): - tmp['simple_continual_target']=True - tasks_env_kwargs.append(tmp.copy()) - tmp['simple_continual_target']=False - elif (t=='cc'): - - tmp['circular_continual_move']=True - tasks_env_kwargs.append(tmp.copy()) - tmp['circular_continual_move']=False - elif (t=='sqc'): - tmp['square_continual_move']=True - tasks_env_kwargs.append(tmp.copy()) - tmp['square_continual_move']=False - elif (t=='ec'): - tmp['eight_continual_move']=True - tasks_env_kwargs.append(tmp.copy()) - tmp['eight_continual_move']=False - return tasks_env_kwargs - -def createEnv( model_dir,train_args, algo_name, algo_class, env_kwargs, log_dir="/tmp/gym/test/",num_cpu=1,seed=0): - - # Log dir for testing the agent - log_dir += "{}/{}/".format(algo_name, datetime.now().strftime("%y-%m-%d_%Hh%M_%S_%f")) - os.makedirs(log_dir, exist_ok=True) - args = { - "env": train_args['env'], - "seed":seed, - "num_cpu": num_cpu, - "num_stack": train_args["num_stack"], - "srl_model": train_args["srl_model"], - "algo_type": train_args.get('algo_type', None), - "log_dir": log_dir - } - algo_args = type('attrib_dict', (), args)() # anonymous class so the dict looks like Arguments object - envs = algo_class.makeEnv(algo_args, env_kwargs=env_kwargs, load_path_normalise=model_dir) - - return log_dir, envs, algo_args - - - - -def policyEval(envs,model_path,log_dir,algo_class,algo_args,num_timesteps=1000,num_cpu=1): - tf.reset_default_graph() - method = algo_class.load(model_path, args=algo_args) - using_custom_vec_env = isinstance(envs, WrapFrameStack) - obs = envs.reset() - if using_custom_vec_env: - obs = obs.reshape((1,) + obs.shape) - n_done = 0 - last_n_done = 0 - episode_reward=[] - dones = [False for _ in range(num_cpu)] - - for i in range(num_timesteps): - actions=method.getAction(obs,dones) - obs, rewards, dones, _ = envs.step(actions) - if using_custom_vec_env: - obs = obs.reshape((1,) + obs.shape) - if using_custom_vec_env: - if dones: - obs = envs.reset() - obs = obs.reshape((1,) + obs.shape) - - n_done += np.sum(dones) - if (n_done - last_n_done) > 1: - last_n_done = n_done - _, mean_reward = computeMeanReward(log_dir, n_done) - episode_reward.append(mean_reward) - - _, mean_reward = computeMeanReward(log_dir, n_done) - - episode_reward.append(mean_reward) - - episode_reward=np.array(episode_reward) - return episode_reward - - - - -def printEnvTasks(list_env_kwargs,tasks): - """ - A Debugger to verify the env_kwargs have the tasks that we want - :param list_env_kwargs: - :param tasks: - :return: - """ - i=0 - for env_kwargs in list_env_kwargs: - - print("For env kwargs {} and task: {}".format(i,tasks[i])) - print("sc :",env_kwargs['simple_continual_target']) - print("ec :", env_kwargs['eight_continual_move']) - print("sqc:", env_kwargs['square_continual_move']) - print("cc :", env_kwargs['circular_continual_move']) - i+=1 - - -def listEnvs(tasks,env_kwargs,train_args, algo_name, algo_class,model_dir): - # For different tasks, we create a list of envs_kwargs to create different envs - list_envs_kwargs = listEnvsKwargs(tasks, env_kwargs) - log_dirs = [] - environments = [] - algo_args_list = [] - for kwargs in list_envs_kwargs: - log_dir, envs, algo_args = createEnv( model_dir, train_args, algo_name, algo_class, kwargs) - log_dirs.append(log_dir) - environments.append(envs) - algo_args_list.append(algo_args) - return (log_dirs,environments,algo_args_list) - - -def latestPolicy(log_dir,algo_name): - files= glob.glob(os.path.join(log_dir+algo_name+'_*_model.pkl')) - files_list = [] - for file in files: - eps=int((file.split('_')[-2])) - files_list.append((eps,file)) - - def sortFirst(val): - return val[0] - - files_list.sort(key=sortFirst) - if len(files_list)>0: - #episode,latest model file path, OK - return files_list[-1][0],files_list[-1][1],True - else: - #No model saved yet - return 0,'',False - -def policyCrossEval(log_dir,tasks,num_timesteps=2000): - - - train_args, algo_name, algo_class, srl_model_path, env_kwargs = loadConfigAndSetup(log_dir) - - episode, model_path,OK=latestPolicy(log_dir,algo_name) - if(not OK): - #no latest model saved yet - return None, None, False - else: - OK=True - printGreen("Evaluation from the model saved at: {}, with evaluation time steps: {}".format(model_path, num_timesteps)) - - log_dirs, environments, algo_args_list = listEnvs( tasks=tasks, env_kwargs=env_kwargs, - train_args=train_args, algo_name=algo_name, algo_class=algo_class, - model_dir=log_dir) - rewards=[] - - for i in range(len(tasks)): - rewards.append(policyEval(environments[i], model_path, log_dirs[i], algo_class, algo_args_list[i], num_timesteps)) - - - #Just a trick to save the episode number of the reward,but need a little bit more space to store - tmp=rewards[-1].copy() - rewards.append(tmp) - rewards=np.array(rewards) - rewards[-1]=episode - - return rewards, OK + res.append(data[t]) + res=np.array(res) + return res +def episodeEval(log_dir, tasks,num_timesteps=1000,num_cpu=1): + for t in tasks: + eval_args=['--log-dir', log_dir, '--num-timesteps', str(num_timesteps), '--num-cpu',str(num_cpu)] + task_args=['--task',t] -''' -The most important function -''' -def episodeEval(log_dir,tasks,save_name='episode_eval.npy'): - #log_dir='logs/OmnirobotEnv-v0/ground_truth/ppo2/19-04-19_14h35_31/' + subprocess.call(['python', '-m', 'rl_baselines.cross_eval_utils']+eval_args+task_args) + file_name=log_dir+'episode_eval.pkl' + with open(file_name, 'rb') as f: + eval_reward = pickle.load(f) - file_name=log_dir+save_name + #Trasfer the data from dict into a numpy array and save + eval_reward=dict2array(tasks,eval_reward) + file_name=log_dir+'episode_eval.npy' + np.save(file_name, eval_reward) - num_timesteps=1000 - if(os.path.isfile(file_name)): - #print(file_name) - eval_reward=np.load(file_name) - # eval_reward: (np.array) [times of evaluation,number of tasks+1,number of episodes in one evaluation ] - episodes=np.unique(eval_reward[:, -1,: ]) - printRed(episodes) - rewards, ok = policyCrossEval(log_dir, tasks, num_timesteps) - # rewards shape: [number of tasks+1, number of episodes in one evaluation] +# if __name__ == '__main__': +# +# log_dir = 'logs/OmnirobotEnv-v0/srl_combination/ppo2/19-04-24_10h36_52/' +# tasks=['cc','sc','sqc'] +# episodeEval(log_dir, tasks, num_timesteps=800, num_cpu=1) - if (ok): - current_episode =np.unique(rewards[-1,:])[0] - #Check if the latest episodes policy is already saved - if (current_episode not in episodes): - eval_reward=np.append(eval_reward,[rewards],axis=0) - np.save(file_name, eval_reward) - else: #There is still not a episodes rewards evaluation registered - rewards, ok = policyCrossEval(log_dir, tasks, num_timesteps) - eval_reward = [] - if(ok): - eval_reward.append(rewards) - eval_reward=np.array(eval_reward) - np.save(file_name, eval_reward) - return diff --git a/rl_baselines/cross_eval_utils.py b/rl_baselines/cross_eval_utils.py new file mode 100644 index 000000000..10da0e203 --- /dev/null +++ b/rl_baselines/cross_eval_utils.py @@ -0,0 +1,327 @@ +""" +Modified version of https://github.com/ikostrikov/pytorch-a2c-ppo-acktr/blob/master/visualize.py +Script used to send plot data to visdom +""" +import glob +import os +import json +import numpy as np +import tensorflow as tf +import pickle +from rl_baselines.utils import WrapFrameStack,computeMeanReward +from stable_baselines.common import set_global_seeds +from rl_baselines import AlgoType +from rl_baselines.registry import registered_rl +from datetime import datetime + +def loadConfigAndSetup(log_dir): + """ + load training variable from a pre-trained model + :param log_dir: the path where the model is located + :return: + """ + algo_name = "" + for algo in list(registered_rl.keys()): + if algo in log_dir: + algo_name = algo + break + algo_class, algo_type, _ = registered_rl[algo_name] + if algo_type == AlgoType.OTHER: + raise ValueError(algo_name + " is not supported for evaluation") + + env_globals = json.load(open(log_dir + "env_globals.json", 'r')) + train_args = json.load(open(log_dir + "args.json", 'r')) + env_kwargs = { + "renders": False, + "shape_reward": False, #TODO, since we dont use simple target, we should elimanate this choice? + "action_joints": train_args["action_joints"], + "is_discrete": not train_args["continuous_actions"], + "random_target": train_args.get('random_target', False), + "srl_model": train_args["srl_model"] + } + + # load it, if it was defined + if "action_repeat" in env_globals: + env_kwargs["action_repeat"] = env_globals['action_repeat'] + + # Remove up action + if train_args["env"] == "Kuka2ButtonGymEnv-v0": + env_kwargs["force_down"] = env_globals.get('force_down', True) + else: + env_kwargs["force_down"] = env_globals.get('force_down', False) + + if train_args["env"] == "OmnirobotEnv-v0": + env_kwargs["simple_continual_target"] = env_globals.get("simple_continual_target", False) + env_kwargs["circular_continual_move"] = env_globals.get("circular_continual_move", False) + env_kwargs["square_continual_move"] = env_globals.get("square_continual_move", False) + env_kwargs["eight_continual_move"] = env_globals.get("eight_continual_move", False) + + srl_model_path = None + if train_args["srl_model"] != "raw_pixels": + train_args["policy"] = "mlp" + path = env_globals.get('srl_model_path') + + if path is not None: + env_kwargs["use_srl"] = True + # Check that the srl saved model exists on the disk + assert os.path.isfile(env_globals['srl_model_path']), "{} does not exist".format(env_globals['srl_model_path']) + srl_model_path = env_globals['srl_model_path'] + env_kwargs["srl_model_path"] = srl_model_path + + return train_args, algo_name, algo_class, srl_model_path, env_kwargs + +def EnvsKwargs(task,env_kwargs): + """ + create several environments kwargs + :param tasks: the task we need the omnirobot to perform + :param env_kwargs: the original env_kwargs from previous pre-trained odel + :return: a list of env_kwargs that has the same length as tasks + """ + t=task + + tmp=env_kwargs.copy() + tmp['simple_continual_target'] = False + tmp['circular_continual_move'] = False + tmp['square_continual_move'] = False + tmp['eight_continual_move'] = False + + + if (t=='sc'): + tmp['simple_continual_target']=True + + elif (t=='cc'): + tmp['circular_continual_move']=True + elif (t=='sqc'): + tmp['square_continual_move']=True + elif (t=='ec'): + tmp['eight_continual_move']=True + + return tmp + +def createEnv( model_dir,train_args, algo_name, algo_class, env_kwargs, log_dir="/tmp/gym/test/",num_cpu=1,seed=0): + """ + create the environment from env)kwargs + :param model_dir: The file name of the file which contains the pkl + :param train_args: + :param algo_name: + :param algo_class: + :param env_kwargs: + :param log_dir: + :param num_cpu: + :param seed: + :return: + """ + # Log dir for testing the agent + log_dir += "{}/{}/".format(algo_name, datetime.now().strftime("%y-%m-%d_%Hh%M_%S_%f")) + os.makedirs(log_dir, exist_ok=True) + args = { + "env": train_args['env'], + "seed":seed, + "num_cpu": num_cpu, + "num_stack": train_args["num_stack"], + "srl_model": train_args["srl_model"], + "algo_type": train_args.get('algo_type', None), + "log_dir": log_dir + } + algo_args = type('attrib_dict', (), args)() # anonymous class so the dict looks like Arguments object + envs = algo_class.makeEnv(algo_args, env_kwargs=env_kwargs, load_path_normalise=model_dir) + + return log_dir, envs, algo_args + + + + +def policyEval(envs,model_path,log_dir,algo_class,algo_args,num_timesteps=1000,num_cpu=1): + """ + evaluation for the policy in the given envs + :param envs: the environment we want to evaluate + :param model_path: (str)the path to the policy ckp + :param log_dir: (str) the path from a gym temporal file + :param algo_class: + :param algo_args: + :param num_timesteps: (int) numbers of the timesteps we want to evaluate the policy + :param num_cpu: + :return: + """ + + + tf.reset_default_graph() + + method = algo_class.load(model_path, args=algo_args) + + using_custom_vec_env = isinstance(envs, WrapFrameStack) + + obs = envs.reset() + + + if using_custom_vec_env: + obs = obs.reshape((1,) + obs.shape) + n_done = 0 + last_n_done = 0 + episode_reward=[] + dones = [False for _ in range(num_cpu)] + + for i in range(num_timesteps): + set_global_seeds(i) + actions=method.getAction(obs,dones) + obs, rewards, dones, _ = envs.step(actions) + if using_custom_vec_env: + obs = obs.reshape((1,) + obs.shape) + if using_custom_vec_env: + if dones: + obs = envs.reset() + obs = obs.reshape((1,) + obs.shape) + + n_done += np.sum(dones) + if (n_done - last_n_done) > 1: + last_n_done = n_done + _, mean_reward = computeMeanReward(log_dir, n_done) + episode_reward.append(mean_reward) + #printRed('Episode:{} Reward:{}'.format(n_done,mean_reward)) + _, mean_reward = computeMeanReward(log_dir, n_done) + #printRed('Episode:{} Reward:{}'.format(n_done, mean_reward)) + + episode_reward.append(mean_reward) + + episode_reward=np.array(episode_reward) + envs.close() + return episode_reward + + + + + + +def latestPolicy(log_dir,algo_name): + """ + Get the latest saved model from a file + :param log_dir: (str) a path leads to the model saved path + :param algo_name: + :return: the file name of the latest saved policy and a flag + """ + files= glob.glob(os.path.join(log_dir+algo_name+'_*_model.pkl')) + files_list = [] + for file in files: + eps=int((file.split('_')[-2])) + files_list.append((eps,file)) + + def sortFirst(val): + return val[0] + + files_list.sort(key=sortFirst) + if len(files_list)>0: + #episode,latest model file path, OK + return files_list[-1][0],files_list[-1][1],True + else: + #No model saved yet + return 0,'',False + +def policyCrossEval(log_dir,task,num_timesteps=2000,num_cpu=1): + """ + Given several tasks and a logdir, to evaluate the policy on different environments corresponding to the tasks + :param log_dir: + :param tasks: + :param num_timesteps: + :return: + """ + + train_args, algo_name, algo_class, srl_model_path, env_kwargs = loadConfigAndSetup(log_dir) + + episode, model_path,OK=latestPolicy(log_dir,algo_name) + env_kwargs = EnvsKwargs(task, env_kwargs) + + OK=True + if(not OK): + #no latest model saved yet + return None, False + else: + pass + printGreen("Evaluation from the model saved at: {}, with evaluation time steps: {}".format(model_path, num_timesteps)) + + log_dir, environment, algo_args = createEnv(log_dir, train_args, algo_name, algo_class, env_kwargs,num_cpu=num_cpu) + + + reward=policyEval(environment, model_path, log_dir, algo_class, algo_args, num_timesteps,num_cpu) + + + #Just a trick to save the episode number of the reward,but need a little bit more space to store + reward=np.append(episode,reward) + return reward, True + + + + +def episodeEval(log_dir,task,save_name='episode_eval.pkl',num_timesteps=800,num_cpu=1): + """ + given a log_dir to the model path and different tasks for ominirobot, save the reward of the latest saved model + it will not save anything if the old policy has already been evaluated + :param log_dir: + :param tasks: + :param save_name: the file name to save the policy evaluation result. + :return: + """ + + file_name=log_dir+save_name + + #can be changed accordingly + + + + + if(os.path.isfile(file_name)): + + #eval_reward=np.load(file_name) + with open(file_name, 'rb') as f: + eval_reward= pickle.load(f) + + + reward, ok = policyCrossEval(log_dir, task, num_timesteps,num_cpu=num_cpu) + if (ok): + if (task in eval_reward.keys()): + episodes = np.unique(eval_reward[task][:, 0]) + + current_episode =reward[0] + #Check if the latest episodes policy is already saved + if (current_episode not in episodes): + eval_reward[task]=np.append(eval_reward[task],[reward],axis=0) + with open(file_name, 'wb') as f: + pickle.dump(eval_reward, f, pickle.HIGHEST_PROTOCOL) + else:# The task is not in the file yet + eval_reward[task] =reward[None,:] + with open(file_name, 'wb') as f: + pickle.dump(eval_reward, f, pickle.HIGHEST_PROTOCOL) + + + else: #There is still not a episodes rewards evaluation registered + reward, ok = policyCrossEval(log_dir, task, num_timesteps,num_cpu=num_cpu) + eval_reward = {} + if(ok): + eval_reward[task]=reward[None,:] + + + with open(file_name, 'wb') as f: + pickle.dump(eval_reward, f, pickle.HIGHEST_PROTOCOL) + + return + + +if __name__ == '__main__': + import argparse + # + # log_dir ='logs/OmnirobotEnv-v0/ground_truth/ppo2/19-04-23_17h44_32/' # sc + # + # log_dir = 'logs/OmnirobotEnv-v0/ground_truth/ppo2/19-04-23_17h35_17/' # cc + # cc + + parser = argparse.ArgumentParser(description="several runtime for cross evaluation", + epilog='') + parser.add_argument('--task', type=str, default='cc', help='task',choices=['cc','sc','sqc']) + parser.add_argument('--log-dir', type=str, default='', help='the directory to policy',required=True) + parser.add_argument('--num-timesteps', type=int, default=1000, help='time steps to evaluate the policy', ) + parser.add_argument('--num-cpu', type=int, default=1, help='number of cpu to perform the evaluation') + + args,_= parser.parse_known_args() + #tasks=['cc'] + task=args.task + log_dir=args.log_dir + episodeEval(log_dir,task,save_name='episode_eval.pkl',num_timesteps=args.num_timesteps,num_cpu=args.num_cpu) diff --git a/rl_baselines/train.py b/rl_baselines/train.py index a0abebe27..f48ac1151 100644 --- a/rl_baselines/train.py +++ b/rl_baselines/train.py @@ -21,7 +21,7 @@ from rl_baselines.utils import computeMeanReward from rl_baselines.utils import filterJSONSerializableObjects from rl_baselines.visualize import timestepsPlot, episodePlot,episodesEvalPlot -from rl_baselines.cross_eval import episodeEval,policyCrossEval +from rl_baselines.cross_eval import episodeEval from srl_zoo.utils import printGreen, printYellow from state_representation import SRLType from state_representation.registry import registered_srl diff --git a/rl_baselines/visualize.py b/rl_baselines/visualize.py index 3bce727b1..22fd450f8 100644 --- a/rl_baselines/visualize.py +++ b/rl_baselines/visualize.py @@ -224,19 +224,16 @@ def episodesEvalPlot(viz, win, folder, game, name, window=1, title=""): if len(result) == 0: return win + print(result.shape) + + y = np.mean(result[:, :, 1:], axis=2).T - y = np.mean(result[:,:-1,:], axis=2) - - x = result[:, -1,:][:,0][:,None] - x = x*np.ones(shape=y.shape) - print(y.shape,x.shape,name) + x = result[:, :, 0].T if y.shape[0] < window: return win - # y = movingAverage(y, window) - if len(y) == 0: return win From 7e39645932dc0011c637280be6757fc7b982efcb Mon Sep 17 00:00:00 2001 From: TeTe <32313299+sun-te@users.noreply.github.com> Date: Fri, 26 Apr 2019 11:01:05 +0200 Subject: [PATCH 066/141] Update Distilation_Readme.md No need to enter srl_zoo dict at first when generating data --- Distilation_Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Distilation_Readme.md b/Distilation_Readme.md index 940fb1f77..643ecd4cf 100644 --- a/Distilation_Readme.md +++ b/Distilation_Readme.md @@ -13,7 +13,7 @@ ### 0 - Generate datasets for SRL (random policy) ``` -cd srl_zoo +cd robotics-rl-srl # Dataset 1 (random reaching target) python -m environments.dataset_generator --num-cpu 6 --name Omnibot_random_simple --env OmnirobotEnv-v0 --simple-continual --num-episode 250 -f # Dataset 2 (Circular task) From 619cd6b5c11bd7ed6a1b601a916c6cfb85538138 Mon Sep 17 00:00:00 2001 From: TeTe <32313299+sun-te@users.noreply.github.com> Date: Fri, 26 Apr 2019 13:20:37 +0200 Subject: [PATCH 067/141] Update Distilation_Readme.md --- Distilation_Readme.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Distilation_Readme.md b/Distilation_Readme.md index 643ecd4cf..4e1b45fc4 100644 --- a/Distilation_Readme.md +++ b/Distilation_Readme.md @@ -42,12 +42,10 @@ cd .. cp config/srl_models.yaml config/srl_models_temp.yaml # Dataset 1 (random reaching target) -cp config/srl_models_simple.yaml config/srl_models.yaml -python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --num-timesteps 1000000 --env OmnirobotEnv-v0 --log-dir logs/simple/ --num-cpu 8 --simple-continual --latest +python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --srl-config-file config/srl_models_simple.yaml --num-timesteps 1000000 --env OmnirobotEnv-v0 --log-dir logs/simple/ --num-cpu 8 --simple-continual --latest # Dataset 2 (Circular task) -cp config/srl_models_circular.yaml config/srl_models.yaml -python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --num-timesteps 1000000 --env OmnirobotEnv-v0 --log-dir logs/circular/ --num-cpu 6 --circular-continual --latest +python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --srl-config-file config/srl_models_circular.yaml --num-timesteps 1000000 --env OmnirobotEnv-v0 --log-dir logs/circular/ --num-cpu 6 --circular-continual --latest # restore config file cp config/srl_models_temp.yaml config/srl_models.yaml From eee27f46aa11a7aa423ab21ca502bc2050a85e35 Mon Sep 17 00:00:00 2001 From: sun-te Date: Fri, 26 Apr 2019 13:22:31 +0200 Subject: [PATCH 068/141] cross eval --- rl_baselines/cross_eval_utils.py | 5 +---- rl_baselines/train.py | 14 +++++++------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/rl_baselines/cross_eval_utils.py b/rl_baselines/cross_eval_utils.py index 10da0e203..edab97b2e 100644 --- a/rl_baselines/cross_eval_utils.py +++ b/rl_baselines/cross_eval_utils.py @@ -8,7 +8,7 @@ import numpy as np import tensorflow as tf import pickle -from rl_baselines.utils import WrapFrameStack,computeMeanReward +from rl_baselines.utils import WrapFrameStack,computeMeanReward,printGreen from stable_baselines.common import set_global_seeds from rl_baselines import AlgoType from rl_baselines.registry import registered_rl @@ -189,9 +189,6 @@ def policyEval(envs,model_path,log_dir,algo_class,algo_args,num_timesteps=1000,n - - - def latestPolicy(log_dir,algo_name): """ Get the latest saved model from a file diff --git a/rl_baselines/train.py b/rl_baselines/train.py index f48ac1151..2938cdfa9 100644 --- a/rl_baselines/train.py +++ b/rl_baselines/train.py @@ -166,11 +166,11 @@ def callback(_locals, _globals): best_mean_reward = mean_reward printGreen("Saving new best model") ALGO.save(LOG_DIR + ALGO_NAME + "_model.pkl", _locals) - if n_episodes >0 and n_episodes%20==0: - # Cross evaluation for all tasks: - ALGO.save(LOG_DIR + ALGO_NAME +"_"+str(n_episodes)+ "_model.pkl", _locals) - printYellow(EVAL_TASK) - episodeEval(LOG_DIR, EVAL_TASK) + # if n_episodes >0 and n_episodes%100==0: + # # Cross evaluation for all tasks: + # ALGO.save(LOG_DIR + ALGO_NAME +"_"+str(n_episodes)+ "_model.pkl", _locals) + # printYellow(EVAL_TASK) + # episodeEval(LOG_DIR, EVAL_TASK) # Plots in visdom if viz and (n_steps + 1) % LOG_INTERVAL == 0: @@ -179,8 +179,8 @@ def callback(_locals, _globals): is_es=is_es) win_episodes = episodePlot(viz, win_episodes, LOG_DIR, ENV_NAME, ALGO_NAME, window=EPISODE_WINDOW, title=PLOT_TITLE + " [Episodes]", is_es=is_es) - win_crossEval= episodesEvalPlot(viz,win_crossEval,LOG_DIR,ENV_NAME,EVAL_TASK, - title=PLOT_TITLE +" [Cross Evaluation]") + # win_crossEval= episodesEvalPlot(viz,win_crossEval,LOG_DIR,ENV_NAME,EVAL_TASK, + # title=PLOT_TITLE +" [Cross Evaluation]") n_steps += 1 return True From 34fff5dc7f80a1681ed42fada6dfa500305ee648 Mon Sep 17 00:00:00 2001 From: kalifou Date: Fri, 26 Apr 2019 15:00:11 +0200 Subject: [PATCH 069/141] fix MLP Policy for distillation --- .../supervised_rl/policy_distillation.py | 35 ++++++++++--------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/rl_baselines/supervised_rl/policy_distillation.py b/rl_baselines/supervised_rl/policy_distillation.py index 6afa37193..563e9215e 100644 --- a/rl_baselines/supervised_rl/policy_distillation.py +++ b/rl_baselines/supervised_rl/policy_distillation.py @@ -29,26 +29,21 @@ class MLPPolicy(nn.Module): - def __init__(self, output_size, input_size, hidden_size=400): + def __init__(self, output_size, input_size, hidden_size=16): super(MLPPolicy, self).__init__() self.input_size = input_size self.hidden_size = hidden_size self.output_size = output_size - self.fc1 = nn.Linear(self.input_size, self.hidden_size) - self.fc2 = nn.Linear(self.hidden_size, self.hidden_size) - self.fc3 = nn.Linear(self.hidden_size, self.hidden_size) - self.fc4 = nn.Linear(self.hidden_size, self.output_size) + self.fc = nn.Sequential(nn.Linear(self.input_size, self.hidden_size), + nn.ReLU(inplace=True), + nn.Linear(self.hidden_size, self.output_size) + ) def forward(self, input): - input = input.view(-1, self.input_size) - x = F.relu(self.fc1(input)) - x = F.relu(self.fc2(x)) - x = F.relu(self.fc3(x)) - x = F.softmax(self.fc4(x), dim=1) - return x + return F.softmax(self.fc(input), dim=1) class CNNPolicy(nn.Module): @@ -223,20 +218,25 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): # TODO: add sanity checks & test for all possible SRL for distillation if env_kwargs["srl_model"] == "raw_pixels": self.model = CNNPolicy(n_actions) + learnable_params = self.model.parameters() + learning_rate = 1e-3 + else: self.state_dim = getSRLDim(env_kwargs.get("srl_model_path", None)) self.srl_model = loadSRLModel(env_kwargs.get("srl_model_path", None), th.cuda.is_available(), self.state_dim, env_object=None) - self.model = MLPPolicy(n_actions, self.state_dim) + self.model = MLPPolicy(output_size=n_actions, input_size=self.state_dim) + for param in self.model.parameters(): + param.requires_grad = True + learnable_params = [param for param in self.model.parameters()] + learning_rate = 1e-3 self.device = th.device("cuda" if th.cuda.is_available() else "cpu") if th.cuda.is_available(): self.model.cuda() - learnable_params = self.model.parameters() - self.optimizer = th.optim.Adam(learnable_params, lr=1e-3) - + self.optimizer = th.optim.Adam(learnable_params, lr=learning_rate) best_error = np.inf best_model_path = "{}/distillation_model.pkl".format(args.log_dir) @@ -247,6 +247,7 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): pbar = tqdm(total=len(minibatchlist)) for minibatch_num, (minibatch_idx, obs, _, _, _) in enumerate(data_loader): + self.optimizer.zero_grad() obs = obs.to(self.device) validation_mode = minibatch_idx in val_indices @@ -277,7 +278,8 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): pred_action = self.model.forward(state) loss = self.loss_fn_kd(pred_action, actions_proba_st.float(), - labels=cl_labels_st, adaptive_temperature=USE_ADAPTIVE_TEMPERATURE) + labels=cl_labels_st, adaptive_temperature=USE_ADAPTIVE_TEMPERATURE) + loss.backward() if validation_mode: @@ -289,7 +291,6 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): epoch_loss += loss.item() epoch_batches += 1 pbar.update(1) - self.optimizer.zero_grad() train_loss = epoch_loss / float(epoch_batches) val_loss /= float(n_val_batches) From ef8146175391a5e2921cd7846fa2a3ffc5ecd25e Mon Sep 17 00:00:00 2001 From: TLESORT Date: Fri, 26 Apr 2019 16:31:51 +0200 Subject: [PATCH 070/141] add automatic creation of save_path if the folder does not exist --- environments/dataset_generator.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/environments/dataset_generator.py b/environments/dataset_generator.py index e75937281..b0d41380c 100644 --- a/environments/dataset_generator.py +++ b/environments/dataset_generator.py @@ -278,6 +278,9 @@ def main(): assert not (args.log_generative_model == '' and args.replay_generative_model == 'custom'), \ "If using a custom policy, please specify a valid log folder for loading it." + if not os.path.exists(args.save_path): + os.makedirs(args.save_path) + # this is done so seed 0 and 1 are different and not simply offset of the same datasets. args.seed = np.random.RandomState(args.seed).randint(int(1e10)) From a90681b296fdc09d8f60fdb377ac17fb8b97b242 Mon Sep 17 00:00:00 2001 From: TLESORT Date: Fri, 26 Apr 2019 17:37:24 +0200 Subject: [PATCH 071/141] add latest past possible (to use carefully) --- environments/dataset_generator.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/environments/dataset_generator.py b/environments/dataset_generator.py index b0d41380c..0e7d0945a 100644 --- a/environments/dataset_generator.py +++ b/environments/dataset_generator.py @@ -31,6 +31,12 @@ os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' # used to remove debug info of tensorflow +def latestPath(path): + """ + :param path: path to the log folder (defined in srl_model.yaml) (str) + :return: path to latest learned model in the same dataset folder (str) + """ + return max([path + d for d in os.listdir(path) if os.path.isdir(path + "/" + d)],key=os.path.getmtime) + '/' def convertImagePath(args, path, record_id_start): """ @@ -95,7 +101,7 @@ def env_thread(args, thread_num, partition=True): generated_obs = None if args.run_policy == "custom": - args.log_dir = args.log_custom_policy + args.log_dir = latestPath(args.log_custom_policy) args.render = args.display args.plotting, args.action_proba = False, False @@ -253,6 +259,7 @@ def main(): parser.add_argument('-sqc', '--square-continual', action='store_true', default=False, help='Green square target for task 3 of continual learning scenario. ' + 'The task is: robot should turn in square around the target.') + parser.add_argument('--short-episodes', action='store_true', default=False, help='Generate short episodes (only 10 contacts with the target allowed).') From 4ab3c49fe5677bed54c4aea90d1de9df5056e938 Mon Sep 17 00:00:00 2001 From: TLESORT Date: Fri, 26 Apr 2019 17:44:08 +0200 Subject: [PATCH 072/141] add latest flag --- environments/dataset_generator.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/environments/dataset_generator.py b/environments/dataset_generator.py index 0e7d0945a..924d0a415 100644 --- a/environments/dataset_generator.py +++ b/environments/dataset_generator.py @@ -101,7 +101,10 @@ def env_thread(args, thread_num, partition=True): generated_obs = None if args.run_policy == "custom": - args.log_dir = latestPath(args.log_custom_policy) + if args.latest: + args.log_dir = latestPath(args.log_custom_policy) + else: + args.log_dir = args.log_custom_policy args.render = args.display args.plotting, args.action_proba = False, False @@ -242,6 +245,8 @@ def main(): '(random, localy pretrained ppo2, pretrained custom policy)') parser.add_argument('--log-custom-policy', type=str, default='', help='Logs of the custom pretained policy to run for data collection') + parser.add_argument('--latest', action='store_true', default=False, + help='load the latest learned model (location: args.log-custom-policy)') parser.add_argument('-rgm', '--replay-generative-model', type=str, default="", choices=['vae'], help='Generative model to replay for generating a dataset (for Continual Learning purposes)') parser.add_argument('--log-generative-model', type=str, default='', From 6fd19d19397d4d7ea96bbb6cadd57cdd5f4bb900 Mon Sep 17 00:00:00 2001 From: sun-te Date: Fri, 26 Apr 2019 17:44:30 +0200 Subject: [PATCH 073/141] normalisation of reward --- rl_baselines/cross_eval.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/rl_baselines/cross_eval.py b/rl_baselines/cross_eval.py index 1bd2dea1d..faaa13cbc 100644 --- a/rl_baselines/cross_eval.py +++ b/rl_baselines/cross_eval.py @@ -14,8 +14,13 @@ def dict2array(tasks,data): res=[] + for t in tasks: - res.append(data[t]) + if(t=='sc'): + max_reward=250 + else: + max_reward=1850 + res.append(data[t]/max_reward) res=np.array(res) return res From 6b37395b32ce210ec48f04250db6c0a770ac0051 Mon Sep 17 00:00:00 2001 From: TLESORT Date: Fri, 26 Apr 2019 17:44:40 +0200 Subject: [PATCH 074/141] update and fix readme with comments --- Distilation_Readme.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Distilation_Readme.md b/Distilation_Readme.md index 6922f9b52..ccfd26cf2 100644 --- a/Distilation_Readme.md +++ b/Distilation_Readme.md @@ -82,12 +82,15 @@ python -m replay.plots --log-dir /logs/circular/OmnirobotEnv-v0/srl_combination/ ``` # Dataset 1 (random reaching target) -python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 600 --run-policy custom --log-custom-policy logs/*path2policy* --short-episodes --save-path data/ --name reaching_on_policy -sc +python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 100 --run-policy custom --log-custom-policy logs/*path2policy* --short-episodes --save-path data/ --name reaching_on_policy -sc # Dataset 2 (Circular task) python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 100 --run-policy custom --log-custom-policy logs/*path2policy* --short-episodes --save-path data/ --name circular_on_policy -cc # Merge Datasets + +(/ ! \ it removes the generated dataset for dataset 1 and 2) + python -m environments.dataset_fusioner --merge data/circular_on_policy/ data/reaching_on_policy/ data/merge_CC_SC # Copy the merged Dataset to srl_zoo repository From 919fc9b1f61f2bb7a70769d5378fd8266994ae3b Mon Sep 17 00:00:00 2001 From: TLESORT Date: Fri, 26 Apr 2019 17:47:03 +0200 Subject: [PATCH 075/141] first version of script to run all in once --- run_policy.sh | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 run_policy.sh diff --git a/run_policy.sh b/run_policy.sh new file mode 100644 index 000000000..709af8257 --- /dev/null +++ b/run_policy.sh @@ -0,0 +1,75 @@ + + + + + +policy="ppo2" +env="OmnirobotEnv-v0" + + +### 0 - Generate datasets for SRL (random policy) +# Dataset 1 (random reaching target) +python -m environments.dataset_generator --num-cpu 6 --name Omnibot_random_simple --env $env --simple-continual --num-episode 250 -f +# Dataset 2 (Circular task) +python -m environments.dataset_generator --num-cpu 6 --name Omnibot_random_circular --env $env --circular-continual --num-episode 250 -f + + +### 1.1) Train SRL + +cd srl_zoo +# Dataset 1 (random reaching target) +python train.py --data-folder data/Omnibot_random_simple -bs 32 --epochs 20 --state-dim 200 --training-set-size 20000 --losses autoencoder inverse +# Dataset 2 (Circular task) +python train.py --data-folder data/Omnibot_random_circular -bs 32 --epochs 20 --state-dim 200 --training-set-size 20000 --losses autoencoder inverse + +### 1.2) Train policy +cd .. + +# Dataset 1 (random reaching target) +cp config/srl_models_simple.yaml config/srl_models.yaml +python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --num-timesteps 1000000 --env OmnirobotEnv-v0 --log-dir logs/simple/ --num-cpu 8 --simple-continual --latest + +# Dataset 2 (Circular task) +cp config/srl_models_circular.yaml config/srl_models.yaml +python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --num-timesteps 1000000 --env OmnirobotEnv-v0 --log-dir logs/circular/ --num-cpu 6 --circular-continual --latest + + + +# Dataset 1 (random reaching target) + + +path2policy="logs/simple/OmnirobotEnv-v0/srl_combination/ppo2/" + +python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 100 --run-policy custom --log-custom-policy $path2policy --short-episodes --save-path data/ --name reaching_on_policy -sc --latest + + +path2policy="logs/circular/OmnirobotEnv-v0/srl_combination/ppo2/" +# Dataset 2 (Circular task) +python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 100 --run-policy custom --log-custom-policy logs/*path2policy* --short-episodes --save-path data/ --name circular_on_policy -cc --latest + +# Merge Datasets + +(/ ! \ it removes the generated dataset for dataset 1 and 2) + +python -m environments.dataset_fusioner --merge data/circular_on_policy/ data/reaching_on_policy/ data/merge_CC_SC + +# Copy the merged Dataset to srl_zoo repository +cp -r data/merge_CC_SC srl_zoo/data/merge_CC_SC + + +### 2.3) Train SRL 1&2 + +cd srl_zoo +# Dataset 1 +python train.py --data-folder data/merge_CC_SC -bs 32 --epochs 20 --state-dim 200 --training-set-size 30000--losses autoencoder inverse + + +### 2.3) Run Distillation + +``` +# make a new log folder +mkdir logs/CL_SC_CC +cp config/srl_models_merged.yaml config/srl_models.yaml + +# Merged Dataset +python -m rl_baselines.train --algo distillation --srl-model srl_combination --env OmnirobotEnv-v0 --log-dir logs/CL_SC_CC --teacher-data-folder srl_zoo/data/merge_CC_SC -cc --distillation-training-set-size 40000 --epochs-distillation 20 --latest From 66b6bdf3a7fc264c5be3fd391da6f9601a23a8a2 Mon Sep 17 00:00:00 2001 From: TLESORT Date: Fri, 26 Apr 2019 17:51:21 +0200 Subject: [PATCH 076/141] small fix, NB : starting from a clean repos is recommended to run the script --- run_policy.sh | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/run_policy.sh b/run_policy.sh index 709af8257..0e410d927 100644 --- a/run_policy.sh +++ b/run_policy.sh @@ -9,9 +9,9 @@ env="OmnirobotEnv-v0" ### 0 - Generate datasets for SRL (random policy) # Dataset 1 (random reaching target) -python -m environments.dataset_generator --num-cpu 6 --name Omnibot_random_simple --env $env --simple-continual --num-episode 250 -f +python -m environments.dataset_generator --num-cpu 8 --name Omnibot_random_simple --env $env --simple-continual --num-episode 250 -f # Dataset 2 (Circular task) -python -m environments.dataset_generator --num-cpu 6 --name Omnibot_random_circular --env $env --circular-continual --num-episode 250 -f +python -m environments.dataset_generator --num-cpu 8 --name Omnibot_random_circular --env $env --circular-continual --num-episode 250 -f ### 1.1) Train SRL @@ -31,21 +31,20 @@ python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --num-times # Dataset 2 (Circular task) cp config/srl_models_circular.yaml config/srl_models.yaml -python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --num-timesteps 1000000 --env OmnirobotEnv-v0 --log-dir logs/circular/ --num-cpu 6 --circular-continual --latest +python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --num-timesteps 1000000 --env OmnirobotEnv-v0 --log-dir logs/circular/ --num-cpu 8 --circular-continual --latest # Dataset 1 (random reaching target) - +# Dataset 1 (random reaching target) path2policy="logs/simple/OmnirobotEnv-v0/srl_combination/ppo2/" - python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 100 --run-policy custom --log-custom-policy $path2policy --short-episodes --save-path data/ --name reaching_on_policy -sc --latest -path2policy="logs/circular/OmnirobotEnv-v0/srl_combination/ppo2/" # Dataset 2 (Circular task) -python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 100 --run-policy custom --log-custom-policy logs/*path2policy* --short-episodes --save-path data/ --name circular_on_policy -cc --latest +path2policy="logs/circular/OmnirobotEnv-v0/srl_combination/ppo2/" +python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 100 --run-policy custom --log-custom-policy $path2policy --short-episodes --save-path data/ --name circular_on_policy -cc --latest # Merge Datasets From be7b7798d01321227acd55a8f6ea010f55e7fe24 Mon Sep 17 00:00:00 2001 From: TLESORT Date: Fri, 26 Apr 2019 18:34:20 +0200 Subject: [PATCH 077/141] tested run in once script --- run_policy.sh | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/run_policy.sh b/run_policy.sh index 709af8257..657fe4caf 100644 --- a/run_policy.sh +++ b/run_policy.sh @@ -9,9 +9,9 @@ env="OmnirobotEnv-v0" ### 0 - Generate datasets for SRL (random policy) # Dataset 1 (random reaching target) -python -m environments.dataset_generator --num-cpu 6 --name Omnibot_random_simple --env $env --simple-continual --num-episode 250 -f +python -m environments.dataset_generator --num-cpu 8 --name Omnibot_random_simple --env $env --simple-continual --num-episode 250 -f # Dataset 2 (Circular task) -python -m environments.dataset_generator --num-cpu 6 --name Omnibot_random_circular --env $env --circular-continual --num-episode 250 -f +python -m environments.dataset_generator --num-cpu 8 --name Omnibot_random_circular --env $env --circular-continual --num-episode 250 -f ### 1.1) Train SRL @@ -27,29 +27,28 @@ cd .. # Dataset 1 (random reaching target) cp config/srl_models_simple.yaml config/srl_models.yaml -python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --num-timesteps 1000000 --env OmnirobotEnv-v0 --log-dir logs/simple/ --num-cpu 8 --simple-continual --latest +python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --num-timesteps 500000 --env OmnirobotEnv-v0 --log-dir logs/simple/ --num-cpu 8 --simple-continual --latest # Dataset 2 (Circular task) cp config/srl_models_circular.yaml config/srl_models.yaml -python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --num-timesteps 1000000 --env OmnirobotEnv-v0 --log-dir logs/circular/ --num-cpu 6 --circular-continual --latest +python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --num-timesteps 100000 --env OmnirobotEnv-v0 --log-dir logs/circular/ --num-cpu 8 --circular-continual --latest # Dataset 1 (random reaching target) - +# Dataset 1 (random reaching target) path2policy="logs/simple/OmnirobotEnv-v0/srl_combination/ppo2/" - python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 100 --run-policy custom --log-custom-policy $path2policy --short-episodes --save-path data/ --name reaching_on_policy -sc --latest -path2policy="logs/circular/OmnirobotEnv-v0/srl_combination/ppo2/" # Dataset 2 (Circular task) -python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 100 --run-policy custom --log-custom-policy logs/*path2policy* --short-episodes --save-path data/ --name circular_on_policy -cc --latest +path2policy="logs/circular/OmnirobotEnv-v0/srl_combination/ppo2/" +python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 100 --run-policy custom --log-custom-policy $path2policy --short-episodes --save-path data/ --name circular_on_policy -cc --latest # Merge Datasets -(/ ! \ it removes the generated dataset for dataset 1 and 2) +#(/ ! \ it removes the generated dataset for dataset 1 and 2) python -m environments.dataset_fusioner --merge data/circular_on_policy/ data/reaching_on_policy/ data/merge_CC_SC @@ -61,15 +60,16 @@ cp -r data/merge_CC_SC srl_zoo/data/merge_CC_SC cd srl_zoo # Dataset 1 -python train.py --data-folder data/merge_CC_SC -bs 32 --epochs 20 --state-dim 200 --training-set-size 30000--losses autoencoder inverse +python train.py --data-folder data/merge_CC_SC -bs 32 --epochs 20 --state-dim 200 --training-set-size 30000 --losses autoencoder inverse ### 2.3) Run Distillation -``` # make a new log folder mkdir logs/CL_SC_CC cp config/srl_models_merged.yaml config/srl_models.yaml # Merged Dataset +cd .. python -m rl_baselines.train --algo distillation --srl-model srl_combination --env OmnirobotEnv-v0 --log-dir logs/CL_SC_CC --teacher-data-folder srl_zoo/data/merge_CC_SC -cc --distillation-training-set-size 40000 --epochs-distillation 20 --latest + From 162d96ad20ab91d00c3e51817faed5ee7c015906 Mon Sep 17 00:00:00 2001 From: TLESORT Date: Fri, 26 Apr 2019 18:35:19 +0200 Subject: [PATCH 078/141] dry run file for end to end testing --- run_policy_dry_run.sh | 75 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100755 run_policy_dry_run.sh diff --git a/run_policy_dry_run.sh b/run_policy_dry_run.sh new file mode 100755 index 000000000..702923ed9 --- /dev/null +++ b/run_policy_dry_run.sh @@ -0,0 +1,75 @@ + + + + + +policy="ppo2" +env="OmnirobotEnv-v0" + + +### 0 - Generate datasets for SRL (random policy) +# Dataset 1 (random reaching target) +python -m environments.dataset_generator --num-cpu 8 --name Omnibot_random_simple --env $env --simple-continual --num-episode 1 -f +# Dataset 2 (Circular task) +python -m environments.dataset_generator --num-cpu 8 --name Omnibot_random_circular --env $env --circular-continual --num-episode 1 -f + + +### 1.1) Train SRL + +cd srl_zoo +# Dataset 1 (random reaching target) +python train.py --data-folder data/Omnibot_random_simple -bs 32 --epochs 2 --state-dim 200 --training-set-size 20000 --losses autoencoder inverse +# Dataset 2 (Circular task) +python train.py --data-folder data/Omnibot_random_circular -bs 32 --epochs 2 --state-dim 200 --training-set-size 20000 --losses autoencoder inverse + +### 1.2) Train policy +cd .. + +# Dataset 1 (random reaching target) +cp config/srl_models_simple.yaml config/srl_models.yaml +python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --num-timesteps 30000 --env OmnirobotEnv-v0 --log-dir logs/simple/ --num-cpu 8 --simple-continual --latest + +# Dataset 2 (Circular task) +cp config/srl_models_circular.yaml config/srl_models.yaml +python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --num-timesteps 30000 --env OmnirobotEnv-v0 --log-dir logs/circular/ --num-cpu 8 --circular-continual --latest + + + +# Dataset 1 (random reaching target) + +# Dataset 1 (random reaching target) +path2policy="logs/simple/OmnirobotEnv-v0/srl_combination/ppo2/" +python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 2 --run-policy custom --log-custom-policy $path2policy --short-episodes --save-path data/ --name reaching_on_policy -sc --latest + + +# Dataset 2 (Circular task) +path2policy="logs/circular/OmnirobotEnv-v0/srl_combination/ppo2/" +python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 2 --run-policy custom --log-custom-policy $path2policy --short-episodes --save-path data/ --name circular_on_policy -cc --latest + +# Merge Datasets + +#(/ ! \ it removes the generated dataset for dataset 1 and 2) + +python -m environments.dataset_fusioner --merge data/circular_on_policy/ data/reaching_on_policy/ data/merge_CC_SC + +# Copy the merged Dataset to srl_zoo repository +cp -r data/merge_CC_SC srl_zoo/data/merge_CC_SC + + +### 2.3) Train SRL 1&2 + +cd srl_zoo +# Dataset 1 +python train.py --data-folder data/merge_CC_SC -bs 32 --epochs 2 --state-dim 200 --training-set-size 30000 --losses autoencoder inverse + + +### 2.3) Run Distillation + +# make a new log folder +mkdir logs/CL_SC_CC +cp config/srl_models_merged.yaml config/srl_models.yaml + +# Merged Dataset +cd .. +python -m rl_baselines.train --algo distillation --srl-model srl_combination --env OmnirobotEnv-v0 --log-dir logs/CL_SC_CC --teacher-data-folder srl_zoo/data/merge_CC_SC -cc --distillation-training-set-size 40000 --epochs-distillation 2 --latest + From 95e02be604e5104fe56315f2ddd088f987922452 Mon Sep 17 00:00:00 2001 From: TLESORT Date: Fri, 26 Apr 2019 18:42:41 +0200 Subject: [PATCH 079/141] name's folder have been parametrize to easely change path --- run_policy.sh | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/run_policy.sh b/run_policy.sh index 657fe4caf..b46e600c5 100644 --- a/run_policy.sh +++ b/run_policy.sh @@ -7,6 +7,13 @@ policy="ppo2" env="OmnirobotEnv-v0" +# those name can not be reuse for a unique run, in other case some folder need to be manually removed +name_circular_policy_folder="circular_on_policy" +name_reaching_policy_folder="reaching_on_policy" +merging_file="merge_CC_SC" + + + ### 0 - Generate datasets for SRL (random policy) # Dataset 1 (random reaching target) python -m environments.dataset_generator --num-cpu 8 --name Omnibot_random_simple --env $env --simple-continual --num-episode 250 -f @@ -39,28 +46,28 @@ python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --num-times # Dataset 1 (random reaching target) path2policy="logs/simple/OmnirobotEnv-v0/srl_combination/ppo2/" -python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 100 --run-policy custom --log-custom-policy $path2policy --short-episodes --save-path data/ --name reaching_on_policy -sc --latest +python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 100 --run-policy custom --log-custom-policy $path2policy --short-episodes --save-path data/ --name $name_reaching_policy_folder -sc --latest # Dataset 2 (Circular task) path2policy="logs/circular/OmnirobotEnv-v0/srl_combination/ppo2/" -python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 100 --run-policy custom --log-custom-policy $path2policy --short-episodes --save-path data/ --name circular_on_policy -cc --latest +python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 100 --run-policy custom --log-custom-policy $path2policy --short-episodes --save-path data/ --name $name_circular_policy_folder -cc --latest # Merge Datasets #(/ ! \ it removes the generated dataset for dataset 1 and 2) -python -m environments.dataset_fusioner --merge data/circular_on_policy/ data/reaching_on_policy/ data/merge_CC_SC +python -m environments.dataset_fusioner --merge data/$name_circular_policy_folder\/ data/$name_reaching_policy_folder\/ data/$merging_file # Copy the merged Dataset to srl_zoo repository -cp -r data/merge_CC_SC srl_zoo/data/merge_CC_SC +cp -r data/$merging_file srl_zoo/data/$merging_file ### 2.3) Train SRL 1&2 cd srl_zoo # Dataset 1 -python train.py --data-folder data/merge_CC_SC -bs 32 --epochs 20 --state-dim 200 --training-set-size 30000 --losses autoencoder inverse +python train.py --data-folder data/$merging_file -bs 32 --epochs 20 --state-dim 200 --training-set-size 30000 --losses autoencoder inverse ### 2.3) Run Distillation @@ -71,5 +78,5 @@ cp config/srl_models_merged.yaml config/srl_models.yaml # Merged Dataset cd .. -python -m rl_baselines.train --algo distillation --srl-model srl_combination --env OmnirobotEnv-v0 --log-dir logs/CL_SC_CC --teacher-data-folder srl_zoo/data/merge_CC_SC -cc --distillation-training-set-size 40000 --epochs-distillation 20 --latest +python -m rl_baselines.train --algo distillation --srl-model srl_combination --env OmnirobotEnv-v0 --log-dir logs/CL_SC_CC --teacher-data-folder srl_zoo/data/$merging_file -cc --distillation-training-set-size 40000 --epochs-distillation 20 --latest From 77b1cb01b4fc575f45073a6548c99b51f8088bb8 Mon Sep 17 00:00:00 2001 From: sun-te Date: Fri, 26 Apr 2019 18:44:39 +0200 Subject: [PATCH 080/141] evaluation for student policy(TODO) --- rl_baselines/student_eval.py | 120 +++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 rl_baselines/student_eval.py diff --git a/rl_baselines/student_eval.py b/rl_baselines/student_eval.py new file mode 100644 index 000000000..c02b9e46c --- /dev/null +++ b/rl_baselines/student_eval.py @@ -0,0 +1,120 @@ +""" +Modified version of https://github.com/ikostrikov/pytorch-a2c-ppo-acktr/blob/master/visualize.py +Script used to send plot data to visdom +""" +import glob +import os +import json +import numpy as np +import tensorflow as tf +import pickle +from srl_zoo.utils import printRed +from rl_baselines.utils import WrapFrameStack,computeMeanReward +from stable_baselines.common import set_global_seeds +from rl_baselines import AlgoType +from rl_baselines.registry import registered_rl +from rl_baselines.cross_eval_utils import loadConfigAndSetup, latestPolicy +from datetime import datetime +import subprocess + +def newFile(episode,filename): + #Verify if the new saved policy is already learned by the student + return + +def srl_train(teacher_path): + tmp_dir=os.getcwd() + os.chdir('srl_zoo') + # python - m + # environments.dataset_generator - -num - cpu + # 6 - -name + # Omnibot_random_simple - -env + # OmnirobotEnv - v0 - -simple - continual - -num - episode + # 250 - f + printRed(os.getcwd()) + subprocess.call(['python ']) + os.chdir(tmp_dir) + printRed(os.getcwd()) + return + + + +def DatasetGenerator(teacher_path,output_name,task_id, + env_name='OmnirobotEnv-v0', num_cpu=1,num_eps=600): + command_line = ['python','-m', 'environments.dataset_generator','--run-policy', 'custom'] + cpu_command = ['--num-cpu',str(num_cpu)] + name_command = ['--name',output_name] + env_command = ['--env',env_name] + task_command = [task_id] + episode_command= ['--num-episode', str(num_eps)] + policy_command = ['--log-custom-policy',teacher_path] + + ok=subprocess.call(command_line + cpu_command +policy_command + +name_command+env_command + +task_command +episode_command) + + + +def allPolicy(log_dir): + train_args, algo_name, algo_class, srl_model_path, env_kwargs = loadConfigAndSetup(log_dir) + files= glob.glob(os.path.join(log_dir+algo_name+'_*_model.pkl')) + files_list = [] + for file in files: + eps=int((file.split('_')[-2])) + files_list.append((eps,file)) + + def sortFirst(val): + return val[0] + + files_list.sort(key=sortFirst) + res = np.array(files_list) + return res[:,0], res[:,1] + + + + +def newPolicy(episodes, file_path): + train_args, algo_name, algo_class, srl_model_path, env_kwargs=loadConfigAndSetup(file_path) + episode, model_path,OK=latestPolicy(file_path,algo_name) + if(episode in episodes): + return -1,'', False + else: + return episode, model_path,True + + +def trainStudent(teacher_data_path,task_id, + yaml_file='config/srl_models.yaml', + log_dir='logs/', + srl_model='srl_combination', + env_name='OmnirobotEnv-v0', + training_size=40000, epochs=20): + command_line = ['python','-m', 'rl_baselines.train','--latest','--algo', 'distillation','--log-dir',log_dir] + srl_command = ['--srl-model',srl_model] + env_command = ['--env',env_name] + policy_command = ['--teacher-data-folder', teacher_data_path] + size_epochs =['--distillation-training-set-size',str(training_size),'--epochs-distillation',str(epochs)] + task_command = [task_id] + ok = subprocess.call(command_line + srl_command + +env_command +policy_command +size_epochs+task_command +['--srl-config-file',yaml_file]) + +#python -m environments.dataset_fusioner +# --merge srl_zoo/data/circular_on_policy/ srl_zoo/data/reaching_on_policy/ srl_zoo/data/merge_CC_SC +def mergeData(teacher_dataset_1,teacher_dataset_2,merge_dataset): + merge_command=['--merge',teacher_dataset_1,teacher_dataset_2,merge_dataset] + subprocess.call(['python', '-m', 'environments.dataset_fusioner']+merge_command) + + +if __name__ == '__main__': + teacher_path='logs/circular/OmnirobotEnv-v0/srl_combination/ppo2/19-04-26_12h02_30/' + teacher_path = 'logs/ground_truth/ppo2/19-04-23_17h35_17/' + teacher_data_path='srl_zoo/data/circular_teacher/' + task_id='-cc' + output_name='circular_on_policy1' + num_cpu=8 + yaml_file='config/srl_models_circular.yaml' + merge_path='srl_zoo/data/merge' + + t1,t2='srl_zoo/data/Omnibot_circular','srl_zoo/data/Omnibot_random_simple' + #mergeData(t1,t2,merge_path) + #print(newPolicy([1,2,3],teacher_path)) + #trainStudent(teacher_data_path,task_id) + print(allPolicy(teacher_path)[1]) From f586d0ce956cdadeacb377e2c34c8b263d5faf1e Mon Sep 17 00:00:00 2001 From: Caselles Date: Fri, 26 Apr 2019 19:04:49 +0200 Subject: [PATCH 081/141] Added scripts for raw pixels --- run_policy_raw_pixels.sh | 0 run_raw_pixels_dry_run.sh | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 run_policy_raw_pixels.sh create mode 100644 run_raw_pixels_dry_run.sh diff --git a/run_policy_raw_pixels.sh b/run_policy_raw_pixels.sh new file mode 100644 index 000000000..e69de29bb diff --git a/run_raw_pixels_dry_run.sh b/run_raw_pixels_dry_run.sh new file mode 100644 index 000000000..e69de29bb From 6fdba9e88858c4c3c9a196990d13f17b5207c76a Mon Sep 17 00:00:00 2001 From: kalifou Date: Sat, 27 Apr 2019 14:10:30 +0200 Subject: [PATCH 082/141] grid walking policy (draft) --- environments/dataset_generator.py | 46 +++++++++++++++++---- environments/omnirobot_gym/omnirobot_env.py | 37 ++++++++++++----- environments/srl_env.py | 4 +- 3 files changed, 67 insertions(+), 20 deletions(-) diff --git a/environments/dataset_generator.py b/environments/dataset_generator.py index 924d0a415..e00d17db5 100644 --- a/environments/dataset_generator.py +++ b/environments/dataset_generator.py @@ -18,6 +18,7 @@ from environments import ThreadingType from environments.registry import registered_env +from real_robots.constants import * from replay.enjoy_baselines import createEnv, loadConfigAndSetup from rl_baselines.utils import MultiprocessSRLModel from srl_zoo.utils import printRed, printYellow @@ -28,6 +29,7 @@ RENDER_WIDTH = 224 VALID_MODELS = ["forward", "inverse", "reward", "priors", "episode-prior", "reward-prior", "triplet", "autoencoder", "vae", "dae", "random"] +VALID_POLICIES = ['walker', 'random', 'ppo2', 'custom'] os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' # used to remove debug info of tensorflow @@ -38,6 +40,19 @@ def latestPath(path): """ return max([path + d for d in os.listdir(path) if os.path.isdir(path + "/" + d)],key=os.path.getmtime) + '/' +def walkerPath(): + """ + + :return: + """ + eps = 0.01 + left = [2 for _ in range(100)] #np.linspace(MIN_X + eps, MAX_X - eps, 100, endpoint=True) + right = [3 for _ in range(100)] #np.linspace(MIN_Y + eps, MAX_Y - eps, 100, endpoint=True) + path = left + right #+ left + right + + return path + + def convertImagePath(args, path, record_id_start): """ Used to convert an image path, from one location, to another @@ -100,11 +115,12 @@ def env_thread(args, thread_num, partition=True): srl_state_dim = 0 generated_obs = None - if args.run_policy == "custom": + if args.run_policy in ["walker", "custom"]: if args.latest: args.log_dir = latestPath(args.log_custom_policy) else: args.log_dir = args.log_custom_policy + args.log_dir = args.log_custom_policy args.render = args.display args.plotting, args.action_proba = False, False @@ -121,7 +137,11 @@ def env_thread(args, thread_num, partition=True): env_class = registered_env[args.env][0] env = env_class(**env_kwargs) - if args.run_policy in ['custom', 'ppo2']: + walker_path = None + action_walker = None + state_init_for_walker = None + + if args.run_policy in ['custom', 'ppo2', 'walker']: # Additional env when using a trained agent to generate data train_env = vecEnv(env_kwargs, env_class) @@ -134,6 +154,8 @@ def env_thread(args, thread_num, partition=True): set_global_seeds(args.seed) printYellow("Compiling Policy function....") model = algo_class.load(load_path, args=algo_args) + if args.run_policy == 'walker': + walker_path = walkerPath() if len(args.replay_generative_model) > 0: srl_model = loadSRLModel(args.log_generative_model, th.cuda.is_available()) @@ -148,7 +170,7 @@ def env_thread(args, thread_num, partition=True): seed = args.seed + i_episode + args.num_episode // args.num_cpu * thread_num + \ (thread_num if thread_num <= args.num_episode % args.num_cpu else args.num_episode % args.num_cpu) - if not args.run_policy == 'custom': + if not args.run_policy in ['custom', 'walker']: env.seed(seed) env.action_space.seed(seed) # this is for the sample() function from gym.space @@ -162,7 +184,7 @@ def env_thread(args, thread_num, partition=True): generated_obs = generated_obs[0].detach().cpu().numpy().transpose(1, 2, 0) generated_obs = deNormalize(generated_obs) - obs = env.reset(generated_observation=generated_obs) + obs = env.reset(generated_observation=generated_obs, state_override=state_init_for_walker) done = False action_proba = None t = 0 @@ -171,13 +193,20 @@ def env_thread(args, thread_num, partition=True): while not done: env.render() + + # Policy to run on the fly - to be trained before generation if args.run_policy == 'ppo2': action, _ = model.predict([obs]) - elif args.run_policy == 'custom': + # Custom pre-trained Policy (SRL or End-to-End) + elif args.run_policy in['custom', 'walker']: action = [model.getAction(obs, done)] action_proba = model.getActionProba(obs, done) + if args.run_policy == 'walker': + print("POLICY: walker policy to be used") + action_walker = [walker_path[t]] + # Random Policy else: if episode_toward_target_on and np.random.rand() < args.toward_target_timesteps_proportion: action = [env.actionPolicyTowardTarget()] @@ -197,7 +226,8 @@ def env_thread(args, thread_num, partition=True): action_to_step = action[0] - obs, _, done, _ = env.step(action_to_step, generated_observation=generated_obs, action_proba=action_proba) + obs, _, done, _ = env.step(action_to_step, generated_observation=generated_obs, action_proba=action_proba, + action_grid_walker=action_walker) frames += 1 t += 1 @@ -240,7 +270,7 @@ def main(): parser.add_argument('--reward-dist', action='store_true', default=False, help='Prints out the reward distribution when the dataset generation is finished') parser.add_argument('--run-policy', type=str, default="random", - choices=['random', 'ppo2', 'custom'], + choices=VALID_POLICIES, help='Policy to run for data collection ' + '(random, localy pretrained ppo2, pretrained custom policy)') parser.add_argument('--log-custom-policy', type=str, default='', @@ -284,7 +314,7 @@ def main(): assert sum([args.simple_continual, args.circular_continual, args.square_continual]) <= 1, \ "For continual SRL and RL, please provide only one scenario at the time !" - assert not (args.log_custom_policy == '' and args.run_policy == 'custom'), \ + assert not (args.log_custom_policy == '' and args.run_policy in ['walker', 'custom']), \ "If using a custom policy, please specify a valid log folder for loading it." assert not (args.log_generative_model == '' and args.replay_generative_model == 'custom'), \ diff --git a/environments/omnirobot_gym/omnirobot_env.py b/environments/omnirobot_gym/omnirobot_env.py index 27ca35e4b..e4380021b 100644 --- a/environments/omnirobot_gym/omnirobot_env.py +++ b/environments/omnirobot_gym/omnirobot_env.py @@ -183,23 +183,36 @@ def actionPolicyTowardTarget(self): else: return DELTA_POS if self.robot_pos[1] < self.target_pos[1] else -DELTA_POS - def step(self, action, generated_observation=None, action_proba=None): + def step(self, action, generated_observation=None, action_proba=None, action_grid_walker=None): """ - :action: (int) + + :param :action: (int) + :param generated_observation: + :param action_proba: + :param action_grid_walker: # Whether or not we want to override the action with the one from a grid walker :return: (tensor (np.ndarray)) observation, int reward, bool done, dict extras) """ + if action_grid_walker is None: + action_to_step = action + action_from_teacher = None + else: + print('walker policy on!') + action_to_step = action_grid_walker + action_from_teacher = action + assert self.action_space.contains(action_from_teacher) + if not self._is_discrete: - action = np.array(action) - assert self.action_space.contains(action) + action_to_step = np.array(action_to_step) + assert self.action_space.contains(action_to_step) # Convert int action to action in (x,y,z) space # serialize the action - if isinstance(action, np.ndarray): - self.action = action.tolist() - elif hasattr(action, 'dtype'): # convert numpy type to python type + if isinstance(action_to_step, np.ndarray): + self.action = action_to_step.tolist() + elif hasattr(action_to_step, 'dtype'): # convert numpy type to python type self.action = action.item() else: - self.action = action + self.action = action_to_step self._env_step_counter += 1 @@ -218,7 +231,7 @@ def step(self, action, generated_observation=None, action_proba=None): self.render() if self.saver is not None: - self.saver.step(self.observation, action, + self.saver.step(self.observation, action_from_teacher if action_grid_walker is not None else action_to_step, self.reward, done, self.getGroundTruth(), action_proba=action_proba) if self.use_srl: return self.getSRLState(self.observation), self.reward, done, {} @@ -276,9 +289,11 @@ def getRobotPos(self): """ return self.robot_pos - def reset(self, generated_observation=None): + def reset(self, generated_observation=None, state_override=None): """ Reset the environment + :param generated_observation: + :param state_override: :return: (numpy ndarray) first observation of the env """ self.episode_terminated = False @@ -290,6 +305,8 @@ def reset(self, generated_observation=None): # Update state related variables, important step to get both data and # metadata that allow reading the observation image self.getEnvState() + self.robot_pos = np.array([0, 0]) if state_override is None else state_override + self.observation = self.getObservation() if generated_observation is None else generated_observation * 255 if self.saver is not None: self.saver.reset(self.observation, diff --git a/environments/srl_env.py b/environments/srl_env.py index c7e8d6951..c38ccd17c 100644 --- a/environments/srl_env.py +++ b/environments/srl_env.py @@ -81,13 +81,13 @@ def close(self): # TODO: implement close function to close GUI pass - def step(self, action, generated_observation=None, action_proba=None): + def step(self, action, generated_observation=None, action_proba=None, action_grid_walker=None): """ :param action: (int or [float]) """ raise NotImplementedError() - def reset(self): + def reset(self, state_override=None): """ Reset the environment :return: (numpy tensor) first observation of the env From adf48fbfcc58c62bdc95ddc8cfd998b2b2b15535 Mon Sep 17 00:00:00 2001 From: kalifou Date: Sat, 27 Apr 2019 15:55:49 +0200 Subject: [PATCH 083/141] grid walker for exploration in on-policy data generation --- environments/dataset_generator.py | 21 +++++++++++++------ environments/omnirobot_gym/omnirobot_env.py | 9 ++++---- real_robots/omnirobot_simulator_server.py | 4 +++- .../omnirobot_utils/omnirobot_manager_base.py | 3 ++- 4 files changed, 24 insertions(+), 13 deletions(-) diff --git a/environments/dataset_generator.py b/environments/dataset_generator.py index e00d17db5..91c6b7faf 100644 --- a/environments/dataset_generator.py +++ b/environments/dataset_generator.py @@ -33,6 +33,7 @@ os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' # used to remove debug info of tensorflow + def latestPath(path): """ :param path: path to the log folder (defined in srl_model.yaml) (str) @@ -40,15 +41,21 @@ def latestPath(path): """ return max([path + d for d in os.listdir(path) if os.path.isdir(path + "/" + d)],key=os.path.getmtime) + '/' + def walkerPath(): """ :return: """ eps = 0.01 - left = [2 for _ in range(100)] #np.linspace(MIN_X + eps, MAX_X - eps, 100, endpoint=True) - right = [3 for _ in range(100)] #np.linspace(MIN_Y + eps, MAX_Y - eps, 100, endpoint=True) - path = left + right #+ left + right + N_times = 14 + path = [] + left = [0 for _ in range(N_times)] + right = [1 for _ in range(N_times)] + + for idx in range(N_times * 2): + path += left if idx % 2 == 0 else right + path += [3] if idx < N_times else [2] return path @@ -128,6 +135,9 @@ def env_thread(args, thread_num, partition=True): env_kwargs["srl_model"] = env_kwargs_extra["srl_model"] env_kwargs["random_target"] = env_kwargs_extra.get("random_target", False) env_kwargs["use_srl"] = env_kwargs_extra.get("use_srl", False) + eps = 0.2 + env_kwargs["state_init_override"] = np.array([MIN_X + eps, MAX_X - eps]) \ + if args.run_policy == 'walker' else None if env_kwargs["use_srl"]: env_kwargs["srl_model_path"] = env_kwargs_extra.get("srl_model_path", None) env_kwargs["state_dim"] = getSRLDim(env_kwargs_extra.get("srl_model_path", None)) @@ -184,7 +194,7 @@ def env_thread(args, thread_num, partition=True): generated_obs = generated_obs[0].detach().cpu().numpy().transpose(1, 2, 0) generated_obs = deNormalize(generated_obs) - obs = env.reset(generated_observation=generated_obs, state_override=state_init_for_walker) + obs = env.reset(generated_observation=generated_obs) done = False action_proba = None t = 0 @@ -203,8 +213,7 @@ def env_thread(args, thread_num, partition=True): action = [model.getAction(obs, done)] action_proba = model.getActionProba(obs, done) if args.run_policy == 'walker': - print("POLICY: walker policy to be used") - action_walker = [walker_path[t]] + action_walker = np.array(walker_path[t]) # Random Policy else: diff --git a/environments/omnirobot_gym/omnirobot_env.py b/environments/omnirobot_gym/omnirobot_env.py index e4380021b..48a7fd246 100644 --- a/environments/omnirobot_gym/omnirobot_env.py +++ b/environments/omnirobot_gym/omnirobot_env.py @@ -73,8 +73,8 @@ class OmniRobotEnv(SRLGymEnv): def __init__(self, renders=False, name="Omnirobot", is_discrete=True, save_path='srl_zoo/data/', state_dim=-1, learn_states=False, srl_model="raw_pixels", record_data=False, action_repeat=1, random_target=True, shape_reward=False, simple_continual_target=False, circular_continual_move=False, - square_continual_move=False, eight_continual_move=False, short_episodes=False, env_rank=0, - srl_pipe=None, **_): + square_continual_move=False, eight_continual_move=False, short_episodes=False, + state_init_override=None, env_rank=0, srl_pipe=None, **_): super(OmniRobotEnv, self).__init__(srl_model=srl_model, relative_pos=RELATIVE_POS, @@ -140,7 +140,8 @@ def __init__(self, renders=False, name="Omnirobot", is_discrete=True, save_path= square_continual_move=square_continual_move, eight_continual_move=eight_continual_move, output_size=[RENDER_WIDTH, RENDER_HEIGHT], - random_target=self._random_target) + random_target=self._random_target, + state_init_override=state_init_override) else: # Initialize Baxter effector by connecting to the Gym bridge ROS node: self.context = zmq.Context() @@ -196,7 +197,6 @@ def step(self, action, generated_observation=None, action_proba=None, action_gri action_to_step = action action_from_teacher = None else: - print('walker policy on!') action_to_step = action_grid_walker action_from_teacher = action assert self.action_space.contains(action_from_teacher) @@ -306,7 +306,6 @@ def reset(self, generated_observation=None, state_override=None): # metadata that allow reading the observation image self.getEnvState() self.robot_pos = np.array([0, 0]) if state_override is None else state_override - self.observation = self.getObservation() if generated_observation is None else generated_observation * 255 if self.saver is not None: self.saver.reset(self.observation, diff --git a/real_robots/omnirobot_simulator_server.py b/real_robots/omnirobot_simulator_server.py index 05266f93e..afd1439d3 100755 --- a/real_robots/omnirobot_simulator_server.py +++ b/real_robots/omnirobot_simulator_server.py @@ -422,6 +422,7 @@ def __init__(self, **args): self._random_target = self.new_args["random_target"] if self.new_args["simple_continual_target"]: self._random_target = True + self.state_init_override = self.new_args['state_init_override'] self.resetEpisode() # for a random target initial position def resetEpisode(self): @@ -433,7 +434,8 @@ def resetEpisode(self): if self.second_cam_topic is not None: assert NotImplementedError # Env reset - random_init_position = self.sampleRobotInitalPosition() + random_init_position = self.sampleRobotInitalPosition() if self.state_init_override is None \ + else self.state_init_override self.robot.setRobotCmd( random_init_position[0], random_init_position[1], 0) diff --git a/real_robots/omnirobot_utils/omnirobot_manager_base.py b/real_robots/omnirobot_utils/omnirobot_manager_base.py index ddc5d2ead..8eeb10794 100644 --- a/real_robots/omnirobot_utils/omnirobot_manager_base.py +++ b/real_robots/omnirobot_utils/omnirobot_manager_base.py @@ -5,7 +5,7 @@ class OmnirobotManagerBase(object): def __init__(self, simple_continual_target=False, circular_continual_move=False, square_continual_move=False, - eight_continual_move=False, lambda_c=10.0, second_cam_topic=None): + eight_continual_move=False, lambda_c=10.0, second_cam_topic=None, state_init_override=None): """ This class is the basic class for omnirobot server, and omnirobot simulator's server. This class takes omnirobot position at instant t, and takes the action at instant t, @@ -19,6 +19,7 @@ def __init__(self, simple_continual_target=False, circular_continual_move=False, self.square_continual_move = square_continual_move self.eight_continual_move = eight_continual_move self.lambda_c = lambda_c + self.state_init_override = state_init_override # the abstract object for robot, # can be the real robot (Omnirobot class) From f53dbc518ba923de5b522475339cd5e3cfe94fbd Mon Sep 17 00:00:00 2001 From: kalifou Date: Mon, 29 Apr 2019 14:25:32 +0200 Subject: [PATCH 084/141] Option for finetuning of SRL while distilling --- .../supervised_rl/policy_distillation.py | 25 +++++++++++++++---- rl_baselines/train.py | 4 +-- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/rl_baselines/supervised_rl/policy_distillation.py b/rl_baselines/supervised_rl/policy_distillation.py index 563e9215e..c0f5033ec 100644 --- a/rl_baselines/supervised_rl/policy_distillation.py +++ b/rl_baselines/supervised_rl/policy_distillation.py @@ -19,6 +19,7 @@ MAX_BATCH_SIZE_GPU = 256 # For plotting, max batch_size before having memory issues RENDER_HEIGHT = 224 RENDER_WIDTH = 224 +FINE_TUNING = False CONTINUAL_LEARNING_LABELS = ['CC', 'SC', 'EC', 'SQC'] CL_LABEL_KEY = "continual_learning_label" @@ -129,8 +130,7 @@ def loss_fn_kd(self, outputs, teacher_outputs, labels=None, adaptive_temperature T = th.from_numpy(np.array([TEMPERATURES[labels[idx_elm]] for idx_elm in range(BATCH_SIZE)])).cuda().float() KD_loss = F.softmax(th.div(teacher_outputs.transpose(1, 0), T), dim=1) * \ - th.log((F.softmax(th.div(teacher_outputs.transpose(1, 0), T), dim=1) / F.softmax( - th.div(outputs.transpose(1, 0), T), dim=1))) + th.log((F.softmax(th.div(teacher_outputs.transpose(1, 0), T), dim=1) / F.softmax(outputs, dim=1))) else: T = TEMPERATURES["default"] KD_loss = F.softmax(teacher_outputs/T, dim=1) * \ @@ -226,10 +226,17 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): self.srl_model = loadSRLModel(env_kwargs.get("srl_model_path", None), th.cuda.is_available(), self.state_dim, env_object=None) + self.model = MLPPolicy(output_size=n_actions, input_size=self.state_dim) for param in self.model.parameters(): param.requires_grad = True learnable_params = [param for param in self.model.parameters()] + + if FINE_TUNING and self.srl_model is not None: + for param in self.srl_model.model.parameters(): + param.requires_grad = True + learnable_params += [param for param in self.srl_model.model.parameters()] + learning_rate = 1e-3 self.device = th.device("cuda" if th.cuda.is_available() else "cpu") @@ -253,8 +260,12 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): validation_mode = minibatch_idx in val_indices if validation_mode: self.model.eval() + if FINE_TUNING and self.srl_model is not None: + self.srl_model.model.eval() else: self.model.train() + if FINE_TUNING and self.srl_model is not None: + self.srl_model.model.train() # Actions associated to the observations of the current minibatch actions_st = actions[minibatchlist[minibatch_idx]] @@ -273,14 +284,18 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): actions_st = th.from_numpy(actions_st).view(-1, self.dim_action).requires_grad_(False).to( self.device) - state = obs.detach() if self.srl_model is None \ - else self.srl_model.model.getStates(obs).to(self.device).detach() + if self.srl_model is not None: + state = self.srl_model.model.getStates(obs).to(self.device).detach() + if "autoencoder" in self.srl_model.model.losses: + use_ae = True + decoded_obs = self.srl_model.model.model.decode(state).to(self.device).detach() + else: + state = obs.detach() pred_action = self.model.forward(state) loss = self.loss_fn_kd(pred_action, actions_proba_st.float(), labels=cl_labels_st, adaptive_temperature=USE_ADAPTIVE_TEMPERATURE) - loss.backward() if validation_mode: val_loss += loss.item() diff --git a/rl_baselines/train.py b/rl_baselines/train.py index 61246c501..575401444 100644 --- a/rl_baselines/train.py +++ b/rl_baselines/train.py @@ -260,8 +260,8 @@ def main(): break assert found, "Error: srl_model {}, is not compatible with the {} environment.".format(args.srl_model, args.env) - assert sum([args.simple_continual, args.circular_continual, args.square_continual, args.eight_continual]) \ - <= 1 and args.env == "OmnirobotEnv-v0", \ + assert not(sum([args.simple_continual, args.circular_continual, args.square_continual, args.eight_continual]) \ + > 1 and args.env == "OmnirobotEnv-v0"), \ "For continual SRL and RL, please provide only one scenario at the time and use OmnirobotEnv-v0 environment !" assert not(args.algo == "distillation" and (args.teacher_data_folder == '' or args.continuous_actions is True)), \ From 4cdb4f4ae35dc17614637cbfd3865b34e5c5ef52 Mon Sep 17 00:00:00 2001 From: sun-te Date: Mon, 29 Apr 2019 14:50:27 +0200 Subject: [PATCH 085/141] cross_eval and student eval --- environments/dataset_fusioner.py | 9 +- environments/dataset_generator_student.py | 465 ++++++++++++++++++++++ rl_baselines/base_classes.py | 40 +- rl_baselines/cross_eval.py | 13 +- rl_baselines/cross_eval_utils.py | 45 +-- rl_baselines/student_eval.py | 63 ++- rl_baselines/train.py | 24 +- 7 files changed, 602 insertions(+), 57 deletions(-) create mode 100644 environments/dataset_generator_student.py diff --git a/environments/dataset_fusioner.py b/environments/dataset_fusioner.py index 9d3d97b21..741cec7ee 100644 --- a/environments/dataset_fusioner.py +++ b/environments/dataset_fusioner.py @@ -28,8 +28,13 @@ def main(): if 'merge' in args: # let make sure everything is in order assert os.path.exists(args.merge[0]), "Error: dataset '{}' could not be found".format(args.merge[0]) - assert (not os.path.exists(args.merge[2])), "Error: dataset '{}' already exists, cannot rename '{}' to '{}'"\ - .format(args.merge[2], args.merge[0], args.merge[2]) + # assert (not os.path.exists(args.merge[2])), "Error: dataset '{}' already exists, cannot rename '{}' to '{}'"\ + # .format(args.merge[2], args.merge[0], args.merge[2]) + ############################################# + #If the merge file exists already, delete it for the convenince of updating student's policy + if (os.path.exists(args.merge[2])): + shutil.rmtree(args.merge[2]) + ############################################# if 'continual_learning_labels' in args: assert args.continual_learning_labels[0] in CONTINUAL_LEARNING_LABELS \ and args.continual_learning_labels[1] in CONTINUAL_LEARNING_LABELS, \ diff --git a/environments/dataset_generator_student.py b/environments/dataset_generator_student.py new file mode 100644 index 000000000..9ab9297af --- /dev/null +++ b/environments/dataset_generator_student.py @@ -0,0 +1,465 @@ +from __future__ import division, absolute_import, print_function + +import argparse +import glob +import multiprocessing +import os +import shutil +import tensorflow as tf +import time +import torch as th +from torch.autograd import Variable + +import numpy as np +from stable_baselines import PPO2 +from stable_baselines.common import set_global_seeds +from stable_baselines.common.vec_env import DummyVecEnv, VecNormalize +from stable_baselines.common.policies import CnnPolicy + +from environments import ThreadingType +from environments.registry import registered_env +from replay.enjoy_baselines import createEnv, loadConfigAndSetup +from rl_baselines.utils import MultiprocessSRLModel +from srl_zoo.utils import printRed, printYellow +from srl_zoo.preprocessing.utils import deNormalize +from state_representation.models import loadSRLModel, getSRLDim +from rl_baselines.registry import registered_rl +import json +from rl_baselines import AlgoType + +RENDER_HEIGHT = 224 +RENDER_WIDTH = 224 +VALID_MODELS = ["forward", "inverse", "reward", "priors", "episode-prior", "reward-prior", "triplet", + "autoencoder", "vae", "dae", "random"] + +os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' # used to remove debug info of tensorflow + + + +def loadConfigAndSetup(load_args): + """ + Get the training config and setup the parameters + :param load_args: (Arguments) + :return: (dict, str, str, str, dict) + """ + algo_name = "" + for algo in list(registered_rl.keys()): + if algo in load_args.log_dir: + algo_name = algo + break + algo_class, algo_type, _ = registered_rl[algo_name] + if algo_type == AlgoType.OTHER: + raise ValueError(algo_name + " is not supported for replay") + if(not load_args.episode ==-1): + load_path = "{}/{}_{}_model.pkl".format(load_args.log_dir, algo_name,load_args.episode,) + else: + load_path = "{}/{}_model.pkl".format(load_args.log_dir, algo_name) + + env_globals = json.load(open(load_args.log_dir + "env_globals.json", 'r')) + train_args = json.load(open(load_args.log_dir + "args.json", 'r')) + + env_kwargs = { + "renders": load_args.render, + "shape_reward": load_args.shape_reward, # Reward sparse or shaped + "action_joints": train_args["action_joints"], + "is_discrete": not train_args["continuous_actions"], + "random_target": train_args.get('random_target', False), + "srl_model": train_args["srl_model"] + } + + # load it, if it was defined + if "action_repeat" in env_globals: + env_kwargs["action_repeat"] = env_globals['action_repeat'] + + # Remove up action + if train_args["env"] == "Kuka2ButtonGymEnv-v0": + env_kwargs["force_down"] = env_globals.get('force_down', True) + else: + env_kwargs["force_down"] = env_globals.get('force_down', False) + + if train_args["env"] == "OmnirobotEnv-v0": + env_kwargs["simple_continual_target"] = env_globals.get("simple_continual_target", False) + env_kwargs["circular_continual_move"] = env_globals.get("circular_continual_move", False) + env_kwargs["square_continual_move"] = env_globals.get("square_continual_move", False) + env_kwargs["eight_continual_move"] = env_globals.get("eight_continual_move", False) + + if sum([load_args.simple_continual, load_args.circular_continual, load_args.square_continual]) >= 1: + env_kwargs["simple_continual_target"] = load_args.simple_continual + env_kwargs["circular_continual_move"] = load_args.circular_continual + env_kwargs["square_continual_move"] = load_args.square_continual + env_kwargs["random_target"] = not (load_args.circular_continual or load_args.square_continual) + + srl_model_path = None + if train_args["srl_model"] != "raw_pixels": + train_args["policy"] = "mlp" + path = env_globals.get('srl_model_path') + + if path is not None: + env_kwargs["use_srl"] = True + # Check that the srl saved model exists on the disk + assert os.path.isfile(env_globals['srl_model_path']), "{} does not exist".format(env_globals['srl_model_path']) + srl_model_path = env_globals['srl_model_path'] + env_kwargs["srl_model_path"] = srl_model_path + + return train_args, load_path, algo_name, algo_class, srl_model_path, env_kwargs + + + +def convertImagePath(args, path, record_id_start): + """ + Used to convert an image path, from one location, to another + :param args: (ArgumentParser object) + :param path: (str) + :param record_id_start: (int) where does the current part start counting its records + :return: + """ + image_name = path.split("/")[-1] + # get record id for output, by adding the current offset with the record_id + # of the folder + new_record_id = record_id_start + int(path.split("/")[-2].split("_")[-1]) + return args.name + "/record_{:03d}".format(new_record_id) + "/" + image_name + + +def vecEnv(env_kwargs_local, env_class): + """ + Local Env Wrapper + :param env_kwargs_local: arguments related to the environment wrapper + :param env_class: class of the env + :return: env for the pretrained algo + """ + train_env = env_class(**{**env_kwargs_local, "record_data": False, "renders": False}) + train_env = DummyVecEnv([lambda: train_env]) + train_env = VecNormalize(train_env, norm_obs=True, norm_reward=False) + return train_env + + +def env_thread(args, thread_num, partition=True): + """ + Run a session of an environment + :param args: (ArgumentParser object) + :param thread_num: (int) The thread ID of the environment session + :param partition: (bool) If the output should be in multiple parts (default=True) + """ + env_kwargs = { + "max_distance": args.max_distance, + "random_target": args.random_target, + "force_down": True, + "is_discrete": not args.continuous_actions, + "renders": thread_num == 0 and args.display, + "record_data": not args.no_record_data, + "multi_view": args.multi_view, + "save_path": args.save_path, + "shape_reward": args.shape_reward, + "simple_continual_target": args.simple_continual, + "circular_continual_move": args.circular_continual, + "square_continual_move": args.square_continual, + "short_episodes": args.short_episodes + } + + if partition: + env_kwargs["name"] = args.name + "_part-" + str(thread_num) + else: + env_kwargs["name"] = args.name + + load_path, train_args, algo_name, algo_class = None, None, None, None + model = None + srl_model = None + srl_state_dim = 0 + generated_obs = None + + if args.run_policy == "custom": + args.log_dir = args.log_custom_policy + args.render = args.display + args.plotting, args.action_proba = False, False + + train_args, load_path, algo_name, algo_class, _, env_kwargs_extra = loadConfigAndSetup(args) + env_kwargs["srl_model"] = env_kwargs_extra["srl_model"] + env_kwargs["random_target"] = env_kwargs_extra.get("random_target", False) + env_kwargs["use_srl"] = env_kwargs_extra.get("use_srl", False) + if env_kwargs["use_srl"]: + env_kwargs["srl_model_path"] = env_kwargs_extra.get("srl_model_path", None) + env_kwargs["state_dim"] = getSRLDim(env_kwargs_extra.get("srl_model_path", None)) + srl_model = MultiprocessSRLModel(args.num_cpu, args.env, env_kwargs) + env_kwargs["srl_pipe"] = srl_model.pipe + + env_class = registered_env[args.env][0] + env = env_class(**env_kwargs) + + if args.run_policy in ['custom', 'ppo2']: + + # Additional env when using a trained agent to generate data + train_env = vecEnv(env_kwargs, env_class) + + if args.run_policy == 'ppo2': + model = PPO2(CnnPolicy, train_env).learn(args.ppo2_timesteps) + else: + _, _, algo_args = createEnv(args, train_args, algo_name, algo_class, env_kwargs) + tf.reset_default_graph() + set_global_seeds(args.seed) + printYellow("Compiling Policy function....") + model = algo_class.load(load_path, args=algo_args) + + if len(args.replay_generative_model) > 0: + srl_model = loadSRLModel(args.log_generative_model, th.cuda.is_available()) + srl_state_dim = srl_model.state_dim + srl_model = srl_model.model.model + + frames = 0 + start_time = time.time() + # divide evenly, then do an extra one for only some of them in order to get the right count + for i_episode in range(args.num_episode // args.num_cpu + 1 * (args.num_episode % args.num_cpu > thread_num)): + # seed + position in this slice + size of slice (with reminder if uneven partitions) + seed = args.seed + i_episode + args.num_episode // args.num_cpu * thread_num + \ + (thread_num if thread_num <= args.num_episode % args.num_cpu else args.num_episode % args.num_cpu) + + if not args.run_policy == 'custom': + env.seed(seed) + env.action_space.seed(seed) # this is for the sample() function from gym.space + + if len(args.replay_generative_model) > 0: + + sample = Variable(th.randn(1, srl_state_dim)) + if th.cuda.is_available(): + sample = sample.cuda() + + generated_obs = srl_model.decode(sample) + generated_obs = generated_obs[0].detach().cpu().numpy().transpose(1, 2, 0) + generated_obs = deNormalize(generated_obs) + + obs = env.reset(generated_observation=generated_obs) + done = False + action_proba = None + t = 0 + episode_toward_target_on = False + + while not done: + + env.render() + if args.run_policy == 'ppo2': + action, _ = model.predict([obs]) + + elif args.run_policy == 'custom': + action = [model.getAction(obs, done)] + action_proba = model.getActionProba(obs, done) + + else: + if episode_toward_target_on and np.random.rand() < args.toward_target_timesteps_proportion: + action = [env.actionPolicyTowardTarget()] + else: + action = [env.action_space.sample()] + + if len(args.replay_generative_model) > 0: + + sample = Variable(th.randn(1, srl_state_dim)) + + if th.cuda.is_available(): + sample = sample.cuda() + + generated_obs = srl_model.decode(sample) + generated_obs = generated_obs[0].detach().cpu().numpy().transpose(1, 2, 0) + generated_obs = deNormalize(generated_obs) + + action_to_step = action[0] + + obs, _, done, _ = env.step(action_to_step, generated_observation=generated_obs, action_proba=action_proba) + + frames += 1 + t += 1 + if done: + + if np.random.rand() < args.toward_target_timesteps_proportion: + episode_toward_target_on = True + else: + episode_toward_target_on = False + print("Episode finished after {} timesteps".format(t + 1)) + + if thread_num == 0: + print("{:.2f} FPS".format(frames * args.num_cpu / (time.time() - start_time))) + + +def main(): + parser = argparse.ArgumentParser(description='Deteministic dataset generator for SRL training ' + + '(can be used for environment testing)') + parser.add_argument('--num-cpu', type=int, default=1, help='number of cpu to run on') + parser.add_argument('--num-episode', type=int, default=50, help='number of episode to run') + parser.add_argument('--save-path', type=str, default='srl_zoo/data/', + help='Folder where the environments will save the output') + parser.add_argument('--name', type=str, default='kuka_button', help='Folder name for the output') + parser.add_argument('--env', type=str, default='KukaButtonGymEnv-v0', help='The environment wanted', + choices=list(registered_env.keys())) + parser.add_argument('--display', action='store_true', default=False) + parser.add_argument('--no-record-data', action='store_true', default=False) + parser.add_argument('--max-distance', type=float, default=0.28, + help='Beyond this distance from the goal, the agent gets a negative reward') + parser.add_argument('-c', '--continuous-actions', action='store_true', default=False) + parser.add_argument('--seed', type=int, default=0, help='the seed') + parser.add_argument('-f', '--force', action='store_true', default=False, + help='Force the save, even if it overrides something else,' + + ' including partial parts if they exist') + parser.add_argument('-r', '--random-target', action='store_true', default=False, + help='Set the button to a random position') + parser.add_argument('--multi-view', action='store_true', default=False, help='Set a second camera to the scene') + parser.add_argument('--shape-reward', action='store_true', default=False, + help='Shape the reward (reward = - distance) instead of a sparse reward') + parser.add_argument('--reward-dist', action='store_true', default=False, + help='Prints out the reward distribution when the dataset generation is finished') + parser.add_argument('--run-policy', type=str, default="random", + choices=['random', 'ppo2', 'custom'], + help='Policy to run for data collection ' + + '(random, localy pretrained ppo2, pretrained custom policy)') + parser.add_argument('--log-custom-policy', type=str, default='', + help='Logs of the custom pretained policy to run for data collection') + parser.add_argument('-rgm', '--replay-generative-model', type=str, default="", choices=['vae'], + help='Generative model to replay for generating a dataset (for Continual Learning purposes)') + parser.add_argument('--log-generative-model', type=str, default='', + help='Logs of the custom pretained policy to run for data collection') + parser.add_argument('--ppo2-timesteps', type=int, default=1000, + help='number of timesteps to run PPO2 on before generating the dataset') + parser.add_argument('--toward-target-timesteps-proportion', type=float, default=0.0, + help="propotion of timesteps that use simply towards target policy, should be 0.0 to 1.0") + parser.add_argument('-sc', '--simple-continual', action='store_true', default=False, + help='Simple red square target for task 1 of continual learning scenario. ' + + 'The task is: robot should reach the target.') + parser.add_argument('-cc', '--circular-continual', action='store_true', default=False, + help='Blue square target for task 2 of continual learning scenario. ' + + 'The task is: robot should turn in circle around the target.') + parser.add_argument('-sqc', '--square-continual', action='store_true', default=False, + help='Green square target for task 3 of continual learning scenario. ' + + 'The task is: robot should turn in square around the target.') + parser.add_argument('--short-episodes', action='store_true', default=False, + help='Generate short episodes (only 10 contacts with the target allowed).') + parser.add_argument('--episode', type=int, default=-1, + help='Model saved at episode N that we want to load') + + args = parser.parse_args() + + assert (args.num_cpu > 0), "Error: number of cpu must be positive and non zero" + assert (args.max_distance > 0), "Error: max distance must be positive and non zero" + assert (args.num_episode > 0), "Error: number of episodes must be positive and non zero" + assert not args.reward_dist or not args.shape_reward, \ + "Error: cannot display the reward distribution for continuous reward" + assert not(registered_env[args.env][3] is ThreadingType.NONE and args.num_cpu != 1), \ + "Error: cannot have more than 1 CPU for the environment {}".format(args.env) + if args.num_cpu > args.num_episode: + args.num_cpu = args.num_episode + printYellow("num_cpu cannot be greater than num_episode, defaulting to {} cpus.".format(args.num_cpu)) + + assert sum([args.simple_continual, args.circular_continual, args.square_continual]) <= 1, \ + "For continual SRL and RL, please provide only one scenario at the time !" + + assert not (args.log_custom_policy == '' and args.run_policy == 'custom'), \ + "If using a custom policy, please specify a valid log folder for loading it." + + assert not (args.log_generative_model == '' and args.replay_generative_model == 'custom'), \ + "If using a custom policy, please specify a valid log folder for loading it." + + # this is done so seed 0 and 1 are different and not simply offset of the same datasets. + args.seed = np.random.RandomState(args.seed).randint(int(1e10)) + + # File exists, need to deal with it + if not args.no_record_data and os.path.exists(args.save_path + args.name): + assert args.force, "Error: save directory '{}' already exists".format(args.save_path + args.name) + + shutil.rmtree(args.save_path + args.name) + for part in glob.glob(args.save_path + args.name + "_part-[0-9]*"): + shutil.rmtree(part) + if not args.no_record_data: + # create the output + os.mkdir(args.save_path + args.name) + + if args.num_cpu == 1: + env_thread(args, 0, partition=False) + else: + # try and divide into multiple processes, with an environment each + try: + jobs = [] + for i in range(args.num_cpu): + process = multiprocessing.Process(target=env_thread, args=(args, i, True)) + jobs.append(process) + + for j in jobs: + j.start() + + try: + for j in jobs: + j.join() + except Exception as e: + printRed("Error: unable to join thread") + raise e + + except Exception as e: + printRed("Error: unable to start thread") + raise e + + if not args.no_record_data and args.num_cpu > 1: + # sleep 1 second, to avoid congruency issues from multiprocess (eg., files still writing) + time.sleep(1) + # get all the parts + file_parts = sorted(glob.glob(args.save_path + args.name + "_part-[0-9]*"), key=lambda a: int(a.split("-")[-1])) + + # move the config files from any as they are identical + os.rename(file_parts[0] + "/dataset_config.json", args.save_path + args.name + "/dataset_config.json") + os.rename(file_parts[0] + "/env_globals.json", args.save_path + args.name + "/env_globals.json") + + ground_truth = None + preprocessed_data = None + + # used to convert the part record_id to the fused record_id + record_id = 0 + for part in file_parts: + # sort the record names alphabetically, then numerically + records = sorted(glob.glob(part + "/record_[0-9]*"), key=lambda a: int(a.split("_")[-1])) + + record_id_start = record_id + for record in records: + os.renames(record, args.save_path + args.name + "/record_{:03d}".format(record_id)) + record_id += 1 + + # fuse the npz files together, in the right order + if ground_truth is None: + # init + ground_truth = {} + preprocessed_data = {} + ground_truth_load = np.load(part + "/ground_truth.npz") + preprocessed_data_load = np.load(part + "/preprocessed_data.npz") + + for arr in ground_truth_load.files: + if arr == "images_path": + ground_truth[arr] = np.array( + [convertImagePath(args, path, record_id_start) for path in ground_truth_load[arr]]) + else: + ground_truth[arr] = ground_truth_load[arr] + for arr in preprocessed_data_load.files: + preprocessed_data[arr] = preprocessed_data_load[arr] + + else: + ground_truth_load = np.load(part + "/ground_truth.npz") + preprocessed_data_load = np.load(part + "/preprocessed_data.npz") + + for arr in ground_truth_load.files: + if arr == "images_path": + sanitised_paths = np.array( + [convertImagePath(args, path, record_id_start) for path in ground_truth_load[arr]]) + ground_truth[arr] = np.concatenate((ground_truth[arr], sanitised_paths)) + else: + ground_truth[arr] = np.concatenate((ground_truth[arr], ground_truth_load[arr])) + for arr in preprocessed_data_load.files: + preprocessed_data[arr] = np.concatenate((preprocessed_data[arr], preprocessed_data_load[arr])) + + # remove the current part folder + shutil.rmtree(part) + + # save the fused outputs + np.savez(args.save_path + args.name + "/ground_truth.npz", **ground_truth) + np.savez(args.save_path + args.name + "/preprocessed_data.npz", **preprocessed_data) + + if args.reward_dist: + rewards, counts = np.unique(np.load(args.save_path + args.name + "/preprocessed_data.npz")['rewards'], + return_counts=True) + counts = ["{:.2f}%".format(val * 100) for val in counts / np.sum(counts)] + print("reward distribution:") + [print(" ", reward, count) for reward, count in list(zip(rewards, counts))] + + +if __name__ == '__main__': + main() diff --git a/rl_baselines/base_classes.py b/rl_baselines/base_classes.py index 9260d46dc..1ad80e037 100644 --- a/rl_baselines/base_classes.py +++ b/rl_baselines/base_classes.py @@ -1,6 +1,6 @@ import os import pickle - +import re from stable_baselines.common.policies import CnnPolicy, CnnLstmPolicy, CnnLnLstmPolicy, MlpPolicy, MlpLstmPolicy, \ MlpLnLstmPolicy @@ -124,10 +124,30 @@ def save(self, save_path, _locals=None): :param save_path: (str) :param _locals: (dict) local variable from callback, if present """ + # assert self.model is not None, "Error: must train or load model before use" + # model_save_name = self.name + ".pkl" + # if os.path.basename(save_path) == model_save_name: + # model_save_name = self.name + "_model.pkl" + # + # self.model.save(os.path.dirname(save_path) + "/" + model_save_name) + # save_param = { + # "ob_space": self.ob_space, + # "ac_space": self.ac_space, + # "policy": self.policy + # } + # with open(save_path, "wb") as f: + # pickle.dump(save_param, f) assert self.model is not None, "Error: must train or load model before use" - model_save_name = self.name + ".pkl" - if os.path.basename(save_path) == model_save_name: - model_save_name = self.name + "_model.pkl" + # model_save_name = self.name + ".pkl" + # if os.path.basename(save_path) == model_save_name: + # model_save_name = self.name + "_model.pkl" + + episode = os.path.basename(save_path).split('_')[-2] + if(bool(re.search('[a-z]', episode))): + #That means this is not a episode, it is a algo name + model_save_name = self.name +".pkl" + else: + model_save_name = self.name + '_' + episode + ".pkl" self.model.save(os.path.dirname(save_path) + "/" + model_save_name) save_param = { @@ -137,6 +157,8 @@ def save(self, save_path, _locals=None): } with open(save_path, "wb") as f: pickle.dump(save_param, f) + + def setLoadPath(self, load_path): """ Load the only the parameters of the neuro-network model from a path @@ -159,10 +181,14 @@ def load(cls, load_path, args=None): loaded_model = cls() loaded_model.__dict__ = {**loaded_model.__dict__, **save_param} - model_save_name = loaded_model.name + ".pkl" - if os.path.basename(load_path) == model_save_name: - model_save_name = loaded_model.name + "_model.pkl" + episode = os.path.basename(load_path).split('_')[-2] + if(bool(re.search('[a-z]', episode))): + #That means this is not a episode, it is a algo name + model_save_name = loaded_model.name +".pkl" + else: + model_save_name = loaded_model.name +'_' + episode + ".pkl" + print(model_save_name) loaded_model.model = loaded_model.model_class.load(os.path.dirname(load_path) + "/" + model_save_name) loaded_model.states = loaded_model.model.initial_state diff --git a/rl_baselines/cross_eval.py b/rl_baselines/cross_eval.py index faaa13cbc..62d11d349 100644 --- a/rl_baselines/cross_eval.py +++ b/rl_baselines/cross_eval.py @@ -20,7 +20,8 @@ def dict2array(tasks,data): max_reward=250 else: max_reward=1850 - res.append(data[t]/max_reward) + data[t][:,1:]=data[t][:,1:]/max_reward + res.append(data[t]) res=np.array(res) return res @@ -39,9 +40,9 @@ def episodeEval(log_dir, tasks,num_timesteps=1000,num_cpu=1): file_name=log_dir+'episode_eval.npy' np.save(file_name, eval_reward) -# if __name__ == '__main__': -# -# log_dir = 'logs/OmnirobotEnv-v0/srl_combination/ppo2/19-04-24_10h36_52/' -# tasks=['cc','sc','sqc'] -# episodeEval(log_dir, tasks, num_timesteps=800, num_cpu=1) +if __name__ == '__main__': + + log_dir = 'logs_copy/cc2sc/OmnirobotEnv-v0/srl_combination/ppo2/19-04-26_20h17_37/' + tasks=['cc','sc','sqc'] + episodeEval(log_dir, tasks, num_timesteps=800, num_cpu=1) diff --git a/rl_baselines/cross_eval_utils.py b/rl_baselines/cross_eval_utils.py index edab97b2e..f2499504a 100644 --- a/rl_baselines/cross_eval_utils.py +++ b/rl_baselines/cross_eval_utils.py @@ -9,6 +9,7 @@ import tensorflow as tf import pickle from rl_baselines.utils import WrapFrameStack,computeMeanReward,printGreen +from srl_zoo.utils import printRed from stable_baselines.common import set_global_seeds from rl_baselines import AlgoType from rl_baselines.registry import registered_rl @@ -32,7 +33,7 @@ def loadConfigAndSetup(log_dir): env_globals = json.load(open(log_dir + "env_globals.json", 'r')) train_args = json.load(open(log_dir + "args.json", 'r')) env_kwargs = { - "renders": False, + "renders":False, "shape_reward": False, #TODO, since we dont use simple target, we should elimanate this choice? "action_joints": train_args["action_joints"], "is_discrete": not train_args["continuous_actions"], @@ -147,7 +148,7 @@ def policyEval(envs,model_path,log_dir,algo_class,algo_args,num_timesteps=1000,n tf.reset_default_graph() - method = algo_class.load(model_path, args=algo_args) + method = algo_class.load(model_path, args=algo_args) using_custom_vec_env = isinstance(envs, WrapFrameStack) @@ -177,9 +178,9 @@ def policyEval(envs,model_path,log_dir,algo_class,algo_args,num_timesteps=1000,n last_n_done = n_done _, mean_reward = computeMeanReward(log_dir, n_done) episode_reward.append(mean_reward) - #printRed('Episode:{} Reward:{}'.format(n_done,mean_reward)) + printRed('Episode:{} Reward:{}'.format(n_done,mean_reward)) _, mean_reward = computeMeanReward(log_dir, n_done) - #printRed('Episode:{} Reward:{}'.format(n_done, mean_reward)) + printRed('Episode:{} Reward:{}'.format(n_done, mean_reward)) episode_reward.append(mean_reward) @@ -189,6 +190,9 @@ def policyEval(envs,model_path,log_dir,algo_class,algo_args,num_timesteps=1000,n + + + def latestPolicy(log_dir,algo_name): """ Get the latest saved model from a file @@ -214,40 +218,31 @@ def sortFirst(val): return 0,'',False def policyCrossEval(log_dir,task,num_timesteps=2000,num_cpu=1): - """ - Given several tasks and a logdir, to evaluate the policy on different environments corresponding to the tasks - :param log_dir: - :param tasks: - :param num_timesteps: - :return: - """ - train_args, algo_name, algo_class, srl_model_path, env_kwargs = loadConfigAndSetup(log_dir) - - episode, model_path,OK=latestPolicy(log_dir,algo_name) + episode, model_path, OK = latestPolicy(log_dir, algo_name) env_kwargs = EnvsKwargs(task, env_kwargs) - OK=True - if(not OK): - #no latest model saved yet - return None, False + OK = True + if (not OK): + # no latest model saved yet + return None, False else: pass - printGreen("Evaluation from the model saved at: {}, with evaluation time steps: {}".format(model_path, num_timesteps)) + printGreen( + "Evaluation from the model saved at: {}, with evaluation time steps: {}".format(model_path, num_timesteps)) - log_dir, environment, algo_args = createEnv(log_dir, train_args, algo_name, algo_class, env_kwargs,num_cpu=num_cpu) + log_dir, environment, algo_args = createEnv(log_dir, train_args, algo_name, algo_class, env_kwargs, num_cpu=num_cpu) + reward = policyEval(environment, model_path, log_dir, algo_class, algo_args, num_timesteps, num_cpu) - reward=policyEval(environment, model_path, log_dir, algo_class, algo_args, num_timesteps,num_cpu) - - - #Just a trick to save the episode number of the reward,but need a little bit more space to store - reward=np.append(episode,reward) + # Just a trick to save the episode number of the reward,but need a little bit more space to store + reward = np.append(episode, reward) return reward, True + def episodeEval(log_dir,task,save_name='episode_eval.pkl',num_timesteps=800,num_cpu=1): """ given a log_dir to the model path and different tasks for ominirobot, save the reward of the latest saved model diff --git a/rl_baselines/student_eval.py b/rl_baselines/student_eval.py index c02b9e46c..f8d0498a2 100644 --- a/rl_baselines/student_eval.py +++ b/rl_baselines/student_eval.py @@ -38,19 +38,24 @@ def srl_train(teacher_path): -def DatasetGenerator(teacher_path,output_name,task_id, - env_name='OmnirobotEnv-v0', num_cpu=1,num_eps=600): - command_line = ['python','-m', 'environments.dataset_generator','--run-policy', 'custom'] +def DatasetGenerator(teacher_path,output_name,task_id,episode=-1, + env_name='OmnirobotEnv-v0', num_cpu=1,num_eps=200): + command_line = ['python','-m', 'environments.dataset_generator_student','--run-policy', 'custom'] cpu_command = ['--num-cpu',str(num_cpu)] name_command = ['--name',output_name] env_command = ['--env',env_name] task_command = [task_id] episode_command= ['--num-episode', str(num_eps)] policy_command = ['--log-custom-policy',teacher_path] + if(episode==-1): + eps_policy = [] + else: + eps_policy = ['--episode', str(episode)] - ok=subprocess.call(command_line + cpu_command +policy_command - +name_command+env_command - +task_command +episode_command) + command=command_line + cpu_command +policy_command+name_command+env_command+task_command +episode_command +eps_policy + if(task_id=='-sc' or task_id=='--simple-continual'): + command+=['--short-episodes'] + ok=subprocess.call(command) @@ -103,9 +108,17 @@ def mergeData(teacher_dataset_1,teacher_dataset_2,merge_dataset): subprocess.call(['python', '-m', 'environments.dataset_fusioner']+merge_command) + +def evaluateStudent(): + #TODO + + return + if __name__ == '__main__': teacher_path='logs/circular/OmnirobotEnv-v0/srl_combination/ppo2/19-04-26_12h02_30/' - teacher_path = 'logs/ground_truth/ppo2/19-04-23_17h35_17/' + teacher_path = 'logs_copy/cc2sc/OmnirobotEnv-v0/srl_combination/ppo2/19-04-26_20h17_37/' + + teacher_data_path='srl_zoo/data/circular_teacher/' task_id='-cc' output_name='circular_on_policy1' @@ -117,4 +130,38 @@ def mergeData(teacher_dataset_1,teacher_dataset_2,merge_dataset): #mergeData(t1,t2,merge_path) #print(newPolicy([1,2,3],teacher_path)) #trainStudent(teacher_data_path,task_id) - print(allPolicy(teacher_path)[1]) + + + task_pro,task_learn='-sc','-cc' + teacher_pro = 'logs_copy/cc2sc/OmnirobotEnv-v0/srl_combination/ppo2/19-04-26_20h17_37/' + teacher_learn = 'logs_copy/cc2sc/OmnirobotEnv-v0/srl_combination/ppo2/19-04-26_20h17_37/' + + #The output path generate from the + teacher_pro_data = 'srl_zoo/data/Untitled Folder/'+task_pro[1:]+'/' + teacher_learn_data = 'srl_zoo/data/Untitled Folder/'+task_learn[1:]+'/' + + + + episodes, policy_path = allPolicy(teacher_path) + + + for eps in episodes: + print('OK') + #generate data from Professional teacher + DatasetGenerator(teacher_pro,teacher_pro_data,task_pro,episodes[5],num_eps=200) + #Generate data from learning teacher + DatasetGenerator(teacher_learn, teacher_learn_data, task_learn, episodes[5],num_eps=200) + #merge the data + mergeData(teacher_pro_data, teacher_learn_data,merge_path) + + #train on the merged data + log_dir = 'logs/student/' + yaml_file ='config/srl_models.yaml' + + + trainStudent(merge_path, task_id, yaml_file=yaml_file, log_dir=log_dir, + srl_model='srl_combination', env_name='OmnirobotEnv-v0',training_size=40000, epochs=20) + + evaluateStudent(log_dir) + + diff --git a/rl_baselines/train.py b/rl_baselines/train.py index 2938cdfa9..282c32d18 100644 --- a/rl_baselines/train.py +++ b/rl_baselines/train.py @@ -166,11 +166,17 @@ def callback(_locals, _globals): best_mean_reward = mean_reward printGreen("Saving new best model") ALGO.save(LOG_DIR + ALGO_NAME + "_model.pkl", _locals) - # if n_episodes >0 and n_episodes%100==0: - # # Cross evaluation for all tasks: - # ALGO.save(LOG_DIR + ALGO_NAME +"_"+str(n_episodes)+ "_model.pkl", _locals) - # printYellow(EVAL_TASK) - # episodeEval(LOG_DIR, EVAL_TASK) + if n_episodes >0 : + if (n_episodes>=70 and n_episodes%40==0): + ALGO.save(LOG_DIR + ALGO_NAME +"_"+str(n_episodes)+ "_model.pkl", _locals) + printYellow(EVAL_TASK) + episodeEval(LOG_DIR, EVAL_TASK) + + if(n_episodes>=800 and n_episodes%200==0): + ALGO.save(LOG_DIR + ALGO_NAME + "_" + str(n_episodes) + "_model.pkl", _locals) + printYellow(EVAL_TASK) + episodeEval(LOG_DIR, EVAL_TASK) + # Plots in visdom if viz and (n_steps + 1) % LOG_INTERVAL == 0: @@ -179,8 +185,8 @@ def callback(_locals, _globals): is_es=is_es) win_episodes = episodePlot(viz, win_episodes, LOG_DIR, ENV_NAME, ALGO_NAME, window=EPISODE_WINDOW, title=PLOT_TITLE + " [Episodes]", is_es=is_es) - # win_crossEval= episodesEvalPlot(viz,win_crossEval,LOG_DIR,ENV_NAME,EVAL_TASK, - # title=PLOT_TITLE +" [Cross Evaluation]") + win_crossEval= episodesEvalPlot(viz,win_crossEval,LOG_DIR,ENV_NAME,EVAL_TASK, + title=PLOT_TITLE +" [Cross Evaluation]") n_steps += 1 return True @@ -372,8 +378,8 @@ def main(): if args.load_rl_model_path is not None: #use a small learning rate - print("use a small learning rate: {:f}".format(1.0e-4)) - hyperparams["learning_rate"] = lambda f: f * 1.0e-4 + print("use a small learning rate: {:f}".format(1.0e-8)) + hyperparams["learning_rate"] = lambda f: f * 1.0e-8 # Train the agent # episodeEval(LOG_DIR,EVAL_TASK) From c8af5360ca7309173b15ff17b594fa2090d7b0d7 Mon Sep 17 00:00:00 2001 From: kalifou Date: Mon, 29 Apr 2019 16:50:13 +0200 Subject: [PATCH 086/141] update: student policy distillation and eval while learning a teacher/task 2 --- rl_baselines/student_eval.py | 231 +++++++++++++++++++++-------------- rl_baselines/train.py | 17 ++- 2 files changed, 148 insertions(+), 100 deletions(-) diff --git a/rl_baselines/student_eval.py b/rl_baselines/student_eval.py index f8d0498a2..273de6325 100644 --- a/rl_baselines/student_eval.py +++ b/rl_baselines/student_eval.py @@ -1,70 +1,59 @@ -""" -Modified version of https://github.com/ikostrikov/pytorch-a2c-ppo-acktr/blob/master/visualize.py -Script used to send plot data to visdom -""" +import argparse import glob -import os -import json import numpy as np -import tensorflow as tf -import pickle -from srl_zoo.utils import printRed -from rl_baselines.utils import WrapFrameStack,computeMeanReward -from stable_baselines.common import set_global_seeds -from rl_baselines import AlgoType -from rl_baselines.registry import registered_rl -from rl_baselines.cross_eval_utils import loadConfigAndSetup, latestPolicy -from datetime import datetime +import os import subprocess +import yaml -def newFile(episode,filename): - #Verify if the new saved policy is already learned by the student - return +from rl_baselines.cross_eval_utils import loadConfigAndSetup, latestPolicy +from srl_zoo.utils import printRed, printYellow +from state_representation.registry import registered_srl -def srl_train(teacher_path): - tmp_dir=os.getcwd() - os.chdir('srl_zoo') - # python - m - # environments.dataset_generator - -num - cpu - # 6 - -name - # Omnibot_random_simple - -env - # OmnirobotEnv - v0 - -simple - continual - -num - episode - # 250 - f - printRed(os.getcwd()) - subprocess.call(['python ']) - os.chdir(tmp_dir) - printRed(os.getcwd()) - return +CONTINUAL_LEARNING_LABELS = ['CC', 'SC', 'EC', 'SQC'] +CL_LABEL_KEY = "continual_learning_label" +def DatasetGenerator(teacher_path, output_name, task_id, episode=-1, + env_name='OmnirobotEnv-v0', num_cpu=1, num_eps=200): + """ -def DatasetGenerator(teacher_path,output_name,task_id,episode=-1, - env_name='OmnirobotEnv-v0', num_cpu=1,num_eps=200): + :param teacher_path: + :param output_name: + :param task_id: + :param episode: + :param env_name: + :param num_cpu: + :param num_eps: + :return: + """ command_line = ['python','-m', 'environments.dataset_generator_student','--run-policy', 'custom'] - cpu_command = ['--num-cpu',str(num_cpu)] + cpu_command = ['--num-cpu',str(num_cpu)] name_command = ['--name',output_name] - env_command = ['--env',env_name] - task_command = [task_id] - episode_command= ['--num-episode', str(num_eps)] + save_path = ['--save-path', "data/"] + env_command = ['--env',env_name] + task_command = ["-sc" if task_id is "SC" else '-cc'] + episode_command = ['--num-episode', str(num_eps)] policy_command = ['--log-custom-policy',teacher_path] if(episode==-1): eps_policy = [] else: eps_policy = ['--episode', str(episode)] - command=command_line + cpu_command +policy_command+name_command+env_command+task_command +episode_command +eps_policy - if(task_id=='-sc' or task_id=='--simple-continual'): - command+=['--short-episodes'] - ok=subprocess.call(command) + command=command_line + cpu_command +policy_command + name_command + env_command + task_command + \ + episode_command + eps_policy + save_path + ['-f'] + if task_id == 'SC': + command += ['--short-episodes'] + + ok = subprocess.call(command) def allPolicy(log_dir): train_args, algo_name, algo_class, srl_model_path, env_kwargs = loadConfigAndSetup(log_dir) - files= glob.glob(os.path.join(log_dir+algo_name+'_*_model.pkl')) + files = glob.glob(os.path.join(log_dir+algo_name+'_*_model.pkl')) files_list = [] for file in files: - eps=int((file.split('_')[-2])) + eps = int((file.split('_')[-2])) files_list.append((eps,file)) def sortFirst(val): @@ -72,11 +61,10 @@ def sortFirst(val): files_list.sort(key=sortFirst) res = np.array(files_list) + print("res: ", res) return res[:,0], res[:,1] - - def newPolicy(episodes, file_path): train_args, algo_name, algo_class, srl_model_path, env_kwargs=loadConfigAndSetup(file_path) episode, model_path,OK=latestPolicy(file_path,algo_name) @@ -86,82 +74,137 @@ def newPolicy(episodes, file_path): return episode, model_path,True -def trainStudent(teacher_data_path,task_id, +def trainStudent(teacher_data_path, task_id, yaml_file='config/srl_models.yaml', log_dir='logs/', srl_model='srl_combination', env_name='OmnirobotEnv-v0', training_size=40000, epochs=20): - command_line = ['python','-m', 'rl_baselines.train','--latest','--algo', 'distillation','--log-dir',log_dir] - srl_command = ['--srl-model',srl_model] - env_command = ['--env',env_name] + """ + + :param teacher_data_path: + :param task_id: Environment ID + :param yaml_file: + :param log_dir: + :param srl_model: + :param env_name: + :param training_size: + :param epochs: + :return: + """ + command_line = ['python','-m', 'rl_baselines.train', '--latest', '--algo', 'distillation', '--log-dir',log_dir] + srl_command = ['--srl-model',srl_model] + env_command = ['--env', env_name] policy_command = ['--teacher-data-folder', teacher_data_path] - size_epochs =['--distillation-training-set-size',str(training_size),'--epochs-distillation',str(epochs)] - task_command = [task_id] + size_epochs = ['--distillation-training-set-size',str(training_size),'--epochs-distillation',str(epochs)] + task_command = ["-sc" if task_id is "SC" else '-cc'] ok = subprocess.call(command_line + srl_command - +env_command +policy_command +size_epochs+task_command +['--srl-config-file',yaml_file]) + + env_command + policy_command + size_epochs + task_command +['--srl-config-file',yaml_file]) + -#python -m environments.dataset_fusioner -# --merge srl_zoo/data/circular_on_policy/ srl_zoo/data/reaching_on_policy/ srl_zoo/data/merge_CC_SC def mergeData(teacher_dataset_1,teacher_dataset_2,merge_dataset): merge_command=['--merge',teacher_dataset_1,teacher_dataset_2,merge_dataset] subprocess.call(['python', '-m', 'environments.dataset_fusioner']+merge_command) - def evaluateStudent(): #TODO return -if __name__ == '__main__': - teacher_path='logs/circular/OmnirobotEnv-v0/srl_combination/ppo2/19-04-26_12h02_30/' - teacher_path = 'logs_copy/cc2sc/OmnirobotEnv-v0/srl_combination/ppo2/19-04-26_20h17_37/' - - - teacher_data_path='srl_zoo/data/circular_teacher/' - task_id='-cc' - output_name='circular_on_policy1' - num_cpu=8 - yaml_file='config/srl_models_circular.yaml' - merge_path='srl_zoo/data/merge' - t1,t2='srl_zoo/data/Omnibot_circular','srl_zoo/data/Omnibot_random_simple' - #mergeData(t1,t2,merge_path) - #print(newPolicy([1,2,3],teacher_path)) - #trainStudent(teacher_data_path,task_id) - - - task_pro,task_learn='-sc','-cc' - teacher_pro = 'logs_copy/cc2sc/OmnirobotEnv-v0/srl_combination/ppo2/19-04-26_20h17_37/' - teacher_learn = 'logs_copy/cc2sc/OmnirobotEnv-v0/srl_combination/ppo2/19-04-26_20h17_37/' +def main(): + # Global variables for callback + global ENV_NAME, ALGO, ALGO_NAME, LOG_INTERVAL, VISDOM_PORT, viz + global SAVE_INTERVAL, EPISODE_WINDOW, MIN_EPISODES_BEFORE_SAVE + parser = argparse.ArgumentParser(description="Eval script for distillation from two teacher policies") + parser.add_argument('--seed', type=int, default=0, help='random seed (default: 0)') + parser.add_argument('--episode_window', type=int, default=40, + help='Episode window for moving average plot (default: 40)') + parser.add_argument('--log-dir-teacher-one', default='/tmp/gym/', type=str, + help='directory to load an optmimal agent for task 1 (default: /tmp/gym)') + parser.add_argument('--log-dir-teacher-two', default='/tmp/gym/', type=str, + help='directory to load an optmimal agent for task 2 (default: /tmp/gym)') + parser.add_argument('--log-dir-student', default='/tmp/gym/', type=str, + help='directory to save the student agent logs and model (default: /tmp/gym)') + parser.add_argument('--srl-config-file-one', type=str, default="config/srl_models_one.yaml", + help='Set the location of the SRL model path configuration.') + parser.add_argument('--srl-config-file-two', type=str, default="config/srl_models_two.yaml", + help='Set the location of the SRL model path configuration.') + parser.add_argument('--epochs-distillation', type=int, default=30, metavar='N', + help='number of epochs to train for distillation(default: 30)') + parser.add_argument('--distillation-training-set-size', type=int, default=-1, + help='Limit size (number of samples) of the training set (default: -1)') + parser.add_argument('--eval-tasks', type=str, nargs='+', default=['cc', 'sqc', 'sc'], + help='A cross evaluation from the latest stored model to all tasks') + parser.add_argument('--continual-learning-labels', type=str, nargs=2, metavar=('label_1', 'label_2'), + default=argparse.SUPPRESS, + help='Labels for the continual learning RL distillation task.') + parser.add_argument('--student-srl-model', type=str, default='raw_pixels', choices=list(registered_srl.keys()), + help='SRL model to use for the student RL policy') + parser.add_argument('--epochs-teacher-datasets', type=int, default=30, metavar='N', + help='number of epochs for generating both RL teacher datasets (default: 30)') + + args, unknown = parser.parse_known_args() + + if 'continual_learning_labels' in args: + assert args.continual_learning_labels[0] in CONTINUAL_LEARNING_LABELS \ + and args.continual_learning_labels[1] in CONTINUAL_LEARNING_LABELS, \ + "Please specify a valid Continual learning label to each dataset to be used for RL distillation !" + + assert os.path.exists(args.srl_config_file_one), \ + "Error: cannot load \"--srl-config-file {}\", file not found!".format(args.srl_config_file_one) + assert os.path.exists(args.srl_config_file_two), \ + "Error: cannot load \"--srl-config-file {}\", file not found!".format(args.srl_config_file_two) + assert os.path.exists(args.log_dir_teacher_one), \ + "Error: cannot load \"--srl-config-file {}\", file not found!".format(args.log_dir_teacher_one) + assert os.path.exists(args.log_dir_teacher_two), \ + "Error: cannot load \"--srl-config-file {}\", file not found!".format(args.srl_config_file_two) + + with open(args.srl_config_file_one, 'rb') as f: + model_one = yaml.load(f) + + with open(args.srl_config_file_two, 'rb') as f: + model_two = yaml.load(f) + + teacher_pro = args.log_dir_teacher_one + teacher_learn = args.log_dir_teacher_two #The output path generate from the - teacher_pro_data = 'srl_zoo/data/Untitled Folder/'+task_pro[1:]+'/' - teacher_learn_data = 'srl_zoo/data/Untitled Folder/'+task_learn[1:]+'/' + teacher_pro_data = args.continual_learning_labels[0] + '/' + teacher_learn_data = args.continual_learning_labels[1] + '/' + merge_path = "data/on_policy_merged" + print(teacher_pro_data, teacher_learn_data) + episodes, policy_path = allPolicy(teacher_learn) + for eps in [120]: #episodes: + # generate data from Professional teacher + printYellow("\nGenerating on policy for optimal teacher :" + args.continual_learning_labels[0]) - episodes, policy_path = allPolicy(teacher_path) + DatasetGenerator(teacher_pro, teacher_pro_data, args.continual_learning_labels[0], + num_eps=args.epochs_teacher_datasets, episode=-1) + # Generate data from learning teacher + printYellow("\nGenerating on policy for optimal teacher :" + args.continual_learning_labels[1]) + DatasetGenerator(teacher_learn, teacher_learn_data, args.continual_learning_labels[1], eps, + num_eps=args.epochs_teacher_datasets) - for eps in episodes: - print('OK') - #generate data from Professional teacher - DatasetGenerator(teacher_pro,teacher_pro_data,task_pro,episodes[5],num_eps=200) - #Generate data from learning teacher - DatasetGenerator(teacher_learn, teacher_learn_data, task_learn, episodes[5],num_eps=200) - #merge the data - mergeData(teacher_pro_data, teacher_learn_data,merge_path) + # # merge the data + mergeData('data/' + teacher_pro_data, 'data/' + teacher_learn_data, merge_path) - #train on the merged data - log_dir = 'logs/student/' - yaml_file ='config/srl_models.yaml' + ok = subprocess.call( + ['cp', '-r', merge_path, 'srl_zoo/' + merge_path]) + assert ok == 0 + # Train a policy with distillation on the merged teacher's datasets + trainStudent(merge_path, args.continual_learning_labels[1], yaml_file=args.srl_config_file_one, + log_dir=args.log_dir_student, + srl_model=args.student_srl_model, env_name='OmnirobotEnv-v0', + training_size=args.distillation_training_set_size, epochs=args.epochs_distillation) - trainStudent(merge_path, task_id, yaml_file=yaml_file, log_dir=log_dir, - srl_model='srl_combination', env_name='OmnirobotEnv-v0',training_size=40000, epochs=20) - - evaluateStudent(log_dir) + # evaluateStudent(log_dir) +if __name__ == '__main__': + main() diff --git a/rl_baselines/train.py b/rl_baselines/train.py index 282c32d18..abe4d8a53 100644 --- a/rl_baselines/train.py +++ b/rl_baselines/train.py @@ -35,6 +35,7 @@ PLOT_TITLE = "" EPISODE_WINDOW = 40 # For plotting moving average EVAL_TASK=['cc','sc','sqc'] +CROSS_EVAL = False viz = None n_steps = 0 @@ -170,13 +171,14 @@ def callback(_locals, _globals): if (n_episodes>=70 and n_episodes%40==0): ALGO.save(LOG_DIR + ALGO_NAME +"_"+str(n_episodes)+ "_model.pkl", _locals) printYellow(EVAL_TASK) - episodeEval(LOG_DIR, EVAL_TASK) + if CROSS_EVAL: + episodeEval(LOG_DIR, EVAL_TASK) if(n_episodes>=800 and n_episodes%200==0): ALGO.save(LOG_DIR + ALGO_NAME + "_" + str(n_episodes) + "_model.pkl", _locals) printYellow(EVAL_TASK) - episodeEval(LOG_DIR, EVAL_TASK) - + if CROSS_EVAL: + episodeEval(LOG_DIR, EVAL_TASK) # Plots in visdom if viz and (n_steps + 1) % LOG_INTERVAL == 0: @@ -185,8 +187,9 @@ def callback(_locals, _globals): is_es=is_es) win_episodes = episodePlot(viz, win_episodes, LOG_DIR, ENV_NAME, ALGO_NAME, window=EPISODE_WINDOW, title=PLOT_TITLE + " [Episodes]", is_es=is_es) - win_crossEval= episodesEvalPlot(viz,win_crossEval,LOG_DIR,ENV_NAME,EVAL_TASK, - title=PLOT_TITLE +" [Cross Evaluation]") + if CROSS_EVAL: + win_crossEval= episodesEvalPlot(viz,win_crossEval,LOG_DIR,ENV_NAME,EVAL_TASK, + title=PLOT_TITLE + " [Cross Evaluation]") n_steps += 1 return True @@ -247,9 +250,10 @@ def main(): help='number of epochs to train for distillation(default: 30)') parser.add_argument('--distillation-training-set-size', type=int, default=-1, help='Limit size (number of samples) of the training set (default: -1)') - parser.add_argument('--eval-tasks', type=str, nargs='+', default=['cc','sqc','sc'], + parser.add_argument('--perform-cross-evaluation-cc', action='store_true', default=False, help='A cross evaluation from the latest stored model to all tasks') + # Ignore unknown args for now args, unknown = parser.parse_known_args() env_kwargs = {} @@ -290,6 +294,7 @@ def main(): VISDOM_PORT = args.port EPISODE_WINDOW = args.episode_window MIN_EPISODES_BEFORE_SAVE = args.min_episodes_save + CROSS_EVAL = args.perform_cross_evaluation_cc if args.no_vis: From e561b9320092bac4d12a84533cac30d5e7c5b03d Mon Sep 17 00:00:00 2001 From: kalifou Date: Mon, 29 Apr 2019 19:36:21 +0200 Subject: [PATCH 087/141] update of distillation eval --- rl_baselines/student_eval.py | 39 +++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/rl_baselines/student_eval.py b/rl_baselines/student_eval.py index 273de6325..34bd93221 100644 --- a/rl_baselines/student_eval.py +++ b/rl_baselines/student_eval.py @@ -46,6 +46,7 @@ def DatasetGenerator(teacher_path, output_name, task_id, episode=-1, command += ['--short-episodes'] ok = subprocess.call(command) + assert ok == 0, "Teacher dataset for task " + task_id + " was not generated !" def allPolicy(log_dir): @@ -61,7 +62,7 @@ def sortFirst(val): files_list.sort(key=sortFirst) res = np.array(files_list) - print("res: ", res) + #print("res: ", res) return res[:,0], res[:,1] @@ -117,7 +118,7 @@ def main(): # Global variables for callback global ENV_NAME, ALGO, ALGO_NAME, LOG_INTERVAL, VISDOM_PORT, viz global SAVE_INTERVAL, EPISODE_WINDOW, MIN_EPISODES_BEFORE_SAVE - parser = argparse.ArgumentParser(description="Eval script for distillation from two teacher policies") + parser = argparse.ArgumentParser(description="Evaluation script for distillation from two teacher policies") parser.add_argument('--seed', type=int, default=0, help='random seed (default: 0)') parser.add_argument('--episode_window', type=int, default=40, help='Episode window for moving average plot (default: 40)') @@ -144,6 +145,8 @@ def main(): help='SRL model to use for the student RL policy') parser.add_argument('--epochs-teacher-datasets', type=int, default=30, metavar='N', help='number of epochs for generating both RL teacher datasets (default: 30)') + parser.add_argument('--num-iteration', type=int, default=15, + help='number of time each algorithm should be run the eval (N seeds).') args, unknown = parser.parse_known_args() @@ -177,16 +180,19 @@ def main(): print(teacher_pro_data, teacher_learn_data) episodes, policy_path = allPolicy(teacher_learn) + student_path = args.log_dir_student #"+ '/' + args.student_srl_model + "/distillation/" - for eps in [120]: #episodes: + rewards_at_episode = {} + for eps in episodes[:2]: + printRed("\n\nEvaluation at episode " + str(eps)) # generate data from Professional teacher - printYellow("\nGenerating on policy for optimal teacher :" + args.continual_learning_labels[0]) + printYellow("\nGenerating on policy for optimal teacher: " + args.continual_learning_labels[0]) DatasetGenerator(teacher_pro, teacher_pro_data, args.continual_learning_labels[0], num_eps=args.epochs_teacher_datasets, episode=-1) # Generate data from learning teacher - printYellow("\nGenerating on policy for optimal teacher :" + args.continual_learning_labels[1]) + printYellow("\nGenerating on policy for optimal teacher: " + args.continual_learning_labels[1]) DatasetGenerator(teacher_learn, teacher_learn_data, args.continual_learning_labels[1], eps, num_eps=args.epochs_teacher_datasets) @@ -202,8 +208,27 @@ def main(): log_dir=args.log_dir_student, srl_model=args.student_srl_model, env_name='OmnirobotEnv-v0', training_size=args.distillation_training_set_size, epochs=args.epochs_distillation) - - # evaluateStudent(log_dir) + latest_student_path = max([student_path + "/" + d for d in os.listdir(student_path) if os.path.isdir(student_path + "/" + d)], + key=os.path.getmtime) + rewards = {} + printRed(latest_student_path) + for task_label in ["-sc", "-cc"]: + rewards[task_label] = [] + for seed_i in range(args.num_iteration): + printYellow("\nEvaluating student on task: " + task_label +" for seed: " + str(seed_i)) + command_line_enjoy_student = ['python','-m', 'replay.enjoy_baselines','--num-timesteps', '251', + '--log-dir', latest_student_path, task_label, "--seed", str(seed_i)] + ok = subprocess.check_output(command_line_enjoy_student) + ok = ok.decode('utf-8') + str_before = "Mean reward: " + str_after = "\npybullet" + idx_before = ok.find(str_before) + len(str_before) + idx_after = ok.find(str_after) + seed_reward = float(ok[idx_before: idx_after]) + rewards[task_label].append(seed_reward) + print("rewards at eps : ", rewards) + rewards_at_episode[eps] = rewards + print("All rewards: ", rewards_at_episode) if __name__ == '__main__': From 35286efba728626d3c037d6e812c3428b70bec72 Mon Sep 17 00:00:00 2001 From: kalifou Date: Mon, 29 Apr 2019 23:03:21 +0200 Subject: [PATCH 088/141] update eval distillation --- environments/dataset_generator_student.py | 1 - environments/omnirobot_gym/omnirobot_env.py | 9 +- rl_baselines/student_eval.py | 134 +++++++++++--------- rl_baselines/train.py | 18 ++- 4 files changed, 85 insertions(+), 77 deletions(-) diff --git a/environments/dataset_generator_student.py b/environments/dataset_generator_student.py index 9ab9297af..687bbbe82 100644 --- a/environments/dataset_generator_student.py +++ b/environments/dataset_generator_student.py @@ -104,7 +104,6 @@ def loadConfigAndSetup(load_args): return train_args, load_path, algo_name, algo_class, srl_model_path, env_kwargs - def convertImagePath(args, path, record_id_start): """ Used to convert an image path, from one location, to another diff --git a/environments/omnirobot_gym/omnirobot_env.py b/environments/omnirobot_gym/omnirobot_env.py index 27ca35e4b..e842e0559 100644 --- a/environments/omnirobot_gym/omnirobot_env.py +++ b/environments/omnirobot_gym/omnirobot_env.py @@ -303,9 +303,12 @@ def _hasEpisodeTerminated(self): """ Returns True if the episode is over and False otherwise """ - if self.episode_terminated or self._env_step_counter > MAX_STEPS or \ - (self.n_contacts >= N_CONTACTS_BEFORE_TERMINATION and self.short_episodes) or \ - (self._env_step_counter > MAX_STEPS_CIRCULAR_TASK_SHORT_EPISODES and self.short_episodes): + if (self.episode_terminated or self._env_step_counter > MAX_STEPS) or \ + (self.n_contacts >= N_CONTACTS_BEFORE_TERMINATION and self.short_episodes and + self.simple_continual_target) or \ + (self._env_step_counter > MAX_STEPS_CIRCULAR_TASK_SHORT_EPISODES and self.short_episodes and + self.circular_continual_move): + print(self.simple_continual_target, self.circular_continual_move) return True if np.abs(self.reward - REWARD_TARGET_REACH) < 0.000001: # reach the target diff --git a/rl_baselines/student_eval.py b/rl_baselines/student_eval.py index 34bd93221..abbd2e699 100644 --- a/rl_baselines/student_eval.py +++ b/rl_baselines/student_eval.py @@ -3,8 +3,9 @@ import numpy as np import os import subprocess -import yaml +# import yaml +from environments.registry import registered_env from rl_baselines.cross_eval_utils import loadConfigAndSetup, latestPolicy from srl_zoo.utils import printRed, printYellow from state_representation.registry import registered_srl @@ -13,8 +14,8 @@ CL_LABEL_KEY = "continual_learning_label" -def DatasetGenerator(teacher_path, output_name, task_id, episode=-1, - env_name='OmnirobotEnv-v0', num_cpu=1, num_eps=200): +def DatasetGenerator(teacher_path, output_name, task_id, episode=-1, env_name='OmnirobotEnv-v0', num_cpu=1, + num_eps=200): """ :param teacher_path: @@ -26,21 +27,21 @@ def DatasetGenerator(teacher_path, output_name, task_id, episode=-1, :param num_eps: :return: """ - command_line = ['python','-m', 'environments.dataset_generator_student','--run-policy', 'custom'] - cpu_command = ['--num-cpu',str(num_cpu)] - name_command = ['--name',output_name] + command_line = ['python', '-m', 'environments.dataset_generator_student', '--run-policy', 'custom'] + cpu_command = ['--num-cpu', str(num_cpu)] + name_command = ['--name', output_name] save_path = ['--save-path', "data/"] - env_command = ['--env',env_name] - task_command = ["-sc" if task_id is "SC" else '-cc'] + env_command = ['--env', env_name] + task_command = ["-sc" if task_id == "SC" else '-cc'] episode_command = ['--num-episode', str(num_eps)] - policy_command = ['--log-custom-policy',teacher_path] - if(episode==-1): + policy_command = ['--log-custom-policy', teacher_path] + if episode == -1: eps_policy = [] else: eps_policy = ['--episode', str(episode)] - command=command_line + cpu_command +policy_command + name_command + env_command + task_command + \ - episode_command + eps_policy + save_path + ['-f'] + command = command_line + cpu_command + policy_command + name_command + env_command + task_command + \ + episode_command + eps_policy + save_path + ['-f'] if task_id == 'SC': command += ['--short-episodes'] @@ -50,37 +51,48 @@ def DatasetGenerator(teacher_path, output_name, task_id, episode=-1, def allPolicy(log_dir): + """ + + :param log_dir: + :return: + """ train_args, algo_name, algo_class, srl_model_path, env_kwargs = loadConfigAndSetup(log_dir) - files = glob.glob(os.path.join(log_dir+algo_name+'_*_model.pkl')) + files = glob.glob(os.path.join(log_dir + algo_name + '_*_model.pkl')) files_list = [] for file in files: eps = int((file.split('_')[-2])) - files_list.append((eps,file)) + files_list.append((eps, file)) def sortFirst(val): + """ + + :param val: + :return: + """ return val[0] files_list.sort(key=sortFirst) res = np.array(files_list) - #print("res: ", res) - return res[:,0], res[:,1] + return res[:, 0], res[:, 1] def newPolicy(episodes, file_path): - train_args, algo_name, algo_class, srl_model_path, env_kwargs=loadConfigAndSetup(file_path) - episode, model_path,OK=latestPolicy(file_path,algo_name) - if(episode in episodes): - return -1,'', False + """ + + :param episodes: + :param file_path: + :return: + """ + train_args, algo_name, algo_class, srl_model_path, env_kwargs = loadConfigAndSetup(file_path) + episode, model_path, OK = latestPolicy(file_path, algo_name) + if episode in episodes: + return -1, '', False else: - return episode, model_path,True + return episode, model_path, True -def trainStudent(teacher_data_path, task_id, - yaml_file='config/srl_models.yaml', - log_dir='logs/', - srl_model='srl_combination', - env_name='OmnirobotEnv-v0', - training_size=40000, epochs=20): +def trainStudent(teacher_data_path, task_id, yaml_file='config/srl_models.yaml', log_dir='logs/', + srl_model='srl_combination', env_name='OmnirobotEnv-v0', training_size=40000, epochs=20): """ :param teacher_data_path: @@ -93,33 +105,27 @@ def trainStudent(teacher_data_path, task_id, :param epochs: :return: """ - command_line = ['python','-m', 'rl_baselines.train', '--latest', '--algo', 'distillation', '--log-dir',log_dir] - srl_command = ['--srl-model',srl_model] + command_line = ['python', '-m', 'rl_baselines.train', '--latest', '--algo', 'distillation', '--log-dir', log_dir] + srl_command = ['--srl-model', srl_model] env_command = ['--env', env_name] policy_command = ['--teacher-data-folder', teacher_data_path] - size_epochs = ['--distillation-training-set-size',str(training_size),'--epochs-distillation',str(epochs)] + size_epochs = ['--distillation-training-set-size', str(training_size), '--epochs-distillation', str(epochs)] task_command = ["-sc" if task_id is "SC" else '-cc'] ok = subprocess.call(command_line + srl_command - + env_command + policy_command + size_epochs + task_command +['--srl-config-file',yaml_file]) - + + env_command + policy_command + size_epochs + task_command + ['--srl-config-file', yaml_file]) -def mergeData(teacher_dataset_1,teacher_dataset_2,merge_dataset): - merge_command=['--merge',teacher_dataset_1,teacher_dataset_2,merge_dataset] - subprocess.call(['python', '-m', 'environments.dataset_fusioner']+merge_command) - -def evaluateStudent(): - #TODO - - return +def mergeData(teacher_dataset_1, teacher_dataset_2, merge_dataset): + merge_command = ['--merge', teacher_dataset_1, teacher_dataset_2, merge_dataset] + subprocess.call(['python', '-m', 'environments.dataset_fusioner'] + merge_command) def main(): # Global variables for callback - global ENV_NAME, ALGO, ALGO_NAME, LOG_INTERVAL, VISDOM_PORT, viz - global SAVE_INTERVAL, EPISODE_WINDOW, MIN_EPISODES_BEFORE_SAVE parser = argparse.ArgumentParser(description="Evaluation script for distillation from two teacher policies") parser.add_argument('--seed', type=int, default=0, help='random seed (default: 0)') + parser.add_argument('--env', type=str, help='environment ID', default='OmnirobotEnv-v0', + choices=list(registered_env.keys())) parser.add_argument('--episode_window', type=int, default=40, help='Episode window for moving average plot (default: 40)') parser.add_argument('--log-dir-teacher-one', default='/tmp/gym/', type=str, @@ -145,16 +151,16 @@ def main(): help='SRL model to use for the student RL policy') parser.add_argument('--epochs-teacher-datasets', type=int, default=30, metavar='N', help='number of epochs for generating both RL teacher datasets (default: 30)') - parser.add_argument('--num-iteration', type=int, default=15, + parser.add_argument('--num-iteration', type=int, default=1, help='number of time each algorithm should be run the eval (N seeds).') args, unknown = parser.parse_known_args() if 'continual_learning_labels' in args: - assert args.continual_learning_labels[0] in CONTINUAL_LEARNING_LABELS \ - and args.continual_learning_labels[1] in CONTINUAL_LEARNING_LABELS, \ - "Please specify a valid Continual learning label to each dataset to be used for RL distillation !" - + assert args.continual_learning_labels[0] in CONTINUAL_LEARNING_LABELS and args.continual_learning_labels[1] \ + in CONTINUAL_LEARNING_LABELS, "Please specify a valid Continual learning label to each dataset to be " \ + "used for RL distillation !" + print(args.continual_learning_labels) assert os.path.exists(args.srl_config_file_one), \ "Error: cannot load \"--srl-config-file {}\", file not found!".format(args.srl_config_file_one) assert os.path.exists(args.srl_config_file_two), \ @@ -164,37 +170,37 @@ def main(): assert os.path.exists(args.log_dir_teacher_two), \ "Error: cannot load \"--srl-config-file {}\", file not found!".format(args.srl_config_file_two) - with open(args.srl_config_file_one, 'rb') as f: - model_one = yaml.load(f) + # with open(args.srl_config_file_one, 'rb') as f: + # model_one = yaml.load(f) - with open(args.srl_config_file_two, 'rb') as f: - model_two = yaml.load(f) + # with open(args.srl_config_file_two, 'rb') as f: + # model_two = yaml.load(f) teacher_pro = args.log_dir_teacher_one teacher_learn = args.log_dir_teacher_two - #The output path generate from the + # The output path generate from the teacher_pro_data = args.continual_learning_labels[0] + '/' teacher_learn_data = args.continual_learning_labels[1] + '/' merge_path = "data/on_policy_merged" print(teacher_pro_data, teacher_learn_data) episodes, policy_path = allPolicy(teacher_learn) - student_path = args.log_dir_student #"+ '/' + args.student_srl_model + "/distillation/" rewards_at_episode = {} for eps in episodes[:2]: + student_path = args.log_dir_student printRed("\n\nEvaluation at episode " + str(eps)) # generate data from Professional teacher printYellow("\nGenerating on policy for optimal teacher: " + args.continual_learning_labels[0]) - DatasetGenerator(teacher_pro, teacher_pro_data, args.continual_learning_labels[0], - num_eps=args.epochs_teacher_datasets, episode=-1) + DatasetGenerator(teacher_pro, teacher_pro_data, task_id=args.continual_learning_labels[0], + num_eps=args.epochs_teacher_datasets, episode=-1, env_name=args.env) # Generate data from learning teacher printYellow("\nGenerating on policy for optimal teacher: " + args.continual_learning_labels[1]) - DatasetGenerator(teacher_learn, teacher_learn_data, args.continual_learning_labels[1], eps, - num_eps=args.epochs_teacher_datasets) + DatasetGenerator(teacher_learn, teacher_learn_data, task_id=args.continual_learning_labels[1], episode=eps, + num_eps=args.epochs_teacher_datasets, env_name=args.env) # # merge the data mergeData('data/' + teacher_pro_data, 'data/' + teacher_learn_data, merge_path) @@ -206,17 +212,19 @@ def main(): # Train a policy with distillation on the merged teacher's datasets trainStudent(merge_path, args.continual_learning_labels[1], yaml_file=args.srl_config_file_one, log_dir=args.log_dir_student, - srl_model=args.student_srl_model, env_name='OmnirobotEnv-v0', + srl_model=args.student_srl_model, env_name=args.env, training_size=args.distillation_training_set_size, epochs=args.epochs_distillation) - latest_student_path = max([student_path + "/" + d for d in os.listdir(student_path) if os.path.isdir(student_path + "/" + d)], - key=os.path.getmtime) + student_path += args.env + '/' + args.student_srl_model + "/distillation/" + latest_student_path = max([student_path + "/" + d for d in os.listdir(student_path) + if os.path.isdir(student_path + "/" + d)], key=os.path.getmtime) + '/' rewards = {} printRed(latest_student_path) for task_label in ["-sc", "-cc"]: rewards[task_label] = [] + for seed_i in range(args.num_iteration): - printYellow("\nEvaluating student on task: " + task_label +" for seed: " + str(seed_i)) - command_line_enjoy_student = ['python','-m', 'replay.enjoy_baselines','--num-timesteps', '251', + printYellow("\nEvaluating student on task: " + task_label + " for seed: " + str(seed_i)) + command_line_enjoy_student = ['python', '-m', 'replay.enjoy_baselines', '--num-timesteps', '251', '--log-dir', latest_student_path, task_label, "--seed", str(seed_i)] ok = subprocess.check_output(command_line_enjoy_student) ok = ok.decode('utf-8') @@ -226,7 +234,7 @@ def main(): idx_after = ok.find(str_after) seed_reward = float(ok[idx_before: idx_after]) rewards[task_label].append(seed_reward) - print("rewards at eps : ", rewards) + print("rewards at eps ", eps, ": ", rewards) rewards_at_episode[eps] = rewards print("All rewards: ", rewards_at_episode) diff --git a/rl_baselines/train.py b/rl_baselines/train.py index abe4d8a53..7c6d3bd88 100644 --- a/rl_baselines/train.py +++ b/rl_baselines/train.py @@ -167,14 +167,15 @@ def callback(_locals, _globals): best_mean_reward = mean_reward printGreen("Saving new best model") ALGO.save(LOG_DIR + ALGO_NAME + "_model.pkl", _locals) - if n_episodes >0 : - if (n_episodes>=70 and n_episodes%40==0): - ALGO.save(LOG_DIR + ALGO_NAME +"_"+str(n_episodes)+ "_model.pkl", _locals) + + if n_episodes > 0: + if n_episodes >= 70 and n_episodes % 40 == 0: + ALGO.save(LOG_DIR + ALGO_NAME + "_" + str(n_episodes) + "_model.pkl", _locals) printYellow(EVAL_TASK) if CROSS_EVAL: episodeEval(LOG_DIR, EVAL_TASK) - if(n_episodes>=800 and n_episodes%200==0): + if n_episodes >= 800 and n_episodes % 200 == 0: ALGO.save(LOG_DIR + ALGO_NAME + "_" + str(n_episodes) + "_model.pkl", _locals) printYellow(EVAL_TASK) if CROSS_EVAL: @@ -253,7 +254,6 @@ def main(): parser.add_argument('--perform-cross-evaluation-cc', action='store_true', default=False, help='A cross evaluation from the latest stored model to all tasks') - # Ignore unknown args for now args, unknown = parser.parse_known_args() env_kwargs = {} @@ -296,7 +296,6 @@ def main(): MIN_EPISODES_BEFORE_SAVE = args.min_episodes_save CROSS_EVAL = args.perform_cross_evaluation_cc - if args.no_vis: viz = False @@ -304,7 +303,6 @@ def main(): algo = algo_class() ALGO = algo - # if callback frequency needs to be changed LOG_INTERVAL = algo.LOG_INTERVAL SAVE_INTERVAL = algo.SAVE_INTERVAL @@ -324,8 +322,8 @@ def main(): # Random init position for button env_kwargs["random_target"] = args.random_target - #If in simple continual scenario, then the target should be initialized randomly. - if args.simple_continual == True: + # If in simple continual scenario, then the target should be initialized randomly. + if args.simple_continual is True: env_kwargs["random_target"] = True # Allow up action @@ -382,7 +380,7 @@ def main(): hyperparams = algo.parserHyperParam(hyperparams) if args.load_rl_model_path is not None: - #use a small learning rate + # use a small learning rate print("use a small learning rate: {:f}".format(1.0e-8)) hyperparams["learning_rate"] = lambda f: f * 1.0e-8 From 4c6bdfdaad938162dd9824e63d564ec24f45f20d Mon Sep 17 00:00:00 2001 From: kalifou Date: Mon, 29 Apr 2019 23:55:35 +0200 Subject: [PATCH 089/141] Adjust episode window for checkpoints when saving a teacher --- environments/omnirobot_gym/omnirobot_env.py | 1 - rl_baselines/student_eval.py | 13 +++++++++++-- rl_baselines/train.py | 20 +++++++++++++------- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/environments/omnirobot_gym/omnirobot_env.py b/environments/omnirobot_gym/omnirobot_env.py index e842e0559..3d71c1a1f 100644 --- a/environments/omnirobot_gym/omnirobot_env.py +++ b/environments/omnirobot_gym/omnirobot_env.py @@ -308,7 +308,6 @@ def _hasEpisodeTerminated(self): self.simple_continual_target) or \ (self._env_step_counter > MAX_STEPS_CIRCULAR_TASK_SHORT_EPISODES and self.short_episodes and self.circular_continual_move): - print(self.simple_continual_target, self.circular_continual_move) return True if np.abs(self.reward - REWARD_TARGET_REACH) < 0.000001: # reach the target diff --git a/rl_baselines/student_eval.py b/rl_baselines/student_eval.py index abbd2e699..23bb6674b 100644 --- a/rl_baselines/student_eval.py +++ b/rl_baselines/student_eval.py @@ -1,5 +1,7 @@ import argparse +import datetime import glob +import json import numpy as np import os import subprocess @@ -188,7 +190,7 @@ def main(): episodes, policy_path = allPolicy(teacher_learn) rewards_at_episode = {} - for eps in episodes[:2]: + for eps in episodes: student_path = args.log_dir_student printRed("\n\nEvaluation at episode " + str(eps)) # generate data from Professional teacher @@ -218,7 +220,7 @@ def main(): latest_student_path = max([student_path + "/" + d for d in os.listdir(student_path) if os.path.isdir(student_path + "/" + d)], key=os.path.getmtime) + '/' rewards = {} - printRed(latest_student_path) + printRed("\nSaving the student at path: " + latest_student_path) for task_label in ["-sc", "-cc"]: rewards[task_label] = [] @@ -237,6 +239,13 @@ def main(): print("rewards at eps ", eps, ": ", rewards) rewards_at_episode[eps] = rewards print("All rewards: ", rewards_at_episode) + json_dict = json.dumps(rewards_at_episode) + json_dict_name = args.log_dir_student + "/reward_at_episode_" + \ + datetime.datetime.now().strftime("%y-%m-%d_%Hh%M_%S") + '.json' + f = open(json_dict_name, "w") + f.write(json_dict) + f.close() + printRed("\nSaving the evalation at path: " + json_dict_name) if __name__ == '__main__': diff --git a/rl_baselines/train.py b/rl_baselines/train.py index 7c6d3bd88..93f060bf2 100644 --- a/rl_baselines/train.py +++ b/rl_baselines/train.py @@ -36,6 +36,7 @@ EPISODE_WINDOW = 40 # For plotting moving average EVAL_TASK=['cc','sc','sqc'] CROSS_EVAL = False +EPISODE_WINDOW_DISTILLATION_WIN = 100 viz = None n_steps = 0 @@ -168,14 +169,14 @@ def callback(_locals, _globals): printGreen("Saving new best model") ALGO.save(LOG_DIR + ALGO_NAME + "_model.pkl", _locals) - if n_episodes > 0: - if n_episodes >= 70 and n_episodes % 40 == 0: - ALGO.save(LOG_DIR + ALGO_NAME + "_" + str(n_episodes) + "_model.pkl", _locals) - printYellow(EVAL_TASK) - if CROSS_EVAL: - episodeEval(LOG_DIR, EVAL_TASK) + if n_episodes >= 0: + # if n_episodes >= 70 and n_episodes % 40 == 0: + # ALGO.save(LOG_DIR + ALGO_NAME + "_" + str(n_episodes) + "_model.pkl", _locals) + # printYellow(EVAL_TASK) + # if CROSS_EVAL: + # episodeEval(LOG_DIR, EVAL_TASK) - if n_episodes >= 800 and n_episodes % 200 == 0: + if n_episodes % EPISODE_WINDOW_DISTILLATION_WIN == 0: ALGO.save(LOG_DIR + ALGO_NAME + "_" + str(n_episodes) + "_model.pkl", _locals) printYellow(EVAL_TASK) if CROSS_EVAL: @@ -253,6 +254,9 @@ def main(): help='Limit size (number of samples) of the training set (default: -1)') parser.add_argument('--perform-cross-evaluation-cc', action='store_true', default=False, help='A cross evaluation from the latest stored model to all tasks') + parser.add_argument('--eval-episode-window', type=int, default=100, metavar='N', + help='Episode window for saving each policy checkpoint for future distillation(default: 100)') + # Ignore unknown args for now args, unknown = parser.parse_known_args() @@ -295,6 +299,8 @@ def main(): EPISODE_WINDOW = args.episode_window MIN_EPISODES_BEFORE_SAVE = args.min_episodes_save CROSS_EVAL = args.perform_cross_evaluation_cc + EPISODE_WINDOW_DISTILLATION_WIN = args.eval_episode_window + print("EPISODE_WINDOW_DISTILLATION_WIN: ", EPISODE_WINDOW_DISTILLATION_WIN) if args.no_vis: viz = False From 324aa206cac3abb18a0dee29f80c55a500162272 Mon Sep 17 00:00:00 2001 From: kalifou Date: Mon, 29 Apr 2019 23:58:45 +0200 Subject: [PATCH 090/141] fix default value --- rl_baselines/train.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rl_baselines/train.py b/rl_baselines/train.py index 93f060bf2..39f3948a4 100644 --- a/rl_baselines/train.py +++ b/rl_baselines/train.py @@ -254,7 +254,7 @@ def main(): help='Limit size (number of samples) of the training set (default: -1)') parser.add_argument('--perform-cross-evaluation-cc', action='store_true', default=False, help='A cross evaluation from the latest stored model to all tasks') - parser.add_argument('--eval-episode-window', type=int, default=100, metavar='N', + parser.add_argument('--eval-episode-window', type=int, default=400, metavar='N', help='Episode window for saving each policy checkpoint for future distillation(default: 100)') From a09cb486b8abe24e7172eea4d1eb075399fbb9aa Mon Sep 17 00:00:00 2001 From: kalifou Date: Tue, 30 Apr 2019 13:32:38 +0200 Subject: [PATCH 091/141] update distillation eval --- rl_baselines/student_eval.py | 34 +++++++++++++++---- .../supervised_rl/policy_distillation.py | 2 +- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/rl_baselines/student_eval.py b/rl_baselines/student_eval.py index 23bb6674b..4a4ecaf10 100644 --- a/rl_baselines/student_eval.py +++ b/rl_baselines/student_eval.py @@ -5,6 +5,7 @@ import numpy as np import os import subprocess +import time # import yaml from environments.registry import registered_env @@ -35,7 +36,11 @@ def DatasetGenerator(teacher_path, output_name, task_id, episode=-1, env_name='O save_path = ['--save-path', "data/"] env_command = ['--env', env_name] task_command = ["-sc" if task_id == "SC" else '-cc'] - episode_command = ['--num-episode', str(num_eps)] + if task_id == 'SC': + episode_command = ['--num-episode', str(400)] + else: + episode_command = ['--num-episode', str(60)] + policy_command = ['--log-custom-policy', teacher_path] if episode == -1: eps_policy = [] @@ -43,7 +48,7 @@ def DatasetGenerator(teacher_path, output_name, task_id, episode=-1, env_name='O eps_policy = ['--episode', str(episode)] command = command_line + cpu_command + policy_command + name_command + env_command + task_command + \ - episode_command + eps_policy + save_path + ['-f'] + episode_command + eps_policy + save_path + ['-f'] + ['--seed', str(2)] if task_id == 'SC': command += ['--short-episodes'] @@ -75,6 +80,7 @@ def sortFirst(val): files_list.sort(key=sortFirst) res = np.array(files_list) + print(res) return res[:, 0], res[:, 1] @@ -155,6 +161,8 @@ def main(): help='number of epochs for generating both RL teacher datasets (default: 30)') parser.add_argument('--num-iteration', type=int, default=1, help='number of time each algorithm should be run the eval (N seeds).') + parser.add_argument('--eval-episode-window', type=int, default=400, metavar='N', + help='Episode window for saving each policy checkpoint for future distillation(default: 100)') args, unknown = parser.parse_known_args() @@ -190,14 +198,25 @@ def main(): episodes, policy_path = allPolicy(teacher_learn) rewards_at_episode = {} - for eps in episodes: + episodes_to_test = [e for e in episodes if (int(e) < 2000 and int(e) % 200 == 0) or + (int(e) > 2000 and int(e) % 1000 == 0)] + #[e for e in episodes if int(e) % args.eval_episode_window == 0] + + # generate data from Professional teacher + printYellow("\nGenerating on policy for optimal teacher: " + args.continual_learning_labels[0]) + + DatasetGenerator(teacher_pro, args.continual_learning_labels[0] + '_copy/', task_id=args.continual_learning_labels[0], + num_eps=args.epochs_teacher_datasets, episode=-1, env_name=args.env) + print("Eval on eps list: ", episodes_to_test) + for eps in episodes_to_test: student_path = args.log_dir_student printRed("\n\nEvaluation at episode " + str(eps)) - # generate data from Professional teacher - printYellow("\nGenerating on policy for optimal teacher: " + args.continual_learning_labels[0]) - DatasetGenerator(teacher_pro, teacher_pro_data, task_id=args.continual_learning_labels[0], - num_eps=args.epochs_teacher_datasets, episode=-1, env_name=args.env) + # Use a copy of the optimal teacher + ok = subprocess.call( + ['cp', '-r', 'data/' + args.continual_learning_labels[0] + '_copy/', 'data/' + teacher_pro_data]) + assert ok == 0 + time.sleep(10) # Generate data from learning teacher printYellow("\nGenerating on policy for optimal teacher: " + args.continual_learning_labels[1]) @@ -210,6 +229,7 @@ def main(): ok = subprocess.call( ['cp', '-r', merge_path, 'srl_zoo/' + merge_path]) assert ok == 0 + time.sleep(10) # Train a policy with distillation on the merged teacher's datasets trainStudent(merge_path, args.continual_learning_labels[1], yaml_file=args.srl_config_file_one, diff --git a/rl_baselines/supervised_rl/policy_distillation.py b/rl_baselines/supervised_rl/policy_distillation.py index c0f5033ec..b108bf646 100644 --- a/rl_baselines/supervised_rl/policy_distillation.py +++ b/rl_baselines/supervised_rl/policy_distillation.py @@ -24,7 +24,7 @@ CONTINUAL_LEARNING_LABELS = ['CC', 'SC', 'EC', 'SQC'] CL_LABEL_KEY = "continual_learning_label" USE_ADAPTIVE_TEMPERATURE = False -TEMPERATURES = {'CC': 0.1, 'SC': 0.1, 'EC': 0.1, 'SQC': 0.1, "default": 0.1} +TEMPERATURES = {'CC': 0.1, 'SC': 0.1, 'EC': 0.1, 'SQC': 0.1, "default": 0.01} # run with 0.1 to have good results! # 0.01 worse reward for CC, better SC From 8afa433ac265d3b95ec59e1c0a430a9c09220276 Mon Sep 17 00:00:00 2001 From: kalifou Date: Tue, 30 Apr 2019 15:05:27 +0200 Subject: [PATCH 092/141] add fix (copy merge to proper loc) --- rl_baselines/student_eval.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rl_baselines/student_eval.py b/rl_baselines/student_eval.py index 4a4ecaf10..54f29a37e 100644 --- a/rl_baselines/student_eval.py +++ b/rl_baselines/student_eval.py @@ -214,7 +214,7 @@ def main(): # Use a copy of the optimal teacher ok = subprocess.call( - ['cp', '-r', 'data/' + args.continual_learning_labels[0] + '_copy/', 'data/' + teacher_pro_data]) + ['cp', '-r', 'data/' + args.continual_learning_labels[0] + '_copy/', 'data/' + teacher_pro_data, '-f']) assert ok == 0 time.sleep(10) @@ -227,12 +227,12 @@ def main(): mergeData('data/' + teacher_pro_data, 'data/' + teacher_learn_data, merge_path) ok = subprocess.call( - ['cp', '-r', merge_path, 'srl_zoo/' + merge_path]) + ['cp', '-r', 'data/on_policy_merged/', 'srl_zoo/data/', '-f']) assert ok == 0 time.sleep(10) # Train a policy with distillation on the merged teacher's datasets - trainStudent(merge_path, args.continual_learning_labels[1], yaml_file=args.srl_config_file_one, + trainStudent('srl_zoo/' + merge_path, args.continual_learning_labels[1], yaml_file=args.srl_config_file_one, log_dir=args.log_dir_student, srl_model=args.student_srl_model, env_name=args.env, training_size=args.distillation_training_set_size, epochs=args.epochs_distillation) From 03091b1b192d73be445612e076fa1404846ea095 Mon Sep 17 00:00:00 2001 From: sun-te Date: Thu, 2 May 2019 13:46:43 +0200 Subject: [PATCH 093/141] Plot for cross evaluation --- replay/cross_eval_plot.py | 88 +++++++++++++++++++++++++++++++++++++++ replay/pipeline.py | 12 ++++-- 2 files changed, 96 insertions(+), 4 deletions(-) create mode 100644 replay/cross_eval_plot.py diff --git a/replay/cross_eval_plot.py b/replay/cross_eval_plot.py new file mode 100644 index 000000000..b8fe3f67d --- /dev/null +++ b/replay/cross_eval_plot.py @@ -0,0 +1,88 @@ +""" +Plot past experiment in visdom +""" +import argparse +import os + +import matplotlib.pyplot as plt +import numpy as np +import seaborn as sns +from matplotlib.ticker import FuncFormatter +from matplotlib import rc + +from replay.aggregate_plots import lightcolors, darkcolors, Y_LIM_SHAPED_REWARD, Y_LIM_SPARSE_REWARD, millions +from srl_zoo.utils import printGreen, printRed + +# Init seaborn +sns.set() +# Style for the title +fontstyle = {'fontname': 'DejaVu Sans', 'fontsize': 20, 'fontweight': 'bold'} +rc('font', weight='bold') + + +def crossEvalPlot(load_path, tasks,title,y_limits,timesteps=True): + res=np.load(load_path) + + y_array=res[:,:,1:] + + x=res[:,:,0][0] + + + fig = plt.figure(title) + for i in range(len(y_array)): + label = tasks[i] + y = y_array[i].T + printRed(y.shape) + print('{}: {} experiments'.format(label, len(y))) + # Compute mean for different seeds + m = np.mean(y, axis=0) + # Compute standard error + s = np.squeeze(np.asarray(np.std(y, axis=0))) + n = y.shape[0] + plt.fill_between(x, m - s / np.sqrt(n), m + s / np.sqrt(n), color=lightcolors[i % len(lightcolors)], alpha=0.5) + plt.plot(x, m, color=darkcolors[i % len(darkcolors)], label=label, linewidth=2) + + plt.xlabel('Number of Episodes') + plt.ylabel('Rewards', fontsize=20, fontweight='bold') + + plt.title(title, **fontstyle) + if(y_limits[0]!=y_limits[1]): + plt.ylim(y_limits) + + plt.legend(framealpha=0.8, frameon=True, labelspacing=0.01, loc='lower right', fontsize=18) + plt.show() + + + +#Example command: +# python -m replay.cross_eval_plot -i logs/sc2cc/OmnirobotEnv-v0/srl_combination/ppo2/19-04-29_14h59_35/episode_eval.npy +if __name__ == '__main__': + parser = argparse.ArgumentParser(description="Plot the learning curve during a training for different tasks") + parser.add_argument('-i', '--input-path', help='folder with the plots as npy files', type=str, required=True) + parser.add_argument('-t', '--title', help='Plot title', type=str, default='Learning Curve') + # parser.add_argument('--episode_window', type=int, default=40, + # help='Episode window for moving average plot (default: 40)') + # parser.add_argument('--shape-reward', action='store_true', default=False, + # help='Change the y_limit to correspond shaped reward bounds') + parser.add_argument('--y-lim', nargs=2, type=float, default=[-1, -1], help="limits for the y axis") + parser.add_argument('--truncate-x', type=int, default=-1, + help="Truncate the experiments after n ticks on the x-axis (default: -1, no truncation)") + # parser.add_argument('--timesteps', action='store_true', default=False, + # help='Plot timesteps instead of episodes') + parser.add_argument('--eval-tasks', type=str, nargs='+', default=['Circular', 'Target Reaching','Square'], + help='A cross evaluation from the latest stored model to all tasks') + args = parser.parse_args() + + + load_path = args.input_path + title = args.title + y_limits = args.y_lim + tasks = args.eval_tasks + + assert (os.path.isfile(load_path) and load_path.split('.')[-1]=='npy'), 'Please load a valid .npy file' + + + + + + crossEvalPlot(load_path, tasks, title,y_limits, timesteps=True) diff --git a/replay/pipeline.py b/replay/pipeline.py index dd842ae67..91939bdc3 100644 --- a/replay/pipeline.py +++ b/replay/pipeline.py @@ -43,13 +43,12 @@ def plotGatheredData(x_list,y_list,y_limits, timesteps,title,legends,no_display, if truncate_x > 0: min_x = min(truncate_x, min_x) x = np.array(x_list[0][:min_x]) - #To reformulize the data by the min_x for i in range(len(y_list)): y_list[i]=y_list[i][:, :min_x] y_list=np.array(y_list) - print("Min, Max rewards:", np.min(y_list), np.max(y_list)) + #print("Min, Max rewards:", np.min(y_list), np.max(y_list)) #Normalize the data between 0 and 1. @@ -110,6 +109,7 @@ def GatherExperiments(folders, algo, window=40, title="", min_num_x=-1, x_list = [] ok = False for folder in folders: + printRed("folder name:{}".format(folder)) if timesteps: x, y = loadData(folder, smooth=1, bin_size=100) if x is not None: @@ -128,7 +128,7 @@ def GatherExperiments(folders, algo, window=40, title="", min_num_x=-1, ok = True y = movingAverage(y, window) y_list.append(y) - + print(len(x)) # Truncate x x = x[len(x) - len(y):] x_list.append(x) @@ -190,10 +190,14 @@ def comparePlots(path, algo,y_limits,title="Learning Curve", x_list,y_list=[],[] for folders_srl in folders: + printGreen("Folder name {}".format(folders_srl)) x,y=GatherExperiments(folders_srl, algo, window=40, title=title, min_num_x=-1, timesteps=timesteps, output_file="") + print(len(x)) x_list.append(x) y_list.append(y) + printGreen(np.array(x_list).shape) + # printGreen('y_list shape {}'.format(np.array(y_list[1]).shape)) plotGatheredData(x_list,y_list,y_limits,timesteps,title,legends,no_display,truncate_x,normalization) @@ -243,4 +247,4 @@ def comparePlots(path, algo,y_limits,title="Learning Curve", timesteps=args.timesteps, truncate_x=args.truncate_x,normalization=args.norm) -#python -m replay.pipeline -i logs_to_plot_with_200Combination/OmnirobotEnv-v0-cc --algo ppo2 --title cc --timesteps \ No newline at end of file +#python -m replay.pipeline -i logs/OmnirobotEnv-v0 --algo ppo2 --title cc --timesteps \ No newline at end of file From eacc954b723cec482895d40c7c41a9eb59f29d54 Mon Sep 17 00:00:00 2001 From: kalifou Date: Mon, 6 May 2019 10:48:03 +0200 Subject: [PATCH 094/141] eval of student from single source --- rl_baselines/student_eval.py | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/rl_baselines/student_eval.py b/rl_baselines/student_eval.py index 54f29a37e..ab5a01183 100644 --- a/rl_baselines/student_eval.py +++ b/rl_baselines/student_eval.py @@ -164,6 +164,7 @@ def main(): parser.add_argument('--eval-episode-window', type=int, default=400, metavar='N', help='Episode window for saving each policy checkpoint for future distillation(default: 100)') + args, unknown = parser.parse_known_args() if 'continual_learning_labels' in args: @@ -173,10 +174,12 @@ def main(): print(args.continual_learning_labels) assert os.path.exists(args.srl_config_file_one), \ "Error: cannot load \"--srl-config-file {}\", file not found!".format(args.srl_config_file_one) + assert os.path.exists(args.srl_config_file_two), \ "Error: cannot load \"--srl-config-file {}\", file not found!".format(args.srl_config_file_two) - assert os.path.exists(args.log_dir_teacher_one), \ - "Error: cannot load \"--srl-config-file {}\", file not found!".format(args.log_dir_teacher_one) + if not (args.log_dir_teacher_one == "None"): + assert os.path.exists(args.log_dir_teacher_one), \ + "Error: cannot load \"--srl-config-file {}\", file not found!".format(args.log_dir_teacher_one) assert os.path.exists(args.log_dir_teacher_two), \ "Error: cannot load \"--srl-config-file {}\", file not found!".format(args.srl_config_file_two) @@ -205,29 +208,36 @@ def main(): # generate data from Professional teacher printYellow("\nGenerating on policy for optimal teacher: " + args.continual_learning_labels[0]) - DatasetGenerator(teacher_pro, args.continual_learning_labels[0] + '_copy/', task_id=args.continual_learning_labels[0], - num_eps=args.epochs_teacher_datasets, episode=-1, env_name=args.env) + if not (args.log_dir_teacher_one == "None"): + DatasetGenerator(teacher_pro, args.continual_learning_labels[0] + '_copy/', task_id=args.continual_learning_labels[0], + num_eps=args.epochs_teacher_datasets, episode=-1, env_name=args.env) print("Eval on eps list: ", episodes_to_test) for eps in episodes_to_test: student_path = args.log_dir_student printRed("\n\nEvaluation at episode " + str(eps)) - # Use a copy of the optimal teacher - ok = subprocess.call( - ['cp', '-r', 'data/' + args.continual_learning_labels[0] + '_copy/', 'data/' + teacher_pro_data, '-f']) - assert ok == 0 - time.sleep(10) + if not (args.log_dir_teacher_one == "None"): + # Use a copy of the optimal teacher + ok = subprocess.call( + ['cp', '-r', 'data/' + args.continual_learning_labels[0] + '_copy/', 'data/' + teacher_pro_data, '-f']) + assert ok == 0 + time.sleep(10) # Generate data from learning teacher printYellow("\nGenerating on policy for optimal teacher: " + args.continual_learning_labels[1]) DatasetGenerator(teacher_learn, teacher_learn_data, task_id=args.continual_learning_labels[1], episode=eps, num_eps=args.epochs_teacher_datasets, env_name=args.env) - # # merge the data - mergeData('data/' + teacher_pro_data, 'data/' + teacher_learn_data, merge_path) + if args.log_dir_teacher_one == "None": + merge_path = 'data/' + teacher_learn_data + ok = subprocess.call( + ['cp', '-r', merge_path, 'srl_zoo/data/', '-f']) + else: + # merge the data + mergeData('data/' + teacher_pro_data, 'data/' + teacher_learn_data, merge_path) - ok = subprocess.call( - ['cp', '-r', 'data/on_policy_merged/', 'srl_zoo/data/', '-f']) + ok = subprocess.call( + ['cp', '-r', 'data/on_policy_merged/', 'srl_zoo/data/', '-f']) assert ok == 0 time.sleep(10) From 1e2ec910b86b630d18f895e266c98295da15fd58 Mon Sep 17 00:00:00 2001 From: sun-te Date: Mon, 6 May 2019 10:56:49 +0200 Subject: [PATCH 095/141] corss eval after training --- replay/enjoy_baselines.py | 9 +- rl_baselines/cross_eval.py | 162 ++++++++++++++++++++++++--- rl_baselines/cross_eval_utils.py | 16 +-- rl_baselines/evaluation/eval_post.py | 134 ++++++++++++++++++++++ 4 files changed, 300 insertions(+), 21 deletions(-) create mode 100644 rl_baselines/evaluation/eval_post.py diff --git a/replay/enjoy_baselines.py b/replay/enjoy_baselines.py index 58880bcb3..b4ff1149f 100644 --- a/replay/enjoy_baselines.py +++ b/replay/enjoy_baselines.py @@ -91,7 +91,13 @@ def loadConfigAndSetup(load_args): raise ValueError(algo_name + " is not supported for replay") printGreen("\n" + algo_name + "\n") - load_path = "{}/{}_model.pkl".format(load_args.log_dir, algo_name) + + if(load_args.log_dir[-3:]!='pkl'): + load_path = "{}/{}_model.pkl".format(load_args.log_dir, algo_name) + else: + load_path = load_args.log_dir + load_args.log_dir = os.path.dirname(load_path)+'/' + env_globals = json.load(open(load_args.log_dir + "env_globals.json", 'r')) train_args = json.load(open(load_args.log_dir + "args.json", 'r')) @@ -185,6 +191,7 @@ def main(): # createTensorflowSession() printYellow("Compiling Policy function....") + printYellow(load_path) method = algo_class.load(load_path, args=algo_args) dones = [False for _ in range(load_args.num_cpu)] diff --git a/rl_baselines/cross_eval.py b/rl_baselines/cross_eval.py index 62d11d349..406b04c83 100644 --- a/rl_baselines/cross_eval.py +++ b/rl_baselines/cross_eval.py @@ -2,24 +2,22 @@ import subprocess import numpy as np import pickle +import argparse +import os -# log_dir = 'logs/OmnirobotEnv-v0/srl_combination/ppo2/19-04-24_10h36_52/' -# tasks=['cc'] -# episodeEval(log_dir,tasks,save_name='episode_eval.npy',num_timesteps=300) -# for i in range(10): -# time.sleep(1) -# print(i) - -#episodeEval(log_dir,tasks,save_name='episode_eval.npy',num_timesteps=300) +from rl_baselines.student_eval import allPolicy +from srl_zoo.utils import printRed, printGreen +from rl_baselines.cross_eval_utils import EnvsKwargs, loadConfigAndSetup, policyEval,createEnv def dict2array(tasks,data): res=[] - + print(data) for t in tasks: if(t=='sc'): max_reward=250 else: max_reward=1850 + data[t]=data[t].astype(float) data[t][:,1:]=data[t][:,1:]/max_reward res.append(data[t]) res=np.array(res) @@ -27,7 +25,7 @@ def dict2array(tasks,data): def episodeEval(log_dir, tasks,num_timesteps=1000,num_cpu=1): for t in tasks: - eval_args=['--log-dir', log_dir, '--num-timesteps', str(num_timesteps), '--num-cpu',str(num_cpu)] + eval_args=['--log-dir', log_dir, '--num-timesteps', str(num_timesteps), '--num-cpu',str(5)] task_args=['--task',t] subprocess.call(['python', '-m', 'rl_baselines.cross_eval_utils']+eval_args+task_args) @@ -40,9 +38,147 @@ def episodeEval(log_dir, tasks,num_timesteps=1000,num_cpu=1): file_name=log_dir+'episode_eval.npy' np.save(file_name, eval_reward) + + + +def policyCrossEval(log_dir,task,episode,model_path, num_timesteps=2000,num_cpu=1): + train_args, algo_name, algo_class, srl_model_path, env_kwargs = loadConfigAndSetup(log_dir) + env_kwargs = EnvsKwargs(task, env_kwargs) + + OK = True + if (not OK): + # no latest model saved yet + return None, False + else: + pass + printGreen( + "Evaluation from the model saved at: {}, with evaluation time steps: {}".format(model_path, num_timesteps)) + + log_dir, environment, algo_args = createEnv(log_dir, train_args, algo_name, algo_class, env_kwargs, num_cpu=num_cpu) + + reward = policyEval(environment, model_path, log_dir, algo_class, algo_args, num_timesteps, num_cpu) + + # Just a trick to save the episode number of the reward,but need a little bit more space to store + reward = np.append(episode, reward) + return reward, True + + +# +# +# +# def saveReward(log_dir,reward, task,save_name='episode_eval.pkl'): +# +# +# file_name=log_dir+save_name +# +# #can be changed accordingly +# if(os.path.isfile(file_name)): +# +# +# with open(file_name, 'rb') as f: +# eval_reward= pickle.load(f) +# +# if (task in eval_reward.keys()): +# episodes = np.unique(eval_reward[task][:, 0]) +# #The fisrt dimension of reward is the episode +# current_episode =reward[0] +# #Check if the latest episodes policy is already saved +# if (current_episode not in episodes): +# eval_reward[task]=np.append(eval_reward[task],[reward],axis=0) +# with open(file_name, 'wb') as f: +# pickle.dump(eval_reward, f, pickle.HIGHEST_PROTOCOL) +# else:# The task is not in the file yet +# eval_reward[task] =reward[None,:] +# with open(file_name, 'wb') as f: +# pickle.dump(eval_reward, f, pickle.HIGHEST_PROTOCOL) +# else: #There is still not a episodes rewards evaluation registered +# +# eval_reward = {} +# +# eval_reward[task]=reward[None,:] +# with open(file_name, 'wb') as f: +# pickle.dump(eval_reward, f, pickle.HIGHEST_PROTOCOL) +# +# return + +#python -m rl_baselines.cross_eval --log-dir logs/sc2cc/OmnirobotEnv-v0/srl_combination/ppo2/19-05-03_11h35_10/ --num-iteration 5 + if __name__ == '__main__': + parser = argparse.ArgumentParser(description="Evaluation after training") + parser.add_argument('--log-dir',type=str, default='' + ,help='RL algo to use') + parser.add_argument('--num-iteration', type=int, default=5, + help='number of time each algorithm should be run the eval (N seeds).') + args, unknown = parser.parse_known_args() + + + log_dir = args.log_dir + #log_dir = 'logs/sc2cc/OmnirobotEnv-v0/srl_combination/ppo2/19-05-03_11h35_10/' + + tasks=['sc'] + episodes, policy_paths = allPolicy(log_dir) + printRed(len(episodes)) + + # + # + # episode_eval=[] + # + # for k in range(120): + # for i in range(10): + # print("Episode: {}".format(episodes[k])) + # for task_label in tasks: + # for seed_i in range(args.num_iteration): + # printRed(policy_paths[k]) + # command=['python', '-m', 'rl_baselines.evaluation.eval_post', '--log-dir',log_dir, + # '--task-label', task_label, '--episode', str(episodes[k]), '--policy-path' , policy_paths[k], + # '--seed', str(seed_i) + # ] + # subprocess.call(command) + # + # file_name = log_dir + 'episode_eval.pkl' + # with open(file_name, 'rb') as f: + # eval_reward = pickle.load(f) + # + # # Trasfer the data from dict into a numpy array and save + # data = eval_reward + # for key in data.keys(): + # data[key]=np.array(data[key][1]) + # printRed(data) + # eval_reward = dict2array(tasks, data) + # file_name = log_dir + 'episode_eval.npy' + # np.save(file_name, eval_reward) + +####################################################### + + + task_label='cc' + + rewards = {} + rewards['episode']=episodes[:186] + rewards['policy']=policy_paths[:186] + rewards[task_label] = [] + + + for k in range(186): + model_path=policy_paths[k] + + local_reward = [int(episodes[k])] + for seed_i in range(args.num_iteration): + + command_line_enjoy_student = ['python', '-m', 'replay.enjoy_baselines', '--num-timesteps', '251', + '--log-dir', model_path, "--seed", str(seed_i)] + ok = subprocess.check_output(command_line_enjoy_student) + ok = ok.decode('utf-8') + str_before = "Mean reward: " + str_after = "\npybullet" + idx_before = ok.find(str_before) + len(str_before) + idx_after = ok.find(str_after) + seed_reward = float(ok[idx_before: idx_after]) + local_reward.append(seed_reward) + print(local_reward) + printRed("current rewards {} at episode {}".format(np.mean(local_reward), episodes[k])) + rewards[task_label].append(local_reward) + with open(args.log_dir+'/eval.pkl', 'wb') as f: + pickle.dump(rewards, f, pickle.HIGHEST_PROTOCOL) - log_dir = 'logs_copy/cc2sc/OmnirobotEnv-v0/srl_combination/ppo2/19-04-26_20h17_37/' - tasks=['cc','sc','sqc'] - episodeEval(log_dir, tasks, num_timesteps=800, num_cpu=1) diff --git a/rl_baselines/cross_eval_utils.py b/rl_baselines/cross_eval_utils.py index f2499504a..0a42a6069 100644 --- a/rl_baselines/cross_eval_utils.py +++ b/rl_baselines/cross_eval_utils.py @@ -8,12 +8,17 @@ import numpy as np import tensorflow as tf import pickle +from datetime import datetime + + from rl_baselines.utils import WrapFrameStack,computeMeanReward,printGreen from srl_zoo.utils import printRed from stable_baselines.common import set_global_seeds from rl_baselines import AlgoType from rl_baselines.registry import registered_rl -from datetime import datetime + + + def loadConfigAndSetup(log_dir): """ @@ -132,7 +137,7 @@ def createEnv( model_dir,train_args, algo_name, algo_class, env_kwargs, log_dir= -def policyEval(envs,model_path,log_dir,algo_class,algo_args,num_timesteps=1000,num_cpu=1): +def policyEval(envs,model_path,log_dir,algo_class,algo_args,num_timesteps=251,num_cpu=1): """ evaluation for the policy in the given envs :param envs: the environment we want to evaluate @@ -163,7 +168,6 @@ def policyEval(envs,model_path,log_dir,algo_class,algo_args,num_timesteps=1000,n dones = [False for _ in range(num_cpu)] for i in range(num_timesteps): - set_global_seeds(i) actions=method.getAction(obs,dones) obs, rewards, dones, _ = envs.step(actions) if using_custom_vec_env: @@ -217,7 +221,7 @@ def sortFirst(val): #No model saved yet return 0,'',False -def policyCrossEval(log_dir,task,num_timesteps=2000,num_cpu=1): +def policyCrossEval(log_dir,task,num_timesteps=2000,num_cpu=1,seed=0): train_args, algo_name, algo_class, srl_model_path, env_kwargs = loadConfigAndSetup(log_dir) episode, model_path, OK = latestPolicy(log_dir, algo_name) env_kwargs = EnvsKwargs(task, env_kwargs) @@ -231,7 +235,7 @@ def policyCrossEval(log_dir,task,num_timesteps=2000,num_cpu=1): printGreen( "Evaluation from the model saved at: {}, with evaluation time steps: {}".format(model_path, num_timesteps)) - log_dir, environment, algo_args = createEnv(log_dir, train_args, algo_name, algo_class, env_kwargs, num_cpu=num_cpu) + log_dir, environment, algo_args = createEnv(log_dir, train_args, algo_name, algo_class, env_kwargs, num_cpu=num_cpu,seed=seed) reward = policyEval(environment, model_path, log_dir, algo_class, algo_args, num_timesteps, num_cpu) @@ -258,8 +262,6 @@ def episodeEval(log_dir,task,save_name='episode_eval.pkl',num_timesteps=800,num_ #can be changed accordingly - - if(os.path.isfile(file_name)): #eval_reward=np.load(file_name) diff --git a/rl_baselines/evaluation/eval_post.py b/rl_baselines/evaluation/eval_post.py new file mode 100644 index 000000000..6788cb0a4 --- /dev/null +++ b/rl_baselines/evaluation/eval_post.py @@ -0,0 +1,134 @@ + +import subprocess +import numpy as np +import pickle +import argparse +import os + +from rl_baselines.student_eval import allPolicy +from srl_zoo.utils import printRed, printGreen +from rl_baselines.cross_eval_utils import EnvsKwargs, loadConfigAndSetup, policyEval,createEnv + +def dict2array(tasks,data): + res=[] + + for t in tasks: + if(t=='sc'): + max_reward=250 + else: + max_reward=1850 + + data[t][:,1:]=data[t][:,1:]/max_reward + res.append(data[t]) + res=np.array(res) + return res + +def episodeEval(log_dir, tasks,num_timesteps=1000): + for t in tasks: + eval_args=['--log-dir', log_dir, '--num-timesteps', str(num_timesteps), '--num-cpu',str(5)] + task_args=['--task',t] + + subprocess.call(['python', '-m', 'rl_baselines.cross_eval_utils']+eval_args+task_args) + file_name=log_dir+'episode_eval.pkl' + with open(file_name, 'rb') as f: + eval_reward = pickle.load(f) + + #Trasfer the data from dict into a numpy array and save + eval_reward=dict2array(tasks,eval_reward) + file_name=log_dir+'episode_eval.npy' + np.save(file_name, eval_reward) + + + + +def policyCrossEval(log_dir,task,episode,model_path, num_timesteps=2000,num_cpu=1,seed=0): + train_args, algo_name, algo_class, srl_model_path, env_kwargs = loadConfigAndSetup(log_dir) + env_kwargs = EnvsKwargs(task, env_kwargs) + + OK = True + if (not OK): + # no latest model saved yet + return None, False + else: + pass + printGreen( + "Evaluation from the model saved at: {}, with evaluation time steps: {}".format(model_path, num_timesteps)) + + log_dir, environment, algo_args = createEnv(log_dir, train_args, algo_name, algo_class, env_kwargs, num_cpu=num_cpu,seed=seed) + + reward = policyEval(environment, model_path, log_dir, algo_class, algo_args, num_timesteps, num_cpu) + + # Just a trick to save the episode number of the reward,but need a little bit more space to store + reward = np.append(episode, reward) + return reward, True + + + + + +def saveReward(log_dir,reward, task,save_name='episode_eval.pkl'): + reward = reward.astype(float) + + file_name=log_dir+save_name + + #can be changed accordingly + if(os.path.isfile(file_name)): + + + with open(file_name, 'rb') as f: + eval_reward= pickle.load(f) + + if (task in eval_reward.keys()): + episodes = eval_reward[task][0] + #The fisrt dimension of reward is the episode + current_episode =reward[0] + #Check if the latest episodes policy is already saved + if (current_episode not in episodes): + # # eval_reward[task]=np.append(eval_reward[task],[reward],axis=0) + eval_reward[task][0].append(reward[0]) + eval_reward[task][1].append(reward.tolist()) + else: + index = episodes.index(current_episode) + eval_reward[task][1][index].extend(reward[1:]) + with open(file_name, 'wb') as f: + pickle.dump(eval_reward, f, pickle.HIGHEST_PROTOCOL) + else:# The task is not in the file yet + eval_reward[task]=([reward[0]],[reward.tolist()]) + with open(file_name, 'wb') as f: + pickle.dump(eval_reward, f, pickle.HIGHEST_PROTOCOL) + else: #There is still not a episodes rewards evaluation registered + + eval_reward = {} + eval_reward[task]=([reward[0]],[reward.tolist()]) + with open(file_name, 'wb') as f: + pickle.dump(eval_reward, f, pickle.HIGHEST_PROTOCOL) + + return + + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description="Evaluation after training") + parser.add_argument('--log-dir',type=str, default='' + ,help='RL algo to use') + parser.add_argument('--task-label', type=str, default='', + help='task to evaluate') + parser.add_argument('--episode', type=str, default='', + help='evaluation for the policy saved at this episode') + parser.add_argument('--policy-path', type=str, default='', + help='policy path') + parser.add_argument('--seed', type=int, default=0, + help='policy path') + args, unknown = parser.parse_known_args() + + + + + reward, _ = policyCrossEval(args.log_dir, args.task_label, episode=args.episode, model_path=args.policy_path, + num_timesteps=251,seed=args.seed) + saveReward(args.log_dir, reward, args.task_label, save_name='episode_eval.pkl') + + + + + From bca62007c721066bd46de8eded6f76c6fe9d30d7 Mon Sep 17 00:00:00 2001 From: sun-te Date: Tue, 7 May 2019 14:43:21 +0200 Subject: [PATCH 096/141] comment and evaluation bugs fixed --- replay/cross_eval_plot.py | 58 +++++- rl_baselines/base_classes.py | 22 +-- rl_baselines/cross_eval.py | 178 ++++++++---------- .../{ => evaluation}/cross_eval_utils.py | 27 +-- rl_baselines/student_eval.py | 31 ++- rl_baselines/train.py | 34 ++-- rl_baselines/visualize.py | 5 +- 7 files changed, 190 insertions(+), 165 deletions(-) rename rl_baselines/{ => evaluation}/cross_eval_utils.py (96%) diff --git a/replay/cross_eval_plot.py b/replay/cross_eval_plot.py index b8fe3f67d..61722a9a2 100644 --- a/replay/cross_eval_plot.py +++ b/replay/cross_eval_plot.py @@ -7,12 +7,11 @@ import matplotlib.pyplot as plt import numpy as np import seaborn as sns -from matplotlib.ticker import FuncFormatter from matplotlib import rc from replay.aggregate_plots import lightcolors, darkcolors, Y_LIM_SHAPED_REWARD, Y_LIM_SPARSE_REWARD, millions from srl_zoo.utils import printGreen, printRed - +from rl_baselines.visualize import smoothRewardCurve # Init seaborn sns.set() # Style for the title @@ -20,7 +19,15 @@ rc('font', weight='bold') -def crossEvalPlot(load_path, tasks,title,y_limits,timesteps=True): +def crossEvalPlot(load_path, tasks,title,y_limits): + """ + Plot with standard deviation, the reward curve + :param load_path: + :param tasks: + :param title: + :param y_limits: + :return: + """ res=np.load(load_path) y_array=res[:,:,1:] @@ -54,6 +61,38 @@ def crossEvalPlot(load_path, tasks,title,y_limits,timesteps=True): +def smoothPlot(load_path, tasks,title,y_limits): + """ + To plot a smoother curve with some tricks of conv1D + :param load_path: (str) + :param tasks: (list) ['sc','cc'] + :param title: (str) + :param y_limits: (list) if not equal, use it as y_limits + :return: + """ + res = np.load(load_path) + y = np.mean(res[:, :, 1:], axis=2) + x = res[:, :, 0][0] + print(y.shape, x.shape) + fig=plt.figure(title) + for i in range(len(y)): + label = tasks[i] + tmp_x,tmp_y=smoothRewardCurve(x,y[i],conv_len=4) + print(tmp_x.shape,tmp_y.shape) + plt.plot(tmp_x, tmp_y, color=darkcolors[i % len(darkcolors)], label=label, linewidth=2) + plt.xlabel('Number of Episodes') + plt.ylabel('Rewards', fontsize=20, fontweight='bold') + + plt.title(title, **fontstyle) + if (y_limits[0] != y_limits[1]): + plt.ylim(y_limits) + + plt.legend(framealpha=0.8, frameon=True, labelspacing=0.01, loc='lower right', fontsize=18) + plt.show() + + + + #Example command: # python -m replay.cross_eval_plot -i logs/sc2cc/OmnirobotEnv-v0/srl_combination/ppo2/19-04-29_14h59_35/episode_eval.npy if __name__ == '__main__': @@ -67,10 +106,12 @@ def crossEvalPlot(load_path, tasks,title,y_limits,timesteps=True): parser.add_argument('--y-lim', nargs=2, type=float, default=[-1, -1], help="limits for the y axis") parser.add_argument('--truncate-x', type=int, default=-1, help="Truncate the experiments after n ticks on the x-axis (default: -1, no truncation)") - # parser.add_argument('--timesteps', action='store_true', default=False, + # parser.add_argument('--timesteps', # help='Plot timesteps instead of episodes') parser.add_argument('--eval-tasks', type=str, nargs='+', default=['Circular', 'Target Reaching','Square'], help='A cross evaluation from the latest stored model to all tasks') + parser.add_argument('-s','--smooth', action='store_true', default=False, + help='Plot with a smooth mode') args = parser.parse_args() @@ -81,8 +122,7 @@ def crossEvalPlot(load_path, tasks,title,y_limits,timesteps=True): assert (os.path.isfile(load_path) and load_path.split('.')[-1]=='npy'), 'Please load a valid .npy file' - - - - - crossEvalPlot(load_path, tasks, title,y_limits, timesteps=True) + if(args.smooth): + smoothPlot(load_path,tasks,title,y_limits) + else: + crossEvalPlot(load_path, tasks, title,y_limits) diff --git a/rl_baselines/base_classes.py b/rl_baselines/base_classes.py index 1ad80e037..97a1c2be7 100644 --- a/rl_baselines/base_classes.py +++ b/rl_baselines/base_classes.py @@ -124,23 +124,8 @@ def save(self, save_path, _locals=None): :param save_path: (str) :param _locals: (dict) local variable from callback, if present """ - # assert self.model is not None, "Error: must train or load model before use" - # model_save_name = self.name + ".pkl" - # if os.path.basename(save_path) == model_save_name: - # model_save_name = self.name + "_model.pkl" - # - # self.model.save(os.path.dirname(save_path) + "/" + model_save_name) - # save_param = { - # "ob_space": self.ob_space, - # "ac_space": self.ac_space, - # "policy": self.policy - # } - # with open(save_path, "wb") as f: - # pickle.dump(save_param, f) + assert self.model is not None, "Error: must train or load model before use" - # model_save_name = self.name + ".pkl" - # if os.path.basename(save_path) == model_save_name: - # model_save_name = self.name + "_model.pkl" episode = os.path.basename(save_path).split('_')[-2] if(bool(re.search('[a-z]', episode))): @@ -244,7 +229,10 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): :param env_kwargs: (dict) The extra arguments for the environment :param train_kwargs: (dict) The list of all training agruments (used in hyperparameter search) """ - envs = self.makeEnv(args, env_kwargs=env_kwargs) + if self.load_rl_model_path is not None: + load_path_normalise = os.path.dirname(self.load_rl_model_path) + + envs = self.makeEnv(args, env_kwargs=env_kwargs,load_path_normalise=load_path_normalise) if train_kwargs is None: train_kwargs = {} diff --git a/rl_baselines/cross_eval.py b/rl_baselines/cross_eval.py index 406b04c83..515b1fec8 100644 --- a/rl_baselines/cross_eval.py +++ b/rl_baselines/cross_eval.py @@ -5,11 +5,19 @@ import argparse import os -from rl_baselines.student_eval import allPolicy +from rl_baselines.student_eval import allPolicyFiles from srl_zoo.utils import printRed, printGreen -from rl_baselines.cross_eval_utils import EnvsKwargs, loadConfigAndSetup, policyEval,createEnv +from rl_baselines.evaluation.cross_eval_utils import EnvsKwargs, loadConfigAndSetup, policyEval,createEnv +from shutil import copyfile + def dict2array(tasks,data): + """ + Convert the dictionary data set into a plotable array + :param tasks: ['sc','cc'], the task key in the dictionary + :param data: the dict itself + :return: + """ res=[] print(data) for t in tasks: @@ -32,16 +40,24 @@ def episodeEval(log_dir, tasks,num_timesteps=1000,num_cpu=1): file_name=log_dir+'episode_eval.pkl' with open(file_name, 'rb') as f: eval_reward = pickle.load(f) - #Trasfer the data from dict into a numpy array and save eval_reward=dict2array(tasks,eval_reward) file_name=log_dir+'episode_eval.npy' np.save(file_name, eval_reward) - - def policyCrossEval(log_dir,task,episode,model_path, num_timesteps=2000,num_cpu=1): + """ + To do a cross evaluation for a certain policy for different tasks + A version of real time evaluation but with some bugs to fix + :param log_dir: + :param task: + :param episode: + :param model_path: + :param num_timesteps: How many timesteps to evaluate the policy + :param num_cpu: + :return: + """ train_args, algo_name, algo_class, srl_model_path, env_kwargs = loadConfigAndSetup(log_dir) env_kwargs = EnvsKwargs(task, env_kwargs) @@ -63,44 +79,7 @@ def policyCrossEval(log_dir,task,episode,model_path, num_timesteps=2000,num_cpu= return reward, True -# -# -# -# def saveReward(log_dir,reward, task,save_name='episode_eval.pkl'): -# -# -# file_name=log_dir+save_name -# -# #can be changed accordingly -# if(os.path.isfile(file_name)): -# -# -# with open(file_name, 'rb') as f: -# eval_reward= pickle.load(f) -# -# if (task in eval_reward.keys()): -# episodes = np.unique(eval_reward[task][:, 0]) -# #The fisrt dimension of reward is the episode -# current_episode =reward[0] -# #Check if the latest episodes policy is already saved -# if (current_episode not in episodes): -# eval_reward[task]=np.append(eval_reward[task],[reward],axis=0) -# with open(file_name, 'wb') as f: -# pickle.dump(eval_reward, f, pickle.HIGHEST_PROTOCOL) -# else:# The task is not in the file yet -# eval_reward[task] =reward[None,:] -# with open(file_name, 'wb') as f: -# pickle.dump(eval_reward, f, pickle.HIGHEST_PROTOCOL) -# else: #There is still not a episodes rewards evaluation registered -# -# eval_reward = {} -# -# eval_reward[task]=reward[None,:] -# with open(file_name, 'wb') as f: -# pickle.dump(eval_reward, f, pickle.HIGHEST_PROTOCOL) -# -# return - +#Example commands: #python -m rl_baselines.cross_eval --log-dir logs/sc2cc/OmnirobotEnv-v0/srl_combination/ppo2/19-05-03_11h35_10/ --num-iteration 5 if __name__ == '__main__': @@ -116,68 +95,61 @@ def policyCrossEval(log_dir,task,episode,model_path, num_timesteps=2000,num_cpu= #log_dir = 'logs/sc2cc/OmnirobotEnv-v0/srl_combination/ppo2/19-05-03_11h35_10/' tasks=['sc'] - episodes, policy_paths = allPolicy(log_dir) - printRed(len(episodes)) - - # - # - # episode_eval=[] - # - # for k in range(120): - # for i in range(10): - # print("Episode: {}".format(episodes[k])) - # for task_label in tasks: - # for seed_i in range(args.num_iteration): - # printRed(policy_paths[k]) - # command=['python', '-m', 'rl_baselines.evaluation.eval_post', '--log-dir',log_dir, - # '--task-label', task_label, '--episode', str(episodes[k]), '--policy-path' , policy_paths[k], - # '--seed', str(seed_i) - # ] - # subprocess.call(command) - # - # file_name = log_dir + 'episode_eval.pkl' - # with open(file_name, 'rb') as f: - # eval_reward = pickle.load(f) - # - # # Trasfer the data from dict into a numpy array and save - # data = eval_reward - # for key in data.keys(): - # data[key]=np.array(data[key][1]) - # printRed(data) - # eval_reward = dict2array(tasks, data) - # file_name = log_dir + 'episode_eval.npy' - # np.save(file_name, eval_reward) - -####################################################### - - - task_label='cc' - - rewards = {} - rewards['episode']=episodes[:186] - rewards['policy']=policy_paths[:186] - rewards[task_label] = [] - - - for k in range(186): + episodes, policy_paths = allPolicyFiles(log_dir) + index_to_begin =0 + + #To verify if the episodes have been evaluated before + if(os.path.isfile(args.log_dir+'/eval.pkl')): + with open(args.log_dir+'/eval.pkl', "rb") as file: + rewards = pickle.load(file) + for e in range(len(episodes)): + if(episodes[e] not in rewards['episode']): + break; + index_to_begin = e + print(index_to_begin) + else: + task_labels = ['cc', 'sc'] + rewards = {} + rewards['episode'] = episodes + rewards['policy'] = policy_paths + + printRed(episodes[index_to_begin:]) + for policy_path in policy_paths[index_to_begin:]: + copyfile(log_dir+'/args.json', policy_path+'/args.json') + copyfile(log_dir + '/env_globals.json', policy_path + '/env_globals.json') + + + + + for t in ['cc','sc']: + rewards[t]=[] + + for k in range(len(episodes)): model_path=policy_paths[k] - local_reward = [int(episodes[k])] - for seed_i in range(args.num_iteration): - - command_line_enjoy_student = ['python', '-m', 'replay.enjoy_baselines', '--num-timesteps', '251', - '--log-dir', model_path, "--seed", str(seed_i)] - ok = subprocess.check_output(command_line_enjoy_student) - ok = ok.decode('utf-8') - str_before = "Mean reward: " - str_after = "\npybullet" - idx_before = ok.find(str_before) + len(str_before) - idx_after = ok.find(str_after) - seed_reward = float(ok[idx_before: idx_after]) - local_reward.append(seed_reward) - print(local_reward) - printRed("current rewards {} at episode {}".format(np.mean(local_reward), episodes[k])) - rewards[task_label].append(local_reward) + for task_label in ["-sc", "-cc"]: + + local_reward = [int(episodes[k])] + + for seed_i in range(args.num_iteration): + + command_line_enjoy_student = ['python', '-m', 'replay.enjoy_baselines', '--num-timesteps', '251', + '--log-dir', model_path, task_label, "--seed", str(seed_i)] + ok = subprocess.check_output(command_line_enjoy_student) + ok = ok.decode('utf-8') + str_before = "Mean reward: " + str_after = "\npybullet" + idx_before = ok.find(str_before) + len(str_before) + idx_after = ok.find(str_after) + seed_reward = float(ok[idx_before: idx_after]) + + local_reward.append(seed_reward) + printGreen(local_reward) + printRed("current rewards {} at episode {} with random seed: {} for task {}".format( + np.mean(seed_reward), episodes[k], seed_i, task_label)) + + rewards[task_label[1:]].append(local_reward) + with open(args.log_dir+'/eval.pkl', 'wb') as f: pickle.dump(rewards, f, pickle.HIGHEST_PROTOCOL) diff --git a/rl_baselines/cross_eval_utils.py b/rl_baselines/evaluation/cross_eval_utils.py similarity index 96% rename from rl_baselines/cross_eval_utils.py rename to rl_baselines/evaluation/cross_eval_utils.py index 0a42a6069..b57856cb3 100644 --- a/rl_baselines/cross_eval_utils.py +++ b/rl_baselines/evaluation/cross_eval_utils.py @@ -1,7 +1,4 @@ -""" -Modified version of https://github.com/ikostrikov/pytorch-a2c-ppo-acktr/blob/master/visualize.py -Script used to send plot data to visdom -""" + import glob import os import json @@ -23,8 +20,9 @@ def loadConfigAndSetup(log_dir): """ load training variable from a pre-trained model - :param log_dir: the path where the model is located - :return: + :param log_dir: the path where the model is located, + example: logs/sc2cc/OmnirobotEnv-v0/srl_combination/ppo2/19-05-07_11h32_39 + :return: train_args, algo_name, algo_class(stable_baselines.PPO2), srl_model_path, env_kwargs """ algo_name = "" for algo in list(registered_rl.keys()): @@ -84,7 +82,6 @@ def EnvsKwargs(task,env_kwargs): :return: a list of env_kwargs that has the same length as tasks """ t=task - tmp=env_kwargs.copy() tmp['simple_continual_target'] = False tmp['circular_continual_move'] = False @@ -149,8 +146,6 @@ def policyEval(envs,model_path,log_dir,algo_class,algo_args,num_timesteps=251,nu :param num_cpu: :return: """ - - tf.reset_default_graph() method = algo_class.load(model_path, args=algo_args) @@ -192,11 +187,6 @@ def policyEval(envs,model_path,log_dir,algo_class,algo_args,num_timesteps=251,nu envs.close() return episode_reward - - - - - def latestPolicy(log_dir,algo_name): """ Get the latest saved model from a file @@ -260,8 +250,6 @@ def episodeEval(log_dir,task,save_name='episode_eval.pkl',num_timesteps=800,num_ file_name=log_dir+save_name #can be changed accordingly - - if(os.path.isfile(file_name)): #eval_reward=np.load(file_name) @@ -300,12 +288,8 @@ def episodeEval(log_dir,task,save_name='episode_eval.pkl',num_timesteps=800,num_ if __name__ == '__main__': + import argparse - # - # log_dir ='logs/OmnirobotEnv-v0/ground_truth/ppo2/19-04-23_17h44_32/' # sc - # - # log_dir = 'logs/OmnirobotEnv-v0/ground_truth/ppo2/19-04-23_17h35_17/' # cc - # cc parser = argparse.ArgumentParser(description="several runtime for cross evaluation", epilog='') @@ -315,7 +299,6 @@ def episodeEval(log_dir,task,save_name='episode_eval.pkl',num_timesteps=800,num_ parser.add_argument('--num-cpu', type=int, default=1, help='number of cpu to perform the evaluation') args,_= parser.parse_known_args() - #tasks=['cc'] task=args.task log_dir=args.log_dir episodeEval(log_dir,task,save_name='episode_eval.pkl',num_timesteps=args.num_timesteps,num_cpu=args.num_cpu) diff --git a/rl_baselines/student_eval.py b/rl_baselines/student_eval.py index ab5a01183..46bb9f371 100644 --- a/rl_baselines/student_eval.py +++ b/rl_baselines/student_eval.py @@ -9,7 +9,7 @@ # import yaml from environments.registry import registered_env -from rl_baselines.cross_eval_utils import loadConfigAndSetup, latestPolicy +from rl_baselines.evaluation.cross_eval_utils import loadConfigAndSetup, latestPolicy from srl_zoo.utils import printRed, printYellow from state_representation.registry import registered_srl @@ -84,6 +84,35 @@ def sortFirst(val): return res[:, 0], res[:, 1] +def allPolicyFiles(log_dir): + """ + + :param log_dir: + :return: + """ + train_args, algo_name, algo_class, srl_model_path, env_kwargs = loadConfigAndSetup(log_dir) + files = glob.glob(os.path.join(log_dir + algo_name + '_*_model.pkl')) + printYellow(log_dir) + files = glob.glob(log_dir + '/model_*') + + + files_list = [] + for file in files: + eps = int((file.split('_')[-1])) + files_list.append((eps, file+'/')) + + def sortFirst(val): + """ + + :param val: + :return: + """ + return val[0] + + files_list.sort(key=sortFirst) + res = np.array(files_list) + return res[:, 0], res[:, 1] + def newPolicy(episodes, file_path): """ diff --git a/rl_baselines/train.py b/rl_baselines/train.py index 978f6985e..ee379d1a9 100644 --- a/rl_baselines/train.py +++ b/rl_baselines/train.py @@ -36,7 +36,9 @@ EPISODE_WINDOW = 40 # For plotting moving average EVAL_TASK=['cc','sc','sqc'] CROSS_EVAL = False -EPISODE_WINDOW_DISTILLATION_WIN = 100 +EPISODE_WINDOW_DISTILLATION_WIN = 20 +NEW_LR=0.01 + viz = None n_steps = 0 @@ -170,15 +172,23 @@ def callback(_locals, _globals): ALGO.save(LOG_DIR + ALGO_NAME + "_model.pkl", _locals) if n_episodes >= 0: - # if n_episodes >= 70 and n_episodes % 40 == 0: - # ALGO.save(LOG_DIR + ALGO_NAME + "_" + str(n_episodes) + "_model.pkl", _locals) - # printYellow(EVAL_TASK) - # if CROSS_EVAL: - # episodeEval(LOG_DIR, EVAL_TASK) + #For every checkpoint, we create one directory for saving logs file (policy and run mean std) if n_episodes % EPISODE_WINDOW_DISTILLATION_WIN == 0: - ALGO.save(LOG_DIR + ALGO_NAME + "_" + str(n_episodes) + "_model.pkl", _locals) - printYellow(EVAL_TASK) + eps_path = LOG_DIR + "model_"+ str(n_episodes) + try: + os.mkdir(LOG_DIR + "model_"+ str(n_episodes)) + except OSError: + print("Creation of the directory {} failed".format(eps_path)) + + ALGO.save("{}/{}".format( eps_path, ALGO_NAME + "_model.pkl"), _locals) + try: + if 'env' in _locals: + _locals['env'].save_running_average(eps_path) + else: + _locals['self'].env.save_running_average(eps_path) + except AttributeError: + pass if CROSS_EVAL: episodeEval(LOG_DIR, EVAL_TASK) @@ -256,7 +266,8 @@ def main(): help='A cross evaluation from the latest stored model to all tasks') parser.add_argument('--eval-episode-window', type=int, default=400, metavar='N', help='Episode window for saving each policy checkpoint for future distillation(default: 100)') - + parser.add_argument('--new-lr',type = float , default =1.e-4 , + help="New learning rate ratio to train a pretrained agent") # Ignore unknown args for now args, unknown = parser.parse_known_args() @@ -300,6 +311,7 @@ def main(): MIN_EPISODES_BEFORE_SAVE = args.min_episodes_save CROSS_EVAL = args.perform_cross_evaluation_cc EPISODE_WINDOW_DISTILLATION_WIN = args.eval_episode_window + NEW_LR =args.new_lr print("EPISODE_WINDOW_DISTILLATION_WIN: ", EPISODE_WINDOW_DISTILLATION_WIN) if args.no_vis: @@ -387,8 +399,8 @@ def main(): if args.load_rl_model_path is not None: # use a small learning rate - print("use a small learning rate: {:f}".format(1.0e-8)) - hyperparams["learning_rate"] = lambda f: f * 1.0e-8 + print("use a small learning rate: {:f}".format(NEW_LR)) + hyperparams["learning_rate"] = lambda f: f * NEW_LR # Train the agent # episodeEval(LOG_DIR,EVAL_TASK) diff --git a/rl_baselines/visualize.py b/rl_baselines/visualize.py index 22fd450f8..e2e1270c9 100644 --- a/rl_baselines/visualize.py +++ b/rl_baselines/visualize.py @@ -9,14 +9,15 @@ from scipy.signal import medfilt -def smoothRewardCurve(x, y): +def smoothRewardCurve(x, y, conv_len=30): """ :param x: (numpy array) :param y: (numpy array) + :param conv_len: an integer, kernel size of the convolution :return: (numpy array, numpy array) """ # Halfwidth of our smoothing convolution - halfwidth = min(31, int(np.ceil(len(x) / 30))) + halfwidth = min(conv_len+1, int(np.ceil(len(x) / conv_len))) k = halfwidth xsmoo = x[k:-k] ysmoo = np.convolve(y, np.ones(2 * k + 1), mode='valid') / \ From dcea7b943325ca57ebd21d425518ba0706c0e5b1 Mon Sep 17 00:00:00 2001 From: sun-te Date: Tue, 7 May 2019 15:02:34 +0200 Subject: [PATCH 097/141] cross plot --- replay/cross_eval_plot.py | 62 ++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 37 deletions(-) diff --git a/replay/cross_eval_plot.py b/replay/cross_eval_plot.py index 61722a9a2..f3fcb7e73 100644 --- a/replay/cross_eval_plot.py +++ b/replay/cross_eval_plot.py @@ -3,14 +3,14 @@ """ import argparse import os - +import pickle import matplotlib.pyplot as plt import numpy as np import seaborn as sns from matplotlib import rc from replay.aggregate_plots import lightcolors, darkcolors, Y_LIM_SHAPED_REWARD, Y_LIM_SPARSE_REWARD, millions -from srl_zoo.utils import printGreen, printRed +from rl_baselines.cross_eval import dict2array from rl_baselines.visualize import smoothRewardCurve # Init seaborn sns.set() @@ -19,27 +19,17 @@ rc('font', weight='bold') -def crossEvalPlot(load_path, tasks,title,y_limits): - """ - Plot with standard deviation, the reward curve - :param load_path: - :param tasks: - :param title: - :param y_limits: - :return: - """ - res=np.load(load_path) - - y_array=res[:,:,1:] - - x=res[:,:,0][0] +def crossEvalPlot(res, tasks, title, y_limits): + y_array = res[:, :, 1:] + # y_array = np.sort(res[:, :, 1:], axis=2) + # y_array = np.mean(y_array[:,:,1:],axis=2) + x = res[:, :, 0][0] fig = plt.figure(title) for i in range(len(y_array)): label = tasks[i] y = y_array[i].T - printRed(y.shape) print('{}: {} experiments'.format(label, len(y))) # Compute mean for different seeds m = np.mean(y, axis=0) @@ -53,32 +43,23 @@ def crossEvalPlot(load_path, tasks,title,y_limits): plt.ylabel('Rewards', fontsize=20, fontweight='bold') plt.title(title, **fontstyle) - if(y_limits[0]!=y_limits[1]): + if (y_limits[0] != y_limits[1]): plt.ylim(y_limits) plt.legend(framealpha=0.8, frameon=True, labelspacing=0.01, loc='lower right', fontsize=18) plt.show() - -def smoothPlot(load_path, tasks,title,y_limits): - """ - To plot a smoother curve with some tricks of conv1D - :param load_path: (str) - :param tasks: (list) ['sc','cc'] - :param title: (str) - :param y_limits: (list) if not equal, use it as y_limits - :return: - """ - res = np.load(load_path) +def smoothPlot(res, tasks, title, y_limits): y = np.mean(res[:, :, 1:], axis=2) + # y = np.sort(res[:, :, 1:], axis=2) + # y = np.mean(y[:,:,1:],axis=2) x = res[:, :, 0][0] print(y.shape, x.shape) - fig=plt.figure(title) + fig = plt.figure(title) for i in range(len(y)): label = tasks[i] - tmp_x,tmp_y=smoothRewardCurve(x,y[i],conv_len=4) - print(tmp_x.shape,tmp_y.shape) + tmp_x, tmp_y = smoothRewardCurve(x, y[i], conv_len=3) plt.plot(tmp_x, tmp_y, color=darkcolors[i % len(darkcolors)], label=label, linewidth=2) plt.xlabel('Number of Episodes') plt.ylabel('Rewards', fontsize=20, fontweight='bold') @@ -92,12 +73,11 @@ def smoothPlot(load_path, tasks,title,y_limits): - #Example command: # python -m replay.cross_eval_plot -i logs/sc2cc/OmnirobotEnv-v0/srl_combination/ppo2/19-04-29_14h59_35/episode_eval.npy if __name__ == '__main__': parser = argparse.ArgumentParser(description="Plot the learning curve during a training for different tasks") - parser.add_argument('-i', '--input-path', help='folder with the plots as npy files', type=str, required=True) + parser.add_argument('-i', '--input-path', help='folder with the plots as pkl files', type=str, required=True) parser.add_argument('-t', '--title', help='Plot title', type=str, default='Learning Curve') # parser.add_argument('--episode_window', type=int, default=40, # help='Episode window for moving average plot (default: 40)') @@ -120,9 +100,17 @@ def smoothPlot(load_path, tasks,title,y_limits): y_limits = args.y_lim tasks = args.eval_tasks - assert (os.path.isfile(load_path) and load_path.split('.')[-1]=='npy'), 'Please load a valid .npy file' + + + assert (os.path.isfile(load_path) and load_path.split('.')[-1]=='pkl'), 'Please load a valid .pkl file' + + + with open(load_path, "rb") as file: + data = pickle.load(file) + + res = dict2array(['cc', 'sc'], data) if(args.smooth): - smoothPlot(load_path,tasks,title,y_limits) + smoothPlot(res,tasks,title,y_limits) else: - crossEvalPlot(load_path, tasks, title,y_limits) + crossEvalPlot(res, tasks, title,y_limits) From 3d0f79d2b0f677026ed34206f01a4f7a1bb7d854 Mon Sep 17 00:00:00 2001 From: kalifou Date: Wed, 8 May 2019 21:19:37 +0200 Subject: [PATCH 098/141] clean and test for distillation(draft) --- environments/dataset_generator_student.py | 2 +- ...{dataset_fusioner.py => dataset_merger.py} | 2 +- real_robots/omnirobot_simulator_server.py | 2 +- rl_baselines/base_classes.py | 3 +- rl_baselines/student_eval.py | 56 +++++++------ .../supervised_rl/Readme.md | 0 .../supervised_rl/policy_distillation.py | 6 +- run_policy_raw_pixels.sh | 0 run_raw_pixels_dry_run.sh | 0 tests/test_distillation_pipeline.py | 83 +++++++++++++++++++ tests/test_end_to_end.py | 6 +- 11 files changed, 125 insertions(+), 35 deletions(-) rename environments/{dataset_fusioner.py => dataset_merger.py} (98%) rename Distilation_Readme.md => rl_baselines/supervised_rl/Readme.md (100%) delete mode 100644 run_policy_raw_pixels.sh delete mode 100644 run_raw_pixels_dry_run.sh create mode 100644 tests/test_distillation_pipeline.py diff --git a/environments/dataset_generator_student.py b/environments/dataset_generator_student.py index 687bbbe82..d168392ef 100644 --- a/environments/dataset_generator_student.py +++ b/environments/dataset_generator_student.py @@ -50,7 +50,7 @@ def loadConfigAndSetup(load_args): algo_class, algo_type, _ = registered_rl[algo_name] if algo_type == AlgoType.OTHER: raise ValueError(algo_name + " is not supported for replay") - if(not load_args.episode ==-1): + if not load_args.episode ==-1: load_path = "{}/{}_{}_model.pkl".format(load_args.log_dir, algo_name,load_args.episode,) else: load_path = "{}/{}_model.pkl".format(load_args.log_dir, algo_name) diff --git a/environments/dataset_fusioner.py b/environments/dataset_merger.py similarity index 98% rename from environments/dataset_fusioner.py rename to environments/dataset_merger.py index 8266c04c8..5b5d195fc 100644 --- a/environments/dataset_fusioner.py +++ b/environments/dataset_merger.py @@ -34,7 +34,7 @@ def main(): # If the merge file exists already, delete it for the convenince of updating student's policy if os.path.exists(args.merge[2]): - assert args.force, "Error: destionation directory '{}' already exists".format(args.merge[2]) + assert args.force, "Error: destination directory '{}' already exists".format(args.merge[2]) shutil.rmtree(args.merge[2]) if 'continual_learning_labels' in args: diff --git a/real_robots/omnirobot_simulator_server.py b/real_robots/omnirobot_simulator_server.py index 764e39c01..3fd781a4d 100755 --- a/real_robots/omnirobot_simulator_server.py +++ b/real_robots/omnirobot_simulator_server.py @@ -379,7 +379,7 @@ def __init__(self, **args): ''' super(OmniRobotSimulatorSocket, self).__init__() - defalt_args = { + default_args = { "back_ground_path": "real_robots/omnirobot_utils/back_ground.jpg", "camera_info_path": CAMERA_INFO_PATH, "robot_marker_path": "real_robots/omnirobot_utils/robot_margin3_pixel_only_tag.png", diff --git a/rl_baselines/base_classes.py b/rl_baselines/base_classes.py index d61350f4a..22c48958b 100644 --- a/rl_baselines/base_classes.py +++ b/rl_baselines/base_classes.py @@ -231,7 +231,8 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): if self.load_rl_model_path is not None: load_path_normalise = os.path.dirname(self.load_rl_model_path) - envs = self.makeEnv(args, env_kwargs=env_kwargs, load_path_normalise=load_path_normalise) + envs = self.makeEnv(args, env_kwargs=env_kwargs, + load_path_normalise=train_kwargs.get("load_path_normalise", None)) if train_kwargs is None: train_kwargs = {} diff --git a/rl_baselines/student_eval.py b/rl_baselines/student_eval.py index 46bb9f371..3a99e2ab3 100644 --- a/rl_baselines/student_eval.py +++ b/rl_baselines/student_eval.py @@ -1,12 +1,12 @@ import argparse import datetime import glob -import json -import numpy as np import os import subprocess import time -# import yaml + +import json +import numpy as np from environments.registry import registered_env from rl_baselines.evaluation.cross_eval_utils import loadConfigAndSetup, latestPolicy @@ -17,8 +17,8 @@ CL_LABEL_KEY = "continual_learning_label" -def DatasetGenerator(teacher_path, output_name, task_id, episode=-1, env_name='OmnirobotEnv-v0', num_cpu=1, - num_eps=200): +def OnPolicyDatasetGenerator(teacher_path, output_name, task_id, episode=-1, env_name='OmnirobotEnv-v0', num_cpu=1, + num_eps=200, test_mode=False): """ :param teacher_path: @@ -37,10 +37,10 @@ def DatasetGenerator(teacher_path, output_name, task_id, episode=-1, env_name='O env_command = ['--env', env_name] task_command = ["-sc" if task_id == "SC" else '-cc'] if task_id == 'SC': - episode_command = ['--num-episode', str(400)] + episode_command = ['--num-episode', str(10 if test_mode else 400)] else: - episode_command = ['--num-episode', str(60)] - + episode_command = ['--num-episode', str(10 if test_mode else 60)] + print("teacher path: ", teacher_path) policy_command = ['--log-custom-policy', teacher_path] if episode == -1: eps_policy = [] @@ -95,7 +95,6 @@ def allPolicyFiles(log_dir): printYellow(log_dir) files = glob.glob(log_dir + '/model_*') - files_list = [] for file in files: eps = int((file.split('_')[-1])) @@ -113,6 +112,7 @@ def sortFirst(val): res = np.array(files_list) return res[:, 0], res[:, 1] + def newPolicy(episodes, file_path): """ @@ -150,11 +150,22 @@ def trainStudent(teacher_data_path, task_id, yaml_file='config/srl_models.yaml', task_command = ["-sc" if task_id is "SC" else '-cc'] ok = subprocess.call(command_line + srl_command + env_command + policy_command + size_epochs + task_command + ['--srl-config-file', yaml_file]) + assert ok == 0 -def mergeData(teacher_dataset_1, teacher_dataset_2, merge_dataset): +def mergeData(teacher_dataset_1, teacher_dataset_2, merge_dataset, force=False): + """ + + :param teacher_dataset_1: + :param teacher_dataset_2: + :param merge_dataset: + :return: + """ merge_command = ['--merge', teacher_dataset_1, teacher_dataset_2, merge_dataset] - subprocess.call(['python', '-m', 'environments.dataset_fusioner'] + merge_command) + if force: + merge_command.append('-f') + ok = subprocess.call(['python', '-m', 'environments.dataset_merger'] + merge_command) + assert ok == 0 def main(): @@ -193,7 +204,6 @@ def main(): parser.add_argument('--eval-episode-window', type=int, default=400, metavar='N', help='Episode window for saving each policy checkpoint for future distillation(default: 100)') - args, unknown = parser.parse_known_args() if 'continual_learning_labels' in args: @@ -212,12 +222,6 @@ def main(): assert os.path.exists(args.log_dir_teacher_two), \ "Error: cannot load \"--srl-config-file {}\", file not found!".format(args.srl_config_file_two) - # with open(args.srl_config_file_one, 'rb') as f: - # model_one = yaml.load(f) - - # with open(args.srl_config_file_two, 'rb') as f: - # model_two = yaml.load(f) - teacher_pro = args.log_dir_teacher_one teacher_learn = args.log_dir_teacher_two @@ -232,14 +236,14 @@ def main(): rewards_at_episode = {} episodes_to_test = [e for e in episodes if (int(e) < 2000 and int(e) % 200 == 0) or (int(e) > 2000 and int(e) % 1000 == 0)] - #[e for e in episodes if int(e) % args.eval_episode_window == 0] # generate data from Professional teacher printYellow("\nGenerating on policy for optimal teacher: " + args.continual_learning_labels[0]) if not (args.log_dir_teacher_one == "None"): - DatasetGenerator(teacher_pro, args.continual_learning_labels[0] + '_copy/', task_id=args.continual_learning_labels[0], - num_eps=args.epochs_teacher_datasets, episode=-1, env_name=args.env) + OnPolicyDatasetGenerator(teacher_pro, args.continual_learning_labels[0] + '_copy/', + task_id=args.continual_learning_labels[0], num_eps=args.epochs_teacher_datasets, + episode=-1, env_name=args.env) print("Eval on eps list: ", episodes_to_test) for eps in episodes_to_test: student_path = args.log_dir_student @@ -253,9 +257,9 @@ def main(): time.sleep(10) # Generate data from learning teacher - printYellow("\nGenerating on policy for optimal teacher: " + args.continual_learning_labels[1]) - DatasetGenerator(teacher_learn, teacher_learn_data, task_id=args.continual_learning_labels[1], episode=eps, - num_eps=args.epochs_teacher_datasets, env_name=args.env) + printYellow("\nGenerating on-policy data from the optimal teacher: " + args.continual_learning_labels[1]) + OnPolicyDatasetGenerator(teacher_learn, teacher_learn_data, task_id=args.continual_learning_labels[1], + episode=eps, num_eps=args.epochs_teacher_datasets, env_name=args.env) if args.log_dir_teacher_one == "None": merge_path = 'data/' + teacher_learn_data @@ -299,8 +303,8 @@ def main(): rewards_at_episode[eps] = rewards print("All rewards: ", rewards_at_episode) json_dict = json.dumps(rewards_at_episode) - json_dict_name = args.log_dir_student + "/reward_at_episode_" + \ - datetime.datetime.now().strftime("%y-%m-%d_%Hh%M_%S") + '.json' + json_dict_name = \ + args.log_dir_student + "/reward_at_episode_" + datetime.datetime.now().strftime("%y-%m-%d_%Hh%M_%S") + '.json' f = open(json_dict_name, "w") f.write(json_dict) f.close() diff --git a/Distilation_Readme.md b/rl_baselines/supervised_rl/Readme.md similarity index 100% rename from Distilation_Readme.md rename to rl_baselines/supervised_rl/Readme.md diff --git a/rl_baselines/supervised_rl/policy_distillation.py b/rl_baselines/supervised_rl/policy_distillation.py index b108bf646..77d268946 100644 --- a/rl_baselines/supervised_rl/policy_distillation.py +++ b/rl_baselines/supervised_rl/policy_distillation.py @@ -226,7 +226,6 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): self.srl_model = loadSRLModel(env_kwargs.get("srl_model_path", None), th.cuda.is_available(), self.state_dim, env_object=None) - self.model = MLPPolicy(output_size=n_actions, input_size=self.state_dim) for param in self.model.parameters(): param.requires_grad = True @@ -293,8 +292,9 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): state = obs.detach() pred_action = self.model.forward(state) - loss = self.loss_fn_kd(pred_action, actions_proba_st.float(), - labels=cl_labels_st, adaptive_temperature=USE_ADAPTIVE_TEMPERATURE) + loss = self.loss_fn_kd(pred_action, + actions_proba_st.float(), + labels=cl_labels_st, adaptive_temperature=USE_ADAPTIVE_TEMPERATURE) loss.backward() if validation_mode: diff --git a/run_policy_raw_pixels.sh b/run_policy_raw_pixels.sh deleted file mode 100644 index e69de29bb..000000000 diff --git a/run_raw_pixels_dry_run.sh b/run_raw_pixels_dry_run.sh deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/test_distillation_pipeline.py b/tests/test_distillation_pipeline.py new file mode 100644 index 000000000..4c9ad63be --- /dev/null +++ b/tests/test_distillation_pipeline.py @@ -0,0 +1,83 @@ +import subprocess +import pytest +import os +import shutil +import time + +from rl_baselines.student_eval import OnPolicyDatasetGenerator, mergeData, trainStudent + + +ENV_NAME = 'OmnirobotEnv-v0' +PATH_SRL = "srl_zoo/data/" +DEFAULT_SRL_TEACHERS = "ground_truth" +DEFAULT_SRL_STUDENT = "raw_pixels" +NUM_TIMESTEP = 25000 +NUM_CPU = 4 + + +def assertEq(left, right): + assert left == right, "{} != {}".format(left, right) + + +@pytest.mark.fast +def testOnPolicyDatasetGeneration(): + + # # Train Ground_truth teacher policies for each env + test_log_dir = "logs/test_distillation/" + test_log_dir_teacher_one = test_log_dir + 'teacher_one/' + test_log_dir_teacher_two = test_log_dir + 'teacher_two/' + + if os.path.exists(test_log_dir): + print("Destination log directory '{}' already exists - removing it before re-creating it".format(test_log_dir)) + shutil.rmtree(test_log_dir) + + os.mkdir(test_log_dir) + os.mkdir(test_log_dir_teacher_one) + os.mkdir(test_log_dir_teacher_two) + + args = ['--algo', "ppo2", '--env', ENV_NAME, '--srl-model', DEFAULT_SRL_TEACHERS, + '--num-timesteps', NUM_TIMESTEP, '--num-cpu', NUM_CPU, '--no-vis', '--log-dir', + test_log_dir_teacher_one, '-sc'] + args = list(map(str, args)) + + ok = subprocess.call(['python', '-m', 'rl_baselines.train'] + args) + assertEq(ok, 0) + + args = ['--algo', "ppo2", '--env', ENV_NAME, '--srl-model', DEFAULT_SRL_TEACHERS, + '--num-timesteps', NUM_TIMESTEP, '--num-cpu', NUM_CPU, '--no-vis', '--log-dir', + test_log_dir_teacher_two, '-cc'] + args = list(map(str, args)) + + ok = subprocess.call(['python', '-m', 'rl_baselines.train'] + args) + assertEq(ok, 0) + + # Generate on-policy datasets from each teacher + test_log_dir_teacher_one += ENV_NAME + '/' + DEFAULT_SRL_TEACHERS + "/ppo2" + teacher_one_path = \ + max([test_log_dir_teacher_one + "/" + d for d in os.listdir(test_log_dir_teacher_one) + if os.path.isdir(test_log_dir_teacher_one + "/" + d)], key=os.path.getmtime) + '/' + + OnPolicyDatasetGenerator(teacher_path=teacher_one_path, + output_name='test_SC_copy/', task_id='SC', episode=-1, env_name=ENV_NAME, test_mode=True) + + test_log_dir_teacher_two += ENV_NAME + '/' + DEFAULT_SRL_TEACHERS + "/ppo2" + teacher_two_path = \ + max([test_log_dir_teacher_two + "/" + d for d in os.listdir(test_log_dir_teacher_two) + if os.path.isdir(test_log_dir_teacher_two + "/" + d)], key=os.path.getmtime) + '/' + + # TODO: fix when fails here! + OnPolicyDatasetGenerator(teacher_path=teacher_two_path, output_name='test_CC_copy/', + task_id='CC', episode=-1, env_name=ENV_NAME, test_mode=True) + + # Merge those on-policy datasets + merge_path = "data/on_policy_merged_test" + mergeData('data/test_SC_copy/', 'data/test_CC_copy/', merge_path, force=True) + + ok = subprocess.call(['cp', '-r', merge_path, 'srl_zoo/data/', '-f']) + assert ok == 0 + time.sleep(180) + + # # Train a raw_pixels student policy via distillation + # trainStudent(merge_path, "CC", log_dir=test_log_dir, srl_model=DEFAULT_SRL_STUDENT, + # env_name=ENV_NAME, training_size=500, epochs=3) + print("Distillation test performed!") diff --git a/tests/test_end_to_end.py b/tests/test_end_to_end.py index 01122a023..1f3286f2e 100644 --- a/tests/test_end_to_end.py +++ b/tests/test_end_to_end.py @@ -167,7 +167,8 @@ def testSrlCombiningTrain(): assertEq(ok, 0) -@pytest.mark.parametrize("model_type", ['vae', 'autoencoder', "robotic_priors", "inverse", "forward", "srl_combination", "multi_view_srl"]) +@pytest.mark.parametrize("model_type", ['vae', 'autoencoder', "robotic_priors", "inverse", "forward", + "srl_combination", "multi_view_srl"]) def testAllRLOnSrlTrain(model_type): """ Testing all the previously learned srl models on the RL pipeline @@ -182,7 +183,8 @@ def testAllRLOnSrlTrain(model_type): assertEq(ok, 0) -@pytest.mark.parametrize("algo", ['a2c', 'acer', 'acktr', 'ars', 'cma-es', 'ddpg', 'deepq', 'ppo1', 'ppo2', 'random_agent', 'sac', 'trpo']) +@pytest.mark.parametrize("algo", ['a2c', 'acer', 'acktr', 'ars', 'cma-es', 'ddpg', 'deepq', 'ppo1', 'ppo2', + 'random_agent', 'sac', 'trpo']) def testAllSrlonRLTrain(algo): """ Testing RL pipeline on previously learned models From fd08dd7aa833ce8fb3b06ff27a526807381d2afe Mon Sep 17 00:00:00 2001 From: sun-te Date: Fri, 10 May 2019 15:24:37 +0200 Subject: [PATCH 099/141] corss eval and dataset generator, test_eval --- environments/dataset_generator.py | 2 + environments/dataset_generator_student.py | 2 +- ...{dataset_fusioner.py => dataset_merger.py} | 34 ++-- environments/omnirobot_gym/omnirobot_env.py | 97 +++++----- replay/cross_eval_plot.py | 16 +- replay/enjoy_baselines.py | 18 +- rl_baselines/base_classes.py | 22 +-- rl_baselines/cross_eval.py | 59 +++++-- rl_baselines/evaluation/eval_post.py | 2 +- rl_baselines/student_eval.py | 67 +++---- rl_baselines/train.py | 48 ++--- tests/test_eval.py | 166 ++++++++++++++++++ 12 files changed, 366 insertions(+), 167 deletions(-) rename environments/{dataset_fusioner.py => dataset_merger.py} (82%) create mode 100644 tests/test_eval.py diff --git a/environments/dataset_generator.py b/environments/dataset_generator.py index 91c6b7faf..e3178a3f1 100644 --- a/environments/dataset_generator.py +++ b/environments/dataset_generator.py @@ -306,6 +306,8 @@ def main(): parser.add_argument('--short-episodes', action='store_true', default=False, help='Generate short episodes (only 10 contacts with the target allowed).') + parser.add_argument('--episode', type=int, default=-1, + help='Model saved at episode N that we want to load') args = parser.parse_args() diff --git a/environments/dataset_generator_student.py b/environments/dataset_generator_student.py index 687bbbe82..d168392ef 100644 --- a/environments/dataset_generator_student.py +++ b/environments/dataset_generator_student.py @@ -50,7 +50,7 @@ def loadConfigAndSetup(load_args): algo_class, algo_type, _ = registered_rl[algo_name] if algo_type == AlgoType.OTHER: raise ValueError(algo_name + " is not supported for replay") - if(not load_args.episode ==-1): + if not load_args.episode ==-1: load_path = "{}/{}_{}_model.pkl".format(load_args.log_dir, algo_name,load_args.episode,) else: load_path = "{}/{}_model.pkl".format(load_args.log_dir, algo_name) diff --git a/environments/dataset_fusioner.py b/environments/dataset_merger.py similarity index 82% rename from environments/dataset_fusioner.py rename to environments/dataset_merger.py index 741cec7ee..11763a8b0 100644 --- a/environments/dataset_fusioner.py +++ b/environments/dataset_merger.py @@ -13,32 +13,35 @@ def main(): - parser = argparse.ArgumentParser(description='Dataset Manipulator: useful to fusion two datasets by concatenating ' - 'episodes. PS: Deleting sources after fusion into destination folder.') + parser = argparse.ArgumentParser(description='Dataset Manipulator: useful to merge two datasets by concatenating ' + + 'episodes. PS: Deleting sources after merging into the destination ' + + 'folder.') parser.add_argument('--continual-learning-labels', type=str, nargs=2, metavar=('label_1', 'label_2'), - default=argparse.SUPPRESS, - help='Labels for the continual learning RL distillation task.') + default=argparse.SUPPRESS, help='Labels for the continual learning RL distillation task.') + parser.add_argument('-f', '--force', action='store_true', default=False, + help='Force the merge, even if it overrides something else,' + ' including the destination if it exist') group = parser.add_mutually_exclusive_group() group.add_argument('--merge', type=str, nargs=3, metavar=('source_1', 'source_2', 'destination'), default=argparse.SUPPRESS, - help='Fusion two datasets by appending the episodes, deleting sources right after.') + help='Merge two datasets by appending the episodes, deleting sources right after.') args = parser.parse_args() if 'merge' in args: # let make sure everything is in order assert os.path.exists(args.merge[0]), "Error: dataset '{}' could not be found".format(args.merge[0]) - # assert (not os.path.exists(args.merge[2])), "Error: dataset '{}' already exists, cannot rename '{}' to '{}'"\ - # .format(args.merge[2], args.merge[0], args.merge[2]) - ############################################# - #If the merge file exists already, delete it for the convenince of updating student's policy - if (os.path.exists(args.merge[2])): + + # If the merge file exists already, delete it for the convenince of updating student's policy + if os.path.exists(args.merge[2]) or os.path.exists(args.merge[2] + '/'): + assert args.force, "Error: destination directory '{}' already exists".format(args.merge[2]) shutil.rmtree(args.merge[2]) - ############################################# + if 'continual_learning_labels' in args: assert args.continual_learning_labels[0] in CONTINUAL_LEARNING_LABELS \ and args.continual_learning_labels[1] in CONTINUAL_LEARNING_LABELS, \ "Please specify a valid Continual learning label to each dataset to be used for RL distillation !" + # create the output os.mkdir(args.merge[2]) @@ -135,11 +138,12 @@ def main(): pr_arr.astype(to_class)), axis=0) if 'continual_learning_labels' in args: if preprocessed.get(CL_LABEL_KEY, None) is None: - preprocessed[CL_LABEL_KEY] = np.array([args.continual_learning_labels[idx] for _ in range(dataset_1_size)]) + preprocessed[CL_LABEL_KEY] = \ + np.array([args.continual_learning_labels[idx] for _ in range(dataset_1_size)]) else: - preprocessed[CL_LABEL_KEY] = np.concatenate((preprocessed[CL_LABEL_KEY], - np.array([args.continual_learning_labels[idx] - for _ in range(dataset_2_size)])), axis=0) + preprocessed[CL_LABEL_KEY] = \ + np.concatenate((preprocessed[CL_LABEL_KEY], np.array([args.continual_learning_labels[idx] + for _ in range(dataset_2_size)])), axis=0) np.savez(args.merge[2] + "/preprocessed_data.npz", ** preprocessed) diff --git a/environments/omnirobot_gym/omnirobot_env.py b/environments/omnirobot_gym/omnirobot_env.py index 96817610e..347d1cab8 100644 --- a/environments/omnirobot_gym/omnirobot_env.py +++ b/environments/omnirobot_gym/omnirobot_env.py @@ -113,9 +113,9 @@ def __init__(self, renders=False, name="Omnirobot", is_discrete=True, save_path= self.action_space = spaces.Discrete(N_DISCRETE_ACTIONS) else: action_dim = 2 - self.action_space = RingBox(positive_low=ACTION_POSITIVE_LOW, positive_high=ACTION_POSITIVE_HIGH, \ - negative_low=ACTION_NEGATIVE_LOW, negative_high=ACTION_NEGATIVE_HIGH, \ - shape=np.array([action_dim]), dtype=np.float32) + self.action_space = RingBox(positive_low=ACTION_POSITIVE_LOW, positive_high=ACTION_POSITIVE_HIGH, + negative_low=ACTION_NEGATIVE_LOW, negative_high=ACTION_NEGATIVE_HIGH, + shape=np.array([action_dim]), dtype=np.float32) # SRL model if self.use_srl: if use_ground_truth: @@ -370,9 +370,8 @@ def initVisualizeBoundary(self): with open(CAMERA_INFO_PATH, 'r') as stream: try: contents = yaml.load(stream) - camera_matrix = np.array(contents['camera_matrix']['data']).reshape((3,3)) - distortion_coefficients = np.array( - contents['distortion_coefficients']['data']).reshape((1, 5)) + camera_matrix = np.array(contents['camera_matrix']['data']).reshape((3, 3)) + distortion_coefficients = np.array(contents['distortion_coefficients']['data']).reshape((1, 5)) except yaml.YAMLError as exc: print(exc) @@ -380,43 +379,43 @@ def initVisualizeBoundary(self): r = R.from_euler('xyz', CAMERA_ROT_EULER_COORD_GROUND, degrees=True) camera_rot_mat_coord_ground = r.as_dcm() - pos_transformer = PosTransformer(camera_matrix, distortion_coefficients, - CAMERA_POS_COORD_GROUND, camera_rot_mat_coord_ground) + pos_transformer = PosTransformer(camera_matrix, distortion_coefficients, CAMERA_POS_COORD_GROUND, + camera_rot_mat_coord_ground) - self.boundary_coner_pixel_pos = np.zeros((2,4)) + self.boundary_coner_pixel_pos = np.zeros((2, 4)) # assume that image is undistorted - self.boundary_coner_pixel_pos[:,0] = pos_transformer.phyPosGround2PixelPos([MIN_X, MIN_Y], - return_distort_image_pos=False).squeeze() - self.boundary_coner_pixel_pos[:,1] = pos_transformer.phyPosGround2PixelPos([MAX_X, MIN_Y], - return_distort_image_pos=False).squeeze() - self.boundary_coner_pixel_pos[:,2] = pos_transformer.phyPosGround2PixelPos([MAX_X, MAX_Y], - return_distort_image_pos=False).squeeze() - self.boundary_coner_pixel_pos[:,3] = pos_transformer.phyPosGround2PixelPos([MIN_X, MAX_Y], - return_distort_image_pos=False).squeeze() + self.boundary_coner_pixel_pos[:, 0] = \ + pos_transformer.phyPosGround2PixelPos([MIN_X, MIN_Y], return_distort_image_pos=False).squeeze() + self.boundary_coner_pixel_pos[:, 1] = \ + pos_transformer.phyPosGround2PixelPos([MAX_X, MIN_Y], return_distort_image_pos=False).squeeze() + self.boundary_coner_pixel_pos[:, 2] = \ + pos_transformer.phyPosGround2PixelPos([MAX_X, MAX_Y], return_distort_image_pos=False).squeeze() + self.boundary_coner_pixel_pos[:, 3] = \ + pos_transformer.phyPosGround2PixelPos([MIN_X, MAX_Y], return_distort_image_pos=False).squeeze() # transform the corresponding points into cropped image - self.boundary_coner_pixel_pos = self.boundary_coner_pixel_pos - (np.array(ORIGIN_SIZE) - np.array(CROPPED_SIZE)).reshape(2,1) / 2.0 + self.boundary_coner_pixel_pos = self.boundary_coner_pixel_pos - (np.array(ORIGIN_SIZE) - + np.array(CROPPED_SIZE)).reshape(2, 1) / 2.0 # transform the corresponding points into resized image (RENDER_WIDHT, RENDER_HEIGHT) - self.boundary_coner_pixel_pos[0,:] *= RENDER_WIDTH/CROPPED_SIZE[0] - self.boundary_coner_pixel_pos[1,:] *= RENDER_HEIGHT/CROPPED_SIZE[1] + self.boundary_coner_pixel_pos[0, :] *= RENDER_WIDTH/CROPPED_SIZE[0] + self.boundary_coner_pixel_pos[1, :] *= RENDER_HEIGHT/CROPPED_SIZE[1] self.boundary_coner_pixel_pos = np.around(self.boundary_coner_pixel_pos).astype(np.int) # Create square for vizu of objective in continual square task if self.square_continual_move: - self.boundary_coner_pixel_pos_continual = np.zeros((2, 4)) # assume that image is undistorted - self.boundary_coner_pixel_pos_continual[:, 0] = pos_transformer.phyPosGround2PixelPos([-RADIUS, -RADIUS], - return_distort_image_pos=False).squeeze() - self.boundary_coner_pixel_pos_continual[:, 1] = pos_transformer.phyPosGround2PixelPos([RADIUS, -RADIUS], - return_distort_image_pos=False).squeeze() - self.boundary_coner_pixel_pos_continual[:, 2] = pos_transformer.phyPosGround2PixelPos([RADIUS, RADIUS], - return_distort_image_pos=False).squeeze() - self.boundary_coner_pixel_pos_continual[:, 3] = pos_transformer.phyPosGround2PixelPos([-RADIUS, RADIUS], - return_distort_image_pos=False).squeeze() + self.boundary_coner_pixel_pos_continual[:, 0] = \ + pos_transformer.phyPosGround2PixelPos([-RADIUS, -RADIUS], return_distort_image_pos=False).squeeze() + self.boundary_coner_pixel_pos_continual[:, 1] = \ + pos_transformer.phyPosGround2PixelPos([RADIUS, -RADIUS], return_distort_image_pos=False).squeeze() + self.boundary_coner_pixel_pos_continual[:, 2] = \ + pos_transformer.phyPosGround2PixelPos([RADIUS, RADIUS], return_distort_image_pos=False).squeeze() + self.boundary_coner_pixel_pos_continual[:, 3] = \ + pos_transformer.phyPosGround2PixelPos([-RADIUS, RADIUS], return_distort_image_pos=False).squeeze() # transform the corresponding points into cropped image self.boundary_coner_pixel_pos_continual = self.boundary_coner_pixel_pos_continual - ( @@ -429,8 +428,8 @@ def initVisualizeBoundary(self): self.boundary_coner_pixel_pos_continual = np.around(self.boundary_coner_pixel_pos_continual).astype(np.int) elif self.circular_continual_move: - self.center_coordinates = pos_transformer.phyPosGround2PixelPos([0, 0], - return_distort_image_pos=False).squeeze() + self.center_coordinates = \ + pos_transformer.phyPosGround2PixelPos([0, 0], return_distort_image_pos=False).squeeze() self.center_coordinates = self.center_coordinates - ( np.array(ORIGIN_SIZE) - np.array(CROPPED_SIZE)) / 2.0 # transform the corresponding points into resized image (RENDER_WIDHT, RENDER_HEIGHT) @@ -439,10 +438,9 @@ def initVisualizeBoundary(self): self.center_coordinates = np.around(self.center_coordinates).astype(np.int) - # Points to convert radisu in env space - self.boundary_coner_pixel_pos_continual = pos_transformer.phyPosGround2PixelPos([0, RADIUS], - return_distort_image_pos=False).squeeze() + self.boundary_coner_pixel_pos_continual = \ + pos_transformer.phyPosGround2PixelPos([0, RADIUS], return_distort_image_pos=False).squeeze() # transform the corresponding points into cropped image self.boundary_coner_pixel_pos_continual = self.boundary_coner_pixel_pos_continual - ( @@ -454,33 +452,26 @@ def initVisualizeBoundary(self): self.boundary_coner_pixel_pos_continual = np.around(self.boundary_coner_pixel_pos_continual).astype(np.int) - def visualizeBoundary(self): """ visualize the unvisible boundary, should call initVisualizeBoundary first """ self.observation_with_boundary = self.observation.copy() - #Add boundary continual + + # Add boundary continual if self.square_continual_move: - cv2.line(self.observation_with_boundary,tuple(self.boundary_coner_pixel_pos_continual[:,0]), - tuple(self.boundary_coner_pixel_pos_continual[:,1]),(0,0,200),2) - cv2.line(self.observation_with_boundary,tuple(self.boundary_coner_pixel_pos_continual[:,1]), - tuple(self.boundary_coner_pixel_pos_continual[:,2]),(0,0,200),2) - cv2.line(self.observation_with_boundary,tuple(self.boundary_coner_pixel_pos_continual[:,2]), - tuple(self.boundary_coner_pixel_pos_continual[:,3]),(0,0,200),2) - cv2.line(self.observation_with_boundary,tuple(self.boundary_coner_pixel_pos_continual[:,3]), - tuple(self.boundary_coner_pixel_pos_continual[:,0]),(0,0,200),2) + for idx in range(4): + idx_next = idx + 1 + cv2.line(self.observation_with_boundary, tuple(self.boundary_coner_pixel_pos_continual[:, idx]), + tuple(self.boundary_coner_pixel_pos_continual[:, idx_next % 4]), (0, 0, 200), 2) + elif self.circular_continual_move: radius_converted = np.linalg.norm(self.center_coordinates - self.boundary_coner_pixel_pos_continual) cv2.circle(self.observation_with_boundary, tuple(self.center_coordinates), np.float32(radius_converted), (0, 0, 200), 2) - #Add boundary of env - cv2.line(self.observation_with_boundary, tuple(self.boundary_coner_pixel_pos[:, 0]), - tuple(self.boundary_coner_pixel_pos[:, 1]), (200, 0, 0), 3) - cv2.line(self.observation_with_boundary, tuple(self.boundary_coner_pixel_pos[:, 1]), - tuple(self.boundary_coner_pixel_pos[:, 2]), (200, 0, 0), 3) - cv2.line(self.observation_with_boundary, tuple(self.boundary_coner_pixel_pos[:, 2]), - tuple(self.boundary_coner_pixel_pos[:, 3]), (200, 0, 0), 3) - cv2.line(self.observation_with_boundary, tuple(self.boundary_coner_pixel_pos[:, 3]), - tuple(self.boundary_coner_pixel_pos[:, 0]), (200, 0, 0), 3) \ No newline at end of file + # Add boundary of env + for idx in range(4): + idx_next = idx + 1 + cv2.line(self.observation_with_boundary, tuple(self.boundary_coner_pixel_pos[:, idx]), + tuple(self.boundary_coner_pixel_pos[:, idx_next % 4]), (200, 0, 0), 3) diff --git a/replay/cross_eval_plot.py b/replay/cross_eval_plot.py index f3fcb7e73..12206e996 100644 --- a/replay/cross_eval_plot.py +++ b/replay/cross_eval_plot.py @@ -74,20 +74,15 @@ def smoothPlot(res, tasks, title, y_limits): #Example command: -# python -m replay.cross_eval_plot -i logs/sc2cc/OmnirobotEnv-v0/srl_combination/ppo2/19-04-29_14h59_35/episode_eval.npy +# python -m replay.cross_eval_plot -i logs/sc2cc/OmnirobotEnv-v0/srl_combination/ppo2/19-04-29_14h59_35/eval.pkl if __name__ == '__main__': parser = argparse.ArgumentParser(description="Plot the learning curve during a training for different tasks") parser.add_argument('-i', '--input-path', help='folder with the plots as pkl files', type=str, required=True) parser.add_argument('-t', '--title', help='Plot title', type=str, default='Learning Curve') - # parser.add_argument('--episode_window', type=int, default=40, - # help='Episode window for moving average plot (default: 40)') - # parser.add_argument('--shape-reward', action='store_true', default=False, - # help='Change the y_limit to correspond shaped reward bounds') + parser.add_argument('--y-lim', nargs=2, type=float, default=[-1, -1], help="limits for the y axis") parser.add_argument('--truncate-x', type=int, default=-1, help="Truncate the experiments after n ticks on the x-axis (default: -1, no truncation)") - # parser.add_argument('--timesteps', - # help='Plot timesteps instead of episodes') parser.add_argument('--eval-tasks', type=str, nargs='+', default=['Circular', 'Target Reaching','Square'], help='A cross evaluation from the latest stored model to all tasks') parser.add_argument('-s','--smooth', action='store_true', default=False, @@ -108,9 +103,10 @@ def smoothPlot(res, tasks, title, y_limits): with open(load_path, "rb") as file: data = pickle.load(file) - res = dict2array(['cc', 'sc'], data) + res = dict2array(['cc', 'sc'], data) + print("{} episodes evaluations to plot".format(res.shape[1])) if(args.smooth): - smoothPlot(res,tasks,title,y_limits) + smoothPlot(res[:,1:],tasks,title,y_limits) else: - crossEvalPlot(res, tasks, title,y_limits) + crossEvalPlot(res[:,1:], tasks, title,y_limits) diff --git a/replay/enjoy_baselines.py b/replay/enjoy_baselines.py index b4ff1149f..63e181a4c 100644 --- a/replay/enjoy_baselines.py +++ b/replay/enjoy_baselines.py @@ -91,12 +91,18 @@ def loadConfigAndSetup(load_args): raise ValueError(algo_name + " is not supported for replay") printGreen("\n" + algo_name + "\n") - - if(load_args.log_dir[-3:]!='pkl'): - load_path = "{}/{}_model.pkl".format(load_args.log_dir, algo_name) - else: - load_path = load_args.log_dir - load_args.log_dir = os.path.dirname(load_path)+'/' + try: #If args contains episode information, this is for student_evaluation (disstilation) + if(not load_args.episode ==-1): + load_path = "{}/{}_{}_model.pkl".format(load_args.log_dir, algo_name,load_args.episode,) + else: + load_path = "{}/{}_model.pkl".format(load_args.log_dir, algo_name) + except: + printYellow("No episode of checkpoint specified, go for the default policy model: {}_model.pkl".format(algo_name)) + if(load_args.log_dir[-3:]!='pkl'): + load_path = "{}/{}_model.pkl".format(load_args.log_dir, algo_name) + else: + load_path = load_args.log_dir + load_args.log_dir = os.path.dirname(load_path)+'/' env_globals = json.load(open(load_args.log_dir + "env_globals.json", 'r')) diff --git a/rl_baselines/base_classes.py b/rl_baselines/base_classes.py index 97a1c2be7..23dff9384 100644 --- a/rl_baselines/base_classes.py +++ b/rl_baselines/base_classes.py @@ -128,9 +128,9 @@ def save(self, save_path, _locals=None): assert self.model is not None, "Error: must train or load model before use" episode = os.path.basename(save_path).split('_')[-2] - if(bool(re.search('[a-z]', episode))): - #That means this is not a episode, it is a algo name - model_save_name = self.name +".pkl" + if (bool(re.search('[a-z]', episode))): + # That means this is not a episode, it is a algo name + model_save_name = self.name + ".pkl" else: model_save_name = self.name + '_' + episode + ".pkl" @@ -146,7 +146,7 @@ def save(self, save_path, _locals=None): def setLoadPath(self, load_path): """ - Load the only the parameters of the neuro-network model from a path + Set the path to later load the parameters of a trained rl model :param load_path: (str) :return: None """ @@ -167,13 +167,12 @@ def load(cls, load_path, args=None): loaded_model.__dict__ = {**loaded_model.__dict__, **save_param} episode = os.path.basename(load_path).split('_')[-2] - if(bool(re.search('[a-z]', episode))): - #That means this is not a episode, it is a algo name - model_save_name = loaded_model.name +".pkl" + if (bool(re.search('[a-z]', episode))): + # That means this is not a episode, it is a algo name + model_save_name = loaded_model.name + ".pkl" else: - model_save_name = loaded_model.name +'_' + episode + ".pkl" + model_save_name = loaded_model.name + '_' + episode + ".pkl" - print(model_save_name) loaded_model.model = loaded_model.model_class.load(os.path.dirname(load_path) + "/" + model_save_name) loaded_model.states = loaded_model.model.initial_state @@ -231,8 +230,9 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): """ if self.load_rl_model_path is not None: load_path_normalise = os.path.dirname(self.load_rl_model_path) - - envs = self.makeEnv(args, env_kwargs=env_kwargs,load_path_normalise=load_path_normalise) + envs = self.makeEnv(args, env_kwargs=env_kwargs,load_path_normalise=load_path_normalise) + else: + envs = self.makeEnv(args, env_kwargs=env_kwargs) if train_kwargs is None: train_kwargs = {} diff --git a/rl_baselines/cross_eval.py b/rl_baselines/cross_eval.py index 515b1fec8..4ad858895 100644 --- a/rl_baselines/cross_eval.py +++ b/rl_baselines/cross_eval.py @@ -19,14 +19,16 @@ def dict2array(tasks,data): :return: """ res=[] - print(data) for t in tasks: if(t=='sc'): max_reward=250 + min_reward = 0 else: - max_reward=1850 - data[t]=data[t].astype(float) - data[t][:,1:]=data[t][:,1:]/max_reward + max_reward = 1900 + min_reward = 0 + + data[t]=np.array(data[t]).astype(float) + data[t][:,1:]=(data[t][:,1:]-min_reward)/max_reward res.append(data[t]) res=np.array(res) return res @@ -94,40 +96,43 @@ def policyCrossEval(log_dir,task,episode,model_path, num_timesteps=2000,num_cpu= log_dir = args.log_dir #log_dir = 'logs/sc2cc/OmnirobotEnv-v0/srl_combination/ppo2/19-05-03_11h35_10/' - tasks=['sc'] episodes, policy_paths = allPolicyFiles(log_dir) index_to_begin =0 + + #To verify if the episodes have been evaluated before if(os.path.isfile(args.log_dir+'/eval.pkl')): with open(args.log_dir+'/eval.pkl', "rb") as file: rewards = pickle.load(file) - for e in range(len(episodes)): - if(episodes[e] not in rewards['episode']): - break; - index_to_begin = e - print(index_to_begin) + max_eps = max(np.array(rewards['episode']).astype(int)) + index_to_begin = episodes.astype(int).tolist().index(max_eps)+1 + else: task_labels = ['cc', 'sc'] rewards = {} - rewards['episode'] = episodes - rewards['policy'] = policy_paths + rewards['episode'] = [] + rewards['policy'] = [] + for t in ['cc', 'sc']: + rewards[t] = [] + - printRed(episodes[index_to_begin:]) for policy_path in policy_paths[index_to_begin:]: copyfile(log_dir+'/args.json', policy_path+'/args.json') copyfile(log_dir + '/env_globals.json', policy_path + '/env_globals.json') + printGreen("The evaluation will begin from {}".format(episodes[index_to_begin])) + last_mean = [250.,1900.] + run_mean = [0,0] - for t in ['cc','sc']: - rewards[t]=[] + for k in range(index_to_begin, len(episodes) ): + increase_interval = True - for k in range(len(episodes)): model_path=policy_paths[k] - for task_label in ["-sc", "-cc"]: + for t , task_label in enumerate(["-sc", "-cc"]): local_reward = [int(episodes[k])] @@ -149,7 +154,27 @@ def policyCrossEval(log_dir,task,episode,model_path, num_timesteps=2000,num_cpu= np.mean(seed_reward), episodes[k], seed_i, task_label)) rewards[task_label[1:]].append(local_reward) + run_mean[t] = np.mean(local_reward[1:]) + + + + # If one of the two mean rewards varies more thant 1%, then we do not increase the evaluation interval + for t in range(len(run_mean)): + if(run_mean[t] > 1.01 * last_mean[t] or run_mean[t] <0.99 *last_mean[t]): + increase_interval = False + + printGreen("Reward now: {}, last Rewards: {} for sc and cc respectively".format(run_mean, last_mean)) + # If the mean reward varies slowly, we increase the length of the evaluation interval + if (increase_interval): + current_eps = episodes[k] + k = k + 5 + printGreen("Reward at current episode {} varies slow, change to episode {} for next evaluation" + .format(current_eps, episodes[k])) + + last_mean = run_mean.copy() + rewards['episode'].append(int(episodes[k])) + rewards['policy'].append(model_path) with open(args.log_dir+'/eval.pkl', 'wb') as f: pickle.dump(rewards, f, pickle.HIGHEST_PROTOCOL) diff --git a/rl_baselines/evaluation/eval_post.py b/rl_baselines/evaluation/eval_post.py index 6788cb0a4..7bbaeab63 100644 --- a/rl_baselines/evaluation/eval_post.py +++ b/rl_baselines/evaluation/eval_post.py @@ -7,7 +7,7 @@ from rl_baselines.student_eval import allPolicy from srl_zoo.utils import printRed, printGreen -from rl_baselines.cross_eval_utils import EnvsKwargs, loadConfigAndSetup, policyEval,createEnv +from rl_baselines.evaluation.cross_eval_utils import EnvsKwargs, loadConfigAndSetup, policyEval,createEnv def dict2array(tasks,data): res=[] diff --git a/rl_baselines/student_eval.py b/rl_baselines/student_eval.py index 46bb9f371..2a6bac9cb 100644 --- a/rl_baselines/student_eval.py +++ b/rl_baselines/student_eval.py @@ -1,12 +1,13 @@ import argparse import datetime import glob -import json -import numpy as np import os import subprocess import time -# import yaml +import shutil + +import json +import numpy as np from environments.registry import registered_env from rl_baselines.evaluation.cross_eval_utils import loadConfigAndSetup, latestPolicy @@ -17,8 +18,8 @@ CL_LABEL_KEY = "continual_learning_label" -def DatasetGenerator(teacher_path, output_name, task_id, episode=-1, env_name='OmnirobotEnv-v0', num_cpu=1, - num_eps=200): +def OnPolicyDatasetGenerator(teacher_path, output_name, task_id, episode=-1, env_name='OmnirobotEnv-v0', num_cpu=1, + num_eps=200, test_mode=True): """ :param teacher_path: @@ -30,17 +31,19 @@ def DatasetGenerator(teacher_path, output_name, task_id, episode=-1, env_name='O :param num_eps: :return: """ - command_line = ['python', '-m', 'environments.dataset_generator_student', '--run-policy', 'custom'] + command_line = ['python', '-m', 'environments.dataset_generator', '--run-policy', 'custom'] cpu_command = ['--num-cpu', str(num_cpu)] name_command = ['--name', output_name] save_path = ['--save-path', "data/"] env_command = ['--env', env_name] task_command = ["-sc" if task_id == "SC" else '-cc'] if task_id == 'SC': - episode_command = ['--num-episode', str(400)] + episode_command = ['--num-episode', str(3 if test_mode else 400)] else: - episode_command = ['--num-episode', str(60)] - + episode_command = ['--num-episode', str(3 if test_mode else 60)] + print("teacher path: ", teacher_path) + if(os.path.exists('data/' + output_name + '/')): + shutil.rmtree('data/' + output_name + '/') policy_command = ['--log-custom-policy', teacher_path] if episode == -1: eps_policy = [] @@ -95,7 +98,6 @@ def allPolicyFiles(log_dir): printYellow(log_dir) files = glob.glob(log_dir + '/model_*') - files_list = [] for file in files: eps = int((file.split('_')[-1])) @@ -113,6 +115,7 @@ def sortFirst(val): res = np.array(files_list) return res[:, 0], res[:, 1] + def newPolicy(episodes, file_path): """ @@ -150,11 +153,22 @@ def trainStudent(teacher_data_path, task_id, yaml_file='config/srl_models.yaml', task_command = ["-sc" if task_id is "SC" else '-cc'] ok = subprocess.call(command_line + srl_command + env_command + policy_command + size_epochs + task_command + ['--srl-config-file', yaml_file]) + assert ok == 0 -def mergeData(teacher_dataset_1, teacher_dataset_2, merge_dataset): +def mergeData(teacher_dataset_1, teacher_dataset_2, merge_dataset, force=False): + """ + + :param teacher_dataset_1: + :param teacher_dataset_2: + :param merge_dataset: + :return: + """ merge_command = ['--merge', teacher_dataset_1, teacher_dataset_2, merge_dataset] - subprocess.call(['python', '-m', 'environments.dataset_fusioner'] + merge_command) + if force: + merge_command.append('-f') + ok = subprocess.call(['python', '-m', 'environments.dataset_merger'] + merge_command) + assert ok == 0 def main(): @@ -193,7 +207,6 @@ def main(): parser.add_argument('--eval-episode-window', type=int, default=400, metavar='N', help='Episode window for saving each policy checkpoint for future distillation(default: 100)') - args, unknown = parser.parse_known_args() if 'continual_learning_labels' in args: @@ -212,12 +225,6 @@ def main(): assert os.path.exists(args.log_dir_teacher_two), \ "Error: cannot load \"--srl-config-file {}\", file not found!".format(args.srl_config_file_two) - # with open(args.srl_config_file_one, 'rb') as f: - # model_one = yaml.load(f) - - # with open(args.srl_config_file_two, 'rb') as f: - # model_two = yaml.load(f) - teacher_pro = args.log_dir_teacher_one teacher_learn = args.log_dir_teacher_two @@ -232,14 +239,14 @@ def main(): rewards_at_episode = {} episodes_to_test = [e for e in episodes if (int(e) < 2000 and int(e) % 200 == 0) or (int(e) > 2000 and int(e) % 1000 == 0)] - #[e for e in episodes if int(e) % args.eval_episode_window == 0] # generate data from Professional teacher printYellow("\nGenerating on policy for optimal teacher: " + args.continual_learning_labels[0]) if not (args.log_dir_teacher_one == "None"): - DatasetGenerator(teacher_pro, args.continual_learning_labels[0] + '_copy/', task_id=args.continual_learning_labels[0], - num_eps=args.epochs_teacher_datasets, episode=-1, env_name=args.env) + OnPolicyDatasetGenerator(teacher_pro, args.continual_learning_labels[0] + '_copy/', + task_id=args.continual_learning_labels[0], num_eps=args.epochs_teacher_datasets, + episode=-1, env_name=args.env) print("Eval on eps list: ", episodes_to_test) for eps in episodes_to_test: student_path = args.log_dir_student @@ -250,12 +257,12 @@ def main(): ok = subprocess.call( ['cp', '-r', 'data/' + args.continual_learning_labels[0] + '_copy/', 'data/' + teacher_pro_data, '-f']) assert ok == 0 - time.sleep(10) + time.sleep(2) # Generate data from learning teacher - printYellow("\nGenerating on policy for optimal teacher: " + args.continual_learning_labels[1]) - DatasetGenerator(teacher_learn, teacher_learn_data, task_id=args.continual_learning_labels[1], episode=eps, - num_eps=args.epochs_teacher_datasets, env_name=args.env) + printYellow("\nGenerating on-policy data from the optimal teacher: " + args.continual_learning_labels[1]) + OnPolicyDatasetGenerator(teacher_learn, teacher_learn_data, task_id=args.continual_learning_labels[1], + episode=eps, num_eps=args.epochs_teacher_datasets, env_name=args.env) if args.log_dir_teacher_one == "None": merge_path = 'data/' + teacher_learn_data @@ -263,12 +270,12 @@ def main(): ['cp', '-r', merge_path, 'srl_zoo/data/', '-f']) else: # merge the data - mergeData('data/' + teacher_pro_data, 'data/' + teacher_learn_data, merge_path) + mergeData('data/' + teacher_pro_data, 'data/' + teacher_learn_data, merge_path,force=True) ok = subprocess.call( ['cp', '-r', 'data/on_policy_merged/', 'srl_zoo/data/', '-f']) assert ok == 0 - time.sleep(10) + time.sleep(2) # Train a policy with distillation on the merged teacher's datasets trainStudent('srl_zoo/' + merge_path, args.continual_learning_labels[1], yaml_file=args.srl_config_file_one, @@ -299,8 +306,8 @@ def main(): rewards_at_episode[eps] = rewards print("All rewards: ", rewards_at_episode) json_dict = json.dumps(rewards_at_episode) - json_dict_name = args.log_dir_student + "/reward_at_episode_" + \ - datetime.datetime.now().strftime("%y-%m-%d_%Hh%M_%S") + '.json' + json_dict_name = \ + args.log_dir_student + "/reward_at_episode_" + datetime.datetime.now().strftime("%y-%m-%d_%Hh%M_%S") + '.json' f = open(json_dict_name, "w") f.write(json_dict) f.close() diff --git a/rl_baselines/train.py b/rl_baselines/train.py index ee379d1a9..563bf2688 100644 --- a/rl_baselines/train.py +++ b/rl_baselines/train.py @@ -35,16 +35,16 @@ PLOT_TITLE = "" EPISODE_WINDOW = 40 # For plotting moving average EVAL_TASK=['cc','sc','sqc'] -CROSS_EVAL = False +CROSS_EVAL = True EPISODE_WINDOW_DISTILLATION_WIN = 20 -NEW_LR=0.01 +NEW_LR=0.001 viz = None n_steps = 0 SAVE_INTERVAL = 0 # initialised during loading of the algorithm N_EPISODES_EVAL = 100 # Evaluate the performance on the last 100 episodes -MIN_EPISODES_BEFORE_SAVE = 100 # Number of episodes to train on before saving best model +MIN_EPISODES_BEFORE_SAVE = 1000 # Number of episodes to train on before saving best model params_saved = False best_mean_reward = -10000 @@ -175,22 +175,24 @@ def callback(_locals, _globals): #For every checkpoint, we create one directory for saving logs file (policy and run mean std) if n_episodes % EPISODE_WINDOW_DISTILLATION_WIN == 0: - eps_path = LOG_DIR + "model_"+ str(n_episodes) - try: - os.mkdir(LOG_DIR + "model_"+ str(n_episodes)) - except OSError: - print("Creation of the directory {} failed".format(eps_path)) - - ALGO.save("{}/{}".format( eps_path, ALGO_NAME + "_model.pkl"), _locals) - try: - if 'env' in _locals: - _locals['env'].save_running_average(eps_path) - else: - _locals['self'].env.save_running_average(eps_path) - except AttributeError: - pass - if CROSS_EVAL: - episodeEval(LOG_DIR, EVAL_TASK) + ALGO.save(LOG_DIR + ALGO_NAME +'_' + str(n_episodes)+ "_model.pkl", _locals) + if(CROSS_EVAL):#If we want to do the cross evaluation after the training + eps_path = LOG_DIR + "model_"+ str(n_episodes) + try: + os.mkdir(LOG_DIR + "model_"+ str(n_episodes)) + except OSError: + print("Creation of the directory {} failed".format(eps_path)) + + ALGO.save("{}/{}".format( eps_path, ALGO_NAME + "_model.pkl"), _locals) + try: + if 'env' in _locals: + _locals['env'].save_running_average(eps_path) + else: + _locals['self'].env.save_running_average(eps_path) + except AttributeError: + pass + # if CROSS_EVAL: + # episodeEval(LOG_DIR, EVAL_TASK) # Plots in visdom if viz and (n_steps + 1) % LOG_INTERVAL == 0: @@ -199,9 +201,9 @@ def callback(_locals, _globals): is_es=is_es) win_episodes = episodePlot(viz, win_episodes, LOG_DIR, ENV_NAME, ALGO_NAME, window=EPISODE_WINDOW, title=PLOT_TITLE + " [Episodes]", is_es=is_es) - if CROSS_EVAL: - win_crossEval= episodesEvalPlot(viz,win_crossEval,LOG_DIR,ENV_NAME,EVAL_TASK, - title=PLOT_TITLE + " [Cross Evaluation]") + # if CROSS_EVAL: + # win_crossEval= episodesEvalPlot(viz,win_crossEval,LOG_DIR,ENV_NAME,EVAL_TASK, + # title=PLOT_TITLE + " [Cross Evaluation]") n_steps += 1 return True @@ -216,7 +218,7 @@ def main(): parser.add_argument('--env', type=str, help='environment ID', default='KukaButtonGymEnv-v0', choices=list(registered_env.keys())) parser.add_argument('--seed', type=int, default=0, help='random seed (default: 0)') - parser.add_argument('--episode_window', type=int, default=40, + parser.add_argument('--episode-window', type=int, default=40, help='Episode window for moving average plot (default: 40)') parser.add_argument('--log-dir', default='/tmp/gym/', type=str, help='directory to save agent logs and model (default: /tmp/gym)') diff --git a/tests/test_eval.py b/tests/test_eval.py new file mode 100644 index 000000000..cd3578d15 --- /dev/null +++ b/tests/test_eval.py @@ -0,0 +1,166 @@ +from __future__ import print_function, division, absolute_import + +import subprocess +import shutil +import pytest +import os +from environments import ThreadingType +from environments.registry import registered_env + +DEFAULT_ALGO = "ppo2" +DEFAULT_SRL = "raw_pixels" +NUM_ITERATION = 1 +NUM_TIMESTEP = 251 # this should be long enough to call a reset of the environment +SEED = 0 +DEFAULT_ENV = "OmnirobotEnv-v0" +DEFAULT_LOG = "logs/test_eval/" +EPOCH_DATA = 2 +EPISODE_WINS =40 +DIR_STUDENT = 'logs/test_students/' +EPOCH_DISTILLATION = 5 +def assertEq(left, right): + assert left == right, "{} != {}".format(left, right) + +# @pytest.mark.fast +# @pytest.mark.parametrize("task", ['-sc','-cc']) +# def testCrossEval(task): +# #Evaluation for the policy on different tasks +# # Long enough to save one policy model +# +# num_timesteps = 10000 +# args = ['--algo', DEFAULT_ALGO, '--srl-model', DEFAULT_SRL, +# '--num-timesteps', num_timesteps, '--seed', SEED, '--no-vis', +# '--episode-window', EPISODE_WINS, +# '--env', DEFAULT_ENV, '--log-dir', DEFAULT_LOG , task, +# '--min-episodes-save', 0] +# +# args = list(map(str, args)) +# #We firstly train a policy to have some checkpoint to evaluate +# ok = subprocess.call(['python', '-m', 'rl_baselines.train'] + args) +# assertEq(ok, 0) +# eval_path = DEFAULT_LOG +# for i in range(4): # Go into the folder that contains the policy file +# eval_path += os.listdir(eval_path)[-1] + '/' +# +# args= ['--log-dir', eval_path, '--num-iteration', str(NUM_ITERATION)] +# ok = subprocess.call(['python', '-m', 'rl_baselines.cross_eval'] + args) +# assertEq(ok, 0) +# +# #Remove test files +# shutil.rmtree(DEFAULT_LOG) + +@pytest.mark.fast +@pytest.mark.parametrize("tasks", [['-cc','-sc']]) +def testStudentEval(tasks,teacher_folder_one='logs/teacher_one/', teacher_folder_two='logs/teacher_two/' ): + + + teacher_args_one = ['--algo', DEFAULT_ALGO, '--srl-model', DEFAULT_SRL, + '--num-timesteps', NUM_TIMESTEP, '--seed', SEED, '--no-vis', + '--episode-window', EPISODE_WINS, + '--env', DEFAULT_ENV, '--log-dir', teacher_folder_one , tasks[0], + '--min-episodes-save', 0] + + teacher_args_one = list(map(str, teacher_args_one)) + + teacher_args_two = ['--algo', DEFAULT_ALGO, '--srl-model', DEFAULT_SRL, + '--num-timesteps', NUM_TIMESTEP, '--seed', SEED, '--no-vis', + '--episode-window', EPISODE_WINS, + '--env', DEFAULT_ENV, '--log-dir', teacher_folder_two , tasks[1]] + teacher_args_two = list(map(str, teacher_args_two)) + + ok = subprocess.call(['python', '-m', 'rl_baselines.train'] + teacher_args_one) + assertEq(ok, 0) + ok = subprocess.call(['python', '-m', 'rl_baselines.train'] + teacher_args_two) + assertEq(ok, 0) + + folder2remove = [teacher_folder_one, teacher_folder_two] + + for i in range(4):#Go into the folder that contains the policy file + teacher_folder_two += os.listdir(teacher_folder_two)[-1] + '/' + teacher_folder_one += os.listdir(teacher_folder_one)[-1] + '/' + + + #Distillation part + args = ['--num-iteration', NUM_ITERATION, '--epochs-teacher-datasets', EPOCH_DATA, + '--env', DEFAULT_ENV, '--log-dir-student', DIR_STUDENT, + '--log-dir-teacher-one', teacher_folder_one,'--log-dir-teacher-two', teacher_folder_two, + '--epochs-distillation', EPOCH_DISTILLATION] + if(tasks ==['-cc','-sc']): + args+=['--srl-config-file-one', 'config/srl_models_circular.yaml', + '--srl-config-file-two','config/srl_models_simple.yaml', + '--continual-learning-labels', 'CC', 'SC'] + + else: + args += ['--srl-config-file-one', 'config/srl_models_simple.yaml', + '--srl-config-file-two', 'config/srl_models_circular.yaml', + '--continual-learning-labels', 'SC', 'CC'] + + args = list(map(str, args)) + ok = subprocess.call(['python', '-m', 'rl_baselines.student_eval'] + args) + assertEq(ok, 0) + for i in range(10): + print("OK 1 ") + #Remove test files + shutil.rmtree(folder2remove[0]) + shutil.rmtree(folder2remove[1]) + shutil.rmtree(DIR_STUDENT) + for i in range(10): + print("test finished") +# +# +# @pytest.mark.slow +# @pytest.mark.parametrize("algo", ['a2c', 'acer', 'ars', 'cma-es', 'ddpg', 'deepq', 'ppo1', 'ppo2', 'random_agent', +# 'sac', 'trpo']) +# @pytest.mark.parametrize("tasks", [['-cc','-sc'],['-cc', '-sc']]) +# def testStudentEvalAlgo(tasks,algo): +# teacher_folder_one = 'logs/teacher_one/' +# teacher_folder_two = 'logs/teacher_two/' +# +# teacher_args_one = ['--algo', algo, '--srl-model', DEFAULT_SRL, +# '--num-timesteps', NUM_TIMESTEP, '--seed', SEED, '--no-vis', +# '--episode-window', EPISODE_WINS, +# '--env', DEFAULT_ENV, '--log-dir', teacher_folder_one , tasks[0], +# '--min-episodes-save', 0] +# +# teacher_args_one = list(map(str, teacher_args_one)) +# +# teacher_args_two = ['--algo', algo, '--srl-model', DEFAULT_SRL, +# '--num-timesteps', NUM_TIMESTEP, '--seed', SEED, '--no-vis', +# '--episode-window', EPISODE_WINS, +# '--env', DEFAULT_ENV, '--log-dir', teacher_folder_two , tasks[1]] +# teacher_args_two = list(map(str, teacher_args_two)) +# +# ok = subprocess.call(['python', '-m', 'rl_baselines.train'] + teacher_args_one) +# assertEq(ok, 0) +# ok = subprocess.call(['python', '-m', 'rl_baselines.train'] + teacher_args_two) +# assertEq(ok, 0) +# +# folder2remove = [teacher_folder_one, teacher_folder_one] +# +# for i in range(4):#Go into the folder that contains the policy file +# teacher_folder_two += os.listdir(teacher_folder_two)[-1] + '/' +# teacher_folder_one += os.listdir(teacher_folder_one)[-1] + '/' +# +# +# args = ['--num-iteration', NUM_ITERATION, '--epochs-teacher-datasets', EPOCH_DATA, +# '--env', DEFAULT_ENV, '--log-dir-student', DIR_STUDENT, +# '--log-dir-teacher-one', teacher_folder_one,'--log-dir-teacher-two', teacher_folder_two, +# '--epochs-distillation', 5] +# if(tasks ==['-cc','-sc']): +# args+=['--srl-config-file-one', 'config/srl_models_circular.yaml', +# '--srl-config-file-two','config/srl_models_simple.yaml', +# '--continual-learning-labels', 'CC', 'SC'] +# +# else: +# args += ['--srl-config-file-one', 'config/srl_models_simple.yaml', +# '--srl-config-file-two', 'config/srl_models_circular.yaml', +# '--continual-learning-labels', 'SC', 'CC'] +# +# args = list(map(str, args)) +# ok = subprocess.call(['python', '-m', 'rl_baselines.student_eval'] + args) +# assertEq(ok, 0) +# +# #Remove test files +# shutil.rmtree(folder2remove[0]) +# shutil.rmtree(folder2remove[1]) +# shutil.rmtree(DIR_STUDENT) From bac57cebd008d35fb2bf1a25ce8b0677a0b22fc0 Mon Sep 17 00:00:00 2001 From: sun-te Date: Fri, 10 May 2019 15:29:24 +0200 Subject: [PATCH 100/141] dataset generator update --- environments/dataset_generator_student.py | 464 ---------------------- 1 file changed, 464 deletions(-) delete mode 100644 environments/dataset_generator_student.py diff --git a/environments/dataset_generator_student.py b/environments/dataset_generator_student.py deleted file mode 100644 index d168392ef..000000000 --- a/environments/dataset_generator_student.py +++ /dev/null @@ -1,464 +0,0 @@ -from __future__ import division, absolute_import, print_function - -import argparse -import glob -import multiprocessing -import os -import shutil -import tensorflow as tf -import time -import torch as th -from torch.autograd import Variable - -import numpy as np -from stable_baselines import PPO2 -from stable_baselines.common import set_global_seeds -from stable_baselines.common.vec_env import DummyVecEnv, VecNormalize -from stable_baselines.common.policies import CnnPolicy - -from environments import ThreadingType -from environments.registry import registered_env -from replay.enjoy_baselines import createEnv, loadConfigAndSetup -from rl_baselines.utils import MultiprocessSRLModel -from srl_zoo.utils import printRed, printYellow -from srl_zoo.preprocessing.utils import deNormalize -from state_representation.models import loadSRLModel, getSRLDim -from rl_baselines.registry import registered_rl -import json -from rl_baselines import AlgoType - -RENDER_HEIGHT = 224 -RENDER_WIDTH = 224 -VALID_MODELS = ["forward", "inverse", "reward", "priors", "episode-prior", "reward-prior", "triplet", - "autoencoder", "vae", "dae", "random"] - -os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' # used to remove debug info of tensorflow - - - -def loadConfigAndSetup(load_args): - """ - Get the training config and setup the parameters - :param load_args: (Arguments) - :return: (dict, str, str, str, dict) - """ - algo_name = "" - for algo in list(registered_rl.keys()): - if algo in load_args.log_dir: - algo_name = algo - break - algo_class, algo_type, _ = registered_rl[algo_name] - if algo_type == AlgoType.OTHER: - raise ValueError(algo_name + " is not supported for replay") - if not load_args.episode ==-1: - load_path = "{}/{}_{}_model.pkl".format(load_args.log_dir, algo_name,load_args.episode,) - else: - load_path = "{}/{}_model.pkl".format(load_args.log_dir, algo_name) - - env_globals = json.load(open(load_args.log_dir + "env_globals.json", 'r')) - train_args = json.load(open(load_args.log_dir + "args.json", 'r')) - - env_kwargs = { - "renders": load_args.render, - "shape_reward": load_args.shape_reward, # Reward sparse or shaped - "action_joints": train_args["action_joints"], - "is_discrete": not train_args["continuous_actions"], - "random_target": train_args.get('random_target', False), - "srl_model": train_args["srl_model"] - } - - # load it, if it was defined - if "action_repeat" in env_globals: - env_kwargs["action_repeat"] = env_globals['action_repeat'] - - # Remove up action - if train_args["env"] == "Kuka2ButtonGymEnv-v0": - env_kwargs["force_down"] = env_globals.get('force_down', True) - else: - env_kwargs["force_down"] = env_globals.get('force_down', False) - - if train_args["env"] == "OmnirobotEnv-v0": - env_kwargs["simple_continual_target"] = env_globals.get("simple_continual_target", False) - env_kwargs["circular_continual_move"] = env_globals.get("circular_continual_move", False) - env_kwargs["square_continual_move"] = env_globals.get("square_continual_move", False) - env_kwargs["eight_continual_move"] = env_globals.get("eight_continual_move", False) - - if sum([load_args.simple_continual, load_args.circular_continual, load_args.square_continual]) >= 1: - env_kwargs["simple_continual_target"] = load_args.simple_continual - env_kwargs["circular_continual_move"] = load_args.circular_continual - env_kwargs["square_continual_move"] = load_args.square_continual - env_kwargs["random_target"] = not (load_args.circular_continual or load_args.square_continual) - - srl_model_path = None - if train_args["srl_model"] != "raw_pixels": - train_args["policy"] = "mlp" - path = env_globals.get('srl_model_path') - - if path is not None: - env_kwargs["use_srl"] = True - # Check that the srl saved model exists on the disk - assert os.path.isfile(env_globals['srl_model_path']), "{} does not exist".format(env_globals['srl_model_path']) - srl_model_path = env_globals['srl_model_path'] - env_kwargs["srl_model_path"] = srl_model_path - - return train_args, load_path, algo_name, algo_class, srl_model_path, env_kwargs - - -def convertImagePath(args, path, record_id_start): - """ - Used to convert an image path, from one location, to another - :param args: (ArgumentParser object) - :param path: (str) - :param record_id_start: (int) where does the current part start counting its records - :return: - """ - image_name = path.split("/")[-1] - # get record id for output, by adding the current offset with the record_id - # of the folder - new_record_id = record_id_start + int(path.split("/")[-2].split("_")[-1]) - return args.name + "/record_{:03d}".format(new_record_id) + "/" + image_name - - -def vecEnv(env_kwargs_local, env_class): - """ - Local Env Wrapper - :param env_kwargs_local: arguments related to the environment wrapper - :param env_class: class of the env - :return: env for the pretrained algo - """ - train_env = env_class(**{**env_kwargs_local, "record_data": False, "renders": False}) - train_env = DummyVecEnv([lambda: train_env]) - train_env = VecNormalize(train_env, norm_obs=True, norm_reward=False) - return train_env - - -def env_thread(args, thread_num, partition=True): - """ - Run a session of an environment - :param args: (ArgumentParser object) - :param thread_num: (int) The thread ID of the environment session - :param partition: (bool) If the output should be in multiple parts (default=True) - """ - env_kwargs = { - "max_distance": args.max_distance, - "random_target": args.random_target, - "force_down": True, - "is_discrete": not args.continuous_actions, - "renders": thread_num == 0 and args.display, - "record_data": not args.no_record_data, - "multi_view": args.multi_view, - "save_path": args.save_path, - "shape_reward": args.shape_reward, - "simple_continual_target": args.simple_continual, - "circular_continual_move": args.circular_continual, - "square_continual_move": args.square_continual, - "short_episodes": args.short_episodes - } - - if partition: - env_kwargs["name"] = args.name + "_part-" + str(thread_num) - else: - env_kwargs["name"] = args.name - - load_path, train_args, algo_name, algo_class = None, None, None, None - model = None - srl_model = None - srl_state_dim = 0 - generated_obs = None - - if args.run_policy == "custom": - args.log_dir = args.log_custom_policy - args.render = args.display - args.plotting, args.action_proba = False, False - - train_args, load_path, algo_name, algo_class, _, env_kwargs_extra = loadConfigAndSetup(args) - env_kwargs["srl_model"] = env_kwargs_extra["srl_model"] - env_kwargs["random_target"] = env_kwargs_extra.get("random_target", False) - env_kwargs["use_srl"] = env_kwargs_extra.get("use_srl", False) - if env_kwargs["use_srl"]: - env_kwargs["srl_model_path"] = env_kwargs_extra.get("srl_model_path", None) - env_kwargs["state_dim"] = getSRLDim(env_kwargs_extra.get("srl_model_path", None)) - srl_model = MultiprocessSRLModel(args.num_cpu, args.env, env_kwargs) - env_kwargs["srl_pipe"] = srl_model.pipe - - env_class = registered_env[args.env][0] - env = env_class(**env_kwargs) - - if args.run_policy in ['custom', 'ppo2']: - - # Additional env when using a trained agent to generate data - train_env = vecEnv(env_kwargs, env_class) - - if args.run_policy == 'ppo2': - model = PPO2(CnnPolicy, train_env).learn(args.ppo2_timesteps) - else: - _, _, algo_args = createEnv(args, train_args, algo_name, algo_class, env_kwargs) - tf.reset_default_graph() - set_global_seeds(args.seed) - printYellow("Compiling Policy function....") - model = algo_class.load(load_path, args=algo_args) - - if len(args.replay_generative_model) > 0: - srl_model = loadSRLModel(args.log_generative_model, th.cuda.is_available()) - srl_state_dim = srl_model.state_dim - srl_model = srl_model.model.model - - frames = 0 - start_time = time.time() - # divide evenly, then do an extra one for only some of them in order to get the right count - for i_episode in range(args.num_episode // args.num_cpu + 1 * (args.num_episode % args.num_cpu > thread_num)): - # seed + position in this slice + size of slice (with reminder if uneven partitions) - seed = args.seed + i_episode + args.num_episode // args.num_cpu * thread_num + \ - (thread_num if thread_num <= args.num_episode % args.num_cpu else args.num_episode % args.num_cpu) - - if not args.run_policy == 'custom': - env.seed(seed) - env.action_space.seed(seed) # this is for the sample() function from gym.space - - if len(args.replay_generative_model) > 0: - - sample = Variable(th.randn(1, srl_state_dim)) - if th.cuda.is_available(): - sample = sample.cuda() - - generated_obs = srl_model.decode(sample) - generated_obs = generated_obs[0].detach().cpu().numpy().transpose(1, 2, 0) - generated_obs = deNormalize(generated_obs) - - obs = env.reset(generated_observation=generated_obs) - done = False - action_proba = None - t = 0 - episode_toward_target_on = False - - while not done: - - env.render() - if args.run_policy == 'ppo2': - action, _ = model.predict([obs]) - - elif args.run_policy == 'custom': - action = [model.getAction(obs, done)] - action_proba = model.getActionProba(obs, done) - - else: - if episode_toward_target_on and np.random.rand() < args.toward_target_timesteps_proportion: - action = [env.actionPolicyTowardTarget()] - else: - action = [env.action_space.sample()] - - if len(args.replay_generative_model) > 0: - - sample = Variable(th.randn(1, srl_state_dim)) - - if th.cuda.is_available(): - sample = sample.cuda() - - generated_obs = srl_model.decode(sample) - generated_obs = generated_obs[0].detach().cpu().numpy().transpose(1, 2, 0) - generated_obs = deNormalize(generated_obs) - - action_to_step = action[0] - - obs, _, done, _ = env.step(action_to_step, generated_observation=generated_obs, action_proba=action_proba) - - frames += 1 - t += 1 - if done: - - if np.random.rand() < args.toward_target_timesteps_proportion: - episode_toward_target_on = True - else: - episode_toward_target_on = False - print("Episode finished after {} timesteps".format(t + 1)) - - if thread_num == 0: - print("{:.2f} FPS".format(frames * args.num_cpu / (time.time() - start_time))) - - -def main(): - parser = argparse.ArgumentParser(description='Deteministic dataset generator for SRL training ' + - '(can be used for environment testing)') - parser.add_argument('--num-cpu', type=int, default=1, help='number of cpu to run on') - parser.add_argument('--num-episode', type=int, default=50, help='number of episode to run') - parser.add_argument('--save-path', type=str, default='srl_zoo/data/', - help='Folder where the environments will save the output') - parser.add_argument('--name', type=str, default='kuka_button', help='Folder name for the output') - parser.add_argument('--env', type=str, default='KukaButtonGymEnv-v0', help='The environment wanted', - choices=list(registered_env.keys())) - parser.add_argument('--display', action='store_true', default=False) - parser.add_argument('--no-record-data', action='store_true', default=False) - parser.add_argument('--max-distance', type=float, default=0.28, - help='Beyond this distance from the goal, the agent gets a negative reward') - parser.add_argument('-c', '--continuous-actions', action='store_true', default=False) - parser.add_argument('--seed', type=int, default=0, help='the seed') - parser.add_argument('-f', '--force', action='store_true', default=False, - help='Force the save, even if it overrides something else,' + - ' including partial parts if they exist') - parser.add_argument('-r', '--random-target', action='store_true', default=False, - help='Set the button to a random position') - parser.add_argument('--multi-view', action='store_true', default=False, help='Set a second camera to the scene') - parser.add_argument('--shape-reward', action='store_true', default=False, - help='Shape the reward (reward = - distance) instead of a sparse reward') - parser.add_argument('--reward-dist', action='store_true', default=False, - help='Prints out the reward distribution when the dataset generation is finished') - parser.add_argument('--run-policy', type=str, default="random", - choices=['random', 'ppo2', 'custom'], - help='Policy to run for data collection ' + - '(random, localy pretrained ppo2, pretrained custom policy)') - parser.add_argument('--log-custom-policy', type=str, default='', - help='Logs of the custom pretained policy to run for data collection') - parser.add_argument('-rgm', '--replay-generative-model', type=str, default="", choices=['vae'], - help='Generative model to replay for generating a dataset (for Continual Learning purposes)') - parser.add_argument('--log-generative-model', type=str, default='', - help='Logs of the custom pretained policy to run for data collection') - parser.add_argument('--ppo2-timesteps', type=int, default=1000, - help='number of timesteps to run PPO2 on before generating the dataset') - parser.add_argument('--toward-target-timesteps-proportion', type=float, default=0.0, - help="propotion of timesteps that use simply towards target policy, should be 0.0 to 1.0") - parser.add_argument('-sc', '--simple-continual', action='store_true', default=False, - help='Simple red square target for task 1 of continual learning scenario. ' + - 'The task is: robot should reach the target.') - parser.add_argument('-cc', '--circular-continual', action='store_true', default=False, - help='Blue square target for task 2 of continual learning scenario. ' + - 'The task is: robot should turn in circle around the target.') - parser.add_argument('-sqc', '--square-continual', action='store_true', default=False, - help='Green square target for task 3 of continual learning scenario. ' + - 'The task is: robot should turn in square around the target.') - parser.add_argument('--short-episodes', action='store_true', default=False, - help='Generate short episodes (only 10 contacts with the target allowed).') - parser.add_argument('--episode', type=int, default=-1, - help='Model saved at episode N that we want to load') - - args = parser.parse_args() - - assert (args.num_cpu > 0), "Error: number of cpu must be positive and non zero" - assert (args.max_distance > 0), "Error: max distance must be positive and non zero" - assert (args.num_episode > 0), "Error: number of episodes must be positive and non zero" - assert not args.reward_dist or not args.shape_reward, \ - "Error: cannot display the reward distribution for continuous reward" - assert not(registered_env[args.env][3] is ThreadingType.NONE and args.num_cpu != 1), \ - "Error: cannot have more than 1 CPU for the environment {}".format(args.env) - if args.num_cpu > args.num_episode: - args.num_cpu = args.num_episode - printYellow("num_cpu cannot be greater than num_episode, defaulting to {} cpus.".format(args.num_cpu)) - - assert sum([args.simple_continual, args.circular_continual, args.square_continual]) <= 1, \ - "For continual SRL and RL, please provide only one scenario at the time !" - - assert not (args.log_custom_policy == '' and args.run_policy == 'custom'), \ - "If using a custom policy, please specify a valid log folder for loading it." - - assert not (args.log_generative_model == '' and args.replay_generative_model == 'custom'), \ - "If using a custom policy, please specify a valid log folder for loading it." - - # this is done so seed 0 and 1 are different and not simply offset of the same datasets. - args.seed = np.random.RandomState(args.seed).randint(int(1e10)) - - # File exists, need to deal with it - if not args.no_record_data and os.path.exists(args.save_path + args.name): - assert args.force, "Error: save directory '{}' already exists".format(args.save_path + args.name) - - shutil.rmtree(args.save_path + args.name) - for part in glob.glob(args.save_path + args.name + "_part-[0-9]*"): - shutil.rmtree(part) - if not args.no_record_data: - # create the output - os.mkdir(args.save_path + args.name) - - if args.num_cpu == 1: - env_thread(args, 0, partition=False) - else: - # try and divide into multiple processes, with an environment each - try: - jobs = [] - for i in range(args.num_cpu): - process = multiprocessing.Process(target=env_thread, args=(args, i, True)) - jobs.append(process) - - for j in jobs: - j.start() - - try: - for j in jobs: - j.join() - except Exception as e: - printRed("Error: unable to join thread") - raise e - - except Exception as e: - printRed("Error: unable to start thread") - raise e - - if not args.no_record_data and args.num_cpu > 1: - # sleep 1 second, to avoid congruency issues from multiprocess (eg., files still writing) - time.sleep(1) - # get all the parts - file_parts = sorted(glob.glob(args.save_path + args.name + "_part-[0-9]*"), key=lambda a: int(a.split("-")[-1])) - - # move the config files from any as they are identical - os.rename(file_parts[0] + "/dataset_config.json", args.save_path + args.name + "/dataset_config.json") - os.rename(file_parts[0] + "/env_globals.json", args.save_path + args.name + "/env_globals.json") - - ground_truth = None - preprocessed_data = None - - # used to convert the part record_id to the fused record_id - record_id = 0 - for part in file_parts: - # sort the record names alphabetically, then numerically - records = sorted(glob.glob(part + "/record_[0-9]*"), key=lambda a: int(a.split("_")[-1])) - - record_id_start = record_id - for record in records: - os.renames(record, args.save_path + args.name + "/record_{:03d}".format(record_id)) - record_id += 1 - - # fuse the npz files together, in the right order - if ground_truth is None: - # init - ground_truth = {} - preprocessed_data = {} - ground_truth_load = np.load(part + "/ground_truth.npz") - preprocessed_data_load = np.load(part + "/preprocessed_data.npz") - - for arr in ground_truth_load.files: - if arr == "images_path": - ground_truth[arr] = np.array( - [convertImagePath(args, path, record_id_start) for path in ground_truth_load[arr]]) - else: - ground_truth[arr] = ground_truth_load[arr] - for arr in preprocessed_data_load.files: - preprocessed_data[arr] = preprocessed_data_load[arr] - - else: - ground_truth_load = np.load(part + "/ground_truth.npz") - preprocessed_data_load = np.load(part + "/preprocessed_data.npz") - - for arr in ground_truth_load.files: - if arr == "images_path": - sanitised_paths = np.array( - [convertImagePath(args, path, record_id_start) for path in ground_truth_load[arr]]) - ground_truth[arr] = np.concatenate((ground_truth[arr], sanitised_paths)) - else: - ground_truth[arr] = np.concatenate((ground_truth[arr], ground_truth_load[arr])) - for arr in preprocessed_data_load.files: - preprocessed_data[arr] = np.concatenate((preprocessed_data[arr], preprocessed_data_load[arr])) - - # remove the current part folder - shutil.rmtree(part) - - # save the fused outputs - np.savez(args.save_path + args.name + "/ground_truth.npz", **ground_truth) - np.savez(args.save_path + args.name + "/preprocessed_data.npz", **preprocessed_data) - - if args.reward_dist: - rewards, counts = np.unique(np.load(args.save_path + args.name + "/preprocessed_data.npz")['rewards'], - return_counts=True) - counts = ["{:.2f}%".format(val * 100) for val in counts / np.sum(counts)] - print("reward distribution:") - [print(" ", reward, count) for reward, count in list(zip(rewards, counts))] - - -if __name__ == '__main__': - main() From 80c01ae6afb4bf7878bf630f113d8242023d8ef9 Mon Sep 17 00:00:00 2001 From: kalifou Date: Tue, 21 May 2019 23:28:47 +0200 Subject: [PATCH 101/141] update tests for distillation --- environments/dataset_generator_student.py | 464 ---------------------- tests/test_distillation_pipeline.py | 13 +- 2 files changed, 7 insertions(+), 470 deletions(-) delete mode 100644 environments/dataset_generator_student.py diff --git a/environments/dataset_generator_student.py b/environments/dataset_generator_student.py deleted file mode 100644 index d168392ef..000000000 --- a/environments/dataset_generator_student.py +++ /dev/null @@ -1,464 +0,0 @@ -from __future__ import division, absolute_import, print_function - -import argparse -import glob -import multiprocessing -import os -import shutil -import tensorflow as tf -import time -import torch as th -from torch.autograd import Variable - -import numpy as np -from stable_baselines import PPO2 -from stable_baselines.common import set_global_seeds -from stable_baselines.common.vec_env import DummyVecEnv, VecNormalize -from stable_baselines.common.policies import CnnPolicy - -from environments import ThreadingType -from environments.registry import registered_env -from replay.enjoy_baselines import createEnv, loadConfigAndSetup -from rl_baselines.utils import MultiprocessSRLModel -from srl_zoo.utils import printRed, printYellow -from srl_zoo.preprocessing.utils import deNormalize -from state_representation.models import loadSRLModel, getSRLDim -from rl_baselines.registry import registered_rl -import json -from rl_baselines import AlgoType - -RENDER_HEIGHT = 224 -RENDER_WIDTH = 224 -VALID_MODELS = ["forward", "inverse", "reward", "priors", "episode-prior", "reward-prior", "triplet", - "autoencoder", "vae", "dae", "random"] - -os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' # used to remove debug info of tensorflow - - - -def loadConfigAndSetup(load_args): - """ - Get the training config and setup the parameters - :param load_args: (Arguments) - :return: (dict, str, str, str, dict) - """ - algo_name = "" - for algo in list(registered_rl.keys()): - if algo in load_args.log_dir: - algo_name = algo - break - algo_class, algo_type, _ = registered_rl[algo_name] - if algo_type == AlgoType.OTHER: - raise ValueError(algo_name + " is not supported for replay") - if not load_args.episode ==-1: - load_path = "{}/{}_{}_model.pkl".format(load_args.log_dir, algo_name,load_args.episode,) - else: - load_path = "{}/{}_model.pkl".format(load_args.log_dir, algo_name) - - env_globals = json.load(open(load_args.log_dir + "env_globals.json", 'r')) - train_args = json.load(open(load_args.log_dir + "args.json", 'r')) - - env_kwargs = { - "renders": load_args.render, - "shape_reward": load_args.shape_reward, # Reward sparse or shaped - "action_joints": train_args["action_joints"], - "is_discrete": not train_args["continuous_actions"], - "random_target": train_args.get('random_target', False), - "srl_model": train_args["srl_model"] - } - - # load it, if it was defined - if "action_repeat" in env_globals: - env_kwargs["action_repeat"] = env_globals['action_repeat'] - - # Remove up action - if train_args["env"] == "Kuka2ButtonGymEnv-v0": - env_kwargs["force_down"] = env_globals.get('force_down', True) - else: - env_kwargs["force_down"] = env_globals.get('force_down', False) - - if train_args["env"] == "OmnirobotEnv-v0": - env_kwargs["simple_continual_target"] = env_globals.get("simple_continual_target", False) - env_kwargs["circular_continual_move"] = env_globals.get("circular_continual_move", False) - env_kwargs["square_continual_move"] = env_globals.get("square_continual_move", False) - env_kwargs["eight_continual_move"] = env_globals.get("eight_continual_move", False) - - if sum([load_args.simple_continual, load_args.circular_continual, load_args.square_continual]) >= 1: - env_kwargs["simple_continual_target"] = load_args.simple_continual - env_kwargs["circular_continual_move"] = load_args.circular_continual - env_kwargs["square_continual_move"] = load_args.square_continual - env_kwargs["random_target"] = not (load_args.circular_continual or load_args.square_continual) - - srl_model_path = None - if train_args["srl_model"] != "raw_pixels": - train_args["policy"] = "mlp" - path = env_globals.get('srl_model_path') - - if path is not None: - env_kwargs["use_srl"] = True - # Check that the srl saved model exists on the disk - assert os.path.isfile(env_globals['srl_model_path']), "{} does not exist".format(env_globals['srl_model_path']) - srl_model_path = env_globals['srl_model_path'] - env_kwargs["srl_model_path"] = srl_model_path - - return train_args, load_path, algo_name, algo_class, srl_model_path, env_kwargs - - -def convertImagePath(args, path, record_id_start): - """ - Used to convert an image path, from one location, to another - :param args: (ArgumentParser object) - :param path: (str) - :param record_id_start: (int) where does the current part start counting its records - :return: - """ - image_name = path.split("/")[-1] - # get record id for output, by adding the current offset with the record_id - # of the folder - new_record_id = record_id_start + int(path.split("/")[-2].split("_")[-1]) - return args.name + "/record_{:03d}".format(new_record_id) + "/" + image_name - - -def vecEnv(env_kwargs_local, env_class): - """ - Local Env Wrapper - :param env_kwargs_local: arguments related to the environment wrapper - :param env_class: class of the env - :return: env for the pretrained algo - """ - train_env = env_class(**{**env_kwargs_local, "record_data": False, "renders": False}) - train_env = DummyVecEnv([lambda: train_env]) - train_env = VecNormalize(train_env, norm_obs=True, norm_reward=False) - return train_env - - -def env_thread(args, thread_num, partition=True): - """ - Run a session of an environment - :param args: (ArgumentParser object) - :param thread_num: (int) The thread ID of the environment session - :param partition: (bool) If the output should be in multiple parts (default=True) - """ - env_kwargs = { - "max_distance": args.max_distance, - "random_target": args.random_target, - "force_down": True, - "is_discrete": not args.continuous_actions, - "renders": thread_num == 0 and args.display, - "record_data": not args.no_record_data, - "multi_view": args.multi_view, - "save_path": args.save_path, - "shape_reward": args.shape_reward, - "simple_continual_target": args.simple_continual, - "circular_continual_move": args.circular_continual, - "square_continual_move": args.square_continual, - "short_episodes": args.short_episodes - } - - if partition: - env_kwargs["name"] = args.name + "_part-" + str(thread_num) - else: - env_kwargs["name"] = args.name - - load_path, train_args, algo_name, algo_class = None, None, None, None - model = None - srl_model = None - srl_state_dim = 0 - generated_obs = None - - if args.run_policy == "custom": - args.log_dir = args.log_custom_policy - args.render = args.display - args.plotting, args.action_proba = False, False - - train_args, load_path, algo_name, algo_class, _, env_kwargs_extra = loadConfigAndSetup(args) - env_kwargs["srl_model"] = env_kwargs_extra["srl_model"] - env_kwargs["random_target"] = env_kwargs_extra.get("random_target", False) - env_kwargs["use_srl"] = env_kwargs_extra.get("use_srl", False) - if env_kwargs["use_srl"]: - env_kwargs["srl_model_path"] = env_kwargs_extra.get("srl_model_path", None) - env_kwargs["state_dim"] = getSRLDim(env_kwargs_extra.get("srl_model_path", None)) - srl_model = MultiprocessSRLModel(args.num_cpu, args.env, env_kwargs) - env_kwargs["srl_pipe"] = srl_model.pipe - - env_class = registered_env[args.env][0] - env = env_class(**env_kwargs) - - if args.run_policy in ['custom', 'ppo2']: - - # Additional env when using a trained agent to generate data - train_env = vecEnv(env_kwargs, env_class) - - if args.run_policy == 'ppo2': - model = PPO2(CnnPolicy, train_env).learn(args.ppo2_timesteps) - else: - _, _, algo_args = createEnv(args, train_args, algo_name, algo_class, env_kwargs) - tf.reset_default_graph() - set_global_seeds(args.seed) - printYellow("Compiling Policy function....") - model = algo_class.load(load_path, args=algo_args) - - if len(args.replay_generative_model) > 0: - srl_model = loadSRLModel(args.log_generative_model, th.cuda.is_available()) - srl_state_dim = srl_model.state_dim - srl_model = srl_model.model.model - - frames = 0 - start_time = time.time() - # divide evenly, then do an extra one for only some of them in order to get the right count - for i_episode in range(args.num_episode // args.num_cpu + 1 * (args.num_episode % args.num_cpu > thread_num)): - # seed + position in this slice + size of slice (with reminder if uneven partitions) - seed = args.seed + i_episode + args.num_episode // args.num_cpu * thread_num + \ - (thread_num if thread_num <= args.num_episode % args.num_cpu else args.num_episode % args.num_cpu) - - if not args.run_policy == 'custom': - env.seed(seed) - env.action_space.seed(seed) # this is for the sample() function from gym.space - - if len(args.replay_generative_model) > 0: - - sample = Variable(th.randn(1, srl_state_dim)) - if th.cuda.is_available(): - sample = sample.cuda() - - generated_obs = srl_model.decode(sample) - generated_obs = generated_obs[0].detach().cpu().numpy().transpose(1, 2, 0) - generated_obs = deNormalize(generated_obs) - - obs = env.reset(generated_observation=generated_obs) - done = False - action_proba = None - t = 0 - episode_toward_target_on = False - - while not done: - - env.render() - if args.run_policy == 'ppo2': - action, _ = model.predict([obs]) - - elif args.run_policy == 'custom': - action = [model.getAction(obs, done)] - action_proba = model.getActionProba(obs, done) - - else: - if episode_toward_target_on and np.random.rand() < args.toward_target_timesteps_proportion: - action = [env.actionPolicyTowardTarget()] - else: - action = [env.action_space.sample()] - - if len(args.replay_generative_model) > 0: - - sample = Variable(th.randn(1, srl_state_dim)) - - if th.cuda.is_available(): - sample = sample.cuda() - - generated_obs = srl_model.decode(sample) - generated_obs = generated_obs[0].detach().cpu().numpy().transpose(1, 2, 0) - generated_obs = deNormalize(generated_obs) - - action_to_step = action[0] - - obs, _, done, _ = env.step(action_to_step, generated_observation=generated_obs, action_proba=action_proba) - - frames += 1 - t += 1 - if done: - - if np.random.rand() < args.toward_target_timesteps_proportion: - episode_toward_target_on = True - else: - episode_toward_target_on = False - print("Episode finished after {} timesteps".format(t + 1)) - - if thread_num == 0: - print("{:.2f} FPS".format(frames * args.num_cpu / (time.time() - start_time))) - - -def main(): - parser = argparse.ArgumentParser(description='Deteministic dataset generator for SRL training ' + - '(can be used for environment testing)') - parser.add_argument('--num-cpu', type=int, default=1, help='number of cpu to run on') - parser.add_argument('--num-episode', type=int, default=50, help='number of episode to run') - parser.add_argument('--save-path', type=str, default='srl_zoo/data/', - help='Folder where the environments will save the output') - parser.add_argument('--name', type=str, default='kuka_button', help='Folder name for the output') - parser.add_argument('--env', type=str, default='KukaButtonGymEnv-v0', help='The environment wanted', - choices=list(registered_env.keys())) - parser.add_argument('--display', action='store_true', default=False) - parser.add_argument('--no-record-data', action='store_true', default=False) - parser.add_argument('--max-distance', type=float, default=0.28, - help='Beyond this distance from the goal, the agent gets a negative reward') - parser.add_argument('-c', '--continuous-actions', action='store_true', default=False) - parser.add_argument('--seed', type=int, default=0, help='the seed') - parser.add_argument('-f', '--force', action='store_true', default=False, - help='Force the save, even if it overrides something else,' + - ' including partial parts if they exist') - parser.add_argument('-r', '--random-target', action='store_true', default=False, - help='Set the button to a random position') - parser.add_argument('--multi-view', action='store_true', default=False, help='Set a second camera to the scene') - parser.add_argument('--shape-reward', action='store_true', default=False, - help='Shape the reward (reward = - distance) instead of a sparse reward') - parser.add_argument('--reward-dist', action='store_true', default=False, - help='Prints out the reward distribution when the dataset generation is finished') - parser.add_argument('--run-policy', type=str, default="random", - choices=['random', 'ppo2', 'custom'], - help='Policy to run for data collection ' + - '(random, localy pretrained ppo2, pretrained custom policy)') - parser.add_argument('--log-custom-policy', type=str, default='', - help='Logs of the custom pretained policy to run for data collection') - parser.add_argument('-rgm', '--replay-generative-model', type=str, default="", choices=['vae'], - help='Generative model to replay for generating a dataset (for Continual Learning purposes)') - parser.add_argument('--log-generative-model', type=str, default='', - help='Logs of the custom pretained policy to run for data collection') - parser.add_argument('--ppo2-timesteps', type=int, default=1000, - help='number of timesteps to run PPO2 on before generating the dataset') - parser.add_argument('--toward-target-timesteps-proportion', type=float, default=0.0, - help="propotion of timesteps that use simply towards target policy, should be 0.0 to 1.0") - parser.add_argument('-sc', '--simple-continual', action='store_true', default=False, - help='Simple red square target for task 1 of continual learning scenario. ' + - 'The task is: robot should reach the target.') - parser.add_argument('-cc', '--circular-continual', action='store_true', default=False, - help='Blue square target for task 2 of continual learning scenario. ' + - 'The task is: robot should turn in circle around the target.') - parser.add_argument('-sqc', '--square-continual', action='store_true', default=False, - help='Green square target for task 3 of continual learning scenario. ' + - 'The task is: robot should turn in square around the target.') - parser.add_argument('--short-episodes', action='store_true', default=False, - help='Generate short episodes (only 10 contacts with the target allowed).') - parser.add_argument('--episode', type=int, default=-1, - help='Model saved at episode N that we want to load') - - args = parser.parse_args() - - assert (args.num_cpu > 0), "Error: number of cpu must be positive and non zero" - assert (args.max_distance > 0), "Error: max distance must be positive and non zero" - assert (args.num_episode > 0), "Error: number of episodes must be positive and non zero" - assert not args.reward_dist or not args.shape_reward, \ - "Error: cannot display the reward distribution for continuous reward" - assert not(registered_env[args.env][3] is ThreadingType.NONE and args.num_cpu != 1), \ - "Error: cannot have more than 1 CPU for the environment {}".format(args.env) - if args.num_cpu > args.num_episode: - args.num_cpu = args.num_episode - printYellow("num_cpu cannot be greater than num_episode, defaulting to {} cpus.".format(args.num_cpu)) - - assert sum([args.simple_continual, args.circular_continual, args.square_continual]) <= 1, \ - "For continual SRL and RL, please provide only one scenario at the time !" - - assert not (args.log_custom_policy == '' and args.run_policy == 'custom'), \ - "If using a custom policy, please specify a valid log folder for loading it." - - assert not (args.log_generative_model == '' and args.replay_generative_model == 'custom'), \ - "If using a custom policy, please specify a valid log folder for loading it." - - # this is done so seed 0 and 1 are different and not simply offset of the same datasets. - args.seed = np.random.RandomState(args.seed).randint(int(1e10)) - - # File exists, need to deal with it - if not args.no_record_data and os.path.exists(args.save_path + args.name): - assert args.force, "Error: save directory '{}' already exists".format(args.save_path + args.name) - - shutil.rmtree(args.save_path + args.name) - for part in glob.glob(args.save_path + args.name + "_part-[0-9]*"): - shutil.rmtree(part) - if not args.no_record_data: - # create the output - os.mkdir(args.save_path + args.name) - - if args.num_cpu == 1: - env_thread(args, 0, partition=False) - else: - # try and divide into multiple processes, with an environment each - try: - jobs = [] - for i in range(args.num_cpu): - process = multiprocessing.Process(target=env_thread, args=(args, i, True)) - jobs.append(process) - - for j in jobs: - j.start() - - try: - for j in jobs: - j.join() - except Exception as e: - printRed("Error: unable to join thread") - raise e - - except Exception as e: - printRed("Error: unable to start thread") - raise e - - if not args.no_record_data and args.num_cpu > 1: - # sleep 1 second, to avoid congruency issues from multiprocess (eg., files still writing) - time.sleep(1) - # get all the parts - file_parts = sorted(glob.glob(args.save_path + args.name + "_part-[0-9]*"), key=lambda a: int(a.split("-")[-1])) - - # move the config files from any as they are identical - os.rename(file_parts[0] + "/dataset_config.json", args.save_path + args.name + "/dataset_config.json") - os.rename(file_parts[0] + "/env_globals.json", args.save_path + args.name + "/env_globals.json") - - ground_truth = None - preprocessed_data = None - - # used to convert the part record_id to the fused record_id - record_id = 0 - for part in file_parts: - # sort the record names alphabetically, then numerically - records = sorted(glob.glob(part + "/record_[0-9]*"), key=lambda a: int(a.split("_")[-1])) - - record_id_start = record_id - for record in records: - os.renames(record, args.save_path + args.name + "/record_{:03d}".format(record_id)) - record_id += 1 - - # fuse the npz files together, in the right order - if ground_truth is None: - # init - ground_truth = {} - preprocessed_data = {} - ground_truth_load = np.load(part + "/ground_truth.npz") - preprocessed_data_load = np.load(part + "/preprocessed_data.npz") - - for arr in ground_truth_load.files: - if arr == "images_path": - ground_truth[arr] = np.array( - [convertImagePath(args, path, record_id_start) for path in ground_truth_load[arr]]) - else: - ground_truth[arr] = ground_truth_load[arr] - for arr in preprocessed_data_load.files: - preprocessed_data[arr] = preprocessed_data_load[arr] - - else: - ground_truth_load = np.load(part + "/ground_truth.npz") - preprocessed_data_load = np.load(part + "/preprocessed_data.npz") - - for arr in ground_truth_load.files: - if arr == "images_path": - sanitised_paths = np.array( - [convertImagePath(args, path, record_id_start) for path in ground_truth_load[arr]]) - ground_truth[arr] = np.concatenate((ground_truth[arr], sanitised_paths)) - else: - ground_truth[arr] = np.concatenate((ground_truth[arr], ground_truth_load[arr])) - for arr in preprocessed_data_load.files: - preprocessed_data[arr] = np.concatenate((preprocessed_data[arr], preprocessed_data_load[arr])) - - # remove the current part folder - shutil.rmtree(part) - - # save the fused outputs - np.savez(args.save_path + args.name + "/ground_truth.npz", **ground_truth) - np.savez(args.save_path + args.name + "/preprocessed_data.npz", **preprocessed_data) - - if args.reward_dist: - rewards, counts = np.unique(np.load(args.save_path + args.name + "/preprocessed_data.npz")['rewards'], - return_counts=True) - counts = ["{:.2f}%".format(val * 100) for val in counts / np.sum(counts)] - print("reward distribution:") - [print(" ", reward, count) for reward, count in list(zip(rewards, counts))] - - -if __name__ == '__main__': - main() diff --git a/tests/test_distillation_pipeline.py b/tests/test_distillation_pipeline.py index 4c9ad63be..dbbe63d50 100644 --- a/tests/test_distillation_pipeline.py +++ b/tests/test_distillation_pipeline.py @@ -23,7 +23,9 @@ def assertEq(left, right): def testOnPolicyDatasetGeneration(): # # Train Ground_truth teacher policies for each env - test_log_dir = "logs/test_distillation/" + + # do not write distillation in path to prevent loading irrelevant algo based on folder name + test_log_dir = "logs/test_dist/" test_log_dir_teacher_one = test_log_dir + 'teacher_one/' test_log_dir_teacher_two = test_log_dir + 'teacher_two/' @@ -65,7 +67,6 @@ def testOnPolicyDatasetGeneration(): max([test_log_dir_teacher_two + "/" + d for d in os.listdir(test_log_dir_teacher_two) if os.path.isdir(test_log_dir_teacher_two + "/" + d)], key=os.path.getmtime) + '/' - # TODO: fix when fails here! OnPolicyDatasetGenerator(teacher_path=teacher_two_path, output_name='test_CC_copy/', task_id='CC', episode=-1, env_name=ENV_NAME, test_mode=True) @@ -75,9 +76,9 @@ def testOnPolicyDatasetGeneration(): ok = subprocess.call(['cp', '-r', merge_path, 'srl_zoo/data/', '-f']) assert ok == 0 - time.sleep(180) + time.sleep(10) - # # Train a raw_pixels student policy via distillation - # trainStudent(merge_path, "CC", log_dir=test_log_dir, srl_model=DEFAULT_SRL_STUDENT, - # env_name=ENV_NAME, training_size=500, epochs=3) + # Train a raw_pixels student policy via distillation + trainStudent(merge_path, "CC", log_dir=test_log_dir, srl_model=DEFAULT_SRL_STUDENT, + env_name=ENV_NAME, training_size=500, epochs=3) print("Distillation test performed!") From 9eec0f5899b20b0f010dedff51b4c9ff30feda1f Mon Sep 17 00:00:00 2001 From: kalifou Date: Tue, 21 May 2019 23:53:31 +0200 Subject: [PATCH 102/141] reduce distillation config files --- config/srl_models_circular.yaml | 137 -------------------------------- config/srl_models_merged.yaml | 137 -------------------------------- config/srl_models_simple.yaml | 137 -------------------------------- 3 files changed, 411 deletions(-) diff --git a/config/srl_models_circular.yaml b/config/srl_models_circular.yaml index a3ead3cf3..e4f493867 100644 --- a/config/srl_models_circular.yaml +++ b/config/srl_models_circular.yaml @@ -1,140 +1,3 @@ -KukaButtonGymEnv-v0: - # Base path to SRL log folder - log_folder: srl_zoo/logs/kuka_button_relative/ - # Path to the different trained SRL models - autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth - vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth - supervised: baselines/supervised_custom_cnn_SEED1_EPOCHS25_BS32/srl_supervised_model.pth - pca: baselines/pca_ST_DIM5/pca.pkl - robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth - inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth - forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth - multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth - srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth - srl_splits: 18-08-10_15h20_21_custom_cnn_ST_DIM200_autoencoder_reward_inverse/srl_model.pth - -Kuka2ButtonGymEnv-v0: - # Base path to SRL log folder - log_folder: srl_zoo/logs/kuka_2_button/ - # Path to the different trained SRL models - autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth - vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth - supervised: baselines/supervised_custom_cnn_SEED1_EPOCHS25_BS32/srl_supervised_model.pth - pca: baselines/pca_ST_DIM32/pca.pkl - robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth - inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth - forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth - multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth - srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth - -KukaRandButtonGymEnv-v0: - # Base path to SRL log folder - log_folder: srl_zoo/logs/kuka_rand_button/ - # Path to the different trained SRL models - autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth - vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth - supervised: baselines/supervised_custom_cnn_SEED1_EPOCHS25_BS32/srl_supervised_model.pth - pca: baselines/pca_ST_DIM10/pca.pkl - robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth - inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth - forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth - multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth - srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth - -KukaMovingButtonGymEnv-v0: - # Base path to SRL log folder - log_folder: srl_zoo/logs/kuka_moving_button_big/ - # Path to the different trained SRL models - autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth - vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth - supervised: baselines/supervised_custom_cnn_SEED1_EPOCHS25_BS32/srl_supervised_model.pth - pca: baselines/pca_ST_DIM32/pca.pkl - robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth - inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth - forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth - multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth - srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth - -MobileRobotGymEnv-v0: - # Base path to SRL log folder - log_folder: srl_zoo/logs/mobile_robot_relative/ - # Path to the different trained SRL models - autoencoder: 18-07-22_13h36_14_custom_cnn_ST_DIM200_autoencoder/srl_model.pth - vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth - supervised: baselines/supervised_resnet_SEED1_EPOCHS25_BS32/srl_supervised_model.pth - pca: baselines/pca_ST_DIM32/pca.pkl - robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth - inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth - forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth - multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth - autoencoder_reward: 18-07-22_13h20_45_custom_cnn_ST_DIM200_autoencoder_reward/srl_model.pth - autoencoder_inverse: 18-07-22_12h30_10_custom_cnn_ST_DIM200_autoencoder_inverse/srl_model.pth - srl_combination: 18-07-21_12h11_17_custom_cnn_ST_DIM200_autoencoder_inverse_reward/srl_model.pth - reward_inverse: 18-07-23_11h02_28_custom_cnn_ST_DIM200_reward_inverse/srl_model.pth - reward: 18-07-23_18h58_24_custom_cnn_ST_DIM200_reward/srl_model.pth - srl_splits: 18-08-14_12h53_54_custom_cnn_ST_DIM200_autoencoder_reward_inverse/srl_model.pth - # srl_splits: 18-08-10_12h58_43_custom_cnn_ST_DIM200_reward_inverse_autoencoder/srl_model.pth - random: 18-08-10_11h50_25_custom_cnn_ST_DIM200_random/srl_model.pth - random_inverse: 18-08-10_11h38_05_custom_cnn_ST_DIM200_inverse_random/srl_model.pth - autoencoder_forward: 18-08-14_10h35_47_custom_cnn_ST_DIM200_autoencoder_forward/srl_model.pth - -MobileRobot2TargetGymEnv-v0: - # Base path to SRL log folder - log_folder: srl_zoo/logs/mobile_robot_2target/ - # Path to the different trained SRL models - autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth - vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth - supervised: baselines/supervised_resnet_SEED1_EPOCHS25_BS32/srl_supervised_model.pth - pca: baselines/pca_ST_DIM32/pca.pkl - robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth - inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth - forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth - multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth - srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth - -MobileRobot1DGymEnv-v0: - # Base path to SRL log folder - log_folder: srl_zoo/logs/mobile_robot_slider/ - # Path to the different trained SRL models - autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth - vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth - supervised: baselines/supervised_resnet_SEED1_EPOCHS25_BS32/srl_supervised_model.pth - pca: baselines/pca_ST_DIM32/pca.pkl - robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth - inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth - forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth - multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth - srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth - -MobileRobotLineTargetGymEnv-v0: - # Base path to SRL log folder - log_folder: srl_zoo/logs/mobile_line_target/ - # Path to the different trained SRL models - autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth - vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth - supervised: baselines/supervised_resnet_SEED1_EPOCHS25_BS32/srl_supervised_model.pth - pca: baselines/pca_ST_DIM32/pca.pkl - robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth - inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth - forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth - multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth - srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth - -CarRacingGymEnv-v0: - # Base path to SRL log folder - log_folder: srl_zoo/logs/car_racing/ - # Path to the different trained SRL models - autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth - vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth - supervised: baselines/supervised_resnet_SEED1_EPOCHS25_BS32/srl_supervised_model.pth - pca: baselines/pca_ST_DIM32/pca.pkl - robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth - inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth - forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth - multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth - autoencoder_inverse: 18-07-20_12h13_18_custom_cnn_ST_DIM200_autoencoder_inverse/srl_model.pth - autoencoder_reward: 18-07-20_14h35_43_custom_cnn_ST_DIM200_autoencoder_reward/srl_model.pth - srl_combination: 18-07-19_18h16_03_custom_cnn_ST_DIM200_reward_autoencoder_inverse/srl_model.pth OmnirobotEnv-v0: # Base path to SRL log folder diff --git a/config/srl_models_merged.yaml b/config/srl_models_merged.yaml index fb540bb09..b299a8396 100644 --- a/config/srl_models_merged.yaml +++ b/config/srl_models_merged.yaml @@ -1,140 +1,3 @@ -KukaButtonGymEnv-v0: - # Base path to SRL log folder - log_folder: srl_zoo/logs/kuka_button_relative/ - # Path to the different trained SRL models - autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth - vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth - supervised: baselines/supervised_custom_cnn_SEED1_EPOCHS25_BS32/srl_supervised_model.pth - pca: baselines/pca_ST_DIM5/pca.pkl - robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth - inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth - forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth - multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth - srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth - srl_splits: 18-08-10_15h20_21_custom_cnn_ST_DIM200_autoencoder_reward_inverse/srl_model.pth - -Kuka2ButtonGymEnv-v0: - # Base path to SRL log folder - log_folder: srl_zoo/logs/kuka_2_button/ - # Path to the different trained SRL models - autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth - vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth - supervised: baselines/supervised_custom_cnn_SEED1_EPOCHS25_BS32/srl_supervised_model.pth - pca: baselines/pca_ST_DIM32/pca.pkl - robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth - inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth - forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth - multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth - srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth - -KukaRandButtonGymEnv-v0: - # Base path to SRL log folder - log_folder: srl_zoo/logs/kuka_rand_button/ - # Path to the different trained SRL models - autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth - vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth - supervised: baselines/supervised_custom_cnn_SEED1_EPOCHS25_BS32/srl_supervised_model.pth - pca: baselines/pca_ST_DIM10/pca.pkl - robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth - inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth - forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth - multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth - srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth - -KukaMovingButtonGymEnv-v0: - # Base path to SRL log folder - log_folder: srl_zoo/logs/kuka_moving_button_big/ - # Path to the different trained SRL models - autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth - vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth - supervised: baselines/supervised_custom_cnn_SEED1_EPOCHS25_BS32/srl_supervised_model.pth - pca: baselines/pca_ST_DIM32/pca.pkl - robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth - inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth - forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth - multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth - srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth - -MobileRobotGymEnv-v0: - # Base path to SRL log folder - log_folder: srl_zoo/logs/mobile_robot_relative/ - # Path to the different trained SRL models - autoencoder: 18-07-22_13h36_14_custom_cnn_ST_DIM200_autoencoder/srl_model.pth - vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth - supervised: baselines/supervised_resnet_SEED1_EPOCHS25_BS32/srl_supervised_model.pth - pca: baselines/pca_ST_DIM32/pca.pkl - robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth - inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth - forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth - multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth - autoencoder_reward: 18-07-22_13h20_45_custom_cnn_ST_DIM200_autoencoder_reward/srl_model.pth - autoencoder_inverse: 18-07-22_12h30_10_custom_cnn_ST_DIM200_autoencoder_inverse/srl_model.pth - srl_combination: 18-07-21_12h11_17_custom_cnn_ST_DIM200_autoencoder_inverse_reward/srl_model.pth - reward_inverse: 18-07-23_11h02_28_custom_cnn_ST_DIM200_reward_inverse/srl_model.pth - reward: 18-07-23_18h58_24_custom_cnn_ST_DIM200_reward/srl_model.pth - srl_splits: 18-08-14_12h53_54_custom_cnn_ST_DIM200_autoencoder_reward_inverse/srl_model.pth - # srl_splits: 18-08-10_12h58_43_custom_cnn_ST_DIM200_reward_inverse_autoencoder/srl_model.pth - random: 18-08-10_11h50_25_custom_cnn_ST_DIM200_random/srl_model.pth - random_inverse: 18-08-10_11h38_05_custom_cnn_ST_DIM200_inverse_random/srl_model.pth - autoencoder_forward: 18-08-14_10h35_47_custom_cnn_ST_DIM200_autoencoder_forward/srl_model.pth - -MobileRobot2TargetGymEnv-v0: - # Base path to SRL log folder - log_folder: srl_zoo/logs/mobile_robot_2target/ - # Path to the different trained SRL models - autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth - vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth - supervised: baselines/supervised_resnet_SEED1_EPOCHS25_BS32/srl_supervised_model.pth - pca: baselines/pca_ST_DIM32/pca.pkl - robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth - inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth - forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth - multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth - srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth - -MobileRobot1DGymEnv-v0: - # Base path to SRL log folder - log_folder: srl_zoo/logs/mobile_robot_slider/ - # Path to the different trained SRL models - autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth - vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth - supervised: baselines/supervised_resnet_SEED1_EPOCHS25_BS32/srl_supervised_model.pth - pca: baselines/pca_ST_DIM32/pca.pkl - robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth - inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth - forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth - multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth - srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth - -MobileRobotLineTargetGymEnv-v0: - # Base path to SRL log folder - log_folder: srl_zoo/logs/mobile_line_target/ - # Path to the different trained SRL models - autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth - vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth - supervised: baselines/supervised_resnet_SEED1_EPOCHS25_BS32/srl_supervised_model.pth - pca: baselines/pca_ST_DIM32/pca.pkl - robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth - inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth - forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth - multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth - srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth - -CarRacingGymEnv-v0: - # Base path to SRL log folder - log_folder: srl_zoo/logs/car_racing/ - # Path to the different trained SRL models - autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth - vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth - supervised: baselines/supervised_resnet_SEED1_EPOCHS25_BS32/srl_supervised_model.pth - pca: baselines/pca_ST_DIM32/pca.pkl - robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth - inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth - forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth - multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth - autoencoder_inverse: 18-07-20_12h13_18_custom_cnn_ST_DIM200_autoencoder_inverse/srl_model.pth - autoencoder_reward: 18-07-20_14h35_43_custom_cnn_ST_DIM200_autoencoder_reward/srl_model.pth - srl_combination: 18-07-19_18h16_03_custom_cnn_ST_DIM200_reward_autoencoder_inverse/srl_model.pth OmnirobotEnv-v0: # Base path to SRL log folder diff --git a/config/srl_models_simple.yaml b/config/srl_models_simple.yaml index 11d6daa73..8c07f243d 100644 --- a/config/srl_models_simple.yaml +++ b/config/srl_models_simple.yaml @@ -1,140 +1,3 @@ -KukaButtonGymEnv-v0: - # Base path to SRL log folder - log_folder: srl_zoo/logs/kuka_button_relative/ - # Path to the different trained SRL models - autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth - vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth - supervised: baselines/supervised_custom_cnn_SEED1_EPOCHS25_BS32/srl_supervised_model.pth - pca: baselines/pca_ST_DIM5/pca.pkl - robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth - inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth - forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth - multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth - srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth - srl_splits: 18-08-10_15h20_21_custom_cnn_ST_DIM200_autoencoder_reward_inverse/srl_model.pth - -Kuka2ButtonGymEnv-v0: - # Base path to SRL log folder - log_folder: srl_zoo/logs/kuka_2_button/ - # Path to the different trained SRL models - autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth - vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth - supervised: baselines/supervised_custom_cnn_SEED1_EPOCHS25_BS32/srl_supervised_model.pth - pca: baselines/pca_ST_DIM32/pca.pkl - robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth - inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth - forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth - multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth - srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth - -KukaRandButtonGymEnv-v0: - # Base path to SRL log folder - log_folder: srl_zoo/logs/kuka_rand_button/ - # Path to the different trained SRL models - autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth - vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth - supervised: baselines/supervised_custom_cnn_SEED1_EPOCHS25_BS32/srl_supervised_model.pth - pca: baselines/pca_ST_DIM10/pca.pkl - robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth - inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth - forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth - multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth - srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth - -KukaMovingButtonGymEnv-v0: - # Base path to SRL log folder - log_folder: srl_zoo/logs/kuka_moving_button_big/ - # Path to the different trained SRL models - autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth - vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth - supervised: baselines/supervised_custom_cnn_SEED1_EPOCHS25_BS32/srl_supervised_model.pth - pca: baselines/pca_ST_DIM32/pca.pkl - robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth - inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth - forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth - multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth - srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth - -MobileRobotGymEnv-v0: - # Base path to SRL log folder - log_folder: srl_zoo/logs/mobile_robot_relative/ - # Path to the different trained SRL models - autoencoder: 18-07-22_13h36_14_custom_cnn_ST_DIM200_autoencoder/srl_model.pth - vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth - supervised: baselines/supervised_resnet_SEED1_EPOCHS25_BS32/srl_supervised_model.pth - pca: baselines/pca_ST_DIM32/pca.pkl - robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth - inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth - forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth - multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth - autoencoder_reward: 18-07-22_13h20_45_custom_cnn_ST_DIM200_autoencoder_reward/srl_model.pth - autoencoder_inverse: 18-07-22_12h30_10_custom_cnn_ST_DIM200_autoencoder_inverse/srl_model.pth - srl_combination: 18-07-21_12h11_17_custom_cnn_ST_DIM200_autoencoder_inverse_reward/srl_model.pth - reward_inverse: 18-07-23_11h02_28_custom_cnn_ST_DIM200_reward_inverse/srl_model.pth - reward: 18-07-23_18h58_24_custom_cnn_ST_DIM200_reward/srl_model.pth - srl_splits: 18-08-14_12h53_54_custom_cnn_ST_DIM200_autoencoder_reward_inverse/srl_model.pth - # srl_splits: 18-08-10_12h58_43_custom_cnn_ST_DIM200_reward_inverse_autoencoder/srl_model.pth - random: 18-08-10_11h50_25_custom_cnn_ST_DIM200_random/srl_model.pth - random_inverse: 18-08-10_11h38_05_custom_cnn_ST_DIM200_inverse_random/srl_model.pth - autoencoder_forward: 18-08-14_10h35_47_custom_cnn_ST_DIM200_autoencoder_forward/srl_model.pth - -MobileRobot2TargetGymEnv-v0: - # Base path to SRL log folder - log_folder: srl_zoo/logs/mobile_robot_2target/ - # Path to the different trained SRL models - autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth - vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth - supervised: baselines/supervised_resnet_SEED1_EPOCHS25_BS32/srl_supervised_model.pth - pca: baselines/pca_ST_DIM32/pca.pkl - robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth - inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth - forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth - multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth - srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth - -MobileRobot1DGymEnv-v0: - # Base path to SRL log folder - log_folder: srl_zoo/logs/mobile_robot_slider/ - # Path to the different trained SRL models - autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth - vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth - supervised: baselines/supervised_resnet_SEED1_EPOCHS25_BS32/srl_supervised_model.pth - pca: baselines/pca_ST_DIM32/pca.pkl - robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth - inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth - forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth - multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth - srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth - -MobileRobotLineTargetGymEnv-v0: - # Base path to SRL log folder - log_folder: srl_zoo/logs/mobile_line_target/ - # Path to the different trained SRL models - autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth - vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth - supervised: baselines/supervised_resnet_SEED1_EPOCHS25_BS32/srl_supervised_model.pth - pca: baselines/pca_ST_DIM32/pca.pkl - robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth - inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth - forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth - multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth - srl_combination: 18-06-20_16h36_48_custom_cnnST_DIM2_forward_reward_inverse_autoencoder/srl_model.pth - -CarRacingGymEnv-v0: - # Base path to SRL log folder - log_folder: srl_zoo/logs/car_racing/ - # Path to the different trained SRL models - autoencoder: 18-07-04_11h08_38_mlp_ST_DIM2_autoencoder/srl_model.pth - vae: 18-07-04_11h08_56_mlp_ST_DIM2_vae/srl_model.pth - supervised: baselines/supervised_resnet_SEED1_EPOCHS25_BS32/srl_supervised_model.pth - pca: baselines/pca_ST_DIM32/pca.pkl - robotic_priors: 18-07-04_11h01_51_custom_cnn_ST_DIM3_priors/srl_model.pth - inverse: 18-06-20_16h36_48_custom_cnnST_DIM2_inverse/srl_model.pth - forward: 18-06-20_16h36_48_custom_cnnST_DIM2_forward/srl_model.pth - multi_view_srl: 18-07-04_11h06_09_custom_cnn_ST_DIM10_priors/srl_model.pth - autoencoder_inverse: 18-07-20_12h13_18_custom_cnn_ST_DIM200_autoencoder_inverse/srl_model.pth - autoencoder_reward: 18-07-20_14h35_43_custom_cnn_ST_DIM200_autoencoder_reward/srl_model.pth - srl_combination: 18-07-19_18h16_03_custom_cnn_ST_DIM200_reward_autoencoder_inverse/srl_model.pth OmnirobotEnv-v0: # Base path to SRL log folder From a85942d85401caea9ab28930151f483b3ea2f703 Mon Sep 17 00:00:00 2001 From: kalifou Date: Wed, 22 May 2019 10:58:31 +0200 Subject: [PATCH 103/141] fix generator for cross env compatibility --- environments/dataset_generator.py | 14 ++++++++++---- environments/omnirobot_gym/omnirobot_env.py | 9 +++++---- environments/srl_env.py | 2 +- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/environments/dataset_generator.py b/environments/dataset_generator.py index 3791fc620..8eb5918b6 100644 --- a/environments/dataset_generator.py +++ b/environments/dataset_generator.py @@ -135,6 +135,7 @@ def env_thread(args, thread_num, partition=True): env_kwargs["srl_model"] = env_kwargs_extra["srl_model"] env_kwargs["random_target"] = env_kwargs_extra.get("random_target", False) env_kwargs["use_srl"] = env_kwargs_extra.get("use_srl", False) + eps = 0.2 env_kwargs["state_init_override"] = np.array([MIN_X + eps, MAX_X - eps]) \ if args.run_policy == 'walker' else None @@ -151,6 +152,7 @@ def env_thread(args, thread_num, partition=True): walker_path = None action_walker = None state_init_for_walker = None + kwargs_reset, kwargs_step = {}, {} if args.run_policy in ['custom', 'ppo2', 'walker']: @@ -184,6 +186,7 @@ def env_thread(args, thread_num, partition=True): (thread_num if thread_num <= args.num_episode % args.num_cpu else args.num_episode % args.num_cpu) if not (args.run_policy in ['custom', 'walker']): + seed = seed % 2^32 env.seed(seed) env.action_space.seed(seed) # this is for the sample() function from gym.space @@ -197,7 +200,8 @@ def env_thread(args, thread_num, partition=True): generated_obs = generated_obs[0].detach().cpu().numpy().transpose(1, 2, 0) generated_obs = deNormalize(generated_obs) - obs = env.reset(generated_observation=generated_obs) + kwargs_reset['generated_observation'] = generated_obs + obs = env.reset(**kwargs_reset) done = False action_proba = None t = 0 @@ -240,8 +244,11 @@ def env_thread(args, thread_num, partition=True): action_to_step = action[0] - obs, _, done, _ = env.step(action_to_step, generated_observation=generated_obs, action_proba=action_proba, - action_grid_walker=action_walker) + kwargs_step = {k: v for (k, v) in [("generated_observation", generated_obs), + ("action_proba", action_proba), + ("action_grid_walker", action_walker)] if v is not None} + + obs, _, done, _ = env.step(action_to_step, **kwargs_step) frames += 1 t += 1 @@ -307,7 +314,6 @@ def main(): parser.add_argument('-sqc', '--square-continual', action='store_true', default=False, help='Green square target for task 3 of continual learning scenario. ' + 'The task is: robot should turn in square around the target.') - parser.add_argument('--short-episodes', action='store_true', default=False, help='Generate short episodes (only 10 contacts with the target allowed).') parser.add_argument('--episode', type=int, default=-1, diff --git a/environments/omnirobot_gym/omnirobot_env.py b/environments/omnirobot_gym/omnirobot_env.py index 347d1cab8..54a49e847 100644 --- a/environments/omnirobot_gym/omnirobot_env.py +++ b/environments/omnirobot_gym/omnirobot_env.py @@ -319,6 +319,7 @@ def _hasEpisodeTerminated(self): """ Returns True if the episode is over and False otherwise """ + #print("is SC at end: ", self.simple_continual_target, self.short_episodes, self.n_contacts) if (self.episode_terminated or self._env_step_counter > MAX_STEPS) or \ (self.n_contacts >= N_CONTACTS_BEFORE_TERMINATION and self.short_episodes and self.simple_continual_target) or \ @@ -357,7 +358,7 @@ def render(self, mode='rgb_array'): self.visualizeBoundary() self.image_plot = plt.imshow(self.observation_with_boundary, cmap='gray') self.image_plot.axes.grid(False) - + else: self.visualizeBoundary() self.image_plot.set_data(self.observation_with_boundary) @@ -365,7 +366,7 @@ def render(self, mode='rgb_array'): # Wait a bit, so that plot is visible plt.pause(0.0001) return self.observation - + def initVisualizeBoundary(self): with open(CAMERA_INFO_PATH, 'r') as stream: try: @@ -396,11 +397,11 @@ def initVisualizeBoundary(self): # transform the corresponding points into cropped image self.boundary_coner_pixel_pos = self.boundary_coner_pixel_pos - (np.array(ORIGIN_SIZE) - np.array(CROPPED_SIZE)).reshape(2, 1) / 2.0 - + # transform the corresponding points into resized image (RENDER_WIDHT, RENDER_HEIGHT) self.boundary_coner_pixel_pos[0, :] *= RENDER_WIDTH/CROPPED_SIZE[0] self.boundary_coner_pixel_pos[1, :] *= RENDER_HEIGHT/CROPPED_SIZE[1] - + self.boundary_coner_pixel_pos = np.around(self.boundary_coner_pixel_pos).astype(np.int) # Create square for vizu of objective in continual square task diff --git a/environments/srl_env.py b/environments/srl_env.py index c38ccd17c..cf1636388 100644 --- a/environments/srl_env.py +++ b/environments/srl_env.py @@ -87,7 +87,7 @@ def step(self, action, generated_observation=None, action_proba=None, action_gri """ raise NotImplementedError() - def reset(self, state_override=None): + def reset(self, generated_observation=None, state_override=None): """ Reset the environment :return: (numpy tensor) first observation of the env From bbe9c44fd3bf5d897736fcd70a1142caf8030258 Mon Sep 17 00:00:00 2001 From: kalifou Date: Wed, 22 May 2019 15:47:04 +0200 Subject: [PATCH 104/141] fix for on-policy data-gen: normalizing obs --- environments/dataset_generator.py | 35 +++++++++++++++------ environments/omnirobot_gym/omnirobot_env.py | 1 - real_robots/omnirobot_server.py | 1 + 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/environments/dataset_generator.py b/environments/dataset_generator.py index 8eb5918b6..80c0c8e50 100644 --- a/environments/dataset_generator.py +++ b/environments/dataset_generator.py @@ -18,9 +18,10 @@ from environments import ThreadingType from environments.registry import registered_env +from environments.utils import makeEnv from real_robots.constants import * from replay.enjoy_baselines import createEnv, loadConfigAndSetup -from rl_baselines.utils import MultiprocessSRLModel +from rl_baselines.utils import MultiprocessSRLModel, loadRunningAverage from srl_zoo.utils import printRed, printYellow from srl_zoo.preprocessing.utils import deNormalize from state_representation.models import loadSRLModel, getSRLDim @@ -39,7 +40,7 @@ def latestPath(path): :param path: path to the log folder (defined in srl_model.yaml) (str) :return: path to latest learned model in the same dataset folder (str) """ - return max([path + d for d in os.listdir(path) if os.path.isdir(path + "/" + d)],key=os.path.getmtime) + '/' + return max([path + d for d in os.listdir(path) if os.path.isdir(path + "/" + d)], key=os.path.getmtime) + '/' def walkerPath(): @@ -136,17 +137,34 @@ def env_thread(args, thread_num, partition=True): env_kwargs["random_target"] = env_kwargs_extra.get("random_target", False) env_kwargs["use_srl"] = env_kwargs_extra.get("use_srl", False) + # TODO REFACTOR + env_kwargs["simple_continual_target"] = env_kwargs_extra.get("simple_continual_target", False) + env_kwargs["circular_continual_move"] = env_kwargs_extra.get("circular_continual_move", False) + env_kwargs["square_continual_move"] = env_kwargs_extra.get("square_continual_move", False) + env_kwargs["eight_continual_move"] = env_kwargs_extra.get("eight_continual_move", False) + eps = 0.2 env_kwargs["state_init_override"] = np.array([MIN_X + eps, MAX_X - eps]) \ if args.run_policy == 'walker' else None if env_kwargs["use_srl"]: env_kwargs["srl_model_path"] = env_kwargs_extra.get("srl_model_path", None) env_kwargs["state_dim"] = getSRLDim(env_kwargs_extra.get("srl_model_path", None)) - srl_model = MultiprocessSRLModel(args.num_cpu, args.env, env_kwargs) + srl_model = MultiprocessSRLModel(num_cpu=args.num_cpu, env_id=args.env, env_kwargs=env_kwargs) env_kwargs["srl_pipe"] = srl_model.pipe env_class = registered_env[args.env][0] env = env_class(**env_kwargs) + + if env_kwargs['srl_model'] != "raw_pixels": + # TODO: Remove env duplication + # This is a dirty trick to normalize the obs. + # So for as we override SRL environment functions (step, reset) for on-policy generation & generative replay + # using stable-baselines' normalisation wrappers (step & reset) breaks... + env_norm = [makeEnv(args.env, args.seed, i, args.log_dir, allow_early_resets=False, env_kwargs=env_kwargs) + for i in range(args.num_cpu)] + env_norm = DummyVecEnv(env_norm) + env_norm = VecNormalize(env_norm, norm_obs=True, norm_reward=False) + env_norm = loadRunningAverage(env_norm, load_path_normalise=args.log_custom_policy) using_real_omnibot = args.env == "OmnirobotEnv-v0" and USING_OMNIROBOT walker_path = None @@ -155,7 +173,6 @@ def env_thread(args, thread_num, partition=True): kwargs_reset, kwargs_step = {}, {} if args.run_policy in ['custom', 'ppo2', 'walker']: - # Additional env when using a trained agent to generate data train_env = vecEnv(env_kwargs, env_class) @@ -164,7 +181,7 @@ def env_thread(args, thread_num, partition=True): else: _, _, algo_args = createEnv(args, train_args, algo_name, algo_class, env_kwargs) tf.reset_default_graph() - set_global_seeds(args.seed) + set_global_seeds(args.seed % 2 ^ 32) printYellow("Compiling Policy function....") model = algo_class.load(load_path, args=algo_args) if args.run_policy == 'walker': @@ -184,9 +201,8 @@ def env_thread(args, thread_num, partition=True): # seed + position in this slice + size of slice (with reminder if uneven partitions) seed = args.seed + i_episode + args.num_episode // args.num_cpu * thread_num + \ (thread_num if thread_num <= args.num_episode % args.num_cpu else args.num_episode % args.num_cpu) - + seed = seed % 2 ^ 32 if not (args.run_policy in ['custom', 'walker']): - seed = seed % 2^32 env.seed(seed) env.action_space.seed(seed) # this is for the sample() function from gym.space @@ -217,6 +233,7 @@ def env_thread(args, thread_num, partition=True): # Custom pre-trained Policy (SRL or End-to-End) elif args.run_policy in['custom', 'walker']: + obs = env_norm._normalize_observation(obs) action = [model.getAction(obs, done)] action_proba = model.getActionProba(obs, done) if args.run_policy == 'walker': @@ -245,8 +262,8 @@ def env_thread(args, thread_num, partition=True): action_to_step = action[0] kwargs_step = {k: v for (k, v) in [("generated_observation", generated_obs), - ("action_proba", action_proba), - ("action_grid_walker", action_walker)] if v is not None} + ("action_proba", action_proba), + ("action_grid_walker", action_walker)] if v is not None} obs, _, done, _ = env.step(action_to_step, **kwargs_step) diff --git a/environments/omnirobot_gym/omnirobot_env.py b/environments/omnirobot_gym/omnirobot_env.py index 54a49e847..ed5099f7a 100644 --- a/environments/omnirobot_gym/omnirobot_env.py +++ b/environments/omnirobot_gym/omnirobot_env.py @@ -319,7 +319,6 @@ def _hasEpisodeTerminated(self): """ Returns True if the episode is over and False otherwise """ - #print("is SC at end: ", self.simple_continual_target, self.short_episodes, self.n_contacts) if (self.episode_terminated or self._env_step_counter > MAX_STEPS) or \ (self.n_contacts >= N_CONTACTS_BEFORE_TERMINATION and self.short_episodes and self.simple_continual_target) or \ diff --git a/real_robots/omnirobot_server.py b/real_robots/omnirobot_server.py index 07a494d84..9e75fb7c2 100755 --- a/real_robots/omnirobot_server.py +++ b/real_robots/omnirobot_server.py @@ -368,6 +368,7 @@ def imageCallback(self, msg): except CvBridgeError as e: print("CvBridgeError:", e) + def saveSecondCamImage(im, episode_folder, episode_step, path="omnirobot_2nd_cam"): """ Write an image to disk From b959e4363ee716aec20c53c748fd72ec26c46fd8 Mon Sep 17 00:00:00 2001 From: kalifou Date: Thu, 23 May 2019 17:50:34 +0200 Subject: [PATCH 105/141] small fixes & cleaning: data-gen, distillation logs --- environments/dataset_generator.py | 8 +-- replay/enjoy_baselines.py | 28 +++++------ rl_baselines/student_eval.py | 4 +- .../supervised_rl/policy_distillation.py | 4 +- rl_baselines/train.py | 50 +++++++++---------- 5 files changed, 45 insertions(+), 49 deletions(-) diff --git a/environments/dataset_generator.py b/environments/dataset_generator.py index 80c0c8e50..68cb0f3ec 100644 --- a/environments/dataset_generator.py +++ b/environments/dataset_generator.py @@ -155,11 +155,11 @@ def env_thread(args, thread_num, partition=True): env_class = registered_env[args.env][0] env = env_class(**env_kwargs) - if env_kwargs['srl_model'] != "raw_pixels": + if env_kwargs.get('srl_model', None) not in ["raw_pixels", None]: # TODO: Remove env duplication - # This is a dirty trick to normalize the obs. - # So for as we override SRL environment functions (step, reset) for on-policy generation & generative replay - # using stable-baselines' normalisation wrappers (step & reset) breaks... + # This is a dirty trick to normalize the obs. + # So for as we override SRL environment functions (step, reset) for on-policy generation & generative replay + # using stable-baselines' normalisation wrappers (step & reset) breaks... env_norm = [makeEnv(args.env, args.seed, i, args.log_dir, allow_early_resets=False, env_kwargs=env_kwargs) for i in range(args.num_cpu)] env_norm = DummyVecEnv(env_norm) diff --git a/replay/enjoy_baselines.py b/replay/enjoy_baselines.py index dc14e76cd..3b235e2e0 100644 --- a/replay/enjoy_baselines.py +++ b/replay/enjoy_baselines.py @@ -6,12 +6,10 @@ import os from datetime import datetime -import yaml import numpy as np import tensorflow as tf from stable_baselines.common import set_global_seeds import matplotlib.pyplot as plt -from mpl_toolkits.mplot3d import Axes3D from sklearn.decomposition import PCA import seaborn as sns @@ -91,20 +89,20 @@ def loadConfigAndSetup(load_args): raise ValueError(algo_name + " is not supported for replay") printGreen("\n" + algo_name + "\n") - try: #If args contains episode information, this is for student_evaluation (disstilation) - if(not load_args.episode ==-1): - load_path = "{}/{}_{}_model.pkl".format(load_args.log_dir, algo_name,load_args.episode,) + try: # If args contains episode information, this is for student_evaluation (distillation) + if not load_args.episode == -1: + load_path = "{}/{}_{}_model.pkl".format(load_args.log_dir, algo_name, load_args.episode,) else: load_path = "{}/{}_model.pkl".format(load_args.log_dir, algo_name) except: - printYellow("No episode of checkpoint specified, go for the default policy model: {}_model.pkl".format(algo_name)) - if(load_args.log_dir[-3:]!='pkl'): + printYellow( + "No episode of checkpoint specified, go for the default policy model: {}_model.pkl".format(algo_name)) + if load_args.log_dir[-3:] != 'pkl': load_path = "{}/{}_model.pkl".format(load_args.log_dir, algo_name) else: load_path = load_args.log_dir load_args.log_dir = os.path.dirname(load_path)+'/' - env_globals = json.load(open(load_args.log_dir + "env_globals.json", 'r')) train_args = json.load(open(load_args.log_dir + "args.json", 'r')) @@ -133,11 +131,12 @@ def loadConfigAndSetup(load_args): env_kwargs["square_continual_move"] = env_globals.get("square_continual_move", False) env_kwargs["eight_continual_move"] = env_globals.get("eight_continual_move", False) - if sum([load_args.simple_continual, load_args.circular_continual, load_args.square_continual]) >= 1: - env_kwargs["simple_continual_target"] = load_args.simple_continual - env_kwargs["circular_continual_move"] = load_args.circular_continual - env_kwargs["square_continual_move"] = load_args.square_continual - env_kwargs["random_target"] = not (load_args.circular_continual or load_args.square_continual) + # If overriding the environment for specific Continual Learning tasks + if sum([load_args.simple_continual, load_args.circular_continual, load_args.square_continual]) >= 1: + env_kwargs["simple_continual_target"] = load_args.simple_continual + env_kwargs["circular_continual_move"] = load_args.circular_continual + env_kwargs["square_continual_move"] = load_args.square_continual + env_kwargs["random_target"] = not (load_args.circular_continual or load_args.square_continual) srl_model_path = None if train_args["srl_model"] != "raw_pixels": @@ -147,7 +146,8 @@ def loadConfigAndSetup(load_args): if path is not None: env_kwargs["use_srl"] = True # Check that the srl saved model exists on the disk - assert os.path.isfile(env_globals['srl_model_path']), "{} does not exist".format(env_globals['srl_model_path']) + assert os.path.isfile(env_globals['srl_model_path']), \ + "{} does not exist".format(env_globals['srl_model_path']) srl_model_path = env_globals['srl_model_path'] env_kwargs["srl_model_path"] = srl_model_path diff --git a/rl_baselines/student_eval.py b/rl_baselines/student_eval.py index 25e3bfea1..601c563ad 100644 --- a/rl_baselines/student_eval.py +++ b/rl_baselines/student_eval.py @@ -10,7 +10,7 @@ from environments.registry import registered_env from rl_baselines.evaluation.cross_eval_utils import loadConfigAndSetup, latestPolicy -from srl_zoo.utils import printRed, printYellow +from srl_zoo.utils import printRed, printYellow, printBlue from state_representation.registry import registered_srl CONTINUAL_LEARNING_LABELS = ['CC', 'SC', 'EC', 'SQC'] @@ -247,7 +247,7 @@ def main(): print("Eval on eps list: ", episodes_to_test) for eps in episodes_to_test: student_path = args.log_dir_student - printRed("\n\nEvaluation at episode " + str(eps)) + printBlue("\n\nEvaluation at episode " + str(eps)) if not (args.log_dir_teacher_one == "None"): # Use a copy of the optimal teacher diff --git a/rl_baselines/supervised_rl/policy_distillation.py b/rl_baselines/supervised_rl/policy_distillation.py index 77d268946..d0febb771 100644 --- a/rl_baselines/supervised_rl/policy_distillation.py +++ b/rl_baselines/supervised_rl/policy_distillation.py @@ -24,7 +24,7 @@ CONTINUAL_LEARNING_LABELS = ['CC', 'SC', 'EC', 'SQC'] CL_LABEL_KEY = "continual_learning_label" USE_ADAPTIVE_TEMPERATURE = False -TEMPERATURES = {'CC': 0.1, 'SC': 0.1, 'EC': 0.1, 'SQC': 0.1, "default": 0.01} +TEMPERATURES = {'CC': 0.1, 'SC': 0.1, 'EC': 0.1, 'SQC': 0.1, "default": 0.1} # run with 0.1 to have good results! # 0.01 worse reward for CC, better SC @@ -244,7 +244,7 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): self.optimizer = th.optim.Adam(learnable_params, lr=learning_rate) best_error = np.inf - best_model_path = "{}/distillation_model.pkl".format(args.log_dir) + best_model_path = "{}/{}_model.pkl".format(args.log_dir, args.algo) for epoch in range(N_EPOCHS): # In each epoch, we do a full pass over the training data: diff --git a/rl_baselines/train.py b/rl_baselines/train.py index 563bf2688..bdcf3c548 100644 --- a/rl_baselines/train.py +++ b/rl_baselines/train.py @@ -127,7 +127,7 @@ def callback(_locals, _globals): :param _locals: (dict) :param _globals: (dict) """ - global win, win_smooth, win_episodes, win_crossEval,n_steps, viz, params_saved, best_mean_reward + global win, win_smooth, win_episodes, win_crossEval, n_steps, viz, params_saved, best_mean_reward # Create vizdom object only if needed if viz is None: viz = Visdom(port=VISDOM_PORT) @@ -173,26 +173,26 @@ def callback(_locals, _globals): if n_episodes >= 0: - #For every checkpoint, we create one directory for saving logs file (policy and run mean std) - if n_episodes % EPISODE_WINDOW_DISTILLATION_WIN == 0: - ALGO.save(LOG_DIR + ALGO_NAME +'_' + str(n_episodes)+ "_model.pkl", _locals) - if(CROSS_EVAL):#If we want to do the cross evaluation after the training - eps_path = LOG_DIR + "model_"+ str(n_episodes) - try: - os.mkdir(LOG_DIR + "model_"+ str(n_episodes)) - except OSError: - print("Creation of the directory {} failed".format(eps_path)) - - ALGO.save("{}/{}".format( eps_path, ALGO_NAME + "_model.pkl"), _locals) - try: - if 'env' in _locals: - _locals['env'].save_running_average(eps_path) - else: - _locals['self'].env.save_running_average(eps_path) - except AttributeError: - pass - # if CROSS_EVAL: - # episodeEval(LOG_DIR, EVAL_TASK) + # For every checkpoint, we create one directory for saving logs file (policy and run mean std) + if EPISODE_WINDOW_DISTILLATION_WIN > 0: + if n_episodes % EPISODE_WINDOW_DISTILLATION_WIN == 0: + ALGO.save(LOG_DIR + ALGO_NAME + '_' + str(n_episodes) + "_model.pkl", _locals) + if CROSS_EVAL: # If we want to do the cross evaluation after the training + eps_path = LOG_DIR + "model_" + str(n_episodes) + try: + os.mkdir(LOG_DIR + "model_" + str(n_episodes)) + except OSError: + pass + #print("Creation of the directory {} failed".format(eps_path)) + + ALGO.save("{}/{}".format(eps_path, ALGO_NAME + "_model.pkl"), _locals) + try: + if 'env' in _locals: + _locals['env'].save_running_average(eps_path) + else: + _locals['self'].env.save_running_average(eps_path) + except AttributeError: + pass # Plots in visdom if viz and (n_steps + 1) % LOG_INTERVAL == 0: @@ -201,9 +201,6 @@ def callback(_locals, _globals): is_es=is_es) win_episodes = episodePlot(viz, win_episodes, LOG_DIR, ENV_NAME, ALGO_NAME, window=EPISODE_WINDOW, title=PLOT_TITLE + " [Episodes]", is_es=is_es) - # if CROSS_EVAL: - # win_crossEval= episodesEvalPlot(viz,win_crossEval,LOG_DIR,ENV_NAME,EVAL_TASK, - # title=PLOT_TITLE + " [Cross Evaluation]") n_steps += 1 return True @@ -268,7 +265,7 @@ def main(): help='A cross evaluation from the latest stored model to all tasks') parser.add_argument('--eval-episode-window', type=int, default=400, metavar='N', help='Episode window for saving each policy checkpoint for future distillation(default: 100)') - parser.add_argument('--new-lr',type = float , default =1.e-4 , + parser.add_argument('--new-lr', type=float, default=1.e-4, help="New learning rate ratio to train a pretrained agent") # Ignore unknown args for now @@ -369,6 +366,7 @@ def main(): globals_env_param = sys.modules[env_class.__module__].getGlobals() super_class = registered_env[args.env][1] + # recursive search through all the super classes of the asked environment, in order to get all the arguments. rec_super_class_lookup = {dict_class: dict_super_class for _, (dict_class, dict_super_class, _, _) in registered_env.items()} @@ -405,8 +403,6 @@ def main(): hyperparams["learning_rate"] = lambda f: f * NEW_LR # Train the agent - # episodeEval(LOG_DIR,EVAL_TASK) - # return if args.load_rl_model_path is not None: algo.setLoadPath(args.load_rl_model_path) algo.train(args, callback, env_kwargs=env_kwargs, train_kwargs=hyperparams) From 387411150fa618431cfe73f4988766a74a3d7e68 Mon Sep 17 00:00:00 2001 From: kalifou Date: Fri, 24 May 2019 16:34:27 +0200 Subject: [PATCH 106/141] adapt generative replay for on-policy data generation --- environments/dataset_generator.py | 23 +++++++++++++-------- environments/omnirobot_gym/omnirobot_env.py | 10 ++++++--- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/environments/dataset_generator.py b/environments/dataset_generator.py index 68cb0f3ec..de60a96fb 100644 --- a/environments/dataset_generator.py +++ b/environments/dataset_generator.py @@ -213,7 +213,7 @@ def env_thread(args, thread_num, partition=True): sample = sample.cuda() generated_obs = srl_model.decode(sample) - generated_obs = generated_obs[0].detach().cpu().numpy().transpose(1, 2, 0) + generated_obs = generated_obs[0].detach().cpu().numpy() generated_obs = deNormalize(generated_obs) kwargs_reset['generated_observation'] = generated_obs @@ -233,12 +233,11 @@ def env_thread(args, thread_num, partition=True): # Custom pre-trained Policy (SRL or End-to-End) elif args.run_policy in['custom', 'walker']: - obs = env_norm._normalize_observation(obs) + obs = env_norm._normalize_observation(obs) action = [model.getAction(obs, done)] action_proba = model.getActionProba(obs, done) if args.run_policy == 'walker': action_walker = np.array(walker_path[t]) - # Random Policy else: # Using a target reaching policy (untrained, from camera) when collecting data from real OmniRobot @@ -248,19 +247,25 @@ def env_thread(args, thread_num, partition=True): else: action = [env.action_space.sample()] + # Generative replay +/- for on-policy action if len(args.replay_generative_model) > 0: - sample = Variable(th.randn(1, srl_state_dim)) + if args.run_policy == 'custom': + obs = obs.reshape(1, srl_state_dim) + obs = th.from_numpy(obs.astype(np.float32)).cuda() + z = obs + generated_obs = srl_model.decode(z) + else: + sample = Variable(th.randn(1, srl_state_dim)) - if th.cuda.is_available(): - sample = sample.cuda() + if th.cuda.is_available(): + sample = sample.cuda() - generated_obs = srl_model.decode(sample) - generated_obs = generated_obs[0].detach().cpu().numpy().transpose(1, 2, 0) + generated_obs = srl_model.decode(sample) + generated_obs = generated_obs[0].detach().cpu().numpy() generated_obs = deNormalize(generated_obs) action_to_step = action[0] - kwargs_step = {k: v for (k, v) in [("generated_observation", generated_obs), ("action_proba", action_proba), ("action_grid_walker", action_walker)] if v is not None} diff --git a/environments/omnirobot_gym/omnirobot_env.py b/environments/omnirobot_gym/omnirobot_env.py index ed5099f7a..3bf4274b1 100644 --- a/environments/omnirobot_gym/omnirobot_env.py +++ b/environments/omnirobot_gym/omnirobot_env.py @@ -29,7 +29,7 @@ def recvMatrix(socket): RENDER_HEIGHT = 224 RENDER_WIDTH = 224 RELATIVE_POS = True -N_CONTACTS_BEFORE_TERMINATION = 10 +N_CONTACTS_BEFORE_TERMINATION = 15 #10 DELTA_POS = 0.1 # DELTA_POS for continuous actions N_DISCRETE_ACTIONS = 4 @@ -233,8 +233,10 @@ def step(self, action, generated_observation=None, action_proba=None, action_gri if self.saver is not None: self.saver.step(self.observation, action_from_teacher if action_grid_walker is not None else action_to_step, self.reward, done, self.getGroundTruth(), action_proba=action_proba) + old_observation = self.getObservation() + if self.use_srl: - return self.getSRLState(self.observation), self.reward, done, {} + return self.getSRLState(self.observation if generated_observation is None else old_observation), self.reward, done, {} else: return self.observation, self.reward, done, {} @@ -310,8 +312,10 @@ def reset(self, generated_observation=None, state_override=None): if self.saver is not None: self.saver.reset(self.observation, self.getTargetPos(), self.getGroundTruth()) + old_observation = self.getObservation() + if self.use_srl: - return self.getSRLState(self.observation) + return self.getSRLState(self.observation if generated_observation is None else old_observation) else: return self.observation From 51694e021c43f96c7a049a6434f5e3f929f8751c Mon Sep 17 00:00:00 2001 From: TLESORT Date: Mon, 3 Jun 2019 14:10:50 +0200 Subject: [PATCH 107/141] args.log_dir fix when latestPath is used --- environments/dataset_generator.py | 1 - 1 file changed, 1 deletion(-) diff --git a/environments/dataset_generator.py b/environments/dataset_generator.py index 91c6b7faf..72896c545 100644 --- a/environments/dataset_generator.py +++ b/environments/dataset_generator.py @@ -127,7 +127,6 @@ def env_thread(args, thread_num, partition=True): args.log_dir = latestPath(args.log_custom_policy) else: args.log_dir = args.log_custom_policy - args.log_dir = args.log_custom_policy args.render = args.display args.plotting, args.action_proba = False, False From e1b72bd86719c58ff2acec13c6107415099eac38 Mon Sep 17 00:00:00 2001 From: TLESORT Date: Mon, 3 Jun 2019 14:15:21 +0200 Subject: [PATCH 108/141] more informative print --- replay/enjoy_baselines.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/replay/enjoy_baselines.py b/replay/enjoy_baselines.py index 58880bcb3..9c3a1f469 100644 --- a/replay/enjoy_baselines.py +++ b/replay/enjoy_baselines.py @@ -184,7 +184,7 @@ def main(): set_global_seeds(load_args.seed) # createTensorflowSession() - printYellow("Compiling Policy function....") + printYellow("Compiling Policy function : " + load_path) method = algo_class.load(load_path, args=algo_args) dones = [False for _ in range(load_args.num_cpu)] From 299a374d42ba6bcabfd16ab69ae188371c52ebb7 Mon Sep 17 00:00:00 2001 From: sun-te Date: Mon, 3 Jun 2019 18:55:52 +0200 Subject: [PATCH 109/141] escape task --- config/srl_models_escape.yaml | 9 ++ environments/omnirobot_gym/omnirobot_env.py | 33 +++++- real_robots/constants.py | 2 +- real_robots/omnirobot_simulator_server.py | 57 ++++++++-- .../omnirobot_utils/omnirobot_manager_base.py | 98 ++++++++++++++++-- real_robots/omnirobot_utils/yellow_T.jpg | Bin 0 -> 1035 bytes replay/enjoy_baselines.py | 16 ++- rl_baselines/train.py | 14 ++- 8 files changed, 200 insertions(+), 29 deletions(-) create mode 100644 config/srl_models_escape.yaml create mode 100644 real_robots/omnirobot_utils/yellow_T.jpg diff --git a/config/srl_models_escape.yaml b/config/srl_models_escape.yaml new file mode 100644 index 000000000..a53351a42 --- /dev/null +++ b/config/srl_models_escape.yaml @@ -0,0 +1,9 @@ + +OmnirobotEnv-v0: + # Base path to SRL log folder + # log_folder: srl_zoo/logs/escape_agent/ + log_folder: srl_zoo/logs/escape_agent/ + autoencoder: 19-02-04_23h27_22_custom_cnn_ST_DIM200_autoencoder_reward_inverse_forward/srl_model.pth + srl_combination: 19-06-03_18h38_59_custom_cnn_ST_DIM200_autoencoder_inverse/srl_model.pth + + diff --git a/environments/omnirobot_gym/omnirobot_env.py b/environments/omnirobot_gym/omnirobot_env.py index 3bf4274b1..14cc5531a 100644 --- a/environments/omnirobot_gym/omnirobot_env.py +++ b/environments/omnirobot_gym/omnirobot_env.py @@ -72,8 +72,8 @@ class OmniRobotEnv(SRLGymEnv): def __init__(self, renders=False, name="Omnirobot", is_discrete=True, save_path='srl_zoo/data/', state_dim=-1, learn_states=False, srl_model="raw_pixels", record_data=False, action_repeat=1, random_target=True, - shape_reward=False, simple_continual_target=False, circular_continual_move=False, - square_continual_move=False, eight_continual_move=False, short_episodes=False, + shape_reward=False, simple_continual_target=False, circular_continual_move=False,escape_continual_move=False, + square_continual_move=False, eight_continual_move=False, chasing_continual_move=False, short_episodes=False, state_init_override=None, env_rank=0, srl_pipe=None, **_): super(OmniRobotEnv, self).__init__(srl_model=srl_model, @@ -107,6 +107,8 @@ def __init__(self, renders=False, name="Omnirobot", is_discrete=True, save_path= self.circular_continual_move = circular_continual_move self.square_continual_move = square_continual_move self.eight_continual_move = eight_continual_move + self.chasing_continual_move = chasing_continual_move + self.escape_continual_move = escape_continual_move self.short_episodes = short_episodes if self._is_discrete: @@ -139,6 +141,8 @@ def __init__(self, renders=False, name="Omnirobot", is_discrete=True, save_path= circular_continual_move=circular_continual_move, square_continual_move=square_continual_move, eight_continual_move=eight_continual_move, + chasing_continual_move=chasing_continual_move, + escape_continual_move = escape_continual_move, output_size=[RENDER_WIDTH, RENDER_HEIGHT], random_target=self._random_target, state_init_override=state_init_override) @@ -184,6 +188,25 @@ def actionPolicyTowardTarget(self): else: return DELTA_POS if self.robot_pos[1] < self.target_pos[1] else -DELTA_POS + def actionPolicyAwayTarget(self): + """ + :return: (int) action + """ + if abs(self.robot_pos[0] - self.target_pos[0]) > abs(self.robot_pos[1] - self.target_pos[1]): + + if self._is_discrete: + return int(Move.BACKWARD) if self.robot_pos[0] < self.target_pos[0] else int(Move.FORWARD) + # forward # backward + else: + return -DELTA_POS if self.robot_pos[0] < self.target_pos[0] else +DELTA_POS + else: + if self._is_discrete: + # left # right + return int(Move.RIGHT) if self.robot_pos[1] < self.target_pos[1] else int(Move.LEFT) + else: + return -DELTA_POS if self.robot_pos[1] < self.target_pos[1] else +DELTA_POS + + def step(self, action, generated_observation=None, action_proba=None, action_grid_walker=None): """ @@ -221,6 +244,8 @@ def step(self, action, generated_observation=None, action_proba=None, action_gri {"command": "action", "action": self.action, "is_discrete": self._is_discrete, "step_counter": self._env_step_counter}) + + # Receive state data (position, etc), important to update state related values self.getEnvState() @@ -232,7 +257,8 @@ def step(self, action, generated_observation=None, action_proba=None, action_gri if self.saver is not None: self.saver.step(self.observation, action_from_teacher if action_grid_walker is not None else action_to_step, - self.reward, done, self.getGroundTruth(), action_proba=action_proba) + self.reward, done, self.getGroundTruth(), action_proba=action_proba, + target_pos=self.getTargetPos()) old_observation = self.getObservation() if self.use_srl: @@ -361,7 +387,6 @@ def render(self, mode='rgb_array'): self.visualizeBoundary() self.image_plot = plt.imshow(self.observation_with_boundary, cmap='gray') self.image_plot.axes.grid(False) - else: self.visualizeBoundary() self.image_plot.set_data(self.observation_with_boundary) diff --git a/real_robots/constants.py b/real_robots/constants.py index cfa23e7a5..cfcd7fd58 100644 --- a/real_robots/constants.py +++ b/real_robots/constants.py @@ -120,7 +120,7 @@ class Move(Enum): STOP = 4 STEP_DISTANCE = 0.1 # meter, distance for each step - + STEP_DISTANCE_TARGET = 0.05 # moving distance for each step # For continuous action, # Define the action_bounds ACTION_POSITIVE_LOW = 0.0 diff --git a/real_robots/omnirobot_simulator_server.py b/real_robots/omnirobot_simulator_server.py index 3fd781a4d..2d2dd0bcd 100755 --- a/real_robots/omnirobot_simulator_server.py +++ b/real_robots/omnirobot_simulator_server.py @@ -97,6 +97,8 @@ def __init__(self, init_x, init_y, init_yaw, origin_size, cropped_size, # Distance for each step self.step_distance = STEP_DISTANCE + self.step_distance_target =STEP_DISTANCE_TARGET + with open(camera_info_path, 'r') as stream: try: contents = yaml.load(stream) @@ -182,7 +184,6 @@ def renderTarget(self): self.pos_transformer.phyPosGround2PixelPos( self.target_pos.reshape(2, 1)), self.target_yaw, np.random.randn() * NOISE_VAR_TARGET_SIZE_PROPOTION + 1.0) - def renderRobot(self): """ render the image. @@ -191,6 +192,7 @@ def renderRobot(self): self.pos_transformer.phyPosGround2PixelPos( self.robot_pos.reshape(2, 1)), self.robot_yaw, self.robot_marker_size_proprotion) + def getHistorySize(self): return self.history_size @@ -292,6 +294,39 @@ def moveContinous(self, action): self.setRobotCmd( self.robot_pos_cmd[0] + action[0], self.robot_pos_cmd[1] + action[1], self.robot_yaw_cmd) + + + def targetMoveDiscrete(self, target_yaw): + pi = np.pi + assert target_yaw>-pi and target_yaw=pi/4 and target_yaw < pi*3/4):#Up + self.setTargetCmd( + self.target_pos_cmd[0] , self.target_pos_cmd[1]- self.step_distance_target, target_yaw) + elif(target_yaw>= 3/4*pi and target_yaw < 5/4 *pi): + self.setTargetCmd( + self.target_pos_cmd[0]+ self.step_distance_target, self.target_pos_cmd[1] , target_yaw) + elif (target_yaw >= 5 / 4 * pi and target_yaw < 7 / 4 * pi): + self.setTargetCmd( + self.target_pos_cmd[0] , self.target_pos_cmd[1]+self.step_distance_target , target_yaw) + else: + self.setTargetCmd( + self.target_pos_cmd[0] -self.step_distance_target, self.target_pos_cmd[1] , target_yaw) + + + + + def targetMoveContinous(self, target_yaw): + """ + Perform a continuous displacement of dx, dy + """ + self.target_yaw = target_yaw + action = ( + self.step_distance_target * np.cos(target_yaw), self.step_distance_target * np.sin(target_yaw)) + self.setTargetCmd( + self.target_pos_cmd[0] +action[0] , self.target_pos_cmd[1] + action[1], target_yaw) + + def moveByVelocityCmd(self, speed_x, speed_y, speed_yaw): """ simuate the robot moved by velocity command @@ -343,7 +378,7 @@ def moveByWheelsCmd(self, left_speed, front_speed, right_speed): local_rot_speed = - self.last_wheel_speeds_cmd[1] / (3.0 * OMNIROBOT_L) \ - self.last_wheel_speeds_cmd[0] / (3.0 * OMNIROBOT_L) \ - self.last_wheel_speeds_cmd[2] / (3.0 * OMNIROBOT_L) - + # translate the last velocity cmd in robot local coordiante to position cmd in gound coordiante cos_direction = np.cos(self.robot_yaw) sin_direction = np.sin(self.robot_yaw) @@ -374,8 +409,8 @@ def normalizeAngle(angle): class OmniRobotSimulatorSocket(OmnirobotManagerBase): def __init__(self, **args): ''' - Simulate the zmq socket like real omnirobot server - :param **args arguments + Simulate the zmq socket like real omnirobot server + :param **args arguments ''' super(OmniRobotSimulatorSocket, self).__init__() @@ -408,6 +443,8 @@ def __init__(self, **args): elif self.new_args["square_continual_move"] or self.new_args["eight_continual_move"]: self.new_args["target_marker_path"] = "real_robots/omnirobot_utils/green_square.png" + elif self.new_args["chasing_continual_move"] or self.new_args["escape_continual_move"]: + self.new_args["target_marker_path"] = "real_robots/omnirobot_utils/yellow_T.jpg" else: # for black target, use target_margin4_pixel.png", self.new_args["target_marker_path"] = "real_robots/omnirobot_utils/red_target_margin4_pixel_480x480.png" @@ -415,16 +452,18 @@ def __init__(self, **args): super(OmniRobotSimulatorSocket, self).__init__(simple_continual_target=self.new_args["simple_continual_target"], circular_continual_move=self.new_args["circular_continual_move"], square_continual_move=self.new_args["square_continual_move"], - eight_continual_move=self.new_args["eight_continual_move"]) + eight_continual_move=self.new_args["eight_continual_move"], + chasing_continual_move=self.new_args["chasing_continual_move"], + escape_continual_move=self.new_args["escape_continual_move"] ) assert len(self.new_args['robot_marker_margin']) == 4 assert len(self.new_args['target_marker_margin']) == 4 assert len(self.new_args['output_size']) == 2 - self.robot = OmniRobotEnvRender(**self.new_args) self.episode_idx = 0 self._random_target = self.new_args["random_target"] - if self.new_args["simple_continual_target"]: + if sum((self.new_args["simple_continual_target"] + , self.new_args["chasing_continual_move"] , self.new_args["escape_continual_move"]))>0: self._random_target = True self.state_init_override = self.new_args['state_init_override'] self.resetEpisode() # for a random target initial position @@ -432,7 +471,7 @@ def __init__(self, **args): def resetEpisode(self): """ override the original method - Give the correct sequance of commands to the robot + Give the correct sequance of commands to the robot to rest environment between the different episodes """ if self.second_cam_topic is not None: @@ -462,8 +501,8 @@ def resetEpisode(self): def send_json(self, msg): # env send msg to render self.processMsg(msg) - self.robot.renderRobot() + self.robot.renderTarget() self.img = self.robot.getCroppedImage() self.img = self.robot.renderEnvLuminosityNoise(self.img, noise_var=NOISE_VAR_ENVIRONMENT, in_RGB=False, diff --git a/real_robots/omnirobot_utils/omnirobot_manager_base.py b/real_robots/omnirobot_utils/omnirobot_manager_base.py index 18df68b3c..e9130803d 100644 --- a/real_robots/omnirobot_utils/omnirobot_manager_base.py +++ b/real_robots/omnirobot_utils/omnirobot_manager_base.py @@ -1,11 +1,12 @@ from __future__ import division, print_function, absolute_import - +import math from real_robots.constants import * class OmnirobotManagerBase(object): def __init__(self, simple_continual_target=False, circular_continual_move=False, square_continual_move=False, - eight_continual_move=False, lambda_c=10.0, second_cam_topic=None, state_init_override=None): + eight_continual_move=False, chasing_continual_move=False, escape_continual_move= False, + lambda_c=10.0, second_cam_topic=None, state_init_override=None): """ This class is the basic class for omnirobot server, and omnirobot simulator's server. This class takes omnirobot position at instant t, and takes the action at instant t, @@ -18,8 +19,11 @@ def __init__(self, simple_continual_target=False, circular_continual_move=False, self.circular_continual_move = circular_continual_move self.square_continual_move = square_continual_move self.eight_continual_move = eight_continual_move + self.chasing_continual_move = chasing_continual_move + self.escape_continual_move = escape_continual_move self.lambda_c = lambda_c self.state_init_override = state_init_override + self.step_counter = 0 # the abstract object for robot, # can be the real robot (Omnirobot class) @@ -29,7 +33,7 @@ def __init__(self, simple_continual_target=False, circular_continual_move=False, def rightAction(self): """ Let robot execute right action, and checking the boundary - :return has_bumped: (bool) + :return has_bumped: (bool) """ if self.robot.robot_pos[1] - STEP_DISTANCE > MIN_Y: self.robot.right() @@ -41,7 +45,7 @@ def rightAction(self): def leftAction(self): """ Let robot execute left action, and checking the boundary - :return has_bumped: (bool) + :return has_bumped: (bool) """ if self.robot.robot_pos[1] + STEP_DISTANCE < MAX_Y: self.robot.left() @@ -53,7 +57,7 @@ def leftAction(self): def forwardAction(self): """ Let robot execute forward action, and checking the boundary - :return has_bumped: (bool) + :return has_bumped: (bool) """ if self.robot.robot_pos[0] + STEP_DISTANCE < MAX_X: self.robot.forward() @@ -65,7 +69,7 @@ def forwardAction(self): def backwardAction(self): """ Let robot execute backward action, and checking the boundary - :return has_bumped: (bool) + :return has_bumped: (bool) """ if self.robot.robot_pos[0] - STEP_DISTANCE > MIN_X: self.robot.backward() @@ -77,7 +81,7 @@ def backwardAction(self): def moveContinousAction(self, msg): """ Let robot execute continous action, and checking the boundary - :return has_bumped: (bool) + :return has_bumped: (bool) """ if MIN_X < self.robot.robot_pos[0] + msg['action'][0] < MAX_X and \ MIN_Y < self.robot.robot_pos[1] + msg['action'][1] < MAX_Y: @@ -86,6 +90,44 @@ def moveContinousAction(self, msg): else: has_bumped = True return has_bumped + def targetMoveContinousAction(self, target_yaw): + """ + Let robot execute continous action, and checking the boundary + :return has_bumped: (bool) + """ + action = ( + self.robot.step_distance_target * np.cos(target_yaw), self.robot.step_distance_target * np.sin(target_yaw)) + if MIN_X < self.robot.target_pos[0] + action[0] < MAX_X and \ + MIN_Y < self.robot.target_pos[1] + action[1] < MAX_Y: + self.robot.targetMoveContinous(target_yaw) + has_bumped = False + else: + has_bumped = True + return has_bumped + + def targetMoveDiscreteAction(self,target_yaw): + + self.robot.targetMoveDiscrete(target_yaw) + + def targetPolicy(self, directed = False): + """ + The policy for the target + :param directed: directed to the robot(agent) + :return: the angle to go for the target + """ + if(directed): + dy = self.robot.robot_pos[1] - self.robot.target_pos[1] + dx = self.robot.robot_pos[0] - self.robot.target_pos[0] + r = math.sqrt(dy**2+dx**2) + dy /= r + dx /= r + yaw = math.atan2(dy, dx ) + return yaw + + period = 70 + yaw = (2*(self.step_counter % period )/period-1)*np.pi + + return yaw def sampleRobotInitalPosition(self): """ @@ -95,10 +137,10 @@ def sampleRobotInitalPosition(self): random_init_x = np.random.random_sample() * (INIT_MAX_X - INIT_MIN_X) + INIT_MIN_X random_init_y = np.random.random_sample() * (INIT_MAX_Y - INIT_MIN_Y) + INIT_MIN_Y return [random_init_x, random_init_y] - + def resetEpisode(self): """ - Give the correct sequance of commands to the robot + Give the correct sequance of commands to the robot to rest environment between the different episodes """ if self.second_cam_topic is not None: @@ -118,6 +160,7 @@ def processMsg(self, msg): if command == 'reset': action = None self.episode_idx += 1 + self.step_counter = 0 # empty list of previous states self.robot.emptyHistory() @@ -135,6 +178,7 @@ def processMsg(self, msg): exit(0) else: raise ValueError("Unknown command: {}".format(msg)) + self.step_counter +=1 has_bumped = False # We are always facing North @@ -155,6 +199,10 @@ def processMsg(self, msg): else: print("Unsupported action: ", action) + + + + # Determinate the reward for this step if self.circular_continual_move or self.square_continual_move or self.eight_continual_move: @@ -187,6 +235,38 @@ def processMsg(self, msg): if has_bumped: self.reward += self.lambda_c * self.lambda_c * REWARD_BUMP_WALL + elif self.chasing_continual_move: + # The action for target agent + target_yaw = self.targetPolicy() + + self.targetMoveContinousAction(target_yaw) + dis = np.linalg.norm(np.array(self.robot.robot_pos) - np.array(self.robot.target_pos)) + if(dis<0.4 and dis > 0.3): + self.reward = REWARD_TARGET_REACH + elif has_bumped: + self.reward = REWARD_BUMP_WALL + else: + self.reward = REWARD_NOTHING + + elif self.escape_continual_move: + + dis = np.linalg.norm(np.array(self.robot.robot_pos) - np.array(self.robot.target_pos)) + + if has_bumped or dis<0.3: + self.reward = REWARD_BUMP_WALL + # elif(dis<0.2): + # self.reward = REWARD_BUMP_WALL + elif(dis>=0.3 and dis<0.6): + self.reward = REWARD_TARGET_REACH + else: + self.reward = REWARD_NOTHING + + target_yaw = self.targetPolicy(directed=True) + #self.targetMoveContinousAction(target_yaw) + self.targetMoveDiscreteAction(target_yaw) + + + else: # Consider that we reached the target if we are close enough # we detect that computing the difference in area between TARGET_INITIAL_AREA diff --git a/real_robots/omnirobot_utils/yellow_T.jpg b/real_robots/omnirobot_utils/yellow_T.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6f7496527ba1220dacb402b4cc4666b06233a319 GIT binary patch literal 1035 zcmex=U zW@aX!`+*(+s;&jfGq4D<3Mm>ovIz$!vMUve7&T5@$f4}C@t|nX#SbdRNkvVZTw>x9 zl2WQ_>Kd9_CZ=ZQ7M51dF0O9w9-dyoA)#U65s^{JDXD4c8JStdC8cHM6_r)ZEv;?s z9i3g1CQq3GGAU*RJ2V zdF$b$$4{OPfBE|D`;VW$K>lK6V1{@LNJ2b@<}X2@znFm0!om*n7b88f2KE_o9%~}Y zXK;@p{B?_ghnW!=dCYw}ZAn?IzWT=LMO|8FnYuITqk!$%r^ULc^b*&_F z7JiORyW{p?hlKJ@xvj^4gh%?yJ<610n|(H52X9Yt?DLMTB^Tc+@2HSUc)yu(V;|?g zsgIJM$0jA7mfiOG{gt0*&Mi|+dilvU^TW@#b^D(b%>U5!`u^vK{~0Du{?E|0_@7{G z^}ibXPe%10L-+n?;JhOLg>Uk|fBhd8{}Wze|3X&%?_c?cQPnkv|JAO4{VezEoXh`e z^T!Ap@4+1>Wjnu^Uavn?%Kn#m z$$y6Zi~nfP`DnLh*3mEJn%qu83Nv))J$e3h?T4#{MRQjjRQ+2y*TU<@%PU(eROMfv zof#77TE)IXkK48{&#EdhxOpa}bao*t$77aqxvwWKMqF7aHM!^BN6S|a7ltj- W@~(LMnM-5QHY-?&qSO5UZvp_8z@kY2 literal 0 HcmV?d00001 diff --git a/replay/enjoy_baselines.py b/replay/enjoy_baselines.py index 54f63f0f9..78c09dccf 100644 --- a/replay/enjoy_baselines.py +++ b/replay/enjoy_baselines.py @@ -67,6 +67,12 @@ def parseArguments(): parser.add_argument('-sqc', '--square-continual', action='store_true', default=False, help='Green square target for task 3 of continual learning scenario. ' + 'The task is: robot should turn in square around the target.') + parser.add_argument('-chc', '--chasing-continual', action='store_true', default=False, + help='Two chasing robots in the same domain of environment' + + 'The task is: one robot should keep a certain distance towards the other.') + parser.add_argument('-esc', '--escape-continual', action='store_true', default=False, + help='Two chasing robots in the same domain of environment' + + 'The task is: the trainable agent tries to escape from the "zombie" robot.') args, unknown = parser.parse_known_args() assert sum([args.simple_continual, args.circular_continual, args.square_continual]) <= 1, \ "For continual SRL and RL, please provide only one scenario at the time and use OmnirobotEnv-v0 environment !" @@ -130,12 +136,17 @@ def loadConfigAndSetup(load_args): env_kwargs["circular_continual_move"] = env_globals.get("circular_continual_move", False) env_kwargs["square_continual_move"] = env_globals.get("square_continual_move", False) env_kwargs["eight_continual_move"] = env_globals.get("eight_continual_move", False) - + env_kwargs["chasing_continual_move"] = env_globals.get("chasing_continual_move", False) + env_kwargs["escape_continual_move"] = env_globals.get("escape_continual_move", False) # If overriding the environment for specific Continual Learning tasks - if sum([load_args.simple_continual, load_args.circular_continual, load_args.square_continual]) >= 1: + if sum([load_args.simple_continual, load_args.circular_continual, + load_args.escape_continual, load_args.chasing_continual, + load_args.square_continual]) >= 1: env_kwargs["simple_continual_target"] = load_args.simple_continual env_kwargs["circular_continual_move"] = load_args.circular_continual env_kwargs["square_continual_move"] = load_args.square_continual + env_kwargs["chasing_continual_move"] =load_args.chasing_continual + env_kwargs["escape_continual_move"] = load_args.escape_continual env_kwargs["random_target"] = not (load_args.circular_continual or load_args.square_continual) srl_model_path = None @@ -196,7 +207,6 @@ def main(): set_global_seeds(load_args.seed) # createTensorflowSession() - printYellow("Compiling Policy function....") printYellow(load_path) method = algo_class.load(load_path, args=algo_args) diff --git a/rl_baselines/train.py b/rl_baselines/train.py index bdcf3c548..5d92599b6 100644 --- a/rl_baselines/train.py +++ b/rl_baselines/train.py @@ -35,7 +35,7 @@ PLOT_TITLE = "" EPISODE_WINDOW = 40 # For plotting moving average EVAL_TASK=['cc','sc','sqc'] -CROSS_EVAL = True +CROSS_EVAL = False EPISODE_WINDOW_DISTILLATION_WIN = 20 NEW_LR=0.001 @@ -110,6 +110,8 @@ def configureEnvAndLogFolder(args, env_kwargs, all_models): env_kwargs["circular_continual_move"] = args.circular_continual env_kwargs["square_continual_move"] = args.square_continual env_kwargs["eight_continual_move"] = args.eight_continual + env_kwargs["chasing_continual_move"] = args.chasing_continual + env_kwargs["escape_continual_move"] = args.escape_continual # Add date + current time args.log_dir += "{}/{}/".format(ALGO_NAME, datetime.now().strftime("%y-%m-%d_%Hh%M_%S")) @@ -255,6 +257,12 @@ def main(): parser.add_argument('-ec', '--eight-continual', action='store_true', default=False, help='Green square target for task 4 of continual learning scenario. ' + 'The task is: robot should do the eigth with the target as center of the shape.') + parser.add_argument('-chc', '--chasing-continual', action='store_true', default=False, + help='Two chasing robots in the same domain of environment' + + 'The task is: one robot should keep a certain distance towars the other.') + parser.add_argument('-esc', '--escape-continual', action='store_true', default=False, + help='Two chasing robots in the same domain of environment' + + 'The task is: the trainable agent tries to escape from the "zombie" robot.') parser.add_argument('--teacher-data-folder', type=str, default="", help='Dataset folder of the teacher(s) policy(ies)', required=False) parser.add_argument('--epochs-distillation', type=int, default=30, metavar='N', @@ -296,8 +304,8 @@ def main(): break assert found, "Error: srl_model {}, is not compatible with the {} environment.".format(args.srl_model, args.env) - assert not(sum([args.simple_continual, args.circular_continual, args.square_continual, args.eight_continual]) \ - > 1 and args.env == "OmnirobotEnv-v0"), \ + assert not(sum([args.simple_continual, args.circular_continual, args.square_continual, args.eight_continual, + args.chasing_continual, args.escape_continual]) > 1 and args.env == "OmnirobotEnv-v0"), \ "For continual SRL and RL, please provide only one scenario at the time and use OmnirobotEnv-v0 environment !" assert not(args.algo == "distillation" and (args.teacher_data_folder == '' or args.continuous_actions is True)), \ From 86c7a731fd00972f62e7f79b74cf66731fd8cb88 Mon Sep 17 00:00:00 2001 From: sun-te Date: Wed, 5 Jun 2019 14:37:25 +0200 Subject: [PATCH 110/141] update for escape evaluation --- environments/dataset_generator.py | 13 +++ environments/omnirobot_gym/omnirobot_env.py | 9 ++- .../omnirobot_utils/omnirobot_manager_base.py | 2 +- replay/cross_eval_plot.py | 80 ++++++++++++++----- rl_baselines/cross_eval.py | 29 ++++--- rl_baselines/train.py | 17 ++-- 6 files changed, 107 insertions(+), 43 deletions(-) diff --git a/environments/dataset_generator.py b/environments/dataset_generator.py index 551a3f6d0..dd43251fd 100644 --- a/environments/dataset_generator.py +++ b/environments/dataset_generator.py @@ -109,6 +109,8 @@ def env_thread(args, thread_num, partition=True): "simple_continual_target": args.simple_continual, "circular_continual_move": args.circular_continual, "square_continual_move": args.square_continual, + "chasing_continual_move":args.chasing_continual, + "escape_continual_move": args.escape_continual, "short_episodes": args.short_episodes } @@ -128,6 +130,7 @@ def env_thread(args, thread_num, partition=True): args.log_dir = latestPath(args.log_custom_policy) else: args.log_dir = args.log_custom_policy + args.log_dir = args.log_custom_policy args.render = args.display args.plotting, args.action_proba = False, False @@ -141,6 +144,9 @@ def env_thread(args, thread_num, partition=True): env_kwargs["circular_continual_move"] = env_kwargs_extra.get("circular_continual_move", False) env_kwargs["square_continual_move"] = env_kwargs_extra.get("square_continual_move", False) env_kwargs["eight_continual_move"] = env_kwargs_extra.get("eight_continual_move", False) + env_kwargs["chasing_continual_move"] = env_kwargs_extra.get("chasing_continual_move",False) + env_kwargs["escape_continual_move"] = env_kwargs_extra.get("escape_continual_move", False) + eps = 0.2 env_kwargs["state_init_override"] = np.array([MIN_X + eps, MAX_X - eps]) \ @@ -284,6 +290,7 @@ def env_thread(args, thread_num, partition=True): print("{:.2f} FPS".format(frames * args.num_cpu / (time.time() - start_time))) + def main(): parser = argparse.ArgumentParser(description='Deteministic dataset generator for SRL training ' + '(can be used for environment testing)') @@ -335,6 +342,12 @@ def main(): parser.add_argument('-sqc', '--square-continual', action='store_true', default=False, help='Green square target for task 3 of continual learning scenario. ' + 'The task is: robot should turn in square around the target.') + parser.add_argument('-chc', '--chasing-continual', action='store_true', default=False, + help='Two chasing robots in the same domain of environment' + + 'The task is: one robot should keep a certain distance towars the other.') + parser.add_argument('-esc', '--escape-continual', action='store_true', default=False, + help='Two chasing robots in the same domain of environment' + + 'The task is: the trainable agent tries to escape from the "zombie" robot.') parser.add_argument('--short-episodes', action='store_true', default=False, help='Generate short episodes (only 10 contacts with the target allowed).') parser.add_argument('--episode', type=int, default=-1, diff --git a/environments/omnirobot_gym/omnirobot_env.py b/environments/omnirobot_gym/omnirobot_env.py index 14cc5531a..a51bdd00f 100644 --- a/environments/omnirobot_gym/omnirobot_env.py +++ b/environments/omnirobot_gym/omnirobot_env.py @@ -28,7 +28,8 @@ def recvMatrix(socket): RENDER_HEIGHT = 224 RENDER_WIDTH = 224 -RELATIVE_POS = True +#RELATIVE_POS = True +RELATIVE_POS = False N_CONTACTS_BEFORE_TERMINATION = 15 #10 DELTA_POS = 0.1 # DELTA_POS for continuous actions @@ -260,7 +261,6 @@ def step(self, action, generated_observation=None, action_proba=None, action_gri self.reward, done, self.getGroundTruth(), action_proba=action_proba, target_pos=self.getTargetPos()) old_observation = self.getObservation() - if self.use_srl: return self.getSRLState(self.observation if generated_observation is None else old_observation), self.reward, done, {} else: @@ -302,14 +302,15 @@ def getGroundTruthDim(): """ :return: (int) """ - return 2 + return 4 def getGroundTruth(self): """ Alias for getRobotPos for compatibility between envs :return: (numpy array) """ - return np.array(self.getRobotPos()) + #return np.array(self.getRobotPos()) + return np.append(self.getRobotPos(),self.getTargetPos()) def getRobotPos(self): """ diff --git a/real_robots/omnirobot_utils/omnirobot_manager_base.py b/real_robots/omnirobot_utils/omnirobot_manager_base.py index e9130803d..7c0171f8e 100644 --- a/real_robots/omnirobot_utils/omnirobot_manager_base.py +++ b/real_robots/omnirobot_utils/omnirobot_manager_base.py @@ -248,6 +248,7 @@ def processMsg(self, msg): else: self.reward = REWARD_NOTHING + elif self.escape_continual_move: dis = np.linalg.norm(np.array(self.robot.robot_pos) - np.array(self.robot.target_pos)) @@ -266,7 +267,6 @@ def processMsg(self, msg): self.targetMoveDiscreteAction(target_yaw) - else: # Consider that we reached the target if we are close enough # we detect that computing the difference in area between TARGET_INITIAL_AREA diff --git a/replay/cross_eval_plot.py b/replay/cross_eval_plot.py index 12206e996..4fc2d42dc 100644 --- a/replay/cross_eval_plot.py +++ b/replay/cross_eval_plot.py @@ -8,23 +8,37 @@ import numpy as np import seaborn as sns from matplotlib import rc - +from matplotlib.ticker import FuncFormatter from replay.aggregate_plots import lightcolors, darkcolors, Y_LIM_SHAPED_REWARD, Y_LIM_SPARSE_REWARD, millions from rl_baselines.cross_eval import dict2array from rl_baselines.visualize import smoothRewardCurve # Init seaborn sns.set() # Style for the title -fontstyle = {'fontname': 'DejaVu Sans', 'fontsize': 20, 'fontweight': 'bold'} +fontstyle = {'fontname': 'DejaVu Sans', 'fontsize': 24, 'fontweight': 'bold'} rc('font', weight='bold') -def crossEvalPlot(res, tasks, title, y_limits): - y_array = res[:, :, 1:] - # y_array = np.sort(res[:, :, 1:], axis=2) - # y_array = np.mean(y_array[:,:,1:],axis=2) +def crossEvalPlot(res, tasks, title, y_limits , truncate_x, plot_mean=False, timesteps=False): - x = res[:, :, 0][0] + index_x = -1 + episodes = res[:,:,0][0] + if (truncate_x>-1): + for eps in episodes: + index_x += 1 + if(eps >= truncate_x): + break + if(index_x ==-1 ): + y_array = res[:, :, 1:] + x = res[:, :, 0][0] + else: + y_array = res[:, :index_x, 1:] + x = res[:, :index_x, 0][0] + if(timesteps): + x = 250 * x + sum_mean = [] + sum_s = [] + sum_n = [] fig = plt.figure(title) for i in range(len(y_array)): @@ -36,32 +50,58 @@ def crossEvalPlot(res, tasks, title, y_limits): # Compute standard error s = np.squeeze(np.asarray(np.std(y, axis=0))) n = y.shape[0] + sum_mean +=[m] + sum_s +=[s] + sum_n +=[n] plt.fill_between(x, m - s / np.sqrt(n), m + s / np.sqrt(n), color=lightcolors[i % len(lightcolors)], alpha=0.5) plt.plot(x, m, color=darkcolors[i % len(darkcolors)], label=label, linewidth=2) - plt.xlabel('Number of Episodes') - plt.ylabel('Rewards', fontsize=20, fontweight='bold') + #reward_sum = np.concatenate([res[0, :index_x, 1:], res[1, :index_x, 1:]], axis=1) + + if(plot_mean): + + m = np.mean(sum_mean, axis=0) + # Compute standard error + s = np.mean(sum_s) + n = np.mean(n) + plt.fill_between(x, m - s / np.sqrt(n), m + s / np.sqrt(n), color=lightcolors[4 % len(lightcolors)], alpha=0.5) + plt.plot(x, m, color=darkcolors[4 % len(darkcolors)], label='mean reward', linewidth=2) + + if timesteps: + formatter = FuncFormatter(millions) + plt.xlabel('Number of Timesteps') + fig.axes[0].xaxis.set_major_formatter(formatter) + else: + plt.xlabel('Number of Episodes') + plt.ylabel('Normalized Rewards', fontsize=15 , fontweight='bold') plt.title(title, **fontstyle) if (y_limits[0] != y_limits[1]): plt.ylim(y_limits) - plt.legend(framealpha=0.8, frameon=True, labelspacing=0.01, loc='lower right', fontsize=18) + plt.legend(framealpha=0.8, frameon=True, labelspacing=0.01, loc='lower right', fontsize=20) plt.show() -def smoothPlot(res, tasks, title, y_limits): +def smoothPlot(res, tasks, title, y_limits,timesteps): y = np.mean(res[:, :, 1:], axis=2) # y = np.sort(res[:, :, 1:], axis=2) # y = np.mean(y[:,:,1:],axis=2) x = res[:, :, 0][0] + if(timesteps): + x = x*250 print(y.shape, x.shape) fig = plt.figure(title) for i in range(len(y)): label = tasks[i] - tmp_x, tmp_y = smoothRewardCurve(x, y[i], conv_len=3) + tmp_x, tmp_y = smoothRewardCurve(x, y[i], conv_len=2) plt.plot(tmp_x, tmp_y, color=darkcolors[i % len(darkcolors)], label=label, linewidth=2) - plt.xlabel('Number of Episodes') + if (timesteps): + formatter = FuncFormatter(millions) + plt.xlabel('Number of Timesteps') + fig.axes[0].xaxis.set_major_formatter(formatter) + else: + plt.xlabel('Number of Episodes') plt.ylabel('Rewards', fontsize=20, fontweight='bold') plt.title(title, **fontstyle) @@ -83,10 +123,13 @@ def smoothPlot(res, tasks, title, y_limits): parser.add_argument('--y-lim', nargs=2, type=float, default=[-1, -1], help="limits for the y axis") parser.add_argument('--truncate-x', type=int, default=-1, help="Truncate the experiments after n ticks on the x-axis (default: -1, no truncation)") - parser.add_argument('--eval-tasks', type=str, nargs='+', default=['Circular', 'Target Reaching','Square'], + parser.add_argument('--eval-tasks', type=str, nargs='+', default=['cc', 'esc','sc'], help='A cross evaluation from the latest stored model to all tasks') parser.add_argument('-s','--smooth', action='store_true', default=False, help='Plot with a smooth mode') + parser.add_argument('--timesteps', action = 'store_true',default=False, + help='Plot with timesteps') + args = parser.parse_args() @@ -94,7 +137,7 @@ def smoothPlot(res, tasks, title, y_limits): title = args.title y_limits = args.y_lim tasks = args.eval_tasks - + truncate_x= args.truncate_x assert (os.path.isfile(load_path) and load_path.split('.')[-1]=='pkl'), 'Please load a valid .pkl file' @@ -104,9 +147,10 @@ def smoothPlot(res, tasks, title, y_limits): data = pickle.load(file) - res = dict2array(['cc', 'sc'], data) + res = dict2array(args.eval_tasks, data) + print("{} episodes evaluations to plot".format(res.shape[1])) if(args.smooth): - smoothPlot(res[:,1:],tasks,title,y_limits) + smoothPlot(res[:,1:],tasks,title,y_limits,args.timesteps) else: - crossEvalPlot(res[:,1:], tasks, title,y_limits) + crossEvalPlot(res[:,:], tasks, title,y_limits, truncate_x,args.timesteps) diff --git a/rl_baselines/cross_eval.py b/rl_baselines/cross_eval.py index 4ad858895..9b34862d3 100644 --- a/rl_baselines/cross_eval.py +++ b/rl_baselines/cross_eval.py @@ -20,11 +20,11 @@ def dict2array(tasks,data): """ res=[] for t in tasks: - if(t=='sc'): + if(t!='cc'): max_reward=250 min_reward = 0 else: - max_reward = 1900 + max_reward = 1920 min_reward = 0 data[t]=np.array(data[t]).astype(float) @@ -90,6 +90,9 @@ def policyCrossEval(log_dir,task,episode,model_path, num_timesteps=2000,num_cpu= ,help='RL algo to use') parser.add_argument('--num-iteration', type=int, default=5, help='number of time each algorithm should be run the eval (N seeds).') + parser.add_argument('--scheduler',type = int, default=1, + help='A step scheduler for the evaluation') + args, unknown = parser.parse_known_args() @@ -98,22 +101,26 @@ def policyCrossEval(log_dir,task,episode,model_path, num_timesteps=2000,num_cpu= episodes, policy_paths = allPolicyFiles(log_dir) index_to_begin =0 - + # The interval to skip, how many times we skip the evaluate + # For example: if interval = 4 and episode, then the evaluation be be performed each 4* saved_checkpoint_episode + interval_len = args.scheduler #To verify if the episodes have been evaluated before if(os.path.isfile(args.log_dir+'/eval.pkl')): with open(args.log_dir+'/eval.pkl', "rb") as file: rewards = pickle.load(file) + max_eps = max(np.array(rewards['episode']).astype(int)) index_to_begin = episodes.astype(int).tolist().index(max_eps)+1 + else: - task_labels = ['cc', 'sc'] + task_labels = ['cc', 'sc','esc'] rewards = {} rewards['episode'] = [] rewards['policy'] = [] - for t in ['cc', 'sc']: + for t in ['cc', 'sc','esc']: rewards[t] = [] @@ -123,21 +130,23 @@ def policyCrossEval(log_dir,task,episode,model_path, num_timesteps=2000,num_cpu= printGreen("The evaluation will begin from {}".format(episodes[index_to_begin])) - last_mean = [250.,1900.] - run_mean = [0,0] + last_mean = [250.,250,1900] + run_mean = [0,0,0] - for k in range(index_to_begin, len(episodes) ): + for k in range(index_to_begin, len(episodes) ,interval_len): + # if(interval_len > 1 and int(episodes[k])>=episode_schedule): + # k += interval_len-1 + printGreen("Evaluation for episode: {}".format(episodes[k])) increase_interval = True model_path=policy_paths[k] - for t , task_label in enumerate(["-sc", "-cc"]): + for t , task_label in enumerate(["-esc","-sc", "-cc" ]): local_reward = [int(episodes[k])] for seed_i in range(args.num_iteration): - command_line_enjoy_student = ['python', '-m', 'replay.enjoy_baselines', '--num-timesteps', '251', '--log-dir', model_path, task_label, "--seed", str(seed_i)] ok = subprocess.check_output(command_line_enjoy_student) diff --git a/rl_baselines/train.py b/rl_baselines/train.py index 5d92599b6..443d20baf 100644 --- a/rl_baselines/train.py +++ b/rl_baselines/train.py @@ -34,8 +34,7 @@ ENV_NAME = "" PLOT_TITLE = "" EPISODE_WINDOW = 40 # For plotting moving average -EVAL_TASK=['cc','sc','sqc'] -CROSS_EVAL = False +CROSS_EVAL = True EPISODE_WINDOW_DISTILLATION_WIN = 20 NEW_LR=0.001 @@ -172,14 +171,12 @@ def callback(_locals, _globals): best_mean_reward = mean_reward printGreen("Saving new best model") ALGO.save(LOG_DIR + ALGO_NAME + "_model.pkl", _locals) - - if n_episodes >= 0: - - # For every checkpoint, we create one directory for saving logs file (policy and run mean std) - if EPISODE_WINDOW_DISTILLATION_WIN > 0: - if n_episodes % EPISODE_WINDOW_DISTILLATION_WIN == 0: - ALGO.save(LOG_DIR + ALGO_NAME + '_' + str(n_episodes) + "_model.pkl", _locals) - if CROSS_EVAL: # If we want to do the cross evaluation after the training + if CROSS_EVAL: # If we want to do the cross evaluation after the training + if n_episodes >= 0: + # For every checkpoint, we create one directory for saving logs file (policy and run mean std) + if EPISODE_WINDOW_DISTILLATION_WIN > 0: + if n_episodes % EPISODE_WINDOW_DISTILLATION_WIN == 0: + ALGO.save(LOG_DIR + ALGO_NAME + '_' + str(n_episodes) + "_model.pkl", _locals) eps_path = LOG_DIR + "model_" + str(n_episodes) try: os.mkdir(LOG_DIR + "model_" + str(n_episodes)) From 6ec2e0a2c7a9b97a34ba06819d62ad5aa4d796a2 Mon Sep 17 00:00:00 2001 From: sun-te Date: Wed, 5 Jun 2019 16:32:12 +0200 Subject: [PATCH 111/141] ground_truth moification --- environments/omnirobot_gym/omnirobot_env.py | 27 +++++++++++++-------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/environments/omnirobot_gym/omnirobot_env.py b/environments/omnirobot_gym/omnirobot_env.py index a51bdd00f..87f067531 100644 --- a/environments/omnirobot_gym/omnirobot_env.py +++ b/environments/omnirobot_gym/omnirobot_env.py @@ -28,8 +28,7 @@ def recvMatrix(socket): RENDER_HEIGHT = 224 RENDER_WIDTH = 224 -#RELATIVE_POS = True -RELATIVE_POS = False +RELATIVE_POS = True N_CONTACTS_BEFORE_TERMINATION = 15 #10 DELTA_POS = 0.1 # DELTA_POS for continuous actions @@ -90,7 +89,7 @@ def __init__(self, renders=False, name="Omnirobot", is_discrete=True, save_path= self.use_srl = use_srl or use_ground_truth self.use_ground_truth = use_ground_truth self.use_joints = False - self.relative_pos = RELATIVE_POS + self.relative_pos = RELATIVE_POS and (not escape_continual_move) self._is_discrete = is_discrete self.observation = [] # Start simulation with first observation @@ -262,7 +261,8 @@ def step(self, action, generated_observation=None, action_proba=None, action_gri target_pos=self.getTargetPos()) old_observation = self.getObservation() if self.use_srl: - return self.getSRLState(self.observation if generated_observation is None else old_observation), self.reward, done, {} + return self.getSRLState(self.observation + if generated_observation is None else old_observation), self.reward, done, {} else: return self.observation, self.reward, done, {} @@ -276,7 +276,6 @@ def getEnvState(self): self.reward = state_data["reward"] self.target_pos = np.array(state_data["target_pos"]) self.robot_pos = np.array(state_data["position"]) - return state_data def getObservation(self): @@ -297,20 +296,28 @@ def getTargetPos(self): """ return self.target_pos - @staticmethod - def getGroundTruthDim(): + + def getGroundTruthDim(self): """ :return: (int) """ - return 4 + if(not self.escape_continual_move): + return 2 + else: + #The position of the robot, target + return 4 + def getGroundTruth(self): """ Alias for getRobotPos for compatibility between envs :return: (numpy array) """ - #return np.array(self.getRobotPos()) - return np.append(self.getRobotPos(),self.getTargetPos()) + # + if(not self.escape_continual_move): + return np.array(self.getRobotPos()) + else: + return np.append(self.getRobotPos(),self.getTargetPos()) def getRobotPos(self): """ From ea564a26057484e01616c68cb4ede79f84b532d9 Mon Sep 17 00:00:00 2001 From: saybunthet Date: Tue, 11 Jun 2019 14:20:43 +0200 Subject: [PATCH 112/141] modify readme.md in policy distillation --- rl_baselines/supervised_rl/Readme.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/rl_baselines/supervised_rl/Readme.md b/rl_baselines/supervised_rl/Readme.md index c62c7d23b..1d758b33d 100644 --- a/rl_baselines/supervised_rl/Readme.md +++ b/rl_baselines/supervised_rl/Readme.md @@ -89,13 +89,13 @@ python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 100 (/ ! \ it removes the generated dataset for dataset 1 and 2) -python -m environments.dataset_fusioner --merge data/circular_on_policy/ data/reaching_on_policy/ data/merge_CC_SC +python -m environments.dataset_merger --merge data/circular_on_policy/ data/reaching_on_policy/ data/merge_CC_SC # Copy the merged Dataset to srl_zoo repository cp -r data/merge_CC_SC srl_zoo/data/merge_CC_SC ``` -### 2.3) Train SRL 1&2 +### 2.2) Train SRL 1&2 ``` cd srl_zoo @@ -104,7 +104,10 @@ python train.py --data-folder data/merge_CC_SC -bs 32 --epochs 20 --state-dim 2 # Update your RL logs to load the proper SRL model for future distillation, i.e distillation: new-log/srl_model.pth ``` +``` +BUNTHET: WE DONT DO THE 2.2 STEP +``` ### 2.3) Run Distillation @@ -114,5 +117,5 @@ mkdir logs/CL_SC_CC cp config/srl_models_merged.yaml config/srl_models.yaml # Merged Dataset -python -m rl_baselines.train --algo distillation --srl-model srl_combination --env OmnirobotEnv-v0 --log-dir logs/CL_SC_CC --teacher-data-folder srl_zoo/data/merge_CC_SC -cc --distillation-training-set-size 40000 --epochs-distillation 20 --latest +python -m rl_baselines.train --algo distillation --srl-model raw_pixel --env OmnirobotEnv-v0 --log-dir logs/CL_SC_CC --teacher-data-folder srl_zoo/data/merge_CC_SC -cc --distillation-training-set-size 40000 --epochs-distillation 20 --latest ``` From 8ae7d9bec91b769cd9786839cdf5c16544e0adbf Mon Sep 17 00:00:00 2001 From: saybunthet Date: Tue, 11 Jun 2019 14:48:26 +0200 Subject: [PATCH 113/141] note in dataset_generator --- environments/dataset_generator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/environments/dataset_generator.py b/environments/dataset_generator.py index 551a3f6d0..13584ed0f 100644 --- a/environments/dataset_generator.py +++ b/environments/dataset_generator.py @@ -341,7 +341,7 @@ def main(): help='Model saved at episode N that we want to load') args = parser.parse_args() - + ######################## NOT QUITE IMORTANT######################################################################### assert (args.num_cpu > 0), "Error: number of cpu must be positive and non zero" assert (args.max_distance > 0), "Error: max distance must be positive and non zero" assert (args.num_episode > 0), "Error: number of episodes must be positive and non zero" @@ -378,7 +378,7 @@ def main(): if not args.no_record_data: # create the output os.mkdir(args.save_path + args.name) - + #################################################################################################################### if args.num_cpu == 1: env_thread(args, 0, partition=False) else: From 4646f163a76cdbd8260b766eefa2a40faea03fae Mon Sep 17 00:00:00 2001 From: saybunthet Date: Tue, 11 Jun 2019 19:38:23 +0200 Subject: [PATCH 114/141] update supervised_rl/reade.md --- rl_baselines/supervised_rl/Readme.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rl_baselines/supervised_rl/Readme.md b/rl_baselines/supervised_rl/Readme.md index 1d758b33d..d65f4f5ac 100644 --- a/rl_baselines/supervised_rl/Readme.md +++ b/rl_baselines/supervised_rl/Readme.md @@ -42,10 +42,10 @@ cd .. cp config/srl_models.yaml config/srl_models_temp.yaml # Dataset 1 (random reaching target) -python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --srl-config-file config/srl_models_simple.yaml --num-timesteps 1000000 --env OmnirobotEnv-v0 --log-dir logs/simple/ --num-cpu 8 --simple-continual --latest +python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --srl-config-file config/srl_models_simple.yaml --num-timesteps 5000000 --env OmnirobotEnv-v0 --log-dir logs/simple/ --num-cpu 8 --simple-continual --latest # Dataset 2 (Circular task) -python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --srl-config-file config/srl_models_circular.yaml --num-timesteps 1000000 --env OmnirobotEnv-v0 --log-dir logs/circular/ --num-cpu 6 --circular-continual --latest +python -m rl_baselines.train --algo ppo2 --srl-model srl_combination --srl-config-file config/srl_models_circular.yaml --num-timesteps 5000000 --env OmnirobotEnv-v0 --log-dir logs/circular/ --num-cpu 6 --circular-continual --latest # restore config file cp config/srl_models_temp.yaml config/srl_models.yaml @@ -117,5 +117,5 @@ mkdir logs/CL_SC_CC cp config/srl_models_merged.yaml config/srl_models.yaml # Merged Dataset -python -m rl_baselines.train --algo distillation --srl-model raw_pixel --env OmnirobotEnv-v0 --log-dir logs/CL_SC_CC --teacher-data-folder srl_zoo/data/merge_CC_SC -cc --distillation-training-set-size 40000 --epochs-distillation 20 --latest +python -m rl_baselines.train --algo distillation --srl-model raw_pixels --env OmnirobotEnv-v0 --log-dir logs/CL_SC_CC --teacher-data-folder srl_zoo/data/merge_CC_SC -cc --distillation-training-set-size 40000 --epochs-distillation 20 --latest ``` From 9490fa8453bd14d879f48279b0b10ee1580c1452 Mon Sep 17 00:00:00 2001 From: kalifou Date: Wed, 12 Jun 2019 14:00:18 +0200 Subject: [PATCH 115/141] fix distillation at checkpoints for CC (TC) --- rl_baselines/student_eval.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/rl_baselines/student_eval.py b/rl_baselines/student_eval.py index 601c563ad..bfdfc745a 100644 --- a/rl_baselines/student_eval.py +++ b/rl_baselines/student_eval.py @@ -40,7 +40,7 @@ def OnPolicyDatasetGenerator(teacher_path, output_name, task_id, episode=-1, env episode_command = ['--num-episode', str(10 if test_mode else 400)] else: episode_command = ['--num-episode', str(10 if test_mode else 60)] - print("teacher path: ", teacher_path) + policy_command = ['--log-custom-policy', teacher_path] if episode == -1: eps_policy = [] @@ -234,13 +234,18 @@ def main(): episodes, policy_path = allPolicy(teacher_learn) rewards_at_episode = {} - episodes_to_test = [e for e in episodes if (int(e) < 2000 and int(e) % 200 == 0) or - (int(e) > 2000 and int(e) % 1000 == 0)] - # generate data from Professional teacher - printYellow("\nGenerating on policy for optimal teacher: " + args.continual_learning_labels[0]) + if args.continual_learning_labels[1] == "CC": + episodes_to_test = [e for e in episodes if (int(e) < 2000 and int(e) % 200 == 0) or + (int(e) > 2000 and int(e) % 1000 == 0)] + else: + episodes_to_test = [e for e in episodes if (int(e) <= 5000 and int(e) % 1000 == 0) or + (int(e) > 5000 and int(e) % 10000 == 0)] if not (args.log_dir_teacher_one == "None"): + # generate data from Professional teacher + printYellow("\nGenerating on policy for optimal teacher: " + args.continual_learning_labels[0]) + OnPolicyDatasetGenerator(teacher_pro, args.continual_learning_labels[0] + '_copy/', task_id=args.continual_learning_labels[0], num_eps=args.epochs_teacher_datasets, episode=-1, env_name=args.env) @@ -259,8 +264,9 @@ def main(): # Generate data from learning teacher printYellow("\nGenerating on-policy data from the optimal teacher: " + args.continual_learning_labels[1]) OnPolicyDatasetGenerator(teacher_learn, teacher_learn_data, task_id=args.continual_learning_labels[1], - episode=eps, num_eps=args.epochs_teacher_datasets, env_name=args.env) + num_eps=args.epochs_teacher_datasets, episode=eps, env_name=args.env) + # If Performing policy distillation from a single (learning) teacher at multiple checkpoints if args.log_dir_teacher_one == "None": merge_path = 'data/' + teacher_learn_data ok = subprocess.call( From 208d472b858c709000929f1e45b76128e9ef2e58 Mon Sep 17 00:00:00 2001 From: kalifou Date: Wed, 12 Jun 2019 18:42:58 +0200 Subject: [PATCH 116/141] cleaning --- environment.yml | 2 +- environments/dataset_generator.py | 9 +-- environments/dataset_merger.py | 3 + rl_baselines/supervised_rl/Readme.md | 4 -- run_policy.sh | 2 +- run_policy_dry_run.sh | 2 +- tests/test_dataset_manipulation.py | 2 +- tests/test_eval.py | 86 ---------------------------- 8 files changed, 12 insertions(+), 98 deletions(-) diff --git a/environment.yml b/environment.yml index 3a9a0cffd..995bba580 100644 --- a/environment.yml +++ b/environment.yml @@ -1,4 +1,4 @@ -name: robot +name: py35 channels: - menpo - pytorch diff --git a/environments/dataset_generator.py b/environments/dataset_generator.py index 13584ed0f..556e6a315 100644 --- a/environments/dataset_generator.py +++ b/environments/dataset_generator.py @@ -45,8 +45,8 @@ def latestPath(path): def walkerPath(): """ - - :return: + Naive Grid Walking Policy: Walking across the grid from the top to the bottom, going left and right. + :return: [int] List of actions taken by a grid walker """ eps = 0.01 N_times = 14 @@ -122,6 +122,7 @@ def env_thread(args, thread_num, partition=True): srl_model = None srl_state_dim = 0 generated_obs = None + env_norm = None if args.run_policy in ["walker", "custom"]: if args.latest: @@ -341,7 +342,7 @@ def main(): help='Model saved at episode N that we want to load') args = parser.parse_args() - ######################## NOT QUITE IMORTANT######################################################################### + assert (args.num_cpu > 0), "Error: number of cpu must be positive and non zero" assert (args.max_distance > 0), "Error: max distance must be positive and non zero" assert (args.num_episode > 0), "Error: number of episodes must be positive and non zero" @@ -378,7 +379,7 @@ def main(): if not args.no_record_data: # create the output os.mkdir(args.save_path + args.name) - #################################################################################################################### + if args.num_cpu == 1: env_thread(args, 0, partition=False) else: diff --git a/environments/dataset_merger.py b/environments/dataset_merger.py index 11763a8b0..7d8ceaa1c 100644 --- a/environments/dataset_merger.py +++ b/environments/dataset_merger.py @@ -8,6 +8,8 @@ import numpy as np from tqdm import tqdm +# List of all possible labels identifying a task, +# for experiments in Continual Learning scenari. CONTINUAL_LEARNING_LABELS = ['CC', 'SC', 'EC', 'SQC'] CL_LABEL_KEY = "continual_learning_label" @@ -120,6 +122,7 @@ def main(): dataset_1_size = preprocessed_load["actions"].shape[0] dataset_2_size = preprocessed_load_2["actions"].shape[0] + # Concatenating additional information: indices of episode start, action probabilities, CL labels... for idx, prepro_load in enumerate([preprocessed_load, preprocessed_load_2]): for arr in prepro_load.files: pr_arr = prepro_load[arr] diff --git a/rl_baselines/supervised_rl/Readme.md b/rl_baselines/supervised_rl/Readme.md index d65f4f5ac..16c273f3a 100644 --- a/rl_baselines/supervised_rl/Readme.md +++ b/rl_baselines/supervised_rl/Readme.md @@ -103,10 +103,6 @@ cd srl_zoo python train.py --data-folder data/merge_CC_SC -bs 32 --epochs 20 --state-dim 200 --training-set-size 30000--losses autoencoder inverse # Update your RL logs to load the proper SRL model for future distillation, i.e distillation: new-log/srl_model.pth -``` -``` -BUNTHET: WE DONT DO THE 2.2 STEP - ``` ### 2.3) Run Distillation diff --git a/run_policy.sh b/run_policy.sh index 25cd0edd9..bcb1ccede 100644 --- a/run_policy.sh +++ b/run_policy.sh @@ -58,7 +58,7 @@ python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 100 #(/ ! \ it removes the generated dataset for dataset 1 and 2) -python -m environments.dataset_fusioner --merge data/$name_circular_policy_folder\/ data/$name_reaching_policy_folder\/ data/$merging_file +python -m environments.dataset_merger --merge data/$name_circular_policy_folder\/ data/$name_reaching_policy_folder\/ data/$merging_file # Copy the merged Dataset to srl_zoo repository cp -r data/$merging_file srl_zoo/data/$merging_file diff --git a/run_policy_dry_run.sh b/run_policy_dry_run.sh index 702923ed9..2ec72e826 100755 --- a/run_policy_dry_run.sh +++ b/run_policy_dry_run.sh @@ -50,7 +50,7 @@ python -m environments.dataset_generator --env OmnirobotEnv-v0 --num-episode 2 - #(/ ! \ it removes the generated dataset for dataset 1 and 2) -python -m environments.dataset_fusioner --merge data/circular_on_policy/ data/reaching_on_policy/ data/merge_CC_SC +python -m environments.dataset_merger --merge data/circular_on_policy/ data/reaching_on_policy/ data/merge_CC_SC # Copy the merged Dataset to srl_zoo repository cp -r data/merge_CC_SC srl_zoo/data/merge_CC_SC diff --git a/tests/test_dataset_manipulation.py b/tests/test_dataset_manipulation.py index 22ccc0be0..87053e4d7 100644 --- a/tests/test_dataset_manipulation.py +++ b/tests/test_dataset_manipulation.py @@ -31,7 +31,7 @@ def testDataGenForFusion(): args_3 = ['--merge', PATH_SRL + DATA_FOLDER_NAME_1, PATH_SRL + DATA_FOLDER_NAME_2, PATH_SRL + DATA_FOLDER_NAME_3] args_3 = list(map(str, args_3)) - ok = subprocess.call(['python', '-m', 'environments.dataset_fusioner'] + args_3) + ok = subprocess.call(['python', '-m', 'environments.dataset_merger'] + args_3) assertEq(ok, 0) # Checking inexistance of original datasets to be merged diff --git a/tests/test_eval.py b/tests/test_eval.py index cd3578d15..44782010b 100644 --- a/tests/test_eval.py +++ b/tests/test_eval.py @@ -21,34 +21,6 @@ def assertEq(left, right): assert left == right, "{} != {}".format(left, right) -# @pytest.mark.fast -# @pytest.mark.parametrize("task", ['-sc','-cc']) -# def testCrossEval(task): -# #Evaluation for the policy on different tasks -# # Long enough to save one policy model -# -# num_timesteps = 10000 -# args = ['--algo', DEFAULT_ALGO, '--srl-model', DEFAULT_SRL, -# '--num-timesteps', num_timesteps, '--seed', SEED, '--no-vis', -# '--episode-window', EPISODE_WINS, -# '--env', DEFAULT_ENV, '--log-dir', DEFAULT_LOG , task, -# '--min-episodes-save', 0] -# -# args = list(map(str, args)) -# #We firstly train a policy to have some checkpoint to evaluate -# ok = subprocess.call(['python', '-m', 'rl_baselines.train'] + args) -# assertEq(ok, 0) -# eval_path = DEFAULT_LOG -# for i in range(4): # Go into the folder that contains the policy file -# eval_path += os.listdir(eval_path)[-1] + '/' -# -# args= ['--log-dir', eval_path, '--num-iteration', str(NUM_ITERATION)] -# ok = subprocess.call(['python', '-m', 'rl_baselines.cross_eval'] + args) -# assertEq(ok, 0) -# -# #Remove test files -# shutil.rmtree(DEFAULT_LOG) - @pytest.mark.fast @pytest.mark.parametrize("tasks", [['-cc','-sc']]) def testStudentEval(tasks,teacher_folder_one='logs/teacher_one/', teacher_folder_two='logs/teacher_two/' ): @@ -106,61 +78,3 @@ def testStudentEval(tasks,teacher_folder_one='logs/teacher_one/', teacher_folder shutil.rmtree(DIR_STUDENT) for i in range(10): print("test finished") -# -# -# @pytest.mark.slow -# @pytest.mark.parametrize("algo", ['a2c', 'acer', 'ars', 'cma-es', 'ddpg', 'deepq', 'ppo1', 'ppo2', 'random_agent', -# 'sac', 'trpo']) -# @pytest.mark.parametrize("tasks", [['-cc','-sc'],['-cc', '-sc']]) -# def testStudentEvalAlgo(tasks,algo): -# teacher_folder_one = 'logs/teacher_one/' -# teacher_folder_two = 'logs/teacher_two/' -# -# teacher_args_one = ['--algo', algo, '--srl-model', DEFAULT_SRL, -# '--num-timesteps', NUM_TIMESTEP, '--seed', SEED, '--no-vis', -# '--episode-window', EPISODE_WINS, -# '--env', DEFAULT_ENV, '--log-dir', teacher_folder_one , tasks[0], -# '--min-episodes-save', 0] -# -# teacher_args_one = list(map(str, teacher_args_one)) -# -# teacher_args_two = ['--algo', algo, '--srl-model', DEFAULT_SRL, -# '--num-timesteps', NUM_TIMESTEP, '--seed', SEED, '--no-vis', -# '--episode-window', EPISODE_WINS, -# '--env', DEFAULT_ENV, '--log-dir', teacher_folder_two , tasks[1]] -# teacher_args_two = list(map(str, teacher_args_two)) -# -# ok = subprocess.call(['python', '-m', 'rl_baselines.train'] + teacher_args_one) -# assertEq(ok, 0) -# ok = subprocess.call(['python', '-m', 'rl_baselines.train'] + teacher_args_two) -# assertEq(ok, 0) -# -# folder2remove = [teacher_folder_one, teacher_folder_one] -# -# for i in range(4):#Go into the folder that contains the policy file -# teacher_folder_two += os.listdir(teacher_folder_two)[-1] + '/' -# teacher_folder_one += os.listdir(teacher_folder_one)[-1] + '/' -# -# -# args = ['--num-iteration', NUM_ITERATION, '--epochs-teacher-datasets', EPOCH_DATA, -# '--env', DEFAULT_ENV, '--log-dir-student', DIR_STUDENT, -# '--log-dir-teacher-one', teacher_folder_one,'--log-dir-teacher-two', teacher_folder_two, -# '--epochs-distillation', 5] -# if(tasks ==['-cc','-sc']): -# args+=['--srl-config-file-one', 'config/srl_models_circular.yaml', -# '--srl-config-file-two','config/srl_models_simple.yaml', -# '--continual-learning-labels', 'CC', 'SC'] -# -# else: -# args += ['--srl-config-file-one', 'config/srl_models_simple.yaml', -# '--srl-config-file-two', 'config/srl_models_circular.yaml', -# '--continual-learning-labels', 'SC', 'CC'] -# -# args = list(map(str, args)) -# ok = subprocess.call(['python', '-m', 'rl_baselines.student_eval'] + args) -# assertEq(ok, 0) -# -# #Remove test files -# shutil.rmtree(folder2remove[0]) -# shutil.rmtree(folder2remove[1]) -# shutil.rmtree(DIR_STUDENT) From 486ea7efd0d18a5b0124a87031a731db3f11f795 Mon Sep 17 00:00:00 2001 From: sun-te Date: Thu, 13 Jun 2019 14:44:43 +0200 Subject: [PATCH 117/141] fixed orientation for the chasing agent --- environments/dataset_generator.py | 5 ++-- real_robots/omnirobot_simulator_server.py | 20 +++++++++++-- .../omnirobot_utils/omnirobot_manager_base.py | 29 +++++++++++++++---- 3 files changed, 43 insertions(+), 11 deletions(-) diff --git a/environments/dataset_generator.py b/environments/dataset_generator.py index e8491ae26..dd43251fd 100644 --- a/environments/dataset_generator.py +++ b/environments/dataset_generator.py @@ -45,8 +45,8 @@ def latestPath(path): def walkerPath(): """ - Naive Grid Walking Policy: Walking across the grid from the top to the bottom, going left and right. - :return: [int] List of actions taken by a grid walker + + :return: """ eps = 0.01 N_times = 14 @@ -124,7 +124,6 @@ def env_thread(args, thread_num, partition=True): srl_model = None srl_state_dim = 0 generated_obs = None - env_norm = None if args.run_policy in ["walker", "custom"]: if args.latest: diff --git a/real_robots/omnirobot_simulator_server.py b/real_robots/omnirobot_simulator_server.py index 2d2dd0bcd..7b6f92ecc 100755 --- a/real_robots/omnirobot_simulator_server.py +++ b/real_robots/omnirobot_simulator_server.py @@ -314,6 +314,21 @@ def targetMoveDiscrete(self, target_yaw): self.target_pos_cmd[0] -self.step_distance_target, self.target_pos_cmd[1] , target_yaw) + def targetMove(self, action=None): + assert action !=None + if action =="forward": + self.setTargetCmd( + self.target_pos_cmd[0] + self.step_distance_target, self.target_pos_cmd[1], self.target_yaw) + elif action =="backward": + self.setTargetCmd( + self.target_pos_cmd[0] - self.step_distance_target, self.target_pos_cmd[1], self.target_yaw) + elif action =="left": + self.setTargetCmd( + self.target_pos_cmd[0] , self.target_pos_cmd[1]+ self.step_distance_target, self.target_yaw) + else : + self.setTargetCmd( + self.target_pos_cmd[0] , self.target_pos_cmd[1]- self.step_distance_target, self.target_yaw) + def targetMoveContinous(self, target_yaw): @@ -444,7 +459,7 @@ def __init__(self, **args): elif self.new_args["square_continual_move"] or self.new_args["eight_continual_move"]: self.new_args["target_marker_path"] = "real_robots/omnirobot_utils/green_square.png" elif self.new_args["chasing_continual_move"] or self.new_args["escape_continual_move"]: - self.new_args["target_marker_path"] = "real_robots/omnirobot_utils/yellow_T.jpg" + self.new_args["target_marker_path"] = "real_robots/omnirobot_utils/yellow_T.png" else: # for black target, use target_margin4_pixel.png", self.new_args["target_marker_path"] = "real_robots/omnirobot_utils/red_target_margin4_pixel_480x480.png" @@ -492,7 +507,8 @@ def resetEpisode(self): random_init_y = np.random.random_sample() * (TARGET_MAX_Y - TARGET_MIN_Y) + \ TARGET_MIN_Y self.robot.setTargetCmd( - random_init_x, random_init_y, 2 * np.pi * np.random.rand() - np.pi) + # random_init_x, random_init_y, 2 * np.pi * np.random.rand() - np.pi) + random_init_x, random_init_y, 0) # render the target and robot self.robot.renderTarget() diff --git a/real_robots/omnirobot_utils/omnirobot_manager_base.py b/real_robots/omnirobot_utils/omnirobot_manager_base.py index 7c0171f8e..aabc693d5 100644 --- a/real_robots/omnirobot_utils/omnirobot_manager_base.py +++ b/real_robots/omnirobot_utils/omnirobot_manager_base.py @@ -90,6 +90,9 @@ def moveContinousAction(self, msg): else: has_bumped = True return has_bumped + + + def targetMoveContinousAction(self, target_yaw): """ Let robot execute continous action, and checking the boundary @@ -105,10 +108,12 @@ def targetMoveContinousAction(self, target_yaw): has_bumped = True return has_bumped + def targetMoveDiscreteAction(self,target_yaw): self.robot.targetMoveDiscrete(target_yaw) + def targetPolicy(self, directed = False): """ The policy for the target @@ -122,7 +127,19 @@ def targetPolicy(self, directed = False): dy /= r dx /= r yaw = math.atan2(dy, dx ) - return yaw + #return yaw + if(abs(dy)>abs(dx)): + if(dy>0): + self.robot.targetMove("left") + else: + self.robot.targetMove("right") + else: + if(dx>0): + self.robot.targetMove("forward") + else: + self.robot.targetMove("backward") + + period = 70 yaw = (2*(self.step_counter % period )/period-1)*np.pi @@ -253,18 +270,18 @@ def processMsg(self, msg): dis = np.linalg.norm(np.array(self.robot.robot_pos) - np.array(self.robot.target_pos)) - if has_bumped or dis<0.3: + if has_bumped or dis<0.4: self.reward = REWARD_BUMP_WALL # elif(dis<0.2): # self.reward = REWARD_BUMP_WALL - elif(dis>=0.3 and dis<0.6): - self.reward = REWARD_TARGET_REACH + elif(dis>=0.4): + self.reward =REWARD_TARGET_REACH else: self.reward = REWARD_NOTHING - target_yaw = self.targetPolicy(directed=True) + self.targetPolicy(directed=True) #self.targetMoveContinousAction(target_yaw) - self.targetMoveDiscreteAction(target_yaw) + #self.targetMoveDiscreteAction(target_yaw) else: From 12cd0c0b3d639f0f1b7a4c554dceddc34326c006 Mon Sep 17 00:00:00 2001 From: sun-te Date: Thu, 13 Jun 2019 14:49:49 +0200 Subject: [PATCH 118/141] bug fixed --- .../red_target_margin4_pixel_480x4801.png | Bin 0 -> 4998 bytes real_robots/omnirobot_utils/yellow_T.png | Bin 0 -> 289 bytes real_robots/omnirobot_utils/yellow_Ttt.png | Bin 0 -> 212 bytes real_robots/omnirobot_utils/zombie.png | Bin 0 -> 4342 bytes real_robots/omnirobot_utils/zombie2.png | Bin 0 -> 5222 bytes 5 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 real_robots/omnirobot_utils/red_target_margin4_pixel_480x4801.png create mode 100644 real_robots/omnirobot_utils/yellow_T.png create mode 100644 real_robots/omnirobot_utils/yellow_Ttt.png create mode 100644 real_robots/omnirobot_utils/zombie.png create mode 100644 real_robots/omnirobot_utils/zombie2.png diff --git a/real_robots/omnirobot_utils/red_target_margin4_pixel_480x4801.png b/real_robots/omnirobot_utils/red_target_margin4_pixel_480x4801.png new file mode 100644 index 0000000000000000000000000000000000000000..d49298b80eb2fad7cc64d8e93c6d70fe85d57681 GIT binary patch literal 4998 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 Qr2qf`07*qoM6N<$g8B7^FaQ7m literal 0 HcmV?d00001 diff --git a/real_robots/omnirobot_utils/yellow_T.png b/real_robots/omnirobot_utils/yellow_T.png new file mode 100644 index 0000000000000000000000000000000000000000..79c359c1f760a1b4894f3359f0882841ad1ea135 GIT binary patch literal 289 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2nC-mSQK*5Dp-y;YjHK@^5&$IEG|2 zzP;hg)#M=4_VM^WKaq--cb7VMIkLaxS{qf;D0XR4FYC4y9CHerF4aihliyJ&@{gZS zL+tFVHXfg2atrkN0v`*QLW#+~CvNnV@aw=1$-_nU-zo((8Q1 z!o^qckEj&pItY!Y%Rp+2!JQFcc?Tjk0Ino!I`W#0 W79?RH^=T%^>kOW*elF{r5}E*!fp22~ literal 0 HcmV?d00001 diff --git a/real_robots/omnirobot_utils/yellow_Ttt.png b/real_robots/omnirobot_utils/yellow_Ttt.png new file mode 100644 index 0000000000000000000000000000000000000000..d48fad228e5c07ec47234f03facaf58c8d54b7dd GIT binary patch literal 212 zcmeAS@N?(olHy`uVBq!ia0vp^<{-?$1|(P9zT^g^Sc;uILpXq-h9ji|$nW-aaSX|5 ze0$xStHFSW;bNFgF8`C#*Q`7qE9P^4p2oV=S?rjd`|PzV-oECxIccHwcty`*qrOuh z#X literal 0 HcmV?d00001 diff --git a/real_robots/omnirobot_utils/zombie.png b/real_robots/omnirobot_utils/zombie.png new file mode 100644 index 0000000000000000000000000000000000000000..84ad6d673955d045f98390d46165664cacaebce1 GIT binary patch literal 4342 zcmVar!OQ-wwBU8G2g6}>#Xa`y)) zNFc%HIA;a}^1XM@Ip4kKp7Y)F0DMcLGg_ABt=e*c;rPUO_j!#jjbSwN8hYd{PZ`)cp_y{oDs`{Lb~#L$r6 zJyuTuGMx^iEp@X!tKfN!!IU>&`_n3oC%i_Rnq9K?x2~bSW21c?A3o4RSX*Y^i?+=C zr@dqMt_WIvDzDMn2+QgSVR)*lVX7)YhUHB@=g?Kr@9hcsJ)J?1vssqJQ2?<`1iCHUlztEnU>R?I>7od1yHnLKap%M5w>!Fmw?emkq!I8|)zQN3zmJVnQ zrj~)W+CL1m)ci_Sl^_5Ztd0%7@u8~O^v!ui3|7aw?9w&=W>3p0uUKA8)~_f*dU6s7 znfIc`6-p_ZyL$2QiSuZ0Yi($|dg_^=*VVLO`Nnteb=>~jJrt$1-1{jV{%q^>U zt6=5kKknMHA^Y`bE6IxD0vHVm-x>%2AcVkfHDlefVu&h94shlde9ns|^_g{W;muAPhm0+0Z%MBp}IzvL#ah8iXKV8@nLZYBpjsrj=pyEhYYBCs> z6^4V%u8}*f?+ZFZmZ~U0N>yoAAl9_prxum(c<;4m_HwIBie}sg_d!G)nx7Ctz_1KB zfd?-LAPfUa)hWcFAUhp>!%m~5v+UQKY-NHrAuZ^2bxbb2F+lWY+p5Lu_Z)d;{~pb% zC51CO!g4IMh6FI|todS2pjeItC-C5SF0zj%01-k^l$(jGx7#fpH>-X$(%bfzc6Df8pc#eh3<40R}FD#}+ytIF3ly5b(b>n2!b&NV)u<6`b zY?oo-B!oONTE}^G`4VBbTA)wRVcg}#!6Rqz%F}xwOw<`cr-c{@#sJB1*pO_qYK``^ z&CbC)pWnaEa=ek#CYlN|Ql9RB#Vii`GEr!SEM?-5j zYMVMD_Z&&sxp7TQ!3+dLIC}OHyzT+~e6JtNa@2`%A)pcix!;M-yW@DX#)sihGVE3} zMxAb)udc=RidB&r<~b-lAK8BsLI}aa%rw*`IoA4JV|Bb%=OBde221h^mgNMq!IASq z#mZ6~`tobsYG}i#(+!W;k6=gy!!QVmVcc%%gw>RY%rplw(~?nKkc;AiTx6v=V&WSB zuGBQ*%FSE&^>bbnW$F;tuZ6y&p{5y*1l1v8*Tj~sRoOEWzg$tHQCcQIR|@=u%h4Fr8C>NbPYPQo#Xx3zx*Cv zuJGcSGB?(kM-EiIH_=g~fFy8)gf`gY>xC0Z$^^wG|(h)=;7y;^=w81CW6s<-B!c6VPFaW@4 z^+lT&DUgLM7{>pCch9P*?TIKL0t=$!u_N0Dug?!jlHr+{y?7!?5^RP@+SEJW2cvqU z_ue|i;ZJ9H9Jn+w%UpyR*mMeHB?5LbL8X%jrJ^dJRGo4*;UfBo&X!2Qj(-5C5=MO- z{35}9CO`xRcAW%Fkj{tmyP`%|06#$-by^Jq;m9N~Y9Pkg)?x*tUV?Rn6K9f%q8gMK zFcUL>zm`PxE3xO7kSKww%9NSp03a9)jRwL5Ce8~G;HUdy0aJw{AQ4c)f@4`2A4;`H z&t67rcQ5|&d(VLo0;53>ci4!qJPKhFDc)A1Vq3|B1_=#C>@+)tXy(gKPl*{Lhhu&5 z`1}Y5{X>(1FaY2hx_jnkcl?nIap^)MO|kel%Uh^nYD84CbLoNkB#Z%BS&VXP_$IeZwkveg19~>S-eM@Il(e2hQ)HbyPh{XBc-B00HM|23r zX|<`&AmrfyK58}MK!*b!Xz2rv-$})|YDHF>70ZeXuxInyXsV@@LJY;$9ZD$< zpQ^&W&c=77P@sQWAiPGGnq9i~*Za0_z~;5fF)%a=Ns?hPCBk91Mzab4sFdRF;K*cM z7#tac%j1L9YyU&>}|NcelSdg{hG{rtjb75#i~-|=VZjx3q@99 z4psngsiqN4ZS5m>n{WK{6vGb#Nh>V-$+FUtwB4K5fMJ;E?8g&^5R?=xL~T<$Gy)Hk zL60$)2TK>_!D5PitB|16;)xv_uy0!hM#f$6`U2oM7B;I1h6LS|f=5*fF&JAEM_nF# zeBwOqx^>|Pa#$Rj5s1NTFI!nsIAh1;z7RrCxn(WNmls2ypaTGmIo(K|q4UVH3{vb? zq}Zo_V?ZfIC=dWuAB3zV%lPx5qv&m|KRDjs_3?CLqd>%Ei2x`x0uP(jjQpGo*es@bw^Avk2#3U&vj?RVUshG)>nqhGEmuxF zsVegHya)b2DI^w4PqxV?T* z`XGEZK2nBtD@&lCh3?-MMV1ltJ)kp`QhZ%qhYvnK>1(Vy@~Cfo_{wZLVt_C#XIQX& z=}g!0+EZ z1Tie(@kiIkq}Ayp1U!!te1$sL(_>eR}eoujSIQ$2}thXXgR}n5G*q2E3hOz}q?bdSa4eJs||E z%N9YB6$FAJ>^2Ktd}0U0a2R1pMpjxfOo@hwQ|GSY^u_DgwQ=>dtD>rEG)rB))qqb< zeC2AcI=ai}9KJeN5YqygPVCu*-^s~H!LChffW9s;4Yxq$M9{1XK#{?mI}UQb57eFt zb;}+U=jY(-D^qAuR4AngPaLS+UOx_>xxuFH zu0!($F=rrpvu#CD`L0jP78h_rM-%F32T^1P#>Je+mi~vfl^x z>sGXnT}5$mY22`q!eL0E2%~K3>cy3shCp}Ch3|h85OW2>*Ne}~(kP1sO4jlaoeNESY zDF(b)dNpo&S#n9+p|((x|EuRAfnP8}e=AIgU)G+;bIKlAaqdUs{oRM>?|Q7vX|oTu*Z(Hub9V#+f%jO3G3=V9z)coO3_}ctKqY(=k6FE=s9w) klA0;KE+My$ut(+Yd9F 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 Date: Fri, 14 Jun 2019 17:05:01 +0200 Subject: [PATCH 119/141] target position update --- state_representation/episode_saver.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/state_representation/episode_saver.py b/state_representation/episode_saver.py index 87579306b..13e69d392 100644 --- a/state_representation/episode_saver.py +++ b/state_representation/episode_saver.py @@ -112,7 +112,7 @@ def reset(self, observation, target_pos, ground_truth): self.ground_truth_states.append(ground_truth) self.saveImage(observation) - def step(self, observation, action, reward, done, ground_truth_state, action_proba=None): + def step(self, observation, action, reward, done, ground_truth_state, action_proba=None,target_pos = []): """ :param observation: (numpy matrix) BGR Image :param action: (int) @@ -134,6 +134,8 @@ def step(self, observation, action, reward, done, ground_truth_state, action_pro if not done: self.episode_starts.append(False) + if (len(target_pos) != 0): + self.target_positions.append(target_pos) self.ground_truth_states.append(ground_truth_state) self.saveImage(observation) else: @@ -149,7 +151,7 @@ def save(self): assert len(self.actions) == len(self.episode_starts) assert len(self.actions) == len(self.images_path) assert len(self.actions) == len(self.ground_truth_states) - assert len(self.target_positions) == self.episode_idx + 1 + assert len(self.target_positions) == self.episode_idx + 1 or len(self.target_positions) ==len(self.actions) assert len(self.actions_proba) == 0 or len(self.actions_proba) == len(self.actions) data = { From 7f2ce56cbaac5ffa65e6525edde1fba97c508659 Mon Sep 17 00:00:00 2001 From: kalifou Date: Mon, 17 Jun 2019 15:06:41 +0200 Subject: [PATCH 120/141] fix merger in case of distillation --- environments/dataset_merger.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/environments/dataset_merger.py b/environments/dataset_merger.py index 7d8ceaa1c..2d1bed0dc 100644 --- a/environments/dataset_merger.py +++ b/environments/dataset_merger.py @@ -107,7 +107,9 @@ def main(): gt_arr = np.repeat(gt_load[arr], num_episode_dataset, axis=0) if idx_ > 1: - ground_truth[arr] = np.concatenate((ground_truth[arr], gt_arr), axis=0) + if gt_arr.shape == ground_truth[arr].shape: + ground_truth[arr] = np.concatenate((ground_truth[arr], gt_arr), axis=0) + else: ground_truth[arr] = gt_arr From fe09e492e4124a0b9a4ea9a2656bcb8f4fc1fe27 Mon Sep 17 00:00:00 2001 From: sun-te Date: Mon, 24 Jun 2019 17:34:14 +0200 Subject: [PATCH 121/141] reward update --- real_robots/omnirobot_utils/omnirobot_manager_base.py | 6 ++++-- rl_baselines/train.py | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/real_robots/omnirobot_utils/omnirobot_manager_base.py b/real_robots/omnirobot_utils/omnirobot_manager_base.py index aabc693d5..48a12f97a 100644 --- a/real_robots/omnirobot_utils/omnirobot_manager_base.py +++ b/real_robots/omnirobot_utils/omnirobot_manager_base.py @@ -121,8 +121,10 @@ def targetPolicy(self, directed = False): :return: the angle to go for the target """ if(directed): - dy = self.robot.robot_pos[1] - self.robot.target_pos[1] - dx = self.robot.robot_pos[0] - self.robot.target_pos[0] + dy = self.robot.robot_pos[1] - self.robot.target_pos[1] + np.random.rand() * abs( + self.robot.robot_pos[1] - self.robot.target_pos[1]) + dx = self.robot.robot_pos[0] - self.robot.target_pos[0] + np.random.rand() * abs( + self.robot.robot_pos[0] - self.robot.target_pos[0]) r = math.sqrt(dy**2+dx**2) dy /= r dx /= r diff --git a/rl_baselines/train.py b/rl_baselines/train.py index 443d20baf..672b7f9a6 100644 --- a/rl_baselines/train.py +++ b/rl_baselines/train.py @@ -34,7 +34,7 @@ ENV_NAME = "" PLOT_TITLE = "" EPISODE_WINDOW = 40 # For plotting moving average -CROSS_EVAL = True +CROSS_EVAL = False EPISODE_WINDOW_DISTILLATION_WIN = 20 NEW_LR=0.001 @@ -171,6 +171,7 @@ def callback(_locals, _globals): best_mean_reward = mean_reward printGreen("Saving new best model") ALGO.save(LOG_DIR + ALGO_NAME + "_model.pkl", _locals) + if CROSS_EVAL: # If we want to do the cross evaluation after the training if n_episodes >= 0: # For every checkpoint, we create one directory for saving logs file (policy and run mean std) From ed26f2e07d88bd317e7869d7b4c0cd12c8bdc2e7 Mon Sep 17 00:00:00 2001 From: sun-te Date: Tue, 25 Jun 2019 22:14:35 +0200 Subject: [PATCH 122/141] reward can be float for circular task and escaping task --- environments/dataset_merger.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/environments/dataset_merger.py b/environments/dataset_merger.py index 7d8ceaa1c..add6ec9a7 100644 --- a/environments/dataset_merger.py +++ b/environments/dataset_merger.py @@ -130,7 +130,7 @@ def main(): to_class = None if arr == "episode_starts": to_class = bool - elif arr == "actions_proba": + elif arr == "actions_proba" or arr == "rewards": to_class = float else: to_class = int From 83bed1e6d834e3c6061ac3ce7a871e15cacef8be Mon Sep 17 00:00:00 2001 From: sun-te Date: Tue, 25 Jun 2019 22:34:44 +0200 Subject: [PATCH 123/141] a new dataset merger for the balanced timesteps settings during the merge --- environments/dataset_merger.py | 135 ++++++++++++++++++++++++++------- 1 file changed, 106 insertions(+), 29 deletions(-) diff --git a/environments/dataset_merger.py b/environments/dataset_merger.py index add6ec9a7..af4b3d9aa 100644 --- a/environments/dataset_merger.py +++ b/environments/dataset_merger.py @@ -4,12 +4,11 @@ import argparse import os import shutil +import pdb import numpy as np from tqdm import tqdm -# List of all possible labels identifying a task, -# for experiments in Continual Learning scenari. CONTINUAL_LEARNING_LABELS = ['CC', 'SC', 'EC', 'SQC'] CL_LABEL_KEY = "continual_learning_label" @@ -23,13 +22,14 @@ def main(): parser.add_argument('-f', '--force', action='store_true', default=False, help='Force the merge, even if it overrides something else,' ' including the destination if it exist') + parser.add_argument('--timesteps', type=int, nargs=2, default=[-1,-1], + help="To have a certain number of frames for two data sets ") group = parser.add_mutually_exclusive_group() group.add_argument('--merge', type=str, nargs=3, metavar=('source_1', 'source_2', 'destination'), default=argparse.SUPPRESS, help='Merge two datasets by appending the episodes, deleting sources right after.') args = parser.parse_args() - if 'merge' in args: # let make sure everything is in order assert os.path.exists(args.merge[0]), "Error: dataset '{}' could not be found".format(args.merge[0]) @@ -47,24 +47,63 @@ def main(): # create the output os.mkdir(args.merge[2]) - # copy files from first source - os.rename(args.merge[0] + "/dataset_config.json", args.merge[2] + "/dataset_config.json") - os.rename(args.merge[0] + "/env_globals.json", args.merge[2] + "/env_globals.json") - for record in sorted(glob.glob(args.merge[0] + "/record_[0-9]*/*")): - s = args.merge[2] + "/" + record.split("/")[-2] + '/' + record.split("/")[-1] - os.renames(record, s) + #os.rename(args.merge[0] + "/dataset_config.json", args.merge[2] + "/dataset_config.json") + #os.rename(args.merge[0] + "/env_globals.json", args.merge[2] + "/env_globals.json") + shutil.copy2(args.merge[0] + "/dataset_config.json",args.merge[2] + "/dataset_config.json") + shutil.copy2(args.merge[0] + "/env_globals.json", args.merge[2] + "/env_globals.json") - num_episode_dataset_1 = int(record.split("/")[-2][7:]) + 1 + # copy files from first source + num_timesteps_1, num_timesteps_2 = args.timesteps + local_path = os.getcwd() + all_records = sorted(glob.glob(args.merge[0] + "/record_[0-9]*/*")) + previous_records = all_records[0] + for ts_counter_1, record in enumerate(all_records): + + #if the timesteps is larger than needed, we wait until this episode is over + if(num_timesteps_1>0 and ts_counter_1 >num_timesteps_1): + if(os.path.dirname(previous_records).split('_')[-1] != os.path.dirname(record).split('_')[-1]): + break + s = args.merge[2] + "/" + record.split("/")[-2] + '/' + record.split("/")[-1] + s = os.path.join(local_path,s) + record = os.path.join(local_path, record) + try: + shutil.copy2(record, s) + except FileNotFoundError: + os.mkdir(os.path.dirname(s)) + shutil.copy2(record, s) + previous_records = record + num_episode_dataset_1 = int(previous_records.split("/")[-2][7:]) + if (num_timesteps_1 == -1): + num_episode_dataset_1 += 1 + ts_counter_1 += 1 # copy files from second source - for record in sorted(glob.glob(args.merge[1] + "/record_[0-9]*/*")): + all_records = sorted(glob.glob(args.merge[1] + "/record_[0-9]*/*")) + previous_records = all_records[0] + for ts_counter_2, record in enumerate(all_records): + + if (num_timesteps_2 > 0 and ts_counter_2 > num_timesteps_2): + if (os.path.dirname(previous_records).split('_')[-1] != os.path.dirname(record).split('_')[-1]): + break episode = str(num_episode_dataset_1 + int(record.split("/")[-2][7:])) new_episode = record.split("/")[-2][:-len(episode)] + episode s = args.merge[2] + "/" + new_episode + '/' + record.split("/")[-1] - os.renames(record, s) - num_episode_dataset_2 = int(record.split("/")[-2][7:]) + 1 - + s = os.path.join(local_path, s) + record = os.path.join(local_path, record) + try: + shutil.copy2(record, s) + except FileNotFoundError: + os.mkdir(os.path.dirname(s)) + shutil.copy2(record, s) + previous_records = record + + num_episode_dataset_2 = int(previous_records.split("/")[-2][7:]) + if(num_timesteps_2==-1): + num_episode_dataset_2 +=1 + ts_counter_2 +=1 + + ts_counter = [ts_counter_1, ts_counter_2] # load and correct ground_truth ground_truth = {} ground_truth_load = np.load(args.merge[0] + "/ground_truth.npz") @@ -76,12 +115,20 @@ def main(): index_margin_str = len("/record_") directory_str = args.merge[2][index_slash+1:] + len_info_1 = [len(ground_truth_load[k]) for k in ground_truth_load.keys()] + num_eps_total_1, num_ts_total_1 = min(len_info_1), max(len_info_1) + len_info_2 = [len(ground_truth_load_2[k]) for k in ground_truth_load_2.keys()] + num_eps_total_2, num_ts_total_2 = min(len_info_2), max(len_info_2) + + for idx_, gt_load in enumerate([ground_truth_load, ground_truth_load_2], 1): + for arr in gt_load.files: + if arr == "images_path": # here, we want to rename just the folder containing the records, hence the black magic - for i in tqdm(range(len(gt_load["images_path"])), + for i in tqdm(range(ts_counter[idx_-1]),#range(len(gt_load["images_path"])), desc="Update of paths (Folder " + str(1+idx_) + ")"): # find the "record_" position path = gt_load["images_path"][i] @@ -95,21 +142,39 @@ def main(): else: new_record_path = path[end_pos:] ground_truth["images_path"].append(directory_str + new_record_path) + else: # anything that isnt image_path, we dont need to change gt_arr = gt_load[arr] if idx_ > 1: num_episode_dataset = num_episode_dataset_2 - # HERE check before overwritting that the target is random !+ if gt_load[arr].shape[0] < num_episode_dataset: gt_arr = np.repeat(gt_load[arr], num_episode_dataset, axis=0) if idx_ > 1: - ground_truth[arr] = np.concatenate((ground_truth[arr], gt_arr), axis=0) + # This is the first dataset + if (len(gt_arr) == num_eps_total_2): + # This is a episode non-change variable + ground_truth[arr] = np.concatenate((ground_truth[arr], + gt_arr[:num_episode_dataset_2]), axis=0) + elif (len(gt_arr) == num_ts_total_2): # a timesteps changing variable + ground_truth[arr] = np.concatenate((ground_truth[arr], + gt_arr[:ts_counter_2]), axis=0) + else: + assert 0 == 1, "No compatible variable in the stored ground truth for the second dataset {}" \ + .format(args.merge[1]) else: - ground_truth[arr] = gt_arr + # This is the first dataset + if(len(gt_arr) == num_eps_total_1): + #This is a episode non-change variable + ground_truth[arr] = gt_arr[:num_episode_dataset_1] + elif(len(gt_arr) == num_ts_total_1): # a timesteps changing variable + ground_truth[arr] = gt_arr[:ts_counter_1] + else: + assert 0 ==1 , "No compatible variable in the stored ground truth for the first dataset {}"\ + .format(args.merge[0]) # save the corrected ground_truth np.savez(args.merge[2] + "/ground_truth.npz", **ground_truth) @@ -121,8 +186,6 @@ def main(): dataset_1_size = preprocessed_load["actions"].shape[0] dataset_2_size = preprocessed_load_2["actions"].shape[0] - - # Concatenating additional information: indices of episode start, action probabilities, CL labels... for idx, prepro_load in enumerate([preprocessed_load, preprocessed_load_2]): for arr in prepro_load.files: pr_arr = prepro_load[arr] @@ -130,29 +193,43 @@ def main(): to_class = None if arr == "episode_starts": to_class = bool - elif arr == "actions_proba" or arr == "rewards": + elif arr == "actions_proba" or arr =="rewards": to_class = float else: to_class = int - if preprocessed.get(arr, None) is None: - preprocessed[arr] = pr_arr.astype(to_class) - else: + # all data is of timesteps changing (instead of episode changing) + if preprocessed.get(arr, None) is None: #for the first dataset + preprocessed[arr] = pr_arr.astype(to_class)[:ts_counter_1] + else:# for the second dataset preprocessed[arr] = np.concatenate((preprocessed[arr].astype(to_class), - pr_arr.astype(to_class)), axis=0) + pr_arr[:ts_counter_2].astype(to_class)), axis=0) if 'continual_learning_labels' in args: if preprocessed.get(CL_LABEL_KEY, None) is None: preprocessed[CL_LABEL_KEY] = \ - np.array([args.continual_learning_labels[idx] for _ in range(dataset_1_size)]) + np.array([args.continual_learning_labels[idx] for _ in range(ts_counter_1)]) else: preprocessed[CL_LABEL_KEY] = \ np.concatenate((preprocessed[CL_LABEL_KEY], np.array([args.continual_learning_labels[idx] - for _ in range(dataset_2_size)])), axis=0) + for _ in range(ts_counter_2)])), axis=0) + + print("The total timesteps: ", ts_counter_1+ts_counter_2) + print("The total episodes: ", num_episode_dataset_1+num_episode_dataset_2) + for k in preprocessed: + print(k) + print(preprocessed[k].shape) + + for k in ground_truth: + print(k) + print(ground_truth[k].shape) + + np.savez(args.merge[2] + "/preprocessed_data.npz", ** preprocessed) + # remove the old folders - shutil.rmtree(args.merge[0]) - shutil.rmtree(args.merge[1]) + # shutil.rmtree(args.merge[0]) + # shutil.rmtree(args.merge[1]) if __name__ == '__main__': From 8701bb08ce866481e4ded57b892905a249dcf481 Mon Sep 17 00:00:00 2001 From: TeTe <32313299+sun-te@users.noreply.github.com> Date: Wed, 26 Jun 2019 15:12:49 +0200 Subject: [PATCH 124/141] Revert "reward can be float for circular task and escaping task" --- environments/dataset_merger.py | 135 +++++++-------------------------- 1 file changed, 29 insertions(+), 106 deletions(-) diff --git a/environments/dataset_merger.py b/environments/dataset_merger.py index af4b3d9aa..7d8ceaa1c 100644 --- a/environments/dataset_merger.py +++ b/environments/dataset_merger.py @@ -4,11 +4,12 @@ import argparse import os import shutil -import pdb import numpy as np from tqdm import tqdm +# List of all possible labels identifying a task, +# for experiments in Continual Learning scenari. CONTINUAL_LEARNING_LABELS = ['CC', 'SC', 'EC', 'SQC'] CL_LABEL_KEY = "continual_learning_label" @@ -22,14 +23,13 @@ def main(): parser.add_argument('-f', '--force', action='store_true', default=False, help='Force the merge, even if it overrides something else,' ' including the destination if it exist') - parser.add_argument('--timesteps', type=int, nargs=2, default=[-1,-1], - help="To have a certain number of frames for two data sets ") group = parser.add_mutually_exclusive_group() group.add_argument('--merge', type=str, nargs=3, metavar=('source_1', 'source_2', 'destination'), default=argparse.SUPPRESS, help='Merge two datasets by appending the episodes, deleting sources right after.') args = parser.parse_args() + if 'merge' in args: # let make sure everything is in order assert os.path.exists(args.merge[0]), "Error: dataset '{}' could not be found".format(args.merge[0]) @@ -47,63 +47,24 @@ def main(): # create the output os.mkdir(args.merge[2]) - - #os.rename(args.merge[0] + "/dataset_config.json", args.merge[2] + "/dataset_config.json") - #os.rename(args.merge[0] + "/env_globals.json", args.merge[2] + "/env_globals.json") - shutil.copy2(args.merge[0] + "/dataset_config.json",args.merge[2] + "/dataset_config.json") - shutil.copy2(args.merge[0] + "/env_globals.json", args.merge[2] + "/env_globals.json") - # copy files from first source - num_timesteps_1, num_timesteps_2 = args.timesteps - local_path = os.getcwd() - all_records = sorted(glob.glob(args.merge[0] + "/record_[0-9]*/*")) - previous_records = all_records[0] - for ts_counter_1, record in enumerate(all_records): - - #if the timesteps is larger than needed, we wait until this episode is over - if(num_timesteps_1>0 and ts_counter_1 >num_timesteps_1): - if(os.path.dirname(previous_records).split('_')[-1] != os.path.dirname(record).split('_')[-1]): - break + os.rename(args.merge[0] + "/dataset_config.json", args.merge[2] + "/dataset_config.json") + os.rename(args.merge[0] + "/env_globals.json", args.merge[2] + "/env_globals.json") + + for record in sorted(glob.glob(args.merge[0] + "/record_[0-9]*/*")): s = args.merge[2] + "/" + record.split("/")[-2] + '/' + record.split("/")[-1] - s = os.path.join(local_path,s) - record = os.path.join(local_path, record) - try: - shutil.copy2(record, s) - except FileNotFoundError: - os.mkdir(os.path.dirname(s)) - shutil.copy2(record, s) - previous_records = record - num_episode_dataset_1 = int(previous_records.split("/")[-2][7:]) - if (num_timesteps_1 == -1): - num_episode_dataset_1 += 1 - ts_counter_1 += 1 + os.renames(record, s) - # copy files from second source - all_records = sorted(glob.glob(args.merge[1] + "/record_[0-9]*/*")) - previous_records = all_records[0] - for ts_counter_2, record in enumerate(all_records): + num_episode_dataset_1 = int(record.split("/")[-2][7:]) + 1 - if (num_timesteps_2 > 0 and ts_counter_2 > num_timesteps_2): - if (os.path.dirname(previous_records).split('_')[-1] != os.path.dirname(record).split('_')[-1]): - break + # copy files from second source + for record in sorted(glob.glob(args.merge[1] + "/record_[0-9]*/*")): episode = str(num_episode_dataset_1 + int(record.split("/")[-2][7:])) new_episode = record.split("/")[-2][:-len(episode)] + episode s = args.merge[2] + "/" + new_episode + '/' + record.split("/")[-1] - s = os.path.join(local_path, s) - record = os.path.join(local_path, record) - try: - shutil.copy2(record, s) - except FileNotFoundError: - os.mkdir(os.path.dirname(s)) - shutil.copy2(record, s) - previous_records = record - - num_episode_dataset_2 = int(previous_records.split("/")[-2][7:]) - if(num_timesteps_2==-1): - num_episode_dataset_2 +=1 - ts_counter_2 +=1 - - ts_counter = [ts_counter_1, ts_counter_2] + os.renames(record, s) + num_episode_dataset_2 = int(record.split("/")[-2][7:]) + 1 + # load and correct ground_truth ground_truth = {} ground_truth_load = np.load(args.merge[0] + "/ground_truth.npz") @@ -115,20 +76,12 @@ def main(): index_margin_str = len("/record_") directory_str = args.merge[2][index_slash+1:] - len_info_1 = [len(ground_truth_load[k]) for k in ground_truth_load.keys()] - num_eps_total_1, num_ts_total_1 = min(len_info_1), max(len_info_1) - len_info_2 = [len(ground_truth_load_2[k]) for k in ground_truth_load_2.keys()] - num_eps_total_2, num_ts_total_2 = min(len_info_2), max(len_info_2) - - for idx_, gt_load in enumerate([ground_truth_load, ground_truth_load_2], 1): - for arr in gt_load.files: - if arr == "images_path": # here, we want to rename just the folder containing the records, hence the black magic - for i in tqdm(range(ts_counter[idx_-1]),#range(len(gt_load["images_path"])), + for i in tqdm(range(len(gt_load["images_path"])), desc="Update of paths (Folder " + str(1+idx_) + ")"): # find the "record_" position path = gt_load["images_path"][i] @@ -142,39 +95,21 @@ def main(): else: new_record_path = path[end_pos:] ground_truth["images_path"].append(directory_str + new_record_path) - else: # anything that isnt image_path, we dont need to change gt_arr = gt_load[arr] if idx_ > 1: num_episode_dataset = num_episode_dataset_2 + # HERE check before overwritting that the target is random !+ if gt_load[arr].shape[0] < num_episode_dataset: gt_arr = np.repeat(gt_load[arr], num_episode_dataset, axis=0) if idx_ > 1: - # This is the first dataset - if (len(gt_arr) == num_eps_total_2): - # This is a episode non-change variable - ground_truth[arr] = np.concatenate((ground_truth[arr], - gt_arr[:num_episode_dataset_2]), axis=0) - elif (len(gt_arr) == num_ts_total_2): # a timesteps changing variable - ground_truth[arr] = np.concatenate((ground_truth[arr], - gt_arr[:ts_counter_2]), axis=0) - else: - assert 0 == 1, "No compatible variable in the stored ground truth for the second dataset {}" \ - .format(args.merge[1]) + ground_truth[arr] = np.concatenate((ground_truth[arr], gt_arr), axis=0) else: - # This is the first dataset - if(len(gt_arr) == num_eps_total_1): - #This is a episode non-change variable - ground_truth[arr] = gt_arr[:num_episode_dataset_1] - elif(len(gt_arr) == num_ts_total_1): # a timesteps changing variable - ground_truth[arr] = gt_arr[:ts_counter_1] - else: - assert 0 ==1 , "No compatible variable in the stored ground truth for the first dataset {}"\ - .format(args.merge[0]) + ground_truth[arr] = gt_arr # save the corrected ground_truth np.savez(args.merge[2] + "/ground_truth.npz", **ground_truth) @@ -186,6 +121,8 @@ def main(): dataset_1_size = preprocessed_load["actions"].shape[0] dataset_2_size = preprocessed_load_2["actions"].shape[0] + + # Concatenating additional information: indices of episode start, action probabilities, CL labels... for idx, prepro_load in enumerate([preprocessed_load, preprocessed_load_2]): for arr in prepro_load.files: pr_arr = prepro_load[arr] @@ -193,43 +130,29 @@ def main(): to_class = None if arr == "episode_starts": to_class = bool - elif arr == "actions_proba" or arr =="rewards": + elif arr == "actions_proba": to_class = float else: to_class = int - # all data is of timesteps changing (instead of episode changing) - if preprocessed.get(arr, None) is None: #for the first dataset - preprocessed[arr] = pr_arr.astype(to_class)[:ts_counter_1] - else:# for the second dataset + if preprocessed.get(arr, None) is None: + preprocessed[arr] = pr_arr.astype(to_class) + else: preprocessed[arr] = np.concatenate((preprocessed[arr].astype(to_class), - pr_arr[:ts_counter_2].astype(to_class)), axis=0) + pr_arr.astype(to_class)), axis=0) if 'continual_learning_labels' in args: if preprocessed.get(CL_LABEL_KEY, None) is None: preprocessed[CL_LABEL_KEY] = \ - np.array([args.continual_learning_labels[idx] for _ in range(ts_counter_1)]) + np.array([args.continual_learning_labels[idx] for _ in range(dataset_1_size)]) else: preprocessed[CL_LABEL_KEY] = \ np.concatenate((preprocessed[CL_LABEL_KEY], np.array([args.continual_learning_labels[idx] - for _ in range(ts_counter_2)])), axis=0) - - print("The total timesteps: ", ts_counter_1+ts_counter_2) - print("The total episodes: ", num_episode_dataset_1+num_episode_dataset_2) - for k in preprocessed: - print(k) - print(preprocessed[k].shape) - - for k in ground_truth: - print(k) - print(ground_truth[k].shape) - - + for _ in range(dataset_2_size)])), axis=0) np.savez(args.merge[2] + "/preprocessed_data.npz", ** preprocessed) - # remove the old folders - # shutil.rmtree(args.merge[0]) - # shutil.rmtree(args.merge[1]) + shutil.rmtree(args.merge[0]) + shutil.rmtree(args.merge[1]) if __name__ == '__main__': From fbde89d64a1a08677a76f327c86501124fa79ea7 Mon Sep 17 00:00:00 2001 From: sun-te Date: Wed, 26 Jun 2019 23:35:06 +0200 Subject: [PATCH 125/141] dataset manager --- environments/data_seperator.py | 53 +++++++++++++ environments/dataset_merger.py | 139 +++++++++++++++++++++++++-------- 2 files changed, 160 insertions(+), 32 deletions(-) create mode 100644 environments/data_seperator.py diff --git a/environments/data_seperator.py b/environments/data_seperator.py new file mode 100644 index 000000000..971b266b5 --- /dev/null +++ b/environments/data_seperator.py @@ -0,0 +1,53 @@ +""" +Script to verify the states distribution +""" +import json +import os +import argparse + + +import numpy as np +import torch as th +from ipdb import set_trace as tt + +from state_representation.models import loadSRLModel, getSRLDim + + + + +#os.chdir('/home/tete/Robotics-branches/robotics-rl-srl-two/logs/teacher_policies_for_evaluation/sc/OmnirobotEnv-v0/srl_combination/ppo2/19-06-19_01h10_00') + + + +def dataDistribution(srl_model_path=None): + state_dim = getSRLDim(srl_model_path) + srl_model = loadSRLModel(srl_model_path,th.cuda.is_available(), state_dim, env_object=None) + + #model = MLPPolicy(output_size=n_actions, input_size=self.state_dim) + + + return + +def loadKwargs(log_dir): + with open(os.path.join(args.log_dir, 'args.json')) as data: + rl_kwargs = json.load(data) + with open(os.path.join(args.log_dir, 'env_globals.json')) as data: + env_kwargs = json.load(data) + return rl_kwargs, env_kwargs + +if __name__ == '__main__': + + + parser = argparse.ArgumentParser(description="Train script for RL algorithms") + parser.add_argument('--log-dir', type=str, default='logs/teacher_policies_for_evaluation/sc/OmnirobotEnv-v0/srl_combination/ppo2/19-06-19_01h10_00' + ) + parser.add_argument('') + args, unknown = parser.parse_known_args() + + rl_kwargs, env_kwargs = loadKwargs(args.log_dir) + srl_model_path = env_kwargs['srl_model_path'] + + dataDistribution(srl_model_path=srl_model_path) + + + print("OK") diff --git a/environments/dataset_merger.py b/environments/dataset_merger.py index 2d1bed0dc..21b874d5a 100644 --- a/environments/dataset_merger.py +++ b/environments/dataset_merger.py @@ -4,12 +4,11 @@ import argparse import os import shutil +import pdb import numpy as np from tqdm import tqdm -# List of all possible labels identifying a task, -# for experiments in Continual Learning scenari. CONTINUAL_LEARNING_LABELS = ['CC', 'SC', 'EC', 'SQC'] CL_LABEL_KEY = "continual_learning_label" @@ -23,13 +22,14 @@ def main(): parser.add_argument('-f', '--force', action='store_true', default=False, help='Force the merge, even if it overrides something else,' ' including the destination if it exist') + parser.add_argument('--timesteps', type=int, nargs=2, default=[-1,-1], + help="To have a certain number of frames for two data sets ") group = parser.add_mutually_exclusive_group() group.add_argument('--merge', type=str, nargs=3, metavar=('source_1', 'source_2', 'destination'), default=argparse.SUPPRESS, help='Merge two datasets by appending the episodes, deleting sources right after.') args = parser.parse_args() - if 'merge' in args: # let make sure everything is in order assert os.path.exists(args.merge[0]), "Error: dataset '{}' could not be found".format(args.merge[0]) @@ -47,24 +47,63 @@ def main(): # create the output os.mkdir(args.merge[2]) - # copy files from first source - os.rename(args.merge[0] + "/dataset_config.json", args.merge[2] + "/dataset_config.json") - os.rename(args.merge[0] + "/env_globals.json", args.merge[2] + "/env_globals.json") - for record in sorted(glob.glob(args.merge[0] + "/record_[0-9]*/*")): - s = args.merge[2] + "/" + record.split("/")[-2] + '/' + record.split("/")[-1] - os.renames(record, s) + #os.rename(args.merge[0] + "/dataset_config.json", args.merge[2] + "/dataset_config.json") + #os.rename(args.merge[0] + "/env_globals.json", args.merge[2] + "/env_globals.json") + shutil.copy2(args.merge[0] + "/dataset_config.json",args.merge[2] + "/dataset_config.json") + shutil.copy2(args.merge[0] + "/env_globals.json", args.merge[2] + "/env_globals.json") - num_episode_dataset_1 = int(record.split("/")[-2][7:]) + 1 + # copy files from first source + num_timesteps_1, num_timesteps_2 = args.timesteps + local_path = os.getcwd() + all_records = sorted(glob.glob(args.merge[0] + "/record_[0-9]*/*")) + previous_records = all_records[0] + for ts_counter_1, record in enumerate(all_records): + + #if the timesteps is larger than needed, we wait until this episode is over + if(num_timesteps_1>0 and ts_counter_1 >num_timesteps_1): + if(os.path.dirname(previous_records).split('_')[-1] != os.path.dirname(record).split('_')[-1]): + break + s = args.merge[2] + "/" + record.split("/")[-2] + '/' + record.split("/")[-1] + s = os.path.join(local_path,s) + record = os.path.join(local_path, record) + try: + shutil.copy2(record, s) + except FileNotFoundError: + os.mkdir(os.path.dirname(s)) + shutil.copy2(record, s) + previous_records = record + num_episode_dataset_1 = int(previous_records.split("/")[-2][7:]) + if (num_timesteps_1 == -1): + num_episode_dataset_1 += 1 + ts_counter_1 += 1 # copy files from second source - for record in sorted(glob.glob(args.merge[1] + "/record_[0-9]*/*")): + all_records = sorted(glob.glob(args.merge[1] + "/record_[0-9]*/*")) + previous_records = all_records[0] + for ts_counter_2, record in enumerate(all_records): + + if (num_timesteps_2 > 0 and ts_counter_2 > num_timesteps_2): + if (os.path.dirname(previous_records).split('_')[-1] != os.path.dirname(record).split('_')[-1]): + break episode = str(num_episode_dataset_1 + int(record.split("/")[-2][7:])) new_episode = record.split("/")[-2][:-len(episode)] + episode s = args.merge[2] + "/" + new_episode + '/' + record.split("/")[-1] - os.renames(record, s) - num_episode_dataset_2 = int(record.split("/")[-2][7:]) + 1 - + s = os.path.join(local_path, s) + record = os.path.join(local_path, record) + try: + shutil.copy2(record, s) + except FileNotFoundError: + os.mkdir(os.path.dirname(s)) + shutil.copy2(record, s) + previous_records = record + + num_episode_dataset_2 = int(previous_records.split("/")[-2][7:]) + if(num_timesteps_2==-1): + num_episode_dataset_2 +=1 + ts_counter_2 +=1 + + ts_counter = [ts_counter_1, ts_counter_2] # load and correct ground_truth ground_truth = {} ground_truth_load = np.load(args.merge[0] + "/ground_truth.npz") @@ -76,12 +115,20 @@ def main(): index_margin_str = len("/record_") directory_str = args.merge[2][index_slash+1:] + len_info_1 = [len(ground_truth_load[k]) for k in ground_truth_load.keys()] + num_eps_total_1, num_ts_total_1 = min(len_info_1), max(len_info_1) + len_info_2 = [len(ground_truth_load_2[k]) for k in ground_truth_load_2.keys()] + num_eps_total_2, num_ts_total_2 = min(len_info_2), max(len_info_2) + + for idx_, gt_load in enumerate([ground_truth_load, ground_truth_load_2], 1): + for arr in gt_load.files: + if arr == "images_path": # here, we want to rename just the folder containing the records, hence the black magic - for i in tqdm(range(len(gt_load["images_path"])), + for i in tqdm(range(ts_counter[idx_-1]),#range(len(gt_load["images_path"])), desc="Update of paths (Folder " + str(1+idx_) + ")"): # find the "record_" position path = gt_load["images_path"][i] @@ -95,23 +142,39 @@ def main(): else: new_record_path = path[end_pos:] ground_truth["images_path"].append(directory_str + new_record_path) + else: # anything that isnt image_path, we dont need to change gt_arr = gt_load[arr] if idx_ > 1: num_episode_dataset = num_episode_dataset_2 - # HERE check before overwritting that the target is random !+ if gt_load[arr].shape[0] < num_episode_dataset: gt_arr = np.repeat(gt_load[arr], num_episode_dataset, axis=0) if idx_ > 1: - if gt_arr.shape == ground_truth[arr].shape: - ground_truth[arr] = np.concatenate((ground_truth[arr], gt_arr), axis=0) - + # This is the first dataset + if (len(gt_arr) == num_eps_total_2): + # This is a episode non-change variable + ground_truth[arr] = np.concatenate((ground_truth[arr], + gt_arr[:num_episode_dataset_2]), axis=0) + elif (len(gt_arr) == num_ts_total_2): # a timesteps changing variable + ground_truth[arr] = np.concatenate((ground_truth[arr], + gt_arr[:ts_counter_2]), axis=0) + else: + assert 0 == 1, "No compatible variable in the stored ground truth for the second dataset {}" \ + .format(args.merge[1]) else: - ground_truth[arr] = gt_arr + # This is the first dataset + if(len(gt_arr) == num_eps_total_1): + #This is a episode non-change variable + ground_truth[arr] = gt_arr[:num_episode_dataset_1] + elif(len(gt_arr) == num_ts_total_1): # a timesteps changing variable + ground_truth[arr] = gt_arr[:ts_counter_1] + else: + assert 0 ==1 , "No compatible variable in the stored ground truth for the first dataset {}"\ + .format(args.merge[0]) # save the corrected ground_truth np.savez(args.merge[2] + "/ground_truth.npz", **ground_truth) @@ -123,8 +186,6 @@ def main(): dataset_1_size = preprocessed_load["actions"].shape[0] dataset_2_size = preprocessed_load_2["actions"].shape[0] - - # Concatenating additional information: indices of episode start, action probabilities, CL labels... for idx, prepro_load in enumerate([preprocessed_load, preprocessed_load_2]): for arr in prepro_load.files: pr_arr = prepro_load[arr] @@ -132,30 +193,44 @@ def main(): to_class = None if arr == "episode_starts": to_class = bool - elif arr == "actions_proba": + elif arr == "actions_proba" or arr =="rewards": to_class = float else: to_class = int - if preprocessed.get(arr, None) is None: - preprocessed[arr] = pr_arr.astype(to_class) - else: + # all data is of timesteps changing (instead of episode changing) + if preprocessed.get(arr, None) is None: #for the first dataset + preprocessed[arr] = pr_arr.astype(to_class)[:ts_counter_1] + else:# for the second dataset preprocessed[arr] = np.concatenate((preprocessed[arr].astype(to_class), - pr_arr.astype(to_class)), axis=0) + pr_arr[:ts_counter_2].astype(to_class)), axis=0) if 'continual_learning_labels' in args: if preprocessed.get(CL_LABEL_KEY, None) is None: preprocessed[CL_LABEL_KEY] = \ - np.array([args.continual_learning_labels[idx] for _ in range(dataset_1_size)]) + np.array([args.continual_learning_labels[idx] for _ in range(ts_counter_1)]) else: preprocessed[CL_LABEL_KEY] = \ np.concatenate((preprocessed[CL_LABEL_KEY], np.array([args.continual_learning_labels[idx] - for _ in range(dataset_2_size)])), axis=0) + for _ in range(ts_counter_2)])), axis=0) + + print("The total timesteps: ", ts_counter_1+ts_counter_2) + print("The total episodes: ", num_episode_dataset_1+num_episode_dataset_2) + for k in preprocessed: + print(k) + print(preprocessed[k].shape) + + for k in ground_truth: + print(k) + print(ground_truth[k].shape) + + np.savez(args.merge[2] + "/preprocessed_data.npz", ** preprocessed) + # remove the old folders - shutil.rmtree(args.merge[0]) - shutil.rmtree(args.merge[1]) + # shutil.rmtree(args.merge[0]) + # shutil.rmtree(args.merge[1]) if __name__ == '__main__': - main() + main() \ No newline at end of file From 52e47302c95eaf5c64aa581f761b5b707f756ab4 Mon Sep 17 00:00:00 2001 From: sun-te Date: Thu, 27 Jun 2019 00:31:02 +0200 Subject: [PATCH 126/141] separator --- environments/data_separator.py | 65 ++++++++++++++++++++++++++++++++++ environments/data_seperator.py | 53 --------------------------- 2 files changed, 65 insertions(+), 53 deletions(-) create mode 100644 environments/data_separator.py delete mode 100644 environments/data_seperator.py diff --git a/environments/data_separator.py b/environments/data_separator.py new file mode 100644 index 000000000..23c31f03f --- /dev/null +++ b/environments/data_separator.py @@ -0,0 +1,65 @@ +""" +Script to verify the states distribution +""" +import json +import os +import argparse + + +import numpy as np +import torch as th +from ipdb import set_trace as tt + +from state_representation.models import loadSRLModel, getSRLDim +from srl_zoo.utils import loadData +from srl_zoo.preprocessing.data_loader import SupervisedDataLoader, DataLoader + + +#os.chdir('/home/tete/Robotics-branches/robotics-rl-srl-two/logs/teacher_policies_for_evaluation/sc/OmnirobotEnv-v0/srl_combination/ppo2/19-06-19_01h10_00') + + + +def dataDistribution(data_foler, srl_model_path=None): + state_dim = getSRLDim(srl_model_path) + srl_model = loadSRLModel(srl_model_path,th.cuda.is_available(), state_dim, env_object=None) + + #load images and other data + training_data, ground_truth, true_states, _ = loadData(data_foler, absolute_path=True) + rewards, episode_starts = training_data['rewards'], training_data['episode_starts'] + images_path = ground_truth['images_path'] + actions = training_data['actions'] + actions_proba = training_data['actions_proba'] + + # we change the path to the local path at the toolbox level + images_path_copy = ["srl_zoo/data/" + images_path[k] for k in range(images_path.shape[0])] + images_path = np.array(images_path_copy) + + tt() + + + + + return + +def loadKwargs(log_dir): + with open(os.path.join(args.log_dir, 'args.json')) as data: + rl_kwargs = json.load(data) + with open(os.path.join(args.log_dir, 'env_globals.json')) as data: + env_kwargs = json.load(data) + return rl_kwargs, env_kwargs + +if __name__ == '__main__': + + + parser = argparse.ArgumentParser(description="Train script for RL algorithms") + parser.add_argument('--log-dir', type=str, default='logs/teacher_policies_for_evaluation/sc/OmnirobotEnv-v0/srl_combination/ppo2/19-06-19_01h10_00') + parser.add_argument('--data-path', type=str, default='data/test_dataset/') + args, unknown = parser.parse_known_args() + + #rl_kwargs, env_kwargs = loadKwargs(args.log_dir) + #srl_model_path = env_kwargs['srl_model_path'] + srl_model_path = 'srl_zoo/logs/test_dataset/19-06-26_23h44_20_custom_cnn_ST_DIM200_inverse_autoencoder/srl_model.pth' + + print('Loading data for separation ') + dataDistribution(data_folder=args.data_path, srl_model_path=srl_model_path) + print("OK") diff --git a/environments/data_seperator.py b/environments/data_seperator.py deleted file mode 100644 index 971b266b5..000000000 --- a/environments/data_seperator.py +++ /dev/null @@ -1,53 +0,0 @@ -""" -Script to verify the states distribution -""" -import json -import os -import argparse - - -import numpy as np -import torch as th -from ipdb import set_trace as tt - -from state_representation.models import loadSRLModel, getSRLDim - - - - -#os.chdir('/home/tete/Robotics-branches/robotics-rl-srl-two/logs/teacher_policies_for_evaluation/sc/OmnirobotEnv-v0/srl_combination/ppo2/19-06-19_01h10_00') - - - -def dataDistribution(srl_model_path=None): - state_dim = getSRLDim(srl_model_path) - srl_model = loadSRLModel(srl_model_path,th.cuda.is_available(), state_dim, env_object=None) - - #model = MLPPolicy(output_size=n_actions, input_size=self.state_dim) - - - return - -def loadKwargs(log_dir): - with open(os.path.join(args.log_dir, 'args.json')) as data: - rl_kwargs = json.load(data) - with open(os.path.join(args.log_dir, 'env_globals.json')) as data: - env_kwargs = json.load(data) - return rl_kwargs, env_kwargs - -if __name__ == '__main__': - - - parser = argparse.ArgumentParser(description="Train script for RL algorithms") - parser.add_argument('--log-dir', type=str, default='logs/teacher_policies_for_evaluation/sc/OmnirobotEnv-v0/srl_combination/ppo2/19-06-19_01h10_00' - ) - parser.add_argument('') - args, unknown = parser.parse_known_args() - - rl_kwargs, env_kwargs = loadKwargs(args.log_dir) - srl_model_path = env_kwargs['srl_model_path'] - - dataDistribution(srl_model_path=srl_model_path) - - - print("OK") From 99d3039e09847020c5a7d42987c18233edc77757 Mon Sep 17 00:00:00 2001 From: sun-te Date: Thu, 27 Jun 2019 01:52:38 +0200 Subject: [PATCH 127/141] data separator --- environments/data_separator.py | 75 +++++++++++++++++-- .../supervised_rl/policy_distillation.py | 2 +- 2 files changed, 69 insertions(+), 8 deletions(-) diff --git a/environments/data_separator.py b/environments/data_separator.py index 23c31f03f..66cdd8648 100644 --- a/environments/data_separator.py +++ b/environments/data_separator.py @@ -5,39 +5,100 @@ import os import argparse - +import matplotlib.pyplot as plt +import seaborn as sns import numpy as np import torch as th +from tqdm import tqdm from ipdb import set_trace as tt + + from state_representation.models import loadSRLModel, getSRLDim from srl_zoo.utils import loadData from srl_zoo.preprocessing.data_loader import SupervisedDataLoader, DataLoader +sns.set() #os.chdir('/home/tete/Robotics-branches/robotics-rl-srl-two/logs/teacher_policies_for_evaluation/sc/OmnirobotEnv-v0/srl_combination/ppo2/19-06-19_01h10_00') +BATCH_SIZE = 32 +N_WORKERS = 4 +DEVICE = th.device("cuda" if th.cuda.is_available() else "cpu") +VALIDATION_SIZE = 0.2 # 20% of training data for validation + +def PCA(data, dim=2): + # preprocess the data + X = th.from_numpy(data).to(DEVICE) + X_mean = th.mean(X,0) + X = X - X_mean.expand_as(X) + # svd + U,S,V = th.svd(th.t(X)) + C = th.mm(X,U[:,:dim]).to('cpu').numpy() + return C -def dataDistribution(data_foler, srl_model_path=None): +def dataSeparator(data_folder, srl_model_path=None): state_dim = getSRLDim(srl_model_path) - srl_model = loadSRLModel(srl_model_path,th.cuda.is_available(), state_dim, env_object=None) + srl_model = loadSRLModel(srl_model_path, th.cuda.is_available(), state_dim, env_object=None) #load images and other data - training_data, ground_truth, true_states, _ = loadData(data_foler, absolute_path=True) + print('Loading data for separation ') + training_data, ground_truth, true_states, _ = loadData(data_folder, absolute_path=True) rewards, episode_starts = training_data['rewards'], training_data['episode_starts'] images_path = ground_truth['images_path'] actions = training_data['actions'] actions_proba = training_data['actions_proba'] + ground_turht_states_dim = true_states.shape[1] + + # we change the path to the local path at the toolbox level images_path_copy = ["srl_zoo/data/" + images_path[k] for k in range(images_path.shape[0])] images_path = np.array(images_path_copy) - tt() + num_samples = images_path.shape[0] # number of samples + + # indices for all time steps where the episode continues + indices = np.array([i for i in range(num_samples-1) if not episode_starts[i + 1]], dtype='int64') + minibatchlist = [np.array(sorted(indices[start_idx:start_idx + BATCH_SIZE])) + for start_idx in range(0, len(indices) - BATCH_SIZE + 1, BATCH_SIZE)] + data_loader = DataLoader(minibatchlist, images_path, n_workers=N_WORKERS, multi_view=False, + use_triplets=False, is_training=True, absolute_path=True) + srl_data = [] + #we only use the srl model to deduct the states + srl_model.model = srl_model.model.eval() + pbar = tqdm(total=len(data_loader)) + for minibatch_num, (minibatch_idx, obs, _, _, _) in enumerate(data_loader): + obs = obs.to(DEVICE) + state = srl_model.model.getStates(obs).to('cpu').detach().numpy() + srl_data.append(state) + pbar.update(1) + # concatenate into one numpy array + srl_data = np.concatenate(srl_data,axis=0) + # PCA for the v + pca_srl_data = PCA(srl_data, dim=ground_turht_states_dim) + + + training_indices = np.concatenate(minibatchlist) + np.random.shuffle(training_indices) + + val_num = int(len(training_indices) * VALIDATION_SIZE) + # TODO: subplot + # plt.scatter(pca_srl_data[:val_num, 0], pca_srl_data[:val_num, 1], s=10, c='r',label='Validation') + # plt.scatter(pca_srl_data[val_num:, 0], pca_srl_data[val_num:, 1], s=3, c='b', label='Training') + # plt.legend() + # plt.show() + + + plt.hist2d(pca_srl_data[:val_num, 0], pca_srl_data[:val_num, 1], bins=val_num//10) + plt.show() + + plt.hist2d(pca_srl_data[val_num:, 0], pca_srl_data[val_num:, 1], bins=len(pca_srl_data[val_num:])//10 ) + plt.show() return @@ -60,6 +121,6 @@ def loadKwargs(log_dir): #srl_model_path = env_kwargs['srl_model_path'] srl_model_path = 'srl_zoo/logs/test_dataset/19-06-26_23h44_20_custom_cnn_ST_DIM200_inverse_autoencoder/srl_model.pth' - print('Loading data for separation ') - dataDistribution(data_folder=args.data_path, srl_model_path=srl_model_path) + + dataSeparator(data_folder=args.data_path, srl_model_path=srl_model_path) print("OK") diff --git a/rl_baselines/supervised_rl/policy_distillation.py b/rl_baselines/supervised_rl/policy_distillation.py index d0febb771..e2f8f0dc5 100644 --- a/rl_baselines/supervised_rl/policy_distillation.py +++ b/rl_baselines/supervised_rl/policy_distillation.py @@ -174,7 +174,7 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): indices = np.array([i for i in range(num_samples) if not episode_starts[i + 1]], dtype='int64') np.random.shuffle(indices) - # split indices into minibatches. minibatchlist is a list of lists; each + # split indices into minibatches. minibatchlis t is a list of lists; each # list is the id of the observation preserved through the training minibatchlist = [np.array(sorted(indices[start_idx:start_idx + self.batch_size])) for start_idx in range(0, len(indices) - self.batch_size + 1, self.batch_size)] From ce2d7e4798766d31303a0431cb65b3090c125210 Mon Sep 17 00:00:00 2001 From: sun-te Date: Thu, 27 Jun 2019 18:38:54 +0200 Subject: [PATCH 128/141] separator --- environments/data_separator.py | 104 ++++++++++++++++++++++++++------- 1 file changed, 83 insertions(+), 21 deletions(-) diff --git a/environments/data_separator.py b/environments/data_separator.py index 66cdd8648..c2c09ff20 100644 --- a/environments/data_separator.py +++ b/environments/data_separator.py @@ -10,6 +10,8 @@ import numpy as np import torch as th from tqdm import tqdm +from multiprocessing import Pool +from functools import partial from ipdb import set_trace as tt @@ -22,8 +24,8 @@ #os.chdir('/home/tete/Robotics-branches/robotics-rl-srl-two/logs/teacher_policies_for_evaluation/sc/OmnirobotEnv-v0/srl_combination/ppo2/19-06-19_01h10_00') -BATCH_SIZE = 32 -N_WORKERS = 4 +BATCH_SIZE = 256 +N_WORKERS = 8 DEVICE = th.device("cuda" if th.cuda.is_available() else "cpu") VALIDATION_SIZE = 0.2 # 20% of training data for validation @@ -38,7 +40,15 @@ def PCA(data, dim=2): C = th.mm(X,U[:,:dim]).to('cpu').numpy() return C -def dataSeparator(data_folder, srl_model_path=None): +def dataSrlLoad(data_folder, srl_model_path=None, pca_mode=True, normalized=True, threshold=0.01): + """ + + :param data_folder: (str) the path to the dataset we want to sample + :param srl_model_path: (str) + :return: the dataset after the srl evaluation and a pca preprocessd, + it self, a random sampled training set, validation set + """ + state_dim = getSRLDim(srl_model_path) srl_model = loadSRLModel(srl_model_path, th.cuda.is_available(), state_dim, env_object=None) @@ -77,35 +87,86 @@ def dataSeparator(data_folder, srl_model_path=None): state = srl_model.model.getStates(obs).to('cpu').detach().numpy() srl_data.append(state) pbar.update(1) + # concatenate into one numpy array srl_data = np.concatenate(srl_data,axis=0) # PCA for the v - pca_srl_data = PCA(srl_data, dim=ground_turht_states_dim) - + if pca_mode: + pca_srl_data = PCA(srl_data, dim=ground_turht_states_dim) + else: + pca_srl_data = srl_data + if normalized: # Normilized into -0.5 to +0.5 + for k in range(pca_srl_data.shape[1]): + pca_srl_data[:, k] = (pca_srl_data[:, k] - np.min(pca_srl_data[:, k])) / ( + np.max(pca_srl_data[:, k]) - np.min(pca_srl_data[:, k])) - 0.5 training_indices = np.concatenate(minibatchlist) - np.random.shuffle(training_indices) val_num = int(len(training_indices) * VALIDATION_SIZE) - # TODO: subplot - # plt.scatter(pca_srl_data[:val_num, 0], pca_srl_data[:val_num, 1], s=10, c='r',label='Validation') - # plt.scatter(pca_srl_data[val_num:, 0], pca_srl_data[val_num:, 1], s=3, c='b', label='Training') - # plt.legend() - # plt.show() + #return the index that we dont need to save anymore + index_del = dataSelection(0.01,pca_srl_data) - plt.hist2d(pca_srl_data[:val_num, 0], pca_srl_data[:val_num, 1], bins=val_num//10) - plt.show() + index_save = [i for i in range(len(index_del)) if not index_del[i]] - plt.hist2d(pca_srl_data[val_num:, 0], pca_srl_data[val_num:, 1], bins=len(pca_srl_data[val_num:])//10 ) + return + +def plotDistribution(pca_srl_data, val_num): + fig, ax = plt.subplots(nrows=1, ncols=3, figsize=[24, 8]) + x_min, x_max = pca_srl_data[:, 0].min(), pca_srl_data[:, 0].max() + y_min, y_max = pca_srl_data[:, 1].min(), pca_srl_data[:, 1].max() + ax[0].scatter(pca_srl_data[val_num:, 0], pca_srl_data[val_num:, 1], s=5, c='b', label='Training') + ax[0].scatter(pca_srl_data[:val_num, 0], pca_srl_data[:val_num, 1], s=5, c='r', label='Validation') + ax[0].legend() + ax[0].title.set_text('Sample') + # plt.show() + ax[1].hist2d(pca_srl_data[:val_num, 0], pca_srl_data[:val_num, 1], + bins=100, range=[[x_min, x_max], [y_min, y_max]]) + ax[1].title.set_text('Validation distribution') + ax[2].hist2d(pca_srl_data[val_num:, 0], pca_srl_data[val_num:, 1], + bins=100, range=[[x_min, x_max], [y_min, y_max]]) + ax[2].title.set_text('Training distribution') plt.show() - return + +def _del_val(p_val, train_set, threshold): + """ + if the points are too close to each other, we will delete it from the dataset. + :param p_val: (np.array) the data points of validation set + :param train_set: (np.array) the training set + :param threshold: (float) + :return: + """ + for p_train in train_set: + if (np.linalg.norm(p_val - p_train) < threshold): + # we will delete the data point + return True + else: + return False + +def dataSelection(threshold, train_set, val_set=None): + """ + + :param val_set: the validation set that we want to resimpling + :param train_set: + :param threshold: + :return: + """ + #if we dont precise the validation set, the suppression will be on the whole dataset (training set) + if val_set == None: + val_set = train_set + # multiprocessing + pool = Pool() + # if index[i] is ture, then we will delete it from the dataset + index_to_del = pool.map(partial(_del_val, train_set=train_set, threshold=threshold), val_set) + + return index_to_del + def loadKwargs(log_dir): - with open(os.path.join(args.log_dir, 'args.json')) as data: + with open(os.path.join(log_dir, 'args.json')) as data: rl_kwargs = json.load(data) - with open(os.path.join(args.log_dir, 'env_globals.json')) as data: + with open(os.path.join(log_dir, 'env_globals.json')) as data: env_kwargs = json.load(data) return rl_kwargs, env_kwargs @@ -117,10 +178,11 @@ def loadKwargs(log_dir): parser.add_argument('--data-path', type=str, default='data/test_dataset/') args, unknown = parser.parse_known_args() - #rl_kwargs, env_kwargs = loadKwargs(args.log_dir) - #srl_model_path = env_kwargs['srl_model_path'] - srl_model_path = 'srl_zoo/logs/test_dataset/19-06-26_23h44_20_custom_cnn_ST_DIM200_inverse_autoencoder/srl_model.pth' + rl_kwargs, env_kwargs = loadKwargs(args.log_dir) + srl_model_path = env_kwargs['srl_model_path'] + tt() + #srl_model_path = 'srl_zoo/logs/test_dataset/19-06-26_23h44_20_custom_cnn_ST_DIM200_inverse_autoencoder/srl_model.pth' - dataSeparator(data_folder=args.data_path, srl_model_path=srl_model_path) + dataSrlLoad(data_folder=args.data_path, srl_model_path=srl_model_path) print("OK") From f6c0f0323e3fe9354d8b1ee23e03505a383d4382 Mon Sep 17 00:00:00 2001 From: sun-te Date: Thu, 27 Jun 2019 19:18:12 +0200 Subject: [PATCH 129/141] sparser dataset --- delete_val.ipynb | 497 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 497 insertions(+) create mode 100644 delete_val.ipynb diff --git a/delete_val.ipynb b/delete_val.ipynb new file mode 100644 index 000000000..dda677110 --- /dev/null +++ b/delete_val.ipynb @@ -0,0 +1,497 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "from environments.data_separator import dataSrlLoad, plotDistribution\n", + "import torch as th\n", + "import matplotlib.pyplot as plt\n", + "import seaborn as sns\n", + "from tqdm import tqdm\n", + "from multiprocessing import Pool" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "BATCH_SIZE = 256\n", + "N_WORKERS = 8\n", + "DEVICE = th.device(\"cuda\" if th.cuda.is_available() else \"cpu\")\n", + "VALIDATION_SIZE = 0.2 # 20% of training data for validation" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "srl_model_path = 'srl_zoo/logs/Omnibot_random_simple//19-06-17_15h37_05_custom_cnn_ST_DIM200_inverse_autoencoder/srl_model.pth'\n", + "data_folder = '/home/tete/Robotics-branches/escape-dev/robotics-rl-srl/data/random_reaching_on_policy/'" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[32m\n", + "SRL: Using custom_cnn with inverse, autoencoder \n", + "\u001b[0m\n", + "\u001b[33mLoading trained model...srl_zoo/logs/Omnibot_random_simple//19-06-17_15h37_05_custom_cnn_ST_DIM200_inverse_autoencoder/srl_model.pth\u001b[0m\n", + "Loading data for separation \n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 74/74 [00:21<00:00, 3.49it/s]" + ] + } + ], + "source": [ + "pca_srl_data, training, validation = dataSrlLoad(data_folder, srl_model_path, pca_mode=True, normalized=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "num_sample = len(pca_srl_data)\n", + "num_val = int(num_sample * VALIDATION_SIZE)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "def plotDistribution(pca_srl_data, val_num):\n", + " fig, ax = plt.subplots(nrows=1, ncols=3, figsize=[24, 8])\n", + " x_min, x_max = pca_srl_data[:, 0].min(), pca_srl_data[:, 0].max()\n", + " y_min, y_max = pca_srl_data[:, 1].min(), pca_srl_data[:, 1].max()\n", + " ax[0].scatter(pca_srl_data[val_num:, 0], pca_srl_data[val_num:, 1], s=5, c='b', label='Training')\n", + " ax[0].scatter(pca_srl_data[:val_num, 0], pca_srl_data[:val_num, 1], s=5, c='r', label='Validation')\n", + " ax[0].legend()\n", + " ax[0].title.set_text('Sample')\n", + " # plt.show()\n", + " ax[1].hist2d(pca_srl_data[:val_num, 0], pca_srl_data[:val_num, 1],\n", + " bins=100, range=[[x_min, x_max], [y_min, y_max]])\n", + " ax[1].title.set_text('Validation distribution')\n", + " ax[2].hist2d(pca_srl_data[val_num:, 0], pca_srl_data[val_num:, 1],\n", + " bins=100, range=[[x_min, x_max], [y_min, y_max]])\n", + " ax[2].title.set_text('Training distribution')\n", + "\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABXMAAAHkCAYAAAB8ALzrAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4zLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvnQurowAAIABJREFUeJzs3Xl8XGXd///XOZOk2WaSUtqmSQpdEo4oCC0IKqC3C7giuEvZFQUUFaULct8qIAqUXWkBEUHuUtTbDVG89b69v/etiCLYoshPLzJtumRr0tJmJntmzvn9cWamM9NJJmmz9/18PPqAM3PmOtc5gZ7MZz7zvizP8xARERERERERERGRqc2e7AmIiIiIiIiIiIiISH4q5oqIiIiIiIiIiIhMAyrmioiIiIiIiIiIiEwDKuaKiIiIiIiIiIiITAMq5oqIiIiIiIiIiIhMAyrmioiIiIiIiIiIiEwDKuaKHEYcx7necZwNkz0PERGZmRzHWeQ4juc4TkFi+1eO41w8kn0P4ljXOY7znUOZ7wiPM+JzOoixz3Acx6Rtb3Mc5+1jMXZivJccx/mXsRpPRESmNsdxAo7jdDmOc9RY7jsG83q74zjb0raN4zhnjNHYFzuO86vEvxck7tmLxmjsCbtGIqNxUL88i8joOY5zOrAWeA0QB/4BXG2MeW5SJyYiIpLgOM5/An82xnwl6/FzgAeAWmNMbKTjGWPeNUbz+hdggzGmNm3sb4zF2KM10nNyHMcD6o0x4WHG+j3gjMW8HMd5BGgyxvxb2vivGYuxRURkfDiO05W2WQr0479XBLjcGPPYaMYzxsSB8rHed6wZY/Le+xzHqQMajDFWnrG+B3xvLOblOM7TwHeMMY8kxp60ayQyHHXmikwAx3FCwC+AbwFHADXADfg3axERkanie8AFjuNkv3G6EHhsNIVcGd7BdiSLiMjMYYwpT/4BdgBnpz12QCFX945Muh5yuNJ/+CIT4xgAY8zjie1e4DcAjuMsBR4ETgA84NfAZ4wx+xLPbwPW4b+RXgp8H7gOeAQ4HXgW+LAxZm/i6ySNwOXA9YAF3GGMuT3XpBzHeT1wJ/BqYDvweWPM/47ROYuIyPTzM+B+4AzgdwCO48wG3gucmth+D3AT/j2pE3jIGHN9rsEcx/lf/I7a7ziOEwBuBS4BIsAdWfteCqwGaoEO4FZjzAOO45QBvwJmpXUwHQN8CqgzxlyQeP37gJvxPzB9AbjSGPOPxHPbgHuBi4Cjgf8ELjbG9OWYc755pp9THfAQcCIwCPzWGPNRx3F+l9j9r4kO3U8Au4AN+B/sfgH4L8dxHiKr4xh4neM43wQW4P88rjTG9DmOcwlwmTHm9LS5eEA98FbgfMBzHOdq4P8ZY85OnPdlxpj/dhxnVuK8PpJ4+Q+BNcaY/mTnM3AXsAa/K+w6Y8zD2ddHREQmjuM4N+H/Pe/i34s/m4jnuQt4Ff77yv8ArjHGDCaKm4PAYmPMtkTE3iuJMU4H/g6sMMY0jmbfxFzeBdwDzAceBZYDDya7WLPmXYr/jZ73Ai2J/dOfbwIuMMb8b+I96XqgLnE+jxpjVrH/95Dkvf8t+O+ZL8K/z18AfDNtrH9JO8TZjuN8EQgC38G/p7mJ61lrjLkkMXaq+9dxnFuBNwAnO45zb+J1K7OuUSX+7xPvALoT53iLMcZzHOcy/Pfsm4BLE9fyCmPMbw78yYocGnXmikyMl4G44zjfcxznXYk3xkkW/pvPauBYYCF+ITbdB4Ez8d+8no3/pvY6YC7+/8efy9r/Lfg34bOANbny9xzHqQF+if+G/Aj8G9WPHceZe/CnKSIi05kxphe/yHdR2sMfAf5pjPlrYrs78Xwl8B7gSsdxzh3B8J/Ef1O3DDgZ+FDW8+2J50P4b4LuchxnuTGmG3gX0JLWrdSS/kLHcY4BHgeuxr83PgU86ThOUdZ5vBNYDLwWv1h7MPNM9zX8D2dn4xehvwVgjHlT4vkTEvP9QWK7Cv+eezR+MTqX8/HfJC7Fv+//2xD7pRhjvg08BqxNHO/sHLv9K/B6/MLzCcApWWNXARX4xfBPAOuyfl8REZHJ8X5gI/7f0T8AYsDngSOB0/DvbZcP8/oVwJfx7z878O9do9rXcZx5+L8frEoctxH/PjKUG/Hf1y4B3g0MlzX/LeA2Y0wIv6D7o8Tjb4KM7uVkPOEb8SML5+J/SJnLOfjF5pPw7+MXDbFfijFmDfBH/AJsuTHm6hy7rcePw1iC/0HqJ7LGfiPwIjAHv+D+UL7jihwMFXNFJoAxJoL/6aaH34Xb4TjOzx3HmW+MCRtj/ssY02+M6cDvlH1z1hDfMsbsMsY0A78HnjXGbE50FP0U/w1nuhuMMd3GmBeBh4HzckzrAuApY8xTxhjXGPNfwPP4N1sRETl8fQ/4kOM4xYnti0jLojPG/K8x5sXEveNv+EXU7PtWLh8B7jbG7DTGvIL/QWaKMeaXxpgtxhjPGPN/+EXSkS6O8lHgl4n76SBwO1CC/6Yq6ZvGmJbEsZ/EL2qOep5ZBvELs9XGmD5jzNN55ukCX03c83uH2OfetGN/ndz38INxPnCjMaY98fvGDfgdREmDiecHjTFPAV2MUZ6viIgckqeNMU8m7ru9xpjnjDHPGmNixpitwLcZ/j78I2PM84n742MMff8bbt/3Ai8YY55IPHcXsHuYcT4C3GSM2WuM2Y7fzTqUQaDecZw5xpioMebZYfYF2GGMuc8YEx/mXnpL2rG/yRjcSx3HKcQ/r2sT89yKfx3S76VbjDHfNX7W7veAWsdxjjzUY4tkU8yCyARJfNXzEgDHcV6F/3XGuxNfh7wH/w1rEP9Dlr1ZL9+V9u+9ObazQ9l3pv37duD4HFM6Gviw4zjp3TuFwP8bwemIiMgMZYx52nGc3cC5juM8h99584Hk847jnArcAhwHFAGz8L/imU81B96fUhJf3/wqfjeqjd/58uIIp12dPl7iq5Q78btMk9rS/r0n8ZpRzzPLavyupT87jrMXP9rou8Ps35Er2iFL9rGHmudoZVyjHGPvMZmZyD1o0RcRkakg/b6QfC95B37XaSl+XWe4Amj2/W+4v9uH2jfj3piIFWgaZpwFjPxeein+B4zGcZytwPWJDxWHsnOY53LtM1b30nlAgAPvpcP9rgH+NRyu8C0yaurMFZkExph/4mfeHgd8A79j9/jEV0suwI9eOBQL0/79KPycomw7gX83xlSm/SkzxtxyiMcWEZHp71H8jtwLgF8bY9I/RNwI/BxYaIypwM/YHcl9q5UD708AJPJcf4zfUTvfGFOJH5WQHNfLM3YL/oeUyfGsxLGaRzCvEc8zmzGmzRjzSWNMNf5XXNcn8veGku88yHHs5D28G/9NOwCO41SNcuyMa8TQvx+IiMjUkv33+wP4ebZ1ifePX+HQ3z/m04ofJwSk7rM1Q+9OGyO/lxpjzMfwi6V34Ef/FTP0fW3M7qX4EUMjHbsdP1M++156ML9riBwSdeaKTIDEp6fvAX5gjGlyHGch/lc9/oSffdQJdCZybFeNwSG/7DjOJ/FzAS/FfzOebQPwnOM47wD+G78r9/VA2Bgz3KesIiIy8z2Kn6f6WvzFutIFgVeMvyjXKfj5eiNZ3OOHwOccx/kF/pupa9OeS3b4dgCxRJfuWfhvVsH/Rsocx3EqjDGdQ4x9reM4b8NfMOXzQD/wzAjmNZp5ZnAc58PAHxP3zb34bwLdtDkvAcKjPP5nEsfuwc+5Tebt/hV4jeM4JwL/5MB8/eTxhvI48G+JbmsP/83/hlHOTUREJl8Q//1jt+M4x+J/mDjeBcVfAPckvtX5K+Aq/MzaofwQuM5xnOfxs/CvGmpHx3EuBH5ljNntOE4n+++l7fgLey5JRBqMxuq0Y3+O/ZFJLwBXJ96PRznwHj/kvdT4C8z9CPhGYlHSufi/I319lHMTOWTqzBWZGFH8VcCfdRynG7+I+3fgGvyvlCzHvyH/EvjJGBzv//DfPP4WuD3XCprGmJ34wfDX4b953olfSNbfCyIihzljzDb8QmgZfhduuk8DNzqOE8UvCP5whMM+CPwavyi5ibT7nTEmiv9m64f4RdEV6cdNfKPlcWCr4zj7HMfJ+LqkMcbgf3D5LfyvMp4NnG2MGRjh3EY0zxxeh39v70rM9/NpbzivB76XmO9HRnH8jfjF8a3AFvyFSjHGvIy/oMx/Aw1Adj7vQ8CrE8f7WY5xb8LPxv8bfnzFpuTYIiIyrVyDv6BYFL9L9wfD737oEt/Q+Sj++i578Bfp3Iz/wWkuX8Xv5t2GX/x9dJjh3w38I/F7xe3AR40xA4nfDW7Gv8/ucxzn5FFM+Un8wu1m/DVmHkk8/p+J7ReBP3Pg7zh3A+cljndnjnE/DQwkzuv/8HNxhzs3kXFhed5IOtRFZDpwHGcR/sqihVm5dyIiIiIiIiKHzHGcAH50wYeMMb+f7PmIHG4UsyAiIiIiIiIiIkNyHOed+N8w7QW+BAzid7eKyATT16lFRERERERERGQ4p+NHAHUA7wDeb4wZKmZBRMaRYhZEREREREREREREpoHpFLMwC3+RiVYgPslzERGRqScALACeY+jFGCQ33WNFRGQ4uscePN1jRURkKAd1f51OxdzXAQrWFhGRfM7gwFXeZXi6x4qIyEjoHjt6useKiEg+o7q/TqdibivA3r3duO7Mi4aYM6ecPXu6JnsaU5KuzdB0bYamazO8mXh9bNti9uwySNwvZFRaAd70L+fS3KzLJyIimWpqFvC7//0Z6B57MHSPlcNKSUFRxnZvbGCSZiIy9R3s/XU6FXPjAK7rzchiLjBjz2ss6NoMTddmaLo2w5vB10dfYRy9OEBzcyvbtzdN9lxERGTq0j129HSPlcNKaeGsjO2eQSWziIzAqO6v9njNQkRERERERERERETGjoq5IiIiIiIiIiIiItPAdIpZEBERERHJaWHwyIztndHdkzQTERGRw5diFUTGn4q5IiIHyfM8uro66e3twnWnV4Rce7uN67qTPY2DYtsBSkrKKS+vwLKsyZ6OiIiIiIiIyIRRMVdE5CDt3duBZVkcccR8AoGCaVVYLCiwicWmXzHX8zzi8RjR6D727u3giCPmTfaURERERERERCaMMnNFRA7SwEAflZVzKCgonFaF3OnMsiwKCgqprJzDwEDfZE9HREREREREZEKpmCsictA8LEt/jU4G/7p7kz0NERERERERkQmlKoSIiIiIiIiIiIjINKDMXBGRGeKTn7yYwcFBYrFBdu7cweLFSwE45hiH66776ojH+eIXr2LVqutYsKB62P2+8Y0bOPvsczn++BMOad4iIiIiIiIiMjIq5oqIzBAPPvg9AFpbW7jssgt55JGNOfeLx+MUFAz9xYw777x3RMcbTYFYRERERERERA6dirkiIpPA9TyiPYOESsd/8bTnnnuW9evvYcmSOsLhBq644iq6ujr54Q+/TywWw7IsrrrqCyxffjIA73//u7n77vUcffQirrzyExx//Gt58cW/sXt3B2ee+U4+9alPA3DllZ/g4os/wetf/0ZuvPHLlJaWsX17I+3tuzjhhGV86UtfwbIsdu1q46abvsrevXupra0lHo9z2mlncO65HxrX8xYRERERERGZaVTMFRGZYK7nsXbjZsLNndTVVLB6xTLscS7obtkSZtWq63j1q48DoLs7wplnvhuAxsatXHPNZ/nJT36Z87Xt7e2sW/cg3d3dfOQj5/De955DdXXNAftt27Y11dV7ySXnsXnzX1i+/GTuumstp5zyBi688BJaWpq5+OLzOO20M8bpTEXkcLUzunuypyAiIjLjlRbOytjuGeyfpJmIHL5UzBURmWDRnkHCzZ24rke4uZNozyAVZUXjesyjj16UKuQC7Ny5gwceuI/duzsIBArYvbuDffv2UVlZecBr3/rWM7Ftm2AwyFFHHU1zc1POYu6b3vQvFBX551Ff79Dc3MTy5SezadNfWL36XwGorq5h2bKTxuksRURERERERGY2FXNFRCZYqLSQupqKVGduqLRw3I9ZUlKasf1v/3YtX/jCGk477Qzi8Thve9tpDAzk/lQ9WaAFsG2beDyed79AIEA8HhuDmYuIiIiIiIhIkoq5IiITzLIsVq9YNmGZubl0dXWxYEE1AE8++VNisfErvC5btpxf/eoXnH/+xbS1tbJ581944xtPG7fjiYiIiIiIiMxUKuaKiEwC27LGPVphOFdfvZI1a75AMBjkDW84nfLy8nE71he+sIabbvoKv/rVL6muruHVr34NZWXjdzwRERERERkfysgVmXyW53mTPYeRWgQ07tnThetOmzmP2Ny5QTo6opM9jSlJ18ZfMCtXF6euzdAm4tq0tW2nqurocT3GeCkosInF3Ak5Vn9/HwUFhQQCATo62rnssotYt+5BamsXHtK42dffti3mzCkHWAxsO6TBDz+LgMal9aeyfXvTZM9FRESmmKOPrmVLw7Oge+zBWITusSIiksPB3l/VmSsyxbmex9qNm1P5qqtXLMOehK/lixys7du38Y1v3IjnecTjcT75ySsPuZArIiIiIiIicjhSMVdkiov2DBJu7sR1PcLNnUR7Bif16/kio3XMMa/ikUc2TvY0RERERERERKY9e7InICLDC5UWUldTgW1b1NVUECotnOwpiYiIiIiIiIjIJFBnrsgUZ1kWq1csy5mZKyIiIvktDB6Zsb0zunuSZiIiIjK9lBbOytjOtwDaaPcXkdFTZ67IJPBcl1hnJyNdgNC2LCrKilTIFRERERERERE5jKkzV2SCea5L0+230htuoKSuntqVa7Bsfa4iIiIiIiIiIiLDUwVJZILFo1F6ww3guvSGG4hHo5M9JRERERERERERmQZUzBWZYIFQiJK6erBtSurqCYRCkz0lmSGuueZz/OxnP8p4zPM8Pvzhc9i8+S9Dvu6qqz7FH/7wewC+8537+e1vf5Nzv4ceeoB777077zyeeupJduzYntp++un/Y926e0ZyCiIi42JndHfGHxERkemktHBWxp+prGewP+OPiIw9xSyITDDLsqhduYZYpBNQBq6Mnfe85318//sbOPfcD6Ue27z5L9i2xYknLh/RGJdddsUhz+Opp56koqKSo446GoDTT38zp5/+5kMeV0RERERERORwp2KuyCRp+/b9ys09jHmuSzwaJRAKjdnCdmec8WbuuONmtm1rZNGixQD88pc/593vPpu//OU5HnzwPgYG+onH41x66WW85S1nHjDG179+Pa961bF88IMfpauri1tuuZGtW7dwxBFzmD9/PrNnzwHg+ef/nDHeRRd9nLe//R388pc/x5h/cPfdt/Pgg/fxmc98no6Odp555vfcdNNaADZseIRf//opAI499jVcffUqSktLeeihB9ixYzvd3V20tDRTU1PL1752K8XFxWNyfURERERERESmO1WPRCaBcnMPb8lF8Lau+gJNt92C57pjMm5hYSFnnvkunnrq5wD09HTz+9//H+9613s55phXsX79d3j44Y3cffd6vvnNu4hEIsOO9/DDD1JaWsbGjT/mppvWsnnzptRz2eOtW3cPkUiE97znfTjOsVx99UoeeWQjr3vdqRlj/vGPf+DXv36K++//Lo8++gPi8TiPPPKd1PPG/IOvfvXrPPbYj4jFYvzmN78ak2sjIiIiIiIiMhOoM1dkEiRzc5OducrNPbzkKuYXVFSMydjvec/7WLnys1x++VX89rf/xfHHn8C8efPZsWM7N998I01NOwgECohEIuzYsZ3jjjt+yLE2b36eq69eBUBlZSVvfvNbU8/t27c3a7zOvOOB39H7tredRVlZOQDve98HuOee21PPn3LK6wkGgwC8+tXH0dzcdNDXQkSml4XBIzO2lW0rIiLiy86ezc7NHc9s2vHOvZ3IcxGZKVTMFZkEydzcsf6avUwP41nMr68/hjlz5vKnPz3DU0/9nA9/eAUAd9xxC6ed9ia+8Y3bsCyL8877AAMDB/+LUvZ4H/vYoY2XVFS0/5c527aJx+OHPKaIiIiIiIjITKGYBZFJYtk2BRUVKuQehpLF/CW33UXtqmvH/L+B97znfXz3u99m584dnHGGv/BYNBplwYIFWJbFc8/9iaamnXnHWb78dTz11JMAdHbu43e/+3+p57LHa27eP15ZWRnd3V05xzz55FP4n//5L3p6uvE8j1/84mcHRDGIiIiIiIiISG4q5opMIa7n0dk9gOd5kz0VGWfjWcw/88x30ti4lbe//Z0UFhYCcOWVV7Fu3T1ccskK/ud//pu6uvq841xyyWVEoxFWrPgg//qvqznxxGWp57LHW7p0/3jve98HePjhB7nkkhU899yzGWO+4Q2ncdZZ7+Lyyy/loos+CsDF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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plotDistribution(pca_srl_data, num_val)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 0.04232138, -0.29665422],\n", + " [-0.00479653, -0.24115586],\n", + " [-0.03012252, -0.21624807],\n", + " ...,\n", + " [ 0.14181286, -0.289236 ],\n", + " [ 0.14182305, -0.28917688],\n", + " [ 0.1130774 , -0.2586394 ]], dtype=float32)" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pca_srl_data" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "ang = np.pi/4\n", + "rot_mat = np.array([[np.cos(ang), -np.sin(ang)],\n", + " [np.sin(ang), np.cos(ang)]])" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "rotated_data = np.matmul(pca_srl_data, rot_mat)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[-0.17984048, -0.23969195],\n", + " [-0.17391461, -0.16713128],\n", + " [-0.17421031, -0.13161064],\n", + " ...,\n", + " [-0.10424391, -0.30479758],\n", + " [-0.10419489, -0.30476298],\n", + " [-0.10292787, -0.26284347]])" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "rotated_data" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plotDistribution(rotated_data, num_val)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "train_set, val_set = pca_srl_data[num_val:], pca_srl_data[:num_val]" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(15156, 2)" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "train_set.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 121, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 254 ms, sys: 638 ms, total: 892 ms\n", + "Wall time: 23.2 s\n" + ] + } + ], + "source": [ + "from multiprocessing import Pool\n", + "\n", + "def del_val(p_val):\n", + " for p_train in train_set:\n", + " if(np.linalg.norm(p_val-p_train) > 100):\n", + " return 1\n", + " else:\n", + " return 0\n", + "pool = Pool() # Create a multiprocessing Pool\n", + "%time index = pool.map(del_val, val_set) " + ] + }, + { + "cell_type": "code", + "execution_count": 123, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 123, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "index.index(None)" + ] + }, + { + "cell_type": "code", + "execution_count": 114, + "metadata": {}, + "outputs": [], + "source": [ + "from functools import partial\n", + "def _del_val(p_val):\n", + " for p_train in train_set:\n", + " if(1.e-10" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plotDistribution(train_set[index_save], 10000000)" + ] + }, + { + "cell_type": "code", + "execution_count": 122, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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FnOJtoknGEQgFkcunUIgFt9wIbe6YOt+fWb0AvR0ClosjsjgCHztBxqchYiIiIiIiIiIdhsWc4m2SSXftlKYrS7kVhds3a/PXr7oFIAPXXzF2VZcWoKesmMV9NQYiktL8B1gMZeIiIiIiIiI6GHBYi7RNnLHJAC1BdvwwDCEYq9VWMpmkUunANNELp1CYXkZgMc+UHF19brHRERERERERES0qynbPQEikrkLtqVs1tlWiWaAoiAQi8NXVQj2BtugxfsBRYHW3w9vkAueERERERERERE9TNiZS7TDuLN0q7Nxm0UzCCEQGRypu42IiGivabZg2noLnrX4AtL4o88mpfFjB6NNtxMRERER3S8s5hLtMEIIhI4Owpifq1nkDKgfzbCRbUREREREREREtLuxmEu0w1imidkrl5zFzLR4PyKDI05uLhERERERERER7U2sDhHtMKVsFno65Yz18TSK2eVtnBEREREREREREe0E7Mwl2mE8wSC0WNzpzIVpYuH6NXbnEhERNXFonxwztFrQna/d+bnusTsz98adW9J4n0+Vxunl+S3Pk4iIiIjobrAyRLTDVBYyi5w6C5QXMdPH0yhls9s8MyIiIiIiIiIi2k4s5hLtQEJRoEW6EIj3A4qCQCxedzE0IiIiIiIiIiLaOxizQLRDCSEQHhhGKZuFJxiEKHfpEhERERERERHR3sRiLtEOJhQF3ra29XckIiLa46ozcjfr5p0ladwsfxcAfro9Ko3/6ubHW742EREREdFmMGaBiIiIiIiIiIiIaBdgMZeIiIiIiIiIiIhoF2Axl4iIiIiIiIiIiGgXYDGXiIiIiIiIiIiIaBfgAmhERERE9NC5UzC2fKx7QbR9PlUac8EzIiIiItou7MwlIiIiIiIiIiIi2gVYzCUiIiIiIiIiIiLaBVjMJSIiIiIiIiIiItoFmJlLRERERLtes4xcd+ate9/1thMRERER7RTszCUiIiIiIiIiIiLaBVjMJSIiIiIiIiIiItoFWMwlIiIiIiIiIiIi2gWYmUtERERED7XD+w5I48mlRWm8XkYuM3SJiIiIaKdgZy4RERERERERERHRLsBiLhEREREREREREdEusJtiFjwAoChiu+dxXzys7+te4f1pjPemOd6fxh62e1P1fjzbOY9dygMAoVDHds+D6L4ItR6Sxmb7bvonMNH2q3o+8Bm7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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plotDistribution(train_set, 10000000)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From d45a369bf726fe99bcaaa29b8310f16a2ad53ff0 Mon Sep 17 00:00:00 2001 From: sun-te Date: Fri, 28 Jun 2019 17:57:15 +0200 Subject: [PATCH 130/141] resampling of data --- delete_val.ipynb | 463 ++++++++++++++++++++++----------- environments/data_separator.py | 125 +++++---- 2 files changed, 389 insertions(+), 199 deletions(-) diff --git a/delete_val.ipynb b/delete_val.ipynb index dda677110..a9364978a 100644 --- a/delete_val.ipynb +++ b/delete_val.ipynb @@ -2,22 +2,27 @@ "cells": [ { "cell_type": "code", - "execution_count": 18, + "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", - "from environments.data_separator import dataSrlLoad, plotDistribution\n", + "from environments.data_separator import dataSrlLoad, plotDistribution, PCA\n", "import torch as th\n", "import matplotlib.pyplot as plt\n", "import seaborn as sns\n", "from tqdm import tqdm\n", - "from multiprocessing import Pool" + "from multiprocessing import Pool\n", + "import os\n", + "import multiprocessing\n", + "from state_representation.models import loadSRLModel, getSRLDim\n", + "from srl_zoo.utils import loadData\n", + "from srl_zoo.preprocessing.data_loader import SupervisedDataLoader, DataLoader" ] }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 14, "metadata": {}, "outputs": [], "source": [ @@ -29,17 +34,83 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "srl_model_path = 'srl_zoo/logs/Omnibot_random_escape/19-06-17_17h36_08_custom_cnn_ST_DIM200_inverse_autoencoder/srl_model.pth'\n", + "data_folder = '/home/tete/Robotics-branches/escape-dev/robotics-rl-srl/data/escape_on_policy/'" + ] + }, + { + "cell_type": "code", + "execution_count": 23, "metadata": {}, "outputs": [], "source": [ - "srl_model_path = 'srl_zoo/logs/Omnibot_random_simple//19-06-17_15h37_05_custom_cnn_ST_DIM200_inverse_autoencoder/srl_model.pth'\n", - "data_folder = '/home/tete/Robotics-branches/escape-dev/robotics-rl-srl/data/random_reaching_on_policy/'" + "def dataSrlLoad(data_folder, srl_model_path, state_dim=2, pca_mode=True, normalized=True):\n", + " \"\"\"\n", + "\n", + " :param data_folder: (str) the path to the dataset we want to sample\n", + " :param srl_model_path: (str)\n", + " :return: the dataset after the srl evaluation and a pca preprocessd,\n", + " it self, a random sampled training set, validation set\n", + " \"\"\"\n", + " state_dim = getSRLDim(srl_model_path)\n", + " srl_model = loadSRLModel(srl_model_path, th.cuda.is_available(), state_dim, env_object=None)\n", + " # load images and other data\n", + " training_data, ground_truth, true_states,_ = loadData(data_folder, absolute_path=True)\n", + " images_path = ground_truth['images_path']\n", + " import ipdb\n", + " ipdb.set_trace()\n", + " ground_truth_states_dim = true_states.shape[1]\n", + "\n", + " # we change the path to the local path at the toolbox level\n", + " images_path_copy = [\"srl_zoo/data/\" + images_path[k] for k in range(images_path.shape[0])]\n", + " images_path = np.array(images_path_copy)\n", + "\n", + " num_samples = images_path.shape[0] # number of samples\n", + "\n", + " # indices for all time steps where the episode continues\n", + " #indices = np.array([i for i in range(num_samples-1) if not episode_starts[i + 1]], dtype='int64')\n", + " indices = np.arange(num_samples)\n", + "\n", + " minibatchlist = [np.array(sorted(indices[start_idx:start_idx + BATCH_SIZE]))\n", + " for start_idx in range(0, len(indices) - BATCH_SIZE + 1, BATCH_SIZE)]\n", + "\n", + " data_loader = DataLoader(minibatchlist, images_path, n_workers=N_WORKERS, multi_view=False,\n", + " use_triplets=False, is_training=True, absolute_path=True)\n", + "\n", + " srl_data = []\n", + " #we only use the srl model to deduct the states\n", + " srl_model.model = srl_model.model.eval()\n", + " pbar = tqdm(total=len(data_loader))\n", + " for minibatch_num, (minibatch_idx, obs, _, _, _) in enumerate(data_loader):\n", + " obs = obs.to(DEVICE)\n", + " state = srl_model.model.getStates(obs).to('cpu').detach().numpy()\n", + " srl_data.append(state)\n", + " pbar.update(1)\n", + "\n", + " # concatenate into one numpy array\n", + " srl_data = np.concatenate(srl_data,axis=0)\n", + " # PCA for the v\n", + " if pca_mode:\n", + " pca_srl_data = PCA(srl_data, dim=ground_truth_states_dim)\n", + " else:\n", + " pca_srl_data = srl_data\n", + " if normalized: # Normilized into -0.5 to +0.5\n", + " for k in range(pca_srl_data.shape[1]):\n", + " pca_srl_data[:, k] = (pca_srl_data[:, k] - np.min(pca_srl_data[:, k])) / (\n", + " np.max(pca_srl_data[:, k]) - np.min(pca_srl_data[:, k])) - 0.5\n", + "\n", + " training_indices = np.concatenate(minibatchlist)\n", + "\n", + " return pca_srl_data, training_indices" ] }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 17, "metadata": {}, "outputs": [ { @@ -49,25 +120,36 @@ "\u001b[32m\n", "SRL: Using custom_cnn with inverse, autoencoder \n", "\u001b[0m\n", - "\u001b[33mLoading trained model...srl_zoo/logs/Omnibot_random_simple//19-06-17_15h37_05_custom_cnn_ST_DIM200_inverse_autoencoder/srl_model.pth\u001b[0m\n", - "Loading data for separation \n" + "\u001b[33mLoading trained model...srl_zoo/logs/Omnibot_random_escape/19-06-17_17h36_08_custom_cnn_ST_DIM200_inverse_autoencoder/srl_model.pth\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "100%|██████████| 74/74 [00:21<00:00, 3.49it/s]" + "\n", + " 0%| | 0/11 [00:00" ] @@ -124,304 +206,382 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "array([[ 0.04232138, -0.29665422],\n", - " [-0.00479653, -0.24115586],\n", - " [-0.03012252, -0.21624807],\n", - " ...,\n", - " [ 0.14181286, -0.289236 ],\n", - " [ 0.14182305, -0.28917688],\n", - " [ 0.1130774 , -0.2586394 ]], dtype=float32)" + "(2816, 2)" ] }, - "execution_count": 8, + "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "pca_srl_data" + "pca_srl_data.shape" ] }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": {}, "outputs": [], - "source": [ - "ang = np.pi/4\n", - "rot_mat = np.array([[np.cos(ang), -np.sin(ang)],\n", - " [np.sin(ang), np.cos(ang)]])" - ] + "source": [] }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 56, "metadata": {}, "outputs": [], "source": [ - "rotated_data = np.matmul(pca_srl_data, rot_mat)" + "def deleteData(data_folder, del_index=[], srl_model_path=None):\n", + " state_dim = getSRLDim(srl_model_path)\n", + " srl_model = loadSRLModel(srl_model_path, th.cuda.is_available(), state_dim, env_object=None)\n", + "\n", + " # load images and other data\n", + " print('Loading data for separation ')\n", + " training_data, ground_truth, true_states, _ = loadData(data_folder, absolute_path=True)\n", + " images_path = ground_truth['images_path']\n", + " ground_truth_states_dim = true_states.shape[1]\n", + " # we change the path to the local path at the toolbox level\n", + " images_path_copy = [\"srl_zoo/data/\" + images_path[k] for k in range(images_path.shape[0])]\n", + " images_path = np.array(images_path_copy)\n", + " \n", + " ground_truth_load = np.load(os.path.join(data_folder, \"/ground_truth.npz\"))\n", + " preprocessed_load = np.load(os.path.join(data_folder, \"/preprocessed_data.npz\"))\n", + " \n", + " " ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 36, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "array([[-0.17984048, -0.23969195],\n", - " [-0.17391461, -0.16713128],\n", - " [-0.17421031, -0.13161064],\n", - " ...,\n", - " [-0.10424391, -0.30479758],\n", - " [-0.10419489, -0.30476298],\n", - " [-0.10292787, -0.26284347]])" + "((19456,), (19456, 2))" ] }, - "execution_count": 11, + "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "rotated_data" + "data_index.shape, pca_srl_data.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": {}, + "outputs": [], + "source": [ + "from functools import partial\n", + "def _del_val(p_val,train_set, threshold):\n", + " for p_train in train_set:\n", + " if(1.e-10" + "15" ] }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" + "execution_count": 76, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ - "plotDistribution(rotated_data, num_val)" + "multiprocessing.cpu_count()-1" ] }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ - "train_set, val_set = pca_srl_data[num_val:], pca_srl_data[:num_val]" + "threshold = 0.003\n", + "test_set = pca_srl_data\n", + "pool = Pool(multiprocessing.cpu_count()-1)\n", + "%time index_del = pool.map(partial(_del_val, train_set=test_set, threshold=threshold), test_set)\n", + "index_save = [i for i in range(len(index_del)) if not index_del[i]]" ] }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 69, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "(15156, 2)" + "4024" ] }, - "execution_count": 14, + "execution_count": 69, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "train_set.shape" + "index_save.__len__()" ] }, { "cell_type": "code", - "execution_count": 121, + "execution_count": 70, "metadata": {}, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "CPU times: user 254 ms, sys: 638 ms, total: 892 ms\n", - "Wall time: 23.2 s\n" - ] + "data": { + "text/plain": [ + "4024" + ] + }, + "execution_count": 70, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ - "from multiprocessing import Pool\n", - "\n", - "def del_val(p_val):\n", - " for p_train in train_set:\n", - " if(np.linalg.norm(p_val-p_train) > 100):\n", - " return 1\n", - " else:\n", - " return 0\n", - "pool = Pool() # Create a multiprocessing Pool\n", - "%time index = pool.map(del_val, val_set) " + "test_set[index_save].__len__()" ] }, { "cell_type": "code", - "execution_count": 123, + "execution_count": 71, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "0" + "((19456, 2), 19456)" ] }, - "execution_count": 123, + "execution_count": 71, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "index.index(None)" + "test_set.shape, len(index_del)" ] }, { "cell_type": "code", - "execution_count": 114, + "execution_count": 72, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "image/png": "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Hbq5PN3mBB4ebiZTMOO2WPbuskQLdlUV//u2nfT/9rdY8TheKkU80cLqjR+kssYvHttliqsVNTXEEy2h9SaC9ZaLULCrqrDjcT83OB7Hrqqa9r0WEREREREREZHiVMwVKWOiGbKWbbOkro61rdsZ7e8DrKAjN2+/bIduLuO2s3VTfsZtqMs1OvQMzwv+PNp3mv7/838A8IaHuWjnLmINayeVXWtZlr/eUGauZVnj4h1WX38jlXV1eed3Bwdx02kA3HQad3CwbPFYREQWr8lm3JbLgZ3u9r0rx37I+IPItulm0l5ZcWHRcwFsYTDv9WQzd5WRKyIiIiLFqJgrUka0oFquWOoXdc8vu49l26SSST9CoaM96K6NdrnmdQBbVqgbOH8dFdVTG0Jm2TZLzs9fb168Q9shOrduIp5oAcY6g+s3b53woDQREREREREREZk+FXNFJiAaqTBRpaIK8iIUGptIdXUCE+9yraytpfr5FzPwm98ST7Tkra9cREI54bXhuuB5frauZQVxE+7g4KSK3CIiIiIiIiIiMj0q5orMkmKD03LCHb92dTW9oX3tqipG+/qKFklzxdoX3HkHT3Uey9uv3Hknsu7MwAD1m7cy2t/Hsf2fJ93V6XfmWpBKJoNOXCuvU1hERERERERERGaTirkis6TY4LSwcMdvUNitqio4DC0nXKx9+uLnceFHtuQVfCdy3kI81/WLtw8+QKo9SbyxCc+2SR/uIt603l+HZakTV0RERERERERknqiYKzJLJjo4LSdX2B3t6ytZjA0Xawd+a3huZLtdVRUMVJtolm24QIzrApDqaA+2pzo7cAcHqaytVSeuiMg5YroDy6Y7ZCz6/nKix7/sxBMTPvYdq1+d9zo6sCzqB5mn8l+XWVu5a/npypfmvY6ufbLD5UrRcDURERGRhU3FXJFZMtnBaeAXVT3PI55I5MUZhIWLxNXPc/K2e65L7749pLo6iTetp37z1gmdNzMwwHDbIfC8gtujQ9lERERERERERGTuqZgrMoss26aiuppMf3/Jgq7nuoz29XH0of2kk0lizQma9uyjsrYOy7LGDTTLFYlXNdfz9NODwXHCXbuprk4ygwPYtXVl12lXVWHF4nipYf8LS5fCyEiwfaJD2UREREREREREZPZMfCqSiExaLr6go/UWeu69By8bYVBon87WW0i3tYHnkU62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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], "source": [ - "from functools import partial\n", - "def _del_val(p_val):\n", - " for p_train in train_set:\n", - " if(1.e-10" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" } ], "source": [ - "threshold = 0.001\n", - "train_set = train_set\n", - "pool = Pool()\n", - "%time index_del = pool.map(_del_val, train_set)" + "plotDistribution(test_set, 10000000)" ] }, { "cell_type": "code", - "execution_count": 116, + "execution_count": 78, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(19456, 2)" + ] + }, + "execution_count": 78, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pca_srl_data.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 87, "metadata": {}, "outputs": [], "source": [ - "index_save = [i for i in range(len(index_del)) if not index_del[i]]" + "k = np.zeros(12).astype(bool)" ] }, { "cell_type": "code", - "execution_count": 120, + "execution_count": 88, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "12382" + "array([False, False, False, False, False, False, False, False, False,\n", + " False, False, False])" ] }, - "execution_count": 120, + "execution_count": 88, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "index_save.__len__()\n" + "k" ] }, { "cell_type": "code", - "execution_count": 117, + "execution_count": 82, "metadata": {}, "outputs": [ { - "data": { - "text/plain": [ - "12382" - ] - }, - "execution_count": 117, - "metadata": {}, - "output_type": "execute_result" + "name": "stdout", + "output_type": "stream", + "text": [ + "False\n" + ] } ], "source": [ - "train_set[index_save].__len__()" + "a =0.0\n", + "print(bool(a))\n", + "if a:\n", + " print(1)" + ] + }, + { + "cell_type": "code", + "execution_count": 147, + "metadata": {}, + "outputs": [], + "source": [ + "def index_save(data_set, threshold):\n", + " pbar = tqdm(total = len(data_set))\n", + " deleted = np.zeros(len(data_set)).astype(bool)\n", + " for t, test_point in enumerate(data_set):\n", + " pbar.update(1)\n", + " for k, data_point in enumerate(data_set):\n", + " if(not deleted[k] and 1.e-5" ] @@ -433,44 +593,47 @@ } ], "source": [ - "plotDistribution(train_set[index_save], 10000000)" + "plotDistribution(data_set[left_index], 10000000)" ] }, { "cell_type": "code", - "execution_count": 122, + "execution_count": 141, "metadata": {}, "outputs": [ { "data": { - "image/png": "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FnOJtoknGEQgFkcunUIgFt9wIbe6YOt+fWb0AvR0ClosjsjgCHztBxqchYiIiIiIiIiIdhsWc4m2SSXftlKYrS7kVhds3a/PXr7oFIAPXXzF2VZcWoKesmMV9NQYiktL8B1gMZeIiIiIiIiI6GHBYi7RNnLHJAC1BdvwwDCEYq9VWMpmkUunANNELp1CYXkZgMc+UHF19brHRERERERERES0qynbPQEikrkLtqVs1tlWiWaAoiAQi8NXVQj2BtugxfsBRYHW3w9vkAueERERERERERE9TNiZS7TDuLN0q7Nxm0UzCCEQGRypu42IiGivabZg2noLnrX4AtL4o88mpfFjB6NNtxMRERER3S8s5hLtMEIIhI4Owpifq1nkDKgfzbCRbUREREREREREtLuxmEu0w1imidkrl5zFzLR4PyKDI05uLhERERERERER7U2sDhHtMKVsFno65Yz18TSK2eVtnBEREREREREREe0E7Mwl2mE8wSC0WNzpzIVpYuH6NXbnEhERNXFonxwztFrQna/d+bnusTsz98adW9J4n0+Vxunl+S3Pk4iIiIjobrAyRLTDVBYyi5w6C5QXMdPH0yhls9s8MyIiIiIiIiIi2k4s5hLtQEJRoEW6EIj3A4qCQCxedzE0IiIiIiIiIiLaOxizQLRDCSEQHhhGKZuFJxiEKHfpEhERERERERHR3sRiLtEOJhQF3ra29XckIiLa46ozcjfr5p0ladwsfxcAfro9Ko3/6ubHW742EREREdFmMGaBiIiIiIiIiIiIaBdgMZeIiIiIiIiIiIhoF2Axl4iIiIiIiIiIiGgXYDGXiIiIiIiIiIiIaBfgAmhERERE9NC5UzC2fKx7QbR9PlUac8EzIiIiItou7MwlIiIiIiIiIiIi2gVYzCUiIiIiIiIiIiLaBVjMJSIiIiIiIiIiItoFmJlLRERERLtes4xcd+ate9/1thMRERER7RTszCUiIiIiIiIiIiLaBVjMJSIiIiIiIiIiItoFWMwlIiIiIiIiIiIi2gWYmUtERERED7XD+w5I48mlRWm8XkYuM3SJiIiIaKdgZy4RERERERERERHRLsBiLhEREREREREREdEusJtiFjwAoChiu+dxXzys7+te4f1pjPemOd6fxh62e1P1fjzbOY9dygMAoVDHds+D6L4ItR6Sxmb7bvonMNH2q3o+8Bm7eXzGEhFRXVt9vgrLsu79bO6PLwL4T9s9CSIi2vF+AcD3tnsSuwyfsUREtBF8xm4en7FERLSeTT1fd1MxVwXw8wAWAJS2eS5ERLTzeAB0APjPALha0ebwGUtERM3wGbt1fMYSEVEjW3q+7qZiLhEREREREREREdGexQXQiIiIiIiIiIiIiHYBFnOJiIiIiIiIiIiIdgEWc4mIiIiIiIiIiIh2ARZziYiIiIiIiIiIiHYBFnOJiIiIiIiIiIiIdgEWc4mIiIiIiIiIiIh2ARZziYiIiIiIiIiIiHYBFnOJiIiIiIiIiIiIdgHvdk9gL0okEvsA/D6AnwVQBDCQTCa/22R/DcAPAOSSyeTPPZhZbo+N3ptEIvHPAZwCoAIQAH4vmUxeeZBzfVASiUQ/gG8COAjgMwBfSSaTKdc+HgBfB/A/ArAAXEgmk9940HPdDhu8Py8B+A0AJQAFACeSyeSfPei5PmgbuTdV+yYA/BDAtWQyOfDgZklUi8/JreNzdHP4jN06Pn+3hs9m2m58xm4dn7Gbw2fs1vD5unV76RnLztztMQBgOZlMxgD8CoBvJBKJlib7vwrgrx/IzLbfRu/NIoBfSSaTPwngvwXwVCKR+IUHOM8H6TqAd5LJZD+AdwC8V2efLwGIAYgD+McAziQSiZ4HNsPttZH78zcAfj6ZTD4G4HcA/HEikQg8wDlul43cm8o/ot4D8G8f4NyImuFzcuv4HN0cPmO3js/freGzmbYbn7Fbx2fs5vAZuzV8vm7dnnnGspi7PX4d5T9U5d8SfB/AL9XbsfyXfhzAhw9sdttrQ/cmmUz+v8lkcr789RKAHwHofoDzfCASicSjAL4A4Dvll74D4AuJROKQa9dfB/BBMpk0k8nkTdh/Kf3ag5vp9tjo/Ukmk3+WTCbvlIcfwf4N+cEHNtFtsIk/OwAwAuC7AMYe0PSI1sPn5NbxObpBfMZuHZ+/W8NnM+0QfMZuHZ+xG8Rn7Nbw+bp1e+0Zy2Lu9ugCMF01zgCIuHdKJBL7AbwB4KkHNK+dYEP3ploikfg8gP8GwP9zH+e1XSIA5pLJZAkAyv+dR+092fR9e0hs9P5U+wqA8WQyOfsA5redNnRvEonETwH4ZwCuPvAZEjXG5+TW8Tm6cXzGbh2fv1vDZzPtBHzGbh2fsRvHZ+zW8Pm6dXvqGcvM3PsgkUj8Ley/lOo5vIlTjcJuEZ9LJBLxu5/Z9ruH96Zyvg4A/w7A05XffhI1kkgk/jsALwP4H7Z7LjtBIpHwAXgfwL9MJpMlOzaI6P7jc3Lr+Byl3YjP343js5nuFp+xW8dnLO02fL5uzsP0jGUx9z5IJpNfaLY9kUhkYH/M4mb5pS4Af1Fn1y8C+OVEInEKgAbgQCKR+Kici7Ir3cN7U2mj/78BXEomk39yL+e5g8wACCUSCU/5LxsPgM7y69Uq9+0/l8fu33A+rDZ6f5BIJP4xgG8B+OfJZDL5gOe5HTZybzoA9AH4P8sPsnYAIpFIBJPJ5OMPfMa0Z/A5uXV8jt5TfMZuHZ+/W8NnM913fMZuHZ+x9xSfsVvD5+vW7alnLGMWtsefAHgCAMq/5fx5AP+Xe6dkMvlYMpnsSSaTPbBXKvwvD/PDs2xD9yaRSBwE8B8AvJ1MJv/1A53hA5RMJj8B8Hf/f3t3qNtkFMZx+M8cDrFr2Ktw4z4QM5MIYGZ+unYGRYJGkU1zGQN7NgLJbmEX0Il+oo6vJ6FnH3uepKJNxZuTpr/kTXOa5HR66TTJj+k+oW1XSd5X1cF0J8zbJNf7m3SMuedTVW+SfEty0lq72e+UY8w5m9bafWvtcOt75lM2d1YtKmT8l3Syn47OpLH99LePNvNEaGw/jZ1JY/voa7/n1ljL3DEuk7yqql/ZXLr8obX2kCRVtaqqs6HTjTX3bC6SHCX5WFU/p8e7MSP/c2dJzqvqNsn59DxV9b2qjqf3fE3yO8ldNv82u2qt/Rkx7ABzzudzkpdJvmx9Xl6PGXev5pwNPEU62U9Hd6Ox/fS3jzYzmsb209jdaGwffe33bBr7Yr1ej54BAAAAAIC/8MtcAAAAAIAFsMwFAAAAAFgAy1wAAAAAgAWwzAUAAAAAWADLXAAAAACABbDMBQAAAABYAMtcAAAAAIAFeAT9H0mxZbBSVgAAAABJRU5ErkJggg==\n", "text/plain": [ - "
" + "array([False, False, False, ..., False, False, False])" ] }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" + "execution_count": 141, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ - "plotDistribution(train_set, 10000000)" + "delete\n" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 142, "metadata": {}, "outputs": [], - "source": [] + "source": [ + "data_set = data_set.copy()" + ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], - "source": [] + "source": [ + "for i, data in enumerate(data_set):\n", + " np.delete" + ] } ], "metadata": { diff --git a/environments/data_separator.py b/environments/data_separator.py index c2c09ff20..b89b938ee 100644 --- a/environments/data_separator.py +++ b/environments/data_separator.py @@ -10,12 +10,11 @@ import numpy as np import torch as th from tqdm import tqdm -from multiprocessing import Pool from functools import partial +from multiprocessing import Pool from ipdb import set_trace as tt - from state_representation.models import loadSRLModel, getSRLDim from srl_zoo.utils import loadData from srl_zoo.preprocessing.data_loader import SupervisedDataLoader, DataLoader @@ -24,11 +23,12 @@ #os.chdir('/home/tete/Robotics-branches/robotics-rl-srl-two/logs/teacher_policies_for_evaluation/sc/OmnirobotEnv-v0/srl_combination/ppo2/19-06-19_01h10_00') -BATCH_SIZE = 256 +BATCH_SIZE = 64 N_WORKERS = 8 DEVICE = th.device("cuda" if th.cuda.is_available() else "cpu") VALIDATION_SIZE = 0.2 # 20% of training data for validation + def PCA(data, dim=2): # preprocess the data X = th.from_numpy(data).to(DEVICE) @@ -40,7 +40,7 @@ def PCA(data, dim=2): C = th.mm(X,U[:,:dim]).to('cpu').numpy() return C -def dataSrlLoad(data_folder, srl_model_path=None, pca_mode=True, normalized=True, threshold=0.01): +def dataSrlLoad(data, srl_model=None, state_dim=2, pca_mode=True, normalized=True): """ :param data_folder: (str) the path to the dataset we want to sample @@ -49,28 +49,20 @@ def dataSrlLoad(data_folder, srl_model_path=None, pca_mode=True, normalized=True it self, a random sampled training set, validation set """ - state_dim = getSRLDim(srl_model_path) - srl_model = loadSRLModel(srl_model_path, th.cuda.is_available(), state_dim, env_object=None) - - #load images and other data - print('Loading data for separation ') - training_data, ground_truth, true_states, _ = loadData(data_folder, absolute_path=True) - rewards, episode_starts = training_data['rewards'], training_data['episode_starts'] + # load images and other data + training_data, ground_truth, true_states = data images_path = ground_truth['images_path'] - actions = training_data['actions'] - actions_proba = training_data['actions_proba'] - ground_turht_states_dim = true_states.shape[1] - - + ground_truth_states_dim = true_states.shape[1] # we change the path to the local path at the toolbox level images_path_copy = ["srl_zoo/data/" + images_path[k] for k in range(images_path.shape[0])] images_path = np.array(images_path_copy) - num_samples = images_path.shape[0] # number of samples + num_samples = images_path.shape[0]-1 # number of samples # indices for all time steps where the episode continues - indices = np.array([i for i in range(num_samples-1) if not episode_starts[i + 1]], dtype='int64') + #indices = np.array([i for i in range(num_samples-1) if not episode_starts[i + 1]], dtype='int64') + indices = np.arange(num_samples) minibatchlist = [np.array(sorted(indices[start_idx:start_idx + BATCH_SIZE])) for start_idx in range(0, len(indices) - BATCH_SIZE + 1, BATCH_SIZE)] @@ -92,7 +84,7 @@ def dataSrlLoad(data_folder, srl_model_path=None, pca_mode=True, normalized=True srl_data = np.concatenate(srl_data,axis=0) # PCA for the v if pca_mode: - pca_srl_data = PCA(srl_data, dim=ground_turht_states_dim) + pca_srl_data = PCA(srl_data, dim=ground_truth_states_dim) else: pca_srl_data = srl_data if normalized: # Normilized into -0.5 to +0.5 @@ -102,14 +94,7 @@ def dataSrlLoad(data_folder, srl_model_path=None, pca_mode=True, normalized=True training_indices = np.concatenate(minibatchlist) - val_num = int(len(training_indices) * VALIDATION_SIZE) - - #return the index that we dont need to save anymore - index_del = dataSelection(0.01,pca_srl_data) - - index_save = [i for i in range(len(index_del)) if not index_del[i]] - - return + return pca_srl_data, training_indices def plotDistribution(pca_srl_data, val_num): fig, ax = plt.subplots(nrows=1, ncols=3, figsize=[24, 8]) @@ -137,32 +122,76 @@ def _del_val(p_val, train_set, threshold): :param threshold: (float) :return: """ + import numpy as np for p_train in train_set: - if (np.linalg.norm(p_val - p_train) < threshold): + if(1.e-10 Date: Fri, 28 Jun 2019 18:47:49 +0200 Subject: [PATCH 131/141] float reward data merger --- environments/dataset_merger.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/environments/dataset_merger.py b/environments/dataset_merger.py index 7d8ceaa1c..add6ec9a7 100644 --- a/environments/dataset_merger.py +++ b/environments/dataset_merger.py @@ -130,7 +130,7 @@ def main(): to_class = None if arr == "episode_starts": to_class = bool - elif arr == "actions_proba": + elif arr == "actions_proba" or arr == "rewards": to_class = float else: to_class = int From 6c29da33406ff84b4ab5b5b28f6bdeaf1118123c Mon Sep 17 00:00:00 2001 From: sun-te Date: Fri, 28 Jun 2019 18:50:43 +0200 Subject: [PATCH 132/141] separator --- delete_val.ipynb | 86 +++++++++++-------- environments/data_separator.py | 7 +- environments/dataset_merger.py | 33 ++++--- .../supervised_rl/policy_distillation.py | 2 + 4 files changed, 69 insertions(+), 59 deletions(-) diff --git a/delete_val.ipynb b/delete_val.ipynb index a9364978a..63c8be5c8 100644 --- a/delete_val.ipynb +++ b/delete_val.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 13, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -22,7 +22,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -34,17 +34,17 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ - "srl_model_path = 'srl_zoo/logs/Omnibot_random_escape/19-06-17_17h36_08_custom_cnn_ST_DIM200_inverse_autoencoder/srl_model.pth'\n", - "data_folder = '/home/tete/Robotics-branches/escape-dev/robotics-rl-srl/data/escape_on_policy/'" + "srl_model_path = 'srl_zoo/logs/Omnibot_random_circular/19-06-17_16h36_37_custom_cnn_ST_DIM200_inverse_autoencoder/srl_model.pth'\n", + "data_folder = '/home/tete/Robotics-branches/escape-dev/robotics-rl-srl/srl_zoo/data/circular_on_policy_short_eps//'" ] }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -61,8 +61,6 @@ " # load images and other data\n", " training_data, ground_truth, true_states,_ = loadData(data_folder, absolute_path=True)\n", " images_path = ground_truth['images_path']\n", - " import ipdb\n", - " ipdb.set_trace()\n", " ground_truth_states_dim = true_states.shape[1]\n", "\n", " # we change the path to the local path at the toolbox level\n", @@ -110,7 +108,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -120,26 +118,38 @@ "\u001b[32m\n", "SRL: Using custom_cnn with inverse, autoencoder \n", "\u001b[0m\n", - "\u001b[33mLoading trained model...srl_zoo/logs/Omnibot_random_escape/19-06-17_17h36_08_custom_cnn_ST_DIM200_inverse_autoencoder/srl_model.pth\u001b[0m\n" + "\u001b[33mLoading trained model...srl_zoo/logs/Omnibot_random_circular/19-06-17_16h36_37_custom_cnn_ST_DIM200_inverse_autoencoder/srl_model.pth\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\n", - " 0%| | 0/11 [00:00\n", + " for func, args, kwargs in self.items]\n", + " File \"/home/tete/Robotics-branches/escape-dev/robotics-rl-srl/srl_zoo/preprocessing/data_loader.py\", line 255, in _makeBatchElement\n", + " raise ValueError(\"tried to load {}.jpg, but it was not found\".format(image_path))\n", + "ValueError: tried to load srl_zoo/data/circular_on_policy_short_eps/record_148/frame000017.jpg, but it was not found\n" ] } ], @@ -149,9 +159,21 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 1, "metadata": {}, - "outputs": [], + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'pca_srl_data' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mnum_sample\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpca_srl_data\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0mnum_val\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnum_sample\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0mVALIDATION_SIZE\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mNameError\u001b[0m: name 'pca_srl_data' is not defined" + ] + } + ], "source": [ "num_sample = len(pca_srl_data)\n", "num_val = int(num_sample * VALIDATION_SIZE)" @@ -159,7 +181,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -641,18 +663,6 @@ "display_name": "Python 3", "language": "python", "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.5.4" } }, "nbformat": 4, diff --git a/environments/data_separator.py b/environments/data_separator.py index b89b938ee..57b24c70c 100644 --- a/environments/data_separator.py +++ b/environments/data_separator.py @@ -187,11 +187,12 @@ def dataSelection(data_folder, srl_model_path=None, threshold=0.003): np.savez(data_folder+ "/preprocessed_data.npz", **preprocessed_data) np.savez(data_folder+ "/ground_truth.npz", **ground_truth_data) - tt() for idx, image in enumerate(images_path): if(not idx in left_index): - os.remove(image+'.ipg') - + try: + os.remove(image+'.jpg') + except: + print("No file named: {}", image+'.jpg') def loadKwargs(log_dir): with open(os.path.join(log_dir, 'args.json')) as data: rl_kwargs = json.load(data) diff --git a/environments/dataset_merger.py b/environments/dataset_merger.py index 21b874d5a..43c3d5418 100644 --- a/environments/dataset_merger.py +++ b/environments/dataset_merger.py @@ -126,7 +126,7 @@ def main(): for arr in gt_load.files: if arr == "images_path": - # here, we want to rename just the folder containing the records, hence the black magic + #here, we want to rename just the folder containing the records, hence the black magic for i in tqdm(range(ts_counter[idx_-1]),#range(len(gt_load["images_path"])), desc="Update of paths (Folder " + str(1+idx_) + ")"): @@ -149,28 +149,25 @@ def main(): if idx_ > 1: num_episode_dataset = num_episode_dataset_2 - # HERE check before overwritting that the target is random !+ - if gt_load[arr].shape[0] < num_episode_dataset: - gt_arr = np.repeat(gt_load[arr], num_episode_dataset, axis=0) + if idx_ > 1: # This is the first dataset - if (len(gt_arr) == num_eps_total_2): + if (len(gt_arr) <= num_eps_total_2): # This is a episode non-change variable + ground_truth[arr] = np.concatenate((ground_truth[arr],gt_arr[:num_episode_dataset_2,:2]), axis=0) + elif (len(gt_arr) <= num_ts_total_2): # a timesteps changing variable ground_truth[arr] = np.concatenate((ground_truth[arr], - gt_arr[:num_episode_dataset_2]), axis=0) - elif (len(gt_arr) == num_ts_total_2): # a timesteps changing variable - ground_truth[arr] = np.concatenate((ground_truth[arr], - gt_arr[:ts_counter_2]), axis=0) + gt_arr[:ts_counter_2, :2]), axis=0) else: assert 0 == 1, "No compatible variable in the stored ground truth for the second dataset {}" \ .format(args.merge[1]) else: # This is the first dataset - if(len(gt_arr) == num_eps_total_1): + if(len(gt_arr) <= num_eps_total_1): #This is a episode non-change variable ground_truth[arr] = gt_arr[:num_episode_dataset_1] - elif(len(gt_arr) == num_ts_total_1): # a timesteps changing variable + elif(len(gt_arr) <= num_ts_total_1): # a timesteps changing variable ground_truth[arr] = gt_arr[:ts_counter_1] else: assert 0 ==1 , "No compatible variable in the stored ground truth for the first dataset {}"\ @@ -214,13 +211,13 @@ def main(): print("The total timesteps: ", ts_counter_1+ts_counter_2) print("The total episodes: ", num_episode_dataset_1+num_episode_dataset_2) - for k in preprocessed: - print(k) - print(preprocessed[k].shape) - - for k in ground_truth: - print(k) - print(ground_truth[k].shape) + # for k in preprocessed: + # print(k) + # print(preprocessed[k].shape) + # + # for k in ground_truth: + # print(k) + # print(ground_truth[k].shape) diff --git a/rl_baselines/supervised_rl/policy_distillation.py b/rl_baselines/supervised_rl/policy_distillation.py index e2f8f0dc5..88543d929 100644 --- a/rl_baselines/supervised_rl/policy_distillation.py +++ b/rl_baselines/supervised_rl/policy_distillation.py @@ -148,6 +148,7 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): print("We assumed SRL training already done") print('Loading data for distillation ') + training_data, ground_truth, true_states, _ = loadData(args.teacher_data_folder, absolute_path=True) rewards, episode_starts = training_data['rewards'], training_data['episode_starts'] @@ -309,6 +310,7 @@ def train(self, args, callback, env_kwargs=None, train_kwargs=None): train_loss = epoch_loss / float(epoch_batches) val_loss /= float(n_val_batches) + pbar.close() print("Epoch {:3}/{}, train_loss:{:.6f} val_loss:{:.6f}".format(epoch + 1, N_EPOCHS, train_loss, val_loss)) From a1d263948d2f534937934d9891d849e828a78867 Mon Sep 17 00:00:00 2001 From: sun-te Date: Wed, 3 Jul 2019 11:15:26 +0200 Subject: [PATCH 133/141] dataset_merger can preserve the original dataset for further use --- environments/dataset_merger.py | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/environments/dataset_merger.py b/environments/dataset_merger.py index add6ec9a7..c027baabb 100644 --- a/environments/dataset_merger.py +++ b/environments/dataset_merger.py @@ -23,6 +23,8 @@ def main(): parser.add_argument('-f', '--force', action='store_true', default=False, help='Force the merge, even if it overrides something else,' ' including the destination if it exist') + parser.add_argument('-rm', '--remove', action='store_true', default=False, + help='Remove the original data set.') group = parser.add_mutually_exclusive_group() group.add_argument('--merge', type=str, nargs=3, metavar=('source_1', 'source_2', 'destination'), default=argparse.SUPPRESS, @@ -33,6 +35,7 @@ def main(): if 'merge' in args: # let make sure everything is in order assert os.path.exists(args.merge[0]), "Error: dataset '{}' could not be found".format(args.merge[0]) + assert os.path.exists(args.merge[1]), "Error: dataset '{}' could not be found".format(args.merge[1]) # If the merge file exists already, delete it for the convenince of updating student's policy if os.path.exists(args.merge[2]) or os.path.exists(args.merge[2] + '/'): @@ -48,13 +51,16 @@ def main(): os.mkdir(args.merge[2]) # copy files from first source - os.rename(args.merge[0] + "/dataset_config.json", args.merge[2] + "/dataset_config.json") - os.rename(args.merge[0] + "/env_globals.json", args.merge[2] + "/env_globals.json") - + shutil.copy2(args.merge[0] + "/dataset_config.json", args.merge[2] + "/dataset_config.json") + shutil.copy2(args.merge[0] + "/env_globals.json", args.merge[2] + "/env_globals.json") + record = '' for record in sorted(glob.glob(args.merge[0] + "/record_[0-9]*/*")): s = args.merge[2] + "/" + record.split("/")[-2] + '/' + record.split("/")[-1] - os.renames(record, s) - + try: + shutil.copy2(record, s) + except FileNotFoundError: # no folders named so, we should create it first + os.mkdir(os.path.dirname(s)) + shutil.copy2(record, s) num_episode_dataset_1 = int(record.split("/")[-2][7:]) + 1 # copy files from second source @@ -62,7 +68,11 @@ def main(): episode = str(num_episode_dataset_1 + int(record.split("/")[-2][7:])) new_episode = record.split("/")[-2][:-len(episode)] + episode s = args.merge[2] + "/" + new_episode + '/' + record.split("/")[-1] - os.renames(record, s) + try: + shutil.copy2(record, s) + except FileNotFoundError: # no folders named so, we should create it first + os.mkdir(os.path.dirname(s)) + shutil.copy2(record, s) num_episode_dataset_2 = int(record.split("/")[-2][7:]) + 1 # load and correct ground_truth @@ -127,7 +137,6 @@ def main(): for arr in prepro_load.files: pr_arr = prepro_load[arr] - to_class = None if arr == "episode_starts": to_class = bool elif arr == "actions_proba" or arr == "rewards": @@ -151,8 +160,9 @@ def main(): np.savez(args.merge[2] + "/preprocessed_data.npz", ** preprocessed) # remove the old folders - shutil.rmtree(args.merge[0]) - shutil.rmtree(args.merge[1]) + if args.remove: + shutil.rmtree(args.merge[0]) + shutil.rmtree(args.merge[1]) if __name__ == '__main__': From bf50fc5499a169a3cb2ce789f6c3cd9aa6d27832 Mon Sep 17 00:00:00 2001 From: sun-te Date: Mon, 15 Jul 2019 16:40:39 +0200 Subject: [PATCH 134/141] cleaning --- environments/omnirobot_gym/omnirobot_env.py | 34 ++++++++++----------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/environments/omnirobot_gym/omnirobot_env.py b/environments/omnirobot_gym/omnirobot_env.py index 87f067531..430c33262 100644 --- a/environments/omnirobot_gym/omnirobot_env.py +++ b/environments/omnirobot_gym/omnirobot_env.py @@ -72,7 +72,7 @@ class OmniRobotEnv(SRLGymEnv): def __init__(self, renders=False, name="Omnirobot", is_discrete=True, save_path='srl_zoo/data/', state_dim=-1, learn_states=False, srl_model="raw_pixels", record_data=False, action_repeat=1, random_target=True, - shape_reward=False, simple_continual_target=False, circular_continual_move=False,escape_continual_move=False, + shape_reward=False, simple_continual_target=False, circular_continual_move=False, escape_continual_move=False, square_continual_move=False, eight_continual_move=False, chasing_continual_move=False, short_episodes=False, state_init_override=None, env_rank=0, srl_pipe=None, **_): @@ -142,7 +142,7 @@ def __init__(self, renders=False, name="Omnirobot", is_discrete=True, save_path= square_continual_move=square_continual_move, eight_continual_move=eight_continual_move, chasing_continual_move=chasing_continual_move, - escape_continual_move = escape_continual_move, + escape_continual_move=escape_continual_move, output_size=[RENDER_WIDTH, RENDER_HEIGHT], random_target=self._random_target, state_init_override=state_init_override) @@ -209,7 +209,6 @@ def actionPolicyAwayTarget(self): def step(self, action, generated_observation=None, action_proba=None, action_grid_walker=None): """ - :param :action: (int) :param generated_observation: :param action_proba: @@ -244,8 +243,6 @@ def step(self, action, generated_observation=None, action_proba=None, action_gri {"command": "action", "action": self.action, "is_discrete": self._is_discrete, "step_counter": self._env_step_counter}) - - # Receive state data (position, etc), important to update state related values self.getEnvState() @@ -296,17 +293,18 @@ def getTargetPos(self): """ return self.target_pos - - def getGroundTruthDim(self): + @staticmethod + def getGroundTruthDim(): """ + The convergence is slow for escape task with dimension 2 :return: (int) """ - if(not self.escape_continual_move): - return 2 - else: - #The position of the robot, target - return 4 - + # if(not self.escape_continual_move): + # return 2 + # else: + # #The position of the robot, target + # return 4 + return 2 def getGroundTruth(self): """ @@ -314,10 +312,11 @@ def getGroundTruth(self): :return: (numpy array) """ # - if(not self.escape_continual_move): - return np.array(self.getRobotPos()) - else: - return np.append(self.getRobotPos(),self.getTargetPos()) + # if(not self.escape_continual_move): + # return np.array(self.getRobotPos()) + # else: + # return np.append(self.getRobotPos(),self.getTargetPos()) + return np.array(self.getRobotPos()) def getRobotPos(self): """ @@ -395,6 +394,7 @@ def render(self, mode='rgb_array'): self.visualizeBoundary() self.image_plot = plt.imshow(self.observation_with_boundary, cmap='gray') self.image_plot.axes.grid(False) + else: self.visualizeBoundary() self.image_plot.set_data(self.observation_with_boundary) From 24b16be37d475e6d554513a4d3b1acf181606499 Mon Sep 17 00:00:00 2001 From: sun-te Date: Mon, 15 Jul 2019 17:07:39 +0200 Subject: [PATCH 135/141] learning --- real_robots/omnirobot_simulator_server.py | 71 +++++++++---------- .../omnirobot_utils/omnirobot_manager_base.py | 51 ++++--------- 2 files changed, 47 insertions(+), 75 deletions(-) diff --git a/real_robots/omnirobot_simulator_server.py b/real_robots/omnirobot_simulator_server.py index 7b6f92ecc..af6a39226 100755 --- a/real_robots/omnirobot_simulator_server.py +++ b/real_robots/omnirobot_simulator_server.py @@ -96,7 +96,7 @@ def __init__(self, init_x, init_y, init_yaw, origin_size, cropped_size, # Distance for each step self.step_distance = STEP_DISTANCE - + # Distance for the escape task, zombie speed self.step_distance_target =STEP_DISTANCE_TARGET with open(camera_info_path, 'r') as stream: @@ -122,7 +122,7 @@ def __init__(self, init_x, init_y, init_yaw, origin_size, cropped_size, self.cropped_margin[1]+self.cropped_size[1]]).astype(np.int) back_ground_img = cv2.imread(back_ground_path) - if(back_ground_img.shape[0:2] != self.cropped_size): + if back_ground_img.shape[0:2] != self.cropped_size: print("input back ground image's size: ", back_ground_img.shape) print("resize to ", self.cropped_size) self.bg_img[self.cropped_range[0]:self.cropped_range[1], self.cropped_range[2]:self.cropped_range[3], :] \ @@ -259,28 +259,28 @@ def setTargetCmd(self, x, y, yaw): self.target_pos = self.target_pos_cmd self.target_yaw = self.normalizeAngle(self.target_yaw_cmd) - def forward(self, action=None): + def forward(self): """ Move one step forward (Translation) """ self.setRobotCmd( self.robot_pos_cmd[0] + self.step_distance, self.robot_pos_cmd[1], self.robot_yaw_cmd) - def backward(self, action=None): + def backward(self): """ Move one step backward """ self.setRobotCmd( self.robot_pos_cmd[0] - self.step_distance, self.robot_pos_cmd[1], self.robot_yaw_cmd) - def left(self, action=None): + def left(self): """ Translate to the left """ self.setRobotCmd( self.robot_pos_cmd[0], self.robot_pos_cmd[1] + self.step_distance, self.robot_yaw_cmd) - def right(self, action=None): + def right(self): """ Translate to the right """ @@ -294,42 +294,37 @@ def moveContinous(self, action): self.setRobotCmd( self.robot_pos_cmd[0] + action[0], self.robot_pos_cmd[1] + action[1], self.robot_yaw_cmd) - - def targetMoveDiscrete(self, target_yaw): pi = np.pi - assert target_yaw>-pi and target_yaw=pi/4 and target_yaw < pi*3/4):#Up + assert target_yaw > -pi and target_yaw < pi + target_yaw += pi + if target_yaw >= pi/4 and target_yaw < pi*3/4:#Up self.setTargetCmd( - self.target_pos_cmd[0] , self.target_pos_cmd[1]- self.step_distance_target, target_yaw) - elif(target_yaw>= 3/4*pi and target_yaw < 5/4 *pi): + self.target_pos_cmd[0], self.target_pos_cmd[1] - self.step_distance_target, target_yaw) + elif target_yaw >= 3/4*pi and target_yaw < 5/4 *pi: self.setTargetCmd( - self.target_pos_cmd[0]+ self.step_distance_target, self.target_pos_cmd[1] , target_yaw) - elif (target_yaw >= 5 / 4 * pi and target_yaw < 7 / 4 * pi): + self.target_pos_cmd[0] + self.step_distance_target, self.target_pos_cmd[1], target_yaw) + elif target_yaw >= 5/4 * pi and target_yaw < 7/4 * pi: self.setTargetCmd( - self.target_pos_cmd[0] , self.target_pos_cmd[1]+self.step_distance_target , target_yaw) + self.target_pos_cmd[0], self.target_pos_cmd[1]+self.step_distance_target, target_yaw) else: self.setTargetCmd( - self.target_pos_cmd[0] -self.step_distance_target, self.target_pos_cmd[1] , target_yaw) + self.target_pos_cmd[0] - self.step_distance_target, self.target_pos_cmd[1], target_yaw) - def targetMove(self, action=None): - assert action !=None - if action =="forward": + def targetMove(self, action): + if action == "forward": self.setTargetCmd( self.target_pos_cmd[0] + self.step_distance_target, self.target_pos_cmd[1], self.target_yaw) - elif action =="backward": + elif action == "backward": self.setTargetCmd( self.target_pos_cmd[0] - self.step_distance_target, self.target_pos_cmd[1], self.target_yaw) - elif action =="left": + elif action == "left": self.setTargetCmd( - self.target_pos_cmd[0] , self.target_pos_cmd[1]+ self.step_distance_target, self.target_yaw) - else : + self.target_pos_cmd[0] , self.target_pos_cmd[1] + self.step_distance_target, self.target_yaw) + else: self.setTargetCmd( - self.target_pos_cmd[0] , self.target_pos_cmd[1]- self.step_distance_target, self.target_yaw) - - + self.target_pos_cmd[0] , self.target_pos_cmd[1] - self.step_distance_target, self.target_yaw) def targetMoveContinous(self, target_yaw): """ @@ -364,8 +359,7 @@ def moveByVelocityCmd(self, speed_x, speed_y, speed_yaw): cos_direction + self.last_linear_velocity_cmd[0] * sin_direction)/RL_CONTROL_FREQ ground_yaw_cmd = self.robot_yaw + self.last_rot_velocity_cmd/RL_CONTROL_FREQ self.setRobotCmd(ground_pos_cmd_x, ground_pos_cmd_y, ground_yaw_cmd) - - # save the command of this moment + # save the command of this moment self.last_linear_velocity_cmd[0] = speed_x self.last_linear_velocity_cmd[1] = speed_y self.last_rot_velocity_cmd = speed_yaw @@ -379,7 +373,6 @@ def moveByWheelsCmd(self, left_speed, front_speed, right_speed): :param front_speed: (float) linear speed of front wheel (meter/s) :param right_speed: (float) linear speed of right wheel (meter/s) """ - # calculate the robot position by omnirobot's kinematic equations # Assume in 1/RL_CONTROL_FREQ, the heading remains the same (not true, # but should be approximately work if RL_CONTROL_FREQ is high enough) @@ -459,17 +452,17 @@ def __init__(self, **args): elif self.new_args["square_continual_move"] or self.new_args["eight_continual_move"]: self.new_args["target_marker_path"] = "real_robots/omnirobot_utils/green_square.png" elif self.new_args["chasing_continual_move"] or self.new_args["escape_continual_move"]: - self.new_args["target_marker_path"] = "real_robots/omnirobot_utils/yellow_T.png" + self.new_args["target_marker_path"] = "real_robots/omnirobot_utils/yellow_T.png" else: # for black target, use target_margin4_pixel.png", self.new_args["target_marker_path"] = "real_robots/omnirobot_utils/red_target_margin4_pixel_480x480.png" super(OmniRobotSimulatorSocket, self).__init__(simple_continual_target=self.new_args["simple_continual_target"], - circular_continual_move=self.new_args["circular_continual_move"], - square_continual_move=self.new_args["square_continual_move"], - eight_continual_move=self.new_args["eight_continual_move"], - chasing_continual_move=self.new_args["chasing_continual_move"], - escape_continual_move=self.new_args["escape_continual_move"] ) + circular_continual_move=self.new_args["circular_continual_move"], + square_continual_move=self.new_args["square_continual_move"], + eight_continual_move=self.new_args["eight_continual_move"], + chasing_continual_move=self.new_args["chasing_continual_move"], + escape_continual_move=self.new_args["escape_continual_move"]) assert len(self.new_args['robot_marker_margin']) == 4 assert len(self.new_args['target_marker_margin']) == 4 @@ -486,7 +479,7 @@ def __init__(self, **args): def resetEpisode(self): """ override the original method - Give the correct sequance of commands to the robot + Give the correct sequence of commands to the robot to rest environment between the different episodes """ if self.second_cam_topic is not None: @@ -507,8 +500,7 @@ def resetEpisode(self): random_init_y = np.random.random_sample() * (TARGET_MAX_Y - TARGET_MIN_Y) + \ TARGET_MIN_Y self.robot.setTargetCmd( - # random_init_x, random_init_y, 2 * np.pi * np.random.rand() - np.pi) - random_init_x, random_init_y, 0) + random_init_x, random_init_y, 2 * np.pi * np.random.rand() - np.pi) # render the target and robot self.robot.renderTarget() @@ -518,6 +510,7 @@ def send_json(self, msg): # env send msg to render self.processMsg(msg) self.robot.renderRobot() + # As for the escape task, the target is moving, we need to update in every time step self.robot.renderTarget() self.img = self.robot.getCroppedImage() diff --git a/real_robots/omnirobot_utils/omnirobot_manager_base.py b/real_robots/omnirobot_utils/omnirobot_manager_base.py index 48a12f97a..259783b20 100644 --- a/real_robots/omnirobot_utils/omnirobot_manager_base.py +++ b/real_robots/omnirobot_utils/omnirobot_manager_base.py @@ -5,7 +5,7 @@ class OmnirobotManagerBase(object): def __init__(self, simple_continual_target=False, circular_continual_move=False, square_continual_move=False, - eight_continual_move=False, chasing_continual_move=False, escape_continual_move= False, + eight_continual_move=False, chasing_continual_move=False, escape_continual_move=False, lambda_c=10.0, second_cam_topic=None, state_init_override=None): """ This class is the basic class for omnirobot server, and omnirobot simulator's server. @@ -20,7 +20,7 @@ def __init__(self, simple_continual_target=False, circular_continual_move=False, self.square_continual_move = square_continual_move self.eight_continual_move = eight_continual_move self.chasing_continual_move = chasing_continual_move - self.escape_continual_move = escape_continual_move + self.escape_continual_move = escape_continual_move self.lambda_c = lambda_c self.state_init_override = state_init_override self.step_counter = 0 @@ -91,8 +91,6 @@ def moveContinousAction(self, msg): has_bumped = True return has_bumped - - def targetMoveContinousAction(self, target_yaw): """ Let robot execute continous action, and checking the boundary @@ -108,44 +106,37 @@ def targetMoveContinousAction(self, target_yaw): has_bumped = True return has_bumped - - def targetMoveDiscreteAction(self,target_yaw): - + def targetMoveDiscreteAction(self, target_yaw): self.robot.targetMoveDiscrete(target_yaw) - def targetPolicy(self, directed = False): """ The policy for the target :param directed: directed to the robot(agent) :return: the angle to go for the target """ - if(directed): + if directed: dy = self.robot.robot_pos[1] - self.robot.target_pos[1] + np.random.rand() * abs( self.robot.robot_pos[1] - self.robot.target_pos[1]) dx = self.robot.robot_pos[0] - self.robot.target_pos[0] + np.random.rand() * abs( self.robot.robot_pos[0] - self.robot.target_pos[0]) - r = math.sqrt(dy**2+dx**2) + r = math.sqrt(dy**2 + dx**2) dy /= r dx /= r - yaw = math.atan2(dy, dx ) + yaw = math.atan2(dy, dx) #return yaw - if(abs(dy)>abs(dx)): - if(dy>0): + if abs(dy) > abs(dx): + if dy > 0: self.robot.targetMove("left") else: self.robot.targetMove("right") else: - if(dx>0): + if dx > 0: self.robot.targetMove("forward") else: self.robot.targetMove("backward") - - - period = 70 yaw = (2*(self.step_counter % period )/period-1)*np.pi - return yaw def sampleRobotInitalPosition(self): @@ -180,7 +171,6 @@ def processMsg(self, msg): action = None self.episode_idx += 1 self.step_counter = 0 - # empty list of previous states self.robot.emptyHistory() @@ -197,7 +187,7 @@ def processMsg(self, msg): exit(0) else: raise ValueError("Unknown command: {}".format(msg)) - self.step_counter +=1 + self.step_counter += 1 has_bumped = False # We are always facing North @@ -218,10 +208,6 @@ def processMsg(self, msg): else: print("Unsupported action: ", action) - - - - # Determinate the reward for this step if self.circular_continual_move or self.square_continual_move or self.eight_continual_move: @@ -257,35 +243,28 @@ def processMsg(self, msg): elif self.chasing_continual_move: # The action for target agent target_yaw = self.targetPolicy() - self.targetMoveContinousAction(target_yaw) dis = np.linalg.norm(np.array(self.robot.robot_pos) - np.array(self.robot.target_pos)) - if(dis<0.4 and dis > 0.3): + if dis < 0.4 and dis > 0.3: self.reward = REWARD_TARGET_REACH elif has_bumped: self.reward = REWARD_BUMP_WALL else: self.reward = REWARD_NOTHING - - elif self.escape_continual_move: - dis = np.linalg.norm(np.array(self.robot.robot_pos) - np.array(self.robot.target_pos)) - - if has_bumped or dis<0.4: + if has_bumped or dis < 0.4: self.reward = REWARD_BUMP_WALL # elif(dis<0.2): # self.reward = REWARD_BUMP_WALL - elif(dis>=0.4): + elif(dis >= 0.4): self.reward =REWARD_TARGET_REACH else: self.reward = REWARD_NOTHING self.targetPolicy(directed=True) - #self.targetMoveContinousAction(target_yaw) - #self.targetMoveDiscreteAction(target_yaw) - - + # self.targetMoveContinousAction(target_yaw) + # self.targetMoveDiscreteAction(target_yaw) else: # Consider that we reached the target if we are close enough # we detect that computing the difference in area between TARGET_INITIAL_AREA From 6e2272c1335e0fe76edca5aba2e2301736885d4a Mon Sep 17 00:00:00 2001 From: sun-te Date: Mon, 15 Jul 2019 17:17:27 +0200 Subject: [PATCH 136/141] preserve original data after merge --- environments/dataset_merger.py | 136 +++++++++------------------------ 1 file changed, 36 insertions(+), 100 deletions(-) diff --git a/environments/dataset_merger.py b/environments/dataset_merger.py index 43c3d5418..aa64ad366 100644 --- a/environments/dataset_merger.py +++ b/environments/dataset_merger.py @@ -4,12 +4,13 @@ import argparse import os import shutil -import pdb import numpy as np from tqdm import tqdm -CONTINUAL_LEARNING_LABELS = ['CC', 'SC', 'EC', 'SQC'] +# List of all possible labels identifying a task, +# for experiments in Continual Learning scenari. +CONTINUAL_LEARNING_LABELS = ['CC', 'SC', 'EC', 'SQC', 'ESC'] CL_LABEL_KEY = "continual_learning_label" @@ -22,17 +23,19 @@ def main(): parser.add_argument('-f', '--force', action='store_true', default=False, help='Force the merge, even if it overrides something else,' ' including the destination if it exist') - parser.add_argument('--timesteps', type=int, nargs=2, default=[-1,-1], - help="To have a certain number of frames for two data sets ") + parser.add_argument('-rm', '--remove', action='store_true', default=False, + help='Remove the original data set.') group = parser.add_mutually_exclusive_group() group.add_argument('--merge', type=str, nargs=3, metavar=('source_1', 'source_2', 'destination'), default=argparse.SUPPRESS, help='Merge two datasets by appending the episodes, deleting sources right after.') args = parser.parse_args() + if 'merge' in args: # let make sure everything is in order assert os.path.exists(args.merge[0]), "Error: dataset '{}' could not be found".format(args.merge[0]) + assert os.path.exists(args.merge[1]), "Error: dataset '{}' could not be found".format(args.merge[1]) # If the merge file exists already, delete it for the convenince of updating student's policy if os.path.exists(args.merge[2]) or os.path.exists(args.merge[2] + '/'): @@ -47,63 +50,31 @@ def main(): # create the output os.mkdir(args.merge[2]) - - #os.rename(args.merge[0] + "/dataset_config.json", args.merge[2] + "/dataset_config.json") - #os.rename(args.merge[0] + "/env_globals.json", args.merge[2] + "/env_globals.json") - shutil.copy2(args.merge[0] + "/dataset_config.json",args.merge[2] + "/dataset_config.json") - shutil.copy2(args.merge[0] + "/env_globals.json", args.merge[2] + "/env_globals.json") - # copy files from first source - num_timesteps_1, num_timesteps_2 = args.timesteps - local_path = os.getcwd() - all_records = sorted(glob.glob(args.merge[0] + "/record_[0-9]*/*")) - previous_records = all_records[0] - for ts_counter_1, record in enumerate(all_records): - - #if the timesteps is larger than needed, we wait until this episode is over - if(num_timesteps_1>0 and ts_counter_1 >num_timesteps_1): - if(os.path.dirname(previous_records).split('_')[-1] != os.path.dirname(record).split('_')[-1]): - break + shutil.copy2(args.merge[0] + "/dataset_config.json", args.merge[2] + "/dataset_config.json") + shutil.copy2(args.merge[0] + "/env_globals.json", args.merge[2] + "/env_globals.json") + record = '' + for record in sorted(glob.glob(args.merge[0] + "/record_[0-9]*/*")): s = args.merge[2] + "/" + record.split("/")[-2] + '/' + record.split("/")[-1] - s = os.path.join(local_path,s) - record = os.path.join(local_path, record) try: shutil.copy2(record, s) - except FileNotFoundError: + except FileNotFoundError: # no folders named so, we should create it first os.mkdir(os.path.dirname(s)) shutil.copy2(record, s) - previous_records = record - num_episode_dataset_1 = int(previous_records.split("/")[-2][7:]) - if (num_timesteps_1 == -1): - num_episode_dataset_1 += 1 - ts_counter_1 += 1 + num_episode_dataset_1 = int(record.split("/")[-2][7:]) + 1 # copy files from second source - all_records = sorted(glob.glob(args.merge[1] + "/record_[0-9]*/*")) - previous_records = all_records[0] - for ts_counter_2, record in enumerate(all_records): - - if (num_timesteps_2 > 0 and ts_counter_2 > num_timesteps_2): - if (os.path.dirname(previous_records).split('_')[-1] != os.path.dirname(record).split('_')[-1]): - break + for record in sorted(glob.glob(args.merge[1] + "/record_[0-9]*/*")): episode = str(num_episode_dataset_1 + int(record.split("/")[-2][7:])) new_episode = record.split("/")[-2][:-len(episode)] + episode s = args.merge[2] + "/" + new_episode + '/' + record.split("/")[-1] - s = os.path.join(local_path, s) - record = os.path.join(local_path, record) try: shutil.copy2(record, s) - except FileNotFoundError: + except FileNotFoundError: # no folders named so, we should create it first os.mkdir(os.path.dirname(s)) shutil.copy2(record, s) - previous_records = record - - num_episode_dataset_2 = int(previous_records.split("/")[-2][7:]) - if(num_timesteps_2==-1): - num_episode_dataset_2 +=1 - ts_counter_2 +=1 + num_episode_dataset_2 = int(record.split("/")[-2][7:]) + 1 - ts_counter = [ts_counter_1, ts_counter_2] # load and correct ground_truth ground_truth = {} ground_truth_load = np.load(args.merge[0] + "/ground_truth.npz") @@ -115,20 +86,12 @@ def main(): index_margin_str = len("/record_") directory_str = args.merge[2][index_slash+1:] - len_info_1 = [len(ground_truth_load[k]) for k in ground_truth_load.keys()] - num_eps_total_1, num_ts_total_1 = min(len_info_1), max(len_info_1) - len_info_2 = [len(ground_truth_load_2[k]) for k in ground_truth_load_2.keys()] - num_eps_total_2, num_ts_total_2 = min(len_info_2), max(len_info_2) - - for idx_, gt_load in enumerate([ground_truth_load, ground_truth_load_2], 1): - for arr in gt_load.files: - if arr == "images_path": - #here, we want to rename just the folder containing the records, hence the black magic + # here, we want to rename just the folder containing the records, hence the black magic - for i in tqdm(range(ts_counter[idx_-1]),#range(len(gt_load["images_path"])), + for i in tqdm(range(len(gt_load["images_path"])), desc="Update of paths (Folder " + str(1+idx_) + ")"): # find the "record_" position path = gt_load["images_path"][i] @@ -142,7 +105,6 @@ def main(): else: new_record_path = path[end_pos:] ground_truth["images_path"].append(directory_str + new_record_path) - else: # anything that isnt image_path, we dont need to change gt_arr = gt_load[arr] @@ -150,28 +112,14 @@ def main(): if idx_ > 1: num_episode_dataset = num_episode_dataset_2 + # HERE check before overwritting that the target is random !+ + if gt_load[arr].shape[0] < num_episode_dataset: + gt_arr = np.repeat(gt_load[arr], num_episode_dataset, axis=0) if idx_ > 1: - # This is the first dataset - if (len(gt_arr) <= num_eps_total_2): - # This is a episode non-change variable - ground_truth[arr] = np.concatenate((ground_truth[arr],gt_arr[:num_episode_dataset_2,:2]), axis=0) - elif (len(gt_arr) <= num_ts_total_2): # a timesteps changing variable - ground_truth[arr] = np.concatenate((ground_truth[arr], - gt_arr[:ts_counter_2, :2]), axis=0) - else: - assert 0 == 1, "No compatible variable in the stored ground truth for the second dataset {}" \ - .format(args.merge[1]) + ground_truth[arr] = np.concatenate((ground_truth[arr], gt_arr), axis=0) else: - # This is the first dataset - if(len(gt_arr) <= num_eps_total_1): - #This is a episode non-change variable - ground_truth[arr] = gt_arr[:num_episode_dataset_1] - elif(len(gt_arr) <= num_ts_total_1): # a timesteps changing variable - ground_truth[arr] = gt_arr[:ts_counter_1] - else: - assert 0 ==1 , "No compatible variable in the stored ground truth for the first dataset {}"\ - .format(args.merge[0]) + ground_truth[arr] = gt_arr # save the corrected ground_truth np.savez(args.merge[2] + "/ground_truth.npz", **ground_truth) @@ -183,51 +131,39 @@ def main(): dataset_1_size = preprocessed_load["actions"].shape[0] dataset_2_size = preprocessed_load_2["actions"].shape[0] + + # Concatenating additional information: indices of episode start, action probabilities, CL labels... for idx, prepro_load in enumerate([preprocessed_load, preprocessed_load_2]): for arr in prepro_load.files: pr_arr = prepro_load[arr] - to_class = None if arr == "episode_starts": to_class = bool - elif arr == "actions_proba" or arr =="rewards": + elif arr == "actions_proba" or arr == "rewards": to_class = float else: to_class = int - # all data is of timesteps changing (instead of episode changing) - if preprocessed.get(arr, None) is None: #for the first dataset - preprocessed[arr] = pr_arr.astype(to_class)[:ts_counter_1] - else:# for the second dataset + if preprocessed.get(arr, None) is None: + preprocessed[arr] = pr_arr.astype(to_class) + else: preprocessed[arr] = np.concatenate((preprocessed[arr].astype(to_class), - pr_arr[:ts_counter_2].astype(to_class)), axis=0) + pr_arr.astype(to_class)), axis=0) if 'continual_learning_labels' in args: if preprocessed.get(CL_LABEL_KEY, None) is None: preprocessed[CL_LABEL_KEY] = \ - np.array([args.continual_learning_labels[idx] for _ in range(ts_counter_1)]) + np.array([args.continual_learning_labels[idx] for _ in range(dataset_1_size)]) else: preprocessed[CL_LABEL_KEY] = \ np.concatenate((preprocessed[CL_LABEL_KEY], np.array([args.continual_learning_labels[idx] - for _ in range(ts_counter_2)])), axis=0) - - print("The total timesteps: ", ts_counter_1+ts_counter_2) - print("The total episodes: ", num_episode_dataset_1+num_episode_dataset_2) - # for k in preprocessed: - # print(k) - # print(preprocessed[k].shape) - # - # for k in ground_truth: - # print(k) - # print(ground_truth[k].shape) - - + for _ in range(dataset_2_size)])), axis=0) np.savez(args.merge[2] + "/preprocessed_data.npz", ** preprocessed) - # remove the old folders - # shutil.rmtree(args.merge[0]) - # shutil.rmtree(args.merge[1]) + if args.remove: + shutil.rmtree(args.merge[0]) + shutil.rmtree(args.merge[1]) if __name__ == '__main__': - main() \ No newline at end of file + main() From d10e9b694b1a037987776c81757fa8868c43a239 Mon Sep 17 00:00:00 2001 From: TeTe <32313299+sun-te@users.noreply.github.com> Date: Mon, 15 Jul 2019 17:20:51 +0200 Subject: [PATCH 137/141] resampling for the distillation fail to resample, delte --- environments/data_separator.py | 216 --------------------------------- 1 file changed, 216 deletions(-) delete mode 100644 environments/data_separator.py diff --git a/environments/data_separator.py b/environments/data_separator.py deleted file mode 100644 index 57b24c70c..000000000 --- a/environments/data_separator.py +++ /dev/null @@ -1,216 +0,0 @@ -""" -Script to verify the states distribution -""" -import json -import os -import argparse - -import matplotlib.pyplot as plt -import seaborn as sns -import numpy as np -import torch as th -from tqdm import tqdm -from functools import partial -from multiprocessing import Pool -from ipdb import set_trace as tt - - -from state_representation.models import loadSRLModel, getSRLDim -from srl_zoo.utils import loadData -from srl_zoo.preprocessing.data_loader import SupervisedDataLoader, DataLoader - -sns.set() - -#os.chdir('/home/tete/Robotics-branches/robotics-rl-srl-two/logs/teacher_policies_for_evaluation/sc/OmnirobotEnv-v0/srl_combination/ppo2/19-06-19_01h10_00') - -BATCH_SIZE = 64 -N_WORKERS = 8 -DEVICE = th.device("cuda" if th.cuda.is_available() else "cpu") -VALIDATION_SIZE = 0.2 # 20% of training data for validation - - -def PCA(data, dim=2): - # preprocess the data - X = th.from_numpy(data).to(DEVICE) - X_mean = th.mean(X,0) - X = X - X_mean.expand_as(X) - - # svd - U,S,V = th.svd(th.t(X)) - C = th.mm(X,U[:,:dim]).to('cpu').numpy() - return C - -def dataSrlLoad(data, srl_model=None, state_dim=2, pca_mode=True, normalized=True): - """ - - :param data_folder: (str) the path to the dataset we want to sample - :param srl_model_path: (str) - :return: the dataset after the srl evaluation and a pca preprocessd, - it self, a random sampled training set, validation set - """ - - # load images and other data - training_data, ground_truth, true_states = data - images_path = ground_truth['images_path'] - ground_truth_states_dim = true_states.shape[1] - - # we change the path to the local path at the toolbox level - images_path_copy = ["srl_zoo/data/" + images_path[k] for k in range(images_path.shape[0])] - images_path = np.array(images_path_copy) - - num_samples = images_path.shape[0]-1 # number of samples - - # indices for all time steps where the episode continues - #indices = np.array([i for i in range(num_samples-1) if not episode_starts[i + 1]], dtype='int64') - indices = np.arange(num_samples) - - minibatchlist = [np.array(sorted(indices[start_idx:start_idx + BATCH_SIZE])) - for start_idx in range(0, len(indices) - BATCH_SIZE + 1, BATCH_SIZE)] - - data_loader = DataLoader(minibatchlist, images_path, n_workers=N_WORKERS, multi_view=False, - use_triplets=False, is_training=True, absolute_path=True) - - srl_data = [] - #we only use the srl model to deduct the states - srl_model.model = srl_model.model.eval() - pbar = tqdm(total=len(data_loader)) - for minibatch_num, (minibatch_idx, obs, _, _, _) in enumerate(data_loader): - obs = obs.to(DEVICE) - state = srl_model.model.getStates(obs).to('cpu').detach().numpy() - srl_data.append(state) - pbar.update(1) - - # concatenate into one numpy array - srl_data = np.concatenate(srl_data,axis=0) - # PCA for the v - if pca_mode: - pca_srl_data = PCA(srl_data, dim=ground_truth_states_dim) - else: - pca_srl_data = srl_data - if normalized: # Normilized into -0.5 to +0.5 - for k in range(pca_srl_data.shape[1]): - pca_srl_data[:, k] = (pca_srl_data[:, k] - np.min(pca_srl_data[:, k])) / ( - np.max(pca_srl_data[:, k]) - np.min(pca_srl_data[:, k])) - 0.5 - - training_indices = np.concatenate(minibatchlist) - - return pca_srl_data, training_indices - -def plotDistribution(pca_srl_data, val_num): - fig, ax = plt.subplots(nrows=1, ncols=3, figsize=[24, 8]) - x_min, x_max = pca_srl_data[:, 0].min(), pca_srl_data[:, 0].max() - y_min, y_max = pca_srl_data[:, 1].min(), pca_srl_data[:, 1].max() - ax[0].scatter(pca_srl_data[val_num:, 0], pca_srl_data[val_num:, 1], s=5, c='b', label='Training') - ax[0].scatter(pca_srl_data[:val_num, 0], pca_srl_data[:val_num, 1], s=5, c='r', label='Validation') - ax[0].legend() - ax[0].title.set_text('Sample') - # plt.show() - ax[1].hist2d(pca_srl_data[:val_num, 0], pca_srl_data[:val_num, 1], - bins=100, range=[[x_min, x_max], [y_min, y_max]]) - ax[1].title.set_text('Validation distribution') - ax[2].hist2d(pca_srl_data[val_num:, 0], pca_srl_data[val_num:, 1], - bins=100, range=[[x_min, x_max], [y_min, y_max]]) - ax[2].title.set_text('Training distribution') - plt.show() - - -def _del_val(p_val, train_set, threshold): - """ - if the points are too close to each other, we will delete it from the dataset. - :param p_val: (np.array) the data points of validation set - :param train_set: (np.array) the training set - :param threshold: (float) - :return: - """ - import numpy as np - for p_train in train_set: - if(1.e-10 Date: Mon, 15 Jul 2019 17:27:51 +0200 Subject: [PATCH 138/141] cleaning --- state_representation/episode_saver.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/state_representation/episode_saver.py b/state_representation/episode_saver.py index 13e69d392..ab2b61a67 100644 --- a/state_representation/episode_saver.py +++ b/state_representation/episode_saver.py @@ -112,7 +112,7 @@ def reset(self, observation, target_pos, ground_truth): self.ground_truth_states.append(ground_truth) self.saveImage(observation) - def step(self, observation, action, reward, done, ground_truth_state, action_proba=None,target_pos = []): + def step(self, observation, action, reward, done, ground_truth_state, action_proba=None, target_pos=[]): """ :param observation: (numpy matrix) BGR Image :param action: (int) @@ -151,7 +151,7 @@ def save(self): assert len(self.actions) == len(self.episode_starts) assert len(self.actions) == len(self.images_path) assert len(self.actions) == len(self.ground_truth_states) - assert len(self.target_positions) == self.episode_idx + 1 or len(self.target_positions) ==len(self.actions) + assert len(self.target_positions) == self.episode_idx + 1 assert len(self.actions_proba) == 0 or len(self.actions_proba) == len(self.actions) data = { From d4c2bd9b51bdbb6497d1563d5103dec69497eaa5 Mon Sep 17 00:00:00 2001 From: sun-te Date: Thu, 18 Jul 2019 15:29:07 +0200 Subject: [PATCH 139/141] test4esc&clearning --- environments/omnirobot_gym/omnirobot_env.py | 20 +++++--- rl_baselines/student_eval.py | 16 +++--- state_representation/episode_saver.py | 5 +- tests/test_distillation_pipeline.py | 54 +++++++++++++++------ 4 files changed, 64 insertions(+), 31 deletions(-) diff --git a/environments/omnirobot_gym/omnirobot_env.py b/environments/omnirobot_gym/omnirobot_env.py index 430c33262..027adcbea 100644 --- a/environments/omnirobot_gym/omnirobot_env.py +++ b/environments/omnirobot_gym/omnirobot_env.py @@ -72,8 +72,9 @@ class OmniRobotEnv(SRLGymEnv): def __init__(self, renders=False, name="Omnirobot", is_discrete=True, save_path='srl_zoo/data/', state_dim=-1, learn_states=False, srl_model="raw_pixels", record_data=False, action_repeat=1, random_target=True, - shape_reward=False, simple_continual_target=False, circular_continual_move=False, escape_continual_move=False, - square_continual_move=False, eight_continual_move=False, chasing_continual_move=False, short_episodes=False, + shape_reward=False, simple_continual_target=False, circular_continual_move=False, + escape_continual_move=False, square_continual_move=False, eight_continual_move=False, + chasing_continual_move=False, short_episodes=False, state_init_override=None, env_rank=0, srl_pipe=None, **_): super(OmniRobotEnv, self).__init__(srl_model=srl_model, @@ -206,7 +207,6 @@ def actionPolicyAwayTarget(self): else: return -DELTA_POS if self.robot_pos[1] < self.target_pos[1] else +DELTA_POS - def step(self, action, generated_observation=None, action_proba=None, action_grid_walker=None): """ :param :action: (int) @@ -253,9 +253,17 @@ def step(self, action, generated_observation=None, action_proba=None, action_gri self.render() if self.saver is not None: - self.saver.step(self.observation, action_from_teacher if action_grid_walker is not None else action_to_step, - self.reward, done, self.getGroundTruth(), action_proba=action_proba, - target_pos=self.getTargetPos()) + # Dynamic environment + if self.chasing_continual_move or self.escape_continual_move: + self.saver.step(self.observation, action_from_teacher if action_grid_walker is not None else + action_to_step, + self.reward, done, self.getGroundTruth(), + action_proba=action_proba, target_pos=self.getTargetPos()) + else: + self.saver.step(self.observation, action_from_teacher if action_grid_walker is not None else + action_to_step, + self.reward, done, self.getGroundTruth(), + action_proba=action_proba) old_observation = self.getObservation() if self.use_srl: return self.getSRLState(self.observation diff --git a/rl_baselines/student_eval.py b/rl_baselines/student_eval.py index bfdfc745a..2119f072c 100644 --- a/rl_baselines/student_eval.py +++ b/rl_baselines/student_eval.py @@ -13,10 +13,9 @@ from srl_zoo.utils import printRed, printYellow, printBlue from state_representation.registry import registered_srl -CONTINUAL_LEARNING_LABELS = ['CC', 'SC', 'EC', 'SQC'] +CONTINUAL_LEARNING_LABELS = ['CC', 'SC', 'EC', 'SQC', 'ESC'] CL_LABEL_KEY = "continual_learning_label" - def OnPolicyDatasetGenerator(teacher_path, output_name, task_id, episode=-1, env_name='OmnirobotEnv-v0', num_cpu=1, num_eps=200, test_mode=False): """ @@ -30,12 +29,13 @@ def OnPolicyDatasetGenerator(teacher_path, output_name, task_id, episode=-1, env :param num_eps: :return: """ + assert task_id in CONTINUAL_LEARNING_LABELS command_line = ['python', '-m', 'environments.dataset_generator', '--run-policy', 'custom'] cpu_command = ['--num-cpu', str(num_cpu)] name_command = ['--name', output_name] save_path = ['--save-path', "data/"] env_command = ['--env', env_name] - task_command = ["-sc" if task_id == "SC" else '-cc'] + task_command = ['-' + task_id.lower()] if task_id == 'SC': episode_command = ['--num-episode', str(10 if test_mode else 400)] else: @@ -90,8 +90,6 @@ def allPolicyFiles(log_dir): :param log_dir: :return: """ - train_args, algo_name, algo_class, srl_model_path, env_kwargs = loadConfigAndSetup(log_dir) - files = glob.glob(os.path.join(log_dir + algo_name + '_*_model.pkl')) printYellow(log_dir) files = glob.glob(log_dir + '/model_*') @@ -147,7 +145,7 @@ def trainStudent(teacher_data_path, task_id, yaml_file='config/srl_models.yaml', env_command = ['--env', env_name] policy_command = ['--teacher-data-folder', teacher_data_path] size_epochs = ['--distillation-training-set-size', str(training_size), '--epochs-distillation', str(epochs)] - task_command = ["-sc" if task_id is "SC" else '-cc'] + task_command = ['-' + task_id.lower()] ok = subprocess.call(command_line + srl_command + env_command + policy_command + size_epochs + task_command + ['--srl-config-file', yaml_file]) assert ok == 0 @@ -164,7 +162,9 @@ def mergeData(teacher_dataset_1, teacher_dataset_2, merge_dataset, force=False): merge_command = ['--merge', teacher_dataset_1, teacher_dataset_2, merge_dataset] if force: merge_command.append('-f') - ok = subprocess.call(['python', '-m', 'environments.dataset_merger'] + merge_command) + # -rm is to remove the original dataset after training, this would be of the same effect as the old version + # which will remove the dataset automatically. + ok = subprocess.call(['python', '-m', 'environments.dataset_merger', '-rm'] + merge_command) assert ok == 0 @@ -273,7 +273,7 @@ def main(): ['cp', '-r', merge_path, 'srl_zoo/data/', '-f']) else: # merge the data - mergeData('data/' + teacher_pro_data, 'data/' + teacher_learn_data, merge_path,force=True) + mergeData('data/' + teacher_pro_data, 'data/' + teacher_learn_data, merge_path, force=True) ok = subprocess.call( ['cp', '-r', 'data/on_policy_merged/', 'srl_zoo/data/', '-f']) diff --git a/state_representation/episode_saver.py b/state_representation/episode_saver.py index ab2b61a67..ca9439c8b 100644 --- a/state_representation/episode_saver.py +++ b/state_representation/episode_saver.py @@ -134,7 +134,7 @@ def step(self, observation, action, reward, done, ground_truth_state, action_pro if not done: self.episode_starts.append(False) - if (len(target_pos) != 0): + if len(target_pos) != 0: self.target_positions.append(target_pos) self.ground_truth_states.append(ground_truth_state) self.saveImage(observation) @@ -151,7 +151,8 @@ def save(self): assert len(self.actions) == len(self.episode_starts) assert len(self.actions) == len(self.images_path) assert len(self.actions) == len(self.ground_truth_states) - assert len(self.target_positions) == self.episode_idx + 1 + # change this assertion since the dynamic environment needs to save the target position at each step + assert len(self.target_positions) == self.episode_idx + 1 or len(self.target_positions) == len(self.actions) assert len(self.actions_proba) == 0 or len(self.actions_proba) == len(self.actions) data = { diff --git a/tests/test_distillation_pipeline.py b/tests/test_distillation_pipeline.py index dbbe63d50..0a11930c4 100644 --- a/tests/test_distillation_pipeline.py +++ b/tests/test_distillation_pipeline.py @@ -26,57 +26,81 @@ def testOnPolicyDatasetGeneration(): # do not write distillation in path to prevent loading irrelevant algo based on folder name test_log_dir = "logs/test_dist/" - test_log_dir_teacher_one = test_log_dir + 'teacher_one/' - test_log_dir_teacher_two = test_log_dir + 'teacher_two/' + test_log_dir_teacher_sc = test_log_dir + 'teacher_sc/' + test_log_dir_teacher_cc = test_log_dir + 'teacher_cc/' + test_log_dir_teacher_esc = test_log_dir + 'teacher_esc/' + teacher_log_dirs = [test_log_dir_teacher_sc, test_log_dir_teacher_cc, test_log_dir_teacher_esc] if os.path.exists(test_log_dir): print("Destination log directory '{}' already exists - removing it before re-creating it".format(test_log_dir)) shutil.rmtree(test_log_dir) - + if not os.path.exists("logs"): + os.mkdir("logs/") os.mkdir(test_log_dir) - os.mkdir(test_log_dir_teacher_one) - os.mkdir(test_log_dir_teacher_two) + for log_dir in teacher_log_dirs: + os.mkdir(log_dir) + + print("Teachers training") + # First Teacher for circular task args = ['--algo', "ppo2", '--env', ENV_NAME, '--srl-model', DEFAULT_SRL_TEACHERS, '--num-timesteps', NUM_TIMESTEP, '--num-cpu', NUM_CPU, '--no-vis', '--log-dir', - test_log_dir_teacher_one, '-sc'] + teacher_log_dirs[0], '-sc'] args = list(map(str, args)) ok = subprocess.call(['python', '-m', 'rl_baselines.train'] + args) assertEq(ok, 0) + # Second teacher for circular task + args = ['--algo', "ppo2", '--env', ENV_NAME, '--srl-model', DEFAULT_SRL_TEACHERS, + '--num-timesteps', NUM_TIMESTEP, '--num-cpu', NUM_CPU, '--no-vis', '--log-dir', + teacher_log_dirs[1], '-cc'] + args = list(map(str, args)) + ok = subprocess.call(['python', '-m', 'rl_baselines.train'] + args) + assertEq(ok, 0) + # Third teacher for circular task args = ['--algo', "ppo2", '--env', ENV_NAME, '--srl-model', DEFAULT_SRL_TEACHERS, '--num-timesteps', NUM_TIMESTEP, '--num-cpu', NUM_CPU, '--no-vis', '--log-dir', - test_log_dir_teacher_two, '-cc'] + teacher_log_dirs[2], '-esc'] args = list(map(str, args)) ok = subprocess.call(['python', '-m', 'rl_baselines.train'] + args) assertEq(ok, 0) # Generate on-policy datasets from each teacher - test_log_dir_teacher_one += ENV_NAME + '/' + DEFAULT_SRL_TEACHERS + "/ppo2" + teacher_log_dirs[0] += ENV_NAME + '/' + DEFAULT_SRL_TEACHERS + "/ppo2" teacher_one_path = \ - max([test_log_dir_teacher_one + "/" + d for d in os.listdir(test_log_dir_teacher_one) - if os.path.isdir(test_log_dir_teacher_one + "/" + d)], key=os.path.getmtime) + '/' + max([teacher_log_dirs[0] + "/" + d for d in os.listdir(teacher_log_dirs[0]) + if os.path.isdir(teacher_log_dirs[0] + "/" + d)], key=os.path.getmtime) + '/' OnPolicyDatasetGenerator(teacher_path=teacher_one_path, output_name='test_SC_copy/', task_id='SC', episode=-1, env_name=ENV_NAME, test_mode=True) - test_log_dir_teacher_two += ENV_NAME + '/' + DEFAULT_SRL_TEACHERS + "/ppo2" + teacher_log_dirs[1] += ENV_NAME + '/' + DEFAULT_SRL_TEACHERS + "/ppo2" teacher_two_path = \ - max([test_log_dir_teacher_two + "/" + d for d in os.listdir(test_log_dir_teacher_two) - if os.path.isdir(test_log_dir_teacher_two + "/" + d)], key=os.path.getmtime) + '/' + max([teacher_log_dirs[1] + "/" + d for d in os.listdir(teacher_log_dirs[1]) + if os.path.isdir(teacher_log_dirs[1] + "/" + d)], key=os.path.getmtime) + '/' OnPolicyDatasetGenerator(teacher_path=teacher_two_path, output_name='test_CC_copy/', task_id='CC', episode=-1, env_name=ENV_NAME, test_mode=True) + teacher_log_dirs[2] += ENV_NAME + '/' + DEFAULT_SRL_TEACHERS + "/ppo2" + teacher_three_path = \ + max([teacher_log_dirs[2] + "/" + d for d in os.listdir(teacher_log_dirs[2]) + if os.path.isdir(teacher_log_dirs[2] + "/" + d)], key=os.path.getmtime) + '/' + + OnPolicyDatasetGenerator(teacher_path=teacher_three_path, output_name='test_ESC_copy/', + task_id='ESC', episode=-1, env_name=ENV_NAME, test_mode=True) + # Merge those on-policy datasets merge_path = "data/on_policy_merged_test" - mergeData('data/test_SC_copy/', 'data/test_CC_copy/', merge_path, force=True) + tmp_path = 'data/on_policy_merged_sc_cc/' + mergeData('data/test_SC_copy/', 'data/test_CC_copy/', tmp_path, force=True) + mergeData(tmp_path, 'data/test_ESC_copy/', merge_path, force=True) ok = subprocess.call(['cp', '-r', merge_path, 'srl_zoo/data/', '-f']) assert ok == 0 - time.sleep(10) + time.sleep(1) # Train a raw_pixels student policy via distillation trainStudent(merge_path, "CC", log_dir=test_log_dir, srl_model=DEFAULT_SRL_STUDENT, From 9527b009b46511128198db3f690eb0bbe0c1bfd1 Mon Sep 17 00:00:00 2001 From: TeTe <32313299+sun-te@users.noreply.github.com> Date: Thu, 18 Jul 2019 15:37:10 +0200 Subject: [PATCH 140/141] Delete delete_val.ipynb delete jupyter notebook created for testing purpose --- delete_val.ipynb | 670 ----------------------------------------------- 1 file changed, 670 deletions(-) delete mode 100644 delete_val.ipynb diff --git a/delete_val.ipynb b/delete_val.ipynb deleted file mode 100644 index 63c8be5c8..000000000 --- a/delete_val.ipynb +++ /dev/null @@ -1,670 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "from environments.data_separator import dataSrlLoad, plotDistribution, PCA\n", - "import torch as th\n", - "import matplotlib.pyplot as plt\n", - "import seaborn as sns\n", - "from tqdm import tqdm\n", - "from multiprocessing import Pool\n", - "import os\n", - "import multiprocessing\n", - "from state_representation.models import loadSRLModel, getSRLDim\n", - "from srl_zoo.utils import loadData\n", - "from srl_zoo.preprocessing.data_loader import SupervisedDataLoader, DataLoader" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "BATCH_SIZE = 256\n", - "N_WORKERS = 8\n", - "DEVICE = th.device(\"cuda\" if th.cuda.is_available() else \"cpu\")\n", - "VALIDATION_SIZE = 0.2 # 20% of training data for validation" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "srl_model_path = 'srl_zoo/logs/Omnibot_random_circular/19-06-17_16h36_37_custom_cnn_ST_DIM200_inverse_autoencoder/srl_model.pth'\n", - "data_folder = '/home/tete/Robotics-branches/escape-dev/robotics-rl-srl/srl_zoo/data/circular_on_policy_short_eps//'" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "def dataSrlLoad(data_folder, srl_model_path, state_dim=2, pca_mode=True, normalized=True):\n", - " \"\"\"\n", - "\n", - " :param data_folder: (str) the path to the dataset we want to sample\n", - " :param srl_model_path: (str)\n", - " :return: the dataset after the srl evaluation and a pca preprocessd,\n", - " it self, a random sampled training set, validation set\n", - " \"\"\"\n", - " state_dim = getSRLDim(srl_model_path)\n", - " srl_model = loadSRLModel(srl_model_path, th.cuda.is_available(), state_dim, env_object=None)\n", - " # load images and other data\n", - " training_data, ground_truth, true_states,_ = loadData(data_folder, absolute_path=True)\n", - " images_path = ground_truth['images_path']\n", - " ground_truth_states_dim = true_states.shape[1]\n", - "\n", - " # we change the path to the local path at the toolbox level\n", - " images_path_copy = [\"srl_zoo/data/\" + images_path[k] for k in range(images_path.shape[0])]\n", - " images_path = np.array(images_path_copy)\n", - "\n", - " num_samples = images_path.shape[0] # number of samples\n", - "\n", - " # indices for all time steps where the episode continues\n", - " #indices = np.array([i for i in range(num_samples-1) if not episode_starts[i + 1]], dtype='int64')\n", - " indices = np.arange(num_samples)\n", - "\n", - " minibatchlist = [np.array(sorted(indices[start_idx:start_idx + BATCH_SIZE]))\n", - " for start_idx in range(0, len(indices) - BATCH_SIZE + 1, BATCH_SIZE)]\n", - "\n", - " data_loader = DataLoader(minibatchlist, images_path, n_workers=N_WORKERS, multi_view=False,\n", - " use_triplets=False, is_training=True, absolute_path=True)\n", - "\n", - " srl_data = []\n", - " #we only use the srl model to deduct the states\n", - " srl_model.model = srl_model.model.eval()\n", - " pbar = tqdm(total=len(data_loader))\n", - " for minibatch_num, (minibatch_idx, obs, _, _, _) in enumerate(data_loader):\n", - " obs = obs.to(DEVICE)\n", - " state = srl_model.model.getStates(obs).to('cpu').detach().numpy()\n", - " srl_data.append(state)\n", - " pbar.update(1)\n", - "\n", - " # concatenate into one numpy array\n", - " srl_data = np.concatenate(srl_data,axis=0)\n", - " # PCA for the v\n", - " if pca_mode:\n", - " pca_srl_data = PCA(srl_data, dim=ground_truth_states_dim)\n", - " else:\n", - " pca_srl_data = srl_data\n", - " if normalized: # Normilized into -0.5 to +0.5\n", - " for k in range(pca_srl_data.shape[1]):\n", - " pca_srl_data[:, k] = (pca_srl_data[:, k] - np.min(pca_srl_data[:, k])) / (\n", - " np.max(pca_srl_data[:, k]) - np.min(pca_srl_data[:, k])) - 0.5\n", - "\n", - " training_indices = np.concatenate(minibatchlist)\n", - "\n", - " return pca_srl_data, training_indices" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[32m\n", - "SRL: Using custom_cnn with inverse, autoencoder \n", - "\u001b[0m\n", - "\u001b[33mLoading trained model...srl_zoo/logs/Omnibot_random_circular/19-06-17_16h36_37_custom_cnn_ST_DIM200_inverse_autoencoder/srl_model.pth\u001b[0m\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " 0%| | 0/118 [00:00\n", - " for func, args, kwargs in self.items]\n", - " File \"/home/tete/Robotics-branches/escape-dev/robotics-rl-srl/srl_zoo/preprocessing/data_loader.py\", line 255, in _makeBatchElement\n", - " raise ValueError(\"tried to load {}.jpg, but it was not found\".format(image_path))\n", - "ValueError: tried to load srl_zoo/data/circular_on_policy_short_eps/record_148/frame000017.jpg, but it was not found\n" - ] - } - ], - "source": [ - "pca_srl_data, data_index = dataSrlLoad(data_folder, srl_model_path, pca_mode=True, normalized=True)" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "ename": "NameError", - "evalue": "name 'pca_srl_data' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mnum_sample\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpca_srl_data\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0mnum_val\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnum_sample\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0mVALIDATION_SIZE\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mNameError\u001b[0m: name 'pca_srl_data' is not defined" - ] - } - ], - "source": [ - "num_sample = len(pca_srl_data)\n", - "num_val = int(num_sample * VALIDATION_SIZE)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def plotDistribution(pca_srl_data, val_num):\n", - " fig, ax = plt.subplots(nrows=1, ncols=3, figsize=[24, 8])\n", - " x_min, x_max = pca_srl_data[:, 0].min(), pca_srl_data[:, 0].max()\n", - " y_min, y_max = pca_srl_data[:, 1].min(), pca_srl_data[:, 1].max()\n", - " ax[0].scatter(pca_srl_data[val_num:, 0], pca_srl_data[val_num:, 1], s=5, c='b', label='Training')\n", - " ax[0].scatter(pca_srl_data[:val_num, 0], pca_srl_data[:val_num, 1], s=5, c='r', label='Validation')\n", - " ax[0].legend()\n", - " ax[0].title.set_text('Sample')\n", - " # plt.show()\n", - " ax[1].hist2d(pca_srl_data[:val_num, 0], pca_srl_data[:val_num, 1],\n", - " bins=100, range=[[x_min, x_max], [y_min, y_max]])\n", - " ax[1].title.set_text('Validation distribution')\n", - " ax[2].hist2d(pca_srl_data[val_num:, 0], pca_srl_data[val_num:, 1],\n", - " bins=100, range=[[x_min, x_max], [y_min, y_max]])\n", - " ax[2].title.set_text('Training distribution')\n", - "\n", - " plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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idLcstFNdbkbml3c85sprzWZ/PNtH+nIGV+QN79/qfmjnPG7e3I3RLPzrpe/QVr+hm2zoQ3PZLkyl3oCIpI23nlrmsaUnbfjhdr5ijnIP4tpmhRVVU04/0zmJiIiIiIiIiIiC0uduSLLxEw7b+dTVXkJ52ysItQRIdjon7LbdinmJiIiIiIiIiIiuVTMFVlGZhORMB/SRdotkxZpxzdGG398secmIiIiIiIiIiK5VMwVWeUmK9I6rsut9z+R2WxNG56JiMhi8zW8Omecnxt74vLzcsbr7ntuztcqlEmbf61P3Jf7+oXOwFVGroiInIrs7Nd3k5sDm59xu3+oNWd82yxzYwvmzNY25gwtX24G7/cYyBm/LVWdM86fb34GcH6mbrb8PN18dqwnZ6zMXFmulJkrIhNEh0cJdYZzNjwTEREREREREZGlpWKuiEygDc9ERERERERERJYfxSyIyATa8ExEREREREREZPlRMVdEJqUNz0REZDnJz43Nz609lXMVUiiPVxm4IiKyUuXnwl7XcGnOOD8zNz939sc9T+SM8zNt8323yJcz/tpZuec/FsrNyL3Jk5uhm+8zid9N+3z2fPLnKrJSKWZBREREREREREREZAVQMVdERERERERERERkBVAxV0RERERERERERGQFUDFXREREREREREREZAXQBmgiIiIiIgtIG56JiMhKcVvXwznjQhua5cvfUG3C+fOev60r9/n861m+umnPn3/8bOc73WsLvReRpaLOXBEREREREREREZEVQMVcERERERERERERkRVAxVwRERERERERERGRFUCZuSIiIiIip6BQJu5N9X84q+NFRESWSqHc2PwM21M9X6HnZ5tbW+j8s3mtyHKlzlwRERERERERERGRFUDFXBEREREREREREZEVQMVcERERERERERERkRVAmbkiIiIiIgtIGbkiIrJSFMqN/XHPE/N6vtnm1J5qBq/I6UCduSIiIiIiIiIiIiIrgIq5IiIiIiIiIiIiIivASopZ8ACYprHU81gwp/N7O1W6N1PTvZma7s30Trf7k/V+PEs5jxXKAxAI1Bc6TkREVqGs9UFr7OxpjRWZR4HK2pxxqtozq+dFlpO5rq+G67rzP5uF8Srg50s9CRERWfZeDfzvUk9ihdEaKyIiM6E1dva0xoqISCGzWl9XUjG3FHg50A2klnguIiKy/HiAeuA3wMgSz2Wl0RorIiLT0Ro7d1pjRURkKnNaX1dSMVdERERERERERERk1dIGaCIiIiIiIiIiIiIrgIq5IiIiIiIiIiIiIiuAirkiIiIiIiIiIiIiK4CKuSIiIiIiIiIiIiIrgIq5IiIiIiIiIiIiIiuAirkiIiIiIiIiIiIiK4CKuSIiIiIiIiIiIiIrgIq5IiIiIiIiIiIiIitA0VJPYLWyLKsMuAe4EEgCO2zb/uE0x3uBx4GYbdsXLc4sl8ZM741lWW8FPg6UAgbwL7Ztf34x57oYLMs6B/gGsA44Afy1bdutecd4gC8DbwBc4Gbbtr+22HNdbDO8Nx8D3gGkgFHgH2zb/sliz3UpzOT+ZB1rAU8Ad9i2vWPxZikykdbIudMaOjtaY+dOa/DcaG2WpaY1du60xs6O1ti50fo6d6tpjVVn7tLZAURs2w4Cbwa+ZllWxTTH/xPwy0WZ2dKb6b3pAd5s2/YFwCXANZZlvXoR57lY7gL22rZ9DrAXuHuSYy4HgkAL8Argk5ZlnbVoM1w6M7k3vwZebtv2S4F3A9+xLMu3iHNcSjO5P+P/J+puYP8izk1kOloj505r6OxojZ07rcFzo7VZlprW2LnTGjs7WmPnRuvr3K2aNVbF3KXzdsa+WGN/UvAY8MbJDhz7F38L8K1Fm93SmtG9sW37V7Ztd439fRh4DjhzEee54CzLqgW2AA+MPfQAsMWyrJq8Q98OfNW2bce27X7S/1J62+LNdPHN9N7Ytv0T27aHx4ZPkf7T8XWLNtElMovvDsANwA+B5xdpeiKFaI2cO62hM6Q1du60Bs+N1mZZJrTGzp3W2BnSGjs3Wl/nbrWtsSrmLp0zgCNZ46PAxvyDLMsqB74IXLNI81oOZnRvslmWdS5wMfDTBZzXUtgIdNq2nQIY+2sXE+/HrO/ZaWCm9ybbXwNttm13LML8ltqM7o9lWS8DXg98YdFnKDI1rZFzpzV05rTGzp3W4LnR2izLgdbYudMaO3NaY+dG6+vcrao1Vpm5C8SyrAOk/8U0mQ2zONVu0m3inZZltZz6zJbePN6b8fPVAw8C7xv/E1CRfJZlvQb4NPDHSz2X5cKyrGLgn4F32badSscGiSw8rZFzpzVUViKtwTOntVlOldbYudMaKyuN1tfZOZ3WWBVzF4ht21ume96yrKOkf2rRP/bQGcDPJjn0VcCbLMv6OOAF1liW9dRYNsqKNI/3ZryV/v8Ct9q2/b35nOcycQwIWJblGfuXjQdoGHs82/g9+83YOP9POE9HM703WJb1CmAf8Fbbtu1FnudSmcn9qQeagR+NLWTVgGFZlt+27asWfcayamiNnDutofNKa+zcaQ2eG63NsuC0xs6d1th5pTV2brS+zt2qWmMVs7B0vgdcDTD2J50vB/4z/yDbtl9q2/ZZtm2fRXq3wqdP5wV0zIzujWVZ64D/Am63bfvrizrDRWLbdh/wJLBt7KFtwBNjeULZvgf8nWVZ5lgmzFbgXxdvpotvpvfGsqyXA98B/tK27QOLO8ulM5P7Y9v2Udu212f9O+aLpDOrVtRCJqclrZFzpzV0hrTGzp3W4LnR2izLhNbYudMaO0NaY+dG6+vcrbY1VsXcpbMbqLYsK0Q6ePkq27ajAJZlfcqyrPcu6eyW1kzvzQ3AOcDVlmU9Ofa/dy3NlBfUe4EPWJb1PPCBsTGWZf3IsqyLxo75FnAIaCW92+ynbNtuX4rJLrKZ3Js7AB9wd9b35CVLM91FN5P7I7IcaY2cO62hs6M1du60Bs+N1mZZalpj505r7OxojZ0bra9zt2rWWMN13aWeg4iIiIiIiIiIiIgUoM5cERERERERERERkRVAxVwRERERERERERGRFUDFXBEREREREREREZEVQMVcERERERERERERkRVAxVwRERERERERERGRFUDFXBEREREREREREZEVQMVcERERERERERERkRXg/wEzwqNjihvaEAAAAABJRU5ErkJggg==\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "plotDistribution(pca_srl_data, num_val)" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(2816, 2)" - ] - }, - "execution_count": 22, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "pca_srl_data.shape" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": 56, - "metadata": {}, - "outputs": [], - "source": [ - "def deleteData(data_folder, del_index=[], srl_model_path=None):\n", - " state_dim = getSRLDim(srl_model_path)\n", - " srl_model = loadSRLModel(srl_model_path, th.cuda.is_available(), state_dim, env_object=None)\n", - "\n", - " # load images and other data\n", - " print('Loading data for separation ')\n", - " training_data, ground_truth, true_states, _ = loadData(data_folder, absolute_path=True)\n", - " images_path = ground_truth['images_path']\n", - " ground_truth_states_dim = true_states.shape[1]\n", - " # we change the path to the local path at the toolbox level\n", - " images_path_copy = [\"srl_zoo/data/\" + images_path[k] for k in range(images_path.shape[0])]\n", - " images_path = np.array(images_path_copy)\n", - " \n", - " ground_truth_load = np.load(os.path.join(data_folder, \"/ground_truth.npz\"))\n", - " preprocessed_load = np.load(os.path.join(data_folder, \"/preprocessed_data.npz\"))\n", - " \n", - " " - ] - }, - { - "cell_type": "code", - "execution_count": 36, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "((19456,), (19456, 2))" - ] - }, - "execution_count": 36, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "data_index.shape, pca_srl_data.shape" - ] - }, - { - "cell_type": "code", - "execution_count": 43, - "metadata": {}, - "outputs": [], - "source": [ - "from functools import partial\n", - "def _del_val(p_val,train_set, threshold):\n", - " for p_train in train_set:\n", - " if(1.e-10" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "plotDistribution(test_set[index_save], 10000000)" - ] - }, - { - "cell_type": "code", - "execution_count": 73, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAABXMAAAHkCAYAAAB8ALzrAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4zLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvnQurowAAIABJREFUeJzs3Xl8XHd9//vXOVpmZGtzHCe2JdmSNfJhLZCyL6W0UAoBShfgEiCEH9kMARLbsk1CEsdksZ2YEEIcJ4GSQAjL7cKPJZS2dIMulCW09JZ8rX21YyfY2qIZaeac+8eZGc05mtFItmRZ8vv5ePCIz8yZc75zFHI8H33m/bE8z0NEREREREREREREzm72Yi9ARERERERERERERIpTMVdERERERERERERkCVAxV0RERERERERERGQJUDFXREREREREREREZAlQMVdERERERERERERkCVAxV0RERERERERERGQJUDFX5BziOM5ux3EeXex1iIjI8uQ4TqPjOJ7jOKXp7e87jvPB2ex7Cue63nGcL5zOemd5nlm/p1M49uscxzE5292O47xxPo6dPt7/5zjO787X8URE5OzmOE6J4zijjuNsmM9952Fdb3Qcpztn2ziO87p5OvYHHcf5fvrPpel7duM8HfuMXSORuTilvzyLyNw5jvNaYD/wfCAF/Bq41hjz00VdmIiISJrjOH8D/Kcx5qbQ438EPADUG2OSsz2eMeYt87Su3wUeNcbU5xz79vk49lzN9j05juMBLcaY9hmO9SPAmY91OY7zMNBvjPlUzvGfPx/HFhGRheE4zmjO5goggf9ZEeAqY8xX53I8Y0wKqJzvfeebMabovc9xnBjQZoyxihzrEeCR+ViX4zg/Br5gjHk4fexFu0YiM1FnrsgZ4DhONfBd4F7gPKAOuAX/Zi0iInK2eAR4v+M44Q9OHwC+OpdCrszsVDuSRURk+TDGVGb+B/QCb895bFohV/eOIF0POVfpX3yRM2MzgDHma+ntceBvARzHaQYeAl4EeMAPgI8aY06mn+8G7sP/IN0MfB24HngYeC3wE+BdxpgT6a+TdAFXAbsBCzhgjLkr36Icx3kl8BngeUAP8AljzD/N03sWEZGl51vAIeB1wL8AOI6zCngb8Ir09sXArfj3pCHgi8aY3fkO5jjOP+F31H7BcZwS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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "plotDistribution(test_set, 10000000)" - ] - }, - { - "cell_type": "code", - "execution_count": 78, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(19456, 2)" - ] - }, - "execution_count": 78, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "pca_srl_data.shape" - ] - }, - { - "cell_type": "code", - "execution_count": 87, - "metadata": {}, - "outputs": [], - "source": [ - "k = np.zeros(12).astype(bool)" - ] - }, - { - "cell_type": "code", - "execution_count": 88, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([False, False, False, False, False, False, False, False, False,\n", - " False, False, False])" - ] - }, - "execution_count": 88, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "k" - ] - }, - { - "cell_type": "code", - "execution_count": 82, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "False\n" - ] - } - ], - "source": [ - "a =0.0\n", - "print(bool(a))\n", - "if a:\n", - " print(1)" - ] - }, - { - "cell_type": "code", - "execution_count": 147, - "metadata": {}, - "outputs": [], - "source": [ - "def index_save(data_set, threshold):\n", - " pbar = tqdm(total = len(data_set))\n", - " deleted = np.zeros(len(data_set)).astype(bool)\n", - " for t, test_point in enumerate(data_set):\n", - " pbar.update(1)\n", - " for k, data_point in enumerate(data_set):\n", - " if(not deleted[k] and 1.e-5" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "plotDistribution(data_set[left_index], 10000000)" - ] - }, - { - "cell_type": "code", - "execution_count": 141, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([False, False, False, ..., False, False, False])" - ] - }, - "execution_count": 141, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "delete\n" - ] - }, - { - "cell_type": "code", - "execution_count": 142, - "metadata": {}, - "outputs": [], - "source": [ - "data_set = data_set.copy()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for i, data in enumerate(data_set):\n", - " np.delete" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} From e2f4c769e1dae591ca392c4049eb42883b63d7c4 Mon Sep 17 00:00:00 2001 From: TeTe <32313299+sun-te@users.noreply.github.com> Date: Thu, 18 Jul 2019 15:37:53 +0200 Subject: [PATCH 141/141] Update environment.yml --- environment.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/environment.yml b/environment.yml index 995bba580..2904538ff 100644 --- a/environment.yml +++ b/environment.yml @@ -9,6 +9,7 @@ dependencies: - html5lib=0.9999999=py35_0 - markdown=2.6.9=py35_0 - protobuf=3.4.1=py35he6b9134_0 + - tensorflow-gpu=1.8.0 - werkzeug=0.14.1=py35_0 - bzip2=1.0.6=h6d464ef_2 - ca-certificates=2017.08.26=h1d4fec5_0